From: Dmytro Laktyushkin <Dmytro.Laktyushkin@xxxxxxx> Currently odm scaling calculations are only done when adding initial odm pipe. Any scaling re-calculations will mess up odm because of this. This change resolves the problem by updating scaling split logic to handle odm. Signed-off-by: Dmytro Laktyushkin <Dmytro.Laktyushkin@xxxxxxx> Reviewed-by: Eric Yang <eric.yang2@xxxxxxx> Acked-by: Michael Strauss <Michael.Strauss@xxxxxxx> Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@xxxxxxx> --- .../gpu/drm/amd/display/dc/core/dc_resource.c | 171 +++++++++++------- .../drm/amd/display/dc/dcn20/dcn20_resource.c | 40 ++-- .../drm/amd/display/dc/dcn20/dcn20_resource.h | 1 + 3 files changed, 132 insertions(+), 80 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index cd80d8249d14..a65a1e7820d6 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -532,6 +532,35 @@ static inline void get_vp_scan_direction( *flip_horz_scan_dir = !*flip_horz_scan_dir; } +static void calculate_split_count_and_index(struct pipe_ctx *pipe_ctx, int *split_count, int *split_idx) +{ + *split_count = get_num_odm_splits(pipe_ctx); + *split_idx = 0; + if (*split_count == 0) { + /*Check for mpc split*/ + struct pipe_ctx *split_pipe = pipe_ctx->top_pipe; + + while (split_pipe && split_pipe->plane_state == pipe_ctx->plane_state) { + (*split_idx)++; + (*split_count)++; + split_pipe = split_pipe->top_pipe; + } + split_pipe = pipe_ctx->bottom_pipe; + while (split_pipe && split_pipe->plane_state == pipe_ctx->plane_state) { + (*split_count)++; + split_pipe = split_pipe->bottom_pipe; + } + } else { + /*Get odm split index*/ + struct pipe_ctx *split_pipe = pipe_ctx->prev_odm_pipe; + + while (split_pipe) { + (*split_idx)++; + split_pipe = split_pipe->prev_odm_pipe; + } + } +} + static void calculate_viewport(struct pipe_ctx *pipe_ctx) { const struct dc_plane_state *plane_state = pipe_ctx->plane_state; @@ -541,16 +570,16 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) struct rect clip, dest; int vpc_div = (data->format == PIXEL_FORMAT_420BPP8 || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1; - bool pri_split = pipe_ctx->bottom_pipe && - pipe_ctx->bottom_pipe->plane_state == pipe_ctx->plane_state; - bool sec_split = pipe_ctx->top_pipe && - pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state; + int split_count = 0; + int split_idx = 0; bool orthogonal_rotation, flip_y_start, flip_x_start; + calculate_split_count_and_index(pipe_ctx, &split_count, &split_idx); + if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE || stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) { - pri_split = false; - sec_split = false; + split_count = 0; + split_idx = 0; } /* The actual clip is an intersection between stream @@ -609,23 +638,32 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) data->viewport.height = clip.height * surf_src.height / dest.height; /* Handle split */ - if (pri_split || sec_split) { + if (split_count) { + /* extra pixels in the division remainder need to go to pipes after + * the extra pixel index minus one(epimo) defined here as: + */ + int epimo = 0; + if (orthogonal_rotation) { - if (flip_y_start != pri_split) - data->viewport.height /= 2; - else { - data->viewport.y += data->viewport.height / 2; - /* Ceil offset pipe */ - data->viewport.height = (data->viewport.height + 1) / 2; - } + if (flip_y_start) + split_idx = split_count - split_idx; + + epimo = split_count - data->viewport.height % (split_count + 1); + + data->viewport.y += (data->viewport.height / (split_count + 1)) * split_idx; + if (split_idx > epimo) + data->viewport.y += split_idx - epimo - 1; + data->viewport.height = data->viewport.height / (split_count + 1) + (split_idx > epimo ? 1 : 0); } else { - if (flip_x_start != pri_split) - data->viewport.width /= 2; - else { - data->viewport.x += data->viewport.width / 2; - /* Ceil offset pipe */ - data->viewport.width = (data->viewport.width + 1) / 2; - } + if (flip_x_start) + split_idx = split_count - split_idx; + + epimo = split_count - data->viewport.width % (split_count + 1); + + data->viewport.x += (data->viewport.width / (split_count + 1)) * split_idx; + if (split_idx > epimo) + data->viewport.x += split_idx - epimo - 1; + data->viewport.width = data->viewport.width / (split_count + 1) + (split_idx > epimo ? 1 : 0); } } @@ -644,58 +682,58 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx) { const struct dc_plane_state *plane_state = pipe_ctx->plane_state; const struct dc_stream_state *stream = pipe_ctx->stream; + struct scaler_data *data = &pipe_ctx->plane_res.scl_data; struct rect surf_clip = plane_state->clip_rect; - bool pri_split = pipe_ctx->bottom_pipe && - pipe_ctx->bottom_pipe->plane_state == pipe_ctx->plane_state; - bool sec_split = pipe_ctx->top_pipe && - pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state; - bool top_bottom_split = stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM; - - pipe_ctx->plane_res.scl_data.recout.x = stream->dst.x; + bool pri_split_tb = pipe_ctx->bottom_pipe && + pipe_ctx->bottom_pipe->plane_state == pipe_ctx->plane_state && + stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM; + bool sec_split_tb = pipe_ctx->top_pipe && + pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state && + stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM; + int split_count = 0; + int split_idx = 0; + + calculate_split_count_and_index(pipe_ctx, &split_count, &split_idx); + + data->recout.x = stream->dst.x; if (stream->src.x < surf_clip.x) - pipe_ctx->plane_res.scl_data.recout.x += (surf_clip.x - - stream->src.x) * stream->dst.width + data->recout.x += (surf_clip.x - stream->src.x) * stream->dst.width / stream->src.width; - pipe_ctx->plane_res.scl_data.recout.width = surf_clip.width * - stream->dst.width / stream->src.width; - if (pipe_ctx->plane_res.scl_data.recout.width + pipe_ctx->plane_res.scl_data.recout.x > - stream->dst.x + stream->dst.width) - pipe_ctx->plane_res.scl_data.recout.width = - stream->dst.x + stream->dst.width - - pipe_ctx->plane_res.scl_data.recout.x; + data->recout.width = surf_clip.width * stream->dst.width / stream->src.width; + if (data->recout.width + data->recout.x > stream->dst.x + stream->dst.width) + data->recout.width = stream->dst.x + stream->dst.width - data->recout.x; - pipe_ctx->plane_res.scl_data.recout.y = stream->dst.y; + data->recout.y = stream->dst.y; if (stream->src.y < surf_clip.y) - pipe_ctx->plane_res.scl_data.recout.y += (surf_clip.y - - stream->src.y) * stream->dst.height + data->recout.y += (surf_clip.y - stream->src.y) * stream->dst.height / stream->src.height; - pipe_ctx->plane_res.scl_data.recout.height = surf_clip.height * - stream->dst.height / stream->src.height; - if (pipe_ctx->plane_res.scl_data.recout.height + pipe_ctx->plane_res.scl_data.recout.y > - stream->dst.y + stream->dst.height) - pipe_ctx->plane_res.scl_data.recout.height = - stream->dst.y + stream->dst.height - - pipe_ctx->plane_res.scl_data.recout.y; + data->recout.height = surf_clip.height * stream->dst.height / stream->src.height; + if (data->recout.height + data->recout.y > stream->dst.y + stream->dst.height) + data->recout.height = stream->dst.y + stream->dst.height - data->recout.y; /* Handle h & v split, handle rotation using viewport */ - if (sec_split && top_bottom_split) { - pipe_ctx->plane_res.scl_data.recout.y += - pipe_ctx->plane_res.scl_data.recout.height / 2; + if (sec_split_tb) { + data->recout.y += data->recout.height / 2; /* Floor primary pipe, ceil 2ndary pipe */ - pipe_ctx->plane_res.scl_data.recout.height = - (pipe_ctx->plane_res.scl_data.recout.height + 1) / 2; - } else if (pri_split && top_bottom_split) - pipe_ctx->plane_res.scl_data.recout.height /= 2; - else if (sec_split) { - pipe_ctx->plane_res.scl_data.recout.x += - pipe_ctx->plane_res.scl_data.recout.width / 2; - /* Ceil offset pipe */ - pipe_ctx->plane_res.scl_data.recout.width = - (pipe_ctx->plane_res.scl_data.recout.width + 1) / 2; - } else if (pri_split) - pipe_ctx->plane_res.scl_data.recout.width /= 2; + data->recout.height = (data->recout.height + 1) / 2; + } else if (pri_split_tb) + data->recout.height /= 2; + else if (split_count) { + /* extra pixels in the division remainder need to go to pipes after + * the extra pixel index minus one(epimo) defined here as: + */ + int epimo = split_count - data->recout.width % (split_count + 1); + + /*no recout offset due to odm */ + if (!pipe_ctx->next_odm_pipe && !pipe_ctx->prev_odm_pipe) { + data->recout.x += (data->recout.width / (split_count + 1)) * split_idx; + if (split_idx > epimo) + data->recout.x += split_idx - epimo - 1; + } + data->recout.width = data->recout.width / (split_count + 1) + (split_idx > epimo ? 1 : 0); + } } static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) @@ -832,6 +870,7 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx) { const struct dc_plane_state *plane_state = pipe_ctx->plane_state; const struct dc_stream_state *stream = pipe_ctx->stream; + struct pipe_ctx *odm_pipe = pipe_ctx->prev_odm_pipe; struct scaler_data *data = &pipe_ctx->plane_res.scl_data; struct rect src = pipe_ctx->plane_state->src_rect; int recout_skip_h, recout_skip_v, surf_size_h, surf_size_v; @@ -869,6 +908,12 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx) * stream->dst.width / stream->src.width - src.x * plane_state->dst_rect.width / src.width * stream->dst.width / stream->src.width); + /*modified recout_skip_h calculation due to odm having no recout offset caused by split*/ + while (odm_pipe) { + recout_skip_h += odm_pipe->plane_res.scl_data.recout.width + odm_pipe->plane_res.scl_data.recout.x; + odm_pipe = odm_pipe->prev_odm_pipe; + } + recout_skip_v = data->recout.y - (stream->dst.y + (plane_state->dst_rect.y - stream->src.y) * stream->dst.height / stream->src.height - src.y * plane_state->dst_rect.height / src.height @@ -1021,6 +1066,8 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) store_h_border_left + timing->h_border_right; pipe_ctx->plane_res.scl_data.v_active = timing->v_addressable + timing->v_border_top + timing->v_border_bottom; + if (pipe_ctx->next_odm_pipe || pipe_ctx->prev_odm_pipe) + pipe_ctx->plane_res.scl_data.h_active /= get_num_odm_splits(pipe_ctx) + 1; /* Taps calculations */ if (pipe_ctx->plane_res.xfm != NULL) diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c index 85f90f3e24cb..39026df56fa6 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c @@ -1861,20 +1861,20 @@ void dcn20_populate_dml_writeback_from_context( } -static int get_num_odm_heads(struct pipe_ctx *pipe) +int get_num_odm_splits(struct pipe_ctx *pipe) { - int odm_head_count = 0; + int odm_split_count = 0; struct pipe_ctx *next_pipe = pipe->next_odm_pipe; while (next_pipe) { - odm_head_count++; + odm_split_count++; next_pipe = next_pipe->next_odm_pipe; } pipe = pipe->prev_odm_pipe; while (pipe) { - odm_head_count++; + odm_split_count++; pipe = pipe->prev_odm_pipe; } - return odm_head_count ? odm_head_count + 1 : 0; + return odm_split_count; } int dcn20_populate_dml_pipes_from_context( @@ -1956,8 +1956,8 @@ int dcn20_populate_dml_pipes_from_context( pipes[pipe_cnt].dout.dp_lanes = 4; pipes[pipe_cnt].pipe.dest.vtotal_min = res_ctx->pipe_ctx[i].stream->adjust.v_total_min; pipes[pipe_cnt].pipe.dest.vtotal_max = res_ctx->pipe_ctx[i].stream->adjust.v_total_max; - switch (get_num_odm_heads(&res_ctx->pipe_ctx[i])) { - case 2: + switch (get_num_odm_splits(&res_ctx->pipe_ctx[i])) { + case 1: pipes[pipe_cnt].pipe.dest.odm_combine = dm_odm_combine_mode_2to1; break; default: @@ -2124,18 +2124,22 @@ int dcn20_populate_dml_pipes_from_context( pipes[pipe_cnt].pipe.src.dcc = pln->dcc.enable; pipes[pipe_cnt].pipe.dest.recout_width = scl->recout.width; pipes[pipe_cnt].pipe.dest.recout_height = scl->recout.height; - pipes[pipe_cnt].pipe.dest.full_recout_width = scl->recout.width; pipes[pipe_cnt].pipe.dest.full_recout_height = scl->recout.height; - if (res_ctx->pipe_ctx[i].bottom_pipe && res_ctx->pipe_ctx[i].bottom_pipe->plane_state == pln) { - pipes[pipe_cnt].pipe.dest.full_recout_width += - res_ctx->pipe_ctx[i].bottom_pipe->plane_res.scl_data.recout.width; - pipes[pipe_cnt].pipe.dest.full_recout_height += - res_ctx->pipe_ctx[i].bottom_pipe->plane_res.scl_data.recout.height; - } else if (res_ctx->pipe_ctx[i].top_pipe && res_ctx->pipe_ctx[i].top_pipe->plane_state == pln) { - pipes[pipe_cnt].pipe.dest.full_recout_width += - res_ctx->pipe_ctx[i].top_pipe->plane_res.scl_data.recout.width; - pipes[pipe_cnt].pipe.dest.full_recout_height += - res_ctx->pipe_ctx[i].top_pipe->plane_res.scl_data.recout.height; + pipes[pipe_cnt].pipe.dest.full_recout_width = scl->recout.width; + if (pipes[pipe_cnt].pipe.dest.odm_combine == dm_odm_combine_mode_2to1) + pipes[pipe_cnt].pipe.dest.full_recout_width *= 2; + else { + struct pipe_ctx *split_pipe = res_ctx->pipe_ctx[i].bottom_pipe; + + while (split_pipe && split_pipe->plane_state == pln) { + pipes[pipe_cnt].pipe.dest.full_recout_width += split_pipe->plane_res.scl_data.recout.width; + split_pipe = split_pipe->bottom_pipe; + } + split_pipe = res_ctx->pipe_ctx[i].top_pipe; + while (split_pipe && split_pipe->plane_state == pln) { + pipes[pipe_cnt].pipe.dest.full_recout_width += split_pipe->plane_res.scl_data.recout.width; + split_pipe = split_pipe->top_pipe; + } } pipes[pipe_cnt].pipe.scale_ratio_depth.lb_depth = dm_lb_16; diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h index f5893840b79b..5180088ab6bc 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h @@ -49,6 +49,7 @@ unsigned int dcn20_calc_max_scaled_time( unsigned int time_per_pixel, enum mmhubbub_wbif_mode mode, unsigned int urgent_watermark); +int get_num_odm_splits(struct pipe_ctx *pipe); int dcn20_populate_dml_pipes_from_context( struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes); struct pipe_ctx *dcn20_acquire_idle_pipe_for_layer( -- 2.25.0 _______________________________________________ amd-gfx mailing list amd-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/amd-gfx