aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c')
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c118
1 files changed, 64 insertions, 54 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c
index 1db1ca19411d..8c5045711264 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c
@@ -48,6 +48,8 @@
#include "dc_dmub_srv.h"
#include "link_hwss.h"
#include "dpcd_defs.h"
+#include "../dcn20/dcn20_hwseq.h"
+#include "dcn30_resource.h"
#include "inc/dc_link_dp.h"
#include "inc/link_dpcd.h"
@@ -344,17 +346,6 @@ void dcn30_enable_writeback(
dwb->funcs->enable(dwb, &wb_info->dwb_params);
}
-void dcn30_prepare_bandwidth(struct dc *dc,
- struct dc_state *context)
-{
- if (dc->clk_mgr->dc_mode_softmax_enabled)
- if (dc->clk_mgr->clks.dramclk_khz <= dc->clk_mgr->bw_params->dc_mode_softmax_memclk * 1000 &&
- context->bw_ctx.bw.dcn.clk.dramclk_khz > dc->clk_mgr->bw_params->dc_mode_softmax_memclk * 1000)
- dc->clk_mgr->funcs->set_max_memclk(dc->clk_mgr, dc->clk_mgr->bw_params->clk_table.entries[dc->clk_mgr->bw_params->clk_table.num_entries - 1].memclk_mhz);
-
- dcn20_prepare_bandwidth(dc, context);
-}
-
void dcn30_disable_writeback(
struct dc *dc,
unsigned int dwb_pipe_inst)
@@ -535,8 +526,12 @@ void dcn30_init_hw(struct dc *dc)
/* Check for enabled DIG to identify enabled display */
if (link->link_enc->funcs->is_dig_enabled &&
- link->link_enc->funcs->is_dig_enabled(link->link_enc))
+ link->link_enc->funcs->is_dig_enabled(link->link_enc)) {
link->link_status.link_active = true;
+ if (link->link_enc->funcs->fec_is_active &&
+ link->link_enc->funcs->fec_is_active(link->link_enc))
+ link->fec_state = dc_link_fec_enabled;
+ }
}
/* Power gate DSCs */
@@ -545,8 +540,10 @@ void dcn30_init_hw(struct dc *dc)
hws->funcs.dsc_pg_control(hws, res_pool->dscs[i]->inst, false);
/* we want to turn off all dp displays before doing detection */
- if (dc->config.power_down_display_on_boot)
- dc_link_blank_all_dp_displays(dc);
+ dc_link_blank_all_dp_displays(dc);
+
+ if (hws->funcs.enable_power_gating_plane)
+ hws->funcs.enable_power_gating_plane(dc->hwseq, true);
/* 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
@@ -554,7 +551,7 @@ void dcn30_init_hw(struct dc *dc)
* Otherwise, if taking control is not possible, we need to power
* everything down.
*/
- if (dcb->funcs->is_accelerated_mode(dcb) || dc->config.power_down_display_on_boot) {
+ if (dcb->funcs->is_accelerated_mode(dcb) || !dc->config.seamless_boot_edp_requested) {
hws->funcs.init_pipes(dc, dc->current_state);
if (dc->res_pool->hubbub->funcs->allow_self_refresh_control)
dc->res_pool->hubbub->funcs->allow_self_refresh_control(dc->res_pool->hubbub,
@@ -566,7 +563,7 @@ void dcn30_init_hw(struct dc *dc)
* To avoid this, power down hardware on boot
* if DIG is turned on and seamless boot not enabled
*/
- if (dc->config.power_down_display_on_boot) {
+ if (!dc->config.seamless_boot_edp_requested) {
struct dc_link *edp_links[MAX_NUM_EDP];
struct dc_link *edp_link = NULL;
@@ -625,8 +622,6 @@ void dcn30_init_hw(struct dc *dc)
REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);
}
- if (hws->funcs.enable_power_gating_plane)
- hws->funcs.enable_power_gating_plane(dc->hwseq, true);
if (!dcb->funcs->is_accelerated_mode(dcb) && dc->res_pool->hubbub->funcs->init_watermarks)
dc->res_pool->hubbub->funcs->init_watermarks(dc->res_pool->hubbub);
@@ -643,6 +638,10 @@ void dcn30_init_hw(struct dc *dc)
if (dc->res_pool->hubbub->funcs->init_crb)
dc->res_pool->hubbub->funcs->init_crb(dc->res_pool->hubbub);
+ // Get DMCUB capabilities
+ dc_dmub_srv_query_caps_cmd(dc->ctx->dmub_srv->dmub);
+ dc->caps.dmub_caps.psr = dc->ctx->dmub_srv->dmub->feature_caps.psr;
+ dc->caps.dmub_caps.mclk_sw = dc->ctx->dmub_srv->dmub->feature_caps.fw_assisted_mclk_switch;
}
void dcn30_set_avmute(struct pipe_ctx *pipe_ctx, bool enable)
@@ -940,11 +939,36 @@ bool dcn30_does_plane_fit_in_mall(struct dc *dc, struct dc_plane_state *plane, s
void dcn30_hardware_release(struct dc *dc)
{
- /* if pstate unsupported, force it supported */
- if (!dc->clk_mgr->clks.p_state_change_support &&
- dc->res_pool->hubbub->funcs->force_pstate_change_control)
- dc->res_pool->hubbub->funcs->force_pstate_change_control(
- dc->res_pool->hubbub, true, true);
+ bool subvp_in_use = false;
+ uint32_t i;
+
+ dc_dmub_srv_p_state_delegate(dc, false, NULL);
+ dc_dmub_setup_subvp_dmub_command(dc, dc->current_state, false);
+
+ /* SubVP treated the same way as FPO. If driver disable and
+ * we are using a SubVP config, disable and force on DCN side
+ * to prevent P-State hang on driver enable.
+ */
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i];
+
+ if (!pipe->stream)
+ continue;
+
+ if (pipe->stream->mall_stream_config.type == SUBVP_MAIN) {
+ subvp_in_use = true;
+ break;
+ }
+ }
+ /* If pstate unsupported, or still supported
+ * by firmware, force it supported by dcn
+ */
+ if (dc->current_state)
+ if ((!dc->clk_mgr->clks.p_state_change_support || subvp_in_use ||
+ dc->current_state->bw_ctx.bw.dcn.clk.fw_based_mclk_switching) &&
+ dc->res_pool->hubbub->funcs->force_pstate_change_control)
+ dc->res_pool->hubbub->funcs->force_pstate_change_control(
+ dc->res_pool->hubbub, true, true);
}
void dcn30_set_disp_pattern_generator(const struct dc *dc,
@@ -955,35 +979,21 @@ void dcn30_set_disp_pattern_generator(const struct dc *dc,
const struct tg_color *solid_color,
int width, int height, int offset)
{
- struct stream_resource *stream_res = &pipe_ctx->stream_res;
- struct pipe_ctx *mpcc_pipe;
-
- if (test_pattern != CONTROLLER_DP_TEST_PATTERN_VIDEOMODE) {
- pipe_ctx->vtp_locked = false;
- /* turning on DPG */
- stream_res->opp->funcs->opp_set_disp_pattern_generator(stream_res->opp, test_pattern, color_space,
- color_depth, solid_color, width, height, offset);
-
- /* Defer hubp blank if tg is locked */
- if (stream_res->tg->funcs->is_tg_enabled(stream_res->tg)) {
- if (stream_res->tg->funcs->is_locked(stream_res->tg))
- pipe_ctx->vtp_locked = true;
- else {
- /* Blank HUBP to allow p-state during blank on all timings */
- pipe_ctx->plane_res.hubp->funcs->set_blank(pipe_ctx->plane_res.hubp, true);
-
- for (mpcc_pipe = pipe_ctx->bottom_pipe; mpcc_pipe; mpcc_pipe = mpcc_pipe->bottom_pipe)
- mpcc_pipe->plane_res.hubp->funcs->set_blank(mpcc_pipe->plane_res.hubp, true);
- }
- }
- } else {
- /* turning off DPG */
- pipe_ctx->plane_res.hubp->funcs->set_blank(pipe_ctx->plane_res.hubp, false);
- for (mpcc_pipe = pipe_ctx->bottom_pipe; mpcc_pipe; mpcc_pipe = mpcc_pipe->bottom_pipe)
- if (mpcc_pipe->plane_res.hubp)
- mpcc_pipe->plane_res.hubp->funcs->set_blank(mpcc_pipe->plane_res.hubp, false);
-
- stream_res->opp->funcs->opp_set_disp_pattern_generator(stream_res->opp, test_pattern, color_space,
- color_depth, solid_color, width, height, offset);
- }
+ pipe_ctx->stream_res.opp->funcs->opp_set_disp_pattern_generator(pipe_ctx->stream_res.opp, test_pattern,
+ color_space, color_depth, solid_color, width, height, offset);
}
+
+void dcn30_prepare_bandwidth(struct dc *dc,
+ struct dc_state *context)
+{
+ if (dc->clk_mgr->dc_mode_softmax_enabled)
+ if (dc->clk_mgr->clks.dramclk_khz <= dc->clk_mgr->bw_params->dc_mode_softmax_memclk * 1000 &&
+ context->bw_ctx.bw.dcn.clk.dramclk_khz > dc->clk_mgr->bw_params->dc_mode_softmax_memclk * 1000)
+ dc->clk_mgr->funcs->set_max_memclk(dc->clk_mgr, dc->clk_mgr->bw_params->clk_table.entries[dc->clk_mgr->bw_params->clk_table.num_entries - 1].memclk_mhz);
+
+ dcn20_prepare_bandwidth(dc, context);
+
+ dc_dmub_srv_p_state_delegate(dc,
+ context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching, context);
+}
+