aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3555-drm-amd-display-Make-init_hw-and-init_pipes-generic-.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3555-drm-amd-display-Make-init_hw-and-init_pipes-generic-.patch')
-rw-r--r--meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3555-drm-amd-display-Make-init_hw-and-init_pipes-generic-.patch1086
1 files changed, 1086 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3555-drm-amd-display-Make-init_hw-and-init_pipes-generic-.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3555-drm-amd-display-Make-init_hw-and-init_pipes-generic-.patch
new file mode 100644
index 00000000..ef02eddb
--- /dev/null
+++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3555-drm-amd-display-Make-init_hw-and-init_pipes-generic-.patch
@@ -0,0 +1,1086 @@
+From b794722e64e6d98fce6b19921a2da22d2326233e Mon Sep 17 00:00:00 2001
+From: Martin Leung <martin.leung@amd.com>
+Date: Tue, 9 Jul 2019 15:15:17 -0400
+Subject: [PATCH 3555/4256] drm/amd/display: Make init_hw and init_pipes
+ generic for seamless boot
+
+[Why]
+For seamless boot the init_hw sequence must be split into
+actual hardware vs pipes, in order to defer pipe initialization to set mode
+and skip of pipe-destructive sequences
+
+[How]
+made dcn10_init_hw and dcn10_init_pipes generic for future dcns to inherit
+deleted dcn20 specific versions. This is part 1 of a 2 partimplementation
+of seamless boot
+
+Change-Id: I66fe630d9742a3fcfa1ce02c49da6411f0e95ca1
+Signed-off-by: Martin Leung <martin.leung@amd.com>
+Reviewed-by: Jun Lei <Jun.Lei@amd.com>
+Acked-by: Leo Li <sunpeng.li@amd.com>
+---
+ .../display/dc/dce110/dce110_hw_sequencer.c | 12 +-
+ .../display/dc/dce110/dce110_hw_sequencer.h | 6 +-
+ .../drm/amd/display/dc/dcn10/dcn10_hubbub.c | 4 +-
+ .../drm/amd/display/dc/dcn10/dcn10_hubbub.h | 2 +-
+ .../amd/display/dc/dcn10/dcn10_hw_sequencer.c | 182 ++++++---
+ .../drm/amd/display/dc/dcn20/dcn20_hubbub.c | 2 +-
+ .../drm/amd/display/dc/dcn20/dcn20_hwseq.c | 383 +++++++-----------
+ .../gpu/drm/amd/display/dc/inc/hw/dchubbub.h | 4 +
+ .../gpu/drm/amd/display/dc/inc/hw_sequencer.h | 32 ++
+ 9 files changed, 314 insertions(+), 313 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
+index 919647166bce..5a046e5bc756 100644
+--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
++++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
+@@ -728,7 +728,7 @@ static enum bp_result link_transmitter_control(
+ * @brief
+ * eDP only.
+ */
+-void hwss_edp_wait_for_hpd_ready(
++void dce110_edp_wait_for_hpd_ready(
+ struct dc_link *link,
+ bool power_up)
+ {
+@@ -796,7 +796,7 @@ void hwss_edp_wait_for_hpd_ready(
+ }
+ }
+
+-void hwss_edp_power_control(
++void dce110_edp_power_control(
+ struct dc_link *link,
+ bool power_up)
+ {
+@@ -878,7 +878,7 @@ void hwss_edp_power_control(
+ * @brief
+ * eDP only. Control the backlight of the eDP panel
+ */
+-void hwss_edp_backlight_control(
++void dce110_edp_backlight_control(
+ struct dc_link *link,
+ bool enable)
+ {
+@@ -2755,9 +2755,9 @@ static const struct hw_sequencer_funcs dce110_funcs = {
+ .setup_stereo = NULL,
+ .set_avmute = dce110_set_avmute,
+ .wait_for_mpcc_disconnect = dce110_wait_for_mpcc_disconnect,
+- .edp_backlight_control = hwss_edp_backlight_control,
+- .edp_power_control = hwss_edp_power_control,
+- .edp_wait_for_hpd_ready = hwss_edp_wait_for_hpd_ready,
++ .edp_backlight_control = dce110_edp_backlight_control,
++ .edp_power_control = dce110_edp_power_control,
++ .edp_wait_for_hpd_ready = dce110_edp_wait_for_hpd_ready,
+ .set_cursor_position = dce110_set_cursor_position,
+ .set_cursor_attribute = dce110_set_cursor_attribute
+ };
+diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h
+index cd3e36d52a52..668feb0d169d 100644
+--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h
++++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h
+@@ -73,15 +73,15 @@ void dce110_optimize_bandwidth(
+
+ void dp_receiver_power_ctrl(struct dc_link *link, bool on);
+
+-void hwss_edp_power_control(
++void dce110_edp_power_control(
+ struct dc_link *link,
+ bool power_up);
+
+-void hwss_edp_backlight_control(
++void dce110_edp_backlight_control(
+ struct dc_link *link,
+ bool enable);
+
+-void hwss_edp_wait_for_hpd_ready(
++void dce110_edp_wait_for_hpd_ready(
+ struct dc_link *link,
+ bool power_up);
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c
+index 0ab391446d3d..90c30a21bd09 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c
+@@ -102,7 +102,7 @@ void hubbub1_allow_self_refresh_control(struct hubbub *hubbub, bool allow)
+ DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, !allow);
+ }
+
+-bool hububu1_is_allow_self_refresh_enabled(struct hubbub *hubbub)
++bool hubbub1_is_allow_self_refresh_enabled(struct hubbub *hubbub)
+ {
+ struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub);
+ uint32_t enable = 0;
+@@ -943,6 +943,8 @@ static const struct hubbub_funcs hubbub1_funcs = {
+ .get_dcc_compression_cap = hubbub1_get_dcc_compression_cap,
+ .wm_read_state = hubbub1_wm_read_state,
+ .program_watermarks = hubbub1_program_watermarks,
++ .is_allow_self_refresh_enabled = hubbub1_is_allow_self_refresh_enabled,
++ .allow_self_refresh_control = hubbub1_allow_self_refresh_control,
+ };
+
+ void hubbub1_construct(struct hubbub *hubbub,
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h
+index 7c2559c9ae23..70e5d84fc69a 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h
++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h
+@@ -247,7 +247,7 @@ void hubbub1_program_watermarks(
+
+ void hubbub1_allow_self_refresh_control(struct hubbub *hubbub, bool allow);
+
+-bool hububu1_is_allow_self_refresh_enabled(struct hubbub *hubub);
++bool hubbub1_is_allow_self_refresh_enabled(struct hubbub *hubub);
+
+ void hubbub1_toggle_watermark_change_req(
+ struct hubbub *hubbub);
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
+index 5390f8d84b2a..1835157b9fad 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
+@@ -437,7 +437,7 @@ bool dcn10_did_underflow_occur(struct dc *dc, struct pipe_ctx *pipe_ctx)
+ return false;
+ }
+
+-static void enable_power_gating_plane(
++static void dcn10_enable_power_gating_plane(
+ struct dce_hwseq *hws,
+ bool enable)
+ {
+@@ -459,7 +459,7 @@ static void enable_power_gating_plane(
+ REG_UPDATE(DOMAIN7_PG_CONFIG, DOMAIN7_POWER_FORCEON, force_on);
+ }
+
+-static void disable_vga(
++static void dcn10_disable_vga(
+ struct dce_hwseq *hws)
+ {
+ unsigned int in_vga1_mode = 0;
+@@ -492,7 +492,7 @@ static void disable_vga(
+ REG_UPDATE(VGA_TEST_CONTROL, VGA_TEST_RENDER_START, 1);
+ }
+
+-static void dpp_pg_control(
++static void dcn10_dpp_pg_control(
+ struct dce_hwseq *hws,
+ unsigned int dpp_inst,
+ bool power_on)
+@@ -544,7 +544,7 @@ static void dpp_pg_control(
+ }
+ }
+
+-static void hubp_pg_control(
++static void dcn10_hubp_pg_control(
+ struct dce_hwseq *hws,
+ unsigned int hubp_inst,
+ bool power_on)
+@@ -604,8 +604,8 @@ static void power_on_plane(
+ if (REG(DC_IP_REQUEST_CNTL)) {
+ REG_SET(DC_IP_REQUEST_CNTL, 0,
+ IP_REQUEST_EN, 1);
+- dpp_pg_control(hws, plane_id, true);
+- hubp_pg_control(hws, plane_id, true);
++ hws->ctx->dc->hwss.dpp_pg_control(hws, plane_id, true);
++ hws->ctx->dc->hwss.hubp_pg_control(hws, plane_id, true);
+ REG_SET(DC_IP_REQUEST_CNTL, 0,
+ IP_REQUEST_EN, 0);
+ DC_LOG_DEBUG(
+@@ -626,7 +626,7 @@ static void undo_DEGVIDCN10_253_wa(struct dc *dc)
+ REG_SET(DC_IP_REQUEST_CNTL, 0,
+ IP_REQUEST_EN, 1);
+
+- hubp_pg_control(hws, 0, false);
++ dc->hwss.hubp_pg_control(hws, 0, false);
+ REG_SET(DC_IP_REQUEST_CNTL, 0,
+ IP_REQUEST_EN, 0);
+
+@@ -655,7 +655,7 @@ static void apply_DEGVIDCN10_253_wa(struct dc *dc)
+ REG_SET(DC_IP_REQUEST_CNTL, 0,
+ IP_REQUEST_EN, 1);
+
+- hubp_pg_control(hws, 0, true);
++ dc->hwss.hubp_pg_control(hws, 0, true);
+ REG_SET(DC_IP_REQUEST_CNTL, 0,
+ IP_REQUEST_EN, 0);
+
+@@ -663,10 +663,23 @@ static void apply_DEGVIDCN10_253_wa(struct dc *dc)
+ hws->wa_state.DEGVIDCN10_253_applied = true;
+ }
+
+-static void bios_golden_init(struct dc *dc)
++static void dcn10_bios_golden_init(struct dc *dc)
+ {
+ struct dc_bios *bp = dc->ctx->dc_bios;
+ int i;
++ bool allow_self_fresh_force_enable = true;
++
++ if (dc->res_pool->hubbub->funcs->is_allow_self_refresh_enabled)
++ allow_self_fresh_force_enable =
++ dc->res_pool->hubbub->funcs->is_allow_self_refresh_enabled(dc->res_pool->hubbub);
++
++
++ /* WA for making DF sleep when idle after resume from S0i3.
++ * DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE is set to 1 by
++ * command table, if DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE = 0
++ * before calling command table and it changed to 1 after,
++ * it should be set back to 0.
++ */
+
+ /* initialize dcn global */
+ bp->funcs->enable_disp_power_gating(bp,
+@@ -677,6 +690,12 @@ static void bios_golden_init(struct dc *dc)
+ bp->funcs->enable_disp_power_gating(bp,
+ CONTROLLER_ID_D0 + i, ASIC_PIPE_DISABLE);
+ }
++
++ if (dc->res_pool->hubbub->funcs->allow_self_refresh_control)
++ if (allow_self_fresh_force_enable == false &&
++ dc->res_pool->hubbub->funcs->is_allow_self_refresh_enabled(dc->res_pool->hubbub))
++ dc->res_pool->hubbub->funcs->allow_self_refresh_control(dc->res_pool->hubbub, true);
++
+ }
+
+ static void false_optc_underflow_wa(
+@@ -971,7 +990,7 @@ void hwss1_plane_atomic_disconnect(struct dc *dc, struct pipe_ctx *pipe_ctx)
+ dcn10_verify_allow_pstate_change_high(dc);
+ }
+
+-static void plane_atomic_power_down(struct dc *dc,
++static void dcn10_plane_atomic_power_down(struct dc *dc,
+ struct dpp *dpp,
+ struct hubp *hubp)
+ {
+@@ -981,8 +1000,8 @@ static void plane_atomic_power_down(struct dc *dc,
+ if (REG(DC_IP_REQUEST_CNTL)) {
+ REG_SET(DC_IP_REQUEST_CNTL, 0,
+ IP_REQUEST_EN, 1);
+- dpp_pg_control(hws, dpp->inst, false);
+- hubp_pg_control(hws, hubp->inst, false);
++ dc->hwss.dpp_pg_control(hws, dpp->inst, false);
++ dc->hwss.hubp_pg_control(hws, hubp->inst, false);
+ dpp->funcs->dpp_reset(dpp);
+ REG_SET(DC_IP_REQUEST_CNTL, 0,
+ IP_REQUEST_EN, 0);
+@@ -994,7 +1013,7 @@ static void plane_atomic_power_down(struct dc *dc,
+ /* disable HW used by plane.
+ * note: cannot disable until disconnect is complete
+ */
+-static void plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx)
++static void dcn10_plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx)
+ {
+ struct hubp *hubp = pipe_ctx->plane_res.hubp;
+ struct dpp *dpp = pipe_ctx->plane_res.dpp;
+@@ -1014,7 +1033,7 @@ static void plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx)
+ hubp->power_gated = true;
+ dc->optimized_required = false; /* We're powering off, no need to optimize */
+
+- plane_atomic_power_down(dc,
++ dc->hwss.plane_atomic_power_down(dc,
+ pipe_ctx->plane_res.dpp,
+ pipe_ctx->plane_res.hubp);
+
+@@ -1033,7 +1052,7 @@ static void dcn10_disable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx)
+ if (!pipe_ctx->plane_res.hubp || pipe_ctx->plane_res.hubp->power_gated)
+ return;
+
+- plane_atomic_disable(dc, pipe_ctx);
++ dc->hwss.plane_atomic_disable(dc, pipe_ctx);
+
+ apply_DEGVIDCN10_253_wa(dc);
+
+@@ -1068,9 +1087,14 @@ static void dcn10_init_pipes(struct dc *dc, struct dc_state *context)
+ * command table.
+ */
+ if (tg->funcs->is_tg_enabled(tg)) {
+- tg->funcs->lock(tg);
+- tg->funcs->set_blank(tg, true);
+- hwss_wait_for_blank_complete(tg);
++ if (dc->hwss.init_blank != NULL) {
++ dc->hwss.init_blank(dc, tg);
++ tg->funcs->lock(tg);
++ } else {
++ tg->funcs->lock(tg);
++ tg->funcs->set_blank(tg, true);
++ hwss_wait_for_blank_complete(tg);
++ }
+ }
+ }
+
+@@ -1121,12 +1145,12 @@ static void dcn10_init_pipes(struct dc *dc, struct dc_state *context)
+ dc->res_pool->opps[i]->mpcc_disconnect_pending[pipe_ctx->plane_res.mpcc_inst] = true;
+ pipe_ctx->stream_res.opp = dc->res_pool->opps[i];
+
+- hwss1_plane_atomic_disconnect(dc, pipe_ctx);
++ dc->hwss.plane_atomic_disconnect(dc, pipe_ctx);
+
+ if (tg->funcs->is_tg_enabled(tg))
+ tg->funcs->unlock(tg);
+
+- dcn10_disable_plane(dc, pipe_ctx);
++ dc->hwss.disable_plane(dc, pipe_ctx);
+
+ pipe_ctx->stream_res.tg = NULL;
+ pipe_ctx->plane_res.hubp = NULL;
+@@ -1142,8 +1166,17 @@ static void dcn10_init_hw(struct dc *dc)
+ struct dmcu *dmcu = dc->res_pool->dmcu;
+ struct dce_hwseq *hws = dc->hwseq;
+ struct dc_bios *dcb = dc->ctx->dc_bios;
++ struct resource_pool *res_pool = dc->res_pool;
++
++ if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks)
++ dc->clk_mgr->funcs->init_clocks(dc->clk_mgr);
++
++ // Initialize the dccg
++ if (dc->res_pool->dccg && dc->res_pool->dccg->funcs->dccg_init)
++ dc->res_pool->dccg->funcs->dccg_init(res_pool->dccg);
+
+ if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
++
+ REG_WRITE(REFCLK_CNTL, 0);
+ REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1);
+ REG_WRITE(DIO_MEM_PWR_CTRL, 0);
+@@ -1157,30 +1190,39 @@ static void dcn10_init_hw(struct dc *dc)
+ REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);
+ }
+
+- enable_power_gating_plane(dc->hwseq, true);
++ //Enable ability to power gate / don't force power on permanently
++ dc->hwss.enable_power_gating_plane(hws, true);
+
+- /* end of FPGA. Below if real ASIC */
+ return;
+ }
+
+ if (!dcb->funcs->is_accelerated_mode(dcb)) {
+- bool allow_self_fresh_force_enable =
+- hububu1_is_allow_self_refresh_enabled(
+- dc->res_pool->hubbub);
+-
+- bios_golden_init(dc);
+-
+- /* WA for making DF sleep when idle after resume from S0i3.
+- * DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE is set to 1 by
+- * command table, if DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE = 0
+- * before calling command table and it changed to 1 after,
+- * it should be set back to 0.
+- */
+- if (allow_self_fresh_force_enable == false &&
+- hububu1_is_allow_self_refresh_enabled(dc->res_pool->hubbub))
+- hubbub1_allow_self_refresh_control(dc->res_pool->hubbub, true);
+-
+- disable_vga(dc->hwseq);
++ dc->hwss.bios_golden_init(dc);
++ if (dc->ctx->dc_bios->fw_info_valid) {
++ res_pool->ref_clocks.xtalin_clock_inKhz =
++ dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency;
++
++ if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
++ if (res_pool->dccg && res_pool->hubbub) {
++
++ (res_pool->dccg->funcs->get_dccg_ref_freq)(res_pool->dccg,
++ dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency,
++ &res_pool->ref_clocks.dccg_ref_clock_inKhz);
++
++ (res_pool->hubbub->funcs->get_dchub_ref_freq)(res_pool->hubbub,
++ res_pool->ref_clocks.dccg_ref_clock_inKhz,
++ &res_pool->ref_clocks.dchub_ref_clock_inKhz);
++ } else {
++ // Not all ASICs have DCCG sw component
++ res_pool->ref_clocks.dccg_ref_clock_inKhz =
++ res_pool->ref_clocks.xtalin_clock_inKhz;
++ res_pool->ref_clocks.dchub_ref_clock_inKhz =
++ res_pool->ref_clocks.xtalin_clock_inKhz;
++ }
++ }
++ } else
++ ASSERT_CRITICAL(false);
++ dc->hwss.disable_vga(dc->hwseq);
+ }
+
+ for (i = 0; i < dc->link_count; i++) {
+@@ -1198,6 +1240,13 @@ static void dcn10_init_hw(struct dc *dc)
+ link->link_status.link_active = true;
+ }
+
++ /* Power gate DSCs */
++#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
++ for (i = 0; i < res_pool->res_cap->num_dsc; i++)
++ if (dc->hwss.dsc_pg_control != NULL)
++ dc->hwss.dsc_pg_control(hws, res_pool->dscs[i]->inst, false);
++#endif
++
+ /* If taking control over from VBIOS, we may want to optimize our first
+ * mode set, so we need to skip powering down pipes until we know which
+ * pipes we want to use.
+@@ -1206,10 +1255,21 @@ static void dcn10_init_hw(struct dc *dc)
+ */
+ if (dcb->funcs->is_accelerated_mode(dcb) || dc->config.power_down_display_on_boot) {
+ dc->hwss.init_pipes(dc, dc->current_state);
++ for (i = 0; i < res_pool->pipe_count; i++) {
++ struct hubp *hubp = res_pool->hubps[i];
++ struct dpp *dpp = res_pool->dpps[i];
++
++ hubp->funcs->hubp_init(hubp);
++ res_pool->opps[i]->mpc_tree_params.opp_id = res_pool->opps[i]->inst;
++ dc->hwss.plane_atomic_power_down(dc, dpp, hubp);
++ }
++
++ apply_DEGVIDCN10_253_wa(dc);
+ }
+
+- for (i = 0; i < dc->res_pool->audio_count; i++) {
+- struct audio *audio = dc->res_pool->audios[i];
++
++ for (i = 0; i < res_pool->audio_count; i++) {
++ struct audio *audio = res_pool->audios[i];
+
+ audio->funcs->hw_init(audio);
+ }
+@@ -1237,7 +1297,7 @@ static void dcn10_init_hw(struct dc *dc)
+ REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);
+ }
+
+- enable_power_gating_plane(dc->hwseq, true);
++ dc->hwss.enable_power_gating_plane(dc->hwseq, true);
+ }
+
+ static void dcn10_reset_hw_ctx_wrap(
+@@ -1825,7 +1885,7 @@ static void dcn10_enable_plane(
+ }
+ }
+
+-static void program_gamut_remap(struct pipe_ctx *pipe_ctx)
++static void dcn10_program_gamut_remap(struct pipe_ctx *pipe_ctx)
+ {
+ int i = 0;
+ struct dpp_grph_csc_adjustment adjust;
+@@ -2303,7 +2363,7 @@ void update_dchubp_dpp(
+
+ if (plane_state->update_flags.bits.full_update) {
+ /*gamut remap*/
+- program_gamut_remap(pipe_ctx);
++ dc->hwss.program_gamut_remap(pipe_ctx);
+
+ dc->hwss.program_output_csc(dc,
+ pipe_ctx,
+@@ -2540,7 +2600,7 @@ static void dcn10_apply_ctx_for_surface(
+ if (old_pipe_ctx->stream_res.tg == tg &&
+ old_pipe_ctx->plane_res.hubp &&
+ old_pipe_ctx->plane_res.hubp->opp_id != OPP_ID_INVALID)
+- dcn10_disable_plane(dc, old_pipe_ctx);
++ dc->hwss.disable_plane(dc, old_pipe_ctx);
+ }
+
+ if ((!pipe_ctx->plane_state ||
+@@ -2588,7 +2648,7 @@ static void dcn10_apply_ctx_for_surface(
+
+ for (i = 0; i < dc->res_pool->pipe_count; i++)
+ if (removed_pipe[i])
+- dcn10_disable_plane(dc, &dc->current_state->res_ctx.pipe_ctx[i]);
++ dc->hwss.disable_plane(dc, &dc->current_state->res_ctx.pipe_ctx[i]);
+
+ for (i = 0; i < dc->res_pool->pipe_count; i++)
+ if (removed_pipe[i]) {
+@@ -2680,7 +2740,7 @@ static void dcn10_optimize_bandwidth(
+ dcn10_verify_allow_pstate_change_high(dc);
+ }
+
+-static void set_drr(struct pipe_ctx **pipe_ctx,
++static void dcn10_set_drr(struct pipe_ctx **pipe_ctx,
+ int num_pipes, int vmin, int vmax)
+ {
+ int i = 0;
+@@ -2705,7 +2765,7 @@ static void set_drr(struct pipe_ctx **pipe_ctx,
+ }
+ }
+
+-static void get_position(struct pipe_ctx **pipe_ctx,
++static void dcn10_get_position(struct pipe_ctx **pipe_ctx,
+ int num_pipes,
+ struct crtc_position *position)
+ {
+@@ -2717,7 +2777,7 @@ static void get_position(struct pipe_ctx **pipe_ctx,
+ pipe_ctx[i]->stream_res.tg->funcs->get_position(pipe_ctx[i]->stream_res.tg, position);
+ }
+
+-static void set_static_screen_control(struct pipe_ctx **pipe_ctx,
++static void dcn10_set_static_screen_control(struct pipe_ctx **pipe_ctx,
+ int num_pipes, const struct dc_static_screen_events *events)
+ {
+ unsigned int i;
+@@ -3204,7 +3264,7 @@ static void dcn10_get_clock(struct dc *dc,
+ }
+
+ static const struct hw_sequencer_funcs dcn10_funcs = {
+- .program_gamut_remap = program_gamut_remap,
++ .program_gamut_remap = dcn10_program_gamut_remap,
+ .init_hw = dcn10_init_hw,
+ .init_pipes = dcn10_init_pipes,
+ .apply_ctx_to_hw = dce110_apply_ctx_to_hw,
+@@ -3237,18 +3297,18 @@ static const struct hw_sequencer_funcs dcn10_funcs = {
+ .optimize_bandwidth = dcn10_optimize_bandwidth,
+ .reset_hw_ctx_wrap = dcn10_reset_hw_ctx_wrap,
+ .enable_stream_timing = dcn10_enable_stream_timing,
+- .set_drr = set_drr,
+- .get_position = get_position,
+- .set_static_screen_control = set_static_screen_control,
++ .set_drr = dcn10_set_drr,
++ .get_position = dcn10_get_position,
++ .set_static_screen_control = dcn10_set_static_screen_control,
+ .setup_stereo = dcn10_setup_stereo,
+ .set_avmute = dce110_set_avmute,
+ .log_hw_state = dcn10_log_hw_state,
+ .get_hw_state = dcn10_get_hw_state,
+ .clear_status_bits = dcn10_clear_status_bits,
+ .wait_for_mpcc_disconnect = dcn10_wait_for_mpcc_disconnect,
+- .edp_backlight_control = hwss_edp_backlight_control,
+- .edp_power_control = hwss_edp_power_control,
+- .edp_wait_for_hpd_ready = hwss_edp_wait_for_hpd_ready,
++ .edp_backlight_control = dce110_edp_backlight_control,
++ .edp_power_control = dce110_edp_power_control,
++ .edp_wait_for_hpd_ready = dce110_edp_wait_for_hpd_ready,
+ .set_cursor_position = dcn10_set_cursor_position,
+ .set_cursor_attribute = dcn10_set_cursor_attribute,
+ .set_cursor_sdr_white_level = dcn10_set_cursor_sdr_white_level,
+@@ -3258,6 +3318,16 @@ static const struct hw_sequencer_funcs dcn10_funcs = {
+ .setup_vupdate_interrupt = dcn10_setup_vupdate_interrupt,
+ .set_clock = dcn10_set_clock,
+ .get_clock = dcn10_get_clock,
++ .did_underflow_occur = dcn10_did_underflow_occur,
++ .init_blank = NULL,
++ .disable_vga = dcn10_disable_vga,
++ .bios_golden_init = dcn10_bios_golden_init,
++ .plane_atomic_disable = dcn10_plane_atomic_disable,
++ .plane_atomic_power_down = dcn10_plane_atomic_power_down,
++ .enable_power_gating_plane = dcn10_enable_power_gating_plane,
++ .dpp_pg_control = dcn10_dpp_pg_control,
++ .hubp_pg_control = dcn10_hubp_pg_control,
++ .dsc_pg_control = NULL,
+ };
+
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.c
+index 2b7859dfc089..f13e039f8ef4 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubbub.c
+@@ -595,7 +595,7 @@ static const struct hubbub_funcs hubbub2_funcs = {
+ .get_dcc_compression_cap = hubbub2_get_dcc_compression_cap,
+ .wm_read_state = hubbub2_wm_read_state,
+ .get_dchub_ref_freq = hubbub2_get_dchub_ref_freq,
+- .program_watermarks = hubbub2_program_watermarks,
++ .program_watermarks = hubbub2_program_watermarks
+ };
+
+ void hubbub2_construct(struct dcn20_hubbub *hubbub,
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
+index 91357271e360..57d9645659d8 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
+@@ -64,23 +64,7 @@
+ #define FN(reg_name, field_name) \
+ hws->shifts->field_name, hws->masks->field_name
+
+-static void bios_golden_init(struct dc *dc)
+-{
+- struct dc_bios *bp = dc->ctx->dc_bios;
+- int i;
+-
+- /* initialize dcn global */
+- bp->funcs->enable_disp_power_gating(bp,
+- CONTROLLER_ID_D0, ASIC_PIPE_INIT);
+-
+- for (i = 0; i < dc->res_pool->pipe_count; i++) {
+- /* initialize dcn per pipe */
+- bp->funcs->enable_disp_power_gating(bp,
+- CONTROLLER_ID_D0 + i, ASIC_PIPE_DISABLE);
+- }
+-}
+-
+-static void enable_power_gating_plane(
++static void dcn20_enable_power_gating_plane(
+ struct dce_hwseq *hws,
+ bool enable)
+ {
+@@ -183,7 +167,7 @@ void dcn20_display_init(struct dc *dc)
+ REG_WRITE(AZALIA_CONTROLLER_CLOCK_GATING, 0x1);
+ }
+
+-static void disable_vga(
++void dcn20_disable_vga(
+ struct dce_hwseq *hws)
+ {
+ REG_WRITE(D1VGA_CONTROL, 0);
+@@ -486,29 +470,6 @@ static void dcn20_hubp_pg_control(
+ }
+
+
+-
+-static void dcn20_plane_atomic_power_down(struct dc *dc, struct pipe_ctx *pipe_ctx)
+-{
+- struct dce_hwseq *hws = dc->hwseq;
+- struct dpp *dpp = pipe_ctx->plane_res.dpp;
+-
+- DC_LOGGER_INIT(dc->ctx->logger);
+-
+- if (REG(DC_IP_REQUEST_CNTL)) {
+- REG_SET(DC_IP_REQUEST_CNTL, 0,
+- IP_REQUEST_EN, 1);
+- dcn20_dpp_pg_control(hws, dpp->inst, false);
+- dcn20_hubp_pg_control(hws, pipe_ctx->plane_res.hubp->inst, false);
+- dpp->funcs->dpp_reset(dpp);
+- REG_SET(DC_IP_REQUEST_CNTL, 0,
+- IP_REQUEST_EN, 0);
+- DC_LOG_DEBUG(
+- "Power gated front end %d\n", pipe_ctx->pipe_idx);
+- }
+-}
+-
+-
+-
+ /* disable HW used by plane.
+ * note: cannot disable until disconnect is complete
+ */
+@@ -534,7 +495,9 @@ static void dcn20_plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx)
+ hubp->power_gated = true;
+ dc->optimized_required = false; /* We're powering off, no need to optimize */
+
+- dcn20_plane_atomic_power_down(dc, pipe_ctx);
++ dc->hwss.plane_atomic_power_down(dc,
++ pipe_ctx->plane_res.dpp,
++ pipe_ctx->plane_res.hubp);
+
+ pipe_ctx->stream = NULL;
+ memset(&pipe_ctx->stream_res, 0, sizeof(pipe_ctx->stream_res));
+@@ -558,204 +521,6 @@ void dcn20_disable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx)
+ pipe_ctx->pipe_idx);
+ }
+
+-static void dcn20_init_hw(struct dc *dc)
+-{
+- int i, j;
+- struct abm *abm = dc->res_pool->abm;
+- struct dmcu *dmcu = dc->res_pool->dmcu;
+- struct dce_hwseq *hws = dc->hwseq;
+- struct dc_bios *dcb = dc->ctx->dc_bios;
+- struct resource_pool *res_pool = dc->res_pool;
+- struct dc_state *context = dc->current_state;
+-
+- if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks)
+- dc->clk_mgr->funcs->init_clocks(dc->clk_mgr);
+-
+- // Initialize the dccg
+- if (res_pool->dccg->funcs->dccg_init)
+- res_pool->dccg->funcs->dccg_init(res_pool->dccg);
+-
+- //Enable ability to power gate / don't force power on permanently
+- enable_power_gating_plane(dc->hwseq, true);
+-
+- if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
+- REG_WRITE(RBBMIF_TIMEOUT_DIS, 0xFFFFFFFF);
+- REG_WRITE(RBBMIF_TIMEOUT_DIS_2, 0xFFFFFFFF);
+-
+- dcn20_dccg_init(hws);
+-
+- REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, 2);
+- REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1);
+- REG_WRITE(REFCLK_CNTL, 0);
+- } else {
+- if (!dcb->funcs->is_accelerated_mode(dcb)) {
+- bios_golden_init(dc);
+- if (dc->ctx->dc_bios->fw_info_valid) {
+- res_pool->ref_clocks.xtalin_clock_inKhz =
+- dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency;
+-
+- if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
+- if (res_pool->dccg && res_pool->hubbub) {
+-
+- (res_pool->dccg->funcs->get_dccg_ref_freq)(res_pool->dccg,
+- dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency,
+- &res_pool->ref_clocks.dccg_ref_clock_inKhz);
+-
+- (res_pool->hubbub->funcs->get_dchub_ref_freq)(res_pool->hubbub,
+- res_pool->ref_clocks.dccg_ref_clock_inKhz,
+- &res_pool->ref_clocks.dchub_ref_clock_inKhz);
+- } else {
+- // Not all ASICs have DCCG sw component
+- res_pool->ref_clocks.dccg_ref_clock_inKhz =
+- res_pool->ref_clocks.xtalin_clock_inKhz;
+- res_pool->ref_clocks.dchub_ref_clock_inKhz =
+- res_pool->ref_clocks.xtalin_clock_inKhz;
+- }
+- }
+- } else
+- ASSERT_CRITICAL(false);
+- disable_vga(dc->hwseq);
+- }
+-
+- for (i = 0; i < dc->link_count; i++) {
+- /* Power up AND update implementation according to the
+- * required signal (which may be different from the
+- * default signal on connector).
+- */
+- struct dc_link *link = dc->links[i];
+-
+- link->link_enc->funcs->hw_init(link->link_enc);
+- }
+- }
+-
+-#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
+- /* Power gate DSCs */
+- for (i = 0; i < res_pool->res_cap->num_dsc; i++)
+- dcn20_dsc_pg_control(hws, res_pool->dscs[i]->inst, false);
+-#endif
+-
+- /* Blank pixel data with OPP DPG */
+- for (i = 0; i < dc->res_pool->timing_generator_count; i++) {
+- struct timing_generator *tg = dc->res_pool->timing_generators[i];
+-
+- if (tg->funcs->is_tg_enabled(tg)) {
+- dcn20_init_blank(dc, tg);
+- }
+- }
+-
+- for (i = 0; i < res_pool->timing_generator_count; i++) {
+- struct timing_generator *tg = dc->res_pool->timing_generators[i];
+-
+- if (tg->funcs->is_tg_enabled(tg))
+- tg->funcs->lock(tg);
+- }
+-
+- for (i = 0; i < dc->res_pool->pipe_count; i++) {
+- struct dpp *dpp = res_pool->dpps[i];
+-
+- dpp->funcs->dpp_reset(dpp);
+- }
+-
+- /* Reset all MPCC muxes */
+- res_pool->mpc->funcs->mpc_init(res_pool->mpc);
+-
+- /* initialize OPP mpc_tree parameter */
+- for (i = 0; i < dc->res_pool->res_cap->num_opp; i++) {
+- res_pool->opps[i]->mpc_tree_params.opp_id = res_pool->opps[i]->inst;
+- res_pool->opps[i]->mpc_tree_params.opp_list = NULL;
+- for (j = 0; j < MAX_PIPES; j++)
+- res_pool->opps[i]->mpcc_disconnect_pending[j] = false;
+- }
+-
+- for (i = 0; i < dc->res_pool->pipe_count; i++) {
+- struct timing_generator *tg = dc->res_pool->timing_generators[i];
+- struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
+- struct hubp *hubp = dc->res_pool->hubps[i];
+- struct dpp *dpp = dc->res_pool->dpps[i];
+-
+- pipe_ctx->stream_res.tg = tg;
+- pipe_ctx->pipe_idx = i;
+-
+- pipe_ctx->plane_res.hubp = hubp;
+- pipe_ctx->plane_res.dpp = dpp;
+- pipe_ctx->plane_res.mpcc_inst = dpp->inst;
+- hubp->mpcc_id = dpp->inst;
+- hubp->opp_id = OPP_ID_INVALID;
+- hubp->power_gated = false;
+- pipe_ctx->stream_res.opp = NULL;
+-
+- hubp->funcs->hubp_init(hubp);
+-
+- //dc->res_pool->opps[i]->mpc_tree_params.opp_id = dc->res_pool->opps[i]->inst;
+- //dc->res_pool->opps[i]->mpc_tree_params.opp_list = NULL;
+- dc->res_pool->opps[i]->mpcc_disconnect_pending[pipe_ctx->plane_res.mpcc_inst] = true;
+- pipe_ctx->stream_res.opp = dc->res_pool->opps[i];
+- /*to do*/
+- hwss1_plane_atomic_disconnect(dc, pipe_ctx);
+- }
+-
+- /* initialize DWB pointer to MCIF_WB */
+- for (i = 0; i < res_pool->res_cap->num_dwb; i++)
+- res_pool->dwbc[i]->mcif = res_pool->mcif_wb[i];
+-
+- for (i = 0; i < dc->res_pool->timing_generator_count; i++) {
+- struct timing_generator *tg = dc->res_pool->timing_generators[i];
+-
+- if (tg->funcs->is_tg_enabled(tg))
+- tg->funcs->unlock(tg);
+- }
+-
+- for (i = 0; i < dc->res_pool->pipe_count; i++) {
+- struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
+-
+- dc->hwss.disable_plane(dc, pipe_ctx);
+-
+- pipe_ctx->stream_res.tg = NULL;
+- pipe_ctx->plane_res.hubp = NULL;
+- }
+-
+- for (i = 0; i < dc->res_pool->timing_generator_count; i++) {
+- struct timing_generator *tg = dc->res_pool->timing_generators[i];
+-
+- tg->funcs->tg_init(tg);
+- }
+-
+- /* end of FPGA. Below if real ASIC */
+- if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment))
+- return;
+-
+-
+- for (i = 0; i < res_pool->audio_count; i++) {
+- struct audio *audio = res_pool->audios[i];
+-
+- audio->funcs->hw_init(audio);
+- }
+-
+- if (abm != NULL) {
+- abm->funcs->init_backlight(abm);
+- abm->funcs->abm_init(abm);
+- }
+-
+- if (dmcu != NULL)
+- dmcu->funcs->dmcu_init(dmcu);
+-
+- if (abm != NULL && dmcu != NULL)
+- abm->dmcu_is_running = dmcu->funcs->is_dmcu_initialized(dmcu);
+-
+- /* power AFMT HDMI memory TODO: may move to dis/en output save power*/
+- REG_WRITE(DIO_MEM_PWR_CTRL, 0);
+-
+- if (!dc->debug.disable_clock_gate) {
+- /* enable all DCN clock gating */
+- REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0);
+-
+- REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0);
+-
+- REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);
+- }
+-
+-}
+-
+ enum dc_status dcn20_enable_stream_timing(
+ struct pipe_ctx *pipe_ctx,
+ struct dc_state *context,
+@@ -1414,7 +1179,7 @@ static void dcn20_apply_ctx_for_surface(
+ if (old_pipe_ctx->stream_res.tg == tg &&
+ old_pipe_ctx->plane_res.hubp &&
+ old_pipe_ctx->plane_res.hubp->opp_id != OPP_ID_INVALID)
+- dcn20_disable_plane(dc, old_pipe_ctx);
++ dc->hwss.disable_plane(dc, old_pipe_ctx);
+ }
+
+ if ((!pipe_ctx->plane_state ||
+@@ -2174,14 +1939,126 @@ static void dcn20_program_dmdata_engine(struct pipe_ctx *pipe_ctx)
+ hubp->inst, mode);
+ }
+
++static void dcn20_fpga_init_hw(struct dc *dc)
++{
++ int i, j;
++ struct dce_hwseq *hws = dc->hwseq;
++ struct resource_pool *res_pool = dc->res_pool;
++ struct dc_state *context = dc->current_state;
++
++ if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks)
++ dc->clk_mgr->funcs->init_clocks(dc->clk_mgr);
++
++ // Initialize the dccg
++ if (res_pool->dccg->funcs->dccg_init)
++ res_pool->dccg->funcs->dccg_init(res_pool->dccg);
++
++ //Enable ability to power gate / don't force power on permanently
++ dc->hwss.enable_power_gating_plane(hws, true);
++
++ // Specific to FPGA dccg and registers
++ REG_WRITE(RBBMIF_TIMEOUT_DIS, 0xFFFFFFFF);
++ REG_WRITE(RBBMIF_TIMEOUT_DIS_2, 0xFFFFFFFF);
++
++ dcn20_dccg_init(hws);
++
++ REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, 2);
++ REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1);
++ REG_WRITE(REFCLK_CNTL, 0);
++ //
++
++
++ /* Blank pixel data with OPP DPG */
++ for (i = 0; i < dc->res_pool->timing_generator_count; i++) {
++ struct timing_generator *tg = dc->res_pool->timing_generators[i];
++
++ if (tg->funcs->is_tg_enabled(tg))
++ dcn20_init_blank(dc, tg);
++ }
++
++ for (i = 0; i < res_pool->timing_generator_count; i++) {
++ struct timing_generator *tg = dc->res_pool->timing_generators[i];
++
++ if (tg->funcs->is_tg_enabled(tg))
++ tg->funcs->lock(tg);
++ }
++
++ for (i = 0; i < dc->res_pool->pipe_count; i++) {
++ struct dpp *dpp = res_pool->dpps[i];
++
++ dpp->funcs->dpp_reset(dpp);
++ }
++
++ /* Reset all MPCC muxes */
++ res_pool->mpc->funcs->mpc_init(res_pool->mpc);
++
++ /* initialize OPP mpc_tree parameter */
++ for (i = 0; i < dc->res_pool->res_cap->num_opp; i++) {
++ res_pool->opps[i]->mpc_tree_params.opp_id = res_pool->opps[i]->inst;
++ res_pool->opps[i]->mpc_tree_params.opp_list = NULL;
++ for (j = 0; j < MAX_PIPES; j++)
++ res_pool->opps[i]->mpcc_disconnect_pending[j] = false;
++ }
++
++ for (i = 0; i < dc->res_pool->pipe_count; i++) {
++ struct timing_generator *tg = dc->res_pool->timing_generators[i];
++ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
++ struct hubp *hubp = dc->res_pool->hubps[i];
++ struct dpp *dpp = dc->res_pool->dpps[i];
++
++ pipe_ctx->stream_res.tg = tg;
++ pipe_ctx->pipe_idx = i;
++
++ pipe_ctx->plane_res.hubp = hubp;
++ pipe_ctx->plane_res.dpp = dpp;
++ pipe_ctx->plane_res.mpcc_inst = dpp->inst;
++ hubp->mpcc_id = dpp->inst;
++ hubp->opp_id = OPP_ID_INVALID;
++ hubp->power_gated = false;
++ pipe_ctx->stream_res.opp = NULL;
++
++ hubp->funcs->hubp_init(hubp);
++
++ //dc->res_pool->opps[i]->mpc_tree_params.opp_id = dc->res_pool->opps[i]->inst;
++ //dc->res_pool->opps[i]->mpc_tree_params.opp_list = NULL;
++ dc->res_pool->opps[i]->mpcc_disconnect_pending[pipe_ctx->plane_res.mpcc_inst] = true;
++ pipe_ctx->stream_res.opp = dc->res_pool->opps[i];
++ /*to do*/
++ hwss1_plane_atomic_disconnect(dc, pipe_ctx);
++ }
++
++ /* initialize DWB pointer to MCIF_WB */
++ for (i = 0; i < res_pool->res_cap->num_dwb; i++)
++ res_pool->dwbc[i]->mcif = res_pool->mcif_wb[i];
++
++ for (i = 0; i < dc->res_pool->timing_generator_count; i++) {
++ struct timing_generator *tg = dc->res_pool->timing_generators[i];
++
++ if (tg->funcs->is_tg_enabled(tg))
++ tg->funcs->unlock(tg);
++ }
++
++ for (i = 0; i < dc->res_pool->pipe_count; i++) {
++ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
++
++ dc->hwss.disable_plane(dc, pipe_ctx);
++
++ pipe_ctx->stream_res.tg = NULL;
++ pipe_ctx->plane_res.hubp = NULL;
++ }
++
++ for (i = 0; i < dc->res_pool->timing_generator_count; i++) {
++ struct timing_generator *tg = dc->res_pool->timing_generators[i];
++
++ tg->funcs->tg_init(tg);
++ }
++}
++
+ void dcn20_hw_sequencer_construct(struct dc *dc)
+ {
+ dcn10_hw_sequencer_construct(dc);
+- dc->hwss.init_hw = dcn20_init_hw;
+- dc->hwss.init_pipes = NULL;
+ dc->hwss.unblank_stream = dcn20_unblank_stream;
+ dc->hwss.update_plane_addr = dcn20_update_plane_addr;
+- dc->hwss.disable_plane = dcn20_disable_plane,
+ dc->hwss.enable_stream_timing = dcn20_enable_stream_timing;
+ dc->hwss.program_triplebuffer = dcn20_program_tripleBuffer;
+ dc->hwss.set_input_transfer_func = dcn20_set_input_transfer_func;
+@@ -2209,5 +2086,21 @@ void dcn20_hw_sequencer_construct(struct dc *dc)
+ dc->hwss.reset_hw_ctx_wrap = dcn20_reset_hw_ctx_wrap;
+ dc->hwss.update_mpcc = dcn20_update_mpcc;
+ dc->hwss.set_flip_control_gsl = dcn20_set_flip_control_gsl;
+- dc->hwss.did_underflow_occur = dcn10_did_underflow_occur;
++ dc->hwss.init_blank = dcn20_init_blank;
++ dc->hwss.disable_plane = dcn20_disable_plane;
++ dc->hwss.plane_atomic_disable = dcn20_plane_atomic_disable;
++ dc->hwss.enable_power_gating_plane = dcn20_enable_power_gating_plane;
++ dc->hwss.dpp_pg_control = dcn20_dpp_pg_control;
++ dc->hwss.hubp_pg_control = dcn20_hubp_pg_control;
++#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
++ dc->hwss.dsc_pg_control = dcn20_dsc_pg_control;
++#endif
++ dc->hwss.disable_vga = dcn20_disable_vga;
++
++ if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
++ dc->hwss.init_hw = dcn20_fpga_init_hw;
++ dc->hwss.init_pipes = NULL;
++ }
++
++
+ }
+diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h
+index 9502478c4a1b..c1f29b1654d9 100644
+--- a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h
++++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h
+@@ -141,6 +141,10 @@ struct hubbub_funcs {
+ struct dcn_watermark_set *watermarks,
+ unsigned int refclk_mhz,
+ bool safe_to_lower);
++
++ bool (*is_allow_self_refresh_enabled)(struct hubbub *hubbub);
++ void (*allow_self_refresh_control)(struct hubbub *hubbub, bool allow);
++
+ };
+
+ struct hubbub {
+diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
+index 28645e10f854..80de2febd7cb 100644
+--- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
++++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
+@@ -78,6 +78,8 @@ struct stream_resource;
+ struct dc_phy_addr_space_config;
+ struct dc_virtual_addr_space_config;
+ #endif
++struct hubp;
++struct dpp;
+
+ struct hw_sequencer_funcs {
+
+@@ -280,6 +282,36 @@ struct hw_sequencer_funcs {
+ void (*setup_vupdate_interrupt)(struct pipe_ctx *pipe_ctx);
+ bool (*did_underflow_occur)(struct dc *dc, struct pipe_ctx *pipe_ctx);
+
++ void (*init_blank)(struct dc *dc, struct timing_generator *tg);
++ void (*disable_vga)(struct dce_hwseq *hws);
++ void (*bios_golden_init)(struct dc *dc);
++ void (*plane_atomic_power_down)(struct dc *dc,
++ struct dpp *dpp,
++ struct hubp *hubp);
++
++ void (*plane_atomic_disable)(
++ struct dc *dc, struct pipe_ctx *pipe_ctx);
++
++ void (*enable_power_gating_plane)(
++ struct dce_hwseq *hws,
++ bool enable);
++
++ void (*dpp_pg_control)(
++ struct dce_hwseq *hws,
++ unsigned int dpp_inst,
++ bool power_on);
++
++ void (*hubp_pg_control)(
++ struct dce_hwseq *hws,
++ unsigned int hubp_inst,
++ bool power_on);
++
++ void (*dsc_pg_control)(
++ struct dce_hwseq *hws,
++ unsigned int dsc_inst,
++ bool power_on);
++
++
+ #if defined(CONFIG_DRM_AMD_DC_DCN2_0)
+ void (*update_odm)(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe_ctx);
+ void (*program_all_writeback_pipes_in_tree)(
+--
+2.17.1
+