Commit 5bf24270 authored by Dmytro Laktyushkin's avatar Dmytro Laktyushkin Committed by Alex Deucher

drm/amd/display: add odm split logic to scaling calculations

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: default avatarDmytro Laktyushkin <Dmytro.Laktyushkin@amd.com>
Reviewed-by: default avatarEric Yang <eric.yang2@amd.com>
Acked-by: default avatarMichael Strauss <Michael.Strauss@amd.com>
Acked-by: default avatarRodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 97f1fbda
...@@ -532,6 +532,35 @@ static inline void get_vp_scan_direction( ...@@ -532,6 +532,35 @@ static inline void get_vp_scan_direction(
*flip_horz_scan_dir = !*flip_horz_scan_dir; *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) static void calculate_viewport(struct pipe_ctx *pipe_ctx)
{ {
const struct dc_plane_state *plane_state = pipe_ctx->plane_state; const struct dc_plane_state *plane_state = pipe_ctx->plane_state;
...@@ -541,16 +570,16 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) ...@@ -541,16 +570,16 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx)
struct rect clip, dest; struct rect clip, dest;
int vpc_div = (data->format == PIXEL_FORMAT_420BPP8 int vpc_div = (data->format == PIXEL_FORMAT_420BPP8
|| data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1; || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1;
bool pri_split = pipe_ctx->bottom_pipe && int split_count = 0;
pipe_ctx->bottom_pipe->plane_state == pipe_ctx->plane_state; int split_idx = 0;
bool sec_split = pipe_ctx->top_pipe &&
pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state;
bool orthogonal_rotation, flip_y_start, flip_x_start; 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 || if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE ||
stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) { stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM) {
pri_split = false; split_count = 0;
sec_split = false; split_idx = 0;
} }
/* The actual clip is an intersection between stream /* The actual clip is an intersection between stream
...@@ -609,23 +638,32 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx) ...@@ -609,23 +638,32 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx)
data->viewport.height = clip.height * surf_src.height / dest.height; data->viewport.height = clip.height * surf_src.height / dest.height;
/* Handle split */ /* 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 (orthogonal_rotation) {
if (flip_y_start != pri_split) if (flip_y_start)
data->viewport.height /= 2; split_idx = split_count - split_idx;
else {
data->viewport.y += data->viewport.height / 2; epimo = split_count - data->viewport.height % (split_count + 1);
/* Ceil offset pipe */
data->viewport.height = (data->viewport.height + 1) / 2; 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 { } else {
if (flip_x_start != pri_split) if (flip_x_start)
data->viewport.width /= 2; split_idx = split_count - split_idx;
else {
data->viewport.x += data->viewport.width / 2; epimo = split_count - data->viewport.width % (split_count + 1);
/* Ceil offset pipe */
data->viewport.width = (data->viewport.width + 1) / 2; 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) ...@@ -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_plane_state *plane_state = pipe_ctx->plane_state;
const struct dc_stream_state *stream = pipe_ctx->stream; 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; struct rect surf_clip = plane_state->clip_rect;
bool pri_split = pipe_ctx->bottom_pipe && bool pri_split_tb = pipe_ctx->bottom_pipe &&
pipe_ctx->bottom_pipe->plane_state == pipe_ctx->plane_state; pipe_ctx->bottom_pipe->plane_state == pipe_ctx->plane_state &&
bool sec_split = pipe_ctx->top_pipe && stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM;
pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state; bool sec_split_tb = pipe_ctx->top_pipe &&
bool top_bottom_split = stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM; pipe_ctx->top_pipe->plane_state == pipe_ctx->plane_state &&
stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM;
pipe_ctx->plane_res.scl_data.recout.x = stream->dst.x; 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) if (stream->src.x < surf_clip.x)
pipe_ctx->plane_res.scl_data.recout.x += (surf_clip.x data->recout.x += (surf_clip.x - stream->src.x) * stream->dst.width
- stream->src.x) * stream->dst.width
/ stream->src.width; / stream->src.width;
pipe_ctx->plane_res.scl_data.recout.width = surf_clip.width * data->recout.width = surf_clip.width * stream->dst.width / stream->src.width;
stream->dst.width / stream->src.width; if (data->recout.width + data->recout.x > stream->dst.x + stream->dst.width)
if (pipe_ctx->plane_res.scl_data.recout.width + pipe_ctx->plane_res.scl_data.recout.x > data->recout.width = stream->dst.x + stream->dst.width - 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;
pipe_ctx->plane_res.scl_data.recout.y = stream->dst.y; data->recout.y = stream->dst.y;
if (stream->src.y < surf_clip.y) if (stream->src.y < surf_clip.y)
pipe_ctx->plane_res.scl_data.recout.y += (surf_clip.y data->recout.y += (surf_clip.y - stream->src.y) * stream->dst.height
- stream->src.y) * stream->dst.height
/ stream->src.height; / stream->src.height;
pipe_ctx->plane_res.scl_data.recout.height = surf_clip.height * data->recout.height = surf_clip.height * stream->dst.height / stream->src.height;
stream->dst.height / stream->src.height; if (data->recout.height + data->recout.y > stream->dst.y + stream->dst.height)
if (pipe_ctx->plane_res.scl_data.recout.height + pipe_ctx->plane_res.scl_data.recout.y > data->recout.height = stream->dst.y + stream->dst.height - 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;
/* Handle h & v split, handle rotation using viewport */ /* Handle h & v split, handle rotation using viewport */
if (sec_split && top_bottom_split) { if (sec_split_tb) {
pipe_ctx->plane_res.scl_data.recout.y += data->recout.y += data->recout.height / 2;
pipe_ctx->plane_res.scl_data.recout.height / 2;
/* Floor primary pipe, ceil 2ndary pipe */ /* Floor primary pipe, ceil 2ndary pipe */
pipe_ctx->plane_res.scl_data.recout.height = data->recout.height = (data->recout.height + 1) / 2;
(pipe_ctx->plane_res.scl_data.recout.height + 1) / 2; } else if (pri_split_tb)
} else if (pri_split && top_bottom_split) data->recout.height /= 2;
pipe_ctx->plane_res.scl_data.recout.height /= 2; else if (split_count) {
else if (sec_split) { /* extra pixels in the division remainder need to go to pipes after
pipe_ctx->plane_res.scl_data.recout.x += * the extra pixel index minus one(epimo) defined here as:
pipe_ctx->plane_res.scl_data.recout.width / 2; */
/* Ceil offset pipe */ int epimo = split_count - data->recout.width % (split_count + 1);
pipe_ctx->plane_res.scl_data.recout.width =
(pipe_ctx->plane_res.scl_data.recout.width + 1) / 2; /*no recout offset due to odm */
} else if (pri_split) if (!pipe_ctx->next_odm_pipe && !pipe_ctx->prev_odm_pipe) {
pipe_ctx->plane_res.scl_data.recout.width /= 2; 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) 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) ...@@ -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_plane_state *plane_state = pipe_ctx->plane_state;
const struct dc_stream_state *stream = pipe_ctx->stream; 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 scaler_data *data = &pipe_ctx->plane_res.scl_data;
struct rect src = pipe_ctx->plane_state->src_rect; struct rect src = pipe_ctx->plane_state->src_rect;
int recout_skip_h, recout_skip_v, surf_size_h, surf_size_v; 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) ...@@ -869,6 +908,12 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx)
* stream->dst.width / stream->src.width - * stream->dst.width / stream->src.width -
src.x * plane_state->dst_rect.width / src.width src.x * plane_state->dst_rect.width / src.width
* stream->dst.width / stream->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) recout_skip_v = data->recout.y - (stream->dst.y + (plane_state->dst_rect.y - stream->src.y)
* stream->dst.height / stream->src.height - * stream->dst.height / stream->src.height -
src.y * plane_state->dst_rect.height / 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) ...@@ -1021,6 +1066,8 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
store_h_border_left + timing->h_border_right; store_h_border_left + timing->h_border_right;
pipe_ctx->plane_res.scl_data.v_active = timing->v_addressable + pipe_ctx->plane_res.scl_data.v_active = timing->v_addressable +
timing->v_border_top + timing->v_border_bottom; 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 */ /* Taps calculations */
if (pipe_ctx->plane_res.xfm != NULL) if (pipe_ctx->plane_res.xfm != NULL)
......
...@@ -1861,20 +1861,20 @@ void dcn20_populate_dml_writeback_from_context( ...@@ -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; struct pipe_ctx *next_pipe = pipe->next_odm_pipe;
while (next_pipe) { while (next_pipe) {
odm_head_count++; odm_split_count++;
next_pipe = next_pipe->next_odm_pipe; next_pipe = next_pipe->next_odm_pipe;
} }
pipe = pipe->prev_odm_pipe; pipe = pipe->prev_odm_pipe;
while (pipe) { while (pipe) {
odm_head_count++; odm_split_count++;
pipe = pipe->prev_odm_pipe; 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( int dcn20_populate_dml_pipes_from_context(
...@@ -1956,8 +1956,8 @@ 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].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_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; 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])) { switch (get_num_odm_splits(&res_ctx->pipe_ctx[i])) {
case 2: case 1:
pipes[pipe_cnt].pipe.dest.odm_combine = dm_odm_combine_mode_2to1; pipes[pipe_cnt].pipe.dest.odm_combine = dm_odm_combine_mode_2to1;
break; break;
default: default:
...@@ -2124,18 +2124,22 @@ int dcn20_populate_dml_pipes_from_context( ...@@ -2124,18 +2124,22 @@ int dcn20_populate_dml_pipes_from_context(
pipes[pipe_cnt].pipe.src.dcc = pln->dcc.enable; 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_width = scl->recout.width;
pipes[pipe_cnt].pipe.dest.recout_height = scl->recout.height; 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; 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 = scl->recout.width;
pipes[pipe_cnt].pipe.dest.full_recout_width += if (pipes[pipe_cnt].pipe.dest.odm_combine == dm_odm_combine_mode_2to1)
res_ctx->pipe_ctx[i].bottom_pipe->plane_res.scl_data.recout.width; pipes[pipe_cnt].pipe.dest.full_recout_width *= 2;
pipes[pipe_cnt].pipe.dest.full_recout_height += else {
res_ctx->pipe_ctx[i].bottom_pipe->plane_res.scl_data.recout.height; struct pipe_ctx *split_pipe = res_ctx->pipe_ctx[i].bottom_pipe;
} 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 += while (split_pipe && split_pipe->plane_state == pln) {
res_ctx->pipe_ctx[i].top_pipe->plane_res.scl_data.recout.width; pipes[pipe_cnt].pipe.dest.full_recout_width += split_pipe->plane_res.scl_data.recout.width;
pipes[pipe_cnt].pipe.dest.full_recout_height += split_pipe = split_pipe->bottom_pipe;
res_ctx->pipe_ctx[i].top_pipe->plane_res.scl_data.recout.height; }
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; pipes[pipe_cnt].pipe.scale_ratio_depth.lb_depth = dm_lb_16;
......
...@@ -49,6 +49,7 @@ unsigned int dcn20_calc_max_scaled_time( ...@@ -49,6 +49,7 @@ unsigned int dcn20_calc_max_scaled_time(
unsigned int time_per_pixel, unsigned int time_per_pixel,
enum mmhubbub_wbif_mode mode, enum mmhubbub_wbif_mode mode,
unsigned int urgent_watermark); unsigned int urgent_watermark);
int get_num_odm_splits(struct pipe_ctx *pipe);
int dcn20_populate_dml_pipes_from_context( int dcn20_populate_dml_pipes_from_context(
struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes); struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes);
struct pipe_ctx *dcn20_acquire_idle_pipe_for_layer( struct pipe_ctx *dcn20_acquire_idle_pipe_for_layer(
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment