media: platform: rename s5p-jpeg/ to samsung/s5p-jpeg/
authorMauro Carvalho Chehab <mchehab@kernel.org>
Sun, 13 Mar 2022 10:18:17 +0000 (11:18 +0100)
committerMauro Carvalho Chehab <mchehab@kernel.org>
Fri, 18 Mar 2022 04:58:34 +0000 (05:58 +0100)
As the end goal is to have platform drivers split by vendor,
rename s5p-jpeg/ to samsung/s5p-jpeg/.

Acked-by: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
27 files changed:
MAINTAINERS
drivers/media/platform/Kconfig
drivers/media/platform/Makefile
drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
drivers/media/platform/renesas/rcar_jpu.c
drivers/media/platform/s5p-jpeg/Kconfig [deleted file]
drivers/media/platform/s5p-jpeg/Makefile [deleted file]
drivers/media/platform/s5p-jpeg/jpeg-core.c [deleted file]
drivers/media/platform/s5p-jpeg/jpeg-core.h [deleted file]
drivers/media/platform/s5p-jpeg/jpeg-hw-exynos3250.c [deleted file]
drivers/media/platform/s5p-jpeg/jpeg-hw-exynos3250.h [deleted file]
drivers/media/platform/s5p-jpeg/jpeg-hw-exynos4.c [deleted file]
drivers/media/platform/s5p-jpeg/jpeg-hw-exynos4.h [deleted file]
drivers/media/platform/s5p-jpeg/jpeg-hw-s5p.c [deleted file]
drivers/media/platform/s5p-jpeg/jpeg-hw-s5p.h [deleted file]
drivers/media/platform/s5p-jpeg/jpeg-regs.h [deleted file]
drivers/media/platform/samsung/s5p-jpeg/Kconfig [new file with mode: 0644]
drivers/media/platform/samsung/s5p-jpeg/Makefile [new file with mode: 0644]
drivers/media/platform/samsung/s5p-jpeg/jpeg-core.c [new file with mode: 0644]
drivers/media/platform/samsung/s5p-jpeg/jpeg-core.h [new file with mode: 0644]
drivers/media/platform/samsung/s5p-jpeg/jpeg-hw-exynos3250.c [new file with mode: 0644]
drivers/media/platform/samsung/s5p-jpeg/jpeg-hw-exynos3250.h [new file with mode: 0644]
drivers/media/platform/samsung/s5p-jpeg/jpeg-hw-exynos4.c [new file with mode: 0644]
drivers/media/platform/samsung/s5p-jpeg/jpeg-hw-exynos4.h [new file with mode: 0644]
drivers/media/platform/samsung/s5p-jpeg/jpeg-hw-s5p.c [new file with mode: 0644]
drivers/media/platform/samsung/s5p-jpeg/jpeg-hw-s5p.h [new file with mode: 0644]
drivers/media/platform/samsung/s5p-jpeg/jpeg-regs.h [new file with mode: 0644]

index 23101a7367a572fec72f1b7041d0743d56ab641d..a19041a4b8fa492ae2fd0fc624383e20e5c96fee 100644 (file)
@@ -2633,7 +2633,7 @@ M:        Sylwester Nawrocki <s.nawrocki@samsung.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 L:     linux-media@vger.kernel.org
 S:     Maintained
-F:     drivers/media/platform/s5p-jpeg/
+F:     drivers/media/platform/samsung/s5p-jpeg/
 
 ARM/SAMSUNG S5P SERIES Multi Format Codec (MFC) SUPPORT
 M:     Marek Szyprowski <m.szyprowski@samsung.com>
index 6ab986c96cf22a275505f8bba4bf1bc94e1b288a..5f7a89e2af806aa0e0a4ef75a2dd8b9f717437cb 100644 (file)
@@ -87,12 +87,12 @@ source "drivers/media/platform/omap3isp/Kconfig"
 source "drivers/media/platform/qcom/Kconfig"
 source "drivers/media/platform/renesas/Kconfig"
 source "drivers/media/platform/rockchip/Kconfig"
-source "drivers/media/platform/s5p-jpeg/Kconfig"
 source "drivers/media/platform/s5p-mfc/Kconfig"
 source "drivers/media/platform/samsung/exynos-gsc/Kconfig"
 source "drivers/media/platform/samsung/exynos4-is/Kconfig"
 source "drivers/media/platform/samsung/s3c-camif/Kconfig"
 source "drivers/media/platform/samsung/s5p-g2d/Kconfig"
+source "drivers/media/platform/samsung/s5p-jpeg/Kconfig"
 source "drivers/media/platform/sti/Kconfig"
 source "drivers/media/platform/stm32/Kconfig"
 source "drivers/media/platform/sunxi/Kconfig"
index 4b3e4209eaf936c3fb458e0259ed6d63fdd45391..86f81e81dadc0caa8f7ebbaa7745ba043b2cd774 100644 (file)
@@ -29,12 +29,12 @@ obj-y += qcom/venus/
 obj-y += renesas/
 obj-y += rockchip/rga/
 obj-y += rockchip/rkisp1/
-obj-y += s5p-jpeg/
 obj-y += s5p-mfc/
 obj-y += samsung/exynos-gsc/
 obj-y += samsung/exynos4-is/
 obj-y += samsung/s3c-camif/
 obj-y += samsung/s5p-g2d/
+obj-y += samsung/s5p-jpeg/
 obj-y += sti/bdisp/
 obj-y += sti/c8sectpfe/
 obj-y += sti/delta/
index 3b892c5792b45f147c093fa27233d65e54304f3b..d1ec1f4b506b8220daac5b31aed1c6984107042e 100644 (file)
@@ -35,7 +35,7 @@
  * it, enable dynamic debug for this module and:
  * echo 1 > /sys/module/mxc_jpeg_encdec/parameters/jpeg_tracing
  *
- * This is inspired by the drivers/media/platform/s5p-jpeg driver
+ * This is inspired by the drivers/media/platform/samsung/s5p-jpeg driver
  *
  * Copyright 2018-2019 NXP
  */
index 56bb464629ed6ea5ea6fbcced134f5980e4cb33c..293beba131e2f897a8e8d03846a475c287e2c6a5 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright (C) 2014-2015 Cogent Embedded, Inc.  <source@cogentembedded.com>
  * Copyright (C) 2014-2015 Renesas Electronics Corporation
  *
- * This is based on the drivers/media/platform/s5p-jpeg driver by
+ * This is based on the drivers/media/platform/samsung/s5p-jpeg driver by
  * Andrzej Pietrasiewicz and Jacek Anaszewski.
  * Some portions of code inspired by VSP1 driver by Laurent Pinchart.
  *
diff --git a/drivers/media/platform/s5p-jpeg/Kconfig b/drivers/media/platform/s5p-jpeg/Kconfig
deleted file mode 100644 (file)
index e522860..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-
-config VIDEO_SAMSUNG_S5P_JPEG
-       tristate "Samsung S5P/Exynos3250/Exynos4 JPEG codec driver"
-       depends on V4L_MEM2MEM_DRIVERS
-       depends on VIDEO_DEV && VIDEO_V4L2
-       depends on ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST
-       select VIDEOBUF2_DMA_CONTIG
-       select V4L2_MEM2MEM_DEV
-       help
-         This is a v4l2 driver for Samsung S5P, EXYNOS3250
-         and EXYNOS4 JPEG codec
diff --git a/drivers/media/platform/s5p-jpeg/Makefile b/drivers/media/platform/s5p-jpeg/Makefile
deleted file mode 100644 (file)
index 8b0f92e..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-s5p-jpeg-objs := jpeg-core.o jpeg-hw-exynos3250.o jpeg-hw-exynos4.o jpeg-hw-s5p.o
-obj-$(CONFIG_VIDEO_SAMSUNG_S5P_JPEG) += s5p-jpeg.o
diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c
deleted file mode 100644 (file)
index a8d9159..0000000
+++ /dev/null
@@ -1,3182 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/* linux/drivers/media/platform/s5p-jpeg/jpeg-core.c
- *
- * Copyright (c) 2011-2014 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com
- *
- * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
- * Author: Jacek Anaszewski <j.anaszewski@samsung.com>
- */
-
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/gfp.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/string.h>
-#include <media/v4l2-event.h>
-#include <media/v4l2-mem2mem.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-rect.h>
-#include <media/videobuf2-v4l2.h>
-#include <media/videobuf2-dma-contig.h>
-
-#include "jpeg-core.h"
-#include "jpeg-hw-s5p.h"
-#include "jpeg-hw-exynos4.h"
-#include "jpeg-hw-exynos3250.h"
-#include "jpeg-regs.h"
-
-static struct s5p_jpeg_fmt sjpeg_formats[] = {
-       {
-               .fourcc         = V4L2_PIX_FMT_JPEG,
-               .flags          = SJPEG_FMT_FLAG_ENC_CAPTURE |
-                                 SJPEG_FMT_FLAG_DEC_OUTPUT |
-                                 SJPEG_FMT_FLAG_S5P |
-                                 SJPEG_FMT_FLAG_EXYNOS3250 |
-                                 SJPEG_FMT_FLAG_EXYNOS4,
-       },
-       {
-               .fourcc         = V4L2_PIX_FMT_YUYV,
-               .depth          = 16,
-               .colplanes      = 1,
-               .h_align        = 4,
-               .v_align        = 3,
-               .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
-                                 SJPEG_FMT_FLAG_DEC_CAPTURE |
-                                 SJPEG_FMT_FLAG_S5P |
-                                 SJPEG_FMT_NON_RGB,
-               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
-       },
-       {
-               .fourcc         = V4L2_PIX_FMT_YUYV,
-               .depth          = 16,
-               .colplanes      = 1,
-               .h_align        = 1,
-               .v_align        = 0,
-               .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
-                                 SJPEG_FMT_FLAG_DEC_CAPTURE |
-                                 SJPEG_FMT_FLAG_EXYNOS4 |
-                                 SJPEG_FMT_NON_RGB,
-               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
-       },
-       {
-               .fourcc         = V4L2_PIX_FMT_YUYV,
-               .depth          = 16,
-               .colplanes      = 1,
-               .h_align        = 2,
-               .v_align        = 0,
-               .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
-                                 SJPEG_FMT_FLAG_DEC_CAPTURE |
-                                 SJPEG_FMT_FLAG_EXYNOS3250 |
-                                 SJPEG_FMT_NON_RGB,
-               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
-       },
-       {
-               .fourcc         = V4L2_PIX_FMT_YVYU,
-               .depth          = 16,
-               .colplanes      = 1,
-               .h_align        = 1,
-               .v_align        = 0,
-               .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
-                                 SJPEG_FMT_FLAG_DEC_CAPTURE |
-                                 SJPEG_FMT_FLAG_EXYNOS4 |
-                                 SJPEG_FMT_NON_RGB,
-               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
-       },
-       {
-               .fourcc         = V4L2_PIX_FMT_YVYU,
-               .depth          = 16,
-               .colplanes      = 1,
-               .h_align        = 2,
-               .v_align        = 0,
-               .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
-                                 SJPEG_FMT_FLAG_DEC_CAPTURE |
-                                 SJPEG_FMT_FLAG_EXYNOS3250 |
-                                 SJPEG_FMT_NON_RGB,
-               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
-       },
-       {
-               .fourcc         = V4L2_PIX_FMT_UYVY,
-               .depth          = 16,
-               .colplanes      = 1,
-               .h_align        = 2,
-               .v_align        = 0,
-               .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
-                                 SJPEG_FMT_FLAG_DEC_CAPTURE |
-                                 SJPEG_FMT_FLAG_EXYNOS3250 |
-                                 SJPEG_FMT_NON_RGB,
-               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
-       },
-       {
-               .fourcc         = V4L2_PIX_FMT_VYUY,
-               .depth          = 16,
-               .colplanes      = 1,
-               .h_align        = 2,
-               .v_align        = 0,
-               .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
-                                 SJPEG_FMT_FLAG_DEC_CAPTURE |
-                                 SJPEG_FMT_FLAG_EXYNOS3250 |
-                                 SJPEG_FMT_NON_RGB,
-               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
-       },
-       {
-               .fourcc         = V4L2_PIX_FMT_RGB565,
-               .depth          = 16,
-               .colplanes      = 1,
-               .h_align        = 0,
-               .v_align        = 0,
-               .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
-                                 SJPEG_FMT_FLAG_DEC_CAPTURE |
-                                 SJPEG_FMT_FLAG_EXYNOS4 |
-                                 SJPEG_FMT_RGB,
-               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
-       },
-       {
-               .fourcc         = V4L2_PIX_FMT_RGB565,
-               .depth          = 16,
-               .colplanes      = 1,
-               .h_align        = 2,
-               .v_align        = 0,
-               .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
-                                 SJPEG_FMT_FLAG_DEC_CAPTURE |
-                                 SJPEG_FMT_FLAG_EXYNOS3250 |
-                                 SJPEG_FMT_RGB,
-               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
-       },
-       {
-               .fourcc         = V4L2_PIX_FMT_RGB565X,
-               .depth          = 16,
-               .colplanes      = 1,
-               .h_align        = 2,
-               .v_align        = 0,
-               .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
-                                 SJPEG_FMT_FLAG_DEC_CAPTURE |
-                                 SJPEG_FMT_FLAG_EXYNOS3250 |
-                                 SJPEG_FMT_RGB,
-               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
-       },
-       {
-               .fourcc         = V4L2_PIX_FMT_RGB565,
-               .depth          = 16,
-               .colplanes      = 1,
-               .h_align        = 0,
-               .v_align        = 0,
-               .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
-                                 SJPEG_FMT_FLAG_S5P |
-                                 SJPEG_FMT_RGB,
-               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
-       },
-       {
-               .fourcc         = V4L2_PIX_FMT_RGB32,
-               .depth          = 32,
-               .colplanes      = 1,
-               .h_align        = 0,
-               .v_align        = 0,
-               .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
-                                 SJPEG_FMT_FLAG_DEC_CAPTURE |
-                                 SJPEG_FMT_FLAG_EXYNOS4 |
-                                 SJPEG_FMT_RGB,
-               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
-       },
-       {
-               .fourcc         = V4L2_PIX_FMT_RGB32,
-               .depth          = 32,
-               .colplanes      = 1,
-               .h_align        = 2,
-               .v_align        = 0,
-               .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
-                                 SJPEG_FMT_FLAG_DEC_CAPTURE |
-                                 SJPEG_FMT_FLAG_EXYNOS3250 |
-                                 SJPEG_FMT_RGB,
-               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
-       },
-       {
-               .fourcc         = V4L2_PIX_FMT_NV24,
-               .depth          = 24,
-               .colplanes      = 2,
-               .h_align        = 0,
-               .v_align        = 0,
-               .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
-                                 SJPEG_FMT_FLAG_DEC_CAPTURE |
-                                 SJPEG_FMT_FLAG_EXYNOS4 |
-                                 SJPEG_FMT_NON_RGB,
-               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
-       },
-       {
-               .fourcc         = V4L2_PIX_FMT_NV42,
-               .depth          = 24,
-               .colplanes      = 2,
-               .h_align        = 0,
-               .v_align        = 0,
-               .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
-                                 SJPEG_FMT_FLAG_DEC_CAPTURE |
-                                 SJPEG_FMT_FLAG_EXYNOS4 |
-                                 SJPEG_FMT_NON_RGB,
-               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
-       },
-       {
-               .fourcc         = V4L2_PIX_FMT_NV61,
-               .depth          = 16,
-               .colplanes      = 2,
-               .h_align        = 1,
-               .v_align        = 0,
-               .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
-                                 SJPEG_FMT_FLAG_DEC_CAPTURE |
-                                 SJPEG_FMT_FLAG_EXYNOS4 |
-                                 SJPEG_FMT_NON_RGB,
-               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
-       },
-       {
-               .fourcc         = V4L2_PIX_FMT_NV16,
-               .depth          = 16,
-               .colplanes      = 2,
-               .h_align        = 1,
-               .v_align        = 0,
-               .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
-                                 SJPEG_FMT_FLAG_DEC_CAPTURE |
-                                 SJPEG_FMT_FLAG_EXYNOS4 |
-                                 SJPEG_FMT_NON_RGB,
-               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
-       },
-       {
-               .fourcc         = V4L2_PIX_FMT_NV12,
-               .depth          = 12,
-               .colplanes      = 2,
-               .h_align        = 1,
-               .v_align        = 1,
-               .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
-                                 SJPEG_FMT_FLAG_DEC_CAPTURE |
-                                 SJPEG_FMT_FLAG_EXYNOS4 |
-                                 SJPEG_FMT_NON_RGB,
-               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
-       },
-       {
-               .fourcc         = V4L2_PIX_FMT_NV12,
-               .depth          = 12,
-               .colplanes      = 2,
-               .h_align        = 3,
-               .v_align        = 3,
-               .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
-                                 SJPEG_FMT_FLAG_DEC_CAPTURE |
-                                 SJPEG_FMT_FLAG_EXYNOS3250 |
-                                 SJPEG_FMT_NON_RGB,
-               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
-       },
-       {
-               .fourcc         = V4L2_PIX_FMT_NV12,
-               .depth          = 12,
-               .colplanes      = 2,
-               .h_align        = 4,
-               .v_align        = 4,
-               .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
-                                 SJPEG_FMT_FLAG_DEC_CAPTURE |
-                                 SJPEG_FMT_FLAG_S5P |
-                                 SJPEG_FMT_NON_RGB,
-               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
-       },
-       {
-               .fourcc         = V4L2_PIX_FMT_NV21,
-               .depth          = 12,
-               .colplanes      = 2,
-               .h_align        = 3,
-               .v_align        = 3,
-               .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
-                                 SJPEG_FMT_FLAG_DEC_CAPTURE |
-                                 SJPEG_FMT_FLAG_EXYNOS3250 |
-                                 SJPEG_FMT_NON_RGB,
-               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
-       },
-       {
-               .fourcc         = V4L2_PIX_FMT_NV21,
-               .depth          = 12,
-               .colplanes      = 2,
-               .h_align        = 1,
-               .v_align        = 1,
-               .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
-                                 SJPEG_FMT_FLAG_DEC_CAPTURE |
-                                 SJPEG_FMT_FLAG_EXYNOS3250 |
-                                 SJPEG_FMT_FLAG_EXYNOS4 |
-                                 SJPEG_FMT_NON_RGB,
-               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
-       },
-       {
-               .fourcc         = V4L2_PIX_FMT_YUV420,
-               .depth          = 12,
-               .colplanes      = 3,
-               .h_align        = 1,
-               .v_align        = 1,
-               .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
-                                 SJPEG_FMT_FLAG_DEC_CAPTURE |
-                                 SJPEG_FMT_FLAG_EXYNOS4 |
-                                 SJPEG_FMT_NON_RGB,
-               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
-       },
-       {
-               .fourcc         = V4L2_PIX_FMT_YUV420,
-               .depth          = 12,
-               .colplanes      = 3,
-               .h_align        = 4,
-               .v_align        = 4,
-               .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
-                                 SJPEG_FMT_FLAG_DEC_CAPTURE |
-                                 SJPEG_FMT_FLAG_EXYNOS3250 |
-                                 SJPEG_FMT_NON_RGB,
-               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
-       },
-       {
-               .fourcc         = V4L2_PIX_FMT_GREY,
-               .depth          = 8,
-               .colplanes      = 1,
-               .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
-                                 SJPEG_FMT_FLAG_DEC_CAPTURE |
-                                 SJPEG_FMT_FLAG_EXYNOS4 |
-                                 SJPEG_FMT_NON_RGB,
-               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY,
-       },
-};
-#define SJPEG_NUM_FORMATS ARRAY_SIZE(sjpeg_formats)
-
-static const unsigned char qtbl_luminance[4][64] = {
-       {/*level 0 - high compression quality */
-               20, 16, 25, 39, 50, 46, 62, 68,
-               16, 18, 23, 38, 38, 53, 65, 68,
-               25, 23, 31, 38, 53, 65, 68, 68,
-               39, 38, 38, 53, 65, 68, 68, 68,
-               50, 38, 53, 65, 68, 68, 68, 68,
-               46, 53, 65, 68, 68, 68, 68, 68,
-               62, 65, 68, 68, 68, 68, 68, 68,
-               68, 68, 68, 68, 68, 68, 68, 68
-       },
-       {/* level 1 */
-               16, 11, 11, 16, 23, 27, 31, 30,
-               11, 12, 12, 15, 20, 23, 23, 30,
-               11, 12, 13, 16, 23, 26, 35, 47,
-               16, 15, 16, 23, 26, 37, 47, 64,
-               23, 20, 23, 26, 39, 51, 64, 64,
-               27, 23, 26, 37, 51, 64, 64, 64,
-               31, 23, 35, 47, 64, 64, 64, 64,
-               30, 30, 47, 64, 64, 64, 64, 64
-       },
-       {/* level 2 */
-               12,  8,  8, 12, 17, 21, 24, 23,
-                8,  9,  9, 11, 15, 19, 18, 23,
-                8,  9, 10, 12, 19, 20, 27, 36,
-               12, 11, 12, 21, 20, 28, 36, 53,
-               17, 15, 19, 20, 30, 39, 51, 59,
-               21, 19, 20, 28, 39, 51, 59, 59,
-               24, 18, 27, 36, 51, 59, 59, 59,
-               23, 23, 36, 53, 59, 59, 59, 59
-       },
-       {/* level 3 - low compression quality */
-                8,  6,  6,  8, 12, 14, 16, 17,
-                6,  6,  6,  8, 10, 13, 12, 15,
-                6,  6,  7,  8, 13, 14, 18, 24,
-                8,  8,  8, 14, 13, 19, 24, 35,
-               12, 10, 13, 13, 20, 26, 34, 39,
-               14, 13, 14, 19, 26, 34, 39, 39,
-               16, 12, 18, 24, 34, 39, 39, 39,
-               17, 15, 24, 35, 39, 39, 39, 39
-       }
-};
-
-static const unsigned char qtbl_chrominance[4][64] = {
-       {/*level 0 - high compression quality */
-               21, 25, 32, 38, 54, 68, 68, 68,
-               25, 28, 24, 38, 54, 68, 68, 68,
-               32, 24, 32, 43, 66, 68, 68, 68,
-               38, 38, 43, 53, 68, 68, 68, 68,
-               54, 54, 66, 68, 68, 68, 68, 68,
-               68, 68, 68, 68, 68, 68, 68, 68,
-               68, 68, 68, 68, 68, 68, 68, 68,
-               68, 68, 68, 68, 68, 68, 68, 68
-       },
-       {/* level 1 */
-               17, 15, 17, 21, 20, 26, 38, 48,
-               15, 19, 18, 17, 20, 26, 35, 43,
-               17, 18, 20, 22, 26, 30, 46, 53,
-               21, 17, 22, 28, 30, 39, 53, 64,
-               20, 20, 26, 30, 39, 48, 64, 64,
-               26, 26, 30, 39, 48, 63, 64, 64,
-               38, 35, 46, 53, 64, 64, 64, 64,
-               48, 43, 53, 64, 64, 64, 64, 64
-       },
-       {/* level 2 */
-               13, 11, 13, 16, 20, 20, 29, 37,
-               11, 14, 14, 14, 16, 20, 26, 32,
-               13, 14, 15, 17, 20, 23, 35, 40,
-               16, 14, 17, 21, 23, 30, 40, 50,
-               20, 16, 20, 23, 30, 37, 50, 59,
-               20, 20, 23, 30, 37, 48, 59, 59,
-               29, 26, 35, 40, 50, 59, 59, 59,
-               37, 32, 40, 50, 59, 59, 59, 59
-       },
-       {/* level 3 - low compression quality */
-                9,  8,  9, 11, 14, 17, 19, 24,
-                8, 10,  9, 11, 14, 13, 17, 22,
-                9,  9, 13, 14, 13, 15, 23, 26,
-               11, 11, 14, 14, 15, 20, 26, 33,
-               14, 14, 13, 15, 20, 24, 33, 39,
-               17, 13, 15, 20, 24, 32, 39, 39,
-               19, 17, 23, 26, 33, 39, 39, 39,
-               24, 22, 26, 33, 39, 39, 39, 39
-       }
-};
-
-static const unsigned char hdctbl0[16] = {
-       0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0
-};
-
-static const unsigned char hdctblg0[12] = {
-       0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb
-};
-static const unsigned char hactbl0[16] = {
-       0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d
-};
-static const unsigned char hactblg0[162] = {
-       0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
-       0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
-       0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
-       0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
-       0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
-       0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
-       0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
-       0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
-       0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
-       0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
-       0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
-       0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
-       0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
-       0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
-       0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
-       0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
-       0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
-       0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
-       0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
-       0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
-       0xf9, 0xfa
-};
-
-/*
- * Fourcc downgrade schema lookup tables for 422 and 420
- * chroma subsampling - fourcc on each position maps on the
- * fourcc from the table fourcc_to_dwngrd_schema_id which allows
- * to get the most suitable fourcc counterpart for the given
- * downgraded subsampling property.
- */
-static const u32 subs422_fourcc_dwngrd_schema[] = {
-       V4L2_PIX_FMT_NV16,
-       V4L2_PIX_FMT_NV61,
-};
-
-static const u32 subs420_fourcc_dwngrd_schema[] = {
-       V4L2_PIX_FMT_NV12,
-       V4L2_PIX_FMT_NV21,
-       V4L2_PIX_FMT_NV12,
-       V4L2_PIX_FMT_NV21,
-       V4L2_PIX_FMT_NV12,
-       V4L2_PIX_FMT_NV21,
-       V4L2_PIX_FMT_GREY,
-       V4L2_PIX_FMT_GREY,
-       V4L2_PIX_FMT_GREY,
-       V4L2_PIX_FMT_GREY,
-};
-
-/*
- * Lookup table for translation of a fourcc to the position
- * of its downgraded counterpart in the *fourcc_dwngrd_schema
- * tables.
- */
-static const u32 fourcc_to_dwngrd_schema_id[] = {
-       V4L2_PIX_FMT_NV24,
-       V4L2_PIX_FMT_NV42,
-       V4L2_PIX_FMT_NV16,
-       V4L2_PIX_FMT_NV61,
-       V4L2_PIX_FMT_YUYV,
-       V4L2_PIX_FMT_YVYU,
-       V4L2_PIX_FMT_NV12,
-       V4L2_PIX_FMT_NV21,
-       V4L2_PIX_FMT_YUV420,
-       V4L2_PIX_FMT_GREY,
-};
-
-static int s5p_jpeg_get_dwngrd_sch_id_by_fourcc(u32 fourcc)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(fourcc_to_dwngrd_schema_id); ++i) {
-               if (fourcc_to_dwngrd_schema_id[i] == fourcc)
-                       return i;
-       }
-
-       return -EINVAL;
-}
-
-static int s5p_jpeg_adjust_fourcc_to_subsampling(
-                                       enum v4l2_jpeg_chroma_subsampling subs,
-                                       u32 in_fourcc,
-                                       u32 *out_fourcc,
-                                       struct s5p_jpeg_ctx *ctx)
-{
-       int dwngrd_sch_id;
-
-       if (ctx->subsampling != V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY) {
-               dwngrd_sch_id =
-                       s5p_jpeg_get_dwngrd_sch_id_by_fourcc(in_fourcc);
-               if (dwngrd_sch_id < 0)
-                       return -EINVAL;
-       }
-
-       switch (ctx->subsampling) {
-       case V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY:
-               *out_fourcc = V4L2_PIX_FMT_GREY;
-               break;
-       case V4L2_JPEG_CHROMA_SUBSAMPLING_420:
-               if (dwngrd_sch_id >
-                               ARRAY_SIZE(subs420_fourcc_dwngrd_schema) - 1)
-                       return -EINVAL;
-               *out_fourcc = subs420_fourcc_dwngrd_schema[dwngrd_sch_id];
-               break;
-       case V4L2_JPEG_CHROMA_SUBSAMPLING_422:
-               if (dwngrd_sch_id >
-                               ARRAY_SIZE(subs422_fourcc_dwngrd_schema) - 1)
-                       return -EINVAL;
-               *out_fourcc = subs422_fourcc_dwngrd_schema[dwngrd_sch_id];
-               break;
-       default:
-               *out_fourcc = V4L2_PIX_FMT_GREY;
-               break;
-       }
-
-       return 0;
-}
-
-static int exynos4x12_decoded_subsampling[] = {
-       V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY,
-       V4L2_JPEG_CHROMA_SUBSAMPLING_444,
-       V4L2_JPEG_CHROMA_SUBSAMPLING_422,
-       V4L2_JPEG_CHROMA_SUBSAMPLING_420,
-};
-
-static int exynos3250_decoded_subsampling[] = {
-       V4L2_JPEG_CHROMA_SUBSAMPLING_444,
-       V4L2_JPEG_CHROMA_SUBSAMPLING_422,
-       V4L2_JPEG_CHROMA_SUBSAMPLING_420,
-       V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY,
-       -1,
-       -1,
-       V4L2_JPEG_CHROMA_SUBSAMPLING_411,
-};
-
-static inline struct s5p_jpeg_ctx *ctrl_to_ctx(struct v4l2_ctrl *c)
-{
-       return container_of(c->handler, struct s5p_jpeg_ctx, ctrl_handler);
-}
-
-static inline struct s5p_jpeg_ctx *fh_to_ctx(struct v4l2_fh *fh)
-{
-       return container_of(fh, struct s5p_jpeg_ctx, fh);
-}
-
-static int s5p_jpeg_to_user_subsampling(struct s5p_jpeg_ctx *ctx)
-{
-       switch (ctx->jpeg->variant->version) {
-       case SJPEG_S5P:
-               WARN_ON(ctx->subsampling > 3);
-               if (ctx->subsampling > 2)
-                       return V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY;
-               return ctx->subsampling;
-       case SJPEG_EXYNOS3250:
-       case SJPEG_EXYNOS5420:
-               WARN_ON(ctx->subsampling > 6);
-               if (ctx->subsampling > 3)
-                       return V4L2_JPEG_CHROMA_SUBSAMPLING_411;
-               return exynos3250_decoded_subsampling[ctx->subsampling];
-       case SJPEG_EXYNOS4:
-               WARN_ON(ctx->subsampling > 3);
-               if (ctx->subsampling > 2)
-                       return V4L2_JPEG_CHROMA_SUBSAMPLING_420;
-               return exynos4x12_decoded_subsampling[ctx->subsampling];
-       case SJPEG_EXYNOS5433:
-               return ctx->subsampling; /* parsed from header */
-       default:
-               WARN_ON(ctx->subsampling > 3);
-               return V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY;
-       }
-}
-
-static inline void s5p_jpeg_set_qtbl(void __iomem *regs,
-                                    const unsigned char *qtbl,
-                                    unsigned long tab, int len)
-{
-       int i;
-
-       for (i = 0; i < len; i++)
-               writel((unsigned int)qtbl[i], regs + tab + (i * 0x04));
-}
-
-static inline void s5p_jpeg_set_qtbl_lum(void __iomem *regs, int quality)
-{
-       /* this driver fills quantisation table 0 with data for luma */
-       s5p_jpeg_set_qtbl(regs, qtbl_luminance[quality],
-                         S5P_JPG_QTBL_CONTENT(0),
-                         ARRAY_SIZE(qtbl_luminance[quality]));
-}
-
-static inline void s5p_jpeg_set_qtbl_chr(void __iomem *regs, int quality)
-{
-       /* this driver fills quantisation table 1 with data for chroma */
-       s5p_jpeg_set_qtbl(regs, qtbl_chrominance[quality],
-                         S5P_JPG_QTBL_CONTENT(1),
-                         ARRAY_SIZE(qtbl_chrominance[quality]));
-}
-
-static inline void s5p_jpeg_set_htbl(void __iomem *regs,
-                                    const unsigned char *htbl,
-                                    unsigned long tab, int len)
-{
-       int i;
-
-       for (i = 0; i < len; i++)
-               writel((unsigned int)htbl[i], regs + tab + (i * 0x04));
-}
-
-static inline void s5p_jpeg_set_hdctbl(void __iomem *regs)
-{
-       /* this driver fills table 0 for this component */
-       s5p_jpeg_set_htbl(regs, hdctbl0, S5P_JPG_HDCTBL(0),
-                                               ARRAY_SIZE(hdctbl0));
-}
-
-static inline void s5p_jpeg_set_hdctblg(void __iomem *regs)
-{
-       /* this driver fills table 0 for this component */
-       s5p_jpeg_set_htbl(regs, hdctblg0, S5P_JPG_HDCTBLG(0),
-                                               ARRAY_SIZE(hdctblg0));
-}
-
-static inline void s5p_jpeg_set_hactbl(void __iomem *regs)
-{
-       /* this driver fills table 0 for this component */
-       s5p_jpeg_set_htbl(regs, hactbl0, S5P_JPG_HACTBL(0),
-                                               ARRAY_SIZE(hactbl0));
-}
-
-static inline void s5p_jpeg_set_hactblg(void __iomem *regs)
-{
-       /* this driver fills table 0 for this component */
-       s5p_jpeg_set_htbl(regs, hactblg0, S5P_JPG_HACTBLG(0),
-                                               ARRAY_SIZE(hactblg0));
-}
-
-static inline void exynos4_jpeg_set_tbl(void __iomem *regs,
-                                       const unsigned char *tbl,
-                                       unsigned long tab, int len)
-{
-       int i;
-       unsigned int dword;
-
-       for (i = 0; i < len; i += 4) {
-               dword = tbl[i] |
-                       (tbl[i + 1] << 8) |
-                       (tbl[i + 2] << 16) |
-                       (tbl[i + 3] << 24);
-               writel(dword, regs + tab + i);
-       }
-}
-
-static inline void exynos4_jpeg_set_qtbl_lum(void __iomem *regs, int quality)
-{
-       /* this driver fills quantisation table 0 with data for luma */
-       exynos4_jpeg_set_tbl(regs, qtbl_luminance[quality],
-                            EXYNOS4_QTBL_CONTENT(0),
-                            ARRAY_SIZE(qtbl_luminance[quality]));
-}
-
-static inline void exynos4_jpeg_set_qtbl_chr(void __iomem *regs, int quality)
-{
-       /* this driver fills quantisation table 1 with data for chroma */
-       exynos4_jpeg_set_tbl(regs, qtbl_chrominance[quality],
-                            EXYNOS4_QTBL_CONTENT(1),
-                            ARRAY_SIZE(qtbl_chrominance[quality]));
-}
-
-static void exynos4_jpeg_set_huff_tbl(void __iomem *base)
-{
-       exynos4_jpeg_set_tbl(base, hdctbl0, EXYNOS4_HUFF_TBL_HDCLL,
-                                                       ARRAY_SIZE(hdctbl0));
-       exynos4_jpeg_set_tbl(base, hdctbl0, EXYNOS4_HUFF_TBL_HDCCL,
-                                                       ARRAY_SIZE(hdctbl0));
-       exynos4_jpeg_set_tbl(base, hdctblg0, EXYNOS4_HUFF_TBL_HDCLV,
-                                                       ARRAY_SIZE(hdctblg0));
-       exynos4_jpeg_set_tbl(base, hdctblg0, EXYNOS4_HUFF_TBL_HDCCV,
-                                                       ARRAY_SIZE(hdctblg0));
-       exynos4_jpeg_set_tbl(base, hactbl0, EXYNOS4_HUFF_TBL_HACLL,
-                                                       ARRAY_SIZE(hactbl0));
-       exynos4_jpeg_set_tbl(base, hactbl0, EXYNOS4_HUFF_TBL_HACCL,
-                                                       ARRAY_SIZE(hactbl0));
-       exynos4_jpeg_set_tbl(base, hactblg0, EXYNOS4_HUFF_TBL_HACLV,
-                                                       ARRAY_SIZE(hactblg0));
-       exynos4_jpeg_set_tbl(base, hactblg0, EXYNOS4_HUFF_TBL_HACCV,
-                                                       ARRAY_SIZE(hactblg0));
-}
-
-static inline int __exynos4_huff_tbl(int class, int id, bool lenval)
-{
-       /*
-        * class: 0 - DC, 1 - AC
-        * id: 0 - Y, 1 - Cb/Cr
-        */
-       if (class) {
-               if (id)
-                       return lenval ? EXYNOS4_HUFF_TBL_HACCL :
-                               EXYNOS4_HUFF_TBL_HACCV;
-               return lenval ? EXYNOS4_HUFF_TBL_HACLL : EXYNOS4_HUFF_TBL_HACLV;
-
-       }
-       /* class == 0 */
-       if (id)
-               return lenval ? EXYNOS4_HUFF_TBL_HDCCL : EXYNOS4_HUFF_TBL_HDCCV;
-
-       return lenval ? EXYNOS4_HUFF_TBL_HDCLL : EXYNOS4_HUFF_TBL_HDCLV;
-}
-
-static inline int exynos4_huff_tbl_len(int class, int id)
-{
-       return __exynos4_huff_tbl(class, id, true);
-}
-
-static inline int exynos4_huff_tbl_val(int class, int id)
-{
-       return __exynos4_huff_tbl(class, id, false);
-}
-
-static int get_byte(struct s5p_jpeg_buffer *buf);
-static int get_word_be(struct s5p_jpeg_buffer *buf, unsigned int *word);
-static void skip(struct s5p_jpeg_buffer *buf, long len);
-
-static void exynos4_jpeg_parse_decode_h_tbl(struct s5p_jpeg_ctx *ctx)
-{
-       struct s5p_jpeg *jpeg = ctx->jpeg;
-       struct vb2_v4l2_buffer *vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
-       struct s5p_jpeg_buffer jpeg_buffer;
-       unsigned int word;
-       int c, x, components;
-
-       jpeg_buffer.size = 2; /* Ls */
-       jpeg_buffer.data =
-               (unsigned long)vb2_plane_vaddr(&vb->vb2_buf, 0) + ctx->out_q.sos + 2;
-       jpeg_buffer.curr = 0;
-
-       word = 0;
-
-       if (get_word_be(&jpeg_buffer, &word))
-               return;
-       jpeg_buffer.size = (long)word - 2;
-       jpeg_buffer.data += 2;
-       jpeg_buffer.curr = 0;
-
-       components = get_byte(&jpeg_buffer);
-       if (components == -1)
-               return;
-       while (components--) {
-               c = get_byte(&jpeg_buffer);
-               if (c == -1)
-                       return;
-               x = get_byte(&jpeg_buffer);
-               if (x == -1)
-                       return;
-               exynos4_jpeg_select_dec_h_tbl(jpeg->regs, c,
-                                       (((x >> 4) & 0x1) << 1) | (x & 0x1));
-       }
-
-}
-
-static void exynos4_jpeg_parse_huff_tbl(struct s5p_jpeg_ctx *ctx)
-{
-       struct s5p_jpeg *jpeg = ctx->jpeg;
-       struct vb2_v4l2_buffer *vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
-       struct s5p_jpeg_buffer jpeg_buffer;
-       unsigned int word;
-       int c, i, n, j;
-
-       for (j = 0; j < ctx->out_q.dht.n; ++j) {
-               jpeg_buffer.size = ctx->out_q.dht.len[j];
-               jpeg_buffer.data = (unsigned long)vb2_plane_vaddr(&vb->vb2_buf, 0) +
-                                  ctx->out_q.dht.marker[j];
-               jpeg_buffer.curr = 0;
-
-               word = 0;
-               while (jpeg_buffer.curr < jpeg_buffer.size) {
-                       char id, class;
-
-                       c = get_byte(&jpeg_buffer);
-                       if (c == -1)
-                               return;
-                       id = c & 0xf;
-                       class = (c >> 4) & 0xf;
-                       n = 0;
-                       for (i = 0; i < 16; ++i) {
-                               c = get_byte(&jpeg_buffer);
-                               if (c == -1)
-                                       return;
-                               word |= c << ((i % 4) * 8);
-                               if ((i + 1) % 4 == 0) {
-                                       writel(word, jpeg->regs +
-                                       exynos4_huff_tbl_len(class, id) +
-                                       (i / 4) * 4);
-                                       word = 0;
-                               }
-                               n += c;
-                       }
-                       word = 0;
-                       for (i = 0; i < n; ++i) {
-                               c = get_byte(&jpeg_buffer);
-                               if (c == -1)
-                                       return;
-                               word |= c << ((i % 4) * 8);
-                               if ((i + 1) % 4 == 0) {
-                                       writel(word, jpeg->regs +
-                                       exynos4_huff_tbl_val(class, id) +
-                                       (i / 4) * 4);
-                                       word = 0;
-                               }
-                       }
-                       if (i % 4) {
-                               writel(word, jpeg->regs +
-                               exynos4_huff_tbl_val(class, id) + (i / 4) * 4);
-                       }
-                       word = 0;
-               }
-       }
-}
-
-static void exynos4_jpeg_parse_decode_q_tbl(struct s5p_jpeg_ctx *ctx)
-{
-       struct s5p_jpeg *jpeg = ctx->jpeg;
-       struct vb2_v4l2_buffer *vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
-       struct s5p_jpeg_buffer jpeg_buffer;
-       int c, x, components;
-
-       jpeg_buffer.size = ctx->out_q.sof_len;
-       jpeg_buffer.data =
-               (unsigned long)vb2_plane_vaddr(&vb->vb2_buf, 0) + ctx->out_q.sof;
-       jpeg_buffer.curr = 0;
-
-       skip(&jpeg_buffer, 5); /* P, Y, X */
-       components = get_byte(&jpeg_buffer);
-       if (components == -1)
-               return;
-
-       exynos4_jpeg_set_dec_components(jpeg->regs, components);
-
-       while (components--) {
-               c = get_byte(&jpeg_buffer);
-               if (c == -1)
-                       return;
-               skip(&jpeg_buffer, 1);
-               x = get_byte(&jpeg_buffer);
-               if (x == -1)
-                       return;
-               exynos4_jpeg_select_dec_q_tbl(jpeg->regs, c, x);
-       }
-}
-
-static void exynos4_jpeg_parse_q_tbl(struct s5p_jpeg_ctx *ctx)
-{
-       struct s5p_jpeg *jpeg = ctx->jpeg;
-       struct vb2_v4l2_buffer *vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
-       struct s5p_jpeg_buffer jpeg_buffer;
-       unsigned int word;
-       int c, i, j;
-
-       for (j = 0; j < ctx->out_q.dqt.n; ++j) {
-               jpeg_buffer.size = ctx->out_q.dqt.len[j];
-               jpeg_buffer.data = (unsigned long)vb2_plane_vaddr(&vb->vb2_buf, 0) +
-                                  ctx->out_q.dqt.marker[j];
-               jpeg_buffer.curr = 0;
-
-               word = 0;
-               while (jpeg_buffer.size - jpeg_buffer.curr >= 65) {
-                       char id;
-
-                       c = get_byte(&jpeg_buffer);
-                       if (c == -1)
-                               return;
-                       id = c & 0xf;
-                       /* nonzero means extended mode - not supported */
-                       if ((c >> 4) & 0xf)
-                               return;
-                       for (i = 0; i < 64; ++i) {
-                               c = get_byte(&jpeg_buffer);
-                               if (c == -1)
-                                       return;
-                               word |= c << ((i % 4) * 8);
-                               if ((i + 1) % 4 == 0) {
-                                       writel(word, jpeg->regs +
-                                       EXYNOS4_QTBL_CONTENT(id) + (i / 4) * 4);
-                                       word = 0;
-                               }
-                       }
-                       word = 0;
-               }
-       }
-}
-
-/*
- * ============================================================================
- * Device file operations
- * ============================================================================
- */
-
-static int queue_init(void *priv, struct vb2_queue *src_vq,
-                     struct vb2_queue *dst_vq);
-static struct s5p_jpeg_fmt *s5p_jpeg_find_format(struct s5p_jpeg_ctx *ctx,
-                               __u32 pixelformat, unsigned int fmt_type);
-static int s5p_jpeg_controls_create(struct s5p_jpeg_ctx *ctx);
-
-static int s5p_jpeg_open(struct file *file)
-{
-       struct s5p_jpeg *jpeg = video_drvdata(file);
-       struct video_device *vfd = video_devdata(file);
-       struct s5p_jpeg_ctx *ctx;
-       struct s5p_jpeg_fmt *out_fmt, *cap_fmt;
-       int ret = 0;
-
-       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
-       if (!ctx)
-               return -ENOMEM;
-
-       if (mutex_lock_interruptible(&jpeg->lock)) {
-               ret = -ERESTARTSYS;
-               goto free;
-       }
-
-       v4l2_fh_init(&ctx->fh, vfd);
-       /* Use separate control handler per file handle */
-       ctx->fh.ctrl_handler = &ctx->ctrl_handler;
-       file->private_data = &ctx->fh;
-       v4l2_fh_add(&ctx->fh);
-
-       ctx->jpeg = jpeg;
-       if (vfd == jpeg->vfd_encoder) {
-               ctx->mode = S5P_JPEG_ENCODE;
-               out_fmt = s5p_jpeg_find_format(ctx, V4L2_PIX_FMT_RGB565,
-                                                       FMT_TYPE_OUTPUT);
-               cap_fmt = s5p_jpeg_find_format(ctx, V4L2_PIX_FMT_JPEG,
-                                                       FMT_TYPE_CAPTURE);
-       } else {
-               ctx->mode = S5P_JPEG_DECODE;
-               out_fmt = s5p_jpeg_find_format(ctx, V4L2_PIX_FMT_JPEG,
-                                                       FMT_TYPE_OUTPUT);
-               cap_fmt = s5p_jpeg_find_format(ctx, V4L2_PIX_FMT_YUYV,
-                                                       FMT_TYPE_CAPTURE);
-               ctx->scale_factor = EXYNOS3250_DEC_SCALE_FACTOR_8_8;
-       }
-
-       ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(jpeg->m2m_dev, ctx, queue_init);
-       if (IS_ERR(ctx->fh.m2m_ctx)) {
-               ret = PTR_ERR(ctx->fh.m2m_ctx);
-               goto error;
-       }
-
-       ctx->out_q.fmt = out_fmt;
-       ctx->cap_q.fmt = cap_fmt;
-
-       ret = s5p_jpeg_controls_create(ctx);
-       if (ret < 0)
-               goto error;
-
-       mutex_unlock(&jpeg->lock);
-       return 0;
-
-error:
-       v4l2_fh_del(&ctx->fh);
-       v4l2_fh_exit(&ctx->fh);
-       mutex_unlock(&jpeg->lock);
-free:
-       kfree(ctx);
-       return ret;
-}
-
-static int s5p_jpeg_release(struct file *file)
-{
-       struct s5p_jpeg *jpeg = video_drvdata(file);
-       struct s5p_jpeg_ctx *ctx = fh_to_ctx(file->private_data);
-
-       mutex_lock(&jpeg->lock);
-       v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
-       v4l2_ctrl_handler_free(&ctx->ctrl_handler);
-       v4l2_fh_del(&ctx->fh);
-       v4l2_fh_exit(&ctx->fh);
-       kfree(ctx);
-       mutex_unlock(&jpeg->lock);
-
-       return 0;
-}
-
-static const struct v4l2_file_operations s5p_jpeg_fops = {
-       .owner          = THIS_MODULE,
-       .open           = s5p_jpeg_open,
-       .release        = s5p_jpeg_release,
-       .poll           = v4l2_m2m_fop_poll,
-       .unlocked_ioctl = video_ioctl2,
-       .mmap           = v4l2_m2m_fop_mmap,
-};
-
-/*
- * ============================================================================
- * video ioctl operations
- * ============================================================================
- */
-
-static int get_byte(struct s5p_jpeg_buffer *buf)
-{
-       if (buf->curr >= buf->size)
-               return -1;
-
-       return ((unsigned char *)buf->data)[buf->curr++];
-}
-
-static int get_word_be(struct s5p_jpeg_buffer *buf, unsigned int *word)
-{
-       unsigned int temp;
-       int byte;
-
-       byte = get_byte(buf);
-       if (byte == -1)
-               return -1;
-       temp = byte << 8;
-       byte = get_byte(buf);
-       if (byte == -1)
-               return -1;
-       *word = (unsigned int)byte | temp;
-       return 0;
-}
-
-static void skip(struct s5p_jpeg_buffer *buf, long len)
-{
-       if (len <= 0)
-               return;
-
-       while (len--)
-               get_byte(buf);
-}
-
-static bool s5p_jpeg_subsampling_decode(struct s5p_jpeg_ctx *ctx,
-                                       unsigned int subsampling)
-{
-       unsigned int version;
-
-       switch (subsampling) {
-       case 0x11:
-               ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444;
-               break;
-       case 0x21:
-               ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422;
-               break;
-       case 0x22:
-               ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420;
-               break;
-       case 0x33:
-               ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY;
-               break;
-       case 0x41:
-               /*
-                * 4:1:1 subsampling only supported by 3250, 5420, and 5433
-                * variants
-                */
-               version = ctx->jpeg->variant->version;
-               if (version != SJPEG_EXYNOS3250 &&
-                   version != SJPEG_EXYNOS5420 &&
-                   version != SJPEG_EXYNOS5433)
-                       return false;
-
-               ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_411;
-               break;
-       default:
-               return false;
-       }
-
-       return true;
-}
-
-static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result,
-                              unsigned long buffer, unsigned long size,
-                              struct s5p_jpeg_ctx *ctx)
-{
-       int c, components = 0, notfound, n_dht = 0, n_dqt = 0;
-       unsigned int height = 0, width = 0, word, subsampling = 0;
-       unsigned int sos = 0, sof = 0, sof_len = 0;
-       unsigned int dht[S5P_JPEG_MAX_MARKER], dht_len[S5P_JPEG_MAX_MARKER];
-       unsigned int dqt[S5P_JPEG_MAX_MARKER], dqt_len[S5P_JPEG_MAX_MARKER];
-       long length;
-       struct s5p_jpeg_buffer jpeg_buffer;
-
-       jpeg_buffer.size = size;
-       jpeg_buffer.data = buffer;
-       jpeg_buffer.curr = 0;
-
-       notfound = 1;
-       while (notfound || !sos) {
-               c = get_byte(&jpeg_buffer);
-               if (c == -1)
-                       return false;
-               if (c != 0xff)
-                       continue;
-               do
-                       c = get_byte(&jpeg_buffer);
-               while (c == 0xff);
-               if (c == -1)
-                       return false;
-               if (c == 0)
-                       continue;
-               length = 0;
-               switch (c) {
-               /* JPEG_MARKER_SOF0: baseline JPEG */
-               case JPEG_MARKER_SOF0:
-                       if (get_word_be(&jpeg_buffer, &word))
-                               break;
-                       length = (long)word - 2;
-                       if (!length)
-                               return false;
-                       sof = jpeg_buffer.curr; /* after 0xffc0 */
-                       sof_len = length;
-                       if (get_byte(&jpeg_buffer) == -1)
-                               break;
-                       if (get_word_be(&jpeg_buffer, &height))
-                               break;
-                       if (get_word_be(&jpeg_buffer, &width))
-                               break;
-                       components = get_byte(&jpeg_buffer);
-                       if (components == -1)
-                               break;
-
-                       if (components == 1) {
-                               subsampling = 0x33;
-                       } else {
-                               skip(&jpeg_buffer, 1);
-                               subsampling = get_byte(&jpeg_buffer);
-                               skip(&jpeg_buffer, 1);
-                       }
-                       if (components > 3)
-                               return false;
-                       skip(&jpeg_buffer, components * 2);
-                       notfound = 0;
-                       break;
-
-               case JPEG_MARKER_DQT:
-                       if (get_word_be(&jpeg_buffer, &word))
-                               break;
-                       length = (long)word - 2;
-                       if (!length)
-                               return false;
-                       if (n_dqt >= S5P_JPEG_MAX_MARKER)
-                               return false;
-                       dqt[n_dqt] = jpeg_buffer.curr; /* after 0xffdb */
-                       dqt_len[n_dqt++] = length;
-                       skip(&jpeg_buffer, length);
-                       break;
-
-               case JPEG_MARKER_DHT:
-                       if (get_word_be(&jpeg_buffer, &word))
-                               break;
-                       length = (long)word - 2;
-                       if (!length)
-                               return false;
-                       if (n_dht >= S5P_JPEG_MAX_MARKER)
-                               return false;
-                       dht[n_dht] = jpeg_buffer.curr; /* after 0xffc4 */
-                       dht_len[n_dht++] = length;
-                       skip(&jpeg_buffer, length);
-                       break;
-
-               case JPEG_MARKER_SOS:
-                       sos = jpeg_buffer.curr - 2; /* 0xffda */
-                       break;
-
-               /* skip payload-less markers */
-               case JPEG_MARKER_RST ... JPEG_MARKER_RST + 7:
-               case JPEG_MARKER_SOI:
-               case JPEG_MARKER_EOI:
-               case JPEG_MARKER_TEM:
-                       break;
-
-               /* skip uninteresting payload markers */
-               default:
-                       if (get_word_be(&jpeg_buffer, &word))
-                               break;
-                       length = (long)word - 2;
-                       skip(&jpeg_buffer, length);
-                       break;
-               }
-       }
-
-       if (notfound || !sos || !s5p_jpeg_subsampling_decode(ctx, subsampling))
-               return false;
-
-       result->w = width;
-       result->h = height;
-       result->sos = sos;
-       result->dht.n = n_dht;
-       while (n_dht--) {
-               result->dht.marker[n_dht] = dht[n_dht];
-               result->dht.len[n_dht] = dht_len[n_dht];
-       }
-       result->dqt.n = n_dqt;
-       while (n_dqt--) {
-               result->dqt.marker[n_dqt] = dqt[n_dqt];
-               result->dqt.len[n_dqt] = dqt_len[n_dqt];
-       }
-       result->sof = sof;
-       result->sof_len = sof_len;
-
-       return true;
-}
-
-static int s5p_jpeg_querycap(struct file *file, void *priv,
-                          struct v4l2_capability *cap)
-{
-       struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
-
-       if (ctx->mode == S5P_JPEG_ENCODE) {
-               strscpy(cap->driver, S5P_JPEG_M2M_NAME,
-                       sizeof(cap->driver));
-               strscpy(cap->card, S5P_JPEG_M2M_NAME " encoder",
-                       sizeof(cap->card));
-       } else {
-               strscpy(cap->driver, S5P_JPEG_M2M_NAME,
-                       sizeof(cap->driver));
-               strscpy(cap->card, S5P_JPEG_M2M_NAME " decoder",
-                       sizeof(cap->card));
-       }
-       snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
-                dev_name(ctx->jpeg->dev));
-       return 0;
-}
-
-static int enum_fmt(struct s5p_jpeg_ctx *ctx,
-                   struct s5p_jpeg_fmt *sjpeg_formats, int n,
-                   struct v4l2_fmtdesc *f, u32 type)
-{
-       int i, num = 0;
-       unsigned int fmt_ver_flag = ctx->jpeg->variant->fmt_ver_flag;
-
-       for (i = 0; i < n; ++i) {
-               if (sjpeg_formats[i].flags & type &&
-                   sjpeg_formats[i].flags & fmt_ver_flag) {
-                       /* index-th format of type type found ? */
-                       if (num == f->index)
-                               break;
-                       /* Correct type but haven't reached our index yet,
-                        * just increment per-type index
-                        */
-                       ++num;
-               }
-       }
-
-       /* Format not found */
-       if (i >= n)
-               return -EINVAL;
-
-       f->pixelformat = sjpeg_formats[i].fourcc;
-
-       return 0;
-}
-
-static int s5p_jpeg_enum_fmt_vid_cap(struct file *file, void *priv,
-                                  struct v4l2_fmtdesc *f)
-{
-       struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
-
-       if (ctx->mode == S5P_JPEG_ENCODE)
-               return enum_fmt(ctx, sjpeg_formats, SJPEG_NUM_FORMATS, f,
-                               SJPEG_FMT_FLAG_ENC_CAPTURE);
-
-       return enum_fmt(ctx, sjpeg_formats, SJPEG_NUM_FORMATS, f,
-                       SJPEG_FMT_FLAG_DEC_CAPTURE);
-}
-
-static int s5p_jpeg_enum_fmt_vid_out(struct file *file, void *priv,
-                                  struct v4l2_fmtdesc *f)
-{
-       struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
-
-       if (ctx->mode == S5P_JPEG_ENCODE)
-               return enum_fmt(ctx, sjpeg_formats, SJPEG_NUM_FORMATS, f,
-                               SJPEG_FMT_FLAG_ENC_OUTPUT);
-
-       return enum_fmt(ctx, sjpeg_formats, SJPEG_NUM_FORMATS, f,
-                       SJPEG_FMT_FLAG_DEC_OUTPUT);
-}
-
-static struct s5p_jpeg_q_data *get_q_data(struct s5p_jpeg_ctx *ctx,
-                                         enum v4l2_buf_type type)
-{
-       if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
-               return &ctx->out_q;
-       if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return &ctx->cap_q;
-
-       return NULL;
-}
-
-static int s5p_jpeg_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
-{
-       struct vb2_queue *vq;
-       struct s5p_jpeg_q_data *q_data = NULL;
-       struct v4l2_pix_format *pix = &f->fmt.pix;
-       struct s5p_jpeg_ctx *ct = fh_to_ctx(priv);
-
-       vq = v4l2_m2m_get_vq(ct->fh.m2m_ctx, f->type);
-       if (!vq)
-               return -EINVAL;
-
-       if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE &&
-           ct->mode == S5P_JPEG_DECODE && !ct->hdr_parsed)
-               return -EINVAL;
-       q_data = get_q_data(ct, f->type);
-       BUG_ON(q_data == NULL);
-
-       pix->width = q_data->w;
-       pix->height = q_data->h;
-       pix->field = V4L2_FIELD_NONE;
-       pix->pixelformat = q_data->fmt->fourcc;
-       pix->bytesperline = 0;
-       if (q_data->fmt->fourcc != V4L2_PIX_FMT_JPEG) {
-               u32 bpl = q_data->w;
-
-               if (q_data->fmt->colplanes == 1)
-                       bpl = (bpl * q_data->fmt->depth) >> 3;
-               pix->bytesperline = bpl;
-       }
-       pix->sizeimage = q_data->size;
-
-       return 0;
-}
-
-static struct s5p_jpeg_fmt *s5p_jpeg_find_format(struct s5p_jpeg_ctx *ctx,
-                               u32 pixelformat, unsigned int fmt_type)
-{
-       unsigned int k, fmt_flag;
-
-       if (ctx->mode == S5P_JPEG_ENCODE)
-               fmt_flag = (fmt_type == FMT_TYPE_OUTPUT) ?
-                               SJPEG_FMT_FLAG_ENC_OUTPUT :
-                               SJPEG_FMT_FLAG_ENC_CAPTURE;
-       else
-               fmt_flag = (fmt_type == FMT_TYPE_OUTPUT) ?
-                               SJPEG_FMT_FLAG_DEC_OUTPUT :
-                               SJPEG_FMT_FLAG_DEC_CAPTURE;
-
-       for (k = 0; k < ARRAY_SIZE(sjpeg_formats); k++) {
-               struct s5p_jpeg_fmt *fmt = &sjpeg_formats[k];
-
-               if (fmt->fourcc == pixelformat &&
-                   fmt->flags & fmt_flag &&
-                   fmt->flags & ctx->jpeg->variant->fmt_ver_flag) {
-                       return fmt;
-               }
-       }
-
-       return NULL;
-}
-
-static void jpeg_bound_align_image(struct s5p_jpeg_ctx *ctx,
-                                  u32 *w, unsigned int wmin, unsigned int wmax,
-                                  unsigned int walign,
-                                  u32 *h, unsigned int hmin, unsigned int hmax,
-                                  unsigned int halign)
-{
-       int width, height, w_step, h_step;
-
-       width = *w;
-       height = *h;
-
-       w_step = 1 << walign;
-       h_step = 1 << halign;
-
-       if (ctx->jpeg->variant->hw3250_compat) {
-               /*
-                * Rightmost and bottommost pixels are cropped by the
-                * Exynos3250/compatible JPEG IP for RGB formats, for the
-                * specific width and height values respectively. This
-                * assignment will result in v4l_bound_align_image returning
-                * dimensions reduced by 1 for the aforementioned cases.
-                */
-               if (w_step == 4 && ((width & 3) == 1)) {
-                       wmax = width;
-                       hmax = height;
-               }
-       }
-
-       v4l_bound_align_image(w, wmin, wmax, walign, h, hmin, hmax, halign, 0);
-
-       if (*w < width && (*w + w_step) < wmax)
-               *w += w_step;
-       if (*h < height && (*h + h_step) < hmax)
-               *h += h_step;
-}
-
-static int vidioc_try_fmt(struct v4l2_format *f, struct s5p_jpeg_fmt *fmt,
-                         struct s5p_jpeg_ctx *ctx, int q_type)
-{
-       struct v4l2_pix_format *pix = &f->fmt.pix;
-
-       if (pix->field == V4L2_FIELD_ANY)
-               pix->field = V4L2_FIELD_NONE;
-       else if (pix->field != V4L2_FIELD_NONE)
-               return -EINVAL;
-
-       /* V4L2 specification suggests the driver corrects the format struct
-        * if any of the dimensions is unsupported
-        */
-       if (q_type == FMT_TYPE_OUTPUT)
-               jpeg_bound_align_image(ctx, &pix->width, S5P_JPEG_MIN_WIDTH,
-                                      S5P_JPEG_MAX_WIDTH, 0,
-                                      &pix->height, S5P_JPEG_MIN_HEIGHT,
-                                      S5P_JPEG_MAX_HEIGHT, 0);
-       else
-               jpeg_bound_align_image(ctx, &pix->width, S5P_JPEG_MIN_WIDTH,
-                                      S5P_JPEG_MAX_WIDTH, fmt->h_align,
-                                      &pix->height, S5P_JPEG_MIN_HEIGHT,
-                                      S5P_JPEG_MAX_HEIGHT, fmt->v_align);
-
-       if (fmt->fourcc == V4L2_PIX_FMT_JPEG) {
-               if (pix->sizeimage <= 0)
-                       pix->sizeimage = PAGE_SIZE;
-               pix->bytesperline = 0;
-       } else {
-               u32 bpl = pix->bytesperline;
-
-               if (fmt->colplanes > 1 && bpl < pix->width)
-                       bpl = pix->width; /* planar */
-
-               if (fmt->colplanes == 1 && /* packed */
-                   (bpl << 3) / fmt->depth < pix->width)
-                       bpl = (pix->width * fmt->depth) >> 3;
-
-               pix->bytesperline = bpl;
-               pix->sizeimage = (pix->width * pix->height * fmt->depth) >> 3;
-       }
-
-       return 0;
-}
-
-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;
-       int ret;
-
-       fmt = s5p_jpeg_find_format(ctx, f->fmt.pix.pixelformat,
-                                               FMT_TYPE_CAPTURE);
-       if (!fmt) {
-               v4l2_err(&ctx->jpeg->v4l2_dev,
-                        "Fourcc format (0x%08x) invalid.\n",
-                        f->fmt.pix.pixelformat);
-               return -EINVAL;
-       }
-
-       if (!ctx->jpeg->variant->hw_ex4_compat || ctx->mode != S5P_JPEG_DECODE)
-               goto exit;
-
-       /*
-        * 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
-        * capture format to the one with subsampling equal to the input jpeg.
-        */
-       if ((fmt->flags & SJPEG_FMT_NON_RGB) &&
-           (fmt->subsampling < ctx->subsampling)) {
-               ret = s5p_jpeg_adjust_fourcc_to_subsampling(ctx->subsampling,
-                                                           fmt->fourcc,
-                                                           &pix->pixelformat,
-                                                           ctx);
-               if (ret < 0)
-                       pix->pixelformat = V4L2_PIX_FMT_GREY;
-
-               fmt = s5p_jpeg_find_format(ctx, pix->pixelformat,
-                                                       FMT_TYPE_CAPTURE);
-       }
-
-       /*
-        * Decompression of a JPEG file with 4:2:0 subsampling and odd
-        * width to the YUV 4:2:0 compliant formats produces a raw image
-        * with broken luma component. Adjust capture format to RGB565
-        * in such a case.
-        */
-       if (ctx->subsampling == V4L2_JPEG_CHROMA_SUBSAMPLING_420 &&
-           (ctx->out_q.w & 1) &&
-           (pix->pixelformat == V4L2_PIX_FMT_NV12 ||
-            pix->pixelformat == V4L2_PIX_FMT_NV21 ||
-            pix->pixelformat == V4L2_PIX_FMT_YUV420)) {
-               pix->pixelformat = V4L2_PIX_FMT_RGB565;
-               fmt = s5p_jpeg_find_format(ctx, pix->pixelformat,
-                                                       FMT_TYPE_CAPTURE);
-       }
-
-exit:
-       return vidioc_try_fmt(f, fmt, ctx, FMT_TYPE_CAPTURE);
-}
-
-static int s5p_jpeg_try_fmt_vid_out(struct file *file, void *priv,
-                                 struct v4l2_format *f)
-{
-       struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
-       struct s5p_jpeg_fmt *fmt;
-
-       fmt = s5p_jpeg_find_format(ctx, f->fmt.pix.pixelformat,
-                                               FMT_TYPE_OUTPUT);
-       if (!fmt) {
-               v4l2_err(&ctx->jpeg->v4l2_dev,
-                        "Fourcc format (0x%08x) invalid.\n",
-                        f->fmt.pix.pixelformat);
-               return -EINVAL;
-       }
-
-       return vidioc_try_fmt(f, fmt, ctx, FMT_TYPE_OUTPUT);
-}
-
-static int exynos4_jpeg_get_output_buffer_size(struct s5p_jpeg_ctx *ctx,
-                                               struct v4l2_format *f,
-                                               int fmt_depth)
-{
-       struct v4l2_pix_format *pix = &f->fmt.pix;
-       u32 pix_fmt = f->fmt.pix.pixelformat;
-       int w = pix->width, h = pix->height, wh_align;
-       int padding = 0;
-
-       if (pix_fmt == V4L2_PIX_FMT_RGB32 ||
-           pix_fmt == V4L2_PIX_FMT_RGB565 ||
-           pix_fmt == V4L2_PIX_FMT_NV24 ||
-           pix_fmt == V4L2_PIX_FMT_NV42 ||
-           pix_fmt == V4L2_PIX_FMT_NV12 ||
-           pix_fmt == V4L2_PIX_FMT_NV21 ||
-           pix_fmt == V4L2_PIX_FMT_YUV420)
-               wh_align = 4;
-       else
-               wh_align = 1;
-
-       jpeg_bound_align_image(ctx, &w, S5P_JPEG_MIN_WIDTH,
-                              S5P_JPEG_MAX_WIDTH, wh_align,
-                              &h, S5P_JPEG_MIN_HEIGHT,
-                              S5P_JPEG_MAX_HEIGHT, wh_align);
-
-       if (ctx->jpeg->variant->version == SJPEG_EXYNOS4)
-               padding = PAGE_SIZE;
-
-       return (w * h * fmt_depth >> 3) + padding;
-}
-
-static int exynos3250_jpeg_try_downscale(struct s5p_jpeg_ctx *ctx,
-                                  struct v4l2_rect *r);
-
-static int s5p_jpeg_s_fmt(struct s5p_jpeg_ctx *ct, struct v4l2_format *f)
-{
-       struct vb2_queue *vq;
-       struct s5p_jpeg_q_data *q_data = NULL;
-       struct v4l2_pix_format *pix = &f->fmt.pix;
-       struct v4l2_ctrl *ctrl_subs;
-       struct v4l2_rect scale_rect;
-       unsigned int f_type;
-
-       vq = v4l2_m2m_get_vq(ct->fh.m2m_ctx, f->type);
-       if (!vq)
-               return -EINVAL;
-
-       q_data = get_q_data(ct, f->type);
-       BUG_ON(q_data == NULL);
-
-       if (vb2_is_busy(vq)) {
-               v4l2_err(&ct->jpeg->v4l2_dev, "%s queue busy\n", __func__);
-               return -EBUSY;
-       }
-
-       f_type = V4L2_TYPE_IS_OUTPUT(f->type) ?
-                       FMT_TYPE_OUTPUT : FMT_TYPE_CAPTURE;
-
-       q_data->fmt = s5p_jpeg_find_format(ct, pix->pixelformat, f_type);
-       if (ct->mode == S5P_JPEG_ENCODE ||
-               (ct->mode == S5P_JPEG_DECODE &&
-               q_data->fmt->fourcc != V4L2_PIX_FMT_JPEG)) {
-               q_data->w = pix->width;
-               q_data->h = pix->height;
-       }
-       if (q_data->fmt->fourcc != V4L2_PIX_FMT_JPEG) {
-               /*
-                * During encoding Exynos4x12 SoCs access wider memory area
-                * than it results from Image_x and Image_y values written to
-                * the JPEG_IMAGE_SIZE register. In order to avoid sysmmu
-                * page fault calculate proper buffer size in such a case.
-                */
-               if (ct->jpeg->variant->hw_ex4_compat &&
-                   f_type == FMT_TYPE_OUTPUT && ct->mode == S5P_JPEG_ENCODE)
-                       q_data->size = exynos4_jpeg_get_output_buffer_size(ct,
-                                                       f,
-                                                       q_data->fmt->depth);
-               else
-                       q_data->size = q_data->w * q_data->h *
-                                               q_data->fmt->depth >> 3;
-       } else {
-               q_data->size = pix->sizeimage;
-       }
-
-       if (f_type == FMT_TYPE_OUTPUT) {
-               ctrl_subs = v4l2_ctrl_find(&ct->ctrl_handler,
-                                       V4L2_CID_JPEG_CHROMA_SUBSAMPLING);
-               if (ctrl_subs)
-                       v4l2_ctrl_s_ctrl(ctrl_subs, q_data->fmt->subsampling);
-               ct->crop_altered = false;
-       }
-
-       /*
-        * For decoding init crop_rect with capture buffer dimmensions which
-        * contain aligned dimensions of the input JPEG image and do it only
-        * if crop rectangle hasn't been altered by the user space e.g. with
-        * S_SELECTION ioctl. For encoding assign output buffer dimensions.
-        */
-       if (!ct->crop_altered &&
-           ((ct->mode == S5P_JPEG_DECODE && f_type == FMT_TYPE_CAPTURE) ||
-            (ct->mode == S5P_JPEG_ENCODE && f_type == FMT_TYPE_OUTPUT))) {
-               ct->crop_rect.width = pix->width;
-               ct->crop_rect.height = pix->height;
-       }
-
-       /*
-        * Prevent downscaling to YUV420 format by more than 2
-        * for Exynos3250/compatible SoC as it produces broken raw image
-        * in such cases.
-        */
-       if (ct->mode == S5P_JPEG_DECODE &&
-           f_type == FMT_TYPE_CAPTURE &&
-           ct->jpeg->variant->hw3250_compat &&
-           pix->pixelformat == V4L2_PIX_FMT_YUV420 &&
-           ct->scale_factor > 2) {
-               scale_rect.width = ct->out_q.w / 2;
-               scale_rect.height = ct->out_q.h / 2;
-               exynos3250_jpeg_try_downscale(ct, &scale_rect);
-       }
-
-       return 0;
-}
-
-static int s5p_jpeg_s_fmt_vid_cap(struct file *file, void *priv,
-                               struct v4l2_format *f)
-{
-       int ret;
-
-       ret = s5p_jpeg_try_fmt_vid_cap(file, priv, f);
-       if (ret)
-               return ret;
-
-       return s5p_jpeg_s_fmt(fh_to_ctx(priv), f);
-}
-
-static int s5p_jpeg_s_fmt_vid_out(struct file *file, void *priv,
-                               struct v4l2_format *f)
-{
-       int ret;
-
-       ret = s5p_jpeg_try_fmt_vid_out(file, priv, f);
-       if (ret)
-               return ret;
-
-       return s5p_jpeg_s_fmt(fh_to_ctx(priv), f);
-}
-
-static int s5p_jpeg_subscribe_event(struct v4l2_fh *fh,
-                                   const struct v4l2_event_subscription *sub)
-{
-       if (sub->type == V4L2_EVENT_SOURCE_CHANGE)
-               return v4l2_src_change_event_subscribe(fh, sub);
-
-       return -EINVAL;
-}
-
-static int exynos3250_jpeg_try_downscale(struct s5p_jpeg_ctx *ctx,
-                                  struct v4l2_rect *r)
-{
-       int w_ratio, h_ratio, scale_factor, cur_ratio, i;
-
-       w_ratio = ctx->out_q.w / r->width;
-       h_ratio = ctx->out_q.h / r->height;
-
-       scale_factor = w_ratio > h_ratio ? w_ratio : h_ratio;
-       scale_factor = clamp_val(scale_factor, 1, 8);
-
-       /* Align scale ratio to the nearest power of 2 */
-       for (i = 0; i <= 3; ++i) {
-               cur_ratio = 1 << i;
-               if (scale_factor <= cur_ratio) {
-                       ctx->scale_factor = cur_ratio;
-                       break;
-               }
-       }
-
-       r->width = round_down(ctx->out_q.w / ctx->scale_factor, 2);
-       r->height = round_down(ctx->out_q.h / ctx->scale_factor, 2);
-
-       ctx->crop_rect.width = r->width;
-       ctx->crop_rect.height = r->height;
-       ctx->crop_rect.left = 0;
-       ctx->crop_rect.top = 0;
-
-       ctx->crop_altered = true;
-
-       return 0;
-}
-
-static int exynos3250_jpeg_try_crop(struct s5p_jpeg_ctx *ctx,
-                                  struct v4l2_rect *r)
-{
-       struct v4l2_rect base_rect;
-       int w_step, h_step;
-
-       switch (ctx->cap_q.fmt->fourcc) {
-       case V4L2_PIX_FMT_NV12:
-       case V4L2_PIX_FMT_NV21:
-               w_step = 1;
-               h_step = 2;
-               break;
-       case V4L2_PIX_FMT_YUV420:
-               w_step = 2;
-               h_step = 2;
-               break;
-       default:
-               w_step = 1;
-               h_step = 1;
-               break;
-       }
-
-       base_rect.top = 0;
-       base_rect.left = 0;
-       base_rect.width = ctx->out_q.w;
-       base_rect.height = ctx->out_q.h;
-
-       r->width = round_down(r->width, w_step);
-       r->height = round_down(r->height, h_step);
-       r->left = round_down(r->left, 2);
-       r->top = round_down(r->top, 2);
-
-       if (!v4l2_rect_enclosed(r, &base_rect))
-               return -EINVAL;
-
-       ctx->crop_rect.left = r->left;
-       ctx->crop_rect.top = r->top;
-       ctx->crop_rect.width = r->width;
-       ctx->crop_rect.height = r->height;
-
-       ctx->crop_altered = true;
-
-       return 0;
-}
-
-/*
- * V4L2 controls
- */
-
-static int s5p_jpeg_g_selection(struct file *file, void *priv,
-                        struct v4l2_selection *s)
-{
-       struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
-
-       if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
-           s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-
-       /* For JPEG blob active == default == bounds */
-       switch (s->target) {
-       case V4L2_SEL_TGT_CROP:
-       case V4L2_SEL_TGT_CROP_BOUNDS:
-       case V4L2_SEL_TGT_CROP_DEFAULT:
-       case V4L2_SEL_TGT_COMPOSE_DEFAULT:
-               s->r.width = ctx->out_q.w;
-               s->r.height = ctx->out_q.h;
-               s->r.left = 0;
-               s->r.top = 0;
-               break;
-       case V4L2_SEL_TGT_COMPOSE:
-       case V4L2_SEL_TGT_COMPOSE_BOUNDS:
-       case V4L2_SEL_TGT_COMPOSE_PADDED:
-               s->r.width = ctx->crop_rect.width;
-               s->r.height =  ctx->crop_rect.height;
-               s->r.left = ctx->crop_rect.left;
-               s->r.top = ctx->crop_rect.top;
-               break;
-       default:
-               return -EINVAL;
-       }
-       return 0;
-}
-
-/*
- * V4L2 controls
- */
-static int s5p_jpeg_s_selection(struct file *file, void *fh,
-                                 struct v4l2_selection *s)
-{
-       struct s5p_jpeg_ctx *ctx = fh_to_ctx(file->private_data);
-       struct v4l2_rect *rect = &s->r;
-       int ret = -EINVAL;
-
-       if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-
-       if (s->target == V4L2_SEL_TGT_COMPOSE) {
-               if (ctx->mode != S5P_JPEG_DECODE)
-                       return -EINVAL;
-               if (ctx->jpeg->variant->hw3250_compat)
-                       ret = exynos3250_jpeg_try_downscale(ctx, rect);
-       } else if (s->target == V4L2_SEL_TGT_CROP) {
-               if (ctx->mode != S5P_JPEG_ENCODE)
-                       return -EINVAL;
-               if (ctx->jpeg->variant->hw3250_compat)
-                       ret = exynos3250_jpeg_try_crop(ctx, rect);
-       }
-
-       return ret;
-}
-
-static int s5p_jpeg_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
-{
-       struct s5p_jpeg_ctx *ctx = ctrl_to_ctx(ctrl);
-       struct s5p_jpeg *jpeg = ctx->jpeg;
-       unsigned long flags;
-
-       switch (ctrl->id) {
-       case V4L2_CID_JPEG_CHROMA_SUBSAMPLING:
-               spin_lock_irqsave(&jpeg->slock, flags);
-               ctrl->val = s5p_jpeg_to_user_subsampling(ctx);
-               spin_unlock_irqrestore(&jpeg->slock, flags);
-               break;
-       }
-
-       return 0;
-}
-
-static int s5p_jpeg_adjust_subs_ctrl(struct s5p_jpeg_ctx *ctx, int *ctrl_val)
-{
-       switch (ctx->jpeg->variant->version) {
-       case SJPEG_S5P:
-               return 0;
-       case SJPEG_EXYNOS3250:
-       case SJPEG_EXYNOS5420:
-               /*
-                * The exynos3250/compatible device can produce JPEG image only
-                * of 4:4:4 subsampling when given RGB32 source image.
-                */
-               if (ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB32)
-                       *ctrl_val = 0;
-               break;
-       case SJPEG_EXYNOS4:
-               /*
-                * The exynos4x12 device requires input raw image fourcc
-                * to be V4L2_PIX_FMT_GREY if gray jpeg format
-                * is to be set.
-                */
-               if (ctx->out_q.fmt->fourcc != V4L2_PIX_FMT_GREY &&
-                   *ctrl_val == V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY)
-                       return -EINVAL;
-               break;
-       }
-
-       /*
-        * The exynos4x12 and exynos3250/compatible devices require resulting
-        * jpeg subsampling not to be lower than the input raw image
-        * subsampling.
-        */
-       if (ctx->out_q.fmt->subsampling > *ctrl_val)
-               *ctrl_val = ctx->out_q.fmt->subsampling;
-
-       return 0;
-}
-
-static int s5p_jpeg_try_ctrl(struct v4l2_ctrl *ctrl)
-{
-       struct s5p_jpeg_ctx *ctx = ctrl_to_ctx(ctrl);
-       unsigned long flags;
-       int ret = 0;
-
-       spin_lock_irqsave(&ctx->jpeg->slock, flags);
-
-       if (ctrl->id == V4L2_CID_JPEG_CHROMA_SUBSAMPLING)
-               ret = s5p_jpeg_adjust_subs_ctrl(ctx, &ctrl->val);
-
-       spin_unlock_irqrestore(&ctx->jpeg->slock, flags);
-       return ret;
-}
-
-static int s5p_jpeg_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-       struct s5p_jpeg_ctx *ctx = ctrl_to_ctx(ctrl);
-       unsigned long flags;
-
-       spin_lock_irqsave(&ctx->jpeg->slock, flags);
-
-       switch (ctrl->id) {
-       case V4L2_CID_JPEG_COMPRESSION_QUALITY:
-               ctx->compr_quality = ctrl->val;
-               break;
-       case V4L2_CID_JPEG_RESTART_INTERVAL:
-               ctx->restart_interval = ctrl->val;
-               break;
-       case V4L2_CID_JPEG_CHROMA_SUBSAMPLING:
-               ctx->subsampling = ctrl->val;
-               break;
-       }
-
-       spin_unlock_irqrestore(&ctx->jpeg->slock, flags);
-       return 0;
-}
-
-static const struct v4l2_ctrl_ops s5p_jpeg_ctrl_ops = {
-       .g_volatile_ctrl        = s5p_jpeg_g_volatile_ctrl,
-       .try_ctrl               = s5p_jpeg_try_ctrl,
-       .s_ctrl                 = s5p_jpeg_s_ctrl,
-};
-
-static int s5p_jpeg_controls_create(struct s5p_jpeg_ctx *ctx)
-{
-       unsigned int mask = ~0x27; /* 444, 422, 420, GRAY */
-       struct v4l2_ctrl *ctrl;
-       int ret;
-
-       v4l2_ctrl_handler_init(&ctx->ctrl_handler, 3);
-
-       if (ctx->mode == S5P_JPEG_ENCODE) {
-               v4l2_ctrl_new_std(&ctx->ctrl_handler, &s5p_jpeg_ctrl_ops,
-                                 V4L2_CID_JPEG_COMPRESSION_QUALITY,
-                                 0, 3, 1, S5P_JPEG_COMPR_QUAL_WORST);
-
-               v4l2_ctrl_new_std(&ctx->ctrl_handler, &s5p_jpeg_ctrl_ops,
-                                 V4L2_CID_JPEG_RESTART_INTERVAL,
-                                 0, 0xffff, 1, 0);
-               if (ctx->jpeg->variant->version == SJPEG_S5P)
-                       mask = ~0x06; /* 422, 420 */
-       }
-
-       ctrl = v4l2_ctrl_new_std_menu(&ctx->ctrl_handler, &s5p_jpeg_ctrl_ops,
-                                     V4L2_CID_JPEG_CHROMA_SUBSAMPLING,
-                                     V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY, mask,
-                                     V4L2_JPEG_CHROMA_SUBSAMPLING_422);
-
-       if (ctx->ctrl_handler.error) {
-               ret = ctx->ctrl_handler.error;
-               goto error_free;
-       }
-
-       if (ctx->mode == S5P_JPEG_DECODE)
-               ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE |
-                       V4L2_CTRL_FLAG_READ_ONLY;
-
-       ret = v4l2_ctrl_handler_setup(&ctx->ctrl_handler);
-       if (ret < 0)
-               goto error_free;
-
-       return ret;
-
-error_free:
-       v4l2_ctrl_handler_free(&ctx->ctrl_handler);
-       return ret;
-}
-
-static const struct v4l2_ioctl_ops s5p_jpeg_ioctl_ops = {
-       .vidioc_querycap                = s5p_jpeg_querycap,
-
-       .vidioc_enum_fmt_vid_cap        = s5p_jpeg_enum_fmt_vid_cap,
-       .vidioc_enum_fmt_vid_out        = s5p_jpeg_enum_fmt_vid_out,
-
-       .vidioc_g_fmt_vid_cap           = s5p_jpeg_g_fmt,
-       .vidioc_g_fmt_vid_out           = s5p_jpeg_g_fmt,
-
-       .vidioc_try_fmt_vid_cap         = s5p_jpeg_try_fmt_vid_cap,
-       .vidioc_try_fmt_vid_out         = s5p_jpeg_try_fmt_vid_out,
-
-       .vidioc_s_fmt_vid_cap           = s5p_jpeg_s_fmt_vid_cap,
-       .vidioc_s_fmt_vid_out           = s5p_jpeg_s_fmt_vid_out,
-
-       .vidioc_reqbufs                 = v4l2_m2m_ioctl_reqbufs,
-       .vidioc_querybuf                = v4l2_m2m_ioctl_querybuf,
-       .vidioc_qbuf                    = v4l2_m2m_ioctl_qbuf,
-       .vidioc_dqbuf                   = v4l2_m2m_ioctl_dqbuf,
-
-       .vidioc_streamon                = v4l2_m2m_ioctl_streamon,
-       .vidioc_streamoff               = v4l2_m2m_ioctl_streamoff,
-
-       .vidioc_g_selection             = s5p_jpeg_g_selection,
-       .vidioc_s_selection             = s5p_jpeg_s_selection,
-
-       .vidioc_subscribe_event         = s5p_jpeg_subscribe_event,
-       .vidioc_unsubscribe_event       = v4l2_event_unsubscribe,
-};
-
-/*
- * ============================================================================
- * mem2mem callbacks
- * ============================================================================
- */
-
-static void s5p_jpeg_device_run(void *priv)
-{
-       struct s5p_jpeg_ctx *ctx = priv;
-       struct s5p_jpeg *jpeg = ctx->jpeg;
-       struct vb2_v4l2_buffer *src_buf, *dst_buf;
-       unsigned long src_addr, dst_addr, flags;
-
-       spin_lock_irqsave(&ctx->jpeg->slock, flags);
-
-       src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
-       dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
-       src_addr = vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0);
-       dst_addr = vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0);
-
-       s5p_jpeg_reset(jpeg->regs);
-       s5p_jpeg_poweron(jpeg->regs);
-       s5p_jpeg_proc_mode(jpeg->regs, ctx->mode);
-       if (ctx->mode == S5P_JPEG_ENCODE) {
-               if (ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB565)
-                       s5p_jpeg_input_raw_mode(jpeg->regs,
-                                                       S5P_JPEG_RAW_IN_565);
-               else
-                       s5p_jpeg_input_raw_mode(jpeg->regs,
-                                                       S5P_JPEG_RAW_IN_422);
-               s5p_jpeg_subsampling_mode(jpeg->regs, ctx->subsampling);
-               s5p_jpeg_dri(jpeg->regs, ctx->restart_interval);
-               s5p_jpeg_x(jpeg->regs, ctx->out_q.w);
-               s5p_jpeg_y(jpeg->regs, ctx->out_q.h);
-               s5p_jpeg_imgadr(jpeg->regs, src_addr);
-               s5p_jpeg_jpgadr(jpeg->regs, dst_addr);
-
-               /* ultimately comes from sizeimage from userspace */
-               s5p_jpeg_enc_stream_int(jpeg->regs, ctx->cap_q.size);
-
-               /* JPEG RGB to YCbCr conversion matrix */
-               s5p_jpeg_coef(jpeg->regs, 1, 1, S5P_JPEG_COEF11);
-               s5p_jpeg_coef(jpeg->regs, 1, 2, S5P_JPEG_COEF12);
-               s5p_jpeg_coef(jpeg->regs, 1, 3, S5P_JPEG_COEF13);
-               s5p_jpeg_coef(jpeg->regs, 2, 1, S5P_JPEG_COEF21);
-               s5p_jpeg_coef(jpeg->regs, 2, 2, S5P_JPEG_COEF22);
-               s5p_jpeg_coef(jpeg->regs, 2, 3, S5P_JPEG_COEF23);
-               s5p_jpeg_coef(jpeg->regs, 3, 1, S5P_JPEG_COEF31);
-               s5p_jpeg_coef(jpeg->regs, 3, 2, S5P_JPEG_COEF32);
-               s5p_jpeg_coef(jpeg->regs, 3, 3, S5P_JPEG_COEF33);
-
-               /*
-                * JPEG IP allows storing 4 quantization tables
-                * We fill table 0 for luma and table 1 for chroma
-                */
-               s5p_jpeg_set_qtbl_lum(jpeg->regs, ctx->compr_quality);
-               s5p_jpeg_set_qtbl_chr(jpeg->regs, ctx->compr_quality);
-               /* use table 0 for Y */
-               s5p_jpeg_qtbl(jpeg->regs, 1, 0);
-               /* use table 1 for Cb and Cr*/
-               s5p_jpeg_qtbl(jpeg->regs, 2, 1);
-               s5p_jpeg_qtbl(jpeg->regs, 3, 1);
-
-               /* Y, Cb, Cr use Huffman table 0 */
-               s5p_jpeg_htbl_ac(jpeg->regs, 1);
-               s5p_jpeg_htbl_dc(jpeg->regs, 1);
-               s5p_jpeg_htbl_ac(jpeg->regs, 2);
-               s5p_jpeg_htbl_dc(jpeg->regs, 2);
-               s5p_jpeg_htbl_ac(jpeg->regs, 3);
-               s5p_jpeg_htbl_dc(jpeg->regs, 3);
-       } else { /* S5P_JPEG_DECODE */
-               s5p_jpeg_rst_int_enable(jpeg->regs, true);
-               s5p_jpeg_data_num_int_enable(jpeg->regs, true);
-               s5p_jpeg_final_mcu_num_int_enable(jpeg->regs, true);
-               if (ctx->cap_q.fmt->fourcc == V4L2_PIX_FMT_YUYV)
-                       s5p_jpeg_outform_raw(jpeg->regs, S5P_JPEG_RAW_OUT_422);
-               else
-                       s5p_jpeg_outform_raw(jpeg->regs, S5P_JPEG_RAW_OUT_420);
-               s5p_jpeg_jpgadr(jpeg->regs, src_addr);
-               s5p_jpeg_imgadr(jpeg->regs, dst_addr);
-       }
-
-       s5p_jpeg_start(jpeg->regs);
-
-       spin_unlock_irqrestore(&ctx->jpeg->slock, flags);
-}
-
-static void exynos4_jpeg_set_img_addr(struct s5p_jpeg_ctx *ctx)
-{
-       struct s5p_jpeg *jpeg = ctx->jpeg;
-       struct s5p_jpeg_fmt *fmt;
-       struct vb2_v4l2_buffer *vb;
-       struct s5p_jpeg_addr jpeg_addr = {};
-       u32 pix_size, padding_bytes = 0;
-
-       jpeg_addr.cb = 0;
-       jpeg_addr.cr = 0;
-
-       pix_size = ctx->cap_q.w * ctx->cap_q.h;
-
-       if (ctx->mode == S5P_JPEG_ENCODE) {
-               vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
-               fmt = ctx->out_q.fmt;
-               if (ctx->out_q.w % 2 && fmt->h_align > 0)
-                       padding_bytes = ctx->out_q.h;
-       } else {
-               fmt = ctx->cap_q.fmt;
-               vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
-       }
-
-       jpeg_addr.y = vb2_dma_contig_plane_dma_addr(&vb->vb2_buf, 0);
-
-       if (fmt->colplanes == 2) {
-               jpeg_addr.cb = jpeg_addr.y + pix_size - padding_bytes;
-       } else if (fmt->colplanes == 3) {
-               jpeg_addr.cb = jpeg_addr.y + pix_size;
-               if (fmt->fourcc == V4L2_PIX_FMT_YUV420)
-                       jpeg_addr.cr = jpeg_addr.cb + pix_size / 4;
-               else
-                       jpeg_addr.cr = jpeg_addr.cb + pix_size / 2;
-       }
-
-       exynos4_jpeg_set_frame_buf_address(jpeg->regs, &jpeg_addr);
-}
-
-static void exynos4_jpeg_set_jpeg_addr(struct s5p_jpeg_ctx *ctx)
-{
-       struct s5p_jpeg *jpeg = ctx->jpeg;
-       struct vb2_v4l2_buffer *vb;
-       unsigned int jpeg_addr = 0;
-
-       if (ctx->mode == S5P_JPEG_ENCODE)
-               vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
-       else
-               vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
-
-       jpeg_addr = vb2_dma_contig_plane_dma_addr(&vb->vb2_buf, 0);
-       if (jpeg->variant->version == SJPEG_EXYNOS5433 &&
-           ctx->mode == S5P_JPEG_DECODE)
-               jpeg_addr += ctx->out_q.sos;
-       exynos4_jpeg_set_stream_buf_address(jpeg->regs, jpeg_addr);
-}
-
-static inline void exynos4_jpeg_set_img_fmt(void __iomem *base,
-                                           unsigned int img_fmt)
-{
-       __exynos4_jpeg_set_img_fmt(base, img_fmt, SJPEG_EXYNOS4);
-}
-
-static inline void exynos5433_jpeg_set_img_fmt(void __iomem *base,
-                                              unsigned int img_fmt)
-{
-       __exynos4_jpeg_set_img_fmt(base, img_fmt, SJPEG_EXYNOS5433);
-}
-
-static inline void exynos4_jpeg_set_enc_out_fmt(void __iomem *base,
-                                               unsigned int out_fmt)
-{
-       __exynos4_jpeg_set_enc_out_fmt(base, out_fmt, SJPEG_EXYNOS4);
-}
-
-static inline void exynos5433_jpeg_set_enc_out_fmt(void __iomem *base,
-                                                  unsigned int out_fmt)
-{
-       __exynos4_jpeg_set_enc_out_fmt(base, out_fmt, SJPEG_EXYNOS5433);
-}
-
-static void exynos4_jpeg_device_run(void *priv)
-{
-       struct s5p_jpeg_ctx *ctx = priv;
-       struct s5p_jpeg *jpeg = ctx->jpeg;
-       unsigned int bitstream_size;
-       unsigned long flags;
-
-       spin_lock_irqsave(&jpeg->slock, flags);
-
-       if (ctx->mode == S5P_JPEG_ENCODE) {
-               exynos4_jpeg_sw_reset(jpeg->regs);
-               exynos4_jpeg_set_interrupt(jpeg->regs, jpeg->variant->version);
-               exynos4_jpeg_set_huf_table_enable(jpeg->regs, 1);
-
-               exynos4_jpeg_set_huff_tbl(jpeg->regs);
-
-               /*
-                * JPEG IP allows storing 4 quantization tables
-                * We fill table 0 for luma and table 1 for chroma
-                */
-               exynos4_jpeg_set_qtbl_lum(jpeg->regs, ctx->compr_quality);
-               exynos4_jpeg_set_qtbl_chr(jpeg->regs, ctx->compr_quality);
-
-               exynos4_jpeg_set_encode_tbl_select(jpeg->regs,
-                                                       ctx->compr_quality);
-               exynos4_jpeg_set_stream_size(jpeg->regs, ctx->cap_q.w,
-                                                       ctx->cap_q.h);
-
-               if (ctx->jpeg->variant->version == SJPEG_EXYNOS4) {
-                       exynos4_jpeg_set_enc_out_fmt(jpeg->regs,
-                                                    ctx->subsampling);
-                       exynos4_jpeg_set_img_fmt(jpeg->regs,
-                                                ctx->out_q.fmt->fourcc);
-               } else {
-                       exynos5433_jpeg_set_enc_out_fmt(jpeg->regs,
-                                                       ctx->subsampling);
-                       exynos5433_jpeg_set_img_fmt(jpeg->regs,
-                                                   ctx->out_q.fmt->fourcc);
-               }
-               exynos4_jpeg_set_img_addr(ctx);
-               exynos4_jpeg_set_jpeg_addr(ctx);
-               exynos4_jpeg_set_encode_hoff_cnt(jpeg->regs,
-                                                       ctx->out_q.fmt->fourcc);
-       } else {
-               exynos4_jpeg_sw_reset(jpeg->regs);
-               exynos4_jpeg_set_interrupt(jpeg->regs,
-                                          jpeg->variant->version);
-               exynos4_jpeg_set_img_addr(ctx);
-               exynos4_jpeg_set_jpeg_addr(ctx);
-
-               if (jpeg->variant->version == SJPEG_EXYNOS5433) {
-                       exynos4_jpeg_parse_huff_tbl(ctx);
-                       exynos4_jpeg_parse_decode_h_tbl(ctx);
-
-                       exynos4_jpeg_parse_q_tbl(ctx);
-                       exynos4_jpeg_parse_decode_q_tbl(ctx);
-
-                       exynos4_jpeg_set_huf_table_enable(jpeg->regs, 1);
-
-                       exynos4_jpeg_set_stream_size(jpeg->regs, ctx->cap_q.w,
-                                       ctx->cap_q.h);
-                       exynos5433_jpeg_set_enc_out_fmt(jpeg->regs,
-                                                       ctx->subsampling);
-                       exynos5433_jpeg_set_img_fmt(jpeg->regs,
-                                                   ctx->cap_q.fmt->fourcc);
-                       bitstream_size = DIV_ROUND_UP(ctx->out_q.size, 16);
-               } else {
-                       exynos4_jpeg_set_img_fmt(jpeg->regs,
-                                                ctx->cap_q.fmt->fourcc);
-                       bitstream_size = DIV_ROUND_UP(ctx->out_q.size, 32);
-               }
-
-               exynos4_jpeg_set_dec_bitstream_size(jpeg->regs, bitstream_size);
-       }
-
-       exynos4_jpeg_set_sys_int_enable(jpeg->regs, 1);
-       exynos4_jpeg_set_enc_dec_mode(jpeg->regs, ctx->mode);
-
-       spin_unlock_irqrestore(&jpeg->slock, flags);
-}
-
-static void exynos3250_jpeg_set_img_addr(struct s5p_jpeg_ctx *ctx)
-{
-       struct s5p_jpeg *jpeg = ctx->jpeg;
-       struct s5p_jpeg_fmt *fmt;
-       struct vb2_v4l2_buffer *vb;
-       struct s5p_jpeg_addr jpeg_addr = {};
-       u32 pix_size;
-
-       pix_size = ctx->cap_q.w * ctx->cap_q.h;
-
-       if (ctx->mode == S5P_JPEG_ENCODE) {
-               vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
-               fmt = ctx->out_q.fmt;
-       } else {
-               vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
-               fmt = ctx->cap_q.fmt;
-       }
-
-       jpeg_addr.y = vb2_dma_contig_plane_dma_addr(&vb->vb2_buf, 0);
-
-       if (fmt->colplanes == 2) {
-               jpeg_addr.cb = jpeg_addr.y + pix_size;
-       } else if (fmt->colplanes == 3) {
-               jpeg_addr.cb = jpeg_addr.y + pix_size;
-               if (fmt->fourcc == V4L2_PIX_FMT_YUV420)
-                       jpeg_addr.cr = jpeg_addr.cb + pix_size / 4;
-               else
-                       jpeg_addr.cr = jpeg_addr.cb + pix_size / 2;
-       }
-
-       exynos3250_jpeg_imgadr(jpeg->regs, &jpeg_addr);
-}
-
-static void exynos3250_jpeg_set_jpeg_addr(struct s5p_jpeg_ctx *ctx)
-{
-       struct s5p_jpeg *jpeg = ctx->jpeg;
-       struct vb2_v4l2_buffer *vb;
-       unsigned int jpeg_addr = 0;
-
-       if (ctx->mode == S5P_JPEG_ENCODE)
-               vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
-       else
-               vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
-
-       jpeg_addr = vb2_dma_contig_plane_dma_addr(&vb->vb2_buf, 0);
-       exynos3250_jpeg_jpgadr(jpeg->regs, jpeg_addr);
-}
-
-static void exynos3250_jpeg_device_run(void *priv)
-{
-       struct s5p_jpeg_ctx *ctx = priv;
-       struct s5p_jpeg *jpeg = ctx->jpeg;
-       unsigned long flags;
-
-       spin_lock_irqsave(&ctx->jpeg->slock, flags);
-
-       exynos3250_jpeg_reset(jpeg->regs);
-       exynos3250_jpeg_set_dma_num(jpeg->regs);
-       exynos3250_jpeg_poweron(jpeg->regs);
-       exynos3250_jpeg_clk_set(jpeg->regs);
-       exynos3250_jpeg_proc_mode(jpeg->regs, ctx->mode);
-
-       if (ctx->mode == S5P_JPEG_ENCODE) {
-               exynos3250_jpeg_input_raw_fmt(jpeg->regs,
-                                             ctx->out_q.fmt->fourcc);
-               exynos3250_jpeg_dri(jpeg->regs, ctx->restart_interval);
-
-               /*
-                * JPEG IP allows storing 4 quantization tables
-                * We fill table 0 for luma and table 1 for chroma
-                */
-               s5p_jpeg_set_qtbl_lum(jpeg->regs, ctx->compr_quality);
-               s5p_jpeg_set_qtbl_chr(jpeg->regs, ctx->compr_quality);
-               /* use table 0 for Y */
-               exynos3250_jpeg_qtbl(jpeg->regs, 1, 0);
-               /* use table 1 for Cb and Cr*/
-               exynos3250_jpeg_qtbl(jpeg->regs, 2, 1);
-               exynos3250_jpeg_qtbl(jpeg->regs, 3, 1);
-
-               /*
-                * Some SoCs require setting Huffman tables before each run
-                */
-               if (jpeg->variant->htbl_reinit) {
-                       s5p_jpeg_set_hdctbl(jpeg->regs);
-                       s5p_jpeg_set_hdctblg(jpeg->regs);
-                       s5p_jpeg_set_hactbl(jpeg->regs);
-                       s5p_jpeg_set_hactblg(jpeg->regs);
-               }
-
-               /* Y, Cb, Cr use Huffman table 0 */
-               exynos3250_jpeg_htbl_ac(jpeg->regs, 1);
-               exynos3250_jpeg_htbl_dc(jpeg->regs, 1);
-               exynos3250_jpeg_htbl_ac(jpeg->regs, 2);
-               exynos3250_jpeg_htbl_dc(jpeg->regs, 2);
-               exynos3250_jpeg_htbl_ac(jpeg->regs, 3);
-               exynos3250_jpeg_htbl_dc(jpeg->regs, 3);
-
-               exynos3250_jpeg_set_x(jpeg->regs, ctx->crop_rect.width);
-               exynos3250_jpeg_set_y(jpeg->regs, ctx->crop_rect.height);
-               exynos3250_jpeg_stride(jpeg->regs, ctx->out_q.fmt->fourcc,
-                                                               ctx->out_q.w);
-               exynos3250_jpeg_offset(jpeg->regs, ctx->crop_rect.left,
-                                                       ctx->crop_rect.top);
-               exynos3250_jpeg_set_img_addr(ctx);
-               exynos3250_jpeg_set_jpeg_addr(ctx);
-               exynos3250_jpeg_subsampling_mode(jpeg->regs, ctx->subsampling);
-
-               /* ultimately comes from sizeimage from userspace */
-               exynos3250_jpeg_enc_stream_bound(jpeg->regs, ctx->cap_q.size);
-
-               if (ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB565 ||
-                   ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB565X ||
-                   ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB32)
-                       exynos3250_jpeg_set_y16(jpeg->regs, true);
-       } else {
-               exynos3250_jpeg_set_img_addr(ctx);
-               exynos3250_jpeg_set_jpeg_addr(ctx);
-               exynos3250_jpeg_stride(jpeg->regs, ctx->cap_q.fmt->fourcc,
-                                                               ctx->cap_q.w);
-               exynos3250_jpeg_offset(jpeg->regs, 0, 0);
-               exynos3250_jpeg_dec_scaling_ratio(jpeg->regs,
-                                                       ctx->scale_factor);
-               exynos3250_jpeg_dec_stream_size(jpeg->regs, ctx->out_q.size);
-               exynos3250_jpeg_output_raw_fmt(jpeg->regs,
-                                               ctx->cap_q.fmt->fourcc);
-       }
-
-       exynos3250_jpeg_interrupts_enable(jpeg->regs);
-
-       /* JPEG RGB to YCbCr conversion matrix */
-       exynos3250_jpeg_coef(jpeg->regs, ctx->mode);
-
-       exynos3250_jpeg_set_timer(jpeg->regs, EXYNOS3250_IRQ_TIMEOUT);
-       jpeg->irq_status = 0;
-       exynos3250_jpeg_start(jpeg->regs);
-
-       spin_unlock_irqrestore(&ctx->jpeg->slock, flags);
-}
-
-static int s5p_jpeg_job_ready(void *priv)
-{
-       struct s5p_jpeg_ctx *ctx = priv;
-
-       if (ctx->mode == S5P_JPEG_DECODE) {
-               /*
-                * We have only one input buffer and one output buffer. If there
-                * is a resolution change event, no need to continue decoding.
-                */
-               if (ctx->state == JPEGCTX_RESOLUTION_CHANGE)
-                       return 0;
-
-               return ctx->hdr_parsed;
-       }
-
-       return 1;
-}
-
-static const struct v4l2_m2m_ops s5p_jpeg_m2m_ops = {
-       .device_run     = s5p_jpeg_device_run,
-       .job_ready      = s5p_jpeg_job_ready,
-};
-
-static const struct v4l2_m2m_ops exynos3250_jpeg_m2m_ops = {
-       .device_run     = exynos3250_jpeg_device_run,
-       .job_ready      = s5p_jpeg_job_ready,
-};
-
-static const struct v4l2_m2m_ops exynos4_jpeg_m2m_ops = {
-       .device_run     = exynos4_jpeg_device_run,
-       .job_ready      = s5p_jpeg_job_ready,
-};
-
-/*
- * ============================================================================
- * Queue operations
- * ============================================================================
- */
-
-static int s5p_jpeg_queue_setup(struct vb2_queue *vq,
-                          unsigned int *nbuffers, unsigned int *nplanes,
-                          unsigned int sizes[], struct device *alloc_devs[])
-{
-       struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vq);
-       struct s5p_jpeg_q_data *q_data = NULL;
-       unsigned int size, count = *nbuffers;
-
-       q_data = get_q_data(ctx, vq->type);
-       BUG_ON(q_data == NULL);
-
-       size = q_data->size;
-
-       /*
-        * header is parsed during decoding and parsed information stored
-        * in the context so we do not allow another buffer to overwrite it
-        */
-       if (ctx->mode == S5P_JPEG_DECODE)
-               count = 1;
-
-       *nbuffers = count;
-       *nplanes = 1;
-       sizes[0] = size;
-
-       return 0;
-}
-
-static int s5p_jpeg_buf_prepare(struct vb2_buffer *vb)
-{
-       struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
-       struct s5p_jpeg_q_data *q_data = NULL;
-
-       q_data = get_q_data(ctx, vb->vb2_queue->type);
-       BUG_ON(q_data == NULL);
-
-       if (vb2_plane_size(vb, 0) < q_data->size) {
-               pr_err("%s data will not fit into plane (%lu < %lu)\n",
-                               __func__, vb2_plane_size(vb, 0),
-                               (long)q_data->size);
-               return -EINVAL;
-       }
-
-       vb2_set_plane_payload(vb, 0, q_data->size);
-
-       return 0;
-}
-
-static void s5p_jpeg_set_capture_queue_data(struct s5p_jpeg_ctx *ctx)
-{
-       struct s5p_jpeg_q_data *q_data = &ctx->cap_q;
-
-       q_data->w = ctx->out_q.w;
-       q_data->h = ctx->out_q.h;
-
-       /*
-        * This call to jpeg_bound_align_image() takes care of width and
-        * height values alignment when user space calls the QBUF of
-        * OUTPUT buffer after the S_FMT of CAPTURE buffer.
-        * Please note that on Exynos4x12 SoCs, resigning from executing
-        * S_FMT on capture buffer for each JPEG image can result in a
-        * hardware hangup if subsampling is lower than the one of input
-        * JPEG.
-        */
-       jpeg_bound_align_image(ctx, &q_data->w, S5P_JPEG_MIN_WIDTH,
-                              S5P_JPEG_MAX_WIDTH, q_data->fmt->h_align,
-                              &q_data->h, S5P_JPEG_MIN_HEIGHT,
-                              S5P_JPEG_MAX_HEIGHT, q_data->fmt->v_align);
-
-       q_data->size = q_data->w * q_data->h * q_data->fmt->depth >> 3;
-}
-
-static void s5p_jpeg_buf_queue(struct vb2_buffer *vb)
-{
-       struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
-       struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
-
-       if (ctx->mode == S5P_JPEG_DECODE &&
-           vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
-               static const struct v4l2_event ev_src_ch = {
-                       .type = V4L2_EVENT_SOURCE_CHANGE,
-                       .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,
-               };
-               struct vb2_queue *dst_vq;
-               u32 ori_w;
-               u32 ori_h;
-
-               dst_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
-                                        V4L2_BUF_TYPE_VIDEO_CAPTURE);
-               ori_w = ctx->out_q.w;
-               ori_h = ctx->out_q.h;
-
-               ctx->hdr_parsed = s5p_jpeg_parse_hdr(&ctx->out_q,
-                    (unsigned long)vb2_plane_vaddr(vb, 0),
-                    min((unsigned long)ctx->out_q.size,
-                        vb2_get_plane_payload(vb, 0)), ctx);
-               if (!ctx->hdr_parsed) {
-                       vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
-                       return;
-               }
-
-               /*
-                * If there is a resolution change event, only update capture
-                * queue when it is not streaming. Otherwise, update it in
-                * STREAMOFF. See s5p_jpeg_stop_streaming for detail.
-                */
-               if (ctx->out_q.w != ori_w || ctx->out_q.h != ori_h) {
-                       v4l2_event_queue_fh(&ctx->fh, &ev_src_ch);
-                       if (vb2_is_streaming(dst_vq))
-                               ctx->state = JPEGCTX_RESOLUTION_CHANGE;
-                       else
-                               s5p_jpeg_set_capture_queue_data(ctx);
-               }
-       }
-
-       v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
-}
-
-static int s5p_jpeg_start_streaming(struct vb2_queue *q, unsigned int count)
-{
-       struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(q);
-
-       return pm_runtime_resume_and_get(ctx->jpeg->dev);
-}
-
-static void s5p_jpeg_stop_streaming(struct vb2_queue *q)
-{
-       struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(q);
-
-       /*
-        * STREAMOFF is an acknowledgment for resolution change event.
-        * Before STREAMOFF, we still have to return the old resolution and
-        * subsampling. Update capture queue when the stream is off.
-        */
-       if (ctx->state == JPEGCTX_RESOLUTION_CHANGE &&
-           q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-               s5p_jpeg_set_capture_queue_data(ctx);
-               ctx->state = JPEGCTX_RUNNING;
-       }
-
-       pm_runtime_put(ctx->jpeg->dev);
-}
-
-static const struct vb2_ops s5p_jpeg_qops = {
-       .queue_setup            = s5p_jpeg_queue_setup,
-       .buf_prepare            = s5p_jpeg_buf_prepare,
-       .buf_queue              = s5p_jpeg_buf_queue,
-       .wait_prepare           = vb2_ops_wait_prepare,
-       .wait_finish            = vb2_ops_wait_finish,
-       .start_streaming        = s5p_jpeg_start_streaming,
-       .stop_streaming         = s5p_jpeg_stop_streaming,
-};
-
-static int queue_init(void *priv, struct vb2_queue *src_vq,
-                     struct vb2_queue *dst_vq)
-{
-       struct s5p_jpeg_ctx *ctx = priv;
-       int ret;
-
-       src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
-       src_vq->io_modes = VB2_MMAP | VB2_USERPTR;
-       src_vq->drv_priv = ctx;
-       src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
-       src_vq->ops = &s5p_jpeg_qops;
-       src_vq->mem_ops = &vb2_dma_contig_memops;
-       src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
-       src_vq->lock = &ctx->jpeg->lock;
-       src_vq->dev = ctx->jpeg->dev;
-
-       ret = vb2_queue_init(src_vq);
-       if (ret)
-               return ret;
-
-       dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-       dst_vq->io_modes = VB2_MMAP | VB2_USERPTR;
-       dst_vq->drv_priv = ctx;
-       dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
-       dst_vq->ops = &s5p_jpeg_qops;
-       dst_vq->mem_ops = &vb2_dma_contig_memops;
-       dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
-       dst_vq->lock = &ctx->jpeg->lock;
-       dst_vq->dev = ctx->jpeg->dev;
-
-       return vb2_queue_init(dst_vq);
-}
-
-/*
- * ============================================================================
- * ISR
- * ============================================================================
- */
-
-static irqreturn_t s5p_jpeg_irq(int irq, void *dev_id)
-{
-       struct s5p_jpeg *jpeg = dev_id;
-       struct s5p_jpeg_ctx *curr_ctx;
-       struct vb2_v4l2_buffer *src_buf, *dst_buf;
-       unsigned long payload_size = 0;
-       enum vb2_buffer_state state = VB2_BUF_STATE_DONE;
-       bool enc_jpeg_too_large = false;
-       bool timer_elapsed = false;
-       bool op_completed = false;
-
-       spin_lock(&jpeg->slock);
-
-       curr_ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev);
-
-       src_buf = v4l2_m2m_src_buf_remove(curr_ctx->fh.m2m_ctx);
-       dst_buf = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx);
-
-       if (curr_ctx->mode == S5P_JPEG_ENCODE)
-               enc_jpeg_too_large = s5p_jpeg_enc_stream_stat(jpeg->regs);
-       timer_elapsed = s5p_jpeg_timer_stat(jpeg->regs);
-       op_completed = s5p_jpeg_result_stat_ok(jpeg->regs);
-       if (curr_ctx->mode == S5P_JPEG_DECODE)
-               op_completed = op_completed &&
-                                       s5p_jpeg_stream_stat_ok(jpeg->regs);
-
-       if (enc_jpeg_too_large) {
-               state = VB2_BUF_STATE_ERROR;
-               s5p_jpeg_clear_enc_stream_stat(jpeg->regs);
-       } else if (timer_elapsed) {
-               state = VB2_BUF_STATE_ERROR;
-               s5p_jpeg_clear_timer_stat(jpeg->regs);
-       } else if (!op_completed) {
-               state = VB2_BUF_STATE_ERROR;
-       } else {
-               payload_size = s5p_jpeg_compressed_size(jpeg->regs);
-       }
-
-       dst_buf->timecode = src_buf->timecode;
-       dst_buf->vb2_buf.timestamp = src_buf->vb2_buf.timestamp;
-       dst_buf->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
-       dst_buf->flags |=
-               src_buf->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
-
-       v4l2_m2m_buf_done(src_buf, state);
-       if (curr_ctx->mode == S5P_JPEG_ENCODE)
-               vb2_set_plane_payload(&dst_buf->vb2_buf, 0, payload_size);
-       v4l2_m2m_buf_done(dst_buf, state);
-
-       curr_ctx->subsampling = s5p_jpeg_get_subsampling_mode(jpeg->regs);
-       spin_unlock(&jpeg->slock);
-
-       s5p_jpeg_clear_int(jpeg->regs);
-
-       v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->fh.m2m_ctx);
-       return IRQ_HANDLED;
-}
-
-static irqreturn_t exynos4_jpeg_irq(int irq, void *priv)
-{
-       unsigned int int_status;
-       struct vb2_v4l2_buffer *src_vb, *dst_vb;
-       struct s5p_jpeg *jpeg = priv;
-       struct s5p_jpeg_ctx *curr_ctx;
-       unsigned long payload_size = 0;
-
-       spin_lock(&jpeg->slock);
-
-       exynos4_jpeg_set_sys_int_enable(jpeg->regs, 0);
-
-       curr_ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev);
-
-       src_vb = v4l2_m2m_src_buf_remove(curr_ctx->fh.m2m_ctx);
-       dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx);
-
-       int_status = exynos4_jpeg_get_int_status(jpeg->regs);
-
-       if (int_status) {
-               switch (int_status & 0x1f) {
-               case 0x1:
-                       jpeg->irq_ret = ERR_PROT;
-                       break;
-               case 0x2:
-                       jpeg->irq_ret = OK_ENC_OR_DEC;
-                       break;
-               case 0x4:
-                       jpeg->irq_ret = ERR_DEC_INVALID_FORMAT;
-                       break;
-               case 0x8:
-                       jpeg->irq_ret = ERR_MULTI_SCAN;
-                       break;
-               case 0x10:
-                       jpeg->irq_ret = ERR_FRAME;
-                       break;
-               default:
-                       jpeg->irq_ret = ERR_UNKNOWN;
-                       break;
-               }
-       } else {
-               jpeg->irq_ret = ERR_UNKNOWN;
-       }
-
-       if (jpeg->irq_ret == OK_ENC_OR_DEC) {
-               if (curr_ctx->mode == S5P_JPEG_ENCODE) {
-                       payload_size = exynos4_jpeg_get_stream_size(jpeg->regs);
-                       vb2_set_plane_payload(&dst_vb->vb2_buf,
-                                       0, payload_size);
-               }
-               v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE);
-               v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_DONE);
-       } else {
-               v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_ERROR);
-               v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_ERROR);
-       }
-
-       if (jpeg->variant->version == SJPEG_EXYNOS4)
-               curr_ctx->subsampling = exynos4_jpeg_get_frame_fmt(jpeg->regs);
-
-       exynos4_jpeg_set_enc_dec_mode(jpeg->regs, S5P_JPEG_DISABLE);
-
-       spin_unlock(&jpeg->slock);
-
-       v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->fh.m2m_ctx);
-       return IRQ_HANDLED;
-}
-
-static irqreturn_t exynos3250_jpeg_irq(int irq, void *dev_id)
-{
-       struct s5p_jpeg *jpeg = dev_id;
-       struct s5p_jpeg_ctx *curr_ctx;
-       struct vb2_v4l2_buffer *src_buf, *dst_buf;
-       unsigned long payload_size = 0;
-       enum vb2_buffer_state state = VB2_BUF_STATE_DONE;
-       bool interrupt_timeout = false;
-       bool stream_error = false;
-       u32 irq_status;
-
-       spin_lock(&jpeg->slock);
-
-       irq_status = exynos3250_jpeg_get_timer_status(jpeg->regs);
-       if (irq_status & EXYNOS3250_TIMER_INT_STAT) {
-               exynos3250_jpeg_clear_timer_status(jpeg->regs);
-               interrupt_timeout = true;
-               dev_err(jpeg->dev, "Interrupt timeout occurred.\n");
-       }
-
-       irq_status = exynos3250_jpeg_get_int_status(jpeg->regs);
-       exynos3250_jpeg_clear_int_status(jpeg->regs, irq_status);
-
-       jpeg->irq_status |= irq_status;
-
-       if (jpeg->variant->version == SJPEG_EXYNOS5420 &&
-           irq_status & EXYNOS3250_STREAM_STAT) {
-               stream_error = true;
-               dev_err(jpeg->dev, "Syntax error or unrecoverable error occurred.\n");
-       }
-
-       curr_ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev);
-
-       if (!curr_ctx)
-               goto exit_unlock;
-
-       if ((irq_status & EXYNOS3250_HEADER_STAT) &&
-           (curr_ctx->mode == S5P_JPEG_DECODE)) {
-               exynos3250_jpeg_rstart(jpeg->regs);
-               goto exit_unlock;
-       }
-
-       if (jpeg->irq_status & (EXYNOS3250_JPEG_DONE |
-                               EXYNOS3250_WDMA_DONE |
-                               EXYNOS3250_RDMA_DONE |
-                               EXYNOS3250_RESULT_STAT))
-               payload_size = exynos3250_jpeg_compressed_size(jpeg->regs);
-       else if (interrupt_timeout || stream_error)
-               state = VB2_BUF_STATE_ERROR;
-       else
-               goto exit_unlock;
-
-       src_buf = v4l2_m2m_src_buf_remove(curr_ctx->fh.m2m_ctx);
-       dst_buf = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx);
-
-       dst_buf->timecode = src_buf->timecode;
-       dst_buf->vb2_buf.timestamp = src_buf->vb2_buf.timestamp;
-
-       v4l2_m2m_buf_done(src_buf, state);
-       if (curr_ctx->mode == S5P_JPEG_ENCODE)
-               vb2_set_plane_payload(&dst_buf->vb2_buf, 0, payload_size);
-       v4l2_m2m_buf_done(dst_buf, state);
-
-       curr_ctx->subsampling =
-                       exynos3250_jpeg_get_subsampling_mode(jpeg->regs);
-
-       spin_unlock(&jpeg->slock);
-
-       v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->fh.m2m_ctx);
-       return IRQ_HANDLED;
-
-exit_unlock:
-       spin_unlock(&jpeg->slock);
-       return IRQ_HANDLED;
-}
-
-static void *jpeg_get_drv_data(struct device *dev);
-
-/*
- * ============================================================================
- * Driver basic infrastructure
- * ============================================================================
- */
-
-static int s5p_jpeg_probe(struct platform_device *pdev)
-{
-       struct s5p_jpeg *jpeg;
-       int i, ret;
-
-       /* JPEG IP abstraction struct */
-       jpeg = devm_kzalloc(&pdev->dev, sizeof(struct s5p_jpeg), GFP_KERNEL);
-       if (!jpeg)
-               return -ENOMEM;
-
-       jpeg->variant = jpeg_get_drv_data(&pdev->dev);
-       if (!jpeg->variant)
-               return -ENODEV;
-
-       mutex_init(&jpeg->lock);
-       spin_lock_init(&jpeg->slock);
-       jpeg->dev = &pdev->dev;
-
-       /* memory-mapped registers */
-       jpeg->regs = devm_platform_ioremap_resource(pdev, 0);
-       if (IS_ERR(jpeg->regs))
-               return PTR_ERR(jpeg->regs);
-
-       /* interrupt service routine registration */
-       jpeg->irq = ret = platform_get_irq(pdev, 0);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "cannot find IRQ\n");
-               return ret;
-       }
-
-       ret = devm_request_irq(&pdev->dev, jpeg->irq, jpeg->variant->jpeg_irq,
-                               0, dev_name(&pdev->dev), jpeg);
-       if (ret) {
-               dev_err(&pdev->dev, "cannot claim IRQ %d\n", jpeg->irq);
-               return ret;
-       }
-
-       /* clocks */
-       for (i = 0; i < jpeg->variant->num_clocks; i++) {
-               jpeg->clocks[i] = devm_clk_get(&pdev->dev,
-                                             jpeg->variant->clk_names[i]);
-               if (IS_ERR(jpeg->clocks[i])) {
-                       dev_err(&pdev->dev, "failed to get clock: %s\n",
-                               jpeg->variant->clk_names[i]);
-                       return PTR_ERR(jpeg->clocks[i]);
-               }
-       }
-
-       /* v4l2 device */
-       ret = v4l2_device_register(&pdev->dev, &jpeg->v4l2_dev);
-       if (ret) {
-               dev_err(&pdev->dev, "Failed to register v4l2 device\n");
-               return ret;
-       }
-
-       /* mem2mem device */
-       jpeg->m2m_dev = v4l2_m2m_init(jpeg->variant->m2m_ops);
-       if (IS_ERR(jpeg->m2m_dev)) {
-               v4l2_err(&jpeg->v4l2_dev, "Failed to init mem2mem device\n");
-               ret = PTR_ERR(jpeg->m2m_dev);
-               goto device_register_rollback;
-       }
-
-       vb2_dma_contig_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32));
-
-       /* JPEG encoder /dev/videoX node */
-       jpeg->vfd_encoder = video_device_alloc();
-       if (!jpeg->vfd_encoder) {
-               v4l2_err(&jpeg->v4l2_dev, "Failed to allocate video device\n");
-               ret = -ENOMEM;
-               goto m2m_init_rollback;
-       }
-       snprintf(jpeg->vfd_encoder->name, sizeof(jpeg->vfd_encoder->name),
-                               "%s-enc", S5P_JPEG_M2M_NAME);
-       jpeg->vfd_encoder->fops         = &s5p_jpeg_fops;
-       jpeg->vfd_encoder->ioctl_ops    = &s5p_jpeg_ioctl_ops;
-       jpeg->vfd_encoder->minor        = -1;
-       jpeg->vfd_encoder->release      = video_device_release;
-       jpeg->vfd_encoder->lock         = &jpeg->lock;
-       jpeg->vfd_encoder->v4l2_dev     = &jpeg->v4l2_dev;
-       jpeg->vfd_encoder->vfl_dir      = VFL_DIR_M2M;
-       jpeg->vfd_encoder->device_caps  = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M;
-
-       ret = video_register_device(jpeg->vfd_encoder, VFL_TYPE_VIDEO, -1);
-       if (ret) {
-               v4l2_err(&jpeg->v4l2_dev, "Failed to register video device\n");
-               video_device_release(jpeg->vfd_encoder);
-               goto m2m_init_rollback;
-       }
-
-       video_set_drvdata(jpeg->vfd_encoder, jpeg);
-       v4l2_info(&jpeg->v4l2_dev,
-                 "encoder device registered as /dev/video%d\n",
-                 jpeg->vfd_encoder->num);
-
-       /* JPEG decoder /dev/videoX node */
-       jpeg->vfd_decoder = video_device_alloc();
-       if (!jpeg->vfd_decoder) {
-               v4l2_err(&jpeg->v4l2_dev, "Failed to allocate video device\n");
-               ret = -ENOMEM;
-               goto enc_vdev_register_rollback;
-       }
-       snprintf(jpeg->vfd_decoder->name, sizeof(jpeg->vfd_decoder->name),
-                               "%s-dec", S5P_JPEG_M2M_NAME);
-       jpeg->vfd_decoder->fops         = &s5p_jpeg_fops;
-       jpeg->vfd_decoder->ioctl_ops    = &s5p_jpeg_ioctl_ops;
-       jpeg->vfd_decoder->minor        = -1;
-       jpeg->vfd_decoder->release      = video_device_release;
-       jpeg->vfd_decoder->lock         = &jpeg->lock;
-       jpeg->vfd_decoder->v4l2_dev     = &jpeg->v4l2_dev;
-       jpeg->vfd_decoder->vfl_dir      = VFL_DIR_M2M;
-       jpeg->vfd_decoder->device_caps  = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M;
-
-       ret = video_register_device(jpeg->vfd_decoder, VFL_TYPE_VIDEO, -1);
-       if (ret) {
-               v4l2_err(&jpeg->v4l2_dev, "Failed to register video device\n");
-               video_device_release(jpeg->vfd_decoder);
-               goto enc_vdev_register_rollback;
-       }
-
-       video_set_drvdata(jpeg->vfd_decoder, jpeg);
-       v4l2_info(&jpeg->v4l2_dev,
-                 "decoder device registered as /dev/video%d\n",
-                 jpeg->vfd_decoder->num);
-
-       /* final statements & power management */
-       platform_set_drvdata(pdev, jpeg);
-
-       pm_runtime_enable(&pdev->dev);
-
-       v4l2_info(&jpeg->v4l2_dev, "Samsung S5P JPEG codec\n");
-
-       return 0;
-
-enc_vdev_register_rollback:
-       video_unregister_device(jpeg->vfd_encoder);
-
-m2m_init_rollback:
-       v4l2_m2m_release(jpeg->m2m_dev);
-
-device_register_rollback:
-       v4l2_device_unregister(&jpeg->v4l2_dev);
-
-       return ret;
-}
-
-static int s5p_jpeg_remove(struct platform_device *pdev)
-{
-       struct s5p_jpeg *jpeg = platform_get_drvdata(pdev);
-       int i;
-
-       pm_runtime_disable(jpeg->dev);
-
-       video_unregister_device(jpeg->vfd_decoder);
-       video_unregister_device(jpeg->vfd_encoder);
-       vb2_dma_contig_clear_max_seg_size(&pdev->dev);
-       v4l2_m2m_release(jpeg->m2m_dev);
-       v4l2_device_unregister(&jpeg->v4l2_dev);
-
-       if (!pm_runtime_status_suspended(&pdev->dev)) {
-               for (i = jpeg->variant->num_clocks - 1; i >= 0; i--)
-                       clk_disable_unprepare(jpeg->clocks[i]);
-       }
-
-       return 0;
-}
-
-#ifdef CONFIG_PM
-static int s5p_jpeg_runtime_suspend(struct device *dev)
-{
-       struct s5p_jpeg *jpeg = dev_get_drvdata(dev);
-       int i;
-
-       for (i = jpeg->variant->num_clocks - 1; i >= 0; i--)
-               clk_disable_unprepare(jpeg->clocks[i]);
-
-       return 0;
-}
-
-static int s5p_jpeg_runtime_resume(struct device *dev)
-{
-       struct s5p_jpeg *jpeg = dev_get_drvdata(dev);
-       unsigned long flags;
-       int i, ret;
-
-       for (i = 0; i < jpeg->variant->num_clocks; i++) {
-               ret = clk_prepare_enable(jpeg->clocks[i]);
-               if (ret) {
-                       while (--i >= 0)
-                               clk_disable_unprepare(jpeg->clocks[i]);
-                       return ret;
-               }
-       }
-
-       spin_lock_irqsave(&jpeg->slock, flags);
-
-       /*
-        * JPEG IP allows storing two Huffman tables for each component.
-        * We fill table 0 for each component and do this here only
-        * for S5PC210 and Exynos3250 SoCs. Exynos4x12 and Exynos542x SoC
-        * require programming their Huffman tables each time the encoding
-        * process is initialized, and thus it is accomplished in the
-        * device_run callback of m2m_ops.
-        */
-       if (!jpeg->variant->htbl_reinit) {
-               s5p_jpeg_set_hdctbl(jpeg->regs);
-               s5p_jpeg_set_hdctblg(jpeg->regs);
-               s5p_jpeg_set_hactbl(jpeg->regs);
-               s5p_jpeg_set_hactblg(jpeg->regs);
-       }
-
-       spin_unlock_irqrestore(&jpeg->slock, flags);
-
-       return 0;
-}
-#endif /* CONFIG_PM */
-
-static const struct dev_pm_ops s5p_jpeg_pm_ops = {
-       SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
-                               pm_runtime_force_resume)
-       SET_RUNTIME_PM_OPS(s5p_jpeg_runtime_suspend, s5p_jpeg_runtime_resume,
-                          NULL)
-};
-
-static struct s5p_jpeg_variant s5p_jpeg_drvdata = {
-       .version        = SJPEG_S5P,
-       .jpeg_irq       = s5p_jpeg_irq,
-       .m2m_ops        = &s5p_jpeg_m2m_ops,
-       .fmt_ver_flag   = SJPEG_FMT_FLAG_S5P,
-       .clk_names      = {"jpeg"},
-       .num_clocks     = 1,
-};
-
-static struct s5p_jpeg_variant exynos3250_jpeg_drvdata = {
-       .version        = SJPEG_EXYNOS3250,
-       .jpeg_irq       = exynos3250_jpeg_irq,
-       .m2m_ops        = &exynos3250_jpeg_m2m_ops,
-       .fmt_ver_flag   = SJPEG_FMT_FLAG_EXYNOS3250,
-       .hw3250_compat  = 1,
-       .clk_names      = {"jpeg", "sclk"},
-       .num_clocks     = 2,
-};
-
-static struct s5p_jpeg_variant exynos4_jpeg_drvdata = {
-       .version        = SJPEG_EXYNOS4,
-       .jpeg_irq       = exynos4_jpeg_irq,
-       .m2m_ops        = &exynos4_jpeg_m2m_ops,
-       .fmt_ver_flag   = SJPEG_FMT_FLAG_EXYNOS4,
-       .htbl_reinit    = 1,
-       .clk_names      = {"jpeg"},
-       .num_clocks     = 1,
-       .hw_ex4_compat  = 1,
-};
-
-static struct s5p_jpeg_variant exynos5420_jpeg_drvdata = {
-       .version        = SJPEG_EXYNOS5420,
-       .jpeg_irq       = exynos3250_jpeg_irq,          /* intentionally 3250 */
-       .m2m_ops        = &exynos3250_jpeg_m2m_ops,     /* intentionally 3250 */
-       .fmt_ver_flag   = SJPEG_FMT_FLAG_EXYNOS3250,    /* intentionally 3250 */
-       .hw3250_compat  = 1,
-       .htbl_reinit    = 1,
-       .clk_names      = {"jpeg"},
-       .num_clocks     = 1,
-};
-
-static struct s5p_jpeg_variant exynos5433_jpeg_drvdata = {
-       .version        = SJPEG_EXYNOS5433,
-       .jpeg_irq       = exynos4_jpeg_irq,
-       .m2m_ops        = &exynos4_jpeg_m2m_ops,
-       .fmt_ver_flag   = SJPEG_FMT_FLAG_EXYNOS4,
-       .htbl_reinit    = 1,
-       .clk_names      = {"pclk", "aclk", "aclk_xiu", "sclk"},
-       .num_clocks     = 4,
-       .hw_ex4_compat  = 1,
-};
-
-static const struct of_device_id samsung_jpeg_match[] = {
-       {
-               .compatible = "samsung,s5pv210-jpeg",
-               .data = &s5p_jpeg_drvdata,
-       }, {
-               .compatible = "samsung,exynos3250-jpeg",
-               .data = &exynos3250_jpeg_drvdata,
-       }, {
-               .compatible = "samsung,exynos4210-jpeg",
-               .data = &exynos4_jpeg_drvdata,
-       }, {
-               .compatible = "samsung,exynos4212-jpeg",
-               .data = &exynos4_jpeg_drvdata,
-       }, {
-               .compatible = "samsung,exynos5420-jpeg",
-               .data = &exynos5420_jpeg_drvdata,
-       }, {
-               .compatible = "samsung,exynos5433-jpeg",
-               .data = &exynos5433_jpeg_drvdata,
-       },
-       {},
-};
-
-MODULE_DEVICE_TABLE(of, samsung_jpeg_match);
-
-static void *jpeg_get_drv_data(struct device *dev)
-{
-       struct s5p_jpeg_variant *driver_data = NULL;
-       const struct of_device_id *match;
-
-       if (!IS_ENABLED(CONFIG_OF) || !dev->of_node)
-               return &s5p_jpeg_drvdata;
-
-       match = of_match_node(samsung_jpeg_match, dev->of_node);
-
-       if (match)
-               driver_data = (struct s5p_jpeg_variant *)match->data;
-
-       return driver_data;
-}
-
-static struct platform_driver s5p_jpeg_driver = {
-       .probe = s5p_jpeg_probe,
-       .remove = s5p_jpeg_remove,
-       .driver = {
-               .of_match_table = of_match_ptr(samsung_jpeg_match),
-               .name           = S5P_JPEG_M2M_NAME,
-               .pm             = &s5p_jpeg_pm_ops,
-       },
-};
-
-module_platform_driver(s5p_jpeg_driver);
-
-MODULE_AUTHOR("Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>");
-MODULE_AUTHOR("Jacek Anaszewski <j.anaszewski@samsung.com>");
-MODULE_DESCRIPTION("Samsung JPEG codec driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.h b/drivers/media/platform/s5p-jpeg/jpeg-core.h
deleted file mode 100644 (file)
index 4a5fb1b..0000000
+++ /dev/null
@@ -1,267 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/* linux/drivers/media/platform/s5p-jpeg/jpeg-core.h
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com
- *
- * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
- */
-
-#ifndef JPEG_CORE_H_
-#define JPEG_CORE_H_
-
-#include <linux/interrupt.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-fh.h>
-#include <media/v4l2-ctrls.h>
-
-#define S5P_JPEG_M2M_NAME              "s5p-jpeg"
-
-#define JPEG_MAX_CLOCKS                        4
-
-/* JPEG compression quality setting */
-#define S5P_JPEG_COMPR_QUAL_BEST       0
-#define S5P_JPEG_COMPR_QUAL_WORST      3
-
-/* JPEG RGB to YCbCr conversion matrix coefficients */
-#define S5P_JPEG_COEF11                        0x4d
-#define S5P_JPEG_COEF12                        0x97
-#define S5P_JPEG_COEF13                        0x1e
-#define S5P_JPEG_COEF21                        0x2c
-#define S5P_JPEG_COEF22                        0x57
-#define S5P_JPEG_COEF23                        0x83
-#define S5P_JPEG_COEF31                        0x83
-#define S5P_JPEG_COEF32                        0x6e
-#define S5P_JPEG_COEF33                        0x13
-
-#define EXYNOS3250_IRQ_TIMEOUT         0x10000000
-
-/* a selection of JPEG markers */
-#define JPEG_MARKER_TEM                                0x01
-#define JPEG_MARKER_SOF0                               0xc0
-#define JPEG_MARKER_DHT                                0xc4
-#define JPEG_MARKER_RST                                0xd0
-#define JPEG_MARKER_SOI                                0xd8
-#define JPEG_MARKER_EOI                                0xd9
-#define        JPEG_MARKER_SOS                         0xda
-#define JPEG_MARKER_DQT                                0xdb
-#define JPEG_MARKER_DHP                                0xde
-
-/* Flags that indicate a format can be used for capture/output */
-#define SJPEG_FMT_FLAG_ENC_CAPTURE     (1 << 0)
-#define SJPEG_FMT_FLAG_ENC_OUTPUT      (1 << 1)
-#define SJPEG_FMT_FLAG_DEC_CAPTURE     (1 << 2)
-#define SJPEG_FMT_FLAG_DEC_OUTPUT      (1 << 3)
-#define SJPEG_FMT_FLAG_S5P             (1 << 4)
-#define SJPEG_FMT_FLAG_EXYNOS3250      (1 << 5)
-#define SJPEG_FMT_FLAG_EXYNOS4         (1 << 6)
-#define SJPEG_FMT_RGB                  (1 << 7)
-#define SJPEG_FMT_NON_RGB              (1 << 8)
-
-#define S5P_JPEG_ENCODE                0
-#define S5P_JPEG_DECODE                1
-#define S5P_JPEG_DISABLE       -1
-
-#define FMT_TYPE_OUTPUT                0
-#define FMT_TYPE_CAPTURE       1
-
-#define SJPEG_SUBSAMPLING_444  0x11
-#define SJPEG_SUBSAMPLING_422  0x21
-#define SJPEG_SUBSAMPLING_420  0x22
-
-#define S5P_JPEG_MAX_MARKER    4
-
-/* Version numbers */
-enum sjpeg_version {
-       SJPEG_S5P,
-       SJPEG_EXYNOS3250,
-       SJPEG_EXYNOS4,
-       SJPEG_EXYNOS5420,
-       SJPEG_EXYNOS5433,
-};
-
-enum exynos4_jpeg_result {
-       OK_ENC_OR_DEC,
-       ERR_PROT,
-       ERR_DEC_INVALID_FORMAT,
-       ERR_MULTI_SCAN,
-       ERR_FRAME,
-       ERR_UNKNOWN,
-};
-
-enum  exynos4_jpeg_img_quality_level {
-       QUALITY_LEVEL_1 = 0,    /* high */
-       QUALITY_LEVEL_2,
-       QUALITY_LEVEL_3,
-       QUALITY_LEVEL_4,        /* low */
-};
-
-enum s5p_jpeg_ctx_state {
-       JPEGCTX_RUNNING = 0,
-       JPEGCTX_RESOLUTION_CHANGE,
-};
-
-/**
- * struct s5p_jpeg - JPEG IP abstraction
- * @lock:              the mutex protecting this structure
- * @slock:             spinlock protecting the device contexts
- * @v4l2_dev:          v4l2 device for mem2mem mode
- * @vfd_encoder:       video device node for encoder mem2mem mode
- * @vfd_decoder:       video device node for decoder mem2mem mode
- * @m2m_dev:           v4l2 mem2mem device data
- * @regs:              JPEG IP registers mapping
- * @irq:               JPEG IP irq
- * @irq_ret:           JPEG IP irq result value
- * @clocks:            JPEG IP clock(s)
- * @dev:               JPEG IP struct device
- * @variant:           driver variant to be used
- * @irq_status:                interrupt flags set during single encode/decode
- *                     operation
- */
-struct s5p_jpeg {
-       struct mutex            lock;
-       spinlock_t              slock;
-
-       struct v4l2_device      v4l2_dev;
-       struct video_device     *vfd_encoder;
-       struct video_device     *vfd_decoder;
-       struct v4l2_m2m_dev     *m2m_dev;
-
-       void __iomem            *regs;
-       unsigned int            irq;
-       enum exynos4_jpeg_result irq_ret;
-       struct clk              *clocks[JPEG_MAX_CLOCKS];
-       struct device           *dev;
-       struct s5p_jpeg_variant *variant;
-       u32                     irq_status;
-};
-
-struct s5p_jpeg_variant {
-       unsigned int            version;
-       unsigned int            fmt_ver_flag;
-       unsigned int            hw3250_compat:1;
-       unsigned int            htbl_reinit:1;
-       unsigned int            hw_ex4_compat:1;
-       const struct v4l2_m2m_ops *m2m_ops;
-       irqreturn_t             (*jpeg_irq)(int irq, void *priv);
-       const char              *clk_names[JPEG_MAX_CLOCKS];
-       int                     num_clocks;
-};
-
-/**
- * struct s5p_jpeg_fmt - driver's internal color format data
- * @fourcc:    the fourcc code, 0 if not applicable
- * @depth:     number of bits per pixel
- * @colplanes: number of color planes (1 for packed formats)
- * @memplanes: number of memory planes (1 for packed formats)
- * @h_align:   horizontal alignment order (align to 2^h_align)
- * @v_align:   vertical alignment order (align to 2^v_align)
- * @subsampling:subsampling of a raw format or a JPEG
- * @flags:     flags describing format applicability
- */
-struct s5p_jpeg_fmt {
-       u32     fourcc;
-       int     depth;
-       int     colplanes;
-       int     memplanes;
-       int     h_align;
-       int     v_align;
-       int     subsampling;
-       u32     flags;
-};
-
-/**
- * struct s5p_jpeg_marker - collection of markers from jpeg header
- * @marker:    markers' positions relative to the buffer beginning
- * @len:       markers' payload lengths (without length field)
- * @n:         number of markers in collection
- */
-struct s5p_jpeg_marker {
-       u32     marker[S5P_JPEG_MAX_MARKER];
-       u32     len[S5P_JPEG_MAX_MARKER];
-       u32     n;
-};
-
-/**
- * struct s5p_jpeg_q_data - parameters of one queue
- * @fmt:       driver-specific format of this queue
- * @w:         image width
- * @h:         image height
- * @sos:       JPEG_MARKER_SOS's position relative to the buffer beginning
- * @dht:       JPEG_MARKER_DHT' positions relative to the buffer beginning
- * @dqt:       JPEG_MARKER_DQT' positions relative to the buffer beginning
- * @sof:       JPEG_MARKER_SOF0's position relative to the buffer beginning
- * @sof_len:   JPEG_MARKER_SOF0's payload length (without length field itself)
- * @size:      image buffer size in bytes
- */
-struct s5p_jpeg_q_data {
-       struct s5p_jpeg_fmt     *fmt;
-       u32                     w;
-       u32                     h;
-       u32                     sos;
-       struct s5p_jpeg_marker  dht;
-       struct s5p_jpeg_marker  dqt;
-       u32                     sof;
-       u32                     sof_len;
-       u32                     size;
-};
-
-/**
- * struct s5p_jpeg_ctx - the device context data
- * @jpeg:              JPEG IP device for this context
- * @mode:              compression (encode) operation or decompression (decode)
- * @compr_quality:     destination image quality in compression (encode) mode
- * @restart_interval:  JPEG restart interval for JPEG encoding
- * @subsampling:       subsampling of a raw format or a JPEG
- * @out_q:             source (output) queue information
- * @cap_q:             destination (capture) queue queue information
- * @scale_factor:      scale factor for JPEG decoding
- * @crop_rect:         a rectangle representing crop area of the output buffer
- * @fh:                        V4L2 file handle
- * @hdr_parsed:                set if header has been parsed during decompression
- * @crop_altered:      set if crop rectangle has been altered by the user space
- * @ctrl_handler:      controls handler
- * @state:             state of the context
- */
-struct s5p_jpeg_ctx {
-       struct s5p_jpeg         *jpeg;
-       unsigned int            mode;
-       unsigned short          compr_quality;
-       unsigned short          restart_interval;
-       unsigned short          subsampling;
-       struct s5p_jpeg_q_data  out_q;
-       struct s5p_jpeg_q_data  cap_q;
-       unsigned int            scale_factor;
-       struct v4l2_rect        crop_rect;
-       struct v4l2_fh          fh;
-       bool                    hdr_parsed;
-       bool                    crop_altered;
-       struct v4l2_ctrl_handler ctrl_handler;
-       enum s5p_jpeg_ctx_state state;
-};
-
-/**
- * struct s5p_jpeg_buffer - description of memory containing input JPEG data
- * @size:      buffer size
- * @curr:      current position in the buffer
- * @data:      pointer to the data
- */
-struct s5p_jpeg_buffer {
-       unsigned long size;
-       unsigned long curr;
-       unsigned long data;
-};
-
-/**
- * struct s5p_jpeg_addr - JPEG converter physical address set for DMA
- * @y:   luminance plane physical address
- * @cb:  Cb plane physical address
- * @cr:  Cr plane physical address
- */
-struct s5p_jpeg_addr {
-       u32     y;
-       u32     cb;
-       u32     cr;
-};
-
-#endif /* JPEG_CORE_H */
diff --git a/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos3250.c b/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos3250.c
deleted file mode 100644 (file)
index 637a510..0000000
+++ /dev/null
@@ -1,486 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/* linux/drivers/media/platform/exynos3250-jpeg/jpeg-hw.h
- *
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com
- *
- * Author: Jacek Anaszewski <j.anaszewski@samsung.com>
- */
-
-#include <linux/io.h>
-#include <linux/videodev2.h>
-#include <linux/delay.h>
-
-#include "jpeg-core.h"
-#include "jpeg-regs.h"
-#include "jpeg-hw-exynos3250.h"
-
-void exynos3250_jpeg_reset(void __iomem *regs)
-{
-       u32 reg = 1;
-       int count = 1000;
-
-       writel(1, regs + EXYNOS3250_SW_RESET);
-       /* no other way but polling for when JPEG IP becomes operational */
-       while (reg != 0 && --count > 0) {
-               udelay(1);
-               cpu_relax();
-               reg = readl(regs + EXYNOS3250_SW_RESET);
-       }
-
-       reg = 0;
-       count = 1000;
-
-       while (reg != 1 && --count > 0) {
-               writel(1, regs + EXYNOS3250_JPGDRI);
-               udelay(1);
-               cpu_relax();
-               reg = readl(regs + EXYNOS3250_JPGDRI);
-       }
-
-       writel(0, regs + EXYNOS3250_JPGDRI);
-}
-
-void exynos3250_jpeg_poweron(void __iomem *regs)
-{
-       writel(EXYNOS3250_POWER_ON, regs + EXYNOS3250_JPGCLKCON);
-}
-
-void exynos3250_jpeg_set_dma_num(void __iomem *regs)
-{
-       writel(((EXYNOS3250_DMA_MO_COUNT << EXYNOS3250_WDMA_ISSUE_NUM_SHIFT) &
-                       EXYNOS3250_WDMA_ISSUE_NUM_MASK) |
-              ((EXYNOS3250_DMA_MO_COUNT << EXYNOS3250_RDMA_ISSUE_NUM_SHIFT) &
-                       EXYNOS3250_RDMA_ISSUE_NUM_MASK) |
-              ((EXYNOS3250_DMA_MO_COUNT << EXYNOS3250_ISSUE_GATHER_NUM_SHIFT) &
-                       EXYNOS3250_ISSUE_GATHER_NUM_MASK),
-               regs + EXYNOS3250_DMA_ISSUE_NUM);
-}
-
-void exynos3250_jpeg_clk_set(void __iomem *base)
-{
-       u32 reg;
-
-       reg = readl(base + EXYNOS3250_JPGCMOD) & ~EXYNOS3250_HALF_EN_MASK;
-
-       writel(reg | EXYNOS3250_HALF_EN, base + EXYNOS3250_JPGCMOD);
-}
-
-void exynos3250_jpeg_input_raw_fmt(void __iomem *regs, unsigned int fmt)
-{
-       u32 reg;
-
-       reg = readl(regs + EXYNOS3250_JPGCMOD) &
-                       EXYNOS3250_MODE_Y16_MASK;
-
-       switch (fmt) {
-       case V4L2_PIX_FMT_RGB32:
-               reg |= EXYNOS3250_MODE_SEL_ARGB8888;
-               break;
-       case V4L2_PIX_FMT_BGR32:
-               reg |= EXYNOS3250_MODE_SEL_ARGB8888 | EXYNOS3250_SRC_SWAP_RGB;
-               break;
-       case V4L2_PIX_FMT_RGB565:
-               reg |= EXYNOS3250_MODE_SEL_RGB565;
-               break;
-       case V4L2_PIX_FMT_RGB565X:
-               reg |= EXYNOS3250_MODE_SEL_RGB565 | EXYNOS3250_SRC_SWAP_RGB;
-               break;
-       case V4L2_PIX_FMT_YUYV:
-               reg |= EXYNOS3250_MODE_SEL_422_1P_LUM_CHR;
-               break;
-       case V4L2_PIX_FMT_YVYU:
-               reg |= EXYNOS3250_MODE_SEL_422_1P_LUM_CHR |
-                       EXYNOS3250_SRC_SWAP_UV;
-               break;
-       case V4L2_PIX_FMT_UYVY:
-               reg |= EXYNOS3250_MODE_SEL_422_1P_CHR_LUM;
-               break;
-       case V4L2_PIX_FMT_VYUY:
-               reg |= EXYNOS3250_MODE_SEL_422_1P_CHR_LUM |
-                       EXYNOS3250_SRC_SWAP_UV;
-               break;
-       case V4L2_PIX_FMT_NV12:
-               reg |= EXYNOS3250_MODE_SEL_420_2P | EXYNOS3250_SRC_NV12;
-               break;
-       case V4L2_PIX_FMT_NV21:
-               reg |= EXYNOS3250_MODE_SEL_420_2P | EXYNOS3250_SRC_NV21;
-               break;
-       case V4L2_PIX_FMT_YUV420:
-               reg |= EXYNOS3250_MODE_SEL_420_3P;
-               break;
-       default:
-               break;
-
-       }
-
-       writel(reg, regs + EXYNOS3250_JPGCMOD);
-}
-
-void exynos3250_jpeg_set_y16(void __iomem *regs, bool y16)
-{
-       u32 reg;
-
-       reg = readl(regs + EXYNOS3250_JPGCMOD);
-       if (y16)
-               reg |= EXYNOS3250_MODE_Y16;
-       else
-               reg &= ~EXYNOS3250_MODE_Y16_MASK;
-       writel(reg, regs + EXYNOS3250_JPGCMOD);
-}
-
-void exynos3250_jpeg_proc_mode(void __iomem *regs, unsigned int mode)
-{
-       u32 reg, m;
-
-       if (mode == S5P_JPEG_ENCODE)
-               m = EXYNOS3250_PROC_MODE_COMPR;
-       else
-               m = EXYNOS3250_PROC_MODE_DECOMPR;
-       reg = readl(regs + EXYNOS3250_JPGMOD);
-       reg &= ~EXYNOS3250_PROC_MODE_MASK;
-       reg |= m;
-       writel(reg, regs + EXYNOS3250_JPGMOD);
-}
-
-void exynos3250_jpeg_subsampling_mode(void __iomem *regs, unsigned int mode)
-{
-       u32 reg, m = 0;
-
-       switch (mode) {
-       case V4L2_JPEG_CHROMA_SUBSAMPLING_444:
-               m = EXYNOS3250_SUBSAMPLING_MODE_444;
-               break;
-       case V4L2_JPEG_CHROMA_SUBSAMPLING_422:
-               m = EXYNOS3250_SUBSAMPLING_MODE_422;
-               break;
-       case V4L2_JPEG_CHROMA_SUBSAMPLING_420:
-               m = EXYNOS3250_SUBSAMPLING_MODE_420;
-               break;
-       }
-
-       reg = readl(regs + EXYNOS3250_JPGMOD);
-       reg &= ~EXYNOS3250_SUBSAMPLING_MODE_MASK;
-       reg |= m;
-       writel(reg, regs + EXYNOS3250_JPGMOD);
-}
-
-unsigned int exynos3250_jpeg_get_subsampling_mode(void __iomem *regs)
-{
-       return readl(regs + EXYNOS3250_JPGMOD) &
-                               EXYNOS3250_SUBSAMPLING_MODE_MASK;
-}
-
-void exynos3250_jpeg_dri(void __iomem *regs, unsigned int dri)
-{
-       u32 reg;
-
-       reg = dri & EXYNOS3250_JPGDRI_MASK;
-       writel(reg, regs + EXYNOS3250_JPGDRI);
-}
-
-void exynos3250_jpeg_qtbl(void __iomem *regs, unsigned int t, unsigned int n)
-{
-       unsigned long reg;
-
-       reg = readl(regs + EXYNOS3250_QHTBL);
-       reg &= ~EXYNOS3250_QT_NUM_MASK(t);
-       reg |= (n << EXYNOS3250_QT_NUM_SHIFT(t)) &
-                                       EXYNOS3250_QT_NUM_MASK(t);
-       writel(reg, regs + EXYNOS3250_QHTBL);
-}
-
-void exynos3250_jpeg_htbl_ac(void __iomem *regs, unsigned int t)
-{
-       unsigned long reg;
-
-       reg = readl(regs + EXYNOS3250_QHTBL);
-       reg &= ~EXYNOS3250_HT_NUM_AC_MASK(t);
-       /* this driver uses table 0 for all color components */
-       reg |= (0 << EXYNOS3250_HT_NUM_AC_SHIFT(t)) &
-                                       EXYNOS3250_HT_NUM_AC_MASK(t);
-       writel(reg, regs + EXYNOS3250_QHTBL);
-}
-
-void exynos3250_jpeg_htbl_dc(void __iomem *regs, unsigned int t)
-{
-       unsigned long reg;
-
-       reg = readl(regs + EXYNOS3250_QHTBL);
-       reg &= ~EXYNOS3250_HT_NUM_DC_MASK(t);
-       /* this driver uses table 0 for all color components */
-       reg |= (0 << EXYNOS3250_HT_NUM_DC_SHIFT(t)) &
-                                       EXYNOS3250_HT_NUM_DC_MASK(t);
-       writel(reg, regs + EXYNOS3250_QHTBL);
-}
-
-void exynos3250_jpeg_set_y(void __iomem *regs, unsigned int y)
-{
-       u32 reg;
-
-       reg = y & EXYNOS3250_JPGY_MASK;
-       writel(reg, regs + EXYNOS3250_JPGY);
-}
-
-void exynos3250_jpeg_set_x(void __iomem *regs, unsigned int x)
-{
-       u32 reg;
-
-       reg = x & EXYNOS3250_JPGX_MASK;
-       writel(reg, regs + EXYNOS3250_JPGX);
-}
-
-#if 0  /* Currently unused */
-unsigned int exynos3250_jpeg_get_y(void __iomem *regs)
-{
-       return readl(regs + EXYNOS3250_JPGY);
-}
-
-unsigned int exynos3250_jpeg_get_x(void __iomem *regs)
-{
-       return readl(regs + EXYNOS3250_JPGX);
-}
-#endif
-
-void exynos3250_jpeg_interrupts_enable(void __iomem *regs)
-{
-       u32 reg;
-
-       reg = readl(regs + EXYNOS3250_JPGINTSE);
-       reg |= (EXYNOS3250_JPEG_DONE_EN |
-               EXYNOS3250_WDMA_DONE_EN |
-               EXYNOS3250_RDMA_DONE_EN |
-               EXYNOS3250_ENC_STREAM_INT_EN |
-               EXYNOS3250_CORE_DONE_EN |
-               EXYNOS3250_ERR_INT_EN |
-               EXYNOS3250_HEAD_INT_EN);
-       writel(reg, regs + EXYNOS3250_JPGINTSE);
-}
-
-void exynos3250_jpeg_enc_stream_bound(void __iomem *regs, unsigned int size)
-{
-       u32 reg;
-
-       reg = size & EXYNOS3250_ENC_STREAM_BOUND_MASK;
-       writel(reg, regs + EXYNOS3250_ENC_STREAM_BOUND);
-}
-
-void exynos3250_jpeg_output_raw_fmt(void __iomem *regs, unsigned int fmt)
-{
-       u32 reg;
-
-       switch (fmt) {
-       case V4L2_PIX_FMT_RGB32:
-               reg = EXYNOS3250_OUT_FMT_ARGB8888;
-               break;
-       case V4L2_PIX_FMT_BGR32:
-               reg = EXYNOS3250_OUT_FMT_ARGB8888 | EXYNOS3250_OUT_SWAP_RGB;
-               break;
-       case V4L2_PIX_FMT_RGB565:
-               reg = EXYNOS3250_OUT_FMT_RGB565;
-               break;
-       case V4L2_PIX_FMT_RGB565X:
-               reg = EXYNOS3250_OUT_FMT_RGB565 | EXYNOS3250_OUT_SWAP_RGB;
-               break;
-       case V4L2_PIX_FMT_YUYV:
-               reg = EXYNOS3250_OUT_FMT_422_1P_LUM_CHR;
-               break;
-       case V4L2_PIX_FMT_YVYU:
-               reg = EXYNOS3250_OUT_FMT_422_1P_LUM_CHR |
-                       EXYNOS3250_OUT_SWAP_UV;
-               break;
-       case V4L2_PIX_FMT_UYVY:
-               reg = EXYNOS3250_OUT_FMT_422_1P_CHR_LUM;
-               break;
-       case V4L2_PIX_FMT_VYUY:
-               reg = EXYNOS3250_OUT_FMT_422_1P_CHR_LUM |
-                       EXYNOS3250_OUT_SWAP_UV;
-               break;
-       case V4L2_PIX_FMT_NV12:
-               reg = EXYNOS3250_OUT_FMT_420_2P | EXYNOS3250_OUT_NV12;
-               break;
-       case V4L2_PIX_FMT_NV21:
-               reg = EXYNOS3250_OUT_FMT_420_2P | EXYNOS3250_OUT_NV21;
-               break;
-       case V4L2_PIX_FMT_YUV420:
-               reg = EXYNOS3250_OUT_FMT_420_3P;
-               break;
-       default:
-               reg = 0;
-               break;
-       }
-
-       writel(reg, regs + EXYNOS3250_OUTFORM);
-}
-
-void exynos3250_jpeg_jpgadr(void __iomem *regs, unsigned int addr)
-{
-       writel(addr, regs + EXYNOS3250_JPG_JPGADR);
-}
-
-void exynos3250_jpeg_imgadr(void __iomem *regs, struct s5p_jpeg_addr *img_addr)
-{
-       writel(img_addr->y, regs + EXYNOS3250_LUMA_BASE);
-       writel(img_addr->cb, regs + EXYNOS3250_CHROMA_BASE);
-       writel(img_addr->cr, regs + EXYNOS3250_CHROMA_CR_BASE);
-}
-
-void exynos3250_jpeg_stride(void __iomem *regs, unsigned int img_fmt,
-                           unsigned int width)
-{
-       u32 reg_luma = 0, reg_cr = 0, reg_cb = 0;
-
-       switch (img_fmt) {
-       case V4L2_PIX_FMT_RGB32:
-               reg_luma = 4 * width;
-               break;
-       case V4L2_PIX_FMT_RGB565:
-       case V4L2_PIX_FMT_RGB565X:
-       case V4L2_PIX_FMT_YUYV:
-       case V4L2_PIX_FMT_YVYU:
-       case V4L2_PIX_FMT_UYVY:
-       case V4L2_PIX_FMT_VYUY:
-               reg_luma = 2 * width;
-               break;
-       case V4L2_PIX_FMT_NV12:
-       case V4L2_PIX_FMT_NV21:
-               reg_luma = width;
-               reg_cb = reg_luma;
-               break;
-       case V4L2_PIX_FMT_YUV420:
-               reg_luma = width;
-               reg_cb = reg_cr = reg_luma / 2;
-               break;
-       default:
-               break;
-       }
-
-       writel(reg_luma, regs + EXYNOS3250_LUMA_STRIDE);
-       writel(reg_cb, regs + EXYNOS3250_CHROMA_STRIDE);
-       writel(reg_cr, regs + EXYNOS3250_CHROMA_CR_STRIDE);
-}
-
-void exynos3250_jpeg_offset(void __iomem *regs, unsigned int x_offset,
-                               unsigned int y_offset)
-{
-       u32 reg;
-
-       reg = (y_offset << EXYNOS3250_LUMA_YY_OFFSET_SHIFT) &
-                       EXYNOS3250_LUMA_YY_OFFSET_MASK;
-       reg |= (x_offset << EXYNOS3250_LUMA_YX_OFFSET_SHIFT) &
-                       EXYNOS3250_LUMA_YX_OFFSET_MASK;
-
-       writel(reg, regs + EXYNOS3250_LUMA_XY_OFFSET);
-
-       reg = (y_offset << EXYNOS3250_CHROMA_YY_OFFSET_SHIFT) &
-                       EXYNOS3250_CHROMA_YY_OFFSET_MASK;
-       reg |= (x_offset << EXYNOS3250_CHROMA_YX_OFFSET_SHIFT) &
-                       EXYNOS3250_CHROMA_YX_OFFSET_MASK;
-
-       writel(reg, regs + EXYNOS3250_CHROMA_XY_OFFSET);
-
-       reg = (y_offset << EXYNOS3250_CHROMA_CR_YY_OFFSET_SHIFT) &
-                       EXYNOS3250_CHROMA_CR_YY_OFFSET_MASK;
-       reg |= (x_offset << EXYNOS3250_CHROMA_CR_YX_OFFSET_SHIFT) &
-                       EXYNOS3250_CHROMA_CR_YX_OFFSET_MASK;
-
-       writel(reg, regs + EXYNOS3250_CHROMA_CR_XY_OFFSET);
-}
-
-void exynos3250_jpeg_coef(void __iomem *base, unsigned int mode)
-{
-       if (mode == S5P_JPEG_ENCODE) {
-               writel(EXYNOS3250_JPEG_ENC_COEF1,
-                                       base + EXYNOS3250_JPG_COEF(1));
-               writel(EXYNOS3250_JPEG_ENC_COEF2,
-                                       base + EXYNOS3250_JPG_COEF(2));
-               writel(EXYNOS3250_JPEG_ENC_COEF3,
-                                       base + EXYNOS3250_JPG_COEF(3));
-       } else {
-               writel(EXYNOS3250_JPEG_DEC_COEF1,
-                                       base + EXYNOS3250_JPG_COEF(1));
-               writel(EXYNOS3250_JPEG_DEC_COEF2,
-                                       base + EXYNOS3250_JPG_COEF(2));
-               writel(EXYNOS3250_JPEG_DEC_COEF3,
-                                       base + EXYNOS3250_JPG_COEF(3));
-       }
-}
-
-void exynos3250_jpeg_start(void __iomem *regs)
-{
-       writel(1, regs + EXYNOS3250_JSTART);
-}
-
-void exynos3250_jpeg_rstart(void __iomem *regs)
-{
-       writel(1, regs + EXYNOS3250_JRSTART);
-}
-
-unsigned int exynos3250_jpeg_get_int_status(void __iomem *regs)
-{
-       return readl(regs + EXYNOS3250_JPGINTST);
-}
-
-void exynos3250_jpeg_clear_int_status(void __iomem *regs,
-                                     unsigned int value)
-{
-       writel(value, regs + EXYNOS3250_JPGINTST);
-}
-
-unsigned int exynos3250_jpeg_operating(void __iomem *regs)
-{
-       return readl(regs + S5P_JPGOPR) & EXYNOS3250_JPGOPR_MASK;
-}
-
-unsigned int exynos3250_jpeg_compressed_size(void __iomem *regs)
-{
-       return readl(regs + EXYNOS3250_JPGCNT) & EXYNOS3250_JPGCNT_MASK;
-}
-
-void exynos3250_jpeg_dec_stream_size(void __iomem *regs,
-                                               unsigned int size)
-{
-       writel(size & EXYNOS3250_DEC_STREAM_MASK,
-                               regs + EXYNOS3250_DEC_STREAM_SIZE);
-}
-
-void exynos3250_jpeg_dec_scaling_ratio(void __iomem *regs,
-                                               unsigned int sratio)
-{
-       switch (sratio) {
-       case 1:
-       default:
-               sratio = EXYNOS3250_DEC_SCALE_FACTOR_8_8;
-               break;
-       case 2:
-               sratio = EXYNOS3250_DEC_SCALE_FACTOR_4_8;
-               break;
-       case 4:
-               sratio = EXYNOS3250_DEC_SCALE_FACTOR_2_8;
-               break;
-       case 8:
-               sratio = EXYNOS3250_DEC_SCALE_FACTOR_1_8;
-               break;
-       }
-
-       writel(sratio & EXYNOS3250_DEC_SCALE_FACTOR_MASK,
-                               regs + EXYNOS3250_DEC_SCALING_RATIO);
-}
-
-void exynos3250_jpeg_set_timer(void __iomem *regs, unsigned int time_value)
-{
-       time_value &= EXYNOS3250_TIMER_INIT_MASK;
-
-       writel(EXYNOS3250_TIMER_INT_STAT | time_value,
-                                       regs + EXYNOS3250_TIMER_SE);
-}
-
-unsigned int exynos3250_jpeg_get_timer_status(void __iomem *regs)
-{
-       return readl(regs + EXYNOS3250_TIMER_ST);
-}
-
-void exynos3250_jpeg_clear_timer_status(void __iomem *regs)
-{
-       writel(EXYNOS3250_TIMER_INT_STAT, regs + EXYNOS3250_TIMER_ST);
-}
diff --git a/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos3250.h b/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos3250.h
deleted file mode 100644 (file)
index 68160be..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/* linux/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos3250.h
- *
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com
- *
- * Author: Jacek Anaszewski <j.anaszewski@samsung.com>
- */
-#ifndef JPEG_HW_EXYNOS3250_H_
-#define JPEG_HW_EXYNOS3250_H_
-
-#include <linux/io.h>
-#include <linux/videodev2.h>
-
-#include "jpeg-regs.h"
-
-void exynos3250_jpeg_reset(void __iomem *regs);
-void exynos3250_jpeg_poweron(void __iomem *regs);
-void exynos3250_jpeg_set_dma_num(void __iomem *regs);
-void exynos3250_jpeg_clk_set(void __iomem *base);
-void exynos3250_jpeg_input_raw_fmt(void __iomem *regs, unsigned int fmt);
-void exynos3250_jpeg_output_raw_fmt(void __iomem *regs, unsigned int fmt);
-void exynos3250_jpeg_set_y16(void __iomem *regs, bool y16);
-void exynos3250_jpeg_proc_mode(void __iomem *regs, unsigned int mode);
-void exynos3250_jpeg_subsampling_mode(void __iomem *regs, unsigned int mode);
-unsigned int exynos3250_jpeg_get_subsampling_mode(void __iomem *regs);
-void exynos3250_jpeg_dri(void __iomem *regs, unsigned int dri);
-void exynos3250_jpeg_qtbl(void __iomem *regs, unsigned int t, unsigned int n);
-void exynos3250_jpeg_htbl_ac(void __iomem *regs, unsigned int t);
-void exynos3250_jpeg_htbl_dc(void __iomem *regs, unsigned int t);
-void exynos3250_jpeg_set_y(void __iomem *regs, unsigned int y);
-void exynos3250_jpeg_set_x(void __iomem *regs, unsigned int x);
-void exynos3250_jpeg_interrupts_enable(void __iomem *regs);
-void exynos3250_jpeg_enc_stream_bound(void __iomem *regs, unsigned int size);
-void exynos3250_jpeg_outform_raw(void __iomem *regs, unsigned long format);
-void exynos3250_jpeg_jpgadr(void __iomem *regs, unsigned int addr);
-void exynos3250_jpeg_imgadr(void __iomem *regs, struct s5p_jpeg_addr *img_addr);
-void exynos3250_jpeg_stride(void __iomem *regs, unsigned int img_fmt,
-                           unsigned int width);
-void exynos3250_jpeg_offset(void __iomem *regs, unsigned int x_offset,
-                               unsigned int y_offset);
-void exynos3250_jpeg_coef(void __iomem *base, unsigned int mode);
-void exynos3250_jpeg_start(void __iomem *regs);
-void exynos3250_jpeg_rstart(void __iomem *regs);
-unsigned int exynos3250_jpeg_get_int_status(void __iomem *regs);
-void exynos3250_jpeg_clear_int_status(void __iomem *regs,
-                                               unsigned int value);
-unsigned int exynos3250_jpeg_operating(void __iomem *regs);
-unsigned int exynos3250_jpeg_compressed_size(void __iomem *regs);
-void exynos3250_jpeg_dec_stream_size(void __iomem *regs, unsigned int size);
-void exynos3250_jpeg_dec_scaling_ratio(void __iomem *regs, unsigned int sratio);
-void exynos3250_jpeg_set_timer(void __iomem *regs, unsigned int time_value);
-unsigned int exynos3250_jpeg_get_timer_status(void __iomem *regs);
-void exynos3250_jpeg_set_timer_status(void __iomem *regs);
-void exynos3250_jpeg_clear_timer_status(void __iomem *regs);
-
-#endif /* JPEG_HW_EXYNOS3250_H_ */
diff --git a/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos4.c b/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos4.c
deleted file mode 100644 (file)
index 0828cfa..0000000
+++ /dev/null
@@ -1,321 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/* Copyright (c) 2013 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * Author: Jacek Anaszewski <j.anaszewski@samsung.com>
- *
- * Register interface file for JPEG driver on Exynos4x12.
- */
-#include <linux/io.h>
-#include <linux/delay.h>
-
-#include "jpeg-core.h"
-#include "jpeg-hw-exynos4.h"
-#include "jpeg-regs.h"
-
-void exynos4_jpeg_sw_reset(void __iomem *base)
-{
-       unsigned int reg;
-
-       reg = readl(base + EXYNOS4_JPEG_CNTL_REG);
-       writel(reg & ~(EXYNOS4_DEC_MODE | EXYNOS4_ENC_MODE),
-                               base + EXYNOS4_JPEG_CNTL_REG);
-
-       reg = readl(base + EXYNOS4_JPEG_CNTL_REG);
-       writel(reg & ~EXYNOS4_SOFT_RESET_HI, base + EXYNOS4_JPEG_CNTL_REG);
-
-       udelay(100);
-
-       writel(reg | EXYNOS4_SOFT_RESET_HI, base + EXYNOS4_JPEG_CNTL_REG);
-}
-
-void exynos4_jpeg_set_enc_dec_mode(void __iomem *base, unsigned int mode)
-{
-       unsigned int reg;
-
-       reg = readl(base + EXYNOS4_JPEG_CNTL_REG);
-       /* set exynos4_jpeg mod register */
-       if (mode == S5P_JPEG_DECODE) {
-               writel((reg & EXYNOS4_ENC_DEC_MODE_MASK) |
-                                       EXYNOS4_DEC_MODE,
-                       base + EXYNOS4_JPEG_CNTL_REG);
-       } else if (mode == S5P_JPEG_ENCODE) {/* encode */
-               writel((reg & EXYNOS4_ENC_DEC_MODE_MASK) |
-                                       EXYNOS4_ENC_MODE,
-                       base + EXYNOS4_JPEG_CNTL_REG);
-       } else { /* disable both */
-               writel(reg & EXYNOS4_ENC_DEC_MODE_MASK,
-                       base + EXYNOS4_JPEG_CNTL_REG);
-       }
-}
-
-void __exynos4_jpeg_set_img_fmt(void __iomem *base, unsigned int img_fmt,
-                               unsigned int version)
-{
-       unsigned int reg;
-       unsigned int exynos4_swap_chroma_cbcr;
-       unsigned int exynos4_swap_chroma_crcb;
-
-       if (version == SJPEG_EXYNOS4) {
-               exynos4_swap_chroma_cbcr = EXYNOS4_SWAP_CHROMA_CBCR;
-               exynos4_swap_chroma_crcb = EXYNOS4_SWAP_CHROMA_CRCB;
-       } else {
-               exynos4_swap_chroma_cbcr = EXYNOS5433_SWAP_CHROMA_CBCR;
-               exynos4_swap_chroma_crcb = EXYNOS5433_SWAP_CHROMA_CRCB;
-       }
-
-       reg = readl(base + EXYNOS4_IMG_FMT_REG) &
-                       EXYNOS4_ENC_IN_FMT_MASK; /* clear except enc format */
-
-       switch (img_fmt) {
-       case V4L2_PIX_FMT_GREY:
-               reg = reg | EXYNOS4_ENC_GRAY_IMG | EXYNOS4_GRAY_IMG_IP;
-               break;
-       case V4L2_PIX_FMT_RGB32:
-               reg = reg | EXYNOS4_ENC_RGB_IMG |
-                               EXYNOS4_RGB_IP_RGB_32BIT_IMG;
-               break;
-       case V4L2_PIX_FMT_RGB565:
-               reg = reg | EXYNOS4_ENC_RGB_IMG |
-                               EXYNOS4_RGB_IP_RGB_16BIT_IMG;
-               break;
-       case V4L2_PIX_FMT_NV24:
-               reg = reg | EXYNOS4_ENC_YUV_444_IMG |
-                               EXYNOS4_YUV_444_IP_YUV_444_2P_IMG |
-                               exynos4_swap_chroma_cbcr;
-               break;
-       case V4L2_PIX_FMT_NV42:
-               reg = reg | EXYNOS4_ENC_YUV_444_IMG |
-                               EXYNOS4_YUV_444_IP_YUV_444_2P_IMG |
-                               exynos4_swap_chroma_crcb;
-               break;
-       case V4L2_PIX_FMT_YUYV:
-               reg = reg | EXYNOS4_DEC_YUV_422_IMG |
-                               EXYNOS4_YUV_422_IP_YUV_422_1P_IMG |
-                               exynos4_swap_chroma_cbcr;
-               break;
-
-       case V4L2_PIX_FMT_YVYU:
-               reg = reg | EXYNOS4_DEC_YUV_422_IMG |
-                               EXYNOS4_YUV_422_IP_YUV_422_1P_IMG |
-                               exynos4_swap_chroma_crcb;
-               break;
-       case V4L2_PIX_FMT_NV16:
-               reg = reg | EXYNOS4_DEC_YUV_422_IMG |
-                               EXYNOS4_YUV_422_IP_YUV_422_2P_IMG |
-                               exynos4_swap_chroma_cbcr;
-               break;
-       case V4L2_PIX_FMT_NV61:
-               reg = reg | EXYNOS4_DEC_YUV_422_IMG |
-                               EXYNOS4_YUV_422_IP_YUV_422_2P_IMG |
-                               exynos4_swap_chroma_crcb;
-               break;
-       case V4L2_PIX_FMT_NV12:
-               reg = reg | EXYNOS4_DEC_YUV_420_IMG |
-                               EXYNOS4_YUV_420_IP_YUV_420_2P_IMG |
-                               exynos4_swap_chroma_cbcr;
-               break;
-       case V4L2_PIX_FMT_NV21:
-               reg = reg | EXYNOS4_DEC_YUV_420_IMG |
-                               EXYNOS4_YUV_420_IP_YUV_420_2P_IMG |
-                               exynos4_swap_chroma_crcb;
-               break;
-       case V4L2_PIX_FMT_YUV420:
-               reg = reg | EXYNOS4_DEC_YUV_420_IMG |
-                               EXYNOS4_YUV_420_IP_YUV_420_3P_IMG |
-                               exynos4_swap_chroma_cbcr;
-               break;
-       default:
-               break;
-
-       }
-
-       writel(reg, base + EXYNOS4_IMG_FMT_REG);
-}
-
-void __exynos4_jpeg_set_enc_out_fmt(void __iomem *base, unsigned int out_fmt,
-                                   unsigned int version)
-{
-       unsigned int reg;
-
-       reg = readl(base + EXYNOS4_IMG_FMT_REG) &
-                       ~(version == SJPEG_EXYNOS4 ? EXYNOS4_ENC_FMT_MASK :
-                         EXYNOS5433_ENC_FMT_MASK); /* clear enc format */
-
-       switch (out_fmt) {
-       case V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY:
-               reg = reg | EXYNOS4_ENC_FMT_GRAY;
-               break;
-
-       case V4L2_JPEG_CHROMA_SUBSAMPLING_444:
-               reg = reg | EXYNOS4_ENC_FMT_YUV_444;
-               break;
-
-       case V4L2_JPEG_CHROMA_SUBSAMPLING_422:
-               reg = reg | EXYNOS4_ENC_FMT_YUV_422;
-               break;
-
-       case V4L2_JPEG_CHROMA_SUBSAMPLING_420:
-               reg = reg | EXYNOS4_ENC_FMT_YUV_420;
-               break;
-
-       default:
-               break;
-       }
-
-       writel(reg, base + EXYNOS4_IMG_FMT_REG);
-}
-
-void exynos4_jpeg_set_interrupt(void __iomem *base, unsigned int version)
-{
-       unsigned int reg;
-
-       if (version == SJPEG_EXYNOS4) {
-               reg = readl(base + EXYNOS4_INT_EN_REG) & ~EXYNOS4_INT_EN_MASK;
-               writel(reg | EXYNOS4_INT_EN_ALL, base + EXYNOS4_INT_EN_REG);
-       } else {
-               reg = readl(base + EXYNOS4_INT_EN_REG) &
-                                                       ~EXYNOS5433_INT_EN_MASK;
-               writel(reg | EXYNOS5433_INT_EN_ALL, base + EXYNOS4_INT_EN_REG);
-       }
-}
-
-unsigned int exynos4_jpeg_get_int_status(void __iomem *base)
-{
-       return readl(base + EXYNOS4_INT_STATUS_REG);
-}
-
-unsigned int exynos4_jpeg_get_fifo_status(void __iomem *base)
-{
-       return readl(base + EXYNOS4_FIFO_STATUS_REG);
-}
-
-void exynos4_jpeg_set_huf_table_enable(void __iomem *base, int value)
-{
-       unsigned int    reg;
-
-       reg = readl(base + EXYNOS4_JPEG_CNTL_REG) & ~EXYNOS4_HUF_TBL_EN;
-
-       if (value == 1)
-               writel(reg | EXYNOS4_HUF_TBL_EN,
-                                       base + EXYNOS4_JPEG_CNTL_REG);
-       else
-               writel(reg & ~EXYNOS4_HUF_TBL_EN,
-                                       base + EXYNOS4_JPEG_CNTL_REG);
-}
-
-void exynos4_jpeg_set_sys_int_enable(void __iomem *base, int value)
-{
-       unsigned int    reg;
-
-       reg = readl(base + EXYNOS4_JPEG_CNTL_REG) & ~(EXYNOS4_SYS_INT_EN);
-
-       if (value == 1)
-               writel(reg | EXYNOS4_SYS_INT_EN, base + EXYNOS4_JPEG_CNTL_REG);
-       else
-               writel(reg & ~EXYNOS4_SYS_INT_EN, base + EXYNOS4_JPEG_CNTL_REG);
-}
-
-void exynos4_jpeg_set_stream_buf_address(void __iomem *base,
-                                        unsigned int address)
-{
-       writel(address, base + EXYNOS4_OUT_MEM_BASE_REG);
-}
-
-void exynos4_jpeg_set_stream_size(void __iomem *base,
-               unsigned int x_value, unsigned int y_value)
-{
-       writel(0x0, base + EXYNOS4_JPEG_IMG_SIZE_REG); /* clear */
-       writel(EXYNOS4_X_SIZE(x_value) | EXYNOS4_Y_SIZE(y_value),
-                       base + EXYNOS4_JPEG_IMG_SIZE_REG);
-}
-
-void exynos4_jpeg_set_frame_buf_address(void __iomem *base,
-                               struct s5p_jpeg_addr *exynos4_jpeg_addr)
-{
-       writel(exynos4_jpeg_addr->y, base + EXYNOS4_IMG_BA_PLANE_1_REG);
-       writel(exynos4_jpeg_addr->cb, base + EXYNOS4_IMG_BA_PLANE_2_REG);
-       writel(exynos4_jpeg_addr->cr, base + EXYNOS4_IMG_BA_PLANE_3_REG);
-}
-
-void exynos4_jpeg_set_encode_tbl_select(void __iomem *base,
-               enum exynos4_jpeg_img_quality_level level)
-{
-       unsigned int    reg;
-
-       reg = EXYNOS4_Q_TBL_COMP1_0 | EXYNOS4_Q_TBL_COMP2_1 |
-               EXYNOS4_Q_TBL_COMP3_1 |
-               EXYNOS4_HUFF_TBL_COMP1_AC_0_DC_1 |
-               EXYNOS4_HUFF_TBL_COMP2_AC_0_DC_0 |
-               EXYNOS4_HUFF_TBL_COMP3_AC_1_DC_1;
-
-       writel(reg, base + EXYNOS4_TBL_SEL_REG);
-}
-
-void exynos4_jpeg_set_dec_components(void __iomem *base, int n)
-{
-       unsigned int    reg;
-
-       reg = readl(base + EXYNOS4_TBL_SEL_REG);
-
-       reg |= EXYNOS4_NF(n);
-       writel(reg, base + EXYNOS4_TBL_SEL_REG);
-}
-
-void exynos4_jpeg_select_dec_q_tbl(void __iomem *base, char c, char x)
-{
-       unsigned int    reg;
-
-       reg = readl(base + EXYNOS4_TBL_SEL_REG);
-
-       reg |= EXYNOS4_Q_TBL_COMP(c, x);
-       writel(reg, base + EXYNOS4_TBL_SEL_REG);
-}
-
-void exynos4_jpeg_select_dec_h_tbl(void __iomem *base, char c, char x)
-{
-       unsigned int    reg;
-
-       reg = readl(base + EXYNOS4_TBL_SEL_REG);
-
-       reg |= EXYNOS4_HUFF_TBL_COMP(c, x);
-       writel(reg, base + EXYNOS4_TBL_SEL_REG);
-}
-
-void exynos4_jpeg_set_encode_hoff_cnt(void __iomem *base, unsigned int fmt)
-{
-       if (fmt == V4L2_PIX_FMT_GREY)
-               writel(0xd2, base + EXYNOS4_HUFF_CNT_REG);
-       else
-               writel(0x1a2, base + EXYNOS4_HUFF_CNT_REG);
-}
-
-unsigned int exynos4_jpeg_get_stream_size(void __iomem *base)
-{
-       return readl(base + EXYNOS4_BITSTREAM_SIZE_REG);
-}
-
-void exynos4_jpeg_set_dec_bitstream_size(void __iomem *base, unsigned int size)
-{
-       writel(size, base + EXYNOS4_BITSTREAM_SIZE_REG);
-}
-
-void exynos4_jpeg_get_frame_size(void __iomem *base,
-                       unsigned int *width, unsigned int *height)
-{
-       *width = (readl(base + EXYNOS4_DECODE_XY_SIZE_REG) &
-                               EXYNOS4_DECODED_SIZE_MASK);
-       *height = (readl(base + EXYNOS4_DECODE_XY_SIZE_REG) >> 16) &
-                               EXYNOS4_DECODED_SIZE_MASK;
-}
-
-unsigned int exynos4_jpeg_get_frame_fmt(void __iomem *base)
-{
-       return readl(base + EXYNOS4_DECODE_IMG_FMT_REG) &
-                               EXYNOS4_JPEG_DECODED_IMG_FMT_MASK;
-}
-
-void exynos4_jpeg_set_timer_count(void __iomem *base, unsigned int size)
-{
-       writel(size, base + EXYNOS4_INT_TIMER_COUNT_REG);
-}
diff --git a/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos4.h b/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos4.h
deleted file mode 100644 (file)
index 3e28875..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/* Copyright (c) 2013 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * Author: Jacek Anaszewski <j.anaszewski@samsung.com>
- *
- * Header file of the register interface for JPEG driver on Exynos4x12.
-*/
-
-#ifndef JPEG_HW_EXYNOS4_H_
-#define JPEG_HW_EXYNOS4_H_
-
-void exynos4_jpeg_sw_reset(void __iomem *base);
-void exynos4_jpeg_set_enc_dec_mode(void __iomem *base, unsigned int mode);
-void __exynos4_jpeg_set_img_fmt(void __iomem *base, unsigned int img_fmt,
-                               unsigned int version);
-void __exynos4_jpeg_set_enc_out_fmt(void __iomem *base, unsigned int out_fmt,
-                                   unsigned int version);
-void exynos4_jpeg_set_enc_tbl(void __iomem *base);
-void exynos4_jpeg_set_interrupt(void __iomem *base, unsigned int version);
-unsigned int exynos4_jpeg_get_int_status(void __iomem *base);
-void exynos4_jpeg_set_huf_table_enable(void __iomem *base, int value);
-void exynos4_jpeg_set_sys_int_enable(void __iomem *base, int value);
-void exynos4_jpeg_set_stream_buf_address(void __iomem *base,
-                                        unsigned int address);
-void exynos4_jpeg_set_stream_size(void __iomem *base,
-               unsigned int x_value, unsigned int y_value);
-void exynos4_jpeg_set_frame_buf_address(void __iomem *base,
-                               struct s5p_jpeg_addr *jpeg_addr);
-void exynos4_jpeg_set_encode_tbl_select(void __iomem *base,
-               enum exynos4_jpeg_img_quality_level level);
-void exynos4_jpeg_set_dec_components(void __iomem *base, int n);
-void exynos4_jpeg_select_dec_q_tbl(void __iomem *base, char c, char x);
-void exynos4_jpeg_select_dec_h_tbl(void __iomem *base, char c, char x);
-void exynos4_jpeg_set_encode_hoff_cnt(void __iomem *base, unsigned int fmt);
-void exynos4_jpeg_set_dec_bitstream_size(void __iomem *base, unsigned int size);
-unsigned int exynos4_jpeg_get_stream_size(void __iomem *base);
-void exynos4_jpeg_get_frame_size(void __iomem *base,
-                       unsigned int *width, unsigned int *height);
-unsigned int exynos4_jpeg_get_frame_fmt(void __iomem *base);
-unsigned int exynos4_jpeg_get_fifo_status(void __iomem *base);
-void exynos4_jpeg_set_timer_count(void __iomem *base, unsigned int size);
-
-#endif /* JPEG_HW_EXYNOS4_H_ */
diff --git a/drivers/media/platform/s5p-jpeg/jpeg-hw-s5p.c b/drivers/media/platform/s5p-jpeg/jpeg-hw-s5p.c
deleted file mode 100644 (file)
index 491e924..0000000
+++ /dev/null
@@ -1,306 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/* linux/drivers/media/platform/s5p-jpeg/jpeg-hw.h
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com
- *
- * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
- */
-
-#include <linux/io.h>
-#include <linux/videodev2.h>
-
-#include "jpeg-core.h"
-#include "jpeg-regs.h"
-#include "jpeg-hw-s5p.h"
-
-void s5p_jpeg_reset(void __iomem *regs)
-{
-       unsigned long reg;
-
-       writel(1, regs + S5P_JPG_SW_RESET);
-       reg = readl(regs + S5P_JPG_SW_RESET);
-       /* no other way but polling for when JPEG IP becomes operational */
-       while (reg != 0) {
-               cpu_relax();
-               reg = readl(regs + S5P_JPG_SW_RESET);
-       }
-}
-
-void s5p_jpeg_poweron(void __iomem *regs)
-{
-       writel(S5P_POWER_ON, regs + S5P_JPGCLKCON);
-}
-
-void s5p_jpeg_input_raw_mode(void __iomem *regs, unsigned long mode)
-{
-       unsigned long reg, m;
-
-       m = S5P_MOD_SEL_565;
-       if (mode == S5P_JPEG_RAW_IN_565)
-               m = S5P_MOD_SEL_565;
-       else if (mode == S5P_JPEG_RAW_IN_422)
-               m = S5P_MOD_SEL_422;
-
-       reg = readl(regs + S5P_JPGCMOD);
-       reg &= ~S5P_MOD_SEL_MASK;
-       reg |= m;
-       writel(reg, regs + S5P_JPGCMOD);
-}
-
-void s5p_jpeg_proc_mode(void __iomem *regs, unsigned long mode)
-{
-       unsigned long reg, m;
-
-       m = S5P_PROC_MODE_DECOMPR;
-       if (mode == S5P_JPEG_ENCODE)
-               m = S5P_PROC_MODE_COMPR;
-       else
-               m = S5P_PROC_MODE_DECOMPR;
-       reg = readl(regs + S5P_JPGMOD);
-       reg &= ~S5P_PROC_MODE_MASK;
-       reg |= m;
-       writel(reg, regs + S5P_JPGMOD);
-}
-
-void s5p_jpeg_subsampling_mode(void __iomem *regs, unsigned int mode)
-{
-       unsigned long reg, m;
-
-       if (mode == V4L2_JPEG_CHROMA_SUBSAMPLING_420)
-               m = S5P_SUBSAMPLING_MODE_420;
-       else
-               m = S5P_SUBSAMPLING_MODE_422;
-
-       reg = readl(regs + S5P_JPGMOD);
-       reg &= ~S5P_SUBSAMPLING_MODE_MASK;
-       reg |= m;
-       writel(reg, regs + S5P_JPGMOD);
-}
-
-unsigned int s5p_jpeg_get_subsampling_mode(void __iomem *regs)
-{
-       return readl(regs + S5P_JPGMOD) & S5P_SUBSAMPLING_MODE_MASK;
-}
-
-void s5p_jpeg_dri(void __iomem *regs, unsigned int dri)
-{
-       unsigned long reg;
-
-       reg = readl(regs + S5P_JPGDRI_U);
-       reg &= ~0xff;
-       reg |= (dri >> 8) & 0xff;
-       writel(reg, regs + S5P_JPGDRI_U);
-
-       reg = readl(regs + S5P_JPGDRI_L);
-       reg &= ~0xff;
-       reg |= dri & 0xff;
-       writel(reg, regs + S5P_JPGDRI_L);
-}
-
-void s5p_jpeg_qtbl(void __iomem *regs, unsigned int t, unsigned int n)
-{
-       unsigned long reg;
-
-       reg = readl(regs + S5P_JPG_QTBL);
-       reg &= ~S5P_QT_NUMt_MASK(t);
-       reg |= (n << S5P_QT_NUMt_SHIFT(t)) & S5P_QT_NUMt_MASK(t);
-       writel(reg, regs + S5P_JPG_QTBL);
-}
-
-void s5p_jpeg_htbl_ac(void __iomem *regs, unsigned int t)
-{
-       unsigned long reg;
-
-       reg = readl(regs + S5P_JPG_HTBL);
-       reg &= ~S5P_HT_NUMt_AC_MASK(t);
-       /* this driver uses table 0 for all color components */
-       reg |= (0 << S5P_HT_NUMt_AC_SHIFT(t)) & S5P_HT_NUMt_AC_MASK(t);
-       writel(reg, regs + S5P_JPG_HTBL);
-}
-
-void s5p_jpeg_htbl_dc(void __iomem *regs, unsigned int t)
-{
-       unsigned long reg;
-
-       reg = readl(regs + S5P_JPG_HTBL);
-       reg &= ~S5P_HT_NUMt_DC_MASK(t);
-       /* this driver uses table 0 for all color components */
-       reg |= (0 << S5P_HT_NUMt_DC_SHIFT(t)) & S5P_HT_NUMt_DC_MASK(t);
-       writel(reg, regs + S5P_JPG_HTBL);
-}
-
-void s5p_jpeg_y(void __iomem *regs, unsigned int y)
-{
-       unsigned long reg;
-
-       reg = readl(regs + S5P_JPGY_U);
-       reg &= ~0xff;
-       reg |= (y >> 8) & 0xff;
-       writel(reg, regs + S5P_JPGY_U);
-
-       reg = readl(regs + S5P_JPGY_L);
-       reg &= ~0xff;
-       reg |= y & 0xff;
-       writel(reg, regs + S5P_JPGY_L);
-}
-
-void s5p_jpeg_x(void __iomem *regs, unsigned int x)
-{
-       unsigned long reg;
-
-       reg = readl(regs + S5P_JPGX_U);
-       reg &= ~0xff;
-       reg |= (x >> 8) & 0xff;
-       writel(reg, regs + S5P_JPGX_U);
-
-       reg = readl(regs + S5P_JPGX_L);
-       reg &= ~0xff;
-       reg |= x & 0xff;
-       writel(reg, regs + S5P_JPGX_L);
-}
-
-void s5p_jpeg_rst_int_enable(void __iomem *regs, bool enable)
-{
-       unsigned long reg;
-
-       reg = readl(regs + S5P_JPGINTSE);
-       reg &= ~S5P_RSTm_INT_EN_MASK;
-       if (enable)
-               reg |= S5P_RSTm_INT_EN;
-       writel(reg, regs + S5P_JPGINTSE);
-}
-
-void s5p_jpeg_data_num_int_enable(void __iomem *regs, bool enable)
-{
-       unsigned long reg;
-
-       reg = readl(regs + S5P_JPGINTSE);
-       reg &= ~S5P_DATA_NUM_INT_EN_MASK;
-       if (enable)
-               reg |= S5P_DATA_NUM_INT_EN;
-       writel(reg, regs + S5P_JPGINTSE);
-}
-
-void s5p_jpeg_final_mcu_num_int_enable(void __iomem *regs, bool enbl)
-{
-       unsigned long reg;
-
-       reg = readl(regs + S5P_JPGINTSE);
-       reg &= ~S5P_FINAL_MCU_NUM_INT_EN_MASK;
-       if (enbl)
-               reg |= S5P_FINAL_MCU_NUM_INT_EN;
-       writel(reg, regs + S5P_JPGINTSE);
-}
-
-int s5p_jpeg_timer_stat(void __iomem *regs)
-{
-       return (int)((readl(regs + S5P_JPG_TIMER_ST) & S5P_TIMER_INT_STAT_MASK)
-                    >> S5P_TIMER_INT_STAT_SHIFT);
-}
-
-void s5p_jpeg_clear_timer_stat(void __iomem *regs)
-{
-       unsigned long reg;
-
-       reg = readl(regs + S5P_JPG_TIMER_SE);
-       reg &= ~S5P_TIMER_INT_STAT_MASK;
-       writel(reg, regs + S5P_JPG_TIMER_SE);
-}
-
-void s5p_jpeg_enc_stream_int(void __iomem *regs, unsigned long size)
-{
-       unsigned long reg;
-
-       reg = readl(regs + S5P_JPG_ENC_STREAM_INTSE);
-       reg &= ~S5P_ENC_STREAM_BOUND_MASK;
-       reg |= S5P_ENC_STREAM_INT_EN;
-       reg |= size & S5P_ENC_STREAM_BOUND_MASK;
-       writel(reg, regs + S5P_JPG_ENC_STREAM_INTSE);
-}
-
-int s5p_jpeg_enc_stream_stat(void __iomem *regs)
-{
-       return (int)(readl(regs + S5P_JPG_ENC_STREAM_INTST) &
-                    S5P_ENC_STREAM_INT_STAT_MASK);
-}
-
-void s5p_jpeg_clear_enc_stream_stat(void __iomem *regs)
-{
-       unsigned long reg;
-
-       reg = readl(regs + S5P_JPG_ENC_STREAM_INTSE);
-       reg &= ~S5P_ENC_STREAM_INT_MASK;
-       writel(reg, regs + S5P_JPG_ENC_STREAM_INTSE);
-}
-
-void s5p_jpeg_outform_raw(void __iomem *regs, unsigned long format)
-{
-       unsigned long reg, f;
-
-       f = S5P_DEC_OUT_FORMAT_422;
-       if (format == S5P_JPEG_RAW_OUT_422)
-               f = S5P_DEC_OUT_FORMAT_422;
-       else if (format == S5P_JPEG_RAW_OUT_420)
-               f = S5P_DEC_OUT_FORMAT_420;
-       reg = readl(regs + S5P_JPG_OUTFORM);
-       reg &= ~S5P_DEC_OUT_FORMAT_MASK;
-       reg |= f;
-       writel(reg, regs + S5P_JPG_OUTFORM);
-}
-
-void s5p_jpeg_jpgadr(void __iomem *regs, unsigned long addr)
-{
-       writel(addr, regs + S5P_JPG_JPGADR);
-}
-
-void s5p_jpeg_imgadr(void __iomem *regs, unsigned long addr)
-{
-       writel(addr, regs + S5P_JPG_IMGADR);
-}
-
-void s5p_jpeg_coef(void __iomem *regs, unsigned int i,
-                            unsigned int j, unsigned int coef)
-{
-       unsigned long reg;
-
-       reg = readl(regs + S5P_JPG_COEF(i));
-       reg &= ~S5P_COEFn_MASK(j);
-       reg |= (coef << S5P_COEFn_SHIFT(j)) & S5P_COEFn_MASK(j);
-       writel(reg, regs + S5P_JPG_COEF(i));
-}
-
-void s5p_jpeg_start(void __iomem *regs)
-{
-       writel(1, regs + S5P_JSTART);
-}
-
-int s5p_jpeg_result_stat_ok(void __iomem *regs)
-{
-       return (int)((readl(regs + S5P_JPGINTST) & S5P_RESULT_STAT_MASK)
-                    >> S5P_RESULT_STAT_SHIFT);
-}
-
-int s5p_jpeg_stream_stat_ok(void __iomem *regs)
-{
-       return !(int)((readl(regs + S5P_JPGINTST) & S5P_STREAM_STAT_MASK)
-                     >> S5P_STREAM_STAT_SHIFT);
-}
-
-void s5p_jpeg_clear_int(void __iomem *regs)
-{
-       readl(regs + S5P_JPGINTST);
-       writel(S5P_INT_RELEASE, regs + S5P_JPGCOM);
-       readl(regs + S5P_JPGOPR);
-}
-
-unsigned int s5p_jpeg_compressed_size(void __iomem *regs)
-{
-       unsigned long jpeg_size = 0;
-
-       jpeg_size |= (readl(regs + S5P_JPGCNT_U) & 0xff) << 16;
-       jpeg_size |= (readl(regs + S5P_JPGCNT_M) & 0xff) << 8;
-       jpeg_size |= (readl(regs + S5P_JPGCNT_L) & 0xff);
-
-       return (unsigned int)jpeg_size;
-}
diff --git a/drivers/media/platform/s5p-jpeg/jpeg-hw-s5p.h b/drivers/media/platform/s5p-jpeg/jpeg-hw-s5p.h
deleted file mode 100644 (file)
index 98ddf70..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/* linux/drivers/media/platform/s5p-jpeg/jpeg-hw.h
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com
- *
- * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
- */
-#ifndef JPEG_HW_S5P_H_
-#define JPEG_HW_S5P_H_
-
-#include <linux/io.h>
-#include <linux/videodev2.h>
-
-#include "jpeg-regs.h"
-
-#define S5P_JPEG_MIN_WIDTH             32
-#define S5P_JPEG_MIN_HEIGHT            32
-#define S5P_JPEG_MAX_WIDTH             8192
-#define S5P_JPEG_MAX_HEIGHT            8192
-#define S5P_JPEG_RAW_IN_565            0
-#define S5P_JPEG_RAW_IN_422            1
-#define S5P_JPEG_RAW_OUT_422           0
-#define S5P_JPEG_RAW_OUT_420           1
-
-void s5p_jpeg_reset(void __iomem *regs);
-void s5p_jpeg_poweron(void __iomem *regs);
-void s5p_jpeg_input_raw_mode(void __iomem *regs, unsigned long mode);
-void s5p_jpeg_proc_mode(void __iomem *regs, unsigned long mode);
-void s5p_jpeg_subsampling_mode(void __iomem *regs, unsigned int mode);
-unsigned int s5p_jpeg_get_subsampling_mode(void __iomem *regs);
-void s5p_jpeg_dri(void __iomem *regs, unsigned int dri);
-void s5p_jpeg_qtbl(void __iomem *regs, unsigned int t, unsigned int n);
-void s5p_jpeg_htbl_ac(void __iomem *regs, unsigned int t);
-void s5p_jpeg_htbl_dc(void __iomem *regs, unsigned int t);
-void s5p_jpeg_y(void __iomem *regs, unsigned int y);
-void s5p_jpeg_x(void __iomem *regs, unsigned int x);
-void s5p_jpeg_rst_int_enable(void __iomem *regs, bool enable);
-void s5p_jpeg_data_num_int_enable(void __iomem *regs, bool enable);
-void s5p_jpeg_final_mcu_num_int_enable(void __iomem *regs, bool enbl);
-int s5p_jpeg_timer_stat(void __iomem *regs);
-void s5p_jpeg_clear_timer_stat(void __iomem *regs);
-void s5p_jpeg_enc_stream_int(void __iomem *regs, unsigned long size);
-int s5p_jpeg_enc_stream_stat(void __iomem *regs);
-void s5p_jpeg_clear_enc_stream_stat(void __iomem *regs);
-void s5p_jpeg_outform_raw(void __iomem *regs, unsigned long format);
-void s5p_jpeg_jpgadr(void __iomem *regs, unsigned long addr);
-void s5p_jpeg_imgadr(void __iomem *regs, unsigned long addr);
-void s5p_jpeg_coef(void __iomem *regs, unsigned int i,
-                            unsigned int j, unsigned int coef);
-void s5p_jpeg_start(void __iomem *regs);
-int s5p_jpeg_result_stat_ok(void __iomem *regs);
-int s5p_jpeg_stream_stat_ok(void __iomem *regs);
-void s5p_jpeg_clear_int(void __iomem *regs);
-unsigned int s5p_jpeg_compressed_size(void __iomem *regs);
-
-#endif /* JPEG_HW_S5P_H_ */
diff --git a/drivers/media/platform/s5p-jpeg/jpeg-regs.h b/drivers/media/platform/s5p-jpeg/jpeg-regs.h
deleted file mode 100644 (file)
index 86f376b..0000000
+++ /dev/null
@@ -1,646 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/* linux/drivers/media/platform/s5p-jpeg/jpeg-regs.h
- *
- * Register definition file for Samsung JPEG codec driver
- *
- * Copyright (c) 2011-2014 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com
- *
- * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
- * Author: Jacek Anaszewski <j.anaszewski@samsung.com>
- */
-
-#ifndef JPEG_REGS_H_
-#define JPEG_REGS_H_
-
-/* Register and bit definitions for S5PC210 */
-
-/* JPEG mode register */
-#define S5P_JPGMOD                     0x00
-#define S5P_PROC_MODE_MASK             (0x1 << 3)
-#define S5P_PROC_MODE_DECOMPR          (0x1 << 3)
-#define S5P_PROC_MODE_COMPR            (0x0 << 3)
-#define S5P_SUBSAMPLING_MODE_MASK      0x7
-#define S5P_SUBSAMPLING_MODE_444       (0x0 << 0)
-#define S5P_SUBSAMPLING_MODE_422       (0x1 << 0)
-#define S5P_SUBSAMPLING_MODE_420       (0x2 << 0)
-#define S5P_SUBSAMPLING_MODE_GRAY      (0x3 << 0)
-
-/* JPEG operation status register */
-#define S5P_JPGOPR                     0x04
-
-/* Quantization tables*/
-#define S5P_JPG_QTBL                   0x08
-#define S5P_QT_NUMt_SHIFT(t)           (((t) - 1) << 1)
-#define S5P_QT_NUMt_MASK(t)            (0x3 << S5P_QT_NUMt_SHIFT(t))
-
-/* Huffman tables */
-#define S5P_JPG_HTBL                   0x0c
-#define S5P_HT_NUMt_AC_SHIFT(t)                (((t) << 1) - 1)
-#define S5P_HT_NUMt_AC_MASK(t)         (0x1 << S5P_HT_NUMt_AC_SHIFT(t))
-
-#define S5P_HT_NUMt_DC_SHIFT(t)                (((t) - 1) << 1)
-#define S5P_HT_NUMt_DC_MASK(t)         (0x1 << S5P_HT_NUMt_DC_SHIFT(t))
-
-/* JPEG restart interval register upper byte */
-#define S5P_JPGDRI_U                   0x10
-
-/* JPEG restart interval register lower byte */
-#define S5P_JPGDRI_L                   0x14
-
-/* JPEG vertical resolution register upper byte */
-#define S5P_JPGY_U                     0x18
-
-/* JPEG vertical resolution register lower byte */
-#define S5P_JPGY_L                     0x1c
-
-/* JPEG horizontal resolution register upper byte */
-#define S5P_JPGX_U                     0x20
-
-/* JPEG horizontal resolution register lower byte */
-#define S5P_JPGX_L                     0x24
-
-/* JPEG byte count register upper byte */
-#define S5P_JPGCNT_U                   0x28
-
-/* JPEG byte count register middle byte */
-#define S5P_JPGCNT_M                   0x2c
-
-/* JPEG byte count register lower byte */
-#define S5P_JPGCNT_L                   0x30
-
-/* JPEG interrupt setting register */
-#define S5P_JPGINTSE                   0x34
-#define S5P_RSTm_INT_EN_MASK           (0x1 << 7)
-#define S5P_RSTm_INT_EN                        (0x1 << 7)
-#define S5P_DATA_NUM_INT_EN_MASK       (0x1 << 6)
-#define S5P_DATA_NUM_INT_EN            (0x1 << 6)
-#define S5P_FINAL_MCU_NUM_INT_EN_MASK  (0x1 << 5)
-#define S5P_FINAL_MCU_NUM_INT_EN       (0x1 << 5)
-
-/* JPEG interrupt status register */
-#define S5P_JPGINTST                   0x38
-#define S5P_RESULT_STAT_SHIFT          6
-#define S5P_RESULT_STAT_MASK           (0x1 << S5P_RESULT_STAT_SHIFT)
-#define S5P_STREAM_STAT_SHIFT          5
-#define S5P_STREAM_STAT_MASK           (0x1 << S5P_STREAM_STAT_SHIFT)
-
-/* JPEG command register */
-#define S5P_JPGCOM                     0x4c
-#define S5P_INT_RELEASE                        (0x1 << 2)
-
-/* Raw image data r/w address register */
-#define S5P_JPG_IMGADR                 0x50
-
-/* JPEG file r/w address register */
-#define S5P_JPG_JPGADR                 0x58
-
-/* Coefficient for RGB-to-YCbCr converter register */
-#define S5P_JPG_COEF(n)                        (0x5c + (((n) - 1) << 2))
-#define S5P_COEFn_SHIFT(j)             ((3 - (j)) << 3)
-#define S5P_COEFn_MASK(j)              (0xff << S5P_COEFn_SHIFT(j))
-
-/* JPEG color mode register */
-#define S5P_JPGCMOD                    0x68
-#define S5P_MOD_SEL_MASK               (0x7 << 5)
-#define S5P_MOD_SEL_422                        (0x1 << 5)
-#define S5P_MOD_SEL_565                        (0x2 << 5)
-#define S5P_MODE_Y16_MASK              (0x1 << 1)
-#define S5P_MODE_Y16                   (0x1 << 1)
-
-/* JPEG clock control register */
-#define S5P_JPGCLKCON                  0x6c
-#define S5P_CLK_DOWN_READY             (0x1 << 1)
-#define S5P_POWER_ON                   (0x1 << 0)
-
-/* JPEG start register */
-#define S5P_JSTART                     0x70
-
-/* JPEG SW reset register */
-#define S5P_JPG_SW_RESET               0x78
-
-/* JPEG timer setting register */
-#define S5P_JPG_TIMER_SE               0x7c
-#define S5P_TIMER_INT_EN_MASK          (0x1UL << 31)
-#define S5P_TIMER_INT_EN               (0x1UL << 31)
-#define S5P_TIMER_INIT_MASK            0x7fffffff
-
-/* JPEG timer status register */
-#define S5P_JPG_TIMER_ST               0x80
-#define S5P_TIMER_INT_STAT_SHIFT       31
-#define S5P_TIMER_INT_STAT_MASK                (0x1UL << S5P_TIMER_INT_STAT_SHIFT)
-#define S5P_TIMER_CNT_SHIFT            0
-#define S5P_TIMER_CNT_MASK             0x7fffffff
-
-/* JPEG decompression output format register */
-#define S5P_JPG_OUTFORM                        0x88
-#define S5P_DEC_OUT_FORMAT_MASK                (0x1 << 0)
-#define S5P_DEC_OUT_FORMAT_422         (0x0 << 0)
-#define S5P_DEC_OUT_FORMAT_420         (0x1 << 0)
-
-/* JPEG version register */
-#define S5P_JPG_VERSION                        0x8c
-
-/* JPEG compressed stream size interrupt setting register */
-#define S5P_JPG_ENC_STREAM_INTSE       0x98
-#define S5P_ENC_STREAM_INT_MASK                (0x1 << 24)
-#define S5P_ENC_STREAM_INT_EN          (0x1 << 24)
-#define S5P_ENC_STREAM_BOUND_MASK      0xffffff
-
-/* JPEG compressed stream size interrupt status register */
-#define S5P_JPG_ENC_STREAM_INTST       0x9c
-#define S5P_ENC_STREAM_INT_STAT_MASK   0x1
-
-/* JPEG quantizer table register */
-#define S5P_JPG_QTBL_CONTENT(n)                (0x400 + (n) * 0x100)
-
-/* JPEG DC Huffman table register */
-#define S5P_JPG_HDCTBL(n)              (0x800 + (n) * 0x400)
-
-/* JPEG DC Huffman table register */
-#define S5P_JPG_HDCTBLG(n)             (0x840 + (n) * 0x400)
-
-/* JPEG AC Huffman table register */
-#define S5P_JPG_HACTBL(n)              (0x880 + (n) * 0x400)
-
-/* JPEG AC Huffman table register */
-#define S5P_JPG_HACTBLG(n)             (0x8c0 + (n) * 0x400)
-
-
-/* Register and bit definitions for Exynos 4x12 */
-
-/* JPEG Codec Control Registers */
-#define EXYNOS4_JPEG_CNTL_REG          0x00
-#define EXYNOS4_INT_EN_REG             0x04
-#define EXYNOS4_INT_TIMER_COUNT_REG    0x08
-#define EXYNOS4_INT_STATUS_REG         0x0c
-#define EXYNOS4_OUT_MEM_BASE_REG               0x10
-#define EXYNOS4_JPEG_IMG_SIZE_REG      0x14
-#define EXYNOS4_IMG_BA_PLANE_1_REG     0x18
-#define EXYNOS4_IMG_SO_PLANE_1_REG     0x1c
-#define EXYNOS4_IMG_PO_PLANE_1_REG     0x20
-#define EXYNOS4_IMG_BA_PLANE_2_REG     0x24
-#define EXYNOS4_IMG_SO_PLANE_2_REG     0x28
-#define EXYNOS4_IMG_PO_PLANE_2_REG     0x2c
-#define EXYNOS4_IMG_BA_PLANE_3_REG     0x30
-#define EXYNOS4_IMG_SO_PLANE_3_REG     0x34
-#define EXYNOS4_IMG_PO_PLANE_3_REG     0x38
-
-#define EXYNOS4_TBL_SEL_REG            0x3c
-
-#define EXYNOS4_IMG_FMT_REG            0x40
-
-#define EXYNOS4_BITSTREAM_SIZE_REG     0x44
-#define EXYNOS4_PADDING_REG            0x48
-#define EXYNOS4_HUFF_CNT_REG           0x4c
-#define EXYNOS4_FIFO_STATUS_REG        0x50
-#define EXYNOS4_DECODE_XY_SIZE_REG     0x54
-#define EXYNOS4_DECODE_IMG_FMT_REG     0x58
-
-#define EXYNOS4_QUAN_TBL_ENTRY_REG     0x100
-#define EXYNOS4_HUFF_TBL_ENTRY_REG     0x200
-
-
-/****************************************************************/
-/* Bit definition part                                         */
-/****************************************************************/
-
-/* JPEG CNTL Register bit */
-#define EXYNOS4_ENC_DEC_MODE_MASK      (0xfffffffc << 0)
-#define EXYNOS4_DEC_MODE               (1 << 0)
-#define EXYNOS4_ENC_MODE               (1 << 1)
-#define EXYNOS4_AUTO_RST_MARKER                (1 << 2)
-#define EXYNOS4_RST_INTERVAL_SHIFT     3
-#define EXYNOS4_RST_INTERVAL(x)                (((x) & 0xffff) \
-                                               << EXYNOS4_RST_INTERVAL_SHIFT)
-#define EXYNOS4_HUF_TBL_EN             (1 << 19)
-#define EXYNOS4_HOR_SCALING_SHIFT      20
-#define EXYNOS4_HOR_SCALING_MASK       (3 << EXYNOS4_HOR_SCALING_SHIFT)
-#define EXYNOS4_HOR_SCALING(x)         (((x) & 0x3) \
-                                               << EXYNOS4_HOR_SCALING_SHIFT)
-#define EXYNOS4_VER_SCALING_SHIFT      22
-#define EXYNOS4_VER_SCALING_MASK       (3 << EXYNOS4_VER_SCALING_SHIFT)
-#define EXYNOS4_VER_SCALING(x)         (((x) & 0x3) \
-                                               << EXYNOS4_VER_SCALING_SHIFT)
-#define EXYNOS4_PADDING                        (1 << 27)
-#define EXYNOS4_SYS_INT_EN             (1 << 28)
-#define EXYNOS4_SOFT_RESET_HI          (1 << 29)
-
-/* JPEG INT Register bit */
-#define EXYNOS4_INT_EN_MASK            (0x1f << 0)
-#define EXYNOS5433_INT_EN_MASK         (0x1ff << 0)
-#define EXYNOS4_PROT_ERR_INT_EN                (1 << 0)
-#define EXYNOS4_IMG_COMPLETION_INT_EN  (1 << 1)
-#define EXYNOS4_DEC_INVALID_FORMAT_EN  (1 << 2)
-#define EXYNOS4_MULTI_SCAN_ERROR_EN    (1 << 3)
-#define EXYNOS4_FRAME_ERR_EN           (1 << 4)
-#define EXYNOS4_INT_EN_ALL             (0x1f << 0)
-#define EXYNOS5433_INT_EN_ALL          (0x1b6 << 0)
-
-#define EXYNOS4_MOD_REG_PROC_ENC       (0 << 3)
-#define EXYNOS4_MOD_REG_PROC_DEC       (1 << 3)
-
-#define EXYNOS4_MOD_REG_SUBSAMPLE_444  (0 << 0)
-#define EXYNOS4_MOD_REG_SUBSAMPLE_422  (1 << 0)
-#define EXYNOS4_MOD_REG_SUBSAMPLE_420  (2 << 0)
-#define EXYNOS4_MOD_REG_SUBSAMPLE_GRAY (3 << 0)
-
-
-/* JPEG IMAGE SIZE Register bit */
-#define EXYNOS4_X_SIZE_SHIFT           0
-#define EXYNOS4_X_SIZE_MASK            (0xffff << EXYNOS4_X_SIZE_SHIFT)
-#define EXYNOS4_X_SIZE(x)              (((x) & 0xffff) << EXYNOS4_X_SIZE_SHIFT)
-#define EXYNOS4_Y_SIZE_SHIFT           16
-#define EXYNOS4_Y_SIZE_MASK            (0xffff << EXYNOS4_Y_SIZE_SHIFT)
-#define EXYNOS4_Y_SIZE(x)              (((x) & 0xffff) << EXYNOS4_Y_SIZE_SHIFT)
-
-/* JPEG IMAGE FORMAT Register bit */
-#define EXYNOS4_ENC_IN_FMT_MASK                0xffff0000
-#define EXYNOS4_ENC_GRAY_IMG           (0 << 0)
-#define EXYNOS4_ENC_RGB_IMG            (1 << 0)
-#define EXYNOS4_ENC_YUV_444_IMG                (2 << 0)
-#define EXYNOS4_ENC_YUV_422_IMG                (3 << 0)
-#define EXYNOS4_ENC_YUV_440_IMG                (4 << 0)
-
-#define EXYNOS4_DEC_GRAY_IMG           (0 << 0)
-#define EXYNOS4_DEC_RGB_IMG            (1 << 0)
-#define EXYNOS4_DEC_YUV_444_IMG                (2 << 0)
-#define EXYNOS4_DEC_YUV_422_IMG                (3 << 0)
-#define EXYNOS4_DEC_YUV_420_IMG                (4 << 0)
-
-#define EXYNOS4_GRAY_IMG_IP_SHIFT      3
-#define EXYNOS4_GRAY_IMG_IP_MASK       (7 << EXYNOS4_GRAY_IMG_IP_SHIFT)
-#define EXYNOS4_GRAY_IMG_IP            (4 << EXYNOS4_GRAY_IMG_IP_SHIFT)
-
-#define EXYNOS4_RGB_IP_SHIFT           6
-#define EXYNOS4_RGB_IP_MASK            (7 << EXYNOS4_RGB_IP_SHIFT)
-#define EXYNOS4_RGB_IP_RGB_16BIT_IMG   (4 << EXYNOS4_RGB_IP_SHIFT)
-#define EXYNOS4_RGB_IP_RGB_32BIT_IMG   (5 << EXYNOS4_RGB_IP_SHIFT)
-
-#define EXYNOS4_YUV_444_IP_SHIFT               9
-#define EXYNOS4_YUV_444_IP_MASK                        (7 << EXYNOS4_YUV_444_IP_SHIFT)
-#define EXYNOS4_YUV_444_IP_YUV_444_2P_IMG      (4 << EXYNOS4_YUV_444_IP_SHIFT)
-#define EXYNOS4_YUV_444_IP_YUV_444_3P_IMG      (5 << EXYNOS4_YUV_444_IP_SHIFT)
-
-#define EXYNOS4_YUV_422_IP_SHIFT               12
-#define EXYNOS4_YUV_422_IP_MASK                        (7 << EXYNOS4_YUV_422_IP_SHIFT)
-#define EXYNOS4_YUV_422_IP_YUV_422_1P_IMG      (4 << EXYNOS4_YUV_422_IP_SHIFT)
-#define EXYNOS4_YUV_422_IP_YUV_422_2P_IMG      (5 << EXYNOS4_YUV_422_IP_SHIFT)
-#define EXYNOS4_YUV_422_IP_YUV_422_3P_IMG      (6 << EXYNOS4_YUV_422_IP_SHIFT)
-
-#define EXYNOS4_YUV_420_IP_SHIFT               15
-#define EXYNOS4_YUV_420_IP_MASK                        (7 << EXYNOS4_YUV_420_IP_SHIFT)
-#define EXYNOS4_YUV_420_IP_YUV_420_2P_IMG      (4 << EXYNOS4_YUV_420_IP_SHIFT)
-#define EXYNOS4_YUV_420_IP_YUV_420_3P_IMG      (5 << EXYNOS4_YUV_420_IP_SHIFT)
-
-#define EXYNOS4_ENC_FMT_SHIFT                  24
-#define EXYNOS4_ENC_FMT_MASK                   (3 << EXYNOS4_ENC_FMT_SHIFT)
-#define EXYNOS5433_ENC_FMT_MASK                        (7 << EXYNOS4_ENC_FMT_SHIFT)
-
-#define EXYNOS4_ENC_FMT_GRAY                   (0 << EXYNOS4_ENC_FMT_SHIFT)
-#define EXYNOS4_ENC_FMT_YUV_444                        (1 << EXYNOS4_ENC_FMT_SHIFT)
-#define EXYNOS4_ENC_FMT_YUV_422                        (2 << EXYNOS4_ENC_FMT_SHIFT)
-#define EXYNOS4_ENC_FMT_YUV_420                        (3 << EXYNOS4_ENC_FMT_SHIFT)
-
-#define EXYNOS4_JPEG_DECODED_IMG_FMT_MASK      0x03
-
-#define EXYNOS4_SWAP_CHROMA_CRCB               (1 << 26)
-#define EXYNOS4_SWAP_CHROMA_CBCR               (0 << 26)
-#define EXYNOS5433_SWAP_CHROMA_CRCB            (1 << 27)
-#define EXYNOS5433_SWAP_CHROMA_CBCR            (0 << 27)
-
-/* JPEG HUFF count Register bit */
-#define EXYNOS4_HUFF_COUNT_MASK                        0xffff
-
-/* JPEG Decoded_img_x_y_size Register bit */
-#define EXYNOS4_DECODED_SIZE_MASK              0x0000ffff
-
-/* JPEG Decoded image format Register bit */
-#define EXYNOS4_DECODED_IMG_FMT_MASK           0x3
-
-/* JPEG TBL SEL Register bit */
-#define EXYNOS4_Q_TBL_COMP(c, n)       ((n) << (((c) - 1) << 1))
-
-#define EXYNOS4_Q_TBL_COMP1_0          EXYNOS4_Q_TBL_COMP(1, 0)
-#define EXYNOS4_Q_TBL_COMP1_1          EXYNOS4_Q_TBL_COMP(1, 1)
-#define EXYNOS4_Q_TBL_COMP1_2          EXYNOS4_Q_TBL_COMP(1, 2)
-#define EXYNOS4_Q_TBL_COMP1_3          EXYNOS4_Q_TBL_COMP(1, 3)
-
-#define EXYNOS4_Q_TBL_COMP2_0          EXYNOS4_Q_TBL_COMP(2, 0)
-#define EXYNOS4_Q_TBL_COMP2_1          EXYNOS4_Q_TBL_COMP(2, 1)
-#define EXYNOS4_Q_TBL_COMP2_2          EXYNOS4_Q_TBL_COMP(2, 2)
-#define EXYNOS4_Q_TBL_COMP2_3          EXYNOS4_Q_TBL_COMP(2, 3)
-
-#define EXYNOS4_Q_TBL_COMP3_0          EXYNOS4_Q_TBL_COMP(3, 0)
-#define EXYNOS4_Q_TBL_COMP3_1          EXYNOS4_Q_TBL_COMP(3, 1)
-#define EXYNOS4_Q_TBL_COMP3_2          EXYNOS4_Q_TBL_COMP(3, 2)
-#define EXYNOS4_Q_TBL_COMP3_3          EXYNOS4_Q_TBL_COMP(3, 3)
-
-#define EXYNOS4_HUFF_TBL_COMP(c, n)    ((n) << ((((c) - 1) << 1) + 6))
-
-#define EXYNOS4_HUFF_TBL_COMP1_AC_0_DC_0       \
-       EXYNOS4_HUFF_TBL_COMP(1, 0)
-#define EXYNOS4_HUFF_TBL_COMP1_AC_0_DC_1       \
-       EXYNOS4_HUFF_TBL_COMP(1, 1)
-#define EXYNOS4_HUFF_TBL_COMP1_AC_1_DC_0       \
-       EXYNOS4_HUFF_TBL_COMP(1, 2)
-#define EXYNOS4_HUFF_TBL_COMP1_AC_1_DC_1       \
-       EXYNOS4_HUFF_TBL_COMP(1, 3)
-
-#define EXYNOS4_HUFF_TBL_COMP2_AC_0_DC_0       \
-       EXYNOS4_HUFF_TBL_COMP(2, 0)
-#define EXYNOS4_HUFF_TBL_COMP2_AC_0_DC_1       \
-       EXYNOS4_HUFF_TBL_COMP(2, 1)
-#define EXYNOS4_HUFF_TBL_COMP2_AC_1_DC_0       \
-       EXYNOS4_HUFF_TBL_COMP(2, 2)
-#define EXYNOS4_HUFF_TBL_COMP2_AC_1_DC_1       \
-       EXYNOS4_HUFF_TBL_COMP(2, 3)
-
-#define EXYNOS4_HUFF_TBL_COMP3_AC_0_DC_0       \
-       EXYNOS4_HUFF_TBL_COMP(3, 0)
-#define EXYNOS4_HUFF_TBL_COMP3_AC_0_DC_1       \
-       EXYNOS4_HUFF_TBL_COMP(3, 1)
-#define EXYNOS4_HUFF_TBL_COMP3_AC_1_DC_0       \
-       EXYNOS4_HUFF_TBL_COMP(3, 2)
-#define EXYNOS4_HUFF_TBL_COMP3_AC_1_DC_1       \
-       EXYNOS4_HUFF_TBL_COMP(3, 3)
-
-#define EXYNOS4_NF_SHIFT                       16
-#define EXYNOS4_NF_MASK                                0xff
-#define EXYNOS4_NF(x)                          \
-       (((x) & EXYNOS4_NF_MASK) << EXYNOS4_NF_SHIFT)
-
-/* JPEG quantizer table register */
-#define EXYNOS4_QTBL_CONTENT(n)        (0x100 + (n) * 0x40)
-
-/* JPEG DC luminance (code length) Huffman table register */
-#define EXYNOS4_HUFF_TBL_HDCLL 0x200
-
-/* JPEG DC luminance (values) Huffman table register */
-#define EXYNOS4_HUFF_TBL_HDCLV 0x210
-
-/* JPEG DC chrominance (code length) Huffman table register */
-#define EXYNOS4_HUFF_TBL_HDCCL 0x220
-
-/* JPEG DC chrominance (values) Huffman table register */
-#define EXYNOS4_HUFF_TBL_HDCCV 0x230
-
-/* JPEG AC luminance (code length) Huffman table register */
-#define EXYNOS4_HUFF_TBL_HACLL 0x240
-
-/* JPEG AC luminance (values) Huffman table register */
-#define EXYNOS4_HUFF_TBL_HACLV 0x250
-
-/* JPEG AC chrominance (code length) Huffman table register */
-#define EXYNOS4_HUFF_TBL_HACCL 0x300
-
-/* JPEG AC chrominance (values) Huffman table register */
-#define EXYNOS4_HUFF_TBL_HACCV 0x310
-
-/* Register and bit definitions for Exynos 3250 */
-
-/* JPEG mode register */
-#define EXYNOS3250_JPGMOD                      0x00
-#define EXYNOS3250_PROC_MODE_MASK              (0x1 << 3)
-#define EXYNOS3250_PROC_MODE_DECOMPR           (0x1 << 3)
-#define EXYNOS3250_PROC_MODE_COMPR             (0x0 << 3)
-#define EXYNOS3250_SUBSAMPLING_MODE_MASK       (0x7 << 0)
-#define EXYNOS3250_SUBSAMPLING_MODE_444                (0x0 << 0)
-#define EXYNOS3250_SUBSAMPLING_MODE_422                (0x1 << 0)
-#define EXYNOS3250_SUBSAMPLING_MODE_420                (0x2 << 0)
-#define EXYNOS3250_SUBSAMPLING_MODE_411                (0x6 << 0)
-#define EXYNOS3250_SUBSAMPLING_MODE_GRAY       (0x3 << 0)
-
-/* JPEG operation status register */
-#define EXYNOS3250_JPGOPR                      0x04
-#define EXYNOS3250_JPGOPR_MASK                 0x01
-
-/* Quantization and Huffman tables register */
-#define EXYNOS3250_QHTBL                       0x08
-#define EXYNOS3250_QT_NUM_SHIFT(t)             ((((t) - 1) << 1) + 8)
-#define EXYNOS3250_QT_NUM_MASK(t)              (0x3 << EXYNOS3250_QT_NUM_SHIFT(t))
-
-/* Huffman tables */
-#define EXYNOS3250_HT_NUM_AC_SHIFT(t)          (((t) << 1) - 1)
-#define EXYNOS3250_HT_NUM_AC_MASK(t)           (0x1 << EXYNOS3250_HT_NUM_AC_SHIFT(t))
-
-#define EXYNOS3250_HT_NUM_DC_SHIFT(t)          (((t) - 1) << 1)
-#define EXYNOS3250_HT_NUM_DC_MASK(t)           (0x1 << EXYNOS3250_HT_NUM_DC_SHIFT(t))
-
-/* JPEG restart interval register */
-#define EXYNOS3250_JPGDRI                      0x0c
-#define EXYNOS3250_JPGDRI_MASK                 0xffff
-
-/* JPEG vertical resolution register */
-#define EXYNOS3250_JPGY                                0x10
-#define EXYNOS3250_JPGY_MASK                   0xffff
-
-/* JPEG horizontal resolution register */
-#define EXYNOS3250_JPGX                                0x14
-#define EXYNOS3250_JPGX_MASK                   0xffff
-
-/* JPEG byte count register */
-#define EXYNOS3250_JPGCNT                      0x18
-#define EXYNOS3250_JPGCNT_MASK                 0xffffff
-
-/* JPEG interrupt mask register */
-#define EXYNOS3250_JPGINTSE                    0x1c
-#define EXYNOS3250_JPEG_DONE_EN                        (1 << 11)
-#define EXYNOS3250_WDMA_DONE_EN                        (1 << 10)
-#define EXYNOS3250_RDMA_DONE_EN                        (1 << 9)
-#define EXYNOS3250_ENC_STREAM_INT_EN           (1 << 8)
-#define EXYNOS3250_CORE_DONE_EN                        (1 << 5)
-#define EXYNOS3250_ERR_INT_EN                  (1 << 4)
-#define EXYNOS3250_HEAD_INT_EN                 (1 << 3)
-
-/* JPEG interrupt status register */
-#define EXYNOS3250_JPGINTST                    0x20
-#define EXYNOS3250_JPEG_DONE                   (1 << 11)
-#define EXYNOS3250_WDMA_DONE                   (1 << 10)
-#define EXYNOS3250_RDMA_DONE                   (1 << 9)
-#define EXYNOS3250_ENC_STREAM_STAT             (1 << 8)
-#define EXYNOS3250_RESULT_STAT                 (1 << 5)
-#define EXYNOS3250_STREAM_STAT                 (1 << 4)
-#define EXYNOS3250_HEADER_STAT                 (1 << 3)
-
-/*
- * Base address of the luma component DMA buffer
- * of the raw input or output image.
- */
-#define EXYNOS3250_LUMA_BASE                   0x100
-#define EXYNOS3250_SRC_TILE_EN_MASK            0x100
-
-/* Stride of source or destination luma raw image buffer */
-#define EXYNOS3250_LUMA_STRIDE                 0x104
-
-/* Horizontal/vertical offset of active region in luma raw image buffer */
-#define EXYNOS3250_LUMA_XY_OFFSET              0x108
-#define EXYNOS3250_LUMA_YY_OFFSET_SHIFT                18
-#define EXYNOS3250_LUMA_YY_OFFSET_MASK         (0x1fff << EXYNOS3250_LUMA_YY_OFFSET_SHIFT)
-#define EXYNOS3250_LUMA_YX_OFFSET_SHIFT                2
-#define EXYNOS3250_LUMA_YX_OFFSET_MASK         (0x1fff << EXYNOS3250_LUMA_YX_OFFSET_SHIFT)
-
-/*
- * Base address of the chroma(Cb) component DMA buffer
- * of the raw input or output image.
- */
-#define EXYNOS3250_CHROMA_BASE                 0x10c
-
-/* Stride of source or destination chroma(Cb) raw image buffer */
-#define EXYNOS3250_CHROMA_STRIDE               0x110
-
-/* Horizontal/vertical offset of active region in chroma(Cb) raw image buffer */
-#define EXYNOS3250_CHROMA_XY_OFFSET            0x114
-#define EXYNOS3250_CHROMA_YY_OFFSET_SHIFT      18
-#define EXYNOS3250_CHROMA_YY_OFFSET_MASK       (0x1fff << EXYNOS3250_CHROMA_YY_OFFSET_SHIFT)
-#define EXYNOS3250_CHROMA_YX_OFFSET_SHIFT      2
-#define EXYNOS3250_CHROMA_YX_OFFSET_MASK       (0x1fff << EXYNOS3250_CHROMA_YX_OFFSET_SHIFT)
-
-/*
- * Base address of the chroma(Cr) component DMA buffer
- * of the raw input or output image.
- */
-#define EXYNOS3250_CHROMA_CR_BASE              0x118
-
-/* Stride of source or destination chroma(Cr) raw image buffer */
-#define EXYNOS3250_CHROMA_CR_STRIDE            0x11c
-
-/* Horizontal/vertical offset of active region in chroma(Cb) raw image buffer */
-#define EXYNOS3250_CHROMA_CR_XY_OFFSET         0x120
-#define EXYNOS3250_CHROMA_CR_YY_OFFSET_SHIFT   18
-#define EXYNOS3250_CHROMA_CR_YY_OFFSET_MASK    (0x1fff << EXYNOS3250_CHROMA_CR_YY_OFFSET_SHIFT)
-#define EXYNOS3250_CHROMA_CR_YX_OFFSET_SHIFT   2
-#define EXYNOS3250_CHROMA_CR_YX_OFFSET_MASK    (0x1fff << EXYNOS3250_CHROMA_CR_YX_OFFSET_SHIFT)
-
-/* Raw image data r/w address register */
-#define EXYNOS3250_JPG_IMGADR                  0x50
-
-/* Source or destination JPEG file DMA buffer address */
-#define EXYNOS3250_JPG_JPGADR                  0x124
-
-/* Coefficients for RGB-to-YCbCr converter register */
-#define EXYNOS3250_JPG_COEF(n)                 (0x128 + (((n) - 1) << 2))
-#define EXYNOS3250_COEF_SHIFT(j)               ((3 - (j)) << 3)
-#define EXYNOS3250_COEF_MASK(j)                        (0xff << EXYNOS3250_COEF_SHIFT(j))
-
-/* Raw input format setting */
-#define EXYNOS3250_JPGCMOD                     0x134
-#define EXYNOS3250_SRC_TILE_EN                 (0x1 << 10)
-#define EXYNOS3250_SRC_NV_MASK                 (0x1 << 9)
-#define EXYNOS3250_SRC_NV12                    (0x0 << 9)
-#define EXYNOS3250_SRC_NV21                    (0x1 << 9)
-#define EXYNOS3250_SRC_BIG_ENDIAN_MASK         (0x1 << 8)
-#define EXYNOS3250_SRC_BIG_ENDIAN              (0x1 << 8)
-#define EXYNOS3250_MODE_SEL_MASK               (0x7 << 5)
-#define EXYNOS3250_MODE_SEL_420_2P             (0x0 << 5)
-#define EXYNOS3250_MODE_SEL_422_1P_LUM_CHR     (0x1 << 5)
-#define EXYNOS3250_MODE_SEL_RGB565             (0x2 << 5)
-#define EXYNOS3250_MODE_SEL_422_1P_CHR_LUM     (0x3 << 5)
-#define EXYNOS3250_MODE_SEL_ARGB8888           (0x4 << 5)
-#define EXYNOS3250_MODE_SEL_420_3P             (0x5 << 5)
-#define EXYNOS3250_SRC_SWAP_RGB                        (0x1 << 3)
-#define EXYNOS3250_SRC_SWAP_UV                 (0x1 << 2)
-#define EXYNOS3250_MODE_Y16_MASK               (0x1 << 1)
-#define EXYNOS3250_MODE_Y16                    (0x1 << 1)
-#define EXYNOS3250_HALF_EN_MASK                        (0x1 << 0)
-#define EXYNOS3250_HALF_EN                     (0x1 << 0)
-
-/* Power on/off and clock down control */
-#define EXYNOS3250_JPGCLKCON                   0x138
-#define EXYNOS3250_CLK_DOWN_READY              (0x1 << 1)
-#define EXYNOS3250_POWER_ON                    (0x1 << 0)
-
-/* Start compression or decompression */
-#define EXYNOS3250_JSTART                      0x13c
-
-/* Restart decompression after header analysis */
-#define EXYNOS3250_JRSTART                     0x140
-
-/* JPEG SW reset register */
-#define EXYNOS3250_SW_RESET                    0x144
-
-/* JPEG timer setting register */
-#define EXYNOS3250_TIMER_SE                    0x148
-#define EXYNOS3250_TIMER_INT_EN_SHIFT          31
-#define EXYNOS3250_TIMER_INT_EN                        (1UL << EXYNOS3250_TIMER_INT_EN_SHIFT)
-#define EXYNOS3250_TIMER_INIT_MASK             0x7fffffff
-
-/* JPEG timer status register */
-#define EXYNOS3250_TIMER_ST                    0x14c
-#define EXYNOS3250_TIMER_INT_STAT_SHIFT                31
-#define EXYNOS3250_TIMER_INT_STAT              (1UL << EXYNOS3250_TIMER_INT_STAT_SHIFT)
-#define EXYNOS3250_TIMER_CNT_SHIFT             0
-#define EXYNOS3250_TIMER_CNT_MASK              0x7fffffff
-
-/* Command status register */
-#define EXYNOS3250_COMSTAT                     0x150
-#define EXYNOS3250_CUR_PROC_MODE               (0x1 << 1)
-#define EXYNOS3250_CUR_COM_MODE                        (0x1 << 0)
-
-/* JPEG decompression output format register */
-#define EXYNOS3250_OUTFORM                     0x154
-#define EXYNOS3250_OUT_ALPHA_MASK              (0xff << 24)
-#define EXYNOS3250_OUT_TILE_EN                 (0x1 << 10)
-#define EXYNOS3250_OUT_NV_MASK                 (0x1 << 9)
-#define EXYNOS3250_OUT_NV12                    (0x0 << 9)
-#define EXYNOS3250_OUT_NV21                    (0x1 << 9)
-#define EXYNOS3250_OUT_BIG_ENDIAN_MASK         (0x1 << 8)
-#define EXYNOS3250_OUT_BIG_ENDIAN              (0x1 << 8)
-#define EXYNOS3250_OUT_SWAP_RGB                        (0x1 << 7)
-#define EXYNOS3250_OUT_SWAP_UV                 (0x1 << 6)
-#define EXYNOS3250_OUT_FMT_MASK                        (0x7 << 0)
-#define EXYNOS3250_OUT_FMT_420_2P              (0x0 << 0)
-#define EXYNOS3250_OUT_FMT_422_1P_LUM_CHR      (0x1 << 0)
-#define EXYNOS3250_OUT_FMT_422_1P_CHR_LUM      (0x3 << 0)
-#define EXYNOS3250_OUT_FMT_420_3P              (0x4 << 0)
-#define EXYNOS3250_OUT_FMT_RGB565              (0x5 << 0)
-#define EXYNOS3250_OUT_FMT_ARGB8888            (0x6 << 0)
-
-/* Input JPEG stream byte size for decompression */
-#define EXYNOS3250_DEC_STREAM_SIZE             0x158
-#define EXYNOS3250_DEC_STREAM_MASK             0x1fffffff
-
-/* The upper bound of the byte size of output compressed stream */
-#define EXYNOS3250_ENC_STREAM_BOUND            0x15c
-#define EXYNOS3250_ENC_STREAM_BOUND_MASK       0xffffc0
-
-/* Scale-down ratio when decoding */
-#define EXYNOS3250_DEC_SCALING_RATIO           0x160
-#define EXYNOS3250_DEC_SCALE_FACTOR_MASK       0x3
-#define EXYNOS3250_DEC_SCALE_FACTOR_8_8                0x0
-#define EXYNOS3250_DEC_SCALE_FACTOR_4_8                0x1
-#define EXYNOS3250_DEC_SCALE_FACTOR_2_8                0x2
-#define EXYNOS3250_DEC_SCALE_FACTOR_1_8                0x3
-
-/* Error check */
-#define EXYNOS3250_CRC_RESULT                  0x164
-
-/* RDMA and WDMA operation status register */
-#define EXYNOS3250_DMA_OPER_STATUS             0x168
-#define EXYNOS3250_WDMA_OPER_STATUS            (0x1 << 1)
-#define EXYNOS3250_RDMA_OPER_STATUS            (0x1 << 0)
-
-/* DMA issue gathering number and issue number settings */
-#define EXYNOS3250_DMA_ISSUE_NUM               0x16c
-#define EXYNOS3250_WDMA_ISSUE_NUM_SHIFT                16
-#define EXYNOS3250_WDMA_ISSUE_NUM_MASK         (0x7 << EXYNOS3250_WDMA_ISSUE_NUM_SHIFT)
-#define EXYNOS3250_RDMA_ISSUE_NUM_SHIFT                8
-#define EXYNOS3250_RDMA_ISSUE_NUM_MASK         (0x7 << EXYNOS3250_RDMA_ISSUE_NUM_SHIFT)
-#define EXYNOS3250_ISSUE_GATHER_NUM_SHIFT      0
-#define EXYNOS3250_ISSUE_GATHER_NUM_MASK       (0x7 << EXYNOS3250_ISSUE_GATHER_NUM_SHIFT)
-#define EXYNOS3250_DMA_MO_COUNT                        0x7
-
-/* Version register */
-#define EXYNOS3250_VERSION                     0x1fc
-
-/* RGB <-> YUV conversion coefficients */
-#define EXYNOS3250_JPEG_ENC_COEF1              0x01352e1e
-#define EXYNOS3250_JPEG_ENC_COEF2              0x00b0ae83
-#define EXYNOS3250_JPEG_ENC_COEF3              0x020cdc13
-
-#define EXYNOS3250_JPEG_DEC_COEF1              0x04a80199
-#define EXYNOS3250_JPEG_DEC_COEF2              0x04a9a064
-#define EXYNOS3250_JPEG_DEC_COEF3              0x04a80102
-
-#endif /* JPEG_REGS_H_ */
-
diff --git a/drivers/media/platform/samsung/s5p-jpeg/Kconfig b/drivers/media/platform/samsung/s5p-jpeg/Kconfig
new file mode 100644 (file)
index 0000000..e522860
--- /dev/null
@@ -0,0 +1,12 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+config VIDEO_SAMSUNG_S5P_JPEG
+       tristate "Samsung S5P/Exynos3250/Exynos4 JPEG codec driver"
+       depends on V4L_MEM2MEM_DRIVERS
+       depends on VIDEO_DEV && VIDEO_V4L2
+       depends on ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST
+       select VIDEOBUF2_DMA_CONTIG
+       select V4L2_MEM2MEM_DEV
+       help
+         This is a v4l2 driver for Samsung S5P, EXYNOS3250
+         and EXYNOS4 JPEG codec
diff --git a/drivers/media/platform/samsung/s5p-jpeg/Makefile b/drivers/media/platform/samsung/s5p-jpeg/Makefile
new file mode 100644 (file)
index 0000000..8b0f92e
--- /dev/null
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0-only
+s5p-jpeg-objs := jpeg-core.o jpeg-hw-exynos3250.o jpeg-hw-exynos4.o jpeg-hw-s5p.o
+obj-$(CONFIG_VIDEO_SAMSUNG_S5P_JPEG) += s5p-jpeg.o
diff --git a/drivers/media/platform/samsung/s5p-jpeg/jpeg-core.c b/drivers/media/platform/samsung/s5p-jpeg/jpeg-core.c
new file mode 100644 (file)
index 0000000..5479bc8
--- /dev/null
@@ -0,0 +1,3182 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* linux/drivers/media/platform/samsung/s5p-jpeg/jpeg-core.c
+ *
+ * Copyright (c) 2011-2014 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
+ * Author: Jacek Anaszewski <j.anaszewski@samsung.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/gfp.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-mem2mem.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-rect.h>
+#include <media/videobuf2-v4l2.h>
+#include <media/videobuf2-dma-contig.h>
+
+#include "jpeg-core.h"
+#include "jpeg-hw-s5p.h"
+#include "jpeg-hw-exynos4.h"
+#include "jpeg-hw-exynos3250.h"
+#include "jpeg-regs.h"
+
+static struct s5p_jpeg_fmt sjpeg_formats[] = {
+       {
+               .fourcc         = V4L2_PIX_FMT_JPEG,
+               .flags          = SJPEG_FMT_FLAG_ENC_CAPTURE |
+                                 SJPEG_FMT_FLAG_DEC_OUTPUT |
+                                 SJPEG_FMT_FLAG_S5P |
+                                 SJPEG_FMT_FLAG_EXYNOS3250 |
+                                 SJPEG_FMT_FLAG_EXYNOS4,
+       },
+       {
+               .fourcc         = V4L2_PIX_FMT_YUYV,
+               .depth          = 16,
+               .colplanes      = 1,
+               .h_align        = 4,
+               .v_align        = 3,
+               .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
+                                 SJPEG_FMT_FLAG_DEC_CAPTURE |
+                                 SJPEG_FMT_FLAG_S5P |
+                                 SJPEG_FMT_NON_RGB,
+               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
+       },
+       {
+               .fourcc         = V4L2_PIX_FMT_YUYV,
+               .depth          = 16,
+               .colplanes      = 1,
+               .h_align        = 1,
+               .v_align        = 0,
+               .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
+                                 SJPEG_FMT_FLAG_DEC_CAPTURE |
+                                 SJPEG_FMT_FLAG_EXYNOS4 |
+                                 SJPEG_FMT_NON_RGB,
+               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
+       },
+       {
+               .fourcc         = V4L2_PIX_FMT_YUYV,
+               .depth          = 16,
+               .colplanes      = 1,
+               .h_align        = 2,
+               .v_align        = 0,
+               .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
+                                 SJPEG_FMT_FLAG_DEC_CAPTURE |
+                                 SJPEG_FMT_FLAG_EXYNOS3250 |
+                                 SJPEG_FMT_NON_RGB,
+               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
+       },
+       {
+               .fourcc         = V4L2_PIX_FMT_YVYU,
+               .depth          = 16,
+               .colplanes      = 1,
+               .h_align        = 1,
+               .v_align        = 0,
+               .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
+                                 SJPEG_FMT_FLAG_DEC_CAPTURE |
+                                 SJPEG_FMT_FLAG_EXYNOS4 |
+                                 SJPEG_FMT_NON_RGB,
+               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
+       },
+       {
+               .fourcc         = V4L2_PIX_FMT_YVYU,
+               .depth          = 16,
+               .colplanes      = 1,
+               .h_align        = 2,
+               .v_align        = 0,
+               .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
+                                 SJPEG_FMT_FLAG_DEC_CAPTURE |
+                                 SJPEG_FMT_FLAG_EXYNOS3250 |
+                                 SJPEG_FMT_NON_RGB,
+               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
+       },
+       {
+               .fourcc         = V4L2_PIX_FMT_UYVY,
+               .depth          = 16,
+               .colplanes      = 1,
+               .h_align        = 2,
+               .v_align        = 0,
+               .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
+                                 SJPEG_FMT_FLAG_DEC_CAPTURE |
+                                 SJPEG_FMT_FLAG_EXYNOS3250 |
+                                 SJPEG_FMT_NON_RGB,
+               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
+       },
+       {
+               .fourcc         = V4L2_PIX_FMT_VYUY,
+               .depth          = 16,
+               .colplanes      = 1,
+               .h_align        = 2,
+               .v_align        = 0,
+               .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
+                                 SJPEG_FMT_FLAG_DEC_CAPTURE |
+                                 SJPEG_FMT_FLAG_EXYNOS3250 |
+                                 SJPEG_FMT_NON_RGB,
+               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
+       },
+       {
+               .fourcc         = V4L2_PIX_FMT_RGB565,
+               .depth          = 16,
+               .colplanes      = 1,
+               .h_align        = 0,
+               .v_align        = 0,
+               .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
+                                 SJPEG_FMT_FLAG_DEC_CAPTURE |
+                                 SJPEG_FMT_FLAG_EXYNOS4 |
+                                 SJPEG_FMT_RGB,
+               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
+       },
+       {
+               .fourcc         = V4L2_PIX_FMT_RGB565,
+               .depth          = 16,
+               .colplanes      = 1,
+               .h_align        = 2,
+               .v_align        = 0,
+               .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
+                                 SJPEG_FMT_FLAG_DEC_CAPTURE |
+                                 SJPEG_FMT_FLAG_EXYNOS3250 |
+                                 SJPEG_FMT_RGB,
+               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
+       },
+       {
+               .fourcc         = V4L2_PIX_FMT_RGB565X,
+               .depth          = 16,
+               .colplanes      = 1,
+               .h_align        = 2,
+               .v_align        = 0,
+               .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
+                                 SJPEG_FMT_FLAG_DEC_CAPTURE |
+                                 SJPEG_FMT_FLAG_EXYNOS3250 |
+                                 SJPEG_FMT_RGB,
+               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
+       },
+       {
+               .fourcc         = V4L2_PIX_FMT_RGB565,
+               .depth          = 16,
+               .colplanes      = 1,
+               .h_align        = 0,
+               .v_align        = 0,
+               .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
+                                 SJPEG_FMT_FLAG_S5P |
+                                 SJPEG_FMT_RGB,
+               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
+       },
+       {
+               .fourcc         = V4L2_PIX_FMT_RGB32,
+               .depth          = 32,
+               .colplanes      = 1,
+               .h_align        = 0,
+               .v_align        = 0,
+               .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
+                                 SJPEG_FMT_FLAG_DEC_CAPTURE |
+                                 SJPEG_FMT_FLAG_EXYNOS4 |
+                                 SJPEG_FMT_RGB,
+               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
+       },
+       {
+               .fourcc         = V4L2_PIX_FMT_RGB32,
+               .depth          = 32,
+               .colplanes      = 1,
+               .h_align        = 2,
+               .v_align        = 0,
+               .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
+                                 SJPEG_FMT_FLAG_DEC_CAPTURE |
+                                 SJPEG_FMT_FLAG_EXYNOS3250 |
+                                 SJPEG_FMT_RGB,
+               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
+       },
+       {
+               .fourcc         = V4L2_PIX_FMT_NV24,
+               .depth          = 24,
+               .colplanes      = 2,
+               .h_align        = 0,
+               .v_align        = 0,
+               .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
+                                 SJPEG_FMT_FLAG_DEC_CAPTURE |
+                                 SJPEG_FMT_FLAG_EXYNOS4 |
+                                 SJPEG_FMT_NON_RGB,
+               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
+       },
+       {
+               .fourcc         = V4L2_PIX_FMT_NV42,
+               .depth          = 24,
+               .colplanes      = 2,
+               .h_align        = 0,
+               .v_align        = 0,
+               .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
+                                 SJPEG_FMT_FLAG_DEC_CAPTURE |
+                                 SJPEG_FMT_FLAG_EXYNOS4 |
+                                 SJPEG_FMT_NON_RGB,
+               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_444,
+       },
+       {
+               .fourcc         = V4L2_PIX_FMT_NV61,
+               .depth          = 16,
+               .colplanes      = 2,
+               .h_align        = 1,
+               .v_align        = 0,
+               .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
+                                 SJPEG_FMT_FLAG_DEC_CAPTURE |
+                                 SJPEG_FMT_FLAG_EXYNOS4 |
+                                 SJPEG_FMT_NON_RGB,
+               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
+       },
+       {
+               .fourcc         = V4L2_PIX_FMT_NV16,
+               .depth          = 16,
+               .colplanes      = 2,
+               .h_align        = 1,
+               .v_align        = 0,
+               .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
+                                 SJPEG_FMT_FLAG_DEC_CAPTURE |
+                                 SJPEG_FMT_FLAG_EXYNOS4 |
+                                 SJPEG_FMT_NON_RGB,
+               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
+       },
+       {
+               .fourcc         = V4L2_PIX_FMT_NV12,
+               .depth          = 12,
+               .colplanes      = 2,
+               .h_align        = 1,
+               .v_align        = 1,
+               .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
+                                 SJPEG_FMT_FLAG_DEC_CAPTURE |
+                                 SJPEG_FMT_FLAG_EXYNOS4 |
+                                 SJPEG_FMT_NON_RGB,
+               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
+       },
+       {
+               .fourcc         = V4L2_PIX_FMT_NV12,
+               .depth          = 12,
+               .colplanes      = 2,
+               .h_align        = 3,
+               .v_align        = 3,
+               .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
+                                 SJPEG_FMT_FLAG_DEC_CAPTURE |
+                                 SJPEG_FMT_FLAG_EXYNOS3250 |
+                                 SJPEG_FMT_NON_RGB,
+               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
+       },
+       {
+               .fourcc         = V4L2_PIX_FMT_NV12,
+               .depth          = 12,
+               .colplanes      = 2,
+               .h_align        = 4,
+               .v_align        = 4,
+               .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
+                                 SJPEG_FMT_FLAG_DEC_CAPTURE |
+                                 SJPEG_FMT_FLAG_S5P |
+                                 SJPEG_FMT_NON_RGB,
+               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
+       },
+       {
+               .fourcc         = V4L2_PIX_FMT_NV21,
+               .depth          = 12,
+               .colplanes      = 2,
+               .h_align        = 3,
+               .v_align        = 3,
+               .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
+                                 SJPEG_FMT_FLAG_DEC_CAPTURE |
+                                 SJPEG_FMT_FLAG_EXYNOS3250 |
+                                 SJPEG_FMT_NON_RGB,
+               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
+       },
+       {
+               .fourcc         = V4L2_PIX_FMT_NV21,
+               .depth          = 12,
+               .colplanes      = 2,
+               .h_align        = 1,
+               .v_align        = 1,
+               .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
+                                 SJPEG_FMT_FLAG_DEC_CAPTURE |
+                                 SJPEG_FMT_FLAG_EXYNOS3250 |
+                                 SJPEG_FMT_FLAG_EXYNOS4 |
+                                 SJPEG_FMT_NON_RGB,
+               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
+       },
+       {
+               .fourcc         = V4L2_PIX_FMT_YUV420,
+               .depth          = 12,
+               .colplanes      = 3,
+               .h_align        = 1,
+               .v_align        = 1,
+               .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
+                                 SJPEG_FMT_FLAG_DEC_CAPTURE |
+                                 SJPEG_FMT_FLAG_EXYNOS4 |
+                                 SJPEG_FMT_NON_RGB,
+               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
+       },
+       {
+               .fourcc         = V4L2_PIX_FMT_YUV420,
+               .depth          = 12,
+               .colplanes      = 3,
+               .h_align        = 4,
+               .v_align        = 4,
+               .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
+                                 SJPEG_FMT_FLAG_DEC_CAPTURE |
+                                 SJPEG_FMT_FLAG_EXYNOS3250 |
+                                 SJPEG_FMT_NON_RGB,
+               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
+       },
+       {
+               .fourcc         = V4L2_PIX_FMT_GREY,
+               .depth          = 8,
+               .colplanes      = 1,
+               .flags          = SJPEG_FMT_FLAG_ENC_OUTPUT |
+                                 SJPEG_FMT_FLAG_DEC_CAPTURE |
+                                 SJPEG_FMT_FLAG_EXYNOS4 |
+                                 SJPEG_FMT_NON_RGB,
+               .subsampling    = V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY,
+       },
+};
+#define SJPEG_NUM_FORMATS ARRAY_SIZE(sjpeg_formats)
+
+static const unsigned char qtbl_luminance[4][64] = {
+       {/*level 0 - high compression quality */
+               20, 16, 25, 39, 50, 46, 62, 68,
+               16, 18, 23, 38, 38, 53, 65, 68,
+               25, 23, 31, 38, 53, 65, 68, 68,
+               39, 38, 38, 53, 65, 68, 68, 68,
+               50, 38, 53, 65, 68, 68, 68, 68,
+               46, 53, 65, 68, 68, 68, 68, 68,
+               62, 65, 68, 68, 68, 68, 68, 68,
+               68, 68, 68, 68, 68, 68, 68, 68
+       },
+       {/* level 1 */
+               16, 11, 11, 16, 23, 27, 31, 30,
+               11, 12, 12, 15, 20, 23, 23, 30,
+               11, 12, 13, 16, 23, 26, 35, 47,
+               16, 15, 16, 23, 26, 37, 47, 64,
+               23, 20, 23, 26, 39, 51, 64, 64,
+               27, 23, 26, 37, 51, 64, 64, 64,
+               31, 23, 35, 47, 64, 64, 64, 64,
+               30, 30, 47, 64, 64, 64, 64, 64
+       },
+       {/* level 2 */
+               12,  8,  8, 12, 17, 21, 24, 23,
+                8,  9,  9, 11, 15, 19, 18, 23,
+                8,  9, 10, 12, 19, 20, 27, 36,
+               12, 11, 12, 21, 20, 28, 36, 53,
+               17, 15, 19, 20, 30, 39, 51, 59,
+               21, 19, 20, 28, 39, 51, 59, 59,
+               24, 18, 27, 36, 51, 59, 59, 59,
+               23, 23, 36, 53, 59, 59, 59, 59
+       },
+       {/* level 3 - low compression quality */
+                8,  6,  6,  8, 12, 14, 16, 17,
+                6,  6,  6,  8, 10, 13, 12, 15,
+                6,  6,  7,  8, 13, 14, 18, 24,
+                8,  8,  8, 14, 13, 19, 24, 35,
+               12, 10, 13, 13, 20, 26, 34, 39,
+               14, 13, 14, 19, 26, 34, 39, 39,
+               16, 12, 18, 24, 34, 39, 39, 39,
+               17, 15, 24, 35, 39, 39, 39, 39
+       }
+};
+
+static const unsigned char qtbl_chrominance[4][64] = {
+       {/*level 0 - high compression quality */
+               21, 25, 32, 38, 54, 68, 68, 68,
+               25, 28, 24, 38, 54, 68, 68, 68,
+               32, 24, 32, 43, 66, 68, 68, 68,
+               38, 38, 43, 53, 68, 68, 68, 68,
+               54, 54, 66, 68, 68, 68, 68, 68,
+               68, 68, 68, 68, 68, 68, 68, 68,
+               68, 68, 68, 68, 68, 68, 68, 68,
+               68, 68, 68, 68, 68, 68, 68, 68
+       },
+       {/* level 1 */
+               17, 15, 17, 21, 20, 26, 38, 48,
+               15, 19, 18, 17, 20, 26, 35, 43,
+               17, 18, 20, 22, 26, 30, 46, 53,
+               21, 17, 22, 28, 30, 39, 53, 64,
+               20, 20, 26, 30, 39, 48, 64, 64,
+               26, 26, 30, 39, 48, 63, 64, 64,
+               38, 35, 46, 53, 64, 64, 64, 64,
+               48, 43, 53, 64, 64, 64, 64, 64
+       },
+       {/* level 2 */
+               13, 11, 13, 16, 20, 20, 29, 37,
+               11, 14, 14, 14, 16, 20, 26, 32,
+               13, 14, 15, 17, 20, 23, 35, 40,
+               16, 14, 17, 21, 23, 30, 40, 50,
+               20, 16, 20, 23, 30, 37, 50, 59,
+               20, 20, 23, 30, 37, 48, 59, 59,
+               29, 26, 35, 40, 50, 59, 59, 59,
+               37, 32, 40, 50, 59, 59, 59, 59
+       },
+       {/* level 3 - low compression quality */
+                9,  8,  9, 11, 14, 17, 19, 24,
+                8, 10,  9, 11, 14, 13, 17, 22,
+                9,  9, 13, 14, 13, 15, 23, 26,
+               11, 11, 14, 14, 15, 20, 26, 33,
+               14, 14, 13, 15, 20, 24, 33, 39,
+               17, 13, 15, 20, 24, 32, 39, 39,
+               19, 17, 23, 26, 33, 39, 39, 39,
+               24, 22, 26, 33, 39, 39, 39, 39
+       }
+};
+
+static const unsigned char hdctbl0[16] = {
+       0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0
+};
+
+static const unsigned char hdctblg0[12] = {
+       0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb
+};
+static const unsigned char hactbl0[16] = {
+       0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d
+};
+static const unsigned char hactblg0[162] = {
+       0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
+       0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
+       0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
+       0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
+       0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
+       0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
+       0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+       0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
+       0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
+       0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
+       0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
+       0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
+       0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
+       0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+       0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
+       0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
+       0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
+       0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
+       0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
+       0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+       0xf9, 0xfa
+};
+
+/*
+ * Fourcc downgrade schema lookup tables for 422 and 420
+ * chroma subsampling - fourcc on each position maps on the
+ * fourcc from the table fourcc_to_dwngrd_schema_id which allows
+ * to get the most suitable fourcc counterpart for the given
+ * downgraded subsampling property.
+ */
+static const u32 subs422_fourcc_dwngrd_schema[] = {
+       V4L2_PIX_FMT_NV16,
+       V4L2_PIX_FMT_NV61,
+};
+
+static const u32 subs420_fourcc_dwngrd_schema[] = {
+       V4L2_PIX_FMT_NV12,
+       V4L2_PIX_FMT_NV21,
+       V4L2_PIX_FMT_NV12,
+       V4L2_PIX_FMT_NV21,
+       V4L2_PIX_FMT_NV12,
+       V4L2_PIX_FMT_NV21,
+       V4L2_PIX_FMT_GREY,
+       V4L2_PIX_FMT_GREY,
+       V4L2_PIX_FMT_GREY,
+       V4L2_PIX_FMT_GREY,
+};
+
+/*
+ * Lookup table for translation of a fourcc to the position
+ * of its downgraded counterpart in the *fourcc_dwngrd_schema
+ * tables.
+ */
+static const u32 fourcc_to_dwngrd_schema_id[] = {
+       V4L2_PIX_FMT_NV24,
+       V4L2_PIX_FMT_NV42,
+       V4L2_PIX_FMT_NV16,
+       V4L2_PIX_FMT_NV61,
+       V4L2_PIX_FMT_YUYV,
+       V4L2_PIX_FMT_YVYU,
+       V4L2_PIX_FMT_NV12,
+       V4L2_PIX_FMT_NV21,
+       V4L2_PIX_FMT_YUV420,
+       V4L2_PIX_FMT_GREY,
+};
+
+static int s5p_jpeg_get_dwngrd_sch_id_by_fourcc(u32 fourcc)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(fourcc_to_dwngrd_schema_id); ++i) {
+               if (fourcc_to_dwngrd_schema_id[i] == fourcc)
+                       return i;
+       }
+
+       return -EINVAL;
+}
+
+static int s5p_jpeg_adjust_fourcc_to_subsampling(
+                                       enum v4l2_jpeg_chroma_subsampling subs,
+                                       u32 in_fourcc,
+                                       u32 *out_fourcc,
+                                       struct s5p_jpeg_ctx *ctx)
+{
+       int dwngrd_sch_id;
+
+       if (ctx->subsampling != V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY) {
+               dwngrd_sch_id =
+                       s5p_jpeg_get_dwngrd_sch_id_by_fourcc(in_fourcc);
+               if (dwngrd_sch_id < 0)
+                       return -EINVAL;
+       }
+
+       switch (ctx->subsampling) {
+       case V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY:
+               *out_fourcc = V4L2_PIX_FMT_GREY;
+               break;
+       case V4L2_JPEG_CHROMA_SUBSAMPLING_420:
+               if (dwngrd_sch_id >
+                               ARRAY_SIZE(subs420_fourcc_dwngrd_schema) - 1)
+                       return -EINVAL;
+               *out_fourcc = subs420_fourcc_dwngrd_schema[dwngrd_sch_id];
+               break;
+       case V4L2_JPEG_CHROMA_SUBSAMPLING_422:
+               if (dwngrd_sch_id >
+                               ARRAY_SIZE(subs422_fourcc_dwngrd_schema) - 1)
+                       return -EINVAL;
+               *out_fourcc = subs422_fourcc_dwngrd_schema[dwngrd_sch_id];
+               break;
+       default:
+               *out_fourcc = V4L2_PIX_FMT_GREY;
+               break;
+       }
+
+       return 0;
+}
+
+static int exynos4x12_decoded_subsampling[] = {
+       V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY,
+       V4L2_JPEG_CHROMA_SUBSAMPLING_444,
+       V4L2_JPEG_CHROMA_SUBSAMPLING_422,
+       V4L2_JPEG_CHROMA_SUBSAMPLING_420,
+};
+
+static int exynos3250_decoded_subsampling[] = {
+       V4L2_JPEG_CHROMA_SUBSAMPLING_444,
+       V4L2_JPEG_CHROMA_SUBSAMPLING_422,
+       V4L2_JPEG_CHROMA_SUBSAMPLING_420,
+       V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY,
+       -1,
+       -1,
+       V4L2_JPEG_CHROMA_SUBSAMPLING_411,
+};
+
+static inline struct s5p_jpeg_ctx *ctrl_to_ctx(struct v4l2_ctrl *c)
+{
+       return container_of(c->handler, struct s5p_jpeg_ctx, ctrl_handler);
+}
+
+static inline struct s5p_jpeg_ctx *fh_to_ctx(struct v4l2_fh *fh)
+{
+       return container_of(fh, struct s5p_jpeg_ctx, fh);
+}
+
+static int s5p_jpeg_to_user_subsampling(struct s5p_jpeg_ctx *ctx)
+{
+       switch (ctx->jpeg->variant->version) {
+       case SJPEG_S5P:
+               WARN_ON(ctx->subsampling > 3);
+               if (ctx->subsampling > 2)
+                       return V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY;
+               return ctx->subsampling;
+       case SJPEG_EXYNOS3250:
+       case SJPEG_EXYNOS5420:
+               WARN_ON(ctx->subsampling > 6);
+               if (ctx->subsampling > 3)
+                       return V4L2_JPEG_CHROMA_SUBSAMPLING_411;
+               return exynos3250_decoded_subsampling[ctx->subsampling];
+       case SJPEG_EXYNOS4:
+               WARN_ON(ctx->subsampling > 3);
+               if (ctx->subsampling > 2)
+                       return V4L2_JPEG_CHROMA_SUBSAMPLING_420;
+               return exynos4x12_decoded_subsampling[ctx->subsampling];
+       case SJPEG_EXYNOS5433:
+               return ctx->subsampling; /* parsed from header */
+       default:
+               WARN_ON(ctx->subsampling > 3);
+               return V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY;
+       }
+}
+
+static inline void s5p_jpeg_set_qtbl(void __iomem *regs,
+                                    const unsigned char *qtbl,
+                                    unsigned long tab, int len)
+{
+       int i;
+
+       for (i = 0; i < len; i++)
+               writel((unsigned int)qtbl[i], regs + tab + (i * 0x04));
+}
+
+static inline void s5p_jpeg_set_qtbl_lum(void __iomem *regs, int quality)
+{
+       /* this driver fills quantisation table 0 with data for luma */
+       s5p_jpeg_set_qtbl(regs, qtbl_luminance[quality],
+                         S5P_JPG_QTBL_CONTENT(0),
+                         ARRAY_SIZE(qtbl_luminance[quality]));
+}
+
+static inline void s5p_jpeg_set_qtbl_chr(void __iomem *regs, int quality)
+{
+       /* this driver fills quantisation table 1 with data for chroma */
+       s5p_jpeg_set_qtbl(regs, qtbl_chrominance[quality],
+                         S5P_JPG_QTBL_CONTENT(1),
+                         ARRAY_SIZE(qtbl_chrominance[quality]));
+}
+
+static inline void s5p_jpeg_set_htbl(void __iomem *regs,
+                                    const unsigned char *htbl,
+                                    unsigned long tab, int len)
+{
+       int i;
+
+       for (i = 0; i < len; i++)
+               writel((unsigned int)htbl[i], regs + tab + (i * 0x04));
+}
+
+static inline void s5p_jpeg_set_hdctbl(void __iomem *regs)
+{
+       /* this driver fills table 0 for this component */
+       s5p_jpeg_set_htbl(regs, hdctbl0, S5P_JPG_HDCTBL(0),
+                                               ARRAY_SIZE(hdctbl0));
+}
+
+static inline void s5p_jpeg_set_hdctblg(void __iomem *regs)
+{
+       /* this driver fills table 0 for this component */
+       s5p_jpeg_set_htbl(regs, hdctblg0, S5P_JPG_HDCTBLG(0),
+                                               ARRAY_SIZE(hdctblg0));
+}
+
+static inline void s5p_jpeg_set_hactbl(void __iomem *regs)
+{
+       /* this driver fills table 0 for this component */
+       s5p_jpeg_set_htbl(regs, hactbl0, S5P_JPG_HACTBL(0),
+                                               ARRAY_SIZE(hactbl0));
+}
+
+static inline void s5p_jpeg_set_hactblg(void __iomem *regs)
+{
+       /* this driver fills table 0 for this component */
+       s5p_jpeg_set_htbl(regs, hactblg0, S5P_JPG_HACTBLG(0),
+                                               ARRAY_SIZE(hactblg0));
+}
+
+static inline void exynos4_jpeg_set_tbl(void __iomem *regs,
+                                       const unsigned char *tbl,
+                                       unsigned long tab, int len)
+{
+       int i;
+       unsigned int dword;
+
+       for (i = 0; i < len; i += 4) {
+               dword = tbl[i] |
+                       (tbl[i + 1] << 8) |
+                       (tbl[i + 2] << 16) |
+                       (tbl[i + 3] << 24);
+               writel(dword, regs + tab + i);
+       }
+}
+
+static inline void exynos4_jpeg_set_qtbl_lum(void __iomem *regs, int quality)
+{
+       /* this driver fills quantisation table 0 with data for luma */
+       exynos4_jpeg_set_tbl(regs, qtbl_luminance[quality],
+                            EXYNOS4_QTBL_CONTENT(0),
+                            ARRAY_SIZE(qtbl_luminance[quality]));
+}
+
+static inline void exynos4_jpeg_set_qtbl_chr(void __iomem *regs, int quality)
+{
+       /* this driver fills quantisation table 1 with data for chroma */
+       exynos4_jpeg_set_tbl(regs, qtbl_chrominance[quality],
+                            EXYNOS4_QTBL_CONTENT(1),
+                            ARRAY_SIZE(qtbl_chrominance[quality]));
+}
+
+static void exynos4_jpeg_set_huff_tbl(void __iomem *base)
+{
+       exynos4_jpeg_set_tbl(base, hdctbl0, EXYNOS4_HUFF_TBL_HDCLL,
+                                                       ARRAY_SIZE(hdctbl0));
+       exynos4_jpeg_set_tbl(base, hdctbl0, EXYNOS4_HUFF_TBL_HDCCL,
+                                                       ARRAY_SIZE(hdctbl0));
+       exynos4_jpeg_set_tbl(base, hdctblg0, EXYNOS4_HUFF_TBL_HDCLV,
+                                                       ARRAY_SIZE(hdctblg0));
+       exynos4_jpeg_set_tbl(base, hdctblg0, EXYNOS4_HUFF_TBL_HDCCV,
+                                                       ARRAY_SIZE(hdctblg0));
+       exynos4_jpeg_set_tbl(base, hactbl0, EXYNOS4_HUFF_TBL_HACLL,
+                                                       ARRAY_SIZE(hactbl0));
+       exynos4_jpeg_set_tbl(base, hactbl0, EXYNOS4_HUFF_TBL_HACCL,
+                                                       ARRAY_SIZE(hactbl0));
+       exynos4_jpeg_set_tbl(base, hactblg0, EXYNOS4_HUFF_TBL_HACLV,
+                                                       ARRAY_SIZE(hactblg0));
+       exynos4_jpeg_set_tbl(base, hactblg0, EXYNOS4_HUFF_TBL_HACCV,
+                                                       ARRAY_SIZE(hactblg0));
+}
+
+static inline int __exynos4_huff_tbl(int class, int id, bool lenval)
+{
+       /*
+        * class: 0 - DC, 1 - AC
+        * id: 0 - Y, 1 - Cb/Cr
+        */
+       if (class) {
+               if (id)
+                       return lenval ? EXYNOS4_HUFF_TBL_HACCL :
+                               EXYNOS4_HUFF_TBL_HACCV;
+               return lenval ? EXYNOS4_HUFF_TBL_HACLL : EXYNOS4_HUFF_TBL_HACLV;
+
+       }
+       /* class == 0 */
+       if (id)
+               return lenval ? EXYNOS4_HUFF_TBL_HDCCL : EXYNOS4_HUFF_TBL_HDCCV;
+
+       return lenval ? EXYNOS4_HUFF_TBL_HDCLL : EXYNOS4_HUFF_TBL_HDCLV;
+}
+
+static inline int exynos4_huff_tbl_len(int class, int id)
+{
+       return __exynos4_huff_tbl(class, id, true);
+}
+
+static inline int exynos4_huff_tbl_val(int class, int id)
+{
+       return __exynos4_huff_tbl(class, id, false);
+}
+
+static int get_byte(struct s5p_jpeg_buffer *buf);
+static int get_word_be(struct s5p_jpeg_buffer *buf, unsigned int *word);
+static void skip(struct s5p_jpeg_buffer *buf, long len);
+
+static void exynos4_jpeg_parse_decode_h_tbl(struct s5p_jpeg_ctx *ctx)
+{
+       struct s5p_jpeg *jpeg = ctx->jpeg;
+       struct vb2_v4l2_buffer *vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+       struct s5p_jpeg_buffer jpeg_buffer;
+       unsigned int word;
+       int c, x, components;
+
+       jpeg_buffer.size = 2; /* Ls */
+       jpeg_buffer.data =
+               (unsigned long)vb2_plane_vaddr(&vb->vb2_buf, 0) + ctx->out_q.sos + 2;
+       jpeg_buffer.curr = 0;
+
+       word = 0;
+
+       if (get_word_be(&jpeg_buffer, &word))
+               return;
+       jpeg_buffer.size = (long)word - 2;
+       jpeg_buffer.data += 2;
+       jpeg_buffer.curr = 0;
+
+       components = get_byte(&jpeg_buffer);
+       if (components == -1)
+               return;
+       while (components--) {
+               c = get_byte(&jpeg_buffer);
+               if (c == -1)
+                       return;
+               x = get_byte(&jpeg_buffer);
+               if (x == -1)
+                       return;
+               exynos4_jpeg_select_dec_h_tbl(jpeg->regs, c,
+                                       (((x >> 4) & 0x1) << 1) | (x & 0x1));
+       }
+
+}
+
+static void exynos4_jpeg_parse_huff_tbl(struct s5p_jpeg_ctx *ctx)
+{
+       struct s5p_jpeg *jpeg = ctx->jpeg;
+       struct vb2_v4l2_buffer *vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+       struct s5p_jpeg_buffer jpeg_buffer;
+       unsigned int word;
+       int c, i, n, j;
+
+       for (j = 0; j < ctx->out_q.dht.n; ++j) {
+               jpeg_buffer.size = ctx->out_q.dht.len[j];
+               jpeg_buffer.data = (unsigned long)vb2_plane_vaddr(&vb->vb2_buf, 0) +
+                                  ctx->out_q.dht.marker[j];
+               jpeg_buffer.curr = 0;
+
+               word = 0;
+               while (jpeg_buffer.curr < jpeg_buffer.size) {
+                       char id, class;
+
+                       c = get_byte(&jpeg_buffer);
+                       if (c == -1)
+                               return;
+                       id = c & 0xf;
+                       class = (c >> 4) & 0xf;
+                       n = 0;
+                       for (i = 0; i < 16; ++i) {
+                               c = get_byte(&jpeg_buffer);
+                               if (c == -1)
+                                       return;
+                               word |= c << ((i % 4) * 8);
+                               if ((i + 1) % 4 == 0) {
+                                       writel(word, jpeg->regs +
+                                       exynos4_huff_tbl_len(class, id) +
+                                       (i / 4) * 4);
+                                       word = 0;
+                               }
+                               n += c;
+                       }
+                       word = 0;
+                       for (i = 0; i < n; ++i) {
+                               c = get_byte(&jpeg_buffer);
+                               if (c == -1)
+                                       return;
+                               word |= c << ((i % 4) * 8);
+                               if ((i + 1) % 4 == 0) {
+                                       writel(word, jpeg->regs +
+                                       exynos4_huff_tbl_val(class, id) +
+                                       (i / 4) * 4);
+                                       word = 0;
+                               }
+                       }
+                       if (i % 4) {
+                               writel(word, jpeg->regs +
+                               exynos4_huff_tbl_val(class, id) + (i / 4) * 4);
+                       }
+                       word = 0;
+               }
+       }
+}
+
+static void exynos4_jpeg_parse_decode_q_tbl(struct s5p_jpeg_ctx *ctx)
+{
+       struct s5p_jpeg *jpeg = ctx->jpeg;
+       struct vb2_v4l2_buffer *vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+       struct s5p_jpeg_buffer jpeg_buffer;
+       int c, x, components;
+
+       jpeg_buffer.size = ctx->out_q.sof_len;
+       jpeg_buffer.data =
+               (unsigned long)vb2_plane_vaddr(&vb->vb2_buf, 0) + ctx->out_q.sof;
+       jpeg_buffer.curr = 0;
+
+       skip(&jpeg_buffer, 5); /* P, Y, X */
+       components = get_byte(&jpeg_buffer);
+       if (components == -1)
+               return;
+
+       exynos4_jpeg_set_dec_components(jpeg->regs, components);
+
+       while (components--) {
+               c = get_byte(&jpeg_buffer);
+               if (c == -1)
+                       return;
+               skip(&jpeg_buffer, 1);
+               x = get_byte(&jpeg_buffer);
+               if (x == -1)
+                       return;
+               exynos4_jpeg_select_dec_q_tbl(jpeg->regs, c, x);
+       }
+}
+
+static void exynos4_jpeg_parse_q_tbl(struct s5p_jpeg_ctx *ctx)
+{
+       struct s5p_jpeg *jpeg = ctx->jpeg;
+       struct vb2_v4l2_buffer *vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+       struct s5p_jpeg_buffer jpeg_buffer;
+       unsigned int word;
+       int c, i, j;
+
+       for (j = 0; j < ctx->out_q.dqt.n; ++j) {
+               jpeg_buffer.size = ctx->out_q.dqt.len[j];
+               jpeg_buffer.data = (unsigned long)vb2_plane_vaddr(&vb->vb2_buf, 0) +
+                                  ctx->out_q.dqt.marker[j];
+               jpeg_buffer.curr = 0;
+
+               word = 0;
+               while (jpeg_buffer.size - jpeg_buffer.curr >= 65) {
+                       char id;
+
+                       c = get_byte(&jpeg_buffer);
+                       if (c == -1)
+                               return;
+                       id = c & 0xf;
+                       /* nonzero means extended mode - not supported */
+                       if ((c >> 4) & 0xf)
+                               return;
+                       for (i = 0; i < 64; ++i) {
+                               c = get_byte(&jpeg_buffer);
+                               if (c == -1)
+                                       return;
+                               word |= c << ((i % 4) * 8);
+                               if ((i + 1) % 4 == 0) {
+                                       writel(word, jpeg->regs +
+                                       EXYNOS4_QTBL_CONTENT(id) + (i / 4) * 4);
+                                       word = 0;
+                               }
+                       }
+                       word = 0;
+               }
+       }
+}
+
+/*
+ * ============================================================================
+ * Device file operations
+ * ============================================================================
+ */
+
+static int queue_init(void *priv, struct vb2_queue *src_vq,
+                     struct vb2_queue *dst_vq);
+static struct s5p_jpeg_fmt *s5p_jpeg_find_format(struct s5p_jpeg_ctx *ctx,
+                               __u32 pixelformat, unsigned int fmt_type);
+static int s5p_jpeg_controls_create(struct s5p_jpeg_ctx *ctx);
+
+static int s5p_jpeg_open(struct file *file)
+{
+       struct s5p_jpeg *jpeg = video_drvdata(file);
+       struct video_device *vfd = video_devdata(file);
+       struct s5p_jpeg_ctx *ctx;
+       struct s5p_jpeg_fmt *out_fmt, *cap_fmt;
+       int ret = 0;
+
+       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+       if (!ctx)
+               return -ENOMEM;
+
+       if (mutex_lock_interruptible(&jpeg->lock)) {
+               ret = -ERESTARTSYS;
+               goto free;
+       }
+
+       v4l2_fh_init(&ctx->fh, vfd);
+       /* Use separate control handler per file handle */
+       ctx->fh.ctrl_handler = &ctx->ctrl_handler;
+       file->private_data = &ctx->fh;
+       v4l2_fh_add(&ctx->fh);
+
+       ctx->jpeg = jpeg;
+       if (vfd == jpeg->vfd_encoder) {
+               ctx->mode = S5P_JPEG_ENCODE;
+               out_fmt = s5p_jpeg_find_format(ctx, V4L2_PIX_FMT_RGB565,
+                                                       FMT_TYPE_OUTPUT);
+               cap_fmt = s5p_jpeg_find_format(ctx, V4L2_PIX_FMT_JPEG,
+                                                       FMT_TYPE_CAPTURE);
+       } else {
+               ctx->mode = S5P_JPEG_DECODE;
+               out_fmt = s5p_jpeg_find_format(ctx, V4L2_PIX_FMT_JPEG,
+                                                       FMT_TYPE_OUTPUT);
+               cap_fmt = s5p_jpeg_find_format(ctx, V4L2_PIX_FMT_YUYV,
+                                                       FMT_TYPE_CAPTURE);
+               ctx->scale_factor = EXYNOS3250_DEC_SCALE_FACTOR_8_8;
+       }
+
+       ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(jpeg->m2m_dev, ctx, queue_init);
+       if (IS_ERR(ctx->fh.m2m_ctx)) {
+               ret = PTR_ERR(ctx->fh.m2m_ctx);
+               goto error;
+       }
+
+       ctx->out_q.fmt = out_fmt;
+       ctx->cap_q.fmt = cap_fmt;
+
+       ret = s5p_jpeg_controls_create(ctx);
+       if (ret < 0)
+               goto error;
+
+       mutex_unlock(&jpeg->lock);
+       return 0;
+
+error:
+       v4l2_fh_del(&ctx->fh);
+       v4l2_fh_exit(&ctx->fh);
+       mutex_unlock(&jpeg->lock);
+free:
+       kfree(ctx);
+       return ret;
+}
+
+static int s5p_jpeg_release(struct file *file)
+{
+       struct s5p_jpeg *jpeg = video_drvdata(file);
+       struct s5p_jpeg_ctx *ctx = fh_to_ctx(file->private_data);
+
+       mutex_lock(&jpeg->lock);
+       v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
+       v4l2_ctrl_handler_free(&ctx->ctrl_handler);
+       v4l2_fh_del(&ctx->fh);
+       v4l2_fh_exit(&ctx->fh);
+       kfree(ctx);
+       mutex_unlock(&jpeg->lock);
+
+       return 0;
+}
+
+static const struct v4l2_file_operations s5p_jpeg_fops = {
+       .owner          = THIS_MODULE,
+       .open           = s5p_jpeg_open,
+       .release        = s5p_jpeg_release,
+       .poll           = v4l2_m2m_fop_poll,
+       .unlocked_ioctl = video_ioctl2,
+       .mmap           = v4l2_m2m_fop_mmap,
+};
+
+/*
+ * ============================================================================
+ * video ioctl operations
+ * ============================================================================
+ */
+
+static int get_byte(struct s5p_jpeg_buffer *buf)
+{
+       if (buf->curr >= buf->size)
+               return -1;
+
+       return ((unsigned char *)buf->data)[buf->curr++];
+}
+
+static int get_word_be(struct s5p_jpeg_buffer *buf, unsigned int *word)
+{
+       unsigned int temp;
+       int byte;
+
+       byte = get_byte(buf);
+       if (byte == -1)
+               return -1;
+       temp = byte << 8;
+       byte = get_byte(buf);
+       if (byte == -1)
+               return -1;
+       *word = (unsigned int)byte | temp;
+       return 0;
+}
+
+static void skip(struct s5p_jpeg_buffer *buf, long len)
+{
+       if (len <= 0)
+               return;
+
+       while (len--)
+               get_byte(buf);
+}
+
+static bool s5p_jpeg_subsampling_decode(struct s5p_jpeg_ctx *ctx,
+                                       unsigned int subsampling)
+{
+       unsigned int version;
+
+       switch (subsampling) {
+       case 0x11:
+               ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_444;
+               break;
+       case 0x21:
+               ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422;
+               break;
+       case 0x22:
+               ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420;
+               break;
+       case 0x33:
+               ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY;
+               break;
+       case 0x41:
+               /*
+                * 4:1:1 subsampling only supported by 3250, 5420, and 5433
+                * variants
+                */
+               version = ctx->jpeg->variant->version;
+               if (version != SJPEG_EXYNOS3250 &&
+                   version != SJPEG_EXYNOS5420 &&
+                   version != SJPEG_EXYNOS5433)
+                       return false;
+
+               ctx->subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_411;
+               break;
+       default:
+               return false;
+       }
+
+       return true;
+}
+
+static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result,
+                              unsigned long buffer, unsigned long size,
+                              struct s5p_jpeg_ctx *ctx)
+{
+       int c, components = 0, notfound, n_dht = 0, n_dqt = 0;
+       unsigned int height = 0, width = 0, word, subsampling = 0;
+       unsigned int sos = 0, sof = 0, sof_len = 0;
+       unsigned int dht[S5P_JPEG_MAX_MARKER], dht_len[S5P_JPEG_MAX_MARKER];
+       unsigned int dqt[S5P_JPEG_MAX_MARKER], dqt_len[S5P_JPEG_MAX_MARKER];
+       long length;
+       struct s5p_jpeg_buffer jpeg_buffer;
+
+       jpeg_buffer.size = size;
+       jpeg_buffer.data = buffer;
+       jpeg_buffer.curr = 0;
+
+       notfound = 1;
+       while (notfound || !sos) {
+               c = get_byte(&jpeg_buffer);
+               if (c == -1)
+                       return false;
+               if (c != 0xff)
+                       continue;
+               do
+                       c = get_byte(&jpeg_buffer);
+               while (c == 0xff);
+               if (c == -1)
+                       return false;
+               if (c == 0)
+                       continue;
+               length = 0;
+               switch (c) {
+               /* JPEG_MARKER_SOF0: baseline JPEG */
+               case JPEG_MARKER_SOF0:
+                       if (get_word_be(&jpeg_buffer, &word))
+                               break;
+                       length = (long)word - 2;
+                       if (!length)
+                               return false;
+                       sof = jpeg_buffer.curr; /* after 0xffc0 */
+                       sof_len = length;
+                       if (get_byte(&jpeg_buffer) == -1)
+                               break;
+                       if (get_word_be(&jpeg_buffer, &height))
+                               break;
+                       if (get_word_be(&jpeg_buffer, &width))
+                               break;
+                       components = get_byte(&jpeg_buffer);
+                       if (components == -1)
+                               break;
+
+                       if (components == 1) {
+                               subsampling = 0x33;
+                       } else {
+                               skip(&jpeg_buffer, 1);
+                               subsampling = get_byte(&jpeg_buffer);
+                               skip(&jpeg_buffer, 1);
+                       }
+                       if (components > 3)
+                               return false;
+                       skip(&jpeg_buffer, components * 2);
+                       notfound = 0;
+                       break;
+
+               case JPEG_MARKER_DQT:
+                       if (get_word_be(&jpeg_buffer, &word))
+                               break;
+                       length = (long)word - 2;
+                       if (!length)
+                               return false;
+                       if (n_dqt >= S5P_JPEG_MAX_MARKER)
+                               return false;
+                       dqt[n_dqt] = jpeg_buffer.curr; /* after 0xffdb */
+                       dqt_len[n_dqt++] = length;
+                       skip(&jpeg_buffer, length);
+                       break;
+
+               case JPEG_MARKER_DHT:
+                       if (get_word_be(&jpeg_buffer, &word))
+                               break;
+                       length = (long)word - 2;
+                       if (!length)
+                               return false;
+                       if (n_dht >= S5P_JPEG_MAX_MARKER)
+                               return false;
+                       dht[n_dht] = jpeg_buffer.curr; /* after 0xffc4 */
+                       dht_len[n_dht++] = length;
+                       skip(&jpeg_buffer, length);
+                       break;
+
+               case JPEG_MARKER_SOS:
+                       sos = jpeg_buffer.curr - 2; /* 0xffda */
+                       break;
+
+               /* skip payload-less markers */
+               case JPEG_MARKER_RST ... JPEG_MARKER_RST + 7:
+               case JPEG_MARKER_SOI:
+               case JPEG_MARKER_EOI:
+               case JPEG_MARKER_TEM:
+                       break;
+
+               /* skip uninteresting payload markers */
+               default:
+                       if (get_word_be(&jpeg_buffer, &word))
+                               break;
+                       length = (long)word - 2;
+                       skip(&jpeg_buffer, length);
+                       break;
+               }
+       }
+
+       if (notfound || !sos || !s5p_jpeg_subsampling_decode(ctx, subsampling))
+               return false;
+
+       result->w = width;
+       result->h = height;
+       result->sos = sos;
+       result->dht.n = n_dht;
+       while (n_dht--) {
+               result->dht.marker[n_dht] = dht[n_dht];
+               result->dht.len[n_dht] = dht_len[n_dht];
+       }
+       result->dqt.n = n_dqt;
+       while (n_dqt--) {
+               result->dqt.marker[n_dqt] = dqt[n_dqt];
+               result->dqt.len[n_dqt] = dqt_len[n_dqt];
+       }
+       result->sof = sof;
+       result->sof_len = sof_len;
+
+       return true;
+}
+
+static int s5p_jpeg_querycap(struct file *file, void *priv,
+                          struct v4l2_capability *cap)
+{
+       struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
+
+       if (ctx->mode == S5P_JPEG_ENCODE) {
+               strscpy(cap->driver, S5P_JPEG_M2M_NAME,
+                       sizeof(cap->driver));
+               strscpy(cap->card, S5P_JPEG_M2M_NAME " encoder",
+                       sizeof(cap->card));
+       } else {
+               strscpy(cap->driver, S5P_JPEG_M2M_NAME,
+                       sizeof(cap->driver));
+               strscpy(cap->card, S5P_JPEG_M2M_NAME " decoder",
+                       sizeof(cap->card));
+       }
+       snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
+                dev_name(ctx->jpeg->dev));
+       return 0;
+}
+
+static int enum_fmt(struct s5p_jpeg_ctx *ctx,
+                   struct s5p_jpeg_fmt *sjpeg_formats, int n,
+                   struct v4l2_fmtdesc *f, u32 type)
+{
+       int i, num = 0;
+       unsigned int fmt_ver_flag = ctx->jpeg->variant->fmt_ver_flag;
+
+       for (i = 0; i < n; ++i) {
+               if (sjpeg_formats[i].flags & type &&
+                   sjpeg_formats[i].flags & fmt_ver_flag) {
+                       /* index-th format of type type found ? */
+                       if (num == f->index)
+                               break;
+                       /* Correct type but haven't reached our index yet,
+                        * just increment per-type index
+                        */
+                       ++num;
+               }
+       }
+
+       /* Format not found */
+       if (i >= n)
+               return -EINVAL;
+
+       f->pixelformat = sjpeg_formats[i].fourcc;
+
+       return 0;
+}
+
+static int s5p_jpeg_enum_fmt_vid_cap(struct file *file, void *priv,
+                                  struct v4l2_fmtdesc *f)
+{
+       struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
+
+       if (ctx->mode == S5P_JPEG_ENCODE)
+               return enum_fmt(ctx, sjpeg_formats, SJPEG_NUM_FORMATS, f,
+                               SJPEG_FMT_FLAG_ENC_CAPTURE);
+
+       return enum_fmt(ctx, sjpeg_formats, SJPEG_NUM_FORMATS, f,
+                       SJPEG_FMT_FLAG_DEC_CAPTURE);
+}
+
+static int s5p_jpeg_enum_fmt_vid_out(struct file *file, void *priv,
+                                  struct v4l2_fmtdesc *f)
+{
+       struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
+
+       if (ctx->mode == S5P_JPEG_ENCODE)
+               return enum_fmt(ctx, sjpeg_formats, SJPEG_NUM_FORMATS, f,
+                               SJPEG_FMT_FLAG_ENC_OUTPUT);
+
+       return enum_fmt(ctx, sjpeg_formats, SJPEG_NUM_FORMATS, f,
+                       SJPEG_FMT_FLAG_DEC_OUTPUT);
+}
+
+static struct s5p_jpeg_q_data *get_q_data(struct s5p_jpeg_ctx *ctx,
+                                         enum v4l2_buf_type type)
+{
+       if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
+               return &ctx->out_q;
+       if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return &ctx->cap_q;
+
+       return NULL;
+}
+
+static int s5p_jpeg_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
+{
+       struct vb2_queue *vq;
+       struct s5p_jpeg_q_data *q_data = NULL;
+       struct v4l2_pix_format *pix = &f->fmt.pix;
+       struct s5p_jpeg_ctx *ct = fh_to_ctx(priv);
+
+       vq = v4l2_m2m_get_vq(ct->fh.m2m_ctx, f->type);
+       if (!vq)
+               return -EINVAL;
+
+       if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+           ct->mode == S5P_JPEG_DECODE && !ct->hdr_parsed)
+               return -EINVAL;
+       q_data = get_q_data(ct, f->type);
+       BUG_ON(q_data == NULL);
+
+       pix->width = q_data->w;
+       pix->height = q_data->h;
+       pix->field = V4L2_FIELD_NONE;
+       pix->pixelformat = q_data->fmt->fourcc;
+       pix->bytesperline = 0;
+       if (q_data->fmt->fourcc != V4L2_PIX_FMT_JPEG) {
+               u32 bpl = q_data->w;
+
+               if (q_data->fmt->colplanes == 1)
+                       bpl = (bpl * q_data->fmt->depth) >> 3;
+               pix->bytesperline = bpl;
+       }
+       pix->sizeimage = q_data->size;
+
+       return 0;
+}
+
+static struct s5p_jpeg_fmt *s5p_jpeg_find_format(struct s5p_jpeg_ctx *ctx,
+                               u32 pixelformat, unsigned int fmt_type)
+{
+       unsigned int k, fmt_flag;
+
+       if (ctx->mode == S5P_JPEG_ENCODE)
+               fmt_flag = (fmt_type == FMT_TYPE_OUTPUT) ?
+                               SJPEG_FMT_FLAG_ENC_OUTPUT :
+                               SJPEG_FMT_FLAG_ENC_CAPTURE;
+       else
+               fmt_flag = (fmt_type == FMT_TYPE_OUTPUT) ?
+                               SJPEG_FMT_FLAG_DEC_OUTPUT :
+                               SJPEG_FMT_FLAG_DEC_CAPTURE;
+
+       for (k = 0; k < ARRAY_SIZE(sjpeg_formats); k++) {
+               struct s5p_jpeg_fmt *fmt = &sjpeg_formats[k];
+
+               if (fmt->fourcc == pixelformat &&
+                   fmt->flags & fmt_flag &&
+                   fmt->flags & ctx->jpeg->variant->fmt_ver_flag) {
+                       return fmt;
+               }
+       }
+
+       return NULL;
+}
+
+static void jpeg_bound_align_image(struct s5p_jpeg_ctx *ctx,
+                                  u32 *w, unsigned int wmin, unsigned int wmax,
+                                  unsigned int walign,
+                                  u32 *h, unsigned int hmin, unsigned int hmax,
+                                  unsigned int halign)
+{
+       int width, height, w_step, h_step;
+
+       width = *w;
+       height = *h;
+
+       w_step = 1 << walign;
+       h_step = 1 << halign;
+
+       if (ctx->jpeg->variant->hw3250_compat) {
+               /*
+                * Rightmost and bottommost pixels are cropped by the
+                * Exynos3250/compatible JPEG IP for RGB formats, for the
+                * specific width and height values respectively. This
+                * assignment will result in v4l_bound_align_image returning
+                * dimensions reduced by 1 for the aforementioned cases.
+                */
+               if (w_step == 4 && ((width & 3) == 1)) {
+                       wmax = width;
+                       hmax = height;
+               }
+       }
+
+       v4l_bound_align_image(w, wmin, wmax, walign, h, hmin, hmax, halign, 0);
+
+       if (*w < width && (*w + w_step) < wmax)
+               *w += w_step;
+       if (*h < height && (*h + h_step) < hmax)
+               *h += h_step;
+}
+
+static int vidioc_try_fmt(struct v4l2_format *f, struct s5p_jpeg_fmt *fmt,
+                         struct s5p_jpeg_ctx *ctx, int q_type)
+{
+       struct v4l2_pix_format *pix = &f->fmt.pix;
+
+       if (pix->field == V4L2_FIELD_ANY)
+               pix->field = V4L2_FIELD_NONE;
+       else if (pix->field != V4L2_FIELD_NONE)
+               return -EINVAL;
+
+       /* V4L2 specification suggests the driver corrects the format struct
+        * if any of the dimensions is unsupported
+        */
+       if (q_type == FMT_TYPE_OUTPUT)
+               jpeg_bound_align_image(ctx, &pix->width, S5P_JPEG_MIN_WIDTH,
+                                      S5P_JPEG_MAX_WIDTH, 0,
+                                      &pix->height, S5P_JPEG_MIN_HEIGHT,
+                                      S5P_JPEG_MAX_HEIGHT, 0);
+       else
+               jpeg_bound_align_image(ctx, &pix->width, S5P_JPEG_MIN_WIDTH,
+                                      S5P_JPEG_MAX_WIDTH, fmt->h_align,
+                                      &pix->height, S5P_JPEG_MIN_HEIGHT,
+                                      S5P_JPEG_MAX_HEIGHT, fmt->v_align);
+
+       if (fmt->fourcc == V4L2_PIX_FMT_JPEG) {
+               if (pix->sizeimage <= 0)
+                       pix->sizeimage = PAGE_SIZE;
+               pix->bytesperline = 0;
+       } else {
+               u32 bpl = pix->bytesperline;
+
+               if (fmt->colplanes > 1 && bpl < pix->width)
+                       bpl = pix->width; /* planar */
+
+               if (fmt->colplanes == 1 && /* packed */
+                   (bpl << 3) / fmt->depth < pix->width)
+                       bpl = (pix->width * fmt->depth) >> 3;
+
+               pix->bytesperline = bpl;
+               pix->sizeimage = (pix->width * pix->height * fmt->depth) >> 3;
+       }
+
+       return 0;
+}
+
+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;
+       int ret;
+
+       fmt = s5p_jpeg_find_format(ctx, f->fmt.pix.pixelformat,
+                                               FMT_TYPE_CAPTURE);
+       if (!fmt) {
+               v4l2_err(&ctx->jpeg->v4l2_dev,
+                        "Fourcc format (0x%08x) invalid.\n",
+                        f->fmt.pix.pixelformat);
+               return -EINVAL;
+       }
+
+       if (!ctx->jpeg->variant->hw_ex4_compat || ctx->mode != S5P_JPEG_DECODE)
+               goto exit;
+
+       /*
+        * 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
+        * capture format to the one with subsampling equal to the input jpeg.
+        */
+       if ((fmt->flags & SJPEG_FMT_NON_RGB) &&
+           (fmt->subsampling < ctx->subsampling)) {
+               ret = s5p_jpeg_adjust_fourcc_to_subsampling(ctx->subsampling,
+                                                           fmt->fourcc,
+                                                           &pix->pixelformat,
+                                                           ctx);
+               if (ret < 0)
+                       pix->pixelformat = V4L2_PIX_FMT_GREY;
+
+               fmt = s5p_jpeg_find_format(ctx, pix->pixelformat,
+                                                       FMT_TYPE_CAPTURE);
+       }
+
+       /*
+        * Decompression of a JPEG file with 4:2:0 subsampling and odd
+        * width to the YUV 4:2:0 compliant formats produces a raw image
+        * with broken luma component. Adjust capture format to RGB565
+        * in such a case.
+        */
+       if (ctx->subsampling == V4L2_JPEG_CHROMA_SUBSAMPLING_420 &&
+           (ctx->out_q.w & 1) &&
+           (pix->pixelformat == V4L2_PIX_FMT_NV12 ||
+            pix->pixelformat == V4L2_PIX_FMT_NV21 ||
+            pix->pixelformat == V4L2_PIX_FMT_YUV420)) {
+               pix->pixelformat = V4L2_PIX_FMT_RGB565;
+               fmt = s5p_jpeg_find_format(ctx, pix->pixelformat,
+                                                       FMT_TYPE_CAPTURE);
+       }
+
+exit:
+       return vidioc_try_fmt(f, fmt, ctx, FMT_TYPE_CAPTURE);
+}
+
+static int s5p_jpeg_try_fmt_vid_out(struct file *file, void *priv,
+                                 struct v4l2_format *f)
+{
+       struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
+       struct s5p_jpeg_fmt *fmt;
+
+       fmt = s5p_jpeg_find_format(ctx, f->fmt.pix.pixelformat,
+                                               FMT_TYPE_OUTPUT);
+       if (!fmt) {
+               v4l2_err(&ctx->jpeg->v4l2_dev,
+                        "Fourcc format (0x%08x) invalid.\n",
+                        f->fmt.pix.pixelformat);
+               return -EINVAL;
+       }
+
+       return vidioc_try_fmt(f, fmt, ctx, FMT_TYPE_OUTPUT);
+}
+
+static int exynos4_jpeg_get_output_buffer_size(struct s5p_jpeg_ctx *ctx,
+                                               struct v4l2_format *f,
+                                               int fmt_depth)
+{
+       struct v4l2_pix_format *pix = &f->fmt.pix;
+       u32 pix_fmt = f->fmt.pix.pixelformat;
+       int w = pix->width, h = pix->height, wh_align;
+       int padding = 0;
+
+       if (pix_fmt == V4L2_PIX_FMT_RGB32 ||
+           pix_fmt == V4L2_PIX_FMT_RGB565 ||
+           pix_fmt == V4L2_PIX_FMT_NV24 ||
+           pix_fmt == V4L2_PIX_FMT_NV42 ||
+           pix_fmt == V4L2_PIX_FMT_NV12 ||
+           pix_fmt == V4L2_PIX_FMT_NV21 ||
+           pix_fmt == V4L2_PIX_FMT_YUV420)
+               wh_align = 4;
+       else
+               wh_align = 1;
+
+       jpeg_bound_align_image(ctx, &w, S5P_JPEG_MIN_WIDTH,
+                              S5P_JPEG_MAX_WIDTH, wh_align,
+                              &h, S5P_JPEG_MIN_HEIGHT,
+                              S5P_JPEG_MAX_HEIGHT, wh_align);
+
+       if (ctx->jpeg->variant->version == SJPEG_EXYNOS4)
+               padding = PAGE_SIZE;
+
+       return (w * h * fmt_depth >> 3) + padding;
+}
+
+static int exynos3250_jpeg_try_downscale(struct s5p_jpeg_ctx *ctx,
+                                  struct v4l2_rect *r);
+
+static int s5p_jpeg_s_fmt(struct s5p_jpeg_ctx *ct, struct v4l2_format *f)
+{
+       struct vb2_queue *vq;
+       struct s5p_jpeg_q_data *q_data = NULL;
+       struct v4l2_pix_format *pix = &f->fmt.pix;
+       struct v4l2_ctrl *ctrl_subs;
+       struct v4l2_rect scale_rect;
+       unsigned int f_type;
+
+       vq = v4l2_m2m_get_vq(ct->fh.m2m_ctx, f->type);
+       if (!vq)
+               return -EINVAL;
+
+       q_data = get_q_data(ct, f->type);
+       BUG_ON(q_data == NULL);
+
+       if (vb2_is_busy(vq)) {
+               v4l2_err(&ct->jpeg->v4l2_dev, "%s queue busy\n", __func__);
+               return -EBUSY;
+       }
+
+       f_type = V4L2_TYPE_IS_OUTPUT(f->type) ?
+                       FMT_TYPE_OUTPUT : FMT_TYPE_CAPTURE;
+
+       q_data->fmt = s5p_jpeg_find_format(ct, pix->pixelformat, f_type);
+       if (ct->mode == S5P_JPEG_ENCODE ||
+               (ct->mode == S5P_JPEG_DECODE &&
+               q_data->fmt->fourcc != V4L2_PIX_FMT_JPEG)) {
+               q_data->w = pix->width;
+               q_data->h = pix->height;
+       }
+       if (q_data->fmt->fourcc != V4L2_PIX_FMT_JPEG) {
+               /*
+                * During encoding Exynos4x12 SoCs access wider memory area
+                * than it results from Image_x and Image_y values written to
+                * the JPEG_IMAGE_SIZE register. In order to avoid sysmmu
+                * page fault calculate proper buffer size in such a case.
+                */
+               if (ct->jpeg->variant->hw_ex4_compat &&
+                   f_type == FMT_TYPE_OUTPUT && ct->mode == S5P_JPEG_ENCODE)
+                       q_data->size = exynos4_jpeg_get_output_buffer_size(ct,
+                                                       f,
+                                                       q_data->fmt->depth);
+               else
+                       q_data->size = q_data->w * q_data->h *
+                                               q_data->fmt->depth >> 3;
+       } else {
+               q_data->size = pix->sizeimage;
+       }
+
+       if (f_type == FMT_TYPE_OUTPUT) {
+               ctrl_subs = v4l2_ctrl_find(&ct->ctrl_handler,
+                                       V4L2_CID_JPEG_CHROMA_SUBSAMPLING);
+               if (ctrl_subs)
+                       v4l2_ctrl_s_ctrl(ctrl_subs, q_data->fmt->subsampling);
+               ct->crop_altered = false;
+       }
+
+       /*
+        * For decoding init crop_rect with capture buffer dimmensions which
+        * contain aligned dimensions of the input JPEG image and do it only
+        * if crop rectangle hasn't been altered by the user space e.g. with
+        * S_SELECTION ioctl. For encoding assign output buffer dimensions.
+        */
+       if (!ct->crop_altered &&
+           ((ct->mode == S5P_JPEG_DECODE && f_type == FMT_TYPE_CAPTURE) ||
+            (ct->mode == S5P_JPEG_ENCODE && f_type == FMT_TYPE_OUTPUT))) {
+               ct->crop_rect.width = pix->width;
+               ct->crop_rect.height = pix->height;
+       }
+
+       /*
+        * Prevent downscaling to YUV420 format by more than 2
+        * for Exynos3250/compatible SoC as it produces broken raw image
+        * in such cases.
+        */
+       if (ct->mode == S5P_JPEG_DECODE &&
+           f_type == FMT_TYPE_CAPTURE &&
+           ct->jpeg->variant->hw3250_compat &&
+           pix->pixelformat == V4L2_PIX_FMT_YUV420 &&
+           ct->scale_factor > 2) {
+               scale_rect.width = ct->out_q.w / 2;
+               scale_rect.height = ct->out_q.h / 2;
+               exynos3250_jpeg_try_downscale(ct, &scale_rect);
+       }
+
+       return 0;
+}
+
+static int s5p_jpeg_s_fmt_vid_cap(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       int ret;
+
+       ret = s5p_jpeg_try_fmt_vid_cap(file, priv, f);
+       if (ret)
+               return ret;
+
+       return s5p_jpeg_s_fmt(fh_to_ctx(priv), f);
+}
+
+static int s5p_jpeg_s_fmt_vid_out(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       int ret;
+
+       ret = s5p_jpeg_try_fmt_vid_out(file, priv, f);
+       if (ret)
+               return ret;
+
+       return s5p_jpeg_s_fmt(fh_to_ctx(priv), f);
+}
+
+static int s5p_jpeg_subscribe_event(struct v4l2_fh *fh,
+                                   const struct v4l2_event_subscription *sub)
+{
+       if (sub->type == V4L2_EVENT_SOURCE_CHANGE)
+               return v4l2_src_change_event_subscribe(fh, sub);
+
+       return -EINVAL;
+}
+
+static int exynos3250_jpeg_try_downscale(struct s5p_jpeg_ctx *ctx,
+                                  struct v4l2_rect *r)
+{
+       int w_ratio, h_ratio, scale_factor, cur_ratio, i;
+
+       w_ratio = ctx->out_q.w / r->width;
+       h_ratio = ctx->out_q.h / r->height;
+
+       scale_factor = w_ratio > h_ratio ? w_ratio : h_ratio;
+       scale_factor = clamp_val(scale_factor, 1, 8);
+
+       /* Align scale ratio to the nearest power of 2 */
+       for (i = 0; i <= 3; ++i) {
+               cur_ratio = 1 << i;
+               if (scale_factor <= cur_ratio) {
+                       ctx->scale_factor = cur_ratio;
+                       break;
+               }
+       }
+
+       r->width = round_down(ctx->out_q.w / ctx->scale_factor, 2);
+       r->height = round_down(ctx->out_q.h / ctx->scale_factor, 2);
+
+       ctx->crop_rect.width = r->width;
+       ctx->crop_rect.height = r->height;
+       ctx->crop_rect.left = 0;
+       ctx->crop_rect.top = 0;
+
+       ctx->crop_altered = true;
+
+       return 0;
+}
+
+static int exynos3250_jpeg_try_crop(struct s5p_jpeg_ctx *ctx,
+                                  struct v4l2_rect *r)
+{
+       struct v4l2_rect base_rect;
+       int w_step, h_step;
+
+       switch (ctx->cap_q.fmt->fourcc) {
+       case V4L2_PIX_FMT_NV12:
+       case V4L2_PIX_FMT_NV21:
+               w_step = 1;
+               h_step = 2;
+               break;
+       case V4L2_PIX_FMT_YUV420:
+               w_step = 2;
+               h_step = 2;
+               break;
+       default:
+               w_step = 1;
+               h_step = 1;
+               break;
+       }
+
+       base_rect.top = 0;
+       base_rect.left = 0;
+       base_rect.width = ctx->out_q.w;
+       base_rect.height = ctx->out_q.h;
+
+       r->width = round_down(r->width, w_step);
+       r->height = round_down(r->height, h_step);
+       r->left = round_down(r->left, 2);
+       r->top = round_down(r->top, 2);
+
+       if (!v4l2_rect_enclosed(r, &base_rect))
+               return -EINVAL;
+
+       ctx->crop_rect.left = r->left;
+       ctx->crop_rect.top = r->top;
+       ctx->crop_rect.width = r->width;
+       ctx->crop_rect.height = r->height;
+
+       ctx->crop_altered = true;
+
+       return 0;
+}
+
+/*
+ * V4L2 controls
+ */
+
+static int s5p_jpeg_g_selection(struct file *file, void *priv,
+                        struct v4l2_selection *s)
+{
+       struct s5p_jpeg_ctx *ctx = fh_to_ctx(priv);
+
+       if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+           s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       /* For JPEG blob active == default == bounds */
+       switch (s->target) {
+       case V4L2_SEL_TGT_CROP:
+       case V4L2_SEL_TGT_CROP_BOUNDS:
+       case V4L2_SEL_TGT_CROP_DEFAULT:
+       case V4L2_SEL_TGT_COMPOSE_DEFAULT:
+               s->r.width = ctx->out_q.w;
+               s->r.height = ctx->out_q.h;
+               s->r.left = 0;
+               s->r.top = 0;
+               break;
+       case V4L2_SEL_TGT_COMPOSE:
+       case V4L2_SEL_TGT_COMPOSE_BOUNDS:
+       case V4L2_SEL_TGT_COMPOSE_PADDED:
+               s->r.width = ctx->crop_rect.width;
+               s->r.height =  ctx->crop_rect.height;
+               s->r.left = ctx->crop_rect.left;
+               s->r.top = ctx->crop_rect.top;
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+/*
+ * V4L2 controls
+ */
+static int s5p_jpeg_s_selection(struct file *file, void *fh,
+                                 struct v4l2_selection *s)
+{
+       struct s5p_jpeg_ctx *ctx = fh_to_ctx(file->private_data);
+       struct v4l2_rect *rect = &s->r;
+       int ret = -EINVAL;
+
+       if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       if (s->target == V4L2_SEL_TGT_COMPOSE) {
+               if (ctx->mode != S5P_JPEG_DECODE)
+                       return -EINVAL;
+               if (ctx->jpeg->variant->hw3250_compat)
+                       ret = exynos3250_jpeg_try_downscale(ctx, rect);
+       } else if (s->target == V4L2_SEL_TGT_CROP) {
+               if (ctx->mode != S5P_JPEG_ENCODE)
+                       return -EINVAL;
+               if (ctx->jpeg->variant->hw3250_compat)
+                       ret = exynos3250_jpeg_try_crop(ctx, rect);
+       }
+
+       return ret;
+}
+
+static int s5p_jpeg_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct s5p_jpeg_ctx *ctx = ctrl_to_ctx(ctrl);
+       struct s5p_jpeg *jpeg = ctx->jpeg;
+       unsigned long flags;
+
+       switch (ctrl->id) {
+       case V4L2_CID_JPEG_CHROMA_SUBSAMPLING:
+               spin_lock_irqsave(&jpeg->slock, flags);
+               ctrl->val = s5p_jpeg_to_user_subsampling(ctx);
+               spin_unlock_irqrestore(&jpeg->slock, flags);
+               break;
+       }
+
+       return 0;
+}
+
+static int s5p_jpeg_adjust_subs_ctrl(struct s5p_jpeg_ctx *ctx, int *ctrl_val)
+{
+       switch (ctx->jpeg->variant->version) {
+       case SJPEG_S5P:
+               return 0;
+       case SJPEG_EXYNOS3250:
+       case SJPEG_EXYNOS5420:
+               /*
+                * The exynos3250/compatible device can produce JPEG image only
+                * of 4:4:4 subsampling when given RGB32 source image.
+                */
+               if (ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB32)
+                       *ctrl_val = 0;
+               break;
+       case SJPEG_EXYNOS4:
+               /*
+                * The exynos4x12 device requires input raw image fourcc
+                * to be V4L2_PIX_FMT_GREY if gray jpeg format
+                * is to be set.
+                */
+               if (ctx->out_q.fmt->fourcc != V4L2_PIX_FMT_GREY &&
+                   *ctrl_val == V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY)
+                       return -EINVAL;
+               break;
+       }
+
+       /*
+        * The exynos4x12 and exynos3250/compatible devices require resulting
+        * jpeg subsampling not to be lower than the input raw image
+        * subsampling.
+        */
+       if (ctx->out_q.fmt->subsampling > *ctrl_val)
+               *ctrl_val = ctx->out_q.fmt->subsampling;
+
+       return 0;
+}
+
+static int s5p_jpeg_try_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct s5p_jpeg_ctx *ctx = ctrl_to_ctx(ctrl);
+       unsigned long flags;
+       int ret = 0;
+
+       spin_lock_irqsave(&ctx->jpeg->slock, flags);
+
+       if (ctrl->id == V4L2_CID_JPEG_CHROMA_SUBSAMPLING)
+               ret = s5p_jpeg_adjust_subs_ctrl(ctx, &ctrl->val);
+
+       spin_unlock_irqrestore(&ctx->jpeg->slock, flags);
+       return ret;
+}
+
+static int s5p_jpeg_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct s5p_jpeg_ctx *ctx = ctrl_to_ctx(ctrl);
+       unsigned long flags;
+
+       spin_lock_irqsave(&ctx->jpeg->slock, flags);
+
+       switch (ctrl->id) {
+       case V4L2_CID_JPEG_COMPRESSION_QUALITY:
+               ctx->compr_quality = ctrl->val;
+               break;
+       case V4L2_CID_JPEG_RESTART_INTERVAL:
+               ctx->restart_interval = ctrl->val;
+               break;
+       case V4L2_CID_JPEG_CHROMA_SUBSAMPLING:
+               ctx->subsampling = ctrl->val;
+               break;
+       }
+
+       spin_unlock_irqrestore(&ctx->jpeg->slock, flags);
+       return 0;
+}
+
+static const struct v4l2_ctrl_ops s5p_jpeg_ctrl_ops = {
+       .g_volatile_ctrl        = s5p_jpeg_g_volatile_ctrl,
+       .try_ctrl               = s5p_jpeg_try_ctrl,
+       .s_ctrl                 = s5p_jpeg_s_ctrl,
+};
+
+static int s5p_jpeg_controls_create(struct s5p_jpeg_ctx *ctx)
+{
+       unsigned int mask = ~0x27; /* 444, 422, 420, GRAY */
+       struct v4l2_ctrl *ctrl;
+       int ret;
+
+       v4l2_ctrl_handler_init(&ctx->ctrl_handler, 3);
+
+       if (ctx->mode == S5P_JPEG_ENCODE) {
+               v4l2_ctrl_new_std(&ctx->ctrl_handler, &s5p_jpeg_ctrl_ops,
+                                 V4L2_CID_JPEG_COMPRESSION_QUALITY,
+                                 0, 3, 1, S5P_JPEG_COMPR_QUAL_WORST);
+
+               v4l2_ctrl_new_std(&ctx->ctrl_handler, &s5p_jpeg_ctrl_ops,
+                                 V4L2_CID_JPEG_RESTART_INTERVAL,
+                                 0, 0xffff, 1, 0);
+               if (ctx->jpeg->variant->version == SJPEG_S5P)
+                       mask = ~0x06; /* 422, 420 */
+       }
+
+       ctrl = v4l2_ctrl_new_std_menu(&ctx->ctrl_handler, &s5p_jpeg_ctrl_ops,
+                                     V4L2_CID_JPEG_CHROMA_SUBSAMPLING,
+                                     V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY, mask,
+                                     V4L2_JPEG_CHROMA_SUBSAMPLING_422);
+
+       if (ctx->ctrl_handler.error) {
+               ret = ctx->ctrl_handler.error;
+               goto error_free;
+       }
+
+       if (ctx->mode == S5P_JPEG_DECODE)
+               ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE |
+                       V4L2_CTRL_FLAG_READ_ONLY;
+
+       ret = v4l2_ctrl_handler_setup(&ctx->ctrl_handler);
+       if (ret < 0)
+               goto error_free;
+
+       return ret;
+
+error_free:
+       v4l2_ctrl_handler_free(&ctx->ctrl_handler);
+       return ret;
+}
+
+static const struct v4l2_ioctl_ops s5p_jpeg_ioctl_ops = {
+       .vidioc_querycap                = s5p_jpeg_querycap,
+
+       .vidioc_enum_fmt_vid_cap        = s5p_jpeg_enum_fmt_vid_cap,
+       .vidioc_enum_fmt_vid_out        = s5p_jpeg_enum_fmt_vid_out,
+
+       .vidioc_g_fmt_vid_cap           = s5p_jpeg_g_fmt,
+       .vidioc_g_fmt_vid_out           = s5p_jpeg_g_fmt,
+
+       .vidioc_try_fmt_vid_cap         = s5p_jpeg_try_fmt_vid_cap,
+       .vidioc_try_fmt_vid_out         = s5p_jpeg_try_fmt_vid_out,
+
+       .vidioc_s_fmt_vid_cap           = s5p_jpeg_s_fmt_vid_cap,
+       .vidioc_s_fmt_vid_out           = s5p_jpeg_s_fmt_vid_out,
+
+       .vidioc_reqbufs                 = v4l2_m2m_ioctl_reqbufs,
+       .vidioc_querybuf                = v4l2_m2m_ioctl_querybuf,
+       .vidioc_qbuf                    = v4l2_m2m_ioctl_qbuf,
+       .vidioc_dqbuf                   = v4l2_m2m_ioctl_dqbuf,
+
+       .vidioc_streamon                = v4l2_m2m_ioctl_streamon,
+       .vidioc_streamoff               = v4l2_m2m_ioctl_streamoff,
+
+       .vidioc_g_selection             = s5p_jpeg_g_selection,
+       .vidioc_s_selection             = s5p_jpeg_s_selection,
+
+       .vidioc_subscribe_event         = s5p_jpeg_subscribe_event,
+       .vidioc_unsubscribe_event       = v4l2_event_unsubscribe,
+};
+
+/*
+ * ============================================================================
+ * mem2mem callbacks
+ * ============================================================================
+ */
+
+static void s5p_jpeg_device_run(void *priv)
+{
+       struct s5p_jpeg_ctx *ctx = priv;
+       struct s5p_jpeg *jpeg = ctx->jpeg;
+       struct vb2_v4l2_buffer *src_buf, *dst_buf;
+       unsigned long src_addr, dst_addr, flags;
+
+       spin_lock_irqsave(&ctx->jpeg->slock, flags);
+
+       src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+       dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
+       src_addr = vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0);
+       dst_addr = vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0);
+
+       s5p_jpeg_reset(jpeg->regs);
+       s5p_jpeg_poweron(jpeg->regs);
+       s5p_jpeg_proc_mode(jpeg->regs, ctx->mode);
+       if (ctx->mode == S5P_JPEG_ENCODE) {
+               if (ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB565)
+                       s5p_jpeg_input_raw_mode(jpeg->regs,
+                                                       S5P_JPEG_RAW_IN_565);
+               else
+                       s5p_jpeg_input_raw_mode(jpeg->regs,
+                                                       S5P_JPEG_RAW_IN_422);
+               s5p_jpeg_subsampling_mode(jpeg->regs, ctx->subsampling);
+               s5p_jpeg_dri(jpeg->regs, ctx->restart_interval);
+               s5p_jpeg_x(jpeg->regs, ctx->out_q.w);
+               s5p_jpeg_y(jpeg->regs, ctx->out_q.h);
+               s5p_jpeg_imgadr(jpeg->regs, src_addr);
+               s5p_jpeg_jpgadr(jpeg->regs, dst_addr);
+
+               /* ultimately comes from sizeimage from userspace */
+               s5p_jpeg_enc_stream_int(jpeg->regs, ctx->cap_q.size);
+
+               /* JPEG RGB to YCbCr conversion matrix */
+               s5p_jpeg_coef(jpeg->regs, 1, 1, S5P_JPEG_COEF11);
+               s5p_jpeg_coef(jpeg->regs, 1, 2, S5P_JPEG_COEF12);
+               s5p_jpeg_coef(jpeg->regs, 1, 3, S5P_JPEG_COEF13);
+               s5p_jpeg_coef(jpeg->regs, 2, 1, S5P_JPEG_COEF21);
+               s5p_jpeg_coef(jpeg->regs, 2, 2, S5P_JPEG_COEF22);
+               s5p_jpeg_coef(jpeg->regs, 2, 3, S5P_JPEG_COEF23);
+               s5p_jpeg_coef(jpeg->regs, 3, 1, S5P_JPEG_COEF31);
+               s5p_jpeg_coef(jpeg->regs, 3, 2, S5P_JPEG_COEF32);
+               s5p_jpeg_coef(jpeg->regs, 3, 3, S5P_JPEG_COEF33);
+
+               /*
+                * JPEG IP allows storing 4 quantization tables
+                * We fill table 0 for luma and table 1 for chroma
+                */
+               s5p_jpeg_set_qtbl_lum(jpeg->regs, ctx->compr_quality);
+               s5p_jpeg_set_qtbl_chr(jpeg->regs, ctx->compr_quality);
+               /* use table 0 for Y */
+               s5p_jpeg_qtbl(jpeg->regs, 1, 0);
+               /* use table 1 for Cb and Cr*/
+               s5p_jpeg_qtbl(jpeg->regs, 2, 1);
+               s5p_jpeg_qtbl(jpeg->regs, 3, 1);
+
+               /* Y, Cb, Cr use Huffman table 0 */
+               s5p_jpeg_htbl_ac(jpeg->regs, 1);
+               s5p_jpeg_htbl_dc(jpeg->regs, 1);
+               s5p_jpeg_htbl_ac(jpeg->regs, 2);
+               s5p_jpeg_htbl_dc(jpeg->regs, 2);
+               s5p_jpeg_htbl_ac(jpeg->regs, 3);
+               s5p_jpeg_htbl_dc(jpeg->regs, 3);
+       } else { /* S5P_JPEG_DECODE */
+               s5p_jpeg_rst_int_enable(jpeg->regs, true);
+               s5p_jpeg_data_num_int_enable(jpeg->regs, true);
+               s5p_jpeg_final_mcu_num_int_enable(jpeg->regs, true);
+               if (ctx->cap_q.fmt->fourcc == V4L2_PIX_FMT_YUYV)
+                       s5p_jpeg_outform_raw(jpeg->regs, S5P_JPEG_RAW_OUT_422);
+               else
+                       s5p_jpeg_outform_raw(jpeg->regs, S5P_JPEG_RAW_OUT_420);
+               s5p_jpeg_jpgadr(jpeg->regs, src_addr);
+               s5p_jpeg_imgadr(jpeg->regs, dst_addr);
+       }
+
+       s5p_jpeg_start(jpeg->regs);
+
+       spin_unlock_irqrestore(&ctx->jpeg->slock, flags);
+}
+
+static void exynos4_jpeg_set_img_addr(struct s5p_jpeg_ctx *ctx)
+{
+       struct s5p_jpeg *jpeg = ctx->jpeg;
+       struct s5p_jpeg_fmt *fmt;
+       struct vb2_v4l2_buffer *vb;
+       struct s5p_jpeg_addr jpeg_addr = {};
+       u32 pix_size, padding_bytes = 0;
+
+       jpeg_addr.cb = 0;
+       jpeg_addr.cr = 0;
+
+       pix_size = ctx->cap_q.w * ctx->cap_q.h;
+
+       if (ctx->mode == S5P_JPEG_ENCODE) {
+               vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+               fmt = ctx->out_q.fmt;
+               if (ctx->out_q.w % 2 && fmt->h_align > 0)
+                       padding_bytes = ctx->out_q.h;
+       } else {
+               fmt = ctx->cap_q.fmt;
+               vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
+       }
+
+       jpeg_addr.y = vb2_dma_contig_plane_dma_addr(&vb->vb2_buf, 0);
+
+       if (fmt->colplanes == 2) {
+               jpeg_addr.cb = jpeg_addr.y + pix_size - padding_bytes;
+       } else if (fmt->colplanes == 3) {
+               jpeg_addr.cb = jpeg_addr.y + pix_size;
+               if (fmt->fourcc == V4L2_PIX_FMT_YUV420)
+                       jpeg_addr.cr = jpeg_addr.cb + pix_size / 4;
+               else
+                       jpeg_addr.cr = jpeg_addr.cb + pix_size / 2;
+       }
+
+       exynos4_jpeg_set_frame_buf_address(jpeg->regs, &jpeg_addr);
+}
+
+static void exynos4_jpeg_set_jpeg_addr(struct s5p_jpeg_ctx *ctx)
+{
+       struct s5p_jpeg *jpeg = ctx->jpeg;
+       struct vb2_v4l2_buffer *vb;
+       unsigned int jpeg_addr = 0;
+
+       if (ctx->mode == S5P_JPEG_ENCODE)
+               vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
+       else
+               vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+
+       jpeg_addr = vb2_dma_contig_plane_dma_addr(&vb->vb2_buf, 0);
+       if (jpeg->variant->version == SJPEG_EXYNOS5433 &&
+           ctx->mode == S5P_JPEG_DECODE)
+               jpeg_addr += ctx->out_q.sos;
+       exynos4_jpeg_set_stream_buf_address(jpeg->regs, jpeg_addr);
+}
+
+static inline void exynos4_jpeg_set_img_fmt(void __iomem *base,
+                                           unsigned int img_fmt)
+{
+       __exynos4_jpeg_set_img_fmt(base, img_fmt, SJPEG_EXYNOS4);
+}
+
+static inline void exynos5433_jpeg_set_img_fmt(void __iomem *base,
+                                              unsigned int img_fmt)
+{
+       __exynos4_jpeg_set_img_fmt(base, img_fmt, SJPEG_EXYNOS5433);
+}
+
+static inline void exynos4_jpeg_set_enc_out_fmt(void __iomem *base,
+                                               unsigned int out_fmt)
+{
+       __exynos4_jpeg_set_enc_out_fmt(base, out_fmt, SJPEG_EXYNOS4);
+}
+
+static inline void exynos5433_jpeg_set_enc_out_fmt(void __iomem *base,
+                                                  unsigned int out_fmt)
+{
+       __exynos4_jpeg_set_enc_out_fmt(base, out_fmt, SJPEG_EXYNOS5433);
+}
+
+static void exynos4_jpeg_device_run(void *priv)
+{
+       struct s5p_jpeg_ctx *ctx = priv;
+       struct s5p_jpeg *jpeg = ctx->jpeg;
+       unsigned int bitstream_size;
+       unsigned long flags;
+
+       spin_lock_irqsave(&jpeg->slock, flags);
+
+       if (ctx->mode == S5P_JPEG_ENCODE) {
+               exynos4_jpeg_sw_reset(jpeg->regs);
+               exynos4_jpeg_set_interrupt(jpeg->regs, jpeg->variant->version);
+               exynos4_jpeg_set_huf_table_enable(jpeg->regs, 1);
+
+               exynos4_jpeg_set_huff_tbl(jpeg->regs);
+
+               /*
+                * JPEG IP allows storing 4 quantization tables
+                * We fill table 0 for luma and table 1 for chroma
+                */
+               exynos4_jpeg_set_qtbl_lum(jpeg->regs, ctx->compr_quality);
+               exynos4_jpeg_set_qtbl_chr(jpeg->regs, ctx->compr_quality);
+
+               exynos4_jpeg_set_encode_tbl_select(jpeg->regs,
+                                                       ctx->compr_quality);
+               exynos4_jpeg_set_stream_size(jpeg->regs, ctx->cap_q.w,
+                                                       ctx->cap_q.h);
+
+               if (ctx->jpeg->variant->version == SJPEG_EXYNOS4) {
+                       exynos4_jpeg_set_enc_out_fmt(jpeg->regs,
+                                                    ctx->subsampling);
+                       exynos4_jpeg_set_img_fmt(jpeg->regs,
+                                                ctx->out_q.fmt->fourcc);
+               } else {
+                       exynos5433_jpeg_set_enc_out_fmt(jpeg->regs,
+                                                       ctx->subsampling);
+                       exynos5433_jpeg_set_img_fmt(jpeg->regs,
+                                                   ctx->out_q.fmt->fourcc);
+               }
+               exynos4_jpeg_set_img_addr(ctx);
+               exynos4_jpeg_set_jpeg_addr(ctx);
+               exynos4_jpeg_set_encode_hoff_cnt(jpeg->regs,
+                                                       ctx->out_q.fmt->fourcc);
+       } else {
+               exynos4_jpeg_sw_reset(jpeg->regs);
+               exynos4_jpeg_set_interrupt(jpeg->regs,
+                                          jpeg->variant->version);
+               exynos4_jpeg_set_img_addr(ctx);
+               exynos4_jpeg_set_jpeg_addr(ctx);
+
+               if (jpeg->variant->version == SJPEG_EXYNOS5433) {
+                       exynos4_jpeg_parse_huff_tbl(ctx);
+                       exynos4_jpeg_parse_decode_h_tbl(ctx);
+
+                       exynos4_jpeg_parse_q_tbl(ctx);
+                       exynos4_jpeg_parse_decode_q_tbl(ctx);
+
+                       exynos4_jpeg_set_huf_table_enable(jpeg->regs, 1);
+
+                       exynos4_jpeg_set_stream_size(jpeg->regs, ctx->cap_q.w,
+                                       ctx->cap_q.h);
+                       exynos5433_jpeg_set_enc_out_fmt(jpeg->regs,
+                                                       ctx->subsampling);
+                       exynos5433_jpeg_set_img_fmt(jpeg->regs,
+                                                   ctx->cap_q.fmt->fourcc);
+                       bitstream_size = DIV_ROUND_UP(ctx->out_q.size, 16);
+               } else {
+                       exynos4_jpeg_set_img_fmt(jpeg->regs,
+                                                ctx->cap_q.fmt->fourcc);
+                       bitstream_size = DIV_ROUND_UP(ctx->out_q.size, 32);
+               }
+
+               exynos4_jpeg_set_dec_bitstream_size(jpeg->regs, bitstream_size);
+       }
+
+       exynos4_jpeg_set_sys_int_enable(jpeg->regs, 1);
+       exynos4_jpeg_set_enc_dec_mode(jpeg->regs, ctx->mode);
+
+       spin_unlock_irqrestore(&jpeg->slock, flags);
+}
+
+static void exynos3250_jpeg_set_img_addr(struct s5p_jpeg_ctx *ctx)
+{
+       struct s5p_jpeg *jpeg = ctx->jpeg;
+       struct s5p_jpeg_fmt *fmt;
+       struct vb2_v4l2_buffer *vb;
+       struct s5p_jpeg_addr jpeg_addr = {};
+       u32 pix_size;
+
+       pix_size = ctx->cap_q.w * ctx->cap_q.h;
+
+       if (ctx->mode == S5P_JPEG_ENCODE) {
+               vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+               fmt = ctx->out_q.fmt;
+       } else {
+               vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
+               fmt = ctx->cap_q.fmt;
+       }
+
+       jpeg_addr.y = vb2_dma_contig_plane_dma_addr(&vb->vb2_buf, 0);
+
+       if (fmt->colplanes == 2) {
+               jpeg_addr.cb = jpeg_addr.y + pix_size;
+       } else if (fmt->colplanes == 3) {
+               jpeg_addr.cb = jpeg_addr.y + pix_size;
+               if (fmt->fourcc == V4L2_PIX_FMT_YUV420)
+                       jpeg_addr.cr = jpeg_addr.cb + pix_size / 4;
+               else
+                       jpeg_addr.cr = jpeg_addr.cb + pix_size / 2;
+       }
+
+       exynos3250_jpeg_imgadr(jpeg->regs, &jpeg_addr);
+}
+
+static void exynos3250_jpeg_set_jpeg_addr(struct s5p_jpeg_ctx *ctx)
+{
+       struct s5p_jpeg *jpeg = ctx->jpeg;
+       struct vb2_v4l2_buffer *vb;
+       unsigned int jpeg_addr = 0;
+
+       if (ctx->mode == S5P_JPEG_ENCODE)
+               vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
+       else
+               vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+
+       jpeg_addr = vb2_dma_contig_plane_dma_addr(&vb->vb2_buf, 0);
+       exynos3250_jpeg_jpgadr(jpeg->regs, jpeg_addr);
+}
+
+static void exynos3250_jpeg_device_run(void *priv)
+{
+       struct s5p_jpeg_ctx *ctx = priv;
+       struct s5p_jpeg *jpeg = ctx->jpeg;
+       unsigned long flags;
+
+       spin_lock_irqsave(&ctx->jpeg->slock, flags);
+
+       exynos3250_jpeg_reset(jpeg->regs);
+       exynos3250_jpeg_set_dma_num(jpeg->regs);
+       exynos3250_jpeg_poweron(jpeg->regs);
+       exynos3250_jpeg_clk_set(jpeg->regs);
+       exynos3250_jpeg_proc_mode(jpeg->regs, ctx->mode);
+
+       if (ctx->mode == S5P_JPEG_ENCODE) {
+               exynos3250_jpeg_input_raw_fmt(jpeg->regs,
+                                             ctx->out_q.fmt->fourcc);
+               exynos3250_jpeg_dri(jpeg->regs, ctx->restart_interval);
+
+               /*
+                * JPEG IP allows storing 4 quantization tables
+                * We fill table 0 for luma and table 1 for chroma
+                */
+               s5p_jpeg_set_qtbl_lum(jpeg->regs, ctx->compr_quality);
+               s5p_jpeg_set_qtbl_chr(jpeg->regs, ctx->compr_quality);
+               /* use table 0 for Y */
+               exynos3250_jpeg_qtbl(jpeg->regs, 1, 0);
+               /* use table 1 for Cb and Cr*/
+               exynos3250_jpeg_qtbl(jpeg->regs, 2, 1);
+               exynos3250_jpeg_qtbl(jpeg->regs, 3, 1);
+
+               /*
+                * Some SoCs require setting Huffman tables before each run
+                */
+               if (jpeg->variant->htbl_reinit) {
+                       s5p_jpeg_set_hdctbl(jpeg->regs);
+                       s5p_jpeg_set_hdctblg(jpeg->regs);
+                       s5p_jpeg_set_hactbl(jpeg->regs);
+                       s5p_jpeg_set_hactblg(jpeg->regs);
+               }
+
+               /* Y, Cb, Cr use Huffman table 0 */
+               exynos3250_jpeg_htbl_ac(jpeg->regs, 1);
+               exynos3250_jpeg_htbl_dc(jpeg->regs, 1);
+               exynos3250_jpeg_htbl_ac(jpeg->regs, 2);
+               exynos3250_jpeg_htbl_dc(jpeg->regs, 2);
+               exynos3250_jpeg_htbl_ac(jpeg->regs, 3);
+               exynos3250_jpeg_htbl_dc(jpeg->regs, 3);
+
+               exynos3250_jpeg_set_x(jpeg->regs, ctx->crop_rect.width);
+               exynos3250_jpeg_set_y(jpeg->regs, ctx->crop_rect.height);
+               exynos3250_jpeg_stride(jpeg->regs, ctx->out_q.fmt->fourcc,
+                                                               ctx->out_q.w);
+               exynos3250_jpeg_offset(jpeg->regs, ctx->crop_rect.left,
+                                                       ctx->crop_rect.top);
+               exynos3250_jpeg_set_img_addr(ctx);
+               exynos3250_jpeg_set_jpeg_addr(ctx);
+               exynos3250_jpeg_subsampling_mode(jpeg->regs, ctx->subsampling);
+
+               /* ultimately comes from sizeimage from userspace */
+               exynos3250_jpeg_enc_stream_bound(jpeg->regs, ctx->cap_q.size);
+
+               if (ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB565 ||
+                   ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB565X ||
+                   ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB32)
+                       exynos3250_jpeg_set_y16(jpeg->regs, true);
+       } else {
+               exynos3250_jpeg_set_img_addr(ctx);
+               exynos3250_jpeg_set_jpeg_addr(ctx);
+               exynos3250_jpeg_stride(jpeg->regs, ctx->cap_q.fmt->fourcc,
+                                                               ctx->cap_q.w);
+               exynos3250_jpeg_offset(jpeg->regs, 0, 0);
+               exynos3250_jpeg_dec_scaling_ratio(jpeg->regs,
+                                                       ctx->scale_factor);
+               exynos3250_jpeg_dec_stream_size(jpeg->regs, ctx->out_q.size);
+               exynos3250_jpeg_output_raw_fmt(jpeg->regs,
+                                               ctx->cap_q.fmt->fourcc);
+       }
+
+       exynos3250_jpeg_interrupts_enable(jpeg->regs);
+
+       /* JPEG RGB to YCbCr conversion matrix */
+       exynos3250_jpeg_coef(jpeg->regs, ctx->mode);
+
+       exynos3250_jpeg_set_timer(jpeg->regs, EXYNOS3250_IRQ_TIMEOUT);
+       jpeg->irq_status = 0;
+       exynos3250_jpeg_start(jpeg->regs);
+
+       spin_unlock_irqrestore(&ctx->jpeg->slock, flags);
+}
+
+static int s5p_jpeg_job_ready(void *priv)
+{
+       struct s5p_jpeg_ctx *ctx = priv;
+
+       if (ctx->mode == S5P_JPEG_DECODE) {
+               /*
+                * We have only one input buffer and one output buffer. If there
+                * is a resolution change event, no need to continue decoding.
+                */
+               if (ctx->state == JPEGCTX_RESOLUTION_CHANGE)
+                       return 0;
+
+               return ctx->hdr_parsed;
+       }
+
+       return 1;
+}
+
+static const struct v4l2_m2m_ops s5p_jpeg_m2m_ops = {
+       .device_run     = s5p_jpeg_device_run,
+       .job_ready      = s5p_jpeg_job_ready,
+};
+
+static const struct v4l2_m2m_ops exynos3250_jpeg_m2m_ops = {
+       .device_run     = exynos3250_jpeg_device_run,
+       .job_ready      = s5p_jpeg_job_ready,
+};
+
+static const struct v4l2_m2m_ops exynos4_jpeg_m2m_ops = {
+       .device_run     = exynos4_jpeg_device_run,
+       .job_ready      = s5p_jpeg_job_ready,
+};
+
+/*
+ * ============================================================================
+ * Queue operations
+ * ============================================================================
+ */
+
+static int s5p_jpeg_queue_setup(struct vb2_queue *vq,
+                          unsigned int *nbuffers, unsigned int *nplanes,
+                          unsigned int sizes[], struct device *alloc_devs[])
+{
+       struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vq);
+       struct s5p_jpeg_q_data *q_data = NULL;
+       unsigned int size, count = *nbuffers;
+
+       q_data = get_q_data(ctx, vq->type);
+       BUG_ON(q_data == NULL);
+
+       size = q_data->size;
+
+       /*
+        * header is parsed during decoding and parsed information stored
+        * in the context so we do not allow another buffer to overwrite it
+        */
+       if (ctx->mode == S5P_JPEG_DECODE)
+               count = 1;
+
+       *nbuffers = count;
+       *nplanes = 1;
+       sizes[0] = size;
+
+       return 0;
+}
+
+static int s5p_jpeg_buf_prepare(struct vb2_buffer *vb)
+{
+       struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+       struct s5p_jpeg_q_data *q_data = NULL;
+
+       q_data = get_q_data(ctx, vb->vb2_queue->type);
+       BUG_ON(q_data == NULL);
+
+       if (vb2_plane_size(vb, 0) < q_data->size) {
+               pr_err("%s data will not fit into plane (%lu < %lu)\n",
+                               __func__, vb2_plane_size(vb, 0),
+                               (long)q_data->size);
+               return -EINVAL;
+       }
+
+       vb2_set_plane_payload(vb, 0, q_data->size);
+
+       return 0;
+}
+
+static void s5p_jpeg_set_capture_queue_data(struct s5p_jpeg_ctx *ctx)
+{
+       struct s5p_jpeg_q_data *q_data = &ctx->cap_q;
+
+       q_data->w = ctx->out_q.w;
+       q_data->h = ctx->out_q.h;
+
+       /*
+        * This call to jpeg_bound_align_image() takes care of width and
+        * height values alignment when user space calls the QBUF of
+        * OUTPUT buffer after the S_FMT of CAPTURE buffer.
+        * Please note that on Exynos4x12 SoCs, resigning from executing
+        * S_FMT on capture buffer for each JPEG image can result in a
+        * hardware hangup if subsampling is lower than the one of input
+        * JPEG.
+        */
+       jpeg_bound_align_image(ctx, &q_data->w, S5P_JPEG_MIN_WIDTH,
+                              S5P_JPEG_MAX_WIDTH, q_data->fmt->h_align,
+                              &q_data->h, S5P_JPEG_MIN_HEIGHT,
+                              S5P_JPEG_MAX_HEIGHT, q_data->fmt->v_align);
+
+       q_data->size = q_data->w * q_data->h * q_data->fmt->depth >> 3;
+}
+
+static void s5p_jpeg_buf_queue(struct vb2_buffer *vb)
+{
+       struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+       struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+
+       if (ctx->mode == S5P_JPEG_DECODE &&
+           vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+               static const struct v4l2_event ev_src_ch = {
+                       .type = V4L2_EVENT_SOURCE_CHANGE,
+                       .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,
+               };
+               struct vb2_queue *dst_vq;
+               u32 ori_w;
+               u32 ori_h;
+
+               dst_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
+                                        V4L2_BUF_TYPE_VIDEO_CAPTURE);
+               ori_w = ctx->out_q.w;
+               ori_h = ctx->out_q.h;
+
+               ctx->hdr_parsed = s5p_jpeg_parse_hdr(&ctx->out_q,
+                    (unsigned long)vb2_plane_vaddr(vb, 0),
+                    min((unsigned long)ctx->out_q.size,
+                        vb2_get_plane_payload(vb, 0)), ctx);
+               if (!ctx->hdr_parsed) {
+                       vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
+                       return;
+               }
+
+               /*
+                * If there is a resolution change event, only update capture
+                * queue when it is not streaming. Otherwise, update it in
+                * STREAMOFF. See s5p_jpeg_stop_streaming for detail.
+                */
+               if (ctx->out_q.w != ori_w || ctx->out_q.h != ori_h) {
+                       v4l2_event_queue_fh(&ctx->fh, &ev_src_ch);
+                       if (vb2_is_streaming(dst_vq))
+                               ctx->state = JPEGCTX_RESOLUTION_CHANGE;
+                       else
+                               s5p_jpeg_set_capture_queue_data(ctx);
+               }
+       }
+
+       v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
+}
+
+static int s5p_jpeg_start_streaming(struct vb2_queue *q, unsigned int count)
+{
+       struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(q);
+
+       return pm_runtime_resume_and_get(ctx->jpeg->dev);
+}
+
+static void s5p_jpeg_stop_streaming(struct vb2_queue *q)
+{
+       struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(q);
+
+       /*
+        * STREAMOFF is an acknowledgment for resolution change event.
+        * Before STREAMOFF, we still have to return the old resolution and
+        * subsampling. Update capture queue when the stream is off.
+        */
+       if (ctx->state == JPEGCTX_RESOLUTION_CHANGE &&
+           q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               s5p_jpeg_set_capture_queue_data(ctx);
+               ctx->state = JPEGCTX_RUNNING;
+       }
+
+       pm_runtime_put(ctx->jpeg->dev);
+}
+
+static const struct vb2_ops s5p_jpeg_qops = {
+       .queue_setup            = s5p_jpeg_queue_setup,
+       .buf_prepare            = s5p_jpeg_buf_prepare,
+       .buf_queue              = s5p_jpeg_buf_queue,
+       .wait_prepare           = vb2_ops_wait_prepare,
+       .wait_finish            = vb2_ops_wait_finish,
+       .start_streaming        = s5p_jpeg_start_streaming,
+       .stop_streaming         = s5p_jpeg_stop_streaming,
+};
+
+static int queue_init(void *priv, struct vb2_queue *src_vq,
+                     struct vb2_queue *dst_vq)
+{
+       struct s5p_jpeg_ctx *ctx = priv;
+       int ret;
+
+       src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+       src_vq->io_modes = VB2_MMAP | VB2_USERPTR;
+       src_vq->drv_priv = ctx;
+       src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
+       src_vq->ops = &s5p_jpeg_qops;
+       src_vq->mem_ops = &vb2_dma_contig_memops;
+       src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+       src_vq->lock = &ctx->jpeg->lock;
+       src_vq->dev = ctx->jpeg->dev;
+
+       ret = vb2_queue_init(src_vq);
+       if (ret)
+               return ret;
+
+       dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       dst_vq->io_modes = VB2_MMAP | VB2_USERPTR;
+       dst_vq->drv_priv = ctx;
+       dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
+       dst_vq->ops = &s5p_jpeg_qops;
+       dst_vq->mem_ops = &vb2_dma_contig_memops;
+       dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+       dst_vq->lock = &ctx->jpeg->lock;
+       dst_vq->dev = ctx->jpeg->dev;
+
+       return vb2_queue_init(dst_vq);
+}
+
+/*
+ * ============================================================================
+ * ISR
+ * ============================================================================
+ */
+
+static irqreturn_t s5p_jpeg_irq(int irq, void *dev_id)
+{
+       struct s5p_jpeg *jpeg = dev_id;
+       struct s5p_jpeg_ctx *curr_ctx;
+       struct vb2_v4l2_buffer *src_buf, *dst_buf;
+       unsigned long payload_size = 0;
+       enum vb2_buffer_state state = VB2_BUF_STATE_DONE;
+       bool enc_jpeg_too_large = false;
+       bool timer_elapsed = false;
+       bool op_completed = false;
+
+       spin_lock(&jpeg->slock);
+
+       curr_ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev);
+
+       src_buf = v4l2_m2m_src_buf_remove(curr_ctx->fh.m2m_ctx);
+       dst_buf = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx);
+
+       if (curr_ctx->mode == S5P_JPEG_ENCODE)
+               enc_jpeg_too_large = s5p_jpeg_enc_stream_stat(jpeg->regs);
+       timer_elapsed = s5p_jpeg_timer_stat(jpeg->regs);
+       op_completed = s5p_jpeg_result_stat_ok(jpeg->regs);
+       if (curr_ctx->mode == S5P_JPEG_DECODE)
+               op_completed = op_completed &&
+                                       s5p_jpeg_stream_stat_ok(jpeg->regs);
+
+       if (enc_jpeg_too_large) {
+               state = VB2_BUF_STATE_ERROR;
+               s5p_jpeg_clear_enc_stream_stat(jpeg->regs);
+       } else if (timer_elapsed) {
+               state = VB2_BUF_STATE_ERROR;
+               s5p_jpeg_clear_timer_stat(jpeg->regs);
+       } else if (!op_completed) {
+               state = VB2_BUF_STATE_ERROR;
+       } else {
+               payload_size = s5p_jpeg_compressed_size(jpeg->regs);
+       }
+
+       dst_buf->timecode = src_buf->timecode;
+       dst_buf->vb2_buf.timestamp = src_buf->vb2_buf.timestamp;
+       dst_buf->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
+       dst_buf->flags |=
+               src_buf->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
+
+       v4l2_m2m_buf_done(src_buf, state);
+       if (curr_ctx->mode == S5P_JPEG_ENCODE)
+               vb2_set_plane_payload(&dst_buf->vb2_buf, 0, payload_size);
+       v4l2_m2m_buf_done(dst_buf, state);
+
+       curr_ctx->subsampling = s5p_jpeg_get_subsampling_mode(jpeg->regs);
+       spin_unlock(&jpeg->slock);
+
+       s5p_jpeg_clear_int(jpeg->regs);
+
+       v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->fh.m2m_ctx);
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t exynos4_jpeg_irq(int irq, void *priv)
+{
+       unsigned int int_status;
+       struct vb2_v4l2_buffer *src_vb, *dst_vb;
+       struct s5p_jpeg *jpeg = priv;
+       struct s5p_jpeg_ctx *curr_ctx;
+       unsigned long payload_size = 0;
+
+       spin_lock(&jpeg->slock);
+
+       exynos4_jpeg_set_sys_int_enable(jpeg->regs, 0);
+
+       curr_ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev);
+
+       src_vb = v4l2_m2m_src_buf_remove(curr_ctx->fh.m2m_ctx);
+       dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx);
+
+       int_status = exynos4_jpeg_get_int_status(jpeg->regs);
+
+       if (int_status) {
+               switch (int_status & 0x1f) {
+               case 0x1:
+                       jpeg->irq_ret = ERR_PROT;
+                       break;
+               case 0x2:
+                       jpeg->irq_ret = OK_ENC_OR_DEC;
+                       break;
+               case 0x4:
+                       jpeg->irq_ret = ERR_DEC_INVALID_FORMAT;
+                       break;
+               case 0x8:
+                       jpeg->irq_ret = ERR_MULTI_SCAN;
+                       break;
+               case 0x10:
+                       jpeg->irq_ret = ERR_FRAME;
+                       break;
+               default:
+                       jpeg->irq_ret = ERR_UNKNOWN;
+                       break;
+               }
+       } else {
+               jpeg->irq_ret = ERR_UNKNOWN;
+       }
+
+       if (jpeg->irq_ret == OK_ENC_OR_DEC) {
+               if (curr_ctx->mode == S5P_JPEG_ENCODE) {
+                       payload_size = exynos4_jpeg_get_stream_size(jpeg->regs);
+                       vb2_set_plane_payload(&dst_vb->vb2_buf,
+                                       0, payload_size);
+               }
+               v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE);
+               v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_DONE);
+       } else {
+               v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_ERROR);
+               v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_ERROR);
+       }
+
+       if (jpeg->variant->version == SJPEG_EXYNOS4)
+               curr_ctx->subsampling = exynos4_jpeg_get_frame_fmt(jpeg->regs);
+
+       exynos4_jpeg_set_enc_dec_mode(jpeg->regs, S5P_JPEG_DISABLE);
+
+       spin_unlock(&jpeg->slock);
+
+       v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->fh.m2m_ctx);
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t exynos3250_jpeg_irq(int irq, void *dev_id)
+{
+       struct s5p_jpeg *jpeg = dev_id;
+       struct s5p_jpeg_ctx *curr_ctx;
+       struct vb2_v4l2_buffer *src_buf, *dst_buf;
+       unsigned long payload_size = 0;
+       enum vb2_buffer_state state = VB2_BUF_STATE_DONE;
+       bool interrupt_timeout = false;
+       bool stream_error = false;
+       u32 irq_status;
+
+       spin_lock(&jpeg->slock);
+
+       irq_status = exynos3250_jpeg_get_timer_status(jpeg->regs);
+       if (irq_status & EXYNOS3250_TIMER_INT_STAT) {
+               exynos3250_jpeg_clear_timer_status(jpeg->regs);
+               interrupt_timeout = true;
+               dev_err(jpeg->dev, "Interrupt timeout occurred.\n");
+       }
+
+       irq_status = exynos3250_jpeg_get_int_status(jpeg->regs);
+       exynos3250_jpeg_clear_int_status(jpeg->regs, irq_status);
+
+       jpeg->irq_status |= irq_status;
+
+       if (jpeg->variant->version == SJPEG_EXYNOS5420 &&
+           irq_status & EXYNOS3250_STREAM_STAT) {
+               stream_error = true;
+               dev_err(jpeg->dev, "Syntax error or unrecoverable error occurred.\n");
+       }
+
+       curr_ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev);
+
+       if (!curr_ctx)
+               goto exit_unlock;
+
+       if ((irq_status & EXYNOS3250_HEADER_STAT) &&
+           (curr_ctx->mode == S5P_JPEG_DECODE)) {
+               exynos3250_jpeg_rstart(jpeg->regs);
+               goto exit_unlock;
+       }
+
+       if (jpeg->irq_status & (EXYNOS3250_JPEG_DONE |
+                               EXYNOS3250_WDMA_DONE |
+                               EXYNOS3250_RDMA_DONE |
+                               EXYNOS3250_RESULT_STAT))
+               payload_size = exynos3250_jpeg_compressed_size(jpeg->regs);
+       else if (interrupt_timeout || stream_error)
+               state = VB2_BUF_STATE_ERROR;
+       else
+               goto exit_unlock;
+
+       src_buf = v4l2_m2m_src_buf_remove(curr_ctx->fh.m2m_ctx);
+       dst_buf = v4l2_m2m_dst_buf_remove(curr_ctx->fh.m2m_ctx);
+
+       dst_buf->timecode = src_buf->timecode;
+       dst_buf->vb2_buf.timestamp = src_buf->vb2_buf.timestamp;
+
+       v4l2_m2m_buf_done(src_buf, state);
+       if (curr_ctx->mode == S5P_JPEG_ENCODE)
+               vb2_set_plane_payload(&dst_buf->vb2_buf, 0, payload_size);
+       v4l2_m2m_buf_done(dst_buf, state);
+
+       curr_ctx->subsampling =
+                       exynos3250_jpeg_get_subsampling_mode(jpeg->regs);
+
+       spin_unlock(&jpeg->slock);
+
+       v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->fh.m2m_ctx);
+       return IRQ_HANDLED;
+
+exit_unlock:
+       spin_unlock(&jpeg->slock);
+       return IRQ_HANDLED;
+}
+
+static void *jpeg_get_drv_data(struct device *dev);
+
+/*
+ * ============================================================================
+ * Driver basic infrastructure
+ * ============================================================================
+ */
+
+static int s5p_jpeg_probe(struct platform_device *pdev)
+{
+       struct s5p_jpeg *jpeg;
+       int i, ret;
+
+       /* JPEG IP abstraction struct */
+       jpeg = devm_kzalloc(&pdev->dev, sizeof(struct s5p_jpeg), GFP_KERNEL);
+       if (!jpeg)
+               return -ENOMEM;
+
+       jpeg->variant = jpeg_get_drv_data(&pdev->dev);
+       if (!jpeg->variant)
+               return -ENODEV;
+
+       mutex_init(&jpeg->lock);
+       spin_lock_init(&jpeg->slock);
+       jpeg->dev = &pdev->dev;
+
+       /* memory-mapped registers */
+       jpeg->regs = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(jpeg->regs))
+               return PTR_ERR(jpeg->regs);
+
+       /* interrupt service routine registration */
+       jpeg->irq = ret = platform_get_irq(pdev, 0);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "cannot find IRQ\n");
+               return ret;
+       }
+
+       ret = devm_request_irq(&pdev->dev, jpeg->irq, jpeg->variant->jpeg_irq,
+                               0, dev_name(&pdev->dev), jpeg);
+       if (ret) {
+               dev_err(&pdev->dev, "cannot claim IRQ %d\n", jpeg->irq);
+               return ret;
+       }
+
+       /* clocks */
+       for (i = 0; i < jpeg->variant->num_clocks; i++) {
+               jpeg->clocks[i] = devm_clk_get(&pdev->dev,
+                                             jpeg->variant->clk_names[i]);
+               if (IS_ERR(jpeg->clocks[i])) {
+                       dev_err(&pdev->dev, "failed to get clock: %s\n",
+                               jpeg->variant->clk_names[i]);
+                       return PTR_ERR(jpeg->clocks[i]);
+               }
+       }
+
+       /* v4l2 device */
+       ret = v4l2_device_register(&pdev->dev, &jpeg->v4l2_dev);
+       if (ret) {
+               dev_err(&pdev->dev, "Failed to register v4l2 device\n");
+               return ret;
+       }
+
+       /* mem2mem device */
+       jpeg->m2m_dev = v4l2_m2m_init(jpeg->variant->m2m_ops);
+       if (IS_ERR(jpeg->m2m_dev)) {
+               v4l2_err(&jpeg->v4l2_dev, "Failed to init mem2mem device\n");
+               ret = PTR_ERR(jpeg->m2m_dev);
+               goto device_register_rollback;
+       }
+
+       vb2_dma_contig_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32));
+
+       /* JPEG encoder /dev/videoX node */
+       jpeg->vfd_encoder = video_device_alloc();
+       if (!jpeg->vfd_encoder) {
+               v4l2_err(&jpeg->v4l2_dev, "Failed to allocate video device\n");
+               ret = -ENOMEM;
+               goto m2m_init_rollback;
+       }
+       snprintf(jpeg->vfd_encoder->name, sizeof(jpeg->vfd_encoder->name),
+                               "%s-enc", S5P_JPEG_M2M_NAME);
+       jpeg->vfd_encoder->fops         = &s5p_jpeg_fops;
+       jpeg->vfd_encoder->ioctl_ops    = &s5p_jpeg_ioctl_ops;
+       jpeg->vfd_encoder->minor        = -1;
+       jpeg->vfd_encoder->release      = video_device_release;
+       jpeg->vfd_encoder->lock         = &jpeg->lock;
+       jpeg->vfd_encoder->v4l2_dev     = &jpeg->v4l2_dev;
+       jpeg->vfd_encoder->vfl_dir      = VFL_DIR_M2M;
+       jpeg->vfd_encoder->device_caps  = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M;
+
+       ret = video_register_device(jpeg->vfd_encoder, VFL_TYPE_VIDEO, -1);
+       if (ret) {
+               v4l2_err(&jpeg->v4l2_dev, "Failed to register video device\n");
+               video_device_release(jpeg->vfd_encoder);
+               goto m2m_init_rollback;
+       }
+
+       video_set_drvdata(jpeg->vfd_encoder, jpeg);
+       v4l2_info(&jpeg->v4l2_dev,
+                 "encoder device registered as /dev/video%d\n",
+                 jpeg->vfd_encoder->num);
+
+       /* JPEG decoder /dev/videoX node */
+       jpeg->vfd_decoder = video_device_alloc();
+       if (!jpeg->vfd_decoder) {
+               v4l2_err(&jpeg->v4l2_dev, "Failed to allocate video device\n");
+               ret = -ENOMEM;
+               goto enc_vdev_register_rollback;
+       }
+       snprintf(jpeg->vfd_decoder->name, sizeof(jpeg->vfd_decoder->name),
+                               "%s-dec", S5P_JPEG_M2M_NAME);
+       jpeg->vfd_decoder->fops         = &s5p_jpeg_fops;
+       jpeg->vfd_decoder->ioctl_ops    = &s5p_jpeg_ioctl_ops;
+       jpeg->vfd_decoder->minor        = -1;
+       jpeg->vfd_decoder->release      = video_device_release;
+       jpeg->vfd_decoder->lock         = &jpeg->lock;
+       jpeg->vfd_decoder->v4l2_dev     = &jpeg->v4l2_dev;
+       jpeg->vfd_decoder->vfl_dir      = VFL_DIR_M2M;
+       jpeg->vfd_decoder->device_caps  = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M;
+
+       ret = video_register_device(jpeg->vfd_decoder, VFL_TYPE_VIDEO, -1);
+       if (ret) {
+               v4l2_err(&jpeg->v4l2_dev, "Failed to register video device\n");
+               video_device_release(jpeg->vfd_decoder);
+               goto enc_vdev_register_rollback;
+       }
+
+       video_set_drvdata(jpeg->vfd_decoder, jpeg);
+       v4l2_info(&jpeg->v4l2_dev,
+                 "decoder device registered as /dev/video%d\n",
+                 jpeg->vfd_decoder->num);
+
+       /* final statements & power management */
+       platform_set_drvdata(pdev, jpeg);
+
+       pm_runtime_enable(&pdev->dev);
+
+       v4l2_info(&jpeg->v4l2_dev, "Samsung S5P JPEG codec\n");
+
+       return 0;
+
+enc_vdev_register_rollback:
+       video_unregister_device(jpeg->vfd_encoder);
+
+m2m_init_rollback:
+       v4l2_m2m_release(jpeg->m2m_dev);
+
+device_register_rollback:
+       v4l2_device_unregister(&jpeg->v4l2_dev);
+
+       return ret;
+}
+
+static int s5p_jpeg_remove(struct platform_device *pdev)
+{
+       struct s5p_jpeg *jpeg = platform_get_drvdata(pdev);
+       int i;
+
+       pm_runtime_disable(jpeg->dev);
+
+       video_unregister_device(jpeg->vfd_decoder);
+       video_unregister_device(jpeg->vfd_encoder);
+       vb2_dma_contig_clear_max_seg_size(&pdev->dev);
+       v4l2_m2m_release(jpeg->m2m_dev);
+       v4l2_device_unregister(&jpeg->v4l2_dev);
+
+       if (!pm_runtime_status_suspended(&pdev->dev)) {
+               for (i = jpeg->variant->num_clocks - 1; i >= 0; i--)
+                       clk_disable_unprepare(jpeg->clocks[i]);
+       }
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int s5p_jpeg_runtime_suspend(struct device *dev)
+{
+       struct s5p_jpeg *jpeg = dev_get_drvdata(dev);
+       int i;
+
+       for (i = jpeg->variant->num_clocks - 1; i >= 0; i--)
+               clk_disable_unprepare(jpeg->clocks[i]);
+
+       return 0;
+}
+
+static int s5p_jpeg_runtime_resume(struct device *dev)
+{
+       struct s5p_jpeg *jpeg = dev_get_drvdata(dev);
+       unsigned long flags;
+       int i, ret;
+
+       for (i = 0; i < jpeg->variant->num_clocks; i++) {
+               ret = clk_prepare_enable(jpeg->clocks[i]);
+               if (ret) {
+                       while (--i >= 0)
+                               clk_disable_unprepare(jpeg->clocks[i]);
+                       return ret;
+               }
+       }
+
+       spin_lock_irqsave(&jpeg->slock, flags);
+
+       /*
+        * JPEG IP allows storing two Huffman tables for each component.
+        * We fill table 0 for each component and do this here only
+        * for S5PC210 and Exynos3250 SoCs. Exynos4x12 and Exynos542x SoC
+        * require programming their Huffman tables each time the encoding
+        * process is initialized, and thus it is accomplished in the
+        * device_run callback of m2m_ops.
+        */
+       if (!jpeg->variant->htbl_reinit) {
+               s5p_jpeg_set_hdctbl(jpeg->regs);
+               s5p_jpeg_set_hdctblg(jpeg->regs);
+               s5p_jpeg_set_hactbl(jpeg->regs);
+               s5p_jpeg_set_hactblg(jpeg->regs);
+       }
+
+       spin_unlock_irqrestore(&jpeg->slock, flags);
+
+       return 0;
+}
+#endif /* CONFIG_PM */
+
+static const struct dev_pm_ops s5p_jpeg_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+                               pm_runtime_force_resume)
+       SET_RUNTIME_PM_OPS(s5p_jpeg_runtime_suspend, s5p_jpeg_runtime_resume,
+                          NULL)
+};
+
+static struct s5p_jpeg_variant s5p_jpeg_drvdata = {
+       .version        = SJPEG_S5P,
+       .jpeg_irq       = s5p_jpeg_irq,
+       .m2m_ops        = &s5p_jpeg_m2m_ops,
+       .fmt_ver_flag   = SJPEG_FMT_FLAG_S5P,
+       .clk_names      = {"jpeg"},
+       .num_clocks     = 1,
+};
+
+static struct s5p_jpeg_variant exynos3250_jpeg_drvdata = {
+       .version        = SJPEG_EXYNOS3250,
+       .jpeg_irq       = exynos3250_jpeg_irq,
+       .m2m_ops        = &exynos3250_jpeg_m2m_ops,
+       .fmt_ver_flag   = SJPEG_FMT_FLAG_EXYNOS3250,
+       .hw3250_compat  = 1,
+       .clk_names      = {"jpeg", "sclk"},
+       .num_clocks     = 2,
+};
+
+static struct s5p_jpeg_variant exynos4_jpeg_drvdata = {
+       .version        = SJPEG_EXYNOS4,
+       .jpeg_irq       = exynos4_jpeg_irq,
+       .m2m_ops        = &exynos4_jpeg_m2m_ops,
+       .fmt_ver_flag   = SJPEG_FMT_FLAG_EXYNOS4,
+       .htbl_reinit    = 1,
+       .clk_names      = {"jpeg"},
+       .num_clocks     = 1,
+       .hw_ex4_compat  = 1,
+};
+
+static struct s5p_jpeg_variant exynos5420_jpeg_drvdata = {
+       .version        = SJPEG_EXYNOS5420,
+       .jpeg_irq       = exynos3250_jpeg_irq,          /* intentionally 3250 */
+       .m2m_ops        = &exynos3250_jpeg_m2m_ops,     /* intentionally 3250 */
+       .fmt_ver_flag   = SJPEG_FMT_FLAG_EXYNOS3250,    /* intentionally 3250 */
+       .hw3250_compat  = 1,
+       .htbl_reinit    = 1,
+       .clk_names      = {"jpeg"},
+       .num_clocks     = 1,
+};
+
+static struct s5p_jpeg_variant exynos5433_jpeg_drvdata = {
+       .version        = SJPEG_EXYNOS5433,
+       .jpeg_irq       = exynos4_jpeg_irq,
+       .m2m_ops        = &exynos4_jpeg_m2m_ops,
+       .fmt_ver_flag   = SJPEG_FMT_FLAG_EXYNOS4,
+       .htbl_reinit    = 1,
+       .clk_names      = {"pclk", "aclk", "aclk_xiu", "sclk"},
+       .num_clocks     = 4,
+       .hw_ex4_compat  = 1,
+};
+
+static const struct of_device_id samsung_jpeg_match[] = {
+       {
+               .compatible = "samsung,s5pv210-jpeg",
+               .data = &s5p_jpeg_drvdata,
+       }, {
+               .compatible = "samsung,exynos3250-jpeg",
+               .data = &exynos3250_jpeg_drvdata,
+       }, {
+               .compatible = "samsung,exynos4210-jpeg",
+               .data = &exynos4_jpeg_drvdata,
+       }, {
+               .compatible = "samsung,exynos4212-jpeg",
+               .data = &exynos4_jpeg_drvdata,
+       }, {
+               .compatible = "samsung,exynos5420-jpeg",
+               .data = &exynos5420_jpeg_drvdata,
+       }, {
+               .compatible = "samsung,exynos5433-jpeg",
+               .data = &exynos5433_jpeg_drvdata,
+       },
+       {},
+};
+
+MODULE_DEVICE_TABLE(of, samsung_jpeg_match);
+
+static void *jpeg_get_drv_data(struct device *dev)
+{
+       struct s5p_jpeg_variant *driver_data = NULL;
+       const struct of_device_id *match;
+
+       if (!IS_ENABLED(CONFIG_OF) || !dev->of_node)
+               return &s5p_jpeg_drvdata;
+
+       match = of_match_node(samsung_jpeg_match, dev->of_node);
+
+       if (match)
+               driver_data = (struct s5p_jpeg_variant *)match->data;
+
+       return driver_data;
+}
+
+static struct platform_driver s5p_jpeg_driver = {
+       .probe = s5p_jpeg_probe,
+       .remove = s5p_jpeg_remove,
+       .driver = {
+               .of_match_table = of_match_ptr(samsung_jpeg_match),
+               .name           = S5P_JPEG_M2M_NAME,
+               .pm             = &s5p_jpeg_pm_ops,
+       },
+};
+
+module_platform_driver(s5p_jpeg_driver);
+
+MODULE_AUTHOR("Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>");
+MODULE_AUTHOR("Jacek Anaszewski <j.anaszewski@samsung.com>");
+MODULE_DESCRIPTION("Samsung JPEG codec driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/samsung/s5p-jpeg/jpeg-core.h b/drivers/media/platform/samsung/s5p-jpeg/jpeg-core.h
new file mode 100644 (file)
index 0000000..5570c79
--- /dev/null
@@ -0,0 +1,267 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* linux/drivers/media/platform/samsung/s5p-jpeg/jpeg-core.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
+ */
+
+#ifndef JPEG_CORE_H_
+#define JPEG_CORE_H_
+
+#include <linux/interrupt.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-fh.h>
+#include <media/v4l2-ctrls.h>
+
+#define S5P_JPEG_M2M_NAME              "s5p-jpeg"
+
+#define JPEG_MAX_CLOCKS                        4
+
+/* JPEG compression quality setting */
+#define S5P_JPEG_COMPR_QUAL_BEST       0
+#define S5P_JPEG_COMPR_QUAL_WORST      3
+
+/* JPEG RGB to YCbCr conversion matrix coefficients */
+#define S5P_JPEG_COEF11                        0x4d
+#define S5P_JPEG_COEF12                        0x97
+#define S5P_JPEG_COEF13                        0x1e
+#define S5P_JPEG_COEF21                        0x2c
+#define S5P_JPEG_COEF22                        0x57
+#define S5P_JPEG_COEF23                        0x83
+#define S5P_JPEG_COEF31                        0x83
+#define S5P_JPEG_COEF32                        0x6e
+#define S5P_JPEG_COEF33                        0x13
+
+#define EXYNOS3250_IRQ_TIMEOUT         0x10000000
+
+/* a selection of JPEG markers */
+#define JPEG_MARKER_TEM                                0x01
+#define JPEG_MARKER_SOF0                               0xc0
+#define JPEG_MARKER_DHT                                0xc4
+#define JPEG_MARKER_RST                                0xd0
+#define JPEG_MARKER_SOI                                0xd8
+#define JPEG_MARKER_EOI                                0xd9
+#define        JPEG_MARKER_SOS                         0xda
+#define JPEG_MARKER_DQT                                0xdb
+#define JPEG_MARKER_DHP                                0xde
+
+/* Flags that indicate a format can be used for capture/output */
+#define SJPEG_FMT_FLAG_ENC_CAPTURE     (1 << 0)
+#define SJPEG_FMT_FLAG_ENC_OUTPUT      (1 << 1)
+#define SJPEG_FMT_FLAG_DEC_CAPTURE     (1 << 2)
+#define SJPEG_FMT_FLAG_DEC_OUTPUT      (1 << 3)
+#define SJPEG_FMT_FLAG_S5P             (1 << 4)
+#define SJPEG_FMT_FLAG_EXYNOS3250      (1 << 5)
+#define SJPEG_FMT_FLAG_EXYNOS4         (1 << 6)
+#define SJPEG_FMT_RGB                  (1 << 7)
+#define SJPEG_FMT_NON_RGB              (1 << 8)
+
+#define S5P_JPEG_ENCODE                0
+#define S5P_JPEG_DECODE                1
+#define S5P_JPEG_DISABLE       -1
+
+#define FMT_TYPE_OUTPUT                0
+#define FMT_TYPE_CAPTURE       1
+
+#define SJPEG_SUBSAMPLING_444  0x11
+#define SJPEG_SUBSAMPLING_422  0x21
+#define SJPEG_SUBSAMPLING_420  0x22
+
+#define S5P_JPEG_MAX_MARKER    4
+
+/* Version numbers */
+enum sjpeg_version {
+       SJPEG_S5P,
+       SJPEG_EXYNOS3250,
+       SJPEG_EXYNOS4,
+       SJPEG_EXYNOS5420,
+       SJPEG_EXYNOS5433,
+};
+
+enum exynos4_jpeg_result {
+       OK_ENC_OR_DEC,
+       ERR_PROT,
+       ERR_DEC_INVALID_FORMAT,
+       ERR_MULTI_SCAN,
+       ERR_FRAME,
+       ERR_UNKNOWN,
+};
+
+enum  exynos4_jpeg_img_quality_level {
+       QUALITY_LEVEL_1 = 0,    /* high */
+       QUALITY_LEVEL_2,
+       QUALITY_LEVEL_3,
+       QUALITY_LEVEL_4,        /* low */
+};
+
+enum s5p_jpeg_ctx_state {
+       JPEGCTX_RUNNING = 0,
+       JPEGCTX_RESOLUTION_CHANGE,
+};
+
+/**
+ * struct s5p_jpeg - JPEG IP abstraction
+ * @lock:              the mutex protecting this structure
+ * @slock:             spinlock protecting the device contexts
+ * @v4l2_dev:          v4l2 device for mem2mem mode
+ * @vfd_encoder:       video device node for encoder mem2mem mode
+ * @vfd_decoder:       video device node for decoder mem2mem mode
+ * @m2m_dev:           v4l2 mem2mem device data
+ * @regs:              JPEG IP registers mapping
+ * @irq:               JPEG IP irq
+ * @irq_ret:           JPEG IP irq result value
+ * @clocks:            JPEG IP clock(s)
+ * @dev:               JPEG IP struct device
+ * @variant:           driver variant to be used
+ * @irq_status:                interrupt flags set during single encode/decode
+ *                     operation
+ */
+struct s5p_jpeg {
+       struct mutex            lock;
+       spinlock_t              slock;
+
+       struct v4l2_device      v4l2_dev;
+       struct video_device     *vfd_encoder;
+       struct video_device     *vfd_decoder;
+       struct v4l2_m2m_dev     *m2m_dev;
+
+       void __iomem            *regs;
+       unsigned int            irq;
+       enum exynos4_jpeg_result irq_ret;
+       struct clk              *clocks[JPEG_MAX_CLOCKS];
+       struct device           *dev;
+       struct s5p_jpeg_variant *variant;
+       u32                     irq_status;
+};
+
+struct s5p_jpeg_variant {
+       unsigned int            version;
+       unsigned int            fmt_ver_flag;
+       unsigned int            hw3250_compat:1;
+       unsigned int            htbl_reinit:1;
+       unsigned int            hw_ex4_compat:1;
+       const struct v4l2_m2m_ops *m2m_ops;
+       irqreturn_t             (*jpeg_irq)(int irq, void *priv);
+       const char              *clk_names[JPEG_MAX_CLOCKS];
+       int                     num_clocks;
+};
+
+/**
+ * struct s5p_jpeg_fmt - driver's internal color format data
+ * @fourcc:    the fourcc code, 0 if not applicable
+ * @depth:     number of bits per pixel
+ * @colplanes: number of color planes (1 for packed formats)
+ * @memplanes: number of memory planes (1 for packed formats)
+ * @h_align:   horizontal alignment order (align to 2^h_align)
+ * @v_align:   vertical alignment order (align to 2^v_align)
+ * @subsampling:subsampling of a raw format or a JPEG
+ * @flags:     flags describing format applicability
+ */
+struct s5p_jpeg_fmt {
+       u32     fourcc;
+       int     depth;
+       int     colplanes;
+       int     memplanes;
+       int     h_align;
+       int     v_align;
+       int     subsampling;
+       u32     flags;
+};
+
+/**
+ * struct s5p_jpeg_marker - collection of markers from jpeg header
+ * @marker:    markers' positions relative to the buffer beginning
+ * @len:       markers' payload lengths (without length field)
+ * @n:         number of markers in collection
+ */
+struct s5p_jpeg_marker {
+       u32     marker[S5P_JPEG_MAX_MARKER];
+       u32     len[S5P_JPEG_MAX_MARKER];
+       u32     n;
+};
+
+/**
+ * struct s5p_jpeg_q_data - parameters of one queue
+ * @fmt:       driver-specific format of this queue
+ * @w:         image width
+ * @h:         image height
+ * @sos:       JPEG_MARKER_SOS's position relative to the buffer beginning
+ * @dht:       JPEG_MARKER_DHT' positions relative to the buffer beginning
+ * @dqt:       JPEG_MARKER_DQT' positions relative to the buffer beginning
+ * @sof:       JPEG_MARKER_SOF0's position relative to the buffer beginning
+ * @sof_len:   JPEG_MARKER_SOF0's payload length (without length field itself)
+ * @size:      image buffer size in bytes
+ */
+struct s5p_jpeg_q_data {
+       struct s5p_jpeg_fmt     *fmt;
+       u32                     w;
+       u32                     h;
+       u32                     sos;
+       struct s5p_jpeg_marker  dht;
+       struct s5p_jpeg_marker  dqt;
+       u32                     sof;
+       u32                     sof_len;
+       u32                     size;
+};
+
+/**
+ * struct s5p_jpeg_ctx - the device context data
+ * @jpeg:              JPEG IP device for this context
+ * @mode:              compression (encode) operation or decompression (decode)
+ * @compr_quality:     destination image quality in compression (encode) mode
+ * @restart_interval:  JPEG restart interval for JPEG encoding
+ * @subsampling:       subsampling of a raw format or a JPEG
+ * @out_q:             source (output) queue information
+ * @cap_q:             destination (capture) queue queue information
+ * @scale_factor:      scale factor for JPEG decoding
+ * @crop_rect:         a rectangle representing crop area of the output buffer
+ * @fh:                        V4L2 file handle
+ * @hdr_parsed:                set if header has been parsed during decompression
+ * @crop_altered:      set if crop rectangle has been altered by the user space
+ * @ctrl_handler:      controls handler
+ * @state:             state of the context
+ */
+struct s5p_jpeg_ctx {
+       struct s5p_jpeg         *jpeg;
+       unsigned int            mode;
+       unsigned short          compr_quality;
+       unsigned short          restart_interval;
+       unsigned short          subsampling;
+       struct s5p_jpeg_q_data  out_q;
+       struct s5p_jpeg_q_data  cap_q;
+       unsigned int            scale_factor;
+       struct v4l2_rect        crop_rect;
+       struct v4l2_fh          fh;
+       bool                    hdr_parsed;
+       bool                    crop_altered;
+       struct v4l2_ctrl_handler ctrl_handler;
+       enum s5p_jpeg_ctx_state state;
+};
+
+/**
+ * struct s5p_jpeg_buffer - description of memory containing input JPEG data
+ * @size:      buffer size
+ * @curr:      current position in the buffer
+ * @data:      pointer to the data
+ */
+struct s5p_jpeg_buffer {
+       unsigned long size;
+       unsigned long curr;
+       unsigned long data;
+};
+
+/**
+ * struct s5p_jpeg_addr - JPEG converter physical address set for DMA
+ * @y:   luminance plane physical address
+ * @cb:  Cb plane physical address
+ * @cr:  Cr plane physical address
+ */
+struct s5p_jpeg_addr {
+       u32     y;
+       u32     cb;
+       u32     cr;
+};
+
+#endif /* JPEG_CORE_H */
diff --git a/drivers/media/platform/samsung/s5p-jpeg/jpeg-hw-exynos3250.c b/drivers/media/platform/samsung/s5p-jpeg/jpeg-hw-exynos3250.c
new file mode 100644 (file)
index 0000000..637a510
--- /dev/null
@@ -0,0 +1,486 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* linux/drivers/media/platform/exynos3250-jpeg/jpeg-hw.h
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Author: Jacek Anaszewski <j.anaszewski@samsung.com>
+ */
+
+#include <linux/io.h>
+#include <linux/videodev2.h>
+#include <linux/delay.h>
+
+#include "jpeg-core.h"
+#include "jpeg-regs.h"
+#include "jpeg-hw-exynos3250.h"
+
+void exynos3250_jpeg_reset(void __iomem *regs)
+{
+       u32 reg = 1;
+       int count = 1000;
+
+       writel(1, regs + EXYNOS3250_SW_RESET);
+       /* no other way but polling for when JPEG IP becomes operational */
+       while (reg != 0 && --count > 0) {
+               udelay(1);
+               cpu_relax();
+               reg = readl(regs + EXYNOS3250_SW_RESET);
+       }
+
+       reg = 0;
+       count = 1000;
+
+       while (reg != 1 && --count > 0) {
+               writel(1, regs + EXYNOS3250_JPGDRI);
+               udelay(1);
+               cpu_relax();
+               reg = readl(regs + EXYNOS3250_JPGDRI);
+       }
+
+       writel(0, regs + EXYNOS3250_JPGDRI);
+}
+
+void exynos3250_jpeg_poweron(void __iomem *regs)
+{
+       writel(EXYNOS3250_POWER_ON, regs + EXYNOS3250_JPGCLKCON);
+}
+
+void exynos3250_jpeg_set_dma_num(void __iomem *regs)
+{
+       writel(((EXYNOS3250_DMA_MO_COUNT << EXYNOS3250_WDMA_ISSUE_NUM_SHIFT) &
+                       EXYNOS3250_WDMA_ISSUE_NUM_MASK) |
+              ((EXYNOS3250_DMA_MO_COUNT << EXYNOS3250_RDMA_ISSUE_NUM_SHIFT) &
+                       EXYNOS3250_RDMA_ISSUE_NUM_MASK) |
+              ((EXYNOS3250_DMA_MO_COUNT << EXYNOS3250_ISSUE_GATHER_NUM_SHIFT) &
+                       EXYNOS3250_ISSUE_GATHER_NUM_MASK),
+               regs + EXYNOS3250_DMA_ISSUE_NUM);
+}
+
+void exynos3250_jpeg_clk_set(void __iomem *base)
+{
+       u32 reg;
+
+       reg = readl(base + EXYNOS3250_JPGCMOD) & ~EXYNOS3250_HALF_EN_MASK;
+
+       writel(reg | EXYNOS3250_HALF_EN, base + EXYNOS3250_JPGCMOD);
+}
+
+void exynos3250_jpeg_input_raw_fmt(void __iomem *regs, unsigned int fmt)
+{
+       u32 reg;
+
+       reg = readl(regs + EXYNOS3250_JPGCMOD) &
+                       EXYNOS3250_MODE_Y16_MASK;
+
+       switch (fmt) {
+       case V4L2_PIX_FMT_RGB32:
+               reg |= EXYNOS3250_MODE_SEL_ARGB8888;
+               break;
+       case V4L2_PIX_FMT_BGR32:
+               reg |= EXYNOS3250_MODE_SEL_ARGB8888 | EXYNOS3250_SRC_SWAP_RGB;
+               break;
+       case V4L2_PIX_FMT_RGB565:
+               reg |= EXYNOS3250_MODE_SEL_RGB565;
+               break;
+       case V4L2_PIX_FMT_RGB565X:
+               reg |= EXYNOS3250_MODE_SEL_RGB565 | EXYNOS3250_SRC_SWAP_RGB;
+               break;
+       case V4L2_PIX_FMT_YUYV:
+               reg |= EXYNOS3250_MODE_SEL_422_1P_LUM_CHR;
+               break;
+       case V4L2_PIX_FMT_YVYU:
+               reg |= EXYNOS3250_MODE_SEL_422_1P_LUM_CHR |
+                       EXYNOS3250_SRC_SWAP_UV;
+               break;
+       case V4L2_PIX_FMT_UYVY:
+               reg |= EXYNOS3250_MODE_SEL_422_1P_CHR_LUM;
+               break;
+       case V4L2_PIX_FMT_VYUY:
+               reg |= EXYNOS3250_MODE_SEL_422_1P_CHR_LUM |
+                       EXYNOS3250_SRC_SWAP_UV;
+               break;
+       case V4L2_PIX_FMT_NV12:
+               reg |= EXYNOS3250_MODE_SEL_420_2P | EXYNOS3250_SRC_NV12;
+               break;
+       case V4L2_PIX_FMT_NV21:
+               reg |= EXYNOS3250_MODE_SEL_420_2P | EXYNOS3250_SRC_NV21;
+               break;
+       case V4L2_PIX_FMT_YUV420:
+               reg |= EXYNOS3250_MODE_SEL_420_3P;
+               break;
+       default:
+               break;
+
+       }
+
+       writel(reg, regs + EXYNOS3250_JPGCMOD);
+}
+
+void exynos3250_jpeg_set_y16(void __iomem *regs, bool y16)
+{
+       u32 reg;
+
+       reg = readl(regs + EXYNOS3250_JPGCMOD);
+       if (y16)
+               reg |= EXYNOS3250_MODE_Y16;
+       else
+               reg &= ~EXYNOS3250_MODE_Y16_MASK;
+       writel(reg, regs + EXYNOS3250_JPGCMOD);
+}
+
+void exynos3250_jpeg_proc_mode(void __iomem *regs, unsigned int mode)
+{
+       u32 reg, m;
+
+       if (mode == S5P_JPEG_ENCODE)
+               m = EXYNOS3250_PROC_MODE_COMPR;
+       else
+               m = EXYNOS3250_PROC_MODE_DECOMPR;
+       reg = readl(regs + EXYNOS3250_JPGMOD);
+       reg &= ~EXYNOS3250_PROC_MODE_MASK;
+       reg |= m;
+       writel(reg, regs + EXYNOS3250_JPGMOD);
+}
+
+void exynos3250_jpeg_subsampling_mode(void __iomem *regs, unsigned int mode)
+{
+       u32 reg, m = 0;
+
+       switch (mode) {
+       case V4L2_JPEG_CHROMA_SUBSAMPLING_444:
+               m = EXYNOS3250_SUBSAMPLING_MODE_444;
+               break;
+       case V4L2_JPEG_CHROMA_SUBSAMPLING_422:
+               m = EXYNOS3250_SUBSAMPLING_MODE_422;
+               break;
+       case V4L2_JPEG_CHROMA_SUBSAMPLING_420:
+               m = EXYNOS3250_SUBSAMPLING_MODE_420;
+               break;
+       }
+
+       reg = readl(regs + EXYNOS3250_JPGMOD);
+       reg &= ~EXYNOS3250_SUBSAMPLING_MODE_MASK;
+       reg |= m;
+       writel(reg, regs + EXYNOS3250_JPGMOD);
+}
+
+unsigned int exynos3250_jpeg_get_subsampling_mode(void __iomem *regs)
+{
+       return readl(regs + EXYNOS3250_JPGMOD) &
+                               EXYNOS3250_SUBSAMPLING_MODE_MASK;
+}
+
+void exynos3250_jpeg_dri(void __iomem *regs, unsigned int dri)
+{
+       u32 reg;
+
+       reg = dri & EXYNOS3250_JPGDRI_MASK;
+       writel(reg, regs + EXYNOS3250_JPGDRI);
+}
+
+void exynos3250_jpeg_qtbl(void __iomem *regs, unsigned int t, unsigned int n)
+{
+       unsigned long reg;
+
+       reg = readl(regs + EXYNOS3250_QHTBL);
+       reg &= ~EXYNOS3250_QT_NUM_MASK(t);
+       reg |= (n << EXYNOS3250_QT_NUM_SHIFT(t)) &
+                                       EXYNOS3250_QT_NUM_MASK(t);
+       writel(reg, regs + EXYNOS3250_QHTBL);
+}
+
+void exynos3250_jpeg_htbl_ac(void __iomem *regs, unsigned int t)
+{
+       unsigned long reg;
+
+       reg = readl(regs + EXYNOS3250_QHTBL);
+       reg &= ~EXYNOS3250_HT_NUM_AC_MASK(t);
+       /* this driver uses table 0 for all color components */
+       reg |= (0 << EXYNOS3250_HT_NUM_AC_SHIFT(t)) &
+                                       EXYNOS3250_HT_NUM_AC_MASK(t);
+       writel(reg, regs + EXYNOS3250_QHTBL);
+}
+
+void exynos3250_jpeg_htbl_dc(void __iomem *regs, unsigned int t)
+{
+       unsigned long reg;
+
+       reg = readl(regs + EXYNOS3250_QHTBL);
+       reg &= ~EXYNOS3250_HT_NUM_DC_MASK(t);
+       /* this driver uses table 0 for all color components */
+       reg |= (0 << EXYNOS3250_HT_NUM_DC_SHIFT(t)) &
+                                       EXYNOS3250_HT_NUM_DC_MASK(t);
+       writel(reg, regs + EXYNOS3250_QHTBL);
+}
+
+void exynos3250_jpeg_set_y(void __iomem *regs, unsigned int y)
+{
+       u32 reg;
+
+       reg = y & EXYNOS3250_JPGY_MASK;
+       writel(reg, regs + EXYNOS3250_JPGY);
+}
+
+void exynos3250_jpeg_set_x(void __iomem *regs, unsigned int x)
+{
+       u32 reg;
+
+       reg = x & EXYNOS3250_JPGX_MASK;
+       writel(reg, regs + EXYNOS3250_JPGX);
+}
+
+#if 0  /* Currently unused */
+unsigned int exynos3250_jpeg_get_y(void __iomem *regs)
+{
+       return readl(regs + EXYNOS3250_JPGY);
+}
+
+unsigned int exynos3250_jpeg_get_x(void __iomem *regs)
+{
+       return readl(regs + EXYNOS3250_JPGX);
+}
+#endif
+
+void exynos3250_jpeg_interrupts_enable(void __iomem *regs)
+{
+       u32 reg;
+
+       reg = readl(regs + EXYNOS3250_JPGINTSE);
+       reg |= (EXYNOS3250_JPEG_DONE_EN |
+               EXYNOS3250_WDMA_DONE_EN |
+               EXYNOS3250_RDMA_DONE_EN |
+               EXYNOS3250_ENC_STREAM_INT_EN |
+               EXYNOS3250_CORE_DONE_EN |
+               EXYNOS3250_ERR_INT_EN |
+               EXYNOS3250_HEAD_INT_EN);
+       writel(reg, regs + EXYNOS3250_JPGINTSE);
+}
+
+void exynos3250_jpeg_enc_stream_bound(void __iomem *regs, unsigned int size)
+{
+       u32 reg;
+
+       reg = size & EXYNOS3250_ENC_STREAM_BOUND_MASK;
+       writel(reg, regs + EXYNOS3250_ENC_STREAM_BOUND);
+}
+
+void exynos3250_jpeg_output_raw_fmt(void __iomem *regs, unsigned int fmt)
+{
+       u32 reg;
+
+       switch (fmt) {
+       case V4L2_PIX_FMT_RGB32:
+               reg = EXYNOS3250_OUT_FMT_ARGB8888;
+               break;
+       case V4L2_PIX_FMT_BGR32:
+               reg = EXYNOS3250_OUT_FMT_ARGB8888 | EXYNOS3250_OUT_SWAP_RGB;
+               break;
+       case V4L2_PIX_FMT_RGB565:
+               reg = EXYNOS3250_OUT_FMT_RGB565;
+               break;
+       case V4L2_PIX_FMT_RGB565X:
+               reg = EXYNOS3250_OUT_FMT_RGB565 | EXYNOS3250_OUT_SWAP_RGB;
+               break;
+       case V4L2_PIX_FMT_YUYV:
+               reg = EXYNOS3250_OUT_FMT_422_1P_LUM_CHR;
+               break;
+       case V4L2_PIX_FMT_YVYU:
+               reg = EXYNOS3250_OUT_FMT_422_1P_LUM_CHR |
+                       EXYNOS3250_OUT_SWAP_UV;
+               break;
+       case V4L2_PIX_FMT_UYVY:
+               reg = EXYNOS3250_OUT_FMT_422_1P_CHR_LUM;
+               break;
+       case V4L2_PIX_FMT_VYUY:
+               reg = EXYNOS3250_OUT_FMT_422_1P_CHR_LUM |
+                       EXYNOS3250_OUT_SWAP_UV;
+               break;
+       case V4L2_PIX_FMT_NV12:
+               reg = EXYNOS3250_OUT_FMT_420_2P | EXYNOS3250_OUT_NV12;
+               break;
+       case V4L2_PIX_FMT_NV21:
+               reg = EXYNOS3250_OUT_FMT_420_2P | EXYNOS3250_OUT_NV21;
+               break;
+       case V4L2_PIX_FMT_YUV420:
+               reg = EXYNOS3250_OUT_FMT_420_3P;
+               break;
+       default:
+               reg = 0;
+               break;
+       }
+
+       writel(reg, regs + EXYNOS3250_OUTFORM);
+}
+
+void exynos3250_jpeg_jpgadr(void __iomem *regs, unsigned int addr)
+{
+       writel(addr, regs + EXYNOS3250_JPG_JPGADR);
+}
+
+void exynos3250_jpeg_imgadr(void __iomem *regs, struct s5p_jpeg_addr *img_addr)
+{
+       writel(img_addr->y, regs + EXYNOS3250_LUMA_BASE);
+       writel(img_addr->cb, regs + EXYNOS3250_CHROMA_BASE);
+       writel(img_addr->cr, regs + EXYNOS3250_CHROMA_CR_BASE);
+}
+
+void exynos3250_jpeg_stride(void __iomem *regs, unsigned int img_fmt,
+                           unsigned int width)
+{
+       u32 reg_luma = 0, reg_cr = 0, reg_cb = 0;
+
+       switch (img_fmt) {
+       case V4L2_PIX_FMT_RGB32:
+               reg_luma = 4 * width;
+               break;
+       case V4L2_PIX_FMT_RGB565:
+       case V4L2_PIX_FMT_RGB565X:
+       case V4L2_PIX_FMT_YUYV:
+       case V4L2_PIX_FMT_YVYU:
+       case V4L2_PIX_FMT_UYVY:
+       case V4L2_PIX_FMT_VYUY:
+               reg_luma = 2 * width;
+               break;
+       case V4L2_PIX_FMT_NV12:
+       case V4L2_PIX_FMT_NV21:
+               reg_luma = width;
+               reg_cb = reg_luma;
+               break;
+       case V4L2_PIX_FMT_YUV420:
+               reg_luma = width;
+               reg_cb = reg_cr = reg_luma / 2;
+               break;
+       default:
+               break;
+       }
+
+       writel(reg_luma, regs + EXYNOS3250_LUMA_STRIDE);
+       writel(reg_cb, regs + EXYNOS3250_CHROMA_STRIDE);
+       writel(reg_cr, regs + EXYNOS3250_CHROMA_CR_STRIDE);
+}
+
+void exynos3250_jpeg_offset(void __iomem *regs, unsigned int x_offset,
+                               unsigned int y_offset)
+{
+       u32 reg;
+
+       reg = (y_offset << EXYNOS3250_LUMA_YY_OFFSET_SHIFT) &
+                       EXYNOS3250_LUMA_YY_OFFSET_MASK;
+       reg |= (x_offset << EXYNOS3250_LUMA_YX_OFFSET_SHIFT) &
+                       EXYNOS3250_LUMA_YX_OFFSET_MASK;
+
+       writel(reg, regs + EXYNOS3250_LUMA_XY_OFFSET);
+
+       reg = (y_offset << EXYNOS3250_CHROMA_YY_OFFSET_SHIFT) &
+                       EXYNOS3250_CHROMA_YY_OFFSET_MASK;
+       reg |= (x_offset << EXYNOS3250_CHROMA_YX_OFFSET_SHIFT) &
+                       EXYNOS3250_CHROMA_YX_OFFSET_MASK;
+
+       writel(reg, regs + EXYNOS3250_CHROMA_XY_OFFSET);
+
+       reg = (y_offset << EXYNOS3250_CHROMA_CR_YY_OFFSET_SHIFT) &
+                       EXYNOS3250_CHROMA_CR_YY_OFFSET_MASK;
+       reg |= (x_offset << EXYNOS3250_CHROMA_CR_YX_OFFSET_SHIFT) &
+                       EXYNOS3250_CHROMA_CR_YX_OFFSET_MASK;
+
+       writel(reg, regs + EXYNOS3250_CHROMA_CR_XY_OFFSET);
+}
+
+void exynos3250_jpeg_coef(void __iomem *base, unsigned int mode)
+{
+       if (mode == S5P_JPEG_ENCODE) {
+               writel(EXYNOS3250_JPEG_ENC_COEF1,
+                                       base + EXYNOS3250_JPG_COEF(1));
+               writel(EXYNOS3250_JPEG_ENC_COEF2,
+                                       base + EXYNOS3250_JPG_COEF(2));
+               writel(EXYNOS3250_JPEG_ENC_COEF3,
+                                       base + EXYNOS3250_JPG_COEF(3));
+       } else {
+               writel(EXYNOS3250_JPEG_DEC_COEF1,
+                                       base + EXYNOS3250_JPG_COEF(1));
+               writel(EXYNOS3250_JPEG_DEC_COEF2,
+                                       base + EXYNOS3250_JPG_COEF(2));
+               writel(EXYNOS3250_JPEG_DEC_COEF3,
+                                       base + EXYNOS3250_JPG_COEF(3));
+       }
+}
+
+void exynos3250_jpeg_start(void __iomem *regs)
+{
+       writel(1, regs + EXYNOS3250_JSTART);
+}
+
+void exynos3250_jpeg_rstart(void __iomem *regs)
+{
+       writel(1, regs + EXYNOS3250_JRSTART);
+}
+
+unsigned int exynos3250_jpeg_get_int_status(void __iomem *regs)
+{
+       return readl(regs + EXYNOS3250_JPGINTST);
+}
+
+void exynos3250_jpeg_clear_int_status(void __iomem *regs,
+                                     unsigned int value)
+{
+       writel(value, regs + EXYNOS3250_JPGINTST);
+}
+
+unsigned int exynos3250_jpeg_operating(void __iomem *regs)
+{
+       return readl(regs + S5P_JPGOPR) & EXYNOS3250_JPGOPR_MASK;
+}
+
+unsigned int exynos3250_jpeg_compressed_size(void __iomem *regs)
+{
+       return readl(regs + EXYNOS3250_JPGCNT) & EXYNOS3250_JPGCNT_MASK;
+}
+
+void exynos3250_jpeg_dec_stream_size(void __iomem *regs,
+                                               unsigned int size)
+{
+       writel(size & EXYNOS3250_DEC_STREAM_MASK,
+                               regs + EXYNOS3250_DEC_STREAM_SIZE);
+}
+
+void exynos3250_jpeg_dec_scaling_ratio(void __iomem *regs,
+                                               unsigned int sratio)
+{
+       switch (sratio) {
+       case 1:
+       default:
+               sratio = EXYNOS3250_DEC_SCALE_FACTOR_8_8;
+               break;
+       case 2:
+               sratio = EXYNOS3250_DEC_SCALE_FACTOR_4_8;
+               break;
+       case 4:
+               sratio = EXYNOS3250_DEC_SCALE_FACTOR_2_8;
+               break;
+       case 8:
+               sratio = EXYNOS3250_DEC_SCALE_FACTOR_1_8;
+               break;
+       }
+
+       writel(sratio & EXYNOS3250_DEC_SCALE_FACTOR_MASK,
+                               regs + EXYNOS3250_DEC_SCALING_RATIO);
+}
+
+void exynos3250_jpeg_set_timer(void __iomem *regs, unsigned int time_value)
+{
+       time_value &= EXYNOS3250_TIMER_INIT_MASK;
+
+       writel(EXYNOS3250_TIMER_INT_STAT | time_value,
+                                       regs + EXYNOS3250_TIMER_SE);
+}
+
+unsigned int exynos3250_jpeg_get_timer_status(void __iomem *regs)
+{
+       return readl(regs + EXYNOS3250_TIMER_ST);
+}
+
+void exynos3250_jpeg_clear_timer_status(void __iomem *regs)
+{
+       writel(EXYNOS3250_TIMER_INT_STAT, regs + EXYNOS3250_TIMER_ST);
+}
diff --git a/drivers/media/platform/samsung/s5p-jpeg/jpeg-hw-exynos3250.h b/drivers/media/platform/samsung/s5p-jpeg/jpeg-hw-exynos3250.h
new file mode 100644 (file)
index 0000000..15af928
--- /dev/null
@@ -0,0 +1,57 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* linux/drivers/media/platform/samsung/s5p-jpeg/jpeg-hw-exynos3250.h
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Author: Jacek Anaszewski <j.anaszewski@samsung.com>
+ */
+#ifndef JPEG_HW_EXYNOS3250_H_
+#define JPEG_HW_EXYNOS3250_H_
+
+#include <linux/io.h>
+#include <linux/videodev2.h>
+
+#include "jpeg-regs.h"
+
+void exynos3250_jpeg_reset(void __iomem *regs);
+void exynos3250_jpeg_poweron(void __iomem *regs);
+void exynos3250_jpeg_set_dma_num(void __iomem *regs);
+void exynos3250_jpeg_clk_set(void __iomem *base);
+void exynos3250_jpeg_input_raw_fmt(void __iomem *regs, unsigned int fmt);
+void exynos3250_jpeg_output_raw_fmt(void __iomem *regs, unsigned int fmt);
+void exynos3250_jpeg_set_y16(void __iomem *regs, bool y16);
+void exynos3250_jpeg_proc_mode(void __iomem *regs, unsigned int mode);
+void exynos3250_jpeg_subsampling_mode(void __iomem *regs, unsigned int mode);
+unsigned int exynos3250_jpeg_get_subsampling_mode(void __iomem *regs);
+void exynos3250_jpeg_dri(void __iomem *regs, unsigned int dri);
+void exynos3250_jpeg_qtbl(void __iomem *regs, unsigned int t, unsigned int n);
+void exynos3250_jpeg_htbl_ac(void __iomem *regs, unsigned int t);
+void exynos3250_jpeg_htbl_dc(void __iomem *regs, unsigned int t);
+void exynos3250_jpeg_set_y(void __iomem *regs, unsigned int y);
+void exynos3250_jpeg_set_x(void __iomem *regs, unsigned int x);
+void exynos3250_jpeg_interrupts_enable(void __iomem *regs);
+void exynos3250_jpeg_enc_stream_bound(void __iomem *regs, unsigned int size);
+void exynos3250_jpeg_outform_raw(void __iomem *regs, unsigned long format);
+void exynos3250_jpeg_jpgadr(void __iomem *regs, unsigned int addr);
+void exynos3250_jpeg_imgadr(void __iomem *regs, struct s5p_jpeg_addr *img_addr);
+void exynos3250_jpeg_stride(void __iomem *regs, unsigned int img_fmt,
+                           unsigned int width);
+void exynos3250_jpeg_offset(void __iomem *regs, unsigned int x_offset,
+                               unsigned int y_offset);
+void exynos3250_jpeg_coef(void __iomem *base, unsigned int mode);
+void exynos3250_jpeg_start(void __iomem *regs);
+void exynos3250_jpeg_rstart(void __iomem *regs);
+unsigned int exynos3250_jpeg_get_int_status(void __iomem *regs);
+void exynos3250_jpeg_clear_int_status(void __iomem *regs,
+                                               unsigned int value);
+unsigned int exynos3250_jpeg_operating(void __iomem *regs);
+unsigned int exynos3250_jpeg_compressed_size(void __iomem *regs);
+void exynos3250_jpeg_dec_stream_size(void __iomem *regs, unsigned int size);
+void exynos3250_jpeg_dec_scaling_ratio(void __iomem *regs, unsigned int sratio);
+void exynos3250_jpeg_set_timer(void __iomem *regs, unsigned int time_value);
+unsigned int exynos3250_jpeg_get_timer_status(void __iomem *regs);
+void exynos3250_jpeg_set_timer_status(void __iomem *regs);
+void exynos3250_jpeg_clear_timer_status(void __iomem *regs);
+
+#endif /* JPEG_HW_EXYNOS3250_H_ */
diff --git a/drivers/media/platform/samsung/s5p-jpeg/jpeg-hw-exynos4.c b/drivers/media/platform/samsung/s5p-jpeg/jpeg-hw-exynos4.c
new file mode 100644 (file)
index 0000000..0828cfa
--- /dev/null
@@ -0,0 +1,321 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * Author: Jacek Anaszewski <j.anaszewski@samsung.com>
+ *
+ * Register interface file for JPEG driver on Exynos4x12.
+ */
+#include <linux/io.h>
+#include <linux/delay.h>
+
+#include "jpeg-core.h"
+#include "jpeg-hw-exynos4.h"
+#include "jpeg-regs.h"
+
+void exynos4_jpeg_sw_reset(void __iomem *base)
+{
+       unsigned int reg;
+
+       reg = readl(base + EXYNOS4_JPEG_CNTL_REG);
+       writel(reg & ~(EXYNOS4_DEC_MODE | EXYNOS4_ENC_MODE),
+                               base + EXYNOS4_JPEG_CNTL_REG);
+
+       reg = readl(base + EXYNOS4_JPEG_CNTL_REG);
+       writel(reg & ~EXYNOS4_SOFT_RESET_HI, base + EXYNOS4_JPEG_CNTL_REG);
+
+       udelay(100);
+
+       writel(reg | EXYNOS4_SOFT_RESET_HI, base + EXYNOS4_JPEG_CNTL_REG);
+}
+
+void exynos4_jpeg_set_enc_dec_mode(void __iomem *base, unsigned int mode)
+{
+       unsigned int reg;
+
+       reg = readl(base + EXYNOS4_JPEG_CNTL_REG);
+       /* set exynos4_jpeg mod register */
+       if (mode == S5P_JPEG_DECODE) {
+               writel((reg & EXYNOS4_ENC_DEC_MODE_MASK) |
+                                       EXYNOS4_DEC_MODE,
+                       base + EXYNOS4_JPEG_CNTL_REG);
+       } else if (mode == S5P_JPEG_ENCODE) {/* encode */
+               writel((reg & EXYNOS4_ENC_DEC_MODE_MASK) |
+                                       EXYNOS4_ENC_MODE,
+                       base + EXYNOS4_JPEG_CNTL_REG);
+       } else { /* disable both */
+               writel(reg & EXYNOS4_ENC_DEC_MODE_MASK,
+                       base + EXYNOS4_JPEG_CNTL_REG);
+       }
+}
+
+void __exynos4_jpeg_set_img_fmt(void __iomem *base, unsigned int img_fmt,
+                               unsigned int version)
+{
+       unsigned int reg;
+       unsigned int exynos4_swap_chroma_cbcr;
+       unsigned int exynos4_swap_chroma_crcb;
+
+       if (version == SJPEG_EXYNOS4) {
+               exynos4_swap_chroma_cbcr = EXYNOS4_SWAP_CHROMA_CBCR;
+               exynos4_swap_chroma_crcb = EXYNOS4_SWAP_CHROMA_CRCB;
+       } else {
+               exynos4_swap_chroma_cbcr = EXYNOS5433_SWAP_CHROMA_CBCR;
+               exynos4_swap_chroma_crcb = EXYNOS5433_SWAP_CHROMA_CRCB;
+       }
+
+       reg = readl(base + EXYNOS4_IMG_FMT_REG) &
+                       EXYNOS4_ENC_IN_FMT_MASK; /* clear except enc format */
+
+       switch (img_fmt) {
+       case V4L2_PIX_FMT_GREY:
+               reg = reg | EXYNOS4_ENC_GRAY_IMG | EXYNOS4_GRAY_IMG_IP;
+               break;
+       case V4L2_PIX_FMT_RGB32:
+               reg = reg | EXYNOS4_ENC_RGB_IMG |
+                               EXYNOS4_RGB_IP_RGB_32BIT_IMG;
+               break;
+       case V4L2_PIX_FMT_RGB565:
+               reg = reg | EXYNOS4_ENC_RGB_IMG |
+                               EXYNOS4_RGB_IP_RGB_16BIT_IMG;
+               break;
+       case V4L2_PIX_FMT_NV24:
+               reg = reg | EXYNOS4_ENC_YUV_444_IMG |
+                               EXYNOS4_YUV_444_IP_YUV_444_2P_IMG |
+                               exynos4_swap_chroma_cbcr;
+               break;
+       case V4L2_PIX_FMT_NV42:
+               reg = reg | EXYNOS4_ENC_YUV_444_IMG |
+                               EXYNOS4_YUV_444_IP_YUV_444_2P_IMG |
+                               exynos4_swap_chroma_crcb;
+               break;
+       case V4L2_PIX_FMT_YUYV:
+               reg = reg | EXYNOS4_DEC_YUV_422_IMG |
+                               EXYNOS4_YUV_422_IP_YUV_422_1P_IMG |
+                               exynos4_swap_chroma_cbcr;
+               break;
+
+       case V4L2_PIX_FMT_YVYU:
+               reg = reg | EXYNOS4_DEC_YUV_422_IMG |
+                               EXYNOS4_YUV_422_IP_YUV_422_1P_IMG |
+                               exynos4_swap_chroma_crcb;
+               break;
+       case V4L2_PIX_FMT_NV16:
+               reg = reg | EXYNOS4_DEC_YUV_422_IMG |
+                               EXYNOS4_YUV_422_IP_YUV_422_2P_IMG |
+                               exynos4_swap_chroma_cbcr;
+               break;
+       case V4L2_PIX_FMT_NV61:
+               reg = reg | EXYNOS4_DEC_YUV_422_IMG |
+                               EXYNOS4_YUV_422_IP_YUV_422_2P_IMG |
+                               exynos4_swap_chroma_crcb;
+               break;
+       case V4L2_PIX_FMT_NV12:
+               reg = reg | EXYNOS4_DEC_YUV_420_IMG |
+                               EXYNOS4_YUV_420_IP_YUV_420_2P_IMG |
+                               exynos4_swap_chroma_cbcr;
+               break;
+       case V4L2_PIX_FMT_NV21:
+               reg = reg | EXYNOS4_DEC_YUV_420_IMG |
+                               EXYNOS4_YUV_420_IP_YUV_420_2P_IMG |
+                               exynos4_swap_chroma_crcb;
+               break;
+       case V4L2_PIX_FMT_YUV420:
+               reg = reg | EXYNOS4_DEC_YUV_420_IMG |
+                               EXYNOS4_YUV_420_IP_YUV_420_3P_IMG |
+                               exynos4_swap_chroma_cbcr;
+               break;
+       default:
+               break;
+
+       }
+
+       writel(reg, base + EXYNOS4_IMG_FMT_REG);
+}
+
+void __exynos4_jpeg_set_enc_out_fmt(void __iomem *base, unsigned int out_fmt,
+                                   unsigned int version)
+{
+       unsigned int reg;
+
+       reg = readl(base + EXYNOS4_IMG_FMT_REG) &
+                       ~(version == SJPEG_EXYNOS4 ? EXYNOS4_ENC_FMT_MASK :
+                         EXYNOS5433_ENC_FMT_MASK); /* clear enc format */
+
+       switch (out_fmt) {
+       case V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY:
+               reg = reg | EXYNOS4_ENC_FMT_GRAY;
+               break;
+
+       case V4L2_JPEG_CHROMA_SUBSAMPLING_444:
+               reg = reg | EXYNOS4_ENC_FMT_YUV_444;
+               break;
+
+       case V4L2_JPEG_CHROMA_SUBSAMPLING_422:
+               reg = reg | EXYNOS4_ENC_FMT_YUV_422;
+               break;
+
+       case V4L2_JPEG_CHROMA_SUBSAMPLING_420:
+               reg = reg | EXYNOS4_ENC_FMT_YUV_420;
+               break;
+
+       default:
+               break;
+       }
+
+       writel(reg, base + EXYNOS4_IMG_FMT_REG);
+}
+
+void exynos4_jpeg_set_interrupt(void __iomem *base, unsigned int version)
+{
+       unsigned int reg;
+
+       if (version == SJPEG_EXYNOS4) {
+               reg = readl(base + EXYNOS4_INT_EN_REG) & ~EXYNOS4_INT_EN_MASK;
+               writel(reg | EXYNOS4_INT_EN_ALL, base + EXYNOS4_INT_EN_REG);
+       } else {
+               reg = readl(base + EXYNOS4_INT_EN_REG) &
+                                                       ~EXYNOS5433_INT_EN_MASK;
+               writel(reg | EXYNOS5433_INT_EN_ALL, base + EXYNOS4_INT_EN_REG);
+       }
+}
+
+unsigned int exynos4_jpeg_get_int_status(void __iomem *base)
+{
+       return readl(base + EXYNOS4_INT_STATUS_REG);
+}
+
+unsigned int exynos4_jpeg_get_fifo_status(void __iomem *base)
+{
+       return readl(base + EXYNOS4_FIFO_STATUS_REG);
+}
+
+void exynos4_jpeg_set_huf_table_enable(void __iomem *base, int value)
+{
+       unsigned int    reg;
+
+       reg = readl(base + EXYNOS4_JPEG_CNTL_REG) & ~EXYNOS4_HUF_TBL_EN;
+
+       if (value == 1)
+               writel(reg | EXYNOS4_HUF_TBL_EN,
+                                       base + EXYNOS4_JPEG_CNTL_REG);
+       else
+               writel(reg & ~EXYNOS4_HUF_TBL_EN,
+                                       base + EXYNOS4_JPEG_CNTL_REG);
+}
+
+void exynos4_jpeg_set_sys_int_enable(void __iomem *base, int value)
+{
+       unsigned int    reg;
+
+       reg = readl(base + EXYNOS4_JPEG_CNTL_REG) & ~(EXYNOS4_SYS_INT_EN);
+
+       if (value == 1)
+               writel(reg | EXYNOS4_SYS_INT_EN, base + EXYNOS4_JPEG_CNTL_REG);
+       else
+               writel(reg & ~EXYNOS4_SYS_INT_EN, base + EXYNOS4_JPEG_CNTL_REG);
+}
+
+void exynos4_jpeg_set_stream_buf_address(void __iomem *base,
+                                        unsigned int address)
+{
+       writel(address, base + EXYNOS4_OUT_MEM_BASE_REG);
+}
+
+void exynos4_jpeg_set_stream_size(void __iomem *base,
+               unsigned int x_value, unsigned int y_value)
+{
+       writel(0x0, base + EXYNOS4_JPEG_IMG_SIZE_REG); /* clear */
+       writel(EXYNOS4_X_SIZE(x_value) | EXYNOS4_Y_SIZE(y_value),
+                       base + EXYNOS4_JPEG_IMG_SIZE_REG);
+}
+
+void exynos4_jpeg_set_frame_buf_address(void __iomem *base,
+                               struct s5p_jpeg_addr *exynos4_jpeg_addr)
+{
+       writel(exynos4_jpeg_addr->y, base + EXYNOS4_IMG_BA_PLANE_1_REG);
+       writel(exynos4_jpeg_addr->cb, base + EXYNOS4_IMG_BA_PLANE_2_REG);
+       writel(exynos4_jpeg_addr->cr, base + EXYNOS4_IMG_BA_PLANE_3_REG);
+}
+
+void exynos4_jpeg_set_encode_tbl_select(void __iomem *base,
+               enum exynos4_jpeg_img_quality_level level)
+{
+       unsigned int    reg;
+
+       reg = EXYNOS4_Q_TBL_COMP1_0 | EXYNOS4_Q_TBL_COMP2_1 |
+               EXYNOS4_Q_TBL_COMP3_1 |
+               EXYNOS4_HUFF_TBL_COMP1_AC_0_DC_1 |
+               EXYNOS4_HUFF_TBL_COMP2_AC_0_DC_0 |
+               EXYNOS4_HUFF_TBL_COMP3_AC_1_DC_1;
+
+       writel(reg, base + EXYNOS4_TBL_SEL_REG);
+}
+
+void exynos4_jpeg_set_dec_components(void __iomem *base, int n)
+{
+       unsigned int    reg;
+
+       reg = readl(base + EXYNOS4_TBL_SEL_REG);
+
+       reg |= EXYNOS4_NF(n);
+       writel(reg, base + EXYNOS4_TBL_SEL_REG);
+}
+
+void exynos4_jpeg_select_dec_q_tbl(void __iomem *base, char c, char x)
+{
+       unsigned int    reg;
+
+       reg = readl(base + EXYNOS4_TBL_SEL_REG);
+
+       reg |= EXYNOS4_Q_TBL_COMP(c, x);
+       writel(reg, base + EXYNOS4_TBL_SEL_REG);
+}
+
+void exynos4_jpeg_select_dec_h_tbl(void __iomem *base, char c, char x)
+{
+       unsigned int    reg;
+
+       reg = readl(base + EXYNOS4_TBL_SEL_REG);
+
+       reg |= EXYNOS4_HUFF_TBL_COMP(c, x);
+       writel(reg, base + EXYNOS4_TBL_SEL_REG);
+}
+
+void exynos4_jpeg_set_encode_hoff_cnt(void __iomem *base, unsigned int fmt)
+{
+       if (fmt == V4L2_PIX_FMT_GREY)
+               writel(0xd2, base + EXYNOS4_HUFF_CNT_REG);
+       else
+               writel(0x1a2, base + EXYNOS4_HUFF_CNT_REG);
+}
+
+unsigned int exynos4_jpeg_get_stream_size(void __iomem *base)
+{
+       return readl(base + EXYNOS4_BITSTREAM_SIZE_REG);
+}
+
+void exynos4_jpeg_set_dec_bitstream_size(void __iomem *base, unsigned int size)
+{
+       writel(size, base + EXYNOS4_BITSTREAM_SIZE_REG);
+}
+
+void exynos4_jpeg_get_frame_size(void __iomem *base,
+                       unsigned int *width, unsigned int *height)
+{
+       *width = (readl(base + EXYNOS4_DECODE_XY_SIZE_REG) &
+                               EXYNOS4_DECODED_SIZE_MASK);
+       *height = (readl(base + EXYNOS4_DECODE_XY_SIZE_REG) >> 16) &
+                               EXYNOS4_DECODED_SIZE_MASK;
+}
+
+unsigned int exynos4_jpeg_get_frame_fmt(void __iomem *base)
+{
+       return readl(base + EXYNOS4_DECODE_IMG_FMT_REG) &
+                               EXYNOS4_JPEG_DECODED_IMG_FMT_MASK;
+}
+
+void exynos4_jpeg_set_timer_count(void __iomem *base, unsigned int size)
+{
+       writel(size, base + EXYNOS4_INT_TIMER_COUNT_REG);
+}
diff --git a/drivers/media/platform/samsung/s5p-jpeg/jpeg-hw-exynos4.h b/drivers/media/platform/samsung/s5p-jpeg/jpeg-hw-exynos4.h
new file mode 100644 (file)
index 0000000..3e28875
--- /dev/null
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * Author: Jacek Anaszewski <j.anaszewski@samsung.com>
+ *
+ * Header file of the register interface for JPEG driver on Exynos4x12.
+*/
+
+#ifndef JPEG_HW_EXYNOS4_H_
+#define JPEG_HW_EXYNOS4_H_
+
+void exynos4_jpeg_sw_reset(void __iomem *base);
+void exynos4_jpeg_set_enc_dec_mode(void __iomem *base, unsigned int mode);
+void __exynos4_jpeg_set_img_fmt(void __iomem *base, unsigned int img_fmt,
+                               unsigned int version);
+void __exynos4_jpeg_set_enc_out_fmt(void __iomem *base, unsigned int out_fmt,
+                                   unsigned int version);
+void exynos4_jpeg_set_enc_tbl(void __iomem *base);
+void exynos4_jpeg_set_interrupt(void __iomem *base, unsigned int version);
+unsigned int exynos4_jpeg_get_int_status(void __iomem *base);
+void exynos4_jpeg_set_huf_table_enable(void __iomem *base, int value);
+void exynos4_jpeg_set_sys_int_enable(void __iomem *base, int value);
+void exynos4_jpeg_set_stream_buf_address(void __iomem *base,
+                                        unsigned int address);
+void exynos4_jpeg_set_stream_size(void __iomem *base,
+               unsigned int x_value, unsigned int y_value);
+void exynos4_jpeg_set_frame_buf_address(void __iomem *base,
+                               struct s5p_jpeg_addr *jpeg_addr);
+void exynos4_jpeg_set_encode_tbl_select(void __iomem *base,
+               enum exynos4_jpeg_img_quality_level level);
+void exynos4_jpeg_set_dec_components(void __iomem *base, int n);
+void exynos4_jpeg_select_dec_q_tbl(void __iomem *base, char c, char x);
+void exynos4_jpeg_select_dec_h_tbl(void __iomem *base, char c, char x);
+void exynos4_jpeg_set_encode_hoff_cnt(void __iomem *base, unsigned int fmt);
+void exynos4_jpeg_set_dec_bitstream_size(void __iomem *base, unsigned int size);
+unsigned int exynos4_jpeg_get_stream_size(void __iomem *base);
+void exynos4_jpeg_get_frame_size(void __iomem *base,
+                       unsigned int *width, unsigned int *height);
+unsigned int exynos4_jpeg_get_frame_fmt(void __iomem *base);
+unsigned int exynos4_jpeg_get_fifo_status(void __iomem *base);
+void exynos4_jpeg_set_timer_count(void __iomem *base, unsigned int size);
+
+#endif /* JPEG_HW_EXYNOS4_H_ */
diff --git a/drivers/media/platform/samsung/s5p-jpeg/jpeg-hw-s5p.c b/drivers/media/platform/samsung/s5p-jpeg/jpeg-hw-s5p.c
new file mode 100644 (file)
index 0000000..01b47b3
--- /dev/null
@@ -0,0 +1,306 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* linux/drivers/media/platform/samsung/s5p-jpeg/jpeg-hw.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
+ */
+
+#include <linux/io.h>
+#include <linux/videodev2.h>
+
+#include "jpeg-core.h"
+#include "jpeg-regs.h"
+#include "jpeg-hw-s5p.h"
+
+void s5p_jpeg_reset(void __iomem *regs)
+{
+       unsigned long reg;
+
+       writel(1, regs + S5P_JPG_SW_RESET);
+       reg = readl(regs + S5P_JPG_SW_RESET);
+       /* no other way but polling for when JPEG IP becomes operational */
+       while (reg != 0) {
+               cpu_relax();
+               reg = readl(regs + S5P_JPG_SW_RESET);
+       }
+}
+
+void s5p_jpeg_poweron(void __iomem *regs)
+{
+       writel(S5P_POWER_ON, regs + S5P_JPGCLKCON);
+}
+
+void s5p_jpeg_input_raw_mode(void __iomem *regs, unsigned long mode)
+{
+       unsigned long reg, m;
+
+       m = S5P_MOD_SEL_565;
+       if (mode == S5P_JPEG_RAW_IN_565)
+               m = S5P_MOD_SEL_565;
+       else if (mode == S5P_JPEG_RAW_IN_422)
+               m = S5P_MOD_SEL_422;
+
+       reg = readl(regs + S5P_JPGCMOD);
+       reg &= ~S5P_MOD_SEL_MASK;
+       reg |= m;
+       writel(reg, regs + S5P_JPGCMOD);
+}
+
+void s5p_jpeg_proc_mode(void __iomem *regs, unsigned long mode)
+{
+       unsigned long reg, m;
+
+       m = S5P_PROC_MODE_DECOMPR;
+       if (mode == S5P_JPEG_ENCODE)
+               m = S5P_PROC_MODE_COMPR;
+       else
+               m = S5P_PROC_MODE_DECOMPR;
+       reg = readl(regs + S5P_JPGMOD);
+       reg &= ~S5P_PROC_MODE_MASK;
+       reg |= m;
+       writel(reg, regs + S5P_JPGMOD);
+}
+
+void s5p_jpeg_subsampling_mode(void __iomem *regs, unsigned int mode)
+{
+       unsigned long reg, m;
+
+       if (mode == V4L2_JPEG_CHROMA_SUBSAMPLING_420)
+               m = S5P_SUBSAMPLING_MODE_420;
+       else
+               m = S5P_SUBSAMPLING_MODE_422;
+
+       reg = readl(regs + S5P_JPGMOD);
+       reg &= ~S5P_SUBSAMPLING_MODE_MASK;
+       reg |= m;
+       writel(reg, regs + S5P_JPGMOD);
+}
+
+unsigned int s5p_jpeg_get_subsampling_mode(void __iomem *regs)
+{
+       return readl(regs + S5P_JPGMOD) & S5P_SUBSAMPLING_MODE_MASK;
+}
+
+void s5p_jpeg_dri(void __iomem *regs, unsigned int dri)
+{
+       unsigned long reg;
+
+       reg = readl(regs + S5P_JPGDRI_U);
+       reg &= ~0xff;
+       reg |= (dri >> 8) & 0xff;
+       writel(reg, regs + S5P_JPGDRI_U);
+
+       reg = readl(regs + S5P_JPGDRI_L);
+       reg &= ~0xff;
+       reg |= dri & 0xff;
+       writel(reg, regs + S5P_JPGDRI_L);
+}
+
+void s5p_jpeg_qtbl(void __iomem *regs, unsigned int t, unsigned int n)
+{
+       unsigned long reg;
+
+       reg = readl(regs + S5P_JPG_QTBL);
+       reg &= ~S5P_QT_NUMt_MASK(t);
+       reg |= (n << S5P_QT_NUMt_SHIFT(t)) & S5P_QT_NUMt_MASK(t);
+       writel(reg, regs + S5P_JPG_QTBL);
+}
+
+void s5p_jpeg_htbl_ac(void __iomem *regs, unsigned int t)
+{
+       unsigned long reg;
+
+       reg = readl(regs + S5P_JPG_HTBL);
+       reg &= ~S5P_HT_NUMt_AC_MASK(t);
+       /* this driver uses table 0 for all color components */
+       reg |= (0 << S5P_HT_NUMt_AC_SHIFT(t)) & S5P_HT_NUMt_AC_MASK(t);
+       writel(reg, regs + S5P_JPG_HTBL);
+}
+
+void s5p_jpeg_htbl_dc(void __iomem *regs, unsigned int t)
+{
+       unsigned long reg;
+
+       reg = readl(regs + S5P_JPG_HTBL);
+       reg &= ~S5P_HT_NUMt_DC_MASK(t);
+       /* this driver uses table 0 for all color components */
+       reg |= (0 << S5P_HT_NUMt_DC_SHIFT(t)) & S5P_HT_NUMt_DC_MASK(t);
+       writel(reg, regs + S5P_JPG_HTBL);
+}
+
+void s5p_jpeg_y(void __iomem *regs, unsigned int y)
+{
+       unsigned long reg;
+
+       reg = readl(regs + S5P_JPGY_U);
+       reg &= ~0xff;
+       reg |= (y >> 8) & 0xff;
+       writel(reg, regs + S5P_JPGY_U);
+
+       reg = readl(regs + S5P_JPGY_L);
+       reg &= ~0xff;
+       reg |= y & 0xff;
+       writel(reg, regs + S5P_JPGY_L);
+}
+
+void s5p_jpeg_x(void __iomem *regs, unsigned int x)
+{
+       unsigned long reg;
+
+       reg = readl(regs + S5P_JPGX_U);
+       reg &= ~0xff;
+       reg |= (x >> 8) & 0xff;
+       writel(reg, regs + S5P_JPGX_U);
+
+       reg = readl(regs + S5P_JPGX_L);
+       reg &= ~0xff;
+       reg |= x & 0xff;
+       writel(reg, regs + S5P_JPGX_L);
+}
+
+void s5p_jpeg_rst_int_enable(void __iomem *regs, bool enable)
+{
+       unsigned long reg;
+
+       reg = readl(regs + S5P_JPGINTSE);
+       reg &= ~S5P_RSTm_INT_EN_MASK;
+       if (enable)
+               reg |= S5P_RSTm_INT_EN;
+       writel(reg, regs + S5P_JPGINTSE);
+}
+
+void s5p_jpeg_data_num_int_enable(void __iomem *regs, bool enable)
+{
+       unsigned long reg;
+
+       reg = readl(regs + S5P_JPGINTSE);
+       reg &= ~S5P_DATA_NUM_INT_EN_MASK;
+       if (enable)
+               reg |= S5P_DATA_NUM_INT_EN;
+       writel(reg, regs + S5P_JPGINTSE);
+}
+
+void s5p_jpeg_final_mcu_num_int_enable(void __iomem *regs, bool enbl)
+{
+       unsigned long reg;
+
+       reg = readl(regs + S5P_JPGINTSE);
+       reg &= ~S5P_FINAL_MCU_NUM_INT_EN_MASK;
+       if (enbl)
+               reg |= S5P_FINAL_MCU_NUM_INT_EN;
+       writel(reg, regs + S5P_JPGINTSE);
+}
+
+int s5p_jpeg_timer_stat(void __iomem *regs)
+{
+       return (int)((readl(regs + S5P_JPG_TIMER_ST) & S5P_TIMER_INT_STAT_MASK)
+                    >> S5P_TIMER_INT_STAT_SHIFT);
+}
+
+void s5p_jpeg_clear_timer_stat(void __iomem *regs)
+{
+       unsigned long reg;
+
+       reg = readl(regs + S5P_JPG_TIMER_SE);
+       reg &= ~S5P_TIMER_INT_STAT_MASK;
+       writel(reg, regs + S5P_JPG_TIMER_SE);
+}
+
+void s5p_jpeg_enc_stream_int(void __iomem *regs, unsigned long size)
+{
+       unsigned long reg;
+
+       reg = readl(regs + S5P_JPG_ENC_STREAM_INTSE);
+       reg &= ~S5P_ENC_STREAM_BOUND_MASK;
+       reg |= S5P_ENC_STREAM_INT_EN;
+       reg |= size & S5P_ENC_STREAM_BOUND_MASK;
+       writel(reg, regs + S5P_JPG_ENC_STREAM_INTSE);
+}
+
+int s5p_jpeg_enc_stream_stat(void __iomem *regs)
+{
+       return (int)(readl(regs + S5P_JPG_ENC_STREAM_INTST) &
+                    S5P_ENC_STREAM_INT_STAT_MASK);
+}
+
+void s5p_jpeg_clear_enc_stream_stat(void __iomem *regs)
+{
+       unsigned long reg;
+
+       reg = readl(regs + S5P_JPG_ENC_STREAM_INTSE);
+       reg &= ~S5P_ENC_STREAM_INT_MASK;
+       writel(reg, regs + S5P_JPG_ENC_STREAM_INTSE);
+}
+
+void s5p_jpeg_outform_raw(void __iomem *regs, unsigned long format)
+{
+       unsigned long reg, f;
+
+       f = S5P_DEC_OUT_FORMAT_422;
+       if (format == S5P_JPEG_RAW_OUT_422)
+               f = S5P_DEC_OUT_FORMAT_422;
+       else if (format == S5P_JPEG_RAW_OUT_420)
+               f = S5P_DEC_OUT_FORMAT_420;
+       reg = readl(regs + S5P_JPG_OUTFORM);
+       reg &= ~S5P_DEC_OUT_FORMAT_MASK;
+       reg |= f;
+       writel(reg, regs + S5P_JPG_OUTFORM);
+}
+
+void s5p_jpeg_jpgadr(void __iomem *regs, unsigned long addr)
+{
+       writel(addr, regs + S5P_JPG_JPGADR);
+}
+
+void s5p_jpeg_imgadr(void __iomem *regs, unsigned long addr)
+{
+       writel(addr, regs + S5P_JPG_IMGADR);
+}
+
+void s5p_jpeg_coef(void __iomem *regs, unsigned int i,
+                            unsigned int j, unsigned int coef)
+{
+       unsigned long reg;
+
+       reg = readl(regs + S5P_JPG_COEF(i));
+       reg &= ~S5P_COEFn_MASK(j);
+       reg |= (coef << S5P_COEFn_SHIFT(j)) & S5P_COEFn_MASK(j);
+       writel(reg, regs + S5P_JPG_COEF(i));
+}
+
+void s5p_jpeg_start(void __iomem *regs)
+{
+       writel(1, regs + S5P_JSTART);
+}
+
+int s5p_jpeg_result_stat_ok(void __iomem *regs)
+{
+       return (int)((readl(regs + S5P_JPGINTST) & S5P_RESULT_STAT_MASK)
+                    >> S5P_RESULT_STAT_SHIFT);
+}
+
+int s5p_jpeg_stream_stat_ok(void __iomem *regs)
+{
+       return !(int)((readl(regs + S5P_JPGINTST) & S5P_STREAM_STAT_MASK)
+                     >> S5P_STREAM_STAT_SHIFT);
+}
+
+void s5p_jpeg_clear_int(void __iomem *regs)
+{
+       readl(regs + S5P_JPGINTST);
+       writel(S5P_INT_RELEASE, regs + S5P_JPGCOM);
+       readl(regs + S5P_JPGOPR);
+}
+
+unsigned int s5p_jpeg_compressed_size(void __iomem *regs)
+{
+       unsigned long jpeg_size = 0;
+
+       jpeg_size |= (readl(regs + S5P_JPGCNT_U) & 0xff) << 16;
+       jpeg_size |= (readl(regs + S5P_JPGCNT_M) & 0xff) << 8;
+       jpeg_size |= (readl(regs + S5P_JPGCNT_L) & 0xff);
+
+       return (unsigned int)jpeg_size;
+}
diff --git a/drivers/media/platform/samsung/s5p-jpeg/jpeg-hw-s5p.h b/drivers/media/platform/samsung/s5p-jpeg/jpeg-hw-s5p.h
new file mode 100644 (file)
index 0000000..f068d52
--- /dev/null
@@ -0,0 +1,57 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* linux/drivers/media/platform/samsung/s5p-jpeg/jpeg-hw.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
+ */
+#ifndef JPEG_HW_S5P_H_
+#define JPEG_HW_S5P_H_
+
+#include <linux/io.h>
+#include <linux/videodev2.h>
+
+#include "jpeg-regs.h"
+
+#define S5P_JPEG_MIN_WIDTH             32
+#define S5P_JPEG_MIN_HEIGHT            32
+#define S5P_JPEG_MAX_WIDTH             8192
+#define S5P_JPEG_MAX_HEIGHT            8192
+#define S5P_JPEG_RAW_IN_565            0
+#define S5P_JPEG_RAW_IN_422            1
+#define S5P_JPEG_RAW_OUT_422           0
+#define S5P_JPEG_RAW_OUT_420           1
+
+void s5p_jpeg_reset(void __iomem *regs);
+void s5p_jpeg_poweron(void __iomem *regs);
+void s5p_jpeg_input_raw_mode(void __iomem *regs, unsigned long mode);
+void s5p_jpeg_proc_mode(void __iomem *regs, unsigned long mode);
+void s5p_jpeg_subsampling_mode(void __iomem *regs, unsigned int mode);
+unsigned int s5p_jpeg_get_subsampling_mode(void __iomem *regs);
+void s5p_jpeg_dri(void __iomem *regs, unsigned int dri);
+void s5p_jpeg_qtbl(void __iomem *regs, unsigned int t, unsigned int n);
+void s5p_jpeg_htbl_ac(void __iomem *regs, unsigned int t);
+void s5p_jpeg_htbl_dc(void __iomem *regs, unsigned int t);
+void s5p_jpeg_y(void __iomem *regs, unsigned int y);
+void s5p_jpeg_x(void __iomem *regs, unsigned int x);
+void s5p_jpeg_rst_int_enable(void __iomem *regs, bool enable);
+void s5p_jpeg_data_num_int_enable(void __iomem *regs, bool enable);
+void s5p_jpeg_final_mcu_num_int_enable(void __iomem *regs, bool enbl);
+int s5p_jpeg_timer_stat(void __iomem *regs);
+void s5p_jpeg_clear_timer_stat(void __iomem *regs);
+void s5p_jpeg_enc_stream_int(void __iomem *regs, unsigned long size);
+int s5p_jpeg_enc_stream_stat(void __iomem *regs);
+void s5p_jpeg_clear_enc_stream_stat(void __iomem *regs);
+void s5p_jpeg_outform_raw(void __iomem *regs, unsigned long format);
+void s5p_jpeg_jpgadr(void __iomem *regs, unsigned long addr);
+void s5p_jpeg_imgadr(void __iomem *regs, unsigned long addr);
+void s5p_jpeg_coef(void __iomem *regs, unsigned int i,
+                            unsigned int j, unsigned int coef);
+void s5p_jpeg_start(void __iomem *regs);
+int s5p_jpeg_result_stat_ok(void __iomem *regs);
+int s5p_jpeg_stream_stat_ok(void __iomem *regs);
+void s5p_jpeg_clear_int(void __iomem *regs);
+unsigned int s5p_jpeg_compressed_size(void __iomem *regs);
+
+#endif /* JPEG_HW_S5P_H_ */
diff --git a/drivers/media/platform/samsung/s5p-jpeg/jpeg-regs.h b/drivers/media/platform/samsung/s5p-jpeg/jpeg-regs.h
new file mode 100644 (file)
index 0000000..c2298b6
--- /dev/null
@@ -0,0 +1,646 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* linux/drivers/media/platform/samsung/s5p-jpeg/jpeg-regs.h
+ *
+ * Register definition file for Samsung JPEG codec driver
+ *
+ * Copyright (c) 2011-2014 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Author: Andrzej Pietrasiewicz <andrzejtp2010@gmail.com>
+ * Author: Jacek Anaszewski <j.anaszewski@samsung.com>
+ */
+
+#ifndef JPEG_REGS_H_
+#define JPEG_REGS_H_
+
+/* Register and bit definitions for S5PC210 */
+
+/* JPEG mode register */
+#define S5P_JPGMOD                     0x00
+#define S5P_PROC_MODE_MASK             (0x1 << 3)
+#define S5P_PROC_MODE_DECOMPR          (0x1 << 3)
+#define S5P_PROC_MODE_COMPR            (0x0 << 3)
+#define S5P_SUBSAMPLING_MODE_MASK      0x7
+#define S5P_SUBSAMPLING_MODE_444       (0x0 << 0)
+#define S5P_SUBSAMPLING_MODE_422       (0x1 << 0)
+#define S5P_SUBSAMPLING_MODE_420       (0x2 << 0)
+#define S5P_SUBSAMPLING_MODE_GRAY      (0x3 << 0)
+
+/* JPEG operation status register */
+#define S5P_JPGOPR                     0x04
+
+/* Quantization tables*/
+#define S5P_JPG_QTBL                   0x08
+#define S5P_QT_NUMt_SHIFT(t)           (((t) - 1) << 1)
+#define S5P_QT_NUMt_MASK(t)            (0x3 << S5P_QT_NUMt_SHIFT(t))
+
+/* Huffman tables */
+#define S5P_JPG_HTBL                   0x0c
+#define S5P_HT_NUMt_AC_SHIFT(t)                (((t) << 1) - 1)
+#define S5P_HT_NUMt_AC_MASK(t)         (0x1 << S5P_HT_NUMt_AC_SHIFT(t))
+
+#define S5P_HT_NUMt_DC_SHIFT(t)                (((t) - 1) << 1)
+#define S5P_HT_NUMt_DC_MASK(t)         (0x1 << S5P_HT_NUMt_DC_SHIFT(t))
+
+/* JPEG restart interval register upper byte */
+#define S5P_JPGDRI_U                   0x10
+
+/* JPEG restart interval register lower byte */
+#define S5P_JPGDRI_L                   0x14
+
+/* JPEG vertical resolution register upper byte */
+#define S5P_JPGY_U                     0x18
+
+/* JPEG vertical resolution register lower byte */
+#define S5P_JPGY_L                     0x1c
+
+/* JPEG horizontal resolution register upper byte */
+#define S5P_JPGX_U                     0x20
+
+/* JPEG horizontal resolution register lower byte */
+#define S5P_JPGX_L                     0x24
+
+/* JPEG byte count register upper byte */
+#define S5P_JPGCNT_U                   0x28
+
+/* JPEG byte count register middle byte */
+#define S5P_JPGCNT_M                   0x2c
+
+/* JPEG byte count register lower byte */
+#define S5P_JPGCNT_L                   0x30
+
+/* JPEG interrupt setting register */
+#define S5P_JPGINTSE                   0x34
+#define S5P_RSTm_INT_EN_MASK           (0x1 << 7)
+#define S5P_RSTm_INT_EN                        (0x1 << 7)
+#define S5P_DATA_NUM_INT_EN_MASK       (0x1 << 6)
+#define S5P_DATA_NUM_INT_EN            (0x1 << 6)
+#define S5P_FINAL_MCU_NUM_INT_EN_MASK  (0x1 << 5)
+#define S5P_FINAL_MCU_NUM_INT_EN       (0x1 << 5)
+
+/* JPEG interrupt status register */
+#define S5P_JPGINTST                   0x38
+#define S5P_RESULT_STAT_SHIFT          6
+#define S5P_RESULT_STAT_MASK           (0x1 << S5P_RESULT_STAT_SHIFT)
+#define S5P_STREAM_STAT_SHIFT          5
+#define S5P_STREAM_STAT_MASK           (0x1 << S5P_STREAM_STAT_SHIFT)
+
+/* JPEG command register */
+#define S5P_JPGCOM                     0x4c
+#define S5P_INT_RELEASE                        (0x1 << 2)
+
+/* Raw image data r/w address register */
+#define S5P_JPG_IMGADR                 0x50
+
+/* JPEG file r/w address register */
+#define S5P_JPG_JPGADR                 0x58
+
+/* Coefficient for RGB-to-YCbCr converter register */
+#define S5P_JPG_COEF(n)                        (0x5c + (((n) - 1) << 2))
+#define S5P_COEFn_SHIFT(j)             ((3 - (j)) << 3)
+#define S5P_COEFn_MASK(j)              (0xff << S5P_COEFn_SHIFT(j))
+
+/* JPEG color mode register */
+#define S5P_JPGCMOD                    0x68
+#define S5P_MOD_SEL_MASK               (0x7 << 5)
+#define S5P_MOD_SEL_422                        (0x1 << 5)
+#define S5P_MOD_SEL_565                        (0x2 << 5)
+#define S5P_MODE_Y16_MASK              (0x1 << 1)
+#define S5P_MODE_Y16                   (0x1 << 1)
+
+/* JPEG clock control register */
+#define S5P_JPGCLKCON                  0x6c
+#define S5P_CLK_DOWN_READY             (0x1 << 1)
+#define S5P_POWER_ON                   (0x1 << 0)
+
+/* JPEG start register */
+#define S5P_JSTART                     0x70
+
+/* JPEG SW reset register */
+#define S5P_JPG_SW_RESET               0x78
+
+/* JPEG timer setting register */
+#define S5P_JPG_TIMER_SE               0x7c
+#define S5P_TIMER_INT_EN_MASK          (0x1UL << 31)
+#define S5P_TIMER_INT_EN               (0x1UL << 31)
+#define S5P_TIMER_INIT_MASK            0x7fffffff
+
+/* JPEG timer status register */
+#define S5P_JPG_TIMER_ST               0x80
+#define S5P_TIMER_INT_STAT_SHIFT       31
+#define S5P_TIMER_INT_STAT_MASK                (0x1UL << S5P_TIMER_INT_STAT_SHIFT)
+#define S5P_TIMER_CNT_SHIFT            0
+#define S5P_TIMER_CNT_MASK             0x7fffffff
+
+/* JPEG decompression output format register */
+#define S5P_JPG_OUTFORM                        0x88
+#define S5P_DEC_OUT_FORMAT_MASK                (0x1 << 0)
+#define S5P_DEC_OUT_FORMAT_422         (0x0 << 0)
+#define S5P_DEC_OUT_FORMAT_420         (0x1 << 0)
+
+/* JPEG version register */
+#define S5P_JPG_VERSION                        0x8c
+
+/* JPEG compressed stream size interrupt setting register */
+#define S5P_JPG_ENC_STREAM_INTSE       0x98
+#define S5P_ENC_STREAM_INT_MASK                (0x1 << 24)
+#define S5P_ENC_STREAM_INT_EN          (0x1 << 24)
+#define S5P_ENC_STREAM_BOUND_MASK      0xffffff
+
+/* JPEG compressed stream size interrupt status register */
+#define S5P_JPG_ENC_STREAM_INTST       0x9c
+#define S5P_ENC_STREAM_INT_STAT_MASK   0x1
+
+/* JPEG quantizer table register */
+#define S5P_JPG_QTBL_CONTENT(n)                (0x400 + (n) * 0x100)
+
+/* JPEG DC Huffman table register */
+#define S5P_JPG_HDCTBL(n)              (0x800 + (n) * 0x400)
+
+/* JPEG DC Huffman table register */
+#define S5P_JPG_HDCTBLG(n)             (0x840 + (n) * 0x400)
+
+/* JPEG AC Huffman table register */
+#define S5P_JPG_HACTBL(n)              (0x880 + (n) * 0x400)
+
+/* JPEG AC Huffman table register */
+#define S5P_JPG_HACTBLG(n)             (0x8c0 + (n) * 0x400)
+
+
+/* Register and bit definitions for Exynos 4x12 */
+
+/* JPEG Codec Control Registers */
+#define EXYNOS4_JPEG_CNTL_REG          0x00
+#define EXYNOS4_INT_EN_REG             0x04
+#define EXYNOS4_INT_TIMER_COUNT_REG    0x08
+#define EXYNOS4_INT_STATUS_REG         0x0c
+#define EXYNOS4_OUT_MEM_BASE_REG               0x10
+#define EXYNOS4_JPEG_IMG_SIZE_REG      0x14
+#define EXYNOS4_IMG_BA_PLANE_1_REG     0x18
+#define EXYNOS4_IMG_SO_PLANE_1_REG     0x1c
+#define EXYNOS4_IMG_PO_PLANE_1_REG     0x20
+#define EXYNOS4_IMG_BA_PLANE_2_REG     0x24
+#define EXYNOS4_IMG_SO_PLANE_2_REG     0x28
+#define EXYNOS4_IMG_PO_PLANE_2_REG     0x2c
+#define EXYNOS4_IMG_BA_PLANE_3_REG     0x30
+#define EXYNOS4_IMG_SO_PLANE_3_REG     0x34
+#define EXYNOS4_IMG_PO_PLANE_3_REG     0x38
+
+#define EXYNOS4_TBL_SEL_REG            0x3c
+
+#define EXYNOS4_IMG_FMT_REG            0x40
+
+#define EXYNOS4_BITSTREAM_SIZE_REG     0x44
+#define EXYNOS4_PADDING_REG            0x48
+#define EXYNOS4_HUFF_CNT_REG           0x4c
+#define EXYNOS4_FIFO_STATUS_REG        0x50
+#define EXYNOS4_DECODE_XY_SIZE_REG     0x54
+#define EXYNOS4_DECODE_IMG_FMT_REG     0x58
+
+#define EXYNOS4_QUAN_TBL_ENTRY_REG     0x100
+#define EXYNOS4_HUFF_TBL_ENTRY_REG     0x200
+
+
+/****************************************************************/
+/* Bit definition part                                         */
+/****************************************************************/
+
+/* JPEG CNTL Register bit */
+#define EXYNOS4_ENC_DEC_MODE_MASK      (0xfffffffc << 0)
+#define EXYNOS4_DEC_MODE               (1 << 0)
+#define EXYNOS4_ENC_MODE               (1 << 1)
+#define EXYNOS4_AUTO_RST_MARKER                (1 << 2)
+#define EXYNOS4_RST_INTERVAL_SHIFT     3
+#define EXYNOS4_RST_INTERVAL(x)                (((x) & 0xffff) \
+                                               << EXYNOS4_RST_INTERVAL_SHIFT)
+#define EXYNOS4_HUF_TBL_EN             (1 << 19)
+#define EXYNOS4_HOR_SCALING_SHIFT      20
+#define EXYNOS4_HOR_SCALING_MASK       (3 << EXYNOS4_HOR_SCALING_SHIFT)
+#define EXYNOS4_HOR_SCALING(x)         (((x) & 0x3) \
+                                               << EXYNOS4_HOR_SCALING_SHIFT)
+#define EXYNOS4_VER_SCALING_SHIFT      22
+#define EXYNOS4_VER_SCALING_MASK       (3 << EXYNOS4_VER_SCALING_SHIFT)
+#define EXYNOS4_VER_SCALING(x)         (((x) & 0x3) \
+                                               << EXYNOS4_VER_SCALING_SHIFT)
+#define EXYNOS4_PADDING                        (1 << 27)
+#define EXYNOS4_SYS_INT_EN             (1 << 28)
+#define EXYNOS4_SOFT_RESET_HI          (1 << 29)
+
+/* JPEG INT Register bit */
+#define EXYNOS4_INT_EN_MASK            (0x1f << 0)
+#define EXYNOS5433_INT_EN_MASK         (0x1ff << 0)
+#define EXYNOS4_PROT_ERR_INT_EN                (1 << 0)
+#define EXYNOS4_IMG_COMPLETION_INT_EN  (1 << 1)
+#define EXYNOS4_DEC_INVALID_FORMAT_EN  (1 << 2)
+#define EXYNOS4_MULTI_SCAN_ERROR_EN    (1 << 3)
+#define EXYNOS4_FRAME_ERR_EN           (1 << 4)
+#define EXYNOS4_INT_EN_ALL             (0x1f << 0)
+#define EXYNOS5433_INT_EN_ALL          (0x1b6 << 0)
+
+#define EXYNOS4_MOD_REG_PROC_ENC       (0 << 3)
+#define EXYNOS4_MOD_REG_PROC_DEC       (1 << 3)
+
+#define EXYNOS4_MOD_REG_SUBSAMPLE_444  (0 << 0)
+#define EXYNOS4_MOD_REG_SUBSAMPLE_422  (1 << 0)
+#define EXYNOS4_MOD_REG_SUBSAMPLE_420  (2 << 0)
+#define EXYNOS4_MOD_REG_SUBSAMPLE_GRAY (3 << 0)
+
+
+/* JPEG IMAGE SIZE Register bit */
+#define EXYNOS4_X_SIZE_SHIFT           0
+#define EXYNOS4_X_SIZE_MASK            (0xffff << EXYNOS4_X_SIZE_SHIFT)
+#define EXYNOS4_X_SIZE(x)              (((x) & 0xffff) << EXYNOS4_X_SIZE_SHIFT)
+#define EXYNOS4_Y_SIZE_SHIFT           16
+#define EXYNOS4_Y_SIZE_MASK            (0xffff << EXYNOS4_Y_SIZE_SHIFT)
+#define EXYNOS4_Y_SIZE(x)              (((x) & 0xffff) << EXYNOS4_Y_SIZE_SHIFT)
+
+/* JPEG IMAGE FORMAT Register bit */
+#define EXYNOS4_ENC_IN_FMT_MASK                0xffff0000
+#define EXYNOS4_ENC_GRAY_IMG           (0 << 0)
+#define EXYNOS4_ENC_RGB_IMG            (1 << 0)
+#define EXYNOS4_ENC_YUV_444_IMG                (2 << 0)
+#define EXYNOS4_ENC_YUV_422_IMG                (3 << 0)
+#define EXYNOS4_ENC_YUV_440_IMG                (4 << 0)
+
+#define EXYNOS4_DEC_GRAY_IMG           (0 << 0)
+#define EXYNOS4_DEC_RGB_IMG            (1 << 0)
+#define EXYNOS4_DEC_YUV_444_IMG                (2 << 0)
+#define EXYNOS4_DEC_YUV_422_IMG                (3 << 0)
+#define EXYNOS4_DEC_YUV_420_IMG                (4 << 0)
+
+#define EXYNOS4_GRAY_IMG_IP_SHIFT      3
+#define EXYNOS4_GRAY_IMG_IP_MASK       (7 << EXYNOS4_GRAY_IMG_IP_SHIFT)
+#define EXYNOS4_GRAY_IMG_IP            (4 << EXYNOS4_GRAY_IMG_IP_SHIFT)
+
+#define EXYNOS4_RGB_IP_SHIFT           6
+#define EXYNOS4_RGB_IP_MASK            (7 << EXYNOS4_RGB_IP_SHIFT)
+#define EXYNOS4_RGB_IP_RGB_16BIT_IMG   (4 << EXYNOS4_RGB_IP_SHIFT)
+#define EXYNOS4_RGB_IP_RGB_32BIT_IMG   (5 << EXYNOS4_RGB_IP_SHIFT)
+
+#define EXYNOS4_YUV_444_IP_SHIFT               9
+#define EXYNOS4_YUV_444_IP_MASK                        (7 << EXYNOS4_YUV_444_IP_SHIFT)
+#define EXYNOS4_YUV_444_IP_YUV_444_2P_IMG      (4 << EXYNOS4_YUV_444_IP_SHIFT)
+#define EXYNOS4_YUV_444_IP_YUV_444_3P_IMG      (5 << EXYNOS4_YUV_444_IP_SHIFT)
+
+#define EXYNOS4_YUV_422_IP_SHIFT               12
+#define EXYNOS4_YUV_422_IP_MASK                        (7 << EXYNOS4_YUV_422_IP_SHIFT)
+#define EXYNOS4_YUV_422_IP_YUV_422_1P_IMG      (4 << EXYNOS4_YUV_422_IP_SHIFT)
+#define EXYNOS4_YUV_422_IP_YUV_422_2P_IMG      (5 << EXYNOS4_YUV_422_IP_SHIFT)
+#define EXYNOS4_YUV_422_IP_YUV_422_3P_IMG      (6 << EXYNOS4_YUV_422_IP_SHIFT)
+
+#define EXYNOS4_YUV_420_IP_SHIFT               15
+#define EXYNOS4_YUV_420_IP_MASK                        (7 << EXYNOS4_YUV_420_IP_SHIFT)
+#define EXYNOS4_YUV_420_IP_YUV_420_2P_IMG      (4 << EXYNOS4_YUV_420_IP_SHIFT)
+#define EXYNOS4_YUV_420_IP_YUV_420_3P_IMG      (5 << EXYNOS4_YUV_420_IP_SHIFT)
+
+#define EXYNOS4_ENC_FMT_SHIFT                  24
+#define EXYNOS4_ENC_FMT_MASK                   (3 << EXYNOS4_ENC_FMT_SHIFT)
+#define EXYNOS5433_ENC_FMT_MASK                        (7 << EXYNOS4_ENC_FMT_SHIFT)
+
+#define EXYNOS4_ENC_FMT_GRAY                   (0 << EXYNOS4_ENC_FMT_SHIFT)
+#define EXYNOS4_ENC_FMT_YUV_444                        (1 << EXYNOS4_ENC_FMT_SHIFT)
+#define EXYNOS4_ENC_FMT_YUV_422                        (2 << EXYNOS4_ENC_FMT_SHIFT)
+#define EXYNOS4_ENC_FMT_YUV_420                        (3 << EXYNOS4_ENC_FMT_SHIFT)
+
+#define EXYNOS4_JPEG_DECODED_IMG_FMT_MASK      0x03
+
+#define EXYNOS4_SWAP_CHROMA_CRCB               (1 << 26)
+#define EXYNOS4_SWAP_CHROMA_CBCR               (0 << 26)
+#define EXYNOS5433_SWAP_CHROMA_CRCB            (1 << 27)
+#define EXYNOS5433_SWAP_CHROMA_CBCR            (0 << 27)
+
+/* JPEG HUFF count Register bit */
+#define EXYNOS4_HUFF_COUNT_MASK                        0xffff
+
+/* JPEG Decoded_img_x_y_size Register bit */
+#define EXYNOS4_DECODED_SIZE_MASK              0x0000ffff
+
+/* JPEG Decoded image format Register bit */
+#define EXYNOS4_DECODED_IMG_FMT_MASK           0x3
+
+/* JPEG TBL SEL Register bit */
+#define EXYNOS4_Q_TBL_COMP(c, n)       ((n) << (((c) - 1) << 1))
+
+#define EXYNOS4_Q_TBL_COMP1_0          EXYNOS4_Q_TBL_COMP(1, 0)
+#define EXYNOS4_Q_TBL_COMP1_1          EXYNOS4_Q_TBL_COMP(1, 1)
+#define EXYNOS4_Q_TBL_COMP1_2          EXYNOS4_Q_TBL_COMP(1, 2)
+#define EXYNOS4_Q_TBL_COMP1_3          EXYNOS4_Q_TBL_COMP(1, 3)
+
+#define EXYNOS4_Q_TBL_COMP2_0          EXYNOS4_Q_TBL_COMP(2, 0)
+#define EXYNOS4_Q_TBL_COMP2_1          EXYNOS4_Q_TBL_COMP(2, 1)
+#define EXYNOS4_Q_TBL_COMP2_2          EXYNOS4_Q_TBL_COMP(2, 2)
+#define EXYNOS4_Q_TBL_COMP2_3          EXYNOS4_Q_TBL_COMP(2, 3)
+
+#define EXYNOS4_Q_TBL_COMP3_0          EXYNOS4_Q_TBL_COMP(3, 0)
+#define EXYNOS4_Q_TBL_COMP3_1          EXYNOS4_Q_TBL_COMP(3, 1)
+#define EXYNOS4_Q_TBL_COMP3_2          EXYNOS4_Q_TBL_COMP(3, 2)
+#define EXYNOS4_Q_TBL_COMP3_3          EXYNOS4_Q_TBL_COMP(3, 3)
+
+#define EXYNOS4_HUFF_TBL_COMP(c, n)    ((n) << ((((c) - 1) << 1) + 6))
+
+#define EXYNOS4_HUFF_TBL_COMP1_AC_0_DC_0       \
+       EXYNOS4_HUFF_TBL_COMP(1, 0)
+#define EXYNOS4_HUFF_TBL_COMP1_AC_0_DC_1       \
+       EXYNOS4_HUFF_TBL_COMP(1, 1)
+#define EXYNOS4_HUFF_TBL_COMP1_AC_1_DC_0       \
+       EXYNOS4_HUFF_TBL_COMP(1, 2)
+#define EXYNOS4_HUFF_TBL_COMP1_AC_1_DC_1       \
+       EXYNOS4_HUFF_TBL_COMP(1, 3)
+
+#define EXYNOS4_HUFF_TBL_COMP2_AC_0_DC_0       \
+       EXYNOS4_HUFF_TBL_COMP(2, 0)
+#define EXYNOS4_HUFF_TBL_COMP2_AC_0_DC_1       \
+       EXYNOS4_HUFF_TBL_COMP(2, 1)
+#define EXYNOS4_HUFF_TBL_COMP2_AC_1_DC_0       \
+       EXYNOS4_HUFF_TBL_COMP(2, 2)
+#define EXYNOS4_HUFF_TBL_COMP2_AC_1_DC_1       \
+       EXYNOS4_HUFF_TBL_COMP(2, 3)
+
+#define EXYNOS4_HUFF_TBL_COMP3_AC_0_DC_0       \
+       EXYNOS4_HUFF_TBL_COMP(3, 0)
+#define EXYNOS4_HUFF_TBL_COMP3_AC_0_DC_1       \
+       EXYNOS4_HUFF_TBL_COMP(3, 1)
+#define EXYNOS4_HUFF_TBL_COMP3_AC_1_DC_0       \
+       EXYNOS4_HUFF_TBL_COMP(3, 2)
+#define EXYNOS4_HUFF_TBL_COMP3_AC_1_DC_1       \
+       EXYNOS4_HUFF_TBL_COMP(3, 3)
+
+#define EXYNOS4_NF_SHIFT                       16
+#define EXYNOS4_NF_MASK                                0xff
+#define EXYNOS4_NF(x)                          \
+       (((x) & EXYNOS4_NF_MASK) << EXYNOS4_NF_SHIFT)
+
+/* JPEG quantizer table register */
+#define EXYNOS4_QTBL_CONTENT(n)        (0x100 + (n) * 0x40)
+
+/* JPEG DC luminance (code length) Huffman table register */
+#define EXYNOS4_HUFF_TBL_HDCLL 0x200
+
+/* JPEG DC luminance (values) Huffman table register */
+#define EXYNOS4_HUFF_TBL_HDCLV 0x210
+
+/* JPEG DC chrominance (code length) Huffman table register */
+#define EXYNOS4_HUFF_TBL_HDCCL 0x220
+
+/* JPEG DC chrominance (values) Huffman table register */
+#define EXYNOS4_HUFF_TBL_HDCCV 0x230
+
+/* JPEG AC luminance (code length) Huffman table register */
+#define EXYNOS4_HUFF_TBL_HACLL 0x240
+
+/* JPEG AC luminance (values) Huffman table register */
+#define EXYNOS4_HUFF_TBL_HACLV 0x250
+
+/* JPEG AC chrominance (code length) Huffman table register */
+#define EXYNOS4_HUFF_TBL_HACCL 0x300
+
+/* JPEG AC chrominance (values) Huffman table register */
+#define EXYNOS4_HUFF_TBL_HACCV 0x310
+
+/* Register and bit definitions for Exynos 3250 */
+
+/* JPEG mode register */
+#define EXYNOS3250_JPGMOD                      0x00
+#define EXYNOS3250_PROC_MODE_MASK              (0x1 << 3)
+#define EXYNOS3250_PROC_MODE_DECOMPR           (0x1 << 3)
+#define EXYNOS3250_PROC_MODE_COMPR             (0x0 << 3)
+#define EXYNOS3250_SUBSAMPLING_MODE_MASK       (0x7 << 0)
+#define EXYNOS3250_SUBSAMPLING_MODE_444                (0x0 << 0)
+#define EXYNOS3250_SUBSAMPLING_MODE_422                (0x1 << 0)
+#define EXYNOS3250_SUBSAMPLING_MODE_420                (0x2 << 0)
+#define EXYNOS3250_SUBSAMPLING_MODE_411                (0x6 << 0)
+#define EXYNOS3250_SUBSAMPLING_MODE_GRAY       (0x3 << 0)
+
+/* JPEG operation status register */
+#define EXYNOS3250_JPGOPR                      0x04
+#define EXYNOS3250_JPGOPR_MASK                 0x01
+
+/* Quantization and Huffman tables register */
+#define EXYNOS3250_QHTBL                       0x08
+#define EXYNOS3250_QT_NUM_SHIFT(t)             ((((t) - 1) << 1) + 8)
+#define EXYNOS3250_QT_NUM_MASK(t)              (0x3 << EXYNOS3250_QT_NUM_SHIFT(t))
+
+/* Huffman tables */
+#define EXYNOS3250_HT_NUM_AC_SHIFT(t)          (((t) << 1) - 1)
+#define EXYNOS3250_HT_NUM_AC_MASK(t)           (0x1 << EXYNOS3250_HT_NUM_AC_SHIFT(t))
+
+#define EXYNOS3250_HT_NUM_DC_SHIFT(t)          (((t) - 1) << 1)
+#define EXYNOS3250_HT_NUM_DC_MASK(t)           (0x1 << EXYNOS3250_HT_NUM_DC_SHIFT(t))
+
+/* JPEG restart interval register */
+#define EXYNOS3250_JPGDRI                      0x0c
+#define EXYNOS3250_JPGDRI_MASK                 0xffff
+
+/* JPEG vertical resolution register */
+#define EXYNOS3250_JPGY                                0x10
+#define EXYNOS3250_JPGY_MASK                   0xffff
+
+/* JPEG horizontal resolution register */
+#define EXYNOS3250_JPGX                                0x14
+#define EXYNOS3250_JPGX_MASK                   0xffff
+
+/* JPEG byte count register */
+#define EXYNOS3250_JPGCNT                      0x18
+#define EXYNOS3250_JPGCNT_MASK                 0xffffff
+
+/* JPEG interrupt mask register */
+#define EXYNOS3250_JPGINTSE                    0x1c
+#define EXYNOS3250_JPEG_DONE_EN                        (1 << 11)
+#define EXYNOS3250_WDMA_DONE_EN                        (1 << 10)
+#define EXYNOS3250_RDMA_DONE_EN                        (1 << 9)
+#define EXYNOS3250_ENC_STREAM_INT_EN           (1 << 8)
+#define EXYNOS3250_CORE_DONE_EN                        (1 << 5)
+#define EXYNOS3250_ERR_INT_EN                  (1 << 4)
+#define EXYNOS3250_HEAD_INT_EN                 (1 << 3)
+
+/* JPEG interrupt status register */
+#define EXYNOS3250_JPGINTST                    0x20
+#define EXYNOS3250_JPEG_DONE                   (1 << 11)
+#define EXYNOS3250_WDMA_DONE                   (1 << 10)
+#define EXYNOS3250_RDMA_DONE                   (1 << 9)
+#define EXYNOS3250_ENC_STREAM_STAT             (1 << 8)
+#define EXYNOS3250_RESULT_STAT                 (1 << 5)
+#define EXYNOS3250_STREAM_STAT                 (1 << 4)
+#define EXYNOS3250_HEADER_STAT                 (1 << 3)
+
+/*
+ * Base address of the luma component DMA buffer
+ * of the raw input or output image.
+ */
+#define EXYNOS3250_LUMA_BASE                   0x100
+#define EXYNOS3250_SRC_TILE_EN_MASK            0x100
+
+/* Stride of source or destination luma raw image buffer */
+#define EXYNOS3250_LUMA_STRIDE                 0x104
+
+/* Horizontal/vertical offset of active region in luma raw image buffer */
+#define EXYNOS3250_LUMA_XY_OFFSET              0x108
+#define EXYNOS3250_LUMA_YY_OFFSET_SHIFT                18
+#define EXYNOS3250_LUMA_YY_OFFSET_MASK         (0x1fff << EXYNOS3250_LUMA_YY_OFFSET_SHIFT)
+#define EXYNOS3250_LUMA_YX_OFFSET_SHIFT                2
+#define EXYNOS3250_LUMA_YX_OFFSET_MASK         (0x1fff << EXYNOS3250_LUMA_YX_OFFSET_SHIFT)
+
+/*
+ * Base address of the chroma(Cb) component DMA buffer
+ * of the raw input or output image.
+ */
+#define EXYNOS3250_CHROMA_BASE                 0x10c
+
+/* Stride of source or destination chroma(Cb) raw image buffer */
+#define EXYNOS3250_CHROMA_STRIDE               0x110
+
+/* Horizontal/vertical offset of active region in chroma(Cb) raw image buffer */
+#define EXYNOS3250_CHROMA_XY_OFFSET            0x114
+#define EXYNOS3250_CHROMA_YY_OFFSET_SHIFT      18
+#define EXYNOS3250_CHROMA_YY_OFFSET_MASK       (0x1fff << EXYNOS3250_CHROMA_YY_OFFSET_SHIFT)
+#define EXYNOS3250_CHROMA_YX_OFFSET_SHIFT      2
+#define EXYNOS3250_CHROMA_YX_OFFSET_MASK       (0x1fff << EXYNOS3250_CHROMA_YX_OFFSET_SHIFT)
+
+/*
+ * Base address of the chroma(Cr) component DMA buffer
+ * of the raw input or output image.
+ */
+#define EXYNOS3250_CHROMA_CR_BASE              0x118
+
+/* Stride of source or destination chroma(Cr) raw image buffer */
+#define EXYNOS3250_CHROMA_CR_STRIDE            0x11c
+
+/* Horizontal/vertical offset of active region in chroma(Cb) raw image buffer */
+#define EXYNOS3250_CHROMA_CR_XY_OFFSET         0x120
+#define EXYNOS3250_CHROMA_CR_YY_OFFSET_SHIFT   18
+#define EXYNOS3250_CHROMA_CR_YY_OFFSET_MASK    (0x1fff << EXYNOS3250_CHROMA_CR_YY_OFFSET_SHIFT)
+#define EXYNOS3250_CHROMA_CR_YX_OFFSET_SHIFT   2
+#define EXYNOS3250_CHROMA_CR_YX_OFFSET_MASK    (0x1fff << EXYNOS3250_CHROMA_CR_YX_OFFSET_SHIFT)
+
+/* Raw image data r/w address register */
+#define EXYNOS3250_JPG_IMGADR                  0x50
+
+/* Source or destination JPEG file DMA buffer address */
+#define EXYNOS3250_JPG_JPGADR                  0x124
+
+/* Coefficients for RGB-to-YCbCr converter register */
+#define EXYNOS3250_JPG_COEF(n)                 (0x128 + (((n) - 1) << 2))
+#define EXYNOS3250_COEF_SHIFT(j)               ((3 - (j)) << 3)
+#define EXYNOS3250_COEF_MASK(j)                        (0xff << EXYNOS3250_COEF_SHIFT(j))
+
+/* Raw input format setting */
+#define EXYNOS3250_JPGCMOD                     0x134
+#define EXYNOS3250_SRC_TILE_EN                 (0x1 << 10)
+#define EXYNOS3250_SRC_NV_MASK                 (0x1 << 9)
+#define EXYNOS3250_SRC_NV12                    (0x0 << 9)
+#define EXYNOS3250_SRC_NV21                    (0x1 << 9)
+#define EXYNOS3250_SRC_BIG_ENDIAN_MASK         (0x1 << 8)
+#define EXYNOS3250_SRC_BIG_ENDIAN              (0x1 << 8)
+#define EXYNOS3250_MODE_SEL_MASK               (0x7 << 5)
+#define EXYNOS3250_MODE_SEL_420_2P             (0x0 << 5)
+#define EXYNOS3250_MODE_SEL_422_1P_LUM_CHR     (0x1 << 5)
+#define EXYNOS3250_MODE_SEL_RGB565             (0x2 << 5)
+#define EXYNOS3250_MODE_SEL_422_1P_CHR_LUM     (0x3 << 5)
+#define EXYNOS3250_MODE_SEL_ARGB8888           (0x4 << 5)
+#define EXYNOS3250_MODE_SEL_420_3P             (0x5 << 5)
+#define EXYNOS3250_SRC_SWAP_RGB                        (0x1 << 3)
+#define EXYNOS3250_SRC_SWAP_UV                 (0x1 << 2)
+#define EXYNOS3250_MODE_Y16_MASK               (0x1 << 1)
+#define EXYNOS3250_MODE_Y16                    (0x1 << 1)
+#define EXYNOS3250_HALF_EN_MASK                        (0x1 << 0)
+#define EXYNOS3250_HALF_EN                     (0x1 << 0)
+
+/* Power on/off and clock down control */
+#define EXYNOS3250_JPGCLKCON                   0x138
+#define EXYNOS3250_CLK_DOWN_READY              (0x1 << 1)
+#define EXYNOS3250_POWER_ON                    (0x1 << 0)
+
+/* Start compression or decompression */
+#define EXYNOS3250_JSTART                      0x13c
+
+/* Restart decompression after header analysis */
+#define EXYNOS3250_JRSTART                     0x140
+
+/* JPEG SW reset register */
+#define EXYNOS3250_SW_RESET                    0x144
+
+/* JPEG timer setting register */
+#define EXYNOS3250_TIMER_SE                    0x148
+#define EXYNOS3250_TIMER_INT_EN_SHIFT          31
+#define EXYNOS3250_TIMER_INT_EN                        (1UL << EXYNOS3250_TIMER_INT_EN_SHIFT)
+#define EXYNOS3250_TIMER_INIT_MASK             0x7fffffff
+
+/* JPEG timer status register */
+#define EXYNOS3250_TIMER_ST                    0x14c
+#define EXYNOS3250_TIMER_INT_STAT_SHIFT                31
+#define EXYNOS3250_TIMER_INT_STAT              (1UL << EXYNOS3250_TIMER_INT_STAT_SHIFT)
+#define EXYNOS3250_TIMER_CNT_SHIFT             0
+#define EXYNOS3250_TIMER_CNT_MASK              0x7fffffff
+
+/* Command status register */
+#define EXYNOS3250_COMSTAT                     0x150
+#define EXYNOS3250_CUR_PROC_MODE               (0x1 << 1)
+#define EXYNOS3250_CUR_COM_MODE                        (0x1 << 0)
+
+/* JPEG decompression output format register */
+#define EXYNOS3250_OUTFORM                     0x154
+#define EXYNOS3250_OUT_ALPHA_MASK              (0xff << 24)
+#define EXYNOS3250_OUT_TILE_EN                 (0x1 << 10)
+#define EXYNOS3250_OUT_NV_MASK                 (0x1 << 9)
+#define EXYNOS3250_OUT_NV12                    (0x0 << 9)
+#define EXYNOS3250_OUT_NV21                    (0x1 << 9)
+#define EXYNOS3250_OUT_BIG_ENDIAN_MASK         (0x1 << 8)
+#define EXYNOS3250_OUT_BIG_ENDIAN              (0x1 << 8)
+#define EXYNOS3250_OUT_SWAP_RGB                        (0x1 << 7)
+#define EXYNOS3250_OUT_SWAP_UV                 (0x1 << 6)
+#define EXYNOS3250_OUT_FMT_MASK                        (0x7 << 0)
+#define EXYNOS3250_OUT_FMT_420_2P              (0x0 << 0)
+#define EXYNOS3250_OUT_FMT_422_1P_LUM_CHR      (0x1 << 0)
+#define EXYNOS3250_OUT_FMT_422_1P_CHR_LUM      (0x3 << 0)
+#define EXYNOS3250_OUT_FMT_420_3P              (0x4 << 0)
+#define EXYNOS3250_OUT_FMT_RGB565              (0x5 << 0)
+#define EXYNOS3250_OUT_FMT_ARGB8888            (0x6 << 0)
+
+/* Input JPEG stream byte size for decompression */
+#define EXYNOS3250_DEC_STREAM_SIZE             0x158
+#define EXYNOS3250_DEC_STREAM_MASK             0x1fffffff
+
+/* The upper bound of the byte size of output compressed stream */
+#define EXYNOS3250_ENC_STREAM_BOUND            0x15c
+#define EXYNOS3250_ENC_STREAM_BOUND_MASK       0xffffc0
+
+/* Scale-down ratio when decoding */
+#define EXYNOS3250_DEC_SCALING_RATIO           0x160
+#define EXYNOS3250_DEC_SCALE_FACTOR_MASK       0x3
+#define EXYNOS3250_DEC_SCALE_FACTOR_8_8                0x0
+#define EXYNOS3250_DEC_SCALE_FACTOR_4_8                0x1
+#define EXYNOS3250_DEC_SCALE_FACTOR_2_8                0x2
+#define EXYNOS3250_DEC_SCALE_FACTOR_1_8                0x3
+
+/* Error check */
+#define EXYNOS3250_CRC_RESULT                  0x164
+
+/* RDMA and WDMA operation status register */
+#define EXYNOS3250_DMA_OPER_STATUS             0x168
+#define EXYNOS3250_WDMA_OPER_STATUS            (0x1 << 1)
+#define EXYNOS3250_RDMA_OPER_STATUS            (0x1 << 0)
+
+/* DMA issue gathering number and issue number settings */
+#define EXYNOS3250_DMA_ISSUE_NUM               0x16c
+#define EXYNOS3250_WDMA_ISSUE_NUM_SHIFT                16
+#define EXYNOS3250_WDMA_ISSUE_NUM_MASK         (0x7 << EXYNOS3250_WDMA_ISSUE_NUM_SHIFT)
+#define EXYNOS3250_RDMA_ISSUE_NUM_SHIFT                8
+#define EXYNOS3250_RDMA_ISSUE_NUM_MASK         (0x7 << EXYNOS3250_RDMA_ISSUE_NUM_SHIFT)
+#define EXYNOS3250_ISSUE_GATHER_NUM_SHIFT      0
+#define EXYNOS3250_ISSUE_GATHER_NUM_MASK       (0x7 << EXYNOS3250_ISSUE_GATHER_NUM_SHIFT)
+#define EXYNOS3250_DMA_MO_COUNT                        0x7
+
+/* Version register */
+#define EXYNOS3250_VERSION                     0x1fc
+
+/* RGB <-> YUV conversion coefficients */
+#define EXYNOS3250_JPEG_ENC_COEF1              0x01352e1e
+#define EXYNOS3250_JPEG_ENC_COEF2              0x00b0ae83
+#define EXYNOS3250_JPEG_ENC_COEF3              0x020cdc13
+
+#define EXYNOS3250_JPEG_DEC_COEF1              0x04a80199
+#define EXYNOS3250_JPEG_DEC_COEF2              0x04a9a064
+#define EXYNOS3250_JPEG_DEC_COEF3              0x04a80102
+
+#endif /* JPEG_REGS_H_ */
+