2 * Copyright 2016 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.
27 #include "dm_services.h"
28 #include "dm_helpers.h"
29 #include "core_types.h"
32 #include "dce/dce_hwseq.h"
34 #include "reg_helper.h"
38 #include "timing_generator.h"
43 #include "dc_dmub_srv.h"
44 #include "dcn31_hwseq.h"
45 #include "link_hwss.h"
46 #include "dpcd_defs.h"
47 #include "dce/dmub_outbox.h"
48 #include "dc_link_dp.h"
49 #include "inc/link_dpcd.h"
50 #include "dcn10/dcn10_hw_sequencer.h"
52 #define DC_LOGGER_INIT(logger)
63 #define FN(reg_name, field_name) \
64 hws->shifts->field_name, hws->masks->field_name
66 void dcn31_init_hw(struct dc
*dc
)
68 struct abm
**abms
= dc
->res_pool
->multiple_abms
;
69 struct dce_hwseq
*hws
= dc
->hwseq
;
70 struct dc_bios
*dcb
= dc
->ctx
->dc_bios
;
71 struct resource_pool
*res_pool
= dc
->res_pool
;
72 uint32_t backlight
= MAX_BACKLIGHT_LEVEL
;
76 if (dc
->clk_mgr
&& dc
->clk_mgr
->funcs
->init_clocks
)
77 dc
->clk_mgr
->funcs
->init_clocks(dc
->clk_mgr
);
79 // Initialize the dccg
80 if (res_pool
->dccg
->funcs
->dccg_init
)
81 res_pool
->dccg
->funcs
->dccg_init(res_pool
->dccg
);
83 if (IS_FPGA_MAXIMUS_DC(dc
->ctx
->dce_environment
)) {
85 REG_WRITE(REFCLK_CNTL
, 0);
86 REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL
, DCHUBBUB_GLOBAL_TIMER_ENABLE
, 1);
87 REG_WRITE(DIO_MEM_PWR_CTRL
, 0);
89 if (!dc
->debug
.disable_clock_gate
) {
90 /* enable all DCN clock gating */
91 REG_WRITE(DCCG_GATE_DISABLE_CNTL
, 0);
93 REG_WRITE(DCCG_GATE_DISABLE_CNTL2
, 0);
95 REG_UPDATE(DCFCLK_CNTL
, DCFCLK_GATE_DIS
, 0);
98 //Enable ability to power gate / don't force power on permanently
99 if (hws
->funcs
.enable_power_gating_plane
)
100 hws
->funcs
.enable_power_gating_plane(hws
, true);
105 if (!dcb
->funcs
->is_accelerated_mode(dcb
)) {
106 hws
->funcs
.bios_golden_init(dc
);
107 hws
->funcs
.disable_vga(dc
->hwseq
);
110 if (dc
->debug
.enable_mem_low_power
.bits
.dmcu
) {
111 // Force ERAM to shutdown if DMCU is not enabled
112 if (dc
->debug
.disable_dmcu
|| dc
->config
.disable_dmcu
) {
113 REG_UPDATE(DMU_MEM_PWR_CNTL
, DMCU_ERAM_MEM_PWR_FORCE
, 3);
117 // Set default OPTC memory power states
118 if (dc
->debug
.enable_mem_low_power
.bits
.optc
) {
119 // Shutdown when unassigned and light sleep in VBLANK
120 REG_SET_2(ODM_MEM_PWR_CTRL3
, 0, ODM_MEM_UNASSIGNED_PWR_MODE
, 3, ODM_MEM_VBLANK_PWR_MODE
, 1);
123 if (dc
->debug
.enable_mem_low_power
.bits
.vga
) {
124 // Power down VGA memory
125 REG_UPDATE(MMHUBBUB_MEM_PWR_CNTL
, VGA_MEM_PWR_FORCE
, 1);
128 if (dc
->ctx
->dc_bios
->fw_info_valid
) {
129 res_pool
->ref_clocks
.xtalin_clock_inKhz
=
130 dc
->ctx
->dc_bios
->fw_info
.pll_info
.crystal_frequency
;
132 if (!IS_FPGA_MAXIMUS_DC(dc
->ctx
->dce_environment
)) {
133 if (res_pool
->dccg
&& res_pool
->hubbub
) {
135 (res_pool
->dccg
->funcs
->get_dccg_ref_freq
)(res_pool
->dccg
,
136 dc
->ctx
->dc_bios
->fw_info
.pll_info
.crystal_frequency
,
137 &res_pool
->ref_clocks
.dccg_ref_clock_inKhz
);
139 (res_pool
->hubbub
->funcs
->get_dchub_ref_freq
)(res_pool
->hubbub
,
140 res_pool
->ref_clocks
.dccg_ref_clock_inKhz
,
141 &res_pool
->ref_clocks
.dchub_ref_clock_inKhz
);
143 // Not all ASICs have DCCG sw component
144 res_pool
->ref_clocks
.dccg_ref_clock_inKhz
=
145 res_pool
->ref_clocks
.xtalin_clock_inKhz
;
146 res_pool
->ref_clocks
.dchub_ref_clock_inKhz
=
147 res_pool
->ref_clocks
.xtalin_clock_inKhz
;
151 ASSERT_CRITICAL(false);
153 for (i
= 0; i
< dc
->link_count
; i
++) {
154 /* Power up AND update implementation according to the
155 * required signal (which may be different from the
156 * default signal on connector).
158 struct dc_link
*link
= dc
->links
[i
];
160 link
->link_enc
->funcs
->hw_init(link
->link_enc
);
162 /* Check for enabled DIG to identify enabled display */
163 if (link
->link_enc
->funcs
->is_dig_enabled
&&
164 link
->link_enc
->funcs
->is_dig_enabled(link
->link_enc
))
165 link
->link_status
.link_active
= true;
168 /* Power gate DSCs */
169 for (i
= 0; i
< res_pool
->res_cap
->num_dsc
; i
++)
170 if (hws
->funcs
.dsc_pg_control
!= NULL
)
171 hws
->funcs
.dsc_pg_control(hws
, res_pool
->dscs
[i
]->inst
, false);
173 /* we want to turn off all dp displays before doing detection */
174 if (dc
->config
.power_down_display_on_boot
) {
175 uint8_t dpcd_power_state
= '\0';
176 enum dc_status status
= DC_ERROR_UNEXPECTED
;
178 for (i
= 0; i
< dc
->link_count
; i
++) {
179 if (dc
->links
[i
]->connector_signal
!= SIGNAL_TYPE_DISPLAY_PORT
)
182 /* if any of the displays are lit up turn them off */
183 status
= core_link_read_dpcd(dc
->links
[i
], DP_SET_POWER
,
184 &dpcd_power_state
, sizeof(dpcd_power_state
));
185 if (status
== DC_OK
&& dpcd_power_state
== DP_POWER_STATE_D0
) {
186 /* blank dp stream before power off receiver*/
187 if (dc
->links
[i
]->link_enc
->funcs
->get_dig_frontend
) {
190 fe
= dc
->links
[i
]->link_enc
->funcs
->get_dig_frontend(
191 dc
->links
[i
]->link_enc
);
192 if (fe
== ENGINE_ID_UNKNOWN
)
195 for (j
= 0; j
< dc
->res_pool
->stream_enc_count
; j
++) {
196 if (fe
== dc
->res_pool
->stream_enc
[j
]->id
) {
197 dc
->res_pool
->stream_enc
[j
]->funcs
->dp_blank(
198 dc
->res_pool
->stream_enc
[j
]);
203 dp_receiver_power_ctrl(dc
->links
[i
], false);
208 /* If taking control over from VBIOS, we may want to optimize our first
209 * mode set, so we need to skip powering down pipes until we know which
210 * pipes we want to use.
211 * Otherwise, if taking control is not possible, we need to power
214 if (dcb
->funcs
->is_accelerated_mode(dcb
) || dc
->config
.power_down_display_on_boot
) {
215 hws
->funcs
.init_pipes(dc
, dc
->current_state
);
216 if (dc
->res_pool
->hubbub
->funcs
->allow_self_refresh_control
)
217 dc
->res_pool
->hubbub
->funcs
->allow_self_refresh_control(dc
->res_pool
->hubbub
,
218 !dc
->res_pool
->hubbub
->ctx
->dc
->debug
.disable_stutter
);
221 /* In headless boot cases, DIG may be turned
222 * on which causes HW/SW discrepancies.
223 * To avoid this, power down hardware on boot
224 * if DIG is turned on and seamless boot not enabled
226 if (dc
->config
.power_down_display_on_boot
) {
227 struct dc_link
*edp_links
[MAX_NUM_EDP
];
228 struct dc_link
*edp_link
;
229 bool power_down
= false;
231 get_edp_links(dc
, edp_links
, &edp_num
);
233 for (i
= 0; i
< edp_num
; i
++) {
234 edp_link
= edp_links
[i
];
235 if (edp_link
->link_enc
->funcs
->is_dig_enabled
&&
236 edp_link
->link_enc
->funcs
->is_dig_enabled(edp_link
->link_enc
) &&
237 dc
->hwss
.edp_backlight_control
&&
238 dc
->hwss
.power_down
&&
239 dc
->hwss
.edp_power_control
) {
240 dc
->hwss
.edp_backlight_control(edp_link
, false);
241 dc
->hwss
.power_down(dc
);
242 dc
->hwss
.edp_power_control(edp_link
, false);
248 for (i
= 0; i
< dc
->link_count
; i
++) {
249 struct dc_link
*link
= dc
->links
[i
];
251 if (link
->link_enc
->funcs
->is_dig_enabled
&&
252 link
->link_enc
->funcs
->is_dig_enabled(link
->link_enc
) &&
253 dc
->hwss
.power_down
) {
254 dc
->hwss
.power_down(dc
);
262 for (i
= 0; i
< res_pool
->audio_count
; i
++) {
263 struct audio
*audio
= res_pool
->audios
[i
];
265 audio
->funcs
->hw_init(audio
);
268 for (i
= 0; i
< dc
->link_count
; i
++) {
269 struct dc_link
*link
= dc
->links
[i
];
271 if (link
->panel_cntl
)
272 backlight
= link
->panel_cntl
->funcs
->hw_init(link
->panel_cntl
);
275 for (i
= 0; i
< dc
->res_pool
->pipe_count
; i
++) {
277 abms
[i
]->funcs
->abm_init(abms
[i
], backlight
);
280 /* power AFMT HDMI memory TODO: may move to dis/en output save power*/
281 REG_WRITE(DIO_MEM_PWR_CTRL
, 0);
283 if (!dc
->debug
.disable_clock_gate
) {
284 /* enable all DCN clock gating */
285 REG_WRITE(DCCG_GATE_DISABLE_CNTL
, 0);
287 REG_WRITE(DCCG_GATE_DISABLE_CNTL2
, 0);
289 REG_UPDATE(DCFCLK_CNTL
, DCFCLK_GATE_DIS
, 0);
291 if (hws
->funcs
.enable_power_gating_plane
)
292 hws
->funcs
.enable_power_gating_plane(dc
->hwseq
, true);
294 if (!dcb
->funcs
->is_accelerated_mode(dcb
) && dc
->res_pool
->hubbub
->funcs
->init_watermarks
)
295 dc
->res_pool
->hubbub
->funcs
->init_watermarks(dc
->res_pool
->hubbub
);
297 if (dc
->clk_mgr
->funcs
->notify_wm_ranges
)
298 dc
->clk_mgr
->funcs
->notify_wm_ranges(dc
->clk_mgr
);
300 if (dc
->clk_mgr
->funcs
->set_hard_max_memclk
)
301 dc
->clk_mgr
->funcs
->set_hard_max_memclk(dc
->clk_mgr
);
303 if (dc
->res_pool
->hubbub
->funcs
->force_pstate_change_control
)
304 dc
->res_pool
->hubbub
->funcs
->force_pstate_change_control(
305 dc
->res_pool
->hubbub
, false, false);
306 if (dc
->res_pool
->hubbub
->funcs
->init_crb
)
307 dc
->res_pool
->hubbub
->funcs
->init_crb(dc
->res_pool
->hubbub
);
310 void dcn31_dsc_pg_control(
311 struct dce_hwseq
*hws
,
312 unsigned int dsc_inst
,
315 uint32_t power_gate
= power_on
? 0 : 1;
316 uint32_t pwr_status
= power_on
? 0 : 2;
317 uint32_t org_ip_request_cntl
= 0;
319 if (hws
->ctx
->dc
->debug
.disable_dsc_power_gate
)
322 REG_GET(DC_IP_REQUEST_CNTL
, IP_REQUEST_EN
, &org_ip_request_cntl
);
323 if (org_ip_request_cntl
== 0)
324 REG_SET(DC_IP_REQUEST_CNTL
, 0, IP_REQUEST_EN
, 1);
328 REG_UPDATE(DOMAIN16_PG_CONFIG
,
329 DOMAIN_POWER_GATE
, power_gate
);
331 REG_WAIT(DOMAIN16_PG_STATUS
,
332 DOMAIN_PGFSM_PWR_STATUS
, pwr_status
,
336 REG_UPDATE(DOMAIN17_PG_CONFIG
,
337 DOMAIN_POWER_GATE
, power_gate
);
339 REG_WAIT(DOMAIN17_PG_STATUS
,
340 DOMAIN_PGFSM_PWR_STATUS
, pwr_status
,
344 REG_UPDATE(DOMAIN18_PG_CONFIG
,
345 DOMAIN_POWER_GATE
, power_gate
);
347 REG_WAIT(DOMAIN18_PG_STATUS
,
348 DOMAIN_PGFSM_PWR_STATUS
, pwr_status
,
356 if (org_ip_request_cntl
== 0)
357 REG_SET(DC_IP_REQUEST_CNTL
, 0, IP_REQUEST_EN
, 0);
361 void dcn31_enable_power_gating_plane(
362 struct dce_hwseq
*hws
,
365 bool force_on
= true; /* disable power gating */
370 /* DCHUBP0/1/2/3/4/5 */
371 REG_UPDATE(DOMAIN0_PG_CONFIG
, DOMAIN_POWER_FORCEON
, force_on
);
372 REG_UPDATE(DOMAIN2_PG_CONFIG
, DOMAIN_POWER_FORCEON
, force_on
);
375 REG_UPDATE(DOMAIN1_PG_CONFIG
, DOMAIN_POWER_FORCEON
, force_on
);
376 REG_UPDATE(DOMAIN3_PG_CONFIG
, DOMAIN_POWER_FORCEON
, force_on
);
379 REG_UPDATE(DOMAIN16_PG_CONFIG
, DOMAIN_POWER_FORCEON
, force_on
);
380 REG_UPDATE(DOMAIN17_PG_CONFIG
, DOMAIN_POWER_FORCEON
, force_on
);
381 REG_UPDATE(DOMAIN18_PG_CONFIG
, DOMAIN_POWER_FORCEON
, force_on
);
384 void dcn31_update_info_frame(struct pipe_ctx
*pipe_ctx
)
389 ASSERT(pipe_ctx
->stream
);
391 if (pipe_ctx
->stream_res
.stream_enc
== NULL
)
392 return; /* this is not root pipe */
394 is_hdmi_tmds
= dc_is_hdmi_tmds_signal(pipe_ctx
->stream
->signal
);
395 is_dp
= dc_is_dp_signal(pipe_ctx
->stream
->signal
);
397 if (!is_hdmi_tmds
&& !is_dp
)
401 pipe_ctx
->stream_res
.stream_enc
->funcs
->update_hdmi_info_packets(
402 pipe_ctx
->stream_res
.stream_enc
,
403 &pipe_ctx
->stream_res
.encoder_info_frame
);
405 pipe_ctx
->stream_res
.stream_enc
->funcs
->update_dp_info_packets(
406 pipe_ctx
->stream_res
.stream_enc
,
407 &pipe_ctx
->stream_res
.encoder_info_frame
);
410 void dcn31_z10_save_init(struct dc
*dc
)
412 union dmub_rb_cmd cmd
;
414 memset(&cmd
, 0, sizeof(cmd
));
415 cmd
.dcn_restore
.header
.type
= DMUB_CMD__IDLE_OPT
;
416 cmd
.dcn_restore
.header
.sub_type
= DMUB_CMD__IDLE_OPT_DCN_SAVE_INIT
;
418 dc_dmub_srv_cmd_queue(dc
->ctx
->dmub_srv
, &cmd
);
419 dc_dmub_srv_cmd_execute(dc
->ctx
->dmub_srv
);
420 dc_dmub_srv_wait_idle(dc
->ctx
->dmub_srv
);
423 void dcn31_z10_restore(struct dc
*dc
)
425 union dmub_rb_cmd cmd
;
428 * DMUB notifies whether restore is required.
429 * Optimization to avoid sending commands when not required.
431 if (!dc_dmub_srv_is_restore_required(dc
->ctx
->dmub_srv
))
434 memset(&cmd
, 0, sizeof(cmd
));
435 cmd
.dcn_restore
.header
.type
= DMUB_CMD__IDLE_OPT
;
436 cmd
.dcn_restore
.header
.sub_type
= DMUB_CMD__IDLE_OPT_DCN_RESTORE
;
438 dc_dmub_srv_cmd_queue(dc
->ctx
->dmub_srv
, &cmd
);
439 dc_dmub_srv_cmd_execute(dc
->ctx
->dmub_srv
);
440 dc_dmub_srv_wait_idle(dc
->ctx
->dmub_srv
);
443 void dcn31_hubp_pg_control(struct dce_hwseq
*hws
, unsigned int hubp_inst
, bool power_on
)
445 uint32_t power_gate
= power_on
? 0 : 1;
446 uint32_t pwr_status
= power_on
? 0 : 2;
448 if (hws
->ctx
->dc
->debug
.disable_hubp_power_gate
)
451 if (REG(DOMAIN0_PG_CONFIG
) == 0)
456 REG_SET(DOMAIN0_PG_CONFIG
, 0, DOMAIN_POWER_GATE
, power_gate
);
457 REG_WAIT(DOMAIN0_PG_STATUS
, DOMAIN_PGFSM_PWR_STATUS
, pwr_status
, 1, 1000);
460 REG_SET(DOMAIN1_PG_CONFIG
, 0, DOMAIN_POWER_GATE
, power_gate
);
461 REG_WAIT(DOMAIN1_PG_STATUS
, DOMAIN_PGFSM_PWR_STATUS
, pwr_status
, 1, 1000);
464 REG_SET(DOMAIN2_PG_CONFIG
, 0, DOMAIN_POWER_GATE
, power_gate
);
465 REG_WAIT(DOMAIN2_PG_STATUS
, DOMAIN_PGFSM_PWR_STATUS
, pwr_status
, 1, 1000);
468 REG_SET(DOMAIN3_PG_CONFIG
, 0, DOMAIN_POWER_GATE
, power_gate
);
469 REG_WAIT(DOMAIN3_PG_STATUS
, DOMAIN_PGFSM_PWR_STATUS
, pwr_status
, 1, 1000);
477 int dcn31_init_sys_ctx(struct dce_hwseq
*hws
, struct dc
*dc
, struct dc_phy_addr_space_config
*pa_config
)
479 struct dcn_hubbub_phys_addr_config config
;
481 config
.system_aperture
.fb_top
= pa_config
->system_aperture
.fb_top
;
482 config
.system_aperture
.fb_offset
= pa_config
->system_aperture
.fb_offset
;
483 config
.system_aperture
.fb_base
= pa_config
->system_aperture
.fb_base
;
484 config
.system_aperture
.agp_top
= pa_config
->system_aperture
.agp_top
;
485 config
.system_aperture
.agp_bot
= pa_config
->system_aperture
.agp_bot
;
486 config
.system_aperture
.agp_base
= pa_config
->system_aperture
.agp_base
;
487 config
.gart_config
.page_table_start_addr
= pa_config
->gart_config
.page_table_start_addr
;
488 config
.gart_config
.page_table_end_addr
= pa_config
->gart_config
.page_table_end_addr
;
490 if (pa_config
->gart_config
.base_addr_is_mc_addr
) {
491 /* Convert from MC address to offset into FB */
492 config
.gart_config
.page_table_base_addr
= pa_config
->gart_config
.page_table_base_addr
-
493 pa_config
->system_aperture
.fb_base
+
494 pa_config
->system_aperture
.fb_offset
;
496 config
.gart_config
.page_table_base_addr
= pa_config
->gart_config
.page_table_base_addr
;
498 return dc
->res_pool
->hubbub
->funcs
->init_dchub_sys_ctx(dc
->res_pool
->hubbub
, &config
);
501 static void dcn31_reset_back_end_for_pipe(
503 struct pipe_ctx
*pipe_ctx
,
504 struct dc_state
*context
)
506 struct dc_link
*link
;
508 DC_LOGGER_INIT(dc
->ctx
->logger
);
509 if (pipe_ctx
->stream_res
.stream_enc
== NULL
) {
510 pipe_ctx
->stream
= NULL
;
513 ASSERT(!pipe_ctx
->top_pipe
);
515 dc
->hwss
.set_abm_immediate_disable(pipe_ctx
);
517 pipe_ctx
->stream_res
.tg
->funcs
->set_dsc_config(
518 pipe_ctx
->stream_res
.tg
,
519 OPTC_DSC_DISABLED
, 0, 0);
520 pipe_ctx
->stream_res
.tg
->funcs
->disable_crtc(pipe_ctx
->stream_res
.tg
);
522 pipe_ctx
->stream_res
.tg
->funcs
->enable_optc_clock(pipe_ctx
->stream_res
.tg
, false);
523 if (pipe_ctx
->stream_res
.tg
->funcs
->set_odm_bypass
)
524 pipe_ctx
->stream_res
.tg
->funcs
->set_odm_bypass(
525 pipe_ctx
->stream_res
.tg
, &pipe_ctx
->stream
->timing
);
527 if (pipe_ctx
->stream_res
.tg
->funcs
->set_drr
)
528 pipe_ctx
->stream_res
.tg
->funcs
->set_drr(
529 pipe_ctx
->stream_res
.tg
, NULL
);
531 if (!IS_FPGA_MAXIMUS_DC(dc
->ctx
->dce_environment
)) {
532 link
= pipe_ctx
->stream
->link
;
533 /* DPMS may already disable or */
534 /* dpms_off status is incorrect due to fastboot
535 * feature. When system resume from S4 with second
536 * screen only, the dpms_off would be true but
537 * VBIOS lit up eDP, so check link status too.
539 if (!pipe_ctx
->stream
->dpms_off
|| link
->link_status
.link_active
)
540 core_link_disable_stream(pipe_ctx
);
541 else if (pipe_ctx
->stream_res
.audio
)
542 dc
->hwss
.disable_audio_stream(pipe_ctx
);
544 /* free acquired resources */
545 if (pipe_ctx
->stream_res
.audio
) {
546 /*disable az_endpoint*/
547 pipe_ctx
->stream_res
.audio
->funcs
->az_disable(pipe_ctx
->stream_res
.audio
);
550 if (dc
->caps
.dynamic_audio
== true) {
551 /*we have to dynamic arbitrate the audio endpoints*/
552 /*we free the resource, need reset is_audio_acquired*/
553 update_audio_usage(&dc
->current_state
->res_ctx
, dc
->res_pool
,
554 pipe_ctx
->stream_res
.audio
, false);
555 pipe_ctx
->stream_res
.audio
= NULL
;
558 } else if (pipe_ctx
->stream_res
.dsc
) {
559 dp_set_dsc_enable(pipe_ctx
, false);
562 pipe_ctx
->stream
= NULL
;
563 DC_LOG_DEBUG("Reset back end for pipe %d, tg:%d\n",
564 pipe_ctx
->pipe_idx
, pipe_ctx
->stream_res
.tg
->inst
);
567 void dcn31_reset_hw_ctx_wrap(
569 struct dc_state
*context
)
572 struct dce_hwseq
*hws
= dc
->hwseq
;
575 for (i
= dc
->res_pool
->pipe_count
- 1; i
>= 0 ; i
--) {
576 struct pipe_ctx
*pipe_ctx_old
=
577 &dc
->current_state
->res_ctx
.pipe_ctx
[i
];
578 struct pipe_ctx
*pipe_ctx
= &context
->res_ctx
.pipe_ctx
[i
];
580 if (!pipe_ctx_old
->stream
)
583 if (pipe_ctx_old
->top_pipe
|| pipe_ctx_old
->prev_odm_pipe
)
586 if (!pipe_ctx
->stream
||
587 pipe_need_reprogram(pipe_ctx_old
, pipe_ctx
)) {
588 struct clock_source
*old_clk
= pipe_ctx_old
->clock_source
;
590 dcn31_reset_back_end_for_pipe(dc
, pipe_ctx_old
, dc
->current_state
);
591 if (hws
->funcs
.enable_stream_gating
)
592 hws
->funcs
.enable_stream_gating(dc
, pipe_ctx
);
594 old_clk
->funcs
->cs_power_down(old_clk
);
599 bool dcn31_is_abm_supported(struct dc
*dc
,
600 struct dc_state
*context
, struct dc_stream_state
*stream
)
604 for (i
= 0; i
< dc
->res_pool
->pipe_count
; i
++) {
605 struct pipe_ctx
*pipe_ctx
= &context
->res_ctx
.pipe_ctx
[i
];
607 if (pipe_ctx
->stream
== stream
&&
608 (pipe_ctx
->prev_odm_pipe
== NULL
&& pipe_ctx
->next_odm_pipe
== NULL
))