1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25#include "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#include "gpio_service_interface.h"
36
37#if defined(CONFIG_DRM_AMD_DC_FBC)
38#include "dce110_compressor.h"
39#endif
40
41#include "bios/bios_parser_helper.h"
42#include "timing_generator.h"
43#include "mem_input.h"
44#include "opp.h"
45#include "ipp.h"
46#include "transform.h"
47#include "stream_encoder.h"
48#include "link_encoder.h"
49#include "link_hwss.h"
50#include "clock_source.h"
51#include "abm.h"
52#include "audio.h"
53#include "reg_helper.h"
54
55
56#include "dce/dce_11_0_d.h"
57#include "dce/dce_11_0_sh_mask.h"
58#include "custom_float.h"
59
60#include "atomfirmware.h"
61
62
63
64
65
66
67#define PANEL_POWER_UP_TIMEOUT 300
68#define PANEL_POWER_DOWN_TIMEOUT 500
69#define HPD_CHECK_INTERVAL 10
70
71#define CTX \
72 hws->ctx
73#define DC_LOGGER \
74 ctx->logger
75#define REG(reg)\
76 hws->regs->reg
77
78#undef FN
79#define FN(reg_name, field_name) \
80 hws->shifts->field_name, hws->masks->field_name
81
82struct dce110_hw_seq_reg_offsets {
83 uint32_t crtc;
84};
85
86static const struct dce110_hw_seq_reg_offsets reg_offsets[] = {
87{
88 .crtc = (mmCRTC0_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
89},
90{
91 .crtc = (mmCRTC1_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
92},
93{
94 .crtc = (mmCRTC2_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
95},
96{
97 .crtc = (mmCRTCV_GSL_CONTROL - mmCRTC_GSL_CONTROL),
98}
99};
100
101#define HW_REG_BLND(reg, id)\
102 (reg + reg_offsets[id].blnd)
103
104#define HW_REG_CRTC(reg, id)\
105 (reg + reg_offsets[id].crtc)
106
107#define MAX_WATERMARK 0xFFFF
108#define SAFE_NBP_MARK 0x7FFF
109
110
111
112
113
114static void dce110_init_pte(struct dc_context *ctx)
115{
116 uint32_t addr;
117 uint32_t value = 0;
118 uint32_t chunk_int = 0;
119 uint32_t chunk_mul = 0;
120
121 addr = mmUNP_DVMM_PTE_CONTROL;
122 value = dm_read_reg(ctx, addr);
123
124 set_reg_field_value(
125 value,
126 0,
127 DVMM_PTE_CONTROL,
128 DVMM_USE_SINGLE_PTE);
129
130 set_reg_field_value(
131 value,
132 1,
133 DVMM_PTE_CONTROL,
134 DVMM_PTE_BUFFER_MODE0);
135
136 set_reg_field_value(
137 value,
138 1,
139 DVMM_PTE_CONTROL,
140 DVMM_PTE_BUFFER_MODE1);
141
142 dm_write_reg(ctx, addr, value);
143
144 addr = mmDVMM_PTE_REQ;
145 value = dm_read_reg(ctx, addr);
146
147 chunk_int = get_reg_field_value(
148 value,
149 DVMM_PTE_REQ,
150 HFLIP_PTEREQ_PER_CHUNK_INT);
151
152 chunk_mul = get_reg_field_value(
153 value,
154 DVMM_PTE_REQ,
155 HFLIP_PTEREQ_PER_CHUNK_MULTIPLIER);
156
157 if (chunk_int != 0x4 || chunk_mul != 0x4) {
158
159 set_reg_field_value(
160 value,
161 255,
162 DVMM_PTE_REQ,
163 MAX_PTEREQ_TO_ISSUE);
164
165 set_reg_field_value(
166 value,
167 4,
168 DVMM_PTE_REQ,
169 HFLIP_PTEREQ_PER_CHUNK_INT);
170
171 set_reg_field_value(
172 value,
173 4,
174 DVMM_PTE_REQ,
175 HFLIP_PTEREQ_PER_CHUNK_MULTIPLIER);
176
177 dm_write_reg(ctx, addr, value);
178 }
179}
180
181
182static void enable_display_pipe_clock_gating(
183 struct dc_context *ctx,
184 bool clock_gating)
185{
186
187}
188
189static bool dce110_enable_display_power_gating(
190 struct dc *dc,
191 uint8_t controller_id,
192 struct dc_bios *dcb,
193 enum pipe_gating_control power_gating)
194{
195 enum bp_result bp_result = BP_RESULT_OK;
196 enum bp_pipe_control_action cntl;
197 struct dc_context *ctx = dc->ctx;
198 unsigned int underlay_idx = dc->res_pool->underlay_pipe_index;
199
200 if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment))
201 return true;
202
203 if (power_gating == PIPE_GATING_CONTROL_INIT)
204 cntl = ASIC_PIPE_INIT;
205 else if (power_gating == PIPE_GATING_CONTROL_ENABLE)
206 cntl = ASIC_PIPE_ENABLE;
207 else
208 cntl = ASIC_PIPE_DISABLE;
209
210 if (controller_id == underlay_idx)
211 controller_id = CONTROLLER_ID_UNDERLAY0 - 1;
212
213 if (power_gating != PIPE_GATING_CONTROL_INIT || controller_id == 0){
214
215 bp_result = dcb->funcs->enable_disp_power_gating(
216 dcb, controller_id + 1, cntl);
217
218
219
220
221
222
223
224
225 if (controller_id < CONTROLLER_ID_MAX - 1)
226 dm_write_reg(ctx,
227 HW_REG_CRTC(mmCRTC_MASTER_UPDATE_MODE, controller_id),
228 0);
229 }
230
231 if (power_gating != PIPE_GATING_CONTROL_ENABLE)
232 dce110_init_pte(ctx);
233
234 if (bp_result == BP_RESULT_OK)
235 return true;
236 else
237 return false;
238}
239
240static void build_prescale_params(struct ipp_prescale_params *prescale_params,
241 const struct dc_plane_state *plane_state)
242{
243 prescale_params->mode = IPP_PRESCALE_MODE_FIXED_UNSIGNED;
244
245 switch (plane_state->format) {
246 case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
247 case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
248 prescale_params->scale = 0x2020;
249 break;
250 case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
251 case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
252 prescale_params->scale = 0x2008;
253 break;
254 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
255 case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
256 prescale_params->scale = 0x2000;
257 break;
258 default:
259 ASSERT(false);
260 break;
261 }
262}
263
264static bool
265dce110_set_input_transfer_func(struct pipe_ctx *pipe_ctx,
266 const struct dc_plane_state *plane_state)
267{
268 struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp;
269 const struct dc_transfer_func *tf = NULL;
270 struct ipp_prescale_params prescale_params = { 0 };
271 bool result = true;
272
273 if (ipp == NULL)
274 return false;
275
276 if (plane_state->in_transfer_func)
277 tf = plane_state->in_transfer_func;
278
279 build_prescale_params(&prescale_params, plane_state);
280 ipp->funcs->ipp_program_prescale(ipp, &prescale_params);
281
282 if (plane_state->gamma_correction && dce_use_lut(plane_state->format))
283 ipp->funcs->ipp_program_input_lut(ipp, plane_state->gamma_correction);
284
285 if (tf == NULL) {
286
287 ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_HW_sRGB);
288 } else if (tf->type == TF_TYPE_PREDEFINED) {
289 switch (tf->tf) {
290 case TRANSFER_FUNCTION_SRGB:
291 ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_HW_sRGB);
292 break;
293 case TRANSFER_FUNCTION_BT709:
294 ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_HW_xvYCC);
295 break;
296 case TRANSFER_FUNCTION_LINEAR:
297 ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS);
298 break;
299 case TRANSFER_FUNCTION_PQ:
300 default:
301 result = false;
302 break;
303 }
304 } else if (tf->type == TF_TYPE_BYPASS) {
305 ipp->funcs->ipp_set_degamma(ipp, IPP_DEGAMMA_MODE_BYPASS);
306 } else {
307
308 result = false;
309 }
310
311 return result;
312}
313
314static bool convert_to_custom_float(struct pwl_result_data *rgb_resulted,
315 struct curve_points *arr_points,
316 uint32_t hw_points_num)
317{
318 struct custom_float_format fmt;
319
320 struct pwl_result_data *rgb = rgb_resulted;
321
322 uint32_t i = 0;
323
324 fmt.exponenta_bits = 6;
325 fmt.mantissa_bits = 12;
326 fmt.sign = true;
327
328 if (!convert_to_custom_float_format(arr_points[0].x, &fmt,
329 &arr_points[0].custom_float_x)) {
330 BREAK_TO_DEBUGGER();
331 return false;
332 }
333
334 if (!convert_to_custom_float_format(arr_points[0].offset, &fmt,
335 &arr_points[0].custom_float_offset)) {
336 BREAK_TO_DEBUGGER();
337 return false;
338 }
339
340 if (!convert_to_custom_float_format(arr_points[0].slope, &fmt,
341 &arr_points[0].custom_float_slope)) {
342 BREAK_TO_DEBUGGER();
343 return false;
344 }
345
346 fmt.mantissa_bits = 10;
347 fmt.sign = false;
348
349 if (!convert_to_custom_float_format(arr_points[1].x, &fmt,
350 &arr_points[1].custom_float_x)) {
351 BREAK_TO_DEBUGGER();
352 return false;
353 }
354
355 if (!convert_to_custom_float_format(arr_points[1].y, &fmt,
356 &arr_points[1].custom_float_y)) {
357 BREAK_TO_DEBUGGER();
358 return false;
359 }
360
361 if (!convert_to_custom_float_format(arr_points[1].slope, &fmt,
362 &arr_points[1].custom_float_slope)) {
363 BREAK_TO_DEBUGGER();
364 return false;
365 }
366
367 fmt.mantissa_bits = 12;
368 fmt.sign = true;
369
370 while (i != hw_points_num) {
371 if (!convert_to_custom_float_format(rgb->red, &fmt,
372 &rgb->red_reg)) {
373 BREAK_TO_DEBUGGER();
374 return false;
375 }
376
377 if (!convert_to_custom_float_format(rgb->green, &fmt,
378 &rgb->green_reg)) {
379 BREAK_TO_DEBUGGER();
380 return false;
381 }
382
383 if (!convert_to_custom_float_format(rgb->blue, &fmt,
384 &rgb->blue_reg)) {
385 BREAK_TO_DEBUGGER();
386 return false;
387 }
388
389 if (!convert_to_custom_float_format(rgb->delta_red, &fmt,
390 &rgb->delta_red_reg)) {
391 BREAK_TO_DEBUGGER();
392 return false;
393 }
394
395 if (!convert_to_custom_float_format(rgb->delta_green, &fmt,
396 &rgb->delta_green_reg)) {
397 BREAK_TO_DEBUGGER();
398 return false;
399 }
400
401 if (!convert_to_custom_float_format(rgb->delta_blue, &fmt,
402 &rgb->delta_blue_reg)) {
403 BREAK_TO_DEBUGGER();
404 return false;
405 }
406
407 ++rgb;
408 ++i;
409 }
410
411 return true;
412}
413
414#define MAX_LOW_POINT 25
415#define NUMBER_REGIONS 16
416#define NUMBER_SW_SEGMENTS 16
417
418static bool
419dce110_translate_regamma_to_hw_format(const struct dc_transfer_func *output_tf,
420 struct pwl_params *regamma_params)
421{
422 struct curve_points *arr_points;
423 struct pwl_result_data *rgb_resulted;
424 struct pwl_result_data *rgb;
425 struct pwl_result_data *rgb_plus_1;
426 struct fixed31_32 y_r;
427 struct fixed31_32 y_g;
428 struct fixed31_32 y_b;
429 struct fixed31_32 y1_min;
430 struct fixed31_32 y3_max;
431
432 int32_t region_start, region_end;
433 uint32_t i, j, k, seg_distr[NUMBER_REGIONS], increment, start_index, hw_points;
434
435 if (output_tf == NULL || regamma_params == NULL || output_tf->type == TF_TYPE_BYPASS)
436 return false;
437
438 arr_points = regamma_params->arr_points;
439 rgb_resulted = regamma_params->rgb_resulted;
440 hw_points = 0;
441
442 memset(regamma_params, 0, sizeof(struct pwl_params));
443
444 if (output_tf->tf == TRANSFER_FUNCTION_PQ) {
445
446
447
448 region_start = -11;
449 region_end = region_start + NUMBER_REGIONS;
450
451 for (i = 0; i < NUMBER_REGIONS; i++)
452 seg_distr[i] = 4;
453
454 } else {
455
456
457
458
459
460
461 region_start = -10;
462 region_end = 1;
463
464 seg_distr[0] = 4;
465 seg_distr[1] = 4;
466 seg_distr[2] = 4;
467 seg_distr[3] = 4;
468 seg_distr[4] = 4;
469 seg_distr[5] = 4;
470 seg_distr[6] = 4;
471 seg_distr[7] = 4;
472 seg_distr[8] = 4;
473 seg_distr[9] = 4;
474 seg_distr[10] = 0;
475 seg_distr[11] = -1;
476 seg_distr[12] = -1;
477 seg_distr[13] = -1;
478 seg_distr[14] = -1;
479 seg_distr[15] = -1;
480 }
481
482 for (k = 0; k < 16; k++) {
483 if (seg_distr[k] != -1)
484 hw_points += (1 << seg_distr[k]);
485 }
486
487 j = 0;
488 for (k = 0; k < (region_end - region_start); k++) {
489 increment = NUMBER_SW_SEGMENTS / (1 << seg_distr[k]);
490 start_index = (region_start + k + MAX_LOW_POINT) *
491 NUMBER_SW_SEGMENTS;
492 for (i = start_index; i < start_index + NUMBER_SW_SEGMENTS;
493 i += increment) {
494 if (j == hw_points - 1)
495 break;
496 rgb_resulted[j].red = output_tf->tf_pts.red[i];
497 rgb_resulted[j].green = output_tf->tf_pts.green[i];
498 rgb_resulted[j].blue = output_tf->tf_pts.blue[i];
499 j++;
500 }
501 }
502
503
504 start_index = (region_end + MAX_LOW_POINT) * NUMBER_SW_SEGMENTS;
505 rgb_resulted[hw_points - 1].red = output_tf->tf_pts.red[start_index];
506 rgb_resulted[hw_points - 1].green = output_tf->tf_pts.green[start_index];
507 rgb_resulted[hw_points - 1].blue = output_tf->tf_pts.blue[start_index];
508
509 arr_points[0].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2),
510 dal_fixed31_32_from_int(region_start));
511 arr_points[1].x = dal_fixed31_32_pow(dal_fixed31_32_from_int(2),
512 dal_fixed31_32_from_int(region_end));
513
514 y_r = rgb_resulted[0].red;
515 y_g = rgb_resulted[0].green;
516 y_b = rgb_resulted[0].blue;
517
518 y1_min = dal_fixed31_32_min(y_r, dal_fixed31_32_min(y_g, y_b));
519
520 arr_points[0].y = y1_min;
521 arr_points[0].slope = dal_fixed31_32_div(arr_points[0].y,
522 arr_points[0].x);
523
524 y_r = rgb_resulted[hw_points - 1].red;
525 y_g = rgb_resulted[hw_points - 1].green;
526 y_b = rgb_resulted[hw_points - 1].blue;
527
528
529
530
531 y3_max = dal_fixed31_32_max(y_r, dal_fixed31_32_max(y_g, y_b));
532
533 arr_points[1].y = y3_max;
534
535 arr_points[1].slope = dal_fixed31_32_zero;
536
537 if (output_tf->tf == TRANSFER_FUNCTION_PQ) {
538
539
540
541 const struct fixed31_32 end_value = dal_fixed31_32_from_int(125);
542
543 arr_points[1].slope = dal_fixed31_32_div(
544 dal_fixed31_32_sub(dal_fixed31_32_one, arr_points[1].y),
545 dal_fixed31_32_sub(end_value, arr_points[1].x));
546 }
547
548 regamma_params->hw_points_num = hw_points;
549
550 i = 1;
551 for (k = 0; k < 16 && i < 16; k++) {
552 if (seg_distr[k] != -1) {
553 regamma_params->arr_curve_points[k].segments_num = seg_distr[k];
554 regamma_params->arr_curve_points[i].offset =
555 regamma_params->arr_curve_points[k].offset + (1 << seg_distr[k]);
556 }
557 i++;
558 }
559
560 if (seg_distr[k] != -1)
561 regamma_params->arr_curve_points[k].segments_num = seg_distr[k];
562
563 rgb = rgb_resulted;
564 rgb_plus_1 = rgb_resulted + 1;
565
566 i = 1;
567
568 while (i != hw_points + 1) {
569 if (dal_fixed31_32_lt(rgb_plus_1->red, rgb->red))
570 rgb_plus_1->red = rgb->red;
571 if (dal_fixed31_32_lt(rgb_plus_1->green, rgb->green))
572 rgb_plus_1->green = rgb->green;
573 if (dal_fixed31_32_lt(rgb_plus_1->blue, rgb->blue))
574 rgb_plus_1->blue = rgb->blue;
575
576 rgb->delta_red = dal_fixed31_32_sub(rgb_plus_1->red, rgb->red);
577 rgb->delta_green = dal_fixed31_32_sub(rgb_plus_1->green, rgb->green);
578 rgb->delta_blue = dal_fixed31_32_sub(rgb_plus_1->blue, rgb->blue);
579
580 ++rgb_plus_1;
581 ++rgb;
582 ++i;
583 }
584
585 convert_to_custom_float(rgb_resulted, arr_points, hw_points);
586
587 return true;
588}
589
590static bool
591dce110_set_output_transfer_func(struct pipe_ctx *pipe_ctx,
592 const struct dc_stream_state *stream)
593{
594 struct transform *xfm = pipe_ctx->plane_res.xfm;
595
596 xfm->funcs->opp_power_on_regamma_lut(xfm, true);
597 xfm->regamma_params.hw_points_num = GAMMA_HW_POINTS_NUM;
598
599 if (stream->out_transfer_func &&
600 stream->out_transfer_func->type == TF_TYPE_PREDEFINED &&
601 stream->out_transfer_func->tf == TRANSFER_FUNCTION_SRGB) {
602 xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_SRGB);
603 } else if (dce110_translate_regamma_to_hw_format(stream->out_transfer_func,
604 &xfm->regamma_params)) {
605 xfm->funcs->opp_program_regamma_pwl(xfm, &xfm->regamma_params);
606 xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_USER);
607 } else {
608 xfm->funcs->opp_set_regamma_mode(xfm, OPP_REGAMMA_BYPASS);
609 }
610
611 xfm->funcs->opp_power_on_regamma_lut(xfm, false);
612
613 return true;
614}
615
616static enum dc_status bios_parser_crtc_source_select(
617 struct pipe_ctx *pipe_ctx)
618{
619 struct dc_bios *dcb;
620
621
622
623 struct bp_crtc_source_select crtc_source_select = {0};
624 const struct dc_sink *sink = pipe_ctx->stream->sink;
625
626 crtc_source_select.engine_id = pipe_ctx->stream_res.stream_enc->id;
627 crtc_source_select.controller_id = pipe_ctx->stream_res.tg->inst + 1;
628
629
630
631 crtc_source_select.signal = pipe_ctx->stream->signal;
632 crtc_source_select.enable_dp_audio = false;
633 crtc_source_select.sink_signal = pipe_ctx->stream->signal;
634
635 switch (pipe_ctx->stream->timing.display_color_depth) {
636 case COLOR_DEPTH_666:
637 crtc_source_select.display_output_bit_depth = PANEL_6BIT_COLOR;
638 break;
639 case COLOR_DEPTH_888:
640 crtc_source_select.display_output_bit_depth = PANEL_8BIT_COLOR;
641 break;
642 case COLOR_DEPTH_101010:
643 crtc_source_select.display_output_bit_depth = PANEL_10BIT_COLOR;
644 break;
645 case COLOR_DEPTH_121212:
646 crtc_source_select.display_output_bit_depth = PANEL_12BIT_COLOR;
647 break;
648 default:
649 BREAK_TO_DEBUGGER();
650 crtc_source_select.display_output_bit_depth = PANEL_8BIT_COLOR;
651 break;
652 }
653
654 dcb = sink->ctx->dc_bios;
655
656 if (BP_RESULT_OK != dcb->funcs->crtc_source_select(
657 dcb,
658 &crtc_source_select)) {
659 return DC_ERROR_UNEXPECTED;
660 }
661
662 return DC_OK;
663}
664
665void dce110_update_info_frame(struct pipe_ctx *pipe_ctx)
666{
667 ASSERT(pipe_ctx->stream);
668
669 if (pipe_ctx->stream_res.stream_enc == NULL)
670 return;
671
672 if (dc_is_hdmi_signal(pipe_ctx->stream->signal))
673 pipe_ctx->stream_res.stream_enc->funcs->update_hdmi_info_packets(
674 pipe_ctx->stream_res.stream_enc,
675 &pipe_ctx->stream_res.encoder_info_frame);
676 else if (dc_is_dp_signal(pipe_ctx->stream->signal))
677 pipe_ctx->stream_res.stream_enc->funcs->update_dp_info_packets(
678 pipe_ctx->stream_res.stream_enc,
679 &pipe_ctx->stream_res.encoder_info_frame);
680}
681
682void dce110_enable_stream(struct pipe_ctx *pipe_ctx)
683{
684 enum dc_lane_count lane_count =
685 pipe_ctx->stream->sink->link->cur_link_settings.lane_count;
686
687 struct dc_crtc_timing *timing = &pipe_ctx->stream->timing;
688 struct dc_link *link = pipe_ctx->stream->sink->link;
689
690
691 uint32_t active_total_with_borders;
692 uint32_t early_control = 0;
693 struct timing_generator *tg = pipe_ctx->stream_res.tg;
694
695
696
697
698
699 link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc,
700 pipe_ctx->stream_res.stream_enc->id, true);
701
702
703
704 dce110_update_info_frame(pipe_ctx);
705
706
707 active_total_with_borders =
708 timing->h_addressable
709 + timing->h_border_left
710 + timing->h_border_right;
711
712 if (lane_count != 0)
713 early_control = active_total_with_borders % lane_count;
714
715 if (early_control == 0)
716 early_control = lane_count;
717
718 tg->funcs->set_early_control(tg, early_control);
719
720
721 if (pipe_ctx->stream_res.audio != NULL) {
722 if (dc_is_dp_signal(pipe_ctx->stream->signal))
723 pipe_ctx->stream_res.stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_res.stream_enc);
724 }
725
726
727
728
729}
730
731
732static bool is_panel_backlight_on(struct dce_hwseq *hws)
733{
734 uint32_t value;
735
736 REG_GET(LVTMA_PWRSEQ_CNTL, LVTMA_BLON, &value);
737
738 return value;
739}
740
741static bool is_panel_powered_on(struct dce_hwseq *hws)
742{
743 uint32_t pwr_seq_state, dig_on, dig_on_ovrd;
744
745
746 REG_GET(LVTMA_PWRSEQ_STATE, LVTMA_PWRSEQ_TARGET_STATE_R, &pwr_seq_state);
747
748 REG_GET_2(LVTMA_PWRSEQ_CNTL, LVTMA_DIGON, &dig_on, LVTMA_DIGON_OVRD, &dig_on_ovrd);
749
750 return (pwr_seq_state == 1) || (dig_on == 1 && dig_on_ovrd == 1);
751}
752
753static enum bp_result link_transmitter_control(
754 struct dc_bios *bios,
755 struct bp_transmitter_control *cntl)
756{
757 enum bp_result result;
758
759 result = bios->funcs->transmitter_control(bios, cntl);
760
761 return result;
762}
763
764
765
766
767
768void hwss_edp_wait_for_hpd_ready(
769 struct dc_link *link,
770 bool power_up)
771{
772 struct dc_context *ctx = link->ctx;
773 struct graphics_object_id connector = link->link_enc->connector;
774 struct gpio *hpd;
775 bool edp_hpd_high = false;
776 uint32_t time_elapsed = 0;
777 uint32_t timeout = power_up ?
778 PANEL_POWER_UP_TIMEOUT : PANEL_POWER_DOWN_TIMEOUT;
779
780 if (dal_graphics_object_id_get_connector_id(connector)
781 != CONNECTOR_ID_EDP) {
782 BREAK_TO_DEBUGGER();
783 return;
784 }
785
786 if (!power_up)
787
788
789
790
791 return;
792
793
794
795
796
797
798
799
800 hpd = get_hpd_gpio(ctx->dc_bios, connector, ctx->gpio_service);
801
802 if (!hpd) {
803 BREAK_TO_DEBUGGER();
804 return;
805 }
806
807 dal_gpio_open(hpd, GPIO_MODE_INTERRUPT);
808
809
810
811 do {
812 uint32_t detected = 0;
813
814 dal_gpio_get_value(hpd, &detected);
815
816 if (!(detected ^ power_up)) {
817 edp_hpd_high = true;
818 break;
819 }
820
821 msleep(HPD_CHECK_INTERVAL);
822
823 time_elapsed += HPD_CHECK_INTERVAL;
824 } while (time_elapsed < timeout);
825
826 dal_gpio_close(hpd);
827
828 dal_gpio_destroy_irq(&hpd);
829
830 if (false == edp_hpd_high) {
831 DC_LOG_ERROR(
832 "%s: wait timed out!\n", __func__);
833 }
834}
835
836void hwss_edp_power_control(
837 struct dc_link *link,
838 bool power_up)
839{
840 struct dc_context *ctx = link->ctx;
841 struct dce_hwseq *hwseq = ctx->dc->hwseq;
842 struct bp_transmitter_control cntl = { 0 };
843 enum bp_result bp_result;
844
845
846 if (dal_graphics_object_id_get_connector_id(link->link_enc->connector)
847 != CONNECTOR_ID_EDP) {
848 BREAK_TO_DEBUGGER();
849 return;
850 }
851
852 if (power_up != is_panel_powered_on(hwseq)) {
853
854
855 DC_LOG_HW_RESUME_S3(
856 "%s: Panel Power action: %s\n",
857 __func__, (power_up ? "On":"Off"));
858
859 cntl.action = power_up ?
860 TRANSMITTER_CONTROL_POWER_ON :
861 TRANSMITTER_CONTROL_POWER_OFF;
862 cntl.transmitter = link->link_enc->transmitter;
863 cntl.connector_obj_id = link->link_enc->connector;
864 cntl.coherent = false;
865 cntl.lanes_number = LANE_COUNT_FOUR;
866 cntl.hpd_sel = link->link_enc->hpd_source;
867
868 bp_result = link_transmitter_control(ctx->dc_bios, &cntl);
869
870 if (bp_result != BP_RESULT_OK)
871 DC_LOG_ERROR(
872 "%s: Panel Power bp_result: %d\n",
873 __func__, bp_result);
874 } else {
875 DC_LOG_HW_RESUME_S3(
876 "%s: Skipping Panel Power action: %s\n",
877 __func__, (power_up ? "On":"Off"));
878 }
879}
880
881
882
883
884
885
886void hwss_edp_backlight_control(
887 struct dc_link *link,
888 bool enable)
889{
890 struct dc_context *ctx = link->ctx;
891 struct dce_hwseq *hws = ctx->dc->hwseq;
892 struct bp_transmitter_control cntl = { 0 };
893
894 if (dal_graphics_object_id_get_connector_id(link->link_enc->connector)
895 != CONNECTOR_ID_EDP) {
896 BREAK_TO_DEBUGGER();
897 return;
898 }
899
900 if (enable && is_panel_backlight_on(hws)) {
901 DC_LOG_HW_RESUME_S3(
902 "%s: panel already powered up. Do nothing.\n",
903 __func__);
904 return;
905 }
906
907
908
909 DC_LOG_HW_RESUME_S3(
910 "%s: backlight action: %s\n",
911 __func__, (enable ? "On":"Off"));
912
913 cntl.action = enable ?
914 TRANSMITTER_CONTROL_BACKLIGHT_ON :
915 TRANSMITTER_CONTROL_BACKLIGHT_OFF;
916
917
918 cntl.transmitter = link->link_enc->transmitter;
919 cntl.connector_obj_id = link->link_enc->connector;
920
921 cntl.lanes_number = LANE_COUNT_FOUR;
922 cntl.hpd_sel = link->link_enc->hpd_source;
923 cntl.signal = SIGNAL_TYPE_EDP;
924
925
926
927
928
929
930
931
932
933
934
935
936
937 if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_ON)
938 edp_receiver_ready_T7(link);
939 link_transmitter_control(ctx->dc_bios, &cntl);
940
941 if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_OFF)
942 edp_receiver_ready_T9(link);
943}
944
945void dce110_disable_stream(struct pipe_ctx *pipe_ctx, int option)
946{
947 struct dc_stream_state *stream = pipe_ctx->stream;
948 struct dc_link *link = stream->sink->link;
949 struct dc *dc = pipe_ctx->stream->ctx->dc;
950
951 if (dc_is_hdmi_signal(pipe_ctx->stream->signal))
952 pipe_ctx->stream_res.stream_enc->funcs->stop_hdmi_info_packets(
953 pipe_ctx->stream_res.stream_enc);
954
955 if (dc_is_dp_signal(pipe_ctx->stream->signal))
956 pipe_ctx->stream_res.stream_enc->funcs->stop_dp_info_packets(
957 pipe_ctx->stream_res.stream_enc);
958
959 pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control(
960 pipe_ctx->stream_res.stream_enc, true);
961 if (pipe_ctx->stream_res.audio) {
962 if (option != KEEP_ACQUIRED_RESOURCE ||
963 !dc->debug.az_endpoint_mute_only) {
964
965 pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio);
966 }
967
968 if (dc_is_dp_signal(pipe_ctx->stream->signal))
969 pipe_ctx->stream_res.stream_enc->funcs->dp_audio_disable(
970 pipe_ctx->stream_res.stream_enc);
971 else
972 pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_disable(
973 pipe_ctx->stream_res.stream_enc);
974
975 if (option == FREE_ACQUIRED_RESOURCE && dc->caps.dynamic_audio == true) {
976
977 pipe_ctx->stream_res.audio = NULL;
978
979 update_audio_usage(&dc->current_state->res_ctx, dc->res_pool, pipe_ctx->stream_res.audio, false);
980 }
981
982
983
984
985
986
987 }
988
989
990 link->link_enc->funcs->connect_dig_be_to_fe(
991 link->link_enc,
992 pipe_ctx->stream_res.stream_enc->id,
993 false);
994
995}
996
997void dce110_unblank_stream(struct pipe_ctx *pipe_ctx,
998 struct dc_link_settings *link_settings)
999{
1000 struct encoder_unblank_param params = { { 0 } };
1001 struct dc_stream_state *stream = pipe_ctx->stream;
1002 struct dc_link *link = stream->sink->link;
1003
1004
1005 params.pixel_clk_khz =
1006 pipe_ctx->stream->timing.pix_clk_khz;
1007 params.link_settings.link_rate = link_settings->link_rate;
1008
1009 if (dc_is_dp_signal(pipe_ctx->stream->signal))
1010 pipe_ctx->stream_res.stream_enc->funcs->dp_unblank(pipe_ctx->stream_res.stream_enc, ¶ms);
1011
1012 if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP) {
1013 link->dc->hwss.edp_backlight_control(link, true);
1014 stream->bl_pwm_level = 0;
1015 }
1016}
1017void dce110_blank_stream(struct pipe_ctx *pipe_ctx)
1018{
1019 struct dc_stream_state *stream = pipe_ctx->stream;
1020 struct dc_link *link = stream->sink->link;
1021
1022 if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP) {
1023 link->dc->hwss.edp_backlight_control(link, false);
1024 dc_link_set_abm_disable(link);
1025 }
1026
1027 if (dc_is_dp_signal(pipe_ctx->stream->signal))
1028 pipe_ctx->stream_res.stream_enc->funcs->dp_blank(pipe_ctx->stream_res.stream_enc);
1029}
1030
1031
1032void dce110_set_avmute(struct pipe_ctx *pipe_ctx, bool enable)
1033{
1034 if (pipe_ctx != NULL && pipe_ctx->stream_res.stream_enc != NULL)
1035 pipe_ctx->stream_res.stream_enc->funcs->set_avmute(pipe_ctx->stream_res.stream_enc, enable);
1036}
1037
1038static enum audio_dto_source translate_to_dto_source(enum controller_id crtc_id)
1039{
1040 switch (crtc_id) {
1041 case CONTROLLER_ID_D0:
1042 return DTO_SOURCE_ID0;
1043 case CONTROLLER_ID_D1:
1044 return DTO_SOURCE_ID1;
1045 case CONTROLLER_ID_D2:
1046 return DTO_SOURCE_ID2;
1047 case CONTROLLER_ID_D3:
1048 return DTO_SOURCE_ID3;
1049 case CONTROLLER_ID_D4:
1050 return DTO_SOURCE_ID4;
1051 case CONTROLLER_ID_D5:
1052 return DTO_SOURCE_ID5;
1053 default:
1054 return DTO_SOURCE_UNKNOWN;
1055 }
1056}
1057
1058static void build_audio_output(
1059 struct dc_state *state,
1060 const struct pipe_ctx *pipe_ctx,
1061 struct audio_output *audio_output)
1062{
1063 const struct dc_stream_state *stream = pipe_ctx->stream;
1064 audio_output->engine_id = pipe_ctx->stream_res.stream_enc->id;
1065
1066 audio_output->signal = pipe_ctx->stream->signal;
1067
1068
1069
1070 audio_output->crtc_info.h_total =
1071 stream->timing.h_total;
1072
1073
1074
1075
1076
1077 audio_output->crtc_info.h_active =
1078 stream->timing.h_addressable
1079 + stream->timing.h_border_left
1080 + stream->timing.h_border_right;
1081
1082 audio_output->crtc_info.v_active =
1083 stream->timing.v_addressable
1084 + stream->timing.v_border_top
1085 + stream->timing.v_border_bottom;
1086
1087 audio_output->crtc_info.pixel_repetition = 1;
1088
1089 audio_output->crtc_info.interlaced =
1090 stream->timing.flags.INTERLACE;
1091
1092 audio_output->crtc_info.refresh_rate =
1093 (stream->timing.pix_clk_khz*1000)/
1094 (stream->timing.h_total*stream->timing.v_total);
1095
1096 audio_output->crtc_info.color_depth =
1097 stream->timing.display_color_depth;
1098
1099 audio_output->crtc_info.requested_pixel_clock =
1100 pipe_ctx->stream_res.pix_clk_params.requested_pix_clk;
1101
1102 audio_output->crtc_info.calculated_pixel_clock =
1103 pipe_ctx->stream_res.pix_clk_params.requested_pix_clk;
1104
1105
1106 if (dc_is_hdmi_signal(pipe_ctx->stream->signal) &&
1107 audio_output->crtc_info.requested_pixel_clock ==
1108 stream->timing.pix_clk_khz) {
1109 if (pipe_ctx->stream_res.pix_clk_params.pixel_encoding == PIXEL_ENCODING_YCBCR420) {
1110 audio_output->crtc_info.requested_pixel_clock =
1111 audio_output->crtc_info.requested_pixel_clock/2;
1112 audio_output->crtc_info.calculated_pixel_clock =
1113 pipe_ctx->stream_res.pix_clk_params.requested_pix_clk/2;
1114
1115 }
1116 }
1117
1118 if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT ||
1119 pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
1120 audio_output->pll_info.dp_dto_source_clock_in_khz =
1121 state->dis_clk->funcs->get_dp_ref_clk_frequency(
1122 state->dis_clk);
1123 }
1124
1125 audio_output->pll_info.feed_back_divider =
1126 pipe_ctx->pll_settings.feedback_divider;
1127
1128 audio_output->pll_info.dto_source =
1129 translate_to_dto_source(
1130 pipe_ctx->stream_res.tg->inst + 1);
1131
1132
1133 audio_output->pll_info.ss_enabled = true;
1134
1135 audio_output->pll_info.ss_percentage =
1136 pipe_ctx->pll_settings.ss_percentage;
1137}
1138
1139static void get_surface_visual_confirm_color(const struct pipe_ctx *pipe_ctx,
1140 struct tg_color *color)
1141{
1142 uint32_t color_value = MAX_TG_COLOR_VALUE * (4 - pipe_ctx->stream_res.tg->inst) / 4;
1143
1144 switch (pipe_ctx->plane_res.scl_data.format) {
1145 case PIXEL_FORMAT_ARGB8888:
1146
1147 color->color_r_cr = color_value;
1148 break;
1149
1150 case PIXEL_FORMAT_ARGB2101010:
1151
1152 color->color_b_cb = color_value;
1153 break;
1154 case PIXEL_FORMAT_420BPP8:
1155
1156 color->color_g_y = color_value;
1157 break;
1158 case PIXEL_FORMAT_420BPP10:
1159
1160 color->color_g_y = color_value;
1161 color->color_r_cr = color_value;
1162 break;
1163 case PIXEL_FORMAT_FP16:
1164
1165 color->color_r_cr = color_value;
1166 color->color_b_cb = color_value;
1167 color->color_g_y = color_value;
1168 break;
1169 default:
1170 break;
1171 }
1172}
1173
1174static void program_scaler(const struct dc *dc,
1175 const struct pipe_ctx *pipe_ctx)
1176{
1177 struct tg_color color = {0};
1178
1179#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
1180
1181 if (pipe_ctx->plane_res.xfm->funcs->transform_set_pixel_storage_depth == NULL)
1182 return;
1183#endif
1184
1185 if (dc->debug.surface_visual_confirm)
1186 get_surface_visual_confirm_color(pipe_ctx, &color);
1187 else
1188 color_space_to_black_color(dc,
1189 pipe_ctx->stream->output_color_space,
1190 &color);
1191
1192 pipe_ctx->plane_res.xfm->funcs->transform_set_pixel_storage_depth(
1193 pipe_ctx->plane_res.xfm,
1194 pipe_ctx->plane_res.scl_data.lb_params.depth,
1195 &pipe_ctx->stream->bit_depth_params);
1196
1197 if (pipe_ctx->stream_res.tg->funcs->set_overscan_blank_color)
1198 pipe_ctx->stream_res.tg->funcs->set_overscan_blank_color(
1199 pipe_ctx->stream_res.tg,
1200 &color);
1201
1202 pipe_ctx->plane_res.xfm->funcs->transform_set_scaler(pipe_ctx->plane_res.xfm,
1203 &pipe_ctx->plane_res.scl_data);
1204}
1205
1206static enum dc_status dce110_prog_pixclk_crtc_otg(
1207 struct pipe_ctx *pipe_ctx,
1208 struct dc_state *context,
1209 struct dc *dc)
1210{
1211 struct dc_stream_state *stream = pipe_ctx->stream;
1212 struct pipe_ctx *pipe_ctx_old = &dc->current_state->res_ctx.
1213 pipe_ctx[pipe_ctx->pipe_idx];
1214 struct tg_color black_color = {0};
1215
1216 if (!pipe_ctx_old->stream) {
1217
1218
1219 color_space_to_black_color(dc,
1220 stream->output_color_space, &black_color);
1221 pipe_ctx->stream_res.tg->funcs->set_blank_color(
1222 pipe_ctx->stream_res.tg,
1223 &black_color);
1224
1225
1226
1227
1228
1229 pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, true);
1230
1231 if (false == pipe_ctx->clock_source->funcs->program_pix_clk(
1232 pipe_ctx->clock_source,
1233 &pipe_ctx->stream_res.pix_clk_params,
1234 &pipe_ctx->pll_settings)) {
1235 BREAK_TO_DEBUGGER();
1236 return DC_ERROR_UNEXPECTED;
1237 }
1238
1239 pipe_ctx->stream_res.tg->funcs->program_timing(
1240 pipe_ctx->stream_res.tg,
1241 &stream->timing,
1242 true);
1243
1244 pipe_ctx->stream_res.tg->funcs->set_static_screen_control(
1245 pipe_ctx->stream_res.tg,
1246 0x182);
1247 }
1248
1249 if (!pipe_ctx_old->stream) {
1250 if (false == pipe_ctx->stream_res.tg->funcs->enable_crtc(
1251 pipe_ctx->stream_res.tg)) {
1252 BREAK_TO_DEBUGGER();
1253 return DC_ERROR_UNEXPECTED;
1254 }
1255 }
1256
1257
1258
1259 return DC_OK;
1260}
1261
1262static enum dc_status apply_single_controller_ctx_to_hw(
1263 struct pipe_ctx *pipe_ctx,
1264 struct dc_state *context,
1265 struct dc *dc)
1266{
1267 struct dc_stream_state *stream = pipe_ctx->stream;
1268 struct pipe_ctx *pipe_ctx_old = &dc->current_state->res_ctx.
1269 pipe_ctx[pipe_ctx->pipe_idx];
1270
1271
1272 dc->hwss.prog_pixclk_crtc_otg(pipe_ctx, context, dc);
1273
1274
1275 if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
1276 pipe_ctx->stream_res.opp->funcs->opp_set_dyn_expansion(
1277 pipe_ctx->stream_res.opp,
1278 COLOR_SPACE_YCBCR601,
1279 stream->timing.display_color_depth,
1280 pipe_ctx->stream->signal);
1281
1282 pipe_ctx->stream_res.opp->funcs->opp_program_fmt(
1283 pipe_ctx->stream_res.opp,
1284 &stream->bit_depth_params,
1285 &stream->clamping);
1286 return DC_OK;
1287 }
1288
1289 if (pipe_ctx->stream->signal != SIGNAL_TYPE_VIRTUAL)
1290 if (DC_OK != bios_parser_crtc_source_select(pipe_ctx)) {
1291 BREAK_TO_DEBUGGER();
1292 return DC_ERROR_UNEXPECTED;
1293 }
1294 pipe_ctx->stream_res.opp->funcs->opp_set_dyn_expansion(
1295 pipe_ctx->stream_res.opp,
1296 COLOR_SPACE_YCBCR601,
1297 stream->timing.display_color_depth,
1298 pipe_ctx->stream->signal);
1299
1300 if (pipe_ctx->stream->signal != SIGNAL_TYPE_VIRTUAL)
1301 stream->sink->link->link_enc->funcs->setup(
1302 stream->sink->link->link_enc,
1303 pipe_ctx->stream->signal);
1304
1305 if (pipe_ctx->stream->signal != SIGNAL_TYPE_VIRTUAL)
1306 pipe_ctx->stream_res.stream_enc->funcs->setup_stereo_sync(
1307 pipe_ctx->stream_res.stream_enc,
1308 pipe_ctx->stream_res.tg->inst,
1309 stream->timing.timing_3d_format != TIMING_3D_FORMAT_NONE);
1310
1311
1312 pipe_ctx->stream_res.opp->funcs->opp_program_fmt(
1313 pipe_ctx->stream_res.opp,
1314 &stream->bit_depth_params,
1315 &stream->clamping);
1316
1317 if (dc_is_dp_signal(pipe_ctx->stream->signal))
1318 pipe_ctx->stream_res.stream_enc->funcs->dp_set_stream_attribute(
1319 pipe_ctx->stream_res.stream_enc,
1320 &stream->timing,
1321 stream->output_color_space);
1322
1323 if (dc_is_hdmi_signal(pipe_ctx->stream->signal))
1324 pipe_ctx->stream_res.stream_enc->funcs->hdmi_set_stream_attribute(
1325 pipe_ctx->stream_res.stream_enc,
1326 &stream->timing,
1327 stream->phy_pix_clk,
1328 pipe_ctx->stream_res.audio != NULL);
1329
1330 if (dc_is_dvi_signal(pipe_ctx->stream->signal))
1331 pipe_ctx->stream_res.stream_enc->funcs->dvi_set_stream_attribute(
1332 pipe_ctx->stream_res.stream_enc,
1333 &stream->timing,
1334 (pipe_ctx->stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK) ?
1335 true : false);
1336
1337 resource_build_info_frame(pipe_ctx);
1338 dce110_update_info_frame(pipe_ctx);
1339 if (!pipe_ctx_old->stream)
1340 core_link_enable_stream(context, pipe_ctx);
1341
1342 pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0;
1343
1344 pipe_ctx->stream->sink->link->psr_enabled = false;
1345
1346 return DC_OK;
1347}
1348
1349
1350
1351static void power_down_encoders(struct dc *dc)
1352{
1353 int i;
1354 enum connector_id connector_id;
1355 enum signal_type signal = SIGNAL_TYPE_NONE;
1356
1357
1358
1359
1360 for (i = 0; i < dc->res_pool->stream_enc_count; i++) {
1361 dc->res_pool->stream_enc[i]->funcs->dp_blank(
1362 dc->res_pool->stream_enc[i]);
1363 }
1364
1365 for (i = 0; i < dc->link_count; i++) {
1366 connector_id = dal_graphics_object_id_get_connector_id(dc->links[i]->link_id);
1367 if ((connector_id == CONNECTOR_ID_DISPLAY_PORT) ||
1368 (connector_id == CONNECTOR_ID_EDP)) {
1369
1370 if (!dc->links[i]->wa_flags.dp_keep_receiver_powered)
1371 dp_receiver_power_ctrl(dc->links[i], false);
1372 if (connector_id == CONNECTOR_ID_EDP)
1373 signal = SIGNAL_TYPE_EDP;
1374 }
1375
1376 dc->links[i]->link_enc->funcs->disable_output(
1377 dc->links[i]->link_enc, signal);
1378 }
1379}
1380
1381static void power_down_controllers(struct dc *dc)
1382{
1383 int i;
1384
1385 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1386 dc->res_pool->timing_generators[i]->funcs->disable_crtc(
1387 dc->res_pool->timing_generators[i]);
1388 }
1389}
1390
1391static void power_down_clock_sources(struct dc *dc)
1392{
1393 int i;
1394
1395 if (dc->res_pool->dp_clock_source->funcs->cs_power_down(
1396 dc->res_pool->dp_clock_source) == false)
1397 dm_error("Failed to power down pll! (dp clk src)\n");
1398
1399 for (i = 0; i < dc->res_pool->clk_src_count; i++) {
1400 if (dc->res_pool->clock_sources[i]->funcs->cs_power_down(
1401 dc->res_pool->clock_sources[i]) == false)
1402 dm_error("Failed to power down pll! (clk src index=%d)\n", i);
1403 }
1404}
1405
1406static void power_down_all_hw_blocks(struct dc *dc)
1407{
1408 power_down_encoders(dc);
1409
1410 power_down_controllers(dc);
1411
1412 power_down_clock_sources(dc);
1413
1414#if defined(CONFIG_DRM_AMD_DC_FBC)
1415 if (dc->fbc_compressor)
1416 dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor);
1417#endif
1418}
1419
1420static void disable_vga_and_power_gate_all_controllers(
1421 struct dc *dc)
1422{
1423 int i;
1424 struct timing_generator *tg;
1425 struct dc_context *ctx = dc->ctx;
1426
1427 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1428 tg = dc->res_pool->timing_generators[i];
1429
1430 if (tg->funcs->disable_vga)
1431 tg->funcs->disable_vga(tg);
1432
1433
1434
1435 enable_display_pipe_clock_gating(ctx,
1436 true);
1437
1438 dc->current_state->res_ctx.pipe_ctx[i].pipe_idx = i;
1439 dc->hwss.disable_plane(dc,
1440 &dc->current_state->res_ctx.pipe_ctx[i]);
1441 }
1442}
1443
1444static struct dc_link *get_link_for_edp_not_in_use(
1445 struct dc *dc,
1446 struct dc_state *context)
1447{
1448 int i;
1449 struct dc_link *link = NULL;
1450
1451
1452 for (i = 0; i < context->stream_count; i++) {
1453 if (context->streams[i]->signal == SIGNAL_TYPE_EDP)
1454 return NULL;
1455 }
1456
1457
1458 for (i = 0; i < dc->link_count; i++) {
1459 if (dc->links[i]->local_sink &&
1460 dc->links[i]->local_sink->sink_signal == SIGNAL_TYPE_EDP) {
1461 link = dc->links[i];
1462 break;
1463 }
1464 }
1465
1466 return link;
1467}
1468
1469
1470
1471
1472
1473
1474
1475
1476void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context)
1477{
1478 struct dc_bios *dcb = dc->ctx->dc_bios;
1479
1480
1481
1482
1483 bool can_eDP_fast_boot_optimize =
1484 (dcb->funcs->get_vga_enabled_displays(dc->ctx->dc_bios) == ATOM_DISPLAY_LCD1_ACTIVE);
1485
1486
1487 struct dc_link *edp_link_to_turnoff = NULL;
1488
1489 if (can_eDP_fast_boot_optimize) {
1490 edp_link_to_turnoff = get_link_for_edp_not_in_use(dc, context);
1491
1492 if (!edp_link_to_turnoff)
1493 dc->apply_edp_fast_boot_optimization = true;
1494 }
1495
1496 if (!dc->apply_edp_fast_boot_optimization) {
1497 if (edp_link_to_turnoff) {
1498
1499 dc->hwss.edp_backlight_control(edp_link_to_turnoff, false);
1500 }
1501
1502 power_down_all_hw_blocks(dc);
1503 disable_vga_and_power_gate_all_controllers(dc);
1504 if (edp_link_to_turnoff)
1505 dc->hwss.edp_power_control(edp_link_to_turnoff, false);
1506 }
1507 bios_set_scratch_acc_mode_change(dc->ctx->dc_bios);
1508}
1509
1510static uint32_t compute_pstate_blackout_duration(
1511 struct bw_fixed blackout_duration,
1512 const struct dc_stream_state *stream)
1513{
1514 uint32_t total_dest_line_time_ns;
1515 uint32_t pstate_blackout_duration_ns;
1516
1517 pstate_blackout_duration_ns = 1000 * blackout_duration.value >> 24;
1518
1519 total_dest_line_time_ns = 1000000UL *
1520 stream->timing.h_total /
1521 stream->timing.pix_clk_khz +
1522 pstate_blackout_duration_ns;
1523
1524 return total_dest_line_time_ns;
1525}
1526
1527static void dce110_set_displaymarks(
1528 const struct dc *dc,
1529 struct dc_state *context)
1530{
1531 uint8_t i, num_pipes;
1532 unsigned int underlay_idx = dc->res_pool->underlay_pipe_index;
1533
1534 for (i = 0, num_pipes = 0; i < MAX_PIPES; i++) {
1535 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1536 uint32_t total_dest_line_time_ns;
1537
1538 if (pipe_ctx->stream == NULL)
1539 continue;
1540
1541 total_dest_line_time_ns = compute_pstate_blackout_duration(
1542 dc->bw_vbios->blackout_duration, pipe_ctx->stream);
1543 pipe_ctx->plane_res.mi->funcs->mem_input_program_display_marks(
1544 pipe_ctx->plane_res.mi,
1545 context->bw.dce.nbp_state_change_wm_ns[num_pipes],
1546 context->bw.dce.stutter_exit_wm_ns[num_pipes],
1547 context->bw.dce.urgent_wm_ns[num_pipes],
1548 total_dest_line_time_ns);
1549 if (i == underlay_idx) {
1550 num_pipes++;
1551 pipe_ctx->plane_res.mi->funcs->mem_input_program_chroma_display_marks(
1552 pipe_ctx->plane_res.mi,
1553 context->bw.dce.nbp_state_change_wm_ns[num_pipes],
1554 context->bw.dce.stutter_exit_wm_ns[num_pipes],
1555 context->bw.dce.urgent_wm_ns[num_pipes],
1556 total_dest_line_time_ns);
1557 }
1558 num_pipes++;
1559 }
1560}
1561
1562static void set_safe_displaymarks(
1563 struct resource_context *res_ctx,
1564 const struct resource_pool *pool)
1565{
1566 int i;
1567 int underlay_idx = pool->underlay_pipe_index;
1568 struct dce_watermarks max_marks = {
1569 MAX_WATERMARK, MAX_WATERMARK, MAX_WATERMARK, MAX_WATERMARK };
1570 struct dce_watermarks nbp_marks = {
1571 SAFE_NBP_MARK, SAFE_NBP_MARK, SAFE_NBP_MARK, SAFE_NBP_MARK };
1572
1573 for (i = 0; i < MAX_PIPES; i++) {
1574 if (res_ctx->pipe_ctx[i].stream == NULL || res_ctx->pipe_ctx[i].plane_res.mi == NULL)
1575 continue;
1576
1577 res_ctx->pipe_ctx[i].plane_res.mi->funcs->mem_input_program_display_marks(
1578 res_ctx->pipe_ctx[i].plane_res.mi,
1579 nbp_marks,
1580 max_marks,
1581 max_marks,
1582 MAX_WATERMARK);
1583
1584 if (i == underlay_idx)
1585 res_ctx->pipe_ctx[i].plane_res.mi->funcs->mem_input_program_chroma_display_marks(
1586 res_ctx->pipe_ctx[i].plane_res.mi,
1587 nbp_marks,
1588 max_marks,
1589 max_marks,
1590 MAX_WATERMARK);
1591
1592 }
1593}
1594
1595
1596
1597
1598
1599static void set_drr(struct pipe_ctx **pipe_ctx,
1600 int num_pipes, int vmin, int vmax)
1601{
1602 int i = 0;
1603 struct drr_params params = {0};
1604
1605 params.vertical_total_max = vmax;
1606 params.vertical_total_min = vmin;
1607
1608
1609
1610
1611
1612 for (i = 0; i < num_pipes; i++) {
1613 pipe_ctx[i]->stream_res.tg->funcs->set_drr(pipe_ctx[i]->stream_res.tg, ¶ms);
1614 }
1615}
1616
1617static void get_position(struct pipe_ctx **pipe_ctx,
1618 int num_pipes,
1619 struct crtc_position *position)
1620{
1621 int i = 0;
1622
1623
1624
1625 for (i = 0; i < num_pipes; i++)
1626 pipe_ctx[i]->stream_res.tg->funcs->get_position(pipe_ctx[i]->stream_res.tg, position);
1627}
1628
1629static void set_static_screen_control(struct pipe_ctx **pipe_ctx,
1630 int num_pipes, const struct dc_static_screen_events *events)
1631{
1632 unsigned int i;
1633 unsigned int value = 0;
1634
1635 if (events->overlay_update)
1636 value |= 0x100;
1637 if (events->surface_update)
1638 value |= 0x80;
1639 if (events->cursor_update)
1640 value |= 0x2;
1641 if (events->force_trigger)
1642 value |= 0x1;
1643
1644#if defined(CONFIG_DRM_AMD_DC_FBC)
1645 value |= 0x84;
1646#endif
1647
1648 for (i = 0; i < num_pipes; i++)
1649 pipe_ctx[i]->stream_res.tg->funcs->
1650 set_static_screen_control(pipe_ctx[i]->stream_res.tg, value);
1651}
1652
1653
1654
1655
1656
1657
1658static uint32_t get_max_pixel_clock_for_all_paths(
1659 struct dc *dc,
1660 struct dc_state *context,
1661 bool pre_mode_set)
1662{
1663 uint32_t max_pix_clk = 0;
1664 int i;
1665
1666 if (!pre_mode_set) {
1667
1668 ASSERT(0);
1669 }
1670
1671 for (i = 0; i < MAX_PIPES; i++) {
1672 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1673
1674 if (pipe_ctx->stream == NULL)
1675 continue;
1676
1677
1678 if (pipe_ctx->top_pipe)
1679 continue;
1680
1681 if (pipe_ctx->stream_res.pix_clk_params.requested_pix_clk > max_pix_clk)
1682 max_pix_clk =
1683 pipe_ctx->stream_res.pix_clk_params.requested_pix_clk;
1684 }
1685
1686 if (max_pix_clk == 0)
1687 ASSERT(0);
1688
1689 return max_pix_clk;
1690}
1691
1692
1693
1694
1695
1696
1697static void apply_min_clocks(
1698 struct dc *dc,
1699 struct dc_state *context,
1700 enum dm_pp_clocks_state *clocks_state,
1701 bool pre_mode_set)
1702{
1703 struct state_dependent_clocks req_clocks = {0};
1704
1705 if (!pre_mode_set) {
1706
1707 if (context->dis_clk->funcs->set_min_clocks_state) {
1708 context->dis_clk->funcs->set_min_clocks_state(
1709 context->dis_clk, *clocks_state);
1710 return;
1711 }
1712
1713
1714 context->dis_clk->funcs->apply_clock_voltage_request(
1715 context->dis_clk,
1716 DM_PP_CLOCK_TYPE_DISPLAY_CLK,
1717 context->dis_clk->cur_clocks_value.dispclk_in_khz,
1718 pre_mode_set,
1719 false);
1720
1721 context->dis_clk->funcs->apply_clock_voltage_request(
1722 context->dis_clk,
1723 DM_PP_CLOCK_TYPE_PIXELCLK,
1724 context->dis_clk->cur_clocks_value.max_pixelclk_in_khz,
1725 pre_mode_set,
1726 false);
1727
1728 context->dis_clk->funcs->apply_clock_voltage_request(
1729 context->dis_clk,
1730 DM_PP_CLOCK_TYPE_DISPLAYPHYCLK,
1731 context->dis_clk->cur_clocks_value.max_non_dp_phyclk_in_khz,
1732 pre_mode_set,
1733 false);
1734 return;
1735 }
1736
1737
1738
1739
1740 req_clocks.display_clk_khz = context->bw.dce.dispclk_khz;
1741
1742 req_clocks.pixel_clk_khz = get_max_pixel_clock_for_all_paths(
1743 dc, context, true);
1744
1745 if (context->dis_clk->funcs->get_required_clocks_state) {
1746 *clocks_state = context->dis_clk->funcs->get_required_clocks_state(
1747 context->dis_clk, &req_clocks);
1748 context->dis_clk->funcs->set_min_clocks_state(
1749 context->dis_clk, *clocks_state);
1750 } else {
1751 context->dis_clk->funcs->apply_clock_voltage_request(
1752 context->dis_clk,
1753 DM_PP_CLOCK_TYPE_DISPLAY_CLK,
1754 req_clocks.display_clk_khz,
1755 pre_mode_set,
1756 false);
1757
1758 context->dis_clk->funcs->apply_clock_voltage_request(
1759 context->dis_clk,
1760 DM_PP_CLOCK_TYPE_PIXELCLK,
1761 req_clocks.pixel_clk_khz,
1762 pre_mode_set,
1763 false);
1764
1765 context->dis_clk->funcs->apply_clock_voltage_request(
1766 context->dis_clk,
1767 DM_PP_CLOCK_TYPE_DISPLAYPHYCLK,
1768 req_clocks.pixel_clk_khz,
1769 pre_mode_set,
1770 false);
1771 }
1772}
1773
1774#if defined(CONFIG_DRM_AMD_DC_FBC)
1775
1776
1777
1778
1779static bool should_enable_fbc(struct dc *dc,
1780 struct dc_state *context,
1781 uint32_t *pipe_idx)
1782{
1783 uint32_t i;
1784 struct pipe_ctx *pipe_ctx = NULL;
1785 struct resource_context *res_ctx = &context->res_ctx;
1786
1787
1788 ASSERT(dc->fbc_compressor);
1789
1790
1791 if (!dc->ctx->fbc_gpu_addr)
1792 return false;
1793
1794
1795 if (context->stream_count != 1)
1796 return false;
1797
1798 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1799 if (res_ctx->pipe_ctx[i].stream) {
1800 pipe_ctx = &res_ctx->pipe_ctx[i];
1801 *pipe_idx = i;
1802 break;
1803 }
1804 }
1805
1806
1807 if (pipe_ctx->stream->sink->link->connector_signal != SIGNAL_TYPE_EDP)
1808 return false;
1809
1810
1811 if (pipe_ctx->stream->sink->link->psr_enabled)
1812 return false;
1813
1814
1815 if (!pipe_ctx->plane_state)
1816 return false;
1817
1818
1819 if (pipe_ctx->plane_state->tiling_info.gfx8.array_mode == DC_ARRAY_LINEAR_GENERAL)
1820 return false;
1821
1822 return true;
1823}
1824
1825
1826
1827
1828static void enable_fbc(struct dc *dc,
1829 struct dc_state *context)
1830{
1831 uint32_t pipe_idx = 0;
1832
1833 if (should_enable_fbc(dc, context, &pipe_idx)) {
1834
1835 struct compr_addr_and_pitch_params params = {0, 0, 0};
1836 struct compressor *compr = dc->fbc_compressor;
1837 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[pipe_idx];
1838
1839
1840 params.source_view_width = pipe_ctx->stream->timing.h_addressable;
1841 params.source_view_height = pipe_ctx->stream->timing.v_addressable;
1842
1843 compr->compr_surface_address.quad_part = dc->ctx->fbc_gpu_addr;
1844
1845 compr->funcs->surface_address_and_pitch(compr, ¶ms);
1846 compr->funcs->set_fbc_invalidation_triggers(compr, 1);
1847
1848 compr->funcs->enable_fbc(compr, ¶ms);
1849 }
1850}
1851#endif
1852
1853static void dce110_reset_hw_ctx_wrap(
1854 struct dc *dc,
1855 struct dc_state *context)
1856{
1857 int i;
1858
1859
1860
1861 for (i = 0; i < MAX_PIPES; i++) {
1862 struct pipe_ctx *pipe_ctx_old =
1863 &dc->current_state->res_ctx.pipe_ctx[i];
1864 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1865
1866
1867
1868
1869
1870
1871
1872 if (!pipe_ctx_old->stream || pipe_ctx_old->top_pipe)
1873 continue;
1874
1875 if (!pipe_ctx->stream ||
1876 pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) {
1877 struct clock_source *old_clk = pipe_ctx_old->clock_source;
1878
1879
1880
1881
1882 if (!pipe_ctx->stream || !pipe_ctx->stream->dpms_off)
1883 core_link_disable_stream(pipe_ctx_old, FREE_ACQUIRED_RESOURCE);
1884
1885 pipe_ctx_old->stream_res.tg->funcs->set_blank(pipe_ctx_old->stream_res.tg, true);
1886 if (!hwss_wait_for_blank_complete(pipe_ctx_old->stream_res.tg)) {
1887 dm_error("DC: failed to blank crtc!\n");
1888 BREAK_TO_DEBUGGER();
1889 }
1890 pipe_ctx_old->stream_res.tg->funcs->disable_crtc(pipe_ctx_old->stream_res.tg);
1891 pipe_ctx_old->plane_res.mi->funcs->free_mem_input(
1892 pipe_ctx_old->plane_res.mi, dc->current_state->stream_count);
1893
1894 if (old_clk)
1895 old_clk->funcs->cs_power_down(old_clk);
1896
1897 dc->hwss.disable_plane(dc, pipe_ctx_old);
1898
1899 pipe_ctx_old->stream = NULL;
1900 }
1901 }
1902}
1903
1904
1905enum dc_status dce110_apply_ctx_to_hw(
1906 struct dc *dc,
1907 struct dc_state *context)
1908{
1909 struct dc_bios *dcb = dc->ctx->dc_bios;
1910 enum dc_status status;
1911 int i;
1912 enum dm_pp_clocks_state clocks_state = DM_PP_CLOCKS_STATE_INVALID;
1913
1914
1915
1916 dc->hwss.reset_hw_ctx_wrap(dc, context);
1917
1918
1919 if (context->stream_count <= 0)
1920 return DC_OK;
1921
1922
1923 dcb->funcs->set_scratch_critical_state(dcb, true);
1924
1925
1926 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1927 struct pipe_ctx *pipe_ctx_old =
1928 &dc->current_state->res_ctx.pipe_ctx[i];
1929 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1930
1931 if (pipe_ctx->stream == NULL || pipe_ctx->top_pipe)
1932 continue;
1933
1934 if (pipe_ctx->stream == pipe_ctx_old->stream) {
1935 if (pipe_ctx_old->clock_source != pipe_ctx->clock_source)
1936 dce_crtc_switch_to_clk_src(dc->hwseq,
1937 pipe_ctx->clock_source, i);
1938 continue;
1939 }
1940
1941 dc->hwss.enable_display_power_gating(
1942 dc, i, dc->ctx->dc_bios,
1943 PIPE_GATING_CONTROL_DISABLE);
1944 }
1945
1946 set_safe_displaymarks(&context->res_ctx, dc->res_pool);
1947
1948#if defined(CONFIG_DRM_AMD_DC_FBC)
1949 if (dc->fbc_compressor)
1950 dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor);
1951#endif
1952
1953 apply_min_clocks(dc, context, &clocks_state, true);
1954
1955#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
1956 if (dc->ctx->dce_version >= DCN_VERSION_1_0) {
1957 if (context->bw.dcn.calc_clk.fclk_khz
1958 > dc->current_state->bw.dcn.cur_clk.fclk_khz) {
1959 struct dm_pp_clock_for_voltage_req clock;
1960
1961 clock.clk_type = DM_PP_CLOCK_TYPE_FCLK;
1962 clock.clocks_in_khz = context->bw.dcn.calc_clk.fclk_khz;
1963 dm_pp_apply_clock_for_voltage_request(dc->ctx, &clock);
1964 dc->current_state->bw.dcn.cur_clk.fclk_khz = clock.clocks_in_khz;
1965 context->bw.dcn.cur_clk.fclk_khz = clock.clocks_in_khz;
1966 }
1967 if (context->bw.dcn.calc_clk.dcfclk_khz
1968 > dc->current_state->bw.dcn.cur_clk.dcfclk_khz) {
1969 struct dm_pp_clock_for_voltage_req clock;
1970
1971 clock.clk_type = DM_PP_CLOCK_TYPE_DCFCLK;
1972 clock.clocks_in_khz = context->bw.dcn.calc_clk.dcfclk_khz;
1973 dm_pp_apply_clock_for_voltage_request(dc->ctx, &clock);
1974 dc->current_state->bw.dcn.cur_clk.dcfclk_khz = clock.clocks_in_khz;
1975 context->bw.dcn.cur_clk.dcfclk_khz = clock.clocks_in_khz;
1976 }
1977 if (context->bw.dcn.calc_clk.dispclk_khz
1978 > dc->current_state->bw.dcn.cur_clk.dispclk_khz) {
1979 dc->res_pool->display_clock->funcs->set_clock(
1980 dc->res_pool->display_clock,
1981 context->bw.dcn.calc_clk.dispclk_khz);
1982 dc->current_state->bw.dcn.cur_clk.dispclk_khz =
1983 context->bw.dcn.calc_clk.dispclk_khz;
1984 context->bw.dcn.cur_clk.dispclk_khz =
1985 context->bw.dcn.calc_clk.dispclk_khz;
1986 }
1987 } else
1988#endif
1989 if (context->bw.dce.dispclk_khz
1990 > dc->current_state->bw.dce.dispclk_khz) {
1991 dc->res_pool->display_clock->funcs->set_clock(
1992 dc->res_pool->display_clock,
1993 context->bw.dce.dispclk_khz * 115 / 100);
1994 }
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2015 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2016
2017 if (pipe_ctx->stream == NULL)
2018 continue;
2019
2020 if (pipe_ctx->top_pipe)
2021 continue;
2022
2023 if (pipe_ctx->stream->signal != SIGNAL_TYPE_HDMI_TYPE_A)
2024 continue;
2025
2026 if (pipe_ctx->stream_res.audio != NULL) {
2027 struct audio_output audio_output;
2028
2029 build_audio_output(context, pipe_ctx, &audio_output);
2030
2031 pipe_ctx->stream_res.audio->funcs->wall_dto_setup(
2032 pipe_ctx->stream_res.audio,
2033 pipe_ctx->stream->signal,
2034 &audio_output.crtc_info,
2035 &audio_output.pll_info);
2036 break;
2037 }
2038 }
2039
2040
2041 if (i == dc->res_pool->pipe_count) {
2042 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2043 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2044
2045 if (pipe_ctx->stream == NULL)
2046 continue;
2047
2048 if (pipe_ctx->top_pipe)
2049 continue;
2050
2051 if (!dc_is_dp_signal(pipe_ctx->stream->signal))
2052 continue;
2053
2054 if (pipe_ctx->stream_res.audio != NULL) {
2055 struct audio_output audio_output;
2056
2057 build_audio_output(context, pipe_ctx, &audio_output);
2058
2059 pipe_ctx->stream_res.audio->funcs->wall_dto_setup(
2060 pipe_ctx->stream_res.audio,
2061 pipe_ctx->stream->signal,
2062 &audio_output.crtc_info,
2063 &audio_output.pll_info);
2064 break;
2065 }
2066 }
2067 }
2068
2069 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2070 struct pipe_ctx *pipe_ctx_old =
2071 &dc->current_state->res_ctx.pipe_ctx[i];
2072 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2073
2074 if (pipe_ctx->stream == NULL)
2075 continue;
2076
2077 if (pipe_ctx->stream == pipe_ctx_old->stream)
2078 continue;
2079
2080 if (pipe_ctx_old->stream && !pipe_need_reprogram(pipe_ctx_old, pipe_ctx))
2081 continue;
2082
2083 if (pipe_ctx->top_pipe)
2084 continue;
2085
2086 if (context->res_ctx.pipe_ctx[i].stream_res.audio != NULL) {
2087
2088 struct audio_output audio_output;
2089
2090 build_audio_output(context, pipe_ctx, &audio_output);
2091
2092 if (dc_is_dp_signal(pipe_ctx->stream->signal))
2093 pipe_ctx->stream_res.stream_enc->funcs->dp_audio_setup(
2094 pipe_ctx->stream_res.stream_enc,
2095 pipe_ctx->stream_res.audio->inst,
2096 &pipe_ctx->stream->audio_info);
2097 else
2098 pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_setup(
2099 pipe_ctx->stream_res.stream_enc,
2100 pipe_ctx->stream_res.audio->inst,
2101 &pipe_ctx->stream->audio_info,
2102 &audio_output.crtc_info);
2103
2104 pipe_ctx->stream_res.audio->funcs->az_configure(
2105 pipe_ctx->stream_res.audio,
2106 pipe_ctx->stream->signal,
2107 &audio_output.crtc_info,
2108 &pipe_ctx->stream->audio_info);
2109 }
2110
2111 status = apply_single_controller_ctx_to_hw(
2112 pipe_ctx,
2113 context,
2114 dc);
2115
2116 if (DC_OK != status)
2117 return status;
2118 }
2119
2120
2121 apply_min_clocks(dc, context, &clocks_state, false);
2122
2123 dcb->funcs->set_scratch_critical_state(dcb, false);
2124
2125#if defined(CONFIG_DRM_AMD_DC_FBC)
2126 if (dc->fbc_compressor)
2127 enable_fbc(dc, context);
2128
2129#endif
2130
2131 return DC_OK;
2132}
2133
2134
2135
2136
2137static void set_default_colors(struct pipe_ctx *pipe_ctx)
2138{
2139 struct default_adjustment default_adjust = { 0 };
2140
2141 default_adjust.force_hw_default = false;
2142 default_adjust.in_color_space = pipe_ctx->plane_state->color_space;
2143 default_adjust.out_color_space = pipe_ctx->stream->output_color_space;
2144 default_adjust.csc_adjust_type = GRAPHICS_CSC_ADJUST_TYPE_SW;
2145 default_adjust.surface_pixel_format = pipe_ctx->plane_res.scl_data.format;
2146
2147
2148 default_adjust.color_depth =
2149 pipe_ctx->stream->timing.display_color_depth;
2150
2151
2152 default_adjust.lb_color_depth = pipe_ctx->plane_res.scl_data.lb_params.depth;
2153
2154 pipe_ctx->plane_res.xfm->funcs->opp_set_csc_default(
2155 pipe_ctx->plane_res.xfm, &default_adjust);
2156}
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178static void program_surface_visibility(const struct dc *dc,
2179 struct pipe_ctx *pipe_ctx)
2180{
2181 enum blnd_mode blender_mode = BLND_MODE_CURRENT_PIPE;
2182 bool blank_target = false;
2183
2184 if (pipe_ctx->bottom_pipe) {
2185
2186
2187 ASSERT(pipe_ctx->bottom_pipe->bottom_pipe == NULL);
2188
2189 if (pipe_ctx->bottom_pipe->plane_state->visible) {
2190 if (pipe_ctx->plane_state->visible)
2191 blender_mode = BLND_MODE_BLENDING;
2192 else
2193 blender_mode = BLND_MODE_OTHER_PIPE;
2194
2195 } else if (!pipe_ctx->plane_state->visible)
2196 blank_target = true;
2197
2198 } else if (!pipe_ctx->plane_state->visible)
2199 blank_target = true;
2200
2201 dce_set_blender_mode(dc->hwseq, pipe_ctx->stream_res.tg->inst, blender_mode);
2202 pipe_ctx->stream_res.tg->funcs->set_blank(pipe_ctx->stream_res.tg, blank_target);
2203
2204}
2205
2206static void program_gamut_remap(struct pipe_ctx *pipe_ctx)
2207{
2208 int i = 0;
2209 struct xfm_grph_csc_adjustment adjust;
2210 memset(&adjust, 0, sizeof(adjust));
2211 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS;
2212
2213
2214 if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) {
2215 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW;
2216
2217 for (i = 0; i < CSC_TEMPERATURE_MATRIX_SIZE; i++)
2218 adjust.temperature_matrix[i] =
2219 pipe_ctx->stream->gamut_remap_matrix.matrix[i];
2220 }
2221
2222 pipe_ctx->plane_res.xfm->funcs->transform_set_gamut_remap(pipe_ctx->plane_res.xfm, &adjust);
2223}
2224
2225
2226
2227
2228static void set_plane_config(
2229 const struct dc *dc,
2230 struct pipe_ctx *pipe_ctx,
2231 struct resource_context *res_ctx)
2232{
2233 struct mem_input *mi = pipe_ctx->plane_res.mi;
2234 struct dc_plane_state *plane_state = pipe_ctx->plane_state;
2235 struct xfm_grph_csc_adjustment adjust;
2236 struct out_csc_color_matrix tbl_entry;
2237 unsigned int i;
2238
2239 memset(&adjust, 0, sizeof(adjust));
2240 memset(&tbl_entry, 0, sizeof(tbl_entry));
2241 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS;
2242
2243 dce_enable_fe_clock(dc->hwseq, mi->inst, true);
2244
2245 set_default_colors(pipe_ctx);
2246 if (pipe_ctx->stream->csc_color_matrix.enable_adjustment == true) {
2247 tbl_entry.color_space =
2248 pipe_ctx->stream->output_color_space;
2249
2250 for (i = 0; i < 12; i++)
2251 tbl_entry.regval[i] =
2252 pipe_ctx->stream->csc_color_matrix.matrix[i];
2253
2254 pipe_ctx->plane_res.xfm->funcs->opp_set_csc_adjustment
2255 (pipe_ctx->plane_res.xfm, &tbl_entry);
2256 }
2257
2258 if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) {
2259 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW;
2260
2261 for (i = 0; i < CSC_TEMPERATURE_MATRIX_SIZE; i++)
2262 adjust.temperature_matrix[i] =
2263 pipe_ctx->stream->gamut_remap_matrix.matrix[i];
2264 }
2265
2266 pipe_ctx->plane_res.xfm->funcs->transform_set_gamut_remap(pipe_ctx->plane_res.xfm, &adjust);
2267
2268 pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0;
2269 program_scaler(dc, pipe_ctx);
2270
2271 program_surface_visibility(dc, pipe_ctx);
2272
2273 mi->funcs->mem_input_program_surface_config(
2274 mi,
2275 plane_state->format,
2276 &plane_state->tiling_info,
2277 &plane_state->plane_size,
2278 plane_state->rotation,
2279 NULL,
2280 false);
2281 if (mi->funcs->set_blank)
2282 mi->funcs->set_blank(mi, pipe_ctx->plane_state->visible);
2283
2284 if (dc->config.gpu_vm_support)
2285 mi->funcs->mem_input_program_pte_vm(
2286 pipe_ctx->plane_res.mi,
2287 plane_state->format,
2288 &plane_state->tiling_info,
2289 plane_state->rotation);
2290}
2291
2292static void update_plane_addr(const struct dc *dc,
2293 struct pipe_ctx *pipe_ctx)
2294{
2295 struct dc_plane_state *plane_state = pipe_ctx->plane_state;
2296
2297 if (plane_state == NULL)
2298 return;
2299
2300 pipe_ctx->plane_res.mi->funcs->mem_input_program_surface_flip_and_addr(
2301 pipe_ctx->plane_res.mi,
2302 &plane_state->address,
2303 plane_state->flip_immediate);
2304
2305 plane_state->status.requested_address = plane_state->address;
2306}
2307
2308static void dce110_update_pending_status(struct pipe_ctx *pipe_ctx)
2309{
2310 struct dc_plane_state *plane_state = pipe_ctx->plane_state;
2311
2312 if (plane_state == NULL)
2313 return;
2314
2315 plane_state->status.is_flip_pending =
2316 pipe_ctx->plane_res.mi->funcs->mem_input_is_flip_pending(
2317 pipe_ctx->plane_res.mi);
2318
2319 if (plane_state->status.is_flip_pending && !plane_state->visible)
2320 pipe_ctx->plane_res.mi->current_address = pipe_ctx->plane_res.mi->request_address;
2321
2322 plane_state->status.current_address = pipe_ctx->plane_res.mi->current_address;
2323 if (pipe_ctx->plane_res.mi->current_address.type == PLN_ADDR_TYPE_GRPH_STEREO &&
2324 pipe_ctx->stream_res.tg->funcs->is_stereo_left_eye) {
2325 plane_state->status.is_right_eye =\
2326 !pipe_ctx->stream_res.tg->funcs->is_stereo_left_eye(pipe_ctx->stream_res.tg);
2327 }
2328}
2329
2330void dce110_power_down(struct dc *dc)
2331{
2332 power_down_all_hw_blocks(dc);
2333 disable_vga_and_power_gate_all_controllers(dc);
2334}
2335
2336static bool wait_for_reset_trigger_to_occur(
2337 struct dc_context *dc_ctx,
2338 struct timing_generator *tg)
2339{
2340 bool rc = false;
2341
2342
2343
2344 const uint32_t frames_to_wait_on_triggered_reset = 10;
2345 uint32_t i;
2346
2347 for (i = 0; i < frames_to_wait_on_triggered_reset; i++) {
2348
2349 if (!tg->funcs->is_counter_moving(tg)) {
2350 DC_ERROR("TG counter is not moving!\n");
2351 break;
2352 }
2353
2354 if (tg->funcs->did_triggered_reset_occur(tg)) {
2355 rc = true;
2356
2357 DC_SYNC_INFO("GSL: reset occurred at wait count: %d\n",
2358 i);
2359 break;
2360 }
2361
2362
2363 tg->funcs->wait_for_state(tg, CRTC_STATE_VACTIVE);
2364 tg->funcs->wait_for_state(tg, CRTC_STATE_VBLANK);
2365 }
2366
2367 if (false == rc)
2368 DC_ERROR("GSL: Timeout on reset trigger!\n");
2369
2370 return rc;
2371}
2372
2373
2374static void dce110_enable_timing_synchronization(
2375 struct dc *dc,
2376 int group_index,
2377 int group_size,
2378 struct pipe_ctx *grouped_pipes[])
2379{
2380 struct dc_context *dc_ctx = dc->ctx;
2381 struct dcp_gsl_params gsl_params = { 0 };
2382 int i;
2383
2384 DC_SYNC_INFO("GSL: Setting-up...\n");
2385
2386
2387
2388
2389 gsl_params.gsl_group = 0;
2390 gsl_params.gsl_master = grouped_pipes[0]->stream_res.tg->inst;
2391
2392 for (i = 0; i < group_size; i++)
2393 grouped_pipes[i]->stream_res.tg->funcs->setup_global_swap_lock(
2394 grouped_pipes[i]->stream_res.tg, &gsl_params);
2395
2396
2397 DC_SYNC_INFO("GSL: enabling trigger-reset\n");
2398
2399 for (i = 1 ; i < group_size; i++)
2400 grouped_pipes[i]->stream_res.tg->funcs->enable_reset_trigger(
2401 grouped_pipes[i]->stream_res.tg,
2402 gsl_params.gsl_group);
2403
2404 for (i = 1 ; i < group_size; i++) {
2405 DC_SYNC_INFO("GSL: waiting for reset to occur.\n");
2406 wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[i]->stream_res.tg);
2407 grouped_pipes[i]->stream_res.tg->funcs->disable_reset_trigger(
2408 grouped_pipes[i]->stream_res.tg);
2409 }
2410
2411
2412
2413 DC_SYNC_INFO("GSL: Restoring register states.\n");
2414 for (i = 0; i < group_size; i++)
2415 grouped_pipes[i]->stream_res.tg->funcs->tear_down_global_swap_lock(grouped_pipes[i]->stream_res.tg);
2416
2417 DC_SYNC_INFO("GSL: Set-up complete.\n");
2418}
2419
2420static void dce110_enable_per_frame_crtc_position_reset(
2421 struct dc *dc,
2422 int group_size,
2423 struct pipe_ctx *grouped_pipes[])
2424{
2425 struct dc_context *dc_ctx = dc->ctx;
2426 struct dcp_gsl_params gsl_params = { 0 };
2427 int i;
2428
2429 gsl_params.gsl_group = 0;
2430 gsl_params.gsl_master = grouped_pipes[0]->stream->triggered_crtc_reset.event_source->status.primary_otg_inst;
2431
2432 for (i = 0; i < group_size; i++)
2433 grouped_pipes[i]->stream_res.tg->funcs->setup_global_swap_lock(
2434 grouped_pipes[i]->stream_res.tg, &gsl_params);
2435
2436 DC_SYNC_INFO("GSL: enabling trigger-reset\n");
2437
2438 for (i = 1; i < group_size; i++)
2439 grouped_pipes[i]->stream_res.tg->funcs->enable_crtc_reset(
2440 grouped_pipes[i]->stream_res.tg,
2441 gsl_params.gsl_master,
2442 &grouped_pipes[i]->stream->triggered_crtc_reset);
2443
2444 DC_SYNC_INFO("GSL: waiting for reset to occur.\n");
2445 for (i = 1; i < group_size; i++)
2446 wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[i]->stream_res.tg);
2447
2448 for (i = 0; i < group_size; i++)
2449 grouped_pipes[i]->stream_res.tg->funcs->tear_down_global_swap_lock(grouped_pipes[i]->stream_res.tg);
2450
2451}
2452
2453static void init_hw(struct dc *dc)
2454{
2455 int i;
2456 struct dc_bios *bp;
2457 struct transform *xfm;
2458 struct abm *abm;
2459
2460 bp = dc->ctx->dc_bios;
2461 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2462 xfm = dc->res_pool->transforms[i];
2463 xfm->funcs->transform_reset(xfm);
2464
2465 dc->hwss.enable_display_power_gating(
2466 dc, i, bp,
2467 PIPE_GATING_CONTROL_INIT);
2468 dc->hwss.enable_display_power_gating(
2469 dc, i, bp,
2470 PIPE_GATING_CONTROL_DISABLE);
2471 dc->hwss.enable_display_pipe_clock_gating(
2472 dc->ctx,
2473 true);
2474 }
2475
2476 dce_clock_gating_power_up(dc->hwseq, false);
2477
2478
2479 for (i = 0; i < dc->link_count; i++) {
2480
2481
2482
2483
2484 struct dc_link *link = dc->links[i];
2485
2486 if (link->link_enc->connector.id == CONNECTOR_ID_EDP)
2487 dc->hwss.edp_power_control(link, true);
2488
2489 link->link_enc->funcs->hw_init(link->link_enc);
2490 }
2491
2492 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2493 struct timing_generator *tg = dc->res_pool->timing_generators[i];
2494
2495 tg->funcs->disable_vga(tg);
2496
2497
2498
2499 tg->funcs->set_blank(tg, true);
2500 hwss_wait_for_blank_complete(tg);
2501 }
2502
2503 for (i = 0; i < dc->res_pool->audio_count; i++) {
2504 struct audio *audio = dc->res_pool->audios[i];
2505 audio->funcs->hw_init(audio);
2506 }
2507
2508 abm = dc->res_pool->abm;
2509 if (abm != NULL) {
2510 abm->funcs->init_backlight(abm);
2511 abm->funcs->abm_init(abm);
2512 }
2513#if defined(CONFIG_DRM_AMD_DC_FBC)
2514 if (dc->fbc_compressor)
2515 dc->fbc_compressor->funcs->power_up_fbc(dc->fbc_compressor);
2516#endif
2517
2518}
2519
2520void dce110_fill_display_configs(
2521 const struct dc_state *context,
2522 struct dm_pp_display_configuration *pp_display_cfg)
2523{
2524 int j;
2525 int num_cfgs = 0;
2526
2527 for (j = 0; j < context->stream_count; j++) {
2528 int k;
2529
2530 const struct dc_stream_state *stream = context->streams[j];
2531 struct dm_pp_single_disp_config *cfg =
2532 &pp_display_cfg->disp_configs[num_cfgs];
2533 const struct pipe_ctx *pipe_ctx = NULL;
2534
2535 for (k = 0; k < MAX_PIPES; k++)
2536 if (stream == context->res_ctx.pipe_ctx[k].stream) {
2537 pipe_ctx = &context->res_ctx.pipe_ctx[k];
2538 break;
2539 }
2540
2541 ASSERT(pipe_ctx != NULL);
2542
2543
2544 if (stream->dpms_off)
2545 continue;
2546
2547 num_cfgs++;
2548 cfg->signal = pipe_ctx->stream->signal;
2549 cfg->pipe_idx = pipe_ctx->stream_res.tg->inst;
2550 cfg->src_height = stream->src.height;
2551 cfg->src_width = stream->src.width;
2552 cfg->ddi_channel_mapping =
2553 stream->sink->link->ddi_channel_mapping.raw;
2554 cfg->transmitter =
2555 stream->sink->link->link_enc->transmitter;
2556 cfg->link_settings.lane_count =
2557 stream->sink->link->cur_link_settings.lane_count;
2558 cfg->link_settings.link_rate =
2559 stream->sink->link->cur_link_settings.link_rate;
2560 cfg->link_settings.link_spread =
2561 stream->sink->link->cur_link_settings.link_spread;
2562 cfg->sym_clock = stream->phy_pix_clk;
2563
2564 cfg->v_refresh = stream->timing.pix_clk_khz * 1000;
2565 cfg->v_refresh /= stream->timing.h_total;
2566 cfg->v_refresh = (cfg->v_refresh + stream->timing.v_total / 2)
2567 / stream->timing.v_total;
2568 }
2569
2570 pp_display_cfg->display_count = num_cfgs;
2571}
2572
2573uint32_t dce110_get_min_vblank_time_us(const struct dc_state *context)
2574{
2575 uint8_t j;
2576 uint32_t min_vertical_blank_time = -1;
2577
2578 for (j = 0; j < context->stream_count; j++) {
2579 struct dc_stream_state *stream = context->streams[j];
2580 uint32_t vertical_blank_in_pixels = 0;
2581 uint32_t vertical_blank_time = 0;
2582
2583 vertical_blank_in_pixels = stream->timing.h_total *
2584 (stream->timing.v_total
2585 - stream->timing.v_addressable);
2586
2587 vertical_blank_time = vertical_blank_in_pixels
2588 * 1000 / stream->timing.pix_clk_khz;
2589
2590 if (min_vertical_blank_time > vertical_blank_time)
2591 min_vertical_blank_time = vertical_blank_time;
2592 }
2593
2594 return min_vertical_blank_time;
2595}
2596
2597static int determine_sclk_from_bounding_box(
2598 const struct dc *dc,
2599 int required_sclk)
2600{
2601 int i;
2602
2603
2604
2605
2606
2607 if (dc->sclk_lvls.num_levels == 0)
2608 return required_sclk;
2609
2610 for (i = 0; i < dc->sclk_lvls.num_levels; i++) {
2611 if (dc->sclk_lvls.clocks_in_khz[i] >= required_sclk)
2612 return dc->sclk_lvls.clocks_in_khz[i];
2613 }
2614
2615
2616
2617
2618
2619 ASSERT(0);
2620 return dc->sclk_lvls.clocks_in_khz[dc->sclk_lvls.num_levels - 1];
2621}
2622
2623static void pplib_apply_display_requirements(
2624 struct dc *dc,
2625 struct dc_state *context)
2626{
2627 struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg;
2628
2629 pp_display_cfg->all_displays_in_sync =
2630 context->bw.dce.all_displays_in_sync;
2631 pp_display_cfg->nb_pstate_switch_disable =
2632 context->bw.dce.nbp_state_change_enable == false;
2633 pp_display_cfg->cpu_cc6_disable =
2634 context->bw.dce.cpuc_state_change_enable == false;
2635 pp_display_cfg->cpu_pstate_disable =
2636 context->bw.dce.cpup_state_change_enable == false;
2637 pp_display_cfg->cpu_pstate_separation_time =
2638 context->bw.dce.blackout_recovery_time_us;
2639
2640 pp_display_cfg->min_memory_clock_khz = context->bw.dce.yclk_khz
2641 / MEMORY_TYPE_MULTIPLIER;
2642
2643 pp_display_cfg->min_engine_clock_khz = determine_sclk_from_bounding_box(
2644 dc,
2645 context->bw.dce.sclk_khz);
2646
2647 pp_display_cfg->min_engine_clock_deep_sleep_khz
2648 = context->bw.dce.sclk_deep_sleep_khz;
2649
2650 pp_display_cfg->avail_mclk_switch_time_us =
2651 dce110_get_min_vblank_time_us(context);
2652
2653 pp_display_cfg->avail_mclk_switch_time_in_disp_active_us = 0;
2654
2655 pp_display_cfg->disp_clk_khz = context->bw.dce.dispclk_khz;
2656
2657 dce110_fill_display_configs(context, pp_display_cfg);
2658
2659
2660 if (pp_display_cfg->display_count == 1) {
2661 const struct dc_crtc_timing *timing =
2662 &context->streams[0]->timing;
2663
2664 pp_display_cfg->crtc_index =
2665 pp_display_cfg->disp_configs[0].pipe_idx;
2666 pp_display_cfg->line_time_in_us = timing->h_total * 1000
2667 / timing->pix_clk_khz;
2668 }
2669
2670 if (memcmp(&dc->prev_display_config, pp_display_cfg, sizeof(
2671 struct dm_pp_display_configuration)) != 0)
2672 dm_pp_apply_display_requirements(dc->ctx, pp_display_cfg);
2673
2674 dc->prev_display_config = *pp_display_cfg;
2675}
2676
2677static void dce110_set_bandwidth(
2678 struct dc *dc,
2679 struct dc_state *context,
2680 bool decrease_allowed)
2681{
2682 dce110_set_displaymarks(dc, context);
2683
2684 if (decrease_allowed || context->bw.dce.dispclk_khz > dc->current_state->bw.dce.dispclk_khz) {
2685 dc->res_pool->display_clock->funcs->set_clock(
2686 dc->res_pool->display_clock,
2687 context->bw.dce.dispclk_khz * 115 / 100);
2688 dc->current_state->bw.dce.dispclk_khz = context->bw.dce.dispclk_khz;
2689 }
2690
2691 pplib_apply_display_requirements(dc, context);
2692}
2693
2694static void dce110_program_front_end_for_pipe(
2695 struct dc *dc, struct pipe_ctx *pipe_ctx)
2696{
2697 struct mem_input *mi = pipe_ctx->plane_res.mi;
2698 struct pipe_ctx *old_pipe = NULL;
2699 struct dc_plane_state *plane_state = pipe_ctx->plane_state;
2700 struct xfm_grph_csc_adjustment adjust;
2701 struct out_csc_color_matrix tbl_entry;
2702 unsigned int i;
2703 struct dc_context *ctx = dc->ctx;
2704 memset(&tbl_entry, 0, sizeof(tbl_entry));
2705
2706 if (dc->current_state)
2707 old_pipe = &dc->current_state->res_ctx.pipe_ctx[pipe_ctx->pipe_idx];
2708
2709 memset(&adjust, 0, sizeof(adjust));
2710 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS;
2711
2712 dce_enable_fe_clock(dc->hwseq, mi->inst, true);
2713
2714 set_default_colors(pipe_ctx);
2715 if (pipe_ctx->stream->csc_color_matrix.enable_adjustment
2716 == true) {
2717 tbl_entry.color_space =
2718 pipe_ctx->stream->output_color_space;
2719
2720 for (i = 0; i < 12; i++)
2721 tbl_entry.regval[i] =
2722 pipe_ctx->stream->csc_color_matrix.matrix[i];
2723
2724 pipe_ctx->plane_res.xfm->funcs->opp_set_csc_adjustment
2725 (pipe_ctx->plane_res.xfm, &tbl_entry);
2726 }
2727
2728 if (pipe_ctx->stream->gamut_remap_matrix.enable_remap == true) {
2729 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW;
2730
2731 for (i = 0; i < CSC_TEMPERATURE_MATRIX_SIZE; i++)
2732 adjust.temperature_matrix[i] =
2733 pipe_ctx->stream->gamut_remap_matrix.matrix[i];
2734 }
2735
2736 pipe_ctx->plane_res.xfm->funcs->transform_set_gamut_remap(pipe_ctx->plane_res.xfm, &adjust);
2737
2738 pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0;
2739
2740 program_scaler(dc, pipe_ctx);
2741
2742#if defined(CONFIG_DRM_AMD_DC_FBC)
2743 if (dc->fbc_compressor && old_pipe->stream) {
2744 if (plane_state->tiling_info.gfx8.array_mode == DC_ARRAY_LINEAR_GENERAL)
2745 dc->fbc_compressor->funcs->disable_fbc(dc->fbc_compressor);
2746 else
2747 enable_fbc(dc, dc->current_state);
2748 }
2749#endif
2750
2751 mi->funcs->mem_input_program_surface_config(
2752 mi,
2753 plane_state->format,
2754 &plane_state->tiling_info,
2755 &plane_state->plane_size,
2756 plane_state->rotation,
2757 NULL,
2758 false);
2759 if (mi->funcs->set_blank)
2760 mi->funcs->set_blank(mi, pipe_ctx->plane_state->visible);
2761
2762 if (dc->config.gpu_vm_support)
2763 mi->funcs->mem_input_program_pte_vm(
2764 pipe_ctx->plane_res.mi,
2765 plane_state->format,
2766 &plane_state->tiling_info,
2767 plane_state->rotation);
2768
2769
2770 if (pipe_ctx->plane_state->update_flags.bits.full_update ||
2771 pipe_ctx->plane_state->update_flags.bits.in_transfer_func_change ||
2772 pipe_ctx->plane_state->update_flags.bits.gamma_change)
2773 dc->hwss.set_input_transfer_func(pipe_ctx, pipe_ctx->plane_state);
2774
2775 if (pipe_ctx->plane_state->update_flags.bits.full_update)
2776 dc->hwss.set_output_transfer_func(pipe_ctx, pipe_ctx->stream);
2777
2778 DC_LOG_SURFACE(
2779 "Pipe:%d 0x%x: addr hi:0x%x, "
2780 "addr low:0x%x, "
2781 "src: %d, %d, %d,"
2782 " %d; dst: %d, %d, %d, %d;"
2783 "clip: %d, %d, %d, %d\n",
2784 pipe_ctx->pipe_idx,
2785 pipe_ctx->plane_state,
2786 pipe_ctx->plane_state->address.grph.addr.high_part,
2787 pipe_ctx->plane_state->address.grph.addr.low_part,
2788 pipe_ctx->plane_state->src_rect.x,
2789 pipe_ctx->plane_state->src_rect.y,
2790 pipe_ctx->plane_state->src_rect.width,
2791 pipe_ctx->plane_state->src_rect.height,
2792 pipe_ctx->plane_state->dst_rect.x,
2793 pipe_ctx->plane_state->dst_rect.y,
2794 pipe_ctx->plane_state->dst_rect.width,
2795 pipe_ctx->plane_state->dst_rect.height,
2796 pipe_ctx->plane_state->clip_rect.x,
2797 pipe_ctx->plane_state->clip_rect.y,
2798 pipe_ctx->plane_state->clip_rect.width,
2799 pipe_ctx->plane_state->clip_rect.height);
2800
2801 DC_LOG_SURFACE(
2802 "Pipe %d: width, height, x, y\n"
2803 "viewport:%d, %d, %d, %d\n"
2804 "recout: %d, %d, %d, %d\n",
2805 pipe_ctx->pipe_idx,
2806 pipe_ctx->plane_res.scl_data.viewport.width,
2807 pipe_ctx->plane_res.scl_data.viewport.height,
2808 pipe_ctx->plane_res.scl_data.viewport.x,
2809 pipe_ctx->plane_res.scl_data.viewport.y,
2810 pipe_ctx->plane_res.scl_data.recout.width,
2811 pipe_ctx->plane_res.scl_data.recout.height,
2812 pipe_ctx->plane_res.scl_data.recout.x,
2813 pipe_ctx->plane_res.scl_data.recout.y);
2814}
2815
2816static void dce110_apply_ctx_for_surface(
2817 struct dc *dc,
2818 const struct dc_stream_state *stream,
2819 int num_planes,
2820 struct dc_state *context)
2821{
2822 int i;
2823
2824 if (num_planes == 0)
2825 return;
2826
2827 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2828 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2829 struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
2830
2831 if (stream == pipe_ctx->stream) {
2832 if (!pipe_ctx->top_pipe &&
2833 (pipe_ctx->plane_state || old_pipe_ctx->plane_state))
2834 dc->hwss.pipe_control_lock(dc, pipe_ctx, true);
2835 }
2836 }
2837
2838 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2839 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2840
2841 if (pipe_ctx->stream != stream)
2842 continue;
2843
2844
2845 pipe_ctx->plane_res.mi->funcs->allocate_mem_input(
2846 pipe_ctx->plane_res.mi,
2847 pipe_ctx->stream->timing.h_total,
2848 pipe_ctx->stream->timing.v_total,
2849 pipe_ctx->stream->timing.pix_clk_khz,
2850 context->stream_count);
2851
2852 dce110_program_front_end_for_pipe(dc, pipe_ctx);
2853
2854 dc->hwss.update_plane_addr(dc, pipe_ctx);
2855
2856 program_surface_visibility(dc, pipe_ctx);
2857
2858 }
2859
2860 for (i = 0; i < dc->res_pool->pipe_count; i++) {
2861 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
2862 struct pipe_ctx *old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
2863
2864 if ((stream == pipe_ctx->stream) &&
2865 (!pipe_ctx->top_pipe) &&
2866 (pipe_ctx->plane_state || old_pipe_ctx->plane_state))
2867 dc->hwss.pipe_control_lock(dc, pipe_ctx, false);
2868 }
2869}
2870
2871static void dce110_power_down_fe(struct dc *dc, struct pipe_ctx *pipe_ctx)
2872{
2873 int fe_idx = pipe_ctx->plane_res.mi ?
2874 pipe_ctx->plane_res.mi->inst : pipe_ctx->pipe_idx;
2875
2876
2877 if (dc->current_state->res_ctx.pipe_ctx[fe_idx].stream)
2878 return;
2879
2880 dc->hwss.enable_display_power_gating(
2881 dc, fe_idx, dc->ctx->dc_bios, PIPE_GATING_CONTROL_ENABLE);
2882
2883 dc->res_pool->transforms[fe_idx]->funcs->transform_reset(
2884 dc->res_pool->transforms[fe_idx]);
2885}
2886
2887static void dce110_wait_for_mpcc_disconnect(
2888 struct dc *dc,
2889 struct resource_pool *res_pool,
2890 struct pipe_ctx *pipe_ctx)
2891{
2892
2893}
2894
2895static void program_csc_matrix(struct pipe_ctx *pipe_ctx,
2896 enum dc_color_space colorspace,
2897 uint16_t *matrix)
2898{
2899 int i;
2900 struct out_csc_color_matrix tbl_entry;
2901
2902 if (pipe_ctx->stream->csc_color_matrix.enable_adjustment
2903 == true) {
2904 enum dc_color_space color_space =
2905 pipe_ctx->stream->output_color_space;
2906
2907
2908 for (i = 0; i < 12; i++)
2909 tbl_entry.regval[i] = pipe_ctx->stream->csc_color_matrix.matrix[i];
2910
2911 tbl_entry.color_space = color_space;
2912
2913 pipe_ctx->plane_res.xfm->funcs->opp_set_csc_adjustment(pipe_ctx->plane_res.xfm, &tbl_entry);
2914 }
2915}
2916
2917void dce110_set_cursor_position(struct pipe_ctx *pipe_ctx)
2918{
2919 struct dc_cursor_position pos_cpy = pipe_ctx->stream->cursor_position;
2920 struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp;
2921 struct mem_input *mi = pipe_ctx->plane_res.mi;
2922 struct dc_cursor_mi_param param = {
2923 .pixel_clk_khz = pipe_ctx->stream->timing.pix_clk_khz,
2924 .ref_clk_khz = pipe_ctx->stream->ctx->dc->res_pool->ref_clock_inKhz,
2925 .viewport_x_start = pipe_ctx->plane_res.scl_data.viewport.x,
2926 .viewport_width = pipe_ctx->plane_res.scl_data.viewport.width,
2927 .h_scale_ratio = pipe_ctx->plane_res.scl_data.ratios.horz
2928 };
2929
2930 if (pipe_ctx->plane_state->address.type
2931 == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE)
2932 pos_cpy.enable = false;
2933
2934 if (pipe_ctx->top_pipe && pipe_ctx->plane_state != pipe_ctx->top_pipe->plane_state)
2935 pos_cpy.enable = false;
2936
2937 if (ipp->funcs->ipp_cursor_set_position)
2938 ipp->funcs->ipp_cursor_set_position(ipp, &pos_cpy, ¶m);
2939 if (mi->funcs->set_cursor_position)
2940 mi->funcs->set_cursor_position(mi, &pos_cpy, ¶m);
2941}
2942
2943void dce110_set_cursor_attribute(struct pipe_ctx *pipe_ctx)
2944{
2945 struct dc_cursor_attributes *attributes = &pipe_ctx->stream->cursor_attributes;
2946
2947 if (pipe_ctx->plane_res.ipp &&
2948 pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes)
2949 pipe_ctx->plane_res.ipp->funcs->ipp_cursor_set_attributes(
2950 pipe_ctx->plane_res.ipp, attributes);
2951
2952 if (pipe_ctx->plane_res.mi &&
2953 pipe_ctx->plane_res.mi->funcs->set_cursor_attributes)
2954 pipe_ctx->plane_res.mi->funcs->set_cursor_attributes(
2955 pipe_ctx->plane_res.mi, attributes);
2956
2957 if (pipe_ctx->plane_res.xfm &&
2958 pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes)
2959 pipe_ctx->plane_res.xfm->funcs->set_cursor_attributes(
2960 pipe_ctx->plane_res.xfm, attributes);
2961}
2962
2963static void ready_shared_resources(struct dc *dc, struct dc_state *context) {}
2964
2965static void optimize_shared_resources(struct dc *dc) {}
2966
2967static const struct hw_sequencer_funcs dce110_funcs = {
2968 .program_gamut_remap = program_gamut_remap,
2969 .program_csc_matrix = program_csc_matrix,
2970 .init_hw = init_hw,
2971 .apply_ctx_to_hw = dce110_apply_ctx_to_hw,
2972 .apply_ctx_for_surface = dce110_apply_ctx_for_surface,
2973 .set_plane_config = set_plane_config,
2974 .update_plane_addr = update_plane_addr,
2975 .update_pending_status = dce110_update_pending_status,
2976 .set_input_transfer_func = dce110_set_input_transfer_func,
2977 .set_output_transfer_func = dce110_set_output_transfer_func,
2978 .power_down = dce110_power_down,
2979 .enable_accelerated_mode = dce110_enable_accelerated_mode,
2980 .enable_timing_synchronization = dce110_enable_timing_synchronization,
2981 .enable_per_frame_crtc_position_reset = dce110_enable_per_frame_crtc_position_reset,
2982 .update_info_frame = dce110_update_info_frame,
2983 .enable_stream = dce110_enable_stream,
2984 .disable_stream = dce110_disable_stream,
2985 .unblank_stream = dce110_unblank_stream,
2986 .blank_stream = dce110_blank_stream,
2987 .enable_display_pipe_clock_gating = enable_display_pipe_clock_gating,
2988 .enable_display_power_gating = dce110_enable_display_power_gating,
2989 .disable_plane = dce110_power_down_fe,
2990 .pipe_control_lock = dce_pipe_control_lock,
2991 .set_bandwidth = dce110_set_bandwidth,
2992 .set_drr = set_drr,
2993 .get_position = get_position,
2994 .set_static_screen_control = set_static_screen_control,
2995 .reset_hw_ctx_wrap = dce110_reset_hw_ctx_wrap,
2996 .prog_pixclk_crtc_otg = dce110_prog_pixclk_crtc_otg,
2997 .setup_stereo = NULL,
2998 .set_avmute = dce110_set_avmute,
2999 .wait_for_mpcc_disconnect = dce110_wait_for_mpcc_disconnect,
3000 .ready_shared_resources = ready_shared_resources,
3001 .optimize_shared_resources = optimize_shared_resources,
3002 .pplib_apply_display_requirements = pplib_apply_display_requirements,
3003 .edp_backlight_control = hwss_edp_backlight_control,
3004 .edp_power_control = hwss_edp_power_control,
3005 .edp_wait_for_hpd_ready = hwss_edp_wait_for_hpd_ready,
3006 .set_cursor_position = dce110_set_cursor_position,
3007 .set_cursor_attribute = dce110_set_cursor_attribute
3008};
3009
3010void dce110_hw_sequencer_construct(struct dc *dc)
3011{
3012 dc->hwss = dce110_funcs;
3013}
3014
3015