2 * Copyright 2015 Advanced Micro Devices, Inc.
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
25 #include "dm_services.h"
27 #include "dc_bios_types.h"
28 #include "core_types.h"
29 #include "core_status.h"
31 #include "hw_sequencer.h"
32 #include "dm_helpers.h"
33 #include "dce110_hw_sequencer.h"
34 #include "dce110_timing_generator.h"
36 #include "bios/bios_parser_helper.h"
37 #include "timing_generator.h"
38 #include "mem_input.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"
47 #include "dce/dce_hwseq.h"
49 /* include DCE11 register header files */
50 #include "dce/dce_11_0_d.h"
51 #include "dce/dce_11_0_sh_mask.h"
53 struct dce110_hw_seq_reg_offsets
{
57 static const struct dce110_hw_seq_reg_offsets reg_offsets
[] = {
59 .crtc
= (mmCRTC0_CRTC_GSL_CONTROL
- mmCRTC_GSL_CONTROL
),
62 .crtc
= (mmCRTC1_CRTC_GSL_CONTROL
- mmCRTC_GSL_CONTROL
),
65 .crtc
= (mmCRTC2_CRTC_GSL_CONTROL
- mmCRTC_GSL_CONTROL
),
68 .crtc
= (mmCRTCV_GSL_CONTROL
- mmCRTC_GSL_CONTROL
),
72 #define HW_REG_BLND(reg, id)\
73 (reg + reg_offsets[id].blnd)
75 #define HW_REG_CRTC(reg, id)\
76 (reg + reg_offsets[id].crtc)
78 #define MAX_WATERMARK 0xFFFF
79 #define SAFE_NBP_MARK 0x7FFF
81 /*******************************************************************************
83 ******************************************************************************/
84 /***************************PIPE_CONTROL***********************************/
85 static void dce110_init_pte(struct dc_context
*ctx
)
89 uint32_t chunk_int
= 0;
90 uint32_t chunk_mul
= 0;
92 addr
= mmUNP_DVMM_PTE_CONTROL
;
93 value
= dm_read_reg(ctx
, addr
);
105 DVMM_PTE_BUFFER_MODE0
);
111 DVMM_PTE_BUFFER_MODE1
);
113 dm_write_reg(ctx
, addr
, value
);
115 addr
= mmDVMM_PTE_REQ
;
116 value
= dm_read_reg(ctx
, addr
);
118 chunk_int
= get_reg_field_value(
121 HFLIP_PTEREQ_PER_CHUNK_INT
);
123 chunk_mul
= get_reg_field_value(
126 HFLIP_PTEREQ_PER_CHUNK_MULTIPLIER
);
128 if (chunk_int
!= 0x4 || chunk_mul
!= 0x4) {
134 MAX_PTEREQ_TO_ISSUE
);
140 HFLIP_PTEREQ_PER_CHUNK_INT
);
146 HFLIP_PTEREQ_PER_CHUNK_MULTIPLIER
);
148 dm_write_reg(ctx
, addr
, value
);
151 /**************************************************************************/
153 static void enable_display_pipe_clock_gating(
154 struct dc_context
*ctx
,
160 static bool dce110_enable_display_power_gating(
162 uint8_t controller_id
,
164 enum pipe_gating_control power_gating
)
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
;
171 if (IS_FPGA_MAXIMUS_DC(ctx
->dce_environment
))
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
;
179 cntl
= ASIC_PIPE_DISABLE
;
181 if (controller_id
== underlay_idx
)
182 controller_id
= CONTROLLER_ID_UNDERLAY0
- 1;
184 if (power_gating
!= PIPE_GATING_CONTROL_INIT
|| controller_id
== 0){
186 bp_result
= dcb
->funcs
->enable_disp_power_gating(
187 dcb
, controller_id
+ 1, cntl
);
189 /* Revert MASTER_UPDATE_MODE to 0 because bios sets it 2
190 * by default when command table is called
192 * Bios parser accepts controller_id = 6 as indicative of
193 * underlay pipe in dce110. But we do not support more
196 if (controller_id
< CONTROLLER_ID_MAX
- 1)
198 HW_REG_CRTC(mmCRTC_MASTER_UPDATE_MODE
, controller_id
),
202 if (power_gating
!= PIPE_GATING_CONTROL_ENABLE
)
203 dce110_init_pte(ctx
);
205 if (bp_result
== BP_RESULT_OK
)
211 static void build_prescale_params(struct ipp_prescale_params
*prescale_params
,
212 const struct core_surface
*surface
)
214 prescale_params
->mode
= IPP_PRESCALE_MODE_FIXED_UNSIGNED
;
216 switch (surface
->public.format
) {
217 case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888
:
218 case SURFACE_PIXEL_FORMAT_GRPH_BGRA8888
:
219 prescale_params
->scale
= 0x2020;
221 case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010
:
222 case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010
:
223 prescale_params
->scale
= 0x2008;
225 case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616
:
226 case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F
:
227 prescale_params
->scale
= 0x2000;
235 static bool dce110_set_input_transfer_func(
236 struct pipe_ctx
*pipe_ctx
,
237 const struct core_surface
*surface
)
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 };
247 if (surface
->public.in_transfer_func
)
248 tf
= DC_TRANSFER_FUNC_TO_CORE(surface
->public.in_transfer_func
);
250 build_prescale_params(&prescale_params
, surface
);
251 ipp
->funcs
->ipp_program_prescale(ipp
, &prescale_params
);
253 if (surface
->public.gamma_correction
)
254 ipp
->funcs
->ipp_program_input_lut(ipp
, surface
->public.gamma_correction
);
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
);
266 case TRANSFER_FUNCTION_BT709
:
267 ipp
->funcs
->ipp_set_degamma(ipp
,
268 IPP_DEGAMMA_MODE_HW_xvYCC
);
270 case TRANSFER_FUNCTION_LINEAR
:
271 ipp
->funcs
->ipp_set_degamma(ipp
,
272 IPP_DEGAMMA_MODE_BYPASS
);
274 case TRANSFER_FUNCTION_PQ
:
282 /*TF_TYPE_DISTRIBUTED_POINTS - Not supported in DCE 11*/
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
)
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
;
300 if (surface
->public.gamma_correction
)
301 ramp
= DC_GAMMA_TO_CORE(surface
->public.gamma_correction
);
303 regamma_params
= dm_alloc(sizeof(struct pwl_params
));
304 if (regamma_params
== NULL
)
305 goto regamma_alloc_fail
;
307 regamma_params
->hw_points_num
= GAMMA_HW_POINTS_NUM
;
309 opp
->funcs
->opp_power_on_regamma_lut(opp
, true);
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
);
319 opp
->funcs
->opp_set_regamma_mode(opp
, OPP_REGAMMA_BYPASS
);
322 opp
->funcs
->opp_power_on_regamma_lut(opp
, false);
326 dm_free(regamma_params
);
332 static enum dc_status
bios_parser_crtc_source_select(
333 struct pipe_ctx
*pipe_ctx
)
336 /* call VBIOS table to set CRTC source for the HW
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
;
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
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
;
352 dcb
= sink
->ctx
->dc_bios
;
354 if (BP_RESULT_OK
!= dcb
->funcs
->crtc_source_select(
356 &crtc_source_select
)) {
357 return DC_ERROR_UNEXPECTED
;
363 void dce110_update_info_frame(struct pipe_ctx
*pipe_ctx
)
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
);
375 void dce110_enable_stream(struct pipe_ctx
*pipe_ctx
)
377 enum dc_lane_count lane_count
=
378 pipe_ctx
->stream
->sink
->link
->public.cur_link_settings
.lane_count
;
380 struct dc_crtc_timing
*timing
= &pipe_ctx
->stream
->public.timing
;
381 struct core_link
*link
= pipe_ctx
->stream
->sink
->link
;
383 /* 1. update AVI info frame (HDMI, DP)
384 * we always need to update info frame
386 uint32_t active_total_with_borders
;
387 uint32_t early_control
= 0;
388 struct timing_generator
*tg
= pipe_ctx
->tg
;
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
;
399 early_control
= active_total_with_borders
% lane_count
;
401 if (early_control
== 0)
402 early_control
= lane_count
;
404 tg
->funcs
->set_early_control(tg
, early_control
);
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
);
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);
421 void dce110_disable_stream(struct pipe_ctx
*pipe_ctx
)
423 struct core_stream
*stream
= pipe_ctx
->stream
;
424 struct core_link
*link
= stream
->sink
->link
;
426 if (pipe_ctx
->audio
) {
427 pipe_ctx
->audio
->funcs
->az_disable(pipe_ctx
->audio
);
429 if (dc_is_dp_signal(pipe_ctx
->stream
->signal
))
430 pipe_ctx
->stream_enc
->funcs
->dp_audio_disable(
431 pipe_ctx
->stream_enc
);
433 pipe_ctx
->stream_enc
->funcs
->hdmi_audio_disable(
434 pipe_ctx
->stream_enc
);
436 pipe_ctx
->audio
= NULL
;
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);
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
);
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
);
453 pipe_ctx
->stream_enc
->funcs
->audio_mute_control(
454 pipe_ctx
->stream_enc
, true);
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
);
461 link
->link_enc
->funcs
->connect_dig_be_to_fe(
463 pipe_ctx
->stream_enc
->id
,
468 void dce110_unblank_stream(struct pipe_ctx
*pipe_ctx
,
469 struct dc_link_settings
*link_settings
)
471 struct encoder_unblank_param params
= { { 0 } };
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
, ¶ms
);
480 static enum audio_dto_source
translate_to_dto_source(enum controller_id 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
;
496 return DTO_SOURCE_UNKNOWN
;
500 static void build_audio_output(
501 const struct pipe_ctx
*pipe_ctx
,
502 struct audio_output
*audio_output
)
504 const struct core_stream
*stream
= pipe_ctx
->stream
;
505 audio_output
->engine_id
= pipe_ctx
->stream_enc
->id
;
507 audio_output
->signal
= pipe_ctx
->stream
->signal
;
509 /* audio_crtc_info */
511 audio_output
->crtc_info
.h_total
=
512 stream
->public.timing
.h_total
;
515 * Audio packets are sent during actual CRTC blank physical signal, we
516 * need to specify actual active signal portion
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
;
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
;
528 audio_output
->crtc_info
.pixel_repetition
= 1;
530 audio_output
->crtc_info
.interlaced
=
531 stream
->public.timing
.flags
.INTERLACE
;
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
);
537 audio_output
->crtc_info
.color_depth
=
538 stream
->public.timing
.display_color_depth
;
540 audio_output
->crtc_info
.requested_pixel_clock
=
541 pipe_ctx
->pix_clk_params
.requested_pix_clk
;
544 * TODO - Investigate why calculated pixel clk has to be
545 * requested pixel clk
547 audio_output
->crtc_info
.calculated_pixel_clock
=
548 pipe_ctx
->pix_clk_params
.requested_pix_clk
;
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(
557 audio_output
->pll_info
.feed_back_divider
=
558 pipe_ctx
->pll_settings
.feedback_divider
;
560 audio_output
->pll_info
.dto_source
=
561 translate_to_dto_source(
562 pipe_ctx
->pipe_idx
+ 1);
564 /* TODO hard code to enable for now. Need get from stream */
565 audio_output
->pll_info
.ss_enabled
= true;
567 audio_output
->pll_info
.ss_percentage
=
568 pipe_ctx
->pll_settings
.ss_percentage
;
571 static void get_surface_visual_confirm_color(const struct pipe_ctx
*pipe_ctx
,
572 struct tg_color
*color
)
574 uint32_t color_value
= MAX_TG_COLOR_VALUE
* (4 - pipe_ctx
->pipe_idx
) / 4;
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
;
582 case PIXEL_FORMAT_ARGB2101010
:
583 /* set boarder color to blue */
584 color
->color_b_cb
= color_value
;
586 case PIXEL_FORMAT_420BPP12
:
587 /* set boarder color to green */
588 color
->color_g_y
= color_value
;
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
;
601 static void program_scaler(const struct core_dc
*dc
,
602 const struct pipe_ctx
*pipe_ctx
)
604 struct tg_color color
= {0};
606 if (dc
->public.debug
.surface_visual_confirm
)
607 get_surface_visual_confirm_color(pipe_ctx
, &color
);
609 color_space_to_black_color(dc
,
610 pipe_ctx
->stream
->public.output_color_space
,
613 pipe_ctx
->xfm
->funcs
->transform_set_pixel_storage_depth(
615 pipe_ctx
->scl_data
.lb_params
.depth
,
616 &pipe_ctx
->stream
->bit_depth_params
);
618 if (pipe_ctx
->tg
->funcs
->set_overscan_blank_color
)
619 pipe_ctx
->tg
->funcs
->set_overscan_blank_color(
623 pipe_ctx
->xfm
->funcs
->transform_set_scaler(pipe_ctx
->xfm
,
624 &pipe_ctx
->scl_data
);
627 static enum dc_status
prog_pixclk_crtc_otg(
628 struct pipe_ctx
*pipe_ctx
,
629 struct validate_context
*context
,
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};
637 if (!pipe_ctx_old
->stream
) {
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(
646 * Must blank CRTC after disabling power gating and before any
647 * programming, otherwise CRTC will be hung in bad state
649 pipe_ctx
->tg
->funcs
->set_blank(pipe_ctx
->tg
, true);
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
)) {
656 return DC_ERROR_UNEXPECTED
;
659 pipe_ctx
->tg
->funcs
->program_timing(
661 &stream
->public.timing
,
665 if (!pipe_ctx_old
->stream
) {
666 if (false == pipe_ctx
->tg
->funcs
->enable_crtc(
669 return DC_ERROR_UNEXPECTED
;
676 static enum dc_status
apply_single_controller_ctx_to_hw(
677 struct pipe_ctx
*pipe_ctx
,
678 struct validate_context
*context
,
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
];
686 dc
->hwss
.prog_pixclk_crtc_otg(pipe_ctx
, context
, dc
);
688 pipe_ctx
->opp
->funcs
->opp_set_dyn_expansion(
690 COLOR_SPACE_YCBCR601
,
691 stream
->public.timing
.display_color_depth
,
692 pipe_ctx
->stream
->signal
);
694 pipe_ctx
->opp
->funcs
->opp_program_fmt(
696 &stream
->bit_depth_params
,
699 /* FPGA does not program backend */
700 if (IS_FPGA_MAXIMUS_DC(dc
->ctx
->dce_environment
))
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
)) {
707 return DC_ERROR_UNEXPECTED
;
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
);
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
);
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
,
726 pipe_ctx
->audio
!= NULL
);
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
) ?
735 if (!pipe_ctx_old
->stream
) {
736 core_link_enable_stream(pipe_ctx
);
738 if (dc_is_dp_signal(pipe_ctx
->stream
->signal
))
739 dce110_unblank_stream(pipe_ctx
,
740 &stream
->sink
->link
->public.cur_link_settings
);
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
,
747 sizeof(struct scaler_data
)) != 0)
748 program_scaler(dc
, pipe_ctx
);
750 /* mst support - use total stream count */
751 pipe_ctx
->mi
->funcs
->allocate_mem_input(
753 stream
->public.timing
.h_total
,
754 stream
->public.timing
.v_total
,
755 stream
->public.timing
.pix_clk_khz
,
756 context
->target_count
);
761 /******************************************************************************/
763 static void power_down_encoders(struct core_dc
*dc
)
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
);
773 static void power_down_controllers(struct core_dc
*dc
)
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
]);
783 static void power_down_clock_sources(struct core_dc
*dc
)
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");
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
);
798 static void power_down_all_hw_blocks(struct core_dc
*dc
)
800 power_down_encoders(dc
);
802 power_down_controllers(dc
);
804 power_down_clock_sources(dc
);
807 static void disable_vga_and_power_gate_all_controllers(
811 struct timing_generator
*tg
;
812 struct dc_context
*ctx
= dc
->ctx
;
814 for (i
= 0; i
< dc
->res_pool
->pipe_count
; i
++) {
815 tg
= dc
->res_pool
->timing_generators
[i
];
817 tg
->funcs
->disable_vga(tg
);
819 /* Enable CLOCK gating for each pipe BEFORE controller
821 enable_display_pipe_clock_gating(ctx
,
824 dc
->hwss
.power_down_front_end(
825 dc
, &dc
->current_context
->res_ctx
.pipe_ctx
[i
]);
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)
836 void dce110_enable_accelerated_mode(struct core_dc
*dc
)
838 power_down_all_hw_blocks(dc
);
840 disable_vga_and_power_gate_all_controllers(dc
);
841 bios_set_scratch_acc_mode_change(dc
->ctx
->dc_bios
);
844 static uint32_t compute_pstate_blackout_duration(
845 struct bw_fixed blackout_duration
,
846 const struct core_stream
*stream
)
848 uint32_t total_dest_line_time_ns
;
849 uint32_t pstate_blackout_duration_ns
;
851 pstate_blackout_duration_ns
= 1000 * blackout_duration
.value
>> 24;
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
;
858 return total_dest_line_time_ns
;
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
,
866 int i
, collapsed_idx
;
868 if (res_ctx
->pipe_ctx
[pipe_idx
].top_pipe
)
872 for (i
= 0; i
< pipe_idx
; i
++) {
873 if (res_ctx
->pipe_ctx
[i
].stream
)
877 return collapsed_idx
;
880 static bool is_watermark_set_a_greater(
881 const struct bw_watermarks
*set_a
,
882 const struct bw_watermarks
*set_b
)
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
)
892 static bool did_watermarks_increase(
893 struct pipe_ctx
*pipe_ctx
,
894 struct validate_context
*context
,
895 struct validate_context
*old_context
)
897 int collapsed_pipe_idx
= get_bw_result_idx(&context
->res_ctx
,
899 int old_collapsed_pipe_idx
= get_bw_result_idx(&old_context
->res_ctx
,
901 struct pipe_ctx
*old_pipe_ctx
= &old_context
->res_ctx
.pipe_ctx
[pipe_ctx
->pipe_idx
];
903 if (!old_pipe_ctx
->stream
)
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
]))
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
]))
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
]))
922 static void program_wm_for_pipe(struct core_dc
*dc
,
923 struct pipe_ctx
*pipe_ctx
,
924 struct validate_context
*context
)
926 int total_dest_line_time_ns
= compute_pstate_blackout_duration(
927 dc
->bw_vbios
.blackout_duration
,
929 int bw_result_idx
= get_bw_result_idx(&context
->res_ctx
,
932 pipe_ctx
->mi
->funcs
->mem_input_program_display_marks(
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
);
939 if (pipe_ctx
->top_pipe
)
940 pipe_ctx
->mi
->funcs
->mem_input_program_chroma_display_marks(
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
);
948 void dce110_set_displaymarks(
949 const struct core_dc
*dc
,
950 struct validate_context
*context
)
952 uint8_t i
, num_pipes
;
953 unsigned int underlay_idx
= dc
->res_pool
->underlay_pipe_index
;
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
;
959 if (pipe_ctx
->stream
== NULL
)
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(
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
) {
972 pipe_ctx
->mi
->funcs
->mem_input_program_chroma_display_marks(
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
);
983 static void set_safe_displaymarks(struct resource_context
*res_ctx
)
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
};
992 for (i
= 0; i
< MAX_PIPES
; i
++) {
993 if (res_ctx
->pipe_ctx
[i
].stream
== NULL
)
996 res_ctx
->pipe_ctx
[i
].mi
->funcs
->mem_input_program_display_marks(
997 res_ctx
->pipe_ctx
[i
].mi
,
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
,
1012 static void switch_dp_clock_sources(
1013 const struct core_dc
*dc
,
1014 struct resource_context
*res_ctx
)
1017 for (i
= 0; i
< MAX_PIPES
; i
++) {
1018 struct pipe_ctx
*pipe_ctx
= &res_ctx
->pipe_ctx
[i
];
1020 if (pipe_ctx
->stream
== NULL
|| pipe_ctx
->top_pipe
)
1023 if (dc_is_dp_signal(pipe_ctx
->stream
->signal
)) {
1024 struct clock_source
*clk_src
=
1025 resource_find_used_clk_src_for_sharing(
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
);
1035 dce_crtc_switch_to_clk_src(dc
->hwseq
, clk_src
, i
);
1041 /*******************************************************************************
1043 ******************************************************************************/
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
)
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();
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
);
1061 dc
->hwss
.power_down_front_end((struct core_dc
*)dc
, pipe_ctx
);
1063 pipe_ctx
->stream
= NULL
;
1066 static void set_drr(struct pipe_ctx
**pipe_ctx
,
1067 int num_pipes
, int vmin
, int vmax
)
1070 struct drr_params params
= {0};
1072 params
.vertical_total_max
= vmax
;
1073 params
.vertical_total_min
= vmin
;
1075 /* TODO: If multiple pipes are to be supported, you need
1079 for (i
= 0; i
< num_pipes
; i
++) {
1080 pipe_ctx
[i
]->tg
->funcs
->set_drr(pipe_ctx
[i
]->tg
, ¶ms
);
1084 static void set_static_screen_control(struct pipe_ctx
**pipe_ctx
,
1085 int num_pipes
, int value
)
1089 for (i
= 0; i
< num_pipes
; i
++)
1090 pipe_ctx
[i
]->tg
->funcs
->
1091 set_static_screen_control(pipe_ctx
[i
]->tg
, value
);
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
1099 static uint32_t get_max_pixel_clock_for_all_paths(
1101 struct validate_context
*context
,
1104 uint32_t max_pix_clk
= 0;
1107 if (!pre_mode_set
) {
1108 /* TODO: read ASIC register to get pixel clock */
1112 for (i
= 0; i
< MAX_PIPES
; i
++) {
1113 struct pipe_ctx
*pipe_ctx
= &context
->res_ctx
.pipe_ctx
[i
];
1115 if (pipe_ctx
->stream
== NULL
)
1118 /* do not check under lay */
1119 if (pipe_ctx
->top_pipe
)
1122 if (pipe_ctx
->pix_clk_params
.requested_pix_clk
> max_pix_clk
)
1124 pipe_ctx
->pix_clk_params
.requested_pix_clk
;
1127 if (max_pix_clk
== 0)
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
1137 static void apply_min_clocks(
1139 struct validate_context
*context
,
1140 enum dm_pp_clocks_state
*clocks_state
,
1143 struct state_dependent_clocks req_clocks
= {0};
1144 struct pipe_ctx
*pipe_ctx
;
1147 for (i
= 0; i
< MAX_PIPES
; i
++) {
1148 pipe_ctx
= &context
->res_ctx
.pipe_ctx
[i
];
1149 if (pipe_ctx
->dis_clk
!= NULL
)
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
);
1164 /* get the required state based on state dependent clocks:
1165 * display clock and pixel clock
1167 req_clocks
.display_clk_khz
= context
->bw_results
.dispclk_khz
;
1169 req_clocks
.pixel_clk_khz
= get_max_pixel_clock_for_all_paths(
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
);
1181 static enum dc_status
apply_ctx_to_hw_fpga(
1183 struct validate_context
*context
)
1185 enum dc_status status
= DC_ERROR_UNEXPECTED
;
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
];
1193 if (pipe_ctx
->stream
== NULL
)
1196 if (pipe_ctx
->stream
== pipe_ctx_old
->stream
)
1199 status
= apply_single_controller_ctx_to_hw(
1204 if (status
!= DC_OK
)
1211 static void reset_hw_ctx_wrap(
1213 struct validate_context
*context
)
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
];
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.
1229 /* Skip underlay pipe since it will be handled in commit surface*/
1230 if (!pipe_ctx_old
->stream
|| pipe_ctx_old
->top_pipe
)
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
);
1240 /*TODO: const validate_context*/
1241 enum dc_status
dce110_apply_ctx_to_hw(
1243 struct validate_context
*context
)
1245 struct dc_bios
*dcb
= dc
->ctx
->dc_bios
;
1246 enum dc_status status
;
1248 bool programmed_audio_dto
= false;
1249 enum dm_pp_clocks_state clocks_state
= DM_PP_CLOCKS_STATE_INVALID
;
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
);
1255 /* Skip applying if no targets */
1256 if (context
->target_count
<= 0)
1259 if (IS_FPGA_MAXIMUS_DC(dc
->ctx
->dce_environment
)) {
1260 apply_ctx_to_hw_fpga(dc
, context
);
1264 /* Apply new context */
1265 dcb
->funcs
->set_scratch_critical_state(dcb
, true);
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
];
1273 if (pipe_ctx
->stream
== NULL
|| pipe_ctx
->top_pipe
)
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
);
1283 dc
->hwss
.enable_display_power_gating(
1284 dc
, i
, dc
->ctx
->dc_bios
,
1285 PIPE_GATING_CONTROL_DISABLE
);
1288 set_safe_displaymarks(&context
->res_ctx
);
1289 /*TODO: when pplib works*/
1290 apply_min_clocks(dc
, context
, &clocks_state
, true);
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);
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
];
1303 if (pipe_ctx
->stream
== NULL
)
1306 if (pipe_ctx
->stream
== pipe_ctx_old
->stream
)
1309 if (pipe_ctx
->top_pipe
)
1312 if (context
->res_ctx
.pipe_ctx
[i
].audio
!= NULL
) {
1313 /* Setup audio rate clock source */
1315 * Audio lag happened on DP monitor when unplug a HDMI monitor
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.
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.
1328 struct audio_output audio_output
;
1330 build_audio_output(pipe_ctx
, &audio_output
);
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
);
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
);
1344 pipe_ctx
->audio
->funcs
->az_configure(
1346 pipe_ctx
->stream
->signal
,
1347 &audio_output
.crtc_info
,
1348 &pipe_ctx
->stream
->public.audio_info
);
1350 if (!programmed_audio_dto
) {
1351 pipe_ctx
->audio
->funcs
->wall_dto_setup(
1353 pipe_ctx
->stream
->signal
,
1354 &audio_output
.crtc_info
,
1355 &audio_output
.pll_info
);
1356 programmed_audio_dto
= true;
1360 status
= apply_single_controller_ctx_to_hw(
1365 if (DC_OK
!= status
)
1369 dc
->hwss
.set_displaymarks(dc
, context
);
1372 apply_min_clocks(dc
, context
, &clocks_state
, false);
1374 dcb
->funcs
->set_scratch_critical_state(dcb
, false);
1376 switch_dp_clock_sources(dc
, &context
->res_ctx
);
1381 /*******************************************************************************
1382 * Front End programming
1383 ******************************************************************************/
1384 static void set_default_colors(struct pipe_ctx
*pipe_ctx
)
1386 struct default_adjustment default_adjust
= { 0 };
1388 default_adjust
.force_hw_default
= false;
1389 if (pipe_ctx
->surface
== NULL
)
1390 default_adjust
.in_color_space
= COLOR_SPACE_SRGB
;
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
;
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
;
1402 /* display color depth */
1403 default_adjust
.color_depth
=
1404 pipe_ctx
->stream
->public.timing
.display_color_depth
;
1406 /* Lb color depth */
1407 default_adjust
.lb_color_depth
= pipe_ctx
->scl_data
.lb_params
.depth
;
1409 pipe_ctx
->opp
->funcs
->opp_set_csc_default(
1410 pipe_ctx
->opp
, &default_adjust
);
1413 static void program_blender(const struct core_dc
*dc
,
1414 struct pipe_ctx
*pipe_ctx
)
1416 enum blnd_mode blender_mode
= BLND_MODE_CURRENT_PIPE
;
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
;
1423 blender_mode
= BLND_MODE_OTHER_PIPE
;
1426 dce_set_blender_mode(dc
->hwseq
, pipe_ctx
->pipe_idx
, blender_mode
);
1430 * TODO REMOVE, USE UPDATE INSTEAD
1432 static void set_plane_config(
1433 const struct core_dc
*dc
,
1434 struct pipe_ctx
*pipe_ctx
,
1435 struct resource_context
*res_ctx
)
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
;
1443 memset(&adjust
, 0, sizeof(adjust
));
1444 memset(&tbl_entry
, 0, sizeof(tbl_entry
));
1445 adjust
.gamut_adjust_type
= GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS
;
1447 dce_enable_fe_clock(dc
->hwseq
, pipe_ctx
->pipe_idx
, true);
1449 set_default_colors(pipe_ctx
);
1450 if (pipe_ctx
->stream
->public.csc_color_matrix
.enable_adjustment
1452 tbl_entry
.color_space
=
1453 pipe_ctx
->stream
->public.output_color_space
;
1455 for (i
= 0; i
< 12; i
++)
1456 tbl_entry
.regval
[i
] =
1457 pipe_ctx
->stream
->public.csc_color_matrix
.matrix
[i
];
1459 pipe_ctx
->opp
->funcs
->opp_set_csc_adjustment
1460 (pipe_ctx
->opp
, &tbl_entry
);
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] =
1467 public.gamut_remap_matrix
.matrix
[0];
1468 adjust
.temperature_matrix
[1] =
1470 public.gamut_remap_matrix
.matrix
[1];
1471 adjust
.temperature_matrix
[2] =
1473 public.gamut_remap_matrix
.matrix
[2];
1474 adjust
.temperature_matrix
[3] =
1476 public.gamut_remap_matrix
.matrix
[4];
1477 adjust
.temperature_matrix
[4] =
1479 public.gamut_remap_matrix
.matrix
[5];
1480 adjust
.temperature_matrix
[5] =
1482 public.gamut_remap_matrix
.matrix
[6];
1483 adjust
.temperature_matrix
[6] =
1485 public.gamut_remap_matrix
.matrix
[8];
1486 adjust
.temperature_matrix
[7] =
1488 public.gamut_remap_matrix
.matrix
[9];
1489 adjust
.temperature_matrix
[8] =
1491 public.gamut_remap_matrix
.matrix
[10];
1494 pipe_ctx
->xfm
->funcs
->transform_set_gamut_remap(pipe_ctx
->xfm
, &adjust
);
1496 pipe_ctx
->scl_data
.lb_params
.alpha_en
= pipe_ctx
->bottom_pipe
!= 0;
1497 program_scaler(dc
, pipe_ctx
);
1499 program_blender(dc
, pipe_ctx
);
1501 mi
->funcs
->mem_input_program_surface_config(
1503 surface
->public.format
,
1504 &surface
->public.tiling_info
,
1505 &surface
->public.plane_size
,
1506 surface
->public.rotation
,
1510 if (dc
->public.config
.gpu_vm_support
)
1511 mi
->funcs
->mem_input_program_pte_vm(
1513 surface
->public.format
,
1514 &surface
->public.tiling_info
,
1515 surface
->public.rotation
);
1518 static void update_plane_addr(const struct core_dc
*dc
,
1519 struct pipe_ctx
*pipe_ctx
)
1521 struct core_surface
*surface
= pipe_ctx
->surface
;
1523 if (surface
== NULL
)
1526 pipe_ctx
->mi
->funcs
->mem_input_program_surface_flip_and_addr(
1528 &surface
->public.address
,
1529 surface
->public.flip_immediate
);
1531 surface
->status
.requested_address
= surface
->public.address
;
1533 if (surface
->public.visible
)
1534 pipe_ctx
->tg
->funcs
->set_blank(pipe_ctx
->tg
, false);
1537 void dce110_update_pending_status(struct pipe_ctx
*pipe_ctx
)
1539 struct core_surface
*surface
= pipe_ctx
->surface
;
1541 if (surface
== NULL
)
1544 surface
->status
.is_flip_pending
=
1545 pipe_ctx
->mi
->funcs
->mem_input_is_flip_pending(
1548 if (surface
->status
.is_flip_pending
&& !surface
->public.visible
)
1549 pipe_ctx
->mi
->current_address
= pipe_ctx
->mi
->request_address
;
1551 surface
->status
.current_address
= pipe_ctx
->mi
->current_address
;
1554 void dce110_power_down(struct core_dc
*dc
)
1556 power_down_all_hw_blocks(dc
);
1557 disable_vga_and_power_gate_all_controllers(dc
);
1560 static bool wait_for_reset_trigger_to_occur(
1561 struct dc_context
*dc_ctx
,
1562 struct timing_generator
*tg
)
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;
1571 for (i
= 0; i
< frames_to_wait_on_triggered_reset
; i
++) {
1573 if (!tg
->funcs
->is_counter_moving(tg
)) {
1574 DC_ERROR("TG counter is not moving!\n");
1578 if (tg
->funcs
->did_triggered_reset_occur(tg
)) {
1580 /* usually occurs at i=1 */
1581 DC_SYNC_INFO("GSL: reset occurred at wait count: %d\n",
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
);
1592 DC_ERROR("GSL: Timeout on reset trigger!\n");
1597 /* Enable timing synchronization for a group of Timing Generators. */
1598 static void dce110_enable_timing_synchronization(
1602 struct pipe_ctx
*grouped_pipes
[])
1604 struct dc_context
*dc_ctx
= dc
->ctx
;
1605 struct dcp_gsl_params gsl_params
= { 0 };
1608 DC_SYNC_INFO("GSL: Setting-up...\n");
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
;
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
);
1620 /* Reset slave controllers on master VSync */
1621 DC_SYNC_INFO("GSL: enabling trigger-reset\n");
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
);
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
);
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
);
1645 DC_SYNC_INFO("GSL: Set-up complete.\n");
1648 static void init_hw(struct core_dc
*dc
)
1652 struct transform
*xfm
;
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
);
1659 dc
->hwss
.enable_display_power_gating(
1661 PIPE_GATING_CONTROL_INIT
);
1662 dc
->hwss
.enable_display_power_gating(
1664 PIPE_GATING_CONTROL_DISABLE
);
1665 dc
->hwss
.enable_display_pipe_clock_gating(
1670 dce_clock_gating_power_up(dc
->hwseq
, false);;
1671 /***************************************/
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
);
1682 for (i
= 0; i
< dc
->res_pool
->pipe_count
; i
++) {
1683 struct timing_generator
*tg
= dc
->res_pool
->timing_generators
[i
];
1685 tg
->funcs
->disable_vga(tg
);
1687 /* Blank controller using driver code instead of
1689 tg
->funcs
->set_blank(tg
, true);
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
);
1698 /* TODO: move this to apply_ctx_tohw some how?*/
1699 static void dce110_power_on_pipe_if_needed(
1701 struct pipe_ctx
*pipe_ctx
,
1702 struct validate_context
*context
)
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};
1708 if (!old_pipe_ctx
->stream
&& pipe_ctx
->stream
) {
1709 dc
->hwss
.enable_display_power_gating(
1712 dcb
, PIPE_GATING_CONTROL_DISABLE
);
1715 * This is for powering on underlay, so crtc does not
1716 * need to be enabled
1719 pipe_ctx
->tg
->funcs
->program_timing(pipe_ctx
->tg
,
1720 &pipe_ctx
->stream
->public.timing
,
1723 pipe_ctx
->tg
->funcs
->enable_advanced_request(
1726 &pipe_ctx
->stream
->public.timing
);
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
);
1734 /* TODO unhardcode*/
1735 color_space_to_black_color(dc
,
1736 COLOR_SPACE_YCBCR601
, &black_color
);
1737 pipe_ctx
->tg
->funcs
->set_blank_color(
1743 static void dce110_increase_watermarks_for_pipe(
1745 struct pipe_ctx
*pipe_ctx
,
1746 struct validate_context
*context
)
1748 if (did_watermarks_increase(pipe_ctx
, context
, dc
->current_context
))
1749 program_wm_for_pipe(dc
, pipe_ctx
, context
);
1752 static void dce110_set_bandwidth(struct core_dc
*dc
)
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
];
1759 if (!pipe_ctx
->stream
)
1762 program_wm_for_pipe(dc
, pipe_ctx
, dc
->current_context
);
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);
1770 static void dce110_program_front_end_for_pipe(
1771 struct core_dc
*dc
, struct pipe_ctx
*pipe_ctx
)
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
;
1780 memset(&tbl_entry
, 0, sizeof(tbl_entry
));
1782 if (dc
->current_context
)
1783 old_pipe
= &dc
->current_context
->res_ctx
.pipe_ctx
[pipe_ctx
->pipe_idx
];
1785 memset(&adjust
, 0, sizeof(adjust
));
1786 adjust
.gamut_adjust_type
= GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS
;
1788 dce_enable_fe_clock(dc
->hwseq
, pipe_ctx
->pipe_idx
, true);
1790 set_default_colors(pipe_ctx
);
1791 if (pipe_ctx
->stream
->public.csc_color_matrix
.enable_adjustment
1793 tbl_entry
.color_space
=
1794 pipe_ctx
->stream
->public.output_color_space
;
1796 for (i
= 0; i
< 12; i
++)
1797 tbl_entry
.regval
[i
] =
1798 pipe_ctx
->stream
->public.csc_color_matrix
.matrix
[i
];
1800 pipe_ctx
->opp
->funcs
->opp_set_csc_adjustment
1801 (pipe_ctx
->opp
, &tbl_entry
);
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] =
1808 public.gamut_remap_matrix
.matrix
[0];
1809 adjust
.temperature_matrix
[1] =
1811 public.gamut_remap_matrix
.matrix
[1];
1812 adjust
.temperature_matrix
[2] =
1814 public.gamut_remap_matrix
.matrix
[2];
1815 adjust
.temperature_matrix
[3] =
1817 public.gamut_remap_matrix
.matrix
[4];
1818 adjust
.temperature_matrix
[4] =
1820 public.gamut_remap_matrix
.matrix
[5];
1821 adjust
.temperature_matrix
[5] =
1823 public.gamut_remap_matrix
.matrix
[6];
1824 adjust
.temperature_matrix
[6] =
1826 public.gamut_remap_matrix
.matrix
[8];
1827 adjust
.temperature_matrix
[7] =
1829 public.gamut_remap_matrix
.matrix
[9];
1830 adjust
.temperature_matrix
[8] =
1832 public.gamut_remap_matrix
.matrix
[10];
1835 pipe_ctx
->xfm
->funcs
->transform_set_gamut_remap(pipe_ctx
->xfm
, &adjust
);
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
);
1843 mi
->funcs
->mem_input_program_surface_config(
1845 surface
->public.format
,
1846 &surface
->public.tiling_info
,
1847 &surface
->public.plane_size
,
1848 surface
->public.rotation
,
1852 if (dc
->public.config
.gpu_vm_support
)
1853 mi
->funcs
->mem_input_program_pte_vm(
1855 surface
->public.format
,
1856 &surface
->public.tiling_info
,
1857 surface
->public.rotation
);
1859 dm_logger_write(dc
->ctx
->logger
, LOG_SURFACE
,
1860 "Pipe:%d 0x%x: addr hi:0x%x, "
1863 " %d; dst: %d, %d, %d, %d;"
1864 "clip: %d, %d, %d, %d\n",
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
);
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",
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
);
1897 static void dce110_prepare_pipe_for_context(
1899 struct pipe_ctx
*pipe_ctx
,
1900 struct validate_context
*context
)
1902 dce110_power_on_pipe_if_needed(dc
, pipe_ctx
, context
);
1903 dc
->hwss
.increase_watermarks_for_pipe(dc
, pipe_ctx
, context
);
1906 static void dce110_apply_ctx_for_surface(
1908 struct core_surface
*surface
,
1909 struct validate_context
*context
)
1913 /* TODO remove when removing the surface reset workaroud*/
1917 for (i
= 0; i
< context
->res_ctx
.pool
->pipe_count
; i
++) {
1918 struct pipe_ctx
*pipe_ctx
= &context
->res_ctx
.pipe_ctx
[i
];
1920 if (pipe_ctx
->surface
!= surface
)
1923 dce110_program_front_end_for_pipe(dc
, pipe_ctx
);
1924 program_blender(dc
, pipe_ctx
);
1929 static void dce110_power_down_fe(struct core_dc
*dc
, struct pipe_ctx
*pipe
)
1933 for (i
= 0; i
< dc
->res_pool
->pipe_count
; i
++)
1934 if (&dc
->current_context
->res_ctx
.pipe_ctx
[i
] == pipe
)
1937 if (i
== dc
->res_pool
->pipe_count
)
1940 dc
->hwss
.enable_display_power_gating(
1941 dc
, i
, dc
->ctx
->dc_bios
, PIPE_GATING_CONTROL_ENABLE
);
1943 pipe
->xfm
->funcs
->transform_reset(pipe
->xfm
);
1944 memset(&pipe
->scl_data
, 0, sizeof(struct scaler_data
));
1947 static const struct hw_sequencer_funcs dce110_funcs
= {
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
,
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
,
1977 bool dce110_hw_sequencer_construct(struct core_dc
*dc
)
1979 dc
->hwss
= dce110_funcs
;