This source file includes following definitions.
- dcn20_enable_power_gating_plane
- dcn20_dccg_init
- dcn20_display_init
- dcn20_disable_vga
- dcn20_program_tripleBuffer
- dcn20_init_blank
- dcn20_dsc_pg_control
- dcn20_dpp_pg_control
- dcn20_hubp_pg_control
- dcn20_plane_atomic_disable
- dcn20_disable_plane
- dcn20_enable_stream_timing
- dcn20_program_output_csc
- dcn20_set_output_transfer_func
- dcn20_set_blend_lut
- dcn20_set_shaper_3dlut
- dcn20_set_input_transfer_func
- dcn20_update_odm
- dcn20_blank_pixel_data
- dcn20_power_on_plane
- dcn20_enable_plane
- dcn20_program_pipe
- dcn20_program_all_pipe_in_tree
- dcn20_pipe_control_lock_global
- dcn20_pipe_control_lock
- dcn20_apply_ctx_for_surface
- dcn20_prepare_bandwidth
- dcn20_optimize_bandwidth
- dcn20_update_bandwidth
- dcn20_enable_writeback
- dcn20_disable_writeback
- dcn20_hwss_wait_for_blank_complete
- dcn20_dmdata_status_done
- dcn20_disable_stream_gating
- dcn20_enable_stream_gating
- dcn20_set_dmdata_attributes
- dcn20_disable_stream
- dcn20_init_vm_ctx
- dcn20_init_sys_ctx
- patch_address_for_sbs_tb_stereo
- dcn20_update_plane_addr
- dcn20_unblank_stream
- dcn20_setup_vupdate_interrupt
- dcn20_reset_back_end_for_pipe
- dcn20_reset_hw_ctx_wrap
- dcn20_update_mpcc
- find_free_gsl_group
- dcn20_setup_gsl_group_as_lock
- dcn20_set_flip_control_gsl
- dcn20_enable_stream
- dcn20_program_dmdata_engine
- dcn20_fpga_init_hw
- dcn20_hw_sequencer_construct
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 "dm_helpers.h"
29 #include "core_types.h"
30 #include "resource.h"
31 #include "dcn20/dcn20_resource.h"
32 #include "dce110/dce110_hw_sequencer.h"
33 #include "dcn10/dcn10_hw_sequencer.h"
34 #include "dcn20_hwseq.h"
35 #include "dce/dce_hwseq.h"
36 #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
37 #include "dcn20/dcn20_dsc.h"
38 #endif
39 #include "abm.h"
40 #include "clk_mgr.h"
41 #include "dmcu.h"
42 #include "hubp.h"
43 #include "timing_generator.h"
44 #include "opp.h"
45 #include "ipp.h"
46 #include "mpc.h"
47 #include "mcif_wb.h"
48 #include "reg_helper.h"
49 #include "dcn10/dcn10_cm_common.h"
50 #include "dcn10/dcn10_hubbub.h"
51 #include "dcn10/dcn10_optc.h"
52 #include "dc_link_dp.h"
53 #include "vm_helper.h"
54 #include "dccg.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
67 static void dcn20_enable_power_gating_plane(
68 struct dce_hwseq *hws,
69 bool enable)
70 {
71 bool force_on = 1;
72
73 if (enable)
74 force_on = 0;
75
76
77 REG_UPDATE(DOMAIN0_PG_CONFIG, DOMAIN0_POWER_FORCEON, force_on);
78 REG_UPDATE(DOMAIN2_PG_CONFIG, DOMAIN2_POWER_FORCEON, force_on);
79 REG_UPDATE(DOMAIN4_PG_CONFIG, DOMAIN4_POWER_FORCEON, force_on);
80 REG_UPDATE(DOMAIN6_PG_CONFIG, DOMAIN6_POWER_FORCEON, force_on);
81 if (REG(DOMAIN8_PG_CONFIG))
82 REG_UPDATE(DOMAIN8_PG_CONFIG, DOMAIN8_POWER_FORCEON, force_on);
83 if (REG(DOMAIN10_PG_CONFIG))
84 REG_UPDATE(DOMAIN10_PG_CONFIG, DOMAIN8_POWER_FORCEON, force_on);
85
86
87 REG_UPDATE(DOMAIN1_PG_CONFIG, DOMAIN1_POWER_FORCEON, force_on);
88 REG_UPDATE(DOMAIN3_PG_CONFIG, DOMAIN3_POWER_FORCEON, force_on);
89 REG_UPDATE(DOMAIN5_PG_CONFIG, DOMAIN5_POWER_FORCEON, force_on);
90 REG_UPDATE(DOMAIN7_PG_CONFIG, DOMAIN7_POWER_FORCEON, force_on);
91 if (REG(DOMAIN9_PG_CONFIG))
92 REG_UPDATE(DOMAIN9_PG_CONFIG, DOMAIN9_POWER_FORCEON, force_on);
93 if (REG(DOMAIN11_PG_CONFIG))
94 REG_UPDATE(DOMAIN11_PG_CONFIG, DOMAIN9_POWER_FORCEON, force_on);
95
96
97 REG_UPDATE(DOMAIN16_PG_CONFIG, DOMAIN16_POWER_FORCEON, force_on);
98 REG_UPDATE(DOMAIN17_PG_CONFIG, DOMAIN17_POWER_FORCEON, force_on);
99 REG_UPDATE(DOMAIN18_PG_CONFIG, DOMAIN18_POWER_FORCEON, force_on);
100 if (REG(DOMAIN19_PG_CONFIG))
101 REG_UPDATE(DOMAIN19_PG_CONFIG, DOMAIN19_POWER_FORCEON, force_on);
102 if (REG(DOMAIN20_PG_CONFIG))
103 REG_UPDATE(DOMAIN20_PG_CONFIG, DOMAIN20_POWER_FORCEON, force_on);
104 if (REG(DOMAIN21_PG_CONFIG))
105 REG_UPDATE(DOMAIN21_PG_CONFIG, DOMAIN21_POWER_FORCEON, force_on);
106 }
107
108 void dcn20_dccg_init(struct dce_hwseq *hws)
109 {
110
111
112
113
114
115
116
117 REG_WRITE(MICROSECOND_TIME_BASE_DIV, 0x120264);
118
119
120
121
122
123
124
125
126 REG_WRITE(MILLISECOND_TIME_BASE_DIV, 0x1186a0);
127
128
129 REG_WRITE(DISPCLK_FREQ_CHANGE_CNTL, 0x801003c);
130 }
131 void dcn20_display_init(struct dc *dc)
132 {
133 struct dce_hwseq *hws = dc->hwseq;
134
135
136
137
138
139 REG_WRITE(RBBMIF_TIMEOUT_DIS, 0xFFFFFFFF);
140 REG_WRITE(RBBMIF_TIMEOUT_DIS_2, 0xFFFFFFFF);
141
142
143 dcn20_dccg_init(hws);
144
145 REG_UPDATE(DC_MEM_GLOBAL_PWR_REQ_CNTL, DC_MEM_GLOBAL_PWR_REQ_DIS, 0);
146
147
148
149
150
151
152
153 REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, 2);
154 REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1);
155 REG_WRITE(REFCLK_CNTL, 0);
156
157
158
159
160
161
162
163
164
165 REG_UPDATE(AZALIA_AUDIO_DTO, AZALIA_AUDIO_DTO_MODULE, 0x64);
166
167 REG_WRITE(AZALIA_CONTROLLER_CLOCK_GATING, 0x1);
168 }
169
170 void dcn20_disable_vga(
171 struct dce_hwseq *hws)
172 {
173 REG_WRITE(D1VGA_CONTROL, 0);
174 REG_WRITE(D2VGA_CONTROL, 0);
175 REG_WRITE(D3VGA_CONTROL, 0);
176 REG_WRITE(D4VGA_CONTROL, 0);
177 REG_WRITE(D5VGA_CONTROL, 0);
178 REG_WRITE(D6VGA_CONTROL, 0);
179 }
180
181 void dcn20_program_tripleBuffer(
182 const struct dc *dc,
183 struct pipe_ctx *pipe_ctx,
184 bool enableTripleBuffer)
185 {
186 if (pipe_ctx->plane_res.hubp && pipe_ctx->plane_res.hubp->funcs) {
187 pipe_ctx->plane_res.hubp->funcs->hubp_enable_tripleBuffer(
188 pipe_ctx->plane_res.hubp,
189 enableTripleBuffer);
190 }
191 }
192
193
194 void dcn20_init_blank(
195 struct dc *dc,
196 struct timing_generator *tg)
197 {
198 enum dc_color_space color_space;
199 struct tg_color black_color = {0};
200 struct output_pixel_processor *opp = NULL;
201 struct output_pixel_processor *bottom_opp = NULL;
202 uint32_t num_opps, opp_id_src0, opp_id_src1;
203 uint32_t otg_active_width, otg_active_height;
204
205
206 color_space = COLOR_SPACE_SRGB;
207 color_space_to_black_color(dc, color_space, &black_color);
208
209
210 tg->funcs->get_otg_active_size(tg,
211 &otg_active_width,
212 &otg_active_height);
213
214
215 tg->funcs->get_optc_source(tg, &num_opps, &opp_id_src0, &opp_id_src1);
216 ASSERT(opp_id_src0 < dc->res_pool->res_cap->num_opp);
217 opp = dc->res_pool->opps[opp_id_src0];
218
219 if (num_opps == 2) {
220 otg_active_width = otg_active_width / 2;
221 ASSERT(opp_id_src1 < dc->res_pool->res_cap->num_opp);
222 bottom_opp = dc->res_pool->opps[opp_id_src1];
223 }
224
225 opp->funcs->opp_set_disp_pattern_generator(
226 opp,
227 CONTROLLER_DP_TEST_PATTERN_SOLID_COLOR,
228 COLOR_DEPTH_UNDEFINED,
229 &black_color,
230 otg_active_width,
231 otg_active_height);
232
233 if (num_opps == 2) {
234 bottom_opp->funcs->opp_set_disp_pattern_generator(
235 bottom_opp,
236 CONTROLLER_DP_TEST_PATTERN_SOLID_COLOR,
237 COLOR_DEPTH_UNDEFINED,
238 &black_color,
239 otg_active_width,
240 otg_active_height);
241 }
242
243 dcn20_hwss_wait_for_blank_complete(opp);
244 }
245
246 #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
247 static void dcn20_dsc_pg_control(
248 struct dce_hwseq *hws,
249 unsigned int dsc_inst,
250 bool power_on)
251 {
252 uint32_t power_gate = power_on ? 0 : 1;
253 uint32_t pwr_status = power_on ? 0 : 2;
254 uint32_t org_ip_request_cntl = 0;
255
256 if (hws->ctx->dc->debug.disable_dsc_power_gate)
257 return;
258
259 if (REG(DOMAIN16_PG_CONFIG) == 0)
260 return;
261
262 REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl);
263 if (org_ip_request_cntl == 0)
264 REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1);
265
266 switch (dsc_inst) {
267 case 0:
268 REG_UPDATE(DOMAIN16_PG_CONFIG,
269 DOMAIN16_POWER_GATE, power_gate);
270
271 REG_WAIT(DOMAIN16_PG_STATUS,
272 DOMAIN16_PGFSM_PWR_STATUS, pwr_status,
273 1, 1000);
274 break;
275 case 1:
276 REG_UPDATE(DOMAIN17_PG_CONFIG,
277 DOMAIN17_POWER_GATE, power_gate);
278
279 REG_WAIT(DOMAIN17_PG_STATUS,
280 DOMAIN17_PGFSM_PWR_STATUS, pwr_status,
281 1, 1000);
282 break;
283 case 2:
284 REG_UPDATE(DOMAIN18_PG_CONFIG,
285 DOMAIN18_POWER_GATE, power_gate);
286
287 REG_WAIT(DOMAIN18_PG_STATUS,
288 DOMAIN18_PGFSM_PWR_STATUS, pwr_status,
289 1, 1000);
290 break;
291 case 3:
292 REG_UPDATE(DOMAIN19_PG_CONFIG,
293 DOMAIN19_POWER_GATE, power_gate);
294
295 REG_WAIT(DOMAIN19_PG_STATUS,
296 DOMAIN19_PGFSM_PWR_STATUS, pwr_status,
297 1, 1000);
298 break;
299 case 4:
300 REG_UPDATE(DOMAIN20_PG_CONFIG,
301 DOMAIN20_POWER_GATE, power_gate);
302
303 REG_WAIT(DOMAIN20_PG_STATUS,
304 DOMAIN20_PGFSM_PWR_STATUS, pwr_status,
305 1, 1000);
306 break;
307 case 5:
308 REG_UPDATE(DOMAIN21_PG_CONFIG,
309 DOMAIN21_POWER_GATE, power_gate);
310
311 REG_WAIT(DOMAIN21_PG_STATUS,
312 DOMAIN21_PGFSM_PWR_STATUS, pwr_status,
313 1, 1000);
314 break;
315 default:
316 BREAK_TO_DEBUGGER();
317 break;
318 }
319
320 if (org_ip_request_cntl == 0)
321 REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0);
322 }
323 #endif
324
325 static void dcn20_dpp_pg_control(
326 struct dce_hwseq *hws,
327 unsigned int dpp_inst,
328 bool power_on)
329 {
330 uint32_t power_gate = power_on ? 0 : 1;
331 uint32_t pwr_status = power_on ? 0 : 2;
332
333 if (hws->ctx->dc->debug.disable_dpp_power_gate)
334 return;
335 if (REG(DOMAIN1_PG_CONFIG) == 0)
336 return;
337
338 switch (dpp_inst) {
339 case 0:
340 REG_UPDATE(DOMAIN1_PG_CONFIG,
341 DOMAIN1_POWER_GATE, power_gate);
342
343 REG_WAIT(DOMAIN1_PG_STATUS,
344 DOMAIN1_PGFSM_PWR_STATUS, pwr_status,
345 1, 1000);
346 break;
347 case 1:
348 REG_UPDATE(DOMAIN3_PG_CONFIG,
349 DOMAIN3_POWER_GATE, power_gate);
350
351 REG_WAIT(DOMAIN3_PG_STATUS,
352 DOMAIN3_PGFSM_PWR_STATUS, pwr_status,
353 1, 1000);
354 break;
355 case 2:
356 REG_UPDATE(DOMAIN5_PG_CONFIG,
357 DOMAIN5_POWER_GATE, power_gate);
358
359 REG_WAIT(DOMAIN5_PG_STATUS,
360 DOMAIN5_PGFSM_PWR_STATUS, pwr_status,
361 1, 1000);
362 break;
363 case 3:
364 REG_UPDATE(DOMAIN7_PG_CONFIG,
365 DOMAIN7_POWER_GATE, power_gate);
366
367 REG_WAIT(DOMAIN7_PG_STATUS,
368 DOMAIN7_PGFSM_PWR_STATUS, pwr_status,
369 1, 1000);
370 break;
371 case 4:
372 REG_UPDATE(DOMAIN9_PG_CONFIG,
373 DOMAIN9_POWER_GATE, power_gate);
374
375 REG_WAIT(DOMAIN9_PG_STATUS,
376 DOMAIN9_PGFSM_PWR_STATUS, pwr_status,
377 1, 1000);
378 break;
379 case 5:
380
381
382
383
384
385
386
387
388
389
390
391 break;
392 default:
393 BREAK_TO_DEBUGGER();
394 break;
395 }
396 }
397
398
399 static void dcn20_hubp_pg_control(
400 struct dce_hwseq *hws,
401 unsigned int hubp_inst,
402 bool power_on)
403 {
404 uint32_t power_gate = power_on ? 0 : 1;
405 uint32_t pwr_status = power_on ? 0 : 2;
406
407 if (hws->ctx->dc->debug.disable_hubp_power_gate)
408 return;
409 if (REG(DOMAIN0_PG_CONFIG) == 0)
410 return;
411
412 switch (hubp_inst) {
413 case 0:
414 REG_UPDATE(DOMAIN0_PG_CONFIG,
415 DOMAIN0_POWER_GATE, power_gate);
416
417 REG_WAIT(DOMAIN0_PG_STATUS,
418 DOMAIN0_PGFSM_PWR_STATUS, pwr_status,
419 1, 1000);
420 break;
421 case 1:
422 REG_UPDATE(DOMAIN2_PG_CONFIG,
423 DOMAIN2_POWER_GATE, power_gate);
424
425 REG_WAIT(DOMAIN2_PG_STATUS,
426 DOMAIN2_PGFSM_PWR_STATUS, pwr_status,
427 1, 1000);
428 break;
429 case 2:
430 REG_UPDATE(DOMAIN4_PG_CONFIG,
431 DOMAIN4_POWER_GATE, power_gate);
432
433 REG_WAIT(DOMAIN4_PG_STATUS,
434 DOMAIN4_PGFSM_PWR_STATUS, pwr_status,
435 1, 1000);
436 break;
437 case 3:
438 REG_UPDATE(DOMAIN6_PG_CONFIG,
439 DOMAIN6_POWER_GATE, power_gate);
440
441 REG_WAIT(DOMAIN6_PG_STATUS,
442 DOMAIN6_PGFSM_PWR_STATUS, pwr_status,
443 1, 1000);
444 break;
445 case 4:
446 REG_UPDATE(DOMAIN8_PG_CONFIG,
447 DOMAIN8_POWER_GATE, power_gate);
448
449 REG_WAIT(DOMAIN8_PG_STATUS,
450 DOMAIN8_PGFSM_PWR_STATUS, pwr_status,
451 1, 1000);
452 break;
453 case 5:
454
455
456
457
458
459
460
461
462
463
464
465 break;
466 default:
467 BREAK_TO_DEBUGGER();
468 break;
469 }
470 }
471
472
473
474
475
476 static void dcn20_plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx)
477 {
478 struct hubp *hubp = pipe_ctx->plane_res.hubp;
479 struct dpp *dpp = pipe_ctx->plane_res.dpp;
480
481 dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, pipe_ctx);
482
483
484
485
486 if (pipe_ctx->stream_res.gsl_group != 0)
487 dcn20_setup_gsl_group_as_lock(dc, pipe_ctx, false);
488
489 dc->hwss.set_flip_control_gsl(pipe_ctx, false);
490
491 hubp->funcs->hubp_clk_cntl(hubp, false);
492
493 dpp->funcs->dpp_dppclk_control(dpp, false, false);
494
495 hubp->power_gated = true;
496
497 dc->hwss.plane_atomic_power_down(dc,
498 pipe_ctx->plane_res.dpp,
499 pipe_ctx->plane_res.hubp);
500
501 pipe_ctx->stream = NULL;
502 memset(&pipe_ctx->stream_res, 0, sizeof(pipe_ctx->stream_res));
503 memset(&pipe_ctx->plane_res, 0, sizeof(pipe_ctx->plane_res));
504 pipe_ctx->top_pipe = NULL;
505 pipe_ctx->bottom_pipe = NULL;
506 pipe_ctx->plane_state = NULL;
507 }
508
509
510 void dcn20_disable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx)
511 {
512 DC_LOGGER_INIT(dc->ctx->logger);
513
514 if (!pipe_ctx->plane_res.hubp || pipe_ctx->plane_res.hubp->power_gated)
515 return;
516
517 dcn20_plane_atomic_disable(dc, pipe_ctx);
518
519 DC_LOG_DC("Power down front end %d\n",
520 pipe_ctx->pipe_idx);
521 }
522
523 enum dc_status dcn20_enable_stream_timing(
524 struct pipe_ctx *pipe_ctx,
525 struct dc_state *context,
526 struct dc *dc)
527 {
528 struct dc_stream_state *stream = pipe_ctx->stream;
529 struct drr_params params = {0};
530 unsigned int event_triggers = 0;
531 struct pipe_ctx *odm_pipe;
532 int opp_cnt = 1;
533 int opp_inst[MAX_PIPES] = { pipe_ctx->stream_res.opp->inst };
534
535
536
537
538
539 if (pipe_ctx->top_pipe != NULL)
540 return DC_OK;
541
542
543
544 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
545 opp_inst[opp_cnt] = odm_pipe->stream_res.opp->inst;
546 opp_cnt++;
547 }
548
549 if (opp_cnt > 1)
550 pipe_ctx->stream_res.tg->funcs->set_odm_combine(
551 pipe_ctx->stream_res.tg,
552 opp_inst, opp_cnt,
553 &pipe_ctx->stream->timing);
554
555
556
557
558 pipe_ctx->stream_res.tg->funcs->enable_optc_clock(pipe_ctx->stream_res.tg, true);
559
560 if (false == pipe_ctx->clock_source->funcs->program_pix_clk(
561 pipe_ctx->clock_source,
562 &pipe_ctx->stream_res.pix_clk_params,
563 &pipe_ctx->pll_settings)) {
564 BREAK_TO_DEBUGGER();
565 return DC_ERROR_UNEXPECTED;
566 }
567
568 pipe_ctx->stream_res.tg->funcs->program_timing(
569 pipe_ctx->stream_res.tg,
570 &stream->timing,
571 pipe_ctx->pipe_dlg_param.vready_offset,
572 pipe_ctx->pipe_dlg_param.vstartup_start,
573 pipe_ctx->pipe_dlg_param.vupdate_offset,
574 pipe_ctx->pipe_dlg_param.vupdate_width,
575 pipe_ctx->stream->signal,
576 true);
577
578 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
579 odm_pipe->stream_res.opp->funcs->opp_pipe_clock_control(
580 odm_pipe->stream_res.opp,
581 true);
582
583 pipe_ctx->stream_res.opp->funcs->opp_pipe_clock_control(
584 pipe_ctx->stream_res.opp,
585 true);
586
587 dc->hwss.blank_pixel_data(dc, pipe_ctx, true);
588
589
590 if (false == pipe_ctx->stream_res.tg->funcs->enable_crtc(pipe_ctx->stream_res.tg)) {
591 BREAK_TO_DEBUGGER();
592 return DC_ERROR_UNEXPECTED;
593 }
594
595 dcn20_hwss_wait_for_blank_complete(pipe_ctx->stream_res.opp);
596
597 params.vertical_total_min = stream->adjust.v_total_min;
598 params.vertical_total_max = stream->adjust.v_total_max;
599 params.vertical_total_mid = stream->adjust.v_total_mid;
600 params.vertical_total_mid_frame_num = stream->adjust.v_total_mid_frame_num;
601 if (pipe_ctx->stream_res.tg->funcs->set_drr)
602 pipe_ctx->stream_res.tg->funcs->set_drr(
603 pipe_ctx->stream_res.tg, ¶ms);
604
605
606 if (stream->adjust.v_total_min != 0 && stream->adjust.v_total_max != 0)
607 event_triggers = 0x80;
608 if (pipe_ctx->stream_res.tg->funcs->set_static_screen_control)
609 pipe_ctx->stream_res.tg->funcs->set_static_screen_control(
610 pipe_ctx->stream_res.tg, event_triggers);
611
612
613
614
615
616
617
618
619
620 return DC_OK;
621 }
622
623 void dcn20_program_output_csc(struct dc *dc,
624 struct pipe_ctx *pipe_ctx,
625 enum dc_color_space colorspace,
626 uint16_t *matrix,
627 int opp_id)
628 {
629 struct mpc *mpc = dc->res_pool->mpc;
630 enum mpc_output_csc_mode ocsc_mode = MPC_OUTPUT_CSC_COEF_A;
631 int mpcc_id = pipe_ctx->plane_res.hubp->inst;
632
633 if (mpc->funcs->power_on_mpc_mem_pwr)
634 mpc->funcs->power_on_mpc_mem_pwr(mpc, mpcc_id, true);
635
636 if (pipe_ctx->stream->csc_color_matrix.enable_adjustment == true) {
637 if (mpc->funcs->set_output_csc != NULL)
638 mpc->funcs->set_output_csc(mpc,
639 opp_id,
640 matrix,
641 ocsc_mode);
642 } else {
643 if (mpc->funcs->set_ocsc_default != NULL)
644 mpc->funcs->set_ocsc_default(mpc,
645 opp_id,
646 colorspace,
647 ocsc_mode);
648 }
649 }
650
651 bool dcn20_set_output_transfer_func(struct pipe_ctx *pipe_ctx,
652 const struct dc_stream_state *stream)
653 {
654 int mpcc_id = pipe_ctx->plane_res.hubp->inst;
655 struct mpc *mpc = pipe_ctx->stream_res.opp->ctx->dc->res_pool->mpc;
656 struct pwl_params *params = NULL;
657
658
659
660
661
662
663
664 if (mpc->funcs->power_on_mpc_mem_pwr)
665 mpc->funcs->power_on_mpc_mem_pwr(mpc, mpcc_id, true);
666 if (pipe_ctx->top_pipe == NULL
667 && mpc->funcs->set_output_gamma && stream->out_transfer_func) {
668 if (stream->out_transfer_func->type == TF_TYPE_HWPWL)
669 params = &stream->out_transfer_func->pwl;
670 else if (pipe_ctx->stream->out_transfer_func->type ==
671 TF_TYPE_DISTRIBUTED_POINTS &&
672 cm_helper_translate_curve_to_hw_format(
673 stream->out_transfer_func,
674 &mpc->blender_params, false))
675 params = &mpc->blender_params;
676
677
678
679 if (stream->out_transfer_func->type == TF_TYPE_PREDEFINED)
680 BREAK_TO_DEBUGGER();
681 }
682
683
684
685 mpc->funcs->set_output_gamma(mpc, mpcc_id, params);
686
687 return true;
688 }
689
690 static bool dcn20_set_blend_lut(
691 struct pipe_ctx *pipe_ctx, const struct dc_plane_state *plane_state)
692 {
693 struct dpp *dpp_base = pipe_ctx->plane_res.dpp;
694 bool result = true;
695 struct pwl_params *blend_lut = NULL;
696
697 if (plane_state->blend_tf) {
698 if (plane_state->blend_tf->type == TF_TYPE_HWPWL)
699 blend_lut = &plane_state->blend_tf->pwl;
700 else if (plane_state->blend_tf->type == TF_TYPE_DISTRIBUTED_POINTS) {
701 cm_helper_translate_curve_to_hw_format(
702 plane_state->blend_tf,
703 &dpp_base->regamma_params, false);
704 blend_lut = &dpp_base->regamma_params;
705 }
706 }
707 result = dpp_base->funcs->dpp_program_blnd_lut(dpp_base, blend_lut);
708
709 return result;
710 }
711
712 static bool dcn20_set_shaper_3dlut(
713 struct pipe_ctx *pipe_ctx, const struct dc_plane_state *plane_state)
714 {
715 struct dpp *dpp_base = pipe_ctx->plane_res.dpp;
716 bool result = true;
717 struct pwl_params *shaper_lut = NULL;
718
719 if (plane_state->in_shaper_func) {
720 if (plane_state->in_shaper_func->type == TF_TYPE_HWPWL)
721 shaper_lut = &plane_state->in_shaper_func->pwl;
722 else if (plane_state->in_shaper_func->type == TF_TYPE_DISTRIBUTED_POINTS) {
723 cm_helper_translate_curve_to_hw_format(
724 plane_state->in_shaper_func,
725 &dpp_base->shaper_params, true);
726 shaper_lut = &dpp_base->shaper_params;
727 }
728 }
729
730 result = dpp_base->funcs->dpp_program_shaper_lut(dpp_base, shaper_lut);
731 if (plane_state->lut3d_func &&
732 plane_state->lut3d_func->state.bits.initialized == 1)
733 result = dpp_base->funcs->dpp_program_3dlut(dpp_base,
734 &plane_state->lut3d_func->lut_3d);
735 else
736 result = dpp_base->funcs->dpp_program_3dlut(dpp_base, NULL);
737
738 if (plane_state->lut3d_func &&
739 plane_state->lut3d_func->state.bits.initialized == 1 &&
740 plane_state->lut3d_func->hdr_multiplier != 0)
741 dpp_base->funcs->dpp_set_hdr_multiplier(dpp_base,
742 plane_state->lut3d_func->hdr_multiplier);
743 else
744 dpp_base->funcs->dpp_set_hdr_multiplier(dpp_base, 0x1f000);
745
746 return result;
747 }
748
749 bool dcn20_set_input_transfer_func(struct pipe_ctx *pipe_ctx,
750 const struct dc_plane_state *plane_state)
751 {
752 struct dpp *dpp_base = pipe_ctx->plane_res.dpp;
753 const struct dc_transfer_func *tf = NULL;
754 bool result = true;
755 bool use_degamma_ram = false;
756
757 if (dpp_base == NULL || plane_state == NULL)
758 return false;
759
760 dcn20_set_shaper_3dlut(pipe_ctx, plane_state);
761 dcn20_set_blend_lut(pipe_ctx, plane_state);
762
763 if (plane_state->in_transfer_func)
764 tf = plane_state->in_transfer_func;
765
766
767 if (tf == NULL) {
768 dpp_base->funcs->dpp_set_degamma(dpp_base,
769 IPP_DEGAMMA_MODE_BYPASS);
770 return true;
771 }
772
773 if (tf->type == TF_TYPE_HWPWL || tf->type == TF_TYPE_DISTRIBUTED_POINTS)
774 use_degamma_ram = true;
775
776 if (use_degamma_ram == true) {
777 if (tf->type == TF_TYPE_HWPWL)
778 dpp_base->funcs->dpp_program_degamma_pwl(dpp_base,
779 &tf->pwl);
780 else if (tf->type == TF_TYPE_DISTRIBUTED_POINTS) {
781 cm_helper_translate_curve_to_degamma_hw_format(tf,
782 &dpp_base->degamma_params);
783 dpp_base->funcs->dpp_program_degamma_pwl(dpp_base,
784 &dpp_base->degamma_params);
785 }
786 return true;
787 }
788
789
790
791 if (tf->type == TF_TYPE_PREDEFINED) {
792 switch (tf->tf) {
793 case TRANSFER_FUNCTION_SRGB:
794 dpp_base->funcs->dpp_set_degamma(dpp_base,
795 IPP_DEGAMMA_MODE_HW_sRGB);
796 break;
797 case TRANSFER_FUNCTION_BT709:
798 dpp_base->funcs->dpp_set_degamma(dpp_base,
799 IPP_DEGAMMA_MODE_HW_xvYCC);
800 break;
801 case TRANSFER_FUNCTION_LINEAR:
802 dpp_base->funcs->dpp_set_degamma(dpp_base,
803 IPP_DEGAMMA_MODE_BYPASS);
804 break;
805 case TRANSFER_FUNCTION_PQ:
806 default:
807 result = false;
808 break;
809 }
810 } else if (tf->type == TF_TYPE_BYPASS)
811 dpp_base->funcs->dpp_set_degamma(dpp_base,
812 IPP_DEGAMMA_MODE_BYPASS);
813 else {
814
815
816
817
818 BREAK_TO_DEBUGGER();
819 dpp_base->funcs->dpp_set_degamma(dpp_base,
820 IPP_DEGAMMA_MODE_BYPASS);
821 }
822
823 return result;
824 }
825
826 static void dcn20_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe_ctx)
827 {
828 struct pipe_ctx *odm_pipe;
829 int opp_cnt = 1;
830 int opp_inst[MAX_PIPES] = { pipe_ctx->stream_res.opp->inst };
831
832 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
833 opp_inst[opp_cnt] = odm_pipe->stream_res.opp->inst;
834 opp_cnt++;
835 }
836
837 if (opp_cnt > 1)
838 pipe_ctx->stream_res.tg->funcs->set_odm_combine(
839 pipe_ctx->stream_res.tg,
840 opp_inst, opp_cnt,
841 &pipe_ctx->stream->timing);
842 else
843 pipe_ctx->stream_res.tg->funcs->set_odm_bypass(
844 pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing);
845 }
846
847 void dcn20_blank_pixel_data(
848 struct dc *dc,
849 struct pipe_ctx *pipe_ctx,
850 bool blank)
851 {
852 struct tg_color black_color = {0};
853 struct stream_resource *stream_res = &pipe_ctx->stream_res;
854 struct dc_stream_state *stream = pipe_ctx->stream;
855 enum dc_color_space color_space = stream->output_color_space;
856 enum controller_dp_test_pattern test_pattern = CONTROLLER_DP_TEST_PATTERN_SOLID_COLOR;
857 struct pipe_ctx *odm_pipe;
858 int odm_cnt = 1;
859
860 int width = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right;
861 int height = stream->timing.v_addressable + stream->timing.v_border_bottom + stream->timing.v_border_top;
862
863
864 color_space_to_black_color(dc, color_space, &black_color);
865
866 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
867 odm_cnt++;
868
869 width = width / odm_cnt;
870
871 if (blank) {
872 if (stream_res->abm)
873 stream_res->abm->funcs->set_abm_immediate_disable(stream_res->abm);
874
875 if (dc->debug.visual_confirm != VISUAL_CONFIRM_DISABLE)
876 test_pattern = CONTROLLER_DP_TEST_PATTERN_COLORSQUARES;
877 } else {
878 test_pattern = CONTROLLER_DP_TEST_PATTERN_VIDEOMODE;
879 }
880
881 stream_res->opp->funcs->opp_set_disp_pattern_generator(
882 stream_res->opp,
883 test_pattern,
884 stream->timing.display_color_depth,
885 &black_color,
886 width,
887 height);
888
889 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
890 odm_pipe->stream_res.opp->funcs->opp_set_disp_pattern_generator(
891 odm_pipe->stream_res.opp,
892 dc->debug.visual_confirm != VISUAL_CONFIRM_DISABLE && blank ?
893 CONTROLLER_DP_TEST_PATTERN_COLORRAMP : test_pattern,
894 stream->timing.display_color_depth,
895 &black_color,
896 width,
897 height);
898 }
899
900 if (!blank)
901 if (stream_res->abm) {
902 stream_res->abm->funcs->set_pipe(stream_res->abm, stream_res->tg->inst + 1);
903 stream_res->abm->funcs->set_abm_level(stream_res->abm, stream->abm_level);
904 }
905 }
906
907
908 static void dcn20_power_on_plane(
909 struct dce_hwseq *hws,
910 struct pipe_ctx *pipe_ctx)
911 {
912 DC_LOGGER_INIT(hws->ctx->logger);
913 if (REG(DC_IP_REQUEST_CNTL)) {
914 REG_SET(DC_IP_REQUEST_CNTL, 0,
915 IP_REQUEST_EN, 1);
916 dcn20_dpp_pg_control(hws, pipe_ctx->plane_res.dpp->inst, true);
917 dcn20_hubp_pg_control(hws, pipe_ctx->plane_res.hubp->inst, true);
918 REG_SET(DC_IP_REQUEST_CNTL, 0,
919 IP_REQUEST_EN, 0);
920 DC_LOG_DEBUG(
921 "Un-gated front end for pipe %d\n", pipe_ctx->plane_res.hubp->inst);
922 }
923 }
924
925 void dcn20_enable_plane(
926 struct dc *dc,
927 struct pipe_ctx *pipe_ctx,
928 struct dc_state *context)
929 {
930
931
932
933 dcn20_power_on_plane(dc->hwseq, pipe_ctx);
934
935
936 pipe_ctx->plane_res.hubp->funcs->hubp_clk_cntl(pipe_ctx->plane_res.hubp, true);
937
938
939 pipe_ctx->plane_res.hubp->funcs->hubp_init(pipe_ctx->plane_res.hubp);
940
941
942 pipe_ctx->stream_res.opp->funcs->opp_pipe_clock_control(
943 pipe_ctx->stream_res.opp,
944 true);
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983 if (dc->vm_pa_config.valid) {
984 struct vm_system_aperture_param apt;
985
986 apt.sys_default.quad_part = 0;
987
988 apt.sys_low.quad_part = dc->vm_pa_config.system_aperture.start_addr;
989 apt.sys_high.quad_part = dc->vm_pa_config.system_aperture.end_addr;
990
991
992 pipe_ctx->plane_res.hubp->funcs->hubp_set_vm_system_aperture_settings(pipe_ctx->plane_res.hubp, &apt);
993 }
994
995
996
997
998 }
999
1000
1001 static void dcn20_program_pipe(
1002 struct dc *dc,
1003 struct pipe_ctx *pipe_ctx,
1004 struct dc_state *context)
1005 {
1006 pipe_ctx->plane_state->update_flags.bits.full_update =
1007 context->commit_hints.full_update_needed ? 1 : pipe_ctx->plane_state->update_flags.bits.full_update;
1008
1009 if (pipe_ctx->plane_state->update_flags.bits.full_update)
1010 dcn20_enable_plane(dc, pipe_ctx, context);
1011
1012 update_dchubp_dpp(dc, pipe_ctx, context);
1013
1014 set_hdr_multiplier(pipe_ctx);
1015
1016 if (pipe_ctx->plane_state->update_flags.bits.full_update ||
1017 pipe_ctx->plane_state->update_flags.bits.in_transfer_func_change ||
1018 pipe_ctx->plane_state->update_flags.bits.gamma_change)
1019 dc->hwss.set_input_transfer_func(pipe_ctx, pipe_ctx->plane_state);
1020
1021
1022
1023
1024
1025
1026
1027 if (pipe_ctx->plane_state->update_flags.bits.full_update)
1028 dc->hwss.set_output_transfer_func(pipe_ctx, pipe_ctx->stream);
1029 }
1030
1031 static void dcn20_program_all_pipe_in_tree(
1032 struct dc *dc,
1033 struct pipe_ctx *pipe_ctx,
1034 struct dc_state *context)
1035 {
1036 if (pipe_ctx->top_pipe == NULL && !pipe_ctx->prev_odm_pipe) {
1037 bool blank = !is_pipe_tree_visible(pipe_ctx);
1038
1039 pipe_ctx->stream_res.tg->funcs->program_global_sync(
1040 pipe_ctx->stream_res.tg,
1041 pipe_ctx->pipe_dlg_param.vready_offset,
1042 pipe_ctx->pipe_dlg_param.vstartup_start,
1043 pipe_ctx->pipe_dlg_param.vupdate_offset,
1044 pipe_ctx->pipe_dlg_param.vupdate_width);
1045
1046 pipe_ctx->stream_res.tg->funcs->set_vtg_params(
1047 pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing);
1048
1049 dc->hwss.blank_pixel_data(dc, pipe_ctx, blank);
1050
1051 if (dc->hwss.update_odm)
1052 dc->hwss.update_odm(dc, context, pipe_ctx);
1053 }
1054
1055 if (pipe_ctx->plane_state != NULL)
1056 dcn20_program_pipe(dc, pipe_ctx, context);
1057
1058 if (pipe_ctx->bottom_pipe != NULL) {
1059 ASSERT(pipe_ctx->bottom_pipe != pipe_ctx);
1060 dcn20_program_all_pipe_in_tree(dc, pipe_ctx->bottom_pipe, context);
1061 } else if (pipe_ctx->next_odm_pipe != NULL) {
1062 ASSERT(pipe_ctx->next_odm_pipe != pipe_ctx);
1063 dcn20_program_all_pipe_in_tree(dc, pipe_ctx->next_odm_pipe, context);
1064 }
1065 }
1066
1067 void dcn20_pipe_control_lock_global(
1068 struct dc *dc,
1069 struct pipe_ctx *pipe,
1070 bool lock)
1071 {
1072 if (lock) {
1073 pipe->stream_res.tg->funcs->lock_doublebuffer_enable(
1074 pipe->stream_res.tg);
1075 pipe->stream_res.tg->funcs->lock(pipe->stream_res.tg);
1076 } else {
1077 pipe->stream_res.tg->funcs->unlock(pipe->stream_res.tg);
1078 pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg,
1079 CRTC_STATE_VACTIVE);
1080 pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg,
1081 CRTC_STATE_VBLANK);
1082 pipe->stream_res.tg->funcs->wait_for_state(pipe->stream_res.tg,
1083 CRTC_STATE_VACTIVE);
1084 pipe->stream_res.tg->funcs->lock_doublebuffer_disable(
1085 pipe->stream_res.tg);
1086 }
1087 }
1088
1089 void dcn20_pipe_control_lock(
1090 struct dc *dc,
1091 struct pipe_ctx *pipe,
1092 bool lock)
1093 {
1094 bool flip_immediate = false;
1095
1096
1097
1098
1099 if (pipe->top_pipe)
1100 return;
1101
1102 if (pipe->plane_state != NULL)
1103 flip_immediate = pipe->plane_state->flip_immediate;
1104
1105 if (flip_immediate && lock) {
1106 const int TIMEOUT_FOR_FLIP_PENDING = 100000;
1107 int i;
1108
1109 for (i = 0; i < TIMEOUT_FOR_FLIP_PENDING; ++i) {
1110 if (!pipe->plane_res.hubp->funcs->hubp_is_flip_pending(pipe->plane_res.hubp))
1111 break;
1112 udelay(1);
1113 }
1114
1115 if (pipe->bottom_pipe != NULL) {
1116 for (i = 0; i < TIMEOUT_FOR_FLIP_PENDING; ++i) {
1117 if (!pipe->bottom_pipe->plane_res.hubp->funcs->hubp_is_flip_pending(pipe->bottom_pipe->plane_res.hubp))
1118 break;
1119 udelay(1);
1120 }
1121 }
1122 }
1123
1124
1125
1126
1127 if (lock && pipe->bottom_pipe != NULL)
1128 if ((flip_immediate && pipe->stream_res.gsl_group == 0) ||
1129 (!flip_immediate && pipe->stream_res.gsl_group > 0))
1130 dcn20_setup_gsl_group_as_lock(dc, pipe, flip_immediate);
1131
1132 if (pipe->plane_state != NULL && pipe->plane_state->triplebuffer_flips) {
1133 if (lock)
1134 pipe->stream_res.tg->funcs->triplebuffer_lock(pipe->stream_res.tg);
1135 else
1136 pipe->stream_res.tg->funcs->triplebuffer_unlock(pipe->stream_res.tg);
1137 } else {
1138 if (lock)
1139 pipe->stream_res.tg->funcs->lock(pipe->stream_res.tg);
1140 else
1141 pipe->stream_res.tg->funcs->unlock(pipe->stream_res.tg);
1142 }
1143 }
1144
1145 static void dcn20_apply_ctx_for_surface(
1146 struct dc *dc,
1147 const struct dc_stream_state *stream,
1148 int num_planes,
1149 struct dc_state *context)
1150 {
1151 const unsigned int TIMEOUT_FOR_PIPE_ENABLE_MS = 100;
1152 int i;
1153 struct timing_generator *tg;
1154 bool removed_pipe[6] = { false };
1155 bool interdependent_update = false;
1156 struct pipe_ctx *top_pipe_to_program =
1157 find_top_pipe_for_stream(dc, context, stream);
1158 struct pipe_ctx *prev_top_pipe_to_program =
1159 find_top_pipe_for_stream(dc, dc->current_state, stream);
1160 DC_LOGGER_INIT(dc->ctx->logger);
1161
1162 if (!top_pipe_to_program)
1163 return;
1164
1165
1166 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1167 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1168 struct pipe_ctx *old_pipe_ctx =
1169 &dc->current_state->res_ctx.pipe_ctx[i];
1170
1171 if (pipe_ctx->stream == stream &&
1172 pipe_ctx->stream == old_pipe_ctx->stream)
1173 pipe_ctx->stream_res.gsl_group =
1174 old_pipe_ctx->stream_res.gsl_group;
1175 }
1176
1177 tg = top_pipe_to_program->stream_res.tg;
1178
1179 interdependent_update = top_pipe_to_program->plane_state &&
1180 top_pipe_to_program->plane_state->update_flags.bits.full_update;
1181
1182 if (interdependent_update)
1183 lock_all_pipes(dc, context, true);
1184 else
1185 dcn20_pipe_control_lock(dc, top_pipe_to_program, true);
1186
1187 if (num_planes == 0) {
1188
1189 dc->hwss.blank_pixel_data(dc, top_pipe_to_program, true);
1190 }
1191
1192
1193 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1194 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1195 struct pipe_ctx *old_pipe_ctx =
1196 &dc->current_state->res_ctx.pipe_ctx[i];
1197
1198
1199
1200
1201
1202
1203 if (pipe_ctx->plane_state && !old_pipe_ctx->plane_state) {
1204 if (old_pipe_ctx->stream_res.tg == tg &&
1205 old_pipe_ctx->plane_res.hubp &&
1206 old_pipe_ctx->plane_res.hubp->opp_id != OPP_ID_INVALID)
1207 dc->hwss.disable_plane(dc, old_pipe_ctx);
1208 }
1209
1210 if ((!pipe_ctx->plane_state ||
1211 pipe_ctx->stream_res.tg != old_pipe_ctx->stream_res.tg) &&
1212 old_pipe_ctx->plane_state &&
1213 old_pipe_ctx->stream_res.tg == tg) {
1214
1215 dc->hwss.plane_atomic_disconnect(dc, old_pipe_ctx);
1216 removed_pipe[i] = true;
1217
1218 DC_LOG_DC("Reset mpcc for pipe %d\n",
1219 old_pipe_ctx->pipe_idx);
1220 }
1221 }
1222
1223 if (num_planes > 0)
1224 dcn20_program_all_pipe_in_tree(dc, top_pipe_to_program, context);
1225
1226
1227 if ((stream->num_wb_info > 0) && (dc->hwss.program_all_writeback_pipes_in_tree))
1228 dc->hwss.program_all_writeback_pipes_in_tree(dc, stream, context);
1229
1230 if (interdependent_update)
1231 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1232 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1233
1234
1235 if (!pipe_ctx->stream || pipe_ctx->stream == stream ||
1236 !pipe_ctx->plane_state || !tg->funcs->is_tg_enabled(tg))
1237 continue;
1238
1239 pipe_ctx->plane_res.hubp->funcs->hubp_setup_interdependent(
1240 pipe_ctx->plane_res.hubp,
1241 &pipe_ctx->dlg_regs,
1242 &pipe_ctx->ttu_regs);
1243 }
1244
1245 if (interdependent_update)
1246 lock_all_pipes(dc, context, false);
1247 else
1248 dcn20_pipe_control_lock(dc, top_pipe_to_program, false);
1249
1250 for (i = 0; i < dc->res_pool->pipe_count; i++)
1251 if (removed_pipe[i])
1252 dcn20_disable_plane(dc, &dc->current_state->res_ctx.pipe_ctx[i]);
1253
1254
1255
1256
1257
1258
1259
1260 i = 0;
1261 if (num_planes > 0 && top_pipe_to_program &&
1262 (prev_top_pipe_to_program == NULL || prev_top_pipe_to_program->plane_state == NULL)) {
1263 while (i < TIMEOUT_FOR_PIPE_ENABLE_MS &&
1264 top_pipe_to_program->plane_res.hubp->funcs->hubp_is_flip_pending(top_pipe_to_program->plane_res.hubp)) {
1265 i += 1;
1266 msleep(1);
1267 }
1268 }
1269 }
1270
1271
1272 void dcn20_prepare_bandwidth(
1273 struct dc *dc,
1274 struct dc_state *context)
1275 {
1276 struct hubbub *hubbub = dc->res_pool->hubbub;
1277
1278 dc->clk_mgr->funcs->update_clocks(
1279 dc->clk_mgr,
1280 context,
1281 false);
1282
1283
1284 hubbub->funcs->program_watermarks(hubbub,
1285 &context->bw_ctx.bw.dcn.watermarks,
1286 dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000,
1287 false);
1288 }
1289
1290 void dcn20_optimize_bandwidth(
1291 struct dc *dc,
1292 struct dc_state *context)
1293 {
1294 struct hubbub *hubbub = dc->res_pool->hubbub;
1295
1296
1297 hubbub->funcs->program_watermarks(hubbub,
1298 &context->bw_ctx.bw.dcn.watermarks,
1299 dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000,
1300 true);
1301
1302 dc->clk_mgr->funcs->update_clocks(
1303 dc->clk_mgr,
1304 context,
1305 true);
1306 }
1307
1308 bool dcn20_update_bandwidth(
1309 struct dc *dc,
1310 struct dc_state *context)
1311 {
1312 int i;
1313
1314
1315 if (!dc->res_pool->funcs->validate_bandwidth(dc, context, false))
1316 return false;
1317
1318
1319 dc->hwss.prepare_bandwidth(dc, context);
1320
1321
1322 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1323 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1324
1325 if (pipe_ctx->plane_state == NULL)
1326 continue;
1327
1328 if (pipe_ctx->top_pipe == NULL) {
1329 bool blank = !is_pipe_tree_visible(pipe_ctx);
1330
1331 pipe_ctx->stream_res.tg->funcs->program_global_sync(
1332 pipe_ctx->stream_res.tg,
1333 pipe_ctx->pipe_dlg_param.vready_offset,
1334 pipe_ctx->pipe_dlg_param.vstartup_start,
1335 pipe_ctx->pipe_dlg_param.vupdate_offset,
1336 pipe_ctx->pipe_dlg_param.vupdate_width);
1337
1338 pipe_ctx->stream_res.tg->funcs->set_vtg_params(
1339 pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing);
1340 if (pipe_ctx->prev_odm_pipe == NULL)
1341 dc->hwss.blank_pixel_data(dc, pipe_ctx, blank);
1342 }
1343
1344 pipe_ctx->plane_res.hubp->funcs->hubp_setup(
1345 pipe_ctx->plane_res.hubp,
1346 &pipe_ctx->dlg_regs,
1347 &pipe_ctx->ttu_regs,
1348 &pipe_ctx->rq_regs,
1349 &pipe_ctx->pipe_dlg_param);
1350 }
1351
1352 return true;
1353 }
1354
1355 static void dcn20_enable_writeback(
1356 struct dc *dc,
1357 const struct dc_stream_status *stream_status,
1358 struct dc_writeback_info *wb_info,
1359 struct dc_state *context)
1360 {
1361 struct dwbc *dwb;
1362 struct mcif_wb *mcif_wb;
1363 struct timing_generator *optc;
1364
1365 ASSERT(wb_info->dwb_pipe_inst < MAX_DWB_PIPES);
1366 ASSERT(wb_info->wb_enabled);
1367 dwb = dc->res_pool->dwbc[wb_info->dwb_pipe_inst];
1368 mcif_wb = dc->res_pool->mcif_wb[wb_info->dwb_pipe_inst];
1369
1370
1371 ASSERT(stream_status->primary_otg_inst < MAX_PIPES);
1372 optc = dc->res_pool->timing_generators[stream_status->primary_otg_inst];
1373 optc->funcs->set_dwb_source(optc, wb_info->dwb_pipe_inst);
1374
1375 mcif_wb->funcs->config_mcif_buf(mcif_wb, &wb_info->mcif_buf_params, wb_info->dwb_params.dest_height);
1376 mcif_wb->funcs->config_mcif_arb(mcif_wb, &context->bw_ctx.bw.dcn.bw_writeback.mcif_wb_arb[wb_info->dwb_pipe_inst]);
1377
1378 mcif_wb->funcs->enable_mcif(mcif_wb);
1379
1380 dwb->funcs->enable(dwb, &wb_info->dwb_params);
1381
1382 }
1383
1384 void dcn20_disable_writeback(
1385 struct dc *dc,
1386 unsigned int dwb_pipe_inst)
1387 {
1388 struct dwbc *dwb;
1389 struct mcif_wb *mcif_wb;
1390
1391 ASSERT(dwb_pipe_inst < MAX_DWB_PIPES);
1392 dwb = dc->res_pool->dwbc[dwb_pipe_inst];
1393 mcif_wb = dc->res_pool->mcif_wb[dwb_pipe_inst];
1394
1395 dwb->funcs->disable(dwb);
1396 mcif_wb->funcs->disable_mcif(mcif_wb);
1397 }
1398
1399 bool dcn20_hwss_wait_for_blank_complete(
1400 struct output_pixel_processor *opp)
1401 {
1402 int counter;
1403
1404 for (counter = 0; counter < 1000; counter++) {
1405 if (opp->funcs->dpg_is_blanked(opp))
1406 break;
1407
1408 udelay(100);
1409 }
1410
1411 if (counter == 1000) {
1412 dm_error("DC: failed to blank crtc!\n");
1413 return false;
1414 }
1415
1416 return true;
1417 }
1418
1419 bool dcn20_dmdata_status_done(struct pipe_ctx *pipe_ctx)
1420 {
1421 struct hubp *hubp = pipe_ctx->plane_res.hubp;
1422
1423 if (!hubp)
1424 return false;
1425 return hubp->funcs->dmdata_status_done(hubp);
1426 }
1427
1428 static void dcn20_disable_stream_gating(struct dc *dc, struct pipe_ctx *pipe_ctx)
1429 {
1430 #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
1431 struct dce_hwseq *hws = dc->hwseq;
1432
1433 if (pipe_ctx->stream_res.dsc) {
1434 struct pipe_ctx *odm_pipe = pipe_ctx->next_odm_pipe;
1435
1436 dcn20_dsc_pg_control(hws, pipe_ctx->stream_res.dsc->inst, true);
1437 while (odm_pipe) {
1438 dcn20_dsc_pg_control(hws, odm_pipe->stream_res.dsc->inst, true);
1439 odm_pipe = odm_pipe->next_odm_pipe;
1440 }
1441 }
1442 #endif
1443 }
1444
1445 static void dcn20_enable_stream_gating(struct dc *dc, struct pipe_ctx *pipe_ctx)
1446 {
1447 #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
1448 struct dce_hwseq *hws = dc->hwseq;
1449
1450 if (pipe_ctx->stream_res.dsc) {
1451 struct pipe_ctx *odm_pipe = pipe_ctx->next_odm_pipe;
1452
1453 dcn20_dsc_pg_control(hws, pipe_ctx->stream_res.dsc->inst, false);
1454 while (odm_pipe) {
1455 dcn20_dsc_pg_control(hws, odm_pipe->stream_res.dsc->inst, false);
1456 odm_pipe = odm_pipe->next_odm_pipe;
1457 }
1458 }
1459 #endif
1460 }
1461
1462 void dcn20_set_dmdata_attributes(struct pipe_ctx *pipe_ctx)
1463 {
1464 struct dc_dmdata_attributes attr = { 0 };
1465 struct hubp *hubp = pipe_ctx->plane_res.hubp;
1466
1467 attr.dmdata_mode = DMDATA_HW_MODE;
1468 attr.dmdata_size =
1469 dc_is_hdmi_signal(pipe_ctx->stream->signal) ? 32 : 36;
1470 attr.address.quad_part =
1471 pipe_ctx->stream->dmdata_address.quad_part;
1472 attr.dmdata_dl_delta = 0;
1473 attr.dmdata_qos_mode = 0;
1474 attr.dmdata_qos_level = 0;
1475 attr.dmdata_repeat = 1;
1476 attr.dmdata_updated = 1;
1477 attr.dmdata_sw_data = NULL;
1478
1479 hubp->funcs->dmdata_set_attributes(hubp, &attr);
1480 }
1481
1482 void dcn20_disable_stream(struct pipe_ctx *pipe_ctx)
1483 {
1484 dce110_disable_stream(pipe_ctx);
1485 }
1486
1487 static void dcn20_init_vm_ctx(
1488 struct dce_hwseq *hws,
1489 struct dc *dc,
1490 struct dc_virtual_addr_space_config *va_config,
1491 int vmid)
1492 {
1493 struct dcn_hubbub_virt_addr_config config;
1494
1495 if (vmid == 0) {
1496 ASSERT(0);
1497 return;
1498 }
1499
1500 config.page_table_start_addr = va_config->page_table_start_addr;
1501 config.page_table_end_addr = va_config->page_table_end_addr;
1502 config.page_table_block_size = va_config->page_table_block_size_in_bytes;
1503 config.page_table_depth = va_config->page_table_depth;
1504 config.page_table_base_addr = va_config->page_table_base_addr;
1505
1506 dc->res_pool->hubbub->funcs->init_vm_ctx(dc->res_pool->hubbub, &config, vmid);
1507 }
1508
1509 static int dcn20_init_sys_ctx(struct dce_hwseq *hws, struct dc *dc, struct dc_phy_addr_space_config *pa_config)
1510 {
1511 struct dcn_hubbub_phys_addr_config config;
1512
1513 config.system_aperture.fb_top = pa_config->system_aperture.fb_top;
1514 config.system_aperture.fb_offset = pa_config->system_aperture.fb_offset;
1515 config.system_aperture.fb_base = pa_config->system_aperture.fb_base;
1516 config.system_aperture.agp_top = pa_config->system_aperture.agp_top;
1517 config.system_aperture.agp_bot = pa_config->system_aperture.agp_bot;
1518 config.system_aperture.agp_base = pa_config->system_aperture.agp_base;
1519 config.gart_config.page_table_start_addr = pa_config->gart_config.page_table_start_addr;
1520 config.gart_config.page_table_end_addr = pa_config->gart_config.page_table_end_addr;
1521 config.gart_config.page_table_base_addr = pa_config->gart_config.page_table_base_addr;
1522 config.page_table_default_page_addr = pa_config->page_table_default_page_addr;
1523
1524 return dc->res_pool->hubbub->funcs->init_dchub_sys_ctx(dc->res_pool->hubbub, &config);
1525 }
1526
1527 static bool patch_address_for_sbs_tb_stereo(
1528 struct pipe_ctx *pipe_ctx, PHYSICAL_ADDRESS_LOC *addr)
1529 {
1530 struct dc_plane_state *plane_state = pipe_ctx->plane_state;
1531 bool sec_split = pipe_ctx->top_pipe &&
1532 pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state;
1533 if (sec_split && plane_state->address.type == PLN_ADDR_TYPE_GRPH_STEREO &&
1534 (pipe_ctx->stream->timing.timing_3d_format ==
1535 TIMING_3D_FORMAT_SIDE_BY_SIDE ||
1536 pipe_ctx->stream->timing.timing_3d_format ==
1537 TIMING_3D_FORMAT_TOP_AND_BOTTOM)) {
1538 *addr = plane_state->address.grph_stereo.left_addr;
1539 plane_state->address.grph_stereo.left_addr =
1540 plane_state->address.grph_stereo.right_addr;
1541 return true;
1542 }
1543
1544 if (pipe_ctx->stream->view_format != VIEW_3D_FORMAT_NONE &&
1545 plane_state->address.type != PLN_ADDR_TYPE_GRPH_STEREO) {
1546 plane_state->address.type = PLN_ADDR_TYPE_GRPH_STEREO;
1547 plane_state->address.grph_stereo.right_addr =
1548 plane_state->address.grph_stereo.left_addr;
1549 }
1550 return false;
1551 }
1552
1553
1554 static void dcn20_update_plane_addr(const struct dc *dc, struct pipe_ctx *pipe_ctx)
1555 {
1556 bool addr_patched = false;
1557 PHYSICAL_ADDRESS_LOC addr;
1558 struct dc_plane_state *plane_state = pipe_ctx->plane_state;
1559
1560 if (plane_state == NULL)
1561 return;
1562
1563 addr_patched = patch_address_for_sbs_tb_stereo(pipe_ctx, &addr);
1564
1565
1566 vm_helper_mark_vmid_used(dc->vm_helper, plane_state->address.vmid, pipe_ctx->plane_res.hubp->inst);
1567
1568 pipe_ctx->plane_res.hubp->funcs->hubp_program_surface_flip_and_addr(
1569 pipe_ctx->plane_res.hubp,
1570 &plane_state->address,
1571 plane_state->flip_immediate);
1572
1573 plane_state->status.requested_address = plane_state->address;
1574
1575 if (plane_state->flip_immediate)
1576 plane_state->status.current_address = plane_state->address;
1577
1578 if (addr_patched)
1579 pipe_ctx->plane_state->address.grph_stereo.left_addr = addr;
1580 }
1581
1582 void dcn20_unblank_stream(struct pipe_ctx *pipe_ctx,
1583 struct dc_link_settings *link_settings)
1584 {
1585 struct encoder_unblank_param params = { { 0 } };
1586 struct dc_stream_state *stream = pipe_ctx->stream;
1587 struct dc_link *link = stream->link;
1588 struct pipe_ctx *odm_pipe;
1589
1590 params.opp_cnt = 1;
1591 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
1592 params.opp_cnt++;
1593 }
1594
1595 params.timing = pipe_ctx->stream->timing;
1596
1597 params.link_settings.link_rate = link_settings->link_rate;
1598
1599 if (dc_is_dp_signal(pipe_ctx->stream->signal)) {
1600 if (optc1_is_two_pixels_per_containter(&stream->timing) || params.opp_cnt > 1)
1601 params.timing.pix_clk_100hz /= 2;
1602 pipe_ctx->stream_res.stream_enc->funcs->dp_set_odm_combine(
1603 pipe_ctx->stream_res.stream_enc, params.opp_cnt > 1);
1604 pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(pipe_ctx->stream_res.stream_enc, ¶ms);
1605 }
1606
1607 if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP) {
1608 link->dc->hwss.edp_backlight_control(link, true);
1609 }
1610 }
1611
1612 void dcn20_setup_vupdate_interrupt(struct pipe_ctx *pipe_ctx)
1613 {
1614 struct timing_generator *tg = pipe_ctx->stream_res.tg;
1615 int start_line = get_vupdate_offset_from_vsync(pipe_ctx);
1616
1617 if (start_line < 0)
1618 start_line = 0;
1619
1620 if (tg->funcs->setup_vertical_interrupt2)
1621 tg->funcs->setup_vertical_interrupt2(tg, start_line);
1622 }
1623
1624 static void dcn20_reset_back_end_for_pipe(
1625 struct dc *dc,
1626 struct pipe_ctx *pipe_ctx,
1627 struct dc_state *context)
1628 {
1629 int i;
1630 DC_LOGGER_INIT(dc->ctx->logger);
1631 if (pipe_ctx->stream_res.stream_enc == NULL) {
1632 pipe_ctx->stream = NULL;
1633 return;
1634 }
1635
1636 if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
1637
1638 if (!pipe_ctx->stream->dpms_off)
1639 core_link_disable_stream(pipe_ctx);
1640 else if (pipe_ctx->stream_res.audio)
1641 dc->hwss.disable_audio_stream(pipe_ctx);
1642
1643
1644 if (pipe_ctx->stream_res.audio) {
1645
1646 pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio);
1647
1648
1649 if (dc->caps.dynamic_audio == true) {
1650
1651
1652 update_audio_usage(&dc->current_state->res_ctx, dc->res_pool,
1653 pipe_ctx->stream_res.audio, false);
1654 pipe_ctx->stream_res.audio = NULL;
1655 }
1656 }
1657 }
1658 #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
1659 else if (pipe_ctx->stream_res.dsc) {
1660 dp_set_dsc_enable(pipe_ctx, false);
1661 }
1662 #endif
1663
1664
1665
1666
1667
1668 if (pipe_ctx->top_pipe == NULL) {
1669 pipe_ctx->stream_res.tg->funcs->disable_crtc(pipe_ctx->stream_res.tg);
1670
1671 pipe_ctx->stream_res.tg->funcs->enable_optc_clock(pipe_ctx->stream_res.tg, false);
1672 if (pipe_ctx->stream_res.tg->funcs->set_odm_bypass)
1673 pipe_ctx->stream_res.tg->funcs->set_odm_bypass(
1674 pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing);
1675
1676 if (pipe_ctx->stream_res.tg->funcs->set_drr)
1677 pipe_ctx->stream_res.tg->funcs->set_drr(
1678 pipe_ctx->stream_res.tg, NULL);
1679 }
1680
1681 for (i = 0; i < dc->res_pool->pipe_count; i++)
1682 if (&dc->current_state->res_ctx.pipe_ctx[i] == pipe_ctx)
1683 break;
1684
1685 if (i == dc->res_pool->pipe_count)
1686 return;
1687
1688 pipe_ctx->stream = NULL;
1689 DC_LOG_DEBUG("Reset back end for pipe %d, tg:%d\n",
1690 pipe_ctx->pipe_idx, pipe_ctx->stream_res.tg->inst);
1691 }
1692
1693 static void dcn20_reset_hw_ctx_wrap(
1694 struct dc *dc,
1695 struct dc_state *context)
1696 {
1697 int i;
1698
1699
1700 for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) {
1701 struct pipe_ctx *pipe_ctx_old =
1702 &dc->current_state->res_ctx.pipe_ctx[i];
1703 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1704
1705 if (!pipe_ctx_old->stream)
1706 continue;
1707
1708 if (pipe_ctx_old->top_pipe || pipe_ctx_old->prev_odm_pipe)
1709 continue;
1710
1711 if (!pipe_ctx->stream ||
1712 pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) {
1713 struct clock_source *old_clk = pipe_ctx_old->clock_source;
1714
1715 dcn20_reset_back_end_for_pipe(dc, pipe_ctx_old, dc->current_state);
1716 if (dc->hwss.enable_stream_gating)
1717 dc->hwss.enable_stream_gating(dc, pipe_ctx);
1718 if (old_clk)
1719 old_clk->funcs->cs_power_down(old_clk);
1720 }
1721 }
1722 }
1723
1724 static void dcn20_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx)
1725 {
1726 struct hubp *hubp = pipe_ctx->plane_res.hubp;
1727 struct mpcc_blnd_cfg blnd_cfg = { {0} };
1728 bool per_pixel_alpha = pipe_ctx->plane_state->per_pixel_alpha;
1729 int mpcc_id;
1730 struct mpcc *new_mpcc;
1731 struct mpc *mpc = dc->res_pool->mpc;
1732 struct mpc_tree *mpc_tree_params = &(pipe_ctx->stream_res.opp->mpc_tree_params);
1733
1734
1735 if (dc->debug.visual_confirm == VISUAL_CONFIRM_HDR) {
1736 dcn10_get_hdr_visual_confirm_color(
1737 pipe_ctx, &blnd_cfg.black_color);
1738 } else if (dc->debug.visual_confirm == VISUAL_CONFIRM_SURFACE) {
1739 dcn10_get_surface_visual_confirm_color(
1740 pipe_ctx, &blnd_cfg.black_color);
1741 }
1742
1743 if (per_pixel_alpha)
1744 blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA;
1745 else
1746 blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_GLOBAL_ALPHA;
1747
1748 blnd_cfg.overlap_only = false;
1749 blnd_cfg.global_gain = 0xff;
1750
1751 if (pipe_ctx->plane_state->global_alpha)
1752 blnd_cfg.global_alpha = pipe_ctx->plane_state->global_alpha_value;
1753 else
1754 blnd_cfg.global_alpha = 0xff;
1755
1756 blnd_cfg.background_color_bpc = 4;
1757 blnd_cfg.bottom_gain_mode = 0;
1758 blnd_cfg.top_gain = 0x1f000;
1759 blnd_cfg.bottom_inside_gain = 0x1f000;
1760 blnd_cfg.bottom_outside_gain = 0x1f000;
1761 blnd_cfg.pre_multiplied_alpha = per_pixel_alpha;
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771 mpcc_id = hubp->inst;
1772
1773
1774 if (!pipe_ctx->plane_state->update_flags.bits.full_update) {
1775 mpc->funcs->update_blending(mpc, &blnd_cfg, mpcc_id);
1776 return;
1777 }
1778
1779
1780 new_mpcc = mpc->funcs->get_mpcc_for_dpp(mpc_tree_params, mpcc_id);
1781
1782 if (new_mpcc != NULL)
1783 mpc->funcs->remove_mpcc(mpc, mpc_tree_params, new_mpcc);
1784 else
1785 if (dc->debug.sanity_checks)
1786 mpc->funcs->assert_mpcc_idle_before_connect(
1787 dc->res_pool->mpc, mpcc_id);
1788
1789
1790 new_mpcc = mpc->funcs->insert_plane(dc->res_pool->mpc,
1791 mpc_tree_params,
1792 &blnd_cfg,
1793 NULL,
1794 NULL,
1795 hubp->inst,
1796 mpcc_id);
1797
1798 ASSERT(new_mpcc != NULL);
1799 hubp->opp_id = pipe_ctx->stream_res.opp->inst;
1800 hubp->mpcc_id = mpcc_id;
1801 }
1802
1803 static int find_free_gsl_group(const struct dc *dc)
1804 {
1805 if (dc->res_pool->gsl_groups.gsl_0 == 0)
1806 return 1;
1807 if (dc->res_pool->gsl_groups.gsl_1 == 0)
1808 return 2;
1809 if (dc->res_pool->gsl_groups.gsl_2 == 0)
1810 return 3;
1811
1812 return 0;
1813 }
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830 void dcn20_setup_gsl_group_as_lock(
1831 const struct dc *dc,
1832 struct pipe_ctx *pipe_ctx,
1833 bool enable)
1834 {
1835 struct gsl_params gsl;
1836 int group_idx;
1837
1838 memset(&gsl, 0, sizeof(struct gsl_params));
1839
1840 if (enable) {
1841
1842
1843
1844 if (pipe_ctx->stream_res.gsl_group > 0)
1845 return;
1846
1847 group_idx = find_free_gsl_group(dc);
1848 ASSERT(group_idx != 0);
1849 pipe_ctx->stream_res.gsl_group = group_idx;
1850
1851
1852 switch (group_idx) {
1853 case 1:
1854 gsl.gsl0_en = 1;
1855 dc->res_pool->gsl_groups.gsl_0 = 1;
1856 break;
1857 case 2:
1858 gsl.gsl1_en = 1;
1859 dc->res_pool->gsl_groups.gsl_1 = 1;
1860 break;
1861 case 3:
1862 gsl.gsl2_en = 1;
1863 dc->res_pool->gsl_groups.gsl_2 = 1;
1864 break;
1865 default:
1866 BREAK_TO_DEBUGGER();
1867 return;
1868 }
1869 gsl.gsl_master_en = 1;
1870 } else {
1871 group_idx = pipe_ctx->stream_res.gsl_group;
1872 if (group_idx == 0)
1873 return;
1874
1875 pipe_ctx->stream_res.gsl_group = 0;
1876
1877
1878 switch (group_idx) {
1879 case 1:
1880 gsl.gsl0_en = 0;
1881 dc->res_pool->gsl_groups.gsl_0 = 0;
1882 break;
1883 case 2:
1884 gsl.gsl1_en = 0;
1885 dc->res_pool->gsl_groups.gsl_1 = 0;
1886 break;
1887 case 3:
1888 gsl.gsl2_en = 0;
1889 dc->res_pool->gsl_groups.gsl_2 = 0;
1890 break;
1891 default:
1892 BREAK_TO_DEBUGGER();
1893 return;
1894 }
1895 gsl.gsl_master_en = 0;
1896 }
1897
1898
1899 if (pipe_ctx->stream_res.tg->funcs->set_gsl != NULL &&
1900 pipe_ctx->stream_res.tg->funcs->set_gsl_source_select != NULL) {
1901 pipe_ctx->stream_res.tg->funcs->set_gsl(
1902 pipe_ctx->stream_res.tg,
1903 &gsl);
1904
1905 pipe_ctx->stream_res.tg->funcs->set_gsl_source_select(
1906 pipe_ctx->stream_res.tg, group_idx, enable ? 4 : 0);
1907 } else
1908 BREAK_TO_DEBUGGER();
1909 }
1910
1911 static void dcn20_set_flip_control_gsl(
1912 struct pipe_ctx *pipe_ctx,
1913 bool flip_immediate)
1914 {
1915 if (pipe_ctx && pipe_ctx->plane_res.hubp->funcs->hubp_set_flip_control_surface_gsl)
1916 pipe_ctx->plane_res.hubp->funcs->hubp_set_flip_control_surface_gsl(
1917 pipe_ctx->plane_res.hubp, flip_immediate);
1918
1919 }
1920
1921 static void dcn20_enable_stream(struct pipe_ctx *pipe_ctx)
1922 {
1923 enum dc_lane_count lane_count =
1924 pipe_ctx->stream->link->cur_link_settings.lane_count;
1925
1926 struct dc_crtc_timing *timing = &pipe_ctx->stream->timing;
1927 struct dc_link *link = pipe_ctx->stream->link;
1928
1929 uint32_t active_total_with_borders;
1930 uint32_t early_control = 0;
1931 struct timing_generator *tg = pipe_ctx->stream_res.tg;
1932
1933
1934
1935
1936
1937
1938 link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc,
1939 pipe_ctx->stream_res.stream_enc->id, true);
1940
1941 if (link->dc->hwss.program_dmdata_engine)
1942 link->dc->hwss.program_dmdata_engine(pipe_ctx);
1943
1944 link->dc->hwss.update_info_frame(pipe_ctx);
1945
1946
1947 active_total_with_borders =
1948 timing->h_addressable
1949 + timing->h_border_left
1950 + timing->h_border_right;
1951
1952 if (lane_count != 0)
1953 early_control = active_total_with_borders % lane_count;
1954
1955 if (early_control == 0)
1956 early_control = lane_count;
1957
1958 tg->funcs->set_early_control(tg, early_control);
1959
1960
1961 if (pipe_ctx->stream_res.audio != NULL) {
1962 if (dc_is_dp_signal(pipe_ctx->stream->signal))
1963 pipe_ctx->stream_res.stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_res.stream_enc);
1964 }
1965 }
1966
1967 static void dcn20_program_dmdata_engine(struct pipe_ctx *pipe_ctx)
1968 {
1969 struct dc_stream_state *stream = pipe_ctx->stream;
1970 struct hubp *hubp = pipe_ctx->plane_res.hubp;
1971 bool enable = false;
1972 struct stream_encoder *stream_enc = pipe_ctx->stream_res.stream_enc;
1973 enum dynamic_metadata_mode mode = dc_is_dp_signal(stream->signal)
1974 ? dmdata_dp
1975 : dmdata_hdmi;
1976
1977
1978 if (pipe_ctx->stream->dmdata_address.quad_part != 0) {
1979 pipe_ctx->stream_res.encoder_info_frame.hdrsmd.valid = false;
1980 enable = true;
1981 }
1982
1983 if (!hubp)
1984 return;
1985
1986 if (!stream_enc || !stream_enc->funcs->set_dynamic_metadata)
1987 return;
1988
1989 stream_enc->funcs->set_dynamic_metadata(stream_enc, enable,
1990 hubp->inst, mode);
1991 }
1992
1993 static void dcn20_fpga_init_hw(struct dc *dc)
1994 {
1995 int i, j;
1996 struct dce_hwseq *hws = dc->hwseq;
1997 struct resource_pool *res_pool = dc->res_pool;
1998 struct dc_state *context = dc->current_state;
1999
2000 if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks)
2001 dc->clk_mgr->funcs->init_clocks(dc->clk_mgr);
2002
2003
2004 if (res_pool->dccg->funcs->dccg_init)
2005 res_pool->dccg->funcs->dccg_init(res_pool->dccg);
2006
2007
2008 dc->hwss.enable_power_gating_plane(hws, true);
2009
2010
2011 REG_WRITE(RBBMIF_TIMEOUT_DIS, 0xFFFFFFFF);
2012 REG_WRITE(RBBMIF_TIMEOUT_DIS_2, 0xFFFFFFFF);
2013
2014 dcn20_dccg_init(hws);
2015
2016 REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, 2);
2017 REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1);
2018 if (REG(REFCLK_CNTL))
2019 REG_WRITE(REFCLK_CNTL, 0);
2020
2021
2022
2023
2024 for (i = 0; i < dc->res_pool->timing_generator_count; i++) {
2025 struct timing_generator *tg = dc->res_pool->timing_generators[i];
2026
2027 if (tg->funcs->is_tg_enabled(tg))
2028 dcn20_init_blank(dc, tg);
2029 }
2030
2031 for (i = 0; i < res_pool->timing_generator_count; i++) {
2032 struct timing_generator *tg = dc->res_pool->timing_generators[i];
2033
2034 if (tg->funcs->is_tg_enabled(tg))
2035 tg->funcs->lock(tg);
2036 }
2037
2038 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2039 struct dpp *dpp = res_pool->dpps[i];
2040
2041 dpp->funcs->dpp_reset(dpp);
2042 }
2043
2044
2045 res_pool->mpc->funcs->mpc_init(res_pool->mpc);
2046
2047
2048 for (i = 0; i < dc->res_pool->res_cap->num_opp; i++) {
2049 res_pool->opps[i]->mpc_tree_params.opp_id = res_pool->opps[i]->inst;
2050 res_pool->opps[i]->mpc_tree_params.opp_list = NULL;
2051 for (j = 0; j < MAX_PIPES; j++)
2052 res_pool->opps[i]->mpcc_disconnect_pending[j] = false;
2053 }
2054
2055 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2056 struct timing_generator *tg = dc->res_pool->timing_generators[i];
2057 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2058 struct hubp *hubp = dc->res_pool->hubps[i];
2059 struct dpp *dpp = dc->res_pool->dpps[i];
2060
2061 pipe_ctx->stream_res.tg = tg;
2062 pipe_ctx->pipe_idx = i;
2063
2064 pipe_ctx->plane_res.hubp = hubp;
2065 pipe_ctx->plane_res.dpp = dpp;
2066 pipe_ctx->plane_res.mpcc_inst = dpp->inst;
2067 hubp->mpcc_id = dpp->inst;
2068 hubp->opp_id = OPP_ID_INVALID;
2069 hubp->power_gated = false;
2070 pipe_ctx->stream_res.opp = NULL;
2071
2072 hubp->funcs->hubp_init(hubp);
2073
2074
2075
2076 dc->res_pool->opps[i]->mpcc_disconnect_pending[pipe_ctx->plane_res.mpcc_inst] = true;
2077 pipe_ctx->stream_res.opp = dc->res_pool->opps[i];
2078
2079 hwss1_plane_atomic_disconnect(dc, pipe_ctx);
2080 }
2081
2082
2083 for (i = 0; i < res_pool->res_cap->num_dwb; i++)
2084 res_pool->dwbc[i]->mcif = res_pool->mcif_wb[i];
2085
2086 for (i = 0; i < dc->res_pool->timing_generator_count; i++) {
2087 struct timing_generator *tg = dc->res_pool->timing_generators[i];
2088
2089 if (tg->funcs->is_tg_enabled(tg))
2090 tg->funcs->unlock(tg);
2091 }
2092
2093 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2094 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2095
2096 dc->hwss.disable_plane(dc, pipe_ctx);
2097
2098 pipe_ctx->stream_res.tg = NULL;
2099 pipe_ctx->plane_res.hubp = NULL;
2100 }
2101
2102 for (i = 0; i < dc->res_pool->timing_generator_count; i++) {
2103 struct timing_generator *tg = dc->res_pool->timing_generators[i];
2104
2105 tg->funcs->tg_init(tg);
2106 }
2107 }
2108
2109 void dcn20_hw_sequencer_construct(struct dc *dc)
2110 {
2111 dcn10_hw_sequencer_construct(dc);
2112 dc->hwss.unblank_stream = dcn20_unblank_stream;
2113 dc->hwss.update_plane_addr = dcn20_update_plane_addr;
2114 dc->hwss.enable_stream_timing = dcn20_enable_stream_timing;
2115 dc->hwss.program_triplebuffer = dcn20_program_tripleBuffer;
2116 dc->hwss.set_input_transfer_func = dcn20_set_input_transfer_func;
2117 dc->hwss.set_output_transfer_func = dcn20_set_output_transfer_func;
2118 dc->hwss.apply_ctx_for_surface = dcn20_apply_ctx_for_surface;
2119 dc->hwss.pipe_control_lock = dcn20_pipe_control_lock;
2120 dc->hwss.pipe_control_lock_global = dcn20_pipe_control_lock_global;
2121 dc->hwss.optimize_bandwidth = dcn20_optimize_bandwidth;
2122 dc->hwss.prepare_bandwidth = dcn20_prepare_bandwidth;
2123 dc->hwss.update_bandwidth = dcn20_update_bandwidth;
2124 dc->hwss.enable_writeback = dcn20_enable_writeback;
2125 dc->hwss.disable_writeback = dcn20_disable_writeback;
2126 dc->hwss.program_output_csc = dcn20_program_output_csc;
2127 dc->hwss.update_odm = dcn20_update_odm;
2128 dc->hwss.blank_pixel_data = dcn20_blank_pixel_data;
2129 dc->hwss.dmdata_status_done = dcn20_dmdata_status_done;
2130 dc->hwss.program_dmdata_engine = dcn20_program_dmdata_engine;
2131 dc->hwss.enable_stream = dcn20_enable_stream;
2132 dc->hwss.disable_stream = dcn20_disable_stream;
2133 dc->hwss.init_sys_ctx = dcn20_init_sys_ctx;
2134 dc->hwss.init_vm_ctx = dcn20_init_vm_ctx;
2135 dc->hwss.disable_stream_gating = dcn20_disable_stream_gating;
2136 dc->hwss.enable_stream_gating = dcn20_enable_stream_gating;
2137 dc->hwss.setup_vupdate_interrupt = dcn20_setup_vupdate_interrupt;
2138 dc->hwss.reset_hw_ctx_wrap = dcn20_reset_hw_ctx_wrap;
2139 dc->hwss.update_mpcc = dcn20_update_mpcc;
2140 dc->hwss.set_flip_control_gsl = dcn20_set_flip_control_gsl;
2141 dc->hwss.init_blank = dcn20_init_blank;
2142 dc->hwss.disable_plane = dcn20_disable_plane;
2143 dc->hwss.plane_atomic_disable = dcn20_plane_atomic_disable;
2144 dc->hwss.enable_power_gating_plane = dcn20_enable_power_gating_plane;
2145 dc->hwss.dpp_pg_control = dcn20_dpp_pg_control;
2146 dc->hwss.hubp_pg_control = dcn20_hubp_pg_control;
2147 #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
2148 dc->hwss.dsc_pg_control = dcn20_dsc_pg_control;
2149 #else
2150 dc->hwss.dsc_pg_control = NULL;
2151 #endif
2152 dc->hwss.disable_vga = dcn20_disable_vga;
2153
2154 if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
2155 dc->hwss.init_hw = dcn20_fpga_init_hw;
2156 dc->hwss.init_pipes = NULL;
2157 }
2158
2159
2160 }