1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26#include <linux/delay.h>
27#include "dm_services.h"
28#include "basics/dc_common.h"
29#include "core_types.h"
30#include "resource.h"
31#include "custom_float.h"
32#include "dcn10_hw_sequencer.h"
33#include "dcn10_hw_sequencer_debug.h"
34#include "dce/dce_hwseq.h"
35#include "abm.h"
36#include "dmcu.h"
37#include "dcn10_optc.h"
38#include "dcn10_dpp.h"
39#include "dcn10_mpc.h"
40#include "timing_generator.h"
41#include "opp.h"
42#include "ipp.h"
43#include "mpc.h"
44#include "reg_helper.h"
45#include "dcn10_hubp.h"
46#include "dcn10_hubbub.h"
47#include "dcn10_cm_common.h"
48#include "dc_link_dp.h"
49#include "dccg.h"
50#include "clk_mgr.h"
51#include "link_hwss.h"
52#include "dpcd_defs.h"
53#include "dsc.h"
54#include "dce/dmub_hw_lock_mgr.h"
55#include "dc_trace.h"
56#include "dce/dmub_outbox.h"
57#include "inc/dc_link_dp.h"
58#include "inc/link_dpcd.h"
59
60#define DC_LOGGER_INIT(logger)
61
62#define CTX \
63 hws->ctx
64#define REG(reg)\
65 hws->regs->reg
66
67#undef FN
68#define FN(reg_name, field_name) \
69 hws->shifts->field_name, hws->masks->field_name
70
71
72#define DTN_INFO_MICRO_SEC(ref_cycle) \
73 print_microsec(dc_ctx, log_ctx, ref_cycle)
74
75#define GAMMA_HW_POINTS_NUM 256
76
77#define PGFSM_POWER_ON 0
78#define PGFSM_POWER_OFF 2
79
80void print_microsec(struct dc_context *dc_ctx,
81 struct dc_log_buffer_ctx *log_ctx,
82 uint32_t ref_cycle)
83{
84 const uint32_t ref_clk_mhz = dc_ctx->dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000;
85 static const unsigned int frac = 1000;
86 uint32_t us_x10 = (ref_cycle * frac) / ref_clk_mhz;
87
88 DTN_INFO(" %11d.%03d",
89 us_x10 / frac,
90 us_x10 % frac);
91}
92
93void dcn10_lock_all_pipes(struct dc *dc,
94 struct dc_state *context,
95 bool lock)
96{
97 struct pipe_ctx *pipe_ctx;
98 struct timing_generator *tg;
99 int i;
100
101 for (i = 0; i < dc->res_pool->pipe_count; i++) {
102 pipe_ctx = &context->res_ctx.pipe_ctx[i];
103 tg = pipe_ctx->stream_res.tg;
104
105
106
107
108
109 if (pipe_ctx->top_pipe ||
110 !pipe_ctx->stream || !pipe_ctx->plane_state ||
111 !tg->funcs->is_tg_enabled(tg))
112 continue;
113
114 if (lock)
115 dc->hwss.pipe_control_lock(dc, pipe_ctx, true);
116 else
117 dc->hwss.pipe_control_lock(dc, pipe_ctx, false);
118 }
119}
120
121static void log_mpc_crc(struct dc *dc,
122 struct dc_log_buffer_ctx *log_ctx)
123{
124 struct dc_context *dc_ctx = dc->ctx;
125 struct dce_hwseq *hws = dc->hwseq;
126
127 if (REG(MPC_CRC_RESULT_GB))
128 DTN_INFO("MPC_CRC_RESULT_GB:%d MPC_CRC_RESULT_C:%d MPC_CRC_RESULT_AR:%d\n",
129 REG_READ(MPC_CRC_RESULT_GB), REG_READ(MPC_CRC_RESULT_C), REG_READ(MPC_CRC_RESULT_AR));
130 if (REG(DPP_TOP0_DPP_CRC_VAL_B_A))
131 DTN_INFO("DPP_TOP0_DPP_CRC_VAL_B_A:%d DPP_TOP0_DPP_CRC_VAL_R_G:%d\n",
132 REG_READ(DPP_TOP0_DPP_CRC_VAL_B_A), REG_READ(DPP_TOP0_DPP_CRC_VAL_R_G));
133}
134
135void dcn10_log_hubbub_state(struct dc *dc, struct dc_log_buffer_ctx *log_ctx)
136{
137 struct dc_context *dc_ctx = dc->ctx;
138 struct dcn_hubbub_wm wm;
139 int i;
140
141 memset(&wm, 0, sizeof(struct dcn_hubbub_wm));
142 dc->res_pool->hubbub->funcs->wm_read_state(dc->res_pool->hubbub, &wm);
143
144 DTN_INFO("HUBBUB WM: data_urgent pte_meta_urgent"
145 " sr_enter sr_exit dram_clk_change\n");
146
147 for (i = 0; i < 4; i++) {
148 struct dcn_hubbub_wm_set *s;
149
150 s = &wm.sets[i];
151 DTN_INFO("WM_Set[%d]:", s->wm_set);
152 DTN_INFO_MICRO_SEC(s->data_urgent);
153 DTN_INFO_MICRO_SEC(s->pte_meta_urgent);
154 DTN_INFO_MICRO_SEC(s->sr_enter);
155 DTN_INFO_MICRO_SEC(s->sr_exit);
156 DTN_INFO_MICRO_SEC(s->dram_clk_chanage);
157 DTN_INFO("\n");
158 }
159
160 DTN_INFO("\n");
161}
162
163static void dcn10_log_hubp_states(struct dc *dc, void *log_ctx)
164{
165 struct dc_context *dc_ctx = dc->ctx;
166 struct resource_pool *pool = dc->res_pool;
167 int i;
168
169 DTN_INFO(
170 "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");
171 for (i = 0; i < pool->pipe_count; i++) {
172 struct hubp *hubp = pool->hubps[i];
173 struct dcn_hubp_state *s = &(TO_DCN10_HUBP(hubp)->state);
174
175 hubp->funcs->hubp_read_state(hubp);
176
177 if (!s->blank_en) {
178 DTN_INFO("[%2d]: %5xh %6xh %5d %6d %2xh %2xh %6xh %6d %8d %8d %7d %8xh",
179 hubp->inst,
180 s->pixel_format,
181 s->inuse_addr_hi,
182 s->viewport_width,
183 s->viewport_height,
184 s->rotation_angle,
185 s->h_mirror_en,
186 s->sw_mode,
187 s->dcc_en,
188 s->blank_en,
189 s->clock_en,
190 s->ttu_disable,
191 s->underflow_status);
192 DTN_INFO_MICRO_SEC(s->min_ttu_vblank);
193 DTN_INFO_MICRO_SEC(s->qos_level_low_wm);
194 DTN_INFO_MICRO_SEC(s->qos_level_high_wm);
195 DTN_INFO("\n");
196 }
197 }
198
199 DTN_INFO("\n=========RQ========\n");
200 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"
201 " min_m_c_s dpte_gr_s mpte_gr_s swath_hei pte_row_h C:chunk_s min_chu_s meta_ch_s"
202 " min_m_c_s dpte_gr_s mpte_gr_s swath_hei pte_row_h\n");
203 for (i = 0; i < pool->pipe_count; i++) {
204 struct dcn_hubp_state *s = &(TO_DCN10_HUBP(pool->hubps[i])->state);
205 struct _vcs_dpi_display_rq_regs_st *rq_regs = &s->rq_regs;
206
207 if (!s->blank_en)
208 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",
209 pool->hubps[i]->inst, rq_regs->drq_expansion_mode, rq_regs->prq_expansion_mode, rq_regs->mrq_expansion_mode,
210 rq_regs->crq_expansion_mode, rq_regs->plane1_base_address, rq_regs->rq_regs_l.chunk_size,
211 rq_regs->rq_regs_l.min_chunk_size, rq_regs->rq_regs_l.meta_chunk_size,
212 rq_regs->rq_regs_l.min_meta_chunk_size, rq_regs->rq_regs_l.dpte_group_size,
213 rq_regs->rq_regs_l.mpte_group_size, rq_regs->rq_regs_l.swath_height,
214 rq_regs->rq_regs_l.pte_row_height_linear, rq_regs->rq_regs_c.chunk_size, rq_regs->rq_regs_c.min_chunk_size,
215 rq_regs->rq_regs_c.meta_chunk_size, rq_regs->rq_regs_c.min_meta_chunk_size,
216 rq_regs->rq_regs_c.dpte_group_size, rq_regs->rq_regs_c.mpte_group_size,
217 rq_regs->rq_regs_c.swath_height, rq_regs->rq_regs_c.pte_row_height_linear);
218 }
219
220 DTN_INFO("========DLG========\n");
221 DTN_INFO("HUBP: rc_hbe dlg_vbe min_d_y_n rc_per_ht rc_x_a_s "
222 " dst_y_a_s dst_y_pf dst_y_vvb dst_y_rvb dst_y_vfl dst_y_rfl rf_pix_fq"
223 " vratio_pf vrat_pf_c rc_pg_vbl rc_pg_vbc rc_mc_vbl rc_mc_vbc rc_pg_fll"
224 " rc_pg_flc rc_mc_fll rc_mc_flc pr_nom_l pr_nom_c rc_pg_nl rc_pg_nc "
225 " mr_nom_l mr_nom_c rc_mc_nl rc_mc_nc rc_ld_pl rc_ld_pc rc_ld_l "
226 " rc_ld_c cha_cur0 ofst_cur1 cha_cur1 vr_af_vc0 ddrq_limt x_rt_dlay"
227 " x_rp_dlay x_rr_sfl\n");
228 for (i = 0; i < pool->pipe_count; i++) {
229 struct dcn_hubp_state *s = &(TO_DCN10_HUBP(pool->hubps[i])->state);
230 struct _vcs_dpi_display_dlg_regs_st *dlg_regs = &s->dlg_attr;
231
232 if (!s->blank_en)
233 DTN_INFO("[%2d]: %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh"
234 "% 8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh"
235 " %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh\n",
236 pool->hubps[i]->inst, dlg_regs->refcyc_h_blank_end, dlg_regs->dlg_vblank_end, dlg_regs->min_dst_y_next_start,
237 dlg_regs->refcyc_per_htotal, dlg_regs->refcyc_x_after_scaler, dlg_regs->dst_y_after_scaler,
238 dlg_regs->dst_y_prefetch, dlg_regs->dst_y_per_vm_vblank, dlg_regs->dst_y_per_row_vblank,
239 dlg_regs->dst_y_per_vm_flip, dlg_regs->dst_y_per_row_flip, dlg_regs->ref_freq_to_pix_freq,
240 dlg_regs->vratio_prefetch, dlg_regs->vratio_prefetch_c, dlg_regs->refcyc_per_pte_group_vblank_l,
241 dlg_regs->refcyc_per_pte_group_vblank_c, dlg_regs->refcyc_per_meta_chunk_vblank_l,
242 dlg_regs->refcyc_per_meta_chunk_vblank_c, dlg_regs->refcyc_per_pte_group_flip_l,
243 dlg_regs->refcyc_per_pte_group_flip_c, dlg_regs->refcyc_per_meta_chunk_flip_l,
244 dlg_regs->refcyc_per_meta_chunk_flip_c, dlg_regs->dst_y_per_pte_row_nom_l,
245 dlg_regs->dst_y_per_pte_row_nom_c, dlg_regs->refcyc_per_pte_group_nom_l,
246 dlg_regs->refcyc_per_pte_group_nom_c, dlg_regs->dst_y_per_meta_row_nom_l,
247 dlg_regs->dst_y_per_meta_row_nom_c, dlg_regs->refcyc_per_meta_chunk_nom_l,
248 dlg_regs->refcyc_per_meta_chunk_nom_c, dlg_regs->refcyc_per_line_delivery_pre_l,
249 dlg_regs->refcyc_per_line_delivery_pre_c, dlg_regs->refcyc_per_line_delivery_l,
250 dlg_regs->refcyc_per_line_delivery_c, dlg_regs->chunk_hdl_adjust_cur0, dlg_regs->dst_y_offset_cur1,
251 dlg_regs->chunk_hdl_adjust_cur1, dlg_regs->vready_after_vcount0, dlg_regs->dst_y_delta_drq_limit,
252 dlg_regs->xfc_reg_transfer_delay, dlg_regs->xfc_reg_precharge_delay,
253 dlg_regs->xfc_reg_remote_surface_flip_latency);
254 }
255
256 DTN_INFO("========TTU========\n");
257 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"
258 " rc_rd_c rc_rd_c0 rc_rd_pc0 rc_rd_c1 rc_rd_pc1 qos_lf_l qos_rds_l"
259 " qos_lf_c qos_rds_c qos_lf_c0 qos_rds_c0 qos_lf_c1 qos_rds_c1\n");
260 for (i = 0; i < pool->pipe_count; i++) {
261 struct dcn_hubp_state *s = &(TO_DCN10_HUBP(pool->hubps[i])->state);
262 struct _vcs_dpi_display_ttu_regs_st *ttu_regs = &s->ttu_attr;
263
264 if (!s->blank_en)
265 DTN_INFO("[%2d]: %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh\n",
266 pool->hubps[i]->inst, ttu_regs->qos_level_low_wm, ttu_regs->qos_level_high_wm, ttu_regs->min_ttu_vblank,
267 ttu_regs->qos_level_flip, ttu_regs->refcyc_per_req_delivery_pre_l, ttu_regs->refcyc_per_req_delivery_l,
268 ttu_regs->refcyc_per_req_delivery_pre_c, ttu_regs->refcyc_per_req_delivery_c, ttu_regs->refcyc_per_req_delivery_cur0,
269 ttu_regs->refcyc_per_req_delivery_pre_cur0, ttu_regs->refcyc_per_req_delivery_cur1,
270 ttu_regs->refcyc_per_req_delivery_pre_cur1, ttu_regs->qos_level_fixed_l, ttu_regs->qos_ramp_disable_l,
271 ttu_regs->qos_level_fixed_c, ttu_regs->qos_ramp_disable_c, ttu_regs->qos_level_fixed_cur0,
272 ttu_regs->qos_ramp_disable_cur0, ttu_regs->qos_level_fixed_cur1, ttu_regs->qos_ramp_disable_cur1);
273 }
274 DTN_INFO("\n");
275}
276
277void dcn10_log_hw_state(struct dc *dc,
278 struct dc_log_buffer_ctx *log_ctx)
279{
280 struct dc_context *dc_ctx = dc->ctx;
281 struct resource_pool *pool = dc->res_pool;
282 int i;
283
284 DTN_INFO_BEGIN();
285
286 dcn10_log_hubbub_state(dc, log_ctx);
287
288 dcn10_log_hubp_states(dc, log_ctx);
289
290 DTN_INFO("DPP: IGAM format IGAM mode DGAM mode RGAM mode"
291 " GAMUT mode C11 C12 C13 C14 C21 C22 C23 C24 "
292 "C31 C32 C33 C34\n");
293 for (i = 0; i < pool->pipe_count; i++) {
294 struct dpp *dpp = pool->dpps[i];
295 struct dcn_dpp_state s = {0};
296
297 dpp->funcs->dpp_read_state(dpp, &s);
298
299 if (!s.is_enabled)
300 continue;
301
302 DTN_INFO("[%2d]: %11xh %-11s %-11s %-11s"
303 "%8x %08xh %08xh %08xh %08xh %08xh %08xh",
304 dpp->inst,
305 s.igam_input_format,
306 (s.igam_lut_mode == 0) ? "BypassFixed" :
307 ((s.igam_lut_mode == 1) ? "BypassFloat" :
308 ((s.igam_lut_mode == 2) ? "RAM" :
309 ((s.igam_lut_mode == 3) ? "RAM" :
310 "Unknown"))),
311 (s.dgam_lut_mode == 0) ? "Bypass" :
312 ((s.dgam_lut_mode == 1) ? "sRGB" :
313 ((s.dgam_lut_mode == 2) ? "Ycc" :
314 ((s.dgam_lut_mode == 3) ? "RAM" :
315 ((s.dgam_lut_mode == 4) ? "RAM" :
316 "Unknown")))),
317 (s.rgam_lut_mode == 0) ? "Bypass" :
318 ((s.rgam_lut_mode == 1) ? "sRGB" :
319 ((s.rgam_lut_mode == 2) ? "Ycc" :
320 ((s.rgam_lut_mode == 3) ? "RAM" :
321 ((s.rgam_lut_mode == 4) ? "RAM" :
322 "Unknown")))),
323 s.gamut_remap_mode,
324 s.gamut_remap_c11_c12,
325 s.gamut_remap_c13_c14,
326 s.gamut_remap_c21_c22,
327 s.gamut_remap_c23_c24,
328 s.gamut_remap_c31_c32,
329 s.gamut_remap_c33_c34);
330 DTN_INFO("\n");
331 }
332 DTN_INFO("\n");
333
334 DTN_INFO("MPCC: OPP DPP MPCCBOT MODE ALPHA_MODE PREMULT OVERLAP_ONLY IDLE\n");
335 for (i = 0; i < pool->pipe_count; i++) {
336 struct mpcc_state s = {0};
337
338 pool->mpc->funcs->read_mpcc_state(pool->mpc, i, &s);
339 if (s.opp_id != 0xf)
340 DTN_INFO("[%2d]: %2xh %2xh %6xh %4d %10d %7d %12d %4d\n",
341 i, s.opp_id, s.dpp_id, s.bot_mpcc_id,
342 s.mode, s.alpha_mode, s.pre_multiplied_alpha, s.overlap_only,
343 s.idle);
344 }
345 DTN_INFO("\n");
346
347 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");
348
349 for (i = 0; i < pool->timing_generator_count; i++) {
350 struct timing_generator *tg = pool->timing_generators[i];
351 struct dcn_otg_state s = {0};
352
353 optc1_read_otg_state(DCN10TG_FROM_TG(tg), &s);
354
355
356
357
358
359
360
361
362 if (pool->opps[i]->funcs->dpg_is_blanked)
363 s.blank_enabled = pool->opps[i]->funcs->dpg_is_blanked(pool->opps[i]);
364 else
365 s.blank_enabled = tg->funcs->is_blanked(tg);
366
367
368 if ((s.otg_enabled & 1) == 0)
369 continue;
370
371 DTN_INFO("[%d]: %5d %5d %5d %5d %5d %5d %5d %9d %9d %5d %5d %5d %5d %5d %5d %5d %9d %8d\n",
372 tg->inst,
373 s.v_blank_start,
374 s.v_blank_end,
375 s.v_sync_a_start,
376 s.v_sync_a_end,
377 s.v_sync_a_pol,
378 s.v_total_max,
379 s.v_total_min,
380 s.v_total_max_sel,
381 s.v_total_min_sel,
382 s.h_blank_start,
383 s.h_blank_end,
384 s.h_sync_a_start,
385 s.h_sync_a_end,
386 s.h_sync_a_pol,
387 s.h_total,
388 s.v_total,
389 s.underflow_occurred_status,
390 s.blank_enabled);
391
392
393
394
395
396 tg->funcs->clear_optc_underflow(tg);
397 }
398 DTN_INFO("\n");
399
400
401
402 DTN_INFO("DSC: CLOCK_EN SLICE_WIDTH Bytes_pp\n");
403 for (i = 0; i < pool->res_cap->num_dsc; i++) {
404 struct display_stream_compressor *dsc = pool->dscs[i];
405 struct dcn_dsc_state s = {0};
406
407 dsc->funcs->dsc_read_state(dsc, &s);
408 DTN_INFO("[%d]: %-9d %-12d %-10d\n",
409 dsc->inst,
410 s.dsc_clock_en,
411 s.dsc_slice_width,
412 s.dsc_bits_per_pixel);
413 DTN_INFO("\n");
414 }
415 DTN_INFO("\n");
416
417 DTN_INFO("S_ENC: DSC_MODE SEC_GSP7_LINE_NUM"
418 " VBID6_LINE_REFERENCE VBID6_LINE_NUM SEC_GSP7_ENABLE SEC_STREAM_ENABLE\n");
419 for (i = 0; i < pool->stream_enc_count; i++) {
420 struct stream_encoder *enc = pool->stream_enc[i];
421 struct enc_state s = {0};
422
423 if (enc->funcs->enc_read_state) {
424 enc->funcs->enc_read_state(enc, &s);
425 DTN_INFO("[%-3d]: %-9d %-18d %-21d %-15d %-16d %-17d\n",
426 enc->id,
427 s.dsc_mode,
428 s.sec_gsp_pps_line_num,
429 s.vbid6_line_reference,
430 s.vbid6_line_num,
431 s.sec_gsp_pps_enable,
432 s.sec_stream_enable);
433 DTN_INFO("\n");
434 }
435 }
436 DTN_INFO("\n");
437
438 DTN_INFO("L_ENC: DPHY_FEC_EN DPHY_FEC_READY_SHADOW DPHY_FEC_ACTIVE_STATUS DP_LINK_TRAINING_COMPLETE\n");
439 for (i = 0; i < dc->link_count; i++) {
440 struct link_encoder *lenc = dc->links[i]->link_enc;
441
442 struct link_enc_state s = {0};
443
444 if (lenc->funcs->read_state) {
445 lenc->funcs->read_state(lenc, &s);
446 DTN_INFO("[%-3d]: %-12d %-22d %-22d %-25d\n",
447 i,
448 s.dphy_fec_en,
449 s.dphy_fec_ready_shadow,
450 s.dphy_fec_active_status,
451 s.dp_link_training_complete);
452 DTN_INFO("\n");
453 }
454 }
455 DTN_INFO("\n");
456
457 DTN_INFO("\nCALCULATED Clocks: dcfclk_khz:%d dcfclk_deep_sleep_khz:%d dispclk_khz:%d\n"
458 "dppclk_khz:%d max_supported_dppclk_khz:%d fclk_khz:%d socclk_khz:%d\n\n",
459 dc->current_state->bw_ctx.bw.dcn.clk.dcfclk_khz,
460 dc->current_state->bw_ctx.bw.dcn.clk.dcfclk_deep_sleep_khz,
461 dc->current_state->bw_ctx.bw.dcn.clk.dispclk_khz,
462 dc->current_state->bw_ctx.bw.dcn.clk.dppclk_khz,
463 dc->current_state->bw_ctx.bw.dcn.clk.max_supported_dppclk_khz,
464 dc->current_state->bw_ctx.bw.dcn.clk.fclk_khz,
465 dc->current_state->bw_ctx.bw.dcn.clk.socclk_khz);
466
467 log_mpc_crc(dc, log_ctx);
468
469 DTN_INFO_END();
470}
471
472bool dcn10_did_underflow_occur(struct dc *dc, struct pipe_ctx *pipe_ctx)
473{
474 struct hubp *hubp = pipe_ctx->plane_res.hubp;
475 struct timing_generator *tg = pipe_ctx->stream_res.tg;
476
477 if (tg->funcs->is_optc_underflow_occurred(tg)) {
478 tg->funcs->clear_optc_underflow(tg);
479 return true;
480 }
481
482 if (hubp->funcs->hubp_get_underflow_status(hubp)) {
483 hubp->funcs->hubp_clear_underflow(hubp);
484 return true;
485 }
486 return false;
487}
488
489void dcn10_enable_power_gating_plane(
490 struct dce_hwseq *hws,
491 bool enable)
492{
493 bool force_on = true;
494
495 if (enable)
496 force_on = false;
497
498
499 REG_UPDATE(DOMAIN0_PG_CONFIG, DOMAIN0_POWER_FORCEON, force_on);
500 REG_UPDATE(DOMAIN2_PG_CONFIG, DOMAIN2_POWER_FORCEON, force_on);
501 REG_UPDATE(DOMAIN4_PG_CONFIG, DOMAIN4_POWER_FORCEON, force_on);
502 REG_UPDATE(DOMAIN6_PG_CONFIG, DOMAIN6_POWER_FORCEON, force_on);
503
504
505 REG_UPDATE(DOMAIN1_PG_CONFIG, DOMAIN1_POWER_FORCEON, force_on);
506 REG_UPDATE(DOMAIN3_PG_CONFIG, DOMAIN3_POWER_FORCEON, force_on);
507 REG_UPDATE(DOMAIN5_PG_CONFIG, DOMAIN5_POWER_FORCEON, force_on);
508 REG_UPDATE(DOMAIN7_PG_CONFIG, DOMAIN7_POWER_FORCEON, force_on);
509}
510
511void dcn10_disable_vga(
512 struct dce_hwseq *hws)
513{
514 unsigned int in_vga1_mode = 0;
515 unsigned int in_vga2_mode = 0;
516 unsigned int in_vga3_mode = 0;
517 unsigned int in_vga4_mode = 0;
518
519 REG_GET(D1VGA_CONTROL, D1VGA_MODE_ENABLE, &in_vga1_mode);
520 REG_GET(D2VGA_CONTROL, D2VGA_MODE_ENABLE, &in_vga2_mode);
521 REG_GET(D3VGA_CONTROL, D3VGA_MODE_ENABLE, &in_vga3_mode);
522 REG_GET(D4VGA_CONTROL, D4VGA_MODE_ENABLE, &in_vga4_mode);
523
524 if (in_vga1_mode == 0 && in_vga2_mode == 0 &&
525 in_vga3_mode == 0 && in_vga4_mode == 0)
526 return;
527
528 REG_WRITE(D1VGA_CONTROL, 0);
529 REG_WRITE(D2VGA_CONTROL, 0);
530 REG_WRITE(D3VGA_CONTROL, 0);
531 REG_WRITE(D4VGA_CONTROL, 0);
532
533
534
535
536
537
538
539
540 REG_UPDATE(VGA_TEST_CONTROL, VGA_TEST_ENABLE, 1);
541 REG_UPDATE(VGA_TEST_CONTROL, VGA_TEST_RENDER_START, 1);
542}
543
544
545
546
547
548
549
550
551
552
553void dcn10_dpp_pg_control(
554 struct dce_hwseq *hws,
555 unsigned int dpp_inst,
556 bool power_on)
557{
558 uint32_t power_gate = power_on ? 0 : 1;
559 uint32_t pwr_status = power_on ? PGFSM_POWER_ON : PGFSM_POWER_OFF;
560
561 if (hws->ctx->dc->debug.disable_dpp_power_gate)
562 return;
563 if (REG(DOMAIN1_PG_CONFIG) == 0)
564 return;
565
566 switch (dpp_inst) {
567 case 0:
568 REG_UPDATE(DOMAIN1_PG_CONFIG,
569 DOMAIN1_POWER_GATE, power_gate);
570
571 REG_WAIT(DOMAIN1_PG_STATUS,
572 DOMAIN1_PGFSM_PWR_STATUS, pwr_status,
573 1, 1000);
574 break;
575 case 1:
576 REG_UPDATE(DOMAIN3_PG_CONFIG,
577 DOMAIN3_POWER_GATE, power_gate);
578
579 REG_WAIT(DOMAIN3_PG_STATUS,
580 DOMAIN3_PGFSM_PWR_STATUS, pwr_status,
581 1, 1000);
582 break;
583 case 2:
584 REG_UPDATE(DOMAIN5_PG_CONFIG,
585 DOMAIN5_POWER_GATE, power_gate);
586
587 REG_WAIT(DOMAIN5_PG_STATUS,
588 DOMAIN5_PGFSM_PWR_STATUS, pwr_status,
589 1, 1000);
590 break;
591 case 3:
592 REG_UPDATE(DOMAIN7_PG_CONFIG,
593 DOMAIN7_POWER_GATE, power_gate);
594
595 REG_WAIT(DOMAIN7_PG_STATUS,
596 DOMAIN7_PGFSM_PWR_STATUS, pwr_status,
597 1, 1000);
598 break;
599 default:
600 BREAK_TO_DEBUGGER();
601 break;
602 }
603}
604
605
606
607
608
609
610
611
612
613
614void dcn10_hubp_pg_control(
615 struct dce_hwseq *hws,
616 unsigned int hubp_inst,
617 bool power_on)
618{
619 uint32_t power_gate = power_on ? 0 : 1;
620 uint32_t pwr_status = power_on ? PGFSM_POWER_ON : PGFSM_POWER_OFF;
621
622 if (hws->ctx->dc->debug.disable_hubp_power_gate)
623 return;
624 if (REG(DOMAIN0_PG_CONFIG) == 0)
625 return;
626
627 switch (hubp_inst) {
628 case 0:
629 REG_UPDATE(DOMAIN0_PG_CONFIG,
630 DOMAIN0_POWER_GATE, power_gate);
631
632 REG_WAIT(DOMAIN0_PG_STATUS,
633 DOMAIN0_PGFSM_PWR_STATUS, pwr_status,
634 1, 1000);
635 break;
636 case 1:
637 REG_UPDATE(DOMAIN2_PG_CONFIG,
638 DOMAIN2_POWER_GATE, power_gate);
639
640 REG_WAIT(DOMAIN2_PG_STATUS,
641 DOMAIN2_PGFSM_PWR_STATUS, pwr_status,
642 1, 1000);
643 break;
644 case 2:
645 REG_UPDATE(DOMAIN4_PG_CONFIG,
646 DOMAIN4_POWER_GATE, power_gate);
647
648 REG_WAIT(DOMAIN4_PG_STATUS,
649 DOMAIN4_PGFSM_PWR_STATUS, pwr_status,
650 1, 1000);
651 break;
652 case 3:
653 REG_UPDATE(DOMAIN6_PG_CONFIG,
654 DOMAIN6_POWER_GATE, power_gate);
655
656 REG_WAIT(DOMAIN6_PG_STATUS,
657 DOMAIN6_PGFSM_PWR_STATUS, pwr_status,
658 1, 1000);
659 break;
660 default:
661 BREAK_TO_DEBUGGER();
662 break;
663 }
664}
665
666static void power_on_plane(
667 struct dce_hwseq *hws,
668 int plane_id)
669{
670 DC_LOGGER_INIT(hws->ctx->logger);
671 if (REG(DC_IP_REQUEST_CNTL)) {
672 REG_SET(DC_IP_REQUEST_CNTL, 0,
673 IP_REQUEST_EN, 1);
674
675 if (hws->funcs.dpp_pg_control)
676 hws->funcs.dpp_pg_control(hws, plane_id, true);
677
678 if (hws->funcs.hubp_pg_control)
679 hws->funcs.hubp_pg_control(hws, plane_id, true);
680
681 REG_SET(DC_IP_REQUEST_CNTL, 0,
682 IP_REQUEST_EN, 0);
683 DC_LOG_DEBUG(
684 "Un-gated front end for pipe %d\n", plane_id);
685 }
686}
687
688static void undo_DEGVIDCN10_253_wa(struct dc *dc)
689{
690 struct dce_hwseq *hws = dc->hwseq;
691 struct hubp *hubp = dc->res_pool->hubps[0];
692
693 if (!hws->wa_state.DEGVIDCN10_253_applied)
694 return;
695
696 hubp->funcs->set_blank(hubp, true);
697
698 REG_SET(DC_IP_REQUEST_CNTL, 0,
699 IP_REQUEST_EN, 1);
700
701 hws->funcs.hubp_pg_control(hws, 0, false);
702 REG_SET(DC_IP_REQUEST_CNTL, 0,
703 IP_REQUEST_EN, 0);
704
705 hws->wa_state.DEGVIDCN10_253_applied = false;
706}
707
708static void apply_DEGVIDCN10_253_wa(struct dc *dc)
709{
710 struct dce_hwseq *hws = dc->hwseq;
711 struct hubp *hubp = dc->res_pool->hubps[0];
712 int i;
713
714 if (dc->debug.disable_stutter)
715 return;
716
717 if (!hws->wa.DEGVIDCN10_253)
718 return;
719
720 for (i = 0; i < dc->res_pool->pipe_count; i++) {
721 if (!dc->res_pool->hubps[i]->power_gated)
722 return;
723 }
724
725
726
727 REG_SET(DC_IP_REQUEST_CNTL, 0,
728 IP_REQUEST_EN, 1);
729
730 hws->funcs.hubp_pg_control(hws, 0, true);
731 REG_SET(DC_IP_REQUEST_CNTL, 0,
732 IP_REQUEST_EN, 0);
733
734 hubp->funcs->set_hubp_blank_en(hubp, false);
735 hws->wa_state.DEGVIDCN10_253_applied = true;
736}
737
738void dcn10_bios_golden_init(struct dc *dc)
739{
740 struct dce_hwseq *hws = dc->hwseq;
741 struct dc_bios *bp = dc->ctx->dc_bios;
742 int i;
743 bool allow_self_fresh_force_enable = true;
744
745 if (hws->funcs.s0i3_golden_init_wa && hws->funcs.s0i3_golden_init_wa(dc))
746 return;
747
748 if (dc->res_pool->hubbub->funcs->is_allow_self_refresh_enabled)
749 allow_self_fresh_force_enable =
750 dc->res_pool->hubbub->funcs->is_allow_self_refresh_enabled(dc->res_pool->hubbub);
751
752
753
754
755
756
757
758
759
760
761 bp->funcs->enable_disp_power_gating(bp,
762 CONTROLLER_ID_D0, ASIC_PIPE_INIT);
763
764 for (i = 0; i < dc->res_pool->pipe_count; i++) {
765
766 bp->funcs->enable_disp_power_gating(bp,
767 CONTROLLER_ID_D0 + i, ASIC_PIPE_DISABLE);
768 }
769
770 if (dc->res_pool->hubbub->funcs->allow_self_refresh_control)
771 if (allow_self_fresh_force_enable == false &&
772 dc->res_pool->hubbub->funcs->is_allow_self_refresh_enabled(dc->res_pool->hubbub))
773 dc->res_pool->hubbub->funcs->allow_self_refresh_control(dc->res_pool->hubbub,
774 !dc->res_pool->hubbub->ctx->dc->debug.disable_stutter);
775
776}
777
778static void false_optc_underflow_wa(
779 struct dc *dc,
780 const struct dc_stream_state *stream,
781 struct timing_generator *tg)
782{
783 int i;
784 bool underflow;
785
786 if (!dc->hwseq->wa.false_optc_underflow)
787 return;
788
789 underflow = tg->funcs->is_optc_underflow_occurred(tg);
790
791 for (i = 0; i < dc->res_pool->pipe_count; i++) {
792 struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
793
794 if (old_pipe_ctx->stream != stream)
795 continue;
796
797 dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, old_pipe_ctx);
798 }
799
800 if (tg->funcs->set_blank_data_double_buffer)
801 tg->funcs->set_blank_data_double_buffer(tg, true);
802
803 if (tg->funcs->is_optc_underflow_occurred(tg) && !underflow)
804 tg->funcs->clear_optc_underflow(tg);
805}
806
807enum dc_status dcn10_enable_stream_timing(
808 struct pipe_ctx *pipe_ctx,
809 struct dc_state *context,
810 struct dc *dc)
811{
812 struct dc_stream_state *stream = pipe_ctx->stream;
813 enum dc_color_space color_space;
814 struct tg_color black_color = {0};
815
816
817
818
819
820 if (pipe_ctx->top_pipe != NULL)
821 return DC_OK;
822
823
824
825
826
827
828 pipe_ctx->stream_res.tg->funcs->enable_optc_clock(pipe_ctx->stream_res.tg, true);
829
830 if (false == pipe_ctx->clock_source->funcs->program_pix_clk(
831 pipe_ctx->clock_source,
832 &pipe_ctx->stream_res.pix_clk_params,
833 &pipe_ctx->pll_settings)) {
834 BREAK_TO_DEBUGGER();
835 return DC_ERROR_UNEXPECTED;
836 }
837
838 pipe_ctx->stream_res.tg->funcs->program_timing(
839 pipe_ctx->stream_res.tg,
840 &stream->timing,
841 pipe_ctx->pipe_dlg_param.vready_offset,
842 pipe_ctx->pipe_dlg_param.vstartup_start,
843 pipe_ctx->pipe_dlg_param.vupdate_offset,
844 pipe_ctx->pipe_dlg_param.vupdate_width,
845 pipe_ctx->stream->signal,
846 true);
847
848#if 0
849
850
851
852 inst_offset = reg_offsets[pipe_ctx->stream_res.tg->inst].fmt;
853
854 pipe_ctx->stream_res.opp->funcs->opp_program_fmt(
855 pipe_ctx->stream_res.opp,
856 &stream->bit_depth_params,
857 &stream->clamping);
858#endif
859
860 color_space = stream->output_color_space;
861 color_space_to_black_color(dc, color_space, &black_color);
862
863
864
865
866
867
868 if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420)
869 black_color.color_r_cr = black_color.color_g_y;
870
871 if (pipe_ctx->stream_res.tg->funcs->set_blank_color)
872 pipe_ctx->stream_res.tg->funcs->set_blank_color(
873 pipe_ctx->stream_res.tg,
874 &black_color);
875
876 if (pipe_ctx->stream_res.tg->funcs->is_blanked &&
877 !pipe_ctx->stream_res.tg->funcs->is_blanked(pipe_ctx->stream_res.tg)) {
878 pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, true);
879 hwss_wait_for_blank_complete(pipe_ctx->stream_res.tg);
880 false_optc_underflow_wa(dc, pipe_ctx->stream, pipe_ctx->stream_res.tg);
881 }
882
883
884 if (false == pipe_ctx->stream_res.tg->funcs->enable_crtc(pipe_ctx->stream_res.tg)) {
885 BREAK_TO_DEBUGGER();
886 return DC_ERROR_UNEXPECTED;
887 }
888
889
890
891
892
893
894
895
896
897 return DC_OK;
898}
899
900static void dcn10_reset_back_end_for_pipe(
901 struct dc *dc,
902 struct pipe_ctx *pipe_ctx,
903 struct dc_state *context)
904{
905 int i;
906 struct dc_link *link;
907 DC_LOGGER_INIT(dc->ctx->logger);
908 if (pipe_ctx->stream_res.stream_enc == NULL) {
909 pipe_ctx->stream = NULL;
910 return;
911 }
912
913 if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
914 link = pipe_ctx->stream->link;
915
916
917
918
919
920
921 if (!pipe_ctx->stream->dpms_off || link->link_status.link_active)
922 core_link_disable_stream(pipe_ctx);
923 else if (pipe_ctx->stream_res.audio)
924 dc->hwss.disable_audio_stream(pipe_ctx);
925
926 if (pipe_ctx->stream_res.audio) {
927
928 pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio);
929
930
931 if (dc->caps.dynamic_audio == true) {
932
933
934 update_audio_usage(&dc->current_state->res_ctx, dc->res_pool,
935 pipe_ctx->stream_res.audio, false);
936 pipe_ctx->stream_res.audio = NULL;
937 }
938 }
939 }
940
941
942
943
944
945 if (pipe_ctx->top_pipe == NULL) {
946
947 if (pipe_ctx->stream_res.abm)
948 dc->hwss.set_abm_immediate_disable(pipe_ctx);
949
950 pipe_ctx->stream_res.tg->funcs->disable_crtc(pipe_ctx->stream_res.tg);
951
952 pipe_ctx->stream_res.tg->funcs->enable_optc_clock(pipe_ctx->stream_res.tg, false);
953 if (pipe_ctx->stream_res.tg->funcs->set_drr)
954 pipe_ctx->stream_res.tg->funcs->set_drr(
955 pipe_ctx->stream_res.tg, NULL);
956 }
957
958 for (i = 0; i < dc->res_pool->pipe_count; i++)
959 if (&dc->current_state->res_ctx.pipe_ctx[i] == pipe_ctx)
960 break;
961
962 if (i == dc->res_pool->pipe_count)
963 return;
964
965 pipe_ctx->stream = NULL;
966 DC_LOG_DEBUG("Reset back end for pipe %d, tg:%d\n",
967 pipe_ctx->pipe_idx, pipe_ctx->stream_res.tg->inst);
968}
969
970static bool dcn10_hw_wa_force_recovery(struct dc *dc)
971{
972 struct hubp *hubp ;
973 unsigned int i;
974 bool need_recover = true;
975
976 if (!dc->debug.recovery_enabled)
977 return false;
978
979 for (i = 0; i < dc->res_pool->pipe_count; i++) {
980 struct pipe_ctx *pipe_ctx =
981 &dc->current_state->res_ctx.pipe_ctx[i];
982 if (pipe_ctx != NULL) {
983 hubp = pipe_ctx->plane_res.hubp;
984 if (hubp != NULL && hubp->funcs->hubp_get_underflow_status) {
985 if (hubp->funcs->hubp_get_underflow_status(hubp) != 0) {
986
987 need_recover = true;
988 }
989 }
990 }
991 }
992 if (!need_recover)
993 return false;
994
995
996
997
998
999
1000
1001
1002
1003
1004 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1005 struct pipe_ctx *pipe_ctx =
1006 &dc->current_state->res_ctx.pipe_ctx[i];
1007 if (pipe_ctx != NULL) {
1008 hubp = pipe_ctx->plane_res.hubp;
1009
1010 if (hubp != NULL && hubp->funcs->set_hubp_blank_en)
1011 hubp->funcs->set_hubp_blank_en(hubp, true);
1012 }
1013 }
1014
1015 hubbub1_soft_reset(dc->res_pool->hubbub, true);
1016
1017 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1018 struct pipe_ctx *pipe_ctx =
1019 &dc->current_state->res_ctx.pipe_ctx[i];
1020 if (pipe_ctx != NULL) {
1021 hubp = pipe_ctx->plane_res.hubp;
1022
1023 if (hubp != NULL && hubp->funcs->hubp_disable_control)
1024 hubp->funcs->hubp_disable_control(hubp, true);
1025 }
1026 }
1027 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1028 struct pipe_ctx *pipe_ctx =
1029 &dc->current_state->res_ctx.pipe_ctx[i];
1030 if (pipe_ctx != NULL) {
1031 hubp = pipe_ctx->plane_res.hubp;
1032
1033 if (hubp != NULL && hubp->funcs->hubp_disable_control)
1034 hubp->funcs->hubp_disable_control(hubp, true);
1035 }
1036 }
1037
1038 hubbub1_soft_reset(dc->res_pool->hubbub, false);
1039 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1040 struct pipe_ctx *pipe_ctx =
1041 &dc->current_state->res_ctx.pipe_ctx[i];
1042 if (pipe_ctx != NULL) {
1043 hubp = pipe_ctx->plane_res.hubp;
1044
1045 if (hubp != NULL && hubp->funcs->set_hubp_blank_en)
1046 hubp->funcs->set_hubp_blank_en(hubp, true);
1047 }
1048 }
1049 return true;
1050
1051}
1052
1053void dcn10_verify_allow_pstate_change_high(struct dc *dc)
1054{
1055 static bool should_log_hw_state;
1056
1057 if (!hubbub1_verify_allow_pstate_change_high(dc->res_pool->hubbub)) {
1058 int i = 0;
1059
1060 if (should_log_hw_state)
1061 dcn10_log_hw_state(dc, NULL);
1062
1063 TRACE_DC_PIPE_STATE(pipe_ctx, i, MAX_PIPES);
1064 BREAK_TO_DEBUGGER();
1065 if (dcn10_hw_wa_force_recovery(dc)) {
1066
1067 if (!hubbub1_verify_allow_pstate_change_high(dc->res_pool->hubbub))
1068 BREAK_TO_DEBUGGER();
1069 }
1070 }
1071}
1072
1073
1074void dcn10_plane_atomic_disconnect(struct dc *dc, struct pipe_ctx *pipe_ctx)
1075{
1076 struct dce_hwseq *hws = dc->hwseq;
1077 struct hubp *hubp = pipe_ctx->plane_res.hubp;
1078 int dpp_id = pipe_ctx->plane_res.dpp->inst;
1079 struct mpc *mpc = dc->res_pool->mpc;
1080 struct mpc_tree *mpc_tree_params;
1081 struct mpcc *mpcc_to_remove = NULL;
1082 struct output_pixel_processor *opp = pipe_ctx->stream_res.opp;
1083
1084 mpc_tree_params = &(opp->mpc_tree_params);
1085 mpcc_to_remove = mpc->funcs->get_mpcc_for_dpp(mpc_tree_params, dpp_id);
1086
1087
1088 if (mpcc_to_remove == NULL)
1089 return;
1090
1091 mpc->funcs->remove_mpcc(mpc, mpc_tree_params, mpcc_to_remove);
1092 if (opp != NULL)
1093 opp->mpcc_disconnect_pending[pipe_ctx->plane_res.mpcc_inst] = true;
1094
1095 dc->optimized_required = true;
1096
1097 if (hubp->funcs->hubp_disconnect)
1098 hubp->funcs->hubp_disconnect(hubp);
1099
1100 if (dc->debug.sanity_checks)
1101 hws->funcs.verify_allow_pstate_change_high(dc);
1102}
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117void dcn10_plane_atomic_power_down(struct dc *dc,
1118 struct dpp *dpp,
1119 struct hubp *hubp)
1120{
1121 struct dce_hwseq *hws = dc->hwseq;
1122 DC_LOGGER_INIT(dc->ctx->logger);
1123
1124 if (REG(DC_IP_REQUEST_CNTL)) {
1125 REG_SET(DC_IP_REQUEST_CNTL, 0,
1126 IP_REQUEST_EN, 1);
1127
1128 if (hws->funcs.dpp_pg_control)
1129 hws->funcs.dpp_pg_control(hws, dpp->inst, false);
1130
1131 if (hws->funcs.hubp_pg_control)
1132 hws->funcs.hubp_pg_control(hws, hubp->inst, false);
1133
1134 dpp->funcs->dpp_reset(dpp);
1135 REG_SET(DC_IP_REQUEST_CNTL, 0,
1136 IP_REQUEST_EN, 0);
1137 DC_LOG_DEBUG(
1138 "Power gated front end %d\n", hubp->inst);
1139 }
1140}
1141
1142
1143
1144
1145void dcn10_plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx)
1146{
1147 struct dce_hwseq *hws = dc->hwseq;
1148 struct hubp *hubp = pipe_ctx->plane_res.hubp;
1149 struct dpp *dpp = pipe_ctx->plane_res.dpp;
1150 int opp_id = hubp->opp_id;
1151
1152 dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, pipe_ctx);
1153
1154 hubp->funcs->hubp_clk_cntl(hubp, false);
1155
1156 dpp->funcs->dpp_dppclk_control(dpp, false, false);
1157
1158 if (opp_id != 0xf && pipe_ctx->stream_res.opp->mpc_tree_params.opp_list == NULL)
1159 pipe_ctx->stream_res.opp->funcs->opp_pipe_clock_control(
1160 pipe_ctx->stream_res.opp,
1161 false);
1162
1163 hubp->power_gated = true;
1164 dc->optimized_required = false;
1165
1166 hws->funcs.plane_atomic_power_down(dc,
1167 pipe_ctx->plane_res.dpp,
1168 pipe_ctx->plane_res.hubp);
1169
1170 pipe_ctx->stream = NULL;
1171 memset(&pipe_ctx->stream_res, 0, sizeof(pipe_ctx->stream_res));
1172 memset(&pipe_ctx->plane_res, 0, sizeof(pipe_ctx->plane_res));
1173 pipe_ctx->top_pipe = NULL;
1174 pipe_ctx->bottom_pipe = NULL;
1175 pipe_ctx->plane_state = NULL;
1176}
1177
1178void dcn10_disable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx)
1179{
1180 struct dce_hwseq *hws = dc->hwseq;
1181 DC_LOGGER_INIT(dc->ctx->logger);
1182
1183 if (!pipe_ctx->plane_res.hubp || pipe_ctx->plane_res.hubp->power_gated)
1184 return;
1185
1186 hws->funcs.plane_atomic_disable(dc, pipe_ctx);
1187
1188 apply_DEGVIDCN10_253_wa(dc);
1189
1190 DC_LOG_DC("Power down front end %d\n",
1191 pipe_ctx->pipe_idx);
1192}
1193
1194void dcn10_init_pipes(struct dc *dc, struct dc_state *context)
1195{
1196 int i;
1197 struct dce_hwseq *hws = dc->hwseq;
1198 bool can_apply_seamless_boot = false;
1199
1200 for (i = 0; i < context->stream_count; i++) {
1201 if (context->streams[i]->apply_seamless_boot_optimization) {
1202 can_apply_seamless_boot = true;
1203 break;
1204 }
1205 }
1206
1207 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1208 struct timing_generator *tg = dc->res_pool->timing_generators[i];
1209 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1210
1211
1212
1213
1214
1215 if (pipe_ctx->stream != NULL && can_apply_seamless_boot)
1216 continue;
1217
1218
1219
1220
1221 if (tg->funcs->is_tg_enabled(tg)) {
1222 if (hws->funcs.init_blank != NULL) {
1223 hws->funcs.init_blank(dc, tg);
1224 tg->funcs->lock(tg);
1225 } else {
1226 tg->funcs->lock(tg);
1227 tg->funcs->set_blank(tg, true);
1228 hwss_wait_for_blank_complete(tg);
1229 }
1230 }
1231 }
1232
1233
1234 for (i = 0; i < dc->res_pool->res_cap->num_opp; i++) {
1235 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1236
1237
1238 if (pipe_ctx->stream != NULL && can_apply_seamless_boot)
1239 continue;
1240
1241 dc->res_pool->mpc->funcs->mpc_init_single_inst(
1242 dc->res_pool->mpc, i);
1243 }
1244
1245 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1246 struct timing_generator *tg = dc->res_pool->timing_generators[i];
1247 struct hubp *hubp = dc->res_pool->hubps[i];
1248 struct dpp *dpp = dc->res_pool->dpps[i];
1249 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1250
1251
1252
1253
1254
1255 if (can_apply_seamless_boot &&
1256 pipe_ctx->stream != NULL &&
1257 pipe_ctx->stream_res.tg->funcs->is_tg_enabled(
1258 pipe_ctx->stream_res.tg)) {
1259
1260
1261
1262
1263 tg->funcs->tg_init(tg);
1264 hubp->power_gated = true;
1265 continue;
1266 }
1267
1268
1269 pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
1270
1271 dpp->funcs->dpp_reset(dpp);
1272
1273 pipe_ctx->stream_res.tg = tg;
1274 pipe_ctx->pipe_idx = i;
1275
1276 pipe_ctx->plane_res.hubp = hubp;
1277 pipe_ctx->plane_res.dpp = dpp;
1278 pipe_ctx->plane_res.mpcc_inst = dpp->inst;
1279 hubp->mpcc_id = dpp->inst;
1280 hubp->opp_id = OPP_ID_INVALID;
1281 hubp->power_gated = false;
1282
1283 dc->res_pool->opps[i]->mpc_tree_params.opp_id = dc->res_pool->opps[i]->inst;
1284 dc->res_pool->opps[i]->mpc_tree_params.opp_list = NULL;
1285 dc->res_pool->opps[i]->mpcc_disconnect_pending[pipe_ctx->plane_res.mpcc_inst] = true;
1286 pipe_ctx->stream_res.opp = dc->res_pool->opps[i];
1287
1288 hws->funcs.plane_atomic_disconnect(dc, pipe_ctx);
1289
1290 if (tg->funcs->is_tg_enabled(tg))
1291 tg->funcs->unlock(tg);
1292
1293 dc->hwss.disable_plane(dc, pipe_ctx);
1294
1295 pipe_ctx->stream_res.tg = NULL;
1296 pipe_ctx->plane_res.hubp = NULL;
1297
1298 tg->funcs->tg_init(tg);
1299 }
1300}
1301
1302void dcn10_init_hw(struct dc *dc)
1303{
1304 int i, j;
1305 struct abm *abm = dc->res_pool->abm;
1306 struct dmcu *dmcu = dc->res_pool->dmcu;
1307 struct dce_hwseq *hws = dc->hwseq;
1308 struct dc_bios *dcb = dc->ctx->dc_bios;
1309 struct resource_pool *res_pool = dc->res_pool;
1310 uint32_t backlight = MAX_BACKLIGHT_LEVEL;
1311 bool is_optimized_init_done = false;
1312
1313 if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks)
1314 dc->clk_mgr->funcs->init_clocks(dc->clk_mgr);
1315
1316
1317 if (dc->res_pool->dccg && dc->res_pool->dccg->funcs->dccg_init)
1318 dc->res_pool->dccg->funcs->dccg_init(res_pool->dccg);
1319
1320 if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
1321
1322 REG_WRITE(REFCLK_CNTL, 0);
1323 REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1);
1324 REG_WRITE(DIO_MEM_PWR_CTRL, 0);
1325
1326 if (!dc->debug.disable_clock_gate) {
1327
1328 REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0);
1329
1330 REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0);
1331
1332 REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);
1333 }
1334
1335
1336 if (hws->funcs.enable_power_gating_plane)
1337 hws->funcs.enable_power_gating_plane(hws, true);
1338
1339 return;
1340 }
1341
1342 if (!dcb->funcs->is_accelerated_mode(dcb))
1343 hws->funcs.disable_vga(dc->hwseq);
1344
1345 hws->funcs.bios_golden_init(dc);
1346
1347 if (dc->ctx->dc_bios->fw_info_valid) {
1348 res_pool->ref_clocks.xtalin_clock_inKhz =
1349 dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency;
1350
1351 if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
1352 if (res_pool->dccg && res_pool->hubbub) {
1353
1354 (res_pool->dccg->funcs->get_dccg_ref_freq)(res_pool->dccg,
1355 dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency,
1356 &res_pool->ref_clocks.dccg_ref_clock_inKhz);
1357
1358 (res_pool->hubbub->funcs->get_dchub_ref_freq)(res_pool->hubbub,
1359 res_pool->ref_clocks.dccg_ref_clock_inKhz,
1360 &res_pool->ref_clocks.dchub_ref_clock_inKhz);
1361 } else {
1362
1363 res_pool->ref_clocks.dccg_ref_clock_inKhz =
1364 res_pool->ref_clocks.xtalin_clock_inKhz;
1365 res_pool->ref_clocks.dchub_ref_clock_inKhz =
1366 res_pool->ref_clocks.xtalin_clock_inKhz;
1367 }
1368 }
1369 } else
1370 ASSERT_CRITICAL(false);
1371
1372 for (i = 0; i < dc->link_count; i++) {
1373
1374
1375
1376
1377 struct dc_link *link = dc->links[i];
1378
1379 if (!is_optimized_init_done)
1380 link->link_enc->funcs->hw_init(link->link_enc);
1381
1382
1383 if (link->link_enc->funcs->is_dig_enabled &&
1384 link->link_enc->funcs->is_dig_enabled(link->link_enc))
1385 link->link_status.link_active = true;
1386 }
1387
1388
1389 if (!is_optimized_init_done) {
1390 for (i = 0; i < res_pool->res_cap->num_dsc; i++)
1391 if (hws->funcs.dsc_pg_control != NULL)
1392 hws->funcs.dsc_pg_control(hws, res_pool->dscs[i]->inst, false);
1393 }
1394
1395
1396 if (dc->debug.enable_dmub_aux_for_legacy_ddc)
1397 dmub_enable_outbox_notification(dc);
1398
1399
1400 if (dc->config.power_down_display_on_boot) {
1401 uint8_t dpcd_power_state = '\0';
1402 enum dc_status status = DC_ERROR_UNEXPECTED;
1403
1404 for (i = 0; i < dc->link_count; i++) {
1405 if (dc->links[i]->connector_signal != SIGNAL_TYPE_DISPLAY_PORT)
1406 continue;
1407
1408
1409 dp_retrieve_lttpr_cap(dc->links[i]);
1410
1411
1412
1413
1414
1415
1416
1417
1418 status = core_link_read_dpcd(dc->links[i], DP_SET_POWER,
1419 &dpcd_power_state, sizeof(dpcd_power_state));
1420 if (status == DC_OK && dpcd_power_state == DP_POWER_STATE_D0) {
1421
1422 if (dc->links[i]->link_enc->funcs->get_dig_frontend) {
1423 unsigned int fe = dc->links[i]->link_enc->funcs->get_dig_frontend(dc->links[i]->link_enc);
1424
1425 for (j = 0; j < dc->res_pool->stream_enc_count; j++) {
1426 if (fe == dc->res_pool->stream_enc[j]->id) {
1427 dc->res_pool->stream_enc[j]->funcs->dp_blank(
1428 dc->res_pool->stream_enc[j]);
1429 break;
1430 }
1431 }
1432 }
1433 dp_receiver_power_ctrl(dc->links[i], false);
1434 }
1435 }
1436 }
1437
1438
1439
1440
1441
1442
1443
1444 if (dcb->funcs->is_accelerated_mode(dcb) || dc->config.power_down_display_on_boot) {
1445 if (!is_optimized_init_done) {
1446 hws->funcs.init_pipes(dc, dc->current_state);
1447 if (dc->res_pool->hubbub->funcs->allow_self_refresh_control)
1448 dc->res_pool->hubbub->funcs->allow_self_refresh_control(dc->res_pool->hubbub,
1449 !dc->res_pool->hubbub->ctx->dc->debug.disable_stutter);
1450 }
1451 }
1452
1453 if (!is_optimized_init_done) {
1454
1455 for (i = 0; i < res_pool->audio_count; i++) {
1456 struct audio *audio = res_pool->audios[i];
1457
1458 audio->funcs->hw_init(audio);
1459 }
1460
1461 for (i = 0; i < dc->link_count; i++) {
1462 struct dc_link *link = dc->links[i];
1463
1464 if (link->panel_cntl)
1465 backlight = link->panel_cntl->funcs->hw_init(link->panel_cntl);
1466 }
1467
1468 if (abm != NULL)
1469 abm->funcs->abm_init(abm, backlight);
1470
1471 if (dmcu != NULL && !dmcu->auto_load_dmcu)
1472 dmcu->funcs->dmcu_init(dmcu);
1473 }
1474
1475 if (abm != NULL && dmcu != NULL)
1476 abm->dmcu_is_running = dmcu->funcs->is_dmcu_initialized(dmcu);
1477
1478
1479 if (!is_optimized_init_done)
1480 REG_WRITE(DIO_MEM_PWR_CTRL, 0);
1481
1482 if (!dc->debug.disable_clock_gate) {
1483
1484 REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0);
1485
1486 REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0);
1487
1488 REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);
1489 }
1490 if (hws->funcs.enable_power_gating_plane)
1491 hws->funcs.enable_power_gating_plane(dc->hwseq, true);
1492
1493 if (dc->clk_mgr->funcs->notify_wm_ranges)
1494 dc->clk_mgr->funcs->notify_wm_ranges(dc->clk_mgr);
1495}
1496
1497
1498
1499
1500
1501
1502void dcn10_power_down_on_boot(struct dc *dc)
1503{
1504 struct dc_link *edp_links[MAX_NUM_EDP];
1505 struct dc_link *edp_link = NULL;
1506 int edp_num;
1507 int i = 0;
1508
1509 get_edp_links(dc, edp_links, &edp_num);
1510 if (edp_num)
1511 edp_link = edp_links[0];
1512
1513 if (edp_link && edp_link->link_enc->funcs->is_dig_enabled &&
1514 edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc) &&
1515 dc->hwseq->funcs.edp_backlight_control &&
1516 dc->hwss.power_down &&
1517 dc->hwss.edp_power_control) {
1518 dc->hwseq->funcs.edp_backlight_control(edp_link, false);
1519 dc->hwss.power_down(dc);
1520 dc->hwss.edp_power_control(edp_link, false);
1521 } else {
1522 for (i = 0; i < dc->link_count; i++) {
1523 struct dc_link *link = dc->links[i];
1524
1525 if (link->link_enc->funcs->is_dig_enabled &&
1526 link->link_enc->funcs->is_dig_enabled(link->link_enc) &&
1527 dc->hwss.power_down) {
1528 dc->hwss.power_down(dc);
1529 break;
1530 }
1531
1532 }
1533 }
1534
1535
1536
1537
1538
1539
1540 if (dc->clk_mgr->funcs->set_low_power_state)
1541 dc->clk_mgr->funcs->set_low_power_state(dc->clk_mgr);
1542}
1543
1544void dcn10_reset_hw_ctx_wrap(
1545 struct dc *dc,
1546 struct dc_state *context)
1547{
1548 int i;
1549 struct dce_hwseq *hws = dc->hwseq;
1550
1551
1552 for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) {
1553 struct pipe_ctx *pipe_ctx_old =
1554 &dc->current_state->res_ctx.pipe_ctx[i];
1555 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1556
1557 if (!pipe_ctx_old->stream)
1558 continue;
1559
1560 if (pipe_ctx_old->top_pipe)
1561 continue;
1562
1563 if (!pipe_ctx->stream ||
1564 pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) {
1565 struct clock_source *old_clk = pipe_ctx_old->clock_source;
1566
1567 dcn10_reset_back_end_for_pipe(dc, pipe_ctx_old, dc->current_state);
1568 if (hws->funcs.enable_stream_gating)
1569 hws->funcs.enable_stream_gating(dc, pipe_ctx);
1570 if (old_clk)
1571 old_clk->funcs->cs_power_down(old_clk);
1572 }
1573 }
1574}
1575
1576static bool patch_address_for_sbs_tb_stereo(
1577 struct pipe_ctx *pipe_ctx, PHYSICAL_ADDRESS_LOC *addr)
1578{
1579 struct dc_plane_state *plane_state = pipe_ctx->plane_state;
1580 bool sec_split = pipe_ctx->top_pipe &&
1581 pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state;
1582 if (sec_split && plane_state->address.type == PLN_ADDR_TYPE_GRPH_STEREO &&
1583 (pipe_ctx->stream->timing.timing_3d_format ==
1584 TIMING_3D_FORMAT_SIDE_BY_SIDE ||
1585 pipe_ctx->stream->timing.timing_3d_format ==
1586 TIMING_3D_FORMAT_TOP_AND_BOTTOM)) {
1587 *addr = plane_state->address.grph_stereo.left_addr;
1588 plane_state->address.grph_stereo.left_addr =
1589 plane_state->address.grph_stereo.right_addr;
1590 return true;
1591 } else {
1592 if (pipe_ctx->stream->view_format != VIEW_3D_FORMAT_NONE &&
1593 plane_state->address.type != PLN_ADDR_TYPE_GRPH_STEREO) {
1594 plane_state->address.type = PLN_ADDR_TYPE_GRPH_STEREO;
1595 plane_state->address.grph_stereo.right_addr =
1596 plane_state->address.grph_stereo.left_addr;
1597 plane_state->address.grph_stereo.right_meta_addr =
1598 plane_state->address.grph_stereo.left_meta_addr;
1599 }
1600 }
1601 return false;
1602}
1603
1604void dcn10_update_plane_addr(const struct dc *dc, struct pipe_ctx *pipe_ctx)
1605{
1606 bool addr_patched = false;
1607 PHYSICAL_ADDRESS_LOC addr;
1608 struct dc_plane_state *plane_state = pipe_ctx->plane_state;
1609
1610 if (plane_state == NULL)
1611 return;
1612
1613 addr_patched = patch_address_for_sbs_tb_stereo(pipe_ctx, &addr);
1614
1615 pipe_ctx->plane_res.hubp->funcs->hubp_program_surface_flip_and_addr(
1616 pipe_ctx->plane_res.hubp,
1617 &plane_state->address,
1618 plane_state->flip_immediate);
1619
1620 plane_state->status.requested_address = plane_state->address;
1621
1622 if (plane_state->flip_immediate)
1623 plane_state->status.current_address = plane_state->address;
1624
1625 if (addr_patched)
1626 pipe_ctx->plane_state->address.grph_stereo.left_addr = addr;
1627}
1628
1629bool dcn10_set_input_transfer_func(struct dc *dc, struct pipe_ctx *pipe_ctx,
1630 const struct dc_plane_state *plane_state)
1631{
1632 struct dpp *dpp_base = pipe_ctx->plane_res.dpp;
1633 const struct dc_transfer_func *tf = NULL;
1634 bool result = true;
1635
1636 if (dpp_base == NULL)
1637 return false;
1638
1639 if (plane_state->in_transfer_func)
1640 tf = plane_state->in_transfer_func;
1641
1642 if (plane_state->gamma_correction &&
1643 !dpp_base->ctx->dc->debug.always_use_regamma
1644 && !plane_state->gamma_correction->is_identity
1645 && dce_use_lut(plane_state->format))
1646 dpp_base->funcs->dpp_program_input_lut(dpp_base, plane_state->gamma_correction);
1647
1648 if (tf == NULL)
1649 dpp_base->funcs->dpp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_BYPASS);
1650 else if (tf->type == TF_TYPE_PREDEFINED) {
1651 switch (tf->tf) {
1652 case TRANSFER_FUNCTION_SRGB:
1653 dpp_base->funcs->dpp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_HW_sRGB);
1654 break;
1655 case TRANSFER_FUNCTION_BT709:
1656 dpp_base->funcs->dpp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_HW_xvYCC);
1657 break;
1658 case TRANSFER_FUNCTION_LINEAR:
1659 dpp_base->funcs->dpp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_BYPASS);
1660 break;
1661 case TRANSFER_FUNCTION_PQ:
1662 dpp_base->funcs->dpp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_USER_PWL);
1663 cm_helper_translate_curve_to_degamma_hw_format(tf, &dpp_base->degamma_params);
1664 dpp_base->funcs->dpp_program_degamma_pwl(dpp_base, &dpp_base->degamma_params);
1665 result = true;
1666 break;
1667 default:
1668 result = false;
1669 break;
1670 }
1671 } else if (tf->type == TF_TYPE_BYPASS) {
1672 dpp_base->funcs->dpp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_BYPASS);
1673 } else {
1674 cm_helper_translate_curve_to_degamma_hw_format(tf,
1675 &dpp_base->degamma_params);
1676 dpp_base->funcs->dpp_program_degamma_pwl(dpp_base,
1677 &dpp_base->degamma_params);
1678 result = true;
1679 }
1680
1681 return result;
1682}
1683
1684#define MAX_NUM_HW_POINTS 0x200
1685
1686static void log_tf(struct dc_context *ctx,
1687 struct dc_transfer_func *tf, uint32_t hw_points_num)
1688{
1689
1690
1691
1692 int i = 0;
1693
1694 DC_LOGGER_INIT(ctx->logger);
1695 DC_LOG_GAMMA("Gamma Correction TF");
1696 DC_LOG_ALL_GAMMA("Logging all tf points...");
1697 DC_LOG_ALL_TF_CHANNELS("Logging all channels...");
1698
1699 for (i = 0; i < hw_points_num; i++) {
1700 DC_LOG_GAMMA("R\t%d\t%llu", i, tf->tf_pts.red[i].value);
1701 DC_LOG_ALL_TF_CHANNELS("G\t%d\t%llu", i, tf->tf_pts.green[i].value);
1702 DC_LOG_ALL_TF_CHANNELS("B\t%d\t%llu", i, tf->tf_pts.blue[i].value);
1703 }
1704
1705 for (i = hw_points_num; i < MAX_NUM_HW_POINTS; i++) {
1706 DC_LOG_ALL_GAMMA("R\t%d\t%llu", i, tf->tf_pts.red[i].value);
1707 DC_LOG_ALL_TF_CHANNELS("G\t%d\t%llu", i, tf->tf_pts.green[i].value);
1708 DC_LOG_ALL_TF_CHANNELS("B\t%d\t%llu", i, tf->tf_pts.blue[i].value);
1709 }
1710}
1711
1712bool dcn10_set_output_transfer_func(struct dc *dc, struct pipe_ctx *pipe_ctx,
1713 const struct dc_stream_state *stream)
1714{
1715 struct dpp *dpp = pipe_ctx->plane_res.dpp;
1716
1717 if (dpp == NULL)
1718 return false;
1719
1720 dpp->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM;
1721
1722 if (stream->out_transfer_func &&
1723 stream->out_transfer_func->type == TF_TYPE_PREDEFINED &&
1724 stream->out_transfer_func->tf == TRANSFER_FUNCTION_SRGB)
1725 dpp->funcs->dpp_program_regamma_pwl(dpp, NULL, OPP_REGAMMA_SRGB);
1726
1727
1728
1729
1730 else if (cm_helper_translate_curve_to_hw_format(
1731 stream->out_transfer_func,
1732 &dpp->regamma_params, false)) {
1733 dpp->funcs->dpp_program_regamma_pwl(
1734 dpp,
1735 &dpp->regamma_params, OPP_REGAMMA_USER);
1736 } else
1737 dpp->funcs->dpp_program_regamma_pwl(dpp, NULL, OPP_REGAMMA_BYPASS);
1738
1739 if (stream != NULL && stream->ctx != NULL &&
1740 stream->out_transfer_func != NULL) {
1741 log_tf(stream->ctx,
1742 stream->out_transfer_func,
1743 dpp->regamma_params.hw_points_num);
1744 }
1745
1746 return true;
1747}
1748
1749void dcn10_pipe_control_lock(
1750 struct dc *dc,
1751 struct pipe_ctx *pipe,
1752 bool lock)
1753{
1754 struct dce_hwseq *hws = dc->hwseq;
1755
1756
1757
1758
1759 if (!pipe || pipe->top_pipe)
1760 return;
1761
1762 if (dc->debug.sanity_checks)
1763 hws->funcs.verify_allow_pstate_change_high(dc);
1764
1765 if (lock)
1766 pipe->stream_res.tg->funcs->lock(pipe->stream_res.tg);
1767 else
1768 pipe->stream_res.tg->funcs->unlock(pipe->stream_res.tg);
1769
1770 if (dc->debug.sanity_checks)
1771 hws->funcs.verify_allow_pstate_change_high(dc);
1772}
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787static void delay_cursor_until_vupdate(struct dc *dc, struct pipe_ctx *pipe_ctx)
1788{
1789 struct dc_stream_state *stream = pipe_ctx->stream;
1790 struct crtc_position position;
1791 uint32_t vupdate_start, vupdate_end;
1792 unsigned int lines_to_vupdate, us_to_vupdate, vpos;
1793 unsigned int us_per_line, us_vupdate;
1794
1795 if (!dc->hwss.calc_vupdate_position || !dc->hwss.get_position)
1796 return;
1797
1798 if (!pipe_ctx->stream_res.stream_enc || !pipe_ctx->stream_res.tg)
1799 return;
1800
1801 dc->hwss.calc_vupdate_position(dc, pipe_ctx, &vupdate_start,
1802 &vupdate_end);
1803
1804 dc->hwss.get_position(&pipe_ctx, 1, &position);
1805 vpos = position.vertical_count;
1806
1807
1808 vupdate_start += stream->timing.v_total;
1809 vupdate_end += stream->timing.v_total;
1810 vpos += stream->timing.v_total;
1811
1812 if (vpos <= vupdate_start) {
1813
1814 lines_to_vupdate = vupdate_start - vpos;
1815 } else if (vpos > vupdate_end) {
1816
1817 return;
1818 } else {
1819
1820 lines_to_vupdate = 0;
1821 }
1822
1823
1824 us_per_line =
1825 stream->timing.h_total * 10000u / stream->timing.pix_clk_100hz;
1826 us_to_vupdate = lines_to_vupdate * us_per_line;
1827
1828
1829 if (us_to_vupdate > 70)
1830 return;
1831
1832
1833 if (vupdate_end < vupdate_start)
1834 vupdate_end += stream->timing.v_total;
1835 us_vupdate = (vupdate_end - vupdate_start + 1) * us_per_line;
1836 udelay(us_to_vupdate + us_vupdate);
1837}
1838
1839void dcn10_cursor_lock(struct dc *dc, struct pipe_ctx *pipe, bool lock)
1840{
1841
1842 if (!pipe || pipe->top_pipe)
1843 return;
1844
1845
1846 if (lock)
1847 delay_cursor_until_vupdate(dc, pipe);
1848
1849 if (pipe->stream && should_use_dmub_lock(pipe->stream->link)) {
1850 union dmub_hw_lock_flags hw_locks = { 0 };
1851 struct dmub_hw_lock_inst_flags inst_flags = { 0 };
1852
1853 hw_locks.bits.lock_cursor = 1;
1854 inst_flags.opp_inst = pipe->stream_res.opp->inst;
1855
1856 dmub_hw_lock_mgr_cmd(dc->ctx->dmub_srv,
1857 lock,
1858 &hw_locks,
1859 &inst_flags);
1860 } else
1861 dc->res_pool->mpc->funcs->cursor_lock(dc->res_pool->mpc,
1862 pipe->stream_res.opp->inst, lock);
1863}
1864
1865static bool wait_for_reset_trigger_to_occur(
1866 struct dc_context *dc_ctx,
1867 struct timing_generator *tg)
1868{
1869 bool rc = false;
1870
1871
1872
1873 const uint32_t frames_to_wait_on_triggered_reset = 10;
1874 int i;
1875
1876 for (i = 0; i < frames_to_wait_on_triggered_reset; i++) {
1877
1878 if (!tg->funcs->is_counter_moving(tg)) {
1879 DC_ERROR("TG counter is not moving!\n");
1880 break;
1881 }
1882
1883 if (tg->funcs->did_triggered_reset_occur(tg)) {
1884 rc = true;
1885
1886 DC_SYNC_INFO("GSL: reset occurred at wait count: %d\n",
1887 i);
1888 break;
1889 }
1890
1891
1892 tg->funcs->wait_for_state(tg, CRTC_STATE_VACTIVE);
1893 tg->funcs->wait_for_state(tg, CRTC_STATE_VBLANK);
1894 }
1895
1896 if (false == rc)
1897 DC_ERROR("GSL: Timeout on reset trigger!\n");
1898
1899 return rc;
1900}
1901
1902uint64_t reduceSizeAndFraction(
1903 uint64_t *numerator,
1904 uint64_t *denominator,
1905 bool checkUint32Bounary)
1906{
1907 int i;
1908 bool ret = checkUint32Bounary == false;
1909 uint64_t max_int32 = 0xffffffff;
1910 uint64_t num, denom;
1911 static const uint16_t prime_numbers[] = {
1912 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43,
1913 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103,
1914 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163,
1915 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227,
1916 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281,
1917 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353,
1918 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421,
1919 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487,
1920 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569,
1921 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631,
1922 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701,
1923 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773,
1924 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857,
1925 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937,
1926 941, 947, 953, 967, 971, 977, 983, 991, 997};
1927 int count = ARRAY_SIZE(prime_numbers);
1928
1929 num = *numerator;
1930 denom = *denominator;
1931 for (i = 0; i < count; i++) {
1932 uint32_t num_remainder, denom_remainder;
1933 uint64_t num_result, denom_result;
1934 if (checkUint32Bounary &&
1935 num <= max_int32 && denom <= max_int32) {
1936 ret = true;
1937 break;
1938 }
1939 do {
1940 num_result = div_u64_rem(num, prime_numbers[i], &num_remainder);
1941 denom_result = div_u64_rem(denom, prime_numbers[i], &denom_remainder);
1942 if (num_remainder == 0 && denom_remainder == 0) {
1943 num = num_result;
1944 denom = denom_result;
1945 }
1946 } while (num_remainder == 0 && denom_remainder == 0);
1947 }
1948 *numerator = num;
1949 *denominator = denom;
1950 return ret;
1951}
1952
1953bool is_low_refresh_rate(struct pipe_ctx *pipe)
1954{
1955 uint32_t master_pipe_refresh_rate =
1956 pipe->stream->timing.pix_clk_100hz * 100 /
1957 pipe->stream->timing.h_total /
1958 pipe->stream->timing.v_total;
1959 return master_pipe_refresh_rate <= 30;
1960}
1961
1962uint8_t get_clock_divider(struct pipe_ctx *pipe, bool account_low_refresh_rate)
1963{
1964 uint32_t clock_divider = 1;
1965 uint32_t numpipes = 1;
1966
1967 if (account_low_refresh_rate && is_low_refresh_rate(pipe))
1968 clock_divider *= 2;
1969
1970 if (pipe->stream_res.pix_clk_params.pixel_encoding == PIXEL_ENCODING_YCBCR420)
1971 clock_divider *= 2;
1972
1973 while (pipe->next_odm_pipe) {
1974 pipe = pipe->next_odm_pipe;
1975 numpipes++;
1976 }
1977 clock_divider *= numpipes;
1978
1979 return clock_divider;
1980}
1981
1982int dcn10_align_pixel_clocks(
1983 struct dc *dc,
1984 int group_size,
1985 struct pipe_ctx *grouped_pipes[])
1986{
1987 struct dc_context *dc_ctx = dc->ctx;
1988 int i, master = -1, embedded = -1;
1989 struct dc_crtc_timing hw_crtc_timing[MAX_PIPES] = {0};
1990 uint64_t phase[MAX_PIPES];
1991 uint64_t modulo[MAX_PIPES];
1992 unsigned int pclk;
1993
1994 uint32_t embedded_pix_clk_100hz;
1995 uint16_t embedded_h_total;
1996 uint16_t embedded_v_total;
1997 bool clamshell_closed = false;
1998 uint32_t dp_ref_clk_100hz =
1999 dc->res_pool->dp_clock_source->ctx->dc->clk_mgr->dprefclk_khz*10;
2000
2001 if (dc->config.vblank_alignment_dto_params &&
2002 dc->res_pool->dp_clock_source->funcs->override_dp_pix_clk) {
2003 clamshell_closed =
2004 (dc->config.vblank_alignment_dto_params >> 63);
2005 embedded_h_total =
2006 (dc->config.vblank_alignment_dto_params >> 32) & 0x7FFF;
2007 embedded_v_total =
2008 (dc->config.vblank_alignment_dto_params >> 48) & 0x7FFF;
2009 embedded_pix_clk_100hz =
2010 dc->config.vblank_alignment_dto_params & 0xFFFFFFFF;
2011
2012 for (i = 0; i < group_size; i++) {
2013 grouped_pipes[i]->stream_res.tg->funcs->get_hw_timing(
2014 grouped_pipes[i]->stream_res.tg,
2015 &hw_crtc_timing[i]);
2016 dc->res_pool->dp_clock_source->funcs->get_pixel_clk_frequency_100hz(
2017 dc->res_pool->dp_clock_source,
2018 grouped_pipes[i]->stream_res.tg->inst,
2019 &pclk);
2020 hw_crtc_timing[i].pix_clk_100hz = pclk;
2021 if (dc_is_embedded_signal(
2022 grouped_pipes[i]->stream->signal)) {
2023 embedded = i;
2024 master = i;
2025 phase[i] = embedded_pix_clk_100hz*100;
2026 modulo[i] = dp_ref_clk_100hz*100;
2027 } else {
2028
2029 phase[i] = (uint64_t)embedded_pix_clk_100hz*
2030 hw_crtc_timing[i].h_total*
2031 hw_crtc_timing[i].v_total;
2032 phase[i] = div_u64(phase[i], get_clock_divider(grouped_pipes[i], true));
2033 modulo[i] = (uint64_t)dp_ref_clk_100hz*
2034 embedded_h_total*
2035 embedded_v_total;
2036
2037 if (reduceSizeAndFraction(&phase[i],
2038 &modulo[i], true) == false) {
2039
2040
2041
2042
2043 DC_SYNC_INFO("Failed to reduce DTO parameters\n");
2044 grouped_pipes[i]->stream->has_non_synchronizable_pclk = true;
2045 }
2046 }
2047 }
2048
2049 for (i = 0; i < group_size; i++) {
2050 if (i != embedded && !grouped_pipes[i]->stream->has_non_synchronizable_pclk) {
2051 dc->res_pool->dp_clock_source->funcs->override_dp_pix_clk(
2052 dc->res_pool->dp_clock_source,
2053 grouped_pipes[i]->stream_res.tg->inst,
2054 phase[i], modulo[i]);
2055 dc->res_pool->dp_clock_source->funcs->get_pixel_clk_frequency_100hz(
2056 dc->res_pool->dp_clock_source,
2057 grouped_pipes[i]->stream_res.tg->inst, &pclk);
2058 grouped_pipes[i]->stream->timing.pix_clk_100hz =
2059 pclk*get_clock_divider(grouped_pipes[i], false);
2060 if (master == -1)
2061 master = i;
2062 }
2063 }
2064
2065 }
2066 return master;
2067}
2068
2069void dcn10_enable_vblanks_synchronization(
2070 struct dc *dc,
2071 int group_index,
2072 int group_size,
2073 struct pipe_ctx *grouped_pipes[])
2074{
2075 struct dc_context *dc_ctx = dc->ctx;
2076 struct output_pixel_processor *opp;
2077 struct timing_generator *tg;
2078 int i, width, height, master;
2079
2080 for (i = 1; i < group_size; i++) {
2081 opp = grouped_pipes[i]->stream_res.opp;
2082 tg = grouped_pipes[i]->stream_res.tg;
2083 tg->funcs->get_otg_active_size(tg, &width, &height);
2084 if (opp->funcs->opp_program_dpg_dimensions)
2085 opp->funcs->opp_program_dpg_dimensions(opp, width, 2*(height) + 1);
2086 }
2087
2088 for (i = 0; i < group_size; i++) {
2089 if (grouped_pipes[i]->stream == NULL)
2090 continue;
2091 grouped_pipes[i]->stream->vblank_synchronized = false;
2092 grouped_pipes[i]->stream->has_non_synchronizable_pclk = false;
2093 }
2094
2095 DC_SYNC_INFO("Aligning DP DTOs\n");
2096
2097 master = dcn10_align_pixel_clocks(dc, group_size, grouped_pipes);
2098
2099 DC_SYNC_INFO("Synchronizing VBlanks\n");
2100
2101 if (master >= 0) {
2102 for (i = 0; i < group_size; i++) {
2103 if (i != master && !grouped_pipes[i]->stream->has_non_synchronizable_pclk)
2104 grouped_pipes[i]->stream_res.tg->funcs->align_vblanks(
2105 grouped_pipes[master]->stream_res.tg,
2106 grouped_pipes[i]->stream_res.tg,
2107 grouped_pipes[master]->stream->timing.pix_clk_100hz,
2108 grouped_pipes[i]->stream->timing.pix_clk_100hz,
2109 get_clock_divider(grouped_pipes[master], false),
2110 get_clock_divider(grouped_pipes[i], false));
2111 grouped_pipes[i]->stream->vblank_synchronized = true;
2112 }
2113 grouped_pipes[master]->stream->vblank_synchronized = true;
2114 DC_SYNC_INFO("Sync complete\n");
2115 }
2116
2117 for (i = 1; i < group_size; i++) {
2118 opp = grouped_pipes[i]->stream_res.opp;
2119 tg = grouped_pipes[i]->stream_res.tg;
2120 tg->funcs->get_otg_active_size(tg, &width, &height);
2121 if (opp->funcs->opp_program_dpg_dimensions)
2122 opp->funcs->opp_program_dpg_dimensions(opp, width, height);
2123 }
2124}
2125
2126void dcn10_enable_timing_synchronization(
2127 struct dc *dc,
2128 int group_index,
2129 int group_size,
2130 struct pipe_ctx *grouped_pipes[])
2131{
2132 struct dc_context *dc_ctx = dc->ctx;
2133 struct output_pixel_processor *opp;
2134 struct timing_generator *tg;
2135 int i, width, height;
2136
2137 DC_SYNC_INFO("Setting up OTG reset trigger\n");
2138
2139 for (i = 1; i < group_size; i++) {
2140 opp = grouped_pipes[i]->stream_res.opp;
2141 tg = grouped_pipes[i]->stream_res.tg;
2142 tg->funcs->get_otg_active_size(tg, &width, &height);
2143 if (opp->funcs->opp_program_dpg_dimensions)
2144 opp->funcs->opp_program_dpg_dimensions(opp, width, 2*(height) + 1);
2145 }
2146
2147 for (i = 0; i < group_size; i++) {
2148 if (grouped_pipes[i]->stream == NULL)
2149 continue;
2150 grouped_pipes[i]->stream->vblank_synchronized = false;
2151 }
2152
2153 for (i = 1; i < group_size; i++)
2154 grouped_pipes[i]->stream_res.tg->funcs->enable_reset_trigger(
2155 grouped_pipes[i]->stream_res.tg,
2156 grouped_pipes[0]->stream_res.tg->inst);
2157
2158 DC_SYNC_INFO("Waiting for trigger\n");
2159
2160
2161
2162
2163
2164 wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[1]->stream_res.tg);
2165 for (i = 1; i < group_size; i++)
2166 grouped_pipes[i]->stream_res.tg->funcs->disable_reset_trigger(
2167 grouped_pipes[i]->stream_res.tg);
2168
2169 for (i = 1; i < group_size; i++) {
2170 opp = grouped_pipes[i]->stream_res.opp;
2171 tg = grouped_pipes[i]->stream_res.tg;
2172 tg->funcs->get_otg_active_size(tg, &width, &height);
2173 if (opp->funcs->opp_program_dpg_dimensions)
2174 opp->funcs->opp_program_dpg_dimensions(opp, width, height);
2175 }
2176
2177 DC_SYNC_INFO("Sync complete\n");
2178}
2179
2180void dcn10_enable_per_frame_crtc_position_reset(
2181 struct dc *dc,
2182 int group_size,
2183 struct pipe_ctx *grouped_pipes[])
2184{
2185 struct dc_context *dc_ctx = dc->ctx;
2186 int i;
2187
2188 DC_SYNC_INFO("Setting up\n");
2189 for (i = 0; i < group_size; i++)
2190 if (grouped_pipes[i]->stream_res.tg->funcs->enable_crtc_reset)
2191 grouped_pipes[i]->stream_res.tg->funcs->enable_crtc_reset(
2192 grouped_pipes[i]->stream_res.tg,
2193 0,
2194 &grouped_pipes[i]->stream->triggered_crtc_reset);
2195
2196 DC_SYNC_INFO("Waiting for trigger\n");
2197
2198 for (i = 0; i < group_size; i++)
2199 wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[i]->stream_res.tg);
2200
2201 DC_SYNC_INFO("Multi-display sync is complete\n");
2202}
2203
2204static void mmhub_read_vm_system_aperture_settings(struct dcn10_hubp *hubp1,
2205 struct vm_system_aperture_param *apt,
2206 struct dce_hwseq *hws)
2207{
2208 PHYSICAL_ADDRESS_LOC physical_page_number;
2209 uint32_t logical_addr_low;
2210 uint32_t logical_addr_high;
2211
2212 REG_GET(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB,
2213 PHYSICAL_PAGE_NUMBER_MSB, &physical_page_number.high_part);
2214 REG_GET(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB,
2215 PHYSICAL_PAGE_NUMBER_LSB, &physical_page_number.low_part);
2216
2217 REG_GET(MC_VM_SYSTEM_APERTURE_LOW_ADDR,
2218 LOGICAL_ADDR, &logical_addr_low);
2219
2220 REG_GET(MC_VM_SYSTEM_APERTURE_HIGH_ADDR,
2221 LOGICAL_ADDR, &logical_addr_high);
2222
2223 apt->sys_default.quad_part = physical_page_number.quad_part << 12;
2224 apt->sys_low.quad_part = (int64_t)logical_addr_low << 18;
2225 apt->sys_high.quad_part = (int64_t)logical_addr_high << 18;
2226}
2227
2228
2229static void mmhub_read_vm_context0_settings(struct dcn10_hubp *hubp1,
2230 struct vm_context0_param *vm0,
2231 struct dce_hwseq *hws)
2232{
2233 PHYSICAL_ADDRESS_LOC fb_base;
2234 PHYSICAL_ADDRESS_LOC fb_offset;
2235 uint32_t fb_base_value;
2236 uint32_t fb_offset_value;
2237
2238 REG_GET(DCHUBBUB_SDPIF_FB_BASE, SDPIF_FB_BASE, &fb_base_value);
2239 REG_GET(DCHUBBUB_SDPIF_FB_OFFSET, SDPIF_FB_OFFSET, &fb_offset_value);
2240
2241 REG_GET(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32,
2242 PAGE_DIRECTORY_ENTRY_HI32, &vm0->pte_base.high_part);
2243 REG_GET(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32,
2244 PAGE_DIRECTORY_ENTRY_LO32, &vm0->pte_base.low_part);
2245
2246 REG_GET(VM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32,
2247 LOGICAL_PAGE_NUMBER_HI4, &vm0->pte_start.high_part);
2248 REG_GET(VM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32,
2249 LOGICAL_PAGE_NUMBER_LO32, &vm0->pte_start.low_part);
2250
2251 REG_GET(VM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32,
2252 LOGICAL_PAGE_NUMBER_HI4, &vm0->pte_end.high_part);
2253 REG_GET(VM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32,
2254 LOGICAL_PAGE_NUMBER_LO32, &vm0->pte_end.low_part);
2255
2256 REG_GET(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_HI32,
2257 PHYSICAL_PAGE_ADDR_HI4, &vm0->fault_default.high_part);
2258 REG_GET(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32,
2259 PHYSICAL_PAGE_ADDR_LO32, &vm0->fault_default.low_part);
2260
2261
2262
2263
2264
2265
2266
2267 fb_base.quad_part = (uint64_t)fb_base_value << 24;
2268 fb_offset.quad_part = (uint64_t)fb_offset_value << 24;
2269 vm0->pte_base.quad_part += fb_base.quad_part;
2270 vm0->pte_base.quad_part -= fb_offset.quad_part;
2271}
2272
2273
2274void dcn10_program_pte_vm(struct dce_hwseq *hws, struct hubp *hubp)
2275{
2276 struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp);
2277 struct vm_system_aperture_param apt = { {{ 0 } } };
2278 struct vm_context0_param vm0 = { { { 0 } } };
2279
2280 mmhub_read_vm_system_aperture_settings(hubp1, &apt, hws);
2281 mmhub_read_vm_context0_settings(hubp1, &vm0, hws);
2282
2283 hubp->funcs->hubp_set_vm_system_aperture_settings(hubp, &apt);
2284 hubp->funcs->hubp_set_vm_context0_settings(hubp, &vm0);
2285}
2286
2287static void dcn10_enable_plane(
2288 struct dc *dc,
2289 struct pipe_ctx *pipe_ctx,
2290 struct dc_state *context)
2291{
2292 struct dce_hwseq *hws = dc->hwseq;
2293
2294 if (dc->debug.sanity_checks) {
2295 hws->funcs.verify_allow_pstate_change_high(dc);
2296 }
2297
2298 undo_DEGVIDCN10_253_wa(dc);
2299
2300 power_on_plane(dc->hwseq,
2301 pipe_ctx->plane_res.hubp->inst);
2302
2303
2304 pipe_ctx->plane_res.hubp->funcs->hubp_clk_cntl(pipe_ctx->plane_res.hubp, true);
2305
2306
2307 pipe_ctx->stream_res.opp->funcs->opp_pipe_clock_control(
2308 pipe_ctx->stream_res.opp,
2309 true);
2310
2311 if (dc->config.gpu_vm_support)
2312 dcn10_program_pte_vm(hws, pipe_ctx->plane_res.hubp);
2313
2314 if (dc->debug.sanity_checks) {
2315 hws->funcs.verify_allow_pstate_change_high(dc);
2316 }
2317
2318 if (!pipe_ctx->top_pipe
2319 && pipe_ctx->plane_state
2320 && pipe_ctx->plane_state->flip_int_enabled
2321 && pipe_ctx->plane_res.hubp->funcs->hubp_set_flip_int)
2322 pipe_ctx->plane_res.hubp->funcs->hubp_set_flip_int(pipe_ctx->plane_res.hubp);
2323
2324}
2325
2326void dcn10_program_gamut_remap(struct pipe_ctx *pipe_ctx)
2327{
2328 int i = 0;
2329 struct dpp_grph_csc_adjustment adjust;
2330 memset(&adjust, 0, sizeof(adjust));
2331 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS;
2332
2333
2334 if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) {
2335 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW;
2336 for (i = 0; i < CSC_TEMPERATURE_MATRIX_SIZE; i++)
2337 adjust.temperature_matrix[i] =
2338 pipe_ctx->stream->gamut_remap_matrix.matrix[i];
2339 } else if (pipe_ctx->plane_state &&
2340 pipe_ctx->plane_state->gamut_remap_matrix.enable_remap == true) {
2341 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW;
2342 for (i = 0; i < CSC_TEMPERATURE_MATRIX_SIZE; i++)
2343 adjust.temperature_matrix[i] =
2344 pipe_ctx->plane_state->gamut_remap_matrix.matrix[i];
2345 }
2346
2347 pipe_ctx->plane_res.dpp->funcs->dpp_set_gamut_remap(pipe_ctx->plane_res.dpp, &adjust);
2348}
2349
2350
2351static bool dcn10_is_rear_mpo_fix_required(struct pipe_ctx *pipe_ctx, enum dc_color_space colorspace)
2352{
2353 if (pipe_ctx->plane_state && pipe_ctx->plane_state->layer_index > 0 && is_rgb_cspace(colorspace)) {
2354 if (pipe_ctx->top_pipe) {
2355 struct pipe_ctx *top = pipe_ctx->top_pipe;
2356
2357 while (top->top_pipe)
2358 top = top->top_pipe;
2359 if (top->plane_state && top->plane_state->layer_index == 0)
2360 return true;
2361 }
2362 }
2363 return false;
2364}
2365
2366static void dcn10_set_csc_adjustment_rgb_mpo_fix(struct pipe_ctx *pipe_ctx, uint16_t *matrix)
2367{
2368
2369 uint16_t rgb_bias = matrix[3];
2370
2371 matrix[3] = 0;
2372 matrix[7] = 0;
2373 matrix[11] = 0;
2374 pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_adjustment(pipe_ctx->plane_res.dpp, matrix);
2375 matrix[3] = rgb_bias;
2376 matrix[7] = rgb_bias;
2377 matrix[11] = rgb_bias;
2378}
2379
2380void dcn10_program_output_csc(struct dc *dc,
2381 struct pipe_ctx *pipe_ctx,
2382 enum dc_color_space colorspace,
2383 uint16_t *matrix,
2384 int opp_id)
2385{
2386 if (pipe_ctx->stream->csc_color_matrix.enable_adjustment == true) {
2387 if (pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_adjustment != NULL) {
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397 int16_t rgb_bias = matrix[3];
2398
2399
2400 if (rgb_bias > 0 && dcn10_is_rear_mpo_fix_required(pipe_ctx, colorspace)) {
2401 dcn10_set_csc_adjustment_rgb_mpo_fix(pipe_ctx, matrix);
2402 } else {
2403 pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_adjustment(pipe_ctx->plane_res.dpp, matrix);
2404 }
2405 }
2406 } else {
2407 if (pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_default != NULL)
2408 pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_default(pipe_ctx->plane_res.dpp, colorspace);
2409 }
2410}
2411
2412static void dcn10_update_dpp(struct dpp *dpp, struct dc_plane_state *plane_state)
2413{
2414 struct dc_bias_and_scale bns_params = {0};
2415
2416
2417 dpp->funcs->dpp_setup(dpp,
2418 plane_state->format,
2419 EXPANSION_MODE_ZERO,
2420 plane_state->input_csc_color_matrix,
2421 plane_state->color_space,
2422 NULL);
2423
2424
2425 build_prescale_params(&bns_params, plane_state);
2426 if (dpp->funcs->dpp_program_bias_and_scale)
2427 dpp->funcs->dpp_program_bias_and_scale(dpp, &bns_params);
2428}
2429
2430void dcn10_update_visual_confirm_color(struct dc *dc, struct pipe_ctx *pipe_ctx, struct tg_color *color, int mpcc_id)
2431{
2432 struct mpc *mpc = dc->res_pool->mpc;
2433
2434 if (dc->debug.visual_confirm == VISUAL_CONFIRM_HDR)
2435 get_hdr_visual_confirm_color(pipe_ctx, color);
2436 else if (dc->debug.visual_confirm == VISUAL_CONFIRM_SURFACE)
2437 get_surface_visual_confirm_color(pipe_ctx, color);
2438 else if (dc->debug.visual_confirm == VISUAL_CONFIRM_SWIZZLE)
2439 get_surface_tile_visual_confirm_color(pipe_ctx, color);
2440 else
2441 color_space_to_black_color(
2442 dc, pipe_ctx->stream->output_color_space, color);
2443
2444 if (mpc->funcs->set_bg_color)
2445 mpc->funcs->set_bg_color(mpc, color, mpcc_id);
2446}
2447
2448void dcn10_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx)
2449{
2450 struct hubp *hubp = pipe_ctx->plane_res.hubp;
2451 struct mpcc_blnd_cfg blnd_cfg = {{0}};
2452 bool per_pixel_alpha = pipe_ctx->plane_state->per_pixel_alpha && pipe_ctx->bottom_pipe;
2453 int mpcc_id;
2454 struct mpcc *new_mpcc;
2455 struct mpc *mpc = dc->res_pool->mpc;
2456 struct mpc_tree *mpc_tree_params = &(pipe_ctx->stream_res.opp->mpc_tree_params);
2457
2458 if (per_pixel_alpha)
2459 blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA;
2460 else
2461 blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_GLOBAL_ALPHA;
2462
2463 blnd_cfg.overlap_only = false;
2464 blnd_cfg.global_gain = 0xff;
2465
2466 if (pipe_ctx->plane_state->global_alpha)
2467 blnd_cfg.global_alpha = pipe_ctx->plane_state->global_alpha_value;
2468 else
2469 blnd_cfg.global_alpha = 0xff;
2470
2471
2472
2473
2474 blnd_cfg.pre_multiplied_alpha = is_rgb_cspace(
2475 pipe_ctx->stream->output_color_space)
2476 && per_pixel_alpha;
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487 mpcc_id = hubp->inst;
2488
2489
2490 if (!pipe_ctx->plane_state->update_flags.bits.full_update) {
2491 mpc->funcs->update_blending(mpc, &blnd_cfg, mpcc_id);
2492 dc->hwss.update_visual_confirm_color(dc, pipe_ctx, &blnd_cfg.black_color, mpcc_id);
2493 return;
2494 }
2495
2496
2497 new_mpcc = mpc->funcs->get_mpcc_for_dpp(mpc_tree_params, mpcc_id);
2498
2499 if (new_mpcc != NULL)
2500 mpc->funcs->remove_mpcc(mpc, mpc_tree_params, new_mpcc);
2501 else
2502 if (dc->debug.sanity_checks)
2503 mpc->funcs->assert_mpcc_idle_before_connect(
2504 dc->res_pool->mpc, mpcc_id);
2505
2506
2507 new_mpcc = mpc->funcs->insert_plane(dc->res_pool->mpc,
2508 mpc_tree_params,
2509 &blnd_cfg,
2510 NULL,
2511 NULL,
2512 hubp->inst,
2513 mpcc_id);
2514 dc->hwss.update_visual_confirm_color(dc, pipe_ctx, &blnd_cfg.black_color, mpcc_id);
2515
2516 ASSERT(new_mpcc != NULL);
2517
2518 hubp->opp_id = pipe_ctx->stream_res.opp->inst;
2519 hubp->mpcc_id = mpcc_id;
2520}
2521
2522static void update_scaler(struct pipe_ctx *pipe_ctx)
2523{
2524 bool per_pixel_alpha =
2525 pipe_ctx->plane_state->per_pixel_alpha && pipe_ctx->bottom_pipe;
2526
2527 pipe_ctx->plane_res.scl_data.lb_params.alpha_en = per_pixel_alpha;
2528 pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_36BPP;
2529
2530 pipe_ctx->plane_res.dpp->funcs->dpp_set_scaler(
2531 pipe_ctx->plane_res.dpp, &pipe_ctx->plane_res.scl_data);
2532}
2533
2534static void dcn10_update_dchubp_dpp(
2535 struct dc *dc,
2536 struct pipe_ctx *pipe_ctx,
2537 struct dc_state *context)
2538{
2539 struct dce_hwseq *hws = dc->hwseq;
2540 struct hubp *hubp = pipe_ctx->plane_res.hubp;
2541 struct dpp *dpp = pipe_ctx->plane_res.dpp;
2542 struct dc_plane_state *plane_state = pipe_ctx->plane_state;
2543 struct plane_size size = plane_state->plane_size;
2544 unsigned int compat_level = 0;
2545 bool should_divided_by_2 = false;
2546
2547
2548
2549
2550
2551 if (plane_state->update_flags.bits.full_update) {
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578 if (context->bw_ctx.bw.dcn.clk.dispclk_khz <
2579 dc->clk_mgr->clks.dispclk_khz)
2580 should_divided_by_2 = false;
2581 else
2582 should_divided_by_2 =
2583 context->bw_ctx.bw.dcn.clk.dppclk_khz <=
2584 dc->clk_mgr->clks.dispclk_khz / 2;
2585
2586 dpp->funcs->dpp_dppclk_control(
2587 dpp,
2588 should_divided_by_2,
2589 true);
2590
2591 if (dc->res_pool->dccg)
2592 dc->res_pool->dccg->funcs->update_dpp_dto(
2593 dc->res_pool->dccg,
2594 dpp->inst,
2595 pipe_ctx->plane_res.bw.dppclk_khz);
2596 else
2597 dc->clk_mgr->clks.dppclk_khz = should_divided_by_2 ?
2598 dc->clk_mgr->clks.dispclk_khz / 2 :
2599 dc->clk_mgr->clks.dispclk_khz;
2600 }
2601
2602
2603
2604
2605
2606 if (plane_state->update_flags.bits.full_update) {
2607 hubp->funcs->hubp_vtg_sel(hubp, pipe_ctx->stream_res.tg->inst);
2608
2609 hubp->funcs->hubp_setup(
2610 hubp,
2611 &pipe_ctx->dlg_regs,
2612 &pipe_ctx->ttu_regs,
2613 &pipe_ctx->rq_regs,
2614 &pipe_ctx->pipe_dlg_param);
2615 hubp->funcs->hubp_setup_interdependent(
2616 hubp,
2617 &pipe_ctx->dlg_regs,
2618 &pipe_ctx->ttu_regs);
2619 }
2620
2621 size.surface_size = pipe_ctx->plane_res.scl_data.viewport;
2622
2623 if (plane_state->update_flags.bits.full_update ||
2624 plane_state->update_flags.bits.bpp_change)
2625 dcn10_update_dpp(dpp, plane_state);
2626
2627 if (plane_state->update_flags.bits.full_update ||
2628 plane_state->update_flags.bits.per_pixel_alpha_change ||
2629 plane_state->update_flags.bits.global_alpha_change)
2630 hws->funcs.update_mpcc(dc, pipe_ctx);
2631
2632 if (plane_state->update_flags.bits.full_update ||
2633 plane_state->update_flags.bits.per_pixel_alpha_change ||
2634 plane_state->update_flags.bits.global_alpha_change ||
2635 plane_state->update_flags.bits.scaling_change ||
2636 plane_state->update_flags.bits.position_change) {
2637 update_scaler(pipe_ctx);
2638 }
2639
2640 if (plane_state->update_flags.bits.full_update ||
2641 plane_state->update_flags.bits.scaling_change ||
2642 plane_state->update_flags.bits.position_change) {
2643 hubp->funcs->mem_program_viewport(
2644 hubp,
2645 &pipe_ctx->plane_res.scl_data.viewport,
2646 &pipe_ctx->plane_res.scl_data.viewport_c);
2647 }
2648
2649 if (pipe_ctx->stream->cursor_attributes.address.quad_part != 0) {
2650 dc->hwss.set_cursor_position(pipe_ctx);
2651 dc->hwss.set_cursor_attribute(pipe_ctx);
2652
2653 if (dc->hwss.set_cursor_sdr_white_level)
2654 dc->hwss.set_cursor_sdr_white_level(pipe_ctx);
2655 }
2656
2657 if (plane_state->update_flags.bits.full_update) {
2658
2659 dc->hwss.program_gamut_remap(pipe_ctx);
2660
2661 dc->hwss.program_output_csc(dc,
2662 pipe_ctx,
2663 pipe_ctx->stream->output_color_space,
2664 pipe_ctx->stream->csc_color_matrix.matrix,
2665 pipe_ctx->stream_res.opp->inst);
2666 }
2667
2668 if (plane_state->update_flags.bits.full_update ||
2669 plane_state->update_flags.bits.pixel_format_change ||
2670 plane_state->update_flags.bits.horizontal_mirror_change ||
2671 plane_state->update_flags.bits.rotation_change ||
2672 plane_state->update_flags.bits.swizzle_change ||
2673 plane_state->update_flags.bits.dcc_change ||
2674 plane_state->update_flags.bits.bpp_change ||
2675 plane_state->update_flags.bits.scaling_change ||
2676 plane_state->update_flags.bits.plane_size_change) {
2677 hubp->funcs->hubp_program_surface_config(
2678 hubp,
2679 plane_state->format,
2680 &plane_state->tiling_info,
2681 &size,
2682 plane_state->rotation,
2683 &plane_state->dcc,
2684 plane_state->horizontal_mirror,
2685 compat_level);
2686 }
2687
2688 hubp->power_gated = false;
2689
2690 hws->funcs.update_plane_addr(dc, pipe_ctx);
2691
2692 if (is_pipe_tree_visible(pipe_ctx))
2693 hubp->funcs->set_blank(hubp, false);
2694}
2695
2696void dcn10_blank_pixel_data(
2697 struct dc *dc,
2698 struct pipe_ctx *pipe_ctx,
2699 bool blank)
2700{
2701 enum dc_color_space color_space;
2702 struct tg_color black_color = {0};
2703 struct stream_resource *stream_res = &pipe_ctx->stream_res;
2704 struct dc_stream_state *stream = pipe_ctx->stream;
2705
2706
2707 color_space = stream->output_color_space;
2708 color_space_to_black_color(dc, color_space, &black_color);
2709
2710
2711
2712
2713
2714
2715 if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420)
2716 black_color.color_r_cr = black_color.color_g_y;
2717
2718
2719 if (stream_res->tg->funcs->set_blank_color)
2720 stream_res->tg->funcs->set_blank_color(
2721 stream_res->tg,
2722 &black_color);
2723
2724 if (!blank) {
2725 if (stream_res->tg->funcs->set_blank)
2726 stream_res->tg->funcs->set_blank(stream_res->tg, blank);
2727 if (stream_res->abm) {
2728 dc->hwss.set_pipe(pipe_ctx);
2729 stream_res->abm->funcs->set_abm_level(stream_res->abm, stream->abm_level);
2730 }
2731 } else if (blank) {
2732 dc->hwss.set_abm_immediate_disable(pipe_ctx);
2733 if (stream_res->tg->funcs->set_blank) {
2734 stream_res->tg->funcs->wait_for_state(stream_res->tg, CRTC_STATE_VBLANK);
2735 stream_res->tg->funcs->set_blank(stream_res->tg, blank);
2736 }
2737 }
2738}
2739
2740void dcn10_set_hdr_multiplier(struct pipe_ctx *pipe_ctx)
2741{
2742 struct fixed31_32 multiplier = pipe_ctx->plane_state->hdr_mult;
2743 uint32_t hw_mult = 0x1f000;
2744 struct custom_float_format fmt;
2745
2746 fmt.exponenta_bits = 6;
2747 fmt.mantissa_bits = 12;
2748 fmt.sign = true;
2749
2750
2751 if (!dc_fixpt_eq(multiplier, dc_fixpt_from_int(0)))
2752 convert_to_custom_float_format(multiplier, &fmt, &hw_mult);
2753
2754 pipe_ctx->plane_res.dpp->funcs->dpp_set_hdr_multiplier(
2755 pipe_ctx->plane_res.dpp, hw_mult);
2756}
2757
2758void dcn10_program_pipe(
2759 struct dc *dc,
2760 struct pipe_ctx *pipe_ctx,
2761 struct dc_state *context)
2762{
2763 struct dce_hwseq *hws = dc->hwseq;
2764
2765 if (pipe_ctx->top_pipe == NULL) {
2766 bool blank = !is_pipe_tree_visible(pipe_ctx);
2767
2768 pipe_ctx->stream_res.tg->funcs->program_global_sync(
2769 pipe_ctx->stream_res.tg,
2770 pipe_ctx->pipe_dlg_param.vready_offset,
2771 pipe_ctx->pipe_dlg_param.vstartup_start,
2772 pipe_ctx->pipe_dlg_param.vupdate_offset,
2773 pipe_ctx->pipe_dlg_param.vupdate_width);
2774
2775 pipe_ctx->stream_res.tg->funcs->set_vtg_params(
2776 pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing, true);
2777
2778 if (hws->funcs.setup_vupdate_interrupt)
2779 hws->funcs.setup_vupdate_interrupt(dc, pipe_ctx);
2780
2781 hws->funcs.blank_pixel_data(dc, pipe_ctx, blank);
2782 }
2783
2784 if (pipe_ctx->plane_state->update_flags.bits.full_update)
2785 dcn10_enable_plane(dc, pipe_ctx, context);
2786
2787 dcn10_update_dchubp_dpp(dc, pipe_ctx, context);
2788
2789 hws->funcs.set_hdr_multiplier(pipe_ctx);
2790
2791 if (pipe_ctx->plane_state->update_flags.bits.full_update ||
2792 pipe_ctx->plane_state->update_flags.bits.in_transfer_func_change ||
2793 pipe_ctx->plane_state->update_flags.bits.gamma_change)
2794 hws->funcs.set_input_transfer_func(dc, pipe_ctx, pipe_ctx->plane_state);
2795
2796
2797
2798
2799
2800
2801
2802 if (pipe_ctx->plane_state->update_flags.bits.full_update)
2803 hws->funcs.set_output_transfer_func(dc, pipe_ctx, pipe_ctx->stream);
2804}
2805
2806void dcn10_wait_for_pending_cleared(struct dc *dc,
2807 struct dc_state *context)
2808{
2809 struct pipe_ctx *pipe_ctx;
2810 struct timing_generator *tg;
2811 int i;
2812
2813 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2814 pipe_ctx = &context->res_ctx.pipe_ctx[i];
2815 tg = pipe_ctx->stream_res.tg;
2816
2817
2818
2819
2820
2821 if (pipe_ctx->top_pipe ||
2822 !pipe_ctx->stream || !pipe_ctx->plane_state ||
2823 !tg->funcs->is_tg_enabled(tg))
2824 continue;
2825
2826
2827
2828
2829
2830
2831
2832
2833 pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VBLANK);
2834 pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VACTIVE);
2835 }
2836}
2837
2838void dcn10_post_unlock_program_front_end(
2839 struct dc *dc,
2840 struct dc_state *context)
2841{
2842 int i;
2843
2844 DC_LOGGER_INIT(dc->ctx->logger);
2845
2846 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2847 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2848
2849 if (!pipe_ctx->top_pipe &&
2850 !pipe_ctx->prev_odm_pipe &&
2851 pipe_ctx->stream) {
2852 struct timing_generator *tg = pipe_ctx->stream_res.tg;
2853
2854 if (context->stream_status[i].plane_count == 0)
2855 false_optc_underflow_wa(dc, pipe_ctx->stream, tg);
2856 }
2857 }
2858
2859 for (i = 0; i < dc->res_pool->pipe_count; i++)
2860 if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable)
2861 dc->hwss.disable_plane(dc, &dc->current_state->res_ctx.pipe_ctx[i]);
2862
2863 for (i = 0; i < dc->res_pool->pipe_count; i++)
2864 if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable) {
2865 dc->hwss.optimize_bandwidth(dc, context);
2866 break;
2867 }
2868
2869 if (dc->hwseq->wa.DEGVIDCN10_254)
2870 hubbub1_wm_change_req_wa(dc->res_pool->hubbub);
2871}
2872
2873static void dcn10_stereo_hw_frame_pack_wa(struct dc *dc, struct dc_state *context)
2874{
2875 uint8_t i;
2876
2877 for (i = 0; i < context->stream_count; i++) {
2878 if (context->streams[i]->timing.timing_3d_format
2879 == TIMING_3D_FORMAT_HW_FRAME_PACKING) {
2880
2881
2882
2883 hubbub1_allow_self_refresh_control(dc->res_pool->hubbub, false);
2884 break;
2885 }
2886 }
2887}
2888
2889void dcn10_prepare_bandwidth(
2890 struct dc *dc,
2891 struct dc_state *context)
2892{
2893 struct dce_hwseq *hws = dc->hwseq;
2894 struct hubbub *hubbub = dc->res_pool->hubbub;
2895
2896 if (dc->debug.sanity_checks)
2897 hws->funcs.verify_allow_pstate_change_high(dc);
2898
2899 if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
2900 if (context->stream_count == 0)
2901 context->bw_ctx.bw.dcn.clk.phyclk_khz = 0;
2902
2903 dc->clk_mgr->funcs->update_clocks(
2904 dc->clk_mgr,
2905 context,
2906 false);
2907 }
2908
2909 dc->wm_optimized_required = hubbub->funcs->program_watermarks(hubbub,
2910 &context->bw_ctx.bw.dcn.watermarks,
2911 dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000,
2912 true);
2913 dcn10_stereo_hw_frame_pack_wa(dc, context);
2914
2915 if (dc->debug.pplib_wm_report_mode == WM_REPORT_OVERRIDE)
2916 dcn_bw_notify_pplib_of_wm_ranges(dc);
2917
2918 if (dc->debug.sanity_checks)
2919 hws->funcs.verify_allow_pstate_change_high(dc);
2920}
2921
2922void dcn10_optimize_bandwidth(
2923 struct dc *dc,
2924 struct dc_state *context)
2925{
2926 struct dce_hwseq *hws = dc->hwseq;
2927 struct hubbub *hubbub = dc->res_pool->hubbub;
2928
2929 if (dc->debug.sanity_checks)
2930 hws->funcs.verify_allow_pstate_change_high(dc);
2931
2932 if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
2933 if (context->stream_count == 0)
2934 context->bw_ctx.bw.dcn.clk.phyclk_khz = 0;
2935
2936 dc->clk_mgr->funcs->update_clocks(
2937 dc->clk_mgr,
2938 context,
2939 true);
2940 }
2941
2942 hubbub->funcs->program_watermarks(hubbub,
2943 &context->bw_ctx.bw.dcn.watermarks,
2944 dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000,
2945 true);
2946
2947 dcn10_stereo_hw_frame_pack_wa(dc, context);
2948
2949 if (dc->debug.pplib_wm_report_mode == WM_REPORT_OVERRIDE)
2950 dcn_bw_notify_pplib_of_wm_ranges(dc);
2951
2952 if (dc->debug.sanity_checks)
2953 hws->funcs.verify_allow_pstate_change_high(dc);
2954}
2955
2956void dcn10_set_drr(struct pipe_ctx **pipe_ctx,
2957 int num_pipes, struct dc_crtc_timing_adjust adjust)
2958{
2959 int i = 0;
2960 struct drr_params params = {0};
2961
2962 unsigned int event_triggers = 0x800;
2963
2964 unsigned int num_frames = 2;
2965
2966 params.vertical_total_max = adjust.v_total_max;
2967 params.vertical_total_min = adjust.v_total_min;
2968 params.vertical_total_mid = adjust.v_total_mid;
2969 params.vertical_total_mid_frame_num = adjust.v_total_mid_frame_num;
2970
2971
2972
2973
2974 for (i = 0; i < num_pipes; i++) {
2975 pipe_ctx[i]->stream_res.tg->funcs->set_drr(
2976 pipe_ctx[i]->stream_res.tg, ¶ms);
2977 if (adjust.v_total_max != 0 && adjust.v_total_min != 0)
2978 pipe_ctx[i]->stream_res.tg->funcs->set_static_screen_control(
2979 pipe_ctx[i]->stream_res.tg,
2980 event_triggers, num_frames);
2981 }
2982}
2983
2984void dcn10_get_position(struct pipe_ctx **pipe_ctx,
2985 int num_pipes,
2986 struct crtc_position *position)
2987{
2988 int i = 0;
2989
2990
2991
2992 for (i = 0; i < num_pipes; i++)
2993 pipe_ctx[i]->stream_res.tg->funcs->get_position(pipe_ctx[i]->stream_res.tg, position);
2994}
2995
2996void dcn10_set_static_screen_control(struct pipe_ctx **pipe_ctx,
2997 int num_pipes, const struct dc_static_screen_params *params)
2998{
2999 unsigned int i;
3000 unsigned int triggers = 0;
3001
3002 if (params->triggers.surface_update)
3003 triggers |= 0x80;
3004 if (params->triggers.cursor_update)
3005 triggers |= 0x2;
3006 if (params->triggers.force_trigger)
3007 triggers |= 0x1;
3008
3009 for (i = 0; i < num_pipes; i++)
3010 pipe_ctx[i]->stream_res.tg->funcs->
3011 set_static_screen_control(pipe_ctx[i]->stream_res.tg,
3012 triggers, params->num_frames);
3013}
3014
3015static void dcn10_config_stereo_parameters(
3016 struct dc_stream_state *stream, struct crtc_stereo_flags *flags)
3017{
3018 enum view_3d_format view_format = stream->view_format;
3019 enum dc_timing_3d_format timing_3d_format =\
3020 stream->timing.timing_3d_format;
3021 bool non_stereo_timing = false;
3022
3023 if (timing_3d_format == TIMING_3D_FORMAT_NONE ||
3024 timing_3d_format == TIMING_3D_FORMAT_SIDE_BY_SIDE ||
3025 timing_3d_format == TIMING_3D_FORMAT_TOP_AND_BOTTOM)
3026 non_stereo_timing = true;
3027
3028 if (non_stereo_timing == false &&
3029 view_format == VIEW_3D_FORMAT_FRAME_SEQUENTIAL) {
3030
3031 flags->PROGRAM_STEREO = 1;
3032 flags->PROGRAM_POLARITY = 1;
3033 if (timing_3d_format == TIMING_3D_FORMAT_INBAND_FA ||
3034 timing_3d_format == TIMING_3D_FORMAT_DP_HDMI_INBAND_FA ||
3035 timing_3d_format == TIMING_3D_FORMAT_SIDEBAND_FA) {
3036 enum display_dongle_type dongle = \
3037 stream->link->ddc->dongle_type;
3038 if (dongle == DISPLAY_DONGLE_DP_VGA_CONVERTER ||
3039 dongle == DISPLAY_DONGLE_DP_DVI_CONVERTER ||
3040 dongle == DISPLAY_DONGLE_DP_HDMI_CONVERTER)
3041 flags->DISABLE_STEREO_DP_SYNC = 1;
3042 }
3043 flags->RIGHT_EYE_POLARITY =\
3044 stream->timing.flags.RIGHT_EYE_3D_POLARITY;
3045 if (timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING)
3046 flags->FRAME_PACKED = 1;
3047 }
3048
3049 return;
3050}
3051
3052void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, struct dc *dc)
3053{
3054 struct crtc_stereo_flags flags = { 0 };
3055 struct dc_stream_state *stream = pipe_ctx->stream;
3056
3057 dcn10_config_stereo_parameters(stream, &flags);
3058
3059 if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_SIDEBAND_FA) {
3060 if (!dc_set_generic_gpio_for_stereo(true, dc->ctx->gpio_service))
3061 dc_set_generic_gpio_for_stereo(false, dc->ctx->gpio_service);
3062 } else {
3063 dc_set_generic_gpio_for_stereo(false, dc->ctx->gpio_service);
3064 }
3065
3066 pipe_ctx->stream_res.opp->funcs->opp_program_stereo(
3067 pipe_ctx->stream_res.opp,
3068 flags.PROGRAM_STEREO == 1,
3069 &stream->timing);
3070
3071 pipe_ctx->stream_res.tg->funcs->program_stereo(
3072 pipe_ctx->stream_res.tg,
3073 &stream->timing,
3074 &flags);
3075
3076 return;
3077}
3078
3079static struct hubp *get_hubp_by_inst(struct resource_pool *res_pool, int mpcc_inst)
3080{
3081 int i;
3082
3083 for (i = 0; i < res_pool->pipe_count; i++) {
3084 if (res_pool->hubps[i]->inst == mpcc_inst)
3085 return res_pool->hubps[i];
3086 }
3087 ASSERT(false);
3088 return NULL;
3089}
3090
3091void dcn10_wait_for_mpcc_disconnect(
3092 struct dc *dc,
3093 struct resource_pool *res_pool,
3094 struct pipe_ctx *pipe_ctx)
3095{
3096 struct dce_hwseq *hws = dc->hwseq;
3097 int mpcc_inst;
3098
3099 if (dc->debug.sanity_checks) {
3100 hws->funcs.verify_allow_pstate_change_high(dc);
3101 }
3102
3103 if (!pipe_ctx->stream_res.opp)
3104 return;
3105
3106 for (mpcc_inst = 0; mpcc_inst < MAX_PIPES; mpcc_inst++) {
3107 if (pipe_ctx->stream_res.opp->mpcc_disconnect_pending[mpcc_inst]) {
3108 struct hubp *hubp = get_hubp_by_inst(res_pool, mpcc_inst);
3109
3110 res_pool->mpc->funcs->wait_for_idle(res_pool->mpc, mpcc_inst);
3111 pipe_ctx->stream_res.opp->mpcc_disconnect_pending[mpcc_inst] = false;
3112 hubp->funcs->set_blank(hubp, true);
3113 }
3114 }
3115
3116 if (dc->debug.sanity_checks) {
3117 hws->funcs.verify_allow_pstate_change_high(dc);
3118 }
3119
3120}
3121
3122bool dcn10_dummy_display_power_gating(
3123 struct dc *dc,
3124 uint8_t controller_id,
3125 struct dc_bios *dcb,
3126 enum pipe_gating_control power_gating)
3127{
3128 return true;
3129}
3130
3131void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx)
3132{
3133 struct dc_plane_state *plane_state = pipe_ctx->plane_state;
3134 struct timing_generator *tg = pipe_ctx->stream_res.tg;
3135 bool flip_pending;
3136 struct dc *dc = plane_state->ctx->dc;
3137
3138 if (plane_state == NULL)
3139 return;
3140
3141 flip_pending = pipe_ctx->plane_res.hubp->funcs->hubp_is_flip_pending(
3142 pipe_ctx->plane_res.hubp);
3143
3144 plane_state->status.is_flip_pending = plane_state->status.is_flip_pending || flip_pending;
3145
3146 if (!flip_pending)
3147 plane_state->status.current_address = plane_state->status.requested_address;
3148
3149 if (plane_state->status.current_address.type == PLN_ADDR_TYPE_GRPH_STEREO &&
3150 tg->funcs->is_stereo_left_eye) {
3151 plane_state->status.is_right_eye =
3152 !tg->funcs->is_stereo_left_eye(pipe_ctx->stream_res.tg);
3153 }
3154
3155 if (dc->hwseq->wa_state.disallow_self_refresh_during_multi_plane_transition_applied) {
3156 struct dce_hwseq *hwseq = dc->hwseq;
3157 struct timing_generator *tg = dc->res_pool->timing_generators[0];
3158 unsigned int cur_frame = tg->funcs->get_frame_count(tg);
3159
3160 if (cur_frame != hwseq->wa_state.disallow_self_refresh_during_multi_plane_transition_applied_on_frame) {
3161 struct hubbub *hubbub = dc->res_pool->hubbub;
3162
3163 hubbub->funcs->allow_self_refresh_control(hubbub, !dc->debug.disable_stutter);
3164 hwseq->wa_state.disallow_self_refresh_during_multi_plane_transition_applied = false;
3165 }
3166 }
3167}
3168
3169void dcn10_update_dchub(struct dce_hwseq *hws, struct dchub_init_data *dh_data)
3170{
3171 struct hubbub *hubbub = hws->ctx->dc->res_pool->hubbub;
3172
3173
3174 hubbub->funcs->update_dchub(hubbub, dh_data);
3175}
3176
3177static bool dcn10_can_pipe_disable_cursor(struct pipe_ctx *pipe_ctx)
3178{
3179 struct pipe_ctx *test_pipe;
3180 const struct scaler_data *scl_data = &pipe_ctx->plane_res.scl_data;
3181 const struct rect *r1 = &scl_data->recout, *r2;
3182 int r1_r = r1->x + r1->width, r1_b = r1->y + r1->height, r2_r, r2_b;
3183 int cur_layer = pipe_ctx->plane_state->layer_index;
3184 bool upper_pipe_exists = false;
3185 struct fixed31_32 one = dc_fixpt_from_int(1);
3186
3187
3188
3189
3190
3191
3192 for (test_pipe = pipe_ctx->top_pipe; test_pipe;
3193 test_pipe = test_pipe->top_pipe) {
3194 if (!test_pipe->plane_state->visible)
3195 continue;
3196
3197 r2 = &test_pipe->plane_res.scl_data.recout;
3198 r2_r = r2->x + r2->width;
3199 r2_b = r2->y + r2->height;
3200
3201 if (r1->x >= r2->x && r1->y >= r2->y && r1_r <= r2_r && r1_b <= r2_b)
3202 return true;
3203
3204 if (test_pipe->plane_state->layer_index < cur_layer)
3205 upper_pipe_exists = true;
3206 }
3207
3208
3209 if (upper_pipe_exists &&
3210 (scl_data->ratios.horz.value != one.value ||
3211 scl_data->ratios.vert.value != one.value))
3212 return true;
3213
3214 return false;
3215}
3216
3217void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx)
3218{
3219 struct dc_cursor_position pos_cpy = pipe_ctx->stream->cursor_position;
3220 struct hubp *hubp = pipe_ctx->plane_res.hubp;
3221 struct dpp *dpp = pipe_ctx->plane_res.dpp;
3222 struct dc_cursor_mi_param param = {
3223 .pixel_clk_khz = pipe_ctx->stream->timing.pix_clk_100hz / 10,
3224 .ref_clk_khz = pipe_ctx->stream->ctx->dc->res_pool->ref_clocks.dchub_ref_clock_inKhz,
3225 .viewport = pipe_ctx->plane_res.scl_data.viewport,
3226 .h_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.horz,
3227 .v_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.vert,
3228 .rotation = pipe_ctx->plane_state->rotation,
3229 .mirror = pipe_ctx->plane_state->horizontal_mirror
3230 };
3231 bool pipe_split_on = (pipe_ctx->top_pipe != NULL) ||
3232 (pipe_ctx->bottom_pipe != NULL);
3233 bool odm_combine_on = (pipe_ctx->next_odm_pipe != NULL) ||
3234 (pipe_ctx->prev_odm_pipe != NULL);
3235
3236 int x_plane = pipe_ctx->plane_state->dst_rect.x;
3237 int y_plane = pipe_ctx->plane_state->dst_rect.y;
3238 int x_pos = pos_cpy.x;
3239 int y_pos = pos_cpy.y;
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258 if (param.rotation == ROTATION_ANGLE_90 || param.rotation == ROTATION_ANGLE_270) {
3259 x_pos = (x_pos - x_plane) * pipe_ctx->plane_state->src_rect.height /
3260 pipe_ctx->plane_state->dst_rect.width;
3261 y_pos = (y_pos - y_plane) * pipe_ctx->plane_state->src_rect.width /
3262 pipe_ctx->plane_state->dst_rect.height;
3263 } else {
3264 x_pos = (x_pos - x_plane) * pipe_ctx->plane_state->src_rect.width /
3265 pipe_ctx->plane_state->dst_rect.width;
3266 y_pos = (y_pos - y_plane) * pipe_ctx->plane_state->src_rect.height /
3267 pipe_ctx->plane_state->dst_rect.height;
3268 }
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282 if (pos_cpy.translate_by_source) {
3283 x_pos += pipe_ctx->plane_state->src_rect.x;
3284 y_pos += pipe_ctx->plane_state->src_rect.y;
3285 }
3286
3287
3288
3289
3290
3291
3292 if (x_pos < 0) {
3293 pos_cpy.x_hotspot -= x_pos;
3294 x_pos = 0;
3295 }
3296
3297 if (y_pos < 0) {
3298 pos_cpy.y_hotspot -= y_pos;
3299 y_pos = 0;
3300 }
3301
3302 pos_cpy.x = (uint32_t)x_pos;
3303 pos_cpy.y = (uint32_t)y_pos;
3304
3305 if (pipe_ctx->plane_state->address.type
3306 == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE)
3307 pos_cpy.enable = false;
3308
3309 if (pos_cpy.enable && dcn10_can_pipe_disable_cursor(pipe_ctx))
3310 pos_cpy.enable = false;
3311
3312
3313 if (param.rotation == ROTATION_ANGLE_90) {
3314 uint32_t temp_x = pos_cpy.x;
3315
3316 pos_cpy.x = pipe_ctx->plane_res.scl_data.viewport.width -
3317 (pos_cpy.y - pipe_ctx->plane_res.scl_data.viewport.x) + pipe_ctx->plane_res.scl_data.viewport.x;
3318 pos_cpy.y = temp_x;
3319 }
3320
3321 else if (param.rotation == ROTATION_ANGLE_270) {
3322 uint32_t temp_y = pos_cpy.y;
3323 int viewport_height =
3324 pipe_ctx->plane_res.scl_data.viewport.height;
3325 int viewport_y =
3326 pipe_ctx->plane_res.scl_data.viewport.y;
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341 if (pipe_split_on || odm_combine_on) {
3342 int pos_cpy_x_offset;
3343 int other_pipe_viewport_y;
3344
3345 if (pipe_split_on) {
3346 if (pipe_ctx->bottom_pipe) {
3347 other_pipe_viewport_y =
3348 pipe_ctx->bottom_pipe->plane_res.scl_data.viewport.y;
3349 } else {
3350 other_pipe_viewport_y =
3351 pipe_ctx->top_pipe->plane_res.scl_data.viewport.y;
3352 }
3353 } else {
3354 if (pipe_ctx->next_odm_pipe) {
3355 other_pipe_viewport_y =
3356 pipe_ctx->next_odm_pipe->plane_res.scl_data.viewport.y;
3357 } else {
3358 other_pipe_viewport_y =
3359 pipe_ctx->prev_odm_pipe->plane_res.scl_data.viewport.y;
3360 }
3361 }
3362 pos_cpy_x_offset = (viewport_y > other_pipe_viewport_y) ?
3363 other_pipe_viewport_y : viewport_y;
3364 pos_cpy.x -= pos_cpy_x_offset;
3365 if (pos_cpy.x > viewport_height) {
3366 pos_cpy.x = pos_cpy.x - viewport_height;
3367 pos_cpy.y = viewport_height - pos_cpy.x;
3368 } else {
3369 pos_cpy.y = 2 * viewport_height - pos_cpy.x;
3370 }
3371 pos_cpy.y += pos_cpy_x_offset;
3372 } else {
3373 pos_cpy.y = (2 * viewport_y) + viewport_height - pos_cpy.x;
3374 }
3375 pos_cpy.x = temp_y;
3376 }
3377
3378 else if (param.rotation == ROTATION_ANGLE_180) {
3379 int viewport_width =
3380 pipe_ctx->plane_res.scl_data.viewport.width;
3381 int viewport_x =
3382 pipe_ctx->plane_res.scl_data.viewport.x;
3383
3384 if (pipe_split_on || odm_combine_on) {
3385 if (pos_cpy.x >= viewport_width + viewport_x) {
3386 pos_cpy.x = 2 * viewport_width
3387 - pos_cpy.x + 2 * viewport_x;
3388 } else {
3389 uint32_t temp_x = pos_cpy.x;
3390
3391 pos_cpy.x = 2 * viewport_x - pos_cpy.x;
3392 if (temp_x >= viewport_x +
3393 (int)hubp->curs_attr.width || pos_cpy.x
3394 <= (int)hubp->curs_attr.width +
3395 pipe_ctx->plane_state->src_rect.x) {
3396 pos_cpy.x = temp_x + viewport_width;
3397 }
3398 }
3399 } else {
3400 pos_cpy.x = viewport_width - pos_cpy.x + 2 * viewport_x;
3401 }
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411 pos_cpy.y = (2 * pipe_ctx->plane_res.scl_data.viewport.y) +
3412 pipe_ctx->plane_res.scl_data.viewport.height - pos_cpy.y;
3413 }
3414
3415 hubp->funcs->set_cursor_position(hubp, &pos_cpy, ¶m);
3416 dpp->funcs->set_cursor_position(dpp, &pos_cpy, ¶m, hubp->curs_attr.width, hubp->curs_attr.height);
3417}
3418
3419void dcn10_set_cursor_attribute(struct pipe_ctx *pipe_ctx)
3420{
3421 struct dc_cursor_attributes *attributes = &pipe_ctx->stream->cursor_attributes;
3422
3423 pipe_ctx->plane_res.hubp->funcs->set_cursor_attributes(
3424 pipe_ctx->plane_res.hubp, attributes);
3425 pipe_ctx->plane_res.dpp->funcs->set_cursor_attributes(
3426 pipe_ctx->plane_res.dpp, attributes);
3427}
3428
3429void dcn10_set_cursor_sdr_white_level(struct pipe_ctx *pipe_ctx)
3430{
3431 uint32_t sdr_white_level = pipe_ctx->stream->cursor_attributes.sdr_white_level;
3432 struct fixed31_32 multiplier;
3433 struct dpp_cursor_attributes opt_attr = { 0 };
3434 uint32_t hw_scale = 0x3c00;
3435 struct custom_float_format fmt;
3436
3437 if (!pipe_ctx->plane_res.dpp->funcs->set_optional_cursor_attributes)
3438 return;
3439
3440 fmt.exponenta_bits = 5;
3441 fmt.mantissa_bits = 10;
3442 fmt.sign = true;
3443
3444 if (sdr_white_level > 80) {
3445 multiplier = dc_fixpt_from_fraction(sdr_white_level, 80);
3446 convert_to_custom_float_format(multiplier, &fmt, &hw_scale);
3447 }
3448
3449 opt_attr.scale = hw_scale;
3450 opt_attr.bias = 0;
3451
3452 pipe_ctx->plane_res.dpp->funcs->set_optional_cursor_attributes(
3453 pipe_ctx->plane_res.dpp, &opt_attr);
3454}
3455
3456
3457
3458
3459
3460
3461
3462static void apply_front_porch_workaround(
3463 struct dc_crtc_timing *timing)
3464{
3465 if (timing->flags.INTERLACE == 1) {
3466 if (timing->v_front_porch < 2)
3467 timing->v_front_porch = 2;
3468 } else {
3469 if (timing->v_front_porch < 1)
3470 timing->v_front_porch = 1;
3471 }
3472}
3473
3474int dcn10_get_vupdate_offset_from_vsync(struct pipe_ctx *pipe_ctx)
3475{
3476 const struct dc_crtc_timing *dc_crtc_timing = &pipe_ctx->stream->timing;
3477 struct dc_crtc_timing patched_crtc_timing;
3478 int vesa_sync_start;
3479 int asic_blank_end;
3480 int interlace_factor;
3481 int vertical_line_start;
3482
3483 patched_crtc_timing = *dc_crtc_timing;
3484 apply_front_porch_workaround(&patched_crtc_timing);
3485
3486 interlace_factor = patched_crtc_timing.flags.INTERLACE ? 2 : 1;
3487
3488 vesa_sync_start = patched_crtc_timing.v_addressable +
3489 patched_crtc_timing.v_border_bottom +
3490 patched_crtc_timing.v_front_porch;
3491
3492 asic_blank_end = (patched_crtc_timing.v_total -
3493 vesa_sync_start -
3494 patched_crtc_timing.v_border_top)
3495 * interlace_factor;
3496
3497 vertical_line_start = asic_blank_end -
3498 pipe_ctx->pipe_dlg_param.vstartup_start + 1;
3499
3500 return vertical_line_start;
3501}
3502
3503void dcn10_calc_vupdate_position(
3504 struct dc *dc,
3505 struct pipe_ctx *pipe_ctx,
3506 uint32_t *start_line,
3507 uint32_t *end_line)
3508{
3509 const struct dc_crtc_timing *dc_crtc_timing = &pipe_ctx->stream->timing;
3510 int vline_int_offset_from_vupdate =
3511 pipe_ctx->stream->periodic_interrupt0.lines_offset;
3512 int vupdate_offset_from_vsync = dc->hwss.get_vupdate_offset_from_vsync(pipe_ctx);
3513 int start_position;
3514
3515 if (vline_int_offset_from_vupdate > 0)
3516 vline_int_offset_from_vupdate--;
3517 else if (vline_int_offset_from_vupdate < 0)
3518 vline_int_offset_from_vupdate++;
3519
3520 start_position = vline_int_offset_from_vupdate + vupdate_offset_from_vsync;
3521
3522 if (start_position >= 0)
3523 *start_line = start_position;
3524 else
3525 *start_line = dc_crtc_timing->v_total + start_position - 1;
3526
3527 *end_line = *start_line + 2;
3528
3529 if (*end_line >= dc_crtc_timing->v_total)
3530 *end_line = 2;
3531}
3532
3533static void dcn10_cal_vline_position(
3534 struct dc *dc,
3535 struct pipe_ctx *pipe_ctx,
3536 enum vline_select vline,
3537 uint32_t *start_line,
3538 uint32_t *end_line)
3539{
3540 enum vertical_interrupt_ref_point ref_point = INVALID_POINT;
3541
3542 if (vline == VLINE0)
3543 ref_point = pipe_ctx->stream->periodic_interrupt0.ref_point;
3544 else if (vline == VLINE1)
3545 ref_point = pipe_ctx->stream->periodic_interrupt1.ref_point;
3546
3547 switch (ref_point) {
3548 case START_V_UPDATE:
3549 dcn10_calc_vupdate_position(
3550 dc,
3551 pipe_ctx,
3552 start_line,
3553 end_line);
3554 break;
3555 case START_V_SYNC:
3556
3557 break;
3558 default:
3559 ASSERT(0);
3560 break;
3561 }
3562}
3563
3564void dcn10_setup_periodic_interrupt(
3565 struct dc *dc,
3566 struct pipe_ctx *pipe_ctx,
3567 enum vline_select vline)
3568{
3569 struct timing_generator *tg = pipe_ctx->stream_res.tg;
3570
3571 if (vline == VLINE0) {
3572 uint32_t start_line = 0;
3573 uint32_t end_line = 0;
3574
3575 dcn10_cal_vline_position(dc, pipe_ctx, vline, &start_line, &end_line);
3576
3577 tg->funcs->setup_vertical_interrupt0(tg, start_line, end_line);
3578
3579 } else if (vline == VLINE1) {
3580 pipe_ctx->stream_res.tg->funcs->setup_vertical_interrupt1(
3581 tg,
3582 pipe_ctx->stream->periodic_interrupt1.lines_offset);
3583 }
3584}
3585
3586void dcn10_setup_vupdate_interrupt(struct dc *dc, struct pipe_ctx *pipe_ctx)
3587{
3588 struct timing_generator *tg = pipe_ctx->stream_res.tg;
3589 int start_line = dc->hwss.get_vupdate_offset_from_vsync(pipe_ctx);
3590
3591 if (start_line < 0) {
3592 ASSERT(0);
3593 start_line = 0;
3594 }
3595
3596 if (tg->funcs->setup_vertical_interrupt2)
3597 tg->funcs->setup_vertical_interrupt2(tg, start_line);
3598}
3599
3600void dcn10_unblank_stream(struct pipe_ctx *pipe_ctx,
3601 struct dc_link_settings *link_settings)
3602{
3603 struct encoder_unblank_param params = { { 0 } };
3604 struct dc_stream_state *stream = pipe_ctx->stream;
3605 struct dc_link *link = stream->link;
3606 struct dce_hwseq *hws = link->dc->hwseq;
3607
3608
3609 params.timing = pipe_ctx->stream->timing;
3610
3611 params.link_settings.link_rate = link_settings->link_rate;
3612
3613 if (dc_is_dp_signal(pipe_ctx->stream->signal)) {
3614 if (params.timing.pixel_encoding == PIXEL_ENCODING_YCBCR420)
3615 params.timing.pix_clk_100hz /= 2;
3616 pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(pipe_ctx->stream_res.stream_enc, ¶ms);
3617 }
3618
3619 if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP) {
3620 hws->funcs.edp_backlight_control(link, true);
3621 }
3622}
3623
3624void dcn10_send_immediate_sdp_message(struct pipe_ctx *pipe_ctx,
3625 const uint8_t *custom_sdp_message,
3626 unsigned int sdp_message_size)
3627{
3628 if (dc_is_dp_signal(pipe_ctx->stream->signal)) {
3629 pipe_ctx->stream_res.stream_enc->funcs->send_immediate_sdp_message(
3630 pipe_ctx->stream_res.stream_enc,
3631 custom_sdp_message,
3632 sdp_message_size);
3633 }
3634}
3635enum dc_status dcn10_set_clock(struct dc *dc,
3636 enum dc_clock_type clock_type,
3637 uint32_t clk_khz,
3638 uint32_t stepping)
3639{
3640 struct dc_state *context = dc->current_state;
3641 struct dc_clock_config clock_cfg = {0};
3642 struct dc_clocks *current_clocks = &context->bw_ctx.bw.dcn.clk;
3643
3644 if (!dc->clk_mgr || !dc->clk_mgr->funcs->get_clock)
3645 return DC_FAIL_UNSUPPORTED_1;
3646
3647 dc->clk_mgr->funcs->get_clock(dc->clk_mgr,
3648 context, clock_type, &clock_cfg);
3649
3650 if (clk_khz > clock_cfg.max_clock_khz)
3651 return DC_FAIL_CLK_EXCEED_MAX;
3652
3653 if (clk_khz < clock_cfg.min_clock_khz)
3654 return DC_FAIL_CLK_BELOW_MIN;
3655
3656 if (clk_khz < clock_cfg.bw_requirequired_clock_khz)
3657 return DC_FAIL_CLK_BELOW_CFG_REQUIRED;
3658
3659
3660 if (clock_type == DC_CLOCK_TYPE_DISPCLK)
3661 current_clocks->dispclk_khz = clk_khz;
3662 else if (clock_type == DC_CLOCK_TYPE_DPPCLK)
3663 current_clocks->dppclk_khz = clk_khz;
3664 else
3665 return DC_ERROR_UNEXPECTED;
3666
3667 if (dc->clk_mgr->funcs->update_clocks)
3668 dc->clk_mgr->funcs->update_clocks(dc->clk_mgr,
3669 context, true);
3670 return DC_OK;
3671
3672}
3673
3674void dcn10_get_clock(struct dc *dc,
3675 enum dc_clock_type clock_type,
3676 struct dc_clock_config *clock_cfg)
3677{
3678 struct dc_state *context = dc->current_state;
3679
3680 if (dc->clk_mgr && dc->clk_mgr->funcs->get_clock)
3681 dc->clk_mgr->funcs->get_clock(dc->clk_mgr, context, clock_type, clock_cfg);
3682
3683}
3684
3685void dcn10_get_dcc_en_bits(struct dc *dc, int *dcc_en_bits)
3686{
3687 struct resource_pool *pool = dc->res_pool;
3688 int i;
3689
3690 for (i = 0; i < pool->pipe_count; i++) {
3691 struct hubp *hubp = pool->hubps[i];
3692 struct dcn_hubp_state *s = &(TO_DCN10_HUBP(hubp)->state);
3693
3694 hubp->funcs->hubp_read_state(hubp);
3695
3696 if (!s->blank_en)
3697 dcc_en_bits[i] = s->dcc_en ? 1 : 0;
3698 }
3699}
3700