diff mbox series

[05/10] media: vim2m: use different framesizes for bayer formats

Message ID 52c07fa56e91243f05022ebae6a65da26e44e1f3.1551446121.git.mchehab+samsung@kernel.org (mailing list archive)
State New, archived
Headers show
Series Improvements and fixups for vim2m driver | expand

Commit Message

Mauro Carvalho Chehab March 1, 2019, 1:24 p.m. UTC
The only real restriction at vim2m is that width should be
multiple of two, as the copy routine always copy two pixels
each time.

However, Bayer formats are defined as having a 2x2 matrix.
So, odd vertical numbers would cause color distortions at the
last line. So, it makes sense to use step 2 for vertical alignment
on Bayer.

With this patch, the reported formats for video capture will
be:

	[0]: 'RGBP' (16-bit RGB 5-6-5)
		Size: Stepwise 32x32 - 640x480 with step 2/1
	[1]: 'RGBR' (16-bit RGB 5-6-5 BE)
		Size: Stepwise 32x32 - 640x480 with step 2/1
	[2]: 'RGB3' (24-bit RGB 8-8-8)
		Size: Stepwise 32x32 - 640x480 with step 2/1
	[3]: 'BGR3' (24-bit BGR 8-8-8)
		Size: Stepwise 32x32 - 640x480 with step 2/1
	[4]: 'YUYV' (YUYV 4:2:2)
		Size: Stepwise 32x32 - 640x480 with step 2/1
	[5]: 'BA81' (8-bit Bayer BGBG/GRGR)
		Size: Stepwise 32x32 - 640x480 with step 2/2
	[6]: 'GBRG' (8-bit Bayer GBGB/RGRG)
		Size: Stepwise 32x32 - 640x480 with step 2/2
	[7]: 'GRBG' (8-bit Bayer GRGR/BGBG)
		Size: Stepwise 32x32 - 640x480 with step 2/2
	[8]: 'RGGB' (8-bit Bayer RGRG/GBGB)
		Size: Stepwise 32x32 - 640x480 with step 2/2

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

Patch

diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/vim2m.c
index bac9d4733d65..5157a59aeb58 100644
--- a/drivers/media/platform/vim2m.c
+++ b/drivers/media/platform/vim2m.c
@@ -50,7 +50,14 @@  MODULE_PARM_DESC(default_transtime, "default transaction time in ms");
 #define MIN_H 32
 #define MAX_W 640
 #define MAX_H 480
-#define WIDTH_ALIGN 2 /* 2-byte alignment */
+
+/* Pixel alignment for non-bayer formats */
+#define WIDTH_ALIGN 2
+#define HEIGHT_ALIGN 1
+
+/* Pixel alignment for bayer formats */
+#define BAYER_WIDTH_ALIGN  2
+#define BAYER_HEIGHT_ALIGN 2
 
 /* Flags that indicate a format can be used for capture/output */
 #define MEM2MEM_CAPTURE	(1 << 0)
@@ -162,6 +169,24 @@  static struct vim2m_fmt *find_format(u32 fourcc)
 	return &formats[k];
 }
 
+void static get_alignment(u32 fourcc,
+			  unsigned int *walign, unsigned int *halign)
+{
+	switch(fourcc) {
+	case V4L2_PIX_FMT_SBGGR8:
+	case V4L2_PIX_FMT_SGBRG8:
+	case V4L2_PIX_FMT_SGRBG8:
+	case V4L2_PIX_FMT_SRGGB8:
+		*walign = BAYER_WIDTH_ALIGN;
+		*halign = BAYER_HEIGHT_ALIGN;
+		return;
+	default:
+		*walign = WIDTH_ALIGN;
+		*halign = HEIGHT_ALIGN;
+		return;
+	}
+}
+
 struct vim2m_dev {
 	struct v4l2_device	v4l2_dev;
 	struct video_device	vfd;
@@ -689,8 +714,10 @@  static int vidioc_enum_framesizes(struct file *file, void *priv,
 	fsize->stepwise.min_height =MIN_H;
 	fsize->stepwise.max_width = MAX_W;
 	fsize->stepwise.max_height = MAX_H;
-	fsize->stepwise.step_width = WIDTH_ALIGN;
-	fsize->stepwise.step_height = 1;
+
+	get_alignment(fsize->pixel_format,
+		      &fsize->stepwise.step_width,
+		      &fsize->stepwise.step_height);
 	return 0;
 }
 
@@ -733,6 +760,7 @@  static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
 
 static int vidioc_try_fmt(struct v4l2_format *f, struct vim2m_fmt *fmt)
 {
+	int walign, halign;
 	/* V4L2 specification suggests the driver corrects the format struct
 	 * if any of the dimensions is unsupported */
 	if (f->fmt.pix.height < MIN_H)
@@ -745,7 +773,9 @@  static int vidioc_try_fmt(struct v4l2_format *f, struct vim2m_fmt *fmt)
 	else if (f->fmt.pix.width > MAX_W)
 		f->fmt.pix.width = MAX_W;
 
-	f->fmt.pix.width &= ~(WIDTH_ALIGN - 1);
+	get_alignment(f->fmt.pix.pixelformat, &walign, &halign);
+	f->fmt.pix.width &= ~(walign - 1);
+	f->fmt.pix.height &= ~(halign - 1);
 	f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3;
 	f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
 	f->fmt.pix.field = V4L2_FIELD_NONE;