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