]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
drm/amd/display: Connect DC resource to FBC compressor
[mirror_ubuntu-bionic-kernel.git] / drivers / gpu / drm / amd / display / dc / dce110 / dce110_hw_sequencer.c
1 /*
2 * Copyright 2015 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 #include "dm_services.h"
26 #include "dc.h"
27 #include "dc_bios_types.h"
28 #include "core_types.h"
29 #include "core_status.h"
30 #include "resource.h"
31 #include "dm_helpers.h"
32 #include "dce110_hw_sequencer.h"
33 #include "dce110_timing_generator.h"
34 #include "dce/dce_hwseq.h"
35
36 #ifdef ENABLE_FBC
37 #include "dce110_compressor.h"
38 #endif
39
40 #include "bios/bios_parser_helper.h"
41 #include "timing_generator.h"
42 #include "mem_input.h"
43 #include "opp.h"
44 #include "ipp.h"
45 #include "transform.h"
46 #include "stream_encoder.h"
47 #include "link_encoder.h"
48 #include "clock_source.h"
49 #include "abm.h"
50 #include "audio.h"
51 #include "dce/dce_hwseq.h"
52
53 /* include DCE11 register header files */
54 #include "dce/dce_11_0_d.h"
55 #include "dce/dce_11_0_sh_mask.h"
56 #include "custom_float.h"
57
58 struct dce110_hw_seq_reg_offsets {
59 uint32_t crtc;
60 };
61
62 static const struct dce110_hw_seq_reg_offsets reg_offsets[] = {
63 {
64 .crtc = (mmCRTC0_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
65 },
66 {
67 .crtc = (mmCRTC1_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
68 },
69 {
70 .crtc = (mmCRTC2_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
71 },
72 {
73 .crtc = (mmCRTCV_GSL_CONTROL - mmCRTC_GSL_CONTROL),
74 }
75 };
76
77 #define HW_REG_BLND(reg, id)\
78 (reg + reg_offsets[id].blnd)
79
80 #define HW_REG_CRTC(reg, id)\
81 (reg + reg_offsets[id].crtc)
82
83 #define MAX_WATERMARK 0xFFFF
84 #define SAFE_NBP_MARK 0x7FFF
85
86 /*******************************************************************************
87 * Private definitions
88 ******************************************************************************/
89 /***************************PIPE_CONTROL***********************************/
90 static void dce110_init_pte(struct dc_context *ctx)
91 {
92 uint32_t addr;
93 uint32_t value = 0;
94 uint32_t chunk_int = 0;
95 uint32_t chunk_mul = 0;
96
97 addr = mmUNP_DVMM_PTE_CONTROL;
98 value = dm_read_reg(ctx, addr);
99
100 set_reg_field_value(
101 value,
102 0,
103 DVMM_PTE_CONTROL,
104 DVMM_USE_SINGLE_PTE);
105
106 set_reg_field_value(
107 value,
108 1,
109 DVMM_PTE_CONTROL,
110 DVMM_PTE_BUFFER_MODE0);
111
112 set_reg_field_value(
113 value,
114 1,
115 DVMM_PTE_CONTROL,
116 DVMM_PTE_BUFFER_MODE1);
117
118 dm_write_reg(ctx, addr, value);
119
120 addr = mmDVMM_PTE_REQ;
121 value = dm_read_reg(ctx, addr);
122
123 chunk_int = get_reg_field_value(
124 value,
125 DVMM_PTE_REQ,
126 HFLIP_PTEREQ_PER_CHUNK_INT);
127
128 chunk_mul = get_reg_field_value(
129 value,
130 DVMM_PTE_REQ,
131 HFLIP_PTEREQ_PER_CHUNK_MULTIPLIER);
132
133 if (chunk_int != 0x4 || chunk_mul != 0x4) {
134
135 set_reg_field_value(
136 value,
137 255,
138 DVMM_PTE_REQ,
139 MAX_PTEREQ_TO_ISSUE);
140
141 set_reg_field_value(
142 value,
143 4,
144 DVMM_PTE_REQ,
145 HFLIP_PTEREQ_PER_CHUNK_INT);
146
147 set_reg_field_value(
148 value,
149 4,
150 DVMM_PTE_REQ,
151 HFLIP_PTEREQ_PER_CHUNK_MULTIPLIER);
152
153 dm_write_reg(ctx, addr, value);
154 }
155 }
156 /**************************************************************************/
157
158 static void enable_display_pipe_clock_gating(
159 struct dc_context *ctx,
160 bool clock_gating)
161 {
162 /*TODO*/
163 }
164
165 static bool dce110_enable_display_power_gating(
166 struct core_dc *dc,
167 uint8_t controller_id,
168 struct dc_bios *dcb,
169 enum pipe_gating_control power_gating)
170 {
171 enum bp_result bp_result = BP_RESULT_OK;
172 enum bp_pipe_control_action cntl;
173 struct dc_context *ctx = dc->ctx;
174 unsigned int underlay_idx = dc->res_pool->underlay_pipe_index;
175
176 if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment))
177 return true;
178
179 if (power_gating == PIPE_GATING_CONTROL_INIT)
180 cntl = ASIC_PIPE_INIT;
181 else if (power_gating == PIPE_GATING_CONTROL_ENABLE)
182 cntl = ASIC_PIPE_ENABLE;
183 else
184 cntl = ASIC_PIPE_DISABLE;
185
186 if (controller_id == underlay_idx)
187 controller_id = CONTROLLER_ID_UNDERLAY0 - 1;
188
189 if (power_gating != PIPE_GATING_CONTROL_INIT || controller_id == 0){
190
191 bp_result = dcb->funcs->enable_disp_power_gating(
192 dcb, controller_id + 1, cntl);
193
194 /* Revert MASTER_UPDATE_MODE to 0 because bios sets it 2
195 * by default when command table is called
196 *
197 * Bios parser accepts controller_id = 6 as indicative of
198 * underlay pipe in dce110. But we do not support more
199 * than 3.
200 */
201 if (controller_id < CONTROLLER_ID_MAX - 1)
202 dm_write_reg(ctx,
203 HW_REG_CRTC(mmCRTC_MASTER_UPDATE_MODE, controller_id),
204 0);
205 }
206
207 if (power_gating != PIPE_GATING_CONTROL_ENABLE)
208 dce110_init_pte(ctx);
209
210 if (bp_result == BP_RESULT_OK)
211 return true;
212 else
213 return false;
214 }
215
216 static void build_prescale_params(struct ipp_prescale_params *prescale_params,
217 const struct core_surface *surface)
218 {
219 prescale_params->mode = IPP_PRESCALE_MODE_FIXED_UNSIGNED;
220
221 switch (surface->public.format) {
222 case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
223 case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
224 prescale_params->scale = 0x2020;
225 break;
226 case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
227 case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
228 prescale_params->scale = 0x2008;
229 break;
230 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
231 case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
232 prescale_params->scale = 0x2000;
233 break;
234 default:
235 ASSERT(false);
236 break;
237 }
238 }
239
240 static bool dce110_set_input_transfer_func(
241 struct pipe_ctx *pipe_ctx,
242 const struct core_surface *surface)
243 {
244 struct input_pixel_processor *ipp = pipe_ctx->ipp;
245 const struct core_transfer_func *tf = NULL;
246 struct ipp_prescale_params prescale_params = { 0 };
247 bool result = true;
248
249 if (ipp == NULL)
250 return false;
251
252 if (surface->public.in_transfer_func)
253 tf = DC_TRANSFER_FUNC_TO_CORE(surface->public.in_transfer_func);
254
255 build_prescale_params(&prescale_params, surface);
256 ipp->funcs->ipp_program_prescale(ipp, &prescale_params);
257
258 if (surface->public.gamma_correction && dce_use_lut(surface))
259 ipp->funcs->ipp_program_input_lut(ipp, surface->public.gamma_correction);
260
261 if (tf == NULL) {
262 /* Default case if no input transfer function specified */
263 ipp->funcs->ipp_set_degamma(ipp,
264 IPP_DEGAMMA_MODE_HW_sRGB);
265 } else if (tf->public.type == TF_TYPE_PREDEFINED) {
266 switch (tf->public.tf) {
267 case TRANSFER_FUNCTION_SRGB:
268 ipp->funcs->ipp_set_degamma(ipp,
269 IPP_DEGAMMA_MODE_HW_sRGB);
270 break;
271 case TRANSFER_FUNCTION_BT709:
272 ipp->funcs->ipp_set_degamma(ipp,
273 IPP_DEGAMMA_MODE_HW_xvYCC);
274 break;
275 case TRANSFER_FUNCTION_LINEAR:
276 ipp->funcs->ipp_set_degamma(ipp,
277 IPP_DEGAMMA_MODE_BYPASS);
278 break;
279 case TRANSFER_FUNCTION_PQ:
280 result = false;
281 break;
282 default:
283 result = false;
284 break;
285 }
286 } else if (tf->public.type == TF_TYPE_BYPASS) {
287 ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS);
288 } else {
289 /*TF_TYPE_DISTRIBUTED_POINTS - Not supported in DCE 11*/
290 result = false;
291 }
292
293 return result;
294 }
295
296 static bool convert_to_custom_float(
297 struct pwl_result_data *rgb_resulted,
298 struct curve_points *arr_points,
299 uint32_t hw_points_num)
300 {
301 struct custom_float_format fmt;
302
303 struct pwl_result_data *rgb = rgb_resulted;
304
305 uint32_t i = 0;
306
307 fmt.exponenta_bits = 6;
308 fmt.mantissa_bits = 12;
309 fmt.sign = true;
310
311 if (!convert_to_custom_float_format(
312 arr_points[0].x,
313 &fmt,
314 &arr_points[0].custom_float_x)) {
315 BREAK_TO_DEBUGGER();
316 return false;
317 }
318
319 if (!convert_to_custom_float_format(
320 arr_points[0].offset,
321 &fmt,
322 &arr_points[0].custom_float_offset)) {
323 BREAK_TO_DEBUGGER();
324 return false;
325 }
326
327 if (!convert_to_custom_float_format(
328 arr_points[0].slope,
329 &fmt,
330 &arr_points[0].custom_float_slope)) {
331 BREAK_TO_DEBUGGER();
332 return false;
333 }
334
335 fmt.mantissa_bits = 10;
336 fmt.sign = false;
337
338 if (!convert_to_custom_float_format(
339 arr_points[1].x,
340 &fmt,
341 &arr_points[1].custom_float_x)) {
342 BREAK_TO_DEBUGGER();
343 return false;
344 }
345
346 if (!convert_to_custom_float_format(
347 arr_points[1].y,
348 &fmt,
349 &arr_points[1].custom_float_y)) {
350 BREAK_TO_DEBUGGER();
351 return false;
352 }
353
354 if (!convert_to_custom_float_format(
355 arr_points[2].slope,
356 &fmt,
357 &arr_points[2].custom_float_slope)) {
358 BREAK_TO_DEBUGGER();
359 return false;
360 }
361
362 fmt.mantissa_bits = 12;
363 fmt.sign = true;
364
365 while (i != hw_points_num) {
366 if (!convert_to_custom_float_format(
367 rgb->red,
368 &fmt,
369 &rgb->red_reg)) {
370 BREAK_TO_DEBUGGER();
371 return false;
372 }
373
374 if (!convert_to_custom_float_format(
375 rgb->green,
376 &fmt,
377 &rgb->green_reg)) {
378 BREAK_TO_DEBUGGER();
379 return false;
380 }
381
382 if (!convert_to_custom_float_format(
383 rgb->blue,
384 &fmt,
385 &rgb->blue_reg)) {
386 BREAK_TO_DEBUGGER();
387 return false;
388 }
389
390 if (!convert_to_custom_float_format(
391 rgb->delta_red,
392 &fmt,
393 &rgb->delta_red_reg)) {
394 BREAK_TO_DEBUGGER();
395 return false;
396 }
397
398 if (!convert_to_custom_float_format(
399 rgb->delta_green,
400 &fmt,
401 &rgb->delta_green_reg)) {
402 BREAK_TO_DEBUGGER();
403 return false;
404 }
405
406 if (!convert_to_custom_float_format(
407 rgb->delta_blue,
408 &fmt,
409 &rgb->delta_blue_reg)) {
410 BREAK_TO_DEBUGGER();
411 return false;
412 }
413
414 ++rgb;
415 ++i;
416 }
417
418 return true;
419 }
420
421 static bool dce110_translate_regamma_to_hw_format(const struct dc_transfer_func
422 *output_tf, struct pwl_params *regamma_params)
423 {
424 struct curve_points *arr_points;
425 struct pwl_result_data *rgb_resulted;
426 struct pwl_result_data *rgb;
427 struct pwl_result_data *rgb_plus_1;
428 struct fixed31_32 y_r;
429 struct fixed31_32 y_g;
430 struct fixed31_32 y_b;
431 struct fixed31_32 y1_min;
432 struct fixed31_32 y3_max;
433
434 int32_t segment_start, segment_end;
435 uint32_t i, j, k, seg_distr[16], increment, start_index, hw_points;
436
437 if (output_tf == NULL || regamma_params == NULL ||
438 output_tf->type == TF_TYPE_BYPASS)
439 return false;
440
441 arr_points = regamma_params->arr_points;
442 rgb_resulted = regamma_params->rgb_resulted;
443 hw_points = 0;
444
445 memset(regamma_params, 0, sizeof(struct pwl_params));
446
447 if (output_tf->tf == TRANSFER_FUNCTION_PQ) {
448 /* 16 segments
449 * segments are from 2^-11 to 2^5
450 */
451 segment_start = -11;
452 segment_end = 5;
453
454 seg_distr[0] = 2;
455 seg_distr[1] = 2;
456 seg_distr[2] = 2;
457 seg_distr[3] = 2;
458 seg_distr[4] = 2;
459 seg_distr[5] = 2;
460 seg_distr[6] = 3;
461 seg_distr[7] = 4;
462 seg_distr[8] = 4;
463 seg_distr[9] = 4;
464 seg_distr[10] = 4;
465 seg_distr[11] = 5;
466 seg_distr[12] = 5;
467 seg_distr[13] = 5;
468 seg_distr[14] = 5;
469 seg_distr[15] = 5;
470
471 } else {
472 /* 10 segments
473 * segment is from 2^-10 to 2^0
474 */
475 segment_start = -10;
476 segment_end = 0;
477
478 seg_distr[0] = 3;
479 seg_distr[1] = 4;
480 seg_distr[2] = 4;
481 seg_distr[3] = 4;
482 seg_distr[4] = 4;
483 seg_distr[5] = 4;
484 seg_distr[6] = 4;
485 seg_distr[7] = 4;
486 seg_distr[8] = 5;
487 seg_distr[9] = 5;
488 seg_distr[10] = -1;
489 seg_distr[11] = -1;
490 seg_distr[12] = -1;
491 seg_distr[13] = -1;
492 seg_distr[14] = -1;
493 seg_distr[15] = -1;
494 }
495
496 for (k = 0; k < 16; k++) {
497 if (seg_distr[k] != -1)
498 hw_points += (1 << seg_distr[k]);
499 }
500
501 j = 0;
502 for (k = 0; k < (segment_end - segment_start); k++) {
503 increment = 32 / (1 << seg_distr[k]);
504 start_index = (segment_start + k + 25) * 32;
505 for (i = start_index; i < start_index + 32; i += increment) {
506 if (j == hw_points - 1)
507 break;
508 rgb_resulted[j].red = output_tf->tf_pts.red[i];
509 rgb_resulted[j].green = output_tf->tf_pts.green[i];
510 rgb_resulted[j].blue = output_tf->tf_pts.blue[i];
511 j++;
512 }
513 }
514
515 /* last point */
516 start_index = (segment_end + 25) * 32;
517 rgb_resulted[hw_points - 1].red =
518 output_tf->tf_pts.red[start_index];
519 rgb_resulted[hw_points - 1].green =
520 output_tf->tf_pts.green[start_index];
521 rgb_resulted[hw_points - 1].blue =
522 output_tf->tf_pts.blue[start_index];
523
524 arr_points[0].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2),
525 dal_fixed31_32_from_int(segment_start));
526 arr_points[1].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2),
527 dal_fixed31_32_from_int(segment_end));
528 arr_points[2].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2),
529 dal_fixed31_32_from_int(segment_end));
530
531 y_r = rgb_resulted[0].red;
532 y_g = rgb_resulted[0].green;
533 y_b = rgb_resulted[0].blue;
534
535 y1_min = dal_fixed31_32_min(y_r, dal_fixed31_32_min(y_g, y_b));
536
537 arr_points[0].y = y1_min;
538 arr_points[0].slope = dal_fixed31_32_div(
539 arr_points[0].y,
540 arr_points[0].x);
541
542 y_r = rgb_resulted[hw_points - 1].red;
543 y_g = rgb_resulted[hw_points - 1].green;
544 y_b = rgb_resulted[hw_points - 1].blue;
545
546 /* see comment above, m_arrPoints[1].y should be the Y value for the
547 * region end (m_numOfHwPoints), not last HW point(m_numOfHwPoints - 1)
548 */
549 y3_max = dal_fixed31_32_max(y_r, dal_fixed31_32_max(y_g, y_b));
550
551 arr_points[1].y = y3_max;
552 arr_points[2].y = y3_max;
553
554 arr_points[1].slope = dal_fixed31_32_zero;
555 arr_points[2].slope = dal_fixed31_32_zero;
556
557 if (output_tf->tf == TRANSFER_FUNCTION_PQ) {
558 /* for PQ, we want to have a straight line from last HW X point,
559 * and the slope to be such that we hit 1.0 at 10000 nits.
560 */
561 const struct fixed31_32 end_value =
562 dal_fixed31_32_from_int(125);
563
564 arr_points[1].slope = dal_fixed31_32_div(
565 dal_fixed31_32_sub(dal_fixed31_32_one, arr_points[1].y),
566 dal_fixed31_32_sub(end_value, arr_points[1].x));
567 arr_points[2].slope = dal_fixed31_32_div(
568 dal_fixed31_32_sub(dal_fixed31_32_one, arr_points[1].y),
569 dal_fixed31_32_sub(end_value, arr_points[1].x));
570 }
571
572 regamma_params->hw_points_num = hw_points;
573
574 i = 1;
575 for (k = 0; k < 16 && i < 16; k++) {
576 if (seg_distr[k] != -1) {
577 regamma_params->arr_curve_points[k].segments_num =
578 seg_distr[k];
579 regamma_params->arr_curve_points[i].offset =
580 regamma_params->arr_curve_points[k].
581 offset + (1 << seg_distr[k]);
582 }
583 i++;
584 }
585
586 if (seg_distr[k] != -1)
587 regamma_params->arr_curve_points[k].segments_num =
588 seg_distr[k];
589
590 rgb = rgb_resulted;
591 rgb_plus_1 = rgb_resulted + 1;
592
593 i = 1;
594
595 while (i != hw_points + 1) {
596 if (dal_fixed31_32_lt(rgb_plus_1->red, rgb->red))
597 rgb_plus_1->red = rgb->red;
598 if (dal_fixed31_32_lt(rgb_plus_1->green, rgb->green))
599 rgb_plus_1->green = rgb->green;
600 if (dal_fixed31_32_lt(rgb_plus_1->blue, rgb->blue))
601 rgb_plus_1->blue = rgb->blue;
602
603 rgb->delta_red = dal_fixed31_32_sub(
604 rgb_plus_1->red,
605 rgb->red);
606 rgb->delta_green = dal_fixed31_32_sub(
607 rgb_plus_1->green,
608 rgb->green);
609 rgb->delta_blue = dal_fixed31_32_sub(
610 rgb_plus_1->blue,
611 rgb->blue);
612
613 ++rgb_plus_1;
614 ++rgb;
615 ++i;
616 }
617
618 convert_to_custom_float(rgb_resulted, arr_points, hw_points);
619
620 return true;
621 }
622
623 static bool dce110_set_output_transfer_func(
624 struct pipe_ctx *pipe_ctx,
625 const struct core_stream *stream)
626 {
627 struct output_pixel_processor *opp = pipe_ctx->opp;
628
629 opp->funcs->opp_power_on_regamma_lut(opp, true);
630 opp->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM;
631
632 if (stream->public.out_transfer_func &&
633 stream->public.out_transfer_func->type ==
634 TF_TYPE_PREDEFINED &&
635 stream->public.out_transfer_func->tf ==
636 TRANSFER_FUNCTION_SRGB) {
637 opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_SRGB);
638 } else if (dce110_translate_regamma_to_hw_format(
639 stream->public.out_transfer_func, &opp->regamma_params)) {
640 opp->funcs->opp_program_regamma_pwl(opp, &opp->regamma_params);
641 opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_USER);
642 } else {
643 opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_BYPASS);
644 }
645
646 opp->funcs->opp_power_on_regamma_lut(opp, false);
647
648 return true;
649 }
650
651 static enum dc_status bios_parser_crtc_source_select(
652 struct pipe_ctx *pipe_ctx)
653 {
654 struct dc_bios *dcb;
655 /* call VBIOS table to set CRTC source for the HW
656 * encoder block
657 * note: video bios clears all FMT setting here. */
658 struct bp_crtc_source_select crtc_source_select = {0};
659 const struct core_sink *sink = pipe_ctx->stream->sink;
660
661 crtc_source_select.engine_id = pipe_ctx->stream_enc->id;
662 crtc_source_select.controller_id = pipe_ctx->pipe_idx + 1;
663 /*TODO: Need to un-hardcode color depth, dp_audio and account for
664 * the case where signal and sink signal is different (translator
665 * encoder)*/
666 crtc_source_select.signal = pipe_ctx->stream->signal;
667 crtc_source_select.enable_dp_audio = false;
668 crtc_source_select.sink_signal = pipe_ctx->stream->signal;
669 crtc_source_select.display_output_bit_depth = PANEL_8BIT_COLOR;
670
671 dcb = sink->ctx->dc_bios;
672
673 if (BP_RESULT_OK != dcb->funcs->crtc_source_select(
674 dcb,
675 &crtc_source_select)) {
676 return DC_ERROR_UNEXPECTED;
677 }
678
679 return DC_OK;
680 }
681
682 void dce110_update_info_frame(struct pipe_ctx *pipe_ctx)
683 {
684 ASSERT(pipe_ctx->stream);
685
686 if (pipe_ctx->stream_enc == NULL)
687 return; /* this is not root pipe */
688
689 if (dc_is_hdmi_signal(pipe_ctx->stream->signal))
690 pipe_ctx->stream_enc->funcs->update_hdmi_info_packets(
691 pipe_ctx->stream_enc,
692 &pipe_ctx->encoder_info_frame);
693 else if (dc_is_dp_signal(pipe_ctx->stream->signal))
694 pipe_ctx->stream_enc->funcs->update_dp_info_packets(
695 pipe_ctx->stream_enc,
696 &pipe_ctx->encoder_info_frame);
697 }
698
699 void dce110_enable_stream(struct pipe_ctx *pipe_ctx)
700 {
701 enum dc_lane_count lane_count =
702 pipe_ctx->stream->sink->link->public.cur_link_settings.lane_count;
703
704 struct dc_crtc_timing *timing = &pipe_ctx->stream->public.timing;
705 struct core_link *link = pipe_ctx->stream->sink->link;
706
707 /* 1. update AVI info frame (HDMI, DP)
708 * we always need to update info frame
709 */
710 uint32_t active_total_with_borders;
711 uint32_t early_control = 0;
712 struct timing_generator *tg = pipe_ctx->tg;
713
714 /* TODOFPGA may change to hwss.update_info_frame */
715 dce110_update_info_frame(pipe_ctx);
716 /* enable early control to avoid corruption on DP monitor*/
717 active_total_with_borders =
718 timing->h_addressable
719 + timing->h_border_left
720 + timing->h_border_right;
721
722 if (lane_count != 0)
723 early_control = active_total_with_borders % lane_count;
724
725 if (early_control == 0)
726 early_control = lane_count;
727
728 tg->funcs->set_early_control(tg, early_control);
729
730 /* enable audio only within mode set */
731 if (pipe_ctx->audio != NULL) {
732 if (dc_is_dp_signal(pipe_ctx->stream->signal))
733 pipe_ctx->stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_enc);
734 }
735
736 /* For MST, there are multiply stream go to only one link.
737 * connect DIG back_end to front_end while enable_stream and
738 * disconnect them during disable_stream
739 * BY this, it is logic clean to separate stream and link */
740 link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc,
741 pipe_ctx->stream_enc->id, true);
742
743 }
744
745 void dce110_disable_stream(struct pipe_ctx *pipe_ctx)
746 {
747 struct core_stream *stream = pipe_ctx->stream;
748 struct core_link *link = stream->sink->link;
749
750 if (pipe_ctx->audio) {
751 pipe_ctx->audio->funcs->az_disable(pipe_ctx->audio);
752
753 if (dc_is_dp_signal(pipe_ctx->stream->signal))
754 pipe_ctx->stream_enc->funcs->dp_audio_disable(
755 pipe_ctx->stream_enc);
756 else
757 pipe_ctx->stream_enc->funcs->hdmi_audio_disable(
758 pipe_ctx->stream_enc);
759
760 pipe_ctx->audio = NULL;
761
762 /* TODO: notify audio driver for if audio modes list changed
763 * add audio mode list change flag */
764 /* dal_audio_disable_azalia_audio_jack_presence(stream->audio,
765 * stream->stream_engine_id);
766 */
767 }
768
769 if (dc_is_hdmi_signal(pipe_ctx->stream->signal))
770 pipe_ctx->stream_enc->funcs->stop_hdmi_info_packets(
771 pipe_ctx->stream_enc);
772
773 if (dc_is_dp_signal(pipe_ctx->stream->signal))
774 pipe_ctx->stream_enc->funcs->stop_dp_info_packets(
775 pipe_ctx->stream_enc);
776
777 pipe_ctx->stream_enc->funcs->audio_mute_control(
778 pipe_ctx->stream_enc, true);
779
780
781 /* blank at encoder level */
782 if (dc_is_dp_signal(pipe_ctx->stream->signal))
783 pipe_ctx->stream_enc->funcs->dp_blank(pipe_ctx->stream_enc);
784
785 link->link_enc->funcs->connect_dig_be_to_fe(
786 link->link_enc,
787 pipe_ctx->stream_enc->id,
788 false);
789
790 }
791
792 void dce110_unblank_stream(struct pipe_ctx *pipe_ctx,
793 struct dc_link_settings *link_settings)
794 {
795 struct encoder_unblank_param params = { { 0 } };
796
797 /* only 3 items below are used by unblank */
798 params.pixel_clk_khz =
799 pipe_ctx->stream->public.timing.pix_clk_khz;
800 params.link_settings.link_rate = link_settings->link_rate;
801 pipe_ctx->stream_enc->funcs->dp_unblank(pipe_ctx->stream_enc, &params);
802 }
803
804 static enum audio_dto_source translate_to_dto_source(enum controller_id crtc_id)
805 {
806 switch (crtc_id) {
807 case CONTROLLER_ID_D0:
808 return DTO_SOURCE_ID0;
809 case CONTROLLER_ID_D1:
810 return DTO_SOURCE_ID1;
811 case CONTROLLER_ID_D2:
812 return DTO_SOURCE_ID2;
813 case CONTROLLER_ID_D3:
814 return DTO_SOURCE_ID3;
815 case CONTROLLER_ID_D4:
816 return DTO_SOURCE_ID4;
817 case CONTROLLER_ID_D5:
818 return DTO_SOURCE_ID5;
819 default:
820 return DTO_SOURCE_UNKNOWN;
821 }
822 }
823
824 static void build_audio_output(
825 const struct pipe_ctx *pipe_ctx,
826 struct audio_output *audio_output)
827 {
828 const struct core_stream *stream = pipe_ctx->stream;
829 audio_output->engine_id = pipe_ctx->stream_enc->id;
830
831 audio_output->signal = pipe_ctx->stream->signal;
832
833 /* audio_crtc_info */
834
835 audio_output->crtc_info.h_total =
836 stream->public.timing.h_total;
837
838 /*
839 * Audio packets are sent during actual CRTC blank physical signal, we
840 * need to specify actual active signal portion
841 */
842 audio_output->crtc_info.h_active =
843 stream->public.timing.h_addressable
844 + stream->public.timing.h_border_left
845 + stream->public.timing.h_border_right;
846
847 audio_output->crtc_info.v_active =
848 stream->public.timing.v_addressable
849 + stream->public.timing.v_border_top
850 + stream->public.timing.v_border_bottom;
851
852 audio_output->crtc_info.pixel_repetition = 1;
853
854 audio_output->crtc_info.interlaced =
855 stream->public.timing.flags.INTERLACE;
856
857 audio_output->crtc_info.refresh_rate =
858 (stream->public.timing.pix_clk_khz*1000)/
859 (stream->public.timing.h_total*stream->public.timing.v_total);
860
861 audio_output->crtc_info.color_depth =
862 stream->public.timing.display_color_depth;
863
864 audio_output->crtc_info.requested_pixel_clock =
865 pipe_ctx->pix_clk_params.requested_pix_clk;
866
867 audio_output->crtc_info.calculated_pixel_clock =
868 pipe_ctx->pix_clk_params.requested_pix_clk;
869
870 /*for HDMI, audio ACR is with deep color ratio factor*/
871 if (dc_is_hdmi_signal(pipe_ctx->stream->signal) &&
872 audio_output->crtc_info.requested_pixel_clock ==
873 stream->public.timing.pix_clk_khz) {
874 if (pipe_ctx->pix_clk_params.pixel_encoding == PIXEL_ENCODING_YCBCR420) {
875 audio_output->crtc_info.requested_pixel_clock =
876 audio_output->crtc_info.requested_pixel_clock/2;
877 audio_output->crtc_info.calculated_pixel_clock =
878 pipe_ctx->pix_clk_params.requested_pix_clk/2;
879
880 }
881 }
882
883 if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT ||
884 pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
885 audio_output->pll_info.dp_dto_source_clock_in_khz =
886 pipe_ctx->dis_clk->funcs->get_dp_ref_clk_frequency(
887 pipe_ctx->dis_clk);
888 }
889
890 audio_output->pll_info.feed_back_divider =
891 pipe_ctx->pll_settings.feedback_divider;
892
893 audio_output->pll_info.dto_source =
894 translate_to_dto_source(
895 pipe_ctx->pipe_idx + 1);
896
897 /* TODO hard code to enable for now. Need get from stream */
898 audio_output->pll_info.ss_enabled = true;
899
900 audio_output->pll_info.ss_percentage =
901 pipe_ctx->pll_settings.ss_percentage;
902 }
903
904 static void get_surface_visual_confirm_color(const struct pipe_ctx *pipe_ctx,
905 struct tg_color *color)
906 {
907 uint32_t color_value = MAX_TG_COLOR_VALUE * (4 - pipe_ctx->pipe_idx) / 4;
908
909 switch (pipe_ctx->scl_data.format) {
910 case PIXEL_FORMAT_ARGB8888:
911 /* set boarder color to red */
912 color->color_r_cr = color_value;
913 break;
914
915 case PIXEL_FORMAT_ARGB2101010:
916 /* set boarder color to blue */
917 color->color_b_cb = color_value;
918 break;
919 case PIXEL_FORMAT_420BPP12:
920 case PIXEL_FORMAT_420BPP15:
921 /* set boarder color to green */
922 color->color_g_y = color_value;
923 break;
924 case PIXEL_FORMAT_FP16:
925 /* set boarder color to white */
926 color->color_r_cr = color_value;
927 color->color_b_cb = color_value;
928 color->color_g_y = color_value;
929 break;
930 default:
931 break;
932 }
933 }
934
935 static void program_scaler(const struct core_dc *dc,
936 const struct pipe_ctx *pipe_ctx)
937 {
938 struct tg_color color = {0};
939
940 #if defined(CONFIG_DRM_AMD_DC_DCN1_0)
941 /* TOFPGA */
942 if (pipe_ctx->xfm->funcs->transform_set_pixel_storage_depth == NULL)
943 return;
944 #endif
945
946 if (dc->public.debug.surface_visual_confirm)
947 get_surface_visual_confirm_color(pipe_ctx, &color);
948 else
949 color_space_to_black_color(dc,
950 pipe_ctx->stream->public.output_color_space,
951 &color);
952
953 pipe_ctx->xfm->funcs->transform_set_pixel_storage_depth(
954 pipe_ctx->xfm,
955 pipe_ctx->scl_data.lb_params.depth,
956 &pipe_ctx->stream->bit_depth_params);
957
958 if (pipe_ctx->tg->funcs->set_overscan_blank_color)
959 pipe_ctx->tg->funcs->set_overscan_blank_color(
960 pipe_ctx->tg,
961 &color);
962
963 pipe_ctx->xfm->funcs->transform_set_scaler(pipe_ctx->xfm,
964 &pipe_ctx->scl_data);
965 }
966
967 static enum dc_status dce110_prog_pixclk_crtc_otg(
968 struct pipe_ctx *pipe_ctx,
969 struct validate_context *context,
970 struct core_dc *dc)
971 {
972 struct core_stream *stream = pipe_ctx->stream;
973 struct pipe_ctx *pipe_ctx_old = &dc->current_context->res_ctx.
974 pipe_ctx[pipe_ctx->pipe_idx];
975 struct tg_color black_color = {0};
976
977 if (!pipe_ctx_old->stream) {
978
979 /* program blank color */
980 color_space_to_black_color(dc,
981 stream->public.output_color_space, &black_color);
982 pipe_ctx->tg->funcs->set_blank_color(
983 pipe_ctx->tg,
984 &black_color);
985
986 /*
987 * Must blank CRTC after disabling power gating and before any
988 * programming, otherwise CRTC will be hung in bad state
989 */
990 pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, true);
991
992 if (false == pipe_ctx->clock_source->funcs->program_pix_clk(
993 pipe_ctx->clock_source,
994 &pipe_ctx->pix_clk_params,
995 &pipe_ctx->pll_settings)) {
996 BREAK_TO_DEBUGGER();
997 return DC_ERROR_UNEXPECTED;
998 }
999
1000 pipe_ctx->tg->funcs->program_timing(
1001 pipe_ctx->tg,
1002 &stream->public.timing,
1003 true);
1004
1005 pipe_ctx->tg->funcs->set_static_screen_control(
1006 pipe_ctx->tg,
1007 0x182);
1008 }
1009
1010 if (!pipe_ctx_old->stream) {
1011 if (false == pipe_ctx->tg->funcs->enable_crtc(
1012 pipe_ctx->tg)) {
1013 BREAK_TO_DEBUGGER();
1014 return DC_ERROR_UNEXPECTED;
1015 }
1016 }
1017
1018
1019
1020 return DC_OK;
1021 }
1022
1023 static enum dc_status apply_single_controller_ctx_to_hw(
1024 struct pipe_ctx *pipe_ctx,
1025 struct validate_context *context,
1026 struct core_dc *dc)
1027 {
1028 struct core_stream *stream = pipe_ctx->stream;
1029 struct pipe_ctx *pipe_ctx_old = &dc->current_context->res_ctx.
1030 pipe_ctx[pipe_ctx->pipe_idx];
1031
1032 /* */
1033 dc->hwss.prog_pixclk_crtc_otg(pipe_ctx, context, dc);
1034
1035 pipe_ctx->opp->funcs->opp_set_dyn_expansion(
1036 pipe_ctx->opp,
1037 COLOR_SPACE_YCBCR601,
1038 stream->public.timing.display_color_depth,
1039 pipe_ctx->stream->signal);
1040
1041 /* FPGA does not program backend */
1042 if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
1043 pipe_ctx->opp->funcs->opp_program_fmt(
1044 pipe_ctx->opp,
1045 &stream->bit_depth_params,
1046 &stream->clamping);
1047 return DC_OK;
1048 }
1049 /* TODO: move to stream encoder */
1050 if (pipe_ctx->stream->signal != SIGNAL_TYPE_VIRTUAL)
1051 if (DC_OK != bios_parser_crtc_source_select(pipe_ctx)) {
1052 BREAK_TO_DEBUGGER();
1053 return DC_ERROR_UNEXPECTED;
1054 }
1055
1056 if (pipe_ctx->stream->signal != SIGNAL_TYPE_VIRTUAL)
1057 stream->sink->link->link_enc->funcs->setup(
1058 stream->sink->link->link_enc,
1059 pipe_ctx->stream->signal);
1060
1061 if (pipe_ctx->stream->signal != SIGNAL_TYPE_VIRTUAL)
1062 pipe_ctx->stream_enc->funcs->setup_stereo_sync(
1063 pipe_ctx->stream_enc,
1064 pipe_ctx->tg->inst,
1065 stream->public.timing.timing_3d_format != TIMING_3D_FORMAT_NONE);
1066
1067
1068 /*vbios crtc_source_selection and encoder_setup will override fmt_C*/
1069 pipe_ctx->opp->funcs->opp_program_fmt(
1070 pipe_ctx->opp,
1071 &stream->bit_depth_params,
1072 &stream->clamping);
1073
1074 if (dc_is_dp_signal(pipe_ctx->stream->signal))
1075 pipe_ctx->stream_enc->funcs->dp_set_stream_attribute(
1076 pipe_ctx->stream_enc,
1077 &stream->public.timing,
1078 stream->public.output_color_space);
1079
1080 if (dc_is_hdmi_signal(pipe_ctx->stream->signal))
1081 pipe_ctx->stream_enc->funcs->hdmi_set_stream_attribute(
1082 pipe_ctx->stream_enc,
1083 &stream->public.timing,
1084 stream->phy_pix_clk,
1085 pipe_ctx->audio != NULL);
1086
1087 if (dc_is_dvi_signal(pipe_ctx->stream->signal))
1088 pipe_ctx->stream_enc->funcs->dvi_set_stream_attribute(
1089 pipe_ctx->stream_enc,
1090 &stream->public.timing,
1091 (pipe_ctx->stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK) ?
1092 true : false);
1093
1094 if (!pipe_ctx_old->stream) {
1095 core_link_enable_stream(pipe_ctx);
1096
1097 resource_build_info_frame(pipe_ctx);
1098 dce110_update_info_frame(pipe_ctx);
1099 if (dc_is_dp_signal(pipe_ctx->stream->signal))
1100 dce110_unblank_stream(pipe_ctx,
1101 &stream->sink->link->public.cur_link_settings);
1102 }
1103
1104 pipe_ctx->scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0;
1105 /* program_scaler and allocate_mem_input are not new asic */
1106 if ((!pipe_ctx_old ||
1107 memcmp(&pipe_ctx_old->scl_data, &pipe_ctx->scl_data,
1108 sizeof(struct scaler_data)) != 0) &&
1109 pipe_ctx->surface) {
1110 program_scaler(dc, pipe_ctx);
1111 }
1112
1113 /* mst support - use total stream count */
1114 #if defined(CONFIG_DRM_AMD_DC_DCN1_0)
1115 if (pipe_ctx->mi->funcs->allocate_mem_input != NULL)
1116 #endif
1117 pipe_ctx->mi->funcs->allocate_mem_input(
1118 pipe_ctx->mi,
1119 stream->public.timing.h_total,
1120 stream->public.timing.v_total,
1121 stream->public.timing.pix_clk_khz,
1122 context->stream_count);
1123
1124 pipe_ctx->stream->sink->link->psr_enabled = false;
1125
1126 return DC_OK;
1127 }
1128
1129 /******************************************************************************/
1130
1131 static void power_down_encoders(struct core_dc *dc)
1132 {
1133 int i;
1134
1135 for (i = 0; i < dc->link_count; i++) {
1136 dc->links[i]->link_enc->funcs->disable_output(
1137 dc->links[i]->link_enc, SIGNAL_TYPE_NONE);
1138 }
1139 }
1140
1141 static void power_down_controllers(struct core_dc *dc)
1142 {
1143 int i;
1144
1145 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1146 dc->res_pool->timing_generators[i]->funcs->disable_crtc(
1147 dc->res_pool->timing_generators[i]);
1148 }
1149 }
1150
1151 static void power_down_clock_sources(struct core_dc *dc)
1152 {
1153 int i;
1154
1155 if (dc->res_pool->dp_clock_source->funcs->cs_power_down(
1156 dc->res_pool->dp_clock_source) == false)
1157 dm_error("Failed to power down pll! (dp clk src)\n");
1158
1159 for (i = 0; i < dc->res_pool->clk_src_count; i++) {
1160 if (dc->res_pool->clock_sources[i]->funcs->cs_power_down(
1161 dc->res_pool->clock_sources[i]) == false)
1162 dm_error("Failed to power down pll! (clk src index=%d)\n", i);
1163 }
1164 }
1165
1166 static void power_down_all_hw_blocks(struct core_dc *dc)
1167 {
1168 power_down_encoders(dc);
1169
1170 power_down_controllers(dc);
1171
1172 power_down_clock_sources(dc);
1173
1174 #ifdef ENABLE_FBC
1175 dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor);
1176 #endif
1177 }
1178
1179 static void disable_vga_and_power_gate_all_controllers(
1180 struct core_dc *dc)
1181 {
1182 int i;
1183 struct timing_generator *tg;
1184 struct dc_context *ctx = dc->ctx;
1185
1186 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1187 tg = dc->res_pool->timing_generators[i];
1188
1189 tg->funcs->disable_vga(tg);
1190
1191 /* Enable CLOCK gating for each pipe BEFORE controller
1192 * powergating. */
1193 enable_display_pipe_clock_gating(ctx,
1194 true);
1195
1196 dc->hwss.power_down_front_end(dc, i);
1197 }
1198 }
1199
1200 /**
1201 * When ASIC goes from VBIOS/VGA mode to driver/accelerated mode we need:
1202 * 1. Power down all DC HW blocks
1203 * 2. Disable VGA engine on all controllers
1204 * 3. Enable power gating for controller
1205 * 4. Set acc_mode_change bit (VBIOS will clear this bit when going to FSDOS)
1206 */
1207 void dce110_enable_accelerated_mode(struct core_dc *dc)
1208 {
1209 power_down_all_hw_blocks(dc);
1210
1211 disable_vga_and_power_gate_all_controllers(dc);
1212 bios_set_scratch_acc_mode_change(dc->ctx->dc_bios);
1213 }
1214
1215 static uint32_t compute_pstate_blackout_duration(
1216 struct bw_fixed blackout_duration,
1217 const struct core_stream *stream)
1218 {
1219 uint32_t total_dest_line_time_ns;
1220 uint32_t pstate_blackout_duration_ns;
1221
1222 pstate_blackout_duration_ns = 1000 * blackout_duration.value >> 24;
1223
1224 total_dest_line_time_ns = 1000000UL *
1225 stream->public.timing.h_total /
1226 stream->public.timing.pix_clk_khz +
1227 pstate_blackout_duration_ns;
1228
1229 return total_dest_line_time_ns;
1230 }
1231
1232 void dce110_set_displaymarks(
1233 const struct core_dc *dc,
1234 struct validate_context *context)
1235 {
1236 uint8_t i, num_pipes;
1237 unsigned int underlay_idx = dc->res_pool->underlay_pipe_index;
1238
1239 for (i = 0, num_pipes = 0; i < MAX_PIPES; i++) {
1240 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1241 uint32_t total_dest_line_time_ns;
1242
1243 if (pipe_ctx->stream == NULL)
1244 continue;
1245
1246 total_dest_line_time_ns = compute_pstate_blackout_duration(
1247 dc->bw_vbios.blackout_duration, pipe_ctx->stream);
1248 pipe_ctx->mi->funcs->mem_input_program_display_marks(
1249 pipe_ctx->mi,
1250 context->bw.dce.nbp_state_change_wm_ns[num_pipes],
1251 context->bw.dce.stutter_exit_wm_ns[num_pipes],
1252 context->bw.dce.urgent_wm_ns[num_pipes],
1253 total_dest_line_time_ns);
1254 if (i == underlay_idx) {
1255 num_pipes++;
1256 pipe_ctx->mi->funcs->mem_input_program_chroma_display_marks(
1257 pipe_ctx->mi,
1258 context->bw.dce.nbp_state_change_wm_ns[num_pipes],
1259 context->bw.dce.stutter_exit_wm_ns[num_pipes],
1260 context->bw.dce.urgent_wm_ns[num_pipes],
1261 total_dest_line_time_ns);
1262 }
1263 num_pipes++;
1264 }
1265 }
1266
1267 static void set_safe_displaymarks(
1268 struct resource_context *res_ctx,
1269 const struct resource_pool *pool)
1270 {
1271 int i;
1272 int underlay_idx = pool->underlay_pipe_index;
1273 struct dce_watermarks max_marks = {
1274 MAX_WATERMARK, MAX_WATERMARK, MAX_WATERMARK, MAX_WATERMARK };
1275 struct dce_watermarks nbp_marks = {
1276 SAFE_NBP_MARK, SAFE_NBP_MARK, SAFE_NBP_MARK, SAFE_NBP_MARK };
1277
1278 for (i = 0; i < MAX_PIPES; i++) {
1279 if (res_ctx->pipe_ctx[i].stream == NULL)
1280 continue;
1281
1282 res_ctx->pipe_ctx[i].mi->funcs->mem_input_program_display_marks(
1283 res_ctx->pipe_ctx[i].mi,
1284 nbp_marks,
1285 max_marks,
1286 max_marks,
1287 MAX_WATERMARK);
1288 if (i == underlay_idx)
1289 res_ctx->pipe_ctx[i].mi->funcs->mem_input_program_chroma_display_marks(
1290 res_ctx->pipe_ctx[i].mi,
1291 nbp_marks,
1292 max_marks,
1293 max_marks,
1294 MAX_WATERMARK);
1295 }
1296 }
1297
1298 static void switch_dp_clock_sources(
1299 const struct core_dc *dc,
1300 struct resource_context *res_ctx)
1301 {
1302 uint8_t i;
1303 for (i = 0; i < MAX_PIPES; i++) {
1304 struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
1305
1306 if (pipe_ctx->stream == NULL || pipe_ctx->top_pipe)
1307 continue;
1308
1309 if (dc_is_dp_signal(pipe_ctx->stream->signal)) {
1310 struct clock_source *clk_src =
1311 resource_find_used_clk_src_for_sharing(
1312 res_ctx, pipe_ctx);
1313
1314 if (clk_src &&
1315 clk_src != pipe_ctx->clock_source) {
1316 resource_unreference_clock_source(
1317 res_ctx, dc->res_pool,
1318 &pipe_ctx->clock_source);
1319 pipe_ctx->clock_source = clk_src;
1320 resource_reference_clock_source(
1321 res_ctx, dc->res_pool, clk_src);
1322
1323 dce_crtc_switch_to_clk_src(dc->hwseq, clk_src, i);
1324 }
1325 }
1326 }
1327 }
1328
1329 /*******************************************************************************
1330 * Public functions
1331 ******************************************************************************/
1332
1333 static void reset_single_pipe_hw_ctx(
1334 const struct core_dc *dc,
1335 struct pipe_ctx *pipe_ctx,
1336 struct validate_context *context)
1337 {
1338 core_link_disable_stream(pipe_ctx);
1339 pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, true);
1340 if (!hwss_wait_for_blank_complete(pipe_ctx->tg)) {
1341 dm_error("DC: failed to blank crtc!\n");
1342 BREAK_TO_DEBUGGER();
1343 }
1344 pipe_ctx->tg->funcs->disable_crtc(pipe_ctx->tg);
1345 pipe_ctx->mi->funcs->free_mem_input(
1346 pipe_ctx->mi, context->stream_count);
1347 resource_unreference_clock_source(&context->res_ctx, dc->res_pool,
1348 &pipe_ctx->clock_source);
1349
1350 dc->hwss.power_down_front_end((struct core_dc *)dc, pipe_ctx->pipe_idx);
1351
1352 pipe_ctx->stream = NULL;
1353 }
1354
1355 static void set_drr(struct pipe_ctx **pipe_ctx,
1356 int num_pipes, int vmin, int vmax)
1357 {
1358 int i = 0;
1359 struct drr_params params = {0};
1360
1361 params.vertical_total_max = vmax;
1362 params.vertical_total_min = vmin;
1363
1364 /* TODO: If multiple pipes are to be supported, you need
1365 * some GSL stuff
1366 */
1367
1368 for (i = 0; i < num_pipes; i++) {
1369 pipe_ctx[i]->tg->funcs->set_drr(pipe_ctx[i]->tg, &params);
1370 }
1371 }
1372
1373 static void get_position(struct pipe_ctx **pipe_ctx,
1374 int num_pipes,
1375 struct crtc_position *position)
1376 {
1377 int i = 0;
1378
1379 /* TODO: handle pipes > 1
1380 */
1381 for (i = 0; i < num_pipes; i++)
1382 pipe_ctx[i]->tg->funcs->get_position(pipe_ctx[i]->tg, position);
1383 }
1384
1385 static void set_static_screen_control(struct pipe_ctx **pipe_ctx,
1386 int num_pipes, const struct dc_static_screen_events *events)
1387 {
1388 unsigned int i;
1389 unsigned int value = 0;
1390
1391 if (events->overlay_update)
1392 value |= 0x100;
1393 if (events->surface_update)
1394 value |= 0x80;
1395 if (events->cursor_update)
1396 value |= 0x2;
1397
1398 for (i = 0; i < num_pipes; i++)
1399 pipe_ctx[i]->tg->funcs->
1400 set_static_screen_control(pipe_ctx[i]->tg, value);
1401 }
1402
1403 /* unit: in_khz before mode set, get pixel clock from context. ASIC register
1404 * may not be programmed yet.
1405 * TODO: after mode set, pre_mode_set = false,
1406 * may read PLL register to get pixel clock
1407 */
1408 static uint32_t get_max_pixel_clock_for_all_paths(
1409 struct core_dc *dc,
1410 struct validate_context *context,
1411 bool pre_mode_set)
1412 {
1413 uint32_t max_pix_clk = 0;
1414 int i;
1415
1416 if (!pre_mode_set) {
1417 /* TODO: read ASIC register to get pixel clock */
1418 ASSERT(0);
1419 }
1420
1421 for (i = 0; i < MAX_PIPES; i++) {
1422 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1423
1424 if (pipe_ctx->stream == NULL)
1425 continue;
1426
1427 /* do not check under lay */
1428 if (pipe_ctx->top_pipe)
1429 continue;
1430
1431 if (pipe_ctx->pix_clk_params.requested_pix_clk > max_pix_clk)
1432 max_pix_clk =
1433 pipe_ctx->pix_clk_params.requested_pix_clk;
1434 }
1435
1436 if (max_pix_clk == 0)
1437 ASSERT(0);
1438
1439 return max_pix_clk;
1440 }
1441
1442 /* Find clock state based on clock requested. if clock value is 0, simply
1443 * set clock state as requested without finding clock state by clock value
1444 *TODO: when dce120_hw_sequencer.c is created, override apply_min_clock.
1445 *
1446 * TODOFPGA remove TODO after implement dal_display_clock_get_cur_clocks_value
1447 * etc support for dcn1.0
1448 */
1449 static void apply_min_clocks(
1450 struct core_dc *dc,
1451 struct validate_context *context,
1452 enum dm_pp_clocks_state *clocks_state,
1453 bool pre_mode_set)
1454 {
1455 struct state_dependent_clocks req_clocks = {0};
1456 struct pipe_ctx *pipe_ctx;
1457 int i;
1458
1459 for (i = 0; i < MAX_PIPES; i++) {
1460 pipe_ctx = &context->res_ctx.pipe_ctx[i];
1461 if (pipe_ctx->dis_clk != NULL)
1462 break;
1463 }
1464
1465 if (!pre_mode_set) {
1466 /* set clock_state without verification */
1467 if (pipe_ctx->dis_clk->funcs->set_min_clocks_state) {
1468 pipe_ctx->dis_clk->funcs->set_min_clocks_state(
1469 pipe_ctx->dis_clk, *clocks_state);
1470 return;
1471 }
1472
1473 /* TODO: This is incorrect. Figure out how to fix. */
1474 pipe_ctx->dis_clk->funcs->apply_clock_voltage_request(
1475 pipe_ctx->dis_clk,
1476 DM_PP_CLOCK_TYPE_DISPLAY_CLK,
1477 pipe_ctx->dis_clk->cur_clocks_value.dispclk_in_khz,
1478 pre_mode_set,
1479 false);
1480
1481 pipe_ctx->dis_clk->funcs->apply_clock_voltage_request(
1482 pipe_ctx->dis_clk,
1483 DM_PP_CLOCK_TYPE_PIXELCLK,
1484 pipe_ctx->dis_clk->cur_clocks_value.max_pixelclk_in_khz,
1485 pre_mode_set,
1486 false);
1487
1488 pipe_ctx->dis_clk->funcs->apply_clock_voltage_request(
1489 pipe_ctx->dis_clk,
1490 DM_PP_CLOCK_TYPE_DISPLAYPHYCLK,
1491 pipe_ctx->dis_clk->cur_clocks_value.max_non_dp_phyclk_in_khz,
1492 pre_mode_set,
1493 false);
1494 return;
1495 }
1496
1497 /* get the required state based on state dependent clocks:
1498 * display clock and pixel clock
1499 */
1500 req_clocks.display_clk_khz = context->bw.dce.dispclk_khz;
1501
1502 req_clocks.pixel_clk_khz = get_max_pixel_clock_for_all_paths(
1503 dc, context, true);
1504
1505 if (pipe_ctx->dis_clk->funcs->get_required_clocks_state) {
1506 *clocks_state = pipe_ctx->dis_clk->funcs->get_required_clocks_state(
1507 pipe_ctx->dis_clk, &req_clocks);
1508 pipe_ctx->dis_clk->funcs->set_min_clocks_state(
1509 pipe_ctx->dis_clk, *clocks_state);
1510 } else {
1511 pipe_ctx->dis_clk->funcs->apply_clock_voltage_request(
1512 pipe_ctx->dis_clk,
1513 DM_PP_CLOCK_TYPE_DISPLAY_CLK,
1514 req_clocks.display_clk_khz,
1515 pre_mode_set,
1516 false);
1517
1518 pipe_ctx->dis_clk->funcs->apply_clock_voltage_request(
1519 pipe_ctx->dis_clk,
1520 DM_PP_CLOCK_TYPE_PIXELCLK,
1521 req_clocks.pixel_clk_khz,
1522 pre_mode_set,
1523 false);
1524
1525 pipe_ctx->dis_clk->funcs->apply_clock_voltage_request(
1526 pipe_ctx->dis_clk,
1527 DM_PP_CLOCK_TYPE_DISPLAYPHYCLK,
1528 req_clocks.pixel_clk_khz,
1529 pre_mode_set,
1530 false);
1531 }
1532 }
1533
1534 static enum dc_status apply_ctx_to_hw_fpga(
1535 struct core_dc *dc,
1536 struct validate_context *context)
1537 {
1538 enum dc_status status = DC_ERROR_UNEXPECTED;
1539 int i;
1540
1541 for (i = 0; i < MAX_PIPES; i++) {
1542 struct pipe_ctx *pipe_ctx_old =
1543 &dc->current_context->res_ctx.pipe_ctx[i];
1544 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1545
1546 if (pipe_ctx->stream == NULL)
1547 continue;
1548
1549 if (pipe_ctx->stream == pipe_ctx_old->stream)
1550 continue;
1551
1552 status = apply_single_controller_ctx_to_hw(
1553 pipe_ctx,
1554 context,
1555 dc);
1556
1557 if (status != DC_OK)
1558 return status;
1559 }
1560
1561 return DC_OK;
1562 }
1563
1564 static void reset_hw_ctx_wrap(
1565 struct core_dc *dc,
1566 struct validate_context *context)
1567 {
1568 int i;
1569
1570 /* Reset old context */
1571 /* look up the targets that have been removed since last commit */
1572 for (i = 0; i < MAX_PIPES; i++) {
1573 struct pipe_ctx *pipe_ctx_old =
1574 &dc->current_context->res_ctx.pipe_ctx[i];
1575 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1576
1577 /* Note: We need to disable output if clock sources change,
1578 * since bios does optimization and doesn't apply if changing
1579 * PHY when not already disabled.
1580 */
1581
1582 /* Skip underlay pipe since it will be handled in commit surface*/
1583 if (!pipe_ctx_old->stream || pipe_ctx_old->top_pipe)
1584 continue;
1585
1586 if (!pipe_ctx->stream ||
1587 pipe_need_reprogram(pipe_ctx_old, pipe_ctx))
1588 reset_single_pipe_hw_ctx(
1589 dc, pipe_ctx_old, dc->current_context);
1590 }
1591 }
1592
1593
1594 enum dc_status dce110_apply_ctx_to_hw(
1595 struct core_dc *dc,
1596 struct validate_context *context)
1597 {
1598 struct dc_bios *dcb = dc->ctx->dc_bios;
1599 enum dc_status status;
1600 int i;
1601 enum dm_pp_clocks_state clocks_state = DM_PP_CLOCKS_STATE_INVALID;
1602
1603 /* Reset old context */
1604 /* look up the targets that have been removed since last commit */
1605 dc->hwss.reset_hw_ctx_wrap(dc, context);
1606
1607 /* Skip applying if no targets */
1608 if (context->stream_count <= 0)
1609 return DC_OK;
1610
1611 if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
1612 apply_ctx_to_hw_fpga(dc, context);
1613 return DC_OK;
1614 }
1615
1616 /* Apply new context */
1617 dcb->funcs->set_scratch_critical_state(dcb, true);
1618
1619 /* below is for real asic only */
1620 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1621 struct pipe_ctx *pipe_ctx_old =
1622 &dc->current_context->res_ctx.pipe_ctx[i];
1623 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1624
1625 if (pipe_ctx->stream == NULL || pipe_ctx->top_pipe)
1626 continue;
1627
1628 if (pipe_ctx->stream == pipe_ctx_old->stream) {
1629 if (pipe_ctx_old->clock_source != pipe_ctx->clock_source)
1630 dce_crtc_switch_to_clk_src(dc->hwseq,
1631 pipe_ctx->clock_source, i);
1632 continue;
1633 }
1634
1635 dc->hwss.enable_display_power_gating(
1636 dc, i, dc->ctx->dc_bios,
1637 PIPE_GATING_CONTROL_DISABLE);
1638 }
1639
1640 set_safe_displaymarks(&context->res_ctx, dc->res_pool);
1641
1642 #ifdef ENABLE_FBC
1643 dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor);
1644 #endif
1645 /*TODO: when pplib works*/
1646 apply_min_clocks(dc, context, &clocks_state, true);
1647
1648 #if defined(CONFIG_DRM_AMD_DC_DCN1_0)
1649 if (dc->ctx->dce_version == DCN_VERSION_1_0) {
1650 if (context->bw.dcn.calc_clk.fclk_khz
1651 > dc->current_context->bw.dcn.cur_clk.fclk_khz) {
1652 struct dm_pp_clock_for_voltage_req clock;
1653
1654 clock.clk_type = DM_PP_CLOCK_TYPE_FCLK;
1655 clock.clocks_in_khz = context->bw.dcn.calc_clk.fclk_khz;
1656 dm_pp_apply_clock_for_voltage_request(dc->ctx, &clock);
1657 dc->current_context->bw.dcn.cur_clk.fclk_khz = clock.clocks_in_khz;
1658 context->bw.dcn.cur_clk.fclk_khz = clock.clocks_in_khz;
1659 }
1660 if (context->bw.dcn.calc_clk.dcfclk_khz
1661 > dc->current_context->bw.dcn.cur_clk.dcfclk_khz) {
1662 struct dm_pp_clock_for_voltage_req clock;
1663
1664 clock.clk_type = DM_PP_CLOCK_TYPE_DCFCLK;
1665 clock.clocks_in_khz = context->bw.dcn.calc_clk.dcfclk_khz;
1666 dm_pp_apply_clock_for_voltage_request(dc->ctx, &clock);
1667 dc->current_context->bw.dcn.cur_clk.dcfclk_khz = clock.clocks_in_khz;
1668 context->bw.dcn.cur_clk.dcfclk_khz = clock.clocks_in_khz;
1669 }
1670 if (context->bw.dcn.calc_clk.dispclk_khz
1671 > dc->current_context->bw.dcn.cur_clk.dispclk_khz) {
1672 dc->res_pool->display_clock->funcs->set_clock(
1673 dc->res_pool->display_clock,
1674 context->bw.dcn.calc_clk.dispclk_khz);
1675 dc->current_context->bw.dcn.cur_clk.dispclk_khz =
1676 context->bw.dcn.calc_clk.dispclk_khz;
1677 context->bw.dcn.cur_clk.dispclk_khz =
1678 context->bw.dcn.calc_clk.dispclk_khz;
1679 }
1680 } else
1681 #endif
1682 if (context->bw.dce.dispclk_khz
1683 > dc->current_context->bw.dce.dispclk_khz) {
1684 dc->res_pool->display_clock->funcs->set_clock(
1685 dc->res_pool->display_clock,
1686 context->bw.dce.dispclk_khz * 115 / 100);
1687 }
1688 /* program audio wall clock. use HDMI as clock source if HDMI
1689 * audio active. Otherwise, use DP as clock source
1690 * first, loop to find any HDMI audio, if not, loop find DP audio
1691 */
1692 /* Setup audio rate clock source */
1693 /* Issue:
1694 * Audio lag happened on DP monitor when unplug a HDMI monitor
1695 *
1696 * Cause:
1697 * In case of DP and HDMI connected or HDMI only, DCCG_AUDIO_DTO_SEL
1698 * is set to either dto0 or dto1, audio should work fine.
1699 * In case of DP connected only, DCCG_AUDIO_DTO_SEL should be dto1,
1700 * set to dto0 will cause audio lag.
1701 *
1702 * Solution:
1703 * Not optimized audio wall dto setup. When mode set, iterate pipe_ctx,
1704 * find first available pipe with audio, setup audio wall DTO per topology
1705 * instead of per pipe.
1706 */
1707 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1708 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1709
1710 if (pipe_ctx->stream == NULL)
1711 continue;
1712
1713 if (pipe_ctx->top_pipe)
1714 continue;
1715
1716 if (pipe_ctx->stream->signal != SIGNAL_TYPE_HDMI_TYPE_A)
1717 continue;
1718
1719 if (pipe_ctx->audio != NULL) {
1720 struct audio_output audio_output;
1721
1722 build_audio_output(pipe_ctx, &audio_output);
1723
1724 pipe_ctx->audio->funcs->wall_dto_setup(
1725 pipe_ctx->audio,
1726 pipe_ctx->stream->signal,
1727 &audio_output.crtc_info,
1728 &audio_output.pll_info);
1729 break;
1730 }
1731 }
1732
1733 /* no HDMI audio is found, try DP audio */
1734 if (i == dc->res_pool->pipe_count) {
1735 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1736 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1737
1738 if (pipe_ctx->stream == NULL)
1739 continue;
1740
1741 if (pipe_ctx->top_pipe)
1742 continue;
1743
1744 if (!dc_is_dp_signal(pipe_ctx->stream->signal))
1745 continue;
1746
1747 if (pipe_ctx->audio != NULL) {
1748 struct audio_output audio_output;
1749
1750 build_audio_output(pipe_ctx, &audio_output);
1751
1752 pipe_ctx->audio->funcs->wall_dto_setup(
1753 pipe_ctx->audio,
1754 pipe_ctx->stream->signal,
1755 &audio_output.crtc_info,
1756 &audio_output.pll_info);
1757 break;
1758 }
1759 }
1760 }
1761
1762 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1763 struct pipe_ctx *pipe_ctx_old =
1764 &dc->current_context->res_ctx.pipe_ctx[i];
1765 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1766
1767 if (pipe_ctx->stream == NULL)
1768 continue;
1769
1770 if (pipe_ctx->stream == pipe_ctx_old->stream)
1771 continue;
1772
1773 if (pipe_ctx->stream && pipe_ctx_old->stream
1774 && !pipe_need_reprogram(pipe_ctx_old, pipe_ctx))
1775 continue;
1776
1777 if (pipe_ctx->top_pipe)
1778 continue;
1779
1780 if (context->res_ctx.pipe_ctx[i].audio != NULL) {
1781
1782 struct audio_output audio_output;
1783
1784 build_audio_output(pipe_ctx, &audio_output);
1785
1786 if (dc_is_dp_signal(pipe_ctx->stream->signal))
1787 pipe_ctx->stream_enc->funcs->dp_audio_setup(
1788 pipe_ctx->stream_enc,
1789 pipe_ctx->audio->inst,
1790 &pipe_ctx->stream->public.audio_info);
1791 else
1792 pipe_ctx->stream_enc->funcs->hdmi_audio_setup(
1793 pipe_ctx->stream_enc,
1794 pipe_ctx->audio->inst,
1795 &pipe_ctx->stream->public.audio_info,
1796 &audio_output.crtc_info);
1797
1798 pipe_ctx->audio->funcs->az_configure(
1799 pipe_ctx->audio,
1800 pipe_ctx->stream->signal,
1801 &audio_output.crtc_info,
1802 &pipe_ctx->stream->public.audio_info);
1803 }
1804
1805 status = apply_single_controller_ctx_to_hw(
1806 pipe_ctx,
1807 context,
1808 dc);
1809
1810 if (dc->hwss.power_on_front_end)
1811 dc->hwss.power_on_front_end(dc, pipe_ctx, context);
1812
1813 if (DC_OK != status)
1814 return status;
1815 }
1816
1817 dc->hwss.set_bandwidth(dc, context, true);
1818
1819 /* to save power */
1820 apply_min_clocks(dc, context, &clocks_state, false);
1821
1822 dcb->funcs->set_scratch_critical_state(dcb, false);
1823
1824 switch_dp_clock_sources(dc, &context->res_ctx);
1825
1826
1827 return DC_OK;
1828 }
1829
1830 /*******************************************************************************
1831 * Front End programming
1832 ******************************************************************************/
1833 static void set_default_colors(struct pipe_ctx *pipe_ctx)
1834 {
1835 struct default_adjustment default_adjust = { 0 };
1836
1837 default_adjust.force_hw_default = false;
1838 if (pipe_ctx->surface == NULL)
1839 default_adjust.in_color_space = COLOR_SPACE_SRGB;
1840 else
1841 default_adjust.in_color_space =
1842 pipe_ctx->surface->public.color_space;
1843 if (pipe_ctx->stream == NULL)
1844 default_adjust.out_color_space = COLOR_SPACE_SRGB;
1845 else
1846 default_adjust.out_color_space =
1847 pipe_ctx->stream->public.output_color_space;
1848 default_adjust.csc_adjust_type = GRAPHICS_CSC_ADJUST_TYPE_SW;
1849 default_adjust.surface_pixel_format = pipe_ctx->scl_data.format;
1850
1851 /* display color depth */
1852 default_adjust.color_depth =
1853 pipe_ctx->stream->public.timing.display_color_depth;
1854
1855 /* Lb color depth */
1856 default_adjust.lb_color_depth = pipe_ctx->scl_data.lb_params.depth;
1857
1858 pipe_ctx->opp->funcs->opp_set_csc_default(
1859 pipe_ctx->opp, &default_adjust);
1860 }
1861
1862
1863 /*******************************************************************************
1864 * In order to turn on/off specific surface we will program
1865 * Blender + CRTC
1866 *
1867 * In case that we have two surfaces and they have a different visibility
1868 * we can't turn off the CRTC since it will turn off the entire display
1869 *
1870 * |----------------------------------------------- |
1871 * |bottom pipe|curr pipe | | |
1872 * |Surface |Surface | Blender | CRCT |
1873 * |visibility |visibility | Configuration| |
1874 * |------------------------------------------------|
1875 * | off | off | CURRENT_PIPE | blank |
1876 * | off | on | CURRENT_PIPE | unblank |
1877 * | on | off | OTHER_PIPE | unblank |
1878 * | on | on | BLENDING | unblank |
1879 * -------------------------------------------------|
1880 *
1881 ******************************************************************************/
1882 static void program_surface_visibility(const struct core_dc *dc,
1883 struct pipe_ctx *pipe_ctx)
1884 {
1885 enum blnd_mode blender_mode = BLND_MODE_CURRENT_PIPE;
1886 bool blank_target = false;
1887
1888 if (pipe_ctx->bottom_pipe) {
1889
1890 /* For now we are supporting only two pipes */
1891 ASSERT(pipe_ctx->bottom_pipe->bottom_pipe == NULL);
1892
1893 if (pipe_ctx->bottom_pipe->surface->public.visible) {
1894 if (pipe_ctx->surface->public.visible)
1895 blender_mode = BLND_MODE_BLENDING;
1896 else
1897 blender_mode = BLND_MODE_OTHER_PIPE;
1898
1899 } else if (!pipe_ctx->surface->public.visible)
1900 blank_target = true;
1901
1902 } else if (!pipe_ctx->surface->public.visible)
1903 blank_target = true;
1904
1905 dce_set_blender_mode(dc->hwseq, pipe_ctx->pipe_idx, blender_mode);
1906 pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, blank_target);
1907
1908 }
1909
1910 static void program_gamut_remap(struct pipe_ctx *pipe_ctx)
1911 {
1912 struct xfm_grph_csc_adjustment adjust;
1913 memset(&adjust, 0, sizeof(adjust));
1914 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS;
1915
1916
1917 if (pipe_ctx->stream->public.gamut_remap_matrix.enable_remap == true) {
1918 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW;
1919 adjust.temperature_matrix[0] =
1920 pipe_ctx->stream->
1921 public.gamut_remap_matrix.matrix[0];
1922 adjust.temperature_matrix[1] =
1923 pipe_ctx->stream->
1924 public.gamut_remap_matrix.matrix[1];
1925 adjust.temperature_matrix[2] =
1926 pipe_ctx->stream->
1927 public.gamut_remap_matrix.matrix[2];
1928 adjust.temperature_matrix[3] =
1929 pipe_ctx->stream->
1930 public.gamut_remap_matrix.matrix[4];
1931 adjust.temperature_matrix[4] =
1932 pipe_ctx->stream->
1933 public.gamut_remap_matrix.matrix[5];
1934 adjust.temperature_matrix[5] =
1935 pipe_ctx->stream->
1936 public.gamut_remap_matrix.matrix[6];
1937 adjust.temperature_matrix[6] =
1938 pipe_ctx->stream->
1939 public.gamut_remap_matrix.matrix[8];
1940 adjust.temperature_matrix[7] =
1941 pipe_ctx->stream->
1942 public.gamut_remap_matrix.matrix[9];
1943 adjust.temperature_matrix[8] =
1944 pipe_ctx->stream->
1945 public.gamut_remap_matrix.matrix[10];
1946 }
1947
1948 pipe_ctx->xfm->funcs->transform_set_gamut_remap(pipe_ctx->xfm, &adjust);
1949 }
1950
1951 /**
1952 * TODO REMOVE, USE UPDATE INSTEAD
1953 */
1954 static void set_plane_config(
1955 const struct core_dc *dc,
1956 struct pipe_ctx *pipe_ctx,
1957 struct resource_context *res_ctx)
1958 {
1959 struct mem_input *mi = pipe_ctx->mi;
1960 struct core_surface *surface = pipe_ctx->surface;
1961 struct xfm_grph_csc_adjustment adjust;
1962 struct out_csc_color_matrix tbl_entry;
1963 unsigned int i;
1964
1965 memset(&adjust, 0, sizeof(adjust));
1966 memset(&tbl_entry, 0, sizeof(tbl_entry));
1967 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS;
1968
1969 dce_enable_fe_clock(dc->hwseq, pipe_ctx->pipe_idx, true);
1970
1971 set_default_colors(pipe_ctx);
1972 if (pipe_ctx->stream->public.csc_color_matrix.enable_adjustment
1973 == true) {
1974 tbl_entry.color_space =
1975 pipe_ctx->stream->public.output_color_space;
1976
1977 for (i = 0; i < 12; i++)
1978 tbl_entry.regval[i] =
1979 pipe_ctx->stream->public.csc_color_matrix.matrix[i];
1980
1981 pipe_ctx->opp->funcs->opp_set_csc_adjustment
1982 (pipe_ctx->opp, &tbl_entry);
1983 }
1984
1985 if (pipe_ctx->stream->public.gamut_remap_matrix.enable_remap == true) {
1986 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW;
1987 adjust.temperature_matrix[0] =
1988 pipe_ctx->stream->
1989 public.gamut_remap_matrix.matrix[0];
1990 adjust.temperature_matrix[1] =
1991 pipe_ctx->stream->
1992 public.gamut_remap_matrix.matrix[1];
1993 adjust.temperature_matrix[2] =
1994 pipe_ctx->stream->
1995 public.gamut_remap_matrix.matrix[2];
1996 adjust.temperature_matrix[3] =
1997 pipe_ctx->stream->
1998 public.gamut_remap_matrix.matrix[4];
1999 adjust.temperature_matrix[4] =
2000 pipe_ctx->stream->
2001 public.gamut_remap_matrix.matrix[5];
2002 adjust.temperature_matrix[5] =
2003 pipe_ctx->stream->
2004 public.gamut_remap_matrix.matrix[6];
2005 adjust.temperature_matrix[6] =
2006 pipe_ctx->stream->
2007 public.gamut_remap_matrix.matrix[8];
2008 adjust.temperature_matrix[7] =
2009 pipe_ctx->stream->
2010 public.gamut_remap_matrix.matrix[9];
2011 adjust.temperature_matrix[8] =
2012 pipe_ctx->stream->
2013 public.gamut_remap_matrix.matrix[10];
2014 }
2015
2016 pipe_ctx->xfm->funcs->transform_set_gamut_remap(pipe_ctx->xfm, &adjust);
2017
2018 pipe_ctx->scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0;
2019 program_scaler(dc, pipe_ctx);
2020
2021 program_surface_visibility(dc, pipe_ctx);
2022
2023 mi->funcs->mem_input_program_surface_config(
2024 mi,
2025 surface->public.format,
2026 &surface->public.tiling_info,
2027 &surface->public.plane_size,
2028 surface->public.rotation,
2029 NULL,
2030 false);
2031 if (mi->funcs->set_blank)
2032 mi->funcs->set_blank(mi, pipe_ctx->surface->public.visible);
2033
2034 if (dc->public.config.gpu_vm_support)
2035 mi->funcs->mem_input_program_pte_vm(
2036 pipe_ctx->mi,
2037 surface->public.format,
2038 &surface->public.tiling_info,
2039 surface->public.rotation);
2040 }
2041
2042 static void update_plane_addr(const struct core_dc *dc,
2043 struct pipe_ctx *pipe_ctx)
2044 {
2045 struct core_surface *surface = pipe_ctx->surface;
2046
2047 if (surface == NULL)
2048 return;
2049
2050 pipe_ctx->mi->funcs->mem_input_program_surface_flip_and_addr(
2051 pipe_ctx->mi,
2052 &surface->public.address,
2053 surface->public.flip_immediate);
2054
2055 surface->status.requested_address = surface->public.address;
2056 }
2057
2058 void dce110_update_pending_status(struct pipe_ctx *pipe_ctx)
2059 {
2060 struct core_surface *surface = pipe_ctx->surface;
2061
2062 if (surface == NULL)
2063 return;
2064
2065 surface->status.is_flip_pending =
2066 pipe_ctx->mi->funcs->mem_input_is_flip_pending(
2067 pipe_ctx->mi);
2068
2069 if (surface->status.is_flip_pending && !surface->public.visible)
2070 pipe_ctx->mi->current_address = pipe_ctx->mi->request_address;
2071
2072 surface->status.current_address = pipe_ctx->mi->current_address;
2073 if (pipe_ctx->mi->current_address.type == PLN_ADDR_TYPE_GRPH_STEREO &&
2074 pipe_ctx->tg->funcs->is_stereo_left_eye) {
2075 surface->status.is_right_eye =\
2076 !pipe_ctx->tg->funcs->is_stereo_left_eye(pipe_ctx->tg);
2077 }
2078 }
2079
2080 void dce110_power_down(struct core_dc *dc)
2081 {
2082 power_down_all_hw_blocks(dc);
2083 disable_vga_and_power_gate_all_controllers(dc);
2084 }
2085
2086 static bool wait_for_reset_trigger_to_occur(
2087 struct dc_context *dc_ctx,
2088 struct timing_generator *tg)
2089 {
2090 bool rc = false;
2091
2092 /* To avoid endless loop we wait at most
2093 * frames_to_wait_on_triggered_reset frames for the reset to occur. */
2094 const uint32_t frames_to_wait_on_triggered_reset = 10;
2095 uint32_t i;
2096
2097 for (i = 0; i < frames_to_wait_on_triggered_reset; i++) {
2098
2099 if (!tg->funcs->is_counter_moving(tg)) {
2100 DC_ERROR("TG counter is not moving!\n");
2101 break;
2102 }
2103
2104 if (tg->funcs->did_triggered_reset_occur(tg)) {
2105 rc = true;
2106 /* usually occurs at i=1 */
2107 DC_SYNC_INFO("GSL: reset occurred at wait count: %d\n",
2108 i);
2109 break;
2110 }
2111
2112 /* Wait for one frame. */
2113 tg->funcs->wait_for_state(tg, CRTC_STATE_VACTIVE);
2114 tg->funcs->wait_for_state(tg, CRTC_STATE_VBLANK);
2115 }
2116
2117 if (false == rc)
2118 DC_ERROR("GSL: Timeout on reset trigger!\n");
2119
2120 return rc;
2121 }
2122
2123 /* Enable timing synchronization for a group of Timing Generators. */
2124 static void dce110_enable_timing_synchronization(
2125 struct core_dc *dc,
2126 int group_index,
2127 int group_size,
2128 struct pipe_ctx *grouped_pipes[])
2129 {
2130 struct dc_context *dc_ctx = dc->ctx;
2131 struct dcp_gsl_params gsl_params = { 0 };
2132 int i;
2133
2134 DC_SYNC_INFO("GSL: Setting-up...\n");
2135
2136 /* Designate a single TG in the group as a master.
2137 * Since HW doesn't care which one, we always assign
2138 * the 1st one in the group. */
2139 gsl_params.gsl_group = 0;
2140 gsl_params.gsl_master = grouped_pipes[0]->tg->inst;
2141
2142 for (i = 0; i < group_size; i++)
2143 grouped_pipes[i]->tg->funcs->setup_global_swap_lock(
2144 grouped_pipes[i]->tg, &gsl_params);
2145
2146 /* Reset slave controllers on master VSync */
2147 DC_SYNC_INFO("GSL: enabling trigger-reset\n");
2148
2149 for (i = 1 /* skip the master */; i < group_size; i++)
2150 grouped_pipes[i]->tg->funcs->enable_reset_trigger(
2151 grouped_pipes[i]->tg, gsl_params.gsl_group);
2152
2153
2154
2155 for (i = 1 /* skip the master */; i < group_size; i++) {
2156 DC_SYNC_INFO("GSL: waiting for reset to occur.\n");
2157 wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[i]->tg);
2158 /* Regardless of success of the wait above, remove the reset or
2159 * the driver will start timing out on Display requests. */
2160 DC_SYNC_INFO("GSL: disabling trigger-reset.\n");
2161 grouped_pipes[i]->tg->funcs->disable_reset_trigger(grouped_pipes[i]->tg);
2162 }
2163
2164
2165 /* GSL Vblank synchronization is a one time sync mechanism, assumption
2166 * is that the sync'ed displays will not drift out of sync over time*/
2167 DC_SYNC_INFO("GSL: Restoring register states.\n");
2168 for (i = 0; i < group_size; i++)
2169 grouped_pipes[i]->tg->funcs->tear_down_global_swap_lock(grouped_pipes[i]->tg);
2170
2171 DC_SYNC_INFO("GSL: Set-up complete.\n");
2172 }
2173
2174 static void init_hw(struct core_dc *dc)
2175 {
2176 int i;
2177 struct dc_bios *bp;
2178 struct transform *xfm;
2179 struct abm *abm;
2180
2181 bp = dc->ctx->dc_bios;
2182 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2183 xfm = dc->res_pool->transforms[i];
2184 xfm->funcs->transform_reset(xfm);
2185
2186 dc->hwss.enable_display_power_gating(
2187 dc, i, bp,
2188 PIPE_GATING_CONTROL_INIT);
2189 dc->hwss.enable_display_power_gating(
2190 dc, i, bp,
2191 PIPE_GATING_CONTROL_DISABLE);
2192 dc->hwss.enable_display_pipe_clock_gating(
2193 dc->ctx,
2194 true);
2195 }
2196
2197 dce_clock_gating_power_up(dc->hwseq, false);
2198 /***************************************/
2199
2200 for (i = 0; i < dc->link_count; i++) {
2201 /****************************************/
2202 /* Power up AND update implementation according to the
2203 * required signal (which may be different from the
2204 * default signal on connector). */
2205 struct core_link *link = dc->links[i];
2206 link->link_enc->funcs->hw_init(link->link_enc);
2207 }
2208
2209 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2210 struct timing_generator *tg = dc->res_pool->timing_generators[i];
2211
2212 tg->funcs->disable_vga(tg);
2213
2214 /* Blank controller using driver code instead of
2215 * command table. */
2216 tg->funcs->set_blank(tg, true);
2217 hwss_wait_for_blank_complete(tg);
2218 }
2219
2220 for (i = 0; i < dc->res_pool->audio_count; i++) {
2221 struct audio *audio = dc->res_pool->audios[i];
2222 audio->funcs->hw_init(audio);
2223 }
2224
2225 abm = dc->res_pool->abm;
2226 if (abm != NULL) {
2227 abm->funcs->init_backlight(abm);
2228 abm->funcs->abm_init(abm);
2229 }
2230 #ifdef ENABLE_FBC
2231 dc->fbc_compressor->funcs->power_up_fbc(dc->fbc_compressor);
2232 #endif
2233 }
2234
2235 void dce110_fill_display_configs(
2236 const struct validate_context *context,
2237 struct dm_pp_display_configuration *pp_display_cfg)
2238 {
2239 int j;
2240 int num_cfgs = 0;
2241
2242 for (j = 0; j < context->stream_count; j++) {
2243 int k;
2244
2245 const struct core_stream *stream = context->streams[j];
2246 struct dm_pp_single_disp_config *cfg =
2247 &pp_display_cfg->disp_configs[num_cfgs];
2248 const struct pipe_ctx *pipe_ctx = NULL;
2249
2250 for (k = 0; k < MAX_PIPES; k++)
2251 if (stream == context->res_ctx.pipe_ctx[k].stream) {
2252 pipe_ctx = &context->res_ctx.pipe_ctx[k];
2253 break;
2254 }
2255
2256 ASSERT(pipe_ctx != NULL);
2257
2258 num_cfgs++;
2259 cfg->signal = pipe_ctx->stream->signal;
2260 cfg->pipe_idx = pipe_ctx->pipe_idx;
2261 cfg->src_height = stream->public.src.height;
2262 cfg->src_width = stream->public.src.width;
2263 cfg->ddi_channel_mapping =
2264 stream->sink->link->ddi_channel_mapping.raw;
2265 cfg->transmitter =
2266 stream->sink->link->link_enc->transmitter;
2267 cfg->link_settings.lane_count =
2268 stream->sink->link->public.cur_link_settings.lane_count;
2269 cfg->link_settings.link_rate =
2270 stream->sink->link->public.cur_link_settings.link_rate;
2271 cfg->link_settings.link_spread =
2272 stream->sink->link->public.cur_link_settings.link_spread;
2273 cfg->sym_clock = stream->phy_pix_clk;
2274 /* Round v_refresh*/
2275 cfg->v_refresh = stream->public.timing.pix_clk_khz * 1000;
2276 cfg->v_refresh /= stream->public.timing.h_total;
2277 cfg->v_refresh = (cfg->v_refresh + stream->public.timing.v_total / 2)
2278 / stream->public.timing.v_total;
2279 }
2280
2281 pp_display_cfg->display_count = num_cfgs;
2282 }
2283
2284 uint32_t dce110_get_min_vblank_time_us(const struct validate_context *context)
2285 {
2286 uint8_t j;
2287 uint32_t min_vertical_blank_time = -1;
2288
2289 for (j = 0; j < context->stream_count; j++) {
2290 const struct dc_stream *stream = &context->streams[j]->public;
2291 uint32_t vertical_blank_in_pixels = 0;
2292 uint32_t vertical_blank_time = 0;
2293
2294 vertical_blank_in_pixels = stream->timing.h_total *
2295 (stream->timing.v_total
2296 - stream->timing.v_addressable);
2297
2298 vertical_blank_time = vertical_blank_in_pixels
2299 * 1000 / stream->timing.pix_clk_khz;
2300
2301 if (min_vertical_blank_time > vertical_blank_time)
2302 min_vertical_blank_time = vertical_blank_time;
2303 }
2304
2305 return min_vertical_blank_time;
2306 }
2307
2308 static int determine_sclk_from_bounding_box(
2309 const struct core_dc *dc,
2310 int required_sclk)
2311 {
2312 int i;
2313
2314 /*
2315 * Some asics do not give us sclk levels, so we just report the actual
2316 * required sclk
2317 */
2318 if (dc->sclk_lvls.num_levels == 0)
2319 return required_sclk;
2320
2321 for (i = 0; i < dc->sclk_lvls.num_levels; i++) {
2322 if (dc->sclk_lvls.clocks_in_khz[i] >= required_sclk)
2323 return dc->sclk_lvls.clocks_in_khz[i];
2324 }
2325 /*
2326 * even maximum level could not satisfy requirement, this
2327 * is unexpected at this stage, should have been caught at
2328 * validation time
2329 */
2330 ASSERT(0);
2331 return dc->sclk_lvls.clocks_in_khz[dc->sclk_lvls.num_levels - 1];
2332 }
2333
2334 static void pplib_apply_display_requirements(
2335 struct core_dc *dc,
2336 struct validate_context *context)
2337 {
2338 struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg;
2339
2340 pp_display_cfg->all_displays_in_sync =
2341 context->bw.dce.all_displays_in_sync;
2342 pp_display_cfg->nb_pstate_switch_disable =
2343 context->bw.dce.nbp_state_change_enable == false;
2344 pp_display_cfg->cpu_cc6_disable =
2345 context->bw.dce.cpuc_state_change_enable == false;
2346 pp_display_cfg->cpu_pstate_disable =
2347 context->bw.dce.cpup_state_change_enable == false;
2348 pp_display_cfg->cpu_pstate_separation_time =
2349 context->bw.dce.blackout_recovery_time_us;
2350
2351 pp_display_cfg->min_memory_clock_khz = context->bw.dce.yclk_khz
2352 / MEMORY_TYPE_MULTIPLIER;
2353
2354 pp_display_cfg->min_engine_clock_khz = determine_sclk_from_bounding_box(
2355 dc,
2356 context->bw.dce.sclk_khz);
2357
2358 pp_display_cfg->min_engine_clock_deep_sleep_khz
2359 = context->bw.dce.sclk_deep_sleep_khz;
2360
2361 pp_display_cfg->avail_mclk_switch_time_us =
2362 dce110_get_min_vblank_time_us(context);
2363 /* TODO: dce11.2*/
2364 pp_display_cfg->avail_mclk_switch_time_in_disp_active_us = 0;
2365
2366 pp_display_cfg->disp_clk_khz = context->bw.dce.dispclk_khz;
2367
2368 dce110_fill_display_configs(context, pp_display_cfg);
2369
2370 /* TODO: is this still applicable?*/
2371 if (pp_display_cfg->display_count == 1) {
2372 const struct dc_crtc_timing *timing =
2373 &context->streams[0]->public.timing;
2374
2375 pp_display_cfg->crtc_index =
2376 pp_display_cfg->disp_configs[0].pipe_idx;
2377 pp_display_cfg->line_time_in_us = timing->h_total * 1000
2378 / timing->pix_clk_khz;
2379 }
2380
2381 if (memcmp(&dc->prev_display_config, pp_display_cfg, sizeof(
2382 struct dm_pp_display_configuration)) != 0)
2383 dm_pp_apply_display_requirements(dc->ctx, pp_display_cfg);
2384
2385 dc->prev_display_config = *pp_display_cfg;
2386 }
2387
2388 static void dce110_set_bandwidth(
2389 struct core_dc *dc,
2390 struct validate_context *context,
2391 bool decrease_allowed)
2392 {
2393 dce110_set_displaymarks(dc, context);
2394
2395 if (decrease_allowed || context->bw.dce.dispclk_khz > dc->current_context->bw.dce.dispclk_khz) {
2396 dc->res_pool->display_clock->funcs->set_clock(
2397 dc->res_pool->display_clock,
2398 context->bw.dce.dispclk_khz * 115 / 100);
2399 dc->current_context->bw.dce.dispclk_khz = context->bw.dce.dispclk_khz;
2400 }
2401
2402 pplib_apply_display_requirements(dc, context);
2403 }
2404
2405 static void dce110_program_front_end_for_pipe(
2406 struct core_dc *dc, struct pipe_ctx *pipe_ctx)
2407 {
2408 struct mem_input *mi = pipe_ctx->mi;
2409 struct pipe_ctx *old_pipe = NULL;
2410 struct core_surface *surface = pipe_ctx->surface;
2411 struct xfm_grph_csc_adjustment adjust;
2412 struct out_csc_color_matrix tbl_entry;
2413 unsigned int i;
2414
2415 memset(&tbl_entry, 0, sizeof(tbl_entry));
2416
2417 if (dc->current_context)
2418 old_pipe = &dc->current_context->res_ctx.pipe_ctx[pipe_ctx->pipe_idx];
2419
2420 memset(&adjust, 0, sizeof(adjust));
2421 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS;
2422
2423 dce_enable_fe_clock(dc->hwseq, pipe_ctx->pipe_idx, true);
2424
2425 set_default_colors(pipe_ctx);
2426 if (pipe_ctx->stream->public.csc_color_matrix.enable_adjustment
2427 == true) {
2428 tbl_entry.color_space =
2429 pipe_ctx->stream->public.output_color_space;
2430
2431 for (i = 0; i < 12; i++)
2432 tbl_entry.regval[i] =
2433 pipe_ctx->stream->public.csc_color_matrix.matrix[i];
2434
2435 pipe_ctx->opp->funcs->opp_set_csc_adjustment
2436 (pipe_ctx->opp, &tbl_entry);
2437 }
2438
2439 if (pipe_ctx->stream->public.gamut_remap_matrix.enable_remap == true) {
2440 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW;
2441 adjust.temperature_matrix[0] =
2442 pipe_ctx->stream->
2443 public.gamut_remap_matrix.matrix[0];
2444 adjust.temperature_matrix[1] =
2445 pipe_ctx->stream->
2446 public.gamut_remap_matrix.matrix[1];
2447 adjust.temperature_matrix[2] =
2448 pipe_ctx->stream->
2449 public.gamut_remap_matrix.matrix[2];
2450 adjust.temperature_matrix[3] =
2451 pipe_ctx->stream->
2452 public.gamut_remap_matrix.matrix[4];
2453 adjust.temperature_matrix[4] =
2454 pipe_ctx->stream->
2455 public.gamut_remap_matrix.matrix[5];
2456 adjust.temperature_matrix[5] =
2457 pipe_ctx->stream->
2458 public.gamut_remap_matrix.matrix[6];
2459 adjust.temperature_matrix[6] =
2460 pipe_ctx->stream->
2461 public.gamut_remap_matrix.matrix[8];
2462 adjust.temperature_matrix[7] =
2463 pipe_ctx->stream->
2464 public.gamut_remap_matrix.matrix[9];
2465 adjust.temperature_matrix[8] =
2466 pipe_ctx->stream->
2467 public.gamut_remap_matrix.matrix[10];
2468 }
2469
2470 pipe_ctx->xfm->funcs->transform_set_gamut_remap(pipe_ctx->xfm, &adjust);
2471
2472 pipe_ctx->scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0;
2473
2474 program_scaler(dc, pipe_ctx);
2475
2476 mi->funcs->mem_input_program_surface_config(
2477 mi,
2478 surface->public.format,
2479 &surface->public.tiling_info,
2480 &surface->public.plane_size,
2481 surface->public.rotation,
2482 NULL,
2483 false);
2484 if (mi->funcs->set_blank)
2485 mi->funcs->set_blank(mi, pipe_ctx->surface->public.visible);
2486
2487 if (dc->public.config.gpu_vm_support)
2488 mi->funcs->mem_input_program_pte_vm(
2489 pipe_ctx->mi,
2490 surface->public.format,
2491 &surface->public.tiling_info,
2492 surface->public.rotation);
2493
2494 dm_logger_write(dc->ctx->logger, LOG_SURFACE,
2495 "Pipe:%d 0x%x: addr hi:0x%x, "
2496 "addr low:0x%x, "
2497 "src: %d, %d, %d,"
2498 " %d; dst: %d, %d, %d, %d;"
2499 "clip: %d, %d, %d, %d\n",
2500 pipe_ctx->pipe_idx,
2501 pipe_ctx->surface,
2502 pipe_ctx->surface->public.address.grph.addr.high_part,
2503 pipe_ctx->surface->public.address.grph.addr.low_part,
2504 pipe_ctx->surface->public.src_rect.x,
2505 pipe_ctx->surface->public.src_rect.y,
2506 pipe_ctx->surface->public.src_rect.width,
2507 pipe_ctx->surface->public.src_rect.height,
2508 pipe_ctx->surface->public.dst_rect.x,
2509 pipe_ctx->surface->public.dst_rect.y,
2510 pipe_ctx->surface->public.dst_rect.width,
2511 pipe_ctx->surface->public.dst_rect.height,
2512 pipe_ctx->surface->public.clip_rect.x,
2513 pipe_ctx->surface->public.clip_rect.y,
2514 pipe_ctx->surface->public.clip_rect.width,
2515 pipe_ctx->surface->public.clip_rect.height);
2516
2517 dm_logger_write(dc->ctx->logger, LOG_SURFACE,
2518 "Pipe %d: width, height, x, y\n"
2519 "viewport:%d, %d, %d, %d\n"
2520 "recout: %d, %d, %d, %d\n",
2521 pipe_ctx->pipe_idx,
2522 pipe_ctx->scl_data.viewport.width,
2523 pipe_ctx->scl_data.viewport.height,
2524 pipe_ctx->scl_data.viewport.x,
2525 pipe_ctx->scl_data.viewport.y,
2526 pipe_ctx->scl_data.recout.width,
2527 pipe_ctx->scl_data.recout.height,
2528 pipe_ctx->scl_data.recout.x,
2529 pipe_ctx->scl_data.recout.y);
2530 }
2531
2532 static void dce110_apply_ctx_for_surface(
2533 struct core_dc *dc,
2534 struct core_surface *surface,
2535 struct validate_context *context)
2536 {
2537 int i;
2538
2539 /* TODO remove when removing the surface reset workaroud*/
2540 if (!surface)
2541 return;
2542
2543 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2544 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2545
2546 if (pipe_ctx->surface != surface)
2547 continue;
2548
2549 dce110_program_front_end_for_pipe(dc, pipe_ctx);
2550 program_surface_visibility(dc, pipe_ctx);
2551
2552 }
2553 }
2554
2555 static void dce110_power_down_fe(struct core_dc *dc, int fe_idx)
2556 {
2557 /* Do not power down fe when stream is active on dce*/
2558 if (dc->current_context->res_ctx.pipe_ctx[fe_idx].stream)
2559 return;
2560
2561 dc->hwss.enable_display_power_gating(
2562 dc, fe_idx, dc->ctx->dc_bios, PIPE_GATING_CONTROL_ENABLE);
2563
2564 dc->res_pool->transforms[fe_idx]->funcs->transform_reset(
2565 dc->res_pool->transforms[fe_idx]);
2566 }
2567
2568 static const struct hw_sequencer_funcs dce110_funcs = {
2569 .program_gamut_remap = program_gamut_remap,
2570 .init_hw = init_hw,
2571 .apply_ctx_to_hw = dce110_apply_ctx_to_hw,
2572 .apply_ctx_for_surface = dce110_apply_ctx_for_surface,
2573 .set_plane_config = set_plane_config,
2574 .update_plane_addr = update_plane_addr,
2575 .update_pending_status = dce110_update_pending_status,
2576 .set_input_transfer_func = dce110_set_input_transfer_func,
2577 .set_output_transfer_func = dce110_set_output_transfer_func,
2578 .power_down = dce110_power_down,
2579 .enable_accelerated_mode = dce110_enable_accelerated_mode,
2580 .enable_timing_synchronization = dce110_enable_timing_synchronization,
2581 .update_info_frame = dce110_update_info_frame,
2582 .enable_stream = dce110_enable_stream,
2583 .disable_stream = dce110_disable_stream,
2584 .unblank_stream = dce110_unblank_stream,
2585 .enable_display_pipe_clock_gating = enable_display_pipe_clock_gating,
2586 .enable_display_power_gating = dce110_enable_display_power_gating,
2587 .power_down_front_end = dce110_power_down_fe,
2588 .pipe_control_lock = dce_pipe_control_lock,
2589 .set_bandwidth = dce110_set_bandwidth,
2590 .set_drr = set_drr,
2591 .get_position = get_position,
2592 .set_static_screen_control = set_static_screen_control,
2593 .reset_hw_ctx_wrap = reset_hw_ctx_wrap,
2594 .prog_pixclk_crtc_otg = dce110_prog_pixclk_crtc_otg,
2595 .setup_stereo = NULL
2596 };
2597
2598 bool dce110_hw_sequencer_construct(struct core_dc *dc)
2599 {
2600 dc->hwss = dce110_funcs;
2601
2602 return true;
2603 }
2604