diff mbox

[12/16] s5p-jpeg: Ensure correct capture format for Exynos4x12

Message ID 1384871228-6648-13-git-send-email-j.anaszewski@samsung.com (mailing list archive)
State New, archived
Headers show

Commit Message

Jacek Anaszewski Nov. 19, 2013, 2:27 p.m. UTC
Adjust capture format to the Exynos4x12 device limitations,
according to the subsampling value parsed from the source
JPEG image header. If the capture format was set to YUV with
subsampling lower than the one of the source JPEG image
the decoding process would not succeed.

Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 drivers/media/platform/s5p-jpeg/jpeg-core.c |   78 +++++++++++++++++++++++++++
 1 file changed, 78 insertions(+)
diff mbox

Patch

diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c
index e09b03a..15b2dea 100644
--- a/drivers/media/platform/s5p-jpeg/jpeg-core.c
+++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c
@@ -941,6 +941,7 @@  static int s5p_jpeg_try_fmt_vid_cap(struct file *file, void *priv,
 				  struct v4l2_format *f)
 {
 	struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
+	struct v4l2_pix_format *pix = &f->fmt.pix;
 	struct s5p_jpeg_fmt *fmt;
 
 	fmt = s5p_jpeg_find_format(ctx, f->fmt.pix.pixelformat,
@@ -952,6 +953,83 @@  static int s5p_jpeg_try_fmt_vid_cap(struct file *file, void *priv,
 		return -EINVAL;
 	}
 
+	/*
+	 * The exynos4x12 device requires resulting YUV image
+	 * subsampling not to be lower than the input jpeg subsampling.
+	 * If this requirement is not met then downgrade the requested
+	 * output format to the one with subsampling equal to the input jpeg.
+	 */
+	if ((ctx->jpeg->variant->version != SJPEG_S5P) &&
+	    (ctx->mode == S5P_JPEG_DECODE) &&
+	    (fmt->flags & SJPEG_FMT_NON_RGB) &&
+	    (fmt->subsampling < ctx->subsampling)) {
+		switch (fmt->fourcc) {
+		case V4L2_PIX_FMT_NV24:
+			switch (ctx->subsampling) {
+			case  V4L2_JPEG_CHROMA_SUBSAMPLING_422:
+				pix->pixelformat = V4L2_PIX_FMT_NV16;
+				break;
+			case  V4L2_JPEG_CHROMA_SUBSAMPLING_420:
+				pix->pixelformat = V4L2_PIX_FMT_NV12;
+				break;
+			case  V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY:
+				pix->pixelformat = V4L2_PIX_FMT_GREY;
+				break;
+			default:
+				return -EINVAL;
+			}
+			break;
+		case V4L2_PIX_FMT_NV42:
+			switch (ctx->subsampling) {
+			case  V4L2_JPEG_CHROMA_SUBSAMPLING_422:
+				pix->pixelformat = V4L2_PIX_FMT_NV61;
+				break;
+			case  V4L2_JPEG_CHROMA_SUBSAMPLING_420:
+				pix->pixelformat = V4L2_PIX_FMT_NV21;
+				break;
+			case  V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY:
+				pix->pixelformat = V4L2_PIX_FMT_GREY;
+				break;
+			default:
+				return -EINVAL;
+			}
+			break;
+		case V4L2_PIX_FMT_YUYV:
+		case V4L2_PIX_FMT_NV16:
+		case V4L2_PIX_FMT_YUV420:
+			switch (ctx->subsampling) {
+			case  V4L2_JPEG_CHROMA_SUBSAMPLING_420:
+				pix->pixelformat = V4L2_PIX_FMT_NV12;
+				break;
+			case  V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY:
+				pix->pixelformat = V4L2_PIX_FMT_GREY;
+				break;
+			default:
+				return -EINVAL;
+			}
+			break;
+		case V4L2_PIX_FMT_YVYU:
+		case V4L2_PIX_FMT_NV61:
+			switch (ctx->subsampling) {
+			case  V4L2_JPEG_CHROMA_SUBSAMPLING_420:
+				pix->pixelformat = V4L2_PIX_FMT_NV21;
+				break;
+			case  V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY:
+				pix->pixelformat = V4L2_PIX_FMT_GREY;
+				break;
+			default:
+				return -EINVAL;
+			}
+			break;
+		case V4L2_PIX_FMT_NV12:
+		case V4L2_PIX_FMT_NV21:
+			pix->pixelformat = V4L2_PIX_FMT_GREY;
+			break;
+		default:
+			return -EINVAL;
+		}
+	}
+
 	return vidioc_try_fmt(f, fmt, ctx, FMT_TYPE_CAPTURE);
 }