diff mbox series

[1/3] media: vim2m: add vertical linear scaler

Message ID 8d53fe1c2d8305dda9a360ace275c63dfacc3b1f.1551444730.git.mchehab+samsung@kernel.org (mailing list archive)
State New, archived
Headers show
Series [1/3] media: vim2m: add vertical linear scaler | expand

Commit Message

Mauro Carvalho Chehab March 1, 2019, 12:52 p.m. UTC
When resolutions are different, the expected behavior is to
scale the image. Implement a vertical scaler as the first step.

Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
---
 drivers/media/platform/vim2m.c | 65 +++++++++++++++++-----------------
 1 file changed, 32 insertions(+), 33 deletions(-)
diff mbox series

Patch

diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/vim2m.c
index ec177de144b6..1708becbaa9d 100644
--- a/drivers/media/platform/vim2m.c
+++ b/drivers/media/platform/vim2m.c
@@ -267,23 +267,17 @@  static const char *type_name(enum v4l2_buf_type type)
 #define CLIP(__color) \
 	(u8)(((__color) > 0xff) ? 0xff : (((__color) < 0) ? 0 : (__color)))
 
-static int fast_copy_two_pixels(struct vim2m_q_data *q_data_in,
+static void fast_copy_two_pixels(struct vim2m_q_data *q_data_in,
 				 struct vim2m_q_data *q_data_out,
-				 u8 **src, u8 **dst, int ypos, bool reverse)
+				 u8 **src, u8 **dst, bool reverse)
 {
 	int depth = q_data_out->fmt->depth >> 3;
 
-	/* Only do fast copy when format and resolution are identical */
-	if (q_data_in->fmt->fourcc != q_data_out->fmt->fourcc ||
-	    q_data_in->width != q_data_out->width ||
-	    q_data_in->height != q_data_out->height)
-		return 0;
-
 	if (!reverse) {
 		memcpy(*dst, *src, depth << 1);
 		*src += depth << 1;
 		*dst += depth << 1;
-		return 1;
+		return;
 	}
 
 	/* Copy line at reverse order - YUYV format */
@@ -303,7 +297,7 @@  static int fast_copy_two_pixels(struct vim2m_q_data *q_data_in,
 		*(*dst)++ = u;
 		*(*dst)++ = y1;
 		*(*dst)++ = v;
-		return 1;
+		return;
 	}
 
 	/* copy RGB formats in reverse order */
@@ -311,7 +305,7 @@  static int fast_copy_two_pixels(struct vim2m_q_data *q_data_in,
 	memcpy(*dst + depth, *src - depth, depth);
 	*src -= depth << 1;
 	*dst += depth << 1;
-	return 1;
+	return;
 }
 
 static void copy_two_pixels(struct vim2m_q_data *q_data_in,
@@ -323,11 +317,6 @@  static void copy_two_pixels(struct vim2m_q_data *q_data_in,
 	u8 _r[2], _g[2], _b[2], *r, *g, *b;
 	int i, step;
 
-	// If format is the same just copy the data, respecting the width
-	if (fast_copy_two_pixels(q_data_in, q_data_out,
-				 src, dst, ypos, reverse))
-	  return;
-
 	/* Step 1: read two consecutive pixels from src pointer */
 
 	r = _r;
@@ -527,25 +516,25 @@  static int device_process(struct vim2m_ctx *ctx,
 	struct vim2m_q_data *q_data_in, *q_data_out;
 	u8 *p_in, *p, *p_out;
 	unsigned int width, height, bytesperline, bytesperline_out;
-	unsigned int x, y, y_out;
+	unsigned int x, y, y_in, y_out;
 	int start, end, step;
 	struct vim2m_fmt *in, *out;
 
 	q_data_in = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
 	in = q_data_in->fmt;
-	width = q_data_in->width;
-	height = q_data_in->height;
 	bytesperline = (q_data_in->width * q_data_in->fmt->depth) >> 3;
 
 	q_data_out = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
 	bytesperline_out = (q_data_out->width * q_data_out->fmt->depth) >> 3;
 	out = q_data_out->fmt;
 
+	/* As we're doing vertical scaling use the out height here */
+	height = q_data_out->height;
+
 	/* Crop to the limits of the destination image */
+	width = q_data_in->width;
 	if (width > q_data_out->width)
 		width = q_data_out->width;
-	if (height > q_data_out->height)
-		height = q_data_out->height;
 
 	p_in = vb2_plane_vaddr(&in_vb->vb2_buf, 0);
 	p_out = vb2_plane_vaddr(&out_vb->vb2_buf, 0);
@@ -555,17 +544,6 @@  static int device_process(struct vim2m_ctx *ctx,
 		return -EFAULT;
 	}
 
-	/*
-	 * FIXME: instead of cropping the image and zeroing any
-	 * extra data, the proper behavior is to either scale the
-	 * data or report that scale is not supported (with depends
-	 * on some API for such purpose).
-	 */
-
-	/* Image size is different. Zero buffer first */
-	if (q_data_in->width  != q_data_out->width ||
-	    q_data_in->height != q_data_out->height)
-		memset(p_out, 0, q_data_out->sizeimage);
 	out_vb->sequence = get_q_data(ctx,
 				      V4L2_BUF_TYPE_VIDEO_CAPTURE)->sequence++;
 	in_vb->sequence = q_data_in->sequence++;
@@ -581,8 +559,29 @@  static int device_process(struct vim2m_ctx *ctx,
 		step = 1;
 	}
 	y_out = 0;
+
+	/* Faster copy logic,  when format and resolution are identical */
+	if (q_data_in->fmt->fourcc == q_data_out->fmt->fourcc &&
+	    q_data_in->width == q_data_out->width &&
+	    q_data_in->height == q_data_out->height) {
+		for (y = start; y != end; y += step, y_out++) {
+			p = p_in + (y * bytesperline);
+			if (ctx->mode & MEM2MEM_HFLIP)
+				p += bytesperline - (q_data_in->fmt->depth >> 3);
+
+			for (x = 0; x < width >> 1; x++)
+				fast_copy_two_pixels(q_data_in, q_data_out,
+						     &p, &p_out,
+						     ctx->mode & MEM2MEM_HFLIP);
+		}
+		return 0;
+	}
+
+	/* Slower algorithm with format conversion and scaler */
 	for (y = start; y != end; y += step, y_out++) {
-		p = p_in + (y * bytesperline);
+		y_in = (y * q_data_in->height) / q_data_out->height;
+
+		p = p_in + (y_in * bytesperline);
 		if (ctx->mode & MEM2MEM_HFLIP)
 			p += bytesperline - (q_data_in->fmt->depth >> 3);