summaryrefslogtreecommitdiff
path: root/drivers/gpu
diff options
context:
space:
mode:
authorPhilipp Zabel <p.zabel@pengutronix.de>2019-08-13 13:42:58 +0200
committerPhilipp Zabel <p.zabel@pengutronix.de>2019-08-19 16:25:30 +0200
commit2e67a553e965b32a648c85fbe1c667fa440d6c92 (patch)
tree35b4758f802c64a4394d666c481b438b13bffb76 /drivers/gpu
parent82c3e948cc0fe7e01b39d437f7a58b197ebb422d (diff)
gpu: ipu-v3: image-convert: limit input seam position to hardware requirements
Limit the input seam position to an interval that guarantees the tile size does not exceed 1024 pixels after the IC downsizing section and that space is left for the next tile. Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/ipu-v3/ipu-image-convert.c30
1 files changed, 24 insertions, 6 deletions
diff --git a/drivers/gpu/ipu-v3/ipu-image-convert.c b/drivers/gpu/ipu-v3/ipu-image-convert.c
index 40d450886e1d..a279d803ed91 100644
--- a/drivers/gpu/ipu-v3/ipu-image-convert.c
+++ b/drivers/gpu/ipu-v3/ipu-image-convert.c
@@ -487,6 +487,8 @@ static void find_best_seam(struct ipu_image_convert_ctx *ctx,
unsigned int min_diff = UINT_MAX;
unsigned int out_start;
unsigned int out_end;
+ unsigned int in_start;
+ unsigned int in_end;
/* Start within 1024 pixels of the right / bottom edge */
out_start = max_t(int, index * out_align, out_edge - 1024);
@@ -494,6 +496,15 @@ static void find_best_seam(struct ipu_image_convert_ctx *ctx,
out_end = min_t(unsigned int, out_edge, index * 1024 + 1);
/*
+ * Limit input seam position to make sure that the downsized input tile
+ * to the right or bottom does not exceed 1024 pixels.
+ */
+ in_start = max_t(int, index * in_align,
+ in_edge - (1024 << downsize_coeff));
+ in_end = min_t(unsigned int, in_edge,
+ index * (1024 << downsize_coeff) + 1);
+
+ /*
* Output tiles must start at a multiple of 8 bytes horizontally and
* possibly at an even line horizontally depending on the pixel format.
* Only consider output aligned positions for the seam.
@@ -502,6 +513,7 @@ static void find_best_seam(struct ipu_image_convert_ctx *ctx,
for (out_pos = out_start; out_pos < out_end; out_pos += out_align) {
unsigned int in_pos;
unsigned int in_pos_aligned;
+ unsigned int in_pos_rounded;
unsigned int abs_diff;
/*
@@ -522,9 +534,16 @@ static void find_best_seam(struct ipu_image_convert_ctx *ctx,
* start the input tile at, 19.13 fixed point.
*/
in_pos_aligned = round_closest(in_pos, 8192U * in_align);
+ /* Convert 19.13 fixed point to integer */
+ in_pos_rounded = in_pos_aligned / 8192U;
+
+ if (in_pos_rounded < in_start)
+ continue;
+ if (in_pos_rounded >= in_end)
+ break;
if ((in_burst > 1) &&
- (in_edge - in_pos_aligned / 8192U) % in_burst)
+ (in_edge - in_pos_rounded) % in_burst)
continue;
if (in_pos < in_pos_aligned)
@@ -533,19 +552,18 @@ static void find_best_seam(struct ipu_image_convert_ctx *ctx,
abs_diff = in_pos - in_pos_aligned;
if (abs_diff < min_diff) {
- in_seam = in_pos_aligned;
+ in_seam = in_pos_rounded;
out_seam = out_pos;
min_diff = abs_diff;
}
}
*_out_seam = out_seam;
- /* Convert 19.13 fixed point to integer seam position */
- *_in_seam = DIV_ROUND_CLOSEST(in_seam, 8192U);
+ *_in_seam = in_seam;
- dev_dbg(dev, "%s: out_seam %u(%u) in [%u, %u], in_seam %u(%u) diff %u.%03u\n",
+ dev_dbg(dev, "%s: out_seam %u(%u) in [%u, %u], in_seam %u(%u) in [%u, %u] diff %u.%03u\n",
__func__, out_seam, out_align, out_start, out_end,
- *_in_seam, in_align, min_diff / 8192,
+ in_seam, in_align, in_start, in_end, min_diff / 8192,
DIV_ROUND_CLOSEST(min_diff % 8192 * 1000, 8192));
}