]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
drm/amd/display: minor dcn10_hwseq clean up/refactor
[mirror_ubuntu-bionic-kernel.git] / drivers / gpu / drm / amd / display / dc / dcn10 / dcn10_hw_sequencer.c
1 /*
2 * Copyright 2016 Advanced Micro Devices, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: AMD
23 *
24 */
25
26 #include "dm_services.h"
27 #include "dc.h"
28 #include "core_dc.h"
29 #include "core_types.h"
30 #include "core_status.h"
31 #include "resource.h"
32 #include "dcn10_hw_sequencer.h"
33 #include "dce110/dce110_hw_sequencer.h"
34 #include "dce/dce_hwseq.h"
35 #include "abm.h"
36 #include "mem_input.h"
37 #include "timing_generator.h"
38 #include "opp.h"
39 #include "ipp.h"
40 #include "dc_bios_types.h"
41 #include "raven1/DCN/dcn_1_0_offset.h"
42 #include "raven1/DCN/dcn_1_0_sh_mask.h"
43 #include "vega10/soc15ip.h"
44 #include "custom_float.h"
45 #include "reg_helper.h"
46
47 #define CTX \
48 hws->ctx
49 #define REG(reg)\
50 hws->regs->reg
51
52 #undef FN
53 #define FN(reg_name, field_name) \
54 hws->shifts->field_name, hws->masks->field_name
55
56 static void enable_dppclk(
57 struct dce_hwseq *hws,
58 uint8_t plane_id,
59 uint32_t requested_pix_clk,
60 bool dppclk_div)
61 {
62 dm_logger_write(hws->ctx->logger, LOG_SURFACE,
63 "dppclk_rate_control for pipe %d programed to %d\n",
64 plane_id,
65 dppclk_div);
66
67 if (dppclk_div) {
68 /* 1/2 DISPCLK*/
69 REG_UPDATE_2(DPP_CONTROL[plane_id],
70 DPPCLK_RATE_CONTROL, 1,
71 DPP_CLOCK_ENABLE, 1);
72 } else {
73 /* DISPCLK */
74 REG_UPDATE_2(DPP_CONTROL[plane_id],
75 DPPCLK_RATE_CONTROL, 0,
76 DPP_CLOCK_ENABLE, 1);
77 }
78 }
79
80 static void enable_power_gating_plane(
81 struct dce_hwseq *hws,
82 bool enable)
83 {
84 bool force_on = 1; /* disable power gating */
85
86 if (enable)
87 force_on = 0;
88
89 /* DCHUBP0/1/2/3 */
90 REG_UPDATE(DOMAIN0_PG_CONFIG, DOMAIN0_POWER_FORCEON, force_on);
91 REG_UPDATE(DOMAIN2_PG_CONFIG, DOMAIN2_POWER_FORCEON, force_on);
92 REG_UPDATE(DOMAIN4_PG_CONFIG, DOMAIN4_POWER_FORCEON, force_on);
93 REG_UPDATE(DOMAIN6_PG_CONFIG, DOMAIN6_POWER_FORCEON, force_on);
94
95 /* DPP0/1/2/3 */
96 REG_UPDATE(DOMAIN1_PG_CONFIG, DOMAIN1_POWER_FORCEON, force_on);
97 REG_UPDATE(DOMAIN3_PG_CONFIG, DOMAIN3_POWER_FORCEON, force_on);
98 REG_UPDATE(DOMAIN5_PG_CONFIG, DOMAIN5_POWER_FORCEON, force_on);
99 REG_UPDATE(DOMAIN7_PG_CONFIG, DOMAIN7_POWER_FORCEON, force_on);
100 }
101
102 static void dpp_pg_control(
103 struct dce_hwseq *hws,
104 unsigned int dpp_inst,
105 bool power_on)
106 {
107 uint32_t power_gate = power_on ? 0 : 1;
108 uint32_t pwr_status = power_on ? 0 : 2;
109
110 if (hws->ctx->dc->debug.disable_dpp_power_gate)
111 return;
112
113 switch (dpp_inst) {
114 case 0: /* DPP0 */
115 REG_UPDATE(DOMAIN1_PG_CONFIG,
116 DOMAIN1_POWER_GATE, power_gate);
117
118 REG_WAIT(DOMAIN1_PG_STATUS,
119 DOMAIN1_PGFSM_PWR_STATUS, pwr_status, 20000, 200000);
120 break;
121 case 1: /* DPP1 */
122 REG_UPDATE(DOMAIN3_PG_CONFIG,
123 DOMAIN3_POWER_GATE, power_gate);
124
125 REG_WAIT(DOMAIN3_PG_STATUS,
126 DOMAIN3_PGFSM_PWR_STATUS, pwr_status, 20000, 200000);
127 break;
128 case 2: /* DPP2 */
129 REG_UPDATE(DOMAIN5_PG_CONFIG,
130 DOMAIN5_POWER_GATE, power_gate);
131
132 REG_WAIT(DOMAIN5_PG_STATUS,
133 DOMAIN5_PGFSM_PWR_STATUS, pwr_status, 20000, 200000);
134 break;
135 case 3: /* DPP3 */
136 REG_UPDATE(DOMAIN7_PG_CONFIG,
137 DOMAIN7_POWER_GATE, power_gate);
138
139 REG_WAIT(DOMAIN7_PG_STATUS,
140 DOMAIN7_PGFSM_PWR_STATUS, pwr_status, 20000, 200000);
141 break;
142 default:
143 BREAK_TO_DEBUGGER();
144 break;
145 }
146 }
147
148 static void hubp_pg_control(
149 struct dce_hwseq *hws,
150 unsigned int hubp_inst,
151 bool power_on)
152 {
153 uint32_t power_gate = power_on ? 0 : 1;
154 uint32_t pwr_status = power_on ? 0 : 2;
155
156 if (hws->ctx->dc->debug.disable_hubp_power_gate)
157 return;
158
159 switch (hubp_inst) {
160 case 0: /* DCHUBP0 */
161 REG_UPDATE(DOMAIN0_PG_CONFIG,
162 DOMAIN0_POWER_GATE, power_gate);
163
164 REG_WAIT(DOMAIN0_PG_STATUS,
165 DOMAIN0_PGFSM_PWR_STATUS, pwr_status, 20000, 200000);
166 break;
167 case 1: /* DCHUBP1 */
168 REG_UPDATE(DOMAIN2_PG_CONFIG,
169 DOMAIN2_POWER_GATE, power_gate);
170
171 REG_WAIT(DOMAIN2_PG_STATUS,
172 DOMAIN2_PGFSM_PWR_STATUS, pwr_status, 20000, 200000);
173 break;
174 case 2: /* DCHUBP2 */
175 REG_UPDATE(DOMAIN4_PG_CONFIG,
176 DOMAIN4_POWER_GATE, power_gate);
177
178 REG_WAIT(DOMAIN4_PG_STATUS,
179 DOMAIN4_PGFSM_PWR_STATUS, pwr_status, 20000, 200000);
180 break;
181 case 3: /* DCHUBP3 */
182 REG_UPDATE(DOMAIN6_PG_CONFIG,
183 DOMAIN6_POWER_GATE, power_gate);
184
185 REG_WAIT(DOMAIN6_PG_STATUS,
186 DOMAIN6_PGFSM_PWR_STATUS, pwr_status, 20000, 200000);
187 break;
188 default:
189 BREAK_TO_DEBUGGER();
190 break;
191 }
192 }
193
194 static void power_on_plane(
195 struct dce_hwseq *hws,
196 int plane_id)
197 {
198 REG_SET(DC_IP_REQUEST_CNTL, 0,
199 IP_REQUEST_EN, 1);
200 dpp_pg_control(hws, plane_id, true);
201 hubp_pg_control(hws, plane_id, true);
202 REG_SET(DC_IP_REQUEST_CNTL, 0,
203 IP_REQUEST_EN, 0);
204 dm_logger_write(hws->ctx->logger, LOG_DC,
205 "Un-gated front end for pipe %d\n", plane_id);
206 }
207
208 static void bios_golden_init(struct core_dc *dc)
209 {
210 struct dc_bios *bp = dc->ctx->dc_bios;
211 int i;
212
213 /* initialize dcn global */
214 bp->funcs->enable_disp_power_gating(bp,
215 CONTROLLER_ID_D0, ASIC_PIPE_INIT);
216
217 for (i = 0; i < dc->res_pool->pipe_count; i++) {
218 /* initialize dcn per pipe */
219 bp->funcs->enable_disp_power_gating(bp,
220 CONTROLLER_ID_D0 + i, ASIC_PIPE_DISABLE);
221 }
222 }
223
224 /*
225 * This should be done within BIOS, we are doing it for maximus only
226 */
227 static void dchubup_setup_timer(struct dce_hwseq *hws)
228 {
229 REG_WRITE(REFCLK_CNTL, 0);
230
231 REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1);
232 }
233
234 static void init_hw(struct core_dc *dc)
235 {
236 int i;
237 struct transform *xfm;
238 struct abm *abm;
239 struct dce_hwseq *hws = dc->hwseq;
240
241 #if 1
242 if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
243 dchubup_setup_timer(dc->hwseq);
244
245 /* TODO: dchubp_map_fb_to_mc will be moved to dchub interface
246 * between dc and kmd
247 */
248 /*dchubp_map_fb_to_mc(dc->hwseq);*/
249 REG_WRITE(DIO_MEM_PWR_CTRL, 0);
250
251 if (!dc->public.debug.disable_clock_gate) {
252 /* enable all DCN clock gating */
253 REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0);
254
255 REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0);
256
257 REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);
258 }
259
260 enable_power_gating_plane(dc->hwseq, true);
261 return;
262 }
263 /* end of FPGA. Below if real ASIC */
264 #endif
265
266 bios_golden_init(dc);
267
268 for (i = 0; i < dc->res_pool->pipe_count; i++) {
269 xfm = dc->res_pool->transforms[i];
270 xfm->funcs->transform_reset(xfm);
271 }
272
273 for (i = 0; i < dc->link_count; i++) {
274 /* Power up AND update implementation according to the
275 * required signal (which may be different from the
276 * default signal on connector).
277 */
278 struct core_link *link = dc->links[i];
279
280 link->link_enc->funcs->hw_init(link->link_enc);
281 }
282
283 for (i = 0; i < dc->res_pool->pipe_count; i++) {
284 struct timing_generator *tg =
285 dc->res_pool->timing_generators[i];
286 struct mpcc *mpcc =
287 dc->res_pool->mpcc[i];
288 struct mpcc_cfg mpcc_cfg;
289
290 tg->funcs->lock(tg);
291 mpcc_cfg.opp_id = 0xf;
292 mpcc_cfg.top_dpp_id = 0xf;
293 mpcc_cfg.bot_mpcc_id = 0xf;
294 mpcc_cfg.top_of_tree = true;
295 mpcc->funcs->set(mpcc, &mpcc_cfg);
296 tg->funcs->unlock(tg);
297
298 tg->funcs->disable_vga(tg);
299 /* Blank controller using driver code instead of
300 * command table.
301 */
302 tg->funcs->set_blank(tg, true);
303 hwss_wait_for_blank_complete(tg);
304 }
305
306 for (i = 0; i < dc->res_pool->audio_count; i++) {
307 struct audio *audio = dc->res_pool->audios[i];
308
309 audio->funcs->hw_init(audio);
310 }
311
312 abm = dc->res_pool->abm;
313 if (abm != NULL) {
314 abm->funcs->init_backlight(abm);
315 abm->funcs->abm_init(abm);
316 }
317
318 /* power AFMT HDMI memory TODO: may move to dis/en output save power*/
319 REG_WRITE(DIO_MEM_PWR_CTRL, 0);
320
321 if (!dc->public.debug.disable_clock_gate) {
322 /* enable all DCN clock gating */
323 REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0);
324
325 REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0);
326
327 REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);
328 }
329
330 enable_power_gating_plane(dc->hwseq, true);
331 }
332
333 static enum dc_status dcn10_prog_pixclk_crtc_otg(
334 struct pipe_ctx *pipe_ctx,
335 struct validate_context *context,
336 struct core_dc *dc)
337 {
338 struct core_stream *stream = pipe_ctx->stream;
339 enum dc_color_space color_space;
340 struct tg_color black_color = {0};
341 bool enableStereo = stream->public.timing.timing_3d_format == TIMING_3D_FORMAT_NONE ?
342 false:true;
343 bool rightEyePolarity = stream->public.timing.flags.RIGHT_EYE_3D_POLARITY;
344
345
346 /* by upper caller loop, pipe0 is parent pipe and be called first.
347 * back end is set up by for pipe0. Other children pipe share back end
348 * with pipe 0. No program is needed.
349 */
350 if (pipe_ctx->top_pipe != NULL)
351 return DC_OK;
352
353 /* TODO check if timing_changed, disable stream if timing changed */
354
355 /* HW program guide assume display already disable
356 * by unplug sequence. OTG assume stop.
357 */
358 pipe_ctx->tg->funcs->enable_optc_clock(pipe_ctx->tg, true);
359
360 if (false == pipe_ctx->clock_source->funcs->program_pix_clk(
361 pipe_ctx->clock_source,
362 &pipe_ctx->pix_clk_params,
363 &pipe_ctx->pll_settings)) {
364 BREAK_TO_DEBUGGER();
365 return DC_ERROR_UNEXPECTED;
366 }
367 pipe_ctx->tg->dlg_otg_param.vready_offset = pipe_ctx->pipe_dlg_param.vready_offset;
368 pipe_ctx->tg->dlg_otg_param.vstartup_start = pipe_ctx->pipe_dlg_param.vstartup_start;
369 pipe_ctx->tg->dlg_otg_param.vupdate_offset = pipe_ctx->pipe_dlg_param.vupdate_offset;
370 pipe_ctx->tg->dlg_otg_param.vupdate_width = pipe_ctx->pipe_dlg_param.vupdate_width;
371
372 pipe_ctx->tg->dlg_otg_param.signal = pipe_ctx->stream->signal;
373
374 pipe_ctx->tg->funcs->program_timing(
375 pipe_ctx->tg,
376 &stream->public.timing,
377 true);
378
379 pipe_ctx->opp->funcs->opp_set_stereo_polarity(
380 pipe_ctx->opp,
381 enableStereo,
382 rightEyePolarity);
383
384 #if 0 /* move to after enable_crtc */
385 /* TODO: OPP FMT, ABM. etc. should be done here. */
386 /* or FPGA now. instance 0 only. TODO: move to opp.c */
387
388 inst_offset = reg_offsets[pipe_ctx->tg->inst].fmt;
389
390 pipe_ctx->opp->funcs->opp_program_fmt(
391 pipe_ctx->opp,
392 &stream->bit_depth_params,
393 &stream->clamping);
394 #endif
395 /* program otg blank color */
396 color_space = stream->public.output_color_space;
397 color_space_to_black_color(dc, color_space, &black_color);
398 pipe_ctx->tg->funcs->set_blank_color(
399 pipe_ctx->tg,
400 &black_color);
401
402 pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, true);
403 hwss_wait_for_blank_complete(pipe_ctx->tg);
404
405 /* VTG is within DCHUB command block. DCFCLK is always on */
406 if (false == pipe_ctx->tg->funcs->enable_crtc(pipe_ctx->tg)) {
407 BREAK_TO_DEBUGGER();
408 return DC_ERROR_UNEXPECTED;
409 }
410
411 /* TODO program crtc source select for non-virtual signal*/
412 /* TODO program FMT */
413 /* TODO setup link_enc */
414 /* TODO set stream attributes */
415 /* TODO program audio */
416 /* TODO enable stream if timing changed */
417 /* TODO unblank stream if DP */
418
419 return DC_OK;
420 }
421
422 static void reset_back_end_for_pipe(
423 struct core_dc *dc,
424 struct pipe_ctx *pipe_ctx,
425 struct validate_context *context)
426 {
427 int i;
428
429 if (pipe_ctx->stream_enc == NULL) {
430 pipe_ctx->stream = NULL;
431 return;
432 }
433
434 /* TODOFPGA break core_link_disable_stream into 2 functions:
435 * disable_stream and disable_link. disable_link will disable PHYPLL
436 * which is used by otg. Move disable_link after disable_crtc
437 */
438 if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment))
439 core_link_disable_stream(pipe_ctx);
440
441 /* by upper caller loop, parent pipe: pipe0, will be reset last.
442 * back end share by all pipes and will be disable only when disable
443 * parent pipe.
444 */
445 if (pipe_ctx->top_pipe == NULL) {
446 pipe_ctx->tg->funcs->disable_crtc(pipe_ctx->tg);
447
448 pipe_ctx->tg->funcs->enable_optc_clock(pipe_ctx->tg, false);
449 }
450
451 if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment))
452 resource_unreference_clock_source(
453 &context->res_ctx, dc->res_pool,
454 &pipe_ctx->clock_source);
455
456 for (i = 0; i < dc->res_pool->pipe_count; i++)
457 if (&dc->current_context->res_ctx.pipe_ctx[i] == pipe_ctx)
458 break;
459
460 if (i == dc->res_pool->pipe_count)
461 return;
462
463 pipe_ctx->stream = NULL;
464 dm_logger_write(dc->ctx->logger, LOG_DC,
465 "Reset back end for pipe %d, tg:%d\n",
466 pipe_ctx->pipe_idx, pipe_ctx->tg->inst);
467 }
468
469 static void reset_front_end(
470 struct core_dc *dc,
471 int fe_idx)
472 {
473 struct dce_hwseq *hws = dc->hwseq;
474 struct mpcc_cfg mpcc_cfg;
475 struct mem_input *mi = dc->res_pool->mis[fe_idx];
476 struct transform *xfm = dc->res_pool->transforms[fe_idx];
477 struct mpcc *mpcc = dc->res_pool->mpcc[fe_idx];
478 struct timing_generator *tg = dc->res_pool->timing_generators[mpcc->opp_id];
479
480 /*Already reset*/
481 if (mpcc->opp_id == 0xf)
482 return;
483
484 mi->funcs->dcc_control(mi, false, false);
485 tg->funcs->lock(tg);
486
487 mpcc_cfg.opp_id = 0xf;
488 mpcc_cfg.top_dpp_id = 0xf;
489 mpcc_cfg.bot_mpcc_id = 0xf;
490 mpcc_cfg.top_of_tree = tg->inst == mpcc->inst;
491 mpcc->funcs->set(mpcc, &mpcc_cfg);
492
493 REG_UPDATE(OTG_GLOBAL_SYNC_STATUS[tg->inst], VUPDATE_NO_LOCK_EVENT_CLEAR, 1);
494 tg->funcs->unlock(tg);
495 REG_WAIT(OTG_GLOBAL_SYNC_STATUS[tg->inst], VUPDATE_NO_LOCK_EVENT_OCCURRED, 1, 20000, 200000);
496
497 mpcc->funcs->wait_for_idle(mpcc);
498 mi->funcs->set_blank(mi, true);
499 REG_WAIT(DCHUBP_CNTL[fe_idx], HUBP_NO_OUTSTANDING_REQ, 1, 20000, 200000);
500 REG_UPDATE(HUBP_CLK_CNTL[fe_idx], HUBP_CLOCK_ENABLE, 0);
501 REG_UPDATE(DPP_CONTROL[fe_idx], DPP_CLOCK_ENABLE, 0);
502
503 xfm->funcs->transform_reset(xfm);
504
505 dm_logger_write(dc->ctx->logger, LOG_DC,
506 "Reset front end %d\n",
507 fe_idx);
508 }
509
510 static void dcn10_power_down_fe(struct core_dc *dc, int fe_idx)
511 {
512 struct dce_hwseq *hws = dc->hwseq;
513
514 reset_front_end(dc, fe_idx);
515
516 REG_SET(DC_IP_REQUEST_CNTL, 0,
517 IP_REQUEST_EN, 1);
518 dpp_pg_control(hws, fe_idx, false);
519 hubp_pg_control(hws, fe_idx, false);
520 REG_SET(DC_IP_REQUEST_CNTL, 0,
521 IP_REQUEST_EN, 0);
522 dm_logger_write(dc->ctx->logger, LOG_DC,
523 "Power gated front end %d\n", fe_idx);
524 }
525
526 static void reset_hw_ctx_wrap(
527 struct core_dc *dc,
528 struct validate_context *context)
529 {
530 int i;
531
532 /* Reset Front End*/
533 for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) {
534 struct pipe_ctx *pipe_ctx_old =
535 &dc->current_context->res_ctx.pipe_ctx[i];
536 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
537
538 /*if (!pipe_ctx_old->stream)
539 continue;*/
540
541 if (!pipe_ctx->stream || !pipe_ctx->surface)
542 dcn10_power_down_fe(dc, i);
543 else if (pipe_need_reprogram(pipe_ctx_old, pipe_ctx))
544 reset_front_end(dc, i);
545 }
546 /* Reset Back End*/
547 for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) {
548 struct pipe_ctx *pipe_ctx_old =
549 &dc->current_context->res_ctx.pipe_ctx[i];
550 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
551
552 if (!pipe_ctx_old->stream)
553 continue;
554
555 if (!pipe_ctx->stream ||
556 pipe_need_reprogram(pipe_ctx_old, pipe_ctx))
557 reset_back_end_for_pipe(dc, pipe_ctx_old, dc->current_context);
558 }
559 }
560
561 static bool patch_address_for_sbs_tb_stereo(
562 struct pipe_ctx *pipe_ctx, PHYSICAL_ADDRESS_LOC *addr)
563 {
564 struct core_surface *surface = pipe_ctx->surface;
565 bool sec_split = pipe_ctx->top_pipe &&
566 pipe_ctx->top_pipe->surface == pipe_ctx->surface;
567 if (sec_split && surface->public.address.type == PLN_ADDR_TYPE_GRPH_STEREO &&
568 (pipe_ctx->stream->public.timing.timing_3d_format ==
569 TIMING_3D_FORMAT_SIDE_BY_SIDE ||
570 pipe_ctx->stream->public.timing.timing_3d_format ==
571 TIMING_3D_FORMAT_TOP_AND_BOTTOM)) {
572 *addr = surface->public.address.grph_stereo.left_addr;
573 surface->public.address.grph_stereo.left_addr =
574 surface->public.address.grph_stereo.right_addr;
575 return true;
576 } else {
577 if (pipe_ctx->stream->public.view_format != VIEW_3D_FORMAT_NONE &&
578 surface->public.address.type != PLN_ADDR_TYPE_GRPH_STEREO) {
579 surface->public.address.type = PLN_ADDR_TYPE_GRPH_STEREO;
580 surface->public.address.grph_stereo.right_addr =
581 surface->public.address.grph_stereo.left_addr;
582 }
583 }
584 return false;
585 }
586
587 static void update_plane_addr(const struct core_dc *dc, struct pipe_ctx *pipe_ctx)
588 {
589 bool addr_patched = false;
590 PHYSICAL_ADDRESS_LOC addr;
591 struct core_surface *surface = pipe_ctx->surface;
592
593 if (surface == NULL)
594 return;
595 addr_patched = patch_address_for_sbs_tb_stereo(pipe_ctx, &addr);
596 pipe_ctx->mi->funcs->mem_input_program_surface_flip_and_addr(
597 pipe_ctx->mi,
598 &surface->public.address,
599 surface->public.flip_immediate);
600 surface->status.requested_address = surface->public.address;
601 if (addr_patched)
602 pipe_ctx->surface->public.address.grph_stereo.left_addr = addr;
603 }
604
605 static bool dcn10_set_input_transfer_func(
606 struct pipe_ctx *pipe_ctx, const struct core_surface *surface)
607 {
608 struct input_pixel_processor *ipp = pipe_ctx->ipp;
609 const struct core_transfer_func *tf = NULL;
610 bool result = true;
611
612 if (ipp == NULL)
613 return false;
614
615 if (surface->public.in_transfer_func)
616 tf = DC_TRANSFER_FUNC_TO_CORE(surface->public.in_transfer_func);
617
618 if (surface->public.gamma_correction && dce_use_lut(surface))
619 ipp->funcs->ipp_program_input_lut(ipp,
620 surface->public.gamma_correction);
621
622 if (tf == NULL)
623 ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS);
624 else if (tf->public.type == TF_TYPE_PREDEFINED) {
625 switch (tf->public.tf) {
626 case TRANSFER_FUNCTION_SRGB:
627 ipp->funcs->ipp_set_degamma(ipp,
628 IPP_DEGAMMA_MODE_HW_sRGB);
629 break;
630 case TRANSFER_FUNCTION_BT709:
631 ipp->funcs->ipp_set_degamma(ipp,
632 IPP_DEGAMMA_MODE_HW_xvYCC);
633 break;
634 case TRANSFER_FUNCTION_LINEAR:
635 ipp->funcs->ipp_set_degamma(ipp,
636 IPP_DEGAMMA_MODE_BYPASS);
637 break;
638 case TRANSFER_FUNCTION_PQ:
639 result = false;
640 break;
641 default:
642 result = false;
643 break;
644 }
645 } else if (tf->public.type == TF_TYPE_BYPASS) {
646 ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS);
647 } else {
648 /*TF_TYPE_DISTRIBUTED_POINTS*/
649 result = false;
650 }
651
652 return result;
653 }
654 /*modify the method to handle rgb for arr_points*/
655 static bool convert_to_custom_float(
656 struct pwl_result_data *rgb_resulted,
657 struct curve_points *arr_points,
658 uint32_t hw_points_num)
659 {
660 struct custom_float_format fmt;
661
662 struct pwl_result_data *rgb = rgb_resulted;
663
664 uint32_t i = 0;
665
666 fmt.exponenta_bits = 6;
667 fmt.mantissa_bits = 12;
668 fmt.sign = false;
669
670 if (!convert_to_custom_float_format(
671 arr_points[0].x,
672 &fmt,
673 &arr_points[0].custom_float_x)) {
674 BREAK_TO_DEBUGGER();
675 return false;
676 }
677
678 if (!convert_to_custom_float_format(
679 arr_points[0].offset,
680 &fmt,
681 &arr_points[0].custom_float_offset)) {
682 BREAK_TO_DEBUGGER();
683 return false;
684 }
685
686 if (!convert_to_custom_float_format(
687 arr_points[0].slope,
688 &fmt,
689 &arr_points[0].custom_float_slope)) {
690 BREAK_TO_DEBUGGER();
691 return false;
692 }
693
694 fmt.mantissa_bits = 10;
695 fmt.sign = false;
696
697 if (!convert_to_custom_float_format(
698 arr_points[1].x,
699 &fmt,
700 &arr_points[1].custom_float_x)) {
701 BREAK_TO_DEBUGGER();
702 return false;
703 }
704
705 if (!convert_to_custom_float_format(
706 arr_points[1].y,
707 &fmt,
708 &arr_points[1].custom_float_y)) {
709 BREAK_TO_DEBUGGER();
710 return false;
711 }
712
713 if (!convert_to_custom_float_format(
714 arr_points[1].slope,
715 &fmt,
716 &arr_points[1].custom_float_slope)) {
717 BREAK_TO_DEBUGGER();
718 return false;
719 }
720
721 fmt.mantissa_bits = 12;
722 fmt.sign = true;
723
724 while (i != hw_points_num) {
725 if (!convert_to_custom_float_format(
726 rgb->red,
727 &fmt,
728 &rgb->red_reg)) {
729 BREAK_TO_DEBUGGER();
730 return false;
731 }
732
733 if (!convert_to_custom_float_format(
734 rgb->green,
735 &fmt,
736 &rgb->green_reg)) {
737 BREAK_TO_DEBUGGER();
738 return false;
739 }
740
741 if (!convert_to_custom_float_format(
742 rgb->blue,
743 &fmt,
744 &rgb->blue_reg)) {
745 BREAK_TO_DEBUGGER();
746 return false;
747 }
748
749 if (!convert_to_custom_float_format(
750 rgb->delta_red,
751 &fmt,
752 &rgb->delta_red_reg)) {
753 BREAK_TO_DEBUGGER();
754 return false;
755 }
756
757 if (!convert_to_custom_float_format(
758 rgb->delta_green,
759 &fmt,
760 &rgb->delta_green_reg)) {
761 BREAK_TO_DEBUGGER();
762 return false;
763 }
764
765 if (!convert_to_custom_float_format(
766 rgb->delta_blue,
767 &fmt,
768 &rgb->delta_blue_reg)) {
769 BREAK_TO_DEBUGGER();
770 return false;
771 }
772
773 ++rgb;
774 ++i;
775 }
776
777 return true;
778 }
779 #define MAX_REGIONS_NUMBER 34
780 #define MAX_LOW_POINT 25
781 #define NUMBER_SEGMENTS 32
782
783 static bool dcn10_translate_regamma_to_hw_format(const struct dc_transfer_func
784 *output_tf, struct pwl_params *regamma_params)
785 {
786 struct curve_points *arr_points;
787 struct pwl_result_data *rgb_resulted;
788 struct pwl_result_data *rgb;
789 struct pwl_result_data *rgb_plus_1;
790 struct fixed31_32 y_r;
791 struct fixed31_32 y_g;
792 struct fixed31_32 y_b;
793 struct fixed31_32 y1_min;
794 struct fixed31_32 y3_max;
795
796 int32_t segment_start, segment_end;
797 int32_t i;
798 uint32_t j, k, seg_distr[MAX_REGIONS_NUMBER], increment, start_index, hw_points;
799
800 if (output_tf == NULL || regamma_params == NULL ||
801 output_tf->type == TF_TYPE_BYPASS)
802 return false;
803
804 arr_points = regamma_params->arr_points;
805 rgb_resulted = regamma_params->rgb_resulted;
806 hw_points = 0;
807
808 memset(regamma_params, 0, sizeof(struct pwl_params));
809 memset(seg_distr, 0, sizeof(seg_distr));
810
811 if (output_tf->tf == TRANSFER_FUNCTION_PQ) {
812 /* 32 segments
813 * segments are from 2^-25 to 2^7
814 */
815 for (i = 0; i < 32 ; i++)
816 seg_distr[i] = 3;
817
818 segment_start = -25;
819 segment_end = 7;
820 } else {
821 /* 10 segments
822 * segment is from 2^-10 to 2^0
823 * There are less than 256 points, for optimization
824 */
825 seg_distr[0] = 3;
826 seg_distr[1] = 4;
827 seg_distr[2] = 4;
828 seg_distr[3] = 4;
829 seg_distr[4] = 4;
830 seg_distr[5] = 4;
831 seg_distr[6] = 4;
832 seg_distr[7] = 4;
833 seg_distr[8] = 5;
834 seg_distr[9] = 5;
835
836 segment_start = -10;
837 segment_end = 0;
838 }
839
840 for (i = segment_end - segment_start; i < MAX_REGIONS_NUMBER ; i++)
841 seg_distr[i] = -1;
842
843 for (k = 0; k < MAX_REGIONS_NUMBER; k++) {
844 if (seg_distr[k] != -1)
845 hw_points += (1 << seg_distr[k]);
846 }
847
848 j = 0;
849 for (k = 0; k < (segment_end - segment_start); k++) {
850 increment = NUMBER_SEGMENTS / (1 << seg_distr[k]);
851 start_index = (segment_start + k + MAX_LOW_POINT) * NUMBER_SEGMENTS;
852 for (i = start_index; i < start_index + NUMBER_SEGMENTS; i += increment) {
853 if (j == hw_points - 1)
854 break;
855 rgb_resulted[j].red = output_tf->tf_pts.red[i];
856 rgb_resulted[j].green = output_tf->tf_pts.green[i];
857 rgb_resulted[j].blue = output_tf->tf_pts.blue[i];
858 j++;
859 }
860 }
861
862 /* last point */
863 start_index = (segment_end + MAX_LOW_POINT) * NUMBER_SEGMENTS;
864 rgb_resulted[hw_points - 1].red =
865 output_tf->tf_pts.red[start_index];
866 rgb_resulted[hw_points - 1].green =
867 output_tf->tf_pts.green[start_index];
868 rgb_resulted[hw_points - 1].blue =
869 output_tf->tf_pts.blue[start_index];
870
871 arr_points[0].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2),
872 dal_fixed31_32_from_int(segment_start));
873 arr_points[1].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2),
874 dal_fixed31_32_from_int(segment_end));
875 arr_points[2].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2),
876 dal_fixed31_32_from_int(segment_end));
877
878 y_r = rgb_resulted[0].red;
879 y_g = rgb_resulted[0].green;
880 y_b = rgb_resulted[0].blue;
881
882 y1_min = dal_fixed31_32_min(y_r, dal_fixed31_32_min(y_g, y_b));
883
884 arr_points[0].y = y1_min;
885 arr_points[0].slope = dal_fixed31_32_div(
886 arr_points[0].y,
887 arr_points[0].x);
888 y_r = rgb_resulted[hw_points - 1].red;
889 y_g = rgb_resulted[hw_points - 1].green;
890 y_b = rgb_resulted[hw_points - 1].blue;
891
892 /* see comment above, m_arrPoints[1].y should be the Y value for the
893 * region end (m_numOfHwPoints), not last HW point(m_numOfHwPoints - 1)
894 */
895 y3_max = dal_fixed31_32_max(y_r, dal_fixed31_32_max(y_g, y_b));
896
897 arr_points[1].y = y3_max;
898 arr_points[2].y = y3_max;
899
900 arr_points[1].slope = dal_fixed31_32_zero;
901 arr_points[2].slope = dal_fixed31_32_zero;
902
903 if (output_tf->tf == TRANSFER_FUNCTION_PQ) {
904 /* for PQ, we want to have a straight line from last HW X point,
905 * and the slope to be such that we hit 1.0 at 10000 nits.
906 */
907 const struct fixed31_32 end_value =
908 dal_fixed31_32_from_int(125);
909
910 arr_points[1].slope = dal_fixed31_32_div(
911 dal_fixed31_32_sub(dal_fixed31_32_one, arr_points[1].y),
912 dal_fixed31_32_sub(end_value, arr_points[1].x));
913 arr_points[2].slope = dal_fixed31_32_div(
914 dal_fixed31_32_sub(dal_fixed31_32_one, arr_points[1].y),
915 dal_fixed31_32_sub(end_value, arr_points[1].x));
916 }
917
918 regamma_params->hw_points_num = hw_points;
919
920 i = 1;
921 for (k = 0; k < MAX_REGIONS_NUMBER && i < MAX_REGIONS_NUMBER; k++) {
922 if (seg_distr[k] != -1) {
923 regamma_params->arr_curve_points[k].segments_num =
924 seg_distr[k];
925 regamma_params->arr_curve_points[i].offset =
926 regamma_params->arr_curve_points[k].
927 offset + (1 << seg_distr[k]);
928 }
929 i++;
930 }
931
932 if (seg_distr[k] != -1)
933 regamma_params->arr_curve_points[k].segments_num =
934 seg_distr[k];
935
936 rgb = rgb_resulted;
937 rgb_plus_1 = rgb_resulted + 1;
938
939 i = 1;
940
941 while (i != hw_points + 1) {
942 if (dal_fixed31_32_lt(rgb_plus_1->red, rgb->red))
943 rgb_plus_1->red = rgb->red;
944 if (dal_fixed31_32_lt(rgb_plus_1->green, rgb->green))
945 rgb_plus_1->green = rgb->green;
946 if (dal_fixed31_32_lt(rgb_plus_1->blue, rgb->blue))
947 rgb_plus_1->blue = rgb->blue;
948
949 rgb->delta_red = dal_fixed31_32_sub(
950 rgb_plus_1->red,
951 rgb->red);
952 rgb->delta_green = dal_fixed31_32_sub(
953 rgb_plus_1->green,
954 rgb->green);
955 rgb->delta_blue = dal_fixed31_32_sub(
956 rgb_plus_1->blue,
957 rgb->blue);
958
959 ++rgb_plus_1;
960 ++rgb;
961 ++i;
962 }
963
964 convert_to_custom_float(rgb_resulted, arr_points, hw_points);
965
966 return true;
967 }
968
969 static bool dcn10_set_output_transfer_func(
970 struct pipe_ctx *pipe_ctx,
971 const struct core_stream *stream)
972 {
973 struct output_pixel_processor *opp = pipe_ctx->opp;
974
975 if (opp == NULL)
976 return false;
977
978 opp->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM;
979
980 if (stream->public.out_transfer_func &&
981 stream->public.out_transfer_func->type ==
982 TF_TYPE_PREDEFINED &&
983 stream->public.out_transfer_func->tf ==
984 TRANSFER_FUNCTION_SRGB) {
985 opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_SRGB);
986 } else if (dcn10_translate_regamma_to_hw_format(
987 stream->public.out_transfer_func, &opp->regamma_params)) {
988 opp->funcs->opp_program_regamma_pwl(opp, &opp->regamma_params);
989 opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_USER);
990 } else {
991 opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_BYPASS);
992 }
993
994 return true;
995 }
996
997 static void dcn10_pipe_control_lock(
998 struct core_dc *dc,
999 struct pipe_ctx *pipe,
1000 bool lock)
1001 {
1002 /* use TG master update lock to lock everything on the TG
1003 * therefore only top pipe need to lock
1004 */
1005 if (pipe->top_pipe)
1006 return;
1007
1008 if (lock)
1009 pipe->tg->funcs->lock(pipe->tg);
1010 else
1011 pipe->tg->funcs->unlock(pipe->tg);
1012 }
1013
1014 static bool wait_for_reset_trigger_to_occur(
1015 struct dc_context *dc_ctx,
1016 struct timing_generator *tg)
1017 {
1018 bool rc = false;
1019
1020 /* To avoid endless loop we wait at most
1021 * frames_to_wait_on_triggered_reset frames for the reset to occur. */
1022 const uint32_t frames_to_wait_on_triggered_reset = 10;
1023 int i;
1024
1025 for (i = 0; i < frames_to_wait_on_triggered_reset; i++) {
1026
1027 if (!tg->funcs->is_counter_moving(tg)) {
1028 DC_ERROR("TG counter is not moving!\n");
1029 break;
1030 }
1031
1032 if (tg->funcs->did_triggered_reset_occur(tg)) {
1033 rc = true;
1034 /* usually occurs at i=1 */
1035 DC_SYNC_INFO("GSL: reset occurred at wait count: %d\n",
1036 i);
1037 break;
1038 }
1039
1040 /* Wait for one frame. */
1041 tg->funcs->wait_for_state(tg, CRTC_STATE_VACTIVE);
1042 tg->funcs->wait_for_state(tg, CRTC_STATE_VBLANK);
1043 }
1044
1045 if (false == rc)
1046 DC_ERROR("GSL: Timeout on reset trigger!\n");
1047
1048 return rc;
1049 }
1050
1051 static void dcn10_enable_timing_synchronization(
1052 struct core_dc *dc,
1053 int group_index,
1054 int group_size,
1055 struct pipe_ctx *grouped_pipes[])
1056 {
1057 struct dc_context *dc_ctx = dc->ctx;
1058 int i;
1059
1060 DC_SYNC_INFO("Setting up OTG reset trigger\n");
1061
1062 for (i = 1; i < group_size; i++)
1063 grouped_pipes[i]->tg->funcs->enable_reset_trigger(
1064 grouped_pipes[i]->tg, grouped_pipes[0]->tg->inst);
1065
1066
1067 DC_SYNC_INFO("Waiting for trigger\n");
1068
1069 /* Need to get only check 1 pipe for having reset as all the others are
1070 * synchronized. Look at last pipe programmed to reset.
1071 */
1072 wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[1]->tg);
1073 for (i = 1; i < group_size; i++)
1074 grouped_pipes[i]->tg->funcs->disable_reset_trigger(
1075 grouped_pipes[i]->tg);
1076
1077 DC_SYNC_INFO("Sync complete\n");
1078 }
1079
1080 static void print_rq_dlg_ttu(
1081 struct core_dc *core_dc,
1082 struct pipe_ctx *pipe_ctx)
1083 {
1084 dm_logger_write(core_dc->ctx->logger, LOG_BANDWIDTH_CALCS,
1085 "\n============== DML TTU Output parameters [%d] ==============\n"
1086 "qos_level_low_wm: %d, \n"
1087 "qos_level_high_wm: %d, \n"
1088 "min_ttu_vblank: %d, \n"
1089 "qos_level_flip: %d, \n"
1090 "refcyc_per_req_delivery_l: %d, \n"
1091 "qos_level_fixed_l: %d, \n"
1092 "qos_ramp_disable_l: %d, \n"
1093 "refcyc_per_req_delivery_pre_l: %d, \n"
1094 "refcyc_per_req_delivery_c: %d, \n"
1095 "qos_level_fixed_c: %d, \n"
1096 "qos_ramp_disable_c: %d, \n"
1097 "refcyc_per_req_delivery_pre_c: %d\n"
1098 "=============================================================\n",
1099 pipe_ctx->pipe_idx,
1100 pipe_ctx->ttu_regs.qos_level_low_wm,
1101 pipe_ctx->ttu_regs.qos_level_high_wm,
1102 pipe_ctx->ttu_regs.min_ttu_vblank,
1103 pipe_ctx->ttu_regs.qos_level_flip,
1104 pipe_ctx->ttu_regs.refcyc_per_req_delivery_l,
1105 pipe_ctx->ttu_regs.qos_level_fixed_l,
1106 pipe_ctx->ttu_regs.qos_ramp_disable_l,
1107 pipe_ctx->ttu_regs.refcyc_per_req_delivery_pre_l,
1108 pipe_ctx->ttu_regs.refcyc_per_req_delivery_c,
1109 pipe_ctx->ttu_regs.qos_level_fixed_c,
1110 pipe_ctx->ttu_regs.qos_ramp_disable_c,
1111 pipe_ctx->ttu_regs.refcyc_per_req_delivery_pre_c
1112 );
1113
1114 dm_logger_write(core_dc->ctx->logger, LOG_BANDWIDTH_CALCS,
1115 "\n============== DML DLG Output parameters [%d] ==============\n"
1116 "refcyc_h_blank_end: %d, \n"
1117 "dlg_vblank_end: %d, \n"
1118 "min_dst_y_next_start: %d, \n"
1119 "refcyc_per_htotal: %d, \n"
1120 "refcyc_x_after_scaler: %d, \n"
1121 "dst_y_after_scaler: %d, \n"
1122 "dst_y_prefetch: %d, \n"
1123 "dst_y_per_vm_vblank: %d, \n"
1124 "dst_y_per_row_vblank: %d, \n"
1125 "ref_freq_to_pix_freq: %d, \n"
1126 "vratio_prefetch: %d, \n"
1127 "refcyc_per_pte_group_vblank_l: %d, \n"
1128 "refcyc_per_meta_chunk_vblank_l: %d, \n"
1129 "dst_y_per_pte_row_nom_l: %d, \n"
1130 "refcyc_per_pte_group_nom_l: %d, \n",
1131 pipe_ctx->pipe_idx,
1132 pipe_ctx->dlg_regs.refcyc_h_blank_end,
1133 pipe_ctx->dlg_regs.dlg_vblank_end,
1134 pipe_ctx->dlg_regs.min_dst_y_next_start,
1135 pipe_ctx->dlg_regs.refcyc_per_htotal,
1136 pipe_ctx->dlg_regs.refcyc_x_after_scaler,
1137 pipe_ctx->dlg_regs.dst_y_after_scaler,
1138 pipe_ctx->dlg_regs.dst_y_prefetch,
1139 pipe_ctx->dlg_regs.dst_y_per_vm_vblank,
1140 pipe_ctx->dlg_regs.dst_y_per_row_vblank,
1141 pipe_ctx->dlg_regs.ref_freq_to_pix_freq,
1142 pipe_ctx->dlg_regs.vratio_prefetch,
1143 pipe_ctx->dlg_regs.refcyc_per_pte_group_vblank_l,
1144 pipe_ctx->dlg_regs.refcyc_per_meta_chunk_vblank_l,
1145 pipe_ctx->dlg_regs.dst_y_per_pte_row_nom_l,
1146 pipe_ctx->dlg_regs.refcyc_per_pte_group_nom_l
1147 );
1148
1149 dm_logger_write(core_dc->ctx->logger, LOG_BANDWIDTH_CALCS,
1150 "\ndst_y_per_meta_row_nom_l: %d, \n"
1151 "refcyc_per_meta_chunk_nom_l: %d, \n"
1152 "refcyc_per_line_delivery_pre_l: %d, \n"
1153 "refcyc_per_line_delivery_l: %d, \n"
1154 "vratio_prefetch_c: %d, \n"
1155 "refcyc_per_pte_group_vblank_c: %d, \n"
1156 "refcyc_per_meta_chunk_vblank_c: %d, \n"
1157 "dst_y_per_pte_row_nom_c: %d, \n"
1158 "refcyc_per_pte_group_nom_c: %d, \n"
1159 "dst_y_per_meta_row_nom_c: %d, \n"
1160 "refcyc_per_meta_chunk_nom_c: %d, \n"
1161 "refcyc_per_line_delivery_pre_c: %d, \n"
1162 "refcyc_per_line_delivery_c: %d \n"
1163 "========================================================\n",
1164 pipe_ctx->dlg_regs.dst_y_per_meta_row_nom_l,
1165 pipe_ctx->dlg_regs.refcyc_per_meta_chunk_nom_l,
1166 pipe_ctx->dlg_regs.refcyc_per_line_delivery_pre_l,
1167 pipe_ctx->dlg_regs.refcyc_per_line_delivery_l,
1168 pipe_ctx->dlg_regs.vratio_prefetch_c,
1169 pipe_ctx->dlg_regs.refcyc_per_pte_group_vblank_c,
1170 pipe_ctx->dlg_regs.refcyc_per_meta_chunk_vblank_c,
1171 pipe_ctx->dlg_regs.dst_y_per_pte_row_nom_c,
1172 pipe_ctx->dlg_regs.refcyc_per_pte_group_nom_c,
1173 pipe_ctx->dlg_regs.dst_y_per_meta_row_nom_c,
1174 pipe_ctx->dlg_regs.refcyc_per_meta_chunk_nom_c,
1175 pipe_ctx->dlg_regs.refcyc_per_line_delivery_pre_c,
1176 pipe_ctx->dlg_regs.refcyc_per_line_delivery_c
1177 );
1178
1179 dm_logger_write(core_dc->ctx->logger, LOG_BANDWIDTH_CALCS,
1180 "\n============== DML RQ Output parameters [%d] ==============\n"
1181 "chunk_size: %d \n"
1182 "min_chunk_size: %d \n"
1183 "meta_chunk_size: %d \n"
1184 "min_meta_chunk_size: %d \n"
1185 "dpte_group_size: %d \n"
1186 "mpte_group_size: %d \n"
1187 "swath_height: %d \n"
1188 "pte_row_height_linear: %d \n"
1189 "========================================================\n",
1190 pipe_ctx->pipe_idx,
1191 pipe_ctx->rq_regs.rq_regs_l.chunk_size,
1192 pipe_ctx->rq_regs.rq_regs_l.min_chunk_size,
1193 pipe_ctx->rq_regs.rq_regs_l.meta_chunk_size,
1194 pipe_ctx->rq_regs.rq_regs_l.min_meta_chunk_size,
1195 pipe_ctx->rq_regs.rq_regs_l.dpte_group_size,
1196 pipe_ctx->rq_regs.rq_regs_l.mpte_group_size,
1197 pipe_ctx->rq_regs.rq_regs_l.swath_height,
1198 pipe_ctx->rq_regs.rq_regs_l.pte_row_height_linear
1199 );
1200 }
1201
1202 static void dcn10_power_on_fe(
1203 struct core_dc *dc,
1204 struct pipe_ctx *pipe_ctx,
1205 struct validate_context *context)
1206 {
1207 struct dc_surface *dc_surface = &pipe_ctx->surface->public;
1208 struct dce_hwseq *hws = dc->hwseq;
1209
1210 power_on_plane(dc->hwseq,
1211 pipe_ctx->pipe_idx);
1212
1213 /* enable DCFCLK current DCHUB */
1214 REG_UPDATE(HUBP_CLK_CNTL[pipe_ctx->pipe_idx], HUBP_CLOCK_ENABLE, 1);
1215
1216 if (dc_surface) {
1217 dm_logger_write(dc->ctx->logger, LOG_DC,
1218 "Pipe:%d 0x%x: addr hi:0x%x, "
1219 "addr low:0x%x, "
1220 "src: %d, %d, %d,"
1221 " %d; dst: %d, %d, %d, %d;\n",
1222 pipe_ctx->pipe_idx,
1223 dc_surface,
1224 dc_surface->address.grph.addr.high_part,
1225 dc_surface->address.grph.addr.low_part,
1226 dc_surface->src_rect.x,
1227 dc_surface->src_rect.y,
1228 dc_surface->src_rect.width,
1229 dc_surface->src_rect.height,
1230 dc_surface->dst_rect.x,
1231 dc_surface->dst_rect.y,
1232 dc_surface->dst_rect.width,
1233 dc_surface->dst_rect.height);
1234
1235 dm_logger_write(dc->ctx->logger, LOG_HW_SET_MODE,
1236 "Pipe %d: width, height, x, y\n"
1237 "viewport:%d, %d, %d, %d\n"
1238 "recout: %d, %d, %d, %d\n",
1239 pipe_ctx->pipe_idx,
1240 pipe_ctx->scl_data.viewport.width,
1241 pipe_ctx->scl_data.viewport.height,
1242 pipe_ctx->scl_data.viewport.x,
1243 pipe_ctx->scl_data.viewport.y,
1244 pipe_ctx->scl_data.recout.width,
1245 pipe_ctx->scl_data.recout.height,
1246 pipe_ctx->scl_data.recout.x,
1247 pipe_ctx->scl_data.recout.y);
1248 print_rq_dlg_ttu(dc, pipe_ctx);
1249 }
1250 }
1251
1252 static void program_gamut_remap(struct pipe_ctx *pipe_ctx)
1253 {
1254 struct xfm_grph_csc_adjustment adjust;
1255 memset(&adjust, 0, sizeof(adjust));
1256 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS;
1257
1258
1259 if (pipe_ctx->stream->public.gamut_remap_matrix.enable_remap == true) {
1260 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW;
1261 adjust.temperature_matrix[0] =
1262 pipe_ctx->stream->
1263 public.gamut_remap_matrix.matrix[0];
1264 adjust.temperature_matrix[1] =
1265 pipe_ctx->stream->
1266 public.gamut_remap_matrix.matrix[1];
1267 adjust.temperature_matrix[2] =
1268 pipe_ctx->stream->
1269 public.gamut_remap_matrix.matrix[2];
1270 adjust.temperature_matrix[3] =
1271 pipe_ctx->stream->
1272 public.gamut_remap_matrix.matrix[4];
1273 adjust.temperature_matrix[4] =
1274 pipe_ctx->stream->
1275 public.gamut_remap_matrix.matrix[5];
1276 adjust.temperature_matrix[5] =
1277 pipe_ctx->stream->
1278 public.gamut_remap_matrix.matrix[6];
1279 adjust.temperature_matrix[6] =
1280 pipe_ctx->stream->
1281 public.gamut_remap_matrix.matrix[8];
1282 adjust.temperature_matrix[7] =
1283 pipe_ctx->stream->
1284 public.gamut_remap_matrix.matrix[9];
1285 adjust.temperature_matrix[8] =
1286 pipe_ctx->stream->
1287 public.gamut_remap_matrix.matrix[10];
1288 }
1289
1290 pipe_ctx->xfm->funcs->transform_set_gamut_remap(pipe_ctx->xfm, &adjust);
1291 }
1292
1293
1294 static void program_csc_matrix(struct pipe_ctx *pipe_ctx,
1295 enum dc_color_space colorspace,
1296 uint16_t *matrix)
1297 {
1298 int i;
1299 struct out_csc_color_matrix tbl_entry;
1300
1301 if (pipe_ctx->stream->public.csc_color_matrix.enable_adjustment
1302 == true) {
1303 enum dc_color_space color_space =
1304 pipe_ctx->stream->public.output_color_space;
1305
1306 //uint16_t matrix[12];
1307 for (i = 0; i < 12; i++)
1308 tbl_entry.regval[i] = pipe_ctx->stream->public.csc_color_matrix.matrix[i];
1309
1310 tbl_entry.color_space = color_space;
1311 //tbl_entry.regval = matrix;
1312 pipe_ctx->opp->funcs->opp_set_csc_adjustment(pipe_ctx->opp, &tbl_entry);
1313 }
1314 }
1315 static bool is_lower_pipe_tree_visible(struct pipe_ctx *pipe_ctx)
1316 {
1317 if (pipe_ctx->surface->public.visible)
1318 return true;
1319 if (pipe_ctx->bottom_pipe && is_lower_pipe_tree_visible(pipe_ctx->bottom_pipe))
1320 return true;
1321 return false;
1322 }
1323
1324 static bool is_upper_pipe_tree_visible(struct pipe_ctx *pipe_ctx)
1325 {
1326 if (pipe_ctx->surface->public.visible)
1327 return true;
1328 if (pipe_ctx->top_pipe && is_upper_pipe_tree_visible(pipe_ctx->top_pipe))
1329 return true;
1330 return false;
1331 }
1332
1333 static bool is_pipe_tree_visible(struct pipe_ctx *pipe_ctx)
1334 {
1335 if (pipe_ctx->surface->public.visible)
1336 return true;
1337 if (pipe_ctx->top_pipe && is_upper_pipe_tree_visible(pipe_ctx->top_pipe))
1338 return true;
1339 if (pipe_ctx->bottom_pipe && is_lower_pipe_tree_visible(pipe_ctx->bottom_pipe))
1340 return true;
1341 return false;
1342 }
1343
1344 static bool is_rgb_cspace(enum dc_color_space output_color_space)
1345 {
1346 switch (output_color_space) {
1347 case COLOR_SPACE_SRGB:
1348 case COLOR_SPACE_SRGB_LIMITED:
1349 case COLOR_SPACE_2020_RGB_FULLRANGE:
1350 case COLOR_SPACE_2020_RGB_LIMITEDRANGE:
1351 case COLOR_SPACE_ADOBERGB:
1352 return true;
1353 case COLOR_SPACE_YCBCR601:
1354 case COLOR_SPACE_YCBCR709:
1355 case COLOR_SPACE_YCBCR601_LIMITED:
1356 case COLOR_SPACE_YCBCR709_LIMITED:
1357 case COLOR_SPACE_2020_YCBCR:
1358 return false;
1359 default:
1360 /* Add a case to switch */
1361 BREAK_TO_DEBUGGER();
1362 return false;
1363 }
1364 }
1365
1366 static void dcn10_get_surface_visual_confirm_color(
1367 const struct pipe_ctx *pipe_ctx,
1368 struct tg_color *color)
1369 {
1370 uint32_t color_value = MAX_TG_COLOR_VALUE;
1371
1372 switch (pipe_ctx->scl_data.format) {
1373 case PIXEL_FORMAT_ARGB8888:
1374 /* set boarder color to red */
1375 color->color_r_cr = color_value;
1376 break;
1377
1378 case PIXEL_FORMAT_ARGB2101010:
1379 /* set boarder color to blue */
1380 color->color_b_cb = color_value;
1381 break;
1382 case PIXEL_FORMAT_420BPP8:
1383 /* set boarder color to green */
1384 color->color_g_y = color_value;
1385 break;
1386 case PIXEL_FORMAT_420BPP10:
1387 /* set boarder color to yellow */
1388 color->color_g_y = color_value;
1389 color->color_r_cr = color_value;
1390 break;
1391 case PIXEL_FORMAT_FP16:
1392 /* set boarder color to white */
1393 color->color_r_cr = color_value;
1394 color->color_b_cb = color_value;
1395 color->color_g_y = color_value;
1396 break;
1397 default:
1398 break;
1399 }
1400 }
1401
1402 static void update_dchubp_dpp(
1403 struct core_dc *dc,
1404 struct pipe_ctx *pipe_ctx,
1405 struct validate_context *context)
1406 {
1407 struct dce_hwseq *hws = dc->hwseq;
1408 struct mem_input *mi = pipe_ctx->mi;
1409 struct input_pixel_processor *ipp = pipe_ctx->ipp;
1410 struct core_surface *surface = pipe_ctx->surface;
1411 union plane_size size = surface->public.plane_size;
1412 struct default_adjustment ocsc = {0};
1413 struct tg_color black_color = {0};
1414 struct mpcc_cfg mpcc_cfg;
1415 bool per_pixel_alpha = surface->public.per_pixel_alpha && pipe_ctx->bottom_pipe;
1416
1417 /* TODO: proper fix once fpga works */
1418 /* depends on DML calculation, DPP clock value may change dynamically */
1419 enable_dppclk(
1420 dc->hwseq,
1421 pipe_ctx->pipe_idx,
1422 pipe_ctx->pix_clk_params.requested_pix_clk,
1423 context->bw.dcn.calc_clk.dppclk_div);
1424 dc->current_context->bw.dcn.cur_clk.dppclk_div =
1425 context->bw.dcn.calc_clk.dppclk_div;
1426 context->bw.dcn.cur_clk.dppclk_div = context->bw.dcn.calc_clk.dppclk_div;
1427
1428 /* TODO: Need input parameter to tell current DCHUB pipe tie to which OTG
1429 * VTG is within DCHUBBUB which is commond block share by each pipe HUBP.
1430 * VTG is 1:1 mapping with OTG. Each pipe HUBP will select which VTG
1431 */
1432 REG_UPDATE(DCHUBP_CNTL[pipe_ctx->pipe_idx], HUBP_VTG_SEL, pipe_ctx->tg->inst);
1433
1434 update_plane_addr(dc, pipe_ctx);
1435
1436 mi->funcs->mem_input_setup(
1437 mi,
1438 &pipe_ctx->dlg_regs,
1439 &pipe_ctx->ttu_regs,
1440 &pipe_ctx->rq_regs,
1441 &pipe_ctx->pipe_dlg_param);
1442
1443 size.grph.surface_size = pipe_ctx->scl_data.viewport;
1444
1445 if (dc->public.config.gpu_vm_support)
1446 mi->funcs->mem_input_program_pte_vm(
1447 pipe_ctx->mi,
1448 surface->public.format,
1449 &surface->public.tiling_info,
1450 surface->public.rotation);
1451
1452 ipp->funcs->ipp_setup(ipp,
1453 surface->public.format,
1454 1,
1455 IPP_OUTPUT_FORMAT_12_BIT_FIX);
1456
1457 pipe_ctx->scl_data.lb_params.alpha_en = per_pixel_alpha;
1458 mpcc_cfg.top_dpp_id = pipe_ctx->pipe_idx;
1459 if (pipe_ctx->bottom_pipe)
1460 mpcc_cfg.bot_mpcc_id = pipe_ctx->bottom_pipe->mpcc->inst;
1461 else
1462 mpcc_cfg.bot_mpcc_id = 0xf;
1463 mpcc_cfg.opp_id = pipe_ctx->tg->inst;
1464 mpcc_cfg.top_of_tree = pipe_ctx->pipe_idx == pipe_ctx->tg->inst;
1465 mpcc_cfg.per_pixel_alpha = per_pixel_alpha;
1466 /* DCN1.0 has output CM before MPC which seems to screw with
1467 * pre-multiplied alpha.
1468 */
1469 mpcc_cfg.pre_multiplied_alpha = is_rgb_cspace(
1470 pipe_ctx->stream->public.output_color_space)
1471 && per_pixel_alpha;
1472 pipe_ctx->mpcc->funcs->set(pipe_ctx->mpcc, &mpcc_cfg);
1473
1474 if (dc->public.debug.surface_visual_confirm) {
1475 dcn10_get_surface_visual_confirm_color(pipe_ctx, &black_color);
1476 } else {
1477 color_space_to_black_color(
1478 dc, pipe_ctx->stream->public.output_color_space,
1479 &black_color);
1480 }
1481 pipe_ctx->mpcc->funcs->set_bg_color(pipe_ctx->mpcc, &black_color);
1482
1483 pipe_ctx->scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP;
1484 /* scaler configuration */
1485 pipe_ctx->xfm->funcs->transform_set_scaler(
1486 pipe_ctx->xfm, &pipe_ctx->scl_data);
1487
1488 /*gamut remap*/
1489 program_gamut_remap(pipe_ctx);
1490
1491 /*TODO add adjustments parameters*/
1492 ocsc.out_color_space = pipe_ctx->stream->public.output_color_space;
1493 pipe_ctx->opp->funcs->opp_set_csc_default(pipe_ctx->opp, &ocsc);
1494
1495 mi->funcs->mem_input_program_surface_config(
1496 mi,
1497 surface->public.format,
1498 &surface->public.tiling_info,
1499 &size,
1500 surface->public.rotation,
1501 &surface->public.dcc,
1502 surface->public.horizontal_mirror);
1503
1504 mi->funcs->set_blank(mi, !is_pipe_tree_visible(pipe_ctx));
1505 }
1506
1507 static void program_all_pipe_in_tree(
1508 struct core_dc *dc,
1509 struct pipe_ctx *pipe_ctx,
1510 struct validate_context *context)
1511 {
1512 unsigned int ref_clk_mhz = dc->res_pool->ref_clock_inKhz/1000;
1513
1514 if (pipe_ctx->top_pipe == NULL) {
1515
1516 /* lock otg_master_update to process all pipes associated with
1517 * this OTG. this is done only one time.
1518 */
1519 /* watermark is for all pipes */
1520 pipe_ctx->mi->funcs->program_watermarks(
1521 pipe_ctx->mi, &context->bw.dcn.watermarks, ref_clk_mhz);
1522 pipe_ctx->tg->funcs->lock(pipe_ctx->tg);
1523
1524 pipe_ctx->tg->dlg_otg_param.vready_offset = pipe_ctx->pipe_dlg_param.vready_offset;
1525 pipe_ctx->tg->dlg_otg_param.vstartup_start = pipe_ctx->pipe_dlg_param.vstartup_start;
1526 pipe_ctx->tg->dlg_otg_param.vupdate_offset = pipe_ctx->pipe_dlg_param.vupdate_offset;
1527 pipe_ctx->tg->dlg_otg_param.vupdate_width = pipe_ctx->pipe_dlg_param.vupdate_width;
1528 pipe_ctx->tg->dlg_otg_param.signal = pipe_ctx->stream->signal;
1529
1530 pipe_ctx->tg->funcs->program_global_sync(
1531 pipe_ctx->tg);
1532 pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, !is_pipe_tree_visible(pipe_ctx));
1533 }
1534
1535 if (pipe_ctx->surface != NULL) {
1536 dcn10_power_on_fe(dc, pipe_ctx, context);
1537 update_dchubp_dpp(dc, pipe_ctx, context);
1538 }
1539
1540 if (pipe_ctx->bottom_pipe != NULL)
1541 program_all_pipe_in_tree(dc, pipe_ctx->bottom_pipe, context);
1542 }
1543
1544 static void dcn10_pplib_apply_display_requirements(
1545 struct core_dc *dc,
1546 struct validate_context *context)
1547 {
1548 struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg;
1549
1550 pp_display_cfg->all_displays_in_sync = false;/*todo*/
1551 pp_display_cfg->nb_pstate_switch_disable = false;
1552 pp_display_cfg->min_engine_clock_khz = context->bw.dcn.cur_clk.dcfclk_khz;
1553 pp_display_cfg->min_memory_clock_khz = context->bw.dcn.cur_clk.fclk_khz;
1554 pp_display_cfg->min_engine_clock_deep_sleep_khz = context->bw.dcn.cur_clk.dcfclk_deep_sleep_khz;
1555 pp_display_cfg->min_dcfc_deep_sleep_clock_khz = context->bw.dcn.cur_clk.dcfclk_deep_sleep_khz;
1556 pp_display_cfg->avail_mclk_switch_time_us =
1557 context->bw.dcn.cur_clk.dram_ccm_us > 0 ? context->bw.dcn.cur_clk.dram_ccm_us : 0;
1558 pp_display_cfg->avail_mclk_switch_time_in_disp_active_us =
1559 context->bw.dcn.cur_clk.min_active_dram_ccm_us > 0 ? context->bw.dcn.cur_clk.min_active_dram_ccm_us : 0;
1560 pp_display_cfg->min_dcfclock_khz = context->bw.dcn.cur_clk.dcfclk_khz;
1561 pp_display_cfg->disp_clk_khz = context->bw.dcn.cur_clk.dispclk_khz;
1562 dce110_fill_display_configs(context, pp_display_cfg);
1563
1564 if (memcmp(&dc->prev_display_config, pp_display_cfg, sizeof(
1565 struct dm_pp_display_configuration)) != 0)
1566 dm_pp_apply_display_requirements(dc->ctx, pp_display_cfg);
1567
1568 dc->prev_display_config = *pp_display_cfg;
1569 }
1570
1571 static void dcn10_apply_ctx_for_surface(
1572 struct core_dc *dc,
1573 struct core_surface *surface,
1574 struct validate_context *context)
1575 {
1576 int i;
1577
1578 /* reset unused mpcc */
1579 /*for (i = 0; i < dc->res_pool->pipe_count; i++) {
1580 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1581 struct pipe_ctx *old_pipe_ctx =
1582 &dc->current_context->res_ctx.pipe_ctx[i];
1583
1584 if ((!pipe_ctx->surface && old_pipe_ctx->surface)
1585 || (!pipe_ctx->stream && old_pipe_ctx->stream)) {
1586 struct mpcc_cfg mpcc_cfg;
1587
1588 mpcc_cfg.opp_id = 0xf;
1589 mpcc_cfg.top_dpp_id = 0xf;
1590 mpcc_cfg.bot_mpcc_id = 0xf;
1591 mpcc_cfg.top_of_tree = !old_pipe_ctx->top_pipe;
1592 old_pipe_ctx->mpcc->funcs->set(old_pipe_ctx->mpcc, &mpcc_cfg);
1593
1594 old_pipe_ctx->top_pipe = NULL;
1595 old_pipe_ctx->bottom_pipe = NULL;
1596 old_pipe_ctx->surface = NULL;
1597
1598 dm_logger_write(dc->ctx->logger, LOG_DC,
1599 "Reset mpcc for pipe %d\n",
1600 old_pipe_ctx->pipe_idx);
1601 }
1602 }*/
1603
1604 if (!surface)
1605 return;
1606
1607 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1608 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1609
1610 if (pipe_ctx->surface != surface)
1611 continue;
1612
1613 /* looking for top pipe to program */
1614 if (!pipe_ctx->top_pipe)
1615 program_all_pipe_in_tree(dc, pipe_ctx, context);
1616 }
1617
1618 dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_CALCS,
1619 "\n============== Watermark parameters ==============\n"
1620 "a.urgent_ns: %d \n"
1621 "a.cstate_enter_plus_exit: %d \n"
1622 "a.cstate_exit: %d \n"
1623 "a.pstate_change: %d \n"
1624 "a.pte_meta_urgent: %d \n"
1625 "b.urgent_ns: %d \n"
1626 "b.cstate_enter_plus_exit: %d \n"
1627 "b.cstate_exit: %d \n"
1628 "b.pstate_change: %d \n"
1629 "b.pte_meta_urgent: %d \n",
1630 context->bw.dcn.watermarks.a.urgent_ns,
1631 context->bw.dcn.watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns,
1632 context->bw.dcn.watermarks.a.cstate_pstate.cstate_exit_ns,
1633 context->bw.dcn.watermarks.a.cstate_pstate.pstate_change_ns,
1634 context->bw.dcn.watermarks.a.pte_meta_urgent_ns,
1635 context->bw.dcn.watermarks.b.urgent_ns,
1636 context->bw.dcn.watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns,
1637 context->bw.dcn.watermarks.b.cstate_pstate.cstate_exit_ns,
1638 context->bw.dcn.watermarks.b.cstate_pstate.pstate_change_ns,
1639 context->bw.dcn.watermarks.b.pte_meta_urgent_ns
1640 );
1641 dm_logger_write(dc->ctx->logger, LOG_BANDWIDTH_CALCS,
1642 "\nc.urgent_ns: %d \n"
1643 "c.cstate_enter_plus_exit: %d \n"
1644 "c.cstate_exit: %d \n"
1645 "c.pstate_change: %d \n"
1646 "c.pte_meta_urgent: %d \n"
1647 "d.urgent_ns: %d \n"
1648 "d.cstate_enter_plus_exit: %d \n"
1649 "d.cstate_exit: %d \n"
1650 "d.pstate_change: %d \n"
1651 "d.pte_meta_urgent: %d \n"
1652 "========================================================\n",
1653 context->bw.dcn.watermarks.c.urgent_ns,
1654 context->bw.dcn.watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns,
1655 context->bw.dcn.watermarks.c.cstate_pstate.cstate_exit_ns,
1656 context->bw.dcn.watermarks.c.cstate_pstate.pstate_change_ns,
1657 context->bw.dcn.watermarks.c.pte_meta_urgent_ns,
1658 context->bw.dcn.watermarks.d.urgent_ns,
1659 context->bw.dcn.watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns,
1660 context->bw.dcn.watermarks.d.cstate_pstate.cstate_exit_ns,
1661 context->bw.dcn.watermarks.d.cstate_pstate.pstate_change_ns,
1662 context->bw.dcn.watermarks.d.pte_meta_urgent_ns
1663 );
1664 }
1665
1666 static void dcn10_set_bandwidth(
1667 struct core_dc *dc,
1668 struct validate_context *context,
1669 bool decrease_allowed)
1670 {
1671 struct dm_pp_clock_for_voltage_req clock;
1672
1673 if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment))
1674 return;
1675
1676 if (decrease_allowed || context->bw.dcn.calc_clk.dispclk_khz
1677 > dc->current_context->bw.dcn.cur_clk.dispclk_khz) {
1678 dc->res_pool->display_clock->funcs->set_clock(
1679 dc->res_pool->display_clock,
1680 context->bw.dcn.calc_clk.dispclk_khz);
1681 dc->current_context->bw.dcn.cur_clk.dispclk_khz =
1682 context->bw.dcn.calc_clk.dispclk_khz;
1683 }
1684 if (decrease_allowed || context->bw.dcn.calc_clk.dcfclk_khz
1685 > dc->current_context->bw.dcn.cur_clk.dcfclk_khz) {
1686 clock.clk_type = DM_PP_CLOCK_TYPE_DCFCLK;
1687 clock.clocks_in_khz = context->bw.dcn.calc_clk.dcfclk_khz;
1688 dm_pp_apply_clock_for_voltage_request(dc->ctx, &clock);
1689 dc->current_context->bw.dcn.cur_clk.dcfclk_khz = clock.clocks_in_khz;
1690 context->bw.dcn.cur_clk.dcfclk_khz = clock.clocks_in_khz;
1691 }
1692 if (decrease_allowed || context->bw.dcn.calc_clk.fclk_khz
1693 > dc->current_context->bw.dcn.cur_clk.fclk_khz) {
1694 clock.clk_type = DM_PP_CLOCK_TYPE_FCLK;
1695 clock.clocks_in_khz = context->bw.dcn.calc_clk.fclk_khz;
1696 dm_pp_apply_clock_for_voltage_request(dc->ctx, &clock);
1697 dc->current_context->bw.dcn.calc_clk.fclk_khz = clock.clocks_in_khz;
1698 context->bw.dcn.cur_clk.fclk_khz = clock.clocks_in_khz;
1699 }
1700 if (decrease_allowed || context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz
1701 > dc->current_context->bw.dcn.cur_clk.dcfclk_deep_sleep_khz) {
1702 dc->current_context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz =
1703 context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz;
1704 context->bw.dcn.cur_clk.dcfclk_deep_sleep_khz =
1705 context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz;
1706 }
1707 /* Decrease in freq is increase in period so opposite comparison for dram_ccm */
1708 if (decrease_allowed || context->bw.dcn.calc_clk.dram_ccm_us
1709 < dc->current_context->bw.dcn.cur_clk.dram_ccm_us) {
1710 dc->current_context->bw.dcn.calc_clk.dram_ccm_us =
1711 context->bw.dcn.calc_clk.dram_ccm_us;
1712 context->bw.dcn.cur_clk.dram_ccm_us =
1713 context->bw.dcn.calc_clk.dram_ccm_us;
1714 }
1715 if (decrease_allowed || context->bw.dcn.calc_clk.min_active_dram_ccm_us
1716 < dc->current_context->bw.dcn.cur_clk.min_active_dram_ccm_us) {
1717 dc->current_context->bw.dcn.calc_clk.min_active_dram_ccm_us =
1718 context->bw.dcn.calc_clk.min_active_dram_ccm_us;
1719 context->bw.dcn.cur_clk.min_active_dram_ccm_us =
1720 context->bw.dcn.calc_clk.min_active_dram_ccm_us;
1721 }
1722 dcn10_pplib_apply_display_requirements(dc, context);
1723 }
1724
1725 static void set_drr(struct pipe_ctx **pipe_ctx,
1726 int num_pipes, int vmin, int vmax)
1727 {
1728 int i = 0;
1729 struct drr_params params = {0};
1730
1731 params.vertical_total_max = vmax;
1732 params.vertical_total_min = vmin;
1733
1734 /* TODO: If multiple pipes are to be supported, you need
1735 * some GSL stuff
1736 */
1737 for (i = 0; i < num_pipes; i++) {
1738 pipe_ctx[i]->tg->funcs->set_drr(pipe_ctx[i]->tg, &params);
1739 }
1740 }
1741
1742 static void get_position(struct pipe_ctx **pipe_ctx,
1743 int num_pipes,
1744 struct crtc_position *position)
1745 {
1746 int i = 0;
1747
1748 /* TODO: handle pipes > 1
1749 */
1750 for (i = 0; i < num_pipes; i++)
1751 pipe_ctx[i]->tg->funcs->get_position(pipe_ctx[i]->tg, position);
1752 }
1753
1754 static void set_static_screen_control(struct pipe_ctx **pipe_ctx,
1755 int num_pipes, const struct dc_static_screen_events *events)
1756 {
1757 unsigned int i;
1758 unsigned int value = 0;
1759
1760 if (events->surface_update)
1761 value |= 0x80;
1762 if (events->cursor_update)
1763 value |= 0x2;
1764
1765 for (i = 0; i < num_pipes; i++)
1766 pipe_ctx[i]->tg->funcs->
1767 set_static_screen_control(pipe_ctx[i]->tg, value);
1768 }
1769
1770 static void set_plane_config(
1771 const struct core_dc *dc,
1772 struct pipe_ctx *pipe_ctx,
1773 struct resource_context *res_ctx)
1774 {
1775 /* TODO */
1776 program_gamut_remap(pipe_ctx);
1777 }
1778
1779 static void dcn10_config_stereo_parameters(
1780 struct core_stream *stream, struct crtc_stereo_flags *flags)
1781 {
1782 enum view_3d_format view_format = stream->public.view_format;
1783 enum dc_timing_3d_format timing_3d_format =\
1784 stream->public.timing.timing_3d_format;
1785 bool non_stereo_timing = false;
1786
1787 if (timing_3d_format == TIMING_3D_FORMAT_NONE ||
1788 timing_3d_format == TIMING_3D_FORMAT_SIDE_BY_SIDE ||
1789 timing_3d_format == TIMING_3D_FORMAT_TOP_AND_BOTTOM)
1790 non_stereo_timing = true;
1791
1792 if (non_stereo_timing == false &&
1793 view_format == VIEW_3D_FORMAT_FRAME_SEQUENTIAL) {
1794
1795 flags->PROGRAM_STEREO = 1;
1796 flags->PROGRAM_POLARITY = 1;
1797 if (timing_3d_format == TIMING_3D_FORMAT_INBAND_FA ||
1798 timing_3d_format == TIMING_3D_FORMAT_DP_HDMI_INBAND_FA ||
1799 timing_3d_format == TIMING_3D_FORMAT_SIDEBAND_FA) {
1800 enum display_dongle_type dongle = \
1801 stream->sink->link->public.ddc->dongle_type;
1802 if (dongle == DISPLAY_DONGLE_DP_VGA_CONVERTER ||
1803 dongle == DISPLAY_DONGLE_DP_DVI_CONVERTER ||
1804 dongle == DISPLAY_DONGLE_DP_HDMI_CONVERTER)
1805 flags->DISABLE_STEREO_DP_SYNC = 1;
1806 }
1807 flags->RIGHT_EYE_POLARITY =\
1808 stream->public.timing.flags.RIGHT_EYE_3D_POLARITY;
1809 if (timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING)
1810 flags->FRAME_PACKED = 1;
1811 }
1812
1813 return;
1814 }
1815
1816 static void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, struct core_dc *dc)
1817 {
1818 struct crtc_stereo_flags flags = { 0 };
1819 struct core_stream *stream = pipe_ctx->stream;
1820
1821 dcn10_config_stereo_parameters(stream, &flags);
1822
1823 pipe_ctx->opp->funcs->opp_set_stereo_polarity(
1824 pipe_ctx->opp,
1825 flags.PROGRAM_STEREO == 1 ? true:false,
1826 stream->public.timing.flags.RIGHT_EYE_3D_POLARITY == 1 ? true:false);
1827
1828 pipe_ctx->tg->funcs->program_stereo(
1829 pipe_ctx->tg,
1830 &stream->public.timing,
1831 &flags);
1832
1833 return;
1834 }
1835
1836 static bool dcn10_dummy_display_power_gating(
1837 struct core_dc *dc,
1838 uint8_t controller_id,
1839 struct dc_bios *dcb,
1840 enum pipe_gating_control power_gating) {return true; }
1841
1842 static const struct hw_sequencer_funcs dcn10_funcs = {
1843 .program_gamut_remap = program_gamut_remap,
1844 .program_csc_matrix = program_csc_matrix,
1845 .init_hw = init_hw,
1846 .apply_ctx_to_hw = dce110_apply_ctx_to_hw,
1847 .apply_ctx_for_surface = dcn10_apply_ctx_for_surface,
1848 .set_plane_config = set_plane_config,
1849 .update_plane_addr = update_plane_addr,
1850 .update_pending_status = dce110_update_pending_status,
1851 .set_input_transfer_func = dcn10_set_input_transfer_func,
1852 .set_output_transfer_func = dcn10_set_output_transfer_func,
1853 .power_down = dce110_power_down,
1854 .enable_accelerated_mode = dce110_enable_accelerated_mode,
1855 .enable_timing_synchronization = dcn10_enable_timing_synchronization,
1856 .update_info_frame = dce110_update_info_frame,
1857 .enable_stream = dce110_enable_stream,
1858 .disable_stream = dce110_disable_stream,
1859 .unblank_stream = dce110_unblank_stream,
1860 .enable_display_power_gating = dcn10_dummy_display_power_gating,
1861 .power_down_front_end = dcn10_power_down_fe,
1862 .power_on_front_end = dcn10_power_on_fe,
1863 .pipe_control_lock = dcn10_pipe_control_lock,
1864 .set_bandwidth = dcn10_set_bandwidth,
1865 .reset_hw_ctx_wrap = reset_hw_ctx_wrap,
1866 .prog_pixclk_crtc_otg = dcn10_prog_pixclk_crtc_otg,
1867 .set_drr = set_drr,
1868 .get_position = get_position,
1869 .set_static_screen_control = set_static_screen_control,
1870 .setup_stereo = dcn10_setup_stereo
1871 };
1872
1873
1874 bool dcn10_hw_sequencer_construct(struct core_dc *dc)
1875 {
1876 dc->hwss = dcn10_funcs;
1877 return true;
1878 }
1879