Blob Blame History Raw
From de2564c70fcc1dfee89fff92eccba5a711a921cc Mon Sep 17 00:00:00 2001
From: Philipp Zabel <p.zabel@pengutronix.de>
Date: Tue, 13 Aug 2019 13:42:58 +0200
Subject: gpu: ipu-v3: image-convert: fix image downsize coefficients and
 tiling calculation
Git-commit: de2564c70fcc1dfee89fff92eccba5a711a921cc
Patch-mainline: v5.4-rc1
References: bsc#1152489

This patch effectively reverts commit 912bbf7e9ca4 ("gpu: ipu-v3:
image-convert: Fix image downsize coefficients") and replaces it with a
different solution based on the preceding patches.

The previous fix tried to solve the problem of intermediate tile size
between IC downsizing and main processing sections not being limited to
1024 pixels by downsizing the input image to a smaller intermediate size
in the downsizing box filter. This causes unnecessary blurring,
especially for scaling factors close to 1.

Now that the seam position calculation makes sure that the 1024 pixel
intermediate tile size limit is not exceeded, calculate the number of
tiles from the maximum of intermediate size and output size and avoid
unnecessary downsizing.

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
---
 drivers/gpu/ipu-v3/ipu-image-convert.c | 49 ++++++++++++++++----------
 1 file changed, 31 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/ipu-v3/ipu-image-convert.c b/drivers/gpu/ipu-v3/ipu-image-convert.c
index a279d803ed91..a3375eec35ce 100644
--- a/drivers/gpu/ipu-v3/ipu-image-convert.c
+++ b/drivers/gpu/ipu-v3/ipu-image-convert.c
@@ -382,8 +382,11 @@ static inline int num_stripes(int dim)
 
 /*
  * Calculate downsizing coefficients, which are the same for all tiles,
- * and bilinear resizing coefficients, which are used to find the best
- * seam positions.
+ * and initial bilinear resizing coefficients, which are used to find the
+ * best seam positions.
+ * Also determine the number of tiles necessary to guarantee that no tile
+ * is larger than 1024 pixels in either dimension at the output and between
+ * IC downsizing and main processing sections.
  */
 static int calc_image_resize_coefficients(struct ipu_image_convert_ctx *ctx,
 					  struct ipu_image *in,
@@ -397,6 +400,8 @@ static int calc_image_resize_coefficients(struct ipu_image_convert_ctx *ctx,
 	u32 resized_height = out->rect.height;
 	u32 resize_coeff_h;
 	u32 resize_coeff_v;
+	u32 cols;
+	u32 rows;
 
 	if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
 		resized_width = out->rect.height;
@@ -407,14 +412,12 @@ static int calc_image_resize_coefficients(struct ipu_image_convert_ctx *ctx,
 	if (WARN_ON(resized_width == 0 || resized_height == 0))
 		return -EINVAL;
 
-	while (downsized_width > 1024 ||
-	       downsized_width >= resized_width * 2) {
+	while (downsized_width >= resized_width * 2) {
 		downsized_width >>= 1;
 		downsize_coeff_h++;
 	}
 
-	while (downsized_height > 1024 ||
-	       downsized_height >= resized_height * 2) {
+	while (downsized_height >= resized_height * 2) {
 		downsized_height >>= 1;
 		downsize_coeff_v++;
 	}
@@ -428,10 +431,18 @@ static int calc_image_resize_coefficients(struct ipu_image_convert_ctx *ctx,
 	resize_coeff_h = 8192 * (downsized_width - 1) / (resized_width - 1);
 	resize_coeff_v = 8192 * (downsized_height - 1) / (resized_height - 1);
 
+	/*
+	 * Both the output of the IC downsizing section before being passed to
+	 * the IC main processing section and the final output of the IC main
+	 * processing section must be <= 1024 pixels in both dimensions.
+	 */
+	cols = num_stripes(max_t(u32, downsized_width, resized_width));
+	rows = num_stripes(max_t(u32, downsized_height, resized_height));
+
 	dev_dbg(ctx->chan->priv->ipu->dev,
 		"%s: hscale: >>%u, *8192/%u vscale: >>%u, *8192/%u, %ux%u tiles\n",
 		__func__, downsize_coeff_h, resize_coeff_h, downsize_coeff_v,
-		resize_coeff_v, ctx->in.num_cols, ctx->in.num_rows);
+		resize_coeff_v, cols, rows);
 
 	if (downsize_coeff_h > 2 || downsize_coeff_v  > 2 ||
 	    resize_coeff_h > 0x3fff || resize_coeff_v > 0x3fff)
@@ -441,6 +452,8 @@ static int calc_image_resize_coefficients(struct ipu_image_convert_ctx *ctx,
 	ctx->downsize_coeff_v = downsize_coeff_v;
 	ctx->image_resize_coeff_h = resize_coeff_h;
 	ctx->image_resize_coeff_v = resize_coeff_v;
+	ctx->in.num_cols = cols;
+	ctx->in.num_rows = rows;
 
 	return 0;
 }
@@ -2038,22 +2051,26 @@ ipu_image_convert_prepare(struct ipu_soc *ipu, enum ipu_ic_task ic_task,
 	ctx->chan = chan;
 	init_completion(&ctx->aborted);
 
+	ctx->rot_mode = rot_mode;
+
+	/* Sets ctx->in.num_rows/cols as well */
+	ret = calc_image_resize_coefficients(ctx, in, out);
+	if (ret)
+		goto out_free;
+
 	s_image = &ctx->in;
 	d_image = &ctx->out;
 
 	/* set tiling and rotation */
-	d_image->num_rows = num_stripes(out->pix.height);
-	d_image->num_cols = num_stripes(out->pix.width);
 	if (ipu_rot_mode_is_irt(rot_mode)) {
-		s_image->num_rows = d_image->num_cols;
-		s_image->num_cols = d_image->num_rows;
+		d_image->num_rows = s_image->num_cols;
+		d_image->num_cols = s_image->num_rows;
 	} else {
-		s_image->num_rows = d_image->num_rows;
-		s_image->num_cols = d_image->num_cols;
+		d_image->num_rows = s_image->num_rows;
+		d_image->num_cols = s_image->num_cols;
 	}
 
 	ctx->num_tiles = d_image->num_cols * d_image->num_rows;
-	ctx->rot_mode = rot_mode;
 
 	ret = fill_image(ctx, s_image, in, IMAGE_CONVERT_IN);
 	if (ret)
@@ -2062,10 +2079,6 @@ ipu_image_convert_prepare(struct ipu_soc *ipu, enum ipu_ic_task ic_task,
 	if (ret)
 		goto out_free;
 
-	ret = calc_image_resize_coefficients(ctx, in, out);
-	if (ret)
-		goto out_free;
-
 	calc_out_tile_map(ctx);
 
 	find_seams(ctx, s_image, d_image);
-- 
2.28.0