drm/amd/display: Set min dcfclk if pipe count is 0
authorMichael Strauss <michael.strauss@amd.com>
Wed, 11 Aug 2021 15:38:44 +0000 (11:38 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 1 Sep 2021 20:55:10 +0000 (16:55 -0400)
[WHY]
Clocks don't get recalculated in 0 stream/0 pipe configs,
blocking S0i3 if dcfclk gets high enough

[HOW]
Create DCN31 copy of DCN30 bandwidth validation func which
doesn't entirely skip validation in 0 pipe scenarios

Override dcfclk to vlevel 0/min value during validation if pipe
count is 0

Reviewed-by: Eric Yang <Eric.Yang2@amd.com>
Acked-by: Qingqing Zhuo <qingqing.zhuo@amd.com>
Signed-off-by: Michael Strauss <michael.strauss@amd.com>
Tested-by: Daniel Wheeler <Daniel.Wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.h
drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c

index a0de309..2feffe7 100644 (file)
@@ -1856,7 +1856,7 @@ static struct pipe_ctx *dcn30_find_split_pipe(
        return pipe;
 }
 
-static noinline bool dcn30_internal_validate_bw(
+noinline bool dcn30_internal_validate_bw(
                struct dc *dc,
                struct dc_state *context,
                display_e2e_pipe_params_st *pipes,
index b754b89..b92e4cc 100644 (file)
@@ -55,6 +55,13 @@ unsigned int dcn30_calc_max_scaled_time(
 
 bool dcn30_validate_bandwidth(struct dc *dc, struct dc_state *context,
                bool fast_validate);
+bool dcn30_internal_validate_bw(
+               struct dc *dc,
+               struct dc_state *context,
+               display_e2e_pipe_params_st *pipes,
+               int *pipe_cnt_out,
+               int *vlevel_out,
+               bool fast_validate);
 void dcn30_calculate_wm_and_dlg(
                struct dc *dc, struct dc_state *context,
                display_e2e_pipe_params_st *pipes,
index 5a4d338..3223a1f 100644 (file)
@@ -1827,6 +1827,15 @@ static void dcn31_calculate_wm_and_dlg_fp(
        if (context->bw_ctx.dml.soc.min_dcfclk > dcfclk)
                dcfclk = context->bw_ctx.dml.soc.min_dcfclk;
 
+       /* We don't recalculate clocks for 0 pipe configs, which can block
+        * S0i3 as high clocks will block low power states
+        * Override any clocks that can block S0i3 to min here
+        */
+       if (pipe_cnt == 0) {
+               context->bw_ctx.bw.dcn.clk.dcfclk_khz = dcfclk; // always should be vlevel 0
+               return;
+       }
+
        pipes[0].clks_cfg.voltage = vlevel;
        pipes[0].clks_cfg.dcfclk_mhz = dcfclk;
        pipes[0].clks_cfg.socclk_mhz = context->bw_ctx.dml.soc.clock_limits[vlevel].socclk_mhz;
@@ -1952,6 +1961,58 @@ static void dcn31_calculate_wm_and_dlg(
        DC_FP_END();
 }
 
+bool dcn31_validate_bandwidth(struct dc *dc,
+               struct dc_state *context,
+               bool fast_validate)
+{
+       bool out = false;
+
+       BW_VAL_TRACE_SETUP();
+
+       int vlevel = 0;
+       int pipe_cnt = 0;
+       display_e2e_pipe_params_st *pipes = kzalloc(dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st), GFP_KERNEL);
+       DC_LOGGER_INIT(dc->ctx->logger);
+
+       BW_VAL_TRACE_COUNT();
+
+       out = dcn30_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, fast_validate);
+
+       // Disable fast_validate to set min dcfclk in alculate_wm_and_dlg
+       if (pipe_cnt == 0)
+               fast_validate = false;
+
+       if (!out)
+               goto validate_fail;
+
+       BW_VAL_TRACE_END_VOLTAGE_LEVEL();
+
+       if (fast_validate) {
+               BW_VAL_TRACE_SKIP(fast);
+               goto validate_out;
+       }
+
+       dc->res_pool->funcs->calculate_wm_and_dlg(dc, context, pipes, pipe_cnt, vlevel);
+
+       BW_VAL_TRACE_END_WATERMARKS();
+
+       goto validate_out;
+
+validate_fail:
+       DC_LOG_WARNING("Mode Validation Warning: %s failed alidation.\n",
+               dml_get_status_message(context->bw_ctx.dml.vba.ValidationStatus[context->bw_ctx.dml.vba.soc.num_states]));
+
+       BW_VAL_TRACE_SKIP(fail);
+       out = false;
+
+validate_out:
+       kfree(pipes);
+
+       BW_VAL_TRACE_FINISH();
+
+       return out;
+}
+
 static struct dc_cap_funcs cap_funcs = {
        .get_dcc_compression_cap = dcn20_get_dcc_compression_cap
 };
@@ -2034,7 +2095,7 @@ static struct resource_funcs dcn31_res_pool_funcs = {
        .link_encs_assign = link_enc_cfg_link_encs_assign,
        .link_enc_unassign = link_enc_cfg_link_enc_unassign,
        .panel_cntl_create = dcn31_panel_cntl_create,
-       .validate_bandwidth = dcn30_validate_bandwidth,
+       .validate_bandwidth = dcn31_validate_bandwidth,
        .calculate_wm_and_dlg = dcn31_calculate_wm_and_dlg,
        .update_soc_for_wm_a = dcn31_update_soc_for_wm_a,
        .populate_dml_pipes = dcn31_populate_dml_pipes_from_context,