media: platform: rename s5p-mfc/ to samsung/s5p-mfc/
authorMauro Carvalho Chehab <mchehab@kernel.org>
Sun, 13 Mar 2022 10:18:18 +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-mfc/ to samsung/s5p-mfc/.

Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
69 files changed:
MAINTAINERS
drivers/media/platform/Kconfig
drivers/media/platform/Makefile
drivers/media/platform/s5p-mfc/Kconfig [deleted file]
drivers/media/platform/s5p-mfc/Makefile [deleted file]
drivers/media/platform/s5p-mfc/regs-mfc-v10.h [deleted file]
drivers/media/platform/s5p-mfc/regs-mfc-v6.h [deleted file]
drivers/media/platform/s5p-mfc/regs-mfc-v7.h [deleted file]
drivers/media/platform/s5p-mfc/regs-mfc-v8.h [deleted file]
drivers/media/platform/s5p-mfc/regs-mfc.h [deleted file]
drivers/media/platform/s5p-mfc/s5p_mfc.c [deleted file]
drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c [deleted file]
drivers/media/platform/s5p-mfc/s5p_mfc_cmd.h [deleted file]
drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c [deleted file]
drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.h [deleted file]
drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c [deleted file]
drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.h [deleted file]
drivers/media/platform/s5p-mfc/s5p_mfc_common.h [deleted file]
drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c [deleted file]
drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h [deleted file]
drivers/media/platform/s5p-mfc/s5p_mfc_debug.h [deleted file]
drivers/media/platform/s5p-mfc/s5p_mfc_dec.c [deleted file]
drivers/media/platform/s5p-mfc/s5p_mfc_dec.h [deleted file]
drivers/media/platform/s5p-mfc/s5p_mfc_enc.c [deleted file]
drivers/media/platform/s5p-mfc/s5p_mfc_enc.h [deleted file]
drivers/media/platform/s5p-mfc/s5p_mfc_intr.c [deleted file]
drivers/media/platform/s5p-mfc/s5p_mfc_intr.h [deleted file]
drivers/media/platform/s5p-mfc/s5p_mfc_iommu.h [deleted file]
drivers/media/platform/s5p-mfc/s5p_mfc_opr.c [deleted file]
drivers/media/platform/s5p-mfc/s5p_mfc_opr.h [deleted file]
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c [deleted file]
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.h [deleted file]
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c [deleted file]
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h [deleted file]
drivers/media/platform/s5p-mfc/s5p_mfc_pm.c [deleted file]
drivers/media/platform/s5p-mfc/s5p_mfc_pm.h [deleted file]
drivers/media/platform/samsung/s5p-mfc/Kconfig [new file with mode: 0644]
drivers/media/platform/samsung/s5p-mfc/Makefile [new file with mode: 0644]
drivers/media/platform/samsung/s5p-mfc/regs-mfc-v10.h [new file with mode: 0644]
drivers/media/platform/samsung/s5p-mfc/regs-mfc-v6.h [new file with mode: 0644]
drivers/media/platform/samsung/s5p-mfc/regs-mfc-v7.h [new file with mode: 0644]
drivers/media/platform/samsung/s5p-mfc/regs-mfc-v8.h [new file with mode: 0644]
drivers/media/platform/samsung/s5p-mfc/regs-mfc.h [new file with mode: 0644]
drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c [new file with mode: 0644]
drivers/media/platform/samsung/s5p-mfc/s5p_mfc_cmd.c [new file with mode: 0644]
drivers/media/platform/samsung/s5p-mfc/s5p_mfc_cmd.h [new file with mode: 0644]
drivers/media/platform/samsung/s5p-mfc/s5p_mfc_cmd_v5.c [new file with mode: 0644]
drivers/media/platform/samsung/s5p-mfc/s5p_mfc_cmd_v5.h [new file with mode: 0644]
drivers/media/platform/samsung/s5p-mfc/s5p_mfc_cmd_v6.c [new file with mode: 0644]
drivers/media/platform/samsung/s5p-mfc/s5p_mfc_cmd_v6.h [new file with mode: 0644]
drivers/media/platform/samsung/s5p-mfc/s5p_mfc_common.h [new file with mode: 0644]
drivers/media/platform/samsung/s5p-mfc/s5p_mfc_ctrl.c [new file with mode: 0644]
drivers/media/platform/samsung/s5p-mfc/s5p_mfc_ctrl.h [new file with mode: 0644]
drivers/media/platform/samsung/s5p-mfc/s5p_mfc_debug.h [new file with mode: 0644]
drivers/media/platform/samsung/s5p-mfc/s5p_mfc_dec.c [new file with mode: 0644]
drivers/media/platform/samsung/s5p-mfc/s5p_mfc_dec.h [new file with mode: 0644]
drivers/media/platform/samsung/s5p-mfc/s5p_mfc_enc.c [new file with mode: 0644]
drivers/media/platform/samsung/s5p-mfc/s5p_mfc_enc.h [new file with mode: 0644]
drivers/media/platform/samsung/s5p-mfc/s5p_mfc_intr.c [new file with mode: 0644]
drivers/media/platform/samsung/s5p-mfc/s5p_mfc_intr.h [new file with mode: 0644]
drivers/media/platform/samsung/s5p-mfc/s5p_mfc_iommu.h [new file with mode: 0644]
drivers/media/platform/samsung/s5p-mfc/s5p_mfc_opr.c [new file with mode: 0644]
drivers/media/platform/samsung/s5p-mfc/s5p_mfc_opr.h [new file with mode: 0644]
drivers/media/platform/samsung/s5p-mfc/s5p_mfc_opr_v5.c [new file with mode: 0644]
drivers/media/platform/samsung/s5p-mfc/s5p_mfc_opr_v5.h [new file with mode: 0644]
drivers/media/platform/samsung/s5p-mfc/s5p_mfc_opr_v6.c [new file with mode: 0644]
drivers/media/platform/samsung/s5p-mfc/s5p_mfc_opr_v6.h [new file with mode: 0644]
drivers/media/platform/samsung/s5p-mfc/s5p_mfc_pm.c [new file with mode: 0644]
drivers/media/platform/samsung/s5p-mfc/s5p_mfc_pm.h [new file with mode: 0644]

index a19041a4b8fa492ae2fd0fc624383e20e5c96fee..84c2fd43608bd3717eb00b795dadf0624c3dfe2d 100644 (file)
@@ -2641,7 +2641,7 @@ M:        Andrzej Hajda <andrzej.hajda@intel.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-mfc/
+F:     drivers/media/platform/samsung/s5p-mfc/
 
 ARM/SHMOBILE ARM ARCHITECTURE
 M:     Geert Uytterhoeven <geert+renesas@glider.be>
index 5f7a89e2af806aa0e0a4ef75a2dd8b9f717437cb..c95a8b283d2aac6c14838da360e47b8f107aaff6 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-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/samsung/s5p-mfc/Kconfig"
 source "drivers/media/platform/sti/Kconfig"
 source "drivers/media/platform/stm32/Kconfig"
 source "drivers/media/platform/sunxi/Kconfig"
index 86f81e81dadc0caa8f7ebbaa7745ba043b2cd774..65bc673587b12c4e3282f046de9cab3d698bc8f8 100644 (file)
@@ -29,12 +29,12 @@ obj-y += qcom/venus/
 obj-y += renesas/
 obj-y += rockchip/rga/
 obj-y += rockchip/rkisp1/
-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 += samsung/s5p-mfc/
 obj-y += sti/bdisp/
 obj-y += sti/c8sectpfe/
 obj-y += sti/delta/
diff --git a/drivers/media/platform/s5p-mfc/Kconfig b/drivers/media/platform/s5p-mfc/Kconfig
deleted file mode 100644 (file)
index 34b52b0..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-config VIDEO_SAMSUNG_S5P_MFC
-       tristate "Samsung S5P MFC Video Codec"
-       depends on V4L_MEM2MEM_DRIVERS
-       depends on VIDEO_DEV && VIDEO_V4L2
-       depends on ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST
-       select VIDEOBUF2_DMA_CONTIG
-       help
-           MFC 5.1 and 6.x driver for V4L2
diff --git a/drivers/media/platform/s5p-mfc/Makefile b/drivers/media/platform/s5p-mfc/Makefile
deleted file mode 100644 (file)
index 0b324af..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC) += s5p-mfc.o
-s5p-mfc-y += s5p_mfc.o s5p_mfc_intr.o
-s5p-mfc-y += s5p_mfc_dec.o s5p_mfc_enc.o
-s5p-mfc-y += s5p_mfc_ctrl.o s5p_mfc_pm.o
-s5p-mfc-y += s5p_mfc_opr.o s5p_mfc_opr_v5.o s5p_mfc_opr_v6.o
-s5p-mfc-y += s5p_mfc_cmd.o s5p_mfc_cmd_v5.o s5p_mfc_cmd_v6.o
diff --git a/drivers/media/platform/s5p-mfc/regs-mfc-v10.h b/drivers/media/platform/s5p-mfc/regs-mfc-v10.h
deleted file mode 100644 (file)
index fadd913..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- *
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
- *     http://www.samsung.com/
- *
- * Register definition file for Samsung MFC V10.x Interface (FIMV) driver
- *
- */
-
-#ifndef _REGS_MFC_V10_H
-#define _REGS_MFC_V10_H
-
-#include <linux/sizes.h>
-#include "regs-mfc-v8.h"
-
-/* MFCv10 register definitions*/
-#define S5P_FIMV_MFC_CLOCK_OFF_V10                     0x7120
-#define S5P_FIMV_MFC_STATE_V10                         0x7124
-#define S5P_FIMV_D_STATIC_BUFFER_ADDR_V10              0xF570
-#define S5P_FIMV_D_STATIC_BUFFER_SIZE_V10              0xF574
-#define S5P_FIMV_E_NUM_T_LAYER_V10                     0xFBAC
-#define S5P_FIMV_E_HIERARCHICAL_QP_LAYER0_V10          0xFBB0
-#define S5P_FIMV_E_HIERARCHICAL_QP_LAYER1_V10          0xFBB4
-#define S5P_FIMV_E_HIERARCHICAL_QP_LAYER2_V10          0xFBB8
-#define S5P_FIMV_E_HIERARCHICAL_QP_LAYER3_V10          0xFBBC
-#define S5P_FIMV_E_HIERARCHICAL_QP_LAYER4_V10          0xFBC0
-#define S5P_FIMV_E_HIERARCHICAL_QP_LAYER5_V10          0xFBC4
-#define S5P_FIMV_E_HIERARCHICAL_QP_LAYER6_V10          0xFBC8
-#define S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER0_V10    0xFD18
-#define S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER1_V10    0xFD1C
-#define S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER2_V10    0xFD20
-#define S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER3_V10    0xFD24
-#define S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER4_V10    0xFD28
-#define S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER5_V10    0xFD2C
-#define S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER6_V10    0xFD30
-#define S5P_FIMV_E_HEVC_OPTIONS_V10                    0xFDD4
-#define S5P_FIMV_E_HEVC_REFRESH_PERIOD_V10             0xFDD8
-#define S5P_FIMV_E_HEVC_CHROMA_QP_OFFSET_V10           0xFDDC
-#define S5P_FIMV_E_HEVC_LF_BETA_OFFSET_DIV2_V10                0xFDE0
-#define S5P_FIMV_E_HEVC_LF_TC_OFFSET_DIV2_V10          0xFDE4
-#define S5P_FIMV_E_HEVC_NAL_CONTROL_V10                        0xFDE8
-
-/* MFCv10 Context buffer sizes */
-#define MFC_CTX_BUF_SIZE_V10           (30 * SZ_1K)
-#define MFC_H264_DEC_CTX_BUF_SIZE_V10  (2 * SZ_1M)
-#define MFC_OTHER_DEC_CTX_BUF_SIZE_V10 (20 * SZ_1K)
-#define MFC_H264_ENC_CTX_BUF_SIZE_V10  (100 * SZ_1K)
-#define MFC_HEVC_ENC_CTX_BUF_SIZE_V10  (30 * SZ_1K)
-#define MFC_OTHER_ENC_CTX_BUF_SIZE_V10  (15 * SZ_1K)
-
-/* MFCv10 variant defines */
-#define MAX_FW_SIZE_V10                (SZ_1M)
-#define MAX_CPB_SIZE_V10       (3 * SZ_1M)
-#define MFC_VERSION_V10                0xA0
-#define MFC_NUM_PORTS_V10      1
-
-/* MFCv10 codec defines*/
-#define S5P_FIMV_CODEC_HEVC_DEC                17
-#define S5P_FIMV_CODEC_VP9_DEC         18
-#define S5P_FIMV_CODEC_HEVC_ENC         26
-
-/* Decoder buffer size for MFC v10 */
-#define DEC_VP9_STATIC_BUFFER_SIZE     20480
-
-/* Encoder buffer size for MFC v10.0 */
-#define ENC_V100_BASE_SIZE(x, y) \
-       (((x + 3) * (y + 3) * 8) \
-       +  ((y * 64) + 1280) * DIV_ROUND_UP(x, 8))
-
-#define ENC_V100_H264_ME_SIZE(x, y) \
-       (ENC_V100_BASE_SIZE(x, y) \
-       + (DIV_ROUND_UP(x * y, 64) * 32))
-
-#define ENC_V100_MPEG4_ME_SIZE(x, y) \
-       (ENC_V100_BASE_SIZE(x, y) \
-       + (DIV_ROUND_UP(x * y, 128) * 16))
-
-#define ENC_V100_VP8_ME_SIZE(x, y) \
-       ENC_V100_BASE_SIZE(x, y)
-
-#define ENC_V100_HEVC_ME_SIZE(x, y)    \
-       (((x + 3) * (y + 3) * 32)       \
-        + ((y * 128) + 1280) * DIV_ROUND_UP(x, 4))
-
-#endif /*_REGS_MFC_V10_H*/
-
diff --git a/drivers/media/platform/s5p-mfc/regs-mfc-v6.h b/drivers/media/platform/s5p-mfc/regs-mfc-v6.h
deleted file mode 100644 (file)
index fa49fe5..0000000
+++ /dev/null
@@ -1,408 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Register definition file for Samsung MFC V6.x Interface (FIMV) driver
- *
- * Copyright (c) 2012 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- */
-
-#ifndef _REGS_FIMV_V6_H
-#define _REGS_FIMV_V6_H
-
-#include <linux/kernel.h>
-#include <linux/sizes.h>
-
-#define S5P_FIMV_REG_SIZE_V6   (S5P_FIMV_END_ADDR - S5P_FIMV_START_ADDR)
-#define S5P_FIMV_REG_COUNT_V6  ((S5P_FIMV_END_ADDR - S5P_FIMV_START_ADDR) / 4)
-
-/* Number of bits that the buffer address should be shifted for particular
- * MFC buffers.  */
-#define S5P_FIMV_MEM_OFFSET_V6         0
-
-#define S5P_FIMV_START_ADDR_V6         0x0000
-#define S5P_FIMV_END_ADDR_V6           0xfd80
-
-#define S5P_FIMV_REG_CLEAR_BEGIN_V6    0xf000
-#define S5P_FIMV_REG_CLEAR_COUNT_V6    1024
-
-/* Codec Common Registers */
-#define S5P_FIMV_RISC_ON_V6                    0x0000
-#define S5P_FIMV_RISC2HOST_INT_V6              0x003C
-#define S5P_FIMV_HOST2RISC_INT_V6              0x0044
-#define S5P_FIMV_RISC_BASE_ADDRESS_V6          0x0054
-
-#define S5P_FIMV_MFC_RESET_V6                  0x1070
-
-#define S5P_FIMV_HOST2RISC_CMD_V6              0x1100
-#define S5P_FIMV_H2R_CMD_EMPTY_V6              0
-#define S5P_FIMV_H2R_CMD_SYS_INIT_V6           1
-#define S5P_FIMV_H2R_CMD_OPEN_INSTANCE_V6      2
-#define S5P_FIMV_CH_SEQ_HEADER_V6              3
-#define S5P_FIMV_CH_INIT_BUFS_V6               4
-#define S5P_FIMV_CH_FRAME_START_V6             5
-#define S5P_FIMV_H2R_CMD_CLOSE_INSTANCE_V6     6
-#define S5P_FIMV_H2R_CMD_SLEEP_V6              7
-#define S5P_FIMV_H2R_CMD_WAKEUP_V6             8
-#define S5P_FIMV_CH_LAST_FRAME_V6              9
-#define S5P_FIMV_H2R_CMD_FLUSH_V6              10
-/* RMVME: REALLOC used? */
-#define S5P_FIMV_CH_FRAME_START_REALLOC_V6     5
-
-#define S5P_FIMV_RISC2HOST_CMD_V6              0x1104
-#define S5P_FIMV_R2H_CMD_EMPTY_V6              0
-#define S5P_FIMV_R2H_CMD_SYS_INIT_RET_V6       1
-#define S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET_V6  2
-#define S5P_FIMV_R2H_CMD_SEQ_DONE_RET_V6       3
-#define S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET_V6   4
-
-#define S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET_V6 6
-#define S5P_FIMV_R2H_CMD_SLEEP_RET_V6          7
-#define S5P_FIMV_R2H_CMD_WAKEUP_RET_V6         8
-#define S5P_FIMV_R2H_CMD_COMPLETE_SEQ_RET_V6   9
-#define S5P_FIMV_R2H_CMD_DPB_FLUSH_RET_V6      10
-#define S5P_FIMV_R2H_CMD_NAL_ABORT_RET_V6      11
-#define S5P_FIMV_R2H_CMD_FW_STATUS_RET_V6      12
-#define S5P_FIMV_R2H_CMD_FRAME_DONE_RET_V6     13
-#define S5P_FIMV_R2H_CMD_FIELD_DONE_RET_V6     14
-#define S5P_FIMV_R2H_CMD_SLICE_DONE_RET_V6     15
-#define S5P_FIMV_R2H_CMD_ENC_BUFFER_FUL_RET_V6 16
-#define S5P_FIMV_R2H_CMD_ERR_RET_V6            32
-
-#define S5P_FIMV_MFC_BUS_RESET_CTRL            0x7110
-#define S5P_FIMV_FW_VERSION_V6                 0xf000
-
-#define S5P_FIMV_INSTANCE_ID_V6                        0xf008
-#define S5P_FIMV_CODEC_TYPE_V6                 0xf00c
-#define S5P_FIMV_CONTEXT_MEM_ADDR_V6           0xf014
-#define S5P_FIMV_CONTEXT_MEM_SIZE_V6           0xf018
-#define S5P_FIMV_PIXEL_FORMAT_V6               0xf020
-
-#define S5P_FIMV_METADATA_ENABLE_V6            0xf024
-#define S5P_FIMV_DBG_BUFFER_ADDR_V6            0xf030
-#define S5P_FIMV_DBG_BUFFER_SIZE_V6            0xf034
-#define S5P_FIMV_RET_INSTANCE_ID_V6            0xf070
-
-#define S5P_FIMV_ERROR_CODE_V6                 0xf074
-#define S5P_FIMV_ERR_WARNINGS_START_V6         160
-#define S5P_FIMV_ERR_DEC_MASK_V6               0xffff
-#define S5P_FIMV_ERR_DEC_SHIFT_V6              0
-#define S5P_FIMV_ERR_DSPL_MASK_V6              0xffff0000
-#define S5P_FIMV_ERR_DSPL_SHIFT_V6             16
-
-#define S5P_FIMV_DBG_BUFFER_OUTPUT_SIZE_V6     0xf078
-#define S5P_FIMV_METADATA_STATUS_V6            0xf07C
-#define S5P_FIMV_METADATA_ADDR_MB_INFO_V6      0xf080
-#define S5P_FIMV_METADATA_SIZE_MB_INFO_V6      0xf084
-
-/* Decoder Registers */
-#define S5P_FIMV_D_CRC_CTRL_V6                 0xf0b0
-#define S5P_FIMV_D_DEC_OPTIONS_V6              0xf0b4
-#define S5P_FIMV_D_OPT_FMO_ASO_CTRL_MASK_V6    4
-#define S5P_FIMV_D_OPT_DDELAY_EN_SHIFT_V6      3
-#define S5P_FIMV_D_OPT_LF_CTRL_SHIFT_V6                1
-#define S5P_FIMV_D_OPT_LF_CTRL_MASK_V6         0x3
-#define S5P_FIMV_D_OPT_TILE_MODE_SHIFT_V6      0
-
-#define S5P_FIMV_D_DISPLAY_DELAY_V6            0xf0b8
-
-#define S5P_FIMV_D_SET_FRAME_WIDTH_V6          0xf0bc
-#define S5P_FIMV_D_SET_FRAME_HEIGHT_V6         0xf0c0
-
-#define S5P_FIMV_D_SEI_ENABLE_V6               0xf0c4
-
-/* Buffer setting registers */
-#define S5P_FIMV_D_MIN_NUM_DPB_V6              0xf0f0
-#define S5P_FIMV_D_MIN_LUMA_DPB_SIZE_V6                0xf0f4
-#define S5P_FIMV_D_MIN_CHROMA_DPB_SIZE_V6      0xf0f8
-#define S5P_FIMV_D_MVC_NUM_VIEWS_V6            0xf0fc
-#define S5P_FIMV_D_MIN_NUM_MV_V6               0xf100
-#define S5P_FIMV_D_NUM_DPB_V6                  0xf130
-#define S5P_FIMV_D_LUMA_DPB_SIZE_V6            0xf134
-#define S5P_FIMV_D_CHROMA_DPB_SIZE_V6          0xf138
-#define S5P_FIMV_D_MV_BUFFER_SIZE_V6           0xf13c
-
-#define S5P_FIMV_D_LUMA_DPB_V6                 0xf140
-#define S5P_FIMV_D_CHROMA_DPB_V6               0xf240
-#define S5P_FIMV_D_MV_BUFFER_V6                        0xf340
-
-#define S5P_FIMV_D_SCRATCH_BUFFER_ADDR_V6      0xf440
-#define S5P_FIMV_D_SCRATCH_BUFFER_SIZE_V6      0xf444
-#define S5P_FIMV_D_METADATA_BUFFER_ADDR_V6     0xf448
-#define S5P_FIMV_D_METADATA_BUFFER_SIZE_V6     0xf44c
-#define S5P_FIMV_D_NUM_MV_V6                   0xf478
-#define S5P_FIMV_D_CPB_BUFFER_ADDR_V6          0xf4b0
-#define S5P_FIMV_D_CPB_BUFFER_SIZE_V6          0xf4b4
-
-#define S5P_FIMV_D_AVAILABLE_DPB_FLAG_UPPER_V6 0xf4b8
-#define S5P_FIMV_D_AVAILABLE_DPB_FLAG_LOWER_V6 0xf4bc
-#define S5P_FIMV_D_CPB_BUFFER_OFFSET_V6                0xf4c0
-#define S5P_FIMV_D_SLICE_IF_ENABLE_V6          0xf4c4
-#define S5P_FIMV_D_PICTURE_TAG_V6              0xf4c8
-#define S5P_FIMV_D_STREAM_DATA_SIZE_V6         0xf4d0
-#define S5P_FIMV_D_INIT_BUFFER_OPTIONS_V6      0xf47c
-
-/* Display information register */
-#define S5P_FIMV_D_DISPLAY_FRAME_WIDTH_V6      0xf500
-#define S5P_FIMV_D_DISPLAY_FRAME_HEIGHT_V6     0xf504
-
-/* Display status */
-#define S5P_FIMV_D_DISPLAY_STATUS_V6           0xf508
-
-#define S5P_FIMV_D_DISPLAY_LUMA_ADDR_V6                0xf50c
-#define S5P_FIMV_D_DISPLAY_CHROMA_ADDR_V6      0xf510
-
-#define S5P_FIMV_D_DISPLAY_FRAME_TYPE_V6       0xf514
-
-#define S5P_FIMV_D_DISPLAY_CROP_INFO1_V6       0xf518
-#define S5P_FIMV_D_DISPLAY_CROP_INFO2_V6       0xf51c
-#define S5P_FIMV_D_DISPLAY_PICTURE_PROFILE_V6  0xf520
-#define S5P_FIMV_D_DISPLAY_LUMA_CRC_TOP_V6     0xf524
-#define S5P_FIMV_D_DISPLAY_CHROMA_CRC_TOP_V6   0xf528
-#define S5P_FIMV_D_DISPLAY_LUMA_CRC_BOT_V6     0xf52c
-#define S5P_FIMV_D_DISPLAY_CHROMA_CRC_BOT_V6   0xf530
-#define S5P_FIMV_D_DISPLAY_ASPECT_RATIO_V6     0xf534
-#define S5P_FIMV_D_DISPLAY_EXTENDED_AR_V6      0xf538
-
-/* Decoded picture information register */
-#define S5P_FIMV_D_DECODED_FRAME_WIDTH_V6      0xf53c
-#define S5P_FIMV_D_DECODED_FRAME_HEIGHT_V6     0xf540
-#define S5P_FIMV_D_DECODED_STATUS_V6           0xf544
-#define S5P_FIMV_DEC_CRC_GEN_MASK_V6           0x1
-#define S5P_FIMV_DEC_CRC_GEN_SHIFT_V6          6
-
-#define S5P_FIMV_D_DECODED_LUMA_ADDR_V6                0xf548
-#define S5P_FIMV_D_DECODED_CHROMA_ADDR_V6      0xf54c
-
-#define S5P_FIMV_D_DECODED_FRAME_TYPE_V6       0xf550
-#define S5P_FIMV_DECODE_FRAME_MASK_V6          7
-
-#define S5P_FIMV_D_DECODED_CROP_INFO1_V6       0xf554
-#define S5P_FIMV_D_DECODED_CROP_INFO2_V6       0xf558
-#define S5P_FIMV_D_DECODED_PICTURE_PROFILE_V6  0xf55c
-#define S5P_FIMV_D_DECODED_NAL_SIZE_V6         0xf560
-#define S5P_FIMV_D_DECODED_LUMA_CRC_TOP_V6     0xf564
-#define S5P_FIMV_D_DECODED_CHROMA_CRC_TOP_V6   0xf568
-#define S5P_FIMV_D_DECODED_LUMA_CRC_BOT_V6     0xf56c
-#define S5P_FIMV_D_DECODED_CHROMA_CRC_BOT_V6   0xf570
-
-/* Returned value register for specific setting */
-#define S5P_FIMV_D_RET_PICTURE_TAG_TOP_V6              0xf574
-#define S5P_FIMV_D_RET_PICTURE_TAG_BOT_V6              0xf578
-#define S5P_FIMV_D_RET_PICTURE_TIME_TOP_V6             0xf57c
-#define S5P_FIMV_D_RET_PICTURE_TIME_BOT_V6             0xf580
-#define S5P_FIMV_D_CHROMA_FORMAT_V6                    0xf588
-#define S5P_FIMV_D_MPEG4_INFO_V6                       0xf58c
-#define S5P_FIMV_D_H264_INFO_V6                                0xf590
-
-#define S5P_FIMV_D_METADATA_ADDR_CONCEALED_MB_V6       0xf594
-#define S5P_FIMV_D_METADATA_SIZE_CONCEALED_MB_V6       0xf598
-#define S5P_FIMV_D_METADATA_ADDR_VC1_PARAM_V6          0xf59c
-#define S5P_FIMV_D_METADATA_SIZE_VC1_PARAM_V6          0xf5a0
-#define S5P_FIMV_D_METADATA_ADDR_SEI_NAL_V6            0xf5a4
-#define S5P_FIMV_D_METADATA_SIZE_SEI_NAL_V6            0xf5a8
-#define S5P_FIMV_D_METADATA_ADDR_VUI_V6                        0xf5ac
-#define S5P_FIMV_D_METADATA_SIZE_VUI_V6                        0xf5b0
-
-#define S5P_FIMV_D_MVC_VIEW_ID_V6              0xf5b4
-
-/* SEI related information */
-#define S5P_FIMV_D_FRAME_PACK_SEI_AVAIL_V6     0xf5f0
-#define S5P_FIMV_D_FRAME_PACK_ARRGMENT_ID_V6   0xf5f4
-#define S5P_FIMV_D_FRAME_PACK_SEI_INFO_V6      0xf5f8
-#define S5P_FIMV_D_FRAME_PACK_GRID_POS_V6      0xf5fc
-
-/* Encoder Registers */
-#define S5P_FIMV_E_FRAME_WIDTH_V6              0xf770
-#define S5P_FIMV_E_FRAME_HEIGHT_V6             0xf774
-#define S5P_FIMV_E_CROPPED_FRAME_WIDTH_V6      0xf778
-#define S5P_FIMV_E_CROPPED_FRAME_HEIGHT_V6     0xf77c
-#define S5P_FIMV_E_FRAME_CROP_OFFSET_V6                0xf780
-#define S5P_FIMV_E_ENC_OPTIONS_V6              0xf784
-#define S5P_FIMV_E_PICTURE_PROFILE_V6          0xf788
-#define S5P_FIMV_E_FIXED_PICTURE_QP_V6         0xf790
-
-#define S5P_FIMV_E_RC_CONFIG_V6                        0xf794
-#define S5P_FIMV_E_RC_QP_BOUND_V6              0xf798
-#define S5P_FIMV_E_RC_RPARAM_V6                        0xf79c
-#define S5P_FIMV_E_MB_RC_CONFIG_V6             0xf7a0
-#define S5P_FIMV_E_PADDING_CTRL_V6             0xf7a4
-#define S5P_FIMV_E_MV_HOR_RANGE_V6             0xf7ac
-#define S5P_FIMV_E_MV_VER_RANGE_V6             0xf7b0
-#define S5P_FIMV_E_MV_RANGE_V6_MASK            0x3fff
-
-#define S5P_FIMV_E_VBV_BUFFER_SIZE_V6          0xf84c
-#define S5P_FIMV_E_VBV_INIT_DELAY_V6           0xf850
-#define S5P_FIMV_E_NUM_DPB_V6                  0xf890
-#define S5P_FIMV_E_LUMA_DPB_V6                 0xf8c0
-#define S5P_FIMV_E_CHROMA_DPB_V6               0xf904
-#define S5P_FIMV_E_ME_BUFFER_V6                        0xf948
-
-#define S5P_FIMV_E_SCRATCH_BUFFER_ADDR_V6      0xf98c
-#define S5P_FIMV_E_SCRATCH_BUFFER_SIZE_V6      0xf990
-#define S5P_FIMV_E_TMV_BUFFER0_V6              0xf994
-#define S5P_FIMV_E_TMV_BUFFER1_V6              0xf998
-#define S5P_FIMV_E_SOURCE_LUMA_ADDR_V6         0xf9f0
-#define S5P_FIMV_E_SOURCE_CHROMA_ADDR_V6       0xf9f4
-#define S5P_FIMV_E_STREAM_BUFFER_ADDR_V6       0xf9f8
-#define S5P_FIMV_E_STREAM_BUFFER_SIZE_V6       0xf9fc
-#define S5P_FIMV_E_ROI_BUFFER_ADDR_V6          0xfA00
-
-#define S5P_FIMV_E_PARAM_CHANGE_V6             0xfa04
-#define S5P_FIMV_E_IR_SIZE_V6                  0xfa08
-#define S5P_FIMV_E_GOP_CONFIG_V6               0xfa0c
-#define S5P_FIMV_E_MSLICE_MODE_V6              0xfa10
-#define S5P_FIMV_E_MSLICE_SIZE_MB_V6           0xfa14
-#define S5P_FIMV_E_MSLICE_SIZE_BITS_V6         0xfa18
-#define S5P_FIMV_E_FRAME_INSERTION_V6          0xfa1c
-
-#define S5P_FIMV_E_RC_FRAME_RATE_V6            0xfa20
-#define S5P_FIMV_E_RC_BIT_RATE_V6              0xfa24
-#define S5P_FIMV_E_RC_QP_OFFSET_V6             0xfa28
-#define S5P_FIMV_E_RC_ROI_CTRL_V6              0xfa2c
-#define S5P_FIMV_E_PICTURE_TAG_V6              0xfa30
-#define S5P_FIMV_E_BIT_COUNT_ENABLE_V6         0xfa34
-#define S5P_FIMV_E_MAX_BIT_COUNT_V6            0xfa38
-#define S5P_FIMV_E_MIN_BIT_COUNT_V6            0xfa3c
-
-#define S5P_FIMV_E_METADATA_BUFFER_ADDR_V6             0xfa40
-#define S5P_FIMV_E_METADATA_BUFFER_SIZE_V6             0xfa44
-#define S5P_FIMV_E_STREAM_SIZE_V6                      0xfa80
-#define S5P_FIMV_E_SLICE_TYPE_V6                       0xfa84
-#define S5P_FIMV_E_PICTURE_COUNT_V6                    0xfa88
-#define S5P_FIMV_E_RET_PICTURE_TAG_V6                  0xfa8c
-#define S5P_FIMV_E_STREAM_BUFFER_WRITE_POINTER_V6      0xfa90
-
-#define S5P_FIMV_E_ENCODED_SOURCE_LUMA_ADDR_V6         0xfa94
-#define S5P_FIMV_E_ENCODED_SOURCE_CHROMA_ADDR_V6       0xfa98
-#define S5P_FIMV_E_RECON_LUMA_DPB_ADDR_V6              0xfa9c
-#define S5P_FIMV_E_RECON_CHROMA_DPB_ADDR_V6            0xfaa0
-#define S5P_FIMV_E_METADATA_ADDR_ENC_SLICE_V6          0xfaa4
-#define S5P_FIMV_E_METADATA_SIZE_ENC_SLICE_V6          0xfaa8
-
-#define S5P_FIMV_E_MPEG4_OPTIONS_V6            0xfb10
-#define S5P_FIMV_E_MPEG4_HEC_PERIOD_V6         0xfb14
-#define S5P_FIMV_E_ASPECT_RATIO_V6             0xfb50
-#define S5P_FIMV_E_EXTENDED_SAR_V6             0xfb54
-
-#define S5P_FIMV_E_H264_OPTIONS_V6             0xfb58
-#define S5P_FIMV_E_H264_LF_ALPHA_OFFSET_V6     0xfb5c
-#define S5P_FIMV_E_H264_LF_BETA_OFFSET_V6      0xfb60
-#define S5P_FIMV_E_H264_I_PERIOD_V6            0xfb64
-
-#define S5P_FIMV_E_H264_FMO_SLICE_GRP_MAP_TYPE_V6              0xfb68
-#define S5P_FIMV_E_H264_FMO_NUM_SLICE_GRP_MINUS1_V6            0xfb6c
-#define S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_DIR_V6            0xfb70
-#define S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_RATE_MINUS1_V6    0xfb74
-#define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_0_V6             0xfb78
-#define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_1_V6             0xfb7c
-#define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_2_V6             0xfb80
-#define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_3_V6             0xfb84
-
-#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_0_V6   0xfb88
-#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_1_V6   0xfb8c
-#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_2_V6   0xfb90
-#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_3_V6   0xfb94
-#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_4_V6   0xfb98
-#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_5_V6   0xfb9c
-#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_6_V6   0xfba0
-#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_7_V6   0xfba4
-
-#define S5P_FIMV_E_H264_CHROMA_QP_OFFSET_V6    0xfba8
-#define S5P_FIMV_E_H264_NUM_T_LAYER_V6         0xfbac
-
-#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER0_V6      0xfbb0
-#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER1_V6      0xfbb4
-#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER2_V6      0xfbb8
-#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER3_V6      0xfbbc
-#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER4_V6      0xfbc0
-#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER5_V6      0xfbc4
-#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER6_V6      0xfbc8
-
-#define S5P_FIMV_E_H264_FRAME_PACKING_SEI_INFO_V6              0xfc4c
-#define S5P_FIMV_ENC_FP_ARRANGEMENT_TYPE_SIDE_BY_SIDE_V6       0
-#define S5P_FIMV_ENC_FP_ARRANGEMENT_TYPE_TOP_BOTTOM_V6         1
-#define S5P_FIMV_ENC_FP_ARRANGEMENT_TYPE_TEMPORAL_V6           2
-
-#define S5P_FIMV_E_MVC_FRAME_QP_VIEW1_V6               0xfd40
-#define S5P_FIMV_E_MVC_RC_FRAME_RATE_VIEW1_V6          0xfd44
-#define S5P_FIMV_E_MVC_RC_BIT_RATE_VIEW1_V6            0xfd48
-#define S5P_FIMV_E_MVC_RC_QBOUND_VIEW1_V6              0xfd4c
-#define S5P_FIMV_E_MVC_RC_RPARA_VIEW1_V6               0xfd50
-#define S5P_FIMV_E_MVC_INTER_VIEW_PREDICTION_ON_V6     0xfd80
-
-/* Codec numbers  */
-#define S5P_FIMV_CODEC_NONE_V6         -1
-
-
-#define S5P_FIMV_CODEC_H264_DEC_V6     0
-#define S5P_FIMV_CODEC_H264_MVC_DEC_V6 1
-
-#define S5P_FIMV_CODEC_MPEG4_DEC_V6    3
-#define S5P_FIMV_CODEC_FIMV1_DEC_V6    4
-#define S5P_FIMV_CODEC_FIMV2_DEC_V6    5
-#define S5P_FIMV_CODEC_FIMV3_DEC_V6    6
-#define S5P_FIMV_CODEC_FIMV4_DEC_V6    7
-#define S5P_FIMV_CODEC_H263_DEC_V6     8
-#define S5P_FIMV_CODEC_VC1RCV_DEC_V6   9
-#define S5P_FIMV_CODEC_VC1_DEC_V6      10
-/* FIXME: Add 11~12 */
-#define S5P_FIMV_CODEC_MPEG2_DEC_V6    13
-#define S5P_FIMV_CODEC_VP8_DEC_V6      14
-/* FIXME: Add 15~16 */
-#define S5P_FIMV_CODEC_H264_ENC_V6     20
-#define S5P_FIMV_CODEC_H264_MVC_ENC_V6 21
-
-#define S5P_FIMV_CODEC_MPEG4_ENC_V6    23
-#define S5P_FIMV_CODEC_H263_ENC_V6     24
-
-#define S5P_FIMV_NV12M_HALIGN_V6               16
-#define S5P_FIMV_NV12MT_HALIGN_V6              16
-#define S5P_FIMV_NV12MT_VALIGN_V6              16
-
-#define S5P_FIMV_TMV_BUFFER_ALIGN_V6           16
-#define S5P_FIMV_LUMA_DPB_BUFFER_ALIGN_V6      256
-#define S5P_FIMV_CHROMA_DPB_BUFFER_ALIGN_V6    256
-#define S5P_FIMV_ME_BUFFER_ALIGN_V6            256
-#define S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6       256
-
-#define S5P_FIMV_LUMA_MB_TO_PIXEL_V6           256
-#define S5P_FIMV_CHROMA_MB_TO_PIXEL_V6         128
-#define S5P_FIMV_NUM_TMV_BUFFERS_V6            2
-
-#define S5P_FIMV_MAX_FRAME_SIZE_V6             (2 * SZ_1M)
-#define S5P_FIMV_NUM_PIXELS_IN_MB_ROW_V6       16
-#define S5P_FIMV_NUM_PIXELS_IN_MB_COL_V6       16
-
-/* Buffer size requirements defined by hardware */
-#define S5P_FIMV_TMV_BUFFER_SIZE_V6(w, h)      (((w) + 1) * ((h) + 3) * 8)
-#define S5P_FIMV_ME_BUFFER_SIZE_V6(imw, imh, mbw, mbh) \
-       (((((imw + 127) / 64) * 16) *  DIV_ROUND_UP(imh, 64) * 256) + \
-        (DIV_ROUND_UP((mbw) * (mbh), 32) * 16))
-#define S5P_FIMV_SCRATCH_BUF_SIZE_H264_DEC_V6(w, h)    (((w) * 192) + 64)
-#define S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_DEC_V6(w, h) \
-                       ((w) * 144 + 8192 * (h) + 49216 + 1048576)
-#define S5P_FIMV_SCRATCH_BUF_SIZE_VC1_DEC_V6(w, h) \
-                                               (2096 * ((w) + (h) + 1))
-#define S5P_FIMV_SCRATCH_BUF_SIZE_H263_DEC_V6(w, h)    \
-                       S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_DEC_V6(w, h)
-#define S5P_FIMV_SCRATCH_BUF_SIZE_VP8_DEC_V6(w, h) \
-                       ((w) * 32 + (h) * 128 + (((w) + 1) / 2) * 64 + 2112)
-#define S5P_FIMV_SCRATCH_BUF_SIZE_H264_ENC_V6(w, h) \
-                       (((w) * 64) + (((w) + 1) * 16) + (4096 * 16))
-#define S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_ENC_V6(w, h) \
-                       (((w) * 16) + (((w) + 1) * 16))
-
-/* MFC Context buffer sizes */
-#define MFC_CTX_BUF_SIZE_V6            (28 * SZ_1K)    /*  28KB */
-#define MFC_H264_DEC_CTX_BUF_SIZE_V6   (2 * SZ_1M)     /*  2MB */
-#define MFC_OTHER_DEC_CTX_BUF_SIZE_V6  (20 * SZ_1K)    /*  20KB */
-#define MFC_H264_ENC_CTX_BUF_SIZE_V6   (100 * SZ_1K)   /* 100KB */
-#define MFC_OTHER_ENC_CTX_BUF_SIZE_V6  (12 * SZ_1K)    /*  12KB */
-
-/* MFCv6 variant defines */
-#define MAX_FW_SIZE_V6                 (SZ_512K)       /* 512KB */
-#define MAX_CPB_SIZE_V6                        (3 * SZ_1M)     /* 3MB */
-#define MFC_VERSION_V6                 0x61
-#define MFC_NUM_PORTS_V6               1
-
-#endif /* _REGS_FIMV_V6_H */
diff --git a/drivers/media/platform/s5p-mfc/regs-mfc-v7.h b/drivers/media/platform/s5p-mfc/regs-mfc-v7.h
deleted file mode 100644 (file)
index 4a7adfd..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Register definition file for Samsung MFC V7.x Interface (FIMV) driver
- *
- * Copyright (c) 2013 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- */
-
-#ifndef _REGS_MFC_V7_H
-#define _REGS_MFC_V7_H
-
-#include "regs-mfc-v6.h"
-
-/* Additional features of v7 */
-#define S5P_FIMV_CODEC_VP8_ENC_V7      25
-
-/* Additional registers for v7 */
-#define S5P_FIMV_E_SOURCE_FIRST_ADDR_V7                        0xf9e0
-#define S5P_FIMV_E_SOURCE_SECOND_ADDR_V7               0xf9e4
-#define S5P_FIMV_E_SOURCE_THIRD_ADDR_V7                        0xf9e8
-#define S5P_FIMV_E_SOURCE_FIRST_STRIDE_V7              0xf9ec
-#define S5P_FIMV_E_SOURCE_SECOND_STRIDE_V7             0xf9f0
-#define S5P_FIMV_E_SOURCE_THIRD_STRIDE_V7              0xf9f4
-
-#define S5P_FIMV_E_ENCODED_SOURCE_FIRST_ADDR_V7                0xfa70
-#define S5P_FIMV_E_ENCODED_SOURCE_SECOND_ADDR_V7       0xfa74
-
-#define S5P_FIMV_E_VP8_OPTIONS_V7                      0xfdb0
-#define S5P_FIMV_E_VP8_FILTER_OPTIONS_V7               0xfdb4
-#define S5P_FIMV_E_VP8_GOLDEN_FRAME_OPTION_V7          0xfdb8
-#define S5P_FIMV_E_VP8_NUM_T_LAYER_V7                  0xfdc4
-
-/* MFCv7 variant defines */
-#define MAX_FW_SIZE_V7                 (SZ_512K)       /* 512KB */
-#define MAX_CPB_SIZE_V7                        (3 * SZ_1M)     /* 3MB */
-#define MFC_VERSION_V7                 0x72
-#define MFC_NUM_PORTS_V7               1
-
-#define MFC_LUMA_PAD_BYTES_V7          256
-#define MFC_CHROMA_PAD_BYTES_V7                128
-
-/* MFCv7 Context buffer sizes */
-#define MFC_CTX_BUF_SIZE_V7            (30 * SZ_1K)    /*  30KB */
-#define MFC_H264_DEC_CTX_BUF_SIZE_V7   (2 * SZ_1M)     /*  2MB */
-#define MFC_OTHER_DEC_CTX_BUF_SIZE_V7  (20 * SZ_1K)    /*  20KB */
-#define MFC_H264_ENC_CTX_BUF_SIZE_V7   (100 * SZ_1K)   /* 100KB */
-#define MFC_OTHER_ENC_CTX_BUF_SIZE_V7  (10 * SZ_1K)    /*  10KB */
-
-/* Buffer size defines */
-#define S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_DEC_V7(w, h) \
-                       (SZ_1M + ((w) * 144) + (8192 * (h)) + 49216)
-
-#define S5P_FIMV_SCRATCH_BUF_SIZE_VP8_ENC_V7(w, h) \
-                       (((w) * 48) + 8192 + ((((w) + 1) / 2) * 128) + 144 + \
-                       ((((((w) * 16) * ((h) * 16)) * 3) / 2) * 4))
-
-#endif /*_REGS_MFC_V7_H*/
diff --git a/drivers/media/platform/s5p-mfc/regs-mfc-v8.h b/drivers/media/platform/s5p-mfc/regs-mfc-v8.h
deleted file mode 100644 (file)
index 162e3c7..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Register definition file for Samsung MFC V8.x Interface (FIMV) driver
- *
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- */
-
-#ifndef _REGS_MFC_V8_H
-#define _REGS_MFC_V8_H
-
-#include <linux/sizes.h>
-#include "regs-mfc-v7.h"
-
-/* Additional registers for v8 */
-#define S5P_FIMV_D_MVC_NUM_VIEWS_V8            0xf104
-#define S5P_FIMV_D_MIN_SCRATCH_BUFFER_SIZE_V8  0xf108
-#define S5P_FIMV_D_FIRST_PLANE_DPB_SIZE_V8     0xf144
-#define S5P_FIMV_D_SECOND_PLANE_DPB_SIZE_V8    0xf148
-#define S5P_FIMV_D_MV_BUFFER_SIZE_V8           0xf150
-
-#define S5P_FIMV_D_FIRST_PLANE_DPB_STRIDE_SIZE_V8      0xf138
-#define S5P_FIMV_D_SECOND_PLANE_DPB_STRIDE_SIZE_V8     0xf13c
-
-#define S5P_FIMV_D_FIRST_PLANE_DPB_V8          0xf160
-#define S5P_FIMV_D_SECOND_PLANE_DPB_V8         0xf260
-#define S5P_FIMV_D_MV_BUFFER_V8                        0xf460
-
-#define S5P_FIMV_D_NUM_MV_V8                   0xf134
-#define S5P_FIMV_D_INIT_BUFFER_OPTIONS_V8      0xf154
-
-#define S5P_FIMV_D_SCRATCH_BUFFER_ADDR_V8      0xf560
-#define S5P_FIMV_D_SCRATCH_BUFFER_SIZE_V8      0xf564
-
-#define S5P_FIMV_D_CPB_BUFFER_ADDR_V8          0xf5b0
-#define S5P_FIMV_D_CPB_BUFFER_SIZE_V8          0xf5b4
-#define S5P_FIMV_D_AVAILABLE_DPB_FLAG_LOWER_V8 0xf5bc
-#define S5P_FIMV_D_CPB_BUFFER_OFFSET_V8                0xf5c0
-#define S5P_FIMV_D_SLICE_IF_ENABLE_V8          0xf5c4
-#define S5P_FIMV_D_STREAM_DATA_SIZE_V8         0xf5d0
-
-/* Display information register */
-#define S5P_FIMV_D_DISPLAY_FRAME_WIDTH_V8      0xf600
-#define S5P_FIMV_D_DISPLAY_FRAME_HEIGHT_V8     0xf604
-
-/* Display status */
-#define S5P_FIMV_D_DISPLAY_STATUS_V8           0xf608
-
-#define S5P_FIMV_D_DISPLAY_FIRST_PLANE_ADDR_V8 0xf60c
-#define S5P_FIMV_D_DISPLAY_SECOND_PLANE_ADDR_V8        0xf610
-
-#define S5P_FIMV_D_DISPLAY_FRAME_TYPE_V8       0xf618
-#define S5P_FIMV_D_DISPLAY_CROP_INFO1_V8       0xf61c
-#define S5P_FIMV_D_DISPLAY_CROP_INFO2_V8       0xf620
-#define S5P_FIMV_D_DISPLAY_PICTURE_PROFILE_V8  0xf624
-
-/* Decoded picture information register */
-#define S5P_FIMV_D_DECODED_STATUS_V8           0xf644
-#define S5P_FIMV_D_DECODED_FIRST_PLANE_ADDR_V8 0xf648
-#define S5P_FIMV_D_DECODED_SECOND_PLANE_ADDR_V8        0xf64c
-#define S5P_FIMV_D_DECODED_THIRD_PLANE_ADDR_V8 0xf650
-#define S5P_FIMV_D_DECODED_FRAME_TYPE_V8       0xf654
-#define S5P_FIMV_D_DECODED_NAL_SIZE_V8          0xf664
-
-/* Returned value register for specific setting */
-#define S5P_FIMV_D_RET_PICTURE_TAG_TOP_V8      0xf674
-#define S5P_FIMV_D_RET_PICTURE_TAG_BOT_V8      0xf678
-#define S5P_FIMV_D_MVC_VIEW_ID_V8              0xf6d8
-
-/* SEI related information */
-#define S5P_FIMV_D_FRAME_PACK_SEI_AVAIL_V8     0xf6dc
-
-/* Encoder Registers */
-#define S5P_FIMV_E_FIXED_PICTURE_QP_V8         0xf794
-#define S5P_FIMV_E_RC_CONFIG_V8                        0xf798
-#define S5P_FIMV_E_RC_QP_BOUND_V8              0xf79c
-#define S5P_FIMV_E_RC_RPARAM_V8                        0xf7a4
-#define S5P_FIMV_E_MB_RC_CONFIG_V8             0xf7a8
-#define S5P_FIMV_E_PADDING_CTRL_V8             0xf7ac
-#define S5P_FIMV_E_MV_HOR_RANGE_V8             0xf7b4
-#define S5P_FIMV_E_MV_VER_RANGE_V8             0xf7b8
-
-#define S5P_FIMV_E_VBV_BUFFER_SIZE_V8          0xf78c
-#define S5P_FIMV_E_VBV_INIT_DELAY_V8           0xf790
-#define S5P_FIMV_E_MIN_SCRATCH_BUFFER_SIZE_V8   0xf894
-
-#define S5P_FIMV_E_ASPECT_RATIO_V8             0xfb4c
-#define S5P_FIMV_E_EXTENDED_SAR_V8             0xfb50
-#define S5P_FIMV_E_H264_OPTIONS_V8             0xfb54
-
-/* MFCv8 Context buffer sizes */
-#define MFC_CTX_BUF_SIZE_V8            (36 * SZ_1K)    /*  36KB */
-#define MFC_H264_DEC_CTX_BUF_SIZE_V8   (2 * SZ_1M)     /*  2MB */
-#define MFC_OTHER_DEC_CTX_BUF_SIZE_V8  (20 * SZ_1K)    /*  20KB */
-#define MFC_H264_ENC_CTX_BUF_SIZE_V8   (100 * SZ_1K)   /* 100KB */
-#define MFC_OTHER_ENC_CTX_BUF_SIZE_V8  (10 * SZ_1K)    /*  10KB */
-
-/* Buffer size defines */
-#define S5P_FIMV_TMV_BUFFER_SIZE_V8(w, h)      (((w) + 1) * ((h) + 1) * 8)
-
-#define S5P_FIMV_SCRATCH_BUF_SIZE_H264_DEC_V8(w, h)    (((w) * 704) + 2176)
-#define S5P_FIMV_SCRATCH_BUF_SIZE_VP8_DEC_V8(w, h) \
-               (((w) * 576 + (h) * 128)  + 4128)
-
-#define S5P_FIMV_SCRATCH_BUF_SIZE_H264_ENC_V8(w, h) \
-                       (((w) * 592) + 2336)
-#define S5P_FIMV_SCRATCH_BUF_SIZE_VP8_ENC_V8(w, h) \
-                       (((w) * 576) + 10512 + \
-                       ((((((w) * 16) * ((h) * 16)) * 3) / 2) * 4))
-#define S5P_FIMV_ME_BUFFER_SIZE_V8(imw, imh, mbw, mbh) \
-       ((DIV_ROUND_UP((mbw * 16), 64) *  DIV_ROUND_UP((mbh * 16), 64) * 256) \
-        + (DIV_ROUND_UP((mbw) * (mbh), 32) * 16))
-
-/* BUffer alignment defines */
-#define S5P_FIMV_D_ALIGN_PLANE_SIZE_V8 64
-
-/* MFCv8 variant defines */
-#define MAX_FW_SIZE_V8                 (SZ_512K)       /* 512KB */
-#define MAX_CPB_SIZE_V8                        (3 * SZ_1M)     /* 3MB */
-#define MFC_VERSION_V8                 0x80
-#define MFC_NUM_PORTS_V8               1
-
-#endif /*_REGS_MFC_V8_H*/
diff --git a/drivers/media/platform/s5p-mfc/regs-mfc.h b/drivers/media/platform/s5p-mfc/regs-mfc.h
deleted file mode 100644 (file)
index 9171e81..0000000
+++ /dev/null
@@ -1,459 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Register definition file for Samsung MFC V5.1 Interface (FIMV) driver
- *
- * Kamil Debski, Copyright (c) 2010 Samsung Electronics
- * http://www.samsung.com/
-*/
-
-#ifndef _REGS_FIMV_H
-#define _REGS_FIMV_H
-
-#include <linux/kernel.h>
-#include <linux/sizes.h>
-
-#define S5P_FIMV_REG_SIZE      (S5P_FIMV_END_ADDR - S5P_FIMV_START_ADDR)
-#define S5P_FIMV_REG_COUNT     ((S5P_FIMV_END_ADDR - S5P_FIMV_START_ADDR) / 4)
-
-/* Number of bits that the buffer address should be shifted for particular
- * MFC buffers.  */
-#define S5P_FIMV_START_ADDR            0x0000
-#define S5P_FIMV_END_ADDR              0xe008
-
-#define S5P_FIMV_SW_RESET              0x0000
-#define S5P_FIMV_RISC_HOST_INT         0x0008
-
-/* Command from HOST to RISC */
-#define S5P_FIMV_HOST2RISC_CMD         0x0030
-#define S5P_FIMV_HOST2RISC_ARG1                0x0034
-#define S5P_FIMV_HOST2RISC_ARG2                0x0038
-#define S5P_FIMV_HOST2RISC_ARG3                0x003c
-#define S5P_FIMV_HOST2RISC_ARG4                0x0040
-
-/* Command from RISC to HOST */
-#define S5P_FIMV_RISC2HOST_CMD         0x0044
-#define S5P_FIMV_RISC2HOST_CMD_MASK    0x1FFFF
-#define S5P_FIMV_RISC2HOST_ARG1                0x0048
-#define S5P_FIMV_RISC2HOST_ARG2                0x004c
-#define S5P_FIMV_RISC2HOST_ARG3                0x0050
-#define S5P_FIMV_RISC2HOST_ARG4                0x0054
-
-#define S5P_FIMV_FW_VERSION            0x0058
-#define S5P_FIMV_SYS_MEM_SZ            0x005c
-#define S5P_FIMV_FW_STATUS             0x0080
-
-/* Memory controller register */
-#define S5P_FIMV_MC_DRAMBASE_ADR_A     0x0508
-#define S5P_FIMV_MC_DRAMBASE_ADR_B     0x050c
-#define S5P_FIMV_MC_STATUS             0x0510
-
-/* Common register */
-#define S5P_FIMV_COMMON_BASE_A         0x0600
-#define S5P_FIMV_COMMON_BASE_B         0x0700
-
-/* Decoder */
-#define S5P_FIMV_DEC_CHROMA_ADR                (S5P_FIMV_COMMON_BASE_A)
-#define S5P_FIMV_DEC_LUMA_ADR          (S5P_FIMV_COMMON_BASE_B)
-
-/* H.264 decoding */
-#define S5P_FIMV_H264_VERT_NB_MV_ADR   (S5P_FIMV_COMMON_BASE_A + 0x8c)
-                                       /* vertical neighbor motion vector */
-#define S5P_FIMV_H264_NB_IP_ADR                (S5P_FIMV_COMMON_BASE_A + 0x90)
-                                       /* neighbor pixels for intra pred */
-#define S5P_FIMV_H264_MV_ADR           (S5P_FIMV_COMMON_BASE_B + 0x80)
-                                       /* H264 motion vector */
-
-/* MPEG4 decoding */
-#define S5P_FIMV_MPEG4_NB_DCAC_ADR     (S5P_FIMV_COMMON_BASE_A + 0x8c)
-                                       /* neighbor AC/DC coeff. */
-#define S5P_FIMV_MPEG4_UP_NB_MV_ADR    (S5P_FIMV_COMMON_BASE_A + 0x90)
-                                       /* upper neighbor motion vector */
-#define S5P_FIMV_MPEG4_SA_MV_ADR       (S5P_FIMV_COMMON_BASE_A + 0x94)
-                                       /* subseq. anchor motion vector */
-#define S5P_FIMV_MPEG4_OT_LINE_ADR     (S5P_FIMV_COMMON_BASE_A + 0x98)
-                                       /* overlap transform line */
-#define S5P_FIMV_MPEG4_SP_ADR          (S5P_FIMV_COMMON_BASE_A + 0xa8)
-                                       /* syntax parser */
-
-/* H.263 decoding */
-#define S5P_FIMV_H263_NB_DCAC_ADR      (S5P_FIMV_COMMON_BASE_A + 0x8c)
-#define S5P_FIMV_H263_UP_NB_MV_ADR     (S5P_FIMV_COMMON_BASE_A + 0x90)
-#define S5P_FIMV_H263_SA_MV_ADR                (S5P_FIMV_COMMON_BASE_A + 0x94)
-#define S5P_FIMV_H263_OT_LINE_ADR      (S5P_FIMV_COMMON_BASE_A + 0x98)
-
-/* VC-1 decoding */
-#define S5P_FIMV_VC1_NB_DCAC_ADR       (S5P_FIMV_COMMON_BASE_A + 0x8c)
-#define S5P_FIMV_VC1_UP_NB_MV_ADR      (S5P_FIMV_COMMON_BASE_A + 0x90)
-#define S5P_FIMV_VC1_SA_MV_ADR         (S5P_FIMV_COMMON_BASE_A + 0x94)
-#define S5P_FIMV_VC1_OT_LINE_ADR       (S5P_FIMV_COMMON_BASE_A + 0x98)
-#define S5P_FIMV_VC1_BITPLANE3_ADR     (S5P_FIMV_COMMON_BASE_A + 0x9c)
-                                       /* bitplane3 */
-#define S5P_FIMV_VC1_BITPLANE2_ADR     (S5P_FIMV_COMMON_BASE_A + 0xa0)
-                                       /* bitplane2 */
-#define S5P_FIMV_VC1_BITPLANE1_ADR     (S5P_FIMV_COMMON_BASE_A + 0xa4)
-                                       /* bitplane1 */
-
-/* Encoder */
-#define S5P_FIMV_ENC_REF0_LUMA_ADR     (S5P_FIMV_COMMON_BASE_A + 0x1c)
-#define S5P_FIMV_ENC_REF1_LUMA_ADR     (S5P_FIMV_COMMON_BASE_A + 0x20)
-                                       /* reconstructed luma */
-#define S5P_FIMV_ENC_REF0_CHROMA_ADR   (S5P_FIMV_COMMON_BASE_B)
-#define S5P_FIMV_ENC_REF1_CHROMA_ADR   (S5P_FIMV_COMMON_BASE_B + 0x04)
-                                       /* reconstructed chroma */
-#define S5P_FIMV_ENC_REF2_LUMA_ADR     (S5P_FIMV_COMMON_BASE_B + 0x10)
-#define S5P_FIMV_ENC_REF2_CHROMA_ADR   (S5P_FIMV_COMMON_BASE_B + 0x08)
-#define S5P_FIMV_ENC_REF3_LUMA_ADR     (S5P_FIMV_COMMON_BASE_B + 0x14)
-#define S5P_FIMV_ENC_REF3_CHROMA_ADR   (S5P_FIMV_COMMON_BASE_B + 0x0c)
-
-/* H.264 encoding */
-#define S5P_FIMV_H264_UP_MV_ADR                (S5P_FIMV_COMMON_BASE_A)
-                                       /* upper motion vector */
-#define S5P_FIMV_H264_NBOR_INFO_ADR    (S5P_FIMV_COMMON_BASE_A + 0x04)
-                                       /* entropy engine's neighbor info. */
-#define S5P_FIMV_H264_UP_INTRA_MD_ADR  (S5P_FIMV_COMMON_BASE_A + 0x08)
-                                       /* upper intra MD */
-#define S5P_FIMV_H264_COZERO_FLAG_ADR  (S5P_FIMV_COMMON_BASE_A + 0x10)
-                                       /* direct cozero flag */
-#define S5P_FIMV_H264_UP_INTRA_PRED_ADR        (S5P_FIMV_COMMON_BASE_B + 0x40)
-                                       /* upper intra PRED */
-
-/* H.263 encoding */
-#define S5P_FIMV_H263_UP_MV_ADR                (S5P_FIMV_COMMON_BASE_A)
-                                       /* upper motion vector */
-#define S5P_FIMV_H263_ACDC_COEF_ADR    (S5P_FIMV_COMMON_BASE_A + 0x04)
-                                       /* upper Q coeff. */
-
-/* MPEG4 encoding */
-#define S5P_FIMV_MPEG4_UP_MV_ADR       (S5P_FIMV_COMMON_BASE_A)
-                                       /* upper motion vector */
-#define S5P_FIMV_MPEG4_ACDC_COEF_ADR   (S5P_FIMV_COMMON_BASE_A + 0x04)
-                                       /* upper Q coeff. */
-#define S5P_FIMV_MPEG4_COZERO_FLAG_ADR (S5P_FIMV_COMMON_BASE_A + 0x10)
-                                       /* direct cozero flag */
-
-#define S5P_FIMV_ENC_REF_B_LUMA_ADR     0x062c /* ref B Luma addr */
-#define S5P_FIMV_ENC_REF_B_CHROMA_ADR   0x0630 /* ref B Chroma addr */
-
-#define S5P_FIMV_ENC_CUR_LUMA_ADR      0x0718 /* current Luma addr */
-#define S5P_FIMV_ENC_CUR_CHROMA_ADR    0x071C /* current Chroma addr */
-
-/* Codec common register */
-#define S5P_FIMV_ENC_HSIZE_PX          0x0818 /* frame width at encoder */
-#define S5P_FIMV_ENC_VSIZE_PX          0x081c /* frame height at encoder */
-#define S5P_FIMV_ENC_PROFILE           0x0830 /* profile register */
-#define S5P_FIMV_ENC_PROFILE_H264_MAIN                 0
-#define S5P_FIMV_ENC_PROFILE_H264_HIGH                 1
-#define S5P_FIMV_ENC_PROFILE_H264_BASELINE             2
-#define S5P_FIMV_ENC_PROFILE_H264_CONSTRAINED_BASELINE 3
-#define S5P_FIMV_ENC_PROFILE_MPEG4_SIMPLE              0
-#define S5P_FIMV_ENC_PROFILE_MPEG4_ADVANCED_SIMPLE     1
-#define S5P_FIMV_ENC_PIC_STRUCT                0x083c /* picture field/frame flag */
-#define S5P_FIMV_ENC_LF_CTRL           0x0848 /* loop filter control */
-#define S5P_FIMV_ENC_ALPHA_OFF         0x084c /* loop filter alpha offset */
-#define S5P_FIMV_ENC_BETA_OFF          0x0850 /* loop filter beta offset */
-#define S5P_FIMV_MR_BUSIF_CTRL         0x0854 /* hidden, bus interface ctrl */
-#define S5P_FIMV_ENC_PXL_CACHE_CTRL    0x0a00 /* pixel cache control */
-
-/* Channel & stream interface register */
-#define S5P_FIMV_SI_RTN_CHID           0x2000 /* Return CH inst ID register */
-#define S5P_FIMV_SI_CH0_INST_ID                0x2040 /* codec instance ID */
-#define S5P_FIMV_SI_CH1_INST_ID                0x2080 /* codec instance ID */
-/* Decoder */
-#define S5P_FIMV_SI_VRESOL             0x2004 /* vertical res of decoder */
-#define S5P_FIMV_SI_HRESOL             0x2008 /* horizontal res of decoder */
-#define S5P_FIMV_SI_BUF_NUMBER         0x200c /* number of frames in the
-                                                               decoded pic */
-#define S5P_FIMV_SI_DISPLAY_Y_ADR      0x2010 /* luma addr of displayed pic */
-#define S5P_FIMV_SI_DISPLAY_C_ADR      0x2014 /* chroma addrof displayed pic */
-
-#define S5P_FIMV_SI_CONSUMED_BYTES     0x2018 /* Consumed number of bytes to
-                                                       decode a frame */
-#define S5P_FIMV_SI_DISPLAY_STATUS     0x201c /* status of decoded picture */
-
-#define S5P_FIMV_SI_DECODE_Y_ADR       0x2024 /* luma addr of decoded pic */
-#define S5P_FIMV_SI_DECODE_C_ADR       0x2028 /* chroma addrof decoded pic */
-#define S5P_FIMV_SI_DECODE_STATUS      0x202c /* status of decoded picture */
-
-#define S5P_FIMV_SI_CH0_SB_ST_ADR      0x2044 /* start addr of stream buf */
-#define S5P_FIMV_SI_CH0_SB_FRM_SIZE    0x2048 /* size of stream buf */
-#define S5P_FIMV_SI_CH0_DESC_ADR       0x204c /* addr of descriptor buf */
-#define S5P_FIMV_SI_CH0_CPB_SIZE       0x2058 /* max size of coded pic. buf */
-#define S5P_FIMV_SI_CH0_DESC_SIZE      0x205c /* max size of descriptor buf */
-
-#define S5P_FIMV_SI_CH1_SB_ST_ADR      0x2084 /* start addr of stream buf */
-#define S5P_FIMV_SI_CH1_SB_FRM_SIZE    0x2088 /* size of stream buf */
-#define S5P_FIMV_SI_CH1_DESC_ADR       0x208c /* addr of descriptor buf */
-#define S5P_FIMV_SI_CH1_CPB_SIZE       0x2098 /* max size of coded pic. buf */
-#define S5P_FIMV_SI_CH1_DESC_SIZE      0x209c /* max size of descriptor buf */
-
-#define S5P_FIMV_CRC_LUMA0             0x2030 /* luma crc data per frame
-                                                               (top field) */
-#define S5P_FIMV_CRC_CHROMA0           0x2034 /* chroma crc data per frame
-                                                               (top field) */
-#define S5P_FIMV_CRC_LUMA1             0x2038 /* luma crc data per bottom
-                                                               field */
-#define S5P_FIMV_CRC_CHROMA1           0x203c /* chroma crc data per bottom
-                                                               field */
-
-/* Display status */
-#define S5P_FIMV_DEC_STATUS_DECODING_ONLY              0
-#define S5P_FIMV_DEC_STATUS_DECODING_DISPLAY           1
-#define S5P_FIMV_DEC_STATUS_DISPLAY_ONLY               2
-#define S5P_FIMV_DEC_STATUS_DECODING_EMPTY             3
-#define S5P_FIMV_DEC_STATUS_DECODING_STATUS_MASK       7
-#define S5P_FIMV_DEC_STATUS_PROGRESSIVE                        (0<<3)
-#define S5P_FIMV_DEC_STATUS_INTERLACE                  (1<<3)
-#define S5P_FIMV_DEC_STATUS_INTERLACE_MASK             (1<<3)
-#define S5P_FIMV_DEC_STATUS_CRC_NUMBER_TWO             (0<<4)
-#define S5P_FIMV_DEC_STATUS_CRC_NUMBER_FOUR            (1<<4)
-#define S5P_FIMV_DEC_STATUS_CRC_NUMBER_MASK            (1<<4)
-#define S5P_FIMV_DEC_STATUS_CRC_GENERATED              (1<<5)
-#define S5P_FIMV_DEC_STATUS_CRC_NOT_GENERATED          (0<<5)
-#define S5P_FIMV_DEC_STATUS_CRC_MASK                   (1<<5)
-
-#define S5P_FIMV_DEC_STATUS_RESOLUTION_MASK            (3<<4)
-#define S5P_FIMV_DEC_STATUS_RESOLUTION_INC             (1<<4)
-#define S5P_FIMV_DEC_STATUS_RESOLUTION_DEC             (2<<4)
-#define S5P_FIMV_DEC_STATUS_RESOLUTION_SHIFT           4
-
-/* Decode frame address */
-#define S5P_FIMV_DECODE_Y_ADR                  0x2024
-#define S5P_FIMV_DECODE_C_ADR                  0x2028
-
-/* Decoded frame tpe */
-#define S5P_FIMV_DECODE_FRAME_TYPE             0x2020
-#define S5P_FIMV_DECODE_FRAME_MASK             7
-
-#define S5P_FIMV_DECODE_FRAME_SKIPPED          0
-#define S5P_FIMV_DECODE_FRAME_I_FRAME          1
-#define S5P_FIMV_DECODE_FRAME_P_FRAME          2
-#define S5P_FIMV_DECODE_FRAME_B_FRAME          3
-#define S5P_FIMV_DECODE_FRAME_OTHER_FRAME      4
-
-/* Sizes of buffers required for decoding */
-#define S5P_FIMV_DEC_NB_IP_SIZE                        (32 * 1024)
-#define S5P_FIMV_DEC_VERT_NB_MV_SIZE           (16 * 1024)
-#define S5P_FIMV_DEC_NB_DCAC_SIZE              (16 * 1024)
-#define S5P_FIMV_DEC_UPNB_MV_SIZE              (68 * 1024)
-#define S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE                (136 * 1024)
-#define S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE     (32 * 1024)
-#define S5P_FIMV_DEC_VC1_BITPLANE_SIZE         (2 * 1024)
-#define S5P_FIMV_DEC_STX_PARSER_SIZE           (68 * 1024)
-
-#define S5P_FIMV_DEC_BUF_ALIGN                 (8 * 1024)
-#define S5P_FIMV_ENC_BUF_ALIGN                 (8 * 1024)
-#define S5P_FIMV_NV12M_HALIGN                  16
-#define S5P_FIMV_NV12M_LVALIGN                 16
-#define S5P_FIMV_NV12M_CVALIGN                 8
-#define S5P_FIMV_NV12MT_HALIGN                 128
-#define S5P_FIMV_NV12MT_VALIGN                 32
-#define S5P_FIMV_NV12M_SALIGN                  2048
-#define S5P_FIMV_NV12MT_SALIGN                 8192
-
-/* Sizes of buffers required for encoding */
-#define S5P_FIMV_ENC_UPMV_SIZE         0x10000
-#define S5P_FIMV_ENC_COLFLG_SIZE       0x10000
-#define S5P_FIMV_ENC_INTRAMD_SIZE      0x10000
-#define S5P_FIMV_ENC_INTRAPRED_SIZE    0x4000
-#define S5P_FIMV_ENC_NBORINFO_SIZE     0x10000
-#define S5P_FIMV_ENC_ACDCCOEF_SIZE     0x10000
-
-/* Encoder */
-#define S5P_FIMV_ENC_SI_STRM_SIZE      0x2004 /* stream size */
-#define S5P_FIMV_ENC_SI_PIC_CNT                0x2008 /* picture count */
-#define S5P_FIMV_ENC_SI_WRITE_PTR      0x200c /* write pointer */
-#define S5P_FIMV_ENC_SI_SLICE_TYPE     0x2010 /* slice type(I/P/B/IDR) */
-#define S5P_FIMV_ENC_SI_SLICE_TYPE_NON_CODED   0
-#define S5P_FIMV_ENC_SI_SLICE_TYPE_I           1
-#define S5P_FIMV_ENC_SI_SLICE_TYPE_P           2
-#define S5P_FIMV_ENC_SI_SLICE_TYPE_B           3
-#define S5P_FIMV_ENC_SI_SLICE_TYPE_SKIPPED     4
-#define S5P_FIMV_ENC_SI_SLICE_TYPE_OTHERS      5
-#define S5P_FIMV_ENCODED_Y_ADDR         0x2014 /* the addr of the encoded
-                                                               luma pic */
-#define S5P_FIMV_ENCODED_C_ADDR         0x2018 /* the addr of the encoded
-                                                               chroma pic */
-
-#define S5P_FIMV_ENC_SI_CH0_SB_ADR     0x2044 /* addr of stream buf */
-#define S5P_FIMV_ENC_SI_CH0_SB_SIZE    0x204c /* size of stream buf */
-#define S5P_FIMV_ENC_SI_CH0_CUR_Y_ADR  0x2050 /* current Luma addr */
-#define S5P_FIMV_ENC_SI_CH0_CUR_C_ADR  0x2054 /* current Chroma addr */
-#define S5P_FIMV_ENC_SI_CH0_FRAME_INS  0x2058 /* frame insertion */
-
-#define S5P_FIMV_ENC_SI_CH1_SB_ADR     0x2084 /* addr of stream buf */
-#define S5P_FIMV_ENC_SI_CH1_SB_SIZE    0x208c /* size of stream buf */
-#define S5P_FIMV_ENC_SI_CH1_CUR_Y_ADR  0x2090 /* current Luma addr */
-#define S5P_FIMV_ENC_SI_CH1_CUR_C_ADR  0x2094 /* current Chroma addr */
-#define S5P_FIMV_ENC_SI_CH1_FRAME_INS  0x2098 /* frame insertion */
-
-#define S5P_FIMV_ENC_PIC_TYPE_CTRL     0xc504 /* pic type level control */
-#define S5P_FIMV_ENC_B_RECON_WRITE_ON  0xc508 /* B frame recon write ctrl */
-#define S5P_FIMV_ENC_MSLICE_CTRL       0xc50c /* multi slice control */
-#define S5P_FIMV_ENC_MSLICE_MB         0xc510 /* MB number in the one slice */
-#define S5P_FIMV_ENC_MSLICE_BIT                0xc514 /* bit count for one slice */
-#define S5P_FIMV_ENC_CIR_CTRL          0xc518 /* number of intra refresh MB */
-#define S5P_FIMV_ENC_MAP_FOR_CUR       0xc51c /* linear or tiled mode */
-#define S5P_FIMV_ENC_PADDING_CTRL      0xc520 /* padding control */
-
-#define S5P_FIMV_ENC_RC_CONFIG         0xc5a0 /* RC config */
-#define S5P_FIMV_ENC_RC_BIT_RATE       0xc5a8 /* bit rate */
-#define S5P_FIMV_ENC_RC_QBOUND         0xc5ac /* max/min QP */
-#define S5P_FIMV_ENC_RC_RPARA          0xc5b0 /* rate control reaction coeff */
-#define S5P_FIMV_ENC_RC_MB_CTRL                0xc5b4 /* MB adaptive scaling */
-
-/* Encoder for H264 only */
-#define S5P_FIMV_ENC_H264_ENTROPY_MODE 0xd004 /* CAVLC or CABAC */
-#define S5P_FIMV_ENC_H264_ALPHA_OFF    0xd008 /* loop filter alpha offset */
-#define S5P_FIMV_ENC_H264_BETA_OFF     0xd00c /* loop filter beta offset */
-#define S5P_FIMV_ENC_H264_NUM_OF_REF   0xd010 /* number of reference for P/B */
-#define S5P_FIMV_ENC_H264_TRANS_FLAG   0xd034 /* 8x8 transform flag in PPS &
-                                                               high profile */
-
-#define S5P_FIMV_ENC_RC_FRAME_RATE     0xd0d0 /* frame rate */
-
-/* Encoder for MPEG4 only */
-#define S5P_FIMV_ENC_MPEG4_QUART_PXL   0xe008 /* qpel interpolation ctrl */
-
-/* Additional */
-#define S5P_FIMV_SI_CH0_DPB_CONF_CTRL   0x2068 /* DPB Config Control Register */
-#define S5P_FIMV_SLICE_INT_MASK                1
-#define S5P_FIMV_SLICE_INT_SHIFT       31
-#define S5P_FIMV_DDELAY_ENA_SHIFT      30
-#define S5P_FIMV_DDELAY_VAL_MASK       0xff
-#define S5P_FIMV_DDELAY_VAL_SHIFT      16
-#define S5P_FIMV_DPB_COUNT_MASK                0xffff
-#define S5P_FIMV_DPB_FLUSH_MASK                1
-#define S5P_FIMV_DPB_FLUSH_SHIFT       14
-
-
-#define S5P_FIMV_SI_CH0_RELEASE_BUF     0x2060 /* DPB release buffer register */
-#define S5P_FIMV_SI_CH0_HOST_WR_ADR    0x2064 /* address of shared memory */
-
-/* Codec numbers  */
-#define S5P_FIMV_CODEC_NONE            -1
-
-#define S5P_FIMV_CODEC_H264_DEC                0
-#define S5P_FIMV_CODEC_VC1_DEC         1
-#define S5P_FIMV_CODEC_MPEG4_DEC       2
-#define S5P_FIMV_CODEC_MPEG2_DEC       3
-#define S5P_FIMV_CODEC_H263_DEC                4
-#define S5P_FIMV_CODEC_VC1RCV_DEC      5
-
-#define S5P_FIMV_CODEC_H264_ENC                16
-#define S5P_FIMV_CODEC_MPEG4_ENC       17
-#define S5P_FIMV_CODEC_H263_ENC                18
-
-/* Channel Control Register */
-#define S5P_FIMV_CH_SEQ_HEADER         1
-#define S5P_FIMV_CH_FRAME_START                2
-#define S5P_FIMV_CH_LAST_FRAME         3
-#define S5P_FIMV_CH_INIT_BUFS          4
-#define S5P_FIMV_CH_FRAME_START_REALLOC        5
-#define S5P_FIMV_CH_MASK               7
-#define S5P_FIMV_CH_SHIFT              16
-
-
-/* Host to RISC command */
-#define S5P_FIMV_H2R_CMD_EMPTY         0
-#define S5P_FIMV_H2R_CMD_OPEN_INSTANCE 1
-#define S5P_FIMV_H2R_CMD_CLOSE_INSTANCE        2
-#define S5P_FIMV_H2R_CMD_SYS_INIT      3
-#define S5P_FIMV_H2R_CMD_FLUSH         4
-#define S5P_FIMV_H2R_CMD_SLEEP         5
-#define S5P_FIMV_H2R_CMD_WAKEUP                6
-
-#define S5P_FIMV_R2H_CMD_EMPTY                 0
-#define S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET     1
-#define S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET    2
-#define S5P_FIMV_R2H_CMD_RSV_RET               3
-#define S5P_FIMV_R2H_CMD_SEQ_DONE_RET          4
-#define S5P_FIMV_R2H_CMD_FRAME_DONE_RET                5
-#define S5P_FIMV_R2H_CMD_SLICE_DONE_RET                6
-#define S5P_FIMV_R2H_CMD_ENC_COMPLETE_RET      7
-#define S5P_FIMV_R2H_CMD_SYS_INIT_RET          8
-#define S5P_FIMV_R2H_CMD_FW_STATUS_RET         9
-#define S5P_FIMV_R2H_CMD_SLEEP_RET             10
-#define S5P_FIMV_R2H_CMD_WAKEUP_RET            11
-#define S5P_FIMV_R2H_CMD_FLUSH_RET             12
-#define S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET      15
-#define S5P_FIMV_R2H_CMD_EDFU_INIT_RET         16
-#define S5P_FIMV_R2H_CMD_ERR_RET               32
-
-/* Dummy definition for MFCv6 compatibility */
-#define S5P_FIMV_CODEC_H264_MVC_DEC            -1
-#define S5P_FIMV_R2H_CMD_FIELD_DONE_RET                -1
-#define S5P_FIMV_MFC_RESET                     -1
-#define S5P_FIMV_RISC_ON                       -1
-#define S5P_FIMV_RISC_BASE_ADDRESS             -1
-#define S5P_FIMV_CODEC_VP8_DEC                 -1
-#define S5P_FIMV_REG_CLEAR_BEGIN               0
-#define S5P_FIMV_REG_CLEAR_COUNT               0
-
-/* Error handling defines */
-#define S5P_FIMV_ERR_NO_VALID_SEQ_HDR          67
-#define S5P_FIMV_ERR_INCOMPLETE_FRAME          124
-#define S5P_FIMV_ERR_TIMEOUT                   140
-#define S5P_FIMV_ERR_WARNINGS_START            145
-#define S5P_FIMV_ERR_DEC_MASK                  0xFFFF
-#define S5P_FIMV_ERR_DEC_SHIFT                 0
-#define S5P_FIMV_ERR_DSPL_MASK                 0xFFFF0000
-#define S5P_FIMV_ERR_DSPL_SHIFT                        16
-
-/* Shared memory registers' offsets */
-
-/* An offset of the start position in the stream when
- * the start position is not aligned */
-#define S5P_FIMV_SHARED_CROP_INFO_H            0x0020
-#define S5P_FIMV_SHARED_CROP_LEFT_MASK         0xFFFF
-#define S5P_FIMV_SHARED_CROP_LEFT_SHIFT                0
-#define S5P_FIMV_SHARED_CROP_RIGHT_MASK                0xFFFF0000
-#define S5P_FIMV_SHARED_CROP_RIGHT_SHIFT       16
-#define S5P_FIMV_SHARED_CROP_INFO_V            0x0024
-#define S5P_FIMV_SHARED_CROP_TOP_MASK          0xFFFF
-#define S5P_FIMV_SHARED_CROP_TOP_SHIFT         0
-#define S5P_FIMV_SHARED_CROP_BOTTOM_MASK       0xFFFF0000
-#define S5P_FIMV_SHARED_CROP_BOTTOM_SHIFT      16
-#define S5P_FIMV_SHARED_SET_FRAME_TAG          0x0004
-#define S5P_FIMV_SHARED_GET_FRAME_TAG_TOP      0x0008
-#define S5P_FIMV_SHARED_GET_FRAME_TAG_BOT      0x000C
-#define S5P_FIMV_SHARED_START_BYTE_NUM         0x0018
-#define S5P_FIMV_SHARED_RC_VOP_TIMING          0x0030
-#define S5P_FIMV_SHARED_LUMA_DPB_SIZE          0x0064
-#define S5P_FIMV_SHARED_CHROMA_DPB_SIZE                0x0068
-#define S5P_FIMV_SHARED_MV_SIZE                        0x006C
-#define S5P_FIMV_SHARED_PIC_TIME_TOP           0x0010
-#define S5P_FIMV_SHARED_PIC_TIME_BOTTOM                0x0014
-#define S5P_FIMV_SHARED_EXT_ENC_CONTROL                0x0028
-#define S5P_FIMV_SHARED_P_B_FRAME_QP           0x0070
-#define S5P_FIMV_SHARED_ASPECT_RATIO_IDC       0x0074
-#define S5P_FIMV_SHARED_EXTENDED_SAR           0x0078
-#define S5P_FIMV_SHARED_H264_I_PERIOD          0x009C
-#define S5P_FIMV_SHARED_RC_CONTROL_CONFIG      0x00A0
-#define S5P_FIMV_SHARED_DISP_FRAME_TYPE_SHIFT  2
-
-/* Offset used by the hardware to store addresses */
-#define MFC_OFFSET_SHIFT       11
-
-#define FIRMWARE_ALIGN         (128 * SZ_1K)   /* 128KB */
-#define MFC_H264_CTX_BUF_SIZE  (600 * SZ_1K)   /* 600KB per H264 instance */
-#define MFC_CTX_BUF_SIZE       (10 * SZ_1K)    /* 10KB per instance */
-#define DESC_BUF_SIZE          (128 * SZ_1K)   /* 128KB for DESC buffer */
-#define SHARED_BUF_SIZE                (8 * SZ_1K)     /* 8KB for shared buffer */
-
-#define DEF_CPB_SIZE           (256 * SZ_1K)   /* 256KB */
-#define MAX_CPB_SIZE           (4 * SZ_1M)     /* 4MB */
-#define MAX_FW_SIZE            (384 * SZ_1K)
-
-#define MFC_VERSION            0x51
-#define MFC_NUM_PORTS          2
-
-#define S5P_FIMV_SHARED_FRAME_PACK_SEI_AVAIL    0x16C
-#define S5P_FIMV_SHARED_FRAME_PACK_ARRGMENT_ID  0x170
-#define S5P_FIMV_SHARED_FRAME_PACK_SEI_INFO     0x174
-#define S5P_FIMV_SHARED_FRAME_PACK_GRID_POS     0x178
-
-/* Values for resolution change in display status */
-#define S5P_FIMV_RES_INCREASE  1
-#define S5P_FIMV_RES_DECREASE  2
-
-#endif /* _REGS_FIMV_H */
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c
deleted file mode 100644 (file)
index 7613419..0000000
+++ /dev/null
@@ -1,1680 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Samsung S5P Multi Format Codec v 5.1
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- * Kamil Debski, <k.debski@samsung.com>
- */
-
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/videodev2.h>
-#include <media/v4l2-event.h>
-#include <linux/workqueue.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/of_reserved_mem.h>
-#include <media/videobuf2-v4l2.h>
-#include "s5p_mfc_common.h"
-#include "s5p_mfc_ctrl.h"
-#include "s5p_mfc_debug.h"
-#include "s5p_mfc_dec.h"
-#include "s5p_mfc_enc.h"
-#include "s5p_mfc_intr.h"
-#include "s5p_mfc_iommu.h"
-#include "s5p_mfc_opr.h"
-#include "s5p_mfc_cmd.h"
-#include "s5p_mfc_pm.h"
-
-#define S5P_MFC_DEC_NAME       "s5p-mfc-dec"
-#define S5P_MFC_ENC_NAME       "s5p-mfc-enc"
-
-int mfc_debug_level;
-module_param_named(debug, mfc_debug_level, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug level - higher value produces more verbose messages");
-
-static char *mfc_mem_size;
-module_param_named(mem, mfc_mem_size, charp, 0644);
-MODULE_PARM_DESC(mem, "Preallocated memory size for the firmware and context buffers");
-
-/* Helper functions for interrupt processing */
-
-/* Remove from hw execution round robin */
-void clear_work_bit(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       spin_lock(&dev->condlock);
-       __clear_bit(ctx->num, &dev->ctx_work_bits);
-       spin_unlock(&dev->condlock);
-}
-
-/* Add to hw execution round robin */
-void set_work_bit(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       spin_lock(&dev->condlock);
-       __set_bit(ctx->num, &dev->ctx_work_bits);
-       spin_unlock(&dev->condlock);
-}
-
-/* Remove from hw execution round robin */
-void clear_work_bit_irqsave(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       unsigned long flags;
-
-       spin_lock_irqsave(&dev->condlock, flags);
-       __clear_bit(ctx->num, &dev->ctx_work_bits);
-       spin_unlock_irqrestore(&dev->condlock, flags);
-}
-
-/* Add to hw execution round robin */
-void set_work_bit_irqsave(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       unsigned long flags;
-
-       spin_lock_irqsave(&dev->condlock, flags);
-       __set_bit(ctx->num, &dev->ctx_work_bits);
-       spin_unlock_irqrestore(&dev->condlock, flags);
-}
-
-int s5p_mfc_get_new_ctx(struct s5p_mfc_dev *dev)
-{
-       unsigned long flags;
-       int ctx;
-
-       spin_lock_irqsave(&dev->condlock, flags);
-       ctx = dev->curr_ctx;
-       do {
-               ctx = (ctx + 1) % MFC_NUM_CONTEXTS;
-               if (ctx == dev->curr_ctx) {
-                       if (!test_bit(ctx, &dev->ctx_work_bits))
-                               ctx = -EAGAIN;
-                       break;
-               }
-       } while (!test_bit(ctx, &dev->ctx_work_bits));
-       spin_unlock_irqrestore(&dev->condlock, flags);
-
-       return ctx;
-}
-
-/* Wake up context wait_queue */
-static void wake_up_ctx(struct s5p_mfc_ctx *ctx, unsigned int reason,
-                       unsigned int err)
-{
-       ctx->int_cond = 1;
-       ctx->int_type = reason;
-       ctx->int_err = err;
-       wake_up(&ctx->queue);
-}
-
-/* Wake up device wait_queue */
-static void wake_up_dev(struct s5p_mfc_dev *dev, unsigned int reason,
-                       unsigned int err)
-{
-       dev->int_cond = 1;
-       dev->int_type = reason;
-       dev->int_err = err;
-       wake_up(&dev->queue);
-}
-
-void s5p_mfc_cleanup_queue(struct list_head *lh, struct vb2_queue *vq)
-{
-       struct s5p_mfc_buf *b;
-       int i;
-
-       while (!list_empty(lh)) {
-               b = list_entry(lh->next, struct s5p_mfc_buf, list);
-               for (i = 0; i < b->b->vb2_buf.num_planes; i++)
-                       vb2_set_plane_payload(&b->b->vb2_buf, i, 0);
-               vb2_buffer_done(&b->b->vb2_buf, VB2_BUF_STATE_ERROR);
-               list_del(&b->list);
-       }
-}
-
-static void s5p_mfc_watchdog(struct timer_list *t)
-{
-       struct s5p_mfc_dev *dev = from_timer(dev, t, watchdog_timer);
-
-       if (test_bit(0, &dev->hw_lock))
-               atomic_inc(&dev->watchdog_cnt);
-       if (atomic_read(&dev->watchdog_cnt) >= MFC_WATCHDOG_CNT) {
-               /* This means that hw is busy and no interrupts were
-                * generated by hw for the Nth time of running this
-                * watchdog timer. This usually means a serious hw
-                * error. Now it is time to kill all instances and
-                * reset the MFC. */
-               mfc_err("Time out during waiting for HW\n");
-               schedule_work(&dev->watchdog_work);
-       }
-       dev->watchdog_timer.expires = jiffies +
-                                       msecs_to_jiffies(MFC_WATCHDOG_INTERVAL);
-       add_timer(&dev->watchdog_timer);
-}
-
-static void s5p_mfc_watchdog_worker(struct work_struct *work)
-{
-       struct s5p_mfc_dev *dev;
-       struct s5p_mfc_ctx *ctx;
-       unsigned long flags;
-       int mutex_locked;
-       int i, ret;
-
-       dev = container_of(work, struct s5p_mfc_dev, watchdog_work);
-
-       mfc_err("Driver timeout error handling\n");
-       /* Lock the mutex that protects open and release.
-        * This is necessary as they may load and unload firmware. */
-       mutex_locked = mutex_trylock(&dev->mfc_mutex);
-       if (!mutex_locked)
-               mfc_err("Error: some instance may be closing/opening\n");
-       spin_lock_irqsave(&dev->irqlock, flags);
-
-       s5p_mfc_clock_off();
-
-       for (i = 0; i < MFC_NUM_CONTEXTS; i++) {
-               ctx = dev->ctx[i];
-               if (!ctx)
-                       continue;
-               ctx->state = MFCINST_ERROR;
-               s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst);
-               s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src);
-               clear_work_bit(ctx);
-               wake_up_ctx(ctx, S5P_MFC_R2H_CMD_ERR_RET, 0);
-       }
-       clear_bit(0, &dev->hw_lock);
-       spin_unlock_irqrestore(&dev->irqlock, flags);
-
-       /* De-init MFC */
-       s5p_mfc_deinit_hw(dev);
-
-       /* Double check if there is at least one instance running.
-        * If no instance is in memory than no firmware should be present */
-       if (dev->num_inst > 0) {
-               ret = s5p_mfc_load_firmware(dev);
-               if (ret) {
-                       mfc_err("Failed to reload FW\n");
-                       goto unlock;
-               }
-               s5p_mfc_clock_on();
-               ret = s5p_mfc_init_hw(dev);
-               s5p_mfc_clock_off();
-               if (ret)
-                       mfc_err("Failed to reinit FW\n");
-       }
-unlock:
-       if (mutex_locked)
-               mutex_unlock(&dev->mfc_mutex);
-}
-
-static void s5p_mfc_handle_frame_all_extracted(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_buf *dst_buf;
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       ctx->state = MFCINST_FINISHED;
-       ctx->sequence++;
-       while (!list_empty(&ctx->dst_queue)) {
-               dst_buf = list_entry(ctx->dst_queue.next,
-                                    struct s5p_mfc_buf, list);
-               mfc_debug(2, "Cleaning up buffer: %d\n",
-                                         dst_buf->b->vb2_buf.index);
-               vb2_set_plane_payload(&dst_buf->b->vb2_buf, 0, 0);
-               vb2_set_plane_payload(&dst_buf->b->vb2_buf, 1, 0);
-               list_del(&dst_buf->list);
-               dst_buf->flags |= MFC_BUF_FLAG_EOS;
-               ctx->dst_queue_cnt--;
-               dst_buf->b->sequence = (ctx->sequence++);
-
-               if (s5p_mfc_hw_call(dev->mfc_ops, get_pic_type_top, ctx) ==
-                       s5p_mfc_hw_call(dev->mfc_ops, get_pic_type_bot, ctx))
-                       dst_buf->b->field = V4L2_FIELD_NONE;
-               else
-                       dst_buf->b->field = V4L2_FIELD_INTERLACED;
-               dst_buf->b->flags |= V4L2_BUF_FLAG_LAST;
-
-               ctx->dec_dst_flag &= ~(1 << dst_buf->b->vb2_buf.index);
-               vb2_buffer_done(&dst_buf->b->vb2_buf, VB2_BUF_STATE_DONE);
-       }
-}
-
-static void s5p_mfc_handle_frame_copy_time(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_buf *dst_buf, *src_buf;
-       u32 dec_y_addr;
-       unsigned int frame_type;
-
-       /* Make sure we actually have a new frame before continuing. */
-       frame_type = s5p_mfc_hw_call(dev->mfc_ops, get_dec_frame_type, dev);
-       if (frame_type == S5P_FIMV_DECODE_FRAME_SKIPPED)
-               return;
-       dec_y_addr = (u32)s5p_mfc_hw_call(dev->mfc_ops, get_dec_y_adr, dev);
-
-       /* Copy timestamp / timecode from decoded src to dst and set
-          appropriate flags. */
-       src_buf = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
-       list_for_each_entry(dst_buf, &ctx->dst_queue, list) {
-               u32 addr = (u32)vb2_dma_contig_plane_dma_addr(&dst_buf->b->vb2_buf, 0);
-
-               if (addr == dec_y_addr) {
-                       dst_buf->b->timecode = src_buf->b->timecode;
-                       dst_buf->b->vb2_buf.timestamp =
-                                               src_buf->b->vb2_buf.timestamp;
-                       dst_buf->b->flags &=
-                               ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
-                       dst_buf->b->flags |=
-                               src_buf->b->flags
-                               & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
-                       switch (frame_type) {
-                       case S5P_FIMV_DECODE_FRAME_I_FRAME:
-                               dst_buf->b->flags |=
-                                               V4L2_BUF_FLAG_KEYFRAME;
-                               break;
-                       case S5P_FIMV_DECODE_FRAME_P_FRAME:
-                               dst_buf->b->flags |=
-                                               V4L2_BUF_FLAG_PFRAME;
-                               break;
-                       case S5P_FIMV_DECODE_FRAME_B_FRAME:
-                               dst_buf->b->flags |=
-                                               V4L2_BUF_FLAG_BFRAME;
-                               break;
-                       default:
-                               /* Don't know how to handle
-                                  S5P_FIMV_DECODE_FRAME_OTHER_FRAME. */
-                               mfc_debug(2, "Unexpected frame type: %d\n",
-                                               frame_type);
-                       }
-                       break;
-               }
-       }
-}
-
-static void s5p_mfc_handle_frame_new(struct s5p_mfc_ctx *ctx, unsigned int err)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_buf  *dst_buf;
-       u32 dspl_y_addr;
-       unsigned int frame_type;
-
-       dspl_y_addr = (u32)s5p_mfc_hw_call(dev->mfc_ops, get_dspl_y_adr, dev);
-       if (IS_MFCV6_PLUS(dev))
-               frame_type = s5p_mfc_hw_call(dev->mfc_ops,
-                       get_disp_frame_type, ctx);
-       else
-               frame_type = s5p_mfc_hw_call(dev->mfc_ops,
-                       get_dec_frame_type, dev);
-
-       /* If frame is same as previous then skip and do not dequeue */
-       if (frame_type == S5P_FIMV_DECODE_FRAME_SKIPPED) {
-               if (!ctx->after_packed_pb)
-                       ctx->sequence++;
-               ctx->after_packed_pb = 0;
-               return;
-       }
-       ctx->sequence++;
-       /* The MFC returns address of the buffer, now we have to
-        * check which videobuf does it correspond to */
-       list_for_each_entry(dst_buf, &ctx->dst_queue, list) {
-               u32 addr = (u32)vb2_dma_contig_plane_dma_addr(&dst_buf->b->vb2_buf, 0);
-
-               /* Check if this is the buffer we're looking for */
-               if (addr == dspl_y_addr) {
-                       list_del(&dst_buf->list);
-                       ctx->dst_queue_cnt--;
-                       dst_buf->b->sequence = ctx->sequence;
-                       if (s5p_mfc_hw_call(dev->mfc_ops,
-                                       get_pic_type_top, ctx) ==
-                               s5p_mfc_hw_call(dev->mfc_ops,
-                                       get_pic_type_bot, ctx))
-                               dst_buf->b->field = V4L2_FIELD_NONE;
-                       else
-                               dst_buf->b->field =
-                                                       V4L2_FIELD_INTERLACED;
-                       vb2_set_plane_payload(&dst_buf->b->vb2_buf, 0,
-                                               ctx->luma_size);
-                       vb2_set_plane_payload(&dst_buf->b->vb2_buf, 1,
-                                               ctx->chroma_size);
-                       clear_bit(dst_buf->b->vb2_buf.index,
-                                                       &ctx->dec_dst_flag);
-
-                       vb2_buffer_done(&dst_buf->b->vb2_buf, err ?
-                               VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
-
-                       break;
-               }
-       }
-}
-
-/* Handle frame decoding interrupt */
-static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx,
-                                       unsigned int reason, unsigned int err)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       unsigned int dst_frame_status;
-       unsigned int dec_frame_status;
-       struct s5p_mfc_buf *src_buf;
-       unsigned int res_change;
-
-       dst_frame_status = s5p_mfc_hw_call(dev->mfc_ops, get_dspl_status, dev)
-                               & S5P_FIMV_DEC_STATUS_DECODING_STATUS_MASK;
-       dec_frame_status = s5p_mfc_hw_call(dev->mfc_ops, get_dec_status, dev)
-                               & S5P_FIMV_DEC_STATUS_DECODING_STATUS_MASK;
-       res_change = (s5p_mfc_hw_call(dev->mfc_ops, get_dspl_status, dev)
-                               & S5P_FIMV_DEC_STATUS_RESOLUTION_MASK)
-                               >> S5P_FIMV_DEC_STATUS_RESOLUTION_SHIFT;
-       mfc_debug(2, "Frame Status: %x\n", dst_frame_status);
-       if (ctx->state == MFCINST_RES_CHANGE_INIT)
-               ctx->state = MFCINST_RES_CHANGE_FLUSH;
-       if (res_change == S5P_FIMV_RES_INCREASE ||
-               res_change == S5P_FIMV_RES_DECREASE) {
-               ctx->state = MFCINST_RES_CHANGE_INIT;
-               s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
-               wake_up_ctx(ctx, reason, err);
-               WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
-               s5p_mfc_clock_off();
-               s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
-               return;
-       }
-       if (ctx->dpb_flush_flag)
-               ctx->dpb_flush_flag = 0;
-
-       /* All frames remaining in the buffer have been extracted  */
-       if (dst_frame_status == S5P_FIMV_DEC_STATUS_DECODING_EMPTY) {
-               if (ctx->state == MFCINST_RES_CHANGE_FLUSH) {
-                       static const struct v4l2_event ev_src_ch = {
-                               .type = V4L2_EVENT_SOURCE_CHANGE,
-                               .u.src_change.changes =
-                                       V4L2_EVENT_SRC_CH_RESOLUTION,
-                       };
-
-                       s5p_mfc_handle_frame_all_extracted(ctx);
-                       ctx->state = MFCINST_RES_CHANGE_END;
-                       v4l2_event_queue_fh(&ctx->fh, &ev_src_ch);
-
-                       goto leave_handle_frame;
-               } else {
-                       s5p_mfc_handle_frame_all_extracted(ctx);
-               }
-       }
-
-       if (dec_frame_status == S5P_FIMV_DEC_STATUS_DECODING_DISPLAY)
-               s5p_mfc_handle_frame_copy_time(ctx);
-
-       /* A frame has been decoded and is in the buffer  */
-       if (dst_frame_status == S5P_FIMV_DEC_STATUS_DISPLAY_ONLY ||
-           dst_frame_status == S5P_FIMV_DEC_STATUS_DECODING_DISPLAY) {
-               s5p_mfc_handle_frame_new(ctx, err);
-       } else {
-               mfc_debug(2, "No frame decode\n");
-       }
-       /* Mark source buffer as complete */
-       if (dst_frame_status != S5P_FIMV_DEC_STATUS_DISPLAY_ONLY
-               && !list_empty(&ctx->src_queue)) {
-               src_buf = list_entry(ctx->src_queue.next, struct s5p_mfc_buf,
-                                                               list);
-               ctx->consumed_stream += s5p_mfc_hw_call(dev->mfc_ops,
-                                               get_consumed_stream, dev);
-               if (ctx->codec_mode != S5P_MFC_CODEC_H264_DEC &&
-                       ctx->codec_mode != S5P_MFC_CODEC_VP8_DEC &&
-                       ctx->consumed_stream + STUFF_BYTE <
-                       src_buf->b->vb2_buf.planes[0].bytesused) {
-                       /* Run MFC again on the same buffer */
-                       mfc_debug(2, "Running again the same buffer\n");
-                       ctx->after_packed_pb = 1;
-               } else {
-                       mfc_debug(2, "MFC needs next buffer\n");
-                       ctx->consumed_stream = 0;
-                       if (src_buf->flags & MFC_BUF_FLAG_EOS)
-                               ctx->state = MFCINST_FINISHING;
-                       list_del(&src_buf->list);
-                       ctx->src_queue_cnt--;
-                       if (s5p_mfc_hw_call(dev->mfc_ops, err_dec, err) > 0)
-                               vb2_buffer_done(&src_buf->b->vb2_buf,
-                                               VB2_BUF_STATE_ERROR);
-                       else
-                               vb2_buffer_done(&src_buf->b->vb2_buf,
-                                               VB2_BUF_STATE_DONE);
-               }
-       }
-leave_handle_frame:
-       if ((ctx->src_queue_cnt == 0 && ctx->state != MFCINST_FINISHING)
-                                   || ctx->dst_queue_cnt < ctx->pb_count)
-               clear_work_bit(ctx);
-       s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
-       wake_up_ctx(ctx, reason, err);
-       WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
-       s5p_mfc_clock_off();
-       /* if suspending, wake up device and do not try_run again*/
-       if (test_bit(0, &dev->enter_suspend))
-               wake_up_dev(dev, reason, err);
-       else
-               s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
-}
-
-/* Error handling for interrupt */
-static void s5p_mfc_handle_error(struct s5p_mfc_dev *dev,
-               struct s5p_mfc_ctx *ctx, unsigned int reason, unsigned int err)
-{
-       mfc_err("Interrupt Error: %08x\n", err);
-
-       if (ctx) {
-               /* Error recovery is dependent on the state of context */
-               switch (ctx->state) {
-               case MFCINST_RES_CHANGE_INIT:
-               case MFCINST_RES_CHANGE_FLUSH:
-               case MFCINST_RES_CHANGE_END:
-               case MFCINST_FINISHING:
-               case MFCINST_FINISHED:
-               case MFCINST_RUNNING:
-                       /* It is highly probable that an error occurred
-                        * while decoding a frame */
-                       clear_work_bit(ctx);
-                       ctx->state = MFCINST_ERROR;
-                       /* Mark all dst buffers as having an error */
-                       s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst);
-                       /* Mark all src buffers as having an error */
-                       s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src);
-                       wake_up_ctx(ctx, reason, err);
-                       break;
-               default:
-                       clear_work_bit(ctx);
-                       ctx->state = MFCINST_ERROR;
-                       wake_up_ctx(ctx, reason, err);
-                       break;
-               }
-       }
-       WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
-       s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
-       s5p_mfc_clock_off();
-       wake_up_dev(dev, reason, err);
-}
-
-/* Header parsing interrupt handling */
-static void s5p_mfc_handle_seq_done(struct s5p_mfc_ctx *ctx,
-                                unsigned int reason, unsigned int err)
-{
-       struct s5p_mfc_dev *dev;
-
-       if (!ctx)
-               return;
-       dev = ctx->dev;
-       if (ctx->c_ops->post_seq_start) {
-               if (ctx->c_ops->post_seq_start(ctx))
-                       mfc_err("post_seq_start() failed\n");
-       } else {
-               ctx->img_width = s5p_mfc_hw_call(dev->mfc_ops, get_img_width,
-                               dev);
-               ctx->img_height = s5p_mfc_hw_call(dev->mfc_ops, get_img_height,
-                               dev);
-
-               s5p_mfc_hw_call(dev->mfc_ops, dec_calc_dpb_size, ctx);
-
-               ctx->pb_count = s5p_mfc_hw_call(dev->mfc_ops, get_dpb_count,
-                               dev);
-               ctx->mv_count = s5p_mfc_hw_call(dev->mfc_ops, get_mv_count,
-                               dev);
-               if (FW_HAS_E_MIN_SCRATCH_BUF(dev))
-                       ctx->scratch_buf_size = s5p_mfc_hw_call(dev->mfc_ops,
-                                               get_min_scratch_buf_size, dev);
-               if (ctx->img_width == 0 || ctx->img_height == 0)
-                       ctx->state = MFCINST_ERROR;
-               else
-                       ctx->state = MFCINST_HEAD_PARSED;
-
-               if ((ctx->codec_mode == S5P_MFC_CODEC_H264_DEC ||
-                       ctx->codec_mode == S5P_MFC_CODEC_H264_MVC_DEC) &&
-                               !list_empty(&ctx->src_queue)) {
-                       struct s5p_mfc_buf *src_buf;
-                       src_buf = list_entry(ctx->src_queue.next,
-                                       struct s5p_mfc_buf, list);
-                       if (s5p_mfc_hw_call(dev->mfc_ops, get_consumed_stream,
-                                               dev) <
-                                       src_buf->b->vb2_buf.planes[0].bytesused)
-                               ctx->head_processed = 0;
-                       else
-                               ctx->head_processed = 1;
-               } else {
-                       ctx->head_processed = 1;
-               }
-       }
-       s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
-       clear_work_bit(ctx);
-       WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
-       s5p_mfc_clock_off();
-       s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
-       wake_up_ctx(ctx, reason, err);
-}
-
-/* Header parsing interrupt handling */
-static void s5p_mfc_handle_init_buffers(struct s5p_mfc_ctx *ctx,
-                                unsigned int reason, unsigned int err)
-{
-       struct s5p_mfc_buf *src_buf;
-       struct s5p_mfc_dev *dev;
-
-       if (!ctx)
-               return;
-       dev = ctx->dev;
-       s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
-       ctx->int_type = reason;
-       ctx->int_err = err;
-       ctx->int_cond = 1;
-       clear_work_bit(ctx);
-       if (err == 0) {
-               ctx->state = MFCINST_RUNNING;
-               if (!ctx->dpb_flush_flag && ctx->head_processed) {
-                       if (!list_empty(&ctx->src_queue)) {
-                               src_buf = list_entry(ctx->src_queue.next,
-                                            struct s5p_mfc_buf, list);
-                               list_del(&src_buf->list);
-                               ctx->src_queue_cnt--;
-                               vb2_buffer_done(&src_buf->b->vb2_buf,
-                                               VB2_BUF_STATE_DONE);
-                       }
-               } else {
-                       ctx->dpb_flush_flag = 0;
-               }
-               WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
-
-               s5p_mfc_clock_off();
-
-               wake_up(&ctx->queue);
-               s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
-       } else {
-               WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
-
-               s5p_mfc_clock_off();
-
-               wake_up(&ctx->queue);
-       }
-}
-
-static void s5p_mfc_handle_stream_complete(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_buf *mb_entry;
-
-       mfc_debug(2, "Stream completed\n");
-
-       ctx->state = MFCINST_FINISHED;
-
-       if (!list_empty(&ctx->dst_queue)) {
-               mb_entry = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf,
-                                                                       list);
-               list_del(&mb_entry->list);
-               ctx->dst_queue_cnt--;
-               vb2_set_plane_payload(&mb_entry->b->vb2_buf, 0, 0);
-               vb2_buffer_done(&mb_entry->b->vb2_buf, VB2_BUF_STATE_DONE);
-       }
-
-       clear_work_bit(ctx);
-
-       WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
-
-       s5p_mfc_clock_off();
-       wake_up(&ctx->queue);
-       s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
-}
-
-/* Interrupt processing */
-static irqreturn_t s5p_mfc_irq(int irq, void *priv)
-{
-       struct s5p_mfc_dev *dev = priv;
-       struct s5p_mfc_ctx *ctx;
-       unsigned int reason;
-       unsigned int err;
-
-       mfc_debug_enter();
-       /* Reset the timeout watchdog */
-       atomic_set(&dev->watchdog_cnt, 0);
-       spin_lock(&dev->irqlock);
-       ctx = dev->ctx[dev->curr_ctx];
-       /* Get the reason of interrupt and the error code */
-       reason = s5p_mfc_hw_call(dev->mfc_ops, get_int_reason, dev);
-       err = s5p_mfc_hw_call(dev->mfc_ops, get_int_err, dev);
-       mfc_debug(1, "Int reason: %d (err: %08x)\n", reason, err);
-       switch (reason) {
-       case S5P_MFC_R2H_CMD_ERR_RET:
-               /* An error has occurred */
-               if (ctx->state == MFCINST_RUNNING &&
-                       (s5p_mfc_hw_call(dev->mfc_ops, err_dec, err) >=
-                               dev->warn_start ||
-                               err == S5P_FIMV_ERR_NO_VALID_SEQ_HDR ||
-                               err == S5P_FIMV_ERR_INCOMPLETE_FRAME ||
-                               err == S5P_FIMV_ERR_TIMEOUT))
-                       s5p_mfc_handle_frame(ctx, reason, err);
-               else
-                       s5p_mfc_handle_error(dev, ctx, reason, err);
-               clear_bit(0, &dev->enter_suspend);
-               break;
-
-       case S5P_MFC_R2H_CMD_SLICE_DONE_RET:
-       case S5P_MFC_R2H_CMD_FIELD_DONE_RET:
-       case S5P_MFC_R2H_CMD_FRAME_DONE_RET:
-               if (ctx->c_ops->post_frame_start) {
-                       if (ctx->c_ops->post_frame_start(ctx))
-                               mfc_err("post_frame_start() failed\n");
-
-                       if (ctx->state == MFCINST_FINISHING &&
-                                               list_empty(&ctx->ref_queue)) {
-                               s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
-                               s5p_mfc_handle_stream_complete(ctx);
-                               break;
-                       }
-                       s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
-                       WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
-                       s5p_mfc_clock_off();
-                       wake_up_ctx(ctx, reason, err);
-                       s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
-               } else {
-                       s5p_mfc_handle_frame(ctx, reason, err);
-               }
-               break;
-
-       case S5P_MFC_R2H_CMD_SEQ_DONE_RET:
-               s5p_mfc_handle_seq_done(ctx, reason, err);
-               break;
-
-       case S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET:
-               ctx->inst_no = s5p_mfc_hw_call(dev->mfc_ops, get_inst_no, dev);
-               ctx->state = MFCINST_GOT_INST;
-               goto irq_cleanup_hw;
-
-       case S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET:
-               ctx->inst_no = MFC_NO_INSTANCE_SET;
-               ctx->state = MFCINST_FREE;
-               goto irq_cleanup_hw;
-
-       case S5P_MFC_R2H_CMD_SYS_INIT_RET:
-       case S5P_MFC_R2H_CMD_FW_STATUS_RET:
-       case S5P_MFC_R2H_CMD_SLEEP_RET:
-       case S5P_MFC_R2H_CMD_WAKEUP_RET:
-               if (ctx)
-                       clear_work_bit(ctx);
-               s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
-               clear_bit(0, &dev->hw_lock);
-               clear_bit(0, &dev->enter_suspend);
-               wake_up_dev(dev, reason, err);
-               break;
-
-       case S5P_MFC_R2H_CMD_INIT_BUFFERS_RET:
-               s5p_mfc_handle_init_buffers(ctx, reason, err);
-               break;
-
-       case S5P_MFC_R2H_CMD_COMPLETE_SEQ_RET:
-               s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
-               ctx->int_type = reason;
-               ctx->int_err = err;
-               s5p_mfc_handle_stream_complete(ctx);
-               break;
-
-       case S5P_MFC_R2H_CMD_DPB_FLUSH_RET:
-               ctx->state = MFCINST_RUNNING;
-               goto irq_cleanup_hw;
-
-       default:
-               mfc_debug(2, "Unknown int reason\n");
-               s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
-       }
-       spin_unlock(&dev->irqlock);
-       mfc_debug_leave();
-       return IRQ_HANDLED;
-irq_cleanup_hw:
-       s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
-       ctx->int_type = reason;
-       ctx->int_err = err;
-       ctx->int_cond = 1;
-       if (test_and_clear_bit(0, &dev->hw_lock) == 0)
-               mfc_err("Failed to unlock hw\n");
-
-       s5p_mfc_clock_off();
-       clear_work_bit(ctx);
-       wake_up(&ctx->queue);
-
-       s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
-       spin_unlock(&dev->irqlock);
-       mfc_debug(2, "Exit via irq_cleanup_hw\n");
-       return IRQ_HANDLED;
-}
-
-/* Open an MFC node */
-static int s5p_mfc_open(struct file *file)
-{
-       struct video_device *vdev = video_devdata(file);
-       struct s5p_mfc_dev *dev = video_drvdata(file);
-       struct s5p_mfc_ctx *ctx = NULL;
-       struct vb2_queue *q;
-       int ret = 0;
-
-       mfc_debug_enter();
-       if (mutex_lock_interruptible(&dev->mfc_mutex))
-               return -ERESTARTSYS;
-       dev->num_inst++;        /* It is guarded by mfc_mutex in vfd */
-       /* Allocate memory for context */
-       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
-       if (!ctx) {
-               ret = -ENOMEM;
-               goto err_alloc;
-       }
-       init_waitqueue_head(&ctx->queue);
-       v4l2_fh_init(&ctx->fh, vdev);
-       file->private_data = &ctx->fh;
-       v4l2_fh_add(&ctx->fh);
-       ctx->dev = dev;
-       INIT_LIST_HEAD(&ctx->src_queue);
-       INIT_LIST_HEAD(&ctx->dst_queue);
-       ctx->src_queue_cnt = 0;
-       ctx->dst_queue_cnt = 0;
-       /* Get context number */
-       ctx->num = 0;
-       while (dev->ctx[ctx->num]) {
-               ctx->num++;
-               if (ctx->num >= MFC_NUM_CONTEXTS) {
-                       mfc_debug(2, "Too many open contexts\n");
-                       ret = -EBUSY;
-                       goto err_no_ctx;
-               }
-       }
-       /* Mark context as idle */
-       clear_work_bit_irqsave(ctx);
-       dev->ctx[ctx->num] = ctx;
-       if (vdev == dev->vfd_dec) {
-               ctx->type = MFCINST_DECODER;
-               ctx->c_ops = get_dec_codec_ops();
-               s5p_mfc_dec_init(ctx);
-               /* Setup ctrl handler */
-               ret = s5p_mfc_dec_ctrls_setup(ctx);
-               if (ret) {
-                       mfc_err("Failed to setup mfc controls\n");
-                       goto err_ctrls_setup;
-               }
-       } else if (vdev == dev->vfd_enc) {
-               ctx->type = MFCINST_ENCODER;
-               ctx->c_ops = get_enc_codec_ops();
-               /* only for encoder */
-               INIT_LIST_HEAD(&ctx->ref_queue);
-               ctx->ref_queue_cnt = 0;
-               s5p_mfc_enc_init(ctx);
-               /* Setup ctrl handler */
-               ret = s5p_mfc_enc_ctrls_setup(ctx);
-               if (ret) {
-                       mfc_err("Failed to setup mfc controls\n");
-                       goto err_ctrls_setup;
-               }
-       } else {
-               ret = -ENOENT;
-               goto err_bad_node;
-       }
-       ctx->fh.ctrl_handler = &ctx->ctrl_handler;
-       ctx->inst_no = MFC_NO_INSTANCE_SET;
-       /* Load firmware if this is the first instance */
-       if (dev->num_inst == 1) {
-               dev->watchdog_timer.expires = jiffies +
-                                       msecs_to_jiffies(MFC_WATCHDOG_INTERVAL);
-               add_timer(&dev->watchdog_timer);
-               ret = s5p_mfc_power_on();
-               if (ret < 0) {
-                       mfc_err("power on failed\n");
-                       goto err_pwr_enable;
-               }
-               s5p_mfc_clock_on();
-               ret = s5p_mfc_load_firmware(dev);
-               if (ret) {
-                       s5p_mfc_clock_off();
-                       goto err_load_fw;
-               }
-               /* Init the FW */
-               ret = s5p_mfc_init_hw(dev);
-               s5p_mfc_clock_off();
-               if (ret)
-                       goto err_init_hw;
-       }
-       /* Init videobuf2 queue for CAPTURE */
-       q = &ctx->vq_dst;
-       q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
-       q->drv_priv = &ctx->fh;
-       q->lock = &dev->mfc_mutex;
-       if (vdev == dev->vfd_dec) {
-               q->io_modes = VB2_MMAP;
-               q->ops = get_dec_queue_ops();
-       } else if (vdev == dev->vfd_enc) {
-               q->io_modes = VB2_MMAP | VB2_USERPTR;
-               q->ops = get_enc_queue_ops();
-       } else {
-               ret = -ENOENT;
-               goto err_queue_init;
-       }
-       /*
-        * We'll do mostly sequential access, so sacrifice TLB efficiency for
-        * faster allocation.
-        */
-       q->dma_attrs = DMA_ATTR_ALLOC_SINGLE_PAGES;
-       q->mem_ops = &vb2_dma_contig_memops;
-       q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
-       ret = vb2_queue_init(q);
-       if (ret) {
-               mfc_err("Failed to initialize videobuf2 queue(capture)\n");
-               goto err_queue_init;
-       }
-       /* Init videobuf2 queue for OUTPUT */
-       q = &ctx->vq_src;
-       q->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
-       q->drv_priv = &ctx->fh;
-       q->lock = &dev->mfc_mutex;
-       if (vdev == dev->vfd_dec) {
-               q->io_modes = VB2_MMAP;
-               q->ops = get_dec_queue_ops();
-       } else if (vdev == dev->vfd_enc) {
-               q->io_modes = VB2_MMAP | VB2_USERPTR;
-               q->ops = get_enc_queue_ops();
-       } else {
-               ret = -ENOENT;
-               goto err_queue_init;
-       }
-       /* One way to indicate end-of-stream for MFC is to set the
-        * bytesused == 0. However by default videobuf2 handles bytesused
-        * equal to 0 as a special case and changes its value to the size
-        * of the buffer. Set the allow_zero_bytesused flag so that videobuf2
-        * will keep the value of bytesused intact.
-        */
-       q->allow_zero_bytesused = 1;
-
-       /*
-        * We'll do mostly sequential access, so sacrifice TLB efficiency for
-        * faster allocation.
-        */
-       q->dma_attrs = DMA_ATTR_ALLOC_SINGLE_PAGES;
-       q->mem_ops = &vb2_dma_contig_memops;
-       q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
-       ret = vb2_queue_init(q);
-       if (ret) {
-               mfc_err("Failed to initialize videobuf2 queue(output)\n");
-               goto err_queue_init;
-       }
-       mutex_unlock(&dev->mfc_mutex);
-       mfc_debug_leave();
-       return ret;
-       /* Deinit when failure occurred */
-err_queue_init:
-       if (dev->num_inst == 1)
-               s5p_mfc_deinit_hw(dev);
-err_init_hw:
-err_load_fw:
-err_pwr_enable:
-       if (dev->num_inst == 1) {
-               if (s5p_mfc_power_off() < 0)
-                       mfc_err("power off failed\n");
-               del_timer_sync(&dev->watchdog_timer);
-       }
-err_ctrls_setup:
-       s5p_mfc_dec_ctrls_delete(ctx);
-err_bad_node:
-       dev->ctx[ctx->num] = NULL;
-err_no_ctx:
-       v4l2_fh_del(&ctx->fh);
-       v4l2_fh_exit(&ctx->fh);
-       kfree(ctx);
-err_alloc:
-       dev->num_inst--;
-       mutex_unlock(&dev->mfc_mutex);
-       mfc_debug_leave();
-       return ret;
-}
-
-/* Release MFC context */
-static int s5p_mfc_release(struct file *file)
-{
-       struct s5p_mfc_ctx *ctx = fh_to_ctx(file->private_data);
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       /* if dev is null, do cleanup that doesn't need dev */
-       mfc_debug_enter();
-       if (dev)
-               mutex_lock(&dev->mfc_mutex);
-       vb2_queue_release(&ctx->vq_src);
-       vb2_queue_release(&ctx->vq_dst);
-       if (dev) {
-               s5p_mfc_clock_on();
-
-               /* Mark context as idle */
-               clear_work_bit_irqsave(ctx);
-               /*
-                * If instance was initialised and not yet freed,
-                * return instance and free resources
-               */
-               if (ctx->state != MFCINST_FREE && ctx->state != MFCINST_INIT) {
-                       mfc_debug(2, "Has to free instance\n");
-                       s5p_mfc_close_mfc_inst(dev, ctx);
-               }
-               /* hardware locking scheme */
-               if (dev->curr_ctx == ctx->num)
-                       clear_bit(0, &dev->hw_lock);
-               dev->num_inst--;
-               if (dev->num_inst == 0) {
-                       mfc_debug(2, "Last instance\n");
-                       s5p_mfc_deinit_hw(dev);
-                       del_timer_sync(&dev->watchdog_timer);
-                       s5p_mfc_clock_off();
-                       if (s5p_mfc_power_off() < 0)
-                               mfc_err("Power off failed\n");
-               } else {
-                       mfc_debug(2, "Shutting down clock\n");
-                       s5p_mfc_clock_off();
-               }
-       }
-       if (dev)
-               dev->ctx[ctx->num] = NULL;
-       s5p_mfc_dec_ctrls_delete(ctx);
-       v4l2_fh_del(&ctx->fh);
-       /* vdev is gone if dev is null */
-       if (dev)
-               v4l2_fh_exit(&ctx->fh);
-       kfree(ctx);
-       mfc_debug_leave();
-       if (dev)
-               mutex_unlock(&dev->mfc_mutex);
-
-       return 0;
-}
-
-/* Poll */
-static __poll_t s5p_mfc_poll(struct file *file,
-                                struct poll_table_struct *wait)
-{
-       struct s5p_mfc_ctx *ctx = fh_to_ctx(file->private_data);
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct vb2_queue *src_q, *dst_q;
-       struct vb2_buffer *src_vb = NULL, *dst_vb = NULL;
-       __poll_t rc = 0;
-       unsigned long flags;
-
-       mutex_lock(&dev->mfc_mutex);
-       src_q = &ctx->vq_src;
-       dst_q = &ctx->vq_dst;
-       /*
-        * There has to be at least one buffer queued on each queued_list, which
-        * means either in driver already or waiting for driver to claim it
-        * and start processing.
-        */
-       if ((!src_q->streaming || list_empty(&src_q->queued_list))
-               && (!dst_q->streaming || list_empty(&dst_q->queued_list))) {
-               rc = EPOLLERR;
-               goto end;
-       }
-       mutex_unlock(&dev->mfc_mutex);
-       poll_wait(file, &ctx->fh.wait, wait);
-       poll_wait(file, &src_q->done_wq, wait);
-       poll_wait(file, &dst_q->done_wq, wait);
-       mutex_lock(&dev->mfc_mutex);
-       if (v4l2_event_pending(&ctx->fh))
-               rc |= EPOLLPRI;
-       spin_lock_irqsave(&src_q->done_lock, flags);
-       if (!list_empty(&src_q->done_list))
-               src_vb = list_first_entry(&src_q->done_list, struct vb2_buffer,
-                                                               done_entry);
-       if (src_vb && (src_vb->state == VB2_BUF_STATE_DONE
-                               || src_vb->state == VB2_BUF_STATE_ERROR))
-               rc |= EPOLLOUT | EPOLLWRNORM;
-       spin_unlock_irqrestore(&src_q->done_lock, flags);
-       spin_lock_irqsave(&dst_q->done_lock, flags);
-       if (!list_empty(&dst_q->done_list))
-               dst_vb = list_first_entry(&dst_q->done_list, struct vb2_buffer,
-                                                               done_entry);
-       if (dst_vb && (dst_vb->state == VB2_BUF_STATE_DONE
-                               || dst_vb->state == VB2_BUF_STATE_ERROR))
-               rc |= EPOLLIN | EPOLLRDNORM;
-       spin_unlock_irqrestore(&dst_q->done_lock, flags);
-end:
-       mutex_unlock(&dev->mfc_mutex);
-       return rc;
-}
-
-/* Mmap */
-static int s5p_mfc_mmap(struct file *file, struct vm_area_struct *vma)
-{
-       struct s5p_mfc_ctx *ctx = fh_to_ctx(file->private_data);
-       unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
-       int ret;
-
-       if (offset < DST_QUEUE_OFF_BASE) {
-               mfc_debug(2, "mmaping source\n");
-               ret = vb2_mmap(&ctx->vq_src, vma);
-       } else {                /* capture */
-               mfc_debug(2, "mmaping destination\n");
-               vma->vm_pgoff -= (DST_QUEUE_OFF_BASE >> PAGE_SHIFT);
-               ret = vb2_mmap(&ctx->vq_dst, vma);
-       }
-       return ret;
-}
-
-/* v4l2 ops */
-static const struct v4l2_file_operations s5p_mfc_fops = {
-       .owner = THIS_MODULE,
-       .open = s5p_mfc_open,
-       .release = s5p_mfc_release,
-       .poll = s5p_mfc_poll,
-       .unlocked_ioctl = video_ioctl2,
-       .mmap = s5p_mfc_mmap,
-};
-
-/* DMA memory related helper functions */
-static void s5p_mfc_memdev_release(struct device *dev)
-{
-       of_reserved_mem_device_release(dev);
-}
-
-static struct device *s5p_mfc_alloc_memdev(struct device *dev,
-                                          const char *name, unsigned int idx)
-{
-       struct device *child;
-       int ret;
-
-       child = devm_kzalloc(dev, sizeof(*child), GFP_KERNEL);
-       if (!child)
-               return NULL;
-
-       device_initialize(child);
-       dev_set_name(child, "%s:%s", dev_name(dev), name);
-       child->parent = dev;
-       child->coherent_dma_mask = dev->coherent_dma_mask;
-       child->dma_mask = dev->dma_mask;
-       child->release = s5p_mfc_memdev_release;
-       child->dma_parms = devm_kzalloc(dev, sizeof(*child->dma_parms),
-                                       GFP_KERNEL);
-       if (!child->dma_parms)
-               goto err;
-
-       /*
-        * The memdevs are not proper OF platform devices, so in order for them
-        * to be treated as valid DMA masters we need a bit of a hack to force
-        * them to inherit the MFC node's DMA configuration.
-        */
-       of_dma_configure(child, dev->of_node, true);
-
-       if (device_add(child) == 0) {
-               ret = of_reserved_mem_device_init_by_idx(child, dev->of_node,
-                                                        idx);
-               if (ret == 0)
-                       return child;
-               device_del(child);
-       }
-err:
-       put_device(child);
-       return NULL;
-}
-
-static int s5p_mfc_configure_2port_memory(struct s5p_mfc_dev *mfc_dev)
-{
-       struct device *dev = &mfc_dev->plat_dev->dev;
-       void *bank2_virt;
-       dma_addr_t bank2_dma_addr;
-       unsigned long align_size = 1 << MFC_BASE_ALIGN_ORDER;
-       int ret;
-
-       /*
-        * Create and initialize virtual devices for accessing
-        * reserved memory regions.
-        */
-       mfc_dev->mem_dev[BANK_L_CTX] = s5p_mfc_alloc_memdev(dev, "left",
-                                                          BANK_L_CTX);
-       if (!mfc_dev->mem_dev[BANK_L_CTX])
-               return -ENODEV;
-       mfc_dev->mem_dev[BANK_R_CTX] = s5p_mfc_alloc_memdev(dev, "right",
-                                                          BANK_R_CTX);
-       if (!mfc_dev->mem_dev[BANK_R_CTX]) {
-               device_unregister(mfc_dev->mem_dev[BANK_L_CTX]);
-               return -ENODEV;
-       }
-
-       /* Allocate memory for firmware and initialize both banks addresses */
-       ret = s5p_mfc_alloc_firmware(mfc_dev);
-       if (ret) {
-               device_unregister(mfc_dev->mem_dev[BANK_R_CTX]);
-               device_unregister(mfc_dev->mem_dev[BANK_L_CTX]);
-               return ret;
-       }
-
-       mfc_dev->dma_base[BANK_L_CTX] = mfc_dev->fw_buf.dma;
-
-       bank2_virt = dma_alloc_coherent(mfc_dev->mem_dev[BANK_R_CTX],
-                                      align_size, &bank2_dma_addr, GFP_KERNEL);
-       if (!bank2_virt) {
-               mfc_err("Allocating bank2 base failed\n");
-               s5p_mfc_release_firmware(mfc_dev);
-               device_unregister(mfc_dev->mem_dev[BANK_R_CTX]);
-               device_unregister(mfc_dev->mem_dev[BANK_L_CTX]);
-               return -ENOMEM;
-       }
-
-       /* Valid buffers passed to MFC encoder with LAST_FRAME command
-        * should not have address of bank2 - MFC will treat it as a null frame.
-        * To avoid such situation we set bank2 address below the pool address.
-        */
-       mfc_dev->dma_base[BANK_R_CTX] = bank2_dma_addr - align_size;
-
-       dma_free_coherent(mfc_dev->mem_dev[BANK_R_CTX], align_size, bank2_virt,
-                         bank2_dma_addr);
-
-       vb2_dma_contig_set_max_seg_size(mfc_dev->mem_dev[BANK_L_CTX],
-                                       DMA_BIT_MASK(32));
-       vb2_dma_contig_set_max_seg_size(mfc_dev->mem_dev[BANK_R_CTX],
-                                       DMA_BIT_MASK(32));
-
-       return 0;
-}
-
-static void s5p_mfc_unconfigure_2port_memory(struct s5p_mfc_dev *mfc_dev)
-{
-       device_unregister(mfc_dev->mem_dev[BANK_L_CTX]);
-       device_unregister(mfc_dev->mem_dev[BANK_R_CTX]);
-       vb2_dma_contig_clear_max_seg_size(mfc_dev->mem_dev[BANK_L_CTX]);
-       vb2_dma_contig_clear_max_seg_size(mfc_dev->mem_dev[BANK_R_CTX]);
-}
-
-static int s5p_mfc_configure_common_memory(struct s5p_mfc_dev *mfc_dev)
-{
-       struct device *dev = &mfc_dev->plat_dev->dev;
-       unsigned long mem_size = SZ_4M;
-
-       if (IS_ENABLED(CONFIG_DMA_CMA) || exynos_is_iommu_available(dev))
-               mem_size = SZ_8M;
-
-       if (mfc_mem_size)
-               mem_size = memparse(mfc_mem_size, NULL);
-
-       mfc_dev->mem_bitmap = bitmap_zalloc(mem_size >> PAGE_SHIFT, GFP_KERNEL);
-       if (!mfc_dev->mem_bitmap)
-               return -ENOMEM;
-
-       mfc_dev->mem_virt = dma_alloc_coherent(dev, mem_size,
-                                              &mfc_dev->mem_base, GFP_KERNEL);
-       if (!mfc_dev->mem_virt) {
-               bitmap_free(mfc_dev->mem_bitmap);
-               dev_err(dev, "failed to preallocate %ld MiB for the firmware and context buffers\n",
-                       (mem_size / SZ_1M));
-               return -ENOMEM;
-       }
-       mfc_dev->mem_size = mem_size;
-       mfc_dev->dma_base[BANK_L_CTX] = mfc_dev->mem_base;
-       mfc_dev->dma_base[BANK_R_CTX] = mfc_dev->mem_base;
-
-       /*
-        * MFC hardware cannot handle 0 as a base address, so mark first 128K
-        * as used (to keep required base alignment) and adjust base address
-        */
-       if (mfc_dev->mem_base == (dma_addr_t)0) {
-               unsigned int offset = 1 << MFC_BASE_ALIGN_ORDER;
-
-               bitmap_set(mfc_dev->mem_bitmap, 0, offset >> PAGE_SHIFT);
-               mfc_dev->dma_base[BANK_L_CTX] += offset;
-               mfc_dev->dma_base[BANK_R_CTX] += offset;
-       }
-
-       /* Firmware allocation cannot fail in this case */
-       s5p_mfc_alloc_firmware(mfc_dev);
-
-       mfc_dev->mem_dev[BANK_L_CTX] = mfc_dev->mem_dev[BANK_R_CTX] = dev;
-       vb2_dma_contig_set_max_seg_size(dev, DMA_BIT_MASK(32));
-
-       dev_info(dev, "preallocated %ld MiB buffer for the firmware and context buffers\n",
-                (mem_size / SZ_1M));
-
-       return 0;
-}
-
-static void s5p_mfc_unconfigure_common_memory(struct s5p_mfc_dev *mfc_dev)
-{
-       struct device *dev = &mfc_dev->plat_dev->dev;
-
-       dma_free_coherent(dev, mfc_dev->mem_size, mfc_dev->mem_virt,
-                         mfc_dev->mem_base);
-       bitmap_free(mfc_dev->mem_bitmap);
-       vb2_dma_contig_clear_max_seg_size(dev);
-}
-
-static int s5p_mfc_configure_dma_memory(struct s5p_mfc_dev *mfc_dev)
-{
-       struct device *dev = &mfc_dev->plat_dev->dev;
-
-       if (exynos_is_iommu_available(dev) || !IS_TWOPORT(mfc_dev))
-               return s5p_mfc_configure_common_memory(mfc_dev);
-       else
-               return s5p_mfc_configure_2port_memory(mfc_dev);
-}
-
-static void s5p_mfc_unconfigure_dma_memory(struct s5p_mfc_dev *mfc_dev)
-{
-       struct device *dev = &mfc_dev->plat_dev->dev;
-
-       s5p_mfc_release_firmware(mfc_dev);
-       if (exynos_is_iommu_available(dev) || !IS_TWOPORT(mfc_dev))
-               s5p_mfc_unconfigure_common_memory(mfc_dev);
-       else
-               s5p_mfc_unconfigure_2port_memory(mfc_dev);
-}
-
-/* MFC probe function */
-static int s5p_mfc_probe(struct platform_device *pdev)
-{
-       struct s5p_mfc_dev *dev;
-       struct video_device *vfd;
-       int ret;
-
-       pr_debug("%s++\n", __func__);
-       dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
-       if (!dev)
-               return -ENOMEM;
-
-       spin_lock_init(&dev->irqlock);
-       spin_lock_init(&dev->condlock);
-       dev->plat_dev = pdev;
-       if (!dev->plat_dev) {
-               mfc_err("No platform data specified\n");
-               return -ENODEV;
-       }
-
-       dev->variant = of_device_get_match_data(&pdev->dev);
-       if (!dev->variant) {
-               dev_err(&pdev->dev, "Failed to get device MFC hardware variant information\n");
-               return -ENOENT;
-       }
-
-       dev->regs_base = devm_platform_ioremap_resource(pdev, 0);
-       if (IS_ERR(dev->regs_base))
-               return PTR_ERR(dev->regs_base);
-
-       ret = platform_get_irq(pdev, 0);
-       if (ret < 0)
-               return ret;
-       dev->irq = ret;
-       ret = devm_request_irq(&pdev->dev, dev->irq, s5p_mfc_irq,
-                                       0, pdev->name, dev);
-       if (ret) {
-               dev_err(&pdev->dev, "Failed to install irq (%d)\n", ret);
-               return ret;
-       }
-
-       ret = s5p_mfc_configure_dma_memory(dev);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "failed to configure DMA memory\n");
-               return ret;
-       }
-
-       ret = s5p_mfc_init_pm(dev);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "failed to get mfc clock source\n");
-               goto err_dma;
-       }
-
-       /*
-        * Load fails if fs isn't mounted. Try loading anyway.
-        * _open() will load it, it it fails now. Ignore failure.
-        */
-       s5p_mfc_load_firmware(dev);
-
-       mutex_init(&dev->mfc_mutex);
-       init_waitqueue_head(&dev->queue);
-       dev->hw_lock = 0;
-       INIT_WORK(&dev->watchdog_work, s5p_mfc_watchdog_worker);
-       atomic_set(&dev->watchdog_cnt, 0);
-       timer_setup(&dev->watchdog_timer, s5p_mfc_watchdog, 0);
-
-       ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
-       if (ret)
-               goto err_v4l2_dev_reg;
-
-       /* decoder */
-       vfd = video_device_alloc();
-       if (!vfd) {
-               v4l2_err(&dev->v4l2_dev, "Failed to allocate video device\n");
-               ret = -ENOMEM;
-               goto err_dec_alloc;
-       }
-       vfd->fops       = &s5p_mfc_fops;
-       vfd->ioctl_ops  = get_dec_v4l2_ioctl_ops();
-       vfd->release    = video_device_release;
-       vfd->lock       = &dev->mfc_mutex;
-       vfd->v4l2_dev   = &dev->v4l2_dev;
-       vfd->vfl_dir    = VFL_DIR_M2M;
-       vfd->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
-       set_bit(V4L2_FL_QUIRK_INVERTED_CROP, &vfd->flags);
-       snprintf(vfd->name, sizeof(vfd->name), "%s", S5P_MFC_DEC_NAME);
-       dev->vfd_dec    = vfd;
-       video_set_drvdata(vfd, dev);
-
-       /* encoder */
-       vfd = video_device_alloc();
-       if (!vfd) {
-               v4l2_err(&dev->v4l2_dev, "Failed to allocate video device\n");
-               ret = -ENOMEM;
-               goto err_enc_alloc;
-       }
-       vfd->fops       = &s5p_mfc_fops;
-       vfd->ioctl_ops  = get_enc_v4l2_ioctl_ops();
-       vfd->release    = video_device_release;
-       vfd->lock       = &dev->mfc_mutex;
-       vfd->v4l2_dev   = &dev->v4l2_dev;
-       vfd->vfl_dir    = VFL_DIR_M2M;
-       vfd->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
-       snprintf(vfd->name, sizeof(vfd->name), "%s", S5P_MFC_ENC_NAME);
-       dev->vfd_enc    = vfd;
-       video_set_drvdata(vfd, dev);
-       platform_set_drvdata(pdev, dev);
-
-       /* Initialize HW ops and commands based on MFC version */
-       s5p_mfc_init_hw_ops(dev);
-       s5p_mfc_init_hw_cmds(dev);
-       s5p_mfc_init_regs(dev);
-
-       /* Register decoder and encoder */
-       ret = video_register_device(dev->vfd_dec, VFL_TYPE_VIDEO, 0);
-       if (ret) {
-               v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
-               goto err_dec_reg;
-       }
-       v4l2_info(&dev->v4l2_dev,
-                 "decoder registered as /dev/video%d\n", dev->vfd_dec->num);
-
-       ret = video_register_device(dev->vfd_enc, VFL_TYPE_VIDEO, 0);
-       if (ret) {
-               v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
-               goto err_enc_reg;
-       }
-       v4l2_info(&dev->v4l2_dev,
-                 "encoder registered as /dev/video%d\n", dev->vfd_enc->num);
-
-       pr_debug("%s--\n", __func__);
-       return 0;
-
-/* Deinit MFC if probe had failed */
-err_enc_reg:
-       video_unregister_device(dev->vfd_dec);
-err_dec_reg:
-       video_device_release(dev->vfd_enc);
-err_enc_alloc:
-       video_device_release(dev->vfd_dec);
-err_dec_alloc:
-       v4l2_device_unregister(&dev->v4l2_dev);
-err_v4l2_dev_reg:
-       s5p_mfc_final_pm(dev);
-err_dma:
-       s5p_mfc_unconfigure_dma_memory(dev);
-
-       pr_debug("%s-- with error\n", __func__);
-       return ret;
-
-}
-
-/* Remove the driver */
-static int s5p_mfc_remove(struct platform_device *pdev)
-{
-       struct s5p_mfc_dev *dev = platform_get_drvdata(pdev);
-       struct s5p_mfc_ctx *ctx;
-       int i;
-
-       v4l2_info(&dev->v4l2_dev, "Removing %s\n", pdev->name);
-
-       /*
-        * Clear ctx dev pointer to avoid races between s5p_mfc_remove()
-        * and s5p_mfc_release() and s5p_mfc_release() accessing ctx->dev
-        * after s5p_mfc_remove() is run during unbind.
-       */
-       mutex_lock(&dev->mfc_mutex);
-       for (i = 0; i < MFC_NUM_CONTEXTS; i++) {
-               ctx = dev->ctx[i];
-               if (!ctx)
-                       continue;
-               /* clear ctx->dev */
-               ctx->dev = NULL;
-       }
-       mutex_unlock(&dev->mfc_mutex);
-
-       del_timer_sync(&dev->watchdog_timer);
-       flush_work(&dev->watchdog_work);
-
-       video_unregister_device(dev->vfd_enc);
-       video_unregister_device(dev->vfd_dec);
-       video_device_release(dev->vfd_enc);
-       video_device_release(dev->vfd_dec);
-       v4l2_device_unregister(&dev->v4l2_dev);
-       s5p_mfc_unconfigure_dma_memory(dev);
-
-       s5p_mfc_final_pm(dev);
-       return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-
-static int s5p_mfc_suspend(struct device *dev)
-{
-       struct s5p_mfc_dev *m_dev = dev_get_drvdata(dev);
-       int ret;
-
-       if (m_dev->num_inst == 0)
-               return 0;
-
-       if (test_and_set_bit(0, &m_dev->enter_suspend) != 0) {
-               mfc_err("Error: going to suspend for a second time\n");
-               return -EIO;
-       }
-
-       /* Check if we're processing then wait if it necessary. */
-       while (test_and_set_bit(0, &m_dev->hw_lock) != 0) {
-               /* Try and lock the HW */
-               /* Wait on the interrupt waitqueue */
-               ret = wait_event_interruptible_timeout(m_dev->queue,
-                       m_dev->int_cond, msecs_to_jiffies(MFC_INT_TIMEOUT));
-               if (ret == 0) {
-                       mfc_err("Waiting for hardware to finish timed out\n");
-                       clear_bit(0, &m_dev->enter_suspend);
-                       return -EIO;
-               }
-       }
-
-       ret = s5p_mfc_sleep(m_dev);
-       if (ret) {
-               clear_bit(0, &m_dev->enter_suspend);
-               clear_bit(0, &m_dev->hw_lock);
-       }
-       return ret;
-}
-
-static int s5p_mfc_resume(struct device *dev)
-{
-       struct s5p_mfc_dev *m_dev = dev_get_drvdata(dev);
-
-       if (m_dev->num_inst == 0)
-               return 0;
-       return s5p_mfc_wakeup(m_dev);
-}
-#endif
-
-/* Power management */
-static const struct dev_pm_ops s5p_mfc_pm_ops = {
-       SET_SYSTEM_SLEEP_PM_OPS(s5p_mfc_suspend, s5p_mfc_resume)
-};
-
-static struct s5p_mfc_buf_size_v5 mfc_buf_size_v5 = {
-       .h264_ctx       = MFC_H264_CTX_BUF_SIZE,
-       .non_h264_ctx   = MFC_CTX_BUF_SIZE,
-       .dsc            = DESC_BUF_SIZE,
-       .shm            = SHARED_BUF_SIZE,
-};
-
-static struct s5p_mfc_buf_size buf_size_v5 = {
-       .fw     = MAX_FW_SIZE,
-       .cpb    = MAX_CPB_SIZE,
-       .priv   = &mfc_buf_size_v5,
-};
-
-static struct s5p_mfc_variant mfc_drvdata_v5 = {
-       .version        = MFC_VERSION,
-       .version_bit    = MFC_V5_BIT,
-       .port_num       = MFC_NUM_PORTS,
-       .buf_size       = &buf_size_v5,
-       .fw_name[0]     = "s5p-mfc.fw",
-       .clk_names      = {"mfc", "sclk_mfc"},
-       .num_clocks     = 2,
-       .use_clock_gating = true,
-};
-
-static struct s5p_mfc_buf_size_v6 mfc_buf_size_v6 = {
-       .dev_ctx        = MFC_CTX_BUF_SIZE_V6,
-       .h264_dec_ctx   = MFC_H264_DEC_CTX_BUF_SIZE_V6,
-       .other_dec_ctx  = MFC_OTHER_DEC_CTX_BUF_SIZE_V6,
-       .h264_enc_ctx   = MFC_H264_ENC_CTX_BUF_SIZE_V6,
-       .other_enc_ctx  = MFC_OTHER_ENC_CTX_BUF_SIZE_V6,
-};
-
-static struct s5p_mfc_buf_size buf_size_v6 = {
-       .fw     = MAX_FW_SIZE_V6,
-       .cpb    = MAX_CPB_SIZE_V6,
-       .priv   = &mfc_buf_size_v6,
-};
-
-static struct s5p_mfc_variant mfc_drvdata_v6 = {
-       .version        = MFC_VERSION_V6,
-       .version_bit    = MFC_V6_BIT,
-       .port_num       = MFC_NUM_PORTS_V6,
-       .buf_size       = &buf_size_v6,
-       .fw_name[0]     = "s5p-mfc-v6.fw",
-       /*
-        * v6-v2 firmware contains bug fixes and interface change
-        * for init buffer command
-        */
-       .fw_name[1]     = "s5p-mfc-v6-v2.fw",
-       .clk_names      = {"mfc"},
-       .num_clocks     = 1,
-};
-
-static struct s5p_mfc_buf_size_v6 mfc_buf_size_v7 = {
-       .dev_ctx        = MFC_CTX_BUF_SIZE_V7,
-       .h264_dec_ctx   = MFC_H264_DEC_CTX_BUF_SIZE_V7,
-       .other_dec_ctx  = MFC_OTHER_DEC_CTX_BUF_SIZE_V7,
-       .h264_enc_ctx   = MFC_H264_ENC_CTX_BUF_SIZE_V7,
-       .other_enc_ctx  = MFC_OTHER_ENC_CTX_BUF_SIZE_V7,
-};
-
-static struct s5p_mfc_buf_size buf_size_v7 = {
-       .fw     = MAX_FW_SIZE_V7,
-       .cpb    = MAX_CPB_SIZE_V7,
-       .priv   = &mfc_buf_size_v7,
-};
-
-static struct s5p_mfc_variant mfc_drvdata_v7 = {
-       .version        = MFC_VERSION_V7,
-       .version_bit    = MFC_V7_BIT,
-       .port_num       = MFC_NUM_PORTS_V7,
-       .buf_size       = &buf_size_v7,
-       .fw_name[0]     = "s5p-mfc-v7.fw",
-       .clk_names      = {"mfc", "sclk_mfc"},
-       .num_clocks     = 2,
-};
-
-static struct s5p_mfc_buf_size_v6 mfc_buf_size_v8 = {
-       .dev_ctx        = MFC_CTX_BUF_SIZE_V8,
-       .h264_dec_ctx   = MFC_H264_DEC_CTX_BUF_SIZE_V8,
-       .other_dec_ctx  = MFC_OTHER_DEC_CTX_BUF_SIZE_V8,
-       .h264_enc_ctx   = MFC_H264_ENC_CTX_BUF_SIZE_V8,
-       .other_enc_ctx  = MFC_OTHER_ENC_CTX_BUF_SIZE_V8,
-};
-
-static struct s5p_mfc_buf_size buf_size_v8 = {
-       .fw     = MAX_FW_SIZE_V8,
-       .cpb    = MAX_CPB_SIZE_V8,
-       .priv   = &mfc_buf_size_v8,
-};
-
-static struct s5p_mfc_variant mfc_drvdata_v8 = {
-       .version        = MFC_VERSION_V8,
-       .version_bit    = MFC_V8_BIT,
-       .port_num       = MFC_NUM_PORTS_V8,
-       .buf_size       = &buf_size_v8,
-       .fw_name[0]     = "s5p-mfc-v8.fw",
-       .clk_names      = {"mfc"},
-       .num_clocks     = 1,
-};
-
-static struct s5p_mfc_variant mfc_drvdata_v8_5433 = {
-       .version        = MFC_VERSION_V8,
-       .version_bit    = MFC_V8_BIT,
-       .port_num       = MFC_NUM_PORTS_V8,
-       .buf_size       = &buf_size_v8,
-       .fw_name[0]     = "s5p-mfc-v8.fw",
-       .clk_names      = {"pclk", "aclk", "aclk_xiu"},
-       .num_clocks     = 3,
-};
-
-static struct s5p_mfc_buf_size_v6 mfc_buf_size_v10 = {
-       .dev_ctx        = MFC_CTX_BUF_SIZE_V10,
-       .h264_dec_ctx   = MFC_H264_DEC_CTX_BUF_SIZE_V10,
-       .other_dec_ctx  = MFC_OTHER_DEC_CTX_BUF_SIZE_V10,
-       .h264_enc_ctx   = MFC_H264_ENC_CTX_BUF_SIZE_V10,
-       .hevc_enc_ctx   = MFC_HEVC_ENC_CTX_BUF_SIZE_V10,
-       .other_enc_ctx  = MFC_OTHER_ENC_CTX_BUF_SIZE_V10,
-};
-
-static struct s5p_mfc_buf_size buf_size_v10 = {
-       .fw     = MAX_FW_SIZE_V10,
-       .cpb    = MAX_CPB_SIZE_V10,
-       .priv   = &mfc_buf_size_v10,
-};
-
-static struct s5p_mfc_variant mfc_drvdata_v10 = {
-       .version        = MFC_VERSION_V10,
-       .version_bit    = MFC_V10_BIT,
-       .port_num       = MFC_NUM_PORTS_V10,
-       .buf_size       = &buf_size_v10,
-       .fw_name[0]     = "s5p-mfc-v10.fw",
-};
-
-static const struct of_device_id exynos_mfc_match[] = {
-       {
-               .compatible = "samsung,mfc-v5",
-               .data = &mfc_drvdata_v5,
-       }, {
-               .compatible = "samsung,mfc-v6",
-               .data = &mfc_drvdata_v6,
-       }, {
-               .compatible = "samsung,mfc-v7",
-               .data = &mfc_drvdata_v7,
-       }, {
-               .compatible = "samsung,mfc-v8",
-               .data = &mfc_drvdata_v8,
-       }, {
-               .compatible = "samsung,exynos5433-mfc",
-               .data = &mfc_drvdata_v8_5433,
-       }, {
-               .compatible = "samsung,mfc-v10",
-               .data = &mfc_drvdata_v10,
-       },
-       {},
-};
-MODULE_DEVICE_TABLE(of, exynos_mfc_match);
-
-static struct platform_driver s5p_mfc_driver = {
-       .probe          = s5p_mfc_probe,
-       .remove         = s5p_mfc_remove,
-       .driver = {
-               .name   = S5P_MFC_NAME,
-               .pm     = &s5p_mfc_pm_ops,
-               .of_match_table = exynos_mfc_match,
-       },
-};
-
-module_platform_driver(s5p_mfc_driver);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Kamil Debski <k.debski@samsung.com>");
-MODULE_DESCRIPTION("Samsung S5P Multi Format Codec V4L2 driver");
-
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c
deleted file mode 100644 (file)
index 0e88c28..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * linux/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c
- *
- * Copyright (C) 2012 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- */
-
-#include "s5p_mfc_cmd.h"
-#include "s5p_mfc_common.h"
-#include "s5p_mfc_debug.h"
-#include "s5p_mfc_cmd_v5.h"
-#include "s5p_mfc_cmd_v6.h"
-
-static struct s5p_mfc_hw_cmds *s5p_mfc_cmds;
-
-void s5p_mfc_init_hw_cmds(struct s5p_mfc_dev *dev)
-{
-       if (IS_MFCV6_PLUS(dev))
-               s5p_mfc_cmds = s5p_mfc_init_hw_cmds_v6();
-       else
-               s5p_mfc_cmds = s5p_mfc_init_hw_cmds_v5();
-
-       dev->mfc_cmds = s5p_mfc_cmds;
-}
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.h b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.h
deleted file mode 100644 (file)
index ed4e32a..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * linux/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.h
- *
- * Copyright (C) 2012 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- */
-
-#ifndef S5P_MFC_CMD_H_
-#define S5P_MFC_CMD_H_
-
-#include "s5p_mfc_common.h"
-
-#define MAX_H2R_ARG    4
-
-struct s5p_mfc_cmd_args {
-       unsigned int    arg[MAX_H2R_ARG];
-};
-
-struct s5p_mfc_hw_cmds {
-       int (*cmd_host2risc)(struct s5p_mfc_dev *dev, int cmd,
-                               struct s5p_mfc_cmd_args *args);
-       int (*sys_init_cmd)(struct s5p_mfc_dev *dev);
-       int (*sleep_cmd)(struct s5p_mfc_dev *dev);
-       int (*wakeup_cmd)(struct s5p_mfc_dev *dev);
-       int (*open_inst_cmd)(struct s5p_mfc_ctx *ctx);
-       int (*close_inst_cmd)(struct s5p_mfc_ctx *ctx);
-};
-
-void s5p_mfc_init_hw_cmds(struct s5p_mfc_dev *dev);
-#endif /* S5P_MFC_CMD_H_ */
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c
deleted file mode 100644 (file)
index 1ea4eda..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * linux/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c
- *
- * Copyright (C) 2011 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- */
-
-#include "regs-mfc.h"
-#include "s5p_mfc_cmd.h"
-#include "s5p_mfc_common.h"
-#include "s5p_mfc_debug.h"
-#include "s5p_mfc_cmd_v5.h"
-
-/* This function is used to send a command to the MFC */
-static int s5p_mfc_cmd_host2risc_v5(struct s5p_mfc_dev *dev, int cmd,
-                               struct s5p_mfc_cmd_args *args)
-{
-       int cur_cmd;
-       unsigned long timeout;
-
-       timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
-       /* wait until host to risc command register becomes 'H2R_CMD_EMPTY' */
-       do {
-               if (time_after(jiffies, timeout)) {
-                       mfc_err("Timeout while waiting for hardware\n");
-                       return -EIO;
-               }
-               cur_cmd = mfc_read(dev, S5P_FIMV_HOST2RISC_CMD);
-       } while (cur_cmd != S5P_FIMV_H2R_CMD_EMPTY);
-       mfc_write(dev, args->arg[0], S5P_FIMV_HOST2RISC_ARG1);
-       mfc_write(dev, args->arg[1], S5P_FIMV_HOST2RISC_ARG2);
-       mfc_write(dev, args->arg[2], S5P_FIMV_HOST2RISC_ARG3);
-       mfc_write(dev, args->arg[3], S5P_FIMV_HOST2RISC_ARG4);
-       /* Issue the command */
-       mfc_write(dev, cmd, S5P_FIMV_HOST2RISC_CMD);
-       return 0;
-}
-
-/* Initialize the MFC */
-static int s5p_mfc_sys_init_cmd_v5(struct s5p_mfc_dev *dev)
-{
-       struct s5p_mfc_cmd_args h2r_args;
-
-       memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
-       h2r_args.arg[0] = dev->fw_buf.size;
-       return s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_SYS_INIT,
-                       &h2r_args);
-}
-
-/* Suspend the MFC hardware */
-static int s5p_mfc_sleep_cmd_v5(struct s5p_mfc_dev *dev)
-{
-       struct s5p_mfc_cmd_args h2r_args;
-
-       memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
-       return s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_SLEEP, &h2r_args);
-}
-
-/* Wake up the MFC hardware */
-static int s5p_mfc_wakeup_cmd_v5(struct s5p_mfc_dev *dev)
-{
-       struct s5p_mfc_cmd_args h2r_args;
-
-       memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
-       return s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_WAKEUP,
-                       &h2r_args);
-}
-
-
-static int s5p_mfc_open_inst_cmd_v5(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_cmd_args h2r_args;
-       int ret;
-
-       /* Preparing decoding - getting instance number */
-       mfc_debug(2, "Getting instance number (codec: %d)\n", ctx->codec_mode);
-       dev->curr_ctx = ctx->num;
-       memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
-       switch (ctx->codec_mode) {
-       case S5P_MFC_CODEC_H264_DEC:
-               h2r_args.arg[0] = S5P_FIMV_CODEC_H264_DEC;
-               break;
-       case S5P_MFC_CODEC_VC1_DEC:
-               h2r_args.arg[0] = S5P_FIMV_CODEC_VC1_DEC;
-               break;
-       case S5P_MFC_CODEC_MPEG4_DEC:
-               h2r_args.arg[0] = S5P_FIMV_CODEC_MPEG4_DEC;
-               break;
-       case S5P_MFC_CODEC_MPEG2_DEC:
-               h2r_args.arg[0] = S5P_FIMV_CODEC_MPEG2_DEC;
-               break;
-       case S5P_MFC_CODEC_H263_DEC:
-               h2r_args.arg[0] = S5P_FIMV_CODEC_H263_DEC;
-               break;
-       case S5P_MFC_CODEC_VC1RCV_DEC:
-               h2r_args.arg[0] = S5P_FIMV_CODEC_VC1RCV_DEC;
-               break;
-       case S5P_MFC_CODEC_H264_ENC:
-               h2r_args.arg[0] = S5P_FIMV_CODEC_H264_ENC;
-               break;
-       case S5P_MFC_CODEC_MPEG4_ENC:
-               h2r_args.arg[0] = S5P_FIMV_CODEC_MPEG4_ENC;
-               break;
-       case S5P_MFC_CODEC_H263_ENC:
-               h2r_args.arg[0] = S5P_FIMV_CODEC_H263_ENC;
-               break;
-       default:
-               h2r_args.arg[0] = S5P_FIMV_CODEC_NONE;
-       }
-       h2r_args.arg[1] = 0; /* no crc & no pixelcache */
-       h2r_args.arg[2] = ctx->ctx.ofs;
-       h2r_args.arg[3] = ctx->ctx.size;
-       ret = s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_OPEN_INSTANCE,
-                                                               &h2r_args);
-       if (ret) {
-               mfc_err("Failed to create a new instance\n");
-               ctx->state = MFCINST_ERROR;
-       }
-       return ret;
-}
-
-static int s5p_mfc_close_inst_cmd_v5(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_cmd_args h2r_args;
-       int ret;
-
-       if (ctx->state == MFCINST_FREE) {
-               mfc_err("Instance already returned\n");
-               ctx->state = MFCINST_ERROR;
-               return -EINVAL;
-       }
-       /* Closing decoding instance  */
-       mfc_debug(2, "Returning instance number %d\n", ctx->inst_no);
-       dev->curr_ctx = ctx->num;
-       memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
-       h2r_args.arg[0] = ctx->inst_no;
-       ret = s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_CLOSE_INSTANCE,
-                                                               &h2r_args);
-       if (ret) {
-               mfc_err("Failed to return an instance\n");
-               ctx->state = MFCINST_ERROR;
-               return -EINVAL;
-       }
-       return 0;
-}
-
-/* Initialize cmd function pointers for MFC v5 */
-static struct s5p_mfc_hw_cmds s5p_mfc_cmds_v5 = {
-       .cmd_host2risc = s5p_mfc_cmd_host2risc_v5,
-       .sys_init_cmd = s5p_mfc_sys_init_cmd_v5,
-       .sleep_cmd = s5p_mfc_sleep_cmd_v5,
-       .wakeup_cmd = s5p_mfc_wakeup_cmd_v5,
-       .open_inst_cmd = s5p_mfc_open_inst_cmd_v5,
-       .close_inst_cmd = s5p_mfc_close_inst_cmd_v5,
-};
-
-struct s5p_mfc_hw_cmds *s5p_mfc_init_hw_cmds_v5(void)
-{
-       return &s5p_mfc_cmds_v5;
-}
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.h b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.h
deleted file mode 100644 (file)
index 917854b..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * linux/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.h
- *
- * Copyright (C) 2011 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- */
-
-#ifndef S5P_MFC_CMD_V5_H_
-#define S5P_MFC_CMD_V5_H_
-
-#include "s5p_mfc_common.h"
-
-struct s5p_mfc_hw_cmds *s5p_mfc_init_hw_cmds_v5(void);
-
-#endif /* S5P_MFC_CMD_H_ */
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c
deleted file mode 100644 (file)
index 1f42130..0000000
+++ /dev/null
@@ -1,169 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * linux/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.c
- *
- * Copyright (c) 2012 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- */
-
-#include "s5p_mfc_common.h"
-
-#include "s5p_mfc_cmd.h"
-#include "s5p_mfc_debug.h"
-#include "s5p_mfc_intr.h"
-#include "s5p_mfc_opr.h"
-#include "s5p_mfc_cmd_v6.h"
-
-static int s5p_mfc_cmd_host2risc_v6(struct s5p_mfc_dev *dev, int cmd,
-                               struct s5p_mfc_cmd_args *args)
-{
-       mfc_debug(2, "Issue the command: %d\n", cmd);
-
-       /* Reset RISC2HOST command */
-       mfc_write(dev, 0x0, S5P_FIMV_RISC2HOST_CMD_V6);
-
-       /* Issue the command */
-       mfc_write(dev, cmd, S5P_FIMV_HOST2RISC_CMD_V6);
-       mfc_write(dev, 0x1, S5P_FIMV_HOST2RISC_INT_V6);
-
-       return 0;
-}
-
-static int s5p_mfc_sys_init_cmd_v6(struct s5p_mfc_dev *dev)
-{
-       struct s5p_mfc_cmd_args h2r_args;
-       struct s5p_mfc_buf_size_v6 *buf_size = dev->variant->buf_size->priv;
-       int ret;
-
-       ret = s5p_mfc_hw_call(dev->mfc_ops, alloc_dev_context_buffer, dev);
-       if (ret)
-               return ret;
-
-       mfc_write(dev, dev->ctx_buf.dma, S5P_FIMV_CONTEXT_MEM_ADDR_V6);
-       mfc_write(dev, buf_size->dev_ctx, S5P_FIMV_CONTEXT_MEM_SIZE_V6);
-       return s5p_mfc_cmd_host2risc_v6(dev, S5P_FIMV_H2R_CMD_SYS_INIT_V6,
-                                       &h2r_args);
-}
-
-static int s5p_mfc_sleep_cmd_v6(struct s5p_mfc_dev *dev)
-{
-       struct s5p_mfc_cmd_args h2r_args;
-
-       memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
-       return s5p_mfc_cmd_host2risc_v6(dev, S5P_FIMV_H2R_CMD_SLEEP_V6,
-                       &h2r_args);
-}
-
-static int s5p_mfc_wakeup_cmd_v6(struct s5p_mfc_dev *dev)
-{
-       struct s5p_mfc_cmd_args h2r_args;
-
-       memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
-       return s5p_mfc_cmd_host2risc_v6(dev, S5P_FIMV_H2R_CMD_WAKEUP_V6,
-                                       &h2r_args);
-}
-
-/* Open a new instance and get its number */
-static int s5p_mfc_open_inst_cmd_v6(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_cmd_args h2r_args;
-       int codec_type;
-
-       mfc_debug(2, "Requested codec mode: %d\n", ctx->codec_mode);
-       dev->curr_ctx = ctx->num;
-       switch (ctx->codec_mode) {
-       case S5P_MFC_CODEC_H264_DEC:
-               codec_type = S5P_FIMV_CODEC_H264_DEC_V6;
-               break;
-       case S5P_MFC_CODEC_H264_MVC_DEC:
-               codec_type = S5P_FIMV_CODEC_H264_MVC_DEC_V6;
-               break;
-       case S5P_MFC_CODEC_VC1_DEC:
-               codec_type = S5P_FIMV_CODEC_VC1_DEC_V6;
-               break;
-       case S5P_MFC_CODEC_MPEG4_DEC:
-               codec_type = S5P_FIMV_CODEC_MPEG4_DEC_V6;
-               break;
-       case S5P_MFC_CODEC_MPEG2_DEC:
-               codec_type = S5P_FIMV_CODEC_MPEG2_DEC_V6;
-               break;
-       case S5P_MFC_CODEC_H263_DEC:
-               codec_type = S5P_FIMV_CODEC_H263_DEC_V6;
-               break;
-       case S5P_MFC_CODEC_VC1RCV_DEC:
-               codec_type = S5P_FIMV_CODEC_VC1RCV_DEC_V6;
-               break;
-       case S5P_MFC_CODEC_VP8_DEC:
-               codec_type = S5P_FIMV_CODEC_VP8_DEC_V6;
-               break;
-       case S5P_MFC_CODEC_HEVC_DEC:
-               codec_type = S5P_FIMV_CODEC_HEVC_DEC;
-               break;
-       case S5P_MFC_CODEC_VP9_DEC:
-               codec_type = S5P_FIMV_CODEC_VP9_DEC;
-               break;
-       case S5P_MFC_CODEC_H264_ENC:
-               codec_type = S5P_FIMV_CODEC_H264_ENC_V6;
-               break;
-       case S5P_MFC_CODEC_H264_MVC_ENC:
-               codec_type = S5P_FIMV_CODEC_H264_MVC_ENC_V6;
-               break;
-       case S5P_MFC_CODEC_MPEG4_ENC:
-               codec_type = S5P_FIMV_CODEC_MPEG4_ENC_V6;
-               break;
-       case S5P_MFC_CODEC_H263_ENC:
-               codec_type = S5P_FIMV_CODEC_H263_ENC_V6;
-               break;
-       case S5P_MFC_CODEC_VP8_ENC:
-               codec_type = S5P_FIMV_CODEC_VP8_ENC_V7;
-               break;
-       case S5P_MFC_CODEC_HEVC_ENC:
-               codec_type = S5P_FIMV_CODEC_HEVC_ENC;
-               break;
-       default:
-               codec_type = S5P_FIMV_CODEC_NONE_V6;
-       }
-       mfc_write(dev, codec_type, S5P_FIMV_CODEC_TYPE_V6);
-       mfc_write(dev, ctx->ctx.dma, S5P_FIMV_CONTEXT_MEM_ADDR_V6);
-       mfc_write(dev, ctx->ctx.size, S5P_FIMV_CONTEXT_MEM_SIZE_V6);
-       mfc_write(dev, 0, S5P_FIMV_D_CRC_CTRL_V6); /* no crc */
-
-       return s5p_mfc_cmd_host2risc_v6(dev, S5P_FIMV_H2R_CMD_OPEN_INSTANCE_V6,
-                                       &h2r_args);
-}
-
-/* Close instance */
-static int s5p_mfc_close_inst_cmd_v6(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_cmd_args h2r_args;
-       int ret = 0;
-
-       dev->curr_ctx = ctx->num;
-       if (ctx->state != MFCINST_FREE) {
-               mfc_write(dev, ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6);
-               ret = s5p_mfc_cmd_host2risc_v6(dev,
-                                       S5P_FIMV_H2R_CMD_CLOSE_INSTANCE_V6,
-                                       &h2r_args);
-       } else {
-               ret = -EINVAL;
-       }
-
-       return ret;
-}
-
-/* Initialize cmd function pointers for MFC v6 */
-static struct s5p_mfc_hw_cmds s5p_mfc_cmds_v6 = {
-       .cmd_host2risc = s5p_mfc_cmd_host2risc_v6,
-       .sys_init_cmd = s5p_mfc_sys_init_cmd_v6,
-       .sleep_cmd = s5p_mfc_sleep_cmd_v6,
-       .wakeup_cmd = s5p_mfc_wakeup_cmd_v6,
-       .open_inst_cmd = s5p_mfc_open_inst_cmd_v6,
-       .close_inst_cmd = s5p_mfc_close_inst_cmd_v6,
-};
-
-struct s5p_mfc_hw_cmds *s5p_mfc_init_hw_cmds_v6(void)
-{
-       return &s5p_mfc_cmds_v6;
-}
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.h b/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.h
deleted file mode 100644 (file)
index c19884e..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * linux/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v6.h
- *
- * Copyright (C) 2011 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- */
-
-#ifndef S5P_MFC_CMD_V6_H_
-#define S5P_MFC_CMD_V6_H_
-
-#include "s5p_mfc_common.h"
-
-struct s5p_mfc_hw_cmds *s5p_mfc_init_hw_cmds_v6(void);
-
-#endif /* S5P_MFC_CMD_H_ */
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
deleted file mode 100644 (file)
index 5304f42..0000000
+++ /dev/null
@@ -1,792 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Samsung S5P Multi Format Codec v 5.0
- *
- * This file contains definitions of enums and structs used by the codec
- * driver.
- *
- * Copyright (C) 2011 Samsung Electronics Co., Ltd.
- * Kamil Debski, <k.debski@samsung.com>
- */
-
-#ifndef S5P_MFC_COMMON_H_
-#define S5P_MFC_COMMON_H_
-
-#include <linux/platform_device.h>
-#include <linux/videodev2.h>
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-ioctl.h>
-#include <media/videobuf2-v4l2.h>
-#include "regs-mfc.h"
-#include "regs-mfc-v10.h"
-
-#define S5P_MFC_NAME           "s5p-mfc"
-
-/* Definitions related to MFC memory */
-
-/* Offset base used to differentiate between CAPTURE and OUTPUT
-*  while mmaping */
-#define DST_QUEUE_OFF_BASE     (1 << 30)
-
-#define BANK_L_CTX     0
-#define BANK_R_CTX     1
-#define BANK_CTX_NUM   2
-
-#define MFC_BANK1_ALIGN_ORDER  13
-#define MFC_BANK2_ALIGN_ORDER  13
-#define MFC_BASE_ALIGN_ORDER   17
-
-#define MFC_FW_MAX_VERSIONS    2
-
-#include <media/videobuf2-dma-contig.h>
-
-/* MFC definitions */
-#define MFC_MAX_EXTRA_DPB       5
-#define MFC_MAX_BUFFERS                32
-#define MFC_NUM_CONTEXTS       4
-/* Interrupt timeout */
-#define MFC_INT_TIMEOUT                2000
-/* Busy wait timeout */
-#define MFC_BW_TIMEOUT         500
-/* Watchdog interval */
-#define MFC_WATCHDOG_INTERVAL   1000
-/* After how many executions watchdog should assume lock up */
-#define MFC_WATCHDOG_CNT        10
-#define MFC_NO_INSTANCE_SET    -1
-#define MFC_ENC_CAP_PLANE_COUNT        1
-#define MFC_ENC_OUT_PLANE_COUNT        2
-#define STUFF_BYTE             4
-#define MFC_MAX_CTRLS          128
-
-#define S5P_MFC_CODEC_NONE             -1
-#define S5P_MFC_CODEC_H264_DEC         0
-#define S5P_MFC_CODEC_H264_MVC_DEC     1
-#define S5P_MFC_CODEC_VC1_DEC          2
-#define S5P_MFC_CODEC_MPEG4_DEC                3
-#define S5P_MFC_CODEC_MPEG2_DEC                4
-#define S5P_MFC_CODEC_H263_DEC         5
-#define S5P_MFC_CODEC_VC1RCV_DEC       6
-#define S5P_MFC_CODEC_VP8_DEC          7
-#define S5P_MFC_CODEC_HEVC_DEC         17
-#define S5P_MFC_CODEC_VP9_DEC          18
-
-#define S5P_MFC_CODEC_H264_ENC         20
-#define S5P_MFC_CODEC_H264_MVC_ENC     21
-#define S5P_MFC_CODEC_MPEG4_ENC                22
-#define S5P_MFC_CODEC_H263_ENC         23
-#define S5P_MFC_CODEC_VP8_ENC          24
-#define S5P_MFC_CODEC_HEVC_ENC         26
-
-#define S5P_MFC_R2H_CMD_EMPTY                  0
-#define S5P_MFC_R2H_CMD_SYS_INIT_RET           1
-#define S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET      2
-#define S5P_MFC_R2H_CMD_SEQ_DONE_RET           3
-#define S5P_MFC_R2H_CMD_INIT_BUFFERS_RET       4
-#define S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET     6
-#define S5P_MFC_R2H_CMD_SLEEP_RET              7
-#define S5P_MFC_R2H_CMD_WAKEUP_RET             8
-#define S5P_MFC_R2H_CMD_COMPLETE_SEQ_RET       9
-#define S5P_MFC_R2H_CMD_DPB_FLUSH_RET          10
-#define S5P_MFC_R2H_CMD_NAL_ABORT_RET          11
-#define S5P_MFC_R2H_CMD_FW_STATUS_RET          12
-#define S5P_MFC_R2H_CMD_FRAME_DONE_RET         13
-#define S5P_MFC_R2H_CMD_FIELD_DONE_RET         14
-#define S5P_MFC_R2H_CMD_SLICE_DONE_RET         15
-#define S5P_MFC_R2H_CMD_ENC_BUFFER_FUL_RET     16
-#define S5P_MFC_R2H_CMD_ERR_RET                        32
-
-#define MFC_MAX_CLOCKS         4
-
-#define mfc_read(dev, offset)          readl(dev->regs_base + (offset))
-#define mfc_write(dev, data, offset)   writel((data), dev->regs_base + \
-                                                               (offset))
-
-/*
- * enum s5p_mfc_fmt_type - type of the pixelformat
- */
-enum s5p_mfc_fmt_type {
-       MFC_FMT_DEC,
-       MFC_FMT_ENC,
-       MFC_FMT_RAW,
-};
-
-/*
- * enum s5p_mfc_inst_type - The type of an MFC instance.
- */
-enum s5p_mfc_inst_type {
-       MFCINST_INVALID,
-       MFCINST_DECODER,
-       MFCINST_ENCODER,
-};
-
-/*
- * enum s5p_mfc_inst_state - The state of an MFC instance.
- */
-enum s5p_mfc_inst_state {
-       MFCINST_FREE = 0,
-       MFCINST_INIT = 100,
-       MFCINST_GOT_INST,
-       MFCINST_HEAD_PARSED,
-       MFCINST_HEAD_PRODUCED,
-       MFCINST_BUFS_SET,
-       MFCINST_RUNNING,
-       MFCINST_FINISHING,
-       MFCINST_FINISHED,
-       MFCINST_RETURN_INST,
-       MFCINST_ERROR,
-       MFCINST_ABORT,
-       MFCINST_FLUSH,
-       MFCINST_RES_CHANGE_INIT,
-       MFCINST_RES_CHANGE_FLUSH,
-       MFCINST_RES_CHANGE_END,
-};
-
-/*
- * enum s5p_mfc_queue_state - The state of buffer queue.
- */
-enum s5p_mfc_queue_state {
-       QUEUE_FREE,
-       QUEUE_BUFS_REQUESTED,
-       QUEUE_BUFS_QUERIED,
-       QUEUE_BUFS_MMAPED,
-};
-
-/*
- * enum s5p_mfc_decode_arg - type of frame decoding
- */
-enum s5p_mfc_decode_arg {
-       MFC_DEC_FRAME,
-       MFC_DEC_LAST_FRAME,
-       MFC_DEC_RES_CHANGE,
-};
-
-enum s5p_mfc_fw_ver {
-       MFC_FW_V1,
-       MFC_FW_V2,
-};
-
-#define MFC_BUF_FLAG_USED      (1 << 0)
-#define MFC_BUF_FLAG_EOS       (1 << 1)
-
-struct s5p_mfc_ctx;
-
-/*
- * struct s5p_mfc_buf - MFC buffer
- */
-struct s5p_mfc_buf {
-       struct vb2_v4l2_buffer *b;
-       struct list_head list;
-       union {
-               struct {
-                       size_t luma;
-                       size_t chroma;
-               } raw;
-               size_t stream;
-       } cookie;
-       int flags;
-};
-
-/*
- * struct s5p_mfc_pm - power management data structure
- */
-struct s5p_mfc_pm {
-       struct clk      *clock_gate;
-       const char * const *clk_names;
-       struct clk      *clocks[MFC_MAX_CLOCKS];
-       int             num_clocks;
-       bool            use_clock_gating;
-
-       struct device   *device;
-};
-
-struct s5p_mfc_buf_size_v5 {
-       unsigned int h264_ctx;
-       unsigned int non_h264_ctx;
-       unsigned int dsc;
-       unsigned int shm;
-};
-
-struct s5p_mfc_buf_size_v6 {
-       unsigned int dev_ctx;
-       unsigned int h264_dec_ctx;
-       unsigned int other_dec_ctx;
-       unsigned int h264_enc_ctx;
-       unsigned int hevc_enc_ctx;
-       unsigned int other_enc_ctx;
-};
-
-struct s5p_mfc_buf_size {
-       unsigned int fw;
-       unsigned int cpb;
-       void *priv;
-};
-
-struct s5p_mfc_variant {
-       unsigned int version;
-       unsigned int port_num;
-       u32 version_bit;
-       struct s5p_mfc_buf_size *buf_size;
-       char    *fw_name[MFC_FW_MAX_VERSIONS];
-       const char      *clk_names[MFC_MAX_CLOCKS];
-       int             num_clocks;
-       bool            use_clock_gating;
-};
-
-/**
- * struct s5p_mfc_priv_buf - represents internal used buffer
- * @ofs:               offset of each buffer, will be used for MFC
- * @virt:              kernel virtual address, only valid when the
- *                     buffer accessed by driver
- * @dma:               DMA address, only valid when kernel DMA API used
- * @size:              size of the buffer
- * @ctx:               memory context (bank) used for this allocation
- */
-struct s5p_mfc_priv_buf {
-       unsigned long   ofs;
-       void            *virt;
-       dma_addr_t      dma;
-       size_t          size;
-       unsigned int    ctx;
-};
-
-/**
- * struct s5p_mfc_dev - The struct containing driver internal parameters.
- *
- * @v4l2_dev:          v4l2_device
- * @vfd_dec:           video device for decoding
- * @vfd_enc:           video device for encoding
- * @plat_dev:          platform device
- * @mem_dev:           child devices of the memory banks
- * @regs_base:         base address of the MFC hw registers
- * @irq:               irq resource
- * @dec_ctrl_handler:  control framework handler for decoding
- * @enc_ctrl_handler:  control framework handler for encoding
- * @pm:                        power management control
- * @variant:           MFC hardware variant information
- * @num_inst:          counter of active MFC instances
- * @irqlock:           lock for operations on videobuf2 queues
- * @condlock:          lock for changing/checking if a context is ready to be
- *                     processed
- * @mfc_mutex:         lock for video_device
- * @int_cond:          variable used by the waitqueue
- * @int_type:          type of last interrupt
- * @int_err:           error number for last interrupt
- * @queue:             waitqueue for waiting for completion of device commands
- * @fw_buf:            the firmware buffer data structure
- * @mem_size:          size of the firmware operation memory
- * @mem_base:          base DMA address of the firmware operation memory
- * @mem_bitmap:                bitmap for managing MFC internal buffer allocations
- * @mem_virt:          virtual address of the firmware operation memory
- * @dma_base:          address of the beginning of memory banks
- * @hw_lock:           used for hardware locking
- * @ctx:               array of driver contexts
- * @curr_ctx:          number of the currently running context
- * @ctx_work_bits:     used to mark which contexts are waiting for hardware
- * @watchdog_cnt:      counter for the watchdog
- * @watchdog_timer:    timer for the watchdog
- * @watchdog_workqueue:        workqueue for the watchdog
- * @watchdog_work:     worker for the watchdog
- * @enter_suspend:     flag set when entering suspend
- * @ctx_buf:           common context memory (MFCv6)
- * @warn_start:                hardware error code from which warnings start
- * @mfc_ops:           ops structure holding HW operation function pointers
- * @mfc_cmds:          cmd structure holding HW commands function pointers
- * @mfc_regs:          structure holding MFC registers
- * @fw_ver:            loaded firmware sub-version
- * @fw_get_done:       flag set when request_firmware() is complete and
- *                     copied into fw_buf
- * @risc_on:           flag indicates RISC is on or off
- *
- */
-struct s5p_mfc_dev {
-       struct v4l2_device      v4l2_dev;
-       struct video_device     *vfd_dec;
-       struct video_device     *vfd_enc;
-       struct platform_device  *plat_dev;
-       struct device           *mem_dev[BANK_CTX_NUM];
-       void __iomem            *regs_base;
-       int                     irq;
-       struct v4l2_ctrl_handler dec_ctrl_handler;
-       struct v4l2_ctrl_handler enc_ctrl_handler;
-       struct s5p_mfc_pm       pm;
-       const struct s5p_mfc_variant    *variant;
-       int num_inst;
-       spinlock_t irqlock;     /* lock when operating on context */
-       spinlock_t condlock;    /* lock when changing/checking if a context is
-                                       ready to be processed */
-       struct mutex mfc_mutex; /* video_device lock */
-       int int_cond;
-       int int_type;
-       unsigned int int_err;
-       wait_queue_head_t queue;
-       struct s5p_mfc_priv_buf fw_buf;
-       size_t mem_size;
-       dma_addr_t mem_base;
-       unsigned long *mem_bitmap;
-       void *mem_virt;
-       dma_addr_t dma_base[BANK_CTX_NUM];
-       unsigned long hw_lock;
-       struct s5p_mfc_ctx *ctx[MFC_NUM_CONTEXTS];
-       int curr_ctx;
-       unsigned long ctx_work_bits;
-       atomic_t watchdog_cnt;
-       struct timer_list watchdog_timer;
-       struct workqueue_struct *watchdog_workqueue;
-       struct work_struct watchdog_work;
-       unsigned long enter_suspend;
-
-       struct s5p_mfc_priv_buf ctx_buf;
-       int warn_start;
-       struct s5p_mfc_hw_ops *mfc_ops;
-       struct s5p_mfc_hw_cmds *mfc_cmds;
-       const struct s5p_mfc_regs *mfc_regs;
-       enum s5p_mfc_fw_ver fw_ver;
-       bool fw_get_done;
-       bool risc_on; /* indicates if RISC is on or off */
-};
-
-/*
- * struct s5p_mfc_h264_enc_params - encoding parameters for h264
- */
-struct s5p_mfc_h264_enc_params {
-       enum v4l2_mpeg_video_h264_profile profile;
-       enum v4l2_mpeg_video_h264_loop_filter_mode loop_filter_mode;
-       s8 loop_filter_alpha;
-       s8 loop_filter_beta;
-       enum v4l2_mpeg_video_h264_entropy_mode entropy_mode;
-       u8 max_ref_pic;
-       u8 num_ref_pic_4p;
-       int _8x8_transform;
-       int rc_mb_dark;
-       int rc_mb_smooth;
-       int rc_mb_static;
-       int rc_mb_activity;
-       int vui_sar;
-       u8 vui_sar_idc;
-       u16 vui_ext_sar_width;
-       u16 vui_ext_sar_height;
-       int open_gop;
-       u16 open_gop_size;
-       u8 rc_frame_qp;
-       u8 rc_min_qp;
-       u8 rc_max_qp;
-       u8 rc_p_frame_qp;
-       u8 rc_b_frame_qp;
-       enum v4l2_mpeg_video_h264_level level_v4l2;
-       int level;
-       u16 cpb_size;
-       int interlace;
-       u8 hier_qp;
-       u8 hier_qp_type;
-       u8 hier_qp_layer;
-       u8 hier_qp_layer_qp[7];
-       u8 sei_frame_packing;
-       u8 sei_fp_curr_frame_0;
-       u8 sei_fp_arrangement_type;
-
-       u8 fmo;
-       u8 fmo_map_type;
-       u8 fmo_slice_grp;
-       u8 fmo_chg_dir;
-       u32 fmo_chg_rate;
-       u32 fmo_run_len[4];
-       u8 aso;
-       u32 aso_slice_order[8];
-};
-
-/*
- * struct s5p_mfc_mpeg4_enc_params - encoding parameters for h263 and mpeg4
- */
-struct s5p_mfc_mpeg4_enc_params {
-       /* MPEG4 Only */
-       enum v4l2_mpeg_video_mpeg4_profile profile;
-       int quarter_pixel;
-       /* Common for MPEG4, H263 */
-       u16 vop_time_res;
-       u16 vop_frm_delta;
-       u8 rc_frame_qp;
-       u8 rc_min_qp;
-       u8 rc_max_qp;
-       u8 rc_p_frame_qp;
-       u8 rc_b_frame_qp;
-       enum v4l2_mpeg_video_mpeg4_level level_v4l2;
-       int level;
-};
-
-/*
- * struct s5p_mfc_vp8_enc_params - encoding parameters for vp8
- */
-struct s5p_mfc_vp8_enc_params {
-       u8 imd_4x4;
-       enum v4l2_vp8_num_partitions num_partitions;
-       enum v4l2_vp8_num_ref_frames num_ref;
-       u8 filter_level;
-       u8 filter_sharpness;
-       u32 golden_frame_ref_period;
-       enum v4l2_vp8_golden_frame_sel golden_frame_sel;
-       u8 hier_layer;
-       u8 hier_layer_qp[3];
-       u8 rc_min_qp;
-       u8 rc_max_qp;
-       u8 rc_frame_qp;
-       u8 rc_p_frame_qp;
-       u8 profile;
-};
-
-struct s5p_mfc_hevc_enc_params {
-       enum v4l2_mpeg_video_hevc_profile profile;
-       int level;
-       enum v4l2_mpeg_video_h264_level level_v4l2;
-       u8 tier;
-       u32 rc_framerate;
-       u8 rc_min_qp;
-       u8 rc_max_qp;
-       u8 rc_lcu_dark;
-       u8 rc_lcu_smooth;
-       u8 rc_lcu_static;
-       u8 rc_lcu_activity;
-       u8 rc_frame_qp;
-       u8 rc_p_frame_qp;
-       u8 rc_b_frame_qp;
-       u8 max_partition_depth;
-       u8 num_refs_for_p;
-       u8 refreshtype;
-       u16 refreshperiod;
-       s32 lf_beta_offset_div2;
-       s32 lf_tc_offset_div2;
-       u8 loopfilter;
-       u8 loopfilter_disable;
-       u8 loopfilter_across;
-       u8 nal_control_length_filed;
-       u8 nal_control_user_ref;
-       u8 nal_control_store_ref;
-       u8 const_intra_period_enable;
-       u8 lossless_cu_enable;
-       u8 wavefront_enable;
-       u8 enable_ltr;
-       u8 hier_qp_enable;
-       enum v4l2_mpeg_video_hevc_hier_coding_type hier_qp_type;
-       u8 num_hier_layer;
-       u8 hier_qp_layer[7];
-       u32 hier_bit_layer[7];
-       u8 sign_data_hiding;
-       u8 general_pb_enable;
-       u8 temporal_id_enable;
-       u8 strong_intra_smooth;
-       u8 intra_pu_split_disable;
-       u8 tmv_prediction_disable;
-       u8 max_num_merge_mv;
-       u8 eco_mode_enable;
-       u8 encoding_nostartcode_enable;
-       u8 size_of_length_field;
-       u8 prepend_sps_pps_to_idr;
-};
-
-/*
- * struct s5p_mfc_enc_params - general encoding parameters
- */
-struct s5p_mfc_enc_params {
-       u16 width;
-       u16 height;
-       u32 mv_h_range;
-       u32 mv_v_range;
-
-       u16 gop_size;
-       enum v4l2_mpeg_video_multi_slice_mode slice_mode;
-       u16 slice_mb;
-       u32 slice_bit;
-       u16 intra_refresh_mb;
-       int pad;
-       u8 pad_luma;
-       u8 pad_cb;
-       u8 pad_cr;
-       int rc_frame;
-       int rc_mb;
-       u32 rc_bitrate;
-       u16 rc_reaction_coeff;
-       u16 vbv_size;
-       u32 vbv_delay;
-
-       enum v4l2_mpeg_video_header_mode seq_hdr_mode;
-       enum v4l2_mpeg_mfc51_video_frame_skip_mode frame_skip_mode;
-       int fixed_target_bit;
-
-       u8 num_b_frame;
-       u32 rc_framerate_num;
-       u32 rc_framerate_denom;
-
-       struct {
-               struct s5p_mfc_h264_enc_params h264;
-               struct s5p_mfc_mpeg4_enc_params mpeg4;
-               struct s5p_mfc_vp8_enc_params vp8;
-               struct s5p_mfc_hevc_enc_params hevc;
-       } codec;
-
-};
-
-/*
- * struct s5p_mfc_codec_ops - codec ops, used by encoding
- */
-struct s5p_mfc_codec_ops {
-       /* initialization routines */
-       int (*pre_seq_start) (struct s5p_mfc_ctx *ctx);
-       int (*post_seq_start) (struct s5p_mfc_ctx *ctx);
-       /* execution routines */
-       int (*pre_frame_start) (struct s5p_mfc_ctx *ctx);
-       int (*post_frame_start) (struct s5p_mfc_ctx *ctx);
-};
-
-#define call_cop(c, op, args...)                               \
-       (((c)->c_ops->op) ?                                     \
-               ((c)->c_ops->op(args)) : 0)
-
-/**
- * struct s5p_mfc_ctx - This struct contains the instance context
- *
- * @dev:               pointer to the s5p_mfc_dev of the device
- * @fh:                        struct v4l2_fh
- * @num:               number of the context that this structure describes
- * @int_cond:          variable used by the waitqueue
- * @int_type:          type of the last interrupt
- * @int_err:           error number received from MFC hw in the interrupt
- * @queue:             waitqueue that can be used to wait for this context to
- *                     finish
- * @src_fmt:           source pixelformat information
- * @dst_fmt:           destination pixelformat information
- * @vq_src:            vb2 queue for source buffers
- * @vq_dst:            vb2 queue for destination buffers
- * @src_queue:         driver internal queue for source buffers
- * @dst_queue:         driver internal queue for destination buffers
- * @src_queue_cnt:     number of buffers queued on the source internal queue
- * @dst_queue_cnt:     number of buffers queued on the dest internal queue
- * @type:              type of the instance - decoder or encoder
- * @state:             state of the context
- * @inst_no:           number of hw instance associated with the context
- * @img_width:         width of the image that is decoded or encoded
- * @img_height:                height of the image that is decoded or encoded
- * @buf_width:         width of the buffer for processed image
- * @buf_height:                height of the buffer for processed image
- * @luma_size:         size of a luma plane
- * @chroma_size:       size of a chroma plane
- * @mv_size:           size of a motion vectors buffer
- * @consumed_stream:   number of bytes that have been used so far from the
- *                     decoding buffer
- * @dpb_flush_flag:    flag used to indicate that a DPB buffers are being
- *                     flushed
- * @head_processed:    flag mentioning whether the header data is processed
- *                     completely or not
- * @bank1:             handle to memory allocated for temporary buffers from
- *                     memory bank 1
- * @bank2:             handle to memory allocated for temporary buffers from
- *                     memory bank 2
- * @capture_state:     state of the capture buffers queue
- * @output_state:      state of the output buffers queue
- * @src_bufs:          information on allocated source buffers
- * @src_bufs_cnt:      number of allocated source buffers
- * @dst_bufs:          information on allocated destination buffers
- * @dst_bufs_cnt:      number of allocated destination buffers
- * @sequence:          counter for the sequence number for v4l2
- * @dec_dst_flag:      flags for buffers queued in the hardware
- * @dec_src_buf_size:  size of the buffer for source buffers in decoding
- * @codec_mode:                number of codec mode used by MFC hw
- * @slice_interface:   slice interface flag
- * @loop_filter_mpeg4: loop filter for MPEG4 flag
- * @display_delay:     value of the display delay for H264
- * @display_delay_enable:      display delay for H264 enable flag
- * @after_packed_pb:   flag used to track buffer when stream is in
- *                     Packed PB format
- * @sei_fp_parse:      enable/disable parsing of frame packing SEI information
- * @pb_count:          count of the DPB buffers required by MFC hw
- * @total_dpb_count:   count of DPB buffers with additional buffers
- *                     requested by the application
- * @ctx:               context buffer information
- * @dsc:               descriptor buffer information
- * @shm:               shared memory buffer information
- * @mv_count:          number of MV buffers allocated for decoding
- * @enc_params:                encoding parameters for MFC
- * @enc_dst_buf_size:  size of the buffers for encoder output
- * @luma_dpb_size:     dpb buffer size for luma
- * @chroma_dpb_size:   dpb buffer size for chroma
- * @me_buffer_size:    size of the motion estimation buffer
- * @tmv_buffer_size:   size of temporal predictor motion vector buffer
- * @frame_type:                used to force the type of the next encoded frame
- * @ref_queue:         list of the reference buffers for encoding
- * @force_frame_type:  encoder's frame type forcing control
- * @ref_queue_cnt:     number of the buffers in the reference list
- * @slice_size:                slice size
- * @slice_mode:                mode of dividing frames into slices
- * @c_ops:             ops for encoding
- * @ctrls:             array of controls, used when adding controls to the
- *                     v4l2 control framework
- * @ctrl_handler:      handler for v4l2 framework
- * @scratch_buf_size:  scratch buffer size
- */
-struct s5p_mfc_ctx {
-       struct s5p_mfc_dev *dev;
-       struct v4l2_fh fh;
-
-       int num;
-
-       int int_cond;
-       int int_type;
-       unsigned int int_err;
-       wait_queue_head_t queue;
-
-       struct s5p_mfc_fmt *src_fmt;
-       struct s5p_mfc_fmt *dst_fmt;
-
-       struct vb2_queue vq_src;
-       struct vb2_queue vq_dst;
-
-       struct list_head src_queue;
-       struct list_head dst_queue;
-
-       unsigned int src_queue_cnt;
-       unsigned int dst_queue_cnt;
-
-       enum s5p_mfc_inst_type type;
-       enum s5p_mfc_inst_state state;
-       int inst_no;
-
-       /* Image parameters */
-       int img_width;
-       int img_height;
-       int buf_width;
-       int buf_height;
-
-       int luma_size;
-       int chroma_size;
-       int mv_size;
-
-       unsigned long consumed_stream;
-
-       unsigned int dpb_flush_flag;
-       unsigned int head_processed;
-
-       struct s5p_mfc_priv_buf bank1;
-       struct s5p_mfc_priv_buf bank2;
-
-       enum s5p_mfc_queue_state capture_state;
-       enum s5p_mfc_queue_state output_state;
-
-       struct s5p_mfc_buf src_bufs[MFC_MAX_BUFFERS];
-       int src_bufs_cnt;
-       struct s5p_mfc_buf dst_bufs[MFC_MAX_BUFFERS];
-       int dst_bufs_cnt;
-
-       unsigned int sequence;
-       unsigned long dec_dst_flag;
-       size_t dec_src_buf_size;
-
-       /* Control values */
-       int codec_mode;
-       int slice_interface;
-       int loop_filter_mpeg4;
-       int display_delay;
-       int display_delay_enable;
-       int after_packed_pb;
-       int sei_fp_parse;
-
-       int pb_count;
-       int total_dpb_count;
-       int mv_count;
-       /* Buffers */
-       struct s5p_mfc_priv_buf ctx;
-       struct s5p_mfc_priv_buf dsc;
-       struct s5p_mfc_priv_buf shm;
-
-       struct s5p_mfc_enc_params enc_params;
-
-       size_t enc_dst_buf_size;
-       size_t luma_dpb_size;
-       size_t chroma_dpb_size;
-       size_t me_buffer_size;
-       size_t tmv_buffer_size;
-
-       enum v4l2_mpeg_mfc51_video_force_frame_type force_frame_type;
-
-       struct list_head ref_queue;
-       unsigned int ref_queue_cnt;
-
-       enum v4l2_mpeg_video_multi_slice_mode slice_mode;
-       union {
-               unsigned int mb;
-               unsigned int bits;
-       } slice_size;
-
-       const struct s5p_mfc_codec_ops *c_ops;
-
-       struct v4l2_ctrl *ctrls[MFC_MAX_CTRLS];
-       struct v4l2_ctrl_handler ctrl_handler;
-       size_t scratch_buf_size;
-};
-
-/*
- * struct s5p_mfc_fmt -        structure used to store information about pixelformats
- *                     used by the MFC
- */
-struct s5p_mfc_fmt {
-       u32 fourcc;
-       u32 codec_mode;
-       enum s5p_mfc_fmt_type type;
-       u32 num_planes;
-       u32 versions;
-       u32 flags;
-};
-
-/*
- * struct mfc_control -        structure used to store information about MFC controls
- *                     it is used to initialize the control framework.
- */
-struct mfc_control {
-       __u32                   id;
-       enum v4l2_ctrl_type     type;
-       __u8                    name[32];  /* Whatever */
-       __s32                   minimum;   /* Note signedness */
-       __s32                   maximum;
-       __s32                   step;
-       __u32                   menu_skip_mask;
-       __s32                   default_value;
-       __u32                   flags;
-       __u32                   reserved[2];
-       __u8                    is_volatile;
-};
-
-/* Macro for making hardware specific calls */
-#define s5p_mfc_hw_call(f, op, args...) \
-       ((f && f->op) ? f->op(args) : (typeof(f->op(args)))(-ENODEV))
-
-#define fh_to_ctx(__fh) container_of(__fh, struct s5p_mfc_ctx, fh)
-#define ctrl_to_ctx(__ctrl) \
-       container_of((__ctrl)->handler, struct s5p_mfc_ctx, ctrl_handler)
-
-void clear_work_bit(struct s5p_mfc_ctx *ctx);
-void set_work_bit(struct s5p_mfc_ctx *ctx);
-void clear_work_bit_irqsave(struct s5p_mfc_ctx *ctx);
-void set_work_bit_irqsave(struct s5p_mfc_ctx *ctx);
-int s5p_mfc_get_new_ctx(struct s5p_mfc_dev *dev);
-void s5p_mfc_cleanup_queue(struct list_head *lh, struct vb2_queue *vq);
-
-#define HAS_PORTNUM(dev)       (dev ? (dev->variant ? \
-                               (dev->variant->port_num ? 1 : 0) : 0) : 0)
-#define IS_TWOPORT(dev)                (dev->variant->port_num == 2 ? 1 : 0)
-#define IS_MFCV6_PLUS(dev)     (dev->variant->version >= 0x60 ? 1 : 0)
-#define IS_MFCV7_PLUS(dev)     (dev->variant->version >= 0x70 ? 1 : 0)
-#define IS_MFCV8_PLUS(dev)     (dev->variant->version >= 0x80 ? 1 : 0)
-#define IS_MFCV10(dev)         (dev->variant->version >= 0xA0 ? 1 : 0)
-#define FW_HAS_E_MIN_SCRATCH_BUF(dev) (IS_MFCV10(dev))
-
-#define MFC_V5_BIT     BIT(0)
-#define MFC_V6_BIT     BIT(1)
-#define MFC_V7_BIT     BIT(2)
-#define MFC_V8_BIT     BIT(3)
-#define MFC_V10_BIT    BIT(5)
-
-#define MFC_V5PLUS_BITS                (MFC_V5_BIT | MFC_V6_BIT | MFC_V7_BIT | \
-                                       MFC_V8_BIT | MFC_V10_BIT)
-#define MFC_V6PLUS_BITS                (MFC_V6_BIT | MFC_V7_BIT | MFC_V8_BIT | \
-                                       MFC_V10_BIT)
-#define MFC_V7PLUS_BITS                (MFC_V7_BIT | MFC_V8_BIT | MFC_V10_BIT)
-
-#endif /* S5P_MFC_COMMON_H_ */
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
deleted file mode 100644 (file)
index da138c3..0000000
+++ /dev/null
@@ -1,482 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * linux/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- */
-
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/firmware.h>
-#include <linux/jiffies.h>
-#include <linux/sched.h>
-#include "s5p_mfc_cmd.h"
-#include "s5p_mfc_common.h"
-#include "s5p_mfc_debug.h"
-#include "s5p_mfc_intr.h"
-#include "s5p_mfc_opr.h"
-#include "s5p_mfc_pm.h"
-#include "s5p_mfc_ctrl.h"
-
-/* Allocate memory for firmware */
-int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev)
-{
-       struct s5p_mfc_priv_buf *fw_buf = &dev->fw_buf;
-       int err;
-
-       fw_buf->size = dev->variant->buf_size->fw;
-
-       if (fw_buf->virt) {
-               mfc_err("Attempting to allocate firmware when it seems that it is already loaded\n");
-               return -ENOMEM;
-       }
-
-       err = s5p_mfc_alloc_priv_buf(dev, BANK_L_CTX, &dev->fw_buf);
-       if (err) {
-               mfc_err("Allocating bitprocessor buffer failed\n");
-               return err;
-       }
-
-       return 0;
-}
-
-/* Load firmware */
-int s5p_mfc_load_firmware(struct s5p_mfc_dev *dev)
-{
-       struct firmware *fw_blob;
-       int i, err = -EINVAL;
-
-       /* Firmware has to be present as a separate file or compiled
-        * into kernel. */
-       mfc_debug_enter();
-
-       if (dev->fw_get_done)
-               return 0;
-
-       for (i = MFC_FW_MAX_VERSIONS - 1; i >= 0; i--) {
-               if (!dev->variant->fw_name[i])
-                       continue;
-               err = request_firmware((const struct firmware **)&fw_blob,
-                               dev->variant->fw_name[i], &dev->plat_dev->dev);
-               if (!err) {
-                       dev->fw_ver = (enum s5p_mfc_fw_ver) i;
-                       break;
-               }
-       }
-
-       if (err != 0) {
-               mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n");
-               return -EINVAL;
-       }
-       if (fw_blob->size > dev->fw_buf.size) {
-               mfc_err("MFC firmware is too big to be loaded\n");
-               release_firmware(fw_blob);
-               return -ENOMEM;
-       }
-       memcpy(dev->fw_buf.virt, fw_blob->data, fw_blob->size);
-       wmb();
-       dev->fw_get_done = true;
-       release_firmware(fw_blob);
-       mfc_debug_leave();
-       return 0;
-}
-
-/* Release firmware memory */
-int s5p_mfc_release_firmware(struct s5p_mfc_dev *dev)
-{
-       /* Before calling this function one has to make sure
-        * that MFC is no longer processing */
-       s5p_mfc_release_priv_buf(dev, &dev->fw_buf);
-       dev->fw_get_done = false;
-       return 0;
-}
-
-static int s5p_mfc_bus_reset(struct s5p_mfc_dev *dev)
-{
-       unsigned int status;
-       unsigned long timeout;
-
-       /* Reset */
-       mfc_write(dev, 0x1, S5P_FIMV_MFC_BUS_RESET_CTRL);
-       timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
-       /* Check bus status */
-       do {
-               if (time_after(jiffies, timeout)) {
-                       mfc_err("Timeout while resetting MFC.\n");
-                       return -EIO;
-               }
-               status = mfc_read(dev, S5P_FIMV_MFC_BUS_RESET_CTRL);
-       } while ((status & 0x2) == 0);
-       return 0;
-}
-
-/* Reset the device */
-int s5p_mfc_reset(struct s5p_mfc_dev *dev)
-{
-       unsigned int mc_status;
-       unsigned long timeout;
-       int i;
-
-       mfc_debug_enter();
-
-       if (IS_MFCV6_PLUS(dev)) {
-               /* Zero Initialization of MFC registers */
-               mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD_V6);
-               mfc_write(dev, 0, S5P_FIMV_HOST2RISC_CMD_V6);
-               mfc_write(dev, 0, S5P_FIMV_FW_VERSION_V6);
-
-               for (i = 0; i < S5P_FIMV_REG_CLEAR_COUNT_V6; i++)
-                       mfc_write(dev, 0, S5P_FIMV_REG_CLEAR_BEGIN_V6 + (i*4));
-
-               /* check bus reset control before reset */
-               if (dev->risc_on)
-                       if (s5p_mfc_bus_reset(dev))
-                               return -EIO;
-               /* Reset
-                * set RISC_ON to 0 during power_on & wake_up.
-                * V6 needs RISC_ON set to 0 during reset also.
-                */
-               if ((!dev->risc_on) || (!IS_MFCV7_PLUS(dev)))
-                       mfc_write(dev, 0, S5P_FIMV_RISC_ON_V6);
-
-               mfc_write(dev, 0x1FFF, S5P_FIMV_MFC_RESET_V6);
-               mfc_write(dev, 0, S5P_FIMV_MFC_RESET_V6);
-       } else {
-               /* Stop procedure */
-               /*  reset RISC */
-               mfc_write(dev, 0x3f6, S5P_FIMV_SW_RESET);
-               /*  All reset except for MC */
-               mfc_write(dev, 0x3e2, S5P_FIMV_SW_RESET);
-               mdelay(10);
-
-               timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
-               /* Check MC status */
-               do {
-                       if (time_after(jiffies, timeout)) {
-                               mfc_err("Timeout while resetting MFC\n");
-                               return -EIO;
-                       }
-
-                       mc_status = mfc_read(dev, S5P_FIMV_MC_STATUS);
-
-               } while (mc_status & 0x3);
-
-               mfc_write(dev, 0x0, S5P_FIMV_SW_RESET);
-               mfc_write(dev, 0x3fe, S5P_FIMV_SW_RESET);
-       }
-
-       mfc_debug_leave();
-       return 0;
-}
-
-static inline void s5p_mfc_init_memctrl(struct s5p_mfc_dev *dev)
-{
-       if (IS_MFCV6_PLUS(dev)) {
-               mfc_write(dev, dev->dma_base[BANK_L_CTX],
-                         S5P_FIMV_RISC_BASE_ADDRESS_V6);
-               mfc_debug(2, "Base Address : %pad\n",
-                         &dev->dma_base[BANK_L_CTX]);
-       } else {
-               mfc_write(dev, dev->dma_base[BANK_L_CTX],
-                         S5P_FIMV_MC_DRAMBASE_ADR_A);
-               mfc_write(dev, dev->dma_base[BANK_R_CTX],
-                         S5P_FIMV_MC_DRAMBASE_ADR_B);
-               mfc_debug(2, "Bank1: %pad, Bank2: %pad\n",
-                         &dev->dma_base[BANK_L_CTX],
-                         &dev->dma_base[BANK_R_CTX]);
-       }
-}
-
-static inline void s5p_mfc_clear_cmds(struct s5p_mfc_dev *dev)
-{
-       if (IS_MFCV6_PLUS(dev)) {
-               /* Zero initialization should be done before RESET.
-                * Nothing to do here. */
-       } else {
-               mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH0_INST_ID);
-               mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH1_INST_ID);
-               mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
-               mfc_write(dev, 0, S5P_FIMV_HOST2RISC_CMD);
-       }
-}
-
-/* Initialize hardware */
-int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
-{
-       unsigned int ver;
-       int ret;
-
-       mfc_debug_enter();
-       if (!dev->fw_buf.virt) {
-               mfc_err("Firmware memory is not allocated.\n");
-               return -EINVAL;
-       }
-
-       /* 0. MFC reset */
-       mfc_debug(2, "MFC reset..\n");
-       s5p_mfc_clock_on();
-       dev->risc_on = 0;
-       ret = s5p_mfc_reset(dev);
-       if (ret) {
-               mfc_err("Failed to reset MFC - timeout\n");
-               return ret;
-       }
-       mfc_debug(2, "Done MFC reset..\n");
-       /* 1. Set DRAM base Addr */
-       s5p_mfc_init_memctrl(dev);
-       /* 2. Initialize registers of channel I/F */
-       s5p_mfc_clear_cmds(dev);
-       /* 3. Release reset signal to the RISC */
-       s5p_mfc_clean_dev_int_flags(dev);
-       if (IS_MFCV6_PLUS(dev)) {
-               dev->risc_on = 1;
-               mfc_write(dev, 0x1, S5P_FIMV_RISC_ON_V6);
-       }
-       else
-               mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
-
-       if (IS_MFCV10(dev))
-               mfc_write(dev, 0x0, S5P_FIMV_MFC_CLOCK_OFF_V10);
-
-       mfc_debug(2, "Will now wait for completion of firmware transfer\n");
-       if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_FW_STATUS_RET)) {
-               mfc_err("Failed to load firmware\n");
-               s5p_mfc_reset(dev);
-               s5p_mfc_clock_off();
-               return -EIO;
-       }
-       s5p_mfc_clean_dev_int_flags(dev);
-       /* 4. Initialize firmware */
-       ret = s5p_mfc_hw_call(dev->mfc_cmds, sys_init_cmd, dev);
-       if (ret) {
-               mfc_err("Failed to send command to MFC - timeout\n");
-               s5p_mfc_reset(dev);
-               s5p_mfc_clock_off();
-               return ret;
-       }
-       mfc_debug(2, "Ok, now will wait for completion of hardware init\n");
-       if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_SYS_INIT_RET)) {
-               mfc_err("Failed to init hardware\n");
-               s5p_mfc_reset(dev);
-               s5p_mfc_clock_off();
-               return -EIO;
-       }
-       dev->int_cond = 0;
-       if (dev->int_err != 0 || dev->int_type !=
-                                       S5P_MFC_R2H_CMD_SYS_INIT_RET) {
-               /* Failure. */
-               mfc_err("Failed to init firmware - error: %d int: %d\n",
-                                               dev->int_err, dev->int_type);
-               s5p_mfc_reset(dev);
-               s5p_mfc_clock_off();
-               return -EIO;
-       }
-       if (IS_MFCV6_PLUS(dev))
-               ver = mfc_read(dev, S5P_FIMV_FW_VERSION_V6);
-       else
-               ver = mfc_read(dev, S5P_FIMV_FW_VERSION);
-
-       mfc_debug(2, "MFC F/W version : %02xyy, %02xmm, %02xdd\n",
-               (ver >> 16) & 0xFF, (ver >> 8) & 0xFF, ver & 0xFF);
-       s5p_mfc_clock_off();
-       mfc_debug_leave();
-       return 0;
-}
-
-
-/* Deinitialize hardware */
-void s5p_mfc_deinit_hw(struct s5p_mfc_dev *dev)
-{
-       s5p_mfc_clock_on();
-
-       s5p_mfc_reset(dev);
-       s5p_mfc_hw_call(dev->mfc_ops, release_dev_context_buffer, dev);
-
-       s5p_mfc_clock_off();
-}
-
-int s5p_mfc_sleep(struct s5p_mfc_dev *dev)
-{
-       int ret;
-
-       mfc_debug_enter();
-       s5p_mfc_clock_on();
-       s5p_mfc_clean_dev_int_flags(dev);
-       ret = s5p_mfc_hw_call(dev->mfc_cmds, sleep_cmd, dev);
-       if (ret) {
-               mfc_err("Failed to send command to MFC - timeout\n");
-               return ret;
-       }
-       if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_SLEEP_RET)) {
-               mfc_err("Failed to sleep\n");
-               return -EIO;
-       }
-       s5p_mfc_clock_off();
-       dev->int_cond = 0;
-       if (dev->int_err != 0 || dev->int_type !=
-                                               S5P_MFC_R2H_CMD_SLEEP_RET) {
-               /* Failure. */
-               mfc_err("Failed to sleep - error: %d int: %d\n", dev->int_err,
-                                                               dev->int_type);
-               return -EIO;
-       }
-       mfc_debug_leave();
-       return ret;
-}
-
-static int s5p_mfc_v8_wait_wakeup(struct s5p_mfc_dev *dev)
-{
-       int ret;
-
-       /* Release reset signal to the RISC */
-       dev->risc_on = 1;
-       mfc_write(dev, 0x1, S5P_FIMV_RISC_ON_V6);
-
-       if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_FW_STATUS_RET)) {
-               mfc_err("Failed to reset MFCV8\n");
-               return -EIO;
-       }
-       mfc_debug(2, "Write command to wakeup MFCV8\n");
-       ret = s5p_mfc_hw_call(dev->mfc_cmds, wakeup_cmd, dev);
-       if (ret) {
-               mfc_err("Failed to send command to MFCV8 - timeout\n");
-               return ret;
-       }
-
-       if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_WAKEUP_RET)) {
-               mfc_err("Failed to wakeup MFC\n");
-               return -EIO;
-       }
-       return ret;
-}
-
-static int s5p_mfc_wait_wakeup(struct s5p_mfc_dev *dev)
-{
-       int ret;
-
-       /* Send MFC wakeup command */
-       ret = s5p_mfc_hw_call(dev->mfc_cmds, wakeup_cmd, dev);
-       if (ret) {
-               mfc_err("Failed to send command to MFC - timeout\n");
-               return ret;
-       }
-
-       /* Release reset signal to the RISC */
-       if (IS_MFCV6_PLUS(dev)) {
-               dev->risc_on = 1;
-               mfc_write(dev, 0x1, S5P_FIMV_RISC_ON_V6);
-       } else {
-               mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
-       }
-
-       if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_WAKEUP_RET)) {
-               mfc_err("Failed to wakeup MFC\n");
-               return -EIO;
-       }
-       return ret;
-}
-
-int s5p_mfc_wakeup(struct s5p_mfc_dev *dev)
-{
-       int ret;
-
-       mfc_debug_enter();
-       /* 0. MFC reset */
-       mfc_debug(2, "MFC reset..\n");
-       s5p_mfc_clock_on();
-       dev->risc_on = 0;
-       ret = s5p_mfc_reset(dev);
-       if (ret) {
-               mfc_err("Failed to reset MFC - timeout\n");
-               s5p_mfc_clock_off();
-               return ret;
-       }
-       mfc_debug(2, "Done MFC reset..\n");
-       /* 1. Set DRAM base Addr */
-       s5p_mfc_init_memctrl(dev);
-       /* 2. Initialize registers of channel I/F */
-       s5p_mfc_clear_cmds(dev);
-       s5p_mfc_clean_dev_int_flags(dev);
-       /* 3. Send MFC wakeup command and wait for completion*/
-       if (IS_MFCV8_PLUS(dev))
-               ret = s5p_mfc_v8_wait_wakeup(dev);
-       else
-               ret = s5p_mfc_wait_wakeup(dev);
-
-       s5p_mfc_clock_off();
-       if (ret)
-               return ret;
-
-       dev->int_cond = 0;
-       if (dev->int_err != 0 || dev->int_type !=
-                                               S5P_MFC_R2H_CMD_WAKEUP_RET) {
-               /* Failure. */
-               mfc_err("Failed to wakeup - error: %d int: %d\n", dev->int_err,
-                                                               dev->int_type);
-               return -EIO;
-       }
-       mfc_debug_leave();
-       return 0;
-}
-
-int s5p_mfc_open_mfc_inst(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx)
-{
-       int ret = 0;
-
-       ret = s5p_mfc_hw_call(dev->mfc_ops, alloc_instance_buffer, ctx);
-       if (ret) {
-               mfc_err("Failed allocating instance buffer\n");
-               goto err;
-       }
-
-       if (ctx->type == MFCINST_DECODER) {
-               ret = s5p_mfc_hw_call(dev->mfc_ops,
-                                       alloc_dec_temp_buffers, ctx);
-               if (ret) {
-                       mfc_err("Failed allocating temporary buffers\n");
-                       goto err_free_inst_buf;
-               }
-       }
-
-       set_work_bit_irqsave(ctx);
-       s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
-       if (s5p_mfc_wait_for_done_ctx(ctx,
-               S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET, 0)) {
-               /* Error or timeout */
-               mfc_err("Error getting instance from hardware\n");
-               ret = -EIO;
-               goto err_free_desc_buf;
-       }
-
-       mfc_debug(2, "Got instance number: %d\n", ctx->inst_no);
-       return ret;
-
-err_free_desc_buf:
-       if (ctx->type == MFCINST_DECODER)
-               s5p_mfc_hw_call(dev->mfc_ops, release_dec_desc_buffer, ctx);
-err_free_inst_buf:
-       s5p_mfc_hw_call(dev->mfc_ops, release_instance_buffer, ctx);
-err:
-       return ret;
-}
-
-void s5p_mfc_close_mfc_inst(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx)
-{
-       ctx->state = MFCINST_RETURN_INST;
-       set_work_bit_irqsave(ctx);
-       s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
-       /* Wait until instance is returned or timeout occurred */
-       if (s5p_mfc_wait_for_done_ctx(ctx,
-                               S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET, 0))
-               mfc_err("Err returning instance\n");
-
-       /* Free resources */
-       s5p_mfc_hw_call(dev->mfc_ops, release_codec_buffers, ctx);
-       s5p_mfc_hw_call(dev->mfc_ops, release_instance_buffer, ctx);
-       if (ctx->type == MFCINST_DECODER)
-               s5p_mfc_hw_call(dev->mfc_ops, release_dec_desc_buffer, ctx);
-
-       ctx->inst_no = MFC_NO_INSTANCE_SET;
-       ctx->state = MFCINST_FREE;
-}
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h
deleted file mode 100644 (file)
index 7f32ef8..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * linux/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- */
-
-#ifndef S5P_MFC_CTRL_H
-#define S5P_MFC_CTRL_H
-
-#include "s5p_mfc_common.h"
-
-int s5p_mfc_release_firmware(struct s5p_mfc_dev *dev);
-int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev);
-int s5p_mfc_load_firmware(struct s5p_mfc_dev *dev);
-
-int s5p_mfc_init_hw(struct s5p_mfc_dev *dev);
-void s5p_mfc_deinit_hw(struct s5p_mfc_dev *dev);
-
-int s5p_mfc_sleep(struct s5p_mfc_dev *dev);
-int s5p_mfc_wakeup(struct s5p_mfc_dev *dev);
-
-int s5p_mfc_reset(struct s5p_mfc_dev *dev);
-
-int s5p_mfc_open_mfc_inst(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx);
-void s5p_mfc_close_mfc_inst(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx);
-
-#endif /* S5P_MFC_CTRL_H */
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_debug.h b/drivers/media/platform/s5p-mfc/s5p_mfc_debug.h
deleted file mode 100644 (file)
index 752bbe4..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * drivers/media/platform/s5p-mfc/s5p_mfc_debug.h
- *
- * Header file for Samsung MFC (Multi Function Codec - FIMV) driver
- * This file contains debug macros
- *
- * Kamil Debski, Copyright (c) 2011 Samsung Electronics
- * http://www.samsung.com/
- */
-
-#ifndef S5P_MFC_DEBUG_H_
-#define S5P_MFC_DEBUG_H_
-
-#define DEBUG
-
-#ifdef DEBUG
-extern int mfc_debug_level;
-
-#define mfc_debug(level, fmt, args...)                         \
-       do {                                                    \
-               if (mfc_debug_level >= level)                   \
-                       printk(KERN_DEBUG "%s:%d: " fmt,        \
-                               __func__, __LINE__, ##args);    \
-       } while (0)
-#else
-#define mfc_debug(level, fmt, args...)
-#endif
-
-#define mfc_debug_enter() mfc_debug(5, "enter\n")
-#define mfc_debug_leave() mfc_debug(5, "leave\n")
-
-#define mfc_err(fmt, args...)                          \
-       do {                                            \
-               printk(KERN_ERR "%s:%d: " fmt,          \
-                      __func__, __LINE__, ##args);     \
-       } while (0)
-
-#define mfc_err_limited(fmt, args...)                  \
-       do {                                            \
-               printk_ratelimited(KERN_ERR "%s:%d: " fmt,      \
-                      __func__, __LINE__, ##args);     \
-       } while (0)
-
-#define mfc_info(fmt, args...)                         \
-       do {                                            \
-               printk(KERN_INFO "%s:%d: " fmt,         \
-                      __func__, __LINE__, ##args);     \
-       } while (0)
-
-#endif /* S5P_MFC_DEBUG_H_ */
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
deleted file mode 100644 (file)
index c079881..0000000
+++ /dev/null
@@ -1,1218 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * linux/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
- *
- * Copyright (C) 2011 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- * Kamil Debski, <k.debski@samsung.com>
- */
-
-#include <linux/clk.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/videodev2.h>
-#include <linux/workqueue.h>
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-event.h>
-#include <media/videobuf2-v4l2.h>
-#include "s5p_mfc_common.h"
-#include "s5p_mfc_ctrl.h"
-#include "s5p_mfc_debug.h"
-#include "s5p_mfc_dec.h"
-#include "s5p_mfc_intr.h"
-#include "s5p_mfc_opr.h"
-#include "s5p_mfc_pm.h"
-
-static struct s5p_mfc_fmt formats[] = {
-       {
-               .fourcc         = V4L2_PIX_FMT_NV12MT_16X16,
-               .codec_mode     = S5P_MFC_CODEC_NONE,
-               .type           = MFC_FMT_RAW,
-               .num_planes     = 2,
-               .versions       = MFC_V6_BIT | MFC_V7_BIT,
-       },
-       {
-               .fourcc         = V4L2_PIX_FMT_NV12MT,
-               .codec_mode     = S5P_MFC_CODEC_NONE,
-               .type           = MFC_FMT_RAW,
-               .num_planes     = 2,
-               .versions       = MFC_V5_BIT,
-       },
-       {
-               .fourcc         = V4L2_PIX_FMT_NV12M,
-               .codec_mode     = S5P_MFC_CODEC_NONE,
-               .type           = MFC_FMT_RAW,
-               .num_planes     = 2,
-               .versions       = MFC_V6PLUS_BITS,
-       },
-       {
-               .fourcc         = V4L2_PIX_FMT_NV21M,
-               .codec_mode     = S5P_MFC_CODEC_NONE,
-               .type           = MFC_FMT_RAW,
-               .num_planes     = 2,
-               .versions       = MFC_V6PLUS_BITS,
-       },
-       {
-               .fourcc         = V4L2_PIX_FMT_H264,
-               .codec_mode     = S5P_MFC_CODEC_H264_DEC,
-               .type           = MFC_FMT_DEC,
-               .num_planes     = 1,
-               .versions       = MFC_V5PLUS_BITS,
-               .flags          = V4L2_FMT_FLAG_DYN_RESOLUTION |
-                                 V4L2_FMT_FLAG_CONTINUOUS_BYTESTREAM,
-       },
-       {
-               .fourcc         = V4L2_PIX_FMT_H264_MVC,
-               .codec_mode     = S5P_MFC_CODEC_H264_MVC_DEC,
-               .type           = MFC_FMT_DEC,
-               .num_planes     = 1,
-               .versions       = MFC_V6PLUS_BITS,
-               .flags          = V4L2_FMT_FLAG_DYN_RESOLUTION |
-                                 V4L2_FMT_FLAG_CONTINUOUS_BYTESTREAM,
-       },
-       {
-               .fourcc         = V4L2_PIX_FMT_H263,
-               .codec_mode     = S5P_MFC_CODEC_H263_DEC,
-               .type           = MFC_FMT_DEC,
-               .num_planes     = 1,
-               .versions       = MFC_V5PLUS_BITS,
-               .flags          = V4L2_FMT_FLAG_DYN_RESOLUTION,
-       },
-       {
-               .fourcc         = V4L2_PIX_FMT_MPEG1,
-               .codec_mode     = S5P_MFC_CODEC_MPEG2_DEC,
-               .type           = MFC_FMT_DEC,
-               .num_planes     = 1,
-               .versions       = MFC_V5PLUS_BITS,
-               .flags          = V4L2_FMT_FLAG_DYN_RESOLUTION |
-                                 V4L2_FMT_FLAG_CONTINUOUS_BYTESTREAM,
-       },
-       {
-               .fourcc         = V4L2_PIX_FMT_MPEG2,
-               .codec_mode     = S5P_MFC_CODEC_MPEG2_DEC,
-               .type           = MFC_FMT_DEC,
-               .num_planes     = 1,
-               .versions       = MFC_V5PLUS_BITS,
-               .flags          = V4L2_FMT_FLAG_DYN_RESOLUTION |
-                                 V4L2_FMT_FLAG_CONTINUOUS_BYTESTREAM,
-       },
-       {
-               .fourcc         = V4L2_PIX_FMT_MPEG4,
-               .codec_mode     = S5P_MFC_CODEC_MPEG4_DEC,
-               .type           = MFC_FMT_DEC,
-               .num_planes     = 1,
-               .versions       = MFC_V5PLUS_BITS,
-               .flags          = V4L2_FMT_FLAG_DYN_RESOLUTION |
-                                 V4L2_FMT_FLAG_CONTINUOUS_BYTESTREAM,
-       },
-       {
-               .fourcc         = V4L2_PIX_FMT_XVID,
-               .codec_mode     = S5P_MFC_CODEC_MPEG4_DEC,
-               .type           = MFC_FMT_DEC,
-               .num_planes     = 1,
-               .versions       = MFC_V5PLUS_BITS,
-               .flags          = V4L2_FMT_FLAG_DYN_RESOLUTION,
-       },
-       {
-               .fourcc         = V4L2_PIX_FMT_VC1_ANNEX_G,
-               .codec_mode     = S5P_MFC_CODEC_VC1_DEC,
-               .type           = MFC_FMT_DEC,
-               .num_planes     = 1,
-               .versions       = MFC_V5PLUS_BITS,
-               .flags          = V4L2_FMT_FLAG_DYN_RESOLUTION,
-       },
-       {
-               .fourcc         = V4L2_PIX_FMT_VC1_ANNEX_L,
-               .codec_mode     = S5P_MFC_CODEC_VC1RCV_DEC,
-               .type           = MFC_FMT_DEC,
-               .num_planes     = 1,
-               .versions       = MFC_V5PLUS_BITS,
-               .flags          = V4L2_FMT_FLAG_DYN_RESOLUTION,
-       },
-       {
-               .fourcc         = V4L2_PIX_FMT_VP8,
-               .codec_mode     = S5P_MFC_CODEC_VP8_DEC,
-               .type           = MFC_FMT_DEC,
-               .num_planes     = 1,
-               .versions       = MFC_V6PLUS_BITS,
-               .flags          = V4L2_FMT_FLAG_DYN_RESOLUTION,
-       },
-       {
-               .fourcc         = V4L2_PIX_FMT_HEVC,
-               .codec_mode     = S5P_FIMV_CODEC_HEVC_DEC,
-               .type           = MFC_FMT_DEC,
-               .num_planes     = 1,
-               .versions       = MFC_V10_BIT,
-               .flags          = V4L2_FMT_FLAG_DYN_RESOLUTION |
-                                 V4L2_FMT_FLAG_CONTINUOUS_BYTESTREAM,
-       },
-       {
-               .fourcc         = V4L2_PIX_FMT_VP9,
-               .codec_mode     = S5P_FIMV_CODEC_VP9_DEC,
-               .type           = MFC_FMT_DEC,
-               .num_planes     = 1,
-               .versions       = MFC_V10_BIT,
-               .flags          = V4L2_FMT_FLAG_DYN_RESOLUTION,
-       },
-};
-
-#define NUM_FORMATS ARRAY_SIZE(formats)
-
-/* Find selected format description */
-static struct s5p_mfc_fmt *find_format(struct v4l2_format *f, unsigned int t)
-{
-       unsigned int i;
-
-       for (i = 0; i < NUM_FORMATS; i++) {
-               if (formats[i].fourcc == f->fmt.pix_mp.pixelformat &&
-                   formats[i].type == t)
-                       return &formats[i];
-       }
-       return NULL;
-}
-
-static struct mfc_control controls[] = {
-       {
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "H264 Display Delay",
-               .minimum = 0,
-               .maximum = 16383,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = 0,
-               .maximum = 16383,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY_ENABLE,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "H264 Display Delay Enable",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY_ENABLE,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .minimum = 0,
-               .maximum = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "Mpeg4 Loop Filter Enable",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "Slice Interface Enable",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Minimum number of cap bufs",
-               .minimum = 1,
-               .maximum = 32,
-               .step = 1,
-               .default_value = 1,
-               .is_volatile = 1,
-       },
-};
-
-#define NUM_CTRLS ARRAY_SIZE(controls)
-
-/* Check whether a context should be run on hardware */
-static int s5p_mfc_ctx_ready(struct s5p_mfc_ctx *ctx)
-{
-       /* Context is to parse header */
-       if (ctx->src_queue_cnt >= 1 && ctx->state == MFCINST_GOT_INST)
-               return 1;
-       /* Context is to decode a frame */
-       if (ctx->src_queue_cnt >= 1 &&
-           ctx->state == MFCINST_RUNNING &&
-           ctx->dst_queue_cnt >= ctx->pb_count)
-               return 1;
-       /* Context is to return last frame */
-       if (ctx->state == MFCINST_FINISHING &&
-           ctx->dst_queue_cnt >= ctx->pb_count)
-               return 1;
-       /* Context is to set buffers */
-       if (ctx->src_queue_cnt >= 1 &&
-           ctx->state == MFCINST_HEAD_PARSED &&
-           ctx->capture_state == QUEUE_BUFS_MMAPED)
-               return 1;
-       /* Resolution change */
-       if ((ctx->state == MFCINST_RES_CHANGE_INIT ||
-               ctx->state == MFCINST_RES_CHANGE_FLUSH) &&
-               ctx->dst_queue_cnt >= ctx->pb_count)
-               return 1;
-       if (ctx->state == MFCINST_RES_CHANGE_END &&
-               ctx->src_queue_cnt >= 1)
-               return 1;
-       mfc_debug(2, "ctx is not ready\n");
-       return 0;
-}
-
-static const struct s5p_mfc_codec_ops decoder_codec_ops = {
-       .pre_seq_start          = NULL,
-       .post_seq_start         = NULL,
-       .pre_frame_start        = NULL,
-       .post_frame_start       = NULL,
-};
-
-/* Query capabilities of the device */
-static int vidioc_querycap(struct file *file, void *priv,
-                          struct v4l2_capability *cap)
-{
-       struct s5p_mfc_dev *dev = video_drvdata(file);
-
-       strscpy(cap->driver, S5P_MFC_NAME, sizeof(cap->driver));
-       strscpy(cap->card, dev->vfd_dec->name, sizeof(cap->card));
-       snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
-                dev_name(&dev->plat_dev->dev));
-       return 0;
-}
-
-/* Enumerate format */
-static int vidioc_enum_fmt(struct file *file, struct v4l2_fmtdesc *f,
-                                                       bool out)
-{
-       struct s5p_mfc_dev *dev = video_drvdata(file);
-       int i, j = 0;
-
-       for (i = 0; i < ARRAY_SIZE(formats); ++i) {
-               if (out && formats[i].type != MFC_FMT_DEC)
-                       continue;
-               else if (!out && formats[i].type != MFC_FMT_RAW)
-                       continue;
-               else if ((dev->variant->version_bit & formats[i].versions) == 0)
-                       continue;
-
-               if (j == f->index)
-                       break;
-               ++j;
-       }
-       if (i == ARRAY_SIZE(formats))
-               return -EINVAL;
-       f->pixelformat = formats[i].fourcc;
-       return 0;
-}
-
-static int vidioc_enum_fmt_vid_cap(struct file *file, void *pirv,
-                                  struct v4l2_fmtdesc *f)
-{
-       return vidioc_enum_fmt(file, f, false);
-}
-
-static int vidioc_enum_fmt_vid_out(struct file *file, void *priv,
-                                  struct v4l2_fmtdesc *f)
-{
-       return vidioc_enum_fmt(file, f, true);
-}
-
-/* Get format */
-static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
-{
-       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
-       struct v4l2_pix_format_mplane *pix_mp;
-
-       mfc_debug_enter();
-       pix_mp = &f->fmt.pix_mp;
-       if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
-           (ctx->state == MFCINST_GOT_INST || ctx->state ==
-                                               MFCINST_RES_CHANGE_END)) {
-               /* If the MFC is parsing the header,
-                * so wait until it is finished */
-               s5p_mfc_wait_for_done_ctx(ctx, S5P_MFC_R2H_CMD_SEQ_DONE_RET,
-                                                                       0);
-       }
-       if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
-           ctx->state >= MFCINST_HEAD_PARSED &&
-           ctx->state < MFCINST_ABORT) {
-               /* This is run on CAPTURE (decode output) */
-               /* Width and height are set to the dimensions
-                  of the movie, the buffer is bigger and
-                  further processing stages should crop to this
-                  rectangle. */
-               pix_mp->width = ctx->buf_width;
-               pix_mp->height = ctx->buf_height;
-               pix_mp->field = V4L2_FIELD_NONE;
-               pix_mp->num_planes = 2;
-               /* Set pixelformat to the format in which MFC
-                  outputs the decoded frame */
-               pix_mp->pixelformat = ctx->dst_fmt->fourcc;
-               pix_mp->plane_fmt[0].bytesperline = ctx->buf_width;
-               pix_mp->plane_fmt[0].sizeimage = ctx->luma_size;
-               pix_mp->plane_fmt[1].bytesperline = ctx->buf_width;
-               pix_mp->plane_fmt[1].sizeimage = ctx->chroma_size;
-       } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               /* This is run on OUTPUT
-                  The buffer contains compressed image
-                  so width and height have no meaning */
-               pix_mp->width = 0;
-               pix_mp->height = 0;
-               pix_mp->field = V4L2_FIELD_NONE;
-               pix_mp->plane_fmt[0].bytesperline = ctx->dec_src_buf_size;
-               pix_mp->plane_fmt[0].sizeimage = ctx->dec_src_buf_size;
-               pix_mp->pixelformat = ctx->src_fmt->fourcc;
-               pix_mp->num_planes = ctx->src_fmt->num_planes;
-       } else {
-               mfc_err("Format could not be read\n");
-               mfc_debug(2, "%s-- with error\n", __func__);
-               return -EINVAL;
-       }
-       mfc_debug_leave();
-       return 0;
-}
-
-/* Try format */
-static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
-{
-       struct s5p_mfc_dev *dev = video_drvdata(file);
-       struct s5p_mfc_fmt *fmt;
-
-       mfc_debug(2, "Type is %d\n", f->type);
-       if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               fmt = find_format(f, MFC_FMT_DEC);
-               if (!fmt) {
-                       mfc_err("Unsupported format for source.\n");
-                       return -EINVAL;
-               }
-               if (fmt->codec_mode == S5P_FIMV_CODEC_NONE) {
-                       mfc_err("Unknown codec\n");
-                       return -EINVAL;
-               }
-               if ((dev->variant->version_bit & fmt->versions) == 0) {
-                       mfc_err("Unsupported format by this MFC version.\n");
-                       return -EINVAL;
-               }
-       } else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-               fmt = find_format(f, MFC_FMT_RAW);
-               if (!fmt) {
-                       mfc_err("Unsupported format for destination.\n");
-                       return -EINVAL;
-               }
-               if ((dev->variant->version_bit & fmt->versions) == 0) {
-                       mfc_err("Unsupported format by this MFC version.\n");
-                       return -EINVAL;
-               }
-       }
-
-       return 0;
-}
-
-/* Set format */
-static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
-{
-       struct s5p_mfc_dev *dev = video_drvdata(file);
-       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
-       int ret = 0;
-       struct v4l2_pix_format_mplane *pix_mp;
-       struct s5p_mfc_buf_size *buf_size = dev->variant->buf_size;
-
-       mfc_debug_enter();
-       ret = vidioc_try_fmt(file, priv, f);
-       pix_mp = &f->fmt.pix_mp;
-       if (ret)
-               return ret;
-       if (vb2_is_streaming(&ctx->vq_src) || vb2_is_streaming(&ctx->vq_dst)) {
-               v4l2_err(&dev->v4l2_dev, "%s queue busy\n", __func__);
-               ret = -EBUSY;
-               goto out;
-       }
-       if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-               /* dst_fmt is validated by call to vidioc_try_fmt */
-               ctx->dst_fmt = find_format(f, MFC_FMT_RAW);
-               ret = 0;
-               goto out;
-       } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               /* src_fmt is validated by call to vidioc_try_fmt */
-               ctx->src_fmt = find_format(f, MFC_FMT_DEC);
-               ctx->codec_mode = ctx->src_fmt->codec_mode;
-               mfc_debug(2, "The codec number is: %d\n", ctx->codec_mode);
-               pix_mp->height = 0;
-               pix_mp->width = 0;
-               if (pix_mp->plane_fmt[0].sizeimage == 0)
-                       pix_mp->plane_fmt[0].sizeimage = ctx->dec_src_buf_size =
-                                                               DEF_CPB_SIZE;
-               else if (pix_mp->plane_fmt[0].sizeimage > buf_size->cpb)
-                       ctx->dec_src_buf_size = buf_size->cpb;
-               else
-                       ctx->dec_src_buf_size = pix_mp->plane_fmt[0].sizeimage;
-               pix_mp->plane_fmt[0].bytesperline = 0;
-               ctx->state = MFCINST_INIT;
-               ret = 0;
-               goto out;
-       } else {
-               mfc_err("Wrong type error for S_FMT : %d", f->type);
-               ret = -EINVAL;
-               goto out;
-       }
-
-out:
-       mfc_debug_leave();
-       return ret;
-}
-
-static int reqbufs_output(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx,
-                               struct v4l2_requestbuffers *reqbufs)
-{
-       int ret = 0;
-
-       s5p_mfc_clock_on();
-
-       if (reqbufs->count == 0) {
-               mfc_debug(2, "Freeing buffers\n");
-               ret = vb2_reqbufs(&ctx->vq_src, reqbufs);
-               if (ret)
-                       goto out;
-               ctx->src_bufs_cnt = 0;
-               ctx->output_state = QUEUE_FREE;
-       } else if (ctx->output_state == QUEUE_FREE) {
-               /* Can only request buffers when we have a valid format set. */
-               WARN_ON(ctx->src_bufs_cnt != 0);
-               if (ctx->state != MFCINST_INIT) {
-                       mfc_err("Reqbufs called in an invalid state\n");
-                       ret = -EINVAL;
-                       goto out;
-               }
-
-               mfc_debug(2, "Allocating %d buffers for OUTPUT queue\n",
-                               reqbufs->count);
-               ret = vb2_reqbufs(&ctx->vq_src, reqbufs);
-               if (ret)
-                       goto out;
-
-               ret = s5p_mfc_open_mfc_inst(dev, ctx);
-               if (ret) {
-                       reqbufs->count = 0;
-                       vb2_reqbufs(&ctx->vq_src, reqbufs);
-                       goto out;
-               }
-
-               ctx->output_state = QUEUE_BUFS_REQUESTED;
-       } else {
-               mfc_err("Buffers have already been requested\n");
-               ret = -EINVAL;
-       }
-out:
-       s5p_mfc_clock_off();
-       if (ret)
-               mfc_err("Failed allocating buffers for OUTPUT queue\n");
-       return ret;
-}
-
-static int reqbufs_capture(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx,
-                               struct v4l2_requestbuffers *reqbufs)
-{
-       int ret = 0;
-
-       s5p_mfc_clock_on();
-
-       if (reqbufs->count == 0) {
-               mfc_debug(2, "Freeing buffers\n");
-               ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
-               if (ret)
-                       goto out;
-               s5p_mfc_hw_call(dev->mfc_ops, release_codec_buffers, ctx);
-               ctx->dst_bufs_cnt = 0;
-       } else if (ctx->capture_state == QUEUE_FREE) {
-               WARN_ON(ctx->dst_bufs_cnt != 0);
-               mfc_debug(2, "Allocating %d buffers for CAPTURE queue\n",
-                               reqbufs->count);
-               ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
-               if (ret)
-                       goto out;
-
-               ctx->capture_state = QUEUE_BUFS_REQUESTED;
-               ctx->total_dpb_count = reqbufs->count;
-
-               ret = s5p_mfc_hw_call(dev->mfc_ops, alloc_codec_buffers, ctx);
-               if (ret) {
-                       mfc_err("Failed to allocate decoding buffers\n");
-                       reqbufs->count = 0;
-                       vb2_reqbufs(&ctx->vq_dst, reqbufs);
-                       ret = -ENOMEM;
-                       ctx->capture_state = QUEUE_FREE;
-                       goto out;
-               }
-
-               WARN_ON(ctx->dst_bufs_cnt != ctx->total_dpb_count);
-               ctx->capture_state = QUEUE_BUFS_MMAPED;
-
-               if (s5p_mfc_ctx_ready(ctx))
-                       set_work_bit_irqsave(ctx);
-               s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
-               s5p_mfc_wait_for_done_ctx(ctx, S5P_MFC_R2H_CMD_INIT_BUFFERS_RET,
-                                         0);
-       } else {
-               mfc_err("Buffers have already been requested\n");
-               ret = -EINVAL;
-       }
-out:
-       s5p_mfc_clock_off();
-       if (ret)
-               mfc_err("Failed allocating buffers for CAPTURE queue\n");
-       return ret;
-}
-
-/* Request buffers */
-static int vidioc_reqbufs(struct file *file, void *priv,
-                                         struct v4l2_requestbuffers *reqbufs)
-{
-       struct s5p_mfc_dev *dev = video_drvdata(file);
-       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
-
-       if (reqbufs->memory != V4L2_MEMORY_MMAP) {
-               mfc_debug(2, "Only V4L2_MEMORY_MMAP is supported\n");
-               return -EINVAL;
-       }
-
-       if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               return reqbufs_output(dev, ctx, reqbufs);
-       } else if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-               return reqbufs_capture(dev, ctx, reqbufs);
-       } else {
-               mfc_err("Invalid type requested\n");
-               return -EINVAL;
-       }
-}
-
-/* Query buffer */
-static int vidioc_querybuf(struct file *file, void *priv,
-                                                  struct v4l2_buffer *buf)
-{
-       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
-       int ret;
-       int i;
-
-       if (buf->memory != V4L2_MEMORY_MMAP) {
-               mfc_err("Only mmapped buffers can be used\n");
-               return -EINVAL;
-       }
-       mfc_debug(2, "State: %d, buf->type: %d\n", ctx->state, buf->type);
-       if (ctx->state == MFCINST_GOT_INST &&
-                       buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               ret = vb2_querybuf(&ctx->vq_src, buf);
-       } else if (ctx->state == MFCINST_RUNNING &&
-                       buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-               ret = vb2_querybuf(&ctx->vq_dst, buf);
-               for (i = 0; i < buf->length; i++)
-                       buf->m.planes[i].m.mem_offset += DST_QUEUE_OFF_BASE;
-       } else {
-               mfc_err("vidioc_querybuf called in an inappropriate state\n");
-               ret = -EINVAL;
-       }
-       mfc_debug_leave();
-       return ret;
-}
-
-/* Queue a buffer */
-static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
-{
-       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
-
-       if (ctx->state == MFCINST_ERROR) {
-               mfc_err("Call on QBUF after unrecoverable error\n");
-               return -EIO;
-       }
-       if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
-               return vb2_qbuf(&ctx->vq_src, NULL, buf);
-       else if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
-               return vb2_qbuf(&ctx->vq_dst, NULL, buf);
-       return -EINVAL;
-}
-
-/* Dequeue a buffer */
-static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
-{
-       const struct v4l2_event ev = {
-               .type = V4L2_EVENT_EOS
-       };
-       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
-       int ret;
-
-       if (ctx->state == MFCINST_ERROR) {
-               mfc_err_limited("Call on DQBUF after unrecoverable error\n");
-               return -EIO;
-       }
-
-       switch (buf->type) {
-       case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
-               return vb2_dqbuf(&ctx->vq_src, buf, file->f_flags & O_NONBLOCK);
-       case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
-               ret = vb2_dqbuf(&ctx->vq_dst, buf, file->f_flags & O_NONBLOCK);
-               if (ret)
-                       return ret;
-
-               if (ctx->state == MFCINST_FINISHED &&
-                   (ctx->dst_bufs[buf->index].flags & MFC_BUF_FLAG_EOS))
-                       v4l2_event_queue_fh(&ctx->fh, &ev);
-               return 0;
-       default:
-               return -EINVAL;
-       }
-}
-
-/* Export DMA buffer */
-static int vidioc_expbuf(struct file *file, void *priv,
-       struct v4l2_exportbuffer *eb)
-{
-       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
-
-       if (eb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
-               return vb2_expbuf(&ctx->vq_src, eb);
-       if (eb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
-               return vb2_expbuf(&ctx->vq_dst, eb);
-       return -EINVAL;
-}
-
-/* Stream on */
-static int vidioc_streamon(struct file *file, void *priv,
-                          enum v4l2_buf_type type)
-{
-       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
-       int ret = -EINVAL;
-
-       mfc_debug_enter();
-       if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
-               ret = vb2_streamon(&ctx->vq_src, type);
-       else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
-               ret = vb2_streamon(&ctx->vq_dst, type);
-       mfc_debug_leave();
-       return ret;
-}
-
-/* Stream off, which equals to a pause */
-static int vidioc_streamoff(struct file *file, void *priv,
-                           enum v4l2_buf_type type)
-{
-       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
-
-       if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
-               return vb2_streamoff(&ctx->vq_src, type);
-       else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
-               return vb2_streamoff(&ctx->vq_dst, type);
-       return -EINVAL;
-}
-
-/* Set controls - v4l2 control framework */
-static int s5p_mfc_dec_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-       struct s5p_mfc_ctx *ctx = ctrl_to_ctx(ctrl);
-
-       switch (ctrl->id) {
-       case V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY:
-       case V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY:
-               ctx->display_delay = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY_ENABLE:
-       case V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY_ENABLE:
-               ctx->display_delay_enable = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER:
-               ctx->loop_filter_mpeg4 = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE:
-               ctx->slice_interface = ctrl->val;
-               break;
-       default:
-               mfc_err("Invalid control 0x%08x\n", ctrl->id);
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static int s5p_mfc_dec_g_v_ctrl(struct v4l2_ctrl *ctrl)
-{
-       struct s5p_mfc_ctx *ctx = ctrl_to_ctx(ctrl);
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       switch (ctrl->id) {
-       case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:
-               if (ctx->state >= MFCINST_HEAD_PARSED &&
-                   ctx->state < MFCINST_ABORT) {
-                       ctrl->val = ctx->pb_count;
-                       break;
-               } else if (ctx->state != MFCINST_INIT &&
-                               ctx->state != MFCINST_RES_CHANGE_END) {
-                       v4l2_err(&dev->v4l2_dev, "Decoding not initialised\n");
-                       return -EINVAL;
-               }
-               /* Should wait for the header to be parsed */
-               s5p_mfc_wait_for_done_ctx(ctx,
-                               S5P_MFC_R2H_CMD_SEQ_DONE_RET, 0);
-               if (ctx->state >= MFCINST_HEAD_PARSED &&
-                   ctx->state < MFCINST_ABORT) {
-                       ctrl->val = ctx->pb_count;
-               } else {
-                       v4l2_err(&dev->v4l2_dev, "Decoding not initialised\n");
-                       return -EINVAL;
-               }
-               break;
-       }
-       return 0;
-}
-
-
-static const struct v4l2_ctrl_ops s5p_mfc_dec_ctrl_ops = {
-       .s_ctrl = s5p_mfc_dec_s_ctrl,
-       .g_volatile_ctrl = s5p_mfc_dec_g_v_ctrl,
-};
-
-/* Get compose information */
-static int vidioc_g_selection(struct file *file, void *priv,
-                             struct v4l2_selection *s)
-{
-       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
-       struct s5p_mfc_dev *dev = ctx->dev;
-       u32 left, right, top, bottom;
-       u32 width, height;
-
-       if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-
-       if (ctx->state != MFCINST_HEAD_PARSED &&
-           ctx->state != MFCINST_RUNNING &&
-           ctx->state != MFCINST_FINISHING &&
-           ctx->state != MFCINST_FINISHED) {
-               mfc_err("Can not get compose information\n");
-               return -EINVAL;
-       }
-       if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_H264) {
-               left = s5p_mfc_hw_call(dev->mfc_ops, get_crop_info_h, ctx);
-               right = left >> S5P_FIMV_SHARED_CROP_RIGHT_SHIFT;
-               left = left & S5P_FIMV_SHARED_CROP_LEFT_MASK;
-               top = s5p_mfc_hw_call(dev->mfc_ops, get_crop_info_v, ctx);
-               bottom = top >> S5P_FIMV_SHARED_CROP_BOTTOM_SHIFT;
-               top = top & S5P_FIMV_SHARED_CROP_TOP_MASK;
-               width = ctx->img_width - left - right;
-               height = ctx->img_height - top - bottom;
-               mfc_debug(2, "Composing info [h264]: l=%d t=%d w=%d h=%d (r=%d b=%d fw=%d fh=%d\n",
-                         left, top, s->r.width, s->r.height, right, bottom,
-                         ctx->buf_width, ctx->buf_height);
-       } else {
-               left = 0;
-               top = 0;
-               width = ctx->img_width;
-               height = ctx->img_height;
-               mfc_debug(2, "Composing info: w=%d h=%d fw=%d fh=%d\n",
-                         s->r.width, s->r.height, ctx->buf_width,
-                         ctx->buf_height);
-       }
-
-       switch (s->target) {
-       case V4L2_SEL_TGT_COMPOSE:
-       case V4L2_SEL_TGT_COMPOSE_DEFAULT:
-       case V4L2_SEL_TGT_COMPOSE_BOUNDS:
-               s->r.left = left;
-               s->r.top = top;
-               s->r.width = width;
-               s->r.height = height;
-               break;
-       default:
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static int vidioc_decoder_cmd(struct file *file, void *priv,
-                             struct v4l2_decoder_cmd *cmd)
-{
-       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_buf *buf;
-       unsigned long flags;
-
-       switch (cmd->cmd) {
-       case V4L2_DEC_CMD_STOP:
-               if (cmd->flags != 0)
-                       return -EINVAL;
-
-               if (!vb2_is_streaming(&ctx->vq_src))
-                       return -EINVAL;
-
-               spin_lock_irqsave(&dev->irqlock, flags);
-               if (list_empty(&ctx->src_queue)) {
-                       mfc_err("EOS: empty src queue, entering finishing state");
-                       ctx->state = MFCINST_FINISHING;
-                       if (s5p_mfc_ctx_ready(ctx))
-                               set_work_bit_irqsave(ctx);
-                       spin_unlock_irqrestore(&dev->irqlock, flags);
-                       s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
-               } else {
-                       mfc_err("EOS: marking last buffer of stream");
-                       buf = list_entry(ctx->src_queue.prev,
-                                               struct s5p_mfc_buf, list);
-                       if (buf->flags & MFC_BUF_FLAG_USED)
-                               ctx->state = MFCINST_FINISHING;
-                       else
-                               buf->flags |= MFC_BUF_FLAG_EOS;
-                       spin_unlock_irqrestore(&dev->irqlock, flags);
-               }
-               break;
-       default:
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static int vidioc_subscribe_event(struct v4l2_fh *fh,
-                               const struct  v4l2_event_subscription *sub)
-{
-       switch (sub->type) {
-       case V4L2_EVENT_EOS:
-               return v4l2_event_subscribe(fh, sub, 2, NULL);
-       case V4L2_EVENT_SOURCE_CHANGE:
-               return v4l2_src_change_event_subscribe(fh, sub);
-       default:
-               return -EINVAL;
-       }
-}
-
-
-/* v4l2_ioctl_ops */
-static const struct v4l2_ioctl_ops s5p_mfc_dec_ioctl_ops = {
-       .vidioc_querycap = vidioc_querycap,
-       .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
-       .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out,
-       .vidioc_g_fmt_vid_cap_mplane = vidioc_g_fmt,
-       .vidioc_g_fmt_vid_out_mplane = vidioc_g_fmt,
-       .vidioc_try_fmt_vid_cap_mplane = vidioc_try_fmt,
-       .vidioc_try_fmt_vid_out_mplane = vidioc_try_fmt,
-       .vidioc_s_fmt_vid_cap_mplane = vidioc_s_fmt,
-       .vidioc_s_fmt_vid_out_mplane = vidioc_s_fmt,
-       .vidioc_reqbufs = vidioc_reqbufs,
-       .vidioc_querybuf = vidioc_querybuf,
-       .vidioc_qbuf = vidioc_qbuf,
-       .vidioc_dqbuf = vidioc_dqbuf,
-       .vidioc_expbuf = vidioc_expbuf,
-       .vidioc_streamon = vidioc_streamon,
-       .vidioc_streamoff = vidioc_streamoff,
-       .vidioc_g_selection = vidioc_g_selection,
-       .vidioc_decoder_cmd = vidioc_decoder_cmd,
-       .vidioc_subscribe_event = vidioc_subscribe_event,
-       .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
-};
-
-static int s5p_mfc_queue_setup(struct vb2_queue *vq,
-                       unsigned int *buf_count,
-                       unsigned int *plane_count, unsigned int psize[],
-                       struct device *alloc_devs[])
-{
-       struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       /* Video output for decoding (source)
-        * this can be set after getting an instance */
-       if (ctx->state == MFCINST_INIT &&
-           vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               /* A single plane is required for input */
-               *plane_count = 1;
-               if (*buf_count < 1)
-                       *buf_count = 1;
-               if (*buf_count > MFC_MAX_BUFFERS)
-                       *buf_count = MFC_MAX_BUFFERS;
-       /* Video capture for decoding (destination)
-        * this can be set after the header was parsed */
-       } else if (ctx->state == MFCINST_HEAD_PARSED &&
-                  vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-               /* Output plane count is 2 - one for Y and one for CbCr */
-               *plane_count = 2;
-               /* Setup buffer count */
-               if (*buf_count < ctx->pb_count)
-                       *buf_count = ctx->pb_count;
-               if (*buf_count > ctx->pb_count + MFC_MAX_EXTRA_DPB)
-                       *buf_count = ctx->pb_count + MFC_MAX_EXTRA_DPB;
-               if (*buf_count > MFC_MAX_BUFFERS)
-                       *buf_count = MFC_MAX_BUFFERS;
-       } else {
-               mfc_err("State seems invalid. State = %d, vq->type = %d\n",
-                                                       ctx->state, vq->type);
-               return -EINVAL;
-       }
-       mfc_debug(2, "Buffer count=%d, plane count=%d\n",
-                                               *buf_count, *plane_count);
-       if (ctx->state == MFCINST_HEAD_PARSED &&
-           vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-               psize[0] = ctx->luma_size;
-               psize[1] = ctx->chroma_size;
-
-               if (IS_MFCV6_PLUS(dev))
-                       alloc_devs[0] = ctx->dev->mem_dev[BANK_L_CTX];
-               else
-                       alloc_devs[0] = ctx->dev->mem_dev[BANK_R_CTX];
-               alloc_devs[1] = ctx->dev->mem_dev[BANK_L_CTX];
-       } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
-                  ctx->state == MFCINST_INIT) {
-               psize[0] = ctx->dec_src_buf_size;
-               alloc_devs[0] = ctx->dev->mem_dev[BANK_L_CTX];
-       } else {
-               mfc_err("This video node is dedicated to decoding. Decoding not initialized\n");
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static int s5p_mfc_buf_init(struct vb2_buffer *vb)
-{
-       struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
-       struct vb2_queue *vq = vb->vb2_queue;
-       struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
-       unsigned int i;
-
-       if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-               if (ctx->capture_state == QUEUE_BUFS_MMAPED)
-                       return 0;
-               for (i = 0; i < ctx->dst_fmt->num_planes; i++) {
-                       if (IS_ERR_OR_NULL(ERR_PTR(
-                                       vb2_dma_contig_plane_dma_addr(vb, i)))) {
-                               mfc_err("Plane mem not allocated\n");
-                               return -EINVAL;
-                       }
-               }
-               if (vb2_plane_size(vb, 0) < ctx->luma_size ||
-                       vb2_plane_size(vb, 1) < ctx->chroma_size) {
-                       mfc_err("Plane buffer (CAPTURE) is too small\n");
-                       return -EINVAL;
-               }
-               i = vb->index;
-               ctx->dst_bufs[i].b = vbuf;
-               ctx->dst_bufs[i].cookie.raw.luma =
-                                       vb2_dma_contig_plane_dma_addr(vb, 0);
-               ctx->dst_bufs[i].cookie.raw.chroma =
-                                       vb2_dma_contig_plane_dma_addr(vb, 1);
-               ctx->dst_bufs_cnt++;
-       } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               if (IS_ERR_OR_NULL(ERR_PTR(
-                                       vb2_dma_contig_plane_dma_addr(vb, 0)))) {
-                       mfc_err("Plane memory not allocated\n");
-                       return -EINVAL;
-               }
-               if (vb2_plane_size(vb, 0) < ctx->dec_src_buf_size) {
-                       mfc_err("Plane buffer (OUTPUT) is too small\n");
-                       return -EINVAL;
-               }
-
-               i = vb->index;
-               ctx->src_bufs[i].b = vbuf;
-               ctx->src_bufs[i].cookie.stream =
-                                       vb2_dma_contig_plane_dma_addr(vb, 0);
-               ctx->src_bufs_cnt++;
-       } else {
-               mfc_err("s5p_mfc_buf_init: unknown queue type\n");
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static int s5p_mfc_start_streaming(struct vb2_queue *q, unsigned int count)
-{
-       struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv);
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       v4l2_ctrl_handler_setup(&ctx->ctrl_handler);
-       if (ctx->state == MFCINST_FINISHING ||
-               ctx->state == MFCINST_FINISHED)
-               ctx->state = MFCINST_RUNNING;
-       /* If context is ready then dev = work->data;schedule it to run */
-       if (s5p_mfc_ctx_ready(ctx))
-               set_work_bit_irqsave(ctx);
-       s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
-       return 0;
-}
-
-static void s5p_mfc_stop_streaming(struct vb2_queue *q)
-{
-       unsigned long flags;
-       struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv);
-       struct s5p_mfc_dev *dev = ctx->dev;
-       int aborted = 0;
-
-       spin_lock_irqsave(&dev->irqlock, flags);
-       if ((ctx->state == MFCINST_FINISHING ||
-               ctx->state ==  MFCINST_RUNNING) &&
-               dev->curr_ctx == ctx->num && dev->hw_lock) {
-               ctx->state = MFCINST_ABORT;
-               spin_unlock_irqrestore(&dev->irqlock, flags);
-               s5p_mfc_wait_for_done_ctx(ctx,
-                                       S5P_MFC_R2H_CMD_FRAME_DONE_RET, 0);
-               aborted = 1;
-               spin_lock_irqsave(&dev->irqlock, flags);
-       }
-       if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-               s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst);
-               INIT_LIST_HEAD(&ctx->dst_queue);
-               ctx->dst_queue_cnt = 0;
-               ctx->dpb_flush_flag = 1;
-               ctx->dec_dst_flag = 0;
-               if (IS_MFCV6_PLUS(dev) && (ctx->state == MFCINST_RUNNING)) {
-                       ctx->state = MFCINST_FLUSH;
-                       set_work_bit_irqsave(ctx);
-                       s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
-                       spin_unlock_irqrestore(&dev->irqlock, flags);
-                       if (s5p_mfc_wait_for_done_ctx(ctx,
-                               S5P_MFC_R2H_CMD_DPB_FLUSH_RET, 0))
-                               mfc_err("Err flushing buffers\n");
-                       spin_lock_irqsave(&dev->irqlock, flags);
-               }
-       } else if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src);
-               INIT_LIST_HEAD(&ctx->src_queue);
-               ctx->src_queue_cnt = 0;
-       }
-       if (aborted)
-               ctx->state = MFCINST_RUNNING;
-       spin_unlock_irqrestore(&dev->irqlock, flags);
-}
-
-
-static void s5p_mfc_buf_queue(struct vb2_buffer *vb)
-{
-       struct vb2_queue *vq = vb->vb2_queue;
-       struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
-       struct s5p_mfc_dev *dev = ctx->dev;
-       unsigned long flags;
-       struct s5p_mfc_buf *mfc_buf;
-
-       if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               mfc_buf = &ctx->src_bufs[vb->index];
-               mfc_buf->flags &= ~MFC_BUF_FLAG_USED;
-               spin_lock_irqsave(&dev->irqlock, flags);
-               list_add_tail(&mfc_buf->list, &ctx->src_queue);
-               ctx->src_queue_cnt++;
-               spin_unlock_irqrestore(&dev->irqlock, flags);
-       } else if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-               mfc_buf = &ctx->dst_bufs[vb->index];
-               mfc_buf->flags &= ~MFC_BUF_FLAG_USED;
-               /* Mark destination as available for use by MFC */
-               spin_lock_irqsave(&dev->irqlock, flags);
-               set_bit(vb->index, &ctx->dec_dst_flag);
-               list_add_tail(&mfc_buf->list, &ctx->dst_queue);
-               ctx->dst_queue_cnt++;
-               spin_unlock_irqrestore(&dev->irqlock, flags);
-       } else {
-               mfc_err("Unsupported buffer type (%d)\n", vq->type);
-       }
-       if (s5p_mfc_ctx_ready(ctx))
-               set_work_bit_irqsave(ctx);
-       s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
-}
-
-static struct vb2_ops s5p_mfc_dec_qops = {
-       .queue_setup            = s5p_mfc_queue_setup,
-       .wait_prepare           = vb2_ops_wait_prepare,
-       .wait_finish            = vb2_ops_wait_finish,
-       .buf_init               = s5p_mfc_buf_init,
-       .start_streaming        = s5p_mfc_start_streaming,
-       .stop_streaming         = s5p_mfc_stop_streaming,
-       .buf_queue              = s5p_mfc_buf_queue,
-};
-
-const struct s5p_mfc_codec_ops *get_dec_codec_ops(void)
-{
-       return &decoder_codec_ops;
-}
-
-struct vb2_ops *get_dec_queue_ops(void)
-{
-       return &s5p_mfc_dec_qops;
-}
-
-const struct v4l2_ioctl_ops *get_dec_v4l2_ioctl_ops(void)
-{
-       return &s5p_mfc_dec_ioctl_ops;
-}
-
-#define IS_MFC51_PRIV(x) ((V4L2_CTRL_ID2WHICH(x) == V4L2_CTRL_CLASS_CODEC) \
-                                               && V4L2_CTRL_DRIVER_PRIV(x))
-
-int s5p_mfc_dec_ctrls_setup(struct s5p_mfc_ctx *ctx)
-{
-       struct v4l2_ctrl_config cfg;
-       int i;
-
-       v4l2_ctrl_handler_init(&ctx->ctrl_handler, NUM_CTRLS);
-       if (ctx->ctrl_handler.error) {
-               mfc_err("v4l2_ctrl_handler_init failed\n");
-               return ctx->ctrl_handler.error;
-       }
-
-       for (i = 0; i < NUM_CTRLS; i++) {
-               if (IS_MFC51_PRIV(controls[i].id)) {
-                       memset(&cfg, 0, sizeof(struct v4l2_ctrl_config));
-                       cfg.ops = &s5p_mfc_dec_ctrl_ops;
-                       cfg.id = controls[i].id;
-                       cfg.min = controls[i].minimum;
-                       cfg.max = controls[i].maximum;
-                       cfg.def = controls[i].default_value;
-                       cfg.name = controls[i].name;
-                       cfg.type = controls[i].type;
-
-                       cfg.step = controls[i].step;
-                       cfg.menu_skip_mask = 0;
-
-                       ctx->ctrls[i] = v4l2_ctrl_new_custom(&ctx->ctrl_handler,
-                                       &cfg, NULL);
-               } else {
-                       ctx->ctrls[i] = v4l2_ctrl_new_std(&ctx->ctrl_handler,
-                                       &s5p_mfc_dec_ctrl_ops,
-                                       controls[i].id, controls[i].minimum,
-                                       controls[i].maximum, controls[i].step,
-                                       controls[i].default_value);
-               }
-               if (ctx->ctrl_handler.error) {
-                       mfc_err("Adding control (%d) failed\n", i);
-                       return ctx->ctrl_handler.error;
-               }
-               if (controls[i].is_volatile && ctx->ctrls[i])
-                       ctx->ctrls[i]->flags |= V4L2_CTRL_FLAG_VOLATILE;
-       }
-       return 0;
-}
-
-void s5p_mfc_dec_ctrls_delete(struct s5p_mfc_ctx *ctx)
-{
-       int i;
-
-       v4l2_ctrl_handler_free(&ctx->ctrl_handler);
-       for (i = 0; i < NUM_CTRLS; i++)
-               ctx->ctrls[i] = NULL;
-}
-
-void s5p_mfc_dec_init(struct s5p_mfc_ctx *ctx)
-{
-       struct v4l2_format f;
-       f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264;
-       ctx->src_fmt = find_format(&f, MFC_FMT_DEC);
-       if (IS_MFCV8_PLUS(ctx->dev))
-               f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12M;
-       else if (IS_MFCV6_PLUS(ctx->dev))
-               f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12MT_16X16;
-       else
-               f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12MT;
-       ctx->dst_fmt = find_format(&f, MFC_FMT_RAW);
-       mfc_debug(2, "Default src_fmt is %p, dest_fmt is %p\n",
-                       ctx->src_fmt, ctx->dst_fmt);
-}
-
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.h b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.h
deleted file mode 100644 (file)
index 0e9a0e3..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * linux/drivers/media/platform/s5p-mfc/s5p_mfc_dec.h
- *
- * Copyright (C) 2011 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- */
-
-#ifndef S5P_MFC_DEC_H_
-#define S5P_MFC_DEC_H_
-
-const struct s5p_mfc_codec_ops *get_dec_codec_ops(void);
-struct vb2_ops *get_dec_queue_ops(void);
-const struct v4l2_ioctl_ops *get_dec_v4l2_ioctl_ops(void);
-struct s5p_mfc_fmt *get_dec_def_fmt(bool src);
-int s5p_mfc_dec_ctrls_setup(struct s5p_mfc_ctx *ctx);
-void s5p_mfc_dec_ctrls_delete(struct s5p_mfc_ctx *ctx);
-void s5p_mfc_dec_init(struct s5p_mfc_ctx *ctx);
-
-#endif /* S5P_MFC_DEC_H_ */
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
deleted file mode 100644 (file)
index 1fad99e..0000000
+++ /dev/null
@@ -1,2697 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * linux/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * Jeongtae Park       <jtp.park@samsung.com>
- * Kamil Debski                <k.debski@samsung.com>
- */
-
-#include <linux/clk.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/sched.h>
-#include <linux/videodev2.h>
-#include <media/v4l2-event.h>
-#include <linux/workqueue.h>
-#include <media/v4l2-ctrls.h>
-#include <media/videobuf2-v4l2.h>
-#include "s5p_mfc_common.h"
-#include "s5p_mfc_ctrl.h"
-#include "s5p_mfc_debug.h"
-#include "s5p_mfc_enc.h"
-#include "s5p_mfc_intr.h"
-#include "s5p_mfc_opr.h"
-
-#define DEF_SRC_FMT_ENC        V4L2_PIX_FMT_NV12M
-#define DEF_DST_FMT_ENC        V4L2_PIX_FMT_H264
-
-static struct s5p_mfc_fmt formats[] = {
-       {
-               .fourcc         = V4L2_PIX_FMT_NV12MT_16X16,
-               .codec_mode     = S5P_MFC_CODEC_NONE,
-               .type           = MFC_FMT_RAW,
-               .num_planes     = 2,
-               .versions       = MFC_V6_BIT | MFC_V7_BIT,
-       },
-       {
-               .fourcc         = V4L2_PIX_FMT_NV12MT,
-               .codec_mode     = S5P_MFC_CODEC_NONE,
-               .type           = MFC_FMT_RAW,
-               .num_planes     = 2,
-               .versions       = MFC_V5_BIT,
-       },
-       {
-               .fourcc         = V4L2_PIX_FMT_NV12M,
-               .codec_mode     = S5P_MFC_CODEC_NONE,
-               .type           = MFC_FMT_RAW,
-               .num_planes     = 2,
-               .versions       = MFC_V5PLUS_BITS,
-       },
-       {
-               .fourcc         = V4L2_PIX_FMT_NV21M,
-               .codec_mode     = S5P_MFC_CODEC_NONE,
-               .type           = MFC_FMT_RAW,
-               .num_planes     = 2,
-               .versions       = MFC_V6PLUS_BITS,
-       },
-       {
-               .fourcc         = V4L2_PIX_FMT_H264,
-               .codec_mode     = S5P_MFC_CODEC_H264_ENC,
-               .type           = MFC_FMT_ENC,
-               .num_planes     = 1,
-               .versions       = MFC_V5PLUS_BITS,
-       },
-       {
-               .fourcc         = V4L2_PIX_FMT_MPEG4,
-               .codec_mode     = S5P_MFC_CODEC_MPEG4_ENC,
-               .type           = MFC_FMT_ENC,
-               .num_planes     = 1,
-               .versions       = MFC_V5PLUS_BITS,
-       },
-       {
-               .fourcc         = V4L2_PIX_FMT_H263,
-               .codec_mode     = S5P_MFC_CODEC_H263_ENC,
-               .type           = MFC_FMT_ENC,
-               .num_planes     = 1,
-               .versions       = MFC_V5PLUS_BITS,
-       },
-       {
-               .fourcc         = V4L2_PIX_FMT_VP8,
-               .codec_mode     = S5P_MFC_CODEC_VP8_ENC,
-               .type           = MFC_FMT_ENC,
-               .num_planes     = 1,
-               .versions       = MFC_V7PLUS_BITS,
-       },
-       {
-               .fourcc         = V4L2_PIX_FMT_HEVC,
-               .codec_mode     = S5P_FIMV_CODEC_HEVC_ENC,
-               .type           = MFC_FMT_ENC,
-               .num_planes     = 1,
-               .versions       = MFC_V10_BIT,
-       },
-};
-
-#define NUM_FORMATS ARRAY_SIZE(formats)
-static struct s5p_mfc_fmt *find_format(struct v4l2_format *f, unsigned int t)
-{
-       unsigned int i;
-
-       for (i = 0; i < NUM_FORMATS; i++) {
-               if (formats[i].fourcc == f->fmt.pix_mp.pixelformat &&
-                   formats[i].type == t)
-                       return &formats[i];
-       }
-       return NULL;
-}
-
-static struct mfc_control controls[] = {
-       {
-               .id = V4L2_CID_MPEG_VIDEO_GOP_SIZE,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = 0,
-               .maximum = (1 << 16) - 1,
-               .step = 1,
-               .default_value = 12,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE,
-               .type = V4L2_CTRL_TYPE_MENU,
-               .minimum = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE,
-               .maximum = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES,
-               .default_value = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE,
-               .menu_skip_mask = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = 1,
-               .maximum = (1 << 16) - 1,
-               .step = 1,
-               .default_value = 1,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = 1900,
-               .maximum = (1 << 30) - 1,
-               .step = 1,
-               .default_value = 1900,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = 0,
-               .maximum = (1 << 16) - 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_PADDING,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "Padding Control Enable",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_PADDING_YUV,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Padding Color YUV Value",
-               .minimum = 0,
-               .maximum = (1 << 25) - 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_BITRATE,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = 1,
-               .maximum = (1 << 30) - 1,
-               .step = 1,
-               .default_value = 1,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_RC_REACTION_COEFF,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Rate Control Reaction Coeff.",
-               .minimum = 1,
-               .maximum = (1 << 16) - 1,
-               .step = 1,
-               .default_value = 1,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE,
-               .type = V4L2_CTRL_TYPE_MENU,
-               .name = "Force frame type",
-               .minimum = V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_DISABLED,
-               .maximum = V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_NOT_CODED,
-               .default_value = V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_DISABLED,
-               .menu_skip_mask = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME,
-               .type = V4L2_CTRL_TYPE_BUTTON,
-               .minimum = 0,
-               .maximum = 0,
-               .step = 0,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_VBV_SIZE,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = 0,
-               .maximum = (1 << 16) - 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_MV_H_SEARCH_RANGE,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Horizontal MV Search Range",
-               .minimum = 16,
-               .maximum = 128,
-               .step = 16,
-               .default_value = 32,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_MV_V_SEARCH_RANGE,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Vertical MV Search Range",
-               .minimum = 16,
-               .maximum = 128,
-               .step = 16,
-               .default_value = 32,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = 0,
-               .maximum = (1 << 16) - 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEADER_MODE,
-               .type = V4L2_CTRL_TYPE_MENU,
-               .minimum = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE,
-               .maximum = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME,
-               .default_value = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE,
-               .menu_skip_mask = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE,
-               .type = V4L2_CTRL_TYPE_MENU,
-               .name = "Frame Skip Enable",
-               .minimum = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_DISABLED,
-               .maximum = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT,
-               .menu_skip_mask = 0,
-               .default_value = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_DISABLED,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_FRAME_SKIP_MODE,
-               .type = V4L2_CTRL_TYPE_MENU,
-               .maximum = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT,
-               .default_value = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_RC_FIXED_TARGET_BIT,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "Fixed Target Bit Enable",
-               .minimum = 0,
-               .maximum = 1,
-               .default_value = 0,
-               .step = 1,
-               .menu_skip_mask = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_B_FRAMES,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = 0,
-               .maximum = 2,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_PROFILE,
-               .type = V4L2_CTRL_TYPE_MENU,
-               .minimum = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE,
-               .maximum = V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH,
-               .default_value = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE,
-               .menu_skip_mask = ~(
-                               (1 << V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) |
-                               (1 << V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) |
-                               (1 << V4L2_MPEG_VIDEO_H264_PROFILE_HIGH)
-                               ),
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_LEVEL,
-               .type = V4L2_CTRL_TYPE_MENU,
-               .minimum = V4L2_MPEG_VIDEO_H264_LEVEL_1_0,
-               .maximum = V4L2_MPEG_VIDEO_H264_LEVEL_4_0,
-               .default_value = V4L2_MPEG_VIDEO_H264_LEVEL_1_0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL,
-               .type = V4L2_CTRL_TYPE_MENU,
-               .minimum = V4L2_MPEG_VIDEO_MPEG4_LEVEL_0,
-               .maximum = V4L2_MPEG_VIDEO_MPEG4_LEVEL_5,
-               .default_value = V4L2_MPEG_VIDEO_MPEG4_LEVEL_0,
-               .menu_skip_mask = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE,
-               .type = V4L2_CTRL_TYPE_MENU,
-               .minimum = V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED,
-               .maximum = V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY,
-               .default_value = V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED,
-               .menu_skip_mask = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = -6,
-               .maximum = 6,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = -6,
-               .maximum = 6,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE,
-               .type = V4L2_CTRL_TYPE_MENU,
-               .minimum = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC,
-               .maximum = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC,
-               .default_value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC,
-               .menu_skip_mask = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_H264_NUM_REF_PIC_FOR_P,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "The Number of Ref. Pic for P",
-               .minimum = 1,
-               .maximum = 2,
-               .step = 1,
-               .default_value = 1,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = 0,
-               .maximum = 51,
-               .step = 1,
-               .default_value = 1,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_MIN_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = 0,
-               .maximum = 51,
-               .step = 1,
-               .default_value = 1,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_MAX_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = 0,
-               .maximum = 51,
-               .step = 1,
-               .default_value = 51,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = 0,
-               .maximum = 51,
-               .step = 1,
-               .default_value = 1,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = 0,
-               .maximum = 51,
-               .step = 1,
-               .default_value = 1,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "H263 I-Frame QP value",
-               .minimum = 1,
-               .maximum = 31,
-               .step = 1,
-               .default_value = 1,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H263_MIN_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "H263 Minimum QP value",
-               .minimum = 1,
-               .maximum = 31,
-               .step = 1,
-               .default_value = 1,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H263_MAX_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "H263 Maximum QP value",
-               .minimum = 1,
-               .maximum = 31,
-               .step = 1,
-               .default_value = 31,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "H263 P frame QP value",
-               .minimum = 1,
-               .maximum = 31,
-               .step = 1,
-               .default_value = 1,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "H263 B frame QP value",
-               .minimum = 1,
-               .maximum = 31,
-               .step = 1,
-               .default_value = 1,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "MPEG4 I-Frame QP value",
-               .minimum = 1,
-               .maximum = 31,
-               .step = 1,
-               .default_value = 1,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "MPEG4 Minimum QP value",
-               .minimum = 1,
-               .maximum = 31,
-               .step = 1,
-               .default_value = 1,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "MPEG4 Maximum QP value",
-               .minimum = 0,
-               .maximum = 51,
-               .step = 1,
-               .default_value = 51,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "MPEG4 P frame QP value",
-               .minimum = 1,
-               .maximum = 31,
-               .step = 1,
-               .default_value = 1,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "MPEG4 B frame QP value",
-               .minimum = 1,
-               .maximum = 31,
-               .step = 1,
-               .default_value = 1,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_DARK,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "H264 Dark Reg Adaptive RC",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_SMOOTH,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "H264 Smooth Reg Adaptive RC",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_STATIC,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "H264 Static Reg Adaptive RC",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_ACTIVITY,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "H264 Activity Reg Adaptive RC",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC,
-               .type = V4L2_CTRL_TYPE_MENU,
-               .minimum = V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_UNSPECIFIED,
-               .maximum = V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_EXTENDED,
-               .default_value = V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_UNSPECIFIED,
-               .menu_skip_mask = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = 0,
-               .maximum = (1 << 16) - 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_HEIGHT,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = 0,
-               .maximum = (1 << 16) - 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_GOP_CLOSURE,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 1,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_I_PERIOD,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = 0,
-               .maximum = (1 << 16) - 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE,
-               .type = V4L2_CTRL_TYPE_MENU,
-               .minimum = V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE,
-               .maximum = V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE,
-               .default_value = V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE,
-               .menu_skip_mask = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_MPEG4_QPEL,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_VPX_NUM_PARTITIONS,
-               .type = V4L2_CTRL_TYPE_INTEGER_MENU,
-               .maximum = V4L2_CID_MPEG_VIDEO_VPX_8_PARTITIONS,
-               .default_value = V4L2_CID_MPEG_VIDEO_VPX_1_PARTITION,
-               .menu_skip_mask = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_VPX_IMD_DISABLE_4X4,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_VPX_NUM_REF_FRAMES,
-               .type = V4L2_CTRL_TYPE_INTEGER_MENU,
-               .maximum = V4L2_CID_MPEG_VIDEO_VPX_2_REF_FRAME,
-               .default_value = V4L2_CID_MPEG_VIDEO_VPX_1_REF_FRAME,
-               .menu_skip_mask = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_VPX_FILTER_LEVEL,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = 0,
-               .maximum = 63,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_VPX_FILTER_SHARPNESS,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = 0,
-               .maximum = 7,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_REF_PERIOD,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = 0,
-               .maximum = (1 << 16) - 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_SEL,
-               .type = V4L2_CTRL_TYPE_MENU,
-               .minimum = V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_USE_PREV,
-               .maximum = V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_USE_REF_PERIOD,
-               .default_value = V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_USE_PREV,
-               .menu_skip_mask = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_VPX_MAX_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = 0,
-               .maximum = 127,
-               .step = 1,
-               .default_value = 127,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_VPX_MIN_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = 0,
-               .maximum = 11,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_VPX_I_FRAME_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = 0,
-               .maximum = 127,
-               .step = 1,
-               .default_value = 10,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_VPX_P_FRAME_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = 0,
-               .maximum = 127,
-               .step = 1,
-               .default_value = 10,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_VP8_PROFILE,
-               .type = V4L2_CTRL_TYPE_MENU,
-               .minimum = V4L2_MPEG_VIDEO_VP8_PROFILE_0,
-               .maximum = V4L2_MPEG_VIDEO_VP8_PROFILE_3,
-               .default_value = V4L2_MPEG_VIDEO_VP8_PROFILE_0,
-               .menu_skip_mask = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "HEVC I Frame QP Value",
-               .minimum = 0,
-               .maximum = 51,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "HEVC P Frame QP Value",
-               .minimum = 0,
-               .maximum = 51,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = 0,
-               .maximum = 51,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = 0,
-               .maximum = 51,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = 0,
-               .maximum = 51,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_PROFILE,
-               .type = V4L2_CTRL_TYPE_MENU,
-               .minimum = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN,
-               .maximum = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE,
-               .step = 1,
-               .default_value = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_LEVEL,
-               .type = V4L2_CTRL_TYPE_MENU,
-               .minimum = V4L2_MPEG_VIDEO_HEVC_LEVEL_1,
-               .maximum = V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2,
-               .step = 1,
-               .default_value = V4L2_MPEG_VIDEO_HEVC_LEVEL_1,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_TIER,
-               .type = V4L2_CTRL_TYPE_MENU,
-               .minimum = V4L2_MPEG_VIDEO_HEVC_TIER_MAIN,
-               .maximum = V4L2_MPEG_VIDEO_HEVC_TIER_HIGH,
-               .step = 1,
-               .default_value = V4L2_MPEG_VIDEO_HEVC_TIER_MAIN,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_FRAME_RATE_RESOLUTION,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = 1,
-               .maximum = (1 << 16) - 1,
-               .step = 1,
-               .default_value = 1,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_MAX_PARTITION_DEPTH,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_REF_NUMBER_FOR_PFRAMES,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = 1,
-               .maximum = 2,
-               .step = 1,
-               .default_value = 1,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_REFRESH_TYPE,
-               .type = V4L2_CTRL_TYPE_MENU,
-               .minimum = V4L2_MPEG_VIDEO_HEVC_REFRESH_NONE,
-               .maximum = V4L2_MPEG_VIDEO_HEVC_REFRESH_IDR,
-               .step = 1,
-               .default_value = V4L2_MPEG_VIDEO_HEVC_REFRESH_NONE,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_CONST_INTRA_PRED,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_LOSSLESS_CU,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_WAVEFRONT,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE,
-               .type = V4L2_CTRL_TYPE_MENU,
-               .minimum = V4L2_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE_DISABLED,
-               .maximum = V4L2_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY,
-               .step = 1,
-               .default_value = V4L2_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE_DISABLED,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_QP,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_TYPE,
-               .type = V4L2_CTRL_TYPE_MENU,
-               .minimum = V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B,
-               .maximum = V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P,
-               .step = 1,
-               .default_value = V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_LAYER,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = 0,
-               .maximum = 6,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L0_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = 0,
-               .maximum = 51,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L1_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = 0,
-               .maximum = 51,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L2_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = 0,
-               .maximum = 51,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L3_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = 0,
-               .maximum = 51,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L4_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = 0,
-               .maximum = 51,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L5_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = 0,
-               .maximum = 51,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L6_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = 0,
-               .maximum = 51,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L0_BR,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L1_BR,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L2_BR,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L3_BR,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L4_BR,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L5_BR,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L6_BR,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_GENERAL_PB,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_TEMPORAL_ID,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_STRONG_SMOOTHING,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_INTRA_PU_SPLIT,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_TMV_PREDICTION,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_MAX_NUM_MERGE_MV_MINUS1,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = 0,
-               .maximum = 4,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_WITHOUT_STARTCODE,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_REFRESH_PERIOD,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = 0,
-               .maximum = (1 << 16) - 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_LF_BETA_OFFSET_DIV2,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = -6,
-               .maximum = 6,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_LF_TC_OFFSET_DIV2,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = -6,
-               .maximum = 6,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_SIZE_OF_LENGTH_FIELD,
-               .type = V4L2_CTRL_TYPE_MENU,
-               .minimum = V4L2_MPEG_VIDEO_HEVC_SIZE_0,
-               .maximum = V4L2_MPEG_VIDEO_HEVC_SIZE_4,
-               .step = 1,
-               .default_value = V4L2_MPEG_VIDEO_HEVC_SIZE_0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_PREPEND_SPSPPS_TO_IDR,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MIN_BUFFERS_FOR_OUTPUT,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Minimum number of output bufs",
-               .minimum = 1,
-               .maximum = 32,
-               .step = 1,
-               .default_value = 1,
-               .is_volatile = 1,
-       },
-};
-
-#define NUM_CTRLS ARRAY_SIZE(controls)
-static const char * const *mfc51_get_menu(u32 id)
-{
-       static const char * const mfc51_video_frame_skip[] = {
-               "Disabled",
-               "Level Limit",
-               "VBV/CPB Limit",
-               NULL,
-       };
-       static const char * const mfc51_video_force_frame[] = {
-               "Disabled",
-               "I Frame",
-               "Not Coded",
-               NULL,
-       };
-       switch (id) {
-       case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE:
-               return mfc51_video_frame_skip;
-       case V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE:
-               return mfc51_video_force_frame;
-       }
-       return NULL;
-}
-
-static int s5p_mfc_ctx_ready(struct s5p_mfc_ctx *ctx)
-{
-       mfc_debug(2, "src=%d, dst=%d, state=%d\n",
-                 ctx->src_queue_cnt, ctx->dst_queue_cnt, ctx->state);
-       /* context is ready to make header */
-       if (ctx->state == MFCINST_GOT_INST && ctx->dst_queue_cnt >= 1)
-               return 1;
-       /* context is ready to encode a frame */
-       if ((ctx->state == MFCINST_RUNNING ||
-               ctx->state == MFCINST_HEAD_PRODUCED) &&
-               ctx->src_queue_cnt >= 1 && ctx->dst_queue_cnt >= 1)
-               return 1;
-       /* context is ready to encode remaining frames */
-       if (ctx->state == MFCINST_FINISHING &&
-               ctx->dst_queue_cnt >= 1)
-               return 1;
-       mfc_debug(2, "ctx is not ready\n");
-       return 0;
-}
-
-static void cleanup_ref_queue(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_buf *mb_entry;
-
-       /* move buffers in ref queue to src queue */
-       while (!list_empty(&ctx->ref_queue)) {
-               mb_entry = list_entry((&ctx->ref_queue)->next,
-                                               struct s5p_mfc_buf, list);
-               list_del(&mb_entry->list);
-               ctx->ref_queue_cnt--;
-               list_add_tail(&mb_entry->list, &ctx->src_queue);
-               ctx->src_queue_cnt++;
-       }
-       mfc_debug(2, "enc src count: %d, enc ref count: %d\n",
-                 ctx->src_queue_cnt, ctx->ref_queue_cnt);
-       INIT_LIST_HEAD(&ctx->ref_queue);
-       ctx->ref_queue_cnt = 0;
-}
-
-static int enc_pre_seq_start(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_buf *dst_mb;
-       unsigned long dst_addr;
-       unsigned int dst_size;
-
-       dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
-       dst_addr = vb2_dma_contig_plane_dma_addr(&dst_mb->b->vb2_buf, 0);
-       dst_size = vb2_plane_size(&dst_mb->b->vb2_buf, 0);
-       s5p_mfc_hw_call(dev->mfc_ops, set_enc_stream_buffer, ctx, dst_addr,
-                       dst_size);
-       return 0;
-}
-
-static int enc_post_seq_start(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_enc_params *p = &ctx->enc_params;
-       struct s5p_mfc_buf *dst_mb;
-       unsigned int enc_pb_count;
-
-       if (p->seq_hdr_mode == V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE) {
-               if (!list_empty(&ctx->dst_queue)) {
-                       dst_mb = list_entry(ctx->dst_queue.next,
-                                       struct s5p_mfc_buf, list);
-                       list_del(&dst_mb->list);
-                       ctx->dst_queue_cnt--;
-                       vb2_set_plane_payload(&dst_mb->b->vb2_buf, 0,
-                               s5p_mfc_hw_call(dev->mfc_ops, get_enc_strm_size,
-                                               dev));
-                       vb2_buffer_done(&dst_mb->b->vb2_buf,
-                                       VB2_BUF_STATE_DONE);
-               }
-       }
-
-       if (!IS_MFCV6_PLUS(dev)) {
-               ctx->state = MFCINST_RUNNING;
-               if (s5p_mfc_ctx_ready(ctx))
-                       set_work_bit_irqsave(ctx);
-               s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
-       } else {
-               enc_pb_count = s5p_mfc_hw_call(dev->mfc_ops,
-                               get_enc_dpb_count, dev);
-               if (ctx->pb_count < enc_pb_count)
-                       ctx->pb_count = enc_pb_count;
-               if (FW_HAS_E_MIN_SCRATCH_BUF(dev)) {
-                       ctx->scratch_buf_size = s5p_mfc_hw_call(dev->mfc_ops,
-                                       get_e_min_scratch_buf_size, dev);
-                       ctx->bank1.size += ctx->scratch_buf_size;
-               }
-               ctx->state = MFCINST_HEAD_PRODUCED;
-       }
-
-       return 0;
-}
-
-static int enc_pre_frame_start(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_buf *dst_mb;
-       struct s5p_mfc_buf *src_mb;
-       unsigned long src_y_addr, src_c_addr, dst_addr;
-       unsigned int dst_size;
-
-       src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
-       src_y_addr = vb2_dma_contig_plane_dma_addr(&src_mb->b->vb2_buf, 0);
-       src_c_addr = vb2_dma_contig_plane_dma_addr(&src_mb->b->vb2_buf, 1);
-       s5p_mfc_hw_call(dev->mfc_ops, set_enc_frame_buffer, ctx,
-                                                       src_y_addr, src_c_addr);
-
-       dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
-       dst_addr = vb2_dma_contig_plane_dma_addr(&dst_mb->b->vb2_buf, 0);
-       dst_size = vb2_plane_size(&dst_mb->b->vb2_buf, 0);
-       s5p_mfc_hw_call(dev->mfc_ops, set_enc_stream_buffer, ctx, dst_addr,
-                       dst_size);
-
-       return 0;
-}
-
-static int enc_post_frame_start(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_buf *mb_entry;
-       unsigned long enc_y_addr = 0, enc_c_addr = 0;
-       unsigned long mb_y_addr, mb_c_addr;
-       int slice_type;
-       unsigned int strm_size;
-
-       slice_type = s5p_mfc_hw_call(dev->mfc_ops, get_enc_slice_type, dev);
-       strm_size = s5p_mfc_hw_call(dev->mfc_ops, get_enc_strm_size, dev);
-       mfc_debug(2, "Encoded slice type: %d\n", slice_type);
-       mfc_debug(2, "Encoded stream size: %d\n", strm_size);
-       mfc_debug(2, "Display order: %d\n",
-                 mfc_read(dev, S5P_FIMV_ENC_SI_PIC_CNT));
-       if (slice_type >= 0) {
-               s5p_mfc_hw_call(dev->mfc_ops, get_enc_frame_buffer, ctx,
-                               &enc_y_addr, &enc_c_addr);
-               list_for_each_entry(mb_entry, &ctx->src_queue, list) {
-                       mb_y_addr = vb2_dma_contig_plane_dma_addr(
-                                       &mb_entry->b->vb2_buf, 0);
-                       mb_c_addr = vb2_dma_contig_plane_dma_addr(
-                                       &mb_entry->b->vb2_buf, 1);
-                       if ((enc_y_addr == mb_y_addr) &&
-                                               (enc_c_addr == mb_c_addr)) {
-                               list_del(&mb_entry->list);
-                               ctx->src_queue_cnt--;
-                               vb2_buffer_done(&mb_entry->b->vb2_buf,
-                                                       VB2_BUF_STATE_DONE);
-                               break;
-                       }
-               }
-               list_for_each_entry(mb_entry, &ctx->ref_queue, list) {
-                       mb_y_addr = vb2_dma_contig_plane_dma_addr(
-                                       &mb_entry->b->vb2_buf, 0);
-                       mb_c_addr = vb2_dma_contig_plane_dma_addr(
-                                       &mb_entry->b->vb2_buf, 1);
-                       if ((enc_y_addr == mb_y_addr) &&
-                                               (enc_c_addr == mb_c_addr)) {
-                               list_del(&mb_entry->list);
-                               ctx->ref_queue_cnt--;
-                               vb2_buffer_done(&mb_entry->b->vb2_buf,
-                                                       VB2_BUF_STATE_DONE);
-                               break;
-                       }
-               }
-       }
-       if ((ctx->src_queue_cnt > 0) && (ctx->state == MFCINST_RUNNING)) {
-               mb_entry = list_entry(ctx->src_queue.next, struct s5p_mfc_buf,
-                                                                       list);
-               if (mb_entry->flags & MFC_BUF_FLAG_USED) {
-                       list_del(&mb_entry->list);
-                       ctx->src_queue_cnt--;
-                       list_add_tail(&mb_entry->list, &ctx->ref_queue);
-                       ctx->ref_queue_cnt++;
-               }
-       }
-       mfc_debug(2, "enc src count: %d, enc ref count: %d\n",
-                 ctx->src_queue_cnt, ctx->ref_queue_cnt);
-       if ((ctx->dst_queue_cnt > 0) && (strm_size > 0)) {
-               mb_entry = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf,
-                                                                       list);
-               list_del(&mb_entry->list);
-               ctx->dst_queue_cnt--;
-               switch (slice_type) {
-               case S5P_FIMV_ENC_SI_SLICE_TYPE_I:
-                       mb_entry->b->flags |= V4L2_BUF_FLAG_KEYFRAME;
-                       break;
-               case S5P_FIMV_ENC_SI_SLICE_TYPE_P:
-                       mb_entry->b->flags |= V4L2_BUF_FLAG_PFRAME;
-                       break;
-               case S5P_FIMV_ENC_SI_SLICE_TYPE_B:
-                       mb_entry->b->flags |= V4L2_BUF_FLAG_BFRAME;
-                       break;
-               }
-               vb2_set_plane_payload(&mb_entry->b->vb2_buf, 0, strm_size);
-               vb2_buffer_done(&mb_entry->b->vb2_buf, VB2_BUF_STATE_DONE);
-       }
-       if ((ctx->src_queue_cnt == 0) || (ctx->dst_queue_cnt == 0))
-               clear_work_bit(ctx);
-
-       return 0;
-}
-
-static const struct s5p_mfc_codec_ops encoder_codec_ops = {
-       .pre_seq_start          = enc_pre_seq_start,
-       .post_seq_start         = enc_post_seq_start,
-       .pre_frame_start        = enc_pre_frame_start,
-       .post_frame_start       = enc_post_frame_start,
-};
-
-/* Query capabilities of the device */
-static int vidioc_querycap(struct file *file, void *priv,
-                          struct v4l2_capability *cap)
-{
-       struct s5p_mfc_dev *dev = video_drvdata(file);
-
-       strscpy(cap->driver, S5P_MFC_NAME, sizeof(cap->driver));
-       strscpy(cap->card, dev->vfd_enc->name, sizeof(cap->card));
-       snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
-                dev_name(&dev->plat_dev->dev));
-       return 0;
-}
-
-static int vidioc_enum_fmt(struct file *file, struct v4l2_fmtdesc *f,
-                                                       bool out)
-{
-       struct s5p_mfc_dev *dev = video_drvdata(file);
-       int i, j = 0;
-
-       for (i = 0; i < ARRAY_SIZE(formats); ++i) {
-               if (out && formats[i].type != MFC_FMT_RAW)
-                       continue;
-               else if (!out && formats[i].type != MFC_FMT_ENC)
-                       continue;
-               else if ((dev->variant->version_bit & formats[i].versions) == 0)
-                       continue;
-
-               if (j == f->index) {
-                       f->pixelformat = formats[i].fourcc;
-                       return 0;
-               }
-               ++j;
-       }
-       return -EINVAL;
-}
-
-static int vidioc_enum_fmt_vid_cap(struct file *file, void *pirv,
-                                  struct v4l2_fmtdesc *f)
-{
-       return vidioc_enum_fmt(file, f, false);
-}
-
-static int vidioc_enum_fmt_vid_out(struct file *file, void *priv,
-                                  struct v4l2_fmtdesc *f)
-{
-       return vidioc_enum_fmt(file, f, true);
-}
-
-static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
-{
-       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
-       struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
-
-       mfc_debug(2, "f->type = %d ctx->state = %d\n", f->type, ctx->state);
-       if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-               /* This is run on output (encoder dest) */
-               pix_fmt_mp->width = 0;
-               pix_fmt_mp->height = 0;
-               pix_fmt_mp->field = V4L2_FIELD_NONE;
-               pix_fmt_mp->pixelformat = ctx->dst_fmt->fourcc;
-               pix_fmt_mp->num_planes = ctx->dst_fmt->num_planes;
-
-               pix_fmt_mp->plane_fmt[0].bytesperline = ctx->enc_dst_buf_size;
-               pix_fmt_mp->plane_fmt[0].sizeimage = ctx->enc_dst_buf_size;
-       } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               /* This is run on capture (encoder src) */
-               pix_fmt_mp->width = ctx->img_width;
-               pix_fmt_mp->height = ctx->img_height;
-
-               pix_fmt_mp->field = V4L2_FIELD_NONE;
-               pix_fmt_mp->pixelformat = ctx->src_fmt->fourcc;
-               pix_fmt_mp->num_planes = ctx->src_fmt->num_planes;
-
-               pix_fmt_mp->plane_fmt[0].bytesperline = ctx->buf_width;
-               pix_fmt_mp->plane_fmt[0].sizeimage = ctx->luma_size;
-               pix_fmt_mp->plane_fmt[1].bytesperline = ctx->buf_width;
-               pix_fmt_mp->plane_fmt[1].sizeimage = ctx->chroma_size;
-       } else {
-               mfc_err("invalid buf type\n");
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
-{
-       struct s5p_mfc_dev *dev = video_drvdata(file);
-       struct s5p_mfc_fmt *fmt;
-       struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
-
-       if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-               fmt = find_format(f, MFC_FMT_ENC);
-               if (!fmt) {
-                       mfc_err("failed to try output format\n");
-                       return -EINVAL;
-               }
-               if ((dev->variant->version_bit & fmt->versions) == 0) {
-                       mfc_err("Unsupported format by this MFC version.\n");
-                       return -EINVAL;
-               }
-
-               pix_fmt_mp->plane_fmt[0].bytesperline =
-                       pix_fmt_mp->plane_fmt[0].sizeimage;
-       } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               fmt = find_format(f, MFC_FMT_RAW);
-               if (!fmt) {
-                       mfc_err("failed to try output format\n");
-                       return -EINVAL;
-               }
-               if ((dev->variant->version_bit & fmt->versions) == 0) {
-                       mfc_err("Unsupported format by this MFC version.\n");
-                       return -EINVAL;
-               }
-
-               v4l_bound_align_image(&pix_fmt_mp->width, 8, 1920, 1,
-                       &pix_fmt_mp->height, 4, 1080, 1, 0);
-       } else {
-               mfc_err("invalid buf type\n");
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
-{
-       struct s5p_mfc_dev *dev = video_drvdata(file);
-       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
-       struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
-       int ret = 0;
-
-       ret = vidioc_try_fmt(file, priv, f);
-       if (ret)
-               return ret;
-       if (ctx->vq_src.streaming || ctx->vq_dst.streaming) {
-               v4l2_err(&dev->v4l2_dev, "%s queue busy\n", __func__);
-               ret = -EBUSY;
-               goto out;
-       }
-       if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-               /* dst_fmt is validated by call to vidioc_try_fmt */
-               ctx->dst_fmt = find_format(f, MFC_FMT_ENC);
-               ctx->state = MFCINST_INIT;
-               ctx->codec_mode = ctx->dst_fmt->codec_mode;
-               ctx->enc_dst_buf_size = pix_fmt_mp->plane_fmt[0].sizeimage;
-               pix_fmt_mp->plane_fmt[0].bytesperline = 0;
-               ctx->dst_bufs_cnt = 0;
-               ctx->capture_state = QUEUE_FREE;
-               ret = s5p_mfc_open_mfc_inst(dev, ctx);
-       } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               /* src_fmt is validated by call to vidioc_try_fmt */
-               ctx->src_fmt = find_format(f, MFC_FMT_RAW);
-               ctx->img_width = pix_fmt_mp->width;
-               ctx->img_height = pix_fmt_mp->height;
-               mfc_debug(2, "codec number: %d\n", ctx->src_fmt->codec_mode);
-               mfc_debug(2, "fmt - w: %d, h: %d, ctx - w: %d, h: %d\n",
-                       pix_fmt_mp->width, pix_fmt_mp->height,
-                       ctx->img_width, ctx->img_height);
-
-               s5p_mfc_hw_call(dev->mfc_ops, enc_calc_src_size, ctx);
-               pix_fmt_mp->plane_fmt[0].sizeimage = ctx->luma_size;
-               pix_fmt_mp->plane_fmt[0].bytesperline = ctx->buf_width;
-               pix_fmt_mp->plane_fmt[1].sizeimage = ctx->chroma_size;
-               pix_fmt_mp->plane_fmt[1].bytesperline = ctx->buf_width;
-
-               ctx->src_bufs_cnt = 0;
-               ctx->output_state = QUEUE_FREE;
-       } else {
-               mfc_err("invalid buf type\n");
-               ret = -EINVAL;
-       }
-out:
-       mfc_debug_leave();
-       return ret;
-}
-
-static int vidioc_reqbufs(struct file *file, void *priv,
-                                         struct v4l2_requestbuffers *reqbufs)
-{
-       struct s5p_mfc_dev *dev = video_drvdata(file);
-       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
-       int ret = 0;
-
-       /* if memory is not mmp or userptr return error */
-       if ((reqbufs->memory != V4L2_MEMORY_MMAP) &&
-               (reqbufs->memory != V4L2_MEMORY_USERPTR))
-               return -EINVAL;
-       if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-               if (reqbufs->count == 0) {
-                       mfc_debug(2, "Freeing buffers\n");
-                       ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
-                       s5p_mfc_hw_call(dev->mfc_ops, release_codec_buffers,
-                                       ctx);
-                       ctx->capture_state = QUEUE_FREE;
-                       return ret;
-               }
-               if (ctx->capture_state != QUEUE_FREE) {
-                       mfc_err("invalid capture state: %d\n",
-                                                       ctx->capture_state);
-                       return -EINVAL;
-               }
-               ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
-               if (ret != 0) {
-                       mfc_err("error in vb2_reqbufs() for E(D)\n");
-                       return ret;
-               }
-               ctx->capture_state = QUEUE_BUFS_REQUESTED;
-
-               ret = s5p_mfc_hw_call(ctx->dev->mfc_ops,
-                               alloc_codec_buffers, ctx);
-               if (ret) {
-                       mfc_err("Failed to allocate encoding buffers\n");
-                       reqbufs->count = 0;
-                       ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
-                       return -ENOMEM;
-               }
-       } else if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               if (reqbufs->count == 0) {
-                       mfc_debug(2, "Freeing buffers\n");
-                       ret = vb2_reqbufs(&ctx->vq_src, reqbufs);
-                       s5p_mfc_hw_call(dev->mfc_ops, release_codec_buffers,
-                                       ctx);
-                       ctx->output_state = QUEUE_FREE;
-                       return ret;
-               }
-               if (ctx->output_state != QUEUE_FREE) {
-                       mfc_err("invalid output state: %d\n",
-                                                       ctx->output_state);
-                       return -EINVAL;
-               }
-
-               if (IS_MFCV6_PLUS(dev)) {
-                       /* Check for min encoder buffers */
-                       if (ctx->pb_count &&
-                               (reqbufs->count < ctx->pb_count)) {
-                               reqbufs->count = ctx->pb_count;
-                               mfc_debug(2, "Minimum %d output buffers needed\n",
-                                               ctx->pb_count);
-                       } else {
-                               ctx->pb_count = reqbufs->count;
-                       }
-               }
-
-               ret = vb2_reqbufs(&ctx->vq_src, reqbufs);
-               if (ret != 0) {
-                       mfc_err("error in vb2_reqbufs() for E(S)\n");
-                       return ret;
-               }
-               ctx->output_state = QUEUE_BUFS_REQUESTED;
-       } else {
-               mfc_err("invalid buf type\n");
-               return -EINVAL;
-       }
-       return ret;
-}
-
-static int vidioc_querybuf(struct file *file, void *priv,
-                                                  struct v4l2_buffer *buf)
-{
-       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
-       int ret = 0;
-
-       /* if memory is not mmp or userptr return error */
-       if ((buf->memory != V4L2_MEMORY_MMAP) &&
-               (buf->memory != V4L2_MEMORY_USERPTR))
-               return -EINVAL;
-       if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-               if (ctx->state != MFCINST_GOT_INST) {
-                       mfc_err("invalid context state: %d\n", ctx->state);
-                       return -EINVAL;
-               }
-               ret = vb2_querybuf(&ctx->vq_dst, buf);
-               if (ret != 0) {
-                       mfc_err("error in vb2_querybuf() for E(D)\n");
-                       return ret;
-               }
-               buf->m.planes[0].m.mem_offset += DST_QUEUE_OFF_BASE;
-       } else if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               ret = vb2_querybuf(&ctx->vq_src, buf);
-               if (ret != 0) {
-                       mfc_err("error in vb2_querybuf() for E(S)\n");
-                       return ret;
-               }
-       } else {
-               mfc_err("invalid buf type\n");
-               return -EINVAL;
-       }
-       return ret;
-}
-
-/* Queue a buffer */
-static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
-{
-       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
-
-       if (ctx->state == MFCINST_ERROR) {
-               mfc_err("Call on QBUF after unrecoverable error\n");
-               return -EIO;
-       }
-       if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               if (ctx->state == MFCINST_FINISHING) {
-                       mfc_err("Call on QBUF after EOS command\n");
-                       return -EIO;
-               }
-               return vb2_qbuf(&ctx->vq_src, NULL, buf);
-       } else if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-               return vb2_qbuf(&ctx->vq_dst, NULL, buf);
-       }
-       return -EINVAL;
-}
-
-/* Dequeue a buffer */
-static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
-{
-       const struct v4l2_event ev = {
-               .type = V4L2_EVENT_EOS
-       };
-       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
-       int ret;
-
-       if (ctx->state == MFCINST_ERROR) {
-               mfc_err_limited("Call on DQBUF after unrecoverable error\n");
-               return -EIO;
-       }
-       if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               ret = vb2_dqbuf(&ctx->vq_src, buf, file->f_flags & O_NONBLOCK);
-       } else if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-               ret = vb2_dqbuf(&ctx->vq_dst, buf, file->f_flags & O_NONBLOCK);
-               if (ret == 0 && ctx->state == MFCINST_FINISHED
-                                       && list_empty(&ctx->vq_dst.done_list))
-                       v4l2_event_queue_fh(&ctx->fh, &ev);
-       } else {
-               ret = -EINVAL;
-       }
-
-       return ret;
-}
-
-/* Export DMA buffer */
-static int vidioc_expbuf(struct file *file, void *priv,
-       struct v4l2_exportbuffer *eb)
-{
-       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
-
-       if (eb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
-               return vb2_expbuf(&ctx->vq_src, eb);
-       if (eb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
-               return vb2_expbuf(&ctx->vq_dst, eb);
-       return -EINVAL;
-}
-
-/* Stream on */
-static int vidioc_streamon(struct file *file, void *priv,
-                          enum v4l2_buf_type type)
-{
-       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
-
-       if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
-               return vb2_streamon(&ctx->vq_src, type);
-       else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
-               return vb2_streamon(&ctx->vq_dst, type);
-       return -EINVAL;
-}
-
-/* Stream off, which equals to a pause */
-static int vidioc_streamoff(struct file *file, void *priv,
-                           enum v4l2_buf_type type)
-{
-       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
-
-       if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
-               return vb2_streamoff(&ctx->vq_src, type);
-       else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
-               return vb2_streamoff(&ctx->vq_dst, type);
-       return -EINVAL;
-}
-
-static inline int h264_level(enum v4l2_mpeg_video_h264_level lvl)
-{
-       static unsigned int t[V4L2_MPEG_VIDEO_H264_LEVEL_4_0 + 1] = {
-               /* V4L2_MPEG_VIDEO_H264_LEVEL_1_0   */ 10,
-               /* V4L2_MPEG_VIDEO_H264_LEVEL_1B    */ 9,
-               /* V4L2_MPEG_VIDEO_H264_LEVEL_1_1   */ 11,
-               /* V4L2_MPEG_VIDEO_H264_LEVEL_1_2   */ 12,
-               /* V4L2_MPEG_VIDEO_H264_LEVEL_1_3   */ 13,
-               /* V4L2_MPEG_VIDEO_H264_LEVEL_2_0   */ 20,
-               /* V4L2_MPEG_VIDEO_H264_LEVEL_2_1   */ 21,
-               /* V4L2_MPEG_VIDEO_H264_LEVEL_2_2   */ 22,
-               /* V4L2_MPEG_VIDEO_H264_LEVEL_3_0   */ 30,
-               /* V4L2_MPEG_VIDEO_H264_LEVEL_3_1   */ 31,
-               /* V4L2_MPEG_VIDEO_H264_LEVEL_3_2   */ 32,
-               /* V4L2_MPEG_VIDEO_H264_LEVEL_4_0   */ 40,
-       };
-       return t[lvl];
-}
-
-static inline int mpeg4_level(enum v4l2_mpeg_video_mpeg4_level lvl)
-{
-       static unsigned int t[V4L2_MPEG_VIDEO_MPEG4_LEVEL_5 + 1] = {
-               /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_0    */ 0,
-               /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_0B   */ 9,
-               /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_1    */ 1,
-               /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_2    */ 2,
-               /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_3    */ 3,
-               /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_3B   */ 7,
-               /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_4    */ 4,
-               /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_5    */ 5,
-       };
-       return t[lvl];
-}
-
-static inline int hevc_level(enum v4l2_mpeg_video_hevc_level lvl)
-{
-       static unsigned int t[] = {
-               /* V4L2_MPEG_VIDEO_HEVC_LEVEL_1    */ 10,
-               /* V4L2_MPEG_VIDEO_HEVC_LEVEL_2    */ 20,
-               /* V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1  */ 21,
-               /* V4L2_MPEG_VIDEO_HEVC_LEVEL_3    */ 30,
-               /* V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1  */ 31,
-               /* V4L2_MPEG_VIDEO_HEVC_LEVEL_4    */ 40,
-               /* V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1  */ 41,
-               /* V4L2_MPEG_VIDEO_HEVC_LEVEL_5    */ 50,
-               /* V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1  */ 51,
-               /* V4L2_MPEG_VIDEO_HEVC_LEVEL_5_2  */ 52,
-               /* V4L2_MPEG_VIDEO_HEVC_LEVEL_6    */ 60,
-               /* V4L2_MPEG_VIDEO_HEVC_LEVEL_6_1  */ 61,
-               /* V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2  */ 62,
-       };
-       return t[lvl];
-}
-
-static inline int vui_sar_idc(enum v4l2_mpeg_video_h264_vui_sar_idc sar)
-{
-       static unsigned int t[V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_EXTENDED + 1] = {
-               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_UNSPECIFIED     */ 0,
-               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_1x1             */ 1,
-               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_12x11           */ 2,
-               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_10x11           */ 3,
-               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_16x11           */ 4,
-               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_40x33           */ 5,
-               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_24x11           */ 6,
-               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_20x11           */ 7,
-               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_32x11           */ 8,
-               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_80x33           */ 9,
-               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_18x11           */ 10,
-               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_15x11           */ 11,
-               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_64x33           */ 12,
-               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_160x99          */ 13,
-               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_4x3             */ 14,
-               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_3x2             */ 15,
-               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_2x1             */ 16,
-               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_EXTENDED        */ 255,
-       };
-       return t[sar];
-}
-
-/*
- * Update range of all HEVC quantization parameter controls that depend on the
- * V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP, V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP controls.
- */
-static void __enc_update_hevc_qp_ctrls_range(struct s5p_mfc_ctx *ctx,
-                                            int min, int max)
-{
-       static const int __hevc_qp_ctrls[] = {
-               V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP,
-               V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_QP,
-               V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_QP,
-               V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L0_QP,
-               V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L1_QP,
-               V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L2_QP,
-               V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L3_QP,
-               V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L4_QP,
-               V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L5_QP,
-               V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L6_QP,
-       };
-       struct v4l2_ctrl *ctrl = NULL;
-       int i, j;
-
-       for (i = 0; i < ARRAY_SIZE(__hevc_qp_ctrls); i++) {
-               for (j = 0; j < ARRAY_SIZE(ctx->ctrls); j++) {
-                       if (ctx->ctrls[j]->id == __hevc_qp_ctrls[i]) {
-                               ctrl = ctx->ctrls[j];
-                               break;
-                       }
-               }
-               if (WARN_ON(!ctrl))
-                       break;
-
-               __v4l2_ctrl_modify_range(ctrl, min, max, ctrl->step, min);
-       }
-}
-
-static int s5p_mfc_enc_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-       struct s5p_mfc_ctx *ctx = ctrl_to_ctx(ctrl);
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_enc_params *p = &ctx->enc_params;
-       int ret = 0;
-
-       switch (ctrl->id) {
-       case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
-               p->gop_size = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE:
-               p->slice_mode = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB:
-               p->slice_mb = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES:
-               p->slice_bit = ctrl->val * 8;
-               break;
-       case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB:
-               p->intra_refresh_mb = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_MFC51_VIDEO_PADDING:
-               p->pad = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_MFC51_VIDEO_PADDING_YUV:
-               p->pad_luma = (ctrl->val >> 16) & 0xff;
-               p->pad_cb = (ctrl->val >> 8) & 0xff;
-               p->pad_cr = (ctrl->val >> 0) & 0xff;
-               break;
-       case V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE:
-               p->rc_frame = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_BITRATE:
-               p->rc_bitrate = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_MFC51_VIDEO_RC_REACTION_COEFF:
-               p->rc_reaction_coeff = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE:
-               ctx->force_frame_type = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME:
-               ctx->force_frame_type =
-                       V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_I_FRAME;
-               break;
-       case V4L2_CID_MPEG_VIDEO_VBV_SIZE:
-               p->vbv_size = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_MV_H_SEARCH_RANGE:
-               p->mv_h_range = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_MV_V_SEARCH_RANGE:
-               p->mv_v_range = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE:
-               p->codec.h264.cpb_size = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEADER_MODE:
-               p->seq_hdr_mode = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE:
-       case V4L2_CID_MPEG_VIDEO_FRAME_SKIP_MODE:
-               p->frame_skip_mode = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_MFC51_VIDEO_RC_FIXED_TARGET_BIT:
-               p->fixed_target_bit = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_B_FRAMES:
-               p->num_b_frame = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
-               switch (ctrl->val) {
-               case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:
-                       p->codec.h264.profile =
-                                       S5P_FIMV_ENC_PROFILE_H264_MAIN;
-                       break;
-               case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH:
-                       p->codec.h264.profile =
-                                       S5P_FIMV_ENC_PROFILE_H264_HIGH;
-                       break;
-               case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
-                       p->codec.h264.profile =
-                               S5P_FIMV_ENC_PROFILE_H264_BASELINE;
-                       break;
-               case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
-                       if (IS_MFCV6_PLUS(dev))
-                               p->codec.h264.profile =
-                               S5P_FIMV_ENC_PROFILE_H264_CONSTRAINED_BASELINE;
-                       else
-                               ret = -EINVAL;
-                       break;
-               default:
-                       ret = -EINVAL;
-               }
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
-               p->codec.h264.level_v4l2 = ctrl->val;
-               p->codec.h264.level = h264_level(ctrl->val);
-               if (p->codec.h264.level < 0) {
-                       mfc_err("Level number is wrong\n");
-                       ret = p->codec.h264.level;
-               }
-               break;
-       case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL:
-               p->codec.mpeg4.level_v4l2 = ctrl->val;
-               p->codec.mpeg4.level = mpeg4_level(ctrl->val);
-               if (p->codec.mpeg4.level < 0) {
-                       mfc_err("Level number is wrong\n");
-                       ret = p->codec.mpeg4.level;
-               }
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE:
-               p->codec.h264.loop_filter_mode = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA:
-               p->codec.h264.loop_filter_alpha = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA:
-               p->codec.h264.loop_filter_beta = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:
-               p->codec.h264.entropy_mode = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_MFC51_VIDEO_H264_NUM_REF_PIC_FOR_P:
-               p->codec.h264.num_ref_pic_4p = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM:
-               p->codec.h264._8x8_transform = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE:
-               p->rc_mb = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP:
-               p->codec.h264.rc_frame_qp = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:
-               p->codec.h264.rc_min_qp = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:
-               p->codec.h264.rc_max_qp = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP:
-               p->codec.h264.rc_p_frame_qp = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP:
-               p->codec.h264.rc_b_frame_qp = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP:
-       case V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP:
-               p->codec.mpeg4.rc_frame_qp = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP:
-       case V4L2_CID_MPEG_VIDEO_H263_MIN_QP:
-               p->codec.mpeg4.rc_min_qp = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP:
-       case V4L2_CID_MPEG_VIDEO_H263_MAX_QP:
-               p->codec.mpeg4.rc_max_qp = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP:
-       case V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP:
-               p->codec.mpeg4.rc_p_frame_qp = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP:
-       case V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP:
-               p->codec.mpeg4.rc_b_frame_qp = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_DARK:
-               p->codec.h264.rc_mb_dark = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_SMOOTH:
-               p->codec.h264.rc_mb_smooth = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_STATIC:
-               p->codec.h264.rc_mb_static = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_ACTIVITY:
-               p->codec.h264.rc_mb_activity = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE:
-               p->codec.h264.vui_sar = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC:
-               p->codec.h264.vui_sar_idc = vui_sar_idc(ctrl->val);
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH:
-               p->codec.h264.vui_ext_sar_width = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_HEIGHT:
-               p->codec.h264.vui_ext_sar_height = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
-               p->codec.h264.open_gop = !ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_I_PERIOD:
-               p->codec.h264.open_gop_size = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE:
-               switch (ctrl->val) {
-               case V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE:
-                       p->codec.mpeg4.profile =
-                               S5P_FIMV_ENC_PROFILE_MPEG4_SIMPLE;
-                       break;
-               case V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE:
-                       p->codec.mpeg4.profile =
-                       S5P_FIMV_ENC_PROFILE_MPEG4_ADVANCED_SIMPLE;
-                       break;
-               default:
-                       ret = -EINVAL;
-               }
-               break;
-       case V4L2_CID_MPEG_VIDEO_MPEG4_QPEL:
-               p->codec.mpeg4.quarter_pixel = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_VPX_NUM_PARTITIONS:
-               p->codec.vp8.num_partitions = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_VPX_IMD_DISABLE_4X4:
-               p->codec.vp8.imd_4x4 = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_VPX_NUM_REF_FRAMES:
-               p->codec.vp8.num_ref = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_VPX_FILTER_LEVEL:
-               p->codec.vp8.filter_level = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_VPX_FILTER_SHARPNESS:
-               p->codec.vp8.filter_sharpness = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_REF_PERIOD:
-               p->codec.vp8.golden_frame_ref_period = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_SEL:
-               p->codec.vp8.golden_frame_sel = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_VPX_MIN_QP:
-               p->codec.vp8.rc_min_qp = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_VPX_MAX_QP:
-               p->codec.vp8.rc_max_qp = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_VPX_I_FRAME_QP:
-               p->codec.vp8.rc_frame_qp = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_VPX_P_FRAME_QP:
-               p->codec.vp8.rc_p_frame_qp = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_VP8_PROFILE:
-               p->codec.vp8.profile = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP:
-               p->codec.hevc.rc_frame_qp = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_QP:
-               p->codec.hevc.rc_p_frame_qp = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_QP:
-               p->codec.hevc.rc_b_frame_qp = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_FRAME_RATE_RESOLUTION:
-               p->codec.hevc.rc_framerate = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP:
-               p->codec.hevc.rc_min_qp = ctrl->val;
-               __enc_update_hevc_qp_ctrls_range(ctx, ctrl->val,
-                                                p->codec.hevc.rc_max_qp);
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP:
-               p->codec.hevc.rc_max_qp = ctrl->val;
-               __enc_update_hevc_qp_ctrls_range(ctx, p->codec.hevc.rc_min_qp,
-                                                ctrl->val);
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_LEVEL:
-               p->codec.hevc.level_v4l2 = ctrl->val;
-               p->codec.hevc.level = hevc_level(ctrl->val);
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_PROFILE:
-               switch (ctrl->val) {
-               case V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN:
-                       p->codec.hevc.profile =
-                               V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN;
-                       break;
-               case V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE:
-                       p->codec.hevc.profile =
-                       V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE;
-                       break;
-               default:
-                       ret = -EINVAL;
-               }
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_TIER:
-               p->codec.hevc.tier = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_MAX_PARTITION_DEPTH:
-               p->codec.hevc.max_partition_depth = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_REF_NUMBER_FOR_PFRAMES:
-               p->codec.hevc.num_refs_for_p = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_REFRESH_TYPE:
-               p->codec.hevc.refreshtype = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_CONST_INTRA_PRED:
-               p->codec.hevc.const_intra_period_enable = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_LOSSLESS_CU:
-               p->codec.hevc.lossless_cu_enable = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_WAVEFRONT:
-               p->codec.hevc.wavefront_enable = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE:
-               p->codec.hevc.loopfilter = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_HIER_QP:
-               p->codec.hevc.hier_qp_enable = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_TYPE:
-               p->codec.hevc.hier_qp_type = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_LAYER:
-               p->codec.hevc.num_hier_layer = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L0_QP:
-               p->codec.hevc.hier_qp_layer[0] = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L1_QP:
-               p->codec.hevc.hier_qp_layer[1] = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L2_QP:
-               p->codec.hevc.hier_qp_layer[2] = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L3_QP:
-               p->codec.hevc.hier_qp_layer[3] = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L4_QP:
-               p->codec.hevc.hier_qp_layer[4] = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L5_QP:
-               p->codec.hevc.hier_qp_layer[5] = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L6_QP:
-               p->codec.hevc.hier_qp_layer[6] = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L0_BR:
-               p->codec.hevc.hier_bit_layer[0] = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L1_BR:
-               p->codec.hevc.hier_bit_layer[1] = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L2_BR:
-               p->codec.hevc.hier_bit_layer[2] = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L3_BR:
-               p->codec.hevc.hier_bit_layer[3] = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L4_BR:
-               p->codec.hevc.hier_bit_layer[4] = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L5_BR:
-               p->codec.hevc.hier_bit_layer[5] = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L6_BR:
-               p->codec.hevc.hier_bit_layer[6] = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_GENERAL_PB:
-               p->codec.hevc.general_pb_enable = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_TEMPORAL_ID:
-               p->codec.hevc.temporal_id_enable = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_STRONG_SMOOTHING:
-               p->codec.hevc.strong_intra_smooth = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_INTRA_PU_SPLIT:
-               p->codec.hevc.intra_pu_split_disable = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_TMV_PREDICTION:
-               p->codec.hevc.tmv_prediction_disable = !ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_MAX_NUM_MERGE_MV_MINUS1:
-               p->codec.hevc.max_num_merge_mv = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_WITHOUT_STARTCODE:
-               p->codec.hevc.encoding_nostartcode_enable = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_REFRESH_PERIOD:
-               p->codec.hevc.refreshperiod = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_LF_BETA_OFFSET_DIV2:
-               p->codec.hevc.lf_beta_offset_div2 = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_LF_TC_OFFSET_DIV2:
-               p->codec.hevc.lf_tc_offset_div2 = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_SIZE_OF_LENGTH_FIELD:
-               p->codec.hevc.size_of_length_field = ctrl->val;
-               break;
-       case V4L2_CID_MPEG_VIDEO_PREPEND_SPSPPS_TO_IDR:
-               p->codec.hevc.prepend_sps_pps_to_idr = ctrl->val;
-               break;
-       default:
-               v4l2_err(&dev->v4l2_dev, "Invalid control, id=%d, val=%d\n",
-                                                       ctrl->id, ctrl->val);
-               ret = -EINVAL;
-       }
-       return ret;
-}
-
-static int s5p_mfc_enc_g_v_ctrl(struct v4l2_ctrl *ctrl)
-{
-       struct s5p_mfc_ctx *ctx = ctrl_to_ctx(ctrl);
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       switch (ctrl->id) {
-       case V4L2_CID_MIN_BUFFERS_FOR_OUTPUT:
-               if (ctx->state >= MFCINST_HEAD_PARSED &&
-                   ctx->state < MFCINST_ABORT) {
-                       ctrl->val = ctx->pb_count;
-                       break;
-               } else if (ctx->state != MFCINST_INIT) {
-                       v4l2_err(&dev->v4l2_dev, "Encoding not initialised\n");
-                       return -EINVAL;
-               }
-               /* Should wait for the header to be produced */
-               s5p_mfc_wait_for_done_ctx(ctx,
-                               S5P_MFC_R2H_CMD_SEQ_DONE_RET, 0);
-               if (ctx->state >= MFCINST_HEAD_PARSED &&
-                   ctx->state < MFCINST_ABORT) {
-                       ctrl->val = ctx->pb_count;
-               } else {
-                       v4l2_err(&dev->v4l2_dev, "Encoding not initialised\n");
-                       return -EINVAL;
-               }
-               break;
-       }
-       return 0;
-}
-
-static const struct v4l2_ctrl_ops s5p_mfc_enc_ctrl_ops = {
-       .s_ctrl = s5p_mfc_enc_s_ctrl,
-       .g_volatile_ctrl = s5p_mfc_enc_g_v_ctrl,
-};
-
-static int vidioc_s_parm(struct file *file, void *priv,
-                        struct v4l2_streamparm *a)
-{
-       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
-
-       if (a->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               ctx->enc_params.rc_framerate_num =
-                                       a->parm.output.timeperframe.denominator;
-               ctx->enc_params.rc_framerate_denom =
-                                       a->parm.output.timeperframe.numerator;
-       } else {
-               mfc_err("Setting FPS is only possible for the output queue\n");
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static int vidioc_g_parm(struct file *file, void *priv,
-                        struct v4l2_streamparm *a)
-{
-       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
-
-       if (a->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
-               a->parm.output.timeperframe.denominator =
-                                       ctx->enc_params.rc_framerate_num;
-               a->parm.output.timeperframe.numerator =
-                                       ctx->enc_params.rc_framerate_denom;
-       } else {
-               mfc_err("Setting FPS is only possible for the output queue\n");
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static int vidioc_encoder_cmd(struct file *file, void *priv,
-                             struct v4l2_encoder_cmd *cmd)
-{
-       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_buf *buf;
-       unsigned long flags;
-
-       switch (cmd->cmd) {
-       case V4L2_ENC_CMD_STOP:
-               if (cmd->flags != 0)
-                       return -EINVAL;
-
-               if (!ctx->vq_src.streaming)
-                       return -EINVAL;
-
-               spin_lock_irqsave(&dev->irqlock, flags);
-               if (list_empty(&ctx->src_queue)) {
-                       mfc_debug(2, "EOS: empty src queue, entering finishing state\n");
-                       ctx->state = MFCINST_FINISHING;
-                       if (s5p_mfc_ctx_ready(ctx))
-                               set_work_bit_irqsave(ctx);
-                       spin_unlock_irqrestore(&dev->irqlock, flags);
-                       s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
-               } else {
-                       mfc_debug(2, "EOS: marking last buffer of stream\n");
-                       buf = list_entry(ctx->src_queue.prev,
-                                               struct s5p_mfc_buf, list);
-                       if (buf->flags & MFC_BUF_FLAG_USED)
-                               ctx->state = MFCINST_FINISHING;
-                       else
-                               buf->flags |= MFC_BUF_FLAG_EOS;
-                       spin_unlock_irqrestore(&dev->irqlock, flags);
-               }
-               break;
-       default:
-               return -EINVAL;
-
-       }
-       return 0;
-}
-
-static int vidioc_subscribe_event(struct v4l2_fh *fh,
-                                 const struct v4l2_event_subscription *sub)
-{
-       switch (sub->type) {
-       case V4L2_EVENT_EOS:
-               return v4l2_event_subscribe(fh, sub, 2, NULL);
-       default:
-               return -EINVAL;
-       }
-}
-
-static const struct v4l2_ioctl_ops s5p_mfc_enc_ioctl_ops = {
-       .vidioc_querycap = vidioc_querycap,
-       .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
-       .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out,
-       .vidioc_g_fmt_vid_cap_mplane = vidioc_g_fmt,
-       .vidioc_g_fmt_vid_out_mplane = vidioc_g_fmt,
-       .vidioc_try_fmt_vid_cap_mplane = vidioc_try_fmt,
-       .vidioc_try_fmt_vid_out_mplane = vidioc_try_fmt,
-       .vidioc_s_fmt_vid_cap_mplane = vidioc_s_fmt,
-       .vidioc_s_fmt_vid_out_mplane = vidioc_s_fmt,
-       .vidioc_reqbufs = vidioc_reqbufs,
-       .vidioc_querybuf = vidioc_querybuf,
-       .vidioc_qbuf = vidioc_qbuf,
-       .vidioc_dqbuf = vidioc_dqbuf,
-       .vidioc_expbuf = vidioc_expbuf,
-       .vidioc_streamon = vidioc_streamon,
-       .vidioc_streamoff = vidioc_streamoff,
-       .vidioc_s_parm = vidioc_s_parm,
-       .vidioc_g_parm = vidioc_g_parm,
-       .vidioc_encoder_cmd = vidioc_encoder_cmd,
-       .vidioc_subscribe_event = vidioc_subscribe_event,
-       .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
-};
-
-static int check_vb_with_fmt(struct s5p_mfc_fmt *fmt, struct vb2_buffer *vb)
-{
-       int i;
-
-       if (!fmt)
-               return -EINVAL;
-       if (fmt->num_planes != vb->num_planes) {
-               mfc_err("invalid plane number for the format\n");
-               return -EINVAL;
-       }
-       for (i = 0; i < fmt->num_planes; i++) {
-               dma_addr_t dma = vb2_dma_contig_plane_dma_addr(vb, i);
-               if (!dma) {
-                       mfc_err("failed to get plane cookie\n");
-                       return -EINVAL;
-               }
-               mfc_debug(2, "index: %d, plane[%d] cookie: %pad\n",
-                         vb->index, i, &dma);
-       }
-       return 0;
-}
-
-static int s5p_mfc_queue_setup(struct vb2_queue *vq,
-                       unsigned int *buf_count, unsigned int *plane_count,
-                       unsigned int psize[], struct device *alloc_devs[])
-{
-       struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-               if (ctx->state != MFCINST_GOT_INST) {
-                       mfc_err("invalid state: %d\n", ctx->state);
-                       return -EINVAL;
-               }
-
-               if (ctx->dst_fmt)
-                       *plane_count = ctx->dst_fmt->num_planes;
-               else
-                       *plane_count = MFC_ENC_CAP_PLANE_COUNT;
-               if (*buf_count < 1)
-                       *buf_count = 1;
-               if (*buf_count > MFC_MAX_BUFFERS)
-                       *buf_count = MFC_MAX_BUFFERS;
-               psize[0] = ctx->enc_dst_buf_size;
-               alloc_devs[0] = ctx->dev->mem_dev[BANK_L_CTX];
-       } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               if (ctx->src_fmt)
-                       *plane_count = ctx->src_fmt->num_planes;
-               else
-                       *plane_count = MFC_ENC_OUT_PLANE_COUNT;
-
-               if (*buf_count < 1)
-                       *buf_count = 1;
-               if (*buf_count > MFC_MAX_BUFFERS)
-                       *buf_count = MFC_MAX_BUFFERS;
-
-               psize[0] = ctx->luma_size;
-               psize[1] = ctx->chroma_size;
-
-               if (IS_MFCV6_PLUS(dev)) {
-                       alloc_devs[0] = ctx->dev->mem_dev[BANK_L_CTX];
-                       alloc_devs[1] = ctx->dev->mem_dev[BANK_L_CTX];
-               } else {
-                       alloc_devs[0] = ctx->dev->mem_dev[BANK_R_CTX];
-                       alloc_devs[1] = ctx->dev->mem_dev[BANK_R_CTX];
-               }
-       } else {
-               mfc_err("invalid queue type: %d\n", vq->type);
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static int s5p_mfc_buf_init(struct vb2_buffer *vb)
-{
-       struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
-       struct vb2_queue *vq = vb->vb2_queue;
-       struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
-       unsigned int i;
-       int ret;
-
-       if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-               ret = check_vb_with_fmt(ctx->dst_fmt, vb);
-               if (ret < 0)
-                       return ret;
-               i = vb->index;
-               ctx->dst_bufs[i].b = vbuf;
-               ctx->dst_bufs[i].cookie.stream =
-                                       vb2_dma_contig_plane_dma_addr(vb, 0);
-               ctx->dst_bufs_cnt++;
-       } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               ret = check_vb_with_fmt(ctx->src_fmt, vb);
-               if (ret < 0)
-                       return ret;
-               i = vb->index;
-               ctx->src_bufs[i].b = vbuf;
-               ctx->src_bufs[i].cookie.raw.luma =
-                                       vb2_dma_contig_plane_dma_addr(vb, 0);
-               ctx->src_bufs[i].cookie.raw.chroma =
-                                       vb2_dma_contig_plane_dma_addr(vb, 1);
-               ctx->src_bufs_cnt++;
-       } else {
-               mfc_err("invalid queue type: %d\n", vq->type);
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static int s5p_mfc_buf_prepare(struct vb2_buffer *vb)
-{
-       struct vb2_queue *vq = vb->vb2_queue;
-       struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
-       int ret;
-
-       if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-               ret = check_vb_with_fmt(ctx->dst_fmt, vb);
-               if (ret < 0)
-                       return ret;
-               mfc_debug(2, "plane size: %ld, dst size: %zu\n",
-                       vb2_plane_size(vb, 0), ctx->enc_dst_buf_size);
-               if (vb2_plane_size(vb, 0) < ctx->enc_dst_buf_size) {
-                       mfc_err("plane size is too small for capture\n");
-                       return -EINVAL;
-               }
-       } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               ret = check_vb_with_fmt(ctx->src_fmt, vb);
-               if (ret < 0)
-                       return ret;
-               mfc_debug(2, "plane size: %ld, luma size: %d\n",
-                       vb2_plane_size(vb, 0), ctx->luma_size);
-               mfc_debug(2, "plane size: %ld, chroma size: %d\n",
-                       vb2_plane_size(vb, 1), ctx->chroma_size);
-               if (vb2_plane_size(vb, 0) < ctx->luma_size ||
-                   vb2_plane_size(vb, 1) < ctx->chroma_size) {
-                       mfc_err("plane size is too small for output\n");
-                       return -EINVAL;
-               }
-       } else {
-               mfc_err("invalid queue type: %d\n", vq->type);
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static int s5p_mfc_start_streaming(struct vb2_queue *q, unsigned int count)
-{
-       struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv);
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       if (IS_MFCV6_PLUS(dev) &&
-                       (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)) {
-
-               if ((ctx->state == MFCINST_GOT_INST) &&
-                       (dev->curr_ctx == ctx->num) && dev->hw_lock) {
-                       s5p_mfc_wait_for_done_ctx(ctx,
-                                               S5P_MFC_R2H_CMD_SEQ_DONE_RET,
-                                               0);
-               }
-
-               if (ctx->src_bufs_cnt < ctx->pb_count) {
-                       mfc_err("Need minimum %d OUTPUT buffers\n",
-                                       ctx->pb_count);
-                       return -ENOBUFS;
-               }
-       }
-
-       /* If context is ready then dev = work->data;schedule it to run */
-       if (s5p_mfc_ctx_ready(ctx))
-               set_work_bit_irqsave(ctx);
-       s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
-
-       return 0;
-}
-
-static void s5p_mfc_stop_streaming(struct vb2_queue *q)
-{
-       unsigned long flags;
-       struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv);
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       if ((ctx->state == MFCINST_FINISHING ||
-               ctx->state == MFCINST_RUNNING) &&
-               dev->curr_ctx == ctx->num && dev->hw_lock) {
-               ctx->state = MFCINST_ABORT;
-               s5p_mfc_wait_for_done_ctx(ctx, S5P_MFC_R2H_CMD_FRAME_DONE_RET,
-                                         0);
-       }
-       ctx->state = MFCINST_FINISHED;
-       spin_lock_irqsave(&dev->irqlock, flags);
-       if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-               s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst);
-               INIT_LIST_HEAD(&ctx->dst_queue);
-               ctx->dst_queue_cnt = 0;
-       }
-       if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               cleanup_ref_queue(ctx);
-               s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src);
-               INIT_LIST_HEAD(&ctx->src_queue);
-               ctx->src_queue_cnt = 0;
-       }
-       spin_unlock_irqrestore(&dev->irqlock, flags);
-}
-
-static void s5p_mfc_buf_queue(struct vb2_buffer *vb)
-{
-       struct vb2_queue *vq = vb->vb2_queue;
-       struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
-       struct s5p_mfc_dev *dev = ctx->dev;
-       unsigned long flags;
-       struct s5p_mfc_buf *mfc_buf;
-
-       if (ctx->state == MFCINST_ERROR) {
-               vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
-               cleanup_ref_queue(ctx);
-               return;
-       }
-       if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-               mfc_buf = &ctx->dst_bufs[vb->index];
-               mfc_buf->flags &= ~MFC_BUF_FLAG_USED;
-               /* Mark destination as available for use by MFC */
-               spin_lock_irqsave(&dev->irqlock, flags);
-               list_add_tail(&mfc_buf->list, &ctx->dst_queue);
-               ctx->dst_queue_cnt++;
-               spin_unlock_irqrestore(&dev->irqlock, flags);
-       } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               mfc_buf = &ctx->src_bufs[vb->index];
-               mfc_buf->flags &= ~MFC_BUF_FLAG_USED;
-               spin_lock_irqsave(&dev->irqlock, flags);
-               list_add_tail(&mfc_buf->list, &ctx->src_queue);
-               ctx->src_queue_cnt++;
-               spin_unlock_irqrestore(&dev->irqlock, flags);
-       } else {
-               mfc_err("unsupported buffer type (%d)\n", vq->type);
-       }
-       if (s5p_mfc_ctx_ready(ctx))
-               set_work_bit_irqsave(ctx);
-       s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
-}
-
-static struct vb2_ops s5p_mfc_enc_qops = {
-       .queue_setup            = s5p_mfc_queue_setup,
-       .wait_prepare           = vb2_ops_wait_prepare,
-       .wait_finish            = vb2_ops_wait_finish,
-       .buf_init               = s5p_mfc_buf_init,
-       .buf_prepare            = s5p_mfc_buf_prepare,
-       .start_streaming        = s5p_mfc_start_streaming,
-       .stop_streaming         = s5p_mfc_stop_streaming,
-       .buf_queue              = s5p_mfc_buf_queue,
-};
-
-const struct s5p_mfc_codec_ops *get_enc_codec_ops(void)
-{
-       return &encoder_codec_ops;
-}
-
-struct vb2_ops *get_enc_queue_ops(void)
-{
-       return &s5p_mfc_enc_qops;
-}
-
-const struct v4l2_ioctl_ops *get_enc_v4l2_ioctl_ops(void)
-{
-       return &s5p_mfc_enc_ioctl_ops;
-}
-
-#define IS_MFC51_PRIV(x) ((V4L2_CTRL_ID2WHICH(x) == V4L2_CTRL_CLASS_CODEC) \
-                                               && V4L2_CTRL_DRIVER_PRIV(x))
-
-int s5p_mfc_enc_ctrls_setup(struct s5p_mfc_ctx *ctx)
-{
-       struct v4l2_ctrl_config cfg;
-       int i;
-
-       v4l2_ctrl_handler_init(&ctx->ctrl_handler, NUM_CTRLS);
-       if (ctx->ctrl_handler.error) {
-               mfc_err("v4l2_ctrl_handler_init failed\n");
-               return ctx->ctrl_handler.error;
-       }
-       for (i = 0; i < NUM_CTRLS; i++) {
-               if (IS_MFC51_PRIV(controls[i].id)) {
-                       memset(&cfg, 0, sizeof(struct v4l2_ctrl_config));
-                       cfg.ops = &s5p_mfc_enc_ctrl_ops;
-                       cfg.id = controls[i].id;
-                       cfg.min = controls[i].minimum;
-                       cfg.max = controls[i].maximum;
-                       cfg.def = controls[i].default_value;
-                       cfg.name = controls[i].name;
-                       cfg.type = controls[i].type;
-                       cfg.flags = 0;
-
-                       if (cfg.type == V4L2_CTRL_TYPE_MENU) {
-                               cfg.step = 0;
-                               cfg.menu_skip_mask = controls[i].menu_skip_mask;
-                               cfg.qmenu = mfc51_get_menu(cfg.id);
-                       } else {
-                               cfg.step = controls[i].step;
-                               cfg.menu_skip_mask = 0;
-                       }
-                       ctx->ctrls[i] = v4l2_ctrl_new_custom(&ctx->ctrl_handler,
-                                       &cfg, NULL);
-               } else {
-                       if ((controls[i].type == V4L2_CTRL_TYPE_MENU) ||
-                               (controls[i].type ==
-                                       V4L2_CTRL_TYPE_INTEGER_MENU)) {
-                               ctx->ctrls[i] = v4l2_ctrl_new_std_menu(
-                                       &ctx->ctrl_handler,
-                                       &s5p_mfc_enc_ctrl_ops, controls[i].id,
-                                       controls[i].maximum, 0,
-                                       controls[i].default_value);
-                       } else {
-                               ctx->ctrls[i] = v4l2_ctrl_new_std(
-                                       &ctx->ctrl_handler,
-                                       &s5p_mfc_enc_ctrl_ops, controls[i].id,
-                                       controls[i].minimum,
-                                       controls[i].maximum, controls[i].step,
-                                       controls[i].default_value);
-                       }
-               }
-               if (ctx->ctrl_handler.error) {
-                       mfc_err("Adding control (%d) failed\n", i);
-                       return ctx->ctrl_handler.error;
-               }
-               if (controls[i].is_volatile && ctx->ctrls[i])
-                       ctx->ctrls[i]->flags |= V4L2_CTRL_FLAG_VOLATILE;
-       }
-       v4l2_ctrl_handler_setup(&ctx->ctrl_handler);
-       return 0;
-}
-
-void s5p_mfc_enc_ctrls_delete(struct s5p_mfc_ctx *ctx)
-{
-       int i;
-
-       v4l2_ctrl_handler_free(&ctx->ctrl_handler);
-       for (i = 0; i < NUM_CTRLS; i++)
-               ctx->ctrls[i] = NULL;
-}
-
-void s5p_mfc_enc_init(struct s5p_mfc_ctx *ctx)
-{
-       struct v4l2_format f;
-       f.fmt.pix_mp.pixelformat = DEF_SRC_FMT_ENC;
-       ctx->src_fmt = find_format(&f, MFC_FMT_RAW);
-       f.fmt.pix_mp.pixelformat = DEF_DST_FMT_ENC;
-       ctx->dst_fmt = find_format(&f, MFC_FMT_ENC);
-}
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.h b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.h
deleted file mode 100644 (file)
index cacd1ca..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * linux/drivers/media/platform/s5p-mfc/s5p_mfc_enc.h
- *
- * Copyright (C) 2011 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- */
-
-#ifndef S5P_MFC_ENC_H_
-#define S5P_MFC_ENC_H_
-
-const struct s5p_mfc_codec_ops *get_enc_codec_ops(void);
-struct vb2_ops *get_enc_queue_ops(void);
-const struct v4l2_ioctl_ops *get_enc_v4l2_ioctl_ops(void);
-struct s5p_mfc_fmt *get_enc_def_fmt(bool src);
-int s5p_mfc_enc_ctrls_setup(struct s5p_mfc_ctx *ctx);
-void s5p_mfc_enc_ctrls_delete(struct s5p_mfc_ctx *ctx);
-void s5p_mfc_enc_init(struct s5p_mfc_ctx *ctx);
-
-#endif /* S5P_MFC_ENC_H_  */
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_intr.c b/drivers/media/platform/s5p-mfc/s5p_mfc_intr.c
deleted file mode 100644 (file)
index 0a38f6d..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * drivers/media/platform/samsung/mfc5/s5p_mfc_intr.c
- *
- * C file for Samsung MFC (Multi Function Codec - FIMV) driver
- * This file contains functions used to wait for command completion.
- *
- * Kamil Debski, Copyright (C) 2011 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- */
-
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/io.h>
-#include <linux/sched.h>
-#include <linux/wait.h>
-#include "s5p_mfc_common.h"
-#include "s5p_mfc_debug.h"
-#include "s5p_mfc_intr.h"
-
-int s5p_mfc_wait_for_done_dev(struct s5p_mfc_dev *dev, int command)
-{
-       int ret;
-
-       ret = wait_event_interruptible_timeout(dev->queue,
-               (dev->int_cond && (dev->int_type == command
-               || dev->int_type == S5P_MFC_R2H_CMD_ERR_RET)),
-               msecs_to_jiffies(MFC_INT_TIMEOUT));
-       if (ret == 0) {
-               mfc_err("Interrupt (dev->int_type:%d, command:%d) timed out\n",
-                                                       dev->int_type, command);
-               return 1;
-       } else if (ret == -ERESTARTSYS) {
-               mfc_err("Interrupted by a signal\n");
-               return 1;
-       }
-       mfc_debug(1, "Finished waiting (dev->int_type:%d, command: %d)\n",
-                                                       dev->int_type, command);
-       if (dev->int_type == S5P_MFC_R2H_CMD_ERR_RET)
-               return 1;
-       return 0;
-}
-
-void s5p_mfc_clean_dev_int_flags(struct s5p_mfc_dev *dev)
-{
-       dev->int_cond = 0;
-       dev->int_type = 0;
-       dev->int_err = 0;
-}
-
-int s5p_mfc_wait_for_done_ctx(struct s5p_mfc_ctx *ctx,
-                                   int command, int interrupt)
-{
-       int ret;
-
-       if (interrupt) {
-               ret = wait_event_interruptible_timeout(ctx->queue,
-                               (ctx->int_cond && (ctx->int_type == command
-                       || ctx->int_type == S5P_MFC_R2H_CMD_ERR_RET)),
-                                       msecs_to_jiffies(MFC_INT_TIMEOUT));
-       } else {
-               ret = wait_event_timeout(ctx->queue,
-                               (ctx->int_cond && (ctx->int_type == command
-                       || ctx->int_type == S5P_MFC_R2H_CMD_ERR_RET)),
-                                       msecs_to_jiffies(MFC_INT_TIMEOUT));
-       }
-       if (ret == 0) {
-               mfc_err("Interrupt (ctx->int_type:%d, command:%d) timed out\n",
-                                                       ctx->int_type, command);
-               return 1;
-       } else if (ret == -ERESTARTSYS) {
-               mfc_err("Interrupted by a signal\n");
-               return 1;
-       }
-       mfc_debug(1, "Finished waiting (ctx->int_type:%d, command: %d)\n",
-                                                       ctx->int_type, command);
-       if (ctx->int_type == S5P_MFC_R2H_CMD_ERR_RET)
-               return 1;
-       return 0;
-}
-
-void s5p_mfc_clean_ctx_int_flags(struct s5p_mfc_ctx *ctx)
-{
-       ctx->int_cond = 0;
-       ctx->int_type = 0;
-       ctx->int_err = 0;
-}
-
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_intr.h b/drivers/media/platform/s5p-mfc/s5p_mfc_intr.h
deleted file mode 100644 (file)
index d32860d..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * drivers/media/platform/samsung/mfc5/s5p_mfc_intr.h
- *
- * Header file for Samsung MFC (Multi Function Codec - FIMV) driver
- * It contains waiting functions declarations.
- *
- * Kamil Debski, Copyright (C) 2011 Samsung Electronics
- * http://www.samsung.com/
- */
-
-#ifndef S5P_MFC_INTR_H_
-#define S5P_MFC_INTR_H_
-
-#include "s5p_mfc_common.h"
-
-int s5p_mfc_wait_for_done_ctx(struct s5p_mfc_ctx *ctx,
-                             int command, int interrupt);
-int s5p_mfc_wait_for_done_dev(struct s5p_mfc_dev *dev, int command);
-void s5p_mfc_clean_ctx_int_flags(struct s5p_mfc_ctx *ctx);
-void s5p_mfc_clean_dev_int_flags(struct s5p_mfc_dev *dev);
-
-#endif /* S5P_MFC_INTR_H_ */
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_iommu.h b/drivers/media/platform/s5p-mfc/s5p_mfc_iommu.h
deleted file mode 100644 (file)
index 1a32266..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2015 Samsung Electronics Co.Ltd
- * Authors: Marek Szyprowski <m.szyprowski@samsung.com>
- */
-
-#ifndef S5P_MFC_IOMMU_H_
-#define S5P_MFC_IOMMU_H_
-
-#if defined(CONFIG_EXYNOS_IOMMU)
-
-#include <linux/iommu.h>
-
-static inline bool exynos_is_iommu_available(struct device *dev)
-{
-       return dev_iommu_priv_get(dev) != NULL;
-}
-
-#else
-
-static inline bool exynos_is_iommu_available(struct device *dev)
-{
-       return false;
-}
-
-#endif
-
-#endif /* S5P_MFC_IOMMU_H_ */
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c
deleted file mode 100644 (file)
index bb65671..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * drivers/media/platform/s5p-mfc/s5p_mfc_opr.c
- *
- * Samsung MFC (Multi Function Codec - FIMV) driver
- * This file contains hw related functions.
- *
- * Kamil Debski, Copyright (c) 2012 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- */
-
-#include "s5p_mfc_debug.h"
-#include "s5p_mfc_opr.h"
-#include "s5p_mfc_opr_v5.h"
-#include "s5p_mfc_opr_v6.h"
-
-static struct s5p_mfc_hw_ops *s5p_mfc_ops;
-
-void s5p_mfc_init_hw_ops(struct s5p_mfc_dev *dev)
-{
-       if (IS_MFCV6_PLUS(dev)) {
-               s5p_mfc_ops = s5p_mfc_init_hw_ops_v6();
-               dev->warn_start = S5P_FIMV_ERR_WARNINGS_START_V6;
-       } else {
-               s5p_mfc_ops = s5p_mfc_init_hw_ops_v5();
-               dev->warn_start = S5P_FIMV_ERR_WARNINGS_START;
-       }
-       dev->mfc_ops = s5p_mfc_ops;
-}
-
-void s5p_mfc_init_regs(struct s5p_mfc_dev *dev)
-{
-       if (IS_MFCV6_PLUS(dev))
-               dev->mfc_regs = s5p_mfc_init_regs_v6_plus(dev);
-}
-
-int s5p_mfc_alloc_priv_buf(struct s5p_mfc_dev *dev, unsigned int mem_ctx,
-                          struct s5p_mfc_priv_buf *b)
-{
-       unsigned int bits = dev->mem_size >> PAGE_SHIFT;
-       unsigned int count = b->size >> PAGE_SHIFT;
-       unsigned int align = (SZ_64K >> PAGE_SHIFT) - 1;
-       unsigned int start, offset;
-
-       mfc_debug(3, "Allocating priv: %zu\n", b->size);
-
-       if (dev->mem_virt) {
-               start = bitmap_find_next_zero_area(dev->mem_bitmap, bits, 0, count, align);
-               if (start > bits)
-                       goto no_mem;
-
-               bitmap_set(dev->mem_bitmap, start, count);
-               offset = start << PAGE_SHIFT;
-               b->virt = dev->mem_virt + offset;
-               b->dma = dev->mem_base + offset;
-       } else {
-               struct device *mem_dev = dev->mem_dev[mem_ctx];
-               dma_addr_t base = dev->dma_base[mem_ctx];
-
-               b->ctx = mem_ctx;
-               b->virt = dma_alloc_coherent(mem_dev, b->size, &b->dma, GFP_KERNEL);
-               if (!b->virt)
-                       goto no_mem;
-               if (b->dma < base) {
-                       mfc_err("Invalid memory configuration - buffer (%pad) is below base memory address(%pad)\n",
-                               &b->dma, &base);
-                       dma_free_coherent(mem_dev, b->size, b->virt, b->dma);
-                       return -ENOMEM;
-               }
-       }
-
-       mfc_debug(3, "Allocated addr %p %pad\n", b->virt, &b->dma);
-       return 0;
-no_mem:
-       mfc_err("Allocating private buffer of size %zu failed\n", b->size);
-       return -ENOMEM;
-}
-
-int s5p_mfc_alloc_generic_buf(struct s5p_mfc_dev *dev, unsigned int mem_ctx,
-                          struct s5p_mfc_priv_buf *b)
-{
-       struct device *mem_dev = dev->mem_dev[mem_ctx];
-
-       mfc_debug(3, "Allocating generic buf: %zu\n", b->size);
-
-       b->ctx = mem_ctx;
-       b->virt = dma_alloc_coherent(mem_dev, b->size, &b->dma, GFP_KERNEL);
-       if (!b->virt)
-               goto no_mem;
-
-       mfc_debug(3, "Allocated addr %p %pad\n", b->virt, &b->dma);
-       return 0;
-no_mem:
-       mfc_err("Allocating generic buffer of size %zu failed\n", b->size);
-       return -ENOMEM;
-}
-
-void s5p_mfc_release_priv_buf(struct s5p_mfc_dev *dev,
-                             struct s5p_mfc_priv_buf *b)
-{
-       if (dev->mem_virt) {
-               unsigned int start = (b->dma - dev->mem_base) >> PAGE_SHIFT;
-               unsigned int count = b->size >> PAGE_SHIFT;
-
-               bitmap_clear(dev->mem_bitmap, start, count);
-       } else {
-               struct device *mem_dev = dev->mem_dev[b->ctx];
-
-               dma_free_coherent(mem_dev, b->size, b->virt, b->dma);
-       }
-       b->virt = NULL;
-       b->dma = 0;
-       b->size = 0;
-}
-
-void s5p_mfc_release_generic_buf(struct s5p_mfc_dev *dev,
-                             struct s5p_mfc_priv_buf *b)
-{
-       struct device *mem_dev = dev->mem_dev[b->ctx];
-       dma_free_coherent(mem_dev, b->size, b->virt, b->dma);
-       b->virt = NULL;
-       b->dma = 0;
-       b->size = 0;
-}
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h b/drivers/media/platform/s5p-mfc/s5p_mfc_opr.h
deleted file mode 100644 (file)
index 1c5d2d4..0000000
+++ /dev/null
@@ -1,339 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * drivers/media/platform/s5p-mfc/s5p_mfc_opr.h
- *
- * Header file for Samsung MFC (Multi Function Codec - FIMV) driver
- * Contains declarations of hw related functions.
- *
- * Kamil Debski, Copyright (C) 2012 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- */
-
-#ifndef S5P_MFC_OPR_H_
-#define S5P_MFC_OPR_H_
-
-#include "s5p_mfc_common.h"
-
-struct s5p_mfc_regs {
-
-       /* codec common registers */
-       void __iomem *risc_on;
-       void __iomem *risc2host_int;
-       void __iomem *host2risc_int;
-       void __iomem *risc_base_address;
-       void __iomem *mfc_reset;
-       void __iomem *host2risc_command;
-       void __iomem *risc2host_command;
-       void __iomem *mfc_bus_reset_ctrl;
-       void __iomem *firmware_version;
-       void __iomem *instance_id;
-       void __iomem *codec_type;
-       void __iomem *context_mem_addr;
-       void __iomem *context_mem_size;
-       void __iomem *pixel_format;
-       void __iomem *metadata_enable;
-       void __iomem *mfc_version;
-       void __iomem *dbg_info_enable;
-       void __iomem *dbg_buffer_addr;
-       void __iomem *dbg_buffer_size;
-       void __iomem *hed_control;
-       void __iomem *mfc_timeout_value;
-       void __iomem *hed_shared_mem_addr;
-       void __iomem *dis_shared_mem_addr;/* only v7 */
-       void __iomem *ret_instance_id;
-       void __iomem *error_code;
-       void __iomem *dbg_buffer_output_size;
-       void __iomem *metadata_status;
-       void __iomem *metadata_addr_mb_info;
-       void __iomem *metadata_size_mb_info;
-       void __iomem *dbg_info_stage_counter;
-
-       /* decoder registers */
-       void __iomem *d_crc_ctrl;
-       void __iomem *d_dec_options;
-       void __iomem *d_display_delay;
-       void __iomem *d_set_frame_width;
-       void __iomem *d_set_frame_height;
-       void __iomem *d_sei_enable;
-       void __iomem *d_min_num_dpb;
-       void __iomem *d_min_first_plane_dpb_size;
-       void __iomem *d_min_second_plane_dpb_size;
-       void __iomem *d_min_third_plane_dpb_size;/* only v8 */
-       void __iomem *d_min_num_mv;
-       void __iomem *d_mvc_num_views;
-       void __iomem *d_min_num_dis;/* only v7 */
-       void __iomem *d_min_first_dis_size;/* only v7 */
-       void __iomem *d_min_second_dis_size;/* only v7 */
-       void __iomem *d_min_third_dis_size;/* only v7 */
-       void __iomem *d_post_filter_luma_dpb0;/*  v7 and v8 */
-       void __iomem *d_post_filter_luma_dpb1;/* v7 and v8 */
-       void __iomem *d_post_filter_luma_dpb2;/* only v7 */
-       void __iomem *d_post_filter_chroma_dpb0;/* v7 and v8 */
-       void __iomem *d_post_filter_chroma_dpb1;/* v7 and v8 */
-       void __iomem *d_post_filter_chroma_dpb2;/* only v7 */
-       void __iomem *d_num_dpb;
-       void __iomem *d_num_mv;
-       void __iomem *d_init_buffer_options;
-       void __iomem *d_first_plane_dpb_stride_size;/* only v8 */
-       void __iomem *d_second_plane_dpb_stride_size;/* only v8 */
-       void __iomem *d_third_plane_dpb_stride_size;/* only v8 */
-       void __iomem *d_first_plane_dpb_size;
-       void __iomem *d_second_plane_dpb_size;
-       void __iomem *d_third_plane_dpb_size;/* only v8 */
-       void __iomem *d_mv_buffer_size;
-       void __iomem *d_first_plane_dpb;
-       void __iomem *d_second_plane_dpb;
-       void __iomem *d_third_plane_dpb;
-       void __iomem *d_mv_buffer;
-       void __iomem *d_scratch_buffer_addr;
-       void __iomem *d_scratch_buffer_size;
-       void __iomem *d_metadata_buffer_addr;
-       void __iomem *d_metadata_buffer_size;
-       void __iomem *d_nal_start_options;/* v7 and v8 */
-       void __iomem *d_cpb_buffer_addr;
-       void __iomem *d_cpb_buffer_size;
-       void __iomem *d_available_dpb_flag_upper;
-       void __iomem *d_available_dpb_flag_lower;
-       void __iomem *d_cpb_buffer_offset;
-       void __iomem *d_slice_if_enable;
-       void __iomem *d_picture_tag;
-       void __iomem *d_stream_data_size;
-       void __iomem *d_dynamic_dpb_flag_upper;/* v7 and v8 */
-       void __iomem *d_dynamic_dpb_flag_lower;/* v7 and v8 */
-       void __iomem *d_display_frame_width;
-       void __iomem *d_display_frame_height;
-       void __iomem *d_display_status;
-       void __iomem *d_display_first_plane_addr;
-       void __iomem *d_display_second_plane_addr;
-       void __iomem *d_display_third_plane_addr;/* only v8 */
-       void __iomem *d_display_frame_type;
-       void __iomem *d_display_crop_info1;
-       void __iomem *d_display_crop_info2;
-       void __iomem *d_display_picture_profile;
-       void __iomem *d_display_luma_crc;/* v7 and v8 */
-       void __iomem *d_display_chroma0_crc;/* v7 and v8 */
-       void __iomem *d_display_chroma1_crc;/* only v8 */
-       void __iomem *d_display_luma_crc_top;/* only v6 */
-       void __iomem *d_display_chroma_crc_top;/* only v6 */
-       void __iomem *d_display_luma_crc_bot;/* only v6 */
-       void __iomem *d_display_chroma_crc_bot;/* only v6 */
-       void __iomem *d_display_aspect_ratio;
-       void __iomem *d_display_extended_ar;
-       void __iomem *d_decoded_frame_width;
-       void __iomem *d_decoded_frame_height;
-       void __iomem *d_decoded_status;
-       void __iomem *d_decoded_first_plane_addr;
-       void __iomem *d_decoded_second_plane_addr;
-       void __iomem *d_decoded_third_plane_addr;/* only v8 */
-       void __iomem *d_decoded_frame_type;
-       void __iomem *d_decoded_crop_info1;
-       void __iomem *d_decoded_crop_info2;
-       void __iomem *d_decoded_picture_profile;
-       void __iomem *d_decoded_nal_size;
-       void __iomem *d_decoded_luma_crc;
-       void __iomem *d_decoded_chroma0_crc;
-       void __iomem *d_decoded_chroma1_crc;/* only v8 */
-       void __iomem *d_ret_picture_tag_top;
-       void __iomem *d_ret_picture_tag_bot;
-       void __iomem *d_ret_picture_time_top;
-       void __iomem *d_ret_picture_time_bot;
-       void __iomem *d_chroma_format;
-       void __iomem *d_vc1_info;/* v7 and v8 */
-       void __iomem *d_mpeg4_info;
-       void __iomem *d_h264_info;
-       void __iomem *d_metadata_addr_concealed_mb;
-       void __iomem *d_metadata_size_concealed_mb;
-       void __iomem *d_metadata_addr_vc1_param;
-       void __iomem *d_metadata_size_vc1_param;
-       void __iomem *d_metadata_addr_sei_nal;
-       void __iomem *d_metadata_size_sei_nal;
-       void __iomem *d_metadata_addr_vui;
-       void __iomem *d_metadata_size_vui;
-       void __iomem *d_metadata_addr_mvcvui;/* v7 and v8 */
-       void __iomem *d_metadata_size_mvcvui;/* v7 and v8 */
-       void __iomem *d_mvc_view_id;
-       void __iomem *d_frame_pack_sei_avail;
-       void __iomem *d_frame_pack_arrgment_id;
-       void __iomem *d_frame_pack_sei_info;
-       void __iomem *d_frame_pack_grid_pos;
-       void __iomem *d_display_recovery_sei_info;/* v7 and v8 */
-       void __iomem *d_decoded_recovery_sei_info;/* v7 and v8 */
-       void __iomem *d_display_first_addr;/* only v7 */
-       void __iomem *d_display_second_addr;/* only v7 */
-       void __iomem *d_display_third_addr;/* only v7 */
-       void __iomem *d_decoded_first_addr;/* only v7 */
-       void __iomem *d_decoded_second_addr;/* only v7 */
-       void __iomem *d_decoded_third_addr;/* only v7 */
-       void __iomem *d_used_dpb_flag_upper;/* v7 and v8 */
-       void __iomem *d_used_dpb_flag_lower;/* v7 and v8 */
-       void __iomem *d_min_scratch_buffer_size; /* v10 */
-       void __iomem *d_static_buffer_addr; /* v10 */
-       void __iomem *d_static_buffer_size; /* v10 */
-
-       /* encoder registers */
-       void __iomem *e_frame_width;
-       void __iomem *e_frame_height;
-       void __iomem *e_cropped_frame_width;
-       void __iomem *e_cropped_frame_height;
-       void __iomem *e_frame_crop_offset;
-       void __iomem *e_enc_options;
-       void __iomem *e_picture_profile;
-       void __iomem *e_vbv_buffer_size;
-       void __iomem *e_vbv_init_delay;
-       void __iomem *e_fixed_picture_qp;
-       void __iomem *e_rc_config;
-       void __iomem *e_rc_qp_bound;
-       void __iomem *e_rc_qp_bound_pb;/* v7 and v8 */
-       void __iomem *e_rc_mode;
-       void __iomem *e_mb_rc_config;
-       void __iomem *e_padding_ctrl;
-       void __iomem *e_air_threshold;
-       void __iomem *e_mv_hor_range;
-       void __iomem *e_mv_ver_range;
-       void __iomem *e_num_dpb;
-       void __iomem *e_luma_dpb;
-       void __iomem *e_chroma_dpb;
-       void __iomem *e_me_buffer;
-       void __iomem *e_scratch_buffer_addr;
-       void __iomem *e_scratch_buffer_size;
-       void __iomem *e_tmv_buffer0;
-       void __iomem *e_tmv_buffer1;
-       void __iomem *e_ir_buffer_addr;/* v7 and v8 */
-       void __iomem *e_source_first_plane_addr;
-       void __iomem *e_source_second_plane_addr;
-       void __iomem *e_source_third_plane_addr;/* v7 and v8 */
-       void __iomem *e_source_first_plane_stride;/* v7 and v8 */
-       void __iomem *e_source_second_plane_stride;/* v7 and v8 */
-       void __iomem *e_source_third_plane_stride;/* v7 and v8 */
-       void __iomem *e_stream_buffer_addr;
-       void __iomem *e_stream_buffer_size;
-       void __iomem *e_roi_buffer_addr;
-       void __iomem *e_param_change;
-       void __iomem *e_ir_size;
-       void __iomem *e_gop_config;
-       void __iomem *e_mslice_mode;
-       void __iomem *e_mslice_size_mb;
-       void __iomem *e_mslice_size_bits;
-       void __iomem *e_frame_insertion;
-       void __iomem *e_rc_frame_rate;
-       void __iomem *e_rc_bit_rate;
-       void __iomem *e_rc_roi_ctrl;
-       void __iomem *e_picture_tag;
-       void __iomem *e_bit_count_enable;
-       void __iomem *e_max_bit_count;
-       void __iomem *e_min_bit_count;
-       void __iomem *e_metadata_buffer_addr;
-       void __iomem *e_metadata_buffer_size;
-       void __iomem *e_encoded_source_first_plane_addr;
-       void __iomem *e_encoded_source_second_plane_addr;
-       void __iomem *e_encoded_source_third_plane_addr;/* v7 and v8 */
-       void __iomem *e_stream_size;
-       void __iomem *e_slice_type;
-       void __iomem *e_picture_count;
-       void __iomem *e_ret_picture_tag;
-       void __iomem *e_stream_buffer_write_pointer; /*  only v6 */
-       void __iomem *e_recon_luma_dpb_addr;
-       void __iomem *e_recon_chroma_dpb_addr;
-       void __iomem *e_metadata_addr_enc_slice;
-       void __iomem *e_metadata_size_enc_slice;
-       void __iomem *e_mpeg4_options;
-       void __iomem *e_mpeg4_hec_period;
-       void __iomem *e_aspect_ratio;
-       void __iomem *e_extended_sar;
-       void __iomem *e_h264_options;
-       void __iomem *e_h264_options_2;/* v7 and v8 */
-       void __iomem *e_h264_lf_alpha_offset;
-       void __iomem *e_h264_lf_beta_offset;
-       void __iomem *e_h264_i_period;
-       void __iomem *e_h264_fmo_slice_grp_map_type;
-       void __iomem *e_h264_fmo_num_slice_grp_minus1;
-       void __iomem *e_h264_fmo_slice_grp_change_dir;
-       void __iomem *e_h264_fmo_slice_grp_change_rate_minus1;
-       void __iomem *e_h264_fmo_run_length_minus1_0;
-       void __iomem *e_h264_aso_slice_order_0;
-       void __iomem *e_h264_chroma_qp_offset;
-       void __iomem *e_h264_num_t_layer;
-       void __iomem *e_h264_hierarchical_qp_layer0;
-       void __iomem *e_h264_frame_packing_sei_info;
-       void __iomem *e_h264_nal_control;/* v7 and v8 */
-       void __iomem *e_mvc_frame_qp_view1;
-       void __iomem *e_mvc_rc_bit_rate_view1;
-       void __iomem *e_mvc_rc_qbound_view1;
-       void __iomem *e_mvc_rc_mode_view1;
-       void __iomem *e_mvc_inter_view_prediction_on;
-       void __iomem *e_vp8_options;/* v7 and v8 */
-       void __iomem *e_vp8_filter_options;/* v7 and v8 */
-       void __iomem *e_vp8_golden_frame_option;/* v7 and v8 */
-       void __iomem *e_vp8_num_t_layer;/* v7 and v8 */
-       void __iomem *e_vp8_hierarchical_qp_layer0;/* v7 and v8 */
-       void __iomem *e_vp8_hierarchical_qp_layer1;/* v7 and v8 */
-       void __iomem *e_vp8_hierarchical_qp_layer2;/* v7 and v8 */
-       void __iomem *e_min_scratch_buffer_size; /* v10 */
-       void __iomem *e_num_t_layer; /* v10 */
-       void __iomem *e_hier_qp_layer0; /* v10 */
-       void __iomem *e_hier_bit_rate_layer0; /* v10 */
-       void __iomem *e_hevc_options; /* v10 */
-       void __iomem *e_hevc_refresh_period; /* v10 */
-       void __iomem *e_hevc_lf_beta_offset_div2; /* v10 */
-       void __iomem *e_hevc_lf_tc_offset_div2; /* v10 */
-       void __iomem *e_hevc_nal_control; /* v10 */
-};
-
-struct s5p_mfc_hw_ops {
-       int (*alloc_dec_temp_buffers)(struct s5p_mfc_ctx *ctx);
-       void (*release_dec_desc_buffer)(struct s5p_mfc_ctx *ctx);
-       int (*alloc_codec_buffers)(struct s5p_mfc_ctx *ctx);
-       void (*release_codec_buffers)(struct s5p_mfc_ctx *ctx);
-       int (*alloc_instance_buffer)(struct s5p_mfc_ctx *ctx);
-       void (*release_instance_buffer)(struct s5p_mfc_ctx *ctx);
-       int (*alloc_dev_context_buffer)(struct s5p_mfc_dev *dev);
-       void (*release_dev_context_buffer)(struct s5p_mfc_dev *dev);
-       void (*dec_calc_dpb_size)(struct s5p_mfc_ctx *ctx);
-       void (*enc_calc_src_size)(struct s5p_mfc_ctx *ctx);
-       int (*set_enc_stream_buffer)(struct s5p_mfc_ctx *ctx,
-                       unsigned long addr, unsigned int size);
-       void (*set_enc_frame_buffer)(struct s5p_mfc_ctx *ctx,
-                       unsigned long y_addr, unsigned long c_addr);
-       void (*get_enc_frame_buffer)(struct s5p_mfc_ctx *ctx,
-                       unsigned long *y_addr, unsigned long *c_addr);
-       void (*try_run)(struct s5p_mfc_dev *dev);
-       void (*clear_int_flags)(struct s5p_mfc_dev *dev);
-       int (*get_dspl_y_adr)(struct s5p_mfc_dev *dev);
-       int (*get_dec_y_adr)(struct s5p_mfc_dev *dev);
-       int (*get_dspl_status)(struct s5p_mfc_dev *dev);
-       int (*get_dec_status)(struct s5p_mfc_dev *dev);
-       int (*get_dec_frame_type)(struct s5p_mfc_dev *dev);
-       int (*get_disp_frame_type)(struct s5p_mfc_ctx *ctx);
-       int (*get_consumed_stream)(struct s5p_mfc_dev *dev);
-       int (*get_int_reason)(struct s5p_mfc_dev *dev);
-       int (*get_int_err)(struct s5p_mfc_dev *dev);
-       int (*err_dec)(unsigned int err);
-       int (*get_img_width)(struct s5p_mfc_dev *dev);
-       int (*get_img_height)(struct s5p_mfc_dev *dev);
-       int (*get_dpb_count)(struct s5p_mfc_dev *dev);
-       int (*get_mv_count)(struct s5p_mfc_dev *dev);
-       int (*get_inst_no)(struct s5p_mfc_dev *dev);
-       int (*get_enc_strm_size)(struct s5p_mfc_dev *dev);
-       int (*get_enc_slice_type)(struct s5p_mfc_dev *dev);
-       int (*get_enc_dpb_count)(struct s5p_mfc_dev *dev);
-       unsigned int (*get_pic_type_top)(struct s5p_mfc_ctx *ctx);
-       unsigned int (*get_pic_type_bot)(struct s5p_mfc_ctx *ctx);
-       unsigned int (*get_crop_info_h)(struct s5p_mfc_ctx *ctx);
-       unsigned int (*get_crop_info_v)(struct s5p_mfc_ctx *ctx);
-       int (*get_min_scratch_buf_size)(struct s5p_mfc_dev *dev);
-       int (*get_e_min_scratch_buf_size)(struct s5p_mfc_dev *dev);
-};
-
-void s5p_mfc_init_hw_ops(struct s5p_mfc_dev *dev);
-void s5p_mfc_init_regs(struct s5p_mfc_dev *dev);
-int s5p_mfc_alloc_priv_buf(struct s5p_mfc_dev *dev, unsigned int mem_ctx,
-                          struct s5p_mfc_priv_buf *b);
-void s5p_mfc_release_priv_buf(struct s5p_mfc_dev *dev,
-                             struct s5p_mfc_priv_buf *b);
-int s5p_mfc_alloc_generic_buf(struct s5p_mfc_dev *dev, unsigned int mem_ctx,
-                          struct s5p_mfc_priv_buf *b);
-void s5p_mfc_release_generic_buf(struct s5p_mfc_dev *dev,
-                             struct s5p_mfc_priv_buf *b);
-
-
-#endif /* S5P_MFC_OPR_H_ */
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c
deleted file mode 100644 (file)
index 28a06dc..0000000
+++ /dev/null
@@ -1,1637 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * drivers/media/platform/samsung/mfc5/s5p_mfc_opr_v5.c
- *
- * Samsung MFC (Multi Function Codec - FIMV) driver
- * This file contains hw related functions.
- *
- * Kamil Debski, Copyright (c) 2011 Samsung Electronics
- * http://www.samsung.com/
- */
-
-#include "s5p_mfc_common.h"
-#include "s5p_mfc_cmd.h"
-#include "s5p_mfc_ctrl.h"
-#include "s5p_mfc_debug.h"
-#include "s5p_mfc_intr.h"
-#include "s5p_mfc_pm.h"
-#include "s5p_mfc_opr.h"
-#include "s5p_mfc_opr_v5.h"
-#include <asm/cacheflush.h>
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
-#include <linux/err.h>
-#include <linux/firmware.h>
-#include <linux/io.h>
-#include <linux/jiffies.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-
-#define OFFSETA(x)             (((x) - dev->dma_base[BANK_L_CTX]) >> MFC_OFFSET_SHIFT)
-#define OFFSETB(x)             (((x) - dev->dma_base[BANK_R_CTX]) >> MFC_OFFSET_SHIFT)
-
-/* Allocate temporary buffers for decoding */
-static int s5p_mfc_alloc_dec_temp_buffers_v5(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_buf_size_v5 *buf_size = dev->variant->buf_size->priv;
-       int ret;
-
-       ctx->dsc.size = buf_size->dsc;
-       ret =  s5p_mfc_alloc_priv_buf(dev, BANK_L_CTX, &ctx->dsc);
-       if (ret) {
-               mfc_err("Failed to allocate temporary buffer\n");
-               return ret;
-       }
-
-       BUG_ON(ctx->dsc.dma & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
-       memset(ctx->dsc.virt, 0, ctx->dsc.size);
-       wmb();
-       return 0;
-}
-
-
-/* Release temporary buffers for decoding */
-static void s5p_mfc_release_dec_desc_buffer_v5(struct s5p_mfc_ctx *ctx)
-{
-       s5p_mfc_release_priv_buf(ctx->dev, &ctx->dsc);
-}
-
-/* Allocate codec buffers */
-static int s5p_mfc_alloc_codec_buffers_v5(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       unsigned int enc_ref_y_size = 0;
-       unsigned int enc_ref_c_size = 0;
-       unsigned int guard_width, guard_height;
-       int ret;
-
-       if (ctx->type == MFCINST_DECODER) {
-               mfc_debug(2, "Luma size:%d Chroma size:%d MV size:%d\n",
-                         ctx->luma_size, ctx->chroma_size, ctx->mv_size);
-               mfc_debug(2, "Totals bufs: %d\n", ctx->total_dpb_count);
-       } else if (ctx->type == MFCINST_ENCODER) {
-               enc_ref_y_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
-                       * ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);
-               enc_ref_y_size = ALIGN(enc_ref_y_size, S5P_FIMV_NV12MT_SALIGN);
-
-               if (ctx->codec_mode == S5P_MFC_CODEC_H264_ENC) {
-                       enc_ref_c_size = ALIGN(ctx->img_width,
-                                               S5P_FIMV_NV12MT_HALIGN)
-                                               * ALIGN(ctx->img_height >> 1,
-                                               S5P_FIMV_NV12MT_VALIGN);
-                       enc_ref_c_size = ALIGN(enc_ref_c_size,
-                                                       S5P_FIMV_NV12MT_SALIGN);
-               } else {
-                       guard_width = ALIGN(ctx->img_width + 16,
-                                                       S5P_FIMV_NV12MT_HALIGN);
-                       guard_height = ALIGN((ctx->img_height >> 1) + 4,
-                                                       S5P_FIMV_NV12MT_VALIGN);
-                       enc_ref_c_size = ALIGN(guard_width * guard_height,
-                                              S5P_FIMV_NV12MT_SALIGN);
-               }
-               mfc_debug(2, "recon luma size: %d chroma size: %d\n",
-                         enc_ref_y_size, enc_ref_c_size);
-       } else {
-               return -EINVAL;
-       }
-       /* Codecs have different memory requirements */
-       switch (ctx->codec_mode) {
-       case S5P_MFC_CODEC_H264_DEC:
-               ctx->bank1.size =
-                   ALIGN(S5P_FIMV_DEC_NB_IP_SIZE +
-                                       S5P_FIMV_DEC_VERT_NB_MV_SIZE,
-                                       S5P_FIMV_DEC_BUF_ALIGN);
-               ctx->bank2.size = ctx->total_dpb_count * ctx->mv_size;
-               break;
-       case S5P_MFC_CODEC_MPEG4_DEC:
-               ctx->bank1.size =
-                   ALIGN(S5P_FIMV_DEC_NB_DCAC_SIZE +
-                                    S5P_FIMV_DEC_UPNB_MV_SIZE +
-                                    S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE +
-                                    S5P_FIMV_DEC_STX_PARSER_SIZE +
-                                    S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE,
-                                    S5P_FIMV_DEC_BUF_ALIGN);
-               ctx->bank2.size = 0;
-               break;
-       case S5P_MFC_CODEC_VC1RCV_DEC:
-       case S5P_MFC_CODEC_VC1_DEC:
-               ctx->bank1.size =
-                   ALIGN(S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE +
-                            S5P_FIMV_DEC_UPNB_MV_SIZE +
-                            S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE +
-                            S5P_FIMV_DEC_NB_DCAC_SIZE +
-                            3 * S5P_FIMV_DEC_VC1_BITPLANE_SIZE,
-                            S5P_FIMV_DEC_BUF_ALIGN);
-               ctx->bank2.size = 0;
-               break;
-       case S5P_MFC_CODEC_MPEG2_DEC:
-               ctx->bank1.size = 0;
-               ctx->bank2.size = 0;
-               break;
-       case S5P_MFC_CODEC_H263_DEC:
-               ctx->bank1.size =
-                   ALIGN(S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE +
-                            S5P_FIMV_DEC_UPNB_MV_SIZE +
-                            S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE +
-                            S5P_FIMV_DEC_NB_DCAC_SIZE,
-                            S5P_FIMV_DEC_BUF_ALIGN);
-               ctx->bank2.size = 0;
-               break;
-       case S5P_MFC_CODEC_H264_ENC:
-               ctx->bank1.size = (enc_ref_y_size * 2) +
-                                  S5P_FIMV_ENC_UPMV_SIZE +
-                                  S5P_FIMV_ENC_COLFLG_SIZE +
-                                  S5P_FIMV_ENC_INTRAMD_SIZE +
-                                  S5P_FIMV_ENC_NBORINFO_SIZE;
-               ctx->bank2.size = (enc_ref_y_size * 2) +
-                                  (enc_ref_c_size * 4) +
-                                  S5P_FIMV_ENC_INTRAPRED_SIZE;
-               break;
-       case S5P_MFC_CODEC_MPEG4_ENC:
-               ctx->bank1.size = (enc_ref_y_size * 2) +
-                                  S5P_FIMV_ENC_UPMV_SIZE +
-                                  S5P_FIMV_ENC_COLFLG_SIZE +
-                                  S5P_FIMV_ENC_ACDCCOEF_SIZE;
-               ctx->bank2.size = (enc_ref_y_size * 2) +
-                                  (enc_ref_c_size * 4);
-               break;
-       case S5P_MFC_CODEC_H263_ENC:
-               ctx->bank1.size = (enc_ref_y_size * 2) +
-                                  S5P_FIMV_ENC_UPMV_SIZE +
-                                  S5P_FIMV_ENC_ACDCCOEF_SIZE;
-               ctx->bank2.size = (enc_ref_y_size * 2) +
-                                  (enc_ref_c_size * 4);
-               break;
-       default:
-               break;
-       }
-       /* Allocate only if memory from bank 1 is necessary */
-       if (ctx->bank1.size > 0) {
-
-               ret = s5p_mfc_alloc_priv_buf(dev, BANK_L_CTX, &ctx->bank1);
-               if (ret) {
-                       mfc_err("Failed to allocate Bank1 temporary buffer\n");
-                       return ret;
-               }
-               BUG_ON(ctx->bank1.dma & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
-       }
-       /* Allocate only if memory from bank 2 is necessary */
-       if (ctx->bank2.size > 0) {
-               ret = s5p_mfc_alloc_priv_buf(dev, BANK_R_CTX, &ctx->bank2);
-               if (ret) {
-                       mfc_err("Failed to allocate Bank2 temporary buffer\n");
-                       s5p_mfc_release_priv_buf(ctx->dev, &ctx->bank1);
-                       return ret;
-               }
-               BUG_ON(ctx->bank2.dma & ((1 << MFC_BANK2_ALIGN_ORDER) - 1));
-       }
-       return 0;
-}
-
-/* Release buffers allocated for codec */
-static void s5p_mfc_release_codec_buffers_v5(struct s5p_mfc_ctx *ctx)
-{
-       s5p_mfc_release_priv_buf(ctx->dev, &ctx->bank1);
-       s5p_mfc_release_priv_buf(ctx->dev, &ctx->bank2);
-}
-
-/* Allocate memory for instance data buffer */
-static int s5p_mfc_alloc_instance_buffer_v5(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_buf_size_v5 *buf_size = dev->variant->buf_size->priv;
-       int ret;
-
-       if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC ||
-               ctx->codec_mode == S5P_MFC_CODEC_H264_ENC)
-               ctx->ctx.size = buf_size->h264_ctx;
-       else
-               ctx->ctx.size = buf_size->non_h264_ctx;
-
-       ret = s5p_mfc_alloc_priv_buf(dev, BANK_L_CTX, &ctx->ctx);
-       if (ret) {
-               mfc_err("Failed to allocate instance buffer\n");
-               return ret;
-       }
-       ctx->ctx.ofs = OFFSETA(ctx->ctx.dma);
-
-       /* Zero content of the allocated memory */
-       memset(ctx->ctx.virt, 0, ctx->ctx.size);
-       wmb();
-
-       /* Initialize shared memory */
-       ctx->shm.size = buf_size->shm;
-       ret = s5p_mfc_alloc_priv_buf(dev, BANK_L_CTX, &ctx->shm);
-       if (ret) {
-               mfc_err("Failed to allocate shared memory buffer\n");
-               s5p_mfc_release_priv_buf(dev, &ctx->ctx);
-               return ret;
-       }
-
-       /* shared memory offset only keeps the offset from base (port a) */
-       ctx->shm.ofs = ctx->shm.dma - dev->dma_base[BANK_L_CTX];
-       BUG_ON(ctx->shm.ofs & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
-
-       memset(ctx->shm.virt, 0, buf_size->shm);
-       wmb();
-       return 0;
-}
-
-/* Release instance buffer */
-static void s5p_mfc_release_instance_buffer_v5(struct s5p_mfc_ctx *ctx)
-{
-       s5p_mfc_release_priv_buf(ctx->dev, &ctx->ctx);
-       s5p_mfc_release_priv_buf(ctx->dev, &ctx->shm);
-}
-
-static int s5p_mfc_alloc_dev_context_buffer_v5(struct s5p_mfc_dev *dev)
-{
-       /* NOP */
-
-       return 0;
-}
-
-static void s5p_mfc_release_dev_context_buffer_v5(struct s5p_mfc_dev *dev)
-{
-       /* NOP */
-}
-
-static void s5p_mfc_write_info_v5(struct s5p_mfc_ctx *ctx, unsigned int data,
-                       unsigned int ofs)
-{
-       *(u32 *)(ctx->shm.virt + ofs) = data;
-       wmb();
-}
-
-static unsigned int s5p_mfc_read_info_v5(struct s5p_mfc_ctx *ctx,
-                               unsigned long ofs)
-{
-       rmb();
-       return *(u32 *)(ctx->shm.virt + ofs);
-}
-
-static void s5p_mfc_dec_calc_dpb_size_v5(struct s5p_mfc_ctx *ctx)
-{
-       unsigned int guard_width, guard_height;
-
-       ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN);
-       ctx->buf_height = ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);
-       mfc_debug(2,
-               "SEQ Done: Movie dimensions %dx%d, buffer dimensions: %dx%d\n",
-               ctx->img_width, ctx->img_height, ctx->buf_width,
-               ctx->buf_height);
-
-       if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC) {
-               ctx->luma_size = ALIGN(ctx->buf_width * ctx->buf_height,
-                               S5P_FIMV_DEC_BUF_ALIGN);
-               ctx->chroma_size = ALIGN(ctx->buf_width *
-                               ALIGN((ctx->img_height >> 1),
-                                       S5P_FIMV_NV12MT_VALIGN),
-                               S5P_FIMV_DEC_BUF_ALIGN);
-               ctx->mv_size = ALIGN(ctx->buf_width *
-                               ALIGN((ctx->buf_height >> 2),
-                                       S5P_FIMV_NV12MT_VALIGN),
-                               S5P_FIMV_DEC_BUF_ALIGN);
-       } else {
-               guard_width =
-                       ALIGN(ctx->img_width + 24, S5P_FIMV_NV12MT_HALIGN);
-               guard_height =
-                       ALIGN(ctx->img_height + 16, S5P_FIMV_NV12MT_VALIGN);
-               ctx->luma_size = ALIGN(guard_width * guard_height,
-                               S5P_FIMV_DEC_BUF_ALIGN);
-
-               guard_width =
-                       ALIGN(ctx->img_width + 16, S5P_FIMV_NV12MT_HALIGN);
-               guard_height =
-                       ALIGN((ctx->img_height >> 1) + 4,
-                                       S5P_FIMV_NV12MT_VALIGN);
-               ctx->chroma_size = ALIGN(guard_width * guard_height,
-                               S5P_FIMV_DEC_BUF_ALIGN);
-
-               ctx->mv_size = 0;
-       }
-}
-
-static void s5p_mfc_enc_calc_src_size_v5(struct s5p_mfc_ctx *ctx)
-{
-       if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M) {
-               ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN);
-
-               ctx->luma_size = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN)
-                       * ALIGN(ctx->img_height, S5P_FIMV_NV12M_LVALIGN);
-               ctx->chroma_size = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN)
-                       * ALIGN((ctx->img_height >> 1), S5P_FIMV_NV12M_CVALIGN);
-
-               ctx->luma_size = ALIGN(ctx->luma_size, S5P_FIMV_NV12M_SALIGN);
-               ctx->chroma_size =
-                       ALIGN(ctx->chroma_size, S5P_FIMV_NV12M_SALIGN);
-       } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT) {
-               ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN);
-
-               ctx->luma_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
-                       * ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);
-               ctx->chroma_size =
-                       ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
-                       * ALIGN((ctx->img_height >> 1), S5P_FIMV_NV12MT_VALIGN);
-
-               ctx->luma_size = ALIGN(ctx->luma_size, S5P_FIMV_NV12MT_SALIGN);
-               ctx->chroma_size =
-                       ALIGN(ctx->chroma_size, S5P_FIMV_NV12MT_SALIGN);
-       }
-}
-
-/* Set registers for decoding temporary buffers */
-static void s5p_mfc_set_dec_desc_buffer(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_buf_size_v5 *buf_size = dev->variant->buf_size->priv;
-
-       mfc_write(dev, OFFSETA(ctx->dsc.dma), S5P_FIMV_SI_CH0_DESC_ADR);
-       mfc_write(dev, buf_size->dsc, S5P_FIMV_SI_CH0_DESC_SIZE);
-}
-
-/* Set registers for shared buffer */
-static void s5p_mfc_set_shared_buffer(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       mfc_write(dev, ctx->shm.ofs, S5P_FIMV_SI_CH0_HOST_WR_ADR);
-}
-
-/* Set registers for decoding stream buffer */
-static int s5p_mfc_set_dec_stream_buffer_v5(struct s5p_mfc_ctx *ctx,
-               int buf_addr, unsigned int start_num_byte,
-               unsigned int buf_size)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       mfc_write(dev, OFFSETA(buf_addr), S5P_FIMV_SI_CH0_SB_ST_ADR);
-       mfc_write(dev, ctx->dec_src_buf_size, S5P_FIMV_SI_CH0_CPB_SIZE);
-       mfc_write(dev, buf_size, S5P_FIMV_SI_CH0_SB_FRM_SIZE);
-       s5p_mfc_write_info_v5(ctx, start_num_byte, START_BYTE_NUM);
-       return 0;
-}
-
-/* Set decoding frame buffer */
-static int s5p_mfc_set_dec_frame_buffer_v5(struct s5p_mfc_ctx *ctx)
-{
-       unsigned int frame_size_lu, i;
-       unsigned int frame_size_ch, frame_size_mv;
-       struct s5p_mfc_dev *dev = ctx->dev;
-       unsigned int dpb;
-       size_t buf_addr1, buf_addr2;
-       int buf_size1, buf_size2;
-
-       buf_addr1 = ctx->bank1.dma;
-       buf_size1 = ctx->bank1.size;
-       buf_addr2 = ctx->bank2.dma;
-       buf_size2 = ctx->bank2.size;
-       dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) &
-                                               ~S5P_FIMV_DPB_COUNT_MASK;
-       mfc_write(dev, ctx->total_dpb_count | dpb,
-                                               S5P_FIMV_SI_CH0_DPB_CONF_CTRL);
-       s5p_mfc_set_shared_buffer(ctx);
-       switch (ctx->codec_mode) {
-       case S5P_MFC_CODEC_H264_DEC:
-               mfc_write(dev, OFFSETA(buf_addr1),
-                                               S5P_FIMV_H264_VERT_NB_MV_ADR);
-               buf_addr1 += S5P_FIMV_DEC_VERT_NB_MV_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_VERT_NB_MV_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H264_NB_IP_ADR);
-               buf_addr1 += S5P_FIMV_DEC_NB_IP_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_NB_IP_SIZE;
-               break;
-       case S5P_MFC_CODEC_MPEG4_DEC:
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_NB_DCAC_ADR);
-               buf_addr1 += S5P_FIMV_DEC_NB_DCAC_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_NB_DCAC_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_UP_NB_MV_ADR);
-               buf_addr1 += S5P_FIMV_DEC_UPNB_MV_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_UPNB_MV_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_SA_MV_ADR);
-               buf_addr1 += S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_SP_ADR);
-               buf_addr1 += S5P_FIMV_DEC_STX_PARSER_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_STX_PARSER_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_OT_LINE_ADR);
-               buf_addr1 += S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
-               break;
-       case S5P_MFC_CODEC_H263_DEC:
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_OT_LINE_ADR);
-               buf_addr1 += S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_UP_NB_MV_ADR);
-               buf_addr1 += S5P_FIMV_DEC_UPNB_MV_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_UPNB_MV_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_SA_MV_ADR);
-               buf_addr1 += S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_NB_DCAC_ADR);
-               buf_addr1 += S5P_FIMV_DEC_NB_DCAC_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_NB_DCAC_SIZE;
-               break;
-       case S5P_MFC_CODEC_VC1_DEC:
-       case S5P_MFC_CODEC_VC1RCV_DEC:
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_NB_DCAC_ADR);
-               buf_addr1 += S5P_FIMV_DEC_NB_DCAC_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_NB_DCAC_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_OT_LINE_ADR);
-               buf_addr1 += S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_UP_NB_MV_ADR);
-               buf_addr1 += S5P_FIMV_DEC_UPNB_MV_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_UPNB_MV_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_SA_MV_ADR);
-               buf_addr1 += S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_BITPLANE3_ADR);
-               buf_addr1 += S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_BITPLANE2_ADR);
-               buf_addr1 += S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_BITPLANE1_ADR);
-               buf_addr1 += S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
-               buf_size1 -= S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
-               break;
-       case S5P_MFC_CODEC_MPEG2_DEC:
-               break;
-       default:
-               mfc_err("Unknown codec for decoding (%x)\n",
-                       ctx->codec_mode);
-               return -EINVAL;
-       }
-       frame_size_lu = ctx->luma_size;
-       frame_size_ch = ctx->chroma_size;
-       frame_size_mv = ctx->mv_size;
-       mfc_debug(2, "Frm size: %d ch: %d mv: %d\n", frame_size_lu, frame_size_ch,
-                                                               frame_size_mv);
-       for (i = 0; i < ctx->total_dpb_count; i++) {
-               /* Bank2 */
-               mfc_debug(2, "Luma %d: %zx\n", i,
-                                       ctx->dst_bufs[i].cookie.raw.luma);
-               mfc_write(dev, OFFSETB(ctx->dst_bufs[i].cookie.raw.luma),
-                                               S5P_FIMV_DEC_LUMA_ADR + i * 4);
-               mfc_debug(2, "\tChroma %d: %zx\n", i,
-                                       ctx->dst_bufs[i].cookie.raw.chroma);
-               mfc_write(dev, OFFSETA(ctx->dst_bufs[i].cookie.raw.chroma),
-                                              S5P_FIMV_DEC_CHROMA_ADR + i * 4);
-               if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC) {
-                       mfc_debug(2, "\tBuf2: %zx, size: %d\n",
-                                                       buf_addr2, buf_size2);
-                       mfc_write(dev, OFFSETB(buf_addr2),
-                                               S5P_FIMV_H264_MV_ADR + i * 4);
-                       buf_addr2 += frame_size_mv;
-                       buf_size2 -= frame_size_mv;
-               }
-       }
-       mfc_debug(2, "Buf1: %zu, buf_size1: %d\n", buf_addr1, buf_size1);
-       mfc_debug(2, "Buf 1/2 size after: %d/%d (frames %d)\n",
-                       buf_size1,  buf_size2, ctx->total_dpb_count);
-       if (buf_size1 < 0 || buf_size2 < 0) {
-               mfc_debug(2, "Not enough memory has been allocated\n");
-               return -ENOMEM;
-       }
-       s5p_mfc_write_info_v5(ctx, frame_size_lu, ALLOC_LUMA_DPB_SIZE);
-       s5p_mfc_write_info_v5(ctx, frame_size_ch, ALLOC_CHROMA_DPB_SIZE);
-       if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC)
-               s5p_mfc_write_info_v5(ctx, frame_size_mv, ALLOC_MV_SIZE);
-       mfc_write(dev, ((S5P_FIMV_CH_INIT_BUFS & S5P_FIMV_CH_MASK)
-                                       << S5P_FIMV_CH_SHIFT) | (ctx->inst_no),
-                                               S5P_FIMV_SI_CH0_INST_ID);
-       return 0;
-}
-
-/* Set registers for encoding stream buffer */
-static int s5p_mfc_set_enc_stream_buffer_v5(struct s5p_mfc_ctx *ctx,
-               unsigned long addr, unsigned int size)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       mfc_write(dev, OFFSETA(addr), S5P_FIMV_ENC_SI_CH0_SB_ADR);
-       mfc_write(dev, size, S5P_FIMV_ENC_SI_CH0_SB_SIZE);
-       return 0;
-}
-
-static void s5p_mfc_set_enc_frame_buffer_v5(struct s5p_mfc_ctx *ctx,
-               unsigned long y_addr, unsigned long c_addr)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       mfc_write(dev, OFFSETB(y_addr), S5P_FIMV_ENC_SI_CH0_CUR_Y_ADR);
-       mfc_write(dev, OFFSETB(c_addr), S5P_FIMV_ENC_SI_CH0_CUR_C_ADR);
-}
-
-static void s5p_mfc_get_enc_frame_buffer_v5(struct s5p_mfc_ctx *ctx,
-               unsigned long *y_addr, unsigned long *c_addr)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       *y_addr = dev->dma_base[BANK_R_CTX] +
-                 (mfc_read(dev, S5P_FIMV_ENCODED_Y_ADDR) << MFC_OFFSET_SHIFT);
-       *c_addr = dev->dma_base[BANK_R_CTX] +
-                 (mfc_read(dev, S5P_FIMV_ENCODED_C_ADDR) << MFC_OFFSET_SHIFT);
-}
-
-/* Set encoding ref & codec buffer */
-static int s5p_mfc_set_enc_ref_buffer_v5(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       size_t buf_addr1, buf_addr2;
-       size_t buf_size1, buf_size2;
-       unsigned int enc_ref_y_size, enc_ref_c_size;
-       unsigned int guard_width, guard_height;
-       int i;
-
-       buf_addr1 = ctx->bank1.dma;
-       buf_size1 = ctx->bank1.size;
-       buf_addr2 = ctx->bank2.dma;
-       buf_size2 = ctx->bank2.size;
-       enc_ref_y_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
-               * ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);
-       enc_ref_y_size = ALIGN(enc_ref_y_size, S5P_FIMV_NV12MT_SALIGN);
-       if (ctx->codec_mode == S5P_MFC_CODEC_H264_ENC) {
-               enc_ref_c_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
-                       * ALIGN((ctx->img_height >> 1), S5P_FIMV_NV12MT_VALIGN);
-               enc_ref_c_size = ALIGN(enc_ref_c_size, S5P_FIMV_NV12MT_SALIGN);
-       } else {
-               guard_width = ALIGN(ctx->img_width + 16,
-                                               S5P_FIMV_NV12MT_HALIGN);
-               guard_height = ALIGN((ctx->img_height >> 1) + 4,
-                                               S5P_FIMV_NV12MT_VALIGN);
-               enc_ref_c_size = ALIGN(guard_width * guard_height,
-                                      S5P_FIMV_NV12MT_SALIGN);
-       }
-       mfc_debug(2, "buf_size1: %zu, buf_size2: %zu\n", buf_size1, buf_size2);
-       switch (ctx->codec_mode) {
-       case S5P_MFC_CODEC_H264_ENC:
-               for (i = 0; i < 2; i++) {
-                       mfc_write(dev, OFFSETA(buf_addr1),
-                               S5P_FIMV_ENC_REF0_LUMA_ADR + (4 * i));
-                       buf_addr1 += enc_ref_y_size;
-                       buf_size1 -= enc_ref_y_size;
-
-                       mfc_write(dev, OFFSETB(buf_addr2),
-                               S5P_FIMV_ENC_REF2_LUMA_ADR + (4 * i));
-                       buf_addr2 += enc_ref_y_size;
-                       buf_size2 -= enc_ref_y_size;
-               }
-               for (i = 0; i < 4; i++) {
-                       mfc_write(dev, OFFSETB(buf_addr2),
-                               S5P_FIMV_ENC_REF0_CHROMA_ADR + (4 * i));
-                       buf_addr2 += enc_ref_c_size;
-                       buf_size2 -= enc_ref_c_size;
-               }
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H264_UP_MV_ADR);
-               buf_addr1 += S5P_FIMV_ENC_UPMV_SIZE;
-               buf_size1 -= S5P_FIMV_ENC_UPMV_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1),
-                                       S5P_FIMV_H264_COZERO_FLAG_ADR);
-               buf_addr1 += S5P_FIMV_ENC_COLFLG_SIZE;
-               buf_size1 -= S5P_FIMV_ENC_COLFLG_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1),
-                                       S5P_FIMV_H264_UP_INTRA_MD_ADR);
-               buf_addr1 += S5P_FIMV_ENC_INTRAMD_SIZE;
-               buf_size1 -= S5P_FIMV_ENC_INTRAMD_SIZE;
-               mfc_write(dev, OFFSETB(buf_addr2),
-                                       S5P_FIMV_H264_UP_INTRA_PRED_ADR);
-               buf_addr2 += S5P_FIMV_ENC_INTRAPRED_SIZE;
-               buf_size2 -= S5P_FIMV_ENC_INTRAPRED_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1),
-                                       S5P_FIMV_H264_NBOR_INFO_ADR);
-               buf_addr1 += S5P_FIMV_ENC_NBORINFO_SIZE;
-               buf_size1 -= S5P_FIMV_ENC_NBORINFO_SIZE;
-               mfc_debug(2, "buf_size1: %zu, buf_size2: %zu\n",
-                       buf_size1, buf_size2);
-               break;
-       case S5P_MFC_CODEC_MPEG4_ENC:
-               for (i = 0; i < 2; i++) {
-                       mfc_write(dev, OFFSETA(buf_addr1),
-                               S5P_FIMV_ENC_REF0_LUMA_ADR + (4 * i));
-                       buf_addr1 += enc_ref_y_size;
-                       buf_size1 -= enc_ref_y_size;
-                       mfc_write(dev, OFFSETB(buf_addr2),
-                               S5P_FIMV_ENC_REF2_LUMA_ADR + (4 * i));
-                       buf_addr2 += enc_ref_y_size;
-                       buf_size2 -= enc_ref_y_size;
-               }
-               for (i = 0; i < 4; i++) {
-                       mfc_write(dev, OFFSETB(buf_addr2),
-                               S5P_FIMV_ENC_REF0_CHROMA_ADR + (4 * i));
-                       buf_addr2 += enc_ref_c_size;
-                       buf_size2 -= enc_ref_c_size;
-               }
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_UP_MV_ADR);
-               buf_addr1 += S5P_FIMV_ENC_UPMV_SIZE;
-               buf_size1 -= S5P_FIMV_ENC_UPMV_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1),
-                                               S5P_FIMV_MPEG4_COZERO_FLAG_ADR);
-               buf_addr1 += S5P_FIMV_ENC_COLFLG_SIZE;
-               buf_size1 -= S5P_FIMV_ENC_COLFLG_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1),
-                                               S5P_FIMV_MPEG4_ACDC_COEF_ADR);
-               buf_addr1 += S5P_FIMV_ENC_ACDCCOEF_SIZE;
-               buf_size1 -= S5P_FIMV_ENC_ACDCCOEF_SIZE;
-               mfc_debug(2, "buf_size1: %zu, buf_size2: %zu\n",
-                       buf_size1, buf_size2);
-               break;
-       case S5P_MFC_CODEC_H263_ENC:
-               for (i = 0; i < 2; i++) {
-                       mfc_write(dev, OFFSETA(buf_addr1),
-                               S5P_FIMV_ENC_REF0_LUMA_ADR + (4 * i));
-                       buf_addr1 += enc_ref_y_size;
-                       buf_size1 -= enc_ref_y_size;
-                       mfc_write(dev, OFFSETB(buf_addr2),
-                               S5P_FIMV_ENC_REF2_LUMA_ADR + (4 * i));
-                       buf_addr2 += enc_ref_y_size;
-                       buf_size2 -= enc_ref_y_size;
-               }
-               for (i = 0; i < 4; i++) {
-                       mfc_write(dev, OFFSETB(buf_addr2),
-                               S5P_FIMV_ENC_REF0_CHROMA_ADR + (4 * i));
-                       buf_addr2 += enc_ref_c_size;
-                       buf_size2 -= enc_ref_c_size;
-               }
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_UP_MV_ADR);
-               buf_addr1 += S5P_FIMV_ENC_UPMV_SIZE;
-               buf_size1 -= S5P_FIMV_ENC_UPMV_SIZE;
-               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_ACDC_COEF_ADR);
-               buf_addr1 += S5P_FIMV_ENC_ACDCCOEF_SIZE;
-               buf_size1 -= S5P_FIMV_ENC_ACDCCOEF_SIZE;
-               mfc_debug(2, "buf_size1: %zu, buf_size2: %zu\n",
-                       buf_size1, buf_size2);
-               break;
-       default:
-               mfc_err("Unknown codec set for encoding: %d\n",
-                       ctx->codec_mode);
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static int s5p_mfc_set_enc_params(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_enc_params *p = &ctx->enc_params;
-       unsigned int reg;
-       unsigned int shm;
-
-       /* width */
-       mfc_write(dev, ctx->img_width, S5P_FIMV_ENC_HSIZE_PX);
-       /* height */
-       mfc_write(dev, ctx->img_height, S5P_FIMV_ENC_VSIZE_PX);
-       /* pictype : enable, IDR period */
-       reg = mfc_read(dev, S5P_FIMV_ENC_PIC_TYPE_CTRL);
-       reg |= (1 << 18);
-       reg &= ~(0xFFFF);
-       reg |= p->gop_size;
-       mfc_write(dev, reg, S5P_FIMV_ENC_PIC_TYPE_CTRL);
-       mfc_write(dev, 0, S5P_FIMV_ENC_B_RECON_WRITE_ON);
-       /* multi-slice control */
-       /* multi-slice MB number or bit size */
-       mfc_write(dev, p->slice_mode, S5P_FIMV_ENC_MSLICE_CTRL);
-       if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB) {
-               mfc_write(dev, p->slice_mb, S5P_FIMV_ENC_MSLICE_MB);
-       } else if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES) {
-               mfc_write(dev, p->slice_bit, S5P_FIMV_ENC_MSLICE_BIT);
-       } else {
-               mfc_write(dev, 0, S5P_FIMV_ENC_MSLICE_MB);
-               mfc_write(dev, 0, S5P_FIMV_ENC_MSLICE_BIT);
-       }
-       /* cyclic intra refresh */
-       mfc_write(dev, p->intra_refresh_mb, S5P_FIMV_ENC_CIR_CTRL);
-       /* memory structure cur. frame */
-       if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M)
-               mfc_write(dev, 0, S5P_FIMV_ENC_MAP_FOR_CUR);
-       else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT)
-               mfc_write(dev, 3, S5P_FIMV_ENC_MAP_FOR_CUR);
-       /* padding control & value */
-       reg = mfc_read(dev, S5P_FIMV_ENC_PADDING_CTRL);
-       if (p->pad) {
-               /** enable */
-               reg |= (1UL << 31);
-               /** cr value */
-               reg &= ~(0xFF << 16);
-               reg |= (p->pad_cr << 16);
-               /** cb value */
-               reg &= ~(0xFF << 8);
-               reg |= (p->pad_cb << 8);
-               /** y value */
-               reg &= ~(0xFF);
-               reg |= (p->pad_luma);
-       } else {
-               /** disable & all value clear */
-               reg = 0;
-       }
-       mfc_write(dev, reg, S5P_FIMV_ENC_PADDING_CTRL);
-       /* rate control config. */
-       reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
-       /** frame-level rate control */
-       reg &= ~(0x1 << 9);
-       reg |= (p->rc_frame << 9);
-       mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
-       /* bit rate */
-       if (p->rc_frame)
-               mfc_write(dev, p->rc_bitrate,
-                       S5P_FIMV_ENC_RC_BIT_RATE);
-       else
-               mfc_write(dev, 0, S5P_FIMV_ENC_RC_BIT_RATE);
-       /* reaction coefficient */
-       if (p->rc_frame)
-               mfc_write(dev, p->rc_reaction_coeff, S5P_FIMV_ENC_RC_RPARA);
-       shm = s5p_mfc_read_info_v5(ctx, EXT_ENC_CONTROL);
-       /* seq header ctrl */
-       shm &= ~(0x1 << 3);
-       shm |= (p->seq_hdr_mode << 3);
-       /* frame skip mode */
-       shm &= ~(0x3 << 1);
-       shm |= (p->frame_skip_mode << 1);
-       s5p_mfc_write_info_v5(ctx, shm, EXT_ENC_CONTROL);
-       /* fixed target bit */
-       s5p_mfc_write_info_v5(ctx, p->fixed_target_bit, RC_CONTROL_CONFIG);
-       return 0;
-}
-
-static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_enc_params *p = &ctx->enc_params;
-       struct s5p_mfc_h264_enc_params *p_264 = &p->codec.h264;
-       unsigned int reg;
-       unsigned int shm;
-
-       s5p_mfc_set_enc_params(ctx);
-       /* pictype : number of B */
-       reg = mfc_read(dev, S5P_FIMV_ENC_PIC_TYPE_CTRL);
-       /* num_b_frame - 0 ~ 2 */
-       reg &= ~(0x3 << 16);
-       reg |= (p->num_b_frame << 16);
-       mfc_write(dev, reg, S5P_FIMV_ENC_PIC_TYPE_CTRL);
-       /* profile & level */
-       reg = mfc_read(dev, S5P_FIMV_ENC_PROFILE);
-       /* level */
-       reg &= ~(0xFF << 8);
-       reg |= (p_264->level << 8);
-       /* profile - 0 ~ 2 */
-       reg &= ~(0x3F);
-       reg |= p_264->profile;
-       mfc_write(dev, reg, S5P_FIMV_ENC_PROFILE);
-       /* interlace  */
-       mfc_write(dev, p_264->interlace, S5P_FIMV_ENC_PIC_STRUCT);
-       /* height */
-       if (p_264->interlace)
-               mfc_write(dev, ctx->img_height >> 1, S5P_FIMV_ENC_VSIZE_PX);
-       /* loopfilter ctrl */
-       mfc_write(dev, p_264->loop_filter_mode, S5P_FIMV_ENC_LF_CTRL);
-       /* loopfilter alpha offset */
-       if (p_264->loop_filter_alpha < 0) {
-               reg = 0x10;
-               reg |= (0xFF - p_264->loop_filter_alpha) + 1;
-       } else {
-               reg = 0x00;
-               reg |= (p_264->loop_filter_alpha & 0xF);
-       }
-       mfc_write(dev, reg, S5P_FIMV_ENC_ALPHA_OFF);
-       /* loopfilter beta offset */
-       if (p_264->loop_filter_beta < 0) {
-               reg = 0x10;
-               reg |= (0xFF - p_264->loop_filter_beta) + 1;
-       } else {
-               reg = 0x00;
-               reg |= (p_264->loop_filter_beta & 0xF);
-       }
-       mfc_write(dev, reg, S5P_FIMV_ENC_BETA_OFF);
-       /* entropy coding mode */
-       if (p_264->entropy_mode == V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC)
-               mfc_write(dev, 1, S5P_FIMV_ENC_H264_ENTROPY_MODE);
-       else
-               mfc_write(dev, 0, S5P_FIMV_ENC_H264_ENTROPY_MODE);
-       /* number of ref. picture */
-       reg = mfc_read(dev, S5P_FIMV_ENC_H264_NUM_OF_REF);
-       /* num of ref. pictures of P */
-       reg &= ~(0x3 << 5);
-       reg |= (p_264->num_ref_pic_4p << 5);
-       /* max number of ref. pictures */
-       reg &= ~(0x1F);
-       reg |= p_264->max_ref_pic;
-       mfc_write(dev, reg, S5P_FIMV_ENC_H264_NUM_OF_REF);
-       /* 8x8 transform enable */
-       mfc_write(dev, p_264->_8x8_transform, S5P_FIMV_ENC_H264_TRANS_FLAG);
-       /* rate control config. */
-       reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
-       /* macroblock level rate control */
-       reg &= ~(0x1 << 8);
-       reg |= (p->rc_mb << 8);
-       /* frame QP */
-       reg &= ~(0x3F);
-       reg |= p_264->rc_frame_qp;
-       mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
-       /* frame rate */
-       if (p->rc_frame && p->rc_framerate_denom)
-               mfc_write(dev, p->rc_framerate_num * 1000
-                       / p->rc_framerate_denom, S5P_FIMV_ENC_RC_FRAME_RATE);
-       else
-               mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE);
-       /* max & min value of QP */
-       reg = mfc_read(dev, S5P_FIMV_ENC_RC_QBOUND);
-       /* max QP */
-       reg &= ~(0x3F << 8);
-       reg |= (p_264->rc_max_qp << 8);
-       /* min QP */
-       reg &= ~(0x3F);
-       reg |= p_264->rc_min_qp;
-       mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);
-       /* macroblock adaptive scaling features */
-       if (p->rc_mb) {
-               reg = mfc_read(dev, S5P_FIMV_ENC_RC_MB_CTRL);
-               /* dark region */
-               reg &= ~(0x1 << 3);
-               reg |= (p_264->rc_mb_dark << 3);
-               /* smooth region */
-               reg &= ~(0x1 << 2);
-               reg |= (p_264->rc_mb_smooth << 2);
-               /* static region */
-               reg &= ~(0x1 << 1);
-               reg |= (p_264->rc_mb_static << 1);
-               /* high activity region */
-               reg &= ~(0x1);
-               reg |= p_264->rc_mb_activity;
-               mfc_write(dev, reg, S5P_FIMV_ENC_RC_MB_CTRL);
-       }
-       if (!p->rc_frame && !p->rc_mb) {
-               shm = s5p_mfc_read_info_v5(ctx, P_B_FRAME_QP);
-               shm &= ~(0xFFF);
-               shm |= ((p_264->rc_b_frame_qp & 0x3F) << 6);
-               shm |= (p_264->rc_p_frame_qp & 0x3F);
-               s5p_mfc_write_info_v5(ctx, shm, P_B_FRAME_QP);
-       }
-       /* extended encoder ctrl */
-       shm = s5p_mfc_read_info_v5(ctx, EXT_ENC_CONTROL);
-       /* AR VUI control */
-       shm &= ~(0x1 << 15);
-       shm |= (p_264->vui_sar << 1);
-       s5p_mfc_write_info_v5(ctx, shm, EXT_ENC_CONTROL);
-       if (p_264->vui_sar) {
-               /* aspect ration IDC */
-               shm = s5p_mfc_read_info_v5(ctx, SAMPLE_ASPECT_RATIO_IDC);
-               shm &= ~(0xFF);
-               shm |= p_264->vui_sar_idc;
-               s5p_mfc_write_info_v5(ctx, shm, SAMPLE_ASPECT_RATIO_IDC);
-               if (p_264->vui_sar_idc == 0xFF) {
-                       /* sample  AR info */
-                       shm = s5p_mfc_read_info_v5(ctx, EXTENDED_SAR);
-                       shm &= ~(0xFFFFFFFF);
-                       shm |= p_264->vui_ext_sar_width << 16;
-                       shm |= p_264->vui_ext_sar_height;
-                       s5p_mfc_write_info_v5(ctx, shm, EXTENDED_SAR);
-               }
-       }
-       /* intra picture period for H.264 */
-       shm = s5p_mfc_read_info_v5(ctx, H264_I_PERIOD);
-       /* control */
-       shm &= ~(0x1 << 16);
-       shm |= (p_264->open_gop << 16);
-       /* value */
-       if (p_264->open_gop) {
-               shm &= ~(0xFFFF);
-               shm |= p_264->open_gop_size;
-       }
-       s5p_mfc_write_info_v5(ctx, shm, H264_I_PERIOD);
-       /* extended encoder ctrl */
-       shm = s5p_mfc_read_info_v5(ctx, EXT_ENC_CONTROL);
-       /* vbv buffer size */
-       if (p->frame_skip_mode ==
-                       V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
-               shm &= ~(0xFFFF << 16);
-               shm |= (p_264->cpb_size << 16);
-       }
-       s5p_mfc_write_info_v5(ctx, shm, EXT_ENC_CONTROL);
-       return 0;
-}
-
-static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_enc_params *p = &ctx->enc_params;
-       struct s5p_mfc_mpeg4_enc_params *p_mpeg4 = &p->codec.mpeg4;
-       unsigned int reg;
-       unsigned int shm;
-       unsigned int framerate;
-
-       s5p_mfc_set_enc_params(ctx);
-       /* pictype : number of B */
-       reg = mfc_read(dev, S5P_FIMV_ENC_PIC_TYPE_CTRL);
-       /* num_b_frame - 0 ~ 2 */
-       reg &= ~(0x3 << 16);
-       reg |= (p->num_b_frame << 16);
-       mfc_write(dev, reg, S5P_FIMV_ENC_PIC_TYPE_CTRL);
-       /* profile & level */
-       reg = mfc_read(dev, S5P_FIMV_ENC_PROFILE);
-       /* level */
-       reg &= ~(0xFF << 8);
-       reg |= (p_mpeg4->level << 8);
-       /* profile - 0 ~ 2 */
-       reg &= ~(0x3F);
-       reg |= p_mpeg4->profile;
-       mfc_write(dev, reg, S5P_FIMV_ENC_PROFILE);
-       /* quarter_pixel */
-       mfc_write(dev, p_mpeg4->quarter_pixel, S5P_FIMV_ENC_MPEG4_QUART_PXL);
-       /* qp */
-       if (!p->rc_frame) {
-               shm = s5p_mfc_read_info_v5(ctx, P_B_FRAME_QP);
-               shm &= ~(0xFFF);
-               shm |= ((p_mpeg4->rc_b_frame_qp & 0x3F) << 6);
-               shm |= (p_mpeg4->rc_p_frame_qp & 0x3F);
-               s5p_mfc_write_info_v5(ctx, shm, P_B_FRAME_QP);
-       }
-       /* frame rate */
-       if (p->rc_frame) {
-               if (p->rc_framerate_denom > 0) {
-                       framerate = p->rc_framerate_num * 1000 /
-                                               p->rc_framerate_denom;
-                       mfc_write(dev, framerate,
-                               S5P_FIMV_ENC_RC_FRAME_RATE);
-                       shm = s5p_mfc_read_info_v5(ctx, RC_VOP_TIMING);
-                       shm &= ~(0xFFFFFFFF);
-                       shm |= (1UL << 31);
-                       shm |= ((p->rc_framerate_num & 0x7FFF) << 16);
-                       shm |= (p->rc_framerate_denom & 0xFFFF);
-                       s5p_mfc_write_info_v5(ctx, shm, RC_VOP_TIMING);
-               }
-       } else {
-               mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE);
-       }
-       /* rate control config. */
-       reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
-       /* frame QP */
-       reg &= ~(0x3F);
-       reg |= p_mpeg4->rc_frame_qp;
-       mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
-       /* max & min value of QP */
-       reg = mfc_read(dev, S5P_FIMV_ENC_RC_QBOUND);
-       /* max QP */
-       reg &= ~(0x3F << 8);
-       reg |= (p_mpeg4->rc_max_qp << 8);
-       /* min QP */
-       reg &= ~(0x3F);
-       reg |= p_mpeg4->rc_min_qp;
-       mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);
-       /* extended encoder ctrl */
-       shm = s5p_mfc_read_info_v5(ctx, EXT_ENC_CONTROL);
-       /* vbv buffer size */
-       if (p->frame_skip_mode ==
-                       V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
-               shm &= ~(0xFFFF << 16);
-               shm |= (p->vbv_size << 16);
-       }
-       s5p_mfc_write_info_v5(ctx, shm, EXT_ENC_CONTROL);
-       return 0;
-}
-
-static int s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_enc_params *p = &ctx->enc_params;
-       struct s5p_mfc_mpeg4_enc_params *p_h263 = &p->codec.mpeg4;
-       unsigned int reg;
-       unsigned int shm;
-
-       s5p_mfc_set_enc_params(ctx);
-       /* qp */
-       if (!p->rc_frame) {
-               shm = s5p_mfc_read_info_v5(ctx, P_B_FRAME_QP);
-               shm &= ~(0xFFF);
-               shm |= (p_h263->rc_p_frame_qp & 0x3F);
-               s5p_mfc_write_info_v5(ctx, shm, P_B_FRAME_QP);
-       }
-       /* frame rate */
-       if (p->rc_frame && p->rc_framerate_denom)
-               mfc_write(dev, p->rc_framerate_num * 1000
-                       / p->rc_framerate_denom, S5P_FIMV_ENC_RC_FRAME_RATE);
-       else
-               mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE);
-       /* rate control config. */
-       reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
-       /* frame QP */
-       reg &= ~(0x3F);
-       reg |= p_h263->rc_frame_qp;
-       mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
-       /* max & min value of QP */
-       reg = mfc_read(dev, S5P_FIMV_ENC_RC_QBOUND);
-       /* max QP */
-       reg &= ~(0x3F << 8);
-       reg |= (p_h263->rc_max_qp << 8);
-       /* min QP */
-       reg &= ~(0x3F);
-       reg |= p_h263->rc_min_qp;
-       mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);
-       /* extended encoder ctrl */
-       shm = s5p_mfc_read_info_v5(ctx, EXT_ENC_CONTROL);
-       /* vbv buffer size */
-       if (p->frame_skip_mode ==
-                       V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
-               shm &= ~(0xFFFF << 16);
-               shm |= (p->vbv_size << 16);
-       }
-       s5p_mfc_write_info_v5(ctx, shm, EXT_ENC_CONTROL);
-       return 0;
-}
-
-/* Initialize decoding */
-static int s5p_mfc_init_decode_v5(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       s5p_mfc_set_shared_buffer(ctx);
-       /* Setup loop filter, for decoding this is only valid for MPEG4 */
-       if (ctx->codec_mode == S5P_MFC_CODEC_MPEG4_DEC)
-               mfc_write(dev, ctx->loop_filter_mpeg4, S5P_FIMV_ENC_LF_CTRL);
-       else
-               mfc_write(dev, 0, S5P_FIMV_ENC_LF_CTRL);
-       mfc_write(dev, ((ctx->slice_interface & S5P_FIMV_SLICE_INT_MASK) <<
-               S5P_FIMV_SLICE_INT_SHIFT) | (ctx->display_delay_enable <<
-               S5P_FIMV_DDELAY_ENA_SHIFT) | ((ctx->display_delay &
-               S5P_FIMV_DDELAY_VAL_MASK) << S5P_FIMV_DDELAY_VAL_SHIFT),
-               S5P_FIMV_SI_CH0_DPB_CONF_CTRL);
-       mfc_write(dev,
-       ((S5P_FIMV_CH_SEQ_HEADER & S5P_FIMV_CH_MASK) << S5P_FIMV_CH_SHIFT)
-                               | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
-       return 0;
-}
-
-static void s5p_mfc_set_flush(struct s5p_mfc_ctx *ctx, int flush)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       unsigned int dpb;
-
-       if (flush)
-               dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) | (
-                       S5P_FIMV_DPB_FLUSH_MASK << S5P_FIMV_DPB_FLUSH_SHIFT);
-       else
-               dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) &
-                       ~(S5P_FIMV_DPB_FLUSH_MASK << S5P_FIMV_DPB_FLUSH_SHIFT);
-       mfc_write(dev, dpb, S5P_FIMV_SI_CH0_DPB_CONF_CTRL);
-}
-
-/* Decode a single frame */
-static int s5p_mfc_decode_one_frame_v5(struct s5p_mfc_ctx *ctx,
-                                       enum s5p_mfc_decode_arg last_frame)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       mfc_write(dev, ctx->dec_dst_flag, S5P_FIMV_SI_CH0_RELEASE_BUF);
-       s5p_mfc_set_shared_buffer(ctx);
-       s5p_mfc_set_flush(ctx, ctx->dpb_flush_flag);
-       /* Issue different commands to instance basing on whether it
-        * is the last frame or not. */
-       switch (last_frame) {
-       case MFC_DEC_FRAME:
-               mfc_write(dev, ((S5P_FIMV_CH_FRAME_START & S5P_FIMV_CH_MASK) <<
-               S5P_FIMV_CH_SHIFT) | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
-               break;
-       case MFC_DEC_LAST_FRAME:
-               mfc_write(dev, ((S5P_FIMV_CH_LAST_FRAME & S5P_FIMV_CH_MASK) <<
-               S5P_FIMV_CH_SHIFT) | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
-               break;
-       case MFC_DEC_RES_CHANGE:
-               mfc_write(dev, ((S5P_FIMV_CH_FRAME_START_REALLOC &
-               S5P_FIMV_CH_MASK) << S5P_FIMV_CH_SHIFT) | (ctx->inst_no),
-               S5P_FIMV_SI_CH0_INST_ID);
-               break;
-       }
-       mfc_debug(2, "Decoding a usual frame\n");
-       return 0;
-}
-
-static int s5p_mfc_init_encode_v5(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       if (ctx->codec_mode == S5P_MFC_CODEC_H264_ENC)
-               s5p_mfc_set_enc_params_h264(ctx);
-       else if (ctx->codec_mode == S5P_MFC_CODEC_MPEG4_ENC)
-               s5p_mfc_set_enc_params_mpeg4(ctx);
-       else if (ctx->codec_mode == S5P_MFC_CODEC_H263_ENC)
-               s5p_mfc_set_enc_params_h263(ctx);
-       else {
-               mfc_err("Unknown codec for encoding (%x)\n",
-                       ctx->codec_mode);
-               return -EINVAL;
-       }
-       s5p_mfc_set_shared_buffer(ctx);
-       mfc_write(dev, ((S5P_FIMV_CH_SEQ_HEADER << 16) & 0x70000) |
-               (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
-       return 0;
-}
-
-/* Encode a single frame */
-static int s5p_mfc_encode_one_frame_v5(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       int cmd;
-       /* memory structure cur. frame */
-       if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M)
-               mfc_write(dev, 0, S5P_FIMV_ENC_MAP_FOR_CUR);
-       else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT)
-               mfc_write(dev, 3, S5P_FIMV_ENC_MAP_FOR_CUR);
-       s5p_mfc_set_shared_buffer(ctx);
-
-       if (ctx->state == MFCINST_FINISHING)
-               cmd = S5P_FIMV_CH_LAST_FRAME;
-       else
-               cmd = S5P_FIMV_CH_FRAME_START;
-       mfc_write(dev, ((cmd & S5P_FIMV_CH_MASK) << S5P_FIMV_CH_SHIFT)
-                               | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
-
-       return 0;
-}
-
-static void s5p_mfc_run_res_change(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       s5p_mfc_set_dec_stream_buffer_v5(ctx, 0, 0, 0);
-       dev->curr_ctx = ctx->num;
-       s5p_mfc_decode_one_frame_v5(ctx, MFC_DEC_RES_CHANGE);
-}
-
-static int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx, int last_frame)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_buf *temp_vb;
-
-       if (ctx->state == MFCINST_FINISHING) {
-               last_frame = MFC_DEC_LAST_FRAME;
-               s5p_mfc_set_dec_stream_buffer_v5(ctx, 0, 0, 0);
-               dev->curr_ctx = ctx->num;
-               s5p_mfc_decode_one_frame_v5(ctx, last_frame);
-               return 0;
-       }
-
-       /* Frames are being decoded */
-       if (list_empty(&ctx->src_queue)) {
-               mfc_debug(2, "No src buffers\n");
-               return -EAGAIN;
-       }
-       /* Get the next source buffer */
-       temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
-       temp_vb->flags |= MFC_BUF_FLAG_USED;
-       s5p_mfc_set_dec_stream_buffer_v5(ctx,
-               vb2_dma_contig_plane_dma_addr(&temp_vb->b->vb2_buf, 0),
-               ctx->consumed_stream, temp_vb->b->vb2_buf.planes[0].bytesused);
-       dev->curr_ctx = ctx->num;
-       if (temp_vb->b->vb2_buf.planes[0].bytesused == 0) {
-               last_frame = MFC_DEC_LAST_FRAME;
-               mfc_debug(2, "Setting ctx->state to FINISHING\n");
-               ctx->state = MFCINST_FINISHING;
-       }
-       s5p_mfc_decode_one_frame_v5(ctx, last_frame);
-       return 0;
-}
-
-static int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_buf *dst_mb;
-       struct s5p_mfc_buf *src_mb;
-       unsigned long src_y_addr, src_c_addr, dst_addr;
-       unsigned int dst_size;
-
-       if (list_empty(&ctx->src_queue) && ctx->state != MFCINST_FINISHING) {
-               mfc_debug(2, "no src buffers\n");
-               return -EAGAIN;
-       }
-       if (list_empty(&ctx->dst_queue)) {
-               mfc_debug(2, "no dst buffers\n");
-               return -EAGAIN;
-       }
-       if (list_empty(&ctx->src_queue)) {
-               /* send null frame */
-               s5p_mfc_set_enc_frame_buffer_v5(ctx, dev->dma_base[BANK_R_CTX],
-                                               dev->dma_base[BANK_R_CTX]);
-               src_mb = NULL;
-       } else {
-               src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf,
-                                                                       list);
-               src_mb->flags |= MFC_BUF_FLAG_USED;
-               if (src_mb->b->vb2_buf.planes[0].bytesused == 0) {
-                       /* send null frame */
-                       s5p_mfc_set_enc_frame_buffer_v5(ctx,
-                                               dev->dma_base[BANK_R_CTX],
-                                               dev->dma_base[BANK_R_CTX]);
-                       ctx->state = MFCINST_FINISHING;
-               } else {
-                       src_y_addr = vb2_dma_contig_plane_dma_addr(
-                                       &src_mb->b->vb2_buf, 0);
-                       src_c_addr = vb2_dma_contig_plane_dma_addr(
-                                       &src_mb->b->vb2_buf, 1);
-                       s5p_mfc_set_enc_frame_buffer_v5(ctx, src_y_addr,
-                                                               src_c_addr);
-                       if (src_mb->flags & MFC_BUF_FLAG_EOS)
-                               ctx->state = MFCINST_FINISHING;
-               }
-       }
-       dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
-       dst_mb->flags |= MFC_BUF_FLAG_USED;
-       dst_addr = vb2_dma_contig_plane_dma_addr(&dst_mb->b->vb2_buf, 0);
-       dst_size = vb2_plane_size(&dst_mb->b->vb2_buf, 0);
-       s5p_mfc_set_enc_stream_buffer_v5(ctx, dst_addr, dst_size);
-       dev->curr_ctx = ctx->num;
-       mfc_debug(2, "encoding buffer with index=%d state=%d\n",
-                 src_mb ? src_mb->b->vb2_buf.index : -1, ctx->state);
-       s5p_mfc_encode_one_frame_v5(ctx);
-       return 0;
-}
-
-static void s5p_mfc_run_init_dec(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_buf *temp_vb;
-
-       /* Initializing decoding - parsing header */
-       mfc_debug(2, "Preparing to init decoding\n");
-       temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
-       s5p_mfc_set_dec_desc_buffer(ctx);
-       mfc_debug(2, "Header size: %d\n",
-                       temp_vb->b->vb2_buf.planes[0].bytesused);
-       s5p_mfc_set_dec_stream_buffer_v5(ctx,
-                       vb2_dma_contig_plane_dma_addr(&temp_vb->b->vb2_buf, 0),
-                       0, temp_vb->b->vb2_buf.planes[0].bytesused);
-       dev->curr_ctx = ctx->num;
-       s5p_mfc_init_decode_v5(ctx);
-}
-
-static void s5p_mfc_run_init_enc(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_buf *dst_mb;
-       unsigned long dst_addr;
-       unsigned int dst_size;
-
-       s5p_mfc_set_enc_ref_buffer_v5(ctx);
-       dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
-       dst_addr = vb2_dma_contig_plane_dma_addr(&dst_mb->b->vb2_buf, 0);
-       dst_size = vb2_plane_size(&dst_mb->b->vb2_buf, 0);
-       s5p_mfc_set_enc_stream_buffer_v5(ctx, dst_addr, dst_size);
-       dev->curr_ctx = ctx->num;
-       s5p_mfc_init_encode_v5(ctx);
-}
-
-static int s5p_mfc_run_init_dec_buffers(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_buf *temp_vb;
-       int ret;
-
-       /*
-        * Header was parsed now starting processing
-        * First set the output frame buffers
-        */
-       if (ctx->capture_state != QUEUE_BUFS_MMAPED) {
-               mfc_err("It seems that not all destination buffers were mmapped\nMFC requires that all destination are mmapped before starting processing\n");
-               return -EAGAIN;
-       }
-       if (list_empty(&ctx->src_queue)) {
-               mfc_err("Header has been deallocated in the middle of initialization\n");
-               return -EIO;
-       }
-       temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
-       mfc_debug(2, "Header size: %d\n",
-                       temp_vb->b->vb2_buf.planes[0].bytesused);
-       s5p_mfc_set_dec_stream_buffer_v5(ctx,
-                       vb2_dma_contig_plane_dma_addr(&temp_vb->b->vb2_buf, 0),
-                       0, temp_vb->b->vb2_buf.planes[0].bytesused);
-       dev->curr_ctx = ctx->num;
-       ret = s5p_mfc_set_dec_frame_buffer_v5(ctx);
-       if (ret) {
-               mfc_err("Failed to alloc frame mem\n");
-               ctx->state = MFCINST_ERROR;
-       }
-       return ret;
-}
-
-/* Try running an operation on hardware */
-static void s5p_mfc_try_run_v5(struct s5p_mfc_dev *dev)
-{
-       struct s5p_mfc_ctx *ctx;
-       int new_ctx;
-       unsigned int ret = 0;
-
-       if (test_bit(0, &dev->enter_suspend)) {
-               mfc_debug(1, "Entering suspend so do not schedule any jobs\n");
-               return;
-       }
-       /* Check whether hardware is not running */
-       if (test_and_set_bit(0, &dev->hw_lock) != 0) {
-               /* This is perfectly ok, the scheduled ctx should wait */
-               mfc_debug(1, "Couldn't lock HW\n");
-               return;
-       }
-       /* Choose the context to run */
-       new_ctx = s5p_mfc_get_new_ctx(dev);
-       if (new_ctx < 0) {
-               /* No contexts to run */
-               if (test_and_clear_bit(0, &dev->hw_lock) == 0) {
-                       mfc_err("Failed to unlock hardware\n");
-                       return;
-               }
-               mfc_debug(1, "No ctx is scheduled to be run\n");
-               return;
-       }
-       ctx = dev->ctx[new_ctx];
-       /* Got context to run in ctx */
-       /*
-        * Last frame has already been sent to MFC.
-        * Now obtaining frames from MFC buffer
-        */
-       s5p_mfc_clock_on();
-       s5p_mfc_clean_ctx_int_flags(ctx);
-
-       if (ctx->type == MFCINST_DECODER) {
-               s5p_mfc_set_dec_desc_buffer(ctx);
-               switch (ctx->state) {
-               case MFCINST_FINISHING:
-                       s5p_mfc_run_dec_frame(ctx, MFC_DEC_LAST_FRAME);
-                       break;
-               case MFCINST_RUNNING:
-                       ret = s5p_mfc_run_dec_frame(ctx, MFC_DEC_FRAME);
-                       break;
-               case MFCINST_INIT:
-                       ret = s5p_mfc_hw_call(dev->mfc_cmds, open_inst_cmd,
-                                       ctx);
-                       break;
-               case MFCINST_RETURN_INST:
-                       ret = s5p_mfc_hw_call(dev->mfc_cmds, close_inst_cmd,
-                                       ctx);
-                       break;
-               case MFCINST_GOT_INST:
-                       s5p_mfc_run_init_dec(ctx);
-                       break;
-               case MFCINST_HEAD_PARSED:
-                       ret = s5p_mfc_run_init_dec_buffers(ctx);
-                       mfc_debug(1, "head parsed\n");
-                       break;
-               case MFCINST_RES_CHANGE_INIT:
-                       s5p_mfc_run_res_change(ctx);
-                       break;
-               case MFCINST_RES_CHANGE_FLUSH:
-                       s5p_mfc_run_dec_frame(ctx, MFC_DEC_FRAME);
-                       break;
-               case MFCINST_RES_CHANGE_END:
-                       mfc_debug(2, "Finished remaining frames after resolution change\n");
-                       ctx->capture_state = QUEUE_FREE;
-                       mfc_debug(2, "Will re-init the codec\n");
-                       s5p_mfc_run_init_dec(ctx);
-                       break;
-               default:
-                       ret = -EAGAIN;
-               }
-       } else if (ctx->type == MFCINST_ENCODER) {
-               switch (ctx->state) {
-               case MFCINST_FINISHING:
-               case MFCINST_RUNNING:
-                       ret = s5p_mfc_run_enc_frame(ctx);
-                       break;
-               case MFCINST_INIT:
-                       ret = s5p_mfc_hw_call(dev->mfc_cmds, open_inst_cmd,
-                                       ctx);
-                       break;
-               case MFCINST_RETURN_INST:
-                       ret = s5p_mfc_hw_call(dev->mfc_cmds, close_inst_cmd,
-                                       ctx);
-                       break;
-               case MFCINST_GOT_INST:
-                       s5p_mfc_run_init_enc(ctx);
-                       break;
-               default:
-                       ret = -EAGAIN;
-               }
-       } else {
-               mfc_err("Invalid context type: %d\n", ctx->type);
-               ret = -EAGAIN;
-       }
-
-       if (ret) {
-               /* Free hardware lock */
-               if (test_and_clear_bit(0, &dev->hw_lock) == 0)
-                       mfc_err("Failed to unlock hardware\n");
-
-               /* This is indeed important, as no operation has been
-                * scheduled, reduce the clock count as no one will
-                * ever do this, because no interrupt related to this try_run
-                * will ever come from hardware. */
-               s5p_mfc_clock_off();
-       }
-}
-
-static void s5p_mfc_clear_int_flags_v5(struct s5p_mfc_dev *dev)
-{
-       mfc_write(dev, 0, S5P_FIMV_RISC_HOST_INT);
-       mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
-       mfc_write(dev, 0xffff, S5P_FIMV_SI_RTN_CHID);
-}
-
-static int s5p_mfc_get_dspl_y_adr_v5(struct s5p_mfc_dev *dev)
-{
-       return mfc_read(dev, S5P_FIMV_SI_DISPLAY_Y_ADR) << MFC_OFFSET_SHIFT;
-}
-
-static int s5p_mfc_get_dec_y_adr_v5(struct s5p_mfc_dev *dev)
-{
-       return mfc_read(dev, S5P_FIMV_SI_DECODE_Y_ADR) << MFC_OFFSET_SHIFT;
-}
-
-static int s5p_mfc_get_dspl_status_v5(struct s5p_mfc_dev *dev)
-{
-       return mfc_read(dev, S5P_FIMV_SI_DISPLAY_STATUS);
-}
-
-static int s5p_mfc_get_dec_status_v5(struct s5p_mfc_dev *dev)
-{
-       return mfc_read(dev, S5P_FIMV_SI_DECODE_STATUS);
-}
-
-static int s5p_mfc_get_dec_frame_type_v5(struct s5p_mfc_dev *dev)
-{
-       return mfc_read(dev, S5P_FIMV_DECODE_FRAME_TYPE) &
-               S5P_FIMV_DECODE_FRAME_MASK;
-}
-
-static int s5p_mfc_get_disp_frame_type_v5(struct s5p_mfc_ctx *ctx)
-{
-       return (s5p_mfc_read_info_v5(ctx, DISP_PIC_FRAME_TYPE) >>
-                       S5P_FIMV_SHARED_DISP_FRAME_TYPE_SHIFT) &
-                       S5P_FIMV_DECODE_FRAME_MASK;
-}
-
-static int s5p_mfc_get_consumed_stream_v5(struct s5p_mfc_dev *dev)
-{
-       return mfc_read(dev, S5P_FIMV_SI_CONSUMED_BYTES);
-}
-
-static int s5p_mfc_get_int_reason_v5(struct s5p_mfc_dev *dev)
-{
-       int reason;
-       reason = mfc_read(dev, S5P_FIMV_RISC2HOST_CMD) &
-               S5P_FIMV_RISC2HOST_CMD_MASK;
-       switch (reason) {
-       case S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET:
-               reason = S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET;
-               break;
-       case S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET:
-               reason = S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET;
-               break;
-       case S5P_FIMV_R2H_CMD_SEQ_DONE_RET:
-               reason = S5P_MFC_R2H_CMD_SEQ_DONE_RET;
-               break;
-       case S5P_FIMV_R2H_CMD_FRAME_DONE_RET:
-               reason = S5P_MFC_R2H_CMD_FRAME_DONE_RET;
-               break;
-       case S5P_FIMV_R2H_CMD_SLICE_DONE_RET:
-               reason = S5P_MFC_R2H_CMD_SLICE_DONE_RET;
-               break;
-       case S5P_FIMV_R2H_CMD_SYS_INIT_RET:
-               reason = S5P_MFC_R2H_CMD_SYS_INIT_RET;
-               break;
-       case S5P_FIMV_R2H_CMD_FW_STATUS_RET:
-               reason = S5P_MFC_R2H_CMD_FW_STATUS_RET;
-               break;
-       case S5P_FIMV_R2H_CMD_SLEEP_RET:
-               reason = S5P_MFC_R2H_CMD_SLEEP_RET;
-               break;
-       case S5P_FIMV_R2H_CMD_WAKEUP_RET:
-               reason = S5P_MFC_R2H_CMD_WAKEUP_RET;
-               break;
-       case S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET:
-               reason = S5P_MFC_R2H_CMD_INIT_BUFFERS_RET;
-               break;
-       case S5P_FIMV_R2H_CMD_ENC_COMPLETE_RET:
-               reason = S5P_MFC_R2H_CMD_COMPLETE_SEQ_RET;
-               break;
-       case S5P_FIMV_R2H_CMD_ERR_RET:
-               reason = S5P_MFC_R2H_CMD_ERR_RET;
-               break;
-       default:
-               reason = S5P_MFC_R2H_CMD_EMPTY;
-       }
-       return reason;
-}
-
-static int s5p_mfc_get_int_err_v5(struct s5p_mfc_dev *dev)
-{
-       return mfc_read(dev, S5P_FIMV_RISC2HOST_ARG2);
-}
-
-static int s5p_mfc_err_dec_v5(unsigned int err)
-{
-       return (err & S5P_FIMV_ERR_DEC_MASK) >> S5P_FIMV_ERR_DEC_SHIFT;
-}
-
-static int s5p_mfc_get_img_width_v5(struct s5p_mfc_dev *dev)
-{
-       return mfc_read(dev, S5P_FIMV_SI_HRESOL);
-}
-
-static int s5p_mfc_get_img_height_v5(struct s5p_mfc_dev *dev)
-{
-       return mfc_read(dev, S5P_FIMV_SI_VRESOL);
-}
-
-static int s5p_mfc_get_dpb_count_v5(struct s5p_mfc_dev *dev)
-{
-       return mfc_read(dev, S5P_FIMV_SI_BUF_NUMBER);
-}
-
-static int s5p_mfc_get_mv_count_v5(struct s5p_mfc_dev *dev)
-{
-       /* NOP */
-       return -1;
-}
-
-static int s5p_mfc_get_inst_no_v5(struct s5p_mfc_dev *dev)
-{
-       return mfc_read(dev, S5P_FIMV_RISC2HOST_ARG1);
-}
-
-static int s5p_mfc_get_enc_strm_size_v5(struct s5p_mfc_dev *dev)
-{
-       return mfc_read(dev, S5P_FIMV_ENC_SI_STRM_SIZE);
-}
-
-static int s5p_mfc_get_enc_slice_type_v5(struct s5p_mfc_dev *dev)
-{
-       return mfc_read(dev, S5P_FIMV_ENC_SI_SLICE_TYPE);
-}
-
-static int s5p_mfc_get_enc_dpb_count_v5(struct s5p_mfc_dev *dev)
-{
-       return -1;
-}
-
-static unsigned int s5p_mfc_get_pic_type_top_v5(struct s5p_mfc_ctx *ctx)
-{
-       return s5p_mfc_read_info_v5(ctx, PIC_TIME_TOP);
-}
-
-static unsigned int s5p_mfc_get_pic_type_bot_v5(struct s5p_mfc_ctx *ctx)
-{
-       return s5p_mfc_read_info_v5(ctx, PIC_TIME_BOT);
-}
-
-static unsigned int s5p_mfc_get_crop_info_h_v5(struct s5p_mfc_ctx *ctx)
-{
-       return s5p_mfc_read_info_v5(ctx, CROP_INFO_H);
-}
-
-static unsigned int s5p_mfc_get_crop_info_v_v5(struct s5p_mfc_ctx *ctx)
-{
-       return s5p_mfc_read_info_v5(ctx, CROP_INFO_V);
-}
-
-/* Initialize opr function pointers for MFC v5 */
-static struct s5p_mfc_hw_ops s5p_mfc_ops_v5 = {
-       .alloc_dec_temp_buffers = s5p_mfc_alloc_dec_temp_buffers_v5,
-       .release_dec_desc_buffer = s5p_mfc_release_dec_desc_buffer_v5,
-       .alloc_codec_buffers = s5p_mfc_alloc_codec_buffers_v5,
-       .release_codec_buffers = s5p_mfc_release_codec_buffers_v5,
-       .alloc_instance_buffer = s5p_mfc_alloc_instance_buffer_v5,
-       .release_instance_buffer = s5p_mfc_release_instance_buffer_v5,
-       .alloc_dev_context_buffer = s5p_mfc_alloc_dev_context_buffer_v5,
-       .release_dev_context_buffer = s5p_mfc_release_dev_context_buffer_v5,
-       .dec_calc_dpb_size = s5p_mfc_dec_calc_dpb_size_v5,
-       .enc_calc_src_size = s5p_mfc_enc_calc_src_size_v5,
-       .set_enc_stream_buffer = s5p_mfc_set_enc_stream_buffer_v5,
-       .set_enc_frame_buffer = s5p_mfc_set_enc_frame_buffer_v5,
-       .get_enc_frame_buffer = s5p_mfc_get_enc_frame_buffer_v5,
-       .try_run = s5p_mfc_try_run_v5,
-       .clear_int_flags = s5p_mfc_clear_int_flags_v5,
-       .get_dspl_y_adr = s5p_mfc_get_dspl_y_adr_v5,
-       .get_dec_y_adr = s5p_mfc_get_dec_y_adr_v5,
-       .get_dspl_status = s5p_mfc_get_dspl_status_v5,
-       .get_dec_status = s5p_mfc_get_dec_status_v5,
-       .get_dec_frame_type = s5p_mfc_get_dec_frame_type_v5,
-       .get_disp_frame_type = s5p_mfc_get_disp_frame_type_v5,
-       .get_consumed_stream = s5p_mfc_get_consumed_stream_v5,
-       .get_int_reason = s5p_mfc_get_int_reason_v5,
-       .get_int_err = s5p_mfc_get_int_err_v5,
-       .err_dec = s5p_mfc_err_dec_v5,
-       .get_img_width = s5p_mfc_get_img_width_v5,
-       .get_img_height = s5p_mfc_get_img_height_v5,
-       .get_dpb_count = s5p_mfc_get_dpb_count_v5,
-       .get_mv_count = s5p_mfc_get_mv_count_v5,
-       .get_inst_no = s5p_mfc_get_inst_no_v5,
-       .get_enc_strm_size = s5p_mfc_get_enc_strm_size_v5,
-       .get_enc_slice_type = s5p_mfc_get_enc_slice_type_v5,
-       .get_enc_dpb_count = s5p_mfc_get_enc_dpb_count_v5,
-       .get_pic_type_top = s5p_mfc_get_pic_type_top_v5,
-       .get_pic_type_bot = s5p_mfc_get_pic_type_bot_v5,
-       .get_crop_info_h = s5p_mfc_get_crop_info_h_v5,
-       .get_crop_info_v = s5p_mfc_get_crop_info_v_v5,
-};
-
-struct s5p_mfc_hw_ops *s5p_mfc_init_hw_ops_v5(void)
-{
-       return &s5p_mfc_ops_v5;
-}
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.h b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.h
deleted file mode 100644 (file)
index b53d376..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * drivers/media/platform/samsung/mfc5/s5p_mfc_opr_v5.h
- *
- * Header file for Samsung MFC (Multi Function Codec - FIMV) driver
- * Contains declarations of hw related functions.
- *
- * Kamil Debski, Copyright (C) 2011 Samsung Electronics
- * http://www.samsung.com/
- */
-
-#ifndef S5P_MFC_OPR_V5_H_
-#define S5P_MFC_OPR_V5_H_
-
-#include "s5p_mfc_common.h"
-#include "s5p_mfc_opr.h"
-
-enum MFC_SHM_OFS {
-       EXTENEDED_DECODE_STATUS = 0x00, /* D */
-       SET_FRAME_TAG           = 0x04, /* D */
-       GET_FRAME_TAG_TOP       = 0x08, /* D */
-       GET_FRAME_TAG_BOT       = 0x0C, /* D */
-       PIC_TIME_TOP            = 0x10, /* D */
-       PIC_TIME_BOT            = 0x14, /* D */
-       START_BYTE_NUM          = 0x18, /* D */
-
-       CROP_INFO_H             = 0x20, /* D */
-       CROP_INFO_V             = 0x24, /* D */
-       EXT_ENC_CONTROL         = 0x28, /* E */
-       ENC_PARAM_CHANGE        = 0x2C, /* E */
-       RC_VOP_TIMING           = 0x30, /* E, MPEG4 */
-       HEC_PERIOD              = 0x34, /* E, MPEG4 */
-       METADATA_ENABLE         = 0x38, /* C */
-       METADATA_STATUS         = 0x3C, /* C */
-       METADATA_DISPLAY_INDEX  = 0x40, /* C */
-       EXT_METADATA_START_ADDR = 0x44, /* C */
-       PUT_EXTRADATA           = 0x48, /* C */
-       EXTRADATA_ADDR          = 0x4C, /* C */
-
-       ALLOC_LUMA_DPB_SIZE     = 0x64, /* D */
-       ALLOC_CHROMA_DPB_SIZE   = 0x68, /* D */
-       ALLOC_MV_SIZE           = 0x6C, /* D */
-       P_B_FRAME_QP            = 0x70, /* E */
-       SAMPLE_ASPECT_RATIO_IDC = 0x74, /* E, H.264, depend on
-                               ASPECT_RATIO_VUI_ENABLE in EXT_ENC_CONTROL */
-       EXTENDED_SAR            = 0x78, /* E, H.264, depned on
-                               ASPECT_RATIO_VUI_ENABLE in EXT_ENC_CONTROL */
-       DISP_PIC_PROFILE        = 0x7C, /* D */
-       FLUSH_CMD_TYPE          = 0x80, /* C */
-       FLUSH_CMD_INBUF1        = 0x84, /* C */
-       FLUSH_CMD_INBUF2        = 0x88, /* C */
-       FLUSH_CMD_OUTBUF        = 0x8C, /* E */
-       NEW_RC_BIT_RATE         = 0x90, /* E, format as RC_BIT_RATE(0xC5A8)
-                       depend on RC_BIT_RATE_CHANGE in ENC_PARAM_CHANGE */
-       NEW_RC_FRAME_RATE       = 0x94, /* E, format as RC_FRAME_RATE(0xD0D0)
-                       depend on RC_FRAME_RATE_CHANGE in ENC_PARAM_CHANGE */
-       NEW_I_PERIOD            = 0x98, /* E, format as I_FRM_CTRL(0xC504)
-                       depend on I_PERIOD_CHANGE in ENC_PARAM_CHANGE */
-       H264_I_PERIOD           = 0x9C, /* E, H.264, open GOP */
-       RC_CONTROL_CONFIG       = 0xA0, /* E */
-       BATCH_INPUT_ADDR        = 0xA4, /* E */
-       BATCH_OUTPUT_ADDR       = 0xA8, /* E */
-       BATCH_OUTPUT_SIZE       = 0xAC, /* E */
-       MIN_LUMA_DPB_SIZE       = 0xB0, /* D */
-       DEVICE_FORMAT_ID        = 0xB4, /* C */
-       H264_POC_TYPE           = 0xB8, /* D */
-       MIN_CHROMA_DPB_SIZE     = 0xBC, /* D */
-       DISP_PIC_FRAME_TYPE     = 0xC0, /* D */
-       FREE_LUMA_DPB           = 0xC4, /* D, VC1 MPEG4 */
-       ASPECT_RATIO_INFO       = 0xC8, /* D, MPEG4 */
-       EXTENDED_PAR            = 0xCC, /* D, MPEG4 */
-       DBG_HISTORY_INPUT0      = 0xD0, /* C */
-       DBG_HISTORY_INPUT1      = 0xD4, /* C */
-       DBG_HISTORY_OUTPUT      = 0xD8, /* C */
-       HIERARCHICAL_P_QP       = 0xE0, /* E, H.264 */
-       FRAME_PACK_SEI_ENABLE   = 0x168, /* C */
-       FRAME_PACK_SEI_AVAIL    = 0x16c, /* D */
-       FRAME_PACK_SEI_INFO     = 0x17c, /* E */
-};
-
-struct s5p_mfc_hw_ops *s5p_mfc_init_hw_ops_v5(void);
-#endif /* S5P_MFC_OPR_H_ */
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
deleted file mode 100644 (file)
index a145305..0000000
+++ /dev/null
@@ -1,2534 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
- *
- * Samsung MFC (Multi Function Codec - FIMV) driver
- * This file contains hw related functions.
- *
- * Copyright (c) 2012 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- */
-
-#undef DEBUG
-
-#include <linux/delay.h>
-#include <linux/mm.h>
-#include <linux/io.h>
-#include <linux/jiffies.h>
-#include <linux/firmware.h>
-#include <linux/err.h>
-#include <linux/sched.h>
-#include <linux/dma-mapping.h>
-
-#include <asm/cacheflush.h>
-
-#include "s5p_mfc_common.h"
-#include "s5p_mfc_cmd.h"
-#include "s5p_mfc_intr.h"
-#include "s5p_mfc_pm.h"
-#include "s5p_mfc_debug.h"
-#include "s5p_mfc_opr.h"
-#include "s5p_mfc_opr_v6.h"
-
-/* #define S5P_MFC_DEBUG_REGWRITE  */
-#ifdef S5P_MFC_DEBUG_REGWRITE
-#undef writel
-#define writel(v, r)                                                   \
-       do {                                                            \
-               pr_err("MFCWRITE(%p): %08x\n", r, (unsigned int)v);     \
-       __raw_writel(v, r);                                             \
-       } while (0)
-#endif /* S5P_MFC_DEBUG_REGWRITE */
-
-#define IS_MFCV6_V2(dev) (!IS_MFCV7_PLUS(dev) && dev->fw_ver == MFC_FW_V2)
-
-/* Allocate temporary buffers for decoding */
-static int s5p_mfc_alloc_dec_temp_buffers_v6(struct s5p_mfc_ctx *ctx)
-{
-       /* NOP */
-
-       return 0;
-}
-
-/* Release temporary buffers for decoding */
-static void s5p_mfc_release_dec_desc_buffer_v6(struct s5p_mfc_ctx *ctx)
-{
-       /* NOP */
-}
-
-/* Allocate codec buffers */
-static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       unsigned int mb_width, mb_height;
-       unsigned int lcu_width = 0, lcu_height = 0;
-       int ret;
-
-       mb_width = MB_WIDTH(ctx->img_width);
-       mb_height = MB_HEIGHT(ctx->img_height);
-
-       if (ctx->type == MFCINST_DECODER) {
-               mfc_debug(2, "Luma size:%d Chroma size:%d MV size:%d\n",
-                         ctx->luma_size, ctx->chroma_size, ctx->mv_size);
-               mfc_debug(2, "Totals bufs: %d\n", ctx->total_dpb_count);
-       } else if (ctx->type == MFCINST_ENCODER) {
-               if (IS_MFCV10(dev)) {
-                       ctx->tmv_buffer_size = 0;
-               } else if (IS_MFCV8_PLUS(dev))
-                       ctx->tmv_buffer_size = S5P_FIMV_NUM_TMV_BUFFERS_V6 *
-                       ALIGN(S5P_FIMV_TMV_BUFFER_SIZE_V8(mb_width, mb_height),
-                       S5P_FIMV_TMV_BUFFER_ALIGN_V6);
-               else
-                       ctx->tmv_buffer_size = S5P_FIMV_NUM_TMV_BUFFERS_V6 *
-                       ALIGN(S5P_FIMV_TMV_BUFFER_SIZE_V6(mb_width, mb_height),
-                       S5P_FIMV_TMV_BUFFER_ALIGN_V6);
-               if (IS_MFCV10(dev)) {
-                       lcu_width = S5P_MFC_LCU_WIDTH(ctx->img_width);
-                       lcu_height = S5P_MFC_LCU_HEIGHT(ctx->img_height);
-                       if (ctx->codec_mode != S5P_FIMV_CODEC_HEVC_ENC) {
-                               ctx->luma_dpb_size =
-                                       ALIGN((mb_width * 16), 64)
-                                       * ALIGN((mb_height * 16), 32)
-                                               + 64;
-                               ctx->chroma_dpb_size =
-                                       ALIGN((mb_width * 16), 64)
-                                                       * (mb_height * 8)
-                                                       + 64;
-                       } else {
-                               ctx->luma_dpb_size =
-                                       ALIGN((lcu_width * 32), 64)
-                                       * ALIGN((lcu_height * 32), 32)
-                                               + 64;
-                               ctx->chroma_dpb_size =
-                                       ALIGN((lcu_width * 32), 64)
-                                                       * (lcu_height * 16)
-                                                       + 64;
-                       }
-               } else {
-                       ctx->luma_dpb_size = ALIGN((mb_width * mb_height) *
-                                       S5P_FIMV_LUMA_MB_TO_PIXEL_V6,
-                                       S5P_FIMV_LUMA_DPB_BUFFER_ALIGN_V6);
-                       ctx->chroma_dpb_size = ALIGN((mb_width * mb_height) *
-                                       S5P_FIMV_CHROMA_MB_TO_PIXEL_V6,
-                                       S5P_FIMV_CHROMA_DPB_BUFFER_ALIGN_V6);
-               }
-               if (IS_MFCV8_PLUS(dev))
-                       ctx->me_buffer_size = ALIGN(S5P_FIMV_ME_BUFFER_SIZE_V8(
-                                               ctx->img_width, ctx->img_height,
-                                               mb_width, mb_height),
-                                               S5P_FIMV_ME_BUFFER_ALIGN_V6);
-               else
-                       ctx->me_buffer_size = ALIGN(S5P_FIMV_ME_BUFFER_SIZE_V6(
-                                               ctx->img_width, ctx->img_height,
-                                               mb_width, mb_height),
-                                               S5P_FIMV_ME_BUFFER_ALIGN_V6);
-
-               mfc_debug(2, "recon luma size: %zu chroma size: %zu\n",
-                         ctx->luma_dpb_size, ctx->chroma_dpb_size);
-       } else {
-               return -EINVAL;
-       }
-
-       /* Codecs have different memory requirements */
-       switch (ctx->codec_mode) {
-       case S5P_MFC_CODEC_H264_DEC:
-       case S5P_MFC_CODEC_H264_MVC_DEC:
-               if (IS_MFCV10(dev))
-                       mfc_debug(2, "Use min scratch buffer size\n");
-               else if (IS_MFCV8_PLUS(dev))
-                       ctx->scratch_buf_size =
-                               S5P_FIMV_SCRATCH_BUF_SIZE_H264_DEC_V8(
-                                       mb_width,
-                                       mb_height);
-               else
-                       ctx->scratch_buf_size =
-                               S5P_FIMV_SCRATCH_BUF_SIZE_H264_DEC_V6(
-                                       mb_width,
-                                       mb_height);
-               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size,
-                               S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
-               ctx->bank1.size =
-                       ctx->scratch_buf_size +
-                       (ctx->mv_count * ctx->mv_size);
-               break;
-       case S5P_MFC_CODEC_MPEG4_DEC:
-               if (IS_MFCV10(dev))
-                       mfc_debug(2, "Use min scratch buffer size\n");
-               else if (IS_MFCV7_PLUS(dev)) {
-                       ctx->scratch_buf_size =
-                               S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_DEC_V7(
-                                               mb_width,
-                                               mb_height);
-               } else {
-                       ctx->scratch_buf_size =
-                               S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_DEC_V6(
-                                               mb_width,
-                                               mb_height);
-               }
-
-               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size,
-                               S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
-               ctx->bank1.size = ctx->scratch_buf_size;
-               break;
-       case S5P_MFC_CODEC_VC1RCV_DEC:
-       case S5P_MFC_CODEC_VC1_DEC:
-               if (IS_MFCV10(dev))
-                       mfc_debug(2, "Use min scratch buffer size\n");
-               else
-                       ctx->scratch_buf_size =
-                               S5P_FIMV_SCRATCH_BUF_SIZE_VC1_DEC_V6(
-                                               mb_width,
-                                               mb_height);
-
-               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size,
-                               S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
-               ctx->bank1.size = ctx->scratch_buf_size;
-               break;
-       case S5P_MFC_CODEC_MPEG2_DEC:
-               ctx->bank1.size = 0;
-               ctx->bank2.size = 0;
-               break;
-       case S5P_MFC_CODEC_H263_DEC:
-               if (IS_MFCV10(dev))
-                       mfc_debug(2, "Use min scratch buffer size\n");
-               else
-                       ctx->scratch_buf_size =
-                               S5P_FIMV_SCRATCH_BUF_SIZE_H263_DEC_V6(
-                                               mb_width,
-                                               mb_height);
-               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size,
-                               S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
-               ctx->bank1.size = ctx->scratch_buf_size;
-               break;
-       case S5P_MFC_CODEC_VP8_DEC:
-               if (IS_MFCV10(dev))
-                       mfc_debug(2, "Use min scratch buffer size\n");
-               else if (IS_MFCV8_PLUS(dev))
-                       ctx->scratch_buf_size =
-                               S5P_FIMV_SCRATCH_BUF_SIZE_VP8_DEC_V8(
-                                               mb_width,
-                                               mb_height);
-               else
-                       ctx->scratch_buf_size =
-                               S5P_FIMV_SCRATCH_BUF_SIZE_VP8_DEC_V6(
-                                               mb_width,
-                                               mb_height);
-               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size,
-                               S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
-               ctx->bank1.size = ctx->scratch_buf_size;
-               break;
-       case S5P_MFC_CODEC_HEVC_DEC:
-               mfc_debug(2, "Use min scratch buffer size\n");
-               ctx->bank1.size =
-                       ctx->scratch_buf_size +
-                       (ctx->mv_count * ctx->mv_size);
-               break;
-       case S5P_MFC_CODEC_VP9_DEC:
-               mfc_debug(2, "Use min scratch buffer size\n");
-               ctx->bank1.size =
-                       ctx->scratch_buf_size +
-                       DEC_VP9_STATIC_BUFFER_SIZE;
-               break;
-       case S5P_MFC_CODEC_H264_ENC:
-               if (IS_MFCV10(dev)) {
-                       mfc_debug(2, "Use min scratch buffer size\n");
-                       ctx->me_buffer_size =
-                       ALIGN(ENC_V100_H264_ME_SIZE(mb_width, mb_height), 16);
-               } else if (IS_MFCV8_PLUS(dev))
-                       ctx->scratch_buf_size =
-                               S5P_FIMV_SCRATCH_BUF_SIZE_H264_ENC_V8(
-                                       mb_width,
-                                       mb_height);
-               else
-                       ctx->scratch_buf_size =
-                               S5P_FIMV_SCRATCH_BUF_SIZE_H264_ENC_V6(
-                                               mb_width,
-                                               mb_height);
-               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size,
-                               S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
-               ctx->bank1.size =
-                       ctx->scratch_buf_size + ctx->tmv_buffer_size +
-                       (ctx->pb_count * (ctx->luma_dpb_size +
-                       ctx->chroma_dpb_size + ctx->me_buffer_size));
-               ctx->bank2.size = 0;
-               break;
-       case S5P_MFC_CODEC_MPEG4_ENC:
-       case S5P_MFC_CODEC_H263_ENC:
-               if (IS_MFCV10(dev)) {
-                       mfc_debug(2, "Use min scratch buffer size\n");
-                       ctx->me_buffer_size =
-                               ALIGN(ENC_V100_MPEG4_ME_SIZE(mb_width,
-                                                       mb_height), 16);
-               } else
-                       ctx->scratch_buf_size =
-                               S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_ENC_V6(
-                                               mb_width,
-                                               mb_height);
-               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size,
-                               S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
-               ctx->bank1.size =
-                       ctx->scratch_buf_size + ctx->tmv_buffer_size +
-                       (ctx->pb_count * (ctx->luma_dpb_size +
-                       ctx->chroma_dpb_size + ctx->me_buffer_size));
-               ctx->bank2.size = 0;
-               break;
-       case S5P_MFC_CODEC_VP8_ENC:
-               if (IS_MFCV10(dev)) {
-                       mfc_debug(2, "Use min scratch buffer size\n");
-                       ctx->me_buffer_size =
-                               ALIGN(ENC_V100_VP8_ME_SIZE(mb_width, mb_height),
-                                               16);
-               } else if (IS_MFCV8_PLUS(dev))
-                       ctx->scratch_buf_size =
-                               S5P_FIMV_SCRATCH_BUF_SIZE_VP8_ENC_V8(
-                                       mb_width,
-                                       mb_height);
-               else
-                       ctx->scratch_buf_size =
-                               S5P_FIMV_SCRATCH_BUF_SIZE_VP8_ENC_V7(
-                                               mb_width,
-                                               mb_height);
-               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size,
-                               S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
-               ctx->bank1.size =
-                       ctx->scratch_buf_size + ctx->tmv_buffer_size +
-                       (ctx->pb_count * (ctx->luma_dpb_size +
-                       ctx->chroma_dpb_size + ctx->me_buffer_size));
-               ctx->bank2.size = 0;
-               break;
-       case S5P_MFC_CODEC_HEVC_ENC:
-               mfc_debug(2, "Use min scratch buffer size\n");
-               ctx->me_buffer_size =
-                       ALIGN(ENC_V100_HEVC_ME_SIZE(lcu_width, lcu_height), 16);
-               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
-               ctx->bank1.size =
-                       ctx->scratch_buf_size + ctx->tmv_buffer_size +
-                       (ctx->pb_count * (ctx->luma_dpb_size +
-                       ctx->chroma_dpb_size + ctx->me_buffer_size));
-               ctx->bank2.size = 0;
-               break;
-       default:
-               break;
-       }
-
-       /* Allocate only if memory from bank 1 is necessary */
-       if (ctx->bank1.size > 0) {
-               ret = s5p_mfc_alloc_generic_buf(dev, BANK_L_CTX, &ctx->bank1);
-               if (ret) {
-                       mfc_err("Failed to allocate Bank1 memory\n");
-                       return ret;
-               }
-               BUG_ON(ctx->bank1.dma & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
-       }
-       return 0;
-}
-
-/* Release buffers allocated for codec */
-static void s5p_mfc_release_codec_buffers_v6(struct s5p_mfc_ctx *ctx)
-{
-       s5p_mfc_release_generic_buf(ctx->dev, &ctx->bank1);
-}
-
-/* Allocate memory for instance data buffer */
-static int s5p_mfc_alloc_instance_buffer_v6(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_buf_size_v6 *buf_size = dev->variant->buf_size->priv;
-       int ret;
-
-       mfc_debug_enter();
-
-       switch (ctx->codec_mode) {
-       case S5P_MFC_CODEC_H264_DEC:
-       case S5P_MFC_CODEC_H264_MVC_DEC:
-       case S5P_MFC_CODEC_HEVC_DEC:
-               ctx->ctx.size = buf_size->h264_dec_ctx;
-               break;
-       case S5P_MFC_CODEC_MPEG4_DEC:
-       case S5P_MFC_CODEC_H263_DEC:
-       case S5P_MFC_CODEC_VC1RCV_DEC:
-       case S5P_MFC_CODEC_VC1_DEC:
-       case S5P_MFC_CODEC_MPEG2_DEC:
-       case S5P_MFC_CODEC_VP8_DEC:
-       case S5P_MFC_CODEC_VP9_DEC:
-               ctx->ctx.size = buf_size->other_dec_ctx;
-               break;
-       case S5P_MFC_CODEC_H264_ENC:
-               ctx->ctx.size = buf_size->h264_enc_ctx;
-               break;
-       case S5P_MFC_CODEC_HEVC_ENC:
-               ctx->ctx.size = buf_size->hevc_enc_ctx;
-               break;
-       case S5P_MFC_CODEC_MPEG4_ENC:
-       case S5P_MFC_CODEC_H263_ENC:
-       case S5P_MFC_CODEC_VP8_ENC:
-               ctx->ctx.size = buf_size->other_enc_ctx;
-               break;
-       default:
-               ctx->ctx.size = 0;
-               mfc_err("Codec type(%d) should be checked!\n", ctx->codec_mode);
-               break;
-       }
-
-       ret = s5p_mfc_alloc_priv_buf(dev, BANK_L_CTX, &ctx->ctx);
-       if (ret) {
-               mfc_err("Failed to allocate instance buffer\n");
-               return ret;
-       }
-
-       memset(ctx->ctx.virt, 0, ctx->ctx.size);
-       wmb();
-
-       mfc_debug_leave();
-
-       return 0;
-}
-
-/* Release instance buffer */
-static void s5p_mfc_release_instance_buffer_v6(struct s5p_mfc_ctx *ctx)
-{
-       s5p_mfc_release_priv_buf(ctx->dev, &ctx->ctx);
-}
-
-/* Allocate context buffers for SYS_INIT */
-static int s5p_mfc_alloc_dev_context_buffer_v6(struct s5p_mfc_dev *dev)
-{
-       struct s5p_mfc_buf_size_v6 *buf_size = dev->variant->buf_size->priv;
-       int ret;
-
-       mfc_debug_enter();
-
-       dev->ctx_buf.size = buf_size->dev_ctx;
-       ret = s5p_mfc_alloc_priv_buf(dev, BANK_L_CTX, &dev->ctx_buf);
-       if (ret) {
-               mfc_err("Failed to allocate device context buffer\n");
-               return ret;
-       }
-
-       memset(dev->ctx_buf.virt, 0, buf_size->dev_ctx);
-       wmb();
-
-       mfc_debug_leave();
-
-       return 0;
-}
-
-/* Release context buffers for SYS_INIT */
-static void s5p_mfc_release_dev_context_buffer_v6(struct s5p_mfc_dev *dev)
-{
-       s5p_mfc_release_priv_buf(dev, &dev->ctx_buf);
-}
-
-static int calc_plane(int width, int height)
-{
-       int mbX, mbY;
-
-       mbX = DIV_ROUND_UP(width, S5P_FIMV_NUM_PIXELS_IN_MB_ROW_V6);
-       mbY = DIV_ROUND_UP(height, S5P_FIMV_NUM_PIXELS_IN_MB_COL_V6);
-
-       if (width * height < S5P_FIMV_MAX_FRAME_SIZE_V6)
-               mbY = (mbY + 1) / 2 * 2;
-
-       return (mbX * S5P_FIMV_NUM_PIXELS_IN_MB_COL_V6) *
-               (mbY * S5P_FIMV_NUM_PIXELS_IN_MB_ROW_V6);
-}
-
-static void s5p_mfc_dec_calc_dpb_size_v6(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN_V6);
-       ctx->buf_height = ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN_V6);
-       mfc_debug(2, "SEQ Done: Movie dimensions %dx%d,\n"
-                       "buffer dimensions: %dx%d\n", ctx->img_width,
-                       ctx->img_height, ctx->buf_width, ctx->buf_height);
-
-       ctx->luma_size = calc_plane(ctx->img_width, ctx->img_height);
-       ctx->chroma_size = calc_plane(ctx->img_width, (ctx->img_height >> 1));
-       if (IS_MFCV8_PLUS(ctx->dev)) {
-               /* MFCv8 needs additional 64 bytes for luma,chroma dpb*/
-               ctx->luma_size += S5P_FIMV_D_ALIGN_PLANE_SIZE_V8;
-               ctx->chroma_size += S5P_FIMV_D_ALIGN_PLANE_SIZE_V8;
-       }
-
-       if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC ||
-                       ctx->codec_mode == S5P_MFC_CODEC_H264_MVC_DEC) {
-               if (IS_MFCV10(dev)) {
-                       ctx->mv_size = S5P_MFC_DEC_MV_SIZE_V10(ctx->img_width,
-                                       ctx->img_height);
-               } else {
-                       ctx->mv_size = S5P_MFC_DEC_MV_SIZE_V6(ctx->img_width,
-                                       ctx->img_height);
-               }
-       } else if (ctx->codec_mode == S5P_MFC_CODEC_HEVC_DEC) {
-               ctx->mv_size = s5p_mfc_dec_hevc_mv_size(ctx->img_width,
-                               ctx->img_height);
-               ctx->mv_size = ALIGN(ctx->mv_size, 32);
-       } else {
-               ctx->mv_size = 0;
-       }
-}
-
-static void s5p_mfc_enc_calc_src_size_v6(struct s5p_mfc_ctx *ctx)
-{
-       unsigned int mb_width, mb_height;
-
-       mb_width = MB_WIDTH(ctx->img_width);
-       mb_height = MB_HEIGHT(ctx->img_height);
-
-       ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN_V6);
-       ctx->luma_size = ALIGN((mb_width * mb_height) * 256, 256);
-       ctx->chroma_size = ALIGN((mb_width * mb_height) * 128, 256);
-
-       /* MFCv7 needs pad bytes for Luma and Chroma */
-       if (IS_MFCV7_PLUS(ctx->dev)) {
-               ctx->luma_size += MFC_LUMA_PAD_BYTES_V7;
-               ctx->chroma_size += MFC_CHROMA_PAD_BYTES_V7;
-       }
-}
-
-/* Set registers for decoding stream buffer */
-static int s5p_mfc_set_dec_stream_buffer_v6(struct s5p_mfc_ctx *ctx,
-                       int buf_addr, unsigned int start_num_byte,
-                       unsigned int strm_size)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs;
-       struct s5p_mfc_buf_size *buf_size = dev->variant->buf_size;
-
-       mfc_debug_enter();
-       mfc_debug(2, "inst_no: %d, buf_addr: 0x%08x,\n"
-               "buf_size: 0x%08x (%d)\n",
-               ctx->inst_no, buf_addr, strm_size, strm_size);
-       writel(strm_size, mfc_regs->d_stream_data_size);
-       writel(buf_addr, mfc_regs->d_cpb_buffer_addr);
-       writel(buf_size->cpb, mfc_regs->d_cpb_buffer_size);
-       writel(start_num_byte, mfc_regs->d_cpb_buffer_offset);
-
-       mfc_debug_leave();
-       return 0;
-}
-
-/* Set decoding frame buffer */
-static int s5p_mfc_set_dec_frame_buffer_v6(struct s5p_mfc_ctx *ctx)
-{
-       unsigned int frame_size, i;
-       unsigned int frame_size_ch, frame_size_mv;
-       struct s5p_mfc_dev *dev = ctx->dev;
-       const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs;
-       size_t buf_addr1;
-       int buf_size1;
-       int align_gap;
-
-       buf_addr1 = ctx->bank1.dma;
-       buf_size1 = ctx->bank1.size;
-
-       mfc_debug(2, "Buf1: %p (%d)\n", (void *)buf_addr1, buf_size1);
-       mfc_debug(2, "Total DPB COUNT: %d\n", ctx->total_dpb_count);
-       mfc_debug(2, "Setting display delay to %d\n", ctx->display_delay);
-
-       writel(ctx->total_dpb_count, mfc_regs->d_num_dpb);
-       writel(ctx->luma_size, mfc_regs->d_first_plane_dpb_size);
-       writel(ctx->chroma_size, mfc_regs->d_second_plane_dpb_size);
-
-       writel(buf_addr1, mfc_regs->d_scratch_buffer_addr);
-       writel(ctx->scratch_buf_size, mfc_regs->d_scratch_buffer_size);
-
-       if (IS_MFCV8_PLUS(dev)) {
-               writel(ctx->img_width,
-                       mfc_regs->d_first_plane_dpb_stride_size);
-               writel(ctx->img_width,
-                       mfc_regs->d_second_plane_dpb_stride_size);
-       }
-
-       buf_addr1 += ctx->scratch_buf_size;
-       buf_size1 -= ctx->scratch_buf_size;
-
-       if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC ||
-                       ctx->codec_mode == S5P_FIMV_CODEC_H264_MVC_DEC ||
-                       ctx->codec_mode == S5P_FIMV_CODEC_HEVC_DEC) {
-               writel(ctx->mv_size, mfc_regs->d_mv_buffer_size);
-               writel(ctx->mv_count, mfc_regs->d_num_mv);
-       }
-
-       frame_size = ctx->luma_size;
-       frame_size_ch = ctx->chroma_size;
-       frame_size_mv = ctx->mv_size;
-       mfc_debug(2, "Frame size: %d ch: %d mv: %d\n",
-                       frame_size, frame_size_ch, frame_size_mv);
-
-       for (i = 0; i < ctx->total_dpb_count; i++) {
-               /* Bank2 */
-               mfc_debug(2, "Luma %d: %zx\n", i,
-                                       ctx->dst_bufs[i].cookie.raw.luma);
-               writel(ctx->dst_bufs[i].cookie.raw.luma,
-                               mfc_regs->d_first_plane_dpb + i * 4);
-               mfc_debug(2, "\tChroma %d: %zx\n", i,
-                                       ctx->dst_bufs[i].cookie.raw.chroma);
-               writel(ctx->dst_bufs[i].cookie.raw.chroma,
-                               mfc_regs->d_second_plane_dpb + i * 4);
-       }
-       if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC ||
-                       ctx->codec_mode == S5P_MFC_CODEC_H264_MVC_DEC ||
-                       ctx->codec_mode == S5P_MFC_CODEC_HEVC_DEC) {
-               for (i = 0; i < ctx->mv_count; i++) {
-                       /* To test alignment */
-                       align_gap = buf_addr1;
-                       buf_addr1 = ALIGN(buf_addr1, 16);
-                       align_gap = buf_addr1 - align_gap;
-                       buf_size1 -= align_gap;
-
-                       mfc_debug(2, "\tBuf1: %zx, size: %d\n",
-                                       buf_addr1, buf_size1);
-                       writel(buf_addr1, mfc_regs->d_mv_buffer + i * 4);
-                       buf_addr1 += frame_size_mv;
-                       buf_size1 -= frame_size_mv;
-               }
-       }
-       if (ctx->codec_mode == S5P_FIMV_CODEC_VP9_DEC) {
-               writel(buf_addr1, mfc_regs->d_static_buffer_addr);
-               writel(DEC_VP9_STATIC_BUFFER_SIZE,
-                               mfc_regs->d_static_buffer_size);
-               buf_addr1 += DEC_VP9_STATIC_BUFFER_SIZE;
-               buf_size1 -= DEC_VP9_STATIC_BUFFER_SIZE;
-       }
-
-       mfc_debug(2, "Buf1: %zx, buf_size1: %d (frames %d)\n",
-                       buf_addr1, buf_size1, ctx->total_dpb_count);
-       if (buf_size1 < 0) {
-               mfc_debug(2, "Not enough memory has been allocated.\n");
-               return -ENOMEM;
-       }
-
-       writel(ctx->inst_no, mfc_regs->instance_id);
-       s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev,
-                       S5P_FIMV_CH_INIT_BUFS_V6, NULL);
-
-       mfc_debug(2, "After setting buffers.\n");
-       return 0;
-}
-
-/* Set registers for encoding stream buffer */
-static int s5p_mfc_set_enc_stream_buffer_v6(struct s5p_mfc_ctx *ctx,
-               unsigned long addr, unsigned int size)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs;
-
-       writel(addr, mfc_regs->e_stream_buffer_addr); /* 16B align */
-       writel(size, mfc_regs->e_stream_buffer_size);
-
-       mfc_debug(2, "stream buf addr: 0x%08lx, size: 0x%x\n",
-                 addr, size);
-
-       return 0;
-}
-
-static void s5p_mfc_set_enc_frame_buffer_v6(struct s5p_mfc_ctx *ctx,
-               unsigned long y_addr, unsigned long c_addr)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs;
-
-       writel(y_addr, mfc_regs->e_source_first_plane_addr);
-       writel(c_addr, mfc_regs->e_source_second_plane_addr);
-
-       mfc_debug(2, "enc src y buf addr: 0x%08lx\n", y_addr);
-       mfc_debug(2, "enc src c buf addr: 0x%08lx\n", c_addr);
-}
-
-static void s5p_mfc_get_enc_frame_buffer_v6(struct s5p_mfc_ctx *ctx,
-               unsigned long *y_addr, unsigned long *c_addr)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs;
-       unsigned long enc_recon_y_addr, enc_recon_c_addr;
-
-       *y_addr = readl(mfc_regs->e_encoded_source_first_plane_addr);
-       *c_addr = readl(mfc_regs->e_encoded_source_second_plane_addr);
-
-       enc_recon_y_addr = readl(mfc_regs->e_recon_luma_dpb_addr);
-       enc_recon_c_addr = readl(mfc_regs->e_recon_chroma_dpb_addr);
-
-       mfc_debug(2, "recon y addr: 0x%08lx y_addr: 0x%08lx\n", enc_recon_y_addr, *y_addr);
-       mfc_debug(2, "recon c addr: 0x%08lx\n", enc_recon_c_addr);
-}
-
-/* Set encoding ref & codec buffer */
-static int s5p_mfc_set_enc_ref_buffer_v6(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs;
-       size_t buf_addr1;
-       int i, buf_size1;
-
-       mfc_debug_enter();
-
-       buf_addr1 = ctx->bank1.dma;
-       buf_size1 = ctx->bank1.size;
-
-       mfc_debug(2, "Buf1: %p (%d)\n", (void *)buf_addr1, buf_size1);
-
-       if (IS_MFCV10(dev)) {
-               /* start address of per buffer is aligned */
-               for (i = 0; i < ctx->pb_count; i++) {
-                       writel(buf_addr1, mfc_regs->e_luma_dpb + (4 * i));
-                       buf_addr1 += ctx->luma_dpb_size;
-                       buf_size1 -= ctx->luma_dpb_size;
-               }
-               for (i = 0; i < ctx->pb_count; i++) {
-                       writel(buf_addr1, mfc_regs->e_chroma_dpb + (4 * i));
-                       buf_addr1 += ctx->chroma_dpb_size;
-                       buf_size1 -= ctx->chroma_dpb_size;
-               }
-               for (i = 0; i < ctx->pb_count; i++) {
-                       writel(buf_addr1, mfc_regs->e_me_buffer + (4 * i));
-                       buf_addr1 += ctx->me_buffer_size;
-                       buf_size1 -= ctx->me_buffer_size;
-               }
-       } else {
-               for (i = 0; i < ctx->pb_count; i++) {
-                       writel(buf_addr1, mfc_regs->e_luma_dpb + (4 * i));
-                       buf_addr1 += ctx->luma_dpb_size;
-                       writel(buf_addr1, mfc_regs->e_chroma_dpb + (4 * i));
-                       buf_addr1 += ctx->chroma_dpb_size;
-                       writel(buf_addr1, mfc_regs->e_me_buffer + (4 * i));
-                       buf_addr1 += ctx->me_buffer_size;
-                       buf_size1 -= (ctx->luma_dpb_size + ctx->chroma_dpb_size
-                                       + ctx->me_buffer_size);
-               }
-       }
-
-       writel(buf_addr1, mfc_regs->e_scratch_buffer_addr);
-       writel(ctx->scratch_buf_size, mfc_regs->e_scratch_buffer_size);
-       buf_addr1 += ctx->scratch_buf_size;
-       buf_size1 -= ctx->scratch_buf_size;
-
-       writel(buf_addr1, mfc_regs->e_tmv_buffer0);
-       buf_addr1 += ctx->tmv_buffer_size >> 1;
-       writel(buf_addr1, mfc_regs->e_tmv_buffer1);
-       buf_addr1 += ctx->tmv_buffer_size >> 1;
-       buf_size1 -= ctx->tmv_buffer_size;
-
-       mfc_debug(2, "Buf1: %zu, buf_size1: %d (ref frames %d)\n",
-                       buf_addr1, buf_size1, ctx->pb_count);
-       if (buf_size1 < 0) {
-               mfc_debug(2, "Not enough memory has been allocated.\n");
-               return -ENOMEM;
-       }
-
-       writel(ctx->inst_no, mfc_regs->instance_id);
-       s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev,
-                       S5P_FIMV_CH_INIT_BUFS_V6, NULL);
-
-       mfc_debug_leave();
-
-       return 0;
-}
-
-static int s5p_mfc_set_slice_mode(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs;
-
-       /* multi-slice control */
-       /* multi-slice MB number or bit size */
-       writel(ctx->slice_mode, mfc_regs->e_mslice_mode);
-       if (ctx->slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB) {
-               writel(ctx->slice_size.mb, mfc_regs->e_mslice_size_mb);
-       } else if (ctx->slice_mode ==
-                       V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES) {
-               writel(ctx->slice_size.bits, mfc_regs->e_mslice_size_bits);
-       } else {
-               writel(0x0, mfc_regs->e_mslice_size_mb);
-               writel(0x0, mfc_regs->e_mslice_size_bits);
-       }
-
-       return 0;
-}
-
-static int s5p_mfc_set_enc_params(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs;
-       struct s5p_mfc_enc_params *p = &ctx->enc_params;
-       unsigned int reg = 0;
-
-       mfc_debug_enter();
-
-       /* width */
-       writel(ctx->img_width, mfc_regs->e_frame_width); /* 16 align */
-       /* height */
-       writel(ctx->img_height, mfc_regs->e_frame_height); /* 16 align */
-
-       /* cropped width */
-       writel(ctx->img_width, mfc_regs->e_cropped_frame_width);
-       /* cropped height */
-       writel(ctx->img_height, mfc_regs->e_cropped_frame_height);
-       /* cropped offset */
-       writel(0x0, mfc_regs->e_frame_crop_offset);
-
-       /* pictype : IDR period */
-       reg = 0;
-       reg |= p->gop_size & 0xFFFF;
-       writel(reg, mfc_regs->e_gop_config);
-
-       /* multi-slice control */
-       /* multi-slice MB number or bit size */
-       ctx->slice_mode = p->slice_mode;
-       reg = 0;
-       if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB) {
-               reg |= (0x1 << 3);
-               writel(reg, mfc_regs->e_enc_options);
-               ctx->slice_size.mb = p->slice_mb;
-       } else if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES) {
-               reg |= (0x1 << 3);
-               writel(reg, mfc_regs->e_enc_options);
-               ctx->slice_size.bits = p->slice_bit;
-       } else {
-               reg &= ~(0x1 << 3);
-               writel(reg, mfc_regs->e_enc_options);
-       }
-
-       s5p_mfc_set_slice_mode(ctx);
-
-       /* cyclic intra refresh */
-       writel(p->intra_refresh_mb, mfc_regs->e_ir_size);
-       reg = readl(mfc_regs->e_enc_options);
-       if (p->intra_refresh_mb == 0)
-               reg &= ~(0x1 << 4);
-       else
-               reg |= (0x1 << 4);
-       writel(reg, mfc_regs->e_enc_options);
-
-       /* 'NON_REFERENCE_STORE_ENABLE' for debugging */
-       reg = readl(mfc_regs->e_enc_options);
-       reg &= ~(0x1 << 9);
-       writel(reg, mfc_regs->e_enc_options);
-
-       /* memory structure cur. frame */
-       if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M) {
-               /* 0: Linear, 1: 2D tiled*/
-               reg = readl(mfc_regs->e_enc_options);
-               reg &= ~(0x1 << 7);
-               writel(reg, mfc_regs->e_enc_options);
-               /* 0: NV12(CbCr), 1: NV21(CrCb) */
-               writel(0x0, mfc_regs->pixel_format);
-       } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV21M) {
-               /* 0: Linear, 1: 2D tiled*/
-               reg = readl(mfc_regs->e_enc_options);
-               reg &= ~(0x1 << 7);
-               writel(reg, mfc_regs->e_enc_options);
-               /* 0: NV12(CbCr), 1: NV21(CrCb) */
-               writel(0x1, mfc_regs->pixel_format);
-       } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16) {
-               /* 0: Linear, 1: 2D tiled*/
-               reg = readl(mfc_regs->e_enc_options);
-               reg |= (0x1 << 7);
-               writel(reg, mfc_regs->e_enc_options);
-               /* 0: NV12(CbCr), 1: NV21(CrCb) */
-               writel(0x0, mfc_regs->pixel_format);
-       }
-
-       /* memory structure recon. frame */
-       /* 0: Linear, 1: 2D tiled */
-       reg = readl(mfc_regs->e_enc_options);
-       reg |= (0x1 << 8);
-       writel(reg, mfc_regs->e_enc_options);
-
-       /* padding control & value */
-       writel(0x0, mfc_regs->e_padding_ctrl);
-       if (p->pad) {
-               reg = 0;
-               /** enable */
-               reg |= (1UL << 31);
-               /** cr value */
-               reg |= ((p->pad_cr & 0xFF) << 16);
-               /** cb value */
-               reg |= ((p->pad_cb & 0xFF) << 8);
-               /** y value */
-               reg |= p->pad_luma & 0xFF;
-               writel(reg, mfc_regs->e_padding_ctrl);
-       }
-
-       /* rate control config. */
-       reg = 0;
-       /* frame-level rate control */
-       reg |= ((p->rc_frame & 0x1) << 9);
-       writel(reg, mfc_regs->e_rc_config);
-
-       /* bit rate */
-       if (p->rc_frame)
-               writel(p->rc_bitrate,
-                       mfc_regs->e_rc_bit_rate);
-       else
-               writel(1, mfc_regs->e_rc_bit_rate);
-
-       /* reaction coefficient */
-       if (p->rc_frame) {
-               if (p->rc_reaction_coeff < TIGHT_CBR_MAX) /* tight CBR */
-                       writel(1, mfc_regs->e_rc_mode);
-               else                                      /* loose CBR */
-                       writel(2, mfc_regs->e_rc_mode);
-       }
-
-       /* seq header ctrl */
-       reg = readl(mfc_regs->e_enc_options);
-       reg &= ~(0x1 << 2);
-       reg |= ((p->seq_hdr_mode & 0x1) << 2);
-
-       /* frame skip mode */
-       reg &= ~(0x3);
-       reg |= (p->frame_skip_mode & 0x3);
-       writel(reg, mfc_regs->e_enc_options);
-
-       /* 'DROP_CONTROL_ENABLE', disable */
-       reg = readl(mfc_regs->e_rc_config);
-       reg &= ~(0x1 << 10);
-       writel(reg, mfc_regs->e_rc_config);
-
-       /* setting for MV range [16, 256] */
-       reg = (p->mv_h_range & S5P_FIMV_E_MV_RANGE_V6_MASK);
-       writel(reg, mfc_regs->e_mv_hor_range);
-
-       reg = (p->mv_v_range & S5P_FIMV_E_MV_RANGE_V6_MASK);
-       writel(reg, mfc_regs->e_mv_ver_range);
-
-       writel(0x0, mfc_regs->e_frame_insertion);
-       writel(0x0, mfc_regs->e_roi_buffer_addr);
-       writel(0x0, mfc_regs->e_param_change);
-       writel(0x0, mfc_regs->e_rc_roi_ctrl);
-       writel(0x0, mfc_regs->e_picture_tag);
-
-       writel(0x0, mfc_regs->e_bit_count_enable);
-       writel(0x0, mfc_regs->e_max_bit_count);
-       writel(0x0, mfc_regs->e_min_bit_count);
-
-       writel(0x0, mfc_regs->e_metadata_buffer_addr);
-       writel(0x0, mfc_regs->e_metadata_buffer_size);
-
-       mfc_debug_leave();
-
-       return 0;
-}
-
-static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs;
-       struct s5p_mfc_enc_params *p = &ctx->enc_params;
-       struct s5p_mfc_h264_enc_params *p_h264 = &p->codec.h264;
-       unsigned int reg = 0;
-       int i;
-
-       mfc_debug_enter();
-
-       s5p_mfc_set_enc_params(ctx);
-
-       /* pictype : number of B */
-       reg = readl(mfc_regs->e_gop_config);
-       reg &= ~(0x3 << 16);
-       reg |= ((p->num_b_frame & 0x3) << 16);
-       writel(reg, mfc_regs->e_gop_config);
-
-       /* profile & level */
-       reg = 0;
-       /** level */
-       reg |= ((p_h264->level & 0xFF) << 8);
-       /** profile - 0 ~ 3 */
-       reg |= p_h264->profile & 0x3F;
-       writel(reg, mfc_regs->e_picture_profile);
-
-       /* rate control config. */
-       reg = readl(mfc_regs->e_rc_config);
-       /** macroblock level rate control */
-       reg &= ~(0x1 << 8);
-       reg |= ((p->rc_mb & 0x1) << 8);
-       writel(reg, mfc_regs->e_rc_config);
-
-       /** frame QP */
-       reg &= ~(0x3F);
-       reg |= p_h264->rc_frame_qp & 0x3F;
-       writel(reg, mfc_regs->e_rc_config);
-
-       /* max & min value of QP */
-       reg = 0;
-       /** max QP */
-       reg |= ((p_h264->rc_max_qp & 0x3F) << 8);
-       /** min QP */
-       reg |= p_h264->rc_min_qp & 0x3F;
-       writel(reg, mfc_regs->e_rc_qp_bound);
-
-       /* other QPs */
-       writel(0x0, mfc_regs->e_fixed_picture_qp);
-       if (!p->rc_frame && !p->rc_mb) {
-               reg = 0;
-               reg |= ((p_h264->rc_b_frame_qp & 0x3F) << 16);
-               reg |= ((p_h264->rc_p_frame_qp & 0x3F) << 8);
-               reg |= p_h264->rc_frame_qp & 0x3F;
-               writel(reg, mfc_regs->e_fixed_picture_qp);
-       }
-
-       /* frame rate */
-       if (p->rc_frame && p->rc_framerate_num && p->rc_framerate_denom) {
-               reg = 0;
-               reg |= ((p->rc_framerate_num & 0xFFFF) << 16);
-               reg |= p->rc_framerate_denom & 0xFFFF;
-               writel(reg, mfc_regs->e_rc_frame_rate);
-       }
-
-       /* vbv buffer size */
-       if (p->frame_skip_mode ==
-                       V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
-               writel(p_h264->cpb_size & 0xFFFF,
-                               mfc_regs->e_vbv_buffer_size);
-
-               if (p->rc_frame)
-                       writel(p->vbv_delay, mfc_regs->e_vbv_init_delay);
-       }
-
-       /* interlace */
-       reg = 0;
-       reg |= ((p_h264->interlace & 0x1) << 3);
-       writel(reg, mfc_regs->e_h264_options);
-
-       /* height */
-       if (p_h264->interlace) {
-               writel(ctx->img_height >> 1,
-                               mfc_regs->e_frame_height); /* 32 align */
-               /* cropped height */
-               writel(ctx->img_height >> 1,
-                               mfc_regs->e_cropped_frame_height);
-       }
-
-       /* loop filter ctrl */
-       reg = readl(mfc_regs->e_h264_options);
-       reg &= ~(0x3 << 1);
-       reg |= ((p_h264->loop_filter_mode & 0x3) << 1);
-       writel(reg, mfc_regs->e_h264_options);
-
-       /* loopfilter alpha offset */
-       if (p_h264->loop_filter_alpha < 0) {
-               reg = 0x10;
-               reg |= (0xFF - p_h264->loop_filter_alpha) + 1;
-       } else {
-               reg = 0x00;
-               reg |= (p_h264->loop_filter_alpha & 0xF);
-       }
-       writel(reg, mfc_regs->e_h264_lf_alpha_offset);
-
-       /* loopfilter beta offset */
-       if (p_h264->loop_filter_beta < 0) {
-               reg = 0x10;
-               reg |= (0xFF - p_h264->loop_filter_beta) + 1;
-       } else {
-               reg = 0x00;
-               reg |= (p_h264->loop_filter_beta & 0xF);
-       }
-       writel(reg, mfc_regs->e_h264_lf_beta_offset);
-
-       /* entropy coding mode */
-       reg = readl(mfc_regs->e_h264_options);
-       reg &= ~(0x1);
-       reg |= p_h264->entropy_mode & 0x1;
-       writel(reg, mfc_regs->e_h264_options);
-
-       /* number of ref. picture */
-       reg = readl(mfc_regs->e_h264_options);
-       reg &= ~(0x1 << 7);
-       reg |= (((p_h264->num_ref_pic_4p - 1) & 0x1) << 7);
-       writel(reg, mfc_regs->e_h264_options);
-
-       /* 8x8 transform enable */
-       reg = readl(mfc_regs->e_h264_options);
-       reg &= ~(0x3 << 12);
-       reg |= ((p_h264->_8x8_transform & 0x3) << 12);
-       writel(reg, mfc_regs->e_h264_options);
-
-       /* macroblock adaptive scaling features */
-       writel(0x0, mfc_regs->e_mb_rc_config);
-       if (p->rc_mb) {
-               reg = 0;
-               /** dark region */
-               reg |= ((p_h264->rc_mb_dark & 0x1) << 3);
-               /** smooth region */
-               reg |= ((p_h264->rc_mb_smooth & 0x1) << 2);
-               /** static region */
-               reg |= ((p_h264->rc_mb_static & 0x1) << 1);
-               /** high activity region */
-               reg |= p_h264->rc_mb_activity & 0x1;
-               writel(reg, mfc_regs->e_mb_rc_config);
-       }
-
-       /* aspect ratio VUI */
-       readl(mfc_regs->e_h264_options);
-       reg &= ~(0x1 << 5);
-       reg |= ((p_h264->vui_sar & 0x1) << 5);
-       writel(reg, mfc_regs->e_h264_options);
-
-       writel(0x0, mfc_regs->e_aspect_ratio);
-       writel(0x0, mfc_regs->e_extended_sar);
-       if (p_h264->vui_sar) {
-               /* aspect ration IDC */
-               reg = 0;
-               reg |= p_h264->vui_sar_idc & 0xFF;
-               writel(reg, mfc_regs->e_aspect_ratio);
-               if (p_h264->vui_sar_idc == 0xFF) {
-                       /* extended SAR */
-                       reg = 0;
-                       reg |= (p_h264->vui_ext_sar_width & 0xFFFF) << 16;
-                       reg |= p_h264->vui_ext_sar_height & 0xFFFF;
-                       writel(reg, mfc_regs->e_extended_sar);
-               }
-       }
-
-       /* intra picture period for H.264 open GOP */
-       /* control */
-       readl(mfc_regs->e_h264_options);
-       reg &= ~(0x1 << 4);
-       reg |= ((p_h264->open_gop & 0x1) << 4);
-       writel(reg, mfc_regs->e_h264_options);
-
-       /* value */
-       writel(0x0, mfc_regs->e_h264_i_period);
-       if (p_h264->open_gop) {
-               reg = 0;
-               reg |= p_h264->open_gop_size & 0xFFFF;
-               writel(reg, mfc_regs->e_h264_i_period);
-       }
-
-       /* 'WEIGHTED_BI_PREDICTION' for B is disable */
-       readl(mfc_regs->e_h264_options);
-       reg &= ~(0x3 << 9);
-       writel(reg, mfc_regs->e_h264_options);
-
-       /* 'CONSTRAINED_INTRA_PRED_ENABLE' is disable */
-       readl(mfc_regs->e_h264_options);
-       reg &= ~(0x1 << 14);
-       writel(reg, mfc_regs->e_h264_options);
-
-       /* ASO */
-       readl(mfc_regs->e_h264_options);
-       reg &= ~(0x1 << 6);
-       reg |= ((p_h264->aso & 0x1) << 6);
-       writel(reg, mfc_regs->e_h264_options);
-
-       /* hier qp enable */
-       readl(mfc_regs->e_h264_options);
-       reg &= ~(0x1 << 8);
-       reg |= ((p_h264->open_gop & 0x1) << 8);
-       writel(reg, mfc_regs->e_h264_options);
-       reg = 0;
-       if (p_h264->hier_qp && p_h264->hier_qp_layer) {
-               reg |= (p_h264->hier_qp_type & 0x1) << 0x3;
-               reg |= p_h264->hier_qp_layer & 0x7;
-               writel(reg, mfc_regs->e_h264_num_t_layer);
-               /* QP value for each layer */
-               for (i = 0; i < p_h264->hier_qp_layer &&
-                               i < ARRAY_SIZE(p_h264->hier_qp_layer_qp); i++) {
-                       writel(p_h264->hier_qp_layer_qp[i],
-                               mfc_regs->e_h264_hierarchical_qp_layer0
-                               + i * 4);
-               }
-       }
-       /* number of coding layer should be zero when hierarchical is disable */
-       writel(reg, mfc_regs->e_h264_num_t_layer);
-
-       /* frame packing SEI generation */
-       readl(mfc_regs->e_h264_options);
-       reg &= ~(0x1 << 25);
-       reg |= ((p_h264->sei_frame_packing & 0x1) << 25);
-       writel(reg, mfc_regs->e_h264_options);
-       if (p_h264->sei_frame_packing) {
-               reg = 0;
-               /** current frame0 flag */
-               reg |= ((p_h264->sei_fp_curr_frame_0 & 0x1) << 2);
-               /** arrangement type */
-               reg |= p_h264->sei_fp_arrangement_type & 0x3;
-               writel(reg, mfc_regs->e_h264_frame_packing_sei_info);
-       }
-
-       if (p_h264->fmo) {
-               switch (p_h264->fmo_map_type) {
-               case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_INTERLEAVED_SLICES:
-                       if (p_h264->fmo_slice_grp > 4)
-                               p_h264->fmo_slice_grp = 4;
-                       for (i = 0; i < (p_h264->fmo_slice_grp & 0xF); i++)
-                               writel(p_h264->fmo_run_len[i] - 1,
-                                       mfc_regs->e_h264_fmo_run_length_minus1_0
-                                       + i * 4);
-                       break;
-               case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_SCATTERED_SLICES:
-                       if (p_h264->fmo_slice_grp > 4)
-                               p_h264->fmo_slice_grp = 4;
-                       break;
-               case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_RASTER_SCAN:
-               case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_WIPE_SCAN:
-                       if (p_h264->fmo_slice_grp > 2)
-                               p_h264->fmo_slice_grp = 2;
-                       writel(p_h264->fmo_chg_dir & 0x1,
-                               mfc_regs->e_h264_fmo_slice_grp_change_dir);
-                       /* the valid range is 0 ~ number of macroblocks -1 */
-                       writel(p_h264->fmo_chg_rate,
-                       mfc_regs->e_h264_fmo_slice_grp_change_rate_minus1);
-                       break;
-               default:
-                       mfc_err("Unsupported map type for FMO: %d\n",
-                                       p_h264->fmo_map_type);
-                       p_h264->fmo_map_type = 0;
-                       p_h264->fmo_slice_grp = 1;
-                       break;
-               }
-
-               writel(p_h264->fmo_map_type,
-                               mfc_regs->e_h264_fmo_slice_grp_map_type);
-               writel(p_h264->fmo_slice_grp - 1,
-                               mfc_regs->e_h264_fmo_num_slice_grp_minus1);
-       } else {
-               writel(0, mfc_regs->e_h264_fmo_num_slice_grp_minus1);
-       }
-
-       mfc_debug_leave();
-
-       return 0;
-}
-
-static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs;
-       struct s5p_mfc_enc_params *p = &ctx->enc_params;
-       struct s5p_mfc_mpeg4_enc_params *p_mpeg4 = &p->codec.mpeg4;
-       unsigned int reg = 0;
-
-       mfc_debug_enter();
-
-       s5p_mfc_set_enc_params(ctx);
-
-       /* pictype : number of B */
-       reg = readl(mfc_regs->e_gop_config);
-       reg &= ~(0x3 << 16);
-       reg |= ((p->num_b_frame & 0x3) << 16);
-       writel(reg, mfc_regs->e_gop_config);
-
-       /* profile & level */
-       reg = 0;
-       /** level */
-       reg |= ((p_mpeg4->level & 0xFF) << 8);
-       /** profile - 0 ~ 1 */
-       reg |= p_mpeg4->profile & 0x3F;
-       writel(reg, mfc_regs->e_picture_profile);
-
-       /* rate control config. */
-       reg = readl(mfc_regs->e_rc_config);
-       /** macroblock level rate control */
-       reg &= ~(0x1 << 8);
-       reg |= ((p->rc_mb & 0x1) << 8);
-       writel(reg, mfc_regs->e_rc_config);
-
-       /** frame QP */
-       reg &= ~(0x3F);
-       reg |= p_mpeg4->rc_frame_qp & 0x3F;
-       writel(reg, mfc_regs->e_rc_config);
-
-       /* max & min value of QP */
-       reg = 0;
-       /** max QP */
-       reg |= ((p_mpeg4->rc_max_qp & 0x3F) << 8);
-       /** min QP */
-       reg |= p_mpeg4->rc_min_qp & 0x3F;
-       writel(reg, mfc_regs->e_rc_qp_bound);
-
-       /* other QPs */
-       writel(0x0, mfc_regs->e_fixed_picture_qp);
-       if (!p->rc_frame && !p->rc_mb) {
-               reg = 0;
-               reg |= ((p_mpeg4->rc_b_frame_qp & 0x3F) << 16);
-               reg |= ((p_mpeg4->rc_p_frame_qp & 0x3F) << 8);
-               reg |= p_mpeg4->rc_frame_qp & 0x3F;
-               writel(reg, mfc_regs->e_fixed_picture_qp);
-       }
-
-       /* frame rate */
-       if (p->rc_frame && p->rc_framerate_num && p->rc_framerate_denom) {
-               reg = 0;
-               reg |= ((p->rc_framerate_num & 0xFFFF) << 16);
-               reg |= p->rc_framerate_denom & 0xFFFF;
-               writel(reg, mfc_regs->e_rc_frame_rate);
-       }
-
-       /* vbv buffer size */
-       if (p->frame_skip_mode ==
-                       V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
-               writel(p->vbv_size & 0xFFFF, mfc_regs->e_vbv_buffer_size);
-
-               if (p->rc_frame)
-                       writel(p->vbv_delay, mfc_regs->e_vbv_init_delay);
-       }
-
-       /* Disable HEC */
-       writel(0x0, mfc_regs->e_mpeg4_options);
-       writel(0x0, mfc_regs->e_mpeg4_hec_period);
-
-       mfc_debug_leave();
-
-       return 0;
-}
-
-static int s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs;
-       struct s5p_mfc_enc_params *p = &ctx->enc_params;
-       struct s5p_mfc_mpeg4_enc_params *p_h263 = &p->codec.mpeg4;
-       unsigned int reg = 0;
-
-       mfc_debug_enter();
-
-       s5p_mfc_set_enc_params(ctx);
-
-       /* profile & level */
-       reg = 0;
-       /** profile */
-       reg |= (0x1 << 4);
-       writel(reg, mfc_regs->e_picture_profile);
-
-       /* rate control config. */
-       reg = readl(mfc_regs->e_rc_config);
-       /** macroblock level rate control */
-       reg &= ~(0x1 << 8);
-       reg |= ((p->rc_mb & 0x1) << 8);
-       writel(reg, mfc_regs->e_rc_config);
-
-       /** frame QP */
-       reg &= ~(0x3F);
-       reg |= p_h263->rc_frame_qp & 0x3F;
-       writel(reg, mfc_regs->e_rc_config);
-
-       /* max & min value of QP */
-       reg = 0;
-       /** max QP */
-       reg |= ((p_h263->rc_max_qp & 0x3F) << 8);
-       /** min QP */
-       reg |= p_h263->rc_min_qp & 0x3F;
-       writel(reg, mfc_regs->e_rc_qp_bound);
-
-       /* other QPs */
-       writel(0x0, mfc_regs->e_fixed_picture_qp);
-       if (!p->rc_frame && !p->rc_mb) {
-               reg = 0;
-               reg |= ((p_h263->rc_b_frame_qp & 0x3F) << 16);
-               reg |= ((p_h263->rc_p_frame_qp & 0x3F) << 8);
-               reg |= p_h263->rc_frame_qp & 0x3F;
-               writel(reg, mfc_regs->e_fixed_picture_qp);
-       }
-
-       /* frame rate */
-       if (p->rc_frame && p->rc_framerate_num && p->rc_framerate_denom) {
-               reg = 0;
-               reg |= ((p->rc_framerate_num & 0xFFFF) << 16);
-               reg |= p->rc_framerate_denom & 0xFFFF;
-               writel(reg, mfc_regs->e_rc_frame_rate);
-       }
-
-       /* vbv buffer size */
-       if (p->frame_skip_mode ==
-                       V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
-               writel(p->vbv_size & 0xFFFF, mfc_regs->e_vbv_buffer_size);
-
-               if (p->rc_frame)
-                       writel(p->vbv_delay, mfc_regs->e_vbv_init_delay);
-       }
-
-       mfc_debug_leave();
-
-       return 0;
-}
-
-static int s5p_mfc_set_enc_params_vp8(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs;
-       struct s5p_mfc_enc_params *p = &ctx->enc_params;
-       struct s5p_mfc_vp8_enc_params *p_vp8 = &p->codec.vp8;
-       unsigned int reg = 0;
-       unsigned int val = 0;
-
-       mfc_debug_enter();
-
-       s5p_mfc_set_enc_params(ctx);
-
-       /* pictype : number of B */
-       reg = readl(mfc_regs->e_gop_config);
-       reg &= ~(0x3 << 16);
-       reg |= ((p->num_b_frame & 0x3) << 16);
-       writel(reg, mfc_regs->e_gop_config);
-
-       /* profile - 0 ~ 3 */
-       reg = p_vp8->profile & 0x3;
-       writel(reg, mfc_regs->e_picture_profile);
-
-       /* rate control config. */
-       reg = readl(mfc_regs->e_rc_config);
-       /** macroblock level rate control */
-       reg &= ~(0x1 << 8);
-       reg |= ((p->rc_mb & 0x1) << 8);
-       writel(reg, mfc_regs->e_rc_config);
-
-       /* frame rate */
-       if (p->rc_frame && p->rc_framerate_num && p->rc_framerate_denom) {
-               reg = 0;
-               reg |= ((p->rc_framerate_num & 0xFFFF) << 16);
-               reg |= p->rc_framerate_denom & 0xFFFF;
-               writel(reg, mfc_regs->e_rc_frame_rate);
-       }
-
-       /* frame QP */
-       reg &= ~(0x7F);
-       reg |= p_vp8->rc_frame_qp & 0x7F;
-       writel(reg, mfc_regs->e_rc_config);
-
-       /* other QPs */
-       writel(0x0, mfc_regs->e_fixed_picture_qp);
-       if (!p->rc_frame && !p->rc_mb) {
-               reg = 0;
-               reg |= ((p_vp8->rc_p_frame_qp & 0x7F) << 8);
-               reg |= p_vp8->rc_frame_qp & 0x7F;
-               writel(reg, mfc_regs->e_fixed_picture_qp);
-       }
-
-       /* max QP */
-       reg = ((p_vp8->rc_max_qp & 0x7F) << 8);
-       /* min QP */
-       reg |= p_vp8->rc_min_qp & 0x7F;
-       writel(reg, mfc_regs->e_rc_qp_bound);
-
-       /* vbv buffer size */
-       if (p->frame_skip_mode ==
-                       V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
-               writel(p->vbv_size & 0xFFFF, mfc_regs->e_vbv_buffer_size);
-
-               if (p->rc_frame)
-                       writel(p->vbv_delay, mfc_regs->e_vbv_init_delay);
-       }
-
-       /* VP8 specific params */
-       reg = 0;
-       reg |= (p_vp8->imd_4x4 & 0x1) << 10;
-       switch (p_vp8->num_partitions) {
-       case V4L2_CID_MPEG_VIDEO_VPX_1_PARTITION:
-               val = 0;
-               break;
-       case V4L2_CID_MPEG_VIDEO_VPX_2_PARTITIONS:
-               val = 2;
-               break;
-       case V4L2_CID_MPEG_VIDEO_VPX_4_PARTITIONS:
-               val = 4;
-               break;
-       case V4L2_CID_MPEG_VIDEO_VPX_8_PARTITIONS:
-               val = 8;
-               break;
-       }
-       reg |= (val & 0xF) << 3;
-       reg |= (p_vp8->num_ref & 0x2);
-       writel(reg, mfc_regs->e_vp8_options);
-
-       mfc_debug_leave();
-
-       return 0;
-}
-
-static int s5p_mfc_set_enc_params_hevc(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs;
-       struct s5p_mfc_enc_params *p = &ctx->enc_params;
-       struct s5p_mfc_hevc_enc_params *p_hevc = &p->codec.hevc;
-       unsigned int reg = 0;
-       int i;
-
-       mfc_debug_enter();
-
-       s5p_mfc_set_enc_params(ctx);
-
-       /* pictype : number of B */
-       reg = readl(mfc_regs->e_gop_config);
-       /* num_b_frame - 0 ~ 2 */
-       reg &= ~(0x3 << 16);
-       reg |= (p->num_b_frame << 16);
-       writel(reg, mfc_regs->e_gop_config);
-
-       /* UHD encoding case */
-       if ((ctx->img_width == 3840) && (ctx->img_height == 2160)) {
-               p_hevc->level = 51;
-               p_hevc->tier = 0;
-       /* this tier can be changed */
-       }
-
-       /* tier & level */
-       reg = 0;
-       /* profile */
-       reg |= p_hevc->profile & 0x3;
-       /* level */
-       reg &= ~(0xFF << 8);
-       reg |= (p_hevc->level << 8);
-       /* tier - 0 ~ 1 */
-       reg |= (p_hevc->tier << 16);
-       writel(reg, mfc_regs->e_picture_profile);
-
-       switch (p_hevc->loopfilter) {
-       case V4L2_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE_DISABLED:
-               p_hevc->loopfilter_disable = 1;
-               break;
-       case V4L2_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE_ENABLED:
-               p_hevc->loopfilter_disable = 0;
-               p_hevc->loopfilter_across = 1;
-               break;
-       case V4L2_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY:
-               p_hevc->loopfilter_disable = 0;
-               p_hevc->loopfilter_across = 0;
-               break;
-       }
-
-       /* max partition depth */
-       reg = 0;
-       reg |= (p_hevc->max_partition_depth & 0x1);
-       reg |= (p_hevc->num_refs_for_p-1) << 2;
-       reg |= (p_hevc->refreshtype & 0x3) << 3;
-       reg |= (p_hevc->const_intra_period_enable & 0x1) << 5;
-       reg |= (p_hevc->lossless_cu_enable & 0x1) << 6;
-       reg |= (p_hevc->wavefront_enable & 0x1) << 7;
-       reg |= (p_hevc->loopfilter_disable & 0x1) << 8;
-       reg |= (p_hevc->loopfilter_across & 0x1) << 9;
-       reg |= (p_hevc->enable_ltr & 0x1) << 10;
-       reg |= (p_hevc->hier_qp_enable & 0x1) << 11;
-       reg |= (p_hevc->general_pb_enable & 0x1) << 13;
-       reg |= (p_hevc->temporal_id_enable & 0x1) << 14;
-       reg |= (p_hevc->strong_intra_smooth & 0x1) << 15;
-       reg |= (p_hevc->intra_pu_split_disable & 0x1) << 16;
-       reg |= (p_hevc->tmv_prediction_disable & 0x1) << 17;
-       reg |= (p_hevc->max_num_merge_mv & 0x7) << 18;
-       reg |= (p_hevc->encoding_nostartcode_enable & 0x1) << 23;
-       reg |= (p_hevc->prepend_sps_pps_to_idr << 26);
-
-       writel(reg, mfc_regs->e_hevc_options);
-       /* refresh period */
-       if (p_hevc->refreshtype) {
-               reg = 0;
-               reg |= (p_hevc->refreshperiod & 0xFFFF);
-               writel(reg, mfc_regs->e_hevc_refresh_period);
-       }
-       /* loop filter setting */
-       if (!(p_hevc->loopfilter_disable & 0x1)) {
-               reg = 0;
-               reg |= (p_hevc->lf_beta_offset_div2);
-               writel(reg, mfc_regs->e_hevc_lf_beta_offset_div2);
-               reg = 0;
-               reg |= (p_hevc->lf_tc_offset_div2);
-               writel(reg, mfc_regs->e_hevc_lf_tc_offset_div2);
-       }
-       /* hier qp enable */
-       if (p_hevc->num_hier_layer) {
-               reg = 0;
-               reg |= (p_hevc->hier_qp_type & 0x1) << 0x3;
-               reg |= p_hevc->num_hier_layer & 0x7;
-               writel(reg, mfc_regs->e_num_t_layer);
-               /* QP value for each layer */
-               if (p_hevc->hier_qp_enable) {
-                       for (i = 0; i < 7; i++)
-                               writel(p_hevc->hier_qp_layer[i],
-                                       mfc_regs->e_hier_qp_layer0 + i * 4);
-               }
-               if (p->rc_frame) {
-                       for (i = 0; i < 7; i++)
-                               writel(p_hevc->hier_bit_layer[i],
-                                               mfc_regs->e_hier_bit_rate_layer0
-                                               + i * 4);
-               }
-       }
-
-       /* rate control config. */
-       reg = readl(mfc_regs->e_rc_config);
-       /* macroblock level rate control */
-       reg &= ~(0x1 << 8);
-       reg |= (p->rc_mb << 8);
-       writel(reg, mfc_regs->e_rc_config);
-       /* frame QP */
-       reg &= ~(0xFF);
-       reg |= p_hevc->rc_frame_qp;
-       writel(reg, mfc_regs->e_rc_config);
-
-       /* frame rate */
-       if (p->rc_frame) {
-               reg = 0;
-               reg &= ~(0xFFFF << 16);
-               reg |= ((p_hevc->rc_framerate) << 16);
-               reg &= ~(0xFFFF);
-               reg |= FRAME_DELTA_DEFAULT;
-               writel(reg, mfc_regs->e_rc_frame_rate);
-       }
-
-       /* max & min value of QP */
-       reg = 0;
-       /* max QP */
-       reg &= ~(0xFF << 8);
-       reg |= (p_hevc->rc_max_qp << 8);
-       /* min QP */
-       reg &= ~(0xFF);
-       reg |= p_hevc->rc_min_qp;
-       writel(reg, mfc_regs->e_rc_qp_bound);
-
-       writel(0x0, mfc_regs->e_fixed_picture_qp);
-       if (!p->rc_frame && !p->rc_mb) {
-               reg = 0;
-               reg &= ~(0xFF << 16);
-               reg |= (p_hevc->rc_b_frame_qp << 16);
-               reg &= ~(0xFF << 8);
-               reg |= (p_hevc->rc_p_frame_qp << 8);
-               reg &= ~(0xFF);
-               reg |= p_hevc->rc_frame_qp;
-               writel(reg, mfc_regs->e_fixed_picture_qp);
-       }
-       mfc_debug_leave();
-
-       return 0;
-}
-
-/* Initialize decoding */
-static int s5p_mfc_init_decode_v6(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs;
-       unsigned int reg = 0;
-       int fmo_aso_ctrl = 0;
-
-       mfc_debug_enter();
-       mfc_debug(2, "InstNo: %d/%d\n", ctx->inst_no,
-                       S5P_FIMV_CH_SEQ_HEADER_V6);
-       mfc_debug(2, "BUFs: %08x %08x %08x\n",
-                 readl(mfc_regs->d_cpb_buffer_addr),
-                 readl(mfc_regs->d_cpb_buffer_addr),
-                 readl(mfc_regs->d_cpb_buffer_addr));
-
-       /* FMO_ASO_CTRL - 0: Enable, 1: Disable */
-       reg |= (fmo_aso_ctrl << S5P_FIMV_D_OPT_FMO_ASO_CTRL_MASK_V6);
-
-       if (ctx->display_delay_enable) {
-               reg |= (0x1 << S5P_FIMV_D_OPT_DDELAY_EN_SHIFT_V6);
-               writel(ctx->display_delay, mfc_regs->d_display_delay);
-       }
-
-       if (IS_MFCV7_PLUS(dev) || IS_MFCV6_V2(dev)) {
-               writel(reg, mfc_regs->d_dec_options);
-               reg = 0;
-       }
-
-       /* Setup loop filter, for decoding this is only valid for MPEG4 */
-       if (ctx->codec_mode == S5P_MFC_CODEC_MPEG4_DEC) {
-               mfc_debug(2, "Set loop filter to: %d\n",
-                               ctx->loop_filter_mpeg4);
-               reg |= (ctx->loop_filter_mpeg4 <<
-                               S5P_FIMV_D_OPT_LF_CTRL_SHIFT_V6);
-       }
-       if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16)
-               reg |= (0x1 << S5P_FIMV_D_OPT_TILE_MODE_SHIFT_V6);
-
-       if (IS_MFCV7_PLUS(dev) || IS_MFCV6_V2(dev))
-               writel(reg, mfc_regs->d_init_buffer_options);
-       else
-               writel(reg, mfc_regs->d_dec_options);
-
-       /* 0: NV12(CbCr), 1: NV21(CrCb) */
-       if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_NV21M)
-               writel(0x1, mfc_regs->pixel_format);
-       else
-               writel(0x0, mfc_regs->pixel_format);
-
-
-       /* sei parse */
-       writel(ctx->sei_fp_parse & 0x1, mfc_regs->d_sei_enable);
-
-       writel(ctx->inst_no, mfc_regs->instance_id);
-       s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev,
-                       S5P_FIMV_CH_SEQ_HEADER_V6, NULL);
-
-       mfc_debug_leave();
-       return 0;
-}
-
-static inline void s5p_mfc_set_flush(struct s5p_mfc_ctx *ctx, int flush)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs;
-
-       if (flush) {
-               dev->curr_ctx = ctx->num;
-               writel(ctx->inst_no, mfc_regs->instance_id);
-               s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev,
-                               S5P_FIMV_H2R_CMD_FLUSH_V6, NULL);
-       }
-}
-
-/* Decode a single frame */
-static int s5p_mfc_decode_one_frame_v6(struct s5p_mfc_ctx *ctx,
-                       enum s5p_mfc_decode_arg last_frame)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs;
-
-       writel(ctx->dec_dst_flag, mfc_regs->d_available_dpb_flag_lower);
-       writel(ctx->slice_interface & 0x1, mfc_regs->d_slice_if_enable);
-
-       writel(ctx->inst_no, mfc_regs->instance_id);
-       /* Issue different commands to instance basing on whether it
-        * is the last frame or not. */
-       switch (last_frame) {
-       case 0:
-               s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev,
-                               S5P_FIMV_CH_FRAME_START_V6, NULL);
-               break;
-       case 1:
-               s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev,
-                               S5P_FIMV_CH_LAST_FRAME_V6, NULL);
-               break;
-       default:
-               mfc_err("Unsupported last frame arg.\n");
-               return -EINVAL;
-       }
-
-       mfc_debug(2, "Decoding a usual frame.\n");
-       return 0;
-}
-
-static int s5p_mfc_init_encode_v6(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs;
-
-       if (ctx->codec_mode == S5P_MFC_CODEC_H264_ENC)
-               s5p_mfc_set_enc_params_h264(ctx);
-       else if (ctx->codec_mode == S5P_MFC_CODEC_MPEG4_ENC)
-               s5p_mfc_set_enc_params_mpeg4(ctx);
-       else if (ctx->codec_mode == S5P_MFC_CODEC_H263_ENC)
-               s5p_mfc_set_enc_params_h263(ctx);
-       else if (ctx->codec_mode == S5P_MFC_CODEC_VP8_ENC)
-               s5p_mfc_set_enc_params_vp8(ctx);
-       else if (ctx->codec_mode == S5P_FIMV_CODEC_HEVC_ENC)
-               s5p_mfc_set_enc_params_hevc(ctx);
-       else {
-               mfc_err("Unknown codec for encoding (%x).\n",
-                       ctx->codec_mode);
-               return -EINVAL;
-       }
-
-       /* Set stride lengths for v7 & above */
-       if (IS_MFCV7_PLUS(dev)) {
-               writel(ctx->img_width, mfc_regs->e_source_first_plane_stride);
-               writel(ctx->img_width, mfc_regs->e_source_second_plane_stride);
-       }
-
-       writel(ctx->inst_no, mfc_regs->instance_id);
-       s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev,
-                       S5P_FIMV_CH_SEQ_HEADER_V6, NULL);
-
-       return 0;
-}
-
-static int s5p_mfc_h264_set_aso_slice_order_v6(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs;
-       struct s5p_mfc_enc_params *p = &ctx->enc_params;
-       struct s5p_mfc_h264_enc_params *p_h264 = &p->codec.h264;
-       int i;
-
-       if (p_h264->aso) {
-               for (i = 0; i < ARRAY_SIZE(p_h264->aso_slice_order); i++) {
-                       writel(p_h264->aso_slice_order[i],
-                               mfc_regs->e_h264_aso_slice_order_0 + i * 4);
-               }
-       }
-       return 0;
-}
-
-/* Encode a single frame */
-static int s5p_mfc_encode_one_frame_v6(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs;
-       int cmd;
-
-       mfc_debug(2, "++\n");
-
-       /* memory structure cur. frame */
-
-       if (ctx->codec_mode == S5P_MFC_CODEC_H264_ENC)
-               s5p_mfc_h264_set_aso_slice_order_v6(ctx);
-
-       s5p_mfc_set_slice_mode(ctx);
-
-       if (ctx->state != MFCINST_FINISHING)
-               cmd = S5P_FIMV_CH_FRAME_START_V6;
-       else
-               cmd = S5P_FIMV_CH_LAST_FRAME_V6;
-
-       writel(ctx->inst_no, mfc_regs->instance_id);
-       s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev, cmd, NULL);
-
-       mfc_debug(2, "--\n");
-
-       return 0;
-}
-
-static inline void s5p_mfc_run_dec_last_frames(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       s5p_mfc_set_dec_stream_buffer_v6(ctx, 0, 0, 0);
-       dev->curr_ctx = ctx->num;
-       s5p_mfc_decode_one_frame_v6(ctx, MFC_DEC_LAST_FRAME);
-}
-
-static inline int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_buf *temp_vb;
-       int last_frame = 0;
-
-       if (ctx->state == MFCINST_FINISHING) {
-               last_frame = MFC_DEC_LAST_FRAME;
-               s5p_mfc_set_dec_stream_buffer_v6(ctx, 0, 0, 0);
-               dev->curr_ctx = ctx->num;
-               s5p_mfc_clean_ctx_int_flags(ctx);
-               s5p_mfc_decode_one_frame_v6(ctx, last_frame);
-               return 0;
-       }
-
-       /* Frames are being decoded */
-       if (list_empty(&ctx->src_queue)) {
-               mfc_debug(2, "No src buffers.\n");
-               return -EAGAIN;
-       }
-       /* Get the next source buffer */
-       temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
-       temp_vb->flags |= MFC_BUF_FLAG_USED;
-       s5p_mfc_set_dec_stream_buffer_v6(ctx,
-               vb2_dma_contig_plane_dma_addr(&temp_vb->b->vb2_buf, 0),
-                       ctx->consumed_stream,
-                       temp_vb->b->vb2_buf.planes[0].bytesused);
-
-       dev->curr_ctx = ctx->num;
-       if (temp_vb->b->vb2_buf.planes[0].bytesused == 0) {
-               last_frame = 1;
-               mfc_debug(2, "Setting ctx->state to FINISHING\n");
-               ctx->state = MFCINST_FINISHING;
-       }
-       s5p_mfc_decode_one_frame_v6(ctx, last_frame);
-
-       return 0;
-}
-
-static inline int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_buf *dst_mb;
-       struct s5p_mfc_buf *src_mb;
-       unsigned long src_y_addr, src_c_addr, dst_addr;
-       /*
-       unsigned int src_y_size, src_c_size;
-       */
-       unsigned int dst_size;
-
-       if (list_empty(&ctx->src_queue) && ctx->state != MFCINST_FINISHING) {
-               mfc_debug(2, "no src buffers.\n");
-               return -EAGAIN;
-       }
-
-       if (list_empty(&ctx->dst_queue)) {
-               mfc_debug(2, "no dst buffers.\n");
-               return -EAGAIN;
-       }
-
-       if (list_empty(&ctx->src_queue)) {
-               /* send null frame */
-               s5p_mfc_set_enc_frame_buffer_v6(ctx, 0, 0);
-               src_mb = NULL;
-       } else {
-               src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
-               src_mb->flags |= MFC_BUF_FLAG_USED;
-               if (src_mb->b->vb2_buf.planes[0].bytesused == 0) {
-                       s5p_mfc_set_enc_frame_buffer_v6(ctx, 0, 0);
-                       ctx->state = MFCINST_FINISHING;
-               } else {
-                       src_y_addr = vb2_dma_contig_plane_dma_addr(&src_mb->b->vb2_buf, 0);
-                       src_c_addr = vb2_dma_contig_plane_dma_addr(&src_mb->b->vb2_buf, 1);
-
-                       mfc_debug(2, "enc src y addr: 0x%08lx\n", src_y_addr);
-                       mfc_debug(2, "enc src c addr: 0x%08lx\n", src_c_addr);
-
-                       s5p_mfc_set_enc_frame_buffer_v6(ctx, src_y_addr, src_c_addr);
-                       if (src_mb->flags & MFC_BUF_FLAG_EOS)
-                               ctx->state = MFCINST_FINISHING;
-               }
-       }
-
-       dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
-       dst_mb->flags |= MFC_BUF_FLAG_USED;
-       dst_addr = vb2_dma_contig_plane_dma_addr(&dst_mb->b->vb2_buf, 0);
-       dst_size = vb2_plane_size(&dst_mb->b->vb2_buf, 0);
-
-       s5p_mfc_set_enc_stream_buffer_v6(ctx, dst_addr, dst_size);
-
-       dev->curr_ctx = ctx->num;
-       s5p_mfc_encode_one_frame_v6(ctx);
-
-       return 0;
-}
-
-static inline void s5p_mfc_run_init_dec(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_buf *temp_vb;
-
-       /* Initializing decoding - parsing header */
-       mfc_debug(2, "Preparing to init decoding.\n");
-       temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
-       mfc_debug(2, "Header size: %d\n", temp_vb->b->vb2_buf.planes[0].bytesused);
-       s5p_mfc_set_dec_stream_buffer_v6(ctx,
-               vb2_dma_contig_plane_dma_addr(&temp_vb->b->vb2_buf, 0), 0,
-                       temp_vb->b->vb2_buf.planes[0].bytesused);
-       dev->curr_ctx = ctx->num;
-       s5p_mfc_init_decode_v6(ctx);
-}
-
-static inline void s5p_mfc_run_init_enc(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_buf *dst_mb;
-       unsigned long dst_addr;
-       unsigned int dst_size;
-
-       dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
-       dst_addr = vb2_dma_contig_plane_dma_addr(&dst_mb->b->vb2_buf, 0);
-       dst_size = vb2_plane_size(&dst_mb->b->vb2_buf, 0);
-       s5p_mfc_set_enc_stream_buffer_v6(ctx, dst_addr, dst_size);
-       dev->curr_ctx = ctx->num;
-       s5p_mfc_init_encode_v6(ctx);
-}
-
-static inline int s5p_mfc_run_init_dec_buffers(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       int ret;
-       /* Header was parsed now start processing
-        * First set the output frame buffers
-        * s5p_mfc_alloc_dec_buffers(ctx); */
-
-       if (ctx->capture_state != QUEUE_BUFS_MMAPED) {
-               mfc_err("It seems that not all destination buffers were\n"
-                       "mmapped.MFC requires that all destination are mmapped\n"
-                       "before starting processing.\n");
-               return -EAGAIN;
-       }
-
-       dev->curr_ctx = ctx->num;
-       ret = s5p_mfc_set_dec_frame_buffer_v6(ctx);
-       if (ret) {
-               mfc_err("Failed to alloc frame mem.\n");
-               ctx->state = MFCINST_ERROR;
-       }
-       return ret;
-}
-
-static inline int s5p_mfc_run_init_enc_buffers(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       int ret;
-
-       dev->curr_ctx = ctx->num;
-       ret = s5p_mfc_set_enc_ref_buffer_v6(ctx);
-       if (ret) {
-               mfc_err("Failed to alloc frame mem.\n");
-               ctx->state = MFCINST_ERROR;
-       }
-       return ret;
-}
-
-/* Try running an operation on hardware */
-static void s5p_mfc_try_run_v6(struct s5p_mfc_dev *dev)
-{
-       struct s5p_mfc_ctx *ctx;
-       int new_ctx;
-       unsigned int ret = 0;
-
-       mfc_debug(1, "Try run dev: %p\n", dev);
-
-       /* Check whether hardware is not running */
-       if (test_and_set_bit(0, &dev->hw_lock) != 0) {
-               /* This is perfectly ok, the scheduled ctx should wait */
-               mfc_debug(1, "Couldn't lock HW.\n");
-               return;
-       }
-
-       /* Choose the context to run */
-       new_ctx = s5p_mfc_get_new_ctx(dev);
-       if (new_ctx < 0) {
-               /* No contexts to run */
-               if (test_and_clear_bit(0, &dev->hw_lock) == 0) {
-                       mfc_err("Failed to unlock hardware.\n");
-                       return;
-               }
-
-               mfc_debug(1, "No ctx is scheduled to be run.\n");
-               return;
-       }
-
-       mfc_debug(1, "New context: %d\n", new_ctx);
-       ctx = dev->ctx[new_ctx];
-       mfc_debug(1, "Setting new context to %p\n", ctx);
-       /* Got context to run in ctx */
-       mfc_debug(1, "ctx->dst_queue_cnt=%d ctx->dpb_count=%d ctx->src_queue_cnt=%d\n",
-               ctx->dst_queue_cnt, ctx->pb_count, ctx->src_queue_cnt);
-       mfc_debug(1, "ctx->state=%d\n", ctx->state);
-       /* Last frame has already been sent to MFC
-        * Now obtaining frames from MFC buffer */
-
-       s5p_mfc_clock_on();
-       s5p_mfc_clean_ctx_int_flags(ctx);
-
-       if (ctx->type == MFCINST_DECODER) {
-               switch (ctx->state) {
-               case MFCINST_FINISHING:
-                       s5p_mfc_run_dec_last_frames(ctx);
-                       break;
-               case MFCINST_RUNNING:
-                       ret = s5p_mfc_run_dec_frame(ctx);
-                       break;
-               case MFCINST_INIT:
-                       ret = s5p_mfc_hw_call(dev->mfc_cmds, open_inst_cmd,
-                                       ctx);
-                       break;
-               case MFCINST_RETURN_INST:
-                       ret = s5p_mfc_hw_call(dev->mfc_cmds, close_inst_cmd,
-                                       ctx);
-                       break;
-               case MFCINST_GOT_INST:
-                       s5p_mfc_run_init_dec(ctx);
-                       break;
-               case MFCINST_HEAD_PARSED:
-                       ret = s5p_mfc_run_init_dec_buffers(ctx);
-                       break;
-               case MFCINST_FLUSH:
-                       s5p_mfc_set_flush(ctx, ctx->dpb_flush_flag);
-                       break;
-               case MFCINST_RES_CHANGE_INIT:
-                       s5p_mfc_run_dec_last_frames(ctx);
-                       break;
-               case MFCINST_RES_CHANGE_FLUSH:
-                       s5p_mfc_run_dec_last_frames(ctx);
-                       break;
-               case MFCINST_RES_CHANGE_END:
-                       mfc_debug(2, "Finished remaining frames after resolution change.\n");
-                       ctx->capture_state = QUEUE_FREE;
-                       mfc_debug(2, "Will re-init the codec`.\n");
-                       s5p_mfc_run_init_dec(ctx);
-                       break;
-               default:
-                       ret = -EAGAIN;
-               }
-       } else if (ctx->type == MFCINST_ENCODER) {
-               switch (ctx->state) {
-               case MFCINST_FINISHING:
-               case MFCINST_RUNNING:
-                       ret = s5p_mfc_run_enc_frame(ctx);
-                       break;
-               case MFCINST_INIT:
-                       ret = s5p_mfc_hw_call(dev->mfc_cmds, open_inst_cmd,
-                                       ctx);
-                       break;
-               case MFCINST_RETURN_INST:
-                       ret = s5p_mfc_hw_call(dev->mfc_cmds, close_inst_cmd,
-                                       ctx);
-                       break;
-               case MFCINST_GOT_INST:
-                       s5p_mfc_run_init_enc(ctx);
-                       break;
-               case MFCINST_HEAD_PRODUCED:
-                       ret = s5p_mfc_run_init_enc_buffers(ctx);
-                       break;
-               default:
-                       ret = -EAGAIN;
-               }
-       } else {
-               mfc_err("invalid context type: %d\n", ctx->type);
-               ret = -EAGAIN;
-       }
-
-       if (ret) {
-               /* Free hardware lock */
-               if (test_and_clear_bit(0, &dev->hw_lock) == 0)
-                       mfc_err("Failed to unlock hardware.\n");
-
-               /* This is in deed imporant, as no operation has been
-                * scheduled, reduce the clock count as no one will
-                * ever do this, because no interrupt related to this try_run
-                * will ever come from hardware. */
-               s5p_mfc_clock_off();
-       }
-}
-
-static void s5p_mfc_clear_int_flags_v6(struct s5p_mfc_dev *dev)
-{
-       const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs;
-       writel(0, mfc_regs->risc2host_command);
-       writel(0, mfc_regs->risc2host_int);
-}
-
-static unsigned int
-s5p_mfc_read_info_v6(struct s5p_mfc_ctx *ctx, unsigned long ofs)
-{
-       int ret;
-
-       s5p_mfc_clock_on();
-       ret = readl((void __iomem *)ofs);
-       s5p_mfc_clock_off();
-
-       return ret;
-}
-
-static int s5p_mfc_get_dspl_y_adr_v6(struct s5p_mfc_dev *dev)
-{
-       return readl(dev->mfc_regs->d_display_first_plane_addr);
-}
-
-static int s5p_mfc_get_dec_y_adr_v6(struct s5p_mfc_dev *dev)
-{
-       return readl(dev->mfc_regs->d_decoded_first_plane_addr);
-}
-
-static int s5p_mfc_get_dspl_status_v6(struct s5p_mfc_dev *dev)
-{
-       return readl(dev->mfc_regs->d_display_status);
-}
-
-static int s5p_mfc_get_dec_status_v6(struct s5p_mfc_dev *dev)
-{
-       return readl(dev->mfc_regs->d_decoded_status);
-}
-
-static int s5p_mfc_get_dec_frame_type_v6(struct s5p_mfc_dev *dev)
-{
-       return readl(dev->mfc_regs->d_decoded_frame_type) &
-               S5P_FIMV_DECODE_FRAME_MASK_V6;
-}
-
-static int s5p_mfc_get_disp_frame_type_v6(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       return readl(dev->mfc_regs->d_display_frame_type) &
-               S5P_FIMV_DECODE_FRAME_MASK_V6;
-}
-
-static int s5p_mfc_get_consumed_stream_v6(struct s5p_mfc_dev *dev)
-{
-       return readl(dev->mfc_regs->d_decoded_nal_size);
-}
-
-static int s5p_mfc_get_int_reason_v6(struct s5p_mfc_dev *dev)
-{
-       return readl(dev->mfc_regs->risc2host_command) &
-               S5P_FIMV_RISC2HOST_CMD_MASK;
-}
-
-static int s5p_mfc_get_int_err_v6(struct s5p_mfc_dev *dev)
-{
-       return readl(dev->mfc_regs->error_code);
-}
-
-static int s5p_mfc_err_dec_v6(unsigned int err)
-{
-       return (err & S5P_FIMV_ERR_DEC_MASK_V6) >> S5P_FIMV_ERR_DEC_SHIFT_V6;
-}
-
-static int s5p_mfc_get_img_width_v6(struct s5p_mfc_dev *dev)
-{
-       return readl(dev->mfc_regs->d_display_frame_width);
-}
-
-static int s5p_mfc_get_img_height_v6(struct s5p_mfc_dev *dev)
-{
-       return readl(dev->mfc_regs->d_display_frame_height);
-}
-
-static int s5p_mfc_get_dpb_count_v6(struct s5p_mfc_dev *dev)
-{
-       return readl(dev->mfc_regs->d_min_num_dpb);
-}
-
-static int s5p_mfc_get_mv_count_v6(struct s5p_mfc_dev *dev)
-{
-       return readl(dev->mfc_regs->d_min_num_mv);
-}
-
-static int s5p_mfc_get_min_scratch_buf_size(struct s5p_mfc_dev *dev)
-{
-       return readl(dev->mfc_regs->d_min_scratch_buffer_size);
-}
-
-static int s5p_mfc_get_e_min_scratch_buf_size(struct s5p_mfc_dev *dev)
-{
-       return readl(dev->mfc_regs->e_min_scratch_buffer_size);
-}
-
-static int s5p_mfc_get_inst_no_v6(struct s5p_mfc_dev *dev)
-{
-       return readl(dev->mfc_regs->ret_instance_id);
-}
-
-static int s5p_mfc_get_enc_dpb_count_v6(struct s5p_mfc_dev *dev)
-{
-       return readl(dev->mfc_regs->e_num_dpb);
-}
-
-static int s5p_mfc_get_enc_strm_size_v6(struct s5p_mfc_dev *dev)
-{
-       return readl(dev->mfc_regs->e_stream_size);
-}
-
-static int s5p_mfc_get_enc_slice_type_v6(struct s5p_mfc_dev *dev)
-{
-       return readl(dev->mfc_regs->e_slice_type);
-}
-
-static unsigned int s5p_mfc_get_pic_type_top_v6(struct s5p_mfc_ctx *ctx)
-{
-       return s5p_mfc_read_info_v6(ctx,
-               (__force unsigned long) ctx->dev->mfc_regs->d_ret_picture_tag_top);
-}
-
-static unsigned int s5p_mfc_get_pic_type_bot_v6(struct s5p_mfc_ctx *ctx)
-{
-       return s5p_mfc_read_info_v6(ctx,
-               (__force unsigned long) ctx->dev->mfc_regs->d_ret_picture_tag_bot);
-}
-
-static unsigned int s5p_mfc_get_crop_info_h_v6(struct s5p_mfc_ctx *ctx)
-{
-       return s5p_mfc_read_info_v6(ctx,
-               (__force unsigned long) ctx->dev->mfc_regs->d_display_crop_info1);
-}
-
-static unsigned int s5p_mfc_get_crop_info_v_v6(struct s5p_mfc_ctx *ctx)
-{
-       return s5p_mfc_read_info_v6(ctx,
-               (__force unsigned long) ctx->dev->mfc_regs->d_display_crop_info2);
-}
-
-static struct s5p_mfc_regs mfc_regs;
-
-/* Initialize registers for MFC v6 onwards */
-const struct s5p_mfc_regs *s5p_mfc_init_regs_v6_plus(struct s5p_mfc_dev *dev)
-{
-       memset(&mfc_regs, 0, sizeof(mfc_regs));
-
-#define S5P_MFC_REG_ADDR(dev, reg) ((dev)->regs_base + (reg))
-#define R(m, r) mfc_regs.m = S5P_MFC_REG_ADDR(dev, r)
-       /* codec common registers */
-       R(risc_on, S5P_FIMV_RISC_ON_V6);
-       R(risc2host_int, S5P_FIMV_RISC2HOST_INT_V6);
-       R(host2risc_int, S5P_FIMV_HOST2RISC_INT_V6);
-       R(risc_base_address, S5P_FIMV_RISC_BASE_ADDRESS_V6);
-       R(mfc_reset, S5P_FIMV_MFC_RESET_V6);
-       R(host2risc_command, S5P_FIMV_HOST2RISC_CMD_V6);
-       R(risc2host_command, S5P_FIMV_RISC2HOST_CMD_V6);
-       R(firmware_version, S5P_FIMV_FW_VERSION_V6);
-       R(instance_id, S5P_FIMV_INSTANCE_ID_V6);
-       R(codec_type, S5P_FIMV_CODEC_TYPE_V6);
-       R(context_mem_addr, S5P_FIMV_CONTEXT_MEM_ADDR_V6);
-       R(context_mem_size, S5P_FIMV_CONTEXT_MEM_SIZE_V6);
-       R(pixel_format, S5P_FIMV_PIXEL_FORMAT_V6);
-       R(ret_instance_id, S5P_FIMV_RET_INSTANCE_ID_V6);
-       R(error_code, S5P_FIMV_ERROR_CODE_V6);
-
-       /* decoder registers */
-       R(d_crc_ctrl, S5P_FIMV_D_CRC_CTRL_V6);
-       R(d_dec_options, S5P_FIMV_D_DEC_OPTIONS_V6);
-       R(d_display_delay, S5P_FIMV_D_DISPLAY_DELAY_V6);
-       R(d_sei_enable, S5P_FIMV_D_SEI_ENABLE_V6);
-       R(d_min_num_dpb, S5P_FIMV_D_MIN_NUM_DPB_V6);
-       R(d_min_num_mv, S5P_FIMV_D_MIN_NUM_MV_V6);
-       R(d_mvc_num_views, S5P_FIMV_D_MVC_NUM_VIEWS_V6);
-       R(d_num_dpb, S5P_FIMV_D_NUM_DPB_V6);
-       R(d_num_mv, S5P_FIMV_D_NUM_MV_V6);
-       R(d_init_buffer_options, S5P_FIMV_D_INIT_BUFFER_OPTIONS_V6);
-       R(d_first_plane_dpb_size, S5P_FIMV_D_LUMA_DPB_SIZE_V6);
-       R(d_second_plane_dpb_size, S5P_FIMV_D_CHROMA_DPB_SIZE_V6);
-       R(d_mv_buffer_size, S5P_FIMV_D_MV_BUFFER_SIZE_V6);
-       R(d_first_plane_dpb, S5P_FIMV_D_LUMA_DPB_V6);
-       R(d_second_plane_dpb, S5P_FIMV_D_CHROMA_DPB_V6);
-       R(d_mv_buffer, S5P_FIMV_D_MV_BUFFER_V6);
-       R(d_scratch_buffer_addr, S5P_FIMV_D_SCRATCH_BUFFER_ADDR_V6);
-       R(d_scratch_buffer_size, S5P_FIMV_D_SCRATCH_BUFFER_SIZE_V6);
-       R(d_cpb_buffer_addr, S5P_FIMV_D_CPB_BUFFER_ADDR_V6);
-       R(d_cpb_buffer_size, S5P_FIMV_D_CPB_BUFFER_SIZE_V6);
-       R(d_available_dpb_flag_lower, S5P_FIMV_D_AVAILABLE_DPB_FLAG_LOWER_V6);
-       R(d_cpb_buffer_offset, S5P_FIMV_D_CPB_BUFFER_OFFSET_V6);
-       R(d_slice_if_enable, S5P_FIMV_D_SLICE_IF_ENABLE_V6);
-       R(d_stream_data_size, S5P_FIMV_D_STREAM_DATA_SIZE_V6);
-       R(d_display_frame_width, S5P_FIMV_D_DISPLAY_FRAME_WIDTH_V6);
-       R(d_display_frame_height, S5P_FIMV_D_DISPLAY_FRAME_HEIGHT_V6);
-       R(d_display_status, S5P_FIMV_D_DISPLAY_STATUS_V6);
-       R(d_display_first_plane_addr, S5P_FIMV_D_DISPLAY_LUMA_ADDR_V6);
-       R(d_display_second_plane_addr, S5P_FIMV_D_DISPLAY_CHROMA_ADDR_V6);
-       R(d_display_frame_type, S5P_FIMV_D_DISPLAY_FRAME_TYPE_V6);
-       R(d_display_crop_info1, S5P_FIMV_D_DISPLAY_CROP_INFO1_V6);
-       R(d_display_crop_info2, S5P_FIMV_D_DISPLAY_CROP_INFO2_V6);
-       R(d_display_aspect_ratio, S5P_FIMV_D_DISPLAY_ASPECT_RATIO_V6);
-       R(d_display_extended_ar, S5P_FIMV_D_DISPLAY_EXTENDED_AR_V6);
-       R(d_decoded_status, S5P_FIMV_D_DECODED_STATUS_V6);
-       R(d_decoded_first_plane_addr, S5P_FIMV_D_DECODED_LUMA_ADDR_V6);
-       R(d_decoded_second_plane_addr, S5P_FIMV_D_DECODED_CHROMA_ADDR_V6);
-       R(d_decoded_frame_type, S5P_FIMV_D_DECODED_FRAME_TYPE_V6);
-       R(d_decoded_nal_size, S5P_FIMV_D_DECODED_NAL_SIZE_V6);
-       R(d_ret_picture_tag_top, S5P_FIMV_D_RET_PICTURE_TAG_TOP_V6);
-       R(d_ret_picture_tag_bot, S5P_FIMV_D_RET_PICTURE_TAG_BOT_V6);
-       R(d_h264_info, S5P_FIMV_D_H264_INFO_V6);
-       R(d_mvc_view_id, S5P_FIMV_D_MVC_VIEW_ID_V6);
-       R(d_frame_pack_sei_avail, S5P_FIMV_D_FRAME_PACK_SEI_AVAIL_V6);
-
-       /* encoder registers */
-       R(e_frame_width, S5P_FIMV_E_FRAME_WIDTH_V6);
-       R(e_frame_height, S5P_FIMV_E_FRAME_HEIGHT_V6);
-       R(e_cropped_frame_width, S5P_FIMV_E_CROPPED_FRAME_WIDTH_V6);
-       R(e_cropped_frame_height, S5P_FIMV_E_CROPPED_FRAME_HEIGHT_V6);
-       R(e_frame_crop_offset, S5P_FIMV_E_FRAME_CROP_OFFSET_V6);
-       R(e_enc_options, S5P_FIMV_E_ENC_OPTIONS_V6);
-       R(e_picture_profile, S5P_FIMV_E_PICTURE_PROFILE_V6);
-       R(e_vbv_buffer_size, S5P_FIMV_E_VBV_BUFFER_SIZE_V6);
-       R(e_vbv_init_delay, S5P_FIMV_E_VBV_INIT_DELAY_V6);
-       R(e_fixed_picture_qp, S5P_FIMV_E_FIXED_PICTURE_QP_V6);
-       R(e_rc_config, S5P_FIMV_E_RC_CONFIG_V6);
-       R(e_rc_qp_bound, S5P_FIMV_E_RC_QP_BOUND_V6);
-       R(e_rc_mode, S5P_FIMV_E_RC_RPARAM_V6);
-       R(e_mb_rc_config, S5P_FIMV_E_MB_RC_CONFIG_V6);
-       R(e_padding_ctrl, S5P_FIMV_E_PADDING_CTRL_V6);
-       R(e_mv_hor_range, S5P_FIMV_E_MV_HOR_RANGE_V6);
-       R(e_mv_ver_range, S5P_FIMV_E_MV_VER_RANGE_V6);
-       R(e_num_dpb, S5P_FIMV_E_NUM_DPB_V6);
-       R(e_luma_dpb, S5P_FIMV_E_LUMA_DPB_V6);
-       R(e_chroma_dpb, S5P_FIMV_E_CHROMA_DPB_V6);
-       R(e_me_buffer, S5P_FIMV_E_ME_BUFFER_V6);
-       R(e_scratch_buffer_addr, S5P_FIMV_E_SCRATCH_BUFFER_ADDR_V6);
-       R(e_scratch_buffer_size, S5P_FIMV_E_SCRATCH_BUFFER_SIZE_V6);
-       R(e_tmv_buffer0, S5P_FIMV_E_TMV_BUFFER0_V6);
-       R(e_tmv_buffer1, S5P_FIMV_E_TMV_BUFFER1_V6);
-       R(e_source_first_plane_addr, S5P_FIMV_E_SOURCE_LUMA_ADDR_V6);
-       R(e_source_second_plane_addr, S5P_FIMV_E_SOURCE_CHROMA_ADDR_V6);
-       R(e_stream_buffer_addr, S5P_FIMV_E_STREAM_BUFFER_ADDR_V6);
-       R(e_stream_buffer_size, S5P_FIMV_E_STREAM_BUFFER_SIZE_V6);
-       R(e_roi_buffer_addr, S5P_FIMV_E_ROI_BUFFER_ADDR_V6);
-       R(e_param_change, S5P_FIMV_E_PARAM_CHANGE_V6);
-       R(e_ir_size, S5P_FIMV_E_IR_SIZE_V6);
-       R(e_gop_config, S5P_FIMV_E_GOP_CONFIG_V6);
-       R(e_mslice_mode, S5P_FIMV_E_MSLICE_MODE_V6);
-       R(e_mslice_size_mb, S5P_FIMV_E_MSLICE_SIZE_MB_V6);
-       R(e_mslice_size_bits, S5P_FIMV_E_MSLICE_SIZE_BITS_V6);
-       R(e_frame_insertion, S5P_FIMV_E_FRAME_INSERTION_V6);
-       R(e_rc_frame_rate, S5P_FIMV_E_RC_FRAME_RATE_V6);
-       R(e_rc_bit_rate, S5P_FIMV_E_RC_BIT_RATE_V6);
-       R(e_rc_roi_ctrl, S5P_FIMV_E_RC_ROI_CTRL_V6);
-       R(e_picture_tag, S5P_FIMV_E_PICTURE_TAG_V6);
-       R(e_bit_count_enable, S5P_FIMV_E_BIT_COUNT_ENABLE_V6);
-       R(e_max_bit_count, S5P_FIMV_E_MAX_BIT_COUNT_V6);
-       R(e_min_bit_count, S5P_FIMV_E_MIN_BIT_COUNT_V6);
-       R(e_metadata_buffer_addr, S5P_FIMV_E_METADATA_BUFFER_ADDR_V6);
-       R(e_metadata_buffer_size, S5P_FIMV_E_METADATA_BUFFER_SIZE_V6);
-       R(e_encoded_source_first_plane_addr,
-                       S5P_FIMV_E_ENCODED_SOURCE_LUMA_ADDR_V6);
-       R(e_encoded_source_second_plane_addr,
-                       S5P_FIMV_E_ENCODED_SOURCE_CHROMA_ADDR_V6);
-       R(e_stream_size, S5P_FIMV_E_STREAM_SIZE_V6);
-       R(e_slice_type, S5P_FIMV_E_SLICE_TYPE_V6);
-       R(e_picture_count, S5P_FIMV_E_PICTURE_COUNT_V6);
-       R(e_ret_picture_tag, S5P_FIMV_E_RET_PICTURE_TAG_V6);
-       R(e_recon_luma_dpb_addr, S5P_FIMV_E_RECON_LUMA_DPB_ADDR_V6);
-       R(e_recon_chroma_dpb_addr, S5P_FIMV_E_RECON_CHROMA_DPB_ADDR_V6);
-       R(e_mpeg4_options, S5P_FIMV_E_MPEG4_OPTIONS_V6);
-       R(e_mpeg4_hec_period, S5P_FIMV_E_MPEG4_HEC_PERIOD_V6);
-       R(e_aspect_ratio, S5P_FIMV_E_ASPECT_RATIO_V6);
-       R(e_extended_sar, S5P_FIMV_E_EXTENDED_SAR_V6);
-       R(e_h264_options, S5P_FIMV_E_H264_OPTIONS_V6);
-       R(e_h264_lf_alpha_offset, S5P_FIMV_E_H264_LF_ALPHA_OFFSET_V6);
-       R(e_h264_lf_beta_offset, S5P_FIMV_E_H264_LF_BETA_OFFSET_V6);
-       R(e_h264_i_period, S5P_FIMV_E_H264_I_PERIOD_V6);
-       R(e_h264_fmo_slice_grp_map_type,
-                       S5P_FIMV_E_H264_FMO_SLICE_GRP_MAP_TYPE_V6);
-       R(e_h264_fmo_num_slice_grp_minus1,
-                       S5P_FIMV_E_H264_FMO_NUM_SLICE_GRP_MINUS1_V6);
-       R(e_h264_fmo_slice_grp_change_dir,
-                       S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_DIR_V6);
-       R(e_h264_fmo_slice_grp_change_rate_minus1,
-                       S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_RATE_MINUS1_V6);
-       R(e_h264_fmo_run_length_minus1_0,
-                       S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_0_V6);
-       R(e_h264_aso_slice_order_0, S5P_FIMV_E_H264_ASO_SLICE_ORDER_0_V6);
-       R(e_h264_num_t_layer, S5P_FIMV_E_H264_NUM_T_LAYER_V6);
-       R(e_h264_hierarchical_qp_layer0,
-                       S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER0_V6);
-       R(e_h264_frame_packing_sei_info,
-                       S5P_FIMV_E_H264_FRAME_PACKING_SEI_INFO_V6);
-
-       if (!IS_MFCV7_PLUS(dev))
-               goto done;
-
-       /* Initialize registers used in MFC v7+ */
-       R(e_source_first_plane_addr, S5P_FIMV_E_SOURCE_FIRST_ADDR_V7);
-       R(e_source_second_plane_addr, S5P_FIMV_E_SOURCE_SECOND_ADDR_V7);
-       R(e_source_third_plane_addr, S5P_FIMV_E_SOURCE_THIRD_ADDR_V7);
-       R(e_source_first_plane_stride, S5P_FIMV_E_SOURCE_FIRST_STRIDE_V7);
-       R(e_source_second_plane_stride, S5P_FIMV_E_SOURCE_SECOND_STRIDE_V7);
-       R(e_source_third_plane_stride, S5P_FIMV_E_SOURCE_THIRD_STRIDE_V7);
-       R(e_encoded_source_first_plane_addr,
-                       S5P_FIMV_E_ENCODED_SOURCE_FIRST_ADDR_V7);
-       R(e_encoded_source_second_plane_addr,
-                       S5P_FIMV_E_ENCODED_SOURCE_SECOND_ADDR_V7);
-       R(e_vp8_options, S5P_FIMV_E_VP8_OPTIONS_V7);
-
-       if (!IS_MFCV8_PLUS(dev))
-               goto done;
-
-       /* Initialize registers used in MFC v8 only.
-        * Also, over-write the registers which have
-        * a different offset for MFC v8. */
-       R(d_stream_data_size, S5P_FIMV_D_STREAM_DATA_SIZE_V8);
-       R(d_cpb_buffer_addr, S5P_FIMV_D_CPB_BUFFER_ADDR_V8);
-       R(d_cpb_buffer_size, S5P_FIMV_D_CPB_BUFFER_SIZE_V8);
-       R(d_cpb_buffer_offset, S5P_FIMV_D_CPB_BUFFER_OFFSET_V8);
-       R(d_first_plane_dpb_size, S5P_FIMV_D_FIRST_PLANE_DPB_SIZE_V8);
-       R(d_second_plane_dpb_size, S5P_FIMV_D_SECOND_PLANE_DPB_SIZE_V8);
-       R(d_scratch_buffer_addr, S5P_FIMV_D_SCRATCH_BUFFER_ADDR_V8);
-       R(d_scratch_buffer_size, S5P_FIMV_D_SCRATCH_BUFFER_SIZE_V8);
-       R(d_first_plane_dpb_stride_size,
-                       S5P_FIMV_D_FIRST_PLANE_DPB_STRIDE_SIZE_V8);
-       R(d_second_plane_dpb_stride_size,
-                       S5P_FIMV_D_SECOND_PLANE_DPB_STRIDE_SIZE_V8);
-       R(d_mv_buffer_size, S5P_FIMV_D_MV_BUFFER_SIZE_V8);
-       R(d_num_mv, S5P_FIMV_D_NUM_MV_V8);
-       R(d_first_plane_dpb, S5P_FIMV_D_FIRST_PLANE_DPB_V8);
-       R(d_second_plane_dpb, S5P_FIMV_D_SECOND_PLANE_DPB_V8);
-       R(d_mv_buffer, S5P_FIMV_D_MV_BUFFER_V8);
-       R(d_init_buffer_options, S5P_FIMV_D_INIT_BUFFER_OPTIONS_V8);
-       R(d_available_dpb_flag_lower, S5P_FIMV_D_AVAILABLE_DPB_FLAG_LOWER_V8);
-       R(d_slice_if_enable, S5P_FIMV_D_SLICE_IF_ENABLE_V8);
-       R(d_display_first_plane_addr, S5P_FIMV_D_DISPLAY_FIRST_PLANE_ADDR_V8);
-       R(d_display_second_plane_addr, S5P_FIMV_D_DISPLAY_SECOND_PLANE_ADDR_V8);
-       R(d_decoded_first_plane_addr, S5P_FIMV_D_DECODED_FIRST_PLANE_ADDR_V8);
-       R(d_decoded_second_plane_addr, S5P_FIMV_D_DECODED_SECOND_PLANE_ADDR_V8);
-       R(d_display_status, S5P_FIMV_D_DISPLAY_STATUS_V8);
-       R(d_decoded_status, S5P_FIMV_D_DECODED_STATUS_V8);
-       R(d_decoded_frame_type, S5P_FIMV_D_DECODED_FRAME_TYPE_V8);
-       R(d_display_frame_type, S5P_FIMV_D_DISPLAY_FRAME_TYPE_V8);
-       R(d_decoded_nal_size, S5P_FIMV_D_DECODED_NAL_SIZE_V8);
-       R(d_display_frame_width, S5P_FIMV_D_DISPLAY_FRAME_WIDTH_V8);
-       R(d_display_frame_height, S5P_FIMV_D_DISPLAY_FRAME_HEIGHT_V8);
-       R(d_frame_pack_sei_avail, S5P_FIMV_D_FRAME_PACK_SEI_AVAIL_V8);
-       R(d_mvc_num_views, S5P_FIMV_D_MVC_NUM_VIEWS_V8);
-       R(d_mvc_view_id, S5P_FIMV_D_MVC_VIEW_ID_V8);
-       R(d_ret_picture_tag_top, S5P_FIMV_D_RET_PICTURE_TAG_TOP_V8);
-       R(d_ret_picture_tag_bot, S5P_FIMV_D_RET_PICTURE_TAG_BOT_V8);
-       R(d_display_crop_info1, S5P_FIMV_D_DISPLAY_CROP_INFO1_V8);
-       R(d_display_crop_info2, S5P_FIMV_D_DISPLAY_CROP_INFO2_V8);
-       R(d_min_scratch_buffer_size, S5P_FIMV_D_MIN_SCRATCH_BUFFER_SIZE_V8);
-
-       /* encoder registers */
-       R(e_padding_ctrl, S5P_FIMV_E_PADDING_CTRL_V8);
-       R(e_rc_config, S5P_FIMV_E_RC_CONFIG_V8);
-       R(e_rc_mode, S5P_FIMV_E_RC_RPARAM_V8);
-       R(e_mv_hor_range, S5P_FIMV_E_MV_HOR_RANGE_V8);
-       R(e_mv_ver_range, S5P_FIMV_E_MV_VER_RANGE_V8);
-       R(e_rc_qp_bound, S5P_FIMV_E_RC_QP_BOUND_V8);
-       R(e_fixed_picture_qp, S5P_FIMV_E_FIXED_PICTURE_QP_V8);
-       R(e_vbv_buffer_size, S5P_FIMV_E_VBV_BUFFER_SIZE_V8);
-       R(e_vbv_init_delay, S5P_FIMV_E_VBV_INIT_DELAY_V8);
-       R(e_mb_rc_config, S5P_FIMV_E_MB_RC_CONFIG_V8);
-       R(e_aspect_ratio, S5P_FIMV_E_ASPECT_RATIO_V8);
-       R(e_extended_sar, S5P_FIMV_E_EXTENDED_SAR_V8);
-       R(e_h264_options, S5P_FIMV_E_H264_OPTIONS_V8);
-       R(e_min_scratch_buffer_size, S5P_FIMV_E_MIN_SCRATCH_BUFFER_SIZE_V8);
-
-       if (!IS_MFCV10(dev))
-               goto done;
-
-       /* Initialize registers used in MFC v10 only.
-        * Also, over-write the registers which have
-        * a different offset for MFC v10.
-        */
-
-       /* decoder registers */
-       R(d_static_buffer_addr, S5P_FIMV_D_STATIC_BUFFER_ADDR_V10);
-       R(d_static_buffer_size, S5P_FIMV_D_STATIC_BUFFER_SIZE_V10);
-
-       /* encoder registers */
-       R(e_num_t_layer, S5P_FIMV_E_NUM_T_LAYER_V10);
-       R(e_hier_qp_layer0, S5P_FIMV_E_HIERARCHICAL_QP_LAYER0_V10);
-       R(e_hier_bit_rate_layer0, S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER0_V10);
-       R(e_hevc_options, S5P_FIMV_E_HEVC_OPTIONS_V10);
-       R(e_hevc_refresh_period, S5P_FIMV_E_HEVC_REFRESH_PERIOD_V10);
-       R(e_hevc_lf_beta_offset_div2, S5P_FIMV_E_HEVC_LF_BETA_OFFSET_DIV2_V10);
-       R(e_hevc_lf_tc_offset_div2, S5P_FIMV_E_HEVC_LF_TC_OFFSET_DIV2_V10);
-       R(e_hevc_nal_control, S5P_FIMV_E_HEVC_NAL_CONTROL_V10);
-
-done:
-       return &mfc_regs;
-#undef S5P_MFC_REG_ADDR
-#undef R
-}
-
-/* Initialize opr function pointers for MFC v6 */
-static struct s5p_mfc_hw_ops s5p_mfc_ops_v6 = {
-       .alloc_dec_temp_buffers = s5p_mfc_alloc_dec_temp_buffers_v6,
-       .release_dec_desc_buffer = s5p_mfc_release_dec_desc_buffer_v6,
-       .alloc_codec_buffers = s5p_mfc_alloc_codec_buffers_v6,
-       .release_codec_buffers = s5p_mfc_release_codec_buffers_v6,
-       .alloc_instance_buffer = s5p_mfc_alloc_instance_buffer_v6,
-       .release_instance_buffer = s5p_mfc_release_instance_buffer_v6,
-       .alloc_dev_context_buffer =
-               s5p_mfc_alloc_dev_context_buffer_v6,
-       .release_dev_context_buffer =
-               s5p_mfc_release_dev_context_buffer_v6,
-       .dec_calc_dpb_size = s5p_mfc_dec_calc_dpb_size_v6,
-       .enc_calc_src_size = s5p_mfc_enc_calc_src_size_v6,
-       .set_enc_stream_buffer = s5p_mfc_set_enc_stream_buffer_v6,
-       .set_enc_frame_buffer = s5p_mfc_set_enc_frame_buffer_v6,
-       .get_enc_frame_buffer = s5p_mfc_get_enc_frame_buffer_v6,
-       .try_run = s5p_mfc_try_run_v6,
-       .clear_int_flags = s5p_mfc_clear_int_flags_v6,
-       .get_dspl_y_adr = s5p_mfc_get_dspl_y_adr_v6,
-       .get_dec_y_adr = s5p_mfc_get_dec_y_adr_v6,
-       .get_dspl_status = s5p_mfc_get_dspl_status_v6,
-       .get_dec_status = s5p_mfc_get_dec_status_v6,
-       .get_dec_frame_type = s5p_mfc_get_dec_frame_type_v6,
-       .get_disp_frame_type = s5p_mfc_get_disp_frame_type_v6,
-       .get_consumed_stream = s5p_mfc_get_consumed_stream_v6,
-       .get_int_reason = s5p_mfc_get_int_reason_v6,
-       .get_int_err = s5p_mfc_get_int_err_v6,
-       .err_dec = s5p_mfc_err_dec_v6,
-       .get_img_width = s5p_mfc_get_img_width_v6,
-       .get_img_height = s5p_mfc_get_img_height_v6,
-       .get_dpb_count = s5p_mfc_get_dpb_count_v6,
-       .get_mv_count = s5p_mfc_get_mv_count_v6,
-       .get_inst_no = s5p_mfc_get_inst_no_v6,
-       .get_enc_strm_size = s5p_mfc_get_enc_strm_size_v6,
-       .get_enc_slice_type = s5p_mfc_get_enc_slice_type_v6,
-       .get_enc_dpb_count = s5p_mfc_get_enc_dpb_count_v6,
-       .get_pic_type_top = s5p_mfc_get_pic_type_top_v6,
-       .get_pic_type_bot = s5p_mfc_get_pic_type_bot_v6,
-       .get_crop_info_h = s5p_mfc_get_crop_info_h_v6,
-       .get_crop_info_v = s5p_mfc_get_crop_info_v_v6,
-       .get_min_scratch_buf_size = s5p_mfc_get_min_scratch_buf_size,
-       .get_e_min_scratch_buf_size = s5p_mfc_get_e_min_scratch_buf_size,
-};
-
-struct s5p_mfc_hw_ops *s5p_mfc_init_hw_ops_v6(void)
-{
-       return &s5p_mfc_ops_v6;
-}
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h
deleted file mode 100644 (file)
index 8ca514b..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.h
- *
- * Header file for Samsung MFC (Multi Function Codec - FIMV) driver
- * Contains declarations of hw related functions.
- *
- * Copyright (c) 2012 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- */
-
-#ifndef S5P_MFC_OPR_V6_H_
-#define S5P_MFC_OPR_V6_H_
-
-#include "s5p_mfc_common.h"
-#include "s5p_mfc_opr.h"
-
-#define MFC_CTRL_MODE_CUSTOM   MFC_CTRL_MODE_SFR
-
-#define MB_WIDTH(x_size)               DIV_ROUND_UP(x_size, 16)
-#define MB_HEIGHT(y_size)              DIV_ROUND_UP(y_size, 16)
-#define S5P_MFC_DEC_MV_SIZE_V6(x, y)   (MB_WIDTH(x) * \
-                                       (((MB_HEIGHT(y)+1)/2)*2) * 64 + 128)
-#define S5P_MFC_DEC_MV_SIZE_V10(x, y)  (MB_WIDTH(x) * \
-                                       (((MB_HEIGHT(y)+1)/2)*2) * 64 + 512)
-#define S5P_MFC_LCU_WIDTH(x_size)      DIV_ROUND_UP(x_size, 32)
-#define S5P_MFC_LCU_HEIGHT(y_size)     DIV_ROUND_UP(y_size, 32)
-
-#define s5p_mfc_dec_hevc_mv_size(x, y) \
-       (DIV_ROUND_UP(x, 64) * DIV_ROUND_UP(y, 64) * 256 + 512)
-
-/* Definition */
-#define ENC_MULTI_SLICE_MB_MAX         ((1 << 30) - 1)
-#define ENC_MULTI_SLICE_BIT_MIN                2800
-#define ENC_INTRA_REFRESH_MB_MAX       ((1 << 18) - 1)
-#define ENC_VBV_BUF_SIZE_MAX           ((1 << 30) - 1)
-#define ENC_H264_LOOP_FILTER_AB_MIN    -12
-#define ENC_H264_LOOP_FILTER_AB_MAX    12
-#define ENC_H264_RC_FRAME_RATE_MAX     ((1 << 16) - 1)
-#define ENC_H263_RC_FRAME_RATE_MAX     ((1 << 16) - 1)
-#define ENC_H264_PROFILE_MAX           3
-#define ENC_H264_LEVEL_MAX             42
-#define ENC_MPEG4_VOP_TIME_RES_MAX     ((1 << 16) - 1)
-#define FRAME_DELTA_H264_H263          1
-#define TIGHT_CBR_MAX                  10
-#define ENC_HEVC_RC_FRAME_RATE_MAX     ((1 << 16) - 1)
-#define ENC_HEVC_QP_INDEX_MIN          -12
-#define ENC_HEVC_QP_INDEX_MAX          12
-#define ENC_HEVC_LOOP_FILTER_MIN       -12
-#define ENC_HEVC_LOOP_FILTER_MAX       12
-#define ENC_HEVC_LEVEL_MAX             62
-
-#define FRAME_DELTA_DEFAULT            1
-
-struct s5p_mfc_hw_ops *s5p_mfc_init_hw_ops_v6(void);
-const struct s5p_mfc_regs *s5p_mfc_init_regs_v6_plus(struct s5p_mfc_dev *dev);
-#endif /* S5P_MFC_OPR_V6_H_ */
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c b/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
deleted file mode 100644 (file)
index 88b7d33..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * linux/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- */
-
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
-#include "s5p_mfc_common.h"
-#include "s5p_mfc_debug.h"
-#include "s5p_mfc_pm.h"
-
-static struct s5p_mfc_pm *pm;
-static struct s5p_mfc_dev *p_dev;
-static atomic_t clk_ref;
-
-int s5p_mfc_init_pm(struct s5p_mfc_dev *dev)
-{
-       int i;
-
-       pm = &dev->pm;
-       p_dev = dev;
-
-       pm->num_clocks = dev->variant->num_clocks;
-       pm->clk_names = dev->variant->clk_names;
-       pm->device = &dev->plat_dev->dev;
-       pm->clock_gate = NULL;
-
-       /* clock control */
-       for (i = 0; i < pm->num_clocks; i++) {
-               pm->clocks[i] = devm_clk_get(pm->device, pm->clk_names[i]);
-               if (IS_ERR(pm->clocks[i])) {
-                       /* additional clocks are optional */
-                       if (i && PTR_ERR(pm->clocks[i]) == -ENOENT) {
-                               pm->clocks[i] = NULL;
-                               continue;
-                       }
-                       mfc_err("Failed to get clock: %s\n",
-                               pm->clk_names[i]);
-                       return PTR_ERR(pm->clocks[i]);
-               }
-       }
-
-       if (dev->variant->use_clock_gating)
-               pm->clock_gate = pm->clocks[0];
-
-       pm_runtime_enable(pm->device);
-       atomic_set(&clk_ref, 0);
-       return 0;
-}
-
-void s5p_mfc_final_pm(struct s5p_mfc_dev *dev)
-{
-       pm_runtime_disable(pm->device);
-}
-
-int s5p_mfc_clock_on(void)
-{
-       atomic_inc(&clk_ref);
-       mfc_debug(3, "+ %d\n", atomic_read(&clk_ref));
-
-       return clk_enable(pm->clock_gate);
-}
-
-void s5p_mfc_clock_off(void)
-{
-       atomic_dec(&clk_ref);
-       mfc_debug(3, "- %d\n", atomic_read(&clk_ref));
-
-       clk_disable(pm->clock_gate);
-}
-
-int s5p_mfc_power_on(void)
-{
-       int i, ret = 0;
-
-       ret = pm_runtime_resume_and_get(pm->device);
-       if (ret < 0)
-               return ret;
-
-       /* clock control */
-       for (i = 0; i < pm->num_clocks; i++) {
-               ret = clk_prepare_enable(pm->clocks[i]);
-               if (ret < 0) {
-                       mfc_err("clock prepare failed for clock: %s\n",
-                               pm->clk_names[i]);
-                       i++;
-                       goto err;
-               }
-       }
-
-       /* prepare for software clock gating */
-       clk_disable(pm->clock_gate);
-
-       return 0;
-err:
-       while (--i > 0)
-               clk_disable_unprepare(pm->clocks[i]);
-       pm_runtime_put(pm->device);
-       return ret;
-}
-
-int s5p_mfc_power_off(void)
-{
-       int i;
-
-       /* finish software clock gating */
-       clk_enable(pm->clock_gate);
-
-       for (i = 0; i < pm->num_clocks; i++)
-               clk_disable_unprepare(pm->clocks[i]);
-
-       return pm_runtime_put_sync(pm->device);
-}
-
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_pm.h b/drivers/media/platform/s5p-mfc/s5p_mfc_pm.h
deleted file mode 100644 (file)
index 3d26443..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * linux/drivers/media/platform/s5p-mfc/s5p_mfc_pm.h
- *
- * Copyright (C) 2011 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- */
-
-#ifndef S5P_MFC_PM_H_
-#define S5P_MFC_PM_H_
-
-int s5p_mfc_init_pm(struct s5p_mfc_dev *dev);
-void s5p_mfc_final_pm(struct s5p_mfc_dev *dev);
-
-int s5p_mfc_clock_on(void);
-void s5p_mfc_clock_off(void);
-int s5p_mfc_power_on(void);
-int s5p_mfc_power_off(void);
-
-#endif /* S5P_MFC_PM_H_ */
diff --git a/drivers/media/platform/samsung/s5p-mfc/Kconfig b/drivers/media/platform/samsung/s5p-mfc/Kconfig
new file mode 100644 (file)
index 0000000..34b52b0
--- /dev/null
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0-only
+config VIDEO_SAMSUNG_S5P_MFC
+       tristate "Samsung S5P MFC Video Codec"
+       depends on V4L_MEM2MEM_DRIVERS
+       depends on VIDEO_DEV && VIDEO_V4L2
+       depends on ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST
+       select VIDEOBUF2_DMA_CONTIG
+       help
+           MFC 5.1 and 6.x driver for V4L2
diff --git a/drivers/media/platform/samsung/s5p-mfc/Makefile b/drivers/media/platform/samsung/s5p-mfc/Makefile
new file mode 100644 (file)
index 0000000..0b324af
--- /dev/null
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC) += s5p-mfc.o
+s5p-mfc-y += s5p_mfc.o s5p_mfc_intr.o
+s5p-mfc-y += s5p_mfc_dec.o s5p_mfc_enc.o
+s5p-mfc-y += s5p_mfc_ctrl.o s5p_mfc_pm.o
+s5p-mfc-y += s5p_mfc_opr.o s5p_mfc_opr_v5.o s5p_mfc_opr_v6.o
+s5p-mfc-y += s5p_mfc_cmd.o s5p_mfc_cmd_v5.o s5p_mfc_cmd_v6.o
diff --git a/drivers/media/platform/samsung/s5p-mfc/regs-mfc-v10.h b/drivers/media/platform/samsung/s5p-mfc/regs-mfc-v10.h
new file mode 100644 (file)
index 0000000..fadd913
--- /dev/null
@@ -0,0 +1,87 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ *     http://www.samsung.com/
+ *
+ * Register definition file for Samsung MFC V10.x Interface (FIMV) driver
+ *
+ */
+
+#ifndef _REGS_MFC_V10_H
+#define _REGS_MFC_V10_H
+
+#include <linux/sizes.h>
+#include "regs-mfc-v8.h"
+
+/* MFCv10 register definitions*/
+#define S5P_FIMV_MFC_CLOCK_OFF_V10                     0x7120
+#define S5P_FIMV_MFC_STATE_V10                         0x7124
+#define S5P_FIMV_D_STATIC_BUFFER_ADDR_V10              0xF570
+#define S5P_FIMV_D_STATIC_BUFFER_SIZE_V10              0xF574
+#define S5P_FIMV_E_NUM_T_LAYER_V10                     0xFBAC
+#define S5P_FIMV_E_HIERARCHICAL_QP_LAYER0_V10          0xFBB0
+#define S5P_FIMV_E_HIERARCHICAL_QP_LAYER1_V10          0xFBB4
+#define S5P_FIMV_E_HIERARCHICAL_QP_LAYER2_V10          0xFBB8
+#define S5P_FIMV_E_HIERARCHICAL_QP_LAYER3_V10          0xFBBC
+#define S5P_FIMV_E_HIERARCHICAL_QP_LAYER4_V10          0xFBC0
+#define S5P_FIMV_E_HIERARCHICAL_QP_LAYER5_V10          0xFBC4
+#define S5P_FIMV_E_HIERARCHICAL_QP_LAYER6_V10          0xFBC8
+#define S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER0_V10    0xFD18
+#define S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER1_V10    0xFD1C
+#define S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER2_V10    0xFD20
+#define S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER3_V10    0xFD24
+#define S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER4_V10    0xFD28
+#define S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER5_V10    0xFD2C
+#define S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER6_V10    0xFD30
+#define S5P_FIMV_E_HEVC_OPTIONS_V10                    0xFDD4
+#define S5P_FIMV_E_HEVC_REFRESH_PERIOD_V10             0xFDD8
+#define S5P_FIMV_E_HEVC_CHROMA_QP_OFFSET_V10           0xFDDC
+#define S5P_FIMV_E_HEVC_LF_BETA_OFFSET_DIV2_V10                0xFDE0
+#define S5P_FIMV_E_HEVC_LF_TC_OFFSET_DIV2_V10          0xFDE4
+#define S5P_FIMV_E_HEVC_NAL_CONTROL_V10                        0xFDE8
+
+/* MFCv10 Context buffer sizes */
+#define MFC_CTX_BUF_SIZE_V10           (30 * SZ_1K)
+#define MFC_H264_DEC_CTX_BUF_SIZE_V10  (2 * SZ_1M)
+#define MFC_OTHER_DEC_CTX_BUF_SIZE_V10 (20 * SZ_1K)
+#define MFC_H264_ENC_CTX_BUF_SIZE_V10  (100 * SZ_1K)
+#define MFC_HEVC_ENC_CTX_BUF_SIZE_V10  (30 * SZ_1K)
+#define MFC_OTHER_ENC_CTX_BUF_SIZE_V10  (15 * SZ_1K)
+
+/* MFCv10 variant defines */
+#define MAX_FW_SIZE_V10                (SZ_1M)
+#define MAX_CPB_SIZE_V10       (3 * SZ_1M)
+#define MFC_VERSION_V10                0xA0
+#define MFC_NUM_PORTS_V10      1
+
+/* MFCv10 codec defines*/
+#define S5P_FIMV_CODEC_HEVC_DEC                17
+#define S5P_FIMV_CODEC_VP9_DEC         18
+#define S5P_FIMV_CODEC_HEVC_ENC         26
+
+/* Decoder buffer size for MFC v10 */
+#define DEC_VP9_STATIC_BUFFER_SIZE     20480
+
+/* Encoder buffer size for MFC v10.0 */
+#define ENC_V100_BASE_SIZE(x, y) \
+       (((x + 3) * (y + 3) * 8) \
+       +  ((y * 64) + 1280) * DIV_ROUND_UP(x, 8))
+
+#define ENC_V100_H264_ME_SIZE(x, y) \
+       (ENC_V100_BASE_SIZE(x, y) \
+       + (DIV_ROUND_UP(x * y, 64) * 32))
+
+#define ENC_V100_MPEG4_ME_SIZE(x, y) \
+       (ENC_V100_BASE_SIZE(x, y) \
+       + (DIV_ROUND_UP(x * y, 128) * 16))
+
+#define ENC_V100_VP8_ME_SIZE(x, y) \
+       ENC_V100_BASE_SIZE(x, y)
+
+#define ENC_V100_HEVC_ME_SIZE(x, y)    \
+       (((x + 3) * (y + 3) * 32)       \
+        + ((y * 128) + 1280) * DIV_ROUND_UP(x, 4))
+
+#endif /*_REGS_MFC_V10_H*/
+
diff --git a/drivers/media/platform/samsung/s5p-mfc/regs-mfc-v6.h b/drivers/media/platform/samsung/s5p-mfc/regs-mfc-v6.h
new file mode 100644 (file)
index 0000000..fa49fe5
--- /dev/null
@@ -0,0 +1,408 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Register definition file for Samsung MFC V6.x Interface (FIMV) driver
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ */
+
+#ifndef _REGS_FIMV_V6_H
+#define _REGS_FIMV_V6_H
+
+#include <linux/kernel.h>
+#include <linux/sizes.h>
+
+#define S5P_FIMV_REG_SIZE_V6   (S5P_FIMV_END_ADDR - S5P_FIMV_START_ADDR)
+#define S5P_FIMV_REG_COUNT_V6  ((S5P_FIMV_END_ADDR - S5P_FIMV_START_ADDR) / 4)
+
+/* Number of bits that the buffer address should be shifted for particular
+ * MFC buffers.  */
+#define S5P_FIMV_MEM_OFFSET_V6         0
+
+#define S5P_FIMV_START_ADDR_V6         0x0000
+#define S5P_FIMV_END_ADDR_V6           0xfd80
+
+#define S5P_FIMV_REG_CLEAR_BEGIN_V6    0xf000
+#define S5P_FIMV_REG_CLEAR_COUNT_V6    1024
+
+/* Codec Common Registers */
+#define S5P_FIMV_RISC_ON_V6                    0x0000
+#define S5P_FIMV_RISC2HOST_INT_V6              0x003C
+#define S5P_FIMV_HOST2RISC_INT_V6              0x0044
+#define S5P_FIMV_RISC_BASE_ADDRESS_V6          0x0054
+
+#define S5P_FIMV_MFC_RESET_V6                  0x1070
+
+#define S5P_FIMV_HOST2RISC_CMD_V6              0x1100
+#define S5P_FIMV_H2R_CMD_EMPTY_V6              0
+#define S5P_FIMV_H2R_CMD_SYS_INIT_V6           1
+#define S5P_FIMV_H2R_CMD_OPEN_INSTANCE_V6      2
+#define S5P_FIMV_CH_SEQ_HEADER_V6              3
+#define S5P_FIMV_CH_INIT_BUFS_V6               4
+#define S5P_FIMV_CH_FRAME_START_V6             5
+#define S5P_FIMV_H2R_CMD_CLOSE_INSTANCE_V6     6
+#define S5P_FIMV_H2R_CMD_SLEEP_V6              7
+#define S5P_FIMV_H2R_CMD_WAKEUP_V6             8
+#define S5P_FIMV_CH_LAST_FRAME_V6              9
+#define S5P_FIMV_H2R_CMD_FLUSH_V6              10
+/* RMVME: REALLOC used? */
+#define S5P_FIMV_CH_FRAME_START_REALLOC_V6     5
+
+#define S5P_FIMV_RISC2HOST_CMD_V6              0x1104
+#define S5P_FIMV_R2H_CMD_EMPTY_V6              0
+#define S5P_FIMV_R2H_CMD_SYS_INIT_RET_V6       1
+#define S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET_V6  2
+#define S5P_FIMV_R2H_CMD_SEQ_DONE_RET_V6       3
+#define S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET_V6   4
+
+#define S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET_V6 6
+#define S5P_FIMV_R2H_CMD_SLEEP_RET_V6          7
+#define S5P_FIMV_R2H_CMD_WAKEUP_RET_V6         8
+#define S5P_FIMV_R2H_CMD_COMPLETE_SEQ_RET_V6   9
+#define S5P_FIMV_R2H_CMD_DPB_FLUSH_RET_V6      10
+#define S5P_FIMV_R2H_CMD_NAL_ABORT_RET_V6      11
+#define S5P_FIMV_R2H_CMD_FW_STATUS_RET_V6      12
+#define S5P_FIMV_R2H_CMD_FRAME_DONE_RET_V6     13
+#define S5P_FIMV_R2H_CMD_FIELD_DONE_RET_V6     14
+#define S5P_FIMV_R2H_CMD_SLICE_DONE_RET_V6     15
+#define S5P_FIMV_R2H_CMD_ENC_BUFFER_FUL_RET_V6 16
+#define S5P_FIMV_R2H_CMD_ERR_RET_V6            32
+
+#define S5P_FIMV_MFC_BUS_RESET_CTRL            0x7110
+#define S5P_FIMV_FW_VERSION_V6                 0xf000
+
+#define S5P_FIMV_INSTANCE_ID_V6                        0xf008
+#define S5P_FIMV_CODEC_TYPE_V6                 0xf00c
+#define S5P_FIMV_CONTEXT_MEM_ADDR_V6           0xf014
+#define S5P_FIMV_CONTEXT_MEM_SIZE_V6           0xf018
+#define S5P_FIMV_PIXEL_FORMAT_V6               0xf020
+
+#define S5P_FIMV_METADATA_ENABLE_V6            0xf024
+#define S5P_FIMV_DBG_BUFFER_ADDR_V6            0xf030
+#define S5P_FIMV_DBG_BUFFER_SIZE_V6            0xf034
+#define S5P_FIMV_RET_INSTANCE_ID_V6            0xf070
+
+#define S5P_FIMV_ERROR_CODE_V6                 0xf074
+#define S5P_FIMV_ERR_WARNINGS_START_V6         160
+#define S5P_FIMV_ERR_DEC_MASK_V6               0xffff
+#define S5P_FIMV_ERR_DEC_SHIFT_V6              0
+#define S5P_FIMV_ERR_DSPL_MASK_V6              0xffff0000
+#define S5P_FIMV_ERR_DSPL_SHIFT_V6             16
+
+#define S5P_FIMV_DBG_BUFFER_OUTPUT_SIZE_V6     0xf078
+#define S5P_FIMV_METADATA_STATUS_V6            0xf07C
+#define S5P_FIMV_METADATA_ADDR_MB_INFO_V6      0xf080
+#define S5P_FIMV_METADATA_SIZE_MB_INFO_V6      0xf084
+
+/* Decoder Registers */
+#define S5P_FIMV_D_CRC_CTRL_V6                 0xf0b0
+#define S5P_FIMV_D_DEC_OPTIONS_V6              0xf0b4
+#define S5P_FIMV_D_OPT_FMO_ASO_CTRL_MASK_V6    4
+#define S5P_FIMV_D_OPT_DDELAY_EN_SHIFT_V6      3
+#define S5P_FIMV_D_OPT_LF_CTRL_SHIFT_V6                1
+#define S5P_FIMV_D_OPT_LF_CTRL_MASK_V6         0x3
+#define S5P_FIMV_D_OPT_TILE_MODE_SHIFT_V6      0
+
+#define S5P_FIMV_D_DISPLAY_DELAY_V6            0xf0b8
+
+#define S5P_FIMV_D_SET_FRAME_WIDTH_V6          0xf0bc
+#define S5P_FIMV_D_SET_FRAME_HEIGHT_V6         0xf0c0
+
+#define S5P_FIMV_D_SEI_ENABLE_V6               0xf0c4
+
+/* Buffer setting registers */
+#define S5P_FIMV_D_MIN_NUM_DPB_V6              0xf0f0
+#define S5P_FIMV_D_MIN_LUMA_DPB_SIZE_V6                0xf0f4
+#define S5P_FIMV_D_MIN_CHROMA_DPB_SIZE_V6      0xf0f8
+#define S5P_FIMV_D_MVC_NUM_VIEWS_V6            0xf0fc
+#define S5P_FIMV_D_MIN_NUM_MV_V6               0xf100
+#define S5P_FIMV_D_NUM_DPB_V6                  0xf130
+#define S5P_FIMV_D_LUMA_DPB_SIZE_V6            0xf134
+#define S5P_FIMV_D_CHROMA_DPB_SIZE_V6          0xf138
+#define S5P_FIMV_D_MV_BUFFER_SIZE_V6           0xf13c
+
+#define S5P_FIMV_D_LUMA_DPB_V6                 0xf140
+#define S5P_FIMV_D_CHROMA_DPB_V6               0xf240
+#define S5P_FIMV_D_MV_BUFFER_V6                        0xf340
+
+#define S5P_FIMV_D_SCRATCH_BUFFER_ADDR_V6      0xf440
+#define S5P_FIMV_D_SCRATCH_BUFFER_SIZE_V6      0xf444
+#define S5P_FIMV_D_METADATA_BUFFER_ADDR_V6     0xf448
+#define S5P_FIMV_D_METADATA_BUFFER_SIZE_V6     0xf44c
+#define S5P_FIMV_D_NUM_MV_V6                   0xf478
+#define S5P_FIMV_D_CPB_BUFFER_ADDR_V6          0xf4b0
+#define S5P_FIMV_D_CPB_BUFFER_SIZE_V6          0xf4b4
+
+#define S5P_FIMV_D_AVAILABLE_DPB_FLAG_UPPER_V6 0xf4b8
+#define S5P_FIMV_D_AVAILABLE_DPB_FLAG_LOWER_V6 0xf4bc
+#define S5P_FIMV_D_CPB_BUFFER_OFFSET_V6                0xf4c0
+#define S5P_FIMV_D_SLICE_IF_ENABLE_V6          0xf4c4
+#define S5P_FIMV_D_PICTURE_TAG_V6              0xf4c8
+#define S5P_FIMV_D_STREAM_DATA_SIZE_V6         0xf4d0
+#define S5P_FIMV_D_INIT_BUFFER_OPTIONS_V6      0xf47c
+
+/* Display information register */
+#define S5P_FIMV_D_DISPLAY_FRAME_WIDTH_V6      0xf500
+#define S5P_FIMV_D_DISPLAY_FRAME_HEIGHT_V6     0xf504
+
+/* Display status */
+#define S5P_FIMV_D_DISPLAY_STATUS_V6           0xf508
+
+#define S5P_FIMV_D_DISPLAY_LUMA_ADDR_V6                0xf50c
+#define S5P_FIMV_D_DISPLAY_CHROMA_ADDR_V6      0xf510
+
+#define S5P_FIMV_D_DISPLAY_FRAME_TYPE_V6       0xf514
+
+#define S5P_FIMV_D_DISPLAY_CROP_INFO1_V6       0xf518
+#define S5P_FIMV_D_DISPLAY_CROP_INFO2_V6       0xf51c
+#define S5P_FIMV_D_DISPLAY_PICTURE_PROFILE_V6  0xf520
+#define S5P_FIMV_D_DISPLAY_LUMA_CRC_TOP_V6     0xf524
+#define S5P_FIMV_D_DISPLAY_CHROMA_CRC_TOP_V6   0xf528
+#define S5P_FIMV_D_DISPLAY_LUMA_CRC_BOT_V6     0xf52c
+#define S5P_FIMV_D_DISPLAY_CHROMA_CRC_BOT_V6   0xf530
+#define S5P_FIMV_D_DISPLAY_ASPECT_RATIO_V6     0xf534
+#define S5P_FIMV_D_DISPLAY_EXTENDED_AR_V6      0xf538
+
+/* Decoded picture information register */
+#define S5P_FIMV_D_DECODED_FRAME_WIDTH_V6      0xf53c
+#define S5P_FIMV_D_DECODED_FRAME_HEIGHT_V6     0xf540
+#define S5P_FIMV_D_DECODED_STATUS_V6           0xf544
+#define S5P_FIMV_DEC_CRC_GEN_MASK_V6           0x1
+#define S5P_FIMV_DEC_CRC_GEN_SHIFT_V6          6
+
+#define S5P_FIMV_D_DECODED_LUMA_ADDR_V6                0xf548
+#define S5P_FIMV_D_DECODED_CHROMA_ADDR_V6      0xf54c
+
+#define S5P_FIMV_D_DECODED_FRAME_TYPE_V6       0xf550
+#define S5P_FIMV_DECODE_FRAME_MASK_V6          7
+
+#define S5P_FIMV_D_DECODED_CROP_INFO1_V6       0xf554
+#define S5P_FIMV_D_DECODED_CROP_INFO2_V6       0xf558
+#define S5P_FIMV_D_DECODED_PICTURE_PROFILE_V6  0xf55c
+#define S5P_FIMV_D_DECODED_NAL_SIZE_V6         0xf560
+#define S5P_FIMV_D_DECODED_LUMA_CRC_TOP_V6     0xf564
+#define S5P_FIMV_D_DECODED_CHROMA_CRC_TOP_V6   0xf568
+#define S5P_FIMV_D_DECODED_LUMA_CRC_BOT_V6     0xf56c
+#define S5P_FIMV_D_DECODED_CHROMA_CRC_BOT_V6   0xf570
+
+/* Returned value register for specific setting */
+#define S5P_FIMV_D_RET_PICTURE_TAG_TOP_V6              0xf574
+#define S5P_FIMV_D_RET_PICTURE_TAG_BOT_V6              0xf578
+#define S5P_FIMV_D_RET_PICTURE_TIME_TOP_V6             0xf57c
+#define S5P_FIMV_D_RET_PICTURE_TIME_BOT_V6             0xf580
+#define S5P_FIMV_D_CHROMA_FORMAT_V6                    0xf588
+#define S5P_FIMV_D_MPEG4_INFO_V6                       0xf58c
+#define S5P_FIMV_D_H264_INFO_V6                                0xf590
+
+#define S5P_FIMV_D_METADATA_ADDR_CONCEALED_MB_V6       0xf594
+#define S5P_FIMV_D_METADATA_SIZE_CONCEALED_MB_V6       0xf598
+#define S5P_FIMV_D_METADATA_ADDR_VC1_PARAM_V6          0xf59c
+#define S5P_FIMV_D_METADATA_SIZE_VC1_PARAM_V6          0xf5a0
+#define S5P_FIMV_D_METADATA_ADDR_SEI_NAL_V6            0xf5a4
+#define S5P_FIMV_D_METADATA_SIZE_SEI_NAL_V6            0xf5a8
+#define S5P_FIMV_D_METADATA_ADDR_VUI_V6                        0xf5ac
+#define S5P_FIMV_D_METADATA_SIZE_VUI_V6                        0xf5b0
+
+#define S5P_FIMV_D_MVC_VIEW_ID_V6              0xf5b4
+
+/* SEI related information */
+#define S5P_FIMV_D_FRAME_PACK_SEI_AVAIL_V6     0xf5f0
+#define S5P_FIMV_D_FRAME_PACK_ARRGMENT_ID_V6   0xf5f4
+#define S5P_FIMV_D_FRAME_PACK_SEI_INFO_V6      0xf5f8
+#define S5P_FIMV_D_FRAME_PACK_GRID_POS_V6      0xf5fc
+
+/* Encoder Registers */
+#define S5P_FIMV_E_FRAME_WIDTH_V6              0xf770
+#define S5P_FIMV_E_FRAME_HEIGHT_V6             0xf774
+#define S5P_FIMV_E_CROPPED_FRAME_WIDTH_V6      0xf778
+#define S5P_FIMV_E_CROPPED_FRAME_HEIGHT_V6     0xf77c
+#define S5P_FIMV_E_FRAME_CROP_OFFSET_V6                0xf780
+#define S5P_FIMV_E_ENC_OPTIONS_V6              0xf784
+#define S5P_FIMV_E_PICTURE_PROFILE_V6          0xf788
+#define S5P_FIMV_E_FIXED_PICTURE_QP_V6         0xf790
+
+#define S5P_FIMV_E_RC_CONFIG_V6                        0xf794
+#define S5P_FIMV_E_RC_QP_BOUND_V6              0xf798
+#define S5P_FIMV_E_RC_RPARAM_V6                        0xf79c
+#define S5P_FIMV_E_MB_RC_CONFIG_V6             0xf7a0
+#define S5P_FIMV_E_PADDING_CTRL_V6             0xf7a4
+#define S5P_FIMV_E_MV_HOR_RANGE_V6             0xf7ac
+#define S5P_FIMV_E_MV_VER_RANGE_V6             0xf7b0
+#define S5P_FIMV_E_MV_RANGE_V6_MASK            0x3fff
+
+#define S5P_FIMV_E_VBV_BUFFER_SIZE_V6          0xf84c
+#define S5P_FIMV_E_VBV_INIT_DELAY_V6           0xf850
+#define S5P_FIMV_E_NUM_DPB_V6                  0xf890
+#define S5P_FIMV_E_LUMA_DPB_V6                 0xf8c0
+#define S5P_FIMV_E_CHROMA_DPB_V6               0xf904
+#define S5P_FIMV_E_ME_BUFFER_V6                        0xf948
+
+#define S5P_FIMV_E_SCRATCH_BUFFER_ADDR_V6      0xf98c
+#define S5P_FIMV_E_SCRATCH_BUFFER_SIZE_V6      0xf990
+#define S5P_FIMV_E_TMV_BUFFER0_V6              0xf994
+#define S5P_FIMV_E_TMV_BUFFER1_V6              0xf998
+#define S5P_FIMV_E_SOURCE_LUMA_ADDR_V6         0xf9f0
+#define S5P_FIMV_E_SOURCE_CHROMA_ADDR_V6       0xf9f4
+#define S5P_FIMV_E_STREAM_BUFFER_ADDR_V6       0xf9f8
+#define S5P_FIMV_E_STREAM_BUFFER_SIZE_V6       0xf9fc
+#define S5P_FIMV_E_ROI_BUFFER_ADDR_V6          0xfA00
+
+#define S5P_FIMV_E_PARAM_CHANGE_V6             0xfa04
+#define S5P_FIMV_E_IR_SIZE_V6                  0xfa08
+#define S5P_FIMV_E_GOP_CONFIG_V6               0xfa0c
+#define S5P_FIMV_E_MSLICE_MODE_V6              0xfa10
+#define S5P_FIMV_E_MSLICE_SIZE_MB_V6           0xfa14
+#define S5P_FIMV_E_MSLICE_SIZE_BITS_V6         0xfa18
+#define S5P_FIMV_E_FRAME_INSERTION_V6          0xfa1c
+
+#define S5P_FIMV_E_RC_FRAME_RATE_V6            0xfa20
+#define S5P_FIMV_E_RC_BIT_RATE_V6              0xfa24
+#define S5P_FIMV_E_RC_QP_OFFSET_V6             0xfa28
+#define S5P_FIMV_E_RC_ROI_CTRL_V6              0xfa2c
+#define S5P_FIMV_E_PICTURE_TAG_V6              0xfa30
+#define S5P_FIMV_E_BIT_COUNT_ENABLE_V6         0xfa34
+#define S5P_FIMV_E_MAX_BIT_COUNT_V6            0xfa38
+#define S5P_FIMV_E_MIN_BIT_COUNT_V6            0xfa3c
+
+#define S5P_FIMV_E_METADATA_BUFFER_ADDR_V6             0xfa40
+#define S5P_FIMV_E_METADATA_BUFFER_SIZE_V6             0xfa44
+#define S5P_FIMV_E_STREAM_SIZE_V6                      0xfa80
+#define S5P_FIMV_E_SLICE_TYPE_V6                       0xfa84
+#define S5P_FIMV_E_PICTURE_COUNT_V6                    0xfa88
+#define S5P_FIMV_E_RET_PICTURE_TAG_V6                  0xfa8c
+#define S5P_FIMV_E_STREAM_BUFFER_WRITE_POINTER_V6      0xfa90
+
+#define S5P_FIMV_E_ENCODED_SOURCE_LUMA_ADDR_V6         0xfa94
+#define S5P_FIMV_E_ENCODED_SOURCE_CHROMA_ADDR_V6       0xfa98
+#define S5P_FIMV_E_RECON_LUMA_DPB_ADDR_V6              0xfa9c
+#define S5P_FIMV_E_RECON_CHROMA_DPB_ADDR_V6            0xfaa0
+#define S5P_FIMV_E_METADATA_ADDR_ENC_SLICE_V6          0xfaa4
+#define S5P_FIMV_E_METADATA_SIZE_ENC_SLICE_V6          0xfaa8
+
+#define S5P_FIMV_E_MPEG4_OPTIONS_V6            0xfb10
+#define S5P_FIMV_E_MPEG4_HEC_PERIOD_V6         0xfb14
+#define S5P_FIMV_E_ASPECT_RATIO_V6             0xfb50
+#define S5P_FIMV_E_EXTENDED_SAR_V6             0xfb54
+
+#define S5P_FIMV_E_H264_OPTIONS_V6             0xfb58
+#define S5P_FIMV_E_H264_LF_ALPHA_OFFSET_V6     0xfb5c
+#define S5P_FIMV_E_H264_LF_BETA_OFFSET_V6      0xfb60
+#define S5P_FIMV_E_H264_I_PERIOD_V6            0xfb64
+
+#define S5P_FIMV_E_H264_FMO_SLICE_GRP_MAP_TYPE_V6              0xfb68
+#define S5P_FIMV_E_H264_FMO_NUM_SLICE_GRP_MINUS1_V6            0xfb6c
+#define S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_DIR_V6            0xfb70
+#define S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_RATE_MINUS1_V6    0xfb74
+#define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_0_V6             0xfb78
+#define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_1_V6             0xfb7c
+#define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_2_V6             0xfb80
+#define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_3_V6             0xfb84
+
+#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_0_V6   0xfb88
+#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_1_V6   0xfb8c
+#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_2_V6   0xfb90
+#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_3_V6   0xfb94
+#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_4_V6   0xfb98
+#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_5_V6   0xfb9c
+#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_6_V6   0xfba0
+#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_7_V6   0xfba4
+
+#define S5P_FIMV_E_H264_CHROMA_QP_OFFSET_V6    0xfba8
+#define S5P_FIMV_E_H264_NUM_T_LAYER_V6         0xfbac
+
+#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER0_V6      0xfbb0
+#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER1_V6      0xfbb4
+#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER2_V6      0xfbb8
+#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER3_V6      0xfbbc
+#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER4_V6      0xfbc0
+#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER5_V6      0xfbc4
+#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER6_V6      0xfbc8
+
+#define S5P_FIMV_E_H264_FRAME_PACKING_SEI_INFO_V6              0xfc4c
+#define S5P_FIMV_ENC_FP_ARRANGEMENT_TYPE_SIDE_BY_SIDE_V6       0
+#define S5P_FIMV_ENC_FP_ARRANGEMENT_TYPE_TOP_BOTTOM_V6         1
+#define S5P_FIMV_ENC_FP_ARRANGEMENT_TYPE_TEMPORAL_V6           2
+
+#define S5P_FIMV_E_MVC_FRAME_QP_VIEW1_V6               0xfd40
+#define S5P_FIMV_E_MVC_RC_FRAME_RATE_VIEW1_V6          0xfd44
+#define S5P_FIMV_E_MVC_RC_BIT_RATE_VIEW1_V6            0xfd48
+#define S5P_FIMV_E_MVC_RC_QBOUND_VIEW1_V6              0xfd4c
+#define S5P_FIMV_E_MVC_RC_RPARA_VIEW1_V6               0xfd50
+#define S5P_FIMV_E_MVC_INTER_VIEW_PREDICTION_ON_V6     0xfd80
+
+/* Codec numbers  */
+#define S5P_FIMV_CODEC_NONE_V6         -1
+
+
+#define S5P_FIMV_CODEC_H264_DEC_V6     0
+#define S5P_FIMV_CODEC_H264_MVC_DEC_V6 1
+
+#define S5P_FIMV_CODEC_MPEG4_DEC_V6    3
+#define S5P_FIMV_CODEC_FIMV1_DEC_V6    4
+#define S5P_FIMV_CODEC_FIMV2_DEC_V6    5
+#define S5P_FIMV_CODEC_FIMV3_DEC_V6    6
+#define S5P_FIMV_CODEC_FIMV4_DEC_V6    7
+#define S5P_FIMV_CODEC_H263_DEC_V6     8
+#define S5P_FIMV_CODEC_VC1RCV_DEC_V6   9
+#define S5P_FIMV_CODEC_VC1_DEC_V6      10
+/* FIXME: Add 11~12 */
+#define S5P_FIMV_CODEC_MPEG2_DEC_V6    13
+#define S5P_FIMV_CODEC_VP8_DEC_V6      14
+/* FIXME: Add 15~16 */
+#define S5P_FIMV_CODEC_H264_ENC_V6     20
+#define S5P_FIMV_CODEC_H264_MVC_ENC_V6 21
+
+#define S5P_FIMV_CODEC_MPEG4_ENC_V6    23
+#define S5P_FIMV_CODEC_H263_ENC_V6     24
+
+#define S5P_FIMV_NV12M_HALIGN_V6               16
+#define S5P_FIMV_NV12MT_HALIGN_V6              16
+#define S5P_FIMV_NV12MT_VALIGN_V6              16
+
+#define S5P_FIMV_TMV_BUFFER_ALIGN_V6           16
+#define S5P_FIMV_LUMA_DPB_BUFFER_ALIGN_V6      256
+#define S5P_FIMV_CHROMA_DPB_BUFFER_ALIGN_V6    256
+#define S5P_FIMV_ME_BUFFER_ALIGN_V6            256
+#define S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6       256
+
+#define S5P_FIMV_LUMA_MB_TO_PIXEL_V6           256
+#define S5P_FIMV_CHROMA_MB_TO_PIXEL_V6         128
+#define S5P_FIMV_NUM_TMV_BUFFERS_V6            2
+
+#define S5P_FIMV_MAX_FRAME_SIZE_V6             (2 * SZ_1M)
+#define S5P_FIMV_NUM_PIXELS_IN_MB_ROW_V6       16
+#define S5P_FIMV_NUM_PIXELS_IN_MB_COL_V6       16
+
+/* Buffer size requirements defined by hardware */
+#define S5P_FIMV_TMV_BUFFER_SIZE_V6(w, h)      (((w) + 1) * ((h) + 3) * 8)
+#define S5P_FIMV_ME_BUFFER_SIZE_V6(imw, imh, mbw, mbh) \
+       (((((imw + 127) / 64) * 16) *  DIV_ROUND_UP(imh, 64) * 256) + \
+        (DIV_ROUND_UP((mbw) * (mbh), 32) * 16))
+#define S5P_FIMV_SCRATCH_BUF_SIZE_H264_DEC_V6(w, h)    (((w) * 192) + 64)
+#define S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_DEC_V6(w, h) \
+                       ((w) * 144 + 8192 * (h) + 49216 + 1048576)
+#define S5P_FIMV_SCRATCH_BUF_SIZE_VC1_DEC_V6(w, h) \
+                                               (2096 * ((w) + (h) + 1))
+#define S5P_FIMV_SCRATCH_BUF_SIZE_H263_DEC_V6(w, h)    \
+                       S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_DEC_V6(w, h)
+#define S5P_FIMV_SCRATCH_BUF_SIZE_VP8_DEC_V6(w, h) \
+                       ((w) * 32 + (h) * 128 + (((w) + 1) / 2) * 64 + 2112)
+#define S5P_FIMV_SCRATCH_BUF_SIZE_H264_ENC_V6(w, h) \
+                       (((w) * 64) + (((w) + 1) * 16) + (4096 * 16))
+#define S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_ENC_V6(w, h) \
+                       (((w) * 16) + (((w) + 1) * 16))
+
+/* MFC Context buffer sizes */
+#define MFC_CTX_BUF_SIZE_V6            (28 * SZ_1K)    /*  28KB */
+#define MFC_H264_DEC_CTX_BUF_SIZE_V6   (2 * SZ_1M)     /*  2MB */
+#define MFC_OTHER_DEC_CTX_BUF_SIZE_V6  (20 * SZ_1K)    /*  20KB */
+#define MFC_H264_ENC_CTX_BUF_SIZE_V6   (100 * SZ_1K)   /* 100KB */
+#define MFC_OTHER_ENC_CTX_BUF_SIZE_V6  (12 * SZ_1K)    /*  12KB */
+
+/* MFCv6 variant defines */
+#define MAX_FW_SIZE_V6                 (SZ_512K)       /* 512KB */
+#define MAX_CPB_SIZE_V6                        (3 * SZ_1M)     /* 3MB */
+#define MFC_VERSION_V6                 0x61
+#define MFC_NUM_PORTS_V6               1
+
+#endif /* _REGS_FIMV_V6_H */
diff --git a/drivers/media/platform/samsung/s5p-mfc/regs-mfc-v7.h b/drivers/media/platform/samsung/s5p-mfc/regs-mfc-v7.h
new file mode 100644 (file)
index 0000000..4a7adfd
--- /dev/null
@@ -0,0 +1,57 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Register definition file for Samsung MFC V7.x Interface (FIMV) driver
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ */
+
+#ifndef _REGS_MFC_V7_H
+#define _REGS_MFC_V7_H
+
+#include "regs-mfc-v6.h"
+
+/* Additional features of v7 */
+#define S5P_FIMV_CODEC_VP8_ENC_V7      25
+
+/* Additional registers for v7 */
+#define S5P_FIMV_E_SOURCE_FIRST_ADDR_V7                        0xf9e0
+#define S5P_FIMV_E_SOURCE_SECOND_ADDR_V7               0xf9e4
+#define S5P_FIMV_E_SOURCE_THIRD_ADDR_V7                        0xf9e8
+#define S5P_FIMV_E_SOURCE_FIRST_STRIDE_V7              0xf9ec
+#define S5P_FIMV_E_SOURCE_SECOND_STRIDE_V7             0xf9f0
+#define S5P_FIMV_E_SOURCE_THIRD_STRIDE_V7              0xf9f4
+
+#define S5P_FIMV_E_ENCODED_SOURCE_FIRST_ADDR_V7                0xfa70
+#define S5P_FIMV_E_ENCODED_SOURCE_SECOND_ADDR_V7       0xfa74
+
+#define S5P_FIMV_E_VP8_OPTIONS_V7                      0xfdb0
+#define S5P_FIMV_E_VP8_FILTER_OPTIONS_V7               0xfdb4
+#define S5P_FIMV_E_VP8_GOLDEN_FRAME_OPTION_V7          0xfdb8
+#define S5P_FIMV_E_VP8_NUM_T_LAYER_V7                  0xfdc4
+
+/* MFCv7 variant defines */
+#define MAX_FW_SIZE_V7                 (SZ_512K)       /* 512KB */
+#define MAX_CPB_SIZE_V7                        (3 * SZ_1M)     /* 3MB */
+#define MFC_VERSION_V7                 0x72
+#define MFC_NUM_PORTS_V7               1
+
+#define MFC_LUMA_PAD_BYTES_V7          256
+#define MFC_CHROMA_PAD_BYTES_V7                128
+
+/* MFCv7 Context buffer sizes */
+#define MFC_CTX_BUF_SIZE_V7            (30 * SZ_1K)    /*  30KB */
+#define MFC_H264_DEC_CTX_BUF_SIZE_V7   (2 * SZ_1M)     /*  2MB */
+#define MFC_OTHER_DEC_CTX_BUF_SIZE_V7  (20 * SZ_1K)    /*  20KB */
+#define MFC_H264_ENC_CTX_BUF_SIZE_V7   (100 * SZ_1K)   /* 100KB */
+#define MFC_OTHER_ENC_CTX_BUF_SIZE_V7  (10 * SZ_1K)    /*  10KB */
+
+/* Buffer size defines */
+#define S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_DEC_V7(w, h) \
+                       (SZ_1M + ((w) * 144) + (8192 * (h)) + 49216)
+
+#define S5P_FIMV_SCRATCH_BUF_SIZE_VP8_ENC_V7(w, h) \
+                       (((w) * 48) + 8192 + ((((w) + 1) / 2) * 128) + 144 + \
+                       ((((((w) * 16) * ((h) * 16)) * 3) / 2) * 4))
+
+#endif /*_REGS_MFC_V7_H*/
diff --git a/drivers/media/platform/samsung/s5p-mfc/regs-mfc-v8.h b/drivers/media/platform/samsung/s5p-mfc/regs-mfc-v8.h
new file mode 100644 (file)
index 0000000..162e3c7
--- /dev/null
@@ -0,0 +1,123 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Register definition file for Samsung MFC V8.x Interface (FIMV) driver
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ */
+
+#ifndef _REGS_MFC_V8_H
+#define _REGS_MFC_V8_H
+
+#include <linux/sizes.h>
+#include "regs-mfc-v7.h"
+
+/* Additional registers for v8 */
+#define S5P_FIMV_D_MVC_NUM_VIEWS_V8            0xf104
+#define S5P_FIMV_D_MIN_SCRATCH_BUFFER_SIZE_V8  0xf108
+#define S5P_FIMV_D_FIRST_PLANE_DPB_SIZE_V8     0xf144
+#define S5P_FIMV_D_SECOND_PLANE_DPB_SIZE_V8    0xf148
+#define S5P_FIMV_D_MV_BUFFER_SIZE_V8           0xf150
+
+#define S5P_FIMV_D_FIRST_PLANE_DPB_STRIDE_SIZE_V8      0xf138
+#define S5P_FIMV_D_SECOND_PLANE_DPB_STRIDE_SIZE_V8     0xf13c
+
+#define S5P_FIMV_D_FIRST_PLANE_DPB_V8          0xf160
+#define S5P_FIMV_D_SECOND_PLANE_DPB_V8         0xf260
+#define S5P_FIMV_D_MV_BUFFER_V8                        0xf460
+
+#define S5P_FIMV_D_NUM_MV_V8                   0xf134
+#define S5P_FIMV_D_INIT_BUFFER_OPTIONS_V8      0xf154
+
+#define S5P_FIMV_D_SCRATCH_BUFFER_ADDR_V8      0xf560
+#define S5P_FIMV_D_SCRATCH_BUFFER_SIZE_V8      0xf564
+
+#define S5P_FIMV_D_CPB_BUFFER_ADDR_V8          0xf5b0
+#define S5P_FIMV_D_CPB_BUFFER_SIZE_V8          0xf5b4
+#define S5P_FIMV_D_AVAILABLE_DPB_FLAG_LOWER_V8 0xf5bc
+#define S5P_FIMV_D_CPB_BUFFER_OFFSET_V8                0xf5c0
+#define S5P_FIMV_D_SLICE_IF_ENABLE_V8          0xf5c4
+#define S5P_FIMV_D_STREAM_DATA_SIZE_V8         0xf5d0
+
+/* Display information register */
+#define S5P_FIMV_D_DISPLAY_FRAME_WIDTH_V8      0xf600
+#define S5P_FIMV_D_DISPLAY_FRAME_HEIGHT_V8     0xf604
+
+/* Display status */
+#define S5P_FIMV_D_DISPLAY_STATUS_V8           0xf608
+
+#define S5P_FIMV_D_DISPLAY_FIRST_PLANE_ADDR_V8 0xf60c
+#define S5P_FIMV_D_DISPLAY_SECOND_PLANE_ADDR_V8        0xf610
+
+#define S5P_FIMV_D_DISPLAY_FRAME_TYPE_V8       0xf618
+#define S5P_FIMV_D_DISPLAY_CROP_INFO1_V8       0xf61c
+#define S5P_FIMV_D_DISPLAY_CROP_INFO2_V8       0xf620
+#define S5P_FIMV_D_DISPLAY_PICTURE_PROFILE_V8  0xf624
+
+/* Decoded picture information register */
+#define S5P_FIMV_D_DECODED_STATUS_V8           0xf644
+#define S5P_FIMV_D_DECODED_FIRST_PLANE_ADDR_V8 0xf648
+#define S5P_FIMV_D_DECODED_SECOND_PLANE_ADDR_V8        0xf64c
+#define S5P_FIMV_D_DECODED_THIRD_PLANE_ADDR_V8 0xf650
+#define S5P_FIMV_D_DECODED_FRAME_TYPE_V8       0xf654
+#define S5P_FIMV_D_DECODED_NAL_SIZE_V8          0xf664
+
+/* Returned value register for specific setting */
+#define S5P_FIMV_D_RET_PICTURE_TAG_TOP_V8      0xf674
+#define S5P_FIMV_D_RET_PICTURE_TAG_BOT_V8      0xf678
+#define S5P_FIMV_D_MVC_VIEW_ID_V8              0xf6d8
+
+/* SEI related information */
+#define S5P_FIMV_D_FRAME_PACK_SEI_AVAIL_V8     0xf6dc
+
+/* Encoder Registers */
+#define S5P_FIMV_E_FIXED_PICTURE_QP_V8         0xf794
+#define S5P_FIMV_E_RC_CONFIG_V8                        0xf798
+#define S5P_FIMV_E_RC_QP_BOUND_V8              0xf79c
+#define S5P_FIMV_E_RC_RPARAM_V8                        0xf7a4
+#define S5P_FIMV_E_MB_RC_CONFIG_V8             0xf7a8
+#define S5P_FIMV_E_PADDING_CTRL_V8             0xf7ac
+#define S5P_FIMV_E_MV_HOR_RANGE_V8             0xf7b4
+#define S5P_FIMV_E_MV_VER_RANGE_V8             0xf7b8
+
+#define S5P_FIMV_E_VBV_BUFFER_SIZE_V8          0xf78c
+#define S5P_FIMV_E_VBV_INIT_DELAY_V8           0xf790
+#define S5P_FIMV_E_MIN_SCRATCH_BUFFER_SIZE_V8   0xf894
+
+#define S5P_FIMV_E_ASPECT_RATIO_V8             0xfb4c
+#define S5P_FIMV_E_EXTENDED_SAR_V8             0xfb50
+#define S5P_FIMV_E_H264_OPTIONS_V8             0xfb54
+
+/* MFCv8 Context buffer sizes */
+#define MFC_CTX_BUF_SIZE_V8            (36 * SZ_1K)    /*  36KB */
+#define MFC_H264_DEC_CTX_BUF_SIZE_V8   (2 * SZ_1M)     /*  2MB */
+#define MFC_OTHER_DEC_CTX_BUF_SIZE_V8  (20 * SZ_1K)    /*  20KB */
+#define MFC_H264_ENC_CTX_BUF_SIZE_V8   (100 * SZ_1K)   /* 100KB */
+#define MFC_OTHER_ENC_CTX_BUF_SIZE_V8  (10 * SZ_1K)    /*  10KB */
+
+/* Buffer size defines */
+#define S5P_FIMV_TMV_BUFFER_SIZE_V8(w, h)      (((w) + 1) * ((h) + 1) * 8)
+
+#define S5P_FIMV_SCRATCH_BUF_SIZE_H264_DEC_V8(w, h)    (((w) * 704) + 2176)
+#define S5P_FIMV_SCRATCH_BUF_SIZE_VP8_DEC_V8(w, h) \
+               (((w) * 576 + (h) * 128)  + 4128)
+
+#define S5P_FIMV_SCRATCH_BUF_SIZE_H264_ENC_V8(w, h) \
+                       (((w) * 592) + 2336)
+#define S5P_FIMV_SCRATCH_BUF_SIZE_VP8_ENC_V8(w, h) \
+                       (((w) * 576) + 10512 + \
+                       ((((((w) * 16) * ((h) * 16)) * 3) / 2) * 4))
+#define S5P_FIMV_ME_BUFFER_SIZE_V8(imw, imh, mbw, mbh) \
+       ((DIV_ROUND_UP((mbw * 16), 64) *  DIV_ROUND_UP((mbh * 16), 64) * 256) \
+        + (DIV_ROUND_UP((mbw) * (mbh), 32) * 16))
+
+/* BUffer alignment defines */
+#define S5P_FIMV_D_ALIGN_PLANE_SIZE_V8 64
+
+/* MFCv8 variant defines */
+#define MAX_FW_SIZE_V8                 (SZ_512K)       /* 512KB */
+#define MAX_CPB_SIZE_V8                        (3 * SZ_1M)     /* 3MB */
+#define MFC_VERSION_V8                 0x80
+#define MFC_NUM_PORTS_V8               1
+
+#endif /*_REGS_MFC_V8_H*/
diff --git a/drivers/media/platform/samsung/s5p-mfc/regs-mfc.h b/drivers/media/platform/samsung/s5p-mfc/regs-mfc.h
new file mode 100644 (file)
index 0000000..9171e81
--- /dev/null
@@ -0,0 +1,459 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Register definition file for Samsung MFC V5.1 Interface (FIMV) driver
+ *
+ * Kamil Debski, Copyright (c) 2010 Samsung Electronics
+ * http://www.samsung.com/
+*/
+
+#ifndef _REGS_FIMV_H
+#define _REGS_FIMV_H
+
+#include <linux/kernel.h>
+#include <linux/sizes.h>
+
+#define S5P_FIMV_REG_SIZE      (S5P_FIMV_END_ADDR - S5P_FIMV_START_ADDR)
+#define S5P_FIMV_REG_COUNT     ((S5P_FIMV_END_ADDR - S5P_FIMV_START_ADDR) / 4)
+
+/* Number of bits that the buffer address should be shifted for particular
+ * MFC buffers.  */
+#define S5P_FIMV_START_ADDR            0x0000
+#define S5P_FIMV_END_ADDR              0xe008
+
+#define S5P_FIMV_SW_RESET              0x0000
+#define S5P_FIMV_RISC_HOST_INT         0x0008
+
+/* Command from HOST to RISC */
+#define S5P_FIMV_HOST2RISC_CMD         0x0030
+#define S5P_FIMV_HOST2RISC_ARG1                0x0034
+#define S5P_FIMV_HOST2RISC_ARG2                0x0038
+#define S5P_FIMV_HOST2RISC_ARG3                0x003c
+#define S5P_FIMV_HOST2RISC_ARG4                0x0040
+
+/* Command from RISC to HOST */
+#define S5P_FIMV_RISC2HOST_CMD         0x0044
+#define S5P_FIMV_RISC2HOST_CMD_MASK    0x1FFFF
+#define S5P_FIMV_RISC2HOST_ARG1                0x0048
+#define S5P_FIMV_RISC2HOST_ARG2                0x004c
+#define S5P_FIMV_RISC2HOST_ARG3                0x0050
+#define S5P_FIMV_RISC2HOST_ARG4                0x0054
+
+#define S5P_FIMV_FW_VERSION            0x0058
+#define S5P_FIMV_SYS_MEM_SZ            0x005c
+#define S5P_FIMV_FW_STATUS             0x0080
+
+/* Memory controller register */
+#define S5P_FIMV_MC_DRAMBASE_ADR_A     0x0508
+#define S5P_FIMV_MC_DRAMBASE_ADR_B     0x050c
+#define S5P_FIMV_MC_STATUS             0x0510
+
+/* Common register */
+#define S5P_FIMV_COMMON_BASE_A         0x0600
+#define S5P_FIMV_COMMON_BASE_B         0x0700
+
+/* Decoder */
+#define S5P_FIMV_DEC_CHROMA_ADR                (S5P_FIMV_COMMON_BASE_A)
+#define S5P_FIMV_DEC_LUMA_ADR          (S5P_FIMV_COMMON_BASE_B)
+
+/* H.264 decoding */
+#define S5P_FIMV_H264_VERT_NB_MV_ADR   (S5P_FIMV_COMMON_BASE_A + 0x8c)
+                                       /* vertical neighbor motion vector */
+#define S5P_FIMV_H264_NB_IP_ADR                (S5P_FIMV_COMMON_BASE_A + 0x90)
+                                       /* neighbor pixels for intra pred */
+#define S5P_FIMV_H264_MV_ADR           (S5P_FIMV_COMMON_BASE_B + 0x80)
+                                       /* H264 motion vector */
+
+/* MPEG4 decoding */
+#define S5P_FIMV_MPEG4_NB_DCAC_ADR     (S5P_FIMV_COMMON_BASE_A + 0x8c)
+                                       /* neighbor AC/DC coeff. */
+#define S5P_FIMV_MPEG4_UP_NB_MV_ADR    (S5P_FIMV_COMMON_BASE_A + 0x90)
+                                       /* upper neighbor motion vector */
+#define S5P_FIMV_MPEG4_SA_MV_ADR       (S5P_FIMV_COMMON_BASE_A + 0x94)
+                                       /* subseq. anchor motion vector */
+#define S5P_FIMV_MPEG4_OT_LINE_ADR     (S5P_FIMV_COMMON_BASE_A + 0x98)
+                                       /* overlap transform line */
+#define S5P_FIMV_MPEG4_SP_ADR          (S5P_FIMV_COMMON_BASE_A + 0xa8)
+                                       /* syntax parser */
+
+/* H.263 decoding */
+#define S5P_FIMV_H263_NB_DCAC_ADR      (S5P_FIMV_COMMON_BASE_A + 0x8c)
+#define S5P_FIMV_H263_UP_NB_MV_ADR     (S5P_FIMV_COMMON_BASE_A + 0x90)
+#define S5P_FIMV_H263_SA_MV_ADR                (S5P_FIMV_COMMON_BASE_A + 0x94)
+#define S5P_FIMV_H263_OT_LINE_ADR      (S5P_FIMV_COMMON_BASE_A + 0x98)
+
+/* VC-1 decoding */
+#define S5P_FIMV_VC1_NB_DCAC_ADR       (S5P_FIMV_COMMON_BASE_A + 0x8c)
+#define S5P_FIMV_VC1_UP_NB_MV_ADR      (S5P_FIMV_COMMON_BASE_A + 0x90)
+#define S5P_FIMV_VC1_SA_MV_ADR         (S5P_FIMV_COMMON_BASE_A + 0x94)
+#define S5P_FIMV_VC1_OT_LINE_ADR       (S5P_FIMV_COMMON_BASE_A + 0x98)
+#define S5P_FIMV_VC1_BITPLANE3_ADR     (S5P_FIMV_COMMON_BASE_A + 0x9c)
+                                       /* bitplane3 */
+#define S5P_FIMV_VC1_BITPLANE2_ADR     (S5P_FIMV_COMMON_BASE_A + 0xa0)
+                                       /* bitplane2 */
+#define S5P_FIMV_VC1_BITPLANE1_ADR     (S5P_FIMV_COMMON_BASE_A + 0xa4)
+                                       /* bitplane1 */
+
+/* Encoder */
+#define S5P_FIMV_ENC_REF0_LUMA_ADR     (S5P_FIMV_COMMON_BASE_A + 0x1c)
+#define S5P_FIMV_ENC_REF1_LUMA_ADR     (S5P_FIMV_COMMON_BASE_A + 0x20)
+                                       /* reconstructed luma */
+#define S5P_FIMV_ENC_REF0_CHROMA_ADR   (S5P_FIMV_COMMON_BASE_B)
+#define S5P_FIMV_ENC_REF1_CHROMA_ADR   (S5P_FIMV_COMMON_BASE_B + 0x04)
+                                       /* reconstructed chroma */
+#define S5P_FIMV_ENC_REF2_LUMA_ADR     (S5P_FIMV_COMMON_BASE_B + 0x10)
+#define S5P_FIMV_ENC_REF2_CHROMA_ADR   (S5P_FIMV_COMMON_BASE_B + 0x08)
+#define S5P_FIMV_ENC_REF3_LUMA_ADR     (S5P_FIMV_COMMON_BASE_B + 0x14)
+#define S5P_FIMV_ENC_REF3_CHROMA_ADR   (S5P_FIMV_COMMON_BASE_B + 0x0c)
+
+/* H.264 encoding */
+#define S5P_FIMV_H264_UP_MV_ADR                (S5P_FIMV_COMMON_BASE_A)
+                                       /* upper motion vector */
+#define S5P_FIMV_H264_NBOR_INFO_ADR    (S5P_FIMV_COMMON_BASE_A + 0x04)
+                                       /* entropy engine's neighbor info. */
+#define S5P_FIMV_H264_UP_INTRA_MD_ADR  (S5P_FIMV_COMMON_BASE_A + 0x08)
+                                       /* upper intra MD */
+#define S5P_FIMV_H264_COZERO_FLAG_ADR  (S5P_FIMV_COMMON_BASE_A + 0x10)
+                                       /* direct cozero flag */
+#define S5P_FIMV_H264_UP_INTRA_PRED_ADR        (S5P_FIMV_COMMON_BASE_B + 0x40)
+                                       /* upper intra PRED */
+
+/* H.263 encoding */
+#define S5P_FIMV_H263_UP_MV_ADR                (S5P_FIMV_COMMON_BASE_A)
+                                       /* upper motion vector */
+#define S5P_FIMV_H263_ACDC_COEF_ADR    (S5P_FIMV_COMMON_BASE_A + 0x04)
+                                       /* upper Q coeff. */
+
+/* MPEG4 encoding */
+#define S5P_FIMV_MPEG4_UP_MV_ADR       (S5P_FIMV_COMMON_BASE_A)
+                                       /* upper motion vector */
+#define S5P_FIMV_MPEG4_ACDC_COEF_ADR   (S5P_FIMV_COMMON_BASE_A + 0x04)
+                                       /* upper Q coeff. */
+#define S5P_FIMV_MPEG4_COZERO_FLAG_ADR (S5P_FIMV_COMMON_BASE_A + 0x10)
+                                       /* direct cozero flag */
+
+#define S5P_FIMV_ENC_REF_B_LUMA_ADR     0x062c /* ref B Luma addr */
+#define S5P_FIMV_ENC_REF_B_CHROMA_ADR   0x0630 /* ref B Chroma addr */
+
+#define S5P_FIMV_ENC_CUR_LUMA_ADR      0x0718 /* current Luma addr */
+#define S5P_FIMV_ENC_CUR_CHROMA_ADR    0x071C /* current Chroma addr */
+
+/* Codec common register */
+#define S5P_FIMV_ENC_HSIZE_PX          0x0818 /* frame width at encoder */
+#define S5P_FIMV_ENC_VSIZE_PX          0x081c /* frame height at encoder */
+#define S5P_FIMV_ENC_PROFILE           0x0830 /* profile register */
+#define S5P_FIMV_ENC_PROFILE_H264_MAIN                 0
+#define S5P_FIMV_ENC_PROFILE_H264_HIGH                 1
+#define S5P_FIMV_ENC_PROFILE_H264_BASELINE             2
+#define S5P_FIMV_ENC_PROFILE_H264_CONSTRAINED_BASELINE 3
+#define S5P_FIMV_ENC_PROFILE_MPEG4_SIMPLE              0
+#define S5P_FIMV_ENC_PROFILE_MPEG4_ADVANCED_SIMPLE     1
+#define S5P_FIMV_ENC_PIC_STRUCT                0x083c /* picture field/frame flag */
+#define S5P_FIMV_ENC_LF_CTRL           0x0848 /* loop filter control */
+#define S5P_FIMV_ENC_ALPHA_OFF         0x084c /* loop filter alpha offset */
+#define S5P_FIMV_ENC_BETA_OFF          0x0850 /* loop filter beta offset */
+#define S5P_FIMV_MR_BUSIF_CTRL         0x0854 /* hidden, bus interface ctrl */
+#define S5P_FIMV_ENC_PXL_CACHE_CTRL    0x0a00 /* pixel cache control */
+
+/* Channel & stream interface register */
+#define S5P_FIMV_SI_RTN_CHID           0x2000 /* Return CH inst ID register */
+#define S5P_FIMV_SI_CH0_INST_ID                0x2040 /* codec instance ID */
+#define S5P_FIMV_SI_CH1_INST_ID                0x2080 /* codec instance ID */
+/* Decoder */
+#define S5P_FIMV_SI_VRESOL             0x2004 /* vertical res of decoder */
+#define S5P_FIMV_SI_HRESOL             0x2008 /* horizontal res of decoder */
+#define S5P_FIMV_SI_BUF_NUMBER         0x200c /* number of frames in the
+                                                               decoded pic */
+#define S5P_FIMV_SI_DISPLAY_Y_ADR      0x2010 /* luma addr of displayed pic */
+#define S5P_FIMV_SI_DISPLAY_C_ADR      0x2014 /* chroma addrof displayed pic */
+
+#define S5P_FIMV_SI_CONSUMED_BYTES     0x2018 /* Consumed number of bytes to
+                                                       decode a frame */
+#define S5P_FIMV_SI_DISPLAY_STATUS     0x201c /* status of decoded picture */
+
+#define S5P_FIMV_SI_DECODE_Y_ADR       0x2024 /* luma addr of decoded pic */
+#define S5P_FIMV_SI_DECODE_C_ADR       0x2028 /* chroma addrof decoded pic */
+#define S5P_FIMV_SI_DECODE_STATUS      0x202c /* status of decoded picture */
+
+#define S5P_FIMV_SI_CH0_SB_ST_ADR      0x2044 /* start addr of stream buf */
+#define S5P_FIMV_SI_CH0_SB_FRM_SIZE    0x2048 /* size of stream buf */
+#define S5P_FIMV_SI_CH0_DESC_ADR       0x204c /* addr of descriptor buf */
+#define S5P_FIMV_SI_CH0_CPB_SIZE       0x2058 /* max size of coded pic. buf */
+#define S5P_FIMV_SI_CH0_DESC_SIZE      0x205c /* max size of descriptor buf */
+
+#define S5P_FIMV_SI_CH1_SB_ST_ADR      0x2084 /* start addr of stream buf */
+#define S5P_FIMV_SI_CH1_SB_FRM_SIZE    0x2088 /* size of stream buf */
+#define S5P_FIMV_SI_CH1_DESC_ADR       0x208c /* addr of descriptor buf */
+#define S5P_FIMV_SI_CH1_CPB_SIZE       0x2098 /* max size of coded pic. buf */
+#define S5P_FIMV_SI_CH1_DESC_SIZE      0x209c /* max size of descriptor buf */
+
+#define S5P_FIMV_CRC_LUMA0             0x2030 /* luma crc data per frame
+                                                               (top field) */
+#define S5P_FIMV_CRC_CHROMA0           0x2034 /* chroma crc data per frame
+                                                               (top field) */
+#define S5P_FIMV_CRC_LUMA1             0x2038 /* luma crc data per bottom
+                                                               field */
+#define S5P_FIMV_CRC_CHROMA1           0x203c /* chroma crc data per bottom
+                                                               field */
+
+/* Display status */
+#define S5P_FIMV_DEC_STATUS_DECODING_ONLY              0
+#define S5P_FIMV_DEC_STATUS_DECODING_DISPLAY           1
+#define S5P_FIMV_DEC_STATUS_DISPLAY_ONLY               2
+#define S5P_FIMV_DEC_STATUS_DECODING_EMPTY             3
+#define S5P_FIMV_DEC_STATUS_DECODING_STATUS_MASK       7
+#define S5P_FIMV_DEC_STATUS_PROGRESSIVE                        (0<<3)
+#define S5P_FIMV_DEC_STATUS_INTERLACE                  (1<<3)
+#define S5P_FIMV_DEC_STATUS_INTERLACE_MASK             (1<<3)
+#define S5P_FIMV_DEC_STATUS_CRC_NUMBER_TWO             (0<<4)
+#define S5P_FIMV_DEC_STATUS_CRC_NUMBER_FOUR            (1<<4)
+#define S5P_FIMV_DEC_STATUS_CRC_NUMBER_MASK            (1<<4)
+#define S5P_FIMV_DEC_STATUS_CRC_GENERATED              (1<<5)
+#define S5P_FIMV_DEC_STATUS_CRC_NOT_GENERATED          (0<<5)
+#define S5P_FIMV_DEC_STATUS_CRC_MASK                   (1<<5)
+
+#define S5P_FIMV_DEC_STATUS_RESOLUTION_MASK            (3<<4)
+#define S5P_FIMV_DEC_STATUS_RESOLUTION_INC             (1<<4)
+#define S5P_FIMV_DEC_STATUS_RESOLUTION_DEC             (2<<4)
+#define S5P_FIMV_DEC_STATUS_RESOLUTION_SHIFT           4
+
+/* Decode frame address */
+#define S5P_FIMV_DECODE_Y_ADR                  0x2024
+#define S5P_FIMV_DECODE_C_ADR                  0x2028
+
+/* Decoded frame tpe */
+#define S5P_FIMV_DECODE_FRAME_TYPE             0x2020
+#define S5P_FIMV_DECODE_FRAME_MASK             7
+
+#define S5P_FIMV_DECODE_FRAME_SKIPPED          0
+#define S5P_FIMV_DECODE_FRAME_I_FRAME          1
+#define S5P_FIMV_DECODE_FRAME_P_FRAME          2
+#define S5P_FIMV_DECODE_FRAME_B_FRAME          3
+#define S5P_FIMV_DECODE_FRAME_OTHER_FRAME      4
+
+/* Sizes of buffers required for decoding */
+#define S5P_FIMV_DEC_NB_IP_SIZE                        (32 * 1024)
+#define S5P_FIMV_DEC_VERT_NB_MV_SIZE           (16 * 1024)
+#define S5P_FIMV_DEC_NB_DCAC_SIZE              (16 * 1024)
+#define S5P_FIMV_DEC_UPNB_MV_SIZE              (68 * 1024)
+#define S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE                (136 * 1024)
+#define S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE     (32 * 1024)
+#define S5P_FIMV_DEC_VC1_BITPLANE_SIZE         (2 * 1024)
+#define S5P_FIMV_DEC_STX_PARSER_SIZE           (68 * 1024)
+
+#define S5P_FIMV_DEC_BUF_ALIGN                 (8 * 1024)
+#define S5P_FIMV_ENC_BUF_ALIGN                 (8 * 1024)
+#define S5P_FIMV_NV12M_HALIGN                  16
+#define S5P_FIMV_NV12M_LVALIGN                 16
+#define S5P_FIMV_NV12M_CVALIGN                 8
+#define S5P_FIMV_NV12MT_HALIGN                 128
+#define S5P_FIMV_NV12MT_VALIGN                 32
+#define S5P_FIMV_NV12M_SALIGN                  2048
+#define S5P_FIMV_NV12MT_SALIGN                 8192
+
+/* Sizes of buffers required for encoding */
+#define S5P_FIMV_ENC_UPMV_SIZE         0x10000
+#define S5P_FIMV_ENC_COLFLG_SIZE       0x10000
+#define S5P_FIMV_ENC_INTRAMD_SIZE      0x10000
+#define S5P_FIMV_ENC_INTRAPRED_SIZE    0x4000
+#define S5P_FIMV_ENC_NBORINFO_SIZE     0x10000
+#define S5P_FIMV_ENC_ACDCCOEF_SIZE     0x10000
+
+/* Encoder */
+#define S5P_FIMV_ENC_SI_STRM_SIZE      0x2004 /* stream size */
+#define S5P_FIMV_ENC_SI_PIC_CNT                0x2008 /* picture count */
+#define S5P_FIMV_ENC_SI_WRITE_PTR      0x200c /* write pointer */
+#define S5P_FIMV_ENC_SI_SLICE_TYPE     0x2010 /* slice type(I/P/B/IDR) */
+#define S5P_FIMV_ENC_SI_SLICE_TYPE_NON_CODED   0
+#define S5P_FIMV_ENC_SI_SLICE_TYPE_I           1
+#define S5P_FIMV_ENC_SI_SLICE_TYPE_P           2
+#define S5P_FIMV_ENC_SI_SLICE_TYPE_B           3
+#define S5P_FIMV_ENC_SI_SLICE_TYPE_SKIPPED     4
+#define S5P_FIMV_ENC_SI_SLICE_TYPE_OTHERS      5
+#define S5P_FIMV_ENCODED_Y_ADDR         0x2014 /* the addr of the encoded
+                                                               luma pic */
+#define S5P_FIMV_ENCODED_C_ADDR         0x2018 /* the addr of the encoded
+                                                               chroma pic */
+
+#define S5P_FIMV_ENC_SI_CH0_SB_ADR     0x2044 /* addr of stream buf */
+#define S5P_FIMV_ENC_SI_CH0_SB_SIZE    0x204c /* size of stream buf */
+#define S5P_FIMV_ENC_SI_CH0_CUR_Y_ADR  0x2050 /* current Luma addr */
+#define S5P_FIMV_ENC_SI_CH0_CUR_C_ADR  0x2054 /* current Chroma addr */
+#define S5P_FIMV_ENC_SI_CH0_FRAME_INS  0x2058 /* frame insertion */
+
+#define S5P_FIMV_ENC_SI_CH1_SB_ADR     0x2084 /* addr of stream buf */
+#define S5P_FIMV_ENC_SI_CH1_SB_SIZE    0x208c /* size of stream buf */
+#define S5P_FIMV_ENC_SI_CH1_CUR_Y_ADR  0x2090 /* current Luma addr */
+#define S5P_FIMV_ENC_SI_CH1_CUR_C_ADR  0x2094 /* current Chroma addr */
+#define S5P_FIMV_ENC_SI_CH1_FRAME_INS  0x2098 /* frame insertion */
+
+#define S5P_FIMV_ENC_PIC_TYPE_CTRL     0xc504 /* pic type level control */
+#define S5P_FIMV_ENC_B_RECON_WRITE_ON  0xc508 /* B frame recon write ctrl */
+#define S5P_FIMV_ENC_MSLICE_CTRL       0xc50c /* multi slice control */
+#define S5P_FIMV_ENC_MSLICE_MB         0xc510 /* MB number in the one slice */
+#define S5P_FIMV_ENC_MSLICE_BIT                0xc514 /* bit count for one slice */
+#define S5P_FIMV_ENC_CIR_CTRL          0xc518 /* number of intra refresh MB */
+#define S5P_FIMV_ENC_MAP_FOR_CUR       0xc51c /* linear or tiled mode */
+#define S5P_FIMV_ENC_PADDING_CTRL      0xc520 /* padding control */
+
+#define S5P_FIMV_ENC_RC_CONFIG         0xc5a0 /* RC config */
+#define S5P_FIMV_ENC_RC_BIT_RATE       0xc5a8 /* bit rate */
+#define S5P_FIMV_ENC_RC_QBOUND         0xc5ac /* max/min QP */
+#define S5P_FIMV_ENC_RC_RPARA          0xc5b0 /* rate control reaction coeff */
+#define S5P_FIMV_ENC_RC_MB_CTRL                0xc5b4 /* MB adaptive scaling */
+
+/* Encoder for H264 only */
+#define S5P_FIMV_ENC_H264_ENTROPY_MODE 0xd004 /* CAVLC or CABAC */
+#define S5P_FIMV_ENC_H264_ALPHA_OFF    0xd008 /* loop filter alpha offset */
+#define S5P_FIMV_ENC_H264_BETA_OFF     0xd00c /* loop filter beta offset */
+#define S5P_FIMV_ENC_H264_NUM_OF_REF   0xd010 /* number of reference for P/B */
+#define S5P_FIMV_ENC_H264_TRANS_FLAG   0xd034 /* 8x8 transform flag in PPS &
+                                                               high profile */
+
+#define S5P_FIMV_ENC_RC_FRAME_RATE     0xd0d0 /* frame rate */
+
+/* Encoder for MPEG4 only */
+#define S5P_FIMV_ENC_MPEG4_QUART_PXL   0xe008 /* qpel interpolation ctrl */
+
+/* Additional */
+#define S5P_FIMV_SI_CH0_DPB_CONF_CTRL   0x2068 /* DPB Config Control Register */
+#define S5P_FIMV_SLICE_INT_MASK                1
+#define S5P_FIMV_SLICE_INT_SHIFT       31
+#define S5P_FIMV_DDELAY_ENA_SHIFT      30
+#define S5P_FIMV_DDELAY_VAL_MASK       0xff
+#define S5P_FIMV_DDELAY_VAL_SHIFT      16
+#define S5P_FIMV_DPB_COUNT_MASK                0xffff
+#define S5P_FIMV_DPB_FLUSH_MASK                1
+#define S5P_FIMV_DPB_FLUSH_SHIFT       14
+
+
+#define S5P_FIMV_SI_CH0_RELEASE_BUF     0x2060 /* DPB release buffer register */
+#define S5P_FIMV_SI_CH0_HOST_WR_ADR    0x2064 /* address of shared memory */
+
+/* Codec numbers  */
+#define S5P_FIMV_CODEC_NONE            -1
+
+#define S5P_FIMV_CODEC_H264_DEC                0
+#define S5P_FIMV_CODEC_VC1_DEC         1
+#define S5P_FIMV_CODEC_MPEG4_DEC       2
+#define S5P_FIMV_CODEC_MPEG2_DEC       3
+#define S5P_FIMV_CODEC_H263_DEC                4
+#define S5P_FIMV_CODEC_VC1RCV_DEC      5
+
+#define S5P_FIMV_CODEC_H264_ENC                16
+#define S5P_FIMV_CODEC_MPEG4_ENC       17
+#define S5P_FIMV_CODEC_H263_ENC                18
+
+/* Channel Control Register */
+#define S5P_FIMV_CH_SEQ_HEADER         1
+#define S5P_FIMV_CH_FRAME_START                2
+#define S5P_FIMV_CH_LAST_FRAME         3
+#define S5P_FIMV_CH_INIT_BUFS          4
+#define S5P_FIMV_CH_FRAME_START_REALLOC        5
+#define S5P_FIMV_CH_MASK               7
+#define S5P_FIMV_CH_SHIFT              16
+
+
+/* Host to RISC command */
+#define S5P_FIMV_H2R_CMD_EMPTY         0
+#define S5P_FIMV_H2R_CMD_OPEN_INSTANCE 1
+#define S5P_FIMV_H2R_CMD_CLOSE_INSTANCE        2
+#define S5P_FIMV_H2R_CMD_SYS_INIT      3
+#define S5P_FIMV_H2R_CMD_FLUSH         4
+#define S5P_FIMV_H2R_CMD_SLEEP         5
+#define S5P_FIMV_H2R_CMD_WAKEUP                6
+
+#define S5P_FIMV_R2H_CMD_EMPTY                 0
+#define S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET     1
+#define S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET    2
+#define S5P_FIMV_R2H_CMD_RSV_RET               3
+#define S5P_FIMV_R2H_CMD_SEQ_DONE_RET          4
+#define S5P_FIMV_R2H_CMD_FRAME_DONE_RET                5
+#define S5P_FIMV_R2H_CMD_SLICE_DONE_RET                6
+#define S5P_FIMV_R2H_CMD_ENC_COMPLETE_RET      7
+#define S5P_FIMV_R2H_CMD_SYS_INIT_RET          8
+#define S5P_FIMV_R2H_CMD_FW_STATUS_RET         9
+#define S5P_FIMV_R2H_CMD_SLEEP_RET             10
+#define S5P_FIMV_R2H_CMD_WAKEUP_RET            11
+#define S5P_FIMV_R2H_CMD_FLUSH_RET             12
+#define S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET      15
+#define S5P_FIMV_R2H_CMD_EDFU_INIT_RET         16
+#define S5P_FIMV_R2H_CMD_ERR_RET               32
+
+/* Dummy definition for MFCv6 compatibility */
+#define S5P_FIMV_CODEC_H264_MVC_DEC            -1
+#define S5P_FIMV_R2H_CMD_FIELD_DONE_RET                -1
+#define S5P_FIMV_MFC_RESET                     -1
+#define S5P_FIMV_RISC_ON                       -1
+#define S5P_FIMV_RISC_BASE_ADDRESS             -1
+#define S5P_FIMV_CODEC_VP8_DEC                 -1
+#define S5P_FIMV_REG_CLEAR_BEGIN               0
+#define S5P_FIMV_REG_CLEAR_COUNT               0
+
+/* Error handling defines */
+#define S5P_FIMV_ERR_NO_VALID_SEQ_HDR          67
+#define S5P_FIMV_ERR_INCOMPLETE_FRAME          124
+#define S5P_FIMV_ERR_TIMEOUT                   140
+#define S5P_FIMV_ERR_WARNINGS_START            145
+#define S5P_FIMV_ERR_DEC_MASK                  0xFFFF
+#define S5P_FIMV_ERR_DEC_SHIFT                 0
+#define S5P_FIMV_ERR_DSPL_MASK                 0xFFFF0000
+#define S5P_FIMV_ERR_DSPL_SHIFT                        16
+
+/* Shared memory registers' offsets */
+
+/* An offset of the start position in the stream when
+ * the start position is not aligned */
+#define S5P_FIMV_SHARED_CROP_INFO_H            0x0020
+#define S5P_FIMV_SHARED_CROP_LEFT_MASK         0xFFFF
+#define S5P_FIMV_SHARED_CROP_LEFT_SHIFT                0
+#define S5P_FIMV_SHARED_CROP_RIGHT_MASK                0xFFFF0000
+#define S5P_FIMV_SHARED_CROP_RIGHT_SHIFT       16
+#define S5P_FIMV_SHARED_CROP_INFO_V            0x0024
+#define S5P_FIMV_SHARED_CROP_TOP_MASK          0xFFFF
+#define S5P_FIMV_SHARED_CROP_TOP_SHIFT         0
+#define S5P_FIMV_SHARED_CROP_BOTTOM_MASK       0xFFFF0000
+#define S5P_FIMV_SHARED_CROP_BOTTOM_SHIFT      16
+#define S5P_FIMV_SHARED_SET_FRAME_TAG          0x0004
+#define S5P_FIMV_SHARED_GET_FRAME_TAG_TOP      0x0008
+#define S5P_FIMV_SHARED_GET_FRAME_TAG_BOT      0x000C
+#define S5P_FIMV_SHARED_START_BYTE_NUM         0x0018
+#define S5P_FIMV_SHARED_RC_VOP_TIMING          0x0030
+#define S5P_FIMV_SHARED_LUMA_DPB_SIZE          0x0064
+#define S5P_FIMV_SHARED_CHROMA_DPB_SIZE                0x0068
+#define S5P_FIMV_SHARED_MV_SIZE                        0x006C
+#define S5P_FIMV_SHARED_PIC_TIME_TOP           0x0010
+#define S5P_FIMV_SHARED_PIC_TIME_BOTTOM                0x0014
+#define S5P_FIMV_SHARED_EXT_ENC_CONTROL                0x0028
+#define S5P_FIMV_SHARED_P_B_FRAME_QP           0x0070
+#define S5P_FIMV_SHARED_ASPECT_RATIO_IDC       0x0074
+#define S5P_FIMV_SHARED_EXTENDED_SAR           0x0078
+#define S5P_FIMV_SHARED_H264_I_PERIOD          0x009C
+#define S5P_FIMV_SHARED_RC_CONTROL_CONFIG      0x00A0
+#define S5P_FIMV_SHARED_DISP_FRAME_TYPE_SHIFT  2
+
+/* Offset used by the hardware to store addresses */
+#define MFC_OFFSET_SHIFT       11
+
+#define FIRMWARE_ALIGN         (128 * SZ_1K)   /* 128KB */
+#define MFC_H264_CTX_BUF_SIZE  (600 * SZ_1K)   /* 600KB per H264 instance */
+#define MFC_CTX_BUF_SIZE       (10 * SZ_1K)    /* 10KB per instance */
+#define DESC_BUF_SIZE          (128 * SZ_1K)   /* 128KB for DESC buffer */
+#define SHARED_BUF_SIZE                (8 * SZ_1K)     /* 8KB for shared buffer */
+
+#define DEF_CPB_SIZE           (256 * SZ_1K)   /* 256KB */
+#define MAX_CPB_SIZE           (4 * SZ_1M)     /* 4MB */
+#define MAX_FW_SIZE            (384 * SZ_1K)
+
+#define MFC_VERSION            0x51
+#define MFC_NUM_PORTS          2
+
+#define S5P_FIMV_SHARED_FRAME_PACK_SEI_AVAIL    0x16C
+#define S5P_FIMV_SHARED_FRAME_PACK_ARRGMENT_ID  0x170
+#define S5P_FIMV_SHARED_FRAME_PACK_SEI_INFO     0x174
+#define S5P_FIMV_SHARED_FRAME_PACK_GRID_POS     0x178
+
+/* Values for resolution change in display status */
+#define S5P_FIMV_RES_INCREASE  1
+#define S5P_FIMV_RES_DECREASE  2
+
+#endif /* _REGS_FIMV_H */
diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c
new file mode 100644 (file)
index 0000000..7613419
--- /dev/null
@@ -0,0 +1,1680 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Samsung S5P Multi Format Codec v 5.1
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Kamil Debski, <k.debski@samsung.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-event.h>
+#include <linux/workqueue.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_reserved_mem.h>
+#include <media/videobuf2-v4l2.h>
+#include "s5p_mfc_common.h"
+#include "s5p_mfc_ctrl.h"
+#include "s5p_mfc_debug.h"
+#include "s5p_mfc_dec.h"
+#include "s5p_mfc_enc.h"
+#include "s5p_mfc_intr.h"
+#include "s5p_mfc_iommu.h"
+#include "s5p_mfc_opr.h"
+#include "s5p_mfc_cmd.h"
+#include "s5p_mfc_pm.h"
+
+#define S5P_MFC_DEC_NAME       "s5p-mfc-dec"
+#define S5P_MFC_ENC_NAME       "s5p-mfc-enc"
+
+int mfc_debug_level;
+module_param_named(debug, mfc_debug_level, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug level - higher value produces more verbose messages");
+
+static char *mfc_mem_size;
+module_param_named(mem, mfc_mem_size, charp, 0644);
+MODULE_PARM_DESC(mem, "Preallocated memory size for the firmware and context buffers");
+
+/* Helper functions for interrupt processing */
+
+/* Remove from hw execution round robin */
+void clear_work_bit(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       spin_lock(&dev->condlock);
+       __clear_bit(ctx->num, &dev->ctx_work_bits);
+       spin_unlock(&dev->condlock);
+}
+
+/* Add to hw execution round robin */
+void set_work_bit(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       spin_lock(&dev->condlock);
+       __set_bit(ctx->num, &dev->ctx_work_bits);
+       spin_unlock(&dev->condlock);
+}
+
+/* Remove from hw execution round robin */
+void clear_work_bit_irqsave(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned long flags;
+
+       spin_lock_irqsave(&dev->condlock, flags);
+       __clear_bit(ctx->num, &dev->ctx_work_bits);
+       spin_unlock_irqrestore(&dev->condlock, flags);
+}
+
+/* Add to hw execution round robin */
+void set_work_bit_irqsave(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned long flags;
+
+       spin_lock_irqsave(&dev->condlock, flags);
+       __set_bit(ctx->num, &dev->ctx_work_bits);
+       spin_unlock_irqrestore(&dev->condlock, flags);
+}
+
+int s5p_mfc_get_new_ctx(struct s5p_mfc_dev *dev)
+{
+       unsigned long flags;
+       int ctx;
+
+       spin_lock_irqsave(&dev->condlock, flags);
+       ctx = dev->curr_ctx;
+       do {
+               ctx = (ctx + 1) % MFC_NUM_CONTEXTS;
+               if (ctx == dev->curr_ctx) {
+                       if (!test_bit(ctx, &dev->ctx_work_bits))
+                               ctx = -EAGAIN;
+                       break;
+               }
+       } while (!test_bit(ctx, &dev->ctx_work_bits));
+       spin_unlock_irqrestore(&dev->condlock, flags);
+
+       return ctx;
+}
+
+/* Wake up context wait_queue */
+static void wake_up_ctx(struct s5p_mfc_ctx *ctx, unsigned int reason,
+                       unsigned int err)
+{
+       ctx->int_cond = 1;
+       ctx->int_type = reason;
+       ctx->int_err = err;
+       wake_up(&ctx->queue);
+}
+
+/* Wake up device wait_queue */
+static void wake_up_dev(struct s5p_mfc_dev *dev, unsigned int reason,
+                       unsigned int err)
+{
+       dev->int_cond = 1;
+       dev->int_type = reason;
+       dev->int_err = err;
+       wake_up(&dev->queue);
+}
+
+void s5p_mfc_cleanup_queue(struct list_head *lh, struct vb2_queue *vq)
+{
+       struct s5p_mfc_buf *b;
+       int i;
+
+       while (!list_empty(lh)) {
+               b = list_entry(lh->next, struct s5p_mfc_buf, list);
+               for (i = 0; i < b->b->vb2_buf.num_planes; i++)
+                       vb2_set_plane_payload(&b->b->vb2_buf, i, 0);
+               vb2_buffer_done(&b->b->vb2_buf, VB2_BUF_STATE_ERROR);
+               list_del(&b->list);
+       }
+}
+
+static void s5p_mfc_watchdog(struct timer_list *t)
+{
+       struct s5p_mfc_dev *dev = from_timer(dev, t, watchdog_timer);
+
+       if (test_bit(0, &dev->hw_lock))
+               atomic_inc(&dev->watchdog_cnt);
+       if (atomic_read(&dev->watchdog_cnt) >= MFC_WATCHDOG_CNT) {
+               /* This means that hw is busy and no interrupts were
+                * generated by hw for the Nth time of running this
+                * watchdog timer. This usually means a serious hw
+                * error. Now it is time to kill all instances and
+                * reset the MFC. */
+               mfc_err("Time out during waiting for HW\n");
+               schedule_work(&dev->watchdog_work);
+       }
+       dev->watchdog_timer.expires = jiffies +
+                                       msecs_to_jiffies(MFC_WATCHDOG_INTERVAL);
+       add_timer(&dev->watchdog_timer);
+}
+
+static void s5p_mfc_watchdog_worker(struct work_struct *work)
+{
+       struct s5p_mfc_dev *dev;
+       struct s5p_mfc_ctx *ctx;
+       unsigned long flags;
+       int mutex_locked;
+       int i, ret;
+
+       dev = container_of(work, struct s5p_mfc_dev, watchdog_work);
+
+       mfc_err("Driver timeout error handling\n");
+       /* Lock the mutex that protects open and release.
+        * This is necessary as they may load and unload firmware. */
+       mutex_locked = mutex_trylock(&dev->mfc_mutex);
+       if (!mutex_locked)
+               mfc_err("Error: some instance may be closing/opening\n");
+       spin_lock_irqsave(&dev->irqlock, flags);
+
+       s5p_mfc_clock_off();
+
+       for (i = 0; i < MFC_NUM_CONTEXTS; i++) {
+               ctx = dev->ctx[i];
+               if (!ctx)
+                       continue;
+               ctx->state = MFCINST_ERROR;
+               s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst);
+               s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src);
+               clear_work_bit(ctx);
+               wake_up_ctx(ctx, S5P_MFC_R2H_CMD_ERR_RET, 0);
+       }
+       clear_bit(0, &dev->hw_lock);
+       spin_unlock_irqrestore(&dev->irqlock, flags);
+
+       /* De-init MFC */
+       s5p_mfc_deinit_hw(dev);
+
+       /* Double check if there is at least one instance running.
+        * If no instance is in memory than no firmware should be present */
+       if (dev->num_inst > 0) {
+               ret = s5p_mfc_load_firmware(dev);
+               if (ret) {
+                       mfc_err("Failed to reload FW\n");
+                       goto unlock;
+               }
+               s5p_mfc_clock_on();
+               ret = s5p_mfc_init_hw(dev);
+               s5p_mfc_clock_off();
+               if (ret)
+                       mfc_err("Failed to reinit FW\n");
+       }
+unlock:
+       if (mutex_locked)
+               mutex_unlock(&dev->mfc_mutex);
+}
+
+static void s5p_mfc_handle_frame_all_extracted(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_buf *dst_buf;
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       ctx->state = MFCINST_FINISHED;
+       ctx->sequence++;
+       while (!list_empty(&ctx->dst_queue)) {
+               dst_buf = list_entry(ctx->dst_queue.next,
+                                    struct s5p_mfc_buf, list);
+               mfc_debug(2, "Cleaning up buffer: %d\n",
+                                         dst_buf->b->vb2_buf.index);
+               vb2_set_plane_payload(&dst_buf->b->vb2_buf, 0, 0);
+               vb2_set_plane_payload(&dst_buf->b->vb2_buf, 1, 0);
+               list_del(&dst_buf->list);
+               dst_buf->flags |= MFC_BUF_FLAG_EOS;
+               ctx->dst_queue_cnt--;
+               dst_buf->b->sequence = (ctx->sequence++);
+
+               if (s5p_mfc_hw_call(dev->mfc_ops, get_pic_type_top, ctx) ==
+                       s5p_mfc_hw_call(dev->mfc_ops, get_pic_type_bot, ctx))
+                       dst_buf->b->field = V4L2_FIELD_NONE;
+               else
+                       dst_buf->b->field = V4L2_FIELD_INTERLACED;
+               dst_buf->b->flags |= V4L2_BUF_FLAG_LAST;
+
+               ctx->dec_dst_flag &= ~(1 << dst_buf->b->vb2_buf.index);
+               vb2_buffer_done(&dst_buf->b->vb2_buf, VB2_BUF_STATE_DONE);
+       }
+}
+
+static void s5p_mfc_handle_frame_copy_time(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_buf *dst_buf, *src_buf;
+       u32 dec_y_addr;
+       unsigned int frame_type;
+
+       /* Make sure we actually have a new frame before continuing. */
+       frame_type = s5p_mfc_hw_call(dev->mfc_ops, get_dec_frame_type, dev);
+       if (frame_type == S5P_FIMV_DECODE_FRAME_SKIPPED)
+               return;
+       dec_y_addr = (u32)s5p_mfc_hw_call(dev->mfc_ops, get_dec_y_adr, dev);
+
+       /* Copy timestamp / timecode from decoded src to dst and set
+          appropriate flags. */
+       src_buf = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
+       list_for_each_entry(dst_buf, &ctx->dst_queue, list) {
+               u32 addr = (u32)vb2_dma_contig_plane_dma_addr(&dst_buf->b->vb2_buf, 0);
+
+               if (addr == dec_y_addr) {
+                       dst_buf->b->timecode = src_buf->b->timecode;
+                       dst_buf->b->vb2_buf.timestamp =
+                                               src_buf->b->vb2_buf.timestamp;
+                       dst_buf->b->flags &=
+                               ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
+                       dst_buf->b->flags |=
+                               src_buf->b->flags
+                               & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
+                       switch (frame_type) {
+                       case S5P_FIMV_DECODE_FRAME_I_FRAME:
+                               dst_buf->b->flags |=
+                                               V4L2_BUF_FLAG_KEYFRAME;
+                               break;
+                       case S5P_FIMV_DECODE_FRAME_P_FRAME:
+                               dst_buf->b->flags |=
+                                               V4L2_BUF_FLAG_PFRAME;
+                               break;
+                       case S5P_FIMV_DECODE_FRAME_B_FRAME:
+                               dst_buf->b->flags |=
+                                               V4L2_BUF_FLAG_BFRAME;
+                               break;
+                       default:
+                               /* Don't know how to handle
+                                  S5P_FIMV_DECODE_FRAME_OTHER_FRAME. */
+                               mfc_debug(2, "Unexpected frame type: %d\n",
+                                               frame_type);
+                       }
+                       break;
+               }
+       }
+}
+
+static void s5p_mfc_handle_frame_new(struct s5p_mfc_ctx *ctx, unsigned int err)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_buf  *dst_buf;
+       u32 dspl_y_addr;
+       unsigned int frame_type;
+
+       dspl_y_addr = (u32)s5p_mfc_hw_call(dev->mfc_ops, get_dspl_y_adr, dev);
+       if (IS_MFCV6_PLUS(dev))
+               frame_type = s5p_mfc_hw_call(dev->mfc_ops,
+                       get_disp_frame_type, ctx);
+       else
+               frame_type = s5p_mfc_hw_call(dev->mfc_ops,
+                       get_dec_frame_type, dev);
+
+       /* If frame is same as previous then skip and do not dequeue */
+       if (frame_type == S5P_FIMV_DECODE_FRAME_SKIPPED) {
+               if (!ctx->after_packed_pb)
+                       ctx->sequence++;
+               ctx->after_packed_pb = 0;
+               return;
+       }
+       ctx->sequence++;
+       /* The MFC returns address of the buffer, now we have to
+        * check which videobuf does it correspond to */
+       list_for_each_entry(dst_buf, &ctx->dst_queue, list) {
+               u32 addr = (u32)vb2_dma_contig_plane_dma_addr(&dst_buf->b->vb2_buf, 0);
+
+               /* Check if this is the buffer we're looking for */
+               if (addr == dspl_y_addr) {
+                       list_del(&dst_buf->list);
+                       ctx->dst_queue_cnt--;
+                       dst_buf->b->sequence = ctx->sequence;
+                       if (s5p_mfc_hw_call(dev->mfc_ops,
+                                       get_pic_type_top, ctx) ==
+                               s5p_mfc_hw_call(dev->mfc_ops,
+                                       get_pic_type_bot, ctx))
+                               dst_buf->b->field = V4L2_FIELD_NONE;
+                       else
+                               dst_buf->b->field =
+                                                       V4L2_FIELD_INTERLACED;
+                       vb2_set_plane_payload(&dst_buf->b->vb2_buf, 0,
+                                               ctx->luma_size);
+                       vb2_set_plane_payload(&dst_buf->b->vb2_buf, 1,
+                                               ctx->chroma_size);
+                       clear_bit(dst_buf->b->vb2_buf.index,
+                                                       &ctx->dec_dst_flag);
+
+                       vb2_buffer_done(&dst_buf->b->vb2_buf, err ?
+                               VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
+
+                       break;
+               }
+       }
+}
+
+/* Handle frame decoding interrupt */
+static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx,
+                                       unsigned int reason, unsigned int err)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned int dst_frame_status;
+       unsigned int dec_frame_status;
+       struct s5p_mfc_buf *src_buf;
+       unsigned int res_change;
+
+       dst_frame_status = s5p_mfc_hw_call(dev->mfc_ops, get_dspl_status, dev)
+                               & S5P_FIMV_DEC_STATUS_DECODING_STATUS_MASK;
+       dec_frame_status = s5p_mfc_hw_call(dev->mfc_ops, get_dec_status, dev)
+                               & S5P_FIMV_DEC_STATUS_DECODING_STATUS_MASK;
+       res_change = (s5p_mfc_hw_call(dev->mfc_ops, get_dspl_status, dev)
+                               & S5P_FIMV_DEC_STATUS_RESOLUTION_MASK)
+                               >> S5P_FIMV_DEC_STATUS_RESOLUTION_SHIFT;
+       mfc_debug(2, "Frame Status: %x\n", dst_frame_status);
+       if (ctx->state == MFCINST_RES_CHANGE_INIT)
+               ctx->state = MFCINST_RES_CHANGE_FLUSH;
+       if (res_change == S5P_FIMV_RES_INCREASE ||
+               res_change == S5P_FIMV_RES_DECREASE) {
+               ctx->state = MFCINST_RES_CHANGE_INIT;
+               s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
+               wake_up_ctx(ctx, reason, err);
+               WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
+               s5p_mfc_clock_off();
+               s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
+               return;
+       }
+       if (ctx->dpb_flush_flag)
+               ctx->dpb_flush_flag = 0;
+
+       /* All frames remaining in the buffer have been extracted  */
+       if (dst_frame_status == S5P_FIMV_DEC_STATUS_DECODING_EMPTY) {
+               if (ctx->state == MFCINST_RES_CHANGE_FLUSH) {
+                       static const struct v4l2_event ev_src_ch = {
+                               .type = V4L2_EVENT_SOURCE_CHANGE,
+                               .u.src_change.changes =
+                                       V4L2_EVENT_SRC_CH_RESOLUTION,
+                       };
+
+                       s5p_mfc_handle_frame_all_extracted(ctx);
+                       ctx->state = MFCINST_RES_CHANGE_END;
+                       v4l2_event_queue_fh(&ctx->fh, &ev_src_ch);
+
+                       goto leave_handle_frame;
+               } else {
+                       s5p_mfc_handle_frame_all_extracted(ctx);
+               }
+       }
+
+       if (dec_frame_status == S5P_FIMV_DEC_STATUS_DECODING_DISPLAY)
+               s5p_mfc_handle_frame_copy_time(ctx);
+
+       /* A frame has been decoded and is in the buffer  */
+       if (dst_frame_status == S5P_FIMV_DEC_STATUS_DISPLAY_ONLY ||
+           dst_frame_status == S5P_FIMV_DEC_STATUS_DECODING_DISPLAY) {
+               s5p_mfc_handle_frame_new(ctx, err);
+       } else {
+               mfc_debug(2, "No frame decode\n");
+       }
+       /* Mark source buffer as complete */
+       if (dst_frame_status != S5P_FIMV_DEC_STATUS_DISPLAY_ONLY
+               && !list_empty(&ctx->src_queue)) {
+               src_buf = list_entry(ctx->src_queue.next, struct s5p_mfc_buf,
+                                                               list);
+               ctx->consumed_stream += s5p_mfc_hw_call(dev->mfc_ops,
+                                               get_consumed_stream, dev);
+               if (ctx->codec_mode != S5P_MFC_CODEC_H264_DEC &&
+                       ctx->codec_mode != S5P_MFC_CODEC_VP8_DEC &&
+                       ctx->consumed_stream + STUFF_BYTE <
+                       src_buf->b->vb2_buf.planes[0].bytesused) {
+                       /* Run MFC again on the same buffer */
+                       mfc_debug(2, "Running again the same buffer\n");
+                       ctx->after_packed_pb = 1;
+               } else {
+                       mfc_debug(2, "MFC needs next buffer\n");
+                       ctx->consumed_stream = 0;
+                       if (src_buf->flags & MFC_BUF_FLAG_EOS)
+                               ctx->state = MFCINST_FINISHING;
+                       list_del(&src_buf->list);
+                       ctx->src_queue_cnt--;
+                       if (s5p_mfc_hw_call(dev->mfc_ops, err_dec, err) > 0)
+                               vb2_buffer_done(&src_buf->b->vb2_buf,
+                                               VB2_BUF_STATE_ERROR);
+                       else
+                               vb2_buffer_done(&src_buf->b->vb2_buf,
+                                               VB2_BUF_STATE_DONE);
+               }
+       }
+leave_handle_frame:
+       if ((ctx->src_queue_cnt == 0 && ctx->state != MFCINST_FINISHING)
+                                   || ctx->dst_queue_cnt < ctx->pb_count)
+               clear_work_bit(ctx);
+       s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
+       wake_up_ctx(ctx, reason, err);
+       WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
+       s5p_mfc_clock_off();
+       /* if suspending, wake up device and do not try_run again*/
+       if (test_bit(0, &dev->enter_suspend))
+               wake_up_dev(dev, reason, err);
+       else
+               s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
+}
+
+/* Error handling for interrupt */
+static void s5p_mfc_handle_error(struct s5p_mfc_dev *dev,
+               struct s5p_mfc_ctx *ctx, unsigned int reason, unsigned int err)
+{
+       mfc_err("Interrupt Error: %08x\n", err);
+
+       if (ctx) {
+               /* Error recovery is dependent on the state of context */
+               switch (ctx->state) {
+               case MFCINST_RES_CHANGE_INIT:
+               case MFCINST_RES_CHANGE_FLUSH:
+               case MFCINST_RES_CHANGE_END:
+               case MFCINST_FINISHING:
+               case MFCINST_FINISHED:
+               case MFCINST_RUNNING:
+                       /* It is highly probable that an error occurred
+                        * while decoding a frame */
+                       clear_work_bit(ctx);
+                       ctx->state = MFCINST_ERROR;
+                       /* Mark all dst buffers as having an error */
+                       s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst);
+                       /* Mark all src buffers as having an error */
+                       s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src);
+                       wake_up_ctx(ctx, reason, err);
+                       break;
+               default:
+                       clear_work_bit(ctx);
+                       ctx->state = MFCINST_ERROR;
+                       wake_up_ctx(ctx, reason, err);
+                       break;
+               }
+       }
+       WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
+       s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
+       s5p_mfc_clock_off();
+       wake_up_dev(dev, reason, err);
+}
+
+/* Header parsing interrupt handling */
+static void s5p_mfc_handle_seq_done(struct s5p_mfc_ctx *ctx,
+                                unsigned int reason, unsigned int err)
+{
+       struct s5p_mfc_dev *dev;
+
+       if (!ctx)
+               return;
+       dev = ctx->dev;
+       if (ctx->c_ops->post_seq_start) {
+               if (ctx->c_ops->post_seq_start(ctx))
+                       mfc_err("post_seq_start() failed\n");
+       } else {
+               ctx->img_width = s5p_mfc_hw_call(dev->mfc_ops, get_img_width,
+                               dev);
+               ctx->img_height = s5p_mfc_hw_call(dev->mfc_ops, get_img_height,
+                               dev);
+
+               s5p_mfc_hw_call(dev->mfc_ops, dec_calc_dpb_size, ctx);
+
+               ctx->pb_count = s5p_mfc_hw_call(dev->mfc_ops, get_dpb_count,
+                               dev);
+               ctx->mv_count = s5p_mfc_hw_call(dev->mfc_ops, get_mv_count,
+                               dev);
+               if (FW_HAS_E_MIN_SCRATCH_BUF(dev))
+                       ctx->scratch_buf_size = s5p_mfc_hw_call(dev->mfc_ops,
+                                               get_min_scratch_buf_size, dev);
+               if (ctx->img_width == 0 || ctx->img_height == 0)
+                       ctx->state = MFCINST_ERROR;
+               else
+                       ctx->state = MFCINST_HEAD_PARSED;
+
+               if ((ctx->codec_mode == S5P_MFC_CODEC_H264_DEC ||
+                       ctx->codec_mode == S5P_MFC_CODEC_H264_MVC_DEC) &&
+                               !list_empty(&ctx->src_queue)) {
+                       struct s5p_mfc_buf *src_buf;
+                       src_buf = list_entry(ctx->src_queue.next,
+                                       struct s5p_mfc_buf, list);
+                       if (s5p_mfc_hw_call(dev->mfc_ops, get_consumed_stream,
+                                               dev) <
+                                       src_buf->b->vb2_buf.planes[0].bytesused)
+                               ctx->head_processed = 0;
+                       else
+                               ctx->head_processed = 1;
+               } else {
+                       ctx->head_processed = 1;
+               }
+       }
+       s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
+       clear_work_bit(ctx);
+       WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
+       s5p_mfc_clock_off();
+       s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
+       wake_up_ctx(ctx, reason, err);
+}
+
+/* Header parsing interrupt handling */
+static void s5p_mfc_handle_init_buffers(struct s5p_mfc_ctx *ctx,
+                                unsigned int reason, unsigned int err)
+{
+       struct s5p_mfc_buf *src_buf;
+       struct s5p_mfc_dev *dev;
+
+       if (!ctx)
+               return;
+       dev = ctx->dev;
+       s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
+       ctx->int_type = reason;
+       ctx->int_err = err;
+       ctx->int_cond = 1;
+       clear_work_bit(ctx);
+       if (err == 0) {
+               ctx->state = MFCINST_RUNNING;
+               if (!ctx->dpb_flush_flag && ctx->head_processed) {
+                       if (!list_empty(&ctx->src_queue)) {
+                               src_buf = list_entry(ctx->src_queue.next,
+                                            struct s5p_mfc_buf, list);
+                               list_del(&src_buf->list);
+                               ctx->src_queue_cnt--;
+                               vb2_buffer_done(&src_buf->b->vb2_buf,
+                                               VB2_BUF_STATE_DONE);
+                       }
+               } else {
+                       ctx->dpb_flush_flag = 0;
+               }
+               WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
+
+               s5p_mfc_clock_off();
+
+               wake_up(&ctx->queue);
+               s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
+       } else {
+               WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
+
+               s5p_mfc_clock_off();
+
+               wake_up(&ctx->queue);
+       }
+}
+
+static void s5p_mfc_handle_stream_complete(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_buf *mb_entry;
+
+       mfc_debug(2, "Stream completed\n");
+
+       ctx->state = MFCINST_FINISHED;
+
+       if (!list_empty(&ctx->dst_queue)) {
+               mb_entry = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf,
+                                                                       list);
+               list_del(&mb_entry->list);
+               ctx->dst_queue_cnt--;
+               vb2_set_plane_payload(&mb_entry->b->vb2_buf, 0, 0);
+               vb2_buffer_done(&mb_entry->b->vb2_buf, VB2_BUF_STATE_DONE);
+       }
+
+       clear_work_bit(ctx);
+
+       WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
+
+       s5p_mfc_clock_off();
+       wake_up(&ctx->queue);
+       s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
+}
+
+/* Interrupt processing */
+static irqreturn_t s5p_mfc_irq(int irq, void *priv)
+{
+       struct s5p_mfc_dev *dev = priv;
+       struct s5p_mfc_ctx *ctx;
+       unsigned int reason;
+       unsigned int err;
+
+       mfc_debug_enter();
+       /* Reset the timeout watchdog */
+       atomic_set(&dev->watchdog_cnt, 0);
+       spin_lock(&dev->irqlock);
+       ctx = dev->ctx[dev->curr_ctx];
+       /* Get the reason of interrupt and the error code */
+       reason = s5p_mfc_hw_call(dev->mfc_ops, get_int_reason, dev);
+       err = s5p_mfc_hw_call(dev->mfc_ops, get_int_err, dev);
+       mfc_debug(1, "Int reason: %d (err: %08x)\n", reason, err);
+       switch (reason) {
+       case S5P_MFC_R2H_CMD_ERR_RET:
+               /* An error has occurred */
+               if (ctx->state == MFCINST_RUNNING &&
+                       (s5p_mfc_hw_call(dev->mfc_ops, err_dec, err) >=
+                               dev->warn_start ||
+                               err == S5P_FIMV_ERR_NO_VALID_SEQ_HDR ||
+                               err == S5P_FIMV_ERR_INCOMPLETE_FRAME ||
+                               err == S5P_FIMV_ERR_TIMEOUT))
+                       s5p_mfc_handle_frame(ctx, reason, err);
+               else
+                       s5p_mfc_handle_error(dev, ctx, reason, err);
+               clear_bit(0, &dev->enter_suspend);
+               break;
+
+       case S5P_MFC_R2H_CMD_SLICE_DONE_RET:
+       case S5P_MFC_R2H_CMD_FIELD_DONE_RET:
+       case S5P_MFC_R2H_CMD_FRAME_DONE_RET:
+               if (ctx->c_ops->post_frame_start) {
+                       if (ctx->c_ops->post_frame_start(ctx))
+                               mfc_err("post_frame_start() failed\n");
+
+                       if (ctx->state == MFCINST_FINISHING &&
+                                               list_empty(&ctx->ref_queue)) {
+                               s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
+                               s5p_mfc_handle_stream_complete(ctx);
+                               break;
+                       }
+                       s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
+                       WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
+                       s5p_mfc_clock_off();
+                       wake_up_ctx(ctx, reason, err);
+                       s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
+               } else {
+                       s5p_mfc_handle_frame(ctx, reason, err);
+               }
+               break;
+
+       case S5P_MFC_R2H_CMD_SEQ_DONE_RET:
+               s5p_mfc_handle_seq_done(ctx, reason, err);
+               break;
+
+       case S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET:
+               ctx->inst_no = s5p_mfc_hw_call(dev->mfc_ops, get_inst_no, dev);
+               ctx->state = MFCINST_GOT_INST;
+               goto irq_cleanup_hw;
+
+       case S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET:
+               ctx->inst_no = MFC_NO_INSTANCE_SET;
+               ctx->state = MFCINST_FREE;
+               goto irq_cleanup_hw;
+
+       case S5P_MFC_R2H_CMD_SYS_INIT_RET:
+       case S5P_MFC_R2H_CMD_FW_STATUS_RET:
+       case S5P_MFC_R2H_CMD_SLEEP_RET:
+       case S5P_MFC_R2H_CMD_WAKEUP_RET:
+               if (ctx)
+                       clear_work_bit(ctx);
+               s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
+               clear_bit(0, &dev->hw_lock);
+               clear_bit(0, &dev->enter_suspend);
+               wake_up_dev(dev, reason, err);
+               break;
+
+       case S5P_MFC_R2H_CMD_INIT_BUFFERS_RET:
+               s5p_mfc_handle_init_buffers(ctx, reason, err);
+               break;
+
+       case S5P_MFC_R2H_CMD_COMPLETE_SEQ_RET:
+               s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
+               ctx->int_type = reason;
+               ctx->int_err = err;
+               s5p_mfc_handle_stream_complete(ctx);
+               break;
+
+       case S5P_MFC_R2H_CMD_DPB_FLUSH_RET:
+               ctx->state = MFCINST_RUNNING;
+               goto irq_cleanup_hw;
+
+       default:
+               mfc_debug(2, "Unknown int reason\n");
+               s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
+       }
+       spin_unlock(&dev->irqlock);
+       mfc_debug_leave();
+       return IRQ_HANDLED;
+irq_cleanup_hw:
+       s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
+       ctx->int_type = reason;
+       ctx->int_err = err;
+       ctx->int_cond = 1;
+       if (test_and_clear_bit(0, &dev->hw_lock) == 0)
+               mfc_err("Failed to unlock hw\n");
+
+       s5p_mfc_clock_off();
+       clear_work_bit(ctx);
+       wake_up(&ctx->queue);
+
+       s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
+       spin_unlock(&dev->irqlock);
+       mfc_debug(2, "Exit via irq_cleanup_hw\n");
+       return IRQ_HANDLED;
+}
+
+/* Open an MFC node */
+static int s5p_mfc_open(struct file *file)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct s5p_mfc_dev *dev = video_drvdata(file);
+       struct s5p_mfc_ctx *ctx = NULL;
+       struct vb2_queue *q;
+       int ret = 0;
+
+       mfc_debug_enter();
+       if (mutex_lock_interruptible(&dev->mfc_mutex))
+               return -ERESTARTSYS;
+       dev->num_inst++;        /* It is guarded by mfc_mutex in vfd */
+       /* Allocate memory for context */
+       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+       if (!ctx) {
+               ret = -ENOMEM;
+               goto err_alloc;
+       }
+       init_waitqueue_head(&ctx->queue);
+       v4l2_fh_init(&ctx->fh, vdev);
+       file->private_data = &ctx->fh;
+       v4l2_fh_add(&ctx->fh);
+       ctx->dev = dev;
+       INIT_LIST_HEAD(&ctx->src_queue);
+       INIT_LIST_HEAD(&ctx->dst_queue);
+       ctx->src_queue_cnt = 0;
+       ctx->dst_queue_cnt = 0;
+       /* Get context number */
+       ctx->num = 0;
+       while (dev->ctx[ctx->num]) {
+               ctx->num++;
+               if (ctx->num >= MFC_NUM_CONTEXTS) {
+                       mfc_debug(2, "Too many open contexts\n");
+                       ret = -EBUSY;
+                       goto err_no_ctx;
+               }
+       }
+       /* Mark context as idle */
+       clear_work_bit_irqsave(ctx);
+       dev->ctx[ctx->num] = ctx;
+       if (vdev == dev->vfd_dec) {
+               ctx->type = MFCINST_DECODER;
+               ctx->c_ops = get_dec_codec_ops();
+               s5p_mfc_dec_init(ctx);
+               /* Setup ctrl handler */
+               ret = s5p_mfc_dec_ctrls_setup(ctx);
+               if (ret) {
+                       mfc_err("Failed to setup mfc controls\n");
+                       goto err_ctrls_setup;
+               }
+       } else if (vdev == dev->vfd_enc) {
+               ctx->type = MFCINST_ENCODER;
+               ctx->c_ops = get_enc_codec_ops();
+               /* only for encoder */
+               INIT_LIST_HEAD(&ctx->ref_queue);
+               ctx->ref_queue_cnt = 0;
+               s5p_mfc_enc_init(ctx);
+               /* Setup ctrl handler */
+               ret = s5p_mfc_enc_ctrls_setup(ctx);
+               if (ret) {
+                       mfc_err("Failed to setup mfc controls\n");
+                       goto err_ctrls_setup;
+               }
+       } else {
+               ret = -ENOENT;
+               goto err_bad_node;
+       }
+       ctx->fh.ctrl_handler = &ctx->ctrl_handler;
+       ctx->inst_no = MFC_NO_INSTANCE_SET;
+       /* Load firmware if this is the first instance */
+       if (dev->num_inst == 1) {
+               dev->watchdog_timer.expires = jiffies +
+                                       msecs_to_jiffies(MFC_WATCHDOG_INTERVAL);
+               add_timer(&dev->watchdog_timer);
+               ret = s5p_mfc_power_on();
+               if (ret < 0) {
+                       mfc_err("power on failed\n");
+                       goto err_pwr_enable;
+               }
+               s5p_mfc_clock_on();
+               ret = s5p_mfc_load_firmware(dev);
+               if (ret) {
+                       s5p_mfc_clock_off();
+                       goto err_load_fw;
+               }
+               /* Init the FW */
+               ret = s5p_mfc_init_hw(dev);
+               s5p_mfc_clock_off();
+               if (ret)
+                       goto err_init_hw;
+       }
+       /* Init videobuf2 queue for CAPTURE */
+       q = &ctx->vq_dst;
+       q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+       q->drv_priv = &ctx->fh;
+       q->lock = &dev->mfc_mutex;
+       if (vdev == dev->vfd_dec) {
+               q->io_modes = VB2_MMAP;
+               q->ops = get_dec_queue_ops();
+       } else if (vdev == dev->vfd_enc) {
+               q->io_modes = VB2_MMAP | VB2_USERPTR;
+               q->ops = get_enc_queue_ops();
+       } else {
+               ret = -ENOENT;
+               goto err_queue_init;
+       }
+       /*
+        * We'll do mostly sequential access, so sacrifice TLB efficiency for
+        * faster allocation.
+        */
+       q->dma_attrs = DMA_ATTR_ALLOC_SINGLE_PAGES;
+       q->mem_ops = &vb2_dma_contig_memops;
+       q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+       ret = vb2_queue_init(q);
+       if (ret) {
+               mfc_err("Failed to initialize videobuf2 queue(capture)\n");
+               goto err_queue_init;
+       }
+       /* Init videobuf2 queue for OUTPUT */
+       q = &ctx->vq_src;
+       q->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+       q->drv_priv = &ctx->fh;
+       q->lock = &dev->mfc_mutex;
+       if (vdev == dev->vfd_dec) {
+               q->io_modes = VB2_MMAP;
+               q->ops = get_dec_queue_ops();
+       } else if (vdev == dev->vfd_enc) {
+               q->io_modes = VB2_MMAP | VB2_USERPTR;
+               q->ops = get_enc_queue_ops();
+       } else {
+               ret = -ENOENT;
+               goto err_queue_init;
+       }
+       /* One way to indicate end-of-stream for MFC is to set the
+        * bytesused == 0. However by default videobuf2 handles bytesused
+        * equal to 0 as a special case and changes its value to the size
+        * of the buffer. Set the allow_zero_bytesused flag so that videobuf2
+        * will keep the value of bytesused intact.
+        */
+       q->allow_zero_bytesused = 1;
+
+       /*
+        * We'll do mostly sequential access, so sacrifice TLB efficiency for
+        * faster allocation.
+        */
+       q->dma_attrs = DMA_ATTR_ALLOC_SINGLE_PAGES;
+       q->mem_ops = &vb2_dma_contig_memops;
+       q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+       ret = vb2_queue_init(q);
+       if (ret) {
+               mfc_err("Failed to initialize videobuf2 queue(output)\n");
+               goto err_queue_init;
+       }
+       mutex_unlock(&dev->mfc_mutex);
+       mfc_debug_leave();
+       return ret;
+       /* Deinit when failure occurred */
+err_queue_init:
+       if (dev->num_inst == 1)
+               s5p_mfc_deinit_hw(dev);
+err_init_hw:
+err_load_fw:
+err_pwr_enable:
+       if (dev->num_inst == 1) {
+               if (s5p_mfc_power_off() < 0)
+                       mfc_err("power off failed\n");
+               del_timer_sync(&dev->watchdog_timer);
+       }
+err_ctrls_setup:
+       s5p_mfc_dec_ctrls_delete(ctx);
+err_bad_node:
+       dev->ctx[ctx->num] = NULL;
+err_no_ctx:
+       v4l2_fh_del(&ctx->fh);
+       v4l2_fh_exit(&ctx->fh);
+       kfree(ctx);
+err_alloc:
+       dev->num_inst--;
+       mutex_unlock(&dev->mfc_mutex);
+       mfc_debug_leave();
+       return ret;
+}
+
+/* Release MFC context */
+static int s5p_mfc_release(struct file *file)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(file->private_data);
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       /* if dev is null, do cleanup that doesn't need dev */
+       mfc_debug_enter();
+       if (dev)
+               mutex_lock(&dev->mfc_mutex);
+       vb2_queue_release(&ctx->vq_src);
+       vb2_queue_release(&ctx->vq_dst);
+       if (dev) {
+               s5p_mfc_clock_on();
+
+               /* Mark context as idle */
+               clear_work_bit_irqsave(ctx);
+               /*
+                * If instance was initialised and not yet freed,
+                * return instance and free resources
+               */
+               if (ctx->state != MFCINST_FREE && ctx->state != MFCINST_INIT) {
+                       mfc_debug(2, "Has to free instance\n");
+                       s5p_mfc_close_mfc_inst(dev, ctx);
+               }
+               /* hardware locking scheme */
+               if (dev->curr_ctx == ctx->num)
+                       clear_bit(0, &dev->hw_lock);
+               dev->num_inst--;
+               if (dev->num_inst == 0) {
+                       mfc_debug(2, "Last instance\n");
+                       s5p_mfc_deinit_hw(dev);
+                       del_timer_sync(&dev->watchdog_timer);
+                       s5p_mfc_clock_off();
+                       if (s5p_mfc_power_off() < 0)
+                               mfc_err("Power off failed\n");
+               } else {
+                       mfc_debug(2, "Shutting down clock\n");
+                       s5p_mfc_clock_off();
+               }
+       }
+       if (dev)
+               dev->ctx[ctx->num] = NULL;
+       s5p_mfc_dec_ctrls_delete(ctx);
+       v4l2_fh_del(&ctx->fh);
+       /* vdev is gone if dev is null */
+       if (dev)
+               v4l2_fh_exit(&ctx->fh);
+       kfree(ctx);
+       mfc_debug_leave();
+       if (dev)
+               mutex_unlock(&dev->mfc_mutex);
+
+       return 0;
+}
+
+/* Poll */
+static __poll_t s5p_mfc_poll(struct file *file,
+                                struct poll_table_struct *wait)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(file->private_data);
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct vb2_queue *src_q, *dst_q;
+       struct vb2_buffer *src_vb = NULL, *dst_vb = NULL;
+       __poll_t rc = 0;
+       unsigned long flags;
+
+       mutex_lock(&dev->mfc_mutex);
+       src_q = &ctx->vq_src;
+       dst_q = &ctx->vq_dst;
+       /*
+        * There has to be at least one buffer queued on each queued_list, which
+        * means either in driver already or waiting for driver to claim it
+        * and start processing.
+        */
+       if ((!src_q->streaming || list_empty(&src_q->queued_list))
+               && (!dst_q->streaming || list_empty(&dst_q->queued_list))) {
+               rc = EPOLLERR;
+               goto end;
+       }
+       mutex_unlock(&dev->mfc_mutex);
+       poll_wait(file, &ctx->fh.wait, wait);
+       poll_wait(file, &src_q->done_wq, wait);
+       poll_wait(file, &dst_q->done_wq, wait);
+       mutex_lock(&dev->mfc_mutex);
+       if (v4l2_event_pending(&ctx->fh))
+               rc |= EPOLLPRI;
+       spin_lock_irqsave(&src_q->done_lock, flags);
+       if (!list_empty(&src_q->done_list))
+               src_vb = list_first_entry(&src_q->done_list, struct vb2_buffer,
+                                                               done_entry);
+       if (src_vb && (src_vb->state == VB2_BUF_STATE_DONE
+                               || src_vb->state == VB2_BUF_STATE_ERROR))
+               rc |= EPOLLOUT | EPOLLWRNORM;
+       spin_unlock_irqrestore(&src_q->done_lock, flags);
+       spin_lock_irqsave(&dst_q->done_lock, flags);
+       if (!list_empty(&dst_q->done_list))
+               dst_vb = list_first_entry(&dst_q->done_list, struct vb2_buffer,
+                                                               done_entry);
+       if (dst_vb && (dst_vb->state == VB2_BUF_STATE_DONE
+                               || dst_vb->state == VB2_BUF_STATE_ERROR))
+               rc |= EPOLLIN | EPOLLRDNORM;
+       spin_unlock_irqrestore(&dst_q->done_lock, flags);
+end:
+       mutex_unlock(&dev->mfc_mutex);
+       return rc;
+}
+
+/* Mmap */
+static int s5p_mfc_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(file->private_data);
+       unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+       int ret;
+
+       if (offset < DST_QUEUE_OFF_BASE) {
+               mfc_debug(2, "mmaping source\n");
+               ret = vb2_mmap(&ctx->vq_src, vma);
+       } else {                /* capture */
+               mfc_debug(2, "mmaping destination\n");
+               vma->vm_pgoff -= (DST_QUEUE_OFF_BASE >> PAGE_SHIFT);
+               ret = vb2_mmap(&ctx->vq_dst, vma);
+       }
+       return ret;
+}
+
+/* v4l2 ops */
+static const struct v4l2_file_operations s5p_mfc_fops = {
+       .owner = THIS_MODULE,
+       .open = s5p_mfc_open,
+       .release = s5p_mfc_release,
+       .poll = s5p_mfc_poll,
+       .unlocked_ioctl = video_ioctl2,
+       .mmap = s5p_mfc_mmap,
+};
+
+/* DMA memory related helper functions */
+static void s5p_mfc_memdev_release(struct device *dev)
+{
+       of_reserved_mem_device_release(dev);
+}
+
+static struct device *s5p_mfc_alloc_memdev(struct device *dev,
+                                          const char *name, unsigned int idx)
+{
+       struct device *child;
+       int ret;
+
+       child = devm_kzalloc(dev, sizeof(*child), GFP_KERNEL);
+       if (!child)
+               return NULL;
+
+       device_initialize(child);
+       dev_set_name(child, "%s:%s", dev_name(dev), name);
+       child->parent = dev;
+       child->coherent_dma_mask = dev->coherent_dma_mask;
+       child->dma_mask = dev->dma_mask;
+       child->release = s5p_mfc_memdev_release;
+       child->dma_parms = devm_kzalloc(dev, sizeof(*child->dma_parms),
+                                       GFP_KERNEL);
+       if (!child->dma_parms)
+               goto err;
+
+       /*
+        * The memdevs are not proper OF platform devices, so in order for them
+        * to be treated as valid DMA masters we need a bit of a hack to force
+        * them to inherit the MFC node's DMA configuration.
+        */
+       of_dma_configure(child, dev->of_node, true);
+
+       if (device_add(child) == 0) {
+               ret = of_reserved_mem_device_init_by_idx(child, dev->of_node,
+                                                        idx);
+               if (ret == 0)
+                       return child;
+               device_del(child);
+       }
+err:
+       put_device(child);
+       return NULL;
+}
+
+static int s5p_mfc_configure_2port_memory(struct s5p_mfc_dev *mfc_dev)
+{
+       struct device *dev = &mfc_dev->plat_dev->dev;
+       void *bank2_virt;
+       dma_addr_t bank2_dma_addr;
+       unsigned long align_size = 1 << MFC_BASE_ALIGN_ORDER;
+       int ret;
+
+       /*
+        * Create and initialize virtual devices for accessing
+        * reserved memory regions.
+        */
+       mfc_dev->mem_dev[BANK_L_CTX] = s5p_mfc_alloc_memdev(dev, "left",
+                                                          BANK_L_CTX);
+       if (!mfc_dev->mem_dev[BANK_L_CTX])
+               return -ENODEV;
+       mfc_dev->mem_dev[BANK_R_CTX] = s5p_mfc_alloc_memdev(dev, "right",
+                                                          BANK_R_CTX);
+       if (!mfc_dev->mem_dev[BANK_R_CTX]) {
+               device_unregister(mfc_dev->mem_dev[BANK_L_CTX]);
+               return -ENODEV;
+       }
+
+       /* Allocate memory for firmware and initialize both banks addresses */
+       ret = s5p_mfc_alloc_firmware(mfc_dev);
+       if (ret) {
+               device_unregister(mfc_dev->mem_dev[BANK_R_CTX]);
+               device_unregister(mfc_dev->mem_dev[BANK_L_CTX]);
+               return ret;
+       }
+
+       mfc_dev->dma_base[BANK_L_CTX] = mfc_dev->fw_buf.dma;
+
+       bank2_virt = dma_alloc_coherent(mfc_dev->mem_dev[BANK_R_CTX],
+                                      align_size, &bank2_dma_addr, GFP_KERNEL);
+       if (!bank2_virt) {
+               mfc_err("Allocating bank2 base failed\n");
+               s5p_mfc_release_firmware(mfc_dev);
+               device_unregister(mfc_dev->mem_dev[BANK_R_CTX]);
+               device_unregister(mfc_dev->mem_dev[BANK_L_CTX]);
+               return -ENOMEM;
+       }
+
+       /* Valid buffers passed to MFC encoder with LAST_FRAME command
+        * should not have address of bank2 - MFC will treat it as a null frame.
+        * To avoid such situation we set bank2 address below the pool address.
+        */
+       mfc_dev->dma_base[BANK_R_CTX] = bank2_dma_addr - align_size;
+
+       dma_free_coherent(mfc_dev->mem_dev[BANK_R_CTX], align_size, bank2_virt,
+                         bank2_dma_addr);
+
+       vb2_dma_contig_set_max_seg_size(mfc_dev->mem_dev[BANK_L_CTX],
+                                       DMA_BIT_MASK(32));
+       vb2_dma_contig_set_max_seg_size(mfc_dev->mem_dev[BANK_R_CTX],
+                                       DMA_BIT_MASK(32));
+
+       return 0;
+}
+
+static void s5p_mfc_unconfigure_2port_memory(struct s5p_mfc_dev *mfc_dev)
+{
+       device_unregister(mfc_dev->mem_dev[BANK_L_CTX]);
+       device_unregister(mfc_dev->mem_dev[BANK_R_CTX]);
+       vb2_dma_contig_clear_max_seg_size(mfc_dev->mem_dev[BANK_L_CTX]);
+       vb2_dma_contig_clear_max_seg_size(mfc_dev->mem_dev[BANK_R_CTX]);
+}
+
+static int s5p_mfc_configure_common_memory(struct s5p_mfc_dev *mfc_dev)
+{
+       struct device *dev = &mfc_dev->plat_dev->dev;
+       unsigned long mem_size = SZ_4M;
+
+       if (IS_ENABLED(CONFIG_DMA_CMA) || exynos_is_iommu_available(dev))
+               mem_size = SZ_8M;
+
+       if (mfc_mem_size)
+               mem_size = memparse(mfc_mem_size, NULL);
+
+       mfc_dev->mem_bitmap = bitmap_zalloc(mem_size >> PAGE_SHIFT, GFP_KERNEL);
+       if (!mfc_dev->mem_bitmap)
+               return -ENOMEM;
+
+       mfc_dev->mem_virt = dma_alloc_coherent(dev, mem_size,
+                                              &mfc_dev->mem_base, GFP_KERNEL);
+       if (!mfc_dev->mem_virt) {
+               bitmap_free(mfc_dev->mem_bitmap);
+               dev_err(dev, "failed to preallocate %ld MiB for the firmware and context buffers\n",
+                       (mem_size / SZ_1M));
+               return -ENOMEM;
+       }
+       mfc_dev->mem_size = mem_size;
+       mfc_dev->dma_base[BANK_L_CTX] = mfc_dev->mem_base;
+       mfc_dev->dma_base[BANK_R_CTX] = mfc_dev->mem_base;
+
+       /*
+        * MFC hardware cannot handle 0 as a base address, so mark first 128K
+        * as used (to keep required base alignment) and adjust base address
+        */
+       if (mfc_dev->mem_base == (dma_addr_t)0) {
+               unsigned int offset = 1 << MFC_BASE_ALIGN_ORDER;
+
+               bitmap_set(mfc_dev->mem_bitmap, 0, offset >> PAGE_SHIFT);
+               mfc_dev->dma_base[BANK_L_CTX] += offset;
+               mfc_dev->dma_base[BANK_R_CTX] += offset;
+       }
+
+       /* Firmware allocation cannot fail in this case */
+       s5p_mfc_alloc_firmware(mfc_dev);
+
+       mfc_dev->mem_dev[BANK_L_CTX] = mfc_dev->mem_dev[BANK_R_CTX] = dev;
+       vb2_dma_contig_set_max_seg_size(dev, DMA_BIT_MASK(32));
+
+       dev_info(dev, "preallocated %ld MiB buffer for the firmware and context buffers\n",
+                (mem_size / SZ_1M));
+
+       return 0;
+}
+
+static void s5p_mfc_unconfigure_common_memory(struct s5p_mfc_dev *mfc_dev)
+{
+       struct device *dev = &mfc_dev->plat_dev->dev;
+
+       dma_free_coherent(dev, mfc_dev->mem_size, mfc_dev->mem_virt,
+                         mfc_dev->mem_base);
+       bitmap_free(mfc_dev->mem_bitmap);
+       vb2_dma_contig_clear_max_seg_size(dev);
+}
+
+static int s5p_mfc_configure_dma_memory(struct s5p_mfc_dev *mfc_dev)
+{
+       struct device *dev = &mfc_dev->plat_dev->dev;
+
+       if (exynos_is_iommu_available(dev) || !IS_TWOPORT(mfc_dev))
+               return s5p_mfc_configure_common_memory(mfc_dev);
+       else
+               return s5p_mfc_configure_2port_memory(mfc_dev);
+}
+
+static void s5p_mfc_unconfigure_dma_memory(struct s5p_mfc_dev *mfc_dev)
+{
+       struct device *dev = &mfc_dev->plat_dev->dev;
+
+       s5p_mfc_release_firmware(mfc_dev);
+       if (exynos_is_iommu_available(dev) || !IS_TWOPORT(mfc_dev))
+               s5p_mfc_unconfigure_common_memory(mfc_dev);
+       else
+               s5p_mfc_unconfigure_2port_memory(mfc_dev);
+}
+
+/* MFC probe function */
+static int s5p_mfc_probe(struct platform_device *pdev)
+{
+       struct s5p_mfc_dev *dev;
+       struct video_device *vfd;
+       int ret;
+
+       pr_debug("%s++\n", __func__);
+       dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
+       if (!dev)
+               return -ENOMEM;
+
+       spin_lock_init(&dev->irqlock);
+       spin_lock_init(&dev->condlock);
+       dev->plat_dev = pdev;
+       if (!dev->plat_dev) {
+               mfc_err("No platform data specified\n");
+               return -ENODEV;
+       }
+
+       dev->variant = of_device_get_match_data(&pdev->dev);
+       if (!dev->variant) {
+               dev_err(&pdev->dev, "Failed to get device MFC hardware variant information\n");
+               return -ENOENT;
+       }
+
+       dev->regs_base = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(dev->regs_base))
+               return PTR_ERR(dev->regs_base);
+
+       ret = platform_get_irq(pdev, 0);
+       if (ret < 0)
+               return ret;
+       dev->irq = ret;
+       ret = devm_request_irq(&pdev->dev, dev->irq, s5p_mfc_irq,
+                                       0, pdev->name, dev);
+       if (ret) {
+               dev_err(&pdev->dev, "Failed to install irq (%d)\n", ret);
+               return ret;
+       }
+
+       ret = s5p_mfc_configure_dma_memory(dev);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "failed to configure DMA memory\n");
+               return ret;
+       }
+
+       ret = s5p_mfc_init_pm(dev);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "failed to get mfc clock source\n");
+               goto err_dma;
+       }
+
+       /*
+        * Load fails if fs isn't mounted. Try loading anyway.
+        * _open() will load it, it it fails now. Ignore failure.
+        */
+       s5p_mfc_load_firmware(dev);
+
+       mutex_init(&dev->mfc_mutex);
+       init_waitqueue_head(&dev->queue);
+       dev->hw_lock = 0;
+       INIT_WORK(&dev->watchdog_work, s5p_mfc_watchdog_worker);
+       atomic_set(&dev->watchdog_cnt, 0);
+       timer_setup(&dev->watchdog_timer, s5p_mfc_watchdog, 0);
+
+       ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
+       if (ret)
+               goto err_v4l2_dev_reg;
+
+       /* decoder */
+       vfd = video_device_alloc();
+       if (!vfd) {
+               v4l2_err(&dev->v4l2_dev, "Failed to allocate video device\n");
+               ret = -ENOMEM;
+               goto err_dec_alloc;
+       }
+       vfd->fops       = &s5p_mfc_fops;
+       vfd->ioctl_ops  = get_dec_v4l2_ioctl_ops();
+       vfd->release    = video_device_release;
+       vfd->lock       = &dev->mfc_mutex;
+       vfd->v4l2_dev   = &dev->v4l2_dev;
+       vfd->vfl_dir    = VFL_DIR_M2M;
+       vfd->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
+       set_bit(V4L2_FL_QUIRK_INVERTED_CROP, &vfd->flags);
+       snprintf(vfd->name, sizeof(vfd->name), "%s", S5P_MFC_DEC_NAME);
+       dev->vfd_dec    = vfd;
+       video_set_drvdata(vfd, dev);
+
+       /* encoder */
+       vfd = video_device_alloc();
+       if (!vfd) {
+               v4l2_err(&dev->v4l2_dev, "Failed to allocate video device\n");
+               ret = -ENOMEM;
+               goto err_enc_alloc;
+       }
+       vfd->fops       = &s5p_mfc_fops;
+       vfd->ioctl_ops  = get_enc_v4l2_ioctl_ops();
+       vfd->release    = video_device_release;
+       vfd->lock       = &dev->mfc_mutex;
+       vfd->v4l2_dev   = &dev->v4l2_dev;
+       vfd->vfl_dir    = VFL_DIR_M2M;
+       vfd->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
+       snprintf(vfd->name, sizeof(vfd->name), "%s", S5P_MFC_ENC_NAME);
+       dev->vfd_enc    = vfd;
+       video_set_drvdata(vfd, dev);
+       platform_set_drvdata(pdev, dev);
+
+       /* Initialize HW ops and commands based on MFC version */
+       s5p_mfc_init_hw_ops(dev);
+       s5p_mfc_init_hw_cmds(dev);
+       s5p_mfc_init_regs(dev);
+
+       /* Register decoder and encoder */
+       ret = video_register_device(dev->vfd_dec, VFL_TYPE_VIDEO, 0);
+       if (ret) {
+               v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
+               goto err_dec_reg;
+       }
+       v4l2_info(&dev->v4l2_dev,
+                 "decoder registered as /dev/video%d\n", dev->vfd_dec->num);
+
+       ret = video_register_device(dev->vfd_enc, VFL_TYPE_VIDEO, 0);
+       if (ret) {
+               v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
+               goto err_enc_reg;
+       }
+       v4l2_info(&dev->v4l2_dev,
+                 "encoder registered as /dev/video%d\n", dev->vfd_enc->num);
+
+       pr_debug("%s--\n", __func__);
+       return 0;
+
+/* Deinit MFC if probe had failed */
+err_enc_reg:
+       video_unregister_device(dev->vfd_dec);
+err_dec_reg:
+       video_device_release(dev->vfd_enc);
+err_enc_alloc:
+       video_device_release(dev->vfd_dec);
+err_dec_alloc:
+       v4l2_device_unregister(&dev->v4l2_dev);
+err_v4l2_dev_reg:
+       s5p_mfc_final_pm(dev);
+err_dma:
+       s5p_mfc_unconfigure_dma_memory(dev);
+
+       pr_debug("%s-- with error\n", __func__);
+       return ret;
+
+}
+
+/* Remove the driver */
+static int s5p_mfc_remove(struct platform_device *pdev)
+{
+       struct s5p_mfc_dev *dev = platform_get_drvdata(pdev);
+       struct s5p_mfc_ctx *ctx;
+       int i;
+
+       v4l2_info(&dev->v4l2_dev, "Removing %s\n", pdev->name);
+
+       /*
+        * Clear ctx dev pointer to avoid races between s5p_mfc_remove()
+        * and s5p_mfc_release() and s5p_mfc_release() accessing ctx->dev
+        * after s5p_mfc_remove() is run during unbind.
+       */
+       mutex_lock(&dev->mfc_mutex);
+       for (i = 0; i < MFC_NUM_CONTEXTS; i++) {
+               ctx = dev->ctx[i];
+               if (!ctx)
+                       continue;
+               /* clear ctx->dev */
+               ctx->dev = NULL;
+       }
+       mutex_unlock(&dev->mfc_mutex);
+
+       del_timer_sync(&dev->watchdog_timer);
+       flush_work(&dev->watchdog_work);
+
+       video_unregister_device(dev->vfd_enc);
+       video_unregister_device(dev->vfd_dec);
+       video_device_release(dev->vfd_enc);
+       video_device_release(dev->vfd_dec);
+       v4l2_device_unregister(&dev->v4l2_dev);
+       s5p_mfc_unconfigure_dma_memory(dev);
+
+       s5p_mfc_final_pm(dev);
+       return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+
+static int s5p_mfc_suspend(struct device *dev)
+{
+       struct s5p_mfc_dev *m_dev = dev_get_drvdata(dev);
+       int ret;
+
+       if (m_dev->num_inst == 0)
+               return 0;
+
+       if (test_and_set_bit(0, &m_dev->enter_suspend) != 0) {
+               mfc_err("Error: going to suspend for a second time\n");
+               return -EIO;
+       }
+
+       /* Check if we're processing then wait if it necessary. */
+       while (test_and_set_bit(0, &m_dev->hw_lock) != 0) {
+               /* Try and lock the HW */
+               /* Wait on the interrupt waitqueue */
+               ret = wait_event_interruptible_timeout(m_dev->queue,
+                       m_dev->int_cond, msecs_to_jiffies(MFC_INT_TIMEOUT));
+               if (ret == 0) {
+                       mfc_err("Waiting for hardware to finish timed out\n");
+                       clear_bit(0, &m_dev->enter_suspend);
+                       return -EIO;
+               }
+       }
+
+       ret = s5p_mfc_sleep(m_dev);
+       if (ret) {
+               clear_bit(0, &m_dev->enter_suspend);
+               clear_bit(0, &m_dev->hw_lock);
+       }
+       return ret;
+}
+
+static int s5p_mfc_resume(struct device *dev)
+{
+       struct s5p_mfc_dev *m_dev = dev_get_drvdata(dev);
+
+       if (m_dev->num_inst == 0)
+               return 0;
+       return s5p_mfc_wakeup(m_dev);
+}
+#endif
+
+/* Power management */
+static const struct dev_pm_ops s5p_mfc_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(s5p_mfc_suspend, s5p_mfc_resume)
+};
+
+static struct s5p_mfc_buf_size_v5 mfc_buf_size_v5 = {
+       .h264_ctx       = MFC_H264_CTX_BUF_SIZE,
+       .non_h264_ctx   = MFC_CTX_BUF_SIZE,
+       .dsc            = DESC_BUF_SIZE,
+       .shm            = SHARED_BUF_SIZE,
+};
+
+static struct s5p_mfc_buf_size buf_size_v5 = {
+       .fw     = MAX_FW_SIZE,
+       .cpb    = MAX_CPB_SIZE,
+       .priv   = &mfc_buf_size_v5,
+};
+
+static struct s5p_mfc_variant mfc_drvdata_v5 = {
+       .version        = MFC_VERSION,
+       .version_bit    = MFC_V5_BIT,
+       .port_num       = MFC_NUM_PORTS,
+       .buf_size       = &buf_size_v5,
+       .fw_name[0]     = "s5p-mfc.fw",
+       .clk_names      = {"mfc", "sclk_mfc"},
+       .num_clocks     = 2,
+       .use_clock_gating = true,
+};
+
+static struct s5p_mfc_buf_size_v6 mfc_buf_size_v6 = {
+       .dev_ctx        = MFC_CTX_BUF_SIZE_V6,
+       .h264_dec_ctx   = MFC_H264_DEC_CTX_BUF_SIZE_V6,
+       .other_dec_ctx  = MFC_OTHER_DEC_CTX_BUF_SIZE_V6,
+       .h264_enc_ctx   = MFC_H264_ENC_CTX_BUF_SIZE_V6,
+       .other_enc_ctx  = MFC_OTHER_ENC_CTX_BUF_SIZE_V6,
+};
+
+static struct s5p_mfc_buf_size buf_size_v6 = {
+       .fw     = MAX_FW_SIZE_V6,
+       .cpb    = MAX_CPB_SIZE_V6,
+       .priv   = &mfc_buf_size_v6,
+};
+
+static struct s5p_mfc_variant mfc_drvdata_v6 = {
+       .version        = MFC_VERSION_V6,
+       .version_bit    = MFC_V6_BIT,
+       .port_num       = MFC_NUM_PORTS_V6,
+       .buf_size       = &buf_size_v6,
+       .fw_name[0]     = "s5p-mfc-v6.fw",
+       /*
+        * v6-v2 firmware contains bug fixes and interface change
+        * for init buffer command
+        */
+       .fw_name[1]     = "s5p-mfc-v6-v2.fw",
+       .clk_names      = {"mfc"},
+       .num_clocks     = 1,
+};
+
+static struct s5p_mfc_buf_size_v6 mfc_buf_size_v7 = {
+       .dev_ctx        = MFC_CTX_BUF_SIZE_V7,
+       .h264_dec_ctx   = MFC_H264_DEC_CTX_BUF_SIZE_V7,
+       .other_dec_ctx  = MFC_OTHER_DEC_CTX_BUF_SIZE_V7,
+       .h264_enc_ctx   = MFC_H264_ENC_CTX_BUF_SIZE_V7,
+       .other_enc_ctx  = MFC_OTHER_ENC_CTX_BUF_SIZE_V7,
+};
+
+static struct s5p_mfc_buf_size buf_size_v7 = {
+       .fw     = MAX_FW_SIZE_V7,
+       .cpb    = MAX_CPB_SIZE_V7,
+       .priv   = &mfc_buf_size_v7,
+};
+
+static struct s5p_mfc_variant mfc_drvdata_v7 = {
+       .version        = MFC_VERSION_V7,
+       .version_bit    = MFC_V7_BIT,
+       .port_num       = MFC_NUM_PORTS_V7,
+       .buf_size       = &buf_size_v7,
+       .fw_name[0]     = "s5p-mfc-v7.fw",
+       .clk_names      = {"mfc", "sclk_mfc"},
+       .num_clocks     = 2,
+};
+
+static struct s5p_mfc_buf_size_v6 mfc_buf_size_v8 = {
+       .dev_ctx        = MFC_CTX_BUF_SIZE_V8,
+       .h264_dec_ctx   = MFC_H264_DEC_CTX_BUF_SIZE_V8,
+       .other_dec_ctx  = MFC_OTHER_DEC_CTX_BUF_SIZE_V8,
+       .h264_enc_ctx   = MFC_H264_ENC_CTX_BUF_SIZE_V8,
+       .other_enc_ctx  = MFC_OTHER_ENC_CTX_BUF_SIZE_V8,
+};
+
+static struct s5p_mfc_buf_size buf_size_v8 = {
+       .fw     = MAX_FW_SIZE_V8,
+       .cpb    = MAX_CPB_SIZE_V8,
+       .priv   = &mfc_buf_size_v8,
+};
+
+static struct s5p_mfc_variant mfc_drvdata_v8 = {
+       .version        = MFC_VERSION_V8,
+       .version_bit    = MFC_V8_BIT,
+       .port_num       = MFC_NUM_PORTS_V8,
+       .buf_size       = &buf_size_v8,
+       .fw_name[0]     = "s5p-mfc-v8.fw",
+       .clk_names      = {"mfc"},
+       .num_clocks     = 1,
+};
+
+static struct s5p_mfc_variant mfc_drvdata_v8_5433 = {
+       .version        = MFC_VERSION_V8,
+       .version_bit    = MFC_V8_BIT,
+       .port_num       = MFC_NUM_PORTS_V8,
+       .buf_size       = &buf_size_v8,
+       .fw_name[0]     = "s5p-mfc-v8.fw",
+       .clk_names      = {"pclk", "aclk", "aclk_xiu"},
+       .num_clocks     = 3,
+};
+
+static struct s5p_mfc_buf_size_v6 mfc_buf_size_v10 = {
+       .dev_ctx        = MFC_CTX_BUF_SIZE_V10,
+       .h264_dec_ctx   = MFC_H264_DEC_CTX_BUF_SIZE_V10,
+       .other_dec_ctx  = MFC_OTHER_DEC_CTX_BUF_SIZE_V10,
+       .h264_enc_ctx   = MFC_H264_ENC_CTX_BUF_SIZE_V10,
+       .hevc_enc_ctx   = MFC_HEVC_ENC_CTX_BUF_SIZE_V10,
+       .other_enc_ctx  = MFC_OTHER_ENC_CTX_BUF_SIZE_V10,
+};
+
+static struct s5p_mfc_buf_size buf_size_v10 = {
+       .fw     = MAX_FW_SIZE_V10,
+       .cpb    = MAX_CPB_SIZE_V10,
+       .priv   = &mfc_buf_size_v10,
+};
+
+static struct s5p_mfc_variant mfc_drvdata_v10 = {
+       .version        = MFC_VERSION_V10,
+       .version_bit    = MFC_V10_BIT,
+       .port_num       = MFC_NUM_PORTS_V10,
+       .buf_size       = &buf_size_v10,
+       .fw_name[0]     = "s5p-mfc-v10.fw",
+};
+
+static const struct of_device_id exynos_mfc_match[] = {
+       {
+               .compatible = "samsung,mfc-v5",
+               .data = &mfc_drvdata_v5,
+       }, {
+               .compatible = "samsung,mfc-v6",
+               .data = &mfc_drvdata_v6,
+       }, {
+               .compatible = "samsung,mfc-v7",
+               .data = &mfc_drvdata_v7,
+       }, {
+               .compatible = "samsung,mfc-v8",
+               .data = &mfc_drvdata_v8,
+       }, {
+               .compatible = "samsung,exynos5433-mfc",
+               .data = &mfc_drvdata_v8_5433,
+       }, {
+               .compatible = "samsung,mfc-v10",
+               .data = &mfc_drvdata_v10,
+       },
+       {},
+};
+MODULE_DEVICE_TABLE(of, exynos_mfc_match);
+
+static struct platform_driver s5p_mfc_driver = {
+       .probe          = s5p_mfc_probe,
+       .remove         = s5p_mfc_remove,
+       .driver = {
+               .name   = S5P_MFC_NAME,
+               .pm     = &s5p_mfc_pm_ops,
+               .of_match_table = exynos_mfc_match,
+       },
+};
+
+module_platform_driver(s5p_mfc_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Kamil Debski <k.debski@samsung.com>");
+MODULE_DESCRIPTION("Samsung S5P Multi Format Codec V4L2 driver");
+
diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_cmd.c b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_cmd.c
new file mode 100644 (file)
index 0000000..774c573
--- /dev/null
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * linux/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_cmd.c
+ *
+ * Copyright (C) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ */
+
+#include "s5p_mfc_cmd.h"
+#include "s5p_mfc_common.h"
+#include "s5p_mfc_debug.h"
+#include "s5p_mfc_cmd_v5.h"
+#include "s5p_mfc_cmd_v6.h"
+
+static struct s5p_mfc_hw_cmds *s5p_mfc_cmds;
+
+void s5p_mfc_init_hw_cmds(struct s5p_mfc_dev *dev)
+{
+       if (IS_MFCV6_PLUS(dev))
+               s5p_mfc_cmds = s5p_mfc_init_hw_cmds_v6();
+       else
+               s5p_mfc_cmds = s5p_mfc_init_hw_cmds_v5();
+
+       dev->mfc_cmds = s5p_mfc_cmds;
+}
diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_cmd.h b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_cmd.h
new file mode 100644 (file)
index 0000000..945d12f
--- /dev/null
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * linux/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_cmd.h
+ *
+ * Copyright (C) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ */
+
+#ifndef S5P_MFC_CMD_H_
+#define S5P_MFC_CMD_H_
+
+#include "s5p_mfc_common.h"
+
+#define MAX_H2R_ARG    4
+
+struct s5p_mfc_cmd_args {
+       unsigned int    arg[MAX_H2R_ARG];
+};
+
+struct s5p_mfc_hw_cmds {
+       int (*cmd_host2risc)(struct s5p_mfc_dev *dev, int cmd,
+                               struct s5p_mfc_cmd_args *args);
+       int (*sys_init_cmd)(struct s5p_mfc_dev *dev);
+       int (*sleep_cmd)(struct s5p_mfc_dev *dev);
+       int (*wakeup_cmd)(struct s5p_mfc_dev *dev);
+       int (*open_inst_cmd)(struct s5p_mfc_ctx *ctx);
+       int (*close_inst_cmd)(struct s5p_mfc_ctx *ctx);
+};
+
+void s5p_mfc_init_hw_cmds(struct s5p_mfc_dev *dev);
+#endif /* S5P_MFC_CMD_H_ */
diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_cmd_v5.c b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_cmd_v5.c
new file mode 100644 (file)
index 0000000..327e54e
--- /dev/null
@@ -0,0 +1,163 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * linux/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_cmd_v5.c
+ *
+ * Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ */
+
+#include "regs-mfc.h"
+#include "s5p_mfc_cmd.h"
+#include "s5p_mfc_common.h"
+#include "s5p_mfc_debug.h"
+#include "s5p_mfc_cmd_v5.h"
+
+/* This function is used to send a command to the MFC */
+static int s5p_mfc_cmd_host2risc_v5(struct s5p_mfc_dev *dev, int cmd,
+                               struct s5p_mfc_cmd_args *args)
+{
+       int cur_cmd;
+       unsigned long timeout;
+
+       timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
+       /* wait until host to risc command register becomes 'H2R_CMD_EMPTY' */
+       do {
+               if (time_after(jiffies, timeout)) {
+                       mfc_err("Timeout while waiting for hardware\n");
+                       return -EIO;
+               }
+               cur_cmd = mfc_read(dev, S5P_FIMV_HOST2RISC_CMD);
+       } while (cur_cmd != S5P_FIMV_H2R_CMD_EMPTY);
+       mfc_write(dev, args->arg[0], S5P_FIMV_HOST2RISC_ARG1);
+       mfc_write(dev, args->arg[1], S5P_FIMV_HOST2RISC_ARG2);
+       mfc_write(dev, args->arg[2], S5P_FIMV_HOST2RISC_ARG3);
+       mfc_write(dev, args->arg[3], S5P_FIMV_HOST2RISC_ARG4);
+       /* Issue the command */
+       mfc_write(dev, cmd, S5P_FIMV_HOST2RISC_CMD);
+       return 0;
+}
+
+/* Initialize the MFC */
+static int s5p_mfc_sys_init_cmd_v5(struct s5p_mfc_dev *dev)
+{
+       struct s5p_mfc_cmd_args h2r_args;
+
+       memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
+       h2r_args.arg[0] = dev->fw_buf.size;
+       return s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_SYS_INIT,
+                       &h2r_args);
+}
+
+/* Suspend the MFC hardware */
+static int s5p_mfc_sleep_cmd_v5(struct s5p_mfc_dev *dev)
+{
+       struct s5p_mfc_cmd_args h2r_args;
+
+       memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
+       return s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_SLEEP, &h2r_args);
+}
+
+/* Wake up the MFC hardware */
+static int s5p_mfc_wakeup_cmd_v5(struct s5p_mfc_dev *dev)
+{
+       struct s5p_mfc_cmd_args h2r_args;
+
+       memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
+       return s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_WAKEUP,
+                       &h2r_args);
+}
+
+
+static int s5p_mfc_open_inst_cmd_v5(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_cmd_args h2r_args;
+       int ret;
+
+       /* Preparing decoding - getting instance number */
+       mfc_debug(2, "Getting instance number (codec: %d)\n", ctx->codec_mode);
+       dev->curr_ctx = ctx->num;
+       memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
+       switch (ctx->codec_mode) {
+       case S5P_MFC_CODEC_H264_DEC:
+               h2r_args.arg[0] = S5P_FIMV_CODEC_H264_DEC;
+               break;
+       case S5P_MFC_CODEC_VC1_DEC:
+               h2r_args.arg[0] = S5P_FIMV_CODEC_VC1_DEC;
+               break;
+       case S5P_MFC_CODEC_MPEG4_DEC:
+               h2r_args.arg[0] = S5P_FIMV_CODEC_MPEG4_DEC;
+               break;
+       case S5P_MFC_CODEC_MPEG2_DEC:
+               h2r_args.arg[0] = S5P_FIMV_CODEC_MPEG2_DEC;
+               break;
+       case S5P_MFC_CODEC_H263_DEC:
+               h2r_args.arg[0] = S5P_FIMV_CODEC_H263_DEC;
+               break;
+       case S5P_MFC_CODEC_VC1RCV_DEC:
+               h2r_args.arg[0] = S5P_FIMV_CODEC_VC1RCV_DEC;
+               break;
+       case S5P_MFC_CODEC_H264_ENC:
+               h2r_args.arg[0] = S5P_FIMV_CODEC_H264_ENC;
+               break;
+       case S5P_MFC_CODEC_MPEG4_ENC:
+               h2r_args.arg[0] = S5P_FIMV_CODEC_MPEG4_ENC;
+               break;
+       case S5P_MFC_CODEC_H263_ENC:
+               h2r_args.arg[0] = S5P_FIMV_CODEC_H263_ENC;
+               break;
+       default:
+               h2r_args.arg[0] = S5P_FIMV_CODEC_NONE;
+       }
+       h2r_args.arg[1] = 0; /* no crc & no pixelcache */
+       h2r_args.arg[2] = ctx->ctx.ofs;
+       h2r_args.arg[3] = ctx->ctx.size;
+       ret = s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_OPEN_INSTANCE,
+                                                               &h2r_args);
+       if (ret) {
+               mfc_err("Failed to create a new instance\n");
+               ctx->state = MFCINST_ERROR;
+       }
+       return ret;
+}
+
+static int s5p_mfc_close_inst_cmd_v5(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_cmd_args h2r_args;
+       int ret;
+
+       if (ctx->state == MFCINST_FREE) {
+               mfc_err("Instance already returned\n");
+               ctx->state = MFCINST_ERROR;
+               return -EINVAL;
+       }
+       /* Closing decoding instance  */
+       mfc_debug(2, "Returning instance number %d\n", ctx->inst_no);
+       dev->curr_ctx = ctx->num;
+       memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
+       h2r_args.arg[0] = ctx->inst_no;
+       ret = s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_CLOSE_INSTANCE,
+                                                               &h2r_args);
+       if (ret) {
+               mfc_err("Failed to return an instance\n");
+               ctx->state = MFCINST_ERROR;
+               return -EINVAL;
+       }
+       return 0;
+}
+
+/* Initialize cmd function pointers for MFC v5 */
+static struct s5p_mfc_hw_cmds s5p_mfc_cmds_v5 = {
+       .cmd_host2risc = s5p_mfc_cmd_host2risc_v5,
+       .sys_init_cmd = s5p_mfc_sys_init_cmd_v5,
+       .sleep_cmd = s5p_mfc_sleep_cmd_v5,
+       .wakeup_cmd = s5p_mfc_wakeup_cmd_v5,
+       .open_inst_cmd = s5p_mfc_open_inst_cmd_v5,
+       .close_inst_cmd = s5p_mfc_close_inst_cmd_v5,
+};
+
+struct s5p_mfc_hw_cmds *s5p_mfc_init_hw_cmds_v5(void)
+{
+       return &s5p_mfc_cmds_v5;
+}
diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_cmd_v5.h b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_cmd_v5.h
new file mode 100644 (file)
index 0000000..6eafa51
--- /dev/null
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * linux/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_cmd_v5.h
+ *
+ * Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ */
+
+#ifndef S5P_MFC_CMD_V5_H_
+#define S5P_MFC_CMD_V5_H_
+
+#include "s5p_mfc_common.h"
+
+struct s5p_mfc_hw_cmds *s5p_mfc_init_hw_cmds_v5(void);
+
+#endif /* S5P_MFC_CMD_H_ */
diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_cmd_v6.c b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_cmd_v6.c
new file mode 100644 (file)
index 0000000..f8588e5
--- /dev/null
@@ -0,0 +1,169 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * linux/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_cmd_v6.c
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ */
+
+#include "s5p_mfc_common.h"
+
+#include "s5p_mfc_cmd.h"
+#include "s5p_mfc_debug.h"
+#include "s5p_mfc_intr.h"
+#include "s5p_mfc_opr.h"
+#include "s5p_mfc_cmd_v6.h"
+
+static int s5p_mfc_cmd_host2risc_v6(struct s5p_mfc_dev *dev, int cmd,
+                               struct s5p_mfc_cmd_args *args)
+{
+       mfc_debug(2, "Issue the command: %d\n", cmd);
+
+       /* Reset RISC2HOST command */
+       mfc_write(dev, 0x0, S5P_FIMV_RISC2HOST_CMD_V6);
+
+       /* Issue the command */
+       mfc_write(dev, cmd, S5P_FIMV_HOST2RISC_CMD_V6);
+       mfc_write(dev, 0x1, S5P_FIMV_HOST2RISC_INT_V6);
+
+       return 0;
+}
+
+static int s5p_mfc_sys_init_cmd_v6(struct s5p_mfc_dev *dev)
+{
+       struct s5p_mfc_cmd_args h2r_args;
+       struct s5p_mfc_buf_size_v6 *buf_size = dev->variant->buf_size->priv;
+       int ret;
+
+       ret = s5p_mfc_hw_call(dev->mfc_ops, alloc_dev_context_buffer, dev);
+       if (ret)
+               return ret;
+
+       mfc_write(dev, dev->ctx_buf.dma, S5P_FIMV_CONTEXT_MEM_ADDR_V6);
+       mfc_write(dev, buf_size->dev_ctx, S5P_FIMV_CONTEXT_MEM_SIZE_V6);
+       return s5p_mfc_cmd_host2risc_v6(dev, S5P_FIMV_H2R_CMD_SYS_INIT_V6,
+                                       &h2r_args);
+}
+
+static int s5p_mfc_sleep_cmd_v6(struct s5p_mfc_dev *dev)
+{
+       struct s5p_mfc_cmd_args h2r_args;
+
+       memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
+       return s5p_mfc_cmd_host2risc_v6(dev, S5P_FIMV_H2R_CMD_SLEEP_V6,
+                       &h2r_args);
+}
+
+static int s5p_mfc_wakeup_cmd_v6(struct s5p_mfc_dev *dev)
+{
+       struct s5p_mfc_cmd_args h2r_args;
+
+       memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
+       return s5p_mfc_cmd_host2risc_v6(dev, S5P_FIMV_H2R_CMD_WAKEUP_V6,
+                                       &h2r_args);
+}
+
+/* Open a new instance and get its number */
+static int s5p_mfc_open_inst_cmd_v6(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_cmd_args h2r_args;
+       int codec_type;
+
+       mfc_debug(2, "Requested codec mode: %d\n", ctx->codec_mode);
+       dev->curr_ctx = ctx->num;
+       switch (ctx->codec_mode) {
+       case S5P_MFC_CODEC_H264_DEC:
+               codec_type = S5P_FIMV_CODEC_H264_DEC_V6;
+               break;
+       case S5P_MFC_CODEC_H264_MVC_DEC:
+               codec_type = S5P_FIMV_CODEC_H264_MVC_DEC_V6;
+               break;
+       case S5P_MFC_CODEC_VC1_DEC:
+               codec_type = S5P_FIMV_CODEC_VC1_DEC_V6;
+               break;
+       case S5P_MFC_CODEC_MPEG4_DEC:
+               codec_type = S5P_FIMV_CODEC_MPEG4_DEC_V6;
+               break;
+       case S5P_MFC_CODEC_MPEG2_DEC:
+               codec_type = S5P_FIMV_CODEC_MPEG2_DEC_V6;
+               break;
+       case S5P_MFC_CODEC_H263_DEC:
+               codec_type = S5P_FIMV_CODEC_H263_DEC_V6;
+               break;
+       case S5P_MFC_CODEC_VC1RCV_DEC:
+               codec_type = S5P_FIMV_CODEC_VC1RCV_DEC_V6;
+               break;
+       case S5P_MFC_CODEC_VP8_DEC:
+               codec_type = S5P_FIMV_CODEC_VP8_DEC_V6;
+               break;
+       case S5P_MFC_CODEC_HEVC_DEC:
+               codec_type = S5P_FIMV_CODEC_HEVC_DEC;
+               break;
+       case S5P_MFC_CODEC_VP9_DEC:
+               codec_type = S5P_FIMV_CODEC_VP9_DEC;
+               break;
+       case S5P_MFC_CODEC_H264_ENC:
+               codec_type = S5P_FIMV_CODEC_H264_ENC_V6;
+               break;
+       case S5P_MFC_CODEC_H264_MVC_ENC:
+               codec_type = S5P_FIMV_CODEC_H264_MVC_ENC_V6;
+               break;
+       case S5P_MFC_CODEC_MPEG4_ENC:
+               codec_type = S5P_FIMV_CODEC_MPEG4_ENC_V6;
+               break;
+       case S5P_MFC_CODEC_H263_ENC:
+               codec_type = S5P_FIMV_CODEC_H263_ENC_V6;
+               break;
+       case S5P_MFC_CODEC_VP8_ENC:
+               codec_type = S5P_FIMV_CODEC_VP8_ENC_V7;
+               break;
+       case S5P_MFC_CODEC_HEVC_ENC:
+               codec_type = S5P_FIMV_CODEC_HEVC_ENC;
+               break;
+       default:
+               codec_type = S5P_FIMV_CODEC_NONE_V6;
+       }
+       mfc_write(dev, codec_type, S5P_FIMV_CODEC_TYPE_V6);
+       mfc_write(dev, ctx->ctx.dma, S5P_FIMV_CONTEXT_MEM_ADDR_V6);
+       mfc_write(dev, ctx->ctx.size, S5P_FIMV_CONTEXT_MEM_SIZE_V6);
+       mfc_write(dev, 0, S5P_FIMV_D_CRC_CTRL_V6); /* no crc */
+
+       return s5p_mfc_cmd_host2risc_v6(dev, S5P_FIMV_H2R_CMD_OPEN_INSTANCE_V6,
+                                       &h2r_args);
+}
+
+/* Close instance */
+static int s5p_mfc_close_inst_cmd_v6(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_cmd_args h2r_args;
+       int ret = 0;
+
+       dev->curr_ctx = ctx->num;
+       if (ctx->state != MFCINST_FREE) {
+               mfc_write(dev, ctx->inst_no, S5P_FIMV_INSTANCE_ID_V6);
+               ret = s5p_mfc_cmd_host2risc_v6(dev,
+                                       S5P_FIMV_H2R_CMD_CLOSE_INSTANCE_V6,
+                                       &h2r_args);
+       } else {
+               ret = -EINVAL;
+       }
+
+       return ret;
+}
+
+/* Initialize cmd function pointers for MFC v6 */
+static struct s5p_mfc_hw_cmds s5p_mfc_cmds_v6 = {
+       .cmd_host2risc = s5p_mfc_cmd_host2risc_v6,
+       .sys_init_cmd = s5p_mfc_sys_init_cmd_v6,
+       .sleep_cmd = s5p_mfc_sleep_cmd_v6,
+       .wakeup_cmd = s5p_mfc_wakeup_cmd_v6,
+       .open_inst_cmd = s5p_mfc_open_inst_cmd_v6,
+       .close_inst_cmd = s5p_mfc_close_inst_cmd_v6,
+};
+
+struct s5p_mfc_hw_cmds *s5p_mfc_init_hw_cmds_v6(void)
+{
+       return &s5p_mfc_cmds_v6;
+}
diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_cmd_v6.h b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_cmd_v6.h
new file mode 100644 (file)
index 0000000..9dc4446
--- /dev/null
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * linux/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_cmd_v6.h
+ *
+ * Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ */
+
+#ifndef S5P_MFC_CMD_V6_H_
+#define S5P_MFC_CMD_V6_H_
+
+#include "s5p_mfc_common.h"
+
+struct s5p_mfc_hw_cmds *s5p_mfc_init_hw_cmds_v6(void);
+
+#endif /* S5P_MFC_CMD_H_ */
diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_common.h
new file mode 100644 (file)
index 0000000..5304f42
--- /dev/null
@@ -0,0 +1,792 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Samsung S5P Multi Format Codec v 5.0
+ *
+ * This file contains definitions of enums and structs used by the codec
+ * driver.
+ *
+ * Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ * Kamil Debski, <k.debski@samsung.com>
+ */
+
+#ifndef S5P_MFC_COMMON_H_
+#define S5P_MFC_COMMON_H_
+
+#include <linux/platform_device.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <media/videobuf2-v4l2.h>
+#include "regs-mfc.h"
+#include "regs-mfc-v10.h"
+
+#define S5P_MFC_NAME           "s5p-mfc"
+
+/* Definitions related to MFC memory */
+
+/* Offset base used to differentiate between CAPTURE and OUTPUT
+*  while mmaping */
+#define DST_QUEUE_OFF_BASE     (1 << 30)
+
+#define BANK_L_CTX     0
+#define BANK_R_CTX     1
+#define BANK_CTX_NUM   2
+
+#define MFC_BANK1_ALIGN_ORDER  13
+#define MFC_BANK2_ALIGN_ORDER  13
+#define MFC_BASE_ALIGN_ORDER   17
+
+#define MFC_FW_MAX_VERSIONS    2
+
+#include <media/videobuf2-dma-contig.h>
+
+/* MFC definitions */
+#define MFC_MAX_EXTRA_DPB       5
+#define MFC_MAX_BUFFERS                32
+#define MFC_NUM_CONTEXTS       4
+/* Interrupt timeout */
+#define MFC_INT_TIMEOUT                2000
+/* Busy wait timeout */
+#define MFC_BW_TIMEOUT         500
+/* Watchdog interval */
+#define MFC_WATCHDOG_INTERVAL   1000
+/* After how many executions watchdog should assume lock up */
+#define MFC_WATCHDOG_CNT        10
+#define MFC_NO_INSTANCE_SET    -1
+#define MFC_ENC_CAP_PLANE_COUNT        1
+#define MFC_ENC_OUT_PLANE_COUNT        2
+#define STUFF_BYTE             4
+#define MFC_MAX_CTRLS          128
+
+#define S5P_MFC_CODEC_NONE             -1
+#define S5P_MFC_CODEC_H264_DEC         0
+#define S5P_MFC_CODEC_H264_MVC_DEC     1
+#define S5P_MFC_CODEC_VC1_DEC          2
+#define S5P_MFC_CODEC_MPEG4_DEC                3
+#define S5P_MFC_CODEC_MPEG2_DEC                4
+#define S5P_MFC_CODEC_H263_DEC         5
+#define S5P_MFC_CODEC_VC1RCV_DEC       6
+#define S5P_MFC_CODEC_VP8_DEC          7
+#define S5P_MFC_CODEC_HEVC_DEC         17
+#define S5P_MFC_CODEC_VP9_DEC          18
+
+#define S5P_MFC_CODEC_H264_ENC         20
+#define S5P_MFC_CODEC_H264_MVC_ENC     21
+#define S5P_MFC_CODEC_MPEG4_ENC                22
+#define S5P_MFC_CODEC_H263_ENC         23
+#define S5P_MFC_CODEC_VP8_ENC          24
+#define S5P_MFC_CODEC_HEVC_ENC         26
+
+#define S5P_MFC_R2H_CMD_EMPTY                  0
+#define S5P_MFC_R2H_CMD_SYS_INIT_RET           1
+#define S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET      2
+#define S5P_MFC_R2H_CMD_SEQ_DONE_RET           3
+#define S5P_MFC_R2H_CMD_INIT_BUFFERS_RET       4
+#define S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET     6
+#define S5P_MFC_R2H_CMD_SLEEP_RET              7
+#define S5P_MFC_R2H_CMD_WAKEUP_RET             8
+#define S5P_MFC_R2H_CMD_COMPLETE_SEQ_RET       9
+#define S5P_MFC_R2H_CMD_DPB_FLUSH_RET          10
+#define S5P_MFC_R2H_CMD_NAL_ABORT_RET          11
+#define S5P_MFC_R2H_CMD_FW_STATUS_RET          12
+#define S5P_MFC_R2H_CMD_FRAME_DONE_RET         13
+#define S5P_MFC_R2H_CMD_FIELD_DONE_RET         14
+#define S5P_MFC_R2H_CMD_SLICE_DONE_RET         15
+#define S5P_MFC_R2H_CMD_ENC_BUFFER_FUL_RET     16
+#define S5P_MFC_R2H_CMD_ERR_RET                        32
+
+#define MFC_MAX_CLOCKS         4
+
+#define mfc_read(dev, offset)          readl(dev->regs_base + (offset))
+#define mfc_write(dev, data, offset)   writel((data), dev->regs_base + \
+                                                               (offset))
+
+/*
+ * enum s5p_mfc_fmt_type - type of the pixelformat
+ */
+enum s5p_mfc_fmt_type {
+       MFC_FMT_DEC,
+       MFC_FMT_ENC,
+       MFC_FMT_RAW,
+};
+
+/*
+ * enum s5p_mfc_inst_type - The type of an MFC instance.
+ */
+enum s5p_mfc_inst_type {
+       MFCINST_INVALID,
+       MFCINST_DECODER,
+       MFCINST_ENCODER,
+};
+
+/*
+ * enum s5p_mfc_inst_state - The state of an MFC instance.
+ */
+enum s5p_mfc_inst_state {
+       MFCINST_FREE = 0,
+       MFCINST_INIT = 100,
+       MFCINST_GOT_INST,
+       MFCINST_HEAD_PARSED,
+       MFCINST_HEAD_PRODUCED,
+       MFCINST_BUFS_SET,
+       MFCINST_RUNNING,
+       MFCINST_FINISHING,
+       MFCINST_FINISHED,
+       MFCINST_RETURN_INST,
+       MFCINST_ERROR,
+       MFCINST_ABORT,
+       MFCINST_FLUSH,
+       MFCINST_RES_CHANGE_INIT,
+       MFCINST_RES_CHANGE_FLUSH,
+       MFCINST_RES_CHANGE_END,
+};
+
+/*
+ * enum s5p_mfc_queue_state - The state of buffer queue.
+ */
+enum s5p_mfc_queue_state {
+       QUEUE_FREE,
+       QUEUE_BUFS_REQUESTED,
+       QUEUE_BUFS_QUERIED,
+       QUEUE_BUFS_MMAPED,
+};
+
+/*
+ * enum s5p_mfc_decode_arg - type of frame decoding
+ */
+enum s5p_mfc_decode_arg {
+       MFC_DEC_FRAME,
+       MFC_DEC_LAST_FRAME,
+       MFC_DEC_RES_CHANGE,
+};
+
+enum s5p_mfc_fw_ver {
+       MFC_FW_V1,
+       MFC_FW_V2,
+};
+
+#define MFC_BUF_FLAG_USED      (1 << 0)
+#define MFC_BUF_FLAG_EOS       (1 << 1)
+
+struct s5p_mfc_ctx;
+
+/*
+ * struct s5p_mfc_buf - MFC buffer
+ */
+struct s5p_mfc_buf {
+       struct vb2_v4l2_buffer *b;
+       struct list_head list;
+       union {
+               struct {
+                       size_t luma;
+                       size_t chroma;
+               } raw;
+               size_t stream;
+       } cookie;
+       int flags;
+};
+
+/*
+ * struct s5p_mfc_pm - power management data structure
+ */
+struct s5p_mfc_pm {
+       struct clk      *clock_gate;
+       const char * const *clk_names;
+       struct clk      *clocks[MFC_MAX_CLOCKS];
+       int             num_clocks;
+       bool            use_clock_gating;
+
+       struct device   *device;
+};
+
+struct s5p_mfc_buf_size_v5 {
+       unsigned int h264_ctx;
+       unsigned int non_h264_ctx;
+       unsigned int dsc;
+       unsigned int shm;
+};
+
+struct s5p_mfc_buf_size_v6 {
+       unsigned int dev_ctx;
+       unsigned int h264_dec_ctx;
+       unsigned int other_dec_ctx;
+       unsigned int h264_enc_ctx;
+       unsigned int hevc_enc_ctx;
+       unsigned int other_enc_ctx;
+};
+
+struct s5p_mfc_buf_size {
+       unsigned int fw;
+       unsigned int cpb;
+       void *priv;
+};
+
+struct s5p_mfc_variant {
+       unsigned int version;
+       unsigned int port_num;
+       u32 version_bit;
+       struct s5p_mfc_buf_size *buf_size;
+       char    *fw_name[MFC_FW_MAX_VERSIONS];
+       const char      *clk_names[MFC_MAX_CLOCKS];
+       int             num_clocks;
+       bool            use_clock_gating;
+};
+
+/**
+ * struct s5p_mfc_priv_buf - represents internal used buffer
+ * @ofs:               offset of each buffer, will be used for MFC
+ * @virt:              kernel virtual address, only valid when the
+ *                     buffer accessed by driver
+ * @dma:               DMA address, only valid when kernel DMA API used
+ * @size:              size of the buffer
+ * @ctx:               memory context (bank) used for this allocation
+ */
+struct s5p_mfc_priv_buf {
+       unsigned long   ofs;
+       void            *virt;
+       dma_addr_t      dma;
+       size_t          size;
+       unsigned int    ctx;
+};
+
+/**
+ * struct s5p_mfc_dev - The struct containing driver internal parameters.
+ *
+ * @v4l2_dev:          v4l2_device
+ * @vfd_dec:           video device for decoding
+ * @vfd_enc:           video device for encoding
+ * @plat_dev:          platform device
+ * @mem_dev:           child devices of the memory banks
+ * @regs_base:         base address of the MFC hw registers
+ * @irq:               irq resource
+ * @dec_ctrl_handler:  control framework handler for decoding
+ * @enc_ctrl_handler:  control framework handler for encoding
+ * @pm:                        power management control
+ * @variant:           MFC hardware variant information
+ * @num_inst:          counter of active MFC instances
+ * @irqlock:           lock for operations on videobuf2 queues
+ * @condlock:          lock for changing/checking if a context is ready to be
+ *                     processed
+ * @mfc_mutex:         lock for video_device
+ * @int_cond:          variable used by the waitqueue
+ * @int_type:          type of last interrupt
+ * @int_err:           error number for last interrupt
+ * @queue:             waitqueue for waiting for completion of device commands
+ * @fw_buf:            the firmware buffer data structure
+ * @mem_size:          size of the firmware operation memory
+ * @mem_base:          base DMA address of the firmware operation memory
+ * @mem_bitmap:                bitmap for managing MFC internal buffer allocations
+ * @mem_virt:          virtual address of the firmware operation memory
+ * @dma_base:          address of the beginning of memory banks
+ * @hw_lock:           used for hardware locking
+ * @ctx:               array of driver contexts
+ * @curr_ctx:          number of the currently running context
+ * @ctx_work_bits:     used to mark which contexts are waiting for hardware
+ * @watchdog_cnt:      counter for the watchdog
+ * @watchdog_timer:    timer for the watchdog
+ * @watchdog_workqueue:        workqueue for the watchdog
+ * @watchdog_work:     worker for the watchdog
+ * @enter_suspend:     flag set when entering suspend
+ * @ctx_buf:           common context memory (MFCv6)
+ * @warn_start:                hardware error code from which warnings start
+ * @mfc_ops:           ops structure holding HW operation function pointers
+ * @mfc_cmds:          cmd structure holding HW commands function pointers
+ * @mfc_regs:          structure holding MFC registers
+ * @fw_ver:            loaded firmware sub-version
+ * @fw_get_done:       flag set when request_firmware() is complete and
+ *                     copied into fw_buf
+ * @risc_on:           flag indicates RISC is on or off
+ *
+ */
+struct s5p_mfc_dev {
+       struct v4l2_device      v4l2_dev;
+       struct video_device     *vfd_dec;
+       struct video_device     *vfd_enc;
+       struct platform_device  *plat_dev;
+       struct device           *mem_dev[BANK_CTX_NUM];
+       void __iomem            *regs_base;
+       int                     irq;
+       struct v4l2_ctrl_handler dec_ctrl_handler;
+       struct v4l2_ctrl_handler enc_ctrl_handler;
+       struct s5p_mfc_pm       pm;
+       const struct s5p_mfc_variant    *variant;
+       int num_inst;
+       spinlock_t irqlock;     /* lock when operating on context */
+       spinlock_t condlock;    /* lock when changing/checking if a context is
+                                       ready to be processed */
+       struct mutex mfc_mutex; /* video_device lock */
+       int int_cond;
+       int int_type;
+       unsigned int int_err;
+       wait_queue_head_t queue;
+       struct s5p_mfc_priv_buf fw_buf;
+       size_t mem_size;
+       dma_addr_t mem_base;
+       unsigned long *mem_bitmap;
+       void *mem_virt;
+       dma_addr_t dma_base[BANK_CTX_NUM];
+       unsigned long hw_lock;
+       struct s5p_mfc_ctx *ctx[MFC_NUM_CONTEXTS];
+       int curr_ctx;
+       unsigned long ctx_work_bits;
+       atomic_t watchdog_cnt;
+       struct timer_list watchdog_timer;
+       struct workqueue_struct *watchdog_workqueue;
+       struct work_struct watchdog_work;
+       unsigned long enter_suspend;
+
+       struct s5p_mfc_priv_buf ctx_buf;
+       int warn_start;
+       struct s5p_mfc_hw_ops *mfc_ops;
+       struct s5p_mfc_hw_cmds *mfc_cmds;
+       const struct s5p_mfc_regs *mfc_regs;
+       enum s5p_mfc_fw_ver fw_ver;
+       bool fw_get_done;
+       bool risc_on; /* indicates if RISC is on or off */
+};
+
+/*
+ * struct s5p_mfc_h264_enc_params - encoding parameters for h264
+ */
+struct s5p_mfc_h264_enc_params {
+       enum v4l2_mpeg_video_h264_profile profile;
+       enum v4l2_mpeg_video_h264_loop_filter_mode loop_filter_mode;
+       s8 loop_filter_alpha;
+       s8 loop_filter_beta;
+       enum v4l2_mpeg_video_h264_entropy_mode entropy_mode;
+       u8 max_ref_pic;
+       u8 num_ref_pic_4p;
+       int _8x8_transform;
+       int rc_mb_dark;
+       int rc_mb_smooth;
+       int rc_mb_static;
+       int rc_mb_activity;
+       int vui_sar;
+       u8 vui_sar_idc;
+       u16 vui_ext_sar_width;
+       u16 vui_ext_sar_height;
+       int open_gop;
+       u16 open_gop_size;
+       u8 rc_frame_qp;
+       u8 rc_min_qp;
+       u8 rc_max_qp;
+       u8 rc_p_frame_qp;
+       u8 rc_b_frame_qp;
+       enum v4l2_mpeg_video_h264_level level_v4l2;
+       int level;
+       u16 cpb_size;
+       int interlace;
+       u8 hier_qp;
+       u8 hier_qp_type;
+       u8 hier_qp_layer;
+       u8 hier_qp_layer_qp[7];
+       u8 sei_frame_packing;
+       u8 sei_fp_curr_frame_0;
+       u8 sei_fp_arrangement_type;
+
+       u8 fmo;
+       u8 fmo_map_type;
+       u8 fmo_slice_grp;
+       u8 fmo_chg_dir;
+       u32 fmo_chg_rate;
+       u32 fmo_run_len[4];
+       u8 aso;
+       u32 aso_slice_order[8];
+};
+
+/*
+ * struct s5p_mfc_mpeg4_enc_params - encoding parameters for h263 and mpeg4
+ */
+struct s5p_mfc_mpeg4_enc_params {
+       /* MPEG4 Only */
+       enum v4l2_mpeg_video_mpeg4_profile profile;
+       int quarter_pixel;
+       /* Common for MPEG4, H263 */
+       u16 vop_time_res;
+       u16 vop_frm_delta;
+       u8 rc_frame_qp;
+       u8 rc_min_qp;
+       u8 rc_max_qp;
+       u8 rc_p_frame_qp;
+       u8 rc_b_frame_qp;
+       enum v4l2_mpeg_video_mpeg4_level level_v4l2;
+       int level;
+};
+
+/*
+ * struct s5p_mfc_vp8_enc_params - encoding parameters for vp8
+ */
+struct s5p_mfc_vp8_enc_params {
+       u8 imd_4x4;
+       enum v4l2_vp8_num_partitions num_partitions;
+       enum v4l2_vp8_num_ref_frames num_ref;
+       u8 filter_level;
+       u8 filter_sharpness;
+       u32 golden_frame_ref_period;
+       enum v4l2_vp8_golden_frame_sel golden_frame_sel;
+       u8 hier_layer;
+       u8 hier_layer_qp[3];
+       u8 rc_min_qp;
+       u8 rc_max_qp;
+       u8 rc_frame_qp;
+       u8 rc_p_frame_qp;
+       u8 profile;
+};
+
+struct s5p_mfc_hevc_enc_params {
+       enum v4l2_mpeg_video_hevc_profile profile;
+       int level;
+       enum v4l2_mpeg_video_h264_level level_v4l2;
+       u8 tier;
+       u32 rc_framerate;
+       u8 rc_min_qp;
+       u8 rc_max_qp;
+       u8 rc_lcu_dark;
+       u8 rc_lcu_smooth;
+       u8 rc_lcu_static;
+       u8 rc_lcu_activity;
+       u8 rc_frame_qp;
+       u8 rc_p_frame_qp;
+       u8 rc_b_frame_qp;
+       u8 max_partition_depth;
+       u8 num_refs_for_p;
+       u8 refreshtype;
+       u16 refreshperiod;
+       s32 lf_beta_offset_div2;
+       s32 lf_tc_offset_div2;
+       u8 loopfilter;
+       u8 loopfilter_disable;
+       u8 loopfilter_across;
+       u8 nal_control_length_filed;
+       u8 nal_control_user_ref;
+       u8 nal_control_store_ref;
+       u8 const_intra_period_enable;
+       u8 lossless_cu_enable;
+       u8 wavefront_enable;
+       u8 enable_ltr;
+       u8 hier_qp_enable;
+       enum v4l2_mpeg_video_hevc_hier_coding_type hier_qp_type;
+       u8 num_hier_layer;
+       u8 hier_qp_layer[7];
+       u32 hier_bit_layer[7];
+       u8 sign_data_hiding;
+       u8 general_pb_enable;
+       u8 temporal_id_enable;
+       u8 strong_intra_smooth;
+       u8 intra_pu_split_disable;
+       u8 tmv_prediction_disable;
+       u8 max_num_merge_mv;
+       u8 eco_mode_enable;
+       u8 encoding_nostartcode_enable;
+       u8 size_of_length_field;
+       u8 prepend_sps_pps_to_idr;
+};
+
+/*
+ * struct s5p_mfc_enc_params - general encoding parameters
+ */
+struct s5p_mfc_enc_params {
+       u16 width;
+       u16 height;
+       u32 mv_h_range;
+       u32 mv_v_range;
+
+       u16 gop_size;
+       enum v4l2_mpeg_video_multi_slice_mode slice_mode;
+       u16 slice_mb;
+       u32 slice_bit;
+       u16 intra_refresh_mb;
+       int pad;
+       u8 pad_luma;
+       u8 pad_cb;
+       u8 pad_cr;
+       int rc_frame;
+       int rc_mb;
+       u32 rc_bitrate;
+       u16 rc_reaction_coeff;
+       u16 vbv_size;
+       u32 vbv_delay;
+
+       enum v4l2_mpeg_video_header_mode seq_hdr_mode;
+       enum v4l2_mpeg_mfc51_video_frame_skip_mode frame_skip_mode;
+       int fixed_target_bit;
+
+       u8 num_b_frame;
+       u32 rc_framerate_num;
+       u32 rc_framerate_denom;
+
+       struct {
+               struct s5p_mfc_h264_enc_params h264;
+               struct s5p_mfc_mpeg4_enc_params mpeg4;
+               struct s5p_mfc_vp8_enc_params vp8;
+               struct s5p_mfc_hevc_enc_params hevc;
+       } codec;
+
+};
+
+/*
+ * struct s5p_mfc_codec_ops - codec ops, used by encoding
+ */
+struct s5p_mfc_codec_ops {
+       /* initialization routines */
+       int (*pre_seq_start) (struct s5p_mfc_ctx *ctx);
+       int (*post_seq_start) (struct s5p_mfc_ctx *ctx);
+       /* execution routines */
+       int (*pre_frame_start) (struct s5p_mfc_ctx *ctx);
+       int (*post_frame_start) (struct s5p_mfc_ctx *ctx);
+};
+
+#define call_cop(c, op, args...)                               \
+       (((c)->c_ops->op) ?                                     \
+               ((c)->c_ops->op(args)) : 0)
+
+/**
+ * struct s5p_mfc_ctx - This struct contains the instance context
+ *
+ * @dev:               pointer to the s5p_mfc_dev of the device
+ * @fh:                        struct v4l2_fh
+ * @num:               number of the context that this structure describes
+ * @int_cond:          variable used by the waitqueue
+ * @int_type:          type of the last interrupt
+ * @int_err:           error number received from MFC hw in the interrupt
+ * @queue:             waitqueue that can be used to wait for this context to
+ *                     finish
+ * @src_fmt:           source pixelformat information
+ * @dst_fmt:           destination pixelformat information
+ * @vq_src:            vb2 queue for source buffers
+ * @vq_dst:            vb2 queue for destination buffers
+ * @src_queue:         driver internal queue for source buffers
+ * @dst_queue:         driver internal queue for destination buffers
+ * @src_queue_cnt:     number of buffers queued on the source internal queue
+ * @dst_queue_cnt:     number of buffers queued on the dest internal queue
+ * @type:              type of the instance - decoder or encoder
+ * @state:             state of the context
+ * @inst_no:           number of hw instance associated with the context
+ * @img_width:         width of the image that is decoded or encoded
+ * @img_height:                height of the image that is decoded or encoded
+ * @buf_width:         width of the buffer for processed image
+ * @buf_height:                height of the buffer for processed image
+ * @luma_size:         size of a luma plane
+ * @chroma_size:       size of a chroma plane
+ * @mv_size:           size of a motion vectors buffer
+ * @consumed_stream:   number of bytes that have been used so far from the
+ *                     decoding buffer
+ * @dpb_flush_flag:    flag used to indicate that a DPB buffers are being
+ *                     flushed
+ * @head_processed:    flag mentioning whether the header data is processed
+ *                     completely or not
+ * @bank1:             handle to memory allocated for temporary buffers from
+ *                     memory bank 1
+ * @bank2:             handle to memory allocated for temporary buffers from
+ *                     memory bank 2
+ * @capture_state:     state of the capture buffers queue
+ * @output_state:      state of the output buffers queue
+ * @src_bufs:          information on allocated source buffers
+ * @src_bufs_cnt:      number of allocated source buffers
+ * @dst_bufs:          information on allocated destination buffers
+ * @dst_bufs_cnt:      number of allocated destination buffers
+ * @sequence:          counter for the sequence number for v4l2
+ * @dec_dst_flag:      flags for buffers queued in the hardware
+ * @dec_src_buf_size:  size of the buffer for source buffers in decoding
+ * @codec_mode:                number of codec mode used by MFC hw
+ * @slice_interface:   slice interface flag
+ * @loop_filter_mpeg4: loop filter for MPEG4 flag
+ * @display_delay:     value of the display delay for H264
+ * @display_delay_enable:      display delay for H264 enable flag
+ * @after_packed_pb:   flag used to track buffer when stream is in
+ *                     Packed PB format
+ * @sei_fp_parse:      enable/disable parsing of frame packing SEI information
+ * @pb_count:          count of the DPB buffers required by MFC hw
+ * @total_dpb_count:   count of DPB buffers with additional buffers
+ *                     requested by the application
+ * @ctx:               context buffer information
+ * @dsc:               descriptor buffer information
+ * @shm:               shared memory buffer information
+ * @mv_count:          number of MV buffers allocated for decoding
+ * @enc_params:                encoding parameters for MFC
+ * @enc_dst_buf_size:  size of the buffers for encoder output
+ * @luma_dpb_size:     dpb buffer size for luma
+ * @chroma_dpb_size:   dpb buffer size for chroma
+ * @me_buffer_size:    size of the motion estimation buffer
+ * @tmv_buffer_size:   size of temporal predictor motion vector buffer
+ * @frame_type:                used to force the type of the next encoded frame
+ * @ref_queue:         list of the reference buffers for encoding
+ * @force_frame_type:  encoder's frame type forcing control
+ * @ref_queue_cnt:     number of the buffers in the reference list
+ * @slice_size:                slice size
+ * @slice_mode:                mode of dividing frames into slices
+ * @c_ops:             ops for encoding
+ * @ctrls:             array of controls, used when adding controls to the
+ *                     v4l2 control framework
+ * @ctrl_handler:      handler for v4l2 framework
+ * @scratch_buf_size:  scratch buffer size
+ */
+struct s5p_mfc_ctx {
+       struct s5p_mfc_dev *dev;
+       struct v4l2_fh fh;
+
+       int num;
+
+       int int_cond;
+       int int_type;
+       unsigned int int_err;
+       wait_queue_head_t queue;
+
+       struct s5p_mfc_fmt *src_fmt;
+       struct s5p_mfc_fmt *dst_fmt;
+
+       struct vb2_queue vq_src;
+       struct vb2_queue vq_dst;
+
+       struct list_head src_queue;
+       struct list_head dst_queue;
+
+       unsigned int src_queue_cnt;
+       unsigned int dst_queue_cnt;
+
+       enum s5p_mfc_inst_type type;
+       enum s5p_mfc_inst_state state;
+       int inst_no;
+
+       /* Image parameters */
+       int img_width;
+       int img_height;
+       int buf_width;
+       int buf_height;
+
+       int luma_size;
+       int chroma_size;
+       int mv_size;
+
+       unsigned long consumed_stream;
+
+       unsigned int dpb_flush_flag;
+       unsigned int head_processed;
+
+       struct s5p_mfc_priv_buf bank1;
+       struct s5p_mfc_priv_buf bank2;
+
+       enum s5p_mfc_queue_state capture_state;
+       enum s5p_mfc_queue_state output_state;
+
+       struct s5p_mfc_buf src_bufs[MFC_MAX_BUFFERS];
+       int src_bufs_cnt;
+       struct s5p_mfc_buf dst_bufs[MFC_MAX_BUFFERS];
+       int dst_bufs_cnt;
+
+       unsigned int sequence;
+       unsigned long dec_dst_flag;
+       size_t dec_src_buf_size;
+
+       /* Control values */
+       int codec_mode;
+       int slice_interface;
+       int loop_filter_mpeg4;
+       int display_delay;
+       int display_delay_enable;
+       int after_packed_pb;
+       int sei_fp_parse;
+
+       int pb_count;
+       int total_dpb_count;
+       int mv_count;
+       /* Buffers */
+       struct s5p_mfc_priv_buf ctx;
+       struct s5p_mfc_priv_buf dsc;
+       struct s5p_mfc_priv_buf shm;
+
+       struct s5p_mfc_enc_params enc_params;
+
+       size_t enc_dst_buf_size;
+       size_t luma_dpb_size;
+       size_t chroma_dpb_size;
+       size_t me_buffer_size;
+       size_t tmv_buffer_size;
+
+       enum v4l2_mpeg_mfc51_video_force_frame_type force_frame_type;
+
+       struct list_head ref_queue;
+       unsigned int ref_queue_cnt;
+
+       enum v4l2_mpeg_video_multi_slice_mode slice_mode;
+       union {
+               unsigned int mb;
+               unsigned int bits;
+       } slice_size;
+
+       const struct s5p_mfc_codec_ops *c_ops;
+
+       struct v4l2_ctrl *ctrls[MFC_MAX_CTRLS];
+       struct v4l2_ctrl_handler ctrl_handler;
+       size_t scratch_buf_size;
+};
+
+/*
+ * struct s5p_mfc_fmt -        structure used to store information about pixelformats
+ *                     used by the MFC
+ */
+struct s5p_mfc_fmt {
+       u32 fourcc;
+       u32 codec_mode;
+       enum s5p_mfc_fmt_type type;
+       u32 num_planes;
+       u32 versions;
+       u32 flags;
+};
+
+/*
+ * struct mfc_control -        structure used to store information about MFC controls
+ *                     it is used to initialize the control framework.
+ */
+struct mfc_control {
+       __u32                   id;
+       enum v4l2_ctrl_type     type;
+       __u8                    name[32];  /* Whatever */
+       __s32                   minimum;   /* Note signedness */
+       __s32                   maximum;
+       __s32                   step;
+       __u32                   menu_skip_mask;
+       __s32                   default_value;
+       __u32                   flags;
+       __u32                   reserved[2];
+       __u8                    is_volatile;
+};
+
+/* Macro for making hardware specific calls */
+#define s5p_mfc_hw_call(f, op, args...) \
+       ((f && f->op) ? f->op(args) : (typeof(f->op(args)))(-ENODEV))
+
+#define fh_to_ctx(__fh) container_of(__fh, struct s5p_mfc_ctx, fh)
+#define ctrl_to_ctx(__ctrl) \
+       container_of((__ctrl)->handler, struct s5p_mfc_ctx, ctrl_handler)
+
+void clear_work_bit(struct s5p_mfc_ctx *ctx);
+void set_work_bit(struct s5p_mfc_ctx *ctx);
+void clear_work_bit_irqsave(struct s5p_mfc_ctx *ctx);
+void set_work_bit_irqsave(struct s5p_mfc_ctx *ctx);
+int s5p_mfc_get_new_ctx(struct s5p_mfc_dev *dev);
+void s5p_mfc_cleanup_queue(struct list_head *lh, struct vb2_queue *vq);
+
+#define HAS_PORTNUM(dev)       (dev ? (dev->variant ? \
+                               (dev->variant->port_num ? 1 : 0) : 0) : 0)
+#define IS_TWOPORT(dev)                (dev->variant->port_num == 2 ? 1 : 0)
+#define IS_MFCV6_PLUS(dev)     (dev->variant->version >= 0x60 ? 1 : 0)
+#define IS_MFCV7_PLUS(dev)     (dev->variant->version >= 0x70 ? 1 : 0)
+#define IS_MFCV8_PLUS(dev)     (dev->variant->version >= 0x80 ? 1 : 0)
+#define IS_MFCV10(dev)         (dev->variant->version >= 0xA0 ? 1 : 0)
+#define FW_HAS_E_MIN_SCRATCH_BUF(dev) (IS_MFCV10(dev))
+
+#define MFC_V5_BIT     BIT(0)
+#define MFC_V6_BIT     BIT(1)
+#define MFC_V7_BIT     BIT(2)
+#define MFC_V8_BIT     BIT(3)
+#define MFC_V10_BIT    BIT(5)
+
+#define MFC_V5PLUS_BITS                (MFC_V5_BIT | MFC_V6_BIT | MFC_V7_BIT | \
+                                       MFC_V8_BIT | MFC_V10_BIT)
+#define MFC_V6PLUS_BITS                (MFC_V6_BIT | MFC_V7_BIT | MFC_V8_BIT | \
+                                       MFC_V10_BIT)
+#define MFC_V7PLUS_BITS                (MFC_V7_BIT | MFC_V8_BIT | MFC_V10_BIT)
+
+#endif /* S5P_MFC_COMMON_H_ */
diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_ctrl.c b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_ctrl.c
new file mode 100644 (file)
index 0000000..72d7098
--- /dev/null
@@ -0,0 +1,482 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * linux/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_ctrl.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ */
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/firmware.h>
+#include <linux/jiffies.h>
+#include <linux/sched.h>
+#include "s5p_mfc_cmd.h"
+#include "s5p_mfc_common.h"
+#include "s5p_mfc_debug.h"
+#include "s5p_mfc_intr.h"
+#include "s5p_mfc_opr.h"
+#include "s5p_mfc_pm.h"
+#include "s5p_mfc_ctrl.h"
+
+/* Allocate memory for firmware */
+int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev)
+{
+       struct s5p_mfc_priv_buf *fw_buf = &dev->fw_buf;
+       int err;
+
+       fw_buf->size = dev->variant->buf_size->fw;
+
+       if (fw_buf->virt) {
+               mfc_err("Attempting to allocate firmware when it seems that it is already loaded\n");
+               return -ENOMEM;
+       }
+
+       err = s5p_mfc_alloc_priv_buf(dev, BANK_L_CTX, &dev->fw_buf);
+       if (err) {
+               mfc_err("Allocating bitprocessor buffer failed\n");
+               return err;
+       }
+
+       return 0;
+}
+
+/* Load firmware */
+int s5p_mfc_load_firmware(struct s5p_mfc_dev *dev)
+{
+       struct firmware *fw_blob;
+       int i, err = -EINVAL;
+
+       /* Firmware has to be present as a separate file or compiled
+        * into kernel. */
+       mfc_debug_enter();
+
+       if (dev->fw_get_done)
+               return 0;
+
+       for (i = MFC_FW_MAX_VERSIONS - 1; i >= 0; i--) {
+               if (!dev->variant->fw_name[i])
+                       continue;
+               err = request_firmware((const struct firmware **)&fw_blob,
+                               dev->variant->fw_name[i], &dev->plat_dev->dev);
+               if (!err) {
+                       dev->fw_ver = (enum s5p_mfc_fw_ver) i;
+                       break;
+               }
+       }
+
+       if (err != 0) {
+               mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n");
+               return -EINVAL;
+       }
+       if (fw_blob->size > dev->fw_buf.size) {
+               mfc_err("MFC firmware is too big to be loaded\n");
+               release_firmware(fw_blob);
+               return -ENOMEM;
+       }
+       memcpy(dev->fw_buf.virt, fw_blob->data, fw_blob->size);
+       wmb();
+       dev->fw_get_done = true;
+       release_firmware(fw_blob);
+       mfc_debug_leave();
+       return 0;
+}
+
+/* Release firmware memory */
+int s5p_mfc_release_firmware(struct s5p_mfc_dev *dev)
+{
+       /* Before calling this function one has to make sure
+        * that MFC is no longer processing */
+       s5p_mfc_release_priv_buf(dev, &dev->fw_buf);
+       dev->fw_get_done = false;
+       return 0;
+}
+
+static int s5p_mfc_bus_reset(struct s5p_mfc_dev *dev)
+{
+       unsigned int status;
+       unsigned long timeout;
+
+       /* Reset */
+       mfc_write(dev, 0x1, S5P_FIMV_MFC_BUS_RESET_CTRL);
+       timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
+       /* Check bus status */
+       do {
+               if (time_after(jiffies, timeout)) {
+                       mfc_err("Timeout while resetting MFC.\n");
+                       return -EIO;
+               }
+               status = mfc_read(dev, S5P_FIMV_MFC_BUS_RESET_CTRL);
+       } while ((status & 0x2) == 0);
+       return 0;
+}
+
+/* Reset the device */
+int s5p_mfc_reset(struct s5p_mfc_dev *dev)
+{
+       unsigned int mc_status;
+       unsigned long timeout;
+       int i;
+
+       mfc_debug_enter();
+
+       if (IS_MFCV6_PLUS(dev)) {
+               /* Zero Initialization of MFC registers */
+               mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD_V6);
+               mfc_write(dev, 0, S5P_FIMV_HOST2RISC_CMD_V6);
+               mfc_write(dev, 0, S5P_FIMV_FW_VERSION_V6);
+
+               for (i = 0; i < S5P_FIMV_REG_CLEAR_COUNT_V6; i++)
+                       mfc_write(dev, 0, S5P_FIMV_REG_CLEAR_BEGIN_V6 + (i*4));
+
+               /* check bus reset control before reset */
+               if (dev->risc_on)
+                       if (s5p_mfc_bus_reset(dev))
+                               return -EIO;
+               /* Reset
+                * set RISC_ON to 0 during power_on & wake_up.
+                * V6 needs RISC_ON set to 0 during reset also.
+                */
+               if ((!dev->risc_on) || (!IS_MFCV7_PLUS(dev)))
+                       mfc_write(dev, 0, S5P_FIMV_RISC_ON_V6);
+
+               mfc_write(dev, 0x1FFF, S5P_FIMV_MFC_RESET_V6);
+               mfc_write(dev, 0, S5P_FIMV_MFC_RESET_V6);
+       } else {
+               /* Stop procedure */
+               /*  reset RISC */
+               mfc_write(dev, 0x3f6, S5P_FIMV_SW_RESET);
+               /*  All reset except for MC */
+               mfc_write(dev, 0x3e2, S5P_FIMV_SW_RESET);
+               mdelay(10);
+
+               timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
+               /* Check MC status */
+               do {
+                       if (time_after(jiffies, timeout)) {
+                               mfc_err("Timeout while resetting MFC\n");
+                               return -EIO;
+                       }
+
+                       mc_status = mfc_read(dev, S5P_FIMV_MC_STATUS);
+
+               } while (mc_status & 0x3);
+
+               mfc_write(dev, 0x0, S5P_FIMV_SW_RESET);
+               mfc_write(dev, 0x3fe, S5P_FIMV_SW_RESET);
+       }
+
+       mfc_debug_leave();
+       return 0;
+}
+
+static inline void s5p_mfc_init_memctrl(struct s5p_mfc_dev *dev)
+{
+       if (IS_MFCV6_PLUS(dev)) {
+               mfc_write(dev, dev->dma_base[BANK_L_CTX],
+                         S5P_FIMV_RISC_BASE_ADDRESS_V6);
+               mfc_debug(2, "Base Address : %pad\n",
+                         &dev->dma_base[BANK_L_CTX]);
+       } else {
+               mfc_write(dev, dev->dma_base[BANK_L_CTX],
+                         S5P_FIMV_MC_DRAMBASE_ADR_A);
+               mfc_write(dev, dev->dma_base[BANK_R_CTX],
+                         S5P_FIMV_MC_DRAMBASE_ADR_B);
+               mfc_debug(2, "Bank1: %pad, Bank2: %pad\n",
+                         &dev->dma_base[BANK_L_CTX],
+                         &dev->dma_base[BANK_R_CTX]);
+       }
+}
+
+static inline void s5p_mfc_clear_cmds(struct s5p_mfc_dev *dev)
+{
+       if (IS_MFCV6_PLUS(dev)) {
+               /* Zero initialization should be done before RESET.
+                * Nothing to do here. */
+       } else {
+               mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH0_INST_ID);
+               mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH1_INST_ID);
+               mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
+               mfc_write(dev, 0, S5P_FIMV_HOST2RISC_CMD);
+       }
+}
+
+/* Initialize hardware */
+int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
+{
+       unsigned int ver;
+       int ret;
+
+       mfc_debug_enter();
+       if (!dev->fw_buf.virt) {
+               mfc_err("Firmware memory is not allocated.\n");
+               return -EINVAL;
+       }
+
+       /* 0. MFC reset */
+       mfc_debug(2, "MFC reset..\n");
+       s5p_mfc_clock_on();
+       dev->risc_on = 0;
+       ret = s5p_mfc_reset(dev);
+       if (ret) {
+               mfc_err("Failed to reset MFC - timeout\n");
+               return ret;
+       }
+       mfc_debug(2, "Done MFC reset..\n");
+       /* 1. Set DRAM base Addr */
+       s5p_mfc_init_memctrl(dev);
+       /* 2. Initialize registers of channel I/F */
+       s5p_mfc_clear_cmds(dev);
+       /* 3. Release reset signal to the RISC */
+       s5p_mfc_clean_dev_int_flags(dev);
+       if (IS_MFCV6_PLUS(dev)) {
+               dev->risc_on = 1;
+               mfc_write(dev, 0x1, S5P_FIMV_RISC_ON_V6);
+       }
+       else
+               mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
+
+       if (IS_MFCV10(dev))
+               mfc_write(dev, 0x0, S5P_FIMV_MFC_CLOCK_OFF_V10);
+
+       mfc_debug(2, "Will now wait for completion of firmware transfer\n");
+       if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_FW_STATUS_RET)) {
+               mfc_err("Failed to load firmware\n");
+               s5p_mfc_reset(dev);
+               s5p_mfc_clock_off();
+               return -EIO;
+       }
+       s5p_mfc_clean_dev_int_flags(dev);
+       /* 4. Initialize firmware */
+       ret = s5p_mfc_hw_call(dev->mfc_cmds, sys_init_cmd, dev);
+       if (ret) {
+               mfc_err("Failed to send command to MFC - timeout\n");
+               s5p_mfc_reset(dev);
+               s5p_mfc_clock_off();
+               return ret;
+       }
+       mfc_debug(2, "Ok, now will wait for completion of hardware init\n");
+       if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_SYS_INIT_RET)) {
+               mfc_err("Failed to init hardware\n");
+               s5p_mfc_reset(dev);
+               s5p_mfc_clock_off();
+               return -EIO;
+       }
+       dev->int_cond = 0;
+       if (dev->int_err != 0 || dev->int_type !=
+                                       S5P_MFC_R2H_CMD_SYS_INIT_RET) {
+               /* Failure. */
+               mfc_err("Failed to init firmware - error: %d int: %d\n",
+                                               dev->int_err, dev->int_type);
+               s5p_mfc_reset(dev);
+               s5p_mfc_clock_off();
+               return -EIO;
+       }
+       if (IS_MFCV6_PLUS(dev))
+               ver = mfc_read(dev, S5P_FIMV_FW_VERSION_V6);
+       else
+               ver = mfc_read(dev, S5P_FIMV_FW_VERSION);
+
+       mfc_debug(2, "MFC F/W version : %02xyy, %02xmm, %02xdd\n",
+               (ver >> 16) & 0xFF, (ver >> 8) & 0xFF, ver & 0xFF);
+       s5p_mfc_clock_off();
+       mfc_debug_leave();
+       return 0;
+}
+
+
+/* Deinitialize hardware */
+void s5p_mfc_deinit_hw(struct s5p_mfc_dev *dev)
+{
+       s5p_mfc_clock_on();
+
+       s5p_mfc_reset(dev);
+       s5p_mfc_hw_call(dev->mfc_ops, release_dev_context_buffer, dev);
+
+       s5p_mfc_clock_off();
+}
+
+int s5p_mfc_sleep(struct s5p_mfc_dev *dev)
+{
+       int ret;
+
+       mfc_debug_enter();
+       s5p_mfc_clock_on();
+       s5p_mfc_clean_dev_int_flags(dev);
+       ret = s5p_mfc_hw_call(dev->mfc_cmds, sleep_cmd, dev);
+       if (ret) {
+               mfc_err("Failed to send command to MFC - timeout\n");
+               return ret;
+       }
+       if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_SLEEP_RET)) {
+               mfc_err("Failed to sleep\n");
+               return -EIO;
+       }
+       s5p_mfc_clock_off();
+       dev->int_cond = 0;
+       if (dev->int_err != 0 || dev->int_type !=
+                                               S5P_MFC_R2H_CMD_SLEEP_RET) {
+               /* Failure. */
+               mfc_err("Failed to sleep - error: %d int: %d\n", dev->int_err,
+                                                               dev->int_type);
+               return -EIO;
+       }
+       mfc_debug_leave();
+       return ret;
+}
+
+static int s5p_mfc_v8_wait_wakeup(struct s5p_mfc_dev *dev)
+{
+       int ret;
+
+       /* Release reset signal to the RISC */
+       dev->risc_on = 1;
+       mfc_write(dev, 0x1, S5P_FIMV_RISC_ON_V6);
+
+       if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_FW_STATUS_RET)) {
+               mfc_err("Failed to reset MFCV8\n");
+               return -EIO;
+       }
+       mfc_debug(2, "Write command to wakeup MFCV8\n");
+       ret = s5p_mfc_hw_call(dev->mfc_cmds, wakeup_cmd, dev);
+       if (ret) {
+               mfc_err("Failed to send command to MFCV8 - timeout\n");
+               return ret;
+       }
+
+       if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_WAKEUP_RET)) {
+               mfc_err("Failed to wakeup MFC\n");
+               return -EIO;
+       }
+       return ret;
+}
+
+static int s5p_mfc_wait_wakeup(struct s5p_mfc_dev *dev)
+{
+       int ret;
+
+       /* Send MFC wakeup command */
+       ret = s5p_mfc_hw_call(dev->mfc_cmds, wakeup_cmd, dev);
+       if (ret) {
+               mfc_err("Failed to send command to MFC - timeout\n");
+               return ret;
+       }
+
+       /* Release reset signal to the RISC */
+       if (IS_MFCV6_PLUS(dev)) {
+               dev->risc_on = 1;
+               mfc_write(dev, 0x1, S5P_FIMV_RISC_ON_V6);
+       } else {
+               mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
+       }
+
+       if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_WAKEUP_RET)) {
+               mfc_err("Failed to wakeup MFC\n");
+               return -EIO;
+       }
+       return ret;
+}
+
+int s5p_mfc_wakeup(struct s5p_mfc_dev *dev)
+{
+       int ret;
+
+       mfc_debug_enter();
+       /* 0. MFC reset */
+       mfc_debug(2, "MFC reset..\n");
+       s5p_mfc_clock_on();
+       dev->risc_on = 0;
+       ret = s5p_mfc_reset(dev);
+       if (ret) {
+               mfc_err("Failed to reset MFC - timeout\n");
+               s5p_mfc_clock_off();
+               return ret;
+       }
+       mfc_debug(2, "Done MFC reset..\n");
+       /* 1. Set DRAM base Addr */
+       s5p_mfc_init_memctrl(dev);
+       /* 2. Initialize registers of channel I/F */
+       s5p_mfc_clear_cmds(dev);
+       s5p_mfc_clean_dev_int_flags(dev);
+       /* 3. Send MFC wakeup command and wait for completion*/
+       if (IS_MFCV8_PLUS(dev))
+               ret = s5p_mfc_v8_wait_wakeup(dev);
+       else
+               ret = s5p_mfc_wait_wakeup(dev);
+
+       s5p_mfc_clock_off();
+       if (ret)
+               return ret;
+
+       dev->int_cond = 0;
+       if (dev->int_err != 0 || dev->int_type !=
+                                               S5P_MFC_R2H_CMD_WAKEUP_RET) {
+               /* Failure. */
+               mfc_err("Failed to wakeup - error: %d int: %d\n", dev->int_err,
+                                                               dev->int_type);
+               return -EIO;
+       }
+       mfc_debug_leave();
+       return 0;
+}
+
+int s5p_mfc_open_mfc_inst(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx)
+{
+       int ret = 0;
+
+       ret = s5p_mfc_hw_call(dev->mfc_ops, alloc_instance_buffer, ctx);
+       if (ret) {
+               mfc_err("Failed allocating instance buffer\n");
+               goto err;
+       }
+
+       if (ctx->type == MFCINST_DECODER) {
+               ret = s5p_mfc_hw_call(dev->mfc_ops,
+                                       alloc_dec_temp_buffers, ctx);
+               if (ret) {
+                       mfc_err("Failed allocating temporary buffers\n");
+                       goto err_free_inst_buf;
+               }
+       }
+
+       set_work_bit_irqsave(ctx);
+       s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
+       if (s5p_mfc_wait_for_done_ctx(ctx,
+               S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET, 0)) {
+               /* Error or timeout */
+               mfc_err("Error getting instance from hardware\n");
+               ret = -EIO;
+               goto err_free_desc_buf;
+       }
+
+       mfc_debug(2, "Got instance number: %d\n", ctx->inst_no);
+       return ret;
+
+err_free_desc_buf:
+       if (ctx->type == MFCINST_DECODER)
+               s5p_mfc_hw_call(dev->mfc_ops, release_dec_desc_buffer, ctx);
+err_free_inst_buf:
+       s5p_mfc_hw_call(dev->mfc_ops, release_instance_buffer, ctx);
+err:
+       return ret;
+}
+
+void s5p_mfc_close_mfc_inst(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx)
+{
+       ctx->state = MFCINST_RETURN_INST;
+       set_work_bit_irqsave(ctx);
+       s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
+       /* Wait until instance is returned or timeout occurred */
+       if (s5p_mfc_wait_for_done_ctx(ctx,
+                               S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET, 0))
+               mfc_err("Err returning instance\n");
+
+       /* Free resources */
+       s5p_mfc_hw_call(dev->mfc_ops, release_codec_buffers, ctx);
+       s5p_mfc_hw_call(dev->mfc_ops, release_instance_buffer, ctx);
+       if (ctx->type == MFCINST_DECODER)
+               s5p_mfc_hw_call(dev->mfc_ops, release_dec_desc_buffer, ctx);
+
+       ctx->inst_no = MFC_NO_INSTANCE_SET;
+       ctx->state = MFCINST_FREE;
+}
diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_ctrl.h b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_ctrl.h
new file mode 100644 (file)
index 0000000..653ba5f
--- /dev/null
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * linux/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_ctrl.h
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ */
+
+#ifndef S5P_MFC_CTRL_H
+#define S5P_MFC_CTRL_H
+
+#include "s5p_mfc_common.h"
+
+int s5p_mfc_release_firmware(struct s5p_mfc_dev *dev);
+int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev);
+int s5p_mfc_load_firmware(struct s5p_mfc_dev *dev);
+
+int s5p_mfc_init_hw(struct s5p_mfc_dev *dev);
+void s5p_mfc_deinit_hw(struct s5p_mfc_dev *dev);
+
+int s5p_mfc_sleep(struct s5p_mfc_dev *dev);
+int s5p_mfc_wakeup(struct s5p_mfc_dev *dev);
+
+int s5p_mfc_reset(struct s5p_mfc_dev *dev);
+
+int s5p_mfc_open_mfc_inst(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx);
+void s5p_mfc_close_mfc_inst(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx);
+
+#endif /* S5P_MFC_CTRL_H */
diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_debug.h b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_debug.h
new file mode 100644 (file)
index 0000000..bba5dad
--- /dev/null
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * drivers/media/platform/samsung/s5p-mfc/s5p_mfc_debug.h
+ *
+ * Header file for Samsung MFC (Multi Function Codec - FIMV) driver
+ * This file contains debug macros
+ *
+ * Kamil Debski, Copyright (c) 2011 Samsung Electronics
+ * http://www.samsung.com/
+ */
+
+#ifndef S5P_MFC_DEBUG_H_
+#define S5P_MFC_DEBUG_H_
+
+#define DEBUG
+
+#ifdef DEBUG
+extern int mfc_debug_level;
+
+#define mfc_debug(level, fmt, args...)                         \
+       do {                                                    \
+               if (mfc_debug_level >= level)                   \
+                       printk(KERN_DEBUG "%s:%d: " fmt,        \
+                               __func__, __LINE__, ##args);    \
+       } while (0)
+#else
+#define mfc_debug(level, fmt, args...)
+#endif
+
+#define mfc_debug_enter() mfc_debug(5, "enter\n")
+#define mfc_debug_leave() mfc_debug(5, "leave\n")
+
+#define mfc_err(fmt, args...)                          \
+       do {                                            \
+               printk(KERN_ERR "%s:%d: " fmt,          \
+                      __func__, __LINE__, ##args);     \
+       } while (0)
+
+#define mfc_err_limited(fmt, args...)                  \
+       do {                                            \
+               printk_ratelimited(KERN_ERR "%s:%d: " fmt,      \
+                      __func__, __LINE__, ##args);     \
+       } while (0)
+
+#define mfc_info(fmt, args...)                         \
+       do {                                            \
+               printk(KERN_INFO "%s:%d: " fmt,         \
+                      __func__, __LINE__, ##args);     \
+       } while (0)
+
+#endif /* S5P_MFC_DEBUG_H_ */
diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_dec.c
new file mode 100644 (file)
index 0000000..4b89df8
--- /dev/null
@@ -0,0 +1,1218 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * linux/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_dec.c
+ *
+ * Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ * Kamil Debski, <k.debski@samsung.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/videodev2.h>
+#include <linux/workqueue.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-event.h>
+#include <media/videobuf2-v4l2.h>
+#include "s5p_mfc_common.h"
+#include "s5p_mfc_ctrl.h"
+#include "s5p_mfc_debug.h"
+#include "s5p_mfc_dec.h"
+#include "s5p_mfc_intr.h"
+#include "s5p_mfc_opr.h"
+#include "s5p_mfc_pm.h"
+
+static struct s5p_mfc_fmt formats[] = {
+       {
+               .fourcc         = V4L2_PIX_FMT_NV12MT_16X16,
+               .codec_mode     = S5P_MFC_CODEC_NONE,
+               .type           = MFC_FMT_RAW,
+               .num_planes     = 2,
+               .versions       = MFC_V6_BIT | MFC_V7_BIT,
+       },
+       {
+               .fourcc         = V4L2_PIX_FMT_NV12MT,
+               .codec_mode     = S5P_MFC_CODEC_NONE,
+               .type           = MFC_FMT_RAW,
+               .num_planes     = 2,
+               .versions       = MFC_V5_BIT,
+       },
+       {
+               .fourcc         = V4L2_PIX_FMT_NV12M,
+               .codec_mode     = S5P_MFC_CODEC_NONE,
+               .type           = MFC_FMT_RAW,
+               .num_planes     = 2,
+               .versions       = MFC_V6PLUS_BITS,
+       },
+       {
+               .fourcc         = V4L2_PIX_FMT_NV21M,
+               .codec_mode     = S5P_MFC_CODEC_NONE,
+               .type           = MFC_FMT_RAW,
+               .num_planes     = 2,
+               .versions       = MFC_V6PLUS_BITS,
+       },
+       {
+               .fourcc         = V4L2_PIX_FMT_H264,
+               .codec_mode     = S5P_MFC_CODEC_H264_DEC,
+               .type           = MFC_FMT_DEC,
+               .num_planes     = 1,
+               .versions       = MFC_V5PLUS_BITS,
+               .flags          = V4L2_FMT_FLAG_DYN_RESOLUTION |
+                                 V4L2_FMT_FLAG_CONTINUOUS_BYTESTREAM,
+       },
+       {
+               .fourcc         = V4L2_PIX_FMT_H264_MVC,
+               .codec_mode     = S5P_MFC_CODEC_H264_MVC_DEC,
+               .type           = MFC_FMT_DEC,
+               .num_planes     = 1,
+               .versions       = MFC_V6PLUS_BITS,
+               .flags          = V4L2_FMT_FLAG_DYN_RESOLUTION |
+                                 V4L2_FMT_FLAG_CONTINUOUS_BYTESTREAM,
+       },
+       {
+               .fourcc         = V4L2_PIX_FMT_H263,
+               .codec_mode     = S5P_MFC_CODEC_H263_DEC,
+               .type           = MFC_FMT_DEC,
+               .num_planes     = 1,
+               .versions       = MFC_V5PLUS_BITS,
+               .flags          = V4L2_FMT_FLAG_DYN_RESOLUTION,
+       },
+       {
+               .fourcc         = V4L2_PIX_FMT_MPEG1,
+               .codec_mode     = S5P_MFC_CODEC_MPEG2_DEC,
+               .type           = MFC_FMT_DEC,
+               .num_planes     = 1,
+               .versions       = MFC_V5PLUS_BITS,
+               .flags          = V4L2_FMT_FLAG_DYN_RESOLUTION |
+                                 V4L2_FMT_FLAG_CONTINUOUS_BYTESTREAM,
+       },
+       {
+               .fourcc         = V4L2_PIX_FMT_MPEG2,
+               .codec_mode     = S5P_MFC_CODEC_MPEG2_DEC,
+               .type           = MFC_FMT_DEC,
+               .num_planes     = 1,
+               .versions       = MFC_V5PLUS_BITS,
+               .flags          = V4L2_FMT_FLAG_DYN_RESOLUTION |
+                                 V4L2_FMT_FLAG_CONTINUOUS_BYTESTREAM,
+       },
+       {
+               .fourcc         = V4L2_PIX_FMT_MPEG4,
+               .codec_mode     = S5P_MFC_CODEC_MPEG4_DEC,
+               .type           = MFC_FMT_DEC,
+               .num_planes     = 1,
+               .versions       = MFC_V5PLUS_BITS,
+               .flags          = V4L2_FMT_FLAG_DYN_RESOLUTION |
+                                 V4L2_FMT_FLAG_CONTINUOUS_BYTESTREAM,
+       },
+       {
+               .fourcc         = V4L2_PIX_FMT_XVID,
+               .codec_mode     = S5P_MFC_CODEC_MPEG4_DEC,
+               .type           = MFC_FMT_DEC,
+               .num_planes     = 1,
+               .versions       = MFC_V5PLUS_BITS,
+               .flags          = V4L2_FMT_FLAG_DYN_RESOLUTION,
+       },
+       {
+               .fourcc         = V4L2_PIX_FMT_VC1_ANNEX_G,
+               .codec_mode     = S5P_MFC_CODEC_VC1_DEC,
+               .type           = MFC_FMT_DEC,
+               .num_planes     = 1,
+               .versions       = MFC_V5PLUS_BITS,
+               .flags          = V4L2_FMT_FLAG_DYN_RESOLUTION,
+       },
+       {
+               .fourcc         = V4L2_PIX_FMT_VC1_ANNEX_L,
+               .codec_mode     = S5P_MFC_CODEC_VC1RCV_DEC,
+               .type           = MFC_FMT_DEC,
+               .num_planes     = 1,
+               .versions       = MFC_V5PLUS_BITS,
+               .flags          = V4L2_FMT_FLAG_DYN_RESOLUTION,
+       },
+       {
+               .fourcc         = V4L2_PIX_FMT_VP8,
+               .codec_mode     = S5P_MFC_CODEC_VP8_DEC,
+               .type           = MFC_FMT_DEC,
+               .num_planes     = 1,
+               .versions       = MFC_V6PLUS_BITS,
+               .flags          = V4L2_FMT_FLAG_DYN_RESOLUTION,
+       },
+       {
+               .fourcc         = V4L2_PIX_FMT_HEVC,
+               .codec_mode     = S5P_FIMV_CODEC_HEVC_DEC,
+               .type           = MFC_FMT_DEC,
+               .num_planes     = 1,
+               .versions       = MFC_V10_BIT,
+               .flags          = V4L2_FMT_FLAG_DYN_RESOLUTION |
+                                 V4L2_FMT_FLAG_CONTINUOUS_BYTESTREAM,
+       },
+       {
+               .fourcc         = V4L2_PIX_FMT_VP9,
+               .codec_mode     = S5P_FIMV_CODEC_VP9_DEC,
+               .type           = MFC_FMT_DEC,
+               .num_planes     = 1,
+               .versions       = MFC_V10_BIT,
+               .flags          = V4L2_FMT_FLAG_DYN_RESOLUTION,
+       },
+};
+
+#define NUM_FORMATS ARRAY_SIZE(formats)
+
+/* Find selected format description */
+static struct s5p_mfc_fmt *find_format(struct v4l2_format *f, unsigned int t)
+{
+       unsigned int i;
+
+       for (i = 0; i < NUM_FORMATS; i++) {
+               if (formats[i].fourcc == f->fmt.pix_mp.pixelformat &&
+                   formats[i].type == t)
+                       return &formats[i];
+       }
+       return NULL;
+}
+
+static struct mfc_control controls[] = {
+       {
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "H264 Display Delay",
+               .minimum = 0,
+               .maximum = 16383,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = 16383,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY_ENABLE,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "H264 Display Delay Enable",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY_ENABLE,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .minimum = 0,
+               .maximum = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "Mpeg4 Loop Filter Enable",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "Slice Interface Enable",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Minimum number of cap bufs",
+               .minimum = 1,
+               .maximum = 32,
+               .step = 1,
+               .default_value = 1,
+               .is_volatile = 1,
+       },
+};
+
+#define NUM_CTRLS ARRAY_SIZE(controls)
+
+/* Check whether a context should be run on hardware */
+static int s5p_mfc_ctx_ready(struct s5p_mfc_ctx *ctx)
+{
+       /* Context is to parse header */
+       if (ctx->src_queue_cnt >= 1 && ctx->state == MFCINST_GOT_INST)
+               return 1;
+       /* Context is to decode a frame */
+       if (ctx->src_queue_cnt >= 1 &&
+           ctx->state == MFCINST_RUNNING &&
+           ctx->dst_queue_cnt >= ctx->pb_count)
+               return 1;
+       /* Context is to return last frame */
+       if (ctx->state == MFCINST_FINISHING &&
+           ctx->dst_queue_cnt >= ctx->pb_count)
+               return 1;
+       /* Context is to set buffers */
+       if (ctx->src_queue_cnt >= 1 &&
+           ctx->state == MFCINST_HEAD_PARSED &&
+           ctx->capture_state == QUEUE_BUFS_MMAPED)
+               return 1;
+       /* Resolution change */
+       if ((ctx->state == MFCINST_RES_CHANGE_INIT ||
+               ctx->state == MFCINST_RES_CHANGE_FLUSH) &&
+               ctx->dst_queue_cnt >= ctx->pb_count)
+               return 1;
+       if (ctx->state == MFCINST_RES_CHANGE_END &&
+               ctx->src_queue_cnt >= 1)
+               return 1;
+       mfc_debug(2, "ctx is not ready\n");
+       return 0;
+}
+
+static const struct s5p_mfc_codec_ops decoder_codec_ops = {
+       .pre_seq_start          = NULL,
+       .post_seq_start         = NULL,
+       .pre_frame_start        = NULL,
+       .post_frame_start       = NULL,
+};
+
+/* Query capabilities of the device */
+static int vidioc_querycap(struct file *file, void *priv,
+                          struct v4l2_capability *cap)
+{
+       struct s5p_mfc_dev *dev = video_drvdata(file);
+
+       strscpy(cap->driver, S5P_MFC_NAME, sizeof(cap->driver));
+       strscpy(cap->card, dev->vfd_dec->name, sizeof(cap->card));
+       snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
+                dev_name(&dev->plat_dev->dev));
+       return 0;
+}
+
+/* Enumerate format */
+static int vidioc_enum_fmt(struct file *file, struct v4l2_fmtdesc *f,
+                                                       bool out)
+{
+       struct s5p_mfc_dev *dev = video_drvdata(file);
+       int i, j = 0;
+
+       for (i = 0; i < ARRAY_SIZE(formats); ++i) {
+               if (out && formats[i].type != MFC_FMT_DEC)
+                       continue;
+               else if (!out && formats[i].type != MFC_FMT_RAW)
+                       continue;
+               else if ((dev->variant->version_bit & formats[i].versions) == 0)
+                       continue;
+
+               if (j == f->index)
+                       break;
+               ++j;
+       }
+       if (i == ARRAY_SIZE(formats))
+               return -EINVAL;
+       f->pixelformat = formats[i].fourcc;
+       return 0;
+}
+
+static int vidioc_enum_fmt_vid_cap(struct file *file, void *pirv,
+                                  struct v4l2_fmtdesc *f)
+{
+       return vidioc_enum_fmt(file, f, false);
+}
+
+static int vidioc_enum_fmt_vid_out(struct file *file, void *priv,
+                                  struct v4l2_fmtdesc *f)
+{
+       return vidioc_enum_fmt(file, f, true);
+}
+
+/* Get format */
+static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+       struct v4l2_pix_format_mplane *pix_mp;
+
+       mfc_debug_enter();
+       pix_mp = &f->fmt.pix_mp;
+       if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
+           (ctx->state == MFCINST_GOT_INST || ctx->state ==
+                                               MFCINST_RES_CHANGE_END)) {
+               /* If the MFC is parsing the header,
+                * so wait until it is finished */
+               s5p_mfc_wait_for_done_ctx(ctx, S5P_MFC_R2H_CMD_SEQ_DONE_RET,
+                                                                       0);
+       }
+       if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
+           ctx->state >= MFCINST_HEAD_PARSED &&
+           ctx->state < MFCINST_ABORT) {
+               /* This is run on CAPTURE (decode output) */
+               /* Width and height are set to the dimensions
+                  of the movie, the buffer is bigger and
+                  further processing stages should crop to this
+                  rectangle. */
+               pix_mp->width = ctx->buf_width;
+               pix_mp->height = ctx->buf_height;
+               pix_mp->field = V4L2_FIELD_NONE;
+               pix_mp->num_planes = 2;
+               /* Set pixelformat to the format in which MFC
+                  outputs the decoded frame */
+               pix_mp->pixelformat = ctx->dst_fmt->fourcc;
+               pix_mp->plane_fmt[0].bytesperline = ctx->buf_width;
+               pix_mp->plane_fmt[0].sizeimage = ctx->luma_size;
+               pix_mp->plane_fmt[1].bytesperline = ctx->buf_width;
+               pix_mp->plane_fmt[1].sizeimage = ctx->chroma_size;
+       } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               /* This is run on OUTPUT
+                  The buffer contains compressed image
+                  so width and height have no meaning */
+               pix_mp->width = 0;
+               pix_mp->height = 0;
+               pix_mp->field = V4L2_FIELD_NONE;
+               pix_mp->plane_fmt[0].bytesperline = ctx->dec_src_buf_size;
+               pix_mp->plane_fmt[0].sizeimage = ctx->dec_src_buf_size;
+               pix_mp->pixelformat = ctx->src_fmt->fourcc;
+               pix_mp->num_planes = ctx->src_fmt->num_planes;
+       } else {
+               mfc_err("Format could not be read\n");
+               mfc_debug(2, "%s-- with error\n", __func__);
+               return -EINVAL;
+       }
+       mfc_debug_leave();
+       return 0;
+}
+
+/* Try format */
+static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
+{
+       struct s5p_mfc_dev *dev = video_drvdata(file);
+       struct s5p_mfc_fmt *fmt;
+
+       mfc_debug(2, "Type is %d\n", f->type);
+       if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               fmt = find_format(f, MFC_FMT_DEC);
+               if (!fmt) {
+                       mfc_err("Unsupported format for source.\n");
+                       return -EINVAL;
+               }
+               if (fmt->codec_mode == S5P_FIMV_CODEC_NONE) {
+                       mfc_err("Unknown codec\n");
+                       return -EINVAL;
+               }
+               if ((dev->variant->version_bit & fmt->versions) == 0) {
+                       mfc_err("Unsupported format by this MFC version.\n");
+                       return -EINVAL;
+               }
+       } else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               fmt = find_format(f, MFC_FMT_RAW);
+               if (!fmt) {
+                       mfc_err("Unsupported format for destination.\n");
+                       return -EINVAL;
+               }
+               if ((dev->variant->version_bit & fmt->versions) == 0) {
+                       mfc_err("Unsupported format by this MFC version.\n");
+                       return -EINVAL;
+               }
+       }
+
+       return 0;
+}
+
+/* Set format */
+static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
+{
+       struct s5p_mfc_dev *dev = video_drvdata(file);
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+       int ret = 0;
+       struct v4l2_pix_format_mplane *pix_mp;
+       struct s5p_mfc_buf_size *buf_size = dev->variant->buf_size;
+
+       mfc_debug_enter();
+       ret = vidioc_try_fmt(file, priv, f);
+       pix_mp = &f->fmt.pix_mp;
+       if (ret)
+               return ret;
+       if (vb2_is_streaming(&ctx->vq_src) || vb2_is_streaming(&ctx->vq_dst)) {
+               v4l2_err(&dev->v4l2_dev, "%s queue busy\n", __func__);
+               ret = -EBUSY;
+               goto out;
+       }
+       if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               /* dst_fmt is validated by call to vidioc_try_fmt */
+               ctx->dst_fmt = find_format(f, MFC_FMT_RAW);
+               ret = 0;
+               goto out;
+       } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               /* src_fmt is validated by call to vidioc_try_fmt */
+               ctx->src_fmt = find_format(f, MFC_FMT_DEC);
+               ctx->codec_mode = ctx->src_fmt->codec_mode;
+               mfc_debug(2, "The codec number is: %d\n", ctx->codec_mode);
+               pix_mp->height = 0;
+               pix_mp->width = 0;
+               if (pix_mp->plane_fmt[0].sizeimage == 0)
+                       pix_mp->plane_fmt[0].sizeimage = ctx->dec_src_buf_size =
+                                                               DEF_CPB_SIZE;
+               else if (pix_mp->plane_fmt[0].sizeimage > buf_size->cpb)
+                       ctx->dec_src_buf_size = buf_size->cpb;
+               else
+                       ctx->dec_src_buf_size = pix_mp->plane_fmt[0].sizeimage;
+               pix_mp->plane_fmt[0].bytesperline = 0;
+               ctx->state = MFCINST_INIT;
+               ret = 0;
+               goto out;
+       } else {
+               mfc_err("Wrong type error for S_FMT : %d", f->type);
+               ret = -EINVAL;
+               goto out;
+       }
+
+out:
+       mfc_debug_leave();
+       return ret;
+}
+
+static int reqbufs_output(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx,
+                               struct v4l2_requestbuffers *reqbufs)
+{
+       int ret = 0;
+
+       s5p_mfc_clock_on();
+
+       if (reqbufs->count == 0) {
+               mfc_debug(2, "Freeing buffers\n");
+               ret = vb2_reqbufs(&ctx->vq_src, reqbufs);
+               if (ret)
+                       goto out;
+               ctx->src_bufs_cnt = 0;
+               ctx->output_state = QUEUE_FREE;
+       } else if (ctx->output_state == QUEUE_FREE) {
+               /* Can only request buffers when we have a valid format set. */
+               WARN_ON(ctx->src_bufs_cnt != 0);
+               if (ctx->state != MFCINST_INIT) {
+                       mfc_err("Reqbufs called in an invalid state\n");
+                       ret = -EINVAL;
+                       goto out;
+               }
+
+               mfc_debug(2, "Allocating %d buffers for OUTPUT queue\n",
+                               reqbufs->count);
+               ret = vb2_reqbufs(&ctx->vq_src, reqbufs);
+               if (ret)
+                       goto out;
+
+               ret = s5p_mfc_open_mfc_inst(dev, ctx);
+               if (ret) {
+                       reqbufs->count = 0;
+                       vb2_reqbufs(&ctx->vq_src, reqbufs);
+                       goto out;
+               }
+
+               ctx->output_state = QUEUE_BUFS_REQUESTED;
+       } else {
+               mfc_err("Buffers have already been requested\n");
+               ret = -EINVAL;
+       }
+out:
+       s5p_mfc_clock_off();
+       if (ret)
+               mfc_err("Failed allocating buffers for OUTPUT queue\n");
+       return ret;
+}
+
+static int reqbufs_capture(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx,
+                               struct v4l2_requestbuffers *reqbufs)
+{
+       int ret = 0;
+
+       s5p_mfc_clock_on();
+
+       if (reqbufs->count == 0) {
+               mfc_debug(2, "Freeing buffers\n");
+               ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
+               if (ret)
+                       goto out;
+               s5p_mfc_hw_call(dev->mfc_ops, release_codec_buffers, ctx);
+               ctx->dst_bufs_cnt = 0;
+       } else if (ctx->capture_state == QUEUE_FREE) {
+               WARN_ON(ctx->dst_bufs_cnt != 0);
+               mfc_debug(2, "Allocating %d buffers for CAPTURE queue\n",
+                               reqbufs->count);
+               ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
+               if (ret)
+                       goto out;
+
+               ctx->capture_state = QUEUE_BUFS_REQUESTED;
+               ctx->total_dpb_count = reqbufs->count;
+
+               ret = s5p_mfc_hw_call(dev->mfc_ops, alloc_codec_buffers, ctx);
+               if (ret) {
+                       mfc_err("Failed to allocate decoding buffers\n");
+                       reqbufs->count = 0;
+                       vb2_reqbufs(&ctx->vq_dst, reqbufs);
+                       ret = -ENOMEM;
+                       ctx->capture_state = QUEUE_FREE;
+                       goto out;
+               }
+
+               WARN_ON(ctx->dst_bufs_cnt != ctx->total_dpb_count);
+               ctx->capture_state = QUEUE_BUFS_MMAPED;
+
+               if (s5p_mfc_ctx_ready(ctx))
+                       set_work_bit_irqsave(ctx);
+               s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
+               s5p_mfc_wait_for_done_ctx(ctx, S5P_MFC_R2H_CMD_INIT_BUFFERS_RET,
+                                         0);
+       } else {
+               mfc_err("Buffers have already been requested\n");
+               ret = -EINVAL;
+       }
+out:
+       s5p_mfc_clock_off();
+       if (ret)
+               mfc_err("Failed allocating buffers for CAPTURE queue\n");
+       return ret;
+}
+
+/* Request buffers */
+static int vidioc_reqbufs(struct file *file, void *priv,
+                                         struct v4l2_requestbuffers *reqbufs)
+{
+       struct s5p_mfc_dev *dev = video_drvdata(file);
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+
+       if (reqbufs->memory != V4L2_MEMORY_MMAP) {
+               mfc_debug(2, "Only V4L2_MEMORY_MMAP is supported\n");
+               return -EINVAL;
+       }
+
+       if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               return reqbufs_output(dev, ctx, reqbufs);
+       } else if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               return reqbufs_capture(dev, ctx, reqbufs);
+       } else {
+               mfc_err("Invalid type requested\n");
+               return -EINVAL;
+       }
+}
+
+/* Query buffer */
+static int vidioc_querybuf(struct file *file, void *priv,
+                                                  struct v4l2_buffer *buf)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+       int ret;
+       int i;
+
+       if (buf->memory != V4L2_MEMORY_MMAP) {
+               mfc_err("Only mmapped buffers can be used\n");
+               return -EINVAL;
+       }
+       mfc_debug(2, "State: %d, buf->type: %d\n", ctx->state, buf->type);
+       if (ctx->state == MFCINST_GOT_INST &&
+                       buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               ret = vb2_querybuf(&ctx->vq_src, buf);
+       } else if (ctx->state == MFCINST_RUNNING &&
+                       buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               ret = vb2_querybuf(&ctx->vq_dst, buf);
+               for (i = 0; i < buf->length; i++)
+                       buf->m.planes[i].m.mem_offset += DST_QUEUE_OFF_BASE;
+       } else {
+               mfc_err("vidioc_querybuf called in an inappropriate state\n");
+               ret = -EINVAL;
+       }
+       mfc_debug_leave();
+       return ret;
+}
+
+/* Queue a buffer */
+static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+
+       if (ctx->state == MFCINST_ERROR) {
+               mfc_err("Call on QBUF after unrecoverable error\n");
+               return -EIO;
+       }
+       if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+               return vb2_qbuf(&ctx->vq_src, NULL, buf);
+       else if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+               return vb2_qbuf(&ctx->vq_dst, NULL, buf);
+       return -EINVAL;
+}
+
+/* Dequeue a buffer */
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
+{
+       const struct v4l2_event ev = {
+               .type = V4L2_EVENT_EOS
+       };
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+       int ret;
+
+       if (ctx->state == MFCINST_ERROR) {
+               mfc_err_limited("Call on DQBUF after unrecoverable error\n");
+               return -EIO;
+       }
+
+       switch (buf->type) {
+       case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+               return vb2_dqbuf(&ctx->vq_src, buf, file->f_flags & O_NONBLOCK);
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+               ret = vb2_dqbuf(&ctx->vq_dst, buf, file->f_flags & O_NONBLOCK);
+               if (ret)
+                       return ret;
+
+               if (ctx->state == MFCINST_FINISHED &&
+                   (ctx->dst_bufs[buf->index].flags & MFC_BUF_FLAG_EOS))
+                       v4l2_event_queue_fh(&ctx->fh, &ev);
+               return 0;
+       default:
+               return -EINVAL;
+       }
+}
+
+/* Export DMA buffer */
+static int vidioc_expbuf(struct file *file, void *priv,
+       struct v4l2_exportbuffer *eb)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+
+       if (eb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+               return vb2_expbuf(&ctx->vq_src, eb);
+       if (eb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+               return vb2_expbuf(&ctx->vq_dst, eb);
+       return -EINVAL;
+}
+
+/* Stream on */
+static int vidioc_streamon(struct file *file, void *priv,
+                          enum v4l2_buf_type type)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+       int ret = -EINVAL;
+
+       mfc_debug_enter();
+       if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+               ret = vb2_streamon(&ctx->vq_src, type);
+       else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+               ret = vb2_streamon(&ctx->vq_dst, type);
+       mfc_debug_leave();
+       return ret;
+}
+
+/* Stream off, which equals to a pause */
+static int vidioc_streamoff(struct file *file, void *priv,
+                           enum v4l2_buf_type type)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+
+       if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+               return vb2_streamoff(&ctx->vq_src, type);
+       else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+               return vb2_streamoff(&ctx->vq_dst, type);
+       return -EINVAL;
+}
+
+/* Set controls - v4l2 control framework */
+static int s5p_mfc_dec_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct s5p_mfc_ctx *ctx = ctrl_to_ctx(ctrl);
+
+       switch (ctrl->id) {
+       case V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY:
+       case V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY:
+               ctx->display_delay = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY_ENABLE:
+       case V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY_ENABLE:
+               ctx->display_delay_enable = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER:
+               ctx->loop_filter_mpeg4 = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE:
+               ctx->slice_interface = ctrl->val;
+               break;
+       default:
+               mfc_err("Invalid control 0x%08x\n", ctrl->id);
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int s5p_mfc_dec_g_v_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct s5p_mfc_ctx *ctx = ctrl_to_ctx(ctrl);
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       switch (ctrl->id) {
+       case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:
+               if (ctx->state >= MFCINST_HEAD_PARSED &&
+                   ctx->state < MFCINST_ABORT) {
+                       ctrl->val = ctx->pb_count;
+                       break;
+               } else if (ctx->state != MFCINST_INIT &&
+                               ctx->state != MFCINST_RES_CHANGE_END) {
+                       v4l2_err(&dev->v4l2_dev, "Decoding not initialised\n");
+                       return -EINVAL;
+               }
+               /* Should wait for the header to be parsed */
+               s5p_mfc_wait_for_done_ctx(ctx,
+                               S5P_MFC_R2H_CMD_SEQ_DONE_RET, 0);
+               if (ctx->state >= MFCINST_HEAD_PARSED &&
+                   ctx->state < MFCINST_ABORT) {
+                       ctrl->val = ctx->pb_count;
+               } else {
+                       v4l2_err(&dev->v4l2_dev, "Decoding not initialised\n");
+                       return -EINVAL;
+               }
+               break;
+       }
+       return 0;
+}
+
+
+static const struct v4l2_ctrl_ops s5p_mfc_dec_ctrl_ops = {
+       .s_ctrl = s5p_mfc_dec_s_ctrl,
+       .g_volatile_ctrl = s5p_mfc_dec_g_v_ctrl,
+};
+
+/* Get compose information */
+static int vidioc_g_selection(struct file *file, void *priv,
+                             struct v4l2_selection *s)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+       struct s5p_mfc_dev *dev = ctx->dev;
+       u32 left, right, top, bottom;
+       u32 width, height;
+
+       if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       if (ctx->state != MFCINST_HEAD_PARSED &&
+           ctx->state != MFCINST_RUNNING &&
+           ctx->state != MFCINST_FINISHING &&
+           ctx->state != MFCINST_FINISHED) {
+               mfc_err("Can not get compose information\n");
+               return -EINVAL;
+       }
+       if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_H264) {
+               left = s5p_mfc_hw_call(dev->mfc_ops, get_crop_info_h, ctx);
+               right = left >> S5P_FIMV_SHARED_CROP_RIGHT_SHIFT;
+               left = left & S5P_FIMV_SHARED_CROP_LEFT_MASK;
+               top = s5p_mfc_hw_call(dev->mfc_ops, get_crop_info_v, ctx);
+               bottom = top >> S5P_FIMV_SHARED_CROP_BOTTOM_SHIFT;
+               top = top & S5P_FIMV_SHARED_CROP_TOP_MASK;
+               width = ctx->img_width - left - right;
+               height = ctx->img_height - top - bottom;
+               mfc_debug(2, "Composing info [h264]: l=%d t=%d w=%d h=%d (r=%d b=%d fw=%d fh=%d\n",
+                         left, top, s->r.width, s->r.height, right, bottom,
+                         ctx->buf_width, ctx->buf_height);
+       } else {
+               left = 0;
+               top = 0;
+               width = ctx->img_width;
+               height = ctx->img_height;
+               mfc_debug(2, "Composing info: w=%d h=%d fw=%d fh=%d\n",
+                         s->r.width, s->r.height, ctx->buf_width,
+                         ctx->buf_height);
+       }
+
+       switch (s->target) {
+       case V4L2_SEL_TGT_COMPOSE:
+       case V4L2_SEL_TGT_COMPOSE_DEFAULT:
+       case V4L2_SEL_TGT_COMPOSE_BOUNDS:
+               s->r.left = left;
+               s->r.top = top;
+               s->r.width = width;
+               s->r.height = height;
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int vidioc_decoder_cmd(struct file *file, void *priv,
+                             struct v4l2_decoder_cmd *cmd)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_buf *buf;
+       unsigned long flags;
+
+       switch (cmd->cmd) {
+       case V4L2_DEC_CMD_STOP:
+               if (cmd->flags != 0)
+                       return -EINVAL;
+
+               if (!vb2_is_streaming(&ctx->vq_src))
+                       return -EINVAL;
+
+               spin_lock_irqsave(&dev->irqlock, flags);
+               if (list_empty(&ctx->src_queue)) {
+                       mfc_err("EOS: empty src queue, entering finishing state");
+                       ctx->state = MFCINST_FINISHING;
+                       if (s5p_mfc_ctx_ready(ctx))
+                               set_work_bit_irqsave(ctx);
+                       spin_unlock_irqrestore(&dev->irqlock, flags);
+                       s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
+               } else {
+                       mfc_err("EOS: marking last buffer of stream");
+                       buf = list_entry(ctx->src_queue.prev,
+                                               struct s5p_mfc_buf, list);
+                       if (buf->flags & MFC_BUF_FLAG_USED)
+                               ctx->state = MFCINST_FINISHING;
+                       else
+                               buf->flags |= MFC_BUF_FLAG_EOS;
+                       spin_unlock_irqrestore(&dev->irqlock, flags);
+               }
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int vidioc_subscribe_event(struct v4l2_fh *fh,
+                               const struct  v4l2_event_subscription *sub)
+{
+       switch (sub->type) {
+       case V4L2_EVENT_EOS:
+               return v4l2_event_subscribe(fh, sub, 2, NULL);
+       case V4L2_EVENT_SOURCE_CHANGE:
+               return v4l2_src_change_event_subscribe(fh, sub);
+       default:
+               return -EINVAL;
+       }
+}
+
+
+/* v4l2_ioctl_ops */
+static const struct v4l2_ioctl_ops s5p_mfc_dec_ioctl_ops = {
+       .vidioc_querycap = vidioc_querycap,
+       .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
+       .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out,
+       .vidioc_g_fmt_vid_cap_mplane = vidioc_g_fmt,
+       .vidioc_g_fmt_vid_out_mplane = vidioc_g_fmt,
+       .vidioc_try_fmt_vid_cap_mplane = vidioc_try_fmt,
+       .vidioc_try_fmt_vid_out_mplane = vidioc_try_fmt,
+       .vidioc_s_fmt_vid_cap_mplane = vidioc_s_fmt,
+       .vidioc_s_fmt_vid_out_mplane = vidioc_s_fmt,
+       .vidioc_reqbufs = vidioc_reqbufs,
+       .vidioc_querybuf = vidioc_querybuf,
+       .vidioc_qbuf = vidioc_qbuf,
+       .vidioc_dqbuf = vidioc_dqbuf,
+       .vidioc_expbuf = vidioc_expbuf,
+       .vidioc_streamon = vidioc_streamon,
+       .vidioc_streamoff = vidioc_streamoff,
+       .vidioc_g_selection = vidioc_g_selection,
+       .vidioc_decoder_cmd = vidioc_decoder_cmd,
+       .vidioc_subscribe_event = vidioc_subscribe_event,
+       .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+};
+
+static int s5p_mfc_queue_setup(struct vb2_queue *vq,
+                       unsigned int *buf_count,
+                       unsigned int *plane_count, unsigned int psize[],
+                       struct device *alloc_devs[])
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       /* Video output for decoding (source)
+        * this can be set after getting an instance */
+       if (ctx->state == MFCINST_INIT &&
+           vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               /* A single plane is required for input */
+               *plane_count = 1;
+               if (*buf_count < 1)
+                       *buf_count = 1;
+               if (*buf_count > MFC_MAX_BUFFERS)
+                       *buf_count = MFC_MAX_BUFFERS;
+       /* Video capture for decoding (destination)
+        * this can be set after the header was parsed */
+       } else if (ctx->state == MFCINST_HEAD_PARSED &&
+                  vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               /* Output plane count is 2 - one for Y and one for CbCr */
+               *plane_count = 2;
+               /* Setup buffer count */
+               if (*buf_count < ctx->pb_count)
+                       *buf_count = ctx->pb_count;
+               if (*buf_count > ctx->pb_count + MFC_MAX_EXTRA_DPB)
+                       *buf_count = ctx->pb_count + MFC_MAX_EXTRA_DPB;
+               if (*buf_count > MFC_MAX_BUFFERS)
+                       *buf_count = MFC_MAX_BUFFERS;
+       } else {
+               mfc_err("State seems invalid. State = %d, vq->type = %d\n",
+                                                       ctx->state, vq->type);
+               return -EINVAL;
+       }
+       mfc_debug(2, "Buffer count=%d, plane count=%d\n",
+                                               *buf_count, *plane_count);
+       if (ctx->state == MFCINST_HEAD_PARSED &&
+           vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               psize[0] = ctx->luma_size;
+               psize[1] = ctx->chroma_size;
+
+               if (IS_MFCV6_PLUS(dev))
+                       alloc_devs[0] = ctx->dev->mem_dev[BANK_L_CTX];
+               else
+                       alloc_devs[0] = ctx->dev->mem_dev[BANK_R_CTX];
+               alloc_devs[1] = ctx->dev->mem_dev[BANK_L_CTX];
+       } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
+                  ctx->state == MFCINST_INIT) {
+               psize[0] = ctx->dec_src_buf_size;
+               alloc_devs[0] = ctx->dev->mem_dev[BANK_L_CTX];
+       } else {
+               mfc_err("This video node is dedicated to decoding. Decoding not initialized\n");
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int s5p_mfc_buf_init(struct vb2_buffer *vb)
+{
+       struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+       struct vb2_queue *vq = vb->vb2_queue;
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
+       unsigned int i;
+
+       if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               if (ctx->capture_state == QUEUE_BUFS_MMAPED)
+                       return 0;
+               for (i = 0; i < ctx->dst_fmt->num_planes; i++) {
+                       if (IS_ERR_OR_NULL(ERR_PTR(
+                                       vb2_dma_contig_plane_dma_addr(vb, i)))) {
+                               mfc_err("Plane mem not allocated\n");
+                               return -EINVAL;
+                       }
+               }
+               if (vb2_plane_size(vb, 0) < ctx->luma_size ||
+                       vb2_plane_size(vb, 1) < ctx->chroma_size) {
+                       mfc_err("Plane buffer (CAPTURE) is too small\n");
+                       return -EINVAL;
+               }
+               i = vb->index;
+               ctx->dst_bufs[i].b = vbuf;
+               ctx->dst_bufs[i].cookie.raw.luma =
+                                       vb2_dma_contig_plane_dma_addr(vb, 0);
+               ctx->dst_bufs[i].cookie.raw.chroma =
+                                       vb2_dma_contig_plane_dma_addr(vb, 1);
+               ctx->dst_bufs_cnt++;
+       } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               if (IS_ERR_OR_NULL(ERR_PTR(
+                                       vb2_dma_contig_plane_dma_addr(vb, 0)))) {
+                       mfc_err("Plane memory not allocated\n");
+                       return -EINVAL;
+               }
+               if (vb2_plane_size(vb, 0) < ctx->dec_src_buf_size) {
+                       mfc_err("Plane buffer (OUTPUT) is too small\n");
+                       return -EINVAL;
+               }
+
+               i = vb->index;
+               ctx->src_bufs[i].b = vbuf;
+               ctx->src_bufs[i].cookie.stream =
+                                       vb2_dma_contig_plane_dma_addr(vb, 0);
+               ctx->src_bufs_cnt++;
+       } else {
+               mfc_err("s5p_mfc_buf_init: unknown queue type\n");
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int s5p_mfc_start_streaming(struct vb2_queue *q, unsigned int count)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv);
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       v4l2_ctrl_handler_setup(&ctx->ctrl_handler);
+       if (ctx->state == MFCINST_FINISHING ||
+               ctx->state == MFCINST_FINISHED)
+               ctx->state = MFCINST_RUNNING;
+       /* If context is ready then dev = work->data;schedule it to run */
+       if (s5p_mfc_ctx_ready(ctx))
+               set_work_bit_irqsave(ctx);
+       s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
+       return 0;
+}
+
+static void s5p_mfc_stop_streaming(struct vb2_queue *q)
+{
+       unsigned long flags;
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv);
+       struct s5p_mfc_dev *dev = ctx->dev;
+       int aborted = 0;
+
+       spin_lock_irqsave(&dev->irqlock, flags);
+       if ((ctx->state == MFCINST_FINISHING ||
+               ctx->state ==  MFCINST_RUNNING) &&
+               dev->curr_ctx == ctx->num && dev->hw_lock) {
+               ctx->state = MFCINST_ABORT;
+               spin_unlock_irqrestore(&dev->irqlock, flags);
+               s5p_mfc_wait_for_done_ctx(ctx,
+                                       S5P_MFC_R2H_CMD_FRAME_DONE_RET, 0);
+               aborted = 1;
+               spin_lock_irqsave(&dev->irqlock, flags);
+       }
+       if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst);
+               INIT_LIST_HEAD(&ctx->dst_queue);
+               ctx->dst_queue_cnt = 0;
+               ctx->dpb_flush_flag = 1;
+               ctx->dec_dst_flag = 0;
+               if (IS_MFCV6_PLUS(dev) && (ctx->state == MFCINST_RUNNING)) {
+                       ctx->state = MFCINST_FLUSH;
+                       set_work_bit_irqsave(ctx);
+                       s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
+                       spin_unlock_irqrestore(&dev->irqlock, flags);
+                       if (s5p_mfc_wait_for_done_ctx(ctx,
+                               S5P_MFC_R2H_CMD_DPB_FLUSH_RET, 0))
+                               mfc_err("Err flushing buffers\n");
+                       spin_lock_irqsave(&dev->irqlock, flags);
+               }
+       } else if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src);
+               INIT_LIST_HEAD(&ctx->src_queue);
+               ctx->src_queue_cnt = 0;
+       }
+       if (aborted)
+               ctx->state = MFCINST_RUNNING;
+       spin_unlock_irqrestore(&dev->irqlock, flags);
+}
+
+
+static void s5p_mfc_buf_queue(struct vb2_buffer *vb)
+{
+       struct vb2_queue *vq = vb->vb2_queue;
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned long flags;
+       struct s5p_mfc_buf *mfc_buf;
+
+       if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               mfc_buf = &ctx->src_bufs[vb->index];
+               mfc_buf->flags &= ~MFC_BUF_FLAG_USED;
+               spin_lock_irqsave(&dev->irqlock, flags);
+               list_add_tail(&mfc_buf->list, &ctx->src_queue);
+               ctx->src_queue_cnt++;
+               spin_unlock_irqrestore(&dev->irqlock, flags);
+       } else if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               mfc_buf = &ctx->dst_bufs[vb->index];
+               mfc_buf->flags &= ~MFC_BUF_FLAG_USED;
+               /* Mark destination as available for use by MFC */
+               spin_lock_irqsave(&dev->irqlock, flags);
+               set_bit(vb->index, &ctx->dec_dst_flag);
+               list_add_tail(&mfc_buf->list, &ctx->dst_queue);
+               ctx->dst_queue_cnt++;
+               spin_unlock_irqrestore(&dev->irqlock, flags);
+       } else {
+               mfc_err("Unsupported buffer type (%d)\n", vq->type);
+       }
+       if (s5p_mfc_ctx_ready(ctx))
+               set_work_bit_irqsave(ctx);
+       s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
+}
+
+static struct vb2_ops s5p_mfc_dec_qops = {
+       .queue_setup            = s5p_mfc_queue_setup,
+       .wait_prepare           = vb2_ops_wait_prepare,
+       .wait_finish            = vb2_ops_wait_finish,
+       .buf_init               = s5p_mfc_buf_init,
+       .start_streaming        = s5p_mfc_start_streaming,
+       .stop_streaming         = s5p_mfc_stop_streaming,
+       .buf_queue              = s5p_mfc_buf_queue,
+};
+
+const struct s5p_mfc_codec_ops *get_dec_codec_ops(void)
+{
+       return &decoder_codec_ops;
+}
+
+struct vb2_ops *get_dec_queue_ops(void)
+{
+       return &s5p_mfc_dec_qops;
+}
+
+const struct v4l2_ioctl_ops *get_dec_v4l2_ioctl_ops(void)
+{
+       return &s5p_mfc_dec_ioctl_ops;
+}
+
+#define IS_MFC51_PRIV(x) ((V4L2_CTRL_ID2WHICH(x) == V4L2_CTRL_CLASS_CODEC) \
+                                               && V4L2_CTRL_DRIVER_PRIV(x))
+
+int s5p_mfc_dec_ctrls_setup(struct s5p_mfc_ctx *ctx)
+{
+       struct v4l2_ctrl_config cfg;
+       int i;
+
+       v4l2_ctrl_handler_init(&ctx->ctrl_handler, NUM_CTRLS);
+       if (ctx->ctrl_handler.error) {
+               mfc_err("v4l2_ctrl_handler_init failed\n");
+               return ctx->ctrl_handler.error;
+       }
+
+       for (i = 0; i < NUM_CTRLS; i++) {
+               if (IS_MFC51_PRIV(controls[i].id)) {
+                       memset(&cfg, 0, sizeof(struct v4l2_ctrl_config));
+                       cfg.ops = &s5p_mfc_dec_ctrl_ops;
+                       cfg.id = controls[i].id;
+                       cfg.min = controls[i].minimum;
+                       cfg.max = controls[i].maximum;
+                       cfg.def = controls[i].default_value;
+                       cfg.name = controls[i].name;
+                       cfg.type = controls[i].type;
+
+                       cfg.step = controls[i].step;
+                       cfg.menu_skip_mask = 0;
+
+                       ctx->ctrls[i] = v4l2_ctrl_new_custom(&ctx->ctrl_handler,
+                                       &cfg, NULL);
+               } else {
+                       ctx->ctrls[i] = v4l2_ctrl_new_std(&ctx->ctrl_handler,
+                                       &s5p_mfc_dec_ctrl_ops,
+                                       controls[i].id, controls[i].minimum,
+                                       controls[i].maximum, controls[i].step,
+                                       controls[i].default_value);
+               }
+               if (ctx->ctrl_handler.error) {
+                       mfc_err("Adding control (%d) failed\n", i);
+                       return ctx->ctrl_handler.error;
+               }
+               if (controls[i].is_volatile && ctx->ctrls[i])
+                       ctx->ctrls[i]->flags |= V4L2_CTRL_FLAG_VOLATILE;
+       }
+       return 0;
+}
+
+void s5p_mfc_dec_ctrls_delete(struct s5p_mfc_ctx *ctx)
+{
+       int i;
+
+       v4l2_ctrl_handler_free(&ctx->ctrl_handler);
+       for (i = 0; i < NUM_CTRLS; i++)
+               ctx->ctrls[i] = NULL;
+}
+
+void s5p_mfc_dec_init(struct s5p_mfc_ctx *ctx)
+{
+       struct v4l2_format f;
+       f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264;
+       ctx->src_fmt = find_format(&f, MFC_FMT_DEC);
+       if (IS_MFCV8_PLUS(ctx->dev))
+               f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12M;
+       else if (IS_MFCV6_PLUS(ctx->dev))
+               f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12MT_16X16;
+       else
+               f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12MT;
+       ctx->dst_fmt = find_format(&f, MFC_FMT_RAW);
+       mfc_debug(2, "Default src_fmt is %p, dest_fmt is %p\n",
+                       ctx->src_fmt, ctx->dst_fmt);
+}
+
diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_dec.h b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_dec.h
new file mode 100644 (file)
index 0000000..0c52ab4
--- /dev/null
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * linux/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_dec.h
+ *
+ * Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ */
+
+#ifndef S5P_MFC_DEC_H_
+#define S5P_MFC_DEC_H_
+
+const struct s5p_mfc_codec_ops *get_dec_codec_ops(void);
+struct vb2_ops *get_dec_queue_ops(void);
+const struct v4l2_ioctl_ops *get_dec_v4l2_ioctl_ops(void);
+struct s5p_mfc_fmt *get_dec_def_fmt(bool src);
+int s5p_mfc_dec_ctrls_setup(struct s5p_mfc_ctx *ctx);
+void s5p_mfc_dec_ctrls_delete(struct s5p_mfc_ctx *ctx);
+void s5p_mfc_dec_init(struct s5p_mfc_ctx *ctx);
+
+#endif /* S5P_MFC_DEC_H_ */
diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_enc.c
new file mode 100644 (file)
index 0000000..a8877d8
--- /dev/null
@@ -0,0 +1,2697 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * linux/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_enc.c
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * Jeongtae Park       <jtp.park@samsung.com>
+ * Kamil Debski                <k.debski@samsung.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-event.h>
+#include <linux/workqueue.h>
+#include <media/v4l2-ctrls.h>
+#include <media/videobuf2-v4l2.h>
+#include "s5p_mfc_common.h"
+#include "s5p_mfc_ctrl.h"
+#include "s5p_mfc_debug.h"
+#include "s5p_mfc_enc.h"
+#include "s5p_mfc_intr.h"
+#include "s5p_mfc_opr.h"
+
+#define DEF_SRC_FMT_ENC        V4L2_PIX_FMT_NV12M
+#define DEF_DST_FMT_ENC        V4L2_PIX_FMT_H264
+
+static struct s5p_mfc_fmt formats[] = {
+       {
+               .fourcc         = V4L2_PIX_FMT_NV12MT_16X16,
+               .codec_mode     = S5P_MFC_CODEC_NONE,
+               .type           = MFC_FMT_RAW,
+               .num_planes     = 2,
+               .versions       = MFC_V6_BIT | MFC_V7_BIT,
+       },
+       {
+               .fourcc         = V4L2_PIX_FMT_NV12MT,
+               .codec_mode     = S5P_MFC_CODEC_NONE,
+               .type           = MFC_FMT_RAW,
+               .num_planes     = 2,
+               .versions       = MFC_V5_BIT,
+       },
+       {
+               .fourcc         = V4L2_PIX_FMT_NV12M,
+               .codec_mode     = S5P_MFC_CODEC_NONE,
+               .type           = MFC_FMT_RAW,
+               .num_planes     = 2,
+               .versions       = MFC_V5PLUS_BITS,
+       },
+       {
+               .fourcc         = V4L2_PIX_FMT_NV21M,
+               .codec_mode     = S5P_MFC_CODEC_NONE,
+               .type           = MFC_FMT_RAW,
+               .num_planes     = 2,
+               .versions       = MFC_V6PLUS_BITS,
+       },
+       {
+               .fourcc         = V4L2_PIX_FMT_H264,
+               .codec_mode     = S5P_MFC_CODEC_H264_ENC,
+               .type           = MFC_FMT_ENC,
+               .num_planes     = 1,
+               .versions       = MFC_V5PLUS_BITS,
+       },
+       {
+               .fourcc         = V4L2_PIX_FMT_MPEG4,
+               .codec_mode     = S5P_MFC_CODEC_MPEG4_ENC,
+               .type           = MFC_FMT_ENC,
+               .num_planes     = 1,
+               .versions       = MFC_V5PLUS_BITS,
+       },
+       {
+               .fourcc         = V4L2_PIX_FMT_H263,
+               .codec_mode     = S5P_MFC_CODEC_H263_ENC,
+               .type           = MFC_FMT_ENC,
+               .num_planes     = 1,
+               .versions       = MFC_V5PLUS_BITS,
+       },
+       {
+               .fourcc         = V4L2_PIX_FMT_VP8,
+               .codec_mode     = S5P_MFC_CODEC_VP8_ENC,
+               .type           = MFC_FMT_ENC,
+               .num_planes     = 1,
+               .versions       = MFC_V7PLUS_BITS,
+       },
+       {
+               .fourcc         = V4L2_PIX_FMT_HEVC,
+               .codec_mode     = S5P_FIMV_CODEC_HEVC_ENC,
+               .type           = MFC_FMT_ENC,
+               .num_planes     = 1,
+               .versions       = MFC_V10_BIT,
+       },
+};
+
+#define NUM_FORMATS ARRAY_SIZE(formats)
+static struct s5p_mfc_fmt *find_format(struct v4l2_format *f, unsigned int t)
+{
+       unsigned int i;
+
+       for (i = 0; i < NUM_FORMATS; i++) {
+               if (formats[i].fourcc == f->fmt.pix_mp.pixelformat &&
+                   formats[i].type == t)
+                       return &formats[i];
+       }
+       return NULL;
+}
+
+static struct mfc_control controls[] = {
+       {
+               .id = V4L2_CID_MPEG_VIDEO_GOP_SIZE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = (1 << 16) - 1,
+               .step = 1,
+               .default_value = 12,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE,
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE,
+               .maximum = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES,
+               .default_value = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE,
+               .menu_skip_mask = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 1,
+               .maximum = (1 << 16) - 1,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 1900,
+               .maximum = (1 << 30) - 1,
+               .step = 1,
+               .default_value = 1900,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = (1 << 16) - 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_PADDING,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "Padding Control Enable",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_PADDING_YUV,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Padding Color YUV Value",
+               .minimum = 0,
+               .maximum = (1 << 25) - 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_BITRATE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 1,
+               .maximum = (1 << 30) - 1,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_RC_REACTION_COEFF,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Rate Control Reaction Coeff.",
+               .minimum = 1,
+               .maximum = (1 << 16) - 1,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE,
+               .type = V4L2_CTRL_TYPE_MENU,
+               .name = "Force frame type",
+               .minimum = V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_DISABLED,
+               .maximum = V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_NOT_CODED,
+               .default_value = V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_DISABLED,
+               .menu_skip_mask = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME,
+               .type = V4L2_CTRL_TYPE_BUTTON,
+               .minimum = 0,
+               .maximum = 0,
+               .step = 0,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_VBV_SIZE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = (1 << 16) - 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MV_H_SEARCH_RANGE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Horizontal MV Search Range",
+               .minimum = 16,
+               .maximum = 128,
+               .step = 16,
+               .default_value = 32,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MV_V_SEARCH_RANGE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Vertical MV Search Range",
+               .minimum = 16,
+               .maximum = 128,
+               .step = 16,
+               .default_value = 32,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = (1 << 16) - 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEADER_MODE,
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE,
+               .maximum = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME,
+               .default_value = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE,
+               .menu_skip_mask = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE,
+               .type = V4L2_CTRL_TYPE_MENU,
+               .name = "Frame Skip Enable",
+               .minimum = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_DISABLED,
+               .maximum = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT,
+               .menu_skip_mask = 0,
+               .default_value = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_DISABLED,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_FRAME_SKIP_MODE,
+               .type = V4L2_CTRL_TYPE_MENU,
+               .maximum = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT,
+               .default_value = V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_RC_FIXED_TARGET_BIT,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "Fixed Target Bit Enable",
+               .minimum = 0,
+               .maximum = 1,
+               .default_value = 0,
+               .step = 1,
+               .menu_skip_mask = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_B_FRAMES,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = 2,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_PROFILE,
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE,
+               .maximum = V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH,
+               .default_value = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE,
+               .menu_skip_mask = ~(
+                               (1 << V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) |
+                               (1 << V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) |
+                               (1 << V4L2_MPEG_VIDEO_H264_PROFILE_HIGH)
+                               ),
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_LEVEL,
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDEO_H264_LEVEL_1_0,
+               .maximum = V4L2_MPEG_VIDEO_H264_LEVEL_4_0,
+               .default_value = V4L2_MPEG_VIDEO_H264_LEVEL_1_0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL,
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDEO_MPEG4_LEVEL_0,
+               .maximum = V4L2_MPEG_VIDEO_MPEG4_LEVEL_5,
+               .default_value = V4L2_MPEG_VIDEO_MPEG4_LEVEL_0,
+               .menu_skip_mask = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE,
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED,
+               .maximum = V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY,
+               .default_value = V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED,
+               .menu_skip_mask = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = -6,
+               .maximum = 6,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = -6,
+               .maximum = 6,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE,
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC,
+               .maximum = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC,
+               .default_value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC,
+               .menu_skip_mask = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_H264_NUM_REF_PIC_FOR_P,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "The Number of Ref. Pic for P",
+               .minimum = 1,
+               .maximum = 2,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = 51,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_MIN_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = 51,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_MAX_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = 51,
+               .step = 1,
+               .default_value = 51,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = 51,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = 51,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "H263 I-Frame QP value",
+               .minimum = 1,
+               .maximum = 31,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H263_MIN_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "H263 Minimum QP value",
+               .minimum = 1,
+               .maximum = 31,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H263_MAX_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "H263 Maximum QP value",
+               .minimum = 1,
+               .maximum = 31,
+               .step = 1,
+               .default_value = 31,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "H263 P frame QP value",
+               .minimum = 1,
+               .maximum = 31,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "H263 B frame QP value",
+               .minimum = 1,
+               .maximum = 31,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "MPEG4 I-Frame QP value",
+               .minimum = 1,
+               .maximum = 31,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "MPEG4 Minimum QP value",
+               .minimum = 1,
+               .maximum = 31,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "MPEG4 Maximum QP value",
+               .minimum = 0,
+               .maximum = 51,
+               .step = 1,
+               .default_value = 51,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "MPEG4 P frame QP value",
+               .minimum = 1,
+               .maximum = 31,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "MPEG4 B frame QP value",
+               .minimum = 1,
+               .maximum = 31,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_DARK,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "H264 Dark Reg Adaptive RC",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_SMOOTH,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "H264 Smooth Reg Adaptive RC",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_STATIC,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "H264 Static Reg Adaptive RC",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_ACTIVITY,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "H264 Activity Reg Adaptive RC",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC,
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_UNSPECIFIED,
+               .maximum = V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_EXTENDED,
+               .default_value = V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_UNSPECIFIED,
+               .menu_skip_mask = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = (1 << 16) - 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_HEIGHT,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = (1 << 16) - 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_GOP_CLOSURE,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_I_PERIOD,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = (1 << 16) - 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE,
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE,
+               .maximum = V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE,
+               .default_value = V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE,
+               .menu_skip_mask = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MPEG4_QPEL,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_VPX_NUM_PARTITIONS,
+               .type = V4L2_CTRL_TYPE_INTEGER_MENU,
+               .maximum = V4L2_CID_MPEG_VIDEO_VPX_8_PARTITIONS,
+               .default_value = V4L2_CID_MPEG_VIDEO_VPX_1_PARTITION,
+               .menu_skip_mask = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_VPX_IMD_DISABLE_4X4,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_VPX_NUM_REF_FRAMES,
+               .type = V4L2_CTRL_TYPE_INTEGER_MENU,
+               .maximum = V4L2_CID_MPEG_VIDEO_VPX_2_REF_FRAME,
+               .default_value = V4L2_CID_MPEG_VIDEO_VPX_1_REF_FRAME,
+               .menu_skip_mask = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_VPX_FILTER_LEVEL,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = 63,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_VPX_FILTER_SHARPNESS,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = 7,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_REF_PERIOD,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = (1 << 16) - 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_SEL,
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_USE_PREV,
+               .maximum = V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_USE_REF_PERIOD,
+               .default_value = V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_USE_PREV,
+               .menu_skip_mask = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_VPX_MAX_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = 127,
+               .step = 1,
+               .default_value = 127,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_VPX_MIN_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = 11,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_VPX_I_FRAME_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = 127,
+               .step = 1,
+               .default_value = 10,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_VPX_P_FRAME_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = 127,
+               .step = 1,
+               .default_value = 10,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_VP8_PROFILE,
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDEO_VP8_PROFILE_0,
+               .maximum = V4L2_MPEG_VIDEO_VP8_PROFILE_3,
+               .default_value = V4L2_MPEG_VIDEO_VP8_PROFILE_0,
+               .menu_skip_mask = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "HEVC I Frame QP Value",
+               .minimum = 0,
+               .maximum = 51,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "HEVC P Frame QP Value",
+               .minimum = 0,
+               .maximum = 51,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = 51,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = 51,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = 51,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_PROFILE,
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN,
+               .maximum = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE,
+               .step = 1,
+               .default_value = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_LEVEL,
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDEO_HEVC_LEVEL_1,
+               .maximum = V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2,
+               .step = 1,
+               .default_value = V4L2_MPEG_VIDEO_HEVC_LEVEL_1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_TIER,
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDEO_HEVC_TIER_MAIN,
+               .maximum = V4L2_MPEG_VIDEO_HEVC_TIER_HIGH,
+               .step = 1,
+               .default_value = V4L2_MPEG_VIDEO_HEVC_TIER_MAIN,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_FRAME_RATE_RESOLUTION,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 1,
+               .maximum = (1 << 16) - 1,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_MAX_PARTITION_DEPTH,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_REF_NUMBER_FOR_PFRAMES,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 1,
+               .maximum = 2,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_REFRESH_TYPE,
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDEO_HEVC_REFRESH_NONE,
+               .maximum = V4L2_MPEG_VIDEO_HEVC_REFRESH_IDR,
+               .step = 1,
+               .default_value = V4L2_MPEG_VIDEO_HEVC_REFRESH_NONE,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_CONST_INTRA_PRED,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_LOSSLESS_CU,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_WAVEFRONT,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE,
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE_DISABLED,
+               .maximum = V4L2_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY,
+               .step = 1,
+               .default_value = V4L2_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE_DISABLED,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_QP,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_TYPE,
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B,
+               .maximum = V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P,
+               .step = 1,
+               .default_value = V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_LAYER,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = 6,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L0_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = 51,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L1_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = 51,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L2_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = 51,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L3_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = 51,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L4_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = 51,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L5_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = 51,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L6_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = 51,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L0_BR,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L1_BR,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L2_BR,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L3_BR,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L4_BR,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L5_BR,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L6_BR,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_GENERAL_PB,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_TEMPORAL_ID,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_STRONG_SMOOTHING,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_INTRA_PU_SPLIT,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_TMV_PREDICTION,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_MAX_NUM_MERGE_MV_MINUS1,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = 4,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_WITHOUT_STARTCODE,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_REFRESH_PERIOD,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = (1 << 16) - 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_LF_BETA_OFFSET_DIV2,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = -6,
+               .maximum = 6,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_LF_TC_OFFSET_DIV2,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = -6,
+               .maximum = 6,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_SIZE_OF_LENGTH_FIELD,
+               .type = V4L2_CTRL_TYPE_MENU,
+               .minimum = V4L2_MPEG_VIDEO_HEVC_SIZE_0,
+               .maximum = V4L2_MPEG_VIDEO_HEVC_SIZE_4,
+               .step = 1,
+               .default_value = V4L2_MPEG_VIDEO_HEVC_SIZE_0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_PREPEND_SPSPPS_TO_IDR,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MIN_BUFFERS_FOR_OUTPUT,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Minimum number of output bufs",
+               .minimum = 1,
+               .maximum = 32,
+               .step = 1,
+               .default_value = 1,
+               .is_volatile = 1,
+       },
+};
+
+#define NUM_CTRLS ARRAY_SIZE(controls)
+static const char * const *mfc51_get_menu(u32 id)
+{
+       static const char * const mfc51_video_frame_skip[] = {
+               "Disabled",
+               "Level Limit",
+               "VBV/CPB Limit",
+               NULL,
+       };
+       static const char * const mfc51_video_force_frame[] = {
+               "Disabled",
+               "I Frame",
+               "Not Coded",
+               NULL,
+       };
+       switch (id) {
+       case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE:
+               return mfc51_video_frame_skip;
+       case V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE:
+               return mfc51_video_force_frame;
+       }
+       return NULL;
+}
+
+static int s5p_mfc_ctx_ready(struct s5p_mfc_ctx *ctx)
+{
+       mfc_debug(2, "src=%d, dst=%d, state=%d\n",
+                 ctx->src_queue_cnt, ctx->dst_queue_cnt, ctx->state);
+       /* context is ready to make header */
+       if (ctx->state == MFCINST_GOT_INST && ctx->dst_queue_cnt >= 1)
+               return 1;
+       /* context is ready to encode a frame */
+       if ((ctx->state == MFCINST_RUNNING ||
+               ctx->state == MFCINST_HEAD_PRODUCED) &&
+               ctx->src_queue_cnt >= 1 && ctx->dst_queue_cnt >= 1)
+               return 1;
+       /* context is ready to encode remaining frames */
+       if (ctx->state == MFCINST_FINISHING &&
+               ctx->dst_queue_cnt >= 1)
+               return 1;
+       mfc_debug(2, "ctx is not ready\n");
+       return 0;
+}
+
+static void cleanup_ref_queue(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_buf *mb_entry;
+
+       /* move buffers in ref queue to src queue */
+       while (!list_empty(&ctx->ref_queue)) {
+               mb_entry = list_entry((&ctx->ref_queue)->next,
+                                               struct s5p_mfc_buf, list);
+               list_del(&mb_entry->list);
+               ctx->ref_queue_cnt--;
+               list_add_tail(&mb_entry->list, &ctx->src_queue);
+               ctx->src_queue_cnt++;
+       }
+       mfc_debug(2, "enc src count: %d, enc ref count: %d\n",
+                 ctx->src_queue_cnt, ctx->ref_queue_cnt);
+       INIT_LIST_HEAD(&ctx->ref_queue);
+       ctx->ref_queue_cnt = 0;
+}
+
+static int enc_pre_seq_start(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_buf *dst_mb;
+       unsigned long dst_addr;
+       unsigned int dst_size;
+
+       dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
+       dst_addr = vb2_dma_contig_plane_dma_addr(&dst_mb->b->vb2_buf, 0);
+       dst_size = vb2_plane_size(&dst_mb->b->vb2_buf, 0);
+       s5p_mfc_hw_call(dev->mfc_ops, set_enc_stream_buffer, ctx, dst_addr,
+                       dst_size);
+       return 0;
+}
+
+static int enc_post_seq_start(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc_params *p = &ctx->enc_params;
+       struct s5p_mfc_buf *dst_mb;
+       unsigned int enc_pb_count;
+
+       if (p->seq_hdr_mode == V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE) {
+               if (!list_empty(&ctx->dst_queue)) {
+                       dst_mb = list_entry(ctx->dst_queue.next,
+                                       struct s5p_mfc_buf, list);
+                       list_del(&dst_mb->list);
+                       ctx->dst_queue_cnt--;
+                       vb2_set_plane_payload(&dst_mb->b->vb2_buf, 0,
+                               s5p_mfc_hw_call(dev->mfc_ops, get_enc_strm_size,
+                                               dev));
+                       vb2_buffer_done(&dst_mb->b->vb2_buf,
+                                       VB2_BUF_STATE_DONE);
+               }
+       }
+
+       if (!IS_MFCV6_PLUS(dev)) {
+               ctx->state = MFCINST_RUNNING;
+               if (s5p_mfc_ctx_ready(ctx))
+                       set_work_bit_irqsave(ctx);
+               s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
+       } else {
+               enc_pb_count = s5p_mfc_hw_call(dev->mfc_ops,
+                               get_enc_dpb_count, dev);
+               if (ctx->pb_count < enc_pb_count)
+                       ctx->pb_count = enc_pb_count;
+               if (FW_HAS_E_MIN_SCRATCH_BUF(dev)) {
+                       ctx->scratch_buf_size = s5p_mfc_hw_call(dev->mfc_ops,
+                                       get_e_min_scratch_buf_size, dev);
+                       ctx->bank1.size += ctx->scratch_buf_size;
+               }
+               ctx->state = MFCINST_HEAD_PRODUCED;
+       }
+
+       return 0;
+}
+
+static int enc_pre_frame_start(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_buf *dst_mb;
+       struct s5p_mfc_buf *src_mb;
+       unsigned long src_y_addr, src_c_addr, dst_addr;
+       unsigned int dst_size;
+
+       src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
+       src_y_addr = vb2_dma_contig_plane_dma_addr(&src_mb->b->vb2_buf, 0);
+       src_c_addr = vb2_dma_contig_plane_dma_addr(&src_mb->b->vb2_buf, 1);
+       s5p_mfc_hw_call(dev->mfc_ops, set_enc_frame_buffer, ctx,
+                                                       src_y_addr, src_c_addr);
+
+       dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
+       dst_addr = vb2_dma_contig_plane_dma_addr(&dst_mb->b->vb2_buf, 0);
+       dst_size = vb2_plane_size(&dst_mb->b->vb2_buf, 0);
+       s5p_mfc_hw_call(dev->mfc_ops, set_enc_stream_buffer, ctx, dst_addr,
+                       dst_size);
+
+       return 0;
+}
+
+static int enc_post_frame_start(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_buf *mb_entry;
+       unsigned long enc_y_addr = 0, enc_c_addr = 0;
+       unsigned long mb_y_addr, mb_c_addr;
+       int slice_type;
+       unsigned int strm_size;
+
+       slice_type = s5p_mfc_hw_call(dev->mfc_ops, get_enc_slice_type, dev);
+       strm_size = s5p_mfc_hw_call(dev->mfc_ops, get_enc_strm_size, dev);
+       mfc_debug(2, "Encoded slice type: %d\n", slice_type);
+       mfc_debug(2, "Encoded stream size: %d\n", strm_size);
+       mfc_debug(2, "Display order: %d\n",
+                 mfc_read(dev, S5P_FIMV_ENC_SI_PIC_CNT));
+       if (slice_type >= 0) {
+               s5p_mfc_hw_call(dev->mfc_ops, get_enc_frame_buffer, ctx,
+                               &enc_y_addr, &enc_c_addr);
+               list_for_each_entry(mb_entry, &ctx->src_queue, list) {
+                       mb_y_addr = vb2_dma_contig_plane_dma_addr(
+                                       &mb_entry->b->vb2_buf, 0);
+                       mb_c_addr = vb2_dma_contig_plane_dma_addr(
+                                       &mb_entry->b->vb2_buf, 1);
+                       if ((enc_y_addr == mb_y_addr) &&
+                                               (enc_c_addr == mb_c_addr)) {
+                               list_del(&mb_entry->list);
+                               ctx->src_queue_cnt--;
+                               vb2_buffer_done(&mb_entry->b->vb2_buf,
+                                                       VB2_BUF_STATE_DONE);
+                               break;
+                       }
+               }
+               list_for_each_entry(mb_entry, &ctx->ref_queue, list) {
+                       mb_y_addr = vb2_dma_contig_plane_dma_addr(
+                                       &mb_entry->b->vb2_buf, 0);
+                       mb_c_addr = vb2_dma_contig_plane_dma_addr(
+                                       &mb_entry->b->vb2_buf, 1);
+                       if ((enc_y_addr == mb_y_addr) &&
+                                               (enc_c_addr == mb_c_addr)) {
+                               list_del(&mb_entry->list);
+                               ctx->ref_queue_cnt--;
+                               vb2_buffer_done(&mb_entry->b->vb2_buf,
+                                                       VB2_BUF_STATE_DONE);
+                               break;
+                       }
+               }
+       }
+       if ((ctx->src_queue_cnt > 0) && (ctx->state == MFCINST_RUNNING)) {
+               mb_entry = list_entry(ctx->src_queue.next, struct s5p_mfc_buf,
+                                                                       list);
+               if (mb_entry->flags & MFC_BUF_FLAG_USED) {
+                       list_del(&mb_entry->list);
+                       ctx->src_queue_cnt--;
+                       list_add_tail(&mb_entry->list, &ctx->ref_queue);
+                       ctx->ref_queue_cnt++;
+               }
+       }
+       mfc_debug(2, "enc src count: %d, enc ref count: %d\n",
+                 ctx->src_queue_cnt, ctx->ref_queue_cnt);
+       if ((ctx->dst_queue_cnt > 0) && (strm_size > 0)) {
+               mb_entry = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf,
+                                                                       list);
+               list_del(&mb_entry->list);
+               ctx->dst_queue_cnt--;
+               switch (slice_type) {
+               case S5P_FIMV_ENC_SI_SLICE_TYPE_I:
+                       mb_entry->b->flags |= V4L2_BUF_FLAG_KEYFRAME;
+                       break;
+               case S5P_FIMV_ENC_SI_SLICE_TYPE_P:
+                       mb_entry->b->flags |= V4L2_BUF_FLAG_PFRAME;
+                       break;
+               case S5P_FIMV_ENC_SI_SLICE_TYPE_B:
+                       mb_entry->b->flags |= V4L2_BUF_FLAG_BFRAME;
+                       break;
+               }
+               vb2_set_plane_payload(&mb_entry->b->vb2_buf, 0, strm_size);
+               vb2_buffer_done(&mb_entry->b->vb2_buf, VB2_BUF_STATE_DONE);
+       }
+       if ((ctx->src_queue_cnt == 0) || (ctx->dst_queue_cnt == 0))
+               clear_work_bit(ctx);
+
+       return 0;
+}
+
+static const struct s5p_mfc_codec_ops encoder_codec_ops = {
+       .pre_seq_start          = enc_pre_seq_start,
+       .post_seq_start         = enc_post_seq_start,
+       .pre_frame_start        = enc_pre_frame_start,
+       .post_frame_start       = enc_post_frame_start,
+};
+
+/* Query capabilities of the device */
+static int vidioc_querycap(struct file *file, void *priv,
+                          struct v4l2_capability *cap)
+{
+       struct s5p_mfc_dev *dev = video_drvdata(file);
+
+       strscpy(cap->driver, S5P_MFC_NAME, sizeof(cap->driver));
+       strscpy(cap->card, dev->vfd_enc->name, sizeof(cap->card));
+       snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
+                dev_name(&dev->plat_dev->dev));
+       return 0;
+}
+
+static int vidioc_enum_fmt(struct file *file, struct v4l2_fmtdesc *f,
+                                                       bool out)
+{
+       struct s5p_mfc_dev *dev = video_drvdata(file);
+       int i, j = 0;
+
+       for (i = 0; i < ARRAY_SIZE(formats); ++i) {
+               if (out && formats[i].type != MFC_FMT_RAW)
+                       continue;
+               else if (!out && formats[i].type != MFC_FMT_ENC)
+                       continue;
+               else if ((dev->variant->version_bit & formats[i].versions) == 0)
+                       continue;
+
+               if (j == f->index) {
+                       f->pixelformat = formats[i].fourcc;
+                       return 0;
+               }
+               ++j;
+       }
+       return -EINVAL;
+}
+
+static int vidioc_enum_fmt_vid_cap(struct file *file, void *pirv,
+                                  struct v4l2_fmtdesc *f)
+{
+       return vidioc_enum_fmt(file, f, false);
+}
+
+static int vidioc_enum_fmt_vid_out(struct file *file, void *priv,
+                                  struct v4l2_fmtdesc *f)
+{
+       return vidioc_enum_fmt(file, f, true);
+}
+
+static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+       struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
+
+       mfc_debug(2, "f->type = %d ctx->state = %d\n", f->type, ctx->state);
+       if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               /* This is run on output (encoder dest) */
+               pix_fmt_mp->width = 0;
+               pix_fmt_mp->height = 0;
+               pix_fmt_mp->field = V4L2_FIELD_NONE;
+               pix_fmt_mp->pixelformat = ctx->dst_fmt->fourcc;
+               pix_fmt_mp->num_planes = ctx->dst_fmt->num_planes;
+
+               pix_fmt_mp->plane_fmt[0].bytesperline = ctx->enc_dst_buf_size;
+               pix_fmt_mp->plane_fmt[0].sizeimage = ctx->enc_dst_buf_size;
+       } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               /* This is run on capture (encoder src) */
+               pix_fmt_mp->width = ctx->img_width;
+               pix_fmt_mp->height = ctx->img_height;
+
+               pix_fmt_mp->field = V4L2_FIELD_NONE;
+               pix_fmt_mp->pixelformat = ctx->src_fmt->fourcc;
+               pix_fmt_mp->num_planes = ctx->src_fmt->num_planes;
+
+               pix_fmt_mp->plane_fmt[0].bytesperline = ctx->buf_width;
+               pix_fmt_mp->plane_fmt[0].sizeimage = ctx->luma_size;
+               pix_fmt_mp->plane_fmt[1].bytesperline = ctx->buf_width;
+               pix_fmt_mp->plane_fmt[1].sizeimage = ctx->chroma_size;
+       } else {
+               mfc_err("invalid buf type\n");
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
+{
+       struct s5p_mfc_dev *dev = video_drvdata(file);
+       struct s5p_mfc_fmt *fmt;
+       struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
+
+       if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               fmt = find_format(f, MFC_FMT_ENC);
+               if (!fmt) {
+                       mfc_err("failed to try output format\n");
+                       return -EINVAL;
+               }
+               if ((dev->variant->version_bit & fmt->versions) == 0) {
+                       mfc_err("Unsupported format by this MFC version.\n");
+                       return -EINVAL;
+               }
+
+               pix_fmt_mp->plane_fmt[0].bytesperline =
+                       pix_fmt_mp->plane_fmt[0].sizeimage;
+       } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               fmt = find_format(f, MFC_FMT_RAW);
+               if (!fmt) {
+                       mfc_err("failed to try output format\n");
+                       return -EINVAL;
+               }
+               if ((dev->variant->version_bit & fmt->versions) == 0) {
+                       mfc_err("Unsupported format by this MFC version.\n");
+                       return -EINVAL;
+               }
+
+               v4l_bound_align_image(&pix_fmt_mp->width, 8, 1920, 1,
+                       &pix_fmt_mp->height, 4, 1080, 1, 0);
+       } else {
+               mfc_err("invalid buf type\n");
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
+{
+       struct s5p_mfc_dev *dev = video_drvdata(file);
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+       struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
+       int ret = 0;
+
+       ret = vidioc_try_fmt(file, priv, f);
+       if (ret)
+               return ret;
+       if (ctx->vq_src.streaming || ctx->vq_dst.streaming) {
+               v4l2_err(&dev->v4l2_dev, "%s queue busy\n", __func__);
+               ret = -EBUSY;
+               goto out;
+       }
+       if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               /* dst_fmt is validated by call to vidioc_try_fmt */
+               ctx->dst_fmt = find_format(f, MFC_FMT_ENC);
+               ctx->state = MFCINST_INIT;
+               ctx->codec_mode = ctx->dst_fmt->codec_mode;
+               ctx->enc_dst_buf_size = pix_fmt_mp->plane_fmt[0].sizeimage;
+               pix_fmt_mp->plane_fmt[0].bytesperline = 0;
+               ctx->dst_bufs_cnt = 0;
+               ctx->capture_state = QUEUE_FREE;
+               ret = s5p_mfc_open_mfc_inst(dev, ctx);
+       } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               /* src_fmt is validated by call to vidioc_try_fmt */
+               ctx->src_fmt = find_format(f, MFC_FMT_RAW);
+               ctx->img_width = pix_fmt_mp->width;
+               ctx->img_height = pix_fmt_mp->height;
+               mfc_debug(2, "codec number: %d\n", ctx->src_fmt->codec_mode);
+               mfc_debug(2, "fmt - w: %d, h: %d, ctx - w: %d, h: %d\n",
+                       pix_fmt_mp->width, pix_fmt_mp->height,
+                       ctx->img_width, ctx->img_height);
+
+               s5p_mfc_hw_call(dev->mfc_ops, enc_calc_src_size, ctx);
+               pix_fmt_mp->plane_fmt[0].sizeimage = ctx->luma_size;
+               pix_fmt_mp->plane_fmt[0].bytesperline = ctx->buf_width;
+               pix_fmt_mp->plane_fmt[1].sizeimage = ctx->chroma_size;
+               pix_fmt_mp->plane_fmt[1].bytesperline = ctx->buf_width;
+
+               ctx->src_bufs_cnt = 0;
+               ctx->output_state = QUEUE_FREE;
+       } else {
+               mfc_err("invalid buf type\n");
+               ret = -EINVAL;
+       }
+out:
+       mfc_debug_leave();
+       return ret;
+}
+
+static int vidioc_reqbufs(struct file *file, void *priv,
+                                         struct v4l2_requestbuffers *reqbufs)
+{
+       struct s5p_mfc_dev *dev = video_drvdata(file);
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+       int ret = 0;
+
+       /* if memory is not mmp or userptr return error */
+       if ((reqbufs->memory != V4L2_MEMORY_MMAP) &&
+               (reqbufs->memory != V4L2_MEMORY_USERPTR))
+               return -EINVAL;
+       if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               if (reqbufs->count == 0) {
+                       mfc_debug(2, "Freeing buffers\n");
+                       ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
+                       s5p_mfc_hw_call(dev->mfc_ops, release_codec_buffers,
+                                       ctx);
+                       ctx->capture_state = QUEUE_FREE;
+                       return ret;
+               }
+               if (ctx->capture_state != QUEUE_FREE) {
+                       mfc_err("invalid capture state: %d\n",
+                                                       ctx->capture_state);
+                       return -EINVAL;
+               }
+               ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
+               if (ret != 0) {
+                       mfc_err("error in vb2_reqbufs() for E(D)\n");
+                       return ret;
+               }
+               ctx->capture_state = QUEUE_BUFS_REQUESTED;
+
+               ret = s5p_mfc_hw_call(ctx->dev->mfc_ops,
+                               alloc_codec_buffers, ctx);
+               if (ret) {
+                       mfc_err("Failed to allocate encoding buffers\n");
+                       reqbufs->count = 0;
+                       ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
+                       return -ENOMEM;
+               }
+       } else if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               if (reqbufs->count == 0) {
+                       mfc_debug(2, "Freeing buffers\n");
+                       ret = vb2_reqbufs(&ctx->vq_src, reqbufs);
+                       s5p_mfc_hw_call(dev->mfc_ops, release_codec_buffers,
+                                       ctx);
+                       ctx->output_state = QUEUE_FREE;
+                       return ret;
+               }
+               if (ctx->output_state != QUEUE_FREE) {
+                       mfc_err("invalid output state: %d\n",
+                                                       ctx->output_state);
+                       return -EINVAL;
+               }
+
+               if (IS_MFCV6_PLUS(dev)) {
+                       /* Check for min encoder buffers */
+                       if (ctx->pb_count &&
+                               (reqbufs->count < ctx->pb_count)) {
+                               reqbufs->count = ctx->pb_count;
+                               mfc_debug(2, "Minimum %d output buffers needed\n",
+                                               ctx->pb_count);
+                       } else {
+                               ctx->pb_count = reqbufs->count;
+                       }
+               }
+
+               ret = vb2_reqbufs(&ctx->vq_src, reqbufs);
+               if (ret != 0) {
+                       mfc_err("error in vb2_reqbufs() for E(S)\n");
+                       return ret;
+               }
+               ctx->output_state = QUEUE_BUFS_REQUESTED;
+       } else {
+               mfc_err("invalid buf type\n");
+               return -EINVAL;
+       }
+       return ret;
+}
+
+static int vidioc_querybuf(struct file *file, void *priv,
+                                                  struct v4l2_buffer *buf)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+       int ret = 0;
+
+       /* if memory is not mmp or userptr return error */
+       if ((buf->memory != V4L2_MEMORY_MMAP) &&
+               (buf->memory != V4L2_MEMORY_USERPTR))
+               return -EINVAL;
+       if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               if (ctx->state != MFCINST_GOT_INST) {
+                       mfc_err("invalid context state: %d\n", ctx->state);
+                       return -EINVAL;
+               }
+               ret = vb2_querybuf(&ctx->vq_dst, buf);
+               if (ret != 0) {
+                       mfc_err("error in vb2_querybuf() for E(D)\n");
+                       return ret;
+               }
+               buf->m.planes[0].m.mem_offset += DST_QUEUE_OFF_BASE;
+       } else if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               ret = vb2_querybuf(&ctx->vq_src, buf);
+               if (ret != 0) {
+                       mfc_err("error in vb2_querybuf() for E(S)\n");
+                       return ret;
+               }
+       } else {
+               mfc_err("invalid buf type\n");
+               return -EINVAL;
+       }
+       return ret;
+}
+
+/* Queue a buffer */
+static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+
+       if (ctx->state == MFCINST_ERROR) {
+               mfc_err("Call on QBUF after unrecoverable error\n");
+               return -EIO;
+       }
+       if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               if (ctx->state == MFCINST_FINISHING) {
+                       mfc_err("Call on QBUF after EOS command\n");
+                       return -EIO;
+               }
+               return vb2_qbuf(&ctx->vq_src, NULL, buf);
+       } else if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               return vb2_qbuf(&ctx->vq_dst, NULL, buf);
+       }
+       return -EINVAL;
+}
+
+/* Dequeue a buffer */
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
+{
+       const struct v4l2_event ev = {
+               .type = V4L2_EVENT_EOS
+       };
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+       int ret;
+
+       if (ctx->state == MFCINST_ERROR) {
+               mfc_err_limited("Call on DQBUF after unrecoverable error\n");
+               return -EIO;
+       }
+       if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               ret = vb2_dqbuf(&ctx->vq_src, buf, file->f_flags & O_NONBLOCK);
+       } else if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               ret = vb2_dqbuf(&ctx->vq_dst, buf, file->f_flags & O_NONBLOCK);
+               if (ret == 0 && ctx->state == MFCINST_FINISHED
+                                       && list_empty(&ctx->vq_dst.done_list))
+                       v4l2_event_queue_fh(&ctx->fh, &ev);
+       } else {
+               ret = -EINVAL;
+       }
+
+       return ret;
+}
+
+/* Export DMA buffer */
+static int vidioc_expbuf(struct file *file, void *priv,
+       struct v4l2_exportbuffer *eb)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+
+       if (eb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+               return vb2_expbuf(&ctx->vq_src, eb);
+       if (eb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+               return vb2_expbuf(&ctx->vq_dst, eb);
+       return -EINVAL;
+}
+
+/* Stream on */
+static int vidioc_streamon(struct file *file, void *priv,
+                          enum v4l2_buf_type type)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+
+       if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+               return vb2_streamon(&ctx->vq_src, type);
+       else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+               return vb2_streamon(&ctx->vq_dst, type);
+       return -EINVAL;
+}
+
+/* Stream off, which equals to a pause */
+static int vidioc_streamoff(struct file *file, void *priv,
+                           enum v4l2_buf_type type)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+
+       if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+               return vb2_streamoff(&ctx->vq_src, type);
+       else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+               return vb2_streamoff(&ctx->vq_dst, type);
+       return -EINVAL;
+}
+
+static inline int h264_level(enum v4l2_mpeg_video_h264_level lvl)
+{
+       static unsigned int t[V4L2_MPEG_VIDEO_H264_LEVEL_4_0 + 1] = {
+               /* V4L2_MPEG_VIDEO_H264_LEVEL_1_0   */ 10,
+               /* V4L2_MPEG_VIDEO_H264_LEVEL_1B    */ 9,
+               /* V4L2_MPEG_VIDEO_H264_LEVEL_1_1   */ 11,
+               /* V4L2_MPEG_VIDEO_H264_LEVEL_1_2   */ 12,
+               /* V4L2_MPEG_VIDEO_H264_LEVEL_1_3   */ 13,
+               /* V4L2_MPEG_VIDEO_H264_LEVEL_2_0   */ 20,
+               /* V4L2_MPEG_VIDEO_H264_LEVEL_2_1   */ 21,
+               /* V4L2_MPEG_VIDEO_H264_LEVEL_2_2   */ 22,
+               /* V4L2_MPEG_VIDEO_H264_LEVEL_3_0   */ 30,
+               /* V4L2_MPEG_VIDEO_H264_LEVEL_3_1   */ 31,
+               /* V4L2_MPEG_VIDEO_H264_LEVEL_3_2   */ 32,
+               /* V4L2_MPEG_VIDEO_H264_LEVEL_4_0   */ 40,
+       };
+       return t[lvl];
+}
+
+static inline int mpeg4_level(enum v4l2_mpeg_video_mpeg4_level lvl)
+{
+       static unsigned int t[V4L2_MPEG_VIDEO_MPEG4_LEVEL_5 + 1] = {
+               /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_0    */ 0,
+               /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_0B   */ 9,
+               /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_1    */ 1,
+               /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_2    */ 2,
+               /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_3    */ 3,
+               /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_3B   */ 7,
+               /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_4    */ 4,
+               /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_5    */ 5,
+       };
+       return t[lvl];
+}
+
+static inline int hevc_level(enum v4l2_mpeg_video_hevc_level lvl)
+{
+       static unsigned int t[] = {
+               /* V4L2_MPEG_VIDEO_HEVC_LEVEL_1    */ 10,
+               /* V4L2_MPEG_VIDEO_HEVC_LEVEL_2    */ 20,
+               /* V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1  */ 21,
+               /* V4L2_MPEG_VIDEO_HEVC_LEVEL_3    */ 30,
+               /* V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1  */ 31,
+               /* V4L2_MPEG_VIDEO_HEVC_LEVEL_4    */ 40,
+               /* V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1  */ 41,
+               /* V4L2_MPEG_VIDEO_HEVC_LEVEL_5    */ 50,
+               /* V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1  */ 51,
+               /* V4L2_MPEG_VIDEO_HEVC_LEVEL_5_2  */ 52,
+               /* V4L2_MPEG_VIDEO_HEVC_LEVEL_6    */ 60,
+               /* V4L2_MPEG_VIDEO_HEVC_LEVEL_6_1  */ 61,
+               /* V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2  */ 62,
+       };
+       return t[lvl];
+}
+
+static inline int vui_sar_idc(enum v4l2_mpeg_video_h264_vui_sar_idc sar)
+{
+       static unsigned int t[V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_EXTENDED + 1] = {
+               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_UNSPECIFIED     */ 0,
+               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_1x1             */ 1,
+               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_12x11           */ 2,
+               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_10x11           */ 3,
+               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_16x11           */ 4,
+               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_40x33           */ 5,
+               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_24x11           */ 6,
+               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_20x11           */ 7,
+               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_32x11           */ 8,
+               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_80x33           */ 9,
+               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_18x11           */ 10,
+               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_15x11           */ 11,
+               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_64x33           */ 12,
+               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_160x99          */ 13,
+               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_4x3             */ 14,
+               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_3x2             */ 15,
+               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_2x1             */ 16,
+               /* V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_EXTENDED        */ 255,
+       };
+       return t[sar];
+}
+
+/*
+ * Update range of all HEVC quantization parameter controls that depend on the
+ * V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP, V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP controls.
+ */
+static void __enc_update_hevc_qp_ctrls_range(struct s5p_mfc_ctx *ctx,
+                                            int min, int max)
+{
+       static const int __hevc_qp_ctrls[] = {
+               V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP,
+               V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_QP,
+               V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_QP,
+               V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L0_QP,
+               V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L1_QP,
+               V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L2_QP,
+               V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L3_QP,
+               V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L4_QP,
+               V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L5_QP,
+               V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L6_QP,
+       };
+       struct v4l2_ctrl *ctrl = NULL;
+       int i, j;
+
+       for (i = 0; i < ARRAY_SIZE(__hevc_qp_ctrls); i++) {
+               for (j = 0; j < ARRAY_SIZE(ctx->ctrls); j++) {
+                       if (ctx->ctrls[j]->id == __hevc_qp_ctrls[i]) {
+                               ctrl = ctx->ctrls[j];
+                               break;
+                       }
+               }
+               if (WARN_ON(!ctrl))
+                       break;
+
+               __v4l2_ctrl_modify_range(ctrl, min, max, ctrl->step, min);
+       }
+}
+
+static int s5p_mfc_enc_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct s5p_mfc_ctx *ctx = ctrl_to_ctx(ctrl);
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc_params *p = &ctx->enc_params;
+       int ret = 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
+               p->gop_size = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE:
+               p->slice_mode = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB:
+               p->slice_mb = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES:
+               p->slice_bit = ctrl->val * 8;
+               break;
+       case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB:
+               p->intra_refresh_mb = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_PADDING:
+               p->pad = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_PADDING_YUV:
+               p->pad_luma = (ctrl->val >> 16) & 0xff;
+               p->pad_cb = (ctrl->val >> 8) & 0xff;
+               p->pad_cr = (ctrl->val >> 0) & 0xff;
+               break;
+       case V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE:
+               p->rc_frame = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_BITRATE:
+               p->rc_bitrate = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_RC_REACTION_COEFF:
+               p->rc_reaction_coeff = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE:
+               ctx->force_frame_type = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME:
+               ctx->force_frame_type =
+                       V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_I_FRAME;
+               break;
+       case V4L2_CID_MPEG_VIDEO_VBV_SIZE:
+               p->vbv_size = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_MV_H_SEARCH_RANGE:
+               p->mv_h_range = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_MV_V_SEARCH_RANGE:
+               p->mv_v_range = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE:
+               p->codec.h264.cpb_size = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEADER_MODE:
+               p->seq_hdr_mode = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE:
+       case V4L2_CID_MPEG_VIDEO_FRAME_SKIP_MODE:
+               p->frame_skip_mode = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_RC_FIXED_TARGET_BIT:
+               p->fixed_target_bit = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_B_FRAMES:
+               p->num_b_frame = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
+               switch (ctrl->val) {
+               case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:
+                       p->codec.h264.profile =
+                                       S5P_FIMV_ENC_PROFILE_H264_MAIN;
+                       break;
+               case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH:
+                       p->codec.h264.profile =
+                                       S5P_FIMV_ENC_PROFILE_H264_HIGH;
+                       break;
+               case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
+                       p->codec.h264.profile =
+                               S5P_FIMV_ENC_PROFILE_H264_BASELINE;
+                       break;
+               case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
+                       if (IS_MFCV6_PLUS(dev))
+                               p->codec.h264.profile =
+                               S5P_FIMV_ENC_PROFILE_H264_CONSTRAINED_BASELINE;
+                       else
+                               ret = -EINVAL;
+                       break;
+               default:
+                       ret = -EINVAL;
+               }
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
+               p->codec.h264.level_v4l2 = ctrl->val;
+               p->codec.h264.level = h264_level(ctrl->val);
+               if (p->codec.h264.level < 0) {
+                       mfc_err("Level number is wrong\n");
+                       ret = p->codec.h264.level;
+               }
+               break;
+       case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL:
+               p->codec.mpeg4.level_v4l2 = ctrl->val;
+               p->codec.mpeg4.level = mpeg4_level(ctrl->val);
+               if (p->codec.mpeg4.level < 0) {
+                       mfc_err("Level number is wrong\n");
+                       ret = p->codec.mpeg4.level;
+               }
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE:
+               p->codec.h264.loop_filter_mode = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA:
+               p->codec.h264.loop_filter_alpha = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA:
+               p->codec.h264.loop_filter_beta = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:
+               p->codec.h264.entropy_mode = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_H264_NUM_REF_PIC_FOR_P:
+               p->codec.h264.num_ref_pic_4p = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM:
+               p->codec.h264._8x8_transform = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE:
+               p->rc_mb = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP:
+               p->codec.h264.rc_frame_qp = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:
+               p->codec.h264.rc_min_qp = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:
+               p->codec.h264.rc_max_qp = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP:
+               p->codec.h264.rc_p_frame_qp = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP:
+               p->codec.h264.rc_b_frame_qp = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP:
+       case V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP:
+               p->codec.mpeg4.rc_frame_qp = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP:
+       case V4L2_CID_MPEG_VIDEO_H263_MIN_QP:
+               p->codec.mpeg4.rc_min_qp = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP:
+       case V4L2_CID_MPEG_VIDEO_H263_MAX_QP:
+               p->codec.mpeg4.rc_max_qp = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP:
+       case V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP:
+               p->codec.mpeg4.rc_p_frame_qp = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP:
+       case V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP:
+               p->codec.mpeg4.rc_b_frame_qp = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_DARK:
+               p->codec.h264.rc_mb_dark = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_SMOOTH:
+               p->codec.h264.rc_mb_smooth = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_STATIC:
+               p->codec.h264.rc_mb_static = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_ACTIVITY:
+               p->codec.h264.rc_mb_activity = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE:
+               p->codec.h264.vui_sar = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC:
+               p->codec.h264.vui_sar_idc = vui_sar_idc(ctrl->val);
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH:
+               p->codec.h264.vui_ext_sar_width = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_HEIGHT:
+               p->codec.h264.vui_ext_sar_height = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
+               p->codec.h264.open_gop = !ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_I_PERIOD:
+               p->codec.h264.open_gop_size = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE:
+               switch (ctrl->val) {
+               case V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE:
+                       p->codec.mpeg4.profile =
+                               S5P_FIMV_ENC_PROFILE_MPEG4_SIMPLE;
+                       break;
+               case V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE:
+                       p->codec.mpeg4.profile =
+                       S5P_FIMV_ENC_PROFILE_MPEG4_ADVANCED_SIMPLE;
+                       break;
+               default:
+                       ret = -EINVAL;
+               }
+               break;
+       case V4L2_CID_MPEG_VIDEO_MPEG4_QPEL:
+               p->codec.mpeg4.quarter_pixel = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_VPX_NUM_PARTITIONS:
+               p->codec.vp8.num_partitions = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_VPX_IMD_DISABLE_4X4:
+               p->codec.vp8.imd_4x4 = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_VPX_NUM_REF_FRAMES:
+               p->codec.vp8.num_ref = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_VPX_FILTER_LEVEL:
+               p->codec.vp8.filter_level = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_VPX_FILTER_SHARPNESS:
+               p->codec.vp8.filter_sharpness = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_REF_PERIOD:
+               p->codec.vp8.golden_frame_ref_period = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_SEL:
+               p->codec.vp8.golden_frame_sel = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_VPX_MIN_QP:
+               p->codec.vp8.rc_min_qp = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_VPX_MAX_QP:
+               p->codec.vp8.rc_max_qp = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_VPX_I_FRAME_QP:
+               p->codec.vp8.rc_frame_qp = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_VPX_P_FRAME_QP:
+               p->codec.vp8.rc_p_frame_qp = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_VP8_PROFILE:
+               p->codec.vp8.profile = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP:
+               p->codec.hevc.rc_frame_qp = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_QP:
+               p->codec.hevc.rc_p_frame_qp = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_QP:
+               p->codec.hevc.rc_b_frame_qp = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_FRAME_RATE_RESOLUTION:
+               p->codec.hevc.rc_framerate = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP:
+               p->codec.hevc.rc_min_qp = ctrl->val;
+               __enc_update_hevc_qp_ctrls_range(ctx, ctrl->val,
+                                                p->codec.hevc.rc_max_qp);
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP:
+               p->codec.hevc.rc_max_qp = ctrl->val;
+               __enc_update_hevc_qp_ctrls_range(ctx, p->codec.hevc.rc_min_qp,
+                                                ctrl->val);
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_LEVEL:
+               p->codec.hevc.level_v4l2 = ctrl->val;
+               p->codec.hevc.level = hevc_level(ctrl->val);
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_PROFILE:
+               switch (ctrl->val) {
+               case V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN:
+                       p->codec.hevc.profile =
+                               V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN;
+                       break;
+               case V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE:
+                       p->codec.hevc.profile =
+                       V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE;
+                       break;
+               default:
+                       ret = -EINVAL;
+               }
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_TIER:
+               p->codec.hevc.tier = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_MAX_PARTITION_DEPTH:
+               p->codec.hevc.max_partition_depth = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_REF_NUMBER_FOR_PFRAMES:
+               p->codec.hevc.num_refs_for_p = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_REFRESH_TYPE:
+               p->codec.hevc.refreshtype = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_CONST_INTRA_PRED:
+               p->codec.hevc.const_intra_period_enable = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_LOSSLESS_CU:
+               p->codec.hevc.lossless_cu_enable = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_WAVEFRONT:
+               p->codec.hevc.wavefront_enable = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE:
+               p->codec.hevc.loopfilter = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_HIER_QP:
+               p->codec.hevc.hier_qp_enable = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_TYPE:
+               p->codec.hevc.hier_qp_type = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_LAYER:
+               p->codec.hevc.num_hier_layer = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L0_QP:
+               p->codec.hevc.hier_qp_layer[0] = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L1_QP:
+               p->codec.hevc.hier_qp_layer[1] = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L2_QP:
+               p->codec.hevc.hier_qp_layer[2] = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L3_QP:
+               p->codec.hevc.hier_qp_layer[3] = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L4_QP:
+               p->codec.hevc.hier_qp_layer[4] = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L5_QP:
+               p->codec.hevc.hier_qp_layer[5] = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L6_QP:
+               p->codec.hevc.hier_qp_layer[6] = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L0_BR:
+               p->codec.hevc.hier_bit_layer[0] = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L1_BR:
+               p->codec.hevc.hier_bit_layer[1] = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L2_BR:
+               p->codec.hevc.hier_bit_layer[2] = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L3_BR:
+               p->codec.hevc.hier_bit_layer[3] = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L4_BR:
+               p->codec.hevc.hier_bit_layer[4] = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L5_BR:
+               p->codec.hevc.hier_bit_layer[5] = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L6_BR:
+               p->codec.hevc.hier_bit_layer[6] = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_GENERAL_PB:
+               p->codec.hevc.general_pb_enable = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_TEMPORAL_ID:
+               p->codec.hevc.temporal_id_enable = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_STRONG_SMOOTHING:
+               p->codec.hevc.strong_intra_smooth = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_INTRA_PU_SPLIT:
+               p->codec.hevc.intra_pu_split_disable = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_TMV_PREDICTION:
+               p->codec.hevc.tmv_prediction_disable = !ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_MAX_NUM_MERGE_MV_MINUS1:
+               p->codec.hevc.max_num_merge_mv = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_WITHOUT_STARTCODE:
+               p->codec.hevc.encoding_nostartcode_enable = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_REFRESH_PERIOD:
+               p->codec.hevc.refreshperiod = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_LF_BETA_OFFSET_DIV2:
+               p->codec.hevc.lf_beta_offset_div2 = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_LF_TC_OFFSET_DIV2:
+               p->codec.hevc.lf_tc_offset_div2 = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_SIZE_OF_LENGTH_FIELD:
+               p->codec.hevc.size_of_length_field = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_PREPEND_SPSPPS_TO_IDR:
+               p->codec.hevc.prepend_sps_pps_to_idr = ctrl->val;
+               break;
+       default:
+               v4l2_err(&dev->v4l2_dev, "Invalid control, id=%d, val=%d\n",
+                                                       ctrl->id, ctrl->val);
+               ret = -EINVAL;
+       }
+       return ret;
+}
+
+static int s5p_mfc_enc_g_v_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct s5p_mfc_ctx *ctx = ctrl_to_ctx(ctrl);
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       switch (ctrl->id) {
+       case V4L2_CID_MIN_BUFFERS_FOR_OUTPUT:
+               if (ctx->state >= MFCINST_HEAD_PARSED &&
+                   ctx->state < MFCINST_ABORT) {
+                       ctrl->val = ctx->pb_count;
+                       break;
+               } else if (ctx->state != MFCINST_INIT) {
+                       v4l2_err(&dev->v4l2_dev, "Encoding not initialised\n");
+                       return -EINVAL;
+               }
+               /* Should wait for the header to be produced */
+               s5p_mfc_wait_for_done_ctx(ctx,
+                               S5P_MFC_R2H_CMD_SEQ_DONE_RET, 0);
+               if (ctx->state >= MFCINST_HEAD_PARSED &&
+                   ctx->state < MFCINST_ABORT) {
+                       ctrl->val = ctx->pb_count;
+               } else {
+                       v4l2_err(&dev->v4l2_dev, "Encoding not initialised\n");
+                       return -EINVAL;
+               }
+               break;
+       }
+       return 0;
+}
+
+static const struct v4l2_ctrl_ops s5p_mfc_enc_ctrl_ops = {
+       .s_ctrl = s5p_mfc_enc_s_ctrl,
+       .g_volatile_ctrl = s5p_mfc_enc_g_v_ctrl,
+};
+
+static int vidioc_s_parm(struct file *file, void *priv,
+                        struct v4l2_streamparm *a)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+
+       if (a->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               ctx->enc_params.rc_framerate_num =
+                                       a->parm.output.timeperframe.denominator;
+               ctx->enc_params.rc_framerate_denom =
+                                       a->parm.output.timeperframe.numerator;
+       } else {
+               mfc_err("Setting FPS is only possible for the output queue\n");
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int vidioc_g_parm(struct file *file, void *priv,
+                        struct v4l2_streamparm *a)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+
+       if (a->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+               a->parm.output.timeperframe.denominator =
+                                       ctx->enc_params.rc_framerate_num;
+               a->parm.output.timeperframe.numerator =
+                                       ctx->enc_params.rc_framerate_denom;
+       } else {
+               mfc_err("Setting FPS is only possible for the output queue\n");
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int vidioc_encoder_cmd(struct file *file, void *priv,
+                             struct v4l2_encoder_cmd *cmd)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_buf *buf;
+       unsigned long flags;
+
+       switch (cmd->cmd) {
+       case V4L2_ENC_CMD_STOP:
+               if (cmd->flags != 0)
+                       return -EINVAL;
+
+               if (!ctx->vq_src.streaming)
+                       return -EINVAL;
+
+               spin_lock_irqsave(&dev->irqlock, flags);
+               if (list_empty(&ctx->src_queue)) {
+                       mfc_debug(2, "EOS: empty src queue, entering finishing state\n");
+                       ctx->state = MFCINST_FINISHING;
+                       if (s5p_mfc_ctx_ready(ctx))
+                               set_work_bit_irqsave(ctx);
+                       spin_unlock_irqrestore(&dev->irqlock, flags);
+                       s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
+               } else {
+                       mfc_debug(2, "EOS: marking last buffer of stream\n");
+                       buf = list_entry(ctx->src_queue.prev,
+                                               struct s5p_mfc_buf, list);
+                       if (buf->flags & MFC_BUF_FLAG_USED)
+                               ctx->state = MFCINST_FINISHING;
+                       else
+                               buf->flags |= MFC_BUF_FLAG_EOS;
+                       spin_unlock_irqrestore(&dev->irqlock, flags);
+               }
+               break;
+       default:
+               return -EINVAL;
+
+       }
+       return 0;
+}
+
+static int vidioc_subscribe_event(struct v4l2_fh *fh,
+                                 const struct v4l2_event_subscription *sub)
+{
+       switch (sub->type) {
+       case V4L2_EVENT_EOS:
+               return v4l2_event_subscribe(fh, sub, 2, NULL);
+       default:
+               return -EINVAL;
+       }
+}
+
+static const struct v4l2_ioctl_ops s5p_mfc_enc_ioctl_ops = {
+       .vidioc_querycap = vidioc_querycap,
+       .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
+       .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out,
+       .vidioc_g_fmt_vid_cap_mplane = vidioc_g_fmt,
+       .vidioc_g_fmt_vid_out_mplane = vidioc_g_fmt,
+       .vidioc_try_fmt_vid_cap_mplane = vidioc_try_fmt,
+       .vidioc_try_fmt_vid_out_mplane = vidioc_try_fmt,
+       .vidioc_s_fmt_vid_cap_mplane = vidioc_s_fmt,
+       .vidioc_s_fmt_vid_out_mplane = vidioc_s_fmt,
+       .vidioc_reqbufs = vidioc_reqbufs,
+       .vidioc_querybuf = vidioc_querybuf,
+       .vidioc_qbuf = vidioc_qbuf,
+       .vidioc_dqbuf = vidioc_dqbuf,
+       .vidioc_expbuf = vidioc_expbuf,
+       .vidioc_streamon = vidioc_streamon,
+       .vidioc_streamoff = vidioc_streamoff,
+       .vidioc_s_parm = vidioc_s_parm,
+       .vidioc_g_parm = vidioc_g_parm,
+       .vidioc_encoder_cmd = vidioc_encoder_cmd,
+       .vidioc_subscribe_event = vidioc_subscribe_event,
+       .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+};
+
+static int check_vb_with_fmt(struct s5p_mfc_fmt *fmt, struct vb2_buffer *vb)
+{
+       int i;
+
+       if (!fmt)
+               return -EINVAL;
+       if (fmt->num_planes != vb->num_planes) {
+               mfc_err("invalid plane number for the format\n");
+               return -EINVAL;
+       }
+       for (i = 0; i < fmt->num_planes; i++) {
+               dma_addr_t dma = vb2_dma_contig_plane_dma_addr(vb, i);
+               if (!dma) {
+                       mfc_err("failed to get plane cookie\n");
+                       return -EINVAL;
+               }
+               mfc_debug(2, "index: %d, plane[%d] cookie: %pad\n",
+                         vb->index, i, &dma);
+       }
+       return 0;
+}
+
+static int s5p_mfc_queue_setup(struct vb2_queue *vq,
+                       unsigned int *buf_count, unsigned int *plane_count,
+                       unsigned int psize[], struct device *alloc_devs[])
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               if (ctx->state != MFCINST_GOT_INST) {
+                       mfc_err("invalid state: %d\n", ctx->state);
+                       return -EINVAL;
+               }
+
+               if (ctx->dst_fmt)
+                       *plane_count = ctx->dst_fmt->num_planes;
+               else
+                       *plane_count = MFC_ENC_CAP_PLANE_COUNT;
+               if (*buf_count < 1)
+                       *buf_count = 1;
+               if (*buf_count > MFC_MAX_BUFFERS)
+                       *buf_count = MFC_MAX_BUFFERS;
+               psize[0] = ctx->enc_dst_buf_size;
+               alloc_devs[0] = ctx->dev->mem_dev[BANK_L_CTX];
+       } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               if (ctx->src_fmt)
+                       *plane_count = ctx->src_fmt->num_planes;
+               else
+                       *plane_count = MFC_ENC_OUT_PLANE_COUNT;
+
+               if (*buf_count < 1)
+                       *buf_count = 1;
+               if (*buf_count > MFC_MAX_BUFFERS)
+                       *buf_count = MFC_MAX_BUFFERS;
+
+               psize[0] = ctx->luma_size;
+               psize[1] = ctx->chroma_size;
+
+               if (IS_MFCV6_PLUS(dev)) {
+                       alloc_devs[0] = ctx->dev->mem_dev[BANK_L_CTX];
+                       alloc_devs[1] = ctx->dev->mem_dev[BANK_L_CTX];
+               } else {
+                       alloc_devs[0] = ctx->dev->mem_dev[BANK_R_CTX];
+                       alloc_devs[1] = ctx->dev->mem_dev[BANK_R_CTX];
+               }
+       } else {
+               mfc_err("invalid queue type: %d\n", vq->type);
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int s5p_mfc_buf_init(struct vb2_buffer *vb)
+{
+       struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+       struct vb2_queue *vq = vb->vb2_queue;
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
+       unsigned int i;
+       int ret;
+
+       if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               ret = check_vb_with_fmt(ctx->dst_fmt, vb);
+               if (ret < 0)
+                       return ret;
+               i = vb->index;
+               ctx->dst_bufs[i].b = vbuf;
+               ctx->dst_bufs[i].cookie.stream =
+                                       vb2_dma_contig_plane_dma_addr(vb, 0);
+               ctx->dst_bufs_cnt++;
+       } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               ret = check_vb_with_fmt(ctx->src_fmt, vb);
+               if (ret < 0)
+                       return ret;
+               i = vb->index;
+               ctx->src_bufs[i].b = vbuf;
+               ctx->src_bufs[i].cookie.raw.luma =
+                                       vb2_dma_contig_plane_dma_addr(vb, 0);
+               ctx->src_bufs[i].cookie.raw.chroma =
+                                       vb2_dma_contig_plane_dma_addr(vb, 1);
+               ctx->src_bufs_cnt++;
+       } else {
+               mfc_err("invalid queue type: %d\n", vq->type);
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int s5p_mfc_buf_prepare(struct vb2_buffer *vb)
+{
+       struct vb2_queue *vq = vb->vb2_queue;
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
+       int ret;
+
+       if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               ret = check_vb_with_fmt(ctx->dst_fmt, vb);
+               if (ret < 0)
+                       return ret;
+               mfc_debug(2, "plane size: %ld, dst size: %zu\n",
+                       vb2_plane_size(vb, 0), ctx->enc_dst_buf_size);
+               if (vb2_plane_size(vb, 0) < ctx->enc_dst_buf_size) {
+                       mfc_err("plane size is too small for capture\n");
+                       return -EINVAL;
+               }
+       } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               ret = check_vb_with_fmt(ctx->src_fmt, vb);
+               if (ret < 0)
+                       return ret;
+               mfc_debug(2, "plane size: %ld, luma size: %d\n",
+                       vb2_plane_size(vb, 0), ctx->luma_size);
+               mfc_debug(2, "plane size: %ld, chroma size: %d\n",
+                       vb2_plane_size(vb, 1), ctx->chroma_size);
+               if (vb2_plane_size(vb, 0) < ctx->luma_size ||
+                   vb2_plane_size(vb, 1) < ctx->chroma_size) {
+                       mfc_err("plane size is too small for output\n");
+                       return -EINVAL;
+               }
+       } else {
+               mfc_err("invalid queue type: %d\n", vq->type);
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int s5p_mfc_start_streaming(struct vb2_queue *q, unsigned int count)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv);
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       if (IS_MFCV6_PLUS(dev) &&
+                       (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)) {
+
+               if ((ctx->state == MFCINST_GOT_INST) &&
+                       (dev->curr_ctx == ctx->num) && dev->hw_lock) {
+                       s5p_mfc_wait_for_done_ctx(ctx,
+                                               S5P_MFC_R2H_CMD_SEQ_DONE_RET,
+                                               0);
+               }
+
+               if (ctx->src_bufs_cnt < ctx->pb_count) {
+                       mfc_err("Need minimum %d OUTPUT buffers\n",
+                                       ctx->pb_count);
+                       return -ENOBUFS;
+               }
+       }
+
+       /* If context is ready then dev = work->data;schedule it to run */
+       if (s5p_mfc_ctx_ready(ctx))
+               set_work_bit_irqsave(ctx);
+       s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
+
+       return 0;
+}
+
+static void s5p_mfc_stop_streaming(struct vb2_queue *q)
+{
+       unsigned long flags;
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv);
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       if ((ctx->state == MFCINST_FINISHING ||
+               ctx->state == MFCINST_RUNNING) &&
+               dev->curr_ctx == ctx->num && dev->hw_lock) {
+               ctx->state = MFCINST_ABORT;
+               s5p_mfc_wait_for_done_ctx(ctx, S5P_MFC_R2H_CMD_FRAME_DONE_RET,
+                                         0);
+       }
+       ctx->state = MFCINST_FINISHED;
+       spin_lock_irqsave(&dev->irqlock, flags);
+       if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst);
+               INIT_LIST_HEAD(&ctx->dst_queue);
+               ctx->dst_queue_cnt = 0;
+       }
+       if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               cleanup_ref_queue(ctx);
+               s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src);
+               INIT_LIST_HEAD(&ctx->src_queue);
+               ctx->src_queue_cnt = 0;
+       }
+       spin_unlock_irqrestore(&dev->irqlock, flags);
+}
+
+static void s5p_mfc_buf_queue(struct vb2_buffer *vb)
+{
+       struct vb2_queue *vq = vb->vb2_queue;
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned long flags;
+       struct s5p_mfc_buf *mfc_buf;
+
+       if (ctx->state == MFCINST_ERROR) {
+               vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
+               cleanup_ref_queue(ctx);
+               return;
+       }
+       if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               mfc_buf = &ctx->dst_bufs[vb->index];
+               mfc_buf->flags &= ~MFC_BUF_FLAG_USED;
+               /* Mark destination as available for use by MFC */
+               spin_lock_irqsave(&dev->irqlock, flags);
+               list_add_tail(&mfc_buf->list, &ctx->dst_queue);
+               ctx->dst_queue_cnt++;
+               spin_unlock_irqrestore(&dev->irqlock, flags);
+       } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               mfc_buf = &ctx->src_bufs[vb->index];
+               mfc_buf->flags &= ~MFC_BUF_FLAG_USED;
+               spin_lock_irqsave(&dev->irqlock, flags);
+               list_add_tail(&mfc_buf->list, &ctx->src_queue);
+               ctx->src_queue_cnt++;
+               spin_unlock_irqrestore(&dev->irqlock, flags);
+       } else {
+               mfc_err("unsupported buffer type (%d)\n", vq->type);
+       }
+       if (s5p_mfc_ctx_ready(ctx))
+               set_work_bit_irqsave(ctx);
+       s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
+}
+
+static struct vb2_ops s5p_mfc_enc_qops = {
+       .queue_setup            = s5p_mfc_queue_setup,
+       .wait_prepare           = vb2_ops_wait_prepare,
+       .wait_finish            = vb2_ops_wait_finish,
+       .buf_init               = s5p_mfc_buf_init,
+       .buf_prepare            = s5p_mfc_buf_prepare,
+       .start_streaming        = s5p_mfc_start_streaming,
+       .stop_streaming         = s5p_mfc_stop_streaming,
+       .buf_queue              = s5p_mfc_buf_queue,
+};
+
+const struct s5p_mfc_codec_ops *get_enc_codec_ops(void)
+{
+       return &encoder_codec_ops;
+}
+
+struct vb2_ops *get_enc_queue_ops(void)
+{
+       return &s5p_mfc_enc_qops;
+}
+
+const struct v4l2_ioctl_ops *get_enc_v4l2_ioctl_ops(void)
+{
+       return &s5p_mfc_enc_ioctl_ops;
+}
+
+#define IS_MFC51_PRIV(x) ((V4L2_CTRL_ID2WHICH(x) == V4L2_CTRL_CLASS_CODEC) \
+                                               && V4L2_CTRL_DRIVER_PRIV(x))
+
+int s5p_mfc_enc_ctrls_setup(struct s5p_mfc_ctx *ctx)
+{
+       struct v4l2_ctrl_config cfg;
+       int i;
+
+       v4l2_ctrl_handler_init(&ctx->ctrl_handler, NUM_CTRLS);
+       if (ctx->ctrl_handler.error) {
+               mfc_err("v4l2_ctrl_handler_init failed\n");
+               return ctx->ctrl_handler.error;
+       }
+       for (i = 0; i < NUM_CTRLS; i++) {
+               if (IS_MFC51_PRIV(controls[i].id)) {
+                       memset(&cfg, 0, sizeof(struct v4l2_ctrl_config));
+                       cfg.ops = &s5p_mfc_enc_ctrl_ops;
+                       cfg.id = controls[i].id;
+                       cfg.min = controls[i].minimum;
+                       cfg.max = controls[i].maximum;
+                       cfg.def = controls[i].default_value;
+                       cfg.name = controls[i].name;
+                       cfg.type = controls[i].type;
+                       cfg.flags = 0;
+
+                       if (cfg.type == V4L2_CTRL_TYPE_MENU) {
+                               cfg.step = 0;
+                               cfg.menu_skip_mask = controls[i].menu_skip_mask;
+                               cfg.qmenu = mfc51_get_menu(cfg.id);
+                       } else {
+                               cfg.step = controls[i].step;
+                               cfg.menu_skip_mask = 0;
+                       }
+                       ctx->ctrls[i] = v4l2_ctrl_new_custom(&ctx->ctrl_handler,
+                                       &cfg, NULL);
+               } else {
+                       if ((controls[i].type == V4L2_CTRL_TYPE_MENU) ||
+                               (controls[i].type ==
+                                       V4L2_CTRL_TYPE_INTEGER_MENU)) {
+                               ctx->ctrls[i] = v4l2_ctrl_new_std_menu(
+                                       &ctx->ctrl_handler,
+                                       &s5p_mfc_enc_ctrl_ops, controls[i].id,
+                                       controls[i].maximum, 0,
+                                       controls[i].default_value);
+                       } else {
+                               ctx->ctrls[i] = v4l2_ctrl_new_std(
+                                       &ctx->ctrl_handler,
+                                       &s5p_mfc_enc_ctrl_ops, controls[i].id,
+                                       controls[i].minimum,
+                                       controls[i].maximum, controls[i].step,
+                                       controls[i].default_value);
+                       }
+               }
+               if (ctx->ctrl_handler.error) {
+                       mfc_err("Adding control (%d) failed\n", i);
+                       return ctx->ctrl_handler.error;
+               }
+               if (controls[i].is_volatile && ctx->ctrls[i])
+                       ctx->ctrls[i]->flags |= V4L2_CTRL_FLAG_VOLATILE;
+       }
+       v4l2_ctrl_handler_setup(&ctx->ctrl_handler);
+       return 0;
+}
+
+void s5p_mfc_enc_ctrls_delete(struct s5p_mfc_ctx *ctx)
+{
+       int i;
+
+       v4l2_ctrl_handler_free(&ctx->ctrl_handler);
+       for (i = 0; i < NUM_CTRLS; i++)
+               ctx->ctrls[i] = NULL;
+}
+
+void s5p_mfc_enc_init(struct s5p_mfc_ctx *ctx)
+{
+       struct v4l2_format f;
+       f.fmt.pix_mp.pixelformat = DEF_SRC_FMT_ENC;
+       ctx->src_fmt = find_format(&f, MFC_FMT_RAW);
+       f.fmt.pix_mp.pixelformat = DEF_DST_FMT_ENC;
+       ctx->dst_fmt = find_format(&f, MFC_FMT_ENC);
+}
diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_enc.h b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_enc.h
new file mode 100644 (file)
index 0000000..3f1b1a0
--- /dev/null
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * linux/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_enc.h
+ *
+ * Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ */
+
+#ifndef S5P_MFC_ENC_H_
+#define S5P_MFC_ENC_H_
+
+const struct s5p_mfc_codec_ops *get_enc_codec_ops(void);
+struct vb2_ops *get_enc_queue_ops(void);
+const struct v4l2_ioctl_ops *get_enc_v4l2_ioctl_ops(void);
+struct s5p_mfc_fmt *get_enc_def_fmt(bool src);
+int s5p_mfc_enc_ctrls_setup(struct s5p_mfc_ctx *ctx);
+void s5p_mfc_enc_ctrls_delete(struct s5p_mfc_ctx *ctx);
+void s5p_mfc_enc_init(struct s5p_mfc_ctx *ctx);
+
+#endif /* S5P_MFC_ENC_H_  */
diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_intr.c b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_intr.c
new file mode 100644 (file)
index 0000000..0a38f6d
--- /dev/null
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * drivers/media/platform/samsung/mfc5/s5p_mfc_intr.c
+ *
+ * C file for Samsung MFC (Multi Function Codec - FIMV) driver
+ * This file contains functions used to wait for command completion.
+ *
+ * Kamil Debski, Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ */
+
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include "s5p_mfc_common.h"
+#include "s5p_mfc_debug.h"
+#include "s5p_mfc_intr.h"
+
+int s5p_mfc_wait_for_done_dev(struct s5p_mfc_dev *dev, int command)
+{
+       int ret;
+
+       ret = wait_event_interruptible_timeout(dev->queue,
+               (dev->int_cond && (dev->int_type == command
+               || dev->int_type == S5P_MFC_R2H_CMD_ERR_RET)),
+               msecs_to_jiffies(MFC_INT_TIMEOUT));
+       if (ret == 0) {
+               mfc_err("Interrupt (dev->int_type:%d, command:%d) timed out\n",
+                                                       dev->int_type, command);
+               return 1;
+       } else if (ret == -ERESTARTSYS) {
+               mfc_err("Interrupted by a signal\n");
+               return 1;
+       }
+       mfc_debug(1, "Finished waiting (dev->int_type:%d, command: %d)\n",
+                                                       dev->int_type, command);
+       if (dev->int_type == S5P_MFC_R2H_CMD_ERR_RET)
+               return 1;
+       return 0;
+}
+
+void s5p_mfc_clean_dev_int_flags(struct s5p_mfc_dev *dev)
+{
+       dev->int_cond = 0;
+       dev->int_type = 0;
+       dev->int_err = 0;
+}
+
+int s5p_mfc_wait_for_done_ctx(struct s5p_mfc_ctx *ctx,
+                                   int command, int interrupt)
+{
+       int ret;
+
+       if (interrupt) {
+               ret = wait_event_interruptible_timeout(ctx->queue,
+                               (ctx->int_cond && (ctx->int_type == command
+                       || ctx->int_type == S5P_MFC_R2H_CMD_ERR_RET)),
+                                       msecs_to_jiffies(MFC_INT_TIMEOUT));
+       } else {
+               ret = wait_event_timeout(ctx->queue,
+                               (ctx->int_cond && (ctx->int_type == command
+                       || ctx->int_type == S5P_MFC_R2H_CMD_ERR_RET)),
+                                       msecs_to_jiffies(MFC_INT_TIMEOUT));
+       }
+       if (ret == 0) {
+               mfc_err("Interrupt (ctx->int_type:%d, command:%d) timed out\n",
+                                                       ctx->int_type, command);
+               return 1;
+       } else if (ret == -ERESTARTSYS) {
+               mfc_err("Interrupted by a signal\n");
+               return 1;
+       }
+       mfc_debug(1, "Finished waiting (ctx->int_type:%d, command: %d)\n",
+                                                       ctx->int_type, command);
+       if (ctx->int_type == S5P_MFC_R2H_CMD_ERR_RET)
+               return 1;
+       return 0;
+}
+
+void s5p_mfc_clean_ctx_int_flags(struct s5p_mfc_ctx *ctx)
+{
+       ctx->int_cond = 0;
+       ctx->int_type = 0;
+       ctx->int_err = 0;
+}
+
diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_intr.h b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_intr.h
new file mode 100644 (file)
index 0000000..d32860d
--- /dev/null
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * drivers/media/platform/samsung/mfc5/s5p_mfc_intr.h
+ *
+ * Header file for Samsung MFC (Multi Function Codec - FIMV) driver
+ * It contains waiting functions declarations.
+ *
+ * Kamil Debski, Copyright (C) 2011 Samsung Electronics
+ * http://www.samsung.com/
+ */
+
+#ifndef S5P_MFC_INTR_H_
+#define S5P_MFC_INTR_H_
+
+#include "s5p_mfc_common.h"
+
+int s5p_mfc_wait_for_done_ctx(struct s5p_mfc_ctx *ctx,
+                             int command, int interrupt);
+int s5p_mfc_wait_for_done_dev(struct s5p_mfc_dev *dev, int command);
+void s5p_mfc_clean_ctx_int_flags(struct s5p_mfc_ctx *ctx);
+void s5p_mfc_clean_dev_int_flags(struct s5p_mfc_dev *dev);
+
+#endif /* S5P_MFC_INTR_H_ */
diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_iommu.h b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_iommu.h
new file mode 100644 (file)
index 0000000..1a32266
--- /dev/null
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2015 Samsung Electronics Co.Ltd
+ * Authors: Marek Szyprowski <m.szyprowski@samsung.com>
+ */
+
+#ifndef S5P_MFC_IOMMU_H_
+#define S5P_MFC_IOMMU_H_
+
+#if defined(CONFIG_EXYNOS_IOMMU)
+
+#include <linux/iommu.h>
+
+static inline bool exynos_is_iommu_available(struct device *dev)
+{
+       return dev_iommu_priv_get(dev) != NULL;
+}
+
+#else
+
+static inline bool exynos_is_iommu_available(struct device *dev)
+{
+       return false;
+}
+
+#endif
+
+#endif /* S5P_MFC_IOMMU_H_ */
diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_opr.c b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_opr.c
new file mode 100644 (file)
index 0000000..6739623
--- /dev/null
@@ -0,0 +1,124 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * drivers/media/platform/samsung/s5p-mfc/s5p_mfc_opr.c
+ *
+ * Samsung MFC (Multi Function Codec - FIMV) driver
+ * This file contains hw related functions.
+ *
+ * Kamil Debski, Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ */
+
+#include "s5p_mfc_debug.h"
+#include "s5p_mfc_opr.h"
+#include "s5p_mfc_opr_v5.h"
+#include "s5p_mfc_opr_v6.h"
+
+static struct s5p_mfc_hw_ops *s5p_mfc_ops;
+
+void s5p_mfc_init_hw_ops(struct s5p_mfc_dev *dev)
+{
+       if (IS_MFCV6_PLUS(dev)) {
+               s5p_mfc_ops = s5p_mfc_init_hw_ops_v6();
+               dev->warn_start = S5P_FIMV_ERR_WARNINGS_START_V6;
+       } else {
+               s5p_mfc_ops = s5p_mfc_init_hw_ops_v5();
+               dev->warn_start = S5P_FIMV_ERR_WARNINGS_START;
+       }
+       dev->mfc_ops = s5p_mfc_ops;
+}
+
+void s5p_mfc_init_regs(struct s5p_mfc_dev *dev)
+{
+       if (IS_MFCV6_PLUS(dev))
+               dev->mfc_regs = s5p_mfc_init_regs_v6_plus(dev);
+}
+
+int s5p_mfc_alloc_priv_buf(struct s5p_mfc_dev *dev, unsigned int mem_ctx,
+                          struct s5p_mfc_priv_buf *b)
+{
+       unsigned int bits = dev->mem_size >> PAGE_SHIFT;
+       unsigned int count = b->size >> PAGE_SHIFT;
+       unsigned int align = (SZ_64K >> PAGE_SHIFT) - 1;
+       unsigned int start, offset;
+
+       mfc_debug(3, "Allocating priv: %zu\n", b->size);
+
+       if (dev->mem_virt) {
+               start = bitmap_find_next_zero_area(dev->mem_bitmap, bits, 0, count, align);
+               if (start > bits)
+                       goto no_mem;
+
+               bitmap_set(dev->mem_bitmap, start, count);
+               offset = start << PAGE_SHIFT;
+               b->virt = dev->mem_virt + offset;
+               b->dma = dev->mem_base + offset;
+       } else {
+               struct device *mem_dev = dev->mem_dev[mem_ctx];
+               dma_addr_t base = dev->dma_base[mem_ctx];
+
+               b->ctx = mem_ctx;
+               b->virt = dma_alloc_coherent(mem_dev, b->size, &b->dma, GFP_KERNEL);
+               if (!b->virt)
+                       goto no_mem;
+               if (b->dma < base) {
+                       mfc_err("Invalid memory configuration - buffer (%pad) is below base memory address(%pad)\n",
+                               &b->dma, &base);
+                       dma_free_coherent(mem_dev, b->size, b->virt, b->dma);
+                       return -ENOMEM;
+               }
+       }
+
+       mfc_debug(3, "Allocated addr %p %pad\n", b->virt, &b->dma);
+       return 0;
+no_mem:
+       mfc_err("Allocating private buffer of size %zu failed\n", b->size);
+       return -ENOMEM;
+}
+
+int s5p_mfc_alloc_generic_buf(struct s5p_mfc_dev *dev, unsigned int mem_ctx,
+                          struct s5p_mfc_priv_buf *b)
+{
+       struct device *mem_dev = dev->mem_dev[mem_ctx];
+
+       mfc_debug(3, "Allocating generic buf: %zu\n", b->size);
+
+       b->ctx = mem_ctx;
+       b->virt = dma_alloc_coherent(mem_dev, b->size, &b->dma, GFP_KERNEL);
+       if (!b->virt)
+               goto no_mem;
+
+       mfc_debug(3, "Allocated addr %p %pad\n", b->virt, &b->dma);
+       return 0;
+no_mem:
+       mfc_err("Allocating generic buffer of size %zu failed\n", b->size);
+       return -ENOMEM;
+}
+
+void s5p_mfc_release_priv_buf(struct s5p_mfc_dev *dev,
+                             struct s5p_mfc_priv_buf *b)
+{
+       if (dev->mem_virt) {
+               unsigned int start = (b->dma - dev->mem_base) >> PAGE_SHIFT;
+               unsigned int count = b->size >> PAGE_SHIFT;
+
+               bitmap_clear(dev->mem_bitmap, start, count);
+       } else {
+               struct device *mem_dev = dev->mem_dev[b->ctx];
+
+               dma_free_coherent(mem_dev, b->size, b->virt, b->dma);
+       }
+       b->virt = NULL;
+       b->dma = 0;
+       b->size = 0;
+}
+
+void s5p_mfc_release_generic_buf(struct s5p_mfc_dev *dev,
+                             struct s5p_mfc_priv_buf *b)
+{
+       struct device *mem_dev = dev->mem_dev[b->ctx];
+       dma_free_coherent(mem_dev, b->size, b->virt, b->dma);
+       b->virt = NULL;
+       b->dma = 0;
+       b->size = 0;
+}
diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_opr.h b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_opr.h
new file mode 100644 (file)
index 0000000..b983127
--- /dev/null
@@ -0,0 +1,339 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * drivers/media/platform/samsung/s5p-mfc/s5p_mfc_opr.h
+ *
+ * Header file for Samsung MFC (Multi Function Codec - FIMV) driver
+ * Contains declarations of hw related functions.
+ *
+ * Kamil Debski, Copyright (C) 2012 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ */
+
+#ifndef S5P_MFC_OPR_H_
+#define S5P_MFC_OPR_H_
+
+#include "s5p_mfc_common.h"
+
+struct s5p_mfc_regs {
+
+       /* codec common registers */
+       void __iomem *risc_on;
+       void __iomem *risc2host_int;
+       void __iomem *host2risc_int;
+       void __iomem *risc_base_address;
+       void __iomem *mfc_reset;
+       void __iomem *host2risc_command;
+       void __iomem *risc2host_command;
+       void __iomem *mfc_bus_reset_ctrl;
+       void __iomem *firmware_version;
+       void __iomem *instance_id;
+       void __iomem *codec_type;
+       void __iomem *context_mem_addr;
+       void __iomem *context_mem_size;
+       void __iomem *pixel_format;
+       void __iomem *metadata_enable;
+       void __iomem *mfc_version;
+       void __iomem *dbg_info_enable;
+       void __iomem *dbg_buffer_addr;
+       void __iomem *dbg_buffer_size;
+       void __iomem *hed_control;
+       void __iomem *mfc_timeout_value;
+       void __iomem *hed_shared_mem_addr;
+       void __iomem *dis_shared_mem_addr;/* only v7 */
+       void __iomem *ret_instance_id;
+       void __iomem *error_code;
+       void __iomem *dbg_buffer_output_size;
+       void __iomem *metadata_status;
+       void __iomem *metadata_addr_mb_info;
+       void __iomem *metadata_size_mb_info;
+       void __iomem *dbg_info_stage_counter;
+
+       /* decoder registers */
+       void __iomem *d_crc_ctrl;
+       void __iomem *d_dec_options;
+       void __iomem *d_display_delay;
+       void __iomem *d_set_frame_width;
+       void __iomem *d_set_frame_height;
+       void __iomem *d_sei_enable;
+       void __iomem *d_min_num_dpb;
+       void __iomem *d_min_first_plane_dpb_size;
+       void __iomem *d_min_second_plane_dpb_size;
+       void __iomem *d_min_third_plane_dpb_size;/* only v8 */
+       void __iomem *d_min_num_mv;
+       void __iomem *d_mvc_num_views;
+       void __iomem *d_min_num_dis;/* only v7 */
+       void __iomem *d_min_first_dis_size;/* only v7 */
+       void __iomem *d_min_second_dis_size;/* only v7 */
+       void __iomem *d_min_third_dis_size;/* only v7 */
+       void __iomem *d_post_filter_luma_dpb0;/*  v7 and v8 */
+       void __iomem *d_post_filter_luma_dpb1;/* v7 and v8 */
+       void __iomem *d_post_filter_luma_dpb2;/* only v7 */
+       void __iomem *d_post_filter_chroma_dpb0;/* v7 and v8 */
+       void __iomem *d_post_filter_chroma_dpb1;/* v7 and v8 */
+       void __iomem *d_post_filter_chroma_dpb2;/* only v7 */
+       void __iomem *d_num_dpb;
+       void __iomem *d_num_mv;
+       void __iomem *d_init_buffer_options;
+       void __iomem *d_first_plane_dpb_stride_size;/* only v8 */
+       void __iomem *d_second_plane_dpb_stride_size;/* only v8 */
+       void __iomem *d_third_plane_dpb_stride_size;/* only v8 */
+       void __iomem *d_first_plane_dpb_size;
+       void __iomem *d_second_plane_dpb_size;
+       void __iomem *d_third_plane_dpb_size;/* only v8 */
+       void __iomem *d_mv_buffer_size;
+       void __iomem *d_first_plane_dpb;
+       void __iomem *d_second_plane_dpb;
+       void __iomem *d_third_plane_dpb;
+       void __iomem *d_mv_buffer;
+       void __iomem *d_scratch_buffer_addr;
+       void __iomem *d_scratch_buffer_size;
+       void __iomem *d_metadata_buffer_addr;
+       void __iomem *d_metadata_buffer_size;
+       void __iomem *d_nal_start_options;/* v7 and v8 */
+       void __iomem *d_cpb_buffer_addr;
+       void __iomem *d_cpb_buffer_size;
+       void __iomem *d_available_dpb_flag_upper;
+       void __iomem *d_available_dpb_flag_lower;
+       void __iomem *d_cpb_buffer_offset;
+       void __iomem *d_slice_if_enable;
+       void __iomem *d_picture_tag;
+       void __iomem *d_stream_data_size;
+       void __iomem *d_dynamic_dpb_flag_upper;/* v7 and v8 */
+       void __iomem *d_dynamic_dpb_flag_lower;/* v7 and v8 */
+       void __iomem *d_display_frame_width;
+       void __iomem *d_display_frame_height;
+       void __iomem *d_display_status;
+       void __iomem *d_display_first_plane_addr;
+       void __iomem *d_display_second_plane_addr;
+       void __iomem *d_display_third_plane_addr;/* only v8 */
+       void __iomem *d_display_frame_type;
+       void __iomem *d_display_crop_info1;
+       void __iomem *d_display_crop_info2;
+       void __iomem *d_display_picture_profile;
+       void __iomem *d_display_luma_crc;/* v7 and v8 */
+       void __iomem *d_display_chroma0_crc;/* v7 and v8 */
+       void __iomem *d_display_chroma1_crc;/* only v8 */
+       void __iomem *d_display_luma_crc_top;/* only v6 */
+       void __iomem *d_display_chroma_crc_top;/* only v6 */
+       void __iomem *d_display_luma_crc_bot;/* only v6 */
+       void __iomem *d_display_chroma_crc_bot;/* only v6 */
+       void __iomem *d_display_aspect_ratio;
+       void __iomem *d_display_extended_ar;
+       void __iomem *d_decoded_frame_width;
+       void __iomem *d_decoded_frame_height;
+       void __iomem *d_decoded_status;
+       void __iomem *d_decoded_first_plane_addr;
+       void __iomem *d_decoded_second_plane_addr;
+       void __iomem *d_decoded_third_plane_addr;/* only v8 */
+       void __iomem *d_decoded_frame_type;
+       void __iomem *d_decoded_crop_info1;
+       void __iomem *d_decoded_crop_info2;
+       void __iomem *d_decoded_picture_profile;
+       void __iomem *d_decoded_nal_size;
+       void __iomem *d_decoded_luma_crc;
+       void __iomem *d_decoded_chroma0_crc;
+       void __iomem *d_decoded_chroma1_crc;/* only v8 */
+       void __iomem *d_ret_picture_tag_top;
+       void __iomem *d_ret_picture_tag_bot;
+       void __iomem *d_ret_picture_time_top;
+       void __iomem *d_ret_picture_time_bot;
+       void __iomem *d_chroma_format;
+       void __iomem *d_vc1_info;/* v7 and v8 */
+       void __iomem *d_mpeg4_info;
+       void __iomem *d_h264_info;
+       void __iomem *d_metadata_addr_concealed_mb;
+       void __iomem *d_metadata_size_concealed_mb;
+       void __iomem *d_metadata_addr_vc1_param;
+       void __iomem *d_metadata_size_vc1_param;
+       void __iomem *d_metadata_addr_sei_nal;
+       void __iomem *d_metadata_size_sei_nal;
+       void __iomem *d_metadata_addr_vui;
+       void __iomem *d_metadata_size_vui;
+       void __iomem *d_metadata_addr_mvcvui;/* v7 and v8 */
+       void __iomem *d_metadata_size_mvcvui;/* v7 and v8 */
+       void __iomem *d_mvc_view_id;
+       void __iomem *d_frame_pack_sei_avail;
+       void __iomem *d_frame_pack_arrgment_id;
+       void __iomem *d_frame_pack_sei_info;
+       void __iomem *d_frame_pack_grid_pos;
+       void __iomem *d_display_recovery_sei_info;/* v7 and v8 */
+       void __iomem *d_decoded_recovery_sei_info;/* v7 and v8 */
+       void __iomem *d_display_first_addr;/* only v7 */
+       void __iomem *d_display_second_addr;/* only v7 */
+       void __iomem *d_display_third_addr;/* only v7 */
+       void __iomem *d_decoded_first_addr;/* only v7 */
+       void __iomem *d_decoded_second_addr;/* only v7 */
+       void __iomem *d_decoded_third_addr;/* only v7 */
+       void __iomem *d_used_dpb_flag_upper;/* v7 and v8 */
+       void __iomem *d_used_dpb_flag_lower;/* v7 and v8 */
+       void __iomem *d_min_scratch_buffer_size; /* v10 */
+       void __iomem *d_static_buffer_addr; /* v10 */
+       void __iomem *d_static_buffer_size; /* v10 */
+
+       /* encoder registers */
+       void __iomem *e_frame_width;
+       void __iomem *e_frame_height;
+       void __iomem *e_cropped_frame_width;
+       void __iomem *e_cropped_frame_height;
+       void __iomem *e_frame_crop_offset;
+       void __iomem *e_enc_options;
+       void __iomem *e_picture_profile;
+       void __iomem *e_vbv_buffer_size;
+       void __iomem *e_vbv_init_delay;
+       void __iomem *e_fixed_picture_qp;
+       void __iomem *e_rc_config;
+       void __iomem *e_rc_qp_bound;
+       void __iomem *e_rc_qp_bound_pb;/* v7 and v8 */
+       void __iomem *e_rc_mode;
+       void __iomem *e_mb_rc_config;
+       void __iomem *e_padding_ctrl;
+       void __iomem *e_air_threshold;
+       void __iomem *e_mv_hor_range;
+       void __iomem *e_mv_ver_range;
+       void __iomem *e_num_dpb;
+       void __iomem *e_luma_dpb;
+       void __iomem *e_chroma_dpb;
+       void __iomem *e_me_buffer;
+       void __iomem *e_scratch_buffer_addr;
+       void __iomem *e_scratch_buffer_size;
+       void __iomem *e_tmv_buffer0;
+       void __iomem *e_tmv_buffer1;
+       void __iomem *e_ir_buffer_addr;/* v7 and v8 */
+       void __iomem *e_source_first_plane_addr;
+       void __iomem *e_source_second_plane_addr;
+       void __iomem *e_source_third_plane_addr;/* v7 and v8 */
+       void __iomem *e_source_first_plane_stride;/* v7 and v8 */
+       void __iomem *e_source_second_plane_stride;/* v7 and v8 */
+       void __iomem *e_source_third_plane_stride;/* v7 and v8 */
+       void __iomem *e_stream_buffer_addr;
+       void __iomem *e_stream_buffer_size;
+       void __iomem *e_roi_buffer_addr;
+       void __iomem *e_param_change;
+       void __iomem *e_ir_size;
+       void __iomem *e_gop_config;
+       void __iomem *e_mslice_mode;
+       void __iomem *e_mslice_size_mb;
+       void __iomem *e_mslice_size_bits;
+       void __iomem *e_frame_insertion;
+       void __iomem *e_rc_frame_rate;
+       void __iomem *e_rc_bit_rate;
+       void __iomem *e_rc_roi_ctrl;
+       void __iomem *e_picture_tag;
+       void __iomem *e_bit_count_enable;
+       void __iomem *e_max_bit_count;
+       void __iomem *e_min_bit_count;
+       void __iomem *e_metadata_buffer_addr;
+       void __iomem *e_metadata_buffer_size;
+       void __iomem *e_encoded_source_first_plane_addr;
+       void __iomem *e_encoded_source_second_plane_addr;
+       void __iomem *e_encoded_source_third_plane_addr;/* v7 and v8 */
+       void __iomem *e_stream_size;
+       void __iomem *e_slice_type;
+       void __iomem *e_picture_count;
+       void __iomem *e_ret_picture_tag;
+       void __iomem *e_stream_buffer_write_pointer; /*  only v6 */
+       void __iomem *e_recon_luma_dpb_addr;
+       void __iomem *e_recon_chroma_dpb_addr;
+       void __iomem *e_metadata_addr_enc_slice;
+       void __iomem *e_metadata_size_enc_slice;
+       void __iomem *e_mpeg4_options;
+       void __iomem *e_mpeg4_hec_period;
+       void __iomem *e_aspect_ratio;
+       void __iomem *e_extended_sar;
+       void __iomem *e_h264_options;
+       void __iomem *e_h264_options_2;/* v7 and v8 */
+       void __iomem *e_h264_lf_alpha_offset;
+       void __iomem *e_h264_lf_beta_offset;
+       void __iomem *e_h264_i_period;
+       void __iomem *e_h264_fmo_slice_grp_map_type;
+       void __iomem *e_h264_fmo_num_slice_grp_minus1;
+       void __iomem *e_h264_fmo_slice_grp_change_dir;
+       void __iomem *e_h264_fmo_slice_grp_change_rate_minus1;
+       void __iomem *e_h264_fmo_run_length_minus1_0;
+       void __iomem *e_h264_aso_slice_order_0;
+       void __iomem *e_h264_chroma_qp_offset;
+       void __iomem *e_h264_num_t_layer;
+       void __iomem *e_h264_hierarchical_qp_layer0;
+       void __iomem *e_h264_frame_packing_sei_info;
+       void __iomem *e_h264_nal_control;/* v7 and v8 */
+       void __iomem *e_mvc_frame_qp_view1;
+       void __iomem *e_mvc_rc_bit_rate_view1;
+       void __iomem *e_mvc_rc_qbound_view1;
+       void __iomem *e_mvc_rc_mode_view1;
+       void __iomem *e_mvc_inter_view_prediction_on;
+       void __iomem *e_vp8_options;/* v7 and v8 */
+       void __iomem *e_vp8_filter_options;/* v7 and v8 */
+       void __iomem *e_vp8_golden_frame_option;/* v7 and v8 */
+       void __iomem *e_vp8_num_t_layer;/* v7 and v8 */
+       void __iomem *e_vp8_hierarchical_qp_layer0;/* v7 and v8 */
+       void __iomem *e_vp8_hierarchical_qp_layer1;/* v7 and v8 */
+       void __iomem *e_vp8_hierarchical_qp_layer2;/* v7 and v8 */
+       void __iomem *e_min_scratch_buffer_size; /* v10 */
+       void __iomem *e_num_t_layer; /* v10 */
+       void __iomem *e_hier_qp_layer0; /* v10 */
+       void __iomem *e_hier_bit_rate_layer0; /* v10 */
+       void __iomem *e_hevc_options; /* v10 */
+       void __iomem *e_hevc_refresh_period; /* v10 */
+       void __iomem *e_hevc_lf_beta_offset_div2; /* v10 */
+       void __iomem *e_hevc_lf_tc_offset_div2; /* v10 */
+       void __iomem *e_hevc_nal_control; /* v10 */
+};
+
+struct s5p_mfc_hw_ops {
+       int (*alloc_dec_temp_buffers)(struct s5p_mfc_ctx *ctx);
+       void (*release_dec_desc_buffer)(struct s5p_mfc_ctx *ctx);
+       int (*alloc_codec_buffers)(struct s5p_mfc_ctx *ctx);
+       void (*release_codec_buffers)(struct s5p_mfc_ctx *ctx);
+       int (*alloc_instance_buffer)(struct s5p_mfc_ctx *ctx);
+       void (*release_instance_buffer)(struct s5p_mfc_ctx *ctx);
+       int (*alloc_dev_context_buffer)(struct s5p_mfc_dev *dev);
+       void (*release_dev_context_buffer)(struct s5p_mfc_dev *dev);
+       void (*dec_calc_dpb_size)(struct s5p_mfc_ctx *ctx);
+       void (*enc_calc_src_size)(struct s5p_mfc_ctx *ctx);
+       int (*set_enc_stream_buffer)(struct s5p_mfc_ctx *ctx,
+                       unsigned long addr, unsigned int size);
+       void (*set_enc_frame_buffer)(struct s5p_mfc_ctx *ctx,
+                       unsigned long y_addr, unsigned long c_addr);
+       void (*get_enc_frame_buffer)(struct s5p_mfc_ctx *ctx,
+                       unsigned long *y_addr, unsigned long *c_addr);
+       void (*try_run)(struct s5p_mfc_dev *dev);
+       void (*clear_int_flags)(struct s5p_mfc_dev *dev);
+       int (*get_dspl_y_adr)(struct s5p_mfc_dev *dev);
+       int (*get_dec_y_adr)(struct s5p_mfc_dev *dev);
+       int (*get_dspl_status)(struct s5p_mfc_dev *dev);
+       int (*get_dec_status)(struct s5p_mfc_dev *dev);
+       int (*get_dec_frame_type)(struct s5p_mfc_dev *dev);
+       int (*get_disp_frame_type)(struct s5p_mfc_ctx *ctx);
+       int (*get_consumed_stream)(struct s5p_mfc_dev *dev);
+       int (*get_int_reason)(struct s5p_mfc_dev *dev);
+       int (*get_int_err)(struct s5p_mfc_dev *dev);
+       int (*err_dec)(unsigned int err);
+       int (*get_img_width)(struct s5p_mfc_dev *dev);
+       int (*get_img_height)(struct s5p_mfc_dev *dev);
+       int (*get_dpb_count)(struct s5p_mfc_dev *dev);
+       int (*get_mv_count)(struct s5p_mfc_dev *dev);
+       int (*get_inst_no)(struct s5p_mfc_dev *dev);
+       int (*get_enc_strm_size)(struct s5p_mfc_dev *dev);
+       int (*get_enc_slice_type)(struct s5p_mfc_dev *dev);
+       int (*get_enc_dpb_count)(struct s5p_mfc_dev *dev);
+       unsigned int (*get_pic_type_top)(struct s5p_mfc_ctx *ctx);
+       unsigned int (*get_pic_type_bot)(struct s5p_mfc_ctx *ctx);
+       unsigned int (*get_crop_info_h)(struct s5p_mfc_ctx *ctx);
+       unsigned int (*get_crop_info_v)(struct s5p_mfc_ctx *ctx);
+       int (*get_min_scratch_buf_size)(struct s5p_mfc_dev *dev);
+       int (*get_e_min_scratch_buf_size)(struct s5p_mfc_dev *dev);
+};
+
+void s5p_mfc_init_hw_ops(struct s5p_mfc_dev *dev);
+void s5p_mfc_init_regs(struct s5p_mfc_dev *dev);
+int s5p_mfc_alloc_priv_buf(struct s5p_mfc_dev *dev, unsigned int mem_ctx,
+                          struct s5p_mfc_priv_buf *b);
+void s5p_mfc_release_priv_buf(struct s5p_mfc_dev *dev,
+                             struct s5p_mfc_priv_buf *b);
+int s5p_mfc_alloc_generic_buf(struct s5p_mfc_dev *dev, unsigned int mem_ctx,
+                          struct s5p_mfc_priv_buf *b);
+void s5p_mfc_release_generic_buf(struct s5p_mfc_dev *dev,
+                             struct s5p_mfc_priv_buf *b);
+
+
+#endif /* S5P_MFC_OPR_H_ */
diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_opr_v5.c b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_opr_v5.c
new file mode 100644 (file)
index 0000000..28a06dc
--- /dev/null
@@ -0,0 +1,1637 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * drivers/media/platform/samsung/mfc5/s5p_mfc_opr_v5.c
+ *
+ * Samsung MFC (Multi Function Codec - FIMV) driver
+ * This file contains hw related functions.
+ *
+ * Kamil Debski, Copyright (c) 2011 Samsung Electronics
+ * http://www.samsung.com/
+ */
+
+#include "s5p_mfc_common.h"
+#include "s5p_mfc_cmd.h"
+#include "s5p_mfc_ctrl.h"
+#include "s5p_mfc_debug.h"
+#include "s5p_mfc_intr.h"
+#include "s5p_mfc_pm.h"
+#include "s5p_mfc_opr.h"
+#include "s5p_mfc_opr_v5.h"
+#include <asm/cacheflush.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/firmware.h>
+#include <linux/io.h>
+#include <linux/jiffies.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+
+#define OFFSETA(x)             (((x) - dev->dma_base[BANK_L_CTX]) >> MFC_OFFSET_SHIFT)
+#define OFFSETB(x)             (((x) - dev->dma_base[BANK_R_CTX]) >> MFC_OFFSET_SHIFT)
+
+/* Allocate temporary buffers for decoding */
+static int s5p_mfc_alloc_dec_temp_buffers_v5(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_buf_size_v5 *buf_size = dev->variant->buf_size->priv;
+       int ret;
+
+       ctx->dsc.size = buf_size->dsc;
+       ret =  s5p_mfc_alloc_priv_buf(dev, BANK_L_CTX, &ctx->dsc);
+       if (ret) {
+               mfc_err("Failed to allocate temporary buffer\n");
+               return ret;
+       }
+
+       BUG_ON(ctx->dsc.dma & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
+       memset(ctx->dsc.virt, 0, ctx->dsc.size);
+       wmb();
+       return 0;
+}
+
+
+/* Release temporary buffers for decoding */
+static void s5p_mfc_release_dec_desc_buffer_v5(struct s5p_mfc_ctx *ctx)
+{
+       s5p_mfc_release_priv_buf(ctx->dev, &ctx->dsc);
+}
+
+/* Allocate codec buffers */
+static int s5p_mfc_alloc_codec_buffers_v5(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned int enc_ref_y_size = 0;
+       unsigned int enc_ref_c_size = 0;
+       unsigned int guard_width, guard_height;
+       int ret;
+
+       if (ctx->type == MFCINST_DECODER) {
+               mfc_debug(2, "Luma size:%d Chroma size:%d MV size:%d\n",
+                         ctx->luma_size, ctx->chroma_size, ctx->mv_size);
+               mfc_debug(2, "Totals bufs: %d\n", ctx->total_dpb_count);
+       } else if (ctx->type == MFCINST_ENCODER) {
+               enc_ref_y_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
+                       * ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);
+               enc_ref_y_size = ALIGN(enc_ref_y_size, S5P_FIMV_NV12MT_SALIGN);
+
+               if (ctx->codec_mode == S5P_MFC_CODEC_H264_ENC) {
+                       enc_ref_c_size = ALIGN(ctx->img_width,
+                                               S5P_FIMV_NV12MT_HALIGN)
+                                               * ALIGN(ctx->img_height >> 1,
+                                               S5P_FIMV_NV12MT_VALIGN);
+                       enc_ref_c_size = ALIGN(enc_ref_c_size,
+                                                       S5P_FIMV_NV12MT_SALIGN);
+               } else {
+                       guard_width = ALIGN(ctx->img_width + 16,
+                                                       S5P_FIMV_NV12MT_HALIGN);
+                       guard_height = ALIGN((ctx->img_height >> 1) + 4,
+                                                       S5P_FIMV_NV12MT_VALIGN);
+                       enc_ref_c_size = ALIGN(guard_width * guard_height,
+                                              S5P_FIMV_NV12MT_SALIGN);
+               }
+               mfc_debug(2, "recon luma size: %d chroma size: %d\n",
+                         enc_ref_y_size, enc_ref_c_size);
+       } else {
+               return -EINVAL;
+       }
+       /* Codecs have different memory requirements */
+       switch (ctx->codec_mode) {
+       case S5P_MFC_CODEC_H264_DEC:
+               ctx->bank1.size =
+                   ALIGN(S5P_FIMV_DEC_NB_IP_SIZE +
+                                       S5P_FIMV_DEC_VERT_NB_MV_SIZE,
+                                       S5P_FIMV_DEC_BUF_ALIGN);
+               ctx->bank2.size = ctx->total_dpb_count * ctx->mv_size;
+               break;
+       case S5P_MFC_CODEC_MPEG4_DEC:
+               ctx->bank1.size =
+                   ALIGN(S5P_FIMV_DEC_NB_DCAC_SIZE +
+                                    S5P_FIMV_DEC_UPNB_MV_SIZE +
+                                    S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE +
+                                    S5P_FIMV_DEC_STX_PARSER_SIZE +
+                                    S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE,
+                                    S5P_FIMV_DEC_BUF_ALIGN);
+               ctx->bank2.size = 0;
+               break;
+       case S5P_MFC_CODEC_VC1RCV_DEC:
+       case S5P_MFC_CODEC_VC1_DEC:
+               ctx->bank1.size =
+                   ALIGN(S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE +
+                            S5P_FIMV_DEC_UPNB_MV_SIZE +
+                            S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE +
+                            S5P_FIMV_DEC_NB_DCAC_SIZE +
+                            3 * S5P_FIMV_DEC_VC1_BITPLANE_SIZE,
+                            S5P_FIMV_DEC_BUF_ALIGN);
+               ctx->bank2.size = 0;
+               break;
+       case S5P_MFC_CODEC_MPEG2_DEC:
+               ctx->bank1.size = 0;
+               ctx->bank2.size = 0;
+               break;
+       case S5P_MFC_CODEC_H263_DEC:
+               ctx->bank1.size =
+                   ALIGN(S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE +
+                            S5P_FIMV_DEC_UPNB_MV_SIZE +
+                            S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE +
+                            S5P_FIMV_DEC_NB_DCAC_SIZE,
+                            S5P_FIMV_DEC_BUF_ALIGN);
+               ctx->bank2.size = 0;
+               break;
+       case S5P_MFC_CODEC_H264_ENC:
+               ctx->bank1.size = (enc_ref_y_size * 2) +
+                                  S5P_FIMV_ENC_UPMV_SIZE +
+                                  S5P_FIMV_ENC_COLFLG_SIZE +
+                                  S5P_FIMV_ENC_INTRAMD_SIZE +
+                                  S5P_FIMV_ENC_NBORINFO_SIZE;
+               ctx->bank2.size = (enc_ref_y_size * 2) +
+                                  (enc_ref_c_size * 4) +
+                                  S5P_FIMV_ENC_INTRAPRED_SIZE;
+               break;
+       case S5P_MFC_CODEC_MPEG4_ENC:
+               ctx->bank1.size = (enc_ref_y_size * 2) +
+                                  S5P_FIMV_ENC_UPMV_SIZE +
+                                  S5P_FIMV_ENC_COLFLG_SIZE +
+                                  S5P_FIMV_ENC_ACDCCOEF_SIZE;
+               ctx->bank2.size = (enc_ref_y_size * 2) +
+                                  (enc_ref_c_size * 4);
+               break;
+       case S5P_MFC_CODEC_H263_ENC:
+               ctx->bank1.size = (enc_ref_y_size * 2) +
+                                  S5P_FIMV_ENC_UPMV_SIZE +
+                                  S5P_FIMV_ENC_ACDCCOEF_SIZE;
+               ctx->bank2.size = (enc_ref_y_size * 2) +
+                                  (enc_ref_c_size * 4);
+               break;
+       default:
+               break;
+       }
+       /* Allocate only if memory from bank 1 is necessary */
+       if (ctx->bank1.size > 0) {
+
+               ret = s5p_mfc_alloc_priv_buf(dev, BANK_L_CTX, &ctx->bank1);
+               if (ret) {
+                       mfc_err("Failed to allocate Bank1 temporary buffer\n");
+                       return ret;
+               }
+               BUG_ON(ctx->bank1.dma & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
+       }
+       /* Allocate only if memory from bank 2 is necessary */
+       if (ctx->bank2.size > 0) {
+               ret = s5p_mfc_alloc_priv_buf(dev, BANK_R_CTX, &ctx->bank2);
+               if (ret) {
+                       mfc_err("Failed to allocate Bank2 temporary buffer\n");
+                       s5p_mfc_release_priv_buf(ctx->dev, &ctx->bank1);
+                       return ret;
+               }
+               BUG_ON(ctx->bank2.dma & ((1 << MFC_BANK2_ALIGN_ORDER) - 1));
+       }
+       return 0;
+}
+
+/* Release buffers allocated for codec */
+static void s5p_mfc_release_codec_buffers_v5(struct s5p_mfc_ctx *ctx)
+{
+       s5p_mfc_release_priv_buf(ctx->dev, &ctx->bank1);
+       s5p_mfc_release_priv_buf(ctx->dev, &ctx->bank2);
+}
+
+/* Allocate memory for instance data buffer */
+static int s5p_mfc_alloc_instance_buffer_v5(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_buf_size_v5 *buf_size = dev->variant->buf_size->priv;
+       int ret;
+
+       if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC ||
+               ctx->codec_mode == S5P_MFC_CODEC_H264_ENC)
+               ctx->ctx.size = buf_size->h264_ctx;
+       else
+               ctx->ctx.size = buf_size->non_h264_ctx;
+
+       ret = s5p_mfc_alloc_priv_buf(dev, BANK_L_CTX, &ctx->ctx);
+       if (ret) {
+               mfc_err("Failed to allocate instance buffer\n");
+               return ret;
+       }
+       ctx->ctx.ofs = OFFSETA(ctx->ctx.dma);
+
+       /* Zero content of the allocated memory */
+       memset(ctx->ctx.virt, 0, ctx->ctx.size);
+       wmb();
+
+       /* Initialize shared memory */
+       ctx->shm.size = buf_size->shm;
+       ret = s5p_mfc_alloc_priv_buf(dev, BANK_L_CTX, &ctx->shm);
+       if (ret) {
+               mfc_err("Failed to allocate shared memory buffer\n");
+               s5p_mfc_release_priv_buf(dev, &ctx->ctx);
+               return ret;
+       }
+
+       /* shared memory offset only keeps the offset from base (port a) */
+       ctx->shm.ofs = ctx->shm.dma - dev->dma_base[BANK_L_CTX];
+       BUG_ON(ctx->shm.ofs & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
+
+       memset(ctx->shm.virt, 0, buf_size->shm);
+       wmb();
+       return 0;
+}
+
+/* Release instance buffer */
+static void s5p_mfc_release_instance_buffer_v5(struct s5p_mfc_ctx *ctx)
+{
+       s5p_mfc_release_priv_buf(ctx->dev, &ctx->ctx);
+       s5p_mfc_release_priv_buf(ctx->dev, &ctx->shm);
+}
+
+static int s5p_mfc_alloc_dev_context_buffer_v5(struct s5p_mfc_dev *dev)
+{
+       /* NOP */
+
+       return 0;
+}
+
+static void s5p_mfc_release_dev_context_buffer_v5(struct s5p_mfc_dev *dev)
+{
+       /* NOP */
+}
+
+static void s5p_mfc_write_info_v5(struct s5p_mfc_ctx *ctx, unsigned int data,
+                       unsigned int ofs)
+{
+       *(u32 *)(ctx->shm.virt + ofs) = data;
+       wmb();
+}
+
+static unsigned int s5p_mfc_read_info_v5(struct s5p_mfc_ctx *ctx,
+                               unsigned long ofs)
+{
+       rmb();
+       return *(u32 *)(ctx->shm.virt + ofs);
+}
+
+static void s5p_mfc_dec_calc_dpb_size_v5(struct s5p_mfc_ctx *ctx)
+{
+       unsigned int guard_width, guard_height;
+
+       ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN);
+       ctx->buf_height = ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);
+       mfc_debug(2,
+               "SEQ Done: Movie dimensions %dx%d, buffer dimensions: %dx%d\n",
+               ctx->img_width, ctx->img_height, ctx->buf_width,
+               ctx->buf_height);
+
+       if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC) {
+               ctx->luma_size = ALIGN(ctx->buf_width * ctx->buf_height,
+                               S5P_FIMV_DEC_BUF_ALIGN);
+               ctx->chroma_size = ALIGN(ctx->buf_width *
+                               ALIGN((ctx->img_height >> 1),
+                                       S5P_FIMV_NV12MT_VALIGN),
+                               S5P_FIMV_DEC_BUF_ALIGN);
+               ctx->mv_size = ALIGN(ctx->buf_width *
+                               ALIGN((ctx->buf_height >> 2),
+                                       S5P_FIMV_NV12MT_VALIGN),
+                               S5P_FIMV_DEC_BUF_ALIGN);
+       } else {
+               guard_width =
+                       ALIGN(ctx->img_width + 24, S5P_FIMV_NV12MT_HALIGN);
+               guard_height =
+                       ALIGN(ctx->img_height + 16, S5P_FIMV_NV12MT_VALIGN);
+               ctx->luma_size = ALIGN(guard_width * guard_height,
+                               S5P_FIMV_DEC_BUF_ALIGN);
+
+               guard_width =
+                       ALIGN(ctx->img_width + 16, S5P_FIMV_NV12MT_HALIGN);
+               guard_height =
+                       ALIGN((ctx->img_height >> 1) + 4,
+                                       S5P_FIMV_NV12MT_VALIGN);
+               ctx->chroma_size = ALIGN(guard_width * guard_height,
+                               S5P_FIMV_DEC_BUF_ALIGN);
+
+               ctx->mv_size = 0;
+       }
+}
+
+static void s5p_mfc_enc_calc_src_size_v5(struct s5p_mfc_ctx *ctx)
+{
+       if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M) {
+               ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN);
+
+               ctx->luma_size = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN)
+                       * ALIGN(ctx->img_height, S5P_FIMV_NV12M_LVALIGN);
+               ctx->chroma_size = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN)
+                       * ALIGN((ctx->img_height >> 1), S5P_FIMV_NV12M_CVALIGN);
+
+               ctx->luma_size = ALIGN(ctx->luma_size, S5P_FIMV_NV12M_SALIGN);
+               ctx->chroma_size =
+                       ALIGN(ctx->chroma_size, S5P_FIMV_NV12M_SALIGN);
+       } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT) {
+               ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN);
+
+               ctx->luma_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
+                       * ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);
+               ctx->chroma_size =
+                       ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
+                       * ALIGN((ctx->img_height >> 1), S5P_FIMV_NV12MT_VALIGN);
+
+               ctx->luma_size = ALIGN(ctx->luma_size, S5P_FIMV_NV12MT_SALIGN);
+               ctx->chroma_size =
+                       ALIGN(ctx->chroma_size, S5P_FIMV_NV12MT_SALIGN);
+       }
+}
+
+/* Set registers for decoding temporary buffers */
+static void s5p_mfc_set_dec_desc_buffer(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_buf_size_v5 *buf_size = dev->variant->buf_size->priv;
+
+       mfc_write(dev, OFFSETA(ctx->dsc.dma), S5P_FIMV_SI_CH0_DESC_ADR);
+       mfc_write(dev, buf_size->dsc, S5P_FIMV_SI_CH0_DESC_SIZE);
+}
+
+/* Set registers for shared buffer */
+static void s5p_mfc_set_shared_buffer(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       mfc_write(dev, ctx->shm.ofs, S5P_FIMV_SI_CH0_HOST_WR_ADR);
+}
+
+/* Set registers for decoding stream buffer */
+static int s5p_mfc_set_dec_stream_buffer_v5(struct s5p_mfc_ctx *ctx,
+               int buf_addr, unsigned int start_num_byte,
+               unsigned int buf_size)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       mfc_write(dev, OFFSETA(buf_addr), S5P_FIMV_SI_CH0_SB_ST_ADR);
+       mfc_write(dev, ctx->dec_src_buf_size, S5P_FIMV_SI_CH0_CPB_SIZE);
+       mfc_write(dev, buf_size, S5P_FIMV_SI_CH0_SB_FRM_SIZE);
+       s5p_mfc_write_info_v5(ctx, start_num_byte, START_BYTE_NUM);
+       return 0;
+}
+
+/* Set decoding frame buffer */
+static int s5p_mfc_set_dec_frame_buffer_v5(struct s5p_mfc_ctx *ctx)
+{
+       unsigned int frame_size_lu, i;
+       unsigned int frame_size_ch, frame_size_mv;
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned int dpb;
+       size_t buf_addr1, buf_addr2;
+       int buf_size1, buf_size2;
+
+       buf_addr1 = ctx->bank1.dma;
+       buf_size1 = ctx->bank1.size;
+       buf_addr2 = ctx->bank2.dma;
+       buf_size2 = ctx->bank2.size;
+       dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) &
+                                               ~S5P_FIMV_DPB_COUNT_MASK;
+       mfc_write(dev, ctx->total_dpb_count | dpb,
+                                               S5P_FIMV_SI_CH0_DPB_CONF_CTRL);
+       s5p_mfc_set_shared_buffer(ctx);
+       switch (ctx->codec_mode) {
+       case S5P_MFC_CODEC_H264_DEC:
+               mfc_write(dev, OFFSETA(buf_addr1),
+                                               S5P_FIMV_H264_VERT_NB_MV_ADR);
+               buf_addr1 += S5P_FIMV_DEC_VERT_NB_MV_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_VERT_NB_MV_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H264_NB_IP_ADR);
+               buf_addr1 += S5P_FIMV_DEC_NB_IP_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_NB_IP_SIZE;
+               break;
+       case S5P_MFC_CODEC_MPEG4_DEC:
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_NB_DCAC_ADR);
+               buf_addr1 += S5P_FIMV_DEC_NB_DCAC_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_NB_DCAC_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_UP_NB_MV_ADR);
+               buf_addr1 += S5P_FIMV_DEC_UPNB_MV_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_UPNB_MV_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_SA_MV_ADR);
+               buf_addr1 += S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_SP_ADR);
+               buf_addr1 += S5P_FIMV_DEC_STX_PARSER_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_STX_PARSER_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_OT_LINE_ADR);
+               buf_addr1 += S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
+               break;
+       case S5P_MFC_CODEC_H263_DEC:
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_OT_LINE_ADR);
+               buf_addr1 += S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_UP_NB_MV_ADR);
+               buf_addr1 += S5P_FIMV_DEC_UPNB_MV_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_UPNB_MV_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_SA_MV_ADR);
+               buf_addr1 += S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_NB_DCAC_ADR);
+               buf_addr1 += S5P_FIMV_DEC_NB_DCAC_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_NB_DCAC_SIZE;
+               break;
+       case S5P_MFC_CODEC_VC1_DEC:
+       case S5P_MFC_CODEC_VC1RCV_DEC:
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_NB_DCAC_ADR);
+               buf_addr1 += S5P_FIMV_DEC_NB_DCAC_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_NB_DCAC_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_OT_LINE_ADR);
+               buf_addr1 += S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_UP_NB_MV_ADR);
+               buf_addr1 += S5P_FIMV_DEC_UPNB_MV_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_UPNB_MV_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_SA_MV_ADR);
+               buf_addr1 += S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_BITPLANE3_ADR);
+               buf_addr1 += S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_BITPLANE2_ADR);
+               buf_addr1 += S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_VC1_BITPLANE1_ADR);
+               buf_addr1 += S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
+               buf_size1 -= S5P_FIMV_DEC_VC1_BITPLANE_SIZE;
+               break;
+       case S5P_MFC_CODEC_MPEG2_DEC:
+               break;
+       default:
+               mfc_err("Unknown codec for decoding (%x)\n",
+                       ctx->codec_mode);
+               return -EINVAL;
+       }
+       frame_size_lu = ctx->luma_size;
+       frame_size_ch = ctx->chroma_size;
+       frame_size_mv = ctx->mv_size;
+       mfc_debug(2, "Frm size: %d ch: %d mv: %d\n", frame_size_lu, frame_size_ch,
+                                                               frame_size_mv);
+       for (i = 0; i < ctx->total_dpb_count; i++) {
+               /* Bank2 */
+               mfc_debug(2, "Luma %d: %zx\n", i,
+                                       ctx->dst_bufs[i].cookie.raw.luma);
+               mfc_write(dev, OFFSETB(ctx->dst_bufs[i].cookie.raw.luma),
+                                               S5P_FIMV_DEC_LUMA_ADR + i * 4);
+               mfc_debug(2, "\tChroma %d: %zx\n", i,
+                                       ctx->dst_bufs[i].cookie.raw.chroma);
+               mfc_write(dev, OFFSETA(ctx->dst_bufs[i].cookie.raw.chroma),
+                                              S5P_FIMV_DEC_CHROMA_ADR + i * 4);
+               if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC) {
+                       mfc_debug(2, "\tBuf2: %zx, size: %d\n",
+                                                       buf_addr2, buf_size2);
+                       mfc_write(dev, OFFSETB(buf_addr2),
+                                               S5P_FIMV_H264_MV_ADR + i * 4);
+                       buf_addr2 += frame_size_mv;
+                       buf_size2 -= frame_size_mv;
+               }
+       }
+       mfc_debug(2, "Buf1: %zu, buf_size1: %d\n", buf_addr1, buf_size1);
+       mfc_debug(2, "Buf 1/2 size after: %d/%d (frames %d)\n",
+                       buf_size1,  buf_size2, ctx->total_dpb_count);
+       if (buf_size1 < 0 || buf_size2 < 0) {
+               mfc_debug(2, "Not enough memory has been allocated\n");
+               return -ENOMEM;
+       }
+       s5p_mfc_write_info_v5(ctx, frame_size_lu, ALLOC_LUMA_DPB_SIZE);
+       s5p_mfc_write_info_v5(ctx, frame_size_ch, ALLOC_CHROMA_DPB_SIZE);
+       if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC)
+               s5p_mfc_write_info_v5(ctx, frame_size_mv, ALLOC_MV_SIZE);
+       mfc_write(dev, ((S5P_FIMV_CH_INIT_BUFS & S5P_FIMV_CH_MASK)
+                                       << S5P_FIMV_CH_SHIFT) | (ctx->inst_no),
+                                               S5P_FIMV_SI_CH0_INST_ID);
+       return 0;
+}
+
+/* Set registers for encoding stream buffer */
+static int s5p_mfc_set_enc_stream_buffer_v5(struct s5p_mfc_ctx *ctx,
+               unsigned long addr, unsigned int size)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       mfc_write(dev, OFFSETA(addr), S5P_FIMV_ENC_SI_CH0_SB_ADR);
+       mfc_write(dev, size, S5P_FIMV_ENC_SI_CH0_SB_SIZE);
+       return 0;
+}
+
+static void s5p_mfc_set_enc_frame_buffer_v5(struct s5p_mfc_ctx *ctx,
+               unsigned long y_addr, unsigned long c_addr)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       mfc_write(dev, OFFSETB(y_addr), S5P_FIMV_ENC_SI_CH0_CUR_Y_ADR);
+       mfc_write(dev, OFFSETB(c_addr), S5P_FIMV_ENC_SI_CH0_CUR_C_ADR);
+}
+
+static void s5p_mfc_get_enc_frame_buffer_v5(struct s5p_mfc_ctx *ctx,
+               unsigned long *y_addr, unsigned long *c_addr)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       *y_addr = dev->dma_base[BANK_R_CTX] +
+                 (mfc_read(dev, S5P_FIMV_ENCODED_Y_ADDR) << MFC_OFFSET_SHIFT);
+       *c_addr = dev->dma_base[BANK_R_CTX] +
+                 (mfc_read(dev, S5P_FIMV_ENCODED_C_ADDR) << MFC_OFFSET_SHIFT);
+}
+
+/* Set encoding ref & codec buffer */
+static int s5p_mfc_set_enc_ref_buffer_v5(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       size_t buf_addr1, buf_addr2;
+       size_t buf_size1, buf_size2;
+       unsigned int enc_ref_y_size, enc_ref_c_size;
+       unsigned int guard_width, guard_height;
+       int i;
+
+       buf_addr1 = ctx->bank1.dma;
+       buf_size1 = ctx->bank1.size;
+       buf_addr2 = ctx->bank2.dma;
+       buf_size2 = ctx->bank2.size;
+       enc_ref_y_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
+               * ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);
+       enc_ref_y_size = ALIGN(enc_ref_y_size, S5P_FIMV_NV12MT_SALIGN);
+       if (ctx->codec_mode == S5P_MFC_CODEC_H264_ENC) {
+               enc_ref_c_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
+                       * ALIGN((ctx->img_height >> 1), S5P_FIMV_NV12MT_VALIGN);
+               enc_ref_c_size = ALIGN(enc_ref_c_size, S5P_FIMV_NV12MT_SALIGN);
+       } else {
+               guard_width = ALIGN(ctx->img_width + 16,
+                                               S5P_FIMV_NV12MT_HALIGN);
+               guard_height = ALIGN((ctx->img_height >> 1) + 4,
+                                               S5P_FIMV_NV12MT_VALIGN);
+               enc_ref_c_size = ALIGN(guard_width * guard_height,
+                                      S5P_FIMV_NV12MT_SALIGN);
+       }
+       mfc_debug(2, "buf_size1: %zu, buf_size2: %zu\n", buf_size1, buf_size2);
+       switch (ctx->codec_mode) {
+       case S5P_MFC_CODEC_H264_ENC:
+               for (i = 0; i < 2; i++) {
+                       mfc_write(dev, OFFSETA(buf_addr1),
+                               S5P_FIMV_ENC_REF0_LUMA_ADR + (4 * i));
+                       buf_addr1 += enc_ref_y_size;
+                       buf_size1 -= enc_ref_y_size;
+
+                       mfc_write(dev, OFFSETB(buf_addr2),
+                               S5P_FIMV_ENC_REF2_LUMA_ADR + (4 * i));
+                       buf_addr2 += enc_ref_y_size;
+                       buf_size2 -= enc_ref_y_size;
+               }
+               for (i = 0; i < 4; i++) {
+                       mfc_write(dev, OFFSETB(buf_addr2),
+                               S5P_FIMV_ENC_REF0_CHROMA_ADR + (4 * i));
+                       buf_addr2 += enc_ref_c_size;
+                       buf_size2 -= enc_ref_c_size;
+               }
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H264_UP_MV_ADR);
+               buf_addr1 += S5P_FIMV_ENC_UPMV_SIZE;
+               buf_size1 -= S5P_FIMV_ENC_UPMV_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1),
+                                       S5P_FIMV_H264_COZERO_FLAG_ADR);
+               buf_addr1 += S5P_FIMV_ENC_COLFLG_SIZE;
+               buf_size1 -= S5P_FIMV_ENC_COLFLG_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1),
+                                       S5P_FIMV_H264_UP_INTRA_MD_ADR);
+               buf_addr1 += S5P_FIMV_ENC_INTRAMD_SIZE;
+               buf_size1 -= S5P_FIMV_ENC_INTRAMD_SIZE;
+               mfc_write(dev, OFFSETB(buf_addr2),
+                                       S5P_FIMV_H264_UP_INTRA_PRED_ADR);
+               buf_addr2 += S5P_FIMV_ENC_INTRAPRED_SIZE;
+               buf_size2 -= S5P_FIMV_ENC_INTRAPRED_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1),
+                                       S5P_FIMV_H264_NBOR_INFO_ADR);
+               buf_addr1 += S5P_FIMV_ENC_NBORINFO_SIZE;
+               buf_size1 -= S5P_FIMV_ENC_NBORINFO_SIZE;
+               mfc_debug(2, "buf_size1: %zu, buf_size2: %zu\n",
+                       buf_size1, buf_size2);
+               break;
+       case S5P_MFC_CODEC_MPEG4_ENC:
+               for (i = 0; i < 2; i++) {
+                       mfc_write(dev, OFFSETA(buf_addr1),
+                               S5P_FIMV_ENC_REF0_LUMA_ADR + (4 * i));
+                       buf_addr1 += enc_ref_y_size;
+                       buf_size1 -= enc_ref_y_size;
+                       mfc_write(dev, OFFSETB(buf_addr2),
+                               S5P_FIMV_ENC_REF2_LUMA_ADR + (4 * i));
+                       buf_addr2 += enc_ref_y_size;
+                       buf_size2 -= enc_ref_y_size;
+               }
+               for (i = 0; i < 4; i++) {
+                       mfc_write(dev, OFFSETB(buf_addr2),
+                               S5P_FIMV_ENC_REF0_CHROMA_ADR + (4 * i));
+                       buf_addr2 += enc_ref_c_size;
+                       buf_size2 -= enc_ref_c_size;
+               }
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_MPEG4_UP_MV_ADR);
+               buf_addr1 += S5P_FIMV_ENC_UPMV_SIZE;
+               buf_size1 -= S5P_FIMV_ENC_UPMV_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1),
+                                               S5P_FIMV_MPEG4_COZERO_FLAG_ADR);
+               buf_addr1 += S5P_FIMV_ENC_COLFLG_SIZE;
+               buf_size1 -= S5P_FIMV_ENC_COLFLG_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1),
+                                               S5P_FIMV_MPEG4_ACDC_COEF_ADR);
+               buf_addr1 += S5P_FIMV_ENC_ACDCCOEF_SIZE;
+               buf_size1 -= S5P_FIMV_ENC_ACDCCOEF_SIZE;
+               mfc_debug(2, "buf_size1: %zu, buf_size2: %zu\n",
+                       buf_size1, buf_size2);
+               break;
+       case S5P_MFC_CODEC_H263_ENC:
+               for (i = 0; i < 2; i++) {
+                       mfc_write(dev, OFFSETA(buf_addr1),
+                               S5P_FIMV_ENC_REF0_LUMA_ADR + (4 * i));
+                       buf_addr1 += enc_ref_y_size;
+                       buf_size1 -= enc_ref_y_size;
+                       mfc_write(dev, OFFSETB(buf_addr2),
+                               S5P_FIMV_ENC_REF2_LUMA_ADR + (4 * i));
+                       buf_addr2 += enc_ref_y_size;
+                       buf_size2 -= enc_ref_y_size;
+               }
+               for (i = 0; i < 4; i++) {
+                       mfc_write(dev, OFFSETB(buf_addr2),
+                               S5P_FIMV_ENC_REF0_CHROMA_ADR + (4 * i));
+                       buf_addr2 += enc_ref_c_size;
+                       buf_size2 -= enc_ref_c_size;
+               }
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_UP_MV_ADR);
+               buf_addr1 += S5P_FIMV_ENC_UPMV_SIZE;
+               buf_size1 -= S5P_FIMV_ENC_UPMV_SIZE;
+               mfc_write(dev, OFFSETA(buf_addr1), S5P_FIMV_H263_ACDC_COEF_ADR);
+               buf_addr1 += S5P_FIMV_ENC_ACDCCOEF_SIZE;
+               buf_size1 -= S5P_FIMV_ENC_ACDCCOEF_SIZE;
+               mfc_debug(2, "buf_size1: %zu, buf_size2: %zu\n",
+                       buf_size1, buf_size2);
+               break;
+       default:
+               mfc_err("Unknown codec set for encoding: %d\n",
+                       ctx->codec_mode);
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int s5p_mfc_set_enc_params(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc_params *p = &ctx->enc_params;
+       unsigned int reg;
+       unsigned int shm;
+
+       /* width */
+       mfc_write(dev, ctx->img_width, S5P_FIMV_ENC_HSIZE_PX);
+       /* height */
+       mfc_write(dev, ctx->img_height, S5P_FIMV_ENC_VSIZE_PX);
+       /* pictype : enable, IDR period */
+       reg = mfc_read(dev, S5P_FIMV_ENC_PIC_TYPE_CTRL);
+       reg |= (1 << 18);
+       reg &= ~(0xFFFF);
+       reg |= p->gop_size;
+       mfc_write(dev, reg, S5P_FIMV_ENC_PIC_TYPE_CTRL);
+       mfc_write(dev, 0, S5P_FIMV_ENC_B_RECON_WRITE_ON);
+       /* multi-slice control */
+       /* multi-slice MB number or bit size */
+       mfc_write(dev, p->slice_mode, S5P_FIMV_ENC_MSLICE_CTRL);
+       if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB) {
+               mfc_write(dev, p->slice_mb, S5P_FIMV_ENC_MSLICE_MB);
+       } else if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES) {
+               mfc_write(dev, p->slice_bit, S5P_FIMV_ENC_MSLICE_BIT);
+       } else {
+               mfc_write(dev, 0, S5P_FIMV_ENC_MSLICE_MB);
+               mfc_write(dev, 0, S5P_FIMV_ENC_MSLICE_BIT);
+       }
+       /* cyclic intra refresh */
+       mfc_write(dev, p->intra_refresh_mb, S5P_FIMV_ENC_CIR_CTRL);
+       /* memory structure cur. frame */
+       if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M)
+               mfc_write(dev, 0, S5P_FIMV_ENC_MAP_FOR_CUR);
+       else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT)
+               mfc_write(dev, 3, S5P_FIMV_ENC_MAP_FOR_CUR);
+       /* padding control & value */
+       reg = mfc_read(dev, S5P_FIMV_ENC_PADDING_CTRL);
+       if (p->pad) {
+               /** enable */
+               reg |= (1UL << 31);
+               /** cr value */
+               reg &= ~(0xFF << 16);
+               reg |= (p->pad_cr << 16);
+               /** cb value */
+               reg &= ~(0xFF << 8);
+               reg |= (p->pad_cb << 8);
+               /** y value */
+               reg &= ~(0xFF);
+               reg |= (p->pad_luma);
+       } else {
+               /** disable & all value clear */
+               reg = 0;
+       }
+       mfc_write(dev, reg, S5P_FIMV_ENC_PADDING_CTRL);
+       /* rate control config. */
+       reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
+       /** frame-level rate control */
+       reg &= ~(0x1 << 9);
+       reg |= (p->rc_frame << 9);
+       mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
+       /* bit rate */
+       if (p->rc_frame)
+               mfc_write(dev, p->rc_bitrate,
+                       S5P_FIMV_ENC_RC_BIT_RATE);
+       else
+               mfc_write(dev, 0, S5P_FIMV_ENC_RC_BIT_RATE);
+       /* reaction coefficient */
+       if (p->rc_frame)
+               mfc_write(dev, p->rc_reaction_coeff, S5P_FIMV_ENC_RC_RPARA);
+       shm = s5p_mfc_read_info_v5(ctx, EXT_ENC_CONTROL);
+       /* seq header ctrl */
+       shm &= ~(0x1 << 3);
+       shm |= (p->seq_hdr_mode << 3);
+       /* frame skip mode */
+       shm &= ~(0x3 << 1);
+       shm |= (p->frame_skip_mode << 1);
+       s5p_mfc_write_info_v5(ctx, shm, EXT_ENC_CONTROL);
+       /* fixed target bit */
+       s5p_mfc_write_info_v5(ctx, p->fixed_target_bit, RC_CONTROL_CONFIG);
+       return 0;
+}
+
+static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc_params *p = &ctx->enc_params;
+       struct s5p_mfc_h264_enc_params *p_264 = &p->codec.h264;
+       unsigned int reg;
+       unsigned int shm;
+
+       s5p_mfc_set_enc_params(ctx);
+       /* pictype : number of B */
+       reg = mfc_read(dev, S5P_FIMV_ENC_PIC_TYPE_CTRL);
+       /* num_b_frame - 0 ~ 2 */
+       reg &= ~(0x3 << 16);
+       reg |= (p->num_b_frame << 16);
+       mfc_write(dev, reg, S5P_FIMV_ENC_PIC_TYPE_CTRL);
+       /* profile & level */
+       reg = mfc_read(dev, S5P_FIMV_ENC_PROFILE);
+       /* level */
+       reg &= ~(0xFF << 8);
+       reg |= (p_264->level << 8);
+       /* profile - 0 ~ 2 */
+       reg &= ~(0x3F);
+       reg |= p_264->profile;
+       mfc_write(dev, reg, S5P_FIMV_ENC_PROFILE);
+       /* interlace  */
+       mfc_write(dev, p_264->interlace, S5P_FIMV_ENC_PIC_STRUCT);
+       /* height */
+       if (p_264->interlace)
+               mfc_write(dev, ctx->img_height >> 1, S5P_FIMV_ENC_VSIZE_PX);
+       /* loopfilter ctrl */
+       mfc_write(dev, p_264->loop_filter_mode, S5P_FIMV_ENC_LF_CTRL);
+       /* loopfilter alpha offset */
+       if (p_264->loop_filter_alpha < 0) {
+               reg = 0x10;
+               reg |= (0xFF - p_264->loop_filter_alpha) + 1;
+       } else {
+               reg = 0x00;
+               reg |= (p_264->loop_filter_alpha & 0xF);
+       }
+       mfc_write(dev, reg, S5P_FIMV_ENC_ALPHA_OFF);
+       /* loopfilter beta offset */
+       if (p_264->loop_filter_beta < 0) {
+               reg = 0x10;
+               reg |= (0xFF - p_264->loop_filter_beta) + 1;
+       } else {
+               reg = 0x00;
+               reg |= (p_264->loop_filter_beta & 0xF);
+       }
+       mfc_write(dev, reg, S5P_FIMV_ENC_BETA_OFF);
+       /* entropy coding mode */
+       if (p_264->entropy_mode == V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC)
+               mfc_write(dev, 1, S5P_FIMV_ENC_H264_ENTROPY_MODE);
+       else
+               mfc_write(dev, 0, S5P_FIMV_ENC_H264_ENTROPY_MODE);
+       /* number of ref. picture */
+       reg = mfc_read(dev, S5P_FIMV_ENC_H264_NUM_OF_REF);
+       /* num of ref. pictures of P */
+       reg &= ~(0x3 << 5);
+       reg |= (p_264->num_ref_pic_4p << 5);
+       /* max number of ref. pictures */
+       reg &= ~(0x1F);
+       reg |= p_264->max_ref_pic;
+       mfc_write(dev, reg, S5P_FIMV_ENC_H264_NUM_OF_REF);
+       /* 8x8 transform enable */
+       mfc_write(dev, p_264->_8x8_transform, S5P_FIMV_ENC_H264_TRANS_FLAG);
+       /* rate control config. */
+       reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
+       /* macroblock level rate control */
+       reg &= ~(0x1 << 8);
+       reg |= (p->rc_mb << 8);
+       /* frame QP */
+       reg &= ~(0x3F);
+       reg |= p_264->rc_frame_qp;
+       mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
+       /* frame rate */
+       if (p->rc_frame && p->rc_framerate_denom)
+               mfc_write(dev, p->rc_framerate_num * 1000
+                       / p->rc_framerate_denom, S5P_FIMV_ENC_RC_FRAME_RATE);
+       else
+               mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE);
+       /* max & min value of QP */
+       reg = mfc_read(dev, S5P_FIMV_ENC_RC_QBOUND);
+       /* max QP */
+       reg &= ~(0x3F << 8);
+       reg |= (p_264->rc_max_qp << 8);
+       /* min QP */
+       reg &= ~(0x3F);
+       reg |= p_264->rc_min_qp;
+       mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);
+       /* macroblock adaptive scaling features */
+       if (p->rc_mb) {
+               reg = mfc_read(dev, S5P_FIMV_ENC_RC_MB_CTRL);
+               /* dark region */
+               reg &= ~(0x1 << 3);
+               reg |= (p_264->rc_mb_dark << 3);
+               /* smooth region */
+               reg &= ~(0x1 << 2);
+               reg |= (p_264->rc_mb_smooth << 2);
+               /* static region */
+               reg &= ~(0x1 << 1);
+               reg |= (p_264->rc_mb_static << 1);
+               /* high activity region */
+               reg &= ~(0x1);
+               reg |= p_264->rc_mb_activity;
+               mfc_write(dev, reg, S5P_FIMV_ENC_RC_MB_CTRL);
+       }
+       if (!p->rc_frame && !p->rc_mb) {
+               shm = s5p_mfc_read_info_v5(ctx, P_B_FRAME_QP);
+               shm &= ~(0xFFF);
+               shm |= ((p_264->rc_b_frame_qp & 0x3F) << 6);
+               shm |= (p_264->rc_p_frame_qp & 0x3F);
+               s5p_mfc_write_info_v5(ctx, shm, P_B_FRAME_QP);
+       }
+       /* extended encoder ctrl */
+       shm = s5p_mfc_read_info_v5(ctx, EXT_ENC_CONTROL);
+       /* AR VUI control */
+       shm &= ~(0x1 << 15);
+       shm |= (p_264->vui_sar << 1);
+       s5p_mfc_write_info_v5(ctx, shm, EXT_ENC_CONTROL);
+       if (p_264->vui_sar) {
+               /* aspect ration IDC */
+               shm = s5p_mfc_read_info_v5(ctx, SAMPLE_ASPECT_RATIO_IDC);
+               shm &= ~(0xFF);
+               shm |= p_264->vui_sar_idc;
+               s5p_mfc_write_info_v5(ctx, shm, SAMPLE_ASPECT_RATIO_IDC);
+               if (p_264->vui_sar_idc == 0xFF) {
+                       /* sample  AR info */
+                       shm = s5p_mfc_read_info_v5(ctx, EXTENDED_SAR);
+                       shm &= ~(0xFFFFFFFF);
+                       shm |= p_264->vui_ext_sar_width << 16;
+                       shm |= p_264->vui_ext_sar_height;
+                       s5p_mfc_write_info_v5(ctx, shm, EXTENDED_SAR);
+               }
+       }
+       /* intra picture period for H.264 */
+       shm = s5p_mfc_read_info_v5(ctx, H264_I_PERIOD);
+       /* control */
+       shm &= ~(0x1 << 16);
+       shm |= (p_264->open_gop << 16);
+       /* value */
+       if (p_264->open_gop) {
+               shm &= ~(0xFFFF);
+               shm |= p_264->open_gop_size;
+       }
+       s5p_mfc_write_info_v5(ctx, shm, H264_I_PERIOD);
+       /* extended encoder ctrl */
+       shm = s5p_mfc_read_info_v5(ctx, EXT_ENC_CONTROL);
+       /* vbv buffer size */
+       if (p->frame_skip_mode ==
+                       V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
+               shm &= ~(0xFFFF << 16);
+               shm |= (p_264->cpb_size << 16);
+       }
+       s5p_mfc_write_info_v5(ctx, shm, EXT_ENC_CONTROL);
+       return 0;
+}
+
+static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc_params *p = &ctx->enc_params;
+       struct s5p_mfc_mpeg4_enc_params *p_mpeg4 = &p->codec.mpeg4;
+       unsigned int reg;
+       unsigned int shm;
+       unsigned int framerate;
+
+       s5p_mfc_set_enc_params(ctx);
+       /* pictype : number of B */
+       reg = mfc_read(dev, S5P_FIMV_ENC_PIC_TYPE_CTRL);
+       /* num_b_frame - 0 ~ 2 */
+       reg &= ~(0x3 << 16);
+       reg |= (p->num_b_frame << 16);
+       mfc_write(dev, reg, S5P_FIMV_ENC_PIC_TYPE_CTRL);
+       /* profile & level */
+       reg = mfc_read(dev, S5P_FIMV_ENC_PROFILE);
+       /* level */
+       reg &= ~(0xFF << 8);
+       reg |= (p_mpeg4->level << 8);
+       /* profile - 0 ~ 2 */
+       reg &= ~(0x3F);
+       reg |= p_mpeg4->profile;
+       mfc_write(dev, reg, S5P_FIMV_ENC_PROFILE);
+       /* quarter_pixel */
+       mfc_write(dev, p_mpeg4->quarter_pixel, S5P_FIMV_ENC_MPEG4_QUART_PXL);
+       /* qp */
+       if (!p->rc_frame) {
+               shm = s5p_mfc_read_info_v5(ctx, P_B_FRAME_QP);
+               shm &= ~(0xFFF);
+               shm |= ((p_mpeg4->rc_b_frame_qp & 0x3F) << 6);
+               shm |= (p_mpeg4->rc_p_frame_qp & 0x3F);
+               s5p_mfc_write_info_v5(ctx, shm, P_B_FRAME_QP);
+       }
+       /* frame rate */
+       if (p->rc_frame) {
+               if (p->rc_framerate_denom > 0) {
+                       framerate = p->rc_framerate_num * 1000 /
+                                               p->rc_framerate_denom;
+                       mfc_write(dev, framerate,
+                               S5P_FIMV_ENC_RC_FRAME_RATE);
+                       shm = s5p_mfc_read_info_v5(ctx, RC_VOP_TIMING);
+                       shm &= ~(0xFFFFFFFF);
+                       shm |= (1UL << 31);
+                       shm |= ((p->rc_framerate_num & 0x7FFF) << 16);
+                       shm |= (p->rc_framerate_denom & 0xFFFF);
+                       s5p_mfc_write_info_v5(ctx, shm, RC_VOP_TIMING);
+               }
+       } else {
+               mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE);
+       }
+       /* rate control config. */
+       reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
+       /* frame QP */
+       reg &= ~(0x3F);
+       reg |= p_mpeg4->rc_frame_qp;
+       mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
+       /* max & min value of QP */
+       reg = mfc_read(dev, S5P_FIMV_ENC_RC_QBOUND);
+       /* max QP */
+       reg &= ~(0x3F << 8);
+       reg |= (p_mpeg4->rc_max_qp << 8);
+       /* min QP */
+       reg &= ~(0x3F);
+       reg |= p_mpeg4->rc_min_qp;
+       mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);
+       /* extended encoder ctrl */
+       shm = s5p_mfc_read_info_v5(ctx, EXT_ENC_CONTROL);
+       /* vbv buffer size */
+       if (p->frame_skip_mode ==
+                       V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
+               shm &= ~(0xFFFF << 16);
+               shm |= (p->vbv_size << 16);
+       }
+       s5p_mfc_write_info_v5(ctx, shm, EXT_ENC_CONTROL);
+       return 0;
+}
+
+static int s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc_params *p = &ctx->enc_params;
+       struct s5p_mfc_mpeg4_enc_params *p_h263 = &p->codec.mpeg4;
+       unsigned int reg;
+       unsigned int shm;
+
+       s5p_mfc_set_enc_params(ctx);
+       /* qp */
+       if (!p->rc_frame) {
+               shm = s5p_mfc_read_info_v5(ctx, P_B_FRAME_QP);
+               shm &= ~(0xFFF);
+               shm |= (p_h263->rc_p_frame_qp & 0x3F);
+               s5p_mfc_write_info_v5(ctx, shm, P_B_FRAME_QP);
+       }
+       /* frame rate */
+       if (p->rc_frame && p->rc_framerate_denom)
+               mfc_write(dev, p->rc_framerate_num * 1000
+                       / p->rc_framerate_denom, S5P_FIMV_ENC_RC_FRAME_RATE);
+       else
+               mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE);
+       /* rate control config. */
+       reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
+       /* frame QP */
+       reg &= ~(0x3F);
+       reg |= p_h263->rc_frame_qp;
+       mfc_write(dev, reg, S5P_FIMV_ENC_RC_CONFIG);
+       /* max & min value of QP */
+       reg = mfc_read(dev, S5P_FIMV_ENC_RC_QBOUND);
+       /* max QP */
+       reg &= ~(0x3F << 8);
+       reg |= (p_h263->rc_max_qp << 8);
+       /* min QP */
+       reg &= ~(0x3F);
+       reg |= p_h263->rc_min_qp;
+       mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);
+       /* extended encoder ctrl */
+       shm = s5p_mfc_read_info_v5(ctx, EXT_ENC_CONTROL);
+       /* vbv buffer size */
+       if (p->frame_skip_mode ==
+                       V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
+               shm &= ~(0xFFFF << 16);
+               shm |= (p->vbv_size << 16);
+       }
+       s5p_mfc_write_info_v5(ctx, shm, EXT_ENC_CONTROL);
+       return 0;
+}
+
+/* Initialize decoding */
+static int s5p_mfc_init_decode_v5(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       s5p_mfc_set_shared_buffer(ctx);
+       /* Setup loop filter, for decoding this is only valid for MPEG4 */
+       if (ctx->codec_mode == S5P_MFC_CODEC_MPEG4_DEC)
+               mfc_write(dev, ctx->loop_filter_mpeg4, S5P_FIMV_ENC_LF_CTRL);
+       else
+               mfc_write(dev, 0, S5P_FIMV_ENC_LF_CTRL);
+       mfc_write(dev, ((ctx->slice_interface & S5P_FIMV_SLICE_INT_MASK) <<
+               S5P_FIMV_SLICE_INT_SHIFT) | (ctx->display_delay_enable <<
+               S5P_FIMV_DDELAY_ENA_SHIFT) | ((ctx->display_delay &
+               S5P_FIMV_DDELAY_VAL_MASK) << S5P_FIMV_DDELAY_VAL_SHIFT),
+               S5P_FIMV_SI_CH0_DPB_CONF_CTRL);
+       mfc_write(dev,
+       ((S5P_FIMV_CH_SEQ_HEADER & S5P_FIMV_CH_MASK) << S5P_FIMV_CH_SHIFT)
+                               | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
+       return 0;
+}
+
+static void s5p_mfc_set_flush(struct s5p_mfc_ctx *ctx, int flush)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned int dpb;
+
+       if (flush)
+               dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) | (
+                       S5P_FIMV_DPB_FLUSH_MASK << S5P_FIMV_DPB_FLUSH_SHIFT);
+       else
+               dpb = mfc_read(dev, S5P_FIMV_SI_CH0_DPB_CONF_CTRL) &
+                       ~(S5P_FIMV_DPB_FLUSH_MASK << S5P_FIMV_DPB_FLUSH_SHIFT);
+       mfc_write(dev, dpb, S5P_FIMV_SI_CH0_DPB_CONF_CTRL);
+}
+
+/* Decode a single frame */
+static int s5p_mfc_decode_one_frame_v5(struct s5p_mfc_ctx *ctx,
+                                       enum s5p_mfc_decode_arg last_frame)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       mfc_write(dev, ctx->dec_dst_flag, S5P_FIMV_SI_CH0_RELEASE_BUF);
+       s5p_mfc_set_shared_buffer(ctx);
+       s5p_mfc_set_flush(ctx, ctx->dpb_flush_flag);
+       /* Issue different commands to instance basing on whether it
+        * is the last frame or not. */
+       switch (last_frame) {
+       case MFC_DEC_FRAME:
+               mfc_write(dev, ((S5P_FIMV_CH_FRAME_START & S5P_FIMV_CH_MASK) <<
+               S5P_FIMV_CH_SHIFT) | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
+               break;
+       case MFC_DEC_LAST_FRAME:
+               mfc_write(dev, ((S5P_FIMV_CH_LAST_FRAME & S5P_FIMV_CH_MASK) <<
+               S5P_FIMV_CH_SHIFT) | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
+               break;
+       case MFC_DEC_RES_CHANGE:
+               mfc_write(dev, ((S5P_FIMV_CH_FRAME_START_REALLOC &
+               S5P_FIMV_CH_MASK) << S5P_FIMV_CH_SHIFT) | (ctx->inst_no),
+               S5P_FIMV_SI_CH0_INST_ID);
+               break;
+       }
+       mfc_debug(2, "Decoding a usual frame\n");
+       return 0;
+}
+
+static int s5p_mfc_init_encode_v5(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       if (ctx->codec_mode == S5P_MFC_CODEC_H264_ENC)
+               s5p_mfc_set_enc_params_h264(ctx);
+       else if (ctx->codec_mode == S5P_MFC_CODEC_MPEG4_ENC)
+               s5p_mfc_set_enc_params_mpeg4(ctx);
+       else if (ctx->codec_mode == S5P_MFC_CODEC_H263_ENC)
+               s5p_mfc_set_enc_params_h263(ctx);
+       else {
+               mfc_err("Unknown codec for encoding (%x)\n",
+                       ctx->codec_mode);
+               return -EINVAL;
+       }
+       s5p_mfc_set_shared_buffer(ctx);
+       mfc_write(dev, ((S5P_FIMV_CH_SEQ_HEADER << 16) & 0x70000) |
+               (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
+       return 0;
+}
+
+/* Encode a single frame */
+static int s5p_mfc_encode_one_frame_v5(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       int cmd;
+       /* memory structure cur. frame */
+       if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M)
+               mfc_write(dev, 0, S5P_FIMV_ENC_MAP_FOR_CUR);
+       else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT)
+               mfc_write(dev, 3, S5P_FIMV_ENC_MAP_FOR_CUR);
+       s5p_mfc_set_shared_buffer(ctx);
+
+       if (ctx->state == MFCINST_FINISHING)
+               cmd = S5P_FIMV_CH_LAST_FRAME;
+       else
+               cmd = S5P_FIMV_CH_FRAME_START;
+       mfc_write(dev, ((cmd & S5P_FIMV_CH_MASK) << S5P_FIMV_CH_SHIFT)
+                               | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
+
+       return 0;
+}
+
+static void s5p_mfc_run_res_change(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       s5p_mfc_set_dec_stream_buffer_v5(ctx, 0, 0, 0);
+       dev->curr_ctx = ctx->num;
+       s5p_mfc_decode_one_frame_v5(ctx, MFC_DEC_RES_CHANGE);
+}
+
+static int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx, int last_frame)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_buf *temp_vb;
+
+       if (ctx->state == MFCINST_FINISHING) {
+               last_frame = MFC_DEC_LAST_FRAME;
+               s5p_mfc_set_dec_stream_buffer_v5(ctx, 0, 0, 0);
+               dev->curr_ctx = ctx->num;
+               s5p_mfc_decode_one_frame_v5(ctx, last_frame);
+               return 0;
+       }
+
+       /* Frames are being decoded */
+       if (list_empty(&ctx->src_queue)) {
+               mfc_debug(2, "No src buffers\n");
+               return -EAGAIN;
+       }
+       /* Get the next source buffer */
+       temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
+       temp_vb->flags |= MFC_BUF_FLAG_USED;
+       s5p_mfc_set_dec_stream_buffer_v5(ctx,
+               vb2_dma_contig_plane_dma_addr(&temp_vb->b->vb2_buf, 0),
+               ctx->consumed_stream, temp_vb->b->vb2_buf.planes[0].bytesused);
+       dev->curr_ctx = ctx->num;
+       if (temp_vb->b->vb2_buf.planes[0].bytesused == 0) {
+               last_frame = MFC_DEC_LAST_FRAME;
+               mfc_debug(2, "Setting ctx->state to FINISHING\n");
+               ctx->state = MFCINST_FINISHING;
+       }
+       s5p_mfc_decode_one_frame_v5(ctx, last_frame);
+       return 0;
+}
+
+static int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_buf *dst_mb;
+       struct s5p_mfc_buf *src_mb;
+       unsigned long src_y_addr, src_c_addr, dst_addr;
+       unsigned int dst_size;
+
+       if (list_empty(&ctx->src_queue) && ctx->state != MFCINST_FINISHING) {
+               mfc_debug(2, "no src buffers\n");
+               return -EAGAIN;
+       }
+       if (list_empty(&ctx->dst_queue)) {
+               mfc_debug(2, "no dst buffers\n");
+               return -EAGAIN;
+       }
+       if (list_empty(&ctx->src_queue)) {
+               /* send null frame */
+               s5p_mfc_set_enc_frame_buffer_v5(ctx, dev->dma_base[BANK_R_CTX],
+                                               dev->dma_base[BANK_R_CTX]);
+               src_mb = NULL;
+       } else {
+               src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf,
+                                                                       list);
+               src_mb->flags |= MFC_BUF_FLAG_USED;
+               if (src_mb->b->vb2_buf.planes[0].bytesused == 0) {
+                       /* send null frame */
+                       s5p_mfc_set_enc_frame_buffer_v5(ctx,
+                                               dev->dma_base[BANK_R_CTX],
+                                               dev->dma_base[BANK_R_CTX]);
+                       ctx->state = MFCINST_FINISHING;
+               } else {
+                       src_y_addr = vb2_dma_contig_plane_dma_addr(
+                                       &src_mb->b->vb2_buf, 0);
+                       src_c_addr = vb2_dma_contig_plane_dma_addr(
+                                       &src_mb->b->vb2_buf, 1);
+                       s5p_mfc_set_enc_frame_buffer_v5(ctx, src_y_addr,
+                                                               src_c_addr);
+                       if (src_mb->flags & MFC_BUF_FLAG_EOS)
+                               ctx->state = MFCINST_FINISHING;
+               }
+       }
+       dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
+       dst_mb->flags |= MFC_BUF_FLAG_USED;
+       dst_addr = vb2_dma_contig_plane_dma_addr(&dst_mb->b->vb2_buf, 0);
+       dst_size = vb2_plane_size(&dst_mb->b->vb2_buf, 0);
+       s5p_mfc_set_enc_stream_buffer_v5(ctx, dst_addr, dst_size);
+       dev->curr_ctx = ctx->num;
+       mfc_debug(2, "encoding buffer with index=%d state=%d\n",
+                 src_mb ? src_mb->b->vb2_buf.index : -1, ctx->state);
+       s5p_mfc_encode_one_frame_v5(ctx);
+       return 0;
+}
+
+static void s5p_mfc_run_init_dec(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_buf *temp_vb;
+
+       /* Initializing decoding - parsing header */
+       mfc_debug(2, "Preparing to init decoding\n");
+       temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
+       s5p_mfc_set_dec_desc_buffer(ctx);
+       mfc_debug(2, "Header size: %d\n",
+                       temp_vb->b->vb2_buf.planes[0].bytesused);
+       s5p_mfc_set_dec_stream_buffer_v5(ctx,
+                       vb2_dma_contig_plane_dma_addr(&temp_vb->b->vb2_buf, 0),
+                       0, temp_vb->b->vb2_buf.planes[0].bytesused);
+       dev->curr_ctx = ctx->num;
+       s5p_mfc_init_decode_v5(ctx);
+}
+
+static void s5p_mfc_run_init_enc(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_buf *dst_mb;
+       unsigned long dst_addr;
+       unsigned int dst_size;
+
+       s5p_mfc_set_enc_ref_buffer_v5(ctx);
+       dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
+       dst_addr = vb2_dma_contig_plane_dma_addr(&dst_mb->b->vb2_buf, 0);
+       dst_size = vb2_plane_size(&dst_mb->b->vb2_buf, 0);
+       s5p_mfc_set_enc_stream_buffer_v5(ctx, dst_addr, dst_size);
+       dev->curr_ctx = ctx->num;
+       s5p_mfc_init_encode_v5(ctx);
+}
+
+static int s5p_mfc_run_init_dec_buffers(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_buf *temp_vb;
+       int ret;
+
+       /*
+        * Header was parsed now starting processing
+        * First set the output frame buffers
+        */
+       if (ctx->capture_state != QUEUE_BUFS_MMAPED) {
+               mfc_err("It seems that not all destination buffers were mmapped\nMFC requires that all destination are mmapped before starting processing\n");
+               return -EAGAIN;
+       }
+       if (list_empty(&ctx->src_queue)) {
+               mfc_err("Header has been deallocated in the middle of initialization\n");
+               return -EIO;
+       }
+       temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
+       mfc_debug(2, "Header size: %d\n",
+                       temp_vb->b->vb2_buf.planes[0].bytesused);
+       s5p_mfc_set_dec_stream_buffer_v5(ctx,
+                       vb2_dma_contig_plane_dma_addr(&temp_vb->b->vb2_buf, 0),
+                       0, temp_vb->b->vb2_buf.planes[0].bytesused);
+       dev->curr_ctx = ctx->num;
+       ret = s5p_mfc_set_dec_frame_buffer_v5(ctx);
+       if (ret) {
+               mfc_err("Failed to alloc frame mem\n");
+               ctx->state = MFCINST_ERROR;
+       }
+       return ret;
+}
+
+/* Try running an operation on hardware */
+static void s5p_mfc_try_run_v5(struct s5p_mfc_dev *dev)
+{
+       struct s5p_mfc_ctx *ctx;
+       int new_ctx;
+       unsigned int ret = 0;
+
+       if (test_bit(0, &dev->enter_suspend)) {
+               mfc_debug(1, "Entering suspend so do not schedule any jobs\n");
+               return;
+       }
+       /* Check whether hardware is not running */
+       if (test_and_set_bit(0, &dev->hw_lock) != 0) {
+               /* This is perfectly ok, the scheduled ctx should wait */
+               mfc_debug(1, "Couldn't lock HW\n");
+               return;
+       }
+       /* Choose the context to run */
+       new_ctx = s5p_mfc_get_new_ctx(dev);
+       if (new_ctx < 0) {
+               /* No contexts to run */
+               if (test_and_clear_bit(0, &dev->hw_lock) == 0) {
+                       mfc_err("Failed to unlock hardware\n");
+                       return;
+               }
+               mfc_debug(1, "No ctx is scheduled to be run\n");
+               return;
+       }
+       ctx = dev->ctx[new_ctx];
+       /* Got context to run in ctx */
+       /*
+        * Last frame has already been sent to MFC.
+        * Now obtaining frames from MFC buffer
+        */
+       s5p_mfc_clock_on();
+       s5p_mfc_clean_ctx_int_flags(ctx);
+
+       if (ctx->type == MFCINST_DECODER) {
+               s5p_mfc_set_dec_desc_buffer(ctx);
+               switch (ctx->state) {
+               case MFCINST_FINISHING:
+                       s5p_mfc_run_dec_frame(ctx, MFC_DEC_LAST_FRAME);
+                       break;
+               case MFCINST_RUNNING:
+                       ret = s5p_mfc_run_dec_frame(ctx, MFC_DEC_FRAME);
+                       break;
+               case MFCINST_INIT:
+                       ret = s5p_mfc_hw_call(dev->mfc_cmds, open_inst_cmd,
+                                       ctx);
+                       break;
+               case MFCINST_RETURN_INST:
+                       ret = s5p_mfc_hw_call(dev->mfc_cmds, close_inst_cmd,
+                                       ctx);
+                       break;
+               case MFCINST_GOT_INST:
+                       s5p_mfc_run_init_dec(ctx);
+                       break;
+               case MFCINST_HEAD_PARSED:
+                       ret = s5p_mfc_run_init_dec_buffers(ctx);
+                       mfc_debug(1, "head parsed\n");
+                       break;
+               case MFCINST_RES_CHANGE_INIT:
+                       s5p_mfc_run_res_change(ctx);
+                       break;
+               case MFCINST_RES_CHANGE_FLUSH:
+                       s5p_mfc_run_dec_frame(ctx, MFC_DEC_FRAME);
+                       break;
+               case MFCINST_RES_CHANGE_END:
+                       mfc_debug(2, "Finished remaining frames after resolution change\n");
+                       ctx->capture_state = QUEUE_FREE;
+                       mfc_debug(2, "Will re-init the codec\n");
+                       s5p_mfc_run_init_dec(ctx);
+                       break;
+               default:
+                       ret = -EAGAIN;
+               }
+       } else if (ctx->type == MFCINST_ENCODER) {
+               switch (ctx->state) {
+               case MFCINST_FINISHING:
+               case MFCINST_RUNNING:
+                       ret = s5p_mfc_run_enc_frame(ctx);
+                       break;
+               case MFCINST_INIT:
+                       ret = s5p_mfc_hw_call(dev->mfc_cmds, open_inst_cmd,
+                                       ctx);
+                       break;
+               case MFCINST_RETURN_INST:
+                       ret = s5p_mfc_hw_call(dev->mfc_cmds, close_inst_cmd,
+                                       ctx);
+                       break;
+               case MFCINST_GOT_INST:
+                       s5p_mfc_run_init_enc(ctx);
+                       break;
+               default:
+                       ret = -EAGAIN;
+               }
+       } else {
+               mfc_err("Invalid context type: %d\n", ctx->type);
+               ret = -EAGAIN;
+       }
+
+       if (ret) {
+               /* Free hardware lock */
+               if (test_and_clear_bit(0, &dev->hw_lock) == 0)
+                       mfc_err("Failed to unlock hardware\n");
+
+               /* This is indeed important, as no operation has been
+                * scheduled, reduce the clock count as no one will
+                * ever do this, because no interrupt related to this try_run
+                * will ever come from hardware. */
+               s5p_mfc_clock_off();
+       }
+}
+
+static void s5p_mfc_clear_int_flags_v5(struct s5p_mfc_dev *dev)
+{
+       mfc_write(dev, 0, S5P_FIMV_RISC_HOST_INT);
+       mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
+       mfc_write(dev, 0xffff, S5P_FIMV_SI_RTN_CHID);
+}
+
+static int s5p_mfc_get_dspl_y_adr_v5(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_SI_DISPLAY_Y_ADR) << MFC_OFFSET_SHIFT;
+}
+
+static int s5p_mfc_get_dec_y_adr_v5(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_SI_DECODE_Y_ADR) << MFC_OFFSET_SHIFT;
+}
+
+static int s5p_mfc_get_dspl_status_v5(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_SI_DISPLAY_STATUS);
+}
+
+static int s5p_mfc_get_dec_status_v5(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_SI_DECODE_STATUS);
+}
+
+static int s5p_mfc_get_dec_frame_type_v5(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_DECODE_FRAME_TYPE) &
+               S5P_FIMV_DECODE_FRAME_MASK;
+}
+
+static int s5p_mfc_get_disp_frame_type_v5(struct s5p_mfc_ctx *ctx)
+{
+       return (s5p_mfc_read_info_v5(ctx, DISP_PIC_FRAME_TYPE) >>
+                       S5P_FIMV_SHARED_DISP_FRAME_TYPE_SHIFT) &
+                       S5P_FIMV_DECODE_FRAME_MASK;
+}
+
+static int s5p_mfc_get_consumed_stream_v5(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_SI_CONSUMED_BYTES);
+}
+
+static int s5p_mfc_get_int_reason_v5(struct s5p_mfc_dev *dev)
+{
+       int reason;
+       reason = mfc_read(dev, S5P_FIMV_RISC2HOST_CMD) &
+               S5P_FIMV_RISC2HOST_CMD_MASK;
+       switch (reason) {
+       case S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET:
+               reason = S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET;
+               break;
+       case S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET:
+               reason = S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET;
+               break;
+       case S5P_FIMV_R2H_CMD_SEQ_DONE_RET:
+               reason = S5P_MFC_R2H_CMD_SEQ_DONE_RET;
+               break;
+       case S5P_FIMV_R2H_CMD_FRAME_DONE_RET:
+               reason = S5P_MFC_R2H_CMD_FRAME_DONE_RET;
+               break;
+       case S5P_FIMV_R2H_CMD_SLICE_DONE_RET:
+               reason = S5P_MFC_R2H_CMD_SLICE_DONE_RET;
+               break;
+       case S5P_FIMV_R2H_CMD_SYS_INIT_RET:
+               reason = S5P_MFC_R2H_CMD_SYS_INIT_RET;
+               break;
+       case S5P_FIMV_R2H_CMD_FW_STATUS_RET:
+               reason = S5P_MFC_R2H_CMD_FW_STATUS_RET;
+               break;
+       case S5P_FIMV_R2H_CMD_SLEEP_RET:
+               reason = S5P_MFC_R2H_CMD_SLEEP_RET;
+               break;
+       case S5P_FIMV_R2H_CMD_WAKEUP_RET:
+               reason = S5P_MFC_R2H_CMD_WAKEUP_RET;
+               break;
+       case S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET:
+               reason = S5P_MFC_R2H_CMD_INIT_BUFFERS_RET;
+               break;
+       case S5P_FIMV_R2H_CMD_ENC_COMPLETE_RET:
+               reason = S5P_MFC_R2H_CMD_COMPLETE_SEQ_RET;
+               break;
+       case S5P_FIMV_R2H_CMD_ERR_RET:
+               reason = S5P_MFC_R2H_CMD_ERR_RET;
+               break;
+       default:
+               reason = S5P_MFC_R2H_CMD_EMPTY;
+       }
+       return reason;
+}
+
+static int s5p_mfc_get_int_err_v5(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_RISC2HOST_ARG2);
+}
+
+static int s5p_mfc_err_dec_v5(unsigned int err)
+{
+       return (err & S5P_FIMV_ERR_DEC_MASK) >> S5P_FIMV_ERR_DEC_SHIFT;
+}
+
+static int s5p_mfc_get_img_width_v5(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_SI_HRESOL);
+}
+
+static int s5p_mfc_get_img_height_v5(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_SI_VRESOL);
+}
+
+static int s5p_mfc_get_dpb_count_v5(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_SI_BUF_NUMBER);
+}
+
+static int s5p_mfc_get_mv_count_v5(struct s5p_mfc_dev *dev)
+{
+       /* NOP */
+       return -1;
+}
+
+static int s5p_mfc_get_inst_no_v5(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_RISC2HOST_ARG1);
+}
+
+static int s5p_mfc_get_enc_strm_size_v5(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_ENC_SI_STRM_SIZE);
+}
+
+static int s5p_mfc_get_enc_slice_type_v5(struct s5p_mfc_dev *dev)
+{
+       return mfc_read(dev, S5P_FIMV_ENC_SI_SLICE_TYPE);
+}
+
+static int s5p_mfc_get_enc_dpb_count_v5(struct s5p_mfc_dev *dev)
+{
+       return -1;
+}
+
+static unsigned int s5p_mfc_get_pic_type_top_v5(struct s5p_mfc_ctx *ctx)
+{
+       return s5p_mfc_read_info_v5(ctx, PIC_TIME_TOP);
+}
+
+static unsigned int s5p_mfc_get_pic_type_bot_v5(struct s5p_mfc_ctx *ctx)
+{
+       return s5p_mfc_read_info_v5(ctx, PIC_TIME_BOT);
+}
+
+static unsigned int s5p_mfc_get_crop_info_h_v5(struct s5p_mfc_ctx *ctx)
+{
+       return s5p_mfc_read_info_v5(ctx, CROP_INFO_H);
+}
+
+static unsigned int s5p_mfc_get_crop_info_v_v5(struct s5p_mfc_ctx *ctx)
+{
+       return s5p_mfc_read_info_v5(ctx, CROP_INFO_V);
+}
+
+/* Initialize opr function pointers for MFC v5 */
+static struct s5p_mfc_hw_ops s5p_mfc_ops_v5 = {
+       .alloc_dec_temp_buffers = s5p_mfc_alloc_dec_temp_buffers_v5,
+       .release_dec_desc_buffer = s5p_mfc_release_dec_desc_buffer_v5,
+       .alloc_codec_buffers = s5p_mfc_alloc_codec_buffers_v5,
+       .release_codec_buffers = s5p_mfc_release_codec_buffers_v5,
+       .alloc_instance_buffer = s5p_mfc_alloc_instance_buffer_v5,
+       .release_instance_buffer = s5p_mfc_release_instance_buffer_v5,
+       .alloc_dev_context_buffer = s5p_mfc_alloc_dev_context_buffer_v5,
+       .release_dev_context_buffer = s5p_mfc_release_dev_context_buffer_v5,
+       .dec_calc_dpb_size = s5p_mfc_dec_calc_dpb_size_v5,
+       .enc_calc_src_size = s5p_mfc_enc_calc_src_size_v5,
+       .set_enc_stream_buffer = s5p_mfc_set_enc_stream_buffer_v5,
+       .set_enc_frame_buffer = s5p_mfc_set_enc_frame_buffer_v5,
+       .get_enc_frame_buffer = s5p_mfc_get_enc_frame_buffer_v5,
+       .try_run = s5p_mfc_try_run_v5,
+       .clear_int_flags = s5p_mfc_clear_int_flags_v5,
+       .get_dspl_y_adr = s5p_mfc_get_dspl_y_adr_v5,
+       .get_dec_y_adr = s5p_mfc_get_dec_y_adr_v5,
+       .get_dspl_status = s5p_mfc_get_dspl_status_v5,
+       .get_dec_status = s5p_mfc_get_dec_status_v5,
+       .get_dec_frame_type = s5p_mfc_get_dec_frame_type_v5,
+       .get_disp_frame_type = s5p_mfc_get_disp_frame_type_v5,
+       .get_consumed_stream = s5p_mfc_get_consumed_stream_v5,
+       .get_int_reason = s5p_mfc_get_int_reason_v5,
+       .get_int_err = s5p_mfc_get_int_err_v5,
+       .err_dec = s5p_mfc_err_dec_v5,
+       .get_img_width = s5p_mfc_get_img_width_v5,
+       .get_img_height = s5p_mfc_get_img_height_v5,
+       .get_dpb_count = s5p_mfc_get_dpb_count_v5,
+       .get_mv_count = s5p_mfc_get_mv_count_v5,
+       .get_inst_no = s5p_mfc_get_inst_no_v5,
+       .get_enc_strm_size = s5p_mfc_get_enc_strm_size_v5,
+       .get_enc_slice_type = s5p_mfc_get_enc_slice_type_v5,
+       .get_enc_dpb_count = s5p_mfc_get_enc_dpb_count_v5,
+       .get_pic_type_top = s5p_mfc_get_pic_type_top_v5,
+       .get_pic_type_bot = s5p_mfc_get_pic_type_bot_v5,
+       .get_crop_info_h = s5p_mfc_get_crop_info_h_v5,
+       .get_crop_info_v = s5p_mfc_get_crop_info_v_v5,
+};
+
+struct s5p_mfc_hw_ops *s5p_mfc_init_hw_ops_v5(void)
+{
+       return &s5p_mfc_ops_v5;
+}
diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_opr_v5.h b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_opr_v5.h
new file mode 100644 (file)
index 0000000..b53d376
--- /dev/null
@@ -0,0 +1,82 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * drivers/media/platform/samsung/mfc5/s5p_mfc_opr_v5.h
+ *
+ * Header file for Samsung MFC (Multi Function Codec - FIMV) driver
+ * Contains declarations of hw related functions.
+ *
+ * Kamil Debski, Copyright (C) 2011 Samsung Electronics
+ * http://www.samsung.com/
+ */
+
+#ifndef S5P_MFC_OPR_V5_H_
+#define S5P_MFC_OPR_V5_H_
+
+#include "s5p_mfc_common.h"
+#include "s5p_mfc_opr.h"
+
+enum MFC_SHM_OFS {
+       EXTENEDED_DECODE_STATUS = 0x00, /* D */
+       SET_FRAME_TAG           = 0x04, /* D */
+       GET_FRAME_TAG_TOP       = 0x08, /* D */
+       GET_FRAME_TAG_BOT       = 0x0C, /* D */
+       PIC_TIME_TOP            = 0x10, /* D */
+       PIC_TIME_BOT            = 0x14, /* D */
+       START_BYTE_NUM          = 0x18, /* D */
+
+       CROP_INFO_H             = 0x20, /* D */
+       CROP_INFO_V             = 0x24, /* D */
+       EXT_ENC_CONTROL         = 0x28, /* E */
+       ENC_PARAM_CHANGE        = 0x2C, /* E */
+       RC_VOP_TIMING           = 0x30, /* E, MPEG4 */
+       HEC_PERIOD              = 0x34, /* E, MPEG4 */
+       METADATA_ENABLE         = 0x38, /* C */
+       METADATA_STATUS         = 0x3C, /* C */
+       METADATA_DISPLAY_INDEX  = 0x40, /* C */
+       EXT_METADATA_START_ADDR = 0x44, /* C */
+       PUT_EXTRADATA           = 0x48, /* C */
+       EXTRADATA_ADDR          = 0x4C, /* C */
+
+       ALLOC_LUMA_DPB_SIZE     = 0x64, /* D */
+       ALLOC_CHROMA_DPB_SIZE   = 0x68, /* D */
+       ALLOC_MV_SIZE           = 0x6C, /* D */
+       P_B_FRAME_QP            = 0x70, /* E */
+       SAMPLE_ASPECT_RATIO_IDC = 0x74, /* E, H.264, depend on
+                               ASPECT_RATIO_VUI_ENABLE in EXT_ENC_CONTROL */
+       EXTENDED_SAR            = 0x78, /* E, H.264, depned on
+                               ASPECT_RATIO_VUI_ENABLE in EXT_ENC_CONTROL */
+       DISP_PIC_PROFILE        = 0x7C, /* D */
+       FLUSH_CMD_TYPE          = 0x80, /* C */
+       FLUSH_CMD_INBUF1        = 0x84, /* C */
+       FLUSH_CMD_INBUF2        = 0x88, /* C */
+       FLUSH_CMD_OUTBUF        = 0x8C, /* E */
+       NEW_RC_BIT_RATE         = 0x90, /* E, format as RC_BIT_RATE(0xC5A8)
+                       depend on RC_BIT_RATE_CHANGE in ENC_PARAM_CHANGE */
+       NEW_RC_FRAME_RATE       = 0x94, /* E, format as RC_FRAME_RATE(0xD0D0)
+                       depend on RC_FRAME_RATE_CHANGE in ENC_PARAM_CHANGE */
+       NEW_I_PERIOD            = 0x98, /* E, format as I_FRM_CTRL(0xC504)
+                       depend on I_PERIOD_CHANGE in ENC_PARAM_CHANGE */
+       H264_I_PERIOD           = 0x9C, /* E, H.264, open GOP */
+       RC_CONTROL_CONFIG       = 0xA0, /* E */
+       BATCH_INPUT_ADDR        = 0xA4, /* E */
+       BATCH_OUTPUT_ADDR       = 0xA8, /* E */
+       BATCH_OUTPUT_SIZE       = 0xAC, /* E */
+       MIN_LUMA_DPB_SIZE       = 0xB0, /* D */
+       DEVICE_FORMAT_ID        = 0xB4, /* C */
+       H264_POC_TYPE           = 0xB8, /* D */
+       MIN_CHROMA_DPB_SIZE     = 0xBC, /* D */
+       DISP_PIC_FRAME_TYPE     = 0xC0, /* D */
+       FREE_LUMA_DPB           = 0xC4, /* D, VC1 MPEG4 */
+       ASPECT_RATIO_INFO       = 0xC8, /* D, MPEG4 */
+       EXTENDED_PAR            = 0xCC, /* D, MPEG4 */
+       DBG_HISTORY_INPUT0      = 0xD0, /* C */
+       DBG_HISTORY_INPUT1      = 0xD4, /* C */
+       DBG_HISTORY_OUTPUT      = 0xD8, /* C */
+       HIERARCHICAL_P_QP       = 0xE0, /* E, H.264 */
+       FRAME_PACK_SEI_ENABLE   = 0x168, /* C */
+       FRAME_PACK_SEI_AVAIL    = 0x16c, /* D */
+       FRAME_PACK_SEI_INFO     = 0x17c, /* E */
+};
+
+struct s5p_mfc_hw_ops *s5p_mfc_init_hw_ops_v5(void);
+#endif /* S5P_MFC_OPR_H_ */
diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_opr_v6.c b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_opr_v6.c
new file mode 100644 (file)
index 0000000..8227004
--- /dev/null
@@ -0,0 +1,2534 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * drivers/media/platform/samsung/s5p-mfc/s5p_mfc_opr_v6.c
+ *
+ * Samsung MFC (Multi Function Codec - FIMV) driver
+ * This file contains hw related functions.
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ */
+
+#undef DEBUG
+
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/io.h>
+#include <linux/jiffies.h>
+#include <linux/firmware.h>
+#include <linux/err.h>
+#include <linux/sched.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/cacheflush.h>
+
+#include "s5p_mfc_common.h"
+#include "s5p_mfc_cmd.h"
+#include "s5p_mfc_intr.h"
+#include "s5p_mfc_pm.h"
+#include "s5p_mfc_debug.h"
+#include "s5p_mfc_opr.h"
+#include "s5p_mfc_opr_v6.h"
+
+/* #define S5P_MFC_DEBUG_REGWRITE  */
+#ifdef S5P_MFC_DEBUG_REGWRITE
+#undef writel
+#define writel(v, r)                                                   \
+       do {                                                            \
+               pr_err("MFCWRITE(%p): %08x\n", r, (unsigned int)v);     \
+       __raw_writel(v, r);                                             \
+       } while (0)
+#endif /* S5P_MFC_DEBUG_REGWRITE */
+
+#define IS_MFCV6_V2(dev) (!IS_MFCV7_PLUS(dev) && dev->fw_ver == MFC_FW_V2)
+
+/* Allocate temporary buffers for decoding */
+static int s5p_mfc_alloc_dec_temp_buffers_v6(struct s5p_mfc_ctx *ctx)
+{
+       /* NOP */
+
+       return 0;
+}
+
+/* Release temporary buffers for decoding */
+static void s5p_mfc_release_dec_desc_buffer_v6(struct s5p_mfc_ctx *ctx)
+{
+       /* NOP */
+}
+
+/* Allocate codec buffers */
+static int s5p_mfc_alloc_codec_buffers_v6(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned int mb_width, mb_height;
+       unsigned int lcu_width = 0, lcu_height = 0;
+       int ret;
+
+       mb_width = MB_WIDTH(ctx->img_width);
+       mb_height = MB_HEIGHT(ctx->img_height);
+
+       if (ctx->type == MFCINST_DECODER) {
+               mfc_debug(2, "Luma size:%d Chroma size:%d MV size:%d\n",
+                         ctx->luma_size, ctx->chroma_size, ctx->mv_size);
+               mfc_debug(2, "Totals bufs: %d\n", ctx->total_dpb_count);
+       } else if (ctx->type == MFCINST_ENCODER) {
+               if (IS_MFCV10(dev)) {
+                       ctx->tmv_buffer_size = 0;
+               } else if (IS_MFCV8_PLUS(dev))
+                       ctx->tmv_buffer_size = S5P_FIMV_NUM_TMV_BUFFERS_V6 *
+                       ALIGN(S5P_FIMV_TMV_BUFFER_SIZE_V8(mb_width, mb_height),
+                       S5P_FIMV_TMV_BUFFER_ALIGN_V6);
+               else
+                       ctx->tmv_buffer_size = S5P_FIMV_NUM_TMV_BUFFERS_V6 *
+                       ALIGN(S5P_FIMV_TMV_BUFFER_SIZE_V6(mb_width, mb_height),
+                       S5P_FIMV_TMV_BUFFER_ALIGN_V6);
+               if (IS_MFCV10(dev)) {
+                       lcu_width = S5P_MFC_LCU_WIDTH(ctx->img_width);
+                       lcu_height = S5P_MFC_LCU_HEIGHT(ctx->img_height);
+                       if (ctx->codec_mode != S5P_FIMV_CODEC_HEVC_ENC) {
+                               ctx->luma_dpb_size =
+                                       ALIGN((mb_width * 16), 64)
+                                       * ALIGN((mb_height * 16), 32)
+                                               + 64;
+                               ctx->chroma_dpb_size =
+                                       ALIGN((mb_width * 16), 64)
+                                                       * (mb_height * 8)
+                                                       + 64;
+                       } else {
+                               ctx->luma_dpb_size =
+                                       ALIGN((lcu_width * 32), 64)
+                                       * ALIGN((lcu_height * 32), 32)
+                                               + 64;
+                               ctx->chroma_dpb_size =
+                                       ALIGN((lcu_width * 32), 64)
+                                                       * (lcu_height * 16)
+                                                       + 64;
+                       }
+               } else {
+                       ctx->luma_dpb_size = ALIGN((mb_width * mb_height) *
+                                       S5P_FIMV_LUMA_MB_TO_PIXEL_V6,
+                                       S5P_FIMV_LUMA_DPB_BUFFER_ALIGN_V6);
+                       ctx->chroma_dpb_size = ALIGN((mb_width * mb_height) *
+                                       S5P_FIMV_CHROMA_MB_TO_PIXEL_V6,
+                                       S5P_FIMV_CHROMA_DPB_BUFFER_ALIGN_V6);
+               }
+               if (IS_MFCV8_PLUS(dev))
+                       ctx->me_buffer_size = ALIGN(S5P_FIMV_ME_BUFFER_SIZE_V8(
+                                               ctx->img_width, ctx->img_height,
+                                               mb_width, mb_height),
+                                               S5P_FIMV_ME_BUFFER_ALIGN_V6);
+               else
+                       ctx->me_buffer_size = ALIGN(S5P_FIMV_ME_BUFFER_SIZE_V6(
+                                               ctx->img_width, ctx->img_height,
+                                               mb_width, mb_height),
+                                               S5P_FIMV_ME_BUFFER_ALIGN_V6);
+
+               mfc_debug(2, "recon luma size: %zu chroma size: %zu\n",
+                         ctx->luma_dpb_size, ctx->chroma_dpb_size);
+       } else {
+               return -EINVAL;
+       }
+
+       /* Codecs have different memory requirements */
+       switch (ctx->codec_mode) {
+       case S5P_MFC_CODEC_H264_DEC:
+       case S5P_MFC_CODEC_H264_MVC_DEC:
+               if (IS_MFCV10(dev))
+                       mfc_debug(2, "Use min scratch buffer size\n");
+               else if (IS_MFCV8_PLUS(dev))
+                       ctx->scratch_buf_size =
+                               S5P_FIMV_SCRATCH_BUF_SIZE_H264_DEC_V8(
+                                       mb_width,
+                                       mb_height);
+               else
+                       ctx->scratch_buf_size =
+                               S5P_FIMV_SCRATCH_BUF_SIZE_H264_DEC_V6(
+                                       mb_width,
+                                       mb_height);
+               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size,
+                               S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
+               ctx->bank1.size =
+                       ctx->scratch_buf_size +
+                       (ctx->mv_count * ctx->mv_size);
+               break;
+       case S5P_MFC_CODEC_MPEG4_DEC:
+               if (IS_MFCV10(dev))
+                       mfc_debug(2, "Use min scratch buffer size\n");
+               else if (IS_MFCV7_PLUS(dev)) {
+                       ctx->scratch_buf_size =
+                               S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_DEC_V7(
+                                               mb_width,
+                                               mb_height);
+               } else {
+                       ctx->scratch_buf_size =
+                               S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_DEC_V6(
+                                               mb_width,
+                                               mb_height);
+               }
+
+               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size,
+                               S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
+               ctx->bank1.size = ctx->scratch_buf_size;
+               break;
+       case S5P_MFC_CODEC_VC1RCV_DEC:
+       case S5P_MFC_CODEC_VC1_DEC:
+               if (IS_MFCV10(dev))
+                       mfc_debug(2, "Use min scratch buffer size\n");
+               else
+                       ctx->scratch_buf_size =
+                               S5P_FIMV_SCRATCH_BUF_SIZE_VC1_DEC_V6(
+                                               mb_width,
+                                               mb_height);
+
+               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size,
+                               S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
+               ctx->bank1.size = ctx->scratch_buf_size;
+               break;
+       case S5P_MFC_CODEC_MPEG2_DEC:
+               ctx->bank1.size = 0;
+               ctx->bank2.size = 0;
+               break;
+       case S5P_MFC_CODEC_H263_DEC:
+               if (IS_MFCV10(dev))
+                       mfc_debug(2, "Use min scratch buffer size\n");
+               else
+                       ctx->scratch_buf_size =
+                               S5P_FIMV_SCRATCH_BUF_SIZE_H263_DEC_V6(
+                                               mb_width,
+                                               mb_height);
+               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size,
+                               S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
+               ctx->bank1.size = ctx->scratch_buf_size;
+               break;
+       case S5P_MFC_CODEC_VP8_DEC:
+               if (IS_MFCV10(dev))
+                       mfc_debug(2, "Use min scratch buffer size\n");
+               else if (IS_MFCV8_PLUS(dev))
+                       ctx->scratch_buf_size =
+                               S5P_FIMV_SCRATCH_BUF_SIZE_VP8_DEC_V8(
+                                               mb_width,
+                                               mb_height);
+               else
+                       ctx->scratch_buf_size =
+                               S5P_FIMV_SCRATCH_BUF_SIZE_VP8_DEC_V6(
+                                               mb_width,
+                                               mb_height);
+               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size,
+                               S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
+               ctx->bank1.size = ctx->scratch_buf_size;
+               break;
+       case S5P_MFC_CODEC_HEVC_DEC:
+               mfc_debug(2, "Use min scratch buffer size\n");
+               ctx->bank1.size =
+                       ctx->scratch_buf_size +
+                       (ctx->mv_count * ctx->mv_size);
+               break;
+       case S5P_MFC_CODEC_VP9_DEC:
+               mfc_debug(2, "Use min scratch buffer size\n");
+               ctx->bank1.size =
+                       ctx->scratch_buf_size +
+                       DEC_VP9_STATIC_BUFFER_SIZE;
+               break;
+       case S5P_MFC_CODEC_H264_ENC:
+               if (IS_MFCV10(dev)) {
+                       mfc_debug(2, "Use min scratch buffer size\n");
+                       ctx->me_buffer_size =
+                       ALIGN(ENC_V100_H264_ME_SIZE(mb_width, mb_height), 16);
+               } else if (IS_MFCV8_PLUS(dev))
+                       ctx->scratch_buf_size =
+                               S5P_FIMV_SCRATCH_BUF_SIZE_H264_ENC_V8(
+                                       mb_width,
+                                       mb_height);
+               else
+                       ctx->scratch_buf_size =
+                               S5P_FIMV_SCRATCH_BUF_SIZE_H264_ENC_V6(
+                                               mb_width,
+                                               mb_height);
+               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size,
+                               S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
+               ctx->bank1.size =
+                       ctx->scratch_buf_size + ctx->tmv_buffer_size +
+                       (ctx->pb_count * (ctx->luma_dpb_size +
+                       ctx->chroma_dpb_size + ctx->me_buffer_size));
+               ctx->bank2.size = 0;
+               break;
+       case S5P_MFC_CODEC_MPEG4_ENC:
+       case S5P_MFC_CODEC_H263_ENC:
+               if (IS_MFCV10(dev)) {
+                       mfc_debug(2, "Use min scratch buffer size\n");
+                       ctx->me_buffer_size =
+                               ALIGN(ENC_V100_MPEG4_ME_SIZE(mb_width,
+                                                       mb_height), 16);
+               } else
+                       ctx->scratch_buf_size =
+                               S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_ENC_V6(
+                                               mb_width,
+                                               mb_height);
+               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size,
+                               S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
+               ctx->bank1.size =
+                       ctx->scratch_buf_size + ctx->tmv_buffer_size +
+                       (ctx->pb_count * (ctx->luma_dpb_size +
+                       ctx->chroma_dpb_size + ctx->me_buffer_size));
+               ctx->bank2.size = 0;
+               break;
+       case S5P_MFC_CODEC_VP8_ENC:
+               if (IS_MFCV10(dev)) {
+                       mfc_debug(2, "Use min scratch buffer size\n");
+                       ctx->me_buffer_size =
+                               ALIGN(ENC_V100_VP8_ME_SIZE(mb_width, mb_height),
+                                               16);
+               } else if (IS_MFCV8_PLUS(dev))
+                       ctx->scratch_buf_size =
+                               S5P_FIMV_SCRATCH_BUF_SIZE_VP8_ENC_V8(
+                                       mb_width,
+                                       mb_height);
+               else
+                       ctx->scratch_buf_size =
+                               S5P_FIMV_SCRATCH_BUF_SIZE_VP8_ENC_V7(
+                                               mb_width,
+                                               mb_height);
+               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size,
+                               S5P_FIMV_SCRATCH_BUFFER_ALIGN_V6);
+               ctx->bank1.size =
+                       ctx->scratch_buf_size + ctx->tmv_buffer_size +
+                       (ctx->pb_count * (ctx->luma_dpb_size +
+                       ctx->chroma_dpb_size + ctx->me_buffer_size));
+               ctx->bank2.size = 0;
+               break;
+       case S5P_MFC_CODEC_HEVC_ENC:
+               mfc_debug(2, "Use min scratch buffer size\n");
+               ctx->me_buffer_size =
+                       ALIGN(ENC_V100_HEVC_ME_SIZE(lcu_width, lcu_height), 16);
+               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
+               ctx->bank1.size =
+                       ctx->scratch_buf_size + ctx->tmv_buffer_size +
+                       (ctx->pb_count * (ctx->luma_dpb_size +
+                       ctx->chroma_dpb_size + ctx->me_buffer_size));
+               ctx->bank2.size = 0;
+               break;
+       default:
+               break;
+       }
+
+       /* Allocate only if memory from bank 1 is necessary */
+       if (ctx->bank1.size > 0) {
+               ret = s5p_mfc_alloc_generic_buf(dev, BANK_L_CTX, &ctx->bank1);
+               if (ret) {
+                       mfc_err("Failed to allocate Bank1 memory\n");
+                       return ret;
+               }
+               BUG_ON(ctx->bank1.dma & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
+       }
+       return 0;
+}
+
+/* Release buffers allocated for codec */
+static void s5p_mfc_release_codec_buffers_v6(struct s5p_mfc_ctx *ctx)
+{
+       s5p_mfc_release_generic_buf(ctx->dev, &ctx->bank1);
+}
+
+/* Allocate memory for instance data buffer */
+static int s5p_mfc_alloc_instance_buffer_v6(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_buf_size_v6 *buf_size = dev->variant->buf_size->priv;
+       int ret;
+
+       mfc_debug_enter();
+
+       switch (ctx->codec_mode) {
+       case S5P_MFC_CODEC_H264_DEC:
+       case S5P_MFC_CODEC_H264_MVC_DEC:
+       case S5P_MFC_CODEC_HEVC_DEC:
+               ctx->ctx.size = buf_size->h264_dec_ctx;
+               break;
+       case S5P_MFC_CODEC_MPEG4_DEC:
+       case S5P_MFC_CODEC_H263_DEC:
+       case S5P_MFC_CODEC_VC1RCV_DEC:
+       case S5P_MFC_CODEC_VC1_DEC:
+       case S5P_MFC_CODEC_MPEG2_DEC:
+       case S5P_MFC_CODEC_VP8_DEC:
+       case S5P_MFC_CODEC_VP9_DEC:
+               ctx->ctx.size = buf_size->other_dec_ctx;
+               break;
+       case S5P_MFC_CODEC_H264_ENC:
+               ctx->ctx.size = buf_size->h264_enc_ctx;
+               break;
+       case S5P_MFC_CODEC_HEVC_ENC:
+               ctx->ctx.size = buf_size->hevc_enc_ctx;
+               break;
+       case S5P_MFC_CODEC_MPEG4_ENC:
+       case S5P_MFC_CODEC_H263_ENC:
+       case S5P_MFC_CODEC_VP8_ENC:
+               ctx->ctx.size = buf_size->other_enc_ctx;
+               break;
+       default:
+               ctx->ctx.size = 0;
+               mfc_err("Codec type(%d) should be checked!\n", ctx->codec_mode);
+               break;
+       }
+
+       ret = s5p_mfc_alloc_priv_buf(dev, BANK_L_CTX, &ctx->ctx);
+       if (ret) {
+               mfc_err("Failed to allocate instance buffer\n");
+               return ret;
+       }
+
+       memset(ctx->ctx.virt, 0, ctx->ctx.size);
+       wmb();
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+/* Release instance buffer */
+static void s5p_mfc_release_instance_buffer_v6(struct s5p_mfc_ctx *ctx)
+{
+       s5p_mfc_release_priv_buf(ctx->dev, &ctx->ctx);
+}
+
+/* Allocate context buffers for SYS_INIT */
+static int s5p_mfc_alloc_dev_context_buffer_v6(struct s5p_mfc_dev *dev)
+{
+       struct s5p_mfc_buf_size_v6 *buf_size = dev->variant->buf_size->priv;
+       int ret;
+
+       mfc_debug_enter();
+
+       dev->ctx_buf.size = buf_size->dev_ctx;
+       ret = s5p_mfc_alloc_priv_buf(dev, BANK_L_CTX, &dev->ctx_buf);
+       if (ret) {
+               mfc_err("Failed to allocate device context buffer\n");
+               return ret;
+       }
+
+       memset(dev->ctx_buf.virt, 0, buf_size->dev_ctx);
+       wmb();
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+/* Release context buffers for SYS_INIT */
+static void s5p_mfc_release_dev_context_buffer_v6(struct s5p_mfc_dev *dev)
+{
+       s5p_mfc_release_priv_buf(dev, &dev->ctx_buf);
+}
+
+static int calc_plane(int width, int height)
+{
+       int mbX, mbY;
+
+       mbX = DIV_ROUND_UP(width, S5P_FIMV_NUM_PIXELS_IN_MB_ROW_V6);
+       mbY = DIV_ROUND_UP(height, S5P_FIMV_NUM_PIXELS_IN_MB_COL_V6);
+
+       if (width * height < S5P_FIMV_MAX_FRAME_SIZE_V6)
+               mbY = (mbY + 1) / 2 * 2;
+
+       return (mbX * S5P_FIMV_NUM_PIXELS_IN_MB_COL_V6) *
+               (mbY * S5P_FIMV_NUM_PIXELS_IN_MB_ROW_V6);
+}
+
+static void s5p_mfc_dec_calc_dpb_size_v6(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN_V6);
+       ctx->buf_height = ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN_V6);
+       mfc_debug(2, "SEQ Done: Movie dimensions %dx%d,\n"
+                       "buffer dimensions: %dx%d\n", ctx->img_width,
+                       ctx->img_height, ctx->buf_width, ctx->buf_height);
+
+       ctx->luma_size = calc_plane(ctx->img_width, ctx->img_height);
+       ctx->chroma_size = calc_plane(ctx->img_width, (ctx->img_height >> 1));
+       if (IS_MFCV8_PLUS(ctx->dev)) {
+               /* MFCv8 needs additional 64 bytes for luma,chroma dpb*/
+               ctx->luma_size += S5P_FIMV_D_ALIGN_PLANE_SIZE_V8;
+               ctx->chroma_size += S5P_FIMV_D_ALIGN_PLANE_SIZE_V8;
+       }
+
+       if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC ||
+                       ctx->codec_mode == S5P_MFC_CODEC_H264_MVC_DEC) {
+               if (IS_MFCV10(dev)) {
+                       ctx->mv_size = S5P_MFC_DEC_MV_SIZE_V10(ctx->img_width,
+                                       ctx->img_height);
+               } else {
+                       ctx->mv_size = S5P_MFC_DEC_MV_SIZE_V6(ctx->img_width,
+                                       ctx->img_height);
+               }
+       } else if (ctx->codec_mode == S5P_MFC_CODEC_HEVC_DEC) {
+               ctx->mv_size = s5p_mfc_dec_hevc_mv_size(ctx->img_width,
+                               ctx->img_height);
+               ctx->mv_size = ALIGN(ctx->mv_size, 32);
+       } else {
+               ctx->mv_size = 0;
+       }
+}
+
+static void s5p_mfc_enc_calc_src_size_v6(struct s5p_mfc_ctx *ctx)
+{
+       unsigned int mb_width, mb_height;
+
+       mb_width = MB_WIDTH(ctx->img_width);
+       mb_height = MB_HEIGHT(ctx->img_height);
+
+       ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN_V6);
+       ctx->luma_size = ALIGN((mb_width * mb_height) * 256, 256);
+       ctx->chroma_size = ALIGN((mb_width * mb_height) * 128, 256);
+
+       /* MFCv7 needs pad bytes for Luma and Chroma */
+       if (IS_MFCV7_PLUS(ctx->dev)) {
+               ctx->luma_size += MFC_LUMA_PAD_BYTES_V7;
+               ctx->chroma_size += MFC_CHROMA_PAD_BYTES_V7;
+       }
+}
+
+/* Set registers for decoding stream buffer */
+static int s5p_mfc_set_dec_stream_buffer_v6(struct s5p_mfc_ctx *ctx,
+                       int buf_addr, unsigned int start_num_byte,
+                       unsigned int strm_size)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs;
+       struct s5p_mfc_buf_size *buf_size = dev->variant->buf_size;
+
+       mfc_debug_enter();
+       mfc_debug(2, "inst_no: %d, buf_addr: 0x%08x,\n"
+               "buf_size: 0x%08x (%d)\n",
+               ctx->inst_no, buf_addr, strm_size, strm_size);
+       writel(strm_size, mfc_regs->d_stream_data_size);
+       writel(buf_addr, mfc_regs->d_cpb_buffer_addr);
+       writel(buf_size->cpb, mfc_regs->d_cpb_buffer_size);
+       writel(start_num_byte, mfc_regs->d_cpb_buffer_offset);
+
+       mfc_debug_leave();
+       return 0;
+}
+
+/* Set decoding frame buffer */
+static int s5p_mfc_set_dec_frame_buffer_v6(struct s5p_mfc_ctx *ctx)
+{
+       unsigned int frame_size, i;
+       unsigned int frame_size_ch, frame_size_mv;
+       struct s5p_mfc_dev *dev = ctx->dev;
+       const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs;
+       size_t buf_addr1;
+       int buf_size1;
+       int align_gap;
+
+       buf_addr1 = ctx->bank1.dma;
+       buf_size1 = ctx->bank1.size;
+
+       mfc_debug(2, "Buf1: %p (%d)\n", (void *)buf_addr1, buf_size1);
+       mfc_debug(2, "Total DPB COUNT: %d\n", ctx->total_dpb_count);
+       mfc_debug(2, "Setting display delay to %d\n", ctx->display_delay);
+
+       writel(ctx->total_dpb_count, mfc_regs->d_num_dpb);
+       writel(ctx->luma_size, mfc_regs->d_first_plane_dpb_size);
+       writel(ctx->chroma_size, mfc_regs->d_second_plane_dpb_size);
+
+       writel(buf_addr1, mfc_regs->d_scratch_buffer_addr);
+       writel(ctx->scratch_buf_size, mfc_regs->d_scratch_buffer_size);
+
+       if (IS_MFCV8_PLUS(dev)) {
+               writel(ctx->img_width,
+                       mfc_regs->d_first_plane_dpb_stride_size);
+               writel(ctx->img_width,
+                       mfc_regs->d_second_plane_dpb_stride_size);
+       }
+
+       buf_addr1 += ctx->scratch_buf_size;
+       buf_size1 -= ctx->scratch_buf_size;
+
+       if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC ||
+                       ctx->codec_mode == S5P_FIMV_CODEC_H264_MVC_DEC ||
+                       ctx->codec_mode == S5P_FIMV_CODEC_HEVC_DEC) {
+               writel(ctx->mv_size, mfc_regs->d_mv_buffer_size);
+               writel(ctx->mv_count, mfc_regs->d_num_mv);
+       }
+
+       frame_size = ctx->luma_size;
+       frame_size_ch = ctx->chroma_size;
+       frame_size_mv = ctx->mv_size;
+       mfc_debug(2, "Frame size: %d ch: %d mv: %d\n",
+                       frame_size, frame_size_ch, frame_size_mv);
+
+       for (i = 0; i < ctx->total_dpb_count; i++) {
+               /* Bank2 */
+               mfc_debug(2, "Luma %d: %zx\n", i,
+                                       ctx->dst_bufs[i].cookie.raw.luma);
+               writel(ctx->dst_bufs[i].cookie.raw.luma,
+                               mfc_regs->d_first_plane_dpb + i * 4);
+               mfc_debug(2, "\tChroma %d: %zx\n", i,
+                                       ctx->dst_bufs[i].cookie.raw.chroma);
+               writel(ctx->dst_bufs[i].cookie.raw.chroma,
+                               mfc_regs->d_second_plane_dpb + i * 4);
+       }
+       if (ctx->codec_mode == S5P_MFC_CODEC_H264_DEC ||
+                       ctx->codec_mode == S5P_MFC_CODEC_H264_MVC_DEC ||
+                       ctx->codec_mode == S5P_MFC_CODEC_HEVC_DEC) {
+               for (i = 0; i < ctx->mv_count; i++) {
+                       /* To test alignment */
+                       align_gap = buf_addr1;
+                       buf_addr1 = ALIGN(buf_addr1, 16);
+                       align_gap = buf_addr1 - align_gap;
+                       buf_size1 -= align_gap;
+
+                       mfc_debug(2, "\tBuf1: %zx, size: %d\n",
+                                       buf_addr1, buf_size1);
+                       writel(buf_addr1, mfc_regs->d_mv_buffer + i * 4);
+                       buf_addr1 += frame_size_mv;
+                       buf_size1 -= frame_size_mv;
+               }
+       }
+       if (ctx->codec_mode == S5P_FIMV_CODEC_VP9_DEC) {
+               writel(buf_addr1, mfc_regs->d_static_buffer_addr);
+               writel(DEC_VP9_STATIC_BUFFER_SIZE,
+                               mfc_regs->d_static_buffer_size);
+               buf_addr1 += DEC_VP9_STATIC_BUFFER_SIZE;
+               buf_size1 -= DEC_VP9_STATIC_BUFFER_SIZE;
+       }
+
+       mfc_debug(2, "Buf1: %zx, buf_size1: %d (frames %d)\n",
+                       buf_addr1, buf_size1, ctx->total_dpb_count);
+       if (buf_size1 < 0) {
+               mfc_debug(2, "Not enough memory has been allocated.\n");
+               return -ENOMEM;
+       }
+
+       writel(ctx->inst_no, mfc_regs->instance_id);
+       s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev,
+                       S5P_FIMV_CH_INIT_BUFS_V6, NULL);
+
+       mfc_debug(2, "After setting buffers.\n");
+       return 0;
+}
+
+/* Set registers for encoding stream buffer */
+static int s5p_mfc_set_enc_stream_buffer_v6(struct s5p_mfc_ctx *ctx,
+               unsigned long addr, unsigned int size)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs;
+
+       writel(addr, mfc_regs->e_stream_buffer_addr); /* 16B align */
+       writel(size, mfc_regs->e_stream_buffer_size);
+
+       mfc_debug(2, "stream buf addr: 0x%08lx, size: 0x%x\n",
+                 addr, size);
+
+       return 0;
+}
+
+static void s5p_mfc_set_enc_frame_buffer_v6(struct s5p_mfc_ctx *ctx,
+               unsigned long y_addr, unsigned long c_addr)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs;
+
+       writel(y_addr, mfc_regs->e_source_first_plane_addr);
+       writel(c_addr, mfc_regs->e_source_second_plane_addr);
+
+       mfc_debug(2, "enc src y buf addr: 0x%08lx\n", y_addr);
+       mfc_debug(2, "enc src c buf addr: 0x%08lx\n", c_addr);
+}
+
+static void s5p_mfc_get_enc_frame_buffer_v6(struct s5p_mfc_ctx *ctx,
+               unsigned long *y_addr, unsigned long *c_addr)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs;
+       unsigned long enc_recon_y_addr, enc_recon_c_addr;
+
+       *y_addr = readl(mfc_regs->e_encoded_source_first_plane_addr);
+       *c_addr = readl(mfc_regs->e_encoded_source_second_plane_addr);
+
+       enc_recon_y_addr = readl(mfc_regs->e_recon_luma_dpb_addr);
+       enc_recon_c_addr = readl(mfc_regs->e_recon_chroma_dpb_addr);
+
+       mfc_debug(2, "recon y addr: 0x%08lx y_addr: 0x%08lx\n", enc_recon_y_addr, *y_addr);
+       mfc_debug(2, "recon c addr: 0x%08lx\n", enc_recon_c_addr);
+}
+
+/* Set encoding ref & codec buffer */
+static int s5p_mfc_set_enc_ref_buffer_v6(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs;
+       size_t buf_addr1;
+       int i, buf_size1;
+
+       mfc_debug_enter();
+
+       buf_addr1 = ctx->bank1.dma;
+       buf_size1 = ctx->bank1.size;
+
+       mfc_debug(2, "Buf1: %p (%d)\n", (void *)buf_addr1, buf_size1);
+
+       if (IS_MFCV10(dev)) {
+               /* start address of per buffer is aligned */
+               for (i = 0; i < ctx->pb_count; i++) {
+                       writel(buf_addr1, mfc_regs->e_luma_dpb + (4 * i));
+                       buf_addr1 += ctx->luma_dpb_size;
+                       buf_size1 -= ctx->luma_dpb_size;
+               }
+               for (i = 0; i < ctx->pb_count; i++) {
+                       writel(buf_addr1, mfc_regs->e_chroma_dpb + (4 * i));
+                       buf_addr1 += ctx->chroma_dpb_size;
+                       buf_size1 -= ctx->chroma_dpb_size;
+               }
+               for (i = 0; i < ctx->pb_count; i++) {
+                       writel(buf_addr1, mfc_regs->e_me_buffer + (4 * i));
+                       buf_addr1 += ctx->me_buffer_size;
+                       buf_size1 -= ctx->me_buffer_size;
+               }
+       } else {
+               for (i = 0; i < ctx->pb_count; i++) {
+                       writel(buf_addr1, mfc_regs->e_luma_dpb + (4 * i));
+                       buf_addr1 += ctx->luma_dpb_size;
+                       writel(buf_addr1, mfc_regs->e_chroma_dpb + (4 * i));
+                       buf_addr1 += ctx->chroma_dpb_size;
+                       writel(buf_addr1, mfc_regs->e_me_buffer + (4 * i));
+                       buf_addr1 += ctx->me_buffer_size;
+                       buf_size1 -= (ctx->luma_dpb_size + ctx->chroma_dpb_size
+                                       + ctx->me_buffer_size);
+               }
+       }
+
+       writel(buf_addr1, mfc_regs->e_scratch_buffer_addr);
+       writel(ctx->scratch_buf_size, mfc_regs->e_scratch_buffer_size);
+       buf_addr1 += ctx->scratch_buf_size;
+       buf_size1 -= ctx->scratch_buf_size;
+
+       writel(buf_addr1, mfc_regs->e_tmv_buffer0);
+       buf_addr1 += ctx->tmv_buffer_size >> 1;
+       writel(buf_addr1, mfc_regs->e_tmv_buffer1);
+       buf_addr1 += ctx->tmv_buffer_size >> 1;
+       buf_size1 -= ctx->tmv_buffer_size;
+
+       mfc_debug(2, "Buf1: %zu, buf_size1: %d (ref frames %d)\n",
+                       buf_addr1, buf_size1, ctx->pb_count);
+       if (buf_size1 < 0) {
+               mfc_debug(2, "Not enough memory has been allocated.\n");
+               return -ENOMEM;
+       }
+
+       writel(ctx->inst_no, mfc_regs->instance_id);
+       s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev,
+                       S5P_FIMV_CH_INIT_BUFS_V6, NULL);
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+static int s5p_mfc_set_slice_mode(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs;
+
+       /* multi-slice control */
+       /* multi-slice MB number or bit size */
+       writel(ctx->slice_mode, mfc_regs->e_mslice_mode);
+       if (ctx->slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB) {
+               writel(ctx->slice_size.mb, mfc_regs->e_mslice_size_mb);
+       } else if (ctx->slice_mode ==
+                       V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES) {
+               writel(ctx->slice_size.bits, mfc_regs->e_mslice_size_bits);
+       } else {
+               writel(0x0, mfc_regs->e_mslice_size_mb);
+               writel(0x0, mfc_regs->e_mslice_size_bits);
+       }
+
+       return 0;
+}
+
+static int s5p_mfc_set_enc_params(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs;
+       struct s5p_mfc_enc_params *p = &ctx->enc_params;
+       unsigned int reg = 0;
+
+       mfc_debug_enter();
+
+       /* width */
+       writel(ctx->img_width, mfc_regs->e_frame_width); /* 16 align */
+       /* height */
+       writel(ctx->img_height, mfc_regs->e_frame_height); /* 16 align */
+
+       /* cropped width */
+       writel(ctx->img_width, mfc_regs->e_cropped_frame_width);
+       /* cropped height */
+       writel(ctx->img_height, mfc_regs->e_cropped_frame_height);
+       /* cropped offset */
+       writel(0x0, mfc_regs->e_frame_crop_offset);
+
+       /* pictype : IDR period */
+       reg = 0;
+       reg |= p->gop_size & 0xFFFF;
+       writel(reg, mfc_regs->e_gop_config);
+
+       /* multi-slice control */
+       /* multi-slice MB number or bit size */
+       ctx->slice_mode = p->slice_mode;
+       reg = 0;
+       if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB) {
+               reg |= (0x1 << 3);
+               writel(reg, mfc_regs->e_enc_options);
+               ctx->slice_size.mb = p->slice_mb;
+       } else if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES) {
+               reg |= (0x1 << 3);
+               writel(reg, mfc_regs->e_enc_options);
+               ctx->slice_size.bits = p->slice_bit;
+       } else {
+               reg &= ~(0x1 << 3);
+               writel(reg, mfc_regs->e_enc_options);
+       }
+
+       s5p_mfc_set_slice_mode(ctx);
+
+       /* cyclic intra refresh */
+       writel(p->intra_refresh_mb, mfc_regs->e_ir_size);
+       reg = readl(mfc_regs->e_enc_options);
+       if (p->intra_refresh_mb == 0)
+               reg &= ~(0x1 << 4);
+       else
+               reg |= (0x1 << 4);
+       writel(reg, mfc_regs->e_enc_options);
+
+       /* 'NON_REFERENCE_STORE_ENABLE' for debugging */
+       reg = readl(mfc_regs->e_enc_options);
+       reg &= ~(0x1 << 9);
+       writel(reg, mfc_regs->e_enc_options);
+
+       /* memory structure cur. frame */
+       if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M) {
+               /* 0: Linear, 1: 2D tiled*/
+               reg = readl(mfc_regs->e_enc_options);
+               reg &= ~(0x1 << 7);
+               writel(reg, mfc_regs->e_enc_options);
+               /* 0: NV12(CbCr), 1: NV21(CrCb) */
+               writel(0x0, mfc_regs->pixel_format);
+       } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV21M) {
+               /* 0: Linear, 1: 2D tiled*/
+               reg = readl(mfc_regs->e_enc_options);
+               reg &= ~(0x1 << 7);
+               writel(reg, mfc_regs->e_enc_options);
+               /* 0: NV12(CbCr), 1: NV21(CrCb) */
+               writel(0x1, mfc_regs->pixel_format);
+       } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16) {
+               /* 0: Linear, 1: 2D tiled*/
+               reg = readl(mfc_regs->e_enc_options);
+               reg |= (0x1 << 7);
+               writel(reg, mfc_regs->e_enc_options);
+               /* 0: NV12(CbCr), 1: NV21(CrCb) */
+               writel(0x0, mfc_regs->pixel_format);
+       }
+
+       /* memory structure recon. frame */
+       /* 0: Linear, 1: 2D tiled */
+       reg = readl(mfc_regs->e_enc_options);
+       reg |= (0x1 << 8);
+       writel(reg, mfc_regs->e_enc_options);
+
+       /* padding control & value */
+       writel(0x0, mfc_regs->e_padding_ctrl);
+       if (p->pad) {
+               reg = 0;
+               /** enable */
+               reg |= (1UL << 31);
+               /** cr value */
+               reg |= ((p->pad_cr & 0xFF) << 16);
+               /** cb value */
+               reg |= ((p->pad_cb & 0xFF) << 8);
+               /** y value */
+               reg |= p->pad_luma & 0xFF;
+               writel(reg, mfc_regs->e_padding_ctrl);
+       }
+
+       /* rate control config. */
+       reg = 0;
+       /* frame-level rate control */
+       reg |= ((p->rc_frame & 0x1) << 9);
+       writel(reg, mfc_regs->e_rc_config);
+
+       /* bit rate */
+       if (p->rc_frame)
+               writel(p->rc_bitrate,
+                       mfc_regs->e_rc_bit_rate);
+       else
+               writel(1, mfc_regs->e_rc_bit_rate);
+
+       /* reaction coefficient */
+       if (p->rc_frame) {
+               if (p->rc_reaction_coeff < TIGHT_CBR_MAX) /* tight CBR */
+                       writel(1, mfc_regs->e_rc_mode);
+               else                                      /* loose CBR */
+                       writel(2, mfc_regs->e_rc_mode);
+       }
+
+       /* seq header ctrl */
+       reg = readl(mfc_regs->e_enc_options);
+       reg &= ~(0x1 << 2);
+       reg |= ((p->seq_hdr_mode & 0x1) << 2);
+
+       /* frame skip mode */
+       reg &= ~(0x3);
+       reg |= (p->frame_skip_mode & 0x3);
+       writel(reg, mfc_regs->e_enc_options);
+
+       /* 'DROP_CONTROL_ENABLE', disable */
+       reg = readl(mfc_regs->e_rc_config);
+       reg &= ~(0x1 << 10);
+       writel(reg, mfc_regs->e_rc_config);
+
+       /* setting for MV range [16, 256] */
+       reg = (p->mv_h_range & S5P_FIMV_E_MV_RANGE_V6_MASK);
+       writel(reg, mfc_regs->e_mv_hor_range);
+
+       reg = (p->mv_v_range & S5P_FIMV_E_MV_RANGE_V6_MASK);
+       writel(reg, mfc_regs->e_mv_ver_range);
+
+       writel(0x0, mfc_regs->e_frame_insertion);
+       writel(0x0, mfc_regs->e_roi_buffer_addr);
+       writel(0x0, mfc_regs->e_param_change);
+       writel(0x0, mfc_regs->e_rc_roi_ctrl);
+       writel(0x0, mfc_regs->e_picture_tag);
+
+       writel(0x0, mfc_regs->e_bit_count_enable);
+       writel(0x0, mfc_regs->e_max_bit_count);
+       writel(0x0, mfc_regs->e_min_bit_count);
+
+       writel(0x0, mfc_regs->e_metadata_buffer_addr);
+       writel(0x0, mfc_regs->e_metadata_buffer_size);
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs;
+       struct s5p_mfc_enc_params *p = &ctx->enc_params;
+       struct s5p_mfc_h264_enc_params *p_h264 = &p->codec.h264;
+       unsigned int reg = 0;
+       int i;
+
+       mfc_debug_enter();
+
+       s5p_mfc_set_enc_params(ctx);
+
+       /* pictype : number of B */
+       reg = readl(mfc_regs->e_gop_config);
+       reg &= ~(0x3 << 16);
+       reg |= ((p->num_b_frame & 0x3) << 16);
+       writel(reg, mfc_regs->e_gop_config);
+
+       /* profile & level */
+       reg = 0;
+       /** level */
+       reg |= ((p_h264->level & 0xFF) << 8);
+       /** profile - 0 ~ 3 */
+       reg |= p_h264->profile & 0x3F;
+       writel(reg, mfc_regs->e_picture_profile);
+
+       /* rate control config. */
+       reg = readl(mfc_regs->e_rc_config);
+       /** macroblock level rate control */
+       reg &= ~(0x1 << 8);
+       reg |= ((p->rc_mb & 0x1) << 8);
+       writel(reg, mfc_regs->e_rc_config);
+
+       /** frame QP */
+       reg &= ~(0x3F);
+       reg |= p_h264->rc_frame_qp & 0x3F;
+       writel(reg, mfc_regs->e_rc_config);
+
+       /* max & min value of QP */
+       reg = 0;
+       /** max QP */
+       reg |= ((p_h264->rc_max_qp & 0x3F) << 8);
+       /** min QP */
+       reg |= p_h264->rc_min_qp & 0x3F;
+       writel(reg, mfc_regs->e_rc_qp_bound);
+
+       /* other QPs */
+       writel(0x0, mfc_regs->e_fixed_picture_qp);
+       if (!p->rc_frame && !p->rc_mb) {
+               reg = 0;
+               reg |= ((p_h264->rc_b_frame_qp & 0x3F) << 16);
+               reg |= ((p_h264->rc_p_frame_qp & 0x3F) << 8);
+               reg |= p_h264->rc_frame_qp & 0x3F;
+               writel(reg, mfc_regs->e_fixed_picture_qp);
+       }
+
+       /* frame rate */
+       if (p->rc_frame && p->rc_framerate_num && p->rc_framerate_denom) {
+               reg = 0;
+               reg |= ((p->rc_framerate_num & 0xFFFF) << 16);
+               reg |= p->rc_framerate_denom & 0xFFFF;
+               writel(reg, mfc_regs->e_rc_frame_rate);
+       }
+
+       /* vbv buffer size */
+       if (p->frame_skip_mode ==
+                       V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
+               writel(p_h264->cpb_size & 0xFFFF,
+                               mfc_regs->e_vbv_buffer_size);
+
+               if (p->rc_frame)
+                       writel(p->vbv_delay, mfc_regs->e_vbv_init_delay);
+       }
+
+       /* interlace */
+       reg = 0;
+       reg |= ((p_h264->interlace & 0x1) << 3);
+       writel(reg, mfc_regs->e_h264_options);
+
+       /* height */
+       if (p_h264->interlace) {
+               writel(ctx->img_height >> 1,
+                               mfc_regs->e_frame_height); /* 32 align */
+               /* cropped height */
+               writel(ctx->img_height >> 1,
+                               mfc_regs->e_cropped_frame_height);
+       }
+
+       /* loop filter ctrl */
+       reg = readl(mfc_regs->e_h264_options);
+       reg &= ~(0x3 << 1);
+       reg |= ((p_h264->loop_filter_mode & 0x3) << 1);
+       writel(reg, mfc_regs->e_h264_options);
+
+       /* loopfilter alpha offset */
+       if (p_h264->loop_filter_alpha < 0) {
+               reg = 0x10;
+               reg |= (0xFF - p_h264->loop_filter_alpha) + 1;
+       } else {
+               reg = 0x00;
+               reg |= (p_h264->loop_filter_alpha & 0xF);
+       }
+       writel(reg, mfc_regs->e_h264_lf_alpha_offset);
+
+       /* loopfilter beta offset */
+       if (p_h264->loop_filter_beta < 0) {
+               reg = 0x10;
+               reg |= (0xFF - p_h264->loop_filter_beta) + 1;
+       } else {
+               reg = 0x00;
+               reg |= (p_h264->loop_filter_beta & 0xF);
+       }
+       writel(reg, mfc_regs->e_h264_lf_beta_offset);
+
+       /* entropy coding mode */
+       reg = readl(mfc_regs->e_h264_options);
+       reg &= ~(0x1);
+       reg |= p_h264->entropy_mode & 0x1;
+       writel(reg, mfc_regs->e_h264_options);
+
+       /* number of ref. picture */
+       reg = readl(mfc_regs->e_h264_options);
+       reg &= ~(0x1 << 7);
+       reg |= (((p_h264->num_ref_pic_4p - 1) & 0x1) << 7);
+       writel(reg, mfc_regs->e_h264_options);
+
+       /* 8x8 transform enable */
+       reg = readl(mfc_regs->e_h264_options);
+       reg &= ~(0x3 << 12);
+       reg |= ((p_h264->_8x8_transform & 0x3) << 12);
+       writel(reg, mfc_regs->e_h264_options);
+
+       /* macroblock adaptive scaling features */
+       writel(0x0, mfc_regs->e_mb_rc_config);
+       if (p->rc_mb) {
+               reg = 0;
+               /** dark region */
+               reg |= ((p_h264->rc_mb_dark & 0x1) << 3);
+               /** smooth region */
+               reg |= ((p_h264->rc_mb_smooth & 0x1) << 2);
+               /** static region */
+               reg |= ((p_h264->rc_mb_static & 0x1) << 1);
+               /** high activity region */
+               reg |= p_h264->rc_mb_activity & 0x1;
+               writel(reg, mfc_regs->e_mb_rc_config);
+       }
+
+       /* aspect ratio VUI */
+       readl(mfc_regs->e_h264_options);
+       reg &= ~(0x1 << 5);
+       reg |= ((p_h264->vui_sar & 0x1) << 5);
+       writel(reg, mfc_regs->e_h264_options);
+
+       writel(0x0, mfc_regs->e_aspect_ratio);
+       writel(0x0, mfc_regs->e_extended_sar);
+       if (p_h264->vui_sar) {
+               /* aspect ration IDC */
+               reg = 0;
+               reg |= p_h264->vui_sar_idc & 0xFF;
+               writel(reg, mfc_regs->e_aspect_ratio);
+               if (p_h264->vui_sar_idc == 0xFF) {
+                       /* extended SAR */
+                       reg = 0;
+                       reg |= (p_h264->vui_ext_sar_width & 0xFFFF) << 16;
+                       reg |= p_h264->vui_ext_sar_height & 0xFFFF;
+                       writel(reg, mfc_regs->e_extended_sar);
+               }
+       }
+
+       /* intra picture period for H.264 open GOP */
+       /* control */
+       readl(mfc_regs->e_h264_options);
+       reg &= ~(0x1 << 4);
+       reg |= ((p_h264->open_gop & 0x1) << 4);
+       writel(reg, mfc_regs->e_h264_options);
+
+       /* value */
+       writel(0x0, mfc_regs->e_h264_i_period);
+       if (p_h264->open_gop) {
+               reg = 0;
+               reg |= p_h264->open_gop_size & 0xFFFF;
+               writel(reg, mfc_regs->e_h264_i_period);
+       }
+
+       /* 'WEIGHTED_BI_PREDICTION' for B is disable */
+       readl(mfc_regs->e_h264_options);
+       reg &= ~(0x3 << 9);
+       writel(reg, mfc_regs->e_h264_options);
+
+       /* 'CONSTRAINED_INTRA_PRED_ENABLE' is disable */
+       readl(mfc_regs->e_h264_options);
+       reg &= ~(0x1 << 14);
+       writel(reg, mfc_regs->e_h264_options);
+
+       /* ASO */
+       readl(mfc_regs->e_h264_options);
+       reg &= ~(0x1 << 6);
+       reg |= ((p_h264->aso & 0x1) << 6);
+       writel(reg, mfc_regs->e_h264_options);
+
+       /* hier qp enable */
+       readl(mfc_regs->e_h264_options);
+       reg &= ~(0x1 << 8);
+       reg |= ((p_h264->open_gop & 0x1) << 8);
+       writel(reg, mfc_regs->e_h264_options);
+       reg = 0;
+       if (p_h264->hier_qp && p_h264->hier_qp_layer) {
+               reg |= (p_h264->hier_qp_type & 0x1) << 0x3;
+               reg |= p_h264->hier_qp_layer & 0x7;
+               writel(reg, mfc_regs->e_h264_num_t_layer);
+               /* QP value for each layer */
+               for (i = 0; i < p_h264->hier_qp_layer &&
+                               i < ARRAY_SIZE(p_h264->hier_qp_layer_qp); i++) {
+                       writel(p_h264->hier_qp_layer_qp[i],
+                               mfc_regs->e_h264_hierarchical_qp_layer0
+                               + i * 4);
+               }
+       }
+       /* number of coding layer should be zero when hierarchical is disable */
+       writel(reg, mfc_regs->e_h264_num_t_layer);
+
+       /* frame packing SEI generation */
+       readl(mfc_regs->e_h264_options);
+       reg &= ~(0x1 << 25);
+       reg |= ((p_h264->sei_frame_packing & 0x1) << 25);
+       writel(reg, mfc_regs->e_h264_options);
+       if (p_h264->sei_frame_packing) {
+               reg = 0;
+               /** current frame0 flag */
+               reg |= ((p_h264->sei_fp_curr_frame_0 & 0x1) << 2);
+               /** arrangement type */
+               reg |= p_h264->sei_fp_arrangement_type & 0x3;
+               writel(reg, mfc_regs->e_h264_frame_packing_sei_info);
+       }
+
+       if (p_h264->fmo) {
+               switch (p_h264->fmo_map_type) {
+               case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_INTERLEAVED_SLICES:
+                       if (p_h264->fmo_slice_grp > 4)
+                               p_h264->fmo_slice_grp = 4;
+                       for (i = 0; i < (p_h264->fmo_slice_grp & 0xF); i++)
+                               writel(p_h264->fmo_run_len[i] - 1,
+                                       mfc_regs->e_h264_fmo_run_length_minus1_0
+                                       + i * 4);
+                       break;
+               case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_SCATTERED_SLICES:
+                       if (p_h264->fmo_slice_grp > 4)
+                               p_h264->fmo_slice_grp = 4;
+                       break;
+               case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_RASTER_SCAN:
+               case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_WIPE_SCAN:
+                       if (p_h264->fmo_slice_grp > 2)
+                               p_h264->fmo_slice_grp = 2;
+                       writel(p_h264->fmo_chg_dir & 0x1,
+                               mfc_regs->e_h264_fmo_slice_grp_change_dir);
+                       /* the valid range is 0 ~ number of macroblocks -1 */
+                       writel(p_h264->fmo_chg_rate,
+                       mfc_regs->e_h264_fmo_slice_grp_change_rate_minus1);
+                       break;
+               default:
+                       mfc_err("Unsupported map type for FMO: %d\n",
+                                       p_h264->fmo_map_type);
+                       p_h264->fmo_map_type = 0;
+                       p_h264->fmo_slice_grp = 1;
+                       break;
+               }
+
+               writel(p_h264->fmo_map_type,
+                               mfc_regs->e_h264_fmo_slice_grp_map_type);
+               writel(p_h264->fmo_slice_grp - 1,
+                               mfc_regs->e_h264_fmo_num_slice_grp_minus1);
+       } else {
+               writel(0, mfc_regs->e_h264_fmo_num_slice_grp_minus1);
+       }
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs;
+       struct s5p_mfc_enc_params *p = &ctx->enc_params;
+       struct s5p_mfc_mpeg4_enc_params *p_mpeg4 = &p->codec.mpeg4;
+       unsigned int reg = 0;
+
+       mfc_debug_enter();
+
+       s5p_mfc_set_enc_params(ctx);
+
+       /* pictype : number of B */
+       reg = readl(mfc_regs->e_gop_config);
+       reg &= ~(0x3 << 16);
+       reg |= ((p->num_b_frame & 0x3) << 16);
+       writel(reg, mfc_regs->e_gop_config);
+
+       /* profile & level */
+       reg = 0;
+       /** level */
+       reg |= ((p_mpeg4->level & 0xFF) << 8);
+       /** profile - 0 ~ 1 */
+       reg |= p_mpeg4->profile & 0x3F;
+       writel(reg, mfc_regs->e_picture_profile);
+
+       /* rate control config. */
+       reg = readl(mfc_regs->e_rc_config);
+       /** macroblock level rate control */
+       reg &= ~(0x1 << 8);
+       reg |= ((p->rc_mb & 0x1) << 8);
+       writel(reg, mfc_regs->e_rc_config);
+
+       /** frame QP */
+       reg &= ~(0x3F);
+       reg |= p_mpeg4->rc_frame_qp & 0x3F;
+       writel(reg, mfc_regs->e_rc_config);
+
+       /* max & min value of QP */
+       reg = 0;
+       /** max QP */
+       reg |= ((p_mpeg4->rc_max_qp & 0x3F) << 8);
+       /** min QP */
+       reg |= p_mpeg4->rc_min_qp & 0x3F;
+       writel(reg, mfc_regs->e_rc_qp_bound);
+
+       /* other QPs */
+       writel(0x0, mfc_regs->e_fixed_picture_qp);
+       if (!p->rc_frame && !p->rc_mb) {
+               reg = 0;
+               reg |= ((p_mpeg4->rc_b_frame_qp & 0x3F) << 16);
+               reg |= ((p_mpeg4->rc_p_frame_qp & 0x3F) << 8);
+               reg |= p_mpeg4->rc_frame_qp & 0x3F;
+               writel(reg, mfc_regs->e_fixed_picture_qp);
+       }
+
+       /* frame rate */
+       if (p->rc_frame && p->rc_framerate_num && p->rc_framerate_denom) {
+               reg = 0;
+               reg |= ((p->rc_framerate_num & 0xFFFF) << 16);
+               reg |= p->rc_framerate_denom & 0xFFFF;
+               writel(reg, mfc_regs->e_rc_frame_rate);
+       }
+
+       /* vbv buffer size */
+       if (p->frame_skip_mode ==
+                       V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
+               writel(p->vbv_size & 0xFFFF, mfc_regs->e_vbv_buffer_size);
+
+               if (p->rc_frame)
+                       writel(p->vbv_delay, mfc_regs->e_vbv_init_delay);
+       }
+
+       /* Disable HEC */
+       writel(0x0, mfc_regs->e_mpeg4_options);
+       writel(0x0, mfc_regs->e_mpeg4_hec_period);
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+static int s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs;
+       struct s5p_mfc_enc_params *p = &ctx->enc_params;
+       struct s5p_mfc_mpeg4_enc_params *p_h263 = &p->codec.mpeg4;
+       unsigned int reg = 0;
+
+       mfc_debug_enter();
+
+       s5p_mfc_set_enc_params(ctx);
+
+       /* profile & level */
+       reg = 0;
+       /** profile */
+       reg |= (0x1 << 4);
+       writel(reg, mfc_regs->e_picture_profile);
+
+       /* rate control config. */
+       reg = readl(mfc_regs->e_rc_config);
+       /** macroblock level rate control */
+       reg &= ~(0x1 << 8);
+       reg |= ((p->rc_mb & 0x1) << 8);
+       writel(reg, mfc_regs->e_rc_config);
+
+       /** frame QP */
+       reg &= ~(0x3F);
+       reg |= p_h263->rc_frame_qp & 0x3F;
+       writel(reg, mfc_regs->e_rc_config);
+
+       /* max & min value of QP */
+       reg = 0;
+       /** max QP */
+       reg |= ((p_h263->rc_max_qp & 0x3F) << 8);
+       /** min QP */
+       reg |= p_h263->rc_min_qp & 0x3F;
+       writel(reg, mfc_regs->e_rc_qp_bound);
+
+       /* other QPs */
+       writel(0x0, mfc_regs->e_fixed_picture_qp);
+       if (!p->rc_frame && !p->rc_mb) {
+               reg = 0;
+               reg |= ((p_h263->rc_b_frame_qp & 0x3F) << 16);
+               reg |= ((p_h263->rc_p_frame_qp & 0x3F) << 8);
+               reg |= p_h263->rc_frame_qp & 0x3F;
+               writel(reg, mfc_regs->e_fixed_picture_qp);
+       }
+
+       /* frame rate */
+       if (p->rc_frame && p->rc_framerate_num && p->rc_framerate_denom) {
+               reg = 0;
+               reg |= ((p->rc_framerate_num & 0xFFFF) << 16);
+               reg |= p->rc_framerate_denom & 0xFFFF;
+               writel(reg, mfc_regs->e_rc_frame_rate);
+       }
+
+       /* vbv buffer size */
+       if (p->frame_skip_mode ==
+                       V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
+               writel(p->vbv_size & 0xFFFF, mfc_regs->e_vbv_buffer_size);
+
+               if (p->rc_frame)
+                       writel(p->vbv_delay, mfc_regs->e_vbv_init_delay);
+       }
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+static int s5p_mfc_set_enc_params_vp8(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs;
+       struct s5p_mfc_enc_params *p = &ctx->enc_params;
+       struct s5p_mfc_vp8_enc_params *p_vp8 = &p->codec.vp8;
+       unsigned int reg = 0;
+       unsigned int val = 0;
+
+       mfc_debug_enter();
+
+       s5p_mfc_set_enc_params(ctx);
+
+       /* pictype : number of B */
+       reg = readl(mfc_regs->e_gop_config);
+       reg &= ~(0x3 << 16);
+       reg |= ((p->num_b_frame & 0x3) << 16);
+       writel(reg, mfc_regs->e_gop_config);
+
+       /* profile - 0 ~ 3 */
+       reg = p_vp8->profile & 0x3;
+       writel(reg, mfc_regs->e_picture_profile);
+
+       /* rate control config. */
+       reg = readl(mfc_regs->e_rc_config);
+       /** macroblock level rate control */
+       reg &= ~(0x1 << 8);
+       reg |= ((p->rc_mb & 0x1) << 8);
+       writel(reg, mfc_regs->e_rc_config);
+
+       /* frame rate */
+       if (p->rc_frame && p->rc_framerate_num && p->rc_framerate_denom) {
+               reg = 0;
+               reg |= ((p->rc_framerate_num & 0xFFFF) << 16);
+               reg |= p->rc_framerate_denom & 0xFFFF;
+               writel(reg, mfc_regs->e_rc_frame_rate);
+       }
+
+       /* frame QP */
+       reg &= ~(0x7F);
+       reg |= p_vp8->rc_frame_qp & 0x7F;
+       writel(reg, mfc_regs->e_rc_config);
+
+       /* other QPs */
+       writel(0x0, mfc_regs->e_fixed_picture_qp);
+       if (!p->rc_frame && !p->rc_mb) {
+               reg = 0;
+               reg |= ((p_vp8->rc_p_frame_qp & 0x7F) << 8);
+               reg |= p_vp8->rc_frame_qp & 0x7F;
+               writel(reg, mfc_regs->e_fixed_picture_qp);
+       }
+
+       /* max QP */
+       reg = ((p_vp8->rc_max_qp & 0x7F) << 8);
+       /* min QP */
+       reg |= p_vp8->rc_min_qp & 0x7F;
+       writel(reg, mfc_regs->e_rc_qp_bound);
+
+       /* vbv buffer size */
+       if (p->frame_skip_mode ==
+                       V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
+               writel(p->vbv_size & 0xFFFF, mfc_regs->e_vbv_buffer_size);
+
+               if (p->rc_frame)
+                       writel(p->vbv_delay, mfc_regs->e_vbv_init_delay);
+       }
+
+       /* VP8 specific params */
+       reg = 0;
+       reg |= (p_vp8->imd_4x4 & 0x1) << 10;
+       switch (p_vp8->num_partitions) {
+       case V4L2_CID_MPEG_VIDEO_VPX_1_PARTITION:
+               val = 0;
+               break;
+       case V4L2_CID_MPEG_VIDEO_VPX_2_PARTITIONS:
+               val = 2;
+               break;
+       case V4L2_CID_MPEG_VIDEO_VPX_4_PARTITIONS:
+               val = 4;
+               break;
+       case V4L2_CID_MPEG_VIDEO_VPX_8_PARTITIONS:
+               val = 8;
+               break;
+       }
+       reg |= (val & 0xF) << 3;
+       reg |= (p_vp8->num_ref & 0x2);
+       writel(reg, mfc_regs->e_vp8_options);
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+static int s5p_mfc_set_enc_params_hevc(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs;
+       struct s5p_mfc_enc_params *p = &ctx->enc_params;
+       struct s5p_mfc_hevc_enc_params *p_hevc = &p->codec.hevc;
+       unsigned int reg = 0;
+       int i;
+
+       mfc_debug_enter();
+
+       s5p_mfc_set_enc_params(ctx);
+
+       /* pictype : number of B */
+       reg = readl(mfc_regs->e_gop_config);
+       /* num_b_frame - 0 ~ 2 */
+       reg &= ~(0x3 << 16);
+       reg |= (p->num_b_frame << 16);
+       writel(reg, mfc_regs->e_gop_config);
+
+       /* UHD encoding case */
+       if ((ctx->img_width == 3840) && (ctx->img_height == 2160)) {
+               p_hevc->level = 51;
+               p_hevc->tier = 0;
+       /* this tier can be changed */
+       }
+
+       /* tier & level */
+       reg = 0;
+       /* profile */
+       reg |= p_hevc->profile & 0x3;
+       /* level */
+       reg &= ~(0xFF << 8);
+       reg |= (p_hevc->level << 8);
+       /* tier - 0 ~ 1 */
+       reg |= (p_hevc->tier << 16);
+       writel(reg, mfc_regs->e_picture_profile);
+
+       switch (p_hevc->loopfilter) {
+       case V4L2_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE_DISABLED:
+               p_hevc->loopfilter_disable = 1;
+               break;
+       case V4L2_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE_ENABLED:
+               p_hevc->loopfilter_disable = 0;
+               p_hevc->loopfilter_across = 1;
+               break;
+       case V4L2_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY:
+               p_hevc->loopfilter_disable = 0;
+               p_hevc->loopfilter_across = 0;
+               break;
+       }
+
+       /* max partition depth */
+       reg = 0;
+       reg |= (p_hevc->max_partition_depth & 0x1);
+       reg |= (p_hevc->num_refs_for_p-1) << 2;
+       reg |= (p_hevc->refreshtype & 0x3) << 3;
+       reg |= (p_hevc->const_intra_period_enable & 0x1) << 5;
+       reg |= (p_hevc->lossless_cu_enable & 0x1) << 6;
+       reg |= (p_hevc->wavefront_enable & 0x1) << 7;
+       reg |= (p_hevc->loopfilter_disable & 0x1) << 8;
+       reg |= (p_hevc->loopfilter_across & 0x1) << 9;
+       reg |= (p_hevc->enable_ltr & 0x1) << 10;
+       reg |= (p_hevc->hier_qp_enable & 0x1) << 11;
+       reg |= (p_hevc->general_pb_enable & 0x1) << 13;
+       reg |= (p_hevc->temporal_id_enable & 0x1) << 14;
+       reg |= (p_hevc->strong_intra_smooth & 0x1) << 15;
+       reg |= (p_hevc->intra_pu_split_disable & 0x1) << 16;
+       reg |= (p_hevc->tmv_prediction_disable & 0x1) << 17;
+       reg |= (p_hevc->max_num_merge_mv & 0x7) << 18;
+       reg |= (p_hevc->encoding_nostartcode_enable & 0x1) << 23;
+       reg |= (p_hevc->prepend_sps_pps_to_idr << 26);
+
+       writel(reg, mfc_regs->e_hevc_options);
+       /* refresh period */
+       if (p_hevc->refreshtype) {
+               reg = 0;
+               reg |= (p_hevc->refreshperiod & 0xFFFF);
+               writel(reg, mfc_regs->e_hevc_refresh_period);
+       }
+       /* loop filter setting */
+       if (!(p_hevc->loopfilter_disable & 0x1)) {
+               reg = 0;
+               reg |= (p_hevc->lf_beta_offset_div2);
+               writel(reg, mfc_regs->e_hevc_lf_beta_offset_div2);
+               reg = 0;
+               reg |= (p_hevc->lf_tc_offset_div2);
+               writel(reg, mfc_regs->e_hevc_lf_tc_offset_div2);
+       }
+       /* hier qp enable */
+       if (p_hevc->num_hier_layer) {
+               reg = 0;
+               reg |= (p_hevc->hier_qp_type & 0x1) << 0x3;
+               reg |= p_hevc->num_hier_layer & 0x7;
+               writel(reg, mfc_regs->e_num_t_layer);
+               /* QP value for each layer */
+               if (p_hevc->hier_qp_enable) {
+                       for (i = 0; i < 7; i++)
+                               writel(p_hevc->hier_qp_layer[i],
+                                       mfc_regs->e_hier_qp_layer0 + i * 4);
+               }
+               if (p->rc_frame) {
+                       for (i = 0; i < 7; i++)
+                               writel(p_hevc->hier_bit_layer[i],
+                                               mfc_regs->e_hier_bit_rate_layer0
+                                               + i * 4);
+               }
+       }
+
+       /* rate control config. */
+       reg = readl(mfc_regs->e_rc_config);
+       /* macroblock level rate control */
+       reg &= ~(0x1 << 8);
+       reg |= (p->rc_mb << 8);
+       writel(reg, mfc_regs->e_rc_config);
+       /* frame QP */
+       reg &= ~(0xFF);
+       reg |= p_hevc->rc_frame_qp;
+       writel(reg, mfc_regs->e_rc_config);
+
+       /* frame rate */
+       if (p->rc_frame) {
+               reg = 0;
+               reg &= ~(0xFFFF << 16);
+               reg |= ((p_hevc->rc_framerate) << 16);
+               reg &= ~(0xFFFF);
+               reg |= FRAME_DELTA_DEFAULT;
+               writel(reg, mfc_regs->e_rc_frame_rate);
+       }
+
+       /* max & min value of QP */
+       reg = 0;
+       /* max QP */
+       reg &= ~(0xFF << 8);
+       reg |= (p_hevc->rc_max_qp << 8);
+       /* min QP */
+       reg &= ~(0xFF);
+       reg |= p_hevc->rc_min_qp;
+       writel(reg, mfc_regs->e_rc_qp_bound);
+
+       writel(0x0, mfc_regs->e_fixed_picture_qp);
+       if (!p->rc_frame && !p->rc_mb) {
+               reg = 0;
+               reg &= ~(0xFF << 16);
+               reg |= (p_hevc->rc_b_frame_qp << 16);
+               reg &= ~(0xFF << 8);
+               reg |= (p_hevc->rc_p_frame_qp << 8);
+               reg &= ~(0xFF);
+               reg |= p_hevc->rc_frame_qp;
+               writel(reg, mfc_regs->e_fixed_picture_qp);
+       }
+       mfc_debug_leave();
+
+       return 0;
+}
+
+/* Initialize decoding */
+static int s5p_mfc_init_decode_v6(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs;
+       unsigned int reg = 0;
+       int fmo_aso_ctrl = 0;
+
+       mfc_debug_enter();
+       mfc_debug(2, "InstNo: %d/%d\n", ctx->inst_no,
+                       S5P_FIMV_CH_SEQ_HEADER_V6);
+       mfc_debug(2, "BUFs: %08x %08x %08x\n",
+                 readl(mfc_regs->d_cpb_buffer_addr),
+                 readl(mfc_regs->d_cpb_buffer_addr),
+                 readl(mfc_regs->d_cpb_buffer_addr));
+
+       /* FMO_ASO_CTRL - 0: Enable, 1: Disable */
+       reg |= (fmo_aso_ctrl << S5P_FIMV_D_OPT_FMO_ASO_CTRL_MASK_V6);
+
+       if (ctx->display_delay_enable) {
+               reg |= (0x1 << S5P_FIMV_D_OPT_DDELAY_EN_SHIFT_V6);
+               writel(ctx->display_delay, mfc_regs->d_display_delay);
+       }
+
+       if (IS_MFCV7_PLUS(dev) || IS_MFCV6_V2(dev)) {
+               writel(reg, mfc_regs->d_dec_options);
+               reg = 0;
+       }
+
+       /* Setup loop filter, for decoding this is only valid for MPEG4 */
+       if (ctx->codec_mode == S5P_MFC_CODEC_MPEG4_DEC) {
+               mfc_debug(2, "Set loop filter to: %d\n",
+                               ctx->loop_filter_mpeg4);
+               reg |= (ctx->loop_filter_mpeg4 <<
+                               S5P_FIMV_D_OPT_LF_CTRL_SHIFT_V6);
+       }
+       if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16)
+               reg |= (0x1 << S5P_FIMV_D_OPT_TILE_MODE_SHIFT_V6);
+
+       if (IS_MFCV7_PLUS(dev) || IS_MFCV6_V2(dev))
+               writel(reg, mfc_regs->d_init_buffer_options);
+       else
+               writel(reg, mfc_regs->d_dec_options);
+
+       /* 0: NV12(CbCr), 1: NV21(CrCb) */
+       if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_NV21M)
+               writel(0x1, mfc_regs->pixel_format);
+       else
+               writel(0x0, mfc_regs->pixel_format);
+
+
+       /* sei parse */
+       writel(ctx->sei_fp_parse & 0x1, mfc_regs->d_sei_enable);
+
+       writel(ctx->inst_no, mfc_regs->instance_id);
+       s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev,
+                       S5P_FIMV_CH_SEQ_HEADER_V6, NULL);
+
+       mfc_debug_leave();
+       return 0;
+}
+
+static inline void s5p_mfc_set_flush(struct s5p_mfc_ctx *ctx, int flush)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs;
+
+       if (flush) {
+               dev->curr_ctx = ctx->num;
+               writel(ctx->inst_no, mfc_regs->instance_id);
+               s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev,
+                               S5P_FIMV_H2R_CMD_FLUSH_V6, NULL);
+       }
+}
+
+/* Decode a single frame */
+static int s5p_mfc_decode_one_frame_v6(struct s5p_mfc_ctx *ctx,
+                       enum s5p_mfc_decode_arg last_frame)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs;
+
+       writel(ctx->dec_dst_flag, mfc_regs->d_available_dpb_flag_lower);
+       writel(ctx->slice_interface & 0x1, mfc_regs->d_slice_if_enable);
+
+       writel(ctx->inst_no, mfc_regs->instance_id);
+       /* Issue different commands to instance basing on whether it
+        * is the last frame or not. */
+       switch (last_frame) {
+       case 0:
+               s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev,
+                               S5P_FIMV_CH_FRAME_START_V6, NULL);
+               break;
+       case 1:
+               s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev,
+                               S5P_FIMV_CH_LAST_FRAME_V6, NULL);
+               break;
+       default:
+               mfc_err("Unsupported last frame arg.\n");
+               return -EINVAL;
+       }
+
+       mfc_debug(2, "Decoding a usual frame.\n");
+       return 0;
+}
+
+static int s5p_mfc_init_encode_v6(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs;
+
+       if (ctx->codec_mode == S5P_MFC_CODEC_H264_ENC)
+               s5p_mfc_set_enc_params_h264(ctx);
+       else if (ctx->codec_mode == S5P_MFC_CODEC_MPEG4_ENC)
+               s5p_mfc_set_enc_params_mpeg4(ctx);
+       else if (ctx->codec_mode == S5P_MFC_CODEC_H263_ENC)
+               s5p_mfc_set_enc_params_h263(ctx);
+       else if (ctx->codec_mode == S5P_MFC_CODEC_VP8_ENC)
+               s5p_mfc_set_enc_params_vp8(ctx);
+       else if (ctx->codec_mode == S5P_FIMV_CODEC_HEVC_ENC)
+               s5p_mfc_set_enc_params_hevc(ctx);
+       else {
+               mfc_err("Unknown codec for encoding (%x).\n",
+                       ctx->codec_mode);
+               return -EINVAL;
+       }
+
+       /* Set stride lengths for v7 & above */
+       if (IS_MFCV7_PLUS(dev)) {
+               writel(ctx->img_width, mfc_regs->e_source_first_plane_stride);
+               writel(ctx->img_width, mfc_regs->e_source_second_plane_stride);
+       }
+
+       writel(ctx->inst_no, mfc_regs->instance_id);
+       s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev,
+                       S5P_FIMV_CH_SEQ_HEADER_V6, NULL);
+
+       return 0;
+}
+
+static int s5p_mfc_h264_set_aso_slice_order_v6(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs;
+       struct s5p_mfc_enc_params *p = &ctx->enc_params;
+       struct s5p_mfc_h264_enc_params *p_h264 = &p->codec.h264;
+       int i;
+
+       if (p_h264->aso) {
+               for (i = 0; i < ARRAY_SIZE(p_h264->aso_slice_order); i++) {
+                       writel(p_h264->aso_slice_order[i],
+                               mfc_regs->e_h264_aso_slice_order_0 + i * 4);
+               }
+       }
+       return 0;
+}
+
+/* Encode a single frame */
+static int s5p_mfc_encode_one_frame_v6(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs;
+       int cmd;
+
+       mfc_debug(2, "++\n");
+
+       /* memory structure cur. frame */
+
+       if (ctx->codec_mode == S5P_MFC_CODEC_H264_ENC)
+               s5p_mfc_h264_set_aso_slice_order_v6(ctx);
+
+       s5p_mfc_set_slice_mode(ctx);
+
+       if (ctx->state != MFCINST_FINISHING)
+               cmd = S5P_FIMV_CH_FRAME_START_V6;
+       else
+               cmd = S5P_FIMV_CH_LAST_FRAME_V6;
+
+       writel(ctx->inst_no, mfc_regs->instance_id);
+       s5p_mfc_hw_call(dev->mfc_cmds, cmd_host2risc, dev, cmd, NULL);
+
+       mfc_debug(2, "--\n");
+
+       return 0;
+}
+
+static inline void s5p_mfc_run_dec_last_frames(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       s5p_mfc_set_dec_stream_buffer_v6(ctx, 0, 0, 0);
+       dev->curr_ctx = ctx->num;
+       s5p_mfc_decode_one_frame_v6(ctx, MFC_DEC_LAST_FRAME);
+}
+
+static inline int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_buf *temp_vb;
+       int last_frame = 0;
+
+       if (ctx->state == MFCINST_FINISHING) {
+               last_frame = MFC_DEC_LAST_FRAME;
+               s5p_mfc_set_dec_stream_buffer_v6(ctx, 0, 0, 0);
+               dev->curr_ctx = ctx->num;
+               s5p_mfc_clean_ctx_int_flags(ctx);
+               s5p_mfc_decode_one_frame_v6(ctx, last_frame);
+               return 0;
+       }
+
+       /* Frames are being decoded */
+       if (list_empty(&ctx->src_queue)) {
+               mfc_debug(2, "No src buffers.\n");
+               return -EAGAIN;
+       }
+       /* Get the next source buffer */
+       temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
+       temp_vb->flags |= MFC_BUF_FLAG_USED;
+       s5p_mfc_set_dec_stream_buffer_v6(ctx,
+               vb2_dma_contig_plane_dma_addr(&temp_vb->b->vb2_buf, 0),
+                       ctx->consumed_stream,
+                       temp_vb->b->vb2_buf.planes[0].bytesused);
+
+       dev->curr_ctx = ctx->num;
+       if (temp_vb->b->vb2_buf.planes[0].bytesused == 0) {
+               last_frame = 1;
+               mfc_debug(2, "Setting ctx->state to FINISHING\n");
+               ctx->state = MFCINST_FINISHING;
+       }
+       s5p_mfc_decode_one_frame_v6(ctx, last_frame);
+
+       return 0;
+}
+
+static inline int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_buf *dst_mb;
+       struct s5p_mfc_buf *src_mb;
+       unsigned long src_y_addr, src_c_addr, dst_addr;
+       /*
+       unsigned int src_y_size, src_c_size;
+       */
+       unsigned int dst_size;
+
+       if (list_empty(&ctx->src_queue) && ctx->state != MFCINST_FINISHING) {
+               mfc_debug(2, "no src buffers.\n");
+               return -EAGAIN;
+       }
+
+       if (list_empty(&ctx->dst_queue)) {
+               mfc_debug(2, "no dst buffers.\n");
+               return -EAGAIN;
+       }
+
+       if (list_empty(&ctx->src_queue)) {
+               /* send null frame */
+               s5p_mfc_set_enc_frame_buffer_v6(ctx, 0, 0);
+               src_mb = NULL;
+       } else {
+               src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
+               src_mb->flags |= MFC_BUF_FLAG_USED;
+               if (src_mb->b->vb2_buf.planes[0].bytesused == 0) {
+                       s5p_mfc_set_enc_frame_buffer_v6(ctx, 0, 0);
+                       ctx->state = MFCINST_FINISHING;
+               } else {
+                       src_y_addr = vb2_dma_contig_plane_dma_addr(&src_mb->b->vb2_buf, 0);
+                       src_c_addr = vb2_dma_contig_plane_dma_addr(&src_mb->b->vb2_buf, 1);
+
+                       mfc_debug(2, "enc src y addr: 0x%08lx\n", src_y_addr);
+                       mfc_debug(2, "enc src c addr: 0x%08lx\n", src_c_addr);
+
+                       s5p_mfc_set_enc_frame_buffer_v6(ctx, src_y_addr, src_c_addr);
+                       if (src_mb->flags & MFC_BUF_FLAG_EOS)
+                               ctx->state = MFCINST_FINISHING;
+               }
+       }
+
+       dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
+       dst_mb->flags |= MFC_BUF_FLAG_USED;
+       dst_addr = vb2_dma_contig_plane_dma_addr(&dst_mb->b->vb2_buf, 0);
+       dst_size = vb2_plane_size(&dst_mb->b->vb2_buf, 0);
+
+       s5p_mfc_set_enc_stream_buffer_v6(ctx, dst_addr, dst_size);
+
+       dev->curr_ctx = ctx->num;
+       s5p_mfc_encode_one_frame_v6(ctx);
+
+       return 0;
+}
+
+static inline void s5p_mfc_run_init_dec(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_buf *temp_vb;
+
+       /* Initializing decoding - parsing header */
+       mfc_debug(2, "Preparing to init decoding.\n");
+       temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
+       mfc_debug(2, "Header size: %d\n", temp_vb->b->vb2_buf.planes[0].bytesused);
+       s5p_mfc_set_dec_stream_buffer_v6(ctx,
+               vb2_dma_contig_plane_dma_addr(&temp_vb->b->vb2_buf, 0), 0,
+                       temp_vb->b->vb2_buf.planes[0].bytesused);
+       dev->curr_ctx = ctx->num;
+       s5p_mfc_init_decode_v6(ctx);
+}
+
+static inline void s5p_mfc_run_init_enc(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_buf *dst_mb;
+       unsigned long dst_addr;
+       unsigned int dst_size;
+
+       dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
+       dst_addr = vb2_dma_contig_plane_dma_addr(&dst_mb->b->vb2_buf, 0);
+       dst_size = vb2_plane_size(&dst_mb->b->vb2_buf, 0);
+       s5p_mfc_set_enc_stream_buffer_v6(ctx, dst_addr, dst_size);
+       dev->curr_ctx = ctx->num;
+       s5p_mfc_init_encode_v6(ctx);
+}
+
+static inline int s5p_mfc_run_init_dec_buffers(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       int ret;
+       /* Header was parsed now start processing
+        * First set the output frame buffers
+        * s5p_mfc_alloc_dec_buffers(ctx); */
+
+       if (ctx->capture_state != QUEUE_BUFS_MMAPED) {
+               mfc_err("It seems that not all destination buffers were\n"
+                       "mmapped.MFC requires that all destination are mmapped\n"
+                       "before starting processing.\n");
+               return -EAGAIN;
+       }
+
+       dev->curr_ctx = ctx->num;
+       ret = s5p_mfc_set_dec_frame_buffer_v6(ctx);
+       if (ret) {
+               mfc_err("Failed to alloc frame mem.\n");
+               ctx->state = MFCINST_ERROR;
+       }
+       return ret;
+}
+
+static inline int s5p_mfc_run_init_enc_buffers(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       int ret;
+
+       dev->curr_ctx = ctx->num;
+       ret = s5p_mfc_set_enc_ref_buffer_v6(ctx);
+       if (ret) {
+               mfc_err("Failed to alloc frame mem.\n");
+               ctx->state = MFCINST_ERROR;
+       }
+       return ret;
+}
+
+/* Try running an operation on hardware */
+static void s5p_mfc_try_run_v6(struct s5p_mfc_dev *dev)
+{
+       struct s5p_mfc_ctx *ctx;
+       int new_ctx;
+       unsigned int ret = 0;
+
+       mfc_debug(1, "Try run dev: %p\n", dev);
+
+       /* Check whether hardware is not running */
+       if (test_and_set_bit(0, &dev->hw_lock) != 0) {
+               /* This is perfectly ok, the scheduled ctx should wait */
+               mfc_debug(1, "Couldn't lock HW.\n");
+               return;
+       }
+
+       /* Choose the context to run */
+       new_ctx = s5p_mfc_get_new_ctx(dev);
+       if (new_ctx < 0) {
+               /* No contexts to run */
+               if (test_and_clear_bit(0, &dev->hw_lock) == 0) {
+                       mfc_err("Failed to unlock hardware.\n");
+                       return;
+               }
+
+               mfc_debug(1, "No ctx is scheduled to be run.\n");
+               return;
+       }
+
+       mfc_debug(1, "New context: %d\n", new_ctx);
+       ctx = dev->ctx[new_ctx];
+       mfc_debug(1, "Setting new context to %p\n", ctx);
+       /* Got context to run in ctx */
+       mfc_debug(1, "ctx->dst_queue_cnt=%d ctx->dpb_count=%d ctx->src_queue_cnt=%d\n",
+               ctx->dst_queue_cnt, ctx->pb_count, ctx->src_queue_cnt);
+       mfc_debug(1, "ctx->state=%d\n", ctx->state);
+       /* Last frame has already been sent to MFC
+        * Now obtaining frames from MFC buffer */
+
+       s5p_mfc_clock_on();
+       s5p_mfc_clean_ctx_int_flags(ctx);
+
+       if (ctx->type == MFCINST_DECODER) {
+               switch (ctx->state) {
+               case MFCINST_FINISHING:
+                       s5p_mfc_run_dec_last_frames(ctx);
+                       break;
+               case MFCINST_RUNNING:
+                       ret = s5p_mfc_run_dec_frame(ctx);
+                       break;
+               case MFCINST_INIT:
+                       ret = s5p_mfc_hw_call(dev->mfc_cmds, open_inst_cmd,
+                                       ctx);
+                       break;
+               case MFCINST_RETURN_INST:
+                       ret = s5p_mfc_hw_call(dev->mfc_cmds, close_inst_cmd,
+                                       ctx);
+                       break;
+               case MFCINST_GOT_INST:
+                       s5p_mfc_run_init_dec(ctx);
+                       break;
+               case MFCINST_HEAD_PARSED:
+                       ret = s5p_mfc_run_init_dec_buffers(ctx);
+                       break;
+               case MFCINST_FLUSH:
+                       s5p_mfc_set_flush(ctx, ctx->dpb_flush_flag);
+                       break;
+               case MFCINST_RES_CHANGE_INIT:
+                       s5p_mfc_run_dec_last_frames(ctx);
+                       break;
+               case MFCINST_RES_CHANGE_FLUSH:
+                       s5p_mfc_run_dec_last_frames(ctx);
+                       break;
+               case MFCINST_RES_CHANGE_END:
+                       mfc_debug(2, "Finished remaining frames after resolution change.\n");
+                       ctx->capture_state = QUEUE_FREE;
+                       mfc_debug(2, "Will re-init the codec`.\n");
+                       s5p_mfc_run_init_dec(ctx);
+                       break;
+               default:
+                       ret = -EAGAIN;
+               }
+       } else if (ctx->type == MFCINST_ENCODER) {
+               switch (ctx->state) {
+               case MFCINST_FINISHING:
+               case MFCINST_RUNNING:
+                       ret = s5p_mfc_run_enc_frame(ctx);
+                       break;
+               case MFCINST_INIT:
+                       ret = s5p_mfc_hw_call(dev->mfc_cmds, open_inst_cmd,
+                                       ctx);
+                       break;
+               case MFCINST_RETURN_INST:
+                       ret = s5p_mfc_hw_call(dev->mfc_cmds, close_inst_cmd,
+                                       ctx);
+                       break;
+               case MFCINST_GOT_INST:
+                       s5p_mfc_run_init_enc(ctx);
+                       break;
+               case MFCINST_HEAD_PRODUCED:
+                       ret = s5p_mfc_run_init_enc_buffers(ctx);
+                       break;
+               default:
+                       ret = -EAGAIN;
+               }
+       } else {
+               mfc_err("invalid context type: %d\n", ctx->type);
+               ret = -EAGAIN;
+       }
+
+       if (ret) {
+               /* Free hardware lock */
+               if (test_and_clear_bit(0, &dev->hw_lock) == 0)
+                       mfc_err("Failed to unlock hardware.\n");
+
+               /* This is in deed imporant, as no operation has been
+                * scheduled, reduce the clock count as no one will
+                * ever do this, because no interrupt related to this try_run
+                * will ever come from hardware. */
+               s5p_mfc_clock_off();
+       }
+}
+
+static void s5p_mfc_clear_int_flags_v6(struct s5p_mfc_dev *dev)
+{
+       const struct s5p_mfc_regs *mfc_regs = dev->mfc_regs;
+       writel(0, mfc_regs->risc2host_command);
+       writel(0, mfc_regs->risc2host_int);
+}
+
+static unsigned int
+s5p_mfc_read_info_v6(struct s5p_mfc_ctx *ctx, unsigned long ofs)
+{
+       int ret;
+
+       s5p_mfc_clock_on();
+       ret = readl((void __iomem *)ofs);
+       s5p_mfc_clock_off();
+
+       return ret;
+}
+
+static int s5p_mfc_get_dspl_y_adr_v6(struct s5p_mfc_dev *dev)
+{
+       return readl(dev->mfc_regs->d_display_first_plane_addr);
+}
+
+static int s5p_mfc_get_dec_y_adr_v6(struct s5p_mfc_dev *dev)
+{
+       return readl(dev->mfc_regs->d_decoded_first_plane_addr);
+}
+
+static int s5p_mfc_get_dspl_status_v6(struct s5p_mfc_dev *dev)
+{
+       return readl(dev->mfc_regs->d_display_status);
+}
+
+static int s5p_mfc_get_dec_status_v6(struct s5p_mfc_dev *dev)
+{
+       return readl(dev->mfc_regs->d_decoded_status);
+}
+
+static int s5p_mfc_get_dec_frame_type_v6(struct s5p_mfc_dev *dev)
+{
+       return readl(dev->mfc_regs->d_decoded_frame_type) &
+               S5P_FIMV_DECODE_FRAME_MASK_V6;
+}
+
+static int s5p_mfc_get_disp_frame_type_v6(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       return readl(dev->mfc_regs->d_display_frame_type) &
+               S5P_FIMV_DECODE_FRAME_MASK_V6;
+}
+
+static int s5p_mfc_get_consumed_stream_v6(struct s5p_mfc_dev *dev)
+{
+       return readl(dev->mfc_regs->d_decoded_nal_size);
+}
+
+static int s5p_mfc_get_int_reason_v6(struct s5p_mfc_dev *dev)
+{
+       return readl(dev->mfc_regs->risc2host_command) &
+               S5P_FIMV_RISC2HOST_CMD_MASK;
+}
+
+static int s5p_mfc_get_int_err_v6(struct s5p_mfc_dev *dev)
+{
+       return readl(dev->mfc_regs->error_code);
+}
+
+static int s5p_mfc_err_dec_v6(unsigned int err)
+{
+       return (err & S5P_FIMV_ERR_DEC_MASK_V6) >> S5P_FIMV_ERR_DEC_SHIFT_V6;
+}
+
+static int s5p_mfc_get_img_width_v6(struct s5p_mfc_dev *dev)
+{
+       return readl(dev->mfc_regs->d_display_frame_width);
+}
+
+static int s5p_mfc_get_img_height_v6(struct s5p_mfc_dev *dev)
+{
+       return readl(dev->mfc_regs->d_display_frame_height);
+}
+
+static int s5p_mfc_get_dpb_count_v6(struct s5p_mfc_dev *dev)
+{
+       return readl(dev->mfc_regs->d_min_num_dpb);
+}
+
+static int s5p_mfc_get_mv_count_v6(struct s5p_mfc_dev *dev)
+{
+       return readl(dev->mfc_regs->d_min_num_mv);
+}
+
+static int s5p_mfc_get_min_scratch_buf_size(struct s5p_mfc_dev *dev)
+{
+       return readl(dev->mfc_regs->d_min_scratch_buffer_size);
+}
+
+static int s5p_mfc_get_e_min_scratch_buf_size(struct s5p_mfc_dev *dev)
+{
+       return readl(dev->mfc_regs->e_min_scratch_buffer_size);
+}
+
+static int s5p_mfc_get_inst_no_v6(struct s5p_mfc_dev *dev)
+{
+       return readl(dev->mfc_regs->ret_instance_id);
+}
+
+static int s5p_mfc_get_enc_dpb_count_v6(struct s5p_mfc_dev *dev)
+{
+       return readl(dev->mfc_regs->e_num_dpb);
+}
+
+static int s5p_mfc_get_enc_strm_size_v6(struct s5p_mfc_dev *dev)
+{
+       return readl(dev->mfc_regs->e_stream_size);
+}
+
+static int s5p_mfc_get_enc_slice_type_v6(struct s5p_mfc_dev *dev)
+{
+       return readl(dev->mfc_regs->e_slice_type);
+}
+
+static unsigned int s5p_mfc_get_pic_type_top_v6(struct s5p_mfc_ctx *ctx)
+{
+       return s5p_mfc_read_info_v6(ctx,
+               (__force unsigned long) ctx->dev->mfc_regs->d_ret_picture_tag_top);
+}
+
+static unsigned int s5p_mfc_get_pic_type_bot_v6(struct s5p_mfc_ctx *ctx)
+{
+       return s5p_mfc_read_info_v6(ctx,
+               (__force unsigned long) ctx->dev->mfc_regs->d_ret_picture_tag_bot);
+}
+
+static unsigned int s5p_mfc_get_crop_info_h_v6(struct s5p_mfc_ctx *ctx)
+{
+       return s5p_mfc_read_info_v6(ctx,
+               (__force unsigned long) ctx->dev->mfc_regs->d_display_crop_info1);
+}
+
+static unsigned int s5p_mfc_get_crop_info_v_v6(struct s5p_mfc_ctx *ctx)
+{
+       return s5p_mfc_read_info_v6(ctx,
+               (__force unsigned long) ctx->dev->mfc_regs->d_display_crop_info2);
+}
+
+static struct s5p_mfc_regs mfc_regs;
+
+/* Initialize registers for MFC v6 onwards */
+const struct s5p_mfc_regs *s5p_mfc_init_regs_v6_plus(struct s5p_mfc_dev *dev)
+{
+       memset(&mfc_regs, 0, sizeof(mfc_regs));
+
+#define S5P_MFC_REG_ADDR(dev, reg) ((dev)->regs_base + (reg))
+#define R(m, r) mfc_regs.m = S5P_MFC_REG_ADDR(dev, r)
+       /* codec common registers */
+       R(risc_on, S5P_FIMV_RISC_ON_V6);
+       R(risc2host_int, S5P_FIMV_RISC2HOST_INT_V6);
+       R(host2risc_int, S5P_FIMV_HOST2RISC_INT_V6);
+       R(risc_base_address, S5P_FIMV_RISC_BASE_ADDRESS_V6);
+       R(mfc_reset, S5P_FIMV_MFC_RESET_V6);
+       R(host2risc_command, S5P_FIMV_HOST2RISC_CMD_V6);
+       R(risc2host_command, S5P_FIMV_RISC2HOST_CMD_V6);
+       R(firmware_version, S5P_FIMV_FW_VERSION_V6);
+       R(instance_id, S5P_FIMV_INSTANCE_ID_V6);
+       R(codec_type, S5P_FIMV_CODEC_TYPE_V6);
+       R(context_mem_addr, S5P_FIMV_CONTEXT_MEM_ADDR_V6);
+       R(context_mem_size, S5P_FIMV_CONTEXT_MEM_SIZE_V6);
+       R(pixel_format, S5P_FIMV_PIXEL_FORMAT_V6);
+       R(ret_instance_id, S5P_FIMV_RET_INSTANCE_ID_V6);
+       R(error_code, S5P_FIMV_ERROR_CODE_V6);
+
+       /* decoder registers */
+       R(d_crc_ctrl, S5P_FIMV_D_CRC_CTRL_V6);
+       R(d_dec_options, S5P_FIMV_D_DEC_OPTIONS_V6);
+       R(d_display_delay, S5P_FIMV_D_DISPLAY_DELAY_V6);
+       R(d_sei_enable, S5P_FIMV_D_SEI_ENABLE_V6);
+       R(d_min_num_dpb, S5P_FIMV_D_MIN_NUM_DPB_V6);
+       R(d_min_num_mv, S5P_FIMV_D_MIN_NUM_MV_V6);
+       R(d_mvc_num_views, S5P_FIMV_D_MVC_NUM_VIEWS_V6);
+       R(d_num_dpb, S5P_FIMV_D_NUM_DPB_V6);
+       R(d_num_mv, S5P_FIMV_D_NUM_MV_V6);
+       R(d_init_buffer_options, S5P_FIMV_D_INIT_BUFFER_OPTIONS_V6);
+       R(d_first_plane_dpb_size, S5P_FIMV_D_LUMA_DPB_SIZE_V6);
+       R(d_second_plane_dpb_size, S5P_FIMV_D_CHROMA_DPB_SIZE_V6);
+       R(d_mv_buffer_size, S5P_FIMV_D_MV_BUFFER_SIZE_V6);
+       R(d_first_plane_dpb, S5P_FIMV_D_LUMA_DPB_V6);
+       R(d_second_plane_dpb, S5P_FIMV_D_CHROMA_DPB_V6);
+       R(d_mv_buffer, S5P_FIMV_D_MV_BUFFER_V6);
+       R(d_scratch_buffer_addr, S5P_FIMV_D_SCRATCH_BUFFER_ADDR_V6);
+       R(d_scratch_buffer_size, S5P_FIMV_D_SCRATCH_BUFFER_SIZE_V6);
+       R(d_cpb_buffer_addr, S5P_FIMV_D_CPB_BUFFER_ADDR_V6);
+       R(d_cpb_buffer_size, S5P_FIMV_D_CPB_BUFFER_SIZE_V6);
+       R(d_available_dpb_flag_lower, S5P_FIMV_D_AVAILABLE_DPB_FLAG_LOWER_V6);
+       R(d_cpb_buffer_offset, S5P_FIMV_D_CPB_BUFFER_OFFSET_V6);
+       R(d_slice_if_enable, S5P_FIMV_D_SLICE_IF_ENABLE_V6);
+       R(d_stream_data_size, S5P_FIMV_D_STREAM_DATA_SIZE_V6);
+       R(d_display_frame_width, S5P_FIMV_D_DISPLAY_FRAME_WIDTH_V6);
+       R(d_display_frame_height, S5P_FIMV_D_DISPLAY_FRAME_HEIGHT_V6);
+       R(d_display_status, S5P_FIMV_D_DISPLAY_STATUS_V6);
+       R(d_display_first_plane_addr, S5P_FIMV_D_DISPLAY_LUMA_ADDR_V6);
+       R(d_display_second_plane_addr, S5P_FIMV_D_DISPLAY_CHROMA_ADDR_V6);
+       R(d_display_frame_type, S5P_FIMV_D_DISPLAY_FRAME_TYPE_V6);
+       R(d_display_crop_info1, S5P_FIMV_D_DISPLAY_CROP_INFO1_V6);
+       R(d_display_crop_info2, S5P_FIMV_D_DISPLAY_CROP_INFO2_V6);
+       R(d_display_aspect_ratio, S5P_FIMV_D_DISPLAY_ASPECT_RATIO_V6);
+       R(d_display_extended_ar, S5P_FIMV_D_DISPLAY_EXTENDED_AR_V6);
+       R(d_decoded_status, S5P_FIMV_D_DECODED_STATUS_V6);
+       R(d_decoded_first_plane_addr, S5P_FIMV_D_DECODED_LUMA_ADDR_V6);
+       R(d_decoded_second_plane_addr, S5P_FIMV_D_DECODED_CHROMA_ADDR_V6);
+       R(d_decoded_frame_type, S5P_FIMV_D_DECODED_FRAME_TYPE_V6);
+       R(d_decoded_nal_size, S5P_FIMV_D_DECODED_NAL_SIZE_V6);
+       R(d_ret_picture_tag_top, S5P_FIMV_D_RET_PICTURE_TAG_TOP_V6);
+       R(d_ret_picture_tag_bot, S5P_FIMV_D_RET_PICTURE_TAG_BOT_V6);
+       R(d_h264_info, S5P_FIMV_D_H264_INFO_V6);
+       R(d_mvc_view_id, S5P_FIMV_D_MVC_VIEW_ID_V6);
+       R(d_frame_pack_sei_avail, S5P_FIMV_D_FRAME_PACK_SEI_AVAIL_V6);
+
+       /* encoder registers */
+       R(e_frame_width, S5P_FIMV_E_FRAME_WIDTH_V6);
+       R(e_frame_height, S5P_FIMV_E_FRAME_HEIGHT_V6);
+       R(e_cropped_frame_width, S5P_FIMV_E_CROPPED_FRAME_WIDTH_V6);
+       R(e_cropped_frame_height, S5P_FIMV_E_CROPPED_FRAME_HEIGHT_V6);
+       R(e_frame_crop_offset, S5P_FIMV_E_FRAME_CROP_OFFSET_V6);
+       R(e_enc_options, S5P_FIMV_E_ENC_OPTIONS_V6);
+       R(e_picture_profile, S5P_FIMV_E_PICTURE_PROFILE_V6);
+       R(e_vbv_buffer_size, S5P_FIMV_E_VBV_BUFFER_SIZE_V6);
+       R(e_vbv_init_delay, S5P_FIMV_E_VBV_INIT_DELAY_V6);
+       R(e_fixed_picture_qp, S5P_FIMV_E_FIXED_PICTURE_QP_V6);
+       R(e_rc_config, S5P_FIMV_E_RC_CONFIG_V6);
+       R(e_rc_qp_bound, S5P_FIMV_E_RC_QP_BOUND_V6);
+       R(e_rc_mode, S5P_FIMV_E_RC_RPARAM_V6);
+       R(e_mb_rc_config, S5P_FIMV_E_MB_RC_CONFIG_V6);
+       R(e_padding_ctrl, S5P_FIMV_E_PADDING_CTRL_V6);
+       R(e_mv_hor_range, S5P_FIMV_E_MV_HOR_RANGE_V6);
+       R(e_mv_ver_range, S5P_FIMV_E_MV_VER_RANGE_V6);
+       R(e_num_dpb, S5P_FIMV_E_NUM_DPB_V6);
+       R(e_luma_dpb, S5P_FIMV_E_LUMA_DPB_V6);
+       R(e_chroma_dpb, S5P_FIMV_E_CHROMA_DPB_V6);
+       R(e_me_buffer, S5P_FIMV_E_ME_BUFFER_V6);
+       R(e_scratch_buffer_addr, S5P_FIMV_E_SCRATCH_BUFFER_ADDR_V6);
+       R(e_scratch_buffer_size, S5P_FIMV_E_SCRATCH_BUFFER_SIZE_V6);
+       R(e_tmv_buffer0, S5P_FIMV_E_TMV_BUFFER0_V6);
+       R(e_tmv_buffer1, S5P_FIMV_E_TMV_BUFFER1_V6);
+       R(e_source_first_plane_addr, S5P_FIMV_E_SOURCE_LUMA_ADDR_V6);
+       R(e_source_second_plane_addr, S5P_FIMV_E_SOURCE_CHROMA_ADDR_V6);
+       R(e_stream_buffer_addr, S5P_FIMV_E_STREAM_BUFFER_ADDR_V6);
+       R(e_stream_buffer_size, S5P_FIMV_E_STREAM_BUFFER_SIZE_V6);
+       R(e_roi_buffer_addr, S5P_FIMV_E_ROI_BUFFER_ADDR_V6);
+       R(e_param_change, S5P_FIMV_E_PARAM_CHANGE_V6);
+       R(e_ir_size, S5P_FIMV_E_IR_SIZE_V6);
+       R(e_gop_config, S5P_FIMV_E_GOP_CONFIG_V6);
+       R(e_mslice_mode, S5P_FIMV_E_MSLICE_MODE_V6);
+       R(e_mslice_size_mb, S5P_FIMV_E_MSLICE_SIZE_MB_V6);
+       R(e_mslice_size_bits, S5P_FIMV_E_MSLICE_SIZE_BITS_V6);
+       R(e_frame_insertion, S5P_FIMV_E_FRAME_INSERTION_V6);
+       R(e_rc_frame_rate, S5P_FIMV_E_RC_FRAME_RATE_V6);
+       R(e_rc_bit_rate, S5P_FIMV_E_RC_BIT_RATE_V6);
+       R(e_rc_roi_ctrl, S5P_FIMV_E_RC_ROI_CTRL_V6);
+       R(e_picture_tag, S5P_FIMV_E_PICTURE_TAG_V6);
+       R(e_bit_count_enable, S5P_FIMV_E_BIT_COUNT_ENABLE_V6);
+       R(e_max_bit_count, S5P_FIMV_E_MAX_BIT_COUNT_V6);
+       R(e_min_bit_count, S5P_FIMV_E_MIN_BIT_COUNT_V6);
+       R(e_metadata_buffer_addr, S5P_FIMV_E_METADATA_BUFFER_ADDR_V6);
+       R(e_metadata_buffer_size, S5P_FIMV_E_METADATA_BUFFER_SIZE_V6);
+       R(e_encoded_source_first_plane_addr,
+                       S5P_FIMV_E_ENCODED_SOURCE_LUMA_ADDR_V6);
+       R(e_encoded_source_second_plane_addr,
+                       S5P_FIMV_E_ENCODED_SOURCE_CHROMA_ADDR_V6);
+       R(e_stream_size, S5P_FIMV_E_STREAM_SIZE_V6);
+       R(e_slice_type, S5P_FIMV_E_SLICE_TYPE_V6);
+       R(e_picture_count, S5P_FIMV_E_PICTURE_COUNT_V6);
+       R(e_ret_picture_tag, S5P_FIMV_E_RET_PICTURE_TAG_V6);
+       R(e_recon_luma_dpb_addr, S5P_FIMV_E_RECON_LUMA_DPB_ADDR_V6);
+       R(e_recon_chroma_dpb_addr, S5P_FIMV_E_RECON_CHROMA_DPB_ADDR_V6);
+       R(e_mpeg4_options, S5P_FIMV_E_MPEG4_OPTIONS_V6);
+       R(e_mpeg4_hec_period, S5P_FIMV_E_MPEG4_HEC_PERIOD_V6);
+       R(e_aspect_ratio, S5P_FIMV_E_ASPECT_RATIO_V6);
+       R(e_extended_sar, S5P_FIMV_E_EXTENDED_SAR_V6);
+       R(e_h264_options, S5P_FIMV_E_H264_OPTIONS_V6);
+       R(e_h264_lf_alpha_offset, S5P_FIMV_E_H264_LF_ALPHA_OFFSET_V6);
+       R(e_h264_lf_beta_offset, S5P_FIMV_E_H264_LF_BETA_OFFSET_V6);
+       R(e_h264_i_period, S5P_FIMV_E_H264_I_PERIOD_V6);
+       R(e_h264_fmo_slice_grp_map_type,
+                       S5P_FIMV_E_H264_FMO_SLICE_GRP_MAP_TYPE_V6);
+       R(e_h264_fmo_num_slice_grp_minus1,
+                       S5P_FIMV_E_H264_FMO_NUM_SLICE_GRP_MINUS1_V6);
+       R(e_h264_fmo_slice_grp_change_dir,
+                       S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_DIR_V6);
+       R(e_h264_fmo_slice_grp_change_rate_minus1,
+                       S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_RATE_MINUS1_V6);
+       R(e_h264_fmo_run_length_minus1_0,
+                       S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_0_V6);
+       R(e_h264_aso_slice_order_0, S5P_FIMV_E_H264_ASO_SLICE_ORDER_0_V6);
+       R(e_h264_num_t_layer, S5P_FIMV_E_H264_NUM_T_LAYER_V6);
+       R(e_h264_hierarchical_qp_layer0,
+                       S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER0_V6);
+       R(e_h264_frame_packing_sei_info,
+                       S5P_FIMV_E_H264_FRAME_PACKING_SEI_INFO_V6);
+
+       if (!IS_MFCV7_PLUS(dev))
+               goto done;
+
+       /* Initialize registers used in MFC v7+ */
+       R(e_source_first_plane_addr, S5P_FIMV_E_SOURCE_FIRST_ADDR_V7);
+       R(e_source_second_plane_addr, S5P_FIMV_E_SOURCE_SECOND_ADDR_V7);
+       R(e_source_third_plane_addr, S5P_FIMV_E_SOURCE_THIRD_ADDR_V7);
+       R(e_source_first_plane_stride, S5P_FIMV_E_SOURCE_FIRST_STRIDE_V7);
+       R(e_source_second_plane_stride, S5P_FIMV_E_SOURCE_SECOND_STRIDE_V7);
+       R(e_source_third_plane_stride, S5P_FIMV_E_SOURCE_THIRD_STRIDE_V7);
+       R(e_encoded_source_first_plane_addr,
+                       S5P_FIMV_E_ENCODED_SOURCE_FIRST_ADDR_V7);
+       R(e_encoded_source_second_plane_addr,
+                       S5P_FIMV_E_ENCODED_SOURCE_SECOND_ADDR_V7);
+       R(e_vp8_options, S5P_FIMV_E_VP8_OPTIONS_V7);
+
+       if (!IS_MFCV8_PLUS(dev))
+               goto done;
+
+       /* Initialize registers used in MFC v8 only.
+        * Also, over-write the registers which have
+        * a different offset for MFC v8. */
+       R(d_stream_data_size, S5P_FIMV_D_STREAM_DATA_SIZE_V8);
+       R(d_cpb_buffer_addr, S5P_FIMV_D_CPB_BUFFER_ADDR_V8);
+       R(d_cpb_buffer_size, S5P_FIMV_D_CPB_BUFFER_SIZE_V8);
+       R(d_cpb_buffer_offset, S5P_FIMV_D_CPB_BUFFER_OFFSET_V8);
+       R(d_first_plane_dpb_size, S5P_FIMV_D_FIRST_PLANE_DPB_SIZE_V8);
+       R(d_second_plane_dpb_size, S5P_FIMV_D_SECOND_PLANE_DPB_SIZE_V8);
+       R(d_scratch_buffer_addr, S5P_FIMV_D_SCRATCH_BUFFER_ADDR_V8);
+       R(d_scratch_buffer_size, S5P_FIMV_D_SCRATCH_BUFFER_SIZE_V8);
+       R(d_first_plane_dpb_stride_size,
+                       S5P_FIMV_D_FIRST_PLANE_DPB_STRIDE_SIZE_V8);
+       R(d_second_plane_dpb_stride_size,
+                       S5P_FIMV_D_SECOND_PLANE_DPB_STRIDE_SIZE_V8);
+       R(d_mv_buffer_size, S5P_FIMV_D_MV_BUFFER_SIZE_V8);
+       R(d_num_mv, S5P_FIMV_D_NUM_MV_V8);
+       R(d_first_plane_dpb, S5P_FIMV_D_FIRST_PLANE_DPB_V8);
+       R(d_second_plane_dpb, S5P_FIMV_D_SECOND_PLANE_DPB_V8);
+       R(d_mv_buffer, S5P_FIMV_D_MV_BUFFER_V8);
+       R(d_init_buffer_options, S5P_FIMV_D_INIT_BUFFER_OPTIONS_V8);
+       R(d_available_dpb_flag_lower, S5P_FIMV_D_AVAILABLE_DPB_FLAG_LOWER_V8);
+       R(d_slice_if_enable, S5P_FIMV_D_SLICE_IF_ENABLE_V8);
+       R(d_display_first_plane_addr, S5P_FIMV_D_DISPLAY_FIRST_PLANE_ADDR_V8);
+       R(d_display_second_plane_addr, S5P_FIMV_D_DISPLAY_SECOND_PLANE_ADDR_V8);
+       R(d_decoded_first_plane_addr, S5P_FIMV_D_DECODED_FIRST_PLANE_ADDR_V8);
+       R(d_decoded_second_plane_addr, S5P_FIMV_D_DECODED_SECOND_PLANE_ADDR_V8);
+       R(d_display_status, S5P_FIMV_D_DISPLAY_STATUS_V8);
+       R(d_decoded_status, S5P_FIMV_D_DECODED_STATUS_V8);
+       R(d_decoded_frame_type, S5P_FIMV_D_DECODED_FRAME_TYPE_V8);
+       R(d_display_frame_type, S5P_FIMV_D_DISPLAY_FRAME_TYPE_V8);
+       R(d_decoded_nal_size, S5P_FIMV_D_DECODED_NAL_SIZE_V8);
+       R(d_display_frame_width, S5P_FIMV_D_DISPLAY_FRAME_WIDTH_V8);
+       R(d_display_frame_height, S5P_FIMV_D_DISPLAY_FRAME_HEIGHT_V8);
+       R(d_frame_pack_sei_avail, S5P_FIMV_D_FRAME_PACK_SEI_AVAIL_V8);
+       R(d_mvc_num_views, S5P_FIMV_D_MVC_NUM_VIEWS_V8);
+       R(d_mvc_view_id, S5P_FIMV_D_MVC_VIEW_ID_V8);
+       R(d_ret_picture_tag_top, S5P_FIMV_D_RET_PICTURE_TAG_TOP_V8);
+       R(d_ret_picture_tag_bot, S5P_FIMV_D_RET_PICTURE_TAG_BOT_V8);
+       R(d_display_crop_info1, S5P_FIMV_D_DISPLAY_CROP_INFO1_V8);
+       R(d_display_crop_info2, S5P_FIMV_D_DISPLAY_CROP_INFO2_V8);
+       R(d_min_scratch_buffer_size, S5P_FIMV_D_MIN_SCRATCH_BUFFER_SIZE_V8);
+
+       /* encoder registers */
+       R(e_padding_ctrl, S5P_FIMV_E_PADDING_CTRL_V8);
+       R(e_rc_config, S5P_FIMV_E_RC_CONFIG_V8);
+       R(e_rc_mode, S5P_FIMV_E_RC_RPARAM_V8);
+       R(e_mv_hor_range, S5P_FIMV_E_MV_HOR_RANGE_V8);
+       R(e_mv_ver_range, S5P_FIMV_E_MV_VER_RANGE_V8);
+       R(e_rc_qp_bound, S5P_FIMV_E_RC_QP_BOUND_V8);
+       R(e_fixed_picture_qp, S5P_FIMV_E_FIXED_PICTURE_QP_V8);
+       R(e_vbv_buffer_size, S5P_FIMV_E_VBV_BUFFER_SIZE_V8);
+       R(e_vbv_init_delay, S5P_FIMV_E_VBV_INIT_DELAY_V8);
+       R(e_mb_rc_config, S5P_FIMV_E_MB_RC_CONFIG_V8);
+       R(e_aspect_ratio, S5P_FIMV_E_ASPECT_RATIO_V8);
+       R(e_extended_sar, S5P_FIMV_E_EXTENDED_SAR_V8);
+       R(e_h264_options, S5P_FIMV_E_H264_OPTIONS_V8);
+       R(e_min_scratch_buffer_size, S5P_FIMV_E_MIN_SCRATCH_BUFFER_SIZE_V8);
+
+       if (!IS_MFCV10(dev))
+               goto done;
+
+       /* Initialize registers used in MFC v10 only.
+        * Also, over-write the registers which have
+        * a different offset for MFC v10.
+        */
+
+       /* decoder registers */
+       R(d_static_buffer_addr, S5P_FIMV_D_STATIC_BUFFER_ADDR_V10);
+       R(d_static_buffer_size, S5P_FIMV_D_STATIC_BUFFER_SIZE_V10);
+
+       /* encoder registers */
+       R(e_num_t_layer, S5P_FIMV_E_NUM_T_LAYER_V10);
+       R(e_hier_qp_layer0, S5P_FIMV_E_HIERARCHICAL_QP_LAYER0_V10);
+       R(e_hier_bit_rate_layer0, S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER0_V10);
+       R(e_hevc_options, S5P_FIMV_E_HEVC_OPTIONS_V10);
+       R(e_hevc_refresh_period, S5P_FIMV_E_HEVC_REFRESH_PERIOD_V10);
+       R(e_hevc_lf_beta_offset_div2, S5P_FIMV_E_HEVC_LF_BETA_OFFSET_DIV2_V10);
+       R(e_hevc_lf_tc_offset_div2, S5P_FIMV_E_HEVC_LF_TC_OFFSET_DIV2_V10);
+       R(e_hevc_nal_control, S5P_FIMV_E_HEVC_NAL_CONTROL_V10);
+
+done:
+       return &mfc_regs;
+#undef S5P_MFC_REG_ADDR
+#undef R
+}
+
+/* Initialize opr function pointers for MFC v6 */
+static struct s5p_mfc_hw_ops s5p_mfc_ops_v6 = {
+       .alloc_dec_temp_buffers = s5p_mfc_alloc_dec_temp_buffers_v6,
+       .release_dec_desc_buffer = s5p_mfc_release_dec_desc_buffer_v6,
+       .alloc_codec_buffers = s5p_mfc_alloc_codec_buffers_v6,
+       .release_codec_buffers = s5p_mfc_release_codec_buffers_v6,
+       .alloc_instance_buffer = s5p_mfc_alloc_instance_buffer_v6,
+       .release_instance_buffer = s5p_mfc_release_instance_buffer_v6,
+       .alloc_dev_context_buffer =
+               s5p_mfc_alloc_dev_context_buffer_v6,
+       .release_dev_context_buffer =
+               s5p_mfc_release_dev_context_buffer_v6,
+       .dec_calc_dpb_size = s5p_mfc_dec_calc_dpb_size_v6,
+       .enc_calc_src_size = s5p_mfc_enc_calc_src_size_v6,
+       .set_enc_stream_buffer = s5p_mfc_set_enc_stream_buffer_v6,
+       .set_enc_frame_buffer = s5p_mfc_set_enc_frame_buffer_v6,
+       .get_enc_frame_buffer = s5p_mfc_get_enc_frame_buffer_v6,
+       .try_run = s5p_mfc_try_run_v6,
+       .clear_int_flags = s5p_mfc_clear_int_flags_v6,
+       .get_dspl_y_adr = s5p_mfc_get_dspl_y_adr_v6,
+       .get_dec_y_adr = s5p_mfc_get_dec_y_adr_v6,
+       .get_dspl_status = s5p_mfc_get_dspl_status_v6,
+       .get_dec_status = s5p_mfc_get_dec_status_v6,
+       .get_dec_frame_type = s5p_mfc_get_dec_frame_type_v6,
+       .get_disp_frame_type = s5p_mfc_get_disp_frame_type_v6,
+       .get_consumed_stream = s5p_mfc_get_consumed_stream_v6,
+       .get_int_reason = s5p_mfc_get_int_reason_v6,
+       .get_int_err = s5p_mfc_get_int_err_v6,
+       .err_dec = s5p_mfc_err_dec_v6,
+       .get_img_width = s5p_mfc_get_img_width_v6,
+       .get_img_height = s5p_mfc_get_img_height_v6,
+       .get_dpb_count = s5p_mfc_get_dpb_count_v6,
+       .get_mv_count = s5p_mfc_get_mv_count_v6,
+       .get_inst_no = s5p_mfc_get_inst_no_v6,
+       .get_enc_strm_size = s5p_mfc_get_enc_strm_size_v6,
+       .get_enc_slice_type = s5p_mfc_get_enc_slice_type_v6,
+       .get_enc_dpb_count = s5p_mfc_get_enc_dpb_count_v6,
+       .get_pic_type_top = s5p_mfc_get_pic_type_top_v6,
+       .get_pic_type_bot = s5p_mfc_get_pic_type_bot_v6,
+       .get_crop_info_h = s5p_mfc_get_crop_info_h_v6,
+       .get_crop_info_v = s5p_mfc_get_crop_info_v_v6,
+       .get_min_scratch_buf_size = s5p_mfc_get_min_scratch_buf_size,
+       .get_e_min_scratch_buf_size = s5p_mfc_get_e_min_scratch_buf_size,
+};
+
+struct s5p_mfc_hw_ops *s5p_mfc_init_hw_ops_v6(void)
+{
+       return &s5p_mfc_ops_v6;
+}
diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_opr_v6.h b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_opr_v6.h
new file mode 100644 (file)
index 0000000..e4dd03c
--- /dev/null
@@ -0,0 +1,57 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * drivers/media/platform/samsung/s5p-mfc/s5p_mfc_opr_v6.h
+ *
+ * Header file for Samsung MFC (Multi Function Codec - FIMV) driver
+ * Contains declarations of hw related functions.
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ */
+
+#ifndef S5P_MFC_OPR_V6_H_
+#define S5P_MFC_OPR_V6_H_
+
+#include "s5p_mfc_common.h"
+#include "s5p_mfc_opr.h"
+
+#define MFC_CTRL_MODE_CUSTOM   MFC_CTRL_MODE_SFR
+
+#define MB_WIDTH(x_size)               DIV_ROUND_UP(x_size, 16)
+#define MB_HEIGHT(y_size)              DIV_ROUND_UP(y_size, 16)
+#define S5P_MFC_DEC_MV_SIZE_V6(x, y)   (MB_WIDTH(x) * \
+                                       (((MB_HEIGHT(y)+1)/2)*2) * 64 + 128)
+#define S5P_MFC_DEC_MV_SIZE_V10(x, y)  (MB_WIDTH(x) * \
+                                       (((MB_HEIGHT(y)+1)/2)*2) * 64 + 512)
+#define S5P_MFC_LCU_WIDTH(x_size)      DIV_ROUND_UP(x_size, 32)
+#define S5P_MFC_LCU_HEIGHT(y_size)     DIV_ROUND_UP(y_size, 32)
+
+#define s5p_mfc_dec_hevc_mv_size(x, y) \
+       (DIV_ROUND_UP(x, 64) * DIV_ROUND_UP(y, 64) * 256 + 512)
+
+/* Definition */
+#define ENC_MULTI_SLICE_MB_MAX         ((1 << 30) - 1)
+#define ENC_MULTI_SLICE_BIT_MIN                2800
+#define ENC_INTRA_REFRESH_MB_MAX       ((1 << 18) - 1)
+#define ENC_VBV_BUF_SIZE_MAX           ((1 << 30) - 1)
+#define ENC_H264_LOOP_FILTER_AB_MIN    -12
+#define ENC_H264_LOOP_FILTER_AB_MAX    12
+#define ENC_H264_RC_FRAME_RATE_MAX     ((1 << 16) - 1)
+#define ENC_H263_RC_FRAME_RATE_MAX     ((1 << 16) - 1)
+#define ENC_H264_PROFILE_MAX           3
+#define ENC_H264_LEVEL_MAX             42
+#define ENC_MPEG4_VOP_TIME_RES_MAX     ((1 << 16) - 1)
+#define FRAME_DELTA_H264_H263          1
+#define TIGHT_CBR_MAX                  10
+#define ENC_HEVC_RC_FRAME_RATE_MAX     ((1 << 16) - 1)
+#define ENC_HEVC_QP_INDEX_MIN          -12
+#define ENC_HEVC_QP_INDEX_MAX          12
+#define ENC_HEVC_LOOP_FILTER_MIN       -12
+#define ENC_HEVC_LOOP_FILTER_MAX       12
+#define ENC_HEVC_LEVEL_MAX             62
+
+#define FRAME_DELTA_DEFAULT            1
+
+struct s5p_mfc_hw_ops *s5p_mfc_init_hw_ops_v6(void);
+const struct s5p_mfc_regs *s5p_mfc_init_regs_v6_plus(struct s5p_mfc_dev *dev);
+#endif /* S5P_MFC_OPR_V6_H_ */
diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_pm.c b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_pm.c
new file mode 100644 (file)
index 0000000..72a901e
--- /dev/null
@@ -0,0 +1,119 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * linux/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_pm.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include "s5p_mfc_common.h"
+#include "s5p_mfc_debug.h"
+#include "s5p_mfc_pm.h"
+
+static struct s5p_mfc_pm *pm;
+static struct s5p_mfc_dev *p_dev;
+static atomic_t clk_ref;
+
+int s5p_mfc_init_pm(struct s5p_mfc_dev *dev)
+{
+       int i;
+
+       pm = &dev->pm;
+       p_dev = dev;
+
+       pm->num_clocks = dev->variant->num_clocks;
+       pm->clk_names = dev->variant->clk_names;
+       pm->device = &dev->plat_dev->dev;
+       pm->clock_gate = NULL;
+
+       /* clock control */
+       for (i = 0; i < pm->num_clocks; i++) {
+               pm->clocks[i] = devm_clk_get(pm->device, pm->clk_names[i]);
+               if (IS_ERR(pm->clocks[i])) {
+                       /* additional clocks are optional */
+                       if (i && PTR_ERR(pm->clocks[i]) == -ENOENT) {
+                               pm->clocks[i] = NULL;
+                               continue;
+                       }
+                       mfc_err("Failed to get clock: %s\n",
+                               pm->clk_names[i]);
+                       return PTR_ERR(pm->clocks[i]);
+               }
+       }
+
+       if (dev->variant->use_clock_gating)
+               pm->clock_gate = pm->clocks[0];
+
+       pm_runtime_enable(pm->device);
+       atomic_set(&clk_ref, 0);
+       return 0;
+}
+
+void s5p_mfc_final_pm(struct s5p_mfc_dev *dev)
+{
+       pm_runtime_disable(pm->device);
+}
+
+int s5p_mfc_clock_on(void)
+{
+       atomic_inc(&clk_ref);
+       mfc_debug(3, "+ %d\n", atomic_read(&clk_ref));
+
+       return clk_enable(pm->clock_gate);
+}
+
+void s5p_mfc_clock_off(void)
+{
+       atomic_dec(&clk_ref);
+       mfc_debug(3, "- %d\n", atomic_read(&clk_ref));
+
+       clk_disable(pm->clock_gate);
+}
+
+int s5p_mfc_power_on(void)
+{
+       int i, ret = 0;
+
+       ret = pm_runtime_resume_and_get(pm->device);
+       if (ret < 0)
+               return ret;
+
+       /* clock control */
+       for (i = 0; i < pm->num_clocks; i++) {
+               ret = clk_prepare_enable(pm->clocks[i]);
+               if (ret < 0) {
+                       mfc_err("clock prepare failed for clock: %s\n",
+                               pm->clk_names[i]);
+                       i++;
+                       goto err;
+               }
+       }
+
+       /* prepare for software clock gating */
+       clk_disable(pm->clock_gate);
+
+       return 0;
+err:
+       while (--i > 0)
+               clk_disable_unprepare(pm->clocks[i]);
+       pm_runtime_put(pm->device);
+       return ret;
+}
+
+int s5p_mfc_power_off(void)
+{
+       int i;
+
+       /* finish software clock gating */
+       clk_enable(pm->clock_gate);
+
+       for (i = 0; i < pm->num_clocks; i++)
+               clk_disable_unprepare(pm->clocks[i]);
+
+       return pm_runtime_put_sync(pm->device);
+}
+
diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_pm.h b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_pm.h
new file mode 100644 (file)
index 0000000..4159d23
--- /dev/null
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * linux/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_pm.h
+ *
+ * Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ */
+
+#ifndef S5P_MFC_PM_H_
+#define S5P_MFC_PM_H_
+
+int s5p_mfc_init_pm(struct s5p_mfc_dev *dev);
+void s5p_mfc_final_pm(struct s5p_mfc_dev *dev);
+
+int s5p_mfc_clock_on(void);
+void s5p_mfc_clock_off(void);
+int s5p_mfc_power_on(void);
+int s5p_mfc_power_off(void);
+
+#endif /* S5P_MFC_PM_H_ */