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#include <linux/delay.h>
26
27#include "dm_services.h"
28#include "basics/dc_common.h"
29#include "dm_helpers.h"
30#include "core_types.h"
31#include "resource.h"
32#include "dcn20_resource.h"
33#include "dcn20_hwseq.h"
34#include "dce/dce_hwseq.h"
35#include "dcn20_dsc.h"
36#include "dcn20_optc.h"
37#include "abm.h"
38#include "clk_mgr.h"
39#include "dmcu.h"
40#include "hubp.h"
41#include "timing_generator.h"
42#include "opp.h"
43#include "ipp.h"
44#include "mpc.h"
45#include "mcif_wb.h"
46#include "dchubbub.h"
47#include "reg_helper.h"
48#include "dcn10/dcn10_cm_common.h"
49#include "dc_link_dp.h"
50#include "vm_helper.h"
51#include "dccg.h"
52#include "dc_dmub_srv.h"
53#include "dce/dmub_hw_lock_mgr.h"
54#include "hw_sequencer.h"
55
56#define DC_LOGGER_INIT(logger)
57
58#define CTX \
59 hws->ctx
60#define REG(reg)\
61 hws->regs->reg
62
63#undef FN
64#define FN(reg_name, field_name) \
65 hws->shifts->field_name, hws->masks->field_name
66
67static int find_free_gsl_group(const struct dc *dc)
68{
69 if (dc->res_pool->gsl_groups.gsl_0 == 0)
70 return 1;
71 if (dc->res_pool->gsl_groups.gsl_1 == 0)
72 return 2;
73 if (dc->res_pool->gsl_groups.gsl_2 == 0)
74 return 3;
75
76 return 0;
77}
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94static void dcn20_setup_gsl_group_as_lock(
95 const struct dc *dc,
96 struct pipe_ctx *pipe_ctx,
97 bool enable)
98{
99 struct gsl_params gsl;
100 int group_idx;
101
102 memset(&gsl, 0, sizeof(struct gsl_params));
103
104 if (enable) {
105
106
107
108 if (pipe_ctx->stream_res.gsl_group > 0)
109 return;
110
111 group_idx = find_free_gsl_group(dc);
112 ASSERT(group_idx != 0);
113 pipe_ctx->stream_res.gsl_group = group_idx;
114
115
116 switch (group_idx) {
117 case 1:
118 gsl.gsl0_en = 1;
119 dc->res_pool->gsl_groups.gsl_0 = 1;
120 break;
121 case 2:
122 gsl.gsl1_en = 1;
123 dc->res_pool->gsl_groups.gsl_1 = 1;
124 break;
125 case 3:
126 gsl.gsl2_en = 1;
127 dc->res_pool->gsl_groups.gsl_2 = 1;
128 break;
129 default:
130 BREAK_TO_DEBUGGER();
131 return;
132 }
133 gsl.gsl_master_en = 1;
134 } else {
135 group_idx = pipe_ctx->stream_res.gsl_group;
136 if (group_idx == 0)
137 return;
138
139 pipe_ctx->stream_res.gsl_group = 0;
140
141
142 switch (group_idx) {
143 case 1:
144 gsl.gsl0_en = 0;
145 dc->res_pool->gsl_groups.gsl_0 = 0;
146 break;
147 case 2:
148 gsl.gsl1_en = 0;
149 dc->res_pool->gsl_groups.gsl_1 = 0;
150 break;
151 case 3:
152 gsl.gsl2_en = 0;
153 dc->res_pool->gsl_groups.gsl_2 = 0;
154 break;
155 default:
156 BREAK_TO_DEBUGGER();
157 return;
158 }
159 gsl.gsl_master_en = 0;
160 }
161
162
163 if (pipe_ctx->stream_res.tg->funcs->set_gsl != NULL &&
164 pipe_ctx->stream_res.tg->funcs->set_gsl_source_select != NULL) {
165 pipe_ctx->stream_res.tg->funcs->set_gsl(
166 pipe_ctx->stream_res.tg,
167 &gsl);
168
169 pipe_ctx->stream_res.tg->funcs->set_gsl_source_select(
170 pipe_ctx->stream_res.tg, group_idx, enable ? 4 : 0);
171 } else
172 BREAK_TO_DEBUGGER();
173}
174
175void dcn20_set_flip_control_gsl(
176 struct pipe_ctx *pipe_ctx,
177 bool flip_immediate)
178{
179 if (pipe_ctx && pipe_ctx->plane_res.hubp->funcs->hubp_set_flip_control_surface_gsl)
180 pipe_ctx->plane_res.hubp->funcs->hubp_set_flip_control_surface_gsl(
181 pipe_ctx->plane_res.hubp, flip_immediate);
182
183}
184
185void dcn20_enable_power_gating_plane(
186 struct dce_hwseq *hws,
187 bool enable)
188{
189 bool force_on = true;
190
191 if (enable)
192 force_on = false;
193
194
195 REG_UPDATE(DOMAIN0_PG_CONFIG, DOMAIN0_POWER_FORCEON, force_on);
196 REG_UPDATE(DOMAIN2_PG_CONFIG, DOMAIN2_POWER_FORCEON, force_on);
197 REG_UPDATE(DOMAIN4_PG_CONFIG, DOMAIN4_POWER_FORCEON, force_on);
198 REG_UPDATE(DOMAIN6_PG_CONFIG, DOMAIN6_POWER_FORCEON, force_on);
199 if (REG(DOMAIN8_PG_CONFIG))
200 REG_UPDATE(DOMAIN8_PG_CONFIG, DOMAIN8_POWER_FORCEON, force_on);
201 if (REG(DOMAIN10_PG_CONFIG))
202 REG_UPDATE(DOMAIN10_PG_CONFIG, DOMAIN8_POWER_FORCEON, force_on);
203
204
205 REG_UPDATE(DOMAIN1_PG_CONFIG, DOMAIN1_POWER_FORCEON, force_on);
206 REG_UPDATE(DOMAIN3_PG_CONFIG, DOMAIN3_POWER_FORCEON, force_on);
207 REG_UPDATE(DOMAIN5_PG_CONFIG, DOMAIN5_POWER_FORCEON, force_on);
208 REG_UPDATE(DOMAIN7_PG_CONFIG, DOMAIN7_POWER_FORCEON, force_on);
209 if (REG(DOMAIN9_PG_CONFIG))
210 REG_UPDATE(DOMAIN9_PG_CONFIG, DOMAIN9_POWER_FORCEON, force_on);
211 if (REG(DOMAIN11_PG_CONFIG))
212 REG_UPDATE(DOMAIN11_PG_CONFIG, DOMAIN9_POWER_FORCEON, force_on);
213
214
215 REG_UPDATE(DOMAIN16_PG_CONFIG, DOMAIN16_POWER_FORCEON, force_on);
216 REG_UPDATE(DOMAIN17_PG_CONFIG, DOMAIN17_POWER_FORCEON, force_on);
217 REG_UPDATE(DOMAIN18_PG_CONFIG, DOMAIN18_POWER_FORCEON, force_on);
218 if (REG(DOMAIN19_PG_CONFIG))
219 REG_UPDATE(DOMAIN19_PG_CONFIG, DOMAIN19_POWER_FORCEON, force_on);
220 if (REG(DOMAIN20_PG_CONFIG))
221 REG_UPDATE(DOMAIN20_PG_CONFIG, DOMAIN20_POWER_FORCEON, force_on);
222 if (REG(DOMAIN21_PG_CONFIG))
223 REG_UPDATE(DOMAIN21_PG_CONFIG, DOMAIN21_POWER_FORCEON, force_on);
224}
225
226void dcn20_dccg_init(struct dce_hwseq *hws)
227{
228
229
230
231
232
233
234
235 REG_WRITE(MICROSECOND_TIME_BASE_DIV, 0x120264);
236
237
238
239
240
241
242
243
244 REG_WRITE(MILLISECOND_TIME_BASE_DIV, 0x1186a0);
245
246
247 REG_WRITE(DISPCLK_FREQ_CHANGE_CNTL, 0xe01003c);
248}
249
250void dcn20_disable_vga(
251 struct dce_hwseq *hws)
252{
253 REG_WRITE(D1VGA_CONTROL, 0);
254 REG_WRITE(D2VGA_CONTROL, 0);
255 REG_WRITE(D3VGA_CONTROL, 0);
256 REG_WRITE(D4VGA_CONTROL, 0);
257 REG_WRITE(D5VGA_CONTROL, 0);
258 REG_WRITE(D6VGA_CONTROL, 0);
259}
260
261void dcn20_program_triple_buffer(
262 const struct dc *dc,
263 struct pipe_ctx *pipe_ctx,
264 bool enable_triple_buffer)
265{
266 if (pipe_ctx->plane_res.hubp && pipe_ctx->plane_res.hubp->funcs) {
267 pipe_ctx->plane_res.hubp->funcs->hubp_enable_tripleBuffer(
268 pipe_ctx->plane_res.hubp,
269 enable_triple_buffer);
270 }
271}
272
273
274void dcn20_init_blank(
275 struct dc *dc,
276 struct timing_generator *tg)
277{
278 struct dce_hwseq *hws = dc->hwseq;
279 enum dc_color_space color_space;
280 struct tg_color black_color = {0};
281 struct output_pixel_processor *opp = NULL;
282 struct output_pixel_processor *bottom_opp = NULL;
283 uint32_t num_opps, opp_id_src0, opp_id_src1;
284 uint32_t otg_active_width, otg_active_height;
285
286
287 color_space = COLOR_SPACE_SRGB;
288 color_space_to_black_color(dc, color_space, &black_color);
289
290
291 tg->funcs->get_otg_active_size(tg,
292 &otg_active_width,
293 &otg_active_height);
294
295
296 tg->funcs->get_optc_source(tg, &num_opps, &opp_id_src0, &opp_id_src1);
297
298 if (opp_id_src0 >= dc->res_pool->res_cap->num_opp) {
299 ASSERT(false);
300 return;
301 }
302 opp = dc->res_pool->opps[opp_id_src0];
303
304 if (num_opps == 2) {
305 otg_active_width = otg_active_width / 2;
306
307 if (opp_id_src1 >= dc->res_pool->res_cap->num_opp) {
308 ASSERT(false);
309 return;
310 }
311 bottom_opp = dc->res_pool->opps[opp_id_src1];
312 }
313
314 opp->funcs->opp_set_disp_pattern_generator(
315 opp,
316 CONTROLLER_DP_TEST_PATTERN_SOLID_COLOR,
317 CONTROLLER_DP_COLOR_SPACE_UDEFINED,
318 COLOR_DEPTH_UNDEFINED,
319 &black_color,
320 otg_active_width,
321 otg_active_height,
322 0);
323
324 if (num_opps == 2) {
325 bottom_opp->funcs->opp_set_disp_pattern_generator(
326 bottom_opp,
327 CONTROLLER_DP_TEST_PATTERN_SOLID_COLOR,
328 CONTROLLER_DP_COLOR_SPACE_UDEFINED,
329 COLOR_DEPTH_UNDEFINED,
330 &black_color,
331 otg_active_width,
332 otg_active_height,
333 0);
334 }
335
336 hws->funcs.wait_for_blank_complete(opp);
337}
338
339void dcn20_dsc_pg_control(
340 struct dce_hwseq *hws,
341 unsigned int dsc_inst,
342 bool power_on)
343{
344 uint32_t power_gate = power_on ? 0 : 1;
345 uint32_t pwr_status = power_on ? 0 : 2;
346 uint32_t org_ip_request_cntl = 0;
347
348 if (hws->ctx->dc->debug.disable_dsc_power_gate)
349 return;
350
351 if (REG(DOMAIN16_PG_CONFIG) == 0)
352 return;
353
354 REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl);
355 if (org_ip_request_cntl == 0)
356 REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1);
357
358 switch (dsc_inst) {
359 case 0:
360 REG_UPDATE(DOMAIN16_PG_CONFIG,
361 DOMAIN16_POWER_GATE, power_gate);
362
363 REG_WAIT(DOMAIN16_PG_STATUS,
364 DOMAIN16_PGFSM_PWR_STATUS, pwr_status,
365 1, 1000);
366 break;
367 case 1:
368 REG_UPDATE(DOMAIN17_PG_CONFIG,
369 DOMAIN17_POWER_GATE, power_gate);
370
371 REG_WAIT(DOMAIN17_PG_STATUS,
372 DOMAIN17_PGFSM_PWR_STATUS, pwr_status,
373 1, 1000);
374 break;
375 case 2:
376 REG_UPDATE(DOMAIN18_PG_CONFIG,
377 DOMAIN18_POWER_GATE, power_gate);
378
379 REG_WAIT(DOMAIN18_PG_STATUS,
380 DOMAIN18_PGFSM_PWR_STATUS, pwr_status,
381 1, 1000);
382 break;
383 case 3:
384 REG_UPDATE(DOMAIN19_PG_CONFIG,
385 DOMAIN19_POWER_GATE, power_gate);
386
387 REG_WAIT(DOMAIN19_PG_STATUS,
388 DOMAIN19_PGFSM_PWR_STATUS, pwr_status,
389 1, 1000);
390 break;
391 case 4:
392 REG_UPDATE(DOMAIN20_PG_CONFIG,
393 DOMAIN20_POWER_GATE, power_gate);
394
395 REG_WAIT(DOMAIN20_PG_STATUS,
396 DOMAIN20_PGFSM_PWR_STATUS, pwr_status,
397 1, 1000);
398 break;
399 case 5:
400 REG_UPDATE(DOMAIN21_PG_CONFIG,
401 DOMAIN21_POWER_GATE, power_gate);
402
403 REG_WAIT(DOMAIN21_PG_STATUS,
404 DOMAIN21_PGFSM_PWR_STATUS, pwr_status,
405 1, 1000);
406 break;
407 default:
408 BREAK_TO_DEBUGGER();
409 break;
410 }
411
412 if (org_ip_request_cntl == 0)
413 REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0);
414}
415
416void dcn20_dpp_pg_control(
417 struct dce_hwseq *hws,
418 unsigned int dpp_inst,
419 bool power_on)
420{
421 uint32_t power_gate = power_on ? 0 : 1;
422 uint32_t pwr_status = power_on ? 0 : 2;
423
424 if (hws->ctx->dc->debug.disable_dpp_power_gate)
425 return;
426 if (REG(DOMAIN1_PG_CONFIG) == 0)
427 return;
428
429 switch (dpp_inst) {
430 case 0:
431 REG_UPDATE(DOMAIN1_PG_CONFIG,
432 DOMAIN1_POWER_GATE, power_gate);
433
434 REG_WAIT(DOMAIN1_PG_STATUS,
435 DOMAIN1_PGFSM_PWR_STATUS, pwr_status,
436 1, 1000);
437 break;
438 case 1:
439 REG_UPDATE(DOMAIN3_PG_CONFIG,
440 DOMAIN3_POWER_GATE, power_gate);
441
442 REG_WAIT(DOMAIN3_PG_STATUS,
443 DOMAIN3_PGFSM_PWR_STATUS, pwr_status,
444 1, 1000);
445 break;
446 case 2:
447 REG_UPDATE(DOMAIN5_PG_CONFIG,
448 DOMAIN5_POWER_GATE, power_gate);
449
450 REG_WAIT(DOMAIN5_PG_STATUS,
451 DOMAIN5_PGFSM_PWR_STATUS, pwr_status,
452 1, 1000);
453 break;
454 case 3:
455 REG_UPDATE(DOMAIN7_PG_CONFIG,
456 DOMAIN7_POWER_GATE, power_gate);
457
458 REG_WAIT(DOMAIN7_PG_STATUS,
459 DOMAIN7_PGFSM_PWR_STATUS, pwr_status,
460 1, 1000);
461 break;
462 case 4:
463 REG_UPDATE(DOMAIN9_PG_CONFIG,
464 DOMAIN9_POWER_GATE, power_gate);
465
466 REG_WAIT(DOMAIN9_PG_STATUS,
467 DOMAIN9_PGFSM_PWR_STATUS, pwr_status,
468 1, 1000);
469 break;
470 case 5:
471
472
473
474
475
476
477
478
479
480
481
482 break;
483 default:
484 BREAK_TO_DEBUGGER();
485 break;
486 }
487}
488
489
490void dcn20_hubp_pg_control(
491 struct dce_hwseq *hws,
492 unsigned int hubp_inst,
493 bool power_on)
494{
495 uint32_t power_gate = power_on ? 0 : 1;
496 uint32_t pwr_status = power_on ? 0 : 2;
497
498 if (hws->ctx->dc->debug.disable_hubp_power_gate)
499 return;
500 if (REG(DOMAIN0_PG_CONFIG) == 0)
501 return;
502
503 switch (hubp_inst) {
504 case 0:
505 REG_UPDATE(DOMAIN0_PG_CONFIG,
506 DOMAIN0_POWER_GATE, power_gate);
507
508 REG_WAIT(DOMAIN0_PG_STATUS,
509 DOMAIN0_PGFSM_PWR_STATUS, pwr_status,
510 1, 1000);
511 break;
512 case 1:
513 REG_UPDATE(DOMAIN2_PG_CONFIG,
514 DOMAIN2_POWER_GATE, power_gate);
515
516 REG_WAIT(DOMAIN2_PG_STATUS,
517 DOMAIN2_PGFSM_PWR_STATUS, pwr_status,
518 1, 1000);
519 break;
520 case 2:
521 REG_UPDATE(DOMAIN4_PG_CONFIG,
522 DOMAIN4_POWER_GATE, power_gate);
523
524 REG_WAIT(DOMAIN4_PG_STATUS,
525 DOMAIN4_PGFSM_PWR_STATUS, pwr_status,
526 1, 1000);
527 break;
528 case 3:
529 REG_UPDATE(DOMAIN6_PG_CONFIG,
530 DOMAIN6_POWER_GATE, power_gate);
531
532 REG_WAIT(DOMAIN6_PG_STATUS,
533 DOMAIN6_PGFSM_PWR_STATUS, pwr_status,
534 1, 1000);
535 break;
536 case 4:
537 REG_UPDATE(DOMAIN8_PG_CONFIG,
538 DOMAIN8_POWER_GATE, power_gate);
539
540 REG_WAIT(DOMAIN8_PG_STATUS,
541 DOMAIN8_PGFSM_PWR_STATUS, pwr_status,
542 1, 1000);
543 break;
544 case 5:
545
546
547
548
549
550
551
552
553
554
555
556 break;
557 default:
558 BREAK_TO_DEBUGGER();
559 break;
560 }
561}
562
563
564
565
566
567void dcn20_plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx)
568{
569 struct dce_hwseq *hws = dc->hwseq;
570 struct hubp *hubp = pipe_ctx->plane_res.hubp;
571 struct dpp *dpp = pipe_ctx->plane_res.dpp;
572
573 dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, pipe_ctx);
574
575
576
577
578 if (pipe_ctx->stream_res.gsl_group != 0)
579 dcn20_setup_gsl_group_as_lock(dc, pipe_ctx, false);
580
581 dc->hwss.set_flip_control_gsl(pipe_ctx, false);
582
583 hubp->funcs->hubp_clk_cntl(hubp, false);
584
585 dpp->funcs->dpp_dppclk_control(dpp, false, false);
586
587 hubp->power_gated = true;
588
589 hws->funcs.plane_atomic_power_down(dc,
590 pipe_ctx->plane_res.dpp,
591 pipe_ctx->plane_res.hubp);
592
593 pipe_ctx->stream = NULL;
594 memset(&pipe_ctx->stream_res, 0, sizeof(pipe_ctx->stream_res));
595 memset(&pipe_ctx->plane_res, 0, sizeof(pipe_ctx->plane_res));
596 pipe_ctx->top_pipe = NULL;
597 pipe_ctx->bottom_pipe = NULL;
598 pipe_ctx->plane_state = NULL;
599}
600
601
602void dcn20_disable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx)
603{
604 DC_LOGGER_INIT(dc->ctx->logger);
605
606 if (!pipe_ctx->plane_res.hubp || pipe_ctx->plane_res.hubp->power_gated)
607 return;
608
609 dcn20_plane_atomic_disable(dc, pipe_ctx);
610
611 DC_LOG_DC("Power down front end %d\n",
612 pipe_ctx->pipe_idx);
613}
614
615static int calc_mpc_flow_ctrl_cnt(const struct dc_stream_state *stream,
616 int opp_cnt)
617{
618 bool hblank_halved = optc2_is_two_pixels_per_containter(&stream->timing);
619 int flow_ctrl_cnt;
620
621 if (opp_cnt >= 2)
622 hblank_halved = true;
623
624 flow_ctrl_cnt = stream->timing.h_total - stream->timing.h_addressable -
625 stream->timing.h_border_left -
626 stream->timing.h_border_right;
627
628 if (hblank_halved)
629 flow_ctrl_cnt /= 2;
630
631
632 if (opp_cnt == 4)
633 flow_ctrl_cnt /= 2;
634
635 return flow_ctrl_cnt;
636}
637
638enum dc_status dcn20_enable_stream_timing(
639 struct pipe_ctx *pipe_ctx,
640 struct dc_state *context,
641 struct dc *dc)
642{
643 struct dce_hwseq *hws = dc->hwseq;
644 struct dc_stream_state *stream = pipe_ctx->stream;
645 struct drr_params params = {0};
646 unsigned int event_triggers = 0;
647 struct pipe_ctx *odm_pipe;
648 int opp_cnt = 1;
649 int opp_inst[MAX_PIPES] = { pipe_ctx->stream_res.opp->inst };
650 bool interlace = stream->timing.flags.INTERLACE;
651 int i;
652 struct mpc_dwb_flow_control flow_control;
653 struct mpc *mpc = dc->res_pool->mpc;
654 bool rate_control_2x_pclk = (interlace || optc2_is_two_pixels_per_containter(&stream->timing));
655
656
657
658
659
660 if (pipe_ctx->top_pipe != NULL)
661 return DC_OK;
662
663
664
665 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
666 opp_inst[opp_cnt] = odm_pipe->stream_res.opp->inst;
667 opp_cnt++;
668 }
669
670 if (opp_cnt > 1)
671 pipe_ctx->stream_res.tg->funcs->set_odm_combine(
672 pipe_ctx->stream_res.tg,
673 opp_inst, opp_cnt,
674 &pipe_ctx->stream->timing);
675
676
677
678
679 pipe_ctx->stream_res.tg->funcs->enable_optc_clock(pipe_ctx->stream_res.tg, true);
680
681 if (false == pipe_ctx->clock_source->funcs->program_pix_clk(
682 pipe_ctx->clock_source,
683 &pipe_ctx->stream_res.pix_clk_params,
684 &pipe_ctx->pll_settings)) {
685 BREAK_TO_DEBUGGER();
686 return DC_ERROR_UNEXPECTED;
687 }
688
689 if (dc->hwseq->funcs.PLAT_58856_wa && (!dc_is_dp_signal(stream->signal)))
690 dc->hwseq->funcs.PLAT_58856_wa(context, pipe_ctx);
691
692 pipe_ctx->stream_res.tg->funcs->program_timing(
693 pipe_ctx->stream_res.tg,
694 &stream->timing,
695 pipe_ctx->pipe_dlg_param.vready_offset,
696 pipe_ctx->pipe_dlg_param.vstartup_start,
697 pipe_ctx->pipe_dlg_param.vupdate_offset,
698 pipe_ctx->pipe_dlg_param.vupdate_width,
699 pipe_ctx->stream->signal,
700 true);
701
702 rate_control_2x_pclk = rate_control_2x_pclk || opp_cnt > 1;
703 flow_control.flow_ctrl_mode = 0;
704 flow_control.flow_ctrl_cnt0 = 0x80;
705 flow_control.flow_ctrl_cnt1 = calc_mpc_flow_ctrl_cnt(stream, opp_cnt);
706 if (mpc->funcs->set_out_rate_control) {
707 for (i = 0; i < opp_cnt; ++i) {
708 mpc->funcs->set_out_rate_control(
709 mpc, opp_inst[i],
710 true,
711 rate_control_2x_pclk,
712 &flow_control);
713 }
714 }
715
716 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
717 odm_pipe->stream_res.opp->funcs->opp_pipe_clock_control(
718 odm_pipe->stream_res.opp,
719 true);
720
721 pipe_ctx->stream_res.opp->funcs->opp_pipe_clock_control(
722 pipe_ctx->stream_res.opp,
723 true);
724
725 hws->funcs.blank_pixel_data(dc, pipe_ctx, true);
726
727
728 if (false == pipe_ctx->stream_res.tg->funcs->enable_crtc(pipe_ctx->stream_res.tg)) {
729 BREAK_TO_DEBUGGER();
730 return DC_ERROR_UNEXPECTED;
731 }
732
733 hws->funcs.wait_for_blank_complete(pipe_ctx->stream_res.opp);
734
735 params.vertical_total_min = stream->adjust.v_total_min;
736 params.vertical_total_max = stream->adjust.v_total_max;
737 params.vertical_total_mid = stream->adjust.v_total_mid;
738 params.vertical_total_mid_frame_num = stream->adjust.v_total_mid_frame_num;
739 if (pipe_ctx->stream_res.tg->funcs->set_drr)
740 pipe_ctx->stream_res.tg->funcs->set_drr(
741 pipe_ctx->stream_res.tg, ¶ms);
742
743
744 if (stream->adjust.v_total_min != 0 && stream->adjust.v_total_max != 0)
745 event_triggers = 0x80;
746
747
748
749
750 if (pipe_ctx->stream_res.tg->funcs->set_static_screen_control)
751 pipe_ctx->stream_res.tg->funcs->set_static_screen_control(
752 pipe_ctx->stream_res.tg, event_triggers, 2);
753
754
755
756
757
758
759
760
761
762 return DC_OK;
763}
764
765void dcn20_program_output_csc(struct dc *dc,
766 struct pipe_ctx *pipe_ctx,
767 enum dc_color_space colorspace,
768 uint16_t *matrix,
769 int opp_id)
770{
771 struct mpc *mpc = dc->res_pool->mpc;
772 enum mpc_output_csc_mode ocsc_mode = MPC_OUTPUT_CSC_COEF_A;
773 int mpcc_id = pipe_ctx->plane_res.hubp->inst;
774
775 if (mpc->funcs->power_on_mpc_mem_pwr)
776 mpc->funcs->power_on_mpc_mem_pwr(mpc, mpcc_id, true);
777
778 if (pipe_ctx->stream->csc_color_matrix.enable_adjustment == true) {
779 if (mpc->funcs->set_output_csc != NULL)
780 mpc->funcs->set_output_csc(mpc,
781 opp_id,
782 matrix,
783 ocsc_mode);
784 } else {
785 if (mpc->funcs->set_ocsc_default != NULL)
786 mpc->funcs->set_ocsc_default(mpc,
787 opp_id,
788 colorspace,
789 ocsc_mode);
790 }
791}
792
793bool dcn20_set_output_transfer_func(struct dc *dc, struct pipe_ctx *pipe_ctx,
794 const struct dc_stream_state *stream)
795{
796 int mpcc_id = pipe_ctx->plane_res.hubp->inst;
797 struct mpc *mpc = pipe_ctx->stream_res.opp->ctx->dc->res_pool->mpc;
798 struct pwl_params *params = NULL;
799
800
801
802
803
804
805
806 if (mpc->funcs->power_on_mpc_mem_pwr)
807 mpc->funcs->power_on_mpc_mem_pwr(mpc, mpcc_id, true);
808 if (pipe_ctx->top_pipe == NULL
809 && mpc->funcs->set_output_gamma && stream->out_transfer_func) {
810 if (stream->out_transfer_func->type == TF_TYPE_HWPWL)
811 params = &stream->out_transfer_func->pwl;
812 else if (pipe_ctx->stream->out_transfer_func->type ==
813 TF_TYPE_DISTRIBUTED_POINTS &&
814 cm_helper_translate_curve_to_hw_format(
815 stream->out_transfer_func,
816 &mpc->blender_params, false))
817 params = &mpc->blender_params;
818
819
820
821 if (stream->out_transfer_func->type == TF_TYPE_PREDEFINED)
822 BREAK_TO_DEBUGGER();
823 }
824
825
826
827 mpc->funcs->set_output_gamma(mpc, mpcc_id, params);
828
829 return true;
830}
831
832bool dcn20_set_blend_lut(
833 struct pipe_ctx *pipe_ctx, const struct dc_plane_state *plane_state)
834{
835 struct dpp *dpp_base = pipe_ctx->plane_res.dpp;
836 bool result = true;
837 struct pwl_params *blend_lut = NULL;
838
839 if (plane_state->blend_tf) {
840 if (plane_state->blend_tf->type == TF_TYPE_HWPWL)
841 blend_lut = &plane_state->blend_tf->pwl;
842 else if (plane_state->blend_tf->type == TF_TYPE_DISTRIBUTED_POINTS) {
843 cm_helper_translate_curve_to_hw_format(
844 plane_state->blend_tf,
845 &dpp_base->regamma_params, false);
846 blend_lut = &dpp_base->regamma_params;
847 }
848 }
849 result = dpp_base->funcs->dpp_program_blnd_lut(dpp_base, blend_lut);
850
851 return result;
852}
853
854bool dcn20_set_shaper_3dlut(
855 struct pipe_ctx *pipe_ctx, const struct dc_plane_state *plane_state)
856{
857 struct dpp *dpp_base = pipe_ctx->plane_res.dpp;
858 bool result = true;
859 struct pwl_params *shaper_lut = NULL;
860
861 if (plane_state->in_shaper_func) {
862 if (plane_state->in_shaper_func->type == TF_TYPE_HWPWL)
863 shaper_lut = &plane_state->in_shaper_func->pwl;
864 else if (plane_state->in_shaper_func->type == TF_TYPE_DISTRIBUTED_POINTS) {
865 cm_helper_translate_curve_to_hw_format(
866 plane_state->in_shaper_func,
867 &dpp_base->shaper_params, true);
868 shaper_lut = &dpp_base->shaper_params;
869 }
870 }
871
872 result = dpp_base->funcs->dpp_program_shaper_lut(dpp_base, shaper_lut);
873 if (plane_state->lut3d_func &&
874 plane_state->lut3d_func->state.bits.initialized == 1)
875 result = dpp_base->funcs->dpp_program_3dlut(dpp_base,
876 &plane_state->lut3d_func->lut_3d);
877 else
878 result = dpp_base->funcs->dpp_program_3dlut(dpp_base, NULL);
879
880 return result;
881}
882
883bool dcn20_set_input_transfer_func(struct dc *dc,
884 struct pipe_ctx *pipe_ctx,
885 const struct dc_plane_state *plane_state)
886{
887 struct dce_hwseq *hws = dc->hwseq;
888 struct dpp *dpp_base = pipe_ctx->plane_res.dpp;
889 const struct dc_transfer_func *tf = NULL;
890 bool result = true;
891 bool use_degamma_ram = false;
892
893 if (dpp_base == NULL || plane_state == NULL)
894 return false;
895
896 hws->funcs.set_shaper_3dlut(pipe_ctx, plane_state);
897 hws->funcs.set_blend_lut(pipe_ctx, plane_state);
898
899 if (plane_state->in_transfer_func)
900 tf = plane_state->in_transfer_func;
901
902
903 if (tf == NULL) {
904 dpp_base->funcs->dpp_set_degamma(dpp_base,
905 IPP_DEGAMMA_MODE_BYPASS);
906 return true;
907 }
908
909 if (tf->type == TF_TYPE_HWPWL || tf->type == TF_TYPE_DISTRIBUTED_POINTS)
910 use_degamma_ram = true;
911
912 if (use_degamma_ram == true) {
913 if (tf->type == TF_TYPE_HWPWL)
914 dpp_base->funcs->dpp_program_degamma_pwl(dpp_base,
915 &tf->pwl);
916 else if (tf->type == TF_TYPE_DISTRIBUTED_POINTS) {
917 cm_helper_translate_curve_to_degamma_hw_format(tf,
918 &dpp_base->degamma_params);
919 dpp_base->funcs->dpp_program_degamma_pwl(dpp_base,
920 &dpp_base->degamma_params);
921 }
922 return true;
923 }
924
925
926
927 if (tf->type == TF_TYPE_PREDEFINED) {
928 switch (tf->tf) {
929 case TRANSFER_FUNCTION_SRGB:
930 dpp_base->funcs->dpp_set_degamma(dpp_base,
931 IPP_DEGAMMA_MODE_HW_sRGB);
932 break;
933 case TRANSFER_FUNCTION_BT709:
934 dpp_base->funcs->dpp_set_degamma(dpp_base,
935 IPP_DEGAMMA_MODE_HW_xvYCC);
936 break;
937 case TRANSFER_FUNCTION_LINEAR:
938 dpp_base->funcs->dpp_set_degamma(dpp_base,
939 IPP_DEGAMMA_MODE_BYPASS);
940 break;
941 case TRANSFER_FUNCTION_PQ:
942 dpp_base->funcs->dpp_set_degamma(dpp_base, IPP_DEGAMMA_MODE_USER_PWL);
943 cm_helper_translate_curve_to_degamma_hw_format(tf, &dpp_base->degamma_params);
944 dpp_base->funcs->dpp_program_degamma_pwl(dpp_base, &dpp_base->degamma_params);
945 result = true;
946 break;
947 default:
948 result = false;
949 break;
950 }
951 } else if (tf->type == TF_TYPE_BYPASS)
952 dpp_base->funcs->dpp_set_degamma(dpp_base,
953 IPP_DEGAMMA_MODE_BYPASS);
954 else {
955
956
957
958
959 BREAK_TO_DEBUGGER();
960 dpp_base->funcs->dpp_set_degamma(dpp_base,
961 IPP_DEGAMMA_MODE_BYPASS);
962 }
963
964 return result;
965}
966
967void dcn20_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe_ctx)
968{
969 struct pipe_ctx *odm_pipe;
970 int opp_cnt = 1;
971 int opp_inst[MAX_PIPES] = { pipe_ctx->stream_res.opp->inst };
972
973 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
974 opp_inst[opp_cnt] = odm_pipe->stream_res.opp->inst;
975 opp_cnt++;
976 }
977
978 if (opp_cnt > 1)
979 pipe_ctx->stream_res.tg->funcs->set_odm_combine(
980 pipe_ctx->stream_res.tg,
981 opp_inst, opp_cnt,
982 &pipe_ctx->stream->timing);
983 else
984 pipe_ctx->stream_res.tg->funcs->set_odm_bypass(
985 pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing);
986}
987
988void dcn20_blank_pixel_data(
989 struct dc *dc,
990 struct pipe_ctx *pipe_ctx,
991 bool blank)
992{
993 struct tg_color black_color = {0};
994 struct stream_resource *stream_res = &pipe_ctx->stream_res;
995 struct dc_stream_state *stream = pipe_ctx->stream;
996 enum dc_color_space color_space = stream->output_color_space;
997 enum controller_dp_test_pattern test_pattern = CONTROLLER_DP_TEST_PATTERN_SOLID_COLOR;
998 enum controller_dp_color_space test_pattern_color_space = CONTROLLER_DP_COLOR_SPACE_UDEFINED;
999 struct pipe_ctx *odm_pipe;
1000 int odm_cnt = 1;
1001
1002 int width = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right;
1003 int height = stream->timing.v_addressable + stream->timing.v_border_bottom + stream->timing.v_border_top;
1004
1005 if (stream->link->test_pattern_enabled)
1006 return;
1007
1008
1009 color_space_to_black_color(dc, color_space, &black_color);
1010
1011 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
1012 odm_cnt++;
1013
1014 width = width / odm_cnt;
1015
1016 if (blank) {
1017 dc->hwss.set_abm_immediate_disable(pipe_ctx);
1018
1019 if (dc->debug.visual_confirm != VISUAL_CONFIRM_DISABLE) {
1020 test_pattern = CONTROLLER_DP_TEST_PATTERN_COLORSQUARES;
1021 test_pattern_color_space = CONTROLLER_DP_COLOR_SPACE_RGB;
1022 }
1023 } else {
1024 test_pattern = CONTROLLER_DP_TEST_PATTERN_VIDEOMODE;
1025 }
1026
1027 dc->hwss.set_disp_pattern_generator(dc,
1028 pipe_ctx,
1029 test_pattern,
1030 test_pattern_color_space,
1031 stream->timing.display_color_depth,
1032 &black_color,
1033 width,
1034 height,
1035 0);
1036
1037 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
1038 dc->hwss.set_disp_pattern_generator(dc,
1039 odm_pipe,
1040 dc->debug.visual_confirm != VISUAL_CONFIRM_DISABLE && blank ?
1041 CONTROLLER_DP_TEST_PATTERN_COLORRAMP : test_pattern,
1042 test_pattern_color_space,
1043 stream->timing.display_color_depth,
1044 &black_color,
1045 width,
1046 height,
1047 0);
1048 }
1049
1050 if (!blank)
1051 if (stream_res->abm) {
1052 dc->hwss.set_pipe(pipe_ctx);
1053 stream_res->abm->funcs->set_abm_level(stream_res->abm, stream->abm_level);
1054 }
1055}
1056
1057
1058static void dcn20_power_on_plane(
1059 struct dce_hwseq *hws,
1060 struct pipe_ctx *pipe_ctx)
1061{
1062 DC_LOGGER_INIT(hws->ctx->logger);
1063 if (REG(DC_IP_REQUEST_CNTL)) {
1064 REG_SET(DC_IP_REQUEST_CNTL, 0,
1065 IP_REQUEST_EN, 1);
1066
1067 if (hws->funcs.dpp_pg_control)
1068 hws->funcs.dpp_pg_control(hws, pipe_ctx->plane_res.dpp->inst, true);
1069
1070 if (hws->funcs.hubp_pg_control)
1071 hws->funcs.hubp_pg_control(hws, pipe_ctx->plane_res.hubp->inst, true);
1072
1073 REG_SET(DC_IP_REQUEST_CNTL, 0,
1074 IP_REQUEST_EN, 0);
1075 DC_LOG_DEBUG(
1076 "Un-gated front end for pipe %d\n", pipe_ctx->plane_res.hubp->inst);
1077 }
1078}
1079
1080void dcn20_enable_plane(
1081 struct dc *dc,
1082 struct pipe_ctx *pipe_ctx,
1083 struct dc_state *context)
1084{
1085
1086
1087
1088 dcn20_power_on_plane(dc->hwseq, pipe_ctx);
1089
1090
1091 pipe_ctx->plane_res.hubp->funcs->hubp_clk_cntl(pipe_ctx->plane_res.hubp, true);
1092
1093
1094 pipe_ctx->plane_res.hubp->funcs->hubp_init(pipe_ctx->plane_res.hubp);
1095
1096
1097 pipe_ctx->stream_res.opp->funcs->opp_pipe_clock_control(
1098 pipe_ctx->stream_res.opp,
1099 true);
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138 if (dc->vm_pa_config.valid) {
1139 struct vm_system_aperture_param apt;
1140
1141 apt.sys_default.quad_part = 0;
1142
1143 apt.sys_low.quad_part = dc->vm_pa_config.system_aperture.start_addr;
1144 apt.sys_high.quad_part = dc->vm_pa_config.system_aperture.end_addr;
1145
1146
1147 pipe_ctx->plane_res.hubp->funcs->hubp_set_vm_system_aperture_settings(pipe_ctx->plane_res.hubp, &apt);
1148 }
1149
1150 if (!pipe_ctx->top_pipe
1151 && pipe_ctx->plane_state
1152 && pipe_ctx->plane_state->flip_int_enabled
1153 && pipe_ctx->plane_res.hubp->funcs->hubp_set_flip_int)
1154 pipe_ctx->plane_res.hubp->funcs->hubp_set_flip_int(pipe_ctx->plane_res.hubp);
1155
1156
1157
1158
1159}
1160
1161void dcn20_pipe_control_lock(
1162 struct dc *dc,
1163 struct pipe_ctx *pipe,
1164 bool lock)
1165{
1166 struct pipe_ctx *temp_pipe;
1167 bool flip_immediate = false;
1168
1169
1170
1171
1172 if (!pipe || pipe->top_pipe)
1173 return;
1174
1175 if (pipe->plane_state != NULL)
1176 flip_immediate = pipe->plane_state->flip_immediate;
1177
1178 if (pipe->stream_res.gsl_group > 0) {
1179 temp_pipe = pipe->bottom_pipe;
1180 while (!flip_immediate && temp_pipe) {
1181 if (temp_pipe->plane_state != NULL)
1182 flip_immediate = temp_pipe->plane_state->flip_immediate;
1183 temp_pipe = temp_pipe->bottom_pipe;
1184 }
1185 }
1186
1187 if (flip_immediate && lock) {
1188 const int TIMEOUT_FOR_FLIP_PENDING = 100000;
1189 int i;
1190
1191 temp_pipe = pipe;
1192 while (temp_pipe) {
1193 if (temp_pipe->plane_state && temp_pipe->plane_state->flip_immediate) {
1194 for (i = 0; i < TIMEOUT_FOR_FLIP_PENDING; ++i) {
1195 if (!temp_pipe->plane_res.hubp->funcs->hubp_is_flip_pending(temp_pipe->plane_res.hubp))
1196 break;
1197 udelay(1);
1198 }
1199
1200
1201 ASSERT(i != TIMEOUT_FOR_FLIP_PENDING);
1202 }
1203 temp_pipe = temp_pipe->bottom_pipe;
1204 }
1205 }
1206
1207
1208
1209
1210 if (lock && (pipe->bottom_pipe != NULL || !flip_immediate))
1211 if ((flip_immediate && pipe->stream_res.gsl_group == 0) ||
1212 (!flip_immediate && pipe->stream_res.gsl_group > 0))
1213 dcn20_setup_gsl_group_as_lock(dc, pipe, flip_immediate);
1214
1215 if (pipe->plane_state != NULL)
1216 flip_immediate = pipe->plane_state->flip_immediate;
1217
1218 temp_pipe = pipe->bottom_pipe;
1219 while (flip_immediate && temp_pipe) {
1220 if (temp_pipe->plane_state != NULL)
1221 flip_immediate = temp_pipe->plane_state->flip_immediate;
1222 temp_pipe = temp_pipe->bottom_pipe;
1223 }
1224
1225 if (!lock && pipe->stream_res.gsl_group > 0 && pipe->plane_state &&
1226 !flip_immediate)
1227 dcn20_setup_gsl_group_as_lock(dc, pipe, false);
1228
1229 if (pipe->stream && should_use_dmub_lock(pipe->stream->link)) {
1230 union dmub_hw_lock_flags hw_locks = { 0 };
1231 struct dmub_hw_lock_inst_flags inst_flags = { 0 };
1232
1233 hw_locks.bits.lock_pipe = 1;
1234 inst_flags.otg_inst = pipe->stream_res.tg->inst;
1235
1236 if (pipe->plane_state != NULL)
1237 hw_locks.bits.triple_buffer_lock = pipe->plane_state->triplebuffer_flips;
1238
1239 dmub_hw_lock_mgr_cmd(dc->ctx->dmub_srv,
1240 lock,
1241 &hw_locks,
1242 &inst_flags);
1243 } else if (pipe->plane_state != NULL && pipe->plane_state->triplebuffer_flips) {
1244 if (lock)
1245 pipe->stream_res.tg->funcs->triplebuffer_lock(pipe->stream_res.tg);
1246 else
1247 pipe->stream_res.tg->funcs->triplebuffer_unlock(pipe->stream_res.tg);
1248 } else {
1249 if (lock)
1250 pipe->stream_res.tg->funcs->lock(pipe->stream_res.tg);
1251 else
1252 pipe->stream_res.tg->funcs->unlock(pipe->stream_res.tg);
1253 }
1254}
1255
1256static void dcn20_detect_pipe_changes(struct pipe_ctx *old_pipe, struct pipe_ctx *new_pipe)
1257{
1258 new_pipe->update_flags.raw = 0;
1259
1260
1261 if (!old_pipe->plane_state && !new_pipe->plane_state)
1262 return;
1263
1264 if (!old_pipe->plane_state && new_pipe->plane_state) {
1265 new_pipe->update_flags.bits.enable = 1;
1266 new_pipe->update_flags.bits.mpcc = 1;
1267 new_pipe->update_flags.bits.dppclk = 1;
1268 new_pipe->update_flags.bits.hubp_interdependent = 1;
1269 new_pipe->update_flags.bits.hubp_rq_dlg_ttu = 1;
1270 new_pipe->update_flags.bits.gamut_remap = 1;
1271 new_pipe->update_flags.bits.scaler = 1;
1272 new_pipe->update_flags.bits.viewport = 1;
1273 new_pipe->update_flags.bits.det_size = 1;
1274 if (!new_pipe->top_pipe && !new_pipe->prev_odm_pipe) {
1275 new_pipe->update_flags.bits.odm = 1;
1276 new_pipe->update_flags.bits.global_sync = 1;
1277 }
1278 return;
1279 }
1280 if (old_pipe->plane_state && !new_pipe->plane_state) {
1281 new_pipe->update_flags.bits.disable = 1;
1282 return;
1283 }
1284
1285
1286 if (old_pipe->plane_state != new_pipe->plane_state) {
1287 new_pipe->update_flags.bits.plane_changed = true;
1288 }
1289
1290
1291 if (!new_pipe->top_pipe && !new_pipe->prev_odm_pipe) {
1292
1293 if ((old_pipe->next_odm_pipe && new_pipe->next_odm_pipe
1294 && old_pipe->next_odm_pipe->pipe_idx != new_pipe->next_odm_pipe->pipe_idx)
1295 || (!old_pipe->next_odm_pipe && new_pipe->next_odm_pipe)
1296 || (old_pipe->next_odm_pipe && !new_pipe->next_odm_pipe)
1297 || old_pipe->stream_res.opp != new_pipe->stream_res.opp)
1298 new_pipe->update_flags.bits.odm = 1;
1299
1300
1301 if (old_pipe->pipe_dlg_param.vready_offset != new_pipe->pipe_dlg_param.vready_offset
1302 || old_pipe->pipe_dlg_param.vstartup_start != new_pipe->pipe_dlg_param.vstartup_start
1303 || old_pipe->pipe_dlg_param.vupdate_offset != new_pipe->pipe_dlg_param.vupdate_offset
1304 || old_pipe->pipe_dlg_param.vupdate_width != new_pipe->pipe_dlg_param.vupdate_width)
1305 new_pipe->update_flags.bits.global_sync = 1;
1306 }
1307
1308 if (old_pipe->det_buffer_size_kb != new_pipe->det_buffer_size_kb)
1309 new_pipe->update_flags.bits.det_size = 1;
1310
1311
1312
1313
1314
1315
1316
1317
1318 if (old_pipe->stream_res.opp != new_pipe->stream_res.opp)
1319 new_pipe->update_flags.bits.opp_changed = 1;
1320 if (old_pipe->stream_res.tg != new_pipe->stream_res.tg)
1321 new_pipe->update_flags.bits.tg_changed = 1;
1322
1323
1324
1325
1326
1327
1328 if (old_pipe->plane_res.dpp != new_pipe->plane_res.dpp
1329 || old_pipe->stream_res.opp != new_pipe->stream_res.opp)
1330 new_pipe->update_flags.bits.mpcc = 1;
1331
1332
1333 if (old_pipe->plane_res.bw.dppclk_khz != new_pipe->plane_res.bw.dppclk_khz)
1334 new_pipe->update_flags.bits.dppclk = 1;
1335
1336
1337 if (memcmp(&old_pipe->plane_res.scl_data, &new_pipe->plane_res.scl_data, sizeof(struct scaler_data)))
1338 new_pipe->update_flags.bits.scaler = 1;
1339
1340 if (memcmp(&old_pipe->plane_res.scl_data.viewport, &new_pipe->plane_res.scl_data.viewport, sizeof(struct rect))
1341 || memcmp(&old_pipe->plane_res.scl_data.viewport_c,
1342 &new_pipe->plane_res.scl_data.viewport_c, sizeof(struct rect)))
1343 new_pipe->update_flags.bits.viewport = 1;
1344
1345
1346 {
1347 struct _vcs_dpi_display_dlg_regs_st old_dlg_attr = old_pipe->dlg_regs;
1348 struct _vcs_dpi_display_ttu_regs_st old_ttu_attr = old_pipe->ttu_regs;
1349 struct _vcs_dpi_display_dlg_regs_st *new_dlg_attr = &new_pipe->dlg_regs;
1350 struct _vcs_dpi_display_ttu_regs_st *new_ttu_attr = &new_pipe->ttu_regs;
1351
1352
1353 if (old_dlg_attr.dst_y_prefetch != new_dlg_attr->dst_y_prefetch ||
1354 old_dlg_attr.vratio_prefetch != new_dlg_attr->vratio_prefetch ||
1355 old_dlg_attr.vratio_prefetch_c != new_dlg_attr->vratio_prefetch_c ||
1356 old_dlg_attr.dst_y_per_vm_vblank != new_dlg_attr->dst_y_per_vm_vblank ||
1357 old_dlg_attr.dst_y_per_row_vblank != new_dlg_attr->dst_y_per_row_vblank ||
1358 old_dlg_attr.dst_y_per_vm_flip != new_dlg_attr->dst_y_per_vm_flip ||
1359 old_dlg_attr.dst_y_per_row_flip != new_dlg_attr->dst_y_per_row_flip ||
1360 old_dlg_attr.refcyc_per_meta_chunk_vblank_l != new_dlg_attr->refcyc_per_meta_chunk_vblank_l ||
1361 old_dlg_attr.refcyc_per_meta_chunk_vblank_c != new_dlg_attr->refcyc_per_meta_chunk_vblank_c ||
1362 old_dlg_attr.refcyc_per_meta_chunk_flip_l != new_dlg_attr->refcyc_per_meta_chunk_flip_l ||
1363 old_dlg_attr.refcyc_per_line_delivery_pre_l != new_dlg_attr->refcyc_per_line_delivery_pre_l ||
1364 old_dlg_attr.refcyc_per_line_delivery_pre_c != new_dlg_attr->refcyc_per_line_delivery_pre_c ||
1365 old_ttu_attr.refcyc_per_req_delivery_pre_l != new_ttu_attr->refcyc_per_req_delivery_pre_l ||
1366 old_ttu_attr.refcyc_per_req_delivery_pre_c != new_ttu_attr->refcyc_per_req_delivery_pre_c ||
1367 old_ttu_attr.refcyc_per_req_delivery_pre_cur0 != new_ttu_attr->refcyc_per_req_delivery_pre_cur0 ||
1368 old_ttu_attr.refcyc_per_req_delivery_pre_cur1 != new_ttu_attr->refcyc_per_req_delivery_pre_cur1 ||
1369 old_ttu_attr.min_ttu_vblank != new_ttu_attr->min_ttu_vblank ||
1370 old_ttu_attr.qos_level_flip != new_ttu_attr->qos_level_flip) {
1371 old_dlg_attr.dst_y_prefetch = new_dlg_attr->dst_y_prefetch;
1372 old_dlg_attr.vratio_prefetch = new_dlg_attr->vratio_prefetch;
1373 old_dlg_attr.vratio_prefetch_c = new_dlg_attr->vratio_prefetch_c;
1374 old_dlg_attr.dst_y_per_vm_vblank = new_dlg_attr->dst_y_per_vm_vblank;
1375 old_dlg_attr.dst_y_per_row_vblank = new_dlg_attr->dst_y_per_row_vblank;
1376 old_dlg_attr.dst_y_per_vm_flip = new_dlg_attr->dst_y_per_vm_flip;
1377 old_dlg_attr.dst_y_per_row_flip = new_dlg_attr->dst_y_per_row_flip;
1378 old_dlg_attr.refcyc_per_meta_chunk_vblank_l = new_dlg_attr->refcyc_per_meta_chunk_vblank_l;
1379 old_dlg_attr.refcyc_per_meta_chunk_vblank_c = new_dlg_attr->refcyc_per_meta_chunk_vblank_c;
1380 old_dlg_attr.refcyc_per_meta_chunk_flip_l = new_dlg_attr->refcyc_per_meta_chunk_flip_l;
1381 old_dlg_attr.refcyc_per_line_delivery_pre_l = new_dlg_attr->refcyc_per_line_delivery_pre_l;
1382 old_dlg_attr.refcyc_per_line_delivery_pre_c = new_dlg_attr->refcyc_per_line_delivery_pre_c;
1383 old_ttu_attr.refcyc_per_req_delivery_pre_l = new_ttu_attr->refcyc_per_req_delivery_pre_l;
1384 old_ttu_attr.refcyc_per_req_delivery_pre_c = new_ttu_attr->refcyc_per_req_delivery_pre_c;
1385 old_ttu_attr.refcyc_per_req_delivery_pre_cur0 = new_ttu_attr->refcyc_per_req_delivery_pre_cur0;
1386 old_ttu_attr.refcyc_per_req_delivery_pre_cur1 = new_ttu_attr->refcyc_per_req_delivery_pre_cur1;
1387 old_ttu_attr.min_ttu_vblank = new_ttu_attr->min_ttu_vblank;
1388 old_ttu_attr.qos_level_flip = new_ttu_attr->qos_level_flip;
1389 new_pipe->update_flags.bits.hubp_interdependent = 1;
1390 }
1391
1392 if (memcmp(&old_dlg_attr, &new_pipe->dlg_regs, sizeof(old_dlg_attr)) ||
1393 memcmp(&old_ttu_attr, &new_pipe->ttu_regs, sizeof(old_ttu_attr)) ||
1394 memcmp(&old_pipe->rq_regs, &new_pipe->rq_regs, sizeof(old_pipe->rq_regs)))
1395 new_pipe->update_flags.bits.hubp_rq_dlg_ttu = 1;
1396 }
1397}
1398
1399static void dcn20_update_dchubp_dpp(
1400 struct dc *dc,
1401 struct pipe_ctx *pipe_ctx,
1402 struct dc_state *context)
1403{
1404 struct dce_hwseq *hws = dc->hwseq;
1405 struct hubp *hubp = pipe_ctx->plane_res.hubp;
1406 struct dpp *dpp = pipe_ctx->plane_res.dpp;
1407 struct dc_plane_state *plane_state = pipe_ctx->plane_state;
1408 bool viewport_changed = false;
1409
1410 if (pipe_ctx->update_flags.bits.dppclk)
1411 dpp->funcs->dpp_dppclk_control(dpp, false, true);
1412
1413
1414
1415
1416
1417 if (pipe_ctx->update_flags.bits.hubp_rq_dlg_ttu) {
1418 hubp->funcs->hubp_vtg_sel(hubp, pipe_ctx->stream_res.tg->inst);
1419
1420 hubp->funcs->hubp_setup(
1421 hubp,
1422 &pipe_ctx->dlg_regs,
1423 &pipe_ctx->ttu_regs,
1424 &pipe_ctx->rq_regs,
1425 &pipe_ctx->pipe_dlg_param);
1426
1427 if (hubp->funcs->set_unbounded_requesting)
1428 hubp->funcs->set_unbounded_requesting(hubp, pipe_ctx->unbounded_req);
1429 }
1430 if (pipe_ctx->update_flags.bits.hubp_interdependent)
1431 hubp->funcs->hubp_setup_interdependent(
1432 hubp,
1433 &pipe_ctx->dlg_regs,
1434 &pipe_ctx->ttu_regs);
1435
1436 if (pipe_ctx->update_flags.bits.enable ||
1437 pipe_ctx->update_flags.bits.plane_changed ||
1438 plane_state->update_flags.bits.bpp_change ||
1439 plane_state->update_flags.bits.input_csc_change ||
1440 plane_state->update_flags.bits.color_space_change ||
1441 plane_state->update_flags.bits.coeff_reduction_change) {
1442 struct dc_bias_and_scale bns_params = {0};
1443
1444
1445 dpp->funcs->dpp_setup(dpp,
1446 plane_state->format,
1447 EXPANSION_MODE_ZERO,
1448 plane_state->input_csc_color_matrix,
1449 plane_state->color_space,
1450 NULL);
1451
1452 if (dpp->funcs->dpp_program_bias_and_scale) {
1453
1454 build_prescale_params(&bns_params, plane_state);
1455 dpp->funcs->dpp_program_bias_and_scale(dpp, &bns_params);
1456 }
1457 }
1458
1459 if (pipe_ctx->update_flags.bits.mpcc
1460 || pipe_ctx->update_flags.bits.plane_changed
1461 || plane_state->update_flags.bits.global_alpha_change
1462 || plane_state->update_flags.bits.per_pixel_alpha_change) {
1463
1464 int mpcc_inst = hubp->inst;
1465 int opp_inst;
1466 int opp_count = dc->res_pool->pipe_count;
1467
1468 for (opp_inst = 0; opp_inst < opp_count; opp_inst++) {
1469 if (dc->res_pool->opps[opp_inst]->mpcc_disconnect_pending[mpcc_inst]) {
1470 dc->res_pool->mpc->funcs->wait_for_idle(dc->res_pool->mpc, mpcc_inst);
1471 dc->res_pool->opps[opp_inst]->mpcc_disconnect_pending[mpcc_inst] = false;
1472 break;
1473 }
1474 }
1475 hws->funcs.update_mpcc(dc, pipe_ctx);
1476 }
1477
1478 if (pipe_ctx->update_flags.bits.scaler ||
1479 plane_state->update_flags.bits.scaling_change ||
1480 plane_state->update_flags.bits.position_change ||
1481 plane_state->update_flags.bits.per_pixel_alpha_change ||
1482 pipe_ctx->stream->update_flags.bits.scaling) {
1483 pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->plane_state->per_pixel_alpha;
1484 ASSERT(pipe_ctx->plane_res.scl_data.lb_params.depth == LB_PIXEL_DEPTH_36BPP);
1485
1486 pipe_ctx->plane_res.dpp->funcs->dpp_set_scaler(
1487 pipe_ctx->plane_res.dpp, &pipe_ctx->plane_res.scl_data);
1488 }
1489
1490 if (pipe_ctx->update_flags.bits.viewport ||
1491 (context == dc->current_state && plane_state->update_flags.bits.position_change) ||
1492 (context == dc->current_state && plane_state->update_flags.bits.scaling_change) ||
1493 (context == dc->current_state && pipe_ctx->stream->update_flags.bits.scaling)) {
1494
1495 hubp->funcs->mem_program_viewport(
1496 hubp,
1497 &pipe_ctx->plane_res.scl_data.viewport,
1498 &pipe_ctx->plane_res.scl_data.viewport_c);
1499 viewport_changed = true;
1500 }
1501
1502
1503 if ((pipe_ctx->update_flags.bits.enable || pipe_ctx->update_flags.bits.opp_changed ||
1504 pipe_ctx->update_flags.bits.scaler || viewport_changed == true) &&
1505 pipe_ctx->stream->cursor_attributes.address.quad_part != 0) {
1506 dc->hwss.set_cursor_position(pipe_ctx);
1507 dc->hwss.set_cursor_attribute(pipe_ctx);
1508
1509 if (dc->hwss.set_cursor_sdr_white_level)
1510 dc->hwss.set_cursor_sdr_white_level(pipe_ctx);
1511 }
1512
1513
1514
1515 if (pipe_ctx->update_flags.bits.enable || pipe_ctx->update_flags.bits.opp_changed
1516 || pipe_ctx->stream->update_flags.bits.gamut_remap
1517 || pipe_ctx->stream->update_flags.bits.out_csc) {
1518
1519 dc->hwss.program_gamut_remap(pipe_ctx);
1520
1521
1522 dc->hwss.program_output_csc(dc,
1523 pipe_ctx,
1524 pipe_ctx->stream->output_color_space,
1525 pipe_ctx->stream->csc_color_matrix.matrix,
1526 hubp->opp_id);
1527 }
1528
1529 if (pipe_ctx->update_flags.bits.enable ||
1530 pipe_ctx->update_flags.bits.plane_changed ||
1531 pipe_ctx->update_flags.bits.opp_changed ||
1532 plane_state->update_flags.bits.pixel_format_change ||
1533 plane_state->update_flags.bits.horizontal_mirror_change ||
1534 plane_state->update_flags.bits.rotation_change ||
1535 plane_state->update_flags.bits.swizzle_change ||
1536 plane_state->update_flags.bits.dcc_change ||
1537 plane_state->update_flags.bits.bpp_change ||
1538 plane_state->update_flags.bits.scaling_change ||
1539 plane_state->update_flags.bits.plane_size_change) {
1540 struct plane_size size = plane_state->plane_size;
1541
1542 size.surface_size = pipe_ctx->plane_res.scl_data.viewport;
1543 hubp->funcs->hubp_program_surface_config(
1544 hubp,
1545 plane_state->format,
1546 &plane_state->tiling_info,
1547 &size,
1548 plane_state->rotation,
1549 &plane_state->dcc,
1550 plane_state->horizontal_mirror,
1551 0);
1552 hubp->power_gated = false;
1553 }
1554
1555 if (pipe_ctx->update_flags.bits.enable ||
1556 pipe_ctx->update_flags.bits.plane_changed ||
1557 plane_state->update_flags.bits.addr_update)
1558 hws->funcs.update_plane_addr(dc, pipe_ctx);
1559
1560
1561
1562 if (pipe_ctx->update_flags.bits.enable)
1563 hubp->funcs->set_blank(hubp, false);
1564}
1565
1566
1567static void dcn20_program_pipe(
1568 struct dc *dc,
1569 struct pipe_ctx *pipe_ctx,
1570 struct dc_state *context)
1571{
1572 struct dce_hwseq *hws = dc->hwseq;
1573
1574 if ((pipe_ctx->update_flags.bits.enable || pipe_ctx->stream->update_flags.bits.abm_level)
1575 && !pipe_ctx->top_pipe && !pipe_ctx->prev_odm_pipe)
1576 hws->funcs.blank_pixel_data(dc, pipe_ctx, !pipe_ctx->plane_state->visible);
1577
1578
1579 if (pipe_ctx->update_flags.bits.global_sync && !pipe_ctx->top_pipe
1580 && !pipe_ctx->prev_odm_pipe) {
1581
1582 pipe_ctx->stream_res.tg->funcs->program_global_sync(
1583 pipe_ctx->stream_res.tg,
1584 pipe_ctx->pipe_dlg_param.vready_offset,
1585 pipe_ctx->pipe_dlg_param.vstartup_start,
1586 pipe_ctx->pipe_dlg_param.vupdate_offset,
1587 pipe_ctx->pipe_dlg_param.vupdate_width);
1588
1589 pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VBLANK);
1590 pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VACTIVE);
1591
1592 pipe_ctx->stream_res.tg->funcs->set_vtg_params(
1593 pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing, true);
1594
1595 if (hws->funcs.setup_vupdate_interrupt)
1596 hws->funcs.setup_vupdate_interrupt(dc, pipe_ctx);
1597 }
1598
1599 if (pipe_ctx->update_flags.bits.odm)
1600 hws->funcs.update_odm(dc, context, pipe_ctx);
1601
1602 if (pipe_ctx->update_flags.bits.enable) {
1603 dcn20_enable_plane(dc, pipe_ctx, context);
1604 if (dc->res_pool->hubbub->funcs->force_wm_propagate_to_pipes)
1605 dc->res_pool->hubbub->funcs->force_wm_propagate_to_pipes(dc->res_pool->hubbub);
1606 }
1607
1608 if (dc->res_pool->hubbub->funcs->program_det_size && pipe_ctx->update_flags.bits.det_size)
1609 dc->res_pool->hubbub->funcs->program_det_size(
1610 dc->res_pool->hubbub, pipe_ctx->plane_res.hubp->inst, pipe_ctx->det_buffer_size_kb);
1611
1612 if (pipe_ctx->update_flags.raw || pipe_ctx->plane_state->update_flags.raw || pipe_ctx->stream->update_flags.raw)
1613 dcn20_update_dchubp_dpp(dc, pipe_ctx, context);
1614
1615 if (pipe_ctx->update_flags.bits.enable
1616 || pipe_ctx->plane_state->update_flags.bits.hdr_mult)
1617 hws->funcs.set_hdr_multiplier(pipe_ctx);
1618
1619 if (pipe_ctx->update_flags.bits.enable ||
1620 pipe_ctx->plane_state->update_flags.bits.in_transfer_func_change ||
1621 pipe_ctx->plane_state->update_flags.bits.gamma_change)
1622 hws->funcs.set_input_transfer_func(dc, pipe_ctx, pipe_ctx->plane_state);
1623
1624
1625
1626
1627
1628 if (pipe_ctx->update_flags.bits.enable || pipe_ctx->stream->update_flags.bits.out_tf)
1629 hws->funcs.set_output_transfer_func(dc, pipe_ctx, pipe_ctx->stream);
1630
1631
1632
1633
1634
1635
1636 if (pipe_ctx->update_flags.bits.enable
1637 || pipe_ctx->update_flags.bits.opp_changed) {
1638
1639 pipe_ctx->stream_res.opp->funcs->opp_set_dyn_expansion(
1640 pipe_ctx->stream_res.opp,
1641 COLOR_SPACE_YCBCR601,
1642 pipe_ctx->stream->timing.display_color_depth,
1643 pipe_ctx->stream->signal);
1644
1645 pipe_ctx->stream_res.opp->funcs->opp_program_fmt(
1646 pipe_ctx->stream_res.opp,
1647 &pipe_ctx->stream->bit_depth_params,
1648 &pipe_ctx->stream->clamping);
1649 }
1650}
1651
1652void dcn20_program_front_end_for_ctx(
1653 struct dc *dc,
1654 struct dc_state *context)
1655{
1656 int i;
1657 struct dce_hwseq *hws = dc->hwseq;
1658 DC_LOGGER_INIT(dc->ctx->logger);
1659
1660
1661 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1662 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1663 struct pipe_ctx *old_pipe_ctx =
1664 &dc->current_state->res_ctx.pipe_ctx[i];
1665
1666 if (pipe_ctx->stream == old_pipe_ctx->stream)
1667 pipe_ctx->stream_res.gsl_group =
1668 old_pipe_ctx->stream_res.gsl_group;
1669 }
1670
1671 if (dc->hwss.program_triplebuffer != NULL && dc->debug.enable_tri_buf) {
1672 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1673 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1674
1675 if (!pipe_ctx->top_pipe && !pipe_ctx->prev_odm_pipe && pipe_ctx->plane_state) {
1676 ASSERT(!pipe_ctx->plane_state->triplebuffer_flips);
1677
1678 dc->hwss.program_triplebuffer(
1679 dc, pipe_ctx, pipe_ctx->plane_state->triplebuffer_flips);
1680 }
1681 }
1682 }
1683
1684
1685 for (i = 0; i < dc->res_pool->pipe_count; i++)
1686 dcn20_detect_pipe_changes(&dc->current_state->res_ctx.pipe_ctx[i],
1687 &context->res_ctx.pipe_ctx[i]);
1688
1689
1690 for (i = 0; i < dc->res_pool->pipe_count; i++)
1691 if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable
1692 && !context->res_ctx.pipe_ctx[i].top_pipe
1693 && !context->res_ctx.pipe_ctx[i].prev_odm_pipe
1694 && context->res_ctx.pipe_ctx[i].stream)
1695 hws->funcs.blank_pixel_data(dc, &context->res_ctx.pipe_ctx[i], true);
1696
1697
1698
1699 for (i = 0; i < dc->res_pool->pipe_count; i++)
1700 if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable
1701 || context->res_ctx.pipe_ctx[i].update_flags.bits.opp_changed) {
1702 struct hubbub *hubbub = dc->res_pool->hubbub;
1703
1704 if (hubbub->funcs->program_det_size && context->res_ctx.pipe_ctx[i].update_flags.bits.disable)
1705 hubbub->funcs->program_det_size(hubbub, dc->current_state->res_ctx.pipe_ctx[i].plane_res.hubp->inst, 0);
1706 hws->funcs.plane_atomic_disconnect(dc, &dc->current_state->res_ctx.pipe_ctx[i]);
1707 DC_LOG_DC("Reset mpcc for pipe %d\n", dc->current_state->res_ctx.pipe_ctx[i].pipe_idx);
1708 }
1709
1710
1711
1712
1713
1714 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1715 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
1716
1717 if (pipe->plane_state && !pipe->top_pipe) {
1718 while (pipe) {
1719 if (hws->funcs.program_pipe)
1720 hws->funcs.program_pipe(dc, pipe, context);
1721 else
1722 dcn20_program_pipe(dc, pipe, context);
1723
1724 pipe = pipe->bottom_pipe;
1725 }
1726
1727 pipe = &context->res_ctx.pipe_ctx[i];
1728 if (!pipe->prev_odm_pipe && pipe->stream->num_wb_info > 0
1729 && (pipe->update_flags.raw || pipe->plane_state->update_flags.raw || pipe->stream->update_flags.raw)
1730 && hws->funcs.program_all_writeback_pipes_in_tree)
1731 hws->funcs.program_all_writeback_pipes_in_tree(dc, pipe->stream, context);
1732 }
1733 }
1734}
1735
1736void dcn20_post_unlock_program_front_end(
1737 struct dc *dc,
1738 struct dc_state *context)
1739{
1740 int i;
1741 const unsigned int TIMEOUT_FOR_PIPE_ENABLE_MS = 100;
1742 struct dce_hwseq *hwseq = dc->hwseq;
1743
1744 DC_LOGGER_INIT(dc->ctx->logger);
1745
1746 for (i = 0; i < dc->res_pool->pipe_count; i++)
1747 if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable)
1748 dc->hwss.disable_plane(dc, &dc->current_state->res_ctx.pipe_ctx[i]);
1749
1750
1751
1752
1753
1754
1755
1756 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1757 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
1758
1759 if (pipe->plane_state && !pipe->top_pipe && pipe->update_flags.bits.enable) {
1760 struct hubp *hubp = pipe->plane_res.hubp;
1761 int j = 0;
1762
1763 for (j = 0; j < TIMEOUT_FOR_PIPE_ENABLE_MS*1000
1764 && hubp->funcs->hubp_is_flip_pending(hubp); j++)
1765 mdelay(1);
1766 }
1767 }
1768
1769 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1770 struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
1771 struct pipe_ctx *mpcc_pipe;
1772
1773 if (pipe->vtp_locked) {
1774 dc->hwseq->funcs.wait_for_blank_complete(pipe->stream_res.opp);
1775 pipe->plane_res.hubp->funcs->set_blank(pipe->plane_res.hubp, true);
1776 pipe->vtp_locked = false;
1777
1778 for (mpcc_pipe = pipe->bottom_pipe; mpcc_pipe; mpcc_pipe = mpcc_pipe->bottom_pipe)
1779 mpcc_pipe->plane_res.hubp->funcs->set_blank(mpcc_pipe->plane_res.hubp, true);
1780
1781 for (i = 0; i < dc->res_pool->pipe_count; i++)
1782 if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable)
1783 dc->hwss.disable_plane(dc, &dc->current_state->res_ctx.pipe_ctx[i]);
1784 }
1785 }
1786
1787 if (hwseq->wa.DEGVIDCN21)
1788 dc->res_pool->hubbub->funcs->apply_DEDCN21_147_wa(dc->res_pool->hubbub);
1789
1790
1791
1792 if (hwseq->wa.disallow_self_refresh_during_multi_plane_transition) {
1793
1794 if (dc->current_state->stream_status[0].plane_count == 1 &&
1795 context->stream_status[0].plane_count > 1) {
1796
1797 struct timing_generator *tg = dc->res_pool->timing_generators[0];
1798
1799 dc->res_pool->hubbub->funcs->allow_self_refresh_control(dc->res_pool->hubbub, false);
1800
1801 hwseq->wa_state.disallow_self_refresh_during_multi_plane_transition_applied = true;
1802 hwseq->wa_state.disallow_self_refresh_during_multi_plane_transition_applied_on_frame = tg->funcs->get_frame_count(tg);
1803 }
1804 }
1805}
1806
1807void dcn20_prepare_bandwidth(
1808 struct dc *dc,
1809 struct dc_state *context)
1810{
1811 struct hubbub *hubbub = dc->res_pool->hubbub;
1812
1813 dc->clk_mgr->funcs->update_clocks(
1814 dc->clk_mgr,
1815 context,
1816 false);
1817
1818
1819 dc->wm_optimized_required = hubbub->funcs->program_watermarks(hubbub,
1820 &context->bw_ctx.bw.dcn.watermarks,
1821 dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000,
1822 false);
1823
1824 if (hubbub->funcs->program_compbuf_size)
1825 hubbub->funcs->program_compbuf_size(hubbub, context->bw_ctx.bw.dcn.compbuf_size_kb, false);
1826}
1827
1828void dcn20_optimize_bandwidth(
1829 struct dc *dc,
1830 struct dc_state *context)
1831{
1832 struct hubbub *hubbub = dc->res_pool->hubbub;
1833
1834
1835 hubbub->funcs->program_watermarks(hubbub,
1836 &context->bw_ctx.bw.dcn.watermarks,
1837 dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000,
1838 true);
1839
1840 dc->clk_mgr->funcs->update_clocks(
1841 dc->clk_mgr,
1842 context,
1843 true);
1844
1845 if (hubbub->funcs->program_compbuf_size)
1846 hubbub->funcs->program_compbuf_size(hubbub, context->bw_ctx.bw.dcn.compbuf_size_kb, true);
1847}
1848
1849bool dcn20_update_bandwidth(
1850 struct dc *dc,
1851 struct dc_state *context)
1852{
1853 int i;
1854 struct dce_hwseq *hws = dc->hwseq;
1855
1856
1857 if (!dc->res_pool->funcs->validate_bandwidth(dc, context, false))
1858 return false;
1859
1860
1861 dc->hwss.prepare_bandwidth(dc, context);
1862
1863
1864 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1865 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1866
1867 if (pipe_ctx->plane_state == NULL)
1868 continue;
1869
1870 if (pipe_ctx->top_pipe == NULL) {
1871 bool blank = !is_pipe_tree_visible(pipe_ctx);
1872
1873 pipe_ctx->stream_res.tg->funcs->program_global_sync(
1874 pipe_ctx->stream_res.tg,
1875 pipe_ctx->pipe_dlg_param.vready_offset,
1876 pipe_ctx->pipe_dlg_param.vstartup_start,
1877 pipe_ctx->pipe_dlg_param.vupdate_offset,
1878 pipe_ctx->pipe_dlg_param.vupdate_width);
1879
1880 pipe_ctx->stream_res.tg->funcs->set_vtg_params(
1881 pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing, false);
1882
1883 if (pipe_ctx->prev_odm_pipe == NULL)
1884 hws->funcs.blank_pixel_data(dc, pipe_ctx, blank);
1885
1886 if (hws->funcs.setup_vupdate_interrupt)
1887 hws->funcs.setup_vupdate_interrupt(dc, pipe_ctx);
1888 }
1889
1890 pipe_ctx->plane_res.hubp->funcs->hubp_setup(
1891 pipe_ctx->plane_res.hubp,
1892 &pipe_ctx->dlg_regs,
1893 &pipe_ctx->ttu_regs,
1894 &pipe_ctx->rq_regs,
1895 &pipe_ctx->pipe_dlg_param);
1896 }
1897
1898 return true;
1899}
1900
1901void dcn20_enable_writeback(
1902 struct dc *dc,
1903 struct dc_writeback_info *wb_info,
1904 struct dc_state *context)
1905{
1906 struct dwbc *dwb;
1907 struct mcif_wb *mcif_wb;
1908 struct timing_generator *optc;
1909
1910 ASSERT(wb_info->dwb_pipe_inst < MAX_DWB_PIPES);
1911 ASSERT(wb_info->wb_enabled);
1912 dwb = dc->res_pool->dwbc[wb_info->dwb_pipe_inst];
1913 mcif_wb = dc->res_pool->mcif_wb[wb_info->dwb_pipe_inst];
1914
1915
1916 optc = dc->res_pool->timing_generators[dwb->otg_inst];
1917 optc->funcs->set_dwb_source(optc, wb_info->dwb_pipe_inst);
1918
1919 mcif_wb->funcs->config_mcif_buf(mcif_wb, &wb_info->mcif_buf_params, wb_info->dwb_params.dest_height);
1920 mcif_wb->funcs->config_mcif_arb(mcif_wb, &context->bw_ctx.bw.dcn.bw_writeback.mcif_wb_arb[wb_info->dwb_pipe_inst]);
1921
1922 mcif_wb->funcs->enable_mcif(mcif_wb);
1923
1924 dwb->funcs->enable(dwb, &wb_info->dwb_params);
1925
1926}
1927
1928void dcn20_disable_writeback(
1929 struct dc *dc,
1930 unsigned int dwb_pipe_inst)
1931{
1932 struct dwbc *dwb;
1933 struct mcif_wb *mcif_wb;
1934
1935 ASSERT(dwb_pipe_inst < MAX_DWB_PIPES);
1936 dwb = dc->res_pool->dwbc[dwb_pipe_inst];
1937 mcif_wb = dc->res_pool->mcif_wb[dwb_pipe_inst];
1938
1939 dwb->funcs->disable(dwb);
1940 mcif_wb->funcs->disable_mcif(mcif_wb);
1941}
1942
1943bool dcn20_wait_for_blank_complete(
1944 struct output_pixel_processor *opp)
1945{
1946 int counter;
1947
1948 for (counter = 0; counter < 1000; counter++) {
1949 if (opp->funcs->dpg_is_blanked(opp))
1950 break;
1951
1952 udelay(100);
1953 }
1954
1955 if (counter == 1000) {
1956 dm_error("DC: failed to blank crtc!\n");
1957 return false;
1958 }
1959
1960 return true;
1961}
1962
1963bool dcn20_dmdata_status_done(struct pipe_ctx *pipe_ctx)
1964{
1965 struct hubp *hubp = pipe_ctx->plane_res.hubp;
1966
1967 if (!hubp)
1968 return false;
1969 return hubp->funcs->dmdata_status_done(hubp);
1970}
1971
1972void dcn20_disable_stream_gating(struct dc *dc, struct pipe_ctx *pipe_ctx)
1973{
1974 struct dce_hwseq *hws = dc->hwseq;
1975
1976 if (pipe_ctx->stream_res.dsc) {
1977 struct pipe_ctx *odm_pipe = pipe_ctx->next_odm_pipe;
1978
1979 hws->funcs.dsc_pg_control(hws, pipe_ctx->stream_res.dsc->inst, true);
1980 while (odm_pipe) {
1981 hws->funcs.dsc_pg_control(hws, odm_pipe->stream_res.dsc->inst, true);
1982 odm_pipe = odm_pipe->next_odm_pipe;
1983 }
1984 }
1985}
1986
1987void dcn20_enable_stream_gating(struct dc *dc, struct pipe_ctx *pipe_ctx)
1988{
1989 struct dce_hwseq *hws = dc->hwseq;
1990
1991 if (pipe_ctx->stream_res.dsc) {
1992 struct pipe_ctx *odm_pipe = pipe_ctx->next_odm_pipe;
1993
1994 hws->funcs.dsc_pg_control(hws, pipe_ctx->stream_res.dsc->inst, false);
1995 while (odm_pipe) {
1996 hws->funcs.dsc_pg_control(hws, odm_pipe->stream_res.dsc->inst, false);
1997 odm_pipe = odm_pipe->next_odm_pipe;
1998 }
1999 }
2000}
2001
2002void dcn20_set_dmdata_attributes(struct pipe_ctx *pipe_ctx)
2003{
2004 struct dc_dmdata_attributes attr = { 0 };
2005 struct hubp *hubp = pipe_ctx->plane_res.hubp;
2006
2007 attr.dmdata_mode = DMDATA_HW_MODE;
2008 attr.dmdata_size =
2009 dc_is_hdmi_signal(pipe_ctx->stream->signal) ? 32 : 36;
2010 attr.address.quad_part =
2011 pipe_ctx->stream->dmdata_address.quad_part;
2012 attr.dmdata_dl_delta = 0;
2013 attr.dmdata_qos_mode = 0;
2014 attr.dmdata_qos_level = 0;
2015 attr.dmdata_repeat = 1;
2016 attr.dmdata_updated = 1;
2017 attr.dmdata_sw_data = NULL;
2018
2019 hubp->funcs->dmdata_set_attributes(hubp, &attr);
2020}
2021
2022void dcn20_init_vm_ctx(
2023 struct dce_hwseq *hws,
2024 struct dc *dc,
2025 struct dc_virtual_addr_space_config *va_config,
2026 int vmid)
2027{
2028 struct dcn_hubbub_virt_addr_config config;
2029
2030 if (vmid == 0) {
2031 ASSERT(0);
2032 return;
2033 }
2034
2035 config.page_table_start_addr = va_config->page_table_start_addr;
2036 config.page_table_end_addr = va_config->page_table_end_addr;
2037 config.page_table_block_size = va_config->page_table_block_size_in_bytes;
2038 config.page_table_depth = va_config->page_table_depth;
2039 config.page_table_base_addr = va_config->page_table_base_addr;
2040
2041 dc->res_pool->hubbub->funcs->init_vm_ctx(dc->res_pool->hubbub, &config, vmid);
2042}
2043
2044int dcn20_init_sys_ctx(struct dce_hwseq *hws, struct dc *dc, struct dc_phy_addr_space_config *pa_config)
2045{
2046 struct dcn_hubbub_phys_addr_config config;
2047
2048 config.system_aperture.fb_top = pa_config->system_aperture.fb_top;
2049 config.system_aperture.fb_offset = pa_config->system_aperture.fb_offset;
2050 config.system_aperture.fb_base = pa_config->system_aperture.fb_base;
2051 config.system_aperture.agp_top = pa_config->system_aperture.agp_top;
2052 config.system_aperture.agp_bot = pa_config->system_aperture.agp_bot;
2053 config.system_aperture.agp_base = pa_config->system_aperture.agp_base;
2054 config.gart_config.page_table_start_addr = pa_config->gart_config.page_table_start_addr;
2055 config.gart_config.page_table_end_addr = pa_config->gart_config.page_table_end_addr;
2056 config.gart_config.page_table_base_addr = pa_config->gart_config.page_table_base_addr;
2057 config.page_table_default_page_addr = pa_config->page_table_default_page_addr;
2058
2059 return dc->res_pool->hubbub->funcs->init_dchub_sys_ctx(dc->res_pool->hubbub, &config);
2060}
2061
2062static bool patch_address_for_sbs_tb_stereo(
2063 struct pipe_ctx *pipe_ctx, PHYSICAL_ADDRESS_LOC *addr)
2064{
2065 struct dc_plane_state *plane_state = pipe_ctx->plane_state;
2066 bool sec_split = pipe_ctx->top_pipe &&
2067 pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state;
2068 if (sec_split && plane_state->address.type == PLN_ADDR_TYPE_GRPH_STEREO &&
2069 (pipe_ctx->stream->timing.timing_3d_format ==
2070 TIMING_3D_FORMAT_SIDE_BY_SIDE ||
2071 pipe_ctx->stream->timing.timing_3d_format ==
2072 TIMING_3D_FORMAT_TOP_AND_BOTTOM)) {
2073 *addr = plane_state->address.grph_stereo.left_addr;
2074 plane_state->address.grph_stereo.left_addr =
2075 plane_state->address.grph_stereo.right_addr;
2076 return true;
2077 }
2078
2079 if (pipe_ctx->stream->view_format != VIEW_3D_FORMAT_NONE &&
2080 plane_state->address.type != PLN_ADDR_TYPE_GRPH_STEREO) {
2081 plane_state->address.type = PLN_ADDR_TYPE_GRPH_STEREO;
2082 plane_state->address.grph_stereo.right_addr =
2083 plane_state->address.grph_stereo.left_addr;
2084 plane_state->address.grph_stereo.right_meta_addr =
2085 plane_state->address.grph_stereo.left_meta_addr;
2086 }
2087 return false;
2088}
2089
2090void dcn20_update_plane_addr(const struct dc *dc, struct pipe_ctx *pipe_ctx)
2091{
2092 bool addr_patched = false;
2093 PHYSICAL_ADDRESS_LOC addr;
2094 struct dc_plane_state *plane_state = pipe_ctx->plane_state;
2095
2096 if (plane_state == NULL)
2097 return;
2098
2099 addr_patched = patch_address_for_sbs_tb_stereo(pipe_ctx, &addr);
2100
2101
2102 vm_helper_mark_vmid_used(dc->vm_helper, plane_state->address.vmid, pipe_ctx->plane_res.hubp->inst);
2103
2104 pipe_ctx->plane_res.hubp->funcs->hubp_program_surface_flip_and_addr(
2105 pipe_ctx->plane_res.hubp,
2106 &plane_state->address,
2107 plane_state->flip_immediate);
2108
2109 plane_state->status.requested_address = plane_state->address;
2110
2111 if (plane_state->flip_immediate)
2112 plane_state->status.current_address = plane_state->address;
2113
2114 if (addr_patched)
2115 pipe_ctx->plane_state->address.grph_stereo.left_addr = addr;
2116}
2117
2118void dcn20_unblank_stream(struct pipe_ctx *pipe_ctx,
2119 struct dc_link_settings *link_settings)
2120{
2121 struct encoder_unblank_param params = { { 0 } };
2122 struct dc_stream_state *stream = pipe_ctx->stream;
2123 struct dc_link *link = stream->link;
2124 struct dce_hwseq *hws = link->dc->hwseq;
2125 struct pipe_ctx *odm_pipe;
2126
2127 params.opp_cnt = 1;
2128 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
2129 params.opp_cnt++;
2130 }
2131
2132 params.timing = pipe_ctx->stream->timing;
2133
2134 params.link_settings.link_rate = link_settings->link_rate;
2135
2136 if (dc_is_dp_signal(pipe_ctx->stream->signal)) {
2137 if (optc2_is_two_pixels_per_containter(&stream->timing) || params.opp_cnt > 1)
2138 params.timing.pix_clk_100hz /= 2;
2139 pipe_ctx->stream_res.stream_enc->funcs->dp_set_odm_combine(
2140 pipe_ctx->stream_res.stream_enc, params.opp_cnt > 1);
2141 pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(pipe_ctx->stream_res.stream_enc, ¶ms);
2142 }
2143
2144 if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP) {
2145 hws->funcs.edp_backlight_control(link, true);
2146 }
2147}
2148
2149void dcn20_setup_vupdate_interrupt(struct dc *dc, struct pipe_ctx *pipe_ctx)
2150{
2151 struct timing_generator *tg = pipe_ctx->stream_res.tg;
2152 int start_line = dc->hwss.get_vupdate_offset_from_vsync(pipe_ctx);
2153
2154 if (start_line < 0)
2155 start_line = 0;
2156
2157 if (tg->funcs->setup_vertical_interrupt2)
2158 tg->funcs->setup_vertical_interrupt2(tg, start_line);
2159}
2160
2161static void dcn20_reset_back_end_for_pipe(
2162 struct dc *dc,
2163 struct pipe_ctx *pipe_ctx,
2164 struct dc_state *context)
2165{
2166 int i;
2167 struct dc_link *link;
2168 DC_LOGGER_INIT(dc->ctx->logger);
2169 if (pipe_ctx->stream_res.stream_enc == NULL) {
2170 pipe_ctx->stream = NULL;
2171 return;
2172 }
2173
2174 if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
2175 link = pipe_ctx->stream->link;
2176
2177
2178
2179
2180
2181
2182 if (!pipe_ctx->stream->dpms_off || link->link_status.link_active)
2183 core_link_disable_stream(pipe_ctx);
2184 else if (pipe_ctx->stream_res.audio)
2185 dc->hwss.disable_audio_stream(pipe_ctx);
2186
2187
2188 if (pipe_ctx->stream_res.audio) {
2189
2190 pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio);
2191
2192
2193 if (dc->caps.dynamic_audio == true) {
2194
2195
2196 update_audio_usage(&dc->current_state->res_ctx, dc->res_pool,
2197 pipe_ctx->stream_res.audio, false);
2198 pipe_ctx->stream_res.audio = NULL;
2199 }
2200 }
2201 }
2202 else if (pipe_ctx->stream_res.dsc) {
2203 dp_set_dsc_enable(pipe_ctx, false);
2204 }
2205
2206
2207
2208
2209
2210 if (pipe_ctx->top_pipe == NULL) {
2211
2212 dc->hwss.set_abm_immediate_disable(pipe_ctx);
2213
2214 pipe_ctx->stream_res.tg->funcs->disable_crtc(pipe_ctx->stream_res.tg);
2215
2216 pipe_ctx->stream_res.tg->funcs->enable_optc_clock(pipe_ctx->stream_res.tg, false);
2217 if (pipe_ctx->stream_res.tg->funcs->set_odm_bypass)
2218 pipe_ctx->stream_res.tg->funcs->set_odm_bypass(
2219 pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing);
2220
2221 if (pipe_ctx->stream_res.tg->funcs->set_drr)
2222 pipe_ctx->stream_res.tg->funcs->set_drr(
2223 pipe_ctx->stream_res.tg, NULL);
2224 }
2225
2226 for (i = 0; i < dc->res_pool->pipe_count; i++)
2227 if (&dc->current_state->res_ctx.pipe_ctx[i] == pipe_ctx)
2228 break;
2229
2230 if (i == dc->res_pool->pipe_count)
2231 return;
2232
2233 pipe_ctx->stream = NULL;
2234 DC_LOG_DEBUG("Reset back end for pipe %d, tg:%d\n",
2235 pipe_ctx->pipe_idx, pipe_ctx->stream_res.tg->inst);
2236}
2237
2238void dcn20_reset_hw_ctx_wrap(
2239 struct dc *dc,
2240 struct dc_state *context)
2241{
2242 int i;
2243 struct dce_hwseq *hws = dc->hwseq;
2244
2245
2246 for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) {
2247 struct pipe_ctx *pipe_ctx_old =
2248 &dc->current_state->res_ctx.pipe_ctx[i];
2249 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2250
2251 if (!pipe_ctx_old->stream)
2252 continue;
2253
2254 if (pipe_ctx_old->top_pipe || pipe_ctx_old->prev_odm_pipe)
2255 continue;
2256
2257 if (!pipe_ctx->stream ||
2258 pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) {
2259 struct clock_source *old_clk = pipe_ctx_old->clock_source;
2260
2261 dcn20_reset_back_end_for_pipe(dc, pipe_ctx_old, dc->current_state);
2262 if (hws->funcs.enable_stream_gating)
2263 hws->funcs.enable_stream_gating(dc, pipe_ctx);
2264 if (old_clk)
2265 old_clk->funcs->cs_power_down(old_clk);
2266 }
2267 }
2268}
2269
2270void dcn20_update_visual_confirm_color(struct dc *dc, struct pipe_ctx *pipe_ctx, struct tg_color *color, int mpcc_id)
2271{
2272 struct mpc *mpc = dc->res_pool->mpc;
2273
2274
2275 if (dc->debug.visual_confirm == VISUAL_CONFIRM_HDR)
2276 get_hdr_visual_confirm_color(pipe_ctx, color);
2277 else if (dc->debug.visual_confirm == VISUAL_CONFIRM_SURFACE)
2278 get_surface_visual_confirm_color(pipe_ctx, color);
2279 else if (dc->debug.visual_confirm == VISUAL_CONFIRM_MPCTREE)
2280 get_mpctree_visual_confirm_color(pipe_ctx, color);
2281 else if (dc->debug.visual_confirm == VISUAL_CONFIRM_SWIZZLE)
2282 get_surface_tile_visual_confirm_color(pipe_ctx, color);
2283
2284 if (mpc->funcs->set_bg_color)
2285 mpc->funcs->set_bg_color(mpc, color, mpcc_id);
2286}
2287
2288void dcn20_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx)
2289{
2290 struct hubp *hubp = pipe_ctx->plane_res.hubp;
2291 struct mpcc_blnd_cfg blnd_cfg = { {0} };
2292 bool per_pixel_alpha = pipe_ctx->plane_state->per_pixel_alpha;
2293 int mpcc_id;
2294 struct mpcc *new_mpcc;
2295 struct mpc *mpc = dc->res_pool->mpc;
2296 struct mpc_tree *mpc_tree_params = &(pipe_ctx->stream_res.opp->mpc_tree_params);
2297
2298 if (per_pixel_alpha)
2299 blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA;
2300 else
2301 blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_GLOBAL_ALPHA;
2302
2303 blnd_cfg.overlap_only = false;
2304 blnd_cfg.global_gain = 0xff;
2305
2306 if (pipe_ctx->plane_state->global_alpha)
2307 blnd_cfg.global_alpha = pipe_ctx->plane_state->global_alpha_value;
2308 else
2309 blnd_cfg.global_alpha = 0xff;
2310
2311 blnd_cfg.background_color_bpc = 4;
2312 blnd_cfg.bottom_gain_mode = 0;
2313 blnd_cfg.top_gain = 0x1f000;
2314 blnd_cfg.bottom_inside_gain = 0x1f000;
2315 blnd_cfg.bottom_outside_gain = 0x1f000;
2316 blnd_cfg.pre_multiplied_alpha = per_pixel_alpha;
2317 if (pipe_ctx->plane_state->format
2318 == SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA)
2319 blnd_cfg.pre_multiplied_alpha = false;
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329 mpcc_id = hubp->inst;
2330
2331
2332 if (!pipe_ctx->plane_state->update_flags.bits.full_update &&
2333 !pipe_ctx->update_flags.bits.mpcc) {
2334 mpc->funcs->update_blending(mpc, &blnd_cfg, mpcc_id);
2335 dc->hwss.update_visual_confirm_color(dc, pipe_ctx, &blnd_cfg.black_color, mpcc_id);
2336 return;
2337 }
2338
2339
2340 new_mpcc = mpc->funcs->get_mpcc_for_dpp(mpc_tree_params, mpcc_id);
2341
2342 if (new_mpcc != NULL)
2343 mpc->funcs->remove_mpcc(mpc, mpc_tree_params, new_mpcc);
2344 else
2345 if (dc->debug.sanity_checks)
2346 mpc->funcs->assert_mpcc_idle_before_connect(
2347 dc->res_pool->mpc, mpcc_id);
2348
2349
2350 new_mpcc = mpc->funcs->insert_plane(dc->res_pool->mpc,
2351 mpc_tree_params,
2352 &blnd_cfg,
2353 NULL,
2354 NULL,
2355 hubp->inst,
2356 mpcc_id);
2357 dc->hwss.update_visual_confirm_color(dc, pipe_ctx, &blnd_cfg.black_color, mpcc_id);
2358
2359 ASSERT(new_mpcc != NULL);
2360 hubp->opp_id = pipe_ctx->stream_res.opp->inst;
2361 hubp->mpcc_id = mpcc_id;
2362}
2363
2364void dcn20_enable_stream(struct pipe_ctx *pipe_ctx)
2365{
2366 enum dc_lane_count lane_count =
2367 pipe_ctx->stream->link->cur_link_settings.lane_count;
2368
2369 struct dc_crtc_timing *timing = &pipe_ctx->stream->timing;
2370 struct dc_link *link = pipe_ctx->stream->link;
2371
2372 uint32_t active_total_with_borders;
2373 uint32_t early_control = 0;
2374 struct timing_generator *tg = pipe_ctx->stream_res.tg;
2375
2376
2377
2378
2379
2380
2381 link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc,
2382 pipe_ctx->stream_res.stream_enc->id, true);
2383
2384 if (pipe_ctx->plane_state && pipe_ctx->plane_state->flip_immediate != 1) {
2385 if (link->dc->hwss.program_dmdata_engine)
2386 link->dc->hwss.program_dmdata_engine(pipe_ctx);
2387 }
2388
2389 link->dc->hwss.update_info_frame(pipe_ctx);
2390
2391
2392 active_total_with_borders =
2393 timing->h_addressable
2394 + timing->h_border_left
2395 + timing->h_border_right;
2396
2397 if (lane_count != 0)
2398 early_control = active_total_with_borders % lane_count;
2399
2400 if (early_control == 0)
2401 early_control = lane_count;
2402
2403 tg->funcs->set_early_control(tg, early_control);
2404
2405
2406 if (pipe_ctx->stream_res.audio != NULL) {
2407 if (dc_is_dp_signal(pipe_ctx->stream->signal))
2408 pipe_ctx->stream_res.stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_res.stream_enc);
2409 }
2410}
2411
2412void dcn20_program_dmdata_engine(struct pipe_ctx *pipe_ctx)
2413{
2414 struct dc_stream_state *stream = pipe_ctx->stream;
2415 struct hubp *hubp = pipe_ctx->plane_res.hubp;
2416 bool enable = false;
2417 struct stream_encoder *stream_enc = pipe_ctx->stream_res.stream_enc;
2418 enum dynamic_metadata_mode mode = dc_is_dp_signal(stream->signal)
2419 ? dmdata_dp
2420 : dmdata_hdmi;
2421
2422
2423 if (pipe_ctx->stream->dmdata_address.quad_part != 0) {
2424 pipe_ctx->stream_res.encoder_info_frame.hdrsmd.valid = false;
2425 enable = true;
2426 }
2427
2428 if (!hubp)
2429 return;
2430
2431 if (!stream_enc || !stream_enc->funcs->set_dynamic_metadata)
2432 return;
2433
2434 stream_enc->funcs->set_dynamic_metadata(stream_enc, enable,
2435 hubp->inst, mode);
2436}
2437
2438void dcn20_fpga_init_hw(struct dc *dc)
2439{
2440 int i, j;
2441 struct dce_hwseq *hws = dc->hwseq;
2442 struct resource_pool *res_pool = dc->res_pool;
2443 struct dc_state *context = dc->current_state;
2444
2445 if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks)
2446 dc->clk_mgr->funcs->init_clocks(dc->clk_mgr);
2447
2448
2449 if (res_pool->dccg->funcs->dccg_init)
2450 res_pool->dccg->funcs->dccg_init(res_pool->dccg);
2451
2452
2453 hws->funcs.enable_power_gating_plane(hws, true);
2454
2455
2456 REG_WRITE(RBBMIF_TIMEOUT_DIS, 0xFFFFFFFF);
2457 REG_WRITE(RBBMIF_TIMEOUT_DIS_2, 0xFFFFFFFF);
2458
2459 hws->funcs.dccg_init(hws);
2460
2461 REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, 2);
2462 REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1);
2463 if (REG(REFCLK_CNTL))
2464 REG_WRITE(REFCLK_CNTL, 0);
2465
2466
2467
2468
2469 for (i = 0; i < dc->res_pool->timing_generator_count; i++) {
2470 struct timing_generator *tg = dc->res_pool->timing_generators[i];
2471
2472 if (tg->funcs->is_tg_enabled(tg))
2473 dcn20_init_blank(dc, tg);
2474 }
2475
2476 for (i = 0; i < res_pool->timing_generator_count; i++) {
2477 struct timing_generator *tg = dc->res_pool->timing_generators[i];
2478
2479 if (tg->funcs->is_tg_enabled(tg))
2480 tg->funcs->lock(tg);
2481 }
2482
2483 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2484 struct dpp *dpp = res_pool->dpps[i];
2485
2486 dpp->funcs->dpp_reset(dpp);
2487 }
2488
2489
2490 res_pool->mpc->funcs->mpc_init(res_pool->mpc);
2491
2492
2493 for (i = 0; i < dc->res_pool->res_cap->num_opp; i++) {
2494 res_pool->opps[i]->mpc_tree_params.opp_id = res_pool->opps[i]->inst;
2495 res_pool->opps[i]->mpc_tree_params.opp_list = NULL;
2496 for (j = 0; j < MAX_PIPES; j++)
2497 res_pool->opps[i]->mpcc_disconnect_pending[j] = false;
2498 }
2499
2500 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2501 struct timing_generator *tg = dc->res_pool->timing_generators[i];
2502 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2503 struct hubp *hubp = dc->res_pool->hubps[i];
2504 struct dpp *dpp = dc->res_pool->dpps[i];
2505
2506 pipe_ctx->stream_res.tg = tg;
2507 pipe_ctx->pipe_idx = i;
2508
2509 pipe_ctx->plane_res.hubp = hubp;
2510 pipe_ctx->plane_res.dpp = dpp;
2511 pipe_ctx->plane_res.mpcc_inst = dpp->inst;
2512 hubp->mpcc_id = dpp->inst;
2513 hubp->opp_id = OPP_ID_INVALID;
2514 hubp->power_gated = false;
2515 pipe_ctx->stream_res.opp = NULL;
2516
2517 hubp->funcs->hubp_init(hubp);
2518
2519
2520
2521 dc->res_pool->opps[i]->mpcc_disconnect_pending[pipe_ctx->plane_res.mpcc_inst] = true;
2522 pipe_ctx->stream_res.opp = dc->res_pool->opps[i];
2523
2524 hws->funcs.plane_atomic_disconnect(dc, pipe_ctx);
2525 }
2526
2527
2528 for (i = 0; i < res_pool->res_cap->num_dwb; i++)
2529 res_pool->dwbc[i]->mcif = res_pool->mcif_wb[i];
2530
2531 for (i = 0; i < dc->res_pool->timing_generator_count; i++) {
2532 struct timing_generator *tg = dc->res_pool->timing_generators[i];
2533
2534 if (tg->funcs->is_tg_enabled(tg))
2535 tg->funcs->unlock(tg);
2536 }
2537
2538 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2539 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2540
2541 dc->hwss.disable_plane(dc, pipe_ctx);
2542
2543 pipe_ctx->stream_res.tg = NULL;
2544 pipe_ctx->plane_res.hubp = NULL;
2545 }
2546
2547 for (i = 0; i < dc->res_pool->timing_generator_count; i++) {
2548 struct timing_generator *tg = dc->res_pool->timing_generators[i];
2549
2550 tg->funcs->tg_init(tg);
2551 }
2552
2553 if (dc->res_pool->hubbub->funcs->init_crb)
2554 dc->res_pool->hubbub->funcs->init_crb(dc->res_pool->hubbub);
2555}
2556#ifndef TRIM_FSFT
2557bool dcn20_optimize_timing_for_fsft(struct dc *dc,
2558 struct dc_crtc_timing *timing,
2559 unsigned int max_input_rate_in_khz)
2560{
2561 unsigned int old_v_front_porch;
2562 unsigned int old_v_total;
2563 unsigned int max_input_rate_in_100hz;
2564 unsigned long long new_v_total;
2565
2566 max_input_rate_in_100hz = max_input_rate_in_khz * 10;
2567 if (max_input_rate_in_100hz < timing->pix_clk_100hz)
2568 return false;
2569
2570 old_v_total = timing->v_total;
2571 old_v_front_porch = timing->v_front_porch;
2572
2573 timing->fast_transport_output_rate_100hz = timing->pix_clk_100hz;
2574 timing->pix_clk_100hz = max_input_rate_in_100hz;
2575
2576 new_v_total = div_u64((unsigned long long)old_v_total * max_input_rate_in_100hz, timing->pix_clk_100hz);
2577
2578 timing->v_total = new_v_total;
2579 timing->v_front_porch = old_v_front_porch + (timing->v_total - old_v_total);
2580 return true;
2581}
2582#endif
2583
2584void dcn20_set_disp_pattern_generator(const struct dc *dc,
2585 struct pipe_ctx *pipe_ctx,
2586 enum controller_dp_test_pattern test_pattern,
2587 enum controller_dp_color_space color_space,
2588 enum dc_color_depth color_depth,
2589 const struct tg_color *solid_color,
2590 int width, int height, int offset)
2591{
2592 pipe_ctx->stream_res.opp->funcs->opp_set_disp_pattern_generator(pipe_ctx->stream_res.opp, test_pattern,
2593 color_space, color_depth, solid_color, width, height, offset);
2594}
2595