diff options
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-.patch | 1086 |
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 + |