]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
6a7cb3e9294a4291c6230e7f360d8165da2cd986
[mirror_ubuntu-bionic-kernel.git] / drivers / gpu / drm / amd / display / dc / dce110 / dce110_hw_sequencer.c
1 /*
2 * Copyright 2015 Advanced Micro Devices, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Authors: AMD
23 *
24 */
25 #include "dm_services.h"
26 #include "dc.h"
27 #include "dc_bios_types.h"
28 #include "core_types.h"
29 #include "core_status.h"
30 #include "resource.h"
31 #include "hw_sequencer.h"
32 #include "dm_helpers.h"
33 #include "dce110_hw_sequencer.h"
34 #include "dce110_timing_generator.h"
35
36 #include "bios/bios_parser_helper.h"
37 #include "timing_generator.h"
38 #include "mem_input.h"
39 #include "opp.h"
40 #include "ipp.h"
41 #include "transform.h"
42 #include "stream_encoder.h"
43 #include "link_encoder.h"
44 #include "clock_source.h"
45 #include "gamma_calcs.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
53 struct dce110_hw_seq_reg_offsets {
54 uint32_t crtc;
55 };
56
57 static const struct dce110_hw_seq_reg_offsets reg_offsets[] = {
58 {
59 .crtc = (mmCRTC0_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
60 },
61 {
62 .crtc = (mmCRTC1_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
63 },
64 {
65 .crtc = (mmCRTC2_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
66 },
67 {
68 .crtc = (mmCRTCV_GSL_CONTROL - mmCRTC_GSL_CONTROL),
69 }
70 };
71
72 #define HW_REG_BLND(reg, id)\
73 (reg + reg_offsets[id].blnd)
74
75 #define HW_REG_CRTC(reg, id)\
76 (reg + reg_offsets[id].crtc)
77
78 #define MAX_WATERMARK 0xFFFF
79 #define SAFE_NBP_MARK 0x7FFF
80
81 /*******************************************************************************
82 * Private definitions
83 ******************************************************************************/
84 /***************************PIPE_CONTROL***********************************/
85 static void dce110_init_pte(struct dc_context *ctx)
86 {
87 uint32_t addr;
88 uint32_t value = 0;
89 uint32_t chunk_int = 0;
90 uint32_t chunk_mul = 0;
91
92 addr = mmUNP_DVMM_PTE_CONTROL;
93 value = dm_read_reg(ctx, addr);
94
95 set_reg_field_value(
96 value,
97 0,
98 DVMM_PTE_CONTROL,
99 DVMM_USE_SINGLE_PTE);
100
101 set_reg_field_value(
102 value,
103 1,
104 DVMM_PTE_CONTROL,
105 DVMM_PTE_BUFFER_MODE0);
106
107 set_reg_field_value(
108 value,
109 1,
110 DVMM_PTE_CONTROL,
111 DVMM_PTE_BUFFER_MODE1);
112
113 dm_write_reg(ctx, addr, value);
114
115 addr = mmDVMM_PTE_REQ;
116 value = dm_read_reg(ctx, addr);
117
118 chunk_int = get_reg_field_value(
119 value,
120 DVMM_PTE_REQ,
121 HFLIP_PTEREQ_PER_CHUNK_INT);
122
123 chunk_mul = get_reg_field_value(
124 value,
125 DVMM_PTE_REQ,
126 HFLIP_PTEREQ_PER_CHUNK_MULTIPLIER);
127
128 if (chunk_int != 0x4 || chunk_mul != 0x4) {
129
130 set_reg_field_value(
131 value,
132 255,
133 DVMM_PTE_REQ,
134 MAX_PTEREQ_TO_ISSUE);
135
136 set_reg_field_value(
137 value,
138 4,
139 DVMM_PTE_REQ,
140 HFLIP_PTEREQ_PER_CHUNK_INT);
141
142 set_reg_field_value(
143 value,
144 4,
145 DVMM_PTE_REQ,
146 HFLIP_PTEREQ_PER_CHUNK_MULTIPLIER);
147
148 dm_write_reg(ctx, addr, value);
149 }
150 }
151 /**************************************************************************/
152
153 static void enable_display_pipe_clock_gating(
154 struct dc_context *ctx,
155 bool clock_gating)
156 {
157 /*TODO*/
158 }
159
160 static bool dce110_enable_display_power_gating(
161 struct core_dc *dc,
162 uint8_t controller_id,
163 struct dc_bios *dcb,
164 enum pipe_gating_control power_gating)
165 {
166 enum bp_result bp_result = BP_RESULT_OK;
167 enum bp_pipe_control_action cntl;
168 struct dc_context *ctx = dc->ctx;
169 unsigned int underlay_idx = dc->res_pool->underlay_pipe_index;
170
171 if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment))
172 return true;
173
174 if (power_gating == PIPE_GATING_CONTROL_INIT)
175 cntl = ASIC_PIPE_INIT;
176 else if (power_gating == PIPE_GATING_CONTROL_ENABLE)
177 cntl = ASIC_PIPE_ENABLE;
178 else
179 cntl = ASIC_PIPE_DISABLE;
180
181 if (controller_id == underlay_idx)
182 controller_id = CONTROLLER_ID_UNDERLAY0 - 1;
183
184 if (power_gating != PIPE_GATING_CONTROL_INIT || controller_id == 0){
185
186 bp_result = dcb->funcs->enable_disp_power_gating(
187 dcb, controller_id + 1, cntl);
188
189 /* Revert MASTER_UPDATE_MODE to 0 because bios sets it 2
190 * by default when command table is called
191 *
192 * Bios parser accepts controller_id = 6 as indicative of
193 * underlay pipe in dce110. But we do not support more
194 * than 3.
195 */
196 if (controller_id < CONTROLLER_ID_MAX - 1)
197 dm_write_reg(ctx,
198 HW_REG_CRTC(mmCRTC_MASTER_UPDATE_MODE, controller_id),
199 0);
200 }
201
202 if (power_gating != PIPE_GATING_CONTROL_ENABLE)
203 dce110_init_pte(ctx);
204
205 if (bp_result == BP_RESULT_OK)
206 return true;
207 else
208 return false;
209 }
210
211 static void build_prescale_params(struct ipp_prescale_params *prescale_params,
212 const struct core_surface *surface)
213 {
214 prescale_params->mode = IPP_PRESCALE_MODE_FIXED_UNSIGNED;
215
216 switch (surface->public.format) {
217 case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
218 case SURFACE_PIXEL_FORMAT_GRPH_BGRA8888:
219 prescale_params->scale = 0x2020;
220 break;
221 case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
222 case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
223 prescale_params->scale = 0x2008;
224 break;
225 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
226 case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
227 prescale_params->scale = 0x2000;
228 break;
229 default:
230 ASSERT(false);
231 break;
232 }
233 }
234
235 static bool dce110_set_input_transfer_func(
236 struct pipe_ctx *pipe_ctx,
237 const struct core_surface *surface)
238 {
239 struct input_pixel_processor *ipp = pipe_ctx->ipp;
240 const struct core_transfer_func *tf = NULL;
241 struct ipp_prescale_params prescale_params = { 0 };
242 bool result = true;
243
244 if (ipp == NULL)
245 return false;
246
247 if (surface->public.in_transfer_func)
248 tf = DC_TRANSFER_FUNC_TO_CORE(surface->public.in_transfer_func);
249
250 build_prescale_params(&prescale_params, surface);
251 ipp->funcs->ipp_program_prescale(ipp, &prescale_params);
252
253 if (surface->public.gamma_correction)
254 ipp->funcs->ipp_program_input_lut(ipp, surface->public.gamma_correction);
255
256 if (tf == NULL) {
257 /* Default case if no input transfer function specified */
258 ipp->funcs->ipp_set_degamma(ipp,
259 IPP_DEGAMMA_MODE_BYPASS);
260 } else if (tf->public.type == TF_TYPE_PREDEFINED) {
261 switch (tf->public.tf) {
262 case TRANSFER_FUNCTION_SRGB:
263 ipp->funcs->ipp_set_degamma(ipp,
264 IPP_DEGAMMA_MODE_HW_sRGB);
265 break;
266 case TRANSFER_FUNCTION_BT709:
267 ipp->funcs->ipp_set_degamma(ipp,
268 IPP_DEGAMMA_MODE_HW_xvYCC);
269 break;
270 case TRANSFER_FUNCTION_LINEAR:
271 ipp->funcs->ipp_set_degamma(ipp,
272 IPP_DEGAMMA_MODE_BYPASS);
273 break;
274 case TRANSFER_FUNCTION_PQ:
275 result = false;
276 break;
277 default:
278 result = false;
279 break;
280 }
281 } else {
282 /*TF_TYPE_DISTRIBUTED_POINTS - Not supported in DCE 11*/
283 result = false;
284 }
285
286 return result;
287 }
288
289 static bool dce110_set_output_transfer_func(
290 struct pipe_ctx *pipe_ctx,
291 const struct core_surface *surface, /* Surface - To be removed */
292 const struct core_stream *stream)
293 {
294 struct output_pixel_processor *opp = pipe_ctx->opp;
295 const struct core_gamma *ramp = NULL;
296 struct ipp_prescale_params prescale_params = { 0 };
297 struct pwl_params *regamma_params;
298 bool result = false;
299
300 if (surface->public.gamma_correction)
301 ramp = DC_GAMMA_TO_CORE(surface->public.gamma_correction);
302
303 regamma_params = dm_alloc(sizeof(struct pwl_params));
304 if (regamma_params == NULL)
305 goto regamma_alloc_fail;
306
307 regamma_params->hw_points_num = GAMMA_HW_POINTS_NUM;
308
309 opp->funcs->opp_power_on_regamma_lut(opp, true);
310
311 if (stream->public.out_transfer_func &&
312 stream->public.out_transfer_func->type == TF_TYPE_PREDEFINED &&
313 stream->public.out_transfer_func->tf == TRANSFER_FUNCTION_SRGB) {
314 opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_SRGB);
315 } else if (ramp && calculate_regamma_params(regamma_params, ramp, surface, stream)) {
316 opp->funcs->opp_program_regamma_pwl(opp, regamma_params);
317 opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_USER);
318 } else {
319 opp->funcs->opp_set_regamma_mode(opp, OPP_REGAMMA_BYPASS);
320 }
321
322 opp->funcs->opp_power_on_regamma_lut(opp, false);
323
324 result = true;
325
326 dm_free(regamma_params);
327
328 regamma_alloc_fail:
329 return result;
330 }
331
332 static enum dc_status bios_parser_crtc_source_select(
333 struct pipe_ctx *pipe_ctx)
334 {
335 struct dc_bios *dcb;
336 /* call VBIOS table to set CRTC source for the HW
337 * encoder block
338 * note: video bios clears all FMT setting here. */
339 struct bp_crtc_source_select crtc_source_select = {0};
340 const struct core_sink *sink = pipe_ctx->stream->sink;
341
342 crtc_source_select.engine_id = pipe_ctx->stream_enc->id;
343 crtc_source_select.controller_id = pipe_ctx->pipe_idx + 1;
344 /*TODO: Need to un-hardcode color depth, dp_audio and account for
345 * the case where signal and sink signal is different (translator
346 * encoder)*/
347 crtc_source_select.signal = pipe_ctx->stream->signal;
348 crtc_source_select.enable_dp_audio = false;
349 crtc_source_select.sink_signal = pipe_ctx->stream->signal;
350 crtc_source_select.display_output_bit_depth = PANEL_8BIT_COLOR;
351
352 dcb = sink->ctx->dc_bios;
353
354 if (BP_RESULT_OK != dcb->funcs->crtc_source_select(
355 dcb,
356 &crtc_source_select)) {
357 return DC_ERROR_UNEXPECTED;
358 }
359
360 return DC_OK;
361 }
362
363 void dce110_update_info_frame(struct pipe_ctx *pipe_ctx)
364 {
365 if (dc_is_hdmi_signal(pipe_ctx->stream->signal))
366 pipe_ctx->stream_enc->funcs->update_hdmi_info_packets(
367 pipe_ctx->stream_enc,
368 &pipe_ctx->encoder_info_frame);
369 else if (dc_is_dp_signal(pipe_ctx->stream->signal))
370 pipe_ctx->stream_enc->funcs->update_dp_info_packets(
371 pipe_ctx->stream_enc,
372 &pipe_ctx->encoder_info_frame);
373 }
374
375 void dce110_enable_stream(struct pipe_ctx *pipe_ctx)
376 {
377 enum dc_lane_count lane_count =
378 pipe_ctx->stream->sink->link->public.cur_link_settings.lane_count;
379
380 struct dc_crtc_timing *timing = &pipe_ctx->stream->public.timing;
381 struct core_link *link = pipe_ctx->stream->sink->link;
382
383 /* 1. update AVI info frame (HDMI, DP)
384 * we always need to update info frame
385 */
386 uint32_t active_total_with_borders;
387 uint32_t early_control = 0;
388 struct timing_generator *tg = pipe_ctx->tg;
389
390 /* TODOFPGA may change to hwss.update_info_frame */
391 dce110_update_info_frame(pipe_ctx);
392 /* enable early control to avoid corruption on DP monitor*/
393 active_total_with_borders =
394 timing->h_addressable
395 + timing->h_border_left
396 + timing->h_border_right;
397
398 if (lane_count != 0)
399 early_control = active_total_with_borders % lane_count;
400
401 if (early_control == 0)
402 early_control = lane_count;
403
404 tg->funcs->set_early_control(tg, early_control);
405
406 /* enable audio only within mode set */
407 if (pipe_ctx->audio != NULL) {
408 if (dc_is_dp_signal(pipe_ctx->stream->signal))
409 pipe_ctx->stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_enc);
410 }
411
412 /* For MST, there are multiply stream go to only one link.
413 * connect DIG back_end to front_end while enable_stream and
414 * disconnect them during disable_stream
415 * BY this, it is logic clean to separate stream and link */
416 link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc,
417 pipe_ctx->stream_enc->id, true);
418
419 }
420
421 void dce110_disable_stream(struct pipe_ctx *pipe_ctx)
422 {
423 struct core_stream *stream = pipe_ctx->stream;
424 struct core_link *link = stream->sink->link;
425
426 if (pipe_ctx->audio) {
427 pipe_ctx->audio->funcs->az_disable(pipe_ctx->audio);
428
429 if (dc_is_dp_signal(pipe_ctx->stream->signal))
430 pipe_ctx->stream_enc->funcs->dp_audio_disable(
431 pipe_ctx->stream_enc);
432 else
433 pipe_ctx->stream_enc->funcs->hdmi_audio_disable(
434 pipe_ctx->stream_enc);
435
436 pipe_ctx->audio = NULL;
437
438 /* TODO: notify audio driver for if audio modes list changed
439 * add audio mode list change flag */
440 /* dal_audio_disable_azalia_audio_jack_presence(stream->audio,
441 * stream->stream_engine_id);
442 */
443 }
444
445 if (dc_is_hdmi_signal(pipe_ctx->stream->signal))
446 pipe_ctx->stream_enc->funcs->stop_hdmi_info_packets(
447 pipe_ctx->stream_enc);
448
449 if (dc_is_dp_signal(pipe_ctx->stream->signal))
450 pipe_ctx->stream_enc->funcs->stop_dp_info_packets(
451 pipe_ctx->stream_enc);
452
453 pipe_ctx->stream_enc->funcs->audio_mute_control(
454 pipe_ctx->stream_enc, true);
455
456
457 /* blank at encoder level */
458 if (dc_is_dp_signal(pipe_ctx->stream->signal))
459 pipe_ctx->stream_enc->funcs->dp_blank(pipe_ctx->stream_enc);
460
461 link->link_enc->funcs->connect_dig_be_to_fe(
462 link->link_enc,
463 pipe_ctx->stream_enc->id,
464 false);
465
466 }
467
468 void dce110_unblank_stream(struct pipe_ctx *pipe_ctx,
469 struct dc_link_settings *link_settings)
470 {
471 struct encoder_unblank_param params = { { 0 } };
472
473 /* only 3 items below are used by unblank */
474 params.crtc_timing.pixel_clock =
475 pipe_ctx->stream->public.timing.pix_clk_khz;
476 params.link_settings.link_rate = link_settings->link_rate;
477 pipe_ctx->stream_enc->funcs->dp_unblank(pipe_ctx->stream_enc, &params);
478 }
479
480 static enum audio_dto_source translate_to_dto_source(enum controller_id crtc_id)
481 {
482 switch (crtc_id) {
483 case CONTROLLER_ID_D0:
484 return DTO_SOURCE_ID0;
485 case CONTROLLER_ID_D1:
486 return DTO_SOURCE_ID1;
487 case CONTROLLER_ID_D2:
488 return DTO_SOURCE_ID2;
489 case CONTROLLER_ID_D3:
490 return DTO_SOURCE_ID3;
491 case CONTROLLER_ID_D4:
492 return DTO_SOURCE_ID4;
493 case CONTROLLER_ID_D5:
494 return DTO_SOURCE_ID5;
495 default:
496 return DTO_SOURCE_UNKNOWN;
497 }
498 }
499
500 static void build_audio_output(
501 const struct pipe_ctx *pipe_ctx,
502 struct audio_output *audio_output)
503 {
504 const struct core_stream *stream = pipe_ctx->stream;
505 audio_output->engine_id = pipe_ctx->stream_enc->id;
506
507 audio_output->signal = pipe_ctx->stream->signal;
508
509 /* audio_crtc_info */
510
511 audio_output->crtc_info.h_total =
512 stream->public.timing.h_total;
513
514 /*
515 * Audio packets are sent during actual CRTC blank physical signal, we
516 * need to specify actual active signal portion
517 */
518 audio_output->crtc_info.h_active =
519 stream->public.timing.h_addressable
520 + stream->public.timing.h_border_left
521 + stream->public.timing.h_border_right;
522
523 audio_output->crtc_info.v_active =
524 stream->public.timing.v_addressable
525 + stream->public.timing.v_border_top
526 + stream->public.timing.v_border_bottom;
527
528 audio_output->crtc_info.pixel_repetition = 1;
529
530 audio_output->crtc_info.interlaced =
531 stream->public.timing.flags.INTERLACE;
532
533 audio_output->crtc_info.refresh_rate =
534 (stream->public.timing.pix_clk_khz*1000)/
535 (stream->public.timing.h_total*stream->public.timing.v_total);
536
537 audio_output->crtc_info.color_depth =
538 stream->public.timing.display_color_depth;
539
540 audio_output->crtc_info.requested_pixel_clock =
541 pipe_ctx->pix_clk_params.requested_pix_clk;
542
543 /*
544 * TODO - Investigate why calculated pixel clk has to be
545 * requested pixel clk
546 */
547 audio_output->crtc_info.calculated_pixel_clock =
548 pipe_ctx->pix_clk_params.requested_pix_clk;
549
550 if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT ||
551 pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
552 audio_output->pll_info.dp_dto_source_clock_in_khz =
553 pipe_ctx->dis_clk->funcs->get_dp_ref_clk_frequency(
554 pipe_ctx->dis_clk);
555 }
556
557 audio_output->pll_info.feed_back_divider =
558 pipe_ctx->pll_settings.feedback_divider;
559
560 audio_output->pll_info.dto_source =
561 translate_to_dto_source(
562 pipe_ctx->pipe_idx + 1);
563
564 /* TODO hard code to enable for now. Need get from stream */
565 audio_output->pll_info.ss_enabled = true;
566
567 audio_output->pll_info.ss_percentage =
568 pipe_ctx->pll_settings.ss_percentage;
569 }
570
571 static void get_surface_visual_confirm_color(const struct pipe_ctx *pipe_ctx,
572 struct tg_color *color)
573 {
574 uint32_t color_value = MAX_TG_COLOR_VALUE * (4 - pipe_ctx->pipe_idx) / 4;
575
576 switch (pipe_ctx->scl_data.format) {
577 case PIXEL_FORMAT_ARGB8888:
578 /* set boarder color to red */
579 color->color_r_cr = color_value;
580 break;
581
582 case PIXEL_FORMAT_ARGB2101010:
583 /* set boarder color to blue */
584 color->color_b_cb = color_value;
585 break;
586 case PIXEL_FORMAT_420BPP12:
587 /* set boarder color to green */
588 color->color_g_y = color_value;
589 break;
590 case PIXEL_FORMAT_FP16:
591 /* set boarder color to white */
592 color->color_r_cr = color_value;
593 color->color_b_cb = color_value;
594 color->color_g_y = color_value;
595 break;
596 default:
597 break;
598 }
599 }
600
601 static void program_scaler(const struct core_dc *dc,
602 const struct pipe_ctx *pipe_ctx)
603 {
604 struct tg_color color = {0};
605
606 if (dc->public.debug.surface_visual_confirm)
607 get_surface_visual_confirm_color(pipe_ctx, &color);
608 else
609 color_space_to_black_color(dc,
610 pipe_ctx->stream->public.output_color_space,
611 &color);
612
613 pipe_ctx->xfm->funcs->transform_set_pixel_storage_depth(
614 pipe_ctx->xfm,
615 pipe_ctx->scl_data.lb_params.depth,
616 &pipe_ctx->stream->bit_depth_params);
617
618 if (pipe_ctx->tg->funcs->set_overscan_blank_color)
619 pipe_ctx->tg->funcs->set_overscan_blank_color(
620 pipe_ctx->tg,
621 &color);
622
623 pipe_ctx->xfm->funcs->transform_set_scaler(pipe_ctx->xfm,
624 &pipe_ctx->scl_data);
625 }
626
627 static enum dc_status prog_pixclk_crtc_otg(
628 struct pipe_ctx *pipe_ctx,
629 struct validate_context *context,
630 struct core_dc *dc)
631 {
632 struct core_stream *stream = pipe_ctx->stream;
633 struct pipe_ctx *pipe_ctx_old = &dc->current_context->res_ctx.
634 pipe_ctx[pipe_ctx->pipe_idx];
635 struct tg_color black_color = {0};
636
637 if (!pipe_ctx_old->stream) {
638
639 /* program blank color */
640 color_space_to_black_color(dc,
641 stream->public.output_color_space, &black_color);
642 pipe_ctx->tg->funcs->set_blank_color(
643 pipe_ctx->tg,
644 &black_color);
645 /*
646 * Must blank CRTC after disabling power gating and before any
647 * programming, otherwise CRTC will be hung in bad state
648 */
649 pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, true);
650
651 if (false == pipe_ctx->clock_source->funcs->program_pix_clk(
652 pipe_ctx->clock_source,
653 &pipe_ctx->pix_clk_params,
654 &pipe_ctx->pll_settings)) {
655 BREAK_TO_DEBUGGER();
656 return DC_ERROR_UNEXPECTED;
657 }
658
659 pipe_ctx->tg->funcs->program_timing(
660 pipe_ctx->tg,
661 &stream->public.timing,
662 true);
663 }
664
665 if (!pipe_ctx_old->stream) {
666 if (false == pipe_ctx->tg->funcs->enable_crtc(
667 pipe_ctx->tg)) {
668 BREAK_TO_DEBUGGER();
669 return DC_ERROR_UNEXPECTED;
670 }
671 }
672
673 return DC_OK;
674 }
675
676 static enum dc_status apply_single_controller_ctx_to_hw(
677 struct pipe_ctx *pipe_ctx,
678 struct validate_context *context,
679 struct core_dc *dc)
680 {
681 struct core_stream *stream = pipe_ctx->stream;
682 struct pipe_ctx *pipe_ctx_old = &dc->current_context->res_ctx.
683 pipe_ctx[pipe_ctx->pipe_idx];
684
685 /* */
686 dc->hwss.prog_pixclk_crtc_otg(pipe_ctx, context, dc);
687
688 pipe_ctx->opp->funcs->opp_set_dyn_expansion(
689 pipe_ctx->opp,
690 COLOR_SPACE_YCBCR601,
691 stream->public.timing.display_color_depth,
692 pipe_ctx->stream->signal);
693
694 pipe_ctx->opp->funcs->opp_program_fmt(
695 pipe_ctx->opp,
696 &stream->bit_depth_params,
697 &stream->clamping);
698
699 /* FPGA does not program backend */
700 if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment))
701 return DC_OK;
702
703 /* TODO: move to stream encoder */
704 if (pipe_ctx->stream->signal != SIGNAL_TYPE_VIRTUAL)
705 if (DC_OK != bios_parser_crtc_source_select(pipe_ctx)) {
706 BREAK_TO_DEBUGGER();
707 return DC_ERROR_UNEXPECTED;
708 }
709
710 if (pipe_ctx->stream->signal != SIGNAL_TYPE_VIRTUAL)
711 stream->sink->link->link_enc->funcs->setup(
712 stream->sink->link->link_enc,
713 pipe_ctx->stream->signal);
714
715 if (dc_is_dp_signal(pipe_ctx->stream->signal))
716 pipe_ctx->stream_enc->funcs->dp_set_stream_attribute(
717 pipe_ctx->stream_enc,
718 &stream->public.timing,
719 stream->public.output_color_space);
720
721 if (dc_is_hdmi_signal(pipe_ctx->stream->signal))
722 pipe_ctx->stream_enc->funcs->hdmi_set_stream_attribute(
723 pipe_ctx->stream_enc,
724 &stream->public.timing,
725 stream->phy_pix_clk,
726 pipe_ctx->audio != NULL);
727
728 if (dc_is_dvi_signal(pipe_ctx->stream->signal))
729 pipe_ctx->stream_enc->funcs->dvi_set_stream_attribute(
730 pipe_ctx->stream_enc,
731 &stream->public.timing,
732 (pipe_ctx->stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK) ?
733 true : false);
734
735 if (!pipe_ctx_old->stream) {
736 core_link_enable_stream(pipe_ctx);
737
738 if (dc_is_dp_signal(pipe_ctx->stream->signal))
739 dce110_unblank_stream(pipe_ctx,
740 &stream->sink->link->public.cur_link_settings);
741 }
742
743 pipe_ctx->scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0;
744 /* program_scaler and allocate_mem_input are not new asic */
745 if (!pipe_ctx_old || memcmp(&pipe_ctx_old->scl_data,
746 &pipe_ctx->scl_data,
747 sizeof(struct scaler_data)) != 0)
748 program_scaler(dc, pipe_ctx);
749
750 /* mst support - use total stream count */
751 pipe_ctx->mi->funcs->allocate_mem_input(
752 pipe_ctx->mi,
753 stream->public.timing.h_total,
754 stream->public.timing.v_total,
755 stream->public.timing.pix_clk_khz,
756 context->target_count);
757
758 return DC_OK;
759 }
760
761 /******************************************************************************/
762
763 static void power_down_encoders(struct core_dc *dc)
764 {
765 int i;
766
767 for (i = 0; i < dc->link_count; i++) {
768 dc->links[i]->link_enc->funcs->disable_output(
769 dc->links[i]->link_enc, SIGNAL_TYPE_NONE);
770 }
771 }
772
773 static void power_down_controllers(struct core_dc *dc)
774 {
775 int i;
776
777 for (i = 0; i < dc->res_pool->pipe_count; i++) {
778 dc->res_pool->timing_generators[i]->funcs->disable_crtc(
779 dc->res_pool->timing_generators[i]);
780 }
781 }
782
783 static void power_down_clock_sources(struct core_dc *dc)
784 {
785 int i;
786
787 if (dc->res_pool->dp_clock_source->funcs->cs_power_down(
788 dc->res_pool->dp_clock_source) == false)
789 dm_error("Failed to power down pll! (dp clk src)\n");
790
791 for (i = 0; i < dc->res_pool->clk_src_count; i++) {
792 if (dc->res_pool->clock_sources[i]->funcs->cs_power_down(
793 dc->res_pool->clock_sources[i]) == false)
794 dm_error("Failed to power down pll! (clk src index=%d)\n", i);
795 }
796 }
797
798 static void power_down_all_hw_blocks(struct core_dc *dc)
799 {
800 power_down_encoders(dc);
801
802 power_down_controllers(dc);
803
804 power_down_clock_sources(dc);
805 }
806
807 static void disable_vga_and_power_gate_all_controllers(
808 struct core_dc *dc)
809 {
810 int i;
811 struct timing_generator *tg;
812 struct dc_context *ctx = dc->ctx;
813
814 for (i = 0; i < dc->res_pool->pipe_count; i++) {
815 tg = dc->res_pool->timing_generators[i];
816
817 tg->funcs->disable_vga(tg);
818
819 /* Enable CLOCK gating for each pipe BEFORE controller
820 * powergating. */
821 enable_display_pipe_clock_gating(ctx,
822 true);
823
824 dc->hwss.power_down_front_end(
825 dc, &dc->current_context->res_ctx.pipe_ctx[i]);
826 }
827 }
828
829 /**
830 * When ASIC goes from VBIOS/VGA mode to driver/accelerated mode we need:
831 * 1. Power down all DC HW blocks
832 * 2. Disable VGA engine on all controllers
833 * 3. Enable power gating for controller
834 * 4. Set acc_mode_change bit (VBIOS will clear this bit when going to FSDOS)
835 */
836 void dce110_enable_accelerated_mode(struct core_dc *dc)
837 {
838 power_down_all_hw_blocks(dc);
839
840 disable_vga_and_power_gate_all_controllers(dc);
841 bios_set_scratch_acc_mode_change(dc->ctx->dc_bios);
842 }
843
844 static uint32_t compute_pstate_blackout_duration(
845 struct bw_fixed blackout_duration,
846 const struct core_stream *stream)
847 {
848 uint32_t total_dest_line_time_ns;
849 uint32_t pstate_blackout_duration_ns;
850
851 pstate_blackout_duration_ns = 1000 * blackout_duration.value >> 24;
852
853 total_dest_line_time_ns = 1000000UL *
854 stream->public.timing.h_total /
855 stream->public.timing.pix_clk_khz +
856 pstate_blackout_duration_ns;
857
858 return total_dest_line_time_ns;
859 }
860
861 /* get the index of the pipe_ctx if there were no gaps in the pipe_ctx array*/
862 int get_bw_result_idx(
863 struct resource_context *res_ctx,
864 int pipe_idx)
865 {
866 int i, collapsed_idx;
867
868 if (res_ctx->pipe_ctx[pipe_idx].top_pipe)
869 return 3;
870
871 collapsed_idx = 0;
872 for (i = 0; i < pipe_idx; i++) {
873 if (res_ctx->pipe_ctx[i].stream)
874 collapsed_idx++;
875 }
876
877 return collapsed_idx;
878 }
879
880 static bool is_watermark_set_a_greater(
881 const struct bw_watermarks *set_a,
882 const struct bw_watermarks *set_b)
883 {
884 if (set_a->a_mark > set_b->a_mark
885 || set_a->b_mark > set_b->b_mark
886 || set_a->c_mark > set_b->c_mark
887 || set_a->d_mark > set_b->d_mark)
888 return true;
889 return false;
890 }
891
892 static bool did_watermarks_increase(
893 struct pipe_ctx *pipe_ctx,
894 struct validate_context *context,
895 struct validate_context *old_context)
896 {
897 int collapsed_pipe_idx = get_bw_result_idx(&context->res_ctx,
898 pipe_ctx->pipe_idx);
899 int old_collapsed_pipe_idx = get_bw_result_idx(&old_context->res_ctx,
900 pipe_ctx->pipe_idx);
901 struct pipe_ctx *old_pipe_ctx = &old_context->res_ctx.pipe_ctx[pipe_ctx->pipe_idx];
902
903 if (!old_pipe_ctx->stream)
904 return true;
905
906 if (is_watermark_set_a_greater(
907 &context->bw_results.nbp_state_change_wm_ns[collapsed_pipe_idx],
908 &old_context->bw_results.nbp_state_change_wm_ns[old_collapsed_pipe_idx]))
909 return true;
910 if (is_watermark_set_a_greater(
911 &context->bw_results.stutter_exit_wm_ns[collapsed_pipe_idx],
912 &old_context->bw_results.stutter_exit_wm_ns[old_collapsed_pipe_idx]))
913 return true;
914 if (is_watermark_set_a_greater(
915 &context->bw_results.urgent_wm_ns[collapsed_pipe_idx],
916 &old_context->bw_results.urgent_wm_ns[old_collapsed_pipe_idx]))
917 return true;
918
919 return false;
920 }
921
922 static void program_wm_for_pipe(struct core_dc *dc,
923 struct pipe_ctx *pipe_ctx,
924 struct validate_context *context)
925 {
926 int total_dest_line_time_ns = compute_pstate_blackout_duration(
927 dc->bw_vbios.blackout_duration,
928 pipe_ctx->stream);
929 int bw_result_idx = get_bw_result_idx(&context->res_ctx,
930 pipe_ctx->pipe_idx);
931
932 pipe_ctx->mi->funcs->mem_input_program_display_marks(
933 pipe_ctx->mi,
934 context->bw_results.nbp_state_change_wm_ns[bw_result_idx],
935 context->bw_results.stutter_exit_wm_ns[bw_result_idx],
936 context->bw_results.urgent_wm_ns[bw_result_idx],
937 total_dest_line_time_ns);
938
939 if (pipe_ctx->top_pipe)
940 pipe_ctx->mi->funcs->mem_input_program_chroma_display_marks(
941 pipe_ctx->mi,
942 context->bw_results.nbp_state_change_wm_ns[bw_result_idx + 1],
943 context->bw_results.stutter_exit_wm_ns[bw_result_idx + 1],
944 context->bw_results.urgent_wm_ns[bw_result_idx + 1],
945 total_dest_line_time_ns);
946 }
947
948 void dce110_set_displaymarks(
949 const struct core_dc *dc,
950 struct validate_context *context)
951 {
952 uint8_t i, num_pipes;
953 unsigned int underlay_idx = dc->res_pool->underlay_pipe_index;
954
955 for (i = 0, num_pipes = 0; i < MAX_PIPES; i++) {
956 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
957 uint32_t total_dest_line_time_ns;
958
959 if (pipe_ctx->stream == NULL)
960 continue;
961
962 total_dest_line_time_ns = compute_pstate_blackout_duration(
963 dc->bw_vbios.blackout_duration, pipe_ctx->stream);
964 pipe_ctx->mi->funcs->mem_input_program_display_marks(
965 pipe_ctx->mi,
966 context->bw_results.nbp_state_change_wm_ns[num_pipes],
967 context->bw_results.stutter_exit_wm_ns[num_pipes],
968 context->bw_results.urgent_wm_ns[num_pipes],
969 total_dest_line_time_ns);
970 if (i == underlay_idx) {
971 num_pipes++;
972 pipe_ctx->mi->funcs->mem_input_program_chroma_display_marks(
973 pipe_ctx->mi,
974 context->bw_results.nbp_state_change_wm_ns[num_pipes],
975 context->bw_results.stutter_exit_wm_ns[num_pipes],
976 context->bw_results.urgent_wm_ns[num_pipes],
977 total_dest_line_time_ns);
978 }
979 num_pipes++;
980 }
981 }
982
983 static void set_safe_displaymarks(struct resource_context *res_ctx)
984 {
985 int i;
986 int underlay_idx = res_ctx->pool->underlay_pipe_index;
987 struct bw_watermarks max_marks = {
988 MAX_WATERMARK, MAX_WATERMARK, MAX_WATERMARK, MAX_WATERMARK };
989 struct bw_watermarks nbp_marks = {
990 SAFE_NBP_MARK, SAFE_NBP_MARK, SAFE_NBP_MARK, SAFE_NBP_MARK };
991
992 for (i = 0; i < MAX_PIPES; i++) {
993 if (res_ctx->pipe_ctx[i].stream == NULL)
994 continue;
995
996 res_ctx->pipe_ctx[i].mi->funcs->mem_input_program_display_marks(
997 res_ctx->pipe_ctx[i].mi,
998 nbp_marks,
999 max_marks,
1000 max_marks,
1001 MAX_WATERMARK);
1002 if (i == underlay_idx)
1003 res_ctx->pipe_ctx[i].mi->funcs->mem_input_program_chroma_display_marks(
1004 res_ctx->pipe_ctx[i].mi,
1005 nbp_marks,
1006 max_marks,
1007 max_marks,
1008 MAX_WATERMARK);
1009 }
1010 }
1011
1012 static void switch_dp_clock_sources(
1013 const struct core_dc *dc,
1014 struct resource_context *res_ctx)
1015 {
1016 uint8_t i;
1017 for (i = 0; i < MAX_PIPES; i++) {
1018 struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
1019
1020 if (pipe_ctx->stream == NULL || pipe_ctx->top_pipe)
1021 continue;
1022
1023 if (dc_is_dp_signal(pipe_ctx->stream->signal)) {
1024 struct clock_source *clk_src =
1025 resource_find_used_clk_src_for_sharing(
1026 res_ctx, pipe_ctx);
1027
1028 if (clk_src &&
1029 clk_src != pipe_ctx->clock_source) {
1030 resource_unreference_clock_source(
1031 res_ctx, &pipe_ctx->clock_source);
1032 pipe_ctx->clock_source = clk_src;
1033 resource_reference_clock_source(res_ctx, clk_src);
1034
1035 dce_crtc_switch_to_clk_src(dc->hwseq, clk_src, i);
1036 }
1037 }
1038 }
1039 }
1040
1041 /*******************************************************************************
1042 * Public functions
1043 ******************************************************************************/
1044
1045 static void reset_single_pipe_hw_ctx(
1046 const struct core_dc *dc,
1047 struct pipe_ctx *pipe_ctx,
1048 struct validate_context *context)
1049 {
1050 core_link_disable_stream(pipe_ctx);
1051 if (!pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, true)) {
1052 dm_error("DC: failed to blank crtc!\n");
1053 BREAK_TO_DEBUGGER();
1054 }
1055 pipe_ctx->tg->funcs->disable_crtc(pipe_ctx->tg);
1056 pipe_ctx->mi->funcs->free_mem_input(
1057 pipe_ctx->mi, context->target_count);
1058 resource_unreference_clock_source(
1059 &context->res_ctx, &pipe_ctx->clock_source);
1060
1061 dc->hwss.power_down_front_end((struct core_dc *)dc, pipe_ctx);
1062
1063 pipe_ctx->stream = NULL;
1064 }
1065
1066 static void set_drr(struct pipe_ctx **pipe_ctx,
1067 int num_pipes, int vmin, int vmax)
1068 {
1069 int i = 0;
1070 struct drr_params params = {0};
1071
1072 params.vertical_total_max = vmax;
1073 params.vertical_total_min = vmin;
1074
1075 /* TODO: If multiple pipes are to be supported, you need
1076 * some GSL stuff
1077 */
1078
1079 for (i = 0; i < num_pipes; i++) {
1080 pipe_ctx[i]->tg->funcs->set_drr(pipe_ctx[i]->tg, &params);
1081 }
1082 }
1083
1084 static void set_static_screen_control(struct pipe_ctx **pipe_ctx,
1085 int num_pipes, int value)
1086 {
1087 unsigned int i;
1088
1089 for (i = 0; i < num_pipes; i++)
1090 pipe_ctx[i]->tg->funcs->
1091 set_static_screen_control(pipe_ctx[i]->tg, value);
1092 }
1093
1094 /* unit: in_khz before mode set, get pixel clock from context. ASIC register
1095 * may not be programmed yet.
1096 * TODO: after mode set, pre_mode_set = false,
1097 * may read PLL register to get pixel clock
1098 */
1099 static uint32_t get_max_pixel_clock_for_all_paths(
1100 struct core_dc *dc,
1101 struct validate_context *context,
1102 bool pre_mode_set)
1103 {
1104 uint32_t max_pix_clk = 0;
1105 int i;
1106
1107 if (!pre_mode_set) {
1108 /* TODO: read ASIC register to get pixel clock */
1109 ASSERT(0);
1110 }
1111
1112 for (i = 0; i < MAX_PIPES; i++) {
1113 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1114
1115 if (pipe_ctx->stream == NULL)
1116 continue;
1117
1118 /* do not check under lay */
1119 if (pipe_ctx->top_pipe)
1120 continue;
1121
1122 if (pipe_ctx->pix_clk_params.requested_pix_clk > max_pix_clk)
1123 max_pix_clk =
1124 pipe_ctx->pix_clk_params.requested_pix_clk;
1125 }
1126
1127 if (max_pix_clk == 0)
1128 ASSERT(0);
1129
1130 return max_pix_clk;
1131 }
1132
1133 /*
1134 * Find clock state based on clock requested. if clock value is 0, simply
1135 * set clock state as requested without finding clock state by clock value
1136 */
1137 static void apply_min_clocks(
1138 struct core_dc *dc,
1139 struct validate_context *context,
1140 enum dm_pp_clocks_state *clocks_state,
1141 bool pre_mode_set)
1142 {
1143 struct state_dependent_clocks req_clocks = {0};
1144 struct pipe_ctx *pipe_ctx;
1145 int i;
1146
1147 for (i = 0; i < MAX_PIPES; i++) {
1148 pipe_ctx = &context->res_ctx.pipe_ctx[i];
1149 if (pipe_ctx->dis_clk != NULL)
1150 break;
1151 }
1152
1153 if (!pre_mode_set) {
1154 /* set clock_state without verification */
1155 if (pipe_ctx->dis_clk->funcs->set_min_clocks_state) {
1156 pipe_ctx->dis_clk->funcs->set_min_clocks_state(
1157 pipe_ctx->dis_clk, *clocks_state);
1158 return;
1159 }
1160
1161 /* TODOFPGA */
1162 }
1163
1164 /* get the required state based on state dependent clocks:
1165 * display clock and pixel clock
1166 */
1167 req_clocks.display_clk_khz = context->bw_results.dispclk_khz;
1168
1169 req_clocks.pixel_clk_khz = get_max_pixel_clock_for_all_paths(
1170 dc, context, true);
1171
1172 if (pipe_ctx->dis_clk->funcs->get_required_clocks_state) {
1173 *clocks_state = pipe_ctx->dis_clk->funcs->get_required_clocks_state(
1174 pipe_ctx->dis_clk, &req_clocks);
1175 pipe_ctx->dis_clk->funcs->set_min_clocks_state(
1176 pipe_ctx->dis_clk, *clocks_state);
1177 } else {
1178 }
1179 }
1180
1181 static enum dc_status apply_ctx_to_hw_fpga(
1182 struct core_dc *dc,
1183 struct validate_context *context)
1184 {
1185 enum dc_status status = DC_ERROR_UNEXPECTED;
1186 int i;
1187
1188 for (i = 0; i < context->res_ctx.pool->pipe_count; i++) {
1189 struct pipe_ctx *pipe_ctx_old =
1190 &dc->current_context->res_ctx.pipe_ctx[i];
1191 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1192
1193 if (pipe_ctx->stream == NULL)
1194 continue;
1195
1196 if (pipe_ctx->stream == pipe_ctx_old->stream)
1197 continue;
1198
1199 status = apply_single_controller_ctx_to_hw(
1200 pipe_ctx,
1201 context,
1202 dc);
1203
1204 if (status != DC_OK)
1205 return status;
1206 }
1207
1208 return DC_OK;
1209 }
1210
1211 static void reset_hw_ctx_wrap(
1212 struct core_dc *dc,
1213 struct validate_context *context)
1214 {
1215 int i;
1216
1217 /* Reset old context */
1218 /* look up the targets that have been removed since last commit */
1219 for (i = 0; i < context->res_ctx.pool->pipe_count; i++) {
1220 struct pipe_ctx *pipe_ctx_old =
1221 &dc->current_context->res_ctx.pipe_ctx[i];
1222 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1223
1224 /* Note: We need to disable output if clock sources change,
1225 * since bios does optimization and doesn't apply if changing
1226 * PHY when not already disabled.
1227 */
1228
1229 /* Skip underlay pipe since it will be handled in commit surface*/
1230 if (!pipe_ctx_old->stream || pipe_ctx_old->top_pipe)
1231 continue;
1232
1233 if (!pipe_ctx->stream ||
1234 pipe_need_reprogram(pipe_ctx_old, pipe_ctx))
1235 reset_single_pipe_hw_ctx(
1236 dc, pipe_ctx_old, dc->current_context);
1237 }
1238 }
1239
1240 /*TODO: const validate_context*/
1241 enum dc_status dce110_apply_ctx_to_hw(
1242 struct core_dc *dc,
1243 struct validate_context *context)
1244 {
1245 struct dc_bios *dcb = dc->ctx->dc_bios;
1246 enum dc_status status;
1247 int i;
1248 bool programmed_audio_dto = false;
1249 enum dm_pp_clocks_state clocks_state = DM_PP_CLOCKS_STATE_INVALID;
1250
1251 /* Reset old context */
1252 /* look up the targets that have been removed since last commit */
1253 dc->hwss.reset_hw_ctx_wrap(dc, context);
1254
1255 /* Skip applying if no targets */
1256 if (context->target_count <= 0)
1257 return DC_OK;
1258
1259 if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
1260 apply_ctx_to_hw_fpga(dc, context);
1261 return DC_OK;
1262 }
1263
1264 /* Apply new context */
1265 dcb->funcs->set_scratch_critical_state(dcb, true);
1266
1267 /* below is for real asic only */
1268 for (i = 0; i < context->res_ctx.pool->pipe_count; i++) {
1269 struct pipe_ctx *pipe_ctx_old =
1270 &dc->current_context->res_ctx.pipe_ctx[i];
1271 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1272
1273 if (pipe_ctx->stream == NULL || pipe_ctx->top_pipe)
1274 continue;
1275
1276 if (pipe_ctx->stream == pipe_ctx_old->stream) {
1277 if (pipe_ctx_old->clock_source != pipe_ctx->clock_source)
1278 dce_crtc_switch_to_clk_src(dc->hwseq,
1279 pipe_ctx->clock_source, i);
1280 continue;
1281 }
1282
1283 dc->hwss.enable_display_power_gating(
1284 dc, i, dc->ctx->dc_bios,
1285 PIPE_GATING_CONTROL_DISABLE);
1286 }
1287
1288 set_safe_displaymarks(&context->res_ctx);
1289 /*TODO: when pplib works*/
1290 apply_min_clocks(dc, context, &clocks_state, true);
1291
1292 if (context->bw_results.dispclk_khz
1293 > dc->current_context->bw_results.dispclk_khz)
1294 context->res_ctx.pool->display_clock->funcs->set_clock(
1295 context->res_ctx.pool->display_clock,
1296 context->bw_results.dispclk_khz * 115 / 100);
1297
1298 for (i = 0; i < context->res_ctx.pool->pipe_count; i++) {
1299 struct pipe_ctx *pipe_ctx_old =
1300 &dc->current_context->res_ctx.pipe_ctx[i];
1301 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1302
1303 if (pipe_ctx->stream == NULL)
1304 continue;
1305
1306 if (pipe_ctx->stream == pipe_ctx_old->stream)
1307 continue;
1308
1309 if (pipe_ctx->top_pipe)
1310 continue;
1311
1312 if (context->res_ctx.pipe_ctx[i].audio != NULL) {
1313 /* Setup audio rate clock source */
1314 /* Issue:
1315 * Audio lag happened on DP monitor when unplug a HDMI monitor
1316 *
1317 * Cause:
1318 * In case of DP and HDMI connected or HDMI only, DCCG_AUDIO_DTO_SEL
1319 * is set to either dto0 or dto1, audio should work fine.
1320 * In case of DP connected only, DCCG_AUDIO_DTO_SEL should be dto1,
1321 * set to dto0 will cause audio lag.
1322 *
1323 * Solution:
1324 * Not optimized audio wall dto setup. When mode set, iterate pipe_ctx,
1325 * find first available pipe with audio, setup audio wall DTO per topology
1326 * instead of per pipe.
1327 */
1328 struct audio_output audio_output;
1329
1330 build_audio_output(pipe_ctx, &audio_output);
1331
1332 if (dc_is_dp_signal(pipe_ctx->stream->signal))
1333 pipe_ctx->stream_enc->funcs->dp_audio_setup(
1334 pipe_ctx->stream_enc,
1335 pipe_ctx->audio->inst,
1336 &pipe_ctx->stream->public.audio_info);
1337 else
1338 pipe_ctx->stream_enc->funcs->hdmi_audio_setup(
1339 pipe_ctx->stream_enc,
1340 pipe_ctx->audio->inst,
1341 &pipe_ctx->stream->public.audio_info,
1342 &audio_output.crtc_info);
1343
1344 pipe_ctx->audio->funcs->az_configure(
1345 pipe_ctx->audio,
1346 pipe_ctx->stream->signal,
1347 &audio_output.crtc_info,
1348 &pipe_ctx->stream->public.audio_info);
1349
1350 if (!programmed_audio_dto) {
1351 pipe_ctx->audio->funcs->wall_dto_setup(
1352 pipe_ctx->audio,
1353 pipe_ctx->stream->signal,
1354 &audio_output.crtc_info,
1355 &audio_output.pll_info);
1356 programmed_audio_dto = true;
1357 }
1358 }
1359
1360 status = apply_single_controller_ctx_to_hw(
1361 pipe_ctx,
1362 context,
1363 dc);
1364
1365 if (DC_OK != status)
1366 return status;
1367 }
1368
1369 dc->hwss.set_displaymarks(dc, context);
1370
1371 /* to save power */
1372 apply_min_clocks(dc, context, &clocks_state, false);
1373
1374 dcb->funcs->set_scratch_critical_state(dcb, false);
1375
1376 switch_dp_clock_sources(dc, &context->res_ctx);
1377
1378 return DC_OK;
1379 }
1380
1381 /*******************************************************************************
1382 * Front End programming
1383 ******************************************************************************/
1384 static void set_default_colors(struct pipe_ctx *pipe_ctx)
1385 {
1386 struct default_adjustment default_adjust = { 0 };
1387
1388 default_adjust.force_hw_default = false;
1389 if (pipe_ctx->surface == NULL)
1390 default_adjust.in_color_space = COLOR_SPACE_SRGB;
1391 else
1392 default_adjust.in_color_space =
1393 pipe_ctx->surface->public.color_space;
1394 if (pipe_ctx->stream == NULL)
1395 default_adjust.out_color_space = COLOR_SPACE_SRGB;
1396 else
1397 default_adjust.out_color_space =
1398 pipe_ctx->stream->public.output_color_space;
1399 default_adjust.csc_adjust_type = GRAPHICS_CSC_ADJUST_TYPE_SW;
1400 default_adjust.surface_pixel_format = pipe_ctx->scl_data.format;
1401
1402 /* display color depth */
1403 default_adjust.color_depth =
1404 pipe_ctx->stream->public.timing.display_color_depth;
1405
1406 /* Lb color depth */
1407 default_adjust.lb_color_depth = pipe_ctx->scl_data.lb_params.depth;
1408
1409 pipe_ctx->opp->funcs->opp_set_csc_default(
1410 pipe_ctx->opp, &default_adjust);
1411 }
1412
1413 static void program_blender(const struct core_dc *dc,
1414 struct pipe_ctx *pipe_ctx)
1415 {
1416 enum blnd_mode blender_mode = BLND_MODE_CURRENT_PIPE;
1417
1418 if (pipe_ctx->bottom_pipe) {
1419 if (pipe_ctx->bottom_pipe->surface->public.visible) {
1420 if (pipe_ctx->surface->public.visible)
1421 blender_mode = BLND_MODE_BLENDING;
1422 else
1423 blender_mode = BLND_MODE_OTHER_PIPE;
1424 }
1425 }
1426 dce_set_blender_mode(dc->hwseq, pipe_ctx->pipe_idx, blender_mode);
1427 }
1428
1429 /**
1430 * TODO REMOVE, USE UPDATE INSTEAD
1431 */
1432 static void set_plane_config(
1433 const struct core_dc *dc,
1434 struct pipe_ctx *pipe_ctx,
1435 struct resource_context *res_ctx)
1436 {
1437 struct mem_input *mi = pipe_ctx->mi;
1438 struct core_surface *surface = pipe_ctx->surface;
1439 struct xfm_grph_csc_adjustment adjust;
1440 struct out_csc_color_matrix tbl_entry;
1441 unsigned int i;
1442
1443 memset(&adjust, 0, sizeof(adjust));
1444 memset(&tbl_entry, 0, sizeof(tbl_entry));
1445 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS;
1446
1447 dce_enable_fe_clock(dc->hwseq, pipe_ctx->pipe_idx, true);
1448
1449 set_default_colors(pipe_ctx);
1450 if (pipe_ctx->stream->public.csc_color_matrix.enable_adjustment
1451 == true) {
1452 tbl_entry.color_space =
1453 pipe_ctx->stream->public.output_color_space;
1454
1455 for (i = 0; i < 12; i++)
1456 tbl_entry.regval[i] =
1457 pipe_ctx->stream->public.csc_color_matrix.matrix[i];
1458
1459 pipe_ctx->opp->funcs->opp_set_csc_adjustment
1460 (pipe_ctx->opp, &tbl_entry);
1461 }
1462
1463 if (pipe_ctx->stream->public.gamut_remap_matrix.enable_remap == true) {
1464 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW;
1465 adjust.temperature_matrix[0] =
1466 pipe_ctx->stream->
1467 public.gamut_remap_matrix.matrix[0];
1468 adjust.temperature_matrix[1] =
1469 pipe_ctx->stream->
1470 public.gamut_remap_matrix.matrix[1];
1471 adjust.temperature_matrix[2] =
1472 pipe_ctx->stream->
1473 public.gamut_remap_matrix.matrix[2];
1474 adjust.temperature_matrix[3] =
1475 pipe_ctx->stream->
1476 public.gamut_remap_matrix.matrix[4];
1477 adjust.temperature_matrix[4] =
1478 pipe_ctx->stream->
1479 public.gamut_remap_matrix.matrix[5];
1480 adjust.temperature_matrix[5] =
1481 pipe_ctx->stream->
1482 public.gamut_remap_matrix.matrix[6];
1483 adjust.temperature_matrix[6] =
1484 pipe_ctx->stream->
1485 public.gamut_remap_matrix.matrix[8];
1486 adjust.temperature_matrix[7] =
1487 pipe_ctx->stream->
1488 public.gamut_remap_matrix.matrix[9];
1489 adjust.temperature_matrix[8] =
1490 pipe_ctx->stream->
1491 public.gamut_remap_matrix.matrix[10];
1492 }
1493
1494 pipe_ctx->xfm->funcs->transform_set_gamut_remap(pipe_ctx->xfm, &adjust);
1495
1496 pipe_ctx->scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0;
1497 program_scaler(dc, pipe_ctx);
1498
1499 program_blender(dc, pipe_ctx);
1500
1501 mi->funcs->mem_input_program_surface_config(
1502 mi,
1503 surface->public.format,
1504 &surface->public.tiling_info,
1505 &surface->public.plane_size,
1506 surface->public.rotation,
1507 NULL,
1508 false);
1509
1510 if (dc->public.config.gpu_vm_support)
1511 mi->funcs->mem_input_program_pte_vm(
1512 pipe_ctx->mi,
1513 surface->public.format,
1514 &surface->public.tiling_info,
1515 surface->public.rotation);
1516 }
1517
1518 static void update_plane_addr(const struct core_dc *dc,
1519 struct pipe_ctx *pipe_ctx)
1520 {
1521 struct core_surface *surface = pipe_ctx->surface;
1522
1523 if (surface == NULL)
1524 return;
1525
1526 pipe_ctx->mi->funcs->mem_input_program_surface_flip_and_addr(
1527 pipe_ctx->mi,
1528 &surface->public.address,
1529 surface->public.flip_immediate);
1530
1531 surface->status.requested_address = surface->public.address;
1532
1533 if (surface->public.visible)
1534 pipe_ctx->tg->funcs->set_blank(pipe_ctx->tg, false);
1535 }
1536
1537 void dce110_update_pending_status(struct pipe_ctx *pipe_ctx)
1538 {
1539 struct core_surface *surface = pipe_ctx->surface;
1540
1541 if (surface == NULL)
1542 return;
1543
1544 surface->status.is_flip_pending =
1545 pipe_ctx->mi->funcs->mem_input_is_flip_pending(
1546 pipe_ctx->mi);
1547
1548 if (surface->status.is_flip_pending && !surface->public.visible)
1549 pipe_ctx->mi->current_address = pipe_ctx->mi->request_address;
1550
1551 surface->status.current_address = pipe_ctx->mi->current_address;
1552 }
1553
1554 void dce110_power_down(struct core_dc *dc)
1555 {
1556 power_down_all_hw_blocks(dc);
1557 disable_vga_and_power_gate_all_controllers(dc);
1558 }
1559
1560 static bool wait_for_reset_trigger_to_occur(
1561 struct dc_context *dc_ctx,
1562 struct timing_generator *tg)
1563 {
1564 bool rc = false;
1565
1566 /* To avoid endless loop we wait at most
1567 * frames_to_wait_on_triggered_reset frames for the reset to occur. */
1568 const uint32_t frames_to_wait_on_triggered_reset = 10;
1569 uint32_t i;
1570
1571 for (i = 0; i < frames_to_wait_on_triggered_reset; i++) {
1572
1573 if (!tg->funcs->is_counter_moving(tg)) {
1574 DC_ERROR("TG counter is not moving!\n");
1575 break;
1576 }
1577
1578 if (tg->funcs->did_triggered_reset_occur(tg)) {
1579 rc = true;
1580 /* usually occurs at i=1 */
1581 DC_SYNC_INFO("GSL: reset occurred at wait count: %d\n",
1582 i);
1583 break;
1584 }
1585
1586 /* Wait for one frame. */
1587 tg->funcs->wait_for_state(tg, CRTC_STATE_VACTIVE);
1588 tg->funcs->wait_for_state(tg, CRTC_STATE_VBLANK);
1589 }
1590
1591 if (false == rc)
1592 DC_ERROR("GSL: Timeout on reset trigger!\n");
1593
1594 return rc;
1595 }
1596
1597 /* Enable timing synchronization for a group of Timing Generators. */
1598 static void dce110_enable_timing_synchronization(
1599 struct core_dc *dc,
1600 int group_index,
1601 int group_size,
1602 struct pipe_ctx *grouped_pipes[])
1603 {
1604 struct dc_context *dc_ctx = dc->ctx;
1605 struct dcp_gsl_params gsl_params = { 0 };
1606 int i;
1607
1608 DC_SYNC_INFO("GSL: Setting-up...\n");
1609
1610 /* Designate a single TG in the group as a master.
1611 * Since HW doesn't care which one, we always assign
1612 * the 1st one in the group. */
1613 gsl_params.gsl_group = 0;
1614 gsl_params.gsl_master = grouped_pipes[0]->tg->inst;
1615
1616 for (i = 0; i < group_size; i++)
1617 grouped_pipes[i]->tg->funcs->setup_global_swap_lock(
1618 grouped_pipes[i]->tg, &gsl_params);
1619
1620 /* Reset slave controllers on master VSync */
1621 DC_SYNC_INFO("GSL: enabling trigger-reset\n");
1622
1623 for (i = 1 /* skip the master */; i < group_size; i++)
1624 grouped_pipes[i]->tg->funcs->enable_reset_trigger(
1625 grouped_pipes[i]->tg, gsl_params.gsl_group);
1626
1627
1628
1629 for (i = 1 /* skip the master */; i < group_size; i++) {
1630 DC_SYNC_INFO("GSL: waiting for reset to occur.\n");
1631 wait_for_reset_trigger_to_occur(dc_ctx, grouped_pipes[i]->tg);
1632 /* Regardless of success of the wait above, remove the reset or
1633 * the driver will start timing out on Display requests. */
1634 DC_SYNC_INFO("GSL: disabling trigger-reset.\n");
1635 grouped_pipes[i]->tg->funcs->disable_reset_trigger(grouped_pipes[i]->tg);
1636 }
1637
1638
1639 /* GSL Vblank synchronization is a one time sync mechanism, assumption
1640 * is that the sync'ed displays will not drift out of sync over time*/
1641 DC_SYNC_INFO("GSL: Restoring register states.\n");
1642 for (i = 0; i < group_size; i++)
1643 grouped_pipes[i]->tg->funcs->tear_down_global_swap_lock(grouped_pipes[i]->tg);
1644
1645 DC_SYNC_INFO("GSL: Set-up complete.\n");
1646 }
1647
1648 static void init_hw(struct core_dc *dc)
1649 {
1650 int i;
1651 struct dc_bios *bp;
1652 struct transform *xfm;
1653
1654 bp = dc->ctx->dc_bios;
1655 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1656 xfm = dc->res_pool->transforms[i];
1657 xfm->funcs->transform_reset(xfm);
1658
1659 dc->hwss.enable_display_power_gating(
1660 dc, i, bp,
1661 PIPE_GATING_CONTROL_INIT);
1662 dc->hwss.enable_display_power_gating(
1663 dc, i, bp,
1664 PIPE_GATING_CONTROL_DISABLE);
1665 dc->hwss.enable_display_pipe_clock_gating(
1666 dc->ctx,
1667 true);
1668 }
1669
1670 dce_clock_gating_power_up(dc->hwseq, false);;
1671 /***************************************/
1672
1673 for (i = 0; i < dc->link_count; i++) {
1674 /****************************************/
1675 /* Power up AND update implementation according to the
1676 * required signal (which may be different from the
1677 * default signal on connector). */
1678 struct core_link *link = dc->links[i];
1679 link->link_enc->funcs->hw_init(link->link_enc);
1680 }
1681
1682 for (i = 0; i < dc->res_pool->pipe_count; i++) {
1683 struct timing_generator *tg = dc->res_pool->timing_generators[i];
1684
1685 tg->funcs->disable_vga(tg);
1686
1687 /* Blank controller using driver code instead of
1688 * command table. */
1689 tg->funcs->set_blank(tg, true);
1690 }
1691
1692 for (i = 0; i < dc->res_pool->audio_count; i++) {
1693 struct audio *audio = dc->res_pool->audios[i];
1694 audio->funcs->hw_init(audio);
1695 }
1696 }
1697
1698 /* TODO: move this to apply_ctx_tohw some how?*/
1699 static void dce110_power_on_pipe_if_needed(
1700 struct core_dc *dc,
1701 struct pipe_ctx *pipe_ctx,
1702 struct validate_context *context)
1703 {
1704 struct pipe_ctx *old_pipe_ctx = &dc->current_context->res_ctx.pipe_ctx[pipe_ctx->pipe_idx];
1705 struct dc_bios *dcb = dc->ctx->dc_bios;
1706 struct tg_color black_color = {0};
1707
1708 if (!old_pipe_ctx->stream && pipe_ctx->stream) {
1709 dc->hwss.enable_display_power_gating(
1710 dc,
1711 pipe_ctx->pipe_idx,
1712 dcb, PIPE_GATING_CONTROL_DISABLE);
1713
1714 /*
1715 * This is for powering on underlay, so crtc does not
1716 * need to be enabled
1717 */
1718
1719 pipe_ctx->tg->funcs->program_timing(pipe_ctx->tg,
1720 &pipe_ctx->stream->public.timing,
1721 false);
1722
1723 pipe_ctx->tg->funcs->enable_advanced_request(
1724 pipe_ctx->tg,
1725 true,
1726 &pipe_ctx->stream->public.timing);
1727
1728 pipe_ctx->mi->funcs->allocate_mem_input(pipe_ctx->mi,
1729 pipe_ctx->stream->public.timing.h_total,
1730 pipe_ctx->stream->public.timing.v_total,
1731 pipe_ctx->stream->public.timing.pix_clk_khz,
1732 context->target_count);
1733
1734 /* TODO unhardcode*/
1735 color_space_to_black_color(dc,
1736 COLOR_SPACE_YCBCR601, &black_color);
1737 pipe_ctx->tg->funcs->set_blank_color(
1738 pipe_ctx->tg,
1739 &black_color);
1740 }
1741 }
1742
1743 static void dce110_increase_watermarks_for_pipe(
1744 struct core_dc *dc,
1745 struct pipe_ctx *pipe_ctx,
1746 struct validate_context *context)
1747 {
1748 if (did_watermarks_increase(pipe_ctx, context, dc->current_context))
1749 program_wm_for_pipe(dc, pipe_ctx, context);
1750 }
1751
1752 static void dce110_set_bandwidth(struct core_dc *dc)
1753 {
1754 int i;
1755
1756 for (i = 0; i < dc->current_context->res_ctx.pool->pipe_count; i++) {
1757 struct pipe_ctx *pipe_ctx = &dc->current_context->res_ctx.pipe_ctx[i];
1758
1759 if (!pipe_ctx->stream)
1760 continue;
1761
1762 program_wm_for_pipe(dc, pipe_ctx, dc->current_context);
1763 }
1764
1765 dc->current_context->res_ctx.pool->display_clock->funcs->set_clock(
1766 dc->current_context->res_ctx.pool->display_clock,
1767 dc->current_context->bw_results.dispclk_khz * 115 / 100);
1768 }
1769
1770 static void dce110_program_front_end_for_pipe(
1771 struct core_dc *dc, struct pipe_ctx *pipe_ctx)
1772 {
1773 struct mem_input *mi = pipe_ctx->mi;
1774 struct pipe_ctx *old_pipe = NULL;
1775 struct core_surface *surface = pipe_ctx->surface;
1776 struct xfm_grph_csc_adjustment adjust;
1777 struct out_csc_color_matrix tbl_entry;
1778 unsigned int i;
1779
1780 memset(&tbl_entry, 0, sizeof(tbl_entry));
1781
1782 if (dc->current_context)
1783 old_pipe = &dc->current_context->res_ctx.pipe_ctx[pipe_ctx->pipe_idx];
1784
1785 memset(&adjust, 0, sizeof(adjust));
1786 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS;
1787
1788 dce_enable_fe_clock(dc->hwseq, pipe_ctx->pipe_idx, true);
1789
1790 set_default_colors(pipe_ctx);
1791 if (pipe_ctx->stream->public.csc_color_matrix.enable_adjustment
1792 == true) {
1793 tbl_entry.color_space =
1794 pipe_ctx->stream->public.output_color_space;
1795
1796 for (i = 0; i < 12; i++)
1797 tbl_entry.regval[i] =
1798 pipe_ctx->stream->public.csc_color_matrix.matrix[i];
1799
1800 pipe_ctx->opp->funcs->opp_set_csc_adjustment
1801 (pipe_ctx->opp, &tbl_entry);
1802 }
1803
1804 if (pipe_ctx->stream->public.gamut_remap_matrix.enable_remap == true) {
1805 adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_SW;
1806 adjust.temperature_matrix[0] =
1807 pipe_ctx->stream->
1808 public.gamut_remap_matrix.matrix[0];
1809 adjust.temperature_matrix[1] =
1810 pipe_ctx->stream->
1811 public.gamut_remap_matrix.matrix[1];
1812 adjust.temperature_matrix[2] =
1813 pipe_ctx->stream->
1814 public.gamut_remap_matrix.matrix[2];
1815 adjust.temperature_matrix[3] =
1816 pipe_ctx->stream->
1817 public.gamut_remap_matrix.matrix[4];
1818 adjust.temperature_matrix[4] =
1819 pipe_ctx->stream->
1820 public.gamut_remap_matrix.matrix[5];
1821 adjust.temperature_matrix[5] =
1822 pipe_ctx->stream->
1823 public.gamut_remap_matrix.matrix[6];
1824 adjust.temperature_matrix[6] =
1825 pipe_ctx->stream->
1826 public.gamut_remap_matrix.matrix[8];
1827 adjust.temperature_matrix[7] =
1828 pipe_ctx->stream->
1829 public.gamut_remap_matrix.matrix[9];
1830 adjust.temperature_matrix[8] =
1831 pipe_ctx->stream->
1832 public.gamut_remap_matrix.matrix[10];
1833 }
1834
1835 pipe_ctx->xfm->funcs->transform_set_gamut_remap(pipe_ctx->xfm, &adjust);
1836
1837 pipe_ctx->scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != 0;
1838 if (old_pipe && memcmp(&old_pipe->scl_data,
1839 &pipe_ctx->scl_data,
1840 sizeof(struct scaler_data)) != 0)
1841 program_scaler(dc, pipe_ctx);
1842
1843 mi->funcs->mem_input_program_surface_config(
1844 mi,
1845 surface->public.format,
1846 &surface->public.tiling_info,
1847 &surface->public.plane_size,
1848 surface->public.rotation,
1849 false,
1850 false);
1851
1852 if (dc->public.config.gpu_vm_support)
1853 mi->funcs->mem_input_program_pte_vm(
1854 pipe_ctx->mi,
1855 surface->public.format,
1856 &surface->public.tiling_info,
1857 surface->public.rotation);
1858
1859 dm_logger_write(dc->ctx->logger, LOG_SURFACE,
1860 "Pipe:%d 0x%x: addr hi:0x%x, "
1861 "addr low:0x%x, "
1862 "src: %d, %d, %d,"
1863 " %d; dst: %d, %d, %d, %d;"
1864 "clip: %d, %d, %d, %d\n",
1865 pipe_ctx->pipe_idx,
1866 pipe_ctx->surface,
1867 pipe_ctx->surface->public.address.grph.addr.high_part,
1868 pipe_ctx->surface->public.address.grph.addr.low_part,
1869 pipe_ctx->surface->public.src_rect.x,
1870 pipe_ctx->surface->public.src_rect.y,
1871 pipe_ctx->surface->public.src_rect.width,
1872 pipe_ctx->surface->public.src_rect.height,
1873 pipe_ctx->surface->public.dst_rect.x,
1874 pipe_ctx->surface->public.dst_rect.y,
1875 pipe_ctx->surface->public.dst_rect.width,
1876 pipe_ctx->surface->public.dst_rect.height,
1877 pipe_ctx->surface->public.clip_rect.x,
1878 pipe_ctx->surface->public.clip_rect.y,
1879 pipe_ctx->surface->public.clip_rect.width,
1880 pipe_ctx->surface->public.clip_rect.height);
1881
1882 dm_logger_write(dc->ctx->logger, LOG_SURFACE,
1883 "Pipe %d: width, height, x, y\n"
1884 "viewport:%d, %d, %d, %d\n"
1885 "recout: %d, %d, %d, %d\n",
1886 pipe_ctx->pipe_idx,
1887 pipe_ctx->scl_data.viewport.width,
1888 pipe_ctx->scl_data.viewport.height,
1889 pipe_ctx->scl_data.viewport.x,
1890 pipe_ctx->scl_data.viewport.y,
1891 pipe_ctx->scl_data.recout.width,
1892 pipe_ctx->scl_data.recout.height,
1893 pipe_ctx->scl_data.recout.x,
1894 pipe_ctx->scl_data.recout.y);
1895 }
1896
1897 static void dce110_prepare_pipe_for_context(
1898 struct core_dc *dc,
1899 struct pipe_ctx *pipe_ctx,
1900 struct validate_context *context)
1901 {
1902 dce110_power_on_pipe_if_needed(dc, pipe_ctx, context);
1903 dc->hwss.increase_watermarks_for_pipe(dc, pipe_ctx, context);
1904 }
1905
1906 static void dce110_apply_ctx_for_surface(
1907 struct core_dc *dc,
1908 struct core_surface *surface,
1909 struct validate_context *context)
1910 {
1911 int i;
1912
1913 /* TODO remove when removing the surface reset workaroud*/
1914 if (!surface)
1915 return;
1916
1917 for (i = 0; i < context->res_ctx.pool->pipe_count; i++) {
1918 struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
1919
1920 if (pipe_ctx->surface != surface)
1921 continue;
1922
1923 dce110_program_front_end_for_pipe(dc, pipe_ctx);
1924 program_blender(dc, pipe_ctx);
1925
1926 }
1927 }
1928
1929 static void dce110_power_down_fe(struct core_dc *dc, struct pipe_ctx *pipe)
1930 {
1931 int i;
1932
1933 for (i = 0; i < dc->res_pool->pipe_count; i++)
1934 if (&dc->current_context->res_ctx.pipe_ctx[i] == pipe)
1935 break;
1936
1937 if (i == dc->res_pool->pipe_count)
1938 return;
1939
1940 dc->hwss.enable_display_power_gating(
1941 dc, i, dc->ctx->dc_bios, PIPE_GATING_CONTROL_ENABLE);
1942 if (pipe->xfm)
1943 pipe->xfm->funcs->transform_reset(pipe->xfm);
1944 memset(&pipe->scl_data, 0, sizeof(struct scaler_data));
1945 }
1946
1947 static const struct hw_sequencer_funcs dce110_funcs = {
1948 .init_hw = init_hw,
1949 .apply_ctx_to_hw = dce110_apply_ctx_to_hw,
1950 .prepare_pipe_for_context = dce110_prepare_pipe_for_context,
1951 .apply_ctx_for_surface = dce110_apply_ctx_for_surface,
1952 .set_plane_config = set_plane_config,
1953 .update_plane_addr = update_plane_addr,
1954 .update_pending_status = dce110_update_pending_status,
1955 .set_input_transfer_func = dce110_set_input_transfer_func,
1956 .set_output_transfer_func = dce110_set_output_transfer_func,
1957 .power_down = dce110_power_down,
1958 .enable_accelerated_mode = dce110_enable_accelerated_mode,
1959 .enable_timing_synchronization = dce110_enable_timing_synchronization,
1960 .update_info_frame = dce110_update_info_frame,
1961 .enable_stream = dce110_enable_stream,
1962 .disable_stream = dce110_disable_stream,
1963 .unblank_stream = dce110_unblank_stream,
1964 .enable_display_pipe_clock_gating = enable_display_pipe_clock_gating,
1965 .enable_display_power_gating = dce110_enable_display_power_gating,
1966 .power_down_front_end = dce110_power_down_fe,
1967 .pipe_control_lock = dce_pipe_control_lock,
1968 .set_displaymarks = dce110_set_displaymarks,
1969 .increase_watermarks_for_pipe = dce110_increase_watermarks_for_pipe,
1970 .set_bandwidth = dce110_set_bandwidth,
1971 .set_drr = set_drr,
1972 .set_static_screen_control = set_static_screen_control,
1973 .reset_hw_ctx_wrap = reset_hw_ctx_wrap,
1974 .prog_pixclk_crtc_otg = prog_pixclk_crtc_otg,
1975 };
1976
1977 bool dce110_hw_sequencer_construct(struct core_dc *dc)
1978 {
1979 dc->hwss = dce110_funcs;
1980
1981 return true;
1982 }
1983