]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 5.10
authorSasha Levin <sashal@kernel.org>
Tue, 18 Mar 2025 00:58:39 +0000 (20:58 -0400)
committerSasha Levin <sashal@kernel.org>
Tue, 18 Mar 2025 00:58:39 +0000 (20:58 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-5.10/drm-amd-display-check-for-invalid-input-params-when-.patch [new file with mode: 0644]
queue-5.10/drm-amd-display-check-plane-scaling-against-format-s.patch [new file with mode: 0644]
queue-5.10/drm-amd-display-dc-core-dc_resource-staticify-local-.patch [new file with mode: 0644]
queue-5.10/drm-amd-display-fix-null-check-for-pipe_ctx-plane_st.patch [new file with mode: 0644]
queue-5.10/drm-amd-display-fix-odm-scaling.patch [new file with mode: 0644]
queue-5.10/drm-amd-display-reject-too-small-viewport-size-when-.patch [new file with mode: 0644]
queue-5.10/i2c-ali1535-fix-an-error-handling-path-in-ali1535_pr.patch [new file with mode: 0644]
queue-5.10/i2c-ali15x3-fix-an-error-handling-path-in-ali15x3_pr.patch [new file with mode: 0644]
queue-5.10/i2c-sis630-fix-an-error-handling-path-in-sis630_prob.patch [new file with mode: 0644]
queue-5.10/series

diff --git a/queue-5.10/drm-amd-display-check-for-invalid-input-params-when-.patch b/queue-5.10/drm-amd-display-check-for-invalid-input-params-when-.patch
new file mode 100644 (file)
index 0000000..27e0970
--- /dev/null
@@ -0,0 +1,52 @@
+From b2a4ccbb5c1cc12b83b126cba65f715ecd910e47 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 23 Mar 2022 16:06:25 -0400
+Subject: drm/amd/display: Check for invalid input params when building scaling
+ params
+
+From: Michael Strauss <michael.strauss@amd.com>
+
+[ Upstream commit 73b1da69f5314d96e1f963468863eaa884ee1030 ]
+
+[WHY]
+Function to calculate scaling ratios can be called with invalid plane
+src/dest, causing a divide by zero.
+
+[HOW]
+Fail building scaling params if plane state src/dest rects are
+unpopulated
+
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Reviewed-by: Charlene Liu <Charlene.Liu@amd.com>
+Acked-by: Tom Chung <chiahsuan.chung@amd.com>
+Signed-off-by: Michael Strauss <michael.strauss@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Stable-dep-of: 374c9faac5a7 ("drm/amd/display: Fix null check for pipe_ctx->plane_state in resource_build_scaling_params")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+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 0a2b3703be537..9564905c2c797 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+@@ -951,6 +951,15 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
+       bool res = false;
+       DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger);
++      /* Invalid input */
++      if (!plane_state->dst_rect.width ||
++                      !plane_state->dst_rect.height ||
++                      !plane_state->src_rect.width ||
++                      !plane_state->src_rect.height) {
++              ASSERT(0);
++              return false;
++      }
++
+       pipe_ctx->plane_res.scl_data.format = convert_pixel_format_to_dalsurface(
+                       pipe_ctx->plane_state->format);
+-- 
+2.39.5
+
diff --git a/queue-5.10/drm-amd-display-check-plane-scaling-against-format-s.patch b/queue-5.10/drm-amd-display-check-plane-scaling-against-format-s.patch
new file mode 100644 (file)
index 0000000..3abaada
--- /dev/null
@@ -0,0 +1,147 @@
+From 8b9a2151fa9bfbeb283cbf13c1a469a835318393 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 28 Dec 2020 19:50:58 +0100
+Subject: drm/amd/display: Check plane scaling against format specific hw plane
+ caps.
+
+From: Mario Kleiner <mario.kleiner.de@gmail.com>
+
+[ Upstream commit 6300b3bd9d0d7afaf085dd086ce6258511c3f057 ]
+
+This takes hw constraints specific to pixel formats into account,
+e.g., the inability of older hw to scale fp16 format framebuffers.
+
+It should now allow safely to enable fp16 formats also on DCE-8,
+DCE-10, DCE-11.0
+
+Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
+Signed-off-by: Mario Kleiner <mario.kleiner.de@gmail.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Stable-dep-of: 374c9faac5a7 ("drm/amd/display: Fix null check for pipe_ctx->plane_state in resource_build_scaling_params")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 81 +++++++++++++++++--
+ 1 file changed, 73 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+index 50921b340b886..4b4de1751c53f 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -3719,10 +3719,53 @@ static const struct drm_encoder_funcs amdgpu_dm_encoder_funcs = {
+ };
++static void get_min_max_dc_plane_scaling(struct drm_device *dev,
++                                       struct drm_framebuffer *fb,
++                                       int *min_downscale, int *max_upscale)
++{
++      struct amdgpu_device *adev = drm_to_adev(dev);
++      struct dc *dc = adev->dm.dc;
++      /* Caps for all supported planes are the same on DCE and DCN 1 - 3 */
++      struct dc_plane_cap *plane_cap = &dc->caps.planes[0];
++
++      switch (fb->format->format) {
++      case DRM_FORMAT_P010:
++      case DRM_FORMAT_NV12:
++      case DRM_FORMAT_NV21:
++              *max_upscale = plane_cap->max_upscale_factor.nv12;
++              *min_downscale = plane_cap->max_downscale_factor.nv12;
++              break;
++
++      case DRM_FORMAT_XRGB16161616F:
++      case DRM_FORMAT_ARGB16161616F:
++      case DRM_FORMAT_XBGR16161616F:
++      case DRM_FORMAT_ABGR16161616F:
++              *max_upscale = plane_cap->max_upscale_factor.fp16;
++              *min_downscale = plane_cap->max_downscale_factor.fp16;
++              break;
++
++      default:
++              *max_upscale = plane_cap->max_upscale_factor.argb8888;
++              *min_downscale = plane_cap->max_downscale_factor.argb8888;
++              break;
++      }
++
++      /*
++       * A factor of 1 in the plane_cap means to not allow scaling, ie. use a
++       * scaling factor of 1.0 == 1000 units.
++       */
++      if (*max_upscale == 1)
++              *max_upscale = 1000;
++
++      if (*min_downscale == 1)
++              *min_downscale = 1000;
++}
++
++
+ static int fill_dc_scaling_info(const struct drm_plane_state *state,
+                               struct dc_scaling_info *scaling_info)
+ {
+-      int scale_w, scale_h;
++      int scale_w, scale_h, min_downscale, max_upscale;
+       memset(scaling_info, 0, sizeof(*scaling_info));
+@@ -3788,17 +3831,25 @@ static int fill_dc_scaling_info(const struct drm_plane_state *state,
+       /* DRM doesn't specify clipping on destination output. */
+       scaling_info->clip_rect = scaling_info->dst_rect;
+-      /* TODO: Validate scaling per-format with DC plane caps */
++      /* Validate scaling per-format with DC plane caps */
++      if (state->plane && state->plane->dev && state->fb) {
++              get_min_max_dc_plane_scaling(state->plane->dev, state->fb,
++                                           &min_downscale, &max_upscale);
++      } else {
++              min_downscale = 250;
++              max_upscale = 16000;
++      }
++
+       scale_w = scaling_info->dst_rect.width * 1000 /
+                 scaling_info->src_rect.width;
+-      if (scale_w < 250 || scale_w > 16000)
++      if (scale_w < min_downscale || scale_w > max_upscale)
+               return -EINVAL;
+       scale_h = scaling_info->dst_rect.height * 1000 /
+                 scaling_info->src_rect.height;
+-      if (scale_h < 250 || scale_h > 16000)
++      if (scale_h < min_downscale || scale_h > max_upscale)
+               return -EINVAL;
+       /*
+@@ -6010,12 +6061,26 @@ static void dm_plane_helper_cleanup_fb(struct drm_plane *plane,
+ static int dm_plane_helper_check_state(struct drm_plane_state *state,
+                                      struct drm_crtc_state *new_crtc_state)
+ {
+-      int max_downscale = 0;
+-      int max_upscale = INT_MAX;
++      struct drm_framebuffer *fb = state->fb;
++      int min_downscale, max_upscale;
++      int min_scale = 0;
++      int max_scale = INT_MAX;
++
++      /* Plane enabled? Get min/max allowed scaling factors from plane caps. */
++      if (fb && state->crtc) {
++              get_min_max_dc_plane_scaling(state->crtc->dev, fb,
++                                           &min_downscale, &max_upscale);
++              /*
++               * Convert to drm convention: 16.16 fixed point, instead of dc's
++               * 1.0 == 1000. Also drm scaling is src/dst instead of dc's
++               * dst/src, so min_scale = 1.0 / max_upscale, etc.
++               */
++              min_scale = (1000 << 16) / max_upscale;
++              max_scale = (1000 << 16) / min_downscale;
++      }
+-      /* TODO: These should be checked against DC plane caps */
+       return drm_atomic_helper_check_plane_state(
+-              state, new_crtc_state, max_downscale, max_upscale, true, true);
++              state, new_crtc_state, min_scale, max_scale, true, true);
+ }
+ static int dm_plane_atomic_check(struct drm_plane *plane,
+-- 
+2.39.5
+
diff --git a/queue-5.10/drm-amd-display-dc-core-dc_resource-staticify-local-.patch b/queue-5.10/drm-amd-display-dc-core-dc_resource-staticify-local-.patch
new file mode 100644 (file)
index 0000000..dcc9798
--- /dev/null
@@ -0,0 +1,60 @@
+From 7c81547a4f05490294fa59431c4655f02e7aa8a4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 Jan 2021 08:07:28 +0000
+Subject: drm/amd/display/dc/core/dc_resource: Staticify local functions
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Lee Jones <lee.jones@linaro.org>
+
+[ Upstream commit c88855f3a50903721c4e1dda16cb42b5f5432b5c ]
+
+Fixes the following W=1 kernel build warning(s):
+
+ drivers/gpu/drm/amd/amdgpu/../display/dc/core/dc_resource.c:1120:5: warning: no previous prototype for ‘shift_border_left_to_dst’ [-Wmissing-prototypes]
+ drivers/gpu/drm/amd/amdgpu/../display/dc/core/dc_resource.c:1131:6: warning: no previous prototype for ‘restore_border_left_from_dst’ [-Wmissing-prototypes]
+
+Cc: Harry Wentland <harry.wentland@amd.com>
+Cc: Leo Li <sunpeng.li@amd.com>
+Cc: Alex Deucher <alexander.deucher@amd.com>
+Cc: "Christian König" <christian.koenig@amd.com>
+Cc: David Airlie <airlied@linux.ie>
+Cc: Daniel Vetter <daniel@ffwll.ch>
+Cc: amd-gfx@lists.freedesktop.org
+Cc: dri-devel@lists.freedesktop.org
+Signed-off-by: Lee Jones <lee.jones@linaro.org>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Stable-dep-of: 374c9faac5a7 ("drm/amd/display: Fix null check for pipe_ctx->plane_state in resource_build_scaling_params")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 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 b619ebd452ad4..5dc6840cea248 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+@@ -1108,7 +1108,7 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx)
+  * We also need to make sure pipe_ctx->plane_res.scl_data.h_active uses the
+  * original h_border_left value in its calculation.
+  */
+-int shift_border_left_to_dst(struct pipe_ctx *pipe_ctx)
++static int shift_border_left_to_dst(struct pipe_ctx *pipe_ctx)
+ {
+       int store_h_border_left = pipe_ctx->stream->timing.h_border_left;
+@@ -1119,8 +1119,8 @@ int shift_border_left_to_dst(struct pipe_ctx *pipe_ctx)
+       return store_h_border_left;
+ }
+-void restore_border_left_from_dst(struct pipe_ctx *pipe_ctx,
+-                                  int store_h_border_left)
++static void restore_border_left_from_dst(struct pipe_ctx *pipe_ctx,
++                                       int store_h_border_left)
+ {
+       pipe_ctx->stream->dst.x -= store_h_border_left;
+       pipe_ctx->stream->timing.h_border_left = store_h_border_left;
+-- 
+2.39.5
+
diff --git a/queue-5.10/drm-amd-display-fix-null-check-for-pipe_ctx-plane_st.patch b/queue-5.10/drm-amd-display-fix-null-check-for-pipe_ctx-plane_st.patch
new file mode 100644 (file)
index 0000000..b98ff93
--- /dev/null
@@ -0,0 +1,44 @@
+From 75d2caf39b8e8099ce17fac479b26a87009f666d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 26 Feb 2025 16:37:31 +0800
+Subject: drm/amd/display: Fix null check for pipe_ctx->plane_state in
+ resource_build_scaling_params
+
+From: Ma Ke <make24@iscas.ac.cn>
+
+[ Upstream commit 374c9faac5a763a05bc3f68ad9f73dab3c6aec90 ]
+
+Null pointer dereference issue could occur when pipe_ctx->plane_state
+is null. The fix adds a check to ensure 'pipe_ctx->plane_state' is not
+null before accessing. This prevents a null pointer dereference.
+
+Found by code review.
+
+Fixes: 3be5262e353b ("drm/amd/display: Rename more dc_surface stuff to plane_state")
+Reviewed-by: Alex Hung <alex.hung@amd.com>
+Signed-off-by: Ma Ke <make24@iscas.ac.cn>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+(cherry picked from commit 63e6a77ccf239337baa9b1e7787cde9fa0462092)
+Cc: stable@vger.kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+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 9564905c2c797..8dace2e401bbd 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+@@ -952,7 +952,8 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
+       DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger);
+       /* Invalid input */
+-      if (!plane_state->dst_rect.width ||
++      if (!plane_state ||
++                      !plane_state->dst_rect.width ||
+                       !plane_state->dst_rect.height ||
+                       !plane_state->src_rect.width ||
+                       !plane_state->src_rect.height) {
+-- 
+2.39.5
+
diff --git a/queue-5.10/drm-amd-display-fix-odm-scaling.patch b/queue-5.10/drm-amd-display-fix-odm-scaling.patch
new file mode 100644 (file)
index 0000000..f08e34a
--- /dev/null
@@ -0,0 +1,868 @@
+From 43861af8f73add0ced7fe9a1fac5a0fcd54b1ca8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 10 May 2021 10:19:18 -0400
+Subject: drm/amd/display: fix odm scaling
+
+From: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com>
+
+[ Upstream commit 6566cae7aef30da8833f1fa0eb854baf33b96676 ]
+
+There are two issues with scaling calculations, odm recout
+calculation and matching viewport to actual recout.
+
+This change fixes both issues. Odm recout calculation via
+special casing and viewport matching issue by reworking
+the viewport calcualtion to use scaling ratios and recout
+to derrive the required offset and size.
+
+Signed-off-by: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com>
+Reviewed-by: Jun Lei <Jun.Lei@amd.com>
+Acked-by: Qingqing Zhuo <qingqing.zhuo@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Stable-dep-of: 374c9faac5a7 ("drm/amd/display: Fix null check for pipe_ctx->plane_state in resource_build_scaling_params")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../gpu/drm/amd/display/dc/core/dc_resource.c | 568 +++++++-----------
+ drivers/gpu/drm/amd/display/dc/dc_types.h     |   5 -
+ .../drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c |  12 +-
+ .../drm/amd/display/dc/dcn20/dcn20_resource.c |  14 +-
+ .../amd/display/dc/dml/display_mode_structs.h |   2 +
+ .../drm/amd/display/dc/dml/display_mode_vba.c |  13 +
+ .../gpu/drm/amd/display/dc/inc/hw/transform.h |   4 -
+ 7 files changed, 232 insertions(+), 386 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 d77001b2e106b..0a2b3703be537 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+@@ -647,124 +647,23 @@ static void calculate_split_count_and_index(struct pipe_ctx *pipe_ctx, int *spli
+       }
+ }
+-static void calculate_viewport(struct pipe_ctx *pipe_ctx)
++/*
++ * This is a preliminary vp size calculation to allow us to check taps support.
++ * The result is completely overridden afterwards.
++ */
++static void calculate_viewport_size(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_src = plane_state->src_rect;
+-      struct rect clip, dest;
+-      int vpc_div = (data->format == PIXEL_FORMAT_420BPP8
+-                      || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1;
+-      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) {
+-              split_count = 0;
+-              split_idx = 0;
+-      }
+-
+-      /* The actual clip is an intersection between stream
+-       * source and surface clip
+-       */
+-      dest = plane_state->dst_rect;
+-      clip.x = stream->src.x > plane_state->clip_rect.x ?
+-                      stream->src.x : plane_state->clip_rect.x;
+-
+-      clip.width = stream->src.x + stream->src.width <
+-                      plane_state->clip_rect.x + plane_state->clip_rect.width ?
+-                      stream->src.x + stream->src.width - clip.x :
+-                      plane_state->clip_rect.x + plane_state->clip_rect.width - clip.x ;
+-
+-      clip.y = stream->src.y > plane_state->clip_rect.y ?
+-                      stream->src.y : plane_state->clip_rect.y;
+-
+-      clip.height = stream->src.y + stream->src.height <
+-                      plane_state->clip_rect.y + plane_state->clip_rect.height ?
+-                      stream->src.y + stream->src.height - clip.y :
+-                      plane_state->clip_rect.y + plane_state->clip_rect.height - clip.y ;
+-
+-      /*
+-       * Need to calculate how scan origin is shifted in vp space
+-       * to correctly rotate clip and dst
+-       */
+-      get_vp_scan_direction(
+-                      plane_state->rotation,
+-                      plane_state->horizontal_mirror,
+-                      &orthogonal_rotation,
+-                      &flip_y_start,
+-                      &flip_x_start);
+-
+-      if (orthogonal_rotation) {
+-              swap(clip.x, clip.y);
+-              swap(clip.width, clip.height);
+-              swap(dest.x, dest.y);
+-              swap(dest.width, dest.height);
+-      }
+-      if (flip_x_start) {
+-              clip.x = dest.x + dest.width - clip.x - clip.width;
+-              dest.x = 0;
+-      }
+-      if (flip_y_start) {
+-              clip.y = dest.y + dest.height - clip.y - clip.height;
+-              dest.y = 0;
+-      }
+-
+-      /* offset = surf_src.ofs + (clip.ofs - surface->dst_rect.ofs) * scl_ratio
+-       * num_pixels = clip.num_pix * scl_ratio
+-       */
+-      data->viewport.x = surf_src.x + (clip.x - dest.x) * surf_src.width / dest.width;
+-      data->viewport.width = clip.width * surf_src.width / dest.width;
+-
+-      data->viewport.y = surf_src.y + (clip.y - dest.y) * surf_src.height / dest.height;
+-      data->viewport.height = clip.height * surf_src.height / dest.height;
+-
+-      /* Handle 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)
+-                              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)
+-                              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);
+-              }
++      data->viewport.width = dc_fixpt_ceil(dc_fixpt_mul_int(data->ratios.horz, data->recout.width));
++      data->viewport.height = dc_fixpt_ceil(dc_fixpt_mul_int(data->ratios.vert, data->recout.height));
++      data->viewport_c.width = dc_fixpt_ceil(dc_fixpt_mul_int(data->ratios.horz_c, data->recout.width));
++      data->viewport_c.height = dc_fixpt_ceil(dc_fixpt_mul_int(data->ratios.vert_c, data->recout.height));
++      if (pipe_ctx->plane_state->rotation == ROTATION_ANGLE_90 ||
++                      pipe_ctx->plane_state->rotation == ROTATION_ANGLE_270) {
++              swap(data->viewport.width, data->viewport.height);
++              swap(data->viewport_c.width, data->viewport_c.height);
+       }
+-
+-      /* 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 ? dc_fixpt_half : dc_fixpt_zero;
+-      data->inits.v_c = (data->viewport.y % vpc_div) != 0 ? dc_fixpt_half : dc_fixpt_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;
+-
+-      data->viewport_unadjusted = data->viewport;
+-      data->viewport_c_unadjusted = data->viewport_c;
+ }
+ static void calculate_recout(struct pipe_ctx *pipe_ctx)
+@@ -773,26 +672,21 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx)
+       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_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;
++      bool split_tb = stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM;
++      int split_count, split_idx;
+       calculate_split_count_and_index(pipe_ctx, &split_count, &split_idx);
++      if (stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE)
++              split_idx = 0;
+       /*
+        * Only the leftmost ODM pipe should be offset by a nonzero distance
+        */
+-      if (!pipe_ctx->prev_odm_pipe) {
++      if (!pipe_ctx->prev_odm_pipe || split_idx == split_count) {
+               data->recout.x = stream->dst.x;
+               if (stream->src.x < surf_clip.x)
+                       data->recout.x += (surf_clip.x - stream->src.x) * stream->dst.width
+                                               / stream->src.width;
+-
+       } else
+               data->recout.x = 0;
+@@ -809,26 +703,31 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx)
+       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_tb) {
+-              data->recout.y += data->recout.height / 2;
+-              /* Floor primary pipe, ceil 2ndary pipe */
+-              data->recout.height = (data->recout.height + 1) / 2;
+-      } else if (pri_split_tb)
++      /* Handle h & v split */
++      if (split_tb) {
++              ASSERT(data->recout.height % 2 == 0);
+               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 */
++      } else if (split_count) {
+               if (!pipe_ctx->next_odm_pipe && !pipe_ctx->prev_odm_pipe) {
++                      /* 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);
++
+                       data->recout.x += (data->recout.width / (split_count + 1)) * split_idx;
+                       if (split_idx > epimo)
+                               data->recout.x += split_idx - epimo - 1;
++                      ASSERT(stream->view_format != VIEW_3D_FORMAT_SIDE_BY_SIDE || data->recout.width % 2 == 0);
++                      data->recout.width = data->recout.width / (split_count + 1) + (split_idx > epimo ? 1 : 0);
++              } else {
++                      /* odm */
++                      if (split_idx == split_count) {
++                              /* rightmost pipe is the remainder recout */
++                              data->recout.width -= data->h_active * split_count - data->recout.x;
++                              data->recout.x = 0;
++                      } else
++                              data->recout.width = data->h_active - data->recout.x;
+               }
+-              data->recout.width = data->recout.width / (split_count + 1) + (split_idx > epimo ? 1 : 0);
+       }
+ }
+@@ -882,9 +781,15 @@ static void calculate_scaling_ratios(struct pipe_ctx *pipe_ctx)
+                       pipe_ctx->plane_res.scl_data.ratios.vert_c, 19);
+ }
+-static inline void adjust_vp_and_init_for_seamless_clip(
++
++/*
++ * We completely calculate vp offset, size and inits here based entirely on scaling
++ * ratios and recout for pixel perfect pipe combine.
++ */
++static void calculate_init_and_vp(
+               bool flip_scan_dir,
+-              int recout_skip,
++              int recout_offset_within_recout_full,
++              int recout_size,
+               int src_size,
+               int taps,
+               struct fixed31_32 ratio,
+@@ -892,91 +797,87 @@ static inline void adjust_vp_and_init_for_seamless_clip(
+               int *vp_offset,
+               int *vp_size)
+ {
+-      if (!flip_scan_dir) {
+-              /* Adjust for viewport end clip-off */
+-              if ((*vp_offset + *vp_size) < src_size) {
+-                      int vp_clip = src_size - *vp_size - *vp_offset;
+-                      int int_part = dc_fixpt_floor(dc_fixpt_sub(*init, ratio));
+-
+-                      int_part = int_part > 0 ? int_part : 0;
+-                      *vp_size += int_part < vp_clip ? int_part : vp_clip;
+-              }
+-
+-              /* Adjust for non-0 viewport offset */
+-              if (*vp_offset) {
+-                      int int_part;
+-
+-                      *init = dc_fixpt_add(*init, dc_fixpt_mul_int(ratio, recout_skip));
+-                      int_part = dc_fixpt_floor(*init) - *vp_offset;
+-                      if (int_part < taps) {
+-                              int int_adj = *vp_offset >= (taps - int_part) ?
+-                                                      (taps - int_part) : *vp_offset;
+-                              *vp_offset -= int_adj;
+-                              *vp_size += int_adj;
+-                              int_part += int_adj;
+-                      } else if (int_part > taps) {
+-                              *vp_offset += int_part - taps;
+-                              *vp_size -= int_part - taps;
+-                              int_part = taps;
+-                      }
+-                      init->value &= 0xffffffff;
+-                      *init = dc_fixpt_add_int(*init, int_part);
+-              }
+-      } else {
+-              /* Adjust for non-0 viewport offset */
+-              if (*vp_offset) {
+-                      int int_part = dc_fixpt_floor(dc_fixpt_sub(*init, ratio));
+-
+-                      int_part = int_part > 0 ? int_part : 0;
+-                      *vp_size += int_part < *vp_offset ? int_part : *vp_offset;
+-                      *vp_offset -= int_part < *vp_offset ? int_part : *vp_offset;
+-              }
++      struct fixed31_32 temp;
++      int int_part;
+-              /* Adjust for viewport end clip-off */
+-              if ((*vp_offset + *vp_size) < src_size) {
+-                      int int_part;
+-                      int end_offset = src_size - *vp_offset - *vp_size;
+-
+-                      /*
+-                       * this is init if vp had no offset, keep in mind this is from the
+-                       * right side of vp due to scan direction
+-                       */
+-                      *init = dc_fixpt_add(*init, dc_fixpt_mul_int(ratio, recout_skip));
+-                      /*
+-                       * 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(*init) - end_offset;
+-                      if (int_part < taps) {
+-                              int int_adj = end_offset >= (taps - int_part) ?
+-                                                      (taps - int_part) : end_offset;
+-                              *vp_size += int_adj;
+-                              int_part += int_adj;
+-                      } else if (int_part > taps) {
+-                              *vp_size += int_part - taps;
+-                              int_part = taps;
+-                      }
+-                      init->value &= 0xffffffff;
+-                      *init = dc_fixpt_add_int(*init, int_part);
+-              }
++      /*
++       * First of the taps starts sampling pixel number <init_int_part> corresponding to recout
++       * pixel 1. Next recout pixel samples int part of <init + scaling ratio> and so on.
++       * All following calculations are based on this logic.
++       *
++       * Init calculated according to formula:
++       *      init = (scaling_ratio + number_of_taps + 1) / 2
++       *      init_bot = init + scaling_ratio
++       *      to get pixel perfect combine add the fraction from calculating vp offset
++       */
++      temp = dc_fixpt_mul_int(ratio, recout_offset_within_recout_full);
++      *vp_offset = dc_fixpt_floor(temp);
++      temp.value &= 0xffffffff;
++      *init = dc_fixpt_truncate(dc_fixpt_add(dc_fixpt_div_int(
++                      dc_fixpt_add_int(ratio, taps + 1), 2), temp), 19);
++      /*
++       * If viewport has non 0 offset and there are more taps than covered by init then
++       * we should decrease the offset and increase init so we are never sampling
++       * outside of viewport.
++       */
++      int_part = dc_fixpt_floor(*init);
++      if (int_part < taps) {
++              int_part = taps - int_part;
++              if (int_part > *vp_offset)
++                      int_part = *vp_offset;
++              *vp_offset -= int_part;
++              *init = dc_fixpt_add_int(*init, int_part);
+       }
++      /*
++       * If taps are sampling outside of viewport at end of recout and there are more pixels
++       * available in the surface we should increase the viewport size, regardless set vp to
++       * only what is used.
++       */
++      temp = dc_fixpt_add(*init, dc_fixpt_mul_int(ratio, recout_size - 1));
++      *vp_size = dc_fixpt_floor(temp);
++      if (*vp_size + *vp_offset > src_size)
++              *vp_size = src_size - *vp_offset;
++
++      /* We did all the math assuming we are scanning same direction as display does,
++       * however mirror/rotation changes how vp scans vs how it is offset. If scan direction
++       * is flipped we simply need to calculate offset from the other side of plane.
++       * Note that outside of viewport all scaling hardware works in recout space.
++       */
++      if (flip_scan_dir)
++              *vp_offset = src_size - *vp_offset - *vp_size;
+ }
+-static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx)
++static void calculate_inits_and_viewports(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;
+       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;
++      struct rect src = plane_state->src_rect;
+       int vpc_div = (data->format == PIXEL_FORMAT_420BPP8
+-                      || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1;
++                              || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1;
++      int split_count, split_idx, ro_lb, ro_tb, recout_full_x, recout_full_y;
+       bool orthogonal_rotation, flip_vert_scan_dir, flip_horz_scan_dir;
+-      int odm_idx = 0;
++      calculate_split_count_and_index(pipe_ctx, &split_count, &split_idx);
+       /*
+-       * Need to calculate the scan direction for viewport to make adjustments
++       * recout full is what the recout would have been if we didnt clip
++       * the source plane at all. We only care about left(ro_lb) and top(ro_tb)
++       * offsets of recout within recout full because those are the directions
++       * we scan from and therefore the only ones that affect inits.
++       */
++      recout_full_x = stream->dst.x + (plane_state->dst_rect.x - stream->src.x)
++                      * stream->dst.width / stream->src.width;
++      recout_full_y = stream->dst.y + (plane_state->dst_rect.y - stream->src.y)
++                      * stream->dst.height / stream->src.height;
++      if (pipe_ctx->prev_odm_pipe && split_idx)
++              ro_lb = data->h_active * split_idx - recout_full_x;
++      else
++              ro_lb = data->recout.x - recout_full_x;
++      ro_tb = data->recout.y - recout_full_y;
++      ASSERT(ro_lb >= 0 && ro_tb >= 0);
++
++      /*
++       * Work in recout rotation since that requires less transformations
+        */
+       get_vp_scan_direction(
+                       plane_state->rotation,
+@@ -985,145 +886,62 @@ static void calculate_inits_and_adj_vp(struct pipe_ctx *pipe_ctx)
+                       &flip_vert_scan_dir,
+                       &flip_horz_scan_dir);
+-      /* Calculate src rect rotation adjusted to recout space */
+-      surf_size_h = src.x + src.width;
+-      surf_size_v = src.y + src.height;
+-      if (flip_horz_scan_dir)
+-              src.x = 0;
+-      if (flip_vert_scan_dir)
+-              src.y = 0;
+       if (orthogonal_rotation) {
+-              swap(src.x, src.y);
+               swap(src.width, src.height);
++              swap(flip_vert_scan_dir, flip_horz_scan_dir);
+       }
+-      /*modified recout_skip_h calculation due to odm having no recout offset*/
+-      while (odm_pipe->prev_odm_pipe) {
+-              odm_idx++;
+-              odm_pipe = odm_pipe->prev_odm_pipe;
+-      }
+-      /*odm_pipe is the leftmost pipe in the ODM group*/
+-      recout_skip_h = odm_idx * data->recout.width;
+-
+-      /* Recout matching initial vp offset = recout_offset - (stream dst offset +
+-       *                      ((surf dst offset - stream src offset) * 1/ stream scaling ratio)
+-       *                      - (surf surf_src offset * 1/ full scl ratio))
+-       */
+-      recout_skip_h += odm_pipe->plane_res.scl_data.recout.x
+-                              - (stream->dst.x + (plane_state->dst_rect.x - stream->src.x)
+-                                      * stream->dst.width / stream->src.width -
+-                                      src.x * plane_state->dst_rect.width / src.width
+-                                      * stream->dst.width / stream->src.width);
+-
+-
+-      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
+-                                      * stream->dst.height / stream->src.height);
+-      if (orthogonal_rotation)
+-              swap(recout_skip_h, recout_skip_v);
+-      /*
+-       * 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 = dc_fixpt_truncate(dc_fixpt_div_int(
+-                      dc_fixpt_add_int(data->ratios.horz, data->taps.h_taps + 1), 2), 19);
+-
+-      data->inits.h_c = dc_fixpt_truncate(dc_fixpt_add(data->inits.h_c, dc_fixpt_div_int(
+-                      dc_fixpt_add_int(data->ratios.horz_c, data->taps.h_taps_c + 1), 2)), 19);
+-
+-      data->inits.v = dc_fixpt_truncate(dc_fixpt_div_int(
+-                      dc_fixpt_add_int(data->ratios.vert, data->taps.v_taps + 1), 2), 19);
+-
+-      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);
+-
+-      /*
+-       * Taps, inits and scaling ratios are in recout space need to rotate
+-       * to viewport rotation before adjustment
+-       */
+-      adjust_vp_and_init_for_seamless_clip(
++      calculate_init_and_vp(
+                       flip_horz_scan_dir,
+-                      recout_skip_h,
+-                      surf_size_h,
+-                      orthogonal_rotation ? data->taps.v_taps : data->taps.h_taps,
+-                      orthogonal_rotation ? data->ratios.vert : data->ratios.horz,
+-                      orthogonal_rotation ? &data->inits.v : &data->inits.h,
++                      ro_lb,
++                      data->recout.width,
++                      src.width,
++                      data->taps.h_taps,
++                      data->ratios.horz,
++                      &data->inits.h,
+                       &data->viewport.x,
+                       &data->viewport.width);
+-      adjust_vp_and_init_for_seamless_clip(
++      calculate_init_and_vp(
+                       flip_horz_scan_dir,
+-                      recout_skip_h,
+-                      surf_size_h / vpc_div,
+-                      orthogonal_rotation ? data->taps.v_taps_c : data->taps.h_taps_c,
+-                      orthogonal_rotation ? data->ratios.vert_c : data->ratios.horz_c,
+-                      orthogonal_rotation ? &data->inits.v_c : &data->inits.h_c,
++                      ro_lb,
++                      data->recout.width,
++                      src.width / vpc_div,
++                      data->taps.h_taps_c,
++                      data->ratios.horz_c,
++                      &data->inits.h_c,
+                       &data->viewport_c.x,
+                       &data->viewport_c.width);
+-      adjust_vp_and_init_for_seamless_clip(
++      calculate_init_and_vp(
+                       flip_vert_scan_dir,
+-                      recout_skip_v,
+-                      surf_size_v,
+-                      orthogonal_rotation ? data->taps.h_taps : data->taps.v_taps,
+-                      orthogonal_rotation ? data->ratios.horz : data->ratios.vert,
+-                      orthogonal_rotation ? &data->inits.h : &data->inits.v,
++                      ro_tb,
++                      data->recout.height,
++                      src.height,
++                      data->taps.v_taps,
++                      data->ratios.vert,
++                      &data->inits.v,
+                       &data->viewport.y,
+                       &data->viewport.height);
+-      adjust_vp_and_init_for_seamless_clip(
++      calculate_init_and_vp(
+                       flip_vert_scan_dir,
+-                      recout_skip_v,
+-                      surf_size_v / vpc_div,
+-                      orthogonal_rotation ? data->taps.h_taps_c : data->taps.v_taps_c,
+-                      orthogonal_rotation ? data->ratios.horz_c : data->ratios.vert_c,
+-                      orthogonal_rotation ? &data->inits.h_c : &data->inits.v_c,
++                      ro_tb,
++                      data->recout.height,
++                      src.height / vpc_div,
++                      data->taps.v_taps_c,
++                      data->ratios.vert_c,
++                      &data->inits.v_c,
+                       &data->viewport_c.y,
+                       &data->viewport_c.height);
+-
+-      /* Interlaced inits based on final vert inits */
+-      data->inits.v_bot = dc_fixpt_add(data->inits.v, data->ratios.vert);
+-      data->inits.v_c_bot = dc_fixpt_add(data->inits.v_c, data->ratios.vert_c);
+-
+-}
+-
+-/*
+- * When handling 270 rotation in mixed SLS mode, we have
+- * stream->timing.h_border_left that is non zero.  If we are doing
+- * pipe-splitting, this h_border_left value gets added to recout.x and when it
+- * calls calculate_inits_and_adj_vp() and
+- * adjust_vp_and_init_for_seamless_clip(), it can cause viewport.height for a
+- * pipe to be incorrect.
+- *
+- * To fix this, instead of using stream->timing.h_border_left, we can use
+- * stream->dst.x to represent the border instead.  So we will set h_border_left
+- * to 0 and shift the appropriate amount in stream->dst.x.  We will then
+- * perform all calculations in resource_build_scaling_params() based on this
+- * and then restore the h_border_left and stream->dst.x to their original
+- * values.
+- *
+- * shift_border_left_to_dst() will shift the amount of h_border_left to
+- * stream->dst.x and set h_border_left to 0.  restore_border_left_from_dst()
+- * will restore h_border_left and stream->dst.x back to their original values
+- * We also need to make sure pipe_ctx->plane_res.scl_data.h_active uses the
+- * original h_border_left value in its calculation.
+- */
+-static int shift_border_left_to_dst(struct pipe_ctx *pipe_ctx)
+-{
+-      int store_h_border_left = pipe_ctx->stream->timing.h_border_left;
+-
+-      if (store_h_border_left) {
+-              pipe_ctx->stream->timing.h_border_left = 0;
+-              pipe_ctx->stream->dst.x += store_h_border_left;
++      if (orthogonal_rotation) {
++              swap(data->viewport.x, data->viewport.y);
++              swap(data->viewport.width, data->viewport.height);
++              swap(data->viewport_c.x, data->viewport_c.y);
++              swap(data->viewport_c.width, data->viewport_c.height);
+       }
+-      return store_h_border_left;
+-}
+-
+-static void restore_border_left_from_dst(struct pipe_ctx *pipe_ctx,
+-                                       int store_h_border_left)
+-{
+-      pipe_ctx->stream->dst.x -= store_h_border_left;
+-      pipe_ctx->stream->timing.h_border_left = store_h_border_left;
++      data->viewport.x += src.x;
++      data->viewport.y += src.y;
++      ASSERT(src.x % vpc_div == 0 && src.y % vpc_div == 0);
++      data->viewport_c.x += src.x / vpc_div;
++      data->viewport_c.y += src.y / vpc_div;
+ }
+ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
+@@ -1131,48 +949,42 @@ 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;
+       bool res = false;
+-      int store_h_border_left = shift_border_left_to_dst(pipe_ctx);
+       DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger);
+-      /* 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->plane_res.scl_data.format = convert_pixel_format_to_dalsurface(
+                       pipe_ctx->plane_state->format);
+-      calculate_scaling_ratios(pipe_ctx);
+-
+-      calculate_viewport(pipe_ctx);
++      /* Timing borders are part of vactive that we are also supposed to skip in addition
++       * to any stream dst offset. Since dm logic assumes dst is in addressable
++       * space we need to add the the left and top borders to dst offsets temporarily.
++       * TODO: fix in DM, stream dst is supposed to be in vactive
++       */
++      pipe_ctx->stream->dst.x += timing->h_border_left;
++      pipe_ctx->stream->dst.y += timing->v_border_top;
+-      if (pipe_ctx->plane_res.scl_data.viewport.height < MIN_VIEWPORT_SIZE ||
+-              pipe_ctx->plane_res.scl_data.viewport.width < MIN_VIEWPORT_SIZE) {
+-              if (store_h_border_left) {
+-                      restore_border_left_from_dst(pipe_ctx,
+-                              store_h_border_left);
+-              }
+-              return false;
+-      }
++      /* Calculate H and V active size */
++      pipe_ctx->plane_res.scl_data.h_active = timing->h_addressable +
++                      timing->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;
++      /* depends on h_active */
+       calculate_recout(pipe_ctx);
++      /* depends on pixel format */
++      calculate_scaling_ratios(pipe_ctx);
++      /* depends on scaling ratios and recout, does not calculate offset yet */
++      calculate_viewport_size(pipe_ctx);
+-      /**
++      /*
++       * LB calculations depend on vp size, h/v_active and scaling ratios
+        * Setting line buffer pixel depth to 24bpp yields banding
+        * on certain displays, such as the Sharp 4k
+        */
+       pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP;
+       pipe_ctx->plane_res.scl_data.lb_params.alpha_en = plane_state->per_pixel_alpha;
+-      pipe_ctx->plane_res.scl_data.recout.x += timing->h_border_left;
+-      pipe_ctx->plane_res.scl_data.recout.y += timing->v_border_top;
+-
+-      pipe_ctx->plane_res.scl_data.h_active = timing->h_addressable +
+-              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)
+               res = pipe_ctx->plane_res.xfm->funcs->transform_get_optimal_number_of_taps(
+                               pipe_ctx->plane_res.xfm, &pipe_ctx->plane_res.scl_data, &plane_state->scaling_quality);
+@@ -1199,9 +1011,31 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
+                                       &plane_state->scaling_quality);
+       }
++      /*
++       * Depends on recout, scaling ratios, h_active and taps
++       * May need to re-check lb size after this in some obscure scenario
++       */
+       if (res)
+-              /* May need to re-check lb size after this in some obscure scenario */
+-              calculate_inits_and_adj_vp(pipe_ctx);
++              calculate_inits_and_viewports(pipe_ctx);
++
++      /*
++       * Handle side by side and top bottom 3d recout offsets after vp calculation
++       * since 3d is special and needs to calculate vp as if there is no recout offset
++       * This may break with rotation, good thing we aren't mixing hw rotation and 3d
++       */
++      if (pipe_ctx->top_pipe && pipe_ctx->top_pipe->plane_state == plane_state) {
++              ASSERT(plane_state->rotation == ROTATION_ANGLE_0 ||
++                      (pipe_ctx->stream->view_format != VIEW_3D_FORMAT_TOP_AND_BOTTOM &&
++                              pipe_ctx->stream->view_format != VIEW_3D_FORMAT_SIDE_BY_SIDE));
++              if (pipe_ctx->stream->view_format == VIEW_3D_FORMAT_TOP_AND_BOTTOM)
++                      pipe_ctx->plane_res.scl_data.recout.y += pipe_ctx->plane_res.scl_data.recout.height;
++              else if (pipe_ctx->stream->view_format == VIEW_3D_FORMAT_SIDE_BY_SIDE)
++                      pipe_ctx->plane_res.scl_data.recout.x += pipe_ctx->plane_res.scl_data.recout.width;
++      }
++
++      if (pipe_ctx->plane_res.scl_data.viewport.height < MIN_VIEWPORT_SIZE ||
++                      pipe_ctx->plane_res.scl_data.viewport.width < MIN_VIEWPORT_SIZE)
++              res = false;
+       DC_LOG_SCALER("%s pipe %d:\nViewport: height:%d width:%d x:%d y:%d  Recout: height:%d width:%d x:%d y:%d  HACTIVE:%d VACTIVE:%d\n"
+                       "src_rect: height:%d width:%d x:%d y:%d  dst_rect: height:%d width:%d x:%d y:%d  clip_rect: height:%d width:%d x:%d y:%d\n",
+@@ -1230,8 +1064,8 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
+                       plane_state->clip_rect.x,
+                       plane_state->clip_rect.y);
+-      if (store_h_border_left)
+-              restore_border_left_from_dst(pipe_ctx, store_h_border_left);
++      pipe_ctx->stream->dst.x -= timing->h_border_left;
++      pipe_ctx->stream->dst.y -= timing->v_border_top;
+       return res;
+ }
+diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h
+index c47a19719de2c..c8c2ba7e7b05c 100644
+--- a/drivers/gpu/drm/amd/display/dc/dc_types.h
++++ b/drivers/gpu/drm/amd/display/dc/dc_types.h
+@@ -268,11 +268,6 @@ struct dc_edid_caps {
+       struct dc_panel_patch panel_patch;
+ };
+-struct view {
+-      uint32_t width;
+-      uint32_t height;
+-};
+-
+ struct dc_mode_flags {
+       /* note: part of refresh rate flag*/
+       uint32_t INTERLACE :1;
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c
+index 8bb5912d837d4..bd842055ea95b 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c
+@@ -617,8 +617,10 @@ static void dpp1_dscl_set_manual_ratio_init(
+               SCL_V_INIT_INT, init_int);
+       if (REG(SCL_VERT_FILTER_INIT_BOT)) {
+-              init_frac = dc_fixpt_u0d19(data->inits.v_bot) << 5;
+-              init_int = dc_fixpt_floor(data->inits.v_bot);
++              struct fixed31_32 bot = dc_fixpt_add(data->inits.v, data->ratios.vert);
++
++              init_frac = dc_fixpt_u0d19(bot) << 5;
++              init_int = dc_fixpt_floor(bot);
+               REG_SET_2(SCL_VERT_FILTER_INIT_BOT, 0,
+                       SCL_V_INIT_FRAC_BOT, init_frac,
+                       SCL_V_INIT_INT_BOT, init_int);
+@@ -631,8 +633,10 @@ static void dpp1_dscl_set_manual_ratio_init(
+               SCL_V_INIT_INT_C, init_int);
+       if (REG(SCL_VERT_FILTER_INIT_BOT_C)) {
+-              init_frac = dc_fixpt_u0d19(data->inits.v_c_bot) << 5;
+-              init_int = dc_fixpt_floor(data->inits.v_c_bot);
++              struct fixed31_32 bot = dc_fixpt_add(data->inits.v_c, data->ratios.vert_c);
++
++              init_frac = dc_fixpt_u0d19(bot) << 5;
++              init_int = dc_fixpt_floor(bot);
+               REG_SET_2(SCL_VERT_FILTER_INIT_BOT_C, 0,
+                       SCL_V_INIT_FRAC_BOT_C, init_frac,
+                       SCL_V_INIT_INT_BOT_C, init_int);
+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 53ac826935328..b4bff3b3d842d 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
+@@ -2281,12 +2281,14 @@ int dcn20_populate_dml_pipes_from_context(
+                       pipes[pipe_cnt].pipe.src.source_scan = pln->rotation == ROTATION_ANGLE_90
+                                       || pln->rotation == ROTATION_ANGLE_270 ? dm_vert : dm_horz;
+-                      pipes[pipe_cnt].pipe.src.viewport_y_y = scl->viewport_unadjusted.y;
+-                      pipes[pipe_cnt].pipe.src.viewport_y_c = scl->viewport_c_unadjusted.y;
+-                      pipes[pipe_cnt].pipe.src.viewport_width = scl->viewport_unadjusted.width;
+-                      pipes[pipe_cnt].pipe.src.viewport_width_c = scl->viewport_c_unadjusted.width;
+-                      pipes[pipe_cnt].pipe.src.viewport_height = scl->viewport_unadjusted.height;
+-                      pipes[pipe_cnt].pipe.src.viewport_height_c = scl->viewport_c_unadjusted.height;
++                      pipes[pipe_cnt].pipe.src.viewport_y_y = scl->viewport.y;
++                      pipes[pipe_cnt].pipe.src.viewport_y_c = scl->viewport_c.y;
++                      pipes[pipe_cnt].pipe.src.viewport_width = scl->viewport.width;
++                      pipes[pipe_cnt].pipe.src.viewport_width_c = scl->viewport_c.width;
++                      pipes[pipe_cnt].pipe.src.viewport_height = scl->viewport.height;
++                      pipes[pipe_cnt].pipe.src.viewport_height_c = scl->viewport_c.height;
++                      pipes[pipe_cnt].pipe.src.viewport_width_max = pln->src_rect.width;
++                      pipes[pipe_cnt].pipe.src.viewport_height_max = pln->src_rect.height;
+                       pipes[pipe_cnt].pipe.src.surface_width_y = pln->plane_size.surface_size.width;
+                       pipes[pipe_cnt].pipe.src.surface_height_y = pln->plane_size.surface_size.height;
+                       pipes[pipe_cnt].pipe.src.surface_width_c = pln->plane_size.chroma_size.width;
+diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h
+index 6ab74640c0da7..a86b821d61c82 100644
+--- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h
++++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h
+@@ -255,6 +255,8 @@ struct _vcs_dpi_display_pipe_source_params_st {
+       unsigned int viewport_y_c;
+       unsigned int viewport_width_c;
+       unsigned int viewport_height_c;
++      unsigned int viewport_width_max;
++      unsigned int viewport_height_max;
+       unsigned int data_pitch;
+       unsigned int data_pitch_c;
+       unsigned int meta_pitch;
+diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c
+index b320931360893..079fa52a73791 100644
+--- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c
++++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c
+@@ -628,6 +628,19 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib)
+                               }
+                       }
+               }
++              if (src->viewport_width_max) {
++                      int hdiv_c = src->source_format >= dm_420_8 && src->source_format <= dm_422_10 ? 2 : 1;
++                      int vdiv_c = src->source_format >= dm_420_8 && src->source_format <= dm_420_12 ? 2 : 1;
++
++                      if (mode_lib->vba.ViewportWidth[mode_lib->vba.NumberOfActivePlanes] > src->viewport_width_max)
++                              mode_lib->vba.ViewportWidth[mode_lib->vba.NumberOfActivePlanes] = src->viewport_width_max;
++                      if (mode_lib->vba.ViewportHeight[mode_lib->vba.NumberOfActivePlanes] > src->viewport_height_max)
++                              mode_lib->vba.ViewportHeight[mode_lib->vba.NumberOfActivePlanes] = src->viewport_height_max;
++                      if (mode_lib->vba.ViewportWidthChroma[mode_lib->vba.NumberOfActivePlanes] > src->viewport_width_max / hdiv_c)
++                              mode_lib->vba.ViewportWidthChroma[mode_lib->vba.NumberOfActivePlanes] = src->viewport_width_max / hdiv_c;
++                      if (mode_lib->vba.ViewportHeightChroma[mode_lib->vba.NumberOfActivePlanes] > src->viewport_height_max / vdiv_c)
++                              mode_lib->vba.ViewportHeightChroma[mode_lib->vba.NumberOfActivePlanes] = src->viewport_height_max / vdiv_c;
++              }
+               if (pipes[k].pipe.src.immediate_flip) {
+                       mode_lib->vba.ImmediateFlipSupport = true;
+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 2947d1b155129..2a0db2b03047e 100644
+--- a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h
++++ b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h
+@@ -162,9 +162,7 @@ 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 {
+@@ -173,8 +171,6 @@ struct scaler_data {
+       struct scaling_taps taps;
+       struct rect viewport;
+       struct rect viewport_c;
+-      struct rect viewport_unadjusted;
+-      struct rect viewport_c_unadjusted;
+       struct rect recout;
+       struct scaling_ratios ratios;
+       struct scl_inits inits;
+-- 
+2.39.5
+
diff --git a/queue-5.10/drm-amd-display-reject-too-small-viewport-size-when-.patch b/queue-5.10/drm-amd-display-reject-too-small-viewport-size-when-.patch
new file mode 100644 (file)
index 0000000..1ff9d75
--- /dev/null
@@ -0,0 +1,103 @@
+From 2062cc888befbf073a452dccf5235478ad943099 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 Jan 2021 22:35:54 -0500
+Subject: drm/amd/display: Reject too small viewport size when validating plane
+
+From: Nikola Cornij <nikola.cornij@amd.com>
+
+[ Upstream commit 40d916a2602c8920e0f04a49abfd1ff7c1e54e91 ]
+
+[why]
+Overlay won't move to a new positon if viewport size is smaller than
+what can be handled. It'd either disappear or stay at the old
+position. This condition is for example hit if overlay is moved too
+much outside of left or top edge of the screen, but it applies to
+any non-cursor plane type.
+
+[how]
+Reject this contidion at validation time. This gives the calling
+level a chance to handle this gracefully and avoid inconsistent
+behaivor.
+
+Signed-off-by: Nikola Cornij <nikola.cornij@amd.com>
+Reviewed-by: Nicholas Kazlauskas <Nicholas.Kazlauskas@amd.com>
+Acked-by: Anson Jacob <Anson.Jacob@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Stable-dep-of: 374c9faac5a7 ("drm/amd/display: Fix null check for pipe_ctx->plane_state in resource_build_scaling_params")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 27 ++++++++++++++++++-
+ .../gpu/drm/amd/display/dc/core/dc_resource.c |  4 +--
+ drivers/gpu/drm/amd/display/dc/dc.h           |  1 +
+ 3 files changed, 29 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+index 4b4de1751c53f..786cd892f1797 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -6066,8 +6066,33 @@ static int dm_plane_helper_check_state(struct drm_plane_state *state,
+       int min_scale = 0;
+       int max_scale = INT_MAX;
+-      /* Plane enabled? Get min/max allowed scaling factors from plane caps. */
++      /* Plane enabled? Validate viewport and get scaling factors from plane caps. */
+       if (fb && state->crtc) {
++              /* Validate viewport to cover the case when only the position changes */
++              if (state->plane->type != DRM_PLANE_TYPE_CURSOR) {
++                      int viewport_width = state->crtc_w;
++                      int viewport_height = state->crtc_h;
++
++                      if (state->crtc_x < 0)
++                              viewport_width += state->crtc_x;
++                      else if (state->crtc_x + state->crtc_w > new_crtc_state->mode.crtc_hdisplay)
++                              viewport_width = new_crtc_state->mode.crtc_hdisplay - state->crtc_x;
++
++                      if (state->crtc_y < 0)
++                              viewport_height += state->crtc_y;
++                      else if (state->crtc_y + state->crtc_h > new_crtc_state->mode.crtc_vdisplay)
++                              viewport_height = new_crtc_state->mode.crtc_vdisplay - state->crtc_y;
++
++                      /* If completely outside of screen, viewport_width and/or viewport_height will be negative,
++                       * which is still OK to satisfy the condition below, thereby also covering these cases
++                       * (when plane is completely outside of screen).
++                       * x2 for width is because of pipe-split.
++                       */
++                      if (viewport_width < MIN_VIEWPORT_SIZE*2 || viewport_height < MIN_VIEWPORT_SIZE)
++                              return -EINVAL;
++              }
++
++              /* Get min/max allowed scaling factors from plane caps. */
+               get_min_max_dc_plane_scaling(state->crtc->dev, fb,
+                                            &min_downscale, &max_upscale);
+               /*
+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 5dc6840cea248..d77001b2e106b 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+@@ -1144,8 +1144,8 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
+       calculate_viewport(pipe_ctx);
+-      if (pipe_ctx->plane_res.scl_data.viewport.height < 12 ||
+-              pipe_ctx->plane_res.scl_data.viewport.width < 12) {
++      if (pipe_ctx->plane_res.scl_data.viewport.height < MIN_VIEWPORT_SIZE ||
++              pipe_ctx->plane_res.scl_data.viewport.width < MIN_VIEWPORT_SIZE) {
+               if (store_h_border_left) {
+                       restore_border_left_from_dst(pipe_ctx,
+                               store_h_border_left);
+diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
+index 1df7c49ac8d77..d3a4a55f3f1fa 100644
+--- a/drivers/gpu/drm/amd/display/dc/dc.h
++++ b/drivers/gpu/drm/amd/display/dc/dc.h
+@@ -48,6 +48,7 @@
+ #define MAX_PLANES 6
+ #define MAX_STREAMS 6
+ #define MAX_SINKS_PER_LINK 4
++#define MIN_VIEWPORT_SIZE 12
+ /*******************************************************************************
+  * Display Core Interfaces
+-- 
+2.39.5
+
diff --git a/queue-5.10/i2c-ali1535-fix-an-error-handling-path-in-ali1535_pr.patch b/queue-5.10/i2c-ali1535-fix-an-error-handling-path-in-ali1535_pr.patch
new file mode 100644 (file)
index 0000000..cf2ccc7
--- /dev/null
@@ -0,0 +1,55 @@
+From bd0a89a159d1ec5c6c15fed1fdc6145107b62766 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Mar 2025 20:53:08 +0100
+Subject: i2c: ali1535: Fix an error handling path in ali1535_probe()
+
+From: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+
+[ Upstream commit 9b5463f349d019a261f1e80803447efca3126151 ]
+
+If i2c_add_adapter() fails, the request_region() call in ali1535_setup()
+must be undone by a corresponding release_region() call, as done in the
+remove function.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+Signed-off-by: Andi Shyti <andi.shyti@kernel.org>
+Link: https://lore.kernel.org/r/0daf63d7a2ce74c02e2664ba805bbfadab7d25e5.1741031571.git.christophe.jaillet@wanadoo.fr
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/i2c/busses/i2c-ali1535.c | 12 +++++++++++-
+ 1 file changed, 11 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c
+index fb93152845f43..b36b75fc5b089 100644
+--- a/drivers/i2c/busses/i2c-ali1535.c
++++ b/drivers/i2c/busses/i2c-ali1535.c
+@@ -490,6 +490,8 @@ MODULE_DEVICE_TABLE(pci, ali1535_ids);
+ static int ali1535_probe(struct pci_dev *dev, const struct pci_device_id *id)
+ {
++      int ret;
++
+       if (ali1535_setup(dev)) {
+               dev_warn(&dev->dev,
+                       "ALI1535 not detected, module not inserted.\n");
+@@ -501,7 +503,15 @@ static int ali1535_probe(struct pci_dev *dev, const struct pci_device_id *id)
+       snprintf(ali1535_adapter.name, sizeof(ali1535_adapter.name),
+               "SMBus ALI1535 adapter at %04x", ali1535_offset);
+-      return i2c_add_adapter(&ali1535_adapter);
++      ret = i2c_add_adapter(&ali1535_adapter);
++      if (ret)
++              goto release_region;
++
++      return 0;
++
++release_region:
++      release_region(ali1535_smba, ALI1535_SMB_IOSIZE);
++      return ret;
+ }
+ static void ali1535_remove(struct pci_dev *dev)
+-- 
+2.39.5
+
diff --git a/queue-5.10/i2c-ali15x3-fix-an-error-handling-path-in-ali15x3_pr.patch b/queue-5.10/i2c-ali15x3-fix-an-error-handling-path-in-ali15x3_pr.patch
new file mode 100644 (file)
index 0000000..b857afe
--- /dev/null
@@ -0,0 +1,55 @@
+From 073a4b895b28a4e59566f75b4171ada4df2e17dd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Mar 2025 20:58:06 +0100
+Subject: i2c: ali15x3: Fix an error handling path in ali15x3_probe()
+
+From: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+
+[ Upstream commit 6e55caaf30c88209d097e575a169b1dface1ab69 ]
+
+If i2c_add_adapter() fails, the request_region() call in ali15x3_setup()
+must be undone by a corresponding release_region() call, as done in the
+remove function.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+Signed-off-by: Andi Shyti <andi.shyti@kernel.org>
+Link: https://lore.kernel.org/r/9b2090cbcc02659f425188ea05f2e02745c4e67b.1741031878.git.christophe.jaillet@wanadoo.fr
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/i2c/busses/i2c-ali15x3.c | 12 +++++++++++-
+ 1 file changed, 11 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c
+index cc58feacd0821..28a57cb6efb99 100644
+--- a/drivers/i2c/busses/i2c-ali15x3.c
++++ b/drivers/i2c/busses/i2c-ali15x3.c
+@@ -473,6 +473,8 @@ MODULE_DEVICE_TABLE (pci, ali15x3_ids);
+ static int ali15x3_probe(struct pci_dev *dev, const struct pci_device_id *id)
+ {
++      int ret;
++
+       if (ali15x3_setup(dev)) {
+               dev_err(&dev->dev,
+                       "ALI15X3 not detected, module not inserted.\n");
+@@ -484,7 +486,15 @@ static int ali15x3_probe(struct pci_dev *dev, const struct pci_device_id *id)
+       snprintf(ali15x3_adapter.name, sizeof(ali15x3_adapter.name),
+               "SMBus ALI15X3 adapter at %04x", ali15x3_smba);
+-      return i2c_add_adapter(&ali15x3_adapter);
++      ret = i2c_add_adapter(&ali15x3_adapter);
++      if (ret)
++              goto release_region;
++
++      return 0;
++
++release_region:
++      release_region(ali15x3_smba, ALI15X3_SMB_IOSIZE);
++      return ret;
+ }
+ static void ali15x3_remove(struct pci_dev *dev)
+-- 
+2.39.5
+
diff --git a/queue-5.10/i2c-sis630-fix-an-error-handling-path-in-sis630_prob.patch b/queue-5.10/i2c-sis630-fix-an-error-handling-path-in-sis630_prob.patch
new file mode 100644 (file)
index 0000000..e23744d
--- /dev/null
@@ -0,0 +1,55 @@
+From c3c5af5afe55c5cf5b8839b68e592ba7e457cfe3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 3 Mar 2025 21:26:54 +0100
+Subject: i2c: sis630: Fix an error handling path in sis630_probe()
+
+From: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+
+[ Upstream commit 2b22459792fcb4def9f0936d64575ac11a95a58d ]
+
+If i2c_add_adapter() fails, the request_region() call in sis630_setup()
+must be undone by a corresponding release_region() call, as done in the
+remove function.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+Link: https://lore.kernel.org/r/3d607601f2c38e896b10207963c6ab499ca5c307.1741033587.git.christophe.jaillet@wanadoo.fr
+Signed-off-by: Andi Shyti <andi.shyti@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/i2c/busses/i2c-sis630.c | 12 +++++++++++-
+ 1 file changed, 11 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/i2c/busses/i2c-sis630.c b/drivers/i2c/busses/i2c-sis630.c
+index cfb8e04a2a831..6befa6ff83f26 100644
+--- a/drivers/i2c/busses/i2c-sis630.c
++++ b/drivers/i2c/busses/i2c-sis630.c
+@@ -509,6 +509,8 @@ MODULE_DEVICE_TABLE(pci, sis630_ids);
+ static int sis630_probe(struct pci_dev *dev, const struct pci_device_id *id)
+ {
++      int ret;
++
+       if (sis630_setup(dev)) {
+               dev_err(&dev->dev,
+                       "SIS630 compatible bus not detected, "
+@@ -522,7 +524,15 @@ static int sis630_probe(struct pci_dev *dev, const struct pci_device_id *id)
+       snprintf(sis630_adapter.name, sizeof(sis630_adapter.name),
+                "SMBus SIS630 adapter at %04x", smbus_base + SMB_STS);
+-      return i2c_add_adapter(&sis630_adapter);
++      ret = i2c_add_adapter(&sis630_adapter);
++      if (ret)
++              goto release_region;
++
++      return 0;
++
++release_region:
++      release_region(smbus_base + SMB_STS, SIS630_SMB_IOREGION);
++      return ret;
+ }
+ static void sis630_remove(struct pci_dev *dev)
+-- 
+2.39.5
+
index 35eeeaba9c314c6d943d5660ad5f79151e50acf7..6eb9ef1add08b349da5230942c24bcc65af18afd 100644 (file)
@@ -56,3 +56,12 @@ drm-amd-display-fix-slab-use-after-free-on-hdcp_work.patch
 qlcnic-fix-memory-leak-issues-in-qlcnic_sriov_common.c.patch
 drm-gma500-add-null-check-for-pci_gfx_root-in-mid_ge.patch
 asoc-codecs-wm0010-fix-error-handling-path-in-wm0010.patch
+i2c-ali1535-fix-an-error-handling-path-in-ali1535_pr.patch
+i2c-ali15x3-fix-an-error-handling-path-in-ali15x3_pr.patch
+i2c-sis630-fix-an-error-handling-path-in-sis630_prob.patch
+drm-amd-display-check-plane-scaling-against-format-s.patch
+drm-amd-display-dc-core-dc_resource-staticify-local-.patch
+drm-amd-display-reject-too-small-viewport-size-when-.patch
+drm-amd-display-fix-odm-scaling.patch
+drm-amd-display-check-for-invalid-input-params-when-.patch
+drm-amd-display-fix-null-check-for-pipe_ctx-plane_st.patch