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