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