drm/amd/display: Do second pass through DML for DET calculation
[Why & How] If we find that DML requires pipe split, run through DML again because the DET allocation per pipe must be re-assigned. Reviewed-by: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com> Acked-by: Wayne Lin <wayne.lin@amd.com> Signed-off-by: Alvin Lee <Alvin.Lee2@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
4aecd050a8
commit
66990450e3
@ -1837,12 +1837,6 @@ validate_out:
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
static bool is_dual_plane(enum surface_pixel_format format)
|
||||
{
|
||||
return format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN || format == SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA;
|
||||
}
|
||||
|
||||
int dcn32_populate_dml_pipes_from_context(
|
||||
struct dc *dc, struct dc_state *context,
|
||||
display_e2e_pipe_params_st *pipes,
|
||||
@ -1852,7 +1846,6 @@ int dcn32_populate_dml_pipes_from_context(
|
||||
struct resource_context *res_ctx = &context->res_ctx;
|
||||
struct pipe_ctx *pipe;
|
||||
bool subvp_in_use = false;
|
||||
uint8_t is_pipe_split_expected[MAX_PIPES] = {0};
|
||||
int plane_count = 0;
|
||||
struct dc_crtc_timing *timing;
|
||||
|
||||
@ -1940,11 +1933,6 @@ int dcn32_populate_dml_pipes_from_context(
|
||||
if (pipe->stream && !pipe->prev_odm_pipe &&
|
||||
(!pipe->top_pipe || pipe->top_pipe->plane_state != pipe->plane_state))
|
||||
++plane_count;
|
||||
|
||||
DC_FP_START();
|
||||
is_pipe_split_expected[i] = dcn32_predict_pipe_split(context, &pipes[pipe_cnt]);
|
||||
DC_FP_END();
|
||||
|
||||
pipe_cnt++;
|
||||
}
|
||||
|
||||
@ -1952,19 +1940,7 @@ int dcn32_populate_dml_pipes_from_context(
|
||||
* the DET available for each pipe). Use the DET override input to maintain our driver
|
||||
* policy.
|
||||
*/
|
||||
if (pipe_cnt == 1 && !is_pipe_split_expected[0]) {
|
||||
pipes[0].pipe.src.det_size_override = DCN3_2_MAX_DET_SIZE;
|
||||
if (pipe->plane_state && !dc->debug.disable_z9_mpc) {
|
||||
if (!is_dual_plane(pipe->plane_state->format)) {
|
||||
pipes[0].pipe.src.det_size_override = DCN3_2_DEFAULT_DET_SIZE;
|
||||
pipes[0].pipe.src.unbounded_req_mode = true;
|
||||
if (pipe->plane_state->src_rect.width >= 5120 &&
|
||||
pipe->plane_state->src_rect.height >= 2880)
|
||||
pipes[0].pipe.src.det_size_override = 320; // 5K or higher
|
||||
}
|
||||
}
|
||||
} else
|
||||
dcn32_determine_det_override(dc, context, pipes, is_pipe_split_expected);
|
||||
dcn32_set_det_allocations(dc, context, pipes);
|
||||
|
||||
// In general cases we want to keep the dram clock change requirement
|
||||
// (prefer configs that support MCLK switch). Only override to false
|
||||
|
@ -28,6 +28,10 @@
|
||||
|
||||
#include "core_types.h"
|
||||
|
||||
#define DCN3_2_DEFAULT_DET_SIZE 256
|
||||
#define DCN3_2_MAX_DET_SIZE 1152
|
||||
#define DCN3_2_MIN_DET_SIZE 128
|
||||
#define DCN3_2_MIN_COMPBUF_SIZE_KB 128
|
||||
#define DCN3_2_DET_SEG_SIZE 64
|
||||
#define DCN3_2_MALL_MBLK_SIZE_BYTES 65536 // 64 * 1024
|
||||
#define DCN3_2_MBLK_WIDTH 128
|
||||
@ -111,9 +115,10 @@ struct pipe_ctx *dcn32_acquire_idle_pipe_for_head_pipe_in_layer(
|
||||
|
||||
void dcn32_determine_det_override(struct dc *dc,
|
||||
struct dc_state *context,
|
||||
display_e2e_pipe_params_st *pipes,
|
||||
uint8_t *is_pipe_split_expected);
|
||||
display_e2e_pipe_params_st *pipes);
|
||||
|
||||
void dcn32_set_det_allocations(struct dc *dc, struct dc_state *context,
|
||||
display_e2e_pipe_params_st *pipes);
|
||||
/* definitions for run time init of reg offsets */
|
||||
|
||||
/* CLK SRC */
|
||||
|
@ -28,6 +28,11 @@
|
||||
#include "dcn20/dcn20_resource.h"
|
||||
#include "dml/dcn32/display_mode_vba_util_32.h"
|
||||
|
||||
static bool is_dual_plane(enum surface_pixel_format format)
|
||||
{
|
||||
return format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN || format == SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA;
|
||||
}
|
||||
|
||||
/**
|
||||
* ********************************************************************************************
|
||||
* dcn32_helper_calculate_num_ways_for_subvp: Calculate number of ways needed for SubVP
|
||||
@ -239,22 +244,17 @@ bool dcn32_mpo_in_use(struct dc_state *context)
|
||||
* If there is a plane that's driven by more than 1 pipe (i.e. pipe split), then the
|
||||
* number of DET for that given plane will be split among the pipes driving that plane.
|
||||
*
|
||||
* The pipe split prediction (is_pipe_split_expected) has to work 100% of the time in
|
||||
* order for this function to work properly.
|
||||
*
|
||||
* High level algorithm:
|
||||
* 1. Split total DET among number of streams
|
||||
* 2. For each stream, split DET among the planes
|
||||
* 3. For each plane, check if pipe split is expected. If yes, split the DET for that plane
|
||||
* among the number of splits we expect (i.e. 2 [2:1] or 4 [4:1])
|
||||
* - NOTE: Make sure not to double count the pipe splits (i.e. the pipes could
|
||||
* already be split in the context).
|
||||
* 3. For each plane, check if there is a pipe split. If yes, split the DET allocation
|
||||
* among those pipes.
|
||||
* 4. Assign the DET override to the DML pipes.
|
||||
*
|
||||
* @param [in]: dc: Current DC state
|
||||
* @param [in]: context: New DC state to be programmed
|
||||
* @param [in]: pipes: Array of DML pipes
|
||||
* @param [in]: is_pipe_split_expected: Array indicating pipe split prediction for each pipe
|
||||
*
|
||||
* @return: void
|
||||
*
|
||||
@ -262,16 +262,13 @@ bool dcn32_mpo_in_use(struct dc_state *context)
|
||||
*/
|
||||
void dcn32_determine_det_override(struct dc *dc,
|
||||
struct dc_state *context,
|
||||
display_e2e_pipe_params_st *pipes,
|
||||
uint8_t *is_pipe_split_expected)
|
||||
display_e2e_pipe_params_st *pipes)
|
||||
{
|
||||
uint32_t i, j;
|
||||
uint32_t i, j, k;
|
||||
uint8_t pipe_plane_count, stream_segments, plane_segments, pipe_segments[MAX_PIPES] = {0};
|
||||
uint8_t pipe_counted[MAX_PIPES] = {0};
|
||||
uint8_t pipe_cnt = 0;
|
||||
struct dc_plane_state *current_plane = NULL;
|
||||
struct pipe_ctx *next_odm_pipe = NULL;
|
||||
struct pipe_ctx *bottom_pipe = NULL;
|
||||
uint8_t stream_count = 0;
|
||||
|
||||
for (i = 0; i < context->stream_count; i++) {
|
||||
@ -301,32 +298,21 @@ void dcn32_determine_det_override(struct dc *dc,
|
||||
pipe_plane_count++;
|
||||
pipe_counted[j] = 1;
|
||||
current_plane = context->res_ctx.pipe_ctx[j].plane_state;
|
||||
if (is_pipe_split_expected[j] != 0) {
|
||||
pipe_plane_count += is_pipe_split_expected[j];
|
||||
|
||||
next_odm_pipe = context->res_ctx.pipe_ctx[j].next_odm_pipe;
|
||||
bottom_pipe = context->res_ctx.pipe_ctx[j].bottom_pipe;
|
||||
|
||||
/* If pipe already happens to be split in context, mark as already
|
||||
* counted so we don't double count the pipe split.
|
||||
*/
|
||||
while (next_odm_pipe) {
|
||||
if (next_odm_pipe->plane_state == current_plane) {
|
||||
pipe_counted[next_odm_pipe->pipe_idx] = 1;
|
||||
pipe_segments[next_odm_pipe->pipe_idx] = plane_segments / pipe_plane_count;
|
||||
}
|
||||
next_odm_pipe = next_odm_pipe->next_odm_pipe;
|
||||
}
|
||||
|
||||
while (bottom_pipe) {
|
||||
if (bottom_pipe->plane_state == current_plane) {
|
||||
pipe_counted[bottom_pipe->pipe_idx] = 1;
|
||||
pipe_segments[bottom_pipe->pipe_idx] = plane_segments / pipe_plane_count;
|
||||
}
|
||||
bottom_pipe = bottom_pipe->bottom_pipe;
|
||||
for (k = 0; k < dc->res_pool->pipe_count; k++) {
|
||||
if (k != j && context->res_ctx.pipe_ctx[k].stream == context->streams[i] &&
|
||||
context->res_ctx.pipe_ctx[k].plane_state == current_plane) {
|
||||
pipe_plane_count++;
|
||||
pipe_counted[k] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
pipe_segments[j] = plane_segments / pipe_plane_count;
|
||||
for (k = 0; k < dc->res_pool->pipe_count; k++) {
|
||||
if (k != j && context->res_ctx.pipe_ctx[k].stream == context->streams[i] &&
|
||||
context->res_ctx.pipe_ctx[k].plane_state == current_plane) {
|
||||
pipe_segments[k] = plane_segments / pipe_plane_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -342,3 +328,38 @@ void dcn32_determine_det_override(struct dc *dc,
|
||||
pipes[i].pipe.src.det_size_override = 4 * DCN3_2_DET_SEG_SIZE; //DCN3_2_DEFAULT_DET_SIZE
|
||||
}
|
||||
}
|
||||
|
||||
void dcn32_set_det_allocations(struct dc *dc, struct dc_state *context,
|
||||
display_e2e_pipe_params_st *pipes)
|
||||
{
|
||||
int i, pipe_cnt;
|
||||
struct resource_context *res_ctx = &context->res_ctx;
|
||||
struct pipe_ctx *pipe;
|
||||
|
||||
for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
|
||||
if (!res_ctx->pipe_ctx[i].stream)
|
||||
continue;
|
||||
|
||||
pipe = &res_ctx->pipe_ctx[i];
|
||||
pipe_cnt++;
|
||||
}
|
||||
|
||||
/* For DET allocation, we don't want to use DML policy (not optimal for utilizing all
|
||||
* the DET available for each pipe). Use the DET override input to maintain our driver
|
||||
* policy.
|
||||
*/
|
||||
if (pipe_cnt == 1) {
|
||||
pipes[0].pipe.src.det_size_override = DCN3_2_MAX_DET_SIZE;
|
||||
if (pipe->plane_state && !dc->debug.disable_z9_mpc && pipe->plane_state->tiling_info.gfx9.swizzle != DC_SW_LINEAR) {
|
||||
if (!is_dual_plane(pipe->plane_state->format)) {
|
||||
pipes[0].pipe.src.det_size_override = DCN3_2_DEFAULT_DET_SIZE;
|
||||
pipes[0].pipe.src.unbounded_req_mode = true;
|
||||
if (pipe->plane_state->src_rect.width >= 5120 &&
|
||||
pipe->plane_state->src_rect.height >= 2880)
|
||||
pipes[0].pipe.src.det_size_override = 320; // 5K or higher
|
||||
}
|
||||
}
|
||||
} else
|
||||
dcn32_determine_det_override(dc, context, pipes);
|
||||
}
|
||||
|
@ -1720,8 +1720,20 @@ bool dcn32_internal_validate_bw(struct dc *dc,
|
||||
goto validate_fail;
|
||||
}
|
||||
|
||||
if (repopulate_pipes)
|
||||
if (repopulate_pipes) {
|
||||
pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, fast_validate);
|
||||
|
||||
/* repopulate_pipes = 1 means the pipes were either split or merged. In this case
|
||||
* we have to re-calculate the DET allocation and run through DML once more to
|
||||
* ensure all the params are calculated correctly. We do not need to run the
|
||||
* pipe split check again after this call (pipes are already split / merged).
|
||||
* */
|
||||
if (!fast_validate) {
|
||||
context->bw_ctx.dml.soc.allow_for_pstate_or_stutter_in_vblank_final =
|
||||
dm_prefetch_support_uclk_fclk_and_stutter_if_possible;
|
||||
vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt);
|
||||
}
|
||||
}
|
||||
*vlevel_out = vlevel;
|
||||
*pipe_cnt_out = pipe_cnt;
|
||||
|
||||
|
@ -29,11 +29,6 @@
|
||||
|
||||
#include "clk_mgr_internal.h"
|
||||
|
||||
#define DCN3_2_DEFAULT_DET_SIZE 256
|
||||
#define DCN3_2_MAX_DET_SIZE 1152
|
||||
#define DCN3_2_MIN_DET_SIZE 128
|
||||
#define DCN3_2_MIN_COMPBUF_SIZE_KB 128
|
||||
|
||||
void dcn32_build_wm_range_table_fpu(struct clk_mgr_internal *clk_mgr);
|
||||
|
||||
void dcn32_helper_populate_phantom_dlg_params(struct dc *dc,
|
||||
|
Loading…
x
Reference in New Issue
Block a user