aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/linux-yocto-4.14.71/4528-drm-amd-display-upgrade-scaler-math.patch
diff options
context:
space:
mode:
Diffstat (limited to 'common/recipes-kernel/linux/linux-yocto-4.14.71/4528-drm-amd-display-upgrade-scaler-math.patch')
-rw-r--r--common/recipes-kernel/linux/linux-yocto-4.14.71/4528-drm-amd-display-upgrade-scaler-math.patch525
1 files changed, 525 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/linux-yocto-4.14.71/4528-drm-amd-display-upgrade-scaler-math.patch b/common/recipes-kernel/linux/linux-yocto-4.14.71/4528-drm-amd-display-upgrade-scaler-math.patch
new file mode 100644
index 00000000..364cb4a5
--- /dev/null
+++ b/common/recipes-kernel/linux/linux-yocto-4.14.71/4528-drm-amd-display-upgrade-scaler-math.patch
@@ -0,0 +1,525 @@
+From 28b39973cdb2d45d57e08e1c08e06d84b904bcdc Mon Sep 17 00:00:00 2001
+From: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com>
+Date: Thu, 3 May 2018 13:42:43 -0400
+Subject: [PATCH 4528/5725] drm/amd/display: upgrade scaler math
+
+This change will allow the viewport overlap to apply to rotated/
+mirrored surfaces. Viewport overlap results in extra pixels being
+added to viewport allowing the first few pixels to be scaled as
+if there is no cut-off(mpo or pipe split) and allows us to get matching
+crc's between scaled split and unsplit outputs of the same thing.
+
+Signed-off-by: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com>
+Reviewed-by: Charlene Liu <Charlene.Liu@amd.com>
+Acked-by: Harry Wentland <harry.wentland@amd.com>
+---
+ drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 419 +++++++++++++++-------
+ 1 file changed, 289 insertions(+), 130 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 f02f366..ad09f0c 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+@@ -521,13 +521,12 @@ static void calculate_viewport(struct pipe_ctx *pipe_ctx)
+ }
+ }
+
+-static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip)
++static void calculate_recout(struct pipe_ctx *pipe_ctx, struct rect *recout_full)
+ {
+ const struct dc_plane_state *plane_state = pipe_ctx->plane_state;
+ const struct dc_stream_state *stream = pipe_ctx->stream;
+ struct rect surf_src = plane_state->src_rect;
+ struct rect surf_clip = plane_state->clip_rect;
+- int recout_full_x, recout_full_y;
+ bool pri_split = pipe_ctx->bottom_pipe &&
+ pipe_ctx->bottom_pipe->plane_state == pipe_ctx->plane_state;
+ bool sec_split = pipe_ctx->top_pipe &&
+@@ -596,20 +595,22 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx, struct view *recout_skip
+ }
+ }
+ /* Unclipped recout offset = stream dst offset + ((surf dst offset - stream surf_src offset)
+- * * 1/ stream scaling ratio) - (surf surf_src offset * 1/ full scl
+- * ratio)
++ * * 1/ stream scaling ratio) - (surf surf_src offset * 1/ full scl
++ * ratio)
+ */
+- recout_full_x = stream->dst.x + (plane_state->dst_rect.x - stream->src.x)
++ recout_full->x = stream->dst.x + (plane_state->dst_rect.x - stream->src.x)
+ * stream->dst.width / stream->src.width -
+ surf_src.x * plane_state->dst_rect.width / surf_src.width
+ * stream->dst.width / stream->src.width;
+- recout_full_y = stream->dst.y + (plane_state->dst_rect.y - stream->src.y)
++ recout_full->y = stream->dst.y + (plane_state->dst_rect.y - stream->src.y)
+ * stream->dst.height / stream->src.height -
+ surf_src.y * plane_state->dst_rect.height / surf_src.height
+ * stream->dst.height / stream->src.height;
+
+- recout_skip->width = pipe_ctx->plane_res.scl_data.recout.x - recout_full_x;
+- recout_skip->height = pipe_ctx->plane_res.scl_data.recout.y - recout_full_y;
++ recout_full->width = plane_state->dst_rect.width
++ * stream->dst.width / stream->src.width;
++ recout_full->height = plane_state->dst_rect.height
++ * stream->dst.height / stream->src.height;
+ }
+
+ static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx)
+@@ -661,7 +662,7 @@ static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx)
+ pipe_ctx->plane_res.scl_data.ratios.vert_c, 19);
+ }
+
+-static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *recout_skip)
++static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct rect *recout_full)
+ {
+ struct scaler_data *data = &pipe_ctx->plane_res.scl_data;
+ struct rect src = pipe_ctx->plane_state->src_rect;
+@@ -679,15 +680,14 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *r
+ flip_vert_scan_dir = true;
+ else if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270)
+ flip_horz_scan_dir = true;
+- if (pipe_ctx->plane_state->horizontal_mirror)
+- flip_horz_scan_dir = !flip_horz_scan_dir;
+
+ if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 ||
+ pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) {
+ rect_swap_helper(&src);
+ rect_swap_helper(&data->viewport_c);
+ rect_swap_helper(&data->viewport);
+- }
++ } else if (pipe_ctx->plane_state->horizontal_mirror)
++ flip_horz_scan_dir = !flip_horz_scan_dir;
+
+ /*
+ * Init calculated according to formula:
+@@ -707,127 +707,286 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx, struct view *r
+ data->inits.v_c = dc_fixpt_truncate(dc_fixpt_add(data->inits.v_c, dc_fixpt_div_int(
+ dc_fixpt_add_int(data->ratios.vert_c, data->taps.v_taps_c + 1), 2)), 19);
+
++ if (!flip_horz_scan_dir) {
++ /* 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 = dc_fixpt_floor(
++ dc_fixpt_sub(data->inits.h, data->ratios.horz));
+
++ int_part = int_part > 0 ? int_part : 0;
++ data->viewport.width += 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 = dc_fixpt_floor(
++ dc_fixpt_sub(data->inits.h_c, data->ratios.horz_c));
++
++ int_part = int_part > 0 ? int_part : 0;
++ data->viewport_c.width += int_part < vp_clip ? int_part : vp_clip;
++ }
+
+- /* Adjust for viewport end clip-off */
+- if ((data->viewport.x + data->viewport.width) < (src.x + src.width) && !flip_horz_scan_dir) {
+- int vp_clip = src.x + src.width - data->viewport.width - data->viewport.x;
+- int int_part = dc_fixpt_floor(
+- dc_fixpt_sub(data->inits.h, data->ratios.horz));
+-
+- int_part = int_part > 0 ? int_part : 0;
+- data->viewport.width += int_part < vp_clip ? int_part : vp_clip;
+- }
+- if ((data->viewport.y + data->viewport.height) < (src.y + src.height) && !flip_vert_scan_dir) {
+- int vp_clip = src.y + src.height - data->viewport.height - data->viewport.y;
+- int int_part = dc_fixpt_floor(
+- dc_fixpt_sub(data->inits.v, data->ratios.vert));
+-
+- int_part = int_part > 0 ? int_part : 0;
+- 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 && !flip_horz_scan_dir) {
+- int vp_clip = (src.x + src.width) / vpc_div -
+- data->viewport_c.width - data->viewport_c.x;
+- int int_part = dc_fixpt_floor(
+- dc_fixpt_sub(data->inits.h_c, data->ratios.horz_c));
+-
+- int_part = int_part > 0 ? int_part : 0;
+- 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 && !flip_vert_scan_dir) {
+- int vp_clip = (src.y + src.height) / vpc_div -
+- data->viewport_c.height - data->viewport_c.y;
+- int int_part = dc_fixpt_floor(
+- dc_fixpt_sub(data->inits.v_c, data->ratios.vert_c));
+-
+- int_part = int_part > 0 ? int_part : 0;
+- data->viewport_c.height += int_part < vp_clip ? int_part : vp_clip;
+- }
+-
+- /* Adjust for non-0 viewport offset */
+- if (data->viewport.x && !flip_horz_scan_dir) {
+- int int_part;
+-
+- data->inits.h = dc_fixpt_add(data->inits.h, dc_fixpt_mul_int(
+- data->ratios.horz, recout_skip->width));
+- int_part = dc_fixpt_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;
++ /* Adjust for non-0 viewport offset */
++ if (data->viewport.x) {
++ int int_part;
++
++ data->inits.h = dc_fixpt_add(data->inits.h, dc_fixpt_mul_int(
++ data->ratios.horz, data->recout.x - recout_full->x));
++ int_part = dc_fixpt_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 = dc_fixpt_add_int(data->inits.h, int_part);
+ }
+- data->inits.h.value &= 0xffffffff;
+- data->inits.h = dc_fixpt_add_int(data->inits.h, int_part);
+- }
+-
+- if (data->viewport_c.x && !flip_horz_scan_dir) {
+- int int_part;
+-
+- data->inits.h_c = dc_fixpt_add(data->inits.h_c, dc_fixpt_mul_int(
+- data->ratios.horz_c, recout_skip->width));
+- int_part = dc_fixpt_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;
++
++ if (data->viewport_c.x) {
++ int int_part;
++
++ data->inits.h_c = dc_fixpt_add(data->inits.h_c, dc_fixpt_mul_int(
++ data->ratios.horz_c, data->recout.x - recout_full->x));
++ int_part = dc_fixpt_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 = dc_fixpt_add_int(data->inits.h_c, int_part);
+ }
+- data->inits.h_c.value &= 0xffffffff;
+- data->inits.h_c = dc_fixpt_add_int(data->inits.h_c, int_part);
+- }
+-
+- if (data->viewport.y && !flip_vert_scan_dir) {
+- int int_part;
+-
+- data->inits.v = dc_fixpt_add(data->inits.v, dc_fixpt_mul_int(
+- data->ratios.vert, recout_skip->height));
+- int_part = dc_fixpt_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;
++ } else {
++ /* Adjust for non-0 viewport offset */
++ if (data->viewport.x) {
++ int int_part = dc_fixpt_floor(
++ dc_fixpt_sub(data->inits.h, data->ratios.horz));
++
++ int_part = int_part > 0 ? int_part : 0;
++ data->viewport.width += int_part < data->viewport.x ? int_part : data->viewport.x;
++ data->viewport.x -= int_part < data->viewport.x ? int_part : data->viewport.x;
++ }
++ if (data->viewport_c.x) {
++ int int_part = dc_fixpt_floor(
++ dc_fixpt_sub(data->inits.h_c, data->ratios.horz_c));
++
++ int_part = int_part > 0 ? int_part : 0;
++ data->viewport_c.width += int_part < data->viewport_c.x ? int_part : data->viewport_c.x;
++ data->viewport_c.x -= int_part < data->viewport_c.x ? int_part : data->viewport_c.x;
+ }
+- data->inits.v.value &= 0xffffffff;
+- data->inits.v = dc_fixpt_add_int(data->inits.v, int_part);
+- }
+-
+- if (data->viewport_c.y && !flip_vert_scan_dir) {
+- int int_part;
+-
+- data->inits.v_c = dc_fixpt_add(data->inits.v_c, dc_fixpt_mul_int(
+- data->ratios.vert_c, recout_skip->height));
+- int_part = dc_fixpt_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;
++
++ /* Adjust for viewport end clip-off */
++ if ((data->viewport.x + data->viewport.width) < (src.x + src.width)) {
++ int int_part;
++ int end_offset = src.x + src.width
++ - data->viewport.x - data->viewport.width;
++
++ /*
++ * this is init if vp had no offset, keep in mind this is from the
++ * right side of vp due to scan direction
++ */
++ data->inits.h = dc_fixpt_add(data->inits.h, dc_fixpt_mul_int(
++ data->ratios.horz, data->recout.x - recout_full->x));
++ /*
++ * this is the difference between first pixel of viewport available to read
++ * and init position, takning into account scan direction
++ */
++ int_part = dc_fixpt_floor(data->inits.h) - end_offset;
++ if (int_part < data->taps.h_taps) {
++ int int_adj = end_offset >= (data->taps.h_taps - int_part) ?
++ (data->taps.h_taps - int_part) : end_offset;
++ data->viewport.width += int_adj;
++ int_part += int_adj;
++ } else if (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 = dc_fixpt_add_int(data->inits.h, int_part);
++ }
++
++ if ((data->viewport_c.x + data->viewport_c.width) < (src.x + src.width) / vpc_div) {
++ int int_part;
++ int end_offset = (src.x + src.width) / vpc_div
++ - data->viewport_c.x - data->viewport_c.width;
++
++ /*
++ * this is init if vp had no offset, keep in mind this is from the
++ * right side of vp due to scan direction
++ */
++ data->inits.h_c = dc_fixpt_add(data->inits.h_c, dc_fixpt_mul_int(
++ data->ratios.horz_c, data->recout.x - recout_full->x));
++ /*
++ * this is the difference between first pixel of viewport available to read
++ * and init position, takning into account scan direction
++ */
++ int_part = dc_fixpt_floor(data->inits.h_c) - end_offset;
++ if (int_part < data->taps.h_taps_c) {
++ int int_adj = end_offset >= (data->taps.h_taps_c - int_part) ?
++ (data->taps.h_taps_c - int_part) : end_offset;
++ data->viewport_c.width += int_adj;
++ int_part += int_adj;
++ } else if (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 = dc_fixpt_add_int(data->inits.h_c, int_part);
++ }
++
++ }
++ if (!flip_vert_scan_dir) {
++ /* Adjust for viewport end clip-off */
++ 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 = dc_fixpt_floor(
++ dc_fixpt_sub(data->inits.v, data->ratios.vert));
++
++ int_part = int_part > 0 ? int_part : 0;
++ data->viewport.height += 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 = dc_fixpt_floor(
++ dc_fixpt_sub(data->inits.v_c, data->ratios.vert_c));
++
++ int_part = int_part > 0 ? int_part : 0;
++ data->viewport_c.height += int_part < vp_clip ? int_part : vp_clip;
++ }
++
++ /* Adjust for non-0 viewport offset */
++ if (data->viewport.y) {
++ int int_part;
++
++ data->inits.v = dc_fixpt_add(data->inits.v, dc_fixpt_mul_int(
++ data->ratios.vert, data->recout.y - recout_full->y));
++ int_part = dc_fixpt_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 = dc_fixpt_add_int(data->inits.v, int_part);
++ }
++
++ if (data->viewport_c.y) {
++ int int_part;
++
++ data->inits.v_c = dc_fixpt_add(data->inits.v_c, dc_fixpt_mul_int(
++ data->ratios.vert_c, data->recout.y - recout_full->y));
++ int_part = dc_fixpt_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 = dc_fixpt_add_int(data->inits.v_c, int_part);
++ }
++ } else {
++ /* Adjust for non-0 viewport offset */
++ if (data->viewport.y) {
++ int int_part = dc_fixpt_floor(
++ dc_fixpt_sub(data->inits.v, data->ratios.vert));
++
++ int_part = int_part > 0 ? int_part : 0;
++ data->viewport.height += int_part < data->viewport.y ? int_part : data->viewport.y;
++ data->viewport.y -= int_part < data->viewport.y ? int_part : data->viewport.y;
++ }
++ if (data->viewport_c.y) {
++ int int_part = dc_fixpt_floor(
++ dc_fixpt_sub(data->inits.v_c, data->ratios.vert_c));
++
++ int_part = int_part > 0 ? int_part : 0;
++ data->viewport_c.height += int_part < data->viewport_c.y ? int_part : data->viewport_c.y;
++ data->viewport_c.y -= int_part < data->viewport_c.y ? int_part : data->viewport_c.y;
++ }
++
++ /* Adjust for viewport end clip-off */
++ if ((data->viewport.y + data->viewport.height) < (src.y + src.height)) {
++ int int_part;
++ int end_offset = src.y + src.height
++ - data->viewport.y - data->viewport.height;
++
++ /*
++ * this is init if vp had no offset, keep in mind this is from the
++ * right side of vp due to scan direction
++ */
++ data->inits.v = dc_fixpt_add(data->inits.v, dc_fixpt_mul_int(
++ data->ratios.vert, data->recout.y - recout_full->y));
++ /*
++ * this is the difference between first pixel of viewport available to read
++ * and init position, taking into account scan direction
++ */
++ int_part = dc_fixpt_floor(data->inits.v) - end_offset;
++ if (int_part < data->taps.v_taps) {
++ int int_adj = end_offset >= (data->taps.v_taps - int_part) ?
++ (data->taps.v_taps - int_part) : end_offset;
++ data->viewport.height += int_adj;
++ int_part += int_adj;
++ } else if (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 = dc_fixpt_add_int(data->inits.v, int_part);
++ }
++
++ if ((data->viewport_c.y + data->viewport_c.height) < (src.y + src.height) / vpc_div) {
++ int int_part;
++ int end_offset = (src.y + src.height) / vpc_div
++ - data->viewport_c.y - data->viewport_c.height;
++
++ /*
++ * this is init if vp had no offset, keep in mind this is from the
++ * right side of vp due to scan direction
++ */
++ data->inits.v_c = dc_fixpt_add(data->inits.v_c, dc_fixpt_mul_int(
++ data->ratios.vert_c, data->recout.y - recout_full->y));
++ /*
++ * this is the difference between first pixel of viewport available to read
++ * and init position, taking into account scan direction
++ */
++ int_part = dc_fixpt_floor(data->inits.v_c) - end_offset;
++ if (int_part < data->taps.v_taps_c) {
++ int int_adj = end_offset >= (data->taps.v_taps_c - int_part) ?
++ (data->taps.v_taps_c - int_part) : end_offset;
++ data->viewport_c.height += int_adj;
++ int_part += int_adj;
++ } else if (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 = dc_fixpt_add_int(data->inits.v_c, int_part);
+ }
+- data->inits.v_c.value &= 0xffffffff;
+- data->inits.v_c = dc_fixpt_add_int(data->inits.v_c, int_part);
+ }
+
+ /* Interlaced inits based on final vert inits */
+@@ -845,7 +1004,7 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
+ {
+ const struct dc_plane_state *plane_state = pipe_ctx->plane_state;
+ struct dc_crtc_timing *timing = &pipe_ctx->stream->timing;
+- struct view recout_skip = { 0 };
++ struct rect recout_full = { 0 };
+ bool res = false;
+ DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger);
+ /* Important: scaling ratio calculation requires pixel format,
+@@ -865,7 +1024,7 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
+ if (pipe_ctx->plane_res.scl_data.viewport.height < 16 || pipe_ctx->plane_res.scl_data.viewport.width < 16)
+ return false;
+
+- calculate_recout(pipe_ctx, &recout_skip);
++ calculate_recout(pipe_ctx, &recout_full);
+
+ /**
+ * Setting line buffer pixel depth to 24bpp yields banding
+@@ -909,7 +1068,7 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
+
+ if (res)
+ /* May need to re-check lb size after this in some obscure scenario */
+- calculate_inits_and_adj_vp(pipe_ctx, &recout_skip);
++ calculate_inits_and_adj_vp(pipe_ctx, &recout_full);
+
+ DC_LOG_SCALER(
+ "%s: Viewport:\nheight:%d width:%d x:%d "
+--
+2.7.4
+