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 "dm_services.h"
27#include "core_types.h"
28#include "resource.h"
29#include "custom_float.h"
30#include "dcn10_hw_sequencer.h"
31#include "dce110/dce110_hw_sequencer.h"
32#include "dce/dce_hwseq.h"
33#include "abm.h"
34#include "dmcu.h"
35#include "dcn10_optc.h"
36#include "dcn10/dcn10_dpp.h"
37#include "dcn10/dcn10_mpc.h"
38#include "timing_generator.h"
39#include "opp.h"
40#include "ipp.h"
41#include "mpc.h"
42#include "reg_helper.h"
43#include "custom_float.h"
44#include "dcn10_hubp.h"
45#include "dcn10_hubbub.h"
46#include "dcn10_cm_common.h"
47
48#define DC_LOGGER_INIT(logger)
49
50#define CTX \
51 hws->ctx
52#define REG(reg)\
53 hws->regs->reg
54
55#undef FN
56#define FN(reg_name, field_name) \
57 hws->shifts->field_name, hws->masks->field_name
58
59
60#define DTN_INFO_MICRO_SEC(ref_cycle) \
61 print_microsec(dc_ctx, ref_cycle)
62
63void print_microsec(struct dc_context *dc_ctx, uint32_t ref_cycle)
64{
65 const uint32_t ref_clk_mhz = dc_ctx->dc->res_pool->ref_clock_inKhz / 1000;
66 static const unsigned int frac = 1000;
67 uint32_t us_x10 = (ref_cycle * frac) / ref_clk_mhz;
68
69 DTN_INFO(" %11d.%03d",
70 us_x10 / frac,
71 us_x10 % frac);
72}
73
74
75static void log_mpc_crc(struct dc *dc)
76{
77 struct dc_context *dc_ctx = dc->ctx;
78 struct dce_hwseq *hws = dc->hwseq;
79
80 if (REG(MPC_CRC_RESULT_GB))
81 DTN_INFO("MPC_CRC_RESULT_GB:%d MPC_CRC_RESULT_C:%d MPC_CRC_RESULT_AR:%d\n",
82 REG_READ(MPC_CRC_RESULT_GB), REG_READ(MPC_CRC_RESULT_C), REG_READ(MPC_CRC_RESULT_AR));
83 if (REG(DPP_TOP0_DPP_CRC_VAL_B_A))
84 DTN_INFO("DPP_TOP0_DPP_CRC_VAL_B_A:%d DPP_TOP0_DPP_CRC_VAL_R_G:%d\n",
85 REG_READ(DPP_TOP0_DPP_CRC_VAL_B_A), REG_READ(DPP_TOP0_DPP_CRC_VAL_R_G));
86}
87
88void dcn10_log_hubbub_state(struct dc *dc)
89{
90 struct dc_context *dc_ctx = dc->ctx;
91 struct dcn_hubbub_wm wm;
92 int i;
93
94 hubbub1_wm_read_state(dc->res_pool->hubbub, &wm);
95
96 DTN_INFO("HUBBUB WM: data_urgent pte_meta_urgent"
97 " sr_enter sr_exit dram_clk_change\n");
98
99 for (i = 0; i < 4; i++) {
100 struct dcn_hubbub_wm_set *s;
101
102 s = &wm.sets[i];
103 DTN_INFO("WM_Set[%d]:", s->wm_set);
104 DTN_INFO_MICRO_SEC(s->data_urgent);
105 DTN_INFO_MICRO_SEC(s->pte_meta_urgent);
106 DTN_INFO_MICRO_SEC(s->sr_enter);
107 DTN_INFO_MICRO_SEC(s->sr_exit);
108 DTN_INFO_MICRO_SEC(s->dram_clk_chanage);
109 DTN_INFO("\n");
110 }
111
112 DTN_INFO("\n");
113}
114
115static void dcn10_log_hubp_states(struct dc *dc)
116{
117 struct dc_context *dc_ctx = dc->ctx;
118 struct resource_pool *pool = dc->res_pool;
119 int i;
120
121 DTN_INFO("HUBP: format addr_hi width height"
122 " rot mir sw_mode dcc_en blank_en ttu_dis underflow"
123 " min_ttu_vblank qos_low_wm qos_high_wm\n");
124 for (i = 0; i < pool->pipe_count; i++) {
125 struct hubp *hubp = pool->hubps[i];
126 struct dcn_hubp_state *s = &(TO_DCN10_HUBP(hubp)->state);
127
128 hubp->funcs->hubp_read_state(hubp);
129
130 if (!s->blank_en) {
131 DTN_INFO("[%2d]: %5xh %6xh %5d %6d %2xh %2xh %6xh"
132 " %6d %8d %7d %8xh",
133 hubp->inst,
134 s->pixel_format,
135 s->inuse_addr_hi,
136 s->viewport_width,
137 s->viewport_height,
138 s->rotation_angle,
139 s->h_mirror_en,
140 s->sw_mode,
141 s->dcc_en,
142 s->blank_en,
143 s->ttu_disable,
144 s->underflow_status);
145 DTN_INFO_MICRO_SEC(s->min_ttu_vblank);
146 DTN_INFO_MICRO_SEC(s->qos_level_low_wm);
147 DTN_INFO_MICRO_SEC(s->qos_level_high_wm);
148 DTN_INFO("\n");
149 }
150 }
151
152 DTN_INFO("\n=========RQ========\n");
153 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"
154 " min_m_c_s dpte_gr_s mpte_gr_s swath_hei pte_row_h C:chunk_s min_chu_s meta_ch_s"
155 " min_m_c_s dpte_gr_s mpte_gr_s swath_hei pte_row_h\n");
156 for (i = 0; i < pool->pipe_count; i++) {
157 struct dcn_hubp_state *s = &(TO_DCN10_HUBP(pool->hubps[i])->state);
158 struct _vcs_dpi_display_rq_regs_st *rq_regs = &s->rq_regs;
159
160 if (!s->blank_en)
161 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",
162 pool->hubps[i]->inst, rq_regs->drq_expansion_mode, rq_regs->prq_expansion_mode, rq_regs->mrq_expansion_mode,
163 rq_regs->crq_expansion_mode, rq_regs->plane1_base_address, rq_regs->rq_regs_l.chunk_size,
164 rq_regs->rq_regs_l.min_chunk_size, rq_regs->rq_regs_l.meta_chunk_size,
165 rq_regs->rq_regs_l.min_meta_chunk_size, rq_regs->rq_regs_l.dpte_group_size,
166 rq_regs->rq_regs_l.mpte_group_size, rq_regs->rq_regs_l.swath_height,
167 rq_regs->rq_regs_l.pte_row_height_linear, rq_regs->rq_regs_c.chunk_size, rq_regs->rq_regs_c.min_chunk_size,
168 rq_regs->rq_regs_c.meta_chunk_size, rq_regs->rq_regs_c.min_meta_chunk_size,
169 rq_regs->rq_regs_c.dpte_group_size, rq_regs->rq_regs_c.mpte_group_size,
170 rq_regs->rq_regs_c.swath_height, rq_regs->rq_regs_c.pte_row_height_linear);
171 }
172
173 DTN_INFO("========DLG========\n");
174 DTN_INFO("HUBP: rc_hbe dlg_vbe min_d_y_n rc_per_ht rc_x_a_s "
175 " dst_y_a_s dst_y_pf dst_y_vvb dst_y_rvb dst_y_vfl dst_y_rfl rf_pix_fq"
176 " vratio_pf vrat_pf_c rc_pg_vbl rc_pg_vbc rc_mc_vbl rc_mc_vbc rc_pg_fll"
177 " rc_pg_flc rc_mc_fll rc_mc_flc pr_nom_l pr_nom_c rc_pg_nl rc_pg_nc "
178 " mr_nom_l mr_nom_c rc_mc_nl rc_mc_nc rc_ld_pl rc_ld_pc rc_ld_l "
179 " rc_ld_c cha_cur0 ofst_cur1 cha_cur1 vr_af_vc0 ddrq_limt x_rt_dlay"
180 " x_rp_dlay x_rr_sfl\n");
181 for (i = 0; i < pool->pipe_count; i++) {
182 struct dcn_hubp_state *s = &(TO_DCN10_HUBP(pool->hubps[i])->state);
183 struct _vcs_dpi_display_dlg_regs_st *dlg_regs = &s->dlg_attr;
184
185 if (!s->blank_en)
186 DTN_INFO("[%2d]: %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh"
187 "% 8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh"
188 " %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh\n",
189 pool->hubps[i]->inst, dlg_regs->refcyc_h_blank_end, dlg_regs->dlg_vblank_end, dlg_regs->min_dst_y_next_start,
190 dlg_regs->refcyc_per_htotal, dlg_regs->refcyc_x_after_scaler, dlg_regs->dst_y_after_scaler,
191 dlg_regs->dst_y_prefetch, dlg_regs->dst_y_per_vm_vblank, dlg_regs->dst_y_per_row_vblank,
192 dlg_regs->dst_y_per_vm_flip, dlg_regs->dst_y_per_row_flip, dlg_regs->ref_freq_to_pix_freq,
193 dlg_regs->vratio_prefetch, dlg_regs->vratio_prefetch_c, dlg_regs->refcyc_per_pte_group_vblank_l,
194 dlg_regs->refcyc_per_pte_group_vblank_c, dlg_regs->refcyc_per_meta_chunk_vblank_l,
195 dlg_regs->refcyc_per_meta_chunk_vblank_c, dlg_regs->refcyc_per_pte_group_flip_l,
196 dlg_regs->refcyc_per_pte_group_flip_c, dlg_regs->refcyc_per_meta_chunk_flip_l,
197 dlg_regs->refcyc_per_meta_chunk_flip_c, dlg_regs->dst_y_per_pte_row_nom_l,
198 dlg_regs->dst_y_per_pte_row_nom_c, dlg_regs->refcyc_per_pte_group_nom_l,
199 dlg_regs->refcyc_per_pte_group_nom_c, dlg_regs->dst_y_per_meta_row_nom_l,
200 dlg_regs->dst_y_per_meta_row_nom_c, dlg_regs->refcyc_per_meta_chunk_nom_l,
201 dlg_regs->refcyc_per_meta_chunk_nom_c, dlg_regs->refcyc_per_line_delivery_pre_l,
202 dlg_regs->refcyc_per_line_delivery_pre_c, dlg_regs->refcyc_per_line_delivery_l,
203 dlg_regs->refcyc_per_line_delivery_c, dlg_regs->chunk_hdl_adjust_cur0, dlg_regs->dst_y_offset_cur1,
204 dlg_regs->chunk_hdl_adjust_cur1, dlg_regs->vready_after_vcount0, dlg_regs->dst_y_delta_drq_limit,
205 dlg_regs->xfc_reg_transfer_delay, dlg_regs->xfc_reg_precharge_delay,
206 dlg_regs->xfc_reg_remote_surface_flip_latency);
207 }
208
209 DTN_INFO("========TTU========\n");
210 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"
211 " rc_rd_c rc_rd_c0 rc_rd_pc0 rc_rd_c1 rc_rd_pc1 qos_lf_l qos_rds_l"
212 " qos_lf_c qos_rds_c qos_lf_c0 qos_rds_c0 qos_lf_c1 qos_rds_c1\n");
213 for (i = 0; i < pool->pipe_count; i++) {
214 struct dcn_hubp_state *s = &(TO_DCN10_HUBP(pool->hubps[i])->state);
215 struct _vcs_dpi_display_ttu_regs_st *ttu_regs = &s->ttu_attr;
216
217 if (!s->blank_en)
218 DTN_INFO("[%2d]: %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh\n",
219 pool->hubps[i]->inst, ttu_regs->qos_level_low_wm, ttu_regs->qos_level_high_wm, ttu_regs->min_ttu_vblank,
220 ttu_regs->qos_level_flip, ttu_regs->refcyc_per_req_delivery_pre_l, ttu_regs->refcyc_per_req_delivery_l,
221 ttu_regs->refcyc_per_req_delivery_pre_c, ttu_regs->refcyc_per_req_delivery_c, ttu_regs->refcyc_per_req_delivery_cur0,
222 ttu_regs->refcyc_per_req_delivery_pre_cur0, ttu_regs->refcyc_per_req_delivery_cur1,
223 ttu_regs->refcyc_per_req_delivery_pre_cur1, ttu_regs->qos_level_fixed_l, ttu_regs->qos_ramp_disable_l,
224 ttu_regs->qos_level_fixed_c, ttu_regs->qos_ramp_disable_c, ttu_regs->qos_level_fixed_cur0,
225 ttu_regs->qos_ramp_disable_cur0, ttu_regs->qos_level_fixed_cur1, ttu_regs->qos_ramp_disable_cur1);
226 }
227 DTN_INFO("\n");
228}
229
230void dcn10_log_hw_state(struct dc *dc)
231{
232 struct dc_context *dc_ctx = dc->ctx;
233 struct resource_pool *pool = dc->res_pool;
234 int i;
235
236 DTN_INFO_BEGIN();
237
238 dcn10_log_hubbub_state(dc);
239
240 dcn10_log_hubp_states(dc);
241
242 DTN_INFO("DPP: IGAM format IGAM mode DGAM mode RGAM mode"
243 " GAMUT mode C11 C12 C13 C14 C21 C22 C23 C24 "
244 "C31 C32 C33 C34\n");
245 for (i = 0; i < pool->pipe_count; i++) {
246 struct dpp *dpp = pool->dpps[i];
247 struct dcn_dpp_state s;
248
249 dpp->funcs->dpp_read_state(dpp, &s);
250
251 DTN_INFO("[%2d]: %11xh %-11s %-11s %-11s"
252 "%8x %08xh %08xh %08xh %08xh %08xh %08xh",
253 dpp->inst,
254 s.igam_input_format,
255 (s.igam_lut_mode == 0) ? "BypassFixed" :
256 ((s.igam_lut_mode == 1) ? "BypassFloat" :
257 ((s.igam_lut_mode == 2) ? "RAM" :
258 ((s.igam_lut_mode == 3) ? "RAM" :
259 "Unknown"))),
260 (s.dgam_lut_mode == 0) ? "Bypass" :
261 ((s.dgam_lut_mode == 1) ? "sRGB" :
262 ((s.dgam_lut_mode == 2) ? "Ycc" :
263 ((s.dgam_lut_mode == 3) ? "RAM" :
264 ((s.dgam_lut_mode == 4) ? "RAM" :
265 "Unknown")))),
266 (s.rgam_lut_mode == 0) ? "Bypass" :
267 ((s.rgam_lut_mode == 1) ? "sRGB" :
268 ((s.rgam_lut_mode == 2) ? "Ycc" :
269 ((s.rgam_lut_mode == 3) ? "RAM" :
270 ((s.rgam_lut_mode == 4) ? "RAM" :
271 "Unknown")))),
272 s.gamut_remap_mode,
273 s.gamut_remap_c11_c12,
274 s.gamut_remap_c13_c14,
275 s.gamut_remap_c21_c22,
276 s.gamut_remap_c23_c24,
277 s.gamut_remap_c31_c32,
278 s.gamut_remap_c33_c34);
279 DTN_INFO("\n");
280 }
281 DTN_INFO("\n");
282
283 DTN_INFO("MPCC: OPP DPP MPCCBOT MODE ALPHA_MODE PREMULT OVERLAP_ONLY IDLE\n");
284 for (i = 0; i < pool->pipe_count; i++) {
285 struct mpcc_state s = {0};
286
287 pool->mpc->funcs->read_mpcc_state(pool->mpc, i, &s);
288 if (s.opp_id != 0xf)
289 DTN_INFO("[%2d]: %2xh %2xh %6xh %4d %10d %7d %12d %4d\n",
290 i, s.opp_id, s.dpp_id, s.bot_mpcc_id,
291 s.mode, s.alpha_mode, s.pre_multiplied_alpha, s.overlap_only,
292 s.idle);
293 }
294 DTN_INFO("\n");
295
296 DTN_INFO("OTG: v_bs v_be v_ss v_se vpol vmax vmin vmax_sel vmin_sel"
297 " h_bs h_be h_ss h_se hpol htot vtot underflow\n");
298
299 for (i = 0; i < pool->timing_generator_count; i++) {
300 struct timing_generator *tg = pool->timing_generators[i];
301 struct dcn_otg_state s = {0};
302
303 optc1_read_otg_state(DCN10TG_FROM_TG(tg), &s);
304
305
306 if ((s.otg_enabled & 1) == 0)
307 continue;
308
309 DTN_INFO("[%d]: %5d %5d %5d %5d %5d %5d %5d %9d %9d %5d %5d %5d"
310 " %5d %5d %5d %5d %9d\n",
311 tg->inst,
312 s.v_blank_start,
313 s.v_blank_end,
314 s.v_sync_a_start,
315 s.v_sync_a_end,
316 s.v_sync_a_pol,
317 s.v_total_max,
318 s.v_total_min,
319 s.v_total_max_sel,
320 s.v_total_min_sel,
321 s.h_blank_start,
322 s.h_blank_end,
323 s.h_sync_a_start,
324 s.h_sync_a_end,
325 s.h_sync_a_pol,
326 s.h_total,
327 s.v_total,
328 s.underflow_occurred_status);
329
330
331
332
333
334 tg->funcs->clear_optc_underflow(tg);
335 }
336 DTN_INFO("\n");
337
338 DTN_INFO("\nCALCULATED Clocks: dcfclk_khz:%d dcfclk_deep_sleep_khz:%d dispclk_khz:%d\n"
339 "dppclk_khz:%d max_supported_dppclk_khz:%d fclk_khz:%d socclk_khz:%d\n\n",
340 dc->current_state->bw.dcn.clk.dcfclk_khz,
341 dc->current_state->bw.dcn.clk.dcfclk_deep_sleep_khz,
342 dc->current_state->bw.dcn.clk.dispclk_khz,
343 dc->current_state->bw.dcn.clk.dppclk_khz,
344 dc->current_state->bw.dcn.clk.max_supported_dppclk_khz,
345 dc->current_state->bw.dcn.clk.fclk_khz,
346 dc->current_state->bw.dcn.clk.socclk_khz);
347
348 log_mpc_crc(dc);
349
350 DTN_INFO_END();
351}
352
353static void enable_power_gating_plane(
354 struct dce_hwseq *hws,
355 bool enable)
356{
357 bool force_on = 1;
358
359 if (enable)
360 force_on = 0;
361
362
363 REG_UPDATE(DOMAIN0_PG_CONFIG, DOMAIN0_POWER_FORCEON, force_on);
364 REG_UPDATE(DOMAIN2_PG_CONFIG, DOMAIN2_POWER_FORCEON, force_on);
365 REG_UPDATE(DOMAIN4_PG_CONFIG, DOMAIN4_POWER_FORCEON, force_on);
366 REG_UPDATE(DOMAIN6_PG_CONFIG, DOMAIN6_POWER_FORCEON, force_on);
367
368
369 REG_UPDATE(DOMAIN1_PG_CONFIG, DOMAIN1_POWER_FORCEON, force_on);
370 REG_UPDATE(DOMAIN3_PG_CONFIG, DOMAIN3_POWER_FORCEON, force_on);
371 REG_UPDATE(DOMAIN5_PG_CONFIG, DOMAIN5_POWER_FORCEON, force_on);
372 REG_UPDATE(DOMAIN7_PG_CONFIG, DOMAIN7_POWER_FORCEON, force_on);
373}
374
375static void disable_vga(
376 struct dce_hwseq *hws)
377{
378 unsigned int in_vga1_mode = 0;
379 unsigned int in_vga2_mode = 0;
380 unsigned int in_vga3_mode = 0;
381 unsigned int in_vga4_mode = 0;
382
383 REG_GET(D1VGA_CONTROL, D1VGA_MODE_ENABLE, &in_vga1_mode);
384 REG_GET(D2VGA_CONTROL, D2VGA_MODE_ENABLE, &in_vga2_mode);
385 REG_GET(D3VGA_CONTROL, D3VGA_MODE_ENABLE, &in_vga3_mode);
386 REG_GET(D4VGA_CONTROL, D4VGA_MODE_ENABLE, &in_vga4_mode);
387
388 if (in_vga1_mode == 0 && in_vga2_mode == 0 &&
389 in_vga3_mode == 0 && in_vga4_mode == 0)
390 return;
391
392 REG_WRITE(D1VGA_CONTROL, 0);
393 REG_WRITE(D2VGA_CONTROL, 0);
394 REG_WRITE(D3VGA_CONTROL, 0);
395 REG_WRITE(D4VGA_CONTROL, 0);
396
397
398
399
400
401
402
403
404 REG_UPDATE(VGA_TEST_CONTROL, VGA_TEST_ENABLE, 1);
405 REG_UPDATE(VGA_TEST_CONTROL, VGA_TEST_RENDER_START, 1);
406}
407
408static void dpp_pg_control(
409 struct dce_hwseq *hws,
410 unsigned int dpp_inst,
411 bool power_on)
412{
413 uint32_t power_gate = power_on ? 0 : 1;
414 uint32_t pwr_status = power_on ? 0 : 2;
415
416 if (hws->ctx->dc->debug.disable_dpp_power_gate)
417 return;
418 if (REG(DOMAIN1_PG_CONFIG) == 0)
419 return;
420
421 switch (dpp_inst) {
422 case 0:
423 REG_UPDATE(DOMAIN1_PG_CONFIG,
424 DOMAIN1_POWER_GATE, power_gate);
425
426 REG_WAIT(DOMAIN1_PG_STATUS,
427 DOMAIN1_PGFSM_PWR_STATUS, pwr_status,
428 1, 1000);
429 break;
430 case 1:
431 REG_UPDATE(DOMAIN3_PG_CONFIG,
432 DOMAIN3_POWER_GATE, power_gate);
433
434 REG_WAIT(DOMAIN3_PG_STATUS,
435 DOMAIN3_PGFSM_PWR_STATUS, pwr_status,
436 1, 1000);
437 break;
438 case 2:
439 REG_UPDATE(DOMAIN5_PG_CONFIG,
440 DOMAIN5_POWER_GATE, power_gate);
441
442 REG_WAIT(DOMAIN5_PG_STATUS,
443 DOMAIN5_PGFSM_PWR_STATUS, pwr_status,
444 1, 1000);
445 break;
446 case 3:
447 REG_UPDATE(DOMAIN7_PG_CONFIG,
448 DOMAIN7_POWER_GATE, power_gate);
449
450 REG_WAIT(DOMAIN7_PG_STATUS,
451 DOMAIN7_PGFSM_PWR_STATUS, pwr_status,
452 1, 1000);
453 break;
454 default:
455 BREAK_TO_DEBUGGER();
456 break;
457 }
458}
459
460static void hubp_pg_control(
461 struct dce_hwseq *hws,
462 unsigned int hubp_inst,
463 bool power_on)
464{
465 uint32_t power_gate = power_on ? 0 : 1;
466 uint32_t pwr_status = power_on ? 0 : 2;
467
468 if (hws->ctx->dc->debug.disable_hubp_power_gate)
469 return;
470 if (REG(DOMAIN0_PG_CONFIG) == 0)
471 return;
472
473 switch (hubp_inst) {
474 case 0:
475 REG_UPDATE(DOMAIN0_PG_CONFIG,
476 DOMAIN0_POWER_GATE, power_gate);
477
478 REG_WAIT(DOMAIN0_PG_STATUS,
479 DOMAIN0_PGFSM_PWR_STATUS, pwr_status,
480 1, 1000);
481 break;
482 case 1:
483 REG_UPDATE(DOMAIN2_PG_CONFIG,
484 DOMAIN2_POWER_GATE, power_gate);
485
486 REG_WAIT(DOMAIN2_PG_STATUS,
487 DOMAIN2_PGFSM_PWR_STATUS, pwr_status,
488 1, 1000);
489 break;
490 case 2:
491 REG_UPDATE(DOMAIN4_PG_CONFIG,
492 DOMAIN4_POWER_GATE, power_gate);
493
494 REG_WAIT(DOMAIN4_PG_STATUS,
495 DOMAIN4_PGFSM_PWR_STATUS, pwr_status,
496 1, 1000);
497 break;
498 case 3:
499 REG_UPDATE(DOMAIN6_PG_CONFIG,
500 DOMAIN6_POWER_GATE, power_gate);
501
502 REG_WAIT(DOMAIN6_PG_STATUS,
503 DOMAIN6_PGFSM_PWR_STATUS, pwr_status,
504 1, 1000);
505 break;
506 default:
507 BREAK_TO_DEBUGGER();
508 break;
509 }
510}
511
512static void power_on_plane(
513 struct dce_hwseq *hws,
514 int plane_id)
515{
516 DC_LOGGER_INIT(hws->ctx->logger);
517 if (REG(DC_IP_REQUEST_CNTL)) {
518 REG_SET(DC_IP_REQUEST_CNTL, 0,
519 IP_REQUEST_EN, 1);
520 dpp_pg_control(hws, plane_id, true);
521 hubp_pg_control(hws, plane_id, true);
522 REG_SET(DC_IP_REQUEST_CNTL, 0,
523 IP_REQUEST_EN, 0);
524 DC_LOG_DEBUG(
525 "Un-gated front end for pipe %d\n", plane_id);
526 }
527}
528
529static void undo_DEGVIDCN10_253_wa(struct dc *dc)
530{
531 struct dce_hwseq *hws = dc->hwseq;
532 struct hubp *hubp = dc->res_pool->hubps[0];
533
534 if (!hws->wa_state.DEGVIDCN10_253_applied)
535 return;
536
537 hubp->funcs->set_blank(hubp, true);
538
539 REG_SET(DC_IP_REQUEST_CNTL, 0,
540 IP_REQUEST_EN, 1);
541
542 hubp_pg_control(hws, 0, false);
543 REG_SET(DC_IP_REQUEST_CNTL, 0,
544 IP_REQUEST_EN, 0);
545
546 hws->wa_state.DEGVIDCN10_253_applied = false;
547}
548
549static void apply_DEGVIDCN10_253_wa(struct dc *dc)
550{
551 struct dce_hwseq *hws = dc->hwseq;
552 struct hubp *hubp = dc->res_pool->hubps[0];
553 int i;
554
555 if (dc->debug.disable_stutter)
556 return;
557
558 if (!hws->wa.DEGVIDCN10_253)
559 return;
560
561 for (i = 0; i < dc->res_pool->pipe_count; i++) {
562 if (!dc->res_pool->hubps[i]->power_gated)
563 return;
564 }
565
566
567
568 REG_SET(DC_IP_REQUEST_CNTL, 0,
569 IP_REQUEST_EN, 1);
570
571 hubp_pg_control(hws, 0, true);
572 REG_SET(DC_IP_REQUEST_CNTL, 0,
573 IP_REQUEST_EN, 0);
574
575 hubp->funcs->set_hubp_blank_en(hubp, false);
576 hws->wa_state.DEGVIDCN10_253_applied = true;
577}
578
579static void bios_golden_init(struct dc *dc)
580{
581 struct dc_bios *bp = dc->ctx->dc_bios;
582 int i;
583
584
585 bp->funcs->enable_disp_power_gating(bp,
586 CONTROLLER_ID_D0, ASIC_PIPE_INIT);
587
588 for (i = 0; i < dc->res_pool->pipe_count; i++) {
589
590 bp->funcs->enable_disp_power_gating(bp,
591 CONTROLLER_ID_D0 + i, ASIC_PIPE_DISABLE);
592 }
593}
594
595static void false_optc_underflow_wa(
596 struct dc *dc,
597 const struct dc_stream_state *stream,
598 struct timing_generator *tg)
599{
600 int i;
601 bool underflow;
602
603 if (!dc->hwseq->wa.false_optc_underflow)
604 return;
605
606 underflow = tg->funcs->is_optc_underflow_occurred(tg);
607
608 for (i = 0; i < dc->res_pool->pipe_count; i++) {
609 struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
610
611 if (old_pipe_ctx->stream != stream)
612 continue;
613
614 dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, old_pipe_ctx);
615 }
616
617 tg->funcs->set_blank_data_double_buffer(tg, true);
618
619 if (tg->funcs->is_optc_underflow_occurred(tg) && !underflow)
620 tg->funcs->clear_optc_underflow(tg);
621}
622
623static enum dc_status dcn10_enable_stream_timing(
624 struct pipe_ctx *pipe_ctx,
625 struct dc_state *context,
626 struct dc *dc)
627{
628 struct dc_stream_state *stream = pipe_ctx->stream;
629 enum dc_color_space color_space;
630 struct tg_color black_color = {0};
631
632
633
634
635
636 if (pipe_ctx->top_pipe != NULL)
637 return DC_OK;
638
639
640
641
642
643
644 pipe_ctx->stream_res.tg->funcs->enable_optc_clock(pipe_ctx->stream_res.tg, true);
645
646 if (false == pipe_ctx->clock_source->funcs->program_pix_clk(
647 pipe_ctx->clock_source,
648 &pipe_ctx->stream_res.pix_clk_params,
649 &pipe_ctx->pll_settings)) {
650 BREAK_TO_DEBUGGER();
651 return DC_ERROR_UNEXPECTED;
652 }
653 pipe_ctx->stream_res.tg->dlg_otg_param.vready_offset = pipe_ctx->pipe_dlg_param.vready_offset;
654 pipe_ctx->stream_res.tg->dlg_otg_param.vstartup_start = pipe_ctx->pipe_dlg_param.vstartup_start;
655 pipe_ctx->stream_res.tg->dlg_otg_param.vupdate_offset = pipe_ctx->pipe_dlg_param.vupdate_offset;
656 pipe_ctx->stream_res.tg->dlg_otg_param.vupdate_width = pipe_ctx->pipe_dlg_param.vupdate_width;
657
658 pipe_ctx->stream_res.tg->dlg_otg_param.signal = pipe_ctx->stream->signal;
659
660 pipe_ctx->stream_res.tg->funcs->program_timing(
661 pipe_ctx->stream_res.tg,
662 &stream->timing,
663 true);
664
665#if 0
666
667
668
669 inst_offset = reg_offsets[pipe_ctx->stream_res.tg->inst].fmt;
670
671 pipe_ctx->stream_res.opp->funcs->opp_program_fmt(
672 pipe_ctx->stream_res.opp,
673 &stream->bit_depth_params,
674 &stream->clamping);
675#endif
676
677 color_space = stream->output_color_space;
678 color_space_to_black_color(dc, color_space, &black_color);
679
680 if (pipe_ctx->stream_res.tg->funcs->set_blank_color)
681 pipe_ctx->stream_res.tg->funcs->set_blank_color(
682 pipe_ctx->stream_res.tg,
683 &black_color);
684
685 if (pipe_ctx->stream_res.tg->funcs->is_blanked &&
686 !pipe_ctx->stream_res.tg->funcs->is_blanked(pipe_ctx->stream_res.tg)) {
687 pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, true);
688 hwss_wait_for_blank_complete(pipe_ctx->stream_res.tg);
689 false_optc_underflow_wa(dc, pipe_ctx->stream, pipe_ctx->stream_res.tg);
690 }
691
692
693 if (false == pipe_ctx->stream_res.tg->funcs->enable_crtc(pipe_ctx->stream_res.tg)) {
694 BREAK_TO_DEBUGGER();
695 return DC_ERROR_UNEXPECTED;
696 }
697
698
699
700
701
702
703
704
705
706 return DC_OK;
707}
708
709static void reset_back_end_for_pipe(
710 struct dc *dc,
711 struct pipe_ctx *pipe_ctx,
712 struct dc_state *context)
713{
714 int i;
715 DC_LOGGER_INIT(dc->ctx->logger);
716 if (pipe_ctx->stream_res.stream_enc == NULL) {
717 pipe_ctx->stream = NULL;
718 return;
719 }
720
721 if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
722
723 if (!pipe_ctx->stream->dpms_off)
724 core_link_disable_stream(pipe_ctx, FREE_ACQUIRED_RESOURCE);
725 else if (pipe_ctx->stream_res.audio) {
726 dc->hwss.disable_audio_stream(pipe_ctx, FREE_ACQUIRED_RESOURCE);
727 }
728
729 }
730
731
732
733
734
735 if (pipe_ctx->top_pipe == NULL) {
736 pipe_ctx->stream_res.tg->funcs->disable_crtc(pipe_ctx->stream_res.tg);
737
738 pipe_ctx->stream_res.tg->funcs->enable_optc_clock(pipe_ctx->stream_res.tg, false);
739 }
740
741 for (i = 0; i < dc->res_pool->pipe_count; i++)
742 if (&dc->current_state->res_ctx.pipe_ctx[i] == pipe_ctx)
743 break;
744
745 if (i == dc->res_pool->pipe_count)
746 return;
747
748 pipe_ctx->stream = NULL;
749 DC_LOG_DEBUG("Reset back end for pipe %d, tg:%d\n",
750 pipe_ctx->pipe_idx, pipe_ctx->stream_res.tg->inst);
751}
752
753static bool dcn10_hw_wa_force_recovery(struct dc *dc)
754{
755 struct hubp *hubp ;
756 unsigned int i;
757 bool need_recover = true;
758
759 if (!dc->debug.recovery_enabled)
760 return false;
761
762 for (i = 0; i < dc->res_pool->pipe_count; i++) {
763 struct pipe_ctx *pipe_ctx =
764 &dc->current_state->res_ctx.pipe_ctx[i];
765 if (pipe_ctx != NULL) {
766 hubp = pipe_ctx->plane_res.hubp;
767 if (hubp != NULL) {
768 if (hubp->funcs->hubp_get_underflow_status(hubp) != 0) {
769
770 need_recover = true;
771 }
772 }
773 }
774 }
775 if (!need_recover)
776 return false;
777
778
779
780
781
782
783
784
785
786
787 for (i = 0; i < dc->res_pool->pipe_count; i++) {
788 struct pipe_ctx *pipe_ctx =
789 &dc->current_state->res_ctx.pipe_ctx[i];
790 if (pipe_ctx != NULL) {
791 hubp = pipe_ctx->plane_res.hubp;
792
793 if (hubp != NULL)
794 hubp->funcs->set_hubp_blank_en(hubp, true);
795 }
796 }
797
798 hubbub1_soft_reset(dc->res_pool->hubbub, true);
799
800 for (i = 0; i < dc->res_pool->pipe_count; i++) {
801 struct pipe_ctx *pipe_ctx =
802 &dc->current_state->res_ctx.pipe_ctx[i];
803 if (pipe_ctx != NULL) {
804 hubp = pipe_ctx->plane_res.hubp;
805
806 if (hubp != NULL)
807 hubp->funcs->hubp_disable_control(hubp, true);
808 }
809 }
810 for (i = 0; i < dc->res_pool->pipe_count; i++) {
811 struct pipe_ctx *pipe_ctx =
812 &dc->current_state->res_ctx.pipe_ctx[i];
813 if (pipe_ctx != NULL) {
814 hubp = pipe_ctx->plane_res.hubp;
815
816 if (hubp != NULL)
817 hubp->funcs->hubp_disable_control(hubp, true);
818 }
819 }
820
821 hubbub1_soft_reset(dc->res_pool->hubbub, false);
822 for (i = 0; i < dc->res_pool->pipe_count; i++) {
823 struct pipe_ctx *pipe_ctx =
824 &dc->current_state->res_ctx.pipe_ctx[i];
825 if (pipe_ctx != NULL) {
826 hubp = pipe_ctx->plane_res.hubp;
827
828 if (hubp != NULL)
829 hubp->funcs->set_hubp_blank_en(hubp, true);
830 }
831 }
832 return true;
833
834}
835
836
837void dcn10_verify_allow_pstate_change_high(struct dc *dc)
838{
839 static bool should_log_hw_state;
840
841 if (!hubbub1_verify_allow_pstate_change_high(dc->res_pool->hubbub)) {
842 if (should_log_hw_state) {
843 dcn10_log_hw_state(dc);
844 }
845 BREAK_TO_DEBUGGER();
846 if (dcn10_hw_wa_force_recovery(dc)) {
847
848 if (!hubbub1_verify_allow_pstate_change_high(dc->res_pool->hubbub))
849 BREAK_TO_DEBUGGER();
850 }
851 }
852}
853
854
855void hwss1_plane_atomic_disconnect(struct dc *dc, struct pipe_ctx *pipe_ctx)
856{
857 struct hubp *hubp = pipe_ctx->plane_res.hubp;
858 int dpp_id = pipe_ctx->plane_res.dpp->inst;
859 struct mpc *mpc = dc->res_pool->mpc;
860 struct mpc_tree *mpc_tree_params;
861 struct mpcc *mpcc_to_remove = NULL;
862 struct output_pixel_processor *opp = pipe_ctx->stream_res.opp;
863
864 mpc_tree_params = &(opp->mpc_tree_params);
865 mpcc_to_remove = mpc->funcs->get_mpcc_for_dpp(mpc_tree_params, dpp_id);
866
867
868 if (mpcc_to_remove == NULL)
869 return;
870
871 mpc->funcs->remove_mpcc(mpc, mpc_tree_params, mpcc_to_remove);
872 if (opp != NULL)
873 opp->mpcc_disconnect_pending[pipe_ctx->plane_res.mpcc_inst] = true;
874
875 dc->optimized_required = true;
876
877 if (hubp->funcs->hubp_disconnect)
878 hubp->funcs->hubp_disconnect(hubp);
879
880 if (dc->debug.sanity_checks)
881 dcn10_verify_allow_pstate_change_high(dc);
882}
883
884static void plane_atomic_power_down(struct dc *dc, struct pipe_ctx *pipe_ctx)
885{
886 struct dce_hwseq *hws = dc->hwseq;
887 struct dpp *dpp = pipe_ctx->plane_res.dpp;
888 DC_LOGGER_INIT(dc->ctx->logger);
889
890 if (REG(DC_IP_REQUEST_CNTL)) {
891 REG_SET(DC_IP_REQUEST_CNTL, 0,
892 IP_REQUEST_EN, 1);
893 dpp_pg_control(hws, dpp->inst, false);
894 hubp_pg_control(hws, pipe_ctx->plane_res.hubp->inst, false);
895 dpp->funcs->dpp_reset(dpp);
896 REG_SET(DC_IP_REQUEST_CNTL, 0,
897 IP_REQUEST_EN, 0);
898 DC_LOG_DEBUG(
899 "Power gated front end %d\n", pipe_ctx->pipe_idx);
900 }
901}
902
903
904
905
906static void plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx)
907{
908 struct hubp *hubp = pipe_ctx->plane_res.hubp;
909 struct dpp *dpp = pipe_ctx->plane_res.dpp;
910 int opp_id = hubp->opp_id;
911
912 dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, pipe_ctx);
913
914 hubp->funcs->hubp_clk_cntl(hubp, false);
915
916 dpp->funcs->dpp_dppclk_control(dpp, false, false);
917
918 if (opp_id != 0xf && pipe_ctx->stream_res.opp->mpc_tree_params.opp_list == NULL)
919 pipe_ctx->stream_res.opp->funcs->opp_pipe_clock_control(
920 pipe_ctx->stream_res.opp,
921 false);
922
923 hubp->power_gated = true;
924 dc->optimized_required = false;
925
926 plane_atomic_power_down(dc, pipe_ctx);
927
928 pipe_ctx->stream = NULL;
929 memset(&pipe_ctx->stream_res, 0, sizeof(pipe_ctx->stream_res));
930 memset(&pipe_ctx->plane_res, 0, sizeof(pipe_ctx->plane_res));
931 pipe_ctx->top_pipe = NULL;
932 pipe_ctx->bottom_pipe = NULL;
933 pipe_ctx->plane_state = NULL;
934}
935
936static void dcn10_disable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx)
937{
938 DC_LOGGER_INIT(dc->ctx->logger);
939
940 if (!pipe_ctx->plane_res.hubp || pipe_ctx->plane_res.hubp->power_gated)
941 return;
942
943 plane_atomic_disable(dc, pipe_ctx);
944
945 apply_DEGVIDCN10_253_wa(dc);
946
947 DC_LOG_DC("Power down front end %d\n",
948 pipe_ctx->pipe_idx);
949}
950
951static void dcn10_init_hw(struct dc *dc)
952{
953 int i;
954 struct abm *abm = dc->res_pool->abm;
955 struct dmcu *dmcu = dc->res_pool->dmcu;
956 struct dce_hwseq *hws = dc->hwseq;
957 struct dc_bios *dcb = dc->ctx->dc_bios;
958 struct dc_state *context = dc->current_state;
959
960 if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
961 REG_WRITE(REFCLK_CNTL, 0);
962 REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1);
963 REG_WRITE(DIO_MEM_PWR_CTRL, 0);
964
965 if (!dc->debug.disable_clock_gate) {
966
967 REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0);
968
969 REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0);
970
971 REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);
972 }
973
974 enable_power_gating_plane(dc->hwseq, true);
975 } else {
976
977 if (!dcb->funcs->is_accelerated_mode(dcb)) {
978 bios_golden_init(dc);
979 disable_vga(dc->hwseq);
980 }
981
982 for (i = 0; i < dc->link_count; i++) {
983
984
985
986
987 struct dc_link *link = dc->links[i];
988
989 if (link->link_enc->connector.id == CONNECTOR_ID_EDP)
990 dc->hwss.edp_power_control(link, true);
991
992 link->link_enc->funcs->hw_init(link->link_enc);
993 }
994 }
995
996 for (i = 0; i < dc->res_pool->pipe_count; i++) {
997 struct timing_generator *tg = dc->res_pool->timing_generators[i];
998
999 if (tg->funcs->is_tg_enabled(tg))
1000 tg->funcs->lock(tg);
1001 }
1002
1003
1004
1005
1006 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1007 struct timing_generator *tg = dc->res_pool->timing_generators[i];
1008
1009 if (tg->funcs->is_tg_enabled(tg)) {
1010 tg->funcs->set_blank(tg, true);
1011 hwss_wait_for_blank_complete(tg);
1012 }
1013 }
1014
1015
1016 dc->res_pool->mpc->funcs->mpc_init(dc->res_pool->mpc);
1017
1018 for (i = 0; i < dc->res_pool->timing_generator_count; i++) {
1019 struct timing_generator *tg = dc->res_pool->timing_generators[i];
1020 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1021 struct hubp *hubp = dc->res_pool->hubps[i];
1022 struct dpp *dpp = dc->res_pool->dpps[i];
1023
1024 pipe_ctx->stream_res.tg = tg;
1025 pipe_ctx->pipe_idx = i;
1026
1027 pipe_ctx->plane_res.hubp = hubp;
1028 pipe_ctx->plane_res.dpp = dpp;
1029 pipe_ctx->plane_res.mpcc_inst = dpp->inst;
1030 hubp->mpcc_id = dpp->inst;
1031 hubp->opp_id = 0xf;
1032 hubp->power_gated = false;
1033
1034 dc->res_pool->opps[i]->mpc_tree_params.opp_id = dc->res_pool->opps[i]->inst;
1035 dc->res_pool->opps[i]->mpc_tree_params.opp_list = NULL;
1036 dc->res_pool->opps[i]->mpcc_disconnect_pending[pipe_ctx->plane_res.mpcc_inst] = true;
1037 pipe_ctx->stream_res.opp = dc->res_pool->opps[i];
1038
1039 hwss1_plane_atomic_disconnect(dc, pipe_ctx);
1040 }
1041
1042 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1043 struct timing_generator *tg = dc->res_pool->timing_generators[i];
1044
1045 if (tg->funcs->is_tg_enabled(tg))
1046 tg->funcs->unlock(tg);
1047 }
1048
1049 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1050 struct timing_generator *tg = dc->res_pool->timing_generators[i];
1051 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1052
1053 dcn10_disable_plane(dc, pipe_ctx);
1054
1055 pipe_ctx->stream_res.tg = NULL;
1056 pipe_ctx->plane_res.hubp = NULL;
1057
1058 tg->funcs->tg_init(tg);
1059 }
1060
1061
1062 if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment))
1063 return;
1064
1065 for (i = 0; i < dc->res_pool->audio_count; i++) {
1066 struct audio *audio = dc->res_pool->audios[i];
1067
1068 audio->funcs->hw_init(audio);
1069 }
1070
1071 if (abm != NULL) {
1072 abm->funcs->init_backlight(abm);
1073 abm->funcs->abm_init(abm);
1074 }
1075
1076 if (dmcu != NULL)
1077 dmcu->funcs->dmcu_init(dmcu);
1078
1079
1080 REG_WRITE(DIO_MEM_PWR_CTRL, 0);
1081
1082 if (!dc->debug.disable_clock_gate) {
1083
1084 REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0);
1085
1086 REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0);
1087
1088 REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);
1089 }
1090
1091 enable_power_gating_plane(dc->hwseq, true);
1092
1093 memset(&dc->res_pool->dccg->clks, 0, sizeof(dc->res_pool->dccg->clks));
1094}
1095
1096static void reset_hw_ctx_wrap(
1097 struct dc *dc,
1098 struct dc_state *context)
1099{
1100 int i;
1101
1102
1103 for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) {
1104 struct pipe_ctx *pipe_ctx_old =
1105 &dc->current_state->res_ctx.pipe_ctx[i];
1106 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1107
1108 if (!pipe_ctx_old->stream)
1109 continue;
1110
1111 if (pipe_ctx_old->top_pipe)
1112 continue;
1113
1114 if (!pipe_ctx->stream ||
1115 pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) {
1116 struct clock_source *old_clk = pipe_ctx_old->clock_source;
1117
1118 reset_back_end_for_pipe(dc, pipe_ctx_old, dc->current_state);
1119 if (old_clk)
1120 old_clk->funcs->cs_power_down(old_clk);
1121 }
1122 }
1123
1124}
1125
1126static bool patch_address_for_sbs_tb_stereo(
1127 struct pipe_ctx *pipe_ctx, PHYSICAL_ADDRESS_LOC *addr)
1128{
1129 struct dc_plane_state *plane_state = pipe_ctx->plane_state;
1130 bool sec_split = pipe_ctx->top_pipe &&
1131 pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state;
1132 if (sec_split && plane_state->address.type == PLN_ADDR_TYPE_GRPH_STEREO &&
1133 (pipe_ctx->stream->timing.timing_3d_format ==
1134 TIMING_3D_FORMAT_SIDE_BY_SIDE ||
1135 pipe_ctx->stream->timing.timing_3d_format ==
1136 TIMING_3D_FORMAT_TOP_AND_BOTTOM)) {
1137 *addr = plane_state->address.grph_stereo.left_addr;
1138 plane_state->address.grph_stereo.left_addr =
1139 plane_state->address.grph_stereo.right_addr;
1140 return true;
1141 } else {
1142 if (pipe_ctx->stream->view_format != VIEW_3D_FORMAT_NONE &&
1143 plane_state->address.type != PLN_ADDR_TYPE_GRPH_STEREO) {
1144 plane_state->address.type = PLN_ADDR_TYPE_GRPH_STEREO;
1145 plane_state->address.grph_stereo.right_addr =
1146 plane_state->address.grph_stereo.left_addr;
1147 }
1148 }
1149 return false;
1150}
1151
1152
1153
1154static void dcn10_update_plane_addr(const struct dc *dc, struct pipe_ctx *pipe_ctx)
1155{
1156 bool addr_patched = false;
1157 PHYSICAL_ADDRESS_LOC addr;
1158 struct dc_plane_state *plane_state = pipe_ctx->plane_state;
1159
1160 if (plane_state == NULL)
1161 return;
1162
1163 addr_patched = patch_address_for_sbs_tb_stereo(pipe_ctx, &addr);
1164
1165 pipe_ctx->plane_res.hubp->funcs->hubp_program_surface_flip_and_addr(
1166 pipe_ctx->plane_res.hubp,
1167 &plane_state->address,
1168 plane_state->flip_immediate);
1169
1170 plane_state->status.requested_address = plane_state->address;
1171
1172 if (plane_state->flip_immediate)
1173 plane_state->status.current_address = plane_state->address;
1174
1175 if (addr_patched)
1176 pipe_ctx->plane_state->address.grph_stereo.left_addr = addr;
1177}
1178
1179static bool dcn10_set_input_transfer_func(struct pipe_ctx *pipe_ctx,
1180 const struct dc_plane_state *plane_state)
1181{
1182 struct dpp *dpp_base = pipe_ctx->plane_res.dpp;
1183 const struct dc_transfer_func *tf = NULL;
1184 bool result = true;
1185
1186 if (dpp_base == NULL)
1187 return false;
1188
1189 if (plane_state->in_transfer_func)
1190 tf = plane_state->in_transfer_func;
1191
1192 if (plane_state->gamma_correction &&
1193 !plane_state->gamma_correction->is_identity
1194 && dce_use_lut(plane_state->format))
1195 dpp_base->funcs->dpp_program_input_lut(dpp_base, plane_state->gamma_correction);
1196
1197 if (tf == NULL)
1198 dpp_base->funcs->dpp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_BYPASS);
1199 else if (tf->type == TF_TYPE_PREDEFINED) {
1200 switch (tf->tf) {
1201 case TRANSFER_FUNCTION_SRGB:
1202 dpp_base->funcs->dpp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_HW_sRGB);
1203 break;
1204 case TRANSFER_FUNCTION_BT709:
1205 dpp_base->funcs->dpp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_HW_xvYCC);
1206 break;
1207 case TRANSFER_FUNCTION_LINEAR:
1208 dpp_base->funcs->dpp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_BYPASS);
1209 break;
1210 case TRANSFER_FUNCTION_PQ:
1211 default:
1212 result = false;
1213 break;
1214 }
1215 } else if (tf->type == TF_TYPE_BYPASS) {
1216 dpp_base->funcs->dpp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_BYPASS);
1217 } else {
1218 cm_helper_translate_curve_to_degamma_hw_format(tf,
1219 &dpp_base->degamma_params);
1220 dpp_base->funcs->dpp_program_degamma_pwl(dpp_base,
1221 &dpp_base->degamma_params);
1222 result = true;
1223 }
1224
1225 return result;
1226}
1227
1228
1229
1230
1231
1232static bool
1233dcn10_set_output_transfer_func(struct pipe_ctx *pipe_ctx,
1234 const struct dc_stream_state *stream)
1235{
1236 struct dpp *dpp = pipe_ctx->plane_res.dpp;
1237
1238 if (dpp == NULL)
1239 return false;
1240
1241 dpp->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM;
1242
1243 if (stream->out_transfer_func &&
1244 stream->out_transfer_func->type == TF_TYPE_PREDEFINED &&
1245 stream->out_transfer_func->tf == TRANSFER_FUNCTION_SRGB)
1246 dpp->funcs->dpp_program_regamma_pwl(dpp, NULL, OPP_REGAMMA_SRGB);
1247
1248
1249
1250
1251 else if (cm_helper_translate_curve_to_hw_format(
1252 stream->out_transfer_func,
1253 &dpp->regamma_params, false)) {
1254 dpp->funcs->dpp_program_regamma_pwl(
1255 dpp,
1256 &dpp->regamma_params, OPP_REGAMMA_USER);
1257 } else
1258 dpp->funcs->dpp_program_regamma_pwl(dpp, NULL, OPP_REGAMMA_BYPASS);
1259
1260 return true;
1261}
1262
1263static void dcn10_pipe_control_lock(
1264 struct dc *dc,
1265 struct pipe_ctx *pipe,
1266 bool lock)
1267{
1268
1269
1270
1271 if (pipe->top_pipe)
1272 return;
1273
1274 if (dc->debug.sanity_checks)
1275 dcn10_verify_allow_pstate_change_high(dc);
1276
1277 if (lock)
1278 pipe->stream_res.tg->funcs->lock(pipe->stream_res.tg);
1279 else
1280 pipe->stream_res.tg->funcs->unlock(pipe->stream_res.tg);
1281
1282 if (dc->debug.sanity_checks)
1283 dcn10_verify_allow_pstate_change_high(dc);
1284}
1285
1286static bool wait_for_reset_trigger_to_occur(
1287 struct dc_context *dc_ctx,
1288 struct timing_generator *tg)
1289{
1290 bool rc = false;
1291
1292
1293
1294 const uint32_t frames_to_wait_on_triggered_reset = 10;
1295 int i;
1296
1297 for (i = 0; i < frames_to_wait_on_triggered_reset; i++) {
1298
1299 if (!tg->funcs->is_counter_moving(tg)) {
1300 DC_ERROR("TG counter is not moving!\n");
1301 break;
1302 }
1303
1304 if (tg->funcs->did_triggered_reset_occur(tg)) {
1305 rc = true;
1306
1307 DC_SYNC_INFO("GSL: reset occurred at wait count: %d\n",
1308 i);
1309 break;
1310 }
1311
1312
1313 tg->funcs->wait_for_state(tg, CRTC_STATE_VACTIVE);
1314 tg->funcs->wait_for_state(tg, CRTC_STATE_VBLANK);
1315 }
1316
1317 if (false == rc)
1318 DC_ERROR("GSL: Timeout on reset trigger!\n");
1319
1320 return rc;
1321}
1322
1323static void dcn10_enable_timing_synchronization(
1324 struct dc *dc,
1325 int group_index,
1326 int group_size,
1327 struct pipe_ctx *grouped_pipes[])
1328{
1329 struct dc_context *dc_ctx = dc->ctx;
1330 int i;
1331
1332 DC_SYNC_INFO("Setting up OTG reset trigger\n");
1333
1334 for (i = 1; i < group_size; i++)
1335 grouped_pipes[i]->stream_res.tg->funcs->enable_reset_trigger(
1336 grouped_pipes[i]->stream_res.tg,
1337 grouped_pipes[0]->stream_res.tg->inst);
1338
1339 DC_SYNC_INFO("Waiting for trigger\n");
1340
1341
1342
1343
1344
1345 wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[1]->stream_res.tg);
1346 for (i = 1; i < group_size; i++)
1347 grouped_pipes[i]->stream_res.tg->funcs->disable_reset_trigger(
1348 grouped_pipes[i]->stream_res.tg);
1349
1350 DC_SYNC_INFO("Sync complete\n");
1351}
1352
1353static void dcn10_enable_per_frame_crtc_position_reset(
1354 struct dc *dc,
1355 int group_size,
1356 struct pipe_ctx *grouped_pipes[])
1357{
1358 struct dc_context *dc_ctx = dc->ctx;
1359 int i;
1360
1361 DC_SYNC_INFO("Setting up\n");
1362 for (i = 0; i < group_size; i++)
1363 if (grouped_pipes[i]->stream_res.tg->funcs->enable_crtc_reset)
1364 grouped_pipes[i]->stream_res.tg->funcs->enable_crtc_reset(
1365 grouped_pipes[i]->stream_res.tg,
1366 grouped_pipes[i]->stream->triggered_crtc_reset.event_source->status.primary_otg_inst,
1367 &grouped_pipes[i]->stream->triggered_crtc_reset);
1368
1369 DC_SYNC_INFO("Waiting for trigger\n");
1370
1371 for (i = 0; i < group_size; i++)
1372 wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[i]->stream_res.tg);
1373
1374 DC_SYNC_INFO("Multi-display sync is complete\n");
1375}
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500static void mmhub_read_vm_system_aperture_settings(struct dcn10_hubp *hubp1,
1501 struct vm_system_aperture_param *apt,
1502 struct dce_hwseq *hws)
1503{
1504 PHYSICAL_ADDRESS_LOC physical_page_number;
1505 uint32_t logical_addr_low;
1506 uint32_t logical_addr_high;
1507
1508 REG_GET(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_MSB,
1509 PHYSICAL_PAGE_NUMBER_MSB, &physical_page_number.high_part);
1510 REG_GET(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR_LSB,
1511 PHYSICAL_PAGE_NUMBER_LSB, &physical_page_number.low_part);
1512
1513 REG_GET(MC_VM_SYSTEM_APERTURE_LOW_ADDR,
1514 LOGICAL_ADDR, &logical_addr_low);
1515
1516 REG_GET(MC_VM_SYSTEM_APERTURE_HIGH_ADDR,
1517 LOGICAL_ADDR, &logical_addr_high);
1518
1519 apt->sys_default.quad_part = physical_page_number.quad_part << 12;
1520 apt->sys_low.quad_part = (int64_t)logical_addr_low << 18;
1521 apt->sys_high.quad_part = (int64_t)logical_addr_high << 18;
1522}
1523
1524
1525static void mmhub_read_vm_context0_settings(struct dcn10_hubp *hubp1,
1526 struct vm_context0_param *vm0,
1527 struct dce_hwseq *hws)
1528{
1529 PHYSICAL_ADDRESS_LOC fb_base;
1530 PHYSICAL_ADDRESS_LOC fb_offset;
1531 uint32_t fb_base_value;
1532 uint32_t fb_offset_value;
1533
1534 REG_GET(DCHUBBUB_SDPIF_FB_BASE, SDPIF_FB_BASE, &fb_base_value);
1535 REG_GET(DCHUBBUB_SDPIF_FB_OFFSET, SDPIF_FB_OFFSET, &fb_offset_value);
1536
1537 REG_GET(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32,
1538 PAGE_DIRECTORY_ENTRY_HI32, &vm0->pte_base.high_part);
1539 REG_GET(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_LO32,
1540 PAGE_DIRECTORY_ENTRY_LO32, &vm0->pte_base.low_part);
1541
1542 REG_GET(VM_CONTEXT0_PAGE_TABLE_START_ADDR_HI32,
1543 LOGICAL_PAGE_NUMBER_HI4, &vm0->pte_start.high_part);
1544 REG_GET(VM_CONTEXT0_PAGE_TABLE_START_ADDR_LO32,
1545 LOGICAL_PAGE_NUMBER_LO32, &vm0->pte_start.low_part);
1546
1547 REG_GET(VM_CONTEXT0_PAGE_TABLE_END_ADDR_HI32,
1548 LOGICAL_PAGE_NUMBER_HI4, &vm0->pte_end.high_part);
1549 REG_GET(VM_CONTEXT0_PAGE_TABLE_END_ADDR_LO32,
1550 LOGICAL_PAGE_NUMBER_LO32, &vm0->pte_end.low_part);
1551
1552 REG_GET(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_HI32,
1553 PHYSICAL_PAGE_ADDR_HI4, &vm0->fault_default.high_part);
1554 REG_GET(VM_L2_PROTECTION_FAULT_DEFAULT_ADDR_LO32,
1555 PHYSICAL_PAGE_ADDR_LO32, &vm0->fault_default.low_part);
1556
1557
1558
1559
1560
1561
1562
1563 fb_base.quad_part = (uint64_t)fb_base_value << 24;
1564 fb_offset.quad_part = (uint64_t)fb_offset_value << 24;
1565 vm0->pte_base.quad_part += fb_base.quad_part;
1566 vm0->pte_base.quad_part -= fb_offset.quad_part;
1567}
1568
1569
1570static void dcn10_program_pte_vm(struct dce_hwseq *hws, struct hubp *hubp)
1571{
1572 struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp);
1573 struct vm_system_aperture_param apt = { {{ 0 } } };
1574 struct vm_context0_param vm0 = { { { 0 } } };
1575
1576 mmhub_read_vm_system_aperture_settings(hubp1, &apt, hws);
1577 mmhub_read_vm_context0_settings(hubp1, &vm0, hws);
1578
1579 hubp->funcs->hubp_set_vm_system_aperture_settings(hubp, &apt);
1580 hubp->funcs->hubp_set_vm_context0_settings(hubp, &vm0);
1581}
1582
1583static void dcn10_enable_plane(
1584 struct dc *dc,
1585 struct pipe_ctx *pipe_ctx,
1586 struct dc_state *context)
1587{
1588 struct dce_hwseq *hws = dc->hwseq;
1589
1590 if (dc->debug.sanity_checks) {
1591 dcn10_verify_allow_pstate_change_high(dc);
1592 }
1593
1594 undo_DEGVIDCN10_253_wa(dc);
1595
1596 power_on_plane(dc->hwseq,
1597 pipe_ctx->plane_res.hubp->inst);
1598
1599
1600 pipe_ctx->plane_res.hubp->funcs->hubp_clk_cntl(pipe_ctx->plane_res.hubp, true);
1601
1602
1603 pipe_ctx->stream_res.opp->funcs->opp_pipe_clock_control(
1604 pipe_ctx->stream_res.opp,
1605 true);
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644 if (dc->config.gpu_vm_support)
1645 dcn10_program_pte_vm(hws, pipe_ctx->plane_res.hubp);
1646
1647 if (dc->debug.sanity_checks) {
1648 dcn10_verify_allow_pstate_change_high(dc);
1649 }
1650}
1651
1652static void program_gamut_remap(struct pipe_ctx *pipe_ctx)
1653{
1654 int i = 0;
1655 struct dpp_grph_csc_adjustment adjust;
1656 memset(&adjust, 0, sizeof(adjust));
1657 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS;
1658
1659
1660 if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) {
1661 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW;
1662 for (i = 0; i < CSC_TEMPERATURE_MATRIX_SIZE; i++)
1663 adjust.temperature_matrix[i] =
1664 pipe_ctx->stream->gamut_remap_matrix.matrix[i];
1665 }
1666
1667 pipe_ctx->plane_res.dpp->funcs->dpp_set_gamut_remap(pipe_ctx->plane_res.dpp, &adjust);
1668}
1669
1670
1671static void program_csc_matrix(struct pipe_ctx *pipe_ctx,
1672 enum dc_color_space colorspace,
1673 uint16_t *matrix)
1674{
1675 if (pipe_ctx->stream->csc_color_matrix.enable_adjustment == true) {
1676 if (pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_adjustment != NULL)
1677 pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_adjustment(pipe_ctx->plane_res.dpp, matrix);
1678 } else {
1679 if (pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_default != NULL)
1680 pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_default(pipe_ctx->plane_res.dpp, colorspace);
1681 }
1682}
1683
1684static void dcn10_program_output_csc(struct dc *dc,
1685 struct pipe_ctx *pipe_ctx,
1686 enum dc_color_space colorspace,
1687 uint16_t *matrix,
1688 int opp_id)
1689{
1690 if (pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_adjustment != NULL)
1691 program_csc_matrix(pipe_ctx,
1692 colorspace,
1693 matrix);
1694}
1695
1696static bool is_lower_pipe_tree_visible(struct pipe_ctx *pipe_ctx)
1697{
1698 if (pipe_ctx->plane_state->visible)
1699 return true;
1700 if (pipe_ctx->bottom_pipe && is_lower_pipe_tree_visible(pipe_ctx->bottom_pipe))
1701 return true;
1702 return false;
1703}
1704
1705static bool is_upper_pipe_tree_visible(struct pipe_ctx *pipe_ctx)
1706{
1707 if (pipe_ctx->plane_state->visible)
1708 return true;
1709 if (pipe_ctx->top_pipe && is_upper_pipe_tree_visible(pipe_ctx->top_pipe))
1710 return true;
1711 return false;
1712}
1713
1714static bool is_pipe_tree_visible(struct pipe_ctx *pipe_ctx)
1715{
1716 if (pipe_ctx->plane_state->visible)
1717 return true;
1718 if (pipe_ctx->top_pipe && is_upper_pipe_tree_visible(pipe_ctx->top_pipe))
1719 return true;
1720 if (pipe_ctx->bottom_pipe && is_lower_pipe_tree_visible(pipe_ctx->bottom_pipe))
1721 return true;
1722 return false;
1723}
1724
1725bool is_rgb_cspace(enum dc_color_space output_color_space)
1726{
1727 switch (output_color_space) {
1728 case COLOR_SPACE_SRGB:
1729 case COLOR_SPACE_SRGB_LIMITED:
1730 case COLOR_SPACE_2020_RGB_FULLRANGE:
1731 case COLOR_SPACE_2020_RGB_LIMITEDRANGE:
1732 case COLOR_SPACE_ADOBERGB:
1733 return true;
1734 case COLOR_SPACE_YCBCR601:
1735 case COLOR_SPACE_YCBCR709:
1736 case COLOR_SPACE_YCBCR601_LIMITED:
1737 case COLOR_SPACE_YCBCR709_LIMITED:
1738 case COLOR_SPACE_2020_YCBCR:
1739 return false;
1740 default:
1741
1742 BREAK_TO_DEBUGGER();
1743 return false;
1744 }
1745}
1746
1747static void dcn10_get_surface_visual_confirm_color(
1748 const struct pipe_ctx *pipe_ctx,
1749 struct tg_color *color)
1750{
1751 uint32_t color_value = MAX_TG_COLOR_VALUE;
1752
1753 switch (pipe_ctx->plane_res.scl_data.format) {
1754 case PIXEL_FORMAT_ARGB8888:
1755
1756 color->color_r_cr = color_value;
1757 break;
1758
1759 case PIXEL_FORMAT_ARGB2101010:
1760
1761 color->color_b_cb = color_value;
1762 break;
1763 case PIXEL_FORMAT_420BPP8:
1764
1765 color->color_g_y = color_value;
1766 break;
1767 case PIXEL_FORMAT_420BPP10:
1768
1769 color->color_g_y = color_value;
1770 color->color_r_cr = color_value;
1771 break;
1772 case PIXEL_FORMAT_FP16:
1773
1774 color->color_r_cr = color_value;
1775 color->color_b_cb = color_value;
1776 color->color_g_y = color_value;
1777 break;
1778 default:
1779 break;
1780 }
1781}
1782
1783static void dcn10_get_hdr_visual_confirm_color(
1784 struct pipe_ctx *pipe_ctx,
1785 struct tg_color *color)
1786{
1787 uint32_t color_value = MAX_TG_COLOR_VALUE;
1788
1789
1790 struct pipe_ctx *top_pipe_ctx = pipe_ctx;
1791
1792 while (top_pipe_ctx->top_pipe != NULL)
1793 top_pipe_ctx = top_pipe_ctx->top_pipe;
1794
1795 switch (top_pipe_ctx->plane_res.scl_data.format) {
1796 case PIXEL_FORMAT_ARGB2101010:
1797 if (top_pipe_ctx->stream->out_transfer_func->tf == TRANSFER_FUNCTION_UNITY) {
1798
1799 color->color_r_cr = color_value;
1800 }
1801 break;
1802 case PIXEL_FORMAT_FP16:
1803 if (top_pipe_ctx->stream->out_transfer_func->tf == TRANSFER_FUNCTION_PQ) {
1804
1805 color->color_b_cb = color_value;
1806 } else if (top_pipe_ctx->stream->out_transfer_func->tf == TRANSFER_FUNCTION_GAMMA22) {
1807
1808 color->color_g_y = color_value;
1809 }
1810 break;
1811 default:
1812
1813 color->color_r_cr = color_value/2;
1814 color->color_b_cb = color_value/2;
1815 color->color_g_y = color_value/2;
1816 break;
1817 }
1818}
1819
1820static uint16_t fixed_point_to_int_frac(
1821 struct fixed31_32 arg,
1822 uint8_t integer_bits,
1823 uint8_t fractional_bits)
1824{
1825 int32_t numerator;
1826 int32_t divisor = 1 << fractional_bits;
1827
1828 uint16_t result;
1829
1830 uint16_t d = (uint16_t)dc_fixpt_floor(
1831 dc_fixpt_abs(
1832 arg));
1833
1834 if (d <= (uint16_t)(1 << integer_bits) - (1 / (uint16_t)divisor))
1835 numerator = (uint16_t)dc_fixpt_floor(
1836 dc_fixpt_mul_int(
1837 arg,
1838 divisor));
1839 else {
1840 numerator = dc_fixpt_floor(
1841 dc_fixpt_sub(
1842 dc_fixpt_from_int(
1843 1LL << integer_bits),
1844 dc_fixpt_recip(
1845 dc_fixpt_from_int(
1846 divisor))));
1847 }
1848
1849 if (numerator >= 0)
1850 result = (uint16_t)numerator;
1851 else
1852 result = (uint16_t)(
1853 (1 << (integer_bits + fractional_bits + 1)) + numerator);
1854
1855 if ((result != 0) && dc_fixpt_lt(
1856 arg, dc_fixpt_zero))
1857 result |= 1 << (integer_bits + fractional_bits);
1858
1859 return result;
1860}
1861
1862void build_prescale_params(struct dc_bias_and_scale *bias_and_scale,
1863 const struct dc_plane_state *plane_state)
1864{
1865 if (plane_state->format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN
1866 && plane_state->format != SURFACE_PIXEL_FORMAT_INVALID
1867 && plane_state->input_csc_color_matrix.enable_adjustment
1868 && plane_state->coeff_reduction_factor.value != 0) {
1869 bias_and_scale->scale_blue = fixed_point_to_int_frac(
1870 dc_fixpt_mul(plane_state->coeff_reduction_factor,
1871 dc_fixpt_from_fraction(256, 255)),
1872 2,
1873 13);
1874 bias_and_scale->scale_red = bias_and_scale->scale_blue;
1875 bias_and_scale->scale_green = bias_and_scale->scale_blue;
1876 } else {
1877 bias_and_scale->scale_blue = 0x2000;
1878 bias_and_scale->scale_red = 0x2000;
1879 bias_and_scale->scale_green = 0x2000;
1880 }
1881}
1882
1883static void update_dpp(struct dpp *dpp, struct dc_plane_state *plane_state)
1884{
1885 struct dc_bias_and_scale bns_params = {0};
1886
1887
1888 dpp->funcs->dpp_setup(dpp,
1889 plane_state->format,
1890 EXPANSION_MODE_ZERO,
1891 plane_state->input_csc_color_matrix,
1892 COLOR_SPACE_YCBCR601_LIMITED);
1893
1894
1895 build_prescale_params(&bns_params, plane_state);
1896 if (dpp->funcs->dpp_program_bias_and_scale)
1897 dpp->funcs->dpp_program_bias_and_scale(dpp, &bns_params);
1898}
1899
1900static void dcn10_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx)
1901{
1902 struct hubp *hubp = pipe_ctx->plane_res.hubp;
1903 struct mpcc_blnd_cfg blnd_cfg = {0};
1904 bool per_pixel_alpha = pipe_ctx->plane_state->per_pixel_alpha && pipe_ctx->bottom_pipe;
1905 int mpcc_id;
1906 struct mpcc *new_mpcc;
1907 struct mpc *mpc = dc->res_pool->mpc;
1908 struct mpc_tree *mpc_tree_params = &(pipe_ctx->stream_res.opp->mpc_tree_params);
1909
1910
1911
1912
1913
1914 if (dc->debug.visual_confirm == VISUAL_CONFIRM_HDR) {
1915 dcn10_get_hdr_visual_confirm_color(
1916 pipe_ctx, &blnd_cfg.black_color);
1917 } else if (dc->debug.visual_confirm == VISUAL_CONFIRM_SURFACE) {
1918 dcn10_get_surface_visual_confirm_color(
1919 pipe_ctx, &blnd_cfg.black_color);
1920 } else {
1921 color_space_to_black_color(
1922 dc, pipe_ctx->stream->output_color_space,
1923 &blnd_cfg.black_color);
1924 }
1925
1926 if (per_pixel_alpha)
1927 blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA;
1928 else
1929 blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_GLOBAL_ALPHA;
1930
1931 blnd_cfg.overlap_only = false;
1932 blnd_cfg.global_alpha = 0xff;
1933 blnd_cfg.global_gain = 0xff;
1934
1935
1936
1937
1938 blnd_cfg.pre_multiplied_alpha = is_rgb_cspace(
1939 pipe_ctx->stream->output_color_space)
1940 && per_pixel_alpha;
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951 mpcc_id = hubp->inst;
1952
1953
1954 if (!pipe_ctx->plane_state->update_flags.bits.full_update) {
1955 mpc->funcs->update_blending(mpc, &blnd_cfg, mpcc_id);
1956 return;
1957 }
1958
1959
1960 new_mpcc = mpc->funcs->get_mpcc_for_dpp(mpc_tree_params, mpcc_id);
1961
1962 if (new_mpcc != NULL)
1963 mpc->funcs->remove_mpcc(mpc, mpc_tree_params, new_mpcc);
1964 else
1965 if (dc->debug.sanity_checks)
1966 mpc->funcs->assert_mpcc_idle_before_connect(
1967 dc->res_pool->mpc, mpcc_id);
1968
1969
1970 new_mpcc = mpc->funcs->insert_plane(dc->res_pool->mpc,
1971 mpc_tree_params,
1972 &blnd_cfg,
1973 NULL,
1974 NULL,
1975 hubp->inst,
1976 mpcc_id);
1977
1978 ASSERT(new_mpcc != NULL);
1979
1980 hubp->opp_id = pipe_ctx->stream_res.opp->inst;
1981 hubp->mpcc_id = mpcc_id;
1982}
1983
1984static void update_scaler(struct pipe_ctx *pipe_ctx)
1985{
1986 bool per_pixel_alpha =
1987 pipe_ctx->plane_state->per_pixel_alpha && pipe_ctx->bottom_pipe;
1988
1989
1990
1991 pipe_ctx->plane_res.scl_data.lb_params.alpha_en = per_pixel_alpha;
1992 pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP;
1993
1994 pipe_ctx->plane_res.dpp->funcs->dpp_set_scaler(
1995 pipe_ctx->plane_res.dpp, &pipe_ctx->plane_res.scl_data);
1996}
1997
1998static void update_dchubp_dpp(
1999 struct dc *dc,
2000 struct pipe_ctx *pipe_ctx,
2001 struct dc_state *context)
2002{
2003 struct hubp *hubp = pipe_ctx->plane_res.hubp;
2004 struct dpp *dpp = pipe_ctx->plane_res.dpp;
2005 struct dc_plane_state *plane_state = pipe_ctx->plane_state;
2006 union plane_size size = plane_state->plane_size;
2007
2008
2009
2010
2011
2012 if (plane_state->update_flags.bits.full_update) {
2013 bool should_divided_by_2 = context->bw.dcn.clk.dppclk_khz <=
2014 dc->res_pool->dccg->clks.dispclk_khz / 2;
2015
2016 dpp->funcs->dpp_dppclk_control(
2017 dpp,
2018 should_divided_by_2,
2019 true);
2020
2021 dc->res_pool->dccg->clks.dppclk_khz = should_divided_by_2 ?
2022 dc->res_pool->dccg->clks.dispclk_khz / 2 :
2023 dc->res_pool->dccg->clks.dispclk_khz;
2024 }
2025
2026
2027
2028
2029
2030 if (plane_state->update_flags.bits.full_update) {
2031 hubp->funcs->hubp_vtg_sel(hubp, pipe_ctx->stream_res.tg->inst);
2032
2033 hubp->funcs->hubp_setup(
2034 hubp,
2035 &pipe_ctx->dlg_regs,
2036 &pipe_ctx->ttu_regs,
2037 &pipe_ctx->rq_regs,
2038 &pipe_ctx->pipe_dlg_param);
2039 }
2040
2041 size.grph.surface_size = pipe_ctx->plane_res.scl_data.viewport;
2042
2043 if (plane_state->update_flags.bits.full_update ||
2044 plane_state->update_flags.bits.bpp_change)
2045 update_dpp(dpp, plane_state);
2046
2047 if (plane_state->update_flags.bits.full_update ||
2048 plane_state->update_flags.bits.per_pixel_alpha_change)
2049 dc->hwss.update_mpcc(dc, pipe_ctx);
2050
2051 if (plane_state->update_flags.bits.full_update ||
2052 plane_state->update_flags.bits.per_pixel_alpha_change ||
2053 plane_state->update_flags.bits.scaling_change ||
2054 plane_state->update_flags.bits.position_change) {
2055 update_scaler(pipe_ctx);
2056 }
2057
2058 if (plane_state->update_flags.bits.full_update ||
2059 plane_state->update_flags.bits.scaling_change ||
2060 plane_state->update_flags.bits.position_change) {
2061 hubp->funcs->mem_program_viewport(
2062 hubp,
2063 &pipe_ctx->plane_res.scl_data.viewport,
2064 &pipe_ctx->plane_res.scl_data.viewport_c);
2065 }
2066
2067 if (pipe_ctx->stream->cursor_attributes.address.quad_part != 0) {
2068 dc->hwss.set_cursor_position(pipe_ctx);
2069 dc->hwss.set_cursor_attribute(pipe_ctx);
2070 }
2071
2072 if (plane_state->update_flags.bits.full_update) {
2073
2074 program_gamut_remap(pipe_ctx);
2075
2076 dc->hwss.program_output_csc(dc,
2077 pipe_ctx,
2078 pipe_ctx->stream->output_color_space,
2079 pipe_ctx->stream->csc_color_matrix.matrix,
2080 hubp->opp_id);
2081 }
2082
2083 if (plane_state->update_flags.bits.full_update ||
2084 plane_state->update_flags.bits.pixel_format_change ||
2085 plane_state->update_flags.bits.horizontal_mirror_change ||
2086 plane_state->update_flags.bits.rotation_change ||
2087 plane_state->update_flags.bits.swizzle_change ||
2088 plane_state->update_flags.bits.dcc_change ||
2089 plane_state->update_flags.bits.bpp_change ||
2090 plane_state->update_flags.bits.scaling_change) {
2091 hubp->funcs->hubp_program_surface_config(
2092 hubp,
2093 plane_state->format,
2094 &plane_state->tiling_info,
2095 &size,
2096 plane_state->rotation,
2097 &plane_state->dcc,
2098 plane_state->horizontal_mirror);
2099 }
2100
2101 hubp->power_gated = false;
2102
2103 dc->hwss.update_plane_addr(dc, pipe_ctx);
2104
2105 if (is_pipe_tree_visible(pipe_ctx))
2106 hubp->funcs->set_blank(hubp, false);
2107}
2108
2109static void dcn10_blank_pixel_data(
2110 struct dc *dc,
2111 struct pipe_ctx *pipe_ctx,
2112 bool blank)
2113{
2114 enum dc_color_space color_space;
2115 struct tg_color black_color = {0};
2116 struct stream_resource *stream_res = &pipe_ctx->stream_res;
2117 struct dc_stream_state *stream = pipe_ctx->stream;
2118
2119
2120 color_space = stream->output_color_space;
2121 color_space_to_black_color(dc, color_space, &black_color);
2122
2123 if (stream_res->tg->funcs->set_blank_color)
2124 stream_res->tg->funcs->set_blank_color(
2125 stream_res->tg,
2126 &black_color);
2127
2128 if (!blank) {
2129 if (stream_res->tg->funcs->set_blank)
2130 stream_res->tg->funcs->set_blank(stream_res->tg, blank);
2131 if (stream_res->abm)
2132 stream_res->abm->funcs->set_abm_level(stream_res->abm, stream->abm_level);
2133 } else if (blank) {
2134 if (stream_res->abm)
2135 stream_res->abm->funcs->set_abm_immediate_disable(stream_res->abm);
2136 if (stream_res->tg->funcs->set_blank)
2137 stream_res->tg->funcs->set_blank(stream_res->tg, blank);
2138 }
2139}
2140
2141static void set_hdr_multiplier(struct pipe_ctx *pipe_ctx)
2142{
2143 struct fixed31_32 multiplier = dc_fixpt_from_fraction(
2144 pipe_ctx->plane_state->sdr_white_level, 80);
2145 uint32_t hw_mult = 0x1f000;
2146 struct custom_float_format fmt;
2147
2148 fmt.exponenta_bits = 6;
2149 fmt.mantissa_bits = 12;
2150 fmt.sign = true;
2151
2152 if (pipe_ctx->plane_state->sdr_white_level > 80)
2153 convert_to_custom_float_format(multiplier, &fmt, &hw_mult);
2154
2155 pipe_ctx->plane_res.dpp->funcs->dpp_set_hdr_multiplier(
2156 pipe_ctx->plane_res.dpp, hw_mult);
2157}
2158
2159void dcn10_program_pipe(
2160 struct dc *dc,
2161 struct pipe_ctx *pipe_ctx,
2162 struct dc_state *context)
2163{
2164 if (pipe_ctx->plane_state->update_flags.bits.full_update)
2165 dcn10_enable_plane(dc, pipe_ctx, context);
2166
2167 update_dchubp_dpp(dc, pipe_ctx, context);
2168
2169 set_hdr_multiplier(pipe_ctx);
2170
2171 if (pipe_ctx->plane_state->update_flags.bits.full_update ||
2172 pipe_ctx->plane_state->update_flags.bits.in_transfer_func_change ||
2173 pipe_ctx->plane_state->update_flags.bits.gamma_change)
2174 dc->hwss.set_input_transfer_func(pipe_ctx, pipe_ctx->plane_state);
2175
2176
2177
2178
2179
2180
2181
2182 if (pipe_ctx->plane_state->update_flags.bits.full_update)
2183 dc->hwss.set_output_transfer_func(pipe_ctx, pipe_ctx->stream);
2184}
2185
2186static void program_all_pipe_in_tree(
2187 struct dc *dc,
2188 struct pipe_ctx *pipe_ctx,
2189 struct dc_state *context)
2190{
2191 if (pipe_ctx->top_pipe == NULL) {
2192 bool blank = !is_pipe_tree_visible(pipe_ctx);
2193
2194 pipe_ctx->stream_res.tg->dlg_otg_param.vready_offset = pipe_ctx->pipe_dlg_param.vready_offset;
2195 pipe_ctx->stream_res.tg->dlg_otg_param.vstartup_start = pipe_ctx->pipe_dlg_param.vstartup_start;
2196 pipe_ctx->stream_res.tg->dlg_otg_param.vupdate_offset = pipe_ctx->pipe_dlg_param.vupdate_offset;
2197 pipe_ctx->stream_res.tg->dlg_otg_param.vupdate_width = pipe_ctx->pipe_dlg_param.vupdate_width;
2198 pipe_ctx->stream_res.tg->dlg_otg_param.signal = pipe_ctx->stream->signal;
2199
2200 pipe_ctx->stream_res.tg->funcs->program_global_sync(
2201 pipe_ctx->stream_res.tg);
2202
2203 dc->hwss.blank_pixel_data(dc, pipe_ctx, blank);
2204
2205 }
2206
2207 if (pipe_ctx->plane_state != NULL) {
2208 dcn10_program_pipe(dc, pipe_ctx, context);
2209 }
2210
2211 if (pipe_ctx->bottom_pipe != NULL && pipe_ctx->bottom_pipe != pipe_ctx) {
2212 program_all_pipe_in_tree(dc, pipe_ctx->bottom_pipe, context);
2213 }
2214}
2215
2216static void dcn10_pplib_apply_display_requirements(
2217 struct dc *dc,
2218 struct dc_state *context)
2219{
2220 struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg;
2221
2222 pp_display_cfg->min_engine_clock_khz = dc->res_pool->dccg->clks.dcfclk_khz;
2223 pp_display_cfg->min_memory_clock_khz = dc->res_pool->dccg->clks.fclk_khz;
2224 pp_display_cfg->min_engine_clock_deep_sleep_khz = dc->res_pool->dccg->clks.dcfclk_deep_sleep_khz;
2225 pp_display_cfg->min_dcfc_deep_sleep_clock_khz = dc->res_pool->dccg->clks.dcfclk_deep_sleep_khz;
2226 pp_display_cfg->min_dcfclock_khz = dc->res_pool->dccg->clks.dcfclk_khz;
2227 pp_display_cfg->disp_clk_khz = dc->res_pool->dccg->clks.dispclk_khz;
2228 dce110_fill_display_configs(context, pp_display_cfg);
2229
2230 if (memcmp(&dc->prev_display_config, pp_display_cfg, sizeof(
2231 struct dm_pp_display_configuration)) != 0)
2232 dm_pp_apply_display_requirements(dc->ctx, pp_display_cfg);
2233
2234 dc->prev_display_config = *pp_display_cfg;
2235}
2236
2237static void optimize_shared_resources(struct dc *dc)
2238{
2239 if (dc->current_state->stream_count == 0) {
2240
2241 dcn10_pplib_apply_display_requirements(dc, dc->current_state);
2242 }
2243
2244 if (dc->debug.pplib_wm_report_mode == WM_REPORT_OVERRIDE)
2245 dcn_bw_notify_pplib_of_wm_ranges(dc);
2246}
2247
2248static void ready_shared_resources(struct dc *dc, struct dc_state *context)
2249{
2250
2251 if (dc->current_state->stream_count == 0 &&
2252 context->stream_count != 0)
2253 dcn10_pplib_apply_display_requirements(dc, context);
2254}
2255
2256static struct pipe_ctx *find_top_pipe_for_stream(
2257 struct dc *dc,
2258 struct dc_state *context,
2259 const struct dc_stream_state *stream)
2260{
2261 int i;
2262
2263 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2264 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2265 struct pipe_ctx *old_pipe_ctx =
2266 &dc->current_state->res_ctx.pipe_ctx[i];
2267
2268 if (!pipe_ctx->plane_state && !old_pipe_ctx->plane_state)
2269 continue;
2270
2271 if (pipe_ctx->stream != stream)
2272 continue;
2273
2274 if (!pipe_ctx->top_pipe)
2275 return pipe_ctx;
2276 }
2277 return NULL;
2278}
2279
2280static void dcn10_apply_ctx_for_surface(
2281 struct dc *dc,
2282 const struct dc_stream_state *stream,
2283 int num_planes,
2284 struct dc_state *context)
2285{
2286 int i;
2287 struct timing_generator *tg;
2288 bool removed_pipe[4] = { false };
2289 struct pipe_ctx *top_pipe_to_program =
2290 find_top_pipe_for_stream(dc, context, stream);
2291 DC_LOGGER_INIT(dc->ctx->logger);
2292
2293 if (!top_pipe_to_program)
2294 return;
2295
2296 tg = top_pipe_to_program->stream_res.tg;
2297
2298 dcn10_pipe_control_lock(dc, top_pipe_to_program, true);
2299
2300 if (num_planes == 0) {
2301
2302 dc->hwss.blank_pixel_data(dc, top_pipe_to_program, true);
2303 }
2304
2305
2306 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2307 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2308 struct pipe_ctx *old_pipe_ctx =
2309 &dc->current_state->res_ctx.pipe_ctx[i];
2310
2311
2312
2313
2314
2315
2316 if (pipe_ctx->plane_state && !old_pipe_ctx->plane_state) {
2317 if (old_pipe_ctx->stream_res.tg == tg &&
2318 old_pipe_ctx->plane_res.hubp &&
2319 old_pipe_ctx->plane_res.hubp->opp_id != 0xf) {
2320 dcn10_disable_plane(dc, old_pipe_ctx);
2321
2322
2323
2324
2325 pipe_ctx->stream_res.tg->funcs->lock(pipe_ctx->stream_res.tg);
2326 }
2327 }
2328
2329 if (!pipe_ctx->plane_state &&
2330 old_pipe_ctx->plane_state &&
2331 old_pipe_ctx->stream_res.tg == tg) {
2332
2333 dc->hwss.plane_atomic_disconnect(dc, old_pipe_ctx);
2334 removed_pipe[i] = true;
2335
2336 DC_LOG_DC("Reset mpcc for pipe %d\n",
2337 old_pipe_ctx->pipe_idx);
2338 }
2339 }
2340
2341 if (num_planes > 0)
2342 program_all_pipe_in_tree(dc, top_pipe_to_program, context);
2343
2344 dcn10_pipe_control_lock(dc, top_pipe_to_program, false);
2345
2346 if (num_planes == 0)
2347 false_optc_underflow_wa(dc, stream, tg);
2348
2349 for (i = 0; i < dc->res_pool->pipe_count; i++)
2350 if (removed_pipe[i])
2351 dcn10_disable_plane(dc, &dc->current_state->res_ctx.pipe_ctx[i]);
2352
2353 if (dc->hwseq->wa.DEGVIDCN10_254)
2354 hubbub1_wm_change_req_wa(dc->res_pool->hubbub);
2355}
2356
2357static void dcn10_set_bandwidth(
2358 struct dc *dc,
2359 struct dc_state *context,
2360 bool safe_to_lower)
2361{
2362 if (dc->debug.sanity_checks)
2363 dcn10_verify_allow_pstate_change_high(dc);
2364
2365 if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
2366 if (context->stream_count == 0)
2367 context->bw.dcn.clk.phyclk_khz = 0;
2368
2369 dc->res_pool->dccg->funcs->update_clocks(
2370 dc->res_pool->dccg,
2371 &context->bw.dcn.clk,
2372 safe_to_lower);
2373
2374 dcn10_pplib_apply_display_requirements(dc, context);
2375 }
2376
2377 hubbub1_program_watermarks(dc->res_pool->hubbub,
2378 &context->bw.dcn.watermarks,
2379 dc->res_pool->ref_clock_inKhz / 1000,
2380 true);
2381
2382 if (dc->debug.sanity_checks)
2383 dcn10_verify_allow_pstate_change_high(dc);
2384}
2385
2386static void set_drr(struct pipe_ctx **pipe_ctx,
2387 int num_pipes, int vmin, int vmax)
2388{
2389 int i = 0;
2390 struct drr_params params = {0};
2391
2392 params.vertical_total_max = vmax;
2393 params.vertical_total_min = vmin;
2394
2395
2396
2397
2398 for (i = 0; i < num_pipes; i++) {
2399 pipe_ctx[i]->stream_res.tg->funcs->set_drr(pipe_ctx[i]->stream_res.tg, ¶ms);
2400 }
2401}
2402
2403static void get_position(struct pipe_ctx **pipe_ctx,
2404 int num_pipes,
2405 struct crtc_position *position)
2406{
2407 int i = 0;
2408
2409
2410
2411 for (i = 0; i < num_pipes; i++)
2412 pipe_ctx[i]->stream_res.tg->funcs->get_position(pipe_ctx[i]->stream_res.tg, position);
2413}
2414
2415static void set_static_screen_control(struct pipe_ctx **pipe_ctx,
2416 int num_pipes, const struct dc_static_screen_events *events)
2417{
2418 unsigned int i;
2419 unsigned int value = 0;
2420
2421 if (events->surface_update)
2422 value |= 0x80;
2423 if (events->cursor_update)
2424 value |= 0x2;
2425 if (events->force_trigger)
2426 value |= 0x1;
2427
2428 for (i = 0; i < num_pipes; i++)
2429 pipe_ctx[i]->stream_res.tg->funcs->
2430 set_static_screen_control(pipe_ctx[i]->stream_res.tg, value);
2431}
2432
2433static void dcn10_config_stereo_parameters(
2434 struct dc_stream_state *stream, struct crtc_stereo_flags *flags)
2435{
2436 enum view_3d_format view_format = stream->view_format;
2437 enum dc_timing_3d_format timing_3d_format =\
2438 stream->timing.timing_3d_format;
2439 bool non_stereo_timing = false;
2440
2441 if (timing_3d_format == TIMING_3D_FORMAT_NONE ||
2442 timing_3d_format == TIMING_3D_FORMAT_SIDE_BY_SIDE ||
2443 timing_3d_format == TIMING_3D_FORMAT_TOP_AND_BOTTOM)
2444 non_stereo_timing = true;
2445
2446 if (non_stereo_timing == false &&
2447 view_format == VIEW_3D_FORMAT_FRAME_SEQUENTIAL) {
2448
2449 flags->PROGRAM_STEREO = 1;
2450 flags->PROGRAM_POLARITY = 1;
2451 if (timing_3d_format == TIMING_3D_FORMAT_INBAND_FA ||
2452 timing_3d_format == TIMING_3D_FORMAT_DP_HDMI_INBAND_FA ||
2453 timing_3d_format == TIMING_3D_FORMAT_SIDEBAND_FA) {
2454 enum display_dongle_type dongle = \
2455 stream->sink->link->ddc->dongle_type;
2456 if (dongle == DISPLAY_DONGLE_DP_VGA_CONVERTER ||
2457 dongle == DISPLAY_DONGLE_DP_DVI_CONVERTER ||
2458 dongle == DISPLAY_DONGLE_DP_HDMI_CONVERTER)
2459 flags->DISABLE_STEREO_DP_SYNC = 1;
2460 }
2461 flags->RIGHT_EYE_POLARITY =\
2462 stream->timing.flags.RIGHT_EYE_3D_POLARITY;
2463 if (timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING)
2464 flags->FRAME_PACKED = 1;
2465 }
2466
2467 return;
2468}
2469
2470static void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, struct dc *dc)
2471{
2472 struct crtc_stereo_flags flags = { 0 };
2473 struct dc_stream_state *stream = pipe_ctx->stream;
2474
2475 dcn10_config_stereo_parameters(stream, &flags);
2476
2477 pipe_ctx->stream_res.opp->funcs->opp_program_stereo(
2478 pipe_ctx->stream_res.opp,
2479 flags.PROGRAM_STEREO == 1 ? true:false,
2480 &stream->timing);
2481
2482 pipe_ctx->stream_res.tg->funcs->program_stereo(
2483 pipe_ctx->stream_res.tg,
2484 &stream->timing,
2485 &flags);
2486
2487 return;
2488}
2489
2490static struct hubp *get_hubp_by_inst(struct resource_pool *res_pool, int mpcc_inst)
2491{
2492 int i;
2493
2494 for (i = 0; i < res_pool->pipe_count; i++) {
2495 if (res_pool->hubps[i]->inst == mpcc_inst)
2496 return res_pool->hubps[i];
2497 }
2498 ASSERT(false);
2499 return NULL;
2500}
2501
2502static void dcn10_wait_for_mpcc_disconnect(
2503 struct dc *dc,
2504 struct resource_pool *res_pool,
2505 struct pipe_ctx *pipe_ctx)
2506{
2507 int mpcc_inst;
2508
2509 if (dc->debug.sanity_checks) {
2510 dcn10_verify_allow_pstate_change_high(dc);
2511 }
2512
2513 if (!pipe_ctx->stream_res.opp)
2514 return;
2515
2516 for (mpcc_inst = 0; mpcc_inst < MAX_PIPES; mpcc_inst++) {
2517 if (pipe_ctx->stream_res.opp->mpcc_disconnect_pending[mpcc_inst]) {
2518 struct hubp *hubp = get_hubp_by_inst(res_pool, mpcc_inst);
2519
2520 res_pool->mpc->funcs->wait_for_idle(res_pool->mpc, mpcc_inst);
2521 pipe_ctx->stream_res.opp->mpcc_disconnect_pending[mpcc_inst] = false;
2522 hubp->funcs->set_blank(hubp, true);
2523
2524
2525
2526 }
2527 }
2528
2529 if (dc->debug.sanity_checks) {
2530 dcn10_verify_allow_pstate_change_high(dc);
2531 }
2532
2533}
2534
2535static bool dcn10_dummy_display_power_gating(
2536 struct dc *dc,
2537 uint8_t controller_id,
2538 struct dc_bios *dcb,
2539 enum pipe_gating_control power_gating)
2540{
2541 return true;
2542}
2543
2544static void dcn10_update_pending_status(struct pipe_ctx *pipe_ctx)
2545{
2546 struct dc_plane_state *plane_state = pipe_ctx->plane_state;
2547 struct timing_generator *tg = pipe_ctx->stream_res.tg;
2548 bool flip_pending;
2549
2550 if (plane_state == NULL)
2551 return;
2552
2553 flip_pending = pipe_ctx->plane_res.hubp->funcs->hubp_is_flip_pending(
2554 pipe_ctx->plane_res.hubp);
2555
2556 plane_state->status.is_flip_pending = flip_pending;
2557
2558 if (!flip_pending)
2559 plane_state->status.current_address = plane_state->status.requested_address;
2560
2561 if (plane_state->status.current_address.type == PLN_ADDR_TYPE_GRPH_STEREO &&
2562 tg->funcs->is_stereo_left_eye) {
2563 plane_state->status.is_right_eye =
2564 !tg->funcs->is_stereo_left_eye(pipe_ctx->stream_res.tg);
2565 }
2566}
2567
2568static void dcn10_update_dchub(struct dce_hwseq *hws, struct dchub_init_data *dh_data)
2569{
2570 if (hws->ctx->dc->res_pool->hubbub != NULL) {
2571 struct hubp *hubp = hws->ctx->dc->res_pool->hubps[0];
2572
2573 if (hubp->funcs->hubp_update_dchub)
2574 hubp->funcs->hubp_update_dchub(hubp, dh_data);
2575 else
2576 hubbub1_update_dchub(hws->ctx->dc->res_pool->hubbub, dh_data);
2577 }
2578}
2579
2580static void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx)
2581{
2582 struct dc_cursor_position pos_cpy = pipe_ctx->stream->cursor_position;
2583 struct hubp *hubp = pipe_ctx->plane_res.hubp;
2584 struct dpp *dpp = pipe_ctx->plane_res.dpp;
2585 struct dc_cursor_mi_param param = {
2586 .pixel_clk_khz = pipe_ctx->stream->timing.pix_clk_khz,
2587 .ref_clk_khz = pipe_ctx->stream->ctx->dc->res_pool->ref_clock_inKhz,
2588 .viewport = pipe_ctx->plane_res.scl_data.viewport,
2589 .h_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.horz,
2590 .v_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.vert,
2591 .rotation = pipe_ctx->plane_state->rotation,
2592 .mirror = pipe_ctx->plane_state->horizontal_mirror
2593 };
2594
2595 if (pipe_ctx->plane_state->address.type
2596 == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE)
2597 pos_cpy.enable = false;
2598
2599 if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state)
2600 pos_cpy.enable = false;
2601
2602 hubp->funcs->set_cursor_position(hubp, &pos_cpy, ¶m);
2603 dpp->funcs->set_cursor_position(dpp, &pos_cpy, ¶m, hubp->curs_attr.width);
2604}
2605
2606static void dcn10_set_cursor_attribute(struct pipe_ctx *pipe_ctx)
2607{
2608 struct dc_cursor_attributes *attributes = &pipe_ctx->stream->cursor_attributes;
2609
2610 pipe_ctx->plane_res.hubp->funcs->set_cursor_attributes(
2611 pipe_ctx->plane_res.hubp, attributes);
2612 pipe_ctx->plane_res.dpp->funcs->set_cursor_attributes(
2613 pipe_ctx->plane_res.dpp, attributes->color_format);
2614}
2615
2616static void dcn10_set_cursor_sdr_white_level(struct pipe_ctx *pipe_ctx)
2617{
2618 uint32_t sdr_white_level = pipe_ctx->stream->cursor_attributes.sdr_white_level;
2619 struct fixed31_32 multiplier;
2620 struct dpp_cursor_attributes opt_attr = { 0 };
2621 uint32_t hw_scale = 0x3c00;
2622 struct custom_float_format fmt;
2623
2624 if (!pipe_ctx->plane_res.dpp->funcs->set_optional_cursor_attributes)
2625 return;
2626
2627 fmt.exponenta_bits = 5;
2628 fmt.mantissa_bits = 10;
2629 fmt.sign = true;
2630
2631 if (sdr_white_level > 80) {
2632 multiplier = dc_fixpt_from_fraction(sdr_white_level, 80);
2633 convert_to_custom_float_format(multiplier, &fmt, &hw_scale);
2634 }
2635
2636 opt_attr.scale = hw_scale;
2637 opt_attr.bias = 0;
2638
2639 pipe_ctx->plane_res.dpp->funcs->set_optional_cursor_attributes(
2640 pipe_ctx->plane_res.dpp, &opt_attr);
2641}
2642
2643static const struct hw_sequencer_funcs dcn10_funcs = {
2644 .program_gamut_remap = program_gamut_remap,
2645 .program_csc_matrix = program_csc_matrix,
2646 .init_hw = dcn10_init_hw,
2647 .apply_ctx_to_hw = dce110_apply_ctx_to_hw,
2648 .apply_ctx_for_surface = dcn10_apply_ctx_for_surface,
2649 .update_plane_addr = dcn10_update_plane_addr,
2650 .plane_atomic_disconnect = hwss1_plane_atomic_disconnect,
2651 .update_dchub = dcn10_update_dchub,
2652 .update_mpcc = dcn10_update_mpcc,
2653 .update_pending_status = dcn10_update_pending_status,
2654 .set_input_transfer_func = dcn10_set_input_transfer_func,
2655 .set_output_transfer_func = dcn10_set_output_transfer_func,
2656 .program_output_csc = dcn10_program_output_csc,
2657 .power_down = dce110_power_down,
2658 .enable_accelerated_mode = dce110_enable_accelerated_mode,
2659 .enable_timing_synchronization = dcn10_enable_timing_synchronization,
2660 .enable_per_frame_crtc_position_reset = dcn10_enable_per_frame_crtc_position_reset,
2661 .update_info_frame = dce110_update_info_frame,
2662 .enable_stream = dce110_enable_stream,
2663 .disable_stream = dce110_disable_stream,
2664 .unblank_stream = dce110_unblank_stream,
2665 .blank_stream = dce110_blank_stream,
2666 .enable_audio_stream = dce110_enable_audio_stream,
2667 .disable_audio_stream = dce110_disable_audio_stream,
2668 .enable_display_power_gating = dcn10_dummy_display_power_gating,
2669 .disable_plane = dcn10_disable_plane,
2670 .blank_pixel_data = dcn10_blank_pixel_data,
2671 .pipe_control_lock = dcn10_pipe_control_lock,
2672 .set_bandwidth = dcn10_set_bandwidth,
2673 .reset_hw_ctx_wrap = reset_hw_ctx_wrap,
2674 .enable_stream_timing = dcn10_enable_stream_timing,
2675 .set_drr = set_drr,
2676 .get_position = get_position,
2677 .set_static_screen_control = set_static_screen_control,
2678 .setup_stereo = dcn10_setup_stereo,
2679 .set_avmute = dce110_set_avmute,
2680 .log_hw_state = dcn10_log_hw_state,
2681 .wait_for_mpcc_disconnect = dcn10_wait_for_mpcc_disconnect,
2682 .ready_shared_resources = ready_shared_resources,
2683 .optimize_shared_resources = optimize_shared_resources,
2684 .pplib_apply_display_requirements =
2685 dcn10_pplib_apply_display_requirements,
2686 .edp_backlight_control = hwss_edp_backlight_control,
2687 .edp_power_control = hwss_edp_power_control,
2688 .edp_wait_for_hpd_ready = hwss_edp_wait_for_hpd_ready,
2689 .set_cursor_position = dcn10_set_cursor_position,
2690 .set_cursor_attribute = dcn10_set_cursor_attribute,
2691 .set_cursor_sdr_white_level = dcn10_set_cursor_sdr_white_level
2692};
2693
2694
2695void dcn10_hw_sequencer_construct(struct dc *dc)
2696{
2697 dc->hwss = dcn10_funcs;
2698}
2699
2700