@@ -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);
}