diff options
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/0266-drm-amd-display-add-init-calculation-to-scaler-param.patch')
-rw-r--r-- | meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/0266-drm-amd-display-add-init-calculation-to-scaler-param.patch | 424 |
1 files changed, 424 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/0266-drm-amd-display-add-init-calculation-to-scaler-param.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/0266-drm-amd-display-add-init-calculation-to-scaler-param.patch new file mode 100644 index 00000000..6a8dd24d --- /dev/null +++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/0266-drm-amd-display-add-init-calculation-to-scaler-param.patch @@ -0,0 +1,424 @@ +From f14046da36f7cc2e2e71642956674f716c0f8553 Mon Sep 17 00:00:00 2001 +From: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com> +Date: Wed, 1 Mar 2017 18:27:17 -0500 +Subject: [PATCH 0266/4131] drm/amd/display: add init calculation to scaler + params + +Signed-off-by: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com> +Acked-by: Harry Wentland <Harry.Wentland@amd.com> +Reviewed-by: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com> +Signed-off-by: Alex Deucher <alexander.deucher@amd.com> +--- + drivers/gpu/drm/amd/display/dc/core/dc.c | 5 +- + drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 245 ++++++++++++++++++--- + .../amd/display/dc/dce110/dce110_hw_sequencer.c | 1 + + drivers/gpu/drm/amd/display/dc/inc/hw/transform.h | 11 + + drivers/gpu/drm/amd/display/dc/inc/resource.h | 4 +- + 5 files changed, 229 insertions(+), 37 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c +index edcb731..b9ca968 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c +@@ -971,8 +971,7 @@ bool dc_pre_update_surfaces_to_stream( + DC_SURFACE_TO_CORE(new_surfaces[i])) + continue; + +- resource_build_scaling_params( +- new_surfaces[i], &context->res_ctx.pipe_ctx[j]); ++ resource_build_scaling_params(&context->res_ctx.pipe_ctx[j]); + } + + if (!core_dc->res_pool->funcs->validate_bandwidth(core_dc, context)) { +@@ -1364,7 +1363,7 @@ void dc_update_surfaces_for_stream(struct dc *dc, + if (pipe_ctx->surface != surface) + continue; + +- resource_build_scaling_params(updates[i].surface, pipe_ctx); ++ resource_build_scaling_params(pipe_ctx); + } + } + +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 3260194..d4b338f 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +@@ -401,15 +401,17 @@ static void rect_swap_helper(struct rect *rect) + rect->y = temp; + } + +-static void calculate_viewport( +- const struct dc_surface *surface, +- struct pipe_ctx *pipe_ctx) ++static void calculate_viewport(struct pipe_ctx *pipe_ctx) + { ++ const struct dc_surface *surface = &pipe_ctx->surface->public; ++ struct scaler_data *data = &pipe_ctx->scl_data; + struct rect stream_src = pipe_ctx->stream->public.src; + struct rect src = surface->src_rect; + struct rect dst = surface->dst_rect; + struct rect surface_clip = surface->clip_rect; + struct rect clip = {0}; ++ int vpc_div = (data->format == PIXEL_FORMAT_420BPP12 ++ || data->format == PIXEL_FORMAT_420BPP15) ? 2 : 1; + + + if (surface->rotation == ROTATION_ANGLE_90 || +@@ -442,27 +444,45 @@ static void calculate_viewport( + /* offset = src.ofs + (clip.ofs - dst.ofs) * scl_ratio + * num_pixels = clip.num_pix * scl_ratio + */ +- pipe_ctx->scl_data.viewport.x = src.x + (clip.x - dst.x) * ++ data->viewport.x = src.x + (clip.x - dst.x) * + src.width / dst.width; +- pipe_ctx->scl_data.viewport.width = clip.width * ++ data->viewport.width = clip.width * + src.width / dst.width; + +- pipe_ctx->scl_data.viewport.y = src.y + (clip.y - dst.y) * ++ data->viewport.y = src.y + (clip.y - dst.y) * + src.height / dst.height; +- pipe_ctx->scl_data.viewport.height = clip.height * ++ data->viewport.height = clip.height * + src.height / dst.height; + +- /* Minimum viewport such that 420/422 chroma vp is non 0 */ +- if (pipe_ctx->scl_data.viewport.width < 2) +- pipe_ctx->scl_data.viewport.width = 2; +- if (pipe_ctx->scl_data.viewport.height < 2) +- pipe_ctx->scl_data.viewport.height = 2; ++ /* Round down, compensate in init */ ++ data->viewport_c.x = data->viewport.x / vpc_div; ++ data->viewport_c.y = data->viewport.y / vpc_div; ++ data->inits.h_c = (data->viewport.x % vpc_div) != 0 ? ++ dal_fixed31_32_half : dal_fixed31_32_zero; ++ data->inits.v_c = (data->viewport.y % vpc_div) != 0 ? ++ dal_fixed31_32_half : dal_fixed31_32_zero; ++ /* Round up, assume original video size always even dimensions */ ++ data->viewport_c.width = (data->viewport.width + vpc_div - 1) / vpc_div; ++ data->viewport_c.height = (data->viewport.height + vpc_div - 1) / vpc_div; ++ ++ /* Handle hsplit */ ++ if (pipe_ctx->top_pipe && pipe_ctx->top_pipe->surface == pipe_ctx->surface) { ++ data->viewport.width /= 2; ++ data->viewport_c.width /= 2; ++ data->viewport.x += data->viewport.width; ++ data->viewport_c.x += data->viewport_c.width; ++ /* Floor primary pipe, ceil 2ndary pipe */ ++ data->viewport.width += data->viewport.width % 2; ++ data->viewport_c.width += data->viewport_c.width % 2; ++ } else if (pipe_ctx->bottom_pipe && pipe_ctx->bottom_pipe->surface == pipe_ctx->surface) { ++ data->viewport.width /= 2; ++ data->viewport_c.width /= 2; ++ } + } + +-static void calculate_recout( +- const struct dc_surface *surface, +- struct pipe_ctx *pipe_ctx) ++static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip) + { ++ const struct dc_surface *surface = &pipe_ctx->surface->public; + struct core_stream *stream = pipe_ctx->stream; + struct rect clip = surface->clip_rect; + +@@ -493,12 +513,26 @@ static void calculate_recout( + pipe_ctx->scl_data.recout.height = + stream->public.dst.y + stream->public.dst.height + - pipe_ctx->scl_data.recout.y; ++ ++ /* Handle hsplit */ ++ if (pipe_ctx->top_pipe && pipe_ctx->top_pipe->surface == pipe_ctx->surface) { ++ pipe_ctx->scl_data.recout.width /= 2; ++ pipe_ctx->scl_data.recout.x += pipe_ctx->scl_data.recout.width; ++ /* Floor primary pipe, ceil 2ndary pipe */ ++ pipe_ctx->scl_data.recout.width += pipe_ctx->scl_data.recout.width % 2; ++ } else if (pipe_ctx->bottom_pipe && pipe_ctx->bottom_pipe->surface == pipe_ctx->surface) { ++ pipe_ctx->scl_data.recout.width /= 2; ++ } ++ ++ recout_skip->width = pipe_ctx->scl_data.recout.x - stream->public.dst.x - ++ surface->dst_rect.x * stream->public.dst.width / stream->public.src.width; ++ recout_skip->height = pipe_ctx->scl_data.recout.y - stream->public.dst.y - ++ surface->dst_rect.y * stream->public.dst.height / stream->public.src.height; + } + +-static void calculate_scaling_ratios( +- const struct dc_surface *surface, +- struct pipe_ctx *pipe_ctx) ++static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx) + { ++ const struct dc_surface *surface = &pipe_ctx->surface->public; + struct core_stream *stream = pipe_ctx->stream; + const uint32_t in_w = stream->public.src.width; + const uint32_t in_h = stream->public.src.height; +@@ -525,31 +559,179 @@ static void calculate_scaling_ratios( + pipe_ctx->scl_data.ratios.horz_c = pipe_ctx->scl_data.ratios.horz; + pipe_ctx->scl_data.ratios.vert_c = pipe_ctx->scl_data.ratios.vert; + +- if (pipe_ctx->scl_data.format == PIXEL_FORMAT_420BPP12) { ++ if (pipe_ctx->scl_data.format == PIXEL_FORMAT_420BPP12 ++ || pipe_ctx->scl_data.format == PIXEL_FORMAT_420BPP15) { + pipe_ctx->scl_data.ratios.horz_c.value /= 2; + pipe_ctx->scl_data.ratios.vert_c.value /= 2; + } + } + +-bool resource_build_scaling_params( +- const struct dc_surface *surface, +- struct pipe_ctx *pipe_ctx) ++static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *recout_skip) + { +- bool res; ++ struct scaler_data *data = &pipe_ctx->scl_data; ++ struct rect src = pipe_ctx->surface->public.src_rect; ++ int vpc_div = (data->format == PIXEL_FORMAT_420BPP12 ++ || data->format == PIXEL_FORMAT_420BPP15) ? 2 : 1; ++ ++ /* ++ * Init calculated according to formula: ++ * init = (scaling_ratio + number_of_taps + 1) / 2 ++ * init_bot = init + scaling_ratio ++ * init_c = init + truncated_vp_c_offset(from calculate viewport) ++ */ ++ data->inits.h = dal_fixed31_32_div_int( ++ dal_fixed31_32_add_int(data->ratios.horz, data->taps.h_taps + 1), 2); ++ ++ data->inits.h_c = dal_fixed31_32_add(data->inits.h_c, dal_fixed31_32_div_int( ++ dal_fixed31_32_add_int(data->ratios.horz_c, data->taps.h_taps_c + 1), 2)); ++ ++ data->inits.v = dal_fixed31_32_div_int( ++ dal_fixed31_32_add_int(data->ratios.vert, data->taps.v_taps + 1), 2); ++ ++ data->inits.v_c = dal_fixed31_32_add(data->inits.v_c, dal_fixed31_32_div_int( ++ dal_fixed31_32_add_int(data->ratios.vert_c, data->taps.v_taps_c + 1), 2)); ++ ++ ++ /* Adjust for viewport end clip-off */ ++ if ((data->viewport.x + data->viewport.width) < (src.x + src.width)) { ++ int vp_clip = src.x + src.width - data->viewport.width - data->viewport.x; ++ int int_part = dal_fixed31_32_floor(data->inits.h); ++ ++ data->viewport.width += int_part < vp_clip ? int_part : vp_clip; ++ } ++ if ((data->viewport.y + data->viewport.height) < (src.y + src.height)) { ++ int vp_clip = src.y + src.height - data->viewport.height - data->viewport.y; ++ int int_part = dal_fixed31_32_floor(data->inits.v); ++ ++ data->viewport.height += int_part < vp_clip ? int_part : vp_clip; ++ } ++ if ((data->viewport_c.x + data->viewport_c.width) < (src.x + src.width) / vpc_div) { ++ int vp_clip = (src.x + src.width) / vpc_div - ++ data->viewport_c.width - data->viewport_c.x; ++ int int_part = dal_fixed31_32_floor(data->inits.h_c); ++ ++ data->viewport_c.width += int_part < vp_clip ? int_part : vp_clip; ++ } ++ if ((data->viewport_c.y + data->viewport_c.height) < (src.y + src.height) / vpc_div) { ++ int vp_clip = (src.y + src.height) / vpc_div - ++ data->viewport_c.height - data->viewport_c.y; ++ int int_part = dal_fixed31_32_floor(data->inits.v_c); ++ ++ data->viewport_c.height += int_part < vp_clip ? int_part : vp_clip; ++ } ++ ++ /* Adjust for non-0 viewport offset */ ++ if (data->viewport.x) { ++ int int_part; ++ ++ data->inits.h = dal_fixed31_32_add(data->inits.h, dal_fixed31_32_mul_int( ++ data->ratios.horz, recout_skip->width)); ++ int_part = dal_fixed31_32_floor(data->inits.h) - data->viewport.x; ++ if (int_part < data->taps.h_taps) { ++ int int_adj = data->viewport.x >= (data->taps.h_taps - int_part) ? ++ (data->taps.h_taps - int_part) : data->viewport.x; ++ data->viewport.x -= int_adj; ++ data->viewport.width += int_adj; ++ int_part += int_adj; ++ } else if (int_part > data->taps.h_taps) { ++ data->viewport.x += int_part - data->taps.h_taps; ++ data->viewport.width -= int_part - data->taps.h_taps; ++ int_part = data->taps.h_taps; ++ } ++ data->inits.h.value &= 0xffffffff; ++ data->inits.h = dal_fixed31_32_add_int(data->inits.h, int_part); ++ } ++ ++ if (data->viewport_c.x) { ++ int int_part; ++ ++ data->inits.h_c = dal_fixed31_32_add(data->inits.h_c, dal_fixed31_32_mul_int( ++ data->ratios.horz_c, recout_skip->width)); ++ int_part = dal_fixed31_32_floor(data->inits.h_c) - data->viewport_c.x; ++ if (int_part < data->taps.h_taps_c) { ++ int int_adj = data->viewport_c.x >= (data->taps.h_taps_c - int_part) ? ++ (data->taps.h_taps_c - int_part) : data->viewport_c.x; ++ data->viewport_c.x -= int_adj; ++ data->viewport_c.width += int_adj; ++ int_part += int_adj; ++ } else if (int_part > data->taps.h_taps_c) { ++ data->viewport_c.x += int_part - data->taps.h_taps_c; ++ data->viewport_c.width -= int_part - data->taps.h_taps_c; ++ int_part = data->taps.h_taps_c; ++ } ++ data->inits.h_c.value &= 0xffffffff; ++ data->inits.h_c = dal_fixed31_32_add_int(data->inits.h_c, int_part); ++ } ++ ++ if (data->viewport.y) { ++ int int_part; ++ ++ data->inits.v = dal_fixed31_32_add(data->inits.v, dal_fixed31_32_mul_int( ++ data->ratios.vert, recout_skip->height)); ++ int_part = dal_fixed31_32_floor(data->inits.v) - data->viewport.y; ++ if (int_part < data->taps.v_taps) { ++ int int_adj = data->viewport.y >= (data->taps.v_taps - int_part) ? ++ (data->taps.v_taps - int_part) : data->viewport.y; ++ data->viewport.y -= int_adj; ++ data->viewport.height += int_adj; ++ int_part += int_adj; ++ } else if (int_part > data->taps.v_taps) { ++ data->viewport.y += int_part - data->taps.v_taps; ++ data->viewport.height -= int_part - data->taps.v_taps; ++ int_part = data->taps.v_taps; ++ } ++ data->inits.v.value &= 0xffffffff; ++ data->inits.v = dal_fixed31_32_add_int(data->inits.v, int_part); ++ } ++ ++ if (data->viewport_c.y) { ++ int int_part; ++ ++ data->inits.v_c = dal_fixed31_32_add(data->inits.v_c, dal_fixed31_32_mul_int( ++ data->ratios.vert_c, recout_skip->height)); ++ int_part = dal_fixed31_32_floor(data->inits.v_c) - data->viewport_c.y; ++ if (int_part < data->taps.v_taps_c) { ++ int int_adj = data->viewport_c.y >= (data->taps.v_taps_c - int_part) ? ++ (data->taps.v_taps_c - int_part) : data->viewport_c.y; ++ data->viewport_c.y -= int_adj; ++ data->viewport_c.height += int_adj; ++ int_part += int_adj; ++ } else if (int_part > data->taps.v_taps_c) { ++ data->viewport_c.y += int_part - data->taps.v_taps_c; ++ data->viewport_c.height -= int_part - data->taps.v_taps_c; ++ int_part = data->taps.v_taps_c; ++ } ++ data->inits.v_c.value &= 0xffffffff; ++ data->inits.v_c = dal_fixed31_32_add_int(data->inits.v_c, int_part); ++ } ++ ++ /* Interlaced inits based on final vert inits */ ++ data->inits.v_bot = dal_fixed31_32_add(data->inits.v, data->ratios.vert); ++ data->inits.v_c_bot = dal_fixed31_32_add(data->inits.v_c, data->ratios.vert_c); ++} ++ ++bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) ++{ ++ const struct dc_surface *surface = &pipe_ctx->surface->public; + struct dc_crtc_timing *timing = &pipe_ctx->stream->public.timing; ++ struct view recout_skip = { 0 }; ++ bool res = false; ++ + /* Important: scaling ratio calculation requires pixel format, + * lb depth calculation requires recout and taps require scaling ratios. ++ * Inits require viewport, taps, ratios and recout of split pipe + */ +- pipe_ctx->scl_data.format = convert_pixel_format_to_dalsurface(surface->format); ++ pipe_ctx->scl_data.format = convert_pixel_format_to_dalsurface( ++ pipe_ctx->surface->public.format); ++ ++ calculate_scaling_ratios(pipe_ctx); + +- calculate_viewport(surface, pipe_ctx); ++ calculate_viewport(pipe_ctx); + + if (pipe_ctx->scl_data.viewport.height < 16 || pipe_ctx->scl_data.viewport.width < 16) + return false; + +- calculate_scaling_ratios(surface, pipe_ctx); +- +- calculate_recout(surface, pipe_ctx); ++ calculate_recout(pipe_ctx, &recout_skip); + + /** + * Setting line buffer pixel depth to 24bpp yields banding +@@ -572,6 +754,9 @@ bool resource_build_scaling_params( + pipe_ctx->xfm, &pipe_ctx->scl_data, &surface->scaling_quality); + } + ++ if (res) ++ calculate_inits_and_adj_vp(pipe_ctx, &recout_skip); ++ + dm_logger_write(pipe_ctx->stream->ctx->logger, LOG_SCALER, + "%s: Viewport:\nheight:%d width:%d x:%d " + "y:%d\n dst_rect:\nheight:%d width:%d x:%d " +@@ -599,9 +784,7 @@ enum dc_status resource_build_scaling_params_for_context( + for (i = 0; i < MAX_PIPES; i++) { + if (context->res_ctx.pipe_ctx[i].surface != NULL && + context->res_ctx.pipe_ctx[i].stream != NULL) +- if (!resource_build_scaling_params( +- &context->res_ctx.pipe_ctx[i].surface->public, +- &context->res_ctx.pipe_ctx[i])) ++ if (!resource_build_scaling_params(&context->res_ctx.pipe_ctx[i])) + return DC_FAIL_SCALING; + } + +diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +index d9dcb37..041830e 100644 +--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c ++++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +@@ -927,6 +927,7 @@ static void get_surface_visual_confirm_color(const struct pipe_ctx *pipe_ctx, + color->color_b_cb = color_value; + break; + case PIXEL_FORMAT_420BPP12: ++ case PIXEL_FORMAT_420BPP15: + /* set boarder color to green */ + color->color_g_y = color_value; + break; +diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h +index 9c5cb0e..8325a0a 100644 +--- a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h ++++ b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h +@@ -147,13 +147,24 @@ struct line_buffer_params { + enum lb_pixel_depth depth; + }; + ++struct scl_inits { ++ struct fixed31_32 h; ++ struct fixed31_32 h_c; ++ struct fixed31_32 v; ++ struct fixed31_32 v_bot; ++ struct fixed31_32 v_c; ++ struct fixed31_32 v_c_bot; ++}; ++ + struct scaler_data { + int h_active; + int v_active; + struct scaling_taps taps; + struct rect viewport; ++ struct rect viewport_c; + struct rect recout; + struct scaling_ratios ratios; ++ struct scl_inits inits; + struct sharpness_adj sharpness; + enum pixel_format format; + struct line_buffer_params lb_params; +diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h +index d96c64b..eb9c966 100644 +--- a/drivers/gpu/drm/amd/display/dc/inc/resource.h ++++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h +@@ -82,9 +82,7 @@ enum dc_status resource_map_pool_resources( + const struct core_dc *dc, + struct validate_context *context); + +-bool resource_build_scaling_params( +- const struct dc_surface *surface, +- struct pipe_ctx *pipe_ctx); ++bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx); + + enum dc_status resource_build_scaling_params_for_context( + const struct core_dc *dc, +-- +2.7.4 + |