[COMMON] media: mfc: DRV4.0: remove "s5p" prefix in file name.
authorSunyoung Kang <sy0816.kang@samsung.com>
Mon, 25 Jun 2018 06:43:24 +0000 (15:43 +0900)
committerSunyoung Kang <sy0816.kang@samsung.com>
Mon, 23 Jul 2018 06:18:48 +0000 (15:18 +0900)
The "s5p" prefix is no longer meaningful so this renames
all files.

Change-Id: I46662fd4660c66eeafd0322053292a61e9b3c3e1
Signed-off-by: Sunyoung Kang <sy0816.kang@samsung.com>
123 files changed:
drivers/media/platform/exynos/mfc/Makefile
drivers/media/platform/exynos/mfc/mfc.c [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_buf.c [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_buf.h [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_cal.c [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_cal.h [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_cmd.c [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_cmd.h [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_common.h [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_ctrl.c [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_ctrl.h [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_data_struct.h [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_debug.h [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_debugfs.c [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_debugfs.h [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_dec.c [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_dec.h [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_dec_internal.h [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_dec_ops.c [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_dec_vb2_ops.c [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_enc.c [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_enc.h [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_enc_internal.h [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_enc_ops.c [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_enc_param.c [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_enc_param.h [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_enc_vb2_ops.c [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_hwfc_internal.h [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_hwlock.c [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_hwlock.h [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_inst.c [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_inst.h [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_irq.c [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_irq.h [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_macros.h [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_mem.c [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_mem.h [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_mmcache.c [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_mmcache.h [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_nal_q.c [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_nal_q.h [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_opr.c [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_opr.h [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_otf.c [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_otf.h [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_perf_measure.c [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_perf_measure.h [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_pm.c [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_pm.h [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_qos.c [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_qos.h [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_queue.c [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_queue.h [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_reg.c [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_reg.h [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_regs_v10.h [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_sync.c [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_sync.h [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_utils.c [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_utils.h [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_watchdog.c [new file with mode: 0644]
drivers/media/platform/exynos/mfc/mfc_watchdog.h [new file with mode: 0644]
drivers/media/platform/exynos/mfc/s5p_mfc.c [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_buf.c [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_buf.h [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_cal.c [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_cal.h [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_cmd.c [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_cmd.h [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_common.h [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_ctrl.c [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_ctrl.h [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_data_struct.h [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_debug.h [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_debugfs.c [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_debugfs.h [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_dec.c [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_dec.h [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_dec_internal.h [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_dec_ops.c [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_dec_vb2_ops.c [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_enc.c [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_enc.h [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_enc_internal.h [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_enc_ops.c [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_enc_param.c [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_enc_param.h [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_enc_vb2_ops.c [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_hwfc_internal.h [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_hwlock.c [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_hwlock.h [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_inst.c [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_inst.h [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_irq.c [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_irq.h [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_macros.h [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_mem.c [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_mem.h [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_mmcache.c [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_mmcache.h [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_nal_q.c [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_nal_q.h [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_opr.c [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_opr.h [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_otf.c [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_otf.h [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_perf_measure.c [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_perf_measure.h [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_pm.c [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_pm.h [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_qos.c [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_qos.h [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_queue.c [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_queue.h [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_reg.c [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_reg.h [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_regs_v10.h [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_sync.c [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_sync.h [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_utils.c [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_utils.h [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_watchdog.c [deleted file]
drivers/media/platform/exynos/mfc/s5p_mfc_watchdog.h [deleted file]

index 428674d17dd16f6cb743aa90a4a4643b280af48e..72eddaeb1112e7216f4bc8aaaf5d5d9ec83f3277 100644 (file)
@@ -1,8 +1,8 @@
-obj-$(CONFIG_VIDEO_EXYNOS_MFC) := s5p-mfc.o
-s5p-mfc-y += s5p_mfc.o s5p_mfc_irq.o s5p_mfc_dec.o s5p_mfc_dec_vb2_ops.o s5p_mfc_enc.o s5p_mfc_enc_vb2_ops.o
-s5p-mfc-y += s5p_mfc_ctrl.o s5p_mfc_hwlock.o s5p_mfc_nal_q.o s5p_mfc_watchdog.o s5p_mfc_opr.o s5p_mfc_sync.o
-s5p-mfc-y += s5p_mfc_pm.o s5p_mfc_inst.o s5p_mfc_cmd.o s5p_mfc_cal.o s5p_mfc_reg.o s5p_mfc_perf_measure.o
-s5p-mfc-y += s5p_mfc_dec_ops.o s5p_mfc_enc_ops.o s5p_mfc_enc_param.o
-s5p-mfc-y += s5p_mfc_queue.o s5p_mfc_buf.o s5p_mfc_utils.o s5p_mfc_qos.o s5p_mfc_mem.o
-s5p-mfc-y += s5p_mfc_debugfs.o s5p_mfc_otf.o
-s5p-mfc-y += s5p_mfc_mmcache.o
+obj-$(CONFIG_VIDEO_EXYNOS_MFC) := exynos_mfc.o
+exynos_mfc-y += mfc.o mfc_irq.o mfc_dec.o mfc_dec_vb2_ops.o mfc_enc.o mfc_enc_vb2_ops.o
+exynos_mfc-y += mfc_ctrl.o mfc_hwlock.o mfc_nal_q.o mfc_watchdog.o mfc_opr.o mfc_sync.o
+exynos_mfc-y += mfc_pm.o mfc_inst.o mfc_cmd.o mfc_cal.o mfc_reg.o mfc_perf_measure.o
+exynos_mfc-y += mfc_dec_ops.o mfc_enc_ops.o mfc_enc_param.o
+exynos_mfc-y += mfc_queue.o mfc_buf.o mfc_utils.o mfc_qos.o mfc_mem.o
+exynos_mfc-y += mfc_debugfs.o mfc_otf.o
+exynos_mfc-y += mfc_mmcache.o
diff --git a/drivers/media/platform/exynos/mfc/mfc.c b/drivers/media/platform/exynos/mfc/mfc.c
new file mode 100644 (file)
index 0000000..7d1adfb
--- /dev/null
@@ -0,0 +1,1651 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc.c
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of_address.h>
+#include <linux/proc_fs.h>
+#include <video/videonode.h>
+#include <linux/of.h>
+#include <linux/smc.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/poll.h>
+
+#include "mfc_common.h"
+
+#include "mfc_irq.h"
+#include "mfc_dec.h"
+#include "mfc_enc.h"
+
+#include "mfc_ctrl.h"
+#include "mfc_hwlock.h"
+#include "mfc_nal_q.h"
+#include "mfc_otf.h"
+#include "mfc_watchdog.h"
+#include "mfc_debugfs.h"
+#include "mfc_opr.h"
+#include "mfc_sync.h"
+
+#include "mfc_inst.h"
+#include "mfc_pm.h"
+#include "mfc_cal.h"
+#include "mfc_perf_measure.h"
+#include "mfc_reg.h"
+#include "mfc_mmcache.h"
+
+#include "mfc_qos.h"
+#include "mfc_queue.h"
+#include "mfc_utils.h"
+#include "mfc_buf.h"
+#include "mfc_mem.h"
+
+#define CREATE_TRACE_POINTS
+#include <trace/events/mfc.h>
+
+#define S5P_MFC_NAME                   "s5p-mfc"
+#define S5P_MFC_DEC_NAME               "s5p-mfc-dec"
+#define S5P_MFC_ENC_NAME               "s5p-mfc-enc"
+#define S5P_MFC_DEC_DRM_NAME           "s5p-mfc-dec-secure"
+#define S5P_MFC_ENC_DRM_NAME           "s5p-mfc-enc-secure"
+#define S5P_MFC_ENC_OTF_NAME           "s5p-mfc-enc-otf"
+#define S5P_MFC_ENC_OTF_DRM_NAME       "s5p-mfc-enc-otf-secure"
+
+struct _mfc_trace g_mfc_trace[MFC_TRACE_COUNT_MAX];
+struct _mfc_trace g_mfc_trace_hwlock[MFC_TRACE_COUNT_MAX];
+struct s5p_mfc_dev *g_mfc_dev;
+
+#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
+static struct proc_dir_entry *mfc_proc_entry;
+
+#define MFC_PROC_ROOT                  "mfc"
+#define MFC_PROC_INSTANCE_NUMBER       "instance_number"
+#define MFC_PROC_DRM_INSTANCE_NUMBER   "drm_instance_number"
+#define MFC_PROC_FW_STATUS             "fw_status"
+#endif
+
+#define DEF_DEC_SRC_FMT        9
+#define DEF_DEC_DST_FMT        5
+
+#define DEF_ENC_SRC_FMT        5
+#define DEF_ENC_DST_FMT        13
+
+void s5p_mfc_butler_worker(struct work_struct *work)
+{
+       struct s5p_mfc_dev *dev;
+
+       dev = container_of(work, struct s5p_mfc_dev, butler_work);
+
+       s5p_mfc_try_run(dev);
+}
+
+extern struct s5p_mfc_ctrls_ops decoder_ctrls_ops;
+extern struct vb2_ops s5p_mfc_dec_qops;
+extern struct s5p_mfc_fmt dec_formats[];
+
+static void mfc_deinit_dec_ctx(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dec *dec = ctx->dec_priv;
+
+       s5p_mfc_delete_queue(&ctx->src_buf_queue);
+       s5p_mfc_delete_queue(&ctx->dst_buf_queue);
+       s5p_mfc_delete_queue(&ctx->src_buf_nal_queue);
+       s5p_mfc_delete_queue(&ctx->dst_buf_nal_queue);
+       s5p_mfc_delete_queue(&ctx->ref_buf_queue);
+
+       s5p_mfc_mem_cleanup_user_shared_handle(ctx, &dec->sh_handle);
+       kfree(dec->ref_info);
+       kfree(dec);
+}
+
+static int mfc_init_dec_ctx(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dec *dec;
+       int ret = 0;
+       int i;
+
+       dec = kzalloc(sizeof(struct s5p_mfc_dec), GFP_KERNEL);
+       if (!dec) {
+               mfc_err_dev("failed to allocate decoder private data\n");
+               return -ENOMEM;
+       }
+       ctx->dec_priv = dec;
+
+       ctx->inst_no = MFC_NO_INSTANCE_SET;
+
+       s5p_mfc_create_queue(&ctx->src_buf_queue);
+       s5p_mfc_create_queue(&ctx->dst_buf_queue);
+       s5p_mfc_create_queue(&ctx->src_buf_nal_queue);
+       s5p_mfc_create_queue(&ctx->dst_buf_nal_queue);
+       s5p_mfc_create_queue(&ctx->ref_buf_queue);
+
+       for (i = 0; i < MFC_MAX_BUFFERS; i++) {
+               INIT_LIST_HEAD(&ctx->src_ctrls[i]);
+               INIT_LIST_HEAD(&ctx->dst_ctrls[i]);
+       }
+       ctx->src_ctrls_avail = 0;
+       ctx->dst_ctrls_avail = 0;
+
+       ctx->capture_state = QUEUE_FREE;
+       ctx->output_state = QUEUE_FREE;
+
+       s5p_mfc_change_state(ctx, MFCINST_INIT);
+       ctx->type = MFCINST_DECODER;
+       ctx->c_ops = &decoder_ctrls_ops;
+       ctx->src_fmt = &dec_formats[DEF_DEC_SRC_FMT];
+       ctx->dst_fmt = &dec_formats[DEF_DEC_DST_FMT];
+
+       s5p_mfc_qos_reset_framerate(ctx);
+
+       ctx->qos_ratio = 100;
+#ifdef CONFIG_MFC_USE_BUS_DEVFREQ
+       INIT_LIST_HEAD(&ctx->qos_list);
+#endif
+       INIT_LIST_HEAD(&ctx->ts_list);
+
+       dec->display_delay = -1;
+       dec->is_interlaced = 0;
+       dec->immediate_display = 0;
+       dec->is_dts_mode = 0;
+       dec->err_reuse_flag = 0;
+       dec->dec_only_release_flag = 0;
+
+       dec->is_dynamic_dpb = 1;
+       dec->dynamic_used = 0;
+       dec->is_dpb_full = 0;
+       s5p_mfc_cleanup_assigned_fd(ctx);
+       s5p_mfc_clear_assigned_dpb(ctx);
+       dec->sh_handle.fd = -1;
+       dec->ref_info = kzalloc(
+               (sizeof(struct dec_dpb_ref_info) * MFC_MAX_DPBS), GFP_KERNEL);
+       if (!dec->ref_info) {
+               mfc_err_dev("failed to allocate decoder information data\n");
+               ret = -ENOMEM;
+               goto fail_dec_init;
+       }
+       for (i = 0; i < MFC_MAX_BUFFERS; i++)
+               dec->ref_info[i].dpb[0].fd[0] = MFC_INFO_INIT_FD;
+
+       /* Init videobuf2 queue for OUTPUT */
+       ctx->vq_src.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+       ctx->vq_src.drv_priv = ctx;
+       ctx->vq_src.buf_struct_size = sizeof(struct s5p_mfc_buf);
+       ctx->vq_src.io_modes = VB2_USERPTR | VB2_DMABUF;
+       ctx->vq_src.ops = &s5p_mfc_dec_qops;
+       ctx->vq_src.mem_ops = s5p_mfc_mem_ops();
+       ctx->vq_src.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+       ret = vb2_queue_init(&ctx->vq_src);
+       if (ret) {
+               mfc_err_dev("Failed to initialize videobuf2 queue(output)\n");
+               goto fail_dec_init;
+       }
+       /* Init videobuf2 queue for CAPTURE */
+       ctx->vq_dst.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+       ctx->vq_dst.drv_priv = ctx;
+       ctx->vq_dst.buf_struct_size = sizeof(struct s5p_mfc_buf);
+       ctx->vq_dst.io_modes = VB2_USERPTR | VB2_DMABUF;
+       ctx->vq_dst.ops = &s5p_mfc_dec_qops;
+       ctx->vq_dst.mem_ops = s5p_mfc_mem_ops();
+       ctx->vq_dst.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+       ret = vb2_queue_init(&ctx->vq_dst);
+       if (ret) {
+               mfc_err_dev("Failed to initialize videobuf2 queue(capture)\n");
+               goto fail_dec_init;
+       }
+
+       return ret;
+
+fail_dec_init:
+       mfc_deinit_dec_ctx(ctx);
+       return ret;
+}
+
+extern struct s5p_mfc_ctrls_ops encoder_ctrls_ops;
+extern struct vb2_ops s5p_mfc_enc_qops;
+extern struct s5p_mfc_fmt enc_formats[];
+
+static void mfc_deinit_enc_ctx(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_enc *enc = ctx->enc_priv;
+
+       s5p_mfc_delete_queue(&ctx->src_buf_queue);
+       s5p_mfc_delete_queue(&ctx->dst_buf_queue);
+       s5p_mfc_delete_queue(&ctx->src_buf_nal_queue);
+       s5p_mfc_delete_queue(&ctx->dst_buf_nal_queue);
+       s5p_mfc_delete_queue(&ctx->ref_buf_queue);
+
+       s5p_mfc_mem_cleanup_user_shared_handle(ctx, &enc->sh_handle_svc);
+       s5p_mfc_mem_cleanup_user_shared_handle(ctx, &enc->sh_handle_roi);
+       s5p_mfc_release_enc_roi_buffer(ctx);
+       kfree(enc);
+}
+
+static int mfc_init_enc_ctx(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_enc *enc;
+       struct s5p_mfc_enc_params *p;
+       int ret = 0;
+       int i;
+
+       enc = kzalloc(sizeof(struct s5p_mfc_enc), GFP_KERNEL);
+       if (!enc) {
+               mfc_err_dev("failed to allocate encoder private data\n");
+               return -ENOMEM;
+       }
+       ctx->enc_priv = enc;
+
+       ctx->inst_no = MFC_NO_INSTANCE_SET;
+
+       s5p_mfc_create_queue(&ctx->src_buf_queue);
+       s5p_mfc_create_queue(&ctx->dst_buf_queue);
+       s5p_mfc_create_queue(&ctx->src_buf_nal_queue);
+       s5p_mfc_create_queue(&ctx->dst_buf_nal_queue);
+       s5p_mfc_create_queue(&ctx->ref_buf_queue);
+
+       for (i = 0; i < MFC_MAX_BUFFERS; i++) {
+               INIT_LIST_HEAD(&ctx->src_ctrls[i]);
+               INIT_LIST_HEAD(&ctx->dst_ctrls[i]);
+       }
+       ctx->src_ctrls_avail = 0;
+       ctx->dst_ctrls_avail = 0;
+
+       ctx->type = MFCINST_ENCODER;
+       ctx->c_ops = &encoder_ctrls_ops;
+       ctx->src_fmt = &enc_formats[DEF_ENC_SRC_FMT];
+       ctx->dst_fmt = &enc_formats[DEF_ENC_DST_FMT];
+
+       s5p_mfc_qos_reset_framerate(ctx);
+
+       ctx->qos_ratio = 100;
+
+       /* disable IVF header by default (VP8, VP9) */
+       p = &enc->params;
+       p->ivf_header_disable = 1;
+
+#ifdef CONFIG_MFC_USE_BUS_DEVFREQ
+       INIT_LIST_HEAD(&ctx->qos_list);
+#endif
+       INIT_LIST_HEAD(&ctx->ts_list);
+
+       enc->sh_handle_svc.fd = -1;
+       enc->sh_handle_roi.fd = -1;
+
+       /* Init videobuf2 queue for OUTPUT */
+       ctx->vq_src.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+       ctx->vq_src.drv_priv = ctx;
+       ctx->vq_src.buf_struct_size = sizeof(struct s5p_mfc_buf);
+       ctx->vq_src.io_modes = VB2_USERPTR | VB2_DMABUF;
+       ctx->vq_src.ops = &s5p_mfc_enc_qops;
+       ctx->vq_src.mem_ops = s5p_mfc_mem_ops();
+       ctx->vq_src.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+       ret = vb2_queue_init(&ctx->vq_src);
+       if (ret) {
+               mfc_err_dev("Failed to initialize videobuf2 queue(output)\n");
+               goto fail_enc_init;
+       }
+
+       /* Init videobuf2 queue for CAPTURE */
+       ctx->vq_dst.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+       ctx->vq_dst.drv_priv = ctx;
+       ctx->vq_dst.buf_struct_size = sizeof(struct s5p_mfc_buf);
+       ctx->vq_dst.io_modes = VB2_USERPTR | VB2_DMABUF;
+       ctx->vq_dst.ops = &s5p_mfc_enc_qops;
+       ctx->vq_dst.mem_ops = s5p_mfc_mem_ops();
+       ctx->vq_dst.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+       ret = vb2_queue_init(&ctx->vq_dst);
+       if (ret) {
+               mfc_err_dev("Failed to initialize videobuf2 queue(capture)\n");
+               goto fail_enc_init;
+       }
+
+       return 0;
+
+fail_enc_init:
+       mfc_deinit_enc_ctx(ctx);
+       return 0;
+}
+
+static int mfc_init_instance(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx)
+{
+       int ret = 0;
+
+       dev->watchdog_timer.expires = jiffies +
+               msecs_to_jiffies(WATCHDOG_TICK_INTERVAL);
+       add_timer(&dev->watchdog_timer);
+
+       /* Load the FW */
+       if (!dev->fw.status) {
+               ret = s5p_mfc_alloc_firmware(dev);
+               if (ret)
+                       goto err_fw_alloc;
+               dev->fw.status = 1;
+       }
+
+       ret = s5p_mfc_load_firmware(dev);
+       if (ret)
+               goto err_fw_load;
+
+#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
+       trace_mfc_dcpp_start(ctx->num, 1, dev->fw.drm_status);
+       if (!dev->drm_fw_buf.daddr) {
+               mfc_err_ctx("DRM F/W buffer is not allocated\n");
+               dev->fw.drm_status = 0;
+       } else {
+               /* Request buffer protection for DRM F/W */
+               ret = exynos_smc(SMC_DRM_PPMP_MFCFW_PROT,
+                               dev->drm_fw_buf.daddr, 0, 0);
+               if (ret != DRMDRV_OK) {
+                       mfc_err_ctx("failed MFC DRM F/W prot(%#x)\n", ret);
+                       call_dop(dev, dump_and_stop_debug_mode, dev);
+                       dev->fw.drm_status = 0;
+               } else {
+                       dev->fw.drm_status = 1;
+               }
+       }
+#endif
+       trace_mfc_dcpp_end(ctx->num, 1, dev->fw.drm_status);
+
+       ret = s5p_mfc_alloc_common_context(dev);
+       if (ret)
+               goto err_context_alloc;
+
+       if (dbg_enable)
+               s5p_mfc_alloc_dbg_info_buffer(dev);
+
+       MFC_TRACE_DEV_HWLOCK("**open\n");
+       ret = s5p_mfc_get_hwlock_dev(dev);
+       if (ret < 0) {
+               mfc_err_dev("Failed to get hwlock\n");
+               mfc_err_dev("dev.hwlock.dev = 0x%lx, bits = 0x%lx, owned_by_irq = %d, wl_count = %d, transfer_owner = %d\n",
+                               dev->hwlock.dev, dev->hwlock.bits, dev->hwlock.owned_by_irq,
+                               dev->hwlock.wl_count, dev->hwlock.transfer_owner);
+               goto err_hw_lock;
+       }
+
+       mfc_debug(2, "power on\n");
+       ret = s5p_mfc_pm_power_on(dev);
+       if (ret < 0) {
+               mfc_err_ctx("power on failed\n");
+               goto err_pwr_enable;
+       }
+
+       dev->curr_ctx = ctx->num;
+       dev->preempt_ctx = MFC_NO_INSTANCE_SET;
+       dev->curr_ctx_is_drm = ctx->is_drm;
+
+       ret = s5p_mfc_init_hw(dev);
+       if (ret) {
+               mfc_err_ctx("Failed to init mfc h/w\n");
+               goto err_hw_init;
+       }
+
+       if (dev->has_mmcache && (dev->mmcache.is_on_status == 0))
+               s5p_mfc_mmcache_enable(dev);
+
+
+       s5p_mfc_release_hwlock_dev(dev);
+
+       if (MFC_FEATURE_SUPPORT(dev, dev->pdata->nal_q)) {
+               dev->nal_q_handle = s5p_mfc_nal_q_create(dev);
+               if (dev->nal_q_handle == NULL)
+                       mfc_err_dev("[NALQ] Can't create nal q\n");
+       }
+
+       return ret;
+
+err_hw_init:
+       s5p_mfc_pm_power_off(dev);
+
+err_pwr_enable:
+       s5p_mfc_release_hwlock_dev(dev);
+
+err_hw_lock:
+       s5p_mfc_release_common_context(dev);
+
+err_context_alloc:
+#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
+       if (dev->fw.drm_status) {
+               int smc_ret = 0;
+               dev->fw.drm_status = 0;
+               /* Request buffer unprotection for DRM F/W */
+               smc_ret = exynos_smc(SMC_DRM_PPMP_MFCFW_UNPROT,
+                                       dev->drm_fw_buf.daddr, 0, 0);
+               if (smc_ret != DRMDRV_OK) {
+                       mfc_err_ctx("failed MFC DRM F/W unprot(%#x)\n", smc_ret);
+                       call_dop(dev, dump_and_stop_debug_mode, dev);
+               }
+       }
+#endif
+
+err_fw_load:
+err_fw_alloc:
+       del_timer_sync(&dev->watchdog_timer);
+
+       mfc_err_dev("failed to init first instance\n");
+       return ret;
+}
+
+/* Open an MFC node */
+static int s5p_mfc_open(struct file *file)
+{
+       struct s5p_mfc_ctx *ctx = NULL;
+       struct s5p_mfc_dev *dev = video_drvdata(file);
+       int ret = 0;
+       enum s5p_mfc_node_type node;
+       struct video_device *vdev = NULL;
+
+       mfc_debug(2, "mfc driver open called\n");
+
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               goto err_no_device;
+       }
+
+       if (mutex_lock_interruptible(&dev->mfc_mutex))
+               return -ERESTARTSYS;
+
+       node = s5p_mfc_get_node_type(file);
+       if (node == MFCNODE_INVALID) {
+               mfc_err_dev("cannot specify node type\n");
+               ret = -ENOENT;
+               goto err_node_type;
+       }
+
+       dev->num_inst++;        /* It is guarded by mfc_mutex in vfd */
+
+       /* Allocate memory for context */
+       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+       if (!ctx) {
+               mfc_err_dev("Not enough memory\n");
+               ret = -ENOMEM;
+               goto err_ctx_alloc;
+       }
+
+       switch (node) {
+       case MFCNODE_DECODER:
+               vdev = dev->vfd_dec;
+               break;
+       case MFCNODE_ENCODER:
+               vdev = dev->vfd_enc;
+               break;
+       case MFCNODE_DECODER_DRM:
+               vdev = dev->vfd_dec_drm;
+               break;
+       case MFCNODE_ENCODER_DRM:
+               vdev = dev->vfd_enc_drm;
+               break;
+       case MFCNODE_ENCODER_OTF:
+               vdev = dev->vfd_enc_otf;
+               break;
+       case MFCNODE_ENCODER_OTF_DRM:
+               vdev = dev->vfd_enc_otf_drm;
+               break;
+       default:
+               mfc_err_dev("Invalid node(%d)\n", node);
+               break;
+       }
+
+       if (!vdev)
+               goto err_vdev;
+
+       v4l2_fh_init(&ctx->fh, vdev);
+       file->private_data = &ctx->fh;
+       v4l2_fh_add(&ctx->fh);
+
+       ctx->dev = dev;
+
+       /* Get context number */
+       ctx->num = 0;
+       while (dev->ctx[ctx->num]) {
+               ctx->num++;
+               if (ctx->num >= MFC_NUM_CONTEXTS) {
+                       mfc_err_dev("Too many open contexts\n");
+                       ret = -EBUSY;
+                       goto err_ctx_num;
+               }
+       }
+
+       init_waitqueue_head(&ctx->cmd_wq);
+       s5p_mfc_init_listable_wq_ctx(ctx);
+       spin_lock_init(&ctx->buf_queue_lock);
+
+       if (s5p_mfc_is_decoder_node(node))
+               ret = mfc_init_dec_ctx(ctx);
+       else
+               ret = mfc_init_enc_ctx(ctx);
+       if (ret)
+               goto err_ctx_init;
+
+       ret = call_cop(ctx, init_ctx_ctrls, ctx);
+       if (ret) {
+               mfc_err_ctx("failed in init_ctx_ctrls\n");
+               goto err_ctx_ctrls;
+       }
+
+#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
+       if (s5p_mfc_is_drm_node(node)) {
+               if (dev->num_drm_inst < MFC_MAX_DRM_CTX) {
+                       if (ctx->raw_protect_flag || ctx->stream_protect_flag) {
+                               mfc_err_ctx("protect_flag(%#lx/%#lx) remained\n",
+                                               ctx->raw_protect_flag,
+                                               ctx->stream_protect_flag);
+                               ret = -EINVAL;
+                               goto err_drm_start;
+                       }
+                       dev->num_drm_inst++;
+                       ctx->is_drm = 1;
+
+                       mfc_info_ctx("DRM instance is opened [%d:%d]\n",
+                                       dev->num_drm_inst, dev->num_inst);
+               } else {
+                       mfc_err_ctx("Too many instance are opened for DRM\n");
+                       ret = -EINVAL;
+                       goto err_drm_start;
+               }
+       } else {
+               mfc_info_ctx("NORMAL instance is opened [%d:%d]\n",
+                               dev->num_drm_inst, dev->num_inst);
+       }
+#endif
+
+       /* Mark context as idle */
+       s5p_mfc_clear_bit(ctx->num, &dev->work_bits);
+       dev->ctx[ctx->num] = ctx;
+
+       /* Load firmware if this is the first instance */
+       if (dev->num_inst == 1) {
+               ret = mfc_init_instance(dev, ctx);
+               if (ret)
+                       goto err_init_inst;
+
+               if (perf_boost_mode)
+                       s5p_mfc_perf_boost_enable(dev);
+       }
+
+#ifdef CONFIG_VIDEO_EXYNOS_REPEATER
+       if (s5p_mfc_is_encoder_otf_node(node)) {
+               ret = s5p_mfc_otf_create(ctx);
+               if (ret)
+                       mfc_err_ctx("[OTF] otf_create failed\n");
+       }
+#endif
+
+       s5p_mfc_perf_init(dev);
+       trace_mfc_node_open(ctx->num, dev->num_inst, ctx->type, ctx->is_drm);
+       mfc_info_ctx("MFC open completed [%d:%d] dev = 0x%p, ctx = 0x%p, version = %d\n",
+                       dev->num_drm_inst, dev->num_inst, dev, ctx, MFC_DRIVER_INFO);
+       mutex_unlock(&dev->mfc_mutex);
+       return ret;
+
+       /* Deinit when failure occured */
+err_init_inst:
+#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
+       if (ctx->is_drm)
+               dev->num_drm_inst--;
+
+err_drm_start:
+#endif
+       call_cop(ctx, cleanup_ctx_ctrls, ctx);
+
+err_ctx_ctrls:
+err_ctx_init:
+       dev->ctx[ctx->num] = 0;
+
+err_ctx_num:
+       v4l2_fh_del(&ctx->fh);
+       v4l2_fh_exit(&ctx->fh);
+
+err_vdev:
+       kfree(ctx);
+
+err_ctx_alloc:
+       dev->num_inst--;
+
+err_node_type:
+       mfc_info_dev("MFC driver open is failed [%d:%d]\n",
+                       dev->num_drm_inst, dev->num_inst);
+       mutex_unlock(&dev->mfc_mutex);
+
+err_no_device:
+
+       return ret;
+}
+
+static int mfc_wait_close_inst(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx)
+{
+       if (atomic_read(&dev->watchdog_run)) {
+               mfc_err_ctx("watchdog already running!\n");
+               return 0;
+       }
+
+       if (ctx->inst_no == MFC_NO_INSTANCE_SET) {
+               mfc_debug(2, "mfc no instance already\n");
+               return 0;
+       }
+
+       s5p_mfc_clean_ctx_int_flags(ctx);
+       s5p_mfc_change_state(ctx, MFCINST_RETURN_INST);
+       s5p_mfc_set_bit(ctx->num, &dev->work_bits);
+
+       /* To issue the command 'CLOSE_INSTANCE' */
+       if (s5p_mfc_just_run(dev, ctx->num)) {
+               mfc_err_ctx("Failed to run MFC\n");
+               return -EIO;
+       }
+
+       /* Wait until instance is returned or timeout occured */
+       if (s5p_mfc_wait_for_done_ctx(ctx,
+                               S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET) == 1) {
+               mfc_err_ctx("Waiting for CLOSE_INSTANCE timed out\n");
+               if (s5p_mfc_wait_for_done_ctx(ctx,
+                                       S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET)) {
+                       mfc_err_ctx("waiting once more but timed out\n");
+                       dev->logging_data->cause |= (1 << MFC_CAUSE_FAIL_CLOSE_INST);
+                       call_dop(dev, dump_and_stop_always, dev);
+               }
+       }
+
+       ctx->inst_no = MFC_NO_INSTANCE_SET;
+
+       return 0;
+}
+
+/* Release MFC context */
+static int s5p_mfc_release(struct file *file)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+       struct s5p_mfc_dev *dev = NULL;
+       int ret = 0;
+
+       dev = ctx->dev;
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return -EINVAL;
+       }
+
+       mutex_lock(&dev->mfc_mutex);
+
+       mfc_info_ctx("MFC driver release is called [%d:%d], is_drm(%d)\n",
+                       dev->num_drm_inst, dev->num_inst, ctx->is_drm);
+
+       s5p_mfc_clear_bit(ctx->num, &dev->work_bits);
+
+       /* If a H/W operation is in progress, wait for it complete */
+       if (need_to_wait_nal_abort(ctx)) {
+               if (s5p_mfc_wait_for_done_ctx(ctx, S5P_FIMV_R2H_CMD_NAL_ABORT_RET)) {
+                       mfc_err_ctx("Failed to wait nal abort\n");
+                       s5p_mfc_cleanup_work_bit_and_try_run(ctx);
+               }
+       }
+       MFC_TRACE_CTX_HWLOCK("**release\n");
+       ret = s5p_mfc_get_hwlock_ctx(ctx);
+       if (ret < 0) {
+               mfc_err_dev("Failed to get hwlock\n");
+               mutex_unlock(&dev->mfc_mutex);
+               return -EBUSY;
+       }
+
+       if (call_cop(ctx, cleanup_ctx_ctrls, ctx) < 0)
+               mfc_err_ctx("failed in cleanup_ctx_ctrl\n");
+
+       v4l2_fh_del(&ctx->fh);
+       v4l2_fh_exit(&ctx->fh);
+
+       /* Mark context as idle */
+       s5p_mfc_clear_bit(ctx->num, &dev->work_bits);
+
+       /* If instance was initialised then
+        * return instance and free reosurces */
+       ret = mfc_wait_close_inst(dev, ctx);
+       if (ret)
+               goto err_release_try;
+
+       if (ctx->is_drm)
+               dev->num_drm_inst--;
+       dev->num_inst--;
+
+       if (dev->num_inst == 0) {
+               s5p_mfc_deinit_hw(dev);
+
+               if (perf_boost_mode)
+                       s5p_mfc_perf_boost_disable(dev);
+
+               del_timer_sync(&dev->watchdog_timer);
+
+               flush_workqueue(dev->butler_wq);
+
+               mfc_debug(2, "power off\n");
+               s5p_mfc_pm_power_off(dev);
+
+               if (dbg_enable)
+                       s5p_mfc_release_dbg_info_buffer(dev);
+
+               s5p_mfc_release_common_context(dev);
+
+#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
+               if (dev->fw.drm_status) {
+                       dev->fw.drm_status = 0;
+                       /* Request buffer unprotection for DRM F/W */
+                       ret = exynos_smc(SMC_DRM_PPMP_MFCFW_UNPROT,
+                                       dev->drm_fw_buf.daddr, 0, 0);
+                       if (ret != DRMDRV_OK) {
+                               mfc_err_ctx("failed MFC DRM F/W unprot(%#x)\n", ret);
+                               call_dop(dev, dump_and_stop_debug_mode, dev);
+                               goto err_release;
+                       }
+               }
+#endif
+
+               if (dev->nal_q_handle) {
+                       ret = s5p_mfc_nal_q_destroy(dev, dev->nal_q_handle);
+                       if (ret) {
+                               mfc_err_ctx("failed nal_q destroy\n");
+                               goto err_release;
+                       }
+               }
+       }
+
+       s5p_mfc_qos_off(ctx);
+
+       if (dev->has_mmcache && dev->mmcache.is_on_status) {
+               s5p_mfc_invalidate_mmcache(dev);
+
+               if (dev->num_inst == 0)
+                       s5p_mfc_mmcache_disable(dev);
+       }
+
+       s5p_mfc_release_codec_buffers(ctx);
+       s5p_mfc_release_instance_context(ctx);
+
+       s5p_mfc_release_hwlock_ctx(ctx);
+
+       /* Free resources */
+       vb2_queue_release(&ctx->vq_src);
+       vb2_queue_release(&ctx->vq_dst);
+
+       if (ctx->type == MFCINST_DECODER)
+               mfc_deinit_dec_ctx(ctx);
+       else if (ctx->type == MFCINST_ENCODER)
+               mfc_deinit_enc_ctx(ctx);
+
+#ifdef CONFIG_VIDEO_EXYNOS_REPEATER
+       if (ctx->otf_handle) {
+               s5p_mfc_otf_deinit(ctx);
+               s5p_mfc_otf_destroy(ctx);
+       }
+#endif
+
+       s5p_mfc_destroy_listable_wq_ctx(ctx);
+
+       trace_mfc_node_close(ctx->num, dev->num_inst, ctx->type, ctx->is_drm);
+
+       dev->ctx[ctx->num] = 0;
+       kfree(ctx);
+
+       s5p_mfc_perf_print();
+
+       mfc_info_dev("mfc driver release finished [%d:%d], dev = 0x%p\n",
+                       dev->num_drm_inst, dev->num_inst, dev);
+
+       if (s5p_mfc_is_work_to_do(dev))
+               queue_work(dev->butler_wq, &dev->butler_work);
+
+       mutex_unlock(&dev->mfc_mutex);
+       return ret;
+
+err_release:
+       s5p_mfc_release_hwlock_ctx(ctx);
+       mutex_unlock(&dev->mfc_mutex);
+       return ret;
+
+err_release_try:
+       s5p_mfc_release_hwlock_ctx(ctx);
+       s5p_mfc_cleanup_work_bit_and_try_run(ctx);
+       mutex_unlock(&dev->mfc_mutex);
+       return ret;
+}
+
+/* Poll */
+static unsigned int s5p_mfc_poll(struct file *file,
+                                struct poll_table_struct *wait)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+       unsigned long req_events = poll_requested_events(wait);
+       unsigned int ret = 0;
+
+       mfc_debug_enter();
+
+       if (req_events & (POLLOUT | POLLWRNORM)) {
+               mfc_debug(2, "wait source buffer\n");
+               ret = vb2_poll(&ctx->vq_src, file, wait);
+       } else if (req_events & (POLLIN | POLLRDNORM)) {
+               mfc_debug(2, "wait destination buffer\n");
+               ret = vb2_poll(&ctx->vq_dst, file, wait);
+       }
+
+       mfc_debug_leave();
+       return ret;
+}
+
+/* Mmap */
+static int s5p_mfc_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+       unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+       int ret;
+
+       mfc_debug_enter();
+
+       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);
+       }
+       mfc_debug_leave();
+       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,
+};
+
+#ifdef CONFIG_MFC_USE_BUS_DEVFREQ
+static int mfc_parse_mfc_qos_platdata(struct device_node *np, char *node_name,
+       struct s5p_mfc_qos *qosdata)
+{
+       int ret = 0;
+       struct device_node *np_qos;
+
+       np_qos = of_find_node_by_name(np, node_name);
+       if (!np_qos) {
+               pr_err("%s: could not find mfc_qos_platdata node\n",
+                       node_name);
+               return -EINVAL;
+       }
+
+       of_property_read_u32(np_qos, "thrd_mb", &qosdata->threshold_mb);
+       of_property_read_u32(np_qos, "freq_mfc", &qosdata->freq_mfc);
+       of_property_read_u32(np_qos, "freq_int", &qosdata->freq_int);
+       of_property_read_u32(np_qos, "freq_mif", &qosdata->freq_mif);
+       of_property_read_u32(np_qos, "mo_value", &qosdata->mo_value);
+       of_property_read_u32(np_qos, "mo_10bit_value", &qosdata->mo_10bit_value);
+       of_property_read_u32(np_qos, "mo_uhd_enc60_value", &qosdata->mo_uhd_enc60_value);
+       of_property_read_u32(np_qos, "time_fw", &qosdata->time_fw);
+
+       return ret;
+}
+#endif
+
+int s5p_mfc_sysmmu_fault_handler(struct iommu_domain *iodmn, struct device *device,
+               unsigned long addr, int id, void *param)
+{
+       struct s5p_mfc_dev *dev;
+
+       dev = (struct s5p_mfc_dev *)param;
+
+       /* [OTF] If AxID is 1 in SYSMMU1 fault info, it is TS-MUX fault */
+       if (dev->has_hwfc && dev->has_2sysmmu) {
+               if (MFC_MMU1_READL(MFC_MMU_INTERRUPT_STATUS) &&
+                               ((MFC_MMU1_READL(MFC_MMU_FAULT_TRANS_INFO) &
+                                 MFC_MMU_FAULT_TRANS_INFO_AXID_MASK) == 1)) {
+                       mfc_err_dev("There is TS-MUX page fault. skip SFR dump\n");
+                       return 0;
+               }
+       }
+
+       /* If sysmmu is used with other IPs, it should be checked whether it's an MFC fault */
+       if (dev->pdata->share_sysmmu) {
+               if ((MFC_MMU0_READL(MFC_MMU_FAULT_TRANS_INFO) & dev->pdata->axid_mask)
+                               != dev->pdata->mfc_fault_num) {
+                       mfc_err_dev("This is not a MFC page fault\n");
+                       return 0;
+               }
+       }
+
+       if (MFC_MMU0_READL(MFC_MMU_INTERRUPT_STATUS)) {
+               if (MFC_MMU0_READL(MFC_MMU_FAULT_TRANS_INFO) & MFC_MMU_FAULT_TRANS_INFO_RW_MASK)
+                       dev->logging_data->cause |= (1 << MFC_CAUSE_0WRITE_PAGE_FAULT);
+               else
+                       dev->logging_data->cause |= (1 << MFC_CAUSE_0READ_PAGE_FAULT);
+               dev->logging_data->fault_status = MFC_MMU0_READL(MFC_MMU_INTERRUPT_STATUS);
+               dev->logging_data->fault_trans_info = MFC_MMU0_READL(MFC_MMU_FAULT_TRANS_INFO);
+       }
+
+       if (dev->has_2sysmmu) {
+               if (MFC_MMU1_READL(MFC_MMU_INTERRUPT_STATUS)) {
+                       if (MFC_MMU1_READL(MFC_MMU_FAULT_TRANS_INFO) & MFC_MMU_FAULT_TRANS_INFO_RW_MASK)
+                               dev->logging_data->cause |= (1 << MFC_CAUSE_1WRITE_PAGE_FAULT);
+                       else
+                               dev->logging_data->cause |= (1 << MFC_CAUSE_1READ_PAGE_FAULT);
+                       dev->logging_data->fault_status = MFC_MMU1_READL(MFC_MMU_INTERRUPT_STATUS);
+                       dev->logging_data->fault_trans_info = MFC_MMU1_READL(MFC_MMU_FAULT_TRANS_INFO);
+               }
+       }
+       dev->logging_data->fault_addr = (unsigned int)addr;
+
+       call_dop(dev, dump_info, dev);
+
+       return 0;
+}
+
+static void mfc_parse_dt(struct device_node *np, struct s5p_mfc_dev *mfc)
+{
+       struct s5p_mfc_platdata *pdata = mfc->pdata;
+#ifdef CONFIG_MFC_USE_BUS_DEVFREQ
+       struct device_node *np_qos;
+       char node_name[50];
+       int i;
+#endif
+
+       if (!np)
+               return;
+
+       /* MFC version */
+       of_property_read_u32(np, "ip_ver", &pdata->ip_ver);
+
+       /* Debug mode */
+       of_property_read_u32(np, "debug_mode", &pdata->debug_mode);
+
+       /* Sysmmu check */
+       of_property_read_u32(np, "share_sysmmu", &pdata->share_sysmmu);
+       of_property_read_u32(np, "axid_mask", &pdata->axid_mask);
+       of_property_read_u32(np, "mfc_fault_num", &pdata->mfc_fault_num);
+
+       /* Features */
+       of_property_read_u32_array(np, "nal_q", &pdata->nal_q.support, 2);
+       of_property_read_u32_array(np, "skype", &pdata->skype.support, 2);
+       of_property_read_u32_array(np, "black_bar", &pdata->black_bar.support, 2);
+       of_property_read_u32_array(np, "color_aspect_dec", &pdata->color_aspect_dec.support, 2);
+       of_property_read_u32_array(np, "static_info_dec", &pdata->static_info_dec.support, 2);
+       of_property_read_u32_array(np, "color_aspect_enc", &pdata->color_aspect_enc.support, 2);
+       of_property_read_u32_array(np, "static_info_enc", &pdata->static_info_enc.support, 2);
+
+       /* Default 10bit format for decoding */
+       of_property_read_u32(np, "P010_decoding", &pdata->P010_decoding);
+
+       /* Formats */
+       of_property_read_u32(np, "support_10bit", &pdata->support_10bit);
+       of_property_read_u32(np, "support_422", &pdata->support_422);
+       of_property_read_u32(np, "support_rgb", &pdata->support_rgb);
+
+       /* Encoder default parameter */
+       of_property_read_u32(np, "enc_param_num", &pdata->enc_param_num);
+       if (pdata->enc_param_num) {
+               of_property_read_u32_array(np, "enc_param_addr",
+                               pdata->enc_param_addr, pdata->enc_param_num);
+               of_property_read_u32_array(np, "enc_param_val",
+                               pdata->enc_param_val, pdata->enc_param_num);
+       }
+
+#ifdef CONFIG_MFC_USE_BUS_DEVFREQ
+       /* QoS */
+       of_property_read_u32(np, "num_qos_steps", &pdata->num_qos_steps);
+       of_property_read_u32(np, "max_qos_steps", &pdata->max_qos_steps);
+       of_property_read_u32(np, "max_mb", &pdata->max_mb);
+       of_property_read_u32(np, "mfc_freq_control", &pdata->mfc_freq_control);
+       of_property_read_u32(np, "mo_control", &pdata->mo_control);
+       of_property_read_u32(np, "bw_control", &pdata->bw_control);
+
+       pdata->qos_table = devm_kzalloc(mfc->device,
+                       sizeof(struct s5p_mfc_qos) * pdata->max_qos_steps, GFP_KERNEL);
+
+       for (i = 0; i < pdata->max_qos_steps; i++) {
+               snprintf(node_name, sizeof(node_name), "mfc_qos_variant_%d", i);
+               mfc_parse_mfc_qos_platdata(np, node_name, &pdata->qos_table[i]);
+       }
+
+       /* performance boost mode */
+       pdata->qos_boost_table = devm_kzalloc(mfc->device,
+                       sizeof(struct s5p_mfc_qos_boost), GFP_KERNEL);
+       np_qos = of_find_node_by_name(np, "mfc_perf_boost_table");
+       if (!np_qos) {
+               pr_err("%s:[QoS] could not find mfc_perf_boost_table node\n", node_name);
+               return;
+       }
+       of_property_read_u32(np_qos, "num_cluster", &pdata->qos_boost_table->num_cluster);
+       of_property_read_u32(np_qos, "freq_mfc", &pdata->qos_boost_table->freq_mfc);
+       of_property_read_u32(np_qos, "freq_int", &pdata->qos_boost_table->freq_int);
+       of_property_read_u32(np_qos, "freq_mif", &pdata->qos_boost_table->freq_mif);
+       of_property_read_u32_array(np_qos, "freq_cluster", &pdata->qos_boost_table->freq_cluster[0],
+                       pdata->qos_boost_table->num_cluster);
+#endif
+}
+
+static void *mfc_get_drv_data(struct platform_device *pdev);
+
+static struct video_device *mfc_video_device_register(struct s5p_mfc_dev *dev,
+                               char *name, int node_num)
+{
+       struct video_device *vfd;
+       int ret = 0;
+
+       vfd = video_device_alloc();
+       if (!vfd) {
+               v4l2_err(&dev->v4l2_dev, "Failed to allocate video device\n");
+               return NULL;
+       }
+       strncpy(vfd->name, name, sizeof(vfd->name) - 1);
+       vfd->fops = &s5p_mfc_fops;
+       vfd->minor = -1;
+       vfd->release = video_device_release;
+
+       if (IS_DEC_NODE(node_num))
+               vfd->ioctl_ops = s5p_mfc_get_dec_v4l2_ioctl_ops();
+       else if(IS_ENC_NODE(node_num))
+               vfd->ioctl_ops = s5p_mfc_get_enc_v4l2_ioctl_ops();
+
+       vfd->lock = &dev->mfc_mutex;
+       vfd->v4l2_dev = &dev->v4l2_dev;
+       vfd->vfl_dir = VFL_DIR_M2M;
+
+       snprintf(vfd->name, sizeof(vfd->name), "%s%d", vfd->name, dev->id);
+
+       ret = video_register_device(vfd, VFL_TYPE_GRABBER, node_num + 60 * dev->id);
+       if (ret) {
+               v4l2_err(&dev->v4l2_dev, "Failed to register video device /dev/video%d\n", node_num);
+               video_device_release(vfd);
+               return NULL;
+       }
+       v4l2_info(&dev->v4l2_dev, "video device registered as /dev/video%d\n",
+                                                               vfd->num);
+       video_set_drvdata(vfd, dev);
+
+       return vfd;
+}
+
+static int mfc_register_resource(struct platform_device *pdev, struct s5p_mfc_dev *dev)
+{
+       struct device_node *np = dev->device->of_node;
+       struct device_node *iommu;
+       struct device_node *hwfc;
+       struct device_node *mmcache;
+       struct resource *res;
+       int ret;
+
+       s5p_mfc_perf_register(dev);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (res == NULL) {
+               dev_err(&pdev->dev, "failed to get memory region resource\n");
+               return -ENOENT;
+       }
+       dev->mfc_mem = request_mem_region(res->start, resource_size(res), pdev->name);
+       if (dev->mfc_mem == NULL) {
+               dev_err(&pdev->dev, "failed to get memory region\n");
+               return -ENOENT;
+       }
+       dev->regs_base = ioremap(dev->mfc_mem->start, resource_size(dev->mfc_mem));
+       if (dev->regs_base == NULL) {
+               dev_err(&pdev->dev, "failed to ioremap address region\n");
+               goto err_ioremap;
+       }
+
+       iommu = of_get_child_by_name(np, "iommu");
+       if (!iommu) {
+               dev_err(&pdev->dev, "failed to get iommu node\n");
+               goto err_ioremap_mmu0;
+       }
+
+       dev->sysmmu0_base = of_iomap(iommu, 0);
+       if (dev->sysmmu0_base == NULL) {
+               dev_err(&pdev->dev, "failed to ioremap sysmmu0 address region\n");
+               goto err_ioremap_mmu0;
+       }
+
+       dev->sysmmu1_base = of_iomap(iommu, 1);
+       if (dev->sysmmu1_base == NULL) {
+               pr_debug("there is only one MFC sysmmu\n");
+       } else {
+               dev->has_2sysmmu = 1;
+       }
+
+       hwfc = of_get_child_by_name(np, "hwfc");
+       if (hwfc) {
+               dev->hwfc_base = of_iomap(hwfc, 0);
+               if (dev->hwfc_base == NULL) {
+                       dev->has_hwfc = 0;
+                       dev_err(&pdev->dev, "failed to iomap hwfc address region\n");
+                       goto err_ioremap_hwfc;
+               } else {
+                       dev->has_hwfc = 1;
+               }
+       }
+
+       mmcache = of_get_child_by_name(np, "mmcache");
+       if (mmcache) {
+               dev->mmcache.base = of_iomap(mmcache, 0);
+               if (dev->mmcache.base == NULL) {
+                       dev->has_mmcache = 0;
+                       dev_err(&pdev->dev, "failed to iomap mmcache address region\n");
+                       goto err_ioremap_mmcache;
+               } else {
+                       dev->has_mmcache = 1;
+               }
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (res == NULL) {
+               dev_err(&pdev->dev, "failed to get irq resource\n");
+               goto err_res_irq;
+       }
+       dev->irq = res->start;
+       ret = request_threaded_irq(dev->irq, s5p_mfc_top_half_irq, s5p_mfc_irq,
+                               IRQF_ONESHOT, pdev->name, dev);
+       if (ret != 0) {
+               dev_err(&pdev->dev, "failed to install irq (%d)\n", ret);
+               goto err_res_irq;
+       }
+
+       return 0;
+
+err_res_irq:
+       if (dev->has_mmcache)
+               iounmap(dev->mmcache.base);
+err_ioremap_mmcache:
+       if (dev->has_hwfc)
+               iounmap(dev->hwfc_base);
+err_ioremap_hwfc:
+       if (dev->has_2sysmmu)
+               iounmap(dev->sysmmu1_base);
+       iounmap(dev->sysmmu0_base);
+err_ioremap_mmu0:
+       iounmap(dev->regs_base);
+err_ioremap:
+       release_mem_region(dev->mfc_mem->start, resource_size(dev->mfc_mem));
+       return -ENOENT;
+}
+
+#ifdef CONFIG_EXYNOS_ITMON
+static int mfc_itmon_notifier(struct notifier_block *nb, unsigned long action, void *nb_data)
+{
+       struct s5p_mfc_dev *dev;
+       struct itmon_notifier *itmon_info = nb_data;
+       int is_mfc_itmon = 0, is_master = 0;
+
+       dev = container_of(nb, struct s5p_mfc_dev, itmon_nb);
+
+       if (IS_ERR_OR_NULL(itmon_info))
+               return NOTIFY_DONE;
+
+       if (!itmon_info->master)
+               return NOTIFY_DONE;
+
+       /* print dump if it is an MFC ITMON error */
+       if ((strncmp("MFC", itmon_info->port, sizeof("MFC") - 1) == 0) &&
+                       (strncmp("MFC", itmon_info->master, sizeof("MFC") - 1) == 0)) {
+               is_mfc_itmon = 1;
+               is_master = 1;
+       } else if (strncmp("MFC", itmon_info->dest, sizeof("MFC") - 1) == 0) {
+               is_mfc_itmon = 1;
+               is_master = 0;
+       }
+
+       if (is_mfc_itmon) {
+               pr_err("mfc_itmon_notifier: MFC +\n");
+               pr_err("MFC is %s\n", is_master ? "master" : "dest");
+               if (!dev->itmon_notified) {
+                       pr_err("dump MFC information\n");
+                       if (is_master || (!is_master && itmon_info->onoff))
+                               call_dop(dev, dump_info, dev);
+                       else
+                               call_dop(dev, dump_info_without_regs, dev);
+               } else {
+                       pr_err("MFC notifier has already been called. skip MFC information\n");
+               }
+               pr_err("mfc_itmon_notifier: MFC -\n");
+               dev->itmon_notified = 1;
+       }
+       return NOTIFY_DONE;
+}
+#endif
+
+/* MFC probe function */
+static int s5p_mfc_probe(struct platform_device *pdev)
+{
+       struct s5p_mfc_dev *dev;
+       int ret = -ENOENT;
+#ifdef CONFIG_MFC_USE_BUS_DEVFREQ
+       int i;
+#endif
+
+       dev_dbg(&pdev->dev, "%s()\n", __func__);
+       dev = devm_kzalloc(&pdev->dev, sizeof(struct s5p_mfc_dev), GFP_KERNEL);
+       if (!dev) {
+               dev_err(&pdev->dev, "Not enough memory for MFC device\n");
+               return -ENOMEM;
+       }
+
+       dev->device = &pdev->dev;
+       dev->pdata = pdev->dev.platform_data;
+
+       dev->variant = mfc_get_drv_data(pdev);
+
+       if (dev->device->of_node)
+               dev->id = of_alias_get_id(pdev->dev.of_node, "mfc");
+
+       dev_dbg(&pdev->dev, "of alias get id : mfc-%d \n", dev->id);
+
+       if (dev->id < 0 || dev->id >= dev->variant->num_entities) {
+               dev_err(&pdev->dev, "Invalid platform device id: %d\n", dev->id);
+               ret = -EINVAL;
+               goto err_pm;
+       }
+
+       dev->pdata = devm_kzalloc(&pdev->dev, sizeof(struct s5p_mfc_platdata), GFP_KERNEL);
+       if (!dev->pdata) {
+               dev_err(&pdev->dev, "no memory for state\n");
+               ret = -ENOMEM;
+               goto err_pm;
+       }
+
+       mfc_parse_dt(dev->device->of_node, dev);
+
+       atomic_set(&dev->trace_ref, 0);
+       atomic_set(&dev->trace_ref_hwlock, 0);
+       dev->mfc_trace = g_mfc_trace;
+       dev->mfc_trace_hwlock = g_mfc_trace_hwlock;
+
+       dma_set_mask(&pdev->dev, DMA_BIT_MASK(36));
+
+       s5p_mfc_pm_init(dev);
+       ret = mfc_register_resource(pdev, dev);
+       if (ret)
+               goto err_res_mem;
+
+       mutex_init(&dev->mfc_mutex);
+
+       ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
+       if (ret)
+               goto err_v4l2_dev;
+
+       init_waitqueue_head(&dev->cmd_wq);
+       s5p_mfc_init_listable_wq_dev(dev);
+
+       /* decoder */
+       dev->vfd_dec = mfc_video_device_register(dev, S5P_MFC_DEC_NAME,
+                       EXYNOS_VIDEONODE_MFC_DEC);
+       if (!dev->vfd_dec) {
+               ret = -ENOMEM;
+               goto alloc_vdev_dec;
+       }
+
+       /* encoder */
+       dev->vfd_enc = mfc_video_device_register(dev, S5P_MFC_ENC_NAME,
+                       EXYNOS_VIDEONODE_MFC_ENC);
+       if (!dev->vfd_enc) {
+               ret = -ENOMEM;
+               goto alloc_vdev_enc;
+       }
+
+       /* secure decoder */
+       dev->vfd_dec_drm = mfc_video_device_register(dev, S5P_MFC_DEC_DRM_NAME,
+                       EXYNOS_VIDEONODE_MFC_DEC_DRM);
+       if (!dev->vfd_dec_drm) {
+               ret = -ENOMEM;
+               goto alloc_vdev_dec_drm;
+       }
+
+       /* secure encoder */
+       dev->vfd_enc_drm = mfc_video_device_register(dev, S5P_MFC_ENC_DRM_NAME,
+                       EXYNOS_VIDEONODE_MFC_ENC_DRM);
+       if (!dev->vfd_enc_drm) {
+               ret = -ENOMEM;
+               goto alloc_vdev_enc_drm;
+       }
+
+       /* OTF encoder */
+       dev->vfd_enc_otf = mfc_video_device_register(dev, S5P_MFC_ENC_OTF_NAME,
+                       EXYNOS_VIDEONODE_MFC_ENC_OTF);
+       if (!dev->vfd_enc_otf) {
+               ret = -ENOMEM;
+               goto alloc_vdev_enc_otf;
+       }
+
+       /* OTF secure encoder */
+       dev->vfd_enc_otf_drm = mfc_video_device_register(dev, S5P_MFC_ENC_OTF_DRM_NAME,
+                       EXYNOS_VIDEONODE_MFC_ENC_OTF_DRM);
+       if (!dev->vfd_enc_otf_drm) {
+               ret = -ENOMEM;
+               goto alloc_vdev_enc_otf_drm;
+       }
+       /* end of node setting*/
+
+       platform_set_drvdata(pdev, dev);
+
+       s5p_mfc_init_hwlock(dev);
+       s5p_mfc_create_bits(&dev->work_bits);
+
+       dev->watchdog_wq =
+               create_singlethread_workqueue("s5p_mfc/watchdog");
+       if (!dev->watchdog_wq) {
+               dev_err(&pdev->dev, "failed to create workqueue for watchdog\n");
+               goto err_wq_watchdog;
+       }
+       INIT_WORK(&dev->watchdog_work, s5p_mfc_watchdog_worker);
+       atomic_set(&dev->watchdog_tick_running, 0);
+       atomic_set(&dev->watchdog_tick_cnt, 0);
+       atomic_set(&dev->watchdog_run, 0);
+       init_timer(&dev->watchdog_timer);
+       dev->watchdog_timer.data = (unsigned long)dev;
+       dev->watchdog_timer.function = s5p_mfc_watchdog_tick;
+
+#ifdef CONFIG_MFC_USE_BUS_DEVFREQ
+       INIT_LIST_HEAD(&dev->qos_queue);
+#endif
+
+       /* default FW alloc is added */
+       dev->butler_wq = alloc_workqueue("s5p_mfc/butler", WQ_UNBOUND
+                                       | WQ_MEM_RECLAIM | WQ_HIGHPRI, 1);
+       if (dev->butler_wq == NULL) {
+               dev_err(&pdev->dev, "failed to create workqueue for butler\n");
+               goto err_butler_wq;
+       }
+       INIT_WORK(&dev->butler_work, s5p_mfc_butler_worker);
+
+       /* dump information call-back function */
+       dev->dump_ops = &mfc_dump_ops;
+
+#ifdef CONFIG_MFC_USE_BUS_DEVFREQ
+       atomic_set(&dev->qos_req_cur, 0);
+
+       mfc_info_dev("[QoS] control: mfc_freq(%d), mo(%d), bw(%d)\n",
+                       dev->pdata->mfc_freq_control, dev->pdata->mo_control, dev->pdata->bw_control);
+       for (i = 0; i < dev->pdata->num_qos_steps; i++) {
+               mfc_info_dev("[QoS] table[%d] mfc: %d, int : %d, mif : %d\n",
+                               i,
+                               dev->pdata->qos_table[i].freq_mfc,
+                               dev->pdata->qos_table[i].freq_int,
+                               dev->pdata->qos_table[i].freq_mif);
+       }
+#endif
+
+       iovmm_set_fault_handler(dev->device,
+               s5p_mfc_sysmmu_fault_handler, dev);
+
+       g_mfc_dev = dev;
+
+       ret = iovmm_activate(&pdev->dev);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Failed to activate iommu\n");
+               goto err_iovmm_active;
+       }
+
+       dev->logging_data = devm_kzalloc(&pdev->dev, sizeof(struct s5p_mfc_debug), GFP_KERNEL);
+       if (!dev->logging_data) {
+               dev_err(&pdev->dev, "no memory for logging data\n");
+               ret = -ENOMEM;
+               goto err_alloc_debug;
+       }
+
+#ifdef CONFIG_EXYNOS_ITMON
+       dev->itmon_nb.notifier_call = mfc_itmon_notifier;
+       itmon_notifier_chain_register(&dev->itmon_nb);
+#endif
+
+       s5p_mfc_init_debugfs(dev);
+
+       pr_debug("%s--\n", __func__);
+       return 0;
+
+/* Deinit MFC if probe had failed */
+err_alloc_debug:
+       iovmm_deactivate(&pdev->dev);
+err_iovmm_active:
+       destroy_workqueue(dev->butler_wq);
+err_butler_wq:
+       destroy_workqueue(dev->watchdog_wq);
+err_wq_watchdog:
+       video_unregister_device(dev->vfd_enc_otf_drm);
+alloc_vdev_enc_otf_drm:
+       video_unregister_device(dev->vfd_enc_otf);
+alloc_vdev_enc_otf:
+       video_unregister_device(dev->vfd_enc_drm);
+alloc_vdev_enc_drm:
+       video_unregister_device(dev->vfd_dec_drm);
+alloc_vdev_dec_drm:
+       video_unregister_device(dev->vfd_enc);
+alloc_vdev_enc:
+       video_unregister_device(dev->vfd_dec);
+alloc_vdev_dec:
+       v4l2_device_unregister(&dev->v4l2_dev);
+err_v4l2_dev:
+       mutex_destroy(&dev->mfc_mutex);
+       free_irq(dev->irq, dev);
+       if (dev->has_mmcache)
+               iounmap(dev->mmcache.base);
+       if (dev->has_hwfc)
+               iounmap(dev->hwfc_base);
+       if (dev->has_2sysmmu)
+               iounmap(dev->sysmmu1_base);
+       iounmap(dev->sysmmu0_base);
+       iounmap(dev->regs_base);
+       release_mem_region(dev->mfc_mem->start, resource_size(dev->mfc_mem));
+err_res_mem:
+       s5p_mfc_pm_final(dev);
+err_pm:
+       return ret;
+}
+
+/* Remove the driver */
+static int s5p_mfc_remove(struct platform_device *pdev)
+{
+       struct s5p_mfc_dev *dev = platform_get_drvdata(pdev);
+
+       dev_dbg(&pdev->dev, "%s++\n", __func__);
+       v4l2_info(&dev->v4l2_dev, "Removing %s\n", pdev->name);
+       del_timer_sync(&dev->watchdog_timer);
+       flush_workqueue(dev->watchdog_wq);
+       destroy_workqueue(dev->watchdog_wq);
+       flush_workqueue(dev->butler_wq);
+       destroy_workqueue(dev->butler_wq);
+       video_unregister_device(dev->vfd_enc);
+       video_unregister_device(dev->vfd_dec);
+       video_unregister_device(dev->vfd_enc_otf);
+       video_unregister_device(dev->vfd_enc_otf_drm);
+       v4l2_device_unregister(&dev->v4l2_dev);
+#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
+       remove_proc_entry(MFC_PROC_FW_STATUS, mfc_proc_entry);
+       remove_proc_entry(MFC_PROC_DRM_INSTANCE_NUMBER, mfc_proc_entry);
+       remove_proc_entry(MFC_PROC_INSTANCE_NUMBER, mfc_proc_entry);
+       remove_proc_entry(MFC_PROC_ROOT, NULL);
+#endif
+       s5p_mfc_destroy_listable_wq_dev(dev);
+       iovmm_deactivate(&pdev->dev);
+       mfc_debug(2, "Will now deinit HW\n");
+       s5p_mfc_deinit_hw(dev);
+       free_irq(dev->irq, dev);
+       if (dev->has_mmcache)
+               iounmap(dev->mmcache.base);
+       if (dev->has_hwfc)
+               iounmap(dev->hwfc_base);
+       if (dev->has_2sysmmu)
+               iounmap(dev->sysmmu1_base);
+       iounmap(dev->sysmmu0_base);
+       iounmap(dev->regs_base);
+       release_mem_region(dev->mfc_mem->start, resource_size(dev->mfc_mem));
+       s5p_mfc_pm_final(dev);
+       kfree(dev);
+       dev_dbg(&pdev->dev, "%s--\n", __func__);
+       return 0;
+}
+
+static void s5p_mfc_shutdown(struct platform_device *pdev)
+{
+       struct s5p_mfc_dev *dev = platform_get_drvdata(pdev);
+       int ret;
+
+       mfc_info_dev("MFC shutdown is called\n");
+       MFC_TRACE_DEV_HWLOCK("**shutdown \n");
+
+       if (!s5p_mfc_pm_get_pwr_ref_cnt(dev)) {
+               dev->shutdown = 1;
+               mfc_info_dev("MFC is not running\n");
+               return;
+       }
+
+       ret = s5p_mfc_get_hwlock_dev(dev);
+       if (ret < 0)
+               mfc_err_dev("Failed to get hwlock\n");
+
+       if (!dev->shutdown) {
+               s5p_mfc_risc_off(dev);
+               dev->shutdown = 1;
+               s5p_mfc_clear_all_bits(&dev->work_bits);
+               iovmm_deactivate(&pdev->dev);
+       }
+       s5p_mfc_release_hwlock_dev(dev);
+       mfc_info_dev("MFC shutdown completed\n");
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int s5p_mfc_suspend(struct device *dev)
+{
+       struct s5p_mfc_dev *m_dev = platform_get_drvdata(to_platform_device(dev));
+       int ret;
+
+       if (!m_dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return -EINVAL;
+       }
+
+       if (m_dev->num_inst == 0)
+               return 0;
+
+       ret = s5p_mfc_sleep(m_dev);
+
+       return ret;
+}
+
+static int s5p_mfc_resume(struct device *dev)
+{
+       struct s5p_mfc_dev *m_dev = platform_get_drvdata(to_platform_device(dev));
+       int ret;
+
+       if (!m_dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return -EINVAL;
+       }
+
+       if (m_dev->num_inst == 0)
+               return 0;
+
+       ret = s5p_mfc_wakeup(m_dev);
+
+       return ret;
+}
+#endif
+
+#ifdef CONFIG_PM
+static int s5p_mfc_runtime_suspend(struct device *dev)
+{
+       mfc_debug(3, "mfc runtime suspend\n");
+
+       return 0;
+}
+
+static int s5p_mfc_runtime_idle(struct device *dev)
+{
+       return 0;
+}
+
+static int s5p_mfc_runtime_resume(struct device *dev)
+{
+       mfc_debug(3, "mfc runtime resume\n");
+
+       return 0;
+}
+#endif
+
+/* Power management */
+static const struct dev_pm_ops s5p_mfc_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(s5p_mfc_suspend, s5p_mfc_resume)
+       SET_RUNTIME_PM_OPS(
+                       s5p_mfc_runtime_suspend,
+                       s5p_mfc_runtime_resume,
+                       s5p_mfc_runtime_idle
+       )
+};
+
+struct s5p_mfc_ctx_buf_size mfc_ctx_buf_size = {
+       .dev_ctx        = PAGE_ALIGN(0x7800),   /*  30KB */
+       .h264_dec_ctx   = PAGE_ALIGN(0x200000), /* 1.6MB */
+       .other_dec_ctx  = PAGE_ALIGN(0x7800),   /*  30KB */
+       .h264_enc_ctx   = PAGE_ALIGN(0x19000),  /* 100KB */
+       .hevc_enc_ctx   = PAGE_ALIGN(0xA000),   /*  40KB */
+       .other_enc_ctx  = PAGE_ALIGN(0x6400),   /*  25KB */
+       .shared_buf     = PAGE_ALIGN(0x2000),   /*   8KB */
+       .dbg_info_buf   = PAGE_ALIGN(0x1000),   /* 4KB for DEBUG INFO */
+};
+
+struct s5p_mfc_buf_size mfc_buf_size = {
+       .firmware_code  = PAGE_ALIGN(0x100000), /* 1MB */
+       .cpb_buf        = PAGE_ALIGN(0x300000), /* 3MB */
+       .ctx_buf        = &mfc_ctx_buf_size,
+};
+
+static struct s5p_mfc_variant mfc_drvdata = {
+       .buf_size = &mfc_buf_size,
+       .num_entities = 2,
+};
+
+static const struct of_device_id exynos_mfc_match[] = {
+       {
+               .compatible = "samsung,exynos-mfc",
+               .data = &mfc_drvdata,
+       },
+       {},
+};
+MODULE_DEVICE_TABLE(of, exynos_mfc_match);
+
+static void *mfc_get_drv_data(struct platform_device *pdev)
+{
+       struct s5p_mfc_variant *driver_data = NULL;
+
+       if (pdev->dev.of_node) {
+               const struct of_device_id *match;
+               match = of_match_node(of_match_ptr(exynos_mfc_match),
+                               pdev->dev.of_node);
+               if (match)
+                       driver_data = (struct s5p_mfc_variant *)match->data;
+       } else {
+               driver_data = (struct s5p_mfc_variant *)
+                       platform_get_device_id(pdev)->driver_data;
+       }
+       return driver_data;
+}
+
+static struct platform_driver s5p_mfc_driver = {
+       .probe          = s5p_mfc_probe,
+       .remove         = s5p_mfc_remove,
+       .shutdown       = s5p_mfc_shutdown,
+       .driver = {
+               .name   = S5P_MFC_NAME,
+               .owner  = THIS_MODULE,
+               .pm     = &s5p_mfc_pm_ops,
+               .of_match_table = exynos_mfc_match,
+               .suppress_bind_attrs = true,
+       },
+};
+
+module_platform_driver(s5p_mfc_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Kamil Debski <k.debski@samsung.com>");
diff --git a/drivers/media/platform/exynos/mfc/mfc_buf.c b/drivers/media/platform/exynos/mfc/mfc_buf.c
new file mode 100644 (file)
index 0000000..d93489f
--- /dev/null
@@ -0,0 +1,711 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_buf.c
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/smc.h>
+#include <linux/firmware.h>
+#include <trace/events/mfc.h>
+
+#include "mfc_buf.h"
+
+#include "mfc_mem.h"
+
+static int mfc_alloc_common_context(struct s5p_mfc_dev *dev,
+                                       enum mfc_buf_usage_type buf_type)
+{
+       struct s5p_mfc_special_buf *ctx_buf;
+       int firmware_size;
+       unsigned long fw_daddr;
+
+       mfc_debug_enter();
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return -EINVAL;
+       }
+
+       ctx_buf = &dev->common_ctx_buf;
+       fw_daddr = dev->fw_buf.daddr;
+
+#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
+       if (buf_type == MFCBUF_DRM) {
+               ctx_buf = &dev->drm_common_ctx_buf;
+               fw_daddr = dev->drm_fw_buf.daddr;
+       }
+#endif
+
+       firmware_size = dev->variant->buf_size->firmware_code;
+
+       ctx_buf->dma_buf = NULL;
+       ctx_buf->vaddr = NULL;
+       ctx_buf->daddr = fw_daddr + firmware_size;
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+/* Wrapper : allocate context buffers for SYS_INIT */
+int s5p_mfc_alloc_common_context(struct s5p_mfc_dev *dev)
+{
+       int ret = 0;
+
+       ret = mfc_alloc_common_context(dev, MFCBUF_NORMAL);
+       if (ret)
+               return ret;
+#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
+       if (dev->fw.drm_status) {
+               ret = mfc_alloc_common_context(dev, MFCBUF_DRM);
+               if (ret)
+                       return ret;
+       }
+#endif
+
+       return ret;
+}
+
+/* Release context buffers for SYS_INIT */
+static void mfc_release_common_context(struct s5p_mfc_dev *dev,
+                                       enum mfc_buf_usage_type buf_type)
+{
+       struct s5p_mfc_special_buf *ctx_buf;
+
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return;
+       }
+
+       ctx_buf = &dev->common_ctx_buf;
+#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
+       if (buf_type == MFCBUF_DRM)
+               ctx_buf = &dev->drm_common_ctx_buf;
+#endif
+
+       ctx_buf->dma_buf = NULL;
+       ctx_buf->vaddr = NULL;
+       ctx_buf->daddr = 0;
+}
+
+/* Release context buffers for SYS_INIT */
+void s5p_mfc_release_common_context(struct s5p_mfc_dev *dev)
+{
+       mfc_release_common_context(dev, MFCBUF_NORMAL);
+
+#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
+       mfc_release_common_context(dev, MFCBUF_DRM);
+#endif
+}
+
+/* Allocate memory for instance data buffer */
+int s5p_mfc_alloc_instance_context(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev;
+       struct s5p_mfc_ctx_buf_size *buf_size;
+
+       mfc_debug_enter();
+       if (!ctx) {
+               mfc_err_dev("no mfc context to run\n");
+               return -EINVAL;
+       }
+       dev = ctx->dev;
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return -EINVAL;
+       }
+       buf_size = dev->variant->buf_size->ctx_buf;
+
+       switch (ctx->codec_mode) {
+       case S5P_FIMV_CODEC_H264_DEC:
+       case S5P_FIMV_CODEC_H264_MVC_DEC:
+       case S5P_FIMV_CODEC_HEVC_DEC:
+       case S5P_FIMV_CODEC_BPG_DEC:
+               ctx->instance_ctx_buf.size = buf_size->h264_dec_ctx;
+               break;
+       case S5P_FIMV_CODEC_MPEG4_DEC:
+       case S5P_FIMV_CODEC_H263_DEC:
+       case S5P_FIMV_CODEC_VC1_RCV_DEC:
+       case S5P_FIMV_CODEC_VC1_DEC:
+       case S5P_FIMV_CODEC_MPEG2_DEC:
+       case S5P_FIMV_CODEC_VP8_DEC:
+       case S5P_FIMV_CODEC_VP9_DEC:
+       case S5P_FIMV_CODEC_FIMV1_DEC:
+       case S5P_FIMV_CODEC_FIMV2_DEC:
+       case S5P_FIMV_CODEC_FIMV3_DEC:
+       case S5P_FIMV_CODEC_FIMV4_DEC:
+               ctx->instance_ctx_buf.size = buf_size->other_dec_ctx;
+               break;
+       case S5P_FIMV_CODEC_H264_ENC:
+               ctx->instance_ctx_buf.size = buf_size->h264_enc_ctx;
+               break;
+       case S5P_FIMV_CODEC_HEVC_ENC:
+       case S5P_FIMV_CODEC_BPG_ENC:
+               ctx->instance_ctx_buf.size = buf_size->hevc_enc_ctx;
+               break;
+       case S5P_FIMV_CODEC_MPEG4_ENC:
+       case S5P_FIMV_CODEC_H263_ENC:
+       case S5P_FIMV_CODEC_VP8_ENC:
+       case S5P_FIMV_CODEC_VP9_ENC:
+               ctx->instance_ctx_buf.size = buf_size->other_enc_ctx;
+               break;
+       default:
+               ctx->instance_ctx_buf.size = 0;
+               mfc_err_ctx("Codec type(%d) should be checked!\n", ctx->codec_mode);
+               return -ENOMEM;
+       }
+
+       if (ctx->is_drm)
+               ctx->instance_ctx_buf.buftype = MFCBUF_DRM;
+       else
+               ctx->instance_ctx_buf.buftype = MFCBUF_NORMAL;
+
+       if (s5p_mfc_mem_ion_alloc(dev, &ctx->instance_ctx_buf)) {
+               mfc_err_ctx("Allocating context buffer failed\n");
+               return -ENOMEM;
+       }
+
+       mfc_debug(2, "[MEMINFO] Instance buf ctx[%d] size: %ld, daddr: 0x%08llx\n",
+                       ctx->num, ctx->instance_ctx_buf.size, ctx->instance_ctx_buf.daddr);
+
+       return 0;
+}
+
+/* Release instance buffer */
+void s5p_mfc_release_instance_context(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev;
+
+       mfc_debug_enter();
+       if (!ctx) {
+               mfc_err_dev("no mfc context to run\n");
+               return;
+       }
+
+       dev = ctx->dev;
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return;
+       }
+
+       s5p_mfc_mem_ion_free(dev, &ctx->instance_ctx_buf);
+       mfc_debug(2, "[MEMINFO] Release the instance buffer ctx[%d]\n", ctx->num);
+
+       mfc_debug_leave();
+}
+
+static void mfc_calc_dec_codec_buffer_size(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dec *dec;
+       int i;
+
+       dec = ctx->dec_priv;
+
+       /* Codecs have different memory requirements */
+       switch (ctx->codec_mode) {
+       case S5P_FIMV_CODEC_H264_DEC:
+       case S5P_FIMV_CODEC_H264_MVC_DEC:
+               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
+               ctx->codec_buf.size =
+                       ctx->scratch_buf_size +
+                       (dec->mv_count * ctx->mv_size);
+               break;
+       case S5P_FIMV_CODEC_MPEG4_DEC:
+       case S5P_FIMV_CODEC_FIMV1_DEC:
+       case S5P_FIMV_CODEC_FIMV2_DEC:
+       case S5P_FIMV_CODEC_FIMV3_DEC:
+       case S5P_FIMV_CODEC_FIMV4_DEC:
+               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
+               if (dec->loop_filter_mpeg4) {
+                       ctx->loopfilter_luma_size = ALIGN(ctx->raw_buf.plane_size[0], 256);
+                       ctx->loopfilter_chroma_size = ALIGN(ctx->raw_buf.plane_size[1] +
+                                                       ctx->raw_buf.plane_size[2], 256);
+                       ctx->codec_buf.size = ctx->scratch_buf_size +
+                               (NUM_MPEG4_LF_BUF * (ctx->loopfilter_luma_size +
+                                                    ctx->loopfilter_chroma_size));
+               } else {
+                       ctx->codec_buf.size = ctx->scratch_buf_size;
+               }
+               break;
+       case S5P_FIMV_CODEC_VC1_RCV_DEC:
+       case S5P_FIMV_CODEC_VC1_DEC:
+               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
+               ctx->codec_buf.size = ctx->scratch_buf_size;
+               break;
+       case S5P_FIMV_CODEC_MPEG2_DEC:
+               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
+               ctx->codec_buf.size = ctx->scratch_buf_size;
+               break;
+       case S5P_FIMV_CODEC_H263_DEC:
+               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
+               ctx->codec_buf.size = ctx->scratch_buf_size;
+               break;
+       case S5P_FIMV_CODEC_VP8_DEC:
+               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
+               ctx->codec_buf.size = ctx->scratch_buf_size;
+               break;
+       case S5P_FIMV_CODEC_VP9_DEC:
+               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
+               ctx->codec_buf.size =
+                       ctx->scratch_buf_size +
+                       DEC_STATIC_BUFFER_SIZE;
+               break;
+       case S5P_FIMV_CODEC_HEVC_DEC:
+       case S5P_FIMV_CODEC_BPG_DEC:
+               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
+               ctx->codec_buf.size =
+                       ctx->scratch_buf_size +
+                       (dec->mv_count * ctx->mv_size);
+               break;
+       default:
+               ctx->codec_buf.size = 0;
+               mfc_err_ctx("invalid codec type: %d\n", ctx->codec_mode);
+               break;
+       }
+
+       mfc_debug(2, "[MEMINFO] scratch: %zu, MV: %zu x count %d\n",
+                       ctx->scratch_buf_size, ctx->mv_size, dec->mv_count);
+       if (dec->loop_filter_mpeg4)
+               mfc_debug(2, "[MEMINFO] (loopfilter luma: %zu, chroma: %zu) x count %d\n",
+                               ctx->loopfilter_luma_size, ctx->loopfilter_chroma_size,
+                               NUM_MPEG4_LF_BUF);
+}
+
+static void mfc_calc_enc_codec_buffer_size(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_enc *enc;
+       unsigned int mb_width, mb_height;
+       unsigned int lcu_width = 0, lcu_height = 0;
+
+       enc = ctx->enc_priv;
+       enc->tmv_buffer_size = 0;
+
+       mb_width = WIDTH_MB(ctx->crop_width);
+       mb_height = HEIGHT_MB(ctx->crop_height);
+
+       lcu_width = ENC_LCU_WIDTH(ctx->crop_width);
+       lcu_height = ENC_LCU_HEIGHT(ctx->crop_height);
+
+       /* default recon buffer size, it can be changed in case of 422, 10bit */
+       enc->luma_dpb_size =
+               ALIGN(ENC_LUMA_DPB_SIZE(ctx->crop_width, ctx->crop_height), 64);
+       enc->chroma_dpb_size =
+               ALIGN(ENC_CHROMA_DPB_SIZE(ctx->crop_width, ctx->crop_height), 64);
+
+       /* Codecs have different memory requirements */
+       switch (ctx->codec_mode) {
+       case S5P_FIMV_CODEC_H264_ENC:
+               enc->me_buffer_size =
+                       ALIGN(ENC_V100_H264_ME_SIZE(mb_width, mb_height), 256);
+
+               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
+               ctx->codec_buf.size =
+                       ctx->scratch_buf_size + enc->tmv_buffer_size +
+                       (ctx->dpb_count * (enc->luma_dpb_size +
+                       enc->chroma_dpb_size + enc->me_buffer_size));
+               break;
+       case S5P_FIMV_CODEC_MPEG4_ENC:
+       case S5P_FIMV_CODEC_H263_ENC:
+               enc->me_buffer_size =
+                       ALIGN(ENC_V100_MPEG4_ME_SIZE(mb_width, mb_height), 256);
+
+               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
+               ctx->codec_buf.size =
+                       ctx->scratch_buf_size + enc->tmv_buffer_size +
+                       (ctx->dpb_count * (enc->luma_dpb_size +
+                       enc->chroma_dpb_size + enc->me_buffer_size));
+               break;
+       case S5P_FIMV_CODEC_VP8_ENC:
+               enc->me_buffer_size =
+                       ALIGN(ENC_V100_VP8_ME_SIZE(mb_width, mb_height), 256);
+
+               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
+               ctx->codec_buf.size =
+                       ctx->scratch_buf_size + enc->tmv_buffer_size +
+                       (ctx->dpb_count * (enc->luma_dpb_size +
+                       enc->chroma_dpb_size + enc->me_buffer_size));
+               break;
+       case S5P_FIMV_CODEC_VP9_ENC:
+               if (ctx->is_10bit || ctx->is_422) {
+                       enc->luma_dpb_size =
+                               ALIGN(ENC_VP9_LUMA_DPB_10B_SIZE(ctx->crop_width, ctx->crop_height), 64);
+                       enc->chroma_dpb_size =
+                               ALIGN(ENC_VP9_CHROMA_DPB_10B_SIZE(ctx->crop_width, ctx->crop_height), 64);
+                       mfc_debug(2, "[10BIT] VP9 10bit or 422 recon luma size: %zu chroma size: %zu\n",
+                                       enc->luma_dpb_size, enc->chroma_dpb_size);
+               }
+               enc->me_buffer_size =
+                       ALIGN(ENC_V100_VP9_ME_SIZE(lcu_width, lcu_height), 256);
+
+               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
+               ctx->codec_buf.size =
+                       ctx->scratch_buf_size + enc->tmv_buffer_size +
+                       (ctx->dpb_count * (enc->luma_dpb_size +
+                                          enc->chroma_dpb_size + enc->me_buffer_size));
+               break;
+       case S5P_FIMV_CODEC_HEVC_ENC:
+       case S5P_FIMV_CODEC_BPG_ENC:
+               if (ctx->is_10bit || ctx->is_422) {
+                       enc->luma_dpb_size =
+                               ALIGN(ENC_HEVC_LUMA_DPB_10B_SIZE(ctx->crop_width, ctx->crop_height), 64);
+                       enc->chroma_dpb_size =
+                               ALIGN(ENC_HEVC_CHROMA_DPB_10B_SIZE(ctx->crop_width, ctx->crop_height), 64);
+                       mfc_debug(2, "[10BIT] HEVC 10bit or 422 recon luma size: %zu chroma size: %zu\n",
+                                       enc->luma_dpb_size, enc->chroma_dpb_size);
+               }
+               enc->me_buffer_size =
+                       ALIGN(ENC_V100_HEVC_ME_SIZE(lcu_width, lcu_height), 256);
+
+               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
+               ctx->codec_buf.size =
+                       ctx->scratch_buf_size + enc->tmv_buffer_size +
+                       (ctx->dpb_count * (enc->luma_dpb_size +
+                                          enc->chroma_dpb_size + enc->me_buffer_size));
+               break;
+       default:
+               ctx->codec_buf.size = 0;
+               mfc_err_ctx("invalid codec type: %d\n", ctx->codec_mode);
+               break;
+       }
+
+       mfc_debug(2, "[MEMINFO] scratch: %zu, TMV: %zu, (recon luma: %zu, chroma: %zu, me: %zu) x count %d\n",
+                       ctx->scratch_buf_size, enc->tmv_buffer_size,
+                       enc->luma_dpb_size, enc->chroma_dpb_size, enc->me_buffer_size,
+                       ctx->dpb_count);
+}
+
+/* Allocate codec buffers */
+int s5p_mfc_alloc_codec_buffers(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev;
+
+       mfc_debug_enter();
+       if (!ctx) {
+               mfc_err_dev("no mfc context to run\n");
+               return -EINVAL;
+       }
+       dev = ctx->dev;
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return -EINVAL;
+       }
+
+       if (ctx->type == MFCINST_DECODER) {
+               mfc_calc_dec_codec_buffer_size(ctx);
+       } else if (ctx->type == MFCINST_ENCODER) {
+               mfc_calc_enc_codec_buffer_size(ctx);
+       } else {
+               mfc_err_ctx("invalid type: %d\n", ctx->type);
+               return -EINVAL;
+       }
+
+       if (ctx->is_drm)
+               ctx->codec_buf.buftype = MFCBUF_DRM;
+       else
+               ctx->codec_buf.buftype = MFCBUF_NORMAL;
+
+       if (ctx->codec_buf.size > 0) {
+               if (s5p_mfc_mem_ion_alloc(dev, &ctx->codec_buf)) {
+                       mfc_err_ctx("Allocating codec buffer failed\n");
+                       return -ENOMEM;
+               }
+               ctx->codec_buffer_allocated = 1;
+       } else if (ctx->codec_mode == S5P_FIMV_CODEC_MPEG2_DEC) {
+               ctx->codec_buffer_allocated = 1;
+       }
+
+       mfc_debug(2, "[MEMINFO] Codec buf ctx[%d] size: %ld, addr: 0x%08llx\n",
+                       ctx->num, ctx->codec_buf.size, ctx->codec_buf.daddr);
+
+       return 0;
+}
+
+/* Release buffers allocated for codec */
+void s5p_mfc_release_codec_buffers(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev;
+
+       if (!ctx) {
+               mfc_err_dev("no mfc context to run\n");
+               return;
+       }
+
+       dev = ctx->dev;
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return;
+       }
+
+       s5p_mfc_mem_ion_free(dev, &ctx->codec_buf);
+       ctx->codec_buffer_allocated = 0;
+       mfc_debug(2, "[MEMINFO] Release the codec buffer ctx[%d]\n", ctx->num);
+}
+
+/* Allocation buffer of debug infor memory for FW debugging */
+int s5p_mfc_alloc_dbg_info_buffer(struct s5p_mfc_dev *dev)
+{
+       struct s5p_mfc_ctx_buf_size *buf_size = dev->variant->buf_size->ctx_buf;
+
+       mfc_debug(2, "Allocate a debug-info buffer\n");
+
+       dev->dbg_info_buf.buftype = MFCBUF_NORMAL;
+       dev->dbg_info_buf.size = buf_size->dbg_info_buf;
+       if (s5p_mfc_mem_ion_alloc(dev, &dev->dbg_info_buf)) {
+               mfc_err_dev("Allocating debug info buffer failed\n");
+               return -ENOMEM;
+       }
+       mfc_debug(2, "[MEMINFO] debug info buf size: %ld, daddr: 0x%08llx, vaddr: 0x%p\n",
+                       dev->dbg_info_buf.size, dev->dbg_info_buf.daddr, dev->dbg_info_buf.vaddr);
+
+       return 0;
+}
+
+/* Release buffer of debug infor memory for FW debugging */
+int s5p_mfc_release_dbg_info_buffer(struct s5p_mfc_dev *dev)
+{
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return -EINVAL;
+       }
+
+       if (!dev->dbg_info_buf.dma_buf) {
+               mfc_debug(2, "debug info buffer is already freed\n");
+               return 0;
+       }
+
+       s5p_mfc_mem_ion_free(dev, &dev->dbg_info_buf);
+       mfc_debug(2, "[MEMINFO] Release the debug info buffer\n");
+
+       return 0;
+}
+
+/* Allocation buffer of ROI macroblock information */
+static int mfc_alloc_enc_roi_buffer(struct s5p_mfc_ctx *ctx, struct s5p_mfc_special_buf *roi_buf)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_ctx_buf_size *buf_size = dev->variant->buf_size->ctx_buf;
+
+       roi_buf->buftype = MFCBUF_NORMAL;
+       roi_buf->size = buf_size->shared_buf;
+       if (s5p_mfc_mem_ion_alloc(dev, roi_buf)) {
+               mfc_err_ctx("[ROI] Allocating ROI buffer failed\n");
+               return -ENOMEM;
+       }
+       mfc_debug(2, "[MEMINFO][ROI] roi buf ctx[%d] size: %ld, daddr: 0x%08llx, vaddr: 0x%p\n",
+                       ctx->num, roi_buf->size, roi_buf->daddr, roi_buf->vaddr);
+
+       memset(roi_buf->vaddr, 0, buf_size->shared_buf);
+
+       return 0;
+}
+
+/* Wrapper : allocation ROI buffers */
+int s5p_mfc_alloc_enc_roi_buffer(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_enc *enc = ctx->enc_priv;
+       int i;
+
+       for (i = 0; i < MFC_MAX_EXTRA_BUF; i++) {
+               if (mfc_alloc_enc_roi_buffer(ctx, &enc->roi_buf[i]) < 0) {
+                       mfc_err_dev("[ROI] Allocating remapping buffer[%d] failed\n", i);
+                       return -ENOMEM;
+               }
+       }
+
+       return 0;
+}
+
+/* Release buffer of ROI macroblock information */
+void s5p_mfc_release_enc_roi_buffer(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_enc *enc = ctx->enc_priv;
+       int i;
+
+       for (i = 0; i < MFC_MAX_EXTRA_BUF; i++)
+               if (enc->roi_buf[i].dma_buf)
+                       s5p_mfc_mem_ion_free(ctx->dev, &enc->roi_buf[i]);
+
+       mfc_debug(2, "[MEMINFO][ROI] Release the ROI buffer\n");
+}
+
+int s5p_mfc_otf_alloc_stream_buf(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct _otf_handle *handle = ctx->otf_handle;
+       struct _otf_debug *debug = &handle->otf_debug;
+       struct s5p_mfc_special_buf *buf;
+       struct s5p_mfc_raw_info *raw = &ctx->raw_buf;
+       int i;
+
+       mfc_debug_enter();
+
+       for (i = 0; i < OTF_MAX_BUF; i++) {
+               buf = &debug->stream_buf[i];
+               buf->buftype = MFCBUF_NORMAL;
+               buf->size = raw->total_plane_size;
+               if (s5p_mfc_mem_ion_alloc(dev, buf)) {
+                       mfc_err_ctx("[OTF] Allocating stream buffer failed\n");
+                       return -EINVAL;
+               }
+               mfc_debug(2, "[OTF][MEMINFO] OTF stream buf[%d] size: %ld, daddr: 0x%08llx, vaddr: 0x%p\n",
+                               i, buf->size, buf->daddr, buf->vaddr);
+               memset(buf->vaddr, 0, raw->total_plane_size);
+       }
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+void s5p_mfc_otf_release_stream_buf(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct _otf_handle *handle = ctx->otf_handle;
+       struct _otf_debug *debug = &handle->otf_debug;
+       struct s5p_mfc_special_buf *buf;
+       int i;
+
+       mfc_debug_enter();
+
+       for (i = 0; i < OTF_MAX_BUF; i++) {
+               buf = &debug->stream_buf[i];
+               if (buf->dma_buf)
+                       s5p_mfc_mem_ion_free(dev, buf);
+       }
+
+       mfc_debug(2, "[OTF][MEMINFO] Release the OTF stream buffer\n");
+       mfc_debug_leave();
+}
+
+/* Allocate firmware */
+int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev)
+{
+       size_t firmware_size;
+       struct s5p_mfc_ctx_buf_size *buf_size;
+
+       mfc_debug_enter();
+
+       if (!dev) {
+               mfc_err_dev("[F/W] no mfc device to run\n");
+               return -EINVAL;
+       }
+
+       buf_size = dev->variant->buf_size->ctx_buf;
+       firmware_size = dev->variant->buf_size->firmware_code;
+       dev->fw.size = firmware_size + buf_size->dev_ctx;
+
+       if (dev->fw_buf.dma_buf)
+               return 0;
+
+       mfc_debug(4, "[F/W] Allocating memory for firmware\n");
+       trace_mfc_loadfw_start(dev->fw.size, firmware_size);
+
+       dev->fw_buf.buftype = MFCBUF_NORMAL;
+       dev->fw_buf.size = dev->fw.size;
+       if (s5p_mfc_mem_ion_alloc(dev, &dev->fw_buf)) {
+               mfc_err_dev("[F/W] Allocating normal firmware buffer failed\n");
+               return -ENOMEM;
+       }
+
+       mfc_debug(2, "[MEMINFO][F/W] FW normal: 0x%08llx (vaddr: 0x%p), size: %08zu\n",
+                       dev->fw_buf.daddr, dev->fw_buf.vaddr,
+                       dev->fw_buf.size);
+
+#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
+       dev->drm_fw_buf.buftype = MFCBUF_DRM_FW;
+       dev->drm_fw_buf.size = dev->fw.size;
+       if (s5p_mfc_mem_ion_alloc(dev, &dev->drm_fw_buf)) {
+               mfc_err_dev("[F/W] Allocating DRM firmware buffer failed\n");
+               return -ENOMEM;
+       }
+
+       mfc_debug(2, "[MEMINFO][F/W] FW DRM: 0x%08llx (vaddr: 0x%p), size: %08zu\n",
+                       dev->drm_fw_buf.daddr, dev->drm_fw_buf.vaddr,
+                       dev->drm_fw_buf.size);
+#endif
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+/* Load firmware to MFC */
+int s5p_mfc_load_firmware(struct s5p_mfc_dev *dev)
+{
+       struct firmware *fw_blob;
+       size_t firmware_size;
+       int err;
+
+       if (!dev) {
+               mfc_err_dev("[F/W] no mfc device to run\n");
+               return -EINVAL;
+       }
+
+       firmware_size = dev->variant->buf_size->firmware_code;
+
+       /* Firmare has to be present as a separate file or compiled
+        * into kernel. */
+       mfc_debug_enter();
+       mfc_debug(4, "[F/W] Requesting F/W\n");
+       err = request_firmware((const struct firmware **)&fw_blob,
+                                       MFC_FW_NAME, dev->v4l2_dev.dev);
+
+       if (err != 0) {
+               mfc_err_dev("[F/W] Couldn't find the F/W invalid path\n");
+               return -EINVAL;
+       }
+
+       mfc_debug(2, "[MEMINFO][F/W] loaded F/W Size: %zu\n", fw_blob->size);
+
+       if (fw_blob->size > firmware_size) {
+               mfc_err_dev("[MEMINFO][F/W] MFC firmware(%zu) is too big to be loaded in memory(%zu)\n",
+                               fw_blob->size, firmware_size);
+               release_firmware(fw_blob);
+               return -ENOMEM;
+       }
+
+       if (dev->fw_buf.dma_buf == NULL || dev->fw_buf.daddr == 0) {
+               mfc_err_dev("[F/W] MFC firmware is not allocated or was not mapped correctly\n");
+               release_firmware(fw_blob);
+               return -EINVAL;
+       }
+
+       memcpy(dev->fw_buf.vaddr, fw_blob->data, fw_blob->size);
+       if (dev->drm_fw_buf.vaddr) {
+               memcpy(dev->drm_fw_buf.vaddr, fw_blob->data, fw_blob->size);
+               mfc_debug(4, "[F/W] copy firmware to secure region\n");
+       }
+       release_firmware(fw_blob);
+       trace_mfc_loadfw_end(dev->fw.size, firmware_size);
+       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 */
+       if (!dev) {
+               mfc_err_dev("[F/W] no mfc device to run\n");
+               return -EINVAL;
+       }
+
+       if (!dev->fw_buf.dma_buf) {
+               mfc_err_dev("[F/W] firmware memory is already freed\n");
+               return -EINVAL;
+       }
+
+#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
+       s5p_mfc_mem_ion_free(dev, &dev->drm_fw_buf);
+#endif
+
+       s5p_mfc_mem_ion_free(dev, &dev->fw_buf);
+
+       return 0;
+}
diff --git a/drivers/media/platform/exynos/mfc/mfc_buf.h b/drivers/media/platform/exynos/mfc/mfc_buf.h
new file mode 100644 (file)
index 0000000..ef58923
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_buf.h
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __MFC_BUF_H
+#define __MFC_BUF_H __FILE__
+
+#include "mfc_common.h"
+
+/* Memory allocation */
+int s5p_mfc_alloc_common_context(struct s5p_mfc_dev *dev);
+void s5p_mfc_release_common_context(struct s5p_mfc_dev *dev);
+
+int s5p_mfc_alloc_instance_context(struct s5p_mfc_ctx *ctx);
+void s5p_mfc_release_instance_context(struct s5p_mfc_ctx *ctx);
+
+int s5p_mfc_alloc_codec_buffers(struct s5p_mfc_ctx *ctx);
+void s5p_mfc_release_codec_buffers(struct s5p_mfc_ctx *ctx);
+
+int s5p_mfc_alloc_enc_roi_buffer(struct s5p_mfc_ctx *ctx);
+void s5p_mfc_release_enc_roi_buffer(struct s5p_mfc_ctx *ctx);
+
+int s5p_mfc_otf_alloc_stream_buf(struct s5p_mfc_ctx *ctx);
+void s5p_mfc_otf_release_stream_buf(struct s5p_mfc_ctx *ctx);
+
+int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev);
+int s5p_mfc_load_firmware(struct s5p_mfc_dev *dev);
+int s5p_mfc_release_firmware(struct s5p_mfc_dev *dev);
+
+int s5p_mfc_alloc_dbg_info_buffer(struct s5p_mfc_dev *dev);
+int s5p_mfc_release_dbg_info_buffer(struct s5p_mfc_dev *dev);
+
+#endif /* __MFC_BUF_H */
diff --git a/drivers/media/platform/exynos/mfc/mfc_cal.c b/drivers/media/platform/exynos/mfc/mfc_cal.c
new file mode 100644 (file)
index 0000000..78a2af0
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_cal.c
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <trace/events/mfc.h>
+
+#include "mfc_cal.h"
+#include "mfc_pm.h"
+
+/* Reset the device */
+int s5p_mfc_reset_mfc(struct s5p_mfc_dev *dev)
+{
+       int i;
+
+       mfc_debug_enter();
+
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return -EINVAL;
+       }
+
+       /* Zero Initialization of MFC registers */
+       MFC_WRITEL(0, S5P_FIMV_RISC2HOST_CMD);
+       MFC_WRITEL(0, S5P_FIMV_HOST2RISC_CMD);
+       MFC_WRITEL(0, S5P_FIMV_FW_VERSION);
+
+       for (i = 0; i < S5P_FIMV_REG_CLEAR_COUNT; i++)
+               MFC_WRITEL(0, S5P_FIMV_REG_CLEAR_BEGIN + (i*4));
+
+       MFC_WRITEL(0x1FFF, S5P_FIMV_MFC_RESET);
+       MFC_WRITEL(0, S5P_FIMV_MFC_RESET);
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+void s5p_mfc_set_risc_base_addr(struct s5p_mfc_dev *dev,
+                                       enum mfc_buf_usage_type buf_type)
+{
+       struct s5p_mfc_special_buf *fw_buf;
+
+       fw_buf = &dev->fw_buf;
+
+       if (buf_type == MFCBUF_DRM)
+               fw_buf = &dev->drm_fw_buf;
+
+       MFC_WRITEL(fw_buf->daddr, S5P_FIMV_RISC_BASE_ADDRESS);
+       mfc_debug(2, "[MEMINFO][F/W] %s Base Address : %#x\n",
+                       buf_type == MFCBUF_DRM ? "DRM" : "NORMAL", fw_buf->daddr);
+       MFC_TRACE_DEV("%s F/W Base Address : %#x\n",
+                       buf_type == MFCBUF_DRM ? "DRM" : "NORMAL", fw_buf->daddr);
+}
+
+void s5p_mfc_cmd_host2risc(struct s5p_mfc_dev *dev, int cmd)
+{
+       mfc_debug(1, "Issue the command: %d\n", cmd);
+       MFC_TRACE_DEV(">> CMD : %d, (dev:0x%lx, bits:%lx, owned:%d, wl:%d, trans:%d)\n",
+                       cmd, dev->hwlock.dev, dev->hwlock.bits, dev->hwlock.owned_by_irq,
+                       dev->hwlock.wl_count, dev->hwlock.transfer_owner);
+
+       trace_mfc_frame_start(dev->curr_ctx, cmd, 0, 0);
+       /* Reset RISC2HOST command except nal q stop command */
+       if (cmd != S5P_FIMV_H2R_CMD_STOP_QUEUE)
+               MFC_WRITEL(0x0, S5P_FIMV_RISC2HOST_CMD);
+
+       /* Start the timeout watchdog */
+       if ((cmd != S5P_FIMV_H2R_CMD_NAL_QUEUE) && (cmd != S5P_FIMV_H2R_CMD_STOP_QUEUE))
+               s5p_mfc_watchdog_start_tick(dev);
+
+       if (dbg_enable) {
+               /* For FW debugging */
+               s5p_mfc_dbg_set_addr(dev);
+               s5p_mfc_dbg_enable(dev);
+       }
+
+       /* Issue the command */
+       MFC_WRITEL(cmd, S5P_FIMV_HOST2RISC_CMD);
+       MFC_WRITEL(0x1, S5P_FIMV_HOST2RISC_INT);
+}
+
+/* Check whether HW interrupt has occurred or not */
+int s5p_mfc_check_risc2host(struct s5p_mfc_dev *dev)
+{
+       if (s5p_mfc_pm_get_pwr_ref_cnt(dev) && s5p_mfc_pm_get_clk_ref_cnt(dev)) {
+               if (MFC_READL(S5P_FIMV_RISC2HOST_INT))
+                       return MFC_READL(S5P_FIMV_RISC2HOST_CMD);
+               else
+                       return 0;
+       }
+
+       return 0;
+}
diff --git a/drivers/media/platform/exynos/mfc/mfc_cal.h b/drivers/media/platform/exynos/mfc/mfc_cal.h
new file mode 100644 (file)
index 0000000..7ea31cb
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_cal.h
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __MFC_CAL_H
+#define __MFC_CAL_H __FILE__
+
+#include "mfc_reg.h"
+
+#include "mfc_common.h"
+
+#include "mfc_utils.h"
+
+
+#define s5p_mfc_get_int_reason()       (MFC_READL(S5P_FIMV_RISC2HOST_CMD)              \
+                                               & S5P_FIMV_RISC2HOST_CMD_MASK)
+#define s5p_mfc_clear_int_sfr()                                \
+               do {                                                    \
+                       MFC_WRITEL(0, S5P_FIMV_RISC2HOST_CMD);  \
+                       MFC_WRITEL(0, S5P_FIMV_RISC2HOST_INT);  \
+               } while (0)
+
+static inline int s5p_mfc_stop_bus(struct s5p_mfc_dev *dev)
+{
+       unsigned int status;
+       unsigned long timeout;
+
+       /* Reset */
+       MFC_WRITEL(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_dev("Timeout while resetting MFC.\n");
+                       return -EIO;
+               }
+               status = MFC_READL(S5P_FIMV_MFC_BUS_RESET_CTRL);
+       } while ((status & 0x2) == 0);
+
+       return 0;
+}
+
+static inline void s5p_mfc_start_bus(struct s5p_mfc_dev *dev)
+{
+       int val;
+
+       val = MFC_READL(S5P_FIMV_MFC_BUS_RESET_CTRL);
+       val &= ~(0x1);
+       MFC_WRITEL(val, S5P_FIMV_MFC_BUS_RESET_CTRL);
+}
+
+static inline void s5p_mfc_risc_on(struct s5p_mfc_dev *dev)
+{
+       s5p_mfc_clean_dev_int_flags(dev);
+
+       MFC_WRITEL(0x1, S5P_FIMV_RISC_ON);
+       MFC_WRITEL(0x0, S5P_FIMV_MFC_OFF);
+       mfc_debug(1, "RISC_ON\n");
+       MFC_TRACE_DEV(">> RISC ON\n");
+}
+
+static inline void s5p_mfc_risc_off(struct s5p_mfc_dev *dev)
+{
+       unsigned int status;
+       unsigned long timeout;
+
+       timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
+       /* Check pending status */
+       do {
+               if (time_after(jiffies, timeout)) {
+                       mfc_err_dev("Timeout while pendng clear\n");
+                       mfc_err_dev("MFC access pending state: %#x\n", status);
+                       mfc_err_dev("MFC access pending R: %#x, W: %#x\n",
+                                       MFC_READL(S5P_FIMV_MFC_RPEND),
+                                       MFC_READL(S5P_FIMV_MFC_WPEND));
+                       break;
+               }
+               status = MFC_READL(S5P_FIMV_MFC_BUS_STATUS);
+       } while (status != 0);
+
+       MFC_WRITEL(0x0, S5P_FIMV_RISC_ON);
+}
+
+static inline void s5p_mfc_mfc_off(struct s5p_mfc_dev *dev)
+{
+       mfc_info_dev("MFC h/w state: %d\n",
+                       MFC_READL(S5P_FIMV_MFC_STATE) & 0x7);
+       MFC_WRITEL(0x1, S5P_FIMV_MFC_OFF);
+}
+
+static inline void s5p_mfc_enable_all_clocks(struct s5p_mfc_dev *dev)
+{
+       /* Enable all FW clock gating */
+       MFC_WRITEL(0xFFFFFFFF, S5P_FIMV_MFC_FW_CLOCK);
+}
+
+int s5p_mfc_reset_mfc(struct s5p_mfc_dev *dev);
+void s5p_mfc_set_risc_base_addr(struct s5p_mfc_dev *dev,
+                               enum mfc_buf_usage_type buf_type);
+void s5p_mfc_cmd_host2risc(struct s5p_mfc_dev *dev, int cmd);
+int s5p_mfc_check_risc2host(struct s5p_mfc_dev *dev);
+
+#endif /* __MFC_CAL_H */
diff --git a/drivers/media/platform/exynos/mfc/mfc_cmd.c b/drivers/media/platform/exynos/mfc/mfc_cmd.c
new file mode 100644 (file)
index 0000000..d0477cd
--- /dev/null
@@ -0,0 +1,292 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_cmd.c
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <trace/events/mfc.h>
+
+#include "mfc_cmd.h"
+
+#include "mfc_cal.h"
+#include "mfc_reg.h"
+#include "mfc_mmcache.h"
+
+#include "mfc_utils.h"
+#include "mfc_buf.h"
+
+int s5p_mfc_cmd_sys_init(struct s5p_mfc_dev *dev,
+                                       enum mfc_buf_usage_type buf_type)
+{
+       struct s5p_mfc_ctx_buf_size *buf_size;
+       struct s5p_mfc_special_buf *ctx_buf;
+
+       mfc_debug_enter();
+
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return -EINVAL;
+       }
+
+       s5p_mfc_clean_dev_int_flags(dev);
+
+       buf_size = dev->variant->buf_size->ctx_buf;
+       ctx_buf = &dev->common_ctx_buf;
+#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
+       if (buf_type == MFCBUF_DRM)
+               ctx_buf = &dev->drm_common_ctx_buf;
+#endif
+       MFC_WRITEL(ctx_buf->daddr, S5P_FIMV_CONTEXT_MEM_ADDR);
+       MFC_WRITEL(buf_size->dev_ctx, S5P_FIMV_CONTEXT_MEM_SIZE);
+
+       s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_SYS_INIT);
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+void s5p_mfc_cmd_sleep(struct s5p_mfc_dev *dev)
+{
+       mfc_debug_enter();
+
+       s5p_mfc_clean_dev_int_flags(dev);
+       s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_SLEEP);
+
+       mfc_debug_leave();
+}
+
+void s5p_mfc_cmd_wakeup(struct s5p_mfc_dev *dev)
+{
+       mfc_debug_enter();
+
+       s5p_mfc_clean_dev_int_flags(dev);
+       s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_WAKEUP);
+
+       mfc_debug_leave();
+}
+
+/* Open a new instance and get its number */
+int s5p_mfc_cmd_open_inst(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev;
+
+       mfc_debug_enter();
+
+       if (!ctx) {
+               mfc_err_dev("no mfc context to run\n");
+               return -EINVAL;
+       }
+       dev = ctx->dev;
+       mfc_debug(2, "Requested codec mode: %d\n", ctx->codec_mode);
+
+       MFC_WRITEL(ctx->codec_mode, S5P_FIMV_CODEC_TYPE);
+       MFC_WRITEL(ctx->instance_ctx_buf.daddr, S5P_FIMV_CONTEXT_MEM_ADDR);
+       MFC_WRITEL(ctx->instance_ctx_buf.size, S5P_FIMV_CONTEXT_MEM_SIZE);
+       if (ctx->type == MFCINST_DECODER)
+               MFC_WRITEL(ctx->dec_priv->crc_enable, S5P_FIMV_D_CRC_CTRL);
+
+       s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_OPEN_INSTANCE);
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+/* Close instance */
+int s5p_mfc_cmd_close_inst(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev;
+
+       mfc_debug_enter();
+
+       if (!ctx) {
+               mfc_err_dev("no mfc context to run\n");
+               return -EINVAL;
+       }
+       dev = ctx->dev;
+
+       MFC_WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID);
+
+       s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_CLOSE_INSTANCE);
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+int s5p_mfc_cmd_dpb_flush(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       if (ON_RES_CHANGE(ctx))
+               mfc_err_ctx("dpb flush on res change(state:%d)\n", ctx->state);
+
+       s5p_mfc_clean_ctx_int_flags(ctx);
+
+       MFC_WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID);
+       s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_DPB_FLUSH);
+
+       return 0;
+}
+
+int s5p_mfc_cmd_cache_flush(struct s5p_mfc_dev *dev)
+{
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return -EINVAL;
+       }
+
+       s5p_mfc_clean_dev_int_flags(dev);
+       s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_CACHE_FLUSH);
+
+       return 0;
+}
+
+int s5p_mfc_cmd_dec_init_buffers(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev;
+       struct s5p_mfc_dec *dec;
+       unsigned int reg = 0, pix_val;
+       int ret;
+
+       if (!ctx) {
+               mfc_err_dev("no mfc context to run\n");
+               return -EINVAL;
+       }
+       dec = ctx->dec_priv;
+       dev = ctx->dev;
+       if (!dev) {
+               mfc_err_ctx("no mfc device to run\n");
+               return -EINVAL;
+       }
+
+       switch (ctx->dst_fmt->fourcc) {
+       case V4L2_PIX_FMT_NV12M:
+       case V4L2_PIX_FMT_NV12N:
+       case V4L2_PIX_FMT_NV12MT_16X16:
+       case V4L2_PIX_FMT_NV16M:
+       case V4L2_PIX_FMT_NV12N_10B:
+       case V4L2_PIX_FMT_NV12M_S10B:
+       case V4L2_PIX_FMT_NV16M_S10B:
+       case V4L2_PIX_FMT_NV12M_P010:
+       case V4L2_PIX_FMT_NV16M_P210:
+               pix_val = 0;
+               break;
+       case V4L2_PIX_FMT_NV21M:
+       case V4L2_PIX_FMT_NV61M:
+       case V4L2_PIX_FMT_NV21M_S10B:
+       case V4L2_PIX_FMT_NV61M_S10B:
+       case V4L2_PIX_FMT_NV21M_P010:
+       case V4L2_PIX_FMT_NV61M_P210:
+               pix_val = 1;
+               break;
+       case V4L2_PIX_FMT_YVU420M:
+               pix_val = 2;
+               break;
+       case V4L2_PIX_FMT_YUV420M:
+       case V4L2_PIX_FMT_YUV420N:
+               pix_val = 3;
+               break;
+       default:
+               pix_val = 0;
+               break;
+       }
+       reg = MFC_READL(S5P_FIMV_PIXEL_FORMAT);
+       reg &= ~(0xF);
+       reg |= pix_val & 0xF;
+       MFC_WRITEL(reg, S5P_FIMV_PIXEL_FORMAT);
+       mfc_debug(2, "[FRAME] pixel format: %d, mem_type_10bit should be fixed on SEQ_START(reg: %#x)\n",
+                       pix_val, reg);
+
+       s5p_mfc_clean_ctx_int_flags(ctx);
+       ret = s5p_mfc_set_dec_codec_buffers(ctx);
+       if (ret) {
+               mfc_info_ctx("isn't enough codec buffer size, re-alloc!\n");
+
+               if (dev->has_mmcache && dev->mmcache.is_on_status)
+                       s5p_mfc_invalidate_mmcache(dev);
+
+               s5p_mfc_release_codec_buffers(ctx);
+               ret = s5p_mfc_alloc_codec_buffers(ctx);
+               if (ret) {
+                       mfc_err_ctx("Failed to allocate decoding buffers\n");
+                       return ret;
+               }
+               ret = s5p_mfc_set_dec_codec_buffers(ctx);
+               if (ret) {
+                       mfc_err_ctx("Failed to alloc frame mem\n");
+                       return ret;
+               }
+       }
+
+       MFC_WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID);
+
+       if (sfr_dump & MFC_DUMP_DEC_INIT_BUFS)
+               call_dop(dev, dump_regs, dev);
+
+       s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_INIT_BUFFERS);
+
+       return ret;
+}
+
+int s5p_mfc_cmd_enc_init_buffers(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev;
+       int ret;
+
+       dev = ctx->dev;
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return -EINVAL;
+       }
+
+       /*
+        * Header was generated now starting processing
+        * First set the reference frame buffers
+        */
+       if (!ctx->codec_buffer_allocated) {
+               mfc_info_ctx("there isn't codec buffer, re-alloc!\n");
+               ret = s5p_mfc_alloc_codec_buffers(ctx);
+               if (ret) {
+                       mfc_err_ctx("Failed to allocate encoding buffers\n");
+                       return ret;
+               }
+       }
+
+       s5p_mfc_clean_ctx_int_flags(ctx);
+       ret = s5p_mfc_set_enc_codec_buffers(ctx);
+       if (ret) {
+               mfc_info_ctx("isn't enough codec buffer size, re-alloc!\n");
+
+               if (dev->has_mmcache && dev->mmcache.is_on_status)
+                       s5p_mfc_invalidate_mmcache(dev);
+
+               s5p_mfc_release_codec_buffers(ctx);
+               ret = s5p_mfc_alloc_codec_buffers(ctx);
+               if (ret) {
+                       mfc_err_ctx("Failed to allocate encoding buffers\n");
+                       return ret;
+               }
+               ret = s5p_mfc_set_enc_codec_buffers(ctx);
+               if (ret) {
+                       mfc_err_ctx("Failed to set enc codec buffers\n");
+                       return ret;
+               }
+       }
+
+       MFC_WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID);
+
+       if (sfr_dump & MFC_DUMP_ENC_INIT_BUFS)
+               call_dop(dev, dump_regs, dev);
+
+       s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_INIT_BUFFERS);
+
+       return ret;
+}
diff --git a/drivers/media/platform/exynos/mfc/mfc_cmd.h b/drivers/media/platform/exynos/mfc/mfc_cmd.h
new file mode 100644 (file)
index 0000000..ebbd970
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_cmd.h
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __MFC_CMD_H
+#define __MFC_CMD_H __FILE__
+
+#include "mfc_common.h"
+
+int s5p_mfc_cmd_sys_init(struct s5p_mfc_dev *dev,
+                               enum mfc_buf_usage_type buf_type);
+void s5p_mfc_cmd_sleep(struct s5p_mfc_dev *dev);
+void s5p_mfc_cmd_wakeup(struct s5p_mfc_dev *dev);
+int s5p_mfc_cmd_open_inst(struct s5p_mfc_ctx *ctx);
+int s5p_mfc_cmd_close_inst(struct s5p_mfc_ctx *ctx);
+int s5p_mfc_cmd_dpb_flush(struct s5p_mfc_ctx *ctx);
+int s5p_mfc_cmd_cache_flush(struct s5p_mfc_dev *dev);
+int s5p_mfc_cmd_dec_init_buffers(struct s5p_mfc_ctx *ctx);
+int s5p_mfc_cmd_enc_init_buffers(struct s5p_mfc_ctx *ctx);
+
+#endif /* __MFC_CMD_H */
diff --git a/drivers/media/platform/exynos/mfc/mfc_common.h b/drivers/media/platform/exynos/mfc/mfc_common.h
new file mode 100644 (file)
index 0000000..37e99fe
--- /dev/null
@@ -0,0 +1,192 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_common.h
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __MFC_COMMON_H
+#define __MFC_COMMON_H __FILE__
+
+#include <linux/exynos_iovmm.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/sched/clock.h>
+#include <linux/ion_exynos.h>
+#include <linux/dma-buf-container.h>
+#include <media/videobuf2-dma-sg.h>
+#include <asm/cacheflush.h>
+
+#include "mfc_regs_v10.h"
+#include "mfc_macros.h"
+#include "mfc_debug.h"
+#include "exynos_mfc_media.h"
+#include "mfc_data_struct.h"
+
+#define MFC_DRIVER_INFO                180315
+
+#define MFC_MAX_REF_BUFS       2
+#define MFC_FRAME_PLANES       2
+#define MFC_INFO_INIT_FD       -1
+
+#define MFC_MAX_DRM_CTX                2
+
+/* Interrupt timeout */
+#define MFC_INT_TIMEOUT                4000
+/* Interrupt short timeout */
+#define MFC_INT_SHORT_TIMEOUT  800
+/* hwlock timeout */
+#define MFC_HWLOCK_TIMEOUT     5000
+/* Busy wait timeout */
+#define MFC_BW_TIMEOUT         500
+/* MMCache invalidation timeout */
+#define MMCACHE_INVAL_TIMEOUT  1000
+/* Interrupt timeout count*/
+#define MFC_INT_TIMEOUT_CNT    2
+
+/* This value guarantees 299.4msec ~ 2.25sec according to MFC clock (668MHz ~ 89MHz)
+ * releated with S5P_FIMV_DEC_TIMEOUT_VALUE */
+#define MFC_TIMEOUT_VALUE      200000000
+
+#define NUM_MPEG4_LF_BUF       2
+
+#define DEFAULT_TAG            (0xE05)
+
+#define MFC_NO_INSTANCE_SET    -1
+
+#define MFC_ENC_CAP_PLANE_COUNT        1
+#define MFC_ENC_OUT_PLANE_COUNT        2
+
+#define MFC_NAME_LEN           16
+#define MFC_FW_NAME            "mfc_fw.bin"
+
+#define STUFF_BYTE             4
+
+#define MFC_BASE_MASK          ((1 << 17) - 1)
+
+#define FLAG_LAST_FRAME                0x80000000
+#define FLAG_EMPTY_DATA                0x40000000
+#define FLAG_CSD               0x20000000
+
+/* MFC conceal color is black */
+#define MFC_CONCEAL_COLOR      0x8020000
+
+#define vb_to_mfc_buf(x)               \
+       container_of(x, struct s5p_mfc_buf, vb.vb2_buf)
+
+#define fh_to_mfc_ctx(x)               \
+       container_of(x, struct s5p_mfc_ctx, fh)
+
+#define call_bop(b, op, args...)       \
+       (b->op ? b->op(args) : 0)
+
+#define call_cop(c, op, args...)       \
+       (((c)->c_ops->op) ?             \
+               ((c)->c_ops->op(args)) : 0)
+
+#define call_dop(d, op, args...)       \
+       (((d)->dump_ops->op) ?          \
+               ((d)->dump_ops->op(args)) : 0)
+
+#define        MFC_CTRL_TYPE_GET       (MFC_CTRL_TYPE_GET_SRC | MFC_CTRL_TYPE_GET_DST)
+#define        MFC_CTRL_TYPE_SRC       (MFC_CTRL_TYPE_SET | MFC_CTRL_TYPE_GET_SRC)
+#define        MFC_CTRL_TYPE_DST       (MFC_CTRL_TYPE_GET_DST)
+
+#define MFC_FMT_STREAM         (1 << 0)
+#define MFC_FMT_FRAME          (1 << 1)
+#define MFC_FMT_10BIT          (1 << 2)
+#define MFC_FMT_422            (1 << 3)
+#define MFC_FMT_RGB            (1 << 4)
+
+/* node check */
+#define IS_DEC_NODE(n)         ((n == EXYNOS_VIDEONODE_MFC_DEC) ||     \
+                               (n == EXYNOS_VIDEONODE_MFC_DEC_DRM))
+#define IS_ENC_NODE(n)         ((n == EXYNOS_VIDEONODE_MFC_ENC) ||     \
+                               (n == EXYNOS_VIDEONODE_MFC_ENC_DRM) ||  \
+                               (n == EXYNOS_VIDEONODE_MFC_ENC_OTF) ||  \
+                               (n == EXYNOS_VIDEONODE_MFC_ENC_OTF_DRM))
+
+/* Decoder codec mode check */
+#define IS_H264_DEC(ctx)       ((ctx)->codec_mode == S5P_FIMV_CODEC_H264_DEC)
+#define IS_H264_MVC_DEC(ctx)   ((ctx)->codec_mode == S5P_FIMV_CODEC_H264_MVC_DEC)
+#define IS_MPEG4_DEC(ctx)      ((ctx)->codec_mode == S5P_FIMV_CODEC_MPEG4_DEC)
+#define IS_FIMV1_DEC(ctx)      ((ctx)->codec_mode == S5P_FIMV_CODEC_FIMV1_DEC)
+#define IS_FIMV2_DEC(ctx)      ((ctx)->codec_mode == S5P_FIMV_CODEC_FIMV2_DEC)
+#define IS_FIMV3_DEC(ctx)      ((ctx)->codec_mode == S5P_FIMV_CODEC_FIMV3_DEC)
+#define IS_FIMV4_DEC(ctx)      ((ctx)->codec_mode == S5P_FIMV_CODEC_FIMV4_DEC)
+#define IS_VC1_DEC(ctx)                ((ctx)->codec_mode == S5P_FIMV_CODEC_VC1_DEC)
+#define IS_VC1_RCV_DEC(ctx)    ((ctx)->codec_mode == S5P_FIMV_CODEC_VC1_RCV_DEC)
+#define IS_MPEG2_DEC(ctx)      ((ctx)->codec_mode == S5P_FIMV_CODEC_MPEG2_DEC)
+#define IS_HEVC_DEC(ctx)       ((ctx)->codec_mode == S5P_FIMV_CODEC_HEVC_DEC)
+#define IS_VP9_DEC(ctx)                ((ctx)->codec_mode == S5P_FIMV_CODEC_VP9_DEC)
+#define IS_BPG_DEC(ctx)                ((ctx)->codec_mode == S5P_FIMV_CODEC_BPG_DEC)
+
+/* Encoder codec mode check */
+#define IS_H264_ENC(ctx)       ((ctx)->codec_mode == S5P_FIMV_CODEC_H264_ENC)
+#define IS_MPEG4_ENC(ctx)      ((ctx)->codec_mode == S5P_FIMV_CODEC_MPEG4_ENC)
+#define IS_H263_ENC(ctx)       ((ctx)->codec_mode == S5P_FIMV_CODEC_H263_ENC)
+#define IS_VP8_ENC(ctx)                ((ctx)->codec_mode == S5P_FIMV_CODEC_VP8_ENC)
+#define IS_HEVC_ENC(ctx)       ((ctx)->codec_mode == S5P_FIMV_CODEC_HEVC_ENC)
+#define IS_VP9_ENC(ctx)                ((ctx)->codec_mode == S5P_FIMV_CODEC_VP9_ENC)
+#define IS_BPG_ENC(ctx)                ((ctx)->codec_mode == S5P_FIMV_CODEC_BPG_ENC)
+
+#define CODEC_NOT_CODED(ctx)   (IS_MPEG4_DEC(ctx) || IS_VC1_DEC(ctx) || IS_VC1_RCV_DEC(ctx))
+#define CODEC_INTERLACED(ctx)  (IS_H264_DEC(ctx) || IS_H264_MVC_DEC(ctx) ||    \
+                               IS_MPEG2_DEC(ctx) || IS_MPEG4_DEC(ctx) ||       \
+                               IS_VC1_DEC(ctx) || IS_VC1_RCV_DEC(ctx))
+#define CODEC_MBAFF(ctx)       (IS_H264_DEC(ctx) || IS_H264_MVC_DEC(ctx))
+#define CODEC_MULTIFRAME(ctx)  (IS_MPEG4_DEC(ctx) || IS_VP9_DEC(ctx) ||        \
+                               IS_FIMV2_DEC(ctx) || IS_FIMV3_DEC(ctx) || IS_FIMV4_DEC(ctx))
+#define CODEC_10BIT(ctx)       (IS_HEVC_DEC(ctx) || IS_HEVC_ENC(ctx) ||        \
+                               IS_VP9_DEC(ctx) || IS_VP9_ENC(ctx) ||           \
+                               IS_BPG_DEC(ctx) || IS_BPG_ENC(ctx))
+#define CODEC_422FORMAT(ctx)   (IS_HEVC_DEC(ctx) || IS_HEVC_ENC(ctx) ||        \
+                               IS_VP9_DEC(ctx) || IS_VP9_ENC(ctx) ||           \
+                               IS_BPG_DEC(ctx) || IS_BPG_ENC(ctx))
+#define ON_RES_CHANGE(ctx)     (((ctx)->state >= MFCINST_RES_CHANGE_INIT) &&   \
+                                ((ctx)->state <= MFCINST_RES_CHANGE_END))
+
+#define IS_BUFFER_BATCH_MODE(ctx)      ((ctx)->batch_mode == 1)
+
+/* UHD resoluition */
+#define MFC_UHD_RES            (3840 * 2160)
+#define IS_UHD_RES(ctx)                (((ctx)->crop_width * (ctx)->crop_height) == MFC_UHD_RES)
+#define OVER_UHD_ENC60(ctx)    ((((ctx)->crop_width * (ctx)->crop_height) == MFC_UHD_RES) && \
+                               ((ctx)->type == MFCINST_ENCODER) &&     \
+                               ((ctx)->framerate / 1000) >= 60)
+
+/* Extra information for Decoder */
+#define        DEC_SET_DUAL_DPB                (1 << 0)
+#define        DEC_SET_DYNAMIC_DPB             (1 << 1)
+#define        DEC_SET_LAST_FRAME_INFO         (1 << 2)
+#define        DEC_SET_SKYPE_FLAG              (1 << 3)
+
+/* Extra information for Encoder */
+#define        ENC_SET_RGB_INPUT               (1 << 0)
+#define        ENC_SET_SPARE_SIZE              (1 << 1)
+#define        ENC_SET_TEMP_SVC_CH             (1 << 2)
+#define        ENC_SET_SKYPE_FLAG              (1 << 3)
+#define        ENC_SET_ROI_CONTROL             (1 << 4)
+#define        ENC_SET_QP_BOUND_PB             (1 << 5)
+#define        ENC_SET_FIXED_SLICE             (1 << 6)
+#define        ENC_SET_PVC_MODE                (1 << 7)
+#define        ENC_SET_RATIO_OF_INTRA          (1 << 8)
+#define        ENC_SET_COLOR_ASPECT            (1 << 9)
+#define        ENC_SET_HP_BITRATE_CONTROL      (1 << 10)
+#define        ENC_SET_STATIC_INFO             (1 << 11)
+
+#define MFC_VER_MAJOR(dev)     ((dev->pdata->ip_ver >> 8) & 0xFF)
+#define MFC_VER_MINOR(dev)     (dev->pdata->ip_ver & 0xFF)
+
+#define MFC_FEATURE_SUPPORT(dev, f)    ((f).support && ((dev)->fw.date >= (f).version))
+
+/* Low memory check */
+#define IS_LOW_MEM                     (totalram_pages <= ((SZ_1G + SZ_512M) >> PAGE_SHIFT))
+#define SZ_600M                                (6 * 1024 * 1024)
+
+#endif /* __MFC_COMMON_H */
diff --git a/drivers/media/platform/exynos/mfc/mfc_ctrl.c b/drivers/media/platform/exynos/mfc/mfc_ctrl.c
new file mode 100644 (file)
index 0000000..10c2a32
--- /dev/null
@@ -0,0 +1,367 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_ctrl.c
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include "mfc_ctrl.h"
+
+#include "mfc_hwlock.h"
+#include "mfc_nal_q.h"
+#include "mfc_sync.h"
+
+#include "mfc_pm.h"
+#include "mfc_cmd.h"
+#include "mfc_cal.h"
+#include "mfc_reg.h"
+
+#include "mfc_utils.h"
+
+/* Initialize hardware */
+static int mfc_init_hw(struct s5p_mfc_dev *dev, enum mfc_buf_usage_type buf_type)
+{
+       int fw_ver;
+       int ret = 0;
+       int curr_ctx_is_drm_backup;
+
+       mfc_debug_enter();
+
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return -EINVAL;
+       }
+
+       curr_ctx_is_drm_backup = dev->curr_ctx_is_drm;
+
+       if (!dev->fw_buf.dma_buf)
+               return -EINVAL;
+
+       /* 0. MFC reset */
+       mfc_debug(2, "MFC reset...\n");
+
+       /* At init time, do not call secure API */
+       if (buf_type == MFCBUF_NORMAL)
+               dev->curr_ctx_is_drm = 0;
+       else if (buf_type == MFCBUF_DRM)
+               dev->curr_ctx_is_drm = 1;
+
+       ret = s5p_mfc_pm_clock_on(dev);
+       if (ret) {
+               mfc_err_dev("Failed to enable clock before reset(%d)\n", ret);
+               dev->curr_ctx_is_drm = curr_ctx_is_drm_backup;
+               return ret;
+       }
+
+       ret = s5p_mfc_reset_mfc(dev);
+       if (ret) {
+               mfc_err_dev("Failed to reset MFC - timeout\n");
+               goto err_init_hw;
+       }
+       mfc_debug(2, "Done MFC reset...\n");
+
+       /* 1. Set DRAM base Addr */
+       s5p_mfc_set_risc_base_addr(dev, buf_type);
+
+       /* 2. Release reset signal to the RISC */
+       s5p_mfc_risc_on(dev);
+
+       mfc_debug(2, "Will now wait for completion of firmware transfer\n");
+       if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_FW_STATUS_RET)) {
+               mfc_err_dev("Failed to RISC_ON\n");
+               s5p_mfc_clean_dev_int_flags(dev);
+               ret = -EIO;
+               goto err_init_hw;
+       }
+
+       /* 3. Initialize firmware */
+       ret = s5p_mfc_cmd_sys_init(dev, buf_type);
+       if (ret) {
+               mfc_err_dev("Failed to send command to MFC - timeout\n");
+               goto err_init_hw;
+       }
+
+       mfc_debug(2, "Ok, now will write a command to init the system\n");
+       if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_SYS_INIT_RET)) {
+               mfc_err_dev("Failed to SYS_INIT\n");
+               s5p_mfc_clean_dev_int_flags(dev);
+               ret = -EIO;
+               goto err_init_hw;
+       }
+
+       dev->int_condition = 0;
+       if (dev->int_err != 0 || dev->int_reason != S5P_FIMV_R2H_CMD_SYS_INIT_RET) {
+               /* Failure. */
+               mfc_err_dev("Failed to init firmware - error: %d, int: %d\n",
+                               dev->int_err, dev->int_reason);
+               ret = -EIO;
+               goto err_init_hw;
+       }
+
+       dev->fw.fimv_info = s5p_mfc_get_fimv_info();
+       if (dev->fw.fimv_info != 'D' && dev->fw.fimv_info != 'E')
+               dev->fw.fimv_info = 'N';
+
+       mfc_info_dev("[F/W] MFC v%x.%x, %02xyy %02xmm %02xdd (%c)\n",
+                MFC_VER_MAJOR(dev),
+                MFC_VER_MINOR(dev),
+                s5p_mfc_get_fw_ver_year(),
+                s5p_mfc_get_fw_ver_month(),
+                s5p_mfc_get_fw_ver_date(),
+                dev->fw.fimv_info);
+
+       dev->fw.date = s5p_mfc_get_fw_ver_all();
+       /* Check MFC version and F/W version */
+       fw_ver = s5p_mfc_get_mfc_version();
+       if (fw_ver != dev->pdata->ip_ver) {
+               mfc_err_dev("Invalid F/W version(0x%x) for MFC H/W(0x%x)\n",
+                               fw_ver, dev->pdata->ip_ver);
+               ret = -EIO;
+               goto err_init_hw;
+       }
+
+#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
+       /* Cache flush for base address change */
+       s5p_mfc_cmd_cache_flush(dev);
+       if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_CACHE_FLUSH_RET)) {
+               mfc_err_dev("Failed to CACHE_FLUSH\n");
+               s5p_mfc_clean_dev_int_flags(dev);
+               ret = -EIO;
+               goto err_init_hw;
+       }
+
+       if (buf_type == MFCBUF_DRM && !curr_ctx_is_drm_backup) {
+               s5p_mfc_pm_clock_off(dev);
+               dev->curr_ctx_is_drm = curr_ctx_is_drm_backup;
+               s5p_mfc_pm_clock_on_with_base(dev, MFCBUF_NORMAL);
+       }
+#endif
+
+err_init_hw:
+       s5p_mfc_pm_clock_off(dev);
+       dev->curr_ctx_is_drm = curr_ctx_is_drm_backup;
+       mfc_debug_leave();
+
+       return ret;
+}
+
+/* Wrapper : Initialize hardware */
+int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
+{
+       int ret;
+
+       ret = mfc_init_hw(dev, MFCBUF_NORMAL);
+       if (ret)
+               return ret;
+
+#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
+       if (dev->fw.drm_status) {
+               ret = mfc_init_hw(dev, MFCBUF_DRM);
+               if (ret)
+                       return ret;
+       }
+#endif
+
+       return ret;
+}
+
+/* Deinitialize hardware */
+void s5p_mfc_deinit_hw(struct s5p_mfc_dev *dev)
+{
+       int ret;
+
+       mfc_debug(2, "mfc deinit start\n");
+
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return;
+       }
+
+       ret = s5p_mfc_pm_clock_on(dev);
+       if (ret) {
+               mfc_err_dev("Failed to enable clock before reset(%d)\n", ret);
+               return;
+       }
+
+       s5p_mfc_mfc_off(dev);
+
+       s5p_mfc_pm_clock_off(dev);
+
+       mfc_debug(2, "mfc deinit completed\n");
+}
+
+int s5p_mfc_sleep(struct s5p_mfc_dev *dev)
+{
+       struct s5p_mfc_ctx *ctx;
+       int ret;
+       int old_state, i;
+       int need_cache_flush = 0;
+
+       mfc_debug_enter();
+
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return -EINVAL;
+       }
+
+       ctx = dev->ctx[dev->curr_ctx];
+       if (!ctx) {
+               for (i = 0; i < MFC_NUM_CONTEXTS; i++) {
+                       if (dev->ctx[i]) {
+                               ctx = dev->ctx[i];
+                               break;
+                       }
+               }
+               if (!ctx) {
+                       mfc_err_dev("no mfc context to run\n");
+                       return -EINVAL;
+               } else {
+                       mfc_info_dev("ctx is changed %d -> %d\n",
+                                       dev->curr_ctx, ctx->num);
+                       dev->curr_ctx = ctx->num;
+                       if (dev->curr_ctx_is_drm != ctx->is_drm) {
+                               need_cache_flush = 1;
+                               mfc_info_dev("DRM attribute is changed %d->%d\n",
+                                               dev->curr_ctx_is_drm, ctx->is_drm);
+                       }
+               }
+       }
+       old_state = ctx->state;
+       s5p_mfc_change_state(ctx, MFCINST_ABORT);
+       MFC_TRACE_DEV_HWLOCK("**sleep (ctx:%d)\n", ctx->num);
+       ret = s5p_mfc_get_hwlock_dev(dev);
+       if (ret < 0) {
+               mfc_err_dev("Failed to get hwlock\n");
+               mfc_err_dev("dev.hwlock.dev = 0x%lx, bits = 0x%lx, owned_by_irq = %d, wl_count = %d, transfer_owner = %d\n",
+                               dev->hwlock.dev, dev->hwlock.bits, dev->hwlock.owned_by_irq,
+                               dev->hwlock.wl_count, dev->hwlock.transfer_owner);
+               return -EBUSY;
+       }
+
+       mfc_info_dev("curr_ctx_is_drm:%d, hwlock.bits:%lu, hwlock.dev:%lu\n",
+                       dev->curr_ctx_is_drm, dev->hwlock.bits, dev->hwlock.dev);
+
+       s5p_mfc_change_state(ctx, old_state);
+       s5p_mfc_pm_clock_on(dev);
+
+       if (need_cache_flush)
+               s5p_mfc_cache_flush(dev, ctx->is_drm);
+
+       s5p_mfc_cmd_sleep(dev);
+
+       if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_SLEEP_RET)) {
+               mfc_err_dev("Failed to SLEEP\n");
+               dev->logging_data->cause |= (1 << MFC_CAUSE_FAIL_SLEEP);
+               call_dop(dev, dump_and_stop_always, dev);
+               return -EIO;
+       }
+
+       dev->int_condition = 0;
+       if (dev->int_err != 0 || dev->int_reason != S5P_FIMV_R2H_CMD_SLEEP_RET) {
+               /* Failure. */
+               mfc_err_dev("Failed to sleep - error: %d, int: %d\n",
+                               dev->int_err, dev->int_reason);
+               ret = -EIO;
+               goto err_mfc_sleep;
+       }
+
+       dev->sleep = 1;
+
+err_mfc_sleep:
+       s5p_mfc_mfc_off(dev);
+       s5p_mfc_pm_clock_off(dev);
+       s5p_mfc_release_hwlock_dev(dev);
+       mfc_debug_leave();
+
+       return ret;
+}
+
+int s5p_mfc_wakeup(struct s5p_mfc_dev *dev)
+{
+       enum mfc_buf_usage_type buf_type;
+       int ret = 0;
+
+       mfc_debug_enter();
+
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return -EINVAL;
+       }
+       mfc_info_dev("curr_ctx_is_drm:%d\n", dev->curr_ctx_is_drm);
+
+       MFC_TRACE_DEV_HWLOCK("**wakeup\n");
+       ret = s5p_mfc_get_hwlock_dev(dev);
+       if (ret < 0) {
+               mfc_err_dev("Failed to get hwlock\n");
+               mfc_err_dev("dev.hwlock.dev = 0x%lx, bits = 0x%lx, owned_by_irq = %d, wl_count = %d, transfer_owner = %d\n",
+                               dev->hwlock.dev, dev->hwlock.bits, dev->hwlock.owned_by_irq,
+                               dev->hwlock.wl_count, dev->hwlock.transfer_owner);
+               return -EBUSY;
+       }
+
+       dev->sleep = 0;
+
+       /* 0. MFC reset */
+       mfc_debug(2, "MFC reset...\n");
+
+       s5p_mfc_pm_clock_on(dev);
+
+       ret = s5p_mfc_reset_mfc(dev);
+       if (ret) {
+               mfc_err_dev("Failed to reset MFC - timeout\n");
+               goto err_mfc_wakeup;
+       }
+       mfc_debug(2, "Done MFC reset...\n");
+       if (dev->curr_ctx_is_drm)
+               buf_type = MFCBUF_DRM;
+       else
+               buf_type = MFCBUF_NORMAL;
+
+       /* 1. Set DRAM base Addr */
+       s5p_mfc_set_risc_base_addr(dev, buf_type);
+
+       /* 2. Release reset signal to the RISC */
+       s5p_mfc_risc_on(dev);
+
+       mfc_debug(2, "Will now wait for completion of firmware transfer\n");
+       if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_FW_STATUS_RET)) {
+               mfc_err_dev("Failed to RISC_ON\n");
+               dev->logging_data->cause |= (1 << MFC_CAUSE_FAIL_RISC_ON);
+               call_dop(dev, dump_and_stop_always, dev);
+               return -EIO;
+       }
+
+       mfc_debug(2, "Ok, now will write a command to wakeup the system\n");
+       s5p_mfc_cmd_wakeup(dev);
+
+       mfc_debug(2, "Will now wait for completion of firmware wake up\n");
+       if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_WAKEUP_RET)) {
+               mfc_err_dev("Failed to WAKEUP\n");
+               dev->logging_data->cause |= (1 << MFC_CAUSE_FAIL_WAKEUP);
+               call_dop(dev, dump_and_stop_always, dev);
+               return -EIO;
+       }
+
+       dev->int_condition = 0;
+       if (dev->int_err != 0 || dev->int_reason != S5P_FIMV_R2H_CMD_WAKEUP_RET) {
+               /* Failure. */
+               mfc_err_dev("Failed to wakeup - error: %d, int: %d\n",
+                               dev->int_err, dev->int_reason);
+               ret = -EIO;
+               goto err_mfc_wakeup;
+       }
+
+err_mfc_wakeup:
+       s5p_mfc_pm_clock_off(dev);
+
+       s5p_mfc_release_hwlock_dev(dev);
+
+       mfc_debug_leave();
+
+       return ret;
+}
diff --git a/drivers/media/platform/exynos/mfc/mfc_ctrl.h b/drivers/media/platform/exynos/mfc/mfc_ctrl.h
new file mode 100644 (file)
index 0000000..4e98e2e
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_ctrl.h
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __MFC_CTRL_H
+#define __MFC_CTRL_H __FILE__
+
+#include "mfc_common.h"
+
+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);
+
+#endif /* __MFC_CTRL_H */
diff --git a/drivers/media/platform/exynos/mfc/mfc_data_struct.h b/drivers/media/platform/exynos/mfc/mfc_data_struct.h
new file mode 100644 (file)
index 0000000..d7e15b7
--- /dev/null
@@ -0,0 +1,1408 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_data_struct.h
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __MFC_DATA_STRUCT_H
+#define __MFC_DATA_STRUCT_H __FILE__
+
+#ifdef CONFIG_ARM_EXYNOS_DEVFREQ
+#define CONFIG_MFC_USE_BUS_DEVFREQ
+#endif
+
+#ifdef CONFIG_MFC_USE_BUS_DEVFREQ
+#include <linux/pm_qos.h>
+#endif
+#ifdef CONFIG_EXYNOS_BTS
+#include <soc/samsung/bts.h>
+#endif
+#include <linux/videodev2.h>
+#ifdef CONFIG_EXYNOS_ITMON
+#include <soc/samsung/exynos-itmon.h>
+#endif
+
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <media/videobuf2-v4l2.h>
+
+#include "exynos_mfc_media.h"
+
+#define MFC_NUM_CONTEXTS               32
+#define MFC_MAX_PLANES                 3
+#define MFC_MAX_DPBS                   32
+#define MFC_MAX_BUFFERS                        32
+#define MFC_MAX_EXTRA_BUF              10
+#define MFC_TIME_INDEX                 15
+#define MFC_SFR_LOGGING_COUNT_SET1     4
+#define MFC_SFR_LOGGING_COUNT_SET2     23
+#define MFC_LOGGING_DATA_SIZE          256
+#define MFC_MAX_DEFAULT_PARAM          100
+
+#define HWFC_MAX_BUF                   10
+#define OTF_MAX_BUF                    30
+
+/* Maximum number of temporal layers */
+#define VIDEO_MAX_TEMPORAL_LAYERS      7
+
+#define MAX_NUM_IMAGES_IN_VB           8
+#define MAX_NUM_BUFCON_BUFS            32
+#define MAX_NUM_CLUSTER                        3
+
+/*
+ *  MFC region id for smc
+ */
+enum {
+       FC_MFC_EXYNOS_ID_MFC_SH        = 0,
+       FC_MFC_EXYNOS_ID_VIDEO         = 1,
+       FC_MFC_EXYNOS_ID_MFC_FW        = 2,
+       FC_MFC_EXYNOS_ID_SECTBL        = 3,
+       FC_MFC_EXYNOS_ID_G2D_WFD       = 4,
+       FC_MFC_EXYNOS_ID_MFC_NFW       = 5,
+       FC_MFC_EXYNOS_ID_VIDEO_EXT     = 6,
+};
+
+/**
+ * enum s5p_mfc_inst_type - The type of an MFC device node.
+ */
+enum s5p_mfc_node_type {
+       MFCNODE_INVALID = -1,
+       MFCNODE_DECODER = 0,
+       MFCNODE_ENCODER = 1,
+       MFCNODE_DECODER_DRM = 2,
+       MFCNODE_ENCODER_DRM = 3,
+       MFCNODE_ENCODER_OTF = 4,
+       MFCNODE_ENCODER_OTF_DRM = 5,
+};
+
+/**
+ * enum s5p_mfc_inst_type - The type of an MFC instance.
+ */
+enum s5p_mfc_inst_type {
+       MFCINST_INVALID = 0,
+       MFCINST_DECODER = 1,
+       MFCINST_ENCODER = 2,
+};
+
+/**
+ * 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_RUNNING_BUF_FULL,
+       MFCINST_RUNNING,
+       MFCINST_FINISHING,
+       MFCINST_RETURN_INST,
+       MFCINST_ERROR,
+       MFCINST_ABORT,
+       MFCINST_RES_CHANGE_INIT,
+       MFCINST_RES_CHANGE_FLUSH,
+       MFCINST_RES_CHANGE_END,
+       MFCINST_RUNNING_NO_OUTPUT, // Unused
+       MFCINST_ABORT_INST,
+       MFCINST_DPB_FLUSHING,
+       MFCINST_SPECIAL_PARSING,
+       MFCINST_SPECIAL_PARSING_NAL,
+};
+
+/**
+ * enum s5p_mfc_queue_state - The state of buffer queue.
+ */
+enum s5p_mfc_queue_state {
+       QUEUE_FREE = 0,
+       QUEUE_BUFS_REQUESTED,
+       QUEUE_BUFS_QUERIED,
+       QUEUE_BUFS_MMAPED,
+};
+
+enum mfc_dec_wait_state {
+       WAIT_NONE = 0,
+       WAIT_DECODING,
+       WAIT_INITBUF_DONE,
+};
+
+/**
+ * enum s5p_mfc_check_state - The state for user notification
+ */
+enum s5p_mfc_check_state {
+       MFCSTATE_PROCESSING = 0,
+       MFCSTATE_DEC_RES_DETECT,
+       MFCSTATE_DEC_TERMINATING,
+       MFCSTATE_ENC_NO_OUTPUT,
+       MFCSTATE_DEC_S3D_REALLOC,
+};
+
+enum mfc_buf_usage_type {
+       MFCBUF_INVALID = 0,
+       MFCBUF_NORMAL,
+       MFCBUF_DRM,
+       MFCBUF_NORMAL_FW,
+       MFCBUF_DRM_FW,
+};
+
+enum mfc_buf_process_type {
+       MFCBUFPROC_DEFAULT              = 0x0,
+       MFCBUFPROC_COPY                 = (1 << 0),
+       MFCBUFPROC_SHARE                = (1 << 1),
+       MFCBUFPROC_META                 = (1 << 2),
+       MFCBUFPROC_ANBSHARE             = (1 << 3),
+       MFCBUFPROC_ANBSHARE_NV12L       = (1 << 4),
+};
+
+enum s5p_mfc_ctrl_type {
+       MFC_CTRL_TYPE_GET_SRC   = 0x1,
+       MFC_CTRL_TYPE_GET_DST   = 0x2,
+       MFC_CTRL_TYPE_SET       = 0x4,
+};
+
+enum s5p_mfc_ctrl_mode {
+       MFC_CTRL_MODE_NONE      = 0x0,
+       MFC_CTRL_MODE_SFR       = 0x1,
+       MFC_CTRL_MODE_CST       = 0x2,
+};
+
+struct s5p_mfc_ctx;
+
+enum s5p_mfc_debug_cause {
+       MFC_CAUSE_0WRITE_PAGE_FAULT             = 0,
+       MFC_CAUSE_0READ_PAGE_FAULT              = 1,
+       MFC_CAUSE_1WRITE_PAGE_FAULT             = 2,
+       MFC_CAUSE_1READ_PAGE_FAULT              = 3,
+       MFC_CAUSE_NO_INTERRUPT                  = 4,
+       MFC_CAUSE_NO_SCHEDULING                 = 5,
+       MFC_CAUSE_FAIL_STOP_NAL_Q               = 6,
+       MFC_CAUSE_FAIL_STOP_NAL_Q_FOR_OTHER     = 7,
+       MFC_CAUSE_FAIL_CLOSE_INST               = 8,
+       MFC_CAUSE_FAIL_SLEEP                    = 9,
+       MFC_CAUSE_FAIL_WAKEUP                   = 10,
+       MFC_CAUSE_FAIL_RISC_ON                  = 11,
+       MFC_CAUSE_FAIL_DPB_FLUSH                = 12,
+       MFC_CAUSE_FAIL_CHACHE_FLUSH             = 13,
+};
+
+struct s5p_mfc_debug {
+       u32     cause;
+       u8      fault_status;
+       u32     fault_trans_info;
+       u32     fault_addr;
+       u8      SFRs_set1[MFC_SFR_LOGGING_COUNT_SET1];
+       u32     SFRs_set2[MFC_SFR_LOGGING_COUNT_SET2];
+       char    errorinfo[MFC_LOGGING_DATA_SIZE];
+};
+
+/**
+ * struct s5p_mfc_buf - MFC buffer
+ *
+ */
+struct s5p_mfc_buf {
+       struct vb2_v4l2_buffer vb;
+       struct list_head list;
+       dma_addr_t addr[MAX_NUM_IMAGES_IN_VB][MFC_MAX_PLANES];
+       struct dma_buf *dmabufs[MAX_NUM_IMAGES_IN_VB][MFC_MAX_PLANES];
+       struct dma_buf_attachment *attachments[MAX_NUM_IMAGES_IN_VB][MFC_MAX_PLANES];
+       int next_index;
+       int done_index;
+       int used;
+       int num_bufs_in_batch;
+       int num_valid_bufs;
+       unsigned char *vir_addr;
+};
+
+struct s5p_mfc_buf_queue {
+       struct list_head head;
+       unsigned int count;
+};
+
+struct s5p_mfc_bits {
+       unsigned long bits;
+       spinlock_t lock;
+};
+
+struct s5p_mfc_hwlock {
+       struct list_head waiting_list;
+       unsigned int wl_count;
+       unsigned long bits;
+       unsigned long dev;
+       unsigned int owned_by_irq;
+       unsigned int transfer_owner;
+       spinlock_t lock;
+};
+
+struct s5p_mfc_listable_wq {
+       struct list_head list;
+       wait_queue_head_t wait_queue;
+       struct mutex wait_mutex;
+       struct s5p_mfc_dev *dev;
+       struct s5p_mfc_ctx *ctx;
+};
+
+struct s5p_mfc_pm {
+       struct clk      *clock;
+       atomic_t        pwr_ref;
+       struct device   *device;
+       spinlock_t      clklock;
+
+       int clock_on_steps;
+       int clock_off_steps;
+       enum mfc_buf_usage_type base_type;
+};
+
+struct s5p_mfc_fw {
+       int             date;
+       int             fimv_info;
+       size_t          size;
+       int             status;
+       int             drm_status;
+};
+
+struct s5p_mfc_ctx_buf_size {
+       size_t dev_ctx;
+       size_t h264_dec_ctx;
+       size_t other_dec_ctx;
+       size_t h264_enc_ctx;
+       size_t hevc_enc_ctx;
+       size_t other_enc_ctx;
+       size_t shared_buf;
+       size_t dbg_info_buf;
+};
+
+struct s5p_mfc_buf_size {
+       size_t firmware_code;
+       unsigned int cpb_buf;
+       void *ctx_buf;
+};
+
+struct s5p_mfc_variant {
+       struct s5p_mfc_buf_size *buf_size;
+       int     num_entities;
+};
+
+enum mfc_sfr_dump_type {
+       MFC_DUMP_NONE                   = 0,
+       MFC_DUMP_DEC_SEQ_START          = (1 << 0),
+       MFC_DUMP_DEC_INIT_BUFS          = (1 << 1),
+       MFC_DUMP_DEC_NAL_START          = (1 << 2),
+       MFC_DUMP_ENC_SEQ_START          = (1 << 3),
+       MFC_DUMP_ENC_INIT_BUFS          = (1 << 4),
+       MFC_DUMP_ENC_NAL_START          = (1 << 5),
+       MFC_DUMP_ERR_INT                = (1 << 6),
+       MFC_DUMP_WARN_INT               = (1 << 7),
+};
+
+struct s5p_mfc_debugfs {
+       struct dentry *root;
+       struct dentry *mfc_info;
+       struct dentry *debug_info;
+       struct dentry *debug_level;
+       struct dentry *debug_ts;
+       struct dentry *dbg_enable;
+       struct dentry *nal_q_dump;
+       struct dentry *nal_q_disable;
+       struct dentry *nal_q_parallel_disable;
+       struct dentry *otf_dump;
+       struct dentry *perf_measure_option;
+       struct dentry *sfr_dump;
+       struct dentry *mmcache_dump;
+       struct dentry *mmcache_disable;
+       struct dentry *perf_boost_mode;
+};
+
+/**
+ * struct s5p_mfc_special_buf - represents internal used buffer
+ * @daddr:             device virtual address
+ * @virt:              kernel virtual address, only valid when the
+ *                     buffer accessed by driver
+ */
+struct s5p_mfc_special_buf {
+       enum mfc_buf_usage_type         buftype;
+       struct dma_buf                  *dma_buf;
+       struct dma_buf_attachment       *attachment;
+       struct sg_table                 *sgt;
+       dma_addr_t                      daddr;
+       void                            *vaddr;
+       size_t                          size;
+};
+
+#ifdef CONFIG_MFC_USE_BUS_DEVFREQ
+struct mfc_qos_bw_data {
+       unsigned long   peak;
+       unsigned long   read;
+       unsigned long   write;
+};
+
+struct s5p_mfc_qos_bw {
+       struct mfc_qos_bw_data h264_dec_uhd_bw;
+       struct mfc_qos_bw_data hevc_dec_uhd_bw;
+       struct mfc_qos_bw_data hevc_dec_uhd_10bit_bw;
+       struct mfc_qos_bw_data vp8_dec_uhd_bw;
+       struct mfc_qos_bw_data vp9_dec_uhd_bw;
+       struct mfc_qos_bw_data mpeg4_dec_uhd_bw;
+       struct mfc_qos_bw_data h264_enc_uhd_bw;
+       struct mfc_qos_bw_data hevc_enc_uhd_bw;
+       struct mfc_qos_bw_data hevc_enc_uhd_10bit_bw;
+       struct mfc_qos_bw_data vp8_enc_uhd_bw;
+       struct mfc_qos_bw_data vp9_enc_uhd_bw;
+       struct mfc_qos_bw_data mpeg4_enc_uhd_bw;
+};
+
+/*
+ * threshold_mb - threshold of total MB(macroblock) count
+ * Total MB count can be calculated by
+ *     (MB of width) * (MB of height) * fps
+ */
+struct s5p_mfc_qos {
+       unsigned int threshold_mb;
+       unsigned int freq_mfc;
+       unsigned int freq_int;
+       unsigned int freq_mif;
+       unsigned int mo_value;
+       unsigned int mo_10bit_value;
+       unsigned int mo_uhd_enc60_value;
+       unsigned int time_fw;
+};
+
+struct s5p_mfc_qos_boost {
+       unsigned int num_cluster;
+       unsigned int freq_mfc;
+       unsigned int freq_int;
+       unsigned int freq_mif;
+       unsigned int freq_cluster[MAX_NUM_CLUSTER];
+};
+#endif
+
+struct s5p_mfc_feature {
+       unsigned int support;
+       unsigned int version;
+};
+
+struct s5p_mfc_platdata {
+       /* MFC version */
+       unsigned int ip_ver;
+       /* Debug mode */
+       unsigned int debug_mode;
+       /* Sysmmu check */
+       unsigned int share_sysmmu;
+       unsigned int axid_mask;
+       unsigned int mfc_fault_num;
+       /* Features */
+       struct s5p_mfc_feature nal_q;
+       struct s5p_mfc_feature skype;
+       struct s5p_mfc_feature black_bar;
+       struct s5p_mfc_feature color_aspect_dec;
+       struct s5p_mfc_feature static_info_dec;
+       struct s5p_mfc_feature color_aspect_enc;
+       struct s5p_mfc_feature static_info_enc;
+       /* Default 10bit format for decoding */
+       unsigned int P010_decoding;
+       /* Formats */
+       unsigned int support_10bit;
+       unsigned int support_422;
+       unsigned int support_rgb;
+       /* Encoder default parameter */
+       unsigned int enc_param_num;
+       unsigned int enc_param_addr[MFC_MAX_DEFAULT_PARAM];
+       unsigned int enc_param_val[MFC_MAX_DEFAULT_PARAM];
+#ifdef CONFIG_MFC_USE_BUS_DEVFREQ
+       /* QoS */
+       unsigned int num_qos_steps;
+       unsigned int max_qos_steps;
+       unsigned int max_mb;
+       unsigned int mfc_freq_control;
+       unsigned int mo_control;
+       unsigned int bw_control;
+       struct s5p_mfc_qos *qos_table;
+       struct s5p_mfc_qos_boost *qos_boost_table;
+#endif
+};
+
+/************************ NAL_Q data structure ************************/
+#define NAL_Q_IN_ENTRY_SIZE            256
+#define NAL_Q_OUT_ENTRY_SIZE           256
+
+#define NAL_Q_IN_DEC_STR_SIZE          112
+#define NAL_Q_IN_ENC_STR_SIZE          204
+#define NAL_Q_OUT_DEC_STR_SIZE         248
+#define NAL_Q_OUT_ENC_STR_SIZE         64
+
+/* 256*128(max instance 32 * slot 4) = 32 kbytes */
+#define NAL_Q_IN_QUEUE_SIZE            128
+#define NAL_Q_OUT_QUEUE_SIZE           128
+
+typedef struct __DecoderInputStr {
+       int StartCode; /* = 0xAAAAAAAA; Decoder input structure marker */
+       int CommandId;
+       int InstanceId;
+       int PictureTag;
+       unsigned int CpbBufferAddr;
+       int CpbBufferSize;
+       int CpbBufferOffset;
+       int StreamDataSize;
+       int AvailableDpbFlagUpper;
+       int AvailableDpbFlagLower;
+       int DynamicDpbFlagUpper;
+       int DynamicDpbFlagLower;
+       unsigned int FrameAddr[3];
+       int FrameSize[3];
+       int NalStartOptions;
+       int FrameStrideSize[3];
+       int Frame2BitSize[2];
+       int Frame2BitStrideSize[2];
+       unsigned int ScratchBufAddr;
+       int ScratchBufSize;
+       char reserved[NAL_Q_IN_ENTRY_SIZE - NAL_Q_IN_DEC_STR_SIZE];
+} DecoderInputStr; /* 28*4 = 112 bytes */
+
+typedef struct __EncoderInputStr {
+       int StartCode; /* 0xBBBBBBBB; Encoder input structure marker */
+       int CommandId;
+       int InstanceId;
+       int PictureTag;
+       unsigned int FrameAddr[3];
+       unsigned int StreamBufferAddr;
+       int StreamBufferSize;
+       int StreamBufferOffset;
+       int RcRoiCtrl;
+       unsigned int RoiBufferAddr;
+       int ParamChange;
+       int IrSize;
+       int GopConfig;
+       int RcFrameRate;
+       int RcBitRate;
+       int MsliceMode;
+       int MsliceSizeMb;
+       int MsliceSizeBits;
+       int FrameInsertion;
+       int HierarchicalBitRateLayer[7];
+       int H264RefreshPeriod;
+       int HevcRefreshPeriod;
+       int RcQpBound;
+       int RcQpBoundPb;
+       int FixedPictureQp;
+       int PictureProfile;
+       int BitCountEnable;
+       int MaxBitCount;
+       int MinBitCount;
+       int NumTLayer;
+       int H264NalControl;
+       int HevcNalControl;
+       int Vp8NalControl;
+       int Vp9NalControl;
+       int H264HDSvcExtension0;
+       int H264HDSvcExtension1;
+       int GopConfig2;
+       int Frame2bitAddr[2];
+       int Weight;
+       int ExtCtbQpAddr;
+       int WeightUpper;
+       int RcMode;
+       char reserved[NAL_Q_IN_ENTRY_SIZE - NAL_Q_IN_ENC_STR_SIZE];
+} EncoderInputStr; /* 51*4 = 204 bytes */
+
+typedef struct __DecoderOutputStr {
+       int StartCode; /* 0xAAAAAAAA; Decoder output structure marker */
+       int CommandId;
+       int InstanceId;
+       int ErrorCode;
+       int PictureTagTop;
+       int PictureTimeTop;
+       int DisplayFrameWidth;
+       int DisplayFrameHeight;
+       int DisplayStatus;
+       unsigned int DisplayAddr[3];
+       int DisplayFrameType;
+       int DisplayCropInfo1;
+       int DisplayCropInfo2;
+       int DisplayPictureProfile;
+       int DisplayAspectRatio;
+       int DisplayExtendedAr;
+       int DecodedNalSize;
+       int UsedDpbFlagUpper;
+       int UsedDpbFlagLower;
+       int SeiAvail;
+       int FramePackArrgmentId;
+       int FramePackSeiInfo;
+       int FramePackGridPos;
+       int DisplayRecoverySeiInfo;
+       int H264Info;
+       int DisplayFirstCrc;
+       int DisplaySecondCrc;
+       int DisplayThirdCrc;
+       int DisplayFirst2BitCrc;
+       int DisplaySecond2BitCrc;
+       int DecodedFrameWidth;
+       int DecodedFrameHeight;
+       int DecodedStatus;
+       unsigned int DecodedAddr[3];
+       int DecodedFrameType;
+       int DecodedCropInfo1;
+       int DecodedCropInfo2;
+       int DecodedPictureProfile;
+       int DecodedRecoverySeiInfo;
+       int DecodedFirstCrc;
+       int DecodedSecondCrc;
+       int DecodedThirdCrc;
+       int DecodedFirst2BitCrc;
+       int DecodedSecond2BitCrc;
+       int PictureTagBot;
+       int PictureTimeBot;
+       int ChromaFormat;
+       int Mpeg4Info;
+       int HevcInfo;
+       int Vc1Info;
+       int VideoSignalType;
+       int ContentLightLevelInfoSei;
+       int MasteringDisplayColourVolumeSei0;
+       int MasteringDisplayColourVolumeSei1;
+       int MasteringDisplayColourVolumeSei2;
+       int MasteringDisplayColourVolumeSei3;
+       int MasteringDisplayColourVolumeSei4;
+       int MasteringDisplayColourVolumeSei5;
+       char reserved[NAL_Q_OUT_ENTRY_SIZE - NAL_Q_OUT_DEC_STR_SIZE];
+} DecoderOutputStr; /* 62*4 =  248 bytes */
+
+typedef struct __EncoderOutputStr {
+       int StartCode; /* 0xBBBBBBBB; Encoder output structure marker */
+       int CommandId;
+       int InstanceId;
+       int ErrorCode;
+       int PictureTag;
+       unsigned int EncodedFrameAddr[3];
+       unsigned int StreamBufferAddr;
+       int StreamBufferOffset;
+       int StreamSize;
+       int SliceType;
+       int NalDoneInfo;
+       unsigned int ReconLumaDpbAddr;
+       unsigned int ReconChromaDpbAddr;
+       int EncCnt;
+       char reserved[NAL_Q_OUT_ENTRY_SIZE - NAL_Q_OUT_ENC_STR_SIZE];
+} EncoderOutputStr; /* 16*4 = 64 bytes */
+
+/**
+ * enum nal_queue_state - The state for nal queue operation.
+ */
+typedef enum _nal_queue_state {
+       NAL_Q_STATE_CREATED = 0,
+       NAL_Q_STATE_STARTED, /* when s5p_mfc_nal_q_start() is called */
+       NAL_Q_STATE_STOPPED, /* when s5p_mfc_nal_q_stop() is called */
+} nal_queue_state;
+
+typedef struct _nal_in_queue {
+       union {
+               DecoderInputStr dec;
+               EncoderInputStr enc;
+       } entry[NAL_Q_IN_QUEUE_SIZE];
+} nal_in_queue;
+
+typedef struct _nal_out_queue {
+       union {
+               DecoderOutputStr dec;
+               EncoderOutputStr enc;
+       } entry[NAL_Q_OUT_QUEUE_SIZE];
+} nal_out_queue;
+
+struct _nal_queue_handle;
+typedef struct _nal_queue_in_handle {
+       struct _nal_queue_handle *nal_q_handle;
+       struct s5p_mfc_special_buf in_buf;
+       unsigned int in_exe_count;
+       nal_in_queue *nal_q_in_addr;
+} nal_queue_in_handle;
+
+typedef struct _nal_queue_out_handle {
+       struct _nal_queue_handle *nal_q_handle;
+       struct s5p_mfc_special_buf out_buf;
+       unsigned int out_exe_count;
+       nal_out_queue *nal_q_out_addr;
+       int nal_q_ctx;
+} nal_queue_out_handle;
+
+typedef struct _nal_queue_handle {
+       nal_queue_in_handle *nal_q_in_handle;
+       nal_queue_out_handle *nal_q_out_handle;
+       nal_queue_state nal_q_state;
+       unsigned int nal_q_clk_cnt;
+       spinlock_t lock;
+       int nal_q_exception;
+} nal_queue_handle;
+
+/************************ OTF data structure ************************/
+struct _otf_buf_addr {
+       dma_addr_t otf_daddr[HWFC_MAX_BUF][3];
+       struct dma_buf_attachment *otf_buf_attach[HWFC_MAX_BUF];
+};
+
+struct _otf_buf_info {
+       int pixel_format;
+       int width;
+       int height;
+       int buffer_count;
+       struct dma_buf *bufs[HWFC_MAX_BUF];
+};
+
+struct _otf_debug {
+       struct s5p_mfc_special_buf stream_buf[OTF_MAX_BUF];
+       unsigned int stream_size[OTF_MAX_BUF];
+       unsigned char frame_cnt;
+};
+
+struct _otf_handle {
+       int otf_work_bit;
+       int otf_buf_index;
+       int otf_job_id;
+       u64 otf_time_stamp;
+       struct _otf_buf_addr otf_buf_addr;
+       struct _otf_buf_info otf_buf_info;
+       struct _otf_debug otf_debug;
+};
+/********************************************************************/
+
+struct s5p_mfc_perf {
+       void __iomem *regs_base0;
+       void __iomem *regs_base1;
+
+       struct timeval begin;
+       struct timeval end;
+
+       int new_start;
+       int count;
+       int drv_margin;
+};
+
+extern struct s5p_mfc_dump_ops mfc_dump_ops;
+struct s5p_mfc_dump_ops {
+       void (*dump_regs)(struct s5p_mfc_dev *dev);
+       void (*dump_info)(struct s5p_mfc_dev *dev);
+       void (*dump_info_without_regs)(struct s5p_mfc_dev *dev);
+       void (*dump_and_stop_always)(struct s5p_mfc_dev *dev);
+       void (*dump_and_stop_debug_mode)(struct s5p_mfc_dev *dev);
+};
+
+struct s5p_mfc_mmcache {
+       void __iomem *base;
+       int is_on_status;
+};
+
+/**
+ * struct s5p_mfc_dev - The struct containing driver internal parameters.
+ */
+struct s5p_mfc_dev {
+       struct v4l2_device      v4l2_dev;
+       struct video_device     *vfd_dec;
+       struct video_device     *vfd_enc;
+       struct video_device     *vfd_dec_drm;
+       struct video_device     *vfd_enc_drm;
+       struct video_device     *vfd_enc_otf;
+       struct video_device     *vfd_enc_otf_drm;
+       struct device           *device;
+
+       void __iomem            *regs_base;
+       void __iomem            *sysmmu0_base;
+       void __iomem            *sysmmu1_base;
+       void __iomem            *hwfc_base;
+
+       int                     irq;
+       struct resource         *mfc_mem;
+
+       struct s5p_mfc_pm       pm;
+       struct s5p_mfc_fw       fw;
+       struct s5p_mfc_variant  *variant;
+       struct s5p_mfc_platdata *pdata;
+       struct s5p_mfc_debug    *logging_data;
+
+       int num_inst;
+
+       struct mutex mfc_mutex;
+
+       int int_condition;
+       int int_reason;
+       unsigned int int_err;
+
+       wait_queue_head_t cmd_wq;
+       struct s5p_mfc_listable_wq hwlock_wq;
+
+       bool has_2sysmmu;
+       bool has_hwfc;
+       bool has_mmcache;
+
+       struct s5p_mfc_special_buf common_ctx_buf;
+       struct s5p_mfc_special_buf drm_common_ctx_buf;
+
+       struct s5p_mfc_ctx *ctx[MFC_NUM_CONTEXTS];
+       int curr_ctx;
+       int preempt_ctx;
+
+       struct s5p_mfc_bits work_bits;
+
+       struct s5p_mfc_hwlock hwlock;
+
+       atomic_t sched_wait_cnt;
+       atomic_t watchdog_tick_running;
+       atomic_t watchdog_tick_cnt;
+       atomic_t watchdog_run;
+       struct timer_list watchdog_timer;
+       struct workqueue_struct *watchdog_wq;
+       struct work_struct watchdog_work;
+
+       /* for DRM */
+       int curr_ctx_is_drm;
+       int num_drm_inst;
+       struct s5p_mfc_special_buf fw_buf;
+       struct s5p_mfc_special_buf drm_fw_buf;
+
+       struct workqueue_struct *butler_wq;
+       struct work_struct butler_work;
+
+#ifdef CONFIG_MFC_USE_BUS_DEVFREQ
+       struct list_head qos_queue;
+       atomic_t qos_req_cur;
+       struct pm_qos_request qos_req_mfc;
+       struct pm_qos_request qos_req_int;
+       struct pm_qos_request qos_req_mif;
+       struct pm_qos_request qos_req_cluster[MAX_NUM_CLUSTER];
+       int qos_has_enc_ctx;
+#endif
+       int id;
+       atomic_t clk_ref;
+
+       atomic_t trace_ref;
+       struct _mfc_trace *mfc_trace;
+       atomic_t trace_ref_hwlock;
+       struct _mfc_trace *mfc_trace_hwlock;
+       bool continue_clock_on;
+
+       bool shutdown;
+       bool sleep;
+
+       nal_queue_handle *nal_q_handle;
+
+       struct s5p_mfc_special_buf dbg_info_buf;
+
+#ifdef CONFIG_EXYNOS_BTS
+       struct bts_bw mfc_bw;
+#endif
+
+       struct s5p_mfc_debugfs debugfs;
+       struct s5p_mfc_dump_ops *dump_ops;
+
+       struct s5p_mfc_perf perf;
+
+       struct s5p_mfc_mmcache mmcache;
+
+#ifdef CONFIG_EXYNOS_ITMON
+       struct notifier_block itmon_nb;
+       int itmon_notified;
+#endif
+};
+
+/**
+ *
+ */
+struct s5p_mfc_h264_enc_params {
+       enum v4l2_mpeg_video_h264_profile profile;
+       u8 level;
+       u8 interlace;
+       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 _8x8_transform;
+       u8 rc_frame_qp;
+       u8 rc_min_qp;
+       u8 rc_max_qp;
+       u8 rc_min_qp_p;
+       u8 rc_max_qp_p;
+       u8 rc_min_qp_b;
+       u8 rc_max_qp_b;
+       u8 rc_mb_dark;
+       u8 rc_mb_smooth;
+       u8 rc_mb_static;
+       u8 rc_mb_activity;
+       u8 rc_p_frame_qp;
+       u8 rc_b_frame_qp;
+       u8 ar_vui;
+       enum v4l2_mpeg_video_h264_vui_sar_idc ar_vui_idc;
+       u16 ext_sar_width;
+       u16 ext_sar_height;
+       u8 open_gop;
+       u16 open_gop_size;
+       u8 hier_qp_enable;
+       enum v4l2_mpeg_video_h264_hierarchical_coding_type hier_qp_type;
+       u8 num_hier_layer;
+       u8 hier_ref_type;
+       u8 hier_qp_layer[7];
+       u32 hier_bit_layer[7];
+       u8 sei_gen_enable;
+       u8 sei_fp_curr_frame_0;
+       enum v4l2_mpeg_video_h264_sei_fp_arrangement_type sei_fp_arrangement_type;
+       u32 fmo_enable;
+       u32 fmo_slice_map_type;
+       u32 fmo_slice_num_grp;
+       u32 fmo_run_length[4];
+       u32 fmo_sg_dir;
+       u32 fmo_sg_rate;
+       u32 aso_enable;
+       u32 aso_slice_order[8];
+
+       u32 prepend_sps_pps_to_idr;
+       u8 enable_ltr;
+       u8 num_of_ltr;
+       u32 set_priority;
+       u32 base_priority;
+       u32 vui_enable;
+};
+
+/**
+ *
+ */
+struct s5p_mfc_mpeg4_enc_params {
+       /* MPEG4 Only */
+       enum v4l2_mpeg_video_mpeg4_profile profile;
+       u8 level;
+       u8 quarter_pixel;
+       u16 vop_time_res;
+       u16 vop_frm_delta;
+       u8 rc_b_frame_qp;
+       /* Common for MPEG4, H263 */
+       u8 rc_frame_qp;
+       u8 rc_min_qp;
+       u8 rc_max_qp;
+       u8 rc_min_qp_p;
+       u8 rc_max_qp_p;
+       u8 rc_min_qp_b;
+       u8 rc_max_qp_b;
+       u8 rc_p_frame_qp;
+};
+
+/**
+ *
+ */
+struct s5p_mfc_vp9_enc_params {
+       /* VP9 Only */
+       u8 vp9_version;
+       u8 rc_min_qp;
+       u8 rc_max_qp;
+       u8 rc_min_qp_p;
+       u8 rc_max_qp_p;
+       u8 rc_frame_qp;
+       u8 rc_p_frame_qp;
+       u8 vp9_goldenframesel;
+       u16 vp9_gfrefreshperiod;
+       u8 hier_qp_enable;
+       u8 hier_qp_layer[3];
+       u32 hier_bit_layer[3];
+       u8 num_hier_layer;
+       u8 max_partition_depth;
+       u8 intra_pu_split_disable;
+       u8 profile;
+};
+
+/**
+ *
+ */
+struct s5p_mfc_vp8_enc_params {
+       /* VP8 Only */
+       u8 vp8_version;
+       u8 rc_min_qp;
+       u8 rc_max_qp;
+       u8 rc_min_qp_p;
+       u8 rc_max_qp_p;
+       u8 rc_frame_qp;
+       u8 rc_p_frame_qp;
+       u8 vp8_numberofpartitions;
+       u8 vp8_filterlevel;
+       u8 vp8_filtersharpness;
+       u8 vp8_goldenframesel;
+       u16 vp8_gfrefreshperiod;
+       u8 hier_qp_enable;
+       u8 hier_qp_layer[3];
+       u32 hier_bit_layer[3];
+       u8 intra_4x4mode_disable;
+       u8 num_hier_layer;
+};
+
+/**
+ *
+ */
+struct s5p_mfc_hevc_enc_params {
+       u8 profile;
+       u8 level;
+       u8 tier_flag;
+       /* HEVC Only */
+       u8 rc_min_qp;
+       u8 rc_max_qp;
+       u8 rc_min_qp_p;
+       u8 rc_max_qp_p;
+       u8 rc_min_qp_b;
+       u8 rc_max_qp_b;
+       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 refreshtype;
+       u16 refreshperiod;
+       s32 lf_beta_offset_div2;
+       s32 lf_tc_offset_div2;
+       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_hierarchical_coding_type hier_qp_type;
+       u8 hier_ref_type;
+       u8 num_hier_layer;
+       u8 hier_qp_layer[7];
+       u32 hier_bit_layer[7];
+       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 user_ref;
+       u8 store_ref;
+       u8 prepend_sps_pps_to_idr;
+};
+
+/**
+ *
+ */
+struct s5p_mfc_bpg_enc_params {
+       u32 thumb_size;
+       u32 exif_size;
+};
+
+/**
+ *
+ */
+struct s5p_mfc_enc_params {
+       u16 width;
+       u16 height;
+
+       u32 gop_size;
+       enum v4l2_mpeg_video_multi_slice_mode slice_mode;
+       u32 slice_mb;
+       u32 slice_bit;
+       u32 slice_mb_row;
+       u32 intra_refresh_mb;
+       u8 pad;
+       u8 pad_luma;
+       u8 pad_cb;
+       u8 pad_cr;
+       u8 rc_frame;
+       u32 rc_bitrate;
+       u32 rc_framerate;
+       u16 rc_reaction_coeff;
+       u32 config_qp;
+       u32 dynamic_qp;
+       u8 frame_tag;
+       u8 ratio_intra;
+
+       u8 num_b_frame;         /* H.264, HEVC, MPEG4 */
+       u8 num_refs_for_p;      /* H.264, HEVC, VP8, VP9 */
+       u8 rc_mb;               /* H.264: MFCv5, MPEG4/H.263: MFCv6 */
+       u8 rc_pvc;
+       u16 vbv_buf_size;
+       enum v4l2_mpeg_video_header_mode seq_hdr_mode;
+       enum v4l2_mpeg_mfc51_video_frame_skip_mode frame_skip_mode;
+       u8 fixed_target_bit;
+       u8 num_hier_max_layer;
+       u8 hier_bitrate_ctrl;
+       u8 weighted_enable;
+       u8 roi_enable;
+       u8 ivf_header_disable;  /* VP8, VP9 */
+
+       u16 rc_frame_delta;     /* MFC6.1 Only */
+
+       u32 i_frm_ctrl_mode;
+       u32 i_frm_ctrl;
+
+       u32 check_color_range;
+       u32 color_range;
+       u32 colour_primaries;
+       u32 transfer_characteristics;
+       u32 matrix_coefficients;
+
+       u32 static_info_enable;
+       u32 max_pic_average_light;
+       u32 max_content_light;
+       u32 max_display_luminance;
+       u32 min_display_luminance;
+       u32 white_point;
+       u32 display_primaries_0;
+       u32 display_primaries_1;
+       u32 display_primaries_2;
+
+       union {
+               struct s5p_mfc_h264_enc_params h264;
+               struct s5p_mfc_mpeg4_enc_params mpeg4;
+               struct s5p_mfc_vp8_enc_params vp8;
+               struct s5p_mfc_vp9_enc_params vp9;
+               struct s5p_mfc_hevc_enc_params hevc;
+               struct s5p_mfc_bpg_enc_params bpg;
+       } codec;
+};
+
+struct s5p_mfc_ctx_ctrl {
+       struct list_head list;
+       enum s5p_mfc_ctrl_type type;
+       unsigned int id;
+       unsigned int addr;
+       int has_new;
+       int val;
+};
+
+struct s5p_mfc_buf_ctrl {
+       struct list_head list;
+       unsigned int id;
+       enum s5p_mfc_ctrl_type type;
+       int has_new;
+       int val;
+       unsigned int old_val;           /* only for MFC_CTRL_TYPE_SET */
+       unsigned int old_val2;          /* only for MFC_CTRL_TYPE_SET */
+       unsigned int is_volatile;       /* only for MFC_CTRL_TYPE_SET */
+       unsigned int updated;
+       unsigned int mode;
+       unsigned int addr;
+       unsigned int mask;
+       unsigned int shft;
+       unsigned int flag_mode;         /* only for MFC_CTRL_TYPE_SET */
+       unsigned int flag_addr;         /* only for MFC_CTRL_TYPE_SET */
+       unsigned int flag_shft;         /* only for MFC_CTRL_TYPE_SET */
+       int (*read_cst) (struct s5p_mfc_ctx *ctx,
+                       struct s5p_mfc_buf_ctrl *buf_ctrl);
+       void (*write_cst) (struct s5p_mfc_ctx *ctx,
+                       struct s5p_mfc_buf_ctrl *buf_ctrl);
+};
+
+struct s5p_mfc_ctrl_cfg {
+       enum s5p_mfc_ctrl_type type;
+       unsigned int id;
+       unsigned int is_volatile;       /* only for MFC_CTRL_TYPE_SET */
+       unsigned int mode;
+       unsigned int addr;
+       unsigned int mask;
+       unsigned int shft;
+       unsigned int flag_mode;         /* only for MFC_CTRL_TYPE_SET */
+       unsigned int flag_addr;         /* only for MFC_CTRL_TYPE_SET */
+       unsigned int flag_shft;         /* only for MFC_CTRL_TYPE_SET */
+       int (*read_cst) (struct s5p_mfc_ctx *ctx,
+                       struct s5p_mfc_buf_ctrl *buf_ctrl);
+       void (*write_cst) (struct s5p_mfc_ctx *ctx,
+                       struct s5p_mfc_buf_ctrl *buf_ctrl);
+};
+
+/* per buffer contol */
+struct s5p_mfc_ctrls_ops {
+       /* controls per buffer */
+       int (*init_ctx_ctrls) (struct s5p_mfc_ctx *ctx);
+       int (*cleanup_ctx_ctrls) (struct s5p_mfc_ctx *ctx);
+       int (*init_buf_ctrls) (struct s5p_mfc_ctx *ctx,
+                       enum s5p_mfc_ctrl_type type, unsigned int index);
+       void (*reset_buf_ctrls) (struct list_head *head);
+       int (*cleanup_buf_ctrls) (struct s5p_mfc_ctx *ctx,
+                       enum s5p_mfc_ctrl_type type, unsigned int index);
+       int (*to_buf_ctrls) (struct s5p_mfc_ctx *ctx, struct list_head *head);
+       int (*to_ctx_ctrls) (struct s5p_mfc_ctx *ctx, struct list_head *head);
+       int (*set_buf_ctrls_val) (struct s5p_mfc_ctx *ctx,
+                       struct list_head *head);
+       int (*get_buf_ctrls_val) (struct s5p_mfc_ctx *ctx,
+                       struct list_head *head);
+       int (*recover_buf_ctrls_val) (struct s5p_mfc_ctx *ctx,
+                       struct list_head *head);
+       int (*get_buf_update_val) (struct s5p_mfc_ctx *ctx,
+                       struct list_head *head, unsigned int id, int value);
+       int (*set_buf_ctrls_val_nal_q_dec) (struct s5p_mfc_ctx *ctx,
+                       struct list_head *head, DecoderInputStr *pInStr);
+       int (*get_buf_ctrls_val_nal_q_dec) (struct s5p_mfc_ctx *ctx,
+                       struct list_head *head, DecoderOutputStr *pOutStr);
+       int (*set_buf_ctrls_val_nal_q_enc) (struct s5p_mfc_ctx *ctx,
+                       struct list_head *head, EncoderInputStr *pInStr);
+       int (*get_buf_ctrls_val_nal_q_enc) (struct s5p_mfc_ctx *ctx,
+                       struct list_head *head, EncoderOutputStr *pOutStr);
+       int (*recover_buf_ctrls_nal_q) (struct s5p_mfc_ctx *ctx,
+                       struct list_head *head);
+};
+
+struct stored_dpb_info {
+       int fd[MFC_MAX_PLANES];
+};
+
+struct dec_dpb_ref_info {
+       int index;
+       struct stored_dpb_info dpb[MFC_MAX_DPBS];
+};
+
+struct temporal_layer_info {
+       unsigned int temporal_layer_count;
+       unsigned int temporal_layer_bitrate[VIDEO_MAX_TEMPORAL_LAYERS];
+};
+
+struct mfc_enc_roi_info {
+       char *addr;
+       int size;
+       int upper_qp;
+       int lower_qp;
+       bool enable;
+};
+
+struct mfc_user_shared_handle {
+       int fd;
+       struct dma_buf *dma_buf;
+       void *vaddr;
+};
+
+struct s5p_mfc_raw_info {
+       int num_planes;
+       int stride[3];
+       int plane_size[3];
+       int stride_2bits[3];
+       int plane_size_2bits[3];
+       unsigned int total_plane_size;
+};
+
+struct mfc_timestamp {
+       struct list_head list;
+       struct timeval timestamp;
+       int index;
+       int interval;
+};
+
+struct s5p_mfc_dec {
+       int total_dpb_count;
+
+       unsigned int src_buf_size;
+
+       int loop_filter_mpeg4;
+       int display_delay;
+       int immediate_display;
+       int slice_enable;
+       int mv_count;
+       int idr_decoding;
+       int is_interlaced;
+       int is_dts_mode;
+
+       int crc_enable;
+       int crc_luma0;
+       int crc_chroma0;
+       int crc_luma1;
+       int crc_chroma1;
+
+       unsigned long consumed;
+       unsigned long remained_size;
+
+       enum v4l2_memory dst_memtype;
+       int sei_parse;
+       int stored_tag;
+       dma_addr_t y_addr_for_pb;
+
+       int cr_left, cr_right, cr_top, cr_bot;
+
+       int detect_black_bar;
+       bool black_bar_updated;
+       struct v4l2_rect black_bar;
+
+       /* For dynamic DPB */
+       int is_dynamic_dpb;
+       unsigned long available_dpb;
+       unsigned int dynamic_set;
+       unsigned int dynamic_used;
+
+       struct dec_dpb_ref_info *ref_info;
+       int assigned_fd[MFC_MAX_DPBS];
+       struct mfc_user_shared_handle sh_handle;
+       struct s5p_mfc_buf *assigned_dpb[MFC_MAX_DPBS];
+
+       int has_multiframe;
+       int is_dpb_full;
+
+       unsigned int err_reuse_flag;
+       unsigned int dec_only_release_flag;
+
+       /* for debugging about black bar detection */
+       void *frame_vaddr[3][30];
+       dma_addr_t frame_daddr[3][30];
+       int index[3][30];
+       int fd[3][30];
+       unsigned int frame_size[3][30];
+       unsigned char frame_cnt;
+
+       unsigned int num_of_tile_over_4;
+
+       unsigned int color_range;
+       unsigned int color_space;
+};
+
+struct s5p_mfc_enc {
+       struct s5p_mfc_enc_params params;
+
+       unsigned int dst_buf_size;
+       unsigned int header_size;
+
+       enum v4l2_mpeg_mfc51_video_frame_type frame_type;
+       enum v4l2_mpeg_mfc51_video_force_frame_type force_frame_type;
+
+       size_t luma_dpb_size;
+       size_t chroma_dpb_size;
+       size_t me_buffer_size;
+       size_t tmv_buffer_size;
+
+       unsigned int slice_mode;
+       union {
+               unsigned int mb;
+               unsigned int bits;
+       } slice_size;
+       unsigned int in_slice;
+       unsigned int buf_full;
+
+       int stored_tag;
+       struct mfc_user_shared_handle sh_handle_svc;
+       struct mfc_user_shared_handle sh_handle_roi;
+       int roi_index;
+       struct s5p_mfc_special_buf roi_buf[MFC_MAX_EXTRA_BUF];
+       struct mfc_enc_roi_info roi_info[MFC_MAX_EXTRA_BUF];
+};
+
+struct s5p_mfc_fmt {
+       char *name;
+       u32 fourcc;
+       u32 codec_mode;
+       u32 type;
+       u32 num_planes;
+       u32 mem_planes;
+};
+
+/**
+ * struct s5p_mfc_ctx - This struct contains the instance context
+ */
+struct s5p_mfc_ctx {
+       struct s5p_mfc_dev *dev;
+       struct v4l2_fh fh;
+       int num;
+
+       int int_condition;
+       int int_reason;
+       unsigned int int_err;
+
+       wait_queue_head_t cmd_wq;
+       struct s5p_mfc_listable_wq hwlock_wq;
+
+       struct s5p_mfc_fmt *src_fmt;
+       struct s5p_mfc_fmt *dst_fmt;
+
+       struct vb2_queue vq_src;
+       struct vb2_queue vq_dst;
+
+       struct s5p_mfc_buf_queue src_buf_queue;
+       struct s5p_mfc_buf_queue dst_buf_queue;
+       struct s5p_mfc_buf_queue src_buf_nal_queue;
+       struct s5p_mfc_buf_queue dst_buf_nal_queue;
+       struct s5p_mfc_buf_queue ref_buf_queue;
+       spinlock_t buf_queue_lock;
+
+       enum s5p_mfc_inst_type type;
+       enum s5p_mfc_inst_state state;
+       int inst_no;
+
+       int img_width;
+       int img_height;
+       int crop_width;
+       int crop_height;
+       int crop_left;
+       int crop_top;
+       int dpb_count;
+       int buf_stride;
+
+       int min_dpb_size[3];
+
+       struct s5p_mfc_raw_info raw_buf;
+       size_t mv_size;
+
+       struct s5p_mfc_special_buf codec_buf;
+       int codec_buffer_allocated;
+
+       enum s5p_mfc_queue_state capture_state;
+       enum s5p_mfc_queue_state output_state;
+
+       struct list_head ctrls;
+
+       struct list_head src_ctrls[MFC_MAX_BUFFERS];
+       struct list_head dst_ctrls[MFC_MAX_BUFFERS];
+
+       unsigned long src_ctrls_avail;
+       unsigned long dst_ctrls_avail;
+
+       unsigned int sequence;
+
+       /* Control values */
+       int codec_mode;
+       __u32 pix_format;
+
+       /* Extra Buffers */
+       struct s5p_mfc_special_buf instance_ctx_buf;
+
+       struct s5p_mfc_dec *dec_priv;
+       struct s5p_mfc_enc *enc_priv;
+
+       struct s5p_mfc_ctrls_ops *c_ops;
+
+       size_t scratch_buf_size;
+       size_t loopfilter_luma_size;
+       size_t loopfilter_chroma_size;
+
+       /* Profile infomation */
+       int is_10bit;
+       int is_422;
+
+       /* for DRM */
+       int is_drm;
+
+       int is_dpb_realloc;
+       enum mfc_dec_wait_state wait_state;
+       int clear_work_bit;
+
+#ifdef CONFIG_MFC_USE_BUS_DEVFREQ
+       int qos_req_step;
+       struct list_head qos_list;
+#endif
+       unsigned int qos_ratio;
+       unsigned long framerate;
+       unsigned long last_framerate;
+
+       struct mfc_timestamp ts_array[MFC_TIME_INDEX];
+       struct list_head ts_list;
+       int ts_count;
+       int ts_is_full;
+
+       int buf_process_type;
+
+       unsigned long raw_protect_flag;
+       unsigned long stream_protect_flag;
+       struct _otf_handle *otf_handle;
+
+       int batch_mode;
+       bool check_dump;
+};
+
+#endif /* __MFC_DATA_STRUCT_H */
diff --git a/drivers/media/platform/exynos/mfc/mfc_debug.h b/drivers/media/platform/exynos/mfc/mfc_debug.h
new file mode 100644 (file)
index 0000000..0f219b2
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_debug.h
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __MFC_DEBUG_H
+#define __MFC_DEBUG_H __FILE__
+
+#define DEBUG
+
+#ifdef DEBUG
+
+extern unsigned int debug_level;
+extern unsigned int debug_ts;
+extern unsigned int dbg_enable;
+extern unsigned int nal_q_dump;
+extern unsigned int nal_q_disable;
+extern unsigned int nal_q_parallel_disable;
+extern unsigned int otf_dump;
+extern unsigned int sfr_dump;
+extern unsigned int mmcache_dump;
+extern unsigned int mmcache_disable;
+extern unsigned int perf_boost_mode;
+
+#define mfc_debug(level, fmt, args...)                         \
+       do {                                                    \
+               if (debug_level >= level)                               \
+                       printk(KERN_DEBUG "%s:%d: " fmt,        \
+                               __func__, __LINE__, ##args);    \
+       } while (0)
+#else
+#define mfc_debug(fmt, args...)
+#endif
+
+#define mfc_debug_enter() mfc_debug(5, "enter\n")
+#define mfc_debug_leave() mfc_debug(5, "leave\n")
+
+#define mfc_err_dev(fmt, args...)                      \
+       do {                                            \
+               printk(KERN_ERR "%s:%d: " fmt,          \
+                      __func__, __LINE__, ##args);     \
+       } while (0)
+
+#define mfc_err_ctx(fmt, args...)                      \
+       do {                                            \
+               printk(KERN_ERR "[c:%d] %s:%d: " fmt,   \
+                       ctx->num,                       \
+                      __func__, __LINE__, ##args);     \
+       } while (0)
+
+#define mfc_info_dev(fmt, args...)                     \
+       do {                                            \
+               printk(KERN_INFO "%s:%d: " fmt,         \
+                       __func__, __LINE__, ##args);    \
+       } while (0)
+
+#define mfc_info_ctx(fmt, args...)                     \
+       do {                                            \
+               printk(KERN_INFO "[c:%d] %s:%d: " fmt,  \
+                       ctx->num,                       \
+                       __func__, __LINE__, ##args);    \
+       } while (0)
+
+#define MFC_TRACE_STR_LEN              80
+#define MFC_TRACE_COUNT_MAX            1024
+#define MFC_TRACE_COUNT_PRINT          30
+
+struct _mfc_trace {
+       unsigned long long time;
+       char str[MFC_TRACE_STR_LEN];
+};
+
+/* If there is no ctx structure */
+#define MFC_TRACE_DEV(fmt, args...)                                                            \
+       do {                                                                                    \
+               int cpu = raw_smp_processor_id();                                               \
+               int cnt;                                                                        \
+               cnt = atomic_inc_return(&dev->trace_ref) & (MFC_TRACE_COUNT_MAX - 1);           \
+               dev->mfc_trace[cnt].time = cpu_clock(cpu);                                      \
+               snprintf(dev->mfc_trace[cnt].str, MFC_TRACE_STR_LEN,                            \
+                               fmt, ##args);                           \
+       } while (0)
+
+/* If there is ctx structure */
+#define MFC_TRACE_CTX(fmt, args...)                                                            \
+       do {                                                                                    \
+               int cpu = raw_smp_processor_id();                                               \
+               int cnt;                                                                        \
+               cnt = atomic_inc_return(&dev->trace_ref) & (MFC_TRACE_COUNT_MAX - 1);           \
+               dev->mfc_trace[cnt].time = cpu_clock(cpu);                                      \
+               snprintf(dev->mfc_trace[cnt].str, MFC_TRACE_STR_LEN,                            \
+                               "[c:%d] " fmt, ctx->num, ##args);                               \
+       } while (0)
+
+
+/* If there is no ctx structure */
+#define MFC_TRACE_DEV_HWLOCK(fmt, args...)                                                     \
+       do {                                                                                    \
+               int cpu = raw_smp_processor_id();                                               \
+               int cnt;                                                                        \
+               cnt = atomic_inc_return(&dev->trace_ref_hwlock) & (MFC_TRACE_COUNT_MAX - 1);    \
+               dev->mfc_trace_hwlock[cnt].time = cpu_clock(cpu);                               \
+               snprintf(dev->mfc_trace_hwlock[cnt].str, MFC_TRACE_STR_LEN,                     \
+                               fmt, ##args);                                                   \
+       } while (0)
+
+/* If there is ctx structure */
+#define MFC_TRACE_CTX_HWLOCK(fmt, args...)                                                     \
+       do {                                                                                    \
+               int cpu = raw_smp_processor_id();                                               \
+               int cnt;                                                                        \
+               cnt = atomic_inc_return(&dev->trace_ref_hwlock) & (MFC_TRACE_COUNT_MAX - 1);    \
+               dev->mfc_trace_hwlock[cnt].time = cpu_clock(cpu);                               \
+               snprintf(dev->mfc_trace_hwlock[cnt].str, MFC_TRACE_STR_LEN,                     \
+                               "[c:%d] " fmt, ctx->num, ##args);                               \
+       } while (0)
+
+
+#endif /* __MFC_DEBUG_H */
diff --git a/drivers/media/platform/exynos/mfc/mfc_debugfs.c b/drivers/media/platform/exynos/mfc/mfc_debugfs.c
new file mode 100644 (file)
index 0000000..f8b6092
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_debug.c
+ *
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+#include "mfc_debugfs.h"
+#include "mfc_sync.h"
+
+#include "mfc_pm.h"
+
+#include "mfc_queue.h"
+
+unsigned int debug_level;
+unsigned int debug_ts;
+unsigned int dbg_enable;
+unsigned int nal_q_dump;
+unsigned int nal_q_disable;
+unsigned int nal_q_parallel_disable;
+unsigned int otf_dump;
+unsigned int perf_measure_option;
+unsigned int sfr_dump;
+unsigned int mmcache_dump;
+unsigned int mmcache_disable;
+unsigned int perf_boost_mode;
+
+static int mfc_info_show(struct seq_file *s, void *unused)
+{
+       struct s5p_mfc_dev *dev = s->private;
+       struct s5p_mfc_ctx *ctx = NULL;
+       int i;
+       char *codec_name = NULL;
+
+       seq_puts(s, ">> MFC device information(common)\n");
+       seq_printf(s, "[VERSION] H/W: v%x.%x, F/W: %06x(%c), DRV: %d\n",
+                MFC_VER_MAJOR(dev), MFC_VER_MINOR(dev), dev->fw.date,
+                dev->fw.fimv_info, MFC_DRIVER_INFO);
+       seq_printf(s, "[PM] power: %d, clock: %d\n",
+                       s5p_mfc_pm_get_pwr_ref_cnt(dev), s5p_mfc_pm_get_clk_ref_cnt(dev));
+       seq_printf(s, "[CTX] num_inst: %d, num_drm_inst: %d, curr_ctx: %d(is_drm: %d)\n",
+                       dev->num_inst, dev->num_drm_inst, dev->curr_ctx, dev->curr_ctx_is_drm);
+       seq_printf(s, "[HWLOCK] bits: %#lx, dev: %#lx, owned_by_irq = %d, wl_count = %d\n",
+                       dev->hwlock.bits, dev->hwlock.dev,
+                       dev->hwlock.owned_by_irq, dev->hwlock.wl_count);
+       seq_printf(s, "[DEBUG MODE] %s\n", dev->pdata->debug_mode ? "enabled" : "disabled");
+       seq_printf(s, "[MMCACHE] %s(%s)\n",
+                       dev->has_mmcache ? "supported" : "not supported",
+                       dev->mmcache.is_on_status ? "enabled" : "disabled");
+       seq_printf(s, "[PERF BOOST] %s\n", perf_boost_mode ? "enabled" : "disabled");
+       seq_printf(s, "[FEATURES] nal_q: %d(0x%x), skype: %d(0x%x), black_bar: %d(0x%x)\n",
+                       dev->pdata->nal_q.support, dev->pdata->nal_q.version,
+                       dev->pdata->skype.support, dev->pdata->skype.version,
+                       dev->pdata->black_bar.support, dev->pdata->black_bar.version);
+       seq_printf(s, "           color_aspect_dec: %d(0x%x), enc: %d(0x%x)\n",
+                       dev->pdata->color_aspect_dec.support, dev->pdata->color_aspect_dec.version,
+                       dev->pdata->color_aspect_enc.support, dev->pdata->color_aspect_enc.version);
+       seq_printf(s, "           static_info_dec: %d(0x%x), enc: %d(0x%x)\n",
+                       dev->pdata->static_info_dec.support, dev->pdata->static_info_dec.version,
+                       dev->pdata->static_info_enc.support, dev->pdata->static_info_enc.version);
+       seq_printf(s, "[FORMATS] 10bit: %s, 422: %s, RGB: %s\n",
+                       dev->pdata->support_10bit ? "supported" : "not supported",
+                       dev->pdata->support_422 ? "supported" : "not supported",
+                       dev->pdata->support_rgb ? "supported" : "not supported");
+       seq_printf(s, "[LOWMEM] is_low_mem: %d\n", IS_LOW_MEM);
+       if (dev->nal_q_handle)
+               seq_printf(s, "[NAL-Q] state: %d\n", dev->nal_q_handle->nal_q_state);
+
+       seq_puts(s, ">> MFC device information(instance)\n");
+       for (i = 0; i < MFC_NUM_CONTEXTS; i++) {
+               ctx = dev->ctx[i];
+               if (ctx) {
+                       if (ctx->type == MFCINST_DECODER)
+                               codec_name = ctx->src_fmt->name;
+                       else
+                               codec_name = ctx->dst_fmt->name;
+
+                       seq_printf(s, "[CTX:%d] codec: %s(%s), width: %d, height: %d, crop: %d %d %d %d, state: %d\n",
+                               ctx->num, ctx->type == MFCINST_DECODER ? "DEC" : "ENC", codec_name,
+                               ctx->img_width, ctx->img_height, ctx->crop_width, ctx->crop_height,
+                               ctx->crop_left, ctx->crop_top, ctx->state);
+                       seq_printf(s, "        queue(src: %d, dst: %d, src_nal: %d, dst_nal: %d, ref: %d)\n",
+                               s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->src_buf_queue),
+                               s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->dst_buf_queue),
+                               s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->src_buf_nal_queue),
+                               s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->dst_buf_nal_queue),
+                               s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->ref_buf_queue));
+               }
+       }
+
+       return 0;
+}
+
+static int mfc_debug_info_show(struct seq_file *s, void *unused)
+{
+       seq_puts(s, ">> MFC debug information\n");
+
+       seq_puts(s, "-----SFR dump options (bit setting)\n");
+       seq_puts(s, "ex) echo 0xff > /d/mfc/sfr_dump (all dump mode)\n");
+       seq_puts(s, "1   (1 << 0): dec SEQ_START\n");
+       seq_puts(s, "2   (1 << 1): dec INIT_BUFS\n");
+       seq_puts(s, "4   (1 << 2): dec NAL_START\n");
+       seq_puts(s, "8   (1 << 3): enc SEQ_START\n");
+       seq_puts(s, "16  (1 << 4): enc INIT_BUFS\n");
+       seq_puts(s, "32  (1 << 5): enc NAL_START\n");
+       seq_puts(s, "64  (1 << 6): ERR interrupt\n");
+       seq_puts(s, "128 (1 << 7): WARN interrupt\n");
+
+       seq_puts(s, "-----Performance boost options (bit setting)\n");
+       seq_puts(s, "ex) echo 7 > /d/mfc/perf_boost_mode (max freq)\n");
+       seq_puts(s, "1   (1 << 0): DVFS (INT/MFC/MIF)\n");
+       seq_puts(s, "2   (1 << 1): MO value\n");
+       seq_puts(s, "4   (1 << 2): CPU frequency\n");
+
+       return 0;
+}
+
+static int mfc_info_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, mfc_info_show, inode->i_private);
+}
+
+static int mfc_debug_info_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, mfc_debug_info_show, inode->i_private);
+}
+
+static const struct file_operations mfc_info_fops = {
+       .open = mfc_info_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release,
+};
+
+static const struct file_operations debug_info_fops = {
+       .open = mfc_debug_info_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release,
+};
+
+void s5p_mfc_init_debugfs(struct s5p_mfc_dev *dev)
+{
+       struct s5p_mfc_debugfs *debugfs = &dev->debugfs;
+
+       debugfs->root = debugfs_create_dir("mfc", NULL);
+       if (!debugfs->root) {
+               mfc_err_dev("debugfs: failed to create root derectory\n");
+               return;
+       }
+
+       debugfs->mfc_info = debugfs_create_file("mfc_info",
+                       0444, debugfs->root, dev, &mfc_info_fops);
+       debugfs->debug_info = debugfs_create_file("debug_info",
+                       0444, debugfs->root, dev, &debug_info_fops);
+       debugfs->debug_level = debugfs_create_u32("debug",
+                       0644, debugfs->root, &debug_level);
+       debugfs->debug_ts = debugfs_create_u32("debug_ts",
+                       0644, debugfs->root, &debug_ts);
+       debugfs->dbg_enable = debugfs_create_u32("dbg_enable",
+                       0644, debugfs->root, &dbg_enable);
+       debugfs->nal_q_dump = debugfs_create_u32("nal_q_dump",
+                       0644, debugfs->root, &nal_q_dump);
+       debugfs->nal_q_disable = debugfs_create_u32("nal_q_disable",
+                       0644, debugfs->root, &nal_q_disable);
+       debugfs->nal_q_parallel_disable = debugfs_create_u32("nal_q_parallel_disable",
+                       0644, debugfs->root, &nal_q_parallel_disable);
+       debugfs->otf_dump = debugfs_create_u32("otf_dump",
+                       0644, debugfs->root, &otf_dump);
+       debugfs->perf_measure_option = debugfs_create_u32("perf_measure_option",
+                       0644, debugfs->root, &perf_measure_option);
+       debugfs->sfr_dump = debugfs_create_u32("sfr_dump",
+                       0644, debugfs->root, &sfr_dump);
+       debugfs->mmcache_dump = debugfs_create_u32("mmcache_dump",
+                       0644, debugfs->root, &mmcache_dump);
+       debugfs->mmcache_disable = debugfs_create_u32("mmcache_disable",
+                       0644, debugfs->root, &mmcache_disable);
+       debugfs->perf_boost_mode = debugfs_create_u32("perf_boost_mode",
+                       0644, debugfs->root, &perf_boost_mode);
+}
diff --git a/drivers/media/platform/exynos/mfc/mfc_debugfs.h b/drivers/media/platform/exynos/mfc/mfc_debugfs.h
new file mode 100644 (file)
index 0000000..36456de
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_debugfs.h
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __MFC_DEBUGFS_H
+#define __MFC_DEBUGFS_H __FILE__
+
+#include "mfc_common.h"
+
+void s5p_mfc_init_debugfs(struct s5p_mfc_dev *dev);
+
+#endif /* __MFC_DEBUGFS_H */
diff --git a/drivers/media/platform/exynos/mfc/mfc_dec.c b/drivers/media/platform/exynos/mfc/mfc_dec.c
new file mode 100644 (file)
index 0000000..d6e2a88
--- /dev/null
@@ -0,0 +1,1279 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_dec.c
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include "mfc_dec.h"
+#include "mfc_dec_internal.h"
+
+#include "mfc_hwlock.h"
+#include "mfc_opr.h"
+#include "mfc_sync.h"
+#include "mfc_mmcache.h"
+
+#include "mfc_qos.h"
+#include "mfc_queue.h"
+#include "mfc_utils.h"
+#include "mfc_buf.h"
+#include "mfc_mem.h"
+
+#define MAX_FRAME_SIZE         (2*1024*1024)
+
+/* Find selected format description */
+static struct s5p_mfc_fmt *mfc_dec_find_format(struct s5p_mfc_ctx *ctx,
+               unsigned int pixelformat)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_fmt *fmt = NULL;
+       unsigned long i;
+
+       for (i = 0; i < NUM_FORMATS; i++) {
+               if (dec_formats[i].fourcc == pixelformat) {
+                       fmt = (struct s5p_mfc_fmt *)&dec_formats[i];
+                       break;
+               }
+       }
+
+       if (!dev->pdata->support_10bit && (fmt->type & MFC_FMT_10BIT)) {
+               mfc_err_ctx("[FRAME] 10bit is not supported\n");
+               fmt = NULL;
+       }
+       if (!dev->pdata->support_422 && (fmt->type & MFC_FMT_422)) {
+               mfc_err_ctx("[FRAME] 422 is not supported\n");
+               fmt = NULL;
+       }
+
+       return fmt;
+}
+
+static struct v4l2_queryctrl *mfc_dec_get_ctrl(int id)
+{
+       unsigned long i;
+
+       for (i = 0; i < NUM_CTRLS; ++i)
+               if (id == controls[i].id)
+                       return &controls[i];
+
+       return NULL;
+}
+
+/* Check whether a ctrl value if correct */
+static int mfc_dec_check_ctrl_val(struct s5p_mfc_ctx *ctx, struct v4l2_control *ctrl)
+{
+       struct v4l2_queryctrl *c;
+
+       c = mfc_dec_get_ctrl(ctrl->id);
+       if (!c) {
+               mfc_err_ctx("[CTRLS] not supported control id (%#x)\n", ctrl->id);
+               return -EINVAL;
+       }
+
+       if (ctrl->value < c->minimum || ctrl->value > c->maximum
+               || (c->step != 0 && ctrl->value % c->step != 0)) {
+               mfc_err_ctx("[CTRLS] Invalid control value (%#x)\n", ctrl->value);
+               return -ERANGE;
+       }
+
+       return 0;
+}
+
+/* Query capabilities of the device */
+static int vidioc_querycap(struct file *file, void *priv,
+                          struct v4l2_capability *cap)
+{
+       strncpy(cap->driver, "MFC", sizeof(cap->driver) - 1);
+       strncpy(cap->card, "decoder", sizeof(cap->card) - 1);
+       cap->bus_info[0] = 0;
+       cap->version = KERNEL_VERSION(1, 0, 0);
+       cap->device_caps = V4L2_CAP_VIDEO_CAPTURE
+                       | V4L2_CAP_VIDEO_OUTPUT
+                       | V4L2_CAP_VIDEO_CAPTURE_MPLANE
+                       | V4L2_CAP_VIDEO_OUTPUT_MPLANE
+                       | V4L2_CAP_STREAMING
+                       | V4L2_CAP_DEVICE_CAPS;
+
+       cap->capabilities = cap->device_caps;
+
+       return 0;
+}
+
+static int mfc_dec_enum_fmt(struct s5p_mfc_dev *dev, struct v4l2_fmtdesc *f,
+               unsigned int type)
+{
+       struct s5p_mfc_fmt *fmt;
+       unsigned long i, j = 0;
+
+       for (i = 0; i < NUM_FORMATS; ++i) {
+               if (!(dec_formats[i].type & type))
+                       continue;
+               if (!dev->pdata->support_10bit && (dec_formats[i].type & MFC_FMT_10BIT))
+                       continue;
+               if (!dev->pdata->support_422 && (dec_formats[i].type & MFC_FMT_422))
+                       continue;
+
+               if (j == f->index) {
+                       fmt = &dec_formats[i];
+                       strlcpy(f->description, fmt->name,
+                               sizeof(f->description));
+                       f->pixelformat = fmt->fourcc;
+
+                       return 0;
+               }
+
+               ++j;
+       }
+
+       return -EINVAL;
+}
+
+static int vidioc_enum_fmt_vid_cap_mplane(struct file *file, void *pirv,
+               struct v4l2_fmtdesc *f)
+{
+       struct s5p_mfc_dev *dev = video_drvdata(file);
+
+       return mfc_dec_enum_fmt(dev, f, MFC_FMT_FRAME);
+}
+
+static int vidioc_enum_fmt_vid_out_mplane(struct file *file, void *prov,
+               struct v4l2_fmtdesc *f)
+{
+       struct s5p_mfc_dev *dev = video_drvdata(file);
+
+       return mfc_dec_enum_fmt(dev, f, MFC_FMT_STREAM);
+}
+
+static void mfc_dec_change_format(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       u32 org_fmt = ctx->dst_fmt->fourcc;
+
+       if (ctx->is_10bit && ctx->is_422) {
+               switch (org_fmt) {
+               case V4L2_PIX_FMT_NV16M_S10B:
+               case V4L2_PIX_FMT_NV61M_S10B:
+               case V4L2_PIX_FMT_NV16M_P210:
+               case V4L2_PIX_FMT_NV61M_P210:
+                       /* It is right format */
+                       break;
+               case V4L2_PIX_FMT_NV12M:
+               case V4L2_PIX_FMT_NV16M:
+               case V4L2_PIX_FMT_NV12M_S10B:
+               case V4L2_PIX_FMT_NV12M_P010:
+                       ctx->dst_fmt = mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV16M_S10B);
+                       break;
+               case V4L2_PIX_FMT_NV21M:
+               case V4L2_PIX_FMT_NV61M:
+               case V4L2_PIX_FMT_NV21M_S10B:
+               case V4L2_PIX_FMT_NV21M_P010:
+                       ctx->dst_fmt = mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV61M_S10B);
+                       break;
+               default:
+                       ctx->dst_fmt = mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV16M_S10B);
+                       break;
+               }
+               ctx->raw_buf.num_planes = 2;
+       } else if (ctx->is_10bit && !ctx->is_422) {
+               if (ctx->dst_fmt->mem_planes == 1) {
+                       /* YUV420 only supports the single plane */
+                       ctx->dst_fmt = mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV12N_10B);
+               } else {
+                       switch (org_fmt) {
+                       case V4L2_PIX_FMT_NV12M_S10B:
+                       case V4L2_PIX_FMT_NV21M_S10B:
+                       case V4L2_PIX_FMT_NV12M_P010:
+                       case V4L2_PIX_FMT_NV21M_P010:
+                               /* It is right format */
+                               break;
+                       case V4L2_PIX_FMT_NV12M:
+                       case V4L2_PIX_FMT_NV16M:
+                       case V4L2_PIX_FMT_NV16M_S10B:
+                       case V4L2_PIX_FMT_NV16M_P210:
+                               if (dev->pdata->P010_decoding)
+                                       ctx->dst_fmt = mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV12M_P010);
+                               else
+                                       ctx->dst_fmt = mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV12M_S10B);
+                               break;
+                       case V4L2_PIX_FMT_NV21M:
+                       case V4L2_PIX_FMT_NV61M:
+                       case V4L2_PIX_FMT_NV61M_S10B:
+                       case V4L2_PIX_FMT_NV61M_P210:
+                               ctx->dst_fmt = mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV21M_S10B);
+                               break;
+                       default:
+                               if (dev->pdata->P010_decoding)
+                                       ctx->dst_fmt = mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV12M_P010);
+                               else
+                                       ctx->dst_fmt = mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV12M_S10B);
+                               break;
+                       }
+               }
+               ctx->raw_buf.num_planes = 2;
+       } else if (!ctx->is_10bit && ctx->is_422) {
+               switch (org_fmt) {
+               case V4L2_PIX_FMT_NV16M:
+               case V4L2_PIX_FMT_NV61M:
+                       /* It is right format */
+                       break;
+               case V4L2_PIX_FMT_NV12M:
+               case V4L2_PIX_FMT_NV12M_S10B:
+               case V4L2_PIX_FMT_NV16M_S10B:
+               case V4L2_PIX_FMT_NV12M_P010:
+               case V4L2_PIX_FMT_NV16M_P210:
+                       ctx->dst_fmt = mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV16M);
+                       break;
+               case V4L2_PIX_FMT_NV21M:
+               case V4L2_PIX_FMT_NV21M_S10B:
+               case V4L2_PIX_FMT_NV61M_S10B:
+               case V4L2_PIX_FMT_NV21M_P010:
+               case V4L2_PIX_FMT_NV61M_P210:
+                       ctx->dst_fmt = mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV61M);
+                       break;
+               default:
+                       ctx->dst_fmt = mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV16M);
+                       break;
+               }
+               ctx->raw_buf.num_planes = 2;
+       } else {
+               /* YUV420 8bit */
+               switch (org_fmt) {
+               case V4L2_PIX_FMT_NV16M:
+               case V4L2_PIX_FMT_NV12M_S10B:
+               case V4L2_PIX_FMT_NV16M_S10B:
+               case V4L2_PIX_FMT_NV12M_P010:
+               case V4L2_PIX_FMT_NV16M_P210:
+                       ctx->dst_fmt = mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV12M);
+                       break;
+               case V4L2_PIX_FMT_NV61M:
+               case V4L2_PIX_FMT_NV21M_S10B:
+               case V4L2_PIX_FMT_NV61M_S10B:
+               case V4L2_PIX_FMT_NV21M_P010:
+               case V4L2_PIX_FMT_NV61M_P210:
+                       ctx->dst_fmt = mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV21M);
+                       break;
+               default:
+                       /* It is right format */
+                       break;
+               }
+       }
+
+       if (org_fmt != ctx->dst_fmt->fourcc)
+               mfc_info_ctx("[FRAME] format is changed to %s\n", ctx->dst_fmt->name);
+}
+
+/* Get format */
+static int vidioc_g_fmt_vid_cap_mplane(struct file *file, void *priv,
+                                               struct v4l2_format *f)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+       struct s5p_mfc_dec *dec;
+       struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
+       struct s5p_mfc_raw_info *raw;
+       int i;
+
+       mfc_debug_enter();
+
+       dec = ctx->dec_priv;
+       if (!dec) {
+               mfc_err_dev("no mfc decoder to run\n");
+               return -EINVAL;
+       }
+
+       mfc_debug(2, "dec dst g_fmt, state: %d\n", ctx->state);
+
+       if (ctx->state == MFCINST_GOT_INST ||
+           ctx->state == MFCINST_RES_CHANGE_FLUSH ||
+           ctx->state == MFCINST_RES_CHANGE_END) {
+               /* If the MFC is parsing the header,
+                * so wait until it is finished */
+               if (s5p_mfc_wait_for_done_ctx(ctx,
+                               S5P_FIMV_R2H_CMD_SEQ_DONE_RET)) {
+                               mfc_err_dev("header parsing failed\n");
+                               return -EAGAIN;
+               }
+       }
+
+       if (ctx->state >= MFCINST_HEAD_PARSED &&
+           ctx->state < MFCINST_ABORT) {
+               /* This is run on CAPTURE (deocde output) */
+
+               /* only NV16(61) format is supported for 422 format */
+               /* only 2 plane is supported for 10bit */
+               mfc_dec_change_format(ctx);
+
+               raw = &ctx->raw_buf;
+               /* Width and height are set to the dimensions
+                  of the movie, the buffer is bigger and
+                  further processing stages should crop to this
+                  rectangle. */
+               s5p_mfc_dec_calc_dpb_size(ctx);
+
+               if (IS_LOW_MEM) {
+                       unsigned int dpb_size;
+                       /*
+                        * If total memory requirement is too big for this device,
+                        * then it returns error.
+                        * DPB size : Total plane size * the number of DPBs
+                        * 5: the number of extra DPBs
+                        * 3: the number of DPBs for Android framework
+                        * 600MB: being used to return an error,
+                        * when 8K resolution video clip is being tried to be decoded
+                        */
+                       dpb_size = (ctx->raw_buf.total_plane_size * (ctx->dpb_count + 5 + 3));
+                       if (dpb_size > SZ_600M) {
+                               mfc_info_ctx("required memory size is too big (%dx%d, dpb: %d)\n",
+                                               ctx->img_width, ctx->img_height, ctx->dpb_count);
+                               return -EINVAL;
+                       }
+               }
+
+               pix_fmt_mp->width = ctx->img_width;
+               pix_fmt_mp->height = ctx->img_height;
+               pix_fmt_mp->num_planes = ctx->dst_fmt->mem_planes;
+
+               if (dec->is_interlaced)
+                       pix_fmt_mp->field = V4L2_FIELD_INTERLACED;
+               else
+                       pix_fmt_mp->field = V4L2_FIELD_NONE;
+
+               /* Set pixelformat to the format in which MFC
+                  outputs the decoded frame */
+               pix_fmt_mp->pixelformat = ctx->dst_fmt->fourcc;
+               for (i = 0; i < ctx->dst_fmt->mem_planes; i++) {
+                       pix_fmt_mp->plane_fmt[i].bytesperline = raw->stride[i];
+                       if (ctx->dst_fmt->mem_planes == 1) {
+                               pix_fmt_mp->plane_fmt[i].sizeimage = raw->total_plane_size;
+                       } else {
+                               if (ctx->is_10bit)
+                                       pix_fmt_mp->plane_fmt[i].sizeimage = raw->plane_size[i]
+                                               + raw->plane_size_2bits[i];
+                               else
+                                       pix_fmt_mp->plane_fmt[i].sizeimage = raw->plane_size[i];
+                       }
+               }
+       }
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+static int vidioc_g_fmt_vid_out_mplane(struct file *file, void *priv,
+                                               struct v4l2_format *f)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+       struct s5p_mfc_dec *dec;
+       struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
+
+       mfc_debug_enter();
+
+       dec = ctx->dec_priv;
+       if (!dec) {
+               mfc_err_dev("no mfc decoder to run\n");
+               return -EINVAL;
+       }
+
+       mfc_debug(4, "dec src g_fmt, state: %d\n", ctx->state);
+
+       /* This is run on OUTPUT
+          The buffer contains compressed image
+          so width and height have no meaning */
+       pix_fmt_mp->width = 0;
+       pix_fmt_mp->height = 0;
+       pix_fmt_mp->field = V4L2_FIELD_NONE;
+       pix_fmt_mp->plane_fmt[0].bytesperline = dec->src_buf_size;
+       pix_fmt_mp->plane_fmt[0].sizeimage = dec->src_buf_size;
+       pix_fmt_mp->pixelformat = ctx->src_fmt->fourcc;
+       pix_fmt_mp->num_planes = ctx->src_fmt->mem_planes;
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+/* Try format */
+static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+       struct s5p_mfc_fmt *fmt;
+       struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
+
+       fmt = mfc_dec_find_format(ctx, pix_fmt_mp->pixelformat);
+       if (!fmt) {
+               mfc_err_dev("Unsupported format for %s\n",
+                               V4L2_TYPE_IS_OUTPUT(f->type) ? "source" : "destination");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/* Set format */
+static int vidioc_s_fmt_vid_cap_mplane(struct file *file, void *priv,
+                                                       struct v4l2_format *f)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+       struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
+
+       mfc_debug_enter();
+
+       if (ctx->vq_dst.streaming) {
+               mfc_err_ctx("queue busy\n");
+               return -EBUSY;
+       }
+
+       ctx->dst_fmt = mfc_dec_find_format(ctx, pix_fmt_mp->pixelformat);
+       if (!ctx->dst_fmt) {
+               mfc_err_ctx("Unsupported format for destination\n");
+               return -EINVAL;
+       }
+       ctx->raw_buf.num_planes = ctx->dst_fmt->num_planes;
+       mfc_info_ctx("[FRAME] dec dst pixelformat : %s\n", ctx->dst_fmt->name);
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+static int mfc_force_close_inst(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx)
+{
+       if (ctx->inst_no == MFC_NO_INSTANCE_SET)
+               return 0;
+
+       s5p_mfc_change_state(ctx, MFCINST_RETURN_INST);
+       s5p_mfc_set_bit(ctx->num, &dev->work_bits);
+       s5p_mfc_clean_ctx_int_flags(ctx);
+       if (s5p_mfc_just_run(dev, ctx->num)) {
+               mfc_err_ctx("Failed to run MFC\n");
+               s5p_mfc_release_hwlock_ctx(ctx);
+               s5p_mfc_cleanup_work_bit_and_try_run(ctx);
+               return -EIO;
+       }
+
+       /* Wait until instance is returned or timeout occured */
+       if (s5p_mfc_wait_for_done_ctx(ctx,
+                               S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET)) {
+               mfc_err_ctx("Waiting for CLOSE_INSTANCE timed out\n");
+               s5p_mfc_release_hwlock_ctx(ctx);
+               s5p_mfc_cleanup_work_bit_and_try_run(ctx);
+               return -EIO;
+       }
+
+       /* Free resources */
+       s5p_mfc_release_instance_context(ctx);
+       s5p_mfc_change_state(ctx, MFCINST_INIT);
+
+       return 0;
+}
+
+static int vidioc_s_fmt_vid_out_mplane(struct file *file, void *priv,
+                                                       struct v4l2_format *f)
+{
+       struct s5p_mfc_dev *dev = video_drvdata(file);
+       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+       struct s5p_mfc_dec *dec = ctx->dec_priv;
+       struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
+       int ret = 0;
+
+       mfc_debug_enter();
+
+       if (ctx->vq_src.streaming) {
+               mfc_err_ctx("queue busy\n");
+               return -EBUSY;
+       }
+
+       ctx->src_fmt = mfc_dec_find_format(ctx, pix_fmt_mp->pixelformat);
+       if (!ctx->src_fmt) {
+               mfc_err_ctx("Unsupported format for source\n");
+               return -EINVAL;
+       }
+
+       ctx->codec_mode = ctx->src_fmt->codec_mode;
+       mfc_info_ctx("[STREAM] Dec src codec(%d): %s\n",
+                       ctx->codec_mode, ctx->src_fmt->name);
+
+       ctx->pix_format = pix_fmt_mp->pixelformat;
+       if ((pix_fmt_mp->width > 0) && (pix_fmt_mp->height > 0)) {
+               ctx->img_height = pix_fmt_mp->height;
+               ctx->img_width = pix_fmt_mp->width;
+       }
+
+       /* As this buffer will contain compressed data, the size is set
+        * to the maximum size. */
+       if (pix_fmt_mp->plane_fmt[0].sizeimage)
+               dec->src_buf_size = pix_fmt_mp->plane_fmt[0].sizeimage;
+       else
+               dec->src_buf_size = MAX_FRAME_SIZE;
+       mfc_debug(2, "[STREAM] sizeimage: %d\n", pix_fmt_mp->plane_fmt[0].sizeimage);
+       pix_fmt_mp->plane_fmt[0].bytesperline = 0;
+
+       MFC_TRACE_CTX_HWLOCK("**DEC s_fmt\n");
+       ret = s5p_mfc_get_hwlock_ctx(ctx);
+       if (ret < 0) {
+               mfc_err_ctx("Failed to get hwlock\n");
+               return -EBUSY;
+       }
+
+       /* In case of calling s_fmt twice or more */
+       ret = mfc_force_close_inst(dev, ctx);
+       if (ret) {
+               mfc_err_ctx("Failed to close already opening instance\n");
+               return -EIO;
+       }
+
+       ret = s5p_mfc_alloc_instance_context(ctx);
+       if (ret) {
+               mfc_err_ctx("Failed to allocate dec instance[%d] buffers\n",
+                               ctx->num);
+               s5p_mfc_release_hwlock_ctx(ctx);
+               return -ENOMEM;
+       }
+
+       s5p_mfc_set_bit(ctx->num, &dev->work_bits);
+       ret = s5p_mfc_just_run(dev, ctx->num);
+       if (ret) {
+               mfc_err_ctx("Failed to run MFC\n");
+               s5p_mfc_release_hwlock_ctx(ctx);
+               s5p_mfc_cleanup_work_bit_and_try_run(ctx);
+               s5p_mfc_release_instance_context(ctx);
+               return -EIO;
+       }
+
+       if (s5p_mfc_wait_for_done_ctx(ctx,
+                       S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET)) {
+               s5p_mfc_release_hwlock_ctx(ctx);
+               s5p_mfc_cleanup_work_bit_and_try_run(ctx);
+               s5p_mfc_release_instance_context(ctx);
+               return -EIO;
+       }
+
+       s5p_mfc_release_hwlock_ctx(ctx);
+
+       mfc_debug(2, "Got instance number: %d\n", ctx->inst_no);
+
+       if (s5p_mfc_dec_ctx_ready(ctx))
+               s5p_mfc_set_bit(ctx->num, &dev->work_bits);
+       if (s5p_mfc_is_work_to_do(dev))
+               queue_work(dev->butler_wq, &dev->butler_work);
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+/* Reqeust 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_mfc_ctx(file->private_data);
+       struct s5p_mfc_dec *dec;
+       int ret = 0;
+
+       mfc_debug_enter();
+
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return -EINVAL;
+       }
+
+       dec = ctx->dec_priv;
+       if (!dec) {
+               mfc_err_dev("no mfc decoder to run\n");
+               return -EINVAL;
+       }
+
+       if (reqbufs->memory == V4L2_MEMORY_MMAP) {
+               mfc_err_ctx("Not supported memory type (%d)\n", reqbufs->memory);
+               return -EINVAL;
+       }
+
+       if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               mfc_debug(4, "dec src reqbuf(%d)\n", reqbufs->count);
+               /* Can only request buffers after
+                  an instance has been opened.*/
+               if (ctx->state == MFCINST_GOT_INST) {
+                       if (reqbufs->count == 0) {
+                               ret = vb2_reqbufs(&ctx->vq_src, reqbufs);
+                               ctx->output_state = QUEUE_FREE;
+                               return ret;
+                       }
+
+                       /* Decoding */
+                       if (ctx->output_state != QUEUE_FREE) {
+                               mfc_err_ctx("Bufs have already been requested\n");
+                               return -EINVAL;
+                       }
+
+                       ret = vb2_reqbufs(&ctx->vq_src, reqbufs);
+                       if (ret) {
+                               mfc_err_ctx("vb2_reqbufs on src failed\n");
+                               return ret;
+                       }
+
+                       ctx->output_state = QUEUE_BUFS_REQUESTED;
+               }
+       } else if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               mfc_debug(4, "dec dst reqbuf(%d)\n", reqbufs->count);
+               if (reqbufs->count == 0) {
+                       ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
+
+                       if (dev->has_mmcache && dev->mmcache.is_on_status)
+                               s5p_mfc_invalidate_mmcache(dev);
+
+                       s5p_mfc_release_codec_buffers(ctx);
+                       ctx->capture_state = QUEUE_FREE;
+                       return ret;
+               }
+
+               dec->dst_memtype = reqbufs->memory;
+
+               if (ctx->capture_state != QUEUE_FREE) {
+                       mfc_err_ctx("Bufs have already been requested\n");
+                       return -EINVAL;
+               }
+
+               ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
+               if (ret) {
+                       mfc_err_ctx("vb2_reqbufs on capture failed\n");
+                       return ret;
+               }
+
+               if (reqbufs->count < ctx->dpb_count) {
+                       mfc_err_ctx("Not enough buffers allocated\n");
+                       reqbufs->count = 0;
+                       vb2_reqbufs(&ctx->vq_dst, reqbufs);
+                       return -ENOMEM;
+               }
+
+               dec->total_dpb_count = reqbufs->count;
+
+               ret = s5p_mfc_alloc_codec_buffers(ctx);
+               if (ret) {
+                       mfc_err_ctx("Failed to allocate decoding buffers\n");
+                       reqbufs->count = 0;
+                       vb2_reqbufs(&ctx->vq_dst, reqbufs);
+                       return -ENOMEM;
+               }
+
+               ctx->capture_state = QUEUE_BUFS_REQUESTED;
+
+               if (s5p_mfc_dec_ctx_ready(ctx))
+                       s5p_mfc_set_bit(ctx->num, &dev->work_bits);
+
+               s5p_mfc_try_run(dev);
+       }
+
+       mfc_debug_leave();
+
+       return ret;
+}
+
+/* Query buffer */
+static int vidioc_querybuf(struct file *file, void *priv,
+                                                  struct v4l2_buffer *buf)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+       int ret;
+
+       mfc_debug_enter();
+
+       if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               mfc_debug(4, "dec dst querybuf, state: %d\n", ctx->state);
+               ret = vb2_querybuf(&ctx->vq_dst, buf);
+               if (ret != 0) {
+                       mfc_err_dev("dec dst: error in vb2_querybuf()\n");
+                       return ret;
+               }
+       } else if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               mfc_debug(4, "dec src querybuf, state: %d\n", ctx->state);
+               ret = vb2_querybuf(&ctx->vq_src, buf);
+               if (ret != 0) {
+                       mfc_err_dev("dec src: error in vb2_querybuf()\n");
+                       return ret;
+               }
+       } else {
+               mfc_err_dev("invalid buf type (%d)\n", buf->type);
+               return -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_mfc_ctx(file->private_data);
+       int ret = -EINVAL;
+
+       mfc_debug_enter();
+
+       if (ctx->state == MFCINST_ERROR) {
+               mfc_err_ctx("Call on QBUF after unrecoverable error\n");
+               return -EIO;
+       }
+
+       if (V4L2_TYPE_IS_MULTIPLANAR(buf->type) && !buf->length) {
+               mfc_err_ctx("multiplanar but length is zero\n");
+               return -EIO;
+       }
+
+       if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               mfc_debug(4, "dec src buf[%d] Q\n", buf->index);
+               if (buf->m.planes[0].bytesused > buf->m.planes[0].length) {
+                       mfc_err_ctx("data size (%d) must be less than "
+                                       "buffer size(%d)\n",
+                                       buf->m.planes[0].bytesused,
+                                       buf->m.planes[0].length);
+                       return -EIO;
+               }
+
+               s5p_mfc_qos_update_framerate(ctx);
+
+               if (!buf->m.planes[0].bytesused) {
+                       buf->m.planes[0].bytesused = buf->m.planes[0].length;
+                       mfc_debug(2, "Src size zero, changed to buf size %d\n",
+                                       buf->m.planes[0].bytesused);
+               } else {
+                       mfc_debug(2, "Src size = %d\n", buf->m.planes[0].bytesused);
+               }
+               ret = vb2_qbuf(&ctx->vq_src, buf);
+       } else {
+               mfc_debug(4, "dec dst buf[%d] Q\n", buf->index);
+               ret = vb2_qbuf(&ctx->vq_dst, buf);
+       }
+
+       mfc_debug_leave();
+       return ret;
+}
+
+/* Dequeue a buffer */
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+       struct s5p_mfc_dec *dec = ctx->dec_priv;
+       struct dec_dpb_ref_info *dstBuf, *srcBuf;
+       int ret;
+       int ncount = 0;
+
+       mfc_debug_enter();
+
+       if (ctx->state == MFCINST_ERROR) {
+               mfc_err_ctx("Call on DQBUF after unrecoverable error\n");
+               return -EIO;
+       }
+       if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               mfc_debug(4, "dec src buf[%d] DQ\n", buf->index);
+               ret = vb2_dqbuf(&ctx->vq_src, buf, file->f_flags & O_NONBLOCK);
+       } else {
+               mfc_debug(4, "dec dst buf[%d] DQ\n", buf->index);
+               ret = vb2_dqbuf(&ctx->vq_dst, buf, file->f_flags & O_NONBLOCK);
+
+               if (buf->index >= MFC_MAX_DPBS) {
+                       mfc_err_ctx("buffer index[%d] range over\n", buf->index);
+                       return -EINVAL;
+               }
+
+               /* Memcpy from dec->ref_info to shared memory */
+               srcBuf = &dec->ref_info[buf->index];
+               for (ncount = 0; ncount < MFC_MAX_DPBS; ncount++) {
+                       if (srcBuf->dpb[ncount].fd[0] == MFC_INFO_INIT_FD)
+                               break;
+                       mfc_debug(2, "[DPB] DQ index[%d] Released FD = %d\n",
+                                       buf->index, srcBuf->dpb[ncount].fd[0]);
+               }
+
+               if (dec->sh_handle.vaddr != NULL) {
+                       dstBuf = (struct dec_dpb_ref_info *)
+                                       dec->sh_handle.vaddr + buf->index;
+                       memcpy(dstBuf, srcBuf, sizeof(struct dec_dpb_ref_info));
+                       dstBuf->index = buf->index;
+               }
+       }
+       mfc_debug_leave();
+       return ret;
+}
+
+/* Stream on */
+static int vidioc_streamon(struct file *file, void *priv,
+                          enum v4l2_buf_type type)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+       int ret = -EINVAL;
+
+       mfc_debug_enter();
+
+       if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               mfc_debug(4, "dec src streamon\n");
+               ret = vb2_streamon(&ctx->vq_src, type);
+       } else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               mfc_debug(4, "dec dst streamon\n");
+               ret = vb2_streamon(&ctx->vq_dst, type);
+
+               if (!ret)
+                       s5p_mfc_qos_on(ctx);
+       } else {
+               mfc_err_ctx("unknown v4l2 buffer type\n");
+       }
+
+       mfc_debug(2, "src: %d, dst: %d,  state = %d, dpb_count = %d\n",
+                 s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->src_buf_queue),
+                 s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->dst_buf_queue),
+                 ctx->state, ctx->dpb_count);
+
+       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_mfc_ctx(file->private_data);
+       int ret = -EINVAL;
+
+       mfc_debug_enter();
+
+       if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               mfc_debug(4, "dec src streamoff\n");
+               s5p_mfc_qos_reset_last_framerate(ctx);
+
+               ret = vb2_streamoff(&ctx->vq_src, type);
+       } else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               mfc_debug(4, "dec dst streamoff\n");
+               ret = vb2_streamoff(&ctx->vq_dst, type);
+               if (!ret)
+                       s5p_mfc_qos_off(ctx);
+       } else {
+               mfc_err_ctx("unknown v4l2 buffer type\n");
+       }
+
+       mfc_debug_leave();
+
+       return ret;
+}
+
+/* Query a ctrl */
+static int vidioc_queryctrl(struct file *file, void *priv,
+                           struct v4l2_queryctrl *qc)
+{
+       struct v4l2_queryctrl *c;
+
+       c = mfc_dec_get_ctrl(qc->id);
+       if (!c) {
+               mfc_err_dev("[CTRLS] not supported control id (%#x)\n", qc->id);
+               return -EINVAL;
+       }
+
+       *qc = *c;
+       return 0;
+}
+
+static int mfc_dec_ext_info(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       int val = 0;
+
+       val |= DEC_SET_DYNAMIC_DPB;
+       if (MFC_FEATURE_SUPPORT(dev, dev->pdata->skype))
+               val |= DEC_SET_SKYPE_FLAG;
+
+       mfc_debug(5, "[CTRLS] ext info val: %#x\n", val);
+
+       return val;
+}
+
+/* Get ctrl */
+static int mfc_dec_get_ctrl_val(struct s5p_mfc_ctx *ctx, struct v4l2_control *ctrl)
+{
+       struct s5p_mfc_dev *dev;
+       struct s5p_mfc_dec *dec;
+       struct s5p_mfc_ctx_ctrl *ctx_ctrl;
+       int found = 0;
+
+       if (!ctx) {
+               mfc_err_dev("no mfc context to run\n");
+               return -EINVAL;
+       }
+       dev = ctx->dev;
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return -EINVAL;
+       }
+       dec = ctx->dec_priv;
+       if (!dec) {
+               mfc_err_dev("no mfc decoder to run\n");
+               return -EINVAL;
+       }
+
+       switch (ctrl->id) {
+       case V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER:
+               ctrl->value = dec->loop_filter_mpeg4;
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY:
+               ctrl->value = dec->display_delay;
+               break;
+       case V4L2_CID_CACHEABLE:
+               mfc_debug(5, "it is supported only V4L2_MEMORY_MMAP\n");
+               break;
+       case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:
+               if (ctx->state >= MFCINST_HEAD_PARSED &&
+                   ctx->state < MFCINST_ABORT) {
+                       ctrl->value = ctx->dpb_count;
+                       break;
+               } else if (ctx->state != MFCINST_INIT) {
+                       mfc_err_ctx("Decoding not initialised\n");
+                       return -EINVAL;
+               }
+
+               /* Should wait for the header to be parsed */
+               if (s5p_mfc_wait_for_done_ctx(ctx,
+                               S5P_FIMV_R2H_CMD_SEQ_DONE_RET)) {
+                       s5p_mfc_cleanup_work_bit_and_try_run(ctx);
+                       return -EIO;
+               }
+
+               if (ctx->state >= MFCINST_HEAD_PARSED &&
+                   ctx->state < MFCINST_ABORT) {
+                       ctrl->value = ctx->dpb_count;
+               } else {
+                       mfc_err_ctx("Decoding not initialised\n");
+                       return -EINVAL;
+               }
+               break;
+       case V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE:
+               ctrl->value = dec->slice_enable;
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_PACKED_PB:
+               /* Not used */
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_CRC_ENABLE:
+               ctrl->value = dec->crc_enable;
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_CHECK_STATE:
+               if (ctx->is_dpb_realloc && ctx->state == MFCINST_HEAD_PARSED)
+                       ctrl->value = MFCSTATE_DEC_S3D_REALLOC;
+               else if (ctx->state == MFCINST_RES_CHANGE_FLUSH
+                               || ctx->state == MFCINST_RES_CHANGE_END
+                               || ctx->state == MFCINST_HEAD_PARSED)
+                       ctrl->value = MFCSTATE_DEC_RES_DETECT;
+               else if (ctx->state == MFCINST_FINISHING)
+                       ctrl->value = MFCSTATE_DEC_TERMINATING;
+               else
+                       ctrl->value = MFCSTATE_PROCESSING;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING:
+               ctrl->value = dec->sei_parse;
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_I_FRAME_DECODING:
+               ctrl->value = dec->idr_decoding;
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_RATE:
+               ctrl->value = s5p_mfc_qos_get_framerate(ctx);
+               break;
+       case V4L2_CID_MPEG_MFC_GET_VERSION_INFO:
+               ctrl->value = dev->pdata->ip_ver;
+               break;
+       case V4L2_CID_MPEG_VIDEO_QOS_RATIO:
+               ctrl->value = ctx->qos_ratio;
+               break;
+       case V4L2_CID_MPEG_MFC_SET_DYNAMIC_DPB_MODE:
+               ctrl->value = dec->is_dynamic_dpb;
+               break;
+       case V4L2_CID_MPEG_MFC_GET_EXT_INFO:
+               ctrl->value = mfc_dec_ext_info(ctx);
+               break;
+       case V4L2_CID_MPEG_MFC_GET_10BIT_INFO:
+               ctrl->value = ctx->is_10bit;
+               break;
+       case V4L2_CID_MPEG_MFC_GET_DRIVER_INFO:
+               ctrl->value = MFC_DRIVER_INFO;
+               break;
+       default:
+               list_for_each_entry(ctx_ctrl, &ctx->ctrls, list) {
+                       if (!(ctx_ctrl->type & MFC_CTRL_TYPE_GET))
+                               continue;
+
+                       if (ctx_ctrl->id == ctrl->id) {
+                               if (ctx_ctrl->has_new) {
+                                       ctx_ctrl->has_new = 0;
+                                       ctrl->value = ctx_ctrl->val;
+                               } else {
+                                       mfc_debug(5, "[CTRLS] Control value "\
+                                                       "is not up to date: "\
+                                                       "0x%08x\n", ctrl->id);
+                                       return -EINVAL;
+                               }
+
+                               found = 1;
+                               break;
+                       }
+               }
+
+               if (!found) {
+                       mfc_err_ctx("Invalid control: 0x%08x\n", ctrl->id);
+                       return -EINVAL;
+               }
+               break;
+       }
+
+       mfc_debug(5, "[CTRLS] get id: %#x, value: %d\n", ctrl->id, ctrl->value);
+
+       return 0;
+}
+
+/* Get a ctrl */
+static int vidioc_g_ctrl(struct file *file, void *priv,
+                       struct v4l2_control *ctrl)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+       int ret = 0;
+
+       mfc_debug_enter();
+       ret = mfc_dec_get_ctrl_val(ctx, ctrl);
+       mfc_debug_leave();
+
+       return ret;
+}
+
+/* Set a ctrl */
+static int vidioc_s_ctrl(struct file *file, void *priv,
+                        struct v4l2_control *ctrl)
+{
+       struct s5p_mfc_dev *dev = video_drvdata(file);
+       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+       struct s5p_mfc_dec *dec;
+       struct s5p_mfc_ctx_ctrl *ctx_ctrl;
+       int ret = 0;
+       int found = 0;
+
+       mfc_debug_enter();
+
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return -EINVAL;
+       }
+
+       dec = ctx->dec_priv;
+       if (!dec) {
+               mfc_err_dev("no mfc decoder to run\n");
+               return -EINVAL;
+       }
+
+       ret = mfc_dec_check_ctrl_val(ctx, ctrl);
+       if (ret)
+               return ret;
+
+       mfc_debug(5, "[CTRLS] set id: %#x, value: %d\n", ctrl->id, ctrl->value);
+
+       switch (ctrl->id) {
+       case V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER:
+               dec->loop_filter_mpeg4 = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY:
+               dec->display_delay = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE:
+               dec->slice_enable = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_PACKED_PB:
+               /* Not used */
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_CRC_ENABLE:
+               dec->crc_enable = ctrl->value;
+               break;
+       case V4L2_CID_CACHEABLE:
+               mfc_debug(5, "it is supported only V4L2_MEMORY_MMAP\n");
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING:
+               dec->sei_parse = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_I_FRAME_DECODING:
+               dec->idr_decoding = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_DECODER_IMMEDIATE_DISPLAY:
+               dec->immediate_display = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_DECODER_DECODING_TIMESTAMP_MODE:
+               dec->is_dts_mode = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_DECODER_WAIT_DECODING_START:
+               ctx->wait_state = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC_SET_DUAL_DPB_MODE:
+               mfc_err_dev("[DPB] not supported CID: 0x%x\n",ctrl->id);
+               break;
+       case V4L2_CID_MPEG_VIDEO_QOS_RATIO:
+               ctx->qos_ratio = ctrl->value;
+               mfc_info_ctx("[QoS] set %d qos_ratio\n", ctrl->value);
+               break;
+       case V4L2_CID_MPEG_MFC_SET_DYNAMIC_DPB_MODE:
+               dec->is_dynamic_dpb = ctrl->value;
+               if (dec->is_dynamic_dpb == 0)
+                       mfc_err_dev("[DPB] is_dynamic_dpb is 0. it has to be enabled\n");
+               break;
+       case V4L2_CID_MPEG_MFC_SET_USER_SHARED_HANDLE:
+               if (dec->sh_handle.fd == -1) {
+                       dec->sh_handle.fd = ctrl->value;
+                       if (s5p_mfc_mem_get_user_shared_handle(ctx, &dec->sh_handle))
+                               return -EINVAL;
+                       else
+                               mfc_debug(2, "[MEMINFO][DPB] shared handle fd: %d, vaddr: 0x%p\n",
+                                               dec->sh_handle.fd, dec->sh_handle.vaddr);
+               }
+               break;
+       case V4L2_CID_MPEG_MFC_SET_BUF_PROCESS_TYPE:
+               ctx->buf_process_type = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_BLACK_BAR_DETECT:
+               dec->detect_black_bar = ctrl->value;
+               break;
+       default:
+               list_for_each_entry(ctx_ctrl, &ctx->ctrls, list) {
+                       if (!(ctx_ctrl->type & MFC_CTRL_TYPE_SET))
+                               continue;
+
+                       if (ctx_ctrl->id == ctrl->id) {
+                               ctx_ctrl->has_new = 1;
+                               ctx_ctrl->val = ctrl->value;
+
+                               found = 1;
+                               break;
+                       }
+               }
+
+               if (!found) {
+                       mfc_err_ctx("Invalid control: 0x%08x\n", ctrl->id);
+                       return -EINVAL;
+               }
+               break;
+       }
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+/* Get cropping information */
+static int vidioc_g_crop(struct file *file, void *priv,
+               struct v4l2_crop *cr)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+       struct s5p_mfc_dec *dec = ctx->dec_priv;
+
+       mfc_debug_enter();
+
+       if (!ready_to_get_crop(ctx)) {
+               mfc_debug(2, "ready to get crop failed\n");
+               return -EINVAL;
+       }
+
+       if (ctx->state == MFCINST_RUNNING && dec->detect_black_bar
+                       && dec->black_bar_updated) {
+               cr->c.left = dec->black_bar.left;
+               cr->c.top = dec->black_bar.top;
+               cr->c.width = dec->black_bar.width;
+               cr->c.height = dec->black_bar.height;
+               mfc_debug(2, "[FRAME][BLACKBAR] Cropping info: l=%d t=%d w=%d h=%d\n",
+                               dec->black_bar.left,
+                               dec->black_bar.top,
+                               dec->black_bar.width,
+                               dec->black_bar.height);
+       } else {
+               if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_H264 ||
+                       ctx->src_fmt->fourcc == V4L2_PIX_FMT_HEVC ||
+                       ctx->src_fmt->fourcc == V4L2_PIX_FMT_BPG) {
+                       cr->c.left = dec->cr_left;
+                       cr->c.top = dec->cr_top;
+                       cr->c.width = ctx->img_width - dec->cr_left - dec->cr_right;
+                       cr->c.height = ctx->img_height - dec->cr_top - dec->cr_bot;
+                       mfc_debug(2, "[FRAME] Cropping info: l=%d t=%d " \
+                                       "w=%d h=%d (r=%d b=%d fw=%d fh=%d)\n",
+                                       dec->cr_left, dec->cr_top,
+                                       cr->c.width, cr->c.height,
+                                       dec->cr_right, dec->cr_bot,
+                                       ctx->img_width, ctx->img_height);
+               } else {
+                       cr->c.left = 0;
+                       cr->c.top = 0;
+                       cr->c.width = ctx->img_width;
+                       cr->c.height = ctx->img_height;
+                       mfc_debug(2, "[FRAME] Cropping info: w=%d h=%d fw=%d fh=%d\n",
+                                       cr->c.width, cr->c.height,
+                                       ctx->img_width, ctx->img_height);
+               }
+       }
+
+       mfc_debug_leave();
+       return 0;
+}
+
+static int vidioc_g_ext_ctrls(struct file *file, void *priv,
+                       struct v4l2_ext_controls *f)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+       struct v4l2_ext_control *ext_ctrl;
+       struct v4l2_control ctrl;
+       int i;
+       int ret = 0;
+
+       if (f->which != V4L2_CTRL_CLASS_MPEG)
+               return -EINVAL;
+
+       for (i = 0; i < f->count; i++) {
+               ext_ctrl = (f->controls + i);
+
+               ctrl.id = ext_ctrl->id;
+
+               ret = mfc_dec_get_ctrl_val(ctx, &ctrl);
+               if (ret == 0) {
+                       ext_ctrl->value = ctrl.value;
+               } else {
+                       f->error_idx = i;
+                       break;
+               }
+
+               mfc_debug(5, "[CTRLS][%d] id: %#x, value: %d\n",
+                               i, ext_ctrl->id, ext_ctrl->value);
+       }
+
+       return ret;
+}
+
+/* v4l2_ioctl_ops */
+static const struct v4l2_ioctl_ops s5p_mfc_dec_ioctl_ops = {
+       .vidioc_querycap                = vidioc_querycap,
+       .vidioc_enum_fmt_vid_cap_mplane = vidioc_enum_fmt_vid_cap_mplane,
+       .vidioc_enum_fmt_vid_out_mplane = vidioc_enum_fmt_vid_out_mplane,
+       .vidioc_g_fmt_vid_cap_mplane    = vidioc_g_fmt_vid_cap_mplane,
+       .vidioc_g_fmt_vid_out_mplane    = vidioc_g_fmt_vid_out_mplane,
+       .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_vid_cap_mplane,
+       .vidioc_s_fmt_vid_out_mplane    = vidioc_s_fmt_vid_out_mplane,
+       .vidioc_reqbufs                 = vidioc_reqbufs,
+       .vidioc_querybuf                = vidioc_querybuf,
+       .vidioc_qbuf                    = vidioc_qbuf,
+       .vidioc_dqbuf                   = vidioc_dqbuf,
+       .vidioc_streamon                = vidioc_streamon,
+       .vidioc_streamoff               = vidioc_streamoff,
+       .vidioc_queryctrl               = vidioc_queryctrl,
+       .vidioc_g_ctrl                  = vidioc_g_ctrl,
+       .vidioc_s_ctrl                  = vidioc_s_ctrl,
+       .vidioc_g_crop                  = vidioc_g_crop,
+       .vidioc_g_ext_ctrls             = vidioc_g_ext_ctrls,
+};
+
+const struct v4l2_ioctl_ops *s5p_mfc_get_dec_v4l2_ioctl_ops(void)
+{
+       return &s5p_mfc_dec_ioctl_ops;
+}
diff --git a/drivers/media/platform/exynos/mfc/mfc_dec.h b/drivers/media/platform/exynos/mfc/mfc_dec.h
new file mode 100644 (file)
index 0000000..c5871ac
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_dec.h
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __MFC_DEC_H
+#define __MFC_DEC_H __FILE__
+
+#include "mfc_common.h"
+
+const struct v4l2_ioctl_ops *s5p_mfc_get_dec_v4l2_ioctl_ops(void);
+
+#endif /* __MFC_DEC_H */
diff --git a/drivers/media/platform/exynos/mfc/mfc_dec_internal.h b/drivers/media/platform/exynos/mfc/mfc_dec_internal.h
new file mode 100644 (file)
index 0000000..81c8eed
--- /dev/null
@@ -0,0 +1,542 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_dec_internal.h
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __MFC_DEC_INTERNAL_H
+#define __MFC_DEC_INTERNAL_H __FILE__
+
+#include "mfc_common.h"
+
+struct s5p_mfc_fmt dec_formats[] = {
+       {
+               .name = "4:2:0 3 Planes Y/Cb/Cr",
+               .fourcc = V4L2_PIX_FMT_YUV420M,
+               .codec_mode = MFC_FORMATS_NO_CODEC,
+               .type = MFC_FMT_FRAME,
+               .num_planes = 3,
+               .mem_planes = 3,
+       },
+       {
+               .name = "4:2:0 3 Planes Y/Cb/Cr single",
+               .fourcc = V4L2_PIX_FMT_YUV420N,
+               .codec_mode = MFC_FORMATS_NO_CODEC,
+               .type = MFC_FMT_FRAME,
+               .num_planes = 3,
+               .mem_planes = 1,
+       },
+       {
+               .name = "4:2:0 3 Planes Y/Cr/Cb",
+               .fourcc = V4L2_PIX_FMT_YVU420M,
+               .codec_mode = MFC_FORMATS_NO_CODEC,
+               .type = MFC_FMT_FRAME,
+               .num_planes = 3,
+               .mem_planes = 3,
+       },
+       {
+               .name = "4:2:0 2 Planes Y/CbCr",
+               .fourcc = V4L2_PIX_FMT_NV12M,
+               .codec_mode = MFC_FORMATS_NO_CODEC,
+               .type = MFC_FMT_FRAME,
+               .num_planes = 2,
+               .mem_planes = 2,
+       },
+       {
+               .name = "4:2:0 2 Planes Y/CbCr single",
+               .fourcc = V4L2_PIX_FMT_NV12N,
+               .codec_mode = MFC_FORMATS_NO_CODEC,
+               .type = MFC_FMT_FRAME,
+               .num_planes = 2,
+               .mem_planes = 1,
+       },
+       {
+               .name = "4:2:0 2 Planes Y/CbCr 8+2 10bit",
+               .fourcc = V4L2_PIX_FMT_NV12M_S10B,
+               .codec_mode = MFC_FORMATS_NO_CODEC,
+               .type = MFC_FMT_FRAME | MFC_FMT_10BIT,
+               .num_planes = 2,
+               .mem_planes = 2,
+       },
+       {
+               .name = "4:2:0 2 Planes Y/CbCr 10bit single",
+               .fourcc = V4L2_PIX_FMT_NV12N_10B,
+               .codec_mode = MFC_FORMATS_NO_CODEC,
+               .type = MFC_FMT_FRAME | MFC_FMT_10BIT,
+               .num_planes = 2,
+               .mem_planes = 1,
+       },
+       {
+               .name = "4:2:0 2 Planes Y/CbCr P010 10bit",
+               .fourcc = V4L2_PIX_FMT_NV12M_P010,
+               .codec_mode = MFC_FORMATS_NO_CODEC,
+               .type = MFC_FMT_FRAME | MFC_FMT_10BIT,
+               .num_planes = 2,
+               .mem_planes = 2,
+       },
+       {
+               .name = "4:2:0 2 Planes Y/CrCb",
+               .fourcc = V4L2_PIX_FMT_NV21M,
+               .codec_mode = MFC_FORMATS_NO_CODEC,
+               .type = MFC_FMT_FRAME,
+               .num_planes = 2,
+               .mem_planes = 2,
+       },
+       {
+               .name = "4:2:0 2 Planes Y/CrCb 8+2 10bit",
+               .fourcc = V4L2_PIX_FMT_NV21M_S10B,
+               .codec_mode = MFC_FORMATS_NO_CODEC,
+               .type = MFC_FMT_FRAME | MFC_FMT_10BIT,
+               .num_planes = 2,
+               .mem_planes = 2,
+       },
+       {
+               .name = "4:2:0 2 Planes Y/CrCb P010 10bit",
+               .fourcc = V4L2_PIX_FMT_NV21M_P010,
+               .codec_mode = MFC_FORMATS_NO_CODEC,
+               .type = MFC_FMT_FRAME | MFC_FMT_10BIT,
+               .num_planes = 2,
+               .mem_planes = 2,
+       },
+       {
+               .name = "4:2:2 2 Planes Y/CbCr",
+               .fourcc = V4L2_PIX_FMT_NV16M,
+               .codec_mode = MFC_FORMATS_NO_CODEC,
+               .type = MFC_FMT_FRAME | MFC_FMT_422,
+               .num_planes = 2,
+               .mem_planes = 2,
+       },
+       {
+               .name = "4:2:2 2 Planes Y/CbCr 8+2 10bit",
+               .fourcc = V4L2_PIX_FMT_NV16M_S10B,
+               .codec_mode = MFC_FORMATS_NO_CODEC,
+               .type = MFC_FMT_FRAME | MFC_FMT_10BIT | MFC_FMT_422,
+               .num_planes = 2,
+               .mem_planes = 2,
+       },
+       {
+               .name = "4:2:2 2 Planes Y/CbCr P210 10bit",
+               .fourcc = V4L2_PIX_FMT_NV16M_P210,
+               .codec_mode = MFC_FORMATS_NO_CODEC,
+               .type = MFC_FMT_FRAME | MFC_FMT_10BIT | MFC_FMT_422,
+               .num_planes = 2,
+               .mem_planes = 2,
+       },
+       {
+               .name = "4:2:2 2 Planes Y/CrCb",
+               .fourcc = V4L2_PIX_FMT_NV61M,
+               .codec_mode = MFC_FORMATS_NO_CODEC,
+               .type = MFC_FMT_FRAME | MFC_FMT_422,
+               .num_planes = 2,
+               .mem_planes = 2,
+       },
+       {
+               .name = "4:2:2 2 Planes Y/CrCb 8+2 10bit",
+               .fourcc = V4L2_PIX_FMT_NV61M_S10B,
+               .codec_mode = MFC_FORMATS_NO_CODEC,
+               .type = MFC_FMT_FRAME | MFC_FMT_10BIT | MFC_FMT_422,
+               .num_planes = 2,
+               .mem_planes = 2,
+       },
+       {
+               .name = "4:2:2 2 Planes Y/CrCb P210 10bit",
+               .fourcc = V4L2_PIX_FMT_NV61M_P210,
+               .codec_mode = MFC_FORMATS_NO_CODEC,
+               .type = MFC_FMT_FRAME | MFC_FMT_10BIT | MFC_FMT_422,
+               .num_planes = 2,
+               .mem_planes = 2,
+       },
+       {
+               .name = "H264 Encoded Stream",
+               .fourcc = V4L2_PIX_FMT_H264,
+               .codec_mode = S5P_FIMV_CODEC_H264_DEC,
+               .type = MFC_FMT_STREAM,
+               .num_planes = 1,
+               .mem_planes = 1,
+       },
+       {
+               .name = "H264/MVC Encoded Stream",
+               .fourcc = V4L2_PIX_FMT_H264_MVC,
+               .codec_mode = S5P_FIMV_CODEC_H264_MVC_DEC,
+               .type = MFC_FMT_STREAM,
+               .num_planes = 1,
+               .mem_planes = 1,
+       },
+       {
+               .name = "H263 Encoded Stream",
+               .fourcc = V4L2_PIX_FMT_H263,
+               .codec_mode = S5P_FIMV_CODEC_H263_DEC,
+               .type = MFC_FMT_STREAM,
+               .num_planes = 1,
+               .mem_planes = 1,
+       },
+       {
+               .name = "MPEG1 Encoded Stream",
+               .fourcc = V4L2_PIX_FMT_MPEG1,
+               .codec_mode = S5P_FIMV_CODEC_MPEG2_DEC,
+               .type = MFC_FMT_STREAM,
+               .num_planes = 1,
+               .mem_planes = 1,
+       },
+       {
+               .name = "MPEG2 Encoded Stream",
+               .fourcc = V4L2_PIX_FMT_MPEG2,
+               .codec_mode = S5P_FIMV_CODEC_MPEG2_DEC,
+               .type = MFC_FMT_STREAM,
+               .num_planes = 1,
+               .mem_planes = 1,
+       },
+       {
+               .name = "MPEG4 Encoded Stream",
+               .fourcc = V4L2_PIX_FMT_MPEG4,
+               .codec_mode = S5P_FIMV_CODEC_MPEG4_DEC,
+               .type = MFC_FMT_STREAM,
+               .num_planes = 1,
+               .mem_planes = 1,
+       },
+       {
+               .name = "FIMV Encoded Stream",
+               .fourcc = V4L2_PIX_FMT_FIMV,
+               .codec_mode = S5P_FIMV_CODEC_MPEG4_DEC,
+               .type = MFC_FMT_STREAM,
+               .num_planes = 1,
+               .mem_planes = 1,
+       },
+       {
+               .name = "FIMV1 Encoded Stream",
+               .fourcc = V4L2_PIX_FMT_FIMV1,
+               .codec_mode = S5P_FIMV_CODEC_FIMV1_DEC,
+               .type = MFC_FMT_STREAM,
+               .num_planes = 1,
+               .mem_planes = 1,
+       },
+       {
+               .name = "FIMV2 Encoded Stream",
+               .fourcc = V4L2_PIX_FMT_FIMV2,
+               .codec_mode = S5P_FIMV_CODEC_FIMV2_DEC,
+               .type = MFC_FMT_STREAM,
+               .num_planes = 1,
+               .mem_planes = 1,
+       },
+       {
+               .name = "FIMV3 Encoded Stream",
+               .fourcc = V4L2_PIX_FMT_FIMV3,
+               .codec_mode = S5P_FIMV_CODEC_FIMV3_DEC,
+               .type = MFC_FMT_STREAM,
+               .num_planes = 1,
+               .mem_planes = 1,
+       },
+       {
+               .name = "FIMV4 Encoded Stream",
+               .fourcc = V4L2_PIX_FMT_FIMV4,
+               .codec_mode = S5P_FIMV_CODEC_FIMV4_DEC,
+               .type = MFC_FMT_STREAM,
+               .num_planes = 1,
+               .mem_planes = 1,
+       },
+       {
+               .name = "XviD Encoded Stream",
+               .fourcc = V4L2_PIX_FMT_XVID,
+               .codec_mode = S5P_FIMV_CODEC_MPEG4_DEC,
+               .type = MFC_FMT_STREAM,
+               .num_planes = 1,
+               .mem_planes = 1,
+       },
+       {
+               .name = "VC1 Encoded Stream",
+               .fourcc = V4L2_PIX_FMT_VC1_ANNEX_G,
+               .codec_mode = S5P_FIMV_CODEC_VC1_DEC,
+               .type = MFC_FMT_STREAM,
+               .num_planes = 1,
+               .mem_planes = 1,
+       },
+       {
+               .name = "VC1 RCV Encoded Stream",
+               .fourcc = V4L2_PIX_FMT_VC1_ANNEX_L,
+               .codec_mode = S5P_FIMV_CODEC_VC1_RCV_DEC,
+               .type = MFC_FMT_STREAM,
+               .num_planes = 1,
+               .mem_planes = 1,
+       },
+       {
+               .name = "VP8 Encoded Stream",
+               .fourcc = V4L2_PIX_FMT_VP8,
+               .codec_mode = S5P_FIMV_CODEC_VP8_DEC,
+               .type = MFC_FMT_STREAM,
+               .num_planes = 1,
+               .mem_planes = 1,
+       },
+       {
+               .name = "VP9 Encoded Stream",
+               .fourcc = V4L2_PIX_FMT_VP9,
+               .codec_mode = S5P_FIMV_CODEC_VP9_DEC,
+               .type = MFC_FMT_STREAM,
+               .num_planes = 1,
+               .mem_planes = 1,
+       },
+       {
+               .name = "HEVC Encoded Stream",
+               .fourcc = V4L2_PIX_FMT_HEVC,
+               .codec_mode = S5P_FIMV_CODEC_HEVC_DEC,
+               .type = MFC_FMT_STREAM,
+               .num_planes = 1,
+               .mem_planes = 1,
+       },
+       {
+               .name = "BPG Encoded Stream",
+               .fourcc = V4L2_PIX_FMT_BPG,
+               .codec_mode = S5P_FIMV_CODEC_BPG_DEC,
+               .type = MFC_FMT_STREAM,
+               .num_planes = 1,
+               .mem_planes = 1,
+       },
+};
+
+#define NUM_FORMATS ARRAY_SIZE(dec_formats)
+
+static struct v4l2_queryctrl controls[] = {
+       {
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "H.264 Display Delay",
+               .minimum = -1,
+               .maximum = 32,
+               .step = 1,
+               .default_value = -1,
+       },
+       {
+               .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_MPEG_MFC51_VIDEO_PACKED_PB,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "Packed PB Enable",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Frame Tag",
+               .minimum = 0,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_CACHEABLE,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "Cacheable flag",
+               .minimum = 0,
+               .maximum = 3,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_CRC_ENABLE,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "CRC enable",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_LUMA,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "CRC data",
+               .minimum = 0,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_CHROMA,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "CRC data",
+               .minimum = 0,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_DISPLAY_STATUS,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Display status",
+               .minimum = 0,
+               .maximum = 3,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TYPE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Frame type",
+               .minimum = 0,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "Frame pack sei parse flag",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_I_FRAME_DECODING,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "I frame decoding mode",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_RATE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Frames per second in 1000x scale",
+               .minimum = 1,
+               .maximum = 480000,
+               .step = 1,
+               .default_value = 60000,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_DECODER_IMMEDIATE_DISPLAY,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "Immediate Display Enable",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_DECODER_DECODING_TIMESTAMP_MODE,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "Decoding Timestamp Mode Enable",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_DECODER_WAIT_DECODING_START,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "Wait until buffer setting done",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC_GET_VERSION_INFO,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Get MFC version information",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC_SET_DUAL_DPB_MODE,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "Set Dual DPB mode",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_QOS_RATIO,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "QoS ratio value",
+               .minimum = 20,
+               .maximum = 1000,
+               .step = 10,
+               .default_value = 100,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC_SET_DYNAMIC_DPB_MODE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Set dynamic DPB",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC_SET_USER_SHARED_HANDLE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Set dynamic DPB",
+               .minimum = 0,
+               .maximum = 65535,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC_GET_EXT_INFO,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Get extra information",
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC_SET_BUF_PROCESS_TYPE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Set buffer process type",
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC_GET_10BIT_INFO,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "10 bit contents information",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_BLACK_BAR_DETECT,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "Set black bar detection option",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+};
+
+#define NUM_CTRLS ARRAY_SIZE(controls)
+
+#endif /* __MFC_DEC_INTERNAL_H */
diff --git a/drivers/media/platform/exynos/mfc/mfc_dec_ops.c b/drivers/media/platform/exynos/mfc/mfc_dec_ops.c
new file mode 100644 (file)
index 0000000..1cbd273
--- /dev/null
@@ -0,0 +1,896 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_dec_ops.c
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include  "mfc_common.h"
+
+#include "mfc_reg.h"
+
+#define NUM_CTRL_CFGS ARRAY_SIZE(mfc_ctrl_list)
+
+struct s5p_mfc_ctrl_cfg mfc_ctrl_list[] = {
+       {
+               .type = MFC_CTRL_TYPE_SET,
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG,
+               .is_volatile = 1,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_D_PICTURE_TAG,
+               .mask = 0xFFFFFFFF,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_NONE,
+               .flag_addr = 0,
+               .flag_shft = 0,
+       },
+       {
+               .type = MFC_CTRL_TYPE_GET_DST,
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG,
+               .is_volatile = 0,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_D_RET_PICTURE_TAG_TOP,
+               .mask = 0xFFFFFFFF,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_NONE,
+               .flag_addr = 0,
+               .flag_shft = 0,
+       },
+       {
+               .type = MFC_CTRL_TYPE_GET_DST,
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_DISPLAY_STATUS,
+               .is_volatile = 0,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_D_DISPLAY_STATUS,
+               .mask = 0x7,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_NONE,
+               .flag_addr = 0,
+               .flag_shft = 0,
+       },
+       /* CRC related definitions are based on non-H.264 type */
+       {
+               .type = MFC_CTRL_TYPE_GET_DST,
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_LUMA,
+               .is_volatile = 0,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_D_DISPLAY_FIRST_PLANE_CRC,
+               .mask = 0xFFFFFFFF,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_NONE,
+               .flag_addr = 0,
+               .flag_shft = 0,
+       },
+       {
+               .type = MFC_CTRL_TYPE_GET_DST,
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_CHROMA,
+               .is_volatile = 0,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_D_DISPLAY_SECOND_PLANE_CRC,
+               .mask = 0xFFFFFFFF,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_NONE,
+               .flag_addr = 0,
+               .flag_shft = 0,
+       },
+       {
+               .type = MFC_CTRL_TYPE_GET_DST,
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_CHROMA1,
+               .is_volatile = 0,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_D_DISPLAY_THIRD_PLANE_CRC,
+               .mask = 0xFFFFFFFF,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_NONE,
+               .flag_addr = 0,
+               .flag_shft = 0,
+       },
+       {
+               .type = MFC_CTRL_TYPE_GET_DST,
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_2BIT_LUMA,
+               .is_volatile = 0,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_D_DISPLAY_FIRST_PLANE_2BIT_CRC,
+               .mask = 0xFFFFFFFF,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_NONE,
+               .flag_addr = 0,
+               .flag_shft = 0,
+       },
+       {
+               .type = MFC_CTRL_TYPE_GET_DST,
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_2BIT_CHROMA,
+               .is_volatile = 0,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_D_DISPLAY_SECOND_PLANE_2BIT_CRC,
+               .mask = 0xFFFFFFFF,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_NONE,
+               .flag_addr = 0,
+               .flag_shft = 0,
+       },
+       {
+               .type = MFC_CTRL_TYPE_GET_DST,
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_CRC_GENERATED,
+               .is_volatile = 0,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_D_DISPLAY_STATUS,
+               .mask = 0x1,
+               .shft = 6,
+               .flag_mode = MFC_CTRL_MODE_NONE,
+               .flag_addr = 0,
+               .flag_shft = 0,
+       },
+       {
+               .type = MFC_CTRL_TYPE_GET_DST,
+               .id = V4L2_CID_MPEG_VIDEO_H264_SEI_FP_AVAIL,
+               .is_volatile = 0,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_D_SEI_AVAIL,
+               .mask = 0x1,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_NONE,
+               .flag_addr = 0,
+               .flag_shft = 0,
+       },
+       {
+               .type = MFC_CTRL_TYPE_GET_DST,
+               .id = V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRGMENT_ID,
+               .is_volatile = 0,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_D_FRAME_PACK_ARRGMENT_ID,
+               .mask = 0xFFFFFFFF,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_NONE,
+               .flag_addr = 0,
+               .flag_shft = 0,
+       },
+       {
+               .type = MFC_CTRL_TYPE_GET_DST,
+               .id = V4L2_CID_MPEG_VIDEO_H264_SEI_FP_INFO,
+               .is_volatile = 0,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_D_FRAME_PACK_SEI_INFO,
+               .mask = 0x3FFFF,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_NONE,
+               .flag_addr = 0,
+               .flag_shft = 0,
+       },
+       {
+               .type = MFC_CTRL_TYPE_GET_DST,
+               .id = V4L2_CID_MPEG_VIDEO_H264_SEI_FP_GRID_POS,
+               .is_volatile = 0,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_D_FRAME_PACK_GRID_POS,
+               .mask = 0xFFFF,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_NONE,
+               .flag_addr = 0,
+               .flag_shft = 0,
+       },
+       {
+               .type = MFC_CTRL_TYPE_GET_DST,
+               .id = V4L2_CID_MPEG_VIDEO_H264_MVC_VIEW_ID,
+               .is_volatile = 0,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_D_MVC_VIEW_ID,
+               .mask = 0xFFFF,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_NONE,
+               .flag_addr = 0,
+               .flag_shft = 0,
+       },
+       {
+               .type = MFC_CTRL_TYPE_GET_DST,
+               .id = V4L2_CID_MPEG_VIDEO_SEI_MAX_PIC_AVERAGE_LIGHT,
+               .is_volatile = 0,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_D_CONTENT_LIGHT_LEVEL_INFO_SEI,
+               .mask = 0xFFFF,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_NONE,
+               .flag_addr = 0,
+               .flag_shft = 0,
+       },
+       {
+               .type = MFC_CTRL_TYPE_GET_DST,
+               .id = V4L2_CID_MPEG_VIDEO_SEI_MAX_CONTENT_LIGHT,
+               .is_volatile = 0,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_D_CONTENT_LIGHT_LEVEL_INFO_SEI,
+               .mask = 0xFFFF,
+               .shft = 16,
+               .flag_mode = MFC_CTRL_MODE_NONE,
+               .flag_addr = 0,
+               .flag_shft = 0,
+       },
+       {
+               .type = MFC_CTRL_TYPE_GET_DST,
+               .id = V4L2_CID_MPEG_VIDEO_SEI_MAX_DISPLAY_LUMINANCE,
+               .is_volatile = 0,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_0,
+               .mask = 0xFFFFFFFF,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_NONE,
+               .flag_addr = 0,
+               .flag_shft = 0,
+       },
+       {
+               .type = MFC_CTRL_TYPE_GET_DST,
+               .id = V4L2_CID_MPEG_VIDEO_SEI_MIN_DISPLAY_LUMINANCE,
+               .is_volatile = 0,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_1,
+               .mask = 0xFFFFFFFF,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_NONE,
+               .flag_addr = 0,
+               .flag_shft = 0,
+       },
+       {
+               .type = MFC_CTRL_TYPE_GET_DST,
+               .id = V4L2_CID_MPEG_VIDEO_MATRIX_COEFFICIENTS,
+               .is_volatile = 0,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_D_VIDEO_SIGNAL_TYPE,
+               .mask = 0xFF,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_NONE,
+               .flag_addr = 0,
+               .flag_shft = 0,
+       },
+       {
+               .type = MFC_CTRL_TYPE_GET_DST,
+               .id = V4L2_CID_MPEG_VIDEO_FORMAT,
+               .is_volatile = 0,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_D_VIDEO_SIGNAL_TYPE,
+               .mask = 0x7,
+               .shft = 26,
+               .flag_mode = MFC_CTRL_MODE_NONE,
+               .flag_addr = 0,
+               .flag_shft = 0,
+       },
+       {
+               .type = MFC_CTRL_TYPE_GET_DST,
+               .id = V4L2_CID_MPEG_VIDEO_FULL_RANGE_FLAG,
+               .is_volatile = 0,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_D_VIDEO_SIGNAL_TYPE,
+               .mask = 0x1,
+               .shft = 25,
+               .flag_mode = MFC_CTRL_MODE_NONE,
+               .flag_addr = 0,
+               .flag_shft = 0,
+       },
+       {
+               .type = MFC_CTRL_TYPE_GET_DST,
+               .id = V4L2_CID_MPEG_VIDEO_COLOUR_PRIMARIES,
+               .is_volatile = 0,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_D_VIDEO_SIGNAL_TYPE,
+               .mask = 0xFF,
+               .shft = 16,
+               .flag_mode = MFC_CTRL_MODE_NONE,
+               .flag_addr = 0,
+               .flag_shft = 0,
+       },
+       {
+               .type = MFC_CTRL_TYPE_GET_DST,
+               .id = V4L2_CID_MPEG_VIDEO_TRANSFER_CHARACTERISTICS,
+               .is_volatile = 0,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_D_VIDEO_SIGNAL_TYPE,
+               .mask = 0xFF,
+               .shft = 8,
+               .flag_mode = MFC_CTRL_MODE_NONE,
+               .flag_addr = 0,
+               .flag_shft = 0,
+       },
+       {
+               .type = MFC_CTRL_TYPE_GET_DST,
+               .id = V4L2_CID_MPEG_VIDEO_SEI_WHITE_POINT,
+               .is_volatile = 0,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_2,
+               .mask = 0xFFFFFFFF,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_NONE,
+               .flag_addr = 0,
+               .flag_shft = 0,
+       },
+       {
+               .type = MFC_CTRL_TYPE_GET_DST,
+               .id = V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_0,
+               .is_volatile = 0,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_3,
+               .mask = 0xFFFFFFFF,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_NONE,
+               .flag_addr = 0,
+               .flag_shft = 0,
+       },
+       {
+               .type = MFC_CTRL_TYPE_GET_DST,
+               .id = V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_1,
+               .is_volatile = 0,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_4,
+               .mask = 0xFFFFFFFF,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_NONE,
+               .flag_addr = 0,
+               .flag_shft = 0,
+       },
+       {
+               .type = MFC_CTRL_TYPE_GET_DST,
+               .id = V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_2,
+               .is_volatile = 0,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_5,
+               .mask = 0xFFFFFFFF,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_NONE,
+               .flag_addr = 0,
+               .flag_shft = 0,
+       },
+};
+
+static int s5p_mfc_dec_cleanup_ctx_ctrls(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_ctx_ctrl *ctx_ctrl;
+
+       while (!list_empty(&ctx->ctrls)) {
+               ctx_ctrl = list_entry((&ctx->ctrls)->next,
+                                     struct s5p_mfc_ctx_ctrl, list);
+               list_del(&ctx_ctrl->list);
+               kfree(ctx_ctrl);
+       }
+
+       INIT_LIST_HEAD(&ctx->ctrls);
+
+       return 0;
+}
+
+static int s5p_mfc_dec_init_ctx_ctrls(struct s5p_mfc_ctx *ctx)
+{
+       unsigned long i;
+       struct s5p_mfc_ctx_ctrl *ctx_ctrl;
+
+       INIT_LIST_HEAD(&ctx->ctrls);
+
+       for (i = 0; i < NUM_CTRL_CFGS; i++) {
+               ctx_ctrl = kzalloc(sizeof(struct s5p_mfc_ctx_ctrl), GFP_KERNEL);
+               if (ctx_ctrl == NULL) {
+                       mfc_err_dev("Failed to allocate context control "\
+                                       "id: 0x%08x, type: %d\n",
+                                       mfc_ctrl_list[i].id,
+                                       mfc_ctrl_list[i].type);
+
+                       s5p_mfc_dec_cleanup_ctx_ctrls(ctx);
+
+                       return -ENOMEM;
+               }
+
+               ctx_ctrl->type = mfc_ctrl_list[i].type;
+               ctx_ctrl->id = mfc_ctrl_list[i].id;
+               ctx_ctrl->addr = mfc_ctrl_list[i].addr;
+               ctx_ctrl->has_new = 0;
+               ctx_ctrl->val = 0;
+
+               list_add_tail(&ctx_ctrl->list, &ctx->ctrls);
+       }
+
+       return 0;
+}
+
+static void mfc_dec_remove_buf_ctrls(struct list_head *head)
+{
+       struct s5p_mfc_buf_ctrl *buf_ctrl;
+
+       while (!list_empty(head)) {
+               buf_ctrl = list_entry(head->next,
+                               struct s5p_mfc_buf_ctrl, list);
+               list_del(&buf_ctrl->list);
+               kfree(buf_ctrl);
+       }
+
+       INIT_LIST_HEAD(head);
+}
+
+static void s5p_mfc_dec_reset_buf_ctrls(struct list_head *head)
+{
+       struct s5p_mfc_buf_ctrl *buf_ctrl;
+
+       list_for_each_entry(buf_ctrl, head, list) {
+               buf_ctrl->has_new = 0;
+               buf_ctrl->val = 0;
+               buf_ctrl->old_val = 0;
+               buf_ctrl->updated = 0;
+       }
+}
+
+static int s5p_mfc_dec_init_buf_ctrls(struct s5p_mfc_ctx *ctx,
+       enum s5p_mfc_ctrl_type type, unsigned int index)
+{
+       unsigned long i;
+       struct s5p_mfc_ctx_ctrl *ctx_ctrl;
+       struct s5p_mfc_buf_ctrl *buf_ctrl;
+       struct list_head *head;
+
+       if (index >= MFC_MAX_BUFFERS) {
+               mfc_err_dev("Per-buffer control index is out of range\n");
+               return -EINVAL;
+       }
+
+       if (type & MFC_CTRL_TYPE_SRC) {
+               if (test_bit(index, &ctx->src_ctrls_avail)) {
+                       s5p_mfc_dec_reset_buf_ctrls(&ctx->src_ctrls[index]);
+
+                       return 0;
+               }
+
+               head = &ctx->src_ctrls[index];
+       } else if (type & MFC_CTRL_TYPE_DST) {
+               if (test_bit(index, &ctx->dst_ctrls_avail)) {
+                       s5p_mfc_dec_reset_buf_ctrls(&ctx->dst_ctrls[index]);
+
+                       return 0;
+               }
+
+               head = &ctx->dst_ctrls[index];
+       } else {
+               mfc_err_dev("Control type mismatch. type : %d\n", type);
+               return -EINVAL;
+       }
+
+       INIT_LIST_HEAD(head);
+
+       list_for_each_entry(ctx_ctrl, &ctx->ctrls, list) {
+               if (!(type & ctx_ctrl->type))
+                       continue;
+
+               /* find matched control configuration index */
+               for (i = 0; i < NUM_CTRL_CFGS; i++) {
+                       if (ctx_ctrl->id == mfc_ctrl_list[i].id)
+                               break;
+               }
+
+               if (i == NUM_CTRL_CFGS) {
+                       mfc_err_dev("Failed to find buffer control "\
+                                       "id: 0x%08x, type: %d\n",
+                                       ctx_ctrl->id, ctx_ctrl->type);
+                       continue;
+               }
+
+               buf_ctrl = kzalloc(sizeof(struct s5p_mfc_buf_ctrl), GFP_KERNEL);
+               if (buf_ctrl == NULL) {
+                       mfc_err_dev("Failed to allocate buffer control "\
+                                       "id: 0x%08x, type: %d\n",
+                                       mfc_ctrl_list[i].id,
+                                       mfc_ctrl_list[i].type);
+
+                       mfc_dec_remove_buf_ctrls(head);
+
+                       return -ENOMEM;
+               }
+
+               buf_ctrl->id = ctx_ctrl->id;
+               buf_ctrl->type = ctx_ctrl->type;
+               buf_ctrl->addr = ctx_ctrl->addr;
+
+               buf_ctrl->is_volatile = mfc_ctrl_list[i].is_volatile;
+               buf_ctrl->mode = mfc_ctrl_list[i].mode;
+               buf_ctrl->mask = mfc_ctrl_list[i].mask;
+               buf_ctrl->shft = mfc_ctrl_list[i].shft;
+               buf_ctrl->flag_mode = mfc_ctrl_list[i].flag_mode;
+               buf_ctrl->flag_addr = mfc_ctrl_list[i].flag_addr;
+               buf_ctrl->flag_shft = mfc_ctrl_list[i].flag_shft;
+
+               list_add_tail(&buf_ctrl->list, head);
+       }
+
+       s5p_mfc_dec_reset_buf_ctrls(head);
+
+       if (type & MFC_CTRL_TYPE_SRC)
+               set_bit(index, &ctx->src_ctrls_avail);
+       else
+               set_bit(index, &ctx->dst_ctrls_avail);
+
+       return 0;
+}
+
+static int s5p_mfc_dec_cleanup_buf_ctrls(struct s5p_mfc_ctx *ctx,
+       enum s5p_mfc_ctrl_type type, unsigned int index)
+{
+       struct list_head *head;
+
+       if (index >= MFC_MAX_BUFFERS) {
+               mfc_err_dev("Per-buffer control index is out of range\n");
+               return -EINVAL;
+       }
+
+       if (type & MFC_CTRL_TYPE_SRC) {
+               if (!(test_and_clear_bit(index, &ctx->src_ctrls_avail))) {
+                       return 0;
+               }
+
+               head = &ctx->src_ctrls[index];
+       } else if (type & MFC_CTRL_TYPE_DST) {
+               if (!(test_and_clear_bit(index, &ctx->dst_ctrls_avail))) {
+                       return 0;
+               }
+
+               head = &ctx->dst_ctrls[index];
+       } else {
+               mfc_err_dev("Control type mismatch. type : %d\n", type);
+               return -EINVAL;
+       }
+
+       mfc_dec_remove_buf_ctrls(head);
+
+       return 0;
+}
+
+static int s5p_mfc_dec_to_buf_ctrls(struct s5p_mfc_ctx *ctx, struct list_head *head)
+{
+       struct s5p_mfc_ctx_ctrl *ctx_ctrl;
+       struct s5p_mfc_buf_ctrl *buf_ctrl;
+
+       list_for_each_entry(ctx_ctrl, &ctx->ctrls, list) {
+               if (!(ctx_ctrl->type & MFC_CTRL_TYPE_SET) || !ctx_ctrl->has_new)
+                       continue;
+
+               list_for_each_entry(buf_ctrl, head, list) {
+                       if (!(buf_ctrl->type & MFC_CTRL_TYPE_SET))
+                               continue;
+
+                       if (buf_ctrl->id == ctx_ctrl->id) {
+                               buf_ctrl->has_new = 1;
+                               buf_ctrl->val = ctx_ctrl->val;
+                               if (buf_ctrl->is_volatile)
+                                       buf_ctrl->updated = 0;
+
+                               ctx_ctrl->has_new = 0;
+                               break;
+                       }
+               }
+       }
+
+       return 0;
+}
+
+static int s5p_mfc_dec_to_ctx_ctrls(struct s5p_mfc_ctx *ctx, struct list_head *head)
+{
+       struct s5p_mfc_ctx_ctrl *ctx_ctrl;
+       struct s5p_mfc_buf_ctrl *buf_ctrl;
+
+       list_for_each_entry(buf_ctrl, head, list) {
+               if (!(buf_ctrl->type & MFC_CTRL_TYPE_GET) || !buf_ctrl->has_new)
+                       continue;
+
+               list_for_each_entry(ctx_ctrl, &ctx->ctrls, list) {
+                       if (!(ctx_ctrl->type & MFC_CTRL_TYPE_GET))
+                               continue;
+
+                       if (ctx_ctrl->id == buf_ctrl->id) {
+                               ctx_ctrl->has_new = 1;
+                               ctx_ctrl->val = buf_ctrl->val;
+
+                               buf_ctrl->has_new = 0;
+                       }
+               }
+       }
+
+       return 0;
+}
+
+static int s5p_mfc_dec_set_buf_ctrls_val(struct s5p_mfc_ctx *ctx, struct list_head *head)
+{
+       struct s5p_mfc_buf_ctrl *buf_ctrl;
+       struct s5p_mfc_dec *dec = ctx->dec_priv;
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned int value = 0;
+
+       list_for_each_entry(buf_ctrl, head, list) {
+               if (!(buf_ctrl->type & MFC_CTRL_TYPE_SET) || !buf_ctrl->has_new)
+                       continue;
+
+               /* read old vlaue */
+               value = MFC_READL(buf_ctrl->addr);
+
+               /* save old vlaue for recovery */
+               if (buf_ctrl->is_volatile)
+                       buf_ctrl->old_val = (value >> buf_ctrl->shft) & buf_ctrl->mask;
+
+               /* write new value */
+               value &= ~(buf_ctrl->mask << buf_ctrl->shft);
+               value |= ((buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft);
+               MFC_WRITEL(value, buf_ctrl->addr);
+
+               /* set change flag bit */
+               if (buf_ctrl->flag_mode == MFC_CTRL_MODE_SFR) {
+                       value = MFC_READL(buf_ctrl->flag_addr);
+                       value |= (1 << buf_ctrl->flag_shft);
+                       MFC_WRITEL(value, buf_ctrl->flag_addr);
+               }
+
+               buf_ctrl->has_new = 0;
+               buf_ctrl->updated = 1;
+
+               if (buf_ctrl->id == V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG)
+                       dec->stored_tag = buf_ctrl->val;
+
+               mfc_debug(6, "[CTRLS] Set buffer control id: 0x%08x, val: %d\n",
+                               buf_ctrl->id, buf_ctrl->val);
+       }
+
+       return 0;
+}
+
+static int s5p_mfc_dec_get_buf_ctrls_val(struct s5p_mfc_ctx *ctx, struct list_head *head)
+{
+       struct s5p_mfc_buf_ctrl *buf_ctrl;
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_dec *dec = ctx->dec_priv;
+       unsigned int value = 0;
+
+       list_for_each_entry(buf_ctrl, head, list) {
+               if (!(buf_ctrl->type & MFC_CTRL_TYPE_GET))
+                       continue;
+
+               value = MFC_READL(buf_ctrl->addr);
+               value = (value >> buf_ctrl->shft) & buf_ctrl->mask;
+
+               buf_ctrl->val = value;
+               buf_ctrl->has_new = 1;
+
+               if (IS_VP9_DEC(ctx)) {
+                       if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_FULL_RANGE_FLAG)
+                               buf_ctrl->val = dec->color_range;
+                       else if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_COLOUR_PRIMARIES)
+                               buf_ctrl->val = dec->color_space;
+               }
+
+               mfc_debug(6, "[CTRLS] Get buffer control id: 0x%08x, val: %d\n",
+                               buf_ctrl->id, buf_ctrl->val);
+       }
+
+       return 0;
+}
+
+static int s5p_mfc_dec_set_buf_ctrls_val_nal_q_dec(struct s5p_mfc_ctx *ctx,
+                       struct list_head *head, DecoderInputStr *pInStr)
+{
+       struct s5p_mfc_buf_ctrl *buf_ctrl;
+       struct s5p_mfc_dec *dec = ctx->dec_priv;
+
+       mfc_debug_enter();
+
+       list_for_each_entry(buf_ctrl, head, list) {
+               if (!(buf_ctrl->type & MFC_CTRL_TYPE_SET) || !buf_ctrl->has_new)
+                       continue;
+               switch (buf_ctrl->id) {
+               case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG:
+                       pInStr->PictureTag &= ~(buf_ctrl->mask << buf_ctrl->shft);
+                       pInStr->PictureTag |=
+                               (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
+                       dec->stored_tag = buf_ctrl->val;
+                       break;
+               /* If new dynamic controls are added, insert here */
+               default:
+                       mfc_info_ctx("[NALQ] can't find control, id: 0x%x\n",
+                                       buf_ctrl->id);
+               }
+               buf_ctrl->has_new = 0;
+               buf_ctrl->updated = 1;
+
+               mfc_debug(6, "[NALQ][CTRLS] Set buffer control id: 0x%08x, val: %d\n",
+                               buf_ctrl->id, buf_ctrl->val);
+       }
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+static int s5p_mfc_dec_get_buf_ctrls_val_nal_q_dec(struct s5p_mfc_ctx *ctx,
+                       struct list_head *head, DecoderOutputStr *pOutStr)
+{
+       struct s5p_mfc_dec *dec = ctx->dec_priv;
+       struct s5p_mfc_buf_ctrl *buf_ctrl;
+       unsigned int value = 0;
+
+       mfc_debug_enter();
+
+       list_for_each_entry(buf_ctrl, head, list) {
+               if (!(buf_ctrl->type & MFC_CTRL_TYPE_GET))
+                       continue;
+               switch (buf_ctrl->id) {
+               case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG:
+                       value = pOutStr->PictureTagTop;
+                       break;
+               case V4L2_CID_MPEG_MFC51_VIDEO_DISPLAY_STATUS:
+                       value = pOutStr->DisplayStatus;
+                       break;
+               case V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_LUMA:
+                       value = pOutStr->DisplayFirstCrc;
+                       break;
+               case V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_CHROMA:
+                       value = pOutStr->DisplaySecondCrc;
+                       break;
+               case V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_CHROMA1:
+                       value = pOutStr->DisplayThirdCrc;
+                       break;
+               case V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_2BIT_LUMA:
+                       value = pOutStr->DisplayFirst2BitCrc;
+                       break;
+               case V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_2BIT_CHROMA:
+                       value = pOutStr->DisplaySecond2BitCrc;
+                       break;
+               case V4L2_CID_MPEG_MFC51_VIDEO_CRC_GENERATED:
+                       value = pOutStr->DisplayStatus;
+                       break;
+               case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_AVAIL:
+                       value = pOutStr->SeiAvail;
+                       break;
+               case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRGMENT_ID:
+                       value = pOutStr->FramePackArrgmentId;
+                       break;
+               case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_INFO:
+                       value = pOutStr->FramePackSeiInfo;
+                       break;
+               case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_GRID_POS:
+                       value = pOutStr->FramePackGridPos;
+                       break;
+               case V4L2_CID_MPEG_VIDEO_H264_MVC_VIEW_ID:
+                       value = 0;
+                       break;
+               /* TO-DO: SEI information has to be added in NAL-Q */
+               case V4L2_CID_MPEG_VIDEO_SEI_MAX_PIC_AVERAGE_LIGHT:
+               case V4L2_CID_MPEG_VIDEO_SEI_MAX_CONTENT_LIGHT:
+                       value = pOutStr->ContentLightLevelInfoSei;
+                       break;
+               case V4L2_CID_MPEG_VIDEO_SEI_MAX_DISPLAY_LUMINANCE:
+                       value = pOutStr->MasteringDisplayColourVolumeSei0;
+                       break;
+               case V4L2_CID_MPEG_VIDEO_SEI_MIN_DISPLAY_LUMINANCE:
+                       value = pOutStr->MasteringDisplayColourVolumeSei1;
+                       break;
+               case V4L2_CID_MPEG_VIDEO_FULL_RANGE_FLAG:
+               case V4L2_CID_MPEG_VIDEO_COLOUR_PRIMARIES:
+               case V4L2_CID_MPEG_VIDEO_FORMAT:
+               case V4L2_CID_MPEG_VIDEO_TRANSFER_CHARACTERISTICS:
+               case V4L2_CID_MPEG_VIDEO_MATRIX_COEFFICIENTS:
+                       value = pOutStr->VideoSignalType;
+                       break;
+               case V4L2_CID_MPEG_VIDEO_SEI_WHITE_POINT:
+                       value = pOutStr->MasteringDisplayColourVolumeSei2;
+                       break;
+               case V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_0:
+                       value = pOutStr->MasteringDisplayColourVolumeSei3;
+                       break;
+               case V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_1:
+                       value = pOutStr->MasteringDisplayColourVolumeSei4;
+                       break;
+               case V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_2:
+                       value = pOutStr->MasteringDisplayColourVolumeSei5;
+                       break;
+                       /* If new dynamic controls are added, insert here */
+               default:
+                       mfc_info_ctx("[NALQ] can't find control, id: 0x%x\n",
+                                       buf_ctrl->id);
+               }
+               value = (value >> buf_ctrl->shft) & buf_ctrl->mask;
+
+               buf_ctrl->val = value;
+               buf_ctrl->has_new = 1;
+
+               if (IS_VP9_DEC(ctx)) {
+                       if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_FULL_RANGE_FLAG)
+                               buf_ctrl->val = dec->color_range;
+                       else if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_COLOUR_PRIMARIES)
+                               buf_ctrl->val = dec->color_space;
+               }
+
+               mfc_debug(6, "[NALQ][CTRLS] Get buffer control id: 0x%08x, val: %d\n",
+                               buf_ctrl->id, buf_ctrl->val);
+       }
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+static int s5p_mfc_dec_recover_buf_ctrls_val(struct s5p_mfc_ctx *ctx, struct list_head *head)
+{
+       struct s5p_mfc_buf_ctrl *buf_ctrl;
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned int value = 0;
+
+       list_for_each_entry(buf_ctrl, head, list) {
+               if (!(buf_ctrl->type & MFC_CTRL_TYPE_SET)
+                       || !buf_ctrl->is_volatile
+                       || !buf_ctrl->updated)
+                       continue;
+
+               value = MFC_READL(buf_ctrl->addr);
+               value &= ~(buf_ctrl->mask << buf_ctrl->shft);
+               value |= ((buf_ctrl->old_val & buf_ctrl->mask) << buf_ctrl->shft);
+               MFC_WRITEL(value, buf_ctrl->addr);
+
+               /* clear change flag bit */
+               if (buf_ctrl->flag_mode == MFC_CTRL_MODE_SFR) {
+                       value = MFC_READL(buf_ctrl->flag_addr);
+                       value &= ~(1 << buf_ctrl->flag_shft);
+                       MFC_WRITEL(value, buf_ctrl->flag_addr);
+               }
+
+               buf_ctrl->updated = 0;
+               mfc_debug(6, "[CTRLS] Recover buffer control id: 0x%08x, old val: %d\n",
+                               buf_ctrl->id, buf_ctrl->old_val);
+       }
+
+       return 0;
+}
+
+static int s5p_mfc_dec_get_buf_update_val(struct s5p_mfc_ctx *ctx,
+                       struct list_head *head, unsigned int id, int value)
+{
+       struct s5p_mfc_buf_ctrl *buf_ctrl;
+
+       list_for_each_entry(buf_ctrl, head, list) {
+               if (buf_ctrl->id == id) {
+                       buf_ctrl->val = value;
+                       mfc_debug(6, "[CTRLS] Update buffer control id: 0x%08x, val: %d\n",
+                                       buf_ctrl->id, buf_ctrl->val);
+                       break;
+               }
+       }
+
+       return 0;
+}
+
+static int s5p_mfc_dec_recover_buf_ctrls_nal_q(struct s5p_mfc_ctx *ctx,
+               struct list_head *head)
+{
+       struct s5p_mfc_buf_ctrl *buf_ctrl;
+
+       list_for_each_entry(buf_ctrl, head, list) {
+               if (!(buf_ctrl->type & MFC_CTRL_TYPE_SET)
+                               || !(buf_ctrl->updated))
+                       continue;
+
+               buf_ctrl->has_new = 1;
+               buf_ctrl->updated = 0;
+               mfc_debug(6, "[NALQ][CTRLS] Recover buffer control id: 0x%08x, val: %d\n",
+                               buf_ctrl->id, buf_ctrl->val);
+       }
+
+       return 0;
+}
+
+struct s5p_mfc_ctrls_ops decoder_ctrls_ops = {
+       .init_ctx_ctrls                 = s5p_mfc_dec_init_ctx_ctrls,
+       .cleanup_ctx_ctrls              = s5p_mfc_dec_cleanup_ctx_ctrls,
+       .init_buf_ctrls                 = s5p_mfc_dec_init_buf_ctrls,
+       .reset_buf_ctrls                = s5p_mfc_dec_reset_buf_ctrls,
+       .cleanup_buf_ctrls              = s5p_mfc_dec_cleanup_buf_ctrls,
+       .to_buf_ctrls                   = s5p_mfc_dec_to_buf_ctrls,
+       .to_ctx_ctrls                   = s5p_mfc_dec_to_ctx_ctrls,
+       .set_buf_ctrls_val              = s5p_mfc_dec_set_buf_ctrls_val,
+       .get_buf_ctrls_val              = s5p_mfc_dec_get_buf_ctrls_val,
+       .set_buf_ctrls_val_nal_q_dec    = s5p_mfc_dec_set_buf_ctrls_val_nal_q_dec,
+       .get_buf_ctrls_val_nal_q_dec    = s5p_mfc_dec_get_buf_ctrls_val_nal_q_dec,
+       .recover_buf_ctrls_val          = s5p_mfc_dec_recover_buf_ctrls_val,
+       .get_buf_update_val             = s5p_mfc_dec_get_buf_update_val,
+       .recover_buf_ctrls_nal_q        = s5p_mfc_dec_recover_buf_ctrls_nal_q,
+};
diff --git a/drivers/media/platform/exynos/mfc/mfc_dec_vb2_ops.c b/drivers/media/platform/exynos/mfc/mfc_dec_vb2_ops.c
new file mode 100644 (file)
index 0000000..dbe739f
--- /dev/null
@@ -0,0 +1,633 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_dec_vb2_ops.c
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include  "mfc_common.h"
+
+#include "mfc_hwlock.h"
+#include "mfc_nal_q.h"
+#include "mfc_opr.h"
+#include "mfc_sync.h"
+
+#include "mfc_queue.h"
+#include "mfc_utils.h"
+#include "mfc_buf.h"
+#include "mfc_mem.h"
+
+static int s5p_mfc_dec_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;
+       struct s5p_mfc_dev *dev;
+       struct s5p_mfc_dec *dec;
+       struct s5p_mfc_raw_info *raw;
+       int i;
+
+       mfc_debug_enter();
+
+       if (!vq) {
+               mfc_err_dev("no vb2_queue info\n");
+               return -EINVAL;
+       }
+
+       ctx = vq->drv_priv;
+       if (!ctx) {
+               mfc_err_dev("no mfc context to run\n");
+               return -EINVAL;
+       }
+       dev = ctx->dev;
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return -EINVAL;
+       }
+       dec = ctx->dec_priv;
+       if (!dec) {
+               mfc_err_dev("no mfc decoder to run\n");
+               return -EINVAL;
+       }
+
+       raw = &ctx->raw_buf;
+
+       /* Video output for decoding (source)
+        * this can be set after getting an instance */
+       if (ctx->state == MFCINST_GOT_INST &&
+           vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               mfc_debug(4, "dec src\n");
+               /* 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;
+
+               psize[0] = dec->src_buf_size;
+               alloc_devs[0] = dev->device;
+       /* 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) {
+               mfc_debug(4, "dec dst\n");
+               /* Output plane count is different by the pixel format */
+               *plane_count = ctx->dst_fmt->mem_planes;
+               /* Setup buffer count */
+               if (*buf_count < ctx->dpb_count)
+                       *buf_count = ctx->dpb_count;
+               if (*buf_count > MFC_MAX_BUFFERS)
+                       *buf_count = MFC_MAX_BUFFERS;
+
+               if (ctx->dst_fmt->mem_planes == 1) {
+                       psize[0] = raw->total_plane_size;
+                       alloc_devs[0] = dev->device;
+               } else {
+                       for (i = 0; i < ctx->dst_fmt->num_planes; i++) {
+                               psize[i] = raw->plane_size[i];
+                               alloc_devs[i] = dev->device;
+                       }
+               }
+       } else {
+               mfc_err_ctx("State seems invalid. State = %d, vq->type = %d\n",
+                                                       ctx->state, vq->type);
+               return -EINVAL;
+       }
+
+       mfc_debug(2, "buf_count: %d, plane_count: %d, type: %#x\n",
+                       *buf_count, *plane_count, vq->type);
+       for (i = 0; i < *plane_count; i++)
+               mfc_debug(2, "plane[%d] size: %d\n", i, psize[i]);
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+static void s5p_mfc_dec_unlock(struct vb2_queue *q)
+{
+       struct s5p_mfc_ctx *ctx = q->drv_priv;
+       struct s5p_mfc_dev *dev;
+
+       if (!ctx) {
+               mfc_err_dev("no mfc context to run\n");
+               return;
+       }
+       dev = ctx->dev;
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return;
+       }
+
+       mutex_unlock(&dev->mfc_mutex);
+}
+
+static void s5p_mfc_dec_lock(struct vb2_queue *q)
+{
+       struct s5p_mfc_ctx *ctx = q->drv_priv;
+       struct s5p_mfc_dev *dev;
+
+       if (!ctx) {
+               mfc_err_dev("no mfc context to run\n");
+               return;
+       }
+       dev = ctx->dev;
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return;
+       }
+
+       mutex_lock(&dev->mfc_mutex);
+}
+
+static int s5p_mfc_dec_buf_init(struct vb2_buffer *vb)
+{
+       struct vb2_queue *vq = vb->vb2_queue;
+       struct s5p_mfc_ctx *ctx = vq->drv_priv;
+       struct s5p_mfc_dev *dev;
+       struct s5p_mfc_dec *dec;
+       struct s5p_mfc_buf *buf = vb_to_mfc_buf(vb);
+       dma_addr_t start_raw;
+       int i, ret;
+
+       mfc_debug_enter();
+       if (!ctx) {
+               mfc_err_dev("no mfc context to run\n");
+               return -EINVAL;
+       }
+       dev = ctx->dev;
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return -EINVAL;
+       }
+       dec = ctx->dec_priv;
+       if (!dec) {
+               mfc_err_dev("no mfc decoder to run\n");
+               return -EINVAL;
+       }
+
+       if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               ret = s5p_mfc_check_vb_with_fmt(ctx->dst_fmt, vb);
+               if (ret < 0)
+                       return ret;
+
+               start_raw = s5p_mfc_mem_get_daddr_vb(vb, 0);
+               if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_NV12N) {
+                       buf->addr[0][0] = start_raw;
+                       buf->addr[0][1] = NV12N_CBCR_BASE(start_raw,
+                                                       ctx->img_width,
+                                                       ctx->img_height);
+               } else if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_NV12N_10B) {
+                       buf->addr[0][0] = start_raw;
+                       buf->addr[0][1] = NV12N_10B_CBCR_BASE(start_raw,
+                                                       ctx->img_width,
+                                                       ctx->img_height);
+               } else if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_YUV420N) {
+                       buf->addr[0][0] = start_raw;
+                       buf->addr[0][1] = YUV420N_CB_BASE(start_raw,
+                                                       ctx->img_width,
+                                                       ctx->img_height);
+                       buf->addr[0][2] = YUV420N_CR_BASE(start_raw,
+                                                       ctx->img_width,
+                                                       ctx->img_height);
+               } else {
+                       for (i = 0; i < ctx->dst_fmt->mem_planes; i++)
+                               buf->addr[0][i] = s5p_mfc_mem_get_daddr_vb(vb, i);
+               }
+
+               if (call_cop(ctx, init_buf_ctrls, ctx, MFC_CTRL_TYPE_DST,
+                                       vb->index) < 0)
+                       mfc_err_ctx("failed in init_buf_ctrls\n");
+       } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               ret = s5p_mfc_check_vb_with_fmt(ctx->src_fmt, vb);
+               if (ret < 0)
+                       return ret;
+
+               buf->addr[0][0] = s5p_mfc_mem_get_daddr_vb(vb, 0);
+
+               if (call_cop(ctx, init_buf_ctrls, ctx, MFC_CTRL_TYPE_SRC,
+                                       vb->index) < 0)
+                       mfc_err_ctx("failed in init_buf_ctrls\n");
+       } else {
+               mfc_err_ctx("s5p_mfc_dec_buf_init: unknown queue type\n");
+               return -EINVAL;
+       }
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+static int s5p_mfc_dec_buf_prepare(struct vb2_buffer *vb)
+{
+       struct vb2_queue *vq = vb->vb2_queue;
+       struct s5p_mfc_ctx *ctx = vq->drv_priv;
+       struct s5p_mfc_dec *dec;
+       struct s5p_mfc_raw_info *raw;
+       unsigned int index = vb->index;
+       size_t buf_size;
+       int i;
+
+       if (!ctx) {
+               mfc_err_dev("no mfc context to run\n");
+               return -EINVAL;
+       }
+       dec = ctx->dec_priv;
+       if (!dec) {
+               mfc_err_dev("no mfc decoder to run\n");
+               return -EINVAL;
+       }
+       if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               raw = &ctx->raw_buf;
+               /* check the size per plane */
+               if (ctx->dst_fmt->mem_planes == 1) {
+                       buf_size = vb2_plane_size(vb, 0);
+                       mfc_debug(2, "[FRAME] single plane vb size: %lu, calc size: %d\n",
+                                       buf_size, raw->total_plane_size);
+                       if (buf_size < raw->total_plane_size) {
+                               mfc_err_ctx("[FRAME] single plane size(%d) is smaller than (%d)\n",
+                                               buf_size, raw->total_plane_size);
+                               return -EINVAL;
+                       }
+               } else {
+                       for (i = 0; i < ctx->dst_fmt->mem_planes; i++) {
+                               buf_size = vb2_plane_size(vb, i);
+                               mfc_debug(2, "[FRAME] plane[%d] vb size: %lu, calc size: %d\n",
+                                               i, buf_size, raw->plane_size[i]);
+                               if (buf_size < raw->plane_size[i]) {
+                                       mfc_err_ctx("[FRAME] plane[%d] size(%d) is smaller than (%d)\n",
+                                                       i, buf_size, raw->plane_size[i]);
+                                       return -EINVAL;
+                               }
+                       }
+               }
+       } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               buf_size = vb2_plane_size(vb, 0);
+               mfc_debug(2, "[STREAM] vb size: %lu, calc size: %d\n",
+                               buf_size, dec->src_buf_size);
+
+               if (buf_size < dec->src_buf_size) {
+                       mfc_err_ctx("[STREAM] size(%d) is smaller than (%d)\n",
+                                       buf_size, dec->src_buf_size);
+                       return -EINVAL;
+               }
+
+               if (call_cop(ctx, to_buf_ctrls, ctx, &ctx->src_ctrls[index]) < 0)
+                       mfc_err_ctx("failed in to_buf_ctrls\n");
+       }
+
+       return 0;
+}
+
+static void s5p_mfc_dec_buf_finish(struct vb2_buffer *vb)
+{
+       struct vb2_queue *vq = vb->vb2_queue;
+       struct s5p_mfc_ctx *ctx = vq->drv_priv;
+       unsigned int index = vb->index;
+
+       if (!ctx) {
+               mfc_err_dev("no mfc context to run\n");
+               return;
+       }
+
+       if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               if (call_cop(ctx, to_ctx_ctrls, ctx, &ctx->dst_ctrls[index]) < 0)
+                       mfc_err_ctx("failed in to_ctx_ctrls\n");
+       } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               if (call_cop(ctx, to_ctx_ctrls, ctx, &ctx->src_ctrls[index]) < 0)
+                       mfc_err_ctx("failed in to_ctx_ctrls\n");
+       }
+}
+
+static void s5p_mfc_dec_buf_cleanup(struct vb2_buffer *vb)
+{
+       struct vb2_queue *vq = vb->vb2_queue;
+       struct s5p_mfc_ctx *ctx = vq->drv_priv;
+       unsigned int index = vb->index;
+
+       mfc_debug_enter();
+       if (!ctx) {
+               mfc_err_dev("no mfc context to run\n");
+               return;
+       }
+
+       if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               if (call_cop(ctx, cleanup_buf_ctrls, ctx,
+                                       MFC_CTRL_TYPE_DST, index) < 0)
+                       mfc_err_ctx("failed in cleanup_buf_ctrls\n");
+       } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               if (call_cop(ctx, cleanup_buf_ctrls, ctx,
+                                       MFC_CTRL_TYPE_SRC, index) < 0)
+                       mfc_err_ctx("failed in cleanup_buf_ctrls\n");
+       } else {
+               mfc_err_ctx("s5p_mfc_dec_buf_cleanup: unknown queue type\n");
+       }
+
+       mfc_debug_leave();
+}
+
+static int s5p_mfc_dec_start_streaming(struct vb2_queue *q, unsigned int count)
+{
+       struct s5p_mfc_ctx *ctx = q->drv_priv;
+       struct s5p_mfc_dev *dev;
+
+       if (!ctx) {
+               mfc_err_dev("no mfc context to run\n");
+               return -EINVAL;
+       }
+
+       dev = ctx->dev;
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return -EINVAL;
+       }
+
+       if (ctx->state == MFCINST_FINISHING)
+               s5p_mfc_change_state(ctx, MFCINST_RUNNING);
+
+       /* If context is ready then dev = work->data;schedule it to run */
+       if (s5p_mfc_dec_ctx_ready(ctx)) {
+               s5p_mfc_set_bit(ctx->num, &dev->work_bits);
+       }
+
+       s5p_mfc_try_run(dev);
+
+       return 0;
+}
+
+static void mfc_dec_src_stop_streaming(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev;
+       struct s5p_mfc_dec *dec;
+       struct s5p_mfc_buf *src_mb;
+       int index, csd, condition = 0;
+       int ret = 0;
+
+       dev = ctx->dev;
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return;
+       }
+
+       dec = ctx->dec_priv;
+       if (!dec) {
+               mfc_err_dev("no mfc decoder to run\n");
+               return;
+       }
+
+       while (1) {
+               csd = s5p_mfc_peek_buf_csd(&ctx->buf_queue_lock, &ctx->src_buf_queue);
+
+               if (csd == 1) {
+                       s5p_mfc_clean_ctx_int_flags(ctx);
+                       if (need_to_special_parsing(ctx)) {
+                               s5p_mfc_change_state(ctx, MFCINST_SPECIAL_PARSING);
+                               condition = S5P_FIMV_R2H_CMD_SEQ_DONE_RET;
+                               mfc_info_ctx("try to special parsing! (before NAL_START)\n");
+                       } else if (need_to_special_parsing_nal(ctx)) {
+                               s5p_mfc_change_state(ctx, MFCINST_SPECIAL_PARSING_NAL);
+                               condition = S5P_FIMV_R2H_CMD_FRAME_DONE_RET;
+                               mfc_info_ctx("try to special parsing! (after NAL_START)\n");
+                       } else {
+                               mfc_info_ctx("can't parsing CSD!, state = %d\n", ctx->state);
+                       }
+
+                       if (condition) {
+                               s5p_mfc_set_bit(ctx->num, &dev->work_bits);
+
+                               ret = s5p_mfc_just_run(dev, ctx->num);
+                               if (ret) {
+                                       mfc_err_ctx("Failed to run MFC\n");
+                               } else {
+                                       if (s5p_mfc_wait_for_done_ctx(ctx, condition))
+                                               mfc_err_ctx("special parsing time out\n");
+                               }
+                       }
+               }
+
+               src_mb = s5p_mfc_get_del_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, MFC_BUF_NO_TOUCH_USED);
+               if (!src_mb)
+                       break;
+
+               index = src_mb->vb.vb2_buf.index;
+
+               if (ctx->is_drm)
+                       s5p_mfc_stream_unprotect(ctx, src_mb, index);
+               vb2_set_plane_payload(&src_mb->vb.vb2_buf, 0, 0);
+               vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_ERROR);
+       }
+
+       dec->consumed = 0;
+       dec->remained_size = 0;
+       ctx->check_dump = 0;
+
+       s5p_mfc_init_queue(&ctx->src_buf_queue);
+
+       index = 0;
+       while (index < MFC_MAX_BUFFERS) {
+               index = find_next_bit(&ctx->src_ctrls_avail,
+                               MFC_MAX_BUFFERS, index);
+               if (index < MFC_MAX_BUFFERS)
+                       call_cop(ctx, reset_buf_ctrls, &ctx->src_ctrls[index]);
+               index++;
+       }
+}
+
+static void mfc_dec_dst_stop_streaming(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dec *dec;
+       int index = 0;
+
+       dec = ctx->dec_priv;
+       if (!dec) {
+               mfc_err_dev("no mfc decoder to run\n");
+               return;
+       }
+
+       s5p_mfc_cleanup_assigned_fd(ctx);
+       s5p_mfc_cleanup_queue(&ctx->buf_queue_lock, &ctx->ref_buf_queue);
+
+       dec->dynamic_used = 0;
+       dec->err_reuse_flag = 0;
+       dec->dec_only_release_flag = 0;
+
+       s5p_mfc_cleanup_queue(&ctx->buf_queue_lock, &ctx->dst_buf_queue);
+
+       ctx->is_dpb_realloc = 0;
+       dec->available_dpb = 0;
+
+       dec->y_addr_for_pb = 0;
+
+       s5p_mfc_cleanup_assigned_dpb(ctx);
+
+       while (index < MFC_MAX_BUFFERS) {
+               index = find_next_bit(&ctx->dst_ctrls_avail,
+                               MFC_MAX_BUFFERS, index);
+               if (index < MFC_MAX_BUFFERS)
+                       call_cop(ctx, reset_buf_ctrls, &ctx->dst_ctrls[index]);
+               index++;
+       }
+
+       if (ctx->wait_state == WAIT_INITBUF_DONE ||
+                       ctx->wait_state == WAIT_DECODING) {
+               ctx->wait_state = WAIT_NONE;
+               mfc_debug(2, "Decoding can be started now\n");
+       }
+}
+
+static void s5p_mfc_dec_stop_streaming(struct vb2_queue *q)
+{
+       struct s5p_mfc_ctx *ctx = q->drv_priv;
+       struct s5p_mfc_dev *dev;
+       int ret = 0;
+       int prev_state;
+
+       if (!ctx) {
+               mfc_err_dev("no mfc context to run\n");
+               return;
+       }
+
+       dev = ctx->dev;
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return;
+       }
+
+       mfc_info_ctx("dec stop_streaming is called, hwlock : %d, type : %d\n",
+                               test_bit(ctx->num, &dev->hwlock.bits), q->type);
+       MFC_TRACE_CTX("** DEC streamoff(type:%d)\n", q->type);
+
+       MFC_TRACE_CTX_HWLOCK("**DEC streamoff(type:%d)\n", q->type);
+       /* If a H/W operation is in progress, wait for it complete */
+       ret = s5p_mfc_get_hwlock_ctx(ctx);
+       if (ret < 0) {
+               mfc_err_ctx("Failed to get hwlock\n");
+               return;
+       }
+
+       if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+               mfc_dec_dst_stop_streaming(ctx);
+       else if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+               mfc_dec_src_stop_streaming(ctx);
+
+       if (ctx->state == MFCINST_FINISHING)
+               s5p_mfc_change_state(ctx, MFCINST_RUNNING);
+
+       if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && need_to_dpb_flush(ctx)) {
+               prev_state = ctx->state;
+               s5p_mfc_change_state(ctx, MFCINST_DPB_FLUSHING);
+               s5p_mfc_set_bit(ctx->num, &dev->work_bits);
+               s5p_mfc_clean_ctx_int_flags(ctx);
+               mfc_info_ctx("try to DPB flush\n");
+               ret = s5p_mfc_just_run(dev, ctx->num);
+               if (ret) {
+                       mfc_err_ctx("Failed to run MFC\n");
+                       s5p_mfc_release_hwlock_ctx(ctx);
+                       s5p_mfc_cleanup_work_bit_and_try_run(ctx);
+                       return;
+               }
+
+               if (s5p_mfc_wait_for_done_ctx(ctx, S5P_FIMV_R2H_CMD_DPB_FLUSH_RET)) {
+                       mfc_err_ctx("time out during DPB flush\n");
+                       dev->logging_data->cause |= (1 << MFC_CAUSE_FAIL_DPB_FLUSH);
+                       call_dop(dev, dump_and_stop_always, dev);
+               }
+
+               s5p_mfc_change_state(ctx, prev_state);
+       }
+
+       mfc_debug(2, "buffer cleanup & flush is done in stop_streaming, type : %d\n", q->type);
+
+       s5p_mfc_clear_bit(ctx->num, &dev->work_bits);
+       s5p_mfc_release_hwlock_ctx(ctx);
+
+       if (s5p_mfc_dec_ctx_ready(ctx))
+               s5p_mfc_set_bit(ctx->num, &dev->work_bits);
+       if (s5p_mfc_is_work_to_do(dev))
+               queue_work(dev->butler_wq, &dev->butler_work);
+}
+
+static void s5p_mfc_dec_buf_queue(struct vb2_buffer *vb)
+{
+       struct vb2_queue *vq = vb->vb2_queue;
+       struct s5p_mfc_ctx *ctx = vq->drv_priv;
+       struct s5p_mfc_dev *dev;
+       struct s5p_mfc_dec *dec;
+       struct s5p_mfc_buf *buf = vb_to_mfc_buf(vb);
+       int i;
+       unsigned char *stream_vir = NULL;
+
+       mfc_debug_enter();
+       if (!ctx) {
+               mfc_err_dev("no mfc context to run\n");
+               return;
+       }
+
+       dev = ctx->dev;
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return;
+       }
+
+       dec = ctx->dec_priv;
+       if (!dec) {
+               mfc_err_dev("no mfc decoder to run\n");
+               return;
+       }
+
+       if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               mfc_debug(2, "[BUFINFO] ctx[%d] add src index:%d, addr: 0x%08llx\n",
+                               ctx->num, vb->index, buf->addr[0][0]);
+               if (dec->dst_memtype == V4L2_MEMORY_DMABUF &&
+                               ctx->state < MFCINST_HEAD_PARSED && !ctx->is_drm)
+                       stream_vir = vb2_plane_vaddr(vb, 0);
+
+               buf->vir_addr = stream_vir;
+
+               s5p_mfc_add_tail_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, buf);
+
+               MFC_TRACE_CTX("Q src[%d] fd: %d, %#llx\n",
+                               vb->index, vb->planes[0].m.fd, buf->addr[0][0]);
+       } else if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               for (i = 0; i < ctx->dst_fmt->mem_planes; i++)
+                       mfc_debug(2, "[BUFINFO] ctx[%d] add dst index: %d, addr[%d]: 0x%08llx\n",
+                                       ctx->num, vb->index, i, buf->addr[0][i]);
+               s5p_mfc_store_dpb(ctx, vb);
+
+               if ((dec->dst_memtype == V4L2_MEMORY_USERPTR || dec->dst_memtype == V4L2_MEMORY_DMABUF) &&
+                               s5p_mfc_is_queue_count_same(&ctx->buf_queue_lock,
+                                       &ctx->dst_buf_queue, dec->total_dpb_count))
+                       ctx->capture_state = QUEUE_BUFS_MMAPED;
+
+               MFC_TRACE_CTX("Q dst[%d] fd: %d, %#llx / avail %#lx used %#x\n",
+                               vb->index, vb->planes[0].m.fd, buf->addr[0][0],
+                               dec->available_dpb, dec->dynamic_used);
+       } else {
+               mfc_err_ctx("Unsupported buffer type (%d)\n", vq->type);
+       }
+
+       if (s5p_mfc_dec_ctx_ready(ctx)) {
+               s5p_mfc_set_bit(ctx->num, &dev->work_bits);
+               s5p_mfc_try_run(dev);
+       }
+
+       mfc_debug_leave();
+}
+
+struct vb2_ops s5p_mfc_dec_qops = {
+       .queue_setup            = s5p_mfc_dec_queue_setup,
+       .wait_prepare           = s5p_mfc_dec_unlock,
+       .wait_finish            = s5p_mfc_dec_lock,
+       .buf_init               = s5p_mfc_dec_buf_init,
+       .buf_prepare            = s5p_mfc_dec_buf_prepare,
+       .buf_finish             = s5p_mfc_dec_buf_finish,
+       .buf_cleanup            = s5p_mfc_dec_buf_cleanup,
+       .start_streaming        = s5p_mfc_dec_start_streaming,
+       .stop_streaming         = s5p_mfc_dec_stop_streaming,
+       .buf_queue              = s5p_mfc_dec_buf_queue,
+};
diff --git a/drivers/media/platform/exynos/mfc/mfc_enc.c b/drivers/media/platform/exynos/mfc/mfc_enc.c
new file mode 100644 (file)
index 0000000..f32c507
--- /dev/null
@@ -0,0 +1,2061 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_enc.c
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include "mfc_enc.h"
+#include "mfc_enc_internal.h"
+
+#include "mfc_hwlock.h"
+#include "mfc_otf.h"
+#include "mfc_opr.h"
+#include "mfc_sync.h"
+
+#include "mfc_qos.h"
+#include "mfc_queue.h"
+#include "mfc_utils.h"
+#include "mfc_buf.h"
+#include "mfc_mem.h"
+
+static struct s5p_mfc_fmt *mfc_enc_find_format(struct s5p_mfc_ctx *ctx,
+               unsigned int pixelformat)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_fmt *fmt = NULL;
+       unsigned long i;
+
+       for (i = 0; i < NUM_FORMATS; i++) {
+               if (enc_formats[i].fourcc == pixelformat) {
+                       fmt = (struct s5p_mfc_fmt *)&enc_formats[i];
+                       break;
+               }
+       }
+
+       if (!dev->pdata->support_10bit && (fmt->type & MFC_FMT_10BIT)) {
+               mfc_err_ctx("[FRAME] 10bit is not supported\n");
+               fmt = NULL;
+       }
+       if (!dev->pdata->support_422 && (fmt->type & MFC_FMT_422)) {
+               mfc_err_ctx("[FRAME] 422 is not supported\n");
+               fmt = NULL;
+       }
+       if (!dev->pdata->support_rgb && (fmt->type & MFC_FMT_RGB)) {
+               mfc_err_ctx("[FRAME] RGB is not supported\n");
+               fmt = NULL;
+       }
+
+       return fmt;
+}
+
+static struct v4l2_queryctrl *mfc_enc_get_ctrl(int id)
+{
+       unsigned long i;
+
+       for (i = 0; i < NUM_CTRLS; ++i)
+               if (id == controls[i].id)
+                       return &controls[i];
+       return NULL;
+}
+
+static int mfc_enc_check_ctrl_val(struct s5p_mfc_ctx *ctx, struct v4l2_control *ctrl)
+{
+       struct v4l2_queryctrl *c;
+
+       c = mfc_enc_get_ctrl(ctrl->id);
+       if (!c) {
+               mfc_err_ctx("[CTRLS] not supported control id (%#x)\n", ctrl->id);
+               return -EINVAL;
+       }
+
+       if (ctrl->id == V4L2_CID_MPEG_VIDEO_GOP_SIZE
+           && ctrl->value > c->maximum) {
+               mfc_info_ctx("GOP_SIZE is changed to max(%d -> %d)\n",
+                                ctrl->value, c->maximum);
+               ctrl->value = c->maximum;
+       }
+
+       if (ctrl->id == V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER) {
+               if ((ctrl->value & ~(1 << 16)) < c->minimum || (ctrl->value & ~(1 << 16)) > c->maximum
+                   || (c->step != 0 && (ctrl->value & ~(1 << 16)) % c->step != 0)) {
+                       mfc_err_ctx("[CTRLS][HIERARCHICAL] Invalid control value for %#x (%#x)\n",
+                                       ctrl->id, ctrl->value);
+                       return -ERANGE;
+               } else {
+                       return 0;
+               }
+       }
+
+       if (ctrl->value < c->minimum || ctrl->value > c->maximum
+           || (c->step != 0 && ctrl->value % c->step != 0)) {
+               mfc_err_ctx("[CTRLS] Invalid control value for %#x (%#x)\n",
+                               ctrl->id, ctrl->value);
+               return -ERANGE;
+       }
+
+       return 0;
+}
+
+static inline int mfc_enc_h264_profile(struct s5p_mfc_ctx *ctx, int profile)
+{
+       int ret = 0;
+
+       switch (profile) {
+       case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:
+               ret = S5P_FIMV_E_PROFILE_H264_MAIN;
+               break;
+       case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH:
+               ret = S5P_FIMV_E_PROFILE_H264_HIGH;
+               break;
+       case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
+               ret = S5P_FIMV_E_PROFILE_H264_BASELINE;
+               break;
+       case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
+               ret = S5P_FIMV_E_PROFILE_H264_CONSTRAINED_BASELINE;
+               break;
+       case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH:
+               ret = S5P_FIMV_E_PROFILE_H264_CONSTRAINED_HIGH;
+               break;
+       default:
+               ret = -EINVAL;
+       }
+
+       return ret;
+}
+
+/* Query capabilities of the device */
+static int vidioc_querycap(struct file *file, void *priv,
+                          struct v4l2_capability *cap)
+{
+       strncpy(cap->driver, "MFC", sizeof(cap->driver) - 1);
+       strncpy(cap->card, "encoder", sizeof(cap->card) - 1);
+       cap->bus_info[0] = 0;
+       cap->version = KERNEL_VERSION(1, 0, 0);
+       cap->device_caps = V4L2_CAP_VIDEO_CAPTURE
+                       | V4L2_CAP_VIDEO_OUTPUT
+                       | V4L2_CAP_VIDEO_CAPTURE_MPLANE
+                       | V4L2_CAP_VIDEO_OUTPUT_MPLANE
+                       | V4L2_CAP_STREAMING
+                       | V4L2_CAP_DEVICE_CAPS;
+
+       cap->capabilities = cap->device_caps;
+
+       return 0;
+}
+
+static int mfc_enc_enum_fmt(struct s5p_mfc_dev *dev, struct v4l2_fmtdesc *f,
+               unsigned int type)
+{
+       struct s5p_mfc_fmt *fmt;
+       unsigned long i, j = 0;
+
+       for (i = 0; i < NUM_FORMATS; ++i) {
+               if (!(enc_formats[i].type & type))
+                       continue;
+               if (!dev->pdata->support_10bit && (enc_formats[i].type & MFC_FMT_10BIT))
+                       continue;
+               if (!dev->pdata->support_422 && (enc_formats[i].type & MFC_FMT_422))
+                       continue;
+               if (!dev->pdata->support_rgb && (enc_formats[i].type & MFC_FMT_RGB))
+                       continue;
+
+               if (j == f->index) {
+                       fmt = &enc_formats[i];
+                       strlcpy(f->description, fmt->name,
+                               sizeof(f->description));
+                       f->pixelformat = fmt->fourcc;
+
+                       return 0;
+               }
+
+               ++j;
+       }
+
+       return -EINVAL;
+}
+
+static int vidioc_enum_fmt_vid_cap_mplane(struct file *file, void *pirv,
+               struct v4l2_fmtdesc *f)
+{
+       struct s5p_mfc_dev *dev = video_drvdata(file);
+
+       return mfc_enc_enum_fmt(dev, f, MFC_FMT_STREAM);
+}
+
+static int vidioc_enum_fmt_vid_out_mplane(struct file *file, void *prov,
+               struct v4l2_fmtdesc *f)
+{
+       struct s5p_mfc_dev *dev = video_drvdata(file);
+
+       return mfc_enc_enum_fmt(dev, f, MFC_FMT_FRAME);
+}
+
+static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+       struct s5p_mfc_enc *enc = ctx->enc_priv;
+       struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
+       struct s5p_mfc_raw_info *raw;
+       int i;
+
+       mfc_debug_enter();
+
+       if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               mfc_debug(4, "enc dst g_fmt\n");
+               /* 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->mem_planes;
+
+               pix_fmt_mp->plane_fmt[0].bytesperline = enc->dst_buf_size;
+               pix_fmt_mp->plane_fmt[0].sizeimage = enc->dst_buf_size;
+       } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               mfc_debug(4, "enc src g_fmt\n");
+               /* This is run on capture (encoder src) */
+               raw = &ctx->raw_buf;
+
+               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->mem_planes;
+               for (i = 0; i < ctx->src_fmt->mem_planes; i++) {
+                       pix_fmt_mp->plane_fmt[i].bytesperline = raw->stride[i];
+                       pix_fmt_mp->plane_fmt[i].sizeimage = raw->plane_size[i];
+               }
+       } else {
+               mfc_err_dev("invalid buf type (%d)\n", f->type);
+               return -EINVAL;
+       }
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+       struct s5p_mfc_fmt *fmt;
+       struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
+
+       fmt = mfc_enc_find_format(ctx, pix_fmt_mp->pixelformat);
+       if (!fmt) {
+               mfc_err_dev("Unsupported format for %s\n",
+                               V4L2_TYPE_IS_OUTPUT(f->type) ? "source" : "destination");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static void mfc_enc_check_format(struct s5p_mfc_ctx *ctx)
+{
+       switch (ctx->src_fmt->fourcc) {
+       case V4L2_PIX_FMT_NV16M_S10B:
+       case V4L2_PIX_FMT_NV61M_S10B:
+       case V4L2_PIX_FMT_NV16M_P210:
+       case V4L2_PIX_FMT_NV61M_P210:
+               mfc_debug(2, "[FRAME][10BIT] is 422 and 10bit format\n");
+               ctx->is_10bit = 1;
+               ctx->is_422 = 1;
+               break;
+       case V4L2_PIX_FMT_NV16M:
+       case V4L2_PIX_FMT_NV61M:
+               mfc_debug(2, "[FRAME] is 422 format\n");
+               ctx->is_10bit = 0;
+               ctx->is_422 = 1;
+               break;
+       case V4L2_PIX_FMT_NV12M_S10B:
+       case V4L2_PIX_FMT_NV12M_P010:
+       case V4L2_PIX_FMT_NV21M_S10B:
+       case V4L2_PIX_FMT_NV21M_P010:
+               mfc_debug(2, "[FRAME][10BIT] is 10bit format\n");
+               ctx->is_10bit = 1;
+               ctx->is_422 = 0;
+               break;
+       default:
+               ctx->is_10bit = 0;
+               ctx->is_422 = 0;
+               break;
+       }
+       mfc_debug(2, "[FRAME] 10bit: %d, 422: %d\n", ctx->is_10bit, ctx->is_422);
+}
+
+static int mfc_enc_check_resolution(struct s5p_mfc_ctx *ctx)
+{
+       int max_width = 0, max_height = 0, min_width = 0, min_height = 0, swap_check = 0;
+
+       /* Check max resolution */
+       switch (ctx->codec_mode) {
+       case S5P_FIMV_CODEC_HEVC_ENC:
+               if (ctx->is_422) {
+                       max_width = 65536;
+                       max_height = 8192;
+                       swap_check = 1;
+               } else {
+                       max_width = 8192;
+                       max_height = 8192;
+               }
+               break;
+       case S5P_FIMV_CODEC_BPG_ENC:
+               max_width = 65536;
+               max_height = 8192;
+               swap_check = 1;
+               break;
+       case S5P_FIMV_CODEC_H264_ENC:
+       case S5P_FIMV_CODEC_VP8_ENC:
+               max_width = 8192;
+               max_height = 8192;
+               break;
+       case S5P_FIMV_CODEC_VP9_ENC:
+               max_width = 4096;
+               max_height = 8192;
+               break;
+       case S5P_FIMV_CODEC_MPEG4_ENC:
+               max_width = 2048;
+               max_height = 2048;
+               break;
+       case S5P_FIMV_CODEC_H263_ENC:
+               max_width = 2048;
+               max_height = 1152;
+               break;
+       default:
+               mfc_err_ctx("Not supported codec(%d)\n", ctx->codec_mode);
+               return -EINVAL;
+       }
+
+       if (swap_check) {
+               if (!((ctx->crop_width < max_width && ctx->crop_height < max_height) ||
+                               (ctx->crop_width < max_height && ctx->crop_height < max_width))) {
+                       mfc_err_ctx("Resolution is too big(%dx%d > %dxi%d or %dx%d\n",
+                                       ctx->crop_width, ctx->crop_height, max_width, max_height,
+                                       max_height, max_width);
+                       return -EINVAL;
+               }
+       } else {
+               if (ctx->crop_width > max_width || ctx->crop_height > max_height) {
+                       mfc_err_ctx("Resolution is too big(%dx%d > %dx%d)\n",
+                                       ctx->crop_width, ctx->crop_height, max_width, max_height);
+                       return -EINVAL;
+               }
+       }
+
+       /* Check min resolution */
+       switch (ctx->codec_mode) {
+       case S5P_FIMV_CODEC_HEVC_ENC:
+       case S5P_FIMV_CODEC_BPG_ENC:
+       case S5P_FIMV_CODEC_VP9_ENC:
+               min_width = 64;
+               min_height = 64;
+               break;
+       case S5P_FIMV_CODEC_H264_ENC:
+       case S5P_FIMV_CODEC_VP8_ENC:
+       case S5P_FIMV_CODEC_MPEG4_ENC:
+       case S5P_FIMV_CODEC_H263_ENC:
+               min_width = 32;
+               min_height = 32;
+               break;
+       default:
+               mfc_err_ctx("Not supported codec(%d)\n", ctx->codec_mode);
+               return -EINVAL;
+       }
+
+       if (ctx->crop_width < min_width || ctx->crop_height < min_height) {
+               mfc_err_ctx("Resolution is too small(%dx%d < %dx%d)\n",
+                               ctx->crop_width, ctx->crop_height, min_width, min_height);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int vidioc_s_fmt_vid_cap_mplane(struct file *file, void *priv,
+                                                       struct v4l2_format *f)
+{
+       struct s5p_mfc_dev *dev = video_drvdata(file);
+       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+       struct s5p_mfc_enc *enc = ctx->enc_priv;
+       struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
+       int ret = 0;
+
+       mfc_debug_enter();
+
+       if (ctx->vq_dst.streaming) {
+               mfc_err_ctx("dst queue busy\n");
+               return -EBUSY;
+       }
+
+       ctx->dst_fmt = mfc_enc_find_format(ctx, pix_fmt_mp->pixelformat);
+       if (!ctx->dst_fmt) {
+               mfc_err_ctx("Unsupported format for destination\n");
+               return -EINVAL;
+       }
+
+       ctx->codec_mode = ctx->dst_fmt->codec_mode;
+       mfc_info_ctx("[STREAM] Enc dst codec(%d) : %s\n",
+                       ctx->codec_mode, ctx->dst_fmt->name);
+
+       if (mfc_enc_check_resolution(ctx)) {
+               mfc_err_ctx("Unsupported resolution\n");
+               return -EINVAL;
+       }
+
+       if (ctx->otf_handle) {
+               if (ctx->dst_fmt->fourcc != V4L2_PIX_FMT_H264 &&
+                               ctx->dst_fmt->fourcc != V4L2_PIX_FMT_HEVC) {
+                       mfc_err_ctx("[OTF] only H.264 and HEVC is supported\n");
+                       return -EINVAL;
+               }
+               if (s5p_mfc_otf_init(ctx)) {
+                       mfc_err_ctx("[OTF] otf_init failed\n");
+                       s5p_mfc_otf_destroy(ctx);
+                       return -EINVAL;
+               }
+       }
+
+       enc->dst_buf_size = pix_fmt_mp->plane_fmt[0].sizeimage;
+       pix_fmt_mp->plane_fmt[0].bytesperline = 0;
+
+       ret = s5p_mfc_alloc_instance_context(ctx);
+       if (ret) {
+               mfc_err_ctx("Failed to allocate enc instance[%d] buffers\n",
+                               ctx->num);
+               return -ENOMEM;
+       }
+
+       s5p_mfc_change_state(ctx, MFCINST_INIT);
+
+       ctx->capture_state = QUEUE_FREE;
+
+       ret = s5p_mfc_alloc_enc_roi_buffer(ctx);
+       if (ret) {
+               mfc_err_ctx("[ROI] Failed to allocate ROI buffers\n");
+               s5p_mfc_release_instance_context(ctx);
+               return -ENOMEM;
+       }
+
+       MFC_TRACE_CTX_HWLOCK("**ENC s_fmt\n");
+
+       ret = s5p_mfc_get_hwlock_ctx(ctx);
+       if (ret < 0) {
+               mfc_err_dev("Failed to get hwlock\n");
+               s5p_mfc_release_instance_context(ctx);
+               s5p_mfc_release_enc_roi_buffer(ctx);
+               return -EBUSY;
+       }
+
+       s5p_mfc_set_bit(ctx->num, &dev->work_bits);
+       ret = s5p_mfc_just_run(dev, ctx->num);
+       if (ret) {
+               mfc_err_ctx("Failed to run MFC\n");
+               s5p_mfc_release_hwlock_ctx(ctx);
+               s5p_mfc_cleanup_work_bit_and_try_run(ctx);
+               s5p_mfc_release_instance_context(ctx);
+               s5p_mfc_release_enc_roi_buffer(ctx);
+               return -EIO;
+       }
+
+       if (s5p_mfc_wait_for_done_ctx(ctx,
+                               S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET)) {
+               mfc_err_ctx("time out during open instance\n");
+               s5p_mfc_release_hwlock_ctx(ctx);
+               s5p_mfc_cleanup_work_bit_and_try_run(ctx);
+               s5p_mfc_release_instance_context(ctx);
+               s5p_mfc_release_enc_roi_buffer(ctx);
+               return -EIO;
+       }
+       s5p_mfc_release_hwlock_ctx(ctx);
+
+       mfc_debug(2, "Got instance number: %d\n", ctx->inst_no);
+
+       if (s5p_mfc_enc_ctx_ready(ctx))
+               s5p_mfc_set_bit(ctx->num, &dev->work_bits);
+       if (ctx->otf_handle && s5p_mfc_otf_ctx_ready(ctx))
+               s5p_mfc_set_bit(ctx->num, &dev->work_bits);
+       if (s5p_mfc_is_work_to_do(dev))
+               queue_work(dev->butler_wq, &dev->butler_work);
+
+       mfc_debug_leave();
+       return 0;
+}
+
+static int vidioc_s_fmt_vid_out_mplane(struct file *file, void *priv,
+                                                       struct v4l2_format *f)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+       struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
+
+       mfc_debug_enter();
+
+       if (ctx->vq_src.streaming) {
+               mfc_err_ctx("src queue busy\n");
+               return -EBUSY;
+       }
+
+       if (ctx->otf_handle) {
+               mfc_info_ctx("[OTF] skip source s_fmt\n");
+               return 0;
+       }
+
+       ctx->src_fmt = mfc_enc_find_format(ctx, pix_fmt_mp->pixelformat);
+       if (!ctx->src_fmt) {
+               mfc_err_ctx("Unsupported format for source\n");
+               return -EINVAL;
+       }
+
+       if (ctx->src_fmt->mem_planes != pix_fmt_mp->num_planes) {
+               mfc_err_ctx("[FRAME] enc src plane number is different (%d != %d)\n",
+                               ctx->src_fmt->mem_planes, pix_fmt_mp->num_planes);
+               return -EINVAL;
+       }
+
+       ctx->raw_buf.num_planes = ctx->src_fmt->num_planes;
+       ctx->img_width = pix_fmt_mp->width;
+       ctx->img_height = pix_fmt_mp->height;
+       ctx->buf_stride = pix_fmt_mp->plane_fmt[0].bytesperline;
+
+       mfc_enc_check_format(ctx);
+
+       if (ctx->state == MFCINST_RUNNING) {
+               s5p_mfc_change_state(ctx, MFCINST_GOT_INST);
+               mfc_info_ctx("[DRC] Enc resolution is changed\n");
+       }
+
+       mfc_info_ctx("[FRAME] enc src pixelformat : %s\n", ctx->src_fmt->name);
+       mfc_info_ctx("[FRAME] resolution w: %d, h: %d, stride: %d\n",
+                       pix_fmt_mp->width, pix_fmt_mp->height, ctx->buf_stride);
+
+       /*
+        * It should be keep till buffer size and stride was calculated.
+        * And it can be changed to real encoding size, if user call the s_crop.
+        */
+       ctx->crop_width = ctx->img_width;
+       ctx->crop_height = ctx->img_height;
+       s5p_mfc_enc_calc_src_size(ctx);
+
+       ctx->output_state = QUEUE_FREE;
+
+       mfc_debug_leave();
+       return 0;
+}
+
+static int vidioc_g_crop(struct file *file, void *fh, struct v4l2_crop *cr)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+
+       mfc_debug_enter();
+
+       cr->c.left = ctx->crop_left;
+       cr->c.top = ctx->crop_top;
+       cr->c.width = ctx->crop_width;
+       cr->c.height = ctx->crop_height;
+
+       mfc_debug(2, "[FRAME] enc crop w: %d, h: %d, offset l: %d t: %d\n",
+                       ctx->crop_width, ctx->crop_height, ctx->crop_left, ctx->crop_top);
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+static int vidioc_s_crop(struct file *file, void *priv, const struct v4l2_crop *cr)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+
+       mfc_debug_enter();
+
+       if (cr->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               mfc_err_ctx("not supported type (It can only in the source)\n");
+               return -EINVAL;
+       }
+
+       if (cr->c.left < 0 || cr->c.top < 0) {
+               mfc_err_ctx("[FRAME] crop position is negative\n");
+               return -EINVAL;
+       }
+
+       if ((cr->c.height > ctx->img_height) || (cr->c.top > ctx->img_height) ||
+                       (cr->c.width > ctx->img_width) || (cr->c.left > ctx->img_width) ||
+                       (cr->c.left <= (ctx->img_width - cr->c.width)) ||
+                       (cr->c.top <= (ctx->img_height - cr->c.height))) {
+               mfc_err_ctx("[FRAME] Out of crop range: (%d,%d,%d,%d) from %dx%d\n",
+                               cr->c.left, cr->c.top, cr->c.width, cr->c.height,
+                               ctx->img_width, ctx->img_height);
+               return -EINVAL;
+       }
+
+       ctx->crop_top = cr->c.top;
+       ctx->crop_left = cr->c.left;
+       ctx->crop_height = cr->c.height;
+       ctx->crop_width = cr->c.width;
+
+       mfc_debug(3, "[FRAME] enc original: %dx%d, crop: %dx%d, offset l: %d t: %d\n",
+                       ctx->img_width, ctx->img_height,
+                       ctx->crop_width, ctx->crop_height,
+                       ctx->crop_left, ctx->crop_top);
+
+       return 0;
+}
+
+static int vidioc_reqbufs(struct file *file, void *priv,
+                                         struct v4l2_requestbuffers *reqbufs)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+       int ret = 0;
+
+       mfc_debug_enter();
+
+       if (reqbufs->memory == V4L2_MEMORY_MMAP) {
+               mfc_err_ctx("Not supported memory type (%d)\n", reqbufs->memory);
+               return -EINVAL;
+       }
+
+       if (ctx->otf_handle) {
+               mfc_info_ctx("[OTF] skip reqbufs\n");
+               return 0;
+       }
+
+       if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               mfc_debug(4, "enc dst reqbuf(%d)\n", reqbufs->count);
+               if (reqbufs->count == 0) {
+                       ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
+                       ctx->capture_state = QUEUE_FREE;
+                       return ret;
+               }
+
+               if (ctx->capture_state != QUEUE_FREE) {
+                       mfc_err_ctx("invalid capture state: %d\n", ctx->capture_state);
+                       return -EINVAL;
+               }
+
+               ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
+               if (ret) {
+                       mfc_err_ctx("error in vb2_reqbufs() for E(D)\n");
+                       return ret;
+               }
+
+               ctx->capture_state = QUEUE_BUFS_REQUESTED;
+       } else if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               mfc_debug(4, "enc src reqbuf(%d)\n", reqbufs->count);
+               if (reqbufs->count == 0) {
+                       ret = vb2_reqbufs(&ctx->vq_src, reqbufs);
+                       ctx->output_state = QUEUE_FREE;
+                       return ret;
+               }
+
+               if (ctx->output_state != QUEUE_FREE) {
+                       mfc_err_ctx("invalid output state: %d\n", ctx->output_state);
+                       return -EINVAL;
+               }
+
+               ret = vb2_reqbufs(&ctx->vq_src, reqbufs);
+               if (ret) {
+                       mfc_err_ctx("error in vb2_reqbufs() for E(S)\n");
+                       return ret;
+               }
+
+               ctx->output_state = QUEUE_BUFS_REQUESTED;
+       } else {
+               mfc_err_ctx("invalid buf type (%d)\n", reqbufs->type);
+               return -EINVAL;
+       }
+
+       mfc_debug_leave();
+
+       return ret;
+}
+
+static int vidioc_querybuf(struct file *file, void *priv,
+                                                  struct v4l2_buffer *buf)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+       int ret = 0;
+
+       mfc_debug_enter();
+
+       if (ctx->otf_handle) {
+               mfc_info_ctx("[OTF] skip source querybuf\n");
+               return 0;
+       }
+
+       if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               mfc_debug(4, "enc dst querybuf, state: %d\n", ctx->state);
+               ret = vb2_querybuf(&ctx->vq_dst, buf);
+               if (ret != 0) {
+                       mfc_err_dev("enc dst: error in vb2_querybuf()\n");
+                       return ret;
+               }
+       } else if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               mfc_debug(4, "enc src querybuf, state: %d\n", ctx->state);
+               ret = vb2_querybuf(&ctx->vq_src, buf);
+               if (ret != 0) {
+                       mfc_err_dev("enc src: error in vb2_querybuf()\n");
+                       return ret;
+               }
+       } else {
+               mfc_err_dev("invalid buf type (%d)\n", buf->type);
+               return -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_mfc_ctx(file->private_data);
+       int i, ret = -EINVAL;
+
+       mfc_debug_enter();
+
+       if (ctx->otf_handle) {
+               mfc_info_ctx("[OTF] skip qbuf\n");
+               return 0;
+       }
+
+       if (ctx->state == MFCINST_ERROR) {
+               mfc_err_ctx("Call on QBUF after unrecoverable error\n");
+               return -EIO;
+       }
+
+       if (V4L2_TYPE_IS_MULTIPLANAR(buf->type) && !buf->length) {
+               mfc_err_ctx("multiplanar but length is zero\n");
+               return -EIO;
+       }
+
+       if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               mfc_debug(4, "enc src buf[%d] Q\n", buf->index);
+               for (i = 0; i < ctx->src_fmt->num_planes; i++) {
+                       if (!buf->m.planes[i].bytesused) {
+                               mfc_debug(2, "[FRAME] enc src[%d] size zero, "
+                                               "changed to buf size %d\n",
+                                               i, buf->m.planes[i].length);
+                               buf->m.planes[i].bytesused = buf->m.planes[i].length;
+                       } else {
+                               mfc_debug(2, "[FRAME] enc src[%d] size %d\n",
+                                               i, buf->m.planes[i].bytesused);
+                       }
+               }
+               ret = vb2_qbuf(&ctx->vq_src, buf);
+       } else {
+               mfc_debug(4, "enc dst buf[%d] Q\n", buf->index);
+               ret = vb2_qbuf(&ctx->vq_dst, buf);
+       }
+
+       mfc_debug_leave();
+       return ret;
+}
+
+/* Dequeue a buffer */
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+       int ret;
+
+       mfc_debug_enter();
+
+       if (ctx->otf_handle) {
+               mfc_info_ctx("[OTF] skip dqbuf\n");
+               return 0;
+       }
+
+       if (ctx->state == MFCINST_ERROR) {
+               mfc_err_ctx("Call on DQBUF after unrecoverable error\n");
+               return -EIO;
+       }
+       if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               mfc_debug(4, "enc src buf[%d] DQ\n", buf->index);
+               ret = vb2_dqbuf(&ctx->vq_src, buf, file->f_flags & O_NONBLOCK);
+       } else {
+               mfc_debug(4, "enc dst buf[%d] DQ\n", buf->index);
+               ret = vb2_dqbuf(&ctx->vq_dst, buf, file->f_flags & O_NONBLOCK);
+       }
+       mfc_debug_leave();
+       return ret;
+}
+
+/* Stream on */
+static int vidioc_streamon(struct file *file, void *priv,
+                          enum v4l2_buf_type type)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+       int ret = -EINVAL;
+
+       mfc_debug_enter();
+
+       if (ctx->otf_handle) {
+               mfc_info_ctx("[OTF] skip streamon\n");
+               return 0;
+       }
+
+       if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               mfc_debug(4, "enc src streamon\n");
+               ret = vb2_streamon(&ctx->vq_src, type);
+
+               if (!ret) {
+                       s5p_mfc_qos_on(ctx);
+               }
+       } else {
+               mfc_debug(4, "enc dst streamon\n");
+               ret = vb2_streamon(&ctx->vq_dst, type);
+       }
+
+       mfc_debug(2, "src: %d, dst: %d, state = %d, dpb_count = %d\n",
+                 s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->src_buf_queue),
+                 s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->dst_buf_queue),
+                 ctx->state, ctx->dpb_count);
+       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_mfc_ctx(file->private_data);
+       int ret;
+
+       mfc_debug_enter();
+
+       if (ctx->otf_handle) {
+               mfc_info_ctx("[OTF] skip streamoff\n");
+               return 0;
+       }
+
+       ret = -EINVAL;
+       if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               mfc_debug(4, "enc src streamoff\n");
+               s5p_mfc_qos_reset_last_framerate(ctx);
+
+               ret = vb2_streamoff(&ctx->vq_src, type);
+               if (!ret)
+                       s5p_mfc_qos_off(ctx);
+       } else {
+               mfc_debug(4, "enc dst streamoff\n");
+               ret = vb2_streamoff(&ctx->vq_dst, type);
+       }
+
+       mfc_debug_leave();
+
+       return ret;
+}
+
+/* Query a ctrl */
+static int vidioc_queryctrl(struct file *file, void *priv,
+                           struct v4l2_queryctrl *qc)
+{
+       struct v4l2_queryctrl *c;
+
+       c = mfc_enc_get_ctrl(qc->id);
+       if (!c) {
+               mfc_err_dev("[CTRLS] not supported control id (%#x)\n", qc->id);
+               return -EINVAL;
+       }
+
+       *qc = *c;
+       return 0;
+}
+
+static int mfc_enc_ext_info(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       int val = 0;
+
+       val |= ENC_SET_SPARE_SIZE;
+       val |= ENC_SET_TEMP_SVC_CH;
+
+       if (MFC_FEATURE_SUPPORT(dev, dev->pdata->skype))
+               val |= ENC_SET_SKYPE_FLAG;
+
+       val |= ENC_SET_ROI_CONTROL;
+       val |= ENC_SET_QP_BOUND_PB;
+       val |= ENC_SET_FIXED_SLICE;
+       val |= ENC_SET_PVC_MODE;
+       val |= ENC_SET_RATIO_OF_INTRA;
+
+       if (MFC_FEATURE_SUPPORT(dev, dev->pdata->color_aspect_enc))
+               val |= ENC_SET_COLOR_ASPECT;
+
+       val |= ENC_SET_HP_BITRATE_CONTROL;
+
+       if (MFC_FEATURE_SUPPORT(dev, dev->pdata->static_info_enc))
+               val |= ENC_SET_STATIC_INFO;
+
+       mfc_debug(5, "[CTRLS] ext info val: %#x\n", val);
+
+       return val;
+}
+
+static int mfc_enc_get_ctrl_val(struct s5p_mfc_ctx *ctx, struct v4l2_control *ctrl)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc *enc = ctx->enc_priv;
+       struct s5p_mfc_ctx_ctrl *ctx_ctrl;
+       int ret = 0;
+       int found = 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_CACHEABLE:
+               mfc_debug(5, "it is supported only V4L2_MEMORY_MMAP\n");
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_STREAM_SIZE:
+               ctrl->value = enc->dst_buf_size;
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TYPE:
+               ctrl->value = enc->frame_type;
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_CHECK_STATE:
+               ctrl->value = MFCSTATE_PROCESSING;
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG:
+       case V4L2_CID_MPEG_MFC51_VIDEO_LUMA_ADDR:
+       case V4L2_CID_MPEG_MFC51_VIDEO_CHROMA_ADDR:
+       case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_STATUS:
+               list_for_each_entry(ctx_ctrl, &ctx->ctrls, list) {
+                       if (!(ctx_ctrl->type & MFC_CTRL_TYPE_GET))
+                               continue;
+
+                       if (ctx_ctrl->id == ctrl->id) {
+                               if (ctx_ctrl->has_new) {
+                                       ctx_ctrl->has_new = 0;
+                                       ctrl->value = ctx_ctrl->val;
+                               } else {
+                                       mfc_debug(5, "[CTRLS] Control value "\
+                                                       "is not up to date: "\
+                                                       "0x%08x\n", ctrl->id);
+                                       return -EINVAL;
+                               }
+
+                               found = 1;
+                               break;
+                       }
+               }
+
+               if (!found) {
+                       mfc_err_ctx("Invalid control: 0x%08x\n", ctrl->id);
+                       return -EINVAL;
+               }
+               break;
+       case V4L2_CID_MPEG_MFC_GET_VERSION_INFO:
+               ctrl->value = dev->pdata->ip_ver;
+               break;
+       case V4L2_CID_MPEG_MFC_GET_DRIVER_INFO:
+               ctrl->value = MFC_DRIVER_INFO;
+               break;
+       case V4L2_CID_MPEG_MFC_GET_EXTRA_BUFFER_SIZE:
+               ctrl->value = MFC_LINEAR_BUF_SIZE;
+               break;
+       case V4L2_CID_MPEG_VIDEO_QOS_RATIO:
+               ctrl->value = ctx->qos_ratio;
+               break;
+       case V4L2_CID_MPEG_MFC_GET_EXT_INFO:
+               ctrl->value = mfc_enc_ext_info(ctx);
+               break;
+       case V4L2_CID_MPEG_VIDEO_BPG_HEADER_SIZE:
+               ctrl->value = enc->header_size;
+               break;
+       default:
+               mfc_err_ctx("Invalid control: 0x%08x\n", ctrl->id);
+               ret = -EINVAL;
+               break;
+       }
+
+       mfc_debug(5, "[CTRLS] get id: %#x, value: %d\n", ctrl->id, ctrl->value);
+
+       return ret;
+}
+
+static int vidioc_g_ctrl(struct file *file, void *priv,
+                        struct v4l2_control *ctrl)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+       int ret = 0;
+
+       mfc_debug_enter();
+       ret = mfc_enc_get_ctrl_val(ctx, ctrl);
+       mfc_debug_leave();
+
+       return ret;
+}
+
+static inline int mfc_enc_h264_level(enum v4l2_mpeg_video_h264_level lvl)
+{
+       static unsigned int t[V4L2_MPEG_VIDEO_H264_LEVEL_5_1 + 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,
+               /* V4L2_MPEG_VIDEO_H264_LEVEL_4_1   */ 41,
+               /* V4L2_MPEG_VIDEO_H264_LEVEL_4_2   */ 42,
+               /* V4L2_MPEG_VIDEO_H264_LEVEL_5_0   */ 50,
+               /* V4L2_MPEG_VIDEO_H264_LEVEL_5_1   */ 51,
+       };
+       return t[lvl];
+}
+
+static inline int mfc_enc_mpeg4_level(enum v4l2_mpeg_video_mpeg4_level lvl)
+{
+       static unsigned int t[V4L2_MPEG_VIDEO_MPEG4_LEVEL_6 + 1] = {
+               /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_0             */ 0,
+               /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_0B, Simple    */ 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, Advanced  */ 7,
+               /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_4             */ 4,
+               /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_5             */ 5,
+               /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_6,  Simple    */ 6,
+       };
+       return t[lvl];
+}
+
+static inline int mfc_enc_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];
+}
+
+static int mfc_enc_set_param(struct s5p_mfc_ctx *ctx, struct v4l2_control *ctrl)
+{
+       struct s5p_mfc_enc *enc = ctx->enc_priv;
+       struct s5p_mfc_enc_params *p = &enc->params;
+       int ret = 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
+               p->gop_size = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE:
+               p->slice_mode =
+                       (enum v4l2_mpeg_video_multi_slice_mode)ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB:
+               p->slice_mb = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES:
+               p->slice_bit = ctrl->value * 8;
+               break;
+       case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB_ROW:
+               p->slice_mb_row = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB:
+               p->intra_refresh_mb = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_PADDING:
+               p->pad = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_PADDING_YUV:
+               p->pad_luma = (ctrl->value >> 16) & 0xff;
+               p->pad_cb = (ctrl->value >> 8) & 0xff;
+               p->pad_cr = (ctrl->value >> 0) & 0xff;
+               break;
+       case V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE:
+               p->rc_frame = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_BITRATE:
+               p->rc_bitrate = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_RC_REACTION_COEFF:
+               p->rc_reaction_coeff = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE:
+               enc->force_frame_type = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_VBV_SIZE:
+               p->vbv_buf_size = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEADER_MODE:
+               p->seq_hdr_mode =
+                       (enum v4l2_mpeg_video_header_mode)(ctrl->value);
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE:
+               p->frame_skip_mode =
+                       (enum v4l2_mpeg_mfc51_video_frame_skip_mode)
+                       (ctrl->value);
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_RC_FIXED_TARGET_BIT:
+               p->fixed_target_bit = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_B_FRAMES:
+               p->num_b_frame = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
+               p->codec.h264.profile =
+               mfc_enc_h264_profile(ctx, (enum v4l2_mpeg_video_h264_profile)(ctrl->value));
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
+               p->codec.h264.level =
+               mfc_enc_h264_level((enum v4l2_mpeg_video_h264_level)(ctrl->value));
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_H264_INTERLACE:
+               p->codec.h264.interlace = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE:
+               p->codec.h264.loop_filter_mode =
+               (enum v4l2_mpeg_video_h264_loop_filter_mode)(ctrl->value);
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA:
+               p->codec.h264.loop_filter_alpha = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA:
+               p->codec.h264.loop_filter_beta = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:
+               p->codec.h264.entropy_mode =
+                       (enum v4l2_mpeg_video_h264_entropy_mode)(ctrl->value);
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_H264_NUM_REF_PIC_FOR_P:
+               p->num_refs_for_p = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM:
+               p->codec.h264._8x8_transform = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE:
+               p->rc_mb = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_H264_RC_FRAME_RATE:
+               p->rc_framerate = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP:
+               p->codec.h264.rc_frame_qp = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:
+               p->codec.h264.rc_min_qp = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:
+               p->codec.h264.rc_max_qp = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_MIN_QP_P:
+               p->codec.h264.rc_min_qp_p = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_MAX_QP_P:
+               p->codec.h264.rc_max_qp_p = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_MIN_QP_B:
+               p->codec.h264.rc_min_qp_b = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_MAX_QP_B:
+               p->codec.h264.rc_max_qp_b = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_DARK:
+               p->codec.h264.rc_mb_dark = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_SMOOTH:
+               p->codec.h264.rc_mb_smooth = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_STATIC:
+               p->codec.h264.rc_mb_static = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_ACTIVITY:
+               p->codec.h264.rc_mb_activity = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP:
+               p->codec.h264.rc_p_frame_qp = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP:
+               p->codec.h264.rc_b_frame_qp = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE:
+               p->codec.h264.ar_vui = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC:
+               p->codec.h264.ar_vui_idc =
+               mfc_enc_vui_sar_idc((enum v4l2_mpeg_video_h264_vui_sar_idc)(ctrl->value));
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH:
+               p->codec.h264.ext_sar_width = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_HEIGHT:
+               p->codec.h264.ext_sar_height = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
+               p->codec.h264.open_gop = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_I_PERIOD:
+               p->codec.h264.open_gop_size = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING:
+               p->codec.h264.hier_qp_enable = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE:
+               p->codec.h264.hier_qp_type =
+               (enum v4l2_mpeg_video_h264_hierarchical_coding_type)(ctrl->value);
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER:
+               p->codec.h264.num_hier_layer = ctrl->value & 0x7;
+               p->codec.h264.hier_ref_type = (ctrl->value >> 16) & 0x1;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_QP:
+               p->codec.h264.hier_qp_layer[(ctrl->value >> 16) & 0x7]
+                       = ctrl->value & 0xFF;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT0:
+               p->codec.h264.hier_bit_layer[0] = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT1:
+               p->codec.h264.hier_bit_layer[1] = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT2:
+               p->codec.h264.hier_bit_layer[2] = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT3:
+               p->codec.h264.hier_bit_layer[3] = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT4:
+               p->codec.h264.hier_bit_layer[4] = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT5:
+               p->codec.h264.hier_bit_layer[5] = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT6:
+               p->codec.h264.hier_bit_layer[6] = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING:
+               p->codec.h264.sei_gen_enable = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_CURRENT_FRAME_0:
+               p->codec.h264.sei_fp_curr_frame_0 = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE:
+               p->codec.h264.sei_fp_arrangement_type = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_FMO:
+               p->codec.h264.fmo_enable = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_FMO_MAP_TYPE:
+               switch ((enum v4l2_mpeg_video_h264_fmo_map_type)(ctrl->value)) {
+               case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_INTERLEAVED_SLICES:
+               case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_SCATTERED_SLICES:
+               case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_RASTER_SCAN:
+               case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_WIPE_SCAN:
+                       p->codec.h264.fmo_slice_map_type = ctrl->value;
+                       break;
+               default:
+                       ret = -EINVAL;
+               }
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_FMO_SLICE_GROUP:
+               p->codec.h264.fmo_slice_num_grp = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_FMO_RUN_LENGTH:
+               p->codec.h264.fmo_run_length[(ctrl->value >> 30) & 0x3]
+                       = ctrl->value & 0x3FFFFFFF;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_DIRECTION:
+               p->codec.h264.fmo_sg_dir = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_RATE:
+               p->codec.h264.fmo_sg_rate = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_ASO:
+               p->codec.h264.aso_enable = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_ASO_SLICE_ORDER:
+               p->codec.h264.aso_slice_order[(ctrl->value >> 18) & 0x7]
+                       &= ~(0xFF << (((ctrl->value >> 16) & 0x3) << 3));
+               p->codec.h264.aso_slice_order[(ctrl->value >> 18) & 0x7]
+                       |= (ctrl->value & 0xFF) << \
+                               (((ctrl->value >> 16) & 0x3) << 3);
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_PREPEND_SPSPPS_TO_IDR:
+               p->codec.h264.prepend_sps_pps_to_idr = ctrl->value ? 1 : 0;
+               break;
+       case V4L2_CID_MPEG_MFC_H264_ENABLE_LTR:
+               p->codec.h264.enable_ltr = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC_H264_NUM_OF_LTR:
+               p->codec.h264.num_of_ltr = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC_H264_BASE_PRIORITY:
+               p->codec.h264.base_priority = ctrl->value;
+               p->codec.h264.set_priority = 1;
+               break;
+       case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE:
+               switch ((enum v4l2_mpeg_video_mpeg4_profile)(ctrl->value)) {
+               case V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE:
+                       p->codec.mpeg4.profile =
+                               S5P_FIMV_E_PROFILE_MPEG4_SIMPLE;
+                       break;
+               case V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE:
+                       p->codec.mpeg4.profile =
+                       S5P_FIMV_E_PROFILE_MPEG4_ADVANCED_SIMPLE;
+                       break;
+               default:
+                       ret = -EINVAL;
+               }
+               break;
+       case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL:
+               p->codec.mpeg4.level =
+               mfc_enc_mpeg4_level((enum v4l2_mpeg_video_mpeg4_level)(ctrl->value));
+               break;
+       case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP:
+               p->codec.mpeg4.rc_frame_qp = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP:
+               p->codec.mpeg4.rc_min_qp = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP:
+               p->codec.mpeg4.rc_max_qp = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_P:
+               p->codec.mpeg4.rc_min_qp_p = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_P:
+               p->codec.mpeg4.rc_max_qp_p = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_B:
+               p->codec.mpeg4.rc_min_qp_b = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_B:
+               p->codec.mpeg4.rc_max_qp_b = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_MPEG4_QPEL:
+               p->codec.mpeg4.quarter_pixel = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP:
+               p->codec.mpeg4.rc_p_frame_qp = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP:
+               p->codec.mpeg4.rc_b_frame_qp = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_MPEG4_VOP_TIME_RES:
+               p->codec.mpeg4.vop_time_res = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_MPEG4_VOP_FRM_DELTA:
+               p->codec.mpeg4.vop_frm_delta = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC51_VIDEO_H263_RC_FRAME_RATE:
+               p->rc_framerate = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP:
+               p->codec.mpeg4.rc_frame_qp = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H263_MIN_QP:
+               p->codec.mpeg4.rc_min_qp = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H263_MAX_QP:
+               p->codec.mpeg4.rc_max_qp = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H263_MIN_QP_P:
+               p->codec.mpeg4.rc_min_qp_p = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H263_MAX_QP_P:
+               p->codec.mpeg4.rc_max_qp_p = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP:
+               p->codec.mpeg4.rc_p_frame_qp = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC70_VIDEO_VP8_VERSION:
+               p->codec.vp8.vp8_version = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC70_VIDEO_VP8_RC_FRAME_RATE:
+               p->rc_framerate = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_VP8_MIN_QP:
+               p->codec.vp8.rc_min_qp = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_VP8_MAX_QP:
+               p->codec.vp8.rc_max_qp = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_VP8_MIN_QP_P:
+               p->codec.vp8.rc_min_qp_p = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_VP8_MAX_QP_P:
+               p->codec.vp8.rc_max_qp_p = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_VP8_I_FRAME_QP:
+               p->codec.vp8.rc_frame_qp = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_VP8_P_FRAME_QP:
+               p->codec.vp8.rc_p_frame_qp = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC70_VIDEO_VP8_NUM_OF_PARTITIONS:
+               p->codec.vp8.vp8_numberofpartitions = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC70_VIDEO_VP8_FILTER_LEVEL:
+               p->codec.vp8.vp8_filterlevel = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC70_VIDEO_VP8_FILTER_SHARPNESS:
+               p->codec.vp8.vp8_filtersharpness = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC70_VIDEO_VP8_GOLDEN_FRAMESEL:
+               p->codec.vp8.vp8_goldenframesel = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC70_VIDEO_VP8_GF_REFRESH_PERIOD:
+               p->codec.vp8.vp8_gfrefreshperiod = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC70_VIDEO_VP8_HIERARCHY_QP_ENABLE:
+               p->codec.vp8.hier_qp_enable = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC70_VIDEO_VP8_HIERARCHY_QP_LAYER0:
+               p->codec.vp8.hier_qp_layer[(ctrl->value >> 16) & 0x3]
+                       = ctrl->value & 0xFF;
+               break;
+       case V4L2_CID_MPEG_MFC70_VIDEO_VP8_HIERARCHY_QP_LAYER1:
+               p->codec.vp8.hier_qp_layer[(ctrl->value >> 16) & 0x3]
+                       = ctrl->value & 0xFF;
+               break;
+       case V4L2_CID_MPEG_MFC70_VIDEO_VP8_HIERARCHY_QP_LAYER2:
+               p->codec.vp8.hier_qp_layer[(ctrl->value >> 16) & 0x3]
+                       = ctrl->value & 0xFF;
+               break;
+       case V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_BIT0:
+               p->codec.vp8.hier_bit_layer[0] = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_BIT1:
+               p->codec.vp8.hier_bit_layer[1] = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_BIT2:
+               p->codec.vp8.hier_bit_layer[2] = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC70_VIDEO_VP8_REF_NUMBER_FOR_PFRAMES:
+               p->num_refs_for_p = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC70_VIDEO_VP8_DISABLE_INTRA_MD4X4:
+               p->codec.vp8.intra_4x4mode_disable = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC70_VIDEO_VP8_NUM_TEMPORAL_LAYER:
+               p->codec.vp8.num_hier_layer = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_VP9_VERSION:
+               p->codec.vp9.vp9_version = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_VP9_RC_FRAME_RATE:
+               p->rc_framerate = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_VP9_MIN_QP:
+               p->codec.vp9.rc_min_qp = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_VP9_MAX_QP:
+               p->codec.vp9.rc_max_qp = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_VP9_MIN_QP_P:
+               p->codec.vp9.rc_min_qp_p = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_VP9_MAX_QP_P:
+               p->codec.vp9.rc_max_qp_p = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_VP9_I_FRAME_QP:
+               p->codec.vp9.rc_frame_qp = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_VP9_P_FRAME_QP:
+               p->codec.vp9.rc_p_frame_qp = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_VP9_GOLDEN_FRAMESEL:
+               p->codec.vp9.vp9_goldenframesel = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_VP9_GF_REFRESH_PERIOD:
+               p->codec.vp9.vp9_gfrefreshperiod = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_VP9_HIERARCHY_QP_ENABLE:
+               p->codec.vp9.hier_qp_enable = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_QP:
+               p->codec.vp9.hier_qp_layer[(ctrl->value >> 16) & 0x3]
+                       = ctrl->value & 0xFF;
+               break;
+       case V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_BIT0:
+               p->codec.vp9.hier_bit_layer[0] = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_BIT1:
+               p->codec.vp9.hier_bit_layer[1] = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_BIT2:
+               p->codec.vp9.hier_bit_layer[2] = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_VP9_REF_NUMBER_FOR_PFRAMES:
+               p->num_refs_for_p = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER:
+               p->codec.vp9.num_hier_layer = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_VP9_MAX_PARTITION_DEPTH:
+               p->codec.vp9.max_partition_depth = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_VP9_DISABLE_INTRA_PU_SPLIT:
+               p->codec.vp9.intra_pu_split_disable = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_DISABLE_IVF_HEADER:
+               p->ivf_header_disable = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_VP9_PROFILE:
+               p->codec.vp9.profile = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP:
+               p->codec.hevc.rc_frame_qp = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_QP:
+               p->codec.hevc.rc_p_frame_qp = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_QP:
+               p->codec.hevc.rc_b_frame_qp = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_RC_FRAME_RATE:
+               p->rc_framerate = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP:
+               p->codec.hevc.rc_min_qp = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP:
+               p->codec.hevc.rc_max_qp = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_P:
+               p->codec.hevc.rc_min_qp_p = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_P:
+               p->codec.hevc.rc_max_qp_p = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_B:
+               p->codec.hevc.rc_min_qp_b = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_B:
+               p->codec.hevc.rc_max_qp_b = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_LEVEL:
+               p->codec.hevc.level = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_PROFILE:
+               p->codec.hevc.profile = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_ADAPTIVE_RC_DARK:
+               p->codec.hevc.rc_lcu_dark = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_ADAPTIVE_RC_SMOOTH:
+               p->codec.hevc.rc_lcu_smooth = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_ADAPTIVE_RC_STATIC:
+               p->codec.hevc.rc_lcu_static = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_ADAPTIVE_RC_ACTIVITY:
+               p->codec.hevc.rc_lcu_activity = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_TIER_FLAG:
+               p->codec.hevc.tier_flag = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_MAX_PARTITION_DEPTH:
+               p->codec.hevc.max_partition_depth = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_REF_NUMBER_FOR_PFRAMES:
+               p->num_refs_for_p = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_REFRESH_TYPE:
+               p->codec.hevc.refreshtype = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_CONST_INTRA_PRED_ENABLE:
+               p->codec.hevc.const_intra_period_enable = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LOSSLESS_CU_ENABLE:
+               p->codec.hevc.lossless_cu_enable = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_WAVEFRONT_ENABLE:
+               p->codec.hevc.wavefront_enable = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LF_DISABLE:
+               p->codec.hevc.loopfilter_disable = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LF_SLICE_BOUNDARY:
+               p->codec.hevc.loopfilter_across = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LTR_ENABLE:
+               p->codec.hevc.enable_ltr = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_QP_ENABLE:
+               p->codec.hevc.hier_qp_enable = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_TYPE:
+               p->codec.hevc.hier_qp_type =
+               (enum v4l2_mpeg_video_hevc_hierarchical_coding_type)(ctrl->value);
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER:
+               p->codec.hevc.num_hier_layer = ctrl->value & 0x7;
+               p->codec.hevc.hier_ref_type = (ctrl->value >> 16) & 0x1;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_QP:
+               p->codec.hevc.hier_qp_layer[(ctrl->value >> 16) & 0x7]
+                       = ctrl->value & 0xFF;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT0:
+               p->codec.hevc.hier_bit_layer[0] = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT1:
+               p->codec.hevc.hier_bit_layer[1] = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT2:
+               p->codec.hevc.hier_bit_layer[2] = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT3:
+               p->codec.hevc.hier_bit_layer[3] = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT4:
+               p->codec.hevc.hier_bit_layer[4] = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT5:
+               p->codec.hevc.hier_bit_layer[5] = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT6:
+               p->codec.hevc.hier_bit_layer[6] = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_GENERAL_PB_ENABLE:
+               p->codec.hevc.general_pb_enable = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_TEMPORAL_ID_ENABLE:
+               p->codec.hevc.temporal_id_enable = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_STRONG_SMOTHING_FLAG:
+               p->codec.hevc.strong_intra_smooth = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_DISABLE_INTRA_PU_SPLIT:
+               p->codec.hevc.intra_pu_split_disable = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_DISABLE_TMV_PREDICTION:
+               p->codec.hevc.tmv_prediction_disable = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_MAX_NUM_MERGE_MV_MINUS1:
+               p->codec.hevc.max_num_merge_mv = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_WITHOUT_STARTCODE_ENABLE:
+               p->codec.hevc.encoding_nostartcode_enable = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_REFRESH_PERIOD:
+               p->codec.hevc.refreshperiod = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LF_BETA_OFFSET_DIV2:
+               p->codec.hevc.lf_beta_offset_div2 = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LF_TC_OFFSET_DIV2:
+               p->codec.hevc.lf_tc_offset_div2 = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_SIZE_OF_LENGTH_FIELD:
+               p->codec.hevc.size_of_length_field = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_USER_REF:
+               p->codec.hevc.user_ref = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_STORE_REF:
+               p->codec.hevc.store_ref = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_ROI_ENABLE:
+               p->roi_enable = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC_H264_VUI_RESTRICTION_ENABLE:
+               p->codec.h264.vui_enable = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEVC_PREPEND_SPSPPS_TO_IDR:
+               p->codec.hevc.prepend_sps_pps_to_idr = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC_CONFIG_QP_ENABLE:
+               p->dynamic_qp = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC_CONFIG_QP:
+               p->config_qp = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_RC_PVC_ENABLE:
+               /* It is valid for H.264, HEVC, VP8, VP9 */
+               p->rc_pvc = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_TEMPORAL_SHORTTERM_MAX_LAYER:
+               p->num_hier_max_layer = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_SIGN_DATA_HIDING:
+               break;
+       case V4L2_CID_MPEG_VIDEO_WEIGHTED_ENABLE:
+               p->weighted_enable = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_BPG_THUMBNAIL_SIZE:
+               /* It should be included when NAL_START */
+               p->codec.bpg.thumb_size = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_BPG_EXIF_SIZE:
+               /* It should be included when NAL_START */
+               p->codec.bpg.exif_size = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_RATIO_OF_INTRA:
+               p->ratio_intra = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_FULL_RANGE_FLAG:
+               p->check_color_range = 1;
+               p->color_range = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_COLOUR_PRIMARIES:
+               p->colour_primaries = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_TRANSFER_CHARACTERISTICS:
+               p->transfer_characteristics = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_MATRIX_COEFFICIENTS:
+               p->matrix_coefficients = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HIERARCHICAL_BITRATE_CTRL:
+               p->hier_bitrate_ctrl = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_STATIC_INFO_ENABLE:
+               p->static_info_enable = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_SEI_MAX_PIC_AVERAGE_LIGHT:
+               p->max_pic_average_light = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_SEI_MAX_CONTENT_LIGHT:
+               p->max_content_light = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_SEI_MAX_DISPLAY_LUMINANCE:
+               p->max_display_luminance = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_SEI_MIN_DISPLAY_LUMINANCE:
+               p->min_display_luminance = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_SEI_WHITE_POINT:
+               p->white_point = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_0:
+               p->display_primaries_0 = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_1:
+               p->display_primaries_1 = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_2:
+               p->display_primaries_2 = ctrl->value;
+               break;
+       default:
+               mfc_err_ctx("Invalid control: 0x%08x\n", ctrl->id);
+               ret = -EINVAL;
+       }
+
+       return ret;
+}
+
+static int mfc_enc_set_ctrl_val(struct s5p_mfc_ctx *ctx, struct v4l2_control *ctrl)
+{
+       struct s5p_mfc_enc *enc = ctx->enc_priv;
+       struct s5p_mfc_enc_params *p = &enc->params;
+       struct s5p_mfc_ctx_ctrl *ctx_ctrl;
+       int ret = 0;
+       int found = 0;
+       int index = 0;
+
+       mfc_debug(5, "[CTRLS] id: %#x, value: %d\n", ctrl->id, ctrl->value);
+
+       switch (ctrl->id) {
+       case V4L2_CID_CACHEABLE:
+               mfc_debug(5, "it is supported only V4L2_MEMORY_MMAP\n");
+               break;
+       case V4L2_CID_MPEG_VIDEO_QOS_RATIO:
+               ctx->qos_ratio = ctrl->value;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:
+       case V4L2_CID_MPEG_VIDEO_H263_MAX_QP:
+       case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP:
+       case V4L2_CID_MPEG_VIDEO_VP8_MAX_QP:
+       case V4L2_CID_MPEG_VIDEO_VP9_MAX_QP:
+       case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP:
+       case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:
+       case V4L2_CID_MPEG_VIDEO_H263_MIN_QP:
+       case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP:
+       case V4L2_CID_MPEG_VIDEO_VP8_MIN_QP:
+       case V4L2_CID_MPEG_VIDEO_VP9_MIN_QP:
+       case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP:
+       case V4L2_CID_MPEG_VIDEO_H264_MAX_QP_P:
+       case V4L2_CID_MPEG_VIDEO_H263_MAX_QP_P:
+       case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_P:
+       case V4L2_CID_MPEG_VIDEO_VP8_MAX_QP_P:
+       case V4L2_CID_MPEG_VIDEO_VP9_MAX_QP_P:
+       case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_P:
+       case V4L2_CID_MPEG_VIDEO_H264_MIN_QP_P:
+       case V4L2_CID_MPEG_VIDEO_H263_MIN_QP_P:
+       case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_P:
+       case V4L2_CID_MPEG_VIDEO_VP8_MIN_QP_P:
+       case V4L2_CID_MPEG_VIDEO_VP9_MIN_QP_P:
+       case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_P:
+       case V4L2_CID_MPEG_VIDEO_H264_MAX_QP_B:
+       case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_B:
+       case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_B:
+       case V4L2_CID_MPEG_VIDEO_H264_MIN_QP_B:
+       case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_B:
+       case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_B:
+       case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG:
+       case V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE:
+       case V4L2_CID_MPEG_MFC51_VIDEO_I_PERIOD_CH:
+       case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_RATE_CH:
+       case V4L2_CID_MPEG_MFC51_VIDEO_BIT_RATE_CH:
+       case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_CH:
+       case V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_CH:
+       case V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_CH:
+       case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_CH:
+       case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
+       case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
+       case V4L2_CID_MPEG_MFC_H264_MARK_LTR:
+       case V4L2_CID_MPEG_MFC_H264_USE_LTR:
+       case V4L2_CID_MPEG_MFC_H264_BASE_PRIORITY:
+       case V4L2_CID_MPEG_MFC_CONFIG_QP:
+       case V4L2_CID_MPEG_VIDEO_ROI_CONTROL:
+       case V4L2_CID_MPEG_VIDEO_YSUM:
+       case V4L2_CID_MPEG_VIDEO_RATIO_OF_INTRA:
+               list_for_each_entry(ctx_ctrl, &ctx->ctrls, list) {
+                       if (!(ctx_ctrl->type & MFC_CTRL_TYPE_SET))
+                               continue;
+
+                       if (ctx_ctrl->id == ctrl->id) {
+                               ctx_ctrl->has_new = 1;
+                               ctx_ctrl->val = ctrl->value;
+                               if (ctx_ctrl->id == \
+                                       V4L2_CID_MPEG_MFC51_VIDEO_FRAME_RATE_CH) {
+                                       ctx_ctrl->val &= ~(0xFFFF << 16);
+                                       ctx_ctrl->val |= ctx_ctrl->val << 16;
+                                       ctx_ctrl->val &= ~(0xFFFF);
+                                       ctx_ctrl->val |= p->rc_frame_delta & 0xFFFF;
+                               }
+                               if (((ctx_ctrl->id == \
+                                       V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_CH) ||
+                                       (ctx_ctrl->id == \
+                                       V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_CH) ||
+                                       (ctx_ctrl->id == \
+                                       V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_CH) ||
+                                       (ctx_ctrl->id == \
+                                       V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_CH)) &&
+                                       (enc->sh_handle_svc.fd == -1)) {
+                                               enc->sh_handle_svc.fd = ctrl->value;
+                                               if (s5p_mfc_mem_get_user_shared_handle(ctx,
+                                                                       &enc->sh_handle_svc))
+                                                       return -EINVAL;
+                                               else
+                                                       mfc_debug(2, "[MEMINFO][HIERARCHICAL] shared handle fd: %d, vaddr: 0x%p\n",
+                                                                       enc->sh_handle_svc.fd,
+                                                                       enc->sh_handle_svc.vaddr);
+                               }
+                               if (ctx_ctrl->id == V4L2_CID_MPEG_MFC51_VIDEO_I_PERIOD_CH &&
+                                               p->i_frm_ctrl_mode) {
+                                       ctx_ctrl->val = ctx_ctrl->val * (p->num_b_frame + 1);
+                                       if (ctx_ctrl->val >= 0x3FFFFFFF) {
+                                               mfc_info_ctx("I frame interval is bigger than max: %d\n",
+                                                               ctx_ctrl->val);
+                                               ctx_ctrl->val = 0x3FFFFFFF;
+                                       }
+                               }
+                               if (ctx_ctrl->id == V4L2_CID_MPEG_VIDEO_H264_LEVEL)
+                                       ctx_ctrl->val = mfc_enc_h264_level((enum v4l2_mpeg_video_h264_level)(ctrl->value));
+                               if (ctx_ctrl->id == V4L2_CID_MPEG_VIDEO_H264_PROFILE)
+                                       ctx_ctrl->val = mfc_enc_h264_profile(ctx, (enum v4l2_mpeg_video_h264_profile)(ctrl->value));
+                               if (ctx_ctrl->id == V4L2_CID_MPEG_VIDEO_ROI_CONTROL) {
+                                       if (enc->sh_handle_roi.fd == -1) {
+                                               enc->sh_handle_roi.fd = ctrl->value;
+                                               if (s5p_mfc_mem_get_user_shared_handle(ctx,
+                                                                       &enc->sh_handle_roi))
+                                                       return -EINVAL;
+                                               else
+                                                       mfc_debug(2, "[MEMINFO][ROI] shared handle fd: %d, vaddr: 0x%p\n",
+                                                                       enc->sh_handle_roi.fd,
+                                                                       enc->sh_handle_roi.vaddr);
+                                       }
+                                       index = enc->roi_index;
+                                       memcpy(&enc->roi_info[index],
+                                                       enc->sh_handle_roi.vaddr,
+                                                       sizeof(struct mfc_enc_roi_info));
+                                       if (copy_from_user(enc->roi_buf[index].vaddr,
+                                                       enc->roi_info[index].addr,
+                                                       enc->roi_info[index].size))
+                                               return -EFAULT;
+                               }
+
+                               found = 1;
+                               break;
+                       }
+               }
+
+               if (!found) {
+                       mfc_err_ctx("Invalid control: 0x%08x\n", ctrl->id);
+                       return -EINVAL;
+               }
+               break;
+       default:
+               ret = mfc_enc_set_param(ctx, ctrl);
+               break;
+       }
+
+       return ret;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+                        struct v4l2_control *ctrl)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+       int ret = 0;
+
+       mfc_debug_enter();
+
+       ret = mfc_enc_check_ctrl_val(ctx, ctrl);
+       if (ret != 0)
+               return ret;
+
+       ret = mfc_enc_set_ctrl_val(ctx, ctrl);
+
+       mfc_debug_leave();
+
+       return ret;
+}
+
+static int vidioc_g_ext_ctrls(struct file *file, void *priv,
+                             struct v4l2_ext_controls *f)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+       struct v4l2_ext_control *ext_ctrl;
+       struct v4l2_control ctrl;
+       int i;
+       int ret = 0;
+
+       if (f->which != V4L2_CTRL_CLASS_MPEG)
+               return -EINVAL;
+
+       for (i = 0; i < f->count; i++) {
+               ext_ctrl = (f->controls + i);
+
+               ctrl.id = ext_ctrl->id;
+
+               ret = mfc_enc_get_ctrl_val(ctx, &ctrl);
+               if (ret == 0) {
+                       ext_ctrl->value = ctrl.value;
+               } else {
+                       f->error_idx = i;
+                       break;
+               }
+
+               mfc_debug(5, "[CTRLS][%d] id: %#x, value: %d\n",
+                               i, ext_ctrl->id, ext_ctrl->value);
+       }
+
+       return ret;
+}
+
+static int vidioc_s_ext_ctrls(struct file *file, void *priv,
+                               struct v4l2_ext_controls *f)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+       struct v4l2_ext_control *ext_ctrl;
+       struct v4l2_control ctrl;
+       int i;
+       int ret = 0;
+
+       if (f->which != V4L2_CTRL_CLASS_MPEG)
+               return -EINVAL;
+
+       for (i = 0; i < f->count; i++) {
+               ext_ctrl = (f->controls + i);
+
+               ctrl.id = ext_ctrl->id;
+               ctrl.value = ext_ctrl->value;
+
+               ret = mfc_enc_check_ctrl_val(ctx, &ctrl);
+               if (ret != 0) {
+                       f->error_idx = i;
+                       break;
+               }
+
+               ret = mfc_enc_set_param(ctx, &ctrl);
+               if (ret != 0) {
+                       f->error_idx = i;
+                       break;
+               }
+
+               mfc_debug(5, "[CTRLS][%d] id: %#x, value: %d\n",
+                               i, ext_ctrl->id, ext_ctrl->value);
+       }
+
+       return ret;
+}
+
+static int vidioc_try_ext_ctrls(struct file *file, void *priv,
+                               struct v4l2_ext_controls *f)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
+       struct v4l2_ext_control *ext_ctrl;
+       struct v4l2_control ctrl;
+       int i;
+       int ret = 0;
+
+       if (f->which != V4L2_CTRL_CLASS_MPEG)
+               return -EINVAL;
+
+       for (i = 0; i < f->count; i++) {
+               ext_ctrl = (f->controls + i);
+
+               ctrl.id = ext_ctrl->id;
+               ctrl.value = ext_ctrl->value;
+
+               ret = mfc_enc_check_ctrl_val(ctx, &ctrl);
+               if (ret != 0) {
+                       f->error_idx = i;
+                       break;
+               }
+
+               mfc_debug(2, "[%d] id: 0x%08x, value: %d\n", i, ext_ctrl->id, ext_ctrl->value);
+       }
+
+       return ret;
+}
+
+static const struct v4l2_ioctl_ops s5p_mfc_enc_ioctl_ops = {
+       .vidioc_querycap                = vidioc_querycap,
+       .vidioc_enum_fmt_vid_cap_mplane = vidioc_enum_fmt_vid_cap_mplane,
+       .vidioc_enum_fmt_vid_out_mplane = vidioc_enum_fmt_vid_out_mplane,
+       .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_vid_cap_mplane,
+       .vidioc_s_fmt_vid_out_mplane    = vidioc_s_fmt_vid_out_mplane,
+       .vidioc_g_crop                  = vidioc_g_crop,
+       .vidioc_s_crop                  = vidioc_s_crop,
+       .vidioc_reqbufs                 = vidioc_reqbufs,
+       .vidioc_querybuf                = vidioc_querybuf,
+       .vidioc_qbuf                    = vidioc_qbuf,
+       .vidioc_dqbuf                   = vidioc_dqbuf,
+       .vidioc_streamon                = vidioc_streamon,
+       .vidioc_streamoff               = vidioc_streamoff,
+       .vidioc_queryctrl               = vidioc_queryctrl,
+       .vidioc_g_ctrl                  = vidioc_g_ctrl,
+       .vidioc_s_ctrl                  = vidioc_s_ctrl,
+       .vidioc_g_ext_ctrls             = vidioc_g_ext_ctrls,
+       .vidioc_s_ext_ctrls             = vidioc_s_ext_ctrls,
+       .vidioc_try_ext_ctrls           = vidioc_try_ext_ctrls,
+};
+
+const struct v4l2_ioctl_ops *s5p_mfc_get_enc_v4l2_ioctl_ops(void)
+{
+       return &s5p_mfc_enc_ioctl_ops;
+}
diff --git a/drivers/media/platform/exynos/mfc/mfc_enc.h b/drivers/media/platform/exynos/mfc/mfc_enc.h
new file mode 100644 (file)
index 0000000..bc0a0ad
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_enc.h
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __MFC_ENC_H
+#define __MFC_ENC_H __FILE__
+
+#include "mfc_common.h"
+
+const struct v4l2_ioctl_ops *s5p_mfc_get_enc_v4l2_ioctl_ops(void);
+
+#endif /* __MFC_ENC_H */
diff --git a/drivers/media/platform/exynos/mfc/mfc_enc_internal.h b/drivers/media/platform/exynos/mfc/mfc_enc_internal.h
new file mode 100644 (file)
index 0000000..60f35f6
--- /dev/null
@@ -0,0 +1,2354 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_enc_internal.h
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __MFC_ENC_INTERNAL_H
+#define __MFC_ENC_INTERNAL_H __FILE__
+
+#include "mfc_common.h"
+
+/*
+ * RGB encoding information to avoid confusion.
+ *
+ * V4L2_PIX_FMT_ARGB32 takes ARGB data like below.
+ * MSB                              LSB
+ * 3       2       1
+ * 2       4       6       8       0
+ * |B......BG......GR......RA......A|
+ */
+struct s5p_mfc_fmt enc_formats[] = {
+       {
+               .name = "4:2:0 3 Planes Y/Cb/Cr",
+               .fourcc = V4L2_PIX_FMT_YUV420M,
+               .codec_mode = MFC_FORMATS_NO_CODEC,
+               .type = MFC_FMT_FRAME,
+               .num_planes = 3,
+               .mem_planes = 3,
+       },
+       {
+               .name = "4:2:0 3 Planes Y/Cb/Cr single",
+               .fourcc = V4L2_PIX_FMT_YUV420N,
+               .codec_mode = MFC_FORMATS_NO_CODEC,
+               .type = MFC_FMT_FRAME,
+               .num_planes = 3,
+               .mem_planes = 1,
+       },
+       {
+               .name = "4:2:0 3 Planes Y/Cr/Cb",
+               .fourcc = V4L2_PIX_FMT_YVU420M,
+               .codec_mode = MFC_FORMATS_NO_CODEC,
+               .type = MFC_FMT_FRAME,
+               .num_planes = 3,
+               .mem_planes = 3,
+       },
+       {
+               .name = "4:2:0 2 Planes",
+               .fourcc = V4L2_PIX_FMT_NV12M,
+               .codec_mode = MFC_FORMATS_NO_CODEC,
+               .type = MFC_FMT_FRAME,
+               .num_planes = 2,
+               .mem_planes = 2,
+       },
+       {
+               .name = "4:2:0 2 Planes Y/CbCr single",
+               .fourcc = V4L2_PIX_FMT_NV12N,
+               .codec_mode = MFC_FORMATS_NO_CODEC,
+               .type = MFC_FMT_FRAME,
+               .num_planes = 2,
+               .mem_planes = 1,
+       },
+       {
+               .name = "4:2:0 2 Planes Y/CbCr 8+2 10bit",
+               .fourcc = V4L2_PIX_FMT_NV12M_S10B,
+               .codec_mode = MFC_FORMATS_NO_CODEC,
+               .type = MFC_FMT_FRAME | MFC_FMT_10BIT,
+               .num_planes = 2,
+               .mem_planes = 2,
+       },
+       {
+               .name = "4:2:0 2 Planes Y/CbCr P010 10bit",
+               .fourcc = V4L2_PIX_FMT_NV12M_P010,
+               .codec_mode = MFC_FORMATS_NO_CODEC,
+               .type = MFC_FMT_FRAME | MFC_FMT_10BIT,
+               .num_planes = 2,
+               .mem_planes = 2,
+       },
+       {
+               .name = "4:2:0 2 Planes Y/CrCb",
+               .fourcc = V4L2_PIX_FMT_NV21M,
+               .codec_mode = MFC_FORMATS_NO_CODEC,
+               .type = MFC_FMT_FRAME,
+               .num_planes = 2,
+               .mem_planes = 2,
+       },
+       {
+               .name = "4:2:0 2 Planes Y/CrCb 8+2 10bit",
+               .fourcc = V4L2_PIX_FMT_NV21M_S10B,
+               .codec_mode = MFC_FORMATS_NO_CODEC,
+               .type = MFC_FMT_FRAME | MFC_FMT_10BIT,
+               .num_planes = 2,
+               .mem_planes = 2,
+       },
+       {
+               .name = "4:2:0 2 Planes Y/CrCb P010 10bit",
+               .fourcc = V4L2_PIX_FMT_NV21M_P010,
+               .codec_mode = MFC_FORMATS_NO_CODEC,
+               .type = MFC_FMT_FRAME | MFC_FMT_10BIT,
+               .num_planes = 2,
+               .mem_planes = 2,
+       },
+       {
+               .name = "4:2:2 2 Planes Y/CbCr",
+               .fourcc = V4L2_PIX_FMT_NV16M,
+               .codec_mode = MFC_FORMATS_NO_CODEC,
+               .type = MFC_FMT_FRAME | MFC_FMT_422,
+               .num_planes = 2,
+               .mem_planes = 2,
+       },
+       {
+               .name = "4:2:2 2 Planes Y/CbCr 8+2 10bit",
+               .fourcc = V4L2_PIX_FMT_NV16M_S10B,
+               .codec_mode = MFC_FORMATS_NO_CODEC,
+               .type = MFC_FMT_FRAME | MFC_FMT_10BIT | MFC_FMT_422,
+               .num_planes = 2,
+               .mem_planes = 2,
+       },
+       {
+               .name = "4:2:2 2 Planes Y/CrCb 8+2 10bit",
+               .fourcc = V4L2_PIX_FMT_NV61M_S10B,
+               .codec_mode = MFC_FORMATS_NO_CODEC,
+               .type = MFC_FMT_FRAME | MFC_FMT_10BIT | MFC_FMT_422,
+               .num_planes = 2,
+               .mem_planes = 2,
+       },
+       {
+               .name = "4:2:2 2 Planes Y/CbCr P210 10bit",
+               .fourcc = V4L2_PIX_FMT_NV16M_P210,
+               .codec_mode = MFC_FORMATS_NO_CODEC,
+               .type = MFC_FMT_FRAME | MFC_FMT_10BIT | MFC_FMT_422,
+               .num_planes = 2,
+               .mem_planes = 2,
+       },
+       {
+               .name = "4:2:2 2 Planes Y/CrCb P210 10bit",
+               .fourcc = V4L2_PIX_FMT_NV61M_P210,
+               .codec_mode = MFC_FORMATS_NO_CODEC,
+               .type = MFC_FMT_FRAME | MFC_FMT_10BIT | MFC_FMT_422,
+               .num_planes = 2,
+               .mem_planes = 2,
+       },
+       {
+               .name = "4:2:2 2 Planes Y/CrCb",
+               .fourcc = V4L2_PIX_FMT_NV61M,
+               .codec_mode = MFC_FORMATS_NO_CODEC,
+               .type = MFC_FMT_FRAME | MFC_FMT_422,
+               .num_planes = 2,
+               .mem_planes = 2,
+       },
+       {
+               .name = "RGB888 1 Plane 24bpp",
+               .fourcc = V4L2_PIX_FMT_RGB24,
+               .codec_mode = MFC_FORMATS_NO_CODEC,
+               .type = MFC_FMT_FRAME | MFC_FMT_RGB,
+               .num_planes = 1,
+               .mem_planes = 1,
+       },
+       {
+               .name = "RGB565 1 Plane 16bpp",
+               .fourcc = V4L2_PIX_FMT_RGB565,
+               .codec_mode = MFC_FORMATS_NO_CODEC,
+               .type = MFC_FMT_FRAME | MFC_FMT_RGB,
+               .num_planes = 1,
+               .mem_planes = 1,
+       },
+       {
+               .name = "RGBX8888 1 Plane 32bpp",
+               .fourcc = V4L2_PIX_FMT_RGB32X,
+               .codec_mode = MFC_FORMATS_NO_CODEC,
+               .type = MFC_FMT_FRAME | MFC_FMT_RGB,
+               .num_planes = 1,
+               .mem_planes = 1,
+       },
+       {
+               .name = "BGRA8888 1 Plane 32bpp",
+               .fourcc = V4L2_PIX_FMT_BGR32,
+               .codec_mode = MFC_FORMATS_NO_CODEC,
+               .type = MFC_FMT_FRAME | MFC_FMT_RGB,
+               .num_planes = 1,
+               .mem_planes = 1,
+       },
+       {
+               .name = "ARGB8888 1 Plane 32bpp",
+               .fourcc = V4L2_PIX_FMT_ARGB32,
+               .codec_mode = MFC_FORMATS_NO_CODEC,
+               .type = MFC_FMT_FRAME | MFC_FMT_RGB,
+               .num_planes = 1,
+               .mem_planes = 1,
+       },
+       {
+               .name = "H264 Encoded Stream",
+               .fourcc = V4L2_PIX_FMT_H264,
+               .codec_mode = S5P_FIMV_CODEC_H264_ENC,
+               .type = MFC_FMT_STREAM,
+               .num_planes = 1,
+               .mem_planes = 1,
+       },
+       {
+               .name = "MPEG4 Encoded Stream",
+               .fourcc = V4L2_PIX_FMT_MPEG4,
+               .codec_mode = S5P_FIMV_CODEC_MPEG4_ENC,
+               .type = MFC_FMT_STREAM,
+               .num_planes = 1,
+               .mem_planes = 1,
+       },
+       {
+               .name = "H263 Encoded Stream",
+               .fourcc = V4L2_PIX_FMT_H263,
+               .codec_mode = S5P_FIMV_CODEC_H263_ENC,
+               .type = MFC_FMT_STREAM,
+               .num_planes = 1,
+               .mem_planes = 1,
+       },
+       {
+               .name = "VP8 Encoded Stream",
+               .fourcc = V4L2_PIX_FMT_VP8,
+               .codec_mode = S5P_FIMV_CODEC_VP8_ENC,
+               .type = MFC_FMT_STREAM,
+               .num_planes = 1,
+               .mem_planes = 1,
+       },
+       {
+               .name = "VP9 Encoded Stream",
+               .fourcc = V4L2_PIX_FMT_VP9,
+               .codec_mode = S5P_FIMV_CODEC_VP9_ENC,
+               .type = MFC_FMT_STREAM,
+               .num_planes = 1,
+               .mem_planes = 1,
+       },
+       {
+               .name = "HEVC Encoded Stream",
+               .fourcc = V4L2_PIX_FMT_HEVC,
+               .codec_mode = S5P_FIMV_CODEC_HEVC_ENC,
+               .type = MFC_FMT_STREAM,
+               .num_planes = 1,
+               .mem_planes = 1,
+       },
+       {
+               .name = "BPG Encoded Stream",
+               .fourcc = V4L2_PIX_FMT_BPG,
+               .codec_mode = S5P_FIMV_CODEC_BPG_ENC,
+               .type = MFC_FMT_STREAM,
+               .num_planes = 1,
+               .mem_planes = 1,
+       },
+};
+
+#define NUM_FORMATS ARRAY_SIZE(enc_formats)
+
+static struct v4l2_queryctrl controls[] = {
+       {
+               .id = V4L2_CID_CACHEABLE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Cacheable flag",
+               .minimum = 0,
+               .maximum = 3,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_GOP_SIZE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "The period of intra frame",
+               .minimum = 0,
+               .maximum = (1 << 30) - 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "The slice partitioning method",
+               .minimum = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE,
+               .maximum = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_FIXED_BYTES,
+               .step = 1,
+               .default_value = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "The number of MB in a slice",
+               .minimum = 1,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "The maximum bits per slices",
+               .minimum = 350,
+               .maximum = INT_MAX / 8,
+               .step = 1,
+               .default_value = 350,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB_ROW,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "The number of MB row in a slice",
+               .minimum = 1,
+               .maximum = INT_MAX / 256,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "The number of intra refresh MBs",
+               .minimum = 0,
+               .maximum = (1 << 18) - 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 << 24) - 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "Frame level rate control enable",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_BITRATE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Target bit rate rate-control",
+               .minimum = 1,
+               .maximum = INT_MAX,
+               .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_STREAM_SIZE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Encoded stream size",
+               .minimum = 0,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+               .flags = V4L2_CTRL_FLAG_READ_ONLY,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_COUNT,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Encoded frame count",
+               .minimum = 0,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+               .flags = V4L2_CTRL_FLAG_READ_ONLY,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TYPE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Encoded frame type",
+               .minimum = 0,
+               .maximum = 5,
+               .step = 1,
+               .default_value = 0,
+               .flags = V4L2_CTRL_FLAG_READ_ONLY,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Force frame type",
+               .minimum = V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_DISABLED,
+               .maximum = V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_NOT_CODED,
+               .step = 1,
+               .default_value = \
+                       V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_DISABLED,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_VBV_SIZE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "VBV buffer size (1Kbits)",
+               .minimum = 0,
+               .maximum = (1 << 16) - 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEADER_MODE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Sequence header mode",
+               .minimum = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE,
+               .maximum = V4L2_MPEG_VIDEO_HEADER_MODE_AT_THE_READY,
+               .step = 1,
+               .default_value = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Frame skip enable",
+               .minimum = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_DISABLED,
+               .maximum = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT,
+               .step = 1,
+               .default_value = V4L2_MPEG_MFC51_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,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_B_FRAMES,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "The number of B frames",
+               .minimum = 0,
+               .maximum = 2,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_PROFILE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "H264 profile",
+               .minimum = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE,
+               .maximum = V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH,
+               .step = 1,
+               .default_value = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_LEVEL,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "H264 level",
+               .minimum = V4L2_MPEG_VIDEO_H264_LEVEL_1_0,
+               .maximum = V4L2_MPEG_VIDEO_H264_LEVEL_5_1,
+               .step = 1,
+               .default_value = V4L2_MPEG_VIDEO_H264_LEVEL_1_0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_H264_INTERLACE,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "H264 interlace mode",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "H264 loop filter mode",
+               .minimum = V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED,
+               .maximum = V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_S_B,
+               .step = 1,
+               .default_value = V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "H264 loop filter alpha offset",
+               .minimum = -12,
+               .maximum = 12,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "H264 loop filter beta offset",
+               .minimum = -12,
+               .maximum = 12,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "H264 entorpy mode",
+               .minimum = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC,
+               .maximum = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC,
+               .step = 1,
+               .default_value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_H264_NUM_REF_PIC_FOR_P,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "The number of ref. picture of P",
+               .minimum = 1,
+               .maximum = 2,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "H264 8x8 transform enable",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "MB level rate control",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_H264_RC_FRAME_RATE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "H264 Frame rate",
+               .minimum = 1,
+               .maximum = (1 << 16) - 1,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "H264 Frame QP value",
+               .minimum = 0,
+               .maximum = 51,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_DARK,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "H264 dark region adaptive",
+               .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 region adaptive",
+               .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 region adaptive",
+               .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 MB activity adaptive",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "H264 P frame QP value",
+               .minimum = 0,
+               .maximum = 51,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "H264 B frame QP value",
+               .minimum = 0,
+               .maximum = 51,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "Aspect ratio VUI enable",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "VUI aspect ratio IDC",
+               .minimum = V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_UNSPECIFIED,
+               .maximum = V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_EXTENDED,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Horizontal size of SAR",
+               .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,
+               .name = "Vertical size of SAR",
+               .minimum = 0,
+               .maximum = (1 << 16) - 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_GOP_CLOSURE,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "GOP closure",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_I_PERIOD,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "H264 I period",
+               .minimum = 0,
+               .maximum = (1 << 16) - 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "Hierarchical Coding",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Hierarchical Coding Type",
+               .minimum = V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_B,
+               .maximum = V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_P,
+               .step = 1,
+               .default_value = V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_P,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Hierarchical Coding Layer",
+               .minimum = 0,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Hierarchical Coding Layer QP",
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "frame pack sei generation flag",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_SEI_FP_CURRENT_FRAME_0,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "Current frame is frame 0 flag",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Frame packing arrangement type",
+               .minimum = V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_SIDE_BY_SIDE,
+               .maximum = V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_TEMPORAL,
+               .step = 1,
+               .default_value = V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_SIDE_BY_SIDE,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_FMO,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "Flexible Macroblock Order",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_FMO_MAP_TYPE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Map type for FMO",
+               .minimum = V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_INTERLEAVED_SLICES,
+               .maximum = V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_WIPE_SCAN,
+               .step = 1,
+               .default_value = \
+                       V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_INTERLEAVED_SLICES,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_FMO_SLICE_GROUP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Number of slice groups for FMO",
+               .minimum = 1,
+               .maximum = 4,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_FMO_RUN_LENGTH,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "FMO Run Length",
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_DIRECTION,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Direction of the slice group",
+               .minimum = V4L2_MPEG_VIDEO_H264_FMO_CHANGE_DIR_RIGHT,
+               .maximum = V4L2_MPEG_VIDEO_H264_FMO_CHANGE_DIR_LEFT,
+               .step = 1,
+               .default_value = V4L2_MPEG_VIDEO_H264_FMO_CHANGE_DIR_RIGHT,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_RATE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Size of the first slice group",
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_ASO,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "Arbitrary Slice Order",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_ASO_SLICE_ORDER,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "ASO Slice order",
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_PREPEND_SPSPPS_TO_IDR,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Prepend SPS/PPS to every IDR",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "MPEG4 profile",
+               .minimum = V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE,
+               .maximum = V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE,
+               .step = 1,
+               .default_value = V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "MPEG4 level",
+               .minimum = V4L2_MPEG_VIDEO_MPEG4_LEVEL_0,
+               .maximum = V4L2_MPEG_VIDEO_MPEG4_LEVEL_6,
+               .step = 1,
+               .default_value = V4L2_MPEG_VIDEO_MPEG4_LEVEL_0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "MPEG4 Frame QP value",
+               .minimum = 1,
+               .maximum = 31,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MPEG4_QPEL,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "Quarter pixel search enable",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .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_MPEG4_VOP_TIME_RES,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "MPEG4 vop time resolution",
+               .minimum = 0,
+               .maximum = (1 << 16) - 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_MPEG4_VOP_FRM_DELTA,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "MPEG4 frame delta",
+               .minimum = 1,
+               .maximum = (1 << 16) - 1,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_H263_RC_FRAME_RATE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "H263 Frame rate",
+               .minimum = 1,
+               .maximum = (1 << 8) - 1,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "H263 Frame QP value",
+               .minimum = 1,
+               .maximum = 31,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .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_MFC51_VIDEO_FRAME_TAG,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Frame Tag",
+               .minimum = 0,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_STATUS,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Frame Status",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_QOS_RATIO,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "QoS ratio value",
+               .minimum = 20,
+               .maximum = 1000,
+               .step = 10,
+               .default_value = 100,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC70_VIDEO_VP8_VERSION,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "VP8 version",
+               .minimum = 0,
+               .maximum = 3,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_VP8_I_FRAME_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "VP8 Frame QP value",
+               .minimum = 0,
+               .maximum = 127,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_VP8_P_FRAME_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "VP8 Frame QP value",
+               .minimum = 0,
+               .maximum = 127,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC70_VIDEO_VP8_RC_FRAME_RATE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "VP8 Frame rate",
+               .minimum = 1,
+               .maximum = (1 << 16) - 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC70_VIDEO_VP8_NUM_OF_PARTITIONS,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "VP8 number of partitions",
+               .minimum = 0,
+               .maximum = 8,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC70_VIDEO_VP8_FILTER_LEVEL,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "VP8 loop filter level",
+               .minimum = 0,
+               .maximum = 63,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC70_VIDEO_VP8_FILTER_SHARPNESS,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "VP8 loop filter sharpness",
+               .minimum = 0,
+               .maximum = 7,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC70_VIDEO_VP8_GOLDEN_FRAMESEL,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "VP8 indication of golden frame",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC70_VIDEO_VP8_GF_REFRESH_PERIOD,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "VP8 indication of golden frame",
+               .minimum = 0,
+               .maximum = (1 << 16) - 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC70_VIDEO_VP8_HIERARCHY_QP_ENABLE,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "VP8 hierarchy QP enable",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC70_VIDEO_VP8_HIERARCHY_QP_LAYER0,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "VP8 layer0 QP value",
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC70_VIDEO_VP8_HIERARCHY_QP_LAYER1,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "VP8 layer1 QP value",
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC70_VIDEO_VP8_HIERARCHY_QP_LAYER2,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "VP8 layer2 QP value",
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC70_VIDEO_VP8_REF_NUMBER_FOR_PFRAMES,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "VP8 Number of reference picture",
+               .minimum = 1,
+               .maximum = 2,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC70_VIDEO_VP8_DISABLE_INTRA_MD4X4,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "VP8 intra 4x4 mode disable",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC70_VIDEO_VP8_NUM_TEMPORAL_LAYER,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "VP8 number of hierarchical layer",
+               .minimum = 0,
+               .maximum = 3,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_VP9_VERSION,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "VP9 version",
+               .minimum = 0,
+               .maximum = 3,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_VP9_I_FRAME_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "VP9 Frame QP value",
+               .minimum = 1,
+               .maximum = 255,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_VP9_P_FRAME_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "VP9 Frame QP value",
+               .minimum = 1,
+               .maximum = 255,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_VP9_RC_FRAME_RATE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "VP9 Frame rate",
+               .minimum = 1,
+               .maximum = (1 << 16) - 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_VP9_GOLDEN_FRAMESEL,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "VP9 indication of golden frame",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_VP9_GF_REFRESH_PERIOD,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "VP9 indication of golden frame",
+               .minimum = 0,
+               .maximum = ((1 << 16) - 1),
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_VP9_HIERARCHY_QP_ENABLE,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "VP9 hierarchy QP enable",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "VP9 layer0 QP value",
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_VP9_REF_NUMBER_FOR_PFRAMES,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "VP9 Number of reference picture",
+               .minimum = 1,
+               .maximum = 2,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "VP9 number of hierarchical layer",
+               .minimum = 0,
+               .maximum = 3,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_VP9_MAX_PARTITION_DEPTH,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "VP9 Maximum coding unit depth",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_VP9_DISABLE_INTRA_PU_SPLIT,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "VP9 disable intra pu split",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_BIT0,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Hierarchical Coding Layer Bit0",
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_BIT1,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Hierarchical Coding Layer Bit1",
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_BIT2,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Hierarchical Coding Layer Bit2",
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_CH,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Hierarchical Coding Layer Change",
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_DISABLE_IVF_HEADER,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "IVF header generation",
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "HEVC Frame QP value",
+               .minimum = -12,
+               .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 = -12,
+               .maximum = 51,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "HEVC B frame QP value",
+               .minimum = -12,
+               .maximum = 51,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_ADAPTIVE_RC_DARK,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "HEVC dark region adaptive",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_ADAPTIVE_RC_SMOOTH,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "HEVC smooth region adaptive",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_ADAPTIVE_RC_STATIC,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "HEVC static region adaptive",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_ADAPTIVE_RC_ACTIVITY,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "HEVC activity adaptive",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_PROFILE,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "HEVC Profile",
+               .minimum = 0,
+               .maximum = 4,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_LEVEL,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "HEVC level",
+               .minimum = 10,
+               .maximum = 62,
+               .step = 1,
+               .default_value = 10,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_TIER_FLAG,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "HEVC tier_flag default is Main",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_RC_FRAME_RATE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "HEVC Frame rate",
+               .minimum = 1,
+               .maximum = (1 << 16) - 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_MAX_PARTITION_DEPTH,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "HEVC Maximum coding unit depth",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0, /* need to check defualt value */
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_REF_NUMBER_FOR_PFRAMES,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "HEVC Number of reference picture",
+               .minimum = 1,
+               .maximum = 2,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_REFRESH_TYPE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "HEVC Number of reference picture",
+               .minimum = 0,
+               .maximum = 2,
+               .step = 1,
+               .default_value = 0, /* need to check defualt value */
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_CONST_INTRA_PRED_ENABLE,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "HEVC refresh type",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0, /* need to check defualt value */
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LOSSLESS_CU_ENABLE,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "HEVC lossless encoding select",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0, /* need to check defualt value */
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_WAVEFRONT_ENABLE,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "HEVC Wavefront enable",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0, /* need to check defualt value */
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LF_DISABLE,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "HEVC Filter disable",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0, /* need to check defualt value */
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LF_SLICE_BOUNDARY,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "across or not slice boundary",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0, /* need to check defualt value */
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LTR_ENABLE,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "long term reference enable",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0, /* need to check defualt value */
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_QP_ENABLE,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "QP values for temporal layer",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0, /* need to check defualt value */
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_TYPE,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "Hierarchical Coding Type",
+               .minimum = V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B,
+               .maximum = V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P,
+               .step = 1,
+               .default_value = 0, /* need to check defualt value */
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Hierarchical Coding Layer",
+               .minimum = 0,
+               .maximum = 7,
+               .step = 1,
+               .default_value = 0, /* need to check defualt value */
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Hierarchical Coding Layer QP",
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0, /* need to check defualt value */
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT0,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Hierarchical Coding Layer BIT0",
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT1,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Hierarchical Coding Layer BIT1",
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT2,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Hierarchical Coding Layer BIT2",
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT3,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Hierarchical Coding Layer BIT3",
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT4,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Hierarchical Coding Layer BIT4",
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT5,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Hierarchical Coding Layer BIT5",
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT6,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Hierarchical Coding Layer BIT6",
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_CH,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Hierarchical Coding Layer Change",
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_SIGN_DATA_HIDING,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "HEVC Sign data hiding",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0, /* need to check defualt value */
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_GENERAL_PB_ENABLE,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "HEVC General pb enable",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0, /* need to check defualt value */
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_TEMPORAL_ID_ENABLE,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "HEVC Temporal id enable",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0, /* need to check defualt value */
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_STRONG_SMOTHING_FLAG,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "HEVC Strong intra smoothing flag",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0, /* need to check defualt value */
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_DISABLE_INTRA_PU_SPLIT,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "HEVC disable intra pu split",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0, /* need to check defualt value */
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_DISABLE_TMV_PREDICTION,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "HEVC disable tmv prediction",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0, /* need to check defualt value */
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_MAX_NUM_MERGE_MV_MINUS1,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "max number of candidate MVs",
+               .minimum = 0,
+               .maximum = 4,
+               .step = 1,
+               .default_value = 0, /* need to check defualt value */
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_WITHOUT_STARTCODE_ENABLE,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "ENC without startcode enable",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0, /* need to check defualt value */
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_REFRESH_PERIOD,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "HEVC Number of reference picture",
+               .minimum = 0,
+               .maximum = (1 << 16) - 1,
+               .step = 1,
+               .default_value = 0, /* need to check defualt value */
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LF_BETA_OFFSET_DIV2,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "HEVC loop filter beta offset",
+               .minimum = -6,
+               .maximum = 6,
+               .step = 1,
+               .default_value = 0, /* need to check defualt value */
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LF_TC_OFFSET_DIV2,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "HEVC loop filter tc offset",
+               .minimum = -6,
+               .maximum = 6,
+               .step = 1,
+               .default_value = 0, /* need to check defualt value */
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_SIZE_OF_LENGTH_FIELD,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "HEVC size of length field",
+               .minimum = 0,
+               .maximum = 3,
+               .step = 1,
+               .default_value = 0, /* need to check defualt value */
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_USER_REF,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "user long term reference frame",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0, /* need to check defualt value */
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_STORE_REF,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "store long term reference frame",
+               .minimum = 0,
+               .maximum = 2,
+               .step = 1,
+               .default_value = 0, /* need to check defualt value */
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC_GET_VERSION_INFO,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Get MFC version information",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC_GET_EXTRA_BUFFER_SIZE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Get extra buffer size",
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC_GET_EXT_INFO,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Get extra information",
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT0,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Hierarchical Coding Layer Bit0",
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT1,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Hierarchical Coding Layer Bit1",
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT2,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Hierarchical Coding Layer Bit2",
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT3,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Hierarchical Coding Layer Bit3",
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT4,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Hierarchical Coding Layer Bit4",
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT5,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Hierarchical Coding Layer Bit5",
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT6,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Hierarchical Coding Layer Bit6",
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_CH,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Hierarchical Coding Layer Change",
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_BIT0,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Hierarchical Coding Layer Bit0",
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_BIT1,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Hierarchical Coding Layer Bit1",
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_BIT2,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Hierarchical Coding Layer Bit2",
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_CH,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Hierarchical Coding Layer Change",
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC_H264_ENABLE_LTR,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Enable LTR",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC_H264_NUM_OF_LTR,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Number of LTR",
+               .minimum = 0,
+               .maximum = 4,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC_H264_MARK_LTR,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Set the frame as a LTRP",
+               .minimum = 0,
+               .maximum = 4,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC_H264_USE_LTR,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Specify a LTRP for encoding",
+               .minimum = 0,
+               .maximum = 0xF,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC_H264_BASE_PRIORITY,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Hierarchical Base Layer Priority",
+               .minimum = 0,
+               .maximum = (1 << 6) - 1 - 6,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC_CONFIG_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "QP control per each frame",
+               .minimum = -12,
+               .maximum = 255,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC_H264_VUI_RESTRICTION_ENABLE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "H264 vui generation enable",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_PREPEND_SPSPPS_TO_IDR,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Prepend SPS/PPS to every IDR",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_MFC_CONFIG_QP_ENABLE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "set dynamic qp controls",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_ROI_CONTROL,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Region-Of-Interest control",
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_ROI_ENABLE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Region-Of-Interest enable",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_MIN_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "H264 Min QP value for I frame",
+               .minimum = 0,
+               .maximum = 51,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_MAX_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "H264 Max QP value for I frame",
+               .minimum = 0,
+               .maximum = 51,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "HEVC Min QP value for I frame",
+               .minimum = -12,
+               .maximum = 51,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "HEVC Max QP value for I frame",
+               .minimum = 0,
+               .maximum = 51,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "MPEG4 Min QP value for I frame",
+               .minimum = 1,
+               .maximum = 31,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "MPEG4 Max QP value for I frame",
+               .minimum = 1,
+               .maximum = 31,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H263_MIN_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "H263 Min QP value for I frame",
+               .minimum = 1,
+               .maximum = 31,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H263_MAX_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "H263 Max QP value for I frame",
+               .minimum = 1,
+               .maximum = 31,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_VP8_MIN_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "VP8 Min QP value for I frame",
+               .minimum = 0,
+               .maximum = 127,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_VP8_MAX_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "VP8 Max QP value for I frame",
+               .minimum = 0,
+               .maximum = 127,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_VP9_MIN_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "VP9 Min QP value for I frame",
+               .minimum = 1,
+               .maximum = 255,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_VP9_MAX_QP,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "VP9 Max QP value for I frame",
+               .minimum = 1,
+               .maximum = 255,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_MIN_QP_P,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "H264 Min QP value for P frame",
+               .minimum = 0,
+               .maximum = 51,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_MAX_QP_P,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "H264 Max QP value for P frame",
+               .minimum = 0,
+               .maximum = 51,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_P,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "HEVC Min QP value for P frame",
+               .minimum = -12,
+               .maximum = 51,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_P,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "HEVC Max QP value for P frame",
+               .minimum = 0,
+               .maximum = 51,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_P,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "MPEG4 Min QP value for P frame",
+               .minimum = 1,
+               .maximum = 31,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_P,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "MPEG4 Max QP value for P frame",
+               .minimum = 1,
+               .maximum = 31,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H263_MIN_QP_P,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "H263 Min QP value for P frame",
+               .minimum = 1,
+               .maximum = 31,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H263_MAX_QP_P,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "H263 Max QP value for P frame",
+               .minimum = 1,
+               .maximum = 31,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_VP8_MIN_QP_P,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "VP8 Min QP value for P frame",
+               .minimum = 0,
+               .maximum = 127,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_VP8_MAX_QP_P,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "VP8 Max QP value for P frame",
+               .minimum = 0,
+               .maximum = 127,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_VP9_MIN_QP_P,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "VP9 Min QP value for P frame",
+               .minimum = 1,
+               .maximum = 255,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_VP9_MAX_QP_P,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "VP9 Max QP value for P frame",
+               .minimum = 1,
+               .maximum = 255,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_MIN_QP_B,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "H264 Min QP value for B frame",
+               .minimum = 0,
+               .maximum = 51,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_H264_MAX_QP_B,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "H264 Max QP value for B frame",
+               .minimum = 0,
+               .maximum = 51,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_B,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "HEVC Min QP value for B frame",
+               .minimum = -12,
+               .maximum = 51,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_B,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "HEVC Max QP value for B frame",
+               .minimum = 0,
+               .maximum = 51,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_B,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "MPEG4 Min QP value for B frame",
+               .minimum = 1,
+               .maximum = 31,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_B,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "MPEG4 Max QP value for B frame",
+               .minimum = 1,
+               .maximum = 31,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_RC_PVC_ENABLE,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "Perceptual Video Coding enable",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_TEMPORAL_SHORTTERM_MAX_LAYER,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Hierarchical Coding max layer",
+               .minimum = 0,
+               .maximum = 3,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_WEIGHTED_ENABLE,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "Weighted Prediction enable",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_YSUM,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "YSUM for weighted Prediction",
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_BPG_THUMBNAIL_SIZE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "BPG thumbnail size",
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_BPG_EXIF_SIZE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "BPG EXIF data size",
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_BPG_HEADER_SIZE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "BPG header size",
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_RATIO_OF_INTRA,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "ratio of intra encoded size",
+               .minimum = 15,
+               .maximum = 50,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_FULL_RANGE_FLAG,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Color range",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_COLOUR_PRIMARIES,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Colour primaries",
+               .minimum = 0,
+               .maximum = 10,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_TRANSFER_CHARACTERISTICS,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Transfer characteristics",
+               .minimum = 0,
+               .maximum = 17,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_MATRIX_COEFFICIENTS,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Matrix coefficients",
+               .minimum = 0,
+               .maximum = 10,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_HIERARCHICAL_BITRATE_CTRL,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "Hierarchical bitrate control",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 1,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_STATIC_INFO_ENABLE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Static info enable",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_SEI_MAX_PIC_AVERAGE_LIGHT,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Max pic average light",
+               .minimum = 0,
+               .maximum = 0xFFFF,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_SEI_MAX_CONTENT_LIGHT,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Max content light",
+               .minimum = 0,
+               .maximum = 0xFFFF,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_SEI_MAX_DISPLAY_LUMINANCE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Max display luminance",
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_SEI_MIN_DISPLAY_LUMINANCE,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Min display luminance",
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_SEI_WHITE_POINT,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "White point",
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_0,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Display primaries 0",
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_1,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Display primaries 1",
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+       {
+               .id = V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_2,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Display primaries 2",
+               .minimum = INT_MIN,
+               .maximum = INT_MAX,
+               .step = 1,
+               .default_value = 0,
+       },
+};
+
+#define NUM_CTRLS ARRAY_SIZE(controls)
+
+#endif /* __MFC_ENC_INTERNAL_H */
diff --git a/drivers/media/platform/exynos/mfc/mfc_enc_ops.c b/drivers/media/platform/exynos/mfc/mfc_enc_ops.c
new file mode 100644 (file)
index 0000000..b688e73
--- /dev/null
@@ -0,0 +1,1622 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_enc_ops.c
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include "mfc_common.h"
+
+#include "mfc_reg.h"
+
+static int mfc_enc_ctrl_read_cst(struct s5p_mfc_ctx *ctx,
+               struct s5p_mfc_buf_ctrl *buf_ctrl)
+{
+       int ret;
+       struct s5p_mfc_enc *enc = ctx->enc_priv;
+
+       switch (buf_ctrl->id) {
+       case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_STATUS:
+               ret = !enc->in_slice;
+               break;
+       default:
+               mfc_err_ctx("not support custom per-buffer control\n");
+               ret = -EINVAL;
+               break;
+       }
+
+       return ret;
+}
+
+static struct s5p_mfc_ctrl_cfg mfc_ctrl_list[] = {
+       {       /* set frame tag */
+               .type = MFC_CTRL_TYPE_SET,
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG,
+               .is_volatile = 1,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_PICTURE_TAG,
+               .mask = 0xFFFFFFFF,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_NONE,
+               .flag_addr = 0,
+               .flag_shft = 0,
+       },
+       {       /* get frame tag */
+               .type = MFC_CTRL_TYPE_GET_DST,
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG,
+               .is_volatile = 0,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_RET_PICTURE_TAG,
+               .mask = 0xFFFFFFFF,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_NONE,
+               .flag_addr = 0,
+               .flag_shft = 0,
+       },
+       {       /* encoded y physical addr */
+               .type = MFC_CTRL_TYPE_GET_DST,
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_LUMA_ADDR,
+               .is_volatile = 0,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_ENCODED_SOURCE_FIRST_ADDR,
+               .mask = 0xFFFFFFFF,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_NONE,
+               .flag_addr = 0,
+               .flag_shft = 0,
+       },
+       {       /* encoded c physical addr */
+               .type = MFC_CTRL_TYPE_GET_DST,
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_CHROMA_ADDR,
+               .is_volatile = 0,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_ENCODED_SOURCE_SECOND_ADDR,
+               .mask = 0xFFFFFFFF,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_NONE,
+               .flag_addr = 0,
+               .flag_shft = 0,
+       },
+       {       /* I, not coded frame insertion */
+               .type = MFC_CTRL_TYPE_SET,
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE,
+               .is_volatile = 1,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_FRAME_INSERTION,
+               .mask = 0x3,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_NONE,
+               .flag_addr = 0,
+               .flag_shft = 0,
+       },
+       {       /* I period change */
+               .type = MFC_CTRL_TYPE_SET,
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_I_PERIOD_CH,
+               .is_volatile = 1,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_GOP_CONFIG,
+               .mask = 0xFFFF,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_SFR,
+               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+               .flag_shft = 0,
+       },
+       {       /* frame rate change */
+               .type = MFC_CTRL_TYPE_SET,
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_RATE_CH,
+               .is_volatile = 1,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_RC_FRAME_RATE,
+               .mask = 0xFFFFFFFF,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_SFR,
+               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+               .flag_shft = 1,
+       },
+       {       /* bit rate change */
+               .type = MFC_CTRL_TYPE_SET,
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_BIT_RATE_CH,
+               .is_volatile = 1,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_RC_BIT_RATE,
+               .mask = 0xFFFFFFFF,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_SFR,
+               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+               .flag_shft = 2,
+       },
+       {       /* frame status (in slice or not) */
+               .type = MFC_CTRL_TYPE_GET_DST,
+               .id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_STATUS,
+               .is_volatile = 0,
+               .mode = MFC_CTRL_MODE_CST,
+               .addr = 0,
+               .mask = 0xFFFFFFFF,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_NONE,
+               .flag_addr = 0,
+               .flag_shft = 0,
+               .read_cst = mfc_enc_ctrl_read_cst,
+               .write_cst = NULL,
+       },
+       {       /* H.264 I frame QP Max change */
+               .type = MFC_CTRL_TYPE_SET,
+               .id = V4L2_CID_MPEG_VIDEO_H264_MAX_QP,
+               .is_volatile = 1,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_RC_QP_BOUND,
+               .mask = 0xFF,
+               .shft = 8,
+               .flag_mode = MFC_CTRL_MODE_SFR,
+               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+               .flag_shft = 4,
+       },
+       {       /* H.264 I frame QP Min change */
+               .type = MFC_CTRL_TYPE_SET,
+               .id = V4L2_CID_MPEG_VIDEO_H264_MIN_QP,
+               .is_volatile = 1,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_RC_QP_BOUND,
+               .mask = 0xFF,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_SFR,
+               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+               .flag_shft = 4,
+       },
+       {       /* H.263 I frame QP Max change */
+               .type = MFC_CTRL_TYPE_SET,
+               .id = V4L2_CID_MPEG_VIDEO_H263_MAX_QP,
+               .is_volatile = 1,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_RC_QP_BOUND,
+               .mask = 0xFF,
+               .shft = 8,
+               .flag_mode = MFC_CTRL_MODE_SFR,
+               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+               .flag_shft = 4,
+       },
+       {       /* H.263 I frame QP Min change */
+               .type = MFC_CTRL_TYPE_SET,
+               .id = V4L2_CID_MPEG_VIDEO_H263_MIN_QP,
+               .is_volatile = 1,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_RC_QP_BOUND,
+               .mask = 0xFF,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_SFR,
+               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+               .flag_shft = 4,
+       },
+       {       /* MPEG4 I frame QP Max change */
+               .type = MFC_CTRL_TYPE_SET,
+               .id = V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP,
+               .is_volatile = 1,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_RC_QP_BOUND,
+               .mask = 0xFF,
+               .shft = 8,
+               .flag_mode = MFC_CTRL_MODE_SFR,
+               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+               .flag_shft = 4,
+       },
+       {       /* MPEG4 I frame QP Min change */
+               .type = MFC_CTRL_TYPE_SET,
+               .id = V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP,
+               .is_volatile = 1,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_RC_QP_BOUND,
+               .mask = 0xFF,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_SFR,
+               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+               .flag_shft = 4,
+       },
+       {       /* VP8 I frame QP Max change */
+               .type = MFC_CTRL_TYPE_SET,
+               .id = V4L2_CID_MPEG_VIDEO_VP8_MAX_QP,
+               .is_volatile = 1,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_RC_QP_BOUND,
+               .mask = 0xFF,
+               .shft = 8,
+               .flag_mode = MFC_CTRL_MODE_SFR,
+               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+               .flag_shft = 4,
+       },
+       {       /* VP8 I frame QP Min change */
+               .type = MFC_CTRL_TYPE_SET,
+               .id = V4L2_CID_MPEG_VIDEO_VP8_MIN_QP,
+               .is_volatile = 1,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_RC_QP_BOUND,
+               .mask = 0xFF,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_SFR,
+               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+               .flag_shft = 4,
+       },
+       {       /* VP9 I frame QP Max change */
+               .type = MFC_CTRL_TYPE_SET,
+               .id = V4L2_CID_MPEG_VIDEO_VP9_MAX_QP,
+               .is_volatile = 1,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_RC_QP_BOUND,
+               .mask = 0xFF,
+               .shft = 8,
+               .flag_mode = MFC_CTRL_MODE_SFR,
+               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+               .flag_shft = 4,
+       },
+       {       /* VP9 I frame QP Min change */
+               .type = MFC_CTRL_TYPE_SET,
+               .id = V4L2_CID_MPEG_VIDEO_VP9_MIN_QP,
+               .is_volatile = 1,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_RC_QP_BOUND,
+               .mask = 0xFF,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_SFR,
+               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+               .flag_shft = 4,
+       },
+       {       /* HEVC I frame QP Max change */
+               .type = MFC_CTRL_TYPE_SET,
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP,
+               .is_volatile = 1,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_RC_QP_BOUND,
+               .mask = 0xFF,
+               .shft = 8,
+               .flag_mode = MFC_CTRL_MODE_SFR,
+               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+               .flag_shft = 4,
+       },
+       {       /* HEVC I frame QP Min change */
+               .type = MFC_CTRL_TYPE_SET,
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP,
+               .is_volatile = 1,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_RC_QP_BOUND,
+               .mask = 0xFF,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_SFR,
+               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+               .flag_shft = 4,
+       },
+       {       /* H.264 P frame QP Max change */
+               .type = MFC_CTRL_TYPE_SET,
+               .id = V4L2_CID_MPEG_VIDEO_H264_MAX_QP_P,
+               .is_volatile = 1,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
+               .mask = 0xFF,
+               .shft = 8,
+               .flag_mode = MFC_CTRL_MODE_SFR,
+               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+               .flag_shft = 4,
+       },
+       {       /* H.264 P frame QP Min change */
+               .type = MFC_CTRL_TYPE_SET,
+               .id = V4L2_CID_MPEG_VIDEO_H264_MIN_QP_P,
+               .is_volatile = 1,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
+               .mask = 0xFF,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_SFR,
+               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+               .flag_shft = 4,
+       },
+       {       /* H.263 P frame QP Max change */
+               .type = MFC_CTRL_TYPE_SET,
+               .id = V4L2_CID_MPEG_VIDEO_H263_MAX_QP_P,
+               .is_volatile = 1,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
+               .mask = 0xFF,
+               .shft = 8,
+               .flag_mode = MFC_CTRL_MODE_SFR,
+               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+               .flag_shft = 4,
+       },
+       {       /* H.263 P frame QP Min change */
+               .type = MFC_CTRL_TYPE_SET,
+               .id = V4L2_CID_MPEG_VIDEO_H263_MIN_QP_P,
+               .is_volatile = 1,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
+               .mask = 0xFF,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_SFR,
+               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+               .flag_shft = 4,
+       },
+       {       /* MPEG4 P frame QP Max change */
+               .type = MFC_CTRL_TYPE_SET,
+               .id = V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_P,
+               .is_volatile = 1,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
+               .mask = 0xFF,
+               .shft = 8,
+               .flag_mode = MFC_CTRL_MODE_SFR,
+               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+               .flag_shft = 4,
+       },
+       {       /* MPEG4 P frame QP Min change */
+               .type = MFC_CTRL_TYPE_SET,
+               .id = V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_P,
+               .is_volatile = 1,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
+               .mask = 0xFF,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_SFR,
+               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+               .flag_shft = 4,
+       },
+       {       /* VP8 P frame QP Max change */
+               .type = MFC_CTRL_TYPE_SET,
+               .id = V4L2_CID_MPEG_VIDEO_VP8_MAX_QP_P,
+               .is_volatile = 1,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
+               .mask = 0xFF,
+               .shft = 8,
+               .flag_mode = MFC_CTRL_MODE_SFR,
+               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+               .flag_shft = 4,
+       },
+       {       /* VP8 P frame QP Min change */
+               .type = MFC_CTRL_TYPE_SET,
+               .id = V4L2_CID_MPEG_VIDEO_VP8_MIN_QP_P,
+               .is_volatile = 1,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
+               .mask = 0xFF,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_SFR,
+               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+               .flag_shft = 4,
+       },
+       {       /* VP9 P frame QP Max change */
+               .type = MFC_CTRL_TYPE_SET,
+               .id = V4L2_CID_MPEG_VIDEO_VP9_MAX_QP_P,
+               .is_volatile = 1,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
+               .mask = 0xFF,
+               .shft = 8,
+               .flag_mode = MFC_CTRL_MODE_SFR,
+               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+               .flag_shft = 4,
+       },
+       {       /* VP9 P frame QP Min change */
+               .type = MFC_CTRL_TYPE_SET,
+               .id = V4L2_CID_MPEG_VIDEO_VP9_MIN_QP_P,
+               .is_volatile = 1,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
+               .mask = 0xFF,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_SFR,
+               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+               .flag_shft = 4,
+       },
+       {       /* HEVC P frame QP Max change */
+               .type = MFC_CTRL_TYPE_SET,
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_P,
+               .is_volatile = 1,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
+               .mask = 0xFF,
+               .shft = 8,
+               .flag_mode = MFC_CTRL_MODE_SFR,
+               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+               .flag_shft = 4,
+       },
+       {       /* HEVC P frame QP Min change */
+               .type = MFC_CTRL_TYPE_SET,
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_P,
+               .is_volatile = 1,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
+               .mask = 0xFF,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_SFR,
+               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+               .flag_shft = 4,
+       },
+       {       /* H.264 B frame QP Max change */
+               .type = MFC_CTRL_TYPE_SET,
+               .id = V4L2_CID_MPEG_VIDEO_H264_MAX_QP_B,
+               .is_volatile = 1,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
+               .mask = 0xFF,
+               .shft = 24,
+               .flag_mode = MFC_CTRL_MODE_SFR,
+               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+               .flag_shft = 4,
+       },
+       {       /* H.264 B frame QP Min change */
+               .type = MFC_CTRL_TYPE_SET,
+               .id = V4L2_CID_MPEG_VIDEO_H264_MIN_QP_B,
+               .is_volatile = 1,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
+               .mask = 0xFF,
+               .shft = 16,
+               .flag_mode = MFC_CTRL_MODE_SFR,
+               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+               .flag_shft = 4,
+       },
+       {       /* MPEG4 B frame QP Max change */
+               .type = MFC_CTRL_TYPE_SET,
+               .id = V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_B,
+               .is_volatile = 1,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
+               .mask = 0xFF,
+               .shft = 24,
+               .flag_mode = MFC_CTRL_MODE_SFR,
+               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+               .flag_shft = 4,
+       },
+       {       /* MPEG4 B frame QP Min change */
+               .type = MFC_CTRL_TYPE_SET,
+               .id = V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_B,
+               .is_volatile = 1,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
+               .mask = 0xFF,
+               .shft = 16,
+               .flag_mode = MFC_CTRL_MODE_SFR,
+               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+               .flag_shft = 4,
+       },
+       {       /* HEVC B frame QP Max change */
+               .type = MFC_CTRL_TYPE_SET,
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_B,
+               .is_volatile = 1,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
+               .mask = 0xFF,
+               .shft = 24,
+               .flag_mode = MFC_CTRL_MODE_SFR,
+               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+               .flag_shft = 4,
+       },
+       {       /* HEVC B frame QP Min change */
+               .type = MFC_CTRL_TYPE_SET,
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_B,
+               .is_volatile = 1,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
+               .mask = 0xFF,
+               .shft = 16,
+               .flag_mode = MFC_CTRL_MODE_SFR,
+               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+               .flag_shft = 4,
+       },
+       {       /* H.264 Dynamic Temporal Layer & bitrate change */
+               .type = MFC_CTRL_TYPE_SET,
+               .id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_CH,
+               .is_volatile = 1,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER0,
+               .mask = 0xFFFFFFFF,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_SFR,
+               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+               .flag_shft = 10,
+       },
+       {       /* HEVC Dynamic Temporal Layer & bitrate change */
+               .type = MFC_CTRL_TYPE_SET,
+               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_CH,
+               .is_volatile = 1,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER0,
+               .mask = 0xFFFFFFFF,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_SFR,
+               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+               .flag_shft = 10,
+       },
+       {       /* VP8 Dynamic Temporal Layer change */
+               .type = MFC_CTRL_TYPE_SET,
+               .id = V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_CH,
+               .is_volatile = 1,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER0,
+               .mask = 0xFFFFFFFF,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_SFR,
+               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+               .flag_shft = 10,
+       },
+       {       /* VP9 Dynamic Temporal Layer change */
+               .type = MFC_CTRL_TYPE_SET,
+               .id = V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_CH,
+               .is_volatile = 1,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER0,
+               .mask = 0xFFFFFFFF,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_SFR,
+               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+               .flag_shft = 10,
+       },
+       {       /* set level */
+               .type = MFC_CTRL_TYPE_SET,
+               .id = V4L2_CID_MPEG_VIDEO_H264_LEVEL,
+               .is_volatile = 1,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_PICTURE_PROFILE,
+               .mask = 0x000000FF,
+               .shft = 8,
+               .flag_mode = MFC_CTRL_MODE_SFR,
+               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+               .flag_shft = 5,
+       },
+       {       /* set profile */
+               .type = MFC_CTRL_TYPE_SET,
+               .id = V4L2_CID_MPEG_VIDEO_H264_PROFILE,
+               .is_volatile = 1,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_PICTURE_PROFILE,
+               .mask = 0x0000000F,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_SFR,
+               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+               .flag_shft = 5,
+       },
+       {       /* set store LTR */
+               .type = MFC_CTRL_TYPE_SET,
+               .id = V4L2_CID_MPEG_MFC_H264_MARK_LTR,
+               .is_volatile = 1,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_H264_NAL_CONTROL,
+               .mask = 0x00000003,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_NONE,
+               .flag_addr = 0,
+               .flag_shft = 0,
+       },
+       {       /* set use LTR */
+               .type = MFC_CTRL_TYPE_SET,
+               .id = V4L2_CID_MPEG_MFC_H264_USE_LTR,
+               .is_volatile = 1,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_H264_NAL_CONTROL,
+               .mask = 0x00000003,
+               .shft = 2,
+               .flag_mode = MFC_CTRL_MODE_NONE,
+               .flag_addr = 0,
+               .flag_shft = 0,
+       },
+       {       /* set base layer priority */
+               .type = MFC_CTRL_TYPE_SET,
+               .id = V4L2_CID_MPEG_MFC_H264_BASE_PRIORITY,
+               .is_volatile = 1,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_H264_HD_SVC_EXTENSION_0,
+               .mask = 0x0000003F,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_SFR,
+               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+               .flag_shft = 12,
+       },
+       {       /* set QP per each frame */
+               .type = MFC_CTRL_TYPE_SET,
+               .id = V4L2_CID_MPEG_MFC_CONFIG_QP,
+               .is_volatile = 1,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_FIXED_PICTURE_QP,
+               .mask = 0x000000FF,
+               .shft = 24,
+               .flag_mode = MFC_CTRL_MODE_NONE,
+               .flag_addr = 0,
+               .flag_shft = 0,
+       },
+       {       /* Region-Of-Interest control */
+               .type = MFC_CTRL_TYPE_SET,
+               .id = V4L2_CID_MPEG_VIDEO_ROI_CONTROL,
+               .is_volatile = 1,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_RC_ROI_CTRL,
+               .mask = 0xFFFFFFFF,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_NONE,
+               .flag_addr = 0,
+               .flag_shft = 0,
+       },
+       {       /* set YSUM for weighted prediction */
+               .type = MFC_CTRL_TYPE_SET,
+               .id = V4L2_CID_MPEG_VIDEO_YSUM,
+               .is_volatile = 1,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_WEIGHT_FOR_WEIGHTED_PREDICTION,
+               .mask = 0xFFFFFFFF,
+               .shft = 0,
+               .flag_mode = MFC_CTRL_MODE_NONE,
+               .flag_mode = 0,
+               .flag_shft = 0,
+       },
+       {       /* set base layer priority */
+               .type = MFC_CTRL_TYPE_SET,
+               .id = V4L2_CID_MPEG_VIDEO_RATIO_OF_INTRA,
+               .is_volatile = 1,
+               .mode = MFC_CTRL_MODE_SFR,
+               .addr = S5P_FIMV_E_RC_MODE,
+               .mask = 0x000000FF,
+               .shft = 8,
+               .flag_mode = MFC_CTRL_MODE_SFR,
+               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
+               .flag_shft = 13,
+       }
+};
+
+#define NUM_CTRL_CFGS ARRAY_SIZE(mfc_ctrl_list)
+
+static int s5p_mfc_enc_cleanup_ctx_ctrls(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_ctx_ctrl *ctx_ctrl;
+
+       while (!list_empty(&ctx->ctrls)) {
+               ctx_ctrl = list_entry((&ctx->ctrls)->next,
+                                     struct s5p_mfc_ctx_ctrl, list);
+               list_del(&ctx_ctrl->list);
+               kfree(ctx_ctrl);
+       }
+
+       INIT_LIST_HEAD(&ctx->ctrls);
+
+       return 0;
+}
+
+static int s5p_mfc_enc_get_buf_update_val(struct s5p_mfc_ctx *ctx,
+                       struct list_head *head, unsigned int id, int value)
+{
+       struct s5p_mfc_buf_ctrl *buf_ctrl;
+
+       list_for_each_entry(buf_ctrl, head, list) {
+               if (buf_ctrl->id == id) {
+                       buf_ctrl->val = value;
+                       mfc_debug(6, "[CTRLS] Update buffer control id: 0x%08x, val: %d\n",
+                                       buf_ctrl->id, buf_ctrl->val);
+                       break;
+               }
+       }
+
+       return 0;
+}
+
+static int s5p_mfc_enc_init_ctx_ctrls(struct s5p_mfc_ctx *ctx)
+{
+       unsigned long i;
+       struct s5p_mfc_ctx_ctrl *ctx_ctrl;
+
+       INIT_LIST_HEAD(&ctx->ctrls);
+
+       for (i = 0; i < NUM_CTRL_CFGS; i++) {
+               ctx_ctrl = kzalloc(sizeof(struct s5p_mfc_ctx_ctrl), GFP_KERNEL);
+               if (ctx_ctrl == NULL) {
+                       mfc_err_dev("Failed to allocate context control "\
+                                       "id: 0x%08x, type: %d\n",
+                                       mfc_ctrl_list[i].id,
+                                       mfc_ctrl_list[i].type);
+
+                       s5p_mfc_enc_cleanup_ctx_ctrls(ctx);
+
+                       return -ENOMEM;
+               }
+
+               ctx_ctrl->type = mfc_ctrl_list[i].type;
+               ctx_ctrl->id = mfc_ctrl_list[i].id;
+               ctx_ctrl->has_new = 0;
+               ctx_ctrl->val = 0;
+
+               list_add_tail(&ctx_ctrl->list, &ctx->ctrls);
+       }
+
+       return 0;
+}
+
+static void s5p_mfc_enc_reset_buf_ctrls(struct list_head *head)
+{
+       struct s5p_mfc_buf_ctrl *buf_ctrl;
+
+       list_for_each_entry(buf_ctrl, head, list) {
+               buf_ctrl->has_new = 0;
+               buf_ctrl->val = 0;
+               buf_ctrl->old_val = 0;
+               buf_ctrl->updated = 0;
+       }
+}
+
+static void mfc_enc_remove_buf_ctrls(struct list_head *head)
+{
+       struct s5p_mfc_buf_ctrl *buf_ctrl;
+
+       while (!list_empty(head)) {
+               buf_ctrl = list_entry(head->next,
+                               struct s5p_mfc_buf_ctrl, list);
+               list_del(&buf_ctrl->list);
+               kfree(buf_ctrl);
+       }
+
+       INIT_LIST_HEAD(head);
+}
+
+static int s5p_mfc_enc_init_buf_ctrls(struct s5p_mfc_ctx *ctx,
+       enum s5p_mfc_ctrl_type type, unsigned int index)
+{
+       unsigned long i;
+       struct s5p_mfc_buf_ctrl *buf_ctrl;
+       struct list_head *head;
+
+       if (index >= MFC_MAX_BUFFERS) {
+               mfc_err_dev("Per-buffer control index is out of range\n");
+               return -EINVAL;
+       }
+
+       if (type & MFC_CTRL_TYPE_SRC) {
+               if (test_bit(index, &ctx->src_ctrls_avail)) {
+                       s5p_mfc_enc_reset_buf_ctrls(&ctx->src_ctrls[index]);
+
+                       return 0;
+               }
+
+               head = &ctx->src_ctrls[index];
+       } else if (type & MFC_CTRL_TYPE_DST) {
+               if (test_bit(index, &ctx->dst_ctrls_avail)) {
+                       s5p_mfc_enc_reset_buf_ctrls(&ctx->dst_ctrls[index]);
+
+                       return 0;
+               }
+
+               head = &ctx->dst_ctrls[index];
+       } else {
+               mfc_err_dev("Control type mismatch. type : %d\n", type);
+               return -EINVAL;
+       }
+
+       INIT_LIST_HEAD(head);
+
+       for (i = 0; i < NUM_CTRL_CFGS; i++) {
+               if (!(type & mfc_ctrl_list[i].type))
+                       continue;
+
+               buf_ctrl = kzalloc(sizeof(struct s5p_mfc_buf_ctrl), GFP_KERNEL);
+               if (buf_ctrl == NULL) {
+                       mfc_err_dev("Failed to allocate buffer control "\
+                                       "id: 0x%08x, type: %d\n",
+                                       mfc_ctrl_list[i].id,
+                                       mfc_ctrl_list[i].type);
+
+                       mfc_enc_remove_buf_ctrls(head);
+
+                       return -ENOMEM;
+               }
+
+               buf_ctrl->type = mfc_ctrl_list[i].type;
+               buf_ctrl->id = mfc_ctrl_list[i].id;
+               buf_ctrl->is_volatile = mfc_ctrl_list[i].is_volatile;
+               buf_ctrl->mode = mfc_ctrl_list[i].mode;
+               buf_ctrl->addr = mfc_ctrl_list[i].addr;
+               buf_ctrl->mask = mfc_ctrl_list[i].mask;
+               buf_ctrl->shft = mfc_ctrl_list[i].shft;
+               buf_ctrl->flag_mode = mfc_ctrl_list[i].flag_mode;
+               buf_ctrl->flag_addr = mfc_ctrl_list[i].flag_addr;
+               buf_ctrl->flag_shft = mfc_ctrl_list[i].flag_shft;
+               if (buf_ctrl->mode == MFC_CTRL_MODE_CST) {
+                       buf_ctrl->read_cst = mfc_ctrl_list[i].read_cst;
+                       buf_ctrl->write_cst = mfc_ctrl_list[i].write_cst;
+               }
+
+               list_add_tail(&buf_ctrl->list, head);
+       }
+
+       s5p_mfc_enc_reset_buf_ctrls(head);
+
+       if (type & MFC_CTRL_TYPE_SRC)
+               set_bit(index, &ctx->src_ctrls_avail);
+       else
+               set_bit(index, &ctx->dst_ctrls_avail);
+
+       return 0;
+}
+
+static int s5p_mfc_enc_cleanup_buf_ctrls(struct s5p_mfc_ctx *ctx,
+       enum s5p_mfc_ctrl_type type, unsigned int index)
+{
+       struct list_head *head;
+
+       if (index >= MFC_MAX_BUFFERS) {
+               mfc_err_dev("Per-buffer control index is out of range\n");
+               return -EINVAL;
+       }
+
+       if (type & MFC_CTRL_TYPE_SRC) {
+               if (!(test_and_clear_bit(index, &ctx->src_ctrls_avail))) {
+                       return 0;
+               }
+
+               head = &ctx->src_ctrls[index];
+       } else if (type & MFC_CTRL_TYPE_DST) {
+               if (!(test_and_clear_bit(index, &ctx->dst_ctrls_avail))) {
+                       return 0;
+               }
+
+               head = &ctx->dst_ctrls[index];
+       } else {
+               mfc_err_dev("Control type mismatch. type : %d\n", type);
+               return -EINVAL;
+       }
+
+       mfc_enc_remove_buf_ctrls(head);
+
+       return 0;
+}
+
+static int s5p_mfc_enc_to_buf_ctrls(struct s5p_mfc_ctx *ctx, struct list_head *head)
+{
+       struct s5p_mfc_ctx_ctrl *ctx_ctrl;
+       struct s5p_mfc_buf_ctrl *buf_ctrl;
+       struct s5p_mfc_enc *enc = ctx->enc_priv;
+       int index = 0;
+       unsigned int reg = 0;
+
+       list_for_each_entry(ctx_ctrl, &ctx->ctrls, list) {
+               if (!(ctx_ctrl->type & MFC_CTRL_TYPE_SET) || !ctx_ctrl->has_new)
+                       continue;
+
+               list_for_each_entry(buf_ctrl, head, list) {
+                       if (!(buf_ctrl->type & MFC_CTRL_TYPE_SET))
+                               continue;
+
+                       if (buf_ctrl->id == ctx_ctrl->id) {
+                               buf_ctrl->has_new = 1;
+                               buf_ctrl->val = ctx_ctrl->val;
+                               if (buf_ctrl->is_volatile)
+                                       buf_ctrl->updated = 0;
+
+                               ctx_ctrl->has_new = 0;
+                               if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_ROI_CONTROL) {
+                                       index = enc->roi_index;
+                                       if (enc->roi_info[index].enable) {
+                                               enc->roi_index =
+                                                       (index + 1) % MFC_MAX_EXTRA_BUF;
+                                               reg |= enc->roi_info[index].enable;
+                                               reg &= ~(0xFF << 8);
+                                               reg |= (enc->roi_info[index].lower_qp << 8);
+                                               reg &= ~(0xFFFF << 16);
+                                               reg |= (enc->roi_info[index].upper_qp << 16);
+                                               mfc_debug(3, "[ROI] buffer[%d] en %d, "\
+                                                               "QP lower %d upper %d reg %#x\n",
+                                                               index, enc->roi_info[index].enable,
+                                                               enc->roi_info[index].lower_qp,
+                                                               enc->roi_info[index].upper_qp,
+                                                               reg);
+                                       } else {
+                                               mfc_debug(3, "[ROI] buffer[%d] is not enabled\n", index);
+                                       }
+                                       buf_ctrl->val = reg;
+                                       buf_ctrl->old_val2 = index;
+                               }
+                               break;
+                       }
+               }
+       }
+
+       return 0;
+}
+
+static int s5p_mfc_enc_to_ctx_ctrls(struct s5p_mfc_ctx *ctx, struct list_head *head)
+{
+       struct s5p_mfc_ctx_ctrl *ctx_ctrl;
+       struct s5p_mfc_buf_ctrl *buf_ctrl;
+
+       list_for_each_entry(buf_ctrl, head, list) {
+               if (!(buf_ctrl->type & MFC_CTRL_TYPE_GET) || !buf_ctrl->has_new)
+                       continue;
+
+               list_for_each_entry(ctx_ctrl, &ctx->ctrls, list) {
+                       if (!(ctx_ctrl->type & MFC_CTRL_TYPE_GET))
+                               continue;
+
+                       if (ctx_ctrl->id == buf_ctrl->id) {
+                               if (ctx_ctrl->has_new)
+                                       mfc_debug(8,
+                                       "Overwrite context control "\
+                                       "value id: 0x%08x, val: %d\n",
+                                               ctx_ctrl->id, ctx_ctrl->val);
+
+                               ctx_ctrl->has_new = 1;
+                               ctx_ctrl->val = buf_ctrl->val;
+
+                               buf_ctrl->has_new = 0;
+                       }
+               }
+       }
+
+       return 0;
+}
+
+static void mfc_enc_set_buf_ctrls_temporal_svc(struct s5p_mfc_ctx *ctx,
+                       struct s5p_mfc_buf_ctrl *buf_ctrl)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc *enc = ctx->enc_priv;
+       unsigned int value = 0, value2 = 0;
+       struct temporal_layer_info temporal_LC;
+       unsigned int i;
+       struct s5p_mfc_enc_params *p = &enc->params;
+
+       if (buf_ctrl->id
+               == V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_CH ||
+               buf_ctrl->id
+               == V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_CH ||
+               buf_ctrl->id
+               == V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_CH ||
+               buf_ctrl->id
+               == V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_CH) {
+               memcpy(&temporal_LC,
+                       enc->sh_handle_svc.vaddr, sizeof(struct temporal_layer_info));
+
+               if(((temporal_LC.temporal_layer_count & 0x7) < 1) ||
+                       ((temporal_LC.temporal_layer_count > 3) && IS_VP8_ENC(ctx)) ||
+                       ((temporal_LC.temporal_layer_count > 3) && IS_VP9_ENC(ctx))) {
+                       /* clear NUM_T_LAYER_CHANGE */
+                       value = MFC_READL(buf_ctrl->flag_addr);
+                       value &= ~(1 << 10);
+                       MFC_WRITEL(value, buf_ctrl->flag_addr);
+                       mfc_err_ctx("[HIERARCHICAL] layer count is invalid : %d\n",
+                                       temporal_LC.temporal_layer_count);
+                       return;
+               }
+
+               if (IS_H264_ENC(ctx))
+                       p->codec.h264.num_hier_layer = temporal_LC.temporal_layer_count & 0x7;
+
+               /* enable RC_BIT_RATE_CHANGE */
+               value = MFC_READL(buf_ctrl->flag_addr);
+               if (temporal_LC.temporal_layer_bitrate[0] > 0 || p->hier_bitrate_ctrl)
+                       /* set RC_BIT_RATE_CHANGE */
+                       value |= (1 << 2);
+               else
+                       /* clear RC_BIT_RATE_CHANGE */
+                       value &= ~(1 << 2);
+               MFC_WRITEL(value, buf_ctrl->flag_addr);
+
+               mfc_debug(3, "[HIERARCHICAL] layer count %d, E_PARAM_CHANGE %#x\n",
+                               temporal_LC.temporal_layer_count & 0x7, value);
+
+               value = MFC_READL(S5P_FIMV_E_NUM_T_LAYER);
+               buf_ctrl->old_val2 = value;
+               value &= ~(0x7);
+               value |= (temporal_LC.temporal_layer_count & 0x7);
+               value &= ~(0x1 << 8);
+               value |= (p->hier_bitrate_ctrl & 0x1) << 8;
+               MFC_WRITEL(value, S5P_FIMV_E_NUM_T_LAYER);
+               mfc_debug(3, "[HIERARCHICAL] E_NUM_T_LAYER %#x\n", value);
+               for (i = 0; i < (temporal_LC.temporal_layer_count & 0x7); i++) {
+                       mfc_debug(3, "[HIERARCHICAL] layer bitrate[%d] %d (FW ctrl: %d)\n",
+                                       i, temporal_LC.temporal_layer_bitrate[i], p->hier_bitrate_ctrl);
+                       MFC_WRITEL(temporal_LC.temporal_layer_bitrate[i],
+                                       buf_ctrl->addr + i * 4);
+               }
+               /* priority change */
+               if (IS_H264_ENC(ctx)) {
+                       value = 0;
+                       value2 = 0;
+                       for (i = 0; i < (p->codec.h264.num_hier_layer & 0x07); i++) {
+                               if (i <= 4)
+                                       value |= ((p->codec.h264.base_priority & 0x3F) + i)
+                                               << (6 * i);
+                               else
+                                       value2 |= ((p->codec.h264.base_priority & 0x3F) + i)
+                                               << (6 * (i - 5));
+                       }
+                       MFC_WRITEL(value, S5P_FIMV_E_H264_HD_SVC_EXTENSION_0);
+                       MFC_WRITEL(value2, S5P_FIMV_E_H264_HD_SVC_EXTENSION_1);
+                       mfc_debug(3, "[HIERARCHICAL] EXTENSION0 %#x, EXTENSION1 %#x\n",
+                                       value, value2);
+
+                       value = MFC_READL(buf_ctrl->flag_addr);
+                       value |= (1 << 12);
+                       MFC_WRITEL(value, buf_ctrl->flag_addr);
+                       mfc_debug(3, "[HIERARCHICAL] E_PARAM_CHANGE %#x\n", value);
+               }
+
+       }
+
+       /* temproral layer priority */
+       if (buf_ctrl->id == V4L2_CID_MPEG_MFC_H264_BASE_PRIORITY) {
+               value = MFC_READL(S5P_FIMV_E_H264_HD_SVC_EXTENSION_0);
+               buf_ctrl->old_val |= value & 0x3FFFFFC0;
+               value &= ~(0x3FFFFFC0);
+               value2 = MFC_READL(S5P_FIMV_E_H264_HD_SVC_EXTENSION_1);
+               buf_ctrl->old_val2 = value2 & 0x0FFF;
+               value2 &= ~(0x0FFF);
+               for (i = 0; i < (p->codec.h264.num_hier_layer & 0x07); i++) {
+                       if (i <= 4)
+                               value |= ((buf_ctrl->val & 0x3F) + i) << (6 * i);
+                       else
+                               value2 |= ((buf_ctrl->val & 0x3F) + i) << (6 * (i - 5));
+               }
+               MFC_WRITEL(value, S5P_FIMV_E_H264_HD_SVC_EXTENSION_0);
+               MFC_WRITEL(value2, S5P_FIMV_E_H264_HD_SVC_EXTENSION_1);
+               p->codec.h264.base_priority = buf_ctrl->val;
+               mfc_debug(3, "[HIERARCHICAL] EXTENSION0 %#x, EXTENSION1 %#x\n",
+                               value, value2);
+       }
+}
+
+static void mfc_enc_set_buf_ctrls_exception(struct s5p_mfc_ctx *ctx,
+                       struct s5p_mfc_buf_ctrl *buf_ctrl)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc *enc = ctx->enc_priv;
+       struct s5p_mfc_enc_params *p = &enc->params;
+       unsigned int value = 0;
+
+       if (buf_ctrl->id == V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG)
+               enc->stored_tag = buf_ctrl->val;
+
+       /* temporal layer setting */
+       mfc_enc_set_buf_ctrls_temporal_svc(ctx, buf_ctrl);
+
+       if (buf_ctrl->id == V4L2_CID_MPEG_MFC_H264_MARK_LTR) {
+               value = MFC_READL(S5P_FIMV_E_H264_NAL_CONTROL);
+               buf_ctrl->old_val2 = (value >> 8) & 0x7;
+               value &= ~(0x7 << 8);
+               value |= (buf_ctrl->val & 0x7) << 8;
+               MFC_WRITEL(value, S5P_FIMV_E_H264_NAL_CONTROL);
+       }
+       if (buf_ctrl->id == V4L2_CID_MPEG_MFC_H264_USE_LTR) {
+               value = MFC_READL(S5P_FIMV_E_H264_NAL_CONTROL);
+               buf_ctrl->old_val2 = (value >> 11) & 0xF;
+               value &= ~(0xF << 11);
+               value |= (buf_ctrl->val & 0xF) << 11;
+               MFC_WRITEL(value, S5P_FIMV_E_H264_NAL_CONTROL);
+       }
+
+       if (buf_ctrl->id == V4L2_CID_MPEG_MFC51_VIDEO_I_PERIOD_CH) {
+               value = MFC_READL(S5P_FIMV_E_GOP_CONFIG2);
+               buf_ctrl->old_val |= (value << 16) & 0x3FFF0000;
+               value &= ~(0x3FFF);
+               value |= (buf_ctrl->val >> 16) & 0x3FFF;
+               MFC_WRITEL(value, S5P_FIMV_E_GOP_CONFIG2);
+       }
+
+       /* PROFILE & LEVEL have to be set up together */
+       if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_H264_LEVEL) {
+               value = MFC_READL(S5P_FIMV_E_PICTURE_PROFILE);
+               buf_ctrl->old_val |= (value & 0x000F) << 8;
+               value &= ~(0x000F);
+               value |= p->codec.h264.profile & 0x000F;
+               MFC_WRITEL(value, S5P_FIMV_E_PICTURE_PROFILE);
+               p->codec.h264.level = buf_ctrl->val;
+       }
+
+       if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_H264_PROFILE) {
+               value = MFC_READL(S5P_FIMV_E_PICTURE_PROFILE);
+               buf_ctrl->old_val |= value & 0xFF00;
+               value &= ~(0x00FF << 8);
+               value |= (p->codec.h264.level << 8) & 0xFF00;
+               MFC_WRITEL(value, S5P_FIMV_E_PICTURE_PROFILE);
+               p->codec.h264.profile = buf_ctrl->val;
+       }
+
+       /* per buffer QP setting change */
+       if (buf_ctrl->id == V4L2_CID_MPEG_MFC_CONFIG_QP)
+               p->config_qp = buf_ctrl->val;
+
+       /* set the ROI buffer DVA */
+       if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_ROI_CONTROL) {
+               MFC_WRITEL(enc->roi_buf[buf_ctrl->old_val2].daddr,
+                               S5P_FIMV_E_ROI_BUFFER_ADDR);
+               mfc_debug(3, "[ROI] buffer[%d] addr %#llx, QP val: %#x\n",
+                               buf_ctrl->old_val2,
+                               enc->roi_buf[buf_ctrl->old_val2].daddr,
+                               buf_ctrl->val);
+       }
+}
+
+static int s5p_mfc_enc_set_buf_ctrls_val(struct s5p_mfc_ctx *ctx, struct list_head *head)
+{
+       struct s5p_mfc_buf_ctrl *buf_ctrl;
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc *enc = ctx->enc_priv;
+       unsigned int value = 0;
+       struct s5p_mfc_enc_params *p = &enc->params;
+
+       list_for_each_entry(buf_ctrl, head, list) {
+               if (!(buf_ctrl->type & MFC_CTRL_TYPE_SET) || !buf_ctrl->has_new)
+                       continue;
+
+               /* read old vlaue */
+               value = MFC_READL(buf_ctrl->addr);
+
+               /* save old value for recovery */
+               if (buf_ctrl->is_volatile)
+                       buf_ctrl->old_val = (value >> buf_ctrl->shft) & buf_ctrl->mask;
+
+               /* write new value */
+               value &= ~(buf_ctrl->mask << buf_ctrl->shft);
+               value |= ((buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft);
+               MFC_WRITEL(value, buf_ctrl->addr);
+
+               /* set change flag bit */
+               if (buf_ctrl->flag_mode == MFC_CTRL_MODE_SFR) {
+                       value = MFC_READL(buf_ctrl->flag_addr);
+                       value |= (1 << buf_ctrl->flag_shft);
+                       MFC_WRITEL(value, buf_ctrl->flag_addr);
+               }
+
+               buf_ctrl->has_new = 0;
+               buf_ctrl->updated = 1;
+
+               mfc_enc_set_buf_ctrls_exception(ctx, buf_ctrl);
+
+               mfc_debug(6, "[CTRLS] Set buffer control id: 0x%08x, val: %d\n",
+                               buf_ctrl->id, buf_ctrl->val);
+       }
+
+       if (!p->rc_frame && !p->rc_mb && p->dynamic_qp) {
+               value = MFC_READL(S5P_FIMV_E_FIXED_PICTURE_QP);
+               value &= ~(0xFF000000);
+               value |= (p->config_qp & 0xFF) << 24;
+               MFC_WRITEL(value, S5P_FIMV_E_FIXED_PICTURE_QP);
+               mfc_debug(6, "[CTRLS] Dynamic QP changed %#x\n",
+                               MFC_READL(S5P_FIMV_E_FIXED_PICTURE_QP));
+       }
+
+       return 0;
+}
+
+static int s5p_mfc_enc_get_buf_ctrls_val(struct s5p_mfc_ctx *ctx, struct list_head *head)
+{
+       struct s5p_mfc_buf_ctrl *buf_ctrl;
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned int value = 0;
+
+       list_for_each_entry(buf_ctrl, head, list) {
+               if (!(buf_ctrl->type & MFC_CTRL_TYPE_GET))
+                       continue;
+
+               if (buf_ctrl->mode == MFC_CTRL_MODE_SFR)
+                       value = MFC_READL(buf_ctrl->addr);
+               else if (buf_ctrl->mode == MFC_CTRL_MODE_CST)
+                       value = call_bop(buf_ctrl, read_cst, ctx, buf_ctrl);
+
+               value = (value >> buf_ctrl->shft) & buf_ctrl->mask;
+
+               buf_ctrl->val = value;
+               buf_ctrl->has_new = 1;
+
+               mfc_debug(6, "[CTRLS] Get buffer control id: 0x%08x, val: %d\n",
+                               buf_ctrl->id, buf_ctrl->val);
+       }
+
+       return 0;
+}
+
+static int s5p_mfc_enc_set_buf_ctrls_val_nal_q_enc(struct s5p_mfc_ctx *ctx,
+                       struct list_head *head, EncoderInputStr *pInStr)
+{
+       struct s5p_mfc_buf_ctrl *buf_ctrl;
+       struct s5p_mfc_enc *enc = ctx->enc_priv;
+       struct temporal_layer_info temporal_LC;
+       unsigned int i, param_change;
+       struct s5p_mfc_enc_params *p = &enc->params;
+
+       mfc_debug_enter();
+
+       list_for_each_entry(buf_ctrl, head, list) {
+               if (!(buf_ctrl->type & MFC_CTRL_TYPE_SET) || !buf_ctrl->has_new)
+                       continue;
+               param_change = 0;
+               switch (buf_ctrl->id) {
+               case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG:
+                       pInStr->PictureTag &= ~(buf_ctrl->mask << buf_ctrl->shft);
+                       pInStr->PictureTag |=
+                               (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
+                       enc->stored_tag = buf_ctrl->val;
+                       break;
+               case V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE:
+                       pInStr->FrameInsertion &= ~(buf_ctrl->mask << buf_ctrl->shft);
+                       pInStr->FrameInsertion |=
+                               (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
+                       break;
+               case V4L2_CID_MPEG_MFC51_VIDEO_I_PERIOD_CH:
+                       pInStr->GopConfig &= ~(buf_ctrl->mask << buf_ctrl->shft);
+                       pInStr->GopConfig |=
+                               (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
+                       pInStr->GopConfig2 &= ~(0x3FFF);
+                       pInStr->GopConfig2 |= (buf_ctrl->val >> 16) & 0x3FFF;
+                       param_change = 1;
+                       break;
+               case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_RATE_CH:
+                       pInStr->RcFrameRate &= ~(buf_ctrl->mask << buf_ctrl->shft);
+                       pInStr->RcFrameRate |=
+                               (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
+                       param_change = 1;
+                       break;
+               case V4L2_CID_MPEG_MFC51_VIDEO_BIT_RATE_CH:
+                       pInStr->RcBitRate &= ~(buf_ctrl->mask << buf_ctrl->shft);
+                       pInStr->RcBitRate |=
+                               (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
+                       param_change = 1;
+                       break;
+               case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:
+               case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP:
+               case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP:
+               case V4L2_CID_MPEG_VIDEO_H263_MAX_QP:
+               case V4L2_CID_MPEG_VIDEO_VP8_MAX_QP:
+               case V4L2_CID_MPEG_VIDEO_VP9_MAX_QP:
+               case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:
+               case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP:
+               case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP:
+               case V4L2_CID_MPEG_VIDEO_H263_MIN_QP:
+               case V4L2_CID_MPEG_VIDEO_VP8_MIN_QP:
+               case V4L2_CID_MPEG_VIDEO_VP9_MIN_QP:
+                       pInStr->RcQpBound &= ~(buf_ctrl->mask << buf_ctrl->shft);
+                       pInStr->RcQpBound |=
+                               (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
+                       param_change = 1;
+                       break;
+               case V4L2_CID_MPEG_VIDEO_H264_MAX_QP_P:
+               case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_P:
+               case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_P:
+               case V4L2_CID_MPEG_VIDEO_H263_MAX_QP_P:
+               case V4L2_CID_MPEG_VIDEO_VP8_MAX_QP_P:
+               case V4L2_CID_MPEG_VIDEO_VP9_MAX_QP_P:
+               case V4L2_CID_MPEG_VIDEO_H264_MIN_QP_P:
+               case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_P:
+               case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_P:
+               case V4L2_CID_MPEG_VIDEO_H263_MIN_QP_P:
+               case V4L2_CID_MPEG_VIDEO_VP8_MIN_QP_P:
+               case V4L2_CID_MPEG_VIDEO_VP9_MIN_QP_P:
+               case V4L2_CID_MPEG_VIDEO_H264_MAX_QP_B:
+               case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_B:
+               case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_B:
+               case V4L2_CID_MPEG_VIDEO_H264_MIN_QP_B:
+               case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_B:
+               case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_B:
+                       pInStr->RcQpBoundPb &= ~(buf_ctrl->mask << buf_ctrl->shft);
+                       pInStr->RcQpBoundPb |=
+                               (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
+                       param_change = 1;
+                       break;
+               case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_CH:
+               case V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_CH:
+               case V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_CH:
+               case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_CH:
+                       memcpy(&temporal_LC,
+                               enc->sh_handle_svc.vaddr, sizeof(struct temporal_layer_info));
+
+                       if (((temporal_LC.temporal_layer_count & 0x7) < 1) ||
+                               ((temporal_LC.temporal_layer_count > 3) && IS_VP8_ENC(ctx)) ||
+                               ((temporal_LC.temporal_layer_count > 3) && IS_VP9_ENC(ctx))) {
+                               /* claer NUM_T_LAYER_CHANGE */
+                               mfc_err_ctx("[NALQ][HIERARCHICAL] layer count(%d) is invalid\n",
+                                               temporal_LC.temporal_layer_count);
+                               return 0;
+                       }
+
+                       if (IS_H264_ENC(ctx))
+                               p->codec.h264.num_hier_layer =
+                                       temporal_LC.temporal_layer_count & 0x7;
+
+                       /* enable RC_BIT_RATE_CHANGE */
+                       if (temporal_LC.temporal_layer_bitrate[0] > 0 || p->hier_bitrate_ctrl)
+                               pInStr->ParamChange |= (1 << 2);
+                       else
+                               pInStr->ParamChange &= ~(1 << 2);
+
+                       /* enalbe NUM_T_LAYER_CHANGE */
+                       if (temporal_LC.temporal_layer_count & 0x7)
+                               pInStr->ParamChange |= (1 << 10);
+                       else
+                               pInStr->ParamChange &= ~(1 << 10);
+                       mfc_debug(3, "[NALQ][HIERARCHICAL] layer count %d\n",
+                                       temporal_LC.temporal_layer_count & 0x7);
+
+                       pInStr->NumTLayer &= ~(0x7);
+                       pInStr->NumTLayer |= (temporal_LC.temporal_layer_count & 0x7);
+                       pInStr->NumTLayer &= ~(0x1 << 8);
+                       pInStr->NumTLayer |= (p->hier_bitrate_ctrl & 0x1) << 8;
+                       for (i = 0; i < (temporal_LC.temporal_layer_count & 0x7); i++) {
+                               mfc_debug(3, "[NALQ][HIERARCHICAL] layer bitrate[%d] %d (FW ctrl: %d)\n",
+                                       i, temporal_LC.temporal_layer_bitrate[i], p->hier_bitrate_ctrl);
+                               pInStr->HierarchicalBitRateLayer[i] =
+                                       temporal_LC.temporal_layer_bitrate[i];
+                       }
+
+                       /* priority change */
+                       if (IS_H264_ENC(ctx)) {
+                               for (i = 0; i < (temporal_LC.temporal_layer_count & 0x7); i++) {
+                                       if (i <= 4)
+                                               pInStr->H264HDSvcExtension0 |=
+                                                       ((p->codec.h264.base_priority & 0x3f) + i) << (6 * i);
+                                       else
+                                               pInStr->H264HDSvcExtension1 |=
+                                                       ((p->codec.h264.base_priority & 0x3f) + i) << (6 * (i - 5));
+                               }
+                               mfc_debug(3, "[NALQ][HIERARCHICAL] EXTENSION0 %#x, EXTENSION1 %#x\n",
+                                               pInStr->H264HDSvcExtension0, pInStr->H264HDSvcExtension1);
+
+                               pInStr->ParamChange |= (1 << 12);
+                       }
+                       break;
+               case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
+                       pInStr->PictureProfile &= ~(buf_ctrl->mask << buf_ctrl->shft);
+                       pInStr->PictureProfile |=
+                               (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
+                       pInStr->PictureProfile &= ~(0xf);
+                       pInStr->PictureProfile |= p->codec.h264.profile & 0xf;
+                       p->codec.h264.level = buf_ctrl->val;
+                       param_change = 1;
+                       break;
+               case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
+                       pInStr->PictureProfile &= ~(buf_ctrl->mask << buf_ctrl->shft);
+                       pInStr->PictureProfile |=
+                               (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
+                       pInStr->PictureProfile &= ~(0xff << 8);
+                       pInStr->PictureProfile |= (p->codec.h264.level << 8) & 0xff00;
+                       p->codec.h264.profile = buf_ctrl->val;
+                       param_change = 1;
+                       break;
+               case V4L2_CID_MPEG_MFC_H264_MARK_LTR:
+                       pInStr->H264NalControl &= ~(buf_ctrl->mask << buf_ctrl->shft);
+                       pInStr->H264NalControl |=
+                               (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
+                       pInStr->H264NalControl &= ~(0x7 << 8);
+                       pInStr->H264NalControl |= (buf_ctrl->val & 0x7) << 8;
+                       break;
+               case V4L2_CID_MPEG_MFC_H264_USE_LTR:
+                       pInStr->H264NalControl &= ~(buf_ctrl->mask << buf_ctrl->shft);
+                       pInStr->H264NalControl |=
+                               (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
+                       pInStr->H264NalControl &= ~(0xF << 11);
+                       pInStr->H264NalControl |= (buf_ctrl->val & 0xF) << 11;
+                       break;
+               case V4L2_CID_MPEG_MFC_H264_BASE_PRIORITY:
+                       for (i = 0; i < (p->codec.h264.num_hier_layer & 0x7); i++)
+                               if (i <= 4)
+                                       pInStr->H264HDSvcExtension0 |=
+                                               ((buf_ctrl->val & 0x3f) + i) << (6 * i);
+                               else
+                                       pInStr->H264HDSvcExtension1 |=
+                                               ((buf_ctrl->val & 0x3f) + i) << (6 * (i - 5));
+                       p->codec.h264.base_priority = buf_ctrl->val;
+                       param_change = 1;
+                       break;
+               case V4L2_CID_MPEG_MFC_CONFIG_QP:
+                       pInStr->FixedPictureQp &= ~(buf_ctrl->mask << buf_ctrl->shft);
+                       pInStr->FixedPictureQp |=
+                               (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
+                       p->config_qp = buf_ctrl->val;
+                       break;
+               case V4L2_CID_MPEG_VIDEO_ROI_CONTROL:
+                       pInStr->RcRoiCtrl &= ~(buf_ctrl->mask << buf_ctrl->shft);
+                       pInStr->RcRoiCtrl |=
+                               (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
+                       pInStr->RoiBufferAddr = enc->roi_buf[buf_ctrl->old_val2].daddr;
+                       mfc_debug(3, "[NALQ][ROI] buffer[%d] addr %#llx, QP val: %#x\n",
+                                       buf_ctrl->old_val2,
+                                       enc->roi_buf[buf_ctrl->old_val2].daddr,
+                                       buf_ctrl->val);
+                       break;
+               case V4L2_CID_MPEG_VIDEO_YSUM:
+                       pInStr->Weight &= ~(buf_ctrl->mask << buf_ctrl->shft);
+                       pInStr->Weight |=
+                               (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
+                       break;
+               case V4L2_CID_MPEG_VIDEO_RATIO_OF_INTRA:
+                       pInStr->RcMode &= ~(buf_ctrl->mask << buf_ctrl->shft);
+                       pInStr->RcMode |=
+                               (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
+                       param_change = 1;
+                       break;
+               /* If new dynamic controls are added, insert here */
+               default:
+                       mfc_info_ctx("[NALQ] can't find control, id: 0x%x\n",
+                                       buf_ctrl->id);
+               }
+
+               if (param_change)
+                       pInStr->ParamChange |= (1 << buf_ctrl->flag_shft);
+
+               buf_ctrl->has_new = 0;
+               buf_ctrl->updated = 1;
+
+               mfc_debug(6, "[NALQ][CTRLS] Set buffer control id: 0x%08x, val: %d\n",
+                               buf_ctrl->id, buf_ctrl->val);
+       }
+
+       if (!p->rc_frame && !p->rc_mb && p->dynamic_qp) {
+               pInStr->FixedPictureQp &= ~(0xFF000000);
+               pInStr->FixedPictureQp |= (p->config_qp & 0xFF) << 24;
+               mfc_debug(6, "[NALQ][CTRLS] Dynamic QP changed %#x\n",
+                               pInStr->FixedPictureQp);
+       }
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+static int s5p_mfc_enc_get_buf_ctrls_val_nal_q_enc(struct s5p_mfc_ctx *ctx,
+                       struct list_head *head, EncoderOutputStr *pOutStr)
+{
+       struct s5p_mfc_buf_ctrl *buf_ctrl;
+       struct s5p_mfc_enc *enc = ctx->enc_priv;
+       unsigned int value = 0;
+
+       mfc_debug_enter();
+
+       list_for_each_entry(buf_ctrl, head, list) {
+               if (!(buf_ctrl->type & MFC_CTRL_TYPE_GET))
+                       continue;
+               switch (buf_ctrl->id) {
+               case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG:
+                       value = pOutStr->PictureTag;
+                       break;
+               case V4L2_CID_MPEG_MFC51_VIDEO_LUMA_ADDR:
+                       value = pOutStr->EncodedFrameAddr[0];
+                       break;
+               case V4L2_CID_MPEG_MFC51_VIDEO_CHROMA_ADDR:
+                       value = pOutStr->EncodedFrameAddr[1];
+                       break;
+               case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_STATUS:
+                       value = !enc->in_slice;
+                       break;
+               /* If new dynamic controls are added, insert here */
+               default:
+                       mfc_info_ctx("[NALQ] can't find control, id: 0x%x\n",
+                                       buf_ctrl->id);
+               }
+               value = (value >> buf_ctrl->shft) & buf_ctrl->mask;
+
+               buf_ctrl->val = value;
+               buf_ctrl->has_new = 1;
+
+               mfc_debug(6, "[NALQ][CTRLS] Get buffer control id: 0x%08x, val: %d\n",
+                               buf_ctrl->id, buf_ctrl->val);
+       }
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+static int s5p_mfc_enc_recover_buf_ctrls_val(struct s5p_mfc_ctx *ctx,
+                                               struct list_head *head)
+{
+       struct s5p_mfc_buf_ctrl *buf_ctrl;
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned int value = 0;
+
+       list_for_each_entry(buf_ctrl, head, list) {
+               if (!(buf_ctrl->type & MFC_CTRL_TYPE_SET)
+                       || !buf_ctrl->is_volatile
+                       || !buf_ctrl->updated)
+                       continue;
+
+               if (buf_ctrl->mode == MFC_CTRL_MODE_SFR)
+                       value = MFC_READL(buf_ctrl->addr);
+
+               value &= ~(buf_ctrl->mask << buf_ctrl->shft);
+               value |= ((buf_ctrl->old_val & buf_ctrl->mask)
+                                                       << buf_ctrl->shft);
+
+               if (buf_ctrl->mode == MFC_CTRL_MODE_SFR)
+                       MFC_WRITEL(value, buf_ctrl->addr);
+
+               /* clear change flag bit */
+               if (buf_ctrl->flag_mode == MFC_CTRL_MODE_SFR) {
+                       value = MFC_READL(buf_ctrl->flag_addr);
+                       value &= ~(1 << buf_ctrl->flag_shft);
+                       MFC_WRITEL(value, buf_ctrl->flag_addr);
+               }
+
+               mfc_debug(6, "[CTRLS] Recover buffer control id: 0x%08x, old val: %d\n",
+                               buf_ctrl->id, buf_ctrl->old_val);
+
+               if (buf_ctrl->id == V4L2_CID_MPEG_MFC51_VIDEO_I_PERIOD_CH) {
+                       value = MFC_READL(S5P_FIMV_E_GOP_CONFIG2);
+                       value &= ~(0x3FFF);
+                       value |= (buf_ctrl->old_val >> 16) & 0x3FFF;
+                       MFC_WRITEL(value, S5P_FIMV_E_GOP_CONFIG2);
+               }
+               if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_H264_LEVEL) {
+                       value = MFC_READL(S5P_FIMV_E_PICTURE_PROFILE);
+                       value &= ~(0x000F);
+                       value |= (buf_ctrl->old_val >> 8) & 0x000F;
+                       MFC_WRITEL(value, S5P_FIMV_E_PICTURE_PROFILE);
+               }
+               if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_H264_PROFILE) {
+                       value = MFC_READL(S5P_FIMV_E_PICTURE_PROFILE);
+                       value &= ~(0xFF00);
+                       value |= buf_ctrl->old_val & 0xFF00;
+                       MFC_WRITEL(value, S5P_FIMV_E_PICTURE_PROFILE);
+               }
+               if (buf_ctrl->id == V4L2_CID_MPEG_MFC_H264_BASE_PRIORITY) {
+                       MFC_WRITEL(buf_ctrl->old_val, S5P_FIMV_E_H264_HD_SVC_EXTENSION_0);
+                       MFC_WRITEL(buf_ctrl->old_val2, S5P_FIMV_E_H264_HD_SVC_EXTENSION_1);
+               }
+               if (buf_ctrl->id
+                       == V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_CH ||
+                       buf_ctrl->id
+                       == V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_CH ||
+                       buf_ctrl->id
+                       == V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_CH) {
+                       MFC_WRITEL(buf_ctrl->old_val2, S5P_FIMV_E_NUM_T_LAYER);
+                       /* clear RC_BIT_RATE_CHANGE */
+                       value = MFC_READL(buf_ctrl->flag_addr);
+                       value &= ~(1 << 2);
+                       MFC_WRITEL(value, buf_ctrl->flag_addr);
+               }
+               if (buf_ctrl->id == V4L2_CID_MPEG_MFC_H264_MARK_LTR) {
+                       value = MFC_READL(S5P_FIMV_E_H264_NAL_CONTROL);
+                       value &= ~(0x7 << 8);
+                       value |= (buf_ctrl->old_val2 & 0x7) << 8;
+                       MFC_WRITEL(value, S5P_FIMV_E_H264_NAL_CONTROL);
+               }
+               if (buf_ctrl->id == V4L2_CID_MPEG_MFC_H264_USE_LTR) {
+                       value = MFC_READL(S5P_FIMV_E_H264_NAL_CONTROL);
+                       value &= ~(0xF << 11);
+                       value |= (buf_ctrl->old_val2 & 0xF) << 11;
+                       MFC_WRITEL(value, S5P_FIMV_E_H264_NAL_CONTROL);
+               }
+               buf_ctrl->updated = 0;
+       }
+
+       return 0;
+}
+
+static int s5p_mfc_enc_recover_buf_ctrls_nal_q(struct s5p_mfc_ctx *ctx,
+               struct list_head *head)
+{
+       struct s5p_mfc_buf_ctrl *buf_ctrl;
+
+       list_for_each_entry(buf_ctrl, head, list) {
+               if (!(buf_ctrl->type & MFC_CTRL_TYPE_SET)
+                               || !(buf_ctrl->updated))
+                       continue;
+
+               buf_ctrl->has_new = 1;
+               buf_ctrl->updated = 0;
+
+               mfc_debug(6, "[NALQ][CTRLS] Recover buffer control id: 0x%08x, val: %d\n",
+                               buf_ctrl->id, buf_ctrl->val);
+       }
+
+       return 0;
+}
+
+struct s5p_mfc_ctrls_ops encoder_ctrls_ops = {
+       .init_ctx_ctrls                 = s5p_mfc_enc_init_ctx_ctrls,
+       .cleanup_ctx_ctrls              = s5p_mfc_enc_cleanup_ctx_ctrls,
+       .init_buf_ctrls                 = s5p_mfc_enc_init_buf_ctrls,
+       .reset_buf_ctrls                = s5p_mfc_enc_reset_buf_ctrls,
+       .cleanup_buf_ctrls              = s5p_mfc_enc_cleanup_buf_ctrls,
+       .to_buf_ctrls                   = s5p_mfc_enc_to_buf_ctrls,
+       .to_ctx_ctrls                   = s5p_mfc_enc_to_ctx_ctrls,
+       .set_buf_ctrls_val              = s5p_mfc_enc_set_buf_ctrls_val,
+       .get_buf_ctrls_val              = s5p_mfc_enc_get_buf_ctrls_val,
+       .recover_buf_ctrls_val          = s5p_mfc_enc_recover_buf_ctrls_val,
+       .get_buf_update_val             = s5p_mfc_enc_get_buf_update_val,
+       .set_buf_ctrls_val_nal_q_enc    = s5p_mfc_enc_set_buf_ctrls_val_nal_q_enc,
+       .get_buf_ctrls_val_nal_q_enc    = s5p_mfc_enc_get_buf_ctrls_val_nal_q_enc,
+       .recover_buf_ctrls_nal_q        = s5p_mfc_enc_recover_buf_ctrls_nal_q,
+};
diff --git a/drivers/media/platform/exynos/mfc/mfc_enc_param.c b/drivers/media/platform/exynos/mfc/mfc_enc_param.c
new file mode 100644 (file)
index 0000000..e6ce770
--- /dev/null
@@ -0,0 +1,1397 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_enc_param.c
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include "mfc_enc_param.h"
+
+#include "mfc_reg.h"
+
+/* Definition */
+#define FRAME_DELTA_DEFAULT            1
+#define CBR_FIX_MAX                    10
+#define CBR_I_LIMIT_MAX                        5
+#define BPG_EXTENSION_TAG_SIZE         5
+
+void s5p_mfc_set_slice_mode(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc *enc = ctx->enc_priv;
+
+       /* multi-slice control */
+       if (enc->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES)
+               MFC_WRITEL((enc->slice_mode + 0x4), S5P_FIMV_E_MSLICE_MODE);
+       else if (enc->slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB_ROW)
+               MFC_WRITEL((enc->slice_mode - 0x2), S5P_FIMV_E_MSLICE_MODE);
+       else if (enc->slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_FIXED_BYTES)
+               MFC_WRITEL((enc->slice_mode + 0x3), S5P_FIMV_E_MSLICE_MODE);
+       else
+               MFC_WRITEL(enc->slice_mode, S5P_FIMV_E_MSLICE_MODE);
+
+       /* multi-slice MB number or bit size */
+       if ((enc->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB) ||
+                       (enc->slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB_ROW)) {
+               MFC_WRITEL(enc->slice_size.mb, S5P_FIMV_E_MSLICE_SIZE_MB);
+       } else if ((enc->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES) ||
+                       (enc->slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_FIXED_BYTES)){
+               MFC_WRITEL(enc->slice_size.bits, S5P_FIMV_E_MSLICE_SIZE_BITS);
+       } else {
+               MFC_WRITEL(0x0, S5P_FIMV_E_MSLICE_SIZE_MB);
+               MFC_WRITEL(0x0, S5P_FIMV_E_MSLICE_SIZE_BITS);
+       }
+}
+
+static void mfc_set_gop_size(struct s5p_mfc_ctx *ctx, int ctrl_mode)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc *enc = ctx->enc_priv;
+       struct s5p_mfc_enc_params *p = &enc->params;
+       unsigned int reg = 0;
+
+       if (ctrl_mode) {
+               p->i_frm_ctrl_mode = 1;
+               p->i_frm_ctrl = p->gop_size * (p->num_b_frame + 1);
+               if (p->i_frm_ctrl >= 0x3FFFFFFF) {
+                       mfc_info_ctx("I frame interval is bigger than max: %d\n",
+                                       p->i_frm_ctrl);
+                       p->i_frm_ctrl = 0x3FFFFFFF;
+               }
+       } else {
+               p->i_frm_ctrl_mode = 0;
+               p->i_frm_ctrl = p->gop_size;
+       }
+
+       mfc_debug(2, "I frame interval: %d, (P: %d, B: %d), ctrl mode: %d\n",
+                       p->i_frm_ctrl, p->gop_size,
+                       p->num_b_frame, p->i_frm_ctrl_mode);
+
+       /* pictype : IDR period, number of B */
+       reg = MFC_READL(S5P_FIMV_E_GOP_CONFIG);
+       reg &= ~(0xFFFF);
+       reg |= p->i_frm_ctrl & 0xFFFF;
+       reg &= ~(0x1 << 19);
+       reg |= p->i_frm_ctrl_mode << 19;
+       reg &= ~(0x3 << 16);
+       /* if B frame is used, the performance falls by half */
+       reg |= (p->num_b_frame << 16);
+       MFC_WRITEL(reg, S5P_FIMV_E_GOP_CONFIG);
+
+       reg = MFC_READL(S5P_FIMV_E_GOP_CONFIG2);
+       reg &= ~(0x3FFF);
+       reg |= (p->i_frm_ctrl >> 16) & 0x3FFF;
+       MFC_WRITEL(reg, S5P_FIMV_E_GOP_CONFIG2);
+}
+
+static void mfc_set_default_params(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       int i;
+
+       mfc_debug(2, "Set default param -  enc_param_num: %d\n", dev->pdata->enc_param_num);
+       for (i = 0; i < dev->pdata->enc_param_num; i++) {
+               if (i >= MFC_MAX_DEFAULT_PARAM) {
+                       mfc_err_dev("enc_param_num(%d) is over max number(%d)\n",
+                                       dev->pdata->enc_param_num, MFC_MAX_DEFAULT_PARAM);
+                       break;
+               }
+               MFC_WRITEL(dev->pdata->enc_param_val[i], dev->pdata->enc_param_addr[i]);
+               mfc_debug(2, "Set default param[%d] - addr:0x%x, val:0x%x\n",
+                               i, dev->pdata->enc_param_addr[i], dev->pdata->enc_param_val[i]);
+       }
+}
+
+static void mfc_init_regs(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       /* Register initialization */
+       MFC_WRITEL(0x0, S5P_FIMV_E_FRAME_INSERTION);
+       MFC_WRITEL(0x0, S5P_FIMV_E_ROI_BUFFER_ADDR);
+       MFC_WRITEL(0x0, S5P_FIMV_E_PARAM_CHANGE);
+       MFC_WRITEL(0x0, S5P_FIMV_E_PICTURE_TAG);
+       MFC_WRITEL(0x0, S5P_FIMV_E_METADATA_BUFFER_ADDR);
+       MFC_WRITEL(0x0, S5P_FIMV_E_METADATA_BUFFER_SIZE);
+}
+
+static void mfc_set_enc_params(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc *enc = ctx->enc_priv;
+       struct s5p_mfc_enc_params *p = &enc->params;
+       unsigned int reg = 0;
+
+       mfc_debug_enter();
+
+       mfc_init_regs(ctx);
+       mfc_set_default_params(ctx);
+
+       /* width */
+       MFC_WRITEL(ctx->crop_width, S5P_FIMV_E_CROPPED_FRAME_WIDTH);
+       /* height */
+       MFC_WRITEL(ctx->crop_height, S5P_FIMV_E_CROPPED_FRAME_HEIGHT);
+       /* cropped offset */
+       reg |= (ctx->crop_left & S5P_FIMV_E_FRAME_CROP_OFFSET_MASK)
+               << S5P_FIMV_E_FRAME_CROP_OFFSET_LEFT;
+       reg |= (ctx->crop_top & S5P_FIMV_E_FRAME_CROP_OFFSET_MASK)
+               << S5P_FIMV_E_FRAME_CROP_OFFSET_TOP;
+       MFC_WRITEL(reg, S5P_FIMV_E_FRAME_CROP_OFFSET);
+
+       /* multi-slice control */
+       /* multi-slice MB number or bit size */
+       enc->slice_mode = p->slice_mode;
+
+       if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB) {
+               enc->slice_size.mb = p->slice_mb;
+       } else if ((p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES) ||
+                       (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_FIXED_BYTES)){
+               enc->slice_size.bits = p->slice_bit;
+       } else if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB_ROW) {
+               enc->slice_size.mb = p->slice_mb_row * ((ctx->crop_width + 15) / 16);
+       } else {
+               enc->slice_size.mb = 0;
+               enc->slice_size.bits = 0;
+       }
+
+       s5p_mfc_set_slice_mode(ctx);
+
+       /* cyclic intra refresh */
+       MFC_WRITEL(p->intra_refresh_mb, S5P_FIMV_E_IR_SIZE);
+
+       reg = MFC_READL(S5P_FIMV_E_ENC_OPTIONS);
+       /* frame skip mode */
+       reg &= ~(0x3);
+       reg |= (p->frame_skip_mode & 0x3);
+       /* seq header ctrl */
+       reg &= ~(0x1 << 2);
+       reg |= ((p->seq_hdr_mode & 0x1) << 2);
+       /* cyclic intra refresh */
+       reg &= ~(0x1 << 4);
+       if (p->intra_refresh_mb)
+               reg |= (0x1 << 4);
+       /* disable seq header generation if OTF mode */
+       reg &= ~(0x1 << 6);
+       if (ctx->otf_handle) {
+               reg |= (0x1 << 6);
+               mfc_debug(2, "[OTF] SEQ_HEADER_GENERATION is disabled\n");
+       }
+       /* 'NON_REFERENCE_STORE_ENABLE' for debugging */
+       reg &= ~(0x1 << 9);
+       /* Disable parallel processing if nal_q_parallel_disable was set */
+       reg &= ~(0x1 << 18);
+       if (nal_q_parallel_disable)
+               reg |= (0x1 << 18);
+       MFC_WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS);
+
+       s5p_mfc_set_pixel_format(dev, ctx->src_fmt->fourcc);
+
+       /* padding control & value */
+       MFC_WRITEL(0x0, S5P_FIMV_E_PADDING_CTRL);
+       if (p->pad) {
+               reg = 0;
+               /** enable */
+               reg |= (1 << 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);
+               MFC_WRITEL(reg, S5P_FIMV_E_PADDING_CTRL);
+       }
+
+       /* rate control config. */
+       reg = MFC_READL(S5P_FIMV_E_RC_CONFIG);
+       /* macroblock level rate control */
+       reg &= ~(0x1 << 8);
+       reg |= ((p->rc_mb & 0x1) << 8);
+       /* frame-level rate control */
+       reg &= ~(0x1 << 9);
+       reg |= ((p->rc_frame & 0x1) << 9);
+       /* 'DROP_CONTROL_ENABLE', disable */
+       reg &= ~(0x1 << 10);
+       MFC_WRITEL(reg, S5P_FIMV_E_RC_CONFIG);
+
+       /* bit rate */
+       MFC_WRITEL(p->rc_bitrate, S5P_FIMV_E_RC_BIT_RATE);
+
+
+       reg = MFC_READL(S5P_FIMV_E_RC_MODE);
+       reg &= ~(0x3 | (0x3 << 4) | (0xFF << 8));
+       if (p->rc_frame) {
+               if (p->rc_reaction_coeff <= CBR_I_LIMIT_MAX) {
+                       reg |= S5P_FIMV_E_RC_CBR_I_LIMIT;
+                       /*
+                        * Ratio of intra for max frame size
+                        * is controled when only CBR_I_LIMIT mode.
+                        * And CBR_I_LIMIT mode is valid for H.264, HEVC codec
+                        */
+                       if (p->ratio_intra)
+                               reg |= ((p->ratio_intra & 0xFF) << 8);
+               } else if (p->rc_reaction_coeff <= CBR_FIX_MAX) {
+                       reg |= S5P_FIMV_E_RC_CBR_FIX;
+               } else {
+                       reg |= S5P_FIMV_E_RC_VBR;
+               }
+
+               if (p->rc_mb)
+                       reg |= ((p->rc_pvc & 0x3) << 4);
+       }
+       MFC_WRITEL(reg, S5P_FIMV_E_RC_MODE);
+
+       /* extended encoder ctrl */
+       /** vbv buffer size */
+       reg = MFC_READL(S5P_FIMV_E_VBV_BUFFER_SIZE);
+       reg &= ~(0xFF);
+       if (p->frame_skip_mode == V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT)
+               reg |= p->vbv_buf_size & 0xFF;
+       MFC_WRITEL(reg, S5P_FIMV_E_VBV_BUFFER_SIZE);
+
+       mfc_debug_leave();
+}
+
+static void mfc_set_temporal_svc_h264(struct s5p_mfc_ctx *ctx, struct s5p_mfc_h264_enc_params *p_264)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc *enc = ctx->enc_priv;
+       struct s5p_mfc_enc_params *p = &enc->params;
+       unsigned int reg = 0, reg2 = 0;
+       int i;
+
+       reg = MFC_READL(S5P_FIMV_E_H264_OPTIONS_2);
+       /* pic_order_cnt_type = 0 for backward compatibilities */
+       reg &= ~(0x3);
+       /* Enable LTR */
+       reg &= ~(0x1 << 2);
+       if ((p_264->enable_ltr & 0x1) || (p_264->num_of_ltr > 0))
+               reg |= (0x1 << 2);
+       /* Number of LTR */
+       reg &= ~(0x3 << 7);
+       if (p_264->num_of_ltr > 2)
+               reg |= (((p_264->num_of_ltr - 2) & 0x3) << 7);
+       MFC_WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_2);
+
+       /* Temporal SVC - qp type, layer number */
+       reg = MFC_READL(S5P_FIMV_E_NUM_T_LAYER);
+       reg &= ~(0x1 << 3);
+       reg |= (p_264->hier_qp_type & 0x1) << 3;
+       reg &= ~(0x7);
+       reg |= p_264->num_hier_layer & 0x7;
+       reg &= ~(0x7 << 4);
+       if (p_264->hier_ref_type) {
+               reg |= 0x1 << 7;
+               reg |= (p->num_hier_max_layer & 0x7) << 4;
+       } else {
+               reg &= ~(0x1 << 7);
+               reg |= 0x7 << 4;
+       }
+       reg &= ~(0x1 << 8);
+       reg |= (p->hier_bitrate_ctrl & 0x1) << 8;
+       MFC_WRITEL(reg, S5P_FIMV_E_NUM_T_LAYER);
+       mfc_debug(3, "[HIERARCHICAL] hier_qp_enable %d, enable_ltr %d, "
+               "num_hier_layer %d, max_layer %d, hier_ref_type %d, NUM_T_LAYER 0x%x\n",
+               p_264->hier_qp_enable, p_264->enable_ltr, p_264->num_hier_layer,
+               p->num_hier_max_layer, p_264->hier_ref_type, reg);
+       /* QP & Bitrate for each layer */
+       for (i = 0; i < 7; i++) {
+               MFC_WRITEL(p_264->hier_qp_layer[i],
+                               S5P_FIMV_E_HIERARCHICAL_QP_LAYER0 + i * 4);
+               /* If hier_bitrate_ctrl is set to 1, this is meaningless */
+               MFC_WRITEL(p_264->hier_bit_layer[i],
+                               S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER0 + i * 4);
+               mfc_debug(3, "[HIERARCHICAL] layer[%d] QP: %#x, bitrate: %d(FW ctrl: %d)\n",
+                                       i, p_264->hier_qp_layer[i],
+                                       p_264->hier_bit_layer[i], p->hier_bitrate_ctrl);
+       }
+       if (p_264->set_priority) {
+               reg = 0;
+               reg2 = 0;
+               for (i = 0; i < (p_264->num_hier_layer & 0x7); i++) {
+                       if (i <= 4)
+                               reg |= ((p_264->base_priority & 0x3F) + i) << (6 * i);
+                       else
+                               reg2 |= ((p_264->base_priority & 0x3F) + i) << (6 * (i - 5));
+               }
+               MFC_WRITEL(reg, S5P_FIMV_E_H264_HD_SVC_EXTENSION_0);
+               MFC_WRITEL(reg2, S5P_FIMV_E_H264_HD_SVC_EXTENSION_1);
+               mfc_debug(3, "[HIERARCHICAL] priority EXTENSION0: %#x, EXTENSION1: %#x\n",
+                                                       reg, reg2);
+       }
+}
+
+static void mfc_set_fmo_slice_map_h264(struct s5p_mfc_ctx *ctx, struct s5p_mfc_h264_enc_params *p_264)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       int i;
+
+       if (p_264->fmo_enable) {
+               switch (p_264->fmo_slice_map_type) {
+               case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_INTERLEAVED_SLICES:
+                       if (p_264->fmo_slice_num_grp > 4)
+                               p_264->fmo_slice_num_grp = 4;
+                       for (i = 0; i < (p_264->fmo_slice_num_grp & 0xF); i++)
+                               MFC_WRITEL(p_264->fmo_run_length[i] - 1,
+                               S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_0 + i*4);
+                       break;
+               case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_SCATTERED_SLICES:
+                       if (p_264->fmo_slice_num_grp > 4)
+                               p_264->fmo_slice_num_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_264->fmo_slice_num_grp > 2)
+                               p_264->fmo_slice_num_grp = 2;
+                       MFC_WRITEL(p_264->fmo_sg_dir & 0x1,
+                               S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_DIR);
+                       /* the valid range is 0 ~ number of macroblocks -1 */
+                       MFC_WRITEL(p_264->fmo_sg_rate, S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_RATE_MINUS1);
+                       break;
+               default:
+                       mfc_err_ctx("Unsupported map type for FMO: %d\n",
+                                       p_264->fmo_slice_map_type);
+                       p_264->fmo_slice_map_type = 0;
+                       p_264->fmo_slice_num_grp = 1;
+                       break;
+               }
+
+               MFC_WRITEL(p_264->fmo_slice_map_type, S5P_FIMV_E_H264_FMO_SLICE_GRP_MAP_TYPE);
+               MFC_WRITEL(p_264->fmo_slice_num_grp - 1, S5P_FIMV_E_H264_FMO_NUM_SLICE_GRP_MINUS1);
+       } else {
+               MFC_WRITEL(0, S5P_FIMV_E_H264_FMO_NUM_SLICE_GRP_MINUS1);
+       }
+}
+
+void s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc *enc = ctx->enc_priv;
+       struct s5p_mfc_enc_params *p = &enc->params;
+       struct s5p_mfc_h264_enc_params *p_264 = &p->codec.h264;
+       unsigned int reg = 0;
+
+       mfc_debug_enter();
+
+       mfc_set_enc_params(ctx);
+
+       if (p_264->num_hier_layer & 0x7) {
+               /* set gop_size without i_frm_ctrl mode */
+               mfc_set_gop_size(ctx, 0);
+       } else {
+               /* set gop_size with i_frm_ctrl mode */
+               mfc_set_gop_size(ctx, 1);
+       }
+
+       /* UHD encoding case */
+       if(IS_UHD_RES(ctx)) {
+               if (p_264->level < 51) {
+                       mfc_info_ctx("Set Level 5.1 for UHD\n");
+                       p_264->level = 51;
+               }
+               if (p_264->profile != 0x2) {
+                       mfc_info_ctx("Set High profile for UHD\n");
+                       p_264->profile = 0x2;
+               }
+       }
+
+       /* profile & level */
+       reg = 0;
+       /** level */
+       reg &= ~(0xFF << 8);
+       reg |= (p_264->level << 8);
+       /** profile - 0 ~ 3 */
+       reg &= ~(0x3F);
+       reg |= p_264->profile;
+       MFC_WRITEL(reg, S5P_FIMV_E_PICTURE_PROFILE);
+
+       reg = MFC_READL(S5P_FIMV_E_H264_OPTIONS);
+       /* entropy coding mode */
+       reg &= ~(0x1);
+       reg |= (p_264->entropy_mode & 0x1);
+       /* loop filter ctrl */
+       reg &= ~(0x3 << 1);
+       reg |= ((p_264->loop_filter_mode & 0x3) << 1);
+       /* interlace */
+       reg &= ~(0x1 << 3);
+       reg |= ((p_264->interlace & 0x1) << 3);
+       /* intra picture period for H.264 open GOP */
+       reg &= ~(0x1 << 4);
+       reg |= ((p_264->open_gop & 0x1) << 4);
+       /* extended encoder ctrl */
+       reg &= ~(0x1 << 5);
+       reg |= ((p_264->ar_vui & 0x1) << 5);
+       /* ASO enable */
+       reg &= ~(0x1 << 6);
+       reg |= ((p_264->aso_enable & 0x1) << 6);
+       /* if num_refs_for_p is 2, the performance falls by half */
+       reg &= ~(0x1 << 7);
+       reg |= (((p->num_refs_for_p - 1) & 0x1) << 7);
+       /* Temporal SVC - hier qp enable */
+       reg &= ~(0x1 << 8);
+       reg |= ((p_264->hier_qp_enable & 0x1) << 8);
+       /* Weighted Prediction enable */
+       reg &= ~(0x3 << 9);
+       reg |= ((p->weighted_enable & 0x1) << 9);
+       /* 8x8 transform enable */
+       reg &= ~(0x1 << 12);
+       reg &= ~(0x1 << 13);
+       reg |= ((p_264->_8x8_transform & 0x1) << 12);
+       reg |= ((p_264->_8x8_transform & 0x1) << 13);
+       /* 'CONSTRAINED_INTRA_PRED_ENABLE' is disable */
+       reg &= ~(0x1 << 14);
+       /*
+        * CONSTRAINT_SET0_FLAG: all constraints specified in
+        * Baseline Profile
+        */
+       reg |= (0x1 << 26);
+       /* sps pps control */
+       reg &= ~(0x1 << 29);
+       reg |= ((p_264->prepend_sps_pps_to_idr & 0x1) << 29);
+       /* enable sps pps control in OTF scenario */
+       if (ctx->otf_handle) {
+               reg |= (0x1 << 29);
+               mfc_debug(2, "[OTF] SPS_PPS_CONTROL enabled\n");
+       }
+       /* VUI parameter disable */
+       reg &= ~(0x1 << 30);
+       reg |= ((p_264->vui_enable & 0x1) << 30);
+       MFC_WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
+
+       /* cropped height */
+       if (p_264->interlace)
+               MFC_WRITEL(ctx->crop_height >> 1, S5P_FIMV_E_CROPPED_FRAME_HEIGHT);
+
+       /* loopfilter alpha offset */
+       reg = MFC_READL(S5P_FIMV_E_H264_LF_ALPHA_OFFSET);
+       reg &= ~(0x1F);
+       reg |= (p_264->loop_filter_alpha & 0x1F);
+       MFC_WRITEL(reg, S5P_FIMV_E_H264_LF_ALPHA_OFFSET);
+
+       /* loopfilter beta offset */
+       reg = MFC_READL(S5P_FIMV_E_H264_LF_BETA_OFFSET);
+       reg &= ~(0x1F);
+       reg |= (p_264->loop_filter_beta & 0x1F);
+       MFC_WRITEL(reg, S5P_FIMV_E_H264_LF_BETA_OFFSET);
+
+       /* rate control config. */
+       reg = MFC_READL(S5P_FIMV_E_RC_CONFIG);
+       /** frame QP */
+       reg &= ~(0xFF);
+       reg |= (p_264->rc_frame_qp & 0xFF);
+       reg &= ~(0x1 << 11);
+       if (!p->rc_frame && !p->rc_mb && p->dynamic_qp)
+               reg |= (0x1 << 11);
+       MFC_WRITEL(reg, S5P_FIMV_E_RC_CONFIG);
+
+       /* frame rate */
+       /* Fix value for H.264, H.263 in the driver */
+       p->rc_frame_delta = FRAME_DELTA_DEFAULT;
+       reg = MFC_READL(S5P_FIMV_E_RC_FRAME_RATE);
+       reg &= ~(0xFFFF << 16);
+       reg |= (p->rc_framerate << 16);
+       reg &= ~(0xFFFF);
+       reg |= p->rc_frame_delta & 0xFFFF;
+       MFC_WRITEL(reg, S5P_FIMV_E_RC_FRAME_RATE);
+
+       /* max & min value of QP for I frame */
+       reg = MFC_READL(S5P_FIMV_E_RC_QP_BOUND);
+       /** max I frame QP */
+       reg &= ~(0xFF << 8);
+       reg |= ((p_264->rc_max_qp & 0xFF) << 8);
+       /** min I frame QP */
+       reg &= ~(0xFF);
+       reg |= p_264->rc_min_qp & 0xFF;
+       MFC_WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND);
+
+       /* max & min value of QP for P/B frame */
+       reg = MFC_READL(S5P_FIMV_E_RC_QP_BOUND_PB);
+       /** max B frame QP */
+       reg &= ~(0xFF << 24);
+       reg |= ((p_264->rc_max_qp_b & 0xFF) << 24);
+       /** min B frame QP */
+       reg &= ~(0xFF << 16);
+       reg |= ((p_264->rc_min_qp_b & 0xFF) << 16);
+       /** max P frame QP */
+       reg &= ~(0xFF << 8);
+       reg |= ((p_264->rc_max_qp_p & 0xFF) << 8);
+       /** min P frame QP */
+       reg &= ~(0xFF);
+       reg |= p_264->rc_min_qp_p & 0xFF;
+       MFC_WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND_PB);
+
+       reg = MFC_READL(S5P_FIMV_E_FIXED_PICTURE_QP);
+       reg &= ~(0xFF << 24);
+       reg |= ((p->config_qp & 0xFF) << 24);
+       reg &= ~(0xFF << 16);
+       reg |= ((p_264->rc_b_frame_qp & 0xFF) << 16);
+       reg &= ~(0xFF << 8);
+       reg |= ((p_264->rc_p_frame_qp & 0xFF) << 8);
+       reg &= ~(0xFF);
+       reg |= (p_264->rc_frame_qp & 0xFF);
+       MFC_WRITEL(reg, S5P_FIMV_E_FIXED_PICTURE_QP);
+
+       MFC_WRITEL(0x0, S5P_FIMV_E_ASPECT_RATIO);
+       MFC_WRITEL(0x0, S5P_FIMV_E_EXTENDED_SAR);
+       if (p_264->ar_vui) {
+               /* aspect ration IDC */
+               reg = 0;
+               reg &= ~(0xff);
+               reg |= p_264->ar_vui_idc;
+               MFC_WRITEL(reg, S5P_FIMV_E_ASPECT_RATIO);
+               if (p_264->ar_vui_idc == 0xFF) {
+                       /* sample  AR info. */
+                       reg = 0;
+                       reg &= ~(0xffffffff);
+                       reg |= p_264->ext_sar_width << 16;
+                       reg |= p_264->ext_sar_height;
+                       MFC_WRITEL(reg, S5P_FIMV_E_EXTENDED_SAR);
+               }
+       }
+       /* intra picture period for H.264 open GOP, value */
+       reg = MFC_READL(S5P_FIMV_E_H264_REFRESH_PERIOD);
+       reg &= ~(0xFFFF);
+       if (p_264->open_gop)
+               reg |= (p_264->open_gop_size & 0xFFFF);
+       MFC_WRITEL(reg, S5P_FIMV_E_H264_REFRESH_PERIOD);
+
+       /* Temporal SVC */
+       mfc_set_temporal_svc_h264(ctx, p_264);
+
+       /* set frame pack sei generation */
+       if (p_264->sei_gen_enable) {
+               /* frame packing enable */
+               reg = MFC_READL(S5P_FIMV_E_H264_OPTIONS);
+               reg |= (1 << 25);
+               MFC_WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
+
+               /* set current frame0 flag & arrangement type */
+               reg = 0;
+               /** current frame0 flag */
+               reg |= ((p_264->sei_fp_curr_frame_0 & 0x1) << 2);
+               /** arrangement type */
+               reg |= (p_264->sei_fp_arrangement_type - 3) & 0x3;
+               MFC_WRITEL(reg, S5P_FIMV_E_H264_FRAME_PACKING_SEI_INFO);
+       }
+
+       if (MFC_FEATURE_SUPPORT(dev, dev->pdata->color_aspect_enc) && p->check_color_range) {
+               reg = MFC_READL(S5P_FIMV_E_VIDEO_SIGNAL_TYPE);
+               /* VIDEO_SIGNAL_TYPE_FLAG */
+               reg |= 0x1 << 31;
+               /* COLOR_RANGE */
+               reg &= ~(0x1 << 25);
+               reg |= p->color_range << 25;
+               if ((p->colour_primaries != 0) && (p->transfer_characteristics != 0) &&
+                               (p->matrix_coefficients != 3)) {
+                       /* COLOUR_DESCRIPTION_PRESENT_FLAG */
+                       reg |= 0x1 << 24;
+                       /* COLOUR_PRIMARIES */
+                       reg &= ~(0xFF << 16);
+                       reg |= p->colour_primaries << 16;
+                       /* TRANSFER_CHARACTERISTICS */
+                       reg &= ~(0xFF << 8);
+                       reg |= p->transfer_characteristics << 8;
+                       /* MATRIX_COEFFICIENTS */
+                       reg &= ~(0xFF);
+                       reg |= p->matrix_coefficients;
+               } else {
+                       reg &= ~(0x1 << 24);
+               }
+               MFC_WRITEL(reg, S5P_FIMV_E_VIDEO_SIGNAL_TYPE);
+               mfc_debug(2, "[HDR] H264 ENC Color aspect: range(%s), pri(%d), trans(%d), mat(%d)\n",
+                               p->color_range ? "Full" : "Limited", p->colour_primaries,
+                               p->transfer_characteristics, p->matrix_coefficients);
+       } else {
+               MFC_WRITEL(0, S5P_FIMV_E_VIDEO_SIGNAL_TYPE);
+       }
+
+       mfc_set_fmo_slice_map_h264(ctx, p_264);
+
+       mfc_debug_leave();
+}
+
+void s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc *enc = ctx->enc_priv;
+       struct s5p_mfc_enc_params *p = &enc->params;
+       struct s5p_mfc_mpeg4_enc_params *p_mpeg4 = &p->codec.mpeg4;
+       unsigned int reg = 0;
+
+       mfc_debug_enter();
+
+       mfc_set_enc_params(ctx);
+
+       /* set gop_size with I_FRM_CTRL mode */
+       mfc_set_gop_size(ctx, 1);
+
+       /* profile & level */
+       reg = 0;
+       /** level */
+       reg &= ~(0xFF << 8);
+       reg |= (p_mpeg4->level << 8);
+       /** profile - 0 ~ 1 */
+       reg &= ~(0x3F);
+       reg |= p_mpeg4->profile;
+       MFC_WRITEL(reg, S5P_FIMV_E_PICTURE_PROFILE);
+
+       /* quarter_pixel */
+       /* MFC_WRITEL(p_mpeg4->quarter_pixel, S5P_FIMV_ENC_MPEG4_QUART_PXL); */
+
+       /* qp */
+       reg = MFC_READL(S5P_FIMV_E_FIXED_PICTURE_QP);
+       reg &= ~(0xFF << 24);
+       reg |= ((p->config_qp & 0xFF) << 24);
+       reg &= ~(0xFF << 16);
+       reg |= ((p_mpeg4->rc_b_frame_qp & 0xFF) << 16);
+       reg &= ~(0xFF << 8);
+       reg |= ((p_mpeg4->rc_p_frame_qp & 0xFF) << 8);
+       reg &= ~(0xFF);
+       reg |= (p_mpeg4->rc_frame_qp & 0xFF);
+       MFC_WRITEL(reg, S5P_FIMV_E_FIXED_PICTURE_QP);
+
+       /* frame rate */
+       p->rc_frame_delta = p_mpeg4->vop_frm_delta;
+       reg = MFC_READL(S5P_FIMV_E_RC_FRAME_RATE);
+       reg &= ~(0xFFFF << 16);
+       reg |= (p_mpeg4->vop_time_res << 16);
+       reg &= ~(0xFFFF);
+       reg |= (p_mpeg4->vop_frm_delta & 0xFFFF);
+       MFC_WRITEL(reg, S5P_FIMV_E_RC_FRAME_RATE);
+
+       /* rate control config. */
+       reg = MFC_READL(S5P_FIMV_E_RC_CONFIG);
+       /** frame QP */
+       reg &= ~(0xFF);
+       reg |= (p_mpeg4->rc_frame_qp & 0xFF);
+       MFC_WRITEL(reg, S5P_FIMV_E_RC_CONFIG);
+
+       /* max & min value of QP for I frame */
+       reg = MFC_READL(S5P_FIMV_E_RC_QP_BOUND);
+       /** max I frame QP */
+       reg &= ~(0xFF << 8);
+       reg |= ((p_mpeg4->rc_max_qp & 0xFF) << 8);
+       /** min I frame QP */
+       reg &= ~(0xFF);
+       reg |= (p_mpeg4->rc_min_qp & 0xFF);
+       MFC_WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND);
+
+       /* max & min value of QP for P/B frame */
+       reg = MFC_READL(S5P_FIMV_E_RC_QP_BOUND_PB);
+       /** max B frame QP */
+       reg &= ~(0xFF << 24);
+       reg |= ((p_mpeg4->rc_max_qp_b & 0xFF) << 24);
+       /** min B frame QP */
+       reg &= ~(0xFF << 16);
+       reg |= ((p_mpeg4->rc_min_qp_b & 0xFF) << 16);
+       /** max P frame QP */
+       reg &= ~(0xFF << 8);
+       reg |= ((p_mpeg4->rc_max_qp_p & 0xFF) << 8);
+       /** min P frame QP */
+       reg &= ~(0xFF);
+       reg |= p_mpeg4->rc_min_qp_p & 0xFF;
+       MFC_WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND_PB);
+
+       /* initialize for '0' only setting*/
+       MFC_WRITEL(0x0, S5P_FIMV_E_MPEG4_OPTIONS); /* SEQ_start only */
+       MFC_WRITEL(0x0, S5P_FIMV_E_MPEG4_HEC_PERIOD); /* SEQ_start only */
+
+       mfc_debug_leave();
+}
+
+void s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc *enc = ctx->enc_priv;
+       struct s5p_mfc_enc_params *p = &enc->params;
+       struct s5p_mfc_mpeg4_enc_params *p_mpeg4 = &p->codec.mpeg4;
+       unsigned int reg = 0;
+
+       mfc_debug_enter();
+
+       mfc_set_enc_params(ctx);
+
+       /* set gop_size with I_FRM_CTRL mode */
+       mfc_set_gop_size(ctx, 1);
+
+       /* profile & level: supports only baseline profile Level 70 */
+
+       /* qp */
+       reg = MFC_READL(S5P_FIMV_E_FIXED_PICTURE_QP);
+       reg &= ~(0xFF << 24);
+       reg |= ((p->config_qp & 0xFF) << 24);
+       reg &= ~(0xFF << 8);
+       reg |= ((p_mpeg4->rc_p_frame_qp & 0xFF) << 8);
+       reg &= ~(0xFF);
+       reg |= (p_mpeg4->rc_frame_qp & 0xFF);
+       MFC_WRITEL(reg, S5P_FIMV_E_FIXED_PICTURE_QP);
+
+       /* frame rate */
+       /* Fix value for H.264, H.263 in the driver */
+       p->rc_frame_delta = FRAME_DELTA_DEFAULT;
+       reg = MFC_READL(S5P_FIMV_E_RC_FRAME_RATE);
+       reg &= ~(0xFFFF << 16);
+       reg |= (p->rc_framerate << 16);
+       reg &= ~(0xFFFF);
+       reg |= (p->rc_frame_delta & 0xFFFF);
+       MFC_WRITEL(reg, S5P_FIMV_E_RC_FRAME_RATE);
+
+       /* rate control config. */
+       reg = MFC_READL(S5P_FIMV_E_RC_CONFIG);
+       /** frame QP */
+       reg &= ~(0xFF);
+       reg |= (p_mpeg4->rc_frame_qp & 0xFF);
+       MFC_WRITEL(reg, S5P_FIMV_E_RC_CONFIG);
+
+       /* max & min value of QP for I frame */
+       reg = MFC_READL(S5P_FIMV_E_RC_QP_BOUND);
+       /** max I frame QP */
+       reg &= ~(0xFF << 8);
+       reg |= ((p_mpeg4->rc_max_qp & 0xFF) << 8);
+       /** min I frame QP */
+       reg &= ~(0xFF);
+       reg |= (p_mpeg4->rc_min_qp & 0xFF);
+       MFC_WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND);
+
+       /* max & min value of QP for P/B frame */
+       reg = MFC_READL(S5P_FIMV_E_RC_QP_BOUND_PB);
+       /** max P frame QP */
+       reg &= ~(0xFF << 8);
+       reg |= ((p_mpeg4->rc_max_qp_p & 0xFF) << 8);
+       /** min P frame QP */
+       reg &= ~(0xFF);
+       reg |= p_mpeg4->rc_min_qp_p & 0xFF;
+       MFC_WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND_PB);
+
+       mfc_debug_leave();
+}
+
+void s5p_mfc_set_enc_params_vp8(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc *enc = ctx->enc_priv;
+       struct s5p_mfc_enc_params *p = &enc->params;
+       struct s5p_mfc_vp8_enc_params *p_vp8 = &p->codec.vp8;
+       unsigned int reg = 0;
+       int i;
+
+       mfc_debug_enter();
+
+       mfc_set_enc_params(ctx);
+
+       if (p_vp8->num_hier_layer & 0x3) {
+               /* set gop_size without i_frm_ctrl mode */
+               mfc_set_gop_size(ctx, 0);
+       } else {
+               /* set gop_size with i_frm_ctrl mode */
+               mfc_set_gop_size(ctx, 1);
+       }
+
+       /* profile*/
+       reg = 0;
+       reg |= (p_vp8->vp8_version) ;
+       MFC_WRITEL(reg, S5P_FIMV_E_PICTURE_PROFILE);
+
+       reg = MFC_READL(S5P_FIMV_E_VP8_OPTION);
+       /* if num_refs_for_p is 2, the performance falls by half */
+       reg &= ~(0x1);
+       reg |= (p->num_refs_for_p - 1) & 0x1;
+       /* vp8 partition is possible as below value: 1/2/4/8 */
+       if (p_vp8->vp8_numberofpartitions & 0x1) {
+               if (p_vp8->vp8_numberofpartitions > 1)
+                       mfc_err_ctx("partition should be even num (%d)\n",
+                                       p_vp8->vp8_numberofpartitions);
+               p_vp8->vp8_numberofpartitions = (p_vp8->vp8_numberofpartitions & ~0x1);
+       }
+       reg &= ~(0xF << 3);
+       reg |= (p_vp8->vp8_numberofpartitions & 0xF) << 3;
+       reg &= ~(0x1 << 10);
+       reg |= (p_vp8->intra_4x4mode_disable & 0x1) << 10;
+       /* Temporal SVC - hier qp enable */
+       reg &= ~(0x1 << 11);
+       reg |= (p_vp8->hier_qp_enable & 0x1) << 11;
+       /* Disable IVF header */
+       reg &= ~(0x1 << 12);
+       reg |= ((p->ivf_header_disable & 0x1) << 12);
+       MFC_WRITEL(reg, S5P_FIMV_E_VP8_OPTION);
+
+       reg = MFC_READL(S5P_FIMV_E_VP8_GOLDEN_FRAME_OPTION);
+       reg &= ~(0x1);
+       reg |= (p_vp8->vp8_goldenframesel & 0x1);
+       reg &= ~(0xFFFF << 1);
+       reg |= (p_vp8->vp8_gfrefreshperiod & 0xFFFF) << 1;
+       MFC_WRITEL(reg, S5P_FIMV_E_VP8_GOLDEN_FRAME_OPTION);
+
+       /* Temporal SVC - layer number */
+       reg = MFC_READL(S5P_FIMV_E_NUM_T_LAYER);
+       reg &= ~(0x7);
+       reg |= p_vp8->num_hier_layer & 0x3;
+       reg &= ~(0x7 << 4);
+       reg |= 0x3 << 4;
+       reg &= ~(0x1 << 8);
+       reg |= (p->hier_bitrate_ctrl & 0x1) << 8;
+       MFC_WRITEL(reg, S5P_FIMV_E_NUM_T_LAYER);
+       mfc_debug(3, "[HIERARCHICAL] hier_qp_enable %d, num_hier_layer %d, NUM_T_LAYER 0x%x\n",
+                       p_vp8->hier_qp_enable, p_vp8->num_hier_layer, reg);
+
+       /* QP & Bitrate for each layer */
+       for (i = 0; i < 3; i++) {
+               MFC_WRITEL(p_vp8->hier_qp_layer[i],
+                               S5P_FIMV_E_HIERARCHICAL_QP_LAYER0 + i * 4);
+               /* If hier_bitrate_ctrl is set to 1, this is meaningless */
+               MFC_WRITEL(p_vp8->hier_bit_layer[i],
+                               S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER0 + i * 4);
+               mfc_debug(3, "[HIERARCHICAL] layer[%d] QP: %#x, bitrate: %#x(FW ctrl: %d)\n",
+                                       i, p_vp8->hier_qp_layer[i],
+                                       p_vp8->hier_bit_layer[i], p->hier_bitrate_ctrl);
+       }
+
+       reg = 0;
+       reg |= (p_vp8->vp8_filtersharpness & 0x7);
+       reg |= (p_vp8->vp8_filterlevel & 0x3f) << 8;
+       MFC_WRITEL(reg, S5P_FIMV_E_VP8_FILTER_OPTION);
+
+       /* qp */
+       reg = MFC_READL(S5P_FIMV_E_FIXED_PICTURE_QP);
+       reg &= ~(0xFF << 24);
+       reg |= ((p->config_qp & 0xFF) << 24);
+       reg &= ~(0xFF << 8);
+       reg |= ((p_vp8->rc_p_frame_qp & 0xFF) << 8);
+       reg &= ~(0xFF);
+       reg |= (p_vp8->rc_frame_qp & 0xFF);
+       MFC_WRITEL(reg, S5P_FIMV_E_FIXED_PICTURE_QP);
+
+       /* frame rate */
+       p->rc_frame_delta = FRAME_DELTA_DEFAULT;
+       reg = MFC_READL(S5P_FIMV_E_RC_FRAME_RATE);
+       reg &= ~(0xFFFF << 16);
+       reg |= (p->rc_framerate << 16);
+       reg &= ~(0xFFFF);
+       reg |= (p->rc_frame_delta & 0xFFFF);
+       MFC_WRITEL(reg, S5P_FIMV_E_RC_FRAME_RATE);
+
+       /* rate control config. */
+       reg = MFC_READL(S5P_FIMV_E_RC_CONFIG);
+       /** frame QP */
+       reg &= ~(0xFF);
+       reg |= (p_vp8->rc_frame_qp & 0xFF);
+       MFC_WRITEL(reg, S5P_FIMV_E_RC_CONFIG);
+
+       /* max & min value of QP for I frame */
+       reg = MFC_READL(S5P_FIMV_E_RC_QP_BOUND);
+       /** max I frame QP */
+       reg &= ~(0xFF << 8);
+       reg |= ((p_vp8->rc_max_qp & 0xFF) << 8);
+       /** min I frame QP */
+       reg &= ~(0xFF);
+       reg |= (p_vp8->rc_min_qp & 0xFF);
+       MFC_WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND);
+
+       /* max & min value of QP for P/B frame */
+       reg = MFC_READL(S5P_FIMV_E_RC_QP_BOUND_PB);
+       /** max P frame QP */
+       reg &= ~(0xFF << 8);
+       reg |= ((p_vp8->rc_max_qp_p & 0xFF) << 8);
+       /** min P frame QP */
+       reg &= ~(0xFF);
+       reg |= p_vp8->rc_min_qp_p & 0xFF;
+       MFC_WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND_PB);
+
+       mfc_debug_leave();
+}
+
+void s5p_mfc_set_enc_params_vp9(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc *enc = ctx->enc_priv;
+       struct s5p_mfc_enc_params *p = &enc->params;
+       struct s5p_mfc_vp9_enc_params *p_vp9 = &p->codec.vp9;
+       unsigned int reg = 0;
+       int i;
+
+       mfc_debug_enter();
+
+       mfc_set_enc_params(ctx);
+
+       if (p_vp9->num_hier_layer & 0x3) {
+               /* set gop_size without i_frm_ctrl mode */
+               mfc_set_gop_size(ctx, 0);
+       } else {
+               /* set gop_size with i_frm_ctrl mode */
+               mfc_set_gop_size(ctx, 1);
+       }
+
+       /* profile*/
+       reg = 0;
+       reg |= p_vp9->vp9_version;
+       /* bit depth minus8 */
+       if (ctx->is_10bit) {
+               reg &= ~(0x3F << 17);
+               reg |= (0x2 << 17);
+               reg |= (0x2 << 20);
+       }
+       MFC_WRITEL(reg, S5P_FIMV_E_PICTURE_PROFILE);
+
+       /* for only information about wrong setting */
+       if (ctx->is_422) {
+               if ((p_vp9->vp9_version != S5P_FIMV_E_PROFILE_VP9_PROFILE1) &&
+                       (p_vp9->vp9_version != S5P_FIMV_E_PROFILE_VP9_PROFILE3)) {
+                       mfc_err_ctx("4:2:2 format is not matched with profile(%d)\n",
+                                       p_vp9->vp9_version);
+               }
+       }
+       if (ctx->is_10bit) {
+               if ((p_vp9->vp9_version != S5P_FIMV_E_PROFILE_VP9_PROFILE2) &&
+                       (p_vp9->vp9_version != S5P_FIMV_E_PROFILE_VP9_PROFILE3)) {
+                       mfc_err_ctx("[10BIT] format is not matched with profile(%d)\n",
+                                       p_vp9->vp9_version);
+               }
+       }
+
+       reg = MFC_READL(S5P_FIMV_E_VP9_OPTION);
+       /* if num_refs_for_p is 2, the performance falls by half */
+       reg &= ~(0x1);
+       reg |= (p->num_refs_for_p - 1) & 0x1;
+       reg &= ~(0x1 << 1);
+       reg |= (p_vp9->intra_pu_split_disable & 0x1) << 1;
+       reg &= ~(0x1 << 3);
+       reg |= (p_vp9->max_partition_depth & 0x1) << 3;
+       /* Temporal SVC - hier qp enable */
+       reg &= ~(0x1 << 11);
+       reg |= ((p_vp9->hier_qp_enable & 0x1) << 11);
+       /* Disable IVF header */
+       reg &= ~(0x1 << 12);
+       reg |= ((p->ivf_header_disable & 0x1) << 12);
+       MFC_WRITEL(reg, S5P_FIMV_E_VP9_OPTION);
+
+       reg = MFC_READL(S5P_FIMV_E_VP9_GOLDEN_FRAME_OPTION);
+       reg &= ~(0x1);
+       reg |= (p_vp9->vp9_goldenframesel & 0x1);
+       reg &= ~(0xFFFF << 1);
+       reg |= (p_vp9->vp9_gfrefreshperiod & 0xFFFF) << 1;
+       MFC_WRITEL(reg, S5P_FIMV_E_VP9_GOLDEN_FRAME_OPTION);
+
+       /* Temporal SVC - layer number */
+       reg = MFC_READL(S5P_FIMV_E_NUM_T_LAYER);
+       reg &= ~(0x7);
+       reg |= p_vp9->num_hier_layer & 0x3;
+       reg &= ~(0x7 << 4);
+       reg |= 0x3 << 4;
+       reg &= ~(0x1 << 8);
+       reg |= (p->hier_bitrate_ctrl & 0x1) << 8;
+       MFC_WRITEL(reg, S5P_FIMV_E_NUM_T_LAYER);
+       mfc_debug(3, "[HIERARCHICAL] hier_qp_enable %d, num_hier_layer %d, NUM_T_LAYER 0x%x\n",
+                       p_vp9->hier_qp_enable, p_vp9->num_hier_layer, reg);
+
+       /* QP & Bitrate for each layer */
+       for (i = 0; i < 3; i++) {
+               MFC_WRITEL(p_vp9->hier_qp_layer[i],
+                               S5P_FIMV_E_HIERARCHICAL_QP_LAYER0 + i * 4);
+               /* If hier_bitrate_ctrl is set to 1, this is meaningless */
+               MFC_WRITEL(p_vp9->hier_bit_layer[i],
+                               S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER0 + i * 4);
+               mfc_debug(3, "[HIERARCHICAL] layer[%d] QP: %#x, bitrate: %#x (FW ctrl: %d)\n",
+                                       i, p_vp9->hier_qp_layer[i],
+                                       p_vp9->hier_bit_layer[i], p->hier_bitrate_ctrl);
+       }
+
+       /* qp */
+       reg = MFC_READL(S5P_FIMV_E_FIXED_PICTURE_QP);
+       reg &= ~(0xFF << 24);
+       reg |= ((p->config_qp & 0xFF) << 24);
+       reg &= ~(0xFF << 8);
+       reg |= ((p_vp9->rc_p_frame_qp & 0xFF) << 8);
+       reg &= ~(0xFF);
+       reg |= (p_vp9->rc_frame_qp & 0xFF);
+       MFC_WRITEL(reg, S5P_FIMV_E_FIXED_PICTURE_QP);
+
+       /* frame rate */
+       p->rc_frame_delta = FRAME_DELTA_DEFAULT;
+       reg = MFC_READL(S5P_FIMV_E_RC_FRAME_RATE);
+       reg &= ~(0xFFFF << 16);
+       reg |= (p->rc_framerate << 16);
+       reg &= ~(0xFFFF);
+       reg |= (p->rc_frame_delta & 0xFFFF);
+       MFC_WRITEL(reg, S5P_FIMV_E_RC_FRAME_RATE);
+
+       /* rate control config. */
+       reg = MFC_READL(S5P_FIMV_E_RC_CONFIG);
+       /** frame QP */
+       reg &= ~(0xFF);
+       reg |= (p_vp9->rc_frame_qp & 0xFF);
+       MFC_WRITEL(reg, S5P_FIMV_E_RC_CONFIG);
+
+       /* max & min value of QP for I frame */
+       reg = MFC_READL(S5P_FIMV_E_RC_QP_BOUND);
+       /** max I frame QP */
+       reg &= ~(0xFF << 8);
+       reg |= ((p_vp9->rc_max_qp & 0xFF) << 8);
+       /** min I frame QP */
+       reg &= ~(0xFF);
+       reg |= (p_vp9->rc_min_qp & 0xFF);
+       MFC_WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND);
+
+       /* max & min value of QP for P/B frame */
+       reg = MFC_READL(S5P_FIMV_E_RC_QP_BOUND_PB);
+       /** max P frame QP */
+       reg &= ~(0xFF << 8);
+       reg |= ((p_vp9->rc_max_qp_p & 0xFF) << 8);
+       /** min P frame QP */
+       reg &= ~(0xFF);
+       reg |= p_vp9->rc_min_qp_p & 0xFF;
+       MFC_WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND_PB);
+
+       if (MFC_FEATURE_SUPPORT(dev, dev->pdata->color_aspect_enc) && p->check_color_range) {
+               reg = MFC_READL(S5P_FIMV_E_VIDEO_SIGNAL_TYPE);
+               /* VIDEO_SIGNAL_TYPE_FLAG */
+               reg |= 0x1 << 31;
+               /* COLOR_SPACE: VP9 uses colour_primaries interface for color space */
+               reg &= ~(0x1F << 26);
+               reg |= p->colour_primaries << 26;
+               /* COLOR_RANGE */
+               reg &= ~(0x1 << 25);
+               reg |= p->color_range << 25;
+               MFC_WRITEL(reg, S5P_FIMV_E_VIDEO_SIGNAL_TYPE);
+               mfc_debug(2, "[HDR] VP9 ENC Color aspect: range(%s), space(%d)\n",
+                               p->color_range ? "Full" : "Limited", p->colour_primaries);
+       } else {
+               MFC_WRITEL(0, S5P_FIMV_E_VIDEO_SIGNAL_TYPE);
+       }
+
+       mfc_debug_leave();
+}
+
+void s5p_mfc_set_enc_params_hevc(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc *enc = ctx->enc_priv;
+       struct s5p_mfc_enc_params *p = &enc->params;
+       struct s5p_mfc_hevc_enc_params *p_hevc = &p->codec.hevc;
+       unsigned int reg = 0;
+       int i;
+
+       mfc_debug_enter();
+
+       mfc_set_enc_params(ctx);
+
+       if (p_hevc->num_hier_layer & 0x7) {
+               /* set gop_size without i_frm_ctrl mode */
+               mfc_set_gop_size(ctx, 0);
+       } else {
+               /* set gop_size with i_frm_ctrl mode */
+               mfc_set_gop_size(ctx, 1);
+       }
+
+       /* UHD encoding case */
+       if (IS_UHD_RES(ctx)) {
+               p_hevc->level = 51;
+               p_hevc->tier_flag = 0;
+       /* this tier_flag can be changed */
+       }
+
+       /* tier_flag & level & profile */
+       reg = 0;
+       /* profile */
+       reg |= p_hevc->profile & 0xf;
+       /* level */
+       reg &= ~(0xFF << 8);
+       reg |= (p_hevc->level << 8);
+       /* tier_flag - 0 ~ 1 */
+       reg |= (p_hevc->tier_flag << 16);
+       /* bit depth minus8 */
+       if (ctx->is_10bit) {
+               reg &= ~(0x3F << 17);
+               reg |= (0x2 << 17);
+               reg |= (0x2 << 20);
+       }
+       MFC_WRITEL(reg, S5P_FIMV_E_PICTURE_PROFILE);
+
+       /* for only information about wrong setting */
+       if (ctx->is_422) {
+               if ((p_hevc->profile != S5P_FIMV_E_PROFILE_HEVC_MAIN_422_10_INTRA) &&
+                       (p_hevc->profile != S5P_FIMV_E_PROFILE_HEVC_MAIN_422_10)) {
+                       mfc_err_ctx("4:2:2 format is not matched with profile(%d)\n",
+                                       p_hevc->profile);
+               }
+       }
+       if (ctx->is_10bit) {
+               if ((p_hevc->profile != S5P_FIMV_E_PROFILE_HEVC_MAIN_422_10_INTRA) &&
+                       (p_hevc->profile != S5P_FIMV_E_PROFILE_HEVC_MAIN_10) &&
+                       (p_hevc->profile != S5P_FIMV_E_PROFILE_HEVC_MAIN_422_10)) {
+                       mfc_err_ctx("[10BIT] format is not matched with profile(%d)\n",
+                                       p_hevc->profile);
+               }
+       }
+
+       /* max partition depth */
+       reg = MFC_READL(S5P_FIMV_E_HEVC_OPTIONS);
+       reg &= ~(0x3);
+       reg |= (p_hevc->max_partition_depth & 0x1);
+       /* if num_refs_for_p is 2, the performance falls by half */
+       reg &= ~(0x1 << 2);
+       reg |= (p->num_refs_for_p - 1) << 2;
+       reg &= ~(0x3 << 3);
+       reg |= (p_hevc->refreshtype & 0x3) << 3;
+       reg &= ~(0x1 << 5);
+       reg |= (p_hevc->const_intra_period_enable & 0x1) << 5;
+       reg &= ~(0x1 << 6);
+       reg |= (p_hevc->lossless_cu_enable & 0x1) << 6;
+       reg &= ~(0x1 << 7);
+       reg |= (p_hevc->wavefront_enable & 0x1) << 7;
+       reg &= ~(0x1 << 8);
+       reg |= (p_hevc->loopfilter_disable & 0x1) << 8;
+       reg &= ~(0x1 << 9);
+       reg |= (p_hevc->loopfilter_across & 0x1) << 9;
+       reg &= ~(0x1 << 10);
+       reg |= (p_hevc->enable_ltr & 0x1) << 10;
+       reg &= ~(0x1 << 11);
+       reg |= (p_hevc->hier_qp_enable & 0x1) << 11;
+       reg &= ~(0x1 << 13);
+       reg |= (p_hevc->general_pb_enable & 0x1) << 13;
+       reg &= ~(0x1 << 14);
+       reg |= (p_hevc->temporal_id_enable & 0x1) << 14;
+       reg &= ~(0x1 << 15);
+       reg |= (p_hevc->strong_intra_smooth & 0x1) << 15;
+       reg &= ~(0x1 << 16);
+       reg |= (p_hevc->intra_pu_split_disable & 0x1) << 16;
+       reg &= ~(0x1 << 17);
+       reg |= (p_hevc->tmv_prediction_disable & 0x1) << 17;
+       reg &= ~(0x7 << 18);
+       reg |= (p_hevc->max_num_merge_mv & 0x7) << 18;
+       reg &= ~(0x1 << 23);
+       reg |= (p_hevc->encoding_nostartcode_enable & 0x1) << 23;
+       reg &= ~(0x1 << 26);
+       reg |= (p_hevc->prepend_sps_pps_to_idr & 0x1) << 26;
+       /* enable sps pps control in OTF scenario */
+       if (ctx->otf_handle) {
+               reg |= (0x1 << 26);
+               mfc_debug(2, "[OTF] SPS_PPS_CONTROL enabled\n");
+       }
+       /* Weighted Prediction enable */
+       reg &= ~(0x1 << 28);
+       reg |= ((p->weighted_enable & 0x1) << 28);
+       /* 30bit is 32x32 transform. If it is enabled, the performance falls by half */
+       reg &= ~(0x1 << 30);
+       MFC_WRITEL(reg, S5P_FIMV_E_HEVC_OPTIONS);
+       /* refresh period */
+       reg = MFC_READL(S5P_FIMV_E_HEVC_REFRESH_PERIOD);
+       reg &= ~(0xFFFF);
+       reg |= (p_hevc->refreshperiod & 0xFFFF);
+       MFC_WRITEL(reg, S5P_FIMV_E_HEVC_REFRESH_PERIOD);
+       /* loop filter setting */
+       MFC_WRITEL(0, S5P_FIMV_E_HEVC_LF_BETA_OFFSET_DIV2);
+       MFC_WRITEL(0, S5P_FIMV_E_HEVC_LF_TC_OFFSET_DIV2);
+       if (!p_hevc->loopfilter_disable) {
+               MFC_WRITEL(p_hevc->lf_beta_offset_div2, S5P_FIMV_E_HEVC_LF_BETA_OFFSET_DIV2);
+               MFC_WRITEL(p_hevc->lf_tc_offset_div2, S5P_FIMV_E_HEVC_LF_TC_OFFSET_DIV2);
+       }
+       /* long term reference */
+       if (p_hevc->enable_ltr) {
+               reg = 0;
+               reg |= (p_hevc->store_ref & 0x3);
+               reg &= ~(0x3 << 2);
+               reg |= (p_hevc->user_ref & 0x3) << 2;
+               MFC_WRITEL(reg, S5P_FIMV_E_HEVC_NAL_CONTROL);
+       }
+
+       /* Temporal SVC - qp type, layer number */
+       reg = MFC_READL(S5P_FIMV_E_NUM_T_LAYER);
+       reg &= ~(0x1 << 3);
+       reg |= (p_hevc->hier_qp_type & 0x1) << 3;
+       reg &= ~(0x7);
+       reg |= p_hevc->num_hier_layer & 0x7;
+       reg &= ~(0x7 << 4);
+       if (p_hevc->hier_ref_type) {
+               reg |= 0x1 << 7;
+               reg |= (p->num_hier_max_layer & 0x7) << 4;
+       } else {
+               reg &= ~(0x1 << 7);
+               reg |= 0x7 << 4;
+       }
+       reg &= ~(0x1 << 8);
+       reg |= (p->hier_bitrate_ctrl & 0x1) << 8;
+       MFC_WRITEL(reg, S5P_FIMV_E_NUM_T_LAYER);
+       mfc_debug(3, "[HIERARCHICAL] hier_qp_enable %d, enable_ltr %d, "
+               "num_hier_layer %d, max_layer %d, hier_ref_type %d, NUM_T_LAYER 0x%x\n",
+               p_hevc->hier_qp_enable, p_hevc->enable_ltr, p_hevc->num_hier_layer,
+               p->num_hier_max_layer, p_hevc->hier_ref_type, reg);
+
+       /* QP & Bitrate for each layer */
+       for (i = 0; i < 7; i++) {
+               MFC_WRITEL(p_hevc->hier_qp_layer[i],
+                       S5P_FIMV_E_HIERARCHICAL_QP_LAYER0 + i * 4);
+               MFC_WRITEL(p_hevc->hier_bit_layer[i],
+                       S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER0 + i * 4);
+               mfc_debug(3, "[HIERARCHICAL] layer[%d] QP: %#x, bitrate: %d(FW ctrl: %d)\n",
+                                       i, p_hevc->hier_qp_layer[i],
+                                       p_hevc->hier_bit_layer[i], p->hier_bitrate_ctrl);
+       }
+
+       /* rate control config. */
+       reg = MFC_READL(S5P_FIMV_E_RC_CONFIG);
+       /** frame QP */
+       reg &= ~(0xFF);
+       reg |= (p_hevc->rc_frame_qp & 0xFF);
+       MFC_WRITEL(reg, S5P_FIMV_E_RC_CONFIG);
+
+       /* frame rate */
+       p->rc_frame_delta = FRAME_DELTA_DEFAULT;
+       reg = MFC_READL(S5P_FIMV_E_RC_FRAME_RATE);
+       reg &= ~(0xFFFF << 16);
+       reg |= (p->rc_framerate << 16);
+       reg &= ~(0xFFFF);
+       reg |= (p->rc_frame_delta & 0xFFFF);
+       MFC_WRITEL(reg, S5P_FIMV_E_RC_FRAME_RATE);
+
+       /* max & min value of QP for I frame */
+       reg = MFC_READL(S5P_FIMV_E_RC_QP_BOUND);
+       /** max I frame QP */
+       reg &= ~(0xFF << 8);
+       reg |= ((p_hevc->rc_max_qp & 0xFF) << 8);
+       /** min I frame QP */
+       reg &= ~(0xFF);
+       reg |= (p_hevc->rc_min_qp & 0xFF);
+       MFC_WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND);
+
+       /* max & min value of QP for P/B frame */
+       reg = MFC_READL(S5P_FIMV_E_RC_QP_BOUND_PB);
+       /** max B frame QP */
+       reg &= ~(0xFF << 24);
+       reg |= ((p_hevc->rc_max_qp_b & 0xFF) << 24);
+       /** min B frame QP */
+       reg &= ~(0xFF << 16);
+       reg |= ((p_hevc->rc_min_qp_b & 0xFF) << 16);
+       /** max P frame QP */
+       reg &= ~(0xFF << 8);
+       reg |= ((p_hevc->rc_max_qp_p & 0xFF) << 8);
+       /** min P frame QP */
+       reg &= ~(0xFF);
+       reg |= p_hevc->rc_min_qp_p & 0xFF;
+       MFC_WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND_PB);
+
+       reg = MFC_READL(S5P_FIMV_E_FIXED_PICTURE_QP);
+       reg &= ~(0xFF << 24);
+       reg |= ((p->config_qp & 0xFF) << 24);
+       reg &= ~(0xFF << 16);
+       reg |= ((p_hevc->rc_b_frame_qp & 0xFF) << 16);
+       reg &= ~(0xFF << 8);
+       reg |= ((p_hevc->rc_p_frame_qp & 0xFF) << 8);
+       reg &= ~(0xFF);
+       reg |= (p_hevc->rc_frame_qp & 0xFF);
+       MFC_WRITEL(reg, S5P_FIMV_E_FIXED_PICTURE_QP);
+
+       /* ROI enable: it must set on SEQ_START only for HEVC encoder */
+       reg = MFC_READL(S5P_FIMV_E_RC_ROI_CTRL);
+       reg &= ~(0x1);
+       reg |= (p->roi_enable);
+       MFC_WRITEL(reg, S5P_FIMV_E_RC_ROI_CTRL);
+       mfc_debug(3, "[ROI] HEVC ROI enable\n");
+
+       if (MFC_FEATURE_SUPPORT(dev, dev->pdata->color_aspect_enc) && p->check_color_range) {
+               reg = MFC_READL(S5P_FIMV_E_VIDEO_SIGNAL_TYPE);
+               /* VIDEO_SIGNAL_TYPE_FLAG */
+               reg |= 0x1 << 31;
+               /* COLOR_RANGE */
+               reg &= ~(0x1 << 25);
+               reg |= p->color_range << 25;
+               if ((p->colour_primaries != 0) && (p->transfer_characteristics != 0) &&
+                               (p->matrix_coefficients != 3)) {
+                       /* COLOUR_DESCRIPTION_PRESENT_FLAG */
+                       reg |= 0x1 << 24;
+                       /* COLOUR_PRIMARIES */
+                       reg &= ~(0xFF << 16);
+                       reg |= p->colour_primaries << 16;
+                       /* TRANSFER_CHARACTERISTICS */
+                       reg &= ~(0xFF << 8);
+                       reg |= p->transfer_characteristics << 8;
+                       /* MATRIX_COEFFICIENTS */
+                       reg &= ~(0xFF);
+                       reg |= p->matrix_coefficients;
+               } else {
+                       reg &= ~(0x1 << 24);
+               }
+               MFC_WRITEL(reg, S5P_FIMV_E_VIDEO_SIGNAL_TYPE);
+               mfc_debug(2, "[HDR] HEVC ENC Color aspect: range(%s), pri(%d), trans(%d), mat(%d)\n",
+                               p->color_range ? "Full" : "Limited", p->colour_primaries,
+                               p->transfer_characteristics, p->matrix_coefficients);
+       } else {
+               MFC_WRITEL(0, S5P_FIMV_E_VIDEO_SIGNAL_TYPE);
+       }
+
+       if (MFC_FEATURE_SUPPORT(dev, dev->pdata->static_info_enc) &&
+                       p->static_info_enable && ctx->is_10bit) {
+               reg = MFC_READL(S5P_FIMV_E_HEVC_OPTIONS_2);
+               /* HDR_STATIC_INFO_ENABLE */
+               reg |= p->static_info_enable;
+               MFC_WRITEL(reg, S5P_FIMV_E_HEVC_OPTIONS_2);
+               /* MAX_PIC_AVERAGE_LIGHT & MAX_CONTENT_LIGHT */
+               reg = p->max_pic_average_light;
+               reg |= (p->max_content_light << 16);
+               MFC_WRITEL(reg, S5P_FIMV_E_CONTENT_LIGHT_LEVEL_INFO_SEI);
+               /* MAX_DISPLAY_LUMINANCE */
+               MFC_WRITEL(p->max_display_luminance, S5P_FIMV_E_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_0);
+               /* MIN DISPLAY LUMINANCE */
+               MFC_WRITEL(p->min_display_luminance, S5P_FIMV_E_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_1);
+               /* WHITE_POINT */
+               MFC_WRITEL(p->white_point, S5P_FIMV_E_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_2);
+               /* DISPLAY PRIMARIES_0 */
+               MFC_WRITEL(p->display_primaries_0, S5P_FIMV_E_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_3);
+               /* DISPLAY PRIMARIES_1 */
+               MFC_WRITEL(p->display_primaries_1, S5P_FIMV_E_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_4);
+               /* DISPLAY PRIMARIES_2 */
+               MFC_WRITEL(p->display_primaries_2, S5P_FIMV_E_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_5);
+
+               mfc_debug(2, "[HDR] HEVC ENC static info: enable(%d), max_pic(0x%x), max_content(0x%x)\n",
+                               p->static_info_enable, p->max_pic_average_light, p->max_content_light);
+               mfc_debug(2, "[HDR] max_disp(0x%x), min_disp(0x%x), white_point(0x%x)\n",
+                               p->max_display_luminance, p->min_display_luminance, p->white_point);
+               mfc_debug(2, "[HDR] disp_pri_0(0x%x), disp_pri_1(0x%x), disp_pri_2(0x%x)\n",
+                               p->display_primaries_0, p->display_primaries_1, p->display_primaries_2);
+       } else {
+               reg = MFC_READL(S5P_FIMV_E_HEVC_OPTIONS_2);
+               /* HDR_STATIC_INFO_ENABLE */
+               reg &=  ~(0x1);
+               MFC_WRITEL(reg, S5P_FIMV_E_HEVC_OPTIONS_2);
+       }
+
+       mfc_debug_leave();
+}
+
+void s5p_mfc_set_enc_params_bpg(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc *enc = ctx->enc_priv;
+       struct s5p_mfc_enc_params *p = &enc->params;
+       struct s5p_mfc_bpg_enc_params *p_bpg = &p->codec.bpg;
+       unsigned int reg = 0;
+
+       mfc_set_enc_params(ctx);
+
+       /* extension tag */
+       reg = p_bpg->thumb_size + p_bpg->exif_size;
+       MFC_WRITEL(reg, S5P_FIMV_E_BPG_EXTENSION_DATA_SIZE);
+       mfc_debug(3, "main image extension size %d (thumbnail: %d, exif: %d)\n",
+                       reg, p_bpg->thumb_size, p_bpg->exif_size);
+
+       /* profile & level */
+       reg = 0;
+       /** profile */
+       reg &= ~(0xF);
+       /* bit depth minus8 */
+       if (ctx->is_10bit) {
+               reg &= ~(0x3F << 17);
+               reg |= (0x2 << 17);
+               reg |= (0x2 << 20);
+               /* fixed profile */
+               if (ctx->is_422)
+                       reg |= 0x1;
+       }
+       MFC_WRITEL(reg, S5P_FIMV_E_PICTURE_PROFILE);
+}
diff --git a/drivers/media/platform/exynos/mfc/mfc_enc_param.h b/drivers/media/platform/exynos/mfc/mfc_enc_param.h
new file mode 100644 (file)
index 0000000..3e7fcf4
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_enc_param.h
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __MFC_ENC_PARAM_H
+#define __MFC_ENC_PARAM_H __FILE__
+
+#include "mfc_common.h"
+
+void s5p_mfc_set_slice_mode(struct s5p_mfc_ctx *ctx);
+void s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx);
+void s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx);
+void s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx);
+void s5p_mfc_set_enc_params_vp8(struct s5p_mfc_ctx *ctx);
+void s5p_mfc_set_enc_params_vp9(struct s5p_mfc_ctx *ctx);
+void s5p_mfc_set_enc_params_hevc(struct s5p_mfc_ctx *ctx);
+void s5p_mfc_set_enc_params_bpg(struct s5p_mfc_ctx *ctx);
+
+#endif /* __MFC_ENC_PARAM_H */
diff --git a/drivers/media/platform/exynos/mfc/mfc_enc_vb2_ops.c b/drivers/media/platform/exynos/mfc/mfc_enc_vb2_ops.c
new file mode 100644 (file)
index 0000000..aade99e
--- /dev/null
@@ -0,0 +1,478 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_enc_vb2_ops.c
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include "mfc_common.h"
+
+#include "mfc_hwlock.h"
+#include "mfc_nal_q.h"
+#include "mfc_opr.h"
+#include "mfc_sync.h"
+
+#include "mfc_qos.h"
+#include "mfc_queue.h"
+#include "mfc_utils.h"
+#include "mfc_buf.h"
+#include "mfc_mem.h"
+
+static int s5p_mfc_enc_queue_setup(struct vb2_queue *vq,
+                               unsigned int *buf_count, unsigned int *plane_count,
+                               unsigned int psize[], struct device *alloc_devs[])
+{
+       struct s5p_mfc_dev *dev;
+       struct s5p_mfc_ctx *ctx = vq->drv_priv;
+       struct s5p_mfc_enc *enc = ctx->enc_priv;
+       struct s5p_mfc_raw_info *raw;
+       int i;
+
+       mfc_debug_enter();
+
+       dev = ctx->dev;
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return -EINVAL;
+       }
+
+       if (ctx->state != MFCINST_GOT_INST &&
+           vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               mfc_err_ctx("invalid state: %d\n", ctx->state);
+               return -EINVAL;
+       }
+       if (ctx->state >= MFCINST_FINISHING &&
+           vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               mfc_err_ctx("invalid state: %d\n", ctx->state);
+               return -EINVAL;
+       }
+
+       if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               mfc_debug(4, "enc dst\n");
+               if (ctx->dst_fmt)
+                       *plane_count = ctx->dst_fmt->mem_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] = enc->dst_buf_size;
+               alloc_devs[0] = dev->device;
+       } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               mfc_debug(4, "enc src\n");
+               raw = &ctx->raw_buf;
+
+               if (ctx->src_fmt)
+                       *plane_count = ctx->src_fmt->mem_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;
+
+               if (*plane_count == 1) {
+                       psize[0] = raw->total_plane_size;
+                       alloc_devs[0] = dev->device;
+               } else {
+                       for (i = 0; i < *plane_count; i++) {
+                               psize[i] = raw->plane_size[i];
+                               alloc_devs[i] = dev->device;
+                       }
+               }
+       } else {
+               mfc_err_ctx("invalid queue type: %d\n", vq->type);
+               return -EINVAL;
+       }
+
+       mfc_debug(2, "buf_count: %d, plane_count: %d, type: %#x\n",
+                       *buf_count, *plane_count, vq->type);
+       for (i = 0; i < *plane_count; i++)
+               mfc_debug(2, "plane[%d] size: %d\n", i, psize[i]);
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+static void s5p_mfc_enc_unlock(struct vb2_queue *q)
+{
+       struct s5p_mfc_ctx *ctx = q->drv_priv;
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       mutex_unlock(&dev->mfc_mutex);
+}
+
+static void s5p_mfc_enc_lock(struct vb2_queue *q)
+{
+       struct s5p_mfc_ctx *ctx = q->drv_priv;
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       mutex_lock(&dev->mfc_mutex);
+}
+
+static int s5p_mfc_enc_buf_init(struct vb2_buffer *vb)
+{
+       struct vb2_queue *vq = vb->vb2_queue;
+       struct s5p_mfc_ctx *ctx = vq->drv_priv;
+       int ret;
+
+       mfc_debug_enter();
+
+       if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               ret = s5p_mfc_check_vb_with_fmt(ctx->dst_fmt, vb);
+               if (ret < 0)
+                       return ret;
+
+               if (call_cop(ctx, init_buf_ctrls, ctx, MFC_CTRL_TYPE_DST,
+                                       vb->index) < 0)
+                       mfc_err_ctx("failed in init_buf_ctrls\n");
+
+       } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               ret = s5p_mfc_check_vb_with_fmt(ctx->src_fmt, vb);
+               if (ret < 0)
+                       return ret;
+
+               if (call_cop(ctx, init_buf_ctrls, ctx, MFC_CTRL_TYPE_SRC,
+                                       vb->index) < 0)
+                       mfc_err_ctx("failed in init_buf_ctrls\n");
+       } else {
+               mfc_err_ctx("inavlid queue type: %d\n", vq->type);
+               return -EINVAL;
+       }
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+static int s5p_mfc_enc_buf_prepare(struct vb2_buffer *vb)
+{
+       struct vb2_queue *vq = vb->vb2_queue;
+       struct s5p_mfc_ctx *ctx = vq->drv_priv;
+       struct s5p_mfc_enc *enc = ctx->enc_priv;
+       struct s5p_mfc_raw_info *raw;
+       unsigned int index = vb->index;
+       struct s5p_mfc_buf *buf = vb_to_mfc_buf(vb);
+       struct dma_buf *bufcon_dmabuf[MFC_MAX_PLANES];
+       int i, mem_get_count = 0;
+       size_t buf_size;
+
+       mfc_debug_enter();
+
+       if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               buf_size = vb2_plane_size(vb, 0);
+               mfc_debug(2, "[STREAM] vb size: %lu, calc size: %u\n",
+                       buf_size, enc->dst_buf_size);
+
+               if (buf_size < enc->dst_buf_size) {
+                       mfc_err_ctx("[STREAM] size(%d) is smaller than (%d)\n",
+                                       buf_size, enc->dst_buf_size);
+                       return -EINVAL;
+               }
+
+               buf->addr[0][0] = s5p_mfc_mem_get_daddr_vb(vb, 0);
+       } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               raw = &ctx->raw_buf;
+               if (ctx->src_fmt->mem_planes == 1) {
+                       buf_size = vb2_plane_size(vb, 0);
+                       mfc_debug(2, "[FRAME] single plane vb size: %lu, calc size: %d\n",
+                                       buf_size, raw->total_plane_size);
+                       if (buf_size < raw->total_plane_size) {
+                               mfc_err_ctx("[FRAME] single plane size(%d) is smaller than (%d)\n",
+                                               buf_size, raw->total_plane_size);
+                               return -EINVAL;
+                       }
+               } else {
+                       for (i = 0; i < ctx->src_fmt->mem_planes; i++) {
+                               buf_size = vb2_plane_size(vb, i);
+                               mfc_debug(2, "[FRAME] plane[%d] vb size: %lu, calc size: %d\n",
+                                               i, buf_size, raw->plane_size[i]);
+                               if (buf_size < raw->plane_size[i]) {
+                                       mfc_err_ctx("[FRAME] plane[%d] size(%d) is smaller than (%d)\n",
+                                                       i, buf_size, raw->plane_size[i]);
+                                       return -EINVAL;
+                               }
+                       }
+               }
+
+               for (i = 0; i < ctx->src_fmt->mem_planes; i++) {
+                       bufcon_dmabuf[i] = dma_buf_get(vb->planes[i].m.fd);
+                       if (IS_ERR(bufcon_dmabuf[i])) {
+                               mfc_err_ctx("failed to get bufcon dmabuf\n");
+                               goto err_mem_put;
+                       }
+
+                       mem_get_count++;
+                       buf->num_bufs_in_batch = s5p_mfc_bufcon_get_buf_count(bufcon_dmabuf[i]);
+                       mfc_debug(3, "[BUFCON] num bufs in batch: %d\n", buf->num_bufs_in_batch);
+                       if (buf->num_bufs_in_batch == 0) {
+                               mfc_err_ctx("[BUFCON] bufs count couldn't be zero\n");
+                               goto err_mem_put;
+                       }
+
+                       if (buf->num_bufs_in_batch < 0)
+                               buf->num_bufs_in_batch = 0;
+
+                       if (!ctx->batch_mode && buf->num_bufs_in_batch > 0) {
+                               ctx->batch_mode = 1;
+                               mfc_debug(2, "[BUFCON] buffer batch mode enable\n");
+                       }
+
+                       if (buf->num_bufs_in_batch > 0) {
+                               if (s5p_mfc_bufcon_get_daddr(ctx, buf, bufcon_dmabuf[i], i)) {
+                                       mfc_err_ctx("[BUFCON] failed to get daddr[%d] in buffer container\n", i);
+                                       goto err_mem_put;
+                               }
+
+                               ctx->framerate = buf->num_valid_bufs * ENC_DEFAULT_CAM_CAPTURE_FPS;
+                               mfc_debug(3, "[BUFCON] framerate: %ld\n", ctx->framerate);
+
+                               dma_buf_put(bufcon_dmabuf[i]);
+                       } else {
+                               dma_addr_t start_raw;
+
+                               dma_buf_put(bufcon_dmabuf[i]);
+                               start_raw = s5p_mfc_mem_get_daddr_vb(vb, 0);
+                               if (start_raw == 0) {
+                                       mfc_err_ctx("Plane mem not allocated\n");
+                                       return -ENOMEM;
+                               }
+                               if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12N) {
+                                       buf->addr[0][0] = start_raw;
+                                       buf->addr[0][1] = NV12N_CBCR_BASE(start_raw,
+                                                       ctx->img_width,
+                                                       ctx->img_height);
+                               } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_YUV420N) {
+                                       buf->addr[0][0] = start_raw;
+                                       buf->addr[0][1] = YUV420N_CB_BASE(start_raw,
+                                                       ctx->img_width,
+                                                       ctx->img_height);
+                                       buf->addr[0][2] = YUV420N_CR_BASE(start_raw,
+                                                       ctx->img_width,
+                                                       ctx->img_height);
+                               } else {
+                                       buf->addr[0][i] = s5p_mfc_mem_get_daddr_vb(vb, i);
+                               }
+                       }
+               }
+
+               if (call_cop(ctx, to_buf_ctrls, ctx, &ctx->src_ctrls[index]) < 0)
+                       mfc_err_ctx("failed in to_buf_ctrls\n");
+       } else {
+               mfc_err_ctx("inavlid queue type: %d\n", vq->type);
+               return -EINVAL;
+       }
+
+       mfc_debug_leave();
+       return 0;
+
+err_mem_put:
+       for (i = 0; i < mem_get_count; i++)
+               dma_buf_put(bufcon_dmabuf[i]);
+
+       return -ENOMEM;
+}
+
+static void s5p_mfc_enc_buf_finish(struct vb2_buffer *vb)
+{
+       struct vb2_queue *vq = vb->vb2_queue;
+       struct s5p_mfc_ctx *ctx = vq->drv_priv;
+       unsigned int index = vb->index;
+
+
+       if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               if (call_cop(ctx, to_ctx_ctrls, ctx, &ctx->dst_ctrls[index]) < 0)
+                       mfc_err_ctx("failed in to_ctx_ctrls\n");
+       } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               if (call_cop(ctx, to_ctx_ctrls, ctx, &ctx->src_ctrls[index]) < 0)
+                       mfc_err_ctx("failed in to_ctx_ctrls\n");
+       }
+}
+
+static void s5p_mfc_enc_buf_cleanup(struct vb2_buffer *vb)
+{
+       struct vb2_queue *vq = vb->vb2_queue;
+       struct s5p_mfc_ctx *ctx = vq->drv_priv;
+       unsigned int index = vb->index;
+
+       mfc_debug_enter();
+
+       if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               if (call_cop(ctx, cleanup_buf_ctrls, ctx,
+                                       MFC_CTRL_TYPE_DST, index) < 0)
+                       mfc_err_ctx("failed in cleanup_buf_ctrls\n");
+       } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               if (call_cop(ctx, cleanup_buf_ctrls, ctx,
+                                       MFC_CTRL_TYPE_SRC, index) < 0)
+                       mfc_err_ctx("failed in cleanup_buf_ctrls\n");
+       } else {
+               mfc_err_ctx("s5p_mfc_enc_buf_cleanup: unknown queue type\n");
+       }
+
+       mfc_debug_leave();
+}
+
+static int s5p_mfc_enc_start_streaming(struct vb2_queue *q, unsigned int count)
+{
+       struct s5p_mfc_ctx *ctx = q->drv_priv;
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       /* If context is ready then dev = work->data;schedule it to run */
+       if (s5p_mfc_enc_ctx_ready(ctx)) {
+               s5p_mfc_set_bit(ctx->num, &dev->work_bits);
+       }
+
+       s5p_mfc_try_run(dev);
+
+       return 0;
+}
+
+static void s5p_mfc_enc_stop_streaming(struct vb2_queue *q)
+{
+       struct s5p_mfc_ctx *ctx = q->drv_priv;
+       struct s5p_mfc_dev *dev = ctx->dev;
+       int index = 0;
+       int aborted = 0;
+       int ret = 0;
+
+       mfc_info_ctx("enc stop_streaming is called, hwlock : %d, type : %d\n",
+                               test_bit(ctx->num, &dev->hwlock.bits), q->type);
+       MFC_TRACE_CTX("** ENC streamoff(type:%d)\n", q->type);
+
+       /* If a H/W operation is in progress, wait for it complete */
+       if (need_to_wait_nal_abort(ctx)) {
+               if (s5p_mfc_wait_for_done_ctx(ctx, S5P_FIMV_R2H_CMD_NAL_ABORT_RET)) {
+                       mfc_err_ctx("time out during nal abort\n");
+                       s5p_mfc_cleanup_work_bit_and_try_run(ctx);
+               }
+               aborted = 1;
+       }
+       MFC_TRACE_CTX_HWLOCK("**ENC streamoff(type:%d)\n", q->type);
+       ret = s5p_mfc_get_hwlock_ctx(ctx);
+       if (ret < 0) {
+               mfc_err_ctx("Failed to get hwlock\n");
+               return;
+       }
+
+       if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               s5p_mfc_cleanup_enc_dst_queue(ctx);
+
+               while (index < MFC_MAX_BUFFERS) {
+                       index = find_next_bit(&ctx->dst_ctrls_avail,
+                                       MFC_MAX_BUFFERS, index);
+                       if (index < MFC_MAX_BUFFERS)
+                               call_cop(ctx, reset_buf_ctrls, &ctx->dst_ctrls[index]);
+                       index++;
+               }
+       } else if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               if (ctx->state == MFCINST_RUNNING) {
+                       s5p_mfc_change_state(ctx, MFCINST_FINISHING);
+                       s5p_mfc_set_bit(ctx->num, &dev->work_bits);
+
+                       while (s5p_mfc_get_buf(&ctx->buf_queue_lock, &ctx->dst_buf_queue, MFC_BUF_NO_TOUCH_USED)) {
+                               ret = s5p_mfc_just_run(dev, ctx->num);
+                               if (ret) {
+                                       mfc_err_ctx("Failed to run MFC\n");
+                                       break;
+                               }
+                               if (s5p_mfc_wait_for_done_ctx(ctx, S5P_FIMV_R2H_CMD_FRAME_DONE_RET)) {
+                                       mfc_err_ctx("Waiting for LAST_SEQ timed out\n");
+                                       break;
+                               }
+                               if (ctx->state == MFCINST_RUNNING) {
+                                       mfc_debug(2, "all encoded buffers out\n");
+                                       break;
+                               }
+                       }
+               }
+
+               s5p_mfc_move_all_bufs(&ctx->buf_queue_lock, &ctx->src_buf_queue,
+                               &ctx->ref_buf_queue, MFC_QUEUE_ADD_BOTTOM);
+               s5p_mfc_cleanup_enc_src_queue(ctx);
+
+               while (index < MFC_MAX_BUFFERS) {
+                       index = find_next_bit(&ctx->src_ctrls_avail,
+                                       MFC_MAX_BUFFERS, index);
+                       if (index < MFC_MAX_BUFFERS)
+                               call_cop(ctx, reset_buf_ctrls, &ctx->src_ctrls[index]);
+                       index++;
+               }
+       }
+
+       if (aborted || ctx->state == MFCINST_FINISHING)
+               s5p_mfc_change_state(ctx, MFCINST_RUNNING);
+
+       mfc_debug(2, "buffer cleanup is done in stop_streaming, type : %d\n", q->type);
+
+       s5p_mfc_clear_bit(ctx->num, &dev->work_bits);
+       s5p_mfc_release_hwlock_ctx(ctx);
+
+       if (s5p_mfc_is_work_to_do(dev))
+               queue_work(dev->butler_wq, &dev->butler_work);
+}
+
+static void s5p_mfc_enc_buf_queue(struct vb2_buffer *vb)
+{
+       struct vb2_queue *vq = vb->vb2_queue;
+       struct s5p_mfc_ctx *ctx = vq->drv_priv;
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_buf *buf = vb_to_mfc_buf(vb);
+       int i;
+
+       mfc_debug_enter();
+
+       buf->next_index = 0;
+       buf->done_index = 0;
+
+       if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               mfc_debug(2, "[BUFINFO] ctx[%d] add dst index: %d, addr: 0x%08llx\n",
+                               ctx->num, vb->index, buf->addr[0][0]);
+
+               /* Mark destination as available for use by MFC */
+               s5p_mfc_add_tail_buf(&ctx->buf_queue_lock, &ctx->dst_buf_queue, buf);
+       } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               for (i = 0; i < ctx->src_fmt->mem_planes; i++)
+                       mfc_debug(2, "[BUFINFO] ctx[%d] add src index: %d, addr[%d]: 0x%08llx\n",
+                                       ctx->num, vb->index, i, buf->addr[0][i]);
+               s5p_mfc_add_tail_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, buf);
+
+               if (debug_ts == 1)
+                       mfc_info_ctx("[TS] framerate: %ld, timestamp: %lld\n",
+                                       ctx->framerate, buf->vb.vb2_buf.timestamp);
+
+               s5p_mfc_qos_update_last_framerate(ctx, buf->vb.vb2_buf.timestamp);
+               s5p_mfc_qos_update_framerate(ctx);
+       } else {
+               mfc_err_ctx("unsupported buffer type (%d)\n", vq->type);
+       }
+
+       if (s5p_mfc_enc_ctx_ready(ctx)) {
+               s5p_mfc_set_bit(ctx->num, &dev->work_bits);
+       }
+       s5p_mfc_try_run(dev);
+
+       mfc_debug_leave();
+}
+
+struct vb2_ops s5p_mfc_enc_qops = {
+       .queue_setup            = s5p_mfc_enc_queue_setup,
+       .wait_prepare           = s5p_mfc_enc_unlock,
+       .wait_finish            = s5p_mfc_enc_lock,
+       .buf_init               = s5p_mfc_enc_buf_init,
+       .buf_prepare            = s5p_mfc_enc_buf_prepare,
+       .buf_finish             = s5p_mfc_enc_buf_finish,
+       .buf_cleanup            = s5p_mfc_enc_buf_cleanup,
+       .start_streaming        = s5p_mfc_enc_start_streaming,
+       .stop_streaming         = s5p_mfc_enc_stop_streaming,
+       .buf_queue              = s5p_mfc_enc_buf_queue,
+};
diff --git a/drivers/media/platform/exynos/mfc/mfc_hwfc_internal.h b/drivers/media/platform/exynos/mfc/mfc_hwfc_internal.h
new file mode 100644 (file)
index 0000000..cb4a6bf
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_hwfc_internal.h
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __MFC_HWFC_INTERNAL_H
+#define __MFC_HWFC_INTERNAL_H __FILE__
+
+#include "mfc_common.h"
+
+/*
+ * RGB encoding information to avoid confusion.
+ *
+ * V4L2_PIX_FMT_ARGB32 takes ARGB data like below.
+ * MSB                              LSB
+ * 3       2       1
+ * 2       4       6       8       0
+ * |B......BG......GR......RA......A|
+ */
+struct s5p_mfc_fmt enc_hwfc_formats[] = {
+       {
+               .name = "4:2:0 2 Planes Y/CbCr single",
+               .fourcc = V4L2_PIX_FMT_NV12N,
+               .codec_mode = MFC_FORMATS_NO_CODEC,
+               .type = MFC_FMT_FRAME,
+               .num_planes = 2,
+               .mem_planes = 1,
+       },
+       {
+               .name = "H264 Encoded Stream",
+               .fourcc = V4L2_PIX_FMT_H264,
+               .codec_mode = S5P_FIMV_CODEC_H264_ENC,
+               .type = MFC_FMT_STREAM,
+               .num_planes = 1,
+               .mem_planes = 1,
+       },
+       {
+               .name = "HEVC Encoded Stream",
+               .fourcc = V4L2_PIX_FMT_HEVC,
+               .codec_mode = S5P_FIMV_CODEC_HEVC_ENC,
+               .type = MFC_FMT_STREAM,
+               .num_planes = 1,
+               .mem_planes = 1,
+       },
+};
+
+#define NUM_FORMATS ARRAY_SIZE(enc_hwfc_formats)
+
+#endif /* __MFC_HWFC_INTERNAL_H */
diff --git a/drivers/media/platform/exynos/mfc/mfc_hwlock.c b/drivers/media/platform/exynos/mfc/mfc_hwlock.c
new file mode 100644 (file)
index 0000000..79cfb44
--- /dev/null
@@ -0,0 +1,1007 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_hwlock.c
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include "mfc_hwlock.h"
+
+#include "mfc_nal_q.h"
+#include "mfc_otf.h"
+#include "mfc_opr.h"
+#include "mfc_sync.h"
+
+#include "mfc_inst.h"
+#include "mfc_pm.h"
+#include "mfc_cmd.h"
+#include "mfc_cal.h"
+#include "mfc_reg.h"
+
+#include "mfc_queue.h"
+#include "mfc_utils.h"
+
+static inline void mfc_print_hwlock(struct s5p_mfc_dev *dev)
+{
+       mfc_debug(2, "dev.hwlock.dev = 0x%lx, bits = 0x%lx, owned_by_irq = %d, wl_count = %d, transfer_owner = %d\n",
+               dev->hwlock.dev, dev->hwlock.bits, dev->hwlock.owned_by_irq,
+               dev->hwlock.wl_count, dev->hwlock.transfer_owner);
+}
+
+void s5p_mfc_init_hwlock(struct s5p_mfc_dev *dev)
+{
+       unsigned long flags;
+
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return;
+       }
+
+       spin_lock_init(&dev->hwlock.lock);
+       spin_lock_irqsave(&dev->hwlock.lock, flags);
+
+       INIT_LIST_HEAD(&dev->hwlock.waiting_list);
+       dev->hwlock.wl_count = 0;
+       dev->hwlock.bits = 0;
+       dev->hwlock.dev = 0;
+       dev->hwlock.owned_by_irq = 0;
+       dev->hwlock.transfer_owner = 0;
+
+       spin_unlock_irqrestore(&dev->hwlock.lock, flags);
+}
+
+static int mfc_remove_listable_wq_dev(struct s5p_mfc_dev *dev)
+{
+       struct s5p_mfc_listable_wq *listable_wq;
+       unsigned long flags;
+       int ret = -1;
+
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return -EINVAL;
+       }
+
+       spin_lock_irqsave(&dev->hwlock.lock, flags);
+       mfc_print_hwlock(dev);
+
+       list_for_each_entry(listable_wq, &dev->hwlock.waiting_list, list) {
+               if (!listable_wq->dev)
+                       continue;
+
+               mfc_debug(2, "Found dev and will delete it!\n");
+
+               list_del(&listable_wq->list);
+               dev->hwlock.wl_count--;
+
+               ret = 0;
+               break;
+       }
+
+       mfc_print_hwlock(dev);
+       spin_unlock_irqrestore(&dev->hwlock.lock, flags);
+
+       return ret;
+}
+
+static int mfc_remove_listable_wq_ctx(struct s5p_mfc_ctx *curr_ctx)
+{
+       struct s5p_mfc_dev *dev;
+       struct s5p_mfc_listable_wq *listable_wq;
+       unsigned long flags;
+       int ret = -1;
+
+       if (!curr_ctx) {
+               mfc_err_dev("no mfc context to run\n");
+               return -EINVAL;
+       }
+
+       dev = curr_ctx->dev;
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return -EINVAL;
+       }
+
+       spin_lock_irqsave(&dev->hwlock.lock, flags);
+       mfc_print_hwlock(dev);
+
+       list_for_each_entry(listable_wq, &dev->hwlock.waiting_list, list) {
+               if (!listable_wq->ctx)
+                       continue;
+
+               if (listable_wq->ctx->num == curr_ctx->num) {
+                       mfc_debug(2, "Found ctx and will delete it (%d)!\n", curr_ctx->num);
+
+                       list_del(&listable_wq->list);
+                       dev->hwlock.wl_count--;
+                       ret = 0;
+                       break;
+               }
+       }
+
+       mfc_print_hwlock(dev);
+       spin_unlock_irqrestore(&dev->hwlock.lock, flags);
+
+       return ret;
+}
+
+/*
+ * Return value description
+ *    0: succeeded to get hwlock
+ * -EIO: failed to get hwlock (time out)
+ */
+int s5p_mfc_get_hwlock_dev(struct s5p_mfc_dev *dev)
+{
+       int ret = 0;
+       unsigned long flags;
+
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return -EINVAL;
+       }
+
+       mutex_lock(&dev->hwlock_wq.wait_mutex);
+
+       spin_lock_irqsave(&dev->hwlock.lock, flags);
+       mfc_print_hwlock(dev);
+
+       if (dev->shutdown) {
+               mfc_info_dev("Couldn't lock HW. Shutdown was called\n");
+               spin_unlock_irqrestore(&dev->hwlock.lock, flags);
+               mutex_unlock(&dev->hwlock_wq.wait_mutex);
+               return -EINVAL;
+       }
+
+       if ((dev->hwlock.bits != 0) || (dev->hwlock.dev != 0)) {
+               list_add_tail(&dev->hwlock_wq.list, &dev->hwlock.waiting_list);
+               dev->hwlock.wl_count++;
+
+               spin_unlock_irqrestore(&dev->hwlock.lock, flags);
+
+               mfc_debug(2, "Waiting for hwlock to be released\n");
+
+               ret = wait_event_timeout(dev->hwlock_wq.wait_queue,
+                       ((dev->hwlock.transfer_owner == 1) && (dev->hwlock.dev == 1)),
+                       msecs_to_jiffies(MFC_HWLOCK_TIMEOUT));
+
+               MFC_TRACE_DEV_HWLOCK("get_hwlock_dev: before waiting\n");
+               MFC_TRACE_DEV_HWLOCK(">>dev:0x%lx, bits:0x%lx, owned:%d, wl:%d, trans:%d\n",
+                               dev->hwlock.dev, dev->hwlock.bits, dev->hwlock.owned_by_irq,
+                               dev->hwlock.wl_count, dev->hwlock.transfer_owner);
+
+               dev->hwlock.transfer_owner = 0;
+               mfc_remove_listable_wq_dev(dev);
+               if (ret == 0) {
+                       mfc_err_dev("Woken up but timed out\n");
+                       mfc_print_hwlock(dev);
+                       mutex_unlock(&dev->hwlock_wq.wait_mutex);
+                       return -EIO;
+               } else {
+                       mfc_debug(2, "Woken up and got hwlock\n");
+                       mfc_print_hwlock(dev);
+                       mutex_unlock(&dev->hwlock_wq.wait_mutex);
+               }
+       } else {
+               dev->hwlock.bits = 0;
+               dev->hwlock.dev = 1;
+               dev->hwlock.owned_by_irq = 0;
+
+               MFC_TRACE_DEV_HWLOCK("get_hwlock_dev: no waiting\n");
+               MFC_TRACE_DEV_HWLOCK(">>dev:0x%lx, bits:0x%lx, owned:%d, wl:%d, trans:%d\n",
+                               dev->hwlock.dev, dev->hwlock.bits, dev->hwlock.owned_by_irq,
+                               dev->hwlock.wl_count, dev->hwlock.transfer_owner);
+
+               mfc_print_hwlock(dev);
+               spin_unlock_irqrestore(&dev->hwlock.lock, flags);
+               mutex_unlock(&dev->hwlock_wq.wait_mutex);
+       }
+
+       /* Stop NAL-Q after getting hwlock */
+       if (dev->nal_q_handle)
+               s5p_mfc_nal_q_stop_if_started(dev);
+
+       return 0;
+}
+
+/*
+ * Return value description
+ *    0: succeeded to get hwlock
+ * -EIO: failed to get hwlock (time out)
+ */
+int s5p_mfc_get_hwlock_ctx(struct s5p_mfc_ctx *curr_ctx)
+{
+       struct s5p_mfc_dev *dev;
+       struct s5p_mfc_ctx *ctx = curr_ctx;
+       int ret = 0;
+       unsigned long flags;
+
+       if (!curr_ctx) {
+               mfc_err_dev("no mfc context to run\n");
+               return -EINVAL;
+       }
+
+       dev = curr_ctx->dev;
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return -EINVAL;
+       }
+
+       mutex_lock(&curr_ctx->hwlock_wq.wait_mutex);
+
+       spin_lock_irqsave(&dev->hwlock.lock, flags);
+       mfc_print_hwlock(dev);
+
+       if (dev->shutdown) {
+               mfc_info_dev("Couldn't lock HW. Shutdown was called\n");
+               spin_unlock_irqrestore(&dev->hwlock.lock, flags);
+               mutex_unlock(&curr_ctx->hwlock_wq.wait_mutex);
+               return -EINVAL;
+       }
+
+       if ((dev->hwlock.bits != 0) || (dev->hwlock.dev != 0)) {
+               list_add_tail(&curr_ctx->hwlock_wq.list, &dev->hwlock.waiting_list);
+               dev->hwlock.wl_count++;
+
+               spin_unlock_irqrestore(&dev->hwlock.lock, flags);
+
+               MFC_TRACE_CTX_HWLOCK("get_hwlock_ctx: before waiting\n");
+               MFC_TRACE_CTX_HWLOCK(">>dev:0x%lx, bits:0x%lx, owned:%d, wl:%d, trans:%d\n",
+                               dev->hwlock.dev, dev->hwlock.bits, dev->hwlock.owned_by_irq,
+                               dev->hwlock.wl_count, dev->hwlock.transfer_owner);
+
+               mfc_debug(2, "Waiting for hwlock to be released\n");
+
+               ret = wait_event_timeout(curr_ctx->hwlock_wq.wait_queue,
+                       ((dev->hwlock.transfer_owner == 1) && (test_bit(curr_ctx->num, &dev->hwlock.bits))),
+                       msecs_to_jiffies(MFC_HWLOCK_TIMEOUT));
+
+               MFC_TRACE_CTX_HWLOCK("get_hwlock_ctx: after waiting, ret:%d\n", ret);
+               MFC_TRACE_CTX_HWLOCK(">>dev:0x%lx, bits:0x%lx, owned:%d, wl:%d, trans:%d\n",
+                               dev->hwlock.dev, dev->hwlock.bits, dev->hwlock.owned_by_irq,
+                               dev->hwlock.wl_count, dev->hwlock.transfer_owner);
+
+               dev->hwlock.transfer_owner = 0;
+               mfc_remove_listable_wq_ctx(curr_ctx);
+               if (ret == 0) {
+                       mfc_err_dev("Woken up but timed out\n");
+                       mfc_print_hwlock(dev);
+                       mutex_unlock(&curr_ctx->hwlock_wq.wait_mutex);
+                       return -EIO;
+               } else {
+                       mfc_debug(2, "Woken up and got hwlock\n");
+                       mfc_print_hwlock(dev);
+                       mutex_unlock(&curr_ctx->hwlock_wq.wait_mutex);
+               }
+       } else {
+               dev->hwlock.bits = 0;
+               dev->hwlock.dev = 0;
+               set_bit(curr_ctx->num, &dev->hwlock.bits);
+               dev->hwlock.owned_by_irq = 0;
+
+               MFC_TRACE_CTX_HWLOCK("get_hwlock_ctx: no waiting\n");
+               MFC_TRACE_CTX_HWLOCK(">>dev:0x%lx, bits:0x%lx, owned:%d, wl:%d, trans:%d\n",
+                               dev->hwlock.dev, dev->hwlock.bits, dev->hwlock.owned_by_irq,
+                               dev->hwlock.wl_count, dev->hwlock.transfer_owner);
+
+               mfc_print_hwlock(dev);
+               spin_unlock_irqrestore(&dev->hwlock.lock, flags);
+               mutex_unlock(&curr_ctx->hwlock_wq.wait_mutex);
+       }
+
+       /* Stop NAL-Q after getting hwlock */
+       if (dev->nal_q_handle)
+               s5p_mfc_nal_q_stop_if_started(dev);
+
+       return 0;
+}
+
+/*
+ * Return value description
+ *  0: succeeded to release hwlock
+ *  1: succeeded to release hwlock, hwlock is captured by another module
+ * -1: error since device is waiting again.
+ */
+int s5p_mfc_release_hwlock_dev(struct s5p_mfc_dev *dev)
+{
+       struct s5p_mfc_listable_wq *listable_wq;
+       unsigned long flags;
+       int ret = -1;
+
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return -EINVAL;
+       }
+
+       spin_lock_irqsave(&dev->hwlock.lock, flags);
+       mfc_print_hwlock(dev);
+
+       dev->hwlock.dev = 0;
+       dev->hwlock.owned_by_irq = 0;
+
+       if (dev->shutdown) {
+               mfc_debug(2, "Couldn't wakeup module. Shutdown was called\n");
+               ret = 0;
+       } else if (list_empty(&dev->hwlock.waiting_list)) {
+               mfc_debug(2, "No waiting module\n");
+               ret = 0;
+       } else {
+               mfc_debug(2, "There is a waiting module\n");
+               listable_wq = list_entry(dev->hwlock.waiting_list.next, struct s5p_mfc_listable_wq, list);
+               list_del(&listable_wq->list);
+               dev->hwlock.wl_count--;
+
+               if (listable_wq->dev) {
+                       mfc_debug(2, "Waking up dev\n");
+                       dev->hwlock.dev = 1;
+               } else {
+                       mfc_debug(2, "Waking up another ctx\n");
+                       set_bit(listable_wq->ctx->num, &dev->hwlock.bits);
+               }
+
+               dev->hwlock.transfer_owner = 1;
+
+               MFC_TRACE_DEV_HWLOCK("release_hwlock_dev: wakeup\n");
+               MFC_TRACE_DEV_HWLOCK(">>dev:0x%lx, bits:0x%lx, owned:%d, wl:%d, trans:%d\n",
+                               dev->hwlock.dev, dev->hwlock.bits, dev->hwlock.owned_by_irq,
+                               dev->hwlock.wl_count, dev->hwlock.transfer_owner);
+
+               wake_up(&listable_wq->wait_queue);
+               ret = 1;
+       }
+
+       mfc_print_hwlock(dev);
+       spin_unlock_irqrestore(&dev->hwlock.lock, flags);
+       return ret;
+}
+
+/*
+ * Should be called with hwlock.lock
+ *
+ * Return value description
+ * 0: succeeded to release hwlock
+ * 1: succeeded to release hwlock, hwlock is captured by another module
+ */
+static int mfc_release_hwlock_ctx_protected(struct s5p_mfc_ctx *curr_ctx)
+{
+       struct s5p_mfc_dev *dev;
+       struct s5p_mfc_ctx *ctx = curr_ctx;
+       struct s5p_mfc_listable_wq *listable_wq;
+       int ret = -1;
+
+       if (!curr_ctx) {
+               mfc_err_dev("no mfc context to run\n");
+               return -EINVAL;
+       }
+
+       dev = curr_ctx->dev;
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return -EINVAL;
+       }
+
+       mfc_print_hwlock(dev);
+       clear_bit(curr_ctx->num, &dev->hwlock.bits);
+       dev->hwlock.owned_by_irq = 0;
+
+       if (dev->shutdown) {
+               mfc_debug(2, "Couldn't wakeup module. Shutdown was called\n");
+               ret = 0;
+       } else if (list_empty(&dev->hwlock.waiting_list)) {
+               mfc_debug(2, "No waiting module\n");
+               ret = 0;
+       } else {
+               mfc_debug(2, "There is a waiting module\n");
+               listable_wq = list_entry(dev->hwlock.waiting_list.next, struct s5p_mfc_listable_wq, list);
+               list_del(&listable_wq->list);
+               dev->hwlock.wl_count--;
+
+               if (listable_wq->dev) {
+                       mfc_debug(2, "Waking up dev\n");
+                       dev->hwlock.dev = 1;
+               } else {
+                       mfc_debug(2, "Waking up another ctx\n");
+                       set_bit(listable_wq->ctx->num, &dev->hwlock.bits);
+               }
+
+               dev->hwlock.transfer_owner = 1;
+
+               MFC_TRACE_CTX_HWLOCK("release_hwlock_ctx: wakeup\n");
+               MFC_TRACE_CTX_HWLOCK(">>dev:0x%lx, bits:0x%lx, owned:%d, wl:%d, trans:%d\n",
+                               dev->hwlock.dev, dev->hwlock.bits, dev->hwlock.owned_by_irq,
+                               dev->hwlock.wl_count, dev->hwlock.transfer_owner);
+
+               wake_up(&listable_wq->wait_queue);
+               ret = 1;
+       }
+
+       mfc_print_hwlock(dev);
+       return ret;
+}
+
+/*
+ * Return value description
+ * 0: succeeded to release hwlock
+ * 1: succeeded to release hwlock, hwlock is captured by another module
+ */
+int s5p_mfc_release_hwlock_ctx(struct s5p_mfc_ctx *curr_ctx)
+{
+       struct s5p_mfc_dev *dev;
+       unsigned long flags;
+       int ret = -1;
+
+       if (!curr_ctx) {
+               mfc_err_dev("no mfc context to run\n");
+               return -EINVAL;
+       }
+
+       dev = curr_ctx->dev;
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return -EINVAL;
+       }
+
+       spin_lock_irqsave(&dev->hwlock.lock, flags);
+       ret = mfc_release_hwlock_ctx_protected(curr_ctx);
+       spin_unlock_irqrestore(&dev->hwlock.lock, flags);
+       return ret;
+}
+
+static inline int mfc_yield_hwlock(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *curr_ctx)
+{
+       unsigned long flags;
+
+       if (!curr_ctx) {
+               mfc_err_dev("no mfc context to run\n");
+               return -EINVAL;
+       }
+
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return -EINVAL;
+       }
+
+       spin_lock_irqsave(&dev->hwlock.lock, flags);
+
+       mfc_release_hwlock_ctx_protected(curr_ctx);
+
+       spin_unlock_irqrestore(&dev->hwlock.lock, flags);
+
+       /* Trigger again if other instance's work is waiting */
+       if (s5p_mfc_is_work_to_do(dev))
+               queue_work(dev->butler_wq, &dev->butler_work);
+
+       return 0;
+}
+
+/*
+ * Should be called with hwlock.lock
+ */
+static inline void mfc_transfer_hwlock_ctx_protected(struct s5p_mfc_dev *dev, int curr_ctx_index)
+{
+       dev->hwlock.dev = 0;
+       dev->hwlock.bits = 0;
+       set_bit(curr_ctx_index, &dev->hwlock.bits);
+}
+
+/*
+ * Should be called with hwlock.lock
+ *
+ * Return value description
+ *   >=0: succeeded to get hwlock_bit for the context, index of new context
+ *   -1, -EINVAL: failed to get hwlock_bit for a context
+ */
+static int mfc_try_to_get_new_ctx_protected(struct s5p_mfc_dev *dev)
+{
+       int ret = 0;
+       int index;
+       struct s5p_mfc_ctx *new_ctx;
+
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return -EINVAL;
+       }
+
+       if (dev->shutdown) {
+               mfc_info_dev("Couldn't lock HW. Shutdown was called\n");
+               return -EINVAL;
+       }
+
+       if (dev->sleep) {
+               mfc_info_dev("Couldn't lock HW. Sleep was called\n");
+               return -EINVAL;
+       }
+
+       /* Check whether hardware is not running */
+       if ((dev->hwlock.bits != 0) || (dev->hwlock.dev != 0)) {
+               /* This is perfectly ok, the scheduled ctx should wait */
+               mfc_debug(2, "Couldn't lock HW\n");
+               return -1;
+       }
+
+       /* Choose the context to run */
+       index = s5p_mfc_get_new_ctx(dev);
+       if (index < 0) {
+               /* This is perfectly ok, the scheduled ctx should wait
+                * No contexts to run
+                */
+               mfc_debug(2, "No ctx is scheduled to be run\n");
+               ret = -1;
+               return ret;
+       }
+
+       new_ctx = dev->ctx[index];
+       if (!new_ctx) {
+               mfc_err_dev("no mfc context to run\n");
+               ret = -1;
+               return ret;
+       }
+
+       set_bit(new_ctx->num, &dev->hwlock.bits);
+       ret = index;
+
+       return ret;
+}
+
+/*
+ * Should be called without hwlock holding
+ *
+ * Try to run an operation on hardware
+ */
+void s5p_mfc_try_run(struct s5p_mfc_dev *dev)
+{
+       int new_ctx_index;
+       int ret;
+       unsigned long flags;
+
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return;
+       }
+
+       spin_lock_irqsave(&dev->hwlock.lock, flags);
+       mfc_print_hwlock(dev);
+
+       new_ctx_index = mfc_try_to_get_new_ctx_protected(dev);
+       if (new_ctx_index < 0) {
+               mfc_debug(2, "Failed to get new context to run\n");
+               mfc_print_hwlock(dev);
+               spin_unlock_irqrestore(&dev->hwlock.lock, flags);
+               return;
+       }
+
+       dev->hwlock.owned_by_irq = 1;
+
+       mfc_print_hwlock(dev);
+       spin_unlock_irqrestore(&dev->hwlock.lock, flags);
+
+       ret = s5p_mfc_just_run(dev, new_ctx_index);
+       if (ret)
+               mfc_yield_hwlock(dev, dev->ctx[new_ctx_index]);
+}
+
+/*
+ * Should be called without hwlock holding
+ *
+ */
+void s5p_mfc_cleanup_work_bit_and_try_run(struct s5p_mfc_ctx *curr_ctx)
+{
+       struct s5p_mfc_dev *dev;
+
+       if (!curr_ctx) {
+               mfc_err_dev("no mfc context to run\n");
+               return;
+       }
+
+       dev = curr_ctx->dev;
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return;
+       }
+
+       s5p_mfc_clear_bit(curr_ctx->num, &dev->work_bits);
+
+       s5p_mfc_try_run(dev);
+}
+
+void s5p_mfc_cache_flush(struct s5p_mfc_dev *dev, int is_drm)
+{
+       s5p_mfc_cmd_cache_flush(dev);
+       if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_CACHE_FLUSH_RET)) {
+               mfc_err_dev("Failed to CACHE_FLUSH\n");
+               dev->logging_data->cause |= (1 << MFC_CAUSE_FAIL_CHACHE_FLUSH);
+               call_dop(dev, dump_and_stop_always, dev);
+       }
+
+       s5p_mfc_pm_clock_off(dev);
+       dev->curr_ctx_is_drm = is_drm;
+       s5p_mfc_pm_clock_on_with_base(dev, (is_drm ? MFCBUF_DRM : MFCBUF_NORMAL));
+}
+
+/*
+ * Return value description
+ *  0: NAL-Q is handled successfully
+ *  1: NAL_START command should be handled
+ * -1: Error
+*/
+static int mfc_nal_q_just_run(struct s5p_mfc_ctx *ctx, int need_cache_flush)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned int ret = -1;
+
+       nal_queue_handle *nal_q_handle = dev->nal_q_handle;
+
+       if (!nal_q_handle) {
+               mfc_err_dev("nal_q_handle is NULL\n");
+               return ret;
+       }
+
+       switch (nal_q_handle->nal_q_state) {
+       case NAL_Q_STATE_CREATED:
+               if (s5p_mfc_nal_q_check_enable(dev) == 0) {
+                       /* NAL START */
+                       ret = 1;
+               } else {
+                       s5p_mfc_nal_q_clock_on(dev, nal_q_handle);
+
+                       s5p_mfc_nal_q_init(dev, nal_q_handle);
+
+                       /* enable NAL QUEUE */
+                       if (need_cache_flush)
+                               s5p_mfc_cache_flush(dev, ctx->is_drm);
+
+                       mfc_info_ctx("[NALQ] start NAL QUEUE\n");
+                       s5p_mfc_nal_q_start(dev, nal_q_handle);
+
+                       if (s5p_mfc_nal_q_enqueue_in_buf(dev, ctx, nal_q_handle->nal_q_in_handle)) {
+                               mfc_debug(2, "[NALQ] Failed to enqueue input data\n");
+                               s5p_mfc_nal_q_clock_off(dev, nal_q_handle);
+                       }
+
+                       s5p_mfc_clear_bit(ctx->num, &dev->work_bits);
+                       if ((s5p_mfc_ctx_ready(ctx) && !ctx->clear_work_bit) ||
+                                       nal_q_handle->nal_q_exception)
+                               s5p_mfc_set_bit(ctx->num, &dev->work_bits);
+                       ctx->clear_work_bit = 0;
+
+                       s5p_mfc_release_hwlock_ctx(ctx);
+
+                       if (s5p_mfc_is_work_to_do(dev))
+                               queue_work(dev->butler_wq, &dev->butler_work);
+
+                       ret = 0;
+               }
+               break;
+       case NAL_Q_STATE_STARTED:
+               s5p_mfc_nal_q_clock_on(dev, nal_q_handle);
+
+               if (s5p_mfc_nal_q_check_enable(dev) == 0 ||
+                               nal_q_handle->nal_q_exception) {
+                       /* disable NAL QUEUE */
+                       s5p_mfc_nal_q_stop(dev, nal_q_handle);
+                       mfc_info_ctx("[NALQ] stop NAL QUEUE\n");
+                       if (s5p_mfc_wait_for_done_dev(dev,
+                                       S5P_FIMV_R2H_CMD_COMPLETE_QUEUE_RET)) {
+                               mfc_err_dev("[NALQ] Failed to stop queue\n");
+                               dev->logging_data->cause |= (1 << MFC_CAUSE_FAIL_STOP_NAL_Q);
+                               call_dop(dev, dump_and_stop_always, dev);
+                       }
+                       ret = 1;
+                       break;
+               } else {
+                       /* NAL QUEUE */
+                       if (s5p_mfc_nal_q_enqueue_in_buf(dev, ctx, nal_q_handle->nal_q_in_handle)) {
+                               mfc_debug(2, "[NALQ] Failed to enqueue input data\n");
+                               s5p_mfc_nal_q_clock_off(dev, nal_q_handle);
+                       }
+
+                       s5p_mfc_clear_bit(ctx->num, &dev->work_bits);
+
+                       if ((s5p_mfc_ctx_ready(ctx) && !ctx->clear_work_bit) ||
+                                       nal_q_handle->nal_q_exception)
+                               s5p_mfc_set_bit(ctx->num, &dev->work_bits);
+                       ctx->clear_work_bit = 0;
+
+                       s5p_mfc_release_hwlock_ctx(ctx);
+
+                       if (s5p_mfc_is_work_to_do(dev))
+                               queue_work(dev->butler_wq, &dev->butler_work);
+                       ret = 0;
+               }
+               break;
+       default:
+               mfc_info_ctx("[NALQ] can't try command, nal_q_state : %d\n",
+                               nal_q_handle->nal_q_state);
+               ret = -1;
+               break;
+       }
+
+       return ret;
+}
+
+static int mfc_just_run_dec(struct s5p_mfc_ctx *ctx)
+{
+       int ret = 0;
+
+       switch (ctx->state) {
+       case MFCINST_FINISHING:
+               ret = s5p_mfc_run_dec_last_frames(ctx);
+               break;
+       case MFCINST_RUNNING:
+       case MFCINST_SPECIAL_PARSING_NAL:
+               ret = s5p_mfc_run_dec_frame(ctx);
+               break;
+       case MFCINST_INIT:
+               ret = s5p_mfc_open_inst(ctx);
+               break;
+       case MFCINST_RETURN_INST:
+               ret = s5p_mfc_close_inst(ctx);
+               break;
+       case MFCINST_GOT_INST:
+       case MFCINST_SPECIAL_PARSING:
+               ret = s5p_mfc_run_dec_init(ctx);
+               break;
+       case MFCINST_HEAD_PARSED:
+               if (ctx->codec_buffer_allocated == 0) {
+                       ctx->clear_work_bit = 1;
+                       mfc_err_ctx("codec buffer is not allocated\n");
+                       ret = -EAGAIN;
+                       break;
+               }
+               ret = s5p_mfc_cmd_dec_init_buffers(ctx);
+               break;
+       case MFCINST_RES_CHANGE_INIT:
+               ret = s5p_mfc_run_dec_last_frames(ctx);
+               break;
+       case MFCINST_RES_CHANGE_FLUSH:
+               ret = s5p_mfc_run_dec_last_frames(ctx);
+               break;
+       case MFCINST_RES_CHANGE_END:
+               mfc_debug(2, "[DRC] Finished remaining frames after resolution change\n");
+               ctx->capture_state = QUEUE_FREE;
+               mfc_debug(2, "[DRC] Will re-init the codec\n");
+               ret = s5p_mfc_run_dec_init(ctx);
+               break;
+       case MFCINST_DPB_FLUSHING:
+               ret = s5p_mfc_cmd_dpb_flush(ctx);
+               break;
+       default:
+               mfc_info_ctx("can't try command(decoder just_run), state : %d\n", ctx->state);
+               ret = -EAGAIN;
+       }
+
+       return ret;
+}
+
+static int mfc_just_run_enc(struct s5p_mfc_ctx *ctx)
+{
+       int ret = 0;
+
+       switch (ctx->state) {
+               case MFCINST_FINISHING:
+                       ret = s5p_mfc_run_enc_last_frames(ctx);
+                       break;
+               case MFCINST_RUNNING:
+                       if (ctx->otf_handle) {
+                               ret = s5p_mfc_otf_run_enc_frame(ctx);
+                               break;
+                       }
+                       ret = s5p_mfc_run_enc_frame(ctx);
+                       break;
+               case MFCINST_INIT:
+                       ret = s5p_mfc_open_inst(ctx);
+                       break;
+               case MFCINST_RETURN_INST:
+                       ret = s5p_mfc_close_inst(ctx);
+                       break;
+               case MFCINST_GOT_INST:
+                       if (ctx->otf_handle) {
+                               ret = s5p_mfc_otf_run_enc_init(ctx);
+                               break;
+                       }
+                       ret = s5p_mfc_run_enc_init(ctx);
+                       break;
+               case MFCINST_HEAD_PARSED:
+                       ret = s5p_mfc_cmd_enc_init_buffers(ctx);
+                       break;
+               case MFCINST_ABORT_INST:
+                       ret = s5p_mfc_abort_inst(ctx);
+                       break;
+               default:
+                       mfc_info_ctx("can't try command(encoder just_run), state : %d\n", ctx->state);
+                       ret = -EAGAIN;
+       }
+
+       return ret;
+}
+
+/* Run an operation on hardware */
+int s5p_mfc_just_run(struct s5p_mfc_dev *dev, int new_ctx_index)
+{
+       struct s5p_mfc_ctx *ctx;
+       unsigned int ret = 0;
+       int need_cache_flush = 0;
+
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return -EINVAL;
+       }
+
+       ctx = dev->ctx[new_ctx_index];
+       if (!ctx) {
+               mfc_err_dev("no mfc context to run\n");
+               return -EINVAL;
+       }
+
+       if (ctx->state == MFCINST_RUNNING)
+               s5p_mfc_clean_ctx_int_flags(ctx);
+
+       mfc_debug(2, "New context: %d\n", new_ctx_index);
+       dev->curr_ctx = ctx->num;
+
+       /* Got context to run in ctx */
+       mfc_debug(2, "src: %d, dst: %d, state: %d, dpb_count = %d\n",
+               s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->src_buf_queue),
+               s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->dst_buf_queue),
+               ctx->state, ctx->dpb_count);
+       mfc_debug(2, "ctx->state = %d\n", ctx->state);
+       /* Last frame has already been sent to MFC
+        * Now obtaining frames from MFC buffer */
+
+       /* Check if cache flush command is needed */
+       if (dev->curr_ctx_is_drm != ctx->is_drm)
+               need_cache_flush = 1;
+       else
+               dev->curr_ctx_is_drm = ctx->is_drm;
+
+       mfc_debug(2, "need_cache_flush = %d, is_drm = %d\n", need_cache_flush, ctx->is_drm);
+
+       if (dev->nal_q_handle) {
+               ret = mfc_nal_q_just_run(ctx, need_cache_flush);
+               if (ret == 0) {
+                       mfc_debug(2, "NAL_Q was handled\n");
+                       return ret;
+               } else if (ret == 1){
+                       /* Path through */
+                       mfc_debug(2, "NAL_START will be handled\n");
+               } else {
+                       return ret;
+               }
+       }
+
+       mfc_debug(2, "continue_clock_on = %d\n", dev->continue_clock_on);
+       if (!dev->continue_clock_on) {
+               s5p_mfc_pm_clock_on(dev);
+       } else {
+               dev->continue_clock_on = false;
+       }
+
+       if (need_cache_flush)
+               s5p_mfc_cache_flush(dev, ctx->is_drm);
+
+       if (ctx->type == MFCINST_DECODER) {
+               ret = mfc_just_run_dec(ctx);
+       } else if (ctx->type == MFCINST_ENCODER) {
+               ret = mfc_just_run_enc(ctx);
+       } else {
+               mfc_err_ctx("invalid context type: %d\n", ctx->type);
+               ret = -EAGAIN;
+       }
+
+       if (ret) {
+               /* Check again the ctx condition and clear work bits
+                * if ctx is not available. */
+               if (s5p_mfc_ctx_ready(ctx) == 0 || ctx->clear_work_bit) {
+                       s5p_mfc_clear_bit(ctx->num, &dev->work_bits);
+                       ctx->clear_work_bit = 0;
+               }
+
+               s5p_mfc_pm_clock_off(dev);
+       }
+
+       return ret;
+}
+
+void s5p_mfc_hwlock_handler_irq(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *curr_ctx,
+               unsigned int reason, unsigned int err)
+{
+       int new_ctx_index;
+       unsigned long flags;
+       int ret;
+
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return;
+       }
+
+       if (!curr_ctx) {
+               mfc_err_dev("no mfc context to run\n");
+               return;
+       }
+
+       spin_lock_irqsave(&dev->hwlock.lock, flags);
+       mfc_print_hwlock(dev);
+
+       if (dev->hwlock.owned_by_irq) {
+               if (dev->preempt_ctx > MFC_NO_INSTANCE_SET) {
+                       mfc_debug(2, "There is a preempt_ctx\n");
+                       dev->continue_clock_on = true;
+                       s5p_mfc_wake_up_ctx(curr_ctx, reason, err);
+                       new_ctx_index = dev->preempt_ctx;
+                       mfc_debug(2, "preempt_ctx is : %d\n", new_ctx_index);
+
+                       spin_unlock_irqrestore(&dev->hwlock.lock, flags);
+
+                       ret = s5p_mfc_just_run(dev, new_ctx_index);
+                       if (ret) {
+                               dev->continue_clock_on = false;
+                               mfc_yield_hwlock(dev, dev->ctx[new_ctx_index]);
+                       }
+               } else if (!list_empty(&dev->hwlock.waiting_list)) {
+                       mfc_debug(2, "There is a waiting module for hwlock\n");
+                       dev->continue_clock_on = false;
+                       s5p_mfc_pm_clock_off(dev);
+
+                       spin_unlock_irqrestore(&dev->hwlock.lock, flags);
+
+                       s5p_mfc_release_hwlock_ctx(curr_ctx);
+                       s5p_mfc_wake_up_ctx(curr_ctx, reason, err);
+                       queue_work(dev->butler_wq, &dev->butler_work);
+               } else {
+                       mfc_debug(2, "No preempt_ctx and no waiting module\n");
+                       new_ctx_index = s5p_mfc_get_new_ctx(dev);
+                       if (new_ctx_index < 0) {
+                               mfc_debug(2, "No ctx to run\n");
+                               /* No contexts to run */
+                               dev->continue_clock_on = false;
+                               s5p_mfc_pm_clock_off(dev);
+
+                               spin_unlock_irqrestore(&dev->hwlock.lock, flags);
+
+                               s5p_mfc_release_hwlock_ctx(curr_ctx);
+                               s5p_mfc_wake_up_ctx(curr_ctx, reason, err);
+                               queue_work(dev->butler_wq, &dev->butler_work);
+                       } else {
+                               mfc_debug(2, "There is a ctx to run\n");
+                               dev->continue_clock_on = true;
+                               s5p_mfc_wake_up_ctx(curr_ctx, reason, err);
+
+                               /* If cache flush command is needed or there is OTF handle, handler should stop */
+                               if ((dev->curr_ctx_is_drm != dev->ctx[new_ctx_index]->is_drm) ||
+                                               dev->ctx[new_ctx_index]->otf_handle) {
+                                       mfc_debug(2, "Secure and nomal switching or OTF mode\n");
+                                       mfc_debug(2, "DRM attribute %d->%d\n",
+                                                       dev->curr_ctx_is_drm, dev->ctx[new_ctx_index]->is_drm);
+
+                                       spin_unlock_irqrestore(&dev->hwlock.lock, flags);
+
+                                       s5p_mfc_release_hwlock_ctx(curr_ctx);
+                                       queue_work(dev->butler_wq, &dev->butler_work);
+                               } else {
+                                       mfc_debug(2, "Work to do successively (next ctx: %d)\n", new_ctx_index);
+                                       mfc_transfer_hwlock_ctx_protected(dev, new_ctx_index);
+
+                                       spin_unlock_irqrestore(&dev->hwlock.lock, flags);
+
+                                       ret = s5p_mfc_just_run(dev, new_ctx_index);
+                                       if (ret) {
+                                               dev->continue_clock_on = false;
+                                               mfc_yield_hwlock(dev, dev->ctx[new_ctx_index]);
+                                       }
+                               }
+                       }
+               }
+       } else {
+               mfc_debug(2, "hwlock is NOT owned by irq\n");
+               dev->continue_clock_on = false;
+               s5p_mfc_pm_clock_off(dev);
+               s5p_mfc_wake_up_ctx(curr_ctx, reason, err);
+               queue_work(dev->butler_wq, &dev->butler_work);
+
+               spin_unlock_irqrestore(&dev->hwlock.lock, flags);
+       }
+       mfc_print_hwlock(dev);
+}
diff --git a/drivers/media/platform/exynos/mfc/mfc_hwlock.h b/drivers/media/platform/exynos/mfc/mfc_hwlock.h
new file mode 100644 (file)
index 0000000..7e6a8a0
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_hwlock.h
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __MFC_HWLOCK_H
+#define __MFC_HWLOCK_H __FILE__
+
+#include "mfc_common.h"
+
+static inline void s5p_mfc_init_listable_wq_dev(struct s5p_mfc_dev *dev)
+{
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return;
+       }
+
+       INIT_LIST_HEAD(&dev->hwlock_wq.list);
+       init_waitqueue_head(&dev->hwlock_wq.wait_queue);
+       mutex_init(&dev->hwlock_wq.wait_mutex);
+       dev->hwlock_wq.ctx = NULL;
+       dev->hwlock_wq.dev = dev;
+}
+
+static inline void s5p_mfc_init_listable_wq_ctx(struct s5p_mfc_ctx *curr_ctx)
+{
+       if (!curr_ctx) {
+               mfc_err_dev("no mfc context to run\n");
+               return;
+       }
+
+       INIT_LIST_HEAD(&curr_ctx->hwlock_wq.list);
+       init_waitqueue_head(&curr_ctx->hwlock_wq.wait_queue);
+       mutex_init(&curr_ctx->hwlock_wq.wait_mutex);
+       curr_ctx->hwlock_wq.ctx = curr_ctx;
+       curr_ctx->hwlock_wq.dev = NULL;
+}
+
+static inline void s5p_mfc_destroy_listable_wq_dev(struct s5p_mfc_dev *dev)
+{
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return;
+       }
+
+       mutex_destroy(&dev->hwlock_wq.wait_mutex);
+}
+
+static inline void s5p_mfc_destroy_listable_wq_ctx(struct s5p_mfc_ctx *curr_ctx)
+{
+       if (!curr_ctx) {
+               mfc_err_dev("no mfc context to run\n");
+               return;
+       }
+
+       mutex_destroy(&curr_ctx->hwlock_wq.wait_mutex);
+}
+
+void s5p_mfc_init_hwlock(struct s5p_mfc_dev *dev);
+
+int s5p_mfc_get_hwlock_dev(struct s5p_mfc_dev *dev);
+int s5p_mfc_get_hwlock_ctx(struct s5p_mfc_ctx *curr_ctx);
+
+int s5p_mfc_release_hwlock_dev(struct s5p_mfc_dev *dev);
+int s5p_mfc_release_hwlock_ctx(struct s5p_mfc_ctx *curr_ctx);
+
+void s5p_mfc_cache_flush(struct s5p_mfc_dev *dev, int is_drm);
+
+void s5p_mfc_try_run(struct s5p_mfc_dev *dev);
+void s5p_mfc_cleanup_work_bit_and_try_run(struct s5p_mfc_ctx *ctx);
+int s5p_mfc_just_run(struct s5p_mfc_dev *dev, int new_ctx_index);
+
+void s5p_mfc_hwlock_handler_irq(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx,
+               unsigned int reason, unsigned int err);
+
+#endif /* __MFC_HWLOCK_H */
diff --git a/drivers/media/platform/exynos/mfc/mfc_inst.c b/drivers/media/platform/exynos/mfc/mfc_inst.c
new file mode 100644 (file)
index 0000000..5d4e67e
--- /dev/null
@@ -0,0 +1,359 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_inst.c
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include "mfc_inst.h"
+
+#include "mfc_cmd.h"
+#include "mfc_enc_param.h"
+#include "mfc_cal.h"
+#include "mfc_perf_measure.h"
+#include "mfc_reg.h"
+
+#include "mfc_utils.h"
+
+int s5p_mfc_open_inst(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned int reg;
+       int ret;
+
+       /* Preparing decoding - getting instance number */
+       mfc_debug(2, "Getting instance number\n");
+       s5p_mfc_clean_ctx_int_flags(ctx);
+
+       reg = MFC_READL(S5P_FIMV_CODEC_CONTROL);
+       /* Clear OTF_CONTROL[2:1] & OTF_DEBUG[3] */
+       reg &= ~(0x7 << 1);
+       if (ctx->otf_handle) {
+               /* Set OTF_CONTROL[2:1], 0: Non-OTF, 1: OTF+HWFC, 2: OTF only */
+               reg |= (0x1 << 1);
+               mfc_info_ctx("HWFC + OTF enabled\n");
+               if (otf_dump && !ctx->is_drm) {
+                       /* Set OTF_DEBUG[3] for OTF path dump */
+                       reg |= (0x1 << 3);
+                       mfc_info_ctx("Debugging mode enabled\n");
+               }
+       }
+       MFC_WRITEL(reg, S5P_FIMV_CODEC_CONTROL);
+
+
+       ret = s5p_mfc_cmd_open_inst(ctx);
+       if (ret) {
+               mfc_err_ctx("Failed to create a new instance\n");
+               s5p_mfc_change_state(ctx, MFCINST_ERROR);
+       }
+
+       return ret;
+}
+
+int s5p_mfc_close_inst(struct s5p_mfc_ctx *ctx)
+{
+       int ret = -EINVAL;
+
+       /* Closing decoding instance  */
+       mfc_debug(2, "Returning instance number\n");
+       s5p_mfc_clean_ctx_int_flags(ctx);
+       if (ctx->state == MFCINST_FREE) {
+               mfc_err_ctx("ctx already free status\n");
+               return ret;
+       }
+
+       ret = s5p_mfc_cmd_close_inst(ctx);
+       if (ret) {
+               mfc_err_ctx("Failed to return an instance\n");
+               s5p_mfc_change_state(ctx, MFCINST_ERROR);
+       }
+
+       return ret;
+}
+
+int s5p_mfc_abort_inst(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev;
+
+       if (!ctx) {
+               mfc_err_dev("no mfc context to run\n");
+               return -EINVAL;
+       }
+
+       dev = ctx->dev;
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return -EINVAL;
+       }
+
+       s5p_mfc_clean_ctx_int_flags(ctx);
+
+       MFC_WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID);
+       s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_NAL_ABORT);
+
+       return 0;
+}
+
+/* Initialize decoding */
+int s5p_mfc_init_decode(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev;
+       struct s5p_mfc_dec *dec;
+       unsigned int reg = 0;
+       int fmo_aso_ctrl = 0;
+
+       mfc_debug_enter();
+       if (!ctx) {
+               mfc_err_dev("no mfc context to run\n");
+               return -EINVAL;
+       }
+
+       dev = ctx->dev;
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return -EINVAL;
+       }
+
+       dec = ctx->dec_priv;
+       if (!dec) {
+               mfc_err_dev("no mfc decoder to run\n");
+               return -EINVAL;
+       }
+       mfc_debug(2, "InstNo: %d/%d\n", ctx->inst_no, S5P_FIMV_H2R_CMD_SEQ_HEADER);
+       mfc_debug(2, "BUFs: %08x\n", MFC_READL(S5P_FIMV_D_CPB_BUFFER_ADDR));
+
+       /* When user sets desplay_delay to 0,
+        * It works as "display_delay enable" and delay set to 0.
+        * If user wants display_delay disable, It should be
+        * set to negative value. */
+       if (dec->display_delay >= 0) {
+               reg |= (0x1 << S5P_FIMV_D_DEC_OPT_DISPLAY_DELAY_EN_SHIFT);
+               MFC_WRITEL(dec->display_delay, S5P_FIMV_D_DISPLAY_DELAY);
+       }
+
+       /* FMO_ASO_CTRL - 0: Enable, 1: Disable */
+       reg |= ((fmo_aso_ctrl & S5P_FIMV_D_DEC_OPT_FMO_ASO_CTRL_MASK)
+                       << S5P_FIMV_D_DEC_OPT_FMO_ASO_CTRL_SHIFT);
+
+       reg |= ((dec->idr_decoding & S5P_FIMV_D_DEC_OPT_IDR_DECODING_MASK)
+                       << S5P_FIMV_D_DEC_OPT_IDR_DECODING_SHIFT);
+
+       /* VC1 RCV: Discard to parse additional header as default */
+       if (IS_VC1_RCV_DEC(ctx))
+               reg |= (0x1 << S5P_FIMV_D_DEC_OPT_DISCARD_RCV_HEADER_SHIFT);
+
+       /* conceal control to specific color */
+       reg |= (0x4 << S5P_FIMV_D_DEC_OPT_CONCEAL_CONTROL_SHIFT);
+
+       /* Disable parallel processing if nal_q_parallel_disable was set */
+       if (nal_q_parallel_disable)
+               reg |= (0x2 << S5P_FIMV_D_DEC_OPT_PARALLEL_DISABLE_SHIFT);
+
+       /* Realloc buffer for resolution decrease case in NAL QUEUE mode */
+       reg |= (0x1 << S5P_FIMV_D_DEC_OPT_REALLOC_CONTROL_SHIFT);
+
+       /* Parsing all including PPS */
+       reg |= (0x1 << S5P_FIMV_D_DEC_OPT_SPECIAL_PARSING_SHIFT);
+
+       MFC_WRITEL(reg, S5P_FIMV_D_DEC_OPTIONS);
+
+       MFC_WRITEL(MFC_CONCEAL_COLOR, S5P_FIMV_D_FORCE_PIXEL_VAL);
+
+       if (IS_FIMV1_DEC(ctx)) {
+               mfc_debug(2, "Setting FIMV1 resolution to %dx%d\n",
+                                       ctx->img_width, ctx->img_height);
+               MFC_WRITEL(ctx->img_width, S5P_FIMV_D_SET_FRAME_WIDTH);
+               MFC_WRITEL(ctx->img_height, S5P_FIMV_D_SET_FRAME_HEIGHT);
+       }
+
+       s5p_mfc_set_pixel_format(dev, ctx->dst_fmt->fourcc);
+
+       reg = 0;
+       /* Enable realloc interface if SEI is enabled */
+       if (dec->sei_parse)
+               reg |= (0x1 << S5P_FIMV_D_SEI_ENABLE_NEED_INIT_BUFFER_SHIFT);
+       if (MFC_FEATURE_SUPPORT(dev, dev->pdata->static_info_dec)) {
+               reg |= (0x1 << S5P_FIMV_D_SEI_ENABLE_CONTENT_LIGHT_SHIFT);
+               reg |= (0x1 << S5P_FIMV_D_SEI_ENABLE_MASTERING_DISPLAY_SHIFT);
+       }
+       reg |= (0x1 << S5P_FIMV_D_SEI_ENABLE_RECOVERY_PARSING_SHIFT);
+
+       MFC_WRITEL(reg, S5P_FIMV_D_SEI_ENABLE);
+       mfc_debug(2, "SEI enable was set, 0x%x\n", MFC_READL(S5P_FIMV_D_SEI_ENABLE));
+
+       MFC_WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID);
+
+       if (sfr_dump & MFC_DUMP_DEC_SEQ_START)
+               call_dop(dev, dump_regs, dev);
+
+       s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_SEQ_HEADER);
+
+       mfc_debug_leave();
+       return 0;
+}
+
+/* Decode a single frame */
+int s5p_mfc_decode_one_frame(struct s5p_mfc_ctx *ctx, int last_frame)
+{
+       struct s5p_mfc_dev *dev;
+       struct s5p_mfc_dec *dec;
+       u32 reg = 0;
+
+       if (!ctx) {
+               mfc_err_dev("no mfc context to run\n");
+               return -EINVAL;
+       }
+
+       dev = ctx->dev;
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return -EINVAL;
+       }
+
+       dec = ctx->dec_priv;
+       if (!dec) {
+               mfc_err_dev("no mfc decoder to run\n");
+               return -EINVAL;
+       }
+
+       mfc_debug(2, "Dynamic:0x%08x, Available:0x%lx\n",
+                       dec->dynamic_set, dec->available_dpb);
+
+       reg = MFC_READL(S5P_FIMV_D_NAL_START_OPTIONS);
+       reg &= ~(0x1 << S5P_FIMV_D_NAL_START_OPT_BLACK_BAR_SHIFT);
+       reg |= ((dec->detect_black_bar & 0x1) << S5P_FIMV_D_NAL_START_OPT_BLACK_BAR_SHIFT);
+       MFC_WRITEL(reg, S5P_FIMV_D_NAL_START_OPTIONS);
+       mfc_debug(3, "[BLACKBAR] black bar detect set: %#x\n", reg);
+
+       MFC_WRITEL(dec->dynamic_set, S5P_FIMV_D_DYNAMIC_DPB_FLAG_LOWER);
+       MFC_WRITEL(0x0, S5P_FIMV_D_DYNAMIC_DPB_FLAG_UPPER);
+       MFC_WRITEL(dec->available_dpb, S5P_FIMV_D_AVAILABLE_DPB_FLAG_LOWER);
+       MFC_WRITEL(0x0, S5P_FIMV_D_AVAILABLE_DPB_FLAG_UPPER);
+       MFC_WRITEL(dec->slice_enable, S5P_FIMV_D_SLICE_IF_ENABLE);
+       MFC_WRITEL(MFC_TIMEOUT_VALUE, S5P_FIMV_DEC_TIMEOUT_VALUE);
+
+       MFC_WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID);
+
+       if ((sfr_dump & MFC_DUMP_DEC_NAL_START) && !ctx->check_dump) {
+               call_dop(dev, dump_regs, dev);
+               ctx->check_dump = 1;
+       }
+
+       /* Issue different commands to instance basing on whether it
+        * is the last frame or not. */
+       switch (last_frame) {
+       case 0:
+               s5p_mfc_perf_measure_on(dev);
+
+               s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_NAL_START);
+               break;
+       case 1:
+               s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_LAST_FRAME);
+               break;
+       }
+
+       mfc_debug(2, "Decoding a usual frame\n");
+       return 0;
+}
+
+int s5p_mfc_init_encode(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       mfc_debug(2, "++\n");
+
+       if (IS_H264_ENC(ctx))
+               s5p_mfc_set_enc_params_h264(ctx);
+       else if (IS_MPEG4_ENC(ctx))
+               s5p_mfc_set_enc_params_mpeg4(ctx);
+       else if (IS_H263_ENC(ctx))
+               s5p_mfc_set_enc_params_h263(ctx);
+       else if (IS_VP8_ENC(ctx))
+               s5p_mfc_set_enc_params_vp8(ctx);
+       else if (IS_VP9_ENC(ctx))
+               s5p_mfc_set_enc_params_vp9(ctx);
+       else if (IS_HEVC_ENC(ctx))
+               s5p_mfc_set_enc_params_hevc(ctx);
+       else if (IS_BPG_ENC(ctx))
+               s5p_mfc_set_enc_params_bpg(ctx);
+       else {
+               mfc_err_ctx("Unknown codec for encoding (%x)\n",
+                       ctx->codec_mode);
+               return -EINVAL;
+       }
+
+       mfc_debug(5, "RC) Bitrate: %d / framerate: %#x / config %#x / mode %#x\n",
+                       MFC_READL(S5P_FIMV_E_RC_BIT_RATE),
+                       MFC_READL(S5P_FIMV_E_RC_FRAME_RATE),
+                       MFC_READL(S5P_FIMV_E_RC_CONFIG),
+                       MFC_READL(S5P_FIMV_E_RC_MODE));
+
+       MFC_WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID);
+
+       if (sfr_dump & MFC_DUMP_ENC_SEQ_START)
+               call_dop(dev, dump_regs, dev);
+
+       s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_SEQ_HEADER);
+
+       mfc_debug(2, "--\n");
+
+       return 0;
+}
+
+static int mfc_h264_set_aso_slice_order(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc *enc = ctx->enc_priv;
+       struct s5p_mfc_enc_params *p = &enc->params;
+       struct s5p_mfc_h264_enc_params *p_264 = &p->codec.h264;
+       int i;
+
+       if (p_264->aso_enable) {
+               for (i = 0; i < 8; i++)
+                       MFC_WRITEL(p_264->aso_slice_order[i],
+                               S5P_FIMV_E_H264_ASO_SLICE_ORDER_0 + i * 4);
+       }
+       return 0;
+}
+
+/* Encode a single frame */
+int s5p_mfc_encode_one_frame(struct s5p_mfc_ctx *ctx, int last_frame)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       mfc_debug(2, "++\n");
+
+       if (IS_H264_ENC(ctx))
+               mfc_h264_set_aso_slice_order(ctx);
+
+       s5p_mfc_set_slice_mode(ctx);
+
+       MFC_WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID);
+
+       if ((sfr_dump & MFC_DUMP_ENC_NAL_START) && !ctx->check_dump) {
+               call_dop(dev, dump_regs, dev);
+               ctx->check_dump = 1;
+       }
+
+       /* Issue different commands to instance basing on whether it
+        * is the last frame or not. */
+       switch (last_frame) {
+       case 0:
+               s5p_mfc_perf_measure_on(dev);
+
+               s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_NAL_START);
+               break;
+       case 1:
+               s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_LAST_FRAME);
+               break;
+       }
+
+       mfc_debug(2, "--\n");
+
+       return 0;
+}
diff --git a/drivers/media/platform/exynos/mfc/mfc_inst.h b/drivers/media/platform/exynos/mfc/mfc_inst.h
new file mode 100644 (file)
index 0000000..10b07ac
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_inst.h
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __MFC_INST_H
+#define __MFC_INST_H __FILE__
+
+#include "mfc_common.h"
+
+int s5p_mfc_open_inst(struct s5p_mfc_ctx *ctx);
+int s5p_mfc_close_inst(struct s5p_mfc_ctx *ctx);
+int s5p_mfc_abort_inst(struct s5p_mfc_ctx *ctx);
+
+int s5p_mfc_init_decode(struct s5p_mfc_ctx *ctx);
+int s5p_mfc_decode_one_frame(struct s5p_mfc_ctx *ctx, int last_frame);
+
+int s5p_mfc_init_encode(struct s5p_mfc_ctx *ctx);
+int s5p_mfc_encode_one_frame(struct s5p_mfc_ctx *ctx, int last_frame);
+
+#endif /* __MFC_INST_H  */
diff --git a/drivers/media/platform/exynos/mfc/mfc_irq.c b/drivers/media/platform/exynos/mfc/mfc_irq.c
new file mode 100644 (file)
index 0000000..95136af
--- /dev/null
@@ -0,0 +1,1564 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_irq.c
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include "mfc_irq.h"
+
+#include "mfc_hwlock.h"
+#include "mfc_nal_q.h"
+#include "mfc_otf.h"
+#include "mfc_opr.h"
+#include "mfc_sync.h"
+
+#include "mfc_pm.h"
+#include "mfc_cal.h"
+#include "mfc_perf_measure.h"
+#include "mfc_reg.h"
+#include "mfc_mmcache.h"
+
+#include "mfc_qos.h"
+#include "mfc_queue.h"
+#include "mfc_buf.h"
+#include "mfc_mem.h"
+
+static void mfc_handle_black_bar_info(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx)
+{
+       struct v4l2_rect new_black_bar;
+       int black_bar_info;
+       struct s5p_mfc_dec *dec = ctx->dec_priv;
+
+       black_bar_info = s5p_mfc_get_black_bar_detection();
+       mfc_debug(3, "[BLACKBAR] type: %#x\n", black_bar_info);
+
+       if (black_bar_info == S5P_FIMV_DISP_STATUS_BLACK_BAR) {
+               new_black_bar.left = s5p_mfc_get_black_bar_pos_x();
+               new_black_bar.top = s5p_mfc_get_black_bar_pos_y();
+               new_black_bar.width = s5p_mfc_get_black_bar_image_w();
+               new_black_bar.height = s5p_mfc_get_black_bar_image_h();
+       } else if (black_bar_info == S5P_FIMV_DISP_STATUS_BLACK_SCREEN) {
+               new_black_bar.left = -1;
+               new_black_bar.top = -1;
+               new_black_bar.width = ctx->img_width;
+               new_black_bar.height = ctx->img_height;
+       } else if (black_bar_info == S5P_FIMV_DISP_STATUS_NOT_DETECTED) {
+               new_black_bar.left = 0;
+               new_black_bar.top = 0;
+               new_black_bar.width = ctx->img_width;
+               new_black_bar.height = ctx->img_height;
+       } else {
+               mfc_err_ctx("[BLACKBAR] Not supported type: %#x\n", black_bar_info);
+               dec->black_bar_updated = 0;
+               return;
+       }
+
+       if ((new_black_bar.left == dec->black_bar.left) &&
+                       (new_black_bar.top == dec->black_bar.top) &&
+                       (new_black_bar.width == dec->black_bar.width) &&
+                       (new_black_bar.height == dec->black_bar.height)) {
+               mfc_debug(4, "[BLACKBAR] information was not changed\n");
+               dec->black_bar_updated = 0;
+               return;
+       }
+
+       dec->black_bar = new_black_bar;
+       dec->black_bar_updated = 1;
+}
+
+static unsigned int mfc_handle_frame_field(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned int interlace_type = 0, is_interlace = 0, is_mbaff = 0;
+       unsigned int field;
+
+       if (CODEC_INTERLACED(ctx))
+               is_interlace = s5p_mfc_is_interlace_picture();
+
+       if (CODEC_MBAFF(ctx))
+               is_mbaff = s5p_mfc_is_mbaff_picture();
+
+       if (is_interlace) {
+               interlace_type = s5p_mfc_get_interlace_type();
+               if (interlace_type)
+                       field = V4L2_FIELD_INTERLACED_TB;
+               else
+                       field = V4L2_FIELD_INTERLACED_BT;
+       } else if (is_mbaff) {
+               field = V4L2_FIELD_INTERLACED_TB;
+       } else {
+               field = V4L2_FIELD_NONE;
+       }
+
+       mfc_debug(2, "[INTERLACE] is_interlace: %d (type : %d), is_mbaff: %d, field: 0x%#x\n",
+                       is_interlace, interlace_type, is_mbaff, field);
+
+       return field;
+}
+
+static void mfc_handle_frame_all_extracted(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dec *dec = ctx->dec_priv;
+       struct s5p_mfc_buf *dst_mb;
+       int index, i, is_first = 1;
+
+       mfc_debug(2, "Decided to finish\n");
+       ctx->sequence++;
+
+       while (1) {
+               dst_mb = s5p_mfc_get_del_buf(&ctx->buf_queue_lock, &ctx->dst_buf_queue, MFC_BUF_NO_TOUCH_USED);
+               if (!dst_mb)
+                       break;
+
+               mfc_debug(2, "Cleaning up buffer: %d\n",
+                                         dst_mb->vb.vb2_buf.index);
+
+               index = dst_mb->vb.vb2_buf.index;
+
+               for (i = 0; i < ctx->dst_fmt->mem_planes; i++)
+                       vb2_set_plane_payload(&dst_mb->vb.vb2_buf, i, 0);
+
+               dst_mb->vb.sequence = (ctx->sequence++);
+               dst_mb->vb.field = mfc_handle_frame_field(ctx);
+               dst_mb->vb.reserved2 = 0;
+
+               clear_bit(dst_mb->vb.vb2_buf.index, &dec->available_dpb);
+
+               if (call_cop(ctx, get_buf_ctrls_val, ctx, &ctx->dst_ctrls[index]) < 0)
+                       mfc_err_ctx("failed in get_buf_ctrls_val\n");
+
+               if (is_first) {
+                       call_cop(ctx, get_buf_update_val, ctx,
+                               &ctx->dst_ctrls[index],
+                               V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG,
+                               dec->stored_tag);
+                       is_first = 0;
+               } else {
+                       call_cop(ctx, get_buf_update_val, ctx,
+                               &ctx->dst_ctrls[index],
+                               V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG,
+                               DEFAULT_TAG);
+                       call_cop(ctx, get_buf_update_val, ctx,
+                               &ctx->dst_ctrls[index],
+                               V4L2_CID_MPEG_VIDEO_H264_SEI_FP_AVAIL,
+                               0);
+               }
+
+               vb2_buffer_done(&dst_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
+
+               /* decoder dst buffer CFW UNPROT */
+               if (ctx->is_drm)
+                       s5p_mfc_raw_unprotect(ctx, dst_mb, index);
+
+               mfc_debug(2, "Cleaned up buffer: %d\n", index);
+       }
+
+       s5p_mfc_handle_force_change_status(ctx);
+       mfc_debug(2, "After cleanup\n");
+}
+
+static void mfc_handle_frame_copy_timestamp(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_buf *ref_mb, *src_mb;
+       dma_addr_t dec_y_addr;
+
+       dec_y_addr = (dma_addr_t)s5p_mfc_get_dec_y_addr();
+
+       /* Get the source buffer */
+       src_mb = s5p_mfc_get_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, MFC_BUF_NO_TOUCH_USED);
+       if (!src_mb) {
+               mfc_err_dev("[TS] no src buffers\n");
+               return;
+       }
+
+       ref_mb = s5p_mfc_find_buf(&ctx->buf_queue_lock, &ctx->ref_buf_queue, dec_y_addr);
+       if (ref_mb)
+               ref_mb->vb.vb2_buf.timestamp = src_mb->vb.vb2_buf.timestamp;
+}
+
+static void mfc_handle_frame_output_move(struct s5p_mfc_ctx *ctx,
+               dma_addr_t dspl_y_addr, unsigned int released_flag)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_dec *dec = ctx->dec_priv;
+       struct s5p_mfc_buf *ref_mb;
+       int index;
+
+       ref_mb = s5p_mfc_find_move_buf(&ctx->buf_queue_lock,
+                       &ctx->dst_buf_queue, &ctx->ref_buf_queue, dspl_y_addr, released_flag);
+       if (ref_mb) {
+               index = ref_mb->vb.vb2_buf.index;
+
+               /* Check if this is the buffer we're looking for */
+               mfc_debug(2, "[DPB] Found buf[%d] 0x%08llx, looking for disp addr 0x%08llx\n",
+                               index, ref_mb->addr[0][0], dspl_y_addr);
+
+               if (released_flag & (1 << index)) {
+                       dec->available_dpb &= ~(1 << index);
+                       released_flag &= ~(1 << index);
+                       mfc_debug(2, "[DPB] Corrupted frame(%d), it will be re-used(release)\n",
+                                       s5p_mfc_get_warn(s5p_mfc_get_int_err()));
+               } else {
+                       dec->err_reuse_flag |= 1 << index;
+                       mfc_debug(2, "[DPB] Corrupted frame(%d), it will be re-used(not released)\n",
+                                       s5p_mfc_get_warn(s5p_mfc_get_int_err()));
+               }
+               dec->dynamic_used |= released_flag;
+       }
+}
+
+static void mfc_handle_frame_output_del(struct s5p_mfc_ctx *ctx,
+               unsigned int err, unsigned int released_flag)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_dec *dec = ctx->dec_priv;
+       struct s5p_mfc_raw_info *raw = &ctx->raw_buf;
+       struct s5p_mfc_buf *ref_mb;
+       dma_addr_t dspl_y_addr;
+       unsigned int frame_type;
+       unsigned int dst_frame_status;
+       unsigned int is_video_signal_type = 0, is_colour_description = 0;
+       unsigned int is_content_light = 0, is_display_colour = 0;
+       unsigned int i, index;
+
+       if (MFC_FEATURE_SUPPORT(dev, dev->pdata->color_aspect_dec)) {
+               is_video_signal_type = s5p_mfc_get_video_signal_type();
+               is_colour_description = s5p_mfc_get_colour_description();
+       }
+
+       if (MFC_FEATURE_SUPPORT(dev, dev->pdata->static_info_dec)) {
+               is_content_light = s5p_mfc_get_sei_avail_content_light();
+               is_display_colour = s5p_mfc_get_sei_avail_mastering_display();
+       }
+
+       if (MFC_FEATURE_SUPPORT(dev, dev->pdata->black_bar) && dec->detect_black_bar)
+               mfc_handle_black_bar_info(dev, ctx);
+       else
+               dec->black_bar_updated = 0;
+
+       if (dec->immediate_display == 1) {
+               dspl_y_addr = (dma_addr_t)s5p_mfc_get_dec_y_addr();
+               frame_type = s5p_mfc_get_dec_frame_type();
+       } else {
+               dspl_y_addr = (dma_addr_t)s5p_mfc_get_disp_y_addr();
+               frame_type = s5p_mfc_get_disp_frame_type();
+       }
+
+       ref_mb = s5p_mfc_find_del_buf(&ctx->buf_queue_lock,
+                       &ctx->ref_buf_queue, dspl_y_addr);
+       if (ref_mb) {
+               index = ref_mb->vb.vb2_buf.index;
+               /* Check if this is the buffer we're looking for */
+               mfc_debug(2, "[BUFINFO][DPB] ctx[%d] get dst index: %d, addr[0]: 0x%08llx\n",
+                               ctx->num, index, ref_mb->addr[0][0]);
+
+               ref_mb->vb.sequence = ctx->sequence;
+               ref_mb->vb.field = mfc_handle_frame_field(ctx);
+
+               /* Set reserved2 bits in order to inform SEI information */
+               ref_mb->vb.reserved2 = 0;
+
+               if (is_content_light) {
+                       ref_mb->vb.reserved2 |= (1 << 0);
+                       mfc_debug(2, "[HDR] content light level parsed\n");
+               }
+
+               if (is_display_colour) {
+                       ref_mb->vb.reserved2 |= (1 << 1);
+                       mfc_debug(2, "[HDR] mastering display colour parsed\n");
+               }
+
+               if (is_video_signal_type) {
+                       ref_mb->vb.reserved2 |= (1 << 4);
+                       mfc_debug(2, "[HDR] video signal type parsed\n");
+                       if (is_colour_description) {
+                               ref_mb->vb.reserved2 |= (1 << 2);
+                               mfc_debug(2, "[HDR] matrix coefficients parsed\n");
+                               ref_mb->vb.reserved2 |= (1 << 3);
+                               mfc_debug(2, "[HDR] colour description parsed\n");
+                       }
+               }
+
+               if (IS_VP9_DEC(ctx) && MFC_FEATURE_SUPPORT(dev, dev->pdata->color_aspect_dec)) {
+                       if (dec->color_space != S5P_FIMV_D_COLOR_UNKNOWN) {
+                               ref_mb->vb.reserved2 |= (1 << 3);
+                               mfc_debug(2, "[HDR] color space parsed\n");
+                       }
+                       ref_mb->vb.reserved2 |= (1 << 4);
+                       mfc_debug(2, "[HDR] color range parsed\n");
+               }
+
+               if (dec->black_bar_updated) {
+                       ref_mb->vb.reserved2 |= (1 << 5);
+                       mfc_debug(3, "[BLACKBAR] black bar detected\n");
+               }
+
+               if (ctx->src_fmt->mem_planes == 1) {
+                       vb2_set_plane_payload(&ref_mb->vb.vb2_buf, 0,
+                                       raw->total_plane_size);
+                       mfc_debug(5, "single plane payload: %d\n",
+                                       raw->total_plane_size);
+               } else {
+                       for (i = 0; i < ctx->src_fmt->mem_planes; i++) {
+                               vb2_set_plane_payload(&ref_mb->vb.vb2_buf, i,
+                                               raw->plane_size[i]);
+                       }
+               }
+
+               clear_bit(index, &dec->available_dpb);
+
+               ref_mb->vb.flags &= ~(V4L2_BUF_FLAG_KEYFRAME |
+                                       V4L2_BUF_FLAG_PFRAME |
+                                       V4L2_BUF_FLAG_BFRAME |
+                                       V4L2_BUF_FLAG_ERROR);
+
+               switch (frame_type) {
+                       case S5P_FIMV_DISPLAY_FRAME_I:
+                               ref_mb->vb.flags |= V4L2_BUF_FLAG_KEYFRAME;
+                               break;
+                       case S5P_FIMV_DISPLAY_FRAME_P:
+                               ref_mb->vb.flags |= V4L2_BUF_FLAG_PFRAME;
+                               break;
+                       case S5P_FIMV_DISPLAY_FRAME_B:
+                               ref_mb->vb.flags |= V4L2_BUF_FLAG_BFRAME;
+                               break;
+                       default:
+                               break;
+               }
+
+               if (s5p_mfc_get_warn(err)) {
+                       mfc_err_ctx("Warning for displayed frame: %d\n",
+                                       s5p_mfc_get_warn(err));
+                       ref_mb->vb.flags |= V4L2_BUF_FLAG_ERROR;
+               }
+
+               if (call_cop(ctx, get_buf_ctrls_val, ctx, &ctx->dst_ctrls[index]) < 0)
+                       mfc_err_ctx("failed in get_buf_ctrls_val\n");
+
+               s5p_mfc_handle_released_info(ctx, released_flag, index);
+
+               if (dec->immediate_display == 1) {
+                       dst_frame_status = s5p_mfc_get_dec_status();
+
+                       call_cop(ctx, get_buf_update_val, ctx,
+                                       &ctx->dst_ctrls[index],
+                                       V4L2_CID_MPEG_MFC51_VIDEO_DISPLAY_STATUS,
+                                       dst_frame_status);
+
+                       call_cop(ctx, get_buf_update_val, ctx,
+                                       &ctx->dst_ctrls[index],
+                                       V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG,
+                                       dec->stored_tag);
+
+                       dec->immediate_display = 0;
+               }
+
+               /* Update frame tag for packed PB */
+               if (CODEC_MULTIFRAME(ctx) && (dec->y_addr_for_pb == dspl_y_addr)) {
+                       call_cop(ctx, get_buf_update_val, ctx,
+                                       &ctx->dst_ctrls[index],
+                                       V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG,
+                                       dec->stored_tag);
+                       dec->y_addr_for_pb = 0;
+               }
+
+               s5p_mfc_qos_update_last_framerate(ctx, ref_mb->vb.vb2_buf.timestamp);
+               vb2_buffer_done(&ref_mb->vb.vb2_buf, s5p_mfc_get_warn(err) ?
+                               VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
+       }
+}
+
+static void mfc_handle_frame_new(struct s5p_mfc_ctx *ctx, unsigned int err)
+{
+       struct s5p_mfc_dec *dec = ctx->dec_priv;
+       struct s5p_mfc_dev *dev = ctx->dev;
+       dma_addr_t dspl_y_addr;
+       unsigned int frame_type;
+       int mvc_view_id;
+       unsigned int prev_flag, released_flag = 0;
+
+       frame_type = s5p_mfc_get_disp_frame_type();
+       mvc_view_id = s5p_mfc_get_mvc_disp_view_id();
+
+       if (IS_H264_MVC_DEC(ctx)) {
+               if (mvc_view_id == 0)
+                       ctx->sequence++;
+       } else {
+               ctx->sequence++;
+       }
+
+       dspl_y_addr = s5p_mfc_get_disp_y_addr();
+
+       if (dec->immediate_display == 1) {
+               dspl_y_addr = (dma_addr_t)s5p_mfc_get_dec_y_addr();
+               frame_type = s5p_mfc_get_dec_frame_type();
+       }
+
+       mfc_debug(2, "[FRAME] frame type: %d\n", frame_type);
+
+       /* If frame is same as previous then skip and do not dequeue */
+       if (frame_type == S5P_FIMV_DISPLAY_FRAME_NOT_CODED)
+               if (!CODEC_NOT_CODED(ctx))
+                       return;
+
+       prev_flag = dec->dynamic_used;
+       dec->dynamic_used = s5p_mfc_get_dec_used_flag();
+       released_flag = prev_flag & (~dec->dynamic_used);
+
+       mfc_debug(2, "[DPB] Used flag: old = %08x, new = %08x, Released buffer = %08x\n",
+                       prev_flag, dec->dynamic_used, released_flag);
+
+       /* decoder dst buffer CFW UNPROT */
+       s5p_mfc_unprotect_released_dpb(ctx, released_flag);
+
+       if ((IS_VC1_RCV_DEC(ctx) &&
+               s5p_mfc_get_warn(err) == S5P_FIMV_ERR_SYNC_POINT_NOT_RECEIVED) ||
+               (s5p_mfc_get_warn(err) == S5P_FIMV_ERR_BROKEN_LINK))
+               mfc_handle_frame_output_move(ctx, dspl_y_addr, released_flag);
+       else
+               mfc_handle_frame_output_del(ctx, err, released_flag);
+}
+
+static void mfc_handle_frame_error(struct s5p_mfc_ctx *ctx,
+               unsigned int reason, unsigned int err)
+{
+       struct s5p_mfc_dec *dec;
+       struct s5p_mfc_buf *src_mb;
+       unsigned int index;
+
+       if (ctx->type == MFCINST_ENCODER) {
+               mfc_err_ctx("Encoder Interrupt Error: %d\n", err);
+               return;
+       }
+
+       dec = ctx->dec_priv;
+       if (!dec) {
+               mfc_err_dev("no mfc decoder to run\n");
+               return;
+       }
+
+       mfc_err_ctx("Interrupt Error: %d\n", err);
+
+       /* Get the source buffer */
+       src_mb = s5p_mfc_get_del_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, MFC_BUF_NO_TOUCH_USED);
+
+       if (!src_mb) {
+               mfc_err_dev("no src buffers\n");
+       } else {
+               index = src_mb->vb.vb2_buf.index;
+               if (call_cop(ctx, recover_buf_ctrls_val, ctx, &ctx->src_ctrls[index]) < 0)
+                       mfc_err_ctx("failed in recover_buf_ctrls_val\n");
+
+               mfc_debug(2, "MFC needs next buffer\n");
+               dec->consumed = 0;
+
+               if (call_cop(ctx, get_buf_ctrls_val, ctx, &ctx->src_ctrls[index]) < 0)
+                       mfc_err_ctx("failed in get_buf_ctrls_val\n");
+
+               /* decoder src buffer CFW UNPROT */
+               if (ctx->is_drm)
+                       s5p_mfc_stream_unprotect(ctx, src_mb, index);
+
+               vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_ERROR);
+       }
+
+       mfc_debug(2, "Assesing whether this context should be run again\n");
+}
+
+static void mfc_handle_ref_frame(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_dec *dec = ctx->dec_priv;
+       struct s5p_mfc_buf *dst_mb;
+       dma_addr_t dec_addr;
+
+       dec_addr = (dma_addr_t)s5p_mfc_get_dec_y_addr();
+
+       /* Try to search decoded address in whole dst queue */
+       dst_mb = s5p_mfc_find_move_buf_used(&ctx->buf_queue_lock,
+                       &ctx->ref_buf_queue, &ctx->dst_buf_queue, dec_addr);
+       if (dst_mb) {
+               mfc_debug(2, "[DPB] Found in dst queue = 0x%08llx, buf = 0x%08llx\n",
+                               dec_addr, dst_mb->addr[0][0]);
+
+               if (!(dec->dynamic_set & s5p_mfc_get_dec_used_flag()))
+                       dec->dynamic_used |= dec->dynamic_set;
+       } else {
+               mfc_debug(2, "[DPB] Can't find buffer for addr = 0x%08llx\n", dec_addr);
+       }
+}
+
+static void mfc_handle_reuse_buffer(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_dec *dec = ctx->dec_priv;
+       unsigned int prev_flag, released_flag = 0;
+       int i;
+
+       prev_flag = dec->dynamic_used;
+       dec->dynamic_used = s5p_mfc_get_dec_used_flag();
+       released_flag = prev_flag & (~dec->dynamic_used);
+
+       if (!released_flag)
+               return;
+
+       /* Reuse not referenced buf anymore */
+       for (i = 0; i < MFC_MAX_DPBS; i++)
+               if (released_flag & (1 << i))
+                       if (s5p_mfc_move_reuse_buffer(ctx, i))
+                               released_flag &= ~(1 << i);
+
+       /* Not reused buffer should be released when there is a display frame */
+       dec->dec_only_release_flag |= released_flag;
+       for (i = 0; i < MFC_MAX_DPBS; i++)
+               if (released_flag & (1 << i))
+                       clear_bit(i, &dec->available_dpb);
+}
+
+static void mfc_handle_frame_input(struct s5p_mfc_ctx *ctx, unsigned int err)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_dec *dec = ctx->dec_priv;
+       struct s5p_mfc_buf *src_mb;
+       unsigned int index;
+       int deleted = 0;
+       unsigned long consumed;
+
+       consumed = dec->consumed + s5p_mfc_get_consumed_stream();
+
+       if (s5p_mfc_get_err(err) == S5P_FIMV_ERR_NON_PAIRED_FIELD) {
+               /*
+                * For non-paired field, the same buffer need to be
+                * resubmitted and the consumed stream will be 0
+                */
+               mfc_debug(2, "Not paired field. Running again the same buffer\n");
+               return;
+       }
+
+       /* Get the source buffer */
+       src_mb = s5p_mfc_get_del_if_consumed(ctx, &ctx->src_buf_queue,
+                       s5p_mfc_get_consumed_stream(), STUFF_BYTE, err, &deleted);
+       if (!src_mb) {
+               mfc_err_dev("no src buffers\n");
+               return;
+       }
+
+       index = src_mb->vb.vb2_buf.index;
+       mfc_debug(2, "[BUFINFO] ctx[%d] get src index: %d, addr: 0x%08llx\n",
+                       ctx->num, index, src_mb->addr[0][0]);
+
+       if (!deleted) {
+               /* Run MFC again on the same buffer */
+               mfc_debug(2, "[MULTIFRAME] Running again the same buffer\n");
+
+               if (CODEC_MULTIFRAME(ctx))
+                       dec->y_addr_for_pb = (dma_addr_t)s5p_mfc_get_dec_y_addr();
+
+               dec->consumed = consumed;
+               dec->remained_size = src_mb->vb.vb2_buf.planes[0].bytesused
+                                       - dec->consumed;
+               dec->has_multiframe = 1;
+
+               MFC_TRACE_CTX("** consumed:%ld, remained:%ld, addr:0x%08llx\n",
+                       dec->consumed, dec->remained_size, dec->y_addr_for_pb);
+               /* Do not move src buffer to done_list */
+               return;
+       }
+
+       if (call_cop(ctx, recover_buf_ctrls_val, ctx, &ctx->src_ctrls[index]) < 0)
+               mfc_err_ctx("failed in recover_buf_ctrls_val\n");
+
+       dec->consumed = 0;
+       dec->remained_size = 0;
+
+       if (call_cop(ctx, get_buf_ctrls_val, ctx, &ctx->src_ctrls[index]) < 0)
+               mfc_err_ctx("failed in get_buf_ctrls_val\n");
+
+       /* decoder src buffer CFW UNPROT */
+       if (ctx->is_drm)
+               s5p_mfc_stream_unprotect(ctx, src_mb, index);
+
+       vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
+}
+
+/* Handle frame decoding interrupt */
+static void mfc_handle_frame(struct s5p_mfc_ctx *ctx,
+                       unsigned int reason, unsigned int err)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_dec *dec = ctx->dec_priv;
+       unsigned int dst_frame_status, sei_avail_frame_pack;
+       unsigned int res_change, need_dpb_change, need_scratch_change;
+
+       dst_frame_status = s5p_mfc_get_disp_status();
+       res_change = s5p_mfc_get_res_change();
+       need_dpb_change = s5p_mfc_get_dpb_change();
+       need_scratch_change = s5p_mfc_get_scratch_change();
+       sei_avail_frame_pack = s5p_mfc_get_sei_avail_frame_pack();
+
+       if (dec->immediate_display == 1)
+               dst_frame_status = s5p_mfc_get_dec_status();
+
+       mfc_debug(2, "[FRAME] frame status: %d\n", dst_frame_status);
+       mfc_debug(2, "[FRAME] display status: %d, type: %d, yaddr: %#x\n",
+                       s5p_mfc_get_disp_status(), s5p_mfc_get_disp_frame_type(),
+                       s5p_mfc_get_disp_y_addr());
+       mfc_debug(2, "[FRAME] decoded status: %d, type: %d, yaddr: %#x\n",
+                       s5p_mfc_get_dec_status(), s5p_mfc_get_dec_frame_type(),
+                       s5p_mfc_get_dec_y_addr());
+
+       mfc_debug(4, "[HDR] SEI available status: 0x%08x\n", s5p_mfc_get_sei_avail());
+       mfc_debug(4, "[HDR] SEI content light: 0x%08x\n", s5p_mfc_get_sei_content_light());
+       mfc_debug(4, "[HDR] SEI luminance: 0x%08x, 0x%08x white point: 0x%08x\n",
+                       s5p_mfc_get_sei_mastering0(), s5p_mfc_get_sei_mastering1(),
+                       s5p_mfc_get_sei_mastering2());
+       mfc_debug(4, "[HDR] SEI display primaries: 0x%08x, 0x%08x, 0x%08x\n",
+                       s5p_mfc_get_sei_mastering3(), s5p_mfc_get_sei_mastering4(),
+                       s5p_mfc_get_sei_mastering5());
+       mfc_debug(2, "[DPB] Used flag: old = %08x, new = %08x\n",
+                               dec->dynamic_used, s5p_mfc_get_dec_used_flag());
+
+       if (ctx->state == MFCINST_RES_CHANGE_INIT)
+               s5p_mfc_change_state(ctx, MFCINST_RES_CHANGE_FLUSH);
+
+       if (res_change) {
+               mfc_debug(2, "[DRC] Resolution change set to %d\n", res_change);
+               s5p_mfc_change_state(ctx, MFCINST_RES_CHANGE_INIT);
+               ctx->wait_state = WAIT_DECODING;
+               mfc_debug(7, "[DRC] Decoding waiting! : %d\n", ctx->wait_state);
+               return;
+       }
+
+       if (need_dpb_change || need_scratch_change)
+               mfc_debug(2, "[DRC] Interframe resolution change is not supported\n");
+
+       if (s5p_mfc_is_queue_count_same(&ctx->buf_queue_lock, &ctx->src_buf_queue, 0) &&
+               s5p_mfc_is_queue_count_same(&ctx->buf_queue_lock, &ctx->dst_buf_queue, 0)) {
+               mfc_err_dev("Queue count is zero for src and dst\n");
+               goto leave_handle_frame;
+       }
+
+       if (IS_H264_DEC(ctx) && sei_avail_frame_pack &&
+               dst_frame_status == S5P_FIMV_DEC_STATUS_DECODING_ONLY) {
+               mfc_debug(2, "Frame packing SEI exists for a frame\n");
+               mfc_debug(2, "Reallocate DPBs and issue init_buffer\n");
+               ctx->is_dpb_realloc = 1;
+               s5p_mfc_change_state(ctx, MFCINST_HEAD_PARSED);
+               ctx->capture_state = QUEUE_FREE;
+               ctx->wait_state = WAIT_DECODING;
+               mfc_handle_frame_all_extracted(ctx);
+               goto leave_handle_frame;
+       }
+
+       /* 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) {
+                       struct mfc_timestamp *temp_ts = NULL;
+
+                       mfc_debug(2, "[DRC] Last frame received after resolution change\n");
+                       mfc_handle_frame_all_extracted(ctx);
+                       s5p_mfc_change_state(ctx, MFCINST_RES_CHANGE_END);
+                       /* If there is no display frame after resolution change,
+                        * Some released frames can't be unprotected.
+                        * So, check and request unprotection in the end of DRC.
+                        */
+                       s5p_mfc_cleanup_assigned_dpb(ctx);
+
+                       /* empty the timestamp queue */
+                       while (!list_empty(&ctx->ts_list)) {
+                               temp_ts = list_entry((&ctx->ts_list)->next,
+                                               struct mfc_timestamp, list);
+                               list_del(&temp_ts->list);
+                       }
+                       ctx->ts_count = 0;
+                       ctx->ts_is_full = 0;
+                       s5p_mfc_qos_reset_last_framerate(ctx);
+                       s5p_mfc_qos_set_framerate(ctx, DEC_DEFAULT_FPS);
+
+                       goto leave_handle_frame;
+               } else {
+                       mfc_handle_frame_all_extracted(ctx);
+               }
+       }
+
+       if (s5p_mfc_get_num_of_tile() >= 4)
+               dec->num_of_tile_over_4 = 1;
+
+       switch (dst_frame_status) {
+       case S5P_FIMV_DEC_STATUS_DECODING_DISPLAY:
+               mfc_handle_ref_frame(ctx);
+               break;
+       case S5P_FIMV_DEC_STATUS_DECODING_ONLY:
+               mfc_handle_ref_frame(ctx);
+               /*
+                * Some cases can have many decoding only frames like VP9
+                * alt-ref frame. So need handling release buffer
+                * because of DPB full.
+                */
+               mfc_handle_reuse_buffer(ctx);
+               break;
+       default:
+               break;
+       }
+
+       if (s5p_mfc_dec_status_decoding(dst_frame_status))
+               mfc_handle_frame_copy_timestamp(ctx);
+
+       /* A frame has been decoded and is in the buffer  */
+       if (s5p_mfc_dec_status_display(dst_frame_status))
+               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)
+               mfc_handle_frame_input(ctx, err);
+
+leave_handle_frame:
+       mfc_debug(2, "Assesing whether this context should be run again\n");
+}
+
+static void mfc_handle_stream_copy_timestamp(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf *src_mb)
+{
+       struct s5p_mfc_dev *dev;
+       struct s5p_mfc_enc *enc = ctx->enc_priv;
+       struct s5p_mfc_enc_params *p = &enc->params;
+       struct s5p_mfc_buf *dst_mb;
+       u32 interval;
+       u64 start_timestamp;
+       u64 new_timestamp;
+
+       if (!ctx) {
+               mfc_err_dev("[BUFCON][TS] no mfc context to run\n");
+               return;
+       }
+
+       dev = ctx->dev;
+       if (!dev) {
+               mfc_err_dev("[BUFCON][TS] no device to run\n");
+               return;
+       }
+
+       start_timestamp = src_mb->vb.vb2_buf.timestamp;
+       interval = NSEC_PER_SEC / p->rc_framerate;
+       if (debug_ts == 1)
+               mfc_info_ctx("[BUFCON][TS] %dfps, start timestamp: %lld, base interval: %d\n",
+                               p->rc_framerate, start_timestamp, interval);
+
+       new_timestamp = start_timestamp + (interval * src_mb->done_index);
+       if (debug_ts == 1)
+               mfc_info_ctx("[BUFCON][TS] new timestamp: %lld, interval: %d\n",
+                               new_timestamp, interval * src_mb->done_index);
+
+       /* Get the destination buffer */
+       dst_mb = s5p_mfc_get_buf(&ctx->buf_queue_lock, &ctx->dst_buf_queue, MFC_BUF_NO_TOUCH_USED);
+       if (dst_mb)
+               dst_mb->vb.vb2_buf.timestamp = new_timestamp;
+}
+
+static void mfc_handle_stream_input(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_raw_info *raw;
+       struct s5p_mfc_buf *ref_mb, *src_mb;
+       dma_addr_t enc_addr[3] = { 0, 0, 0 };
+       int i, found_in_src_queue = 0;
+       unsigned int index;
+
+       raw = &ctx->raw_buf;
+
+       s5p_mfc_get_enc_frame_buffer(ctx, &enc_addr[0], raw->num_planes);
+       if (enc_addr[0] == 0) {
+               mfc_debug(3, "no encoded src\n");
+               goto move_buf;
+       }
+       for (i = 0; i < raw->num_planes; i++)
+               mfc_debug(2, "[BUFINFO] ctx[%d] get src addr[%d]: 0x%08llx\n",
+                               ctx->num, i, enc_addr[i]);
+
+       if (IS_BUFFER_BATCH_MODE(ctx)) {
+               src_mb = s5p_mfc_find_first_buf(&ctx->buf_queue_lock,
+                               &ctx->src_buf_queue, enc_addr[0]);
+               if (src_mb) {
+                       found_in_src_queue = 1;
+
+                       mfc_handle_stream_copy_timestamp(ctx, src_mb);
+                       src_mb->done_index++;
+                       mfc_debug(4, "[BUFCON] batch buf done_index: %d\n", src_mb->done_index);
+
+                       index = src_mb->vb.vb2_buf.index;
+
+                       if (call_cop(ctx, recover_buf_ctrls_val, ctx,
+                                               &ctx->src_ctrls[index]) < 0)
+                               mfc_err_ctx("failed in recover_buf_ctrls_val\n");
+
+                       /* single buffer || last image in a buffer container */
+                       if (!src_mb->num_valid_bufs || src_mb->done_index == src_mb->num_valid_bufs) {
+                               src_mb = s5p_mfc_find_del_buf(&ctx->buf_queue_lock,
+                                               &ctx->src_buf_queue, enc_addr[0]);
+                               for (i = 0; i < raw->num_planes; i++)
+                                       s5p_mfc_bufcon_put_daddr(ctx, src_mb, i);
+                               vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
+                       }
+
+                       /* encoder src buffer CFW UNPROT */
+                       if (ctx->is_drm)
+                               s5p_mfc_raw_unprotect(ctx, src_mb, index);
+               }
+       } else {
+               /* normal single buffer */
+               src_mb = s5p_mfc_find_del_buf(&ctx->buf_queue_lock,
+                               &ctx->src_buf_queue, enc_addr[0]);
+               if (src_mb) {
+                       found_in_src_queue = 1;
+                       index = src_mb->vb.vb2_buf.index;
+                       if (call_cop(ctx, recover_buf_ctrls_val, ctx,
+                                               &ctx->src_ctrls[index]) < 0)
+                               mfc_err_ctx("failed in recover_buf_ctrls_val\n");
+
+                       mfc_debug(3, "find src buf in src_queue\n");
+                       vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
+
+                       /* encoder src buffer CFW UNPROT */
+                       if (ctx->is_drm)
+                               s5p_mfc_raw_unprotect(ctx, src_mb, index);
+               } else {
+                       mfc_debug(3, "no src buf in src_queue\n");
+                       ref_mb = s5p_mfc_find_del_buf(&ctx->buf_queue_lock,
+                                       &ctx->ref_buf_queue, enc_addr[0]);
+                       if (ref_mb) {
+                               mfc_debug(3, "find src buf in ref_queue\n");
+                               vb2_buffer_done(&ref_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
+
+                               /* encoder src buffer CFW UNPROT */
+                               if (ctx->is_drm) {
+                                       index = ref_mb->vb.vb2_buf.index;
+                                       s5p_mfc_raw_unprotect(ctx, ref_mb, index);
+                               }
+                       } else {
+                               mfc_err_ctx("couldn't find src buffer\n");
+                       }
+               }
+       }
+
+move_buf:
+       /* move enqueued src buffer: src queue -> ref queue */
+       if (!found_in_src_queue && ctx->state != MFCINST_FINISHING) {
+               s5p_mfc_move_first_buf_used(&ctx->buf_queue_lock,
+                               &ctx->ref_buf_queue, &ctx->src_buf_queue, MFC_QUEUE_ADD_BOTTOM);
+
+               mfc_debug(2, "enc src_buf_queue(%d) -> ref_buf_queue(%d)\n",
+                               s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->src_buf_queue),
+                               s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->ref_buf_queue));
+       }
+}
+
+static void mfc_handle_stream_output(struct s5p_mfc_ctx *ctx, int slice_type,
+                                       unsigned int strm_size)
+{
+       struct s5p_mfc_enc *enc = ctx->enc_priv;
+       struct s5p_mfc_buf *dst_mb;
+       unsigned int index;
+
+       if (strm_size == 0) {
+               mfc_debug(3, "no encoded dst (reuse)\n");
+               return;
+       } else if (strm_size < 0) {
+               mfc_err_ctx("invalid stream size: %d\n", strm_size);
+               return;
+       }
+
+       /* at least one more dest. buffers exist always  */
+       dst_mb = s5p_mfc_get_del_buf(&ctx->buf_queue_lock,
+                       &ctx->dst_buf_queue, MFC_BUF_NO_TOUCH_USED);
+       if (!dst_mb) {
+               mfc_err_ctx("no dst buffers\n");
+               return;
+       }
+
+       mfc_debug(2, "[BUFINFO] ctx[%d] get dst addr: 0x%08llx\n",
+                       ctx->num, dst_mb->addr[0][0]);
+
+       dst_mb->vb.flags &= ~(V4L2_BUF_FLAG_KEYFRAME |
+                               V4L2_BUF_FLAG_PFRAME |
+                               V4L2_BUF_FLAG_BFRAME);
+       switch (slice_type) {
+       case S5P_FIMV_E_SLICE_TYPE_I:
+               dst_mb->vb.flags |= V4L2_BUF_FLAG_KEYFRAME;
+               break;
+       case S5P_FIMV_E_SLICE_TYPE_P:
+               dst_mb->vb.flags |= V4L2_BUF_FLAG_PFRAME;
+               break;
+       case S5P_FIMV_E_SLICE_TYPE_B:
+               dst_mb->vb.flags |= V4L2_BUF_FLAG_BFRAME;
+               break;
+       default:
+               dst_mb->vb.flags |= V4L2_BUF_FLAG_KEYFRAME;
+               break;
+       }
+       mfc_debug(2, "[STREAM] Slice type flag: %d\n", dst_mb->vb.flags);
+
+       if (IS_BPG_ENC(ctx)) {
+               strm_size += enc->header_size;
+               mfc_debug(2, "bpg total stream size: %d\n", strm_size);
+       }
+       vb2_set_plane_payload(&dst_mb->vb.vb2_buf, 0, strm_size);
+
+       index = dst_mb->vb.vb2_buf.index;
+       if (call_cop(ctx, get_buf_ctrls_val, ctx, &ctx->dst_ctrls[index]) < 0)
+               mfc_err_ctx("failed in get_buf_ctrls_val\n");
+
+       vb2_buffer_done(&dst_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
+
+       /* encoder dst buffer CFW UNPROT */
+       if (ctx->is_drm)
+               s5p_mfc_stream_unprotect(ctx, dst_mb, index);
+}
+
+/* Handle frame encoding interrupt */
+static int mfc_handle_stream(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc *enc = ctx->enc_priv;
+       int slice_type;
+       unsigned int strm_size;
+       unsigned int pic_count;
+
+       slice_type = s5p_mfc_get_enc_slice_type();
+       strm_size = s5p_mfc_get_enc_strm_size();
+       pic_count = s5p_mfc_get_enc_pic_count();
+
+       mfc_debug(2, "[STREAM] encoded slice type: %d, size: %d, display order: %d\n",
+                       slice_type, strm_size, pic_count);
+
+       /* buffer full handling */
+       if (enc->buf_full) {
+               s5p_mfc_change_state(ctx, MFCINST_ABORT_INST);
+               return 0;
+       }
+       if (ctx->state == MFCINST_RUNNING_BUF_FULL)
+               s5p_mfc_change_state(ctx, MFCINST_RUNNING);
+
+       /* set encoded frame type */
+       enc->frame_type = slice_type;
+       ctx->sequence++;
+
+       if (enc->in_slice) {
+               if (s5p_mfc_is_queue_count_same(&ctx->buf_queue_lock, &ctx->dst_buf_queue, 0)) {
+                       s5p_mfc_clear_bit(ctx->num, &dev->work_bits);
+               }
+               return 0;
+       }
+
+       /* handle source buffer */
+       mfc_handle_stream_input(ctx);
+
+       /* handle destination buffer */
+       mfc_handle_stream_output(ctx, slice_type, strm_size);
+
+       return 0;
+}
+
+/* Error handling for interrupt */
+static inline void mfc_handle_error(struct s5p_mfc_ctx *ctx,
+       unsigned int reason, unsigned int err)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_buf *src_mb;
+       int index;
+
+       mfc_err_ctx("Interrupt Error: display: %d, decoded: %d\n",
+                       s5p_mfc_get_warn(err), s5p_mfc_get_err(err));
+       err = s5p_mfc_get_err(err);
+
+       /* Error recovery is dependent on the state of context */
+       switch (ctx->state) {
+       case MFCINST_RES_CHANGE_END:
+       case MFCINST_GOT_INST:
+               /* This error had to happen while parsing the header */
+               if (!ctx->is_drm) {
+                       unsigned char *stream_vir = NULL;
+                       unsigned int strm_size = 0;
+
+                       src_mb = s5p_mfc_get_del_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, MFC_BUF_NO_TOUCH_USED);
+                       if (src_mb) {
+                               stream_vir = src_mb->vir_addr;
+                               strm_size = src_mb->vb.vb2_buf.planes[0].bytesused;
+                               if (strm_size > 32)
+                                       strm_size = 32;
+
+                               if (stream_vir && strm_size)
+                                       print_hex_dump(KERN_ERR, "No header: ",
+                                                       DUMP_PREFIX_ADDRESS, strm_size, 0,
+                                                       stream_vir, strm_size, false);
+
+                               vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
+                       }
+               } else {
+                       src_mb = s5p_mfc_get_del_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, MFC_BUF_NO_TOUCH_USED);
+                       if (src_mb) {
+                               index = src_mb->vb.vb2_buf.index;
+                               /* decoder src buffer CFW UNPROT */
+                               s5p_mfc_stream_unprotect(ctx, src_mb, index);
+                               vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
+                       }
+               }
+               break;
+       case MFCINST_INIT:
+               /* This error had to happen while acquireing instance */
+       case MFCINST_RETURN_INST:
+               /* This error had to happen while releasing instance */
+       case MFCINST_DPB_FLUSHING:
+               /* This error had to happen while flushing DPB */
+       case MFCINST_SPECIAL_PARSING:
+       case MFCINST_SPECIAL_PARSING_NAL:
+               /* This error had to happen while special parsing */
+               break;
+       case MFCINST_HEAD_PARSED:
+               /* This error had to happen while setting dst buffers */
+       case MFCINST_RES_CHANGE_INIT:
+       case MFCINST_RES_CHANGE_FLUSH:
+               /* This error has to happen while resolution change */
+       case MFCINST_ABORT_INST:
+               /* This error has to happen while buffer full handling */
+       case MFCINST_FINISHING:
+               /* It is higly probable that an error occured
+                * while decoding a frame */
+               s5p_mfc_change_state(ctx, MFCINST_ERROR);
+               /* Mark all dst buffers as having an error */
+               s5p_mfc_cleanup_queue(&ctx->buf_queue_lock, &ctx->dst_buf_queue);
+               /* Mark all src buffers as having an error */
+               s5p_mfc_cleanup_queue(&ctx->buf_queue_lock, &ctx->src_buf_queue);
+               break;
+       default:
+               mfc_err_ctx("Encountered an error interrupt which had not been handled\n");
+               mfc_err_ctx("ctx->state = %d, ctx->inst_no = %d\n",
+                                               ctx->state, ctx->inst_no);
+               break;
+       }
+
+       s5p_mfc_wake_up_dev(dev, reason, err);
+
+       return;
+}
+
+/* Handle header decoder interrupt */
+static int mfc_handle_seq_dec(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_dec *dec = ctx->dec_priv;
+       int i, is_interlace, is_mbaff;
+
+       if (ctx->src_fmt->fourcc != V4L2_PIX_FMT_FIMV1) {
+               ctx->img_width = s5p_mfc_get_img_width();
+               ctx->img_height = s5p_mfc_get_img_height();
+               ctx->crop_width = ctx->img_width;
+               ctx->crop_height = ctx->img_height;
+               mfc_info_ctx("[STREAM] resolution w: %d, h: %d\n", ctx->img_width, ctx->img_height);
+       }
+
+       ctx->dpb_count = s5p_mfc_get_dpb_count();
+       ctx->scratch_buf_size = s5p_mfc_get_scratch_size();
+       for (i = 0; i < ctx->dst_fmt->num_planes; i++)
+               ctx->min_dpb_size[i] = s5p_mfc_get_min_dpb_size(i);
+
+       s5p_mfc_dec_store_crop_info(ctx);
+       dec->mv_count = s5p_mfc_get_mv_count();
+       if (CODEC_10BIT(ctx) && dev->pdata->support_10bit) {
+               if (s5p_mfc_get_luma_bit_depth_minus8() ||
+                       s5p_mfc_get_chroma_bit_depth_minus8() ||
+                       s5p_mfc_get_profile() == S5P_FIMV_D_PROFILE_HEVC_MAIN_10) {
+                       ctx->is_10bit = 1;
+                       mfc_info_ctx("[STREAM][10BIT] 10bit contents, profile: %d, depth: %d/%d\n",
+                                       s5p_mfc_get_profile(),
+                                       s5p_mfc_get_luma_bit_depth_minus8() + 8,
+                                       s5p_mfc_get_chroma_bit_depth_minus8() + 8);
+               }
+       }
+       if (CODEC_422FORMAT(ctx) && dev->pdata->support_422) {
+               if (s5p_mfc_get_chroma_format() == S5P_FIMV_D_CHROMA_422) {
+                       ctx->is_422 = 1;
+                       mfc_info_ctx("[STREAM] 422 chroma format\n");
+               }
+       }
+
+       if (ctx->img_width == 0 || ctx->img_height == 0)
+               s5p_mfc_change_state(ctx, MFCINST_ERROR);
+       else
+               s5p_mfc_change_state(ctx, MFCINST_HEAD_PARSED);
+
+       if (ctx->state == MFCINST_HEAD_PARSED) {
+               is_interlace = s5p_mfc_is_interlace_picture();
+               is_mbaff = s5p_mfc_is_mbaff_picture();
+               if (is_interlace || is_mbaff)
+                       dec->is_interlaced = 1;
+               mfc_debug(2, "[INTERLACE] interlace: %d, mbaff: %d\n", is_interlace, is_mbaff);
+       }
+
+       if (IS_H264_DEC(ctx) || IS_H264_MVC_DEC(ctx) || IS_HEVC_DEC(ctx)) {
+               struct s5p_mfc_buf *src_mb = s5p_mfc_get_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, MFC_BUF_NO_TOUCH_USED);
+               if (src_mb) {
+                       dec->consumed += s5p_mfc_get_consumed_stream();
+                       mfc_debug(2, "[STREAM] header total size : %d, consumed : %lu\n",
+                                       src_mb->vb.vb2_buf.planes[0].bytesused, dec->consumed);
+                       if ((dec->consumed > 0) &&
+                                       (src_mb->vb.vb2_buf.planes[0].bytesused > dec->consumed)) {
+                               dec->remained_size = src_mb->vb.vb2_buf.planes[0].bytesused -
+                                       dec->consumed;
+                               mfc_debug(2, "[STREAM] there is remained bytes(%lu) after header parsing\n",
+                                               dec->remained_size);
+                       } else {
+                               dec->consumed = 0;
+                               dec->remained_size = 0;
+                       }
+               }
+       }
+
+       if (IS_VP9_DEC(ctx)) {
+               dec->color_range = s5p_mfc_get_color_range();
+               dec->color_space = s5p_mfc_get_color_space();
+               mfc_debug(2, "color range: %d, color space: %d, It's valid for VP9\n",
+                               dec->color_range, dec->color_space);
+       }
+
+       return 0;
+}
+
+/* Handle header encoder interrupt */
+static int mfc_handle_seq_enc(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc *enc = ctx->enc_priv;
+       struct s5p_mfc_enc_params *p = &enc->params;
+       struct s5p_mfc_buf *dst_mb;
+       int ret;
+
+       enc->header_size = s5p_mfc_get_enc_strm_size();
+       mfc_debug(2, "[STREAM] encoded slice type: %d, header size: %d, display order: %d\n",
+                       s5p_mfc_get_enc_slice_type(), enc->header_size,
+                       s5p_mfc_get_enc_pic_count());
+
+       if (IS_BPG_ENC(ctx)) {
+               dst_mb = s5p_mfc_get_buf(&ctx->buf_queue_lock, &ctx->dst_buf_queue, MFC_BUF_NO_TOUCH_USED);
+               if (!dst_mb) {
+                       mfc_err_dev("no dst buffers\n");
+                       return -EAGAIN;
+               }
+
+               dst_mb->vb.vb2_buf.planes[0].data_offset += (enc->header_size +
+                               p->codec.bpg.thumb_size + p->codec.bpg.exif_size);
+               mfc_debug(2, "offset for NAL_START: %d (header: %d + thumb: %d + exif: %d)\n",
+                               dst_mb->vb.vb2_buf.planes[0].data_offset,
+                               enc->header_size,
+                               p->codec.bpg.thumb_size,
+                               p->codec.bpg.exif_size);
+       } else {
+               if ((p->seq_hdr_mode == V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE) ||
+                       (p->seq_hdr_mode == V4L2_MPEG_VIDEO_HEADER_MODE_AT_THE_READY)) {
+                       dst_mb = s5p_mfc_get_del_buf(&ctx->buf_queue_lock,
+                                       &ctx->dst_buf_queue, MFC_BUF_NO_TOUCH_USED);
+                       if (!dst_mb) {
+                               mfc_err_dev("no dst buffers\n");
+                               return -EAGAIN;
+                       }
+
+                       vb2_set_plane_payload(&dst_mb->vb.vb2_buf, 0, s5p_mfc_get_enc_strm_size());
+                       vb2_buffer_done(&dst_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
+
+                       /* encoder dst buffer CFW UNPROT */
+                       if (ctx->is_drm) {
+                               int index = dst_mb->vb.vb2_buf.index;
+
+                               s5p_mfc_stream_unprotect(ctx, dst_mb, index);
+                       }
+               }
+       }
+
+       ctx->dpb_count = s5p_mfc_get_enc_dpb_count();
+       ctx->scratch_buf_size = s5p_mfc_get_enc_scratch_size();
+
+       /* If the ROI is enabled at SEQ_START, clear ROI_ENABLE bit */
+       s5p_mfc_clear_roi_enable(dev);
+
+       if (!ctx->codec_buffer_allocated) {
+               mfc_debug(2, "[DRC] previous codec buffer is exist\n");
+
+               if (dev->has_mmcache && dev->mmcache.is_on_status)
+                       s5p_mfc_invalidate_mmcache(dev);
+
+               s5p_mfc_release_codec_buffers(ctx);
+       }
+       ret = s5p_mfc_alloc_codec_buffers(ctx);
+       if (ret) {
+               mfc_err_ctx("Failed to allocate encoding buffers\n");
+               return ret;
+       }
+
+       s5p_mfc_change_state(ctx, MFCINST_HEAD_PARSED);
+
+       return 0;
+}
+
+static inline int is_err_condition(unsigned int err)
+{
+       if (err == S5P_FIMV_ERR_NO_AVAILABLE_DPB ||
+               err == S5P_FIMV_ERR_INSUFFICIENT_DPB_SIZE ||
+               err == S5P_FIMV_ERR_INSUFFICIENT_NUM_DPB ||
+               err == S5P_FIMV_ERR_INSUFFICIENT_MV_BUF_SIZE ||
+               err == S5P_FIMV_ERR_INSUFFICIENT_SCRATCH_BUF_SIZE)
+               return 1;
+
+       return 0;
+}
+
+irqreturn_t s5p_mfc_top_half_irq(int irq, void *priv)
+{
+       struct s5p_mfc_dev *dev = priv;
+       struct s5p_mfc_ctx *ctx;
+       unsigned int err;
+       unsigned int reason;
+
+       ctx = dev->ctx[dev->curr_ctx];
+       if (!ctx) {
+               mfc_err_dev("no mfc context to run\n");
+               return IRQ_WAKE_THREAD;
+       }
+
+       reason = s5p_mfc_get_int_reason();
+       err = s5p_mfc_get_int_err();
+       mfc_debug(2, "[c:%d] Int reason: %d (err: %d)\n",
+                       dev->curr_ctx, reason, err);
+       MFC_TRACE_CTX("<< INT(top): %d\n", reason);
+
+       s5p_mfc_perf_measure_off(dev);
+
+       return IRQ_WAKE_THREAD;
+}
+
+/*
+ * Return value description
+ *  0: NAL-Q is handled successfully
+ *  1: NAL_START command
+ * -1: Error
+*/
+static inline int mfc_nal_q_irq(struct s5p_mfc_dev *dev,
+               unsigned int reason, unsigned int err)
+{
+       int ret = -1;
+       unsigned int errcode;
+
+       nal_queue_handle *nal_q_handle = dev->nal_q_handle;
+       EncoderOutputStr *pOutStr;
+
+       switch (reason) {
+       case S5P_FIMV_R2H_CMD_QUEUE_DONE_RET:
+               pOutStr = s5p_mfc_nal_q_dequeue_out_buf(dev,
+                       nal_q_handle->nal_q_out_handle, &errcode);
+               if (pOutStr) {
+                       if (s5p_mfc_nal_q_handle_out_buf(dev, pOutStr))
+                               mfc_err_dev("[NALQ] Failed to handle out buf\n");
+               } else {
+                       mfc_err_dev("[NALQ] pOutStr is NULL\n");
+               }
+
+               if (nal_q_handle->nal_q_exception)
+                       s5p_mfc_set_bit(nal_q_handle->nal_q_out_handle->nal_q_ctx,
+                                       &dev->work_bits);
+               s5p_mfc_clear_int_sfr();
+
+               if (!nal_q_handle->nal_q_exception)
+                       s5p_mfc_nal_q_clock_off(dev, nal_q_handle);
+
+               ret = 0;
+               break;
+       case S5P_FIMV_R2H_CMD_COMPLETE_QUEUE_RET:
+               s5p_mfc_watchdog_stop_tick(dev);
+               nal_q_handle->nal_q_state = NAL_Q_STATE_CREATED;
+               MFC_TRACE_DEV("** NAL Q state : %d\n", nal_q_handle->nal_q_state);
+               mfc_debug(2, "[NALQ] return to created state\n");
+               s5p_mfc_nal_q_cleanup_queue(dev);
+               s5p_mfc_nal_q_cleanup_clock(dev);
+               s5p_mfc_clear_int_sfr();
+               s5p_mfc_pm_clock_off(dev);
+               s5p_mfc_wake_up_dev(dev, reason, err);
+
+               ret = 0;
+               break;
+       default:
+               if (nal_q_handle->nal_q_state == NAL_Q_STATE_STARTED ||
+                       nal_q_handle->nal_q_state == NAL_Q_STATE_STOPPED) {
+                       mfc_err_dev("[NALQ] Should not be here! state: %d, int reason : %d\n",
+                               nal_q_handle->nal_q_state, reason);
+                       s5p_mfc_clear_int_sfr();
+
+                       ret = -1;
+               } else {
+                       /* NAL START */
+                       ret = 1;
+               }
+
+               break;
+       }
+
+       if (ret == 0)
+               queue_work(dev->butler_wq, &dev->butler_work);
+
+       return ret;
+}
+
+static inline int mfc_handle_done_frame(struct s5p_mfc_ctx *ctx,
+                               unsigned int reason, unsigned int err)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc *enc = NULL;
+
+       if (ctx->type == MFCINST_DECODER) {
+               if (ctx->state == MFCINST_SPECIAL_PARSING_NAL) {
+                       s5p_mfc_clear_int_sfr();
+                       s5p_mfc_pm_clock_off(dev);
+                       s5p_mfc_clear_bit(ctx->num, &dev->work_bits);
+                       s5p_mfc_change_state(ctx, MFCINST_RUNNING);
+                       s5p_mfc_wake_up_ctx(ctx, reason, err);
+                       return 0;
+               }
+               mfc_handle_frame(ctx, reason, err);
+       } else if (ctx->type == MFCINST_ENCODER) {
+               if (ctx->otf_handle) {
+                       s5p_mfc_otf_handle_stream(ctx);
+                       return 1;
+               }
+               enc = ctx->enc_priv;
+               if (reason == S5P_FIMV_R2H_CMD_SLICE_DONE_RET) {
+                       dev->preempt_ctx = ctx->num;
+                       enc->buf_full = 0;
+                       enc->in_slice = 1;
+               } else if (reason == S5P_FIMV_R2H_CMD_ENC_BUFFER_FULL_RET) {
+                       mfc_err_ctx("stream buffer size(%d) isn't enough\n",
+                                       s5p_mfc_get_enc_strm_size());
+                       dev->preempt_ctx = ctx->num;
+                       enc->buf_full = 1;
+                       enc->in_slice = 0;
+               } else {
+                       enc->buf_full = 0;
+                       enc->in_slice = 0;
+               }
+               mfc_handle_stream(ctx);
+       }
+
+       return 1;
+}
+
+static inline void mfc_handle_nal_abort(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_enc *enc = ctx->enc_priv;
+
+       if (ctx->type == MFCINST_ENCODER) {
+               s5p_mfc_change_state(ctx, MFCINST_RUNNING_BUF_FULL);
+               enc->buf_full = 0;
+               if (IS_VP8_ENC(ctx))
+                       mfc_err_ctx("stream buffer size isn't enough\n");
+               mfc_handle_stream(ctx);
+       } else {
+               s5p_mfc_change_state(ctx, MFCINST_ABORT);
+       }
+}
+
+static int mfc_irq_dev(struct s5p_mfc_dev *dev, unsigned int reason, unsigned int err)
+{
+       /* Stop the timeout watchdog */
+       if (reason != S5P_FIMV_R2H_CMD_FW_STATUS_RET)
+               s5p_mfc_watchdog_stop_tick(dev);
+
+       switch (reason) {
+       case S5P_FIMV_R2H_CMD_CACHE_FLUSH_RET:
+       case S5P_FIMV_R2H_CMD_SYS_INIT_RET:
+       case S5P_FIMV_R2H_CMD_FW_STATUS_RET:
+       case S5P_FIMV_R2H_CMD_SLEEP_RET:
+       case S5P_FIMV_R2H_CMD_WAKEUP_RET:
+               s5p_mfc_clear_int_sfr();
+               s5p_mfc_wake_up_dev(dev, reason, err);
+               return 0;
+       }
+
+       return 1;
+}
+
+static int mfc_irq_ctx(struct s5p_mfc_ctx *ctx, unsigned int reason, unsigned int err)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       switch (reason) {
+       case S5P_FIMV_R2H_CMD_ERR_RET:
+               if (ctx->otf_handle) {
+                       s5p_mfc_otf_handle_error(ctx, reason, err);
+                       break;
+               }
+               /* An error has occured */
+               if (ctx->state == MFCINST_RUNNING || ctx->state == MFCINST_ABORT) {
+                       if ((s5p_mfc_get_err(err) >= S5P_FIMV_ERR_WARNINGS_START) &&
+                               (s5p_mfc_get_err(err) <= S5P_FIMV_ERR_WARNINGS_END))
+                               mfc_handle_frame(ctx, reason, err);
+                       else
+                               mfc_handle_frame_error(ctx, reason, err);
+               } else {
+                       mfc_handle_error(ctx, reason, err);
+               }
+               break;
+       case S5P_FIMV_R2H_CMD_SLICE_DONE_RET:
+       case S5P_FIMV_R2H_CMD_FIELD_DONE_RET:
+       case S5P_FIMV_R2H_CMD_FRAME_DONE_RET:
+       case S5P_FIMV_R2H_CMD_ENC_BUFFER_FULL_RET:
+               return mfc_handle_done_frame(ctx, reason, err);
+       case S5P_FIMV_R2H_CMD_COMPLETE_SEQ_RET:
+               if (ctx->type == MFCINST_ENCODER) {
+                       mfc_handle_stream(ctx);
+                       s5p_mfc_change_state(ctx, MFCINST_RUNNING);
+               } else if (ctx->type == MFCINST_DECODER) {
+                       return mfc_handle_done_frame(ctx, reason, err);
+               }
+               break;
+       case S5P_FIMV_R2H_CMD_SEQ_DONE_RET:
+               if (ctx->type == MFCINST_ENCODER) {
+                       if (ctx->otf_handle) {
+                               s5p_mfc_otf_handle_seq(ctx);
+                               break;
+                       }
+                       mfc_handle_seq_enc(ctx);
+               } else if (ctx->type == MFCINST_DECODER) {
+                       mfc_handle_seq_dec(ctx);
+               }
+               break;
+       case S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET:
+               ctx->inst_no = s5p_mfc_get_inst_no();
+               s5p_mfc_change_state(ctx, MFCINST_GOT_INST);
+               break;
+       case S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET:
+               s5p_mfc_change_state(ctx, MFCINST_FREE);
+               break;
+       case S5P_FIMV_R2H_CMD_NAL_ABORT_RET:
+               mfc_handle_nal_abort(ctx);
+               break;
+       case S5P_FIMV_R2H_CMD_DPB_FLUSH_RET:
+               s5p_mfc_change_state(ctx, MFCINST_ABORT);
+               break;
+       case S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET:
+               if (err != 0) {
+                       mfc_err_ctx("INIT_BUFFERS_RET error: %d\n", err);
+                       break;
+               }
+
+               s5p_mfc_change_state(ctx, MFCINST_RUNNING);
+               if (ctx->type == MFCINST_DECODER) {
+                       if (ctx->wait_state == WAIT_DECODING) {
+                               ctx->wait_state = WAIT_INITBUF_DONE;
+                               mfc_debug(2, "INIT_BUFFER has done, but can't start decoding\n");
+                       }
+                       if (ctx->is_dpb_realloc)
+                               ctx->is_dpb_realloc = 0;
+               }
+               break;
+       default:
+               mfc_err_ctx("Unknown int reason: %d\n", reason);
+       }
+
+       return 1;
+}
+
+/* Interrupt processing */
+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;
+       int ret = -1;
+
+       mfc_debug_enter();
+
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               goto irq_end;
+       }
+
+       if (s5p_mfc_pm_get_pwr_ref_cnt(dev) == 0) {
+               mfc_err_dev("no mfc power on\n");
+               call_dop(dev, dump_and_stop_debug_mode, dev);
+               goto irq_end;
+       }
+
+       /* Get the reason of interrupt and the error code */
+       reason = s5p_mfc_get_int_reason();
+       err = s5p_mfc_get_int_err();
+       mfc_debug(1, "Int reason: %d (err: %d)\n", reason, err);
+       MFC_TRACE_DEV("<< INT: %d\n", reason);
+
+       dev->preempt_ctx = MFC_NO_INSTANCE_SET;
+
+       if (dbg_enable && (reason != S5P_FIMV_R2H_CMD_QUEUE_DONE_RET))
+               s5p_mfc_dbg_disable(dev);
+
+       if ((sfr_dump & MFC_DUMP_ERR_INT) && (reason == S5P_FIMV_R2H_CMD_ERR_RET))
+               call_dop(dev, dump_regs, dev);
+
+       if ((sfr_dump & MFC_DUMP_WARN_INT) &&
+                       (err && (reason != S5P_FIMV_R2H_CMD_ERR_RET)))
+               call_dop(dev, dump_regs, dev);
+
+       if (is_err_condition(err))
+               call_dop(dev, dump_and_stop_debug_mode, dev);
+
+       if (dev->nal_q_handle) {
+               ret = mfc_nal_q_irq(dev, reason, err);
+               if (ret == 0) {
+                       mfc_debug(2, "[NALQ] command was handled\n");
+                       goto irq_end;
+               } else if (ret == 1){
+                       /* Path through */
+                       mfc_debug(2, "NAL_START command will be handled\n");
+               } else {
+                       mfc_debug(2, "[NALQ] command handling Error\n");
+                       goto irq_end;
+               }
+       }
+
+       ret = mfc_irq_dev(dev, reason, err);
+       if (!ret)
+               goto irq_end;
+
+       ctx = dev->ctx[dev->curr_ctx];
+       if (!ctx) {
+               mfc_err_dev("no mfc context to run\n");
+               s5p_mfc_clear_int_sfr();
+               s5p_mfc_pm_clock_off(dev);
+               goto irq_end;
+       }
+
+       ret = mfc_irq_ctx(ctx, reason, err);
+       if (!ret)
+               goto irq_end;
+
+       /* clean-up interrupt */
+       s5p_mfc_clear_int_sfr();
+
+       if ((ctx->state != MFCINST_RES_CHANGE_INIT) && (s5p_mfc_ctx_ready(ctx) == 0))
+               s5p_mfc_clear_bit(ctx->num, &dev->work_bits);
+
+       if (ctx->otf_handle) {
+               if (s5p_mfc_otf_ctx_ready(ctx))
+                       s5p_mfc_set_bit(ctx->num, &dev->work_bits);
+               else
+                       s5p_mfc_clear_bit(ctx->num, &dev->work_bits);
+       }
+
+       s5p_mfc_hwlock_handler_irq(dev, ctx, reason, err);
+
+irq_end:
+       mfc_debug_leave();
+       return IRQ_HANDLED;
+}
diff --git a/drivers/media/platform/exynos/mfc/mfc_irq.h b/drivers/media/platform/exynos/mfc/mfc_irq.h
new file mode 100644 (file)
index 0000000..51ff3af
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_irq.h
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __MFC_IRQ_H
+#define __MFC_IRQ_H __FILE__
+
+#include <linux/interrupt.h>
+
+#include "mfc_common.h"
+
+#include "mfc_utils.h"
+
+irqreturn_t s5p_mfc_top_half_irq(int irq, void *priv);
+irqreturn_t s5p_mfc_irq(int irq, void *priv);
+
+static inline void s5p_mfc_handle_force_change_status(struct s5p_mfc_ctx *ctx)
+{
+       if (ctx->state != MFCINST_ABORT && ctx->state != MFCINST_HEAD_PARSED &&
+                       ctx->state != MFCINST_RES_CHANGE_FLUSH)
+               s5p_mfc_change_state(ctx, MFCINST_RUNNING);
+}
+
+#endif /* __MFC_IRQ_H */
diff --git a/drivers/media/platform/exynos/mfc/mfc_macros.h b/drivers/media/platform/exynos/mfc/mfc_macros.h
new file mode 100644 (file)
index 0000000..b82cde4
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_macros.h
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __MFC_MACROS_H
+#define __MFC_MACROS_H __FILE__
+
+#define WIDTH_MB(x_size)       ((x_size + 15) / 16)
+#define HEIGHT_MB(y_size)      ((y_size + 15) / 16)
+
+/*
+   Note that lcu_width and lcu_height are defined as follows :
+   lcu_width = (frame_width + lcu_size - 1)/lcu_size
+   lcu_height = (frame_height + lcu_size - 1)/lcu_size.
+   (lcu_size is 32(encoder) or 64(decoder))
+*/
+#define DEC_LCU_WIDTH(x_size)  ((x_size + 63) / 64)
+#define ENC_LCU_WIDTH(x_size)  ((x_size + 31) / 32)
+#define DEC_LCU_HEIGHT(y_size) ((y_size + 63) / 64)
+#define ENC_LCU_HEIGHT(y_size) ((y_size + 31) / 32)
+
+#define STREAM_BUF_ALIGN               512
+#define MFC_LINEAR_BUF_SIZE            256
+#define set_strm_size_max(cpb_max)     ((cpb_max) - STREAM_BUF_ALIGN)
+
+#define DEC_STATIC_BUFFER_SIZE 20480
+
+#define DEC_MV_SIZE_MB(x, y)   (WIDTH_MB(x) * (((HEIGHT_MB(y)+1)/2)*2) * 64 + 1024)
+#define DEC_HEVC_MV_SIZE(x, y) (DEC_LCU_WIDTH(x) * DEC_LCU_HEIGHT(y) * 256 + 512)
+
+#define ENC_HEVC_LUMA_DPB_10B_SIZE(x, y)                               \
+       ((x + 63) / 64) * 64 * ((y + 31) / 32 ) * 32 +                  \
+       (((((ENC_LCU_WIDTH(x) * 32 + 3) / 4) + 15) / 16) * 16) *        \
+       ((y + 31) / 32 ) * 32 + 64
+#define ENC_HEVC_CHROMA_DPB_10B_SIZE(x, y)                             \
+       ((x + 63) / 64) * 64 * ((y + 31) / 32 ) * 32 +                  \
+       (((((ENC_LCU_WIDTH(x) * 32 + 3) / 4) + 15) / 16) * 16) *        \
+       ((y + 31) / 32 ) * 32 + 64
+#define ENC_VP9_LUMA_DPB_10B_SIZE(x, y)                                        \
+       (((x * 2 + 127) / 128) * 128) *                                 \
+       ((y + 31) / 32 ) * 32 + 64
+#define ENC_VP9_CHROMA_DPB_10B_SIZE(x, y)                              \
+       (((x * 2 + 127) / 128) * 128) *                                 \
+       ((y + 31) / 32 ) * 32 + 64
+#define ENC_LUMA_DPB_SIZE(x, y)                                                \
+       ((x + 63) / 64) * 64 * ((y + 31) / 32 ) * 32 + 64
+#define ENC_CHROMA_DPB_SIZE(x, y)                                      \
+       ((x + 63) / 64) * 64 * ((((y + 31) / 32 ) * 32) / 2) + 64
+
+#define ENC_V100_H264_ME_SIZE(x, y)                            \
+       (((x + 3) * (y + 3) * 8) + ((((x * y) + 63) / 64) * 32) + (((y * 64) + 2304) * (x + 7) / 8))
+#define ENC_V100_MPEG4_ME_SIZE(x, y)                           \
+       (((x + 3) * (y + 3) * 8) + ((((x * y) + 127) / 128) * 16) + (((y * 64) + 2304) * (x + 7) / 8))
+#define ENC_V100_VP8_ME_SIZE(x, y)                             \
+       (((x + 3) * (y + 3) * 8) + (((y * 64) + 2304) * (x + 7) / 8))
+#define ENC_V100_VP9_ME_SIZE(x, y)                             \
+       ((((x * 2) + 3) * ((y * 2) + 3) * 128) + (((y * 256) + 2304) * (x + 1) / 2))
+#define ENC_V100_HEVC_ME_SIZE(x, y)                            \
+       (((x + 3) * (y + 3) * 32) + (((y * 128) + 2304) * (x + 3) / 4))
+
+#endif /* __MFC_MACROS_H */
diff --git a/drivers/media/platform/exynos/mfc/mfc_mem.c b/drivers/media/platform/exynos/mfc/mfc_mem.c
new file mode 100644 (file)
index 0000000..f09819e
--- /dev/null
@@ -0,0 +1,274 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_mem.c
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include "mfc_mem.h"
+
+struct vb2_mem_ops *s5p_mfc_mem_ops(void)
+{
+       return (struct vb2_mem_ops *)&vb2_dma_sg_memops;
+}
+
+void s5p_mfc_mem_clean(struct s5p_mfc_dev *dev,
+                       struct s5p_mfc_special_buf *special_buf,
+                       off_t offset, size_t size)
+{
+       __dma_map_area(special_buf->vaddr + offset, size, DMA_TO_DEVICE);
+       return;
+}
+
+void s5p_mfc_mem_invalidate(struct s5p_mfc_dev *dev,
+                       struct s5p_mfc_special_buf *special_buf,
+                       off_t offset, size_t size)
+{
+       __dma_map_area(special_buf->vaddr + offset, size, DMA_FROM_DEVICE);
+       return;
+}
+
+int s5p_mfc_mem_get_user_shared_handle(struct s5p_mfc_ctx *ctx,
+       struct mfc_user_shared_handle *handle)
+{
+       int ret = 0;
+
+       handle->dma_buf = dma_buf_get(handle->fd);
+       if (IS_ERR(handle->dma_buf)) {
+               mfc_err_ctx("Failed to import fd\n");
+               ret = PTR_ERR(handle->dma_buf);
+               goto import_dma_fail;
+       }
+
+       handle->vaddr = dma_buf_vmap(handle->dma_buf);
+       if (handle->vaddr == NULL) {
+               mfc_err_ctx("Failed to get kernel virtual address\n");
+               ret = -EINVAL;
+               goto map_kernel_fail;
+       }
+
+       return 0;
+
+map_kernel_fail:
+       handle->vaddr = NULL;
+       dma_buf_put(handle->dma_buf);
+
+import_dma_fail:
+       handle->dma_buf = NULL;
+       handle->fd = -1;
+       return ret;
+}
+
+void s5p_mfc_mem_cleanup_user_shared_handle(struct s5p_mfc_ctx *ctx,
+               struct mfc_user_shared_handle *handle)
+{
+       if (handle->vaddr)
+               dma_buf_vunmap(handle->dma_buf, handle->vaddr);
+       if (handle->dma_buf)
+               dma_buf_put(handle->dma_buf);
+
+       handle->dma_buf = NULL;
+       handle->vaddr = NULL;
+       handle->fd = -1;
+}
+
+int s5p_mfc_mem_ion_alloc(struct s5p_mfc_dev *dev,
+               struct s5p_mfc_special_buf *special_buf)
+{
+       struct s5p_mfc_ctx *ctx = dev->ctx[dev->curr_ctx];
+       int flag;
+       const char *heapname;
+
+       switch (special_buf->buftype) {
+       case MFCBUF_NORMAL:
+               heapname = "ion_system_heap";
+               flag = 0;
+               break;
+       case MFCBUF_NORMAL_FW:
+               heapname = "vnfw_heap";
+               flag = 0;
+               break;
+       case MFCBUF_DRM:
+               heapname = "vframe_heap";
+               flag = ION_FLAG_PROTECTED;
+               break;
+       case MFCBUF_DRM_FW:
+               heapname = "vfw_heap";
+               flag = ION_FLAG_PROTECTED;
+               break;
+       default:
+               mfc_err_ctx("not supported mfc mem type: %d, heapname: %s\n",
+                               special_buf->buftype, heapname);
+               return -EINVAL;
+       }
+       special_buf->dma_buf =
+                       ion_alloc_dmabuf(heapname, special_buf->size, flag);
+       if (IS_ERR(special_buf->dma_buf)) {
+               mfc_err_ctx("Failed to allocate buffer (err %ld)\n",
+                               PTR_ERR(special_buf->dma_buf));
+               call_dop(dev, dump_and_stop_debug_mode, dev);
+               goto err_ion_alloc;
+       }
+
+       special_buf->attachment = dma_buf_attach(special_buf->dma_buf, dev->device);
+       if (IS_ERR(special_buf->attachment)) {
+               mfc_err_ctx("Failed to get dma_buf_attach (err %ld)\n",
+                               PTR_ERR(special_buf->attachment));
+               call_dop(dev, dump_and_stop_debug_mode, dev);
+               goto err_attach;
+       }
+
+       special_buf->sgt = dma_buf_map_attachment(special_buf->attachment,
+                       DMA_BIDIRECTIONAL);
+       if (IS_ERR(special_buf->sgt)) {
+               mfc_err_ctx("Failed to get sgt (err %ld)\n",
+                               PTR_ERR(special_buf->sgt));
+               call_dop(dev, dump_and_stop_debug_mode, dev);
+               goto err_map;
+       }
+
+       special_buf->daddr = ion_iovmm_map(special_buf->attachment, 0,
+                       special_buf->size, DMA_BIDIRECTIONAL, 0);
+       if (IS_ERR_VALUE(special_buf->daddr)) {
+               mfc_err_ctx("Failed to allocate iova (err 0x%p)\n",
+                               &special_buf->daddr);
+               call_dop(dev, dump_and_stop_debug_mode, dev);
+               goto err_iovmm;
+       }
+
+       special_buf->vaddr = dma_buf_vmap(special_buf->dma_buf);
+       if (IS_ERR(special_buf->vaddr)) {
+               mfc_err_ctx("Failed to get vaddr (err 0x%p)\n",
+                               &special_buf->vaddr);
+               call_dop(dev, dump_and_stop_debug_mode, dev);
+               goto err_vaddr;
+       }
+
+       return 0;
+err_vaddr:
+       special_buf->vaddr = NULL;
+       ion_iovmm_unmap(special_buf->attachment, special_buf->daddr);
+
+err_iovmm:
+       special_buf->daddr = 0;
+       dma_buf_unmap_attachment(special_buf->attachment, special_buf->sgt,
+                                DMA_BIDIRECTIONAL);
+err_map:
+       special_buf->sgt = NULL;
+       dma_buf_detach(special_buf->dma_buf, special_buf->attachment);
+err_attach:
+       special_buf->attachment = NULL;
+       dma_buf_put(special_buf->dma_buf);
+err_ion_alloc:
+       special_buf->dma_buf = NULL;
+       return -ENOMEM;
+}
+
+void s5p_mfc_mem_ion_free(struct s5p_mfc_dev *dev,
+               struct s5p_mfc_special_buf *special_buf)
+{
+       if (special_buf->vaddr)
+               dma_buf_vunmap(special_buf->dma_buf, special_buf->vaddr);
+       if (special_buf->daddr)
+               ion_iovmm_unmap(special_buf->attachment, special_buf->daddr);
+       if (special_buf->sgt)
+               dma_buf_unmap_attachment(special_buf->attachment,
+                                        special_buf->sgt, DMA_BIDIRECTIONAL);
+       if (special_buf->attachment)
+               dma_buf_detach(special_buf->dma_buf, special_buf->attachment);
+       if (special_buf->dma_buf)
+               dma_buf_put(special_buf->dma_buf);
+
+       special_buf->dma_buf = NULL;
+       special_buf->attachment = NULL;
+       special_buf->sgt = NULL;
+       special_buf->daddr = 0;
+       special_buf->vaddr = NULL;
+}
+
+void s5p_mfc_bufcon_put_daddr(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf *mfc_buf, int plane)
+{
+       int i;
+
+       for (i = 0; i < mfc_buf->num_valid_bufs; i++) {
+               if (mfc_buf->addr[i][plane]) {
+                       mfc_debug(4, "[BUFCON] put batch buf addr[%d][%d]: 0x%08llx\n",
+                                       i, plane, mfc_buf->addr[i][plane]);
+                       ion_iovmm_unmap(mfc_buf->attachments[i][plane], mfc_buf->addr[i][plane]);
+               }
+               if (mfc_buf->attachments[i][plane])
+                       dma_buf_detach(mfc_buf->dmabufs[i][plane], mfc_buf->attachments[i][plane]);
+               if (mfc_buf->dmabufs[i][plane])
+                       dma_buf_put(mfc_buf->dmabufs[i][plane]);
+
+               mfc_buf->addr[i][plane] = 0;
+               mfc_buf->attachments[i][plane] = NULL;
+               mfc_buf->dmabufs[i][plane] = NULL;
+       }
+}
+
+int s5p_mfc_bufcon_get_daddr(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf *mfc_buf,
+                                       struct dma_buf *bufcon_dmabuf, int plane)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_raw_info *raw = &ctx->raw_buf;
+       int i, j = 0;
+       u32 mask;
+
+       if (dmabuf_container_get_mask(bufcon_dmabuf, &mask)) {
+               mfc_err_ctx("[BUFCON] it is not buffer container\n");
+               return -1;
+       } else {
+               mfc_debug(3, "[BUFCON] bufcon mask info %#x\n", mask);
+       }
+
+       for (i = 0; i < mfc_buf->num_bufs_in_batch; i++) {
+               if ((mask & (1 << i)) == 0) {
+                       mfc_debug(4, "[BUFCON] unmasked buf[%d]\n", i);
+                       continue;
+               }
+
+               mfc_buf->dmabufs[j][plane] = dmabuf_container_get_buffer(bufcon_dmabuf, i);
+               if (IS_ERR(mfc_buf->dmabufs[i][plane])) {
+                       mfc_err_ctx("[BUFCON] Failed to get dma_buf (err %ld)",
+                                       PTR_ERR(mfc_buf->dmabufs[i][plane]));
+                       call_dop(dev, dump_and_stop_debug_mode, dev);
+                       goto err_get_daddr;
+               }
+
+               mfc_buf->attachments[j][plane] = dma_buf_attach(mfc_buf->dmabufs[i][plane], dev->device);
+               if (IS_ERR(mfc_buf->attachments[i][plane])) {
+                       mfc_err_ctx("[BUFCON] Failed to get dma_buf_attach (err %ld)",
+                                       PTR_ERR(mfc_buf->attachments[i][plane]));
+                       call_dop(dev, dump_and_stop_debug_mode, dev);
+                       goto err_get_daddr;
+               }
+
+               mfc_buf->addr[j][plane] = ion_iovmm_map(mfc_buf->attachments[i][plane], 0,
+                               raw->plane_size[plane], DMA_BIDIRECTIONAL, 0);
+               if (IS_ERR_VALUE(mfc_buf->addr[i][plane])) {
+                       mfc_err_ctx("[BUFCON] Failed to allocate iova (err %pa)",
+                                       &mfc_buf->addr[i][plane]);
+                       call_dop(dev, dump_and_stop_debug_mode, dev);
+                       goto err_get_daddr;
+               }
+
+               mfc_debug(4, "[BUFCON] get batch buf addr[%d][%d]: 0x%08llx, size: %d\n",
+                               j, plane, mfc_buf->addr[j][plane], raw->plane_size[plane]);
+               j++;
+       }
+
+       mfc_buf->num_valid_bufs = j;
+       mfc_debug(3, "[BUFCON] batch buffer has %d buffers\n", mfc_buf->num_valid_bufs);
+
+       return 0;
+
+err_get_daddr:
+       s5p_mfc_bufcon_put_daddr(ctx, mfc_buf, plane);
+       return -1;
+}
diff --git a/drivers/media/platform/exynos/mfc/mfc_mem.h b/drivers/media/platform/exynos/mfc/mfc_mem.h
new file mode 100644 (file)
index 0000000..5a3a65b
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_mem.h
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __MFC_MEM_H
+#define __MFC_MEM_H __FILE__
+
+#include "mfc_common.h"
+
+/* Offset base used to differentiate between CAPTURE and OUTPUT
+*  while mmaping */
+#define DST_QUEUE_OFF_BASE      (TASK_SIZE / 2)
+
+static inline dma_addr_t s5p_mfc_mem_get_daddr_vb(
+       struct vb2_buffer *vb, unsigned int n)
+{
+       dma_addr_t addr = 0;
+
+       addr = vb2_dma_sg_plane_dma_addr(vb, n);
+       WARN_ON((addr == 0) || IS_ERR_VALUE(addr));
+
+       return addr;
+}
+
+static inline int s5p_mfc_bufcon_get_buf_count(struct dma_buf *dmabuf)
+{
+       return dmabuf_container_get_count(dmabuf);
+}
+
+struct vb2_mem_ops *s5p_mfc_mem_ops(void);
+
+void s5p_mfc_mem_set_cacheable(bool cacheable);
+void s5p_mfc_mem_clean(struct s5p_mfc_dev *dev,
+                       struct s5p_mfc_special_buf *specail_buf,
+                       off_t offset, size_t size);
+void s5p_mfc_mem_invalidate(struct s5p_mfc_dev *dev,
+                       struct s5p_mfc_special_buf *specail_buf,
+                       off_t offset, size_t size);
+
+int s5p_mfc_mem_get_user_shared_handle(struct s5p_mfc_ctx *ctx,
+               struct mfc_user_shared_handle *handle);
+void s5p_mfc_mem_cleanup_user_shared_handle(struct s5p_mfc_ctx *ctx,
+               struct mfc_user_shared_handle *handle);
+
+int s5p_mfc_mem_ion_alloc(struct s5p_mfc_dev *dev,
+               struct s5p_mfc_special_buf *special_buf);
+void s5p_mfc_mem_ion_free(struct s5p_mfc_dev *dev,
+               struct s5p_mfc_special_buf *special_buf);
+
+void s5p_mfc_bufcon_put_daddr(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf *mfc_buf, int plane);
+int s5p_mfc_bufcon_get_daddr(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf *mfc_buf,
+                                       struct dma_buf *bufcon_dmabuf, int plane);
+#endif /* __MFC_MEM_H */
diff --git a/drivers/media/platform/exynos/mfc/mfc_mmcache.c b/drivers/media/platform/exynos/mfc/mfc_mmcache.c
new file mode 100644 (file)
index 0000000..7385139
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_mmcache.c
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include "mfc_mmcache.h"
+
+#include "mfc_reg.h"
+
+static const unsigned char mmcache_SFR_0x0010[] = {
+       0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+       0x2A, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+static const unsigned char mmcache_SFR_0x0040[] = {
+       0x0E, 0x00, 0x1E, 0x00, 0x0E, 0x00, 0x1E, 0x00, 0x0E, 0x00, 0x1E, 0x00, 0x0E, 0x00, 0x1E, 0x00,
+       0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+       0x10, 0x00, 0x1F, 0x00, 0x10, 0x00, 0x1F, 0x00, 0x10, 0x00, 0x1F, 0x00, 0x10, 0x00, 0x1F, 0x00,
+       0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
+       0x0C, 0x00, 0x1F, 0x00, 0x0C, 0x00, 0x1F, 0x00, 0x0C, 0x00, 0x1F, 0x00, 0x0C, 0x00, 0x1F, 0x00,
+       0x12, 0x00, 0x3F, 0x00, 0x08, 0x00, 0x3F, 0x00, 0x0C, 0x00, 0x3D, 0x00, 0x0C, 0x00, 0x3D, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+static void mmcache_print_config(struct s5p_mfc_dev *dev)
+{
+       void __iomem *addr;
+       unsigned int size;
+
+       mfc_debug_enter();
+
+       if (!mmcache_dump)
+               return;
+
+       size = sizeof(mmcache_SFR_0x0010);
+       addr = dev->mmcache.base + MMCACHE_WAY0_CTRL;
+
+       print_hex_dump(KERN_ERR, "[MMCACHE] Config:", DUMP_PREFIX_ADDRESS, 32, 4, addr, size, false);
+
+       size = sizeof(mmcache_SFR_0x0040);
+       addr = dev->mmcache.base + MMCACHE_MASTER_GRP0_RPATH0;
+
+       print_hex_dump(KERN_ERR, "[MMCACHE] Config:", DUMP_PREFIX_ADDRESS, 32, 4, addr, size, false);
+
+       mfc_debug_leave();
+}
+
+static void mmcache_set_config(struct s5p_mfc_dev *dev)
+{
+       unsigned int data, i, size;
+       const unsigned int *sfr_dump;
+
+       mfc_debug_enter();
+
+       size = sizeof(mmcache_SFR_0x0010);
+       sfr_dump = (const unsigned int *)mmcache_SFR_0x0010;
+
+       for (i = 0; i < size; i += 4) {
+               data = sfr_dump[i / 4];
+               MMCACHE_WRITEL(data, MMCACHE_WAY0_CTRL + i);
+       }
+
+       size = sizeof(mmcache_SFR_0x0040);
+       sfr_dump = (const unsigned int *)mmcache_SFR_0x0040;
+
+       for (i = 0; i < size; i += 4) {
+               data = sfr_dump[i / 4];
+               MMCACHE_WRITEL(data, MMCACHE_MASTER_GRP0_RPATH0 + i);
+       }
+
+       mfc_debug(2, "[MMCACHE] mmcache config setting is done\n");
+
+       mfc_debug_leave();
+}
+
+static void mmcache_reset_config(struct s5p_mfc_dev *dev)
+{
+       void __iomem *addr;
+       unsigned int data;
+
+       mfc_debug_enter();
+
+       addr = dev->mmcache.base + MMCACHE_MASTER_GRP_CTRL2;
+       data = 0;
+
+       mfc_debug(2, "[MMCACHE] before write 0x%X: (0x%08llX) 0x%X\n",
+                       data, (unsigned long long)(addr),
+                       MMCACHE_READL(MMCACHE_MASTER_GRP_CTRL2));
+
+       MMCACHE_WRITEL(data, MMCACHE_MASTER_GRP_CTRL2);
+
+       mfc_debug(2, "[MMCACHE] after write 0x%X: (0x%08llX) 0x%X\n",
+                       data, (unsigned long long)(addr),
+                       MMCACHE_READL(MMCACHE_MASTER_GRP_CTRL2));
+
+       mfc_debug_leave();
+}
+
+static void mmcache_update_master_grp(struct s5p_mfc_dev *dev)
+{
+       void __iomem *addr;
+       unsigned int data;
+
+       mfc_debug_enter();
+
+       addr = dev->mmcache.base + MMCACHE_GLOBAL_CTRL;
+       data = MMCACHE_GLOBAL_CTRL_VALUE;
+
+       mfc_debug(2, "[MMCACHE] before write 0x%X: (0x%08llX) 0x%X\n",
+                       data, (unsigned long long)(addr),
+                       MMCACHE_READL(MMCACHE_GLOBAL_CTRL));
+
+       MMCACHE_WRITEL(data, MMCACHE_GLOBAL_CTRL);
+
+       mfc_debug(2, "[MMCACHE] after write 0x%X: (0x%08llX) 0x%X\n",
+                       data, (unsigned long long)(addr),
+                       MMCACHE_READL(MMCACHE_GLOBAL_CTRL));
+
+       mfc_debug_leave();
+}
+
+static void mmcache_enable_clock_gating(struct s5p_mfc_dev *dev)
+{
+       void __iomem *addr;
+       unsigned int data;
+
+       mfc_debug_enter();
+
+       addr = dev->mmcache.base + MMCACHE_CG_CONTROL;
+       data = MMCACHE_CG_CONTROL_VALUE;
+
+       mfc_debug(2, "[MMCACHE] before write 0x%X: (0x%08llX) 0x%X\n",
+                       data, (unsigned long long)(addr),
+                       MMCACHE_READL(MMCACHE_CG_CONTROL));
+
+       MMCACHE_WRITEL(data, MMCACHE_CG_CONTROL);
+
+       mfc_debug(2, "[MMCACHE] after write 0x%X: (0x%08llX) 0x%X\n",
+                       data, (unsigned long long)(addr),
+                       MMCACHE_READL(MMCACHE_CG_CONTROL));
+
+       mfc_debug_leave();
+}
+
+void s5p_mfc_mmcache_enable(struct s5p_mfc_dev *dev)
+{
+       mfc_debug_enter();
+
+       if (mmcache_disable)
+               return;
+
+       mmcache_set_config(dev);
+       mmcache_print_config(dev);
+       mmcache_update_master_grp(dev);
+       mmcache_enable_clock_gating(dev);
+
+       dev->mmcache.is_on_status = 1;
+       mfc_info_dev("[MMCACHE] enabled\n");
+       MFC_TRACE_DEV("[MMCACHE] enabled\n");
+
+       mfc_debug_leave();
+}
+
+void s5p_mfc_mmcache_disable(struct s5p_mfc_dev *dev)
+{
+       mfc_debug_enter();
+
+       mmcache_reset_config(dev);
+       mmcache_update_master_grp(dev);
+
+       dev->mmcache.is_on_status = 0;
+       mfc_info_dev("[MMCACHE] disabled\n");
+       MFC_TRACE_DEV("[MMCACHE] disabled\n");
+
+       mfc_debug_leave();
+}
+
+void s5p_mfc_invalidate_mmcache(struct s5p_mfc_dev *dev)
+{
+       void __iomem *addr;
+       unsigned int data;
+       unsigned long timeout;
+
+       mfc_debug_enter();
+
+       addr = dev->mmcache.base + MMCACHE_INVALIDATE;
+       data = MMCACHE_INVALIDATE_VALUE;
+
+       mfc_debug(2, "[MMCACHE] before write 0x%X: (0x%08llX) 0x%X\n",
+                       data, (unsigned long long)(addr),
+                       MMCACHE_READL(MMCACHE_INVALIDATE));
+
+       MMCACHE_WRITEL(data, MMCACHE_INVALIDATE);
+
+       mfc_debug(2, "[MMCACHE] after write 0x%X: (0x%08llX) 0x%X\n",
+                       data, (unsigned long long)(addr),
+                       MMCACHE_READL(MMCACHE_INVALIDATE));
+
+       addr = dev->mmcache.base + MMCACHE_INVALIDATE_STATUS;
+
+       timeout = jiffies + msecs_to_jiffies(MMCACHE_INVAL_TIMEOUT);
+       while (1) {
+               if (MMCACHE_READL(MMCACHE_INVALIDATE_STATUS) == 0) {
+                       mfc_debug(2, "[MMCACHE] invalidate done: (0x%08llX) 0x%X\n",
+                                       (unsigned long long)(addr), __raw_readl(addr));
+                       break;
+               }
+               if (time_after(jiffies, timeout)) {
+                       mfc_err_dev("[MMCACHE] Timeout while invalidation\n");
+                       call_dop(dev, dump_and_stop_debug_mode, dev);
+                       break;
+               }
+       }
+
+       mfc_debug(2, "[MMCACHE] invalidated\n");
+       MFC_TRACE_DEV("[MMCACHE] invalidated\n");
+
+       mfc_debug_leave();
+}
diff --git a/drivers/media/platform/exynos/mfc/mfc_mmcache.h b/drivers/media/platform/exynos/mfc/mfc_mmcache.h
new file mode 100644 (file)
index 0000000..c9f67af
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_mmcache.h
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __MFC_MMCACHE_H
+#define __MFC_MMCACHE_H __FILE__
+
+#include "mfc_common.h"
+
+#define MMCACHE_GLOBAL_CTRL            0x0000
+#define MMCACHE_INVALIDATE_STATUS      0x0008
+#define MMCACHE_WAY0_CTRL              0x0010
+#define MMCACHE_MASTER_GRP_CTRL2       0x0028
+#define MMCACHE_MASTER_GRP0_RPATH0     0x0040
+#define MMCACHE_CG_CONTROL             0x0400
+#define MMCACHE_INVALIDATE             0x0114
+
+#define MMCACHE_GLOBAL_CTRL_VALUE      0x2
+#define MMCACHE_CG_CONTROL_VALUE       0x7FF
+#define MMCACHE_INVALIDATE_VALUE       0x41
+
+/* Need HW lock to call this function */
+
+void s5p_mfc_mmcache_enable(struct s5p_mfc_dev *dev);
+void s5p_mfc_mmcache_disable(struct s5p_mfc_dev *dev);
+
+
+/* Need HW lock to call this function */
+void s5p_mfc_invalidate_mmcache(struct s5p_mfc_dev *dev);
+
+#endif /* __MFC_MMCACHE_H */
diff --git a/drivers/media/platform/exynos/mfc/mfc_nal_q.c b/drivers/media/platform/exynos/mfc/mfc_nal_q.c
new file mode 100644 (file)
index 0000000..74d330b
--- /dev/null
@@ -0,0 +1,1997 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_nal_q.c
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include "mfc_nal_q.h"
+
+#include "mfc_sync.h"
+
+#include "mfc_pm.h"
+#include "mfc_cal.h"
+#include "mfc_reg.h"
+
+#include "mfc_qos.h"
+#include "mfc_queue.h"
+#include "mfc_utils.h"
+#include "mfc_buf.h"
+#include "mfc_mem.h"
+
+#define CBR_I_LIMIT_MAX                        5
+int s5p_mfc_nal_q_check_enable(struct s5p_mfc_dev *dev)
+{
+       struct s5p_mfc_ctx *temp_ctx;
+       struct s5p_mfc_dec *dec = NULL;
+       struct s5p_mfc_enc *enc = NULL;
+       struct s5p_mfc_enc_params *p = NULL;
+       int i;
+
+       mfc_debug_enter();
+
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return -EINVAL;
+       }
+
+       if (nal_q_disable)
+               return 0;
+
+       for (i = 0; i < MFC_NUM_CONTEXTS; i++) {
+               temp_ctx = dev->ctx[i];
+               if (temp_ctx) {
+                       /* NAL-Q doesn't support drm */
+                       if (temp_ctx->is_drm) {
+                               mfc_debug(2, "There is a drm ctx. Can't start NAL-Q\n");
+                               return 0;
+                       }
+                       /* NAL-Q can be enabled when all ctx are in running state */
+                       if (temp_ctx->state != MFCINST_RUNNING) {
+                               mfc_debug(2, "There is a ctx which is not in running state. "
+                                               "index: %d, state: %d\n", i, temp_ctx->state);
+                               return 0;
+                       }
+                       /* NAL-Q can't use the command about last frame */
+                       if (s5p_mfc_is_last_frame(temp_ctx) == 1) {
+                               mfc_debug(2, "There is a last frame. index: %d\n", i);
+                               return 0;
+                       }
+                       /* NAL-Q doesn't support OTF mode */
+                       if (temp_ctx->otf_handle) {
+                               mfc_debug(2, "There is a OTF node\n");
+                               return 0;
+                       }
+                       /* NAL-Q doesn't support BPG */
+                       if (IS_BPG_DEC(temp_ctx) || IS_BPG_ENC(temp_ctx)) {
+                               mfc_debug(2, "BPG codec type\n");
+                               return 0;
+                       }
+                       /* NAL-Q doesn't support multi-frame, interlaced, black bar */
+                       if (temp_ctx->type == MFCINST_DECODER) {
+                               dec = temp_ctx->dec_priv;
+                               if (!dec) {
+                                       mfc_debug(2, "There is no dec\n");
+                                       return 0;
+                               }
+                               if ((dec->has_multiframe && CODEC_MULTIFRAME(temp_ctx)) || dec->consumed) {
+                                       mfc_debug(2, "[MULTIFRAME] There is a multi frame or consumed header\n");
+                                       return 0;
+                               }
+                               if (dec->is_dpb_full) {
+                                       mfc_debug(2, "[DPB] All buffers are referenced\n");
+                                       return 0;
+                               }
+                               if (dec->is_interlaced) {
+                                       mfc_debug(2, "[INTERLACE] There is a interlaced stream\n");
+                                       return 0;
+                               }
+                               if (dec->detect_black_bar) {
+                                       mfc_debug(2, "[BLACKBAR] black bar detection is enabled\n");
+                                       return 0;
+                               }
+                       /* NAL-Q doesn't support fixed byte(slice mode), CBR_VT(rc mode) */
+                       } else if (temp_ctx->type == MFCINST_ENCODER) {
+                               enc = temp_ctx->enc_priv;
+                               if (!enc) {
+                                       mfc_debug(2, "There is no enc\n");
+                                       return 0;
+                               }
+                               if (enc->slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_FIXED_BYTES) {
+                                       mfc_debug(2, "There is fixed bytes option(slice mode)\n");
+                                       return 0;
+                               }
+                               p = &enc->params;
+                               if (p->rc_reaction_coeff <= CBR_I_LIMIT_MAX) {
+                                       mfc_debug(2, "There is CBR_VT option(rc mode)\n");
+                                       return 0;
+                               }
+                       }
+                       mfc_debug(2, "There is a ctx in running state. index: %d\n", i);
+               }
+       }
+
+       mfc_debug(2, "All working ctx are in running state!\n");
+
+       mfc_debug_leave();
+
+       return 1;
+}
+
+void s5p_mfc_nal_q_clock_on(struct s5p_mfc_dev *dev, nal_queue_handle *nal_q_handle)
+{
+       unsigned long flags;
+
+       mfc_debug_enter();
+
+       spin_lock_irqsave(&nal_q_handle->lock, flags);
+
+       mfc_debug(2, "[NALQ] continue_clock_on = %d, nal_q_clk_cnt = %d\n",
+                       dev->continue_clock_on, nal_q_handle->nal_q_clk_cnt);
+
+       if (!dev->continue_clock_on && !nal_q_handle->nal_q_clk_cnt)
+               s5p_mfc_pm_clock_on(dev);
+
+       nal_q_handle->nal_q_clk_cnt++;
+       dev->continue_clock_on = false;
+
+       mfc_debug(2, "[NALQ] nal_q_clk_cnt = %d\n", nal_q_handle->nal_q_clk_cnt);
+
+       spin_unlock_irqrestore(&nal_q_handle->lock, flags);
+
+       mfc_debug_leave();
+}
+
+void s5p_mfc_nal_q_clock_off(struct s5p_mfc_dev *dev, nal_queue_handle *nal_q_handle)
+{
+       unsigned long flags;
+
+       mfc_debug_enter();
+
+       spin_lock_irqsave(&nal_q_handle->lock, flags);
+
+       mfc_debug(2, "[NALQ] nal_q_clk_cnt = %d\n", nal_q_handle->nal_q_clk_cnt);
+
+       if (!nal_q_handle->nal_q_clk_cnt) {
+               mfc_err_dev("[NALQ] nal_q_clk_cnt is already zero\n");
+               return;
+       }
+
+       nal_q_handle->nal_q_clk_cnt--;
+
+       if (!nal_q_handle->nal_q_clk_cnt)
+               s5p_mfc_pm_clock_off(dev);
+
+       mfc_debug(2, "[NALQ] nal_q_clk_cnt = %d\n", nal_q_handle->nal_q_clk_cnt);
+
+       spin_unlock_irqrestore(&nal_q_handle->lock, flags);
+
+       mfc_debug_leave();
+}
+
+void s5p_mfc_nal_q_cleanup_clock(struct s5p_mfc_dev *dev)
+{
+       unsigned long flags;
+
+       mfc_debug_enter();
+
+       spin_lock_irqsave(&dev->nal_q_handle->lock, flags);
+
+       dev->nal_q_handle->nal_q_clk_cnt = 0;
+
+       spin_unlock_irqrestore(&dev->nal_q_handle->lock, flags);
+
+       mfc_debug_leave();
+}
+
+static int mfc_nal_q_find_ctx(struct s5p_mfc_dev *dev, EncoderOutputStr *pOutputStr)
+{
+       int i;
+
+       if (!dev) {
+               mfc_err_dev("[NALQ] no mfc device to run\n");
+               return -EINVAL;
+       }
+
+       for(i = 0; i < MFC_NUM_CONTEXTS; i++) {
+               if (dev->ctx[i] && dev->ctx[i]->inst_no == pOutputStr->InstanceId)
+                       return i;
+       }
+       return -1;
+}
+
+static nal_queue_in_handle* mfc_nal_q_create_in_q(struct s5p_mfc_dev *dev,
+               nal_queue_handle *nal_q_handle)
+{
+       nal_queue_in_handle *nal_q_in_handle;
+
+       mfc_debug_enter();
+
+       if (!dev) {
+               mfc_err_dev("[NALQ] no mfc device to run\n");
+               return NULL;
+       }
+
+       nal_q_in_handle = kzalloc(sizeof(*nal_q_in_handle), GFP_KERNEL);
+       if (!nal_q_in_handle) {
+               mfc_err_dev("[NALQ] Failed to get memory for nal_queue_in_handle\n");
+               return NULL;
+       }
+
+       nal_q_in_handle->nal_q_handle = nal_q_handle;
+       nal_q_in_handle->in_buf.buftype = MFCBUF_NORMAL;
+       nal_q_in_handle->in_buf.size = NAL_Q_IN_ENTRY_SIZE * (NAL_Q_IN_QUEUE_SIZE + 2);
+       if (s5p_mfc_mem_ion_alloc(dev, &nal_q_in_handle->in_buf)) {
+               mfc_err_dev("[NALQ] failed to get memory\n");
+               kfree(nal_q_in_handle);
+               return NULL;
+       }
+       nal_q_in_handle->nal_q_in_addr = (nal_in_queue *)nal_q_in_handle->in_buf.vaddr;
+
+       mfc_debug_leave();
+
+       return nal_q_in_handle;
+}
+
+static nal_queue_out_handle* mfc_nal_q_create_out_q(struct s5p_mfc_dev *dev,
+               nal_queue_handle *nal_q_handle)
+{
+       nal_queue_out_handle *nal_q_out_handle;
+
+       mfc_debug_enter();
+
+       if (!dev) {
+               mfc_err_dev("[NALQ] no mfc device to run\n");
+               return NULL;
+       }
+
+       nal_q_out_handle = kzalloc(sizeof(*nal_q_out_handle), GFP_KERNEL);
+       if (!nal_q_out_handle) {
+               mfc_err_dev("[NALQ] failed to get memory for nal_queue_out_handle\n");
+               return NULL;
+       }
+
+       nal_q_out_handle->nal_q_handle = nal_q_handle;
+       nal_q_out_handle->out_buf.buftype = MFCBUF_NORMAL;
+       nal_q_out_handle->out_buf.size = NAL_Q_OUT_ENTRY_SIZE * (NAL_Q_OUT_QUEUE_SIZE + 2);
+       if (s5p_mfc_mem_ion_alloc(dev, &nal_q_out_handle->out_buf)) {
+               mfc_err_dev("[NALQ] failed to get memory\n");
+               kfree(nal_q_out_handle);
+               return NULL;
+       }
+       nal_q_out_handle->nal_q_out_addr = (nal_out_queue *)nal_q_out_handle->out_buf.vaddr;
+
+       mfc_debug_leave();
+
+       return nal_q_out_handle;
+}
+
+static int mfc_nal_q_destroy_in_q(struct s5p_mfc_dev *dev,
+                       nal_queue_in_handle *nal_q_in_handle)
+{
+       mfc_debug_enter();
+
+       if (!nal_q_in_handle)
+               return -EINVAL;
+
+       s5p_mfc_mem_ion_free(dev, &nal_q_in_handle->in_buf);
+       if (nal_q_in_handle)
+               kfree(nal_q_in_handle);
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+static int mfc_nal_q_destroy_out_q(struct s5p_mfc_dev *dev,
+                       nal_queue_out_handle *nal_q_out_handle)
+{
+       mfc_debug_enter();
+
+       if (!nal_q_out_handle)
+               return -EINVAL;
+
+       s5p_mfc_mem_ion_free(dev, &nal_q_out_handle->out_buf);
+       if (nal_q_out_handle)
+               kfree(nal_q_out_handle);
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+/*
+ * This function should be called after s5p_mfc_alloc_firmware() being called.
+ */
+nal_queue_handle *s5p_mfc_nal_q_create(struct s5p_mfc_dev *dev)
+{
+       nal_queue_handle *nal_q_handle;
+
+       mfc_debug_enter();
+
+       if (!dev) {
+               mfc_err_dev("[NALQ] no mfc device to run\n");
+               return NULL;
+       }
+
+       nal_q_handle = kzalloc(sizeof(*nal_q_handle), GFP_KERNEL);
+       if (!nal_q_handle) {
+               mfc_err_dev("[NALQ] no nal_q_handle\n");
+               return NULL;
+       }
+
+       nal_q_handle->nal_q_in_handle = mfc_nal_q_create_in_q(dev, nal_q_handle);
+       if (!nal_q_handle->nal_q_in_handle) {
+               kfree(nal_q_handle);
+               mfc_err_dev("[NALQ] no nal_q_in_handle\n");
+               return NULL;
+       }
+
+       spin_lock_init(&nal_q_handle->lock);
+
+       nal_q_handle->nal_q_out_handle = mfc_nal_q_create_out_q(dev, nal_q_handle);
+       if (!nal_q_handle->nal_q_out_handle) {
+               mfc_nal_q_destroy_in_q(dev, nal_q_handle->nal_q_in_handle);
+               kfree(nal_q_handle);
+               mfc_err_dev("[NALQ] no nal_q_out_handle\n");
+               return NULL;
+       }
+
+       nal_q_handle->nal_q_state = NAL_Q_STATE_CREATED;
+       MFC_TRACE_DEV("** NAL Q state : %d\n", nal_q_handle->nal_q_state);
+       mfc_debug(2, "[NALQ] handle created, state = %d\n", nal_q_handle->nal_q_state);
+
+       mfc_debug_leave();
+
+       return nal_q_handle;
+}
+
+int s5p_mfc_nal_q_destroy(struct s5p_mfc_dev *dev, nal_queue_handle *nal_q_handle)
+{
+       int ret = 0;
+
+       mfc_debug_enter();
+
+       if (!dev) {
+               mfc_err_dev("[NALQ] no mfc device to run\n");
+               return -EINVAL;
+       }
+
+       if (!nal_q_handle) {
+               mfc_err_dev("[NALQ] there isn't nal_q_handle\n");
+               return -EINVAL;
+       }
+
+       ret = mfc_nal_q_destroy_out_q(dev, nal_q_handle->nal_q_out_handle);
+       if (ret) {
+               mfc_err_dev("[NALQ] failed nal_q_out_handle destroy\n");
+               return ret;
+       }
+
+       ret = mfc_nal_q_destroy_in_q(dev, nal_q_handle->nal_q_in_handle);
+       if (ret) {
+               mfc_err_dev("[NALQ] failed nal_q_in_handle destroy\n");
+               return ret;
+       }
+
+       kfree(nal_q_handle);
+       dev->nal_q_handle = NULL;
+
+       mfc_debug_leave();
+
+       return ret;
+}
+
+void s5p_mfc_nal_q_init(struct s5p_mfc_dev *dev, nal_queue_handle *nal_q_handle)
+{
+       mfc_debug_enter();
+
+       if (!dev) {
+               mfc_err_dev("[NALQ] no mfc device to run\n");
+               return;
+       }
+
+       if (!nal_q_handle) {
+               mfc_err_dev("[NALQ] There is no nal_q_handle\n");
+               return;
+       }
+
+       if ((nal_q_handle->nal_q_state != NAL_Q_STATE_CREATED)
+               && (nal_q_handle->nal_q_state != NAL_Q_STATE_STOPPED)) {
+               mfc_err_dev("[NALQ] State is wrong, state: %d\n", nal_q_handle->nal_q_state);
+               return;
+       }
+
+       s5p_mfc_reset_nal_queue_registers(dev);
+
+       nal_q_handle->nal_q_in_handle->in_exe_count = 0;
+       nal_q_handle->nal_q_out_handle->out_exe_count = 0;
+
+       mfc_debug(2, "[NALQ] S5P_FIMV_NAL_QUEUE_INPUT_COUNT=%d\n",
+               s5p_mfc_get_nal_q_input_count());
+       mfc_debug(2, "[NALQ] S5P_FIMV_NAL_QUEUE_OUTPUT_COUNT=%d\n",
+               s5p_mfc_get_nal_q_output_count());
+       mfc_debug(2, "[NALQ] S5P_FIMV_NAL_QUEUE_INPUT_EXE_COUNT=%d\n",
+               s5p_mfc_get_nal_q_input_exe_count());
+       mfc_debug(2, "[NALQ] S5P_FIMV_NAL_QUEUE_INFO=%d\n",
+               s5p_mfc_get_nal_q_info());
+
+       nal_q_handle->nal_q_exception = 0;
+
+       mfc_debug_leave();
+
+       return;
+}
+
+void s5p_mfc_nal_q_start(struct s5p_mfc_dev *dev, nal_queue_handle *nal_q_handle)
+{
+       dma_addr_t addr;
+
+       mfc_debug_enter();
+
+       if (!dev) {
+               mfc_err_dev("[NALQ] no mfc device to run\n");
+               return;
+       }
+
+       if (!nal_q_handle) {
+               mfc_err_dev("[NALQ] There is no nal_q_handle\n");
+               return;
+       }
+
+       if (nal_q_handle->nal_q_state != NAL_Q_STATE_CREATED) {
+               mfc_err_dev("[NALQ] State is wrong, state: %d\n", nal_q_handle->nal_q_state);
+               return;
+       }
+
+       addr = nal_q_handle->nal_q_in_handle->in_buf.daddr;
+
+       s5p_mfc_update_nal_queue_input(dev, addr, NAL_Q_IN_ENTRY_SIZE * NAL_Q_IN_QUEUE_SIZE);
+
+       mfc_debug(2, "[NALQ] S5P_FIMV_NAL_QUEUE_INPUT_ADDR=0x%x\n",
+               s5p_mfc_get_nal_q_input_addr());
+       mfc_debug(2, "[NALQ] S5P_FIMV_NAL_QUEUE_INPUT_SIZE=%d\n",
+               s5p_mfc_get_nal_q_input_size());
+
+       addr = nal_q_handle->nal_q_out_handle->out_buf.daddr;
+
+       s5p_mfc_update_nal_queue_output(dev, addr, NAL_Q_OUT_ENTRY_SIZE * NAL_Q_OUT_QUEUE_SIZE);
+
+       mfc_debug(2, "[NALQ] S5P_FIMV_NAL_QUEUE_OUTPUT_ADDR=0x%x\n",
+               s5p_mfc_get_nal_q_output_addr());
+       mfc_debug(2, "[NALQ] S5P_FIMV_NAL_QUEUE_OUTPUT_SIZE=%d\n",
+               s5p_mfc_get_nal_q_output_ize());
+
+       nal_q_handle->nal_q_state = NAL_Q_STATE_STARTED;
+       MFC_TRACE_DEV("** NAL Q state : %d\n", nal_q_handle->nal_q_state);
+       mfc_debug(2, "[NALQ] started, state = %d\n", nal_q_handle->nal_q_state);
+
+       MFC_WRITEL(MFC_TIMEOUT_VALUE, S5P_FIMV_DEC_TIMEOUT_VALUE);
+       s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_NAL_QUEUE);
+
+       mfc_debug_leave();
+
+       return;
+}
+
+void s5p_mfc_nal_q_stop(struct s5p_mfc_dev *dev, nal_queue_handle *nal_q_handle)
+{
+       mfc_debug_enter();
+
+       if (!dev) {
+               mfc_err_dev("[NALQ] no mfc device to run\n");
+               return;
+       }
+
+       if (!nal_q_handle) {
+               mfc_err_dev("[NALQ] There is no nal_q_handle\n");
+               return;
+       }
+
+       if (nal_q_handle->nal_q_state != NAL_Q_STATE_STARTED) {
+               mfc_err_dev("[NALQ] State is wrong, state: %d\n", nal_q_handle->nal_q_state);
+               return;
+       }
+
+       nal_q_handle->nal_q_state = NAL_Q_STATE_STOPPED;
+       MFC_TRACE_DEV("** NAL Q state : %d\n", nal_q_handle->nal_q_state);
+       mfc_debug(2, "[NALQ] stopped, state = %d\n", nal_q_handle->nal_q_state);
+
+       s5p_mfc_clean_dev_int_flags(dev);
+
+       s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_STOP_QUEUE);
+
+       mfc_debug_leave();
+
+       return;
+}
+
+void s5p_mfc_nal_q_stop_if_started(struct s5p_mfc_dev *dev)
+{
+       nal_queue_handle *nal_q_handle;
+
+       mfc_debug_enter();
+
+       if (!dev) {
+               mfc_err_dev("[NALQ] no mfc device to run\n");
+               return;
+       }
+
+       nal_q_handle = dev->nal_q_handle;
+       if (!nal_q_handle) {
+               mfc_err_dev("[NALQ] There is no nal_q_handle\n");
+               return;
+       }
+
+       if (nal_q_handle->nal_q_state != NAL_Q_STATE_STARTED) {
+               mfc_debug(2, "[NALQ] it is not running, state: %d\n",
+                               nal_q_handle->nal_q_state);
+               return;
+       }
+
+       s5p_mfc_nal_q_clock_on(dev, nal_q_handle);
+
+       s5p_mfc_nal_q_stop(dev, nal_q_handle);
+       mfc_info_dev("[NALQ] stop NAL QUEUE during get hwlock\n");
+       if (s5p_mfc_wait_for_done_dev(dev,
+                               S5P_FIMV_R2H_CMD_COMPLETE_QUEUE_RET)) {
+               mfc_err_dev("[NALQ] Failed to stop qeueue during get hwlock\n");
+               dev->logging_data->cause |= (1 << MFC_CAUSE_FAIL_STOP_NAL_Q_FOR_OTHER);
+               call_dop(dev, dump_and_stop_always, dev);
+       }
+
+       mfc_debug_leave();
+       return;
+}
+
+void s5p_mfc_nal_q_cleanup_queue(struct s5p_mfc_dev *dev)
+{
+       struct s5p_mfc_ctx *ctx;
+       int i;
+
+       mfc_debug_enter();
+
+       if (!dev) {
+               mfc_err_dev("[NALQ] no mfc device to run\n");
+               return;
+       }
+
+       for(i = 0; i < MFC_NUM_CONTEXTS; i++) {
+               ctx = dev->ctx[i];
+               if (ctx) {
+                       s5p_mfc_cleanup_nal_queue(ctx);
+                       if (s5p_mfc_ctx_ready(ctx)) {
+                               s5p_mfc_set_bit(ctx->num, &dev->work_bits);
+                               mfc_debug(2, "[NALQ] set work_bits after cleanup,"
+                                               " ctx: %d\n", ctx->num);
+                       }
+               }
+       }
+
+       mfc_debug_leave();
+
+       return;
+}
+
+static void mfc_nal_q_set_slice_mode(struct s5p_mfc_ctx *ctx, EncoderInputStr *pInStr)
+{
+       struct s5p_mfc_enc *enc = ctx->enc_priv;
+
+       /* multi-slice control */
+       if (enc->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES)
+               pInStr->MsliceMode = enc->slice_mode + 0x4;
+       else if (enc->slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB_ROW)
+               pInStr->MsliceMode = enc->slice_mode - 0x2;
+       else if (enc->slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_FIXED_BYTES)
+               pInStr->MsliceMode = enc->slice_mode + 0x3;
+       else
+               pInStr->MsliceMode = enc->slice_mode;
+
+       /* multi-slice MB number or bit size */
+       if ((enc->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB) ||
+                       (enc->slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB_ROW)) {
+               pInStr->MsliceSizeMb = enc->slice_size.mb;
+       } else if ((enc->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES) ||
+                       (enc->slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_FIXED_BYTES)){
+               pInStr->MsliceSizeBits = enc->slice_size.bits;
+       } else {
+               pInStr->MsliceSizeMb = 0;
+               pInStr->MsliceSizeBits = 0;
+       }
+}
+
+static int mfc_nal_q_run_in_buf_enc(struct s5p_mfc_ctx *ctx, EncoderInputStr *pInStr)
+{
+       struct s5p_mfc_dev *dev;
+       struct s5p_mfc_buf *src_mb, *dst_mb;
+       struct s5p_mfc_raw_info *raw = NULL;
+       dma_addr_t src_addr[3] = {0, 0, 0};
+       dma_addr_t addr_2bit[2] = {0, 0};
+       unsigned int index, i;
+
+       mfc_debug_enter();
+
+       if (!ctx) {
+               mfc_err_dev("[NALQ] no mfc context to run\n");
+               return -EINVAL;
+       }
+       dev = ctx->dev;
+       if (!dev) {
+               mfc_err_dev("[NALQ] no mfc device to run\n");
+               return -EINVAL;
+       }
+
+       pInStr->StartCode = 0xBBBBBBBB;
+       pInStr->CommandId = s5p_mfc_get_nal_q_input_count();
+       pInStr->InstanceId = ctx->inst_no;
+
+       raw = &ctx->raw_buf;
+
+       if (IS_BUFFER_BATCH_MODE(ctx)) {
+               src_mb = s5p_mfc_get_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, MFC_BUF_SET_USED);
+               if (!src_mb) {
+                       mfc_err_dev("[NALQ][BUFCON] no src buffers\n");
+                       return -EAGAIN;
+               }
+
+               /* last image in a buffer container */
+               /* move src_queue -> src_queue_nal_q */
+               if (src_mb->next_index == (src_mb->num_valid_bufs - 1)) {
+                       src_mb = s5p_mfc_get_move_buf(&ctx->buf_queue_lock,
+                                       &ctx->src_buf_nal_queue, &ctx->src_buf_queue,
+                                       MFC_BUF_SET_USED, MFC_QUEUE_ADD_BOTTOM);
+                       if (!src_mb) {
+                               mfc_err_dev("[NALQ][BUFCON] no src buffers\n");
+                               return -EAGAIN;
+                       }
+               }
+
+               index = src_mb->vb.vb2_buf.index;
+               for (i = 0; i < raw->num_planes; i++) {
+                       src_addr[i] = src_mb->addr[src_mb->next_index][i];
+                       mfc_debug(2, "[NALQ][BUFCON][BUFINFO] ctx[%d] set src index:%d, batch[%d], addr[%d]: 0x%08llx\n",
+                                       ctx->num, index, src_mb->next_index, i, src_addr[i]);
+               }
+               src_mb->next_index++;
+       } else {
+               /* move src_queue -> src_queue_nal_q */
+               src_mb = s5p_mfc_get_move_buf(&ctx->buf_queue_lock,
+                               &ctx->src_buf_nal_queue, &ctx->src_buf_queue,
+                               MFC_BUF_SET_USED, MFC_QUEUE_ADD_BOTTOM);
+               if (!src_mb) {
+                       mfc_err_dev("[NALQ] no src buffers\n");
+                       return -EAGAIN;
+               }
+
+               index = src_mb->vb.vb2_buf.index;
+               for (i = 0; i < raw->num_planes; i++) {
+                       src_addr[i] = src_mb->addr[0][i];
+                       mfc_debug(2, "[NALQ][BUFINFO] ctx[%d] set src index:%d, addr[%d]: 0x%08llx\n",
+                                       ctx->num, index, i, src_addr[i]);
+               }
+       }
+
+       for (i = 0; i < raw->num_planes; i++)
+               pInStr->FrameAddr[i] = src_addr[i];
+
+       if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M_S10B ||
+               ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV21M_S10B) {
+               addr_2bit[0] = src_addr[0] + NV12N_Y_SIZE(ctx->img_width, ctx->img_height);
+               addr_2bit[1] = src_addr[1] + NV12N_CBCR_SIZE(ctx->img_width, ctx->img_height);
+
+               for (i = 0; i < raw->num_planes; i++) {
+                       pInStr->Frame2bitAddr[i] = addr_2bit[i];
+                       mfc_debug(2, "[NALQ][BUFINFO] ctx[%d] set src 2bit addr[%d]: 0x%08llx\n",
+                                       ctx->num, index, i, addr_2bit[i]);
+               }
+       } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV16M_S10B ||
+               ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV61M_S10B) {
+               addr_2bit[0] = src_addr[0] + NV16M_Y_SIZE(ctx->img_width, ctx->img_height);
+               addr_2bit[1] = src_addr[1] + NV16M_CBCR_SIZE(ctx->img_width, ctx->img_height);
+
+               for (i = 0; i < raw->num_planes; i++) {
+                       pInStr->Frame2bitAddr[i] = addr_2bit[i];
+                       mfc_debug(2, "[NALQ][BUFINFO] ctx[%d] set src 2bit addr[%d]: 0x%08llx\n",
+                                       ctx->num, index, i, addr_2bit[i]);
+               }
+       }
+
+       /* move dst_queue -> dst_queue_nal_q */
+       dst_mb = s5p_mfc_get_move_buf(&ctx->buf_queue_lock,
+               &ctx->dst_buf_nal_queue, &ctx->dst_buf_queue, MFC_BUF_SET_USED, MFC_QUEUE_ADD_BOTTOM);
+       if (!dst_mb) {
+               mfc_err_dev("[NALQ] no dst buffers\n");
+               return -EAGAIN;
+       }
+
+       pInStr->StreamBufferAddr = dst_mb->addr[0][0];
+       pInStr->StreamBufferSize = (unsigned int)vb2_plane_size(&dst_mb->vb.vb2_buf, 0);
+       pInStr->StreamBufferSize = ALIGN(pInStr->StreamBufferSize, 512);
+
+       if (call_cop(ctx, set_buf_ctrls_val_nal_q_enc, ctx, &ctx->src_ctrls[index], pInStr) < 0)
+               mfc_err_ctx("[NALQ] failed in set_buf_ctrals_val in nal q\n");
+
+       mfc_debug(2, "[NALQ][BUFINFO] ctx[%d] set dst index: %d, addr: 0x%08llx\n",
+                       ctx->num, dst_mb->vb.vb2_buf.index, pInStr->StreamBufferAddr);
+       mfc_debug(2, "[NALQ] input queue, src_buf_queue -> src_buf_nal_queue, index:%d\n",
+                       src_mb->vb.vb2_buf.index);
+       mfc_debug(2, "[NALQ] input queue, dst_buf_queue -> dst_buf_nal_queue, index:%d\n",
+                       dst_mb->vb.vb2_buf.index);
+
+       mfc_nal_q_set_slice_mode(ctx, pInStr);
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+static int mfc_nal_q_run_in_buf_dec(struct s5p_mfc_ctx *ctx, DecoderInputStr *pInStr)
+{
+       struct s5p_mfc_dev *dev;
+       struct s5p_mfc_buf *src_mb, *dst_mb;
+       struct s5p_mfc_dec *dec;
+       struct s5p_mfc_raw_info *raw = &ctx->raw_buf;
+       dma_addr_t buf_addr;
+       unsigned int strm_size;
+       unsigned int cpb_buf_size;
+       int src_index, dst_index;
+       int i;
+
+       mfc_debug_enter();
+
+       if (!ctx) {
+               mfc_err_dev("[NALQ] no mfc context to run\n");
+               return -EINVAL;
+       }
+       dev = ctx->dev;
+       if (!dev) {
+               mfc_err_dev("[NALQ] no mfc device to run\n");
+               return -EINVAL;
+       }
+       dec = ctx->dec_priv;
+       if (!dec) {
+               mfc_err_dev("[NALQ] no mfc decoder to run\n");
+               return -EINVAL;
+       }
+
+       if (s5p_mfc_is_queue_count_same(&ctx->buf_queue_lock, &ctx->dst_buf_queue, 0) &&
+                       s5p_mfc_is_queue_count_smaller(&ctx->buf_queue_lock,
+                               &ctx->ref_buf_queue, (ctx->dpb_count + 5))) {
+               mfc_err_dev("[NALQ] no dst buffers\n");
+               return -EAGAIN;
+       }
+
+       if (s5p_mfc_is_queue_count_same(&ctx->buf_queue_lock, &ctx->src_buf_queue, 0)) {
+               mfc_err_dev("[NALQ] no src buffers\n");
+               return -EAGAIN;
+       }
+
+       pInStr->StartCode = 0xAAAAAAAA;
+       pInStr->CommandId = s5p_mfc_get_nal_q_input_count();
+       pInStr->InstanceId = ctx->inst_no;
+       pInStr->NalStartOptions = 0;
+
+       /* Try to use the non-referenced DPB on dst-queue */
+       dst_mb = s5p_mfc_search_move_dpb_nal_q(ctx, dec->dynamic_used);
+       if (!dst_mb) {
+               mfc_debug(2, "[NALQ][DPB] couldn't find dst buffers\n");
+               return -EAGAIN;
+       }
+
+       /* move src_queue -> src_queue_nal_q */
+       src_mb = s5p_mfc_get_move_buf(&ctx->buf_queue_lock,
+                       &ctx->src_buf_nal_queue, &ctx->src_buf_queue,
+                       MFC_BUF_SET_USED, MFC_QUEUE_ADD_BOTTOM);
+       if (!src_mb) {
+               mfc_err_dev("[NALQ] no src buffers\n");
+               return -EAGAIN;
+       }
+
+       /* src buffer setting */
+       src_index = src_mb->vb.vb2_buf.index;
+       buf_addr = src_mb->addr[0][0];
+       strm_size = src_mb->vb.vb2_buf.planes[0].bytesused;
+       cpb_buf_size = ALIGN(dec->src_buf_size, STREAM_BUF_ALIGN);
+
+       if (strm_size > set_strm_size_max(cpb_buf_size)) {
+               mfc_info_ctx("[NALQ] Decrease strm_size : %u -> %u, gap : %d\n",
+                               strm_size, set_strm_size_max(cpb_buf_size), STREAM_BUF_ALIGN);
+               strm_size = set_strm_size_max(cpb_buf_size);
+               src_mb->vb.vb2_buf.planes[0].bytesused = strm_size;
+       }
+
+       mfc_debug(2, "[NALQ][BUFINFO] ctx[%d] set src index: %d, addr: 0x%08llx\n",
+                       ctx->num, src_index, buf_addr);
+       mfc_debug(2, "[NALQ][STREAM] strm_size: %#lx(%d), buf_size: %u\n",
+                       strm_size, strm_size, cpb_buf_size);
+
+       if (strm_size == 0)
+               mfc_info_ctx("stream size is 0\n");
+
+       pInStr->StreamDataSize = strm_size;
+       pInStr->CpbBufferAddr = buf_addr;
+       pInStr->CpbBufferSize = cpb_buf_size;
+       pInStr->CpbBufferOffset = 0;
+
+       MFC_TRACE_CTX("Set src[%d] fd: %d, %#llx\n",
+                       src_index, src_mb->vb.vb2_buf.planes[0].m.fd, buf_addr);
+
+       /* dst buffer setting */
+       dst_index = dst_mb->vb.vb2_buf.index;
+       set_bit(dst_index, &dec->available_dpb);
+       dec->dynamic_set = 1 << dst_index;
+
+       for (i = 0; i < raw->num_planes; i++) {
+               pInStr->FrameSize[i] = raw->plane_size[i];
+               pInStr->FrameAddr[i] = dst_mb->addr[0][i];
+               if (ctx->is_10bit)
+                       pInStr->Frame2BitSize[i] = raw->plane_size_2bits[i];
+               mfc_debug(2, "[NALQ][BUFINFO][DPB] ctx[%d] set dst index: %d, addr[%d]: 0x%08llx\n",
+                               ctx->num, dst_index, i, dst_mb->addr[0][i]);
+       }
+
+       pInStr->ScratchBufAddr = ctx->codec_buf.daddr;
+       pInStr->ScratchBufSize = ctx->scratch_buf_size;
+
+       if (call_cop(ctx, set_buf_ctrls_val_nal_q_dec, ctx,
+                               &ctx->src_ctrls[src_index], pInStr) < 0)
+               mfc_err_ctx("[NALQ] failed in set_buf_ctrls_val\n");
+
+       pInStr->DynamicDpbFlagLower = dec->dynamic_set;
+
+       /* use dynamic_set value to available dpb in NAL Q */
+       // pInStr->AvailableDpbFlagLower = dec->available_dpb;
+       pInStr->AvailableDpbFlagLower = dec->dynamic_set;
+
+       MFC_TRACE_CTX("Set dst[%d] fd: %d, %#llx / avail %#lx used %#x\n",
+                       dst_index, dst_mb->vb.vb2_buf.planes[0].m.fd, dst_mb->addr[0][0],
+                       dec->available_dpb, dec->dynamic_used);
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+static void mfc_nal_q_get_enc_frame_buffer(struct s5p_mfc_ctx *ctx,
+               dma_addr_t addr[], int num_planes, EncoderOutputStr *pOutStr)
+{
+       unsigned long enc_recon_y_addr, enc_recon_c_addr;
+       int i;
+
+       for (i = 0; i < num_planes; i++)
+               addr[i] = pOutStr->EncodedFrameAddr[i];
+
+       enc_recon_y_addr = pOutStr->ReconLumaDpbAddr;
+       enc_recon_c_addr = pOutStr->ReconChromaDpbAddr;
+
+       mfc_debug(2, "[NALQ][MEMINFO] recon y: 0x%08lx c: 0x%08lx\n",
+                       enc_recon_y_addr, enc_recon_c_addr);
+}
+
+static void mfc_nal_q_handle_stream_copy_timestamp(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf *src_mb)
+{
+       struct s5p_mfc_dev *dev;
+       struct s5p_mfc_enc *enc = ctx->enc_priv;
+       struct s5p_mfc_enc_params *p = &enc->params;
+       struct s5p_mfc_buf *dst_mb;
+       u32 interval;
+       u64 start_timestamp;
+       u64 new_timestamp;
+
+       if (!ctx) {
+               mfc_err_dev("[NALQ][BUFCON][TS] no mfc context to run\n");
+               return;
+       }
+
+       dev = ctx->dev;
+       if (!dev) {
+               mfc_err_dev("[NALQ][BUFCON][TS] no device to run\n");
+               return;
+       }
+
+       start_timestamp = src_mb->vb.vb2_buf.timestamp;
+       interval = NSEC_PER_SEC / p->rc_framerate;
+       if (debug_ts == 1)
+               mfc_info_ctx("[NALQ][BUFCON][TS] %dfps, start timestamp: %lld, base interval: %d\n",
+                               p->rc_framerate, start_timestamp, interval);
+
+       new_timestamp = start_timestamp + (interval * src_mb->done_index);
+       if (debug_ts == 1)
+               mfc_info_ctx("[NALQ][BUFCON][TS] new timestamp: %lld, interval: %d\n",
+                               new_timestamp, interval * src_mb->done_index);
+
+       /* Get the destination buffer */
+       dst_mb = s5p_mfc_get_buf(&ctx->buf_queue_lock, &ctx->dst_buf_nal_queue, MFC_BUF_NO_TOUCH_USED);
+       if (dst_mb)
+               dst_mb->vb.vb2_buf.timestamp = new_timestamp;
+}
+
+static void mfc_nal_q_handle_stream_input(struct s5p_mfc_ctx *ctx, EncoderOutputStr *pOutStr)
+{
+       struct s5p_mfc_buf *src_mb, *ref_mb;
+       dma_addr_t enc_addr[3] = { 0, 0, 0 };
+       struct s5p_mfc_raw_info *raw;
+       int found_in_src_queue = 0;
+       unsigned int i;
+
+       raw = &ctx->raw_buf;
+
+       mfc_nal_q_get_enc_frame_buffer(ctx, &enc_addr[0], raw->num_planes, pOutStr);
+       if (enc_addr[0] == 0) {
+               mfc_debug(3, "[NALQ] no encoded src\n");
+               goto move_buf;
+       }
+
+       for (i = 0; i < raw->num_planes; i++)
+               mfc_debug(2, "[NALQ][BUFINFO] ctx[%d] get src addr[%d]: 0x%08llx\n",
+                               ctx->num, i, enc_addr[i]);
+
+       if (IS_BUFFER_BATCH_MODE(ctx)) {
+               src_mb = s5p_mfc_find_first_buf(&ctx->buf_queue_lock,
+                               &ctx->src_buf_queue, enc_addr[0]);
+               if (src_mb) {
+                       found_in_src_queue = 1;
+
+                       mfc_nal_q_handle_stream_copy_timestamp(ctx, src_mb);
+                       src_mb->done_index++;
+                       mfc_debug(4, "[NALQ][BUFCON] batch buf done_index: %d\n", src_mb->done_index);
+               } else {
+                       src_mb = s5p_mfc_find_first_buf(&ctx->buf_queue_lock,
+                                       &ctx->src_buf_nal_queue, enc_addr[0]);
+                       if (src_mb) {
+                               found_in_src_queue = 1;
+
+                               mfc_nal_q_handle_stream_copy_timestamp(ctx, src_mb);
+                               src_mb->done_index++;
+                               mfc_debug(4, "[NALQ][BUFCON] batch buf done_index: %d\n", src_mb->done_index);
+
+                               /* last image in a buffer container */
+                               if (src_mb->done_index == src_mb->num_valid_bufs) {
+                                       src_mb = s5p_mfc_find_del_buf(&ctx->buf_queue_lock,
+                                                       &ctx->src_buf_nal_queue, enc_addr[0]);
+                                       for (i = 0; i < raw->num_planes; i++)
+                                               s5p_mfc_bufcon_put_daddr(ctx, src_mb, i);
+                                       vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
+                               }
+                       }
+               }
+       } else {
+               src_mb = s5p_mfc_find_del_buf(&ctx->buf_queue_lock,
+                               &ctx->src_buf_nal_queue, enc_addr[0]);
+               if (src_mb) {
+                       mfc_debug(3, "[NALQ] find src buf in src_queue\n");
+                       found_in_src_queue = 1;
+                       vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
+               } else {
+                       mfc_debug(3, "[NALQ] no src buf in src_queue\n");
+                       ref_mb = s5p_mfc_find_del_buf(&ctx->buf_queue_lock,
+                                       &ctx->ref_buf_queue, enc_addr[0]);
+                       if (ref_mb) {
+                               mfc_debug(3, "[NALQ] find src buf in ref_queue\n");
+                               vb2_buffer_done(&ref_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
+                       } else {
+                               mfc_err_ctx("[NALQ] couldn't find src buffer\n");
+                       }
+               }
+       }
+
+move_buf:
+       /* move enqueued src buffer: src nal queue -> ref queue */
+       if (!found_in_src_queue) {
+               src_mb = s5p_mfc_get_move_buf_used(&ctx->buf_queue_lock,
+                               &ctx->ref_buf_queue, &ctx->src_buf_nal_queue);
+               if (!src_mb)
+                       mfc_err_dev("[NALQ] no src buffers\n");
+
+               mfc_debug(2, "[NALQ] enc src_buf_nal_queue(%d) -> ref_buf_queue(%d)\n",
+                               s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->src_buf_nal_queue),
+                               s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->ref_buf_queue));
+       }
+}
+
+static void mfc_nal_q_handle_stream_output(struct s5p_mfc_ctx *ctx, int slice_type,
+                               unsigned int strm_size, EncoderOutputStr *pOutStr)
+{
+       struct s5p_mfc_buf *dst_mb;
+       unsigned int index;
+
+       if (strm_size == 0) {
+               mfc_debug(3, "[NALQ] no encoded dst (reuse)\n");
+               dst_mb = s5p_mfc_get_move_buf(&ctx->buf_queue_lock,
+                               &ctx->dst_buf_queue, &ctx->dst_buf_nal_queue,
+                               MFC_BUF_RESET_USED, MFC_QUEUE_ADD_TOP);
+               if (!dst_mb) {
+                       mfc_err_dev("[NALQ] no dst buffers\n");
+                       return;
+               }
+
+               mfc_debug(2, "[NALQ] no output, dst_buf_nal_queue(%d) -> dst_buf_queue(%d) index:%d\n",
+                               s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->dst_buf_nal_queue),
+                               s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->dst_buf_queue),
+                               dst_mb->vb.vb2_buf.index);
+               return;
+       } else if (strm_size < 0) {
+               mfc_err_ctx("[NALQ] invalid stream size: %d\n", strm_size);
+               return;
+       }
+
+       /* at least one more dest. buffers exist always  */
+       dst_mb = s5p_mfc_get_del_buf(&ctx->buf_queue_lock, &ctx->dst_buf_nal_queue, MFC_BUF_NO_TOUCH_USED);
+       if (!dst_mb) {
+               mfc_err_dev("[NALQ] no dst buffers\n");
+               return;
+       }
+
+       mfc_debug(2, "[NALQ][BUFINFO] ctx[%d] get dst addr: 0x%08llx\n",
+                       ctx->num, dst_mb->addr[0][0]);
+
+       dst_mb->vb.flags &= ~(V4L2_BUF_FLAG_KEYFRAME |
+                               V4L2_BUF_FLAG_PFRAME |
+                               V4L2_BUF_FLAG_BFRAME);
+
+       switch (slice_type) {
+       case S5P_FIMV_E_SLICE_TYPE_I:
+               dst_mb->vb.flags |= V4L2_BUF_FLAG_KEYFRAME;
+               break;
+       case S5P_FIMV_E_SLICE_TYPE_P:
+               dst_mb->vb.flags |= V4L2_BUF_FLAG_PFRAME;
+               break;
+       case S5P_FIMV_E_SLICE_TYPE_B:
+               dst_mb->vb.flags |= V4L2_BUF_FLAG_BFRAME;
+               break;
+       default:
+               dst_mb->vb.flags |= V4L2_BUF_FLAG_KEYFRAME;
+               break;
+       }
+       mfc_debug(2, "[NALQ][STREAM] Slice type flag: %d\n", dst_mb->vb.flags);
+
+       vb2_set_plane_payload(&dst_mb->vb.vb2_buf, 0, strm_size);
+
+       index = dst_mb->vb.vb2_buf.index;
+       if (call_cop(ctx, get_buf_ctrls_val_nal_q_enc, ctx,
+                               &ctx->dst_ctrls[index], pOutStr) < 0)
+               mfc_err_ctx("[NALQ] failed in get_buf_ctrls_val in nal q\n");
+
+       vb2_buffer_done(&dst_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
+}
+
+static void mfc_nal_q_handle_stream(struct s5p_mfc_ctx *ctx, EncoderOutputStr *pOutStr)
+{
+       struct s5p_mfc_enc *enc = ctx->enc_priv;
+       int slice_type;
+       unsigned int strm_size;
+       unsigned int pic_count;
+
+       mfc_debug_enter();
+
+       slice_type = pOutStr->SliceType;
+       strm_size = pOutStr->StreamSize;
+       pic_count = pOutStr->EncCnt;
+
+       mfc_debug(2, "[NALQ][STREAM] encoded slice type: %d, size: %d, display order: %d\n",
+                       slice_type, strm_size, pic_count);
+
+       /* buffer full handling */
+       if (ctx->state == MFCINST_RUNNING_BUF_FULL)
+               ctx->state = MFCINST_RUNNING;
+
+       /* set encoded frame type */
+       enc->frame_type = slice_type;
+       ctx->sequence++;
+
+       /* handle input buffer */
+       mfc_nal_q_handle_stream_input(ctx, pOutStr);
+
+       /* handle output buffer */
+       mfc_nal_q_handle_stream_output(ctx, slice_type, strm_size, pOutStr);
+
+       mfc_debug_leave();
+
+       return;
+}
+
+static void mfc_nal_q_handle_reuse_buffer(struct s5p_mfc_ctx *ctx, DecoderOutputStr *pOutStr)
+{
+       struct s5p_mfc_dec *dec = ctx->dec_priv;
+       unsigned int prev_flag, released_flag = 0;
+       struct s5p_mfc_buf *dst_mb;
+       dma_addr_t disp_addr;
+       int i;
+
+       /* reuse not used buf: dst_buf_nal_queue -> dst_queue */
+       disp_addr = pOutStr->DisplayAddr[0];
+       if (disp_addr) {
+               mfc_debug(2, "[NALQ][DPB] decoding only but there is disp addr: 0x%llx\n", disp_addr);
+               dst_mb = s5p_mfc_get_move_buf_addr(&ctx->buf_queue_lock,
+                               &ctx->dst_buf_queue, &ctx->dst_buf_nal_queue,
+                               disp_addr);
+               if (dst_mb) {
+                       mfc_debug(2, "[NALQ][DPB] buf[%d] will reused. addr: 0x%08llx\n",
+                                       dst_mb->vb.vb2_buf.index, disp_addr);
+                       dst_mb->used = 0;
+                       clear_bit(dst_mb->vb.vb2_buf.index, &dec->available_dpb);
+               }
+       }
+
+       /* reuse not referenced buf anymore: ref_queue -> dst_queue */
+       prev_flag = dec->dynamic_used;
+       dec->dynamic_used = pOutStr->UsedDpbFlagLower;
+       released_flag = prev_flag & (~dec->dynamic_used);
+
+       if (!released_flag)
+               return;
+
+       for (i = 0; i < MFC_MAX_DPBS; i++)
+               if (released_flag & (1 << i))
+                       if (s5p_mfc_move_reuse_buffer(ctx, i))
+                               released_flag &= ~(1 << i);
+
+       /* Not reused buffer should be released when there is a display frame */
+       dec->dec_only_release_flag |= released_flag;
+       for (i = 0; i < MFC_MAX_DPBS; i++)
+               if (released_flag & (1 << i))
+                       clear_bit(i, &dec->available_dpb);
+}
+
+static void mfc_nal_q_handle_ref_frame(struct s5p_mfc_ctx *ctx, DecoderOutputStr *pOutStr)
+{
+       struct s5p_mfc_dec *dec = ctx->dec_priv;
+       struct s5p_mfc_buf *dst_mb;
+       dma_addr_t dec_addr;
+       int index = 0;
+
+       mfc_debug_enter();
+
+       dec_addr = pOutStr->DecodedAddr[0];
+
+       dst_mb = s5p_mfc_find_move_buf_used(&ctx->buf_queue_lock,
+               &ctx->ref_buf_queue, &ctx->dst_buf_nal_queue, dec_addr);
+       if (dst_mb) {
+               mfc_debug(2, "[NALQ][DPB] Found in dst queue = 0x%08llx, buf = 0x%08llx\n",
+                               dec_addr, dst_mb->addr[0][0]);
+
+               index = dst_mb->vb.vb2_buf.index;
+               if (!((1 << index) & pOutStr->UsedDpbFlagLower))
+                       dec->dynamic_used |= 1 << index;
+       } else {
+               mfc_debug(2, "[NALQ][DPB] Can't find buffer for addr: 0x%08llx\n", dec_addr);
+       }
+
+       mfc_debug_leave();
+}
+
+static void mfc_nal_q_handle_frame_copy_timestamp(struct s5p_mfc_ctx *ctx, DecoderOutputStr *pOutStr)
+{
+       struct s5p_mfc_dec *dec;
+       struct s5p_mfc_dev *dev;
+       struct s5p_mfc_buf *ref_mb, *src_mb;
+       dma_addr_t dec_y_addr;
+
+       mfc_debug_enter();
+
+       if (!ctx) {
+               mfc_err_dev("[TS] no mfc context to run\n");
+               return;
+       }
+
+       dec = ctx->dec_priv;
+       dev = ctx->dev;
+
+       dec_y_addr = pOutStr->DecodedAddr[0];
+
+       /* Get the next source buffer */
+       src_mb = s5p_mfc_get_buf(&ctx->buf_queue_lock, &ctx->src_buf_nal_queue, MFC_BUF_NO_TOUCH_USED);
+       if (!src_mb) {
+               mfc_err_dev("[NALQ] no src buffers\n");
+               return;
+       }
+
+       ref_mb = s5p_mfc_find_buf(&ctx->buf_queue_lock, &ctx->ref_buf_queue, dec_y_addr);
+       if (ref_mb)
+               ref_mb->vb.vb2_buf.timestamp = src_mb->vb.vb2_buf.timestamp;
+
+       mfc_debug_leave();
+}
+
+static void mfc_nal_q_handle_frame_output_move(struct s5p_mfc_ctx *ctx,
+                       dma_addr_t dspl_y_addr, unsigned int released_flag)
+{
+       struct s5p_mfc_dec *dec = ctx->dec_priv;
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_buf *dst_mb;
+       unsigned int index;
+
+       dst_mb = s5p_mfc_find_move_buf(&ctx->buf_queue_lock,
+                       &ctx->dst_buf_queue, &ctx->ref_buf_queue, dspl_y_addr, released_flag);
+       if (dst_mb) {
+               index = dst_mb->vb.vb2_buf.index;
+
+               /* Check if this is the buffer we're looking for */
+               mfc_debug(2, "[NALQ][DPB] Found buf[%d] 0x%08llx, looking for disp addr 0x%08llx\n",
+                               index, dst_mb->addr[0][0], dspl_y_addr);
+
+               if (released_flag & (1 << index)) {
+                       dec->available_dpb &= ~(1 << index);
+                       released_flag &= ~(1 << index);
+                       mfc_debug(2, "[NALQ][DPB] Corrupted frame(%d), it will be re-used(release)\n",
+                                       s5p_mfc_get_warn(s5p_mfc_get_int_err()));
+               } else {
+                       dec->err_reuse_flag |= 1 << index;
+                       mfc_debug(2, "[NALQ][DPB] Corrupted frame(%d), it will be re-used(not released)\n",
+                                       s5p_mfc_get_warn(s5p_mfc_get_int_err()));
+               }
+               dec->dynamic_used |= released_flag;
+       }
+}
+
+static void mfc_nal_q_handle_frame_output_del(struct s5p_mfc_ctx *ctx,
+               DecoderOutputStr *pOutStr, unsigned int err, unsigned int released_flag)
+{
+       struct s5p_mfc_dec *dec = ctx->dec_priv;
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_raw_info *raw = &ctx->raw_buf;
+       struct s5p_mfc_buf *ref_mb;
+       dma_addr_t dspl_y_addr;
+       unsigned int frame_type;
+       unsigned int dst_frame_status;
+       unsigned int is_video_signal_type = 0, is_colour_description = 0;
+       unsigned int is_content_light = 0, is_display_colour = 0;
+       unsigned int disp_err;
+       int i, index;
+
+       if (MFC_FEATURE_SUPPORT(dev, dev->pdata->color_aspect_dec)) {
+               is_video_signal_type = ((pOutStr->VideoSignalType
+                                       >> S5P_FIMV_D_VIDEO_SIGNAL_TYPE_FLAG_SHIFT)
+                                       & S5P_FIMV_D_VIDEO_SIGNAL_TYPE_FLAG_MASK);
+               is_colour_description = ((pOutStr->VideoSignalType
+                                       >> S5P_FIMV_D_COLOUR_DESCRIPTION_FLAG_SHIFT)
+                                       & S5P_FIMV_D_COLOUR_DESCRIPTION_FLAG_MASK);
+       }
+
+       if (MFC_FEATURE_SUPPORT(dev, dev->pdata->static_info_dec)) {
+               is_content_light = ((pOutStr->SeiAvail >> S5P_FIMV_D_SEI_AVAIL_CONTENT_LIGHT_SHIFT)
+                                       & S5P_FIMV_D_SEI_AVAIL_CONTENT_LIGHT_MASK);
+               is_display_colour = ((pOutStr->SeiAvail >> S5P_FIMV_D_SEI_AVAIL_MASTERING_DISPLAY_SHIFT)
+                                       & S5P_FIMV_D_SEI_AVAIL_MASTERING_DISPLAY_MASK);
+       }
+
+       if (dec->immediate_display == 1) {
+               dspl_y_addr = pOutStr->DecodedAddr[0];
+               frame_type = pOutStr->DecodedFrameType & S5P_FIMV_DECODED_FRAME_MASK;
+       } else {
+               dspl_y_addr = pOutStr->DisplayAddr[0];
+               frame_type = pOutStr->DisplayFrameType & S5P_FIMV_DISPLAY_FRAME_MASK;
+       }
+
+       ref_mb = s5p_mfc_find_del_buf(&ctx->buf_queue_lock, &ctx->ref_buf_queue, dspl_y_addr);
+       if (ref_mb) {
+               index = ref_mb->vb.vb2_buf.index;
+
+               /* Check if this is the buffer we're looking for */
+               mfc_debug(2, "[NALQ][BUFINFO][DPB] ctx[%d] get dst index: %d, addr[0]: 0x%08llx\n",
+                               ctx->num, index, ref_mb->addr[0][0]);
+
+               ref_mb->vb.sequence = ctx->sequence;
+
+               /* Set reserved2 bits in order to inform SEI information */
+               ref_mb->vb.reserved2 = 0;
+
+               if (is_content_light) {
+                       ref_mb->vb.reserved2 |= (1 << 0);
+                       mfc_debug(2, "[NALQ][HDR] content light level parsed\n");
+               }
+               if (is_display_colour) {
+                       ref_mb->vb.reserved2 |= (1 << 1);
+                       mfc_debug(2, "[NALQ][HDR] mastering display colour parsed\n");
+               }
+               if (is_video_signal_type) {
+                       ref_mb->vb.reserved2 |= (1 << 4);
+                       mfc_debug(2, "[NALQ][HDR] video signal type parsed\n");
+                       if (is_colour_description) {
+                               ref_mb->vb.reserved2 |= (1 << 2);
+                               mfc_debug(2, "[NALQ][HDR] matrix coefficients parsed\n");
+                               ref_mb->vb.reserved2 |= (1 << 3);
+                               mfc_debug(2, "[NALQ][HDR] colour description parsed\n");
+                       }
+               }
+
+               if (IS_VP9_DEC(ctx) && MFC_FEATURE_SUPPORT(dev, dev->pdata->color_aspect_dec)) {
+                       if (dec->color_space != S5P_FIMV_D_COLOR_UNKNOWN) {
+                               ref_mb->vb.reserved2 |= (1 << 3);
+                               mfc_debug(2, "[NALQ][HDR] color space parsed\n");
+                       }
+                       ref_mb->vb.reserved2 |= (1 << 4);
+                       mfc_debug(2, "[NALQ][HDR] color range parsed\n");
+               }
+
+               for (i = 0; i < raw->num_planes; i++)
+                       vb2_set_plane_payload(&ref_mb->vb.vb2_buf, i,
+                                       raw->plane_size[i]);
+
+               clear_bit(index, &dec->available_dpb);
+
+               ref_mb->vb.flags &= ~(V4L2_BUF_FLAG_KEYFRAME |
+                                       V4L2_BUF_FLAG_PFRAME |
+                                       V4L2_BUF_FLAG_BFRAME |
+                                       V4L2_BUF_FLAG_ERROR);
+
+               switch (frame_type) {
+                       case S5P_FIMV_DISPLAY_FRAME_I:
+                               ref_mb->vb.flags |= V4L2_BUF_FLAG_KEYFRAME;
+                               break;
+                       case S5P_FIMV_DISPLAY_FRAME_P:
+                               ref_mb->vb.flags |= V4L2_BUF_FLAG_PFRAME;
+                               break;
+                       case S5P_FIMV_DISPLAY_FRAME_B:
+                               ref_mb->vb.flags |= V4L2_BUF_FLAG_BFRAME;
+                               break;
+                       default:
+                               break;
+               }
+
+               disp_err = s5p_mfc_get_warn(pOutStr->ErrorCode);
+               if (disp_err) {
+                       mfc_err_ctx("[NALQ] Warning for displayed frame: %d\n",
+                                       disp_err);
+                       ref_mb->vb.flags |= V4L2_BUF_FLAG_ERROR;
+               }
+
+               if (call_cop(ctx, get_buf_ctrls_val_nal_q_dec, ctx,
+                                       &ctx->dst_ctrls[index], pOutStr) < 0)
+                       mfc_err_ctx("[NALQ] failed in get_buf_ctrls_val\n");
+
+               s5p_mfc_handle_released_info(ctx, released_flag, index);
+
+               if (dec->immediate_display == 1) {
+                       dst_frame_status = pOutStr->DecodedStatus
+                               & S5P_FIMV_DEC_STATUS_DECODED_STATUS_MASK;
+
+                       call_cop(ctx, get_buf_update_val, ctx,
+                                       &ctx->dst_ctrls[index],
+                                       V4L2_CID_MPEG_MFC51_VIDEO_DISPLAY_STATUS,
+                                       dst_frame_status);
+
+                       call_cop(ctx, get_buf_update_val, ctx,
+                                       &ctx->dst_ctrls[index],
+                                       V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG,
+                                       dec->stored_tag);
+
+                       dec->immediate_display = 0;
+               }
+
+               s5p_mfc_qos_update_last_framerate(ctx, ref_mb->vb.vb2_buf.timestamp);
+               vb2_buffer_done(&ref_mb->vb.vb2_buf, disp_err ?
+                               VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
+       }
+}
+
+static void mfc_nal_q_handle_frame_new(struct s5p_mfc_ctx *ctx, unsigned int err,
+                                       DecoderOutputStr *pOutStr)
+{
+       struct s5p_mfc_dec *dec = ctx->dec_priv;
+       dma_addr_t dspl_y_addr;
+       unsigned int frame_type;
+       unsigned int prev_flag, released_flag = 0;
+       unsigned int disp_err;
+
+       mfc_debug_enter();
+
+       frame_type = pOutStr->DisplayFrameType & S5P_FIMV_DISPLAY_FRAME_MASK;
+       disp_err = s5p_mfc_get_warn(pOutStr->ErrorCode);
+
+       ctx->sequence++;
+
+       dspl_y_addr = pOutStr->DisplayAddr[0];
+
+       if (dec->immediate_display == 1) {
+               dspl_y_addr = pOutStr->DecodedAddr[0];
+               frame_type = pOutStr->DecodedFrameType & S5P_FIMV_DECODED_FRAME_MASK;
+       }
+
+       mfc_debug(2, "[NALQ][FRAME] frame type: %d\n", frame_type);
+
+       /* If frame is same as previous then skip and do not dequeue */
+       if (frame_type == S5P_FIMV_DISPLAY_FRAME_NOT_CODED) {
+               if (!CODEC_NOT_CODED(ctx))
+                       return;
+       }
+
+       prev_flag = dec->dynamic_used;
+       dec->dynamic_used = pOutStr->UsedDpbFlagLower;
+       released_flag = prev_flag & (~dec->dynamic_used);
+
+       mfc_debug(2, "[NALQ][DPB] Used flag: old = %08x, new = %08x, Released buffer = %08x\n",
+                       prev_flag, dec->dynamic_used, released_flag);
+
+       if ((IS_VC1_RCV_DEC(ctx) &&
+                       (disp_err == S5P_FIMV_ERR_SYNC_POINT_NOT_RECEIVED)) ||
+                       (disp_err == S5P_FIMV_ERR_BROKEN_LINK))
+               mfc_nal_q_handle_frame_output_move(ctx, dspl_y_addr, released_flag);
+       else
+               mfc_nal_q_handle_frame_output_del(ctx, pOutStr, err, released_flag);
+
+       mfc_debug_leave();
+}
+
+static void mfc_nal_q_handle_frame_input(struct s5p_mfc_ctx *ctx, unsigned int err,
+                                       DecoderOutputStr *pOutStr)
+{
+       struct s5p_mfc_dec *dec = ctx->dec_priv;
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_buf *src_mb;
+       unsigned int index;
+       int deleted = 0;
+       unsigned long consumed;
+
+       /* If there is consumed byte, it is abnormal status,
+        * We have to return remained stream buffer
+        */
+       if (dec->consumed) {
+               mfc_err_dev("[NALQ] previous buffer was not fully consumed\n");
+               src_mb = s5p_mfc_get_del_buf(&ctx->buf_queue_lock, &ctx->src_buf_nal_queue,
+                               MFC_BUF_NO_TOUCH_USED);
+               if (src_mb)
+                       vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
+       }
+
+       /* Check multi-frame */
+       consumed = pOutStr->DecodedNalSize;
+       src_mb = s5p_mfc_get_del_if_consumed(ctx, &ctx->src_buf_nal_queue,
+                       consumed, STUFF_BYTE, err, &deleted);
+       if (!src_mb) {
+               mfc_err_dev("[NALQ] no src buffers\n");
+               return;
+       }
+
+       index = src_mb->vb.vb2_buf.index;
+       mfc_debug(2, "[NALQ][BUFINFO] ctx[%d] get src index: %d, addr: 0x%08llx\n",
+                       ctx->num, index, src_mb->addr[0][0]);
+
+       if (!deleted) {
+               /* Run MFC again on the same buffer */
+               mfc_debug(2, "[NALQ][MULTIFRAME] Running again the same buffer\n");
+
+               if (CODEC_MULTIFRAME(ctx))
+                       dec->y_addr_for_pb = (dma_addr_t)pOutStr->DecodedAddr[0];
+
+               dec->consumed = consumed;
+               dec->remained_size = src_mb->vb.vb2_buf.planes[0].bytesused
+                       - dec->consumed;
+               dec->has_multiframe = 1;
+               dev->nal_q_handle->nal_q_exception = 1;
+
+               MFC_TRACE_CTX("** consumed:%ld, remained:%ld, addr:0x%08llx\n",
+                       dec->consumed, dec->remained_size, dec->y_addr_for_pb);
+               /* Do not move src buffer to done_list */
+               return;
+       }
+
+       if (call_cop(ctx, get_buf_ctrls_val_nal_q_dec, ctx,
+                               &ctx->src_ctrls[index], pOutStr) < 0)
+               mfc_err_ctx("[NALQ] failed in get_buf_ctrls_val\n");
+
+       dec->consumed = 0;
+       dec->remained_size = 0;
+
+       vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
+}
+
+void mfc_nal_q_handle_frame(struct s5p_mfc_ctx *ctx, DecoderOutputStr *pOutStr)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_dec *dec = ctx->dec_priv;
+       unsigned int dst_frame_status, sei_avail_status, need_empty_dpb;
+       unsigned int res_change, need_dpb_change, need_scratch_change;
+       unsigned int is_interlaced, err;
+
+       mfc_debug_enter();
+
+       dst_frame_status = pOutStr->DisplayStatus
+                               & S5P_FIMV_DISP_STATUS_DISPLAY_STATUS_MASK;
+       need_empty_dpb = (pOutStr->DisplayStatus
+                               >> S5P_FIMV_DISP_STATUS_NEED_EMPTY_DPB_SHIFT)
+                               & S5P_FIMV_DISP_STATUS_NEED_EMPTY_DPB_MASK;
+       res_change = (pOutStr->DisplayStatus
+                               >> S5P_FIMV_DISP_STATUS_RES_CHANGE_SHIFT)
+                               & S5P_FIMV_DISP_STATUS_RES_CHANGE_MASK;
+       need_dpb_change = (pOutStr->DisplayStatus
+                               >> S5P_FIMV_DISP_STATUS_NEED_DPB_CHANGE_SHIFT)
+                               & S5P_FIMV_DISP_STATUS_NEED_DPB_CHANGE_MASK;
+       need_scratch_change = (pOutStr->DisplayStatus
+                                >> S5P_FIMV_DISP_STATUS_NEED_SCRATCH_CHANGE_SHIFT)
+                               & S5P_FIMV_DISP_STATUS_NEED_SCRATCH_CHANGE_MASK;
+       is_interlaced = (pOutStr->DisplayStatus
+                               >> S5P_FIMV_DISP_STATUS_INTERLACE_SHIFT)
+                               & S5P_FIMV_DISP_STATUS_INTERLACE_MASK;
+       sei_avail_status = pOutStr->SeiAvail;
+       err = pOutStr->ErrorCode;
+
+       if (dec->immediate_display == 1)
+               dst_frame_status = pOutStr->DecodedStatus
+                               & S5P_FIMV_DEC_STATUS_DECODED_STATUS_MASK;
+
+       mfc_debug(2, "[NALQ][FRAME] frame status: %d\n", dst_frame_status);
+       mfc_debug(2, "[NALQ][FRAME] display status: %d, type: %d, yaddr: %#x\n",
+                       pOutStr->DisplayStatus & S5P_FIMV_DISP_STATUS_DISPLAY_STATUS_MASK,
+                       pOutStr->DisplayFrameType & S5P_FIMV_DISPLAY_FRAME_MASK,
+                       pOutStr->DisplayAddr[0]);
+       mfc_debug(2, "[NALQ][FRAME] decoded status: %d, type: %d, yaddr: %#x\n",
+                       pOutStr->DecodedStatus & S5P_FIMV_DEC_STATUS_DECODED_STATUS_MASK,
+                       pOutStr->DecodedFrameType & S5P_FIMV_DECODED_FRAME_MASK,
+                       pOutStr->DecodedAddr[0]);
+       mfc_debug(4, "[NALQ][HDR] SEI available status: %x\n", sei_avail_status);
+       mfc_debug(2, "[NALQ][DPB] Used flag: old = %08x, new = %08x\n",
+                       dec->dynamic_used, pOutStr->UsedDpbFlagLower);
+
+       if (ctx->state == MFCINST_RES_CHANGE_INIT) {
+               mfc_debug(2, "[NALQ][DRC] return until NAL-Q stopped in try_run\n");
+               goto leave_handle_frame;
+       }
+       if (res_change) {
+               mfc_debug(2, "[NALQ][DRC] Resolution change set to %d\n", res_change);
+               s5p_mfc_change_state(ctx, MFCINST_RES_CHANGE_INIT);
+               ctx->wait_state = WAIT_DECODING;
+               dev->nal_q_handle->nal_q_exception = 1;
+               mfc_info_ctx("[NALQ][DRC] nal_q_exception is set (res change)\n");
+               goto leave_handle_frame;
+       }
+       if (need_empty_dpb) {
+               mfc_debug(2, "[NALQ][MULTIFRAME] There is multi-frame. consumed:%ld\n", dec->consumed);
+               dec->has_multiframe = 1;
+               dev->nal_q_handle->nal_q_exception = 1;
+               mfc_info_ctx("[NALQ][MULTIFRAME] nal_q_exception is set\n");
+               goto leave_handle_frame;
+       }
+       if (need_dpb_change || need_scratch_change) {
+               mfc_debug(2, "[NALQ][DRC] Interframe resolution change is not supported\n");
+               dev->nal_q_handle->nal_q_exception = 1;
+               mfc_info_ctx("[NALQ][DRC] nal_q_exception is set (interframe res change)\n");
+               goto leave_handle_frame;
+       }
+       if (is_interlaced) {
+               mfc_debug(2, "[NALQ][INTERLACE] Progressive -> Interlaced\n");
+               dec->is_interlaced = is_interlaced;
+               dev->nal_q_handle->nal_q_exception = 1;
+               mfc_info_ctx("[NALQ][INTERLACE] nal_q_exception is set\n");
+               goto leave_handle_frame;
+       }
+
+       if (s5p_mfc_is_queue_count_same(&ctx->buf_queue_lock, &ctx->src_buf_nal_queue, 0) &&
+               s5p_mfc_is_queue_count_same(&ctx->buf_queue_lock, &ctx->dst_buf_nal_queue, 0)) {
+               mfc_err_dev("[NALQ] Queue count is zero for src/dst\n");
+               goto leave_handle_frame;
+       }
+
+       switch (dst_frame_status) {
+       case S5P_FIMV_DEC_STATUS_DECODING_DISPLAY:
+               mfc_nal_q_handle_ref_frame(ctx, pOutStr);
+               mfc_nal_q_handle_frame_copy_timestamp(ctx, pOutStr);
+               break;
+       case S5P_FIMV_DEC_STATUS_DECODING_ONLY:
+               mfc_nal_q_handle_ref_frame(ctx, pOutStr);
+               mfc_nal_q_handle_reuse_buffer(ctx, pOutStr);
+               break;
+       default:
+               break;
+       }
+
+       /* A frame has been decoded and is in the buffer  */
+       if (s5p_mfc_dec_status_display(dst_frame_status))
+               mfc_nal_q_handle_frame_new(ctx, err, pOutStr);
+       else
+               mfc_debug(2, "[NALQ] No display frame\n");
+
+       /* Mark source buffer as complete */
+       if (dst_frame_status != S5P_FIMV_DEC_STATUS_DISPLAY_ONLY)
+               mfc_nal_q_handle_frame_input(ctx, err, pOutStr);
+       else
+               mfc_debug(2, "[NALQ][DPB] can't support display only in NAL-Q, is_dpb_full: %d\n",
+                               dec->is_dpb_full);
+
+leave_handle_frame:
+       mfc_debug_leave();
+}
+
+int mfc_nal_q_handle_error(struct s5p_mfc_ctx *ctx, EncoderOutputStr *pOutStr, int err)
+{
+       struct s5p_mfc_dev *dev;
+       struct s5p_mfc_dec *dec;
+       struct s5p_mfc_enc *enc;
+       struct s5p_mfc_buf *src_mb;
+       int stop_nal_q = 1;
+
+       mfc_debug_enter();
+
+       if (!ctx) {
+               mfc_err_dev("[NALQ] no mfc context to run\n");
+               goto end;
+       }
+
+       dev = ctx->dev;
+       if (!dev) {
+               mfc_err_dev("[NALQ] no mfc device to run\n");
+               goto end;
+       }
+
+       mfc_err_ctx("[NALQ] Interrupt Error: %d\n", pOutStr->ErrorCode);
+
+       dev->nal_q_handle->nal_q_exception = 1;
+       mfc_info_ctx("[NALQ] nal_q_exception is set (error)\n");
+
+       if (ctx->type == MFCINST_DECODER) {
+               dec = ctx->dec_priv;
+               if (!dec) {
+                       mfc_err_dev("[NALQ] no mfc decoder to run\n");
+                       goto end;
+               }
+               src_mb = s5p_mfc_get_del_buf(&ctx->buf_queue_lock,
+                               &ctx->src_buf_nal_queue, MFC_BUF_NO_TOUCH_USED);
+
+               if (!src_mb) {
+                       mfc_err_dev("[NALQ] no src buffers\n");
+               } else {
+                       dec->consumed = 0;
+                       vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_ERROR);
+               }
+       } else if (ctx->type == MFCINST_ENCODER) {
+               enc = ctx->enc_priv;
+               if (!enc) {
+                       mfc_err_dev("[NALQ] no mfc encoder to run\n");
+                       goto end;
+               }
+
+               /*
+                * If the buffer full error occurs in NAL-Q mode,
+                * one input buffer is returned and the NAL-Q mode continues.
+                */
+               if (err == S5P_FIMV_ERR_BUFFER_FULL) {
+                       src_mb = s5p_mfc_get_del_buf(&ctx->buf_queue_lock,
+                                       &ctx->src_buf_nal_queue, MFC_BUF_NO_TOUCH_USED);
+
+                       if (!src_mb)
+                               mfc_err_dev("[NALQ] no src buffers\n");
+                       else
+                               vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_ERROR);
+
+                       dev->nal_q_handle->nal_q_exception = 0;
+                       stop_nal_q = 0;
+               }
+       }
+
+end:
+       mfc_debug_leave();
+
+       return stop_nal_q;
+}
+
+int s5p_mfc_nal_q_handle_out_buf(struct s5p_mfc_dev *dev, EncoderOutputStr *pOutStr)
+{
+       struct s5p_mfc_ctx *ctx;
+       struct s5p_mfc_enc *enc;
+       struct s5p_mfc_dec *dec;
+       int ctx_num;
+
+       mfc_debug_enter();
+
+       if (!dev) {
+               mfc_err_dev("[NALQ] no mfc device to run\n");
+               return -EINVAL;
+       }
+
+       ctx_num = dev->nal_q_handle->nal_q_out_handle->nal_q_ctx;
+       if (ctx_num < 0) {
+               mfc_err_dev("[NALQ] Can't find ctx in nal q\n");
+               return -EINVAL;
+       }
+
+       ctx = dev->ctx[ctx_num];
+       if (!ctx) {
+               mfc_err_dev("[NALQ] no mfc context to run\n");
+               return -EINVAL;
+       }
+
+       mfc_debug(2, "[NALQ] Int ctx is %d(%s)\n", ctx_num,
+                        ctx->type == MFCINST_ENCODER ? "enc" : "dec");
+
+       if (s5p_mfc_get_err(pOutStr->ErrorCode) &&
+                       (s5p_mfc_get_err(pOutStr->ErrorCode) < S5P_FIMV_ERR_FRAME_CONCEAL)) {
+               if (mfc_nal_q_handle_error(ctx, pOutStr, s5p_mfc_get_err(pOutStr->ErrorCode)))
+                       return 0;
+       }
+
+       if (ctx->type == MFCINST_ENCODER) {
+               enc = ctx->enc_priv;
+               if (!enc) {
+                       mfc_err_dev("[NALQ] no mfc encoder to run\n");
+                       return -EINVAL;
+               }
+               mfc_nal_q_handle_stream(ctx, pOutStr);
+       } else if (ctx->type == MFCINST_DECODER) {
+               dec = ctx->dec_priv;
+               if (!dec) {
+                       mfc_err_dev("[NALQ] no mfc decoder to run\n");
+                       return -EINVAL;
+               }
+               mfc_nal_q_handle_frame(ctx, (DecoderOutputStr *)pOutStr);
+       }
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+/*
+ * This function should be called in NAL_Q_STATE_STARTED state.
+ */
+int s5p_mfc_nal_q_enqueue_in_buf(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx,
+       nal_queue_in_handle *nal_q_in_handle)
+{
+       unsigned long flags;
+       unsigned int input_count = 0;
+       unsigned int input_exe_count = 0;
+       int input_diff = 0;
+       unsigned int index = 0;
+       EncoderInputStr *pStr = NULL;
+       int ret = 0;
+
+       mfc_debug_enter();
+
+       if (!nal_q_in_handle) {
+               mfc_err_dev("[NALQ] There is no nal_q_handle\n");
+               return -EINVAL;
+       }
+
+       if (nal_q_in_handle->nal_q_handle->nal_q_state != NAL_Q_STATE_STARTED) {
+               mfc_err_dev("[NALQ] State is wrong, state: %d\n",
+                               nal_q_in_handle->nal_q_handle->nal_q_state);
+               return -EINVAL;
+       }
+
+       spin_lock_irqsave(&nal_q_in_handle->nal_q_handle->lock, flags);
+
+       input_count = s5p_mfc_get_nal_q_input_count();
+       input_exe_count = s5p_mfc_get_nal_q_input_exe_count();
+       input_diff = input_count - input_exe_count;
+
+       /*
+        * meaning of the variable input_diff
+        * 0:                           number of available slots = NAL_Q_IN_QUEUE_SIZE
+        * 1:                           number of available slots = NAL_Q_IN_QUEUE_SIZE - 1
+        * ...
+        * NAL_Q_IN_QUEUE_SIZE-1:       number of available slots = 1
+        * NAL_Q_IN_QUEUE_SIZE:         number of available slots = 0
+        */
+
+       mfc_debug(2, "[NALQ] input_diff = %d(in: %d, exe: %d)\n",
+                       input_diff, input_count, input_exe_count);
+
+       if ((input_diff < 0) || (input_diff >= NAL_Q_IN_QUEUE_SIZE)) {
+               mfc_err_dev("[NALQ] No available input slot(%d)\n", input_diff);
+               spin_unlock_irqrestore(&nal_q_in_handle->nal_q_handle->lock, flags);
+               return -EINVAL;
+       }
+
+       index = input_count % NAL_Q_IN_QUEUE_SIZE;
+       pStr = &(nal_q_in_handle->nal_q_in_addr->entry[index].enc);
+
+       memset(pStr, 0, NAL_Q_IN_ENTRY_SIZE);
+
+       if (ctx->type == MFCINST_ENCODER)
+               ret = mfc_nal_q_run_in_buf_enc(ctx, pStr);
+       else if (ctx->type == MFCINST_DECODER)
+               ret = mfc_nal_q_run_in_buf_dec(ctx, (DecoderInputStr *)pStr);
+
+       if (ret != 0) {
+               mfc_debug(2, "[NALQ] Failed to set input queue\n");
+               spin_unlock_irqrestore(&nal_q_in_handle->nal_q_handle->lock, flags);
+               return ret;
+       }
+
+       if (nal_q_dump == 1) {
+               mfc_err_dev("[NAL-Q][DUMP][%s INPUT][c: %d] diff: %d, count: %d, exe: %d\n",
+                               ctx->type == MFCINST_ENCODER ? "ENC" : "DEC", dev->curr_ctx,
+                               input_diff, input_count, input_exe_count);
+               print_hex_dump(KERN_ERR, "", DUMP_PREFIX_ADDRESS, 32, 4, (int *)pStr, 256, false);
+               printk("...\n");
+       }
+       input_count++;
+
+       s5p_mfc_update_nal_queue_input_count(dev, input_count);
+
+       if (input_diff == 0)
+               s5p_mfc_watchdog_start_tick(dev);
+
+       spin_unlock_irqrestore(&nal_q_in_handle->nal_q_handle->lock, flags);
+
+       MFC_TRACE_CTX("NAL %s in: diff %d count %d exe %d\n",
+                       ctx->type == MFCINST_ENCODER ? "ENC" : "DEC",
+                       input_diff, input_count, input_exe_count);
+
+       mfc_debug_leave();
+
+       return ret;
+}
+
+/*
+ * This function should be called in NAL_Q_STATE_STARTED state.
+ */
+EncoderOutputStr *s5p_mfc_nal_q_dequeue_out_buf(struct s5p_mfc_dev *dev,
+       nal_queue_out_handle *nal_q_out_handle, unsigned int *reason)
+{
+       struct s5p_mfc_ctx *ctx;
+       unsigned long flags;
+       unsigned int output_count = 0;
+       unsigned int output_exe_count = 0;
+       int output_diff = 0;
+       unsigned int index = 0;
+       EncoderOutputStr *pStr = NULL;
+
+       int input_diff = 0;
+
+       mfc_debug_enter();
+
+       if (!nal_q_out_handle || !nal_q_out_handle->nal_q_out_addr) {
+               mfc_err_dev("[NALQ] There is no handle\n");
+               return pStr;
+       }
+
+       spin_lock_irqsave(&nal_q_out_handle->nal_q_handle->lock, flags);
+
+       output_count = s5p_mfc_get_nal_q_output_count();
+       output_exe_count = nal_q_out_handle->out_exe_count;
+       output_diff = output_count - output_exe_count;
+
+       /*
+        * meaning of the variable output_diff
+        * 0:                           number of output slots = 0
+        * 1:                           number of output slots = 1
+        * ...
+        * NAL_Q_OUT_QUEUE_SIZE-1:      number of output slots = NAL_Q_OUT_QUEUE_SIZE - 1
+        * NAL_Q_OUT_QUEUE_SIZE:        number of output slots = NAL_Q_OUT_QUEUE_SIZE
+        */
+
+       mfc_debug(2, "[NALQ] output_diff = %d(out: %d, exe: %d)\n",
+                       output_diff, output_count, output_exe_count);
+       if ((output_diff <= 0) || (output_diff > NAL_Q_OUT_QUEUE_SIZE)) {
+               spin_unlock_irqrestore(&nal_q_out_handle->nal_q_handle->lock, flags);
+               mfc_debug(2, "[NALQ] No available output slot(%d)\n", output_diff);
+               return pStr;
+       }
+
+       index = output_exe_count % NAL_Q_OUT_QUEUE_SIZE;
+       pStr = &(nal_q_out_handle->nal_q_out_addr->entry[index].enc);
+
+       nal_q_out_handle->nal_q_ctx = mfc_nal_q_find_ctx(dev, pStr);
+       if (nal_q_out_handle->nal_q_ctx < 0) {
+               mfc_err_dev("[NALQ] Can't find ctx in nal q\n");
+               pStr = NULL;
+               return pStr;
+       }
+
+       ctx = dev->ctx[nal_q_out_handle->nal_q_ctx];
+       if (nal_q_dump == 1) {
+               mfc_err_dev("[NALQ][DUMP][%s OUTPUT][c: %d] diff: %d, count: %d, exe: %d\n",
+                               ctx->type == MFCINST_ENCODER ? "ENC" : "DEC",
+                               nal_q_out_handle->nal_q_ctx,
+                               output_diff, output_count, output_exe_count);
+               print_hex_dump(KERN_ERR, "", DUMP_PREFIX_ADDRESS, 32, 4, (int *)pStr, 256, false);
+               printk("...\n");
+       }
+       nal_q_out_handle->out_exe_count++;
+
+       if (pStr->ErrorCode) {
+               *reason = S5P_FIMV_R2H_CMD_ERR_RET;
+               mfc_err_dev("[NALQ] Error : %d\n", pStr->ErrorCode);
+       }
+
+       input_diff = s5p_mfc_get_nal_q_input_count() - s5p_mfc_get_nal_q_input_exe_count();
+       if (input_diff == 0) {
+               s5p_mfc_watchdog_stop_tick(dev);
+       } else if (input_diff > 0) {
+               s5p_mfc_watchdog_reset_tick(dev);
+       }
+
+       spin_unlock_irqrestore(&nal_q_out_handle->nal_q_handle->lock, flags);
+
+       MFC_TRACE_CTX("NAL %s out: diff %d count %d exe %d\n",
+                       ctx->type == MFCINST_ENCODER ? "ENC" : "DEC",
+                       output_diff, output_count, output_exe_count);
+
+       mfc_debug_leave();
+
+       return pStr;
+}
+
+#if 0
+/* not used function - only for reference sfr <-> structure */
+void s5p_mfc_nal_q_fill_DecoderInputStr(struct s5p_mfc_dev *dev, DecoderInputStr *pStr)
+{
+       pStr->StartCode                 = 0xAAAAAAAA; // Decoder input start
+//     pStr->CommandId                 = MFC_READL(S5P_FIMV_HOST2RISC_CMD);            // 0x1100
+       pStr->InstanceId                = MFC_READL(S5P_FIMV_INSTANCE_ID);              // 0xF008
+       pStr->PictureTag                = MFC_READL(S5P_FIMV_D_PICTURE_TAG);            // 0xF5C8
+       pStr->CpbBufferAddr             = MFC_READL(S5P_FIMV_D_CPB_BUFFER_ADDR);        // 0xF5B0
+       pStr->CpbBufferSize             = MFC_READL(S5P_FIMV_D_CPB_BUFFER_SIZE);        // 0xF5B4
+       pStr->CpbBufferOffset           = MFC_READL(S5P_FIMV_D_CPB_BUFFER_OFFSET);      // 0xF5C0
+       pStr->StreamDataSize            = MFC_READL(S5P_FIMV_D_STREAM_DATA_SIZE);       // 0xF5D0
+       pStr->AvailableDpbFlagUpper     = MFC_READL(S5P_FIMV_D_AVAILABLE_DPB_FLAG_UPPER);// 0xF5B8
+       pStr->AvailableDpbFlagLower     = MFC_READL(S5P_FIMV_D_AVAILABLE_DPB_FLAG_LOWER);// 0xF5BC
+       pStr->DynamicDpbFlagUpper       = MFC_READL(S5P_FIMV_D_DYNAMIC_DPB_FLAG_UPPER); // 0xF5D4
+       pStr->DynamicDpbFlagLower       = MFC_READL(S5P_FIMV_D_DYNAMIC_DPB_FLAG_LOWER); // 0xF5D8
+       pStr->FirstPlaneDpb             = MFC_READL(S5P_FIMV_D_FIRST_PLANE_DPB0);       // 0xF160+(index*4)
+       pStr->SecondPlaneDpb            = MFC_READL(S5P_FIMV_D_SECOND_PLANE_DPB0);      // 0xF260+(index*4)
+       pStr->ThirdPlaneDpb             = MFC_READL(S5P_FIMV_D_THIRD_PLANE_DPB0);       // 0xF360+(index*4)
+       pStr->FirstPlaneDpbSize         = MFC_READL(S5P_FIMV_D_FIRST_PLANE_DPB_SIZE);   // 0xF144
+       pStr->SecondPlaneDpbSize        = MFC_READL(S5P_FIMV_D_SECOND_PLANE_DPB_SIZE);  // 0xF148
+       pStr->ThirdPlaneDpbSize         = MFC_READL(S5P_FIMV_D_THIRD_PLANE_DPB_SIZE);   // 0xF14C
+       pStr->NalStartOptions           = MFC_READL(0xF5AC);// S5P_FIMV_D_NAL_START_OPTIONS 0xF5AC
+       pStr->FirstPlaneStrideSize      = MFC_READL(S5P_FIMV_D_FIRST_PLANE_DPB_STRIDE_SIZE);// 0xF138
+       pStr->SecondPlaneStrideSize     = MFC_READL(S5P_FIMV_D_SECOND_PLANE_DPB_STRIDE_SIZE);// 0xF13C
+       pStr->ThirdPlaneStrideSize      = MFC_READL(S5P_FIMV_D_THIRD_PLANE_DPB_STRIDE_SIZE);// 0xF140
+       pStr->FirstPlane2BitDpbSize     = MFC_READL(S5P_FIMV_D_FIRST_PLANE_2BIT_DPB_SIZE);// 0xF578
+       pStr->SecondPlane2BitDpbSize    = MFC_READL(S5P_FIMV_D_SECOND_PLANE_2BIT_DPB_SIZE);// 0xF57C
+       pStr->FirstPlane2BitStrideSize  = MFC_READL(S5P_FIMV_D_FIRST_PLANE_2BIT_DPB_STRIDE_SIZE);// 0xF580
+       pStr->SecondPlane2BitStrideSize = MFC_READL(S5P_FIMV_D_SECOND_PLANE_2BIT_DPB_STRIDE_SIZE);// 0xF584
+       pStr->ScratchBufAddr            = MFC_READL(S5P_FIMV_D_SCRATCH_BUFFER_ADDR);    // 0xF560
+       pStr->ScratchBufSize            = MFC_READL(S5P_FIMV_D_SCRATCH_BUFFER_SIZE);    // 0xF564
+}
+
+void s5p_mfc_nal_q_flush_DecoderOutputStr(struct s5p_mfc_dev *dev, DecoderOutputStr *pStr)
+{
+       //pStr->StartCode; // 0xAAAAAAAA; // Decoder output start
+//     MFC_WRITEL(pStr->CommandId, S5P_FIMV_RISC2HOST_CMD);                            // 0x1104
+       MFC_WRITEL(pStr->InstanceId, S5P_FIMV_RET_INSTANCE_ID);                         // 0xF070
+       MFC_WRITEL(pStr->ErrorCode, S5P_FIMV_ERROR_CODE);                               // 0xF074
+       MFC_WRITEL(pStr->PictureTagTop, S5P_FIMV_D_RET_PICTURE_TAG_TOP);                // 0xF674
+       MFC_WRITEL(pStr->PictureTimeTop, S5P_FIMV_D_RET_PICTURE_TIME_TOP);              // 0xF67C
+       MFC_WRITEL(pStr->DisplayFrameWidth, S5P_FIMV_D_DISPLAY_FRAME_WIDTH);            // 0xF600
+       MFC_WRITEL(pStr->DisplayFrameHeight, S5P_FIMV_D_DISPLAY_FRAME_HEIGHT);          // 0xF604
+       MFC_WRITEL(pStr->DisplayStatus, S5P_FIMV_D_DISPLAY_STATUS);                     // 0xF608
+       MFC_WRITEL(pStr->DisplayFirstPlaneAddr, S5P_FIMV_D_DISPLAY_FIRST_PLANE_ADDR);   // 0xF60C
+       MFC_WRITEL(pStr->DisplaySecondPlaneAddr, S5P_FIMV_D_DISPLAY_SECOND_PLANE_ADDR); // 0xF610
+       MFC_WRITEL(pStr->DisplayThirdPlaneAddr,S5P_FIMV_D_DISPLAY_THIRD_PLANE_ADDR);    // 0xF614
+       MFC_WRITEL(pStr->DisplayFrameType, S5P_FIMV_D_DISPLAY_FRAME_TYPE);              // 0xF618
+       MFC_WRITEL(pStr->DisplayCropInfo1, S5P_FIMV_D_DISPLAY_CROP_INFO1);              // 0xF61C
+       MFC_WRITEL(pStr->DisplayCropInfo2, S5P_FIMV_D_DISPLAY_CROP_INFO2);              // 0xF620
+       MFC_WRITEL(pStr->DisplayPictureProfile, S5P_FIMV_D_DISPLAY_PICTURE_PROFILE);    // 0xF624
+       MFC_WRITEL(pStr->DisplayAspectRatio, S5P_FIMV_D_DISPLAY_ASPECT_RATIO);          // 0xF634
+       MFC_WRITEL(pStr->DisplayExtendedAr, S5P_FIMV_D_DISPLAY_EXTENDED_AR);            // 0xF638
+       MFC_WRITEL(pStr->DecodedNalSize, S5P_FIMV_D_DECODED_NAL_SIZE);                  // 0xF664
+       MFC_WRITEL(pStr->UsedDpbFlagUpper, S5P_FIMV_D_USED_DPB_FLAG_UPPER);             // 0xF720
+       MFC_WRITEL(pStr->UsedDpbFlagLower, S5P_FIMV_D_USED_DPB_FLAG_LOWER);             // 0xF724
+       MFC_WRITEL(pStr->SeiAvail, S5P_FIMV_D_SEI_AVAIL);                               // 0xF6DC
+       MFC_WRITEL(pStr->FramePackArrgmentId, S5P_FIMV_D_FRAME_PACK_ARRGMENT_ID);       // 0xF6E0
+       MFC_WRITEL(pStr->FramePackSeiInfo, S5P_FIMV_D_FRAME_PACK_SEI_INFO);             // 0xF6E4
+       MFC_WRITEL(pStr->FramePackGridPos, S5P_FIMV_D_FRAME_PACK_GRID_POS);             // 0xF6E8
+       MFC_WRITEL(pStr->DisplayRecoverySeiInfo, S5P_FIMV_D_DISPLAY_RECOVERY_SEI_INFO); // 0xF6EC
+       MFC_WRITEL(pStr->H264Info, S5P_FIMV_D_H264_INFO);                               // 0xF690
+       MFC_WRITEL(pStr->DisplayFirstCrc, S5P_FIMV_D_DISPLAY_FIRST_PLANE_CRC);          // 0xF628
+       MFC_WRITEL(pStr->DisplaySecondCrc, S5P_FIMV_D_DISPLAY_SECOND_PLANE_CRC);        // 0xF62C
+       MFC_WRITEL(pStr->DisplayThirdCrc, S5P_FIMV_D_DISPLAY_THIRD_PLANE_CRC);          // 0xF630
+       MFC_WRITEL(pStr->DisplayFirst2BitCrc, S5P_FIMV_D_DISPLAY_FIRST_PLANE_2BIT_CRC); // 0xF6FC
+       MFC_WRITEL(pStr->DisplaySecond2BitCrc, S5P_FIMV_D_DISPLAY_SECOND_PLANE_2BIT_CRC);// 0xF700
+       MFC_WRITEL(pStr->DecodedFrameWidth, S5P_FIMV_D_DECODED_FRAME_WIDTH);            // 0xF63C
+       MFC_WRITEL(pStr->DecodedFrameHeight, S5P_FIMV_D_DECODED_FRAME_HEIGHT);          // 0xF640
+       MFC_WRITEL(pStr->DecodedStatus, S5P_FIMV_D_DECODED_STATUS);                     // 0xF644
+       MFC_WRITEL(pStr->DecodedFirstPlaneAddr, S5P_FIMV_D_DECODED_FIRST_PLANE_ADDR);   // 0xF648
+       MFC_WRITEL(pStr->DecodedSecondPlaneAddr, S5P_FIMV_D_DECODED_SECOND_PLANE_ADDR); // 0xF64C
+       MFC_WRITEL(pStr->DecodedThirdPlaneAddr, S5P_FIMV_D_DECODED_THIRD_PLANE_ADDR);   // 0xF650
+       MFC_WRITEL(pStr->DecodedFrameType, S5P_FIMV_D_DECODED_FRAME_TYPE);              // 0xF654
+       MFC_WRITEL(pStr->DecodedCropInfo1, S5P_FIMV_D_DECODED_CROP_INFO1);              // 0xF658
+       MFC_WRITEL(pStr->DecodedCropInfo2, S5P_FIMV_D_DECODED_CROP_INFO2);              // 0xF65C
+       MFC_WRITEL(pStr->DecodedPictureProfile, S5P_FIMV_D_DECODED_PICTURE_PROFILE);    // 0xF660
+       MFC_WRITEL(pStr->DecodedRecoverySeiInfo, S5P_FIMV_D_DECODED_RECOVERY_SEI_INFO); // 0xF6F0
+       MFC_WRITEL(pStr->DecodedFirstCrc, S5P_FIMV_D_DECODED_FIRST_PLANE_CRC);          // 0xF668
+       MFC_WRITEL(pStr->DecodedSecondCrc, S5P_FIMV_D_DECODED_SECOND_PLANE_CRC);        // 0xF66C
+       MFC_WRITEL(pStr->DecodedThirdCrc, S5P_FIMV_D_DECODED_THIRD_PLANE_CRC);          // 0xF670
+       MFC_WRITEL(pStr->DecodedFirst2BitCrc, S5P_FIMV_D_DECODED_FIRST_PLANE_2BIT_CRC); // 0xF704
+       MFC_WRITEL(pStr->DecodedSecond2BitCrc, S5P_FIMV_D_DECODED_SECOND_PLANE_2BIT_CRC);// 0xF708
+       MFC_WRITEL(pStr->PictureTagBot, S5P_FIMV_D_RET_PICTURE_TAG_BOT);                // 0xF678
+       MFC_WRITEL(pStr->PictureTimeBot, S5P_FIMV_D_RET_PICTURE_TIME_BOT);              // 0xF680
+}
+#endif
diff --git a/drivers/media/platform/exynos/mfc/mfc_nal_q.h b/drivers/media/platform/exynos/mfc/mfc_nal_q.h
new file mode 100644 (file)
index 0000000..ccf7900
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_nal_q.h
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __MFC_NAL_Q_H
+#define __MFC_NAL_Q_H __FILE__
+
+#include "mfc_common.h"
+
+int s5p_mfc_nal_q_check_enable(struct s5p_mfc_dev *dev);
+
+void s5p_mfc_nal_q_clock_on(struct s5p_mfc_dev *dev, nal_queue_handle *nal_q_handle);
+void s5p_mfc_nal_q_clock_off(struct s5p_mfc_dev *dev, nal_queue_handle *nal_q_handle);
+void s5p_mfc_nal_q_cleanup_clock(struct s5p_mfc_dev *dev);
+
+nal_queue_handle *s5p_mfc_nal_q_create(struct s5p_mfc_dev *dev);
+int s5p_mfc_nal_q_destroy(struct s5p_mfc_dev *dev, nal_queue_handle *nal_q_handle);
+
+void s5p_mfc_nal_q_init(struct s5p_mfc_dev *dev, nal_queue_handle *nal_q_handle);
+void s5p_mfc_nal_q_start(struct s5p_mfc_dev *dev, nal_queue_handle *nal_q_handle);
+void s5p_mfc_nal_q_stop(struct s5p_mfc_dev *dev, nal_queue_handle *nal_q_handle);
+void s5p_mfc_nal_q_stop_if_started(struct s5p_mfc_dev *dev);
+void s5p_mfc_nal_q_cleanup_queue(struct s5p_mfc_dev *dev);
+
+int s5p_mfc_nal_q_handle_out_buf(struct s5p_mfc_dev *dev, EncoderOutputStr *pOutStr);
+int s5p_mfc_nal_q_enqueue_in_buf(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx,
+                       nal_queue_in_handle *nal_q_in_handle);
+EncoderOutputStr *s5p_mfc_nal_q_dequeue_out_buf(struct s5p_mfc_dev *dev,
+                       nal_queue_out_handle *nal_q_out_handle, unsigned int *reason);
+
+#endif /* __MFC_NAL_Q_H  */
diff --git a/drivers/media/platform/exynos/mfc/mfc_opr.c b/drivers/media/platform/exynos/mfc/mfc_opr.c
new file mode 100644 (file)
index 0000000..4fe9df0
--- /dev/null
@@ -0,0 +1,336 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_opr.c
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include "mfc_opr.h"
+
+#include "mfc_inst.h"
+#include "mfc_reg.h"
+
+#include "mfc_queue.h"
+#include "mfc_utils.h"
+#include "mfc_mem.h"
+
+int s5p_mfc_run_dec_init(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev;
+       struct s5p_mfc_buf *src_mb;
+       struct s5p_mfc_dec *dec = NULL;
+
+       if (!ctx) {
+               mfc_err_dev("no mfc context to run\n");
+               return -EINVAL;
+       }
+       dev = ctx->dev;
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return -EINVAL;
+       }
+       dec = ctx->dec_priv;
+       /* Initializing decoding - parsing header */
+
+       /* Get the next source buffer */
+       src_mb = s5p_mfc_get_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, MFC_BUF_NO_TOUCH_USED);
+       if (!src_mb) {
+               mfc_err_dev("no src buffers\n");
+               return -EAGAIN;
+       }
+
+       mfc_debug(2, "Preparing to init decoding\n");
+       mfc_debug(2, "Header size: %d, (offset: %lu)\n",
+               src_mb->vb.vb2_buf.planes[0].bytesused, dec->consumed);
+
+       if (dec->consumed) {
+               s5p_mfc_set_dec_stream_buffer(ctx, src_mb, dec->consumed, dec->remained_size);
+       } else {
+               /* decoder src buffer CFW PROT */
+               if (ctx->is_drm) {
+                       int index = src_mb->vb.vb2_buf.index;
+
+                       s5p_mfc_stream_protect(ctx, src_mb, index);
+               }
+
+               s5p_mfc_set_dec_stream_buffer(ctx, src_mb,
+                       0, src_mb->vb.vb2_buf.planes[0].bytesused);
+       }
+
+       mfc_debug(2, "Header addr: 0x%08llx\n", src_mb->addr[0][0]);
+       s5p_mfc_clean_ctx_int_flags(ctx);
+       s5p_mfc_init_decode(ctx);
+
+       return 0;
+}
+
+static int mfc_check_last_frame(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf *mfc_buf)
+{
+       if (mfc_buf->vb.reserved2 & FLAG_LAST_FRAME) {
+               mfc_debug(2, "Setting ctx->state to FINISHING\n");
+               s5p_mfc_change_state(ctx, MFCINST_FINISHING);
+               return 1;
+       }
+
+       return 0;
+}
+
+int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev;
+       struct s5p_mfc_buf *src_mb, *dst_mb;
+       struct s5p_mfc_dec *dec;
+       int last_frame = 0;
+       unsigned int index;
+
+       if (!ctx) {
+               mfc_err_dev("no mfc context to run\n");
+               return -EINVAL;
+       }
+       dec = ctx->dec_priv;
+       dev = ctx->dev;
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return -EINVAL;
+       }
+
+       if (s5p_mfc_is_queue_count_same(&ctx->buf_queue_lock, &ctx->dst_buf_queue, 0) &&
+                       s5p_mfc_is_queue_count_smaller(&ctx->buf_queue_lock,
+                               &ctx->ref_buf_queue, (ctx->dpb_count + 5))) {
+               return -EAGAIN;
+       }
+
+       /* Get the next source buffer */
+       src_mb = s5p_mfc_get_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, MFC_BUF_SET_USED);
+       if (!src_mb) {
+               mfc_debug(2, "no src buffers\n");
+               return -EAGAIN;
+       }
+
+       /* decoder src buffer CFW PROT */
+       if (ctx->is_drm) {
+               if (!dec->consumed) {
+                       index = src_mb->vb.vb2_buf.index;
+                       s5p_mfc_stream_protect(ctx, src_mb, index);
+               }
+       }
+
+       if (src_mb->vb.reserved2 & FLAG_EMPTY_DATA)
+               src_mb->vb.vb2_buf.planes[0].bytesused = 0;
+
+       if (dec->consumed)
+               s5p_mfc_set_dec_stream_buffer(ctx, src_mb, dec->consumed, dec->remained_size);
+       else
+               s5p_mfc_set_dec_stream_buffer(ctx, src_mb, 0, src_mb->vb.vb2_buf.planes[0].bytesused);
+
+       /* Try to use the non-referenced DPB on dst-queue */
+       dst_mb = s5p_mfc_search_for_dpb(ctx, dec->dynamic_used);
+       if (!dst_mb) {
+               mfc_debug(2, "[DPB] couldn't find dst buffers\n");
+               return -EAGAIN;
+       }
+
+       index = src_mb->vb.vb2_buf.index;
+       if (call_cop(ctx, set_buf_ctrls_val, ctx, &ctx->src_ctrls[index]) < 0)
+               mfc_err_ctx("failed in set_buf_ctrls_val\n");
+
+       s5p_mfc_set_dynamic_dpb(ctx, dst_mb);
+
+       s5p_mfc_clean_ctx_int_flags(ctx);
+
+       last_frame = mfc_check_last_frame(ctx, src_mb);
+       s5p_mfc_decode_one_frame(ctx, last_frame);
+
+       return 0;
+}
+
+int s5p_mfc_run_dec_last_frames(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev;
+       struct s5p_mfc_buf *src_mb, *dst_mb;
+       struct s5p_mfc_dec *dec;
+
+       if (!ctx) {
+               mfc_err_dev("no mfc context to run\n");
+               return -EINVAL;
+       }
+
+       dec = ctx->dec_priv;
+       if (!dec) {
+               mfc_err_dev("no decoder context to run\n");
+               return -EINVAL;
+       }
+
+       dev = ctx->dev;
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return -EINVAL;
+       }
+
+       if (s5p_mfc_is_queue_count_same(&ctx->buf_queue_lock, &ctx->dst_buf_queue, 0)) {
+               mfc_debug(2, "no dst buffer\n");
+               return -EAGAIN;
+       }
+
+       /* Get the next source buffer */
+       src_mb = s5p_mfc_get_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, MFC_BUF_SET_USED);
+
+       /* Frames are being decoded */
+       if (!src_mb) {
+               mfc_debug(2, "no src buffers\n");
+               s5p_mfc_set_dec_stream_buffer(ctx, 0, 0, 0);
+       } else {
+               if (dec->consumed) {
+                       s5p_mfc_set_dec_stream_buffer(ctx, src_mb, dec->consumed, dec->remained_size);
+               } else {
+                       /* decoder src buffer CFW PROT */
+                       if (ctx->is_drm) {
+                               int index = src_mb->vb.vb2_buf.index;
+
+                               s5p_mfc_stream_protect(ctx, src_mb, index);
+                       }
+
+                       s5p_mfc_set_dec_stream_buffer(ctx, src_mb, 0, 0);
+               }
+       }
+
+       /* Try to use the non-referenced DPB on dst-queue */
+       dst_mb = s5p_mfc_search_for_dpb(ctx, dec->dynamic_used);
+       if (!dst_mb) {
+               mfc_debug(2, "[DPB] couldn't find dst buffers\n");
+               return -EAGAIN;
+       }
+
+       s5p_mfc_set_dynamic_dpb(ctx, dst_mb);
+
+       s5p_mfc_clean_ctx_int_flags(ctx);
+       s5p_mfc_decode_one_frame(ctx, 1);
+
+       return 0;
+}
+
+int s5p_mfc_run_enc_init(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_buf *dst_mb;
+       int ret;
+
+       dst_mb = s5p_mfc_get_buf(&ctx->buf_queue_lock, &ctx->dst_buf_queue, MFC_BUF_NO_TOUCH_USED);
+       if (!dst_mb) {
+               mfc_debug(2, "no dst buffers\n");
+               return -EAGAIN;
+       }
+
+       /* encoder dst buffer CFW PROT */
+       if (ctx->is_drm) {
+               int index = dst_mb->vb.vb2_buf.index;
+
+               s5p_mfc_stream_protect(ctx, dst_mb, index);
+       }
+       s5p_mfc_set_enc_stream_buffer(ctx, dst_mb);
+
+       s5p_mfc_set_enc_stride(ctx);
+
+       mfc_debug(2, "Header addr: 0x%08llx\n", dst_mb->addr[0][0]);
+       s5p_mfc_clean_ctx_int_flags(ctx);
+
+       ret = s5p_mfc_init_encode(ctx);
+       return ret;
+}
+
+int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_buf *dst_mb;
+       struct s5p_mfc_buf *src_mb;
+       struct s5p_mfc_raw_info *raw;
+       unsigned int index, i;
+       int last_frame = 0;
+
+       raw = &ctx->raw_buf;
+
+       /* Get the next source buffer */
+       src_mb = s5p_mfc_get_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, MFC_BUF_SET_USED);
+       if (!src_mb) {
+               mfc_debug(2, "no src buffers\n");
+               return -EAGAIN;
+       }
+
+       if (src_mb->num_valid_bufs > 0) {
+               /* last image in a buffer container */
+               if (src_mb->next_index == (src_mb->num_valid_bufs - 1)) {
+                       mfc_debug(4, "[BUFCON] last image in a container\n");
+                       last_frame = mfc_check_last_frame(ctx, src_mb);
+               }
+       } else {
+               last_frame = mfc_check_last_frame(ctx, src_mb);
+       }
+
+       index = src_mb->vb.vb2_buf.index;
+
+       /* encoder src buffer CFW PROT */
+       if (ctx->is_drm)
+               s5p_mfc_raw_protect(ctx, src_mb, index);
+
+       s5p_mfc_set_enc_frame_buffer(ctx, src_mb, raw->num_planes);
+
+       dst_mb = s5p_mfc_get_buf(&ctx->buf_queue_lock, &ctx->dst_buf_queue, MFC_BUF_SET_USED);
+       if (!dst_mb) {
+               mfc_debug(2, "no dst buffers\n");
+               return -EAGAIN;
+       }
+
+       /* encoder dst buffer CFW PROT */
+       if (ctx->is_drm) {
+               i = dst_mb->vb.vb2_buf.index;
+               s5p_mfc_stream_protect(ctx, dst_mb, i);
+       }
+       mfc_debug(2, "nal start : src index from src_buf_queue:%d\n",
+               src_mb->vb.vb2_buf.index);
+       mfc_debug(2, "nal start : dst index from dst_buf_queue:%d\n",
+               dst_mb->vb.vb2_buf.index);
+
+       s5p_mfc_set_enc_stream_buffer(ctx, dst_mb);
+
+       if (call_cop(ctx, set_buf_ctrls_val, ctx, &ctx->src_ctrls[index]) < 0)
+               mfc_err_ctx("failed in set_buf_ctrls_val\n");
+
+       s5p_mfc_clean_ctx_int_flags(ctx);
+       s5p_mfc_encode_one_frame(ctx, last_frame);
+
+       return 0;
+}
+
+int s5p_mfc_run_enc_last_frames(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_buf *dst_mb;
+       struct s5p_mfc_raw_info *raw;
+
+       raw = &ctx->raw_buf;
+
+       dst_mb = s5p_mfc_get_buf(&ctx->buf_queue_lock, &ctx->dst_buf_queue, MFC_BUF_SET_USED);
+       if (!dst_mb) {
+               mfc_debug(2, "no dst buffers\n");
+               return -EAGAIN;
+       }
+
+       mfc_debug(2, "Set address zero for all planes\n");
+       s5p_mfc_set_enc_frame_buffer(ctx, 0, raw->num_planes);
+
+       /* encoder dst buffer CFW PROT */
+       if (ctx->is_drm) {
+               int index = dst_mb->vb.vb2_buf.index;
+
+               s5p_mfc_stream_protect(ctx, dst_mb, index);
+       }
+
+       s5p_mfc_set_enc_stream_buffer(ctx, dst_mb);
+
+       s5p_mfc_clean_ctx_int_flags(ctx);
+       s5p_mfc_encode_one_frame(ctx, 1);
+
+       return 0;
+}
diff --git a/drivers/media/platform/exynos/mfc/mfc_opr.h b/drivers/media/platform/exynos/mfc/mfc_opr.h
new file mode 100644 (file)
index 0000000..36bd24f
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_opr.h
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __MFC_OPR_H
+#define __MFC_OPR_H __FILE__
+
+#include "mfc_common.h"
+
+int s5p_mfc_run_dec_init(struct s5p_mfc_ctx *ctx);
+int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx);
+int s5p_mfc_run_dec_last_frames(struct s5p_mfc_ctx *ctx);
+int s5p_mfc_run_enc_init(struct s5p_mfc_ctx *ctx);
+int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx);
+int s5p_mfc_run_enc_last_frames(struct s5p_mfc_ctx *ctx);
+
+#endif /* __MFC_OPR_H */
diff --git a/drivers/media/platform/exynos/mfc/mfc_otf.c b/drivers/media/platform/exynos/mfc/mfc_otf.c
new file mode 100644 (file)
index 0000000..08ed51d
--- /dev/null
@@ -0,0 +1,721 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_otf.c
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifdef CONFIG_VIDEO_EXYNOS_REPEATER
+#include <media/exynos_repeater.h>
+#endif
+#ifdef CONFIG_VIDEO_EXYNOS_TSMUX
+#include <media/exynos_tsmux.h>
+#endif
+#include <media/s5p_mfc_hwfc.h>
+
+#include "mfc_otf.h"
+#include "mfc_hwfc_internal.h"
+
+#include "mfc_sync.h"
+
+#include "mfc_inst.h"
+#include "mfc_pm.h"
+#include "mfc_cmd.h"
+#include "mfc_reg.h"
+
+#include "mfc_qos.h"
+#include "mfc_queue.h"
+#include "mfc_utils.h"
+#include "mfc_buf.h"
+#include "mfc_mem.h"
+
+static struct s5p_mfc_fmt *mfc_enc_hwfc_find_format(unsigned int pixelformat)
+{
+       unsigned long i;
+
+       mfc_debug_enter();
+
+       for (i = 0; i < NUM_FORMATS; i++) {
+               if (enc_hwfc_formats[i].fourcc == pixelformat)
+                       return (struct s5p_mfc_fmt *)&enc_hwfc_formats[i];
+       }
+
+       mfc_debug_leave();
+
+       return NULL;
+}
+
+static int mfc_otf_set_buf_info(struct s5p_mfc_ctx *ctx)
+{
+       struct _otf_handle *handle = ctx->otf_handle;
+       struct _otf_buf_info *buf_info = &handle->otf_buf_info;
+
+       mfc_debug_enter();
+
+       ctx->src_fmt = mfc_enc_hwfc_find_format(buf_info->pixel_format);
+       if (!ctx->src_fmt) {
+               mfc_err_ctx("[OTF] failed to set source format\n");
+               return -EINVAL;
+       }
+
+       mfc_debug(2, "[OTF][FRAME] resolution w: %d, h: %d, format: %s, bufcnt: %d\n",
+                       buf_info->width, buf_info->height,
+                       ctx->src_fmt->name, buf_info->buffer_count);
+
+       /* set source information */
+       ctx->raw_buf.num_planes = ctx->src_fmt->num_planes;
+       ctx->img_width = buf_info->width;
+       ctx->img_height = buf_info->height;
+       ctx->crop_width = buf_info->width;
+       ctx->crop_height = buf_info->height;
+       ctx->buf_stride = ALIGN(ctx->img_width, 16);
+
+       /* calculate source size */
+       s5p_mfc_enc_calc_src_size(ctx);
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+static int mfc_otf_map_buf(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct _otf_handle *handle = ctx->otf_handle;
+       struct _otf_buf_addr *buf_addr = &handle->otf_buf_addr;
+       struct _otf_buf_info *buf_info = &handle->otf_buf_info;
+       struct s5p_mfc_raw_info *raw = &ctx->raw_buf;
+       int i;
+
+       mfc_debug_enter();
+
+       mfc_debug(2, "[OTF] buffer count: %d\n", buf_info->buffer_count);
+       /* map buffers */
+       for (i = 0; i < buf_info->buffer_count; i++) {
+               mfc_debug(2, "[OTF] dma_buf: 0x%p\n", buf_info->bufs[i]);
+               buf_addr->otf_buf_attach[i] = dma_buf_attach(buf_info->bufs[i], dev->device);
+               if (IS_ERR(buf_addr->otf_buf_attach[i])) {
+                       mfc_err_ctx("[OTF] Failed to get attachment (err %ld)",
+                               PTR_ERR(buf_addr->otf_buf_attach[i]));
+                       buf_addr->otf_buf_attach[i] = 0;
+                       return -EINVAL;
+               }
+               buf_addr->otf_daddr[i][0] = ion_iovmm_map(buf_addr->otf_buf_attach[i], 0,
+                               raw->total_plane_size, DMA_BIDIRECTIONAL, 0);
+               if (IS_ERR_VALUE(buf_addr->otf_daddr[i][0])) {
+                       mfc_err_ctx("[OTF] Failed to get daddr (0x%08llx)",
+                                       buf_addr->otf_daddr[i][0]);
+                       buf_addr->otf_daddr[i][0] = 0;
+                       return -EINVAL;
+               }
+               if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12N) {
+                       buf_addr->otf_daddr[i][1] = NV12N_CBCR_BASE(buf_addr->otf_daddr[i][0],
+                                       ctx->img_width, ctx->img_height);
+               } else {
+                       mfc_err_ctx("[OTF] not supported format(0x%x)\n", ctx->src_fmt->fourcc);
+                       return -EINVAL;
+               }
+               mfc_debug(2, "[OTF] index: %d, addr[0]: 0x%08llx, addr[1]: 0x%08llx\n",
+                               i, buf_addr->otf_daddr[i][0], buf_addr->otf_daddr[i][1]);
+       }
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+static void mfc_otf_unmap_buf(struct s5p_mfc_ctx *ctx)
+{
+       struct _otf_handle *handle = ctx->otf_handle;
+       struct _otf_buf_addr *buf_addr = &handle->otf_buf_addr;
+       struct _otf_buf_info *buf_info = &handle->otf_buf_info;
+       int i;
+
+       mfc_debug_enter();
+
+       for (i = 0; i < buf_info->buffer_count; i++) {
+               if (buf_addr->otf_daddr[i][0]) {
+                       ion_iovmm_unmap(buf_addr->otf_buf_attach[i], buf_addr->otf_daddr[i][0]);
+                       buf_addr->otf_daddr[i][0] = 0;
+               }
+               if (buf_addr->otf_buf_attach[i]) {
+                       dma_buf_detach(buf_info->bufs[i], buf_addr->otf_buf_attach[i]);
+                       buf_addr->otf_buf_attach[i] = 0;
+               }
+       }
+
+       mfc_debug_leave();
+}
+
+static void mfc_otf_put_buf(struct s5p_mfc_ctx *ctx)
+{
+       struct _otf_handle *handle = ctx->otf_handle;
+       struct _otf_buf_info *buf_info = &handle->otf_buf_info;
+       int i;
+
+       mfc_debug_enter();
+
+       for (i = 0; i < buf_info->buffer_count; i++) {
+               if (buf_info->bufs[i]) {
+                       dma_buf_put(buf_info->bufs[i]);
+                       buf_info->bufs[i] = NULL;
+               }
+       }
+
+       mfc_debug_leave();
+
+}
+
+static int mfc_otf_init_hwfc_buf(struct s5p_mfc_ctx *ctx)
+{
+#ifdef CONFIG_VIDEO_EXYNOS_REPEATER
+       struct shared_buffer_info *shared_buf_info;
+#endif
+       struct _otf_handle *handle = ctx->otf_handle;
+       struct _otf_buf_info *buf_info = &handle->otf_buf_info;
+
+       mfc_debug_enter();
+
+#ifdef CONFIG_VIDEO_EXYNOS_REPEATER
+       shared_buf_info = (struct shared_buffer_info *)buf_info;
+       /* request buffers */
+       if (hwfc_request_buffer(shared_buf_info, 1)) {
+               mfc_err_dev("[OTF] request_buffer failed\n");
+               return -EINVAL;
+       }
+#endif
+       mfc_debug(2, "[OTF] recieved buffer information\n");
+
+       /* set buffer information to ctx, and calculate buffer size */
+       if (mfc_otf_set_buf_info(ctx)) {
+               mfc_err_ctx("[OTF] failed to set buffer information\n");
+               mfc_otf_put_buf(ctx);
+               return -EINVAL;
+       }
+
+       if (mfc_otf_map_buf(ctx)) {
+               mfc_err_ctx("[OTF] failed to map buffers\n");
+               mfc_otf_unmap_buf(ctx);
+               mfc_otf_put_buf(ctx);
+               return -EINVAL;
+       }
+       mfc_debug(2, "[OTF] HWFC buffer initialized\n");
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+static void mfc_otf_deinit_hwfc_buf(struct s5p_mfc_ctx *ctx)
+{
+       mfc_debug_enter();
+
+       mfc_otf_unmap_buf(ctx);
+       mfc_otf_put_buf(ctx);
+       mfc_debug(2, "[OTF] HWFC buffer de-initialized\n");
+
+       mfc_debug_leave();
+}
+
+static int mfc_otf_create_handle(struct s5p_mfc_ctx *ctx)
+{
+       struct _otf_handle *otf_handle;
+
+       mfc_debug_enter();
+
+       if (!ctx) {
+               mfc_err_dev("[OTF] no mfc context to run\n");
+               return -EINVAL;
+       }
+
+       ctx->otf_handle = kzalloc(sizeof(*otf_handle), GFP_KERNEL);
+       if (!ctx->otf_handle) {
+               mfc_err_dev("[OTF] no otf_handle\n");
+               return -EINVAL;
+       }
+       mfc_debug(2, "[OTF] otf_handle created\n");
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+static void mfc_otf_destroy_handle(struct s5p_mfc_ctx *ctx)
+{
+       mfc_debug_enter();
+
+       if (!ctx) {
+               mfc_err_dev("[OTF] no mfc context to run\n");
+               return;
+       }
+
+       kfree(ctx->otf_handle);
+       ctx->otf_handle = NULL;
+       mfc_debug(2, "[OTF] otf_handle destroyed\n");
+
+       mfc_debug_leave();
+}
+
+int s5p_mfc_otf_create(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev;
+       int i;
+
+       mfc_debug_enter();
+
+       if (!ctx) {
+               mfc_err_dev("[OTF] no mfc context to run\n");
+               return -EINVAL;
+       }
+
+       dev = ctx->dev;
+       if (!dev) {
+               mfc_err_dev("[OTF] no mfc device to run\n");
+               return -EINVAL;
+       }
+
+       for (i = 0; i < MFC_NUM_CONTEXTS; i++) {
+               if (dev->ctx[i] && dev->ctx[i]->otf_handle) {
+                       mfc_err_dev("[OTF] otf_handle is already created, ctx: %d\n", i);
+                       return -EINVAL;
+               }
+       }
+
+       if (mfc_otf_create_handle(ctx)) {
+               mfc_err_dev("[OTF] otf_handle is not created\n");
+               return -EINVAL;
+       }
+
+       if (otf_dump) {
+               /* It is for debugging. Do not return error */
+               if (s5p_mfc_otf_alloc_stream_buf(ctx)) {
+                       mfc_err_dev("[OTF] stream buffer allocation failed\n");
+                       s5p_mfc_otf_release_stream_buf(ctx);
+               }
+       }
+
+       mfc_debug(2, "[OTF] otf_create is completed\n");
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+void s5p_mfc_otf_destroy(struct s5p_mfc_ctx *ctx)
+{
+       mfc_debug_enter();
+
+       if (!ctx) {
+               mfc_err_dev("[OTF] no mfc context to run\n");
+               return;
+       }
+
+       s5p_mfc_otf_release_stream_buf(ctx);
+       mfc_otf_destroy_handle(ctx);
+       mfc_debug(2, "[OTF] otf_destroy is completed\n");
+
+       mfc_debug_leave();
+}
+
+int s5p_mfc_otf_init(struct s5p_mfc_ctx *ctx)
+{
+       mfc_debug_enter();
+
+       if (!ctx) {
+               mfc_err_dev("[OTF] no mfc context to run\n");
+               return -EINVAL;
+       }
+
+       if (!ctx->otf_handle) {
+               mfc_err_dev("[OTF] otf_handle was not created\n");
+               return -EINVAL;
+       }
+
+       if (mfc_otf_init_hwfc_buf(ctx)) {
+               mfc_err_dev("[OTF] HWFC init failed\n");
+               return -EINVAL;
+       }
+
+       mfc_debug(2, "[OTF] otf_init is completed\n");
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+void s5p_mfc_otf_deinit(struct s5p_mfc_ctx *ctx)
+{
+       mfc_debug_enter();
+
+       if (!ctx) {
+               mfc_err_dev("[OTF] no mfc context to run\n");
+               return;
+       }
+
+       mfc_otf_deinit_hwfc_buf(ctx);
+       mfc_debug(2, "[OTF] deinit_otf is completed\n");
+
+       mfc_debug_leave();
+}
+
+int s5p_mfc_otf_ctx_ready(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct _otf_handle *handle;
+
+       mfc_debug_enter();
+
+       if (!ctx->otf_handle)
+               return 0;
+
+       handle = ctx->otf_handle;
+
+       mfc_debug(1, "[OTF] [c:%d] state = %d, otf_work_bit = %d\n",
+                       ctx->num, ctx->state, handle->otf_work_bit);
+       /* If shutdown is called, do not try any cmd */
+       if (dev->shutdown)
+               return 0;
+
+       /* Context is to parse header */
+       if (ctx->state == MFCINST_GOT_INST)
+               return 1;
+
+       /* Context is to set buffers */
+       if (ctx->state == MFCINST_HEAD_PARSED)
+               return 1;
+
+       if (ctx->state == MFCINST_RUNNING && handle->otf_work_bit)
+               return 1;
+       mfc_debug(2, "[OTF] ctx is not ready\n");
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+int s5p_mfc_otf_run_enc_init(struct s5p_mfc_ctx *ctx)
+{
+       int ret;
+
+       mfc_debug_enter();
+
+       s5p_mfc_set_enc_stride(ctx);
+       s5p_mfc_clean_ctx_int_flags(ctx);
+       ret = s5p_mfc_init_encode(ctx);
+
+       mfc_debug_leave();
+
+       return ret;
+}
+
+int s5p_mfc_otf_run_enc_frame(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct _otf_handle *handle = ctx->otf_handle;
+       struct s5p_mfc_raw_info *raw;
+
+       mfc_debug_enter();
+
+       raw = &ctx->raw_buf;
+
+       if (!handle) {
+               mfc_err_ctx("[OTF] There is no otf_handle, handle: 0x%p\n", handle);
+               return -EINVAL;
+       }
+
+       if (!handle->otf_work_bit) {
+               mfc_err_ctx("[OTF] Can't run OTF encoder, otf_work_bit: %d\n",
+                               handle->otf_work_bit);
+               return -EINVAL;
+       }
+
+       if (!dev->has_hwfc) {
+               mfc_err_ctx("[OTF] HWFC register didn't mapped\n");
+               return -EINVAL;
+       }
+
+       s5p_mfc_otf_set_frame_addr(ctx, raw->num_planes);
+       s5p_mfc_otf_set_stream_size(ctx, raw->total_plane_size);
+       s5p_mfc_otf_set_hwfc_index(ctx, handle->otf_job_id);
+
+       if (call_cop(ctx, init_buf_ctrls, ctx, MFC_CTRL_TYPE_SRC, handle->otf_buf_index) < 0)
+               mfc_err_ctx("failed in init_buf_ctrls\n");
+       if (call_cop(ctx, to_buf_ctrls, ctx, &ctx->src_ctrls[handle->otf_buf_index]) < 0)
+               mfc_err_ctx("failed in to_buf_ctrls\n");
+       if (call_cop(ctx, set_buf_ctrls_val, ctx, &ctx->src_ctrls[handle->otf_buf_index]) < 0)
+               mfc_err_ctx("[OTF] failed in set_buf_ctrls_val\n");
+
+       /* Change timestamp usec -> nsec */
+       s5p_mfc_qos_update_last_framerate(ctx, handle->otf_time_stamp * 1000);
+       s5p_mfc_qos_update_framerate(ctx);
+
+       /* Set stream buffer size to handle buffer full */
+       s5p_mfc_clean_ctx_int_flags(ctx);
+       s5p_mfc_encode_one_frame(ctx, 0);
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+int s5p_mfc_otf_handle_seq(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc *enc = ctx->enc_priv;
+
+       mfc_debug_enter();
+
+       enc->header_size = s5p_mfc_get_enc_strm_size();
+       ctx->dpb_count = s5p_mfc_get_enc_dpb_count();
+       ctx->scratch_buf_size = s5p_mfc_get_enc_scratch_size();
+       mfc_debug(2, "[OTF][STREAM] encoded slice type: %d, header size: %d, display order: %d\n",
+                       s5p_mfc_get_enc_slice_type(), enc->header_size,
+                       s5p_mfc_get_enc_pic_count());
+       mfc_debug(2, "[OTF] cpb_count: %d, scratch size: %zu\n",
+                       ctx->dpb_count, ctx->scratch_buf_size);
+
+       s5p_mfc_change_state(ctx, MFCINST_HEAD_PARSED);
+
+       if (s5p_mfc_alloc_codec_buffers(ctx)) {
+               mfc_err_ctx("[OTF] Failed to allocate encoding buffers\n");
+               return -EINVAL;
+       }
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+int s5p_mfc_otf_handle_stream(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc *enc = ctx->enc_priv;
+       struct _otf_handle *handle = ctx->otf_handle;
+       struct _otf_debug *debug = &handle->otf_debug;
+       struct s5p_mfc_special_buf *buf;
+       struct _otf_buf_addr *buf_addr = &handle->otf_buf_addr;
+       struct s5p_mfc_raw_info *raw;
+       dma_addr_t enc_addr[3] = { 0, 0, 0 };
+       int slice_type, i;
+       unsigned int strm_size;
+       unsigned int pic_count;
+       int enc_ret = HWFC_ERR_NONE;
+       unsigned int print_size;
+
+       mfc_debug_enter();
+
+#ifdef CONFIG_VIDEO_EXYNOS_TSMUX
+       mfc_encoding_end();
+#endif
+
+       slice_type = s5p_mfc_get_enc_slice_type();
+       pic_count = s5p_mfc_get_enc_pic_count();
+       strm_size = s5p_mfc_get_enc_strm_size();
+
+       mfc_debug(2, "[OTF][STREAM] encoded slice type: %d, size: %d, display order: %d\n",
+                       slice_type, strm_size, pic_count);
+
+       /* set encoded frame type */
+       enc->frame_type = slice_type;
+       raw = &ctx->raw_buf;
+
+       if (strm_size > 0) {
+               s5p_mfc_get_enc_frame_buffer(ctx, &enc_addr[0], raw->num_planes);
+
+               for (i = 0; i < raw->num_planes; i++)
+                       mfc_debug(2, "[OTF][BUFINFO] ctx[%d] get src addr[%d]: 0x%08llx\n",
+                                       ctx->num, i, enc_addr[i]);
+               if (enc_addr[0] !=  buf_addr->otf_daddr[handle->otf_buf_index][0]) {
+                       mfc_err_ctx("[OTF] address is not matched. 0x%08llx != 0x%08llx\n",
+                                       enc_addr[0], buf_addr->otf_daddr[handle->otf_buf_index][0]);
+                       enc_ret = -HWFC_ERR_MFC;
+               }
+       } else {
+               mfc_err_ctx("[OTF] stream size is zero\n");
+               enc_ret = -HWFC_ERR_MFC;
+       }
+
+       if (otf_dump && !ctx->is_drm) {
+               buf = &debug->stream_buf[debug->frame_cnt];
+               debug->stream_size[debug->frame_cnt] = strm_size;
+               debug->frame_cnt++;
+               if (debug->frame_cnt >= OTF_MAX_BUF)
+                       debug->frame_cnt = 0;
+               /* print stream dump */
+               print_size = (strm_size * 2) + 64;
+
+               if (buf->vaddr)
+                       print_hex_dump(KERN_ERR, "OTF dump: ",
+                                       DUMP_PREFIX_ADDRESS, print_size, 0,
+                                       buf->vaddr, print_size, false);
+       }
+
+       if (call_cop(ctx, recover_buf_ctrls_val, ctx,
+                               &ctx->src_ctrls[handle->otf_buf_index]) < 0)
+               mfc_err_ctx("[OTF] failed in recover_buf_ctrls_val\n");
+       if (call_cop(ctx, cleanup_buf_ctrls, ctx,
+                               MFC_CTRL_TYPE_SRC, handle->otf_buf_index) < 0)
+               mfc_err_ctx("[OTF] failed in cleanup_buf_ctrls\n");
+
+       handle->otf_work_bit = 0;
+       handle->otf_buf_index = 0;
+       handle->otf_job_id = 0;
+
+#ifdef CONFIG_VIDEO_EXYNOS_REPEATER
+       hwfc_encoding_done(enc_ret);
+#endif
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+void s5p_mfc_otf_handle_error(struct s5p_mfc_ctx *ctx,
+               unsigned int reason, unsigned int err)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct _otf_handle *handle = ctx->otf_handle;
+       int enc_ret = -HWFC_ERR_MFC;
+
+       mfc_debug_enter();
+
+       mfc_err_ctx("[OTF] Interrupt Error: display: %d, decoded: %d\n",
+                       s5p_mfc_get_warn(err), s5p_mfc_get_err(err));
+       err = s5p_mfc_get_err(err);
+
+       /* Error recovery is dependent on the state of context */
+       switch (ctx->state) {
+       case MFCINST_GOT_INST:
+       case MFCINST_INIT:
+       case MFCINST_RETURN_INST:
+       case MFCINST_HEAD_PARSED:
+               mfc_err_ctx("[OTF] error happened during init/de-init\n");
+               break;
+       case MFCINST_RUNNING:
+               if (err == S5P_FIMV_ERR_MFC_TIMEOUT) {
+                       mfc_err_ctx("[OTF] MFC TIMEOUT. go to error state\n");
+                       s5p_mfc_change_state(ctx, MFCINST_ERROR);
+                       enc_ret = -HWFC_ERR_MFC_TIMEOUT;
+               } else if (err == S5P_FIMV_ERR_TS_MUX_TIMEOUT ||
+                               err == S5P_FIMV_ERR_G2D_TIMEOUT) {
+                       mfc_err_ctx("[OTF] TS-MUX or G2D TIMEOUT. skip this frame\n");
+                       enc_ret = -HWFC_ERR_MFC_TIMEOUT;
+               } else {
+                       mfc_err_ctx("[OTF] MFC ERROR. skip this frame\n");
+                       enc_ret = -HWFC_ERR_MFC;
+               }
+
+               handle->otf_work_bit = 0;
+               handle->otf_buf_index = 0;
+               handle->otf_job_id = 0;
+
+               if (call_cop(ctx, recover_buf_ctrls_val, ctx,
+                                       &ctx->src_ctrls[handle->otf_buf_index]) < 0)
+                       mfc_err_ctx("[OTF] failed in recover_buf_ctrls_val\n");
+               if (call_cop(ctx, cleanup_buf_ctrls, ctx,
+                                       MFC_CTRL_TYPE_SRC, handle->otf_buf_index) < 0)
+                       mfc_err_ctx("[OTF] failed in cleanup_buf_ctrls\n");
+
+#ifdef CONFIG_VIDEO_EXYNOS_REPEATER
+               hwfc_encoding_done(enc_ret);
+#endif
+               break;
+       default:
+               mfc_err_ctx("Encountered an error interrupt which had not been handled\n");
+               mfc_err_ctx("ctx->state = %d, ctx->inst_no = %d\n",
+                                               ctx->state, ctx->inst_no);
+               break;
+       }
+
+       s5p_mfc_wake_up_dev(dev, reason, err);
+
+       mfc_debug_leave();
+}
+
+int mfc_hwfc_check_run(struct s5p_mfc_ctx *ctx)
+{
+       struct _otf_handle *handle = ctx->otf_handle;
+
+       mfc_debug_enter();
+
+       if (!handle) {
+               mfc_err_ctx("[OTF] there is no handle for OTF\n");
+               return -EINVAL;
+       }
+       if (handle->otf_work_bit) {
+               mfc_err_ctx("[OTF] OTF is already working\n");
+               return -EINVAL;
+       }
+       if (ctx->state != MFCINST_RUNNING) {
+               mfc_err_ctx("[OTF] mfc is not running state\n");
+               return -EINVAL;
+       }
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+int s5p_mfc_hwfc_encode(int buf_index, int job_id, struct encoding_param *param)
+{
+       struct s5p_mfc_dev *dev = g_mfc_dev;
+       struct _otf_handle *handle;
+       struct s5p_mfc_ctx *ctx = NULL;
+#ifdef CONFIG_VIDEO_EXYNOS_TSMUX
+       struct packetizing_param packet_param;
+#endif
+       int i;
+
+       mfc_debug_enter();
+
+#ifdef CONFIG_VIDEO_EXYNOS_TSMUX
+       mfc_encoding_start(buf_index);
+#endif
+
+       for (i = 0; i < MFC_NUM_CONTEXTS; i++) {
+               if (dev->ctx[i] && dev->ctx[i]->otf_handle) {
+                       ctx = dev->ctx[i];
+                       break;
+               }
+       }
+
+       if (!ctx) {
+               mfc_err_dev("[OTF] there is no context to run\n");
+               return -HWFC_ERR_MFC_NOT_PREPARED;
+       }
+
+       if (mfc_hwfc_check_run(ctx)) {
+               mfc_err_dev("[OTF] mfc is not prepared\n");
+               return -HWFC_ERR_MFC_NOT_PREPARED;
+       }
+
+#ifdef CONFIG_VIDEO_EXYNOS_TSMUX
+       packet_param.time_stamp = param->time_stamp;
+       if (debug_ts == 1)
+               mfc_info_ctx("[OTF][TS] timestamp: %llu\n", param->time_stamp);
+       if (packetize(&packet_param)) {
+               mfc_err_dev("[OTF] packetize failed\n");
+               return -HWFC_ERR_TSMUX;
+       }
+#endif
+
+       handle = ctx->otf_handle;
+       handle->otf_work_bit = 1;
+       handle->otf_buf_index = buf_index;
+       handle->otf_job_id = job_id;
+       handle->otf_time_stamp = param->time_stamp;
+
+       if (s5p_mfc_otf_ctx_ready(ctx))
+               s5p_mfc_set_bit(ctx->num, &dev->work_bits);
+       if (s5p_mfc_is_work_to_do(dev))
+               queue_work(dev->butler_wq, &dev->butler_work);
+
+       mfc_debug_leave();
+
+       return HWFC_ERR_NONE;
+}
diff --git a/drivers/media/platform/exynos/mfc/mfc_otf.h b/drivers/media/platform/exynos/mfc/mfc_otf.h
new file mode 100644 (file)
index 0000000..d96e403
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_otf.h
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __MFC_OTF_H
+#define __MFC_OTF_H __FILE__
+
+#include "mfc_common.h"
+
+extern struct s5p_mfc_dev *g_mfc_dev;
+
+int s5p_mfc_otf_create(struct s5p_mfc_ctx *ctx);
+void s5p_mfc_otf_destroy(struct s5p_mfc_ctx *ctx);
+int s5p_mfc_otf_init(struct s5p_mfc_ctx *ctx);
+void s5p_mfc_otf_deinit(struct s5p_mfc_ctx *ctx);
+int s5p_mfc_otf_ctx_ready(struct s5p_mfc_ctx *ctx);
+int s5p_mfc_otf_run_enc_init(struct s5p_mfc_ctx *ctx);
+int s5p_mfc_otf_run_enc_frame(struct s5p_mfc_ctx *ctx);
+int s5p_mfc_otf_handle_seq(struct s5p_mfc_ctx *ctx);
+int s5p_mfc_otf_handle_stream(struct s5p_mfc_ctx *ctx);
+void s5p_mfc_otf_handle_error(struct s5p_mfc_ctx *ctx, unsigned int reason, unsigned int err);
+
+#endif /* __MFC_OTF_H  */
diff --git a/drivers/media/platform/exynos/mfc/mfc_perf_measure.c b/drivers/media/platform/exynos/mfc/mfc_perf_measure.c
new file mode 100644 (file)
index 0000000..a6d335e
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_perf_measure.c
+ *
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include "mfc_perf_measure.h"
+
+#ifndef PERF_MEASURE
+
+void s5p_mfc_perf_register(struct s5p_mfc_dev *dev) {}
+void mfc_measure_init(void) {}
+void mfc_measure_on(struct s5p_mfc_dev *dev) {}
+void mfc_measure_off(struct s5p_mfc_dev *dev) {}
+void mfc_measure_store(struct s5p_mfc_dev *dev, int diff) {}
+void s5p_mfc_perf_print(void) {}
+
+#else
+
+#endif
diff --git a/drivers/media/platform/exynos/mfc/mfc_perf_measure.h b/drivers/media/platform/exynos/mfc/mfc_perf_measure.h
new file mode 100644 (file)
index 0000000..ab7fe57
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_perf_measure.h
+ *
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __MFC_PERF_MEASURE_H
+#define __MFC_PERF_MEASURE_H __FILE__
+
+#include <linux/clk.h>
+
+#include "mfc_reg.h"
+
+void s5p_mfc_perf_register(struct s5p_mfc_dev *dev);
+void mfc_measure_init(void);
+void mfc_measure_on(struct s5p_mfc_dev *dev);
+void mfc_measure_off(struct s5p_mfc_dev *dev);
+void mfc_measure_store(struct s5p_mfc_dev *dev, int diff);
+void s5p_mfc_perf_print(void);
+
+//#define PERF_MEASURE
+
+#ifndef PERF_MEASURE
+
+static inline void s5p_mfc_perf_init(struct s5p_mfc_dev *dev) {}
+static inline void s5p_mfc_perf_cancel_drv_margin(struct s5p_mfc_dev *dev) {}
+static inline void s5p_mfc_perf_measure_on(struct s5p_mfc_dev *dev) {}
+static inline void s5p_mfc_perf_measure_off(struct s5p_mfc_dev *dev) {}
+
+#else
+
+extern unsigned int perf_measure_option;
+
+static inline void s5p_mfc_perf_init(struct s5p_mfc_dev *dev)
+{
+       dev->perf.new_start = 0;
+       dev->perf.count = 0;
+       dev->perf.drv_margin = 0;
+
+       mfc_measure_init();
+
+       mfc_info_dev("MFC frequency : %ld\n", clk_get_rate(dev->pm.clock));
+}
+
+static inline void s5p_mfc_perf_cancel_drv_margin(struct s5p_mfc_dev *dev)
+{
+       dev->perf.drv_margin = 0;
+}
+
+static inline void s5p_mfc_perf_measure_on(struct s5p_mfc_dev *dev)
+{
+       int diff;
+
+       if (dev->perf.drv_margin) {
+               do_gettimeofday(&dev->perf.end);
+
+               diff = (dev->perf.end.tv_sec * 1000000 + dev->perf.end.tv_usec)
+                       - (dev->perf.begin.tv_sec * 1000000 + dev->perf.begin.tv_usec);
+
+               mfc_info_dev("IRQ -> NAL_START time(ms) = %03d.%03d\n", diff / 1000, diff % 1000);
+
+               dev->perf.drv_margin = 0;
+       }
+
+       do_gettimeofday(&dev->perf.begin);
+
+       mfc_measure_on(dev);
+
+       dev->perf.new_start = 1;
+       dev->perf.count++;
+}
+
+static inline void s5p_mfc_perf_measure_off(struct s5p_mfc_dev *dev)
+{
+       unsigned int diff;
+
+       if ((dev->perf.new_start) && (dev->perf.count > 0)) {
+               mfc_measure_off(dev);
+
+               do_gettimeofday(&dev->perf.end);
+
+               diff = (dev->perf.end.tv_sec * 1000000 + dev->perf.end.tv_usec)
+                       - (dev->perf.begin.tv_sec * 1000000 + dev->perf.begin.tv_usec);
+
+               mfc_measure_store(dev, diff);
+
+               mfc_debug(3, "uDECtype :%d, uENCtype :%d, codectype :%d\n",
+                       s5p_mfc_get_dec_frame_type(), s5p_mfc_get_enc_slice_type(), MFC_READL(S5P_FIMV_CODEC_TYPE));
+
+               dev->perf.drv_margin = 1;
+
+               do_gettimeofday(&dev->perf.begin);
+       }
+
+       dev->perf.new_start = 0;
+}
+
+#endif
+
+#endif /* __MFC_PERF_MEASURE_H */
diff --git a/drivers/media/platform/exynos/mfc/mfc_pm.c b/drivers/media/platform/exynos/mfc/mfc_pm.c
new file mode 100644 (file)
index 0000000..b4db056
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_pm.c
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/pm_runtime.h>
+#include <linux/clk.h>
+#include <linux/smc.h>
+
+#include "mfc_pm.h"
+
+#include "mfc_cal.h"
+#include "mfc_reg.h"
+
+void s5p_mfc_pm_init(struct s5p_mfc_dev *dev)
+{
+       spin_lock_init(&dev->pm.clklock);
+       atomic_set(&dev->pm.pwr_ref, 0);
+       atomic_set(&dev->clk_ref, 0);
+
+       dev->pm.device = dev->device;
+       dev->pm.clock_on_steps = 0;
+       dev->pm.clock_off_steps = 0;
+       pm_runtime_enable(dev->pm.device);
+}
+
+void s5p_mfc_pm_final(struct s5p_mfc_dev *dev)
+{
+       pm_runtime_disable(dev->pm.device);
+}
+
+int s5p_mfc_pm_clock_on(struct s5p_mfc_dev *dev)
+{
+       int ret = 0;
+       int state;
+
+       dev->pm.clock_on_steps = 1;
+       state = atomic_read(&dev->clk_ref);
+
+       MFC_TRACE_DEV("** clock_on start: ref state(%d)\n", state);
+       ret = clk_enable(dev->pm.clock);
+       if (ret < 0) {
+               mfc_err_dev("clk_enable failed (%d)\n", ret);
+               call_dop(dev, dump_and_stop_debug_mode, dev);
+               return ret;
+       }
+       dev->pm.clock_on_steps |= 0x1 << 1;
+
+       if (dev->pm.base_type != MFCBUF_INVALID)
+               s5p_mfc_set_risc_base_addr(dev, dev->pm.base_type);
+
+       dev->pm.clock_on_steps |= 0x1 << 2;
+#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
+       if (dev->curr_ctx_is_drm) {
+               unsigned long flags;
+
+               spin_lock_irqsave(&dev->pm.clklock, flags);
+               mfc_debug(3, "Begin: enable protection\n");
+               ret = exynos_smc(SMC_PROTECTION_SET, 0,
+                                       dev->id, SMC_PROTECTION_ENABLE);
+               dev->pm.clock_on_steps |= 0x1 << 3;
+               if (ret != DRMDRV_OK) {
+                       mfc_err_dev("Protection Enable failed! ret(%u)\n", ret);
+                       call_dop(dev, dump_and_stop_debug_mode, dev);
+                       spin_unlock_irqrestore(&dev->pm.clklock, flags);
+                       clk_disable(dev->pm.clock);
+                       return -EACCES;
+               }
+               mfc_debug(3, "End: enable protection\n");
+               spin_unlock_irqrestore(&dev->pm.clklock, flags);
+       }
+#endif
+       dev->pm.clock_on_steps |= 0x1 << 4;
+       atomic_inc_return(&dev->clk_ref);
+
+       dev->pm.clock_on_steps |= 0x1 << 6;
+       state = atomic_read(&dev->clk_ref);
+       mfc_debug(2, "+ %d\n", state);
+       MFC_TRACE_DEV("** clock_on end: ref state(%d)\n", state);
+
+       return 0;
+}
+
+/* Use only in functions that first instance is guaranteed, like mfc_init_hw() */
+int s5p_mfc_pm_clock_on_with_base(struct s5p_mfc_dev *dev,
+                               enum mfc_buf_usage_type buf_type)
+{
+       int ret;
+       dev->pm.base_type = buf_type;
+       ret = s5p_mfc_pm_clock_on(dev);
+       dev->pm.base_type = MFCBUF_INVALID;
+
+       return ret;
+}
+
+void s5p_mfc_pm_clock_off(struct s5p_mfc_dev *dev)
+{
+       int state;
+
+       dev->pm.clock_off_steps = 1;
+       atomic_dec_return(&dev->clk_ref);
+
+       dev->pm.clock_off_steps |= 0x1 << 1;
+       state = atomic_read(&dev->clk_ref);
+       MFC_TRACE_DEV("** clock_off start: ref state(%d)\n", state);
+       if (state < 0) {
+               mfc_err_dev("Clock state is wrong(%d)\n", state);
+               atomic_set(&dev->clk_ref, 0);
+               dev->pm.clock_off_steps |= 0x1 << 2;
+       } else {
+#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
+               if (dev->curr_ctx_is_drm) {
+                       unsigned long flags;
+                       int ret = 0;
+
+                       mfc_debug(3, "Begin: disable protection\n");
+                       spin_lock_irqsave(&dev->pm.clklock, flags);
+                       dev->pm.clock_off_steps |= 0x1 << 3;
+                       ret = exynos_smc(SMC_PROTECTION_SET, 0,
+                                       dev->id, SMC_PROTECTION_DISABLE);
+                       if (ret != DRMDRV_OK) {
+                               mfc_err_dev("Protection Disable failed! ret(%u)\n", ret);
+                               call_dop(dev, dump_and_stop_debug_mode, dev);
+                               spin_unlock_irqrestore(&dev->pm.clklock, flags);
+                               clk_disable(dev->pm.clock);
+                               return;
+                       }
+                       mfc_debug(3, "End: disable protection\n");
+                       dev->pm.clock_off_steps |= 0x1 << 4;
+                       spin_unlock_irqrestore(&dev->pm.clklock, flags);
+               }
+#endif
+               dev->pm.clock_off_steps |= 0x1 << 5;
+               clk_disable(dev->pm.clock);
+       }
+
+       dev->pm.clock_off_steps |= 0x1 << 6;
+       state = atomic_read(&dev->clk_ref);
+       mfc_debug(2, "- %d\n", state);
+       MFC_TRACE_DEV("** clock_off end: ref state(%d)\n", state);
+}
+
+int s5p_mfc_pm_power_on(struct s5p_mfc_dev *dev)
+{
+       int ret;
+
+       MFC_TRACE_DEV("++ Power on\n");
+       ret = pm_runtime_get_sync(dev->pm.device);
+       if (ret < 0) {
+               mfc_err_dev("Failed to get power: ret(%d)\n", ret);
+               call_dop(dev, dump_and_stop_debug_mode, dev);
+               goto err_power_on;
+       }
+
+       dev->pm.clock = clk_get(dev->device, "aclk_mfc");
+       if (IS_ERR(dev->pm.clock)) {
+               mfc_err_dev("failed to get parent clock: ret(%d)\n", ret);
+               ret = -ENOENT;
+               goto err_clk_get;
+       }
+
+       ret = clk_prepare(dev->pm.clock);
+       if (ret) {
+               mfc_err_dev("clk_prepare() failed: ret(%d)\n", ret);
+               goto err_clk_prepare;
+       }
+
+       atomic_inc(&dev->pm.pwr_ref);
+
+       MFC_TRACE_DEV("-- Power on: ret(%d)\n", ret);
+
+       return 0;
+
+err_clk_prepare:
+       clk_put(dev->pm.clock);
+
+err_clk_get:
+       pm_runtime_put_sync(dev->pm.device);
+
+err_power_on:
+       return ret;
+}
+
+int s5p_mfc_pm_power_off(struct s5p_mfc_dev *dev)
+{
+       int ret;
+
+       MFC_TRACE_DEV("++ Power off\n");
+
+       clk_unprepare(dev->pm.clock);
+       clk_put(dev->pm.clock);
+
+       ret = pm_runtime_put_sync(dev->pm.device);
+       if (ret < 0) {
+               mfc_err_dev("Failed to put power: ret(%d)\n", ret);
+               call_dop(dev, dump_and_stop_debug_mode, dev);
+               return ret;
+       }
+
+       atomic_dec(&dev->pm.pwr_ref);
+
+       MFC_TRACE_DEV("-- Power off: ret(%d)\n", ret);
+
+       return ret;
+}
diff --git a/drivers/media/platform/exynos/mfc/mfc_pm.h b/drivers/media/platform/exynos/mfc/mfc_pm.h
new file mode 100644 (file)
index 0000000..8e3aa67
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_pm.h
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __MFC_PM_H
+#define __MFC_PM_H __FILE__
+
+#include "mfc_common.h"
+
+static inline int s5p_mfc_pm_get_pwr_ref_cnt(struct s5p_mfc_dev *dev)
+{
+       return atomic_read(&dev->pm.pwr_ref);
+}
+
+static inline int s5p_mfc_pm_get_clk_ref_cnt(struct s5p_mfc_dev *dev)
+{
+       return atomic_read(&dev->clk_ref);
+}
+
+void s5p_mfc_pm_init(struct s5p_mfc_dev *dev);
+void s5p_mfc_pm_final(struct s5p_mfc_dev *dev);
+
+int s5p_mfc_pm_clock_on(struct s5p_mfc_dev *dev);
+int s5p_mfc_pm_clock_on_with_base(struct s5p_mfc_dev *dev,
+                       enum mfc_buf_usage_type buf_type);
+void s5p_mfc_pm_clock_off(struct s5p_mfc_dev *dev);
+int s5p_mfc_pm_power_on(struct s5p_mfc_dev *dev);
+int s5p_mfc_pm_power_off(struct s5p_mfc_dev *dev);
+
+#endif /* __MFC_PM_H */
diff --git a/drivers/media/platform/exynos/mfc/mfc_qos.c b/drivers/media/platform/exynos/mfc/mfc_qos.c
new file mode 100644 (file)
index 0000000..de6dd19
--- /dev/null
@@ -0,0 +1,832 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_qos.c
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/err.h>
+#ifdef CONFIG_EXYNOS_BTS
+#include <soc/samsung/bts.h>
+#endif
+
+#include "mfc_qos.h"
+
+#ifdef CONFIG_MFC_USE_BUS_DEVFREQ
+enum {
+       MFC_QOS_ADD,
+       MFC_QOS_UPDATE,
+       MFC_QOS_REMOVE,
+       MFC_QOS_BW,
+};
+
+enum {
+       MFC_PERF_BOOST_DVFS     = (1 << 0),
+       MFC_PERF_BOOST_MO       = (1 << 1),
+       MFC_PERF_BOOST_CPU      = (1 << 2),
+};
+
+void s5p_mfc_perf_boost_enable(struct s5p_mfc_dev *dev)
+{
+       struct s5p_mfc_platdata *pdata = dev->pdata;
+       struct s5p_mfc_qos_boost *qos_boost_table = pdata->qos_boost_table;
+       int i;
+
+       if (perf_boost_mode & MFC_PERF_BOOST_DVFS) {
+               if (pdata->mfc_freq_control)
+                       pm_qos_add_request(&dev->qos_req_mfc, PM_QOS_MFC_THROUGHPUT,
+                                       qos_boost_table->freq_mfc);
+               pm_qos_add_request(&dev->qos_req_int, PM_QOS_DEVICE_THROUGHPUT,
+                               qos_boost_table->freq_int);
+               pm_qos_add_request(&dev->qos_req_mif, PM_QOS_BUS_THROUGHPUT,
+                               qos_boost_table->freq_mif);
+               mfc_debug(3, "[QoS][BOOST] DVFS mfc: %d, int:%d, mif:%d\n",
+                               qos_boost_table->freq_mfc, qos_boost_table->freq_int,
+                               qos_boost_table->freq_mif);
+       }
+
+#ifdef CONFIG_EXYNOS_BTS
+       if (perf_boost_mode & MFC_PERF_BOOST_MO) {
+               if (pdata->mo_control) {
+                       bts_update_scen(BS_MFC_UHD_10BIT, 1);
+                       mfc_debug(3, "[QoS][BOOST] BTS(MO): UHD_10BIT\n");
+               }
+       }
+#endif
+
+       if (perf_boost_mode & MFC_PERF_BOOST_CPU) {
+               for (i = 0; i < qos_boost_table->num_cluster; i++) {
+                       pm_qos_add_request(&dev->qos_req_cluster[i], PM_QOS_CLUSTER0_FREQ_MIN + (i * 2),
+                                       qos_boost_table->freq_cluster[i]);
+                       mfc_debug(3, "[QoS][BOOST] CPU cluster[%d]: %d\n",
+                                       i, qos_boost_table->freq_cluster[i]);
+               }
+       }
+}
+
+void s5p_mfc_perf_boost_disable(struct s5p_mfc_dev *dev)
+{
+       struct s5p_mfc_platdata *pdata = dev->pdata;
+       int i;
+
+       if (perf_boost_mode & MFC_PERF_BOOST_DVFS) {
+               if (pdata->mfc_freq_control)
+                       pm_qos_remove_request(&dev->qos_req_mfc);
+               pm_qos_remove_request(&dev->qos_req_int);
+               pm_qos_remove_request(&dev->qos_req_mif);
+               mfc_debug(3, "[QoS][BOOST] DVFS off\n");
+       }
+
+#ifdef CONFIG_EXYNOS_BTS
+       if (perf_boost_mode & MFC_PERF_BOOST_MO) {
+               if (pdata->mo_control) {
+                       bts_update_scen(BS_MFC_UHD_10BIT, 0);
+                       mfc_debug(3, "[QoS][BOOST] BTS(MO) off\n");
+               }
+       }
+#endif
+
+       if (perf_boost_mode & MFC_PERF_BOOST_CPU) {
+               for (i = 0; i < pdata->qos_boost_table->num_cluster; i++) {
+                       pm_qos_remove_request(&dev->qos_req_cluster[i]);
+                       mfc_debug(3, "[QoS][BOOST] CPU cluster[%d] off\n", i);
+               }
+       }
+}
+
+static void mfc_qos_operate(struct s5p_mfc_ctx *ctx, int opr_type, int idx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_platdata *pdata = dev->pdata;
+       struct s5p_mfc_qos *qos_table = pdata->qos_table;
+
+       switch (opr_type) {
+       case MFC_QOS_ADD:
+               if (pdata->mfc_freq_control)
+                       pm_qos_add_request(&dev->qos_req_mfc,
+                                       PM_QOS_MFC_THROUGHPUT,
+                                       qos_table[idx].freq_mfc);
+               pm_qos_add_request(&dev->qos_req_int,
+                               PM_QOS_DEVICE_THROUGHPUT,
+                               qos_table[idx].freq_int);
+               pm_qos_add_request(&dev->qos_req_mif,
+                               PM_QOS_BUS_THROUGHPUT,
+                               qos_table[idx].freq_mif);
+
+#ifdef CONFIG_EXYNOS_BTS
+               if (pdata->mo_control) {
+                       bts_update_scen(BS_MFC_UHD_ENC60, qos_table[idx].mo_uhd_enc60_value);
+                       bts_update_scen(BS_MFC_UHD_10BIT, qos_table[idx].mo_10bit_value);
+                       bts_update_scen(BS_MFC_UHD, qos_table[idx].mo_value);
+                       MFC_TRACE_CTX("BTS(MO) update - uhd:%d, uhd_10bit:%d, uhd_enc60:%d\n",
+                                       qos_table[idx].mo_value, qos_table[idx].mo_10bit_value,
+                                       qos_table[idx].mo_uhd_enc60_value);
+                       mfc_debug(2, "[QoS] BTS(MO) update - uhd:%d, uhd_10bit:%d, uhd_enc60:%d\n",
+                                       qos_table[idx].mo_value, qos_table[idx].mo_10bit_value,
+                                       qos_table[idx].mo_uhd_enc60_value);
+               }
+#endif
+
+               atomic_set(&dev->qos_req_cur, idx + 1);
+               MFC_TRACE_CTX("QoS add[%d] - mfc:%d(%s), int:%d, mif:%d\n",
+                               idx, qos_table[idx].freq_mfc, pdata->mfc_freq_control ? "used" : "un-used",
+                               qos_table[idx].freq_int, qos_table[idx].freq_mif);
+               mfc_debug(2, "[QoS] QoS add[%d] - mfc:%d(%s), int:%d, mif:%d\n",
+                               idx, qos_table[idx].freq_mfc, pdata->mfc_freq_control ? "used" : "un-used",
+                                qos_table[idx].freq_int, qos_table[idx].freq_mif);
+               break;
+       case MFC_QOS_UPDATE:
+               if (pdata->mfc_freq_control)
+                       pm_qos_update_request(&dev->qos_req_mfc,
+                                       qos_table[idx].freq_mfc);
+               pm_qos_update_request(&dev->qos_req_int,
+                               qos_table[idx].freq_int);
+               pm_qos_update_request(&dev->qos_req_mif,
+                               qos_table[idx].freq_mif);
+
+#ifdef CONFIG_EXYNOS_BTS
+               if (pdata->mo_control) {
+                       bts_update_scen(BS_MFC_UHD_ENC60, qos_table[idx].mo_uhd_enc60_value);
+                       bts_update_scen(BS_MFC_UHD_10BIT, qos_table[idx].mo_10bit_value);
+                       bts_update_scen(BS_MFC_UHD, qos_table[idx].mo_value);
+                       MFC_TRACE_CTX("BTS(MO) update - uhd:%d, uhd_10bit:%d, uhd_enc60:%d\n",
+                                       qos_table[idx].mo_value, qos_table[idx].mo_10bit_value,
+                                       qos_table[idx].mo_uhd_enc60_value);
+                       mfc_debug(2, "[QoS] BTS(MO) update - uhd:%d, uhd_10bit:%d, uhd_enc60:%d\n",
+                                       qos_table[idx].mo_value, qos_table[idx].mo_10bit_value,
+                                       qos_table[idx].mo_uhd_enc60_value);
+               }
+#endif
+
+               atomic_set(&dev->qos_req_cur, idx + 1);
+               MFC_TRACE_CTX("QoS update[%d] - mfc:%d(%s), int:%d, mif:%d\n",
+                               idx, qos_table[idx].freq_mfc, pdata->mfc_freq_control ? "used" : "un-used",
+                               qos_table[idx].freq_int, qos_table[idx].freq_mif);
+               mfc_debug(2, "[QoS] QoS update[%d] - mfc:%d(%s), int:%d, mif:%d\n",
+                               idx, qos_table[idx].freq_mfc, pdata->mfc_freq_control ? "used" : "un-used",
+                               qos_table[idx].freq_int, qos_table[idx].freq_mif);
+               break;
+       case MFC_QOS_REMOVE:
+               if (pdata->mfc_freq_control)
+                       pm_qos_remove_request(&dev->qos_req_mfc);
+               pm_qos_remove_request(&dev->qos_req_int);
+               pm_qos_remove_request(&dev->qos_req_mif);
+
+#ifdef CONFIG_EXYNOS_BTS
+               if (pdata->mo_control) {
+                       bts_update_scen(BS_MFC_UHD_ENC60, 0);
+                       bts_update_scen(BS_MFC_UHD_10BIT, 0);
+                       bts_update_scen(BS_MFC_UHD, 0);
+               }
+
+               if (pdata->bw_control) {
+                       dev->mfc_bw.peak = 0;
+                       dev->mfc_bw.read = 0;
+                       dev->mfc_bw.write = 0;
+                       bts_update_bw(BTS_BW_MFC, dev->mfc_bw);
+               }
+#endif
+
+               atomic_set(&dev->qos_req_cur, 0);
+               MFC_TRACE_CTX("QoS remove\n");
+               mfc_debug(2, "[QoS] QoS remove\n");
+               break;
+       case MFC_QOS_BW:
+#ifdef CONFIG_EXYNOS_BTS
+               if (pdata->bw_control) {
+                       bts_update_bw(BTS_BW_MFC, dev->mfc_bw);
+                       MFC_TRACE_CTX("BTS(BW) update (peak: %d, read: %d, write: %d)\n",
+                                       dev->mfc_bw.peak, dev->mfc_bw.read, dev->mfc_bw.write);
+                       mfc_debug(2, "[QoS] BTS(BW) update (peak: %d, read: %d, write: %d)\n",
+                                       dev->mfc_bw.peak, dev->mfc_bw.read, dev->mfc_bw.write);
+               }
+#endif
+               break;
+       default:
+               mfc_err_ctx("[QoS] Unknown request for opr [%d]\n", opr_type);
+               break;
+       }
+}
+
+#ifdef CONFIG_EXYNOS_BTS
+static void mfc_qos_set(struct s5p_mfc_ctx *ctx, struct bts_bw *mfc_bw, int i)
+#else
+static void mfc_qos_set(struct s5p_mfc_ctx *ctx, int i)
+#endif
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_platdata *pdata = dev->pdata;
+       struct s5p_mfc_qos *qos_table = pdata->qos_table;
+
+       mfc_debug(2, "[QoS] table[%d] covered mb %d ~ %d (mfc: %d, int:%d, mif:%d)\n",
+                       i, qos_table[i].threshold_mb,
+                       i == pdata->num_qos_steps - 1 ?
+                       pdata->max_mb : qos_table[i + 1].threshold_mb,
+                       qos_table[i].freq_mfc, qos_table[i].freq_int,
+                       qos_table[i].freq_mif);
+
+#ifdef CONFIG_EXYNOS_BTS
+       if (mfc_bw->peak != dev->mfc_bw.peak) {
+               dev->mfc_bw.peak = mfc_bw->peak;
+               dev->mfc_bw.read = mfc_bw->read;
+               dev->mfc_bw.write = mfc_bw->write;
+               mfc_qos_operate(ctx, MFC_QOS_BW, i);
+       }
+#endif
+
+       if (atomic_read(&dev->qos_req_cur) == 0)
+               mfc_qos_operate(ctx, MFC_QOS_ADD, i);
+       else if (atomic_read(&dev->qos_req_cur) != (i + 1))
+               mfc_qos_operate(ctx, MFC_QOS_UPDATE, i);
+}
+
+static inline unsigned long mfc_qos_get_weighted_mb(struct s5p_mfc_ctx *ctx,
+                                               unsigned long mb)
+{
+       struct s5p_mfc_enc *enc = ctx->enc_priv;
+       struct s5p_mfc_dec *dec = ctx->dec_priv;
+       struct s5p_mfc_enc_params *p;
+       u32 num_planes = ctx->dst_fmt->num_planes;
+       int weight = 1000;
+       unsigned long weighted_mb;
+
+       switch (ctx->codec_mode) {
+       case S5P_FIMV_CODEC_H264_DEC:
+       case S5P_FIMV_CODEC_H264_MVC_DEC:
+       case S5P_FIMV_CODEC_H264_ENC:
+       case S5P_FIMV_CODEC_H264_MVC_ENC:
+       case S5P_FIMV_CODEC_VP8_DEC:
+       case S5P_FIMV_CODEC_VP8_ENC:
+               if (num_planes == 3)
+                       weight = (weight * 100) / MFC_QOS_WEIGHT_3PLANE;
+               break;
+
+       case S5P_FIMV_CODEC_HEVC_DEC:
+       case S5P_FIMV_CODEC_HEVC_ENC:
+       case S5P_FIMV_CODEC_VP9_DEC:
+       case S5P_FIMV_CODEC_VP9_ENC:
+       case S5P_FIMV_CODEC_BPG_DEC:
+       case S5P_FIMV_CODEC_BPG_ENC:
+               if (num_planes == 3) {
+                       weight = (weight * 100) / MFC_QOS_WEIGHT_3PLANE;
+               } else {
+                       if (ctx->is_10bit)
+                               weight = (weight * 100) / MFC_QOS_WEIGHT_10BIT;
+                       else if (ctx->is_422)
+                               weight = (weight * 100) / MFC_QOS_WEIGHT_422_10INTRA;
+               }
+               break;
+
+       case S5P_FIMV_CODEC_MPEG4_DEC:
+       case S5P_FIMV_CODEC_FIMV1_DEC:
+       case S5P_FIMV_CODEC_FIMV2_DEC:
+       case S5P_FIMV_CODEC_FIMV3_DEC:
+       case S5P_FIMV_CODEC_FIMV4_DEC:
+       case S5P_FIMV_CODEC_H263_DEC:
+       case S5P_FIMV_CODEC_VC1_RCV_DEC:
+       case S5P_FIMV_CODEC_VC1_DEC:
+       case S5P_FIMV_CODEC_MPEG2_DEC:
+       case S5P_FIMV_CODEC_MPEG4_ENC:
+       case S5P_FIMV_CODEC_H263_ENC:
+               weight = (weight * 100) / MFC_QOS_WEIGHT_OTHER_CODEC;
+               break;
+
+       default:
+               mfc_err_ctx("[QoS] wrong codec_mode (%d), no weight\n", ctx->codec_mode);
+       }
+
+       if (enc) {
+               p = &enc->params;
+               if ((IS_H264_ENC(ctx) || IS_HEVC_ENC(ctx)) && p->num_b_frame) {
+                       weight = (weight * 100) / MFC_QOS_WEIGHT_BFRAME;
+                       mfc_debug(3, "[QoS] weight: B frame encoding\n");
+               }
+               if ((IS_H264_ENC(ctx) || IS_HEVC_ENC(ctx) || IS_VP8_ENC(ctx) ||
+                                       IS_VP9_ENC(ctx)) && (p->num_refs_for_p >= 2)) {
+                       weight = (weight * 100) / MFC_QOS_WEIGHT_NUM_OF_REF;
+                       mfc_debug(3, "[QoS] weight: num of ref >= 2\n");
+               }
+       }
+       if (dec) {
+               if (dec->num_of_tile_over_4) {
+                       weight = (weight * 100) / MFC_QOS_WEIGHT_NUM_OF_TILE;
+                       mfc_debug(3, "[QoS] weight: num of tile >= 4\n");
+               }
+       }
+
+       weighted_mb = (mb * weight) / 1000;
+       mfc_debug(3, "[QoS] weight: %d.%03d, codec: %d, num planes: %d, "
+                       "10bit: %d, 422format: %d (mb: %ld)\n",
+                       weight / 1000, weight % 1000, ctx->codec_mode,
+                       num_planes, ctx->is_10bit, ctx->is_422,
+                       weighted_mb);
+
+
+       return weighted_mb;
+}
+
+static inline unsigned long mfc_qos_get_mb_per_second(struct s5p_mfc_ctx *ctx)
+{
+       unsigned long mb_width, mb_height, fps, mb;
+
+       mb_width = (ctx->crop_width + 15) / 16;
+       mb_height = (ctx->crop_height + 15) / 16;
+       fps = ctx->framerate / 1000;
+
+       mb = mb_width * mb_height * fps;
+       mfc_debug(4, "[QoS] ctx[%d:%s] %d x %d @ %ld fps (mb: %ld)\n",
+                       ctx->num, ctx->type == MFCINST_ENCODER ? "ENC" : "DEC",
+                       ctx->crop_width, ctx->crop_height, fps, mb);
+
+       return mfc_qos_get_weighted_mb(ctx, mb);
+}
+
+#ifdef CONFIG_EXYNOS_BTS
+static struct s5p_mfc_qos_bw mfc_bw_info = {
+       /*                                peak   read   write   (KB/UHD frame) */
+       .h264_dec_uhd_bw        =       { 38131, 40206, 24870 },
+       .hevc_dec_uhd_bw        =       { 35055, 33741, 20511 },
+       .hevc_dec_uhd_10bit_bw  =       { 38643, 36428, 25491 },
+       .vp8_dec_uhd_bw         =       { 28693, 30464, 22331 },
+       .vp9_dec_uhd_bw         =       { 21464, 22160, 19747 },
+       .mpeg4_dec_uhd_bw       =       { 31567, 25191, 15961 },
+       .h264_enc_uhd_bw        =       { 62543, 75230, 13080 },
+       .hevc_enc_uhd_bw        =       { 54863, 65417, 11422 },
+       .hevc_enc_uhd_10bit_bw  =       { 68011, 79367, 14688 },
+       .vp8_enc_uhd_bw         =       { 63970, 67281, 22508 },
+       .vp9_enc_uhd_bw         =       { 84443, 71588, 19337 },
+       .mpeg4_enc_uhd_bw       =       { 44633, 55310, 9599  },
+};
+
+static void mfc_qos_get_bw_per_second(struct s5p_mfc_ctx *ctx, struct bts_bw *mfc_bw)
+{
+       struct mfc_qos_bw_data bw_data;
+       unsigned long mb_width, mb_height, fps, mb;
+       unsigned long peak_bw_per_sec;
+       unsigned long read_bw_per_sec;
+       unsigned long write_bw_per_sec;
+       unsigned long mb_count_per_uhd_frame = MB_COUNT_PER_UHD_FRAME;
+       unsigned long max_fps_per_uhd_frame = MAX_FPS_PER_UHD_FRAME;
+
+       mb_width = (ctx->crop_width + 15) / 16;
+       mb_height = (ctx->crop_height + 15) / 16;
+       fps = ctx->framerate / 1000;
+
+       mb = mb_width * mb_height * fps;
+
+       switch (ctx->codec_mode) {
+       case S5P_FIMV_CODEC_H264_DEC:
+       case S5P_FIMV_CODEC_H264_MVC_DEC:
+               bw_data = mfc_bw_info.h264_dec_uhd_bw;
+               break;
+       case S5P_FIMV_CODEC_H264_ENC:
+       case S5P_FIMV_CODEC_H264_MVC_ENC:
+               bw_data = mfc_bw_info.h264_enc_uhd_bw;
+               break;
+       case S5P_FIMV_CODEC_HEVC_DEC:
+       case S5P_FIMV_CODEC_BPG_DEC:
+               if (ctx->is_10bit)
+                       bw_data = mfc_bw_info.hevc_dec_uhd_10bit_bw;
+               else
+                       bw_data = mfc_bw_info.hevc_dec_uhd_bw;
+               break;
+       case S5P_FIMV_CODEC_HEVC_ENC:
+       case S5P_FIMV_CODEC_BPG_ENC:
+               if (ctx->is_10bit)
+                       bw_data = mfc_bw_info.hevc_enc_uhd_10bit_bw;
+               else
+                       bw_data = mfc_bw_info.hevc_enc_uhd_bw;
+               break;
+       case S5P_FIMV_CODEC_MPEG4_DEC:
+       case S5P_FIMV_CODEC_FIMV1_DEC:
+       case S5P_FIMV_CODEC_FIMV2_DEC:
+       case S5P_FIMV_CODEC_FIMV3_DEC:
+       case S5P_FIMV_CODEC_FIMV4_DEC:
+       case S5P_FIMV_CODEC_H263_DEC:
+       case S5P_FIMV_CODEC_VC1_RCV_DEC:
+       case S5P_FIMV_CODEC_VC1_DEC:
+       case S5P_FIMV_CODEC_MPEG2_DEC:
+               bw_data = mfc_bw_info.mpeg4_dec_uhd_bw;
+               break;
+       case S5P_FIMV_CODEC_VP8_DEC:
+               bw_data = mfc_bw_info.vp8_dec_uhd_bw;
+               break;
+       case S5P_FIMV_CODEC_VP9_DEC:
+               bw_data = mfc_bw_info.vp9_dec_uhd_bw;
+               break;
+       case S5P_FIMV_CODEC_MPEG4_ENC:
+       case S5P_FIMV_CODEC_H263_ENC:
+               bw_data = mfc_bw_info.mpeg4_enc_uhd_bw;
+               break;
+       case S5P_FIMV_CODEC_VP8_ENC:
+               bw_data = mfc_bw_info.vp8_enc_uhd_bw;
+               break;
+       case S5P_FIMV_CODEC_VP9_ENC:
+               bw_data = mfc_bw_info.vp9_enc_uhd_bw;
+               break;
+       default:
+               bw_data.peak = 0;
+               bw_data.read = 0;
+               bw_data.write = 0;
+               mfc_err_ctx("[QoS] wrong codec_mode (%d)\n", ctx->codec_mode);
+       }
+
+       if (mb > (mb_count_per_uhd_frame * max_fps_per_uhd_frame)) {
+               mfc_debug(4, "[QoS] fix upper mb bound (mb: %ld, fps: %ld)\n", mb, fps);
+               mb = mb_count_per_uhd_frame * max_fps_per_uhd_frame;
+       }
+
+       peak_bw_per_sec = (bw_data.peak * mb) / mb_count_per_uhd_frame;
+       read_bw_per_sec = (bw_data.read * mb) / mb_count_per_uhd_frame;
+       write_bw_per_sec = (bw_data.write * mb) / mb_count_per_uhd_frame;
+
+       if (peak_bw_per_sec == 0) {
+               mfc_debug(4, "[QoS] fix lower peak bound (mb: %ld, fps: %ld)\n", mb, fps);
+               peak_bw_per_sec = MIN_BW_PER_SEC;
+       }
+       if (read_bw_per_sec == 0) {
+               mfc_debug(4, "[QoS] fix lower read bound (mb: %ld, fps: %ld)\n", mb, fps);
+               read_bw_per_sec = MIN_BW_PER_SEC;
+       }
+       if (write_bw_per_sec == 0) {
+               mfc_debug(4, "[QoS] fix lower write bound (mb: %ld, fps: %ld)\n", mb, fps);
+               write_bw_per_sec = MIN_BW_PER_SEC;
+       }
+
+       mfc_bw->peak = (unsigned int)peak_bw_per_sec;
+       mfc_bw->read = (unsigned int)read_bw_per_sec;
+       mfc_bw->write = (unsigned int)write_bw_per_sec;
+}
+#endif
+
+void s5p_mfc_qos_on(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_platdata *pdata = dev->pdata;
+       struct s5p_mfc_qos *qos_table = pdata->qos_table;
+       struct s5p_mfc_ctx *qos_ctx;
+       unsigned long hw_mb = 0, total_mb = 0, total_fps = 0;
+       unsigned int fw_time, sw_time;
+       int i, found = 0, enc_found = 0;
+       int start_qos_step;
+#ifdef CONFIG_EXYNOS_BTS
+       struct bts_bw mfc_bw, mfc_bw_ctx;
+#endif
+
+       if (perf_boost_mode) {
+               mfc_info_ctx("[QoS][BOOST] skip control\n");
+               return;
+       }
+
+       list_for_each_entry(qos_ctx, &dev->qos_queue, qos_list)
+               if (qos_ctx == ctx)
+                       found = 1;
+
+       if (!found)
+               list_add_tail(&ctx->qos_list, &dev->qos_queue);
+
+#ifdef CONFIG_EXYNOS_BTS
+       mfc_bw.peak = 0;
+       mfc_bw.read = 0;
+       mfc_bw.write = 0;
+#endif
+       /* get the hw macroblock */
+       list_for_each_entry(qos_ctx, &dev->qos_queue, qos_list) {
+               if (OVER_UHD_ENC60(qos_ctx))
+                       enc_found = 1;
+               hw_mb += mfc_qos_get_mb_per_second(qos_ctx);
+               total_fps += (qos_ctx->framerate / 1000);
+#ifdef CONFIG_EXYNOS_BTS
+               mfc_qos_get_bw_per_second(qos_ctx, &mfc_bw_ctx);
+               mfc_bw.peak += mfc_bw_ctx.peak;
+               mfc_bw.read += mfc_bw_ctx.read;
+               mfc_bw.write += mfc_bw_ctx.write;
+#endif
+       }
+
+       start_qos_step = pdata->num_qos_steps;
+       if (enc_found)
+               start_qos_step = pdata->max_qos_steps;
+
+       /* search the suitable qos table */
+       for (i = start_qos_step - 1; i >= 0; i--) {
+               fw_time = qos_table[i].time_fw;
+               sw_time = (MFC_DRV_TIME + fw_time);
+
+               if ((total_fps * sw_time) >= 1000000)
+                       total_mb = pdata->max_mb;
+               else
+                       total_mb = ((1000000 * hw_mb) / (1000000 - (total_fps * sw_time)));
+
+               mfc_debug(4, "[QoS] table[%d] fw_time: %dus, hw_mb: %ld, "
+                               "sw_time: %d, total_fps: %ld, total_mb: %ld\n",
+                               i, fw_time, hw_mb, sw_time, total_fps, total_mb);
+
+               if ((total_mb > qos_table[i].threshold_mb) || (i == 0))
+                       break;
+       }
+
+       if (total_mb > pdata->max_mb)
+               mfc_debug(4, "[QoS] overspec mb %ld > %d\n", total_mb, pdata->max_mb);
+
+#ifdef CONFIG_EXYNOS_BTS
+       mfc_qos_set(ctx, &mfc_bw, i);
+#else
+       mfc_qos_set(ctx, i);
+#endif
+}
+
+void s5p_mfc_qos_off(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_platdata *pdata = dev->pdata;
+       struct s5p_mfc_qos *qos_table = pdata->qos_table;
+       struct s5p_mfc_ctx *qos_ctx;
+       unsigned long hw_mb = 0, total_mb = 0, total_fps = 0;
+       unsigned int fw_time, sw_time;
+       int i, found = 0, enc_found = 0;
+       int start_qos_step;
+#ifdef CONFIG_EXYNOS_BTS
+       struct bts_bw mfc_bw, mfc_bw_ctx;
+#endif
+
+       if (perf_boost_mode) {
+               mfc_info_ctx("[QoS][BOOST] skip control\n");
+               return;
+       }
+
+       if (list_empty(&dev->qos_queue)) {
+               if (atomic_read(&dev->qos_req_cur) != 0) {
+                       mfc_err_ctx("[QoS] MFC request count is wrong!\n");
+                       mfc_qos_operate(ctx, MFC_QOS_REMOVE, 0);
+               }
+               return;
+       }
+
+#ifdef CONFIG_EXYNOS_BTS
+       mfc_bw.peak = 0;
+       mfc_bw.read = 0;
+       mfc_bw.write = 0;
+#endif
+       /* get the hw macroblock */
+       list_for_each_entry(qos_ctx, &dev->qos_queue, qos_list) {
+               if (qos_ctx == ctx) {
+                       found = 1;
+                       continue;
+               }
+
+               if (OVER_UHD_ENC60(qos_ctx))
+                       enc_found = 1;
+               hw_mb += mfc_qos_get_mb_per_second(qos_ctx);
+               total_fps += (qos_ctx->framerate / 1000);
+#ifdef CONFIG_EXYNOS_BTS
+               mfc_qos_get_bw_per_second(qos_ctx, &mfc_bw_ctx);
+               mfc_bw.peak += mfc_bw_ctx.peak;
+               mfc_bw.read += mfc_bw_ctx.read;
+               mfc_bw.write += mfc_bw_ctx.write;
+#endif
+       }
+
+       start_qos_step = pdata->num_qos_steps;
+       if (enc_found)
+               start_qos_step = pdata->max_qos_steps;
+
+       /* search the suitable qos table */
+       for (i = start_qos_step - 1; i >= 0; i--) {
+               fw_time = qos_table[i].time_fw;
+               sw_time = (MFC_DRV_TIME + fw_time);
+
+               if ((total_fps * sw_time) >= 1000000)
+                       total_mb = pdata->max_mb;
+               else
+                       total_mb = ((1000000 * hw_mb) / (1000000 - (total_fps * sw_time)));
+
+               mfc_debug(4, "[QoS] table[%d] fw_time: %dus, hw_mb: %ld, "
+                               "sw_time: %d, total_fps: %ld, total_mb: %ld\n",
+                               i, fw_time, hw_mb, sw_time, total_fps, total_mb);
+
+               if ((total_mb > qos_table[i].threshold_mb) || (total_mb == 0) || (i == 0))
+                       break;
+       }
+
+       if (total_mb > pdata->max_mb)
+               mfc_debug(4, "[QoS] overspec mb %ld > %d\n", total_mb, pdata->max_mb);
+
+       if (found)
+               list_del(&ctx->qos_list);
+
+       if (list_empty(&dev->qos_queue) || total_mb == 0)
+               mfc_qos_operate(ctx, MFC_QOS_REMOVE, 0);
+       else
+#ifdef CONFIG_EXYNOS_BTS
+               mfc_qos_set(ctx, &mfc_bw, i);
+#else
+               mfc_qos_set(ctx, i);
+#endif
+}
+#endif
+
+#define COL_FRAME_RATE         0
+#define COL_FRAME_INTERVAL     1
+
+#define MFC_MAX_INTERVAL       (2 * USEC_PER_SEC)
+
+/*
+ * A framerate table determines framerate by the interval(us) of each frame.
+ * Framerate is not accurate, just rough value to seperate overload section.
+ * Base line of each section are selected from middle value.
+ * 40fps(25000us), 80fps(12500us), 144fps(6940us)
+ * 205fps(4860us), 320fps(3125us)
+ *
+ * interval(us) | 0         3125          4860          6940          12500         25000          |
+ * framerate    |    480fps   |    240fps   |    180fps   |    120fps   |    60fps    |    30fps   |
+ */
+static unsigned long framerate_table[][2] = {
+       {  30000, 25000 },
+       {  60000, 12500 },
+       { 120000,  6940 },
+       { 180000,  4860 },
+       { 240000,  3125 },
+       { 480000,     0 },
+};
+
+static inline unsigned long mfc_qos_timeval_diff(struct timeval *to,
+                                       struct timeval *from)
+{
+       return (to->tv_sec * USEC_PER_SEC + to->tv_usec)
+               - (from->tv_sec * USEC_PER_SEC + from->tv_usec);
+}
+
+static unsigned long mfc_qos_get_framerate_by_interval(int interval)
+{
+       unsigned long i;
+
+       /* if the interval is too big (2sec), framerate set to 0 */
+       if (interval > MFC_MAX_INTERVAL)
+               return 0;
+
+       for (i = 0; i < ARRAY_SIZE(framerate_table); i++) {
+               if (interval > framerate_table[i][COL_FRAME_INTERVAL])
+                       return framerate_table[i][COL_FRAME_RATE];
+       }
+
+       return 0;
+}
+
+/* Return the minimum interval between previous and next entry */
+static int mfc_qos_get_interval(struct list_head *head, struct list_head *entry)
+{
+       int prev_interval = MFC_MAX_INTERVAL, next_interval = MFC_MAX_INTERVAL;
+       struct mfc_timestamp *prev_ts, *next_ts, *curr_ts;
+
+       curr_ts = list_entry(entry, struct mfc_timestamp, list);
+
+       if (entry->prev != head) {
+               prev_ts = list_entry(entry->prev, struct mfc_timestamp, list);
+               prev_interval = mfc_qos_timeval_diff(&curr_ts->timestamp, &prev_ts->timestamp);
+       }
+
+       if (entry->next != head) {
+               next_ts = list_entry(entry->next, struct mfc_timestamp, list);
+               next_interval = mfc_qos_timeval_diff(&next_ts->timestamp, &curr_ts->timestamp);
+       }
+
+       return (prev_interval < next_interval ? prev_interval : next_interval);
+}
+
+static int mfc_qos_add_timestamp(struct s5p_mfc_ctx *ctx,
+                       struct timeval *time, struct list_head *head)
+{
+       int replace_entry = 0;
+       struct mfc_timestamp *curr_ts = &ctx->ts_array[ctx->ts_count];
+
+       if (ctx->ts_is_full) {
+               /* Replace the entry if list of array[ts_count] is same as entry */
+               if (&curr_ts->list == head)
+                       replace_entry = 1;
+               else
+                       list_del(&curr_ts->list);
+       }
+
+       memcpy(&curr_ts->timestamp, time, sizeof(struct timeval));
+       if (!replace_entry)
+               list_add(&curr_ts->list, head);
+       curr_ts->interval =
+               mfc_qos_get_interval(&ctx->ts_list, &curr_ts->list);
+       curr_ts->index = ctx->ts_count;
+       ctx->ts_count++;
+
+       if (ctx->ts_count == MFC_TIME_INDEX) {
+               ctx->ts_is_full = 1;
+               ctx->ts_count %= MFC_TIME_INDEX;
+       }
+
+       return 0;
+}
+
+static unsigned long mfc_qos_get_fps_by_timestamp(struct s5p_mfc_ctx *ctx, struct timeval *time)
+{
+       struct mfc_timestamp *temp_ts;
+       int found;
+       int index = 0;
+       int min_interval = MFC_MAX_INTERVAL;
+       int time_diff;
+       unsigned long max_framerate;
+
+       if (debug_ts == 1) {
+               /* Debug info */
+               mfc_info_ctx("===================[TS]===================\n");
+               mfc_info_ctx("[TS] New timestamp = %ld.%06ld, count = %d \n",
+                       time->tv_sec, time->tv_usec, ctx->ts_count);
+       }
+
+       if (IS_BUFFER_BATCH_MODE(ctx)) {
+               if (debug_ts == 1)
+                       mfc_info_ctx("[BUFCON][TS] Keep framerate if buffer batch mode is used, %ldfps\n",
+                                       ctx->framerate);
+               return ctx->framerate;
+       }
+
+       if (list_empty(&ctx->ts_list)) {
+               mfc_qos_add_timestamp(ctx, time, &ctx->ts_list);
+               return mfc_qos_get_framerate_by_interval(0);
+       } else {
+               found = 0;
+               list_for_each_entry_reverse(temp_ts, &ctx->ts_list, list) {
+                       time_diff = timeval_compare(time, &temp_ts->timestamp);
+                       if (time_diff == 0) {
+                               /* Do not add if same timestamp already exists */
+                               found = 1;
+                               break;
+                       } else if (time_diff > 0) {
+                               /* Add this after temp_ts */
+                               mfc_qos_add_timestamp(ctx, time, &temp_ts->list);
+                               found = 1;
+                               break;
+                       }
+               }
+
+               if (!found)     /* Add this at first entry */
+                       mfc_qos_add_timestamp(ctx, time, &ctx->ts_list);
+       }
+
+       list_for_each_entry(temp_ts, &ctx->ts_list, list) {
+               if (temp_ts->interval < min_interval)
+                       min_interval = temp_ts->interval;
+       }
+
+       max_framerate = mfc_qos_get_framerate_by_interval(min_interval);
+
+       if (debug_ts == 1) {
+               /* Debug info */
+               index = 0;
+               list_for_each_entry(temp_ts, &ctx->ts_list, list) {
+                       mfc_info_ctx("[TS] [%d] timestamp [i:%d]: %ld.%06ld\n",
+                                       index, temp_ts->index,
+                                       temp_ts->timestamp.tv_sec,
+                                       temp_ts->timestamp.tv_usec);
+                       index++;
+               }
+               mfc_info_ctx("[TS] Min interval = %d, It is %ld fps\n",
+                               min_interval, max_framerate);
+       } else if (debug_ts == 2) {
+               mfc_info_ctx("[TS] Min interval = %d, It is %ld fps\n",
+                               min_interval, max_framerate);
+       }
+
+       if (!ctx->ts_is_full) {
+               if (debug_ts == 1)
+                       mfc_info_ctx("[TS] ts doesn't full, keep %ld fps\n", ctx->framerate);
+               return ctx->framerate;
+       }
+
+       return max_framerate;
+}
+
+void s5p_mfc_qos_update_framerate(struct s5p_mfc_ctx *ctx)
+{
+       if (ctx->last_framerate != 0 && ctx->last_framerate != ctx->framerate) {
+               mfc_debug(2, "[QoS] fps changed: %ld -> %ld, qos ratio: %d\n",
+                               ctx->framerate, ctx->last_framerate, ctx->qos_ratio);
+               ctx->framerate = ctx->last_framerate;
+               s5p_mfc_qos_on(ctx);
+       }
+}
+
+void s5p_mfc_qos_update_last_framerate(struct s5p_mfc_ctx *ctx, u64 timestamp)
+{
+       struct timeval time;
+
+       time.tv_sec = timestamp / NSEC_PER_SEC;
+       time.tv_usec = (timestamp - (time.tv_sec * NSEC_PER_SEC)) / NSEC_PER_USEC;
+
+       ctx->last_framerate = mfc_qos_get_fps_by_timestamp(ctx, &time);
+       if (ctx->last_framerate > MFC_MAX_FPS)
+               ctx->last_framerate = MFC_MAX_FPS;
+       ctx->last_framerate = (ctx->qos_ratio * ctx->last_framerate) / 100;
+}
diff --git a/drivers/media/platform/exynos/mfc/mfc_qos.h b/drivers/media/platform/exynos/mfc/mfc_qos.h
new file mode 100644 (file)
index 0000000..783bda8
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_qos.h
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __MFC_QOS_H
+#define __MFC_QOS_H __FILE__
+
+#include "mfc_common.h"
+
+#define MFC_MAX_FPS                    (480000)
+#define DEC_DEFAULT_FPS                        (240000)
+#define ENC_DEFAULT_FPS                        (240000)
+#define ENC_DEFAULT_CAM_CAPTURE_FPS    (60000)
+
+#define MB_COUNT_PER_UHD_FRAME         32400
+#define MAX_FPS_PER_UHD_FRAME          120
+#define MIN_BW_PER_SEC                 1
+
+#define MFC_DRV_TIME                   500
+
+#define MFC_QOS_WEIGHT_3PLANE          80
+#define MFC_QOS_WEIGHT_OTHER_CODEC     25
+#define MFC_QOS_WEIGHT_10BIT           75
+#define MFC_QOS_WEIGHT_422_10INTRA     70
+#define MFC_QOS_WEIGHT_BFRAME          50
+#define MFC_QOS_WEIGHT_NUM_OF_REF      50
+#define MFC_QOS_WEIGHT_NUM_OF_TILE     75
+
+#ifdef CONFIG_MFC_USE_BUS_DEVFREQ
+void s5p_mfc_perf_boost_enable(struct s5p_mfc_dev *dev);
+void s5p_mfc_perf_boost_disable(struct s5p_mfc_dev *dev);
+void s5p_mfc_qos_on(struct s5p_mfc_ctx *ctx);
+void s5p_mfc_qos_off(struct s5p_mfc_ctx *ctx);
+#else
+#define s5p_mfc_perf_boost_enable(dev) do {} while (0)
+#define s5p_mfc_perf_boost_disable(dev)        do {} while (0)
+#define s5p_mfc_qos_on(ctx)            do {} while (0)
+#define s5p_mfc_qos_off(ctx)           do {} while (0)
+#endif
+
+void s5p_mfc_qos_update_framerate(struct s5p_mfc_ctx *ctx);
+void s5p_mfc_qos_update_last_framerate(struct s5p_mfc_ctx *ctx, u64 timestamp);
+
+static inline void s5p_mfc_qos_reset_framerate(struct s5p_mfc_ctx *ctx)
+{
+       if (ctx->type == MFCINST_DECODER)
+               ctx->framerate = DEC_DEFAULT_FPS;
+       else if (ctx->type == MFCINST_ENCODER)
+               ctx->framerate = ENC_DEFAULT_FPS;
+}
+
+static inline void s5p_mfc_qos_reset_last_framerate(struct s5p_mfc_ctx *ctx)
+{
+       ctx->last_framerate = 0;
+}
+
+static inline void s5p_mfc_qos_set_framerate(struct s5p_mfc_ctx *ctx, int rate)
+{
+       ctx->framerate = rate;
+}
+
+static inline int s5p_mfc_qos_get_framerate(struct s5p_mfc_ctx *ctx)
+{
+       return ctx->framerate;
+}
+
+#endif /* __MFC_QOS_H */
diff --git a/drivers/media/platform/exynos/mfc/mfc_queue.c b/drivers/media/platform/exynos/mfc/mfc_queue.c
new file mode 100644 (file)
index 0000000..2dec6ab
--- /dev/null
@@ -0,0 +1,1066 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_queue.c
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include "mfc_queue.h"
+
+#include "mfc_utils.h"
+#include "mfc_mem.h"
+
+void s5p_mfc_add_tail_buf(spinlock_t *plock, struct s5p_mfc_buf_queue *queue,
+               struct s5p_mfc_buf *mfc_buf)
+{
+       unsigned long flags;
+
+       if (!mfc_buf) {
+               mfc_err_dev("mfc_buf is NULL!\n");
+               return;
+       }
+
+       spin_lock_irqsave(plock, flags);
+
+       mfc_buf->used = 0;
+       list_add_tail(&mfc_buf->list, &queue->head);
+       queue->count++;
+
+       spin_unlock_irqrestore(plock, flags);
+}
+
+int s5p_mfc_peek_buf_csd(spinlock_t *plock, struct s5p_mfc_buf_queue *queue)
+{
+       unsigned long flags;
+       int csd = -1;
+       struct s5p_mfc_buf *mfc_buf = NULL;
+
+       spin_lock_irqsave(plock, flags);
+
+       if (list_empty(&queue->head)) {
+               mfc_debug(2, "queue is empty\n");
+               spin_unlock_irqrestore(plock, flags);
+               return csd;
+       }
+
+       mfc_buf = list_entry(queue->head.next, struct s5p_mfc_buf, list);
+
+       csd = mfc_buf->vb.reserved2 & FLAG_CSD ? 1 : 0;
+
+       mfc_debug(2, "addr[0]: 0x%08llx\n", mfc_buf->addr[0][0]);
+
+       spin_unlock_irqrestore(plock, flags);
+       return csd;
+}
+
+struct s5p_mfc_buf *s5p_mfc_get_buf(spinlock_t *plock, struct s5p_mfc_buf_queue *queue,
+               enum s5p_mfc_queue_used_type used)
+{
+       unsigned long flags;
+       struct s5p_mfc_buf *mfc_buf = NULL;
+
+       spin_lock_irqsave(plock, flags);
+
+       if (list_empty(&queue->head)) {
+               mfc_debug(2, "queue is empty\n");
+               spin_unlock_irqrestore(plock, flags);
+               return NULL;
+       }
+
+       mfc_buf = list_entry(queue->head.next, struct s5p_mfc_buf, list);
+
+       if ((used == MFC_BUF_RESET_USED) || (used == MFC_BUF_SET_USED))
+               mfc_buf->used = used;
+
+       mfc_debug(2, "addr[0]: 0x%08llx\n", mfc_buf->addr[0][0]);
+
+       spin_unlock_irqrestore(plock, flags);
+       return mfc_buf;
+}
+
+struct s5p_mfc_buf *s5p_mfc_get_del_buf(spinlock_t *plock, struct s5p_mfc_buf_queue *queue,
+               enum s5p_mfc_queue_used_type used)
+{
+       unsigned long flags;
+       struct s5p_mfc_buf *mfc_buf = NULL;
+
+       spin_lock_irqsave(plock, flags);
+
+       if (list_empty(&queue->head)) {
+               mfc_debug(2, "queue is empty\n");
+               spin_unlock_irqrestore(plock, flags);
+               return NULL;
+       }
+
+       mfc_buf = list_entry(queue->head.next, struct s5p_mfc_buf, list);
+
+       if ((used == MFC_BUF_RESET_USED) || (used == MFC_BUF_SET_USED))
+               mfc_buf->used = used;
+
+       mfc_debug(2, "addr[0]: 0x%08llx\n", mfc_buf->addr[0][0]);
+
+       list_del(&mfc_buf->list);
+       queue->count--;
+
+       spin_unlock_irqrestore(plock, flags);
+       return mfc_buf;
+}
+
+struct s5p_mfc_buf *s5p_mfc_get_del_if_consumed(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf_queue *queue,
+               unsigned long consumed, unsigned int min_bytes, int error, int *deleted)
+{
+       unsigned long flags;
+       struct s5p_mfc_buf *mfc_buf = NULL;
+       struct s5p_mfc_dec *dec = ctx->dec_priv;
+       unsigned long remained;
+
+       spin_lock_irqsave(&ctx->buf_queue_lock, flags);
+
+       if (list_empty(&queue->head)) {
+               mfc_debug(2, "queue is empty\n");
+               spin_unlock_irqrestore(&ctx->buf_queue_lock, flags);
+               return NULL;
+       }
+
+       mfc_buf = list_entry(queue->head.next, struct s5p_mfc_buf, list);
+
+       mfc_debug(2, "addr[0]: 0x%08llx\n", mfc_buf->addr[0][0]);
+
+       if (dec->remained_size)
+               remained = dec->remained_size - consumed;
+       else
+               remained = mfc_buf->vb.vb2_buf.planes[0].bytesused - consumed;
+
+       mfc_debug(2, "[MULTIFRAME] Total Size: %d, consumed: %ld, remained: %ld\n",
+               mfc_buf->vb.vb2_buf.planes[0].bytesused, consumed, remained);
+
+       if ((consumed > 0) && (remained > min_bytes) && (error == 0) &&
+                       (mfc_buf->vb.vb2_buf.planes[0].bytesused > consumed)){
+               /* do not delete from queue */
+               *deleted = 0;
+       } else {
+               list_del(&mfc_buf->list);
+               queue->count--;
+
+               *deleted = 1;
+       }
+
+       spin_unlock_irqrestore(&ctx->buf_queue_lock, flags);
+       return mfc_buf;
+}
+
+struct s5p_mfc_buf *s5p_mfc_get_move_buf(spinlock_t *plock,
+               struct s5p_mfc_buf_queue *to_queue, struct s5p_mfc_buf_queue *from_queue,
+               enum s5p_mfc_queue_used_type used, enum s5p_mfc_queue_top_type top)
+{
+       unsigned long flags;
+       struct s5p_mfc_buf *mfc_buf = NULL;
+
+       spin_lock_irqsave(plock, flags);
+
+       if (list_empty(&from_queue->head)) {
+               mfc_debug(2, "from_queue is empty\n");
+               spin_unlock_irqrestore(plock, flags);
+               return NULL;
+       }
+
+       mfc_buf = list_entry(from_queue->head.next, struct s5p_mfc_buf, list);
+
+       if ((used == MFC_BUF_RESET_USED) || (used == MFC_BUF_SET_USED))
+               mfc_buf->used = used;
+
+       mfc_debug(2, "addr[0]: 0x%08llx\n", mfc_buf->addr[0][0]);
+
+       list_del(&mfc_buf->list);
+       from_queue->count--;
+
+       if (top == MFC_QUEUE_ADD_TOP)
+               list_add(&mfc_buf->list, &to_queue->head);
+       else
+               list_add_tail(&mfc_buf->list, &to_queue->head);
+
+       to_queue->count++;
+
+       spin_unlock_irqrestore(plock, flags);
+       return mfc_buf;
+}
+
+struct s5p_mfc_buf *s5p_mfc_get_move_buf_used(spinlock_t *plock,
+               struct s5p_mfc_buf_queue *to_queue, struct s5p_mfc_buf_queue *from_queue)
+{
+       unsigned long flags;
+       struct s5p_mfc_buf *mfc_buf = NULL;
+
+       spin_lock_irqsave(plock, flags);
+
+       if (list_empty(&from_queue->head)) {
+               mfc_debug(2, "from_queue is empty\n");
+               spin_unlock_irqrestore(plock, flags);
+               return NULL;
+       }
+
+       mfc_buf = list_entry(from_queue->head.next, struct s5p_mfc_buf, list);
+
+       if (mfc_buf->used) {
+               mfc_debug(2, "addr[0]: 0x%08llx\n", mfc_buf->addr[0][0]);
+
+               list_del(&mfc_buf->list);
+               from_queue->count--;
+
+               list_add_tail(&mfc_buf->list, &to_queue->head);
+               to_queue->count++;
+
+               spin_unlock_irqrestore(plock, flags);
+               return mfc_buf;
+       } else {
+               spin_unlock_irqrestore(plock, flags);
+               return NULL;
+       }
+}
+
+struct s5p_mfc_buf *s5p_mfc_get_move_buf_addr(spinlock_t *plock,
+               struct s5p_mfc_buf_queue *to_queue, struct s5p_mfc_buf_queue *from_queue,
+               dma_addr_t addr)
+{
+       unsigned long flags;
+       struct s5p_mfc_buf *mfc_buf = NULL;
+
+       spin_lock_irqsave(plock, flags);
+
+       if (list_empty(&from_queue->head)) {
+               mfc_debug(2, "[DPB] from_queue is empty\n");
+               spin_unlock_irqrestore(plock, flags);
+               return NULL;
+       }
+
+       mfc_buf = list_entry(from_queue->head.next, struct s5p_mfc_buf, list);
+
+       if (mfc_buf->addr[0][0] == addr) {
+               mfc_debug(2, "[DPB] addr[0]: 0x%08llx\n", mfc_buf->addr[0][0]);
+
+               list_del(&mfc_buf->list);
+               from_queue->count--;
+
+               list_add_tail(&mfc_buf->list, &to_queue->head);
+               to_queue->count++;
+
+               spin_unlock_irqrestore(plock, flags);
+               return mfc_buf;
+       } else {
+               spin_unlock_irqrestore(plock, flags);
+               return NULL;
+       }
+}
+
+struct s5p_mfc_buf *s5p_mfc_find_first_buf(spinlock_t *plock, struct s5p_mfc_buf_queue *queue,
+               dma_addr_t addr)
+{
+       unsigned long flags;
+       struct s5p_mfc_buf *mfc_buf = NULL;
+       dma_addr_t mb_addr;
+       int i;
+
+       spin_lock_irqsave(plock, flags);
+
+       if (list_empty(&queue->head)) {
+               mfc_debug(2, "queue is empty\n");
+               spin_unlock_irqrestore(plock, flags);
+               return mfc_buf;
+       }
+
+       mfc_debug(4, "Looking for this address: 0x%08llx\n", addr);
+       mfc_buf = list_entry(queue->head.next, struct s5p_mfc_buf, list);
+       if (mfc_buf->num_valid_bufs > 0) {
+               for (i = 0; i < mfc_buf->num_valid_bufs; i++) {
+                       mb_addr = mfc_buf->addr[i][0];
+                       mfc_debug(4, "[BUFCON] batch[%d] addr[0]: 0x%08llx\n", i, mb_addr);
+                       if (addr == mb_addr) {
+                               spin_unlock_irqrestore(plock, flags);
+                               return mfc_buf;
+                       }
+               }
+       } else {
+               mb_addr = mfc_buf->addr[0][0];
+               mfc_debug(4, "addr[0]: 0x%08llx\n", mb_addr);
+
+               if (addr == mb_addr) {
+                       spin_unlock_irqrestore(plock, flags);
+                       return mfc_buf;
+               }
+       }
+
+       spin_unlock_irqrestore(plock, flags);
+       return NULL;
+}
+
+struct s5p_mfc_buf *s5p_mfc_find_buf(spinlock_t *plock, struct s5p_mfc_buf_queue *queue,
+               dma_addr_t addr)
+{
+       unsigned long flags;
+       struct s5p_mfc_buf *mfc_buf = NULL;
+       dma_addr_t mb_addr;
+       int i;
+
+       spin_lock_irqsave(plock, flags);
+
+       mfc_debug(4, "Looking for this address: 0x%08llx\n", addr);
+       list_for_each_entry(mfc_buf, &queue->head, list) {
+               if (mfc_buf->num_valid_bufs > 0) {
+                       for (i = 0; i < mfc_buf->num_valid_bufs; i++) {
+                               mb_addr = mfc_buf->addr[i][0];
+                               mfc_debug(4, "[BUFCON] batch[%d] addr[0]: 0x%08llx\n", i, mb_addr);
+                               if (addr == mb_addr) {
+                                       spin_unlock_irqrestore(plock, flags);
+                                       return mfc_buf;
+                               }
+                       }
+               } else {
+                       mb_addr = mfc_buf->addr[0][0];
+                       mfc_debug(4, "addr[0]: 0x%08llx\n", mb_addr);
+
+                       if (addr == mb_addr) {
+                               spin_unlock_irqrestore(plock, flags);
+                               return mfc_buf;
+                       }
+               }
+       }
+
+       spin_unlock_irqrestore(plock, flags);
+       return NULL;
+}
+
+struct s5p_mfc_buf *s5p_mfc_find_del_buf(spinlock_t *plock, struct s5p_mfc_buf_queue *queue,
+               dma_addr_t addr)
+{
+       unsigned long flags;
+       struct s5p_mfc_buf *mfc_buf = NULL;
+       dma_addr_t mb_addr;
+       int found = 0, i;
+
+       spin_lock_irqsave(plock, flags);
+
+       mfc_debug(4, "Looking for this address: 0x%08llx\n", addr);
+       list_for_each_entry(mfc_buf, &queue->head, list) {
+               if (mfc_buf->num_valid_bufs > 0) {
+                       for (i = 0; i < mfc_buf->num_valid_bufs; i++) {
+                               mb_addr = mfc_buf->addr[i][0];
+                               mfc_debug(4, "batch buf[%d] plane[0] addr: 0x%08llx\n", i, mb_addr);
+
+                               if (addr == mb_addr) {
+                                       found = 1;
+                                       break;
+                               }
+                       }
+
+                       if (found)
+                               break;
+               } else {
+                       mb_addr = mfc_buf->addr[0][0];
+                       mfc_debug(4, "addr[0]: 0x%08llx\n", mb_addr);
+
+                       if (addr == mb_addr) {
+                               found = 1;
+                               break;
+                       }
+               }
+       }
+
+       if (found == 1) {
+               list_del(&mfc_buf->list);
+               queue->count--;
+
+               spin_unlock_irqrestore(plock, flags);
+               return mfc_buf;
+       } else {
+               spin_unlock_irqrestore(plock, flags);
+               return NULL;
+       }
+}
+
+struct s5p_mfc_buf *s5p_mfc_find_move_buf(spinlock_t *plock,
+               struct s5p_mfc_buf_queue *to_queue, struct s5p_mfc_buf_queue *from_queue,
+               dma_addr_t addr, unsigned int released_flag)
+{
+       unsigned long flags;
+       struct s5p_mfc_buf *mfc_buf = NULL;
+       dma_addr_t mb_addr;
+       int found = 0;
+
+       spin_lock_irqsave(plock, flags);
+
+       mfc_debug(4, "[DPB] Looking for this address: 0x%08llx\n", addr);
+       list_for_each_entry(mfc_buf, &from_queue->head, list) {
+               mb_addr = mfc_buf->addr[0][0];
+               mfc_debug(4, "[DPB] addr[0]: 0x%08llx\n", mb_addr);
+
+               if (addr == mb_addr) {
+                       found = 1;
+                       break;
+               }
+       }
+
+       if (found == 1) {
+               if (released_flag & (1 << mfc_buf->vb.vb2_buf.index)) {
+                       list_del(&mfc_buf->list);
+                       from_queue->count--;
+
+                       list_add_tail(&mfc_buf->list, &to_queue->head);
+                       to_queue->count++;
+               }
+
+               spin_unlock_irqrestore(plock, flags);
+               return mfc_buf;
+       } else {
+               spin_unlock_irqrestore(plock, flags);
+               return NULL;
+       }
+}
+
+struct s5p_mfc_buf *s5p_mfc_find_move_buf_used(spinlock_t *plock,
+               struct s5p_mfc_buf_queue *to_queue, struct s5p_mfc_buf_queue *from_queue,
+               dma_addr_t addr)
+{
+       unsigned long flags;
+       struct s5p_mfc_buf *mfc_buf = NULL;
+       dma_addr_t mb_addr;
+       int found = 0;
+
+       spin_lock_irqsave(plock, flags);
+
+       mfc_debug(4, "[DPB] Looking for this address: 0x%08llx\n", addr);
+       list_for_each_entry(mfc_buf, &from_queue->head, list) {
+               mb_addr = mfc_buf->addr[0][0];
+               mfc_debug(4, "[DPB] addr[0]: 0x%08llx, used: %d\n",
+                               mb_addr, mfc_buf->used);
+
+               if ((addr == mb_addr) && (mfc_buf->used == 1)) {
+                       found = 1;
+                       break;
+               }
+       }
+
+       if (found == 1) {
+               list_del(&mfc_buf->list);
+               from_queue->count--;
+
+               list_add_tail(&mfc_buf->list, &to_queue->head);
+               to_queue->count++;
+
+               spin_unlock_irqrestore(plock, flags);
+               return mfc_buf;
+       } else {
+               spin_unlock_irqrestore(plock, flags);
+               return NULL;
+       }
+}
+
+void s5p_mfc_move_first_buf_used(spinlock_t *plock, struct s5p_mfc_buf_queue *to_queue,
+               struct s5p_mfc_buf_queue *from_queue, enum s5p_mfc_queue_top_type top)
+{
+       unsigned long flags;
+       struct s5p_mfc_buf *mfc_buf = NULL;
+
+       spin_lock_irqsave(plock, flags);
+
+       if (list_empty(&from_queue->head)) {
+               mfc_err_dev("from_queue is empty\n");
+               spin_unlock_irqrestore(plock, flags);
+               return;
+       }
+       mfc_buf = list_entry(from_queue->head.next, struct s5p_mfc_buf, list);
+
+       if (mfc_buf->used) {
+               list_del(&mfc_buf->list);
+               from_queue->count--;
+
+               if (top == MFC_QUEUE_ADD_TOP)
+                       list_add(&mfc_buf->list, &to_queue->head);
+               else
+                       list_add_tail(&mfc_buf->list, &to_queue->head);
+
+               to_queue->count++;
+       }
+
+       spin_unlock_irqrestore(plock, flags);
+}
+
+void s5p_mfc_move_all_bufs(spinlock_t *plock, struct s5p_mfc_buf_queue *to_queue,
+               struct s5p_mfc_buf_queue *from_queue, enum s5p_mfc_queue_top_type top)
+{
+       unsigned long flags;
+       struct s5p_mfc_buf *mfc_buf = NULL;
+
+       spin_lock_irqsave(plock, flags);
+
+       if (top == MFC_QUEUE_ADD_TOP) {
+               while (!list_empty(&from_queue->head)) {
+                       mfc_buf = list_entry(from_queue->head.prev, struct s5p_mfc_buf, list);
+
+                       list_del(&mfc_buf->list);
+                       from_queue->count--;
+
+                       list_add(&mfc_buf->list, &to_queue->head);
+                       to_queue->count++;
+               }
+       } else {
+               while (!list_empty(&from_queue->head)) {
+                       mfc_buf = list_entry(from_queue->head.next, struct s5p_mfc_buf, list);
+
+                       list_del(&mfc_buf->list);
+                       from_queue->count--;
+
+                       list_add_tail(&mfc_buf->list, &to_queue->head);
+                       to_queue->count++;
+               }
+       }
+
+       INIT_LIST_HEAD(&from_queue->head);
+       from_queue->count = 0;
+
+       spin_unlock_irqrestore(plock, flags);
+}
+
+void s5p_mfc_cleanup_queue(spinlock_t *plock, struct s5p_mfc_buf_queue *queue)
+{
+       unsigned long flags;
+       struct s5p_mfc_buf *mfc_buf = NULL;
+       int i;
+
+       spin_lock_irqsave(plock, flags);
+
+       while (!list_empty(&queue->head)) {
+               mfc_buf = list_entry(queue->head.next, struct s5p_mfc_buf, list);
+
+               for (i = 0; i < mfc_buf->vb.vb2_buf.num_planes; i++)
+                       vb2_set_plane_payload(&mfc_buf->vb.vb2_buf, i, 0);
+               vb2_buffer_done(&mfc_buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
+               list_del(&mfc_buf->list);
+               queue->count--;
+       }
+
+       INIT_LIST_HEAD(&queue->head);
+       queue->count = 0;
+
+       spin_unlock_irqrestore(plock, flags);
+}
+
+static void mfc_cleanup_batch_queue(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf_queue *queue)
+{
+       unsigned long flags;
+       struct s5p_mfc_buf *mfc_buf = NULL;
+       int i;
+
+       spin_lock_irqsave(&ctx->buf_queue_lock, flags);
+
+       while (!list_empty(&queue->head)) {
+               mfc_buf = list_entry(queue->head.next, struct s5p_mfc_buf, list);
+
+               for (i = 0; i < mfc_buf->vb.vb2_buf.num_planes; i++) {
+                       s5p_mfc_bufcon_put_daddr(ctx, mfc_buf, i);
+                       vb2_set_plane_payload(&mfc_buf->vb.vb2_buf, i, 0);
+               }
+               vb2_buffer_done(&mfc_buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
+               list_del(&mfc_buf->list);
+               queue->count--;
+       }
+
+       INIT_LIST_HEAD(&queue->head);
+       queue->count = 0;
+       ctx->batch_mode = 0;
+
+       spin_unlock_irqrestore(&ctx->buf_queue_lock, flags);
+}
+
+struct s5p_mfc_buf *mfc_find_buf_index(spinlock_t *plock, struct s5p_mfc_buf_queue *queue,
+               int index)
+{
+       unsigned long flags;
+       struct s5p_mfc_buf *mfc_buf = NULL;
+       int buf_index;
+
+       spin_lock_irqsave(plock, flags);
+
+       mfc_debug(4, "[DPB] Looking for index: %d\n", index);
+       list_for_each_entry(mfc_buf, &queue->head, list) {
+               buf_index = mfc_buf->vb.vb2_buf.index;
+
+               if (index == buf_index) {
+                       mfc_debug(2, "[DPB] Found index: %d\n", buf_index);
+                       spin_unlock_irqrestore(plock, flags);
+                       return mfc_buf;
+               }
+       }
+
+       spin_unlock_irqrestore(plock, flags);
+       return NULL;
+}
+
+/*
+ * Check released and enqueued buffers. (dst queue)
+ * Check and move reuse buffers. (ref -> dst queue)
+ */
+static void mfc_check_ref_frame(spinlock_t *plock, struct s5p_mfc_buf_queue *dst_queue,
+               struct s5p_mfc_buf_queue *ref_queue,
+               struct s5p_mfc_ctx *ctx, int ref_index)
+{
+       unsigned long flags;
+       struct s5p_mfc_dec *dec = ctx->dec_priv;
+       struct s5p_mfc_buf *ref_mb, *tmp_mb;
+       int index;
+       int found = 0;
+
+       spin_lock_irqsave(plock, flags);
+
+       /* reuse buffers : error frame, decoding only frame (ref -> dst queue) */
+       list_for_each_entry_safe(ref_mb, tmp_mb, &ref_queue->head, list) {
+               index = ref_mb->vb.vb2_buf.index;
+               if (index == ref_index) {
+                       list_del(&ref_mb->list);
+                       ref_queue->count--;
+
+                       list_add_tail(&ref_mb->list, &dst_queue->head);
+                       dst_queue->count++;
+
+                       dec->assigned_fd[index] =
+                                       ref_mb->vb.vb2_buf.planes[0].m.fd;
+                       clear_bit(index, &dec->available_dpb);
+                       mfc_debug(2, "[DPB] Move buffer[%d], fd[%d] to dst queue\n",
+                                       index, dec->assigned_fd[index]);
+                       found = 1;
+                       break;
+               }
+       }
+
+       /* released and enqueued buffers (dst queue) */
+       if (!found) {
+               list_for_each_entry_safe(ref_mb, tmp_mb, &dst_queue->head, list) {
+                       index = ref_mb->vb.vb2_buf.index;
+                       if (index == ref_index) {
+                               dec->assigned_fd[index] =
+                                       ref_mb->vb.vb2_buf.planes[0].m.fd;
+                               clear_bit(index, &dec->available_dpb);
+                               mfc_debug(2, "[DPB] re-assigned buffer[%d], fd[%d]\n",
+                                               index, dec->assigned_fd[index]);
+                               break;
+                       }
+               }
+       }
+
+       spin_unlock_irqrestore(plock, flags);
+}
+
+/* Process the released reference information */
+void s5p_mfc_handle_released_info(struct s5p_mfc_ctx *ctx,
+               unsigned int released_flag, int index)
+{
+       struct s5p_mfc_dec *dec;
+       struct dec_dpb_ref_info *refBuf;
+       int t, ncount = 0;
+
+       dec = ctx->dec_priv;
+       if (!dec) {
+               mfc_err_dev("[DPB] no decoder context to run\n");
+               return;
+       }
+       refBuf = &dec->ref_info[index];
+
+       if (dec->dec_only_release_flag) {
+               for (t = 0; t < MFC_MAX_DPBS; t++) {
+                       if (dec->dec_only_release_flag & (1 << t)) {
+                               mfc_debug(2, "[DPB] Release FD[%d] = %03d (already released in dec only)\n",
+                                               t, dec->assigned_fd[t]);
+                               refBuf->dpb[ncount].fd[0] = dec->assigned_fd[t];
+                               ncount++;
+                               dec->dec_only_release_flag &= ~(1 << t);
+                       }
+               }
+       }
+
+       if (released_flag) {
+               for (t = 0; t < MFC_MAX_DPBS; t++) {
+                       if (released_flag & (1 << t)) {
+                               if (dec->err_reuse_flag & (1 << t)) {
+                                       /* reuse buffer with error : do not update released info */
+                                       mfc_debug(2, "[DPB] Released, but reuse(error frame). FD[%d] = %03d\n",
+                                                       t, dec->assigned_fd[t]);
+                                       dec->err_reuse_flag &= ~(1 << t);
+                               } else if ((t != index) &&
+                                               mfc_find_buf_index(&ctx->buf_queue_lock, &ctx->ref_buf_queue, t)) {
+                                       /* decoding only frame: do not update released info */
+                                       mfc_debug(2, "[DPB] Released, but reuse(decoding only). FD[%d] = %03d\n",
+                                                       t, dec->assigned_fd[t]);
+                               } else {
+                                       /* displayed and released frame */
+                                       mfc_debug(2, "[DPB] Release FD[%d] = %03d\n",
+                                                       t, dec->assigned_fd[t]);
+                                       refBuf->dpb[ncount].fd[0] = dec->assigned_fd[t];
+                                       ncount++;
+                               }
+                               dec->assigned_fd[t] = MFC_INFO_INIT_FD;
+                               mfc_check_ref_frame(&ctx->buf_queue_lock, &ctx->dst_buf_queue,
+                                               &ctx->ref_buf_queue, ctx, t);
+                       }
+               }
+       }
+
+       if (ncount != MFC_MAX_DPBS)
+               refBuf->dpb[ncount].fd[0] = MFC_INFO_INIT_FD;
+}
+
+struct s5p_mfc_buf *s5p_mfc_move_reuse_buffer(struct s5p_mfc_ctx *ctx, int release_index)
+{
+       struct s5p_mfc_dec *dec = ctx->dec_priv;
+       struct s5p_mfc_buf_queue *dst_queue = &ctx->dst_buf_queue;
+       struct s5p_mfc_buf_queue *ref_queue = &ctx->ref_buf_queue;
+       struct s5p_mfc_buf *ref_mb, *tmp_mb;
+       spinlock_t *plock = &ctx->buf_queue_lock;
+       unsigned long flags;
+       int index;
+
+       spin_lock_irqsave(plock, flags);
+
+       list_for_each_entry_safe(ref_mb, tmp_mb, &ref_queue->head, list) {
+               index = ref_mb->vb.vb2_buf.index;
+               if (index == release_index) {
+                       s5p_mfc_raw_unprotect(ctx, ref_mb, index);
+
+                       ref_mb->used = 0;
+
+                       list_del(&ref_mb->list);
+                       ref_queue->count--;
+
+                       list_add_tail(&ref_mb->list, &dst_queue->head);
+                       dst_queue->count++;
+
+                       clear_bit(index, &dec->available_dpb);
+                       mfc_debug(2, "[DPB] buffer[%d] is moved to dst queue for reuse\n", index);
+
+                       spin_unlock_irqrestore(plock, flags);
+                       return ref_mb;
+               }
+       }
+
+       spin_unlock_irqrestore(plock, flags);
+       return NULL;
+}
+
+void s5p_mfc_cleanup_enc_src_queue(struct s5p_mfc_ctx *ctx)
+{
+       unsigned long flags;
+       struct s5p_mfc_buf *src_mb, *tmp_mb;
+       int i;
+
+       if (ctx->is_drm && ctx->raw_protect_flag) {
+               spin_lock_irqsave(&ctx->buf_queue_lock, flags);
+
+               mfc_debug(2, "raw_protect_flag(%#lx) will be released\n",
+                               ctx->raw_protect_flag);
+
+               list_for_each_entry_safe(src_mb, tmp_mb, &ctx->src_buf_queue.head, list) {
+                       i = src_mb->vb.vb2_buf.index;
+
+                       s5p_mfc_raw_unprotect(ctx, src_mb, i);
+
+                       for (i = 0; i < src_mb->vb.vb2_buf.num_planes; i++) {
+                               s5p_mfc_bufcon_put_daddr(ctx, src_mb, i);
+                               vb2_set_plane_payload(&src_mb->vb.vb2_buf, i, 0);
+                       }
+
+                       vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_ERROR);
+                       list_del(&src_mb->list);
+                       ctx->src_buf_queue.count--;
+               }
+
+               INIT_LIST_HEAD(&ctx->src_buf_queue.head);
+               ctx->src_buf_queue.count = 0;
+
+               spin_unlock_irqrestore(&ctx->buf_queue_lock, flags);
+       } else {
+               if (IS_BUFFER_BATCH_MODE(ctx))
+                       mfc_cleanup_batch_queue(ctx, &ctx->src_buf_queue);
+               else
+                       s5p_mfc_cleanup_queue(&ctx->buf_queue_lock, &ctx->src_buf_queue);
+       }
+}
+
+
+void s5p_mfc_cleanup_enc_dst_queue(struct s5p_mfc_ctx *ctx)
+{
+       unsigned long flags;
+       struct s5p_mfc_buf *dst_mb, *tmp_mb;
+       int i;
+
+       if (ctx->is_drm && ctx->stream_protect_flag) {
+               spin_lock_irqsave(&ctx->buf_queue_lock, flags);
+
+               mfc_debug(2, "stream_protect_flag(%#lx) will be released\n",
+                               ctx->stream_protect_flag);
+
+               list_for_each_entry_safe(dst_mb, tmp_mb, &ctx->dst_buf_queue.head, list) {
+                       i = dst_mb->vb.vb2_buf.index;
+
+                       s5p_mfc_stream_unprotect(ctx, dst_mb, i);
+
+                       for (i = 0; i < dst_mb->vb.vb2_buf.num_planes; i++)
+                               vb2_set_plane_payload(&dst_mb->vb.vb2_buf, i, 0);
+                       vb2_buffer_done(&dst_mb->vb.vb2_buf, VB2_BUF_STATE_ERROR);
+                       list_del(&dst_mb->list);
+                       ctx->dst_buf_queue.count--;
+               }
+
+               INIT_LIST_HEAD(&ctx->dst_buf_queue.head);
+               ctx->dst_buf_queue.count = 0;
+
+               spin_unlock_irqrestore(&ctx->buf_queue_lock, flags);
+       } else {
+               s5p_mfc_cleanup_queue(&ctx->buf_queue_lock, &ctx->dst_buf_queue);
+       }
+}
+
+/* Check all buffers are referenced or not */
+struct s5p_mfc_buf *mfc_check_full_refered_dpb(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dec *dec = NULL;
+       struct s5p_mfc_buf *mfc_buf = NULL;
+       int sum_dpb;
+
+       dec = ctx->dec_priv;
+       if (!dec) {
+               mfc_err_dev("[DPB] no decoder context to run\n");
+               return NULL;
+       }
+
+       sum_dpb = ctx->dst_buf_queue.count + ctx->ref_buf_queue.count;
+
+       if ((ctx->dst_buf_queue.count > 1) && (sum_dpb >= (ctx->dpb_count + 5))) {
+               if (list_empty(&ctx->dst_buf_queue.head)) {
+                       mfc_err_ctx("[DPB] dst_buf_queue is empty\n");
+                       return NULL;
+               }
+               mfc_debug(3, "[DPB] We should use this buffer\n");
+               mfc_buf = list_entry(ctx->dst_buf_queue.head.next,
+                               struct s5p_mfc_buf, list);
+       } else if ((ctx->dst_buf_queue.count == 0)
+                       && ((ctx->ref_buf_queue.count) == (ctx->dpb_count + 5))) {
+               if (list_empty(&ctx->ref_buf_queue.head)) {
+                       mfc_err_ctx("[DPB] ref_buf_queue is empty\n");
+                       return NULL;
+               }
+               mfc_debug(3, "[DPB] All buffers are referenced\n");
+               mfc_buf = list_entry(ctx->ref_buf_queue.head.next,
+                               struct s5p_mfc_buf, list);
+       } else {
+               mfc_debug(3, "[DPB] waiting for dst buffer, ref = %d, dst = %d\n",
+                               ctx->ref_buf_queue.count, ctx->dst_buf_queue.count);
+               ctx->clear_work_bit = 1;
+       }
+
+       if (mfc_buf)
+               mfc_buf->used = 1;
+
+       return mfc_buf;
+}
+
+/* Try to search non-referenced DPB on dst-queue */
+struct s5p_mfc_buf *s5p_mfc_search_for_dpb(struct s5p_mfc_ctx *ctx, unsigned int dynamic_used)
+{
+       unsigned long flags;
+       struct s5p_mfc_buf *mfc_buf = NULL;
+
+       spin_lock_irqsave(&ctx->buf_queue_lock, flags);
+
+       mfc_debug(2, "[DPB] Try to find non-referenced DPB. dynamic_used: 0x%x\n", dynamic_used);
+       list_for_each_entry(mfc_buf, &ctx->dst_buf_queue.head, list) {
+               if ((dynamic_used & (1 << mfc_buf->vb.vb2_buf.index)) == 0) {
+                       mfc_buf->used = 1;
+                       spin_unlock_irqrestore(&ctx->buf_queue_lock, flags);
+                       return mfc_buf;
+               }
+       }
+
+       mfc_buf = mfc_check_full_refered_dpb(ctx);
+
+       spin_unlock_irqrestore(&ctx->buf_queue_lock, flags);
+
+       return mfc_buf;
+}
+
+struct s5p_mfc_buf *s5p_mfc_search_move_dpb_nal_q(struct s5p_mfc_ctx *ctx, unsigned int dynamic_used)
+{
+       unsigned long flags;
+       struct s5p_mfc_buf *mfc_buf = NULL;
+       struct s5p_mfc_dec *dec = NULL;
+
+       dec = ctx->dec_priv;
+       if (!dec) {
+               mfc_err_dev("no mfc decoder to run\n");
+               return mfc_buf;
+       }
+
+       spin_lock_irqsave(&ctx->buf_queue_lock, flags);
+
+       mfc_debug(2, "[NALQ][DPB] Try to find non-referenced DPB. dynamic_used: 0x%x\n", dynamic_used);
+       list_for_each_entry(mfc_buf, &ctx->dst_buf_queue.head, list) {
+               if ((dynamic_used & (1 << mfc_buf->vb.vb2_buf.index)) == 0) {
+                       mfc_buf->used = 1;
+
+                       list_del(&mfc_buf->list);
+                       ctx->dst_buf_queue.count--;
+
+                       list_add_tail(&mfc_buf->list, &ctx->dst_buf_nal_queue.head);
+                       ctx->dst_buf_nal_queue.count++;
+
+                       spin_unlock_irqrestore(&ctx->buf_queue_lock, flags);
+                       return mfc_buf;
+               }
+       }
+
+       mfc_buf = mfc_check_full_refered_dpb(ctx);
+
+       if (mfc_buf) {
+               mfc_debug(2, "[NALQ][DPB] DPB is full. stop NAL-Q if started\n");
+               dec->is_dpb_full = 1;
+       }
+
+       spin_unlock_irqrestore(&ctx->buf_queue_lock, flags);
+
+       return mfc_buf;
+}
+
+/* Add dst buffer in dst_buf_queue */
+void s5p_mfc_store_dpb(struct s5p_mfc_ctx *ctx, struct vb2_buffer *vb)
+{
+       unsigned long flags;
+       struct s5p_mfc_dec *dec;
+       struct s5p_mfc_buf *mfc_buf;
+       int index;
+
+       if (!ctx) {
+               mfc_err_dev("[DPB] no mfc context to run\n");
+               return;
+       }
+
+       dec = ctx->dec_priv;
+       if (!dec) {
+               mfc_err_dev("[DPB] no mfc decoder to run\n");
+               return;
+       }
+
+       spin_lock_irqsave(&ctx->buf_queue_lock, flags);
+
+       mfc_buf = vb_to_mfc_buf(vb);
+       mfc_buf->used = 0;
+       index = vb->index;
+
+       dec->assigned_fd[index] = vb->planes[0].m.fd;
+       mfc_debug(2, "[DPB] Assigned FD[%d] = %d (%s)\n", index, dec->assigned_fd[index],
+                       (dec->dynamic_used & (1 << index) ? "used" : "non-used"));
+
+       list_add_tail(&mfc_buf->list, &ctx->dst_buf_queue.head);
+       ctx->dst_buf_queue.count++;
+
+       spin_unlock_irqrestore(&ctx->buf_queue_lock, flags);
+}
+
+void s5p_mfc_cleanup_nal_queue(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dec *dec = ctx->dec_priv;
+       struct s5p_mfc_buf *src_mb, *dst_mb;
+       unsigned long flags;
+       unsigned int index;
+
+       spin_lock_irqsave(&ctx->buf_queue_lock, flags);
+
+       while (!list_empty(&ctx->src_buf_nal_queue.head)) {
+               src_mb = list_entry(ctx->src_buf_nal_queue.head.prev, struct s5p_mfc_buf, list);
+
+               index = src_mb->vb.vb2_buf.index;
+               call_cop(ctx, recover_buf_ctrls_nal_q, ctx, &ctx->src_ctrls[index]);
+
+               src_mb->used = 0;
+
+               /* If it is not buffer batch mode, index is always zero */
+               if (src_mb->next_index > src_mb->done_index) {
+                       mfc_debug(2, "[NALQ][BUFCON] batch buf next index[%d] recover to [%d]\n",
+                                       src_mb->next_index, src_mb->done_index);
+                       src_mb->next_index = src_mb->done_index;
+               }
+
+               list_del(&src_mb->list);
+               ctx->src_buf_nal_queue.count--;
+
+               list_add(&src_mb->list, &ctx->src_buf_queue.head);
+               ctx->src_buf_queue.count++;
+
+               mfc_debug(2, "[NALQ] cleanup, src_buf_nal_queue -> src_buf_queue, index:%d\n",
+                               src_mb->vb.vb2_buf.index);
+       }
+
+       while (!list_empty(&ctx->dst_buf_nal_queue.head)) {
+               dst_mb = list_entry(ctx->dst_buf_nal_queue.head.prev, struct s5p_mfc_buf, list);
+
+               dst_mb->used = 0;
+               if (ctx->type == MFCINST_DECODER)
+                       clear_bit(dst_mb->vb.vb2_buf.index, &dec->available_dpb);
+               list_del(&dst_mb->list);
+               ctx->dst_buf_nal_queue.count--;
+
+               list_add(&dst_mb->list, &ctx->dst_buf_queue.head);
+               ctx->dst_buf_queue.count++;
+
+               mfc_debug(2, "[NALQ] cleanup, dst_buf_nal_queue -> dst_buf_queue, index:%d\n",
+                               dst_mb->vb.vb2_buf.index);
+       }
+
+       spin_unlock_irqrestore(&ctx->buf_queue_lock, flags);
+}
+
+int s5p_mfc_is_last_frame(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_buf *src_mb;
+       struct s5p_mfc_dev *dev;
+       unsigned long flags;
+
+       mfc_debug_enter();
+
+       if (!ctx) {
+               mfc_err_dev("no mfc context to run\n");
+               return -EINVAL;
+       }
+
+       dev = ctx->dev;
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return -EINVAL;
+       }
+
+       spin_lock_irqsave(&ctx->buf_queue_lock, flags);
+
+       if (list_empty(&ctx->src_buf_queue.head)) {
+               mfc_debug(2, "src_buf_queue is empty\n");
+               spin_unlock_irqrestore(&ctx->buf_queue_lock, flags);
+               return -EINVAL;
+       }
+
+       src_mb = list_entry(ctx->src_buf_queue.head.next, struct s5p_mfc_buf, list);
+
+       mfc_debug(4, "addr[0]: 0x%08llx\n", src_mb->addr[0][0]);
+
+       if (src_mb->vb.reserved2 & FLAG_LAST_FRAME) {
+               mfc_debug(2, "last frame!\n");
+               spin_unlock_irqrestore(&ctx->buf_queue_lock, flags);
+               return 1;
+       }
+
+       mfc_debug(4, "not last frame!\n");
+       spin_unlock_irqrestore(&ctx->buf_queue_lock, flags);
+
+       mfc_debug_leave();
+
+       return 0;
+}
diff --git a/drivers/media/platform/exynos/mfc/mfc_queue.h b/drivers/media/platform/exynos/mfc/mfc_queue.h
new file mode 100644 (file)
index 0000000..71dfc42
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_queue.h
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __MFC_QUEUE_H
+#define __MFC_QUEUE_H __FILE__
+
+#include  "mfc_common.h"
+
+/**
+ * enum s5p_mfc_queue_used_type
+ */
+enum s5p_mfc_queue_used_type {
+       MFC_BUF_NO_TOUCH_USED   = -1,
+       MFC_BUF_RESET_USED      = 0,
+       MFC_BUF_SET_USED        = 1,
+};
+
+/**
+ * enum s5p_mfc_queue_top_type
+ */
+enum s5p_mfc_queue_top_type {
+       MFC_QUEUE_ADD_BOTTOM    = 0,
+       MFC_QUEUE_ADD_TOP       = 1,
+};
+
+static inline unsigned int s5p_mfc_get_queue_count(spinlock_t *plock, struct s5p_mfc_buf_queue *queue)
+{
+       unsigned long flags;
+       unsigned int ret = 0;
+
+       spin_lock_irqsave(plock, flags);
+       ret = queue->count;
+       spin_unlock_irqrestore(plock, flags);
+
+       return ret;
+}
+
+static inline int s5p_mfc_is_queue_count_same(spinlock_t *plock, struct s5p_mfc_buf_queue *queue,
+               unsigned int value)
+{
+       unsigned long flags;
+       int ret = 0;
+
+       spin_lock_irqsave(plock, flags);
+       if (queue->count == value)
+               ret = 1;
+       spin_unlock_irqrestore(plock, flags);
+
+       return ret;
+}
+
+static inline int s5p_mfc_is_queue_count_greater(spinlock_t *plock, struct s5p_mfc_buf_queue *queue,
+               unsigned int value)
+{
+       unsigned long flags;
+       int ret = 0;
+
+       spin_lock_irqsave(plock, flags);
+       if (queue->count > value)
+               ret = 1;
+       spin_unlock_irqrestore(plock, flags);
+
+       return ret;
+}
+
+static inline int s5p_mfc_is_queue_count_smaller(spinlock_t *plock, struct s5p_mfc_buf_queue *queue,
+               unsigned int value)
+{
+       unsigned long flags;
+       int ret = 0;
+
+       spin_lock_irqsave(plock, flags);
+       if (queue->count < value)
+               ret = 1;
+       spin_unlock_irqrestore(plock, flags);
+
+       return ret;
+}
+
+static inline void s5p_mfc_init_queue(struct s5p_mfc_buf_queue *queue)
+{
+       INIT_LIST_HEAD(&queue->head);
+       queue->count = 0;
+}
+
+static inline void s5p_mfc_create_queue(struct s5p_mfc_buf_queue *queue)
+{
+       s5p_mfc_init_queue(queue);
+}
+
+static inline void s5p_mfc_delete_queue(struct s5p_mfc_buf_queue *queue)
+{
+       s5p_mfc_init_queue(queue);
+}
+
+void s5p_mfc_add_tail_buf(spinlock_t *plock, struct s5p_mfc_buf_queue *queue,
+               struct s5p_mfc_buf *mfc_buf);
+
+int s5p_mfc_peek_buf_csd(spinlock_t *plock, struct s5p_mfc_buf_queue *queue);
+
+struct s5p_mfc_buf *s5p_mfc_get_buf(spinlock_t *plock, struct s5p_mfc_buf_queue *queue,
+               enum s5p_mfc_queue_used_type used);
+struct s5p_mfc_buf *s5p_mfc_get_del_buf(spinlock_t *plock, struct s5p_mfc_buf_queue *queue,
+               enum s5p_mfc_queue_used_type used);
+struct s5p_mfc_buf *s5p_mfc_get_del_if_consumed(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf_queue *queue,
+               unsigned long consumed, unsigned int min_bytes, int err, int *deleted);
+struct s5p_mfc_buf *s5p_mfc_get_move_buf(spinlock_t *plock,
+               struct s5p_mfc_buf_queue *to_queue, struct s5p_mfc_buf_queue *from_queue,
+               enum s5p_mfc_queue_used_type used, enum s5p_mfc_queue_top_type top);
+struct s5p_mfc_buf *s5p_mfc_get_move_buf_used(spinlock_t *plock,
+               struct s5p_mfc_buf_queue *to_queue, struct s5p_mfc_buf_queue *from_queue);
+struct s5p_mfc_buf *s5p_mfc_get_move_buf_addr(spinlock_t *plock,
+               struct s5p_mfc_buf_queue *to_queue, struct s5p_mfc_buf_queue *from_queue,
+               dma_addr_t addr);
+
+struct s5p_mfc_buf *s5p_mfc_find_first_buf(spinlock_t *plock, struct s5p_mfc_buf_queue *queue,
+               dma_addr_t addr);
+struct s5p_mfc_buf *s5p_mfc_find_buf(spinlock_t *plock, struct s5p_mfc_buf_queue *queue,
+               dma_addr_t addr);
+struct s5p_mfc_buf *s5p_mfc_find_del_buf(spinlock_t *plock, struct s5p_mfc_buf_queue *queue,
+               dma_addr_t addr);
+struct s5p_mfc_buf *s5p_mfc_find_move_buf(spinlock_t *plock,
+               struct s5p_mfc_buf_queue *to_queue, struct s5p_mfc_buf_queue *from_queue,
+               dma_addr_t addr, unsigned int released_flag);
+struct s5p_mfc_buf *s5p_mfc_find_move_buf_used(spinlock_t *plock,
+               struct s5p_mfc_buf_queue *to_queue, struct s5p_mfc_buf_queue *from_queue,
+               dma_addr_t addr);
+
+void s5p_mfc_move_first_buf_used(spinlock_t *plock, struct s5p_mfc_buf_queue *to_queue,
+               struct s5p_mfc_buf_queue *from_queue, enum s5p_mfc_queue_top_type top);
+void s5p_mfc_move_all_bufs(spinlock_t *plock, struct s5p_mfc_buf_queue *to_queue,
+               struct s5p_mfc_buf_queue *from_queue, enum s5p_mfc_queue_top_type top);
+
+void s5p_mfc_cleanup_queue(spinlock_t *plock, struct s5p_mfc_buf_queue *queue);
+
+void s5p_mfc_handle_released_info(struct s5p_mfc_ctx *ctx,
+               unsigned int released_flag, int index);
+
+struct s5p_mfc_buf *s5p_mfc_move_reuse_buffer(struct s5p_mfc_ctx *ctx, int release_index);
+
+void s5p_mfc_cleanup_enc_src_queue(struct s5p_mfc_ctx *ctx);
+void s5p_mfc_cleanup_enc_dst_queue(struct s5p_mfc_ctx *ctx);
+
+struct s5p_mfc_buf *s5p_mfc_search_for_dpb(struct s5p_mfc_ctx *ctx, unsigned int dynamic_used);
+struct s5p_mfc_buf *s5p_mfc_search_move_dpb_nal_q(struct s5p_mfc_ctx *ctx, unsigned int dynamic_used);
+void s5p_mfc_store_dpb(struct s5p_mfc_ctx *ctx, struct vb2_buffer *vb);
+
+void s5p_mfc_cleanup_nal_queue(struct s5p_mfc_ctx *ctx);
+int s5p_mfc_is_last_frame(struct s5p_mfc_ctx *ctx);
+
+#endif /* __MFC_QUEUE_H */
diff --git a/drivers/media/platform/exynos/mfc/mfc_reg.c b/drivers/media/platform/exynos/mfc/mfc_reg.c
new file mode 100644 (file)
index 0000000..1631025
--- /dev/null
@@ -0,0 +1,547 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_reg.c
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/delay.h>
+
+#include "mfc_reg.h"
+
+void s5p_mfc_dbg_enable(struct s5p_mfc_dev *dev)
+{
+       mfc_debug(2, "MFC debug info enable\n");
+       MFC_WRITEL(0x1, S5P_FIMV_DBG_INFO_ENABLE);
+}
+
+void s5p_mfc_dbg_disable(struct s5p_mfc_dev *dev)
+{
+       mfc_debug(2, "MFC debug info disable\n");
+       MFC_WRITEL(0x0, S5P_FIMV_DBG_INFO_ENABLE);
+}
+
+void s5p_mfc_dbg_set_addr(struct s5p_mfc_dev *dev)
+{
+       struct s5p_mfc_ctx_buf_size *buf_size = dev->variant->buf_size->ctx_buf;
+
+       memset((void *)dev->dbg_info_buf.vaddr, 0, buf_size->dbg_info_buf);
+
+       MFC_WRITEL(dev->dbg_info_buf.daddr, S5P_FIMV_DBG_BUFFER_ADDR);
+       MFC_WRITEL(buf_size->dbg_info_buf, S5P_FIMV_DBG_BUFFER_SIZE);
+}
+
+void s5p_mfc_otf_set_frame_addr(struct s5p_mfc_ctx *ctx, int num_planes)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct _otf_handle *handle = ctx->otf_handle;
+       struct _otf_buf_addr *buf_addr = &handle->otf_buf_addr;
+       int index = handle->otf_buf_index;
+       int i;
+
+       for (i = 0; i < num_planes; i++) {
+               mfc_debug(2, "[OTF][FRAME] set frame buffer[%d], 0x%08llx)\n",
+                               i, buf_addr->otf_daddr[index][i]);
+               MFC_WRITEL(buf_addr->otf_daddr[index][i],
+                               S5P_FIMV_E_SOURCE_FIRST_ADDR + (i * 4));
+       }
+}
+
+void s5p_mfc_otf_set_stream_size(struct s5p_mfc_ctx *ctx, unsigned int size)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct _otf_handle *handle = ctx->otf_handle;
+       struct _otf_debug *debug = &handle->otf_debug;
+       struct s5p_mfc_special_buf *buf;
+
+       mfc_debug(2, "[OTF] set stream buffer full size, %u\n", size);
+       MFC_WRITEL(size, S5P_FIMV_E_STREAM_BUFFER_SIZE);
+
+       if (otf_dump && !ctx->is_drm) {
+               buf = &debug->stream_buf[debug->frame_cnt];
+               mfc_debug(2, "[OTF] set stream addr for debugging\n");
+               mfc_debug(2, "[OTF][STREAM] buf[%d] daddr: 0x%08llx\n",
+                               debug->frame_cnt, buf->daddr);
+               MFC_WRITEL(buf->daddr, S5P_FIMV_E_STREAM_BUFFER_ADDR);
+       }
+}
+
+void s5p_mfc_otf_set_hwfc_index(struct s5p_mfc_ctx *ctx, int job_id)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       mfc_debug(2, "[OTF] set hwfc index, %d\n", job_id);
+       HWFC_WRITEL(job_id, HWFC_ENCODING_IDX);
+}
+
+/* Set decoding frame buffer */
+int s5p_mfc_set_dec_codec_buffers(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev;
+       struct s5p_mfc_dec *dec;
+       unsigned int i;
+       size_t frame_size_mv;
+       dma_addr_t buf_addr;
+       int buf_size;
+       int align_gap;
+       struct s5p_mfc_raw_info *raw;
+       unsigned int reg = 0;
+
+       if (!ctx) {
+               mfc_err_dev("no mfc context to run\n");
+               return -EINVAL;
+       }
+
+       dev = ctx->dev;
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return -EINVAL;
+       }
+
+       dec = ctx->dec_priv;
+       if (!dec) {
+               mfc_err_dev("no mfc decoder to run\n");
+               return -EINVAL;
+       }
+
+       raw = &ctx->raw_buf;
+       buf_addr = ctx->codec_buf.daddr;
+       buf_size = ctx->codec_buf.size;
+
+       mfc_debug(2, "[MEMINFO] codec buf 0x%llx size: %d\n", buf_addr, buf_size);
+       mfc_debug(2, "Total DPB COUNT: %d, display delay: %d\n",
+                       dec->total_dpb_count, dec->display_delay);
+
+       /* set decoder DPB size, stride */
+       MFC_WRITEL(dec->total_dpb_count, S5P_FIMV_D_NUM_DPB);
+       for (i = 0; i < raw->num_planes; i++) {
+               mfc_debug(2, "[FRAME] buf[%d] size: %d, stride: %d\n",
+                               i, raw->plane_size[i], raw->stride[i]);
+               MFC_WRITEL(raw->plane_size[i], S5P_FIMV_D_FIRST_PLANE_DPB_SIZE + (i * 4));
+               MFC_WRITEL(ctx->raw_buf.stride[i],
+                               S5P_FIMV_D_FIRST_PLANE_DPB_STRIDE_SIZE + (i * 4));
+               if (ctx->is_10bit) {
+                       MFC_WRITEL(raw->stride_2bits[i], S5P_FIMV_D_FIRST_PLANE_2BIT_DPB_STRIDE_SIZE + (i * 4));
+                       MFC_WRITEL(raw->plane_size_2bits[i], S5P_FIMV_D_FIRST_PLANE_2BIT_DPB_SIZE + (i * 4));
+                       mfc_debug(2, "[FRAME][10BIT] 2bits buf[%d] size: %d, stride: %d\n",
+                                       i, raw->plane_size_2bits[i], raw->stride_2bits[i]);
+               }
+       }
+
+       /* set codec buffers */
+       MFC_WRITEL(buf_addr, S5P_FIMV_D_SCRATCH_BUFFER_ADDR);
+       MFC_WRITEL(ctx->scratch_buf_size, S5P_FIMV_D_SCRATCH_BUFFER_SIZE);
+       buf_addr += ctx->scratch_buf_size;
+       buf_size -= ctx->scratch_buf_size;
+
+       if (IS_H264_DEC(ctx) || IS_H264_MVC_DEC(ctx) || IS_HEVC_DEC(ctx) || IS_BPG_DEC(ctx))
+               MFC_WRITEL(ctx->mv_size, S5P_FIMV_D_MV_BUFFER_SIZE);
+
+       if (IS_VP9_DEC(ctx)){
+               MFC_WRITEL(buf_addr, S5P_FIMV_D_STATIC_BUFFER_ADDR);
+               MFC_WRITEL(DEC_STATIC_BUFFER_SIZE, S5P_FIMV_D_STATIC_BUFFER_SIZE);
+               buf_addr += DEC_STATIC_BUFFER_SIZE;
+               buf_size -= DEC_STATIC_BUFFER_SIZE;
+       }
+
+       if (IS_MPEG4_DEC(ctx) && dec->loop_filter_mpeg4) {
+               mfc_debug(2, "Add DPB for loop filter of MPEG4\n");
+               for (i = 0; i < NUM_MPEG4_LF_BUF; i++) {
+                       MFC_WRITEL(buf_addr, S5P_FIMV_D_POST_FILTER_LUMA_DPB0 + (4 * i));
+                       buf_addr += ctx->loopfilter_luma_size;
+                       buf_size -= ctx->loopfilter_luma_size;
+
+                       MFC_WRITEL(buf_addr, S5P_FIMV_D_POST_FILTER_CHROMA_DPB0 + (4 * i));
+                       buf_addr += ctx->loopfilter_chroma_size;
+                       buf_size -= ctx->loopfilter_chroma_size;
+               }
+               reg |= ((dec->loop_filter_mpeg4 & S5P_FIMV_D_INIT_BUF_OPT_LF_CTRL_MASK)
+                               << S5P_FIMV_D_INIT_BUF_OPT_LF_CTRL_SHIFT);
+       }
+
+       reg |= (0x1 << S5P_FIMV_D_INIT_BUF_OPT_DYNAMIC_DPB_SET_SHIFT);
+
+       if (CODEC_NOT_CODED(ctx)) {
+               reg |= (0x1 << S5P_FIMV_D_INIT_BUF_OPT_COPY_NOT_CODED_SHIFT);
+               mfc_debug(2, "Notcoded frame copy mode start\n");
+       }
+       /* Enable 10bit Dithering */
+       if (ctx->is_10bit) {
+               reg |= (0x1 << S5P_FIMV_D_INIT_BUF_OPT_DITHERING_EN_SHIFT);
+               /* 64byte align, It is vaid only for VP9 */
+               reg |= (0x1 << S5P_FIMV_D_INIT_BUF_OPT_STRIDE_SIZE_ALIGN);
+       } else {
+               /* 16byte align, It is vaid only for VP9 */
+               reg &= ~(0x1 << S5P_FIMV_D_INIT_BUF_OPT_STRIDE_SIZE_ALIGN);
+       }
+
+       MFC_WRITEL(reg, S5P_FIMV_D_INIT_BUFFER_OPTIONS);
+
+       frame_size_mv = ctx->mv_size;
+       MFC_WRITEL(dec->mv_count, S5P_FIMV_D_NUM_MV);
+       if (IS_H264_DEC(ctx) || IS_H264_MVC_DEC(ctx) || IS_HEVC_DEC(ctx) || IS_BPG_DEC(ctx)) {
+               for (i = 0; i < dec->mv_count; i++) {
+                       /* To test alignment */
+                       align_gap = buf_addr;
+                       buf_addr = ALIGN(buf_addr, 16);
+                       align_gap = buf_addr - align_gap;
+                       buf_size -= align_gap;
+
+                       MFC_WRITEL(buf_addr, S5P_FIMV_D_MV_BUFFER0 + i * 4);
+                       buf_addr += frame_size_mv;
+                       buf_size -= frame_size_mv;
+               }
+       }
+
+       mfc_debug(2, "[MEMINFO] codec buf 0x%llx, remained size: %d\n", buf_addr, buf_size);
+       if (buf_size < 0) {
+               mfc_debug(2, "[MEMINFO] Not enough memory has been allocated\n");
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
+/* Set encoding ref & codec buffer */
+int s5p_mfc_set_enc_codec_buffers(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc *enc = ctx->enc_priv;
+       dma_addr_t buf_addr;
+       int buf_size;
+       int i;
+
+       mfc_debug_enter();
+
+       buf_addr = ctx->codec_buf.daddr;
+       buf_size = ctx->codec_buf.size;
+
+       mfc_debug(2, "[MEMINFO] codec buf 0x%llx, size: %d\n", buf_addr, buf_size);
+       mfc_debug(2, "DPB COUNT: %d\n", ctx->dpb_count);
+
+       MFC_WRITEL(buf_addr, S5P_FIMV_E_SCRATCH_BUFFER_ADDR);
+       MFC_WRITEL(ctx->scratch_buf_size, S5P_FIMV_E_SCRATCH_BUFFER_SIZE);
+       buf_addr += ctx->scratch_buf_size;
+       buf_size -= ctx->scratch_buf_size;
+
+       /* start address of per buffer is aligned */
+       for (i = 0; i < ctx->dpb_count; i++) {
+               MFC_WRITEL(buf_addr, S5P_FIMV_E_LUMA_DPB + (4 * i));
+               buf_addr += enc->luma_dpb_size;
+               buf_size -= enc->luma_dpb_size;
+       }
+       for (i = 0; i < ctx->dpb_count; i++) {
+               MFC_WRITEL(buf_addr, S5P_FIMV_E_CHROMA_DPB + (4 * i));
+               buf_addr += enc->chroma_dpb_size;
+               buf_size -= enc->chroma_dpb_size;
+       }
+       for (i = 0; i < ctx->dpb_count; i++) {
+               MFC_WRITEL(buf_addr, S5P_FIMV_E_ME_BUFFER + (4 * i));
+               buf_addr += enc->me_buffer_size;
+               buf_size -= enc->me_buffer_size;
+       }
+
+       MFC_WRITEL(buf_addr, S5P_FIMV_E_TMV_BUFFER0);
+       buf_addr += enc->tmv_buffer_size >> 1;
+       MFC_WRITEL(buf_addr, S5P_FIMV_E_TMV_BUFFER1);
+       buf_addr += enc->tmv_buffer_size >> 1;
+       buf_size -= enc->tmv_buffer_size;
+
+       mfc_debug(2, "[MEMINFO] codec buf 0x%llx, remained size: %d\n", buf_addr, buf_size);
+       if (buf_size < 0) {
+               mfc_debug(2, "[MEMINFO] Not enough memory has been allocated\n");
+               return -ENOMEM;
+       }
+
+       mfc_debug_leave();
+
+       return 0;
+}
+
+/* Set registers for decoding stream buffer */
+int s5p_mfc_set_dec_stream_buffer(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf *mfc_buf,
+                 unsigned int start_num_byte, unsigned int strm_size)
+{
+       struct s5p_mfc_dev *dev;
+       struct s5p_mfc_dec *dec;
+       unsigned int cpb_buf_size;
+       dma_addr_t addr;
+       int index = -1;
+
+       mfc_debug_enter();
+       if (!ctx) {
+               mfc_err_dev("no mfc context to run\n");
+               return -EINVAL;
+       }
+       dev = ctx->dev;
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return -EINVAL;
+       }
+       dec = ctx->dec_priv;
+       if (!dec) {
+               mfc_err_dev("no mfc decoder to run\n");
+               return -EINVAL;
+       }
+
+       cpb_buf_size = ALIGN(dec->src_buf_size, STREAM_BUF_ALIGN);
+
+       if (mfc_buf) {
+               index = mfc_buf->vb.vb2_buf.index;
+               addr = mfc_buf->addr[0][0];
+               if (strm_size > set_strm_size_max(cpb_buf_size)) {
+                       mfc_info_ctx("Decrease strm_size because of %d align: %u -> %u\n",
+                               STREAM_BUF_ALIGN, strm_size, set_strm_size_max(cpb_buf_size));
+                       strm_size = set_strm_size_max(cpb_buf_size);
+                       mfc_buf->vb.vb2_buf.planes[0].bytesused = strm_size;
+               }
+       } else {
+               addr = 0;
+       }
+
+       mfc_debug(2, "[BUFINFO] ctx[%d] set src index: %d, addr: 0x%08llx\n",
+                       ctx->num, index, addr);
+       mfc_debug(2, "[STREAM] strm_size: %#lx(%d), buf_size: %u, offset: %u\n",
+                       strm_size, strm_size, cpb_buf_size, start_num_byte);
+
+       if (strm_size == 0)
+               mfc_info_ctx("stream size is 0\n");
+
+       MFC_WRITEL(strm_size, S5P_FIMV_D_STREAM_DATA_SIZE);
+       MFC_WRITEL(addr, S5P_FIMV_D_CPB_BUFFER_ADDR);
+       MFC_WRITEL(cpb_buf_size, S5P_FIMV_D_CPB_BUFFER_SIZE);
+       MFC_WRITEL(start_num_byte, S5P_FIMV_D_CPB_BUFFER_OFFSET);
+
+       if (mfc_buf)
+               MFC_TRACE_CTX("Set src[%d] fd: %d, %#llx\n",
+                               index, mfc_buf->vb.vb2_buf.planes[0].m.fd, addr);
+
+       mfc_debug_leave();
+       return 0;
+}
+
+void s5p_mfc_set_enc_frame_buffer(struct s5p_mfc_ctx *ctx,
+               struct s5p_mfc_buf *mfc_buf, int num_planes)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       dma_addr_t addr[3] = { 0, 0, 0 };
+       dma_addr_t addr_2bit[2] = { 0, 0 };
+       int index, i;
+
+       if (!mfc_buf) {
+               mfc_debug(3, "enc zero buffer set\n");
+               goto buffer_set;
+       }
+
+       index = mfc_buf->vb.vb2_buf.index;
+       if (mfc_buf->num_valid_bufs > 0) {
+               for (i = 0; i < num_planes; i++) {
+                       addr[i] = mfc_buf->addr[mfc_buf->next_index][i];
+                       mfc_debug(2, "[BUFCON][BUFINFO] ctx[%d] set src index:%d, batch[%d], addr[%d]: 0x%08llx\n",
+                                       ctx->num, index, mfc_buf->next_index, i, addr[i]);
+               }
+               mfc_buf->next_index++;
+       } else {
+               for (i = 0; i < num_planes; i++) {
+                       addr[i] = mfc_buf->addr[0][i];
+                       mfc_debug(2, "[BUFINFO] ctx[%d] set src index:%d, addr[%d]: 0x%08llx\n",
+                                       ctx->num, index, i, addr[i]);
+               }
+       }
+
+buffer_set:
+       for (i = 0; i < num_planes; i++)
+               MFC_WRITEL(addr[i], S5P_FIMV_E_SOURCE_FIRST_ADDR + (i * 4));
+
+       if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M_S10B ||
+               ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV21M_S10B) {
+               addr_2bit[0] = addr[0] + NV12N_10B_Y_8B_SIZE(ctx->img_width, ctx->img_height);
+               addr_2bit[1] = addr[1] + NV12N_10B_CBCR_8B_SIZE(ctx->img_width, ctx->img_height);
+
+               for (i = 0; i < num_planes; i++) {
+                       MFC_WRITEL(addr_2bit[i], S5P_FIMV_E_SOURCE_FIRST_2BIT_ADDR + (i * 4));
+                       mfc_debug(2, "[BUFINFO][10BIT] ctx[%d] set src 2bit addr[%d]: 0x%08llx\n",
+                                       ctx->num, i, addr_2bit[i]);
+               }
+       } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV16M_S10B ||
+               ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV61M_S10B) {
+               addr_2bit[0] = addr[0] + NV16M_Y_SIZE(ctx->img_width, ctx->img_height);
+               addr_2bit[1] = addr[1] + NV16M_CBCR_SIZE(ctx->img_width, ctx->img_height);
+
+               for (i = 0; i < num_planes; i++) {
+                       MFC_WRITEL(addr_2bit[i], S5P_FIMV_E_SOURCE_FIRST_2BIT_ADDR + (i * 4));
+                       mfc_debug(2, "[BUFINFO][10BIT] ctx[%d] set src 2bit addr[%d]: 0x%08llx\n",
+                                       ctx->num, i, addr_2bit[i]);
+               }
+       }
+}
+
+/* Set registers for encoding stream buffer */
+int s5p_mfc_set_enc_stream_buffer(struct s5p_mfc_ctx *ctx,
+               struct s5p_mfc_buf *mfc_buf)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       dma_addr_t addr;
+       unsigned int size, offset, index;
+
+       index = mfc_buf->vb.vb2_buf.index;
+       addr = mfc_buf->addr[0][0];
+       offset = mfc_buf->vb.vb2_buf.planes[0].data_offset;
+       size = (unsigned int)vb2_plane_size(&mfc_buf->vb.vb2_buf, 0);
+       size = ALIGN(size, 512);
+
+       MFC_WRITEL(addr, S5P_FIMV_E_STREAM_BUFFER_ADDR); /* 16B align */
+       MFC_WRITEL(size, S5P_FIMV_E_STREAM_BUFFER_SIZE);
+       MFC_WRITEL(offset, S5P_FIMV_E_STREAM_BUFFER_OFFSET);
+
+       mfc_debug(2, "[BUFINFO] ctx[%d] set dst index: %d, addr: 0x%08llx\n",
+                       ctx->num, index, addr);
+       mfc_debug(2, "[STREAM] buf_size: %u, offset: %d\n", size, offset);
+
+       return 0;
+}
+
+void s5p_mfc_get_enc_frame_buffer(struct s5p_mfc_ctx *ctx,
+               dma_addr_t addr[], int num_planes)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned long enc_recon_y_addr, enc_recon_c_addr;
+       int i, addr_offset;
+
+       addr_offset = S5P_FIMV_E_ENCODED_SOURCE_FIRST_ADDR;
+
+       for (i = 0; i < num_planes; i++)
+               addr[i] = MFC_READL(addr_offset + (i * 4));
+
+       enc_recon_y_addr = MFC_READL(S5P_FIMV_E_RECON_LUMA_DPB_ADDR);
+       enc_recon_c_addr = MFC_READL(S5P_FIMV_E_RECON_CHROMA_DPB_ADDR);
+
+       mfc_debug(2, "[MEMINFO] recon y: 0x%08lx c: 0x%08lx\n",
+                       enc_recon_y_addr, enc_recon_c_addr);
+}
+
+void s5p_mfc_set_enc_stride(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       int i;
+
+       for (i = 0; i < ctx->raw_buf.num_planes; i++) {
+               MFC_WRITEL(ctx->raw_buf.stride[i],
+                               S5P_FIMV_E_SOURCE_FIRST_STRIDE + (i * 4));
+               mfc_debug(2, "[FRAME] enc src plane[%d] stride: %d\n",
+                               i, ctx->raw_buf.stride[i]);
+       }
+}
+
+int s5p_mfc_set_dynamic_dpb(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf *dst_mb)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_dec *dec = ctx->dec_priv;
+       struct s5p_mfc_raw_info *raw = &ctx->raw_buf;
+       int dst_index;
+       int i;
+
+       dst_index = dst_mb->vb.vb2_buf.index;
+       set_bit(dst_index, &dec->available_dpb);
+       dec->dynamic_set = 1 << dst_index;
+       mfc_debug(2, "[DPB] ADDING Flag after: 0x%lx\n", dec->available_dpb);
+
+       /* for debugging about black bar detection */
+       if (MFC_FEATURE_SUPPORT(dev, dev->pdata->black_bar) && dec->detect_black_bar) {
+               for (i = 0; i < raw->num_planes; i++) {
+                       dec->frame_vaddr[i][dec->frame_cnt] = vb2_plane_vaddr(&dst_mb->vb.vb2_buf, i);
+                       dec->frame_daddr[i][dec->frame_cnt] = dst_mb->addr[0][i];
+                       dec->frame_size[i][dec->frame_cnt] = raw->plane_size[i];
+                       dec->index[i][dec->frame_cnt] = dst_index;
+                       dec->fd[i][dec->frame_cnt] = dst_mb->vb.vb2_buf.planes[0].m.fd;
+               }
+               dec->frame_cnt++;
+               if (dec->frame_cnt >= 30)
+                       dec->frame_cnt = 0;
+       }
+
+       /* decoder dst buffer CFW PROT */
+       s5p_mfc_protect_dpb(ctx, dst_mb);
+
+       for (i = 0; i < raw->num_planes; i++) {
+               MFC_WRITEL(raw->plane_size[i],
+                               S5P_FIMV_D_FIRST_PLANE_DPB_SIZE + i * 4);
+               MFC_WRITEL(dst_mb->addr[0][i],
+                               S5P_FIMV_D_FIRST_PLANE_DPB0 + (i * 0x100 + dst_index * 4));
+               if (ctx->is_10bit)
+                       MFC_WRITEL(raw->plane_size_2bits[i],
+                                       S5P_FIMV_D_FIRST_PLANE_2BIT_DPB_SIZE + (i * 4));
+               mfc_debug(2, "[BUFINFO][DPB] ctx[%d] set dst index: %d, addr[%d]: 0x%08llx\n",
+                               ctx->num, dst_index, i, dst_mb->addr[0][i]);
+       }
+
+       MFC_TRACE_CTX("Set dst[%d] fd: %d, %#llx / avail %#lx used %#x\n",
+                       dst_index, dst_mb->vb.vb2_buf.planes[0].m.fd, dst_mb->addr[0][0],
+                       dec->available_dpb, dec->dynamic_used);
+
+       return 0;
+}
+
+void s5p_mfc_set_pixel_format(struct s5p_mfc_dev *dev, unsigned int format)
+{
+       unsigned int reg = 0;
+       unsigned int pix_val, mem_type_10bit = 0;
+
+       if (dev->pdata->P010_decoding)
+               mem_type_10bit = 1;
+
+       switch (format) {
+       case V4L2_PIX_FMT_NV12M:
+       case V4L2_PIX_FMT_NV12N:
+       case V4L2_PIX_FMT_NV12MT_16X16:
+       case V4L2_PIX_FMT_NV16M:
+               pix_val = 0;
+               break;
+       case V4L2_PIX_FMT_NV21M:
+       case V4L2_PIX_FMT_NV61M:
+               pix_val = 1;
+               break;
+       case V4L2_PIX_FMT_YVU420M:
+               pix_val = 2;
+               break;
+       case V4L2_PIX_FMT_YUV420M:
+       case V4L2_PIX_FMT_YUV420N:
+               pix_val = 3;
+               break;
+       /* For 10bit direct set */
+       case V4L2_PIX_FMT_NV12N_10B:
+       case V4L2_PIX_FMT_NV12M_S10B:
+       case V4L2_PIX_FMT_NV16M_S10B:
+               mem_type_10bit = 0;
+               pix_val = 0;
+               break;
+       case V4L2_PIX_FMT_NV12M_P010:
+       case V4L2_PIX_FMT_NV16M_P210:
+               mem_type_10bit = 1;
+               pix_val = 0;
+               break;
+       case V4L2_PIX_FMT_NV21M_S10B:
+       case V4L2_PIX_FMT_NV61M_S10B:
+               mem_type_10bit = 0;
+               pix_val = 1;
+               break;
+       case V4L2_PIX_FMT_NV21M_P010:
+       case V4L2_PIX_FMT_NV61M_P210:
+               mem_type_10bit = 1;
+               pix_val = 1;
+               break;
+       default:
+               pix_val = 0;
+               break;
+       }
+       reg |= pix_val;
+       reg |= (mem_type_10bit << 4);
+       MFC_WRITEL(reg, S5P_FIMV_PIXEL_FORMAT);
+       mfc_debug(2, "[FRAME] pixel format: %d, mem_type_10bit for 10bit: %d (reg: %#x)\n",
+                       pix_val, mem_type_10bit, reg);
+}
diff --git a/drivers/media/platform/exynos/mfc/mfc_reg.h b/drivers/media/platform/exynos/mfc/mfc_reg.h
new file mode 100644 (file)
index 0000000..3e8be85
--- /dev/null
@@ -0,0 +1,271 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_reg.h
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __MFC_REG_H
+#define __MFC_REG_H __FILE__
+
+#include "mfc_common.h"
+
+#include "mfc_utils.h"
+
+#define MFC_READL(offset)              readl(dev->regs_base + (offset))
+#define MFC_WRITEL(data, offset)       writel((data), dev->regs_base + (offset))
+
+#define MFC_MMU0_READL(offset)         readl(dev->sysmmu0_base + (offset))
+#define MFC_MMU1_READL(offset)         readl(dev->sysmmu1_base + (offset))
+
+#define HWFC_WRITEL(data, offset)      writel((data), dev->hwfc_base + (offset))
+
+#define MMCACHE_READL(offset)          readl(dev->mmcache.base + (offset))
+#define MMCACHE_WRITEL(data, offset)   writel((data), dev->mmcache.base + (offset))
+
+/* version */
+#define s5p_mfc_get_fimv_info()                ((MFC_READL(S5P_FIMV_FW_VERSION)                \
+                                               >> S5P_FIMV_FW_VER_INFO_SHFT)           \
+                                               & S5P_FIMV_FW_VER_INFO_MASK)
+#define s5p_mfc_get_fw_ver_year()      ((MFC_READL(S5P_FIMV_FW_VERSION)                \
+                                               >> S5P_FIMV_FW_VER_YEAR_SHFT)           \
+                                               & S5P_FIMV_FW_VER_YEAR_MASK)
+#define s5p_mfc_get_fw_ver_month()     ((MFC_READL(S5P_FIMV_FW_VERSION)                \
+                                               >> S5P_FIMV_FW_VER_MONTH_SHFT)          \
+                                               & S5P_FIMV_FW_VER_MONTH_MASK)
+#define s5p_mfc_get_fw_ver_date()      ((MFC_READL(S5P_FIMV_FW_VERSION)                \
+                                               >> S5P_FIMV_FW_VER_DATE_SHFT)           \
+                                               & S5P_FIMV_FW_VER_DATE_MASK)
+#define s5p_mfc_get_fw_ver_all()       ((MFC_READL(S5P_FIMV_FW_VERSION)                \
+                                               >> S5P_FIMV_FW_VER_ALL_SHFT)            \
+                                               & S5P_FIMV_FW_VER_ALL_MASK)
+#define s5p_mfc_get_mfc_version()      ((MFC_READL(S5P_FIMV_MFC_VERSION)               \
+                                               >> S5P_FIMV_MFC_VER_SHFT)               \
+                                               & S5P_FIMV_MFC_VER_MASK)
+
+
+/* decoding & display information */
+#define s5p_mfc_get_dec_status()       (MFC_READL(S5P_FIMV_D_DECODED_STATUS)           \
+                                               & S5P_FIMV_DEC_STATUS_DECODED_STATUS_MASK)
+#define s5p_mfc_get_disp_status()      (MFC_READL(S5P_FIMV_D_DISPLAY_STATUS)           \
+                                               & S5P_FIMV_DISP_STATUS_DISPLAY_STATUS_MASK)
+#define s5p_mfc_get_res_change()       ((MFC_READL(S5P_FIMV_D_DISPLAY_STATUS)          \
+                                               >> S5P_FIMV_DISP_STATUS_RES_CHANGE_SHIFT)       \
+                                               & S5P_FIMV_DISP_STATUS_RES_CHANGE_MASK)
+#define s5p_mfc_get_black_bar_detection()      ((MFC_READL(S5P_FIMV_D_DISPLAY_STATUS)          \
+                                               >> S5P_FIMV_DISP_STATUS_BLACK_BAR_DETECT_SHIFT) \
+                                               & S5P_FIMV_DISP_STATUS_BLACK_BAR_DETECT_MASK)
+#define s5p_mfc_get_dpb_change()       ((MFC_READL(S5P_FIMV_D_DISPLAY_STATUS)          \
+                                               >> S5P_FIMV_DISP_STATUS_NEED_DPB_CHANGE_SHIFT)  \
+                                               & S5P_FIMV_DISP_STATUS_NEED_DPB_CHANGE_MASK)
+#define s5p_mfc_get_scratch_change()   ((MFC_READL(S5P_FIMV_D_DISPLAY_STATUS)          \
+                                               >> S5P_FIMV_DISP_STATUS_NEED_SCRATCH_CHANGE_SHIFT)      \
+                                               & S5P_FIMV_DISP_STATUS_NEED_SCRATCH_CHANGE_MASK)
+#define s5p_mfc_get_disp_frame_type()  (MFC_READL(S5P_FIMV_D_DISPLAY_FRAME_TYPE)       \
+                                               & S5P_FIMV_DISPLAY_FRAME_MASK)
+#define s5p_mfc_get_dec_frame_type()   (MFC_READL(S5P_FIMV_D_DECODED_FRAME_TYPE)       \
+                                               & S5P_FIMV_DECODED_FRAME_MASK)
+#define s5p_mfc_get_interlace_type()   ((MFC_READL(S5P_FIMV_D_DISPLAY_FRAME_TYPE)      \
+                                               >> S5P_FIMV_DISPLAY_TEMP_INFO_SHIFT)    \
+                                               & S5P_FIMV_DISPLAY_TEMP_INFO_MASK)
+#define s5p_mfc_is_interlace_picture() ((MFC_READL(S5P_FIMV_D_DISPLAY_STATUS)          \
+                                               >> S5P_FIMV_DISP_STATUS_INTERLACE_SHIFT)\
+                                               & S5P_FIMV_DISP_STATUS_INTERLACE_MASK)
+#define s5p_mfc_is_mbaff_picture()     ((MFC_READL(S5P_FIMV_D_H264_INFO)               \
+                                               >> S5P_FIMV_D_H264_INFO_MBAFF_FRAME_FLAG_SHIFT)\
+                                               & S5P_FIMV_D_H264_INFO_MBAFF_FRAME_FLAG_MASK)
+#define s5p_mfc_get_img_width()                MFC_READL(S5P_FIMV_D_DISPLAY_FRAME_WIDTH)
+#define s5p_mfc_get_img_height()       MFC_READL(S5P_FIMV_D_DISPLAY_FRAME_HEIGHT)
+#define s5p_mfc_get_disp_y_addr()      MFC_READL(S5P_FIMV_D_DISPLAY_LUMA_ADDR)
+#define s5p_mfc_get_dec_y_addr()       MFC_READL(S5P_FIMV_D_DECODED_LUMA_ADDR)
+
+
+/* kind of interrupt */
+#define s5p_mfc_get_int_err()          MFC_READL(S5P_FIMV_ERROR_CODE)
+#define s5p_mfc_get_err(x)             (((x) >> S5P_FIMV_ERR_STATUS_SHIFT)             \
+                                               & S5P_FIMV_ERR_STATUS_MASK)
+#define s5p_mfc_get_warn(x)            (((x) >> S5P_FIMV_WARN_STATUS_SHIFT)            \
+                                               & S5P_FIMV_WARN_STATUS_MASK)
+
+
+/* additional information */
+#define s5p_mfc_get_consumed_stream()          MFC_READL(S5P_FIMV_D_DECODED_NAL_SIZE)
+#define s5p_mfc_get_dpb_count()                        MFC_READL(S5P_FIMV_D_MIN_NUM_DPB)
+#define s5p_mfc_get_min_dpb_size(x)            MFC_READL(S5P_FIMV_D_MIN_FIRST_PLANE_DPB_SIZE + (x * 4))
+#define s5p_mfc_get_scratch_size()             MFC_READL(S5P_FIMV_D_MIN_SCRATCH_BUFFER_SIZE)
+#define s5p_mfc_get_mv_count()                 MFC_READL(S5P_FIMV_D_MIN_NUM_MV)
+#define s5p_mfc_get_inst_no()                  MFC_READL(S5P_FIMV_RET_INSTANCE_ID)
+#define s5p_mfc_get_enc_dpb_count()            MFC_READL(S5P_FIMV_E_NUM_DPB)
+#define s5p_mfc_get_enc_scratch_size()         MFC_READL(S5P_FIMV_E_MIN_SCRATCH_BUFFER_SIZE)
+#define s5p_mfc_get_enc_strm_size()            MFC_READL(S5P_FIMV_E_STREAM_SIZE)
+#define s5p_mfc_get_enc_slice_type()           MFC_READL(S5P_FIMV_E_SLICE_TYPE)
+#define s5p_mfc_get_enc_pic_count()            MFC_READL(S5P_FIMV_E_PICTURE_COUNT)
+#define s5p_mfc_get_sei_avail()                        MFC_READL(S5P_FIMV_D_SEI_AVAIL)
+#define s5p_mfc_get_sei_content_light()                MFC_READL(S5P_FIMV_D_CONTENT_LIGHT_LEVEL_INFO_SEI)
+#define s5p_mfc_get_sei_mastering0()           MFC_READL(S5P_FIMV_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_0)
+#define s5p_mfc_get_sei_mastering1()           MFC_READL(S5P_FIMV_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_1)
+#define s5p_mfc_get_sei_mastering2()           MFC_READL(S5P_FIMV_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_2)
+#define s5p_mfc_get_sei_mastering3()           MFC_READL(S5P_FIMV_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_3)
+#define s5p_mfc_get_sei_mastering4()           MFC_READL(S5P_FIMV_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_4)
+#define s5p_mfc_get_sei_mastering5()           MFC_READL(S5P_FIMV_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_5)
+#define s5p_mfc_get_sei_avail_frame_pack()     (MFC_READL(S5P_FIMV_D_SEI_AVAIL)        \
+                                               & S5P_FIMV_D_SEI_AVAIL_FRAME_PACK_MASK)
+#define s5p_mfc_get_sei_avail_content_light()  ((MFC_READL(S5P_FIMV_D_SEI_AVAIL)       \
+                                               >> S5P_FIMV_D_SEI_AVAIL_CONTENT_LIGHT_SHIFT)    \
+                                               & S5P_FIMV_D_SEI_AVAIL_CONTENT_LIGHT_MASK)
+#define s5p_mfc_get_sei_avail_mastering_display()      ((MFC_READL(S5P_FIMV_D_SEI_AVAIL)       \
+                                               >> S5P_FIMV_D_SEI_AVAIL_MASTERING_DISPLAY_SHIFT)        \
+                                               & S5P_FIMV_D_SEI_AVAIL_MASTERING_DISPLAY_MASK)
+#define s5p_mfc_get_video_signal_type()                ((MFC_READL(S5P_FIMV_D_VIDEO_SIGNAL_TYPE)       \
+                                               >> S5P_FIMV_D_VIDEO_SIGNAL_TYPE_FLAG_SHIFT)     \
+                                               & S5P_FIMV_D_VIDEO_SIGNAL_TYPE_FLAG_MASK)
+#define s5p_mfc_get_colour_description()       ((MFC_READL(S5P_FIMV_D_VIDEO_SIGNAL_TYPE)       \
+                                               >> S5P_FIMV_D_COLOUR_DESCRIPTION_FLAG_SHIFT)    \
+                                               & S5P_FIMV_D_COLOUR_DESCRIPTION_FLAG_MASK)
+#define s5p_mfc_get_black_bar_pos_x()          ((MFC_READL(S5P_FIMV_D_BLACK_BAR_START_POS)     \
+                                               >> S5P_FIMV_D_BLACK_BAR_START_X_SHIFT)          \
+                                               & S5P_FIMV_D_BLACK_BAR_START_X_MASK)
+#define s5p_mfc_get_black_bar_pos_y()          ((MFC_READL(S5P_FIMV_D_BLACK_BAR_START_POS)     \
+                                               >> S5P_FIMV_D_BLACK_BAR_START_Y_SHIFT)          \
+                                               & S5P_FIMV_D_BLACK_BAR_START_Y_MASK)
+#define s5p_mfc_get_black_bar_image_w()                ((MFC_READL(S5P_FIMV_D_BLACK_BAR_IMAGE_SIZE)    \
+                                               >> S5P_FIMV_D_BLACK_BAR_IMAGE_W_SHIFT)  \
+                                               & S5P_FIMV_D_BLACK_BAR_IMAGE_W_MASK)
+#define s5p_mfc_get_black_bar_image_h()                ((MFC_READL(S5P_FIMV_D_BLACK_BAR_IMAGE_SIZE)    \
+                                               >> S5P_FIMV_D_BLACK_BAR_IMAGE_H_SHIFT)  \
+                                               & S5P_FIMV_D_BLACK_BAR_IMAGE_H_MASK)
+#define s5p_mfc_get_mvc_disp_view_id()         (MFC_READL(S5P_FIMV_D_MVC_VIEW_ID)              \
+                                               & S5P_FIMV_D_MVC_VIEW_ID_DISP_MASK)
+#define s5p_mfc_get_profile()                  (MFC_READL(S5P_FIMV_D_DECODED_PICTURE_PROFILE)  \
+                                               & S5P_FIMV_D_DECODED_PIC_PROFILE_MASK)
+#define s5p_mfc_get_luma_bit_depth_minus8()    ((MFC_READL(S5P_FIMV_D_DECODED_PICTURE_PROFILE) \
+                                               >> S5P_FIMV_D_BIT_DEPTH_LUMA_MINUS8_SHIFT)      \
+                                               & S5P_FIMV_D_BIT_DEPTH_LUMA_MINUS8_MASK)
+#define s5p_mfc_get_chroma_bit_depth_minus8()  ((MFC_READL(S5P_FIMV_D_DECODED_PICTURE_PROFILE) \
+                                               >> S5P_FIMV_D_BIT_DEPTH_CHROMA_MINUS8_SHIFT)    \
+                                               & S5P_FIMV_D_BIT_DEPTH_CHROMA_MINUS8_MASK)
+#define s5p_mfc_get_dec_used_flag()            MFC_READL(S5P_FIMV_D_USED_DPB_FLAG_LOWER)
+#define s5p_mfc_get_enc_nal_done_info()                ((MFC_READL(S5P_FIMV_E_NAL_DONE_INFO) & (0x3 << 4)) >> 4)
+#define s5p_mfc_get_chroma_format()            (MFC_READL(S5P_FIMV_D_CHROMA_FORMAT)            \
+                                               & S5P_FIMV_D_CHROMA_FORMAT_MASK)
+#define s5p_mfc_get_color_range()              ((MFC_READL(S5P_FIMV_D_CHROMA_FORMAT)   \
+                                               >> S5P_FIMV_D_COLOR_RANGE_SHIFT)        \
+                                               & S5P_FIMV_D_COLOR_RANGE_MASK)
+#define s5p_mfc_get_color_space()              ((MFC_READL(S5P_FIMV_D_CHROMA_FORMAT)   \
+                                               >> S5P_FIMV_D_COLOR_SPACE_SHIFT)        \
+                                               & S5P_FIMV_D_COLOR_SPACE_MASK)
+#define s5p_mfc_get_num_of_tile()              ((MFC_READL(S5P_FIMV_D_DECODED_STATUS)          \
+                                               >> S5P_FIMV_DEC_STATUS_NUM_OF_TILE_SHIFT)       \
+                                               & S5P_FIMV_DEC_STATUS_NUM_OF_TILE_MASK)
+
+
+/* nal queue information */
+#define s5p_mfc_get_nal_q_input_count()                MFC_READL(S5P_FIMV_NAL_QUEUE_INPUT_COUNT)
+#define s5p_mfc_get_nal_q_output_count()       MFC_READL(S5P_FIMV_NAL_QUEUE_OUTPUT_COUNT)
+#define s5p_mfc_get_nal_q_input_exe_count()    MFC_READL(S5P_FIMV_NAL_QUEUE_INPUT_EXE_COUNT)
+#define s5p_mfc_get_nal_q_info()               MFC_READL(S5P_FIMV_NAL_QUEUE_INFO)
+#define s5p_mfc_get_nal_q_input_addr()         MFC_READL(S5P_FIMV_NAL_QUEUE_INPUT_ADDR)
+#define s5p_mfc_get_nal_q_input_size()         MFC_READL(S5P_FIMV_NAL_QUEUE_INPUT_SIZE)
+#define s5p_mfc_get_nal_q_output_addr()                MFC_READL(S5P_FIMV_NAL_QUEUE_OUTPUT_ADDR)
+#define s5p_mfc_get_nal_q_output_ize()         MFC_READL(S5P_FIMV_NAL_QUEUE_OUTPUT_SIZE)
+
+static inline void s5p_mfc_reset_nal_queue_registers(struct s5p_mfc_dev *dev)
+{
+       MFC_WRITEL(0x0, S5P_FIMV_NAL_QUEUE_INPUT_COUNT);
+       MFC_WRITEL(0x0, S5P_FIMV_NAL_QUEUE_OUTPUT_COUNT);
+       MFC_WRITEL(0x0, S5P_FIMV_NAL_QUEUE_INPUT_EXE_COUNT);
+       MFC_WRITEL(0x0, S5P_FIMV_NAL_QUEUE_INFO);
+}
+
+static inline void s5p_mfc_update_nal_queue_input(struct s5p_mfc_dev *dev,
+       dma_addr_t addr, unsigned int size)
+{
+       MFC_WRITEL(addr, S5P_FIMV_NAL_QUEUE_INPUT_ADDR);
+       MFC_WRITEL(size, S5P_FIMV_NAL_QUEUE_INPUT_SIZE);
+}
+
+static inline void s5p_mfc_update_nal_queue_output(struct s5p_mfc_dev *dev,
+       dma_addr_t addr, unsigned int size)
+{
+       MFC_WRITEL(addr, S5P_FIMV_NAL_QUEUE_OUTPUT_ADDR);
+       MFC_WRITEL(size, S5P_FIMV_NAL_QUEUE_OUTPUT_SIZE);
+}
+
+static inline void s5p_mfc_update_nal_queue_input_count(struct s5p_mfc_dev *dev,
+       unsigned int input_count)
+{
+       MFC_WRITEL(input_count, S5P_FIMV_NAL_QUEUE_INPUT_COUNT);
+}
+
+static inline void s5p_mfc_dec_store_crop_info(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_dec *dec = ctx->dec_priv;
+       u32 left, right, top, bottom;
+
+       left = MFC_READL(S5P_FIMV_D_DISPLAY_CROP_INFO1);
+       right = left >> S5P_FIMV_D_SHARED_CROP_RIGHT_SHIFT;
+       left = left & S5P_FIMV_D_SHARED_CROP_LEFT_MASK;
+       top = MFC_READL(S5P_FIMV_D_DISPLAY_CROP_INFO2);
+       bottom = top >> S5P_FIMV_D_SHARED_CROP_BOTTOM_SHIFT;
+       top = top & S5P_FIMV_D_SHARED_CROP_TOP_MASK;
+
+       dec->cr_left = left;
+       dec->cr_right = right;
+       dec->cr_top = top;
+       dec->cr_bot = bottom;
+}
+
+static inline void s5p_mfc_clear_enc_res_change(struct s5p_mfc_dev *dev)
+{
+       unsigned int reg = 0;
+
+       reg = MFC_READL(S5P_FIMV_E_PARAM_CHANGE);
+       reg &= ~(0x7 << 6);
+       MFC_WRITEL(reg, S5P_FIMV_E_PARAM_CHANGE);
+}
+
+static inline void s5p_mfc_clear_roi_enable(struct s5p_mfc_dev *dev)
+{
+       unsigned int reg = 0;
+
+       reg = MFC_READL(S5P_FIMV_E_RC_ROI_CTRL);
+       reg &= ~(0x1);
+       MFC_WRITEL(reg, S5P_FIMV_E_RC_ROI_CTRL);
+}
+
+void s5p_mfc_dbg_enable(struct s5p_mfc_dev *dev);
+void s5p_mfc_dbg_disable(struct s5p_mfc_dev *dev);
+void s5p_mfc_dbg_set_addr(struct s5p_mfc_dev *dev);
+
+void s5p_mfc_otf_set_frame_addr(struct s5p_mfc_ctx *ctx, int num_planes);
+void s5p_mfc_otf_set_stream_size(struct s5p_mfc_ctx *ctx, unsigned int size);
+void s5p_mfc_otf_set_hwfc_index(struct s5p_mfc_ctx *ctx, int job_id);
+
+int s5p_mfc_set_dec_codec_buffers(struct s5p_mfc_ctx *ctx);
+int s5p_mfc_set_enc_codec_buffers(struct s5p_mfc_ctx *mfc_ctx);
+
+int s5p_mfc_set_dec_stream_buffer(struct s5p_mfc_ctx *ctx,
+               struct s5p_mfc_buf *mfc_buf,
+               unsigned int start_num_byte,
+               unsigned int buf_size);
+
+void s5p_mfc_set_enc_frame_buffer(struct s5p_mfc_ctx *ctx,
+               struct s5p_mfc_buf *mfc_buf, int num_planes);
+int s5p_mfc_set_enc_stream_buffer(struct s5p_mfc_ctx *ctx,
+               struct s5p_mfc_buf *mfc_buf);
+
+void s5p_mfc_get_enc_frame_buffer(struct s5p_mfc_ctx *ctx,
+               dma_addr_t addr[], int num_planes);
+void s5p_mfc_set_enc_stride(struct s5p_mfc_ctx *ctx);
+
+int s5p_mfc_set_dynamic_dpb(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf *dst_vb);
+
+void s5p_mfc_set_pixel_format(struct s5p_mfc_dev *dev, unsigned int format);
+
+#endif /* __MFC_REG_H */
diff --git a/drivers/media/platform/exynos/mfc/mfc_regs_v10.h b/drivers/media/platform/exynos/mfc/mfc_regs_v10.h
new file mode 100644 (file)
index 0000000..94d818e
--- /dev/null
@@ -0,0 +1,743 @@
+/*
+ * drivers/media/platform/exynos/mfc/regs-mfc-v10.h
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __REGS_MFC_V10_H
+#define __REGS_MFC_V10_H __FILE__
+
+#define MFC_MMU_INTERRUPT_STATUS                               0x0060
+#define MFC_MMU_FAULT_TRANS_INFO                               0x0078
+#define MFC_MMU_FAULT_TRANS_INFO_RW_MASK                       0x100000
+#define MFC_MMU_FAULT_TRANS_INFO_AXID_MASK                     0xFFFF
+
+#define HWFC_ENCODING_IDX                                      0x4
+
+/* Codec Common Registers */
+#define S5P_FIMV_RISC_ON                                       0x0000
+#define S5P_FIMV_RISC2HOST_INT                                 0x003C
+#define S5P_FIMV_HOST2RISC_INT                                 0x0044
+#define S5P_FIMV_RISC_BASE_ADDRESS                             0x0054
+
+#define S5P_FIMV_MFC_FW_CLOCK                                  0x1060
+#define S5P_FIMV_MFC_RESET                                     0x1070
+
+#define S5P_FIMV_HOST2RISC_CMD                                 0x1100
+#define S5P_FIMV_RISC2HOST_CMD                                 0x1104
+
+#define S5P_FIMV_MFC_BUS_STATUS                                        0x7018
+#define S5P_FIMV_MFC_RPEND                                     0x7028
+#define S5P_FIMV_MFC_WPEND                                     0x702C
+#define S5P_FIMV_MFC_BUS_RESET_CTRL                            0x7110
+#define S5P_FIMV_MFC_OFF                                       0x7120
+#define S5P_FIMV_MFC_STATE                                     0x7124
+
+#define S5P_FIMV_FW_VERSION                                    0xF000
+#define S5P_FIMV_INSTANCE_ID                                   0xF008
+#define S5P_FIMV_CODEC_TYPE                                    0xF00C
+#define S5P_FIMV_CONTEXT_MEM_ADDR                              0xF014
+#define S5P_FIMV_CONTEXT_MEM_SIZE                              0xF018
+#define S5P_FIMV_SHARED_MEM_ADDR                               0xF01C
+#define S5P_FIMV_PIXEL_FORMAT                                  0xF020
+
+#define S5P_FIMV_METADATA_ENABLE                               0xF024
+#define S5P_FIMV_MFC_VERSION                                   0xF028
+#define S5P_FIMV_DBG_INFO_ENABLE                               0xF02C
+#define S5P_FIMV_DBG_BUFFER_ADDR                               0xF030
+#define S5P_FIMV_DBG_BUFFER_SIZE                               0xF034
+
+#define S5P_FIMV_CODEC_CONTROL                                 0xF038
+#define S5P_FIMV_DEC_TIMEOUT_VALUE                             0xF03C
+#define S5P_FIMV_HED_SHARED_MEM_ADDR                           0xF040
+
+/* NAL QUEUE */
+#define S5P_FIMV_NAL_QUEUE_INPUT_ADDR                          0xF044
+#define S5P_FIMV_NAL_QUEUE_INPUT_SIZE                          0xF048
+#define S5P_FIMV_NAL_QUEUE_OUTPUT_ADDR                         0xF04C
+#define S5P_FIMV_NAL_QUEUE_OUTPUT_SIZE                         0xF050
+#define S5P_FIMV_NAL_QUEUE_INPUT_COUNT                         0xF054
+
+#define S5P_FIMV_RET_INSTANCE_ID                               0xF070
+#define S5P_FIMV_ERROR_CODE                                    0xF074
+#define S5P_FIMV_DBG_BUFFER_OUTPUT_SIZE                                0xF078
+#define S5P_FIMV_METADATA_STATUS                               0xF07C
+
+#define S5P_FIMV_DBG_INFO_STAGE_COUNTER                                0xF088
+
+/* NAL QUEUE */
+#define S5P_FIMV_NAL_QUEUE_OUTPUT_COUNT                                0xF08C
+#define S5P_FIMV_NAL_QUEUE_INPUT_EXE_COUNT                     0xF090
+#define S5P_FIMV_NAL_QUEUE_INFO                                        0xF094
+
+/* Decoder Registers */
+#define S5P_FIMV_D_CRC_CTRL                                    0xF0B0
+#define S5P_FIMV_D_DEC_OPTIONS                                 0xF0B4
+
+#define S5P_FIMV_D_DISPLAY_DELAY                               0xF0B8
+
+#define S5P_FIMV_D_SET_FRAME_WIDTH                             0xF0BC
+#define S5P_FIMV_D_SET_FRAME_HEIGHT                            0xF0C0
+
+#define S5P_FIMV_D_SEI_ENABLE                                  0xF0C4
+
+#define S5P_FIMV_D_FORCE_PIXEL_VAL                             0xF0C8
+
+/* Buffer setting registers */
+/* Session return */
+#define S5P_FIMV_D_MIN_NUM_DPB                                 0xF0F0
+#define S5P_FIMV_D_MIN_FIRST_PLANE_DPB_SIZE                    0xF0F4
+#define S5P_FIMV_D_MIN_SECOND_PLANE_DPB_SIZE                   0xF0F8
+#define S5P_FIMV_D_MIN_THIRD_PLANE_DPB_SIZE                    0xF0FC
+#define S5P_FIMV_D_MIN_NUM_MV                                  0xF100
+#define S5P_FIMV_D_MVC_NUM_VIEWS                               0xF104
+#define S5P_FIMV_D_MIN_SCRATCH_BUFFER_SIZE                     0xF108
+#define S5P_FIMV_D_MIN_FIRST_PLANE_2BIT_DPB_SIZE               0xF10C
+#define S5P_FIMV_D_MIN_SECOND_PLANE_2BIT_DPB_SIZE              0xF110
+#define S5P_FIMV_D_POST_FILTER_LUMA_DPB0                       0xF120
+#define S5P_FIMV_D_POST_FILTER_LUMA_DPB1                       0xF124
+#define S5P_FIMV_D_POST_FILTER_CHROMA_DPB0                     0xF128
+#define S5P_FIMV_D_POST_FILTER_CHROMA_DPB1                     0xF12C
+
+/* Buffers */
+#define S5P_FIMV_D_NUM_DPB                                     0xF130
+#define S5P_FIMV_D_NUM_MV                                      0xF134
+#define S5P_FIMV_D_FIRST_PLANE_DPB_STRIDE_SIZE                 0xF138
+#define S5P_FIMV_D_SECOND_PLANE_DPB_STRIDE_SIZE                        0xF13C
+#define S5P_FIMV_D_THIRD_PLANE_DPB_STRIDE_SIZE                 0xF140
+#define S5P_FIMV_D_FIRST_PLANE_DPB_SIZE                                0xF144
+#define S5P_FIMV_D_SECOND_PLANE_DPB_SIZE                       0xF148
+#define S5P_FIMV_D_THIRD_PLANE_DPB_SIZE                                0xF14C
+#define S5P_FIMV_D_MV_BUFFER_SIZE                              0xF150
+#define S5P_FIMV_D_INIT_BUFFER_OPTIONS                         0xF154
+#define S5P_FIMV_D_FIRST_PLANE_DPB0                            0xF160
+#define S5P_FIMV_D_SECOND_PLANE_DPB0                           0xF260
+#define S5P_FIMV_D_THIRD_PLANE_DPB0                            0xF360
+#define S5P_FIMV_D_MV_BUFFER0                                  0xF460
+#define S5P_FIMV_D_SCRATCH_BUFFER_ADDR                         0xF560
+#define S5P_FIMV_D_SCRATCH_BUFFER_SIZE                         0xF564
+#define S5P_FIMV_D_METADATA_BUFFER_ADDR                                0xF568
+#define S5P_FIMV_D_METADATA_BUFFER_SIZE                                0xF56C
+
+#define S5P_FIMV_D_STATIC_BUFFER_ADDR                          0xF570
+#define S5P_FIMV_D_STATIC_BUFFER_SIZE                          0xF574
+#define S5P_FIMV_D_FIRST_PLANE_2BIT_DPB_SIZE                   0xF578
+#define S5P_FIMV_D_SECOND_PLANE_2BIT_DPB_SIZE                  0xF57C
+#define S5P_FIMV_D_FIRST_PLANE_2BIT_DPB_STRIDE_SIZE            0xF580
+#define S5P_FIMV_D_SECOND_PLANE_2BIT_DPB_STRIDE_SIZE           0xF584
+
+#define S5P_FIMV_D_NAL_START_OPTIONS                           0xF5AC
+
+/* Nal cmd */
+#define S5P_FIMV_D_CPB_BUFFER_ADDR                             0xF5B0
+#define S5P_FIMV_D_CPB_BUFFER_SIZE                             0xF5B4
+#define S5P_FIMV_D_AVAILABLE_DPB_FLAG_UPPER                    0xF5B8
+#define S5P_FIMV_D_AVAILABLE_DPB_FLAG_LOWER                    0xF5BC
+#define S5P_FIMV_D_CPB_BUFFER_OFFSET                           0xF5C0
+#define S5P_FIMV_D_SLICE_IF_ENABLE                             0xF5C4
+#define S5P_FIMV_D_PICTURE_TAG                                 0xF5C8
+#define S5P_FIMV_D_STREAM_DATA_SIZE                            0xF5D0
+#define S5P_FIMV_D_DYNAMIC_DPB_FLAG_UPPER                      0xF5D4
+#define S5P_FIMV_D_DYNAMIC_DPB_FLAG_LOWER                      0xF5D8
+
+/* Nal return */
+#define S5P_FIMV_D_DISPLAY_FRAME_WIDTH                         0xF600
+#define S5P_FIMV_D_DISPLAY_FRAME_HEIGHT                                0xF604
+#define S5P_FIMV_D_DISPLAY_STATUS                              0xF608
+#define S5P_FIMV_D_DISPLAY_FIRST_PLANE_ADDR                    0xF60C
+#define S5P_FIMV_D_DISPLAY_SECOND_PLANE_ADDR                   0xF610
+#define S5P_FIMV_D_DISPLAY_THIRD_PLANE_ADDR                    0xF614
+#define S5P_FIMV_D_DISPLAY_FRAME_TYPE                          0xF618
+#define S5P_FIMV_D_DISPLAY_CROP_INFO1                          0xF61C
+#define S5P_FIMV_D_DISPLAY_CROP_INFO2                          0xF620
+#define S5P_FIMV_D_DISPLAY_PICTURE_PROFILE                     0xF624
+#define S5P_FIMV_D_DISPLAY_FIRST_PLANE_CRC                     0xF628
+#define S5P_FIMV_D_DISPLAY_SECOND_PLANE_CRC                    0xF62C
+#define S5P_FIMV_D_DISPLAY_THIRD_PLANE_CRC                     0xF630
+#define S5P_FIMV_D_DISPLAY_ASPECT_RATIO                                0xF634
+#define S5P_FIMV_D_DISPLAY_EXTENDED_AR                         0xF638
+#define S5P_FIMV_D_DECODED_FRAME_WIDTH                         0xF63C
+#define S5P_FIMV_D_DECODED_FRAME_HEIGHT                                0xF640
+#define S5P_FIMV_D_DECODED_STATUS                              0xF644
+#define S5P_FIMV_D_DECODED_FIRST_PLANE_ADDR                    0xF648
+#define S5P_FIMV_D_DECODED_SECOND_PLANE_ADDR                   0xF64C
+#define S5P_FIMV_D_DECODED_THIRD_PLANE_ADDR                    0xF650
+#define S5P_FIMV_D_DECODED_FRAME_TYPE                          0xF654
+#define S5P_FIMV_D_DECODED_CROP_INFO1                          0xF658
+#define S5P_FIMV_D_DECODED_CROP_INFO2                          0xF65C
+#define S5P_FIMV_D_DECODED_PICTURE_PROFILE                     0xF660
+#define S5P_FIMV_D_DECODED_NAL_SIZE                            0xF664
+#define S5P_FIMV_D_DECODED_FIRST_PLANE_CRC                     0xF668
+#define S5P_FIMV_D_DECODED_SECOND_PLANE_CRC                    0xF66C
+#define S5P_FIMV_D_DECODED_THIRD_PLANE_CRC                     0xF670
+#define S5P_FIMV_D_RET_PICTURE_TAG_TOP                         0xF674
+#define S5P_FIMV_D_RET_PICTURE_TAG_BOT                         0xF678
+#define S5P_FIMV_D_RET_PICTURE_TIME_TOP                                0xF67C
+#define S5P_FIMV_D_RET_PICTURE_TIME_BOT                                0xF680
+#define S5P_FIMV_D_CHROMA_FORMAT                               0xF684
+
+#define S5P_FIMV_D_VC1_INFO                                    0xF688
+#define S5P_FIMV_D_MPEG4_INFO                                  0xF68C
+#define S5P_FIMV_D_H264_INFO                                   0xF690
+#define S5P_FIMV_D_HEVC_INFO                                   0xF6A0
+#define S5P_FIMV_D_BPG_INFO                                    0xF6A8
+
+#define S5P_FIMV_D_METADATA_ADDR_CONCEALED_MB                  0xF6B0
+#define S5P_FIMV_D_METADATA_SIZE_CONCEALED_MB                  0xF6B4
+#define S5P_FIMV_D_METADATA_ADDR_VC1_PARAM                     0xF6B8
+#define S5P_FIMV_D_METADATA_SIZE_VC1_PARAM                     0xF6BC
+#define S5P_FIMV_D_METADATA_ADDR_SEI_NAL                       0xF6C0
+#define S5P_FIMV_D_METADATA_SIZE_SEI_NAL                       0xF6C4
+#define S5P_FIMV_D_METADATA_ADDR_VUI                           0xF6C8
+#define S5P_FIMV_D_METADATA_SIZE_VUI                           0xF6CC
+#define S5P_FIMV_D_METADATA_ADDR_MVCVUI                                0xF6D0
+#define S5P_FIMV_D_METADATA_SIZE_MVCVUI                                0xF6D4
+
+#define S5P_FIMV_D_MVC_VIEW_ID                                 0xF6D8
+
+#define S5P_FIMV_D_SEI_AVAIL                                   0xF6DC
+#define S5P_FIMV_D_FRAME_PACK_ARRGMENT_ID                      0xF6E0
+#define S5P_FIMV_D_FRAME_PACK_SEI_INFO                         0xF6E4
+#define S5P_FIMV_D_FRAME_PACK_GRID_POS                         0xF6E8
+
+#define S5P_FIMV_D_DISPLAY_RECOVERY_SEI_INFO                   0xF6EC
+#define S5P_FIMV_D_DECODED_RECOVERY_SEI_INFO                   0xF6F0
+
+#define S5P_FIMV_D_DISPLAY_FIRST_PLANE_2BIT_CRC                        0xF6FC
+#define S5P_FIMV_D_DISPLAY_SECOND_PLANE_2BIT_CRC               0xF700
+#define S5P_FIMV_D_DECODED_FIRST_PLANE_2BIT_CRC                        0xF704
+#define S5P_FIMV_D_DECODED_SECOND_PLANE_2BIT_CRC               0xF708
+
+#define S5P_FIMV_D_VIDEO_SIGNAL_TYPE                           0xF70C
+#define S5P_FIMV_D_CONTENT_LIGHT_LEVEL_INFO_SEI                        0xF710
+#define S5P_FIMV_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_0       0xF714
+#define S5P_FIMV_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_1       0xF718
+
+#define S5P_FIMV_D_USED_DPB_FLAG_UPPER                         0xF720
+#define S5P_FIMV_D_USED_DPB_FLAG_LOWER                         0xF724
+
+#define S5P_FIMV_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_2       0xF728
+#define S5P_FIMV_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_3       0xF72C
+#define S5P_FIMV_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_4       0xF730
+#define S5P_FIMV_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_5       0xF734
+
+#define S5P_FIMV_D_BLACK_BAR_START_POS                         0xF738
+#define S5P_FIMV_D_BLACK_BAR_IMAGE_SIZE                                0xF73C
+
+#define S5P_FIMV_D_DISPLAY_LUMA_ADDR                           0xF60C
+#define S5P_FIMV_D_DISPLAY_CHROMA_ADDR                         0xF610
+
+#define S5P_FIMV_D_DECODED_LUMA_ADDR                           0xF648
+#define S5P_FIMV_D_DECODED_CHROMA_ADDR                         0xF64C
+
+/* Encoder Registers */
+#define S5P_FIMV_E_CROPPED_FRAME_WIDTH                         0xF778
+#define S5P_FIMV_E_CROPPED_FRAME_HEIGHT                                0xF77C
+#define S5P_FIMV_E_FRAME_CROP_OFFSET                           0xF780
+#define S5P_FIMV_E_ENC_OPTIONS                                 0xF784
+#define S5P_FIMV_E_PICTURE_PROFILE                             0xF788
+#define S5P_FIMV_E_VBV_BUFFER_SIZE                             0xF78C
+#define S5P_FIMV_E_VBV_INIT_DELAY                              0xF790
+#define S5P_FIMV_E_FIXED_PICTURE_QP                            0xF794
+#define S5P_FIMV_E_RC_CONFIG                                   0xF798
+#define S5P_FIMV_E_RC_QP_BOUND                                 0xF79C
+#define S5P_FIMV_E_RC_QP_BOUND_PB                              0xF7A0
+#define S5P_FIMV_E_RC_MODE                                     0xF7A4
+
+#define S5P_FIMV_E_MB_RC_CONFIG                                        0xF7A8
+#define S5P_FIMV_E_PADDING_CTRL                                        0xF7AC
+#define S5P_FIMV_E_AIR_THRESHOLD                               0xF7B0
+
+#define S5P_FIMV_E_MV_HOR_RANGE                                        0xF7B4
+#define S5P_FIMV_E_MV_VER_RANGE                                        0xF7B8
+
+#define S5P_FIMV_E_HIGH_QUALITY_MODE                           0xF7C0
+#define S5P_FIMV_E_VIDEO_SIGNAL_TYPE                           0xF7C4
+
+#define S5P_FIMV_E_SAO_WEIGHT0                                 0xF7C8
+#define S5P_FIMV_E_SAO_WEIGHT1                                 0xF7CC
+
+#define S5P_FIMV_E_NUM_DPB                                     0xF890
+#define S5P_FIMV_E_MIN_SCRATCH_BUFFER_SIZE                     0xF894
+
+#define S5P_FIMV_E_LUMA_DPB                                    0xF8C0
+#define S5P_FIMV_E_CHROMA_DPB                                  0xF904
+#define S5P_FIMV_E_ME_BUFFER                                   0xF948
+
+#define S5P_FIMV_E_SCRATCH_BUFFER_ADDR                         0xF98C
+#define S5P_FIMV_E_SCRATCH_BUFFER_SIZE                         0xF990
+#define S5P_FIMV_E_TMV_BUFFER0                                 0xF994
+#define S5P_FIMV_E_TMV_BUFFER1                                 0xF998
+#define S5P_FIMV_E_IR_BUFFER_ADDR                              0xF99C
+#define S5P_FIMV_E_SOURCE_FIRST_2BIT_ADDR                      0xF9D0
+#define S5P_FIMV_E_SOURCE_SECOND_2BIT_ADDR                     0xF9D4
+#define S5P_FIMV_E_SOURCE_FIRST_2BIT_STRIDE                    0xF9D8
+#define S5P_FIMV_E_SOURCE_SECOND_2BIT_STRIDE                   0xF9DC
+#define S5P_FIMV_E_SOURCE_FIRST_ADDR                           0xF9E0
+#define S5P_FIMV_E_SOURCE_SECOND_ADDR                          0xF9E4
+#define S5P_FIMV_E_SOURCE_THIRD_ADDR                           0xF9E8
+#define S5P_FIMV_E_SOURCE_FIRST_STRIDE                         0xF9EC
+#define S5P_FIMV_E_SOURCE_SECOND_STRIDE                                0xF9F0
+#define S5P_FIMV_E_SOURCE_THIRD_STRIDE                         0xF9F4
+#define S5P_FIMV_E_STREAM_BUFFER_ADDR                          0xF9F8
+#define S5P_FIMV_E_STREAM_BUFFER_SIZE                          0xF9FC
+#define S5P_FIMV_E_ROI_BUFFER_ADDR                             0xFA00
+
+#define S5P_FIMV_E_PARAM_CHANGE                                        0xFA04
+#define S5P_FIMV_E_IR_SIZE                                     0xFA08
+#define S5P_FIMV_E_GOP_CONFIG                                  0xFA0C
+#define S5P_FIMV_E_MSLICE_MODE                                 0xFA10
+#define S5P_FIMV_E_MSLICE_SIZE_MB                              0xFA14
+#define S5P_FIMV_E_MSLICE_SIZE_BITS                            0xFA18
+#define S5P_FIMV_E_FRAME_INSERTION                             0xFA1C
+
+#define S5P_FIMV_E_RC_FRAME_RATE                               0xFA20
+#define S5P_FIMV_E_RC_BIT_RATE                                 0xFA24
+#define S5P_FIMV_E_RC_ROI_CTRL                                 0xFA2C
+#define S5P_FIMV_E_PICTURE_TAG                                 0xFA30
+#define S5P_FIMV_E_BIT_COUNT_ENABLE                            0xFA34
+#define S5P_FIMV_E_MAX_BIT_COUNT                               0xFA38
+#define S5P_FIMV_E_MIN_BIT_COUNT                               0xFA3C
+
+#define S5P_FIMV_E_METADATA_BUFFER_ADDR                                0xFA40
+#define S5P_FIMV_E_METADATA_BUFFER_SIZE                                0xFA44
+
+#define S5P_FIMV_E_ENCODING_ORDER_TIME_INFO                    0xFA50
+#define S5P_FIMV_E_ENCODING_ORDER_INFO                         0xFA54
+#define S5P_FIMV_E_STREAM_BUFFER_OFFSET                                0xFA58
+#define S5P_FIMV_E_GOP_CONFIG2                                 0xFA5C
+#define S5P_FIMV_E_WEIGHT_FOR_WEIGHTED_PREDICTION              0xFA60
+
+#define S5P_FIMV_E_ENCODED_SOURCE_FIRST_ADDR                   0xFA70
+#define S5P_FIMV_E_ENCODED_SOURCE_SECOND_ADDR                  0xFA74
+#define S5P_FIMV_E_ENCODED_SOURCE_THIRD_ADDR                   0xFA78
+
+#define S5P_FIMV_E_STREAM_SIZE                                 0xFA80
+#define S5P_FIMV_E_SLICE_TYPE                                  0xFA84
+#define S5P_FIMV_E_PICTURE_COUNT                               0xFA88
+#define S5P_FIMV_E_RET_PICTURE_TAG                             0xFA8C
+
+#define S5P_FIMV_E_RECON_LUMA_DPB_ADDR                         0xFA9C
+#define S5P_FIMV_E_RECON_CHROMA_DPB_ADDR                       0xFAA0
+#define S5P_FIMV_E_METADATA_ADDR_ENC_SLICE                     0xFAA4
+#define S5P_FIMV_E_METADATA_SIZE_ENC_SLICE                     0xFAA8
+
+#define S5P_FIMV_E_NAL_DONE_INFO                               0xFAEC
+
+#define S5P_FIMV_E_MPEG4_OPTIONS                               0xFB10
+#define S5P_FIMV_E_MPEG4_HEC_PERIOD                            0xFB14
+
+#define S5P_FIMV_E_BPG_OPTIONS                                 0xFB1C
+#define S5P_FIMV_E_BPG_EXT_CTB_QP_CTRL                         0xFB20
+#define S5P_FIMV_E_BPG_CHROMA_QP_OFFSET                                0xFB24
+#define S5P_FIMV_E_BPG_EXTENSION_DATA_SIZE                     0xFB28
+
+#define S5P_FIMV_E_H264_HD_SVC_EXTENSION_0                     0xFB44
+#define S5P_FIMV_E_H264_HD_SVC_EXTENSION_1                     0xFB48
+#define S5P_FIMV_E_ASPECT_RATIO                                        0xFB4C
+#define S5P_FIMV_E_EXTENDED_SAR                                        0xFB50
+
+#define S5P_FIMV_E_H264_OPTIONS                                        0xFB54
+#define S5P_FIMV_E_H264_OPTIONS_2                              0xFB58
+#define S5P_FIMV_E_H264_LF_ALPHA_OFFSET                                0xFB5C
+#define S5P_FIMV_E_H264_LF_BETA_OFFSET                         0xFB60
+#define S5P_FIMV_E_H264_REFRESH_PERIOD                         0xFB64
+
+#define S5P_FIMV_E_H264_FMO_SLICE_GRP_MAP_TYPE                 0xFB68
+#define S5P_FIMV_E_H264_FMO_NUM_SLICE_GRP_MINUS1               0xFB6C
+#define S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_DIR               0xFB70
+#define S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_RATE_MINUS1       0xFB74
+#define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_0                        0xFB78
+#define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_1                        0xFB7C
+#define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_2                        0xFB80
+#define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_3                        0xFB84
+
+#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_0                      0xFB88
+#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_1                      0xFB8C
+#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_2                      0xFB90
+#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_3                      0xFB94
+#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_4                      0xFB98
+#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_5                      0xFB9C
+#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_6                      0xFBA0
+#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_7                      0xFBA4
+#define S5P_FIMV_E_H264_CHROMA_QP_OFFSET                       0xFBA8
+
+#define S5P_FIMV_E_NUM_T_LAYER                                 0xFBAC
+#define S5P_FIMV_E_HIERARCHICAL_QP_LAYER0                      0xFBB0
+#define S5P_FIMV_E_HIERARCHICAL_QP_LAYER1                      0xFBB4
+#define S5P_FIMV_E_HIERARCHICAL_QP_LAYER2                      0xFBB8
+#define S5P_FIMV_E_HIERARCHICAL_QP_LAYER3                      0xFBBC
+#define S5P_FIMV_E_HIERARCHICAL_QP_LAYER4                      0xFBC0
+#define S5P_FIMV_E_HIERARCHICAL_QP_LAYER5                      0xFBC4
+#define S5P_FIMV_E_HIERARCHICAL_QP_LAYER6                      0xFBC8
+
+/* For backward compatibility */
+#define S5P_FIMV_E_H264_FRAME_PACKING_SEI_INFO                 0xFC4C
+
+#define S5P_FIMV_E_H264_NAL_CONTROL                            0xFD14
+#define S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER0                        0xFD18
+#define S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER1                        0xFD1C
+#define S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER2                        0xFD20
+#define S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER3                        0xFD24
+#define S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER4                        0xFD28
+#define S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER5                        0xFD2C
+#define S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER6                        0xFD30
+
+#define S5P_FIMV_E_MVC_FRAME_QP_VIEW1                          0xFD40
+#define S5P_FIMV_E_MVC_RC_FRAME_RATE_VIEW1                     0xFD44
+#define S5P_FIMV_E_MVC_RC_BIT_RATE_VIEW1                       0xFD48
+#define S5P_FIMV_E_MVC_RC_QBOUND_VIEW1                         0xFD4C
+#define S5P_FIMV_E_MVC_RC_MODE_VIEW1                           0xFD50
+#define S5P_FIMV_E_MVC_INTER_VIEW_PREDICTION_ON                        0xFD80
+
+#define S5P_FIMV_E_VP9_OPTION                                  0xFD90
+#define S5P_FIMV_E_VP9_FILTER_OPTION                           0xFD94
+#define S5P_FIMV_E_VP9_GOLDEN_FRAME_OPTION                     0xFD98
+#define S5P_FIMV_E_VP8_OPTION                                  0xFDB0
+#define S5P_FIMV_E_VP8_FILTER_OPTION                           0xFDB4
+#define S5P_FIMV_E_VP8_GOLDEN_FRAME_OPTION                     0xFDB8
+
+#define S5P_FIMV_E_HEVC_OPTIONS_2                              0xFDC4
+
+#define S5P_FIMV_E_HEVC_OPTIONS                                        0xFDD4
+#define S5P_FIMV_E_HEVC_REFRESH_PERIOD                         0xFDD8
+#define S5P_FIMV_E_HEVC_CHROMA_QP_OFFSET                       0xFDDC
+#define S5P_FIMV_E_HEVC_LF_BETA_OFFSET_DIV2                    0xFDE0
+#define S5P_FIMV_E_HEVC_LF_TC_OFFSET_DIV2                      0xFDE4
+#define S5P_FIMV_E_HEVC_NAL_CONTROL                            0xFDE8
+
+#define S5P_FIMV_E_VP8_NAL_CONTROL                             0xFDF0
+#define S5P_FIMV_E_VP9_NAL_CONTROL                             0xFDF4
+#define S5P_FIMV_E_CONTENT_LIGHT_LEVEL_INFO_SEI                        0xFDF8
+#define S5P_FIMV_E_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_0       0xFDFC
+#define S5P_FIMV_E_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_1       0xFE00
+#define S5P_FIMV_E_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_2       0xFE04
+#define S5P_FIMV_E_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_3       0xFE08
+#define S5P_FIMV_E_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_4       0xFE0C
+#define S5P_FIMV_E_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_5       0xFE10
+
+
+#define S5P_FIMV_REG_CLEAR_BEGIN                       0xf000
+#define S5P_FIMV_REG_CLEAR_COUNT                       1024
+
+
+/* Bit Definitions */
+/* 0x1100: S5P_FIMV_HOST2RISC_CMD */
+#define S5P_FIMV_H2R_CMD_EMPTY                         0
+#define S5P_FIMV_H2R_CMD_SYS_INIT                      1
+#define S5P_FIMV_H2R_CMD_OPEN_INSTANCE                 2
+#define S5P_FIMV_H2R_CMD_SEQ_HEADER                    3
+#define S5P_FIMV_H2R_CMD_INIT_BUFFERS                  4
+#define S5P_FIMV_H2R_CMD_NAL_START                     5
+#define S5P_FIMV_H2R_CMD_CLOSE_INSTANCE                        6
+#define S5P_FIMV_H2R_CMD_SLEEP                         7
+#define S5P_FIMV_H2R_CMD_WAKEUP                                8
+#define S5P_FIMV_H2R_CMD_LAST_FRAME                    9
+#define S5P_FIMV_H2R_CMD_DPB_FLUSH                     10
+#define S5P_FIMV_H2R_CMD_NAL_ABORT                     11
+#define S5P_FIMV_H2R_CMD_CACHE_FLUSH                   12
+#define S5P_FIMV_H2R_CMD_NAL_QUEUE                     13
+#define S5P_FIMV_H2R_CMD_STOP_QUEUE                    14
+
+
+/* 0x1104: S5P_FIMV_RISC2HOST_CMD */
+#define S5P_FIMV_RISC2HOST_CMD_MASK                    0x1FFFF
+#define S5P_FIMV_R2H_CMD_EMPTY                         0
+#define S5P_FIMV_R2H_CMD_SYS_INIT_RET                  1
+#define S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET             2
+#define S5P_FIMV_R2H_CMD_SEQ_DONE_RET                  3
+#define S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET              4
+#define S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET            6
+#define S5P_FIMV_R2H_CMD_SLEEP_RET                     7
+#define S5P_FIMV_R2H_CMD_WAKEUP_RET                    8
+#define S5P_FIMV_R2H_CMD_COMPLETE_SEQ_RET              9
+#define S5P_FIMV_R2H_CMD_DPB_FLUSH_RET                 10
+#define S5P_FIMV_R2H_CMD_NAL_ABORT_RET                 11
+#define S5P_FIMV_R2H_CMD_FW_STATUS_RET                 12
+#define S5P_FIMV_R2H_CMD_FRAME_DONE_RET                        13
+#define S5P_FIMV_R2H_CMD_FIELD_DONE_RET                        14
+#define S5P_FIMV_R2H_CMD_SLICE_DONE_RET                        15
+#define S5P_FIMV_R2H_CMD_ENC_BUFFER_FULL_RET           16
+#define S5P_FIMV_R2H_CMD_QUEUE_DONE_RET                        17
+#define S5P_FIMV_R2H_CMD_COMPLETE_QUEUE_RET            18
+#define S5P_FIMV_R2H_CMD_CACHE_FLUSH_RET               20
+#define S5P_FIMV_R2H_CMD_ERR_RET                       32
+
+
+/* 0xF000: S5P_FIMV_FW_VERSION */
+#define S5P_FIMV_FW_VER_INFO_MASK                      0xFF
+#define S5P_FIMV_FW_VER_INFO_SHFT                      24
+#define S5P_FIMV_FW_VER_YEAR_MASK                      0xFF
+#define S5P_FIMV_FW_VER_YEAR_SHFT                      16
+#define S5P_FIMV_FW_VER_MONTH_MASK                     0xFF
+#define S5P_FIMV_FW_VER_MONTH_SHFT                     8
+#define S5P_FIMV_FW_VER_DATE_MASK                      0xFF
+#define S5P_FIMV_FW_VER_DATE_SHFT                      0
+#define S5P_FIMV_FW_VER_ALL_MASK                       0xFFFFFF
+#define S5P_FIMV_FW_VER_ALL_SHFT                       0
+
+
+/* 0xF00C: S5P_FIMV_CODEC_TYPE */
+#define MFC_FORMATS_NO_CODEC                           -1
+/* Decoder */
+#define S5P_FIMV_CODEC_H264_DEC                                0
+#define S5P_FIMV_CODEC_H264_MVC_DEC                    1
+#define S5P_FIMV_CODEC_MPEG4_DEC                       3
+#define S5P_FIMV_CODEC_FIMV1_DEC                       4
+#define S5P_FIMV_CODEC_FIMV2_DEC                       5
+#define S5P_FIMV_CODEC_FIMV3_DEC                       6
+#define S5P_FIMV_CODEC_FIMV4_DEC                       7
+#define S5P_FIMV_CODEC_H263_DEC                                8
+#define S5P_FIMV_CODEC_VC1_RCV_DEC                     9
+#define S5P_FIMV_CODEC_VC1_DEC                         10
+#define S5P_FIMV_CODEC_MPEG2_DEC                       13
+#define S5P_FIMV_CODEC_VP8_DEC                         14
+#define S5P_FIMV_CODEC_HEVC_DEC                                17
+#define S5P_FIMV_CODEC_VP9_DEC                         18
+/* Encoder */
+#define S5P_FIMV_CODEC_H264_ENC                                20
+#define S5P_FIMV_CODEC_H264_MVC_ENC                    21
+#define S5P_FIMV_CODEC_MPEG4_ENC                       23
+#define S5P_FIMV_CODEC_H263_ENC                                24
+#define S5P_FIMV_CODEC_VP8_ENC                         25
+#define S5P_FIMV_CODEC_HEVC_ENC                                26
+#define S5P_FIMV_CODEC_VP9_ENC                         27
+
+#define S5P_FIMV_CODEC_BPG_DEC                         32
+#define S5P_FIMV_CODEC_BPG_ENC                         33
+
+/* 0xF028: S5P_FIMV_MFC_VERSION */
+#define S5P_FIMV_MFC_VER_MASK                          0xFFFFFFFF
+#define S5P_FIMV_MFC_VER_SHFT                          0
+
+
+/* 0xF074: S5P_FIMV_ERROR_CODE */
+#define S5P_FIMV_ERR_STATUS_MASK                       0xFFFF
+#define S5P_FIMV_ERR_STATUS_SHIFT                      0
+#define S5P_FIMV_WARN_STATUS_MASK                      0xFFFF
+#define S5P_FIMV_WARN_STATUS_SHIFT                     16
+/* Error number */
+#define S5P_FIMV_ERR_BUFFER_FULL                       18
+#define S5P_FIMV_ERR_NO_AVAILABLE_DPB                  33
+#define S5P_FIMV_ERR_NO_KEY_FRAME                      34
+#define S5P_FIMV_ERR_VPS_ONLY_ERROR                    42
+#define S5P_FIMV_ERR_INSUFFICIENT_DPB_SIZE             57
+#define S5P_FIMV_ERR_INSUFFICIENT_NUM_DPB              58
+#define S5P_FIMV_ERR_INSUFFICIENT_MV_BUF_SIZE          60
+#define S5P_FIMV_ERR_NULL_SCRATCH                      61
+#define S5P_FIMV_ERR_INSUFFICIENT_SCRATCH_BUF_SIZE     62
+
+#define S5P_FIMV_ERR_UNSUPPORTED_FEATURE               100
+#define S5P_FIMV_ERR_UNSUPPORTED_RESOLUTION            101
+#define S5P_FIMV_ERR_HEADER_NOT_FOUND                  102
+#define S5P_FIMV_ERR_INVAILD_NAL_TYPE                  103
+#define S5P_FIMV_ERR_SEQUENCE_HEADER                   104
+#define S5P_FIMV_ERR_MFC_TIMEOUT                       140
+#define S5P_FIMV_ERR_TS_MUX_TIMEOUT                    141
+#define S5P_FIMV_ERR_G2D_TIMEOUT                       142
+#define S5P_FIMV_ERR_FRAME_CONCEAL                     150
+#define S5P_FIMV_ERR_WARNINGS_START                    160
+#define S5P_FIMV_ERR_BROKEN_LINK                       161
+#define S5P_FIMV_ERR_SYNC_POINT_NOT_RECEIVED           190
+#define S5P_FIMV_ERR_NON_PAIRED_FIELD                  191
+#define S5P_FIMV_ERR_WARNINGS_END                      222
+
+
+/* 0xF0B4: S5P_FIMV_D_DEC_OPTIONS */
+#define S5P_FIMV_D_DEC_OPT_DISPLAY_DELAY_EN_SHIFT      3
+#define S5P_FIMV_D_DEC_OPT_FMO_ASO_CTRL_MASK           0x1
+#define S5P_FIMV_D_DEC_OPT_FMO_ASO_CTRL_SHIFT          4
+#define S5P_FIMV_D_DEC_OPT_IDR_DECODING_MASK           0x1
+#define S5P_FIMV_D_DEC_OPT_IDR_DECODING_SHIFT          6
+#define S5P_FIMV_D_DEC_OPT_DISCARD_RCV_HEADER_SHIFT    7
+#define S5P_FIMV_D_DEC_OPT_CONCEAL_CONTROL_SHIFT       8
+#define S5P_FIMV_D_DEC_OPT_PARALLEL_DISABLE_SHIFT      11
+#define S5P_FIMV_D_DEC_OPT_REALLOC_CONTROL_SHIFT       13
+#define S5P_FIMV_D_DEC_OPT_SPECIAL_PARSING_SHIFT       15
+#define S5P_FIMV_D_DEC_OPT_THUMBNAIL_DECODING          16
+
+
+/* 0xF0C4: S5P_FIMV_D_SEI_ENABLE */
+#define S5P_FIMV_D_SEI_ENABLE_NEED_INIT_BUFFER_SHIFT   1
+#define S5P_FIMV_D_SEI_ENABLE_RECOVERY_PARSING_SHIFT   2
+#define S5P_FIMV_D_SEI_ENABLE_CONTENT_LIGHT_SHIFT      4
+#define S5P_FIMV_D_SEI_ENABLE_MASTERING_DISPLAY_SHIFT  5
+
+
+/* 0xF154: S5P_FIMV_D_INIT_BUFFER_OPTIONS */
+#define S5P_FIMV_D_INIT_BUF_OPT_LF_CTRL_MASK           0x3
+#define S5P_FIMV_D_INIT_BUF_OPT_LF_CTRL_SHIFT          1
+#define S5P_FIMV_D_INIT_BUF_OPT_DYNAMIC_DPB_SET_SHIFT  3
+#define S5P_FIMV_D_INIT_BUF_OPT_COPY_NOT_CODED_SHIFT   4
+#define S5P_FIMV_D_INIT_BUF_OPT_DITHERING_EN_SHIFT     6
+#define S5P_FIMV_D_INIT_BUF_OPT_STRIDE_SIZE_ALIGN      7
+
+
+/* 0xF5AC: S5P_FIMV_D_NAL_START_OPTIONS */
+#define S5P_FIMV_D_NAL_START_OPT_BLACK_BAR_SHIFT       3
+
+
+/* 0xF608: S5P_FIMV_D_DISPLAY_STATUS */
+#define S5P_FIMV_DISP_STATUS_DISPLAY_STATUS_MASK       0x7
+#define S5P_FIMV_DISP_STATUS_INTERLACE_MASK            0x1
+#define S5P_FIMV_DISP_STATUS_INTERLACE_SHIFT           3
+#define S5P_FIMV_DISP_STATUS_RES_CHANGE_MASK           0x3
+#define S5P_FIMV_DISP_STATUS_RES_CHANGE_SHIFT          4
+#define S5P_FIMV_DISP_STATUS_NEED_DPB_CHANGE_MASK      0x1
+#define S5P_FIMV_DISP_STATUS_NEED_DPB_CHANGE_SHIFT     9
+#define S5P_FIMV_DISP_STATUS_NEED_SCRATCH_CHANGE_MASK  0x1
+#define S5P_FIMV_DISP_STATUS_NEED_SCRATCH_CHANGE_SHIFT 10
+#define S5P_FIMV_DISP_STATUS_NEED_EMPTY_DPB_MASK       0x1
+#define S5P_FIMV_DISP_STATUS_NEED_EMPTY_DPB_SHIFT      12
+#define S5P_FIMV_DISP_STATUS_BLACK_BAR_DETECT_MASK     0x3
+#define S5P_FIMV_DISP_STATUS_BLACK_BAR_DETECT_SHIFT    13
+#define S5P_FIMV_DISP_STATUS_NOT_DETECTED              0x0
+#define S5P_FIMV_DISP_STATUS_BLACK_BAR                 0x1
+#define S5P_FIMV_DISP_STATUS_BLACK_SCREEN              0x2
+
+
+/* 0xF618: S5P_FIMV_D_DISPLAY_FRAME_TYPE */
+#define S5P_FIMV_DISPLAY_FRAME_MASK                    0x7
+#define S5P_FIMV_DISPLAY_TEMP_INFO_MASK                        0x1
+#define S5P_FIMV_DISPLAY_TEMP_INFO_SHIFT               7
+#define S5P_FIMV_DISPLAY_FRAME_NOT_CODED               0
+#define S5P_FIMV_DISPLAY_FRAME_I                       1
+#define S5P_FIMV_DISPLAY_FRAME_P                       2
+#define S5P_FIMV_DISPLAY_FRAME_B                       3
+
+
+/* 0xF61C: S5P_FIMV_D_DISPLAY_CROP_INFO1 */
+#define S5P_FIMV_D_SHARED_CROP_LEFT_MASK               0xFFFF
+#define S5P_FIMV_D_SHARED_CROP_RIGHT_SHIFT             16
+
+
+/* 0xF620: S5P_FIMV_D_DISPLAY_CROP_INFO2 */
+#define S5P_FIMV_D_SHARED_CROP_TOP_MASK                        0xFFFF
+#define S5P_FIMV_D_SHARED_CROP_BOTTOM_SHIFT            16
+
+
+/* 0xF644: S5P_FIMV_D_DECODED_STATUS */
+#define S5P_FIMV_DEC_STATUS_DECODED_STATUS_MASK                0x7
+#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_NUM_OF_TILE_MASK           0xF
+#define S5P_FIMV_DEC_STATUS_NUM_OF_TILE_SHIFT          15
+
+
+/* 0xF654: S5P_FIMV_D_DECODED_FRAME_TYPE */
+#define S5P_FIMV_DECODED_FRAME_MASK                    0x7
+#define S5P_FIMV_DECODED_FRAME_NOT_CODED               0
+#define S5P_FIMV_DECODED_FRAME_I                       1
+#define S5P_FIMV_DECODED_FRAME_P                       2
+#define S5P_FIMV_DECODED_FRAME_B                       3
+
+
+/* 0xF660: S5P_FIMV_D_DECODED_PICTURE_PROFILE */
+#define S5P_FIMV_D_DECODED_PIC_PROFILE_MASK            0x1F
+#define S5P_FIMV_D_BIT_DEPTH_CHROMA_MINUS8_MASK                0x7
+#define S5P_FIMV_D_BIT_DEPTH_CHROMA_MINUS8_SHIFT       19
+#define S5P_FIMV_D_BIT_DEPTH_LUMA_MINUS8_MASK          0x7
+#define S5P_FIMV_D_BIT_DEPTH_LUMA_MINUS8_SHIFT         16
+#define S5P_FIMV_D_PROFILE_HEVC_MAIN                   1
+#define S5P_FIMV_D_PROFILE_HEVC_MAIN_10                        2
+#define S5P_FIMV_D_PROFILE_HEVC_RANGE_EXT              4
+
+
+/* 0xF684: S5P_FIMV_D_CHROMA_FORMAT */
+#define S5P_FIMV_D_CHROMA_FORMAT_MASK                  0x3
+#define S5P_FIMV_D_COLOR_RANGE_MASK                    0x1
+#define S5P_FIMV_D_COLOR_RANGE_SHIFT                   3
+#define S5P_FIMV_D_COLOR_SPACE_MASK                    0xF
+#define S5P_FIMV_D_COLOR_SPACE_SHIFT                   4
+#define S5P_FIMV_D_COLOR_UNKNOWN                       0
+#define S5P_FIMV_D_CHROMA_400                          0
+#define S5P_FIMV_D_CHROMA_420                          1
+#define S5P_FIMV_D_CHROMA_422                          2
+#define S5P_FIMV_D_CHROMA_444                          3
+
+
+/* 0xF690: S5P_FIMV_D_H264_INFO */
+#define S5P_FIMV_D_H264_INFO_MBAFF_FRAME_FLAG_SHIFT    9
+#define S5P_FIMV_D_H264_INFO_MBAFF_FRAME_FLAG_MASK     0x1
+
+
+/* 0xF6D8: S5P_FIMV_D_MVC_VIEW_ID */
+#define S5P_FIMV_D_MVC_VIEW_ID_DISP_MASK               0xFFFF
+
+
+/* 0xF6DC: S5P_FIMV_D_SEI_AVAIL */
+#define S5P_FIMV_D_SEI_AVAIL_FRAME_PACK_MASK           0x1
+#define S5P_FIMV_D_SEI_AVAIL_CONTENT_LIGHT_MASK                0x1
+#define S5P_FIMV_D_SEI_AVAIL_CONTENT_LIGHT_SHIFT       1
+#define S5P_FIMV_D_SEI_AVAIL_MASTERING_DISPLAY_MASK    0x1
+#define S5P_FIMV_D_SEI_AVAIL_MASTERING_DISPLAY_SHIFT   2
+
+
+/* 0xF70C: S5P_FIMV_D_VIDEO_SIGNAL_TYPE */
+#define S5P_FIMV_D_VIDEO_SIGNAL_TYPE_FLAG_MASK         0x1
+#define S5P_FIMV_D_VIDEO_SIGNAL_TYPE_FLAG_SHIFT                29
+#define S5P_FIMV_D_COLOUR_DESCRIPTION_FLAG_MASK                0x1
+#define S5P_FIMV_D_COLOUR_DESCRIPTION_FLAG_SHIFT       24
+
+
+/* 0xF738: S5P_FIMV_D_BLACK_BAR_START_POS */
+#define S5P_FIMV_D_BLACK_BAR_START_X_SHIFT             0
+#define S5P_FIMV_D_BLACK_BAR_START_X_MASK              0xFFFF
+#define S5P_FIMV_D_BLACK_BAR_START_Y_SHIFT             16
+#define S5P_FIMV_D_BLACK_BAR_START_Y_MASK              0xFFFF
+
+
+/* 0xF73C: S5P_FIMV_D_BLACK_BAR_IMAGE_SIZE */
+#define S5P_FIMV_D_BLACK_BAR_IMAGE_W_SHIFT             0
+#define S5P_FIMV_D_BLACK_BAR_IMAGE_W_MASK              0xFFFF
+#define S5P_FIMV_D_BLACK_BAR_IMAGE_H_SHIFT             16
+#define S5P_FIMV_D_BLACK_BAR_IMAGE_H_MASK              0xFFFF
+
+
+/* 0xF780:  S5P_FIMV_E_FRAME_CROP_OFFSET */
+#define S5P_FIMV_E_FRAME_CROP_OFFSET_TOP               16
+#define S5P_FIMV_E_FRAME_CROP_OFFSET_LEFT              0
+#define S5P_FIMV_E_FRAME_CROP_OFFSET_MASK              0x3FFF
+
+
+/* 0xF788: S5P_FIMV_E_PICTURE_PROFILE */
+#define S5P_FIMV_E_PROFILE_H264_BASELINE               0
+#define S5P_FIMV_E_PROFILE_H264_MAIN                   1
+#define S5P_FIMV_E_PROFILE_H264_HIGH                   2
+#define S5P_FIMV_E_PROFILE_H264_CONSTRAINED_BASELINE   3
+#define S5P_FIMV_E_PROFILE_H264_CONSTRAINED_HIGH       5
+#define S5P_FIMV_E_PROFILE_MPEG4_SIMPLE                        0
+#define S5P_FIMV_E_PROFILE_MPEG4_ADVANCED_SIMPLE       1
+#define S5P_FIMV_E_PROFILE_HEVC_MAIN_422_10_INTRA      2
+#define S5P_FIMV_E_PROFILE_HEVC_MAIN_10                        3
+#define S5P_FIMV_E_PROFILE_HEVC_MAIN_422_10            4
+#define S5P_FIMV_E_PROFILE_VP9_PROFILE0                        0
+#define S5P_FIMV_E_PROFILE_VP9_PROFILE1                        1
+#define S5P_FIMV_E_PROFILE_VP9_PROFILE2                        2
+#define S5P_FIMV_E_PROFILE_VP9_PROFILE3                        3
+
+
+/* 0xF7A4: S5P_FIMV_E_RC_MODE */
+#define S5P_FIMV_E_RC_CBR_FIX                          0
+#define S5P_FIMV_E_RC_CBR_VAR                          1
+#define S5P_FIMV_E_RC_VBR                              2
+#define S5P_FIMV_E_RC_CBR_I_LIMIT                      3
+
+
+/* 0xFA84: S5P_FIMV_E_SLICE_TYPE */
+#define S5P_FIMV_E_SLICE_TYPE_NOT_CODED                        0
+#define S5P_FIMV_E_SLICE_TYPE_I                                1
+#define S5P_FIMV_E_SLICE_TYPE_P                                2
+#define S5P_FIMV_E_SLICE_TYPE_B                                3
+#define S5P_FIMV_E_SLICE_TYPE_SKIPPED                  4
+
+
+#endif /* __REGS_MFC_V10_H */
diff --git a/drivers/media/platform/exynos/mfc/mfc_sync.c b/drivers/media/platform/exynos/mfc/mfc_sync.c
new file mode 100644 (file)
index 0000000..bc7b192
--- /dev/null
@@ -0,0 +1,342 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_intr.c
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include "mfc_sync.h"
+
+#include "mfc_cal.h"
+#include "mfc_perf_measure.h"
+
+#include "mfc_queue.h"
+
+#define R2H_BIT(x)     (((x) > 0) ? (1 << ((x) - 1)) : 0)
+
+static inline unsigned int mfc_r2h_bit_mask(int cmd)
+{
+       unsigned int mask = R2H_BIT(cmd);
+
+       if (cmd == S5P_FIMV_R2H_CMD_FRAME_DONE_RET)
+               mask |= (R2H_BIT(S5P_FIMV_R2H_CMD_FIELD_DONE_RET) |
+                        R2H_BIT(S5P_FIMV_R2H_CMD_COMPLETE_SEQ_RET) |
+                        R2H_BIT(S5P_FIMV_R2H_CMD_SLICE_DONE_RET) |
+                        R2H_BIT(S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET) |
+                        R2H_BIT(S5P_FIMV_R2H_CMD_ENC_BUFFER_FULL_RET));
+       /* FIXME: Temporal mask for S3D SEI processing */
+       else if (cmd == S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET)
+               mask |= (R2H_BIT(S5P_FIMV_R2H_CMD_FIELD_DONE_RET) |
+                        R2H_BIT(S5P_FIMV_R2H_CMD_SLICE_DONE_RET) |
+                        R2H_BIT(S5P_FIMV_R2H_CMD_FRAME_DONE_RET));
+
+       return (mask |= R2H_BIT(S5P_FIMV_R2H_CMD_ERR_RET));
+}
+
+#define wait_condition(x, c) (x->int_condition &&              \
+               (R2H_BIT(x->int_reason) & mfc_r2h_bit_mask(c)))
+#define is_err_cond(x) ((x->int_condition) && (x->int_reason == S5P_FIMV_R2H_CMD_ERR_RET))
+
+/*
+ * Return value description
+ * 0: waked up before timeout
+ * 1: failed to get the response for the command before timeout
+*/
+int s5p_mfc_wait_for_done_dev(struct s5p_mfc_dev *dev, int command)
+{
+       int ret;
+
+       ret = wait_event_timeout(dev->cmd_wq,
+                       wait_condition(dev, command),
+                       msecs_to_jiffies(MFC_INT_TIMEOUT));
+       if (ret == 0) {
+               mfc_err_dev("Interrupt (dev->int_reason:%d, command:%d) timed out\n",
+                                                       dev->int_reason, command);
+               if (s5p_mfc_check_risc2host(dev)) {
+                       ret = wait_event_timeout(dev->cmd_wq,
+                                       wait_condition(dev, command),
+                                       msecs_to_jiffies(MFC_INT_TIMEOUT * MFC_INT_TIMEOUT_CNT));
+                       if (ret == 0) {
+                               mfc_err_dev("Timeout: MFC driver waited for upward of %dsec\n",
+                                               3 * MFC_INT_TIMEOUT);
+                       } else {
+                               goto wait_done;
+                       }
+               }
+               call_dop(dev, dump_and_stop_debug_mode, dev);
+               return 1;
+       }
+
+wait_done:
+       mfc_debug(2, "Finished waiting (dev->int_reason:%d, command: %d)\n",
+                                                       dev->int_reason, command);
+       return 0;
+}
+
+/*
+ * Return value description
+ *  0: waked up before timeout
+ *  1: failed to get the response for the command before timeout
+ * -1: got the error response for the command before timeout
+*/
+int s5p_mfc_wait_for_done_ctx(struct s5p_mfc_ctx *ctx, int command)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       int ret;
+       unsigned int timeout = MFC_INT_TIMEOUT;
+
+       if (command == S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET)
+               timeout = MFC_INT_SHORT_TIMEOUT;
+
+       ret = wait_event_timeout(ctx->cmd_wq,
+                       wait_condition(ctx, command),
+                       msecs_to_jiffies(timeout));
+       if (ret == 0) {
+               mfc_err_ctx("Interrupt (ctx->int_reason:%d, command:%d) timed out\n",
+                                                       ctx->int_reason, command);
+               if (s5p_mfc_check_risc2host(dev)) {
+                       ret = wait_event_timeout(ctx->cmd_wq,
+                                       wait_condition(ctx, command),
+                                       msecs_to_jiffies(MFC_INT_TIMEOUT * MFC_INT_TIMEOUT_CNT));
+                       if (ret == 0) {
+                               mfc_err_dev("Timeout: MFC driver waited for upward of %dsec\n",
+                                               3 * MFC_INT_TIMEOUT);
+                       } else {
+                               goto wait_done;
+                       }
+               }
+               call_dop(dev, dump_and_stop_debug_mode, dev);
+               return 1;
+       }
+
+wait_done:
+       if (is_err_cond(ctx)) {
+               mfc_err_ctx("Finished (ctx->int_reason:%d, command: %d)\n",
+                               ctx->int_reason, command);
+               mfc_err_ctx("But error (ctx->int_err:%d)\n", ctx->int_err);
+               call_dop(dev, dump_and_stop_debug_mode, dev);
+               return -1;
+       }
+
+       mfc_debug(2, "Finished waiting (ctx->int_reason:%d, command: %d)\n",
+                                                       ctx->int_reason, command);
+       return 0;
+}
+
+/* Wake up device wait_queue */
+void s5p_mfc_wake_up_dev(struct s5p_mfc_dev *dev, unsigned int reason,
+               unsigned int err)
+{
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return;
+       }
+
+       dev->int_condition = 1;
+       dev->int_reason = reason;
+       dev->int_err = err;
+       wake_up(&dev->cmd_wq);
+}
+
+/* Wake up context wait_queue */
+void s5p_mfc_wake_up_ctx(struct s5p_mfc_ctx *ctx, unsigned int reason,
+               unsigned int err)
+{
+       if (!ctx) {
+               mfc_err_dev("no mfc context to run\n");
+               return;
+       }
+
+       ctx->int_condition = 1;
+       ctx->int_reason = reason;
+       ctx->int_err = err;
+       wake_up(&ctx->cmd_wq);
+}
+
+int s5p_mfc_get_new_ctx(struct s5p_mfc_dev *dev)
+{
+       unsigned long wflags;
+       int new_ctx_index = 0;
+       int cnt = 0;
+       int i;
+
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return -EINVAL;
+       }
+
+       spin_lock_irqsave(&dev->work_bits.lock, wflags);
+
+       mfc_debug(2, "Previous context: %d (bits %08lx)\n", dev->curr_ctx,
+                                                       dev->work_bits.bits);
+
+       if (dev->preempt_ctx > MFC_NO_INSTANCE_SET) {
+               new_ctx_index = dev->preempt_ctx;
+               mfc_debug(2, "preempt_ctx is : %d\n", new_ctx_index);
+       } else {
+               for (i = 0; i < MFC_NUM_CONTEXTS; i++) {
+                       if (dev->ctx[i] && dev->ctx[i]->otf_handle) {
+                               if (test_bit(i, &dev->work_bits.bits)) {
+                                       spin_unlock_irqrestore(&dev->work_bits.lock, wflags);
+                                       return i;
+                               }
+                               break;
+                       }
+               }
+
+               new_ctx_index = (dev->curr_ctx + 1) % MFC_NUM_CONTEXTS;
+               while (!test_bit(new_ctx_index, &dev->work_bits.bits)) {
+                       new_ctx_index = (new_ctx_index + 1) % MFC_NUM_CONTEXTS;
+                       cnt++;
+                       if (cnt > MFC_NUM_CONTEXTS) {
+                               /* No contexts to run */
+                               spin_unlock_irqrestore(&dev->work_bits.lock, wflags);
+                               return -EAGAIN;
+                       }
+               }
+       }
+
+       spin_unlock_irqrestore(&dev->work_bits.lock, wflags);
+       return new_ctx_index;
+}
+
+/* Check whether a context should be run on hardware */
+int s5p_mfc_dec_ctx_ready(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       int src_buf_queue_greater_than_0 = 0;
+       int dst_buf_queue_greater_than_0 = 0;
+       int ref_buf_queue_same_dpb_count_plus_5 = 0;
+
+       mfc_debug(1, "[c:%d] src = %d, dst = %d, src_nal = %d, dst_nal = %d, ref = %d, state = %d, capstat = %d\n",
+                 ctx->num, s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->src_buf_queue),
+                 s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->dst_buf_queue),
+                 s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->src_buf_nal_queue),
+                 s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->dst_buf_nal_queue),
+                 s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->ref_buf_queue),
+                 ctx->state, ctx->capture_state);
+       mfc_debug(2, "wait_state = %d\n", ctx->wait_state);
+
+       src_buf_queue_greater_than_0
+               = s5p_mfc_is_queue_count_greater(&ctx->buf_queue_lock, &ctx->src_buf_queue, 0);
+       dst_buf_queue_greater_than_0
+               = s5p_mfc_is_queue_count_greater(&ctx->buf_queue_lock, &ctx->dst_buf_queue, 0);
+       ref_buf_queue_same_dpb_count_plus_5
+               = s5p_mfc_is_queue_count_same(&ctx->buf_queue_lock, &ctx->ref_buf_queue, (ctx->dpb_count + 5));
+
+       /* If shutdown is called, do not try any cmd */
+       if (dev->shutdown)
+               return 0;
+
+       /* Context is to parse header */
+       if (ctx->state == MFCINST_GOT_INST &&
+               src_buf_queue_greater_than_0)
+               return 1;
+
+       /* Context is to decode a frame */
+       if (ctx->state == MFCINST_RUNNING &&
+               ctx->wait_state == WAIT_NONE && src_buf_queue_greater_than_0 &&
+               (dst_buf_queue_greater_than_0 || ref_buf_queue_same_dpb_count_plus_5))
+               return 1;
+
+       /* Context is to return last frame */
+       if (ctx->state == MFCINST_FINISHING &&
+               (dst_buf_queue_greater_than_0 || ref_buf_queue_same_dpb_count_plus_5))
+               return 1;
+
+       /* Context is to set buffers */
+       if (ctx->state == MFCINST_HEAD_PARSED &&
+               (dst_buf_queue_greater_than_0 && ctx->wait_state == WAIT_NONE))
+               return 1;
+
+       /* Resolution change */
+       if ((ctx->state == MFCINST_RES_CHANGE_INIT || ctx->state == MFCINST_RES_CHANGE_FLUSH) &&
+               dst_buf_queue_greater_than_0)
+               return 1;
+
+       if (ctx->state == MFCINST_RES_CHANGE_END &&
+               src_buf_queue_greater_than_0)
+               return 1;
+
+       s5p_mfc_perf_cancel_drv_margin(dev);
+       mfc_debug(2, "ctx is not ready\n");
+
+       return 0;
+}
+
+int s5p_mfc_enc_ctx_ready(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_enc *enc = ctx->enc_priv;
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_enc_params *p = &enc->params;
+       int src_buf_queue_greater_than_0 = 0;
+       int dst_buf_queue_greater_than_0 = 0;
+
+       mfc_debug(1, "[c:%d] src = %d, dst = %d, src_nal = %d, dst_nal = %d, ref = %d, state = %d\n",
+                 ctx->num, s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->src_buf_queue),
+                 s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->dst_buf_queue),
+                 s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->src_buf_nal_queue),
+                 s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->dst_buf_nal_queue),
+                 s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->ref_buf_queue),
+                 ctx->state);
+
+       src_buf_queue_greater_than_0
+               = s5p_mfc_is_queue_count_greater(&ctx->buf_queue_lock, &ctx->src_buf_queue, 0);
+       dst_buf_queue_greater_than_0
+               = s5p_mfc_is_queue_count_greater(&ctx->buf_queue_lock, &ctx->dst_buf_queue, 0);
+
+       /* If shutdown is called, do not try any cmd */
+       if (dev->shutdown)
+               return 0;
+
+       /* context is ready to make header */
+       if (ctx->state == MFCINST_GOT_INST &&
+               dst_buf_queue_greater_than_0) {
+               if (p->seq_hdr_mode == V4L2_MPEG_VIDEO_HEADER_MODE_AT_THE_READY) {
+                       if (src_buf_queue_greater_than_0)
+                               return 1;
+               } else {
+                       return 1;
+               }
+       }
+
+       /* context is ready to allocate DPB */
+       if (ctx->state == MFCINST_HEAD_PARSED &&
+               dst_buf_queue_greater_than_0)
+               return 1;
+
+       /* context is ready to encode a frame */
+       if (ctx->state == MFCINST_RUNNING &&
+               src_buf_queue_greater_than_0 && dst_buf_queue_greater_than_0)
+               return 1;
+
+       /* context is ready to encode a frame for NAL_ABORT command */
+       if (ctx->state == MFCINST_ABORT_INST &&
+               src_buf_queue_greater_than_0 && dst_buf_queue_greater_than_0)
+               return 1;
+
+       /* context is ready to encode remain frames */
+       if (ctx->state == MFCINST_FINISHING &&
+               src_buf_queue_greater_than_0 && dst_buf_queue_greater_than_0)
+               return 1;
+
+       s5p_mfc_perf_cancel_drv_margin(dev);
+       mfc_debug(2, "ctx is not ready\n");
+
+       return 0;
+}
+
+int s5p_mfc_ctx_ready(struct s5p_mfc_ctx *ctx)
+{
+       if (ctx->type == MFCINST_DECODER)
+               return s5p_mfc_dec_ctx_ready(ctx);
+       else if (ctx->type == MFCINST_ENCODER)
+               return s5p_mfc_enc_ctx_ready(ctx);
+
+       return 0;
+}
diff --git a/drivers/media/platform/exynos/mfc/mfc_sync.h b/drivers/media/platform/exynos/mfc/mfc_sync.h
new file mode 100644 (file)
index 0000000..5c99de6
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_intr.h
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __MFC_INTR_H
+#define __MFC_INTR_H __FILE__
+
+#include "mfc_common.h"
+
+#define need_to_dpb_flush(ctx)         \
+       ((ctx->state == MFCINST_FINISHING) ||   \
+         (ctx->state == MFCINST_RUNNING))
+#define need_to_wait_nal_abort(ctx)             \
+       (ctx->state == MFCINST_ABORT_INST)
+#define need_to_continue(ctx)                  \
+       ((ctx->state == MFCINST_DPB_FLUSHING) ||\
+       (ctx->state == MFCINST_ABORT_INST) ||   \
+       (ctx->state == MFCINST_RETURN_INST) ||  \
+       (ctx->state == MFCINST_SPECIAL_PARSING) ||      \
+       (ctx->state == MFCINST_SPECIAL_PARSING_NAL))
+#define need_to_special_parsing(ctx)           \
+       ((ctx->state == MFCINST_GOT_INST) ||    \
+        (ctx->state == MFCINST_HEAD_PARSED))
+#define need_to_special_parsing_nal(ctx)       \
+       (ctx->state == MFCINST_RUNNING)
+#define ready_to_get_crop(ctx)                 \
+       ((ctx->state == MFCINST_HEAD_PARSED) || \
+        (ctx->state == MFCINST_RUNNING) || \
+        (ctx->state == MFCINST_FINISHING))
+
+int s5p_mfc_wait_for_done_dev(struct s5p_mfc_dev *dev, int command);
+int s5p_mfc_wait_for_done_ctx(struct s5p_mfc_ctx *ctx, int command);
+void s5p_mfc_wake_up_dev(struct s5p_mfc_dev *dev, unsigned int reason,
+               unsigned int err);
+void s5p_mfc_wake_up_ctx(struct s5p_mfc_ctx *ctx, unsigned int reason,
+               unsigned int err);
+
+int s5p_mfc_get_new_ctx(struct s5p_mfc_dev *dev);
+int s5p_mfc_dec_ctx_ready(struct s5p_mfc_ctx *ctx);
+int s5p_mfc_enc_ctx_ready(struct s5p_mfc_ctx *ctx);
+int s5p_mfc_ctx_ready(struct s5p_mfc_ctx *ctx);
+
+
+static inline void s5p_mfc_set_bit(int num, struct s5p_mfc_bits *data)
+{
+       unsigned long flags;
+       spin_lock_irqsave(&data->lock, flags);
+       __set_bit(num, &data->bits);
+       spin_unlock_irqrestore(&data->lock, flags);
+}
+
+static inline void s5p_mfc_clear_bit(int num, struct s5p_mfc_bits *data)
+{
+       unsigned long flags;
+       spin_lock_irqsave(&data->lock, flags);
+       __clear_bit(num, &data->bits);
+       spin_unlock_irqrestore(&data->lock, flags);
+}
+
+static inline int s5p_mfc_test_bit(int num, struct s5p_mfc_bits *data)
+{
+       unsigned long flags;
+       int ret;
+       spin_lock_irqsave(&data->lock, flags);
+       ret = test_bit(num, &data->bits);
+       spin_unlock_irqrestore(&data->lock, flags);
+       return ret;
+}
+
+static inline int s5p_mfc_is_all_bits_cleared(struct s5p_mfc_bits *data)
+{
+       unsigned long flags;
+       int ret;
+       spin_lock_irqsave(&data->lock, flags);
+       ret = ((data->bits) == 0) ? 1 : 0;
+       spin_unlock_irqrestore(&data->lock, flags);
+       return ret;
+}
+
+static inline void s5p_mfc_clear_all_bits(struct s5p_mfc_bits *data)
+{
+       unsigned long flags;
+       spin_lock_irqsave(&data->lock, flags);
+       data->bits = 0;
+       spin_unlock_irqrestore(&data->lock, flags);
+}
+
+static inline unsigned long s5p_mfc_get_bits(struct s5p_mfc_bits *data)
+{
+       unsigned long flags;
+       unsigned long ret;
+       spin_lock_irqsave(&data->lock, flags);
+       ret = data->bits;
+       spin_unlock_irqrestore(&data->lock, flags);
+       return ret;
+}
+
+static inline void s5p_mfc_create_bits(struct s5p_mfc_bits *data)
+{
+       spin_lock_init(&data->lock);
+       s5p_mfc_clear_all_bits(data);
+}
+
+static inline void s5p_mfc_delete_bits(struct s5p_mfc_bits *data)
+{
+       s5p_mfc_clear_all_bits(data);
+}
+
+static inline int s5p_mfc_is_work_to_do(struct s5p_mfc_dev *dev)
+{
+       return (!s5p_mfc_is_all_bits_cleared(&dev->work_bits));
+}
+
+#endif /* __MFC_INTR_H */
diff --git a/drivers/media/platform/exynos/mfc/mfc_utils.c b/drivers/media/platform/exynos/mfc/mfc_utils.c
new file mode 100644 (file)
index 0000000..2261477
--- /dev/null
@@ -0,0 +1,553 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_utils.c
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/smc.h>
+
+#include "mfc_utils.h"
+
+int s5p_mfc_check_vb_with_fmt(struct s5p_mfc_fmt *fmt, struct vb2_buffer *vb)
+{
+       if (!fmt)
+               return -EINVAL;
+
+       if (fmt->mem_planes != vb->num_planes) {
+               mfc_err_dev("plane number is different (%d != %d)\n",
+                               fmt->mem_planes, vb->num_planes);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+int mfc_stream_buf_prot(struct s5p_mfc_ctx *ctx,
+                               struct s5p_mfc_buf *buf, bool en)
+{
+       return 0;
+}
+
+int mfc_raw_buf_prot(struct s5p_mfc_ctx *ctx,
+                               struct s5p_mfc_buf *buf, bool en)
+{
+       return 0;
+}
+
+void s5p_mfc_raw_protect(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf *mfc_buf,
+                                       int index)
+{
+       if (!test_bit(index, &ctx->raw_protect_flag)) {
+               if (mfc_raw_buf_prot(ctx, mfc_buf, true)) {
+                       mfc_err_ctx("failed to CFW_PROT\n");
+               } else {
+                       set_bit(index, &ctx->raw_protect_flag);
+                       mfc_debug(2, "[index:%d] raw protect, flag: %#lx\n",
+                                       index, ctx->raw_protect_flag);
+               }
+       }
+}
+
+void s5p_mfc_raw_unprotect(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf *mfc_buf,
+                                       int index)
+{
+       if (test_bit(index, &ctx->raw_protect_flag)) {
+               if (mfc_raw_buf_prot(ctx, mfc_buf, false)) {
+                       mfc_err_ctx("failed to CFW_UNPROT\n");
+               } else {
+                       clear_bit(index, &ctx->raw_protect_flag);
+                       mfc_debug(2, "[index:%d] raw unprotect, flag: %#lx\n",
+                                       index, ctx->raw_protect_flag);
+               }
+       }
+}
+
+void s5p_mfc_stream_protect(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf *mfc_buf,
+                                       int index)
+{
+       if (!test_bit(index, &ctx->stream_protect_flag)) {
+               if (mfc_stream_buf_prot(ctx, mfc_buf, true)) {
+                       mfc_err_ctx("failed to CFW_PROT\n");
+               } else {
+                       set_bit(index, &ctx->stream_protect_flag);
+                       mfc_debug(2, "[index:%d] stream protect, flag: %#lx\n",
+                                       index, ctx->stream_protect_flag);
+               }
+       }
+}
+
+void s5p_mfc_stream_unprotect(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf *mfc_buf,
+                                       int index)
+{
+       if (test_bit(index, &ctx->stream_protect_flag)) {
+               if (mfc_stream_buf_prot(ctx, mfc_buf, false)) {
+                       mfc_err_ctx("failed to CFW_UNPROT\n");
+               } else {
+                       clear_bit(index, &ctx->stream_protect_flag);
+                       mfc_debug(2, "[index:%d] stream unprotect, flag: %#lx\n",
+                                       index, ctx->stream_protect_flag);
+               }
+       }
+}
+
+static int mfc_calc_plane(int width, int height, int is_tiled)
+{
+       int mbX, mbY;
+
+       mbX = (width + 15)/16;
+       mbY = (height + 15)/16;
+
+       /* Alignment for interlaced processing */
+       if (is_tiled)
+               mbY = (mbY + 1) / 2 * 2;
+
+       return (mbX * 16) * (mbY * 16);
+}
+
+static void mfc_set_linear_stride_size(struct s5p_mfc_ctx *ctx,
+                               struct s5p_mfc_fmt *fmt)
+{
+       struct s5p_mfc_raw_info *raw;
+       int i;
+
+       raw = &ctx->raw_buf;
+
+       switch (fmt->fourcc) {
+       case V4L2_PIX_FMT_YUV420M:
+       case V4L2_PIX_FMT_YUV420N:
+       case V4L2_PIX_FMT_YVU420M:
+               raw->stride[0] = ALIGN(ctx->img_width, 16);
+               raw->stride[1] = ALIGN(raw->stride[0] >> 1, 16);
+               raw->stride[2] = ALIGN(raw->stride[0] >> 1, 16);
+               break;
+       case V4L2_PIX_FMT_NV12MT_16X16:
+       case V4L2_PIX_FMT_NV12MT:
+       case V4L2_PIX_FMT_NV12M:
+       case V4L2_PIX_FMT_NV12N:
+       case V4L2_PIX_FMT_NV21M:
+       case V4L2_PIX_FMT_NV16M:
+       case V4L2_PIX_FMT_NV61M:
+               raw->stride[0] = ALIGN(ctx->img_width, 16);
+               raw->stride[1] = ALIGN(ctx->img_width, 16);
+               raw->stride[2] = 0;
+               break;
+       case V4L2_PIX_FMT_NV12M_S10B:
+       case V4L2_PIX_FMT_NV12N_10B:
+       case V4L2_PIX_FMT_NV21M_S10B:
+       case V4L2_PIX_FMT_NV16M_S10B:
+       case V4L2_PIX_FMT_NV61M_S10B:
+               raw->stride[0] = S10B_8B_STRIDE(ctx->img_width);
+               raw->stride[1] = S10B_8B_STRIDE(ctx->img_width);
+               raw->stride[2] = 0;
+               raw->stride_2bits[0] = S10B_2B_STRIDE(ctx->img_width);
+               raw->stride_2bits[1] = S10B_2B_STRIDE(ctx->img_width);
+               raw->stride_2bits[2] = 0;
+               break;
+       case V4L2_PIX_FMT_NV12M_P010:
+       case V4L2_PIX_FMT_NV21M_P010:
+       case V4L2_PIX_FMT_NV61M_P210:
+       case V4L2_PIX_FMT_NV16M_P210:
+               raw->stride[0] = ALIGN(ctx->img_width, 16) * 2;
+               raw->stride[1] = ALIGN(ctx->img_width, 16) * 2;
+               raw->stride[2] = 0;
+               raw->stride_2bits[0] = 0;
+               raw->stride_2bits[1] = 0;
+               raw->stride_2bits[2] = 0;
+               break;
+       case V4L2_PIX_FMT_RGB24:
+               ctx->raw_buf.stride[0] = ctx->img_width * 3;
+               ctx->raw_buf.stride[1] = 0;
+               ctx->raw_buf.stride[2] = 0;
+               break;
+       case V4L2_PIX_FMT_RGB565:
+               ctx->raw_buf.stride[0] = ctx->img_width * 2;
+               ctx->raw_buf.stride[1] = 0;
+               ctx->raw_buf.stride[2] = 0;
+               break;
+       case V4L2_PIX_FMT_RGB32X:
+       case V4L2_PIX_FMT_BGR32:
+       case V4L2_PIX_FMT_ARGB32:
+               ctx->raw_buf.stride[0] = (ctx->buf_stride > ctx->img_width) ?
+                       (ALIGN(ctx->img_width, 16) * 4) : (ctx->img_width * 4);
+               ctx->raw_buf.stride[1] = 0;
+               ctx->raw_buf.stride[2] = 0;
+               break;
+       default:
+               break;
+       }
+
+       /* Decoder needs multiple of 16 alignment for stride */
+       if (ctx->type == MFCINST_DECODER) {
+               for (i = 0; i < 3; i++)
+                       ctx->raw_buf.stride[i] =
+                               ALIGN(ctx->raw_buf.stride[i], 16);
+       }
+}
+
+void s5p_mfc_dec_calc_dpb_size(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev;
+       struct s5p_mfc_dec *dec;
+       struct s5p_mfc_raw_info *raw;
+       int i;
+       int extra = MFC_LINEAR_BUF_SIZE;
+
+       if (!ctx) {
+               mfc_err_dev("no mfc context to run\n");
+               return;
+       }
+
+       dev = ctx->dev;
+       raw = &ctx->raw_buf;
+       raw->total_plane_size = 0;
+
+       dec = ctx->dec_priv;
+
+       for (i = 0; i < raw->num_planes; i++) {
+               raw->plane_size[i] = 0;
+               raw->plane_size_2bits[i] = 0;
+       }
+
+       switch (ctx->dst_fmt->fourcc) {
+       case V4L2_PIX_FMT_NV12M_S10B:
+       case V4L2_PIX_FMT_NV21M_S10B:
+               raw->plane_size[0] = NV12M_Y_SIZE(ctx->img_width, ctx->img_height);
+               raw->plane_size[1] = NV12M_CBCR_SIZE(ctx->img_width, ctx->img_height);
+               raw->plane_size_2bits[0] = NV12M_Y_2B_SIZE(ctx->img_width, ctx->img_height);
+               raw->plane_size_2bits[1] = NV12M_CBCR_2B_SIZE(ctx->img_width, ctx->img_height);
+               break;
+       case V4L2_PIX_FMT_NV12M:
+       case V4L2_PIX_FMT_NV21M:
+               raw->plane_size[0] = mfc_calc_plane(ctx->img_width, ctx->img_height, 0) + extra;
+               raw->plane_size[1] = mfc_calc_plane(ctx->img_width, ctx->img_height, 0) / 2 + extra;
+               break;
+       case V4L2_PIX_FMT_NV12M_P010:
+       case V4L2_PIX_FMT_NV21M_P010:
+               raw->plane_size[0] = mfc_calc_plane(ctx->img_width, ctx->img_height, 0) * 2 + extra;
+               raw->plane_size[1] = mfc_calc_plane(ctx->img_width, ctx->img_height, 0) + extra;
+               break;
+       case V4L2_PIX_FMT_YUV420M:
+       case V4L2_PIX_FMT_YVU420M:
+               raw->plane_size[0] = mfc_calc_plane(ctx->img_width, ctx->img_height, 0) + extra;
+               raw->plane_size[1] = mfc_calc_plane(ctx->img_width, ctx->img_height, 0) / 2 + extra;
+               raw->plane_size[2] = mfc_calc_plane(ctx->img_width, ctx->img_height, 0) / 2 + extra;
+               break;
+       case V4L2_PIX_FMT_NV16M_S10B:
+       case V4L2_PIX_FMT_NV61M_S10B:
+               raw->plane_size[0] = NV16M_Y_SIZE(ctx->img_width, ctx->img_height);
+               raw->plane_size[1] = NV16M_CBCR_SIZE(ctx->img_width, ctx->img_height);
+               raw->plane_size_2bits[0] = NV16M_Y_2B_SIZE(ctx->img_width, ctx->img_height);
+               raw->plane_size_2bits[1] = NV16M_CBCR_2B_SIZE(ctx->img_width, ctx->img_height);
+               break;
+       case V4L2_PIX_FMT_NV16M:
+       case V4L2_PIX_FMT_NV61M:
+               raw->plane_size[0] = mfc_calc_plane(ctx->img_width, ctx->img_height, 0) + extra;
+               raw->plane_size[1] = mfc_calc_plane(ctx->img_width, ctx->img_height, 0) + extra;
+               break;
+       case V4L2_PIX_FMT_NV16M_P210:
+       case V4L2_PIX_FMT_NV61M_P210:
+               raw->plane_size[0] = mfc_calc_plane(ctx->img_width, ctx->img_height, 0) * 2 + extra;
+               raw->plane_size[1] = mfc_calc_plane(ctx->img_width, ctx->img_height, 0) * 2 + extra;
+               break;
+       /* non-contiguous single fd format */
+       case V4L2_PIX_FMT_NV12N_10B:
+               raw->plane_size[0] = NV12N_10B_Y_8B_SIZE(ctx->img_width, ctx->img_height);
+               raw->plane_size[1] = NV12N_10B_CBCR_8B_SIZE(ctx->img_width, ctx->img_height);
+               raw->plane_size_2bits[0] = NV12N_10B_Y_2B_SIZE(ctx->img_width, ctx->img_height);
+               raw->plane_size_2bits[1] = NV12N_10B_CBCR_2B_SIZE(ctx->img_width, ctx->img_height);
+               break;
+       case V4L2_PIX_FMT_NV12N:
+               raw->plane_size[0] = NV12N_Y_SIZE(ctx->img_width, ctx->img_height);
+               raw->plane_size[1] = NV12N_CBCR_SIZE(ctx->img_width, ctx->img_height);
+               break;
+       case V4L2_PIX_FMT_YUV420N:
+               raw->plane_size[0] = YUV420N_Y_SIZE(ctx->img_width, ctx->img_height);
+               raw->plane_size[1] = YUV420N_CB_SIZE(ctx->img_width, ctx->img_height);
+               raw->plane_size[2] = YUV420N_CR_SIZE(ctx->img_width, ctx->img_height);
+               break;
+       default:
+               mfc_err_ctx("Invalid pixelformat : %s\n", ctx->dst_fmt->name);
+               break;
+       }
+
+       mfc_set_linear_stride_size(ctx, ctx->dst_fmt);
+
+       for (i = 0; i < raw->num_planes; i++) {
+               if (raw->plane_size[i] < ctx->min_dpb_size[i]) {
+                       mfc_info_dev("[FRAME] plane[%d] size is changed %d -> %d\n",
+                                       i, raw->plane_size[i], ctx->min_dpb_size[i]);
+                       raw->plane_size[i] = ctx->min_dpb_size[i];
+               }
+       }
+
+       for (i = 0; i < raw->num_planes; i++) {
+               raw->total_plane_size += raw->plane_size[i];
+               mfc_debug(2, "[FRAME] Plane[%d] size = %d, stride = %d\n",
+                       i, raw->plane_size[i], raw->stride[i]);
+       }
+       if (ctx->is_10bit) {
+               for (i = 0; i < raw->num_planes; i++) {
+                       raw->total_plane_size += raw->plane_size_2bits[i];
+                       mfc_debug(2, "[FRAME][10BIT] Plane[%d] 2bit size = %d, stride = %d\n",
+                                       i, raw->plane_size_2bits[i],
+                                       raw->stride_2bits[i]);
+               }
+       }
+       mfc_debug(2, "[FRAME] total plane size: %d\n", raw->total_plane_size);
+
+       if (IS_H264_DEC(ctx) || IS_H264_MVC_DEC(ctx)) {
+               ctx->mv_size = DEC_MV_SIZE_MB(ctx->img_width, ctx->img_height);
+               ctx->mv_size = ALIGN(ctx->mv_size, 32);
+       } else if (IS_HEVC_DEC(ctx) || IS_BPG_DEC(ctx)) {
+               ctx->mv_size = DEC_HEVC_MV_SIZE(ctx->img_width, ctx->img_height);
+               ctx->mv_size = ALIGN(ctx->mv_size, 32);
+       } else {
+               ctx->mv_size = 0;
+       }
+}
+
+void s5p_mfc_enc_calc_src_size(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev;
+       struct s5p_mfc_raw_info *raw;
+       unsigned int mb_width, mb_height, default_size;
+       int i, extra;
+
+       if (!ctx) {
+               mfc_err_dev("no mfc context to run\n");
+               return;
+       }
+
+       dev = ctx->dev;
+       raw = &ctx->raw_buf;
+       raw->total_plane_size = 0;
+       mb_width = WIDTH_MB(ctx->img_width);
+       mb_height = HEIGHT_MB(ctx->img_height);
+       extra = MFC_LINEAR_BUF_SIZE;
+       default_size = mb_width * mb_height * 256;
+
+       for (i = 0; i < raw->num_planes; i++) {
+               raw->plane_size[i] = 0;
+               raw->plane_size_2bits[i] = 0;
+       }
+
+       switch (ctx->src_fmt->fourcc) {
+       case V4L2_PIX_FMT_YUV420M:
+       case V4L2_PIX_FMT_YUV420N:
+       case V4L2_PIX_FMT_YVU420M:
+               raw->plane_size[0] = ALIGN(default_size, 256) + extra;
+               raw->plane_size[1] = ALIGN(default_size >> 2, 256) + extra;
+               raw->plane_size[2] = ALIGN(default_size >> 2, 256) + extra;
+               break;
+       case V4L2_PIX_FMT_NV12M_S10B:
+       case V4L2_PIX_FMT_NV21M_S10B:
+               raw->plane_size[0] = NV12M_Y_SIZE(ctx->img_width, ctx->img_height);
+               raw->plane_size[1] = NV12M_CBCR_SIZE(ctx->img_width, ctx->img_height);
+               raw->plane_size_2bits[0] = NV12M_Y_2B_SIZE(ctx->img_width, ctx->img_height);
+               raw->plane_size_2bits[1] = NV12M_CBCR_2B_SIZE(ctx->img_width, ctx->img_height);
+               break;
+       case V4L2_PIX_FMT_NV12MT_16X16:
+       case V4L2_PIX_FMT_NV12M:
+       case V4L2_PIX_FMT_NV12N:
+       case V4L2_PIX_FMT_NV21M:
+               raw->plane_size[0] = ALIGN(default_size, 256) + extra;
+               raw->plane_size[1] = ALIGN(default_size / 2, 256) + extra;
+               break;
+       case V4L2_PIX_FMT_NV12M_P010:
+       case V4L2_PIX_FMT_NV21M_P010:
+               raw->plane_size[0] = ALIGN(default_size, 256) * 2 + extra;
+               raw->plane_size[1] = ALIGN(default_size, 256) + extra;
+               break;
+       case V4L2_PIX_FMT_NV16M_S10B:
+       case V4L2_PIX_FMT_NV61M_S10B:
+               raw->plane_size[0] = NV16M_Y_SIZE(ctx->img_width, ctx->img_height);
+               raw->plane_size[1] = NV16M_CBCR_SIZE(ctx->img_width, ctx->img_height);
+               raw->plane_size_2bits[0] = NV16M_Y_2B_SIZE(ctx->img_width, ctx->img_height);
+               raw->plane_size_2bits[1] = NV16M_CBCR_2B_SIZE(ctx->img_width, ctx->img_height);
+               break;
+       case V4L2_PIX_FMT_NV16M:
+       case V4L2_PIX_FMT_NV61M:
+               raw->plane_size[0] = ALIGN(default_size, 256) + extra;
+               raw->plane_size[1] = ALIGN(default_size, 256) + extra;
+               break;
+       case V4L2_PIX_FMT_NV16M_P210:
+       case V4L2_PIX_FMT_NV61M_P210:
+               raw->plane_size[0] = ALIGN(default_size, 256) * 2 + extra;
+               raw->plane_size[1] = ALIGN(default_size, 256) * 2 + extra;
+               break;
+       default:
+               mfc_err_ctx("Invalid pixel format(%d)\n", ctx->src_fmt->fourcc);
+               break;
+       }
+
+       mfc_set_linear_stride_size(ctx, ctx->src_fmt);
+
+       for (i = 0; i < raw->num_planes; i++) {
+               raw->total_plane_size += raw->plane_size[i];
+               mfc_debug(2, "[FRAME] Plane[%d] size = %d, stride = %d\n",
+                       i, raw->plane_size[i], raw->stride[i]);
+       }
+       if (ctx->is_10bit) {
+               for (i = 0; i < raw->num_planes; i++) {
+                       raw->total_plane_size += raw->plane_size_2bits[i];
+                       mfc_debug(2, "[FRAME][10BIT] Plane[%d] 2bit size = %d, stride = %d\n",
+                                       i, raw->plane_size_2bits[i],
+                                       raw->stride_2bits[i]);
+               }
+       }
+
+       mfc_debug(2, "[FRAME] total plane size: %d\n", raw->total_plane_size);
+}
+
+void s5p_mfc_cleanup_assigned_dpb(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dec *dec;
+       struct s5p_mfc_buf *dst_mb;
+       int i;
+
+       if (!ctx) {
+               mfc_err_dev("no mfc context to run\n");
+               return;
+       }
+
+       dec = ctx->dec_priv;
+       if (!dec) {
+               mfc_err_dev("no mfc decoder to run\n");
+               return;
+       }
+
+       if (ctx->is_drm && ctx->raw_protect_flag) {
+               mfc_debug(2, "raw_protect_flag(%#lx) will be released\n",
+                               ctx->raw_protect_flag);
+               for (i = 0; i < MFC_MAX_DPBS; i++) {
+                       dst_mb = dec->assigned_dpb[i];
+
+                       s5p_mfc_raw_unprotect(ctx, dst_mb, i);
+               }
+               s5p_mfc_clear_assigned_dpb(ctx);
+       }
+}
+
+void s5p_mfc_unprotect_released_dpb(struct s5p_mfc_ctx *ctx, unsigned int released_flag)
+{
+       struct s5p_mfc_dec *dec;
+       struct s5p_mfc_buf *dst_mb;
+       int i;
+
+       if (!ctx) {
+               mfc_err_dev("no mfc context to run\n");
+               return;
+       }
+
+       dec = ctx->dec_priv;
+       if (!dec) {
+               mfc_err_dev("no mfc decoder to run\n");
+               return;
+       }
+
+       if (ctx->is_drm) {
+               for (i = 0; i < MFC_MAX_DPBS; i++) {
+                       if (released_flag & (1 << i)) {
+                               dst_mb = dec->assigned_dpb[i];
+                               s5p_mfc_raw_unprotect(ctx, dst_mb, i);
+                       }
+               }
+       }
+
+}
+
+void s5p_mfc_protect_dpb(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf *dst_mb)
+{
+       struct s5p_mfc_dec *dec;
+       int dst_index;
+
+       if (!ctx) {
+               mfc_err_dev("no mfc context to run\n");
+               return;
+       }
+
+       dec = ctx->dec_priv;
+       if (!dec) {
+               mfc_err_dev("no mfc decoder to run\n");
+               return;
+       }
+
+       dst_index = dst_mb->vb.vb2_buf.index;
+
+       if (ctx->is_drm) {
+               dec->assigned_dpb[dst_index] = dst_mb;
+               s5p_mfc_raw_protect(ctx, dst_mb, dst_index);
+       }
+}
+
+void s5p_mfc_watchdog_tick(unsigned long arg)
+{
+       struct s5p_mfc_dev *dev = (struct s5p_mfc_dev *)arg;
+
+       if (!dev) {
+               mfc_err_dev("no mfc device to run\n");
+               return;
+       }
+
+       mfc_debug(5, "watchdog is ticking!\n");
+
+       if (atomic_read(&dev->watchdog_tick_running))
+               atomic_inc(&dev->watchdog_tick_cnt);
+       else
+               atomic_set(&dev->watchdog_tick_cnt, 0);
+
+       if (atomic_read(&dev->watchdog_tick_cnt) >= WATCHDOG_TICK_CNT_TO_START_WATCHDOG) {
+               /* 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_dev("[%d] Time out during waiting for HW\n",
+                               atomic_read(&dev->watchdog_tick_cnt));
+               queue_work(dev->watchdog_wq, &dev->watchdog_work);
+       }
+
+       dev->watchdog_timer.expires = jiffies +
+                                       msecs_to_jiffies(WATCHDOG_TICK_INTERVAL);
+       add_timer(&dev->watchdog_timer);
+}
+
+void s5p_mfc_watchdog_start_tick(struct s5p_mfc_dev *dev)
+{
+       if (atomic_read(&dev->watchdog_tick_running)) {
+               mfc_debug(2, "watchdog timer was already started!\n");
+       } else {
+               mfc_debug(2, "watchdog timer is now started!\n");
+               atomic_set(&dev->watchdog_tick_running, 1);
+       }
+
+       /* Reset the timeout watchdog */
+       atomic_set(&dev->watchdog_tick_cnt, 0);
+}
+
+void s5p_mfc_watchdog_stop_tick(struct s5p_mfc_dev *dev)
+{
+       if (atomic_read(&dev->watchdog_tick_running)) {
+               mfc_debug(2, "watchdog timer is now stopped!\n");
+               atomic_set(&dev->watchdog_tick_running, 0);
+       } else {
+               mfc_debug(2, "watchdog timer was already stopped!\n");
+       }
+
+       /* Reset the timeout watchdog */
+       atomic_set(&dev->watchdog_tick_cnt, 0);
+}
+
+void s5p_mfc_watchdog_reset_tick(struct s5p_mfc_dev *dev)
+{
+       mfc_debug(2, "watchdog timer reset!\n");
+
+       /* Reset the timeout watchdog */
+       atomic_set(&dev->watchdog_tick_cnt, 0);
+}
diff --git a/drivers/media/platform/exynos/mfc/mfc_utils.h b/drivers/media/platform/exynos/mfc/mfc_utils.h
new file mode 100644 (file)
index 0000000..1a611a5
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_utils.h
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __MFC_UTILS_H
+#define __MFC_UTILS_H __FILE__
+
+#include "mfc_common.h"
+
+static inline void s5p_mfc_clean_dev_int_flags(struct s5p_mfc_dev *dev)
+{
+       dev->int_condition = 0;
+       dev->int_reason = 0;
+       dev->int_err = 0;
+}
+
+static inline void s5p_mfc_clean_ctx_int_flags(struct s5p_mfc_ctx *ctx)
+{
+       ctx->int_condition = 0;
+       ctx->int_reason = 0;
+       ctx->int_err = 0;
+}
+
+static inline void s5p_mfc_change_state(struct s5p_mfc_ctx *ctx, enum s5p_mfc_inst_state state)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       MFC_TRACE_CTX("** state : %d\n", state);
+       ctx->state = state;
+}
+
+static inline enum s5p_mfc_node_type s5p_mfc_get_node_type(struct file *file)
+{
+       struct video_device *vdev = video_devdata(file);
+       enum s5p_mfc_node_type node_type;
+
+       if (!vdev) {
+               mfc_err_dev("failed to get video_device\n");
+               return MFCNODE_INVALID;
+       }
+
+       mfc_debug(2, "video_device index: %d\n", vdev->index);
+
+       switch (vdev->index) {
+       case 0:
+               node_type = MFCNODE_DECODER;
+               break;
+       case 1:
+               node_type = MFCNODE_ENCODER;
+               break;
+       case 2:
+               node_type = MFCNODE_DECODER_DRM;
+               break;
+       case 3:
+               node_type = MFCNODE_ENCODER_DRM;
+               break;
+       case 4:
+               node_type = MFCNODE_ENCODER_OTF;
+               break;
+       case 5:
+               node_type = MFCNODE_ENCODER_OTF_DRM;
+               break;
+       default:
+               node_type = MFCNODE_INVALID;
+               break;
+       }
+
+       return node_type;
+}
+
+static inline int s5p_mfc_is_decoder_node(enum s5p_mfc_node_type node)
+{
+       if (node == MFCNODE_DECODER || node == MFCNODE_DECODER_DRM)
+               return 1;
+
+       return 0;
+}
+
+static inline int s5p_mfc_is_drm_node(enum s5p_mfc_node_type node)
+{
+       if (node == MFCNODE_DECODER_DRM || node == MFCNODE_ENCODER_DRM ||
+                       node == MFCNODE_ENCODER_OTF_DRM)
+               return 1;
+
+       return 0;
+}
+
+static inline int s5p_mfc_is_encoder_otf_node(enum s5p_mfc_node_type node)
+{
+       if (node == MFCNODE_ENCODER_OTF || node == MFCNODE_ENCODER_OTF_DRM)
+               return 1;
+
+       return 0;
+}
+
+int s5p_mfc_check_vb_with_fmt(struct s5p_mfc_fmt *fmt, struct vb2_buffer *vb);
+
+void s5p_mfc_raw_protect(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf *mfc_buf,
+                                       int index);
+void s5p_mfc_raw_unprotect(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf *mfc_buf,
+                                       int index);
+void s5p_mfc_stream_protect(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf *mfc_buf,
+                                       int index);
+void s5p_mfc_stream_unprotect(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf *mfc_buf,
+                                       int index);
+
+void s5p_mfc_dec_calc_dpb_size(struct s5p_mfc_ctx *ctx);
+void s5p_mfc_enc_calc_src_size(struct s5p_mfc_ctx *ctx);
+
+static inline void s5p_mfc_cleanup_assigned_fd(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dec *dec;
+       int i;
+
+       dec = ctx->dec_priv;
+
+       for (i = 0; i < MFC_MAX_DPBS; i++)
+               dec->assigned_fd[i] = MFC_INFO_INIT_FD;
+}
+
+static inline void s5p_mfc_clear_assigned_dpb(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dec *dec;
+       int i;
+
+       if (!ctx) {
+               mfc_err_dev("no mfc context to run\n");
+               return;
+       }
+
+       dec = ctx->dec_priv;
+       if (!dec) {
+               mfc_err_dev("no mfc decoder to run\n");
+               return;
+       }
+
+       for (i = 0; i < MFC_MAX_DPBS; i++)
+               dec->assigned_dpb[i] = NULL;
+}
+
+static inline int s5p_mfc_dec_status_decoding(unsigned int dst_frame_status)
+{
+       if (dst_frame_status == S5P_FIMV_DEC_STATUS_DECODING_DISPLAY ||
+           dst_frame_status == S5P_FIMV_DEC_STATUS_DECODING_ONLY)
+               return 1;
+       return 0;
+}
+
+static inline int s5p_mfc_dec_status_display(unsigned int dst_frame_status)
+{
+       if (dst_frame_status == S5P_FIMV_DEC_STATUS_DISPLAY_ONLY ||
+           dst_frame_status == S5P_FIMV_DEC_STATUS_DECODING_DISPLAY)
+               return 1;
+
+       return 0;
+}
+
+void s5p_mfc_cleanup_assigned_dpb(struct s5p_mfc_ctx *ctx);
+void s5p_mfc_unprotect_released_dpb(struct s5p_mfc_ctx *ctx, unsigned int released_flag);
+void s5p_mfc_protect_dpb(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf *dst_mb);
+
+/* Watchdog interval */
+#define WATCHDOG_TICK_INTERVAL   1000
+/* After how many executions watchdog should assume lock up */
+#define WATCHDOG_TICK_CNT_TO_START_WATCHDOG        5
+
+void s5p_mfc_watchdog_tick(unsigned long arg);
+void s5p_mfc_watchdog_start_tick(struct s5p_mfc_dev *dev);
+void s5p_mfc_watchdog_stop_tick(struct s5p_mfc_dev *dev);
+void s5p_mfc_watchdog_reset_tick(struct s5p_mfc_dev *dev);
+
+#endif /* __MFC_UTILS_H */
diff --git a/drivers/media/platform/exynos/mfc/mfc_watchdog.c b/drivers/media/platform/exynos/mfc/mfc_watchdog.c
new file mode 100644 (file)
index 0000000..51a905b
--- /dev/null
@@ -0,0 +1,350 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_watchdog.c
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#ifdef BIGDATA_LOGGING_ENABLE
+#include <linux/sec_debug.h>
+#endif
+
+#include "mfc_watchdog.h"
+
+#include "mfc_sync.h"
+
+#include "mfc_pm.h"
+#include "mfc_cmd.h"
+#include "mfc_cal.h"
+#include "mfc_reg.h"
+
+#include "mfc_queue.h"
+#include "mfc_utils.h"
+
+#define MFC_SFR_AREA_COUNT     21
+static void mfc_dump_regs(struct s5p_mfc_dev *dev)
+{
+       int i;
+       struct s5p_mfc_ctx_buf_size *buf_size = NULL;
+       int addr[MFC_SFR_AREA_COUNT][2] = {
+               { 0x0, 0x80 },
+               { 0x1000, 0xCD0 },
+               { 0xF000, 0xFF8 },
+               { 0x2000, 0xA00 },
+               { 0x2f00, 0x6C },
+               { 0x3000, 0x40 },
+               { 0x3094, 0x4 },
+               { 0x30b4, 0x8 },
+               { 0x3110, 0x10 },
+               { 0x5000, 0x100 },
+               { 0x5200, 0x300 },
+               { 0x5600, 0x100 },
+               { 0x5800, 0x100 },
+               { 0x5A00, 0x100 },
+               { 0x6000, 0xC4 },
+               { 0x7000, 0x21C },
+               { 0x8000, 0x20C },
+               { 0x9000, 0x10C },
+               { 0xA000, 0x20C },
+               { 0xB000, 0x444 },
+               { 0xC000, 0x84 },
+       };
+
+       pr_err("-----------dumping MFC registers (SFR base = 0x%p, dev = 0x%p)\n",
+                               dev->regs_base, dev);
+
+       s5p_mfc_enable_all_clocks(dev);
+
+       for (i = 0; i < MFC_SFR_AREA_COUNT; i++) {
+               printk("[%04X .. %04X]\n", addr[i][0], addr[i][0] + addr[i][1]);
+               print_hex_dump(KERN_ERR, "", DUMP_PREFIX_ADDRESS, 32, 4, dev->regs_base + addr[i][0],
+                               addr[i][1], false);
+               printk("...\n");
+       }
+
+       if (dbg_enable) {
+               buf_size = dev->variant->buf_size->ctx_buf;
+               printk("[DBG INFO dump]\n");
+               print_hex_dump(KERN_ERR, "", DUMP_PREFIX_ADDRESS, 32, 4, dev->dbg_info_buf.vaddr,
+                       buf_size->dbg_info_buf, false);
+               printk("...\n");
+       }
+}
+
+const u32 s5p_mfc_logging_sfr_set1[MFC_SFR_LOGGING_COUNT_SET1] = {
+       0x1000, 0x1004, 0x100C, 0x1010
+};
+
+const u32 s5p_mfc_logging_sfr_set2[MFC_SFR_LOGGING_COUNT_SET2] = {
+       0x0070, 0x10B4, 0x2020, 0x2028,
+       0x204C, 0x20B4, 0x3000, 0x3004,
+       0x3010, 0x301C, 0x3110, 0x5A54,
+       0x5A80, 0x5A88, 0x5A94, 0x6038,
+       0x6050, 0x6168, 0x7018, 0x7110,
+       0x7114, 0xF088, 0xFFD0
+};
+
+int mfc_change_hex_to_ascii(u32 hex, u32 byte, char *ascii, int idx)
+{
+       int i;
+       char tmp;
+
+       for (i = 0; i < byte; i++) {
+               if (idx >= MFC_LOGGING_DATA_SIZE) {
+                       pr_err("logging data size exceed: %d\n", idx);
+                       return idx;
+               }
+
+               tmp = (hex >> ((byte - 1 - i) * 4)) & 0xF;
+               if (tmp > 9)
+                       ascii[idx] = tmp + 'a' - 0xa;
+               else if (tmp <= 9)
+                       ascii[idx] = tmp + '0';
+               idx++;
+       }
+
+       /* space */
+       if (idx < MFC_LOGGING_DATA_SIZE)
+               ascii[idx] = ' ';
+
+       return ++idx;
+}
+
+static void mfc_save_logging_sfr(struct s5p_mfc_dev *dev)
+{
+       char *errorinfo;
+       int i, idx = 0;
+
+       pr_err("-----------logging MFC error info-----------\n");
+       errorinfo = dev->logging_data->errorinfo;
+       for (i = 0; i < MFC_SFR_LOGGING_COUNT_SET1; i++)
+               dev->logging_data->SFRs_set1[i] = MFC_READL(s5p_mfc_logging_sfr_set1[i]);
+       for (i = 0; i < MFC_SFR_LOGGING_COUNT_SET2; i++)
+               dev->logging_data->SFRs_set2[i] = MFC_READL(s5p_mfc_logging_sfr_set2[i]);
+
+       idx = mfc_change_hex_to_ascii(dev->logging_data->cause, 8, errorinfo, idx);
+       idx = mfc_change_hex_to_ascii(dev->logging_data->fault_status, 2, errorinfo, idx);
+       idx = mfc_change_hex_to_ascii(dev->logging_data->fault_trans_info, 8, errorinfo, idx);
+       idx = mfc_change_hex_to_ascii(dev->logging_data->fault_addr, 8, errorinfo, idx);
+       for (i = 0; i < MFC_SFR_LOGGING_COUNT_SET1; i++)
+               idx = mfc_change_hex_to_ascii(dev->logging_data->SFRs_set1[i], 2, errorinfo, idx);
+       for (i = 0; i < MFC_SFR_LOGGING_COUNT_SET2; i++)
+               idx = mfc_change_hex_to_ascii(dev->logging_data->SFRs_set2[i], 8, errorinfo, idx);
+
+       pr_err("%s\n", errorinfo);
+
+#ifdef BIGDATA_LOGGING_ENABLE
+       sec_debug_set_extra_info_mfc_error(errorinfo);
+#endif
+}
+
+static void mfc_display_state(struct s5p_mfc_dev *dev)
+{
+       nal_queue_handle *nal_q_handle = dev->nal_q_handle;
+       int i;
+
+       pr_err("-----------dumping MFC device info-----------\n");
+       pr_err("power:%d, clock:%d, num_inst:%d, num_drm_inst:%d, fw_status:%d\n",
+                       s5p_mfc_pm_get_pwr_ref_cnt(dev), s5p_mfc_pm_get_clk_ref_cnt(dev),
+                       dev->num_inst, dev->num_drm_inst, dev->fw.status);
+       pr_err("hwlock bits:%#lx / dev:%#lx, curr_ctx:%d (is_drm:%d),"
+                       " preempt_ctx:%d, work_bits:%#lx\n",
+                       dev->hwlock.bits, dev->hwlock.dev,
+                       dev->curr_ctx, dev->curr_ctx_is_drm,
+                       dev->preempt_ctx, s5p_mfc_get_bits(&dev->work_bits));
+       pr_err("options debug_level:%d, debug_mode:%d, mmcache:%d, perf_boost:%d\n",
+                       debug_level, dev->pdata->debug_mode, dev->mmcache.is_on_status, perf_boost_mode);
+       pr_err("NAL-Q state:%d, exception:%d, in_exe_cnt: %d, out_exe_cnt: %d\n",
+                       nal_q_handle->nal_q_state, nal_q_handle->nal_q_exception,
+                       nal_q_handle->nal_q_in_handle->in_exe_count,
+                       nal_q_handle->nal_q_out_handle->out_exe_count);
+
+       for (i = 0; i < MFC_NUM_CONTEXTS; i++)
+               if (dev->ctx[i])
+                       pr_err("MFC ctx[%d] %s(%d) state:%d, queue_cnt(src:%d, dst:%d, ref:%d, qsrc:%d, qdst:%d)\n"
+                               "     interrupt(cond:%d, type:%d, err:%d)\n",
+                               dev->ctx[i]->num,
+                               dev->ctx[i]->type == MFCINST_DECODER ? "DEC" : "ENC",
+                               dev->ctx[i]->codec_mode, dev->ctx[i]->state,
+                               s5p_mfc_get_queue_count(&dev->ctx[i]->buf_queue_lock, &dev->ctx[i]->src_buf_queue),
+                               s5p_mfc_get_queue_count(&dev->ctx[i]->buf_queue_lock, &dev->ctx[i]->dst_buf_queue),
+                               s5p_mfc_get_queue_count(&dev->ctx[i]->buf_queue_lock, &dev->ctx[i]->ref_buf_queue),
+                               s5p_mfc_get_queue_count(&dev->ctx[i]->buf_queue_lock, &dev->ctx[i]->src_buf_nal_queue),
+                               s5p_mfc_get_queue_count(&dev->ctx[i]->buf_queue_lock, &dev->ctx[i]->dst_buf_nal_queue),
+                               dev->ctx[i]->int_condition, dev->ctx[i]->int_reason,
+                               dev->ctx[i]->int_err);
+}
+
+static void mfc_print_trace(struct s5p_mfc_dev *dev)
+{
+       int i, cnt, trace_cnt;
+
+       pr_err("-----------dumping MFC trace info-----------\n");
+
+       trace_cnt = atomic_read(&dev->trace_ref);
+       for (i = MFC_TRACE_COUNT_PRINT - 1; i >= 0; i--) {
+               cnt = ((trace_cnt + MFC_TRACE_COUNT_MAX) - i) % MFC_TRACE_COUNT_MAX;
+               pr_err("MFC trace[%d]: time=%llu, str=%s", cnt,
+                               dev->mfc_trace[cnt].time, dev->mfc_trace[cnt].str);
+       }
+}
+
+void mfc_dump_buffer_info(struct s5p_mfc_dev *dev)
+{
+       struct s5p_mfc_ctx *ctx;
+
+       ctx = dev->ctx[dev->curr_ctx];
+       if (ctx) {
+               pr_err("-----------dumping MFC buffer info (fault at: %#x)\n",
+                               dev->logging_data->fault_addr);
+               pr_err("common:%#llx~%#llx, instance:%#llx~%#llx, codec:%#llx~%#llx\n",
+                               dev->common_ctx_buf.daddr,
+                               dev->common_ctx_buf.daddr + PAGE_ALIGN(0x7800),
+                               ctx->instance_ctx_buf.daddr,
+                               ctx->instance_ctx_buf.daddr + ctx->instance_ctx_buf.size,
+                               ctx->codec_buf.daddr,
+                               ctx->codec_buf.daddr + ctx->codec_buf.size);
+               if (ctx->type == MFCINST_DECODER) {
+                       pr_err("Decoder CPB:%#x++%#x, scratch:%#x++%#x, static(vp9):%#x++%#x\n",
+                                       MFC_READL(S5P_FIMV_D_CPB_BUFFER_ADDR),
+                                       MFC_READL(S5P_FIMV_D_CPB_BUFFER_SIZE),
+                                       MFC_READL(S5P_FIMV_D_SCRATCH_BUFFER_ADDR),
+                                       MFC_READL(S5P_FIMV_D_SCRATCH_BUFFER_SIZE),
+                                       MFC_READL(S5P_FIMV_D_STATIC_BUFFER_ADDR),
+                                       MFC_READL(S5P_FIMV_D_STATIC_BUFFER_SIZE));
+                       pr_err("DPB [0]plane:++%#x, [1]plane:++%#x, [2]plane:++%#x, MV buffer:++%#lx\n",
+                                       ctx->raw_buf.plane_size[0],
+                                       ctx->raw_buf.plane_size[1],
+                                       ctx->raw_buf.plane_size[2],
+                                       ctx->mv_size);
+                       print_hex_dump(KERN_ERR, "[0] plane ", DUMP_PREFIX_ADDRESS, 32, 4,
+                                       dev->regs_base + S5P_FIMV_D_FIRST_PLANE_DPB0,
+                                       0x100, false);
+                       print_hex_dump(KERN_ERR, "[1] plane ", DUMP_PREFIX_ADDRESS, 32, 4,
+                                       dev->regs_base + S5P_FIMV_D_SECOND_PLANE_DPB0,
+                                       0x100, false);
+                       if (ctx->dst_fmt->num_planes == 3)
+                               print_hex_dump(KERN_ERR, "[2] plane ", DUMP_PREFIX_ADDRESS, 32, 4,
+                                               dev->regs_base + S5P_FIMV_D_THIRD_PLANE_DPB0,
+                                               0x100, false);
+                       print_hex_dump(KERN_ERR, "MV buffer ", DUMP_PREFIX_ADDRESS, 32, 4,
+                                       dev->regs_base + S5P_FIMV_D_MV_BUFFER0,
+                                       0x100, false);
+               } else if (ctx->type == MFCINST_ENCODER) {
+                       pr_err("Encoder SRC %dplane, [0]:%#x++%#x, [1]:%#x++%#x, [2]:%#x++%#x\n",
+                                       ctx->src_fmt->num_planes,
+                                       MFC_READL(S5P_FIMV_E_SOURCE_FIRST_ADDR),
+                                       ctx->raw_buf.plane_size[0],
+                                       MFC_READL(S5P_FIMV_E_SOURCE_SECOND_ADDR),
+                                       ctx->raw_buf.plane_size[1],
+                                       MFC_READL(S5P_FIMV_E_SOURCE_THIRD_ADDR),
+                                       ctx->raw_buf.plane_size[2]);
+                       pr_err("DST:%#x++%#x, scratch:%#x++%#x\n",
+                                       MFC_READL(S5P_FIMV_E_STREAM_BUFFER_ADDR),
+                                       MFC_READL(S5P_FIMV_E_STREAM_BUFFER_SIZE),
+                                       MFC_READL(S5P_FIMV_E_SCRATCH_BUFFER_ADDR),
+                                       MFC_READL(S5P_FIMV_E_SCRATCH_BUFFER_SIZE));
+                       pr_err("DPB [0] plane:++%#lx, [1] plane:++%#lx, ME buffer:++%#lx\n",
+                                       ctx->enc_priv->luma_dpb_size,
+                                       ctx->enc_priv->chroma_dpb_size,
+                                       ctx->enc_priv->me_buffer_size);
+                       print_hex_dump(KERN_ERR, "[0] plane ", DUMP_PREFIX_ADDRESS, 32, 4,
+                                       dev->regs_base + S5P_FIMV_E_LUMA_DPB,
+                                       0x44, false);
+                       print_hex_dump(KERN_ERR, "[1] plane ", DUMP_PREFIX_ADDRESS, 32, 4,
+                                       dev->regs_base + S5P_FIMV_E_CHROMA_DPB,
+                                       0x44, false);
+                       print_hex_dump(KERN_ERR, "ME buffer ", DUMP_PREFIX_ADDRESS, 32, 4,
+                                       dev->regs_base + S5P_FIMV_E_ME_BUFFER,
+                                       0x44, false);
+               } else {
+                       pr_err("invalid MFC instnace type(%d)\n", ctx->type);
+               }
+       }
+}
+
+static void mfc_dump_info_without_regs(struct s5p_mfc_dev *dev)
+{
+       mfc_display_state(dev);
+       mfc_print_trace(dev);
+}
+
+static void mfc_dump_info(struct s5p_mfc_dev *dev)
+{
+       mfc_dump_info_without_regs(dev);
+       mfc_save_logging_sfr(dev);
+       mfc_dump_buffer_info(dev);
+       mfc_dump_regs(dev);
+       exynos_sysmmu_show_status(dev->device);
+}
+
+static void mfc_dump_info_and_stop_hw(struct s5p_mfc_dev *dev)
+{
+       MFC_TRACE_DEV("** mfc will stop!!!\n");
+       mfc_dump_info(dev);
+       BUG();
+}
+
+static void mfc_dump_info_and_stop_hw_debug(struct s5p_mfc_dev *dev)
+{
+       if (!dev->pdata->debug_mode)
+               return;
+
+       MFC_TRACE_DEV("** mfc will stop!!!\n");
+       mfc_dump_info(dev);
+       BUG();
+}
+
+void s5p_mfc_watchdog_worker(struct work_struct *work)
+{
+       struct s5p_mfc_dev *dev;
+       int cmd;
+
+       dev = container_of(work, struct s5p_mfc_dev, watchdog_work);
+
+       if (atomic_read(&dev->watchdog_run)) {
+               mfc_err_dev("watchdog already running???\n");
+               return;
+       }
+
+       if (!atomic_read(&dev->watchdog_tick_cnt)) {
+               mfc_err_dev("interrupt handler is called\n");
+               return;
+       }
+
+       cmd = s5p_mfc_check_risc2host(dev);
+       if (cmd) {
+               if (atomic_read(&dev->watchdog_tick_cnt) == (3 * WATCHDOG_TICK_CNT_TO_START_WATCHDOG)) {
+                       mfc_err_dev("MFC driver waited for upward of %dsec\n",
+                                       3 * WATCHDOG_TICK_CNT_TO_START_WATCHDOG);
+                       dev->logging_data->cause |= (1 << MFC_CAUSE_NO_SCHEDULING);
+               } else {
+                       mfc_err_dev("interrupt(%d) is occurred, wait scheduling\n", cmd);
+                       return;
+               }
+       } else {
+               dev->logging_data->cause |= (1 << MFC_CAUSE_NO_INTERRUPT);
+               mfc_err_dev("Driver timeout error handling\n");
+       }
+
+       /* Run watchdog worker */
+       atomic_set(&dev->watchdog_run, 1);
+
+       /* Reset the timeout watchdog */
+       atomic_set(&dev->watchdog_tick_cnt, 0);
+
+       /* Stop after dumping information */
+       mfc_dump_info_and_stop_hw(dev);
+}
+
+struct s5p_mfc_dump_ops mfc_dump_ops = {
+       .dump_regs                      = mfc_dump_regs,
+       .dump_info                      = mfc_dump_info,
+       .dump_info_without_regs         = mfc_dump_info_without_regs,
+       .dump_and_stop_always           = mfc_dump_info_and_stop_hw,
+       .dump_and_stop_debug_mode       = mfc_dump_info_and_stop_hw_debug,
+};
diff --git a/drivers/media/platform/exynos/mfc/mfc_watchdog.h b/drivers/media/platform/exynos/mfc/mfc_watchdog.h
new file mode 100644 (file)
index 0000000..4d01e16
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * drivers/media/platform/exynos/mfc/s5p_mfc_watchdog.h
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *              http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __MFC_WATCHDOG_H
+#define __MFC_WATCHDOG_H __FILE__
+
+#include "mfc_common.h"
+
+void s5p_mfc_watchdog_worker(struct work_struct *work);
+
+#endif /* __MFC_WATCHDOG_H */
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc.c b/drivers/media/platform/exynos/mfc/s5p_mfc.c
deleted file mode 100644 (file)
index 61a9462..0000000
+++ /dev/null
@@ -1,1651 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc.c
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/of_address.h>
-#include <linux/proc_fs.h>
-#include <video/videonode.h>
-#include <linux/of.h>
-#include <linux/smc.h>
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-#include <linux/poll.h>
-
-#include "s5p_mfc_common.h"
-
-#include "s5p_mfc_irq.h"
-#include "s5p_mfc_dec.h"
-#include "s5p_mfc_enc.h"
-
-#include "s5p_mfc_ctrl.h"
-#include "s5p_mfc_hwlock.h"
-#include "s5p_mfc_nal_q.h"
-#include "s5p_mfc_otf.h"
-#include "s5p_mfc_watchdog.h"
-#include "s5p_mfc_debugfs.h"
-#include "s5p_mfc_opr.h"
-#include "s5p_mfc_sync.h"
-
-#include "s5p_mfc_inst.h"
-#include "s5p_mfc_pm.h"
-#include "s5p_mfc_cal.h"
-#include "s5p_mfc_perf_measure.h"
-#include "s5p_mfc_reg.h"
-#include "s5p_mfc_mmcache.h"
-
-#include "s5p_mfc_qos.h"
-#include "s5p_mfc_queue.h"
-#include "s5p_mfc_utils.h"
-#include "s5p_mfc_buf.h"
-#include "s5p_mfc_mem.h"
-
-#define CREATE_TRACE_POINTS
-#include <trace/events/mfc.h>
-
-#define S5P_MFC_NAME                   "s5p-mfc"
-#define S5P_MFC_DEC_NAME               "s5p-mfc-dec"
-#define S5P_MFC_ENC_NAME               "s5p-mfc-enc"
-#define S5P_MFC_DEC_DRM_NAME           "s5p-mfc-dec-secure"
-#define S5P_MFC_ENC_DRM_NAME           "s5p-mfc-enc-secure"
-#define S5P_MFC_ENC_OTF_NAME           "s5p-mfc-enc-otf"
-#define S5P_MFC_ENC_OTF_DRM_NAME       "s5p-mfc-enc-otf-secure"
-
-struct _mfc_trace g_mfc_trace[MFC_TRACE_COUNT_MAX];
-struct _mfc_trace g_mfc_trace_hwlock[MFC_TRACE_COUNT_MAX];
-struct s5p_mfc_dev *g_mfc_dev;
-
-#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
-static struct proc_dir_entry *mfc_proc_entry;
-
-#define MFC_PROC_ROOT                  "mfc"
-#define MFC_PROC_INSTANCE_NUMBER       "instance_number"
-#define MFC_PROC_DRM_INSTANCE_NUMBER   "drm_instance_number"
-#define MFC_PROC_FW_STATUS             "fw_status"
-#endif
-
-#define DEF_DEC_SRC_FMT        9
-#define DEF_DEC_DST_FMT        5
-
-#define DEF_ENC_SRC_FMT        5
-#define DEF_ENC_DST_FMT        13
-
-void s5p_mfc_butler_worker(struct work_struct *work)
-{
-       struct s5p_mfc_dev *dev;
-
-       dev = container_of(work, struct s5p_mfc_dev, butler_work);
-
-       s5p_mfc_try_run(dev);
-}
-
-extern struct s5p_mfc_ctrls_ops decoder_ctrls_ops;
-extern struct vb2_ops s5p_mfc_dec_qops;
-extern struct s5p_mfc_fmt dec_formats[];
-
-static void mfc_deinit_dec_ctx(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dec *dec = ctx->dec_priv;
-
-       s5p_mfc_delete_queue(&ctx->src_buf_queue);
-       s5p_mfc_delete_queue(&ctx->dst_buf_queue);
-       s5p_mfc_delete_queue(&ctx->src_buf_nal_queue);
-       s5p_mfc_delete_queue(&ctx->dst_buf_nal_queue);
-       s5p_mfc_delete_queue(&ctx->ref_buf_queue);
-
-       s5p_mfc_mem_cleanup_user_shared_handle(ctx, &dec->sh_handle);
-       kfree(dec->ref_info);
-       kfree(dec);
-}
-
-static int mfc_init_dec_ctx(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dec *dec;
-       int ret = 0;
-       int i;
-
-       dec = kzalloc(sizeof(struct s5p_mfc_dec), GFP_KERNEL);
-       if (!dec) {
-               mfc_err_dev("failed to allocate decoder private data\n");
-               return -ENOMEM;
-       }
-       ctx->dec_priv = dec;
-
-       ctx->inst_no = MFC_NO_INSTANCE_SET;
-
-       s5p_mfc_create_queue(&ctx->src_buf_queue);
-       s5p_mfc_create_queue(&ctx->dst_buf_queue);
-       s5p_mfc_create_queue(&ctx->src_buf_nal_queue);
-       s5p_mfc_create_queue(&ctx->dst_buf_nal_queue);
-       s5p_mfc_create_queue(&ctx->ref_buf_queue);
-
-       for (i = 0; i < MFC_MAX_BUFFERS; i++) {
-               INIT_LIST_HEAD(&ctx->src_ctrls[i]);
-               INIT_LIST_HEAD(&ctx->dst_ctrls[i]);
-       }
-       ctx->src_ctrls_avail = 0;
-       ctx->dst_ctrls_avail = 0;
-
-       ctx->capture_state = QUEUE_FREE;
-       ctx->output_state = QUEUE_FREE;
-
-       s5p_mfc_change_state(ctx, MFCINST_INIT);
-       ctx->type = MFCINST_DECODER;
-       ctx->c_ops = &decoder_ctrls_ops;
-       ctx->src_fmt = &dec_formats[DEF_DEC_SRC_FMT];
-       ctx->dst_fmt = &dec_formats[DEF_DEC_DST_FMT];
-
-       s5p_mfc_qos_reset_framerate(ctx);
-
-       ctx->qos_ratio = 100;
-#ifdef CONFIG_MFC_USE_BUS_DEVFREQ
-       INIT_LIST_HEAD(&ctx->qos_list);
-#endif
-       INIT_LIST_HEAD(&ctx->ts_list);
-
-       dec->display_delay = -1;
-       dec->is_interlaced = 0;
-       dec->immediate_display = 0;
-       dec->is_dts_mode = 0;
-       dec->err_reuse_flag = 0;
-       dec->dec_only_release_flag = 0;
-
-       dec->is_dynamic_dpb = 1;
-       dec->dynamic_used = 0;
-       dec->is_dpb_full = 0;
-       s5p_mfc_cleanup_assigned_fd(ctx);
-       s5p_mfc_clear_assigned_dpb(ctx);
-       dec->sh_handle.fd = -1;
-       dec->ref_info = kzalloc(
-               (sizeof(struct dec_dpb_ref_info) * MFC_MAX_DPBS), GFP_KERNEL);
-       if (!dec->ref_info) {
-               mfc_err_dev("failed to allocate decoder information data\n");
-               ret = -ENOMEM;
-               goto fail_dec_init;
-       }
-       for (i = 0; i < MFC_MAX_BUFFERS; i++)
-               dec->ref_info[i].dpb[0].fd[0] = MFC_INFO_INIT_FD;
-
-       /* Init videobuf2 queue for OUTPUT */
-       ctx->vq_src.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
-       ctx->vq_src.drv_priv = ctx;
-       ctx->vq_src.buf_struct_size = sizeof(struct s5p_mfc_buf);
-       ctx->vq_src.io_modes = VB2_USERPTR | VB2_DMABUF;
-       ctx->vq_src.ops = &s5p_mfc_dec_qops;
-       ctx->vq_src.mem_ops = s5p_mfc_mem_ops();
-       ctx->vq_src.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
-       ret = vb2_queue_init(&ctx->vq_src);
-       if (ret) {
-               mfc_err_dev("Failed to initialize videobuf2 queue(output)\n");
-               goto fail_dec_init;
-       }
-       /* Init videobuf2 queue for CAPTURE */
-       ctx->vq_dst.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
-       ctx->vq_dst.drv_priv = ctx;
-       ctx->vq_dst.buf_struct_size = sizeof(struct s5p_mfc_buf);
-       ctx->vq_dst.io_modes = VB2_USERPTR | VB2_DMABUF;
-       ctx->vq_dst.ops = &s5p_mfc_dec_qops;
-       ctx->vq_dst.mem_ops = s5p_mfc_mem_ops();
-       ctx->vq_dst.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
-       ret = vb2_queue_init(&ctx->vq_dst);
-       if (ret) {
-               mfc_err_dev("Failed to initialize videobuf2 queue(capture)\n");
-               goto fail_dec_init;
-       }
-
-       return ret;
-
-fail_dec_init:
-       mfc_deinit_dec_ctx(ctx);
-       return ret;
-}
-
-extern struct s5p_mfc_ctrls_ops encoder_ctrls_ops;
-extern struct vb2_ops s5p_mfc_enc_qops;
-extern struct s5p_mfc_fmt enc_formats[];
-
-static void mfc_deinit_enc_ctx(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_enc *enc = ctx->enc_priv;
-
-       s5p_mfc_delete_queue(&ctx->src_buf_queue);
-       s5p_mfc_delete_queue(&ctx->dst_buf_queue);
-       s5p_mfc_delete_queue(&ctx->src_buf_nal_queue);
-       s5p_mfc_delete_queue(&ctx->dst_buf_nal_queue);
-       s5p_mfc_delete_queue(&ctx->ref_buf_queue);
-
-       s5p_mfc_mem_cleanup_user_shared_handle(ctx, &enc->sh_handle_svc);
-       s5p_mfc_mem_cleanup_user_shared_handle(ctx, &enc->sh_handle_roi);
-       s5p_mfc_release_enc_roi_buffer(ctx);
-       kfree(enc);
-}
-
-static int mfc_init_enc_ctx(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_enc *enc;
-       struct s5p_mfc_enc_params *p;
-       int ret = 0;
-       int i;
-
-       enc = kzalloc(sizeof(struct s5p_mfc_enc), GFP_KERNEL);
-       if (!enc) {
-               mfc_err_dev("failed to allocate encoder private data\n");
-               return -ENOMEM;
-       }
-       ctx->enc_priv = enc;
-
-       ctx->inst_no = MFC_NO_INSTANCE_SET;
-
-       s5p_mfc_create_queue(&ctx->src_buf_queue);
-       s5p_mfc_create_queue(&ctx->dst_buf_queue);
-       s5p_mfc_create_queue(&ctx->src_buf_nal_queue);
-       s5p_mfc_create_queue(&ctx->dst_buf_nal_queue);
-       s5p_mfc_create_queue(&ctx->ref_buf_queue);
-
-       for (i = 0; i < MFC_MAX_BUFFERS; i++) {
-               INIT_LIST_HEAD(&ctx->src_ctrls[i]);
-               INIT_LIST_HEAD(&ctx->dst_ctrls[i]);
-       }
-       ctx->src_ctrls_avail = 0;
-       ctx->dst_ctrls_avail = 0;
-
-       ctx->type = MFCINST_ENCODER;
-       ctx->c_ops = &encoder_ctrls_ops;
-       ctx->src_fmt = &enc_formats[DEF_ENC_SRC_FMT];
-       ctx->dst_fmt = &enc_formats[DEF_ENC_DST_FMT];
-
-       s5p_mfc_qos_reset_framerate(ctx);
-
-       ctx->qos_ratio = 100;
-
-       /* disable IVF header by default (VP8, VP9) */
-       p = &enc->params;
-       p->ivf_header_disable = 1;
-
-#ifdef CONFIG_MFC_USE_BUS_DEVFREQ
-       INIT_LIST_HEAD(&ctx->qos_list);
-#endif
-       INIT_LIST_HEAD(&ctx->ts_list);
-
-       enc->sh_handle_svc.fd = -1;
-       enc->sh_handle_roi.fd = -1;
-
-       /* Init videobuf2 queue for OUTPUT */
-       ctx->vq_src.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
-       ctx->vq_src.drv_priv = ctx;
-       ctx->vq_src.buf_struct_size = sizeof(struct s5p_mfc_buf);
-       ctx->vq_src.io_modes = VB2_USERPTR | VB2_DMABUF;
-       ctx->vq_src.ops = &s5p_mfc_enc_qops;
-       ctx->vq_src.mem_ops = s5p_mfc_mem_ops();
-       ctx->vq_src.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
-       ret = vb2_queue_init(&ctx->vq_src);
-       if (ret) {
-               mfc_err_dev("Failed to initialize videobuf2 queue(output)\n");
-               goto fail_enc_init;
-       }
-
-       /* Init videobuf2 queue for CAPTURE */
-       ctx->vq_dst.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
-       ctx->vq_dst.drv_priv = ctx;
-       ctx->vq_dst.buf_struct_size = sizeof(struct s5p_mfc_buf);
-       ctx->vq_dst.io_modes = VB2_USERPTR | VB2_DMABUF;
-       ctx->vq_dst.ops = &s5p_mfc_enc_qops;
-       ctx->vq_dst.mem_ops = s5p_mfc_mem_ops();
-       ctx->vq_dst.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
-       ret = vb2_queue_init(&ctx->vq_dst);
-       if (ret) {
-               mfc_err_dev("Failed to initialize videobuf2 queue(capture)\n");
-               goto fail_enc_init;
-       }
-
-       return 0;
-
-fail_enc_init:
-       mfc_deinit_enc_ctx(ctx);
-       return 0;
-}
-
-static int mfc_init_instance(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx)
-{
-       int ret = 0;
-
-       dev->watchdog_timer.expires = jiffies +
-               msecs_to_jiffies(WATCHDOG_TICK_INTERVAL);
-       add_timer(&dev->watchdog_timer);
-
-       /* Load the FW */
-       if (!dev->fw.status) {
-               ret = s5p_mfc_alloc_firmware(dev);
-               if (ret)
-                       goto err_fw_alloc;
-               dev->fw.status = 1;
-       }
-
-       ret = s5p_mfc_load_firmware(dev);
-       if (ret)
-               goto err_fw_load;
-
-#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
-       trace_mfc_dcpp_start(ctx->num, 1, dev->fw.drm_status);
-       if (!dev->drm_fw_buf.daddr) {
-               mfc_err_ctx("DRM F/W buffer is not allocated\n");
-               dev->fw.drm_status = 0;
-       } else {
-               /* Request buffer protection for DRM F/W */
-               ret = exynos_smc(SMC_DRM_PPMP_MFCFW_PROT,
-                               dev->drm_fw_buf.daddr, 0, 0);
-               if (ret != DRMDRV_OK) {
-                       mfc_err_ctx("failed MFC DRM F/W prot(%#x)\n", ret);
-                       call_dop(dev, dump_and_stop_debug_mode, dev);
-                       dev->fw.drm_status = 0;
-               } else {
-                       dev->fw.drm_status = 1;
-               }
-       }
-#endif
-       trace_mfc_dcpp_end(ctx->num, 1, dev->fw.drm_status);
-
-       ret = s5p_mfc_alloc_common_context(dev);
-       if (ret)
-               goto err_context_alloc;
-
-       if (dbg_enable)
-               s5p_mfc_alloc_dbg_info_buffer(dev);
-
-       MFC_TRACE_DEV_HWLOCK("**open\n");
-       ret = s5p_mfc_get_hwlock_dev(dev);
-       if (ret < 0) {
-               mfc_err_dev("Failed to get hwlock\n");
-               mfc_err_dev("dev.hwlock.dev = 0x%lx, bits = 0x%lx, owned_by_irq = %d, wl_count = %d, transfer_owner = %d\n",
-                               dev->hwlock.dev, dev->hwlock.bits, dev->hwlock.owned_by_irq,
-                               dev->hwlock.wl_count, dev->hwlock.transfer_owner);
-               goto err_hw_lock;
-       }
-
-       mfc_debug(2, "power on\n");
-       ret = s5p_mfc_pm_power_on(dev);
-       if (ret < 0) {
-               mfc_err_ctx("power on failed\n");
-               goto err_pwr_enable;
-       }
-
-       dev->curr_ctx = ctx->num;
-       dev->preempt_ctx = MFC_NO_INSTANCE_SET;
-       dev->curr_ctx_is_drm = ctx->is_drm;
-
-       ret = s5p_mfc_init_hw(dev);
-       if (ret) {
-               mfc_err_ctx("Failed to init mfc h/w\n");
-               goto err_hw_init;
-       }
-
-       if (dev->has_mmcache && (dev->mmcache.is_on_status == 0))
-               s5p_mfc_mmcache_enable(dev);
-
-
-       s5p_mfc_release_hwlock_dev(dev);
-
-       if (MFC_FEATURE_SUPPORT(dev, dev->pdata->nal_q)) {
-               dev->nal_q_handle = s5p_mfc_nal_q_create(dev);
-               if (dev->nal_q_handle == NULL)
-                       mfc_err_dev("[NALQ] Can't create nal q\n");
-       }
-
-       return ret;
-
-err_hw_init:
-       s5p_mfc_pm_power_off(dev);
-
-err_pwr_enable:
-       s5p_mfc_release_hwlock_dev(dev);
-
-err_hw_lock:
-       s5p_mfc_release_common_context(dev);
-
-err_context_alloc:
-#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
-       if (dev->fw.drm_status) {
-               int smc_ret = 0;
-               dev->fw.drm_status = 0;
-               /* Request buffer unprotection for DRM F/W */
-               smc_ret = exynos_smc(SMC_DRM_PPMP_MFCFW_UNPROT,
-                                       dev->drm_fw_buf.daddr, 0, 0);
-               if (smc_ret != DRMDRV_OK) {
-                       mfc_err_ctx("failed MFC DRM F/W unprot(%#x)\n", smc_ret);
-                       call_dop(dev, dump_and_stop_debug_mode, dev);
-               }
-       }
-#endif
-
-err_fw_load:
-err_fw_alloc:
-       del_timer_sync(&dev->watchdog_timer);
-
-       mfc_err_dev("failed to init first instance\n");
-       return ret;
-}
-
-/* Open an MFC node */
-static int s5p_mfc_open(struct file *file)
-{
-       struct s5p_mfc_ctx *ctx = NULL;
-       struct s5p_mfc_dev *dev = video_drvdata(file);
-       int ret = 0;
-       enum s5p_mfc_node_type node;
-       struct video_device *vdev = NULL;
-
-       mfc_debug(2, "mfc driver open called\n");
-
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               goto err_no_device;
-       }
-
-       if (mutex_lock_interruptible(&dev->mfc_mutex))
-               return -ERESTARTSYS;
-
-       node = s5p_mfc_get_node_type(file);
-       if (node == MFCNODE_INVALID) {
-               mfc_err_dev("cannot specify node type\n");
-               ret = -ENOENT;
-               goto err_node_type;
-       }
-
-       dev->num_inst++;        /* It is guarded by mfc_mutex in vfd */
-
-       /* Allocate memory for context */
-       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
-       if (!ctx) {
-               mfc_err_dev("Not enough memory\n");
-               ret = -ENOMEM;
-               goto err_ctx_alloc;
-       }
-
-       switch (node) {
-       case MFCNODE_DECODER:
-               vdev = dev->vfd_dec;
-               break;
-       case MFCNODE_ENCODER:
-               vdev = dev->vfd_enc;
-               break;
-       case MFCNODE_DECODER_DRM:
-               vdev = dev->vfd_dec_drm;
-               break;
-       case MFCNODE_ENCODER_DRM:
-               vdev = dev->vfd_enc_drm;
-               break;
-       case MFCNODE_ENCODER_OTF:
-               vdev = dev->vfd_enc_otf;
-               break;
-       case MFCNODE_ENCODER_OTF_DRM:
-               vdev = dev->vfd_enc_otf_drm;
-               break;
-       default:
-               mfc_err_dev("Invalid node(%d)\n", node);
-               break;
-       }
-
-       if (!vdev)
-               goto err_vdev;
-
-       v4l2_fh_init(&ctx->fh, vdev);
-       file->private_data = &ctx->fh;
-       v4l2_fh_add(&ctx->fh);
-
-       ctx->dev = dev;
-
-       /* Get context number */
-       ctx->num = 0;
-       while (dev->ctx[ctx->num]) {
-               ctx->num++;
-               if (ctx->num >= MFC_NUM_CONTEXTS) {
-                       mfc_err_dev("Too many open contexts\n");
-                       ret = -EBUSY;
-                       goto err_ctx_num;
-               }
-       }
-
-       init_waitqueue_head(&ctx->cmd_wq);
-       s5p_mfc_init_listable_wq_ctx(ctx);
-       spin_lock_init(&ctx->buf_queue_lock);
-
-       if (s5p_mfc_is_decoder_node(node))
-               ret = mfc_init_dec_ctx(ctx);
-       else
-               ret = mfc_init_enc_ctx(ctx);
-       if (ret)
-               goto err_ctx_init;
-
-       ret = call_cop(ctx, init_ctx_ctrls, ctx);
-       if (ret) {
-               mfc_err_ctx("failed in init_ctx_ctrls\n");
-               goto err_ctx_ctrls;
-       }
-
-#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
-       if (s5p_mfc_is_drm_node(node)) {
-               if (dev->num_drm_inst < MFC_MAX_DRM_CTX) {
-                       if (ctx->raw_protect_flag || ctx->stream_protect_flag) {
-                               mfc_err_ctx("protect_flag(%#lx/%#lx) remained\n",
-                                               ctx->raw_protect_flag,
-                                               ctx->stream_protect_flag);
-                               ret = -EINVAL;
-                               goto err_drm_start;
-                       }
-                       dev->num_drm_inst++;
-                       ctx->is_drm = 1;
-
-                       mfc_info_ctx("DRM instance is opened [%d:%d]\n",
-                                       dev->num_drm_inst, dev->num_inst);
-               } else {
-                       mfc_err_ctx("Too many instance are opened for DRM\n");
-                       ret = -EINVAL;
-                       goto err_drm_start;
-               }
-       } else {
-               mfc_info_ctx("NORMAL instance is opened [%d:%d]\n",
-                               dev->num_drm_inst, dev->num_inst);
-       }
-#endif
-
-       /* Mark context as idle */
-       s5p_mfc_clear_bit(ctx->num, &dev->work_bits);
-       dev->ctx[ctx->num] = ctx;
-
-       /* Load firmware if this is the first instance */
-       if (dev->num_inst == 1) {
-               ret = mfc_init_instance(dev, ctx);
-               if (ret)
-                       goto err_init_inst;
-
-               if (perf_boost_mode)
-                       s5p_mfc_perf_boost_enable(dev);
-       }
-
-#ifdef CONFIG_VIDEO_EXYNOS_REPEATER
-       if (s5p_mfc_is_encoder_otf_node(node)) {
-               ret = s5p_mfc_otf_create(ctx);
-               if (ret)
-                       mfc_err_ctx("[OTF] otf_create failed\n");
-       }
-#endif
-
-       s5p_mfc_perf_init(dev);
-       trace_mfc_node_open(ctx->num, dev->num_inst, ctx->type, ctx->is_drm);
-       mfc_info_ctx("MFC open completed [%d:%d] dev = 0x%p, ctx = 0x%p, version = %d\n",
-                       dev->num_drm_inst, dev->num_inst, dev, ctx, MFC_DRIVER_INFO);
-       mutex_unlock(&dev->mfc_mutex);
-       return ret;
-
-       /* Deinit when failure occured */
-err_init_inst:
-#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
-       if (ctx->is_drm)
-               dev->num_drm_inst--;
-
-err_drm_start:
-#endif
-       call_cop(ctx, cleanup_ctx_ctrls, ctx);
-
-err_ctx_ctrls:
-err_ctx_init:
-       dev->ctx[ctx->num] = 0;
-
-err_ctx_num:
-       v4l2_fh_del(&ctx->fh);
-       v4l2_fh_exit(&ctx->fh);
-
-err_vdev:
-       kfree(ctx);
-
-err_ctx_alloc:
-       dev->num_inst--;
-
-err_node_type:
-       mfc_info_dev("MFC driver open is failed [%d:%d]\n",
-                       dev->num_drm_inst, dev->num_inst);
-       mutex_unlock(&dev->mfc_mutex);
-
-err_no_device:
-
-       return ret;
-}
-
-static int mfc_wait_close_inst(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx)
-{
-       if (atomic_read(&dev->watchdog_run)) {
-               mfc_err_ctx("watchdog already running!\n");
-               return 0;
-       }
-
-       if (ctx->inst_no == MFC_NO_INSTANCE_SET) {
-               mfc_debug(2, "mfc no instance already\n");
-               return 0;
-       }
-
-       s5p_mfc_clean_ctx_int_flags(ctx);
-       s5p_mfc_change_state(ctx, MFCINST_RETURN_INST);
-       s5p_mfc_set_bit(ctx->num, &dev->work_bits);
-
-       /* To issue the command 'CLOSE_INSTANCE' */
-       if (s5p_mfc_just_run(dev, ctx->num)) {
-               mfc_err_ctx("Failed to run MFC\n");
-               return -EIO;
-       }
-
-       /* Wait until instance is returned or timeout occured */
-       if (s5p_mfc_wait_for_done_ctx(ctx,
-                               S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET) == 1) {
-               mfc_err_ctx("Waiting for CLOSE_INSTANCE timed out\n");
-               if (s5p_mfc_wait_for_done_ctx(ctx,
-                                       S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET)) {
-                       mfc_err_ctx("waiting once more but timed out\n");
-                       dev->logging_data->cause |= (1 << MFC_CAUSE_FAIL_CLOSE_INST);
-                       call_dop(dev, dump_and_stop_always, dev);
-               }
-       }
-
-       ctx->inst_no = MFC_NO_INSTANCE_SET;
-
-       return 0;
-}
-
-/* Release MFC context */
-static int s5p_mfc_release(struct file *file)
-{
-       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
-       struct s5p_mfc_dev *dev = NULL;
-       int ret = 0;
-
-       dev = ctx->dev;
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return -EINVAL;
-       }
-
-       mutex_lock(&dev->mfc_mutex);
-
-       mfc_info_ctx("MFC driver release is called [%d:%d], is_drm(%d)\n",
-                       dev->num_drm_inst, dev->num_inst, ctx->is_drm);
-
-       s5p_mfc_clear_bit(ctx->num, &dev->work_bits);
-
-       /* If a H/W operation is in progress, wait for it complete */
-       if (need_to_wait_nal_abort(ctx)) {
-               if (s5p_mfc_wait_for_done_ctx(ctx, S5P_FIMV_R2H_CMD_NAL_ABORT_RET)) {
-                       mfc_err_ctx("Failed to wait nal abort\n");
-                       s5p_mfc_cleanup_work_bit_and_try_run(ctx);
-               }
-       }
-       MFC_TRACE_CTX_HWLOCK("**release\n");
-       ret = s5p_mfc_get_hwlock_ctx(ctx);
-       if (ret < 0) {
-               mfc_err_dev("Failed to get hwlock\n");
-               mutex_unlock(&dev->mfc_mutex);
-               return -EBUSY;
-       }
-
-       if (call_cop(ctx, cleanup_ctx_ctrls, ctx) < 0)
-               mfc_err_ctx("failed in cleanup_ctx_ctrl\n");
-
-       v4l2_fh_del(&ctx->fh);
-       v4l2_fh_exit(&ctx->fh);
-
-       /* Mark context as idle */
-       s5p_mfc_clear_bit(ctx->num, &dev->work_bits);
-
-       /* If instance was initialised then
-        * return instance and free reosurces */
-       ret = mfc_wait_close_inst(dev, ctx);
-       if (ret)
-               goto err_release_try;
-
-       if (ctx->is_drm)
-               dev->num_drm_inst--;
-       dev->num_inst--;
-
-       if (dev->num_inst == 0) {
-               s5p_mfc_deinit_hw(dev);
-
-               if (perf_boost_mode)
-                       s5p_mfc_perf_boost_disable(dev);
-
-               del_timer_sync(&dev->watchdog_timer);
-
-               flush_workqueue(dev->butler_wq);
-
-               mfc_debug(2, "power off\n");
-               s5p_mfc_pm_power_off(dev);
-
-               if (dbg_enable)
-                       s5p_mfc_release_dbg_info_buffer(dev);
-
-               s5p_mfc_release_common_context(dev);
-
-#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
-               if (dev->fw.drm_status) {
-                       dev->fw.drm_status = 0;
-                       /* Request buffer unprotection for DRM F/W */
-                       ret = exynos_smc(SMC_DRM_PPMP_MFCFW_UNPROT,
-                                       dev->drm_fw_buf.daddr, 0, 0);
-                       if (ret != DRMDRV_OK) {
-                               mfc_err_ctx("failed MFC DRM F/W unprot(%#x)\n", ret);
-                               call_dop(dev, dump_and_stop_debug_mode, dev);
-                               goto err_release;
-                       }
-               }
-#endif
-
-               if (dev->nal_q_handle) {
-                       ret = s5p_mfc_nal_q_destroy(dev, dev->nal_q_handle);
-                       if (ret) {
-                               mfc_err_ctx("failed nal_q destroy\n");
-                               goto err_release;
-                       }
-               }
-       }
-
-       s5p_mfc_qos_off(ctx);
-
-       if (dev->has_mmcache && dev->mmcache.is_on_status) {
-               s5p_mfc_invalidate_mmcache(dev);
-
-               if (dev->num_inst == 0)
-                       s5p_mfc_mmcache_disable(dev);
-       }
-
-       s5p_mfc_release_codec_buffers(ctx);
-       s5p_mfc_release_instance_context(ctx);
-
-       s5p_mfc_release_hwlock_ctx(ctx);
-
-       /* Free resources */
-       vb2_queue_release(&ctx->vq_src);
-       vb2_queue_release(&ctx->vq_dst);
-
-       if (ctx->type == MFCINST_DECODER)
-               mfc_deinit_dec_ctx(ctx);
-       else if (ctx->type == MFCINST_ENCODER)
-               mfc_deinit_enc_ctx(ctx);
-
-#ifdef CONFIG_VIDEO_EXYNOS_REPEATER
-       if (ctx->otf_handle) {
-               s5p_mfc_otf_deinit(ctx);
-               s5p_mfc_otf_destroy(ctx);
-       }
-#endif
-
-       s5p_mfc_destroy_listable_wq_ctx(ctx);
-
-       trace_mfc_node_close(ctx->num, dev->num_inst, ctx->type, ctx->is_drm);
-
-       dev->ctx[ctx->num] = 0;
-       kfree(ctx);
-
-       s5p_mfc_perf_print();
-
-       mfc_info_dev("mfc driver release finished [%d:%d], dev = 0x%p\n",
-                       dev->num_drm_inst, dev->num_inst, dev);
-
-       if (s5p_mfc_is_work_to_do(dev))
-               queue_work(dev->butler_wq, &dev->butler_work);
-
-       mutex_unlock(&dev->mfc_mutex);
-       return ret;
-
-err_release:
-       s5p_mfc_release_hwlock_ctx(ctx);
-       mutex_unlock(&dev->mfc_mutex);
-       return ret;
-
-err_release_try:
-       s5p_mfc_release_hwlock_ctx(ctx);
-       s5p_mfc_cleanup_work_bit_and_try_run(ctx);
-       mutex_unlock(&dev->mfc_mutex);
-       return ret;
-}
-
-/* Poll */
-static unsigned int s5p_mfc_poll(struct file *file,
-                                struct poll_table_struct *wait)
-{
-       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
-       unsigned long req_events = poll_requested_events(wait);
-       unsigned int ret = 0;
-
-       mfc_debug_enter();
-
-       if (req_events & (POLLOUT | POLLWRNORM)) {
-               mfc_debug(2, "wait source buffer\n");
-               ret = vb2_poll(&ctx->vq_src, file, wait);
-       } else if (req_events & (POLLIN | POLLRDNORM)) {
-               mfc_debug(2, "wait destination buffer\n");
-               ret = vb2_poll(&ctx->vq_dst, file, wait);
-       }
-
-       mfc_debug_leave();
-       return ret;
-}
-
-/* Mmap */
-static int s5p_mfc_mmap(struct file *file, struct vm_area_struct *vma)
-{
-       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
-       unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
-       int ret;
-
-       mfc_debug_enter();
-
-       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);
-       }
-       mfc_debug_leave();
-       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,
-};
-
-#ifdef CONFIG_MFC_USE_BUS_DEVFREQ
-static int mfc_parse_mfc_qos_platdata(struct device_node *np, char *node_name,
-       struct s5p_mfc_qos *qosdata)
-{
-       int ret = 0;
-       struct device_node *np_qos;
-
-       np_qos = of_find_node_by_name(np, node_name);
-       if (!np_qos) {
-               pr_err("%s: could not find mfc_qos_platdata node\n",
-                       node_name);
-               return -EINVAL;
-       }
-
-       of_property_read_u32(np_qos, "thrd_mb", &qosdata->threshold_mb);
-       of_property_read_u32(np_qos, "freq_mfc", &qosdata->freq_mfc);
-       of_property_read_u32(np_qos, "freq_int", &qosdata->freq_int);
-       of_property_read_u32(np_qos, "freq_mif", &qosdata->freq_mif);
-       of_property_read_u32(np_qos, "mo_value", &qosdata->mo_value);
-       of_property_read_u32(np_qos, "mo_10bit_value", &qosdata->mo_10bit_value);
-       of_property_read_u32(np_qos, "mo_uhd_enc60_value", &qosdata->mo_uhd_enc60_value);
-       of_property_read_u32(np_qos, "time_fw", &qosdata->time_fw);
-
-       return ret;
-}
-#endif
-
-int s5p_mfc_sysmmu_fault_handler(struct iommu_domain *iodmn, struct device *device,
-               unsigned long addr, int id, void *param)
-{
-       struct s5p_mfc_dev *dev;
-
-       dev = (struct s5p_mfc_dev *)param;
-
-       /* [OTF] If AxID is 1 in SYSMMU1 fault info, it is TS-MUX fault */
-       if (dev->has_hwfc && dev->has_2sysmmu) {
-               if (MFC_MMU1_READL(MFC_MMU_INTERRUPT_STATUS) &&
-                               ((MFC_MMU1_READL(MFC_MMU_FAULT_TRANS_INFO) &
-                                 MFC_MMU_FAULT_TRANS_INFO_AXID_MASK) == 1)) {
-                       mfc_err_dev("There is TS-MUX page fault. skip SFR dump\n");
-                       return 0;
-               }
-       }
-
-       /* If sysmmu is used with other IPs, it should be checked whether it's an MFC fault */
-       if (dev->pdata->share_sysmmu) {
-               if ((MFC_MMU0_READL(MFC_MMU_FAULT_TRANS_INFO) & dev->pdata->axid_mask)
-                               != dev->pdata->mfc_fault_num) {
-                       mfc_err_dev("This is not a MFC page fault\n");
-                       return 0;
-               }
-       }
-
-       if (MFC_MMU0_READL(MFC_MMU_INTERRUPT_STATUS)) {
-               if (MFC_MMU0_READL(MFC_MMU_FAULT_TRANS_INFO) & MFC_MMU_FAULT_TRANS_INFO_RW_MASK)
-                       dev->logging_data->cause |= (1 << MFC_CAUSE_0WRITE_PAGE_FAULT);
-               else
-                       dev->logging_data->cause |= (1 << MFC_CAUSE_0READ_PAGE_FAULT);
-               dev->logging_data->fault_status = MFC_MMU0_READL(MFC_MMU_INTERRUPT_STATUS);
-               dev->logging_data->fault_trans_info = MFC_MMU0_READL(MFC_MMU_FAULT_TRANS_INFO);
-       }
-
-       if (dev->has_2sysmmu) {
-               if (MFC_MMU1_READL(MFC_MMU_INTERRUPT_STATUS)) {
-                       if (MFC_MMU1_READL(MFC_MMU_FAULT_TRANS_INFO) & MFC_MMU_FAULT_TRANS_INFO_RW_MASK)
-                               dev->logging_data->cause |= (1 << MFC_CAUSE_1WRITE_PAGE_FAULT);
-                       else
-                               dev->logging_data->cause |= (1 << MFC_CAUSE_1READ_PAGE_FAULT);
-                       dev->logging_data->fault_status = MFC_MMU1_READL(MFC_MMU_INTERRUPT_STATUS);
-                       dev->logging_data->fault_trans_info = MFC_MMU1_READL(MFC_MMU_FAULT_TRANS_INFO);
-               }
-       }
-       dev->logging_data->fault_addr = (unsigned int)addr;
-
-       call_dop(dev, dump_info, dev);
-
-       return 0;
-}
-
-static void mfc_parse_dt(struct device_node *np, struct s5p_mfc_dev *mfc)
-{
-       struct s5p_mfc_platdata *pdata = mfc->pdata;
-#ifdef CONFIG_MFC_USE_BUS_DEVFREQ
-       struct device_node *np_qos;
-       char node_name[50];
-       int i;
-#endif
-
-       if (!np)
-               return;
-
-       /* MFC version */
-       of_property_read_u32(np, "ip_ver", &pdata->ip_ver);
-
-       /* Debug mode */
-       of_property_read_u32(np, "debug_mode", &pdata->debug_mode);
-
-       /* Sysmmu check */
-       of_property_read_u32(np, "share_sysmmu", &pdata->share_sysmmu);
-       of_property_read_u32(np, "axid_mask", &pdata->axid_mask);
-       of_property_read_u32(np, "mfc_fault_num", &pdata->mfc_fault_num);
-
-       /* Features */
-       of_property_read_u32_array(np, "nal_q", &pdata->nal_q.support, 2);
-       of_property_read_u32_array(np, "skype", &pdata->skype.support, 2);
-       of_property_read_u32_array(np, "black_bar", &pdata->black_bar.support, 2);
-       of_property_read_u32_array(np, "color_aspect_dec", &pdata->color_aspect_dec.support, 2);
-       of_property_read_u32_array(np, "static_info_dec", &pdata->static_info_dec.support, 2);
-       of_property_read_u32_array(np, "color_aspect_enc", &pdata->color_aspect_enc.support, 2);
-       of_property_read_u32_array(np, "static_info_enc", &pdata->static_info_enc.support, 2);
-
-       /* Default 10bit format for decoding */
-       of_property_read_u32(np, "P010_decoding", &pdata->P010_decoding);
-
-       /* Formats */
-       of_property_read_u32(np, "support_10bit", &pdata->support_10bit);
-       of_property_read_u32(np, "support_422", &pdata->support_422);
-       of_property_read_u32(np, "support_rgb", &pdata->support_rgb);
-
-       /* Encoder default parameter */
-       of_property_read_u32(np, "enc_param_num", &pdata->enc_param_num);
-       if (pdata->enc_param_num) {
-               of_property_read_u32_array(np, "enc_param_addr",
-                               pdata->enc_param_addr, pdata->enc_param_num);
-               of_property_read_u32_array(np, "enc_param_val",
-                               pdata->enc_param_val, pdata->enc_param_num);
-       }
-
-#ifdef CONFIG_MFC_USE_BUS_DEVFREQ
-       /* QoS */
-       of_property_read_u32(np, "num_qos_steps", &pdata->num_qos_steps);
-       of_property_read_u32(np, "max_qos_steps", &pdata->max_qos_steps);
-       of_property_read_u32(np, "max_mb", &pdata->max_mb);
-       of_property_read_u32(np, "mfc_freq_control", &pdata->mfc_freq_control);
-       of_property_read_u32(np, "mo_control", &pdata->mo_control);
-       of_property_read_u32(np, "bw_control", &pdata->bw_control);
-
-       pdata->qos_table = devm_kzalloc(mfc->device,
-                       sizeof(struct s5p_mfc_qos) * pdata->max_qos_steps, GFP_KERNEL);
-
-       for (i = 0; i < pdata->max_qos_steps; i++) {
-               snprintf(node_name, sizeof(node_name), "mfc_qos_variant_%d", i);
-               mfc_parse_mfc_qos_platdata(np, node_name, &pdata->qos_table[i]);
-       }
-
-       /* performance boost mode */
-       pdata->qos_boost_table = devm_kzalloc(mfc->device,
-                       sizeof(struct s5p_mfc_qos_boost), GFP_KERNEL);
-       np_qos = of_find_node_by_name(np, "mfc_perf_boost_table");
-       if (!np_qos) {
-               pr_err("%s:[QoS] could not find mfc_perf_boost_table node\n", node_name);
-               return;
-       }
-       of_property_read_u32(np_qos, "num_cluster", &pdata->qos_boost_table->num_cluster);
-       of_property_read_u32(np_qos, "freq_mfc", &pdata->qos_boost_table->freq_mfc);
-       of_property_read_u32(np_qos, "freq_int", &pdata->qos_boost_table->freq_int);
-       of_property_read_u32(np_qos, "freq_mif", &pdata->qos_boost_table->freq_mif);
-       of_property_read_u32_array(np_qos, "freq_cluster", &pdata->qos_boost_table->freq_cluster[0],
-                       pdata->qos_boost_table->num_cluster);
-#endif
-}
-
-static void *mfc_get_drv_data(struct platform_device *pdev);
-
-static struct video_device *mfc_video_device_register(struct s5p_mfc_dev *dev,
-                               char *name, int node_num)
-{
-       struct video_device *vfd;
-       int ret = 0;
-
-       vfd = video_device_alloc();
-       if (!vfd) {
-               v4l2_err(&dev->v4l2_dev, "Failed to allocate video device\n");
-               return NULL;
-       }
-       strncpy(vfd->name, name, sizeof(vfd->name) - 1);
-       vfd->fops = &s5p_mfc_fops;
-       vfd->minor = -1;
-       vfd->release = video_device_release;
-
-       if (IS_DEC_NODE(node_num))
-               vfd->ioctl_ops = s5p_mfc_get_dec_v4l2_ioctl_ops();
-       else if(IS_ENC_NODE(node_num))
-               vfd->ioctl_ops = s5p_mfc_get_enc_v4l2_ioctl_ops();
-
-       vfd->lock = &dev->mfc_mutex;
-       vfd->v4l2_dev = &dev->v4l2_dev;
-       vfd->vfl_dir = VFL_DIR_M2M;
-
-       snprintf(vfd->name, sizeof(vfd->name), "%s%d", vfd->name, dev->id);
-
-       ret = video_register_device(vfd, VFL_TYPE_GRABBER, node_num + 60 * dev->id);
-       if (ret) {
-               v4l2_err(&dev->v4l2_dev, "Failed to register video device /dev/video%d\n", node_num);
-               video_device_release(vfd);
-               return NULL;
-       }
-       v4l2_info(&dev->v4l2_dev, "video device registered as /dev/video%d\n",
-                                                               vfd->num);
-       video_set_drvdata(vfd, dev);
-
-       return vfd;
-}
-
-static int mfc_register_resource(struct platform_device *pdev, struct s5p_mfc_dev *dev)
-{
-       struct device_node *np = dev->device->of_node;
-       struct device_node *iommu;
-       struct device_node *hwfc;
-       struct device_node *mmcache;
-       struct resource *res;
-       int ret;
-
-       s5p_mfc_perf_register(dev);
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (res == NULL) {
-               dev_err(&pdev->dev, "failed to get memory region resource\n");
-               return -ENOENT;
-       }
-       dev->mfc_mem = request_mem_region(res->start, resource_size(res), pdev->name);
-       if (dev->mfc_mem == NULL) {
-               dev_err(&pdev->dev, "failed to get memory region\n");
-               return -ENOENT;
-       }
-       dev->regs_base = ioremap(dev->mfc_mem->start, resource_size(dev->mfc_mem));
-       if (dev->regs_base == NULL) {
-               dev_err(&pdev->dev, "failed to ioremap address region\n");
-               goto err_ioremap;
-       }
-
-       iommu = of_get_child_by_name(np, "iommu");
-       if (!iommu) {
-               dev_err(&pdev->dev, "failed to get iommu node\n");
-               goto err_ioremap_mmu0;
-       }
-
-       dev->sysmmu0_base = of_iomap(iommu, 0);
-       if (dev->sysmmu0_base == NULL) {
-               dev_err(&pdev->dev, "failed to ioremap sysmmu0 address region\n");
-               goto err_ioremap_mmu0;
-       }
-
-       dev->sysmmu1_base = of_iomap(iommu, 1);
-       if (dev->sysmmu1_base == NULL) {
-               pr_debug("there is only one MFC sysmmu\n");
-       } else {
-               dev->has_2sysmmu = 1;
-       }
-
-       hwfc = of_get_child_by_name(np, "hwfc");
-       if (hwfc) {
-               dev->hwfc_base = of_iomap(hwfc, 0);
-               if (dev->hwfc_base == NULL) {
-                       dev->has_hwfc = 0;
-                       dev_err(&pdev->dev, "failed to iomap hwfc address region\n");
-                       goto err_ioremap_hwfc;
-               } else {
-                       dev->has_hwfc = 1;
-               }
-       }
-
-       mmcache = of_get_child_by_name(np, "mmcache");
-       if (mmcache) {
-               dev->mmcache.base = of_iomap(mmcache, 0);
-               if (dev->mmcache.base == NULL) {
-                       dev->has_mmcache = 0;
-                       dev_err(&pdev->dev, "failed to iomap mmcache address region\n");
-                       goto err_ioremap_mmcache;
-               } else {
-                       dev->has_mmcache = 1;
-               }
-       }
-
-       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-       if (res == NULL) {
-               dev_err(&pdev->dev, "failed to get irq resource\n");
-               goto err_res_irq;
-       }
-       dev->irq = res->start;
-       ret = request_threaded_irq(dev->irq, s5p_mfc_top_half_irq, s5p_mfc_irq,
-                               IRQF_ONESHOT, pdev->name, dev);
-       if (ret != 0) {
-               dev_err(&pdev->dev, "failed to install irq (%d)\n", ret);
-               goto err_res_irq;
-       }
-
-       return 0;
-
-err_res_irq:
-       if (dev->has_mmcache)
-               iounmap(dev->mmcache.base);
-err_ioremap_mmcache:
-       if (dev->has_hwfc)
-               iounmap(dev->hwfc_base);
-err_ioremap_hwfc:
-       if (dev->has_2sysmmu)
-               iounmap(dev->sysmmu1_base);
-       iounmap(dev->sysmmu0_base);
-err_ioremap_mmu0:
-       iounmap(dev->regs_base);
-err_ioremap:
-       release_mem_region(dev->mfc_mem->start, resource_size(dev->mfc_mem));
-       return -ENOENT;
-}
-
-#ifdef CONFIG_EXYNOS_ITMON
-static int mfc_itmon_notifier(struct notifier_block *nb, unsigned long action, void *nb_data)
-{
-       struct s5p_mfc_dev *dev;
-       struct itmon_notifier *itmon_info = nb_data;
-       int is_mfc_itmon = 0, is_master = 0;
-
-       dev = container_of(nb, struct s5p_mfc_dev, itmon_nb);
-
-       if (IS_ERR_OR_NULL(itmon_info))
-               return NOTIFY_DONE;
-
-       if (!itmon_info->master)
-               return NOTIFY_DONE;
-
-       /* print dump if it is an MFC ITMON error */
-       if ((strncmp("MFC", itmon_info->port, sizeof("MFC") - 1) == 0) &&
-                       (strncmp("MFC", itmon_info->master, sizeof("MFC") - 1) == 0)) {
-               is_mfc_itmon = 1;
-               is_master = 1;
-       } else if (strncmp("MFC", itmon_info->dest, sizeof("MFC") - 1) == 0) {
-               is_mfc_itmon = 1;
-               is_master = 0;
-       }
-
-       if (is_mfc_itmon) {
-               pr_err("mfc_itmon_notifier: MFC +\n");
-               pr_err("MFC is %s\n", is_master ? "master" : "dest");
-               if (!dev->itmon_notified) {
-                       pr_err("dump MFC information\n");
-                       if (is_master || (!is_master && itmon_info->onoff))
-                               call_dop(dev, dump_info, dev);
-                       else
-                               call_dop(dev, dump_info_without_regs, dev);
-               } else {
-                       pr_err("MFC notifier has already been called. skip MFC information\n");
-               }
-               pr_err("mfc_itmon_notifier: MFC -\n");
-               dev->itmon_notified = 1;
-       }
-       return NOTIFY_DONE;
-}
-#endif
-
-/* MFC probe function */
-static int s5p_mfc_probe(struct platform_device *pdev)
-{
-       struct s5p_mfc_dev *dev;
-       int ret = -ENOENT;
-#ifdef CONFIG_MFC_USE_BUS_DEVFREQ
-       int i;
-#endif
-
-       dev_dbg(&pdev->dev, "%s()\n", __func__);
-       dev = devm_kzalloc(&pdev->dev, sizeof(struct s5p_mfc_dev), GFP_KERNEL);
-       if (!dev) {
-               dev_err(&pdev->dev, "Not enough memory for MFC device\n");
-               return -ENOMEM;
-       }
-
-       dev->device = &pdev->dev;
-       dev->pdata = pdev->dev.platform_data;
-
-       dev->variant = mfc_get_drv_data(pdev);
-
-       if (dev->device->of_node)
-               dev->id = of_alias_get_id(pdev->dev.of_node, "mfc");
-
-       dev_dbg(&pdev->dev, "of alias get id : mfc-%d \n", dev->id);
-
-       if (dev->id < 0 || dev->id >= dev->variant->num_entities) {
-               dev_err(&pdev->dev, "Invalid platform device id: %d\n", dev->id);
-               ret = -EINVAL;
-               goto err_pm;
-       }
-
-       dev->pdata = devm_kzalloc(&pdev->dev, sizeof(struct s5p_mfc_platdata), GFP_KERNEL);
-       if (!dev->pdata) {
-               dev_err(&pdev->dev, "no memory for state\n");
-               ret = -ENOMEM;
-               goto err_pm;
-       }
-
-       mfc_parse_dt(dev->device->of_node, dev);
-
-       atomic_set(&dev->trace_ref, 0);
-       atomic_set(&dev->trace_ref_hwlock, 0);
-       dev->mfc_trace = g_mfc_trace;
-       dev->mfc_trace_hwlock = g_mfc_trace_hwlock;
-
-       dma_set_mask(&pdev->dev, DMA_BIT_MASK(36));
-
-       s5p_mfc_pm_init(dev);
-       ret = mfc_register_resource(pdev, dev);
-       if (ret)
-               goto err_res_mem;
-
-       mutex_init(&dev->mfc_mutex);
-
-       ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
-       if (ret)
-               goto err_v4l2_dev;
-
-       init_waitqueue_head(&dev->cmd_wq);
-       s5p_mfc_init_listable_wq_dev(dev);
-
-       /* decoder */
-       dev->vfd_dec = mfc_video_device_register(dev, S5P_MFC_DEC_NAME,
-                       EXYNOS_VIDEONODE_MFC_DEC);
-       if (!dev->vfd_dec) {
-               ret = -ENOMEM;
-               goto alloc_vdev_dec;
-       }
-
-       /* encoder */
-       dev->vfd_enc = mfc_video_device_register(dev, S5P_MFC_ENC_NAME,
-                       EXYNOS_VIDEONODE_MFC_ENC);
-       if (!dev->vfd_enc) {
-               ret = -ENOMEM;
-               goto alloc_vdev_enc;
-       }
-
-       /* secure decoder */
-       dev->vfd_dec_drm = mfc_video_device_register(dev, S5P_MFC_DEC_DRM_NAME,
-                       EXYNOS_VIDEONODE_MFC_DEC_DRM);
-       if (!dev->vfd_dec_drm) {
-               ret = -ENOMEM;
-               goto alloc_vdev_dec_drm;
-       }
-
-       /* secure encoder */
-       dev->vfd_enc_drm = mfc_video_device_register(dev, S5P_MFC_ENC_DRM_NAME,
-                       EXYNOS_VIDEONODE_MFC_ENC_DRM);
-       if (!dev->vfd_enc_drm) {
-               ret = -ENOMEM;
-               goto alloc_vdev_enc_drm;
-       }
-
-       /* OTF encoder */
-       dev->vfd_enc_otf = mfc_video_device_register(dev, S5P_MFC_ENC_OTF_NAME,
-                       EXYNOS_VIDEONODE_MFC_ENC_OTF);
-       if (!dev->vfd_enc_otf) {
-               ret = -ENOMEM;
-               goto alloc_vdev_enc_otf;
-       }
-
-       /* OTF secure encoder */
-       dev->vfd_enc_otf_drm = mfc_video_device_register(dev, S5P_MFC_ENC_OTF_DRM_NAME,
-                       EXYNOS_VIDEONODE_MFC_ENC_OTF_DRM);
-       if (!dev->vfd_enc_otf_drm) {
-               ret = -ENOMEM;
-               goto alloc_vdev_enc_otf_drm;
-       }
-       /* end of node setting*/
-
-       platform_set_drvdata(pdev, dev);
-
-       s5p_mfc_init_hwlock(dev);
-       s5p_mfc_create_bits(&dev->work_bits);
-
-       dev->watchdog_wq =
-               create_singlethread_workqueue("s5p_mfc/watchdog");
-       if (!dev->watchdog_wq) {
-               dev_err(&pdev->dev, "failed to create workqueue for watchdog\n");
-               goto err_wq_watchdog;
-       }
-       INIT_WORK(&dev->watchdog_work, s5p_mfc_watchdog_worker);
-       atomic_set(&dev->watchdog_tick_running, 0);
-       atomic_set(&dev->watchdog_tick_cnt, 0);
-       atomic_set(&dev->watchdog_run, 0);
-       init_timer(&dev->watchdog_timer);
-       dev->watchdog_timer.data = (unsigned long)dev;
-       dev->watchdog_timer.function = s5p_mfc_watchdog_tick;
-
-#ifdef CONFIG_MFC_USE_BUS_DEVFREQ
-       INIT_LIST_HEAD(&dev->qos_queue);
-#endif
-
-       /* default FW alloc is added */
-       dev->butler_wq = alloc_workqueue("s5p_mfc/butler", WQ_UNBOUND
-                                       | WQ_MEM_RECLAIM | WQ_HIGHPRI, 1);
-       if (dev->butler_wq == NULL) {
-               dev_err(&pdev->dev, "failed to create workqueue for butler\n");
-               goto err_butler_wq;
-       }
-       INIT_WORK(&dev->butler_work, s5p_mfc_butler_worker);
-
-       /* dump information call-back function */
-       dev->dump_ops = &mfc_dump_ops;
-
-#ifdef CONFIG_MFC_USE_BUS_DEVFREQ
-       atomic_set(&dev->qos_req_cur, 0);
-
-       mfc_info_dev("[QoS] control: mfc_freq(%d), mo(%d), bw(%d)\n",
-                       dev->pdata->mfc_freq_control, dev->pdata->mo_control, dev->pdata->bw_control);
-       for (i = 0; i < dev->pdata->num_qos_steps; i++) {
-               mfc_info_dev("[QoS] table[%d] mfc: %d, int : %d, mif : %d\n",
-                               i,
-                               dev->pdata->qos_table[i].freq_mfc,
-                               dev->pdata->qos_table[i].freq_int,
-                               dev->pdata->qos_table[i].freq_mif);
-       }
-#endif
-
-       iovmm_set_fault_handler(dev->device,
-               s5p_mfc_sysmmu_fault_handler, dev);
-
-       g_mfc_dev = dev;
-
-       ret = iovmm_activate(&pdev->dev);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "Failed to activate iommu\n");
-               goto err_iovmm_active;
-       }
-
-       dev->logging_data = devm_kzalloc(&pdev->dev, sizeof(struct s5p_mfc_debug), GFP_KERNEL);
-       if (!dev->logging_data) {
-               dev_err(&pdev->dev, "no memory for logging data\n");
-               ret = -ENOMEM;
-               goto err_alloc_debug;
-       }
-
-#ifdef CONFIG_EXYNOS_ITMON
-       dev->itmon_nb.notifier_call = mfc_itmon_notifier;
-       itmon_notifier_chain_register(&dev->itmon_nb);
-#endif
-
-       s5p_mfc_init_debugfs(dev);
-
-       pr_debug("%s--\n", __func__);
-       return 0;
-
-/* Deinit MFC if probe had failed */
-err_alloc_debug:
-       iovmm_deactivate(&pdev->dev);
-err_iovmm_active:
-       destroy_workqueue(dev->butler_wq);
-err_butler_wq:
-       destroy_workqueue(dev->watchdog_wq);
-err_wq_watchdog:
-       video_unregister_device(dev->vfd_enc_otf_drm);
-alloc_vdev_enc_otf_drm:
-       video_unregister_device(dev->vfd_enc_otf);
-alloc_vdev_enc_otf:
-       video_unregister_device(dev->vfd_enc_drm);
-alloc_vdev_enc_drm:
-       video_unregister_device(dev->vfd_dec_drm);
-alloc_vdev_dec_drm:
-       video_unregister_device(dev->vfd_enc);
-alloc_vdev_enc:
-       video_unregister_device(dev->vfd_dec);
-alloc_vdev_dec:
-       v4l2_device_unregister(&dev->v4l2_dev);
-err_v4l2_dev:
-       mutex_destroy(&dev->mfc_mutex);
-       free_irq(dev->irq, dev);
-       if (dev->has_mmcache)
-               iounmap(dev->mmcache.base);
-       if (dev->has_hwfc)
-               iounmap(dev->hwfc_base);
-       if (dev->has_2sysmmu)
-               iounmap(dev->sysmmu1_base);
-       iounmap(dev->sysmmu0_base);
-       iounmap(dev->regs_base);
-       release_mem_region(dev->mfc_mem->start, resource_size(dev->mfc_mem));
-err_res_mem:
-       s5p_mfc_pm_final(dev);
-err_pm:
-       return ret;
-}
-
-/* Remove the driver */
-static int s5p_mfc_remove(struct platform_device *pdev)
-{
-       struct s5p_mfc_dev *dev = platform_get_drvdata(pdev);
-
-       dev_dbg(&pdev->dev, "%s++\n", __func__);
-       v4l2_info(&dev->v4l2_dev, "Removing %s\n", pdev->name);
-       del_timer_sync(&dev->watchdog_timer);
-       flush_workqueue(dev->watchdog_wq);
-       destroy_workqueue(dev->watchdog_wq);
-       flush_workqueue(dev->butler_wq);
-       destroy_workqueue(dev->butler_wq);
-       video_unregister_device(dev->vfd_enc);
-       video_unregister_device(dev->vfd_dec);
-       video_unregister_device(dev->vfd_enc_otf);
-       video_unregister_device(dev->vfd_enc_otf_drm);
-       v4l2_device_unregister(&dev->v4l2_dev);
-#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
-       remove_proc_entry(MFC_PROC_FW_STATUS, mfc_proc_entry);
-       remove_proc_entry(MFC_PROC_DRM_INSTANCE_NUMBER, mfc_proc_entry);
-       remove_proc_entry(MFC_PROC_INSTANCE_NUMBER, mfc_proc_entry);
-       remove_proc_entry(MFC_PROC_ROOT, NULL);
-#endif
-       s5p_mfc_destroy_listable_wq_dev(dev);
-       iovmm_deactivate(&pdev->dev);
-       mfc_debug(2, "Will now deinit HW\n");
-       s5p_mfc_deinit_hw(dev);
-       free_irq(dev->irq, dev);
-       if (dev->has_mmcache)
-               iounmap(dev->mmcache.base);
-       if (dev->has_hwfc)
-               iounmap(dev->hwfc_base);
-       if (dev->has_2sysmmu)
-               iounmap(dev->sysmmu1_base);
-       iounmap(dev->sysmmu0_base);
-       iounmap(dev->regs_base);
-       release_mem_region(dev->mfc_mem->start, resource_size(dev->mfc_mem));
-       s5p_mfc_pm_final(dev);
-       kfree(dev);
-       dev_dbg(&pdev->dev, "%s--\n", __func__);
-       return 0;
-}
-
-static void s5p_mfc_shutdown(struct platform_device *pdev)
-{
-       struct s5p_mfc_dev *dev = platform_get_drvdata(pdev);
-       int ret;
-
-       mfc_info_dev("MFC shutdown is called\n");
-       MFC_TRACE_DEV_HWLOCK("**shutdown \n");
-
-       if (!s5p_mfc_pm_get_pwr_ref_cnt(dev)) {
-               dev->shutdown = 1;
-               mfc_info_dev("MFC is not running\n");
-               return;
-       }
-
-       ret = s5p_mfc_get_hwlock_dev(dev);
-       if (ret < 0)
-               mfc_err_dev("Failed to get hwlock\n");
-
-       if (!dev->shutdown) {
-               s5p_mfc_risc_off(dev);
-               dev->shutdown = 1;
-               s5p_mfc_clear_all_bits(&dev->work_bits);
-               iovmm_deactivate(&pdev->dev);
-       }
-       s5p_mfc_release_hwlock_dev(dev);
-       mfc_info_dev("MFC shutdown completed\n");
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int s5p_mfc_suspend(struct device *dev)
-{
-       struct s5p_mfc_dev *m_dev = platform_get_drvdata(to_platform_device(dev));
-       int ret;
-
-       if (!m_dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return -EINVAL;
-       }
-
-       if (m_dev->num_inst == 0)
-               return 0;
-
-       ret = s5p_mfc_sleep(m_dev);
-
-       return ret;
-}
-
-static int s5p_mfc_resume(struct device *dev)
-{
-       struct s5p_mfc_dev *m_dev = platform_get_drvdata(to_platform_device(dev));
-       int ret;
-
-       if (!m_dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return -EINVAL;
-       }
-
-       if (m_dev->num_inst == 0)
-               return 0;
-
-       ret = s5p_mfc_wakeup(m_dev);
-
-       return ret;
-}
-#endif
-
-#ifdef CONFIG_PM
-static int s5p_mfc_runtime_suspend(struct device *dev)
-{
-       mfc_debug(3, "mfc runtime suspend\n");
-
-       return 0;
-}
-
-static int s5p_mfc_runtime_idle(struct device *dev)
-{
-       return 0;
-}
-
-static int s5p_mfc_runtime_resume(struct device *dev)
-{
-       mfc_debug(3, "mfc runtime resume\n");
-
-       return 0;
-}
-#endif
-
-/* Power management */
-static const struct dev_pm_ops s5p_mfc_pm_ops = {
-       SET_SYSTEM_SLEEP_PM_OPS(s5p_mfc_suspend, s5p_mfc_resume)
-       SET_RUNTIME_PM_OPS(
-                       s5p_mfc_runtime_suspend,
-                       s5p_mfc_runtime_resume,
-                       s5p_mfc_runtime_idle
-       )
-};
-
-struct s5p_mfc_ctx_buf_size mfc_ctx_buf_size = {
-       .dev_ctx        = PAGE_ALIGN(0x7800),   /*  30KB */
-       .h264_dec_ctx   = PAGE_ALIGN(0x200000), /* 1.6MB */
-       .other_dec_ctx  = PAGE_ALIGN(0x7800),   /*  30KB */
-       .h264_enc_ctx   = PAGE_ALIGN(0x19000),  /* 100KB */
-       .hevc_enc_ctx   = PAGE_ALIGN(0xA000),   /*  40KB */
-       .other_enc_ctx  = PAGE_ALIGN(0x6400),   /*  25KB */
-       .shared_buf     = PAGE_ALIGN(0x2000),   /*   8KB */
-       .dbg_info_buf   = PAGE_ALIGN(0x1000),   /* 4KB for DEBUG INFO */
-};
-
-struct s5p_mfc_buf_size mfc_buf_size = {
-       .firmware_code  = PAGE_ALIGN(0x100000), /* 1MB */
-       .cpb_buf        = PAGE_ALIGN(0x300000), /* 3MB */
-       .ctx_buf        = &mfc_ctx_buf_size,
-};
-
-static struct s5p_mfc_variant mfc_drvdata = {
-       .buf_size = &mfc_buf_size,
-       .num_entities = 2,
-};
-
-static const struct of_device_id exynos_mfc_match[] = {
-       {
-               .compatible = "samsung,exynos-mfc",
-               .data = &mfc_drvdata,
-       },
-       {},
-};
-MODULE_DEVICE_TABLE(of, exynos_mfc_match);
-
-static void *mfc_get_drv_data(struct platform_device *pdev)
-{
-       struct s5p_mfc_variant *driver_data = NULL;
-
-       if (pdev->dev.of_node) {
-               const struct of_device_id *match;
-               match = of_match_node(of_match_ptr(exynos_mfc_match),
-                               pdev->dev.of_node);
-               if (match)
-                       driver_data = (struct s5p_mfc_variant *)match->data;
-       } else {
-               driver_data = (struct s5p_mfc_variant *)
-                       platform_get_device_id(pdev)->driver_data;
-       }
-       return driver_data;
-}
-
-static struct platform_driver s5p_mfc_driver = {
-       .probe          = s5p_mfc_probe,
-       .remove         = s5p_mfc_remove,
-       .shutdown       = s5p_mfc_shutdown,
-       .driver = {
-               .name   = S5P_MFC_NAME,
-               .owner  = THIS_MODULE,
-               .pm     = &s5p_mfc_pm_ops,
-               .of_match_table = exynos_mfc_match,
-               .suppress_bind_attrs = true,
-       },
-};
-
-module_platform_driver(s5p_mfc_driver);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Kamil Debski <k.debski@samsung.com>");
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_buf.c b/drivers/media/platform/exynos/mfc/s5p_mfc_buf.c
deleted file mode 100644 (file)
index 1d824c3..0000000
+++ /dev/null
@@ -1,711 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_buf.c
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/smc.h>
-#include <linux/firmware.h>
-#include <trace/events/mfc.h>
-
-#include "s5p_mfc_buf.h"
-
-#include "s5p_mfc_mem.h"
-
-static int mfc_alloc_common_context(struct s5p_mfc_dev *dev,
-                                       enum mfc_buf_usage_type buf_type)
-{
-       struct s5p_mfc_special_buf *ctx_buf;
-       int firmware_size;
-       unsigned long fw_daddr;
-
-       mfc_debug_enter();
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return -EINVAL;
-       }
-
-       ctx_buf = &dev->common_ctx_buf;
-       fw_daddr = dev->fw_buf.daddr;
-
-#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
-       if (buf_type == MFCBUF_DRM) {
-               ctx_buf = &dev->drm_common_ctx_buf;
-               fw_daddr = dev->drm_fw_buf.daddr;
-       }
-#endif
-
-       firmware_size = dev->variant->buf_size->firmware_code;
-
-       ctx_buf->dma_buf = NULL;
-       ctx_buf->vaddr = NULL;
-       ctx_buf->daddr = fw_daddr + firmware_size;
-
-       mfc_debug_leave();
-
-       return 0;
-}
-
-/* Wrapper : allocate context buffers for SYS_INIT */
-int s5p_mfc_alloc_common_context(struct s5p_mfc_dev *dev)
-{
-       int ret = 0;
-
-       ret = mfc_alloc_common_context(dev, MFCBUF_NORMAL);
-       if (ret)
-               return ret;
-#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
-       if (dev->fw.drm_status) {
-               ret = mfc_alloc_common_context(dev, MFCBUF_DRM);
-               if (ret)
-                       return ret;
-       }
-#endif
-
-       return ret;
-}
-
-/* Release context buffers for SYS_INIT */
-static void mfc_release_common_context(struct s5p_mfc_dev *dev,
-                                       enum mfc_buf_usage_type buf_type)
-{
-       struct s5p_mfc_special_buf *ctx_buf;
-
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return;
-       }
-
-       ctx_buf = &dev->common_ctx_buf;
-#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
-       if (buf_type == MFCBUF_DRM)
-               ctx_buf = &dev->drm_common_ctx_buf;
-#endif
-
-       ctx_buf->dma_buf = NULL;
-       ctx_buf->vaddr = NULL;
-       ctx_buf->daddr = 0;
-}
-
-/* Release context buffers for SYS_INIT */
-void s5p_mfc_release_common_context(struct s5p_mfc_dev *dev)
-{
-       mfc_release_common_context(dev, MFCBUF_NORMAL);
-
-#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
-       mfc_release_common_context(dev, MFCBUF_DRM);
-#endif
-}
-
-/* Allocate memory for instance data buffer */
-int s5p_mfc_alloc_instance_context(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev;
-       struct s5p_mfc_ctx_buf_size *buf_size;
-
-       mfc_debug_enter();
-       if (!ctx) {
-               mfc_err_dev("no mfc context to run\n");
-               return -EINVAL;
-       }
-       dev = ctx->dev;
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return -EINVAL;
-       }
-       buf_size = dev->variant->buf_size->ctx_buf;
-
-       switch (ctx->codec_mode) {
-       case S5P_FIMV_CODEC_H264_DEC:
-       case S5P_FIMV_CODEC_H264_MVC_DEC:
-       case S5P_FIMV_CODEC_HEVC_DEC:
-       case S5P_FIMV_CODEC_BPG_DEC:
-               ctx->instance_ctx_buf.size = buf_size->h264_dec_ctx;
-               break;
-       case S5P_FIMV_CODEC_MPEG4_DEC:
-       case S5P_FIMV_CODEC_H263_DEC:
-       case S5P_FIMV_CODEC_VC1_RCV_DEC:
-       case S5P_FIMV_CODEC_VC1_DEC:
-       case S5P_FIMV_CODEC_MPEG2_DEC:
-       case S5P_FIMV_CODEC_VP8_DEC:
-       case S5P_FIMV_CODEC_VP9_DEC:
-       case S5P_FIMV_CODEC_FIMV1_DEC:
-       case S5P_FIMV_CODEC_FIMV2_DEC:
-       case S5P_FIMV_CODEC_FIMV3_DEC:
-       case S5P_FIMV_CODEC_FIMV4_DEC:
-               ctx->instance_ctx_buf.size = buf_size->other_dec_ctx;
-               break;
-       case S5P_FIMV_CODEC_H264_ENC:
-               ctx->instance_ctx_buf.size = buf_size->h264_enc_ctx;
-               break;
-       case S5P_FIMV_CODEC_HEVC_ENC:
-       case S5P_FIMV_CODEC_BPG_ENC:
-               ctx->instance_ctx_buf.size = buf_size->hevc_enc_ctx;
-               break;
-       case S5P_FIMV_CODEC_MPEG4_ENC:
-       case S5P_FIMV_CODEC_H263_ENC:
-       case S5P_FIMV_CODEC_VP8_ENC:
-       case S5P_FIMV_CODEC_VP9_ENC:
-               ctx->instance_ctx_buf.size = buf_size->other_enc_ctx;
-               break;
-       default:
-               ctx->instance_ctx_buf.size = 0;
-               mfc_err_ctx("Codec type(%d) should be checked!\n", ctx->codec_mode);
-               return -ENOMEM;
-       }
-
-       if (ctx->is_drm)
-               ctx->instance_ctx_buf.buftype = MFCBUF_DRM;
-       else
-               ctx->instance_ctx_buf.buftype = MFCBUF_NORMAL;
-
-       if (s5p_mfc_mem_ion_alloc(dev, &ctx->instance_ctx_buf)) {
-               mfc_err_ctx("Allocating context buffer failed\n");
-               return -ENOMEM;
-       }
-
-       mfc_debug(2, "[MEMINFO] Instance buf ctx[%d] size: %ld, daddr: 0x%08llx\n",
-                       ctx->num, ctx->instance_ctx_buf.size, ctx->instance_ctx_buf.daddr);
-
-       return 0;
-}
-
-/* Release instance buffer */
-void s5p_mfc_release_instance_context(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev;
-
-       mfc_debug_enter();
-       if (!ctx) {
-               mfc_err_dev("no mfc context to run\n");
-               return;
-       }
-
-       dev = ctx->dev;
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return;
-       }
-
-       s5p_mfc_mem_ion_free(dev, &ctx->instance_ctx_buf);
-       mfc_debug(2, "[MEMINFO] Release the instance buffer ctx[%d]\n", ctx->num);
-
-       mfc_debug_leave();
-}
-
-static void mfc_calc_dec_codec_buffer_size(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dec *dec;
-       int i;
-
-       dec = ctx->dec_priv;
-
-       /* Codecs have different memory requirements */
-       switch (ctx->codec_mode) {
-       case S5P_FIMV_CODEC_H264_DEC:
-       case S5P_FIMV_CODEC_H264_MVC_DEC:
-               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
-               ctx->codec_buf.size =
-                       ctx->scratch_buf_size +
-                       (dec->mv_count * ctx->mv_size);
-               break;
-       case S5P_FIMV_CODEC_MPEG4_DEC:
-       case S5P_FIMV_CODEC_FIMV1_DEC:
-       case S5P_FIMV_CODEC_FIMV2_DEC:
-       case S5P_FIMV_CODEC_FIMV3_DEC:
-       case S5P_FIMV_CODEC_FIMV4_DEC:
-               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
-               if (dec->loop_filter_mpeg4) {
-                       ctx->loopfilter_luma_size = ALIGN(ctx->raw_buf.plane_size[0], 256);
-                       ctx->loopfilter_chroma_size = ALIGN(ctx->raw_buf.plane_size[1] +
-                                                       ctx->raw_buf.plane_size[2], 256);
-                       ctx->codec_buf.size = ctx->scratch_buf_size +
-                               (NUM_MPEG4_LF_BUF * (ctx->loopfilter_luma_size +
-                                                    ctx->loopfilter_chroma_size));
-               } else {
-                       ctx->codec_buf.size = ctx->scratch_buf_size;
-               }
-               break;
-       case S5P_FIMV_CODEC_VC1_RCV_DEC:
-       case S5P_FIMV_CODEC_VC1_DEC:
-               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
-               ctx->codec_buf.size = ctx->scratch_buf_size;
-               break;
-       case S5P_FIMV_CODEC_MPEG2_DEC:
-               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
-               ctx->codec_buf.size = ctx->scratch_buf_size;
-               break;
-       case S5P_FIMV_CODEC_H263_DEC:
-               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
-               ctx->codec_buf.size = ctx->scratch_buf_size;
-               break;
-       case S5P_FIMV_CODEC_VP8_DEC:
-               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
-               ctx->codec_buf.size = ctx->scratch_buf_size;
-               break;
-       case S5P_FIMV_CODEC_VP9_DEC:
-               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
-               ctx->codec_buf.size =
-                       ctx->scratch_buf_size +
-                       DEC_STATIC_BUFFER_SIZE;
-               break;
-       case S5P_FIMV_CODEC_HEVC_DEC:
-       case S5P_FIMV_CODEC_BPG_DEC:
-               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
-               ctx->codec_buf.size =
-                       ctx->scratch_buf_size +
-                       (dec->mv_count * ctx->mv_size);
-               break;
-       default:
-               ctx->codec_buf.size = 0;
-               mfc_err_ctx("invalid codec type: %d\n", ctx->codec_mode);
-               break;
-       }
-
-       mfc_debug(2, "[MEMINFO] scratch: %zu, MV: %zu x count %d\n",
-                       ctx->scratch_buf_size, ctx->mv_size, dec->mv_count);
-       if (dec->loop_filter_mpeg4)
-               mfc_debug(2, "[MEMINFO] (loopfilter luma: %zu, chroma: %zu) x count %d\n",
-                               ctx->loopfilter_luma_size, ctx->loopfilter_chroma_size,
-                               NUM_MPEG4_LF_BUF);
-}
-
-static void mfc_calc_enc_codec_buffer_size(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_enc *enc;
-       unsigned int mb_width, mb_height;
-       unsigned int lcu_width = 0, lcu_height = 0;
-
-       enc = ctx->enc_priv;
-       enc->tmv_buffer_size = 0;
-
-       mb_width = WIDTH_MB(ctx->crop_width);
-       mb_height = HEIGHT_MB(ctx->crop_height);
-
-       lcu_width = ENC_LCU_WIDTH(ctx->crop_width);
-       lcu_height = ENC_LCU_HEIGHT(ctx->crop_height);
-
-       /* default recon buffer size, it can be changed in case of 422, 10bit */
-       enc->luma_dpb_size =
-               ALIGN(ENC_LUMA_DPB_SIZE(ctx->crop_width, ctx->crop_height), 64);
-       enc->chroma_dpb_size =
-               ALIGN(ENC_CHROMA_DPB_SIZE(ctx->crop_width, ctx->crop_height), 64);
-
-       /* Codecs have different memory requirements */
-       switch (ctx->codec_mode) {
-       case S5P_FIMV_CODEC_H264_ENC:
-               enc->me_buffer_size =
-                       ALIGN(ENC_V100_H264_ME_SIZE(mb_width, mb_height), 256);
-
-               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
-               ctx->codec_buf.size =
-                       ctx->scratch_buf_size + enc->tmv_buffer_size +
-                       (ctx->dpb_count * (enc->luma_dpb_size +
-                       enc->chroma_dpb_size + enc->me_buffer_size));
-               break;
-       case S5P_FIMV_CODEC_MPEG4_ENC:
-       case S5P_FIMV_CODEC_H263_ENC:
-               enc->me_buffer_size =
-                       ALIGN(ENC_V100_MPEG4_ME_SIZE(mb_width, mb_height), 256);
-
-               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
-               ctx->codec_buf.size =
-                       ctx->scratch_buf_size + enc->tmv_buffer_size +
-                       (ctx->dpb_count * (enc->luma_dpb_size +
-                       enc->chroma_dpb_size + enc->me_buffer_size));
-               break;
-       case S5P_FIMV_CODEC_VP8_ENC:
-               enc->me_buffer_size =
-                       ALIGN(ENC_V100_VP8_ME_SIZE(mb_width, mb_height), 256);
-
-               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
-               ctx->codec_buf.size =
-                       ctx->scratch_buf_size + enc->tmv_buffer_size +
-                       (ctx->dpb_count * (enc->luma_dpb_size +
-                       enc->chroma_dpb_size + enc->me_buffer_size));
-               break;
-       case S5P_FIMV_CODEC_VP9_ENC:
-               if (ctx->is_10bit || ctx->is_422) {
-                       enc->luma_dpb_size =
-                               ALIGN(ENC_VP9_LUMA_DPB_10B_SIZE(ctx->crop_width, ctx->crop_height), 64);
-                       enc->chroma_dpb_size =
-                               ALIGN(ENC_VP9_CHROMA_DPB_10B_SIZE(ctx->crop_width, ctx->crop_height), 64);
-                       mfc_debug(2, "[10BIT] VP9 10bit or 422 recon luma size: %zu chroma size: %zu\n",
-                                       enc->luma_dpb_size, enc->chroma_dpb_size);
-               }
-               enc->me_buffer_size =
-                       ALIGN(ENC_V100_VP9_ME_SIZE(lcu_width, lcu_height), 256);
-
-               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
-               ctx->codec_buf.size =
-                       ctx->scratch_buf_size + enc->tmv_buffer_size +
-                       (ctx->dpb_count * (enc->luma_dpb_size +
-                                          enc->chroma_dpb_size + enc->me_buffer_size));
-               break;
-       case S5P_FIMV_CODEC_HEVC_ENC:
-       case S5P_FIMV_CODEC_BPG_ENC:
-               if (ctx->is_10bit || ctx->is_422) {
-                       enc->luma_dpb_size =
-                               ALIGN(ENC_HEVC_LUMA_DPB_10B_SIZE(ctx->crop_width, ctx->crop_height), 64);
-                       enc->chroma_dpb_size =
-                               ALIGN(ENC_HEVC_CHROMA_DPB_10B_SIZE(ctx->crop_width, ctx->crop_height), 64);
-                       mfc_debug(2, "[10BIT] HEVC 10bit or 422 recon luma size: %zu chroma size: %zu\n",
-                                       enc->luma_dpb_size, enc->chroma_dpb_size);
-               }
-               enc->me_buffer_size =
-                       ALIGN(ENC_V100_HEVC_ME_SIZE(lcu_width, lcu_height), 256);
-
-               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
-               ctx->codec_buf.size =
-                       ctx->scratch_buf_size + enc->tmv_buffer_size +
-                       (ctx->dpb_count * (enc->luma_dpb_size +
-                                          enc->chroma_dpb_size + enc->me_buffer_size));
-               break;
-       default:
-               ctx->codec_buf.size = 0;
-               mfc_err_ctx("invalid codec type: %d\n", ctx->codec_mode);
-               break;
-       }
-
-       mfc_debug(2, "[MEMINFO] scratch: %zu, TMV: %zu, (recon luma: %zu, chroma: %zu, me: %zu) x count %d\n",
-                       ctx->scratch_buf_size, enc->tmv_buffer_size,
-                       enc->luma_dpb_size, enc->chroma_dpb_size, enc->me_buffer_size,
-                       ctx->dpb_count);
-}
-
-/* Allocate codec buffers */
-int s5p_mfc_alloc_codec_buffers(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev;
-
-       mfc_debug_enter();
-       if (!ctx) {
-               mfc_err_dev("no mfc context to run\n");
-               return -EINVAL;
-       }
-       dev = ctx->dev;
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return -EINVAL;
-       }
-
-       if (ctx->type == MFCINST_DECODER) {
-               mfc_calc_dec_codec_buffer_size(ctx);
-       } else if (ctx->type == MFCINST_ENCODER) {
-               mfc_calc_enc_codec_buffer_size(ctx);
-       } else {
-               mfc_err_ctx("invalid type: %d\n", ctx->type);
-               return -EINVAL;
-       }
-
-       if (ctx->is_drm)
-               ctx->codec_buf.buftype = MFCBUF_DRM;
-       else
-               ctx->codec_buf.buftype = MFCBUF_NORMAL;
-
-       if (ctx->codec_buf.size > 0) {
-               if (s5p_mfc_mem_ion_alloc(dev, &ctx->codec_buf)) {
-                       mfc_err_ctx("Allocating codec buffer failed\n");
-                       return -ENOMEM;
-               }
-               ctx->codec_buffer_allocated = 1;
-       } else if (ctx->codec_mode == S5P_FIMV_CODEC_MPEG2_DEC) {
-               ctx->codec_buffer_allocated = 1;
-       }
-
-       mfc_debug(2, "[MEMINFO] Codec buf ctx[%d] size: %ld, addr: 0x%08llx\n",
-                       ctx->num, ctx->codec_buf.size, ctx->codec_buf.daddr);
-
-       return 0;
-}
-
-/* Release buffers allocated for codec */
-void s5p_mfc_release_codec_buffers(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev;
-
-       if (!ctx) {
-               mfc_err_dev("no mfc context to run\n");
-               return;
-       }
-
-       dev = ctx->dev;
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return;
-       }
-
-       s5p_mfc_mem_ion_free(dev, &ctx->codec_buf);
-       ctx->codec_buffer_allocated = 0;
-       mfc_debug(2, "[MEMINFO] Release the codec buffer ctx[%d]\n", ctx->num);
-}
-
-/* Allocation buffer of debug infor memory for FW debugging */
-int s5p_mfc_alloc_dbg_info_buffer(struct s5p_mfc_dev *dev)
-{
-       struct s5p_mfc_ctx_buf_size *buf_size = dev->variant->buf_size->ctx_buf;
-
-       mfc_debug(2, "Allocate a debug-info buffer\n");
-
-       dev->dbg_info_buf.buftype = MFCBUF_NORMAL;
-       dev->dbg_info_buf.size = buf_size->dbg_info_buf;
-       if (s5p_mfc_mem_ion_alloc(dev, &dev->dbg_info_buf)) {
-               mfc_err_dev("Allocating debug info buffer failed\n");
-               return -ENOMEM;
-       }
-       mfc_debug(2, "[MEMINFO] debug info buf size: %ld, daddr: 0x%08llx, vaddr: 0x%p\n",
-                       dev->dbg_info_buf.size, dev->dbg_info_buf.daddr, dev->dbg_info_buf.vaddr);
-
-       return 0;
-}
-
-/* Release buffer of debug infor memory for FW debugging */
-int s5p_mfc_release_dbg_info_buffer(struct s5p_mfc_dev *dev)
-{
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return -EINVAL;
-       }
-
-       if (!dev->dbg_info_buf.dma_buf) {
-               mfc_debug(2, "debug info buffer is already freed\n");
-               return 0;
-       }
-
-       s5p_mfc_mem_ion_free(dev, &dev->dbg_info_buf);
-       mfc_debug(2, "[MEMINFO] Release the debug info buffer\n");
-
-       return 0;
-}
-
-/* Allocation buffer of ROI macroblock information */
-static int mfc_alloc_enc_roi_buffer(struct s5p_mfc_ctx *ctx, struct s5p_mfc_special_buf *roi_buf)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_ctx_buf_size *buf_size = dev->variant->buf_size->ctx_buf;
-
-       roi_buf->buftype = MFCBUF_NORMAL;
-       roi_buf->size = buf_size->shared_buf;
-       if (s5p_mfc_mem_ion_alloc(dev, roi_buf)) {
-               mfc_err_ctx("[ROI] Allocating ROI buffer failed\n");
-               return -ENOMEM;
-       }
-       mfc_debug(2, "[MEMINFO][ROI] roi buf ctx[%d] size: %ld, daddr: 0x%08llx, vaddr: 0x%p\n",
-                       ctx->num, roi_buf->size, roi_buf->daddr, roi_buf->vaddr);
-
-       memset(roi_buf->vaddr, 0, buf_size->shared_buf);
-
-       return 0;
-}
-
-/* Wrapper : allocation ROI buffers */
-int s5p_mfc_alloc_enc_roi_buffer(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_enc *enc = ctx->enc_priv;
-       int i;
-
-       for (i = 0; i < MFC_MAX_EXTRA_BUF; i++) {
-               if (mfc_alloc_enc_roi_buffer(ctx, &enc->roi_buf[i]) < 0) {
-                       mfc_err_dev("[ROI] Allocating remapping buffer[%d] failed\n", i);
-                       return -ENOMEM;
-               }
-       }
-
-       return 0;
-}
-
-/* Release buffer of ROI macroblock information */
-void s5p_mfc_release_enc_roi_buffer(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_enc *enc = ctx->enc_priv;
-       int i;
-
-       for (i = 0; i < MFC_MAX_EXTRA_BUF; i++)
-               if (enc->roi_buf[i].dma_buf)
-                       s5p_mfc_mem_ion_free(ctx->dev, &enc->roi_buf[i]);
-
-       mfc_debug(2, "[MEMINFO][ROI] Release the ROI buffer\n");
-}
-
-int s5p_mfc_otf_alloc_stream_buf(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct _otf_handle *handle = ctx->otf_handle;
-       struct _otf_debug *debug = &handle->otf_debug;
-       struct s5p_mfc_special_buf *buf;
-       struct s5p_mfc_raw_info *raw = &ctx->raw_buf;
-       int i;
-
-       mfc_debug_enter();
-
-       for (i = 0; i < OTF_MAX_BUF; i++) {
-               buf = &debug->stream_buf[i];
-               buf->buftype = MFCBUF_NORMAL;
-               buf->size = raw->total_plane_size;
-               if (s5p_mfc_mem_ion_alloc(dev, buf)) {
-                       mfc_err_ctx("[OTF] Allocating stream buffer failed\n");
-                       return -EINVAL;
-               }
-               mfc_debug(2, "[OTF][MEMINFO] OTF stream buf[%d] size: %ld, daddr: 0x%08llx, vaddr: 0x%p\n",
-                               i, buf->size, buf->daddr, buf->vaddr);
-               memset(buf->vaddr, 0, raw->total_plane_size);
-       }
-
-       mfc_debug_leave();
-
-       return 0;
-}
-
-void s5p_mfc_otf_release_stream_buf(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct _otf_handle *handle = ctx->otf_handle;
-       struct _otf_debug *debug = &handle->otf_debug;
-       struct s5p_mfc_special_buf *buf;
-       int i;
-
-       mfc_debug_enter();
-
-       for (i = 0; i < OTF_MAX_BUF; i++) {
-               buf = &debug->stream_buf[i];
-               if (buf->dma_buf)
-                       s5p_mfc_mem_ion_free(dev, buf);
-       }
-
-       mfc_debug(2, "[OTF][MEMINFO] Release the OTF stream buffer\n");
-       mfc_debug_leave();
-}
-
-/* Allocate firmware */
-int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev)
-{
-       size_t firmware_size;
-       struct s5p_mfc_ctx_buf_size *buf_size;
-
-       mfc_debug_enter();
-
-       if (!dev) {
-               mfc_err_dev("[F/W] no mfc device to run\n");
-               return -EINVAL;
-       }
-
-       buf_size = dev->variant->buf_size->ctx_buf;
-       firmware_size = dev->variant->buf_size->firmware_code;
-       dev->fw.size = firmware_size + buf_size->dev_ctx;
-
-       if (dev->fw_buf.dma_buf)
-               return 0;
-
-       mfc_debug(4, "[F/W] Allocating memory for firmware\n");
-       trace_mfc_loadfw_start(dev->fw.size, firmware_size);
-
-       dev->fw_buf.buftype = MFCBUF_NORMAL;
-       dev->fw_buf.size = dev->fw.size;
-       if (s5p_mfc_mem_ion_alloc(dev, &dev->fw_buf)) {
-               mfc_err_dev("[F/W] Allocating normal firmware buffer failed\n");
-               return -ENOMEM;
-       }
-
-       mfc_debug(2, "[MEMINFO][F/W] FW normal: 0x%08llx (vaddr: 0x%p), size: %08zu\n",
-                       dev->fw_buf.daddr, dev->fw_buf.vaddr,
-                       dev->fw_buf.size);
-
-#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
-       dev->drm_fw_buf.buftype = MFCBUF_DRM_FW;
-       dev->drm_fw_buf.size = dev->fw.size;
-       if (s5p_mfc_mem_ion_alloc(dev, &dev->drm_fw_buf)) {
-               mfc_err_dev("[F/W] Allocating DRM firmware buffer failed\n");
-               return -ENOMEM;
-       }
-
-       mfc_debug(2, "[MEMINFO][F/W] FW DRM: 0x%08llx (vaddr: 0x%p), size: %08zu\n",
-                       dev->drm_fw_buf.daddr, dev->drm_fw_buf.vaddr,
-                       dev->drm_fw_buf.size);
-#endif
-
-       mfc_debug_leave();
-
-       return 0;
-}
-
-/* Load firmware to MFC */
-int s5p_mfc_load_firmware(struct s5p_mfc_dev *dev)
-{
-       struct firmware *fw_blob;
-       size_t firmware_size;
-       int err;
-
-       if (!dev) {
-               mfc_err_dev("[F/W] no mfc device to run\n");
-               return -EINVAL;
-       }
-
-       firmware_size = dev->variant->buf_size->firmware_code;
-
-       /* Firmare has to be present as a separate file or compiled
-        * into kernel. */
-       mfc_debug_enter();
-       mfc_debug(4, "[F/W] Requesting F/W\n");
-       err = request_firmware((const struct firmware **)&fw_blob,
-                                       MFC_FW_NAME, dev->v4l2_dev.dev);
-
-       if (err != 0) {
-               mfc_err_dev("[F/W] Couldn't find the F/W invalid path\n");
-               return -EINVAL;
-       }
-
-       mfc_debug(2, "[MEMINFO][F/W] loaded F/W Size: %zu\n", fw_blob->size);
-
-       if (fw_blob->size > firmware_size) {
-               mfc_err_dev("[MEMINFO][F/W] MFC firmware(%zu) is too big to be loaded in memory(%zu)\n",
-                               fw_blob->size, firmware_size);
-               release_firmware(fw_blob);
-               return -ENOMEM;
-       }
-
-       if (dev->fw_buf.dma_buf == NULL || dev->fw_buf.daddr == 0) {
-               mfc_err_dev("[F/W] MFC firmware is not allocated or was not mapped correctly\n");
-               release_firmware(fw_blob);
-               return -EINVAL;
-       }
-
-       memcpy(dev->fw_buf.vaddr, fw_blob->data, fw_blob->size);
-       if (dev->drm_fw_buf.vaddr) {
-               memcpy(dev->drm_fw_buf.vaddr, fw_blob->data, fw_blob->size);
-               mfc_debug(4, "[F/W] copy firmware to secure region\n");
-       }
-       release_firmware(fw_blob);
-       trace_mfc_loadfw_end(dev->fw.size, firmware_size);
-       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 */
-       if (!dev) {
-               mfc_err_dev("[F/W] no mfc device to run\n");
-               return -EINVAL;
-       }
-
-       if (!dev->fw_buf.dma_buf) {
-               mfc_err_dev("[F/W] firmware memory is already freed\n");
-               return -EINVAL;
-       }
-
-#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
-       s5p_mfc_mem_ion_free(dev, &dev->drm_fw_buf);
-#endif
-
-       s5p_mfc_mem_ion_free(dev, &dev->fw_buf);
-
-       return 0;
-}
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_buf.h b/drivers/media/platform/exynos/mfc/s5p_mfc_buf.h
deleted file mode 100644 (file)
index 6ffcc96..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_buf.h
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __S5P_MFC_BUF_H
-#define __S5P_MFC_BUF_H __FILE__
-
-#include "s5p_mfc_common.h"
-
-/* Memory allocation */
-int s5p_mfc_alloc_common_context(struct s5p_mfc_dev *dev);
-void s5p_mfc_release_common_context(struct s5p_mfc_dev *dev);
-
-int s5p_mfc_alloc_instance_context(struct s5p_mfc_ctx *ctx);
-void s5p_mfc_release_instance_context(struct s5p_mfc_ctx *ctx);
-
-int s5p_mfc_alloc_codec_buffers(struct s5p_mfc_ctx *ctx);
-void s5p_mfc_release_codec_buffers(struct s5p_mfc_ctx *ctx);
-
-int s5p_mfc_alloc_enc_roi_buffer(struct s5p_mfc_ctx *ctx);
-void s5p_mfc_release_enc_roi_buffer(struct s5p_mfc_ctx *ctx);
-
-int s5p_mfc_otf_alloc_stream_buf(struct s5p_mfc_ctx *ctx);
-void s5p_mfc_otf_release_stream_buf(struct s5p_mfc_ctx *ctx);
-
-int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev);
-int s5p_mfc_load_firmware(struct s5p_mfc_dev *dev);
-int s5p_mfc_release_firmware(struct s5p_mfc_dev *dev);
-
-int s5p_mfc_alloc_dbg_info_buffer(struct s5p_mfc_dev *dev);
-int s5p_mfc_release_dbg_info_buffer(struct s5p_mfc_dev *dev);
-
-#endif /* __S5P_MFC_BUF_H */
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_cal.c b/drivers/media/platform/exynos/mfc/s5p_mfc_cal.c
deleted file mode 100644 (file)
index c8d5cab..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_cal.c
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <trace/events/mfc.h>
-
-#include "s5p_mfc_cal.h"
-#include "s5p_mfc_pm.h"
-
-/* Reset the device */
-int s5p_mfc_reset_mfc(struct s5p_mfc_dev *dev)
-{
-       int i;
-
-       mfc_debug_enter();
-
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return -EINVAL;
-       }
-
-       /* Zero Initialization of MFC registers */
-       MFC_WRITEL(0, S5P_FIMV_RISC2HOST_CMD);
-       MFC_WRITEL(0, S5P_FIMV_HOST2RISC_CMD);
-       MFC_WRITEL(0, S5P_FIMV_FW_VERSION);
-
-       for (i = 0; i < S5P_FIMV_REG_CLEAR_COUNT; i++)
-               MFC_WRITEL(0, S5P_FIMV_REG_CLEAR_BEGIN + (i*4));
-
-       MFC_WRITEL(0x1FFF, S5P_FIMV_MFC_RESET);
-       MFC_WRITEL(0, S5P_FIMV_MFC_RESET);
-
-       mfc_debug_leave();
-
-       return 0;
-}
-
-void s5p_mfc_set_risc_base_addr(struct s5p_mfc_dev *dev,
-                                       enum mfc_buf_usage_type buf_type)
-{
-       struct s5p_mfc_special_buf *fw_buf;
-
-       fw_buf = &dev->fw_buf;
-
-       if (buf_type == MFCBUF_DRM)
-               fw_buf = &dev->drm_fw_buf;
-
-       MFC_WRITEL(fw_buf->daddr, S5P_FIMV_RISC_BASE_ADDRESS);
-       mfc_debug(2, "[MEMINFO][F/W] %s Base Address : %#x\n",
-                       buf_type == MFCBUF_DRM ? "DRM" : "NORMAL", fw_buf->daddr);
-       MFC_TRACE_DEV("%s F/W Base Address : %#x\n",
-                       buf_type == MFCBUF_DRM ? "DRM" : "NORMAL", fw_buf->daddr);
-}
-
-void s5p_mfc_cmd_host2risc(struct s5p_mfc_dev *dev, int cmd)
-{
-       mfc_debug(1, "Issue the command: %d\n", cmd);
-       MFC_TRACE_DEV(">> CMD : %d, (dev:0x%lx, bits:%lx, owned:%d, wl:%d, trans:%d)\n",
-                       cmd, dev->hwlock.dev, dev->hwlock.bits, dev->hwlock.owned_by_irq,
-                       dev->hwlock.wl_count, dev->hwlock.transfer_owner);
-
-       trace_mfc_frame_start(dev->curr_ctx, cmd, 0, 0);
-       /* Reset RISC2HOST command except nal q stop command */
-       if (cmd != S5P_FIMV_H2R_CMD_STOP_QUEUE)
-               MFC_WRITEL(0x0, S5P_FIMV_RISC2HOST_CMD);
-
-       /* Start the timeout watchdog */
-       if ((cmd != S5P_FIMV_H2R_CMD_NAL_QUEUE) && (cmd != S5P_FIMV_H2R_CMD_STOP_QUEUE))
-               s5p_mfc_watchdog_start_tick(dev);
-
-       if (dbg_enable) {
-               /* For FW debugging */
-               s5p_mfc_dbg_set_addr(dev);
-               s5p_mfc_dbg_enable(dev);
-       }
-
-       /* Issue the command */
-       MFC_WRITEL(cmd, S5P_FIMV_HOST2RISC_CMD);
-       MFC_WRITEL(0x1, S5P_FIMV_HOST2RISC_INT);
-}
-
-/* Check whether HW interrupt has occurred or not */
-int s5p_mfc_check_risc2host(struct s5p_mfc_dev *dev)
-{
-       if (s5p_mfc_pm_get_pwr_ref_cnt(dev) && s5p_mfc_pm_get_clk_ref_cnt(dev)) {
-               if (MFC_READL(S5P_FIMV_RISC2HOST_INT))
-                       return MFC_READL(S5P_FIMV_RISC2HOST_CMD);
-               else
-                       return 0;
-       }
-
-       return 0;
-}
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_cal.h b/drivers/media/platform/exynos/mfc/s5p_mfc_cal.h
deleted file mode 100644 (file)
index f2a965f..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_cal.h
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __S5P_MFC_CAL_H
-#define __S5P_MFC_CAL_H __FILE__
-
-#include "s5p_mfc_reg.h"
-
-#include "s5p_mfc_common.h"
-
-#include "s5p_mfc_utils.h"
-
-
-#define s5p_mfc_get_int_reason()       (MFC_READL(S5P_FIMV_RISC2HOST_CMD)              \
-                                               & S5P_FIMV_RISC2HOST_CMD_MASK)
-#define s5p_mfc_clear_int_sfr()                                \
-               do {                                                    \
-                       MFC_WRITEL(0, S5P_FIMV_RISC2HOST_CMD);  \
-                       MFC_WRITEL(0, S5P_FIMV_RISC2HOST_INT);  \
-               } while (0)
-
-static inline int s5p_mfc_stop_bus(struct s5p_mfc_dev *dev)
-{
-       unsigned int status;
-       unsigned long timeout;
-
-       /* Reset */
-       MFC_WRITEL(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_dev("Timeout while resetting MFC.\n");
-                       return -EIO;
-               }
-               status = MFC_READL(S5P_FIMV_MFC_BUS_RESET_CTRL);
-       } while ((status & 0x2) == 0);
-
-       return 0;
-}
-
-static inline void s5p_mfc_start_bus(struct s5p_mfc_dev *dev)
-{
-       int val;
-
-       val = MFC_READL(S5P_FIMV_MFC_BUS_RESET_CTRL);
-       val &= ~(0x1);
-       MFC_WRITEL(val, S5P_FIMV_MFC_BUS_RESET_CTRL);
-}
-
-static inline void s5p_mfc_risc_on(struct s5p_mfc_dev *dev)
-{
-       s5p_mfc_clean_dev_int_flags(dev);
-
-       MFC_WRITEL(0x1, S5P_FIMV_RISC_ON);
-       MFC_WRITEL(0x0, S5P_FIMV_MFC_OFF);
-       mfc_debug(1, "RISC_ON\n");
-       MFC_TRACE_DEV(">> RISC ON\n");
-}
-
-static inline void s5p_mfc_risc_off(struct s5p_mfc_dev *dev)
-{
-       unsigned int status;
-       unsigned long timeout;
-
-       timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
-       /* Check pending status */
-       do {
-               if (time_after(jiffies, timeout)) {
-                       mfc_err_dev("Timeout while pendng clear\n");
-                       mfc_err_dev("MFC access pending state: %#x\n", status);
-                       mfc_err_dev("MFC access pending R: %#x, W: %#x\n",
-                                       MFC_READL(S5P_FIMV_MFC_RPEND),
-                                       MFC_READL(S5P_FIMV_MFC_WPEND));
-                       break;
-               }
-               status = MFC_READL(S5P_FIMV_MFC_BUS_STATUS);
-       } while (status != 0);
-
-       MFC_WRITEL(0x0, S5P_FIMV_RISC_ON);
-}
-
-static inline void s5p_mfc_mfc_off(struct s5p_mfc_dev *dev)
-{
-       mfc_info_dev("MFC h/w state: %d\n",
-                       MFC_READL(S5P_FIMV_MFC_STATE) & 0x7);
-       MFC_WRITEL(0x1, S5P_FIMV_MFC_OFF);
-}
-
-static inline void s5p_mfc_enable_all_clocks(struct s5p_mfc_dev *dev)
-{
-       /* Enable all FW clock gating */
-       MFC_WRITEL(0xFFFFFFFF, S5P_FIMV_MFC_FW_CLOCK);
-}
-
-int s5p_mfc_reset_mfc(struct s5p_mfc_dev *dev);
-void s5p_mfc_set_risc_base_addr(struct s5p_mfc_dev *dev,
-                               enum mfc_buf_usage_type buf_type);
-void s5p_mfc_cmd_host2risc(struct s5p_mfc_dev *dev, int cmd);
-int s5p_mfc_check_risc2host(struct s5p_mfc_dev *dev);
-
-#endif /* __S5P_MFC_CAL_H */
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_cmd.c b/drivers/media/platform/exynos/mfc/s5p_mfc_cmd.c
deleted file mode 100644 (file)
index c744883..0000000
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_cmd.c
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <trace/events/mfc.h>
-
-#include "s5p_mfc_cmd.h"
-
-#include "s5p_mfc_cal.h"
-#include "s5p_mfc_reg.h"
-#include "s5p_mfc_mmcache.h"
-
-#include "s5p_mfc_utils.h"
-#include "s5p_mfc_buf.h"
-
-int s5p_mfc_cmd_sys_init(struct s5p_mfc_dev *dev,
-                                       enum mfc_buf_usage_type buf_type)
-{
-       struct s5p_mfc_ctx_buf_size *buf_size;
-       struct s5p_mfc_special_buf *ctx_buf;
-
-       mfc_debug_enter();
-
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return -EINVAL;
-       }
-
-       s5p_mfc_clean_dev_int_flags(dev);
-
-       buf_size = dev->variant->buf_size->ctx_buf;
-       ctx_buf = &dev->common_ctx_buf;
-#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
-       if (buf_type == MFCBUF_DRM)
-               ctx_buf = &dev->drm_common_ctx_buf;
-#endif
-       MFC_WRITEL(ctx_buf->daddr, S5P_FIMV_CONTEXT_MEM_ADDR);
-       MFC_WRITEL(buf_size->dev_ctx, S5P_FIMV_CONTEXT_MEM_SIZE);
-
-       s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_SYS_INIT);
-
-       mfc_debug_leave();
-
-       return 0;
-}
-
-void s5p_mfc_cmd_sleep(struct s5p_mfc_dev *dev)
-{
-       mfc_debug_enter();
-
-       s5p_mfc_clean_dev_int_flags(dev);
-       s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_SLEEP);
-
-       mfc_debug_leave();
-}
-
-void s5p_mfc_cmd_wakeup(struct s5p_mfc_dev *dev)
-{
-       mfc_debug_enter();
-
-       s5p_mfc_clean_dev_int_flags(dev);
-       s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_WAKEUP);
-
-       mfc_debug_leave();
-}
-
-/* Open a new instance and get its number */
-int s5p_mfc_cmd_open_inst(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev;
-
-       mfc_debug_enter();
-
-       if (!ctx) {
-               mfc_err_dev("no mfc context to run\n");
-               return -EINVAL;
-       }
-       dev = ctx->dev;
-       mfc_debug(2, "Requested codec mode: %d\n", ctx->codec_mode);
-
-       MFC_WRITEL(ctx->codec_mode, S5P_FIMV_CODEC_TYPE);
-       MFC_WRITEL(ctx->instance_ctx_buf.daddr, S5P_FIMV_CONTEXT_MEM_ADDR);
-       MFC_WRITEL(ctx->instance_ctx_buf.size, S5P_FIMV_CONTEXT_MEM_SIZE);
-       if (ctx->type == MFCINST_DECODER)
-               MFC_WRITEL(ctx->dec_priv->crc_enable, S5P_FIMV_D_CRC_CTRL);
-
-       s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_OPEN_INSTANCE);
-
-       mfc_debug_leave();
-
-       return 0;
-}
-
-/* Close instance */
-int s5p_mfc_cmd_close_inst(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev;
-
-       mfc_debug_enter();
-
-       if (!ctx) {
-               mfc_err_dev("no mfc context to run\n");
-               return -EINVAL;
-       }
-       dev = ctx->dev;
-
-       MFC_WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID);
-
-       s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_CLOSE_INSTANCE);
-
-       mfc_debug_leave();
-
-       return 0;
-}
-
-int s5p_mfc_cmd_dpb_flush(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       if (ON_RES_CHANGE(ctx))
-               mfc_err_ctx("dpb flush on res change(state:%d)\n", ctx->state);
-
-       s5p_mfc_clean_ctx_int_flags(ctx);
-
-       MFC_WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID);
-       s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_DPB_FLUSH);
-
-       return 0;
-}
-
-int s5p_mfc_cmd_cache_flush(struct s5p_mfc_dev *dev)
-{
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return -EINVAL;
-       }
-
-       s5p_mfc_clean_dev_int_flags(dev);
-       s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_CACHE_FLUSH);
-
-       return 0;
-}
-
-int s5p_mfc_cmd_dec_init_buffers(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev;
-       struct s5p_mfc_dec *dec;
-       unsigned int reg = 0, pix_val;
-       int ret;
-
-       if (!ctx) {
-               mfc_err_dev("no mfc context to run\n");
-               return -EINVAL;
-       }
-       dec = ctx->dec_priv;
-       dev = ctx->dev;
-       if (!dev) {
-               mfc_err_ctx("no mfc device to run\n");
-               return -EINVAL;
-       }
-
-       switch (ctx->dst_fmt->fourcc) {
-       case V4L2_PIX_FMT_NV12M:
-       case V4L2_PIX_FMT_NV12N:
-       case V4L2_PIX_FMT_NV12MT_16X16:
-       case V4L2_PIX_FMT_NV16M:
-       case V4L2_PIX_FMT_NV12N_10B:
-       case V4L2_PIX_FMT_NV12M_S10B:
-       case V4L2_PIX_FMT_NV16M_S10B:
-       case V4L2_PIX_FMT_NV12M_P010:
-       case V4L2_PIX_FMT_NV16M_P210:
-               pix_val = 0;
-               break;
-       case V4L2_PIX_FMT_NV21M:
-       case V4L2_PIX_FMT_NV61M:
-       case V4L2_PIX_FMT_NV21M_S10B:
-       case V4L2_PIX_FMT_NV61M_S10B:
-       case V4L2_PIX_FMT_NV21M_P010:
-       case V4L2_PIX_FMT_NV61M_P210:
-               pix_val = 1;
-               break;
-       case V4L2_PIX_FMT_YVU420M:
-               pix_val = 2;
-               break;
-       case V4L2_PIX_FMT_YUV420M:
-       case V4L2_PIX_FMT_YUV420N:
-               pix_val = 3;
-               break;
-       default:
-               pix_val = 0;
-               break;
-       }
-       reg = MFC_READL(S5P_FIMV_PIXEL_FORMAT);
-       reg &= ~(0xF);
-       reg |= pix_val & 0xF;
-       MFC_WRITEL(reg, S5P_FIMV_PIXEL_FORMAT);
-       mfc_debug(2, "[FRAME] pixel format: %d, mem_type_10bit should be fixed on SEQ_START(reg: %#x)\n",
-                       pix_val, reg);
-
-       s5p_mfc_clean_ctx_int_flags(ctx);
-       ret = s5p_mfc_set_dec_codec_buffers(ctx);
-       if (ret) {
-               mfc_info_ctx("isn't enough codec buffer size, re-alloc!\n");
-
-               if (dev->has_mmcache && dev->mmcache.is_on_status)
-                       s5p_mfc_invalidate_mmcache(dev);
-
-               s5p_mfc_release_codec_buffers(ctx);
-               ret = s5p_mfc_alloc_codec_buffers(ctx);
-               if (ret) {
-                       mfc_err_ctx("Failed to allocate decoding buffers\n");
-                       return ret;
-               }
-               ret = s5p_mfc_set_dec_codec_buffers(ctx);
-               if (ret) {
-                       mfc_err_ctx("Failed to alloc frame mem\n");
-                       return ret;
-               }
-       }
-
-       MFC_WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID);
-
-       if (sfr_dump & MFC_DUMP_DEC_INIT_BUFS)
-               call_dop(dev, dump_regs, dev);
-
-       s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_INIT_BUFFERS);
-
-       return ret;
-}
-
-int s5p_mfc_cmd_enc_init_buffers(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev;
-       int ret;
-
-       dev = ctx->dev;
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return -EINVAL;
-       }
-
-       /*
-        * Header was generated now starting processing
-        * First set the reference frame buffers
-        */
-       if (!ctx->codec_buffer_allocated) {
-               mfc_info_ctx("there isn't codec buffer, re-alloc!\n");
-               ret = s5p_mfc_alloc_codec_buffers(ctx);
-               if (ret) {
-                       mfc_err_ctx("Failed to allocate encoding buffers\n");
-                       return ret;
-               }
-       }
-
-       s5p_mfc_clean_ctx_int_flags(ctx);
-       ret = s5p_mfc_set_enc_codec_buffers(ctx);
-       if (ret) {
-               mfc_info_ctx("isn't enough codec buffer size, re-alloc!\n");
-
-               if (dev->has_mmcache && dev->mmcache.is_on_status)
-                       s5p_mfc_invalidate_mmcache(dev);
-
-               s5p_mfc_release_codec_buffers(ctx);
-               ret = s5p_mfc_alloc_codec_buffers(ctx);
-               if (ret) {
-                       mfc_err_ctx("Failed to allocate encoding buffers\n");
-                       return ret;
-               }
-               ret = s5p_mfc_set_enc_codec_buffers(ctx);
-               if (ret) {
-                       mfc_err_ctx("Failed to set enc codec buffers\n");
-                       return ret;
-               }
-       }
-
-       MFC_WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID);
-
-       if (sfr_dump & MFC_DUMP_ENC_INIT_BUFS)
-               call_dop(dev, dump_regs, dev);
-
-       s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_INIT_BUFFERS);
-
-       return ret;
-}
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_cmd.h b/drivers/media/platform/exynos/mfc/s5p_mfc_cmd.h
deleted file mode 100644 (file)
index 0455446..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_cmd.h
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __S5P_MFC_CMD_H
-#define __S5P_MFC_CMD_H __FILE__
-
-#include "s5p_mfc_common.h"
-
-int s5p_mfc_cmd_sys_init(struct s5p_mfc_dev *dev,
-                               enum mfc_buf_usage_type buf_type);
-void s5p_mfc_cmd_sleep(struct s5p_mfc_dev *dev);
-void s5p_mfc_cmd_wakeup(struct s5p_mfc_dev *dev);
-int s5p_mfc_cmd_open_inst(struct s5p_mfc_ctx *ctx);
-int s5p_mfc_cmd_close_inst(struct s5p_mfc_ctx *ctx);
-int s5p_mfc_cmd_dpb_flush(struct s5p_mfc_ctx *ctx);
-int s5p_mfc_cmd_cache_flush(struct s5p_mfc_dev *dev);
-int s5p_mfc_cmd_dec_init_buffers(struct s5p_mfc_ctx *ctx);
-int s5p_mfc_cmd_enc_init_buffers(struct s5p_mfc_ctx *ctx);
-
-#endif /* __S5P_MFC_CMD_H */
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_common.h b/drivers/media/platform/exynos/mfc/s5p_mfc_common.h
deleted file mode 100644 (file)
index 0a91906..0000000
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_common.h
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __S5P_MFC_COMMON_H
-#define __S5P_MFC_COMMON_H __FILE__
-
-#include <linux/exynos_iovmm.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/sched/clock.h>
-#include <linux/ion_exynos.h>
-#include <linux/dma-buf-container.h>
-#include <media/videobuf2-dma-sg.h>
-#include <asm/cacheflush.h>
-
-#include "s5p_mfc_regs_v10.h"
-#include "s5p_mfc_macros.h"
-#include "s5p_mfc_debug.h"
-#include "exynos_mfc_media.h"
-#include "s5p_mfc_data_struct.h"
-
-#define MFC_DRIVER_INFO                180315
-
-#define MFC_MAX_REF_BUFS       2
-#define MFC_FRAME_PLANES       2
-#define MFC_INFO_INIT_FD       -1
-
-#define MFC_MAX_DRM_CTX                2
-
-/* Interrupt timeout */
-#define MFC_INT_TIMEOUT                4000
-/* Interrupt short timeout */
-#define MFC_INT_SHORT_TIMEOUT  800
-/* hwlock timeout */
-#define MFC_HWLOCK_TIMEOUT     5000
-/* Busy wait timeout */
-#define MFC_BW_TIMEOUT         500
-/* MMCache invalidation timeout */
-#define MMCACHE_INVAL_TIMEOUT  1000
-/* Interrupt timeout count*/
-#define MFC_INT_TIMEOUT_CNT    2
-
-/* This value guarantees 299.4msec ~ 2.25sec according to MFC clock (668MHz ~ 89MHz)
- * releated with S5P_FIMV_DEC_TIMEOUT_VALUE */
-#define MFC_TIMEOUT_VALUE      200000000
-
-#define NUM_MPEG4_LF_BUF       2
-
-#define DEFAULT_TAG            (0xE05)
-
-#define MFC_NO_INSTANCE_SET    -1
-
-#define MFC_ENC_CAP_PLANE_COUNT        1
-#define MFC_ENC_OUT_PLANE_COUNT        2
-
-#define MFC_NAME_LEN           16
-#define MFC_FW_NAME            "mfc_fw.bin"
-
-#define STUFF_BYTE             4
-
-#define MFC_BASE_MASK          ((1 << 17) - 1)
-
-#define FLAG_LAST_FRAME                0x80000000
-#define FLAG_EMPTY_DATA                0x40000000
-#define FLAG_CSD               0x20000000
-
-/* MFC conceal color is black */
-#define MFC_CONCEAL_COLOR      0x8020000
-
-#define vb_to_mfc_buf(x)               \
-       container_of(x, struct s5p_mfc_buf, vb.vb2_buf)
-
-#define fh_to_mfc_ctx(x)               \
-       container_of(x, struct s5p_mfc_ctx, fh)
-
-#define call_bop(b, op, args...)       \
-       (b->op ? b->op(args) : 0)
-
-#define call_cop(c, op, args...)       \
-       (((c)->c_ops->op) ?             \
-               ((c)->c_ops->op(args)) : 0)
-
-#define call_dop(d, op, args...)       \
-       (((d)->dump_ops->op) ?          \
-               ((d)->dump_ops->op(args)) : 0)
-
-#define        MFC_CTRL_TYPE_GET       (MFC_CTRL_TYPE_GET_SRC | MFC_CTRL_TYPE_GET_DST)
-#define        MFC_CTRL_TYPE_SRC       (MFC_CTRL_TYPE_SET | MFC_CTRL_TYPE_GET_SRC)
-#define        MFC_CTRL_TYPE_DST       (MFC_CTRL_TYPE_GET_DST)
-
-#define MFC_FMT_STREAM         (1 << 0)
-#define MFC_FMT_FRAME          (1 << 1)
-#define MFC_FMT_10BIT          (1 << 2)
-#define MFC_FMT_422            (1 << 3)
-#define MFC_FMT_RGB            (1 << 4)
-
-/* node check */
-#define IS_DEC_NODE(n)         ((n == EXYNOS_VIDEONODE_MFC_DEC) ||     \
-                               (n == EXYNOS_VIDEONODE_MFC_DEC_DRM))
-#define IS_ENC_NODE(n)         ((n == EXYNOS_VIDEONODE_MFC_ENC) ||     \
-                               (n == EXYNOS_VIDEONODE_MFC_ENC_DRM) ||  \
-                               (n == EXYNOS_VIDEONODE_MFC_ENC_OTF) ||  \
-                               (n == EXYNOS_VIDEONODE_MFC_ENC_OTF_DRM))
-
-/* Decoder codec mode check */
-#define IS_H264_DEC(ctx)       ((ctx)->codec_mode == S5P_FIMV_CODEC_H264_DEC)
-#define IS_H264_MVC_DEC(ctx)   ((ctx)->codec_mode == S5P_FIMV_CODEC_H264_MVC_DEC)
-#define IS_MPEG4_DEC(ctx)      ((ctx)->codec_mode == S5P_FIMV_CODEC_MPEG4_DEC)
-#define IS_FIMV1_DEC(ctx)      ((ctx)->codec_mode == S5P_FIMV_CODEC_FIMV1_DEC)
-#define IS_FIMV2_DEC(ctx)      ((ctx)->codec_mode == S5P_FIMV_CODEC_FIMV2_DEC)
-#define IS_FIMV3_DEC(ctx)      ((ctx)->codec_mode == S5P_FIMV_CODEC_FIMV3_DEC)
-#define IS_FIMV4_DEC(ctx)      ((ctx)->codec_mode == S5P_FIMV_CODEC_FIMV4_DEC)
-#define IS_VC1_DEC(ctx)                ((ctx)->codec_mode == S5P_FIMV_CODEC_VC1_DEC)
-#define IS_VC1_RCV_DEC(ctx)    ((ctx)->codec_mode == S5P_FIMV_CODEC_VC1_RCV_DEC)
-#define IS_MPEG2_DEC(ctx)      ((ctx)->codec_mode == S5P_FIMV_CODEC_MPEG2_DEC)
-#define IS_HEVC_DEC(ctx)       ((ctx)->codec_mode == S5P_FIMV_CODEC_HEVC_DEC)
-#define IS_VP9_DEC(ctx)                ((ctx)->codec_mode == S5P_FIMV_CODEC_VP9_DEC)
-#define IS_BPG_DEC(ctx)                ((ctx)->codec_mode == S5P_FIMV_CODEC_BPG_DEC)
-
-/* Encoder codec mode check */
-#define IS_H264_ENC(ctx)       ((ctx)->codec_mode == S5P_FIMV_CODEC_H264_ENC)
-#define IS_MPEG4_ENC(ctx)      ((ctx)->codec_mode == S5P_FIMV_CODEC_MPEG4_ENC)
-#define IS_H263_ENC(ctx)       ((ctx)->codec_mode == S5P_FIMV_CODEC_H263_ENC)
-#define IS_VP8_ENC(ctx)                ((ctx)->codec_mode == S5P_FIMV_CODEC_VP8_ENC)
-#define IS_HEVC_ENC(ctx)       ((ctx)->codec_mode == S5P_FIMV_CODEC_HEVC_ENC)
-#define IS_VP9_ENC(ctx)                ((ctx)->codec_mode == S5P_FIMV_CODEC_VP9_ENC)
-#define IS_BPG_ENC(ctx)                ((ctx)->codec_mode == S5P_FIMV_CODEC_BPG_ENC)
-
-#define CODEC_NOT_CODED(ctx)   (IS_MPEG4_DEC(ctx) || IS_VC1_DEC(ctx) || IS_VC1_RCV_DEC(ctx))
-#define CODEC_INTERLACED(ctx)  (IS_H264_DEC(ctx) || IS_H264_MVC_DEC(ctx) ||    \
-                               IS_MPEG2_DEC(ctx) || IS_MPEG4_DEC(ctx) ||       \
-                               IS_VC1_DEC(ctx) || IS_VC1_RCV_DEC(ctx))
-#define CODEC_MBAFF(ctx)       (IS_H264_DEC(ctx) || IS_H264_MVC_DEC(ctx))
-#define CODEC_MULTIFRAME(ctx)  (IS_MPEG4_DEC(ctx) || IS_VP9_DEC(ctx) ||        \
-                               IS_FIMV2_DEC(ctx) || IS_FIMV3_DEC(ctx) || IS_FIMV4_DEC(ctx))
-#define CODEC_10BIT(ctx)       (IS_HEVC_DEC(ctx) || IS_HEVC_ENC(ctx) ||        \
-                               IS_VP9_DEC(ctx) || IS_VP9_ENC(ctx) ||           \
-                               IS_BPG_DEC(ctx) || IS_BPG_ENC(ctx))
-#define CODEC_422FORMAT(ctx)   (IS_HEVC_DEC(ctx) || IS_HEVC_ENC(ctx) ||        \
-                               IS_VP9_DEC(ctx) || IS_VP9_ENC(ctx) ||           \
-                               IS_BPG_DEC(ctx) || IS_BPG_ENC(ctx))
-#define ON_RES_CHANGE(ctx)     (((ctx)->state >= MFCINST_RES_CHANGE_INIT) &&   \
-                                ((ctx)->state <= MFCINST_RES_CHANGE_END))
-
-#define IS_BUFFER_BATCH_MODE(ctx)      ((ctx)->batch_mode == 1)
-
-/* UHD resoluition */
-#define MFC_UHD_RES            (3840 * 2160)
-#define IS_UHD_RES(ctx)                (((ctx)->crop_width * (ctx)->crop_height) == MFC_UHD_RES)
-#define OVER_UHD_ENC60(ctx)    ((((ctx)->crop_width * (ctx)->crop_height) == MFC_UHD_RES) && \
-                               ((ctx)->type == MFCINST_ENCODER) &&     \
-                               ((ctx)->framerate / 1000) >= 60)
-
-/* Extra information for Decoder */
-#define        DEC_SET_DUAL_DPB                (1 << 0)
-#define        DEC_SET_DYNAMIC_DPB             (1 << 1)
-#define        DEC_SET_LAST_FRAME_INFO         (1 << 2)
-#define        DEC_SET_SKYPE_FLAG              (1 << 3)
-
-/* Extra information for Encoder */
-#define        ENC_SET_RGB_INPUT               (1 << 0)
-#define        ENC_SET_SPARE_SIZE              (1 << 1)
-#define        ENC_SET_TEMP_SVC_CH             (1 << 2)
-#define        ENC_SET_SKYPE_FLAG              (1 << 3)
-#define        ENC_SET_ROI_CONTROL             (1 << 4)
-#define        ENC_SET_QP_BOUND_PB             (1 << 5)
-#define        ENC_SET_FIXED_SLICE             (1 << 6)
-#define        ENC_SET_PVC_MODE                (1 << 7)
-#define        ENC_SET_RATIO_OF_INTRA          (1 << 8)
-#define        ENC_SET_COLOR_ASPECT            (1 << 9)
-#define        ENC_SET_HP_BITRATE_CONTROL      (1 << 10)
-#define        ENC_SET_STATIC_INFO             (1 << 11)
-
-#define MFC_VER_MAJOR(dev)     ((dev->pdata->ip_ver >> 8) & 0xFF)
-#define MFC_VER_MINOR(dev)     (dev->pdata->ip_ver & 0xFF)
-
-#define MFC_FEATURE_SUPPORT(dev, f)    ((f).support && ((dev)->fw.date >= (f).version))
-
-/* Low memory check */
-#define IS_LOW_MEM                     (totalram_pages <= ((SZ_1G + SZ_512M) >> PAGE_SHIFT))
-#define SZ_600M                                (6 * 1024 * 1024)
-
-#endif /* __S5P_MFC_COMMON_H */
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_ctrl.c b/drivers/media/platform/exynos/mfc/s5p_mfc_ctrl.c
deleted file mode 100644 (file)
index 0736d05..0000000
+++ /dev/null
@@ -1,367 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_ctrl.c
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include "s5p_mfc_ctrl.h"
-
-#include "s5p_mfc_hwlock.h"
-#include "s5p_mfc_nal_q.h"
-#include "s5p_mfc_sync.h"
-
-#include "s5p_mfc_pm.h"
-#include "s5p_mfc_cmd.h"
-#include "s5p_mfc_cal.h"
-#include "s5p_mfc_reg.h"
-
-#include "s5p_mfc_utils.h"
-
-/* Initialize hardware */
-static int mfc_init_hw(struct s5p_mfc_dev *dev, enum mfc_buf_usage_type buf_type)
-{
-       int fw_ver;
-       int ret = 0;
-       int curr_ctx_is_drm_backup;
-
-       mfc_debug_enter();
-
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return -EINVAL;
-       }
-
-       curr_ctx_is_drm_backup = dev->curr_ctx_is_drm;
-
-       if (!dev->fw_buf.dma_buf)
-               return -EINVAL;
-
-       /* 0. MFC reset */
-       mfc_debug(2, "MFC reset...\n");
-
-       /* At init time, do not call secure API */
-       if (buf_type == MFCBUF_NORMAL)
-               dev->curr_ctx_is_drm = 0;
-       else if (buf_type == MFCBUF_DRM)
-               dev->curr_ctx_is_drm = 1;
-
-       ret = s5p_mfc_pm_clock_on(dev);
-       if (ret) {
-               mfc_err_dev("Failed to enable clock before reset(%d)\n", ret);
-               dev->curr_ctx_is_drm = curr_ctx_is_drm_backup;
-               return ret;
-       }
-
-       ret = s5p_mfc_reset_mfc(dev);
-       if (ret) {
-               mfc_err_dev("Failed to reset MFC - timeout\n");
-               goto err_init_hw;
-       }
-       mfc_debug(2, "Done MFC reset...\n");
-
-       /* 1. Set DRAM base Addr */
-       s5p_mfc_set_risc_base_addr(dev, buf_type);
-
-       /* 2. Release reset signal to the RISC */
-       s5p_mfc_risc_on(dev);
-
-       mfc_debug(2, "Will now wait for completion of firmware transfer\n");
-       if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_FW_STATUS_RET)) {
-               mfc_err_dev("Failed to RISC_ON\n");
-               s5p_mfc_clean_dev_int_flags(dev);
-               ret = -EIO;
-               goto err_init_hw;
-       }
-
-       /* 3. Initialize firmware */
-       ret = s5p_mfc_cmd_sys_init(dev, buf_type);
-       if (ret) {
-               mfc_err_dev("Failed to send command to MFC - timeout\n");
-               goto err_init_hw;
-       }
-
-       mfc_debug(2, "Ok, now will write a command to init the system\n");
-       if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_SYS_INIT_RET)) {
-               mfc_err_dev("Failed to SYS_INIT\n");
-               s5p_mfc_clean_dev_int_flags(dev);
-               ret = -EIO;
-               goto err_init_hw;
-       }
-
-       dev->int_condition = 0;
-       if (dev->int_err != 0 || dev->int_reason != S5P_FIMV_R2H_CMD_SYS_INIT_RET) {
-               /* Failure. */
-               mfc_err_dev("Failed to init firmware - error: %d, int: %d\n",
-                               dev->int_err, dev->int_reason);
-               ret = -EIO;
-               goto err_init_hw;
-       }
-
-       dev->fw.fimv_info = s5p_mfc_get_fimv_info();
-       if (dev->fw.fimv_info != 'D' && dev->fw.fimv_info != 'E')
-               dev->fw.fimv_info = 'N';
-
-       mfc_info_dev("[F/W] MFC v%x.%x, %02xyy %02xmm %02xdd (%c)\n",
-                MFC_VER_MAJOR(dev),
-                MFC_VER_MINOR(dev),
-                s5p_mfc_get_fw_ver_year(),
-                s5p_mfc_get_fw_ver_month(),
-                s5p_mfc_get_fw_ver_date(),
-                dev->fw.fimv_info);
-
-       dev->fw.date = s5p_mfc_get_fw_ver_all();
-       /* Check MFC version and F/W version */
-       fw_ver = s5p_mfc_get_mfc_version();
-       if (fw_ver != dev->pdata->ip_ver) {
-               mfc_err_dev("Invalid F/W version(0x%x) for MFC H/W(0x%x)\n",
-                               fw_ver, dev->pdata->ip_ver);
-               ret = -EIO;
-               goto err_init_hw;
-       }
-
-#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
-       /* Cache flush for base address change */
-       s5p_mfc_cmd_cache_flush(dev);
-       if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_CACHE_FLUSH_RET)) {
-               mfc_err_dev("Failed to CACHE_FLUSH\n");
-               s5p_mfc_clean_dev_int_flags(dev);
-               ret = -EIO;
-               goto err_init_hw;
-       }
-
-       if (buf_type == MFCBUF_DRM && !curr_ctx_is_drm_backup) {
-               s5p_mfc_pm_clock_off(dev);
-               dev->curr_ctx_is_drm = curr_ctx_is_drm_backup;
-               s5p_mfc_pm_clock_on_with_base(dev, MFCBUF_NORMAL);
-       }
-#endif
-
-err_init_hw:
-       s5p_mfc_pm_clock_off(dev);
-       dev->curr_ctx_is_drm = curr_ctx_is_drm_backup;
-       mfc_debug_leave();
-
-       return ret;
-}
-
-/* Wrapper : Initialize hardware */
-int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
-{
-       int ret;
-
-       ret = mfc_init_hw(dev, MFCBUF_NORMAL);
-       if (ret)
-               return ret;
-
-#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
-       if (dev->fw.drm_status) {
-               ret = mfc_init_hw(dev, MFCBUF_DRM);
-               if (ret)
-                       return ret;
-       }
-#endif
-
-       return ret;
-}
-
-/* Deinitialize hardware */
-void s5p_mfc_deinit_hw(struct s5p_mfc_dev *dev)
-{
-       int ret;
-
-       mfc_debug(2, "mfc deinit start\n");
-
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return;
-       }
-
-       ret = s5p_mfc_pm_clock_on(dev);
-       if (ret) {
-               mfc_err_dev("Failed to enable clock before reset(%d)\n", ret);
-               return;
-       }
-
-       s5p_mfc_mfc_off(dev);
-
-       s5p_mfc_pm_clock_off(dev);
-
-       mfc_debug(2, "mfc deinit completed\n");
-}
-
-int s5p_mfc_sleep(struct s5p_mfc_dev *dev)
-{
-       struct s5p_mfc_ctx *ctx;
-       int ret;
-       int old_state, i;
-       int need_cache_flush = 0;
-
-       mfc_debug_enter();
-
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return -EINVAL;
-       }
-
-       ctx = dev->ctx[dev->curr_ctx];
-       if (!ctx) {
-               for (i = 0; i < MFC_NUM_CONTEXTS; i++) {
-                       if (dev->ctx[i]) {
-                               ctx = dev->ctx[i];
-                               break;
-                       }
-               }
-               if (!ctx) {
-                       mfc_err_dev("no mfc context to run\n");
-                       return -EINVAL;
-               } else {
-                       mfc_info_dev("ctx is changed %d -> %d\n",
-                                       dev->curr_ctx, ctx->num);
-                       dev->curr_ctx = ctx->num;
-                       if (dev->curr_ctx_is_drm != ctx->is_drm) {
-                               need_cache_flush = 1;
-                               mfc_info_dev("DRM attribute is changed %d->%d\n",
-                                               dev->curr_ctx_is_drm, ctx->is_drm);
-                       }
-               }
-       }
-       old_state = ctx->state;
-       s5p_mfc_change_state(ctx, MFCINST_ABORT);
-       MFC_TRACE_DEV_HWLOCK("**sleep (ctx:%d)\n", ctx->num);
-       ret = s5p_mfc_get_hwlock_dev(dev);
-       if (ret < 0) {
-               mfc_err_dev("Failed to get hwlock\n");
-               mfc_err_dev("dev.hwlock.dev = 0x%lx, bits = 0x%lx, owned_by_irq = %d, wl_count = %d, transfer_owner = %d\n",
-                               dev->hwlock.dev, dev->hwlock.bits, dev->hwlock.owned_by_irq,
-                               dev->hwlock.wl_count, dev->hwlock.transfer_owner);
-               return -EBUSY;
-       }
-
-       mfc_info_dev("curr_ctx_is_drm:%d, hwlock.bits:%lu, hwlock.dev:%lu\n",
-                       dev->curr_ctx_is_drm, dev->hwlock.bits, dev->hwlock.dev);
-
-       s5p_mfc_change_state(ctx, old_state);
-       s5p_mfc_pm_clock_on(dev);
-
-       if (need_cache_flush)
-               s5p_mfc_cache_flush(dev, ctx->is_drm);
-
-       s5p_mfc_cmd_sleep(dev);
-
-       if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_SLEEP_RET)) {
-               mfc_err_dev("Failed to SLEEP\n");
-               dev->logging_data->cause |= (1 << MFC_CAUSE_FAIL_SLEEP);
-               call_dop(dev, dump_and_stop_always, dev);
-               return -EIO;
-       }
-
-       dev->int_condition = 0;
-       if (dev->int_err != 0 || dev->int_reason != S5P_FIMV_R2H_CMD_SLEEP_RET) {
-               /* Failure. */
-               mfc_err_dev("Failed to sleep - error: %d, int: %d\n",
-                               dev->int_err, dev->int_reason);
-               ret = -EIO;
-               goto err_mfc_sleep;
-       }
-
-       dev->sleep = 1;
-
-err_mfc_sleep:
-       s5p_mfc_mfc_off(dev);
-       s5p_mfc_pm_clock_off(dev);
-       s5p_mfc_release_hwlock_dev(dev);
-       mfc_debug_leave();
-
-       return ret;
-}
-
-int s5p_mfc_wakeup(struct s5p_mfc_dev *dev)
-{
-       enum mfc_buf_usage_type buf_type;
-       int ret = 0;
-
-       mfc_debug_enter();
-
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return -EINVAL;
-       }
-       mfc_info_dev("curr_ctx_is_drm:%d\n", dev->curr_ctx_is_drm);
-
-       MFC_TRACE_DEV_HWLOCK("**wakeup\n");
-       ret = s5p_mfc_get_hwlock_dev(dev);
-       if (ret < 0) {
-               mfc_err_dev("Failed to get hwlock\n");
-               mfc_err_dev("dev.hwlock.dev = 0x%lx, bits = 0x%lx, owned_by_irq = %d, wl_count = %d, transfer_owner = %d\n",
-                               dev->hwlock.dev, dev->hwlock.bits, dev->hwlock.owned_by_irq,
-                               dev->hwlock.wl_count, dev->hwlock.transfer_owner);
-               return -EBUSY;
-       }
-
-       dev->sleep = 0;
-
-       /* 0. MFC reset */
-       mfc_debug(2, "MFC reset...\n");
-
-       s5p_mfc_pm_clock_on(dev);
-
-       ret = s5p_mfc_reset_mfc(dev);
-       if (ret) {
-               mfc_err_dev("Failed to reset MFC - timeout\n");
-               goto err_mfc_wakeup;
-       }
-       mfc_debug(2, "Done MFC reset...\n");
-       if (dev->curr_ctx_is_drm)
-               buf_type = MFCBUF_DRM;
-       else
-               buf_type = MFCBUF_NORMAL;
-
-       /* 1. Set DRAM base Addr */
-       s5p_mfc_set_risc_base_addr(dev, buf_type);
-
-       /* 2. Release reset signal to the RISC */
-       s5p_mfc_risc_on(dev);
-
-       mfc_debug(2, "Will now wait for completion of firmware transfer\n");
-       if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_FW_STATUS_RET)) {
-               mfc_err_dev("Failed to RISC_ON\n");
-               dev->logging_data->cause |= (1 << MFC_CAUSE_FAIL_RISC_ON);
-               call_dop(dev, dump_and_stop_always, dev);
-               return -EIO;
-       }
-
-       mfc_debug(2, "Ok, now will write a command to wakeup the system\n");
-       s5p_mfc_cmd_wakeup(dev);
-
-       mfc_debug(2, "Will now wait for completion of firmware wake up\n");
-       if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_WAKEUP_RET)) {
-               mfc_err_dev("Failed to WAKEUP\n");
-               dev->logging_data->cause |= (1 << MFC_CAUSE_FAIL_WAKEUP);
-               call_dop(dev, dump_and_stop_always, dev);
-               return -EIO;
-       }
-
-       dev->int_condition = 0;
-       if (dev->int_err != 0 || dev->int_reason != S5P_FIMV_R2H_CMD_WAKEUP_RET) {
-               /* Failure. */
-               mfc_err_dev("Failed to wakeup - error: %d, int: %d\n",
-                               dev->int_err, dev->int_reason);
-               ret = -EIO;
-               goto err_mfc_wakeup;
-       }
-
-err_mfc_wakeup:
-       s5p_mfc_pm_clock_off(dev);
-
-       s5p_mfc_release_hwlock_dev(dev);
-
-       mfc_debug_leave();
-
-       return ret;
-}
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_ctrl.h b/drivers/media/platform/exynos/mfc/s5p_mfc_ctrl.h
deleted file mode 100644 (file)
index 600083f..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_ctrl.h
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __S5P_MFC_CTRL_H
-#define __S5P_MFC_CTRL_H __FILE__
-
-#include "s5p_mfc_common.h"
-
-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);
-
-#endif /* __S5P_MFC_CTRL_H */
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_data_struct.h b/drivers/media/platform/exynos/mfc/s5p_mfc_data_struct.h
deleted file mode 100644 (file)
index be5790f..0000000
+++ /dev/null
@@ -1,1408 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_data_struct.h
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __S5P_MFC_DATA_STRUCT_H
-#define __S5P_MFC_DATA_STRUCT_H __FILE__
-
-#ifdef CONFIG_ARM_EXYNOS_DEVFREQ
-#define CONFIG_MFC_USE_BUS_DEVFREQ
-#endif
-
-#ifdef CONFIG_MFC_USE_BUS_DEVFREQ
-#include <linux/pm_qos.h>
-#endif
-#ifdef CONFIG_EXYNOS_BTS
-#include <soc/samsung/bts.h>
-#endif
-#include <linux/videodev2.h>
-#ifdef CONFIG_EXYNOS_ITMON
-#include <soc/samsung/exynos-itmon.h>
-#endif
-
-#include <media/v4l2-device.h>
-#include <media/v4l2-ioctl.h>
-#include <media/videobuf2-v4l2.h>
-
-#include "exynos_mfc_media.h"
-
-#define MFC_NUM_CONTEXTS               32
-#define MFC_MAX_PLANES                 3
-#define MFC_MAX_DPBS                   32
-#define MFC_MAX_BUFFERS                        32
-#define MFC_MAX_EXTRA_BUF              10
-#define MFC_TIME_INDEX                 15
-#define MFC_SFR_LOGGING_COUNT_SET1     4
-#define MFC_SFR_LOGGING_COUNT_SET2     23
-#define MFC_LOGGING_DATA_SIZE          256
-#define MFC_MAX_DEFAULT_PARAM          100
-
-#define HWFC_MAX_BUF                   10
-#define OTF_MAX_BUF                    30
-
-/* Maximum number of temporal layers */
-#define VIDEO_MAX_TEMPORAL_LAYERS      7
-
-#define MAX_NUM_IMAGES_IN_VB           8
-#define MAX_NUM_BUFCON_BUFS            32
-#define MAX_NUM_CLUSTER                        3
-
-/*
- *  MFC region id for smc
- */
-enum {
-       FC_MFC_EXYNOS_ID_MFC_SH        = 0,
-       FC_MFC_EXYNOS_ID_VIDEO         = 1,
-       FC_MFC_EXYNOS_ID_MFC_FW        = 2,
-       FC_MFC_EXYNOS_ID_SECTBL        = 3,
-       FC_MFC_EXYNOS_ID_G2D_WFD       = 4,
-       FC_MFC_EXYNOS_ID_MFC_NFW       = 5,
-       FC_MFC_EXYNOS_ID_VIDEO_EXT     = 6,
-};
-
-/**
- * enum s5p_mfc_inst_type - The type of an MFC device node.
- */
-enum s5p_mfc_node_type {
-       MFCNODE_INVALID = -1,
-       MFCNODE_DECODER = 0,
-       MFCNODE_ENCODER = 1,
-       MFCNODE_DECODER_DRM = 2,
-       MFCNODE_ENCODER_DRM = 3,
-       MFCNODE_ENCODER_OTF = 4,
-       MFCNODE_ENCODER_OTF_DRM = 5,
-};
-
-/**
- * enum s5p_mfc_inst_type - The type of an MFC instance.
- */
-enum s5p_mfc_inst_type {
-       MFCINST_INVALID = 0,
-       MFCINST_DECODER = 1,
-       MFCINST_ENCODER = 2,
-};
-
-/**
- * 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_RUNNING_BUF_FULL,
-       MFCINST_RUNNING,
-       MFCINST_FINISHING,
-       MFCINST_RETURN_INST,
-       MFCINST_ERROR,
-       MFCINST_ABORT,
-       MFCINST_RES_CHANGE_INIT,
-       MFCINST_RES_CHANGE_FLUSH,
-       MFCINST_RES_CHANGE_END,
-       MFCINST_RUNNING_NO_OUTPUT, // Unused
-       MFCINST_ABORT_INST,
-       MFCINST_DPB_FLUSHING,
-       MFCINST_SPECIAL_PARSING,
-       MFCINST_SPECIAL_PARSING_NAL,
-};
-
-/**
- * enum s5p_mfc_queue_state - The state of buffer queue.
- */
-enum s5p_mfc_queue_state {
-       QUEUE_FREE = 0,
-       QUEUE_BUFS_REQUESTED,
-       QUEUE_BUFS_QUERIED,
-       QUEUE_BUFS_MMAPED,
-};
-
-enum mfc_dec_wait_state {
-       WAIT_NONE = 0,
-       WAIT_DECODING,
-       WAIT_INITBUF_DONE,
-};
-
-/**
- * enum s5p_mfc_check_state - The state for user notification
- */
-enum s5p_mfc_check_state {
-       MFCSTATE_PROCESSING = 0,
-       MFCSTATE_DEC_RES_DETECT,
-       MFCSTATE_DEC_TERMINATING,
-       MFCSTATE_ENC_NO_OUTPUT,
-       MFCSTATE_DEC_S3D_REALLOC,
-};
-
-enum mfc_buf_usage_type {
-       MFCBUF_INVALID = 0,
-       MFCBUF_NORMAL,
-       MFCBUF_DRM,
-       MFCBUF_NORMAL_FW,
-       MFCBUF_DRM_FW,
-};
-
-enum mfc_buf_process_type {
-       MFCBUFPROC_DEFAULT              = 0x0,
-       MFCBUFPROC_COPY                 = (1 << 0),
-       MFCBUFPROC_SHARE                = (1 << 1),
-       MFCBUFPROC_META                 = (1 << 2),
-       MFCBUFPROC_ANBSHARE             = (1 << 3),
-       MFCBUFPROC_ANBSHARE_NV12L       = (1 << 4),
-};
-
-enum s5p_mfc_ctrl_type {
-       MFC_CTRL_TYPE_GET_SRC   = 0x1,
-       MFC_CTRL_TYPE_GET_DST   = 0x2,
-       MFC_CTRL_TYPE_SET       = 0x4,
-};
-
-enum s5p_mfc_ctrl_mode {
-       MFC_CTRL_MODE_NONE      = 0x0,
-       MFC_CTRL_MODE_SFR       = 0x1,
-       MFC_CTRL_MODE_CST       = 0x2,
-};
-
-struct s5p_mfc_ctx;
-
-enum s5p_mfc_debug_cause {
-       MFC_CAUSE_0WRITE_PAGE_FAULT             = 0,
-       MFC_CAUSE_0READ_PAGE_FAULT              = 1,
-       MFC_CAUSE_1WRITE_PAGE_FAULT             = 2,
-       MFC_CAUSE_1READ_PAGE_FAULT              = 3,
-       MFC_CAUSE_NO_INTERRUPT                  = 4,
-       MFC_CAUSE_NO_SCHEDULING                 = 5,
-       MFC_CAUSE_FAIL_STOP_NAL_Q               = 6,
-       MFC_CAUSE_FAIL_STOP_NAL_Q_FOR_OTHER     = 7,
-       MFC_CAUSE_FAIL_CLOSE_INST               = 8,
-       MFC_CAUSE_FAIL_SLEEP                    = 9,
-       MFC_CAUSE_FAIL_WAKEUP                   = 10,
-       MFC_CAUSE_FAIL_RISC_ON                  = 11,
-       MFC_CAUSE_FAIL_DPB_FLUSH                = 12,
-       MFC_CAUSE_FAIL_CHACHE_FLUSH             = 13,
-};
-
-struct s5p_mfc_debug {
-       u32     cause;
-       u8      fault_status;
-       u32     fault_trans_info;
-       u32     fault_addr;
-       u8      SFRs_set1[MFC_SFR_LOGGING_COUNT_SET1];
-       u32     SFRs_set2[MFC_SFR_LOGGING_COUNT_SET2];
-       char    errorinfo[MFC_LOGGING_DATA_SIZE];
-};
-
-/**
- * struct s5p_mfc_buf - MFC buffer
- *
- */
-struct s5p_mfc_buf {
-       struct vb2_v4l2_buffer vb;
-       struct list_head list;
-       dma_addr_t addr[MAX_NUM_IMAGES_IN_VB][MFC_MAX_PLANES];
-       struct dma_buf *dmabufs[MAX_NUM_IMAGES_IN_VB][MFC_MAX_PLANES];
-       struct dma_buf_attachment *attachments[MAX_NUM_IMAGES_IN_VB][MFC_MAX_PLANES];
-       int next_index;
-       int done_index;
-       int used;
-       int num_bufs_in_batch;
-       int num_valid_bufs;
-       unsigned char *vir_addr;
-};
-
-struct s5p_mfc_buf_queue {
-       struct list_head head;
-       unsigned int count;
-};
-
-struct s5p_mfc_bits {
-       unsigned long bits;
-       spinlock_t lock;
-};
-
-struct s5p_mfc_hwlock {
-       struct list_head waiting_list;
-       unsigned int wl_count;
-       unsigned long bits;
-       unsigned long dev;
-       unsigned int owned_by_irq;
-       unsigned int transfer_owner;
-       spinlock_t lock;
-};
-
-struct s5p_mfc_listable_wq {
-       struct list_head list;
-       wait_queue_head_t wait_queue;
-       struct mutex wait_mutex;
-       struct s5p_mfc_dev *dev;
-       struct s5p_mfc_ctx *ctx;
-};
-
-struct s5p_mfc_pm {
-       struct clk      *clock;
-       atomic_t        pwr_ref;
-       struct device   *device;
-       spinlock_t      clklock;
-
-       int clock_on_steps;
-       int clock_off_steps;
-       enum mfc_buf_usage_type base_type;
-};
-
-struct s5p_mfc_fw {
-       int             date;
-       int             fimv_info;
-       size_t          size;
-       int             status;
-       int             drm_status;
-};
-
-struct s5p_mfc_ctx_buf_size {
-       size_t dev_ctx;
-       size_t h264_dec_ctx;
-       size_t other_dec_ctx;
-       size_t h264_enc_ctx;
-       size_t hevc_enc_ctx;
-       size_t other_enc_ctx;
-       size_t shared_buf;
-       size_t dbg_info_buf;
-};
-
-struct s5p_mfc_buf_size {
-       size_t firmware_code;
-       unsigned int cpb_buf;
-       void *ctx_buf;
-};
-
-struct s5p_mfc_variant {
-       struct s5p_mfc_buf_size *buf_size;
-       int     num_entities;
-};
-
-enum mfc_sfr_dump_type {
-       MFC_DUMP_NONE                   = 0,
-       MFC_DUMP_DEC_SEQ_START          = (1 << 0),
-       MFC_DUMP_DEC_INIT_BUFS          = (1 << 1),
-       MFC_DUMP_DEC_NAL_START          = (1 << 2),
-       MFC_DUMP_ENC_SEQ_START          = (1 << 3),
-       MFC_DUMP_ENC_INIT_BUFS          = (1 << 4),
-       MFC_DUMP_ENC_NAL_START          = (1 << 5),
-       MFC_DUMP_ERR_INT                = (1 << 6),
-       MFC_DUMP_WARN_INT               = (1 << 7),
-};
-
-struct s5p_mfc_debugfs {
-       struct dentry *root;
-       struct dentry *mfc_info;
-       struct dentry *debug_info;
-       struct dentry *debug_level;
-       struct dentry *debug_ts;
-       struct dentry *dbg_enable;
-       struct dentry *nal_q_dump;
-       struct dentry *nal_q_disable;
-       struct dentry *nal_q_parallel_disable;
-       struct dentry *otf_dump;
-       struct dentry *perf_measure_option;
-       struct dentry *sfr_dump;
-       struct dentry *mmcache_dump;
-       struct dentry *mmcache_disable;
-       struct dentry *perf_boost_mode;
-};
-
-/**
- * struct s5p_mfc_special_buf - represents internal used buffer
- * @daddr:             device virtual address
- * @virt:              kernel virtual address, only valid when the
- *                     buffer accessed by driver
- */
-struct s5p_mfc_special_buf {
-       enum mfc_buf_usage_type         buftype;
-       struct dma_buf                  *dma_buf;
-       struct dma_buf_attachment       *attachment;
-       struct sg_table                 *sgt;
-       dma_addr_t                      daddr;
-       void                            *vaddr;
-       size_t                          size;
-};
-
-#ifdef CONFIG_MFC_USE_BUS_DEVFREQ
-struct mfc_qos_bw_data {
-       unsigned long   peak;
-       unsigned long   read;
-       unsigned long   write;
-};
-
-struct s5p_mfc_qos_bw {
-       struct mfc_qos_bw_data h264_dec_uhd_bw;
-       struct mfc_qos_bw_data hevc_dec_uhd_bw;
-       struct mfc_qos_bw_data hevc_dec_uhd_10bit_bw;
-       struct mfc_qos_bw_data vp8_dec_uhd_bw;
-       struct mfc_qos_bw_data vp9_dec_uhd_bw;
-       struct mfc_qos_bw_data mpeg4_dec_uhd_bw;
-       struct mfc_qos_bw_data h264_enc_uhd_bw;
-       struct mfc_qos_bw_data hevc_enc_uhd_bw;
-       struct mfc_qos_bw_data hevc_enc_uhd_10bit_bw;
-       struct mfc_qos_bw_data vp8_enc_uhd_bw;
-       struct mfc_qos_bw_data vp9_enc_uhd_bw;
-       struct mfc_qos_bw_data mpeg4_enc_uhd_bw;
-};
-
-/*
- * threshold_mb - threshold of total MB(macroblock) count
- * Total MB count can be calculated by
- *     (MB of width) * (MB of height) * fps
- */
-struct s5p_mfc_qos {
-       unsigned int threshold_mb;
-       unsigned int freq_mfc;
-       unsigned int freq_int;
-       unsigned int freq_mif;
-       unsigned int mo_value;
-       unsigned int mo_10bit_value;
-       unsigned int mo_uhd_enc60_value;
-       unsigned int time_fw;
-};
-
-struct s5p_mfc_qos_boost {
-       unsigned int num_cluster;
-       unsigned int freq_mfc;
-       unsigned int freq_int;
-       unsigned int freq_mif;
-       unsigned int freq_cluster[MAX_NUM_CLUSTER];
-};
-#endif
-
-struct s5p_mfc_feature {
-       unsigned int support;
-       unsigned int version;
-};
-
-struct s5p_mfc_platdata {
-       /* MFC version */
-       unsigned int ip_ver;
-       /* Debug mode */
-       unsigned int debug_mode;
-       /* Sysmmu check */
-       unsigned int share_sysmmu;
-       unsigned int axid_mask;
-       unsigned int mfc_fault_num;
-       /* Features */
-       struct s5p_mfc_feature nal_q;
-       struct s5p_mfc_feature skype;
-       struct s5p_mfc_feature black_bar;
-       struct s5p_mfc_feature color_aspect_dec;
-       struct s5p_mfc_feature static_info_dec;
-       struct s5p_mfc_feature color_aspect_enc;
-       struct s5p_mfc_feature static_info_enc;
-       /* Default 10bit format for decoding */
-       unsigned int P010_decoding;
-       /* Formats */
-       unsigned int support_10bit;
-       unsigned int support_422;
-       unsigned int support_rgb;
-       /* Encoder default parameter */
-       unsigned int enc_param_num;
-       unsigned int enc_param_addr[MFC_MAX_DEFAULT_PARAM];
-       unsigned int enc_param_val[MFC_MAX_DEFAULT_PARAM];
-#ifdef CONFIG_MFC_USE_BUS_DEVFREQ
-       /* QoS */
-       unsigned int num_qos_steps;
-       unsigned int max_qos_steps;
-       unsigned int max_mb;
-       unsigned int mfc_freq_control;
-       unsigned int mo_control;
-       unsigned int bw_control;
-       struct s5p_mfc_qos *qos_table;
-       struct s5p_mfc_qos_boost *qos_boost_table;
-#endif
-};
-
-/************************ NAL_Q data structure ************************/
-#define NAL_Q_IN_ENTRY_SIZE            256
-#define NAL_Q_OUT_ENTRY_SIZE           256
-
-#define NAL_Q_IN_DEC_STR_SIZE          112
-#define NAL_Q_IN_ENC_STR_SIZE          204
-#define NAL_Q_OUT_DEC_STR_SIZE         248
-#define NAL_Q_OUT_ENC_STR_SIZE         64
-
-/* 256*128(max instance 32 * slot 4) = 32 kbytes */
-#define NAL_Q_IN_QUEUE_SIZE            128
-#define NAL_Q_OUT_QUEUE_SIZE           128
-
-typedef struct __DecoderInputStr {
-       int StartCode; /* = 0xAAAAAAAA; Decoder input structure marker */
-       int CommandId;
-       int InstanceId;
-       int PictureTag;
-       unsigned int CpbBufferAddr;
-       int CpbBufferSize;
-       int CpbBufferOffset;
-       int StreamDataSize;
-       int AvailableDpbFlagUpper;
-       int AvailableDpbFlagLower;
-       int DynamicDpbFlagUpper;
-       int DynamicDpbFlagLower;
-       unsigned int FrameAddr[3];
-       int FrameSize[3];
-       int NalStartOptions;
-       int FrameStrideSize[3];
-       int Frame2BitSize[2];
-       int Frame2BitStrideSize[2];
-       unsigned int ScratchBufAddr;
-       int ScratchBufSize;
-       char reserved[NAL_Q_IN_ENTRY_SIZE - NAL_Q_IN_DEC_STR_SIZE];
-} DecoderInputStr; /* 28*4 = 112 bytes */
-
-typedef struct __EncoderInputStr {
-       int StartCode; /* 0xBBBBBBBB; Encoder input structure marker */
-       int CommandId;
-       int InstanceId;
-       int PictureTag;
-       unsigned int FrameAddr[3];
-       unsigned int StreamBufferAddr;
-       int StreamBufferSize;
-       int StreamBufferOffset;
-       int RcRoiCtrl;
-       unsigned int RoiBufferAddr;
-       int ParamChange;
-       int IrSize;
-       int GopConfig;
-       int RcFrameRate;
-       int RcBitRate;
-       int MsliceMode;
-       int MsliceSizeMb;
-       int MsliceSizeBits;
-       int FrameInsertion;
-       int HierarchicalBitRateLayer[7];
-       int H264RefreshPeriod;
-       int HevcRefreshPeriod;
-       int RcQpBound;
-       int RcQpBoundPb;
-       int FixedPictureQp;
-       int PictureProfile;
-       int BitCountEnable;
-       int MaxBitCount;
-       int MinBitCount;
-       int NumTLayer;
-       int H264NalControl;
-       int HevcNalControl;
-       int Vp8NalControl;
-       int Vp9NalControl;
-       int H264HDSvcExtension0;
-       int H264HDSvcExtension1;
-       int GopConfig2;
-       int Frame2bitAddr[2];
-       int Weight;
-       int ExtCtbQpAddr;
-       int WeightUpper;
-       int RcMode;
-       char reserved[NAL_Q_IN_ENTRY_SIZE - NAL_Q_IN_ENC_STR_SIZE];
-} EncoderInputStr; /* 51*4 = 204 bytes */
-
-typedef struct __DecoderOutputStr {
-       int StartCode; /* 0xAAAAAAAA; Decoder output structure marker */
-       int CommandId;
-       int InstanceId;
-       int ErrorCode;
-       int PictureTagTop;
-       int PictureTimeTop;
-       int DisplayFrameWidth;
-       int DisplayFrameHeight;
-       int DisplayStatus;
-       unsigned int DisplayAddr[3];
-       int DisplayFrameType;
-       int DisplayCropInfo1;
-       int DisplayCropInfo2;
-       int DisplayPictureProfile;
-       int DisplayAspectRatio;
-       int DisplayExtendedAr;
-       int DecodedNalSize;
-       int UsedDpbFlagUpper;
-       int UsedDpbFlagLower;
-       int SeiAvail;
-       int FramePackArrgmentId;
-       int FramePackSeiInfo;
-       int FramePackGridPos;
-       int DisplayRecoverySeiInfo;
-       int H264Info;
-       int DisplayFirstCrc;
-       int DisplaySecondCrc;
-       int DisplayThirdCrc;
-       int DisplayFirst2BitCrc;
-       int DisplaySecond2BitCrc;
-       int DecodedFrameWidth;
-       int DecodedFrameHeight;
-       int DecodedStatus;
-       unsigned int DecodedAddr[3];
-       int DecodedFrameType;
-       int DecodedCropInfo1;
-       int DecodedCropInfo2;
-       int DecodedPictureProfile;
-       int DecodedRecoverySeiInfo;
-       int DecodedFirstCrc;
-       int DecodedSecondCrc;
-       int DecodedThirdCrc;
-       int DecodedFirst2BitCrc;
-       int DecodedSecond2BitCrc;
-       int PictureTagBot;
-       int PictureTimeBot;
-       int ChromaFormat;
-       int Mpeg4Info;
-       int HevcInfo;
-       int Vc1Info;
-       int VideoSignalType;
-       int ContentLightLevelInfoSei;
-       int MasteringDisplayColourVolumeSei0;
-       int MasteringDisplayColourVolumeSei1;
-       int MasteringDisplayColourVolumeSei2;
-       int MasteringDisplayColourVolumeSei3;
-       int MasteringDisplayColourVolumeSei4;
-       int MasteringDisplayColourVolumeSei5;
-       char reserved[NAL_Q_OUT_ENTRY_SIZE - NAL_Q_OUT_DEC_STR_SIZE];
-} DecoderOutputStr; /* 62*4 =  248 bytes */
-
-typedef struct __EncoderOutputStr {
-       int StartCode; /* 0xBBBBBBBB; Encoder output structure marker */
-       int CommandId;
-       int InstanceId;
-       int ErrorCode;
-       int PictureTag;
-       unsigned int EncodedFrameAddr[3];
-       unsigned int StreamBufferAddr;
-       int StreamBufferOffset;
-       int StreamSize;
-       int SliceType;
-       int NalDoneInfo;
-       unsigned int ReconLumaDpbAddr;
-       unsigned int ReconChromaDpbAddr;
-       int EncCnt;
-       char reserved[NAL_Q_OUT_ENTRY_SIZE - NAL_Q_OUT_ENC_STR_SIZE];
-} EncoderOutputStr; /* 16*4 = 64 bytes */
-
-/**
- * enum nal_queue_state - The state for nal queue operation.
- */
-typedef enum _nal_queue_state {
-       NAL_Q_STATE_CREATED = 0,
-       NAL_Q_STATE_STARTED, /* when s5p_mfc_nal_q_start() is called */
-       NAL_Q_STATE_STOPPED, /* when s5p_mfc_nal_q_stop() is called */
-} nal_queue_state;
-
-typedef struct _nal_in_queue {
-       union {
-               DecoderInputStr dec;
-               EncoderInputStr enc;
-       } entry[NAL_Q_IN_QUEUE_SIZE];
-} nal_in_queue;
-
-typedef struct _nal_out_queue {
-       union {
-               DecoderOutputStr dec;
-               EncoderOutputStr enc;
-       } entry[NAL_Q_OUT_QUEUE_SIZE];
-} nal_out_queue;
-
-struct _nal_queue_handle;
-typedef struct _nal_queue_in_handle {
-       struct _nal_queue_handle *nal_q_handle;
-       struct s5p_mfc_special_buf in_buf;
-       unsigned int in_exe_count;
-       nal_in_queue *nal_q_in_addr;
-} nal_queue_in_handle;
-
-typedef struct _nal_queue_out_handle {
-       struct _nal_queue_handle *nal_q_handle;
-       struct s5p_mfc_special_buf out_buf;
-       unsigned int out_exe_count;
-       nal_out_queue *nal_q_out_addr;
-       int nal_q_ctx;
-} nal_queue_out_handle;
-
-typedef struct _nal_queue_handle {
-       nal_queue_in_handle *nal_q_in_handle;
-       nal_queue_out_handle *nal_q_out_handle;
-       nal_queue_state nal_q_state;
-       unsigned int nal_q_clk_cnt;
-       spinlock_t lock;
-       int nal_q_exception;
-} nal_queue_handle;
-
-/************************ OTF data structure ************************/
-struct _otf_buf_addr {
-       dma_addr_t otf_daddr[HWFC_MAX_BUF][3];
-       struct dma_buf_attachment *otf_buf_attach[HWFC_MAX_BUF];
-};
-
-struct _otf_buf_info {
-       int pixel_format;
-       int width;
-       int height;
-       int buffer_count;
-       struct dma_buf *bufs[HWFC_MAX_BUF];
-};
-
-struct _otf_debug {
-       struct s5p_mfc_special_buf stream_buf[OTF_MAX_BUF];
-       unsigned int stream_size[OTF_MAX_BUF];
-       unsigned char frame_cnt;
-};
-
-struct _otf_handle {
-       int otf_work_bit;
-       int otf_buf_index;
-       int otf_job_id;
-       u64 otf_time_stamp;
-       struct _otf_buf_addr otf_buf_addr;
-       struct _otf_buf_info otf_buf_info;
-       struct _otf_debug otf_debug;
-};
-/********************************************************************/
-
-struct s5p_mfc_perf {
-       void __iomem *regs_base0;
-       void __iomem *regs_base1;
-
-       struct timeval begin;
-       struct timeval end;
-
-       int new_start;
-       int count;
-       int drv_margin;
-};
-
-extern struct s5p_mfc_dump_ops mfc_dump_ops;
-struct s5p_mfc_dump_ops {
-       void (*dump_regs)(struct s5p_mfc_dev *dev);
-       void (*dump_info)(struct s5p_mfc_dev *dev);
-       void (*dump_info_without_regs)(struct s5p_mfc_dev *dev);
-       void (*dump_and_stop_always)(struct s5p_mfc_dev *dev);
-       void (*dump_and_stop_debug_mode)(struct s5p_mfc_dev *dev);
-};
-
-struct s5p_mfc_mmcache {
-       void __iomem *base;
-       int is_on_status;
-};
-
-/**
- * struct s5p_mfc_dev - The struct containing driver internal parameters.
- */
-struct s5p_mfc_dev {
-       struct v4l2_device      v4l2_dev;
-       struct video_device     *vfd_dec;
-       struct video_device     *vfd_enc;
-       struct video_device     *vfd_dec_drm;
-       struct video_device     *vfd_enc_drm;
-       struct video_device     *vfd_enc_otf;
-       struct video_device     *vfd_enc_otf_drm;
-       struct device           *device;
-
-       void __iomem            *regs_base;
-       void __iomem            *sysmmu0_base;
-       void __iomem            *sysmmu1_base;
-       void __iomem            *hwfc_base;
-
-       int                     irq;
-       struct resource         *mfc_mem;
-
-       struct s5p_mfc_pm       pm;
-       struct s5p_mfc_fw       fw;
-       struct s5p_mfc_variant  *variant;
-       struct s5p_mfc_platdata *pdata;
-       struct s5p_mfc_debug    *logging_data;
-
-       int num_inst;
-
-       struct mutex mfc_mutex;
-
-       int int_condition;
-       int int_reason;
-       unsigned int int_err;
-
-       wait_queue_head_t cmd_wq;
-       struct s5p_mfc_listable_wq hwlock_wq;
-
-       bool has_2sysmmu;
-       bool has_hwfc;
-       bool has_mmcache;
-
-       struct s5p_mfc_special_buf common_ctx_buf;
-       struct s5p_mfc_special_buf drm_common_ctx_buf;
-
-       struct s5p_mfc_ctx *ctx[MFC_NUM_CONTEXTS];
-       int curr_ctx;
-       int preempt_ctx;
-
-       struct s5p_mfc_bits work_bits;
-
-       struct s5p_mfc_hwlock hwlock;
-
-       atomic_t sched_wait_cnt;
-       atomic_t watchdog_tick_running;
-       atomic_t watchdog_tick_cnt;
-       atomic_t watchdog_run;
-       struct timer_list watchdog_timer;
-       struct workqueue_struct *watchdog_wq;
-       struct work_struct watchdog_work;
-
-       /* for DRM */
-       int curr_ctx_is_drm;
-       int num_drm_inst;
-       struct s5p_mfc_special_buf fw_buf;
-       struct s5p_mfc_special_buf drm_fw_buf;
-
-       struct workqueue_struct *butler_wq;
-       struct work_struct butler_work;
-
-#ifdef CONFIG_MFC_USE_BUS_DEVFREQ
-       struct list_head qos_queue;
-       atomic_t qos_req_cur;
-       struct pm_qos_request qos_req_mfc;
-       struct pm_qos_request qos_req_int;
-       struct pm_qos_request qos_req_mif;
-       struct pm_qos_request qos_req_cluster[MAX_NUM_CLUSTER];
-       int qos_has_enc_ctx;
-#endif
-       int id;
-       atomic_t clk_ref;
-
-       atomic_t trace_ref;
-       struct _mfc_trace *mfc_trace;
-       atomic_t trace_ref_hwlock;
-       struct _mfc_trace *mfc_trace_hwlock;
-       bool continue_clock_on;
-
-       bool shutdown;
-       bool sleep;
-
-       nal_queue_handle *nal_q_handle;
-
-       struct s5p_mfc_special_buf dbg_info_buf;
-
-#ifdef CONFIG_EXYNOS_BTS
-       struct bts_bw mfc_bw;
-#endif
-
-       struct s5p_mfc_debugfs debugfs;
-       struct s5p_mfc_dump_ops *dump_ops;
-
-       struct s5p_mfc_perf perf;
-
-       struct s5p_mfc_mmcache mmcache;
-
-#ifdef CONFIG_EXYNOS_ITMON
-       struct notifier_block itmon_nb;
-       int itmon_notified;
-#endif
-};
-
-/**
- *
- */
-struct s5p_mfc_h264_enc_params {
-       enum v4l2_mpeg_video_h264_profile profile;
-       u8 level;
-       u8 interlace;
-       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 _8x8_transform;
-       u8 rc_frame_qp;
-       u8 rc_min_qp;
-       u8 rc_max_qp;
-       u8 rc_min_qp_p;
-       u8 rc_max_qp_p;
-       u8 rc_min_qp_b;
-       u8 rc_max_qp_b;
-       u8 rc_mb_dark;
-       u8 rc_mb_smooth;
-       u8 rc_mb_static;
-       u8 rc_mb_activity;
-       u8 rc_p_frame_qp;
-       u8 rc_b_frame_qp;
-       u8 ar_vui;
-       enum v4l2_mpeg_video_h264_vui_sar_idc ar_vui_idc;
-       u16 ext_sar_width;
-       u16 ext_sar_height;
-       u8 open_gop;
-       u16 open_gop_size;
-       u8 hier_qp_enable;
-       enum v4l2_mpeg_video_h264_hierarchical_coding_type hier_qp_type;
-       u8 num_hier_layer;
-       u8 hier_ref_type;
-       u8 hier_qp_layer[7];
-       u32 hier_bit_layer[7];
-       u8 sei_gen_enable;
-       u8 sei_fp_curr_frame_0;
-       enum v4l2_mpeg_video_h264_sei_fp_arrangement_type sei_fp_arrangement_type;
-       u32 fmo_enable;
-       u32 fmo_slice_map_type;
-       u32 fmo_slice_num_grp;
-       u32 fmo_run_length[4];
-       u32 fmo_sg_dir;
-       u32 fmo_sg_rate;
-       u32 aso_enable;
-       u32 aso_slice_order[8];
-
-       u32 prepend_sps_pps_to_idr;
-       u8 enable_ltr;
-       u8 num_of_ltr;
-       u32 set_priority;
-       u32 base_priority;
-       u32 vui_enable;
-};
-
-/**
- *
- */
-struct s5p_mfc_mpeg4_enc_params {
-       /* MPEG4 Only */
-       enum v4l2_mpeg_video_mpeg4_profile profile;
-       u8 level;
-       u8 quarter_pixel;
-       u16 vop_time_res;
-       u16 vop_frm_delta;
-       u8 rc_b_frame_qp;
-       /* Common for MPEG4, H263 */
-       u8 rc_frame_qp;
-       u8 rc_min_qp;
-       u8 rc_max_qp;
-       u8 rc_min_qp_p;
-       u8 rc_max_qp_p;
-       u8 rc_min_qp_b;
-       u8 rc_max_qp_b;
-       u8 rc_p_frame_qp;
-};
-
-/**
- *
- */
-struct s5p_mfc_vp9_enc_params {
-       /* VP9 Only */
-       u8 vp9_version;
-       u8 rc_min_qp;
-       u8 rc_max_qp;
-       u8 rc_min_qp_p;
-       u8 rc_max_qp_p;
-       u8 rc_frame_qp;
-       u8 rc_p_frame_qp;
-       u8 vp9_goldenframesel;
-       u16 vp9_gfrefreshperiod;
-       u8 hier_qp_enable;
-       u8 hier_qp_layer[3];
-       u32 hier_bit_layer[3];
-       u8 num_hier_layer;
-       u8 max_partition_depth;
-       u8 intra_pu_split_disable;
-       u8 profile;
-};
-
-/**
- *
- */
-struct s5p_mfc_vp8_enc_params {
-       /* VP8 Only */
-       u8 vp8_version;
-       u8 rc_min_qp;
-       u8 rc_max_qp;
-       u8 rc_min_qp_p;
-       u8 rc_max_qp_p;
-       u8 rc_frame_qp;
-       u8 rc_p_frame_qp;
-       u8 vp8_numberofpartitions;
-       u8 vp8_filterlevel;
-       u8 vp8_filtersharpness;
-       u8 vp8_goldenframesel;
-       u16 vp8_gfrefreshperiod;
-       u8 hier_qp_enable;
-       u8 hier_qp_layer[3];
-       u32 hier_bit_layer[3];
-       u8 intra_4x4mode_disable;
-       u8 num_hier_layer;
-};
-
-/**
- *
- */
-struct s5p_mfc_hevc_enc_params {
-       u8 profile;
-       u8 level;
-       u8 tier_flag;
-       /* HEVC Only */
-       u8 rc_min_qp;
-       u8 rc_max_qp;
-       u8 rc_min_qp_p;
-       u8 rc_max_qp_p;
-       u8 rc_min_qp_b;
-       u8 rc_max_qp_b;
-       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 refreshtype;
-       u16 refreshperiod;
-       s32 lf_beta_offset_div2;
-       s32 lf_tc_offset_div2;
-       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_hierarchical_coding_type hier_qp_type;
-       u8 hier_ref_type;
-       u8 num_hier_layer;
-       u8 hier_qp_layer[7];
-       u32 hier_bit_layer[7];
-       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 user_ref;
-       u8 store_ref;
-       u8 prepend_sps_pps_to_idr;
-};
-
-/**
- *
- */
-struct s5p_mfc_bpg_enc_params {
-       u32 thumb_size;
-       u32 exif_size;
-};
-
-/**
- *
- */
-struct s5p_mfc_enc_params {
-       u16 width;
-       u16 height;
-
-       u32 gop_size;
-       enum v4l2_mpeg_video_multi_slice_mode slice_mode;
-       u32 slice_mb;
-       u32 slice_bit;
-       u32 slice_mb_row;
-       u32 intra_refresh_mb;
-       u8 pad;
-       u8 pad_luma;
-       u8 pad_cb;
-       u8 pad_cr;
-       u8 rc_frame;
-       u32 rc_bitrate;
-       u32 rc_framerate;
-       u16 rc_reaction_coeff;
-       u32 config_qp;
-       u32 dynamic_qp;
-       u8 frame_tag;
-       u8 ratio_intra;
-
-       u8 num_b_frame;         /* H.264, HEVC, MPEG4 */
-       u8 num_refs_for_p;      /* H.264, HEVC, VP8, VP9 */
-       u8 rc_mb;               /* H.264: MFCv5, MPEG4/H.263: MFCv6 */
-       u8 rc_pvc;
-       u16 vbv_buf_size;
-       enum v4l2_mpeg_video_header_mode seq_hdr_mode;
-       enum v4l2_mpeg_mfc51_video_frame_skip_mode frame_skip_mode;
-       u8 fixed_target_bit;
-       u8 num_hier_max_layer;
-       u8 hier_bitrate_ctrl;
-       u8 weighted_enable;
-       u8 roi_enable;
-       u8 ivf_header_disable;  /* VP8, VP9 */
-
-       u16 rc_frame_delta;     /* MFC6.1 Only */
-
-       u32 i_frm_ctrl_mode;
-       u32 i_frm_ctrl;
-
-       u32 check_color_range;
-       u32 color_range;
-       u32 colour_primaries;
-       u32 transfer_characteristics;
-       u32 matrix_coefficients;
-
-       u32 static_info_enable;
-       u32 max_pic_average_light;
-       u32 max_content_light;
-       u32 max_display_luminance;
-       u32 min_display_luminance;
-       u32 white_point;
-       u32 display_primaries_0;
-       u32 display_primaries_1;
-       u32 display_primaries_2;
-
-       union {
-               struct s5p_mfc_h264_enc_params h264;
-               struct s5p_mfc_mpeg4_enc_params mpeg4;
-               struct s5p_mfc_vp8_enc_params vp8;
-               struct s5p_mfc_vp9_enc_params vp9;
-               struct s5p_mfc_hevc_enc_params hevc;
-               struct s5p_mfc_bpg_enc_params bpg;
-       } codec;
-};
-
-struct s5p_mfc_ctx_ctrl {
-       struct list_head list;
-       enum s5p_mfc_ctrl_type type;
-       unsigned int id;
-       unsigned int addr;
-       int has_new;
-       int val;
-};
-
-struct s5p_mfc_buf_ctrl {
-       struct list_head list;
-       unsigned int id;
-       enum s5p_mfc_ctrl_type type;
-       int has_new;
-       int val;
-       unsigned int old_val;           /* only for MFC_CTRL_TYPE_SET */
-       unsigned int old_val2;          /* only for MFC_CTRL_TYPE_SET */
-       unsigned int is_volatile;       /* only for MFC_CTRL_TYPE_SET */
-       unsigned int updated;
-       unsigned int mode;
-       unsigned int addr;
-       unsigned int mask;
-       unsigned int shft;
-       unsigned int flag_mode;         /* only for MFC_CTRL_TYPE_SET */
-       unsigned int flag_addr;         /* only for MFC_CTRL_TYPE_SET */
-       unsigned int flag_shft;         /* only for MFC_CTRL_TYPE_SET */
-       int (*read_cst) (struct s5p_mfc_ctx *ctx,
-                       struct s5p_mfc_buf_ctrl *buf_ctrl);
-       void (*write_cst) (struct s5p_mfc_ctx *ctx,
-                       struct s5p_mfc_buf_ctrl *buf_ctrl);
-};
-
-struct s5p_mfc_ctrl_cfg {
-       enum s5p_mfc_ctrl_type type;
-       unsigned int id;
-       unsigned int is_volatile;       /* only for MFC_CTRL_TYPE_SET */
-       unsigned int mode;
-       unsigned int addr;
-       unsigned int mask;
-       unsigned int shft;
-       unsigned int flag_mode;         /* only for MFC_CTRL_TYPE_SET */
-       unsigned int flag_addr;         /* only for MFC_CTRL_TYPE_SET */
-       unsigned int flag_shft;         /* only for MFC_CTRL_TYPE_SET */
-       int (*read_cst) (struct s5p_mfc_ctx *ctx,
-                       struct s5p_mfc_buf_ctrl *buf_ctrl);
-       void (*write_cst) (struct s5p_mfc_ctx *ctx,
-                       struct s5p_mfc_buf_ctrl *buf_ctrl);
-};
-
-/* per buffer contol */
-struct s5p_mfc_ctrls_ops {
-       /* controls per buffer */
-       int (*init_ctx_ctrls) (struct s5p_mfc_ctx *ctx);
-       int (*cleanup_ctx_ctrls) (struct s5p_mfc_ctx *ctx);
-       int (*init_buf_ctrls) (struct s5p_mfc_ctx *ctx,
-                       enum s5p_mfc_ctrl_type type, unsigned int index);
-       void (*reset_buf_ctrls) (struct list_head *head);
-       int (*cleanup_buf_ctrls) (struct s5p_mfc_ctx *ctx,
-                       enum s5p_mfc_ctrl_type type, unsigned int index);
-       int (*to_buf_ctrls) (struct s5p_mfc_ctx *ctx, struct list_head *head);
-       int (*to_ctx_ctrls) (struct s5p_mfc_ctx *ctx, struct list_head *head);
-       int (*set_buf_ctrls_val) (struct s5p_mfc_ctx *ctx,
-                       struct list_head *head);
-       int (*get_buf_ctrls_val) (struct s5p_mfc_ctx *ctx,
-                       struct list_head *head);
-       int (*recover_buf_ctrls_val) (struct s5p_mfc_ctx *ctx,
-                       struct list_head *head);
-       int (*get_buf_update_val) (struct s5p_mfc_ctx *ctx,
-                       struct list_head *head, unsigned int id, int value);
-       int (*set_buf_ctrls_val_nal_q_dec) (struct s5p_mfc_ctx *ctx,
-                       struct list_head *head, DecoderInputStr *pInStr);
-       int (*get_buf_ctrls_val_nal_q_dec) (struct s5p_mfc_ctx *ctx,
-                       struct list_head *head, DecoderOutputStr *pOutStr);
-       int (*set_buf_ctrls_val_nal_q_enc) (struct s5p_mfc_ctx *ctx,
-                       struct list_head *head, EncoderInputStr *pInStr);
-       int (*get_buf_ctrls_val_nal_q_enc) (struct s5p_mfc_ctx *ctx,
-                       struct list_head *head, EncoderOutputStr *pOutStr);
-       int (*recover_buf_ctrls_nal_q) (struct s5p_mfc_ctx *ctx,
-                       struct list_head *head);
-};
-
-struct stored_dpb_info {
-       int fd[MFC_MAX_PLANES];
-};
-
-struct dec_dpb_ref_info {
-       int index;
-       struct stored_dpb_info dpb[MFC_MAX_DPBS];
-};
-
-struct temporal_layer_info {
-       unsigned int temporal_layer_count;
-       unsigned int temporal_layer_bitrate[VIDEO_MAX_TEMPORAL_LAYERS];
-};
-
-struct mfc_enc_roi_info {
-       char *addr;
-       int size;
-       int upper_qp;
-       int lower_qp;
-       bool enable;
-};
-
-struct mfc_user_shared_handle {
-       int fd;
-       struct dma_buf *dma_buf;
-       void *vaddr;
-};
-
-struct s5p_mfc_raw_info {
-       int num_planes;
-       int stride[3];
-       int plane_size[3];
-       int stride_2bits[3];
-       int plane_size_2bits[3];
-       unsigned int total_plane_size;
-};
-
-struct mfc_timestamp {
-       struct list_head list;
-       struct timeval timestamp;
-       int index;
-       int interval;
-};
-
-struct s5p_mfc_dec {
-       int total_dpb_count;
-
-       unsigned int src_buf_size;
-
-       int loop_filter_mpeg4;
-       int display_delay;
-       int immediate_display;
-       int slice_enable;
-       int mv_count;
-       int idr_decoding;
-       int is_interlaced;
-       int is_dts_mode;
-
-       int crc_enable;
-       int crc_luma0;
-       int crc_chroma0;
-       int crc_luma1;
-       int crc_chroma1;
-
-       unsigned long consumed;
-       unsigned long remained_size;
-
-       enum v4l2_memory dst_memtype;
-       int sei_parse;
-       int stored_tag;
-       dma_addr_t y_addr_for_pb;
-
-       int cr_left, cr_right, cr_top, cr_bot;
-
-       int detect_black_bar;
-       bool black_bar_updated;
-       struct v4l2_rect black_bar;
-
-       /* For dynamic DPB */
-       int is_dynamic_dpb;
-       unsigned long available_dpb;
-       unsigned int dynamic_set;
-       unsigned int dynamic_used;
-
-       struct dec_dpb_ref_info *ref_info;
-       int assigned_fd[MFC_MAX_DPBS];
-       struct mfc_user_shared_handle sh_handle;
-       struct s5p_mfc_buf *assigned_dpb[MFC_MAX_DPBS];
-
-       int has_multiframe;
-       int is_dpb_full;
-
-       unsigned int err_reuse_flag;
-       unsigned int dec_only_release_flag;
-
-       /* for debugging about black bar detection */
-       void *frame_vaddr[3][30];
-       dma_addr_t frame_daddr[3][30];
-       int index[3][30];
-       int fd[3][30];
-       unsigned int frame_size[3][30];
-       unsigned char frame_cnt;
-
-       unsigned int num_of_tile_over_4;
-
-       unsigned int color_range;
-       unsigned int color_space;
-};
-
-struct s5p_mfc_enc {
-       struct s5p_mfc_enc_params params;
-
-       unsigned int dst_buf_size;
-       unsigned int header_size;
-
-       enum v4l2_mpeg_mfc51_video_frame_type frame_type;
-       enum v4l2_mpeg_mfc51_video_force_frame_type force_frame_type;
-
-       size_t luma_dpb_size;
-       size_t chroma_dpb_size;
-       size_t me_buffer_size;
-       size_t tmv_buffer_size;
-
-       unsigned int slice_mode;
-       union {
-               unsigned int mb;
-               unsigned int bits;
-       } slice_size;
-       unsigned int in_slice;
-       unsigned int buf_full;
-
-       int stored_tag;
-       struct mfc_user_shared_handle sh_handle_svc;
-       struct mfc_user_shared_handle sh_handle_roi;
-       int roi_index;
-       struct s5p_mfc_special_buf roi_buf[MFC_MAX_EXTRA_BUF];
-       struct mfc_enc_roi_info roi_info[MFC_MAX_EXTRA_BUF];
-};
-
-struct s5p_mfc_fmt {
-       char *name;
-       u32 fourcc;
-       u32 codec_mode;
-       u32 type;
-       u32 num_planes;
-       u32 mem_planes;
-};
-
-/**
- * struct s5p_mfc_ctx - This struct contains the instance context
- */
-struct s5p_mfc_ctx {
-       struct s5p_mfc_dev *dev;
-       struct v4l2_fh fh;
-       int num;
-
-       int int_condition;
-       int int_reason;
-       unsigned int int_err;
-
-       wait_queue_head_t cmd_wq;
-       struct s5p_mfc_listable_wq hwlock_wq;
-
-       struct s5p_mfc_fmt *src_fmt;
-       struct s5p_mfc_fmt *dst_fmt;
-
-       struct vb2_queue vq_src;
-       struct vb2_queue vq_dst;
-
-       struct s5p_mfc_buf_queue src_buf_queue;
-       struct s5p_mfc_buf_queue dst_buf_queue;
-       struct s5p_mfc_buf_queue src_buf_nal_queue;
-       struct s5p_mfc_buf_queue dst_buf_nal_queue;
-       struct s5p_mfc_buf_queue ref_buf_queue;
-       spinlock_t buf_queue_lock;
-
-       enum s5p_mfc_inst_type type;
-       enum s5p_mfc_inst_state state;
-       int inst_no;
-
-       int img_width;
-       int img_height;
-       int crop_width;
-       int crop_height;
-       int crop_left;
-       int crop_top;
-       int dpb_count;
-       int buf_stride;
-
-       int min_dpb_size[3];
-
-       struct s5p_mfc_raw_info raw_buf;
-       size_t mv_size;
-
-       struct s5p_mfc_special_buf codec_buf;
-       int codec_buffer_allocated;
-
-       enum s5p_mfc_queue_state capture_state;
-       enum s5p_mfc_queue_state output_state;
-
-       struct list_head ctrls;
-
-       struct list_head src_ctrls[MFC_MAX_BUFFERS];
-       struct list_head dst_ctrls[MFC_MAX_BUFFERS];
-
-       unsigned long src_ctrls_avail;
-       unsigned long dst_ctrls_avail;
-
-       unsigned int sequence;
-
-       /* Control values */
-       int codec_mode;
-       __u32 pix_format;
-
-       /* Extra Buffers */
-       struct s5p_mfc_special_buf instance_ctx_buf;
-
-       struct s5p_mfc_dec *dec_priv;
-       struct s5p_mfc_enc *enc_priv;
-
-       struct s5p_mfc_ctrls_ops *c_ops;
-
-       size_t scratch_buf_size;
-       size_t loopfilter_luma_size;
-       size_t loopfilter_chroma_size;
-
-       /* Profile infomation */
-       int is_10bit;
-       int is_422;
-
-       /* for DRM */
-       int is_drm;
-
-       int is_dpb_realloc;
-       enum mfc_dec_wait_state wait_state;
-       int clear_work_bit;
-
-#ifdef CONFIG_MFC_USE_BUS_DEVFREQ
-       int qos_req_step;
-       struct list_head qos_list;
-#endif
-       unsigned int qos_ratio;
-       unsigned long framerate;
-       unsigned long last_framerate;
-
-       struct mfc_timestamp ts_array[MFC_TIME_INDEX];
-       struct list_head ts_list;
-       int ts_count;
-       int ts_is_full;
-
-       int buf_process_type;
-
-       unsigned long raw_protect_flag;
-       unsigned long stream_protect_flag;
-       struct _otf_handle *otf_handle;
-
-       int batch_mode;
-       bool check_dump;
-};
-
-#endif /* __S5P_MFC_DATA_STRUCT_H */
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_debug.h b/drivers/media/platform/exynos/mfc/s5p_mfc_debug.h
deleted file mode 100644 (file)
index f6bd7f1..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_debug.h
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __S5P_MFC_DEBUG_H
-#define __S5P_MFC_DEBUG_H __FILE__
-
-#define DEBUG
-
-#ifdef DEBUG
-
-extern unsigned int debug_level;
-extern unsigned int debug_ts;
-extern unsigned int dbg_enable;
-extern unsigned int nal_q_dump;
-extern unsigned int nal_q_disable;
-extern unsigned int nal_q_parallel_disable;
-extern unsigned int otf_dump;
-extern unsigned int sfr_dump;
-extern unsigned int mmcache_dump;
-extern unsigned int mmcache_disable;
-extern unsigned int perf_boost_mode;
-
-#define mfc_debug(level, fmt, args...)                         \
-       do {                                                    \
-               if (debug_level >= level)                               \
-                       printk(KERN_DEBUG "%s:%d: " fmt,        \
-                               __func__, __LINE__, ##args);    \
-       } while (0)
-#else
-#define mfc_debug(fmt, args...)
-#endif
-
-#define mfc_debug_enter() mfc_debug(5, "enter\n")
-#define mfc_debug_leave() mfc_debug(5, "leave\n")
-
-#define mfc_err_dev(fmt, args...)                      \
-       do {                                            \
-               printk(KERN_ERR "%s:%d: " fmt,          \
-                      __func__, __LINE__, ##args);     \
-       } while (0)
-
-#define mfc_err_ctx(fmt, args...)                      \
-       do {                                            \
-               printk(KERN_ERR "[c:%d] %s:%d: " fmt,   \
-                       ctx->num,                       \
-                      __func__, __LINE__, ##args);     \
-       } while (0)
-
-#define mfc_info_dev(fmt, args...)                     \
-       do {                                            \
-               printk(KERN_INFO "%s:%d: " fmt,         \
-                       __func__, __LINE__, ##args);    \
-       } while (0)
-
-#define mfc_info_ctx(fmt, args...)                     \
-       do {                                            \
-               printk(KERN_INFO "[c:%d] %s:%d: " fmt,  \
-                       ctx->num,                       \
-                       __func__, __LINE__, ##args);    \
-       } while (0)
-
-#define MFC_TRACE_STR_LEN              80
-#define MFC_TRACE_COUNT_MAX            1024
-#define MFC_TRACE_COUNT_PRINT          30
-
-struct _mfc_trace {
-       unsigned long long time;
-       char str[MFC_TRACE_STR_LEN];
-};
-
-/* If there is no ctx structure */
-#define MFC_TRACE_DEV(fmt, args...)                                                            \
-       do {                                                                                    \
-               int cpu = raw_smp_processor_id();                                               \
-               int cnt;                                                                        \
-               cnt = atomic_inc_return(&dev->trace_ref) & (MFC_TRACE_COUNT_MAX - 1);           \
-               dev->mfc_trace[cnt].time = cpu_clock(cpu);                                      \
-               snprintf(dev->mfc_trace[cnt].str, MFC_TRACE_STR_LEN,                            \
-                               fmt, ##args);                           \
-       } while (0)
-
-/* If there is ctx structure */
-#define MFC_TRACE_CTX(fmt, args...)                                                            \
-       do {                                                                                    \
-               int cpu = raw_smp_processor_id();                                               \
-               int cnt;                                                                        \
-               cnt = atomic_inc_return(&dev->trace_ref) & (MFC_TRACE_COUNT_MAX - 1);           \
-               dev->mfc_trace[cnt].time = cpu_clock(cpu);                                      \
-               snprintf(dev->mfc_trace[cnt].str, MFC_TRACE_STR_LEN,                            \
-                               "[c:%d] " fmt, ctx->num, ##args);                               \
-       } while (0)
-
-
-/* If there is no ctx structure */
-#define MFC_TRACE_DEV_HWLOCK(fmt, args...)                                                     \
-       do {                                                                                    \
-               int cpu = raw_smp_processor_id();                                               \
-               int cnt;                                                                        \
-               cnt = atomic_inc_return(&dev->trace_ref_hwlock) & (MFC_TRACE_COUNT_MAX - 1);    \
-               dev->mfc_trace_hwlock[cnt].time = cpu_clock(cpu);                               \
-               snprintf(dev->mfc_trace_hwlock[cnt].str, MFC_TRACE_STR_LEN,                     \
-                               fmt, ##args);                                                   \
-       } while (0)
-
-/* If there is ctx structure */
-#define MFC_TRACE_CTX_HWLOCK(fmt, args...)                                                     \
-       do {                                                                                    \
-               int cpu = raw_smp_processor_id();                                               \
-               int cnt;                                                                        \
-               cnt = atomic_inc_return(&dev->trace_ref_hwlock) & (MFC_TRACE_COUNT_MAX - 1);    \
-               dev->mfc_trace_hwlock[cnt].time = cpu_clock(cpu);                               \
-               snprintf(dev->mfc_trace_hwlock[cnt].str, MFC_TRACE_STR_LEN,                     \
-                               "[c:%d] " fmt, ctx->num, ##args);                               \
-       } while (0)
-
-
-#endif /* __S5P_MFC_DEBUG_H */
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_debugfs.c b/drivers/media/platform/exynos/mfc/s5p_mfc_debugfs.c
deleted file mode 100644 (file)
index 61f80a6..0000000
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_debug.c
- *
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-
-#include "s5p_mfc_debugfs.h"
-#include "s5p_mfc_sync.h"
-
-#include "s5p_mfc_pm.h"
-
-#include "s5p_mfc_queue.h"
-
-unsigned int debug_level;
-unsigned int debug_ts;
-unsigned int dbg_enable;
-unsigned int nal_q_dump;
-unsigned int nal_q_disable;
-unsigned int nal_q_parallel_disable;
-unsigned int otf_dump;
-unsigned int perf_measure_option;
-unsigned int sfr_dump;
-unsigned int mmcache_dump;
-unsigned int mmcache_disable;
-unsigned int perf_boost_mode;
-
-static int mfc_info_show(struct seq_file *s, void *unused)
-{
-       struct s5p_mfc_dev *dev = s->private;
-       struct s5p_mfc_ctx *ctx = NULL;
-       int i;
-       char *codec_name = NULL;
-
-       seq_puts(s, ">> MFC device information(common)\n");
-       seq_printf(s, "[VERSION] H/W: v%x.%x, F/W: %06x(%c), DRV: %d\n",
-                MFC_VER_MAJOR(dev), MFC_VER_MINOR(dev), dev->fw.date,
-                dev->fw.fimv_info, MFC_DRIVER_INFO);
-       seq_printf(s, "[PM] power: %d, clock: %d\n",
-                       s5p_mfc_pm_get_pwr_ref_cnt(dev), s5p_mfc_pm_get_clk_ref_cnt(dev));
-       seq_printf(s, "[CTX] num_inst: %d, num_drm_inst: %d, curr_ctx: %d(is_drm: %d)\n",
-                       dev->num_inst, dev->num_drm_inst, dev->curr_ctx, dev->curr_ctx_is_drm);
-       seq_printf(s, "[HWLOCK] bits: %#lx, dev: %#lx, owned_by_irq = %d, wl_count = %d\n",
-                       dev->hwlock.bits, dev->hwlock.dev,
-                       dev->hwlock.owned_by_irq, dev->hwlock.wl_count);
-       seq_printf(s, "[DEBUG MODE] %s\n", dev->pdata->debug_mode ? "enabled" : "disabled");
-       seq_printf(s, "[MMCACHE] %s(%s)\n",
-                       dev->has_mmcache ? "supported" : "not supported",
-                       dev->mmcache.is_on_status ? "enabled" : "disabled");
-       seq_printf(s, "[PERF BOOST] %s\n", perf_boost_mode ? "enabled" : "disabled");
-       seq_printf(s, "[FEATURES] nal_q: %d(0x%x), skype: %d(0x%x), black_bar: %d(0x%x)\n",
-                       dev->pdata->nal_q.support, dev->pdata->nal_q.version,
-                       dev->pdata->skype.support, dev->pdata->skype.version,
-                       dev->pdata->black_bar.support, dev->pdata->black_bar.version);
-       seq_printf(s, "           color_aspect_dec: %d(0x%x), enc: %d(0x%x)\n",
-                       dev->pdata->color_aspect_dec.support, dev->pdata->color_aspect_dec.version,
-                       dev->pdata->color_aspect_enc.support, dev->pdata->color_aspect_enc.version);
-       seq_printf(s, "           static_info_dec: %d(0x%x), enc: %d(0x%x)\n",
-                       dev->pdata->static_info_dec.support, dev->pdata->static_info_dec.version,
-                       dev->pdata->static_info_enc.support, dev->pdata->static_info_enc.version);
-       seq_printf(s, "[FORMATS] 10bit: %s, 422: %s, RGB: %s\n",
-                       dev->pdata->support_10bit ? "supported" : "not supported",
-                       dev->pdata->support_422 ? "supported" : "not supported",
-                       dev->pdata->support_rgb ? "supported" : "not supported");
-       seq_printf(s, "[LOWMEM] is_low_mem: %d\n", IS_LOW_MEM);
-       if (dev->nal_q_handle)
-               seq_printf(s, "[NAL-Q] state: %d\n", dev->nal_q_handle->nal_q_state);
-
-       seq_puts(s, ">> MFC device information(instance)\n");
-       for (i = 0; i < MFC_NUM_CONTEXTS; i++) {
-               ctx = dev->ctx[i];
-               if (ctx) {
-                       if (ctx->type == MFCINST_DECODER)
-                               codec_name = ctx->src_fmt->name;
-                       else
-                               codec_name = ctx->dst_fmt->name;
-
-                       seq_printf(s, "[CTX:%d] codec: %s(%s), width: %d, height: %d, crop: %d %d %d %d, state: %d\n",
-                               ctx->num, ctx->type == MFCINST_DECODER ? "DEC" : "ENC", codec_name,
-                               ctx->img_width, ctx->img_height, ctx->crop_width, ctx->crop_height,
-                               ctx->crop_left, ctx->crop_top, ctx->state);
-                       seq_printf(s, "        queue(src: %d, dst: %d, src_nal: %d, dst_nal: %d, ref: %d)\n",
-                               s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->src_buf_queue),
-                               s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->dst_buf_queue),
-                               s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->src_buf_nal_queue),
-                               s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->dst_buf_nal_queue),
-                               s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->ref_buf_queue));
-               }
-       }
-
-       return 0;
-}
-
-static int mfc_debug_info_show(struct seq_file *s, void *unused)
-{
-       seq_puts(s, ">> MFC debug information\n");
-
-       seq_puts(s, "-----SFR dump options (bit setting)\n");
-       seq_puts(s, "ex) echo 0xff > /d/mfc/sfr_dump (all dump mode)\n");
-       seq_puts(s, "1   (1 << 0): dec SEQ_START\n");
-       seq_puts(s, "2   (1 << 1): dec INIT_BUFS\n");
-       seq_puts(s, "4   (1 << 2): dec NAL_START\n");
-       seq_puts(s, "8   (1 << 3): enc SEQ_START\n");
-       seq_puts(s, "16  (1 << 4): enc INIT_BUFS\n");
-       seq_puts(s, "32  (1 << 5): enc NAL_START\n");
-       seq_puts(s, "64  (1 << 6): ERR interrupt\n");
-       seq_puts(s, "128 (1 << 7): WARN interrupt\n");
-
-       seq_puts(s, "-----Performance boost options (bit setting)\n");
-       seq_puts(s, "ex) echo 7 > /d/mfc/perf_boost_mode (max freq)\n");
-       seq_puts(s, "1   (1 << 0): DVFS (INT/MFC/MIF)\n");
-       seq_puts(s, "2   (1 << 1): MO value\n");
-       seq_puts(s, "4   (1 << 2): CPU frequency\n");
-
-       return 0;
-}
-
-static int mfc_info_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, mfc_info_show, inode->i_private);
-}
-
-static int mfc_debug_info_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, mfc_debug_info_show, inode->i_private);
-}
-
-static const struct file_operations mfc_info_fops = {
-       .open = mfc_info_open,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = single_release,
-};
-
-static const struct file_operations debug_info_fops = {
-       .open = mfc_debug_info_open,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = single_release,
-};
-
-void s5p_mfc_init_debugfs(struct s5p_mfc_dev *dev)
-{
-       struct s5p_mfc_debugfs *debugfs = &dev->debugfs;
-
-       debugfs->root = debugfs_create_dir("mfc", NULL);
-       if (!debugfs->root) {
-               mfc_err_dev("debugfs: failed to create root derectory\n");
-               return;
-       }
-
-       debugfs->mfc_info = debugfs_create_file("mfc_info",
-                       0444, debugfs->root, dev, &mfc_info_fops);
-       debugfs->debug_info = debugfs_create_file("debug_info",
-                       0444, debugfs->root, dev, &debug_info_fops);
-       debugfs->debug_level = debugfs_create_u32("debug",
-                       0644, debugfs->root, &debug_level);
-       debugfs->debug_ts = debugfs_create_u32("debug_ts",
-                       0644, debugfs->root, &debug_ts);
-       debugfs->dbg_enable = debugfs_create_u32("dbg_enable",
-                       0644, debugfs->root, &dbg_enable);
-       debugfs->nal_q_dump = debugfs_create_u32("nal_q_dump",
-                       0644, debugfs->root, &nal_q_dump);
-       debugfs->nal_q_disable = debugfs_create_u32("nal_q_disable",
-                       0644, debugfs->root, &nal_q_disable);
-       debugfs->nal_q_parallel_disable = debugfs_create_u32("nal_q_parallel_disable",
-                       0644, debugfs->root, &nal_q_parallel_disable);
-       debugfs->otf_dump = debugfs_create_u32("otf_dump",
-                       0644, debugfs->root, &otf_dump);
-       debugfs->perf_measure_option = debugfs_create_u32("perf_measure_option",
-                       0644, debugfs->root, &perf_measure_option);
-       debugfs->sfr_dump = debugfs_create_u32("sfr_dump",
-                       0644, debugfs->root, &sfr_dump);
-       debugfs->mmcache_dump = debugfs_create_u32("mmcache_dump",
-                       0644, debugfs->root, &mmcache_dump);
-       debugfs->mmcache_disable = debugfs_create_u32("mmcache_disable",
-                       0644, debugfs->root, &mmcache_disable);
-       debugfs->perf_boost_mode = debugfs_create_u32("perf_boost_mode",
-                       0644, debugfs->root, &perf_boost_mode);
-}
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_debugfs.h b/drivers/media/platform/exynos/mfc/s5p_mfc_debugfs.h
deleted file mode 100644 (file)
index a4186e9..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_debugfs.h
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __S5P_MFC_DEBUGFS_H
-#define __S5P_MFC_DEBUGFS_H __FILE__
-
-#include "s5p_mfc_common.h"
-
-void s5p_mfc_init_debugfs(struct s5p_mfc_dev *dev);
-
-#endif /* __S5P_MFC_DEBUGFS_H */
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_dec.c b/drivers/media/platform/exynos/mfc/s5p_mfc_dec.c
deleted file mode 100644 (file)
index a28c70f..0000000
+++ /dev/null
@@ -1,1279 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_dec.c
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include "s5p_mfc_dec.h"
-#include "s5p_mfc_dec_internal.h"
-
-#include "s5p_mfc_hwlock.h"
-#include "s5p_mfc_opr.h"
-#include "s5p_mfc_sync.h"
-#include "s5p_mfc_mmcache.h"
-
-#include "s5p_mfc_qos.h"
-#include "s5p_mfc_queue.h"
-#include "s5p_mfc_utils.h"
-#include "s5p_mfc_buf.h"
-#include "s5p_mfc_mem.h"
-
-#define MAX_FRAME_SIZE         (2*1024*1024)
-
-/* Find selected format description */
-static struct s5p_mfc_fmt *mfc_dec_find_format(struct s5p_mfc_ctx *ctx,
-               unsigned int pixelformat)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_fmt *fmt = NULL;
-       unsigned long i;
-
-       for (i = 0; i < NUM_FORMATS; i++) {
-               if (dec_formats[i].fourcc == pixelformat) {
-                       fmt = (struct s5p_mfc_fmt *)&dec_formats[i];
-                       break;
-               }
-       }
-
-       if (!dev->pdata->support_10bit && (fmt->type & MFC_FMT_10BIT)) {
-               mfc_err_ctx("[FRAME] 10bit is not supported\n");
-               fmt = NULL;
-       }
-       if (!dev->pdata->support_422 && (fmt->type & MFC_FMT_422)) {
-               mfc_err_ctx("[FRAME] 422 is not supported\n");
-               fmt = NULL;
-       }
-
-       return fmt;
-}
-
-static struct v4l2_queryctrl *mfc_dec_get_ctrl(int id)
-{
-       unsigned long i;
-
-       for (i = 0; i < NUM_CTRLS; ++i)
-               if (id == controls[i].id)
-                       return &controls[i];
-
-       return NULL;
-}
-
-/* Check whether a ctrl value if correct */
-static int mfc_dec_check_ctrl_val(struct s5p_mfc_ctx *ctx, struct v4l2_control *ctrl)
-{
-       struct v4l2_queryctrl *c;
-
-       c = mfc_dec_get_ctrl(ctrl->id);
-       if (!c) {
-               mfc_err_ctx("[CTRLS] not supported control id (%#x)\n", ctrl->id);
-               return -EINVAL;
-       }
-
-       if (ctrl->value < c->minimum || ctrl->value > c->maximum
-               || (c->step != 0 && ctrl->value % c->step != 0)) {
-               mfc_err_ctx("[CTRLS] Invalid control value (%#x)\n", ctrl->value);
-               return -ERANGE;
-       }
-
-       return 0;
-}
-
-/* Query capabilities of the device */
-static int vidioc_querycap(struct file *file, void *priv,
-                          struct v4l2_capability *cap)
-{
-       strncpy(cap->driver, "MFC", sizeof(cap->driver) - 1);
-       strncpy(cap->card, "decoder", sizeof(cap->card) - 1);
-       cap->bus_info[0] = 0;
-       cap->version = KERNEL_VERSION(1, 0, 0);
-       cap->device_caps = V4L2_CAP_VIDEO_CAPTURE
-                       | V4L2_CAP_VIDEO_OUTPUT
-                       | V4L2_CAP_VIDEO_CAPTURE_MPLANE
-                       | V4L2_CAP_VIDEO_OUTPUT_MPLANE
-                       | V4L2_CAP_STREAMING
-                       | V4L2_CAP_DEVICE_CAPS;
-
-       cap->capabilities = cap->device_caps;
-
-       return 0;
-}
-
-static int mfc_dec_enum_fmt(struct s5p_mfc_dev *dev, struct v4l2_fmtdesc *f,
-               unsigned int type)
-{
-       struct s5p_mfc_fmt *fmt;
-       unsigned long i, j = 0;
-
-       for (i = 0; i < NUM_FORMATS; ++i) {
-               if (!(dec_formats[i].type & type))
-                       continue;
-               if (!dev->pdata->support_10bit && (dec_formats[i].type & MFC_FMT_10BIT))
-                       continue;
-               if (!dev->pdata->support_422 && (dec_formats[i].type & MFC_FMT_422))
-                       continue;
-
-               if (j == f->index) {
-                       fmt = &dec_formats[i];
-                       strlcpy(f->description, fmt->name,
-                               sizeof(f->description));
-                       f->pixelformat = fmt->fourcc;
-
-                       return 0;
-               }
-
-               ++j;
-       }
-
-       return -EINVAL;
-}
-
-static int vidioc_enum_fmt_vid_cap_mplane(struct file *file, void *pirv,
-               struct v4l2_fmtdesc *f)
-{
-       struct s5p_mfc_dev *dev = video_drvdata(file);
-
-       return mfc_dec_enum_fmt(dev, f, MFC_FMT_FRAME);
-}
-
-static int vidioc_enum_fmt_vid_out_mplane(struct file *file, void *prov,
-               struct v4l2_fmtdesc *f)
-{
-       struct s5p_mfc_dev *dev = video_drvdata(file);
-
-       return mfc_dec_enum_fmt(dev, f, MFC_FMT_STREAM);
-}
-
-static void mfc_dec_change_format(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       u32 org_fmt = ctx->dst_fmt->fourcc;
-
-       if (ctx->is_10bit && ctx->is_422) {
-               switch (org_fmt) {
-               case V4L2_PIX_FMT_NV16M_S10B:
-               case V4L2_PIX_FMT_NV61M_S10B:
-               case V4L2_PIX_FMT_NV16M_P210:
-               case V4L2_PIX_FMT_NV61M_P210:
-                       /* It is right format */
-                       break;
-               case V4L2_PIX_FMT_NV12M:
-               case V4L2_PIX_FMT_NV16M:
-               case V4L2_PIX_FMT_NV12M_S10B:
-               case V4L2_PIX_FMT_NV12M_P010:
-                       ctx->dst_fmt = mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV16M_S10B);
-                       break;
-               case V4L2_PIX_FMT_NV21M:
-               case V4L2_PIX_FMT_NV61M:
-               case V4L2_PIX_FMT_NV21M_S10B:
-               case V4L2_PIX_FMT_NV21M_P010:
-                       ctx->dst_fmt = mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV61M_S10B);
-                       break;
-               default:
-                       ctx->dst_fmt = mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV16M_S10B);
-                       break;
-               }
-               ctx->raw_buf.num_planes = 2;
-       } else if (ctx->is_10bit && !ctx->is_422) {
-               if (ctx->dst_fmt->mem_planes == 1) {
-                       /* YUV420 only supports the single plane */
-                       ctx->dst_fmt = mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV12N_10B);
-               } else {
-                       switch (org_fmt) {
-                       case V4L2_PIX_FMT_NV12M_S10B:
-                       case V4L2_PIX_FMT_NV21M_S10B:
-                       case V4L2_PIX_FMT_NV12M_P010:
-                       case V4L2_PIX_FMT_NV21M_P010:
-                               /* It is right format */
-                               break;
-                       case V4L2_PIX_FMT_NV12M:
-                       case V4L2_PIX_FMT_NV16M:
-                       case V4L2_PIX_FMT_NV16M_S10B:
-                       case V4L2_PIX_FMT_NV16M_P210:
-                               if (dev->pdata->P010_decoding)
-                                       ctx->dst_fmt = mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV12M_P010);
-                               else
-                                       ctx->dst_fmt = mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV12M_S10B);
-                               break;
-                       case V4L2_PIX_FMT_NV21M:
-                       case V4L2_PIX_FMT_NV61M:
-                       case V4L2_PIX_FMT_NV61M_S10B:
-                       case V4L2_PIX_FMT_NV61M_P210:
-                               ctx->dst_fmt = mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV21M_S10B);
-                               break;
-                       default:
-                               if (dev->pdata->P010_decoding)
-                                       ctx->dst_fmt = mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV12M_P010);
-                               else
-                                       ctx->dst_fmt = mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV12M_S10B);
-                               break;
-                       }
-               }
-               ctx->raw_buf.num_planes = 2;
-       } else if (!ctx->is_10bit && ctx->is_422) {
-               switch (org_fmt) {
-               case V4L2_PIX_FMT_NV16M:
-               case V4L2_PIX_FMT_NV61M:
-                       /* It is right format */
-                       break;
-               case V4L2_PIX_FMT_NV12M:
-               case V4L2_PIX_FMT_NV12M_S10B:
-               case V4L2_PIX_FMT_NV16M_S10B:
-               case V4L2_PIX_FMT_NV12M_P010:
-               case V4L2_PIX_FMT_NV16M_P210:
-                       ctx->dst_fmt = mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV16M);
-                       break;
-               case V4L2_PIX_FMT_NV21M:
-               case V4L2_PIX_FMT_NV21M_S10B:
-               case V4L2_PIX_FMT_NV61M_S10B:
-               case V4L2_PIX_FMT_NV21M_P010:
-               case V4L2_PIX_FMT_NV61M_P210:
-                       ctx->dst_fmt = mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV61M);
-                       break;
-               default:
-                       ctx->dst_fmt = mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV16M);
-                       break;
-               }
-               ctx->raw_buf.num_planes = 2;
-       } else {
-               /* YUV420 8bit */
-               switch (org_fmt) {
-               case V4L2_PIX_FMT_NV16M:
-               case V4L2_PIX_FMT_NV12M_S10B:
-               case V4L2_PIX_FMT_NV16M_S10B:
-               case V4L2_PIX_FMT_NV12M_P010:
-               case V4L2_PIX_FMT_NV16M_P210:
-                       ctx->dst_fmt = mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV12M);
-                       break;
-               case V4L2_PIX_FMT_NV61M:
-               case V4L2_PIX_FMT_NV21M_S10B:
-               case V4L2_PIX_FMT_NV61M_S10B:
-               case V4L2_PIX_FMT_NV21M_P010:
-               case V4L2_PIX_FMT_NV61M_P210:
-                       ctx->dst_fmt = mfc_dec_find_format(ctx, V4L2_PIX_FMT_NV21M);
-                       break;
-               default:
-                       /* It is right format */
-                       break;
-               }
-       }
-
-       if (org_fmt != ctx->dst_fmt->fourcc)
-               mfc_info_ctx("[FRAME] format is changed to %s\n", ctx->dst_fmt->name);
-}
-
-/* Get format */
-static int vidioc_g_fmt_vid_cap_mplane(struct file *file, void *priv,
-                                               struct v4l2_format *f)
-{
-       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
-       struct s5p_mfc_dec *dec;
-       struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
-       struct s5p_mfc_raw_info *raw;
-       int i;
-
-       mfc_debug_enter();
-
-       dec = ctx->dec_priv;
-       if (!dec) {
-               mfc_err_dev("no mfc decoder to run\n");
-               return -EINVAL;
-       }
-
-       mfc_debug(2, "dec dst g_fmt, state: %d\n", ctx->state);
-
-       if (ctx->state == MFCINST_GOT_INST ||
-           ctx->state == MFCINST_RES_CHANGE_FLUSH ||
-           ctx->state == MFCINST_RES_CHANGE_END) {
-               /* If the MFC is parsing the header,
-                * so wait until it is finished */
-               if (s5p_mfc_wait_for_done_ctx(ctx,
-                               S5P_FIMV_R2H_CMD_SEQ_DONE_RET)) {
-                               mfc_err_dev("header parsing failed\n");
-                               return -EAGAIN;
-               }
-       }
-
-       if (ctx->state >= MFCINST_HEAD_PARSED &&
-           ctx->state < MFCINST_ABORT) {
-               /* This is run on CAPTURE (deocde output) */
-
-               /* only NV16(61) format is supported for 422 format */
-               /* only 2 plane is supported for 10bit */
-               mfc_dec_change_format(ctx);
-
-               raw = &ctx->raw_buf;
-               /* Width and height are set to the dimensions
-                  of the movie, the buffer is bigger and
-                  further processing stages should crop to this
-                  rectangle. */
-               s5p_mfc_dec_calc_dpb_size(ctx);
-
-               if (IS_LOW_MEM) {
-                       unsigned int dpb_size;
-                       /*
-                        * If total memory requirement is too big for this device,
-                        * then it returns error.
-                        * DPB size : Total plane size * the number of DPBs
-                        * 5: the number of extra DPBs
-                        * 3: the number of DPBs for Android framework
-                        * 600MB: being used to return an error,
-                        * when 8K resolution video clip is being tried to be decoded
-                        */
-                       dpb_size = (ctx->raw_buf.total_plane_size * (ctx->dpb_count + 5 + 3));
-                       if (dpb_size > SZ_600M) {
-                               mfc_info_ctx("required memory size is too big (%dx%d, dpb: %d)\n",
-                                               ctx->img_width, ctx->img_height, ctx->dpb_count);
-                               return -EINVAL;
-                       }
-               }
-
-               pix_fmt_mp->width = ctx->img_width;
-               pix_fmt_mp->height = ctx->img_height;
-               pix_fmt_mp->num_planes = ctx->dst_fmt->mem_planes;
-
-               if (dec->is_interlaced)
-                       pix_fmt_mp->field = V4L2_FIELD_INTERLACED;
-               else
-                       pix_fmt_mp->field = V4L2_FIELD_NONE;
-
-               /* Set pixelformat to the format in which MFC
-                  outputs the decoded frame */
-               pix_fmt_mp->pixelformat = ctx->dst_fmt->fourcc;
-               for (i = 0; i < ctx->dst_fmt->mem_planes; i++) {
-                       pix_fmt_mp->plane_fmt[i].bytesperline = raw->stride[i];
-                       if (ctx->dst_fmt->mem_planes == 1) {
-                               pix_fmt_mp->plane_fmt[i].sizeimage = raw->total_plane_size;
-                       } else {
-                               if (ctx->is_10bit)
-                                       pix_fmt_mp->plane_fmt[i].sizeimage = raw->plane_size[i]
-                                               + raw->plane_size_2bits[i];
-                               else
-                                       pix_fmt_mp->plane_fmt[i].sizeimage = raw->plane_size[i];
-                       }
-               }
-       }
-
-       mfc_debug_leave();
-
-       return 0;
-}
-
-static int vidioc_g_fmt_vid_out_mplane(struct file *file, void *priv,
-                                               struct v4l2_format *f)
-{
-       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
-       struct s5p_mfc_dec *dec;
-       struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
-
-       mfc_debug_enter();
-
-       dec = ctx->dec_priv;
-       if (!dec) {
-               mfc_err_dev("no mfc decoder to run\n");
-               return -EINVAL;
-       }
-
-       mfc_debug(4, "dec src g_fmt, state: %d\n", ctx->state);
-
-       /* This is run on OUTPUT
-          The buffer contains compressed image
-          so width and height have no meaning */
-       pix_fmt_mp->width = 0;
-       pix_fmt_mp->height = 0;
-       pix_fmt_mp->field = V4L2_FIELD_NONE;
-       pix_fmt_mp->plane_fmt[0].bytesperline = dec->src_buf_size;
-       pix_fmt_mp->plane_fmt[0].sizeimage = dec->src_buf_size;
-       pix_fmt_mp->pixelformat = ctx->src_fmt->fourcc;
-       pix_fmt_mp->num_planes = ctx->src_fmt->mem_planes;
-
-       mfc_debug_leave();
-
-       return 0;
-}
-
-/* Try format */
-static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
-{
-       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
-       struct s5p_mfc_fmt *fmt;
-       struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
-
-       fmt = mfc_dec_find_format(ctx, pix_fmt_mp->pixelformat);
-       if (!fmt) {
-               mfc_err_dev("Unsupported format for %s\n",
-                               V4L2_TYPE_IS_OUTPUT(f->type) ? "source" : "destination");
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-/* Set format */
-static int vidioc_s_fmt_vid_cap_mplane(struct file *file, void *priv,
-                                                       struct v4l2_format *f)
-{
-       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
-       struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
-
-       mfc_debug_enter();
-
-       if (ctx->vq_dst.streaming) {
-               mfc_err_ctx("queue busy\n");
-               return -EBUSY;
-       }
-
-       ctx->dst_fmt = mfc_dec_find_format(ctx, pix_fmt_mp->pixelformat);
-       if (!ctx->dst_fmt) {
-               mfc_err_ctx("Unsupported format for destination\n");
-               return -EINVAL;
-       }
-       ctx->raw_buf.num_planes = ctx->dst_fmt->num_planes;
-       mfc_info_ctx("[FRAME] dec dst pixelformat : %s\n", ctx->dst_fmt->name);
-
-       mfc_debug_leave();
-
-       return 0;
-}
-
-static int mfc_force_close_inst(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx)
-{
-       if (ctx->inst_no == MFC_NO_INSTANCE_SET)
-               return 0;
-
-       s5p_mfc_change_state(ctx, MFCINST_RETURN_INST);
-       s5p_mfc_set_bit(ctx->num, &dev->work_bits);
-       s5p_mfc_clean_ctx_int_flags(ctx);
-       if (s5p_mfc_just_run(dev, ctx->num)) {
-               mfc_err_ctx("Failed to run MFC\n");
-               s5p_mfc_release_hwlock_ctx(ctx);
-               s5p_mfc_cleanup_work_bit_and_try_run(ctx);
-               return -EIO;
-       }
-
-       /* Wait until instance is returned or timeout occured */
-       if (s5p_mfc_wait_for_done_ctx(ctx,
-                               S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET)) {
-               mfc_err_ctx("Waiting for CLOSE_INSTANCE timed out\n");
-               s5p_mfc_release_hwlock_ctx(ctx);
-               s5p_mfc_cleanup_work_bit_and_try_run(ctx);
-               return -EIO;
-       }
-
-       /* Free resources */
-       s5p_mfc_release_instance_context(ctx);
-       s5p_mfc_change_state(ctx, MFCINST_INIT);
-
-       return 0;
-}
-
-static int vidioc_s_fmt_vid_out_mplane(struct file *file, void *priv,
-                                                       struct v4l2_format *f)
-{
-       struct s5p_mfc_dev *dev = video_drvdata(file);
-       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
-       struct s5p_mfc_dec *dec = ctx->dec_priv;
-       struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
-       int ret = 0;
-
-       mfc_debug_enter();
-
-       if (ctx->vq_src.streaming) {
-               mfc_err_ctx("queue busy\n");
-               return -EBUSY;
-       }
-
-       ctx->src_fmt = mfc_dec_find_format(ctx, pix_fmt_mp->pixelformat);
-       if (!ctx->src_fmt) {
-               mfc_err_ctx("Unsupported format for source\n");
-               return -EINVAL;
-       }
-
-       ctx->codec_mode = ctx->src_fmt->codec_mode;
-       mfc_info_ctx("[STREAM] Dec src codec(%d): %s\n",
-                       ctx->codec_mode, ctx->src_fmt->name);
-
-       ctx->pix_format = pix_fmt_mp->pixelformat;
-       if ((pix_fmt_mp->width > 0) && (pix_fmt_mp->height > 0)) {
-               ctx->img_height = pix_fmt_mp->height;
-               ctx->img_width = pix_fmt_mp->width;
-       }
-
-       /* As this buffer will contain compressed data, the size is set
-        * to the maximum size. */
-       if (pix_fmt_mp->plane_fmt[0].sizeimage)
-               dec->src_buf_size = pix_fmt_mp->plane_fmt[0].sizeimage;
-       else
-               dec->src_buf_size = MAX_FRAME_SIZE;
-       mfc_debug(2, "[STREAM] sizeimage: %d\n", pix_fmt_mp->plane_fmt[0].sizeimage);
-       pix_fmt_mp->plane_fmt[0].bytesperline = 0;
-
-       MFC_TRACE_CTX_HWLOCK("**DEC s_fmt\n");
-       ret = s5p_mfc_get_hwlock_ctx(ctx);
-       if (ret < 0) {
-               mfc_err_ctx("Failed to get hwlock\n");
-               return -EBUSY;
-       }
-
-       /* In case of calling s_fmt twice or more */
-       ret = mfc_force_close_inst(dev, ctx);
-       if (ret) {
-               mfc_err_ctx("Failed to close already opening instance\n");
-               return -EIO;
-       }
-
-       ret = s5p_mfc_alloc_instance_context(ctx);
-       if (ret) {
-               mfc_err_ctx("Failed to allocate dec instance[%d] buffers\n",
-                               ctx->num);
-               s5p_mfc_release_hwlock_ctx(ctx);
-               return -ENOMEM;
-       }
-
-       s5p_mfc_set_bit(ctx->num, &dev->work_bits);
-       ret = s5p_mfc_just_run(dev, ctx->num);
-       if (ret) {
-               mfc_err_ctx("Failed to run MFC\n");
-               s5p_mfc_release_hwlock_ctx(ctx);
-               s5p_mfc_cleanup_work_bit_and_try_run(ctx);
-               s5p_mfc_release_instance_context(ctx);
-               return -EIO;
-       }
-
-       if (s5p_mfc_wait_for_done_ctx(ctx,
-                       S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET)) {
-               s5p_mfc_release_hwlock_ctx(ctx);
-               s5p_mfc_cleanup_work_bit_and_try_run(ctx);
-               s5p_mfc_release_instance_context(ctx);
-               return -EIO;
-       }
-
-       s5p_mfc_release_hwlock_ctx(ctx);
-
-       mfc_debug(2, "Got instance number: %d\n", ctx->inst_no);
-
-       if (s5p_mfc_dec_ctx_ready(ctx))
-               s5p_mfc_set_bit(ctx->num, &dev->work_bits);
-       if (s5p_mfc_is_work_to_do(dev))
-               queue_work(dev->butler_wq, &dev->butler_work);
-
-       mfc_debug_leave();
-
-       return 0;
-}
-
-/* Reqeust 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_mfc_ctx(file->private_data);
-       struct s5p_mfc_dec *dec;
-       int ret = 0;
-
-       mfc_debug_enter();
-
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return -EINVAL;
-       }
-
-       dec = ctx->dec_priv;
-       if (!dec) {
-               mfc_err_dev("no mfc decoder to run\n");
-               return -EINVAL;
-       }
-
-       if (reqbufs->memory == V4L2_MEMORY_MMAP) {
-               mfc_err_ctx("Not supported memory type (%d)\n", reqbufs->memory);
-               return -EINVAL;
-       }
-
-       if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               mfc_debug(4, "dec src reqbuf(%d)\n", reqbufs->count);
-               /* Can only request buffers after
-                  an instance has been opened.*/
-               if (ctx->state == MFCINST_GOT_INST) {
-                       if (reqbufs->count == 0) {
-                               ret = vb2_reqbufs(&ctx->vq_src, reqbufs);
-                               ctx->output_state = QUEUE_FREE;
-                               return ret;
-                       }
-
-                       /* Decoding */
-                       if (ctx->output_state != QUEUE_FREE) {
-                               mfc_err_ctx("Bufs have already been requested\n");
-                               return -EINVAL;
-                       }
-
-                       ret = vb2_reqbufs(&ctx->vq_src, reqbufs);
-                       if (ret) {
-                               mfc_err_ctx("vb2_reqbufs on src failed\n");
-                               return ret;
-                       }
-
-                       ctx->output_state = QUEUE_BUFS_REQUESTED;
-               }
-       } else if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-               mfc_debug(4, "dec dst reqbuf(%d)\n", reqbufs->count);
-               if (reqbufs->count == 0) {
-                       ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
-
-                       if (dev->has_mmcache && dev->mmcache.is_on_status)
-                               s5p_mfc_invalidate_mmcache(dev);
-
-                       s5p_mfc_release_codec_buffers(ctx);
-                       ctx->capture_state = QUEUE_FREE;
-                       return ret;
-               }
-
-               dec->dst_memtype = reqbufs->memory;
-
-               if (ctx->capture_state != QUEUE_FREE) {
-                       mfc_err_ctx("Bufs have already been requested\n");
-                       return -EINVAL;
-               }
-
-               ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
-               if (ret) {
-                       mfc_err_ctx("vb2_reqbufs on capture failed\n");
-                       return ret;
-               }
-
-               if (reqbufs->count < ctx->dpb_count) {
-                       mfc_err_ctx("Not enough buffers allocated\n");
-                       reqbufs->count = 0;
-                       vb2_reqbufs(&ctx->vq_dst, reqbufs);
-                       return -ENOMEM;
-               }
-
-               dec->total_dpb_count = reqbufs->count;
-
-               ret = s5p_mfc_alloc_codec_buffers(ctx);
-               if (ret) {
-                       mfc_err_ctx("Failed to allocate decoding buffers\n");
-                       reqbufs->count = 0;
-                       vb2_reqbufs(&ctx->vq_dst, reqbufs);
-                       return -ENOMEM;
-               }
-
-               ctx->capture_state = QUEUE_BUFS_REQUESTED;
-
-               if (s5p_mfc_dec_ctx_ready(ctx))
-                       s5p_mfc_set_bit(ctx->num, &dev->work_bits);
-
-               s5p_mfc_try_run(dev);
-       }
-
-       mfc_debug_leave();
-
-       return ret;
-}
-
-/* Query buffer */
-static int vidioc_querybuf(struct file *file, void *priv,
-                                                  struct v4l2_buffer *buf)
-{
-       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
-       int ret;
-
-       mfc_debug_enter();
-
-       if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-               mfc_debug(4, "dec dst querybuf, state: %d\n", ctx->state);
-               ret = vb2_querybuf(&ctx->vq_dst, buf);
-               if (ret != 0) {
-                       mfc_err_dev("dec dst: error in vb2_querybuf()\n");
-                       return ret;
-               }
-       } else if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               mfc_debug(4, "dec src querybuf, state: %d\n", ctx->state);
-               ret = vb2_querybuf(&ctx->vq_src, buf);
-               if (ret != 0) {
-                       mfc_err_dev("dec src: error in vb2_querybuf()\n");
-                       return ret;
-               }
-       } else {
-               mfc_err_dev("invalid buf type (%d)\n", buf->type);
-               return -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_mfc_ctx(file->private_data);
-       int ret = -EINVAL;
-
-       mfc_debug_enter();
-
-       if (ctx->state == MFCINST_ERROR) {
-               mfc_err_ctx("Call on QBUF after unrecoverable error\n");
-               return -EIO;
-       }
-
-       if (V4L2_TYPE_IS_MULTIPLANAR(buf->type) && !buf->length) {
-               mfc_err_ctx("multiplanar but length is zero\n");
-               return -EIO;
-       }
-
-       if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               mfc_debug(4, "dec src buf[%d] Q\n", buf->index);
-               if (buf->m.planes[0].bytesused > buf->m.planes[0].length) {
-                       mfc_err_ctx("data size (%d) must be less than "
-                                       "buffer size(%d)\n",
-                                       buf->m.planes[0].bytesused,
-                                       buf->m.planes[0].length);
-                       return -EIO;
-               }
-
-               s5p_mfc_qos_update_framerate(ctx);
-
-               if (!buf->m.planes[0].bytesused) {
-                       buf->m.planes[0].bytesused = buf->m.planes[0].length;
-                       mfc_debug(2, "Src size zero, changed to buf size %d\n",
-                                       buf->m.planes[0].bytesused);
-               } else {
-                       mfc_debug(2, "Src size = %d\n", buf->m.planes[0].bytesused);
-               }
-               ret = vb2_qbuf(&ctx->vq_src, buf);
-       } else {
-               mfc_debug(4, "dec dst buf[%d] Q\n", buf->index);
-               ret = vb2_qbuf(&ctx->vq_dst, buf);
-       }
-
-       mfc_debug_leave();
-       return ret;
-}
-
-/* Dequeue a buffer */
-static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
-{
-       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
-       struct s5p_mfc_dec *dec = ctx->dec_priv;
-       struct dec_dpb_ref_info *dstBuf, *srcBuf;
-       int ret;
-       int ncount = 0;
-
-       mfc_debug_enter();
-
-       if (ctx->state == MFCINST_ERROR) {
-               mfc_err_ctx("Call on DQBUF after unrecoverable error\n");
-               return -EIO;
-       }
-       if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               mfc_debug(4, "dec src buf[%d] DQ\n", buf->index);
-               ret = vb2_dqbuf(&ctx->vq_src, buf, file->f_flags & O_NONBLOCK);
-       } else {
-               mfc_debug(4, "dec dst buf[%d] DQ\n", buf->index);
-               ret = vb2_dqbuf(&ctx->vq_dst, buf, file->f_flags & O_NONBLOCK);
-
-               if (buf->index >= MFC_MAX_DPBS) {
-                       mfc_err_ctx("buffer index[%d] range over\n", buf->index);
-                       return -EINVAL;
-               }
-
-               /* Memcpy from dec->ref_info to shared memory */
-               srcBuf = &dec->ref_info[buf->index];
-               for (ncount = 0; ncount < MFC_MAX_DPBS; ncount++) {
-                       if (srcBuf->dpb[ncount].fd[0] == MFC_INFO_INIT_FD)
-                               break;
-                       mfc_debug(2, "[DPB] DQ index[%d] Released FD = %d\n",
-                                       buf->index, srcBuf->dpb[ncount].fd[0]);
-               }
-
-               if (dec->sh_handle.vaddr != NULL) {
-                       dstBuf = (struct dec_dpb_ref_info *)
-                                       dec->sh_handle.vaddr + buf->index;
-                       memcpy(dstBuf, srcBuf, sizeof(struct dec_dpb_ref_info));
-                       dstBuf->index = buf->index;
-               }
-       }
-       mfc_debug_leave();
-       return ret;
-}
-
-/* Stream on */
-static int vidioc_streamon(struct file *file, void *priv,
-                          enum v4l2_buf_type type)
-{
-       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
-       int ret = -EINVAL;
-
-       mfc_debug_enter();
-
-       if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               mfc_debug(4, "dec src streamon\n");
-               ret = vb2_streamon(&ctx->vq_src, type);
-       } else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-               mfc_debug(4, "dec dst streamon\n");
-               ret = vb2_streamon(&ctx->vq_dst, type);
-
-               if (!ret)
-                       s5p_mfc_qos_on(ctx);
-       } else {
-               mfc_err_ctx("unknown v4l2 buffer type\n");
-       }
-
-       mfc_debug(2, "src: %d, dst: %d,  state = %d, dpb_count = %d\n",
-                 s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->src_buf_queue),
-                 s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->dst_buf_queue),
-                 ctx->state, ctx->dpb_count);
-
-       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_mfc_ctx(file->private_data);
-       int ret = -EINVAL;
-
-       mfc_debug_enter();
-
-       if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               mfc_debug(4, "dec src streamoff\n");
-               s5p_mfc_qos_reset_last_framerate(ctx);
-
-               ret = vb2_streamoff(&ctx->vq_src, type);
-       } else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-               mfc_debug(4, "dec dst streamoff\n");
-               ret = vb2_streamoff(&ctx->vq_dst, type);
-               if (!ret)
-                       s5p_mfc_qos_off(ctx);
-       } else {
-               mfc_err_ctx("unknown v4l2 buffer type\n");
-       }
-
-       mfc_debug_leave();
-
-       return ret;
-}
-
-/* Query a ctrl */
-static int vidioc_queryctrl(struct file *file, void *priv,
-                           struct v4l2_queryctrl *qc)
-{
-       struct v4l2_queryctrl *c;
-
-       c = mfc_dec_get_ctrl(qc->id);
-       if (!c) {
-               mfc_err_dev("[CTRLS] not supported control id (%#x)\n", qc->id);
-               return -EINVAL;
-       }
-
-       *qc = *c;
-       return 0;
-}
-
-static int mfc_dec_ext_info(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       int val = 0;
-
-       val |= DEC_SET_DYNAMIC_DPB;
-       if (MFC_FEATURE_SUPPORT(dev, dev->pdata->skype))
-               val |= DEC_SET_SKYPE_FLAG;
-
-       mfc_debug(5, "[CTRLS] ext info val: %#x\n", val);
-
-       return val;
-}
-
-/* Get ctrl */
-static int mfc_dec_get_ctrl_val(struct s5p_mfc_ctx *ctx, struct v4l2_control *ctrl)
-{
-       struct s5p_mfc_dev *dev;
-       struct s5p_mfc_dec *dec;
-       struct s5p_mfc_ctx_ctrl *ctx_ctrl;
-       int found = 0;
-
-       if (!ctx) {
-               mfc_err_dev("no mfc context to run\n");
-               return -EINVAL;
-       }
-       dev = ctx->dev;
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return -EINVAL;
-       }
-       dec = ctx->dec_priv;
-       if (!dec) {
-               mfc_err_dev("no mfc decoder to run\n");
-               return -EINVAL;
-       }
-
-       switch (ctrl->id) {
-       case V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER:
-               ctrl->value = dec->loop_filter_mpeg4;
-               break;
-       case V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY:
-               ctrl->value = dec->display_delay;
-               break;
-       case V4L2_CID_CACHEABLE:
-               mfc_debug(5, "it is supported only V4L2_MEMORY_MMAP\n");
-               break;
-       case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:
-               if (ctx->state >= MFCINST_HEAD_PARSED &&
-                   ctx->state < MFCINST_ABORT) {
-                       ctrl->value = ctx->dpb_count;
-                       break;
-               } else if (ctx->state != MFCINST_INIT) {
-                       mfc_err_ctx("Decoding not initialised\n");
-                       return -EINVAL;
-               }
-
-               /* Should wait for the header to be parsed */
-               if (s5p_mfc_wait_for_done_ctx(ctx,
-                               S5P_FIMV_R2H_CMD_SEQ_DONE_RET)) {
-                       s5p_mfc_cleanup_work_bit_and_try_run(ctx);
-                       return -EIO;
-               }
-
-               if (ctx->state >= MFCINST_HEAD_PARSED &&
-                   ctx->state < MFCINST_ABORT) {
-                       ctrl->value = ctx->dpb_count;
-               } else {
-                       mfc_err_ctx("Decoding not initialised\n");
-                       return -EINVAL;
-               }
-               break;
-       case V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE:
-               ctrl->value = dec->slice_enable;
-               break;
-       case V4L2_CID_MPEG_MFC51_VIDEO_PACKED_PB:
-               /* Not used */
-               break;
-       case V4L2_CID_MPEG_MFC51_VIDEO_CRC_ENABLE:
-               ctrl->value = dec->crc_enable;
-               break;
-       case V4L2_CID_MPEG_MFC51_VIDEO_CHECK_STATE:
-               if (ctx->is_dpb_realloc && ctx->state == MFCINST_HEAD_PARSED)
-                       ctrl->value = MFCSTATE_DEC_S3D_REALLOC;
-               else if (ctx->state == MFCINST_RES_CHANGE_FLUSH
-                               || ctx->state == MFCINST_RES_CHANGE_END
-                               || ctx->state == MFCINST_HEAD_PARSED)
-                       ctrl->value = MFCSTATE_DEC_RES_DETECT;
-               else if (ctx->state == MFCINST_FINISHING)
-                       ctrl->value = MFCSTATE_DEC_TERMINATING;
-               else
-                       ctrl->value = MFCSTATE_PROCESSING;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING:
-               ctrl->value = dec->sei_parse;
-               break;
-       case V4L2_CID_MPEG_MFC51_VIDEO_I_FRAME_DECODING:
-               ctrl->value = dec->idr_decoding;
-               break;
-       case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_RATE:
-               ctrl->value = s5p_mfc_qos_get_framerate(ctx);
-               break;
-       case V4L2_CID_MPEG_MFC_GET_VERSION_INFO:
-               ctrl->value = dev->pdata->ip_ver;
-               break;
-       case V4L2_CID_MPEG_VIDEO_QOS_RATIO:
-               ctrl->value = ctx->qos_ratio;
-               break;
-       case V4L2_CID_MPEG_MFC_SET_DYNAMIC_DPB_MODE:
-               ctrl->value = dec->is_dynamic_dpb;
-               break;
-       case V4L2_CID_MPEG_MFC_GET_EXT_INFO:
-               ctrl->value = mfc_dec_ext_info(ctx);
-               break;
-       case V4L2_CID_MPEG_MFC_GET_10BIT_INFO:
-               ctrl->value = ctx->is_10bit;
-               break;
-       case V4L2_CID_MPEG_MFC_GET_DRIVER_INFO:
-               ctrl->value = MFC_DRIVER_INFO;
-               break;
-       default:
-               list_for_each_entry(ctx_ctrl, &ctx->ctrls, list) {
-                       if (!(ctx_ctrl->type & MFC_CTRL_TYPE_GET))
-                               continue;
-
-                       if (ctx_ctrl->id == ctrl->id) {
-                               if (ctx_ctrl->has_new) {
-                                       ctx_ctrl->has_new = 0;
-                                       ctrl->value = ctx_ctrl->val;
-                               } else {
-                                       mfc_debug(5, "[CTRLS] Control value "\
-                                                       "is not up to date: "\
-                                                       "0x%08x\n", ctrl->id);
-                                       return -EINVAL;
-                               }
-
-                               found = 1;
-                               break;
-                       }
-               }
-
-               if (!found) {
-                       mfc_err_ctx("Invalid control: 0x%08x\n", ctrl->id);
-                       return -EINVAL;
-               }
-               break;
-       }
-
-       mfc_debug(5, "[CTRLS] get id: %#x, value: %d\n", ctrl->id, ctrl->value);
-
-       return 0;
-}
-
-/* Get a ctrl */
-static int vidioc_g_ctrl(struct file *file, void *priv,
-                       struct v4l2_control *ctrl)
-{
-       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
-       int ret = 0;
-
-       mfc_debug_enter();
-       ret = mfc_dec_get_ctrl_val(ctx, ctrl);
-       mfc_debug_leave();
-
-       return ret;
-}
-
-/* Set a ctrl */
-static int vidioc_s_ctrl(struct file *file, void *priv,
-                        struct v4l2_control *ctrl)
-{
-       struct s5p_mfc_dev *dev = video_drvdata(file);
-       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
-       struct s5p_mfc_dec *dec;
-       struct s5p_mfc_ctx_ctrl *ctx_ctrl;
-       int ret = 0;
-       int found = 0;
-
-       mfc_debug_enter();
-
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return -EINVAL;
-       }
-
-       dec = ctx->dec_priv;
-       if (!dec) {
-               mfc_err_dev("no mfc decoder to run\n");
-               return -EINVAL;
-       }
-
-       ret = mfc_dec_check_ctrl_val(ctx, ctrl);
-       if (ret)
-               return ret;
-
-       mfc_debug(5, "[CTRLS] set id: %#x, value: %d\n", ctrl->id, ctrl->value);
-
-       switch (ctrl->id) {
-       case V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER:
-               dec->loop_filter_mpeg4 = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY:
-               dec->display_delay = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE:
-               dec->slice_enable = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC51_VIDEO_PACKED_PB:
-               /* Not used */
-               break;
-       case V4L2_CID_MPEG_MFC51_VIDEO_CRC_ENABLE:
-               dec->crc_enable = ctrl->value;
-               break;
-       case V4L2_CID_CACHEABLE:
-               mfc_debug(5, "it is supported only V4L2_MEMORY_MMAP\n");
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING:
-               dec->sei_parse = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC51_VIDEO_I_FRAME_DECODING:
-               dec->idr_decoding = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_DECODER_IMMEDIATE_DISPLAY:
-               dec->immediate_display = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_DECODER_DECODING_TIMESTAMP_MODE:
-               dec->is_dts_mode = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_DECODER_WAIT_DECODING_START:
-               ctx->wait_state = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC_SET_DUAL_DPB_MODE:
-               mfc_err_dev("[DPB] not supported CID: 0x%x\n",ctrl->id);
-               break;
-       case V4L2_CID_MPEG_VIDEO_QOS_RATIO:
-               ctx->qos_ratio = ctrl->value;
-               mfc_info_ctx("[QoS] set %d qos_ratio\n", ctrl->value);
-               break;
-       case V4L2_CID_MPEG_MFC_SET_DYNAMIC_DPB_MODE:
-               dec->is_dynamic_dpb = ctrl->value;
-               if (dec->is_dynamic_dpb == 0)
-                       mfc_err_dev("[DPB] is_dynamic_dpb is 0. it has to be enabled\n");
-               break;
-       case V4L2_CID_MPEG_MFC_SET_USER_SHARED_HANDLE:
-               if (dec->sh_handle.fd == -1) {
-                       dec->sh_handle.fd = ctrl->value;
-                       if (s5p_mfc_mem_get_user_shared_handle(ctx, &dec->sh_handle))
-                               return -EINVAL;
-                       else
-                               mfc_debug(2, "[MEMINFO][DPB] shared handle fd: %d, vaddr: 0x%p\n",
-                                               dec->sh_handle.fd, dec->sh_handle.vaddr);
-               }
-               break;
-       case V4L2_CID_MPEG_MFC_SET_BUF_PROCESS_TYPE:
-               ctx->buf_process_type = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_BLACK_BAR_DETECT:
-               dec->detect_black_bar = ctrl->value;
-               break;
-       default:
-               list_for_each_entry(ctx_ctrl, &ctx->ctrls, list) {
-                       if (!(ctx_ctrl->type & MFC_CTRL_TYPE_SET))
-                               continue;
-
-                       if (ctx_ctrl->id == ctrl->id) {
-                               ctx_ctrl->has_new = 1;
-                               ctx_ctrl->val = ctrl->value;
-
-                               found = 1;
-                               break;
-                       }
-               }
-
-               if (!found) {
-                       mfc_err_ctx("Invalid control: 0x%08x\n", ctrl->id);
-                       return -EINVAL;
-               }
-               break;
-       }
-
-       mfc_debug_leave();
-
-       return 0;
-}
-
-/* Get cropping information */
-static int vidioc_g_crop(struct file *file, void *priv,
-               struct v4l2_crop *cr)
-{
-       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
-       struct s5p_mfc_dec *dec = ctx->dec_priv;
-
-       mfc_debug_enter();
-
-       if (!ready_to_get_crop(ctx)) {
-               mfc_debug(2, "ready to get crop failed\n");
-               return -EINVAL;
-       }
-
-       if (ctx->state == MFCINST_RUNNING && dec->detect_black_bar
-                       && dec->black_bar_updated) {
-               cr->c.left = dec->black_bar.left;
-               cr->c.top = dec->black_bar.top;
-               cr->c.width = dec->black_bar.width;
-               cr->c.height = dec->black_bar.height;
-               mfc_debug(2, "[FRAME][BLACKBAR] Cropping info: l=%d t=%d w=%d h=%d\n",
-                               dec->black_bar.left,
-                               dec->black_bar.top,
-                               dec->black_bar.width,
-                               dec->black_bar.height);
-       } else {
-               if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_H264 ||
-                       ctx->src_fmt->fourcc == V4L2_PIX_FMT_HEVC ||
-                       ctx->src_fmt->fourcc == V4L2_PIX_FMT_BPG) {
-                       cr->c.left = dec->cr_left;
-                       cr->c.top = dec->cr_top;
-                       cr->c.width = ctx->img_width - dec->cr_left - dec->cr_right;
-                       cr->c.height = ctx->img_height - dec->cr_top - dec->cr_bot;
-                       mfc_debug(2, "[FRAME] Cropping info: l=%d t=%d " \
-                                       "w=%d h=%d (r=%d b=%d fw=%d fh=%d)\n",
-                                       dec->cr_left, dec->cr_top,
-                                       cr->c.width, cr->c.height,
-                                       dec->cr_right, dec->cr_bot,
-                                       ctx->img_width, ctx->img_height);
-               } else {
-                       cr->c.left = 0;
-                       cr->c.top = 0;
-                       cr->c.width = ctx->img_width;
-                       cr->c.height = ctx->img_height;
-                       mfc_debug(2, "[FRAME] Cropping info: w=%d h=%d fw=%d fh=%d\n",
-                                       cr->c.width, cr->c.height,
-                                       ctx->img_width, ctx->img_height);
-               }
-       }
-
-       mfc_debug_leave();
-       return 0;
-}
-
-static int vidioc_g_ext_ctrls(struct file *file, void *priv,
-                       struct v4l2_ext_controls *f)
-{
-       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
-       struct v4l2_ext_control *ext_ctrl;
-       struct v4l2_control ctrl;
-       int i;
-       int ret = 0;
-
-       if (f->which != V4L2_CTRL_CLASS_MPEG)
-               return -EINVAL;
-
-       for (i = 0; i < f->count; i++) {
-               ext_ctrl = (f->controls + i);
-
-               ctrl.id = ext_ctrl->id;
-
-               ret = mfc_dec_get_ctrl_val(ctx, &ctrl);
-               if (ret == 0) {
-                       ext_ctrl->value = ctrl.value;
-               } else {
-                       f->error_idx = i;
-                       break;
-               }
-
-               mfc_debug(5, "[CTRLS][%d] id: %#x, value: %d\n",
-                               i, ext_ctrl->id, ext_ctrl->value);
-       }
-
-       return ret;
-}
-
-/* v4l2_ioctl_ops */
-static const struct v4l2_ioctl_ops s5p_mfc_dec_ioctl_ops = {
-       .vidioc_querycap                = vidioc_querycap,
-       .vidioc_enum_fmt_vid_cap_mplane = vidioc_enum_fmt_vid_cap_mplane,
-       .vidioc_enum_fmt_vid_out_mplane = vidioc_enum_fmt_vid_out_mplane,
-       .vidioc_g_fmt_vid_cap_mplane    = vidioc_g_fmt_vid_cap_mplane,
-       .vidioc_g_fmt_vid_out_mplane    = vidioc_g_fmt_vid_out_mplane,
-       .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_vid_cap_mplane,
-       .vidioc_s_fmt_vid_out_mplane    = vidioc_s_fmt_vid_out_mplane,
-       .vidioc_reqbufs                 = vidioc_reqbufs,
-       .vidioc_querybuf                = vidioc_querybuf,
-       .vidioc_qbuf                    = vidioc_qbuf,
-       .vidioc_dqbuf                   = vidioc_dqbuf,
-       .vidioc_streamon                = vidioc_streamon,
-       .vidioc_streamoff               = vidioc_streamoff,
-       .vidioc_queryctrl               = vidioc_queryctrl,
-       .vidioc_g_ctrl                  = vidioc_g_ctrl,
-       .vidioc_s_ctrl                  = vidioc_s_ctrl,
-       .vidioc_g_crop                  = vidioc_g_crop,
-       .vidioc_g_ext_ctrls             = vidioc_g_ext_ctrls,
-};
-
-const struct v4l2_ioctl_ops *s5p_mfc_get_dec_v4l2_ioctl_ops(void)
-{
-       return &s5p_mfc_dec_ioctl_ops;
-}
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_dec.h b/drivers/media/platform/exynos/mfc/s5p_mfc_dec.h
deleted file mode 100644 (file)
index 24e48f7..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_dec.h
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __S5P_MFC_DEC_H
-#define __S5P_MFC_DEC_H __FILE__
-
-#include "s5p_mfc_common.h"
-
-const struct v4l2_ioctl_ops *s5p_mfc_get_dec_v4l2_ioctl_ops(void);
-
-#endif /* __S5P_MFC_DEC_H */
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_dec_internal.h b/drivers/media/platform/exynos/mfc/s5p_mfc_dec_internal.h
deleted file mode 100644 (file)
index 07e88c5..0000000
+++ /dev/null
@@ -1,542 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_dec_internal.h
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __S5P_MFC_DEC_INTERNAL_H
-#define __S5P_MFC_DEC_INTERNAL_H __FILE__
-
-#include "s5p_mfc_common.h"
-
-struct s5p_mfc_fmt dec_formats[] = {
-       {
-               .name = "4:2:0 3 Planes Y/Cb/Cr",
-               .fourcc = V4L2_PIX_FMT_YUV420M,
-               .codec_mode = MFC_FORMATS_NO_CODEC,
-               .type = MFC_FMT_FRAME,
-               .num_planes = 3,
-               .mem_planes = 3,
-       },
-       {
-               .name = "4:2:0 3 Planes Y/Cb/Cr single",
-               .fourcc = V4L2_PIX_FMT_YUV420N,
-               .codec_mode = MFC_FORMATS_NO_CODEC,
-               .type = MFC_FMT_FRAME,
-               .num_planes = 3,
-               .mem_planes = 1,
-       },
-       {
-               .name = "4:2:0 3 Planes Y/Cr/Cb",
-               .fourcc = V4L2_PIX_FMT_YVU420M,
-               .codec_mode = MFC_FORMATS_NO_CODEC,
-               .type = MFC_FMT_FRAME,
-               .num_planes = 3,
-               .mem_planes = 3,
-       },
-       {
-               .name = "4:2:0 2 Planes Y/CbCr",
-               .fourcc = V4L2_PIX_FMT_NV12M,
-               .codec_mode = MFC_FORMATS_NO_CODEC,
-               .type = MFC_FMT_FRAME,
-               .num_planes = 2,
-               .mem_planes = 2,
-       },
-       {
-               .name = "4:2:0 2 Planes Y/CbCr single",
-               .fourcc = V4L2_PIX_FMT_NV12N,
-               .codec_mode = MFC_FORMATS_NO_CODEC,
-               .type = MFC_FMT_FRAME,
-               .num_planes = 2,
-               .mem_planes = 1,
-       },
-       {
-               .name = "4:2:0 2 Planes Y/CbCr 8+2 10bit",
-               .fourcc = V4L2_PIX_FMT_NV12M_S10B,
-               .codec_mode = MFC_FORMATS_NO_CODEC,
-               .type = MFC_FMT_FRAME | MFC_FMT_10BIT,
-               .num_planes = 2,
-               .mem_planes = 2,
-       },
-       {
-               .name = "4:2:0 2 Planes Y/CbCr 10bit single",
-               .fourcc = V4L2_PIX_FMT_NV12N_10B,
-               .codec_mode = MFC_FORMATS_NO_CODEC,
-               .type = MFC_FMT_FRAME | MFC_FMT_10BIT,
-               .num_planes = 2,
-               .mem_planes = 1,
-       },
-       {
-               .name = "4:2:0 2 Planes Y/CbCr P010 10bit",
-               .fourcc = V4L2_PIX_FMT_NV12M_P010,
-               .codec_mode = MFC_FORMATS_NO_CODEC,
-               .type = MFC_FMT_FRAME | MFC_FMT_10BIT,
-               .num_planes = 2,
-               .mem_planes = 2,
-       },
-       {
-               .name = "4:2:0 2 Planes Y/CrCb",
-               .fourcc = V4L2_PIX_FMT_NV21M,
-               .codec_mode = MFC_FORMATS_NO_CODEC,
-               .type = MFC_FMT_FRAME,
-               .num_planes = 2,
-               .mem_planes = 2,
-       },
-       {
-               .name = "4:2:0 2 Planes Y/CrCb 8+2 10bit",
-               .fourcc = V4L2_PIX_FMT_NV21M_S10B,
-               .codec_mode = MFC_FORMATS_NO_CODEC,
-               .type = MFC_FMT_FRAME | MFC_FMT_10BIT,
-               .num_planes = 2,
-               .mem_planes = 2,
-       },
-       {
-               .name = "4:2:0 2 Planes Y/CrCb P010 10bit",
-               .fourcc = V4L2_PIX_FMT_NV21M_P010,
-               .codec_mode = MFC_FORMATS_NO_CODEC,
-               .type = MFC_FMT_FRAME | MFC_FMT_10BIT,
-               .num_planes = 2,
-               .mem_planes = 2,
-       },
-       {
-               .name = "4:2:2 2 Planes Y/CbCr",
-               .fourcc = V4L2_PIX_FMT_NV16M,
-               .codec_mode = MFC_FORMATS_NO_CODEC,
-               .type = MFC_FMT_FRAME | MFC_FMT_422,
-               .num_planes = 2,
-               .mem_planes = 2,
-       },
-       {
-               .name = "4:2:2 2 Planes Y/CbCr 8+2 10bit",
-               .fourcc = V4L2_PIX_FMT_NV16M_S10B,
-               .codec_mode = MFC_FORMATS_NO_CODEC,
-               .type = MFC_FMT_FRAME | MFC_FMT_10BIT | MFC_FMT_422,
-               .num_planes = 2,
-               .mem_planes = 2,
-       },
-       {
-               .name = "4:2:2 2 Planes Y/CbCr P210 10bit",
-               .fourcc = V4L2_PIX_FMT_NV16M_P210,
-               .codec_mode = MFC_FORMATS_NO_CODEC,
-               .type = MFC_FMT_FRAME | MFC_FMT_10BIT | MFC_FMT_422,
-               .num_planes = 2,
-               .mem_planes = 2,
-       },
-       {
-               .name = "4:2:2 2 Planes Y/CrCb",
-               .fourcc = V4L2_PIX_FMT_NV61M,
-               .codec_mode = MFC_FORMATS_NO_CODEC,
-               .type = MFC_FMT_FRAME | MFC_FMT_422,
-               .num_planes = 2,
-               .mem_planes = 2,
-       },
-       {
-               .name = "4:2:2 2 Planes Y/CrCb 8+2 10bit",
-               .fourcc = V4L2_PIX_FMT_NV61M_S10B,
-               .codec_mode = MFC_FORMATS_NO_CODEC,
-               .type = MFC_FMT_FRAME | MFC_FMT_10BIT | MFC_FMT_422,
-               .num_planes = 2,
-               .mem_planes = 2,
-       },
-       {
-               .name = "4:2:2 2 Planes Y/CrCb P210 10bit",
-               .fourcc = V4L2_PIX_FMT_NV61M_P210,
-               .codec_mode = MFC_FORMATS_NO_CODEC,
-               .type = MFC_FMT_FRAME | MFC_FMT_10BIT | MFC_FMT_422,
-               .num_planes = 2,
-               .mem_planes = 2,
-       },
-       {
-               .name = "H264 Encoded Stream",
-               .fourcc = V4L2_PIX_FMT_H264,
-               .codec_mode = S5P_FIMV_CODEC_H264_DEC,
-               .type = MFC_FMT_STREAM,
-               .num_planes = 1,
-               .mem_planes = 1,
-       },
-       {
-               .name = "H264/MVC Encoded Stream",
-               .fourcc = V4L2_PIX_FMT_H264_MVC,
-               .codec_mode = S5P_FIMV_CODEC_H264_MVC_DEC,
-               .type = MFC_FMT_STREAM,
-               .num_planes = 1,
-               .mem_planes = 1,
-       },
-       {
-               .name = "H263 Encoded Stream",
-               .fourcc = V4L2_PIX_FMT_H263,
-               .codec_mode = S5P_FIMV_CODEC_H263_DEC,
-               .type = MFC_FMT_STREAM,
-               .num_planes = 1,
-               .mem_planes = 1,
-       },
-       {
-               .name = "MPEG1 Encoded Stream",
-               .fourcc = V4L2_PIX_FMT_MPEG1,
-               .codec_mode = S5P_FIMV_CODEC_MPEG2_DEC,
-               .type = MFC_FMT_STREAM,
-               .num_planes = 1,
-               .mem_planes = 1,
-       },
-       {
-               .name = "MPEG2 Encoded Stream",
-               .fourcc = V4L2_PIX_FMT_MPEG2,
-               .codec_mode = S5P_FIMV_CODEC_MPEG2_DEC,
-               .type = MFC_FMT_STREAM,
-               .num_planes = 1,
-               .mem_planes = 1,
-       },
-       {
-               .name = "MPEG4 Encoded Stream",
-               .fourcc = V4L2_PIX_FMT_MPEG4,
-               .codec_mode = S5P_FIMV_CODEC_MPEG4_DEC,
-               .type = MFC_FMT_STREAM,
-               .num_planes = 1,
-               .mem_planes = 1,
-       },
-       {
-               .name = "FIMV Encoded Stream",
-               .fourcc = V4L2_PIX_FMT_FIMV,
-               .codec_mode = S5P_FIMV_CODEC_MPEG4_DEC,
-               .type = MFC_FMT_STREAM,
-               .num_planes = 1,
-               .mem_planes = 1,
-       },
-       {
-               .name = "FIMV1 Encoded Stream",
-               .fourcc = V4L2_PIX_FMT_FIMV1,
-               .codec_mode = S5P_FIMV_CODEC_FIMV1_DEC,
-               .type = MFC_FMT_STREAM,
-               .num_planes = 1,
-               .mem_planes = 1,
-       },
-       {
-               .name = "FIMV2 Encoded Stream",
-               .fourcc = V4L2_PIX_FMT_FIMV2,
-               .codec_mode = S5P_FIMV_CODEC_FIMV2_DEC,
-               .type = MFC_FMT_STREAM,
-               .num_planes = 1,
-               .mem_planes = 1,
-       },
-       {
-               .name = "FIMV3 Encoded Stream",
-               .fourcc = V4L2_PIX_FMT_FIMV3,
-               .codec_mode = S5P_FIMV_CODEC_FIMV3_DEC,
-               .type = MFC_FMT_STREAM,
-               .num_planes = 1,
-               .mem_planes = 1,
-       },
-       {
-               .name = "FIMV4 Encoded Stream",
-               .fourcc = V4L2_PIX_FMT_FIMV4,
-               .codec_mode = S5P_FIMV_CODEC_FIMV4_DEC,
-               .type = MFC_FMT_STREAM,
-               .num_planes = 1,
-               .mem_planes = 1,
-       },
-       {
-               .name = "XviD Encoded Stream",
-               .fourcc = V4L2_PIX_FMT_XVID,
-               .codec_mode = S5P_FIMV_CODEC_MPEG4_DEC,
-               .type = MFC_FMT_STREAM,
-               .num_planes = 1,
-               .mem_planes = 1,
-       },
-       {
-               .name = "VC1 Encoded Stream",
-               .fourcc = V4L2_PIX_FMT_VC1_ANNEX_G,
-               .codec_mode = S5P_FIMV_CODEC_VC1_DEC,
-               .type = MFC_FMT_STREAM,
-               .num_planes = 1,
-               .mem_planes = 1,
-       },
-       {
-               .name = "VC1 RCV Encoded Stream",
-               .fourcc = V4L2_PIX_FMT_VC1_ANNEX_L,
-               .codec_mode = S5P_FIMV_CODEC_VC1_RCV_DEC,
-               .type = MFC_FMT_STREAM,
-               .num_planes = 1,
-               .mem_planes = 1,
-       },
-       {
-               .name = "VP8 Encoded Stream",
-               .fourcc = V4L2_PIX_FMT_VP8,
-               .codec_mode = S5P_FIMV_CODEC_VP8_DEC,
-               .type = MFC_FMT_STREAM,
-               .num_planes = 1,
-               .mem_planes = 1,
-       },
-       {
-               .name = "VP9 Encoded Stream",
-               .fourcc = V4L2_PIX_FMT_VP9,
-               .codec_mode = S5P_FIMV_CODEC_VP9_DEC,
-               .type = MFC_FMT_STREAM,
-               .num_planes = 1,
-               .mem_planes = 1,
-       },
-       {
-               .name = "HEVC Encoded Stream",
-               .fourcc = V4L2_PIX_FMT_HEVC,
-               .codec_mode = S5P_FIMV_CODEC_HEVC_DEC,
-               .type = MFC_FMT_STREAM,
-               .num_planes = 1,
-               .mem_planes = 1,
-       },
-       {
-               .name = "BPG Encoded Stream",
-               .fourcc = V4L2_PIX_FMT_BPG,
-               .codec_mode = S5P_FIMV_CODEC_BPG_DEC,
-               .type = MFC_FMT_STREAM,
-               .num_planes = 1,
-               .mem_planes = 1,
-       },
-};
-
-#define NUM_FORMATS ARRAY_SIZE(dec_formats)
-
-static struct v4l2_queryctrl controls[] = {
-       {
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "H.264 Display Delay",
-               .minimum = -1,
-               .maximum = 32,
-               .step = 1,
-               .default_value = -1,
-       },
-       {
-               .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_MPEG_MFC51_VIDEO_PACKED_PB,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "Packed PB Enable",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Frame Tag",
-               .minimum = 0,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_CACHEABLE,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "Cacheable flag",
-               .minimum = 0,
-               .maximum = 3,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_CRC_ENABLE,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "CRC enable",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_LUMA,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "CRC data",
-               .minimum = 0,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_CHROMA,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "CRC data",
-               .minimum = 0,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_DISPLAY_STATUS,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Display status",
-               .minimum = 0,
-               .maximum = 3,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TYPE,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Frame type",
-               .minimum = 0,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "Frame pack sei parse flag",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_I_FRAME_DECODING,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "I frame decoding mode",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_RATE,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Frames per second in 1000x scale",
-               .minimum = 1,
-               .maximum = 480000,
-               .step = 1,
-               .default_value = 60000,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_DECODER_IMMEDIATE_DISPLAY,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "Immediate Display Enable",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_DECODER_DECODING_TIMESTAMP_MODE,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "Decoding Timestamp Mode Enable",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_DECODER_WAIT_DECODING_START,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "Wait until buffer setting done",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC_GET_VERSION_INFO,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Get MFC version information",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC_SET_DUAL_DPB_MODE,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "Set Dual DPB mode",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_QOS_RATIO,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "QoS ratio value",
-               .minimum = 20,
-               .maximum = 1000,
-               .step = 10,
-               .default_value = 100,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC_SET_DYNAMIC_DPB_MODE,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Set dynamic DPB",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC_SET_USER_SHARED_HANDLE,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Set dynamic DPB",
-               .minimum = 0,
-               .maximum = 65535,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC_GET_EXT_INFO,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Get extra information",
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC_SET_BUF_PROCESS_TYPE,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Set buffer process type",
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC_GET_10BIT_INFO,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "10 bit contents information",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_BLACK_BAR_DETECT,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "Set black bar detection option",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-};
-
-#define NUM_CTRLS ARRAY_SIZE(controls)
-
-#endif /* __S5P_MFC_DEC_INTERNAL_H */
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_dec_ops.c b/drivers/media/platform/exynos/mfc/s5p_mfc_dec_ops.c
deleted file mode 100644 (file)
index 89ffb16..0000000
+++ /dev/null
@@ -1,896 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_dec_ops.c
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include  "s5p_mfc_common.h"
-
-#include "s5p_mfc_reg.h"
-
-#define NUM_CTRL_CFGS ARRAY_SIZE(mfc_ctrl_list)
-
-struct s5p_mfc_ctrl_cfg mfc_ctrl_list[] = {
-       {
-               .type = MFC_CTRL_TYPE_SET,
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG,
-               .is_volatile = 1,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_D_PICTURE_TAG,
-               .mask = 0xFFFFFFFF,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_NONE,
-               .flag_addr = 0,
-               .flag_shft = 0,
-       },
-       {
-               .type = MFC_CTRL_TYPE_GET_DST,
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG,
-               .is_volatile = 0,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_D_RET_PICTURE_TAG_TOP,
-               .mask = 0xFFFFFFFF,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_NONE,
-               .flag_addr = 0,
-               .flag_shft = 0,
-       },
-       {
-               .type = MFC_CTRL_TYPE_GET_DST,
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_DISPLAY_STATUS,
-               .is_volatile = 0,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_D_DISPLAY_STATUS,
-               .mask = 0x7,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_NONE,
-               .flag_addr = 0,
-               .flag_shft = 0,
-       },
-       /* CRC related definitions are based on non-H.264 type */
-       {
-               .type = MFC_CTRL_TYPE_GET_DST,
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_LUMA,
-               .is_volatile = 0,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_D_DISPLAY_FIRST_PLANE_CRC,
-               .mask = 0xFFFFFFFF,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_NONE,
-               .flag_addr = 0,
-               .flag_shft = 0,
-       },
-       {
-               .type = MFC_CTRL_TYPE_GET_DST,
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_CHROMA,
-               .is_volatile = 0,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_D_DISPLAY_SECOND_PLANE_CRC,
-               .mask = 0xFFFFFFFF,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_NONE,
-               .flag_addr = 0,
-               .flag_shft = 0,
-       },
-       {
-               .type = MFC_CTRL_TYPE_GET_DST,
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_CHROMA1,
-               .is_volatile = 0,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_D_DISPLAY_THIRD_PLANE_CRC,
-               .mask = 0xFFFFFFFF,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_NONE,
-               .flag_addr = 0,
-               .flag_shft = 0,
-       },
-       {
-               .type = MFC_CTRL_TYPE_GET_DST,
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_2BIT_LUMA,
-               .is_volatile = 0,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_D_DISPLAY_FIRST_PLANE_2BIT_CRC,
-               .mask = 0xFFFFFFFF,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_NONE,
-               .flag_addr = 0,
-               .flag_shft = 0,
-       },
-       {
-               .type = MFC_CTRL_TYPE_GET_DST,
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_2BIT_CHROMA,
-               .is_volatile = 0,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_D_DISPLAY_SECOND_PLANE_2BIT_CRC,
-               .mask = 0xFFFFFFFF,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_NONE,
-               .flag_addr = 0,
-               .flag_shft = 0,
-       },
-       {
-               .type = MFC_CTRL_TYPE_GET_DST,
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_CRC_GENERATED,
-               .is_volatile = 0,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_D_DISPLAY_STATUS,
-               .mask = 0x1,
-               .shft = 6,
-               .flag_mode = MFC_CTRL_MODE_NONE,
-               .flag_addr = 0,
-               .flag_shft = 0,
-       },
-       {
-               .type = MFC_CTRL_TYPE_GET_DST,
-               .id = V4L2_CID_MPEG_VIDEO_H264_SEI_FP_AVAIL,
-               .is_volatile = 0,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_D_SEI_AVAIL,
-               .mask = 0x1,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_NONE,
-               .flag_addr = 0,
-               .flag_shft = 0,
-       },
-       {
-               .type = MFC_CTRL_TYPE_GET_DST,
-               .id = V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRGMENT_ID,
-               .is_volatile = 0,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_D_FRAME_PACK_ARRGMENT_ID,
-               .mask = 0xFFFFFFFF,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_NONE,
-               .flag_addr = 0,
-               .flag_shft = 0,
-       },
-       {
-               .type = MFC_CTRL_TYPE_GET_DST,
-               .id = V4L2_CID_MPEG_VIDEO_H264_SEI_FP_INFO,
-               .is_volatile = 0,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_D_FRAME_PACK_SEI_INFO,
-               .mask = 0x3FFFF,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_NONE,
-               .flag_addr = 0,
-               .flag_shft = 0,
-       },
-       {
-               .type = MFC_CTRL_TYPE_GET_DST,
-               .id = V4L2_CID_MPEG_VIDEO_H264_SEI_FP_GRID_POS,
-               .is_volatile = 0,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_D_FRAME_PACK_GRID_POS,
-               .mask = 0xFFFF,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_NONE,
-               .flag_addr = 0,
-               .flag_shft = 0,
-       },
-       {
-               .type = MFC_CTRL_TYPE_GET_DST,
-               .id = V4L2_CID_MPEG_VIDEO_H264_MVC_VIEW_ID,
-               .is_volatile = 0,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_D_MVC_VIEW_ID,
-               .mask = 0xFFFF,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_NONE,
-               .flag_addr = 0,
-               .flag_shft = 0,
-       },
-       {
-               .type = MFC_CTRL_TYPE_GET_DST,
-               .id = V4L2_CID_MPEG_VIDEO_SEI_MAX_PIC_AVERAGE_LIGHT,
-               .is_volatile = 0,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_D_CONTENT_LIGHT_LEVEL_INFO_SEI,
-               .mask = 0xFFFF,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_NONE,
-               .flag_addr = 0,
-               .flag_shft = 0,
-       },
-       {
-               .type = MFC_CTRL_TYPE_GET_DST,
-               .id = V4L2_CID_MPEG_VIDEO_SEI_MAX_CONTENT_LIGHT,
-               .is_volatile = 0,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_D_CONTENT_LIGHT_LEVEL_INFO_SEI,
-               .mask = 0xFFFF,
-               .shft = 16,
-               .flag_mode = MFC_CTRL_MODE_NONE,
-               .flag_addr = 0,
-               .flag_shft = 0,
-       },
-       {
-               .type = MFC_CTRL_TYPE_GET_DST,
-               .id = V4L2_CID_MPEG_VIDEO_SEI_MAX_DISPLAY_LUMINANCE,
-               .is_volatile = 0,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_0,
-               .mask = 0xFFFFFFFF,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_NONE,
-               .flag_addr = 0,
-               .flag_shft = 0,
-       },
-       {
-               .type = MFC_CTRL_TYPE_GET_DST,
-               .id = V4L2_CID_MPEG_VIDEO_SEI_MIN_DISPLAY_LUMINANCE,
-               .is_volatile = 0,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_1,
-               .mask = 0xFFFFFFFF,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_NONE,
-               .flag_addr = 0,
-               .flag_shft = 0,
-       },
-       {
-               .type = MFC_CTRL_TYPE_GET_DST,
-               .id = V4L2_CID_MPEG_VIDEO_MATRIX_COEFFICIENTS,
-               .is_volatile = 0,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_D_VIDEO_SIGNAL_TYPE,
-               .mask = 0xFF,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_NONE,
-               .flag_addr = 0,
-               .flag_shft = 0,
-       },
-       {
-               .type = MFC_CTRL_TYPE_GET_DST,
-               .id = V4L2_CID_MPEG_VIDEO_FORMAT,
-               .is_volatile = 0,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_D_VIDEO_SIGNAL_TYPE,
-               .mask = 0x7,
-               .shft = 26,
-               .flag_mode = MFC_CTRL_MODE_NONE,
-               .flag_addr = 0,
-               .flag_shft = 0,
-       },
-       {
-               .type = MFC_CTRL_TYPE_GET_DST,
-               .id = V4L2_CID_MPEG_VIDEO_FULL_RANGE_FLAG,
-               .is_volatile = 0,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_D_VIDEO_SIGNAL_TYPE,
-               .mask = 0x1,
-               .shft = 25,
-               .flag_mode = MFC_CTRL_MODE_NONE,
-               .flag_addr = 0,
-               .flag_shft = 0,
-       },
-       {
-               .type = MFC_CTRL_TYPE_GET_DST,
-               .id = V4L2_CID_MPEG_VIDEO_COLOUR_PRIMARIES,
-               .is_volatile = 0,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_D_VIDEO_SIGNAL_TYPE,
-               .mask = 0xFF,
-               .shft = 16,
-               .flag_mode = MFC_CTRL_MODE_NONE,
-               .flag_addr = 0,
-               .flag_shft = 0,
-       },
-       {
-               .type = MFC_CTRL_TYPE_GET_DST,
-               .id = V4L2_CID_MPEG_VIDEO_TRANSFER_CHARACTERISTICS,
-               .is_volatile = 0,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_D_VIDEO_SIGNAL_TYPE,
-               .mask = 0xFF,
-               .shft = 8,
-               .flag_mode = MFC_CTRL_MODE_NONE,
-               .flag_addr = 0,
-               .flag_shft = 0,
-       },
-       {
-               .type = MFC_CTRL_TYPE_GET_DST,
-               .id = V4L2_CID_MPEG_VIDEO_SEI_WHITE_POINT,
-               .is_volatile = 0,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_2,
-               .mask = 0xFFFFFFFF,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_NONE,
-               .flag_addr = 0,
-               .flag_shft = 0,
-       },
-       {
-               .type = MFC_CTRL_TYPE_GET_DST,
-               .id = V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_0,
-               .is_volatile = 0,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_3,
-               .mask = 0xFFFFFFFF,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_NONE,
-               .flag_addr = 0,
-               .flag_shft = 0,
-       },
-       {
-               .type = MFC_CTRL_TYPE_GET_DST,
-               .id = V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_1,
-               .is_volatile = 0,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_4,
-               .mask = 0xFFFFFFFF,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_NONE,
-               .flag_addr = 0,
-               .flag_shft = 0,
-       },
-       {
-               .type = MFC_CTRL_TYPE_GET_DST,
-               .id = V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_2,
-               .is_volatile = 0,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_5,
-               .mask = 0xFFFFFFFF,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_NONE,
-               .flag_addr = 0,
-               .flag_shft = 0,
-       },
-};
-
-static int s5p_mfc_dec_cleanup_ctx_ctrls(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_ctx_ctrl *ctx_ctrl;
-
-       while (!list_empty(&ctx->ctrls)) {
-               ctx_ctrl = list_entry((&ctx->ctrls)->next,
-                                     struct s5p_mfc_ctx_ctrl, list);
-               list_del(&ctx_ctrl->list);
-               kfree(ctx_ctrl);
-       }
-
-       INIT_LIST_HEAD(&ctx->ctrls);
-
-       return 0;
-}
-
-static int s5p_mfc_dec_init_ctx_ctrls(struct s5p_mfc_ctx *ctx)
-{
-       unsigned long i;
-       struct s5p_mfc_ctx_ctrl *ctx_ctrl;
-
-       INIT_LIST_HEAD(&ctx->ctrls);
-
-       for (i = 0; i < NUM_CTRL_CFGS; i++) {
-               ctx_ctrl = kzalloc(sizeof(struct s5p_mfc_ctx_ctrl), GFP_KERNEL);
-               if (ctx_ctrl == NULL) {
-                       mfc_err_dev("Failed to allocate context control "\
-                                       "id: 0x%08x, type: %d\n",
-                                       mfc_ctrl_list[i].id,
-                                       mfc_ctrl_list[i].type);
-
-                       s5p_mfc_dec_cleanup_ctx_ctrls(ctx);
-
-                       return -ENOMEM;
-               }
-
-               ctx_ctrl->type = mfc_ctrl_list[i].type;
-               ctx_ctrl->id = mfc_ctrl_list[i].id;
-               ctx_ctrl->addr = mfc_ctrl_list[i].addr;
-               ctx_ctrl->has_new = 0;
-               ctx_ctrl->val = 0;
-
-               list_add_tail(&ctx_ctrl->list, &ctx->ctrls);
-       }
-
-       return 0;
-}
-
-static void mfc_dec_remove_buf_ctrls(struct list_head *head)
-{
-       struct s5p_mfc_buf_ctrl *buf_ctrl;
-
-       while (!list_empty(head)) {
-               buf_ctrl = list_entry(head->next,
-                               struct s5p_mfc_buf_ctrl, list);
-               list_del(&buf_ctrl->list);
-               kfree(buf_ctrl);
-       }
-
-       INIT_LIST_HEAD(head);
-}
-
-static void s5p_mfc_dec_reset_buf_ctrls(struct list_head *head)
-{
-       struct s5p_mfc_buf_ctrl *buf_ctrl;
-
-       list_for_each_entry(buf_ctrl, head, list) {
-               buf_ctrl->has_new = 0;
-               buf_ctrl->val = 0;
-               buf_ctrl->old_val = 0;
-               buf_ctrl->updated = 0;
-       }
-}
-
-static int s5p_mfc_dec_init_buf_ctrls(struct s5p_mfc_ctx *ctx,
-       enum s5p_mfc_ctrl_type type, unsigned int index)
-{
-       unsigned long i;
-       struct s5p_mfc_ctx_ctrl *ctx_ctrl;
-       struct s5p_mfc_buf_ctrl *buf_ctrl;
-       struct list_head *head;
-
-       if (index >= MFC_MAX_BUFFERS) {
-               mfc_err_dev("Per-buffer control index is out of range\n");
-               return -EINVAL;
-       }
-
-       if (type & MFC_CTRL_TYPE_SRC) {
-               if (test_bit(index, &ctx->src_ctrls_avail)) {
-                       s5p_mfc_dec_reset_buf_ctrls(&ctx->src_ctrls[index]);
-
-                       return 0;
-               }
-
-               head = &ctx->src_ctrls[index];
-       } else if (type & MFC_CTRL_TYPE_DST) {
-               if (test_bit(index, &ctx->dst_ctrls_avail)) {
-                       s5p_mfc_dec_reset_buf_ctrls(&ctx->dst_ctrls[index]);
-
-                       return 0;
-               }
-
-               head = &ctx->dst_ctrls[index];
-       } else {
-               mfc_err_dev("Control type mismatch. type : %d\n", type);
-               return -EINVAL;
-       }
-
-       INIT_LIST_HEAD(head);
-
-       list_for_each_entry(ctx_ctrl, &ctx->ctrls, list) {
-               if (!(type & ctx_ctrl->type))
-                       continue;
-
-               /* find matched control configuration index */
-               for (i = 0; i < NUM_CTRL_CFGS; i++) {
-                       if (ctx_ctrl->id == mfc_ctrl_list[i].id)
-                               break;
-               }
-
-               if (i == NUM_CTRL_CFGS) {
-                       mfc_err_dev("Failed to find buffer control "\
-                                       "id: 0x%08x, type: %d\n",
-                                       ctx_ctrl->id, ctx_ctrl->type);
-                       continue;
-               }
-
-               buf_ctrl = kzalloc(sizeof(struct s5p_mfc_buf_ctrl), GFP_KERNEL);
-               if (buf_ctrl == NULL) {
-                       mfc_err_dev("Failed to allocate buffer control "\
-                                       "id: 0x%08x, type: %d\n",
-                                       mfc_ctrl_list[i].id,
-                                       mfc_ctrl_list[i].type);
-
-                       mfc_dec_remove_buf_ctrls(head);
-
-                       return -ENOMEM;
-               }
-
-               buf_ctrl->id = ctx_ctrl->id;
-               buf_ctrl->type = ctx_ctrl->type;
-               buf_ctrl->addr = ctx_ctrl->addr;
-
-               buf_ctrl->is_volatile = mfc_ctrl_list[i].is_volatile;
-               buf_ctrl->mode = mfc_ctrl_list[i].mode;
-               buf_ctrl->mask = mfc_ctrl_list[i].mask;
-               buf_ctrl->shft = mfc_ctrl_list[i].shft;
-               buf_ctrl->flag_mode = mfc_ctrl_list[i].flag_mode;
-               buf_ctrl->flag_addr = mfc_ctrl_list[i].flag_addr;
-               buf_ctrl->flag_shft = mfc_ctrl_list[i].flag_shft;
-
-               list_add_tail(&buf_ctrl->list, head);
-       }
-
-       s5p_mfc_dec_reset_buf_ctrls(head);
-
-       if (type & MFC_CTRL_TYPE_SRC)
-               set_bit(index, &ctx->src_ctrls_avail);
-       else
-               set_bit(index, &ctx->dst_ctrls_avail);
-
-       return 0;
-}
-
-static int s5p_mfc_dec_cleanup_buf_ctrls(struct s5p_mfc_ctx *ctx,
-       enum s5p_mfc_ctrl_type type, unsigned int index)
-{
-       struct list_head *head;
-
-       if (index >= MFC_MAX_BUFFERS) {
-               mfc_err_dev("Per-buffer control index is out of range\n");
-               return -EINVAL;
-       }
-
-       if (type & MFC_CTRL_TYPE_SRC) {
-               if (!(test_and_clear_bit(index, &ctx->src_ctrls_avail))) {
-                       return 0;
-               }
-
-               head = &ctx->src_ctrls[index];
-       } else if (type & MFC_CTRL_TYPE_DST) {
-               if (!(test_and_clear_bit(index, &ctx->dst_ctrls_avail))) {
-                       return 0;
-               }
-
-               head = &ctx->dst_ctrls[index];
-       } else {
-               mfc_err_dev("Control type mismatch. type : %d\n", type);
-               return -EINVAL;
-       }
-
-       mfc_dec_remove_buf_ctrls(head);
-
-       return 0;
-}
-
-static int s5p_mfc_dec_to_buf_ctrls(struct s5p_mfc_ctx *ctx, struct list_head *head)
-{
-       struct s5p_mfc_ctx_ctrl *ctx_ctrl;
-       struct s5p_mfc_buf_ctrl *buf_ctrl;
-
-       list_for_each_entry(ctx_ctrl, &ctx->ctrls, list) {
-               if (!(ctx_ctrl->type & MFC_CTRL_TYPE_SET) || !ctx_ctrl->has_new)
-                       continue;
-
-               list_for_each_entry(buf_ctrl, head, list) {
-                       if (!(buf_ctrl->type & MFC_CTRL_TYPE_SET))
-                               continue;
-
-                       if (buf_ctrl->id == ctx_ctrl->id) {
-                               buf_ctrl->has_new = 1;
-                               buf_ctrl->val = ctx_ctrl->val;
-                               if (buf_ctrl->is_volatile)
-                                       buf_ctrl->updated = 0;
-
-                               ctx_ctrl->has_new = 0;
-                               break;
-                       }
-               }
-       }
-
-       return 0;
-}
-
-static int s5p_mfc_dec_to_ctx_ctrls(struct s5p_mfc_ctx *ctx, struct list_head *head)
-{
-       struct s5p_mfc_ctx_ctrl *ctx_ctrl;
-       struct s5p_mfc_buf_ctrl *buf_ctrl;
-
-       list_for_each_entry(buf_ctrl, head, list) {
-               if (!(buf_ctrl->type & MFC_CTRL_TYPE_GET) || !buf_ctrl->has_new)
-                       continue;
-
-               list_for_each_entry(ctx_ctrl, &ctx->ctrls, list) {
-                       if (!(ctx_ctrl->type & MFC_CTRL_TYPE_GET))
-                               continue;
-
-                       if (ctx_ctrl->id == buf_ctrl->id) {
-                               ctx_ctrl->has_new = 1;
-                               ctx_ctrl->val = buf_ctrl->val;
-
-                               buf_ctrl->has_new = 0;
-                       }
-               }
-       }
-
-       return 0;
-}
-
-static int s5p_mfc_dec_set_buf_ctrls_val(struct s5p_mfc_ctx *ctx, struct list_head *head)
-{
-       struct s5p_mfc_buf_ctrl *buf_ctrl;
-       struct s5p_mfc_dec *dec = ctx->dec_priv;
-       struct s5p_mfc_dev *dev = ctx->dev;
-       unsigned int value = 0;
-
-       list_for_each_entry(buf_ctrl, head, list) {
-               if (!(buf_ctrl->type & MFC_CTRL_TYPE_SET) || !buf_ctrl->has_new)
-                       continue;
-
-               /* read old vlaue */
-               value = MFC_READL(buf_ctrl->addr);
-
-               /* save old vlaue for recovery */
-               if (buf_ctrl->is_volatile)
-                       buf_ctrl->old_val = (value >> buf_ctrl->shft) & buf_ctrl->mask;
-
-               /* write new value */
-               value &= ~(buf_ctrl->mask << buf_ctrl->shft);
-               value |= ((buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft);
-               MFC_WRITEL(value, buf_ctrl->addr);
-
-               /* set change flag bit */
-               if (buf_ctrl->flag_mode == MFC_CTRL_MODE_SFR) {
-                       value = MFC_READL(buf_ctrl->flag_addr);
-                       value |= (1 << buf_ctrl->flag_shft);
-                       MFC_WRITEL(value, buf_ctrl->flag_addr);
-               }
-
-               buf_ctrl->has_new = 0;
-               buf_ctrl->updated = 1;
-
-               if (buf_ctrl->id == V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG)
-                       dec->stored_tag = buf_ctrl->val;
-
-               mfc_debug(6, "[CTRLS] Set buffer control id: 0x%08x, val: %d\n",
-                               buf_ctrl->id, buf_ctrl->val);
-       }
-
-       return 0;
-}
-
-static int s5p_mfc_dec_get_buf_ctrls_val(struct s5p_mfc_ctx *ctx, struct list_head *head)
-{
-       struct s5p_mfc_buf_ctrl *buf_ctrl;
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_dec *dec = ctx->dec_priv;
-       unsigned int value = 0;
-
-       list_for_each_entry(buf_ctrl, head, list) {
-               if (!(buf_ctrl->type & MFC_CTRL_TYPE_GET))
-                       continue;
-
-               value = MFC_READL(buf_ctrl->addr);
-               value = (value >> buf_ctrl->shft) & buf_ctrl->mask;
-
-               buf_ctrl->val = value;
-               buf_ctrl->has_new = 1;
-
-               if (IS_VP9_DEC(ctx)) {
-                       if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_FULL_RANGE_FLAG)
-                               buf_ctrl->val = dec->color_range;
-                       else if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_COLOUR_PRIMARIES)
-                               buf_ctrl->val = dec->color_space;
-               }
-
-               mfc_debug(6, "[CTRLS] Get buffer control id: 0x%08x, val: %d\n",
-                               buf_ctrl->id, buf_ctrl->val);
-       }
-
-       return 0;
-}
-
-static int s5p_mfc_dec_set_buf_ctrls_val_nal_q_dec(struct s5p_mfc_ctx *ctx,
-                       struct list_head *head, DecoderInputStr *pInStr)
-{
-       struct s5p_mfc_buf_ctrl *buf_ctrl;
-       struct s5p_mfc_dec *dec = ctx->dec_priv;
-
-       mfc_debug_enter();
-
-       list_for_each_entry(buf_ctrl, head, list) {
-               if (!(buf_ctrl->type & MFC_CTRL_TYPE_SET) || !buf_ctrl->has_new)
-                       continue;
-               switch (buf_ctrl->id) {
-               case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG:
-                       pInStr->PictureTag &= ~(buf_ctrl->mask << buf_ctrl->shft);
-                       pInStr->PictureTag |=
-                               (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
-                       dec->stored_tag = buf_ctrl->val;
-                       break;
-               /* If new dynamic controls are added, insert here */
-               default:
-                       mfc_info_ctx("[NALQ] can't find control, id: 0x%x\n",
-                                       buf_ctrl->id);
-               }
-               buf_ctrl->has_new = 0;
-               buf_ctrl->updated = 1;
-
-               mfc_debug(6, "[NALQ][CTRLS] Set buffer control id: 0x%08x, val: %d\n",
-                               buf_ctrl->id, buf_ctrl->val);
-       }
-
-       mfc_debug_leave();
-
-       return 0;
-}
-
-static int s5p_mfc_dec_get_buf_ctrls_val_nal_q_dec(struct s5p_mfc_ctx *ctx,
-                       struct list_head *head, DecoderOutputStr *pOutStr)
-{
-       struct s5p_mfc_dec *dec = ctx->dec_priv;
-       struct s5p_mfc_buf_ctrl *buf_ctrl;
-       unsigned int value = 0;
-
-       mfc_debug_enter();
-
-       list_for_each_entry(buf_ctrl, head, list) {
-               if (!(buf_ctrl->type & MFC_CTRL_TYPE_GET))
-                       continue;
-               switch (buf_ctrl->id) {
-               case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG:
-                       value = pOutStr->PictureTagTop;
-                       break;
-               case V4L2_CID_MPEG_MFC51_VIDEO_DISPLAY_STATUS:
-                       value = pOutStr->DisplayStatus;
-                       break;
-               case V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_LUMA:
-                       value = pOutStr->DisplayFirstCrc;
-                       break;
-               case V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_CHROMA:
-                       value = pOutStr->DisplaySecondCrc;
-                       break;
-               case V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_CHROMA1:
-                       value = pOutStr->DisplayThirdCrc;
-                       break;
-               case V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_2BIT_LUMA:
-                       value = pOutStr->DisplayFirst2BitCrc;
-                       break;
-               case V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_2BIT_CHROMA:
-                       value = pOutStr->DisplaySecond2BitCrc;
-                       break;
-               case V4L2_CID_MPEG_MFC51_VIDEO_CRC_GENERATED:
-                       value = pOutStr->DisplayStatus;
-                       break;
-               case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_AVAIL:
-                       value = pOutStr->SeiAvail;
-                       break;
-               case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRGMENT_ID:
-                       value = pOutStr->FramePackArrgmentId;
-                       break;
-               case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_INFO:
-                       value = pOutStr->FramePackSeiInfo;
-                       break;
-               case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_GRID_POS:
-                       value = pOutStr->FramePackGridPos;
-                       break;
-               case V4L2_CID_MPEG_VIDEO_H264_MVC_VIEW_ID:
-                       value = 0;
-                       break;
-               /* TO-DO: SEI information has to be added in NAL-Q */
-               case V4L2_CID_MPEG_VIDEO_SEI_MAX_PIC_AVERAGE_LIGHT:
-               case V4L2_CID_MPEG_VIDEO_SEI_MAX_CONTENT_LIGHT:
-                       value = pOutStr->ContentLightLevelInfoSei;
-                       break;
-               case V4L2_CID_MPEG_VIDEO_SEI_MAX_DISPLAY_LUMINANCE:
-                       value = pOutStr->MasteringDisplayColourVolumeSei0;
-                       break;
-               case V4L2_CID_MPEG_VIDEO_SEI_MIN_DISPLAY_LUMINANCE:
-                       value = pOutStr->MasteringDisplayColourVolumeSei1;
-                       break;
-               case V4L2_CID_MPEG_VIDEO_FULL_RANGE_FLAG:
-               case V4L2_CID_MPEG_VIDEO_COLOUR_PRIMARIES:
-               case V4L2_CID_MPEG_VIDEO_FORMAT:
-               case V4L2_CID_MPEG_VIDEO_TRANSFER_CHARACTERISTICS:
-               case V4L2_CID_MPEG_VIDEO_MATRIX_COEFFICIENTS:
-                       value = pOutStr->VideoSignalType;
-                       break;
-               case V4L2_CID_MPEG_VIDEO_SEI_WHITE_POINT:
-                       value = pOutStr->MasteringDisplayColourVolumeSei2;
-                       break;
-               case V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_0:
-                       value = pOutStr->MasteringDisplayColourVolumeSei3;
-                       break;
-               case V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_1:
-                       value = pOutStr->MasteringDisplayColourVolumeSei4;
-                       break;
-               case V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_2:
-                       value = pOutStr->MasteringDisplayColourVolumeSei5;
-                       break;
-                       /* If new dynamic controls are added, insert here */
-               default:
-                       mfc_info_ctx("[NALQ] can't find control, id: 0x%x\n",
-                                       buf_ctrl->id);
-               }
-               value = (value >> buf_ctrl->shft) & buf_ctrl->mask;
-
-               buf_ctrl->val = value;
-               buf_ctrl->has_new = 1;
-
-               if (IS_VP9_DEC(ctx)) {
-                       if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_FULL_RANGE_FLAG)
-                               buf_ctrl->val = dec->color_range;
-                       else if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_COLOUR_PRIMARIES)
-                               buf_ctrl->val = dec->color_space;
-               }
-
-               mfc_debug(6, "[NALQ][CTRLS] Get buffer control id: 0x%08x, val: %d\n",
-                               buf_ctrl->id, buf_ctrl->val);
-       }
-
-       mfc_debug_leave();
-
-       return 0;
-}
-
-static int s5p_mfc_dec_recover_buf_ctrls_val(struct s5p_mfc_ctx *ctx, struct list_head *head)
-{
-       struct s5p_mfc_buf_ctrl *buf_ctrl;
-       struct s5p_mfc_dev *dev = ctx->dev;
-       unsigned int value = 0;
-
-       list_for_each_entry(buf_ctrl, head, list) {
-               if (!(buf_ctrl->type & MFC_CTRL_TYPE_SET)
-                       || !buf_ctrl->is_volatile
-                       || !buf_ctrl->updated)
-                       continue;
-
-               value = MFC_READL(buf_ctrl->addr);
-               value &= ~(buf_ctrl->mask << buf_ctrl->shft);
-               value |= ((buf_ctrl->old_val & buf_ctrl->mask) << buf_ctrl->shft);
-               MFC_WRITEL(value, buf_ctrl->addr);
-
-               /* clear change flag bit */
-               if (buf_ctrl->flag_mode == MFC_CTRL_MODE_SFR) {
-                       value = MFC_READL(buf_ctrl->flag_addr);
-                       value &= ~(1 << buf_ctrl->flag_shft);
-                       MFC_WRITEL(value, buf_ctrl->flag_addr);
-               }
-
-               buf_ctrl->updated = 0;
-               mfc_debug(6, "[CTRLS] Recover buffer control id: 0x%08x, old val: %d\n",
-                               buf_ctrl->id, buf_ctrl->old_val);
-       }
-
-       return 0;
-}
-
-static int s5p_mfc_dec_get_buf_update_val(struct s5p_mfc_ctx *ctx,
-                       struct list_head *head, unsigned int id, int value)
-{
-       struct s5p_mfc_buf_ctrl *buf_ctrl;
-
-       list_for_each_entry(buf_ctrl, head, list) {
-               if (buf_ctrl->id == id) {
-                       buf_ctrl->val = value;
-                       mfc_debug(6, "[CTRLS] Update buffer control id: 0x%08x, val: %d\n",
-                                       buf_ctrl->id, buf_ctrl->val);
-                       break;
-               }
-       }
-
-       return 0;
-}
-
-static int s5p_mfc_dec_recover_buf_ctrls_nal_q(struct s5p_mfc_ctx *ctx,
-               struct list_head *head)
-{
-       struct s5p_mfc_buf_ctrl *buf_ctrl;
-
-       list_for_each_entry(buf_ctrl, head, list) {
-               if (!(buf_ctrl->type & MFC_CTRL_TYPE_SET)
-                               || !(buf_ctrl->updated))
-                       continue;
-
-               buf_ctrl->has_new = 1;
-               buf_ctrl->updated = 0;
-               mfc_debug(6, "[NALQ][CTRLS] Recover buffer control id: 0x%08x, val: %d\n",
-                               buf_ctrl->id, buf_ctrl->val);
-       }
-
-       return 0;
-}
-
-struct s5p_mfc_ctrls_ops decoder_ctrls_ops = {
-       .init_ctx_ctrls                 = s5p_mfc_dec_init_ctx_ctrls,
-       .cleanup_ctx_ctrls              = s5p_mfc_dec_cleanup_ctx_ctrls,
-       .init_buf_ctrls                 = s5p_mfc_dec_init_buf_ctrls,
-       .reset_buf_ctrls                = s5p_mfc_dec_reset_buf_ctrls,
-       .cleanup_buf_ctrls              = s5p_mfc_dec_cleanup_buf_ctrls,
-       .to_buf_ctrls                   = s5p_mfc_dec_to_buf_ctrls,
-       .to_ctx_ctrls                   = s5p_mfc_dec_to_ctx_ctrls,
-       .set_buf_ctrls_val              = s5p_mfc_dec_set_buf_ctrls_val,
-       .get_buf_ctrls_val              = s5p_mfc_dec_get_buf_ctrls_val,
-       .set_buf_ctrls_val_nal_q_dec    = s5p_mfc_dec_set_buf_ctrls_val_nal_q_dec,
-       .get_buf_ctrls_val_nal_q_dec    = s5p_mfc_dec_get_buf_ctrls_val_nal_q_dec,
-       .recover_buf_ctrls_val          = s5p_mfc_dec_recover_buf_ctrls_val,
-       .get_buf_update_val             = s5p_mfc_dec_get_buf_update_val,
-       .recover_buf_ctrls_nal_q        = s5p_mfc_dec_recover_buf_ctrls_nal_q,
-};
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_dec_vb2_ops.c b/drivers/media/platform/exynos/mfc/s5p_mfc_dec_vb2_ops.c
deleted file mode 100644 (file)
index 50c1735..0000000
+++ /dev/null
@@ -1,633 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_dec_vb2_ops.c
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include  "s5p_mfc_common.h"
-
-#include "s5p_mfc_hwlock.h"
-#include "s5p_mfc_nal_q.h"
-#include "s5p_mfc_opr.h"
-#include "s5p_mfc_sync.h"
-
-#include "s5p_mfc_queue.h"
-#include "s5p_mfc_utils.h"
-#include "s5p_mfc_buf.h"
-#include "s5p_mfc_mem.h"
-
-static int s5p_mfc_dec_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;
-       struct s5p_mfc_dev *dev;
-       struct s5p_mfc_dec *dec;
-       struct s5p_mfc_raw_info *raw;
-       int i;
-
-       mfc_debug_enter();
-
-       if (!vq) {
-               mfc_err_dev("no vb2_queue info\n");
-               return -EINVAL;
-       }
-
-       ctx = vq->drv_priv;
-       if (!ctx) {
-               mfc_err_dev("no mfc context to run\n");
-               return -EINVAL;
-       }
-       dev = ctx->dev;
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return -EINVAL;
-       }
-       dec = ctx->dec_priv;
-       if (!dec) {
-               mfc_err_dev("no mfc decoder to run\n");
-               return -EINVAL;
-       }
-
-       raw = &ctx->raw_buf;
-
-       /* Video output for decoding (source)
-        * this can be set after getting an instance */
-       if (ctx->state == MFCINST_GOT_INST &&
-           vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               mfc_debug(4, "dec src\n");
-               /* 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;
-
-               psize[0] = dec->src_buf_size;
-               alloc_devs[0] = dev->device;
-       /* 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) {
-               mfc_debug(4, "dec dst\n");
-               /* Output plane count is different by the pixel format */
-               *plane_count = ctx->dst_fmt->mem_planes;
-               /* Setup buffer count */
-               if (*buf_count < ctx->dpb_count)
-                       *buf_count = ctx->dpb_count;
-               if (*buf_count > MFC_MAX_BUFFERS)
-                       *buf_count = MFC_MAX_BUFFERS;
-
-               if (ctx->dst_fmt->mem_planes == 1) {
-                       psize[0] = raw->total_plane_size;
-                       alloc_devs[0] = dev->device;
-               } else {
-                       for (i = 0; i < ctx->dst_fmt->num_planes; i++) {
-                               psize[i] = raw->plane_size[i];
-                               alloc_devs[i] = dev->device;
-                       }
-               }
-       } else {
-               mfc_err_ctx("State seems invalid. State = %d, vq->type = %d\n",
-                                                       ctx->state, vq->type);
-               return -EINVAL;
-       }
-
-       mfc_debug(2, "buf_count: %d, plane_count: %d, type: %#x\n",
-                       *buf_count, *plane_count, vq->type);
-       for (i = 0; i < *plane_count; i++)
-               mfc_debug(2, "plane[%d] size: %d\n", i, psize[i]);
-
-       mfc_debug_leave();
-
-       return 0;
-}
-
-static void s5p_mfc_dec_unlock(struct vb2_queue *q)
-{
-       struct s5p_mfc_ctx *ctx = q->drv_priv;
-       struct s5p_mfc_dev *dev;
-
-       if (!ctx) {
-               mfc_err_dev("no mfc context to run\n");
-               return;
-       }
-       dev = ctx->dev;
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return;
-       }
-
-       mutex_unlock(&dev->mfc_mutex);
-}
-
-static void s5p_mfc_dec_lock(struct vb2_queue *q)
-{
-       struct s5p_mfc_ctx *ctx = q->drv_priv;
-       struct s5p_mfc_dev *dev;
-
-       if (!ctx) {
-               mfc_err_dev("no mfc context to run\n");
-               return;
-       }
-       dev = ctx->dev;
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return;
-       }
-
-       mutex_lock(&dev->mfc_mutex);
-}
-
-static int s5p_mfc_dec_buf_init(struct vb2_buffer *vb)
-{
-       struct vb2_queue *vq = vb->vb2_queue;
-       struct s5p_mfc_ctx *ctx = vq->drv_priv;
-       struct s5p_mfc_dev *dev;
-       struct s5p_mfc_dec *dec;
-       struct s5p_mfc_buf *buf = vb_to_mfc_buf(vb);
-       dma_addr_t start_raw;
-       int i, ret;
-
-       mfc_debug_enter();
-       if (!ctx) {
-               mfc_err_dev("no mfc context to run\n");
-               return -EINVAL;
-       }
-       dev = ctx->dev;
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return -EINVAL;
-       }
-       dec = ctx->dec_priv;
-       if (!dec) {
-               mfc_err_dev("no mfc decoder to run\n");
-               return -EINVAL;
-       }
-
-       if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-               ret = s5p_mfc_check_vb_with_fmt(ctx->dst_fmt, vb);
-               if (ret < 0)
-                       return ret;
-
-               start_raw = s5p_mfc_mem_get_daddr_vb(vb, 0);
-               if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_NV12N) {
-                       buf->addr[0][0] = start_raw;
-                       buf->addr[0][1] = NV12N_CBCR_BASE(start_raw,
-                                                       ctx->img_width,
-                                                       ctx->img_height);
-               } else if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_NV12N_10B) {
-                       buf->addr[0][0] = start_raw;
-                       buf->addr[0][1] = NV12N_10B_CBCR_BASE(start_raw,
-                                                       ctx->img_width,
-                                                       ctx->img_height);
-               } else if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_YUV420N) {
-                       buf->addr[0][0] = start_raw;
-                       buf->addr[0][1] = YUV420N_CB_BASE(start_raw,
-                                                       ctx->img_width,
-                                                       ctx->img_height);
-                       buf->addr[0][2] = YUV420N_CR_BASE(start_raw,
-                                                       ctx->img_width,
-                                                       ctx->img_height);
-               } else {
-                       for (i = 0; i < ctx->dst_fmt->mem_planes; i++)
-                               buf->addr[0][i] = s5p_mfc_mem_get_daddr_vb(vb, i);
-               }
-
-               if (call_cop(ctx, init_buf_ctrls, ctx, MFC_CTRL_TYPE_DST,
-                                       vb->index) < 0)
-                       mfc_err_ctx("failed in init_buf_ctrls\n");
-       } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               ret = s5p_mfc_check_vb_with_fmt(ctx->src_fmt, vb);
-               if (ret < 0)
-                       return ret;
-
-               buf->addr[0][0] = s5p_mfc_mem_get_daddr_vb(vb, 0);
-
-               if (call_cop(ctx, init_buf_ctrls, ctx, MFC_CTRL_TYPE_SRC,
-                                       vb->index) < 0)
-                       mfc_err_ctx("failed in init_buf_ctrls\n");
-       } else {
-               mfc_err_ctx("s5p_mfc_dec_buf_init: unknown queue type\n");
-               return -EINVAL;
-       }
-
-       mfc_debug_leave();
-
-       return 0;
-}
-
-static int s5p_mfc_dec_buf_prepare(struct vb2_buffer *vb)
-{
-       struct vb2_queue *vq = vb->vb2_queue;
-       struct s5p_mfc_ctx *ctx = vq->drv_priv;
-       struct s5p_mfc_dec *dec;
-       struct s5p_mfc_raw_info *raw;
-       unsigned int index = vb->index;
-       size_t buf_size;
-       int i;
-
-       if (!ctx) {
-               mfc_err_dev("no mfc context to run\n");
-               return -EINVAL;
-       }
-       dec = ctx->dec_priv;
-       if (!dec) {
-               mfc_err_dev("no mfc decoder to run\n");
-               return -EINVAL;
-       }
-       if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-               raw = &ctx->raw_buf;
-               /* check the size per plane */
-               if (ctx->dst_fmt->mem_planes == 1) {
-                       buf_size = vb2_plane_size(vb, 0);
-                       mfc_debug(2, "[FRAME] single plane vb size: %lu, calc size: %d\n",
-                                       buf_size, raw->total_plane_size);
-                       if (buf_size < raw->total_plane_size) {
-                               mfc_err_ctx("[FRAME] single plane size(%d) is smaller than (%d)\n",
-                                               buf_size, raw->total_plane_size);
-                               return -EINVAL;
-                       }
-               } else {
-                       for (i = 0; i < ctx->dst_fmt->mem_planes; i++) {
-                               buf_size = vb2_plane_size(vb, i);
-                               mfc_debug(2, "[FRAME] plane[%d] vb size: %lu, calc size: %d\n",
-                                               i, buf_size, raw->plane_size[i]);
-                               if (buf_size < raw->plane_size[i]) {
-                                       mfc_err_ctx("[FRAME] plane[%d] size(%d) is smaller than (%d)\n",
-                                                       i, buf_size, raw->plane_size[i]);
-                                       return -EINVAL;
-                               }
-                       }
-               }
-       } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               buf_size = vb2_plane_size(vb, 0);
-               mfc_debug(2, "[STREAM] vb size: %lu, calc size: %d\n",
-                               buf_size, dec->src_buf_size);
-
-               if (buf_size < dec->src_buf_size) {
-                       mfc_err_ctx("[STREAM] size(%d) is smaller than (%d)\n",
-                                       buf_size, dec->src_buf_size);
-                       return -EINVAL;
-               }
-
-               if (call_cop(ctx, to_buf_ctrls, ctx, &ctx->src_ctrls[index]) < 0)
-                       mfc_err_ctx("failed in to_buf_ctrls\n");
-       }
-
-       return 0;
-}
-
-static void s5p_mfc_dec_buf_finish(struct vb2_buffer *vb)
-{
-       struct vb2_queue *vq = vb->vb2_queue;
-       struct s5p_mfc_ctx *ctx = vq->drv_priv;
-       unsigned int index = vb->index;
-
-       if (!ctx) {
-               mfc_err_dev("no mfc context to run\n");
-               return;
-       }
-
-       if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-               if (call_cop(ctx, to_ctx_ctrls, ctx, &ctx->dst_ctrls[index]) < 0)
-                       mfc_err_ctx("failed in to_ctx_ctrls\n");
-       } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               if (call_cop(ctx, to_ctx_ctrls, ctx, &ctx->src_ctrls[index]) < 0)
-                       mfc_err_ctx("failed in to_ctx_ctrls\n");
-       }
-}
-
-static void s5p_mfc_dec_buf_cleanup(struct vb2_buffer *vb)
-{
-       struct vb2_queue *vq = vb->vb2_queue;
-       struct s5p_mfc_ctx *ctx = vq->drv_priv;
-       unsigned int index = vb->index;
-
-       mfc_debug_enter();
-       if (!ctx) {
-               mfc_err_dev("no mfc context to run\n");
-               return;
-       }
-
-       if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-               if (call_cop(ctx, cleanup_buf_ctrls, ctx,
-                                       MFC_CTRL_TYPE_DST, index) < 0)
-                       mfc_err_ctx("failed in cleanup_buf_ctrls\n");
-       } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               if (call_cop(ctx, cleanup_buf_ctrls, ctx,
-                                       MFC_CTRL_TYPE_SRC, index) < 0)
-                       mfc_err_ctx("failed in cleanup_buf_ctrls\n");
-       } else {
-               mfc_err_ctx("s5p_mfc_dec_buf_cleanup: unknown queue type\n");
-       }
-
-       mfc_debug_leave();
-}
-
-static int s5p_mfc_dec_start_streaming(struct vb2_queue *q, unsigned int count)
-{
-       struct s5p_mfc_ctx *ctx = q->drv_priv;
-       struct s5p_mfc_dev *dev;
-
-       if (!ctx) {
-               mfc_err_dev("no mfc context to run\n");
-               return -EINVAL;
-       }
-
-       dev = ctx->dev;
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return -EINVAL;
-       }
-
-       if (ctx->state == MFCINST_FINISHING)
-               s5p_mfc_change_state(ctx, MFCINST_RUNNING);
-
-       /* If context is ready then dev = work->data;schedule it to run */
-       if (s5p_mfc_dec_ctx_ready(ctx)) {
-               s5p_mfc_set_bit(ctx->num, &dev->work_bits);
-       }
-
-       s5p_mfc_try_run(dev);
-
-       return 0;
-}
-
-static void mfc_dec_src_stop_streaming(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev;
-       struct s5p_mfc_dec *dec;
-       struct s5p_mfc_buf *src_mb;
-       int index, csd, condition = 0;
-       int ret = 0;
-
-       dev = ctx->dev;
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return;
-       }
-
-       dec = ctx->dec_priv;
-       if (!dec) {
-               mfc_err_dev("no mfc decoder to run\n");
-               return;
-       }
-
-       while (1) {
-               csd = s5p_mfc_peek_buf_csd(&ctx->buf_queue_lock, &ctx->src_buf_queue);
-
-               if (csd == 1) {
-                       s5p_mfc_clean_ctx_int_flags(ctx);
-                       if (need_to_special_parsing(ctx)) {
-                               s5p_mfc_change_state(ctx, MFCINST_SPECIAL_PARSING);
-                               condition = S5P_FIMV_R2H_CMD_SEQ_DONE_RET;
-                               mfc_info_ctx("try to special parsing! (before NAL_START)\n");
-                       } else if (need_to_special_parsing_nal(ctx)) {
-                               s5p_mfc_change_state(ctx, MFCINST_SPECIAL_PARSING_NAL);
-                               condition = S5P_FIMV_R2H_CMD_FRAME_DONE_RET;
-                               mfc_info_ctx("try to special parsing! (after NAL_START)\n");
-                       } else {
-                               mfc_info_ctx("can't parsing CSD!, state = %d\n", ctx->state);
-                       }
-
-                       if (condition) {
-                               s5p_mfc_set_bit(ctx->num, &dev->work_bits);
-
-                               ret = s5p_mfc_just_run(dev, ctx->num);
-                               if (ret) {
-                                       mfc_err_ctx("Failed to run MFC\n");
-                               } else {
-                                       if (s5p_mfc_wait_for_done_ctx(ctx, condition))
-                                               mfc_err_ctx("special parsing time out\n");
-                               }
-                       }
-               }
-
-               src_mb = s5p_mfc_get_del_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, MFC_BUF_NO_TOUCH_USED);
-               if (!src_mb)
-                       break;
-
-               index = src_mb->vb.vb2_buf.index;
-
-               if (ctx->is_drm)
-                       s5p_mfc_stream_unprotect(ctx, src_mb, index);
-               vb2_set_plane_payload(&src_mb->vb.vb2_buf, 0, 0);
-               vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_ERROR);
-       }
-
-       dec->consumed = 0;
-       dec->remained_size = 0;
-       ctx->check_dump = 0;
-
-       s5p_mfc_init_queue(&ctx->src_buf_queue);
-
-       index = 0;
-       while (index < MFC_MAX_BUFFERS) {
-               index = find_next_bit(&ctx->src_ctrls_avail,
-                               MFC_MAX_BUFFERS, index);
-               if (index < MFC_MAX_BUFFERS)
-                       call_cop(ctx, reset_buf_ctrls, &ctx->src_ctrls[index]);
-               index++;
-       }
-}
-
-static void mfc_dec_dst_stop_streaming(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dec *dec;
-       int index = 0;
-
-       dec = ctx->dec_priv;
-       if (!dec) {
-               mfc_err_dev("no mfc decoder to run\n");
-               return;
-       }
-
-       s5p_mfc_cleanup_assigned_fd(ctx);
-       s5p_mfc_cleanup_queue(&ctx->buf_queue_lock, &ctx->ref_buf_queue);
-
-       dec->dynamic_used = 0;
-       dec->err_reuse_flag = 0;
-       dec->dec_only_release_flag = 0;
-
-       s5p_mfc_cleanup_queue(&ctx->buf_queue_lock, &ctx->dst_buf_queue);
-
-       ctx->is_dpb_realloc = 0;
-       dec->available_dpb = 0;
-
-       dec->y_addr_for_pb = 0;
-
-       s5p_mfc_cleanup_assigned_dpb(ctx);
-
-       while (index < MFC_MAX_BUFFERS) {
-               index = find_next_bit(&ctx->dst_ctrls_avail,
-                               MFC_MAX_BUFFERS, index);
-               if (index < MFC_MAX_BUFFERS)
-                       call_cop(ctx, reset_buf_ctrls, &ctx->dst_ctrls[index]);
-               index++;
-       }
-
-       if (ctx->wait_state == WAIT_INITBUF_DONE ||
-                       ctx->wait_state == WAIT_DECODING) {
-               ctx->wait_state = WAIT_NONE;
-               mfc_debug(2, "Decoding can be started now\n");
-       }
-}
-
-static void s5p_mfc_dec_stop_streaming(struct vb2_queue *q)
-{
-       struct s5p_mfc_ctx *ctx = q->drv_priv;
-       struct s5p_mfc_dev *dev;
-       int ret = 0;
-       int prev_state;
-
-       if (!ctx) {
-               mfc_err_dev("no mfc context to run\n");
-               return;
-       }
-
-       dev = ctx->dev;
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return;
-       }
-
-       mfc_info_ctx("dec stop_streaming is called, hwlock : %d, type : %d\n",
-                               test_bit(ctx->num, &dev->hwlock.bits), q->type);
-       MFC_TRACE_CTX("** DEC streamoff(type:%d)\n", q->type);
-
-       MFC_TRACE_CTX_HWLOCK("**DEC streamoff(type:%d)\n", q->type);
-       /* If a H/W operation is in progress, wait for it complete */
-       ret = s5p_mfc_get_hwlock_ctx(ctx);
-       if (ret < 0) {
-               mfc_err_ctx("Failed to get hwlock\n");
-               return;
-       }
-
-       if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
-               mfc_dec_dst_stop_streaming(ctx);
-       else if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
-               mfc_dec_src_stop_streaming(ctx);
-
-       if (ctx->state == MFCINST_FINISHING)
-               s5p_mfc_change_state(ctx, MFCINST_RUNNING);
-
-       if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE && need_to_dpb_flush(ctx)) {
-               prev_state = ctx->state;
-               s5p_mfc_change_state(ctx, MFCINST_DPB_FLUSHING);
-               s5p_mfc_set_bit(ctx->num, &dev->work_bits);
-               s5p_mfc_clean_ctx_int_flags(ctx);
-               mfc_info_ctx("try to DPB flush\n");
-               ret = s5p_mfc_just_run(dev, ctx->num);
-               if (ret) {
-                       mfc_err_ctx("Failed to run MFC\n");
-                       s5p_mfc_release_hwlock_ctx(ctx);
-                       s5p_mfc_cleanup_work_bit_and_try_run(ctx);
-                       return;
-               }
-
-               if (s5p_mfc_wait_for_done_ctx(ctx, S5P_FIMV_R2H_CMD_DPB_FLUSH_RET)) {
-                       mfc_err_ctx("time out during DPB flush\n");
-                       dev->logging_data->cause |= (1 << MFC_CAUSE_FAIL_DPB_FLUSH);
-                       call_dop(dev, dump_and_stop_always, dev);
-               }
-
-               s5p_mfc_change_state(ctx, prev_state);
-       }
-
-       mfc_debug(2, "buffer cleanup & flush is done in stop_streaming, type : %d\n", q->type);
-
-       s5p_mfc_clear_bit(ctx->num, &dev->work_bits);
-       s5p_mfc_release_hwlock_ctx(ctx);
-
-       if (s5p_mfc_dec_ctx_ready(ctx))
-               s5p_mfc_set_bit(ctx->num, &dev->work_bits);
-       if (s5p_mfc_is_work_to_do(dev))
-               queue_work(dev->butler_wq, &dev->butler_work);
-}
-
-static void s5p_mfc_dec_buf_queue(struct vb2_buffer *vb)
-{
-       struct vb2_queue *vq = vb->vb2_queue;
-       struct s5p_mfc_ctx *ctx = vq->drv_priv;
-       struct s5p_mfc_dev *dev;
-       struct s5p_mfc_dec *dec;
-       struct s5p_mfc_buf *buf = vb_to_mfc_buf(vb);
-       int i;
-       unsigned char *stream_vir = NULL;
-
-       mfc_debug_enter();
-       if (!ctx) {
-               mfc_err_dev("no mfc context to run\n");
-               return;
-       }
-
-       dev = ctx->dev;
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return;
-       }
-
-       dec = ctx->dec_priv;
-       if (!dec) {
-               mfc_err_dev("no mfc decoder to run\n");
-               return;
-       }
-
-       if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               mfc_debug(2, "[BUFINFO] ctx[%d] add src index:%d, addr: 0x%08llx\n",
-                               ctx->num, vb->index, buf->addr[0][0]);
-               if (dec->dst_memtype == V4L2_MEMORY_DMABUF &&
-                               ctx->state < MFCINST_HEAD_PARSED && !ctx->is_drm)
-                       stream_vir = vb2_plane_vaddr(vb, 0);
-
-               buf->vir_addr = stream_vir;
-
-               s5p_mfc_add_tail_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, buf);
-
-               MFC_TRACE_CTX("Q src[%d] fd: %d, %#llx\n",
-                               vb->index, vb->planes[0].m.fd, buf->addr[0][0]);
-       } else if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-               for (i = 0; i < ctx->dst_fmt->mem_planes; i++)
-                       mfc_debug(2, "[BUFINFO] ctx[%d] add dst index: %d, addr[%d]: 0x%08llx\n",
-                                       ctx->num, vb->index, i, buf->addr[0][i]);
-               s5p_mfc_store_dpb(ctx, vb);
-
-               if ((dec->dst_memtype == V4L2_MEMORY_USERPTR || dec->dst_memtype == V4L2_MEMORY_DMABUF) &&
-                               s5p_mfc_is_queue_count_same(&ctx->buf_queue_lock,
-                                       &ctx->dst_buf_queue, dec->total_dpb_count))
-                       ctx->capture_state = QUEUE_BUFS_MMAPED;
-
-               MFC_TRACE_CTX("Q dst[%d] fd: %d, %#llx / avail %#lx used %#x\n",
-                               vb->index, vb->planes[0].m.fd, buf->addr[0][0],
-                               dec->available_dpb, dec->dynamic_used);
-       } else {
-               mfc_err_ctx("Unsupported buffer type (%d)\n", vq->type);
-       }
-
-       if (s5p_mfc_dec_ctx_ready(ctx)) {
-               s5p_mfc_set_bit(ctx->num, &dev->work_bits);
-               s5p_mfc_try_run(dev);
-       }
-
-       mfc_debug_leave();
-}
-
-struct vb2_ops s5p_mfc_dec_qops = {
-       .queue_setup            = s5p_mfc_dec_queue_setup,
-       .wait_prepare           = s5p_mfc_dec_unlock,
-       .wait_finish            = s5p_mfc_dec_lock,
-       .buf_init               = s5p_mfc_dec_buf_init,
-       .buf_prepare            = s5p_mfc_dec_buf_prepare,
-       .buf_finish             = s5p_mfc_dec_buf_finish,
-       .buf_cleanup            = s5p_mfc_dec_buf_cleanup,
-       .start_streaming        = s5p_mfc_dec_start_streaming,
-       .stop_streaming         = s5p_mfc_dec_stop_streaming,
-       .buf_queue              = s5p_mfc_dec_buf_queue,
-};
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_enc.c b/drivers/media/platform/exynos/mfc/s5p_mfc_enc.c
deleted file mode 100644 (file)
index 281cf80..0000000
+++ /dev/null
@@ -1,2061 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_enc.c
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include "s5p_mfc_enc.h"
-#include "s5p_mfc_enc_internal.h"
-
-#include "s5p_mfc_hwlock.h"
-#include "s5p_mfc_otf.h"
-#include "s5p_mfc_opr.h"
-#include "s5p_mfc_sync.h"
-
-#include "s5p_mfc_qos.h"
-#include "s5p_mfc_queue.h"
-#include "s5p_mfc_utils.h"
-#include "s5p_mfc_buf.h"
-#include "s5p_mfc_mem.h"
-
-static struct s5p_mfc_fmt *mfc_enc_find_format(struct s5p_mfc_ctx *ctx,
-               unsigned int pixelformat)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_fmt *fmt = NULL;
-       unsigned long i;
-
-       for (i = 0; i < NUM_FORMATS; i++) {
-               if (enc_formats[i].fourcc == pixelformat) {
-                       fmt = (struct s5p_mfc_fmt *)&enc_formats[i];
-                       break;
-               }
-       }
-
-       if (!dev->pdata->support_10bit && (fmt->type & MFC_FMT_10BIT)) {
-               mfc_err_ctx("[FRAME] 10bit is not supported\n");
-               fmt = NULL;
-       }
-       if (!dev->pdata->support_422 && (fmt->type & MFC_FMT_422)) {
-               mfc_err_ctx("[FRAME] 422 is not supported\n");
-               fmt = NULL;
-       }
-       if (!dev->pdata->support_rgb && (fmt->type & MFC_FMT_RGB)) {
-               mfc_err_ctx("[FRAME] RGB is not supported\n");
-               fmt = NULL;
-       }
-
-       return fmt;
-}
-
-static struct v4l2_queryctrl *mfc_enc_get_ctrl(int id)
-{
-       unsigned long i;
-
-       for (i = 0; i < NUM_CTRLS; ++i)
-               if (id == controls[i].id)
-                       return &controls[i];
-       return NULL;
-}
-
-static int mfc_enc_check_ctrl_val(struct s5p_mfc_ctx *ctx, struct v4l2_control *ctrl)
-{
-       struct v4l2_queryctrl *c;
-
-       c = mfc_enc_get_ctrl(ctrl->id);
-       if (!c) {
-               mfc_err_ctx("[CTRLS] not supported control id (%#x)\n", ctrl->id);
-               return -EINVAL;
-       }
-
-       if (ctrl->id == V4L2_CID_MPEG_VIDEO_GOP_SIZE
-           && ctrl->value > c->maximum) {
-               mfc_info_ctx("GOP_SIZE is changed to max(%d -> %d)\n",
-                                ctrl->value, c->maximum);
-               ctrl->value = c->maximum;
-       }
-
-       if (ctrl->id == V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER) {
-               if ((ctrl->value & ~(1 << 16)) < c->minimum || (ctrl->value & ~(1 << 16)) > c->maximum
-                   || (c->step != 0 && (ctrl->value & ~(1 << 16)) % c->step != 0)) {
-                       mfc_err_ctx("[CTRLS][HIERARCHICAL] Invalid control value for %#x (%#x)\n",
-                                       ctrl->id, ctrl->value);
-                       return -ERANGE;
-               } else {
-                       return 0;
-               }
-       }
-
-       if (ctrl->value < c->minimum || ctrl->value > c->maximum
-           || (c->step != 0 && ctrl->value % c->step != 0)) {
-               mfc_err_ctx("[CTRLS] Invalid control value for %#x (%#x)\n",
-                               ctrl->id, ctrl->value);
-               return -ERANGE;
-       }
-
-       return 0;
-}
-
-static inline int mfc_enc_h264_profile(struct s5p_mfc_ctx *ctx, int profile)
-{
-       int ret = 0;
-
-       switch (profile) {
-       case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:
-               ret = S5P_FIMV_E_PROFILE_H264_MAIN;
-               break;
-       case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH:
-               ret = S5P_FIMV_E_PROFILE_H264_HIGH;
-               break;
-       case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
-               ret = S5P_FIMV_E_PROFILE_H264_BASELINE;
-               break;
-       case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
-               ret = S5P_FIMV_E_PROFILE_H264_CONSTRAINED_BASELINE;
-               break;
-       case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH:
-               ret = S5P_FIMV_E_PROFILE_H264_CONSTRAINED_HIGH;
-               break;
-       default:
-               ret = -EINVAL;
-       }
-
-       return ret;
-}
-
-/* Query capabilities of the device */
-static int vidioc_querycap(struct file *file, void *priv,
-                          struct v4l2_capability *cap)
-{
-       strncpy(cap->driver, "MFC", sizeof(cap->driver) - 1);
-       strncpy(cap->card, "encoder", sizeof(cap->card) - 1);
-       cap->bus_info[0] = 0;
-       cap->version = KERNEL_VERSION(1, 0, 0);
-       cap->device_caps = V4L2_CAP_VIDEO_CAPTURE
-                       | V4L2_CAP_VIDEO_OUTPUT
-                       | V4L2_CAP_VIDEO_CAPTURE_MPLANE
-                       | V4L2_CAP_VIDEO_OUTPUT_MPLANE
-                       | V4L2_CAP_STREAMING
-                       | V4L2_CAP_DEVICE_CAPS;
-
-       cap->capabilities = cap->device_caps;
-
-       return 0;
-}
-
-static int mfc_enc_enum_fmt(struct s5p_mfc_dev *dev, struct v4l2_fmtdesc *f,
-               unsigned int type)
-{
-       struct s5p_mfc_fmt *fmt;
-       unsigned long i, j = 0;
-
-       for (i = 0; i < NUM_FORMATS; ++i) {
-               if (!(enc_formats[i].type & type))
-                       continue;
-               if (!dev->pdata->support_10bit && (enc_formats[i].type & MFC_FMT_10BIT))
-                       continue;
-               if (!dev->pdata->support_422 && (enc_formats[i].type & MFC_FMT_422))
-                       continue;
-               if (!dev->pdata->support_rgb && (enc_formats[i].type & MFC_FMT_RGB))
-                       continue;
-
-               if (j == f->index) {
-                       fmt = &enc_formats[i];
-                       strlcpy(f->description, fmt->name,
-                               sizeof(f->description));
-                       f->pixelformat = fmt->fourcc;
-
-                       return 0;
-               }
-
-               ++j;
-       }
-
-       return -EINVAL;
-}
-
-static int vidioc_enum_fmt_vid_cap_mplane(struct file *file, void *pirv,
-               struct v4l2_fmtdesc *f)
-{
-       struct s5p_mfc_dev *dev = video_drvdata(file);
-
-       return mfc_enc_enum_fmt(dev, f, MFC_FMT_STREAM);
-}
-
-static int vidioc_enum_fmt_vid_out_mplane(struct file *file, void *prov,
-               struct v4l2_fmtdesc *f)
-{
-       struct s5p_mfc_dev *dev = video_drvdata(file);
-
-       return mfc_enc_enum_fmt(dev, f, MFC_FMT_FRAME);
-}
-
-static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
-{
-       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
-       struct s5p_mfc_enc *enc = ctx->enc_priv;
-       struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
-       struct s5p_mfc_raw_info *raw;
-       int i;
-
-       mfc_debug_enter();
-
-       if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-               mfc_debug(4, "enc dst g_fmt\n");
-               /* 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->mem_planes;
-
-               pix_fmt_mp->plane_fmt[0].bytesperline = enc->dst_buf_size;
-               pix_fmt_mp->plane_fmt[0].sizeimage = enc->dst_buf_size;
-       } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               mfc_debug(4, "enc src g_fmt\n");
-               /* This is run on capture (encoder src) */
-               raw = &ctx->raw_buf;
-
-               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->mem_planes;
-               for (i = 0; i < ctx->src_fmt->mem_planes; i++) {
-                       pix_fmt_mp->plane_fmt[i].bytesperline = raw->stride[i];
-                       pix_fmt_mp->plane_fmt[i].sizeimage = raw->plane_size[i];
-               }
-       } else {
-               mfc_err_dev("invalid buf type (%d)\n", f->type);
-               return -EINVAL;
-       }
-
-       mfc_debug_leave();
-
-       return 0;
-}
-
-static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
-{
-       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
-       struct s5p_mfc_fmt *fmt;
-       struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
-
-       fmt = mfc_enc_find_format(ctx, pix_fmt_mp->pixelformat);
-       if (!fmt) {
-               mfc_err_dev("Unsupported format for %s\n",
-                               V4L2_TYPE_IS_OUTPUT(f->type) ? "source" : "destination");
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static void mfc_enc_check_format(struct s5p_mfc_ctx *ctx)
-{
-       switch (ctx->src_fmt->fourcc) {
-       case V4L2_PIX_FMT_NV16M_S10B:
-       case V4L2_PIX_FMT_NV61M_S10B:
-       case V4L2_PIX_FMT_NV16M_P210:
-       case V4L2_PIX_FMT_NV61M_P210:
-               mfc_debug(2, "[FRAME][10BIT] is 422 and 10bit format\n");
-               ctx->is_10bit = 1;
-               ctx->is_422 = 1;
-               break;
-       case V4L2_PIX_FMT_NV16M:
-       case V4L2_PIX_FMT_NV61M:
-               mfc_debug(2, "[FRAME] is 422 format\n");
-               ctx->is_10bit = 0;
-               ctx->is_422 = 1;
-               break;
-       case V4L2_PIX_FMT_NV12M_S10B:
-       case V4L2_PIX_FMT_NV12M_P010:
-       case V4L2_PIX_FMT_NV21M_S10B:
-       case V4L2_PIX_FMT_NV21M_P010:
-               mfc_debug(2, "[FRAME][10BIT] is 10bit format\n");
-               ctx->is_10bit = 1;
-               ctx->is_422 = 0;
-               break;
-       default:
-               ctx->is_10bit = 0;
-               ctx->is_422 = 0;
-               break;
-       }
-       mfc_debug(2, "[FRAME] 10bit: %d, 422: %d\n", ctx->is_10bit, ctx->is_422);
-}
-
-static int mfc_enc_check_resolution(struct s5p_mfc_ctx *ctx)
-{
-       int max_width = 0, max_height = 0, min_width = 0, min_height = 0, swap_check = 0;
-
-       /* Check max resolution */
-       switch (ctx->codec_mode) {
-       case S5P_FIMV_CODEC_HEVC_ENC:
-               if (ctx->is_422) {
-                       max_width = 65536;
-                       max_height = 8192;
-                       swap_check = 1;
-               } else {
-                       max_width = 8192;
-                       max_height = 8192;
-               }
-               break;
-       case S5P_FIMV_CODEC_BPG_ENC:
-               max_width = 65536;
-               max_height = 8192;
-               swap_check = 1;
-               break;
-       case S5P_FIMV_CODEC_H264_ENC:
-       case S5P_FIMV_CODEC_VP8_ENC:
-               max_width = 8192;
-               max_height = 8192;
-               break;
-       case S5P_FIMV_CODEC_VP9_ENC:
-               max_width = 4096;
-               max_height = 8192;
-               break;
-       case S5P_FIMV_CODEC_MPEG4_ENC:
-               max_width = 2048;
-               max_height = 2048;
-               break;
-       case S5P_FIMV_CODEC_H263_ENC:
-               max_width = 2048;
-               max_height = 1152;
-               break;
-       default:
-               mfc_err_ctx("Not supported codec(%d)\n", ctx->codec_mode);
-               return -EINVAL;
-       }
-
-       if (swap_check) {
-               if (!((ctx->crop_width < max_width && ctx->crop_height < max_height) ||
-                               (ctx->crop_width < max_height && ctx->crop_height < max_width))) {
-                       mfc_err_ctx("Resolution is too big(%dx%d > %dxi%d or %dx%d\n",
-                                       ctx->crop_width, ctx->crop_height, max_width, max_height,
-                                       max_height, max_width);
-                       return -EINVAL;
-               }
-       } else {
-               if (ctx->crop_width > max_width || ctx->crop_height > max_height) {
-                       mfc_err_ctx("Resolution is too big(%dx%d > %dx%d)\n",
-                                       ctx->crop_width, ctx->crop_height, max_width, max_height);
-                       return -EINVAL;
-               }
-       }
-
-       /* Check min resolution */
-       switch (ctx->codec_mode) {
-       case S5P_FIMV_CODEC_HEVC_ENC:
-       case S5P_FIMV_CODEC_BPG_ENC:
-       case S5P_FIMV_CODEC_VP9_ENC:
-               min_width = 64;
-               min_height = 64;
-               break;
-       case S5P_FIMV_CODEC_H264_ENC:
-       case S5P_FIMV_CODEC_VP8_ENC:
-       case S5P_FIMV_CODEC_MPEG4_ENC:
-       case S5P_FIMV_CODEC_H263_ENC:
-               min_width = 32;
-               min_height = 32;
-               break;
-       default:
-               mfc_err_ctx("Not supported codec(%d)\n", ctx->codec_mode);
-               return -EINVAL;
-       }
-
-       if (ctx->crop_width < min_width || ctx->crop_height < min_height) {
-               mfc_err_ctx("Resolution is too small(%dx%d < %dx%d)\n",
-                               ctx->crop_width, ctx->crop_height, min_width, min_height);
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static int vidioc_s_fmt_vid_cap_mplane(struct file *file, void *priv,
-                                                       struct v4l2_format *f)
-{
-       struct s5p_mfc_dev *dev = video_drvdata(file);
-       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
-       struct s5p_mfc_enc *enc = ctx->enc_priv;
-       struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
-       int ret = 0;
-
-       mfc_debug_enter();
-
-       if (ctx->vq_dst.streaming) {
-               mfc_err_ctx("dst queue busy\n");
-               return -EBUSY;
-       }
-
-       ctx->dst_fmt = mfc_enc_find_format(ctx, pix_fmt_mp->pixelformat);
-       if (!ctx->dst_fmt) {
-               mfc_err_ctx("Unsupported format for destination\n");
-               return -EINVAL;
-       }
-
-       ctx->codec_mode = ctx->dst_fmt->codec_mode;
-       mfc_info_ctx("[STREAM] Enc dst codec(%d) : %s\n",
-                       ctx->codec_mode, ctx->dst_fmt->name);
-
-       if (mfc_enc_check_resolution(ctx)) {
-               mfc_err_ctx("Unsupported resolution\n");
-               return -EINVAL;
-       }
-
-       if (ctx->otf_handle) {
-               if (ctx->dst_fmt->fourcc != V4L2_PIX_FMT_H264 &&
-                               ctx->dst_fmt->fourcc != V4L2_PIX_FMT_HEVC) {
-                       mfc_err_ctx("[OTF] only H.264 and HEVC is supported\n");
-                       return -EINVAL;
-               }
-               if (s5p_mfc_otf_init(ctx)) {
-                       mfc_err_ctx("[OTF] otf_init failed\n");
-                       s5p_mfc_otf_destroy(ctx);
-                       return -EINVAL;
-               }
-       }
-
-       enc->dst_buf_size = pix_fmt_mp->plane_fmt[0].sizeimage;
-       pix_fmt_mp->plane_fmt[0].bytesperline = 0;
-
-       ret = s5p_mfc_alloc_instance_context(ctx);
-       if (ret) {
-               mfc_err_ctx("Failed to allocate enc instance[%d] buffers\n",
-                               ctx->num);
-               return -ENOMEM;
-       }
-
-       s5p_mfc_change_state(ctx, MFCINST_INIT);
-
-       ctx->capture_state = QUEUE_FREE;
-
-       ret = s5p_mfc_alloc_enc_roi_buffer(ctx);
-       if (ret) {
-               mfc_err_ctx("[ROI] Failed to allocate ROI buffers\n");
-               s5p_mfc_release_instance_context(ctx);
-               return -ENOMEM;
-       }
-
-       MFC_TRACE_CTX_HWLOCK("**ENC s_fmt\n");
-
-       ret = s5p_mfc_get_hwlock_ctx(ctx);
-       if (ret < 0) {
-               mfc_err_dev("Failed to get hwlock\n");
-               s5p_mfc_release_instance_context(ctx);
-               s5p_mfc_release_enc_roi_buffer(ctx);
-               return -EBUSY;
-       }
-
-       s5p_mfc_set_bit(ctx->num, &dev->work_bits);
-       ret = s5p_mfc_just_run(dev, ctx->num);
-       if (ret) {
-               mfc_err_ctx("Failed to run MFC\n");
-               s5p_mfc_release_hwlock_ctx(ctx);
-               s5p_mfc_cleanup_work_bit_and_try_run(ctx);
-               s5p_mfc_release_instance_context(ctx);
-               s5p_mfc_release_enc_roi_buffer(ctx);
-               return -EIO;
-       }
-
-       if (s5p_mfc_wait_for_done_ctx(ctx,
-                               S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET)) {
-               mfc_err_ctx("time out during open instance\n");
-               s5p_mfc_release_hwlock_ctx(ctx);
-               s5p_mfc_cleanup_work_bit_and_try_run(ctx);
-               s5p_mfc_release_instance_context(ctx);
-               s5p_mfc_release_enc_roi_buffer(ctx);
-               return -EIO;
-       }
-       s5p_mfc_release_hwlock_ctx(ctx);
-
-       mfc_debug(2, "Got instance number: %d\n", ctx->inst_no);
-
-       if (s5p_mfc_enc_ctx_ready(ctx))
-               s5p_mfc_set_bit(ctx->num, &dev->work_bits);
-       if (ctx->otf_handle && s5p_mfc_otf_ctx_ready(ctx))
-               s5p_mfc_set_bit(ctx->num, &dev->work_bits);
-       if (s5p_mfc_is_work_to_do(dev))
-               queue_work(dev->butler_wq, &dev->butler_work);
-
-       mfc_debug_leave();
-       return 0;
-}
-
-static int vidioc_s_fmt_vid_out_mplane(struct file *file, void *priv,
-                                                       struct v4l2_format *f)
-{
-       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
-       struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
-
-       mfc_debug_enter();
-
-       if (ctx->vq_src.streaming) {
-               mfc_err_ctx("src queue busy\n");
-               return -EBUSY;
-       }
-
-       if (ctx->otf_handle) {
-               mfc_info_ctx("[OTF] skip source s_fmt\n");
-               return 0;
-       }
-
-       ctx->src_fmt = mfc_enc_find_format(ctx, pix_fmt_mp->pixelformat);
-       if (!ctx->src_fmt) {
-               mfc_err_ctx("Unsupported format for source\n");
-               return -EINVAL;
-       }
-
-       if (ctx->src_fmt->mem_planes != pix_fmt_mp->num_planes) {
-               mfc_err_ctx("[FRAME] enc src plane number is different (%d != %d)\n",
-                               ctx->src_fmt->mem_planes, pix_fmt_mp->num_planes);
-               return -EINVAL;
-       }
-
-       ctx->raw_buf.num_planes = ctx->src_fmt->num_planes;
-       ctx->img_width = pix_fmt_mp->width;
-       ctx->img_height = pix_fmt_mp->height;
-       ctx->buf_stride = pix_fmt_mp->plane_fmt[0].bytesperline;
-
-       mfc_enc_check_format(ctx);
-
-       if (ctx->state == MFCINST_RUNNING) {
-               s5p_mfc_change_state(ctx, MFCINST_GOT_INST);
-               mfc_info_ctx("[DRC] Enc resolution is changed\n");
-       }
-
-       mfc_info_ctx("[FRAME] enc src pixelformat : %s\n", ctx->src_fmt->name);
-       mfc_info_ctx("[FRAME] resolution w: %d, h: %d, stride: %d\n",
-                       pix_fmt_mp->width, pix_fmt_mp->height, ctx->buf_stride);
-
-       /*
-        * It should be keep till buffer size and stride was calculated.
-        * And it can be changed to real encoding size, if user call the s_crop.
-        */
-       ctx->crop_width = ctx->img_width;
-       ctx->crop_height = ctx->img_height;
-       s5p_mfc_enc_calc_src_size(ctx);
-
-       ctx->output_state = QUEUE_FREE;
-
-       mfc_debug_leave();
-       return 0;
-}
-
-static int vidioc_g_crop(struct file *file, void *fh, struct v4l2_crop *cr)
-{
-       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
-
-       mfc_debug_enter();
-
-       cr->c.left = ctx->crop_left;
-       cr->c.top = ctx->crop_top;
-       cr->c.width = ctx->crop_width;
-       cr->c.height = ctx->crop_height;
-
-       mfc_debug(2, "[FRAME] enc crop w: %d, h: %d, offset l: %d t: %d\n",
-                       ctx->crop_width, ctx->crop_height, ctx->crop_left, ctx->crop_top);
-
-       mfc_debug_leave();
-
-       return 0;
-}
-
-static int vidioc_s_crop(struct file *file, void *priv, const struct v4l2_crop *cr)
-{
-       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
-
-       mfc_debug_enter();
-
-       if (cr->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               mfc_err_ctx("not supported type (It can only in the source)\n");
-               return -EINVAL;
-       }
-
-       if (cr->c.left < 0 || cr->c.top < 0) {
-               mfc_err_ctx("[FRAME] crop position is negative\n");
-               return -EINVAL;
-       }
-
-       if ((cr->c.height > ctx->img_height) || (cr->c.top > ctx->img_height) ||
-                       (cr->c.width > ctx->img_width) || (cr->c.left > ctx->img_width) ||
-                       (cr->c.left <= (ctx->img_width - cr->c.width)) ||
-                       (cr->c.top <= (ctx->img_height - cr->c.height))) {
-               mfc_err_ctx("[FRAME] Out of crop range: (%d,%d,%d,%d) from %dx%d\n",
-                               cr->c.left, cr->c.top, cr->c.width, cr->c.height,
-                               ctx->img_width, ctx->img_height);
-               return -EINVAL;
-       }
-
-       ctx->crop_top = cr->c.top;
-       ctx->crop_left = cr->c.left;
-       ctx->crop_height = cr->c.height;
-       ctx->crop_width = cr->c.width;
-
-       mfc_debug(3, "[FRAME] enc original: %dx%d, crop: %dx%d, offset l: %d t: %d\n",
-                       ctx->img_width, ctx->img_height,
-                       ctx->crop_width, ctx->crop_height,
-                       ctx->crop_left, ctx->crop_top);
-
-       return 0;
-}
-
-static int vidioc_reqbufs(struct file *file, void *priv,
-                                         struct v4l2_requestbuffers *reqbufs)
-{
-       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
-       int ret = 0;
-
-       mfc_debug_enter();
-
-       if (reqbufs->memory == V4L2_MEMORY_MMAP) {
-               mfc_err_ctx("Not supported memory type (%d)\n", reqbufs->memory);
-               return -EINVAL;
-       }
-
-       if (ctx->otf_handle) {
-               mfc_info_ctx("[OTF] skip reqbufs\n");
-               return 0;
-       }
-
-       if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-               mfc_debug(4, "enc dst reqbuf(%d)\n", reqbufs->count);
-               if (reqbufs->count == 0) {
-                       ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
-                       ctx->capture_state = QUEUE_FREE;
-                       return ret;
-               }
-
-               if (ctx->capture_state != QUEUE_FREE) {
-                       mfc_err_ctx("invalid capture state: %d\n", ctx->capture_state);
-                       return -EINVAL;
-               }
-
-               ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
-               if (ret) {
-                       mfc_err_ctx("error in vb2_reqbufs() for E(D)\n");
-                       return ret;
-               }
-
-               ctx->capture_state = QUEUE_BUFS_REQUESTED;
-       } else if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               mfc_debug(4, "enc src reqbuf(%d)\n", reqbufs->count);
-               if (reqbufs->count == 0) {
-                       ret = vb2_reqbufs(&ctx->vq_src, reqbufs);
-                       ctx->output_state = QUEUE_FREE;
-                       return ret;
-               }
-
-               if (ctx->output_state != QUEUE_FREE) {
-                       mfc_err_ctx("invalid output state: %d\n", ctx->output_state);
-                       return -EINVAL;
-               }
-
-               ret = vb2_reqbufs(&ctx->vq_src, reqbufs);
-               if (ret) {
-                       mfc_err_ctx("error in vb2_reqbufs() for E(S)\n");
-                       return ret;
-               }
-
-               ctx->output_state = QUEUE_BUFS_REQUESTED;
-       } else {
-               mfc_err_ctx("invalid buf type (%d)\n", reqbufs->type);
-               return -EINVAL;
-       }
-
-       mfc_debug_leave();
-
-       return ret;
-}
-
-static int vidioc_querybuf(struct file *file, void *priv,
-                                                  struct v4l2_buffer *buf)
-{
-       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
-       int ret = 0;
-
-       mfc_debug_enter();
-
-       if (ctx->otf_handle) {
-               mfc_info_ctx("[OTF] skip source querybuf\n");
-               return 0;
-       }
-
-       if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-               mfc_debug(4, "enc dst querybuf, state: %d\n", ctx->state);
-               ret = vb2_querybuf(&ctx->vq_dst, buf);
-               if (ret != 0) {
-                       mfc_err_dev("enc dst: error in vb2_querybuf()\n");
-                       return ret;
-               }
-       } else if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               mfc_debug(4, "enc src querybuf, state: %d\n", ctx->state);
-               ret = vb2_querybuf(&ctx->vq_src, buf);
-               if (ret != 0) {
-                       mfc_err_dev("enc src: error in vb2_querybuf()\n");
-                       return ret;
-               }
-       } else {
-               mfc_err_dev("invalid buf type (%d)\n", buf->type);
-               return -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_mfc_ctx(file->private_data);
-       int i, ret = -EINVAL;
-
-       mfc_debug_enter();
-
-       if (ctx->otf_handle) {
-               mfc_info_ctx("[OTF] skip qbuf\n");
-               return 0;
-       }
-
-       if (ctx->state == MFCINST_ERROR) {
-               mfc_err_ctx("Call on QBUF after unrecoverable error\n");
-               return -EIO;
-       }
-
-       if (V4L2_TYPE_IS_MULTIPLANAR(buf->type) && !buf->length) {
-               mfc_err_ctx("multiplanar but length is zero\n");
-               return -EIO;
-       }
-
-       if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               mfc_debug(4, "enc src buf[%d] Q\n", buf->index);
-               for (i = 0; i < ctx->src_fmt->num_planes; i++) {
-                       if (!buf->m.planes[i].bytesused) {
-                               mfc_debug(2, "[FRAME] enc src[%d] size zero, "
-                                               "changed to buf size %d\n",
-                                               i, buf->m.planes[i].length);
-                               buf->m.planes[i].bytesused = buf->m.planes[i].length;
-                       } else {
-                               mfc_debug(2, "[FRAME] enc src[%d] size %d\n",
-                                               i, buf->m.planes[i].bytesused);
-                       }
-               }
-               ret = vb2_qbuf(&ctx->vq_src, buf);
-       } else {
-               mfc_debug(4, "enc dst buf[%d] Q\n", buf->index);
-               ret = vb2_qbuf(&ctx->vq_dst, buf);
-       }
-
-       mfc_debug_leave();
-       return ret;
-}
-
-/* Dequeue a buffer */
-static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
-{
-       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
-       int ret;
-
-       mfc_debug_enter();
-
-       if (ctx->otf_handle) {
-               mfc_info_ctx("[OTF] skip dqbuf\n");
-               return 0;
-       }
-
-       if (ctx->state == MFCINST_ERROR) {
-               mfc_err_ctx("Call on DQBUF after unrecoverable error\n");
-               return -EIO;
-       }
-       if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               mfc_debug(4, "enc src buf[%d] DQ\n", buf->index);
-               ret = vb2_dqbuf(&ctx->vq_src, buf, file->f_flags & O_NONBLOCK);
-       } else {
-               mfc_debug(4, "enc dst buf[%d] DQ\n", buf->index);
-               ret = vb2_dqbuf(&ctx->vq_dst, buf, file->f_flags & O_NONBLOCK);
-       }
-       mfc_debug_leave();
-       return ret;
-}
-
-/* Stream on */
-static int vidioc_streamon(struct file *file, void *priv,
-                          enum v4l2_buf_type type)
-{
-       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
-       int ret = -EINVAL;
-
-       mfc_debug_enter();
-
-       if (ctx->otf_handle) {
-               mfc_info_ctx("[OTF] skip streamon\n");
-               return 0;
-       }
-
-       if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               mfc_debug(4, "enc src streamon\n");
-               ret = vb2_streamon(&ctx->vq_src, type);
-
-               if (!ret) {
-                       s5p_mfc_qos_on(ctx);
-               }
-       } else {
-               mfc_debug(4, "enc dst streamon\n");
-               ret = vb2_streamon(&ctx->vq_dst, type);
-       }
-
-       mfc_debug(2, "src: %d, dst: %d, state = %d, dpb_count = %d\n",
-                 s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->src_buf_queue),
-                 s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->dst_buf_queue),
-                 ctx->state, ctx->dpb_count);
-       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_mfc_ctx(file->private_data);
-       int ret;
-
-       mfc_debug_enter();
-
-       if (ctx->otf_handle) {
-               mfc_info_ctx("[OTF] skip streamoff\n");
-               return 0;
-       }
-
-       ret = -EINVAL;
-       if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               mfc_debug(4, "enc src streamoff\n");
-               s5p_mfc_qos_reset_last_framerate(ctx);
-
-               ret = vb2_streamoff(&ctx->vq_src, type);
-               if (!ret)
-                       s5p_mfc_qos_off(ctx);
-       } else {
-               mfc_debug(4, "enc dst streamoff\n");
-               ret = vb2_streamoff(&ctx->vq_dst, type);
-       }
-
-       mfc_debug_leave();
-
-       return ret;
-}
-
-/* Query a ctrl */
-static int vidioc_queryctrl(struct file *file, void *priv,
-                           struct v4l2_queryctrl *qc)
-{
-       struct v4l2_queryctrl *c;
-
-       c = mfc_enc_get_ctrl(qc->id);
-       if (!c) {
-               mfc_err_dev("[CTRLS] not supported control id (%#x)\n", qc->id);
-               return -EINVAL;
-       }
-
-       *qc = *c;
-       return 0;
-}
-
-static int mfc_enc_ext_info(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       int val = 0;
-
-       val |= ENC_SET_SPARE_SIZE;
-       val |= ENC_SET_TEMP_SVC_CH;
-
-       if (MFC_FEATURE_SUPPORT(dev, dev->pdata->skype))
-               val |= ENC_SET_SKYPE_FLAG;
-
-       val |= ENC_SET_ROI_CONTROL;
-       val |= ENC_SET_QP_BOUND_PB;
-       val |= ENC_SET_FIXED_SLICE;
-       val |= ENC_SET_PVC_MODE;
-       val |= ENC_SET_RATIO_OF_INTRA;
-
-       if (MFC_FEATURE_SUPPORT(dev, dev->pdata->color_aspect_enc))
-               val |= ENC_SET_COLOR_ASPECT;
-
-       val |= ENC_SET_HP_BITRATE_CONTROL;
-
-       if (MFC_FEATURE_SUPPORT(dev, dev->pdata->static_info_enc))
-               val |= ENC_SET_STATIC_INFO;
-
-       mfc_debug(5, "[CTRLS] ext info val: %#x\n", val);
-
-       return val;
-}
-
-static int mfc_enc_get_ctrl_val(struct s5p_mfc_ctx *ctx, struct v4l2_control *ctrl)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_enc *enc = ctx->enc_priv;
-       struct s5p_mfc_ctx_ctrl *ctx_ctrl;
-       int ret = 0;
-       int found = 0;
-
-       switch (ctrl->id) {
-       case V4L2_CID_CACHEABLE:
-               mfc_debug(5, "it is supported only V4L2_MEMORY_MMAP\n");
-               break;
-       case V4L2_CID_MPEG_MFC51_VIDEO_STREAM_SIZE:
-               ctrl->value = enc->dst_buf_size;
-               break;
-       case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TYPE:
-               ctrl->value = enc->frame_type;
-               break;
-       case V4L2_CID_MPEG_MFC51_VIDEO_CHECK_STATE:
-               ctrl->value = MFCSTATE_PROCESSING;
-               break;
-       case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG:
-       case V4L2_CID_MPEG_MFC51_VIDEO_LUMA_ADDR:
-       case V4L2_CID_MPEG_MFC51_VIDEO_CHROMA_ADDR:
-       case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_STATUS:
-               list_for_each_entry(ctx_ctrl, &ctx->ctrls, list) {
-                       if (!(ctx_ctrl->type & MFC_CTRL_TYPE_GET))
-                               continue;
-
-                       if (ctx_ctrl->id == ctrl->id) {
-                               if (ctx_ctrl->has_new) {
-                                       ctx_ctrl->has_new = 0;
-                                       ctrl->value = ctx_ctrl->val;
-                               } else {
-                                       mfc_debug(5, "[CTRLS] Control value "\
-                                                       "is not up to date: "\
-                                                       "0x%08x\n", ctrl->id);
-                                       return -EINVAL;
-                               }
-
-                               found = 1;
-                               break;
-                       }
-               }
-
-               if (!found) {
-                       mfc_err_ctx("Invalid control: 0x%08x\n", ctrl->id);
-                       return -EINVAL;
-               }
-               break;
-       case V4L2_CID_MPEG_MFC_GET_VERSION_INFO:
-               ctrl->value = dev->pdata->ip_ver;
-               break;
-       case V4L2_CID_MPEG_MFC_GET_DRIVER_INFO:
-               ctrl->value = MFC_DRIVER_INFO;
-               break;
-       case V4L2_CID_MPEG_MFC_GET_EXTRA_BUFFER_SIZE:
-               ctrl->value = MFC_LINEAR_BUF_SIZE;
-               break;
-       case V4L2_CID_MPEG_VIDEO_QOS_RATIO:
-               ctrl->value = ctx->qos_ratio;
-               break;
-       case V4L2_CID_MPEG_MFC_GET_EXT_INFO:
-               ctrl->value = mfc_enc_ext_info(ctx);
-               break;
-       case V4L2_CID_MPEG_VIDEO_BPG_HEADER_SIZE:
-               ctrl->value = enc->header_size;
-               break;
-       default:
-               mfc_err_ctx("Invalid control: 0x%08x\n", ctrl->id);
-               ret = -EINVAL;
-               break;
-       }
-
-       mfc_debug(5, "[CTRLS] get id: %#x, value: %d\n", ctrl->id, ctrl->value);
-
-       return ret;
-}
-
-static int vidioc_g_ctrl(struct file *file, void *priv,
-                        struct v4l2_control *ctrl)
-{
-       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
-       int ret = 0;
-
-       mfc_debug_enter();
-       ret = mfc_enc_get_ctrl_val(ctx, ctrl);
-       mfc_debug_leave();
-
-       return ret;
-}
-
-static inline int mfc_enc_h264_level(enum v4l2_mpeg_video_h264_level lvl)
-{
-       static unsigned int t[V4L2_MPEG_VIDEO_H264_LEVEL_5_1 + 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,
-               /* V4L2_MPEG_VIDEO_H264_LEVEL_4_1   */ 41,
-               /* V4L2_MPEG_VIDEO_H264_LEVEL_4_2   */ 42,
-               /* V4L2_MPEG_VIDEO_H264_LEVEL_5_0   */ 50,
-               /* V4L2_MPEG_VIDEO_H264_LEVEL_5_1   */ 51,
-       };
-       return t[lvl];
-}
-
-static inline int mfc_enc_mpeg4_level(enum v4l2_mpeg_video_mpeg4_level lvl)
-{
-       static unsigned int t[V4L2_MPEG_VIDEO_MPEG4_LEVEL_6 + 1] = {
-               /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_0             */ 0,
-               /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_0B, Simple    */ 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, Advanced  */ 7,
-               /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_4             */ 4,
-               /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_5             */ 5,
-               /* V4L2_MPEG_VIDEO_MPEG4_LEVEL_6,  Simple    */ 6,
-       };
-       return t[lvl];
-}
-
-static inline int mfc_enc_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];
-}
-
-static int mfc_enc_set_param(struct s5p_mfc_ctx *ctx, struct v4l2_control *ctrl)
-{
-       struct s5p_mfc_enc *enc = ctx->enc_priv;
-       struct s5p_mfc_enc_params *p = &enc->params;
-       int ret = 0;
-
-       switch (ctrl->id) {
-       case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
-               p->gop_size = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE:
-               p->slice_mode =
-                       (enum v4l2_mpeg_video_multi_slice_mode)ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB:
-               p->slice_mb = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES:
-               p->slice_bit = ctrl->value * 8;
-               break;
-       case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB_ROW:
-               p->slice_mb_row = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB:
-               p->intra_refresh_mb = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC51_VIDEO_PADDING:
-               p->pad = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC51_VIDEO_PADDING_YUV:
-               p->pad_luma = (ctrl->value >> 16) & 0xff;
-               p->pad_cb = (ctrl->value >> 8) & 0xff;
-               p->pad_cr = (ctrl->value >> 0) & 0xff;
-               break;
-       case V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE:
-               p->rc_frame = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_BITRATE:
-               p->rc_bitrate = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC51_VIDEO_RC_REACTION_COEFF:
-               p->rc_reaction_coeff = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE:
-               enc->force_frame_type = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_VBV_SIZE:
-               p->vbv_buf_size = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEADER_MODE:
-               p->seq_hdr_mode =
-                       (enum v4l2_mpeg_video_header_mode)(ctrl->value);
-               break;
-       case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE:
-               p->frame_skip_mode =
-                       (enum v4l2_mpeg_mfc51_video_frame_skip_mode)
-                       (ctrl->value);
-               break;
-       case V4L2_CID_MPEG_MFC51_VIDEO_RC_FIXED_TARGET_BIT:
-               p->fixed_target_bit = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_B_FRAMES:
-               p->num_b_frame = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
-               p->codec.h264.profile =
-               mfc_enc_h264_profile(ctx, (enum v4l2_mpeg_video_h264_profile)(ctrl->value));
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
-               p->codec.h264.level =
-               mfc_enc_h264_level((enum v4l2_mpeg_video_h264_level)(ctrl->value));
-               break;
-       case V4L2_CID_MPEG_MFC51_VIDEO_H264_INTERLACE:
-               p->codec.h264.interlace = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE:
-               p->codec.h264.loop_filter_mode =
-               (enum v4l2_mpeg_video_h264_loop_filter_mode)(ctrl->value);
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA:
-               p->codec.h264.loop_filter_alpha = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA:
-               p->codec.h264.loop_filter_beta = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:
-               p->codec.h264.entropy_mode =
-                       (enum v4l2_mpeg_video_h264_entropy_mode)(ctrl->value);
-               break;
-       case V4L2_CID_MPEG_MFC51_VIDEO_H264_NUM_REF_PIC_FOR_P:
-               p->num_refs_for_p = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM:
-               p->codec.h264._8x8_transform = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE:
-               p->rc_mb = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC51_VIDEO_H264_RC_FRAME_RATE:
-               p->rc_framerate = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP:
-               p->codec.h264.rc_frame_qp = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:
-               p->codec.h264.rc_min_qp = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:
-               p->codec.h264.rc_max_qp = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_MIN_QP_P:
-               p->codec.h264.rc_min_qp_p = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_MAX_QP_P:
-               p->codec.h264.rc_max_qp_p = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_MIN_QP_B:
-               p->codec.h264.rc_min_qp_b = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_MAX_QP_B:
-               p->codec.h264.rc_max_qp_b = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_DARK:
-               p->codec.h264.rc_mb_dark = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_SMOOTH:
-               p->codec.h264.rc_mb_smooth = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_STATIC:
-               p->codec.h264.rc_mb_static = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_ACTIVITY:
-               p->codec.h264.rc_mb_activity = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP:
-               p->codec.h264.rc_p_frame_qp = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP:
-               p->codec.h264.rc_b_frame_qp = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE:
-               p->codec.h264.ar_vui = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC:
-               p->codec.h264.ar_vui_idc =
-               mfc_enc_vui_sar_idc((enum v4l2_mpeg_video_h264_vui_sar_idc)(ctrl->value));
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH:
-               p->codec.h264.ext_sar_width = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_HEIGHT:
-               p->codec.h264.ext_sar_height = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
-               p->codec.h264.open_gop = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_I_PERIOD:
-               p->codec.h264.open_gop_size = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING:
-               p->codec.h264.hier_qp_enable = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE:
-               p->codec.h264.hier_qp_type =
-               (enum v4l2_mpeg_video_h264_hierarchical_coding_type)(ctrl->value);
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER:
-               p->codec.h264.num_hier_layer = ctrl->value & 0x7;
-               p->codec.h264.hier_ref_type = (ctrl->value >> 16) & 0x1;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_QP:
-               p->codec.h264.hier_qp_layer[(ctrl->value >> 16) & 0x7]
-                       = ctrl->value & 0xFF;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT0:
-               p->codec.h264.hier_bit_layer[0] = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT1:
-               p->codec.h264.hier_bit_layer[1] = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT2:
-               p->codec.h264.hier_bit_layer[2] = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT3:
-               p->codec.h264.hier_bit_layer[3] = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT4:
-               p->codec.h264.hier_bit_layer[4] = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT5:
-               p->codec.h264.hier_bit_layer[5] = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT6:
-               p->codec.h264.hier_bit_layer[6] = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING:
-               p->codec.h264.sei_gen_enable = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_CURRENT_FRAME_0:
-               p->codec.h264.sei_fp_curr_frame_0 = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE:
-               p->codec.h264.sei_fp_arrangement_type = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_FMO:
-               p->codec.h264.fmo_enable = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_FMO_MAP_TYPE:
-               switch ((enum v4l2_mpeg_video_h264_fmo_map_type)(ctrl->value)) {
-               case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_INTERLEAVED_SLICES:
-               case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_SCATTERED_SLICES:
-               case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_RASTER_SCAN:
-               case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_WIPE_SCAN:
-                       p->codec.h264.fmo_slice_map_type = ctrl->value;
-                       break;
-               default:
-                       ret = -EINVAL;
-               }
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_FMO_SLICE_GROUP:
-               p->codec.h264.fmo_slice_num_grp = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_FMO_RUN_LENGTH:
-               p->codec.h264.fmo_run_length[(ctrl->value >> 30) & 0x3]
-                       = ctrl->value & 0x3FFFFFFF;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_DIRECTION:
-               p->codec.h264.fmo_sg_dir = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_RATE:
-               p->codec.h264.fmo_sg_rate = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_ASO:
-               p->codec.h264.aso_enable = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_ASO_SLICE_ORDER:
-               p->codec.h264.aso_slice_order[(ctrl->value >> 18) & 0x7]
-                       &= ~(0xFF << (((ctrl->value >> 16) & 0x3) << 3));
-               p->codec.h264.aso_slice_order[(ctrl->value >> 18) & 0x7]
-                       |= (ctrl->value & 0xFF) << \
-                               (((ctrl->value >> 16) & 0x3) << 3);
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_PREPEND_SPSPPS_TO_IDR:
-               p->codec.h264.prepend_sps_pps_to_idr = ctrl->value ? 1 : 0;
-               break;
-       case V4L2_CID_MPEG_MFC_H264_ENABLE_LTR:
-               p->codec.h264.enable_ltr = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC_H264_NUM_OF_LTR:
-               p->codec.h264.num_of_ltr = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC_H264_BASE_PRIORITY:
-               p->codec.h264.base_priority = ctrl->value;
-               p->codec.h264.set_priority = 1;
-               break;
-       case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE:
-               switch ((enum v4l2_mpeg_video_mpeg4_profile)(ctrl->value)) {
-               case V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE:
-                       p->codec.mpeg4.profile =
-                               S5P_FIMV_E_PROFILE_MPEG4_SIMPLE;
-                       break;
-               case V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE:
-                       p->codec.mpeg4.profile =
-                       S5P_FIMV_E_PROFILE_MPEG4_ADVANCED_SIMPLE;
-                       break;
-               default:
-                       ret = -EINVAL;
-               }
-               break;
-       case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL:
-               p->codec.mpeg4.level =
-               mfc_enc_mpeg4_level((enum v4l2_mpeg_video_mpeg4_level)(ctrl->value));
-               break;
-       case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP:
-               p->codec.mpeg4.rc_frame_qp = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP:
-               p->codec.mpeg4.rc_min_qp = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP:
-               p->codec.mpeg4.rc_max_qp = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_P:
-               p->codec.mpeg4.rc_min_qp_p = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_P:
-               p->codec.mpeg4.rc_max_qp_p = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_B:
-               p->codec.mpeg4.rc_min_qp_b = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_B:
-               p->codec.mpeg4.rc_max_qp_b = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_MPEG4_QPEL:
-               p->codec.mpeg4.quarter_pixel = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP:
-               p->codec.mpeg4.rc_p_frame_qp = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP:
-               p->codec.mpeg4.rc_b_frame_qp = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC51_VIDEO_MPEG4_VOP_TIME_RES:
-               p->codec.mpeg4.vop_time_res = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC51_VIDEO_MPEG4_VOP_FRM_DELTA:
-               p->codec.mpeg4.vop_frm_delta = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC51_VIDEO_H263_RC_FRAME_RATE:
-               p->rc_framerate = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP:
-               p->codec.mpeg4.rc_frame_qp = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H263_MIN_QP:
-               p->codec.mpeg4.rc_min_qp = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H263_MAX_QP:
-               p->codec.mpeg4.rc_max_qp = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H263_MIN_QP_P:
-               p->codec.mpeg4.rc_min_qp_p = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H263_MAX_QP_P:
-               p->codec.mpeg4.rc_max_qp_p = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP:
-               p->codec.mpeg4.rc_p_frame_qp = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC70_VIDEO_VP8_VERSION:
-               p->codec.vp8.vp8_version = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC70_VIDEO_VP8_RC_FRAME_RATE:
-               p->rc_framerate = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_VP8_MIN_QP:
-               p->codec.vp8.rc_min_qp = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_VP8_MAX_QP:
-               p->codec.vp8.rc_max_qp = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_VP8_MIN_QP_P:
-               p->codec.vp8.rc_min_qp_p = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_VP8_MAX_QP_P:
-               p->codec.vp8.rc_max_qp_p = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_VP8_I_FRAME_QP:
-               p->codec.vp8.rc_frame_qp = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_VP8_P_FRAME_QP:
-               p->codec.vp8.rc_p_frame_qp = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC70_VIDEO_VP8_NUM_OF_PARTITIONS:
-               p->codec.vp8.vp8_numberofpartitions = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC70_VIDEO_VP8_FILTER_LEVEL:
-               p->codec.vp8.vp8_filterlevel = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC70_VIDEO_VP8_FILTER_SHARPNESS:
-               p->codec.vp8.vp8_filtersharpness = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC70_VIDEO_VP8_GOLDEN_FRAMESEL:
-               p->codec.vp8.vp8_goldenframesel = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC70_VIDEO_VP8_GF_REFRESH_PERIOD:
-               p->codec.vp8.vp8_gfrefreshperiod = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC70_VIDEO_VP8_HIERARCHY_QP_ENABLE:
-               p->codec.vp8.hier_qp_enable = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC70_VIDEO_VP8_HIERARCHY_QP_LAYER0:
-               p->codec.vp8.hier_qp_layer[(ctrl->value >> 16) & 0x3]
-                       = ctrl->value & 0xFF;
-               break;
-       case V4L2_CID_MPEG_MFC70_VIDEO_VP8_HIERARCHY_QP_LAYER1:
-               p->codec.vp8.hier_qp_layer[(ctrl->value >> 16) & 0x3]
-                       = ctrl->value & 0xFF;
-               break;
-       case V4L2_CID_MPEG_MFC70_VIDEO_VP8_HIERARCHY_QP_LAYER2:
-               p->codec.vp8.hier_qp_layer[(ctrl->value >> 16) & 0x3]
-                       = ctrl->value & 0xFF;
-               break;
-       case V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_BIT0:
-               p->codec.vp8.hier_bit_layer[0] = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_BIT1:
-               p->codec.vp8.hier_bit_layer[1] = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_BIT2:
-               p->codec.vp8.hier_bit_layer[2] = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC70_VIDEO_VP8_REF_NUMBER_FOR_PFRAMES:
-               p->num_refs_for_p = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC70_VIDEO_VP8_DISABLE_INTRA_MD4X4:
-               p->codec.vp8.intra_4x4mode_disable = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC70_VIDEO_VP8_NUM_TEMPORAL_LAYER:
-               p->codec.vp8.num_hier_layer = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_VP9_VERSION:
-               p->codec.vp9.vp9_version = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_VP9_RC_FRAME_RATE:
-               p->rc_framerate = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_VP9_MIN_QP:
-               p->codec.vp9.rc_min_qp = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_VP9_MAX_QP:
-               p->codec.vp9.rc_max_qp = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_VP9_MIN_QP_P:
-               p->codec.vp9.rc_min_qp_p = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_VP9_MAX_QP_P:
-               p->codec.vp9.rc_max_qp_p = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_VP9_I_FRAME_QP:
-               p->codec.vp9.rc_frame_qp = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_VP9_P_FRAME_QP:
-               p->codec.vp9.rc_p_frame_qp = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_VP9_GOLDEN_FRAMESEL:
-               p->codec.vp9.vp9_goldenframesel = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_VP9_GF_REFRESH_PERIOD:
-               p->codec.vp9.vp9_gfrefreshperiod = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_VP9_HIERARCHY_QP_ENABLE:
-               p->codec.vp9.hier_qp_enable = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_QP:
-               p->codec.vp9.hier_qp_layer[(ctrl->value >> 16) & 0x3]
-                       = ctrl->value & 0xFF;
-               break;
-       case V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_BIT0:
-               p->codec.vp9.hier_bit_layer[0] = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_BIT1:
-               p->codec.vp9.hier_bit_layer[1] = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_BIT2:
-               p->codec.vp9.hier_bit_layer[2] = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_VP9_REF_NUMBER_FOR_PFRAMES:
-               p->num_refs_for_p = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER:
-               p->codec.vp9.num_hier_layer = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_VP9_MAX_PARTITION_DEPTH:
-               p->codec.vp9.max_partition_depth = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_VP9_DISABLE_INTRA_PU_SPLIT:
-               p->codec.vp9.intra_pu_split_disable = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_DISABLE_IVF_HEADER:
-               p->ivf_header_disable = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_VP9_PROFILE:
-               p->codec.vp9.profile = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP:
-               p->codec.hevc.rc_frame_qp = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_QP:
-               p->codec.hevc.rc_p_frame_qp = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_QP:
-               p->codec.hevc.rc_b_frame_qp = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_RC_FRAME_RATE:
-               p->rc_framerate = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP:
-               p->codec.hevc.rc_min_qp = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP:
-               p->codec.hevc.rc_max_qp = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_P:
-               p->codec.hevc.rc_min_qp_p = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_P:
-               p->codec.hevc.rc_max_qp_p = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_B:
-               p->codec.hevc.rc_min_qp_b = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_B:
-               p->codec.hevc.rc_max_qp_b = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_LEVEL:
-               p->codec.hevc.level = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_PROFILE:
-               p->codec.hevc.profile = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_ADAPTIVE_RC_DARK:
-               p->codec.hevc.rc_lcu_dark = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_ADAPTIVE_RC_SMOOTH:
-               p->codec.hevc.rc_lcu_smooth = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_ADAPTIVE_RC_STATIC:
-               p->codec.hevc.rc_lcu_static = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_ADAPTIVE_RC_ACTIVITY:
-               p->codec.hevc.rc_lcu_activity = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_TIER_FLAG:
-               p->codec.hevc.tier_flag = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_MAX_PARTITION_DEPTH:
-               p->codec.hevc.max_partition_depth = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_REF_NUMBER_FOR_PFRAMES:
-               p->num_refs_for_p = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_REFRESH_TYPE:
-               p->codec.hevc.refreshtype = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_CONST_INTRA_PRED_ENABLE:
-               p->codec.hevc.const_intra_period_enable = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LOSSLESS_CU_ENABLE:
-               p->codec.hevc.lossless_cu_enable = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_WAVEFRONT_ENABLE:
-               p->codec.hevc.wavefront_enable = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LF_DISABLE:
-               p->codec.hevc.loopfilter_disable = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LF_SLICE_BOUNDARY:
-               p->codec.hevc.loopfilter_across = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LTR_ENABLE:
-               p->codec.hevc.enable_ltr = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_QP_ENABLE:
-               p->codec.hevc.hier_qp_enable = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_TYPE:
-               p->codec.hevc.hier_qp_type =
-               (enum v4l2_mpeg_video_hevc_hierarchical_coding_type)(ctrl->value);
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER:
-               p->codec.hevc.num_hier_layer = ctrl->value & 0x7;
-               p->codec.hevc.hier_ref_type = (ctrl->value >> 16) & 0x1;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_QP:
-               p->codec.hevc.hier_qp_layer[(ctrl->value >> 16) & 0x7]
-                       = ctrl->value & 0xFF;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT0:
-               p->codec.hevc.hier_bit_layer[0] = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT1:
-               p->codec.hevc.hier_bit_layer[1] = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT2:
-               p->codec.hevc.hier_bit_layer[2] = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT3:
-               p->codec.hevc.hier_bit_layer[3] = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT4:
-               p->codec.hevc.hier_bit_layer[4] = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT5:
-               p->codec.hevc.hier_bit_layer[5] = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT6:
-               p->codec.hevc.hier_bit_layer[6] = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_GENERAL_PB_ENABLE:
-               p->codec.hevc.general_pb_enable = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_TEMPORAL_ID_ENABLE:
-               p->codec.hevc.temporal_id_enable = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_STRONG_SMOTHING_FLAG:
-               p->codec.hevc.strong_intra_smooth = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_DISABLE_INTRA_PU_SPLIT:
-               p->codec.hevc.intra_pu_split_disable = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_DISABLE_TMV_PREDICTION:
-               p->codec.hevc.tmv_prediction_disable = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_MAX_NUM_MERGE_MV_MINUS1:
-               p->codec.hevc.max_num_merge_mv = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_WITHOUT_STARTCODE_ENABLE:
-               p->codec.hevc.encoding_nostartcode_enable = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_REFRESH_PERIOD:
-               p->codec.hevc.refreshperiod = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LF_BETA_OFFSET_DIV2:
-               p->codec.hevc.lf_beta_offset_div2 = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LF_TC_OFFSET_DIV2:
-               p->codec.hevc.lf_tc_offset_div2 = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_SIZE_OF_LENGTH_FIELD:
-               p->codec.hevc.size_of_length_field = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_USER_REF:
-               p->codec.hevc.user_ref = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_STORE_REF:
-               p->codec.hevc.store_ref = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_ROI_ENABLE:
-               p->roi_enable = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC_H264_VUI_RESTRICTION_ENABLE:
-               p->codec.h264.vui_enable = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HEVC_PREPEND_SPSPPS_TO_IDR:
-               p->codec.hevc.prepend_sps_pps_to_idr = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC_CONFIG_QP_ENABLE:
-               p->dynamic_qp = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC_CONFIG_QP:
-               p->config_qp = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_RC_PVC_ENABLE:
-               /* It is valid for H.264, HEVC, VP8, VP9 */
-               p->rc_pvc = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_TEMPORAL_SHORTTERM_MAX_LAYER:
-               p->num_hier_max_layer = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_MFC90_VIDEO_HEVC_SIGN_DATA_HIDING:
-               break;
-       case V4L2_CID_MPEG_VIDEO_WEIGHTED_ENABLE:
-               p->weighted_enable = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_BPG_THUMBNAIL_SIZE:
-               /* It should be included when NAL_START */
-               p->codec.bpg.thumb_size = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_BPG_EXIF_SIZE:
-               /* It should be included when NAL_START */
-               p->codec.bpg.exif_size = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_RATIO_OF_INTRA:
-               p->ratio_intra = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_FULL_RANGE_FLAG:
-               p->check_color_range = 1;
-               p->color_range = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_COLOUR_PRIMARIES:
-               p->colour_primaries = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_TRANSFER_CHARACTERISTICS:
-               p->transfer_characteristics = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_MATRIX_COEFFICIENTS:
-               p->matrix_coefficients = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_HIERARCHICAL_BITRATE_CTRL:
-               p->hier_bitrate_ctrl = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_STATIC_INFO_ENABLE:
-               p->static_info_enable = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_SEI_MAX_PIC_AVERAGE_LIGHT:
-               p->max_pic_average_light = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_SEI_MAX_CONTENT_LIGHT:
-               p->max_content_light = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_SEI_MAX_DISPLAY_LUMINANCE:
-               p->max_display_luminance = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_SEI_MIN_DISPLAY_LUMINANCE:
-               p->min_display_luminance = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_SEI_WHITE_POINT:
-               p->white_point = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_0:
-               p->display_primaries_0 = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_1:
-               p->display_primaries_1 = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_2:
-               p->display_primaries_2 = ctrl->value;
-               break;
-       default:
-               mfc_err_ctx("Invalid control: 0x%08x\n", ctrl->id);
-               ret = -EINVAL;
-       }
-
-       return ret;
-}
-
-static int mfc_enc_set_ctrl_val(struct s5p_mfc_ctx *ctx, struct v4l2_control *ctrl)
-{
-       struct s5p_mfc_enc *enc = ctx->enc_priv;
-       struct s5p_mfc_enc_params *p = &enc->params;
-       struct s5p_mfc_ctx_ctrl *ctx_ctrl;
-       int ret = 0;
-       int found = 0;
-       int index = 0;
-
-       mfc_debug(5, "[CTRLS] id: %#x, value: %d\n", ctrl->id, ctrl->value);
-
-       switch (ctrl->id) {
-       case V4L2_CID_CACHEABLE:
-               mfc_debug(5, "it is supported only V4L2_MEMORY_MMAP\n");
-               break;
-       case V4L2_CID_MPEG_VIDEO_QOS_RATIO:
-               ctx->qos_ratio = ctrl->value;
-               break;
-       case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:
-       case V4L2_CID_MPEG_VIDEO_H263_MAX_QP:
-       case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP:
-       case V4L2_CID_MPEG_VIDEO_VP8_MAX_QP:
-       case V4L2_CID_MPEG_VIDEO_VP9_MAX_QP:
-       case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP:
-       case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:
-       case V4L2_CID_MPEG_VIDEO_H263_MIN_QP:
-       case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP:
-       case V4L2_CID_MPEG_VIDEO_VP8_MIN_QP:
-       case V4L2_CID_MPEG_VIDEO_VP9_MIN_QP:
-       case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP:
-       case V4L2_CID_MPEG_VIDEO_H264_MAX_QP_P:
-       case V4L2_CID_MPEG_VIDEO_H263_MAX_QP_P:
-       case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_P:
-       case V4L2_CID_MPEG_VIDEO_VP8_MAX_QP_P:
-       case V4L2_CID_MPEG_VIDEO_VP9_MAX_QP_P:
-       case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_P:
-       case V4L2_CID_MPEG_VIDEO_H264_MIN_QP_P:
-       case V4L2_CID_MPEG_VIDEO_H263_MIN_QP_P:
-       case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_P:
-       case V4L2_CID_MPEG_VIDEO_VP8_MIN_QP_P:
-       case V4L2_CID_MPEG_VIDEO_VP9_MIN_QP_P:
-       case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_P:
-       case V4L2_CID_MPEG_VIDEO_H264_MAX_QP_B:
-       case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_B:
-       case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_B:
-       case V4L2_CID_MPEG_VIDEO_H264_MIN_QP_B:
-       case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_B:
-       case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_B:
-       case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG:
-       case V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE:
-       case V4L2_CID_MPEG_MFC51_VIDEO_I_PERIOD_CH:
-       case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_RATE_CH:
-       case V4L2_CID_MPEG_MFC51_VIDEO_BIT_RATE_CH:
-       case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_CH:
-       case V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_CH:
-       case V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_CH:
-       case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_CH:
-       case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
-       case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
-       case V4L2_CID_MPEG_MFC_H264_MARK_LTR:
-       case V4L2_CID_MPEG_MFC_H264_USE_LTR:
-       case V4L2_CID_MPEG_MFC_H264_BASE_PRIORITY:
-       case V4L2_CID_MPEG_MFC_CONFIG_QP:
-       case V4L2_CID_MPEG_VIDEO_ROI_CONTROL:
-       case V4L2_CID_MPEG_VIDEO_YSUM:
-       case V4L2_CID_MPEG_VIDEO_RATIO_OF_INTRA:
-               list_for_each_entry(ctx_ctrl, &ctx->ctrls, list) {
-                       if (!(ctx_ctrl->type & MFC_CTRL_TYPE_SET))
-                               continue;
-
-                       if (ctx_ctrl->id == ctrl->id) {
-                               ctx_ctrl->has_new = 1;
-                               ctx_ctrl->val = ctrl->value;
-                               if (ctx_ctrl->id == \
-                                       V4L2_CID_MPEG_MFC51_VIDEO_FRAME_RATE_CH) {
-                                       ctx_ctrl->val &= ~(0xFFFF << 16);
-                                       ctx_ctrl->val |= ctx_ctrl->val << 16;
-                                       ctx_ctrl->val &= ~(0xFFFF);
-                                       ctx_ctrl->val |= p->rc_frame_delta & 0xFFFF;
-                               }
-                               if (((ctx_ctrl->id == \
-                                       V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_CH) ||
-                                       (ctx_ctrl->id == \
-                                       V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_CH) ||
-                                       (ctx_ctrl->id == \
-                                       V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_CH) ||
-                                       (ctx_ctrl->id == \
-                                       V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_CH)) &&
-                                       (enc->sh_handle_svc.fd == -1)) {
-                                               enc->sh_handle_svc.fd = ctrl->value;
-                                               if (s5p_mfc_mem_get_user_shared_handle(ctx,
-                                                                       &enc->sh_handle_svc))
-                                                       return -EINVAL;
-                                               else
-                                                       mfc_debug(2, "[MEMINFO][HIERARCHICAL] shared handle fd: %d, vaddr: 0x%p\n",
-                                                                       enc->sh_handle_svc.fd,
-                                                                       enc->sh_handle_svc.vaddr);
-                               }
-                               if (ctx_ctrl->id == V4L2_CID_MPEG_MFC51_VIDEO_I_PERIOD_CH &&
-                                               p->i_frm_ctrl_mode) {
-                                       ctx_ctrl->val = ctx_ctrl->val * (p->num_b_frame + 1);
-                                       if (ctx_ctrl->val >= 0x3FFFFFFF) {
-                                               mfc_info_ctx("I frame interval is bigger than max: %d\n",
-                                                               ctx_ctrl->val);
-                                               ctx_ctrl->val = 0x3FFFFFFF;
-                                       }
-                               }
-                               if (ctx_ctrl->id == V4L2_CID_MPEG_VIDEO_H264_LEVEL)
-                                       ctx_ctrl->val = mfc_enc_h264_level((enum v4l2_mpeg_video_h264_level)(ctrl->value));
-                               if (ctx_ctrl->id == V4L2_CID_MPEG_VIDEO_H264_PROFILE)
-                                       ctx_ctrl->val = mfc_enc_h264_profile(ctx, (enum v4l2_mpeg_video_h264_profile)(ctrl->value));
-                               if (ctx_ctrl->id == V4L2_CID_MPEG_VIDEO_ROI_CONTROL) {
-                                       if (enc->sh_handle_roi.fd == -1) {
-                                               enc->sh_handle_roi.fd = ctrl->value;
-                                               if (s5p_mfc_mem_get_user_shared_handle(ctx,
-                                                                       &enc->sh_handle_roi))
-                                                       return -EINVAL;
-                                               else
-                                                       mfc_debug(2, "[MEMINFO][ROI] shared handle fd: %d, vaddr: 0x%p\n",
-                                                                       enc->sh_handle_roi.fd,
-                                                                       enc->sh_handle_roi.vaddr);
-                                       }
-                                       index = enc->roi_index;
-                                       memcpy(&enc->roi_info[index],
-                                                       enc->sh_handle_roi.vaddr,
-                                                       sizeof(struct mfc_enc_roi_info));
-                                       if (copy_from_user(enc->roi_buf[index].vaddr,
-                                                       enc->roi_info[index].addr,
-                                                       enc->roi_info[index].size))
-                                               return -EFAULT;
-                               }
-
-                               found = 1;
-                               break;
-                       }
-               }
-
-               if (!found) {
-                       mfc_err_ctx("Invalid control: 0x%08x\n", ctrl->id);
-                       return -EINVAL;
-               }
-               break;
-       default:
-               ret = mfc_enc_set_param(ctx, ctrl);
-               break;
-       }
-
-       return ret;
-}
-
-static int vidioc_s_ctrl(struct file *file, void *priv,
-                        struct v4l2_control *ctrl)
-{
-       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
-       int ret = 0;
-
-       mfc_debug_enter();
-
-       ret = mfc_enc_check_ctrl_val(ctx, ctrl);
-       if (ret != 0)
-               return ret;
-
-       ret = mfc_enc_set_ctrl_val(ctx, ctrl);
-
-       mfc_debug_leave();
-
-       return ret;
-}
-
-static int vidioc_g_ext_ctrls(struct file *file, void *priv,
-                             struct v4l2_ext_controls *f)
-{
-       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
-       struct v4l2_ext_control *ext_ctrl;
-       struct v4l2_control ctrl;
-       int i;
-       int ret = 0;
-
-       if (f->which != V4L2_CTRL_CLASS_MPEG)
-               return -EINVAL;
-
-       for (i = 0; i < f->count; i++) {
-               ext_ctrl = (f->controls + i);
-
-               ctrl.id = ext_ctrl->id;
-
-               ret = mfc_enc_get_ctrl_val(ctx, &ctrl);
-               if (ret == 0) {
-                       ext_ctrl->value = ctrl.value;
-               } else {
-                       f->error_idx = i;
-                       break;
-               }
-
-               mfc_debug(5, "[CTRLS][%d] id: %#x, value: %d\n",
-                               i, ext_ctrl->id, ext_ctrl->value);
-       }
-
-       return ret;
-}
-
-static int vidioc_s_ext_ctrls(struct file *file, void *priv,
-                               struct v4l2_ext_controls *f)
-{
-       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
-       struct v4l2_ext_control *ext_ctrl;
-       struct v4l2_control ctrl;
-       int i;
-       int ret = 0;
-
-       if (f->which != V4L2_CTRL_CLASS_MPEG)
-               return -EINVAL;
-
-       for (i = 0; i < f->count; i++) {
-               ext_ctrl = (f->controls + i);
-
-               ctrl.id = ext_ctrl->id;
-               ctrl.value = ext_ctrl->value;
-
-               ret = mfc_enc_check_ctrl_val(ctx, &ctrl);
-               if (ret != 0) {
-                       f->error_idx = i;
-                       break;
-               }
-
-               ret = mfc_enc_set_param(ctx, &ctrl);
-               if (ret != 0) {
-                       f->error_idx = i;
-                       break;
-               }
-
-               mfc_debug(5, "[CTRLS][%d] id: %#x, value: %d\n",
-                               i, ext_ctrl->id, ext_ctrl->value);
-       }
-
-       return ret;
-}
-
-static int vidioc_try_ext_ctrls(struct file *file, void *priv,
-                               struct v4l2_ext_controls *f)
-{
-       struct s5p_mfc_ctx *ctx = fh_to_mfc_ctx(file->private_data);
-       struct v4l2_ext_control *ext_ctrl;
-       struct v4l2_control ctrl;
-       int i;
-       int ret = 0;
-
-       if (f->which != V4L2_CTRL_CLASS_MPEG)
-               return -EINVAL;
-
-       for (i = 0; i < f->count; i++) {
-               ext_ctrl = (f->controls + i);
-
-               ctrl.id = ext_ctrl->id;
-               ctrl.value = ext_ctrl->value;
-
-               ret = mfc_enc_check_ctrl_val(ctx, &ctrl);
-               if (ret != 0) {
-                       f->error_idx = i;
-                       break;
-               }
-
-               mfc_debug(2, "[%d] id: 0x%08x, value: %d\n", i, ext_ctrl->id, ext_ctrl->value);
-       }
-
-       return ret;
-}
-
-static const struct v4l2_ioctl_ops s5p_mfc_enc_ioctl_ops = {
-       .vidioc_querycap                = vidioc_querycap,
-       .vidioc_enum_fmt_vid_cap_mplane = vidioc_enum_fmt_vid_cap_mplane,
-       .vidioc_enum_fmt_vid_out_mplane = vidioc_enum_fmt_vid_out_mplane,
-       .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_vid_cap_mplane,
-       .vidioc_s_fmt_vid_out_mplane    = vidioc_s_fmt_vid_out_mplane,
-       .vidioc_g_crop                  = vidioc_g_crop,
-       .vidioc_s_crop                  = vidioc_s_crop,
-       .vidioc_reqbufs                 = vidioc_reqbufs,
-       .vidioc_querybuf                = vidioc_querybuf,
-       .vidioc_qbuf                    = vidioc_qbuf,
-       .vidioc_dqbuf                   = vidioc_dqbuf,
-       .vidioc_streamon                = vidioc_streamon,
-       .vidioc_streamoff               = vidioc_streamoff,
-       .vidioc_queryctrl               = vidioc_queryctrl,
-       .vidioc_g_ctrl                  = vidioc_g_ctrl,
-       .vidioc_s_ctrl                  = vidioc_s_ctrl,
-       .vidioc_g_ext_ctrls             = vidioc_g_ext_ctrls,
-       .vidioc_s_ext_ctrls             = vidioc_s_ext_ctrls,
-       .vidioc_try_ext_ctrls           = vidioc_try_ext_ctrls,
-};
-
-const struct v4l2_ioctl_ops *s5p_mfc_get_enc_v4l2_ioctl_ops(void)
-{
-       return &s5p_mfc_enc_ioctl_ops;
-}
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_enc.h b/drivers/media/platform/exynos/mfc/s5p_mfc_enc.h
deleted file mode 100644 (file)
index 4cfbc2a..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_enc.h
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __S5P_MFC_ENC_H
-#define __S5P_MFC_ENC_H __FILE__
-
-#include "s5p_mfc_common.h"
-
-const struct v4l2_ioctl_ops *s5p_mfc_get_enc_v4l2_ioctl_ops(void);
-
-#endif /* __S5P_MFC_ENC_H */
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_enc_internal.h b/drivers/media/platform/exynos/mfc/s5p_mfc_enc_internal.h
deleted file mode 100644 (file)
index 80fbc0e..0000000
+++ /dev/null
@@ -1,2354 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_enc_internal.h
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __S5P_MFC_ENC_INTERNAL_H
-#define __S5P_MFC_ENC_INTERNAL_H __FILE__
-
-#include "s5p_mfc_common.h"
-
-/*
- * RGB encoding information to avoid confusion.
- *
- * V4L2_PIX_FMT_ARGB32 takes ARGB data like below.
- * MSB                              LSB
- * 3       2       1
- * 2       4       6       8       0
- * |B......BG......GR......RA......A|
- */
-struct s5p_mfc_fmt enc_formats[] = {
-       {
-               .name = "4:2:0 3 Planes Y/Cb/Cr",
-               .fourcc = V4L2_PIX_FMT_YUV420M,
-               .codec_mode = MFC_FORMATS_NO_CODEC,
-               .type = MFC_FMT_FRAME,
-               .num_planes = 3,
-               .mem_planes = 3,
-       },
-       {
-               .name = "4:2:0 3 Planes Y/Cb/Cr single",
-               .fourcc = V4L2_PIX_FMT_YUV420N,
-               .codec_mode = MFC_FORMATS_NO_CODEC,
-               .type = MFC_FMT_FRAME,
-               .num_planes = 3,
-               .mem_planes = 1,
-       },
-       {
-               .name = "4:2:0 3 Planes Y/Cr/Cb",
-               .fourcc = V4L2_PIX_FMT_YVU420M,
-               .codec_mode = MFC_FORMATS_NO_CODEC,
-               .type = MFC_FMT_FRAME,
-               .num_planes = 3,
-               .mem_planes = 3,
-       },
-       {
-               .name = "4:2:0 2 Planes",
-               .fourcc = V4L2_PIX_FMT_NV12M,
-               .codec_mode = MFC_FORMATS_NO_CODEC,
-               .type = MFC_FMT_FRAME,
-               .num_planes = 2,
-               .mem_planes = 2,
-       },
-       {
-               .name = "4:2:0 2 Planes Y/CbCr single",
-               .fourcc = V4L2_PIX_FMT_NV12N,
-               .codec_mode = MFC_FORMATS_NO_CODEC,
-               .type = MFC_FMT_FRAME,
-               .num_planes = 2,
-               .mem_planes = 1,
-       },
-       {
-               .name = "4:2:0 2 Planes Y/CbCr 8+2 10bit",
-               .fourcc = V4L2_PIX_FMT_NV12M_S10B,
-               .codec_mode = MFC_FORMATS_NO_CODEC,
-               .type = MFC_FMT_FRAME | MFC_FMT_10BIT,
-               .num_planes = 2,
-               .mem_planes = 2,
-       },
-       {
-               .name = "4:2:0 2 Planes Y/CbCr P010 10bit",
-               .fourcc = V4L2_PIX_FMT_NV12M_P010,
-               .codec_mode = MFC_FORMATS_NO_CODEC,
-               .type = MFC_FMT_FRAME | MFC_FMT_10BIT,
-               .num_planes = 2,
-               .mem_planes = 2,
-       },
-       {
-               .name = "4:2:0 2 Planes Y/CrCb",
-               .fourcc = V4L2_PIX_FMT_NV21M,
-               .codec_mode = MFC_FORMATS_NO_CODEC,
-               .type = MFC_FMT_FRAME,
-               .num_planes = 2,
-               .mem_planes = 2,
-       },
-       {
-               .name = "4:2:0 2 Planes Y/CrCb 8+2 10bit",
-               .fourcc = V4L2_PIX_FMT_NV21M_S10B,
-               .codec_mode = MFC_FORMATS_NO_CODEC,
-               .type = MFC_FMT_FRAME | MFC_FMT_10BIT,
-               .num_planes = 2,
-               .mem_planes = 2,
-       },
-       {
-               .name = "4:2:0 2 Planes Y/CrCb P010 10bit",
-               .fourcc = V4L2_PIX_FMT_NV21M_P010,
-               .codec_mode = MFC_FORMATS_NO_CODEC,
-               .type = MFC_FMT_FRAME | MFC_FMT_10BIT,
-               .num_planes = 2,
-               .mem_planes = 2,
-       },
-       {
-               .name = "4:2:2 2 Planes Y/CbCr",
-               .fourcc = V4L2_PIX_FMT_NV16M,
-               .codec_mode = MFC_FORMATS_NO_CODEC,
-               .type = MFC_FMT_FRAME | MFC_FMT_422,
-               .num_planes = 2,
-               .mem_planes = 2,
-       },
-       {
-               .name = "4:2:2 2 Planes Y/CbCr 8+2 10bit",
-               .fourcc = V4L2_PIX_FMT_NV16M_S10B,
-               .codec_mode = MFC_FORMATS_NO_CODEC,
-               .type = MFC_FMT_FRAME | MFC_FMT_10BIT | MFC_FMT_422,
-               .num_planes = 2,
-               .mem_planes = 2,
-       },
-       {
-               .name = "4:2:2 2 Planes Y/CrCb 8+2 10bit",
-               .fourcc = V4L2_PIX_FMT_NV61M_S10B,
-               .codec_mode = MFC_FORMATS_NO_CODEC,
-               .type = MFC_FMT_FRAME | MFC_FMT_10BIT | MFC_FMT_422,
-               .num_planes = 2,
-               .mem_planes = 2,
-       },
-       {
-               .name = "4:2:2 2 Planes Y/CbCr P210 10bit",
-               .fourcc = V4L2_PIX_FMT_NV16M_P210,
-               .codec_mode = MFC_FORMATS_NO_CODEC,
-               .type = MFC_FMT_FRAME | MFC_FMT_10BIT | MFC_FMT_422,
-               .num_planes = 2,
-               .mem_planes = 2,
-       },
-       {
-               .name = "4:2:2 2 Planes Y/CrCb P210 10bit",
-               .fourcc = V4L2_PIX_FMT_NV61M_P210,
-               .codec_mode = MFC_FORMATS_NO_CODEC,
-               .type = MFC_FMT_FRAME | MFC_FMT_10BIT | MFC_FMT_422,
-               .num_planes = 2,
-               .mem_planes = 2,
-       },
-       {
-               .name = "4:2:2 2 Planes Y/CrCb",
-               .fourcc = V4L2_PIX_FMT_NV61M,
-               .codec_mode = MFC_FORMATS_NO_CODEC,
-               .type = MFC_FMT_FRAME | MFC_FMT_422,
-               .num_planes = 2,
-               .mem_planes = 2,
-       },
-       {
-               .name = "RGB888 1 Plane 24bpp",
-               .fourcc = V4L2_PIX_FMT_RGB24,
-               .codec_mode = MFC_FORMATS_NO_CODEC,
-               .type = MFC_FMT_FRAME | MFC_FMT_RGB,
-               .num_planes = 1,
-               .mem_planes = 1,
-       },
-       {
-               .name = "RGB565 1 Plane 16bpp",
-               .fourcc = V4L2_PIX_FMT_RGB565,
-               .codec_mode = MFC_FORMATS_NO_CODEC,
-               .type = MFC_FMT_FRAME | MFC_FMT_RGB,
-               .num_planes = 1,
-               .mem_planes = 1,
-       },
-       {
-               .name = "RGBX8888 1 Plane 32bpp",
-               .fourcc = V4L2_PIX_FMT_RGB32X,
-               .codec_mode = MFC_FORMATS_NO_CODEC,
-               .type = MFC_FMT_FRAME | MFC_FMT_RGB,
-               .num_planes = 1,
-               .mem_planes = 1,
-       },
-       {
-               .name = "BGRA8888 1 Plane 32bpp",
-               .fourcc = V4L2_PIX_FMT_BGR32,
-               .codec_mode = MFC_FORMATS_NO_CODEC,
-               .type = MFC_FMT_FRAME | MFC_FMT_RGB,
-               .num_planes = 1,
-               .mem_planes = 1,
-       },
-       {
-               .name = "ARGB8888 1 Plane 32bpp",
-               .fourcc = V4L2_PIX_FMT_ARGB32,
-               .codec_mode = MFC_FORMATS_NO_CODEC,
-               .type = MFC_FMT_FRAME | MFC_FMT_RGB,
-               .num_planes = 1,
-               .mem_planes = 1,
-       },
-       {
-               .name = "H264 Encoded Stream",
-               .fourcc = V4L2_PIX_FMT_H264,
-               .codec_mode = S5P_FIMV_CODEC_H264_ENC,
-               .type = MFC_FMT_STREAM,
-               .num_planes = 1,
-               .mem_planes = 1,
-       },
-       {
-               .name = "MPEG4 Encoded Stream",
-               .fourcc = V4L2_PIX_FMT_MPEG4,
-               .codec_mode = S5P_FIMV_CODEC_MPEG4_ENC,
-               .type = MFC_FMT_STREAM,
-               .num_planes = 1,
-               .mem_planes = 1,
-       },
-       {
-               .name = "H263 Encoded Stream",
-               .fourcc = V4L2_PIX_FMT_H263,
-               .codec_mode = S5P_FIMV_CODEC_H263_ENC,
-               .type = MFC_FMT_STREAM,
-               .num_planes = 1,
-               .mem_planes = 1,
-       },
-       {
-               .name = "VP8 Encoded Stream",
-               .fourcc = V4L2_PIX_FMT_VP8,
-               .codec_mode = S5P_FIMV_CODEC_VP8_ENC,
-               .type = MFC_FMT_STREAM,
-               .num_planes = 1,
-               .mem_planes = 1,
-       },
-       {
-               .name = "VP9 Encoded Stream",
-               .fourcc = V4L2_PIX_FMT_VP9,
-               .codec_mode = S5P_FIMV_CODEC_VP9_ENC,
-               .type = MFC_FMT_STREAM,
-               .num_planes = 1,
-               .mem_planes = 1,
-       },
-       {
-               .name = "HEVC Encoded Stream",
-               .fourcc = V4L2_PIX_FMT_HEVC,
-               .codec_mode = S5P_FIMV_CODEC_HEVC_ENC,
-               .type = MFC_FMT_STREAM,
-               .num_planes = 1,
-               .mem_planes = 1,
-       },
-       {
-               .name = "BPG Encoded Stream",
-               .fourcc = V4L2_PIX_FMT_BPG,
-               .codec_mode = S5P_FIMV_CODEC_BPG_ENC,
-               .type = MFC_FMT_STREAM,
-               .num_planes = 1,
-               .mem_planes = 1,
-       },
-};
-
-#define NUM_FORMATS ARRAY_SIZE(enc_formats)
-
-static struct v4l2_queryctrl controls[] = {
-       {
-               .id = V4L2_CID_CACHEABLE,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Cacheable flag",
-               .minimum = 0,
-               .maximum = 3,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_GOP_SIZE,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "The period of intra frame",
-               .minimum = 0,
-               .maximum = (1 << 30) - 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "The slice partitioning method",
-               .minimum = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE,
-               .maximum = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_FIXED_BYTES,
-               .step = 1,
-               .default_value = V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "The number of MB in a slice",
-               .minimum = 1,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 1,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "The maximum bits per slices",
-               .minimum = 350,
-               .maximum = INT_MAX / 8,
-               .step = 1,
-               .default_value = 350,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB_ROW,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "The number of MB row in a slice",
-               .minimum = 1,
-               .maximum = INT_MAX / 256,
-               .step = 1,
-               .default_value = 1,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "The number of intra refresh MBs",
-               .minimum = 0,
-               .maximum = (1 << 18) - 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 << 24) - 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "Frame level rate control enable",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_BITRATE,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Target bit rate rate-control",
-               .minimum = 1,
-               .maximum = INT_MAX,
-               .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_STREAM_SIZE,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Encoded stream size",
-               .minimum = 0,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-               .flags = V4L2_CTRL_FLAG_READ_ONLY,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_COUNT,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Encoded frame count",
-               .minimum = 0,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-               .flags = V4L2_CTRL_FLAG_READ_ONLY,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TYPE,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Encoded frame type",
-               .minimum = 0,
-               .maximum = 5,
-               .step = 1,
-               .default_value = 0,
-               .flags = V4L2_CTRL_FLAG_READ_ONLY,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Force frame type",
-               .minimum = V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_DISABLED,
-               .maximum = V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_NOT_CODED,
-               .step = 1,
-               .default_value = \
-                       V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_DISABLED,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_VBV_SIZE,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "VBV buffer size (1Kbits)",
-               .minimum = 0,
-               .maximum = (1 << 16) - 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEADER_MODE,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Sequence header mode",
-               .minimum = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE,
-               .maximum = V4L2_MPEG_VIDEO_HEADER_MODE_AT_THE_READY,
-               .step = 1,
-               .default_value = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Frame skip enable",
-               .minimum = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_DISABLED,
-               .maximum = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT,
-               .step = 1,
-               .default_value = V4L2_MPEG_MFC51_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,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_B_FRAMES,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "The number of B frames",
-               .minimum = 0,
-               .maximum = 2,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_PROFILE,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "H264 profile",
-               .minimum = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE,
-               .maximum = V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH,
-               .step = 1,
-               .default_value = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_LEVEL,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "H264 level",
-               .minimum = V4L2_MPEG_VIDEO_H264_LEVEL_1_0,
-               .maximum = V4L2_MPEG_VIDEO_H264_LEVEL_5_1,
-               .step = 1,
-               .default_value = V4L2_MPEG_VIDEO_H264_LEVEL_1_0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_H264_INTERLACE,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "H264 interlace mode",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "H264 loop filter mode",
-               .minimum = V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED,
-               .maximum = V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_S_B,
-               .step = 1,
-               .default_value = V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "H264 loop filter alpha offset",
-               .minimum = -12,
-               .maximum = 12,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "H264 loop filter beta offset",
-               .minimum = -12,
-               .maximum = 12,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "H264 entorpy mode",
-               .minimum = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC,
-               .maximum = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC,
-               .step = 1,
-               .default_value = V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_H264_NUM_REF_PIC_FOR_P,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "The number of ref. picture of P",
-               .minimum = 1,
-               .maximum = 2,
-               .step = 1,
-               .default_value = 1,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "H264 8x8 transform enable",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "MB level rate control",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_H264_RC_FRAME_RATE,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "H264 Frame rate",
-               .minimum = 1,
-               .maximum = (1 << 16) - 1,
-               .step = 1,
-               .default_value = 1,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "H264 Frame QP value",
-               .minimum = 0,
-               .maximum = 51,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_DARK,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "H264 dark region adaptive",
-               .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 region adaptive",
-               .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 region adaptive",
-               .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 MB activity adaptive",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "H264 P frame QP value",
-               .minimum = 0,
-               .maximum = 51,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "H264 B frame QP value",
-               .minimum = 0,
-               .maximum = 51,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "Aspect ratio VUI enable",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "VUI aspect ratio IDC",
-               .minimum = V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_UNSPECIFIED,
-               .maximum = V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_EXTENDED,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Horizontal size of SAR",
-               .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,
-               .name = "Vertical size of SAR",
-               .minimum = 0,
-               .maximum = (1 << 16) - 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_GOP_CLOSURE,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "GOP closure",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 1,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_I_PERIOD,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "H264 I period",
-               .minimum = 0,
-               .maximum = (1 << 16) - 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "Hierarchical Coding",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Hierarchical Coding Type",
-               .minimum = V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_B,
-               .maximum = V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_P,
-               .step = 1,
-               .default_value = V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_P,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Hierarchical Coding Layer",
-               .minimum = 0,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Hierarchical Coding Layer QP",
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "frame pack sei generation flag",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_SEI_FP_CURRENT_FRAME_0,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "Current frame is frame 0 flag",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Frame packing arrangement type",
-               .minimum = V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_SIDE_BY_SIDE,
-               .maximum = V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_TEMPORAL,
-               .step = 1,
-               .default_value = V4L2_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE_SIDE_BY_SIDE,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_FMO,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "Flexible Macroblock Order",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_FMO_MAP_TYPE,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Map type for FMO",
-               .minimum = V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_INTERLEAVED_SLICES,
-               .maximum = V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_WIPE_SCAN,
-               .step = 1,
-               .default_value = \
-                       V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_INTERLEAVED_SLICES,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_FMO_SLICE_GROUP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Number of slice groups for FMO",
-               .minimum = 1,
-               .maximum = 4,
-               .step = 1,
-               .default_value = 1,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_FMO_RUN_LENGTH,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "FMO Run Length",
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_DIRECTION,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Direction of the slice group",
-               .minimum = V4L2_MPEG_VIDEO_H264_FMO_CHANGE_DIR_RIGHT,
-               .maximum = V4L2_MPEG_VIDEO_H264_FMO_CHANGE_DIR_LEFT,
-               .step = 1,
-               .default_value = V4L2_MPEG_VIDEO_H264_FMO_CHANGE_DIR_RIGHT,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_RATE,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Size of the first slice group",
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_ASO,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "Arbitrary Slice Order",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_ASO_SLICE_ORDER,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "ASO Slice order",
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_PREPEND_SPSPPS_TO_IDR,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Prepend SPS/PPS to every IDR",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "MPEG4 profile",
-               .minimum = V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE,
-               .maximum = V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE,
-               .step = 1,
-               .default_value = V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "MPEG4 level",
-               .minimum = V4L2_MPEG_VIDEO_MPEG4_LEVEL_0,
-               .maximum = V4L2_MPEG_VIDEO_MPEG4_LEVEL_6,
-               .step = 1,
-               .default_value = V4L2_MPEG_VIDEO_MPEG4_LEVEL_0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "MPEG4 Frame QP value",
-               .minimum = 1,
-               .maximum = 31,
-               .step = 1,
-               .default_value = 1,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_MPEG4_QPEL,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "Quarter pixel search enable",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .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_MPEG4_VOP_TIME_RES,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "MPEG4 vop time resolution",
-               .minimum = 0,
-               .maximum = (1 << 16) - 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_MPEG4_VOP_FRM_DELTA,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "MPEG4 frame delta",
-               .minimum = 1,
-               .maximum = (1 << 16) - 1,
-               .step = 1,
-               .default_value = 1,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_H263_RC_FRAME_RATE,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "H263 Frame rate",
-               .minimum = 1,
-               .maximum = (1 << 8) - 1,
-               .step = 1,
-               .default_value = 1,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "H263 Frame QP value",
-               .minimum = 1,
-               .maximum = 31,
-               .step = 1,
-               .default_value = 1,
-       },
-       {
-               .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_MFC51_VIDEO_FRAME_TAG,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Frame Tag",
-               .minimum = 0,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_STATUS,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Frame Status",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_QOS_RATIO,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "QoS ratio value",
-               .minimum = 20,
-               .maximum = 1000,
-               .step = 10,
-               .default_value = 100,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC70_VIDEO_VP8_VERSION,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "VP8 version",
-               .minimum = 0,
-               .maximum = 3,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_VP8_I_FRAME_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "VP8 Frame QP value",
-               .minimum = 0,
-               .maximum = 127,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_VP8_P_FRAME_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "VP8 Frame QP value",
-               .minimum = 0,
-               .maximum = 127,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC70_VIDEO_VP8_RC_FRAME_RATE,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "VP8 Frame rate",
-               .minimum = 1,
-               .maximum = (1 << 16) - 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC70_VIDEO_VP8_NUM_OF_PARTITIONS,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "VP8 number of partitions",
-               .minimum = 0,
-               .maximum = 8,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC70_VIDEO_VP8_FILTER_LEVEL,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "VP8 loop filter level",
-               .minimum = 0,
-               .maximum = 63,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC70_VIDEO_VP8_FILTER_SHARPNESS,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "VP8 loop filter sharpness",
-               .minimum = 0,
-               .maximum = 7,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC70_VIDEO_VP8_GOLDEN_FRAMESEL,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "VP8 indication of golden frame",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC70_VIDEO_VP8_GF_REFRESH_PERIOD,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "VP8 indication of golden frame",
-               .minimum = 0,
-               .maximum = (1 << 16) - 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC70_VIDEO_VP8_HIERARCHY_QP_ENABLE,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "VP8 hierarchy QP enable",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC70_VIDEO_VP8_HIERARCHY_QP_LAYER0,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "VP8 layer0 QP value",
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC70_VIDEO_VP8_HIERARCHY_QP_LAYER1,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "VP8 layer1 QP value",
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC70_VIDEO_VP8_HIERARCHY_QP_LAYER2,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "VP8 layer2 QP value",
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC70_VIDEO_VP8_REF_NUMBER_FOR_PFRAMES,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "VP8 Number of reference picture",
-               .minimum = 1,
-               .maximum = 2,
-               .step = 1,
-               .default_value = 1,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC70_VIDEO_VP8_DISABLE_INTRA_MD4X4,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "VP8 intra 4x4 mode disable",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC70_VIDEO_VP8_NUM_TEMPORAL_LAYER,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "VP8 number of hierarchical layer",
-               .minimum = 0,
-               .maximum = 3,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_VP9_VERSION,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "VP9 version",
-               .minimum = 0,
-               .maximum = 3,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_VP9_I_FRAME_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "VP9 Frame QP value",
-               .minimum = 1,
-               .maximum = 255,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_VP9_P_FRAME_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "VP9 Frame QP value",
-               .minimum = 1,
-               .maximum = 255,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_VP9_RC_FRAME_RATE,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "VP9 Frame rate",
-               .minimum = 1,
-               .maximum = (1 << 16) - 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_VP9_GOLDEN_FRAMESEL,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "VP9 indication of golden frame",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_VP9_GF_REFRESH_PERIOD,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "VP9 indication of golden frame",
-               .minimum = 0,
-               .maximum = ((1 << 16) - 1),
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_VP9_HIERARCHY_QP_ENABLE,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "VP9 hierarchy QP enable",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "VP9 layer0 QP value",
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_VP9_REF_NUMBER_FOR_PFRAMES,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "VP9 Number of reference picture",
-               .minimum = 1,
-               .maximum = 2,
-               .step = 1,
-               .default_value = 1,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "VP9 number of hierarchical layer",
-               .minimum = 0,
-               .maximum = 3,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_VP9_MAX_PARTITION_DEPTH,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "VP9 Maximum coding unit depth",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_VP9_DISABLE_INTRA_PU_SPLIT,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "VP9 disable intra pu split",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_BIT0,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Hierarchical Coding Layer Bit0",
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_BIT1,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Hierarchical Coding Layer Bit1",
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_BIT2,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Hierarchical Coding Layer Bit2",
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_CH,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Hierarchical Coding Layer Change",
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_DISABLE_IVF_HEADER,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "IVF header generation",
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "HEVC Frame QP value",
-               .minimum = -12,
-               .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 = -12,
-               .maximum = 51,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "HEVC B frame QP value",
-               .minimum = -12,
-               .maximum = 51,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_ADAPTIVE_RC_DARK,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "HEVC dark region adaptive",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_ADAPTIVE_RC_SMOOTH,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "HEVC smooth region adaptive",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_ADAPTIVE_RC_STATIC,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "HEVC static region adaptive",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_ADAPTIVE_RC_ACTIVITY,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "HEVC activity adaptive",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_PROFILE,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "HEVC Profile",
-               .minimum = 0,
-               .maximum = 4,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_LEVEL,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "HEVC level",
-               .minimum = 10,
-               .maximum = 62,
-               .step = 1,
-               .default_value = 10,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_TIER_FLAG,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "HEVC tier_flag default is Main",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_RC_FRAME_RATE,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "HEVC Frame rate",
-               .minimum = 1,
-               .maximum = (1 << 16) - 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_MAX_PARTITION_DEPTH,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "HEVC Maximum coding unit depth",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0, /* need to check defualt value */
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_REF_NUMBER_FOR_PFRAMES,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "HEVC Number of reference picture",
-               .minimum = 1,
-               .maximum = 2,
-               .step = 1,
-               .default_value = 1,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_REFRESH_TYPE,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "HEVC Number of reference picture",
-               .minimum = 0,
-               .maximum = 2,
-               .step = 1,
-               .default_value = 0, /* need to check defualt value */
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_CONST_INTRA_PRED_ENABLE,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "HEVC refresh type",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0, /* need to check defualt value */
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LOSSLESS_CU_ENABLE,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "HEVC lossless encoding select",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0, /* need to check defualt value */
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_WAVEFRONT_ENABLE,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "HEVC Wavefront enable",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0, /* need to check defualt value */
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LF_DISABLE,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "HEVC Filter disable",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0, /* need to check defualt value */
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LF_SLICE_BOUNDARY,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "across or not slice boundary",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0, /* need to check defualt value */
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LTR_ENABLE,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "long term reference enable",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0, /* need to check defualt value */
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_QP_ENABLE,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "QP values for temporal layer",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0, /* need to check defualt value */
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_TYPE,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "Hierarchical Coding Type",
-               .minimum = V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B,
-               .maximum = V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P,
-               .step = 1,
-               .default_value = 0, /* need to check defualt value */
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Hierarchical Coding Layer",
-               .minimum = 0,
-               .maximum = 7,
-               .step = 1,
-               .default_value = 0, /* need to check defualt value */
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Hierarchical Coding Layer QP",
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0, /* need to check defualt value */
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT0,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Hierarchical Coding Layer BIT0",
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT1,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Hierarchical Coding Layer BIT1",
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT2,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Hierarchical Coding Layer BIT2",
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT3,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Hierarchical Coding Layer BIT3",
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT4,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Hierarchical Coding Layer BIT4",
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT5,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Hierarchical Coding Layer BIT5",
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT6,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Hierarchical Coding Layer BIT6",
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_CH,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Hierarchical Coding Layer Change",
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_SIGN_DATA_HIDING,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "HEVC Sign data hiding",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0, /* need to check defualt value */
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_GENERAL_PB_ENABLE,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "HEVC General pb enable",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0, /* need to check defualt value */
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_TEMPORAL_ID_ENABLE,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "HEVC Temporal id enable",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0, /* need to check defualt value */
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_STRONG_SMOTHING_FLAG,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "HEVC Strong intra smoothing flag",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0, /* need to check defualt value */
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_DISABLE_INTRA_PU_SPLIT,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "HEVC disable intra pu split",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0, /* need to check defualt value */
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_DISABLE_TMV_PREDICTION,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "HEVC disable tmv prediction",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0, /* need to check defualt value */
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_MAX_NUM_MERGE_MV_MINUS1,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "max number of candidate MVs",
-               .minimum = 0,
-               .maximum = 4,
-               .step = 1,
-               .default_value = 0, /* need to check defualt value */
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_WITHOUT_STARTCODE_ENABLE,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "ENC without startcode enable",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0, /* need to check defualt value */
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_REFRESH_PERIOD,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "HEVC Number of reference picture",
-               .minimum = 0,
-               .maximum = (1 << 16) - 1,
-               .step = 1,
-               .default_value = 0, /* need to check defualt value */
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LF_BETA_OFFSET_DIV2,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "HEVC loop filter beta offset",
-               .minimum = -6,
-               .maximum = 6,
-               .step = 1,
-               .default_value = 0, /* need to check defualt value */
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LF_TC_OFFSET_DIV2,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "HEVC loop filter tc offset",
-               .minimum = -6,
-               .maximum = 6,
-               .step = 1,
-               .default_value = 0, /* need to check defualt value */
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_SIZE_OF_LENGTH_FIELD,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "HEVC size of length field",
-               .minimum = 0,
-               .maximum = 3,
-               .step = 1,
-               .default_value = 0, /* need to check defualt value */
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_USER_REF,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "user long term reference frame",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0, /* need to check defualt value */
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_STORE_REF,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "store long term reference frame",
-               .minimum = 0,
-               .maximum = 2,
-               .step = 1,
-               .default_value = 0, /* need to check defualt value */
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC_GET_VERSION_INFO,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Get MFC version information",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC_GET_EXTRA_BUFFER_SIZE,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Get extra buffer size",
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC_GET_EXT_INFO,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Get extra information",
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT0,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Hierarchical Coding Layer Bit0",
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT1,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Hierarchical Coding Layer Bit1",
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT2,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Hierarchical Coding Layer Bit2",
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT3,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Hierarchical Coding Layer Bit3",
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT4,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Hierarchical Coding Layer Bit4",
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT5,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Hierarchical Coding Layer Bit5",
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT6,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Hierarchical Coding Layer Bit6",
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_CH,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Hierarchical Coding Layer Change",
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_BIT0,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Hierarchical Coding Layer Bit0",
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_BIT1,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Hierarchical Coding Layer Bit1",
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_BIT2,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Hierarchical Coding Layer Bit2",
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_CH,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Hierarchical Coding Layer Change",
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC_H264_ENABLE_LTR,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Enable LTR",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC_H264_NUM_OF_LTR,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Number of LTR",
-               .minimum = 0,
-               .maximum = 4,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC_H264_MARK_LTR,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Set the frame as a LTRP",
-               .minimum = 0,
-               .maximum = 4,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC_H264_USE_LTR,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Specify a LTRP for encoding",
-               .minimum = 0,
-               .maximum = 0xF,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC_H264_BASE_PRIORITY,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Hierarchical Base Layer Priority",
-               .minimum = 0,
-               .maximum = (1 << 6) - 1 - 6,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC_CONFIG_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "QP control per each frame",
-               .minimum = -12,
-               .maximum = 255,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC_H264_VUI_RESTRICTION_ENABLE,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "H264 vui generation enable",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_PREPEND_SPSPPS_TO_IDR,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Prepend SPS/PPS to every IDR",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_MFC_CONFIG_QP_ENABLE,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "set dynamic qp controls",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_ROI_CONTROL,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Region-Of-Interest control",
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_ROI_ENABLE,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Region-Of-Interest enable",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_MIN_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "H264 Min QP value for I frame",
-               .minimum = 0,
-               .maximum = 51,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_MAX_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "H264 Max QP value for I frame",
-               .minimum = 0,
-               .maximum = 51,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "HEVC Min QP value for I frame",
-               .minimum = -12,
-               .maximum = 51,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "HEVC Max QP value for I frame",
-               .minimum = 0,
-               .maximum = 51,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "MPEG4 Min QP value for I frame",
-               .minimum = 1,
-               .maximum = 31,
-               .step = 1,
-               .default_value = 1,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "MPEG4 Max QP value for I frame",
-               .minimum = 1,
-               .maximum = 31,
-               .step = 1,
-               .default_value = 1,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H263_MIN_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "H263 Min QP value for I frame",
-               .minimum = 1,
-               .maximum = 31,
-               .step = 1,
-               .default_value = 1,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H263_MAX_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "H263 Max QP value for I frame",
-               .minimum = 1,
-               .maximum = 31,
-               .step = 1,
-               .default_value = 1,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_VP8_MIN_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "VP8 Min QP value for I frame",
-               .minimum = 0,
-               .maximum = 127,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_VP8_MAX_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "VP8 Max QP value for I frame",
-               .minimum = 0,
-               .maximum = 127,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_VP9_MIN_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "VP9 Min QP value for I frame",
-               .minimum = 1,
-               .maximum = 255,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_VP9_MAX_QP,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "VP9 Max QP value for I frame",
-               .minimum = 1,
-               .maximum = 255,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_MIN_QP_P,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "H264 Min QP value for P frame",
-               .minimum = 0,
-               .maximum = 51,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_MAX_QP_P,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "H264 Max QP value for P frame",
-               .minimum = 0,
-               .maximum = 51,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_P,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "HEVC Min QP value for P frame",
-               .minimum = -12,
-               .maximum = 51,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_P,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "HEVC Max QP value for P frame",
-               .minimum = 0,
-               .maximum = 51,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_P,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "MPEG4 Min QP value for P frame",
-               .minimum = 1,
-               .maximum = 31,
-               .step = 1,
-               .default_value = 1,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_P,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "MPEG4 Max QP value for P frame",
-               .minimum = 1,
-               .maximum = 31,
-               .step = 1,
-               .default_value = 1,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H263_MIN_QP_P,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "H263 Min QP value for P frame",
-               .minimum = 1,
-               .maximum = 31,
-               .step = 1,
-               .default_value = 1,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H263_MAX_QP_P,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "H263 Max QP value for P frame",
-               .minimum = 1,
-               .maximum = 31,
-               .step = 1,
-               .default_value = 1,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_VP8_MIN_QP_P,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "VP8 Min QP value for P frame",
-               .minimum = 0,
-               .maximum = 127,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_VP8_MAX_QP_P,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "VP8 Max QP value for P frame",
-               .minimum = 0,
-               .maximum = 127,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_VP9_MIN_QP_P,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "VP9 Min QP value for P frame",
-               .minimum = 1,
-               .maximum = 255,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_VP9_MAX_QP_P,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "VP9 Max QP value for P frame",
-               .minimum = 1,
-               .maximum = 255,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_MIN_QP_B,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "H264 Min QP value for B frame",
-               .minimum = 0,
-               .maximum = 51,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_H264_MAX_QP_B,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "H264 Max QP value for B frame",
-               .minimum = 0,
-               .maximum = 51,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_B,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "HEVC Min QP value for B frame",
-               .minimum = -12,
-               .maximum = 51,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_B,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "HEVC Max QP value for B frame",
-               .minimum = 0,
-               .maximum = 51,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_B,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "MPEG4 Min QP value for B frame",
-               .minimum = 1,
-               .maximum = 31,
-               .step = 1,
-               .default_value = 1,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_B,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "MPEG4 Max QP value for B frame",
-               .minimum = 1,
-               .maximum = 31,
-               .step = 1,
-               .default_value = 1,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_RC_PVC_ENABLE,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "Perceptual Video Coding enable",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_TEMPORAL_SHORTTERM_MAX_LAYER,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Hierarchical Coding max layer",
-               .minimum = 0,
-               .maximum = 3,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_WEIGHTED_ENABLE,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "Weighted Prediction enable",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_YSUM,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "YSUM for weighted Prediction",
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_BPG_THUMBNAIL_SIZE,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "BPG thumbnail size",
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_BPG_EXIF_SIZE,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "BPG EXIF data size",
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_BPG_HEADER_SIZE,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "BPG header size",
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_RATIO_OF_INTRA,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "ratio of intra encoded size",
-               .minimum = 15,
-               .maximum = 50,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_FULL_RANGE_FLAG,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Color range",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_COLOUR_PRIMARIES,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Colour primaries",
-               .minimum = 0,
-               .maximum = 10,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_TRANSFER_CHARACTERISTICS,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Transfer characteristics",
-               .minimum = 0,
-               .maximum = 17,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_MATRIX_COEFFICIENTS,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Matrix coefficients",
-               .minimum = 0,
-               .maximum = 10,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_HIERARCHICAL_BITRATE_CTRL,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "Hierarchical bitrate control",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 1,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_STATIC_INFO_ENABLE,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Static info enable",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_SEI_MAX_PIC_AVERAGE_LIGHT,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Max pic average light",
-               .minimum = 0,
-               .maximum = 0xFFFF,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_SEI_MAX_CONTENT_LIGHT,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Max content light",
-               .minimum = 0,
-               .maximum = 0xFFFF,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_SEI_MAX_DISPLAY_LUMINANCE,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Max display luminance",
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_SEI_MIN_DISPLAY_LUMINANCE,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Min display luminance",
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_SEI_WHITE_POINT,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "White point",
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_0,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Display primaries 0",
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_1,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Display primaries 1",
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-       {
-               .id = V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_2,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Display primaries 2",
-               .minimum = INT_MIN,
-               .maximum = INT_MAX,
-               .step = 1,
-               .default_value = 0,
-       },
-};
-
-#define NUM_CTRLS ARRAY_SIZE(controls)
-
-#endif /* __S5P_MFC_ENC_INTERNAL_H */
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_enc_ops.c b/drivers/media/platform/exynos/mfc/s5p_mfc_enc_ops.c
deleted file mode 100644 (file)
index eb812aa..0000000
+++ /dev/null
@@ -1,1622 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_enc_ops.c
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include "s5p_mfc_common.h"
-
-#include "s5p_mfc_reg.h"
-
-static int mfc_enc_ctrl_read_cst(struct s5p_mfc_ctx *ctx,
-               struct s5p_mfc_buf_ctrl *buf_ctrl)
-{
-       int ret;
-       struct s5p_mfc_enc *enc = ctx->enc_priv;
-
-       switch (buf_ctrl->id) {
-       case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_STATUS:
-               ret = !enc->in_slice;
-               break;
-       default:
-               mfc_err_ctx("not support custom per-buffer control\n");
-               ret = -EINVAL;
-               break;
-       }
-
-       return ret;
-}
-
-static struct s5p_mfc_ctrl_cfg mfc_ctrl_list[] = {
-       {       /* set frame tag */
-               .type = MFC_CTRL_TYPE_SET,
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG,
-               .is_volatile = 1,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_PICTURE_TAG,
-               .mask = 0xFFFFFFFF,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_NONE,
-               .flag_addr = 0,
-               .flag_shft = 0,
-       },
-       {       /* get frame tag */
-               .type = MFC_CTRL_TYPE_GET_DST,
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG,
-               .is_volatile = 0,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_RET_PICTURE_TAG,
-               .mask = 0xFFFFFFFF,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_NONE,
-               .flag_addr = 0,
-               .flag_shft = 0,
-       },
-       {       /* encoded y physical addr */
-               .type = MFC_CTRL_TYPE_GET_DST,
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_LUMA_ADDR,
-               .is_volatile = 0,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_ENCODED_SOURCE_FIRST_ADDR,
-               .mask = 0xFFFFFFFF,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_NONE,
-               .flag_addr = 0,
-               .flag_shft = 0,
-       },
-       {       /* encoded c physical addr */
-               .type = MFC_CTRL_TYPE_GET_DST,
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_CHROMA_ADDR,
-               .is_volatile = 0,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_ENCODED_SOURCE_SECOND_ADDR,
-               .mask = 0xFFFFFFFF,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_NONE,
-               .flag_addr = 0,
-               .flag_shft = 0,
-       },
-       {       /* I, not coded frame insertion */
-               .type = MFC_CTRL_TYPE_SET,
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE,
-               .is_volatile = 1,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_FRAME_INSERTION,
-               .mask = 0x3,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_NONE,
-               .flag_addr = 0,
-               .flag_shft = 0,
-       },
-       {       /* I period change */
-               .type = MFC_CTRL_TYPE_SET,
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_I_PERIOD_CH,
-               .is_volatile = 1,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_GOP_CONFIG,
-               .mask = 0xFFFF,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_SFR,
-               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
-               .flag_shft = 0,
-       },
-       {       /* frame rate change */
-               .type = MFC_CTRL_TYPE_SET,
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_RATE_CH,
-               .is_volatile = 1,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_RC_FRAME_RATE,
-               .mask = 0xFFFFFFFF,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_SFR,
-               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
-               .flag_shft = 1,
-       },
-       {       /* bit rate change */
-               .type = MFC_CTRL_TYPE_SET,
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_BIT_RATE_CH,
-               .is_volatile = 1,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_RC_BIT_RATE,
-               .mask = 0xFFFFFFFF,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_SFR,
-               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
-               .flag_shft = 2,
-       },
-       {       /* frame status (in slice or not) */
-               .type = MFC_CTRL_TYPE_GET_DST,
-               .id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_STATUS,
-               .is_volatile = 0,
-               .mode = MFC_CTRL_MODE_CST,
-               .addr = 0,
-               .mask = 0xFFFFFFFF,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_NONE,
-               .flag_addr = 0,
-               .flag_shft = 0,
-               .read_cst = mfc_enc_ctrl_read_cst,
-               .write_cst = NULL,
-       },
-       {       /* H.264 I frame QP Max change */
-               .type = MFC_CTRL_TYPE_SET,
-               .id = V4L2_CID_MPEG_VIDEO_H264_MAX_QP,
-               .is_volatile = 1,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_RC_QP_BOUND,
-               .mask = 0xFF,
-               .shft = 8,
-               .flag_mode = MFC_CTRL_MODE_SFR,
-               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
-               .flag_shft = 4,
-       },
-       {       /* H.264 I frame QP Min change */
-               .type = MFC_CTRL_TYPE_SET,
-               .id = V4L2_CID_MPEG_VIDEO_H264_MIN_QP,
-               .is_volatile = 1,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_RC_QP_BOUND,
-               .mask = 0xFF,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_SFR,
-               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
-               .flag_shft = 4,
-       },
-       {       /* H.263 I frame QP Max change */
-               .type = MFC_CTRL_TYPE_SET,
-               .id = V4L2_CID_MPEG_VIDEO_H263_MAX_QP,
-               .is_volatile = 1,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_RC_QP_BOUND,
-               .mask = 0xFF,
-               .shft = 8,
-               .flag_mode = MFC_CTRL_MODE_SFR,
-               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
-               .flag_shft = 4,
-       },
-       {       /* H.263 I frame QP Min change */
-               .type = MFC_CTRL_TYPE_SET,
-               .id = V4L2_CID_MPEG_VIDEO_H263_MIN_QP,
-               .is_volatile = 1,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_RC_QP_BOUND,
-               .mask = 0xFF,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_SFR,
-               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
-               .flag_shft = 4,
-       },
-       {       /* MPEG4 I frame QP Max change */
-               .type = MFC_CTRL_TYPE_SET,
-               .id = V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP,
-               .is_volatile = 1,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_RC_QP_BOUND,
-               .mask = 0xFF,
-               .shft = 8,
-               .flag_mode = MFC_CTRL_MODE_SFR,
-               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
-               .flag_shft = 4,
-       },
-       {       /* MPEG4 I frame QP Min change */
-               .type = MFC_CTRL_TYPE_SET,
-               .id = V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP,
-               .is_volatile = 1,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_RC_QP_BOUND,
-               .mask = 0xFF,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_SFR,
-               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
-               .flag_shft = 4,
-       },
-       {       /* VP8 I frame QP Max change */
-               .type = MFC_CTRL_TYPE_SET,
-               .id = V4L2_CID_MPEG_VIDEO_VP8_MAX_QP,
-               .is_volatile = 1,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_RC_QP_BOUND,
-               .mask = 0xFF,
-               .shft = 8,
-               .flag_mode = MFC_CTRL_MODE_SFR,
-               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
-               .flag_shft = 4,
-       },
-       {       /* VP8 I frame QP Min change */
-               .type = MFC_CTRL_TYPE_SET,
-               .id = V4L2_CID_MPEG_VIDEO_VP8_MIN_QP,
-               .is_volatile = 1,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_RC_QP_BOUND,
-               .mask = 0xFF,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_SFR,
-               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
-               .flag_shft = 4,
-       },
-       {       /* VP9 I frame QP Max change */
-               .type = MFC_CTRL_TYPE_SET,
-               .id = V4L2_CID_MPEG_VIDEO_VP9_MAX_QP,
-               .is_volatile = 1,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_RC_QP_BOUND,
-               .mask = 0xFF,
-               .shft = 8,
-               .flag_mode = MFC_CTRL_MODE_SFR,
-               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
-               .flag_shft = 4,
-       },
-       {       /* VP9 I frame QP Min change */
-               .type = MFC_CTRL_TYPE_SET,
-               .id = V4L2_CID_MPEG_VIDEO_VP9_MIN_QP,
-               .is_volatile = 1,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_RC_QP_BOUND,
-               .mask = 0xFF,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_SFR,
-               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
-               .flag_shft = 4,
-       },
-       {       /* HEVC I frame QP Max change */
-               .type = MFC_CTRL_TYPE_SET,
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP,
-               .is_volatile = 1,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_RC_QP_BOUND,
-               .mask = 0xFF,
-               .shft = 8,
-               .flag_mode = MFC_CTRL_MODE_SFR,
-               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
-               .flag_shft = 4,
-       },
-       {       /* HEVC I frame QP Min change */
-               .type = MFC_CTRL_TYPE_SET,
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP,
-               .is_volatile = 1,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_RC_QP_BOUND,
-               .mask = 0xFF,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_SFR,
-               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
-               .flag_shft = 4,
-       },
-       {       /* H.264 P frame QP Max change */
-               .type = MFC_CTRL_TYPE_SET,
-               .id = V4L2_CID_MPEG_VIDEO_H264_MAX_QP_P,
-               .is_volatile = 1,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
-               .mask = 0xFF,
-               .shft = 8,
-               .flag_mode = MFC_CTRL_MODE_SFR,
-               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
-               .flag_shft = 4,
-       },
-       {       /* H.264 P frame QP Min change */
-               .type = MFC_CTRL_TYPE_SET,
-               .id = V4L2_CID_MPEG_VIDEO_H264_MIN_QP_P,
-               .is_volatile = 1,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
-               .mask = 0xFF,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_SFR,
-               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
-               .flag_shft = 4,
-       },
-       {       /* H.263 P frame QP Max change */
-               .type = MFC_CTRL_TYPE_SET,
-               .id = V4L2_CID_MPEG_VIDEO_H263_MAX_QP_P,
-               .is_volatile = 1,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
-               .mask = 0xFF,
-               .shft = 8,
-               .flag_mode = MFC_CTRL_MODE_SFR,
-               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
-               .flag_shft = 4,
-       },
-       {       /* H.263 P frame QP Min change */
-               .type = MFC_CTRL_TYPE_SET,
-               .id = V4L2_CID_MPEG_VIDEO_H263_MIN_QP_P,
-               .is_volatile = 1,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
-               .mask = 0xFF,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_SFR,
-               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
-               .flag_shft = 4,
-       },
-       {       /* MPEG4 P frame QP Max change */
-               .type = MFC_CTRL_TYPE_SET,
-               .id = V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_P,
-               .is_volatile = 1,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
-               .mask = 0xFF,
-               .shft = 8,
-               .flag_mode = MFC_CTRL_MODE_SFR,
-               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
-               .flag_shft = 4,
-       },
-       {       /* MPEG4 P frame QP Min change */
-               .type = MFC_CTRL_TYPE_SET,
-               .id = V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_P,
-               .is_volatile = 1,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
-               .mask = 0xFF,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_SFR,
-               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
-               .flag_shft = 4,
-       },
-       {       /* VP8 P frame QP Max change */
-               .type = MFC_CTRL_TYPE_SET,
-               .id = V4L2_CID_MPEG_VIDEO_VP8_MAX_QP_P,
-               .is_volatile = 1,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
-               .mask = 0xFF,
-               .shft = 8,
-               .flag_mode = MFC_CTRL_MODE_SFR,
-               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
-               .flag_shft = 4,
-       },
-       {       /* VP8 P frame QP Min change */
-               .type = MFC_CTRL_TYPE_SET,
-               .id = V4L2_CID_MPEG_VIDEO_VP8_MIN_QP_P,
-               .is_volatile = 1,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
-               .mask = 0xFF,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_SFR,
-               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
-               .flag_shft = 4,
-       },
-       {       /* VP9 P frame QP Max change */
-               .type = MFC_CTRL_TYPE_SET,
-               .id = V4L2_CID_MPEG_VIDEO_VP9_MAX_QP_P,
-               .is_volatile = 1,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
-               .mask = 0xFF,
-               .shft = 8,
-               .flag_mode = MFC_CTRL_MODE_SFR,
-               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
-               .flag_shft = 4,
-       },
-       {       /* VP9 P frame QP Min change */
-               .type = MFC_CTRL_TYPE_SET,
-               .id = V4L2_CID_MPEG_VIDEO_VP9_MIN_QP_P,
-               .is_volatile = 1,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
-               .mask = 0xFF,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_SFR,
-               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
-               .flag_shft = 4,
-       },
-       {       /* HEVC P frame QP Max change */
-               .type = MFC_CTRL_TYPE_SET,
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_P,
-               .is_volatile = 1,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
-               .mask = 0xFF,
-               .shft = 8,
-               .flag_mode = MFC_CTRL_MODE_SFR,
-               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
-               .flag_shft = 4,
-       },
-       {       /* HEVC P frame QP Min change */
-               .type = MFC_CTRL_TYPE_SET,
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_P,
-               .is_volatile = 1,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
-               .mask = 0xFF,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_SFR,
-               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
-               .flag_shft = 4,
-       },
-       {       /* H.264 B frame QP Max change */
-               .type = MFC_CTRL_TYPE_SET,
-               .id = V4L2_CID_MPEG_VIDEO_H264_MAX_QP_B,
-               .is_volatile = 1,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
-               .mask = 0xFF,
-               .shft = 24,
-               .flag_mode = MFC_CTRL_MODE_SFR,
-               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
-               .flag_shft = 4,
-       },
-       {       /* H.264 B frame QP Min change */
-               .type = MFC_CTRL_TYPE_SET,
-               .id = V4L2_CID_MPEG_VIDEO_H264_MIN_QP_B,
-               .is_volatile = 1,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
-               .mask = 0xFF,
-               .shft = 16,
-               .flag_mode = MFC_CTRL_MODE_SFR,
-               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
-               .flag_shft = 4,
-       },
-       {       /* MPEG4 B frame QP Max change */
-               .type = MFC_CTRL_TYPE_SET,
-               .id = V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_B,
-               .is_volatile = 1,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
-               .mask = 0xFF,
-               .shft = 24,
-               .flag_mode = MFC_CTRL_MODE_SFR,
-               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
-               .flag_shft = 4,
-       },
-       {       /* MPEG4 B frame QP Min change */
-               .type = MFC_CTRL_TYPE_SET,
-               .id = V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_B,
-               .is_volatile = 1,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
-               .mask = 0xFF,
-               .shft = 16,
-               .flag_mode = MFC_CTRL_MODE_SFR,
-               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
-               .flag_shft = 4,
-       },
-       {       /* HEVC B frame QP Max change */
-               .type = MFC_CTRL_TYPE_SET,
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_B,
-               .is_volatile = 1,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
-               .mask = 0xFF,
-               .shft = 24,
-               .flag_mode = MFC_CTRL_MODE_SFR,
-               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
-               .flag_shft = 4,
-       },
-       {       /* HEVC B frame QP Min change */
-               .type = MFC_CTRL_TYPE_SET,
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_B,
-               .is_volatile = 1,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_RC_QP_BOUND_PB,
-               .mask = 0xFF,
-               .shft = 16,
-               .flag_mode = MFC_CTRL_MODE_SFR,
-               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
-               .flag_shft = 4,
-       },
-       {       /* H.264 Dynamic Temporal Layer & bitrate change */
-               .type = MFC_CTRL_TYPE_SET,
-               .id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_CH,
-               .is_volatile = 1,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER0,
-               .mask = 0xFFFFFFFF,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_SFR,
-               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
-               .flag_shft = 10,
-       },
-       {       /* HEVC Dynamic Temporal Layer & bitrate change */
-               .type = MFC_CTRL_TYPE_SET,
-               .id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_CH,
-               .is_volatile = 1,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER0,
-               .mask = 0xFFFFFFFF,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_SFR,
-               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
-               .flag_shft = 10,
-       },
-       {       /* VP8 Dynamic Temporal Layer change */
-               .type = MFC_CTRL_TYPE_SET,
-               .id = V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_CH,
-               .is_volatile = 1,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER0,
-               .mask = 0xFFFFFFFF,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_SFR,
-               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
-               .flag_shft = 10,
-       },
-       {       /* VP9 Dynamic Temporal Layer change */
-               .type = MFC_CTRL_TYPE_SET,
-               .id = V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_CH,
-               .is_volatile = 1,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER0,
-               .mask = 0xFFFFFFFF,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_SFR,
-               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
-               .flag_shft = 10,
-       },
-       {       /* set level */
-               .type = MFC_CTRL_TYPE_SET,
-               .id = V4L2_CID_MPEG_VIDEO_H264_LEVEL,
-               .is_volatile = 1,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_PICTURE_PROFILE,
-               .mask = 0x000000FF,
-               .shft = 8,
-               .flag_mode = MFC_CTRL_MODE_SFR,
-               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
-               .flag_shft = 5,
-       },
-       {       /* set profile */
-               .type = MFC_CTRL_TYPE_SET,
-               .id = V4L2_CID_MPEG_VIDEO_H264_PROFILE,
-               .is_volatile = 1,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_PICTURE_PROFILE,
-               .mask = 0x0000000F,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_SFR,
-               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
-               .flag_shft = 5,
-       },
-       {       /* set store LTR */
-               .type = MFC_CTRL_TYPE_SET,
-               .id = V4L2_CID_MPEG_MFC_H264_MARK_LTR,
-               .is_volatile = 1,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_H264_NAL_CONTROL,
-               .mask = 0x00000003,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_NONE,
-               .flag_addr = 0,
-               .flag_shft = 0,
-       },
-       {       /* set use LTR */
-               .type = MFC_CTRL_TYPE_SET,
-               .id = V4L2_CID_MPEG_MFC_H264_USE_LTR,
-               .is_volatile = 1,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_H264_NAL_CONTROL,
-               .mask = 0x00000003,
-               .shft = 2,
-               .flag_mode = MFC_CTRL_MODE_NONE,
-               .flag_addr = 0,
-               .flag_shft = 0,
-       },
-       {       /* set base layer priority */
-               .type = MFC_CTRL_TYPE_SET,
-               .id = V4L2_CID_MPEG_MFC_H264_BASE_PRIORITY,
-               .is_volatile = 1,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_H264_HD_SVC_EXTENSION_0,
-               .mask = 0x0000003F,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_SFR,
-               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
-               .flag_shft = 12,
-       },
-       {       /* set QP per each frame */
-               .type = MFC_CTRL_TYPE_SET,
-               .id = V4L2_CID_MPEG_MFC_CONFIG_QP,
-               .is_volatile = 1,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_FIXED_PICTURE_QP,
-               .mask = 0x000000FF,
-               .shft = 24,
-               .flag_mode = MFC_CTRL_MODE_NONE,
-               .flag_addr = 0,
-               .flag_shft = 0,
-       },
-       {       /* Region-Of-Interest control */
-               .type = MFC_CTRL_TYPE_SET,
-               .id = V4L2_CID_MPEG_VIDEO_ROI_CONTROL,
-               .is_volatile = 1,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_RC_ROI_CTRL,
-               .mask = 0xFFFFFFFF,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_NONE,
-               .flag_addr = 0,
-               .flag_shft = 0,
-       },
-       {       /* set YSUM for weighted prediction */
-               .type = MFC_CTRL_TYPE_SET,
-               .id = V4L2_CID_MPEG_VIDEO_YSUM,
-               .is_volatile = 1,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_WEIGHT_FOR_WEIGHTED_PREDICTION,
-               .mask = 0xFFFFFFFF,
-               .shft = 0,
-               .flag_mode = MFC_CTRL_MODE_NONE,
-               .flag_mode = 0,
-               .flag_shft = 0,
-       },
-       {       /* set base layer priority */
-               .type = MFC_CTRL_TYPE_SET,
-               .id = V4L2_CID_MPEG_VIDEO_RATIO_OF_INTRA,
-               .is_volatile = 1,
-               .mode = MFC_CTRL_MODE_SFR,
-               .addr = S5P_FIMV_E_RC_MODE,
-               .mask = 0x000000FF,
-               .shft = 8,
-               .flag_mode = MFC_CTRL_MODE_SFR,
-               .flag_addr = S5P_FIMV_E_PARAM_CHANGE,
-               .flag_shft = 13,
-       }
-};
-
-#define NUM_CTRL_CFGS ARRAY_SIZE(mfc_ctrl_list)
-
-static int s5p_mfc_enc_cleanup_ctx_ctrls(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_ctx_ctrl *ctx_ctrl;
-
-       while (!list_empty(&ctx->ctrls)) {
-               ctx_ctrl = list_entry((&ctx->ctrls)->next,
-                                     struct s5p_mfc_ctx_ctrl, list);
-               list_del(&ctx_ctrl->list);
-               kfree(ctx_ctrl);
-       }
-
-       INIT_LIST_HEAD(&ctx->ctrls);
-
-       return 0;
-}
-
-static int s5p_mfc_enc_get_buf_update_val(struct s5p_mfc_ctx *ctx,
-                       struct list_head *head, unsigned int id, int value)
-{
-       struct s5p_mfc_buf_ctrl *buf_ctrl;
-
-       list_for_each_entry(buf_ctrl, head, list) {
-               if (buf_ctrl->id == id) {
-                       buf_ctrl->val = value;
-                       mfc_debug(6, "[CTRLS] Update buffer control id: 0x%08x, val: %d\n",
-                                       buf_ctrl->id, buf_ctrl->val);
-                       break;
-               }
-       }
-
-       return 0;
-}
-
-static int s5p_mfc_enc_init_ctx_ctrls(struct s5p_mfc_ctx *ctx)
-{
-       unsigned long i;
-       struct s5p_mfc_ctx_ctrl *ctx_ctrl;
-
-       INIT_LIST_HEAD(&ctx->ctrls);
-
-       for (i = 0; i < NUM_CTRL_CFGS; i++) {
-               ctx_ctrl = kzalloc(sizeof(struct s5p_mfc_ctx_ctrl), GFP_KERNEL);
-               if (ctx_ctrl == NULL) {
-                       mfc_err_dev("Failed to allocate context control "\
-                                       "id: 0x%08x, type: %d\n",
-                                       mfc_ctrl_list[i].id,
-                                       mfc_ctrl_list[i].type);
-
-                       s5p_mfc_enc_cleanup_ctx_ctrls(ctx);
-
-                       return -ENOMEM;
-               }
-
-               ctx_ctrl->type = mfc_ctrl_list[i].type;
-               ctx_ctrl->id = mfc_ctrl_list[i].id;
-               ctx_ctrl->has_new = 0;
-               ctx_ctrl->val = 0;
-
-               list_add_tail(&ctx_ctrl->list, &ctx->ctrls);
-       }
-
-       return 0;
-}
-
-static void s5p_mfc_enc_reset_buf_ctrls(struct list_head *head)
-{
-       struct s5p_mfc_buf_ctrl *buf_ctrl;
-
-       list_for_each_entry(buf_ctrl, head, list) {
-               buf_ctrl->has_new = 0;
-               buf_ctrl->val = 0;
-               buf_ctrl->old_val = 0;
-               buf_ctrl->updated = 0;
-       }
-}
-
-static void mfc_enc_remove_buf_ctrls(struct list_head *head)
-{
-       struct s5p_mfc_buf_ctrl *buf_ctrl;
-
-       while (!list_empty(head)) {
-               buf_ctrl = list_entry(head->next,
-                               struct s5p_mfc_buf_ctrl, list);
-               list_del(&buf_ctrl->list);
-               kfree(buf_ctrl);
-       }
-
-       INIT_LIST_HEAD(head);
-}
-
-static int s5p_mfc_enc_init_buf_ctrls(struct s5p_mfc_ctx *ctx,
-       enum s5p_mfc_ctrl_type type, unsigned int index)
-{
-       unsigned long i;
-       struct s5p_mfc_buf_ctrl *buf_ctrl;
-       struct list_head *head;
-
-       if (index >= MFC_MAX_BUFFERS) {
-               mfc_err_dev("Per-buffer control index is out of range\n");
-               return -EINVAL;
-       }
-
-       if (type & MFC_CTRL_TYPE_SRC) {
-               if (test_bit(index, &ctx->src_ctrls_avail)) {
-                       s5p_mfc_enc_reset_buf_ctrls(&ctx->src_ctrls[index]);
-
-                       return 0;
-               }
-
-               head = &ctx->src_ctrls[index];
-       } else if (type & MFC_CTRL_TYPE_DST) {
-               if (test_bit(index, &ctx->dst_ctrls_avail)) {
-                       s5p_mfc_enc_reset_buf_ctrls(&ctx->dst_ctrls[index]);
-
-                       return 0;
-               }
-
-               head = &ctx->dst_ctrls[index];
-       } else {
-               mfc_err_dev("Control type mismatch. type : %d\n", type);
-               return -EINVAL;
-       }
-
-       INIT_LIST_HEAD(head);
-
-       for (i = 0; i < NUM_CTRL_CFGS; i++) {
-               if (!(type & mfc_ctrl_list[i].type))
-                       continue;
-
-               buf_ctrl = kzalloc(sizeof(struct s5p_mfc_buf_ctrl), GFP_KERNEL);
-               if (buf_ctrl == NULL) {
-                       mfc_err_dev("Failed to allocate buffer control "\
-                                       "id: 0x%08x, type: %d\n",
-                                       mfc_ctrl_list[i].id,
-                                       mfc_ctrl_list[i].type);
-
-                       mfc_enc_remove_buf_ctrls(head);
-
-                       return -ENOMEM;
-               }
-
-               buf_ctrl->type = mfc_ctrl_list[i].type;
-               buf_ctrl->id = mfc_ctrl_list[i].id;
-               buf_ctrl->is_volatile = mfc_ctrl_list[i].is_volatile;
-               buf_ctrl->mode = mfc_ctrl_list[i].mode;
-               buf_ctrl->addr = mfc_ctrl_list[i].addr;
-               buf_ctrl->mask = mfc_ctrl_list[i].mask;
-               buf_ctrl->shft = mfc_ctrl_list[i].shft;
-               buf_ctrl->flag_mode = mfc_ctrl_list[i].flag_mode;
-               buf_ctrl->flag_addr = mfc_ctrl_list[i].flag_addr;
-               buf_ctrl->flag_shft = mfc_ctrl_list[i].flag_shft;
-               if (buf_ctrl->mode == MFC_CTRL_MODE_CST) {
-                       buf_ctrl->read_cst = mfc_ctrl_list[i].read_cst;
-                       buf_ctrl->write_cst = mfc_ctrl_list[i].write_cst;
-               }
-
-               list_add_tail(&buf_ctrl->list, head);
-       }
-
-       s5p_mfc_enc_reset_buf_ctrls(head);
-
-       if (type & MFC_CTRL_TYPE_SRC)
-               set_bit(index, &ctx->src_ctrls_avail);
-       else
-               set_bit(index, &ctx->dst_ctrls_avail);
-
-       return 0;
-}
-
-static int s5p_mfc_enc_cleanup_buf_ctrls(struct s5p_mfc_ctx *ctx,
-       enum s5p_mfc_ctrl_type type, unsigned int index)
-{
-       struct list_head *head;
-
-       if (index >= MFC_MAX_BUFFERS) {
-               mfc_err_dev("Per-buffer control index is out of range\n");
-               return -EINVAL;
-       }
-
-       if (type & MFC_CTRL_TYPE_SRC) {
-               if (!(test_and_clear_bit(index, &ctx->src_ctrls_avail))) {
-                       return 0;
-               }
-
-               head = &ctx->src_ctrls[index];
-       } else if (type & MFC_CTRL_TYPE_DST) {
-               if (!(test_and_clear_bit(index, &ctx->dst_ctrls_avail))) {
-                       return 0;
-               }
-
-               head = &ctx->dst_ctrls[index];
-       } else {
-               mfc_err_dev("Control type mismatch. type : %d\n", type);
-               return -EINVAL;
-       }
-
-       mfc_enc_remove_buf_ctrls(head);
-
-       return 0;
-}
-
-static int s5p_mfc_enc_to_buf_ctrls(struct s5p_mfc_ctx *ctx, struct list_head *head)
-{
-       struct s5p_mfc_ctx_ctrl *ctx_ctrl;
-       struct s5p_mfc_buf_ctrl *buf_ctrl;
-       struct s5p_mfc_enc *enc = ctx->enc_priv;
-       int index = 0;
-       unsigned int reg = 0;
-
-       list_for_each_entry(ctx_ctrl, &ctx->ctrls, list) {
-               if (!(ctx_ctrl->type & MFC_CTRL_TYPE_SET) || !ctx_ctrl->has_new)
-                       continue;
-
-               list_for_each_entry(buf_ctrl, head, list) {
-                       if (!(buf_ctrl->type & MFC_CTRL_TYPE_SET))
-                               continue;
-
-                       if (buf_ctrl->id == ctx_ctrl->id) {
-                               buf_ctrl->has_new = 1;
-                               buf_ctrl->val = ctx_ctrl->val;
-                               if (buf_ctrl->is_volatile)
-                                       buf_ctrl->updated = 0;
-
-                               ctx_ctrl->has_new = 0;
-                               if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_ROI_CONTROL) {
-                                       index = enc->roi_index;
-                                       if (enc->roi_info[index].enable) {
-                                               enc->roi_index =
-                                                       (index + 1) % MFC_MAX_EXTRA_BUF;
-                                               reg |= enc->roi_info[index].enable;
-                                               reg &= ~(0xFF << 8);
-                                               reg |= (enc->roi_info[index].lower_qp << 8);
-                                               reg &= ~(0xFFFF << 16);
-                                               reg |= (enc->roi_info[index].upper_qp << 16);
-                                               mfc_debug(3, "[ROI] buffer[%d] en %d, "\
-                                                               "QP lower %d upper %d reg %#x\n",
-                                                               index, enc->roi_info[index].enable,
-                                                               enc->roi_info[index].lower_qp,
-                                                               enc->roi_info[index].upper_qp,
-                                                               reg);
-                                       } else {
-                                               mfc_debug(3, "[ROI] buffer[%d] is not enabled\n", index);
-                                       }
-                                       buf_ctrl->val = reg;
-                                       buf_ctrl->old_val2 = index;
-                               }
-                               break;
-                       }
-               }
-       }
-
-       return 0;
-}
-
-static int s5p_mfc_enc_to_ctx_ctrls(struct s5p_mfc_ctx *ctx, struct list_head *head)
-{
-       struct s5p_mfc_ctx_ctrl *ctx_ctrl;
-       struct s5p_mfc_buf_ctrl *buf_ctrl;
-
-       list_for_each_entry(buf_ctrl, head, list) {
-               if (!(buf_ctrl->type & MFC_CTRL_TYPE_GET) || !buf_ctrl->has_new)
-                       continue;
-
-               list_for_each_entry(ctx_ctrl, &ctx->ctrls, list) {
-                       if (!(ctx_ctrl->type & MFC_CTRL_TYPE_GET))
-                               continue;
-
-                       if (ctx_ctrl->id == buf_ctrl->id) {
-                               if (ctx_ctrl->has_new)
-                                       mfc_debug(8,
-                                       "Overwrite context control "\
-                                       "value id: 0x%08x, val: %d\n",
-                                               ctx_ctrl->id, ctx_ctrl->val);
-
-                               ctx_ctrl->has_new = 1;
-                               ctx_ctrl->val = buf_ctrl->val;
-
-                               buf_ctrl->has_new = 0;
-                       }
-               }
-       }
-
-       return 0;
-}
-
-static void mfc_enc_set_buf_ctrls_temporal_svc(struct s5p_mfc_ctx *ctx,
-                       struct s5p_mfc_buf_ctrl *buf_ctrl)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_enc *enc = ctx->enc_priv;
-       unsigned int value = 0, value2 = 0;
-       struct temporal_layer_info temporal_LC;
-       unsigned int i;
-       struct s5p_mfc_enc_params *p = &enc->params;
-
-       if (buf_ctrl->id
-               == V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_CH ||
-               buf_ctrl->id
-               == V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_CH ||
-               buf_ctrl->id
-               == V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_CH ||
-               buf_ctrl->id
-               == V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_CH) {
-               memcpy(&temporal_LC,
-                       enc->sh_handle_svc.vaddr, sizeof(struct temporal_layer_info));
-
-               if(((temporal_LC.temporal_layer_count & 0x7) < 1) ||
-                       ((temporal_LC.temporal_layer_count > 3) && IS_VP8_ENC(ctx)) ||
-                       ((temporal_LC.temporal_layer_count > 3) && IS_VP9_ENC(ctx))) {
-                       /* clear NUM_T_LAYER_CHANGE */
-                       value = MFC_READL(buf_ctrl->flag_addr);
-                       value &= ~(1 << 10);
-                       MFC_WRITEL(value, buf_ctrl->flag_addr);
-                       mfc_err_ctx("[HIERARCHICAL] layer count is invalid : %d\n",
-                                       temporal_LC.temporal_layer_count);
-                       return;
-               }
-
-               if (IS_H264_ENC(ctx))
-                       p->codec.h264.num_hier_layer = temporal_LC.temporal_layer_count & 0x7;
-
-               /* enable RC_BIT_RATE_CHANGE */
-               value = MFC_READL(buf_ctrl->flag_addr);
-               if (temporal_LC.temporal_layer_bitrate[0] > 0 || p->hier_bitrate_ctrl)
-                       /* set RC_BIT_RATE_CHANGE */
-                       value |= (1 << 2);
-               else
-                       /* clear RC_BIT_RATE_CHANGE */
-                       value &= ~(1 << 2);
-               MFC_WRITEL(value, buf_ctrl->flag_addr);
-
-               mfc_debug(3, "[HIERARCHICAL] layer count %d, E_PARAM_CHANGE %#x\n",
-                               temporal_LC.temporal_layer_count & 0x7, value);
-
-               value = MFC_READL(S5P_FIMV_E_NUM_T_LAYER);
-               buf_ctrl->old_val2 = value;
-               value &= ~(0x7);
-               value |= (temporal_LC.temporal_layer_count & 0x7);
-               value &= ~(0x1 << 8);
-               value |= (p->hier_bitrate_ctrl & 0x1) << 8;
-               MFC_WRITEL(value, S5P_FIMV_E_NUM_T_LAYER);
-               mfc_debug(3, "[HIERARCHICAL] E_NUM_T_LAYER %#x\n", value);
-               for (i = 0; i < (temporal_LC.temporal_layer_count & 0x7); i++) {
-                       mfc_debug(3, "[HIERARCHICAL] layer bitrate[%d] %d (FW ctrl: %d)\n",
-                                       i, temporal_LC.temporal_layer_bitrate[i], p->hier_bitrate_ctrl);
-                       MFC_WRITEL(temporal_LC.temporal_layer_bitrate[i],
-                                       buf_ctrl->addr + i * 4);
-               }
-               /* priority change */
-               if (IS_H264_ENC(ctx)) {
-                       value = 0;
-                       value2 = 0;
-                       for (i = 0; i < (p->codec.h264.num_hier_layer & 0x07); i++) {
-                               if (i <= 4)
-                                       value |= ((p->codec.h264.base_priority & 0x3F) + i)
-                                               << (6 * i);
-                               else
-                                       value2 |= ((p->codec.h264.base_priority & 0x3F) + i)
-                                               << (6 * (i - 5));
-                       }
-                       MFC_WRITEL(value, S5P_FIMV_E_H264_HD_SVC_EXTENSION_0);
-                       MFC_WRITEL(value2, S5P_FIMV_E_H264_HD_SVC_EXTENSION_1);
-                       mfc_debug(3, "[HIERARCHICAL] EXTENSION0 %#x, EXTENSION1 %#x\n",
-                                       value, value2);
-
-                       value = MFC_READL(buf_ctrl->flag_addr);
-                       value |= (1 << 12);
-                       MFC_WRITEL(value, buf_ctrl->flag_addr);
-                       mfc_debug(3, "[HIERARCHICAL] E_PARAM_CHANGE %#x\n", value);
-               }
-
-       }
-
-       /* temproral layer priority */
-       if (buf_ctrl->id == V4L2_CID_MPEG_MFC_H264_BASE_PRIORITY) {
-               value = MFC_READL(S5P_FIMV_E_H264_HD_SVC_EXTENSION_0);
-               buf_ctrl->old_val |= value & 0x3FFFFFC0;
-               value &= ~(0x3FFFFFC0);
-               value2 = MFC_READL(S5P_FIMV_E_H264_HD_SVC_EXTENSION_1);
-               buf_ctrl->old_val2 = value2 & 0x0FFF;
-               value2 &= ~(0x0FFF);
-               for (i = 0; i < (p->codec.h264.num_hier_layer & 0x07); i++) {
-                       if (i <= 4)
-                               value |= ((buf_ctrl->val & 0x3F) + i) << (6 * i);
-                       else
-                               value2 |= ((buf_ctrl->val & 0x3F) + i) << (6 * (i - 5));
-               }
-               MFC_WRITEL(value, S5P_FIMV_E_H264_HD_SVC_EXTENSION_0);
-               MFC_WRITEL(value2, S5P_FIMV_E_H264_HD_SVC_EXTENSION_1);
-               p->codec.h264.base_priority = buf_ctrl->val;
-               mfc_debug(3, "[HIERARCHICAL] EXTENSION0 %#x, EXTENSION1 %#x\n",
-                               value, value2);
-       }
-}
-
-static void mfc_enc_set_buf_ctrls_exception(struct s5p_mfc_ctx *ctx,
-                       struct s5p_mfc_buf_ctrl *buf_ctrl)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_enc *enc = ctx->enc_priv;
-       struct s5p_mfc_enc_params *p = &enc->params;
-       unsigned int value = 0;
-
-       if (buf_ctrl->id == V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG)
-               enc->stored_tag = buf_ctrl->val;
-
-       /* temporal layer setting */
-       mfc_enc_set_buf_ctrls_temporal_svc(ctx, buf_ctrl);
-
-       if (buf_ctrl->id == V4L2_CID_MPEG_MFC_H264_MARK_LTR) {
-               value = MFC_READL(S5P_FIMV_E_H264_NAL_CONTROL);
-               buf_ctrl->old_val2 = (value >> 8) & 0x7;
-               value &= ~(0x7 << 8);
-               value |= (buf_ctrl->val & 0x7) << 8;
-               MFC_WRITEL(value, S5P_FIMV_E_H264_NAL_CONTROL);
-       }
-       if (buf_ctrl->id == V4L2_CID_MPEG_MFC_H264_USE_LTR) {
-               value = MFC_READL(S5P_FIMV_E_H264_NAL_CONTROL);
-               buf_ctrl->old_val2 = (value >> 11) & 0xF;
-               value &= ~(0xF << 11);
-               value |= (buf_ctrl->val & 0xF) << 11;
-               MFC_WRITEL(value, S5P_FIMV_E_H264_NAL_CONTROL);
-       }
-
-       if (buf_ctrl->id == V4L2_CID_MPEG_MFC51_VIDEO_I_PERIOD_CH) {
-               value = MFC_READL(S5P_FIMV_E_GOP_CONFIG2);
-               buf_ctrl->old_val |= (value << 16) & 0x3FFF0000;
-               value &= ~(0x3FFF);
-               value |= (buf_ctrl->val >> 16) & 0x3FFF;
-               MFC_WRITEL(value, S5P_FIMV_E_GOP_CONFIG2);
-       }
-
-       /* PROFILE & LEVEL have to be set up together */
-       if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_H264_LEVEL) {
-               value = MFC_READL(S5P_FIMV_E_PICTURE_PROFILE);
-               buf_ctrl->old_val |= (value & 0x000F) << 8;
-               value &= ~(0x000F);
-               value |= p->codec.h264.profile & 0x000F;
-               MFC_WRITEL(value, S5P_FIMV_E_PICTURE_PROFILE);
-               p->codec.h264.level = buf_ctrl->val;
-       }
-
-       if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_H264_PROFILE) {
-               value = MFC_READL(S5P_FIMV_E_PICTURE_PROFILE);
-               buf_ctrl->old_val |= value & 0xFF00;
-               value &= ~(0x00FF << 8);
-               value |= (p->codec.h264.level << 8) & 0xFF00;
-               MFC_WRITEL(value, S5P_FIMV_E_PICTURE_PROFILE);
-               p->codec.h264.profile = buf_ctrl->val;
-       }
-
-       /* per buffer QP setting change */
-       if (buf_ctrl->id == V4L2_CID_MPEG_MFC_CONFIG_QP)
-               p->config_qp = buf_ctrl->val;
-
-       /* set the ROI buffer DVA */
-       if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_ROI_CONTROL) {
-               MFC_WRITEL(enc->roi_buf[buf_ctrl->old_val2].daddr,
-                               S5P_FIMV_E_ROI_BUFFER_ADDR);
-               mfc_debug(3, "[ROI] buffer[%d] addr %#llx, QP val: %#x\n",
-                               buf_ctrl->old_val2,
-                               enc->roi_buf[buf_ctrl->old_val2].daddr,
-                               buf_ctrl->val);
-       }
-}
-
-static int s5p_mfc_enc_set_buf_ctrls_val(struct s5p_mfc_ctx *ctx, struct list_head *head)
-{
-       struct s5p_mfc_buf_ctrl *buf_ctrl;
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_enc *enc = ctx->enc_priv;
-       unsigned int value = 0;
-       struct s5p_mfc_enc_params *p = &enc->params;
-
-       list_for_each_entry(buf_ctrl, head, list) {
-               if (!(buf_ctrl->type & MFC_CTRL_TYPE_SET) || !buf_ctrl->has_new)
-                       continue;
-
-               /* read old vlaue */
-               value = MFC_READL(buf_ctrl->addr);
-
-               /* save old value for recovery */
-               if (buf_ctrl->is_volatile)
-                       buf_ctrl->old_val = (value >> buf_ctrl->shft) & buf_ctrl->mask;
-
-               /* write new value */
-               value &= ~(buf_ctrl->mask << buf_ctrl->shft);
-               value |= ((buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft);
-               MFC_WRITEL(value, buf_ctrl->addr);
-
-               /* set change flag bit */
-               if (buf_ctrl->flag_mode == MFC_CTRL_MODE_SFR) {
-                       value = MFC_READL(buf_ctrl->flag_addr);
-                       value |= (1 << buf_ctrl->flag_shft);
-                       MFC_WRITEL(value, buf_ctrl->flag_addr);
-               }
-
-               buf_ctrl->has_new = 0;
-               buf_ctrl->updated = 1;
-
-               mfc_enc_set_buf_ctrls_exception(ctx, buf_ctrl);
-
-               mfc_debug(6, "[CTRLS] Set buffer control id: 0x%08x, val: %d\n",
-                               buf_ctrl->id, buf_ctrl->val);
-       }
-
-       if (!p->rc_frame && !p->rc_mb && p->dynamic_qp) {
-               value = MFC_READL(S5P_FIMV_E_FIXED_PICTURE_QP);
-               value &= ~(0xFF000000);
-               value |= (p->config_qp & 0xFF) << 24;
-               MFC_WRITEL(value, S5P_FIMV_E_FIXED_PICTURE_QP);
-               mfc_debug(6, "[CTRLS] Dynamic QP changed %#x\n",
-                               MFC_READL(S5P_FIMV_E_FIXED_PICTURE_QP));
-       }
-
-       return 0;
-}
-
-static int s5p_mfc_enc_get_buf_ctrls_val(struct s5p_mfc_ctx *ctx, struct list_head *head)
-{
-       struct s5p_mfc_buf_ctrl *buf_ctrl;
-       struct s5p_mfc_dev *dev = ctx->dev;
-       unsigned int value = 0;
-
-       list_for_each_entry(buf_ctrl, head, list) {
-               if (!(buf_ctrl->type & MFC_CTRL_TYPE_GET))
-                       continue;
-
-               if (buf_ctrl->mode == MFC_CTRL_MODE_SFR)
-                       value = MFC_READL(buf_ctrl->addr);
-               else if (buf_ctrl->mode == MFC_CTRL_MODE_CST)
-                       value = call_bop(buf_ctrl, read_cst, ctx, buf_ctrl);
-
-               value = (value >> buf_ctrl->shft) & buf_ctrl->mask;
-
-               buf_ctrl->val = value;
-               buf_ctrl->has_new = 1;
-
-               mfc_debug(6, "[CTRLS] Get buffer control id: 0x%08x, val: %d\n",
-                               buf_ctrl->id, buf_ctrl->val);
-       }
-
-       return 0;
-}
-
-static int s5p_mfc_enc_set_buf_ctrls_val_nal_q_enc(struct s5p_mfc_ctx *ctx,
-                       struct list_head *head, EncoderInputStr *pInStr)
-{
-       struct s5p_mfc_buf_ctrl *buf_ctrl;
-       struct s5p_mfc_enc *enc = ctx->enc_priv;
-       struct temporal_layer_info temporal_LC;
-       unsigned int i, param_change;
-       struct s5p_mfc_enc_params *p = &enc->params;
-
-       mfc_debug_enter();
-
-       list_for_each_entry(buf_ctrl, head, list) {
-               if (!(buf_ctrl->type & MFC_CTRL_TYPE_SET) || !buf_ctrl->has_new)
-                       continue;
-               param_change = 0;
-               switch (buf_ctrl->id) {
-               case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG:
-                       pInStr->PictureTag &= ~(buf_ctrl->mask << buf_ctrl->shft);
-                       pInStr->PictureTag |=
-                               (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
-                       enc->stored_tag = buf_ctrl->val;
-                       break;
-               case V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE:
-                       pInStr->FrameInsertion &= ~(buf_ctrl->mask << buf_ctrl->shft);
-                       pInStr->FrameInsertion |=
-                               (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
-                       break;
-               case V4L2_CID_MPEG_MFC51_VIDEO_I_PERIOD_CH:
-                       pInStr->GopConfig &= ~(buf_ctrl->mask << buf_ctrl->shft);
-                       pInStr->GopConfig |=
-                               (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
-                       pInStr->GopConfig2 &= ~(0x3FFF);
-                       pInStr->GopConfig2 |= (buf_ctrl->val >> 16) & 0x3FFF;
-                       param_change = 1;
-                       break;
-               case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_RATE_CH:
-                       pInStr->RcFrameRate &= ~(buf_ctrl->mask << buf_ctrl->shft);
-                       pInStr->RcFrameRate |=
-                               (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
-                       param_change = 1;
-                       break;
-               case V4L2_CID_MPEG_MFC51_VIDEO_BIT_RATE_CH:
-                       pInStr->RcBitRate &= ~(buf_ctrl->mask << buf_ctrl->shft);
-                       pInStr->RcBitRate |=
-                               (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
-                       param_change = 1;
-                       break;
-               case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:
-               case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP:
-               case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP:
-               case V4L2_CID_MPEG_VIDEO_H263_MAX_QP:
-               case V4L2_CID_MPEG_VIDEO_VP8_MAX_QP:
-               case V4L2_CID_MPEG_VIDEO_VP9_MAX_QP:
-               case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:
-               case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP:
-               case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP:
-               case V4L2_CID_MPEG_VIDEO_H263_MIN_QP:
-               case V4L2_CID_MPEG_VIDEO_VP8_MIN_QP:
-               case V4L2_CID_MPEG_VIDEO_VP9_MIN_QP:
-                       pInStr->RcQpBound &= ~(buf_ctrl->mask << buf_ctrl->shft);
-                       pInStr->RcQpBound |=
-                               (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
-                       param_change = 1;
-                       break;
-               case V4L2_CID_MPEG_VIDEO_H264_MAX_QP_P:
-               case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_P:
-               case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_P:
-               case V4L2_CID_MPEG_VIDEO_H263_MAX_QP_P:
-               case V4L2_CID_MPEG_VIDEO_VP8_MAX_QP_P:
-               case V4L2_CID_MPEG_VIDEO_VP9_MAX_QP_P:
-               case V4L2_CID_MPEG_VIDEO_H264_MIN_QP_P:
-               case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_P:
-               case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_P:
-               case V4L2_CID_MPEG_VIDEO_H263_MIN_QP_P:
-               case V4L2_CID_MPEG_VIDEO_VP8_MIN_QP_P:
-               case V4L2_CID_MPEG_VIDEO_VP9_MIN_QP_P:
-               case V4L2_CID_MPEG_VIDEO_H264_MAX_QP_B:
-               case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_B:
-               case V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_B:
-               case V4L2_CID_MPEG_VIDEO_H264_MIN_QP_B:
-               case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_B:
-               case V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_B:
-                       pInStr->RcQpBoundPb &= ~(buf_ctrl->mask << buf_ctrl->shft);
-                       pInStr->RcQpBoundPb |=
-                               (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
-                       param_change = 1;
-                       break;
-               case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_CH:
-               case V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_CH:
-               case V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_CH:
-               case V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_CH:
-                       memcpy(&temporal_LC,
-                               enc->sh_handle_svc.vaddr, sizeof(struct temporal_layer_info));
-
-                       if (((temporal_LC.temporal_layer_count & 0x7) < 1) ||
-                               ((temporal_LC.temporal_layer_count > 3) && IS_VP8_ENC(ctx)) ||
-                               ((temporal_LC.temporal_layer_count > 3) && IS_VP9_ENC(ctx))) {
-                               /* claer NUM_T_LAYER_CHANGE */
-                               mfc_err_ctx("[NALQ][HIERARCHICAL] layer count(%d) is invalid\n",
-                                               temporal_LC.temporal_layer_count);
-                               return 0;
-                       }
-
-                       if (IS_H264_ENC(ctx))
-                               p->codec.h264.num_hier_layer =
-                                       temporal_LC.temporal_layer_count & 0x7;
-
-                       /* enable RC_BIT_RATE_CHANGE */
-                       if (temporal_LC.temporal_layer_bitrate[0] > 0 || p->hier_bitrate_ctrl)
-                               pInStr->ParamChange |= (1 << 2);
-                       else
-                               pInStr->ParamChange &= ~(1 << 2);
-
-                       /* enalbe NUM_T_LAYER_CHANGE */
-                       if (temporal_LC.temporal_layer_count & 0x7)
-                               pInStr->ParamChange |= (1 << 10);
-                       else
-                               pInStr->ParamChange &= ~(1 << 10);
-                       mfc_debug(3, "[NALQ][HIERARCHICAL] layer count %d\n",
-                                       temporal_LC.temporal_layer_count & 0x7);
-
-                       pInStr->NumTLayer &= ~(0x7);
-                       pInStr->NumTLayer |= (temporal_LC.temporal_layer_count & 0x7);
-                       pInStr->NumTLayer &= ~(0x1 << 8);
-                       pInStr->NumTLayer |= (p->hier_bitrate_ctrl & 0x1) << 8;
-                       for (i = 0; i < (temporal_LC.temporal_layer_count & 0x7); i++) {
-                               mfc_debug(3, "[NALQ][HIERARCHICAL] layer bitrate[%d] %d (FW ctrl: %d)\n",
-                                       i, temporal_LC.temporal_layer_bitrate[i], p->hier_bitrate_ctrl);
-                               pInStr->HierarchicalBitRateLayer[i] =
-                                       temporal_LC.temporal_layer_bitrate[i];
-                       }
-
-                       /* priority change */
-                       if (IS_H264_ENC(ctx)) {
-                               for (i = 0; i < (temporal_LC.temporal_layer_count & 0x7); i++) {
-                                       if (i <= 4)
-                                               pInStr->H264HDSvcExtension0 |=
-                                                       ((p->codec.h264.base_priority & 0x3f) + i) << (6 * i);
-                                       else
-                                               pInStr->H264HDSvcExtension1 |=
-                                                       ((p->codec.h264.base_priority & 0x3f) + i) << (6 * (i - 5));
-                               }
-                               mfc_debug(3, "[NALQ][HIERARCHICAL] EXTENSION0 %#x, EXTENSION1 %#x\n",
-                                               pInStr->H264HDSvcExtension0, pInStr->H264HDSvcExtension1);
-
-                               pInStr->ParamChange |= (1 << 12);
-                       }
-                       break;
-               case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
-                       pInStr->PictureProfile &= ~(buf_ctrl->mask << buf_ctrl->shft);
-                       pInStr->PictureProfile |=
-                               (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
-                       pInStr->PictureProfile &= ~(0xf);
-                       pInStr->PictureProfile |= p->codec.h264.profile & 0xf;
-                       p->codec.h264.level = buf_ctrl->val;
-                       param_change = 1;
-                       break;
-               case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
-                       pInStr->PictureProfile &= ~(buf_ctrl->mask << buf_ctrl->shft);
-                       pInStr->PictureProfile |=
-                               (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
-                       pInStr->PictureProfile &= ~(0xff << 8);
-                       pInStr->PictureProfile |= (p->codec.h264.level << 8) & 0xff00;
-                       p->codec.h264.profile = buf_ctrl->val;
-                       param_change = 1;
-                       break;
-               case V4L2_CID_MPEG_MFC_H264_MARK_LTR:
-                       pInStr->H264NalControl &= ~(buf_ctrl->mask << buf_ctrl->shft);
-                       pInStr->H264NalControl |=
-                               (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
-                       pInStr->H264NalControl &= ~(0x7 << 8);
-                       pInStr->H264NalControl |= (buf_ctrl->val & 0x7) << 8;
-                       break;
-               case V4L2_CID_MPEG_MFC_H264_USE_LTR:
-                       pInStr->H264NalControl &= ~(buf_ctrl->mask << buf_ctrl->shft);
-                       pInStr->H264NalControl |=
-                               (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
-                       pInStr->H264NalControl &= ~(0xF << 11);
-                       pInStr->H264NalControl |= (buf_ctrl->val & 0xF) << 11;
-                       break;
-               case V4L2_CID_MPEG_MFC_H264_BASE_PRIORITY:
-                       for (i = 0; i < (p->codec.h264.num_hier_layer & 0x7); i++)
-                               if (i <= 4)
-                                       pInStr->H264HDSvcExtension0 |=
-                                               ((buf_ctrl->val & 0x3f) + i) << (6 * i);
-                               else
-                                       pInStr->H264HDSvcExtension1 |=
-                                               ((buf_ctrl->val & 0x3f) + i) << (6 * (i - 5));
-                       p->codec.h264.base_priority = buf_ctrl->val;
-                       param_change = 1;
-                       break;
-               case V4L2_CID_MPEG_MFC_CONFIG_QP:
-                       pInStr->FixedPictureQp &= ~(buf_ctrl->mask << buf_ctrl->shft);
-                       pInStr->FixedPictureQp |=
-                               (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
-                       p->config_qp = buf_ctrl->val;
-                       break;
-               case V4L2_CID_MPEG_VIDEO_ROI_CONTROL:
-                       pInStr->RcRoiCtrl &= ~(buf_ctrl->mask << buf_ctrl->shft);
-                       pInStr->RcRoiCtrl |=
-                               (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
-                       pInStr->RoiBufferAddr = enc->roi_buf[buf_ctrl->old_val2].daddr;
-                       mfc_debug(3, "[NALQ][ROI] buffer[%d] addr %#llx, QP val: %#x\n",
-                                       buf_ctrl->old_val2,
-                                       enc->roi_buf[buf_ctrl->old_val2].daddr,
-                                       buf_ctrl->val);
-                       break;
-               case V4L2_CID_MPEG_VIDEO_YSUM:
-                       pInStr->Weight &= ~(buf_ctrl->mask << buf_ctrl->shft);
-                       pInStr->Weight |=
-                               (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
-                       break;
-               case V4L2_CID_MPEG_VIDEO_RATIO_OF_INTRA:
-                       pInStr->RcMode &= ~(buf_ctrl->mask << buf_ctrl->shft);
-                       pInStr->RcMode |=
-                               (buf_ctrl->val & buf_ctrl->mask) << buf_ctrl->shft;
-                       param_change = 1;
-                       break;
-               /* If new dynamic controls are added, insert here */
-               default:
-                       mfc_info_ctx("[NALQ] can't find control, id: 0x%x\n",
-                                       buf_ctrl->id);
-               }
-
-               if (param_change)
-                       pInStr->ParamChange |= (1 << buf_ctrl->flag_shft);
-
-               buf_ctrl->has_new = 0;
-               buf_ctrl->updated = 1;
-
-               mfc_debug(6, "[NALQ][CTRLS] Set buffer control id: 0x%08x, val: %d\n",
-                               buf_ctrl->id, buf_ctrl->val);
-       }
-
-       if (!p->rc_frame && !p->rc_mb && p->dynamic_qp) {
-               pInStr->FixedPictureQp &= ~(0xFF000000);
-               pInStr->FixedPictureQp |= (p->config_qp & 0xFF) << 24;
-               mfc_debug(6, "[NALQ][CTRLS] Dynamic QP changed %#x\n",
-                               pInStr->FixedPictureQp);
-       }
-
-       mfc_debug_leave();
-
-       return 0;
-}
-
-static int s5p_mfc_enc_get_buf_ctrls_val_nal_q_enc(struct s5p_mfc_ctx *ctx,
-                       struct list_head *head, EncoderOutputStr *pOutStr)
-{
-       struct s5p_mfc_buf_ctrl *buf_ctrl;
-       struct s5p_mfc_enc *enc = ctx->enc_priv;
-       unsigned int value = 0;
-
-       mfc_debug_enter();
-
-       list_for_each_entry(buf_ctrl, head, list) {
-               if (!(buf_ctrl->type & MFC_CTRL_TYPE_GET))
-                       continue;
-               switch (buf_ctrl->id) {
-               case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG:
-                       value = pOutStr->PictureTag;
-                       break;
-               case V4L2_CID_MPEG_MFC51_VIDEO_LUMA_ADDR:
-                       value = pOutStr->EncodedFrameAddr[0];
-                       break;
-               case V4L2_CID_MPEG_MFC51_VIDEO_CHROMA_ADDR:
-                       value = pOutStr->EncodedFrameAddr[1];
-                       break;
-               case V4L2_CID_MPEG_MFC51_VIDEO_FRAME_STATUS:
-                       value = !enc->in_slice;
-                       break;
-               /* If new dynamic controls are added, insert here */
-               default:
-                       mfc_info_ctx("[NALQ] can't find control, id: 0x%x\n",
-                                       buf_ctrl->id);
-               }
-               value = (value >> buf_ctrl->shft) & buf_ctrl->mask;
-
-               buf_ctrl->val = value;
-               buf_ctrl->has_new = 1;
-
-               mfc_debug(6, "[NALQ][CTRLS] Get buffer control id: 0x%08x, val: %d\n",
-                               buf_ctrl->id, buf_ctrl->val);
-       }
-
-       mfc_debug_leave();
-
-       return 0;
-}
-
-static int s5p_mfc_enc_recover_buf_ctrls_val(struct s5p_mfc_ctx *ctx,
-                                               struct list_head *head)
-{
-       struct s5p_mfc_buf_ctrl *buf_ctrl;
-       struct s5p_mfc_dev *dev = ctx->dev;
-       unsigned int value = 0;
-
-       list_for_each_entry(buf_ctrl, head, list) {
-               if (!(buf_ctrl->type & MFC_CTRL_TYPE_SET)
-                       || !buf_ctrl->is_volatile
-                       || !buf_ctrl->updated)
-                       continue;
-
-               if (buf_ctrl->mode == MFC_CTRL_MODE_SFR)
-                       value = MFC_READL(buf_ctrl->addr);
-
-               value &= ~(buf_ctrl->mask << buf_ctrl->shft);
-               value |= ((buf_ctrl->old_val & buf_ctrl->mask)
-                                                       << buf_ctrl->shft);
-
-               if (buf_ctrl->mode == MFC_CTRL_MODE_SFR)
-                       MFC_WRITEL(value, buf_ctrl->addr);
-
-               /* clear change flag bit */
-               if (buf_ctrl->flag_mode == MFC_CTRL_MODE_SFR) {
-                       value = MFC_READL(buf_ctrl->flag_addr);
-                       value &= ~(1 << buf_ctrl->flag_shft);
-                       MFC_WRITEL(value, buf_ctrl->flag_addr);
-               }
-
-               mfc_debug(6, "[CTRLS] Recover buffer control id: 0x%08x, old val: %d\n",
-                               buf_ctrl->id, buf_ctrl->old_val);
-
-               if (buf_ctrl->id == V4L2_CID_MPEG_MFC51_VIDEO_I_PERIOD_CH) {
-                       value = MFC_READL(S5P_FIMV_E_GOP_CONFIG2);
-                       value &= ~(0x3FFF);
-                       value |= (buf_ctrl->old_val >> 16) & 0x3FFF;
-                       MFC_WRITEL(value, S5P_FIMV_E_GOP_CONFIG2);
-               }
-               if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_H264_LEVEL) {
-                       value = MFC_READL(S5P_FIMV_E_PICTURE_PROFILE);
-                       value &= ~(0x000F);
-                       value |= (buf_ctrl->old_val >> 8) & 0x000F;
-                       MFC_WRITEL(value, S5P_FIMV_E_PICTURE_PROFILE);
-               }
-               if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_H264_PROFILE) {
-                       value = MFC_READL(S5P_FIMV_E_PICTURE_PROFILE);
-                       value &= ~(0xFF00);
-                       value |= buf_ctrl->old_val & 0xFF00;
-                       MFC_WRITEL(value, S5P_FIMV_E_PICTURE_PROFILE);
-               }
-               if (buf_ctrl->id == V4L2_CID_MPEG_MFC_H264_BASE_PRIORITY) {
-                       MFC_WRITEL(buf_ctrl->old_val, S5P_FIMV_E_H264_HD_SVC_EXTENSION_0);
-                       MFC_WRITEL(buf_ctrl->old_val2, S5P_FIMV_E_H264_HD_SVC_EXTENSION_1);
-               }
-               if (buf_ctrl->id
-                       == V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_CH ||
-                       buf_ctrl->id
-                       == V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_CH ||
-                       buf_ctrl->id
-                       == V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_CH) {
-                       MFC_WRITEL(buf_ctrl->old_val2, S5P_FIMV_E_NUM_T_LAYER);
-                       /* clear RC_BIT_RATE_CHANGE */
-                       value = MFC_READL(buf_ctrl->flag_addr);
-                       value &= ~(1 << 2);
-                       MFC_WRITEL(value, buf_ctrl->flag_addr);
-               }
-               if (buf_ctrl->id == V4L2_CID_MPEG_MFC_H264_MARK_LTR) {
-                       value = MFC_READL(S5P_FIMV_E_H264_NAL_CONTROL);
-                       value &= ~(0x7 << 8);
-                       value |= (buf_ctrl->old_val2 & 0x7) << 8;
-                       MFC_WRITEL(value, S5P_FIMV_E_H264_NAL_CONTROL);
-               }
-               if (buf_ctrl->id == V4L2_CID_MPEG_MFC_H264_USE_LTR) {
-                       value = MFC_READL(S5P_FIMV_E_H264_NAL_CONTROL);
-                       value &= ~(0xF << 11);
-                       value |= (buf_ctrl->old_val2 & 0xF) << 11;
-                       MFC_WRITEL(value, S5P_FIMV_E_H264_NAL_CONTROL);
-               }
-               buf_ctrl->updated = 0;
-       }
-
-       return 0;
-}
-
-static int s5p_mfc_enc_recover_buf_ctrls_nal_q(struct s5p_mfc_ctx *ctx,
-               struct list_head *head)
-{
-       struct s5p_mfc_buf_ctrl *buf_ctrl;
-
-       list_for_each_entry(buf_ctrl, head, list) {
-               if (!(buf_ctrl->type & MFC_CTRL_TYPE_SET)
-                               || !(buf_ctrl->updated))
-                       continue;
-
-               buf_ctrl->has_new = 1;
-               buf_ctrl->updated = 0;
-
-               mfc_debug(6, "[NALQ][CTRLS] Recover buffer control id: 0x%08x, val: %d\n",
-                               buf_ctrl->id, buf_ctrl->val);
-       }
-
-       return 0;
-}
-
-struct s5p_mfc_ctrls_ops encoder_ctrls_ops = {
-       .init_ctx_ctrls                 = s5p_mfc_enc_init_ctx_ctrls,
-       .cleanup_ctx_ctrls              = s5p_mfc_enc_cleanup_ctx_ctrls,
-       .init_buf_ctrls                 = s5p_mfc_enc_init_buf_ctrls,
-       .reset_buf_ctrls                = s5p_mfc_enc_reset_buf_ctrls,
-       .cleanup_buf_ctrls              = s5p_mfc_enc_cleanup_buf_ctrls,
-       .to_buf_ctrls                   = s5p_mfc_enc_to_buf_ctrls,
-       .to_ctx_ctrls                   = s5p_mfc_enc_to_ctx_ctrls,
-       .set_buf_ctrls_val              = s5p_mfc_enc_set_buf_ctrls_val,
-       .get_buf_ctrls_val              = s5p_mfc_enc_get_buf_ctrls_val,
-       .recover_buf_ctrls_val          = s5p_mfc_enc_recover_buf_ctrls_val,
-       .get_buf_update_val             = s5p_mfc_enc_get_buf_update_val,
-       .set_buf_ctrls_val_nal_q_enc    = s5p_mfc_enc_set_buf_ctrls_val_nal_q_enc,
-       .get_buf_ctrls_val_nal_q_enc    = s5p_mfc_enc_get_buf_ctrls_val_nal_q_enc,
-       .recover_buf_ctrls_nal_q        = s5p_mfc_enc_recover_buf_ctrls_nal_q,
-};
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_enc_param.c b/drivers/media/platform/exynos/mfc/s5p_mfc_enc_param.c
deleted file mode 100644 (file)
index bfc3233..0000000
+++ /dev/null
@@ -1,1397 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_enc_param.c
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include "s5p_mfc_enc_param.h"
-
-#include "s5p_mfc_reg.h"
-
-/* Definition */
-#define FRAME_DELTA_DEFAULT            1
-#define CBR_FIX_MAX                    10
-#define CBR_I_LIMIT_MAX                        5
-#define BPG_EXTENSION_TAG_SIZE         5
-
-void s5p_mfc_set_slice_mode(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_enc *enc = ctx->enc_priv;
-
-       /* multi-slice control */
-       if (enc->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES)
-               MFC_WRITEL((enc->slice_mode + 0x4), S5P_FIMV_E_MSLICE_MODE);
-       else if (enc->slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB_ROW)
-               MFC_WRITEL((enc->slice_mode - 0x2), S5P_FIMV_E_MSLICE_MODE);
-       else if (enc->slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_FIXED_BYTES)
-               MFC_WRITEL((enc->slice_mode + 0x3), S5P_FIMV_E_MSLICE_MODE);
-       else
-               MFC_WRITEL(enc->slice_mode, S5P_FIMV_E_MSLICE_MODE);
-
-       /* multi-slice MB number or bit size */
-       if ((enc->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB) ||
-                       (enc->slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB_ROW)) {
-               MFC_WRITEL(enc->slice_size.mb, S5P_FIMV_E_MSLICE_SIZE_MB);
-       } else if ((enc->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES) ||
-                       (enc->slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_FIXED_BYTES)){
-               MFC_WRITEL(enc->slice_size.bits, S5P_FIMV_E_MSLICE_SIZE_BITS);
-       } else {
-               MFC_WRITEL(0x0, S5P_FIMV_E_MSLICE_SIZE_MB);
-               MFC_WRITEL(0x0, S5P_FIMV_E_MSLICE_SIZE_BITS);
-       }
-}
-
-static void mfc_set_gop_size(struct s5p_mfc_ctx *ctx, int ctrl_mode)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_enc *enc = ctx->enc_priv;
-       struct s5p_mfc_enc_params *p = &enc->params;
-       unsigned int reg = 0;
-
-       if (ctrl_mode) {
-               p->i_frm_ctrl_mode = 1;
-               p->i_frm_ctrl = p->gop_size * (p->num_b_frame + 1);
-               if (p->i_frm_ctrl >= 0x3FFFFFFF) {
-                       mfc_info_ctx("I frame interval is bigger than max: %d\n",
-                                       p->i_frm_ctrl);
-                       p->i_frm_ctrl = 0x3FFFFFFF;
-               }
-       } else {
-               p->i_frm_ctrl_mode = 0;
-               p->i_frm_ctrl = p->gop_size;
-       }
-
-       mfc_debug(2, "I frame interval: %d, (P: %d, B: %d), ctrl mode: %d\n",
-                       p->i_frm_ctrl, p->gop_size,
-                       p->num_b_frame, p->i_frm_ctrl_mode);
-
-       /* pictype : IDR period, number of B */
-       reg = MFC_READL(S5P_FIMV_E_GOP_CONFIG);
-       reg &= ~(0xFFFF);
-       reg |= p->i_frm_ctrl & 0xFFFF;
-       reg &= ~(0x1 << 19);
-       reg |= p->i_frm_ctrl_mode << 19;
-       reg &= ~(0x3 << 16);
-       /* if B frame is used, the performance falls by half */
-       reg |= (p->num_b_frame << 16);
-       MFC_WRITEL(reg, S5P_FIMV_E_GOP_CONFIG);
-
-       reg = MFC_READL(S5P_FIMV_E_GOP_CONFIG2);
-       reg &= ~(0x3FFF);
-       reg |= (p->i_frm_ctrl >> 16) & 0x3FFF;
-       MFC_WRITEL(reg, S5P_FIMV_E_GOP_CONFIG2);
-}
-
-static void mfc_set_default_params(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       int i;
-
-       mfc_debug(2, "Set default param -  enc_param_num: %d\n", dev->pdata->enc_param_num);
-       for (i = 0; i < dev->pdata->enc_param_num; i++) {
-               if (i >= MFC_MAX_DEFAULT_PARAM) {
-                       mfc_err_dev("enc_param_num(%d) is over max number(%d)\n",
-                                       dev->pdata->enc_param_num, MFC_MAX_DEFAULT_PARAM);
-                       break;
-               }
-               MFC_WRITEL(dev->pdata->enc_param_val[i], dev->pdata->enc_param_addr[i]);
-               mfc_debug(2, "Set default param[%d] - addr:0x%x, val:0x%x\n",
-                               i, dev->pdata->enc_param_addr[i], dev->pdata->enc_param_val[i]);
-       }
-}
-
-static void mfc_init_regs(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       /* Register initialization */
-       MFC_WRITEL(0x0, S5P_FIMV_E_FRAME_INSERTION);
-       MFC_WRITEL(0x0, S5P_FIMV_E_ROI_BUFFER_ADDR);
-       MFC_WRITEL(0x0, S5P_FIMV_E_PARAM_CHANGE);
-       MFC_WRITEL(0x0, S5P_FIMV_E_PICTURE_TAG);
-       MFC_WRITEL(0x0, S5P_FIMV_E_METADATA_BUFFER_ADDR);
-       MFC_WRITEL(0x0, S5P_FIMV_E_METADATA_BUFFER_SIZE);
-}
-
-static void mfc_set_enc_params(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_enc *enc = ctx->enc_priv;
-       struct s5p_mfc_enc_params *p = &enc->params;
-       unsigned int reg = 0;
-
-       mfc_debug_enter();
-
-       mfc_init_regs(ctx);
-       mfc_set_default_params(ctx);
-
-       /* width */
-       MFC_WRITEL(ctx->crop_width, S5P_FIMV_E_CROPPED_FRAME_WIDTH);
-       /* height */
-       MFC_WRITEL(ctx->crop_height, S5P_FIMV_E_CROPPED_FRAME_HEIGHT);
-       /* cropped offset */
-       reg |= (ctx->crop_left & S5P_FIMV_E_FRAME_CROP_OFFSET_MASK)
-               << S5P_FIMV_E_FRAME_CROP_OFFSET_LEFT;
-       reg |= (ctx->crop_top & S5P_FIMV_E_FRAME_CROP_OFFSET_MASK)
-               << S5P_FIMV_E_FRAME_CROP_OFFSET_TOP;
-       MFC_WRITEL(reg, S5P_FIMV_E_FRAME_CROP_OFFSET);
-
-       /* multi-slice control */
-       /* multi-slice MB number or bit size */
-       enc->slice_mode = p->slice_mode;
-
-       if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB) {
-               enc->slice_size.mb = p->slice_mb;
-       } else if ((p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES) ||
-                       (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_FIXED_BYTES)){
-               enc->slice_size.bits = p->slice_bit;
-       } else if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB_ROW) {
-               enc->slice_size.mb = p->slice_mb_row * ((ctx->crop_width + 15) / 16);
-       } else {
-               enc->slice_size.mb = 0;
-               enc->slice_size.bits = 0;
-       }
-
-       s5p_mfc_set_slice_mode(ctx);
-
-       /* cyclic intra refresh */
-       MFC_WRITEL(p->intra_refresh_mb, S5P_FIMV_E_IR_SIZE);
-
-       reg = MFC_READL(S5P_FIMV_E_ENC_OPTIONS);
-       /* frame skip mode */
-       reg &= ~(0x3);
-       reg |= (p->frame_skip_mode & 0x3);
-       /* seq header ctrl */
-       reg &= ~(0x1 << 2);
-       reg |= ((p->seq_hdr_mode & 0x1) << 2);
-       /* cyclic intra refresh */
-       reg &= ~(0x1 << 4);
-       if (p->intra_refresh_mb)
-               reg |= (0x1 << 4);
-       /* disable seq header generation if OTF mode */
-       reg &= ~(0x1 << 6);
-       if (ctx->otf_handle) {
-               reg |= (0x1 << 6);
-               mfc_debug(2, "[OTF] SEQ_HEADER_GENERATION is disabled\n");
-       }
-       /* 'NON_REFERENCE_STORE_ENABLE' for debugging */
-       reg &= ~(0x1 << 9);
-       /* Disable parallel processing if nal_q_parallel_disable was set */
-       reg &= ~(0x1 << 18);
-       if (nal_q_parallel_disable)
-               reg |= (0x1 << 18);
-       MFC_WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS);
-
-       s5p_mfc_set_pixel_format(dev, ctx->src_fmt->fourcc);
-
-       /* padding control & value */
-       MFC_WRITEL(0x0, S5P_FIMV_E_PADDING_CTRL);
-       if (p->pad) {
-               reg = 0;
-               /** enable */
-               reg |= (1 << 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);
-               MFC_WRITEL(reg, S5P_FIMV_E_PADDING_CTRL);
-       }
-
-       /* rate control config. */
-       reg = MFC_READL(S5P_FIMV_E_RC_CONFIG);
-       /* macroblock level rate control */
-       reg &= ~(0x1 << 8);
-       reg |= ((p->rc_mb & 0x1) << 8);
-       /* frame-level rate control */
-       reg &= ~(0x1 << 9);
-       reg |= ((p->rc_frame & 0x1) << 9);
-       /* 'DROP_CONTROL_ENABLE', disable */
-       reg &= ~(0x1 << 10);
-       MFC_WRITEL(reg, S5P_FIMV_E_RC_CONFIG);
-
-       /* bit rate */
-       MFC_WRITEL(p->rc_bitrate, S5P_FIMV_E_RC_BIT_RATE);
-
-
-       reg = MFC_READL(S5P_FIMV_E_RC_MODE);
-       reg &= ~(0x3 | (0x3 << 4) | (0xFF << 8));
-       if (p->rc_frame) {
-               if (p->rc_reaction_coeff <= CBR_I_LIMIT_MAX) {
-                       reg |= S5P_FIMV_E_RC_CBR_I_LIMIT;
-                       /*
-                        * Ratio of intra for max frame size
-                        * is controled when only CBR_I_LIMIT mode.
-                        * And CBR_I_LIMIT mode is valid for H.264, HEVC codec
-                        */
-                       if (p->ratio_intra)
-                               reg |= ((p->ratio_intra & 0xFF) << 8);
-               } else if (p->rc_reaction_coeff <= CBR_FIX_MAX) {
-                       reg |= S5P_FIMV_E_RC_CBR_FIX;
-               } else {
-                       reg |= S5P_FIMV_E_RC_VBR;
-               }
-
-               if (p->rc_mb)
-                       reg |= ((p->rc_pvc & 0x3) << 4);
-       }
-       MFC_WRITEL(reg, S5P_FIMV_E_RC_MODE);
-
-       /* extended encoder ctrl */
-       /** vbv buffer size */
-       reg = MFC_READL(S5P_FIMV_E_VBV_BUFFER_SIZE);
-       reg &= ~(0xFF);
-       if (p->frame_skip_mode == V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT)
-               reg |= p->vbv_buf_size & 0xFF;
-       MFC_WRITEL(reg, S5P_FIMV_E_VBV_BUFFER_SIZE);
-
-       mfc_debug_leave();
-}
-
-static void mfc_set_temporal_svc_h264(struct s5p_mfc_ctx *ctx, struct s5p_mfc_h264_enc_params *p_264)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_enc *enc = ctx->enc_priv;
-       struct s5p_mfc_enc_params *p = &enc->params;
-       unsigned int reg = 0, reg2 = 0;
-       int i;
-
-       reg = MFC_READL(S5P_FIMV_E_H264_OPTIONS_2);
-       /* pic_order_cnt_type = 0 for backward compatibilities */
-       reg &= ~(0x3);
-       /* Enable LTR */
-       reg &= ~(0x1 << 2);
-       if ((p_264->enable_ltr & 0x1) || (p_264->num_of_ltr > 0))
-               reg |= (0x1 << 2);
-       /* Number of LTR */
-       reg &= ~(0x3 << 7);
-       if (p_264->num_of_ltr > 2)
-               reg |= (((p_264->num_of_ltr - 2) & 0x3) << 7);
-       MFC_WRITEL(reg, S5P_FIMV_E_H264_OPTIONS_2);
-
-       /* Temporal SVC - qp type, layer number */
-       reg = MFC_READL(S5P_FIMV_E_NUM_T_LAYER);
-       reg &= ~(0x1 << 3);
-       reg |= (p_264->hier_qp_type & 0x1) << 3;
-       reg &= ~(0x7);
-       reg |= p_264->num_hier_layer & 0x7;
-       reg &= ~(0x7 << 4);
-       if (p_264->hier_ref_type) {
-               reg |= 0x1 << 7;
-               reg |= (p->num_hier_max_layer & 0x7) << 4;
-       } else {
-               reg &= ~(0x1 << 7);
-               reg |= 0x7 << 4;
-       }
-       reg &= ~(0x1 << 8);
-       reg |= (p->hier_bitrate_ctrl & 0x1) << 8;
-       MFC_WRITEL(reg, S5P_FIMV_E_NUM_T_LAYER);
-       mfc_debug(3, "[HIERARCHICAL] hier_qp_enable %d, enable_ltr %d, "
-               "num_hier_layer %d, max_layer %d, hier_ref_type %d, NUM_T_LAYER 0x%x\n",
-               p_264->hier_qp_enable, p_264->enable_ltr, p_264->num_hier_layer,
-               p->num_hier_max_layer, p_264->hier_ref_type, reg);
-       /* QP & Bitrate for each layer */
-       for (i = 0; i < 7; i++) {
-               MFC_WRITEL(p_264->hier_qp_layer[i],
-                               S5P_FIMV_E_HIERARCHICAL_QP_LAYER0 + i * 4);
-               /* If hier_bitrate_ctrl is set to 1, this is meaningless */
-               MFC_WRITEL(p_264->hier_bit_layer[i],
-                               S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER0 + i * 4);
-               mfc_debug(3, "[HIERARCHICAL] layer[%d] QP: %#x, bitrate: %d(FW ctrl: %d)\n",
-                                       i, p_264->hier_qp_layer[i],
-                                       p_264->hier_bit_layer[i], p->hier_bitrate_ctrl);
-       }
-       if (p_264->set_priority) {
-               reg = 0;
-               reg2 = 0;
-               for (i = 0; i < (p_264->num_hier_layer & 0x7); i++) {
-                       if (i <= 4)
-                               reg |= ((p_264->base_priority & 0x3F) + i) << (6 * i);
-                       else
-                               reg2 |= ((p_264->base_priority & 0x3F) + i) << (6 * (i - 5));
-               }
-               MFC_WRITEL(reg, S5P_FIMV_E_H264_HD_SVC_EXTENSION_0);
-               MFC_WRITEL(reg2, S5P_FIMV_E_H264_HD_SVC_EXTENSION_1);
-               mfc_debug(3, "[HIERARCHICAL] priority EXTENSION0: %#x, EXTENSION1: %#x\n",
-                                                       reg, reg2);
-       }
-}
-
-static void mfc_set_fmo_slice_map_h264(struct s5p_mfc_ctx *ctx, struct s5p_mfc_h264_enc_params *p_264)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       int i;
-
-       if (p_264->fmo_enable) {
-               switch (p_264->fmo_slice_map_type) {
-               case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_INTERLEAVED_SLICES:
-                       if (p_264->fmo_slice_num_grp > 4)
-                               p_264->fmo_slice_num_grp = 4;
-                       for (i = 0; i < (p_264->fmo_slice_num_grp & 0xF); i++)
-                               MFC_WRITEL(p_264->fmo_run_length[i] - 1,
-                               S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_0 + i*4);
-                       break;
-               case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_SCATTERED_SLICES:
-                       if (p_264->fmo_slice_num_grp > 4)
-                               p_264->fmo_slice_num_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_264->fmo_slice_num_grp > 2)
-                               p_264->fmo_slice_num_grp = 2;
-                       MFC_WRITEL(p_264->fmo_sg_dir & 0x1,
-                               S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_DIR);
-                       /* the valid range is 0 ~ number of macroblocks -1 */
-                       MFC_WRITEL(p_264->fmo_sg_rate, S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_RATE_MINUS1);
-                       break;
-               default:
-                       mfc_err_ctx("Unsupported map type for FMO: %d\n",
-                                       p_264->fmo_slice_map_type);
-                       p_264->fmo_slice_map_type = 0;
-                       p_264->fmo_slice_num_grp = 1;
-                       break;
-               }
-
-               MFC_WRITEL(p_264->fmo_slice_map_type, S5P_FIMV_E_H264_FMO_SLICE_GRP_MAP_TYPE);
-               MFC_WRITEL(p_264->fmo_slice_num_grp - 1, S5P_FIMV_E_H264_FMO_NUM_SLICE_GRP_MINUS1);
-       } else {
-               MFC_WRITEL(0, S5P_FIMV_E_H264_FMO_NUM_SLICE_GRP_MINUS1);
-       }
-}
-
-void s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_enc *enc = ctx->enc_priv;
-       struct s5p_mfc_enc_params *p = &enc->params;
-       struct s5p_mfc_h264_enc_params *p_264 = &p->codec.h264;
-       unsigned int reg = 0;
-
-       mfc_debug_enter();
-
-       mfc_set_enc_params(ctx);
-
-       if (p_264->num_hier_layer & 0x7) {
-               /* set gop_size without i_frm_ctrl mode */
-               mfc_set_gop_size(ctx, 0);
-       } else {
-               /* set gop_size with i_frm_ctrl mode */
-               mfc_set_gop_size(ctx, 1);
-       }
-
-       /* UHD encoding case */
-       if(IS_UHD_RES(ctx)) {
-               if (p_264->level < 51) {
-                       mfc_info_ctx("Set Level 5.1 for UHD\n");
-                       p_264->level = 51;
-               }
-               if (p_264->profile != 0x2) {
-                       mfc_info_ctx("Set High profile for UHD\n");
-                       p_264->profile = 0x2;
-               }
-       }
-
-       /* profile & level */
-       reg = 0;
-       /** level */
-       reg &= ~(0xFF << 8);
-       reg |= (p_264->level << 8);
-       /** profile - 0 ~ 3 */
-       reg &= ~(0x3F);
-       reg |= p_264->profile;
-       MFC_WRITEL(reg, S5P_FIMV_E_PICTURE_PROFILE);
-
-       reg = MFC_READL(S5P_FIMV_E_H264_OPTIONS);
-       /* entropy coding mode */
-       reg &= ~(0x1);
-       reg |= (p_264->entropy_mode & 0x1);
-       /* loop filter ctrl */
-       reg &= ~(0x3 << 1);
-       reg |= ((p_264->loop_filter_mode & 0x3) << 1);
-       /* interlace */
-       reg &= ~(0x1 << 3);
-       reg |= ((p_264->interlace & 0x1) << 3);
-       /* intra picture period for H.264 open GOP */
-       reg &= ~(0x1 << 4);
-       reg |= ((p_264->open_gop & 0x1) << 4);
-       /* extended encoder ctrl */
-       reg &= ~(0x1 << 5);
-       reg |= ((p_264->ar_vui & 0x1) << 5);
-       /* ASO enable */
-       reg &= ~(0x1 << 6);
-       reg |= ((p_264->aso_enable & 0x1) << 6);
-       /* if num_refs_for_p is 2, the performance falls by half */
-       reg &= ~(0x1 << 7);
-       reg |= (((p->num_refs_for_p - 1) & 0x1) << 7);
-       /* Temporal SVC - hier qp enable */
-       reg &= ~(0x1 << 8);
-       reg |= ((p_264->hier_qp_enable & 0x1) << 8);
-       /* Weighted Prediction enable */
-       reg &= ~(0x3 << 9);
-       reg |= ((p->weighted_enable & 0x1) << 9);
-       /* 8x8 transform enable */
-       reg &= ~(0x1 << 12);
-       reg &= ~(0x1 << 13);
-       reg |= ((p_264->_8x8_transform & 0x1) << 12);
-       reg |= ((p_264->_8x8_transform & 0x1) << 13);
-       /* 'CONSTRAINED_INTRA_PRED_ENABLE' is disable */
-       reg &= ~(0x1 << 14);
-       /*
-        * CONSTRAINT_SET0_FLAG: all constraints specified in
-        * Baseline Profile
-        */
-       reg |= (0x1 << 26);
-       /* sps pps control */
-       reg &= ~(0x1 << 29);
-       reg |= ((p_264->prepend_sps_pps_to_idr & 0x1) << 29);
-       /* enable sps pps control in OTF scenario */
-       if (ctx->otf_handle) {
-               reg |= (0x1 << 29);
-               mfc_debug(2, "[OTF] SPS_PPS_CONTROL enabled\n");
-       }
-       /* VUI parameter disable */
-       reg &= ~(0x1 << 30);
-       reg |= ((p_264->vui_enable & 0x1) << 30);
-       MFC_WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
-
-       /* cropped height */
-       if (p_264->interlace)
-               MFC_WRITEL(ctx->crop_height >> 1, S5P_FIMV_E_CROPPED_FRAME_HEIGHT);
-
-       /* loopfilter alpha offset */
-       reg = MFC_READL(S5P_FIMV_E_H264_LF_ALPHA_OFFSET);
-       reg &= ~(0x1F);
-       reg |= (p_264->loop_filter_alpha & 0x1F);
-       MFC_WRITEL(reg, S5P_FIMV_E_H264_LF_ALPHA_OFFSET);
-
-       /* loopfilter beta offset */
-       reg = MFC_READL(S5P_FIMV_E_H264_LF_BETA_OFFSET);
-       reg &= ~(0x1F);
-       reg |= (p_264->loop_filter_beta & 0x1F);
-       MFC_WRITEL(reg, S5P_FIMV_E_H264_LF_BETA_OFFSET);
-
-       /* rate control config. */
-       reg = MFC_READL(S5P_FIMV_E_RC_CONFIG);
-       /** frame QP */
-       reg &= ~(0xFF);
-       reg |= (p_264->rc_frame_qp & 0xFF);
-       reg &= ~(0x1 << 11);
-       if (!p->rc_frame && !p->rc_mb && p->dynamic_qp)
-               reg |= (0x1 << 11);
-       MFC_WRITEL(reg, S5P_FIMV_E_RC_CONFIG);
-
-       /* frame rate */
-       /* Fix value for H.264, H.263 in the driver */
-       p->rc_frame_delta = FRAME_DELTA_DEFAULT;
-       reg = MFC_READL(S5P_FIMV_E_RC_FRAME_RATE);
-       reg &= ~(0xFFFF << 16);
-       reg |= (p->rc_framerate << 16);
-       reg &= ~(0xFFFF);
-       reg |= p->rc_frame_delta & 0xFFFF;
-       MFC_WRITEL(reg, S5P_FIMV_E_RC_FRAME_RATE);
-
-       /* max & min value of QP for I frame */
-       reg = MFC_READL(S5P_FIMV_E_RC_QP_BOUND);
-       /** max I frame QP */
-       reg &= ~(0xFF << 8);
-       reg |= ((p_264->rc_max_qp & 0xFF) << 8);
-       /** min I frame QP */
-       reg &= ~(0xFF);
-       reg |= p_264->rc_min_qp & 0xFF;
-       MFC_WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND);
-
-       /* max & min value of QP for P/B frame */
-       reg = MFC_READL(S5P_FIMV_E_RC_QP_BOUND_PB);
-       /** max B frame QP */
-       reg &= ~(0xFF << 24);
-       reg |= ((p_264->rc_max_qp_b & 0xFF) << 24);
-       /** min B frame QP */
-       reg &= ~(0xFF << 16);
-       reg |= ((p_264->rc_min_qp_b & 0xFF) << 16);
-       /** max P frame QP */
-       reg &= ~(0xFF << 8);
-       reg |= ((p_264->rc_max_qp_p & 0xFF) << 8);
-       /** min P frame QP */
-       reg &= ~(0xFF);
-       reg |= p_264->rc_min_qp_p & 0xFF;
-       MFC_WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND_PB);
-
-       reg = MFC_READL(S5P_FIMV_E_FIXED_PICTURE_QP);
-       reg &= ~(0xFF << 24);
-       reg |= ((p->config_qp & 0xFF) << 24);
-       reg &= ~(0xFF << 16);
-       reg |= ((p_264->rc_b_frame_qp & 0xFF) << 16);
-       reg &= ~(0xFF << 8);
-       reg |= ((p_264->rc_p_frame_qp & 0xFF) << 8);
-       reg &= ~(0xFF);
-       reg |= (p_264->rc_frame_qp & 0xFF);
-       MFC_WRITEL(reg, S5P_FIMV_E_FIXED_PICTURE_QP);
-
-       MFC_WRITEL(0x0, S5P_FIMV_E_ASPECT_RATIO);
-       MFC_WRITEL(0x0, S5P_FIMV_E_EXTENDED_SAR);
-       if (p_264->ar_vui) {
-               /* aspect ration IDC */
-               reg = 0;
-               reg &= ~(0xff);
-               reg |= p_264->ar_vui_idc;
-               MFC_WRITEL(reg, S5P_FIMV_E_ASPECT_RATIO);
-               if (p_264->ar_vui_idc == 0xFF) {
-                       /* sample  AR info. */
-                       reg = 0;
-                       reg &= ~(0xffffffff);
-                       reg |= p_264->ext_sar_width << 16;
-                       reg |= p_264->ext_sar_height;
-                       MFC_WRITEL(reg, S5P_FIMV_E_EXTENDED_SAR);
-               }
-       }
-       /* intra picture period for H.264 open GOP, value */
-       reg = MFC_READL(S5P_FIMV_E_H264_REFRESH_PERIOD);
-       reg &= ~(0xFFFF);
-       if (p_264->open_gop)
-               reg |= (p_264->open_gop_size & 0xFFFF);
-       MFC_WRITEL(reg, S5P_FIMV_E_H264_REFRESH_PERIOD);
-
-       /* Temporal SVC */
-       mfc_set_temporal_svc_h264(ctx, p_264);
-
-       /* set frame pack sei generation */
-       if (p_264->sei_gen_enable) {
-               /* frame packing enable */
-               reg = MFC_READL(S5P_FIMV_E_H264_OPTIONS);
-               reg |= (1 << 25);
-               MFC_WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
-
-               /* set current frame0 flag & arrangement type */
-               reg = 0;
-               /** current frame0 flag */
-               reg |= ((p_264->sei_fp_curr_frame_0 & 0x1) << 2);
-               /** arrangement type */
-               reg |= (p_264->sei_fp_arrangement_type - 3) & 0x3;
-               MFC_WRITEL(reg, S5P_FIMV_E_H264_FRAME_PACKING_SEI_INFO);
-       }
-
-       if (MFC_FEATURE_SUPPORT(dev, dev->pdata->color_aspect_enc) && p->check_color_range) {
-               reg = MFC_READL(S5P_FIMV_E_VIDEO_SIGNAL_TYPE);
-               /* VIDEO_SIGNAL_TYPE_FLAG */
-               reg |= 0x1 << 31;
-               /* COLOR_RANGE */
-               reg &= ~(0x1 << 25);
-               reg |= p->color_range << 25;
-               if ((p->colour_primaries != 0) && (p->transfer_characteristics != 0) &&
-                               (p->matrix_coefficients != 3)) {
-                       /* COLOUR_DESCRIPTION_PRESENT_FLAG */
-                       reg |= 0x1 << 24;
-                       /* COLOUR_PRIMARIES */
-                       reg &= ~(0xFF << 16);
-                       reg |= p->colour_primaries << 16;
-                       /* TRANSFER_CHARACTERISTICS */
-                       reg &= ~(0xFF << 8);
-                       reg |= p->transfer_characteristics << 8;
-                       /* MATRIX_COEFFICIENTS */
-                       reg &= ~(0xFF);
-                       reg |= p->matrix_coefficients;
-               } else {
-                       reg &= ~(0x1 << 24);
-               }
-               MFC_WRITEL(reg, S5P_FIMV_E_VIDEO_SIGNAL_TYPE);
-               mfc_debug(2, "[HDR] H264 ENC Color aspect: range(%s), pri(%d), trans(%d), mat(%d)\n",
-                               p->color_range ? "Full" : "Limited", p->colour_primaries,
-                               p->transfer_characteristics, p->matrix_coefficients);
-       } else {
-               MFC_WRITEL(0, S5P_FIMV_E_VIDEO_SIGNAL_TYPE);
-       }
-
-       mfc_set_fmo_slice_map_h264(ctx, p_264);
-
-       mfc_debug_leave();
-}
-
-void s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_enc *enc = ctx->enc_priv;
-       struct s5p_mfc_enc_params *p = &enc->params;
-       struct s5p_mfc_mpeg4_enc_params *p_mpeg4 = &p->codec.mpeg4;
-       unsigned int reg = 0;
-
-       mfc_debug_enter();
-
-       mfc_set_enc_params(ctx);
-
-       /* set gop_size with I_FRM_CTRL mode */
-       mfc_set_gop_size(ctx, 1);
-
-       /* profile & level */
-       reg = 0;
-       /** level */
-       reg &= ~(0xFF << 8);
-       reg |= (p_mpeg4->level << 8);
-       /** profile - 0 ~ 1 */
-       reg &= ~(0x3F);
-       reg |= p_mpeg4->profile;
-       MFC_WRITEL(reg, S5P_FIMV_E_PICTURE_PROFILE);
-
-       /* quarter_pixel */
-       /* MFC_WRITEL(p_mpeg4->quarter_pixel, S5P_FIMV_ENC_MPEG4_QUART_PXL); */
-
-       /* qp */
-       reg = MFC_READL(S5P_FIMV_E_FIXED_PICTURE_QP);
-       reg &= ~(0xFF << 24);
-       reg |= ((p->config_qp & 0xFF) << 24);
-       reg &= ~(0xFF << 16);
-       reg |= ((p_mpeg4->rc_b_frame_qp & 0xFF) << 16);
-       reg &= ~(0xFF << 8);
-       reg |= ((p_mpeg4->rc_p_frame_qp & 0xFF) << 8);
-       reg &= ~(0xFF);
-       reg |= (p_mpeg4->rc_frame_qp & 0xFF);
-       MFC_WRITEL(reg, S5P_FIMV_E_FIXED_PICTURE_QP);
-
-       /* frame rate */
-       p->rc_frame_delta = p_mpeg4->vop_frm_delta;
-       reg = MFC_READL(S5P_FIMV_E_RC_FRAME_RATE);
-       reg &= ~(0xFFFF << 16);
-       reg |= (p_mpeg4->vop_time_res << 16);
-       reg &= ~(0xFFFF);
-       reg |= (p_mpeg4->vop_frm_delta & 0xFFFF);
-       MFC_WRITEL(reg, S5P_FIMV_E_RC_FRAME_RATE);
-
-       /* rate control config. */
-       reg = MFC_READL(S5P_FIMV_E_RC_CONFIG);
-       /** frame QP */
-       reg &= ~(0xFF);
-       reg |= (p_mpeg4->rc_frame_qp & 0xFF);
-       MFC_WRITEL(reg, S5P_FIMV_E_RC_CONFIG);
-
-       /* max & min value of QP for I frame */
-       reg = MFC_READL(S5P_FIMV_E_RC_QP_BOUND);
-       /** max I frame QP */
-       reg &= ~(0xFF << 8);
-       reg |= ((p_mpeg4->rc_max_qp & 0xFF) << 8);
-       /** min I frame QP */
-       reg &= ~(0xFF);
-       reg |= (p_mpeg4->rc_min_qp & 0xFF);
-       MFC_WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND);
-
-       /* max & min value of QP for P/B frame */
-       reg = MFC_READL(S5P_FIMV_E_RC_QP_BOUND_PB);
-       /** max B frame QP */
-       reg &= ~(0xFF << 24);
-       reg |= ((p_mpeg4->rc_max_qp_b & 0xFF) << 24);
-       /** min B frame QP */
-       reg &= ~(0xFF << 16);
-       reg |= ((p_mpeg4->rc_min_qp_b & 0xFF) << 16);
-       /** max P frame QP */
-       reg &= ~(0xFF << 8);
-       reg |= ((p_mpeg4->rc_max_qp_p & 0xFF) << 8);
-       /** min P frame QP */
-       reg &= ~(0xFF);
-       reg |= p_mpeg4->rc_min_qp_p & 0xFF;
-       MFC_WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND_PB);
-
-       /* initialize for '0' only setting*/
-       MFC_WRITEL(0x0, S5P_FIMV_E_MPEG4_OPTIONS); /* SEQ_start only */
-       MFC_WRITEL(0x0, S5P_FIMV_E_MPEG4_HEC_PERIOD); /* SEQ_start only */
-
-       mfc_debug_leave();
-}
-
-void s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_enc *enc = ctx->enc_priv;
-       struct s5p_mfc_enc_params *p = &enc->params;
-       struct s5p_mfc_mpeg4_enc_params *p_mpeg4 = &p->codec.mpeg4;
-       unsigned int reg = 0;
-
-       mfc_debug_enter();
-
-       mfc_set_enc_params(ctx);
-
-       /* set gop_size with I_FRM_CTRL mode */
-       mfc_set_gop_size(ctx, 1);
-
-       /* profile & level: supports only baseline profile Level 70 */
-
-       /* qp */
-       reg = MFC_READL(S5P_FIMV_E_FIXED_PICTURE_QP);
-       reg &= ~(0xFF << 24);
-       reg |= ((p->config_qp & 0xFF) << 24);
-       reg &= ~(0xFF << 8);
-       reg |= ((p_mpeg4->rc_p_frame_qp & 0xFF) << 8);
-       reg &= ~(0xFF);
-       reg |= (p_mpeg4->rc_frame_qp & 0xFF);
-       MFC_WRITEL(reg, S5P_FIMV_E_FIXED_PICTURE_QP);
-
-       /* frame rate */
-       /* Fix value for H.264, H.263 in the driver */
-       p->rc_frame_delta = FRAME_DELTA_DEFAULT;
-       reg = MFC_READL(S5P_FIMV_E_RC_FRAME_RATE);
-       reg &= ~(0xFFFF << 16);
-       reg |= (p->rc_framerate << 16);
-       reg &= ~(0xFFFF);
-       reg |= (p->rc_frame_delta & 0xFFFF);
-       MFC_WRITEL(reg, S5P_FIMV_E_RC_FRAME_RATE);
-
-       /* rate control config. */
-       reg = MFC_READL(S5P_FIMV_E_RC_CONFIG);
-       /** frame QP */
-       reg &= ~(0xFF);
-       reg |= (p_mpeg4->rc_frame_qp & 0xFF);
-       MFC_WRITEL(reg, S5P_FIMV_E_RC_CONFIG);
-
-       /* max & min value of QP for I frame */
-       reg = MFC_READL(S5P_FIMV_E_RC_QP_BOUND);
-       /** max I frame QP */
-       reg &= ~(0xFF << 8);
-       reg |= ((p_mpeg4->rc_max_qp & 0xFF) << 8);
-       /** min I frame QP */
-       reg &= ~(0xFF);
-       reg |= (p_mpeg4->rc_min_qp & 0xFF);
-       MFC_WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND);
-
-       /* max & min value of QP for P/B frame */
-       reg = MFC_READL(S5P_FIMV_E_RC_QP_BOUND_PB);
-       /** max P frame QP */
-       reg &= ~(0xFF << 8);
-       reg |= ((p_mpeg4->rc_max_qp_p & 0xFF) << 8);
-       /** min P frame QP */
-       reg &= ~(0xFF);
-       reg |= p_mpeg4->rc_min_qp_p & 0xFF;
-       MFC_WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND_PB);
-
-       mfc_debug_leave();
-}
-
-void s5p_mfc_set_enc_params_vp8(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_enc *enc = ctx->enc_priv;
-       struct s5p_mfc_enc_params *p = &enc->params;
-       struct s5p_mfc_vp8_enc_params *p_vp8 = &p->codec.vp8;
-       unsigned int reg = 0;
-       int i;
-
-       mfc_debug_enter();
-
-       mfc_set_enc_params(ctx);
-
-       if (p_vp8->num_hier_layer & 0x3) {
-               /* set gop_size without i_frm_ctrl mode */
-               mfc_set_gop_size(ctx, 0);
-       } else {
-               /* set gop_size with i_frm_ctrl mode */
-               mfc_set_gop_size(ctx, 1);
-       }
-
-       /* profile*/
-       reg = 0;
-       reg |= (p_vp8->vp8_version) ;
-       MFC_WRITEL(reg, S5P_FIMV_E_PICTURE_PROFILE);
-
-       reg = MFC_READL(S5P_FIMV_E_VP8_OPTION);
-       /* if num_refs_for_p is 2, the performance falls by half */
-       reg &= ~(0x1);
-       reg |= (p->num_refs_for_p - 1) & 0x1;
-       /* vp8 partition is possible as below value: 1/2/4/8 */
-       if (p_vp8->vp8_numberofpartitions & 0x1) {
-               if (p_vp8->vp8_numberofpartitions > 1)
-                       mfc_err_ctx("partition should be even num (%d)\n",
-                                       p_vp8->vp8_numberofpartitions);
-               p_vp8->vp8_numberofpartitions = (p_vp8->vp8_numberofpartitions & ~0x1);
-       }
-       reg &= ~(0xF << 3);
-       reg |= (p_vp8->vp8_numberofpartitions & 0xF) << 3;
-       reg &= ~(0x1 << 10);
-       reg |= (p_vp8->intra_4x4mode_disable & 0x1) << 10;
-       /* Temporal SVC - hier qp enable */
-       reg &= ~(0x1 << 11);
-       reg |= (p_vp8->hier_qp_enable & 0x1) << 11;
-       /* Disable IVF header */
-       reg &= ~(0x1 << 12);
-       reg |= ((p->ivf_header_disable & 0x1) << 12);
-       MFC_WRITEL(reg, S5P_FIMV_E_VP8_OPTION);
-
-       reg = MFC_READL(S5P_FIMV_E_VP8_GOLDEN_FRAME_OPTION);
-       reg &= ~(0x1);
-       reg |= (p_vp8->vp8_goldenframesel & 0x1);
-       reg &= ~(0xFFFF << 1);
-       reg |= (p_vp8->vp8_gfrefreshperiod & 0xFFFF) << 1;
-       MFC_WRITEL(reg, S5P_FIMV_E_VP8_GOLDEN_FRAME_OPTION);
-
-       /* Temporal SVC - layer number */
-       reg = MFC_READL(S5P_FIMV_E_NUM_T_LAYER);
-       reg &= ~(0x7);
-       reg |= p_vp8->num_hier_layer & 0x3;
-       reg &= ~(0x7 << 4);
-       reg |= 0x3 << 4;
-       reg &= ~(0x1 << 8);
-       reg |= (p->hier_bitrate_ctrl & 0x1) << 8;
-       MFC_WRITEL(reg, S5P_FIMV_E_NUM_T_LAYER);
-       mfc_debug(3, "[HIERARCHICAL] hier_qp_enable %d, num_hier_layer %d, NUM_T_LAYER 0x%x\n",
-                       p_vp8->hier_qp_enable, p_vp8->num_hier_layer, reg);
-
-       /* QP & Bitrate for each layer */
-       for (i = 0; i < 3; i++) {
-               MFC_WRITEL(p_vp8->hier_qp_layer[i],
-                               S5P_FIMV_E_HIERARCHICAL_QP_LAYER0 + i * 4);
-               /* If hier_bitrate_ctrl is set to 1, this is meaningless */
-               MFC_WRITEL(p_vp8->hier_bit_layer[i],
-                               S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER0 + i * 4);
-               mfc_debug(3, "[HIERARCHICAL] layer[%d] QP: %#x, bitrate: %#x(FW ctrl: %d)\n",
-                                       i, p_vp8->hier_qp_layer[i],
-                                       p_vp8->hier_bit_layer[i], p->hier_bitrate_ctrl);
-       }
-
-       reg = 0;
-       reg |= (p_vp8->vp8_filtersharpness & 0x7);
-       reg |= (p_vp8->vp8_filterlevel & 0x3f) << 8;
-       MFC_WRITEL(reg, S5P_FIMV_E_VP8_FILTER_OPTION);
-
-       /* qp */
-       reg = MFC_READL(S5P_FIMV_E_FIXED_PICTURE_QP);
-       reg &= ~(0xFF << 24);
-       reg |= ((p->config_qp & 0xFF) << 24);
-       reg &= ~(0xFF << 8);
-       reg |= ((p_vp8->rc_p_frame_qp & 0xFF) << 8);
-       reg &= ~(0xFF);
-       reg |= (p_vp8->rc_frame_qp & 0xFF);
-       MFC_WRITEL(reg, S5P_FIMV_E_FIXED_PICTURE_QP);
-
-       /* frame rate */
-       p->rc_frame_delta = FRAME_DELTA_DEFAULT;
-       reg = MFC_READL(S5P_FIMV_E_RC_FRAME_RATE);
-       reg &= ~(0xFFFF << 16);
-       reg |= (p->rc_framerate << 16);
-       reg &= ~(0xFFFF);
-       reg |= (p->rc_frame_delta & 0xFFFF);
-       MFC_WRITEL(reg, S5P_FIMV_E_RC_FRAME_RATE);
-
-       /* rate control config. */
-       reg = MFC_READL(S5P_FIMV_E_RC_CONFIG);
-       /** frame QP */
-       reg &= ~(0xFF);
-       reg |= (p_vp8->rc_frame_qp & 0xFF);
-       MFC_WRITEL(reg, S5P_FIMV_E_RC_CONFIG);
-
-       /* max & min value of QP for I frame */
-       reg = MFC_READL(S5P_FIMV_E_RC_QP_BOUND);
-       /** max I frame QP */
-       reg &= ~(0xFF << 8);
-       reg |= ((p_vp8->rc_max_qp & 0xFF) << 8);
-       /** min I frame QP */
-       reg &= ~(0xFF);
-       reg |= (p_vp8->rc_min_qp & 0xFF);
-       MFC_WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND);
-
-       /* max & min value of QP for P/B frame */
-       reg = MFC_READL(S5P_FIMV_E_RC_QP_BOUND_PB);
-       /** max P frame QP */
-       reg &= ~(0xFF << 8);
-       reg |= ((p_vp8->rc_max_qp_p & 0xFF) << 8);
-       /** min P frame QP */
-       reg &= ~(0xFF);
-       reg |= p_vp8->rc_min_qp_p & 0xFF;
-       MFC_WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND_PB);
-
-       mfc_debug_leave();
-}
-
-void s5p_mfc_set_enc_params_vp9(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_enc *enc = ctx->enc_priv;
-       struct s5p_mfc_enc_params *p = &enc->params;
-       struct s5p_mfc_vp9_enc_params *p_vp9 = &p->codec.vp9;
-       unsigned int reg = 0;
-       int i;
-
-       mfc_debug_enter();
-
-       mfc_set_enc_params(ctx);
-
-       if (p_vp9->num_hier_layer & 0x3) {
-               /* set gop_size without i_frm_ctrl mode */
-               mfc_set_gop_size(ctx, 0);
-       } else {
-               /* set gop_size with i_frm_ctrl mode */
-               mfc_set_gop_size(ctx, 1);
-       }
-
-       /* profile*/
-       reg = 0;
-       reg |= p_vp9->vp9_version;
-       /* bit depth minus8 */
-       if (ctx->is_10bit) {
-               reg &= ~(0x3F << 17);
-               reg |= (0x2 << 17);
-               reg |= (0x2 << 20);
-       }
-       MFC_WRITEL(reg, S5P_FIMV_E_PICTURE_PROFILE);
-
-       /* for only information about wrong setting */
-       if (ctx->is_422) {
-               if ((p_vp9->vp9_version != S5P_FIMV_E_PROFILE_VP9_PROFILE1) &&
-                       (p_vp9->vp9_version != S5P_FIMV_E_PROFILE_VP9_PROFILE3)) {
-                       mfc_err_ctx("4:2:2 format is not matched with profile(%d)\n",
-                                       p_vp9->vp9_version);
-               }
-       }
-       if (ctx->is_10bit) {
-               if ((p_vp9->vp9_version != S5P_FIMV_E_PROFILE_VP9_PROFILE2) &&
-                       (p_vp9->vp9_version != S5P_FIMV_E_PROFILE_VP9_PROFILE3)) {
-                       mfc_err_ctx("[10BIT] format is not matched with profile(%d)\n",
-                                       p_vp9->vp9_version);
-               }
-       }
-
-       reg = MFC_READL(S5P_FIMV_E_VP9_OPTION);
-       /* if num_refs_for_p is 2, the performance falls by half */
-       reg &= ~(0x1);
-       reg |= (p->num_refs_for_p - 1) & 0x1;
-       reg &= ~(0x1 << 1);
-       reg |= (p_vp9->intra_pu_split_disable & 0x1) << 1;
-       reg &= ~(0x1 << 3);
-       reg |= (p_vp9->max_partition_depth & 0x1) << 3;
-       /* Temporal SVC - hier qp enable */
-       reg &= ~(0x1 << 11);
-       reg |= ((p_vp9->hier_qp_enable & 0x1) << 11);
-       /* Disable IVF header */
-       reg &= ~(0x1 << 12);
-       reg |= ((p->ivf_header_disable & 0x1) << 12);
-       MFC_WRITEL(reg, S5P_FIMV_E_VP9_OPTION);
-
-       reg = MFC_READL(S5P_FIMV_E_VP9_GOLDEN_FRAME_OPTION);
-       reg &= ~(0x1);
-       reg |= (p_vp9->vp9_goldenframesel & 0x1);
-       reg &= ~(0xFFFF << 1);
-       reg |= (p_vp9->vp9_gfrefreshperiod & 0xFFFF) << 1;
-       MFC_WRITEL(reg, S5P_FIMV_E_VP9_GOLDEN_FRAME_OPTION);
-
-       /* Temporal SVC - layer number */
-       reg = MFC_READL(S5P_FIMV_E_NUM_T_LAYER);
-       reg &= ~(0x7);
-       reg |= p_vp9->num_hier_layer & 0x3;
-       reg &= ~(0x7 << 4);
-       reg |= 0x3 << 4;
-       reg &= ~(0x1 << 8);
-       reg |= (p->hier_bitrate_ctrl & 0x1) << 8;
-       MFC_WRITEL(reg, S5P_FIMV_E_NUM_T_LAYER);
-       mfc_debug(3, "[HIERARCHICAL] hier_qp_enable %d, num_hier_layer %d, NUM_T_LAYER 0x%x\n",
-                       p_vp9->hier_qp_enable, p_vp9->num_hier_layer, reg);
-
-       /* QP & Bitrate for each layer */
-       for (i = 0; i < 3; i++) {
-               MFC_WRITEL(p_vp9->hier_qp_layer[i],
-                               S5P_FIMV_E_HIERARCHICAL_QP_LAYER0 + i * 4);
-               /* If hier_bitrate_ctrl is set to 1, this is meaningless */
-               MFC_WRITEL(p_vp9->hier_bit_layer[i],
-                               S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER0 + i * 4);
-               mfc_debug(3, "[HIERARCHICAL] layer[%d] QP: %#x, bitrate: %#x (FW ctrl: %d)\n",
-                                       i, p_vp9->hier_qp_layer[i],
-                                       p_vp9->hier_bit_layer[i], p->hier_bitrate_ctrl);
-       }
-
-       /* qp */
-       reg = MFC_READL(S5P_FIMV_E_FIXED_PICTURE_QP);
-       reg &= ~(0xFF << 24);
-       reg |= ((p->config_qp & 0xFF) << 24);
-       reg &= ~(0xFF << 8);
-       reg |= ((p_vp9->rc_p_frame_qp & 0xFF) << 8);
-       reg &= ~(0xFF);
-       reg |= (p_vp9->rc_frame_qp & 0xFF);
-       MFC_WRITEL(reg, S5P_FIMV_E_FIXED_PICTURE_QP);
-
-       /* frame rate */
-       p->rc_frame_delta = FRAME_DELTA_DEFAULT;
-       reg = MFC_READL(S5P_FIMV_E_RC_FRAME_RATE);
-       reg &= ~(0xFFFF << 16);
-       reg |= (p->rc_framerate << 16);
-       reg &= ~(0xFFFF);
-       reg |= (p->rc_frame_delta & 0xFFFF);
-       MFC_WRITEL(reg, S5P_FIMV_E_RC_FRAME_RATE);
-
-       /* rate control config. */
-       reg = MFC_READL(S5P_FIMV_E_RC_CONFIG);
-       /** frame QP */
-       reg &= ~(0xFF);
-       reg |= (p_vp9->rc_frame_qp & 0xFF);
-       MFC_WRITEL(reg, S5P_FIMV_E_RC_CONFIG);
-
-       /* max & min value of QP for I frame */
-       reg = MFC_READL(S5P_FIMV_E_RC_QP_BOUND);
-       /** max I frame QP */
-       reg &= ~(0xFF << 8);
-       reg |= ((p_vp9->rc_max_qp & 0xFF) << 8);
-       /** min I frame QP */
-       reg &= ~(0xFF);
-       reg |= (p_vp9->rc_min_qp & 0xFF);
-       MFC_WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND);
-
-       /* max & min value of QP for P/B frame */
-       reg = MFC_READL(S5P_FIMV_E_RC_QP_BOUND_PB);
-       /** max P frame QP */
-       reg &= ~(0xFF << 8);
-       reg |= ((p_vp9->rc_max_qp_p & 0xFF) << 8);
-       /** min P frame QP */
-       reg &= ~(0xFF);
-       reg |= p_vp9->rc_min_qp_p & 0xFF;
-       MFC_WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND_PB);
-
-       if (MFC_FEATURE_SUPPORT(dev, dev->pdata->color_aspect_enc) && p->check_color_range) {
-               reg = MFC_READL(S5P_FIMV_E_VIDEO_SIGNAL_TYPE);
-               /* VIDEO_SIGNAL_TYPE_FLAG */
-               reg |= 0x1 << 31;
-               /* COLOR_SPACE: VP9 uses colour_primaries interface for color space */
-               reg &= ~(0x1F << 26);
-               reg |= p->colour_primaries << 26;
-               /* COLOR_RANGE */
-               reg &= ~(0x1 << 25);
-               reg |= p->color_range << 25;
-               MFC_WRITEL(reg, S5P_FIMV_E_VIDEO_SIGNAL_TYPE);
-               mfc_debug(2, "[HDR] VP9 ENC Color aspect: range(%s), space(%d)\n",
-                               p->color_range ? "Full" : "Limited", p->colour_primaries);
-       } else {
-               MFC_WRITEL(0, S5P_FIMV_E_VIDEO_SIGNAL_TYPE);
-       }
-
-       mfc_debug_leave();
-}
-
-void s5p_mfc_set_enc_params_hevc(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_enc *enc = ctx->enc_priv;
-       struct s5p_mfc_enc_params *p = &enc->params;
-       struct s5p_mfc_hevc_enc_params *p_hevc = &p->codec.hevc;
-       unsigned int reg = 0;
-       int i;
-
-       mfc_debug_enter();
-
-       mfc_set_enc_params(ctx);
-
-       if (p_hevc->num_hier_layer & 0x7) {
-               /* set gop_size without i_frm_ctrl mode */
-               mfc_set_gop_size(ctx, 0);
-       } else {
-               /* set gop_size with i_frm_ctrl mode */
-               mfc_set_gop_size(ctx, 1);
-       }
-
-       /* UHD encoding case */
-       if (IS_UHD_RES(ctx)) {
-               p_hevc->level = 51;
-               p_hevc->tier_flag = 0;
-       /* this tier_flag can be changed */
-       }
-
-       /* tier_flag & level & profile */
-       reg = 0;
-       /* profile */
-       reg |= p_hevc->profile & 0xf;
-       /* level */
-       reg &= ~(0xFF << 8);
-       reg |= (p_hevc->level << 8);
-       /* tier_flag - 0 ~ 1 */
-       reg |= (p_hevc->tier_flag << 16);
-       /* bit depth minus8 */
-       if (ctx->is_10bit) {
-               reg &= ~(0x3F << 17);
-               reg |= (0x2 << 17);
-               reg |= (0x2 << 20);
-       }
-       MFC_WRITEL(reg, S5P_FIMV_E_PICTURE_PROFILE);
-
-       /* for only information about wrong setting */
-       if (ctx->is_422) {
-               if ((p_hevc->profile != S5P_FIMV_E_PROFILE_HEVC_MAIN_422_10_INTRA) &&
-                       (p_hevc->profile != S5P_FIMV_E_PROFILE_HEVC_MAIN_422_10)) {
-                       mfc_err_ctx("4:2:2 format is not matched with profile(%d)\n",
-                                       p_hevc->profile);
-               }
-       }
-       if (ctx->is_10bit) {
-               if ((p_hevc->profile != S5P_FIMV_E_PROFILE_HEVC_MAIN_422_10_INTRA) &&
-                       (p_hevc->profile != S5P_FIMV_E_PROFILE_HEVC_MAIN_10) &&
-                       (p_hevc->profile != S5P_FIMV_E_PROFILE_HEVC_MAIN_422_10)) {
-                       mfc_err_ctx("[10BIT] format is not matched with profile(%d)\n",
-                                       p_hevc->profile);
-               }
-       }
-
-       /* max partition depth */
-       reg = MFC_READL(S5P_FIMV_E_HEVC_OPTIONS);
-       reg &= ~(0x3);
-       reg |= (p_hevc->max_partition_depth & 0x1);
-       /* if num_refs_for_p is 2, the performance falls by half */
-       reg &= ~(0x1 << 2);
-       reg |= (p->num_refs_for_p - 1) << 2;
-       reg &= ~(0x3 << 3);
-       reg |= (p_hevc->refreshtype & 0x3) << 3;
-       reg &= ~(0x1 << 5);
-       reg |= (p_hevc->const_intra_period_enable & 0x1) << 5;
-       reg &= ~(0x1 << 6);
-       reg |= (p_hevc->lossless_cu_enable & 0x1) << 6;
-       reg &= ~(0x1 << 7);
-       reg |= (p_hevc->wavefront_enable & 0x1) << 7;
-       reg &= ~(0x1 << 8);
-       reg |= (p_hevc->loopfilter_disable & 0x1) << 8;
-       reg &= ~(0x1 << 9);
-       reg |= (p_hevc->loopfilter_across & 0x1) << 9;
-       reg &= ~(0x1 << 10);
-       reg |= (p_hevc->enable_ltr & 0x1) << 10;
-       reg &= ~(0x1 << 11);
-       reg |= (p_hevc->hier_qp_enable & 0x1) << 11;
-       reg &= ~(0x1 << 13);
-       reg |= (p_hevc->general_pb_enable & 0x1) << 13;
-       reg &= ~(0x1 << 14);
-       reg |= (p_hevc->temporal_id_enable & 0x1) << 14;
-       reg &= ~(0x1 << 15);
-       reg |= (p_hevc->strong_intra_smooth & 0x1) << 15;
-       reg &= ~(0x1 << 16);
-       reg |= (p_hevc->intra_pu_split_disable & 0x1) << 16;
-       reg &= ~(0x1 << 17);
-       reg |= (p_hevc->tmv_prediction_disable & 0x1) << 17;
-       reg &= ~(0x7 << 18);
-       reg |= (p_hevc->max_num_merge_mv & 0x7) << 18;
-       reg &= ~(0x1 << 23);
-       reg |= (p_hevc->encoding_nostartcode_enable & 0x1) << 23;
-       reg &= ~(0x1 << 26);
-       reg |= (p_hevc->prepend_sps_pps_to_idr & 0x1) << 26;
-       /* enable sps pps control in OTF scenario */
-       if (ctx->otf_handle) {
-               reg |= (0x1 << 26);
-               mfc_debug(2, "[OTF] SPS_PPS_CONTROL enabled\n");
-       }
-       /* Weighted Prediction enable */
-       reg &= ~(0x1 << 28);
-       reg |= ((p->weighted_enable & 0x1) << 28);
-       /* 30bit is 32x32 transform. If it is enabled, the performance falls by half */
-       reg &= ~(0x1 << 30);
-       MFC_WRITEL(reg, S5P_FIMV_E_HEVC_OPTIONS);
-       /* refresh period */
-       reg = MFC_READL(S5P_FIMV_E_HEVC_REFRESH_PERIOD);
-       reg &= ~(0xFFFF);
-       reg |= (p_hevc->refreshperiod & 0xFFFF);
-       MFC_WRITEL(reg, S5P_FIMV_E_HEVC_REFRESH_PERIOD);
-       /* loop filter setting */
-       MFC_WRITEL(0, S5P_FIMV_E_HEVC_LF_BETA_OFFSET_DIV2);
-       MFC_WRITEL(0, S5P_FIMV_E_HEVC_LF_TC_OFFSET_DIV2);
-       if (!p_hevc->loopfilter_disable) {
-               MFC_WRITEL(p_hevc->lf_beta_offset_div2, S5P_FIMV_E_HEVC_LF_BETA_OFFSET_DIV2);
-               MFC_WRITEL(p_hevc->lf_tc_offset_div2, S5P_FIMV_E_HEVC_LF_TC_OFFSET_DIV2);
-       }
-       /* long term reference */
-       if (p_hevc->enable_ltr) {
-               reg = 0;
-               reg |= (p_hevc->store_ref & 0x3);
-               reg &= ~(0x3 << 2);
-               reg |= (p_hevc->user_ref & 0x3) << 2;
-               MFC_WRITEL(reg, S5P_FIMV_E_HEVC_NAL_CONTROL);
-       }
-
-       /* Temporal SVC - qp type, layer number */
-       reg = MFC_READL(S5P_FIMV_E_NUM_T_LAYER);
-       reg &= ~(0x1 << 3);
-       reg |= (p_hevc->hier_qp_type & 0x1) << 3;
-       reg &= ~(0x7);
-       reg |= p_hevc->num_hier_layer & 0x7;
-       reg &= ~(0x7 << 4);
-       if (p_hevc->hier_ref_type) {
-               reg |= 0x1 << 7;
-               reg |= (p->num_hier_max_layer & 0x7) << 4;
-       } else {
-               reg &= ~(0x1 << 7);
-               reg |= 0x7 << 4;
-       }
-       reg &= ~(0x1 << 8);
-       reg |= (p->hier_bitrate_ctrl & 0x1) << 8;
-       MFC_WRITEL(reg, S5P_FIMV_E_NUM_T_LAYER);
-       mfc_debug(3, "[HIERARCHICAL] hier_qp_enable %d, enable_ltr %d, "
-               "num_hier_layer %d, max_layer %d, hier_ref_type %d, NUM_T_LAYER 0x%x\n",
-               p_hevc->hier_qp_enable, p_hevc->enable_ltr, p_hevc->num_hier_layer,
-               p->num_hier_max_layer, p_hevc->hier_ref_type, reg);
-
-       /* QP & Bitrate for each layer */
-       for (i = 0; i < 7; i++) {
-               MFC_WRITEL(p_hevc->hier_qp_layer[i],
-                       S5P_FIMV_E_HIERARCHICAL_QP_LAYER0 + i * 4);
-               MFC_WRITEL(p_hevc->hier_bit_layer[i],
-                       S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER0 + i * 4);
-               mfc_debug(3, "[HIERARCHICAL] layer[%d] QP: %#x, bitrate: %d(FW ctrl: %d)\n",
-                                       i, p_hevc->hier_qp_layer[i],
-                                       p_hevc->hier_bit_layer[i], p->hier_bitrate_ctrl);
-       }
-
-       /* rate control config. */
-       reg = MFC_READL(S5P_FIMV_E_RC_CONFIG);
-       /** frame QP */
-       reg &= ~(0xFF);
-       reg |= (p_hevc->rc_frame_qp & 0xFF);
-       MFC_WRITEL(reg, S5P_FIMV_E_RC_CONFIG);
-
-       /* frame rate */
-       p->rc_frame_delta = FRAME_DELTA_DEFAULT;
-       reg = MFC_READL(S5P_FIMV_E_RC_FRAME_RATE);
-       reg &= ~(0xFFFF << 16);
-       reg |= (p->rc_framerate << 16);
-       reg &= ~(0xFFFF);
-       reg |= (p->rc_frame_delta & 0xFFFF);
-       MFC_WRITEL(reg, S5P_FIMV_E_RC_FRAME_RATE);
-
-       /* max & min value of QP for I frame */
-       reg = MFC_READL(S5P_FIMV_E_RC_QP_BOUND);
-       /** max I frame QP */
-       reg &= ~(0xFF << 8);
-       reg |= ((p_hevc->rc_max_qp & 0xFF) << 8);
-       /** min I frame QP */
-       reg &= ~(0xFF);
-       reg |= (p_hevc->rc_min_qp & 0xFF);
-       MFC_WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND);
-
-       /* max & min value of QP for P/B frame */
-       reg = MFC_READL(S5P_FIMV_E_RC_QP_BOUND_PB);
-       /** max B frame QP */
-       reg &= ~(0xFF << 24);
-       reg |= ((p_hevc->rc_max_qp_b & 0xFF) << 24);
-       /** min B frame QP */
-       reg &= ~(0xFF << 16);
-       reg |= ((p_hevc->rc_min_qp_b & 0xFF) << 16);
-       /** max P frame QP */
-       reg &= ~(0xFF << 8);
-       reg |= ((p_hevc->rc_max_qp_p & 0xFF) << 8);
-       /** min P frame QP */
-       reg &= ~(0xFF);
-       reg |= p_hevc->rc_min_qp_p & 0xFF;
-       MFC_WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND_PB);
-
-       reg = MFC_READL(S5P_FIMV_E_FIXED_PICTURE_QP);
-       reg &= ~(0xFF << 24);
-       reg |= ((p->config_qp & 0xFF) << 24);
-       reg &= ~(0xFF << 16);
-       reg |= ((p_hevc->rc_b_frame_qp & 0xFF) << 16);
-       reg &= ~(0xFF << 8);
-       reg |= ((p_hevc->rc_p_frame_qp & 0xFF) << 8);
-       reg &= ~(0xFF);
-       reg |= (p_hevc->rc_frame_qp & 0xFF);
-       MFC_WRITEL(reg, S5P_FIMV_E_FIXED_PICTURE_QP);
-
-       /* ROI enable: it must set on SEQ_START only for HEVC encoder */
-       reg = MFC_READL(S5P_FIMV_E_RC_ROI_CTRL);
-       reg &= ~(0x1);
-       reg |= (p->roi_enable);
-       MFC_WRITEL(reg, S5P_FIMV_E_RC_ROI_CTRL);
-       mfc_debug(3, "[ROI] HEVC ROI enable\n");
-
-       if (MFC_FEATURE_SUPPORT(dev, dev->pdata->color_aspect_enc) && p->check_color_range) {
-               reg = MFC_READL(S5P_FIMV_E_VIDEO_SIGNAL_TYPE);
-               /* VIDEO_SIGNAL_TYPE_FLAG */
-               reg |= 0x1 << 31;
-               /* COLOR_RANGE */
-               reg &= ~(0x1 << 25);
-               reg |= p->color_range << 25;
-               if ((p->colour_primaries != 0) && (p->transfer_characteristics != 0) &&
-                               (p->matrix_coefficients != 3)) {
-                       /* COLOUR_DESCRIPTION_PRESENT_FLAG */
-                       reg |= 0x1 << 24;
-                       /* COLOUR_PRIMARIES */
-                       reg &= ~(0xFF << 16);
-                       reg |= p->colour_primaries << 16;
-                       /* TRANSFER_CHARACTERISTICS */
-                       reg &= ~(0xFF << 8);
-                       reg |= p->transfer_characteristics << 8;
-                       /* MATRIX_COEFFICIENTS */
-                       reg &= ~(0xFF);
-                       reg |= p->matrix_coefficients;
-               } else {
-                       reg &= ~(0x1 << 24);
-               }
-               MFC_WRITEL(reg, S5P_FIMV_E_VIDEO_SIGNAL_TYPE);
-               mfc_debug(2, "[HDR] HEVC ENC Color aspect: range(%s), pri(%d), trans(%d), mat(%d)\n",
-                               p->color_range ? "Full" : "Limited", p->colour_primaries,
-                               p->transfer_characteristics, p->matrix_coefficients);
-       } else {
-               MFC_WRITEL(0, S5P_FIMV_E_VIDEO_SIGNAL_TYPE);
-       }
-
-       if (MFC_FEATURE_SUPPORT(dev, dev->pdata->static_info_enc) &&
-                       p->static_info_enable && ctx->is_10bit) {
-               reg = MFC_READL(S5P_FIMV_E_HEVC_OPTIONS_2);
-               /* HDR_STATIC_INFO_ENABLE */
-               reg |= p->static_info_enable;
-               MFC_WRITEL(reg, S5P_FIMV_E_HEVC_OPTIONS_2);
-               /* MAX_PIC_AVERAGE_LIGHT & MAX_CONTENT_LIGHT */
-               reg = p->max_pic_average_light;
-               reg |= (p->max_content_light << 16);
-               MFC_WRITEL(reg, S5P_FIMV_E_CONTENT_LIGHT_LEVEL_INFO_SEI);
-               /* MAX_DISPLAY_LUMINANCE */
-               MFC_WRITEL(p->max_display_luminance, S5P_FIMV_E_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_0);
-               /* MIN DISPLAY LUMINANCE */
-               MFC_WRITEL(p->min_display_luminance, S5P_FIMV_E_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_1);
-               /* WHITE_POINT */
-               MFC_WRITEL(p->white_point, S5P_FIMV_E_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_2);
-               /* DISPLAY PRIMARIES_0 */
-               MFC_WRITEL(p->display_primaries_0, S5P_FIMV_E_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_3);
-               /* DISPLAY PRIMARIES_1 */
-               MFC_WRITEL(p->display_primaries_1, S5P_FIMV_E_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_4);
-               /* DISPLAY PRIMARIES_2 */
-               MFC_WRITEL(p->display_primaries_2, S5P_FIMV_E_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_5);
-
-               mfc_debug(2, "[HDR] HEVC ENC static info: enable(%d), max_pic(0x%x), max_content(0x%x)\n",
-                               p->static_info_enable, p->max_pic_average_light, p->max_content_light);
-               mfc_debug(2, "[HDR] max_disp(0x%x), min_disp(0x%x), white_point(0x%x)\n",
-                               p->max_display_luminance, p->min_display_luminance, p->white_point);
-               mfc_debug(2, "[HDR] disp_pri_0(0x%x), disp_pri_1(0x%x), disp_pri_2(0x%x)\n",
-                               p->display_primaries_0, p->display_primaries_1, p->display_primaries_2);
-       } else {
-               reg = MFC_READL(S5P_FIMV_E_HEVC_OPTIONS_2);
-               /* HDR_STATIC_INFO_ENABLE */
-               reg &=  ~(0x1);
-               MFC_WRITEL(reg, S5P_FIMV_E_HEVC_OPTIONS_2);
-       }
-
-       mfc_debug_leave();
-}
-
-void s5p_mfc_set_enc_params_bpg(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_enc *enc = ctx->enc_priv;
-       struct s5p_mfc_enc_params *p = &enc->params;
-       struct s5p_mfc_bpg_enc_params *p_bpg = &p->codec.bpg;
-       unsigned int reg = 0;
-
-       mfc_set_enc_params(ctx);
-
-       /* extension tag */
-       reg = p_bpg->thumb_size + p_bpg->exif_size;
-       MFC_WRITEL(reg, S5P_FIMV_E_BPG_EXTENSION_DATA_SIZE);
-       mfc_debug(3, "main image extension size %d (thumbnail: %d, exif: %d)\n",
-                       reg, p_bpg->thumb_size, p_bpg->exif_size);
-
-       /* profile & level */
-       reg = 0;
-       /** profile */
-       reg &= ~(0xF);
-       /* bit depth minus8 */
-       if (ctx->is_10bit) {
-               reg &= ~(0x3F << 17);
-               reg |= (0x2 << 17);
-               reg |= (0x2 << 20);
-               /* fixed profile */
-               if (ctx->is_422)
-                       reg |= 0x1;
-       }
-       MFC_WRITEL(reg, S5P_FIMV_E_PICTURE_PROFILE);
-}
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_enc_param.h b/drivers/media/platform/exynos/mfc/s5p_mfc_enc_param.h
deleted file mode 100644 (file)
index 86afc7e..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_enc_param.h
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __S5P_MFC_ENC_PARAM_H
-#define __S5P_MFC_ENC_PARAM_H __FILE__
-
-#include "s5p_mfc_common.h"
-
-void s5p_mfc_set_slice_mode(struct s5p_mfc_ctx *ctx);
-void s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx);
-void s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx);
-void s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx);
-void s5p_mfc_set_enc_params_vp8(struct s5p_mfc_ctx *ctx);
-void s5p_mfc_set_enc_params_vp9(struct s5p_mfc_ctx *ctx);
-void s5p_mfc_set_enc_params_hevc(struct s5p_mfc_ctx *ctx);
-void s5p_mfc_set_enc_params_bpg(struct s5p_mfc_ctx *ctx);
-
-#endif /* __S5P_MFC_ENC_PARAM_H */
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_enc_vb2_ops.c b/drivers/media/platform/exynos/mfc/s5p_mfc_enc_vb2_ops.c
deleted file mode 100644 (file)
index bc2e872..0000000
+++ /dev/null
@@ -1,478 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_enc_vb2_ops.c
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include "s5p_mfc_common.h"
-
-#include "s5p_mfc_hwlock.h"
-#include "s5p_mfc_nal_q.h"
-#include "s5p_mfc_opr.h"
-#include "s5p_mfc_sync.h"
-
-#include "s5p_mfc_qos.h"
-#include "s5p_mfc_queue.h"
-#include "s5p_mfc_utils.h"
-#include "s5p_mfc_buf.h"
-#include "s5p_mfc_mem.h"
-
-static int s5p_mfc_enc_queue_setup(struct vb2_queue *vq,
-                               unsigned int *buf_count, unsigned int *plane_count,
-                               unsigned int psize[], struct device *alloc_devs[])
-{
-       struct s5p_mfc_dev *dev;
-       struct s5p_mfc_ctx *ctx = vq->drv_priv;
-       struct s5p_mfc_enc *enc = ctx->enc_priv;
-       struct s5p_mfc_raw_info *raw;
-       int i;
-
-       mfc_debug_enter();
-
-       dev = ctx->dev;
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return -EINVAL;
-       }
-
-       if (ctx->state != MFCINST_GOT_INST &&
-           vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-               mfc_err_ctx("invalid state: %d\n", ctx->state);
-               return -EINVAL;
-       }
-       if (ctx->state >= MFCINST_FINISHING &&
-           vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               mfc_err_ctx("invalid state: %d\n", ctx->state);
-               return -EINVAL;
-       }
-
-       if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-               mfc_debug(4, "enc dst\n");
-               if (ctx->dst_fmt)
-                       *plane_count = ctx->dst_fmt->mem_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] = enc->dst_buf_size;
-               alloc_devs[0] = dev->device;
-       } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               mfc_debug(4, "enc src\n");
-               raw = &ctx->raw_buf;
-
-               if (ctx->src_fmt)
-                       *plane_count = ctx->src_fmt->mem_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;
-
-               if (*plane_count == 1) {
-                       psize[0] = raw->total_plane_size;
-                       alloc_devs[0] = dev->device;
-               } else {
-                       for (i = 0; i < *plane_count; i++) {
-                               psize[i] = raw->plane_size[i];
-                               alloc_devs[i] = dev->device;
-                       }
-               }
-       } else {
-               mfc_err_ctx("invalid queue type: %d\n", vq->type);
-               return -EINVAL;
-       }
-
-       mfc_debug(2, "buf_count: %d, plane_count: %d, type: %#x\n",
-                       *buf_count, *plane_count, vq->type);
-       for (i = 0; i < *plane_count; i++)
-               mfc_debug(2, "plane[%d] size: %d\n", i, psize[i]);
-
-       mfc_debug_leave();
-
-       return 0;
-}
-
-static void s5p_mfc_enc_unlock(struct vb2_queue *q)
-{
-       struct s5p_mfc_ctx *ctx = q->drv_priv;
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       mutex_unlock(&dev->mfc_mutex);
-}
-
-static void s5p_mfc_enc_lock(struct vb2_queue *q)
-{
-       struct s5p_mfc_ctx *ctx = q->drv_priv;
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       mutex_lock(&dev->mfc_mutex);
-}
-
-static int s5p_mfc_enc_buf_init(struct vb2_buffer *vb)
-{
-       struct vb2_queue *vq = vb->vb2_queue;
-       struct s5p_mfc_ctx *ctx = vq->drv_priv;
-       int ret;
-
-       mfc_debug_enter();
-
-       if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-               ret = s5p_mfc_check_vb_with_fmt(ctx->dst_fmt, vb);
-               if (ret < 0)
-                       return ret;
-
-               if (call_cop(ctx, init_buf_ctrls, ctx, MFC_CTRL_TYPE_DST,
-                                       vb->index) < 0)
-                       mfc_err_ctx("failed in init_buf_ctrls\n");
-
-       } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               ret = s5p_mfc_check_vb_with_fmt(ctx->src_fmt, vb);
-               if (ret < 0)
-                       return ret;
-
-               if (call_cop(ctx, init_buf_ctrls, ctx, MFC_CTRL_TYPE_SRC,
-                                       vb->index) < 0)
-                       mfc_err_ctx("failed in init_buf_ctrls\n");
-       } else {
-               mfc_err_ctx("inavlid queue type: %d\n", vq->type);
-               return -EINVAL;
-       }
-
-       mfc_debug_leave();
-
-       return 0;
-}
-
-static int s5p_mfc_enc_buf_prepare(struct vb2_buffer *vb)
-{
-       struct vb2_queue *vq = vb->vb2_queue;
-       struct s5p_mfc_ctx *ctx = vq->drv_priv;
-       struct s5p_mfc_enc *enc = ctx->enc_priv;
-       struct s5p_mfc_raw_info *raw;
-       unsigned int index = vb->index;
-       struct s5p_mfc_buf *buf = vb_to_mfc_buf(vb);
-       struct dma_buf *bufcon_dmabuf[MFC_MAX_PLANES];
-       int i, mem_get_count = 0;
-       size_t buf_size;
-
-       mfc_debug_enter();
-
-       if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-               buf_size = vb2_plane_size(vb, 0);
-               mfc_debug(2, "[STREAM] vb size: %lu, calc size: %u\n",
-                       buf_size, enc->dst_buf_size);
-
-               if (buf_size < enc->dst_buf_size) {
-                       mfc_err_ctx("[STREAM] size(%d) is smaller than (%d)\n",
-                                       buf_size, enc->dst_buf_size);
-                       return -EINVAL;
-               }
-
-               buf->addr[0][0] = s5p_mfc_mem_get_daddr_vb(vb, 0);
-       } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               raw = &ctx->raw_buf;
-               if (ctx->src_fmt->mem_planes == 1) {
-                       buf_size = vb2_plane_size(vb, 0);
-                       mfc_debug(2, "[FRAME] single plane vb size: %lu, calc size: %d\n",
-                                       buf_size, raw->total_plane_size);
-                       if (buf_size < raw->total_plane_size) {
-                               mfc_err_ctx("[FRAME] single plane size(%d) is smaller than (%d)\n",
-                                               buf_size, raw->total_plane_size);
-                               return -EINVAL;
-                       }
-               } else {
-                       for (i = 0; i < ctx->src_fmt->mem_planes; i++) {
-                               buf_size = vb2_plane_size(vb, i);
-                               mfc_debug(2, "[FRAME] plane[%d] vb size: %lu, calc size: %d\n",
-                                               i, buf_size, raw->plane_size[i]);
-                               if (buf_size < raw->plane_size[i]) {
-                                       mfc_err_ctx("[FRAME] plane[%d] size(%d) is smaller than (%d)\n",
-                                                       i, buf_size, raw->plane_size[i]);
-                                       return -EINVAL;
-                               }
-                       }
-               }
-
-               for (i = 0; i < ctx->src_fmt->mem_planes; i++) {
-                       bufcon_dmabuf[i] = dma_buf_get(vb->planes[i].m.fd);
-                       if (IS_ERR(bufcon_dmabuf[i])) {
-                               mfc_err_ctx("failed to get bufcon dmabuf\n");
-                               goto err_mem_put;
-                       }
-
-                       mem_get_count++;
-                       buf->num_bufs_in_batch = s5p_mfc_bufcon_get_buf_count(bufcon_dmabuf[i]);
-                       mfc_debug(3, "[BUFCON] num bufs in batch: %d\n", buf->num_bufs_in_batch);
-                       if (buf->num_bufs_in_batch == 0) {
-                               mfc_err_ctx("[BUFCON] bufs count couldn't be zero\n");
-                               goto err_mem_put;
-                       }
-
-                       if (buf->num_bufs_in_batch < 0)
-                               buf->num_bufs_in_batch = 0;
-
-                       if (!ctx->batch_mode && buf->num_bufs_in_batch > 0) {
-                               ctx->batch_mode = 1;
-                               mfc_debug(2, "[BUFCON] buffer batch mode enable\n");
-                       }
-
-                       if (buf->num_bufs_in_batch > 0) {
-                               if (s5p_mfc_bufcon_get_daddr(ctx, buf, bufcon_dmabuf[i], i)) {
-                                       mfc_err_ctx("[BUFCON] failed to get daddr[%d] in buffer container\n", i);
-                                       goto err_mem_put;
-                               }
-
-                               ctx->framerate = buf->num_valid_bufs * ENC_DEFAULT_CAM_CAPTURE_FPS;
-                               mfc_debug(3, "[BUFCON] framerate: %ld\n", ctx->framerate);
-
-                               dma_buf_put(bufcon_dmabuf[i]);
-                       } else {
-                               dma_addr_t start_raw;
-
-                               dma_buf_put(bufcon_dmabuf[i]);
-                               start_raw = s5p_mfc_mem_get_daddr_vb(vb, 0);
-                               if (start_raw == 0) {
-                                       mfc_err_ctx("Plane mem not allocated\n");
-                                       return -ENOMEM;
-                               }
-                               if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12N) {
-                                       buf->addr[0][0] = start_raw;
-                                       buf->addr[0][1] = NV12N_CBCR_BASE(start_raw,
-                                                       ctx->img_width,
-                                                       ctx->img_height);
-                               } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_YUV420N) {
-                                       buf->addr[0][0] = start_raw;
-                                       buf->addr[0][1] = YUV420N_CB_BASE(start_raw,
-                                                       ctx->img_width,
-                                                       ctx->img_height);
-                                       buf->addr[0][2] = YUV420N_CR_BASE(start_raw,
-                                                       ctx->img_width,
-                                                       ctx->img_height);
-                               } else {
-                                       buf->addr[0][i] = s5p_mfc_mem_get_daddr_vb(vb, i);
-                               }
-                       }
-               }
-
-               if (call_cop(ctx, to_buf_ctrls, ctx, &ctx->src_ctrls[index]) < 0)
-                       mfc_err_ctx("failed in to_buf_ctrls\n");
-       } else {
-               mfc_err_ctx("inavlid queue type: %d\n", vq->type);
-               return -EINVAL;
-       }
-
-       mfc_debug_leave();
-       return 0;
-
-err_mem_put:
-       for (i = 0; i < mem_get_count; i++)
-               dma_buf_put(bufcon_dmabuf[i]);
-
-       return -ENOMEM;
-}
-
-static void s5p_mfc_enc_buf_finish(struct vb2_buffer *vb)
-{
-       struct vb2_queue *vq = vb->vb2_queue;
-       struct s5p_mfc_ctx *ctx = vq->drv_priv;
-       unsigned int index = vb->index;
-
-
-       if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-               if (call_cop(ctx, to_ctx_ctrls, ctx, &ctx->dst_ctrls[index]) < 0)
-                       mfc_err_ctx("failed in to_ctx_ctrls\n");
-       } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               if (call_cop(ctx, to_ctx_ctrls, ctx, &ctx->src_ctrls[index]) < 0)
-                       mfc_err_ctx("failed in to_ctx_ctrls\n");
-       }
-}
-
-static void s5p_mfc_enc_buf_cleanup(struct vb2_buffer *vb)
-{
-       struct vb2_queue *vq = vb->vb2_queue;
-       struct s5p_mfc_ctx *ctx = vq->drv_priv;
-       unsigned int index = vb->index;
-
-       mfc_debug_enter();
-
-       if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-               if (call_cop(ctx, cleanup_buf_ctrls, ctx,
-                                       MFC_CTRL_TYPE_DST, index) < 0)
-                       mfc_err_ctx("failed in cleanup_buf_ctrls\n");
-       } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               if (call_cop(ctx, cleanup_buf_ctrls, ctx,
-                                       MFC_CTRL_TYPE_SRC, index) < 0)
-                       mfc_err_ctx("failed in cleanup_buf_ctrls\n");
-       } else {
-               mfc_err_ctx("s5p_mfc_enc_buf_cleanup: unknown queue type\n");
-       }
-
-       mfc_debug_leave();
-}
-
-static int s5p_mfc_enc_start_streaming(struct vb2_queue *q, unsigned int count)
-{
-       struct s5p_mfc_ctx *ctx = q->drv_priv;
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       /* If context is ready then dev = work->data;schedule it to run */
-       if (s5p_mfc_enc_ctx_ready(ctx)) {
-               s5p_mfc_set_bit(ctx->num, &dev->work_bits);
-       }
-
-       s5p_mfc_try_run(dev);
-
-       return 0;
-}
-
-static void s5p_mfc_enc_stop_streaming(struct vb2_queue *q)
-{
-       struct s5p_mfc_ctx *ctx = q->drv_priv;
-       struct s5p_mfc_dev *dev = ctx->dev;
-       int index = 0;
-       int aborted = 0;
-       int ret = 0;
-
-       mfc_info_ctx("enc stop_streaming is called, hwlock : %d, type : %d\n",
-                               test_bit(ctx->num, &dev->hwlock.bits), q->type);
-       MFC_TRACE_CTX("** ENC streamoff(type:%d)\n", q->type);
-
-       /* If a H/W operation is in progress, wait for it complete */
-       if (need_to_wait_nal_abort(ctx)) {
-               if (s5p_mfc_wait_for_done_ctx(ctx, S5P_FIMV_R2H_CMD_NAL_ABORT_RET)) {
-                       mfc_err_ctx("time out during nal abort\n");
-                       s5p_mfc_cleanup_work_bit_and_try_run(ctx);
-               }
-               aborted = 1;
-       }
-       MFC_TRACE_CTX_HWLOCK("**ENC streamoff(type:%d)\n", q->type);
-       ret = s5p_mfc_get_hwlock_ctx(ctx);
-       if (ret < 0) {
-               mfc_err_ctx("Failed to get hwlock\n");
-               return;
-       }
-
-       if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-               s5p_mfc_cleanup_enc_dst_queue(ctx);
-
-               while (index < MFC_MAX_BUFFERS) {
-                       index = find_next_bit(&ctx->dst_ctrls_avail,
-                                       MFC_MAX_BUFFERS, index);
-                       if (index < MFC_MAX_BUFFERS)
-                               call_cop(ctx, reset_buf_ctrls, &ctx->dst_ctrls[index]);
-                       index++;
-               }
-       } else if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               if (ctx->state == MFCINST_RUNNING) {
-                       s5p_mfc_change_state(ctx, MFCINST_FINISHING);
-                       s5p_mfc_set_bit(ctx->num, &dev->work_bits);
-
-                       while (s5p_mfc_get_buf(&ctx->buf_queue_lock, &ctx->dst_buf_queue, MFC_BUF_NO_TOUCH_USED)) {
-                               ret = s5p_mfc_just_run(dev, ctx->num);
-                               if (ret) {
-                                       mfc_err_ctx("Failed to run MFC\n");
-                                       break;
-                               }
-                               if (s5p_mfc_wait_for_done_ctx(ctx, S5P_FIMV_R2H_CMD_FRAME_DONE_RET)) {
-                                       mfc_err_ctx("Waiting for LAST_SEQ timed out\n");
-                                       break;
-                               }
-                               if (ctx->state == MFCINST_RUNNING) {
-                                       mfc_debug(2, "all encoded buffers out\n");
-                                       break;
-                               }
-                       }
-               }
-
-               s5p_mfc_move_all_bufs(&ctx->buf_queue_lock, &ctx->src_buf_queue,
-                               &ctx->ref_buf_queue, MFC_QUEUE_ADD_BOTTOM);
-               s5p_mfc_cleanup_enc_src_queue(ctx);
-
-               while (index < MFC_MAX_BUFFERS) {
-                       index = find_next_bit(&ctx->src_ctrls_avail,
-                                       MFC_MAX_BUFFERS, index);
-                       if (index < MFC_MAX_BUFFERS)
-                               call_cop(ctx, reset_buf_ctrls, &ctx->src_ctrls[index]);
-                       index++;
-               }
-       }
-
-       if (aborted || ctx->state == MFCINST_FINISHING)
-               s5p_mfc_change_state(ctx, MFCINST_RUNNING);
-
-       mfc_debug(2, "buffer cleanup is done in stop_streaming, type : %d\n", q->type);
-
-       s5p_mfc_clear_bit(ctx->num, &dev->work_bits);
-       s5p_mfc_release_hwlock_ctx(ctx);
-
-       if (s5p_mfc_is_work_to_do(dev))
-               queue_work(dev->butler_wq, &dev->butler_work);
-}
-
-static void s5p_mfc_enc_buf_queue(struct vb2_buffer *vb)
-{
-       struct vb2_queue *vq = vb->vb2_queue;
-       struct s5p_mfc_ctx *ctx = vq->drv_priv;
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_buf *buf = vb_to_mfc_buf(vb);
-       int i;
-
-       mfc_debug_enter();
-
-       buf->next_index = 0;
-       buf->done_index = 0;
-
-       if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-               mfc_debug(2, "[BUFINFO] ctx[%d] add dst index: %d, addr: 0x%08llx\n",
-                               ctx->num, vb->index, buf->addr[0][0]);
-
-               /* Mark destination as available for use by MFC */
-               s5p_mfc_add_tail_buf(&ctx->buf_queue_lock, &ctx->dst_buf_queue, buf);
-       } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-               for (i = 0; i < ctx->src_fmt->mem_planes; i++)
-                       mfc_debug(2, "[BUFINFO] ctx[%d] add src index: %d, addr[%d]: 0x%08llx\n",
-                                       ctx->num, vb->index, i, buf->addr[0][i]);
-               s5p_mfc_add_tail_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, buf);
-
-               if (debug_ts == 1)
-                       mfc_info_ctx("[TS] framerate: %ld, timestamp: %lld\n",
-                                       ctx->framerate, buf->vb.vb2_buf.timestamp);
-
-               s5p_mfc_qos_update_last_framerate(ctx, buf->vb.vb2_buf.timestamp);
-               s5p_mfc_qos_update_framerate(ctx);
-       } else {
-               mfc_err_ctx("unsupported buffer type (%d)\n", vq->type);
-       }
-
-       if (s5p_mfc_enc_ctx_ready(ctx)) {
-               s5p_mfc_set_bit(ctx->num, &dev->work_bits);
-       }
-       s5p_mfc_try_run(dev);
-
-       mfc_debug_leave();
-}
-
-struct vb2_ops s5p_mfc_enc_qops = {
-       .queue_setup            = s5p_mfc_enc_queue_setup,
-       .wait_prepare           = s5p_mfc_enc_unlock,
-       .wait_finish            = s5p_mfc_enc_lock,
-       .buf_init               = s5p_mfc_enc_buf_init,
-       .buf_prepare            = s5p_mfc_enc_buf_prepare,
-       .buf_finish             = s5p_mfc_enc_buf_finish,
-       .buf_cleanup            = s5p_mfc_enc_buf_cleanup,
-       .start_streaming        = s5p_mfc_enc_start_streaming,
-       .stop_streaming         = s5p_mfc_enc_stop_streaming,
-       .buf_queue              = s5p_mfc_enc_buf_queue,
-};
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_hwfc_internal.h b/drivers/media/platform/exynos/mfc/s5p_mfc_hwfc_internal.h
deleted file mode 100644 (file)
index c505bbe..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_hwfc_internal.h
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __S5P_MFC_HWFC_INTERNAL_H
-#define __S5P_MFC_HWFC_INTERNAL_H __FILE__
-
-#include "s5p_mfc_common.h"
-
-/*
- * RGB encoding information to avoid confusion.
- *
- * V4L2_PIX_FMT_ARGB32 takes ARGB data like below.
- * MSB                              LSB
- * 3       2       1
- * 2       4       6       8       0
- * |B......BG......GR......RA......A|
- */
-struct s5p_mfc_fmt enc_hwfc_formats[] = {
-       {
-               .name = "4:2:0 2 Planes Y/CbCr single",
-               .fourcc = V4L2_PIX_FMT_NV12N,
-               .codec_mode = MFC_FORMATS_NO_CODEC,
-               .type = MFC_FMT_FRAME,
-               .num_planes = 2,
-               .mem_planes = 1,
-       },
-       {
-               .name = "H264 Encoded Stream",
-               .fourcc = V4L2_PIX_FMT_H264,
-               .codec_mode = S5P_FIMV_CODEC_H264_ENC,
-               .type = MFC_FMT_STREAM,
-               .num_planes = 1,
-               .mem_planes = 1,
-       },
-       {
-               .name = "HEVC Encoded Stream",
-               .fourcc = V4L2_PIX_FMT_HEVC,
-               .codec_mode = S5P_FIMV_CODEC_HEVC_ENC,
-               .type = MFC_FMT_STREAM,
-               .num_planes = 1,
-               .mem_planes = 1,
-       },
-};
-
-#define NUM_FORMATS ARRAY_SIZE(enc_hwfc_formats)
-
-#endif /* __S5P_MFC_HWFC_INTERNAL_H */
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_hwlock.c b/drivers/media/platform/exynos/mfc/s5p_mfc_hwlock.c
deleted file mode 100644 (file)
index cee635d..0000000
+++ /dev/null
@@ -1,1007 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_hwlock.c
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include "s5p_mfc_hwlock.h"
-
-#include "s5p_mfc_nal_q.h"
-#include "s5p_mfc_otf.h"
-#include "s5p_mfc_opr.h"
-#include "s5p_mfc_sync.h"
-
-#include "s5p_mfc_inst.h"
-#include "s5p_mfc_pm.h"
-#include "s5p_mfc_cmd.h"
-#include "s5p_mfc_cal.h"
-#include "s5p_mfc_reg.h"
-
-#include "s5p_mfc_queue.h"
-#include "s5p_mfc_utils.h"
-
-static inline void mfc_print_hwlock(struct s5p_mfc_dev *dev)
-{
-       mfc_debug(2, "dev.hwlock.dev = 0x%lx, bits = 0x%lx, owned_by_irq = %d, wl_count = %d, transfer_owner = %d\n",
-               dev->hwlock.dev, dev->hwlock.bits, dev->hwlock.owned_by_irq,
-               dev->hwlock.wl_count, dev->hwlock.transfer_owner);
-}
-
-void s5p_mfc_init_hwlock(struct s5p_mfc_dev *dev)
-{
-       unsigned long flags;
-
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return;
-       }
-
-       spin_lock_init(&dev->hwlock.lock);
-       spin_lock_irqsave(&dev->hwlock.lock, flags);
-
-       INIT_LIST_HEAD(&dev->hwlock.waiting_list);
-       dev->hwlock.wl_count = 0;
-       dev->hwlock.bits = 0;
-       dev->hwlock.dev = 0;
-       dev->hwlock.owned_by_irq = 0;
-       dev->hwlock.transfer_owner = 0;
-
-       spin_unlock_irqrestore(&dev->hwlock.lock, flags);
-}
-
-static int mfc_remove_listable_wq_dev(struct s5p_mfc_dev *dev)
-{
-       struct s5p_mfc_listable_wq *listable_wq;
-       unsigned long flags;
-       int ret = -1;
-
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return -EINVAL;
-       }
-
-       spin_lock_irqsave(&dev->hwlock.lock, flags);
-       mfc_print_hwlock(dev);
-
-       list_for_each_entry(listable_wq, &dev->hwlock.waiting_list, list) {
-               if (!listable_wq->dev)
-                       continue;
-
-               mfc_debug(2, "Found dev and will delete it!\n");
-
-               list_del(&listable_wq->list);
-               dev->hwlock.wl_count--;
-
-               ret = 0;
-               break;
-       }
-
-       mfc_print_hwlock(dev);
-       spin_unlock_irqrestore(&dev->hwlock.lock, flags);
-
-       return ret;
-}
-
-static int mfc_remove_listable_wq_ctx(struct s5p_mfc_ctx *curr_ctx)
-{
-       struct s5p_mfc_dev *dev;
-       struct s5p_mfc_listable_wq *listable_wq;
-       unsigned long flags;
-       int ret = -1;
-
-       if (!curr_ctx) {
-               mfc_err_dev("no mfc context to run\n");
-               return -EINVAL;
-       }
-
-       dev = curr_ctx->dev;
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return -EINVAL;
-       }
-
-       spin_lock_irqsave(&dev->hwlock.lock, flags);
-       mfc_print_hwlock(dev);
-
-       list_for_each_entry(listable_wq, &dev->hwlock.waiting_list, list) {
-               if (!listable_wq->ctx)
-                       continue;
-
-               if (listable_wq->ctx->num == curr_ctx->num) {
-                       mfc_debug(2, "Found ctx and will delete it (%d)!\n", curr_ctx->num);
-
-                       list_del(&listable_wq->list);
-                       dev->hwlock.wl_count--;
-                       ret = 0;
-                       break;
-               }
-       }
-
-       mfc_print_hwlock(dev);
-       spin_unlock_irqrestore(&dev->hwlock.lock, flags);
-
-       return ret;
-}
-
-/*
- * Return value description
- *    0: succeeded to get hwlock
- * -EIO: failed to get hwlock (time out)
- */
-int s5p_mfc_get_hwlock_dev(struct s5p_mfc_dev *dev)
-{
-       int ret = 0;
-       unsigned long flags;
-
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return -EINVAL;
-       }
-
-       mutex_lock(&dev->hwlock_wq.wait_mutex);
-
-       spin_lock_irqsave(&dev->hwlock.lock, flags);
-       mfc_print_hwlock(dev);
-
-       if (dev->shutdown) {
-               mfc_info_dev("Couldn't lock HW. Shutdown was called\n");
-               spin_unlock_irqrestore(&dev->hwlock.lock, flags);
-               mutex_unlock(&dev->hwlock_wq.wait_mutex);
-               return -EINVAL;
-       }
-
-       if ((dev->hwlock.bits != 0) || (dev->hwlock.dev != 0)) {
-               list_add_tail(&dev->hwlock_wq.list, &dev->hwlock.waiting_list);
-               dev->hwlock.wl_count++;
-
-               spin_unlock_irqrestore(&dev->hwlock.lock, flags);
-
-               mfc_debug(2, "Waiting for hwlock to be released\n");
-
-               ret = wait_event_timeout(dev->hwlock_wq.wait_queue,
-                       ((dev->hwlock.transfer_owner == 1) && (dev->hwlock.dev == 1)),
-                       msecs_to_jiffies(MFC_HWLOCK_TIMEOUT));
-
-               MFC_TRACE_DEV_HWLOCK("get_hwlock_dev: before waiting\n");
-               MFC_TRACE_DEV_HWLOCK(">>dev:0x%lx, bits:0x%lx, owned:%d, wl:%d, trans:%d\n",
-                               dev->hwlock.dev, dev->hwlock.bits, dev->hwlock.owned_by_irq,
-                               dev->hwlock.wl_count, dev->hwlock.transfer_owner);
-
-               dev->hwlock.transfer_owner = 0;
-               mfc_remove_listable_wq_dev(dev);
-               if (ret == 0) {
-                       mfc_err_dev("Woken up but timed out\n");
-                       mfc_print_hwlock(dev);
-                       mutex_unlock(&dev->hwlock_wq.wait_mutex);
-                       return -EIO;
-               } else {
-                       mfc_debug(2, "Woken up and got hwlock\n");
-                       mfc_print_hwlock(dev);
-                       mutex_unlock(&dev->hwlock_wq.wait_mutex);
-               }
-       } else {
-               dev->hwlock.bits = 0;
-               dev->hwlock.dev = 1;
-               dev->hwlock.owned_by_irq = 0;
-
-               MFC_TRACE_DEV_HWLOCK("get_hwlock_dev: no waiting\n");
-               MFC_TRACE_DEV_HWLOCK(">>dev:0x%lx, bits:0x%lx, owned:%d, wl:%d, trans:%d\n",
-                               dev->hwlock.dev, dev->hwlock.bits, dev->hwlock.owned_by_irq,
-                               dev->hwlock.wl_count, dev->hwlock.transfer_owner);
-
-               mfc_print_hwlock(dev);
-               spin_unlock_irqrestore(&dev->hwlock.lock, flags);
-               mutex_unlock(&dev->hwlock_wq.wait_mutex);
-       }
-
-       /* Stop NAL-Q after getting hwlock */
-       if (dev->nal_q_handle)
-               s5p_mfc_nal_q_stop_if_started(dev);
-
-       return 0;
-}
-
-/*
- * Return value description
- *    0: succeeded to get hwlock
- * -EIO: failed to get hwlock (time out)
- */
-int s5p_mfc_get_hwlock_ctx(struct s5p_mfc_ctx *curr_ctx)
-{
-       struct s5p_mfc_dev *dev;
-       struct s5p_mfc_ctx *ctx = curr_ctx;
-       int ret = 0;
-       unsigned long flags;
-
-       if (!curr_ctx) {
-               mfc_err_dev("no mfc context to run\n");
-               return -EINVAL;
-       }
-
-       dev = curr_ctx->dev;
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return -EINVAL;
-       }
-
-       mutex_lock(&curr_ctx->hwlock_wq.wait_mutex);
-
-       spin_lock_irqsave(&dev->hwlock.lock, flags);
-       mfc_print_hwlock(dev);
-
-       if (dev->shutdown) {
-               mfc_info_dev("Couldn't lock HW. Shutdown was called\n");
-               spin_unlock_irqrestore(&dev->hwlock.lock, flags);
-               mutex_unlock(&curr_ctx->hwlock_wq.wait_mutex);
-               return -EINVAL;
-       }
-
-       if ((dev->hwlock.bits != 0) || (dev->hwlock.dev != 0)) {
-               list_add_tail(&curr_ctx->hwlock_wq.list, &dev->hwlock.waiting_list);
-               dev->hwlock.wl_count++;
-
-               spin_unlock_irqrestore(&dev->hwlock.lock, flags);
-
-               MFC_TRACE_CTX_HWLOCK("get_hwlock_ctx: before waiting\n");
-               MFC_TRACE_CTX_HWLOCK(">>dev:0x%lx, bits:0x%lx, owned:%d, wl:%d, trans:%d\n",
-                               dev->hwlock.dev, dev->hwlock.bits, dev->hwlock.owned_by_irq,
-                               dev->hwlock.wl_count, dev->hwlock.transfer_owner);
-
-               mfc_debug(2, "Waiting for hwlock to be released\n");
-
-               ret = wait_event_timeout(curr_ctx->hwlock_wq.wait_queue,
-                       ((dev->hwlock.transfer_owner == 1) && (test_bit(curr_ctx->num, &dev->hwlock.bits))),
-                       msecs_to_jiffies(MFC_HWLOCK_TIMEOUT));
-
-               MFC_TRACE_CTX_HWLOCK("get_hwlock_ctx: after waiting, ret:%d\n", ret);
-               MFC_TRACE_CTX_HWLOCK(">>dev:0x%lx, bits:0x%lx, owned:%d, wl:%d, trans:%d\n",
-                               dev->hwlock.dev, dev->hwlock.bits, dev->hwlock.owned_by_irq,
-                               dev->hwlock.wl_count, dev->hwlock.transfer_owner);
-
-               dev->hwlock.transfer_owner = 0;
-               mfc_remove_listable_wq_ctx(curr_ctx);
-               if (ret == 0) {
-                       mfc_err_dev("Woken up but timed out\n");
-                       mfc_print_hwlock(dev);
-                       mutex_unlock(&curr_ctx->hwlock_wq.wait_mutex);
-                       return -EIO;
-               } else {
-                       mfc_debug(2, "Woken up and got hwlock\n");
-                       mfc_print_hwlock(dev);
-                       mutex_unlock(&curr_ctx->hwlock_wq.wait_mutex);
-               }
-       } else {
-               dev->hwlock.bits = 0;
-               dev->hwlock.dev = 0;
-               set_bit(curr_ctx->num, &dev->hwlock.bits);
-               dev->hwlock.owned_by_irq = 0;
-
-               MFC_TRACE_CTX_HWLOCK("get_hwlock_ctx: no waiting\n");
-               MFC_TRACE_CTX_HWLOCK(">>dev:0x%lx, bits:0x%lx, owned:%d, wl:%d, trans:%d\n",
-                               dev->hwlock.dev, dev->hwlock.bits, dev->hwlock.owned_by_irq,
-                               dev->hwlock.wl_count, dev->hwlock.transfer_owner);
-
-               mfc_print_hwlock(dev);
-               spin_unlock_irqrestore(&dev->hwlock.lock, flags);
-               mutex_unlock(&curr_ctx->hwlock_wq.wait_mutex);
-       }
-
-       /* Stop NAL-Q after getting hwlock */
-       if (dev->nal_q_handle)
-               s5p_mfc_nal_q_stop_if_started(dev);
-
-       return 0;
-}
-
-/*
- * Return value description
- *  0: succeeded to release hwlock
- *  1: succeeded to release hwlock, hwlock is captured by another module
- * -1: error since device is waiting again.
- */
-int s5p_mfc_release_hwlock_dev(struct s5p_mfc_dev *dev)
-{
-       struct s5p_mfc_listable_wq *listable_wq;
-       unsigned long flags;
-       int ret = -1;
-
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return -EINVAL;
-       }
-
-       spin_lock_irqsave(&dev->hwlock.lock, flags);
-       mfc_print_hwlock(dev);
-
-       dev->hwlock.dev = 0;
-       dev->hwlock.owned_by_irq = 0;
-
-       if (dev->shutdown) {
-               mfc_debug(2, "Couldn't wakeup module. Shutdown was called\n");
-               ret = 0;
-       } else if (list_empty(&dev->hwlock.waiting_list)) {
-               mfc_debug(2, "No waiting module\n");
-               ret = 0;
-       } else {
-               mfc_debug(2, "There is a waiting module\n");
-               listable_wq = list_entry(dev->hwlock.waiting_list.next, struct s5p_mfc_listable_wq, list);
-               list_del(&listable_wq->list);
-               dev->hwlock.wl_count--;
-
-               if (listable_wq->dev) {
-                       mfc_debug(2, "Waking up dev\n");
-                       dev->hwlock.dev = 1;
-               } else {
-                       mfc_debug(2, "Waking up another ctx\n");
-                       set_bit(listable_wq->ctx->num, &dev->hwlock.bits);
-               }
-
-               dev->hwlock.transfer_owner = 1;
-
-               MFC_TRACE_DEV_HWLOCK("release_hwlock_dev: wakeup\n");
-               MFC_TRACE_DEV_HWLOCK(">>dev:0x%lx, bits:0x%lx, owned:%d, wl:%d, trans:%d\n",
-                               dev->hwlock.dev, dev->hwlock.bits, dev->hwlock.owned_by_irq,
-                               dev->hwlock.wl_count, dev->hwlock.transfer_owner);
-
-               wake_up(&listable_wq->wait_queue);
-               ret = 1;
-       }
-
-       mfc_print_hwlock(dev);
-       spin_unlock_irqrestore(&dev->hwlock.lock, flags);
-       return ret;
-}
-
-/*
- * Should be called with hwlock.lock
- *
- * Return value description
- * 0: succeeded to release hwlock
- * 1: succeeded to release hwlock, hwlock is captured by another module
- */
-static int mfc_release_hwlock_ctx_protected(struct s5p_mfc_ctx *curr_ctx)
-{
-       struct s5p_mfc_dev *dev;
-       struct s5p_mfc_ctx *ctx = curr_ctx;
-       struct s5p_mfc_listable_wq *listable_wq;
-       int ret = -1;
-
-       if (!curr_ctx) {
-               mfc_err_dev("no mfc context to run\n");
-               return -EINVAL;
-       }
-
-       dev = curr_ctx->dev;
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return -EINVAL;
-       }
-
-       mfc_print_hwlock(dev);
-       clear_bit(curr_ctx->num, &dev->hwlock.bits);
-       dev->hwlock.owned_by_irq = 0;
-
-       if (dev->shutdown) {
-               mfc_debug(2, "Couldn't wakeup module. Shutdown was called\n");
-               ret = 0;
-       } else if (list_empty(&dev->hwlock.waiting_list)) {
-               mfc_debug(2, "No waiting module\n");
-               ret = 0;
-       } else {
-               mfc_debug(2, "There is a waiting module\n");
-               listable_wq = list_entry(dev->hwlock.waiting_list.next, struct s5p_mfc_listable_wq, list);
-               list_del(&listable_wq->list);
-               dev->hwlock.wl_count--;
-
-               if (listable_wq->dev) {
-                       mfc_debug(2, "Waking up dev\n");
-                       dev->hwlock.dev = 1;
-               } else {
-                       mfc_debug(2, "Waking up another ctx\n");
-                       set_bit(listable_wq->ctx->num, &dev->hwlock.bits);
-               }
-
-               dev->hwlock.transfer_owner = 1;
-
-               MFC_TRACE_CTX_HWLOCK("release_hwlock_ctx: wakeup\n");
-               MFC_TRACE_CTX_HWLOCK(">>dev:0x%lx, bits:0x%lx, owned:%d, wl:%d, trans:%d\n",
-                               dev->hwlock.dev, dev->hwlock.bits, dev->hwlock.owned_by_irq,
-                               dev->hwlock.wl_count, dev->hwlock.transfer_owner);
-
-               wake_up(&listable_wq->wait_queue);
-               ret = 1;
-       }
-
-       mfc_print_hwlock(dev);
-       return ret;
-}
-
-/*
- * Return value description
- * 0: succeeded to release hwlock
- * 1: succeeded to release hwlock, hwlock is captured by another module
- */
-int s5p_mfc_release_hwlock_ctx(struct s5p_mfc_ctx *curr_ctx)
-{
-       struct s5p_mfc_dev *dev;
-       unsigned long flags;
-       int ret = -1;
-
-       if (!curr_ctx) {
-               mfc_err_dev("no mfc context to run\n");
-               return -EINVAL;
-       }
-
-       dev = curr_ctx->dev;
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return -EINVAL;
-       }
-
-       spin_lock_irqsave(&dev->hwlock.lock, flags);
-       ret = mfc_release_hwlock_ctx_protected(curr_ctx);
-       spin_unlock_irqrestore(&dev->hwlock.lock, flags);
-       return ret;
-}
-
-static inline int mfc_yield_hwlock(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *curr_ctx)
-{
-       unsigned long flags;
-
-       if (!curr_ctx) {
-               mfc_err_dev("no mfc context to run\n");
-               return -EINVAL;
-       }
-
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return -EINVAL;
-       }
-
-       spin_lock_irqsave(&dev->hwlock.lock, flags);
-
-       mfc_release_hwlock_ctx_protected(curr_ctx);
-
-       spin_unlock_irqrestore(&dev->hwlock.lock, flags);
-
-       /* Trigger again if other instance's work is waiting */
-       if (s5p_mfc_is_work_to_do(dev))
-               queue_work(dev->butler_wq, &dev->butler_work);
-
-       return 0;
-}
-
-/*
- * Should be called with hwlock.lock
- */
-static inline void mfc_transfer_hwlock_ctx_protected(struct s5p_mfc_dev *dev, int curr_ctx_index)
-{
-       dev->hwlock.dev = 0;
-       dev->hwlock.bits = 0;
-       set_bit(curr_ctx_index, &dev->hwlock.bits);
-}
-
-/*
- * Should be called with hwlock.lock
- *
- * Return value description
- *   >=0: succeeded to get hwlock_bit for the context, index of new context
- *   -1, -EINVAL: failed to get hwlock_bit for a context
- */
-static int mfc_try_to_get_new_ctx_protected(struct s5p_mfc_dev *dev)
-{
-       int ret = 0;
-       int index;
-       struct s5p_mfc_ctx *new_ctx;
-
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return -EINVAL;
-       }
-
-       if (dev->shutdown) {
-               mfc_info_dev("Couldn't lock HW. Shutdown was called\n");
-               return -EINVAL;
-       }
-
-       if (dev->sleep) {
-               mfc_info_dev("Couldn't lock HW. Sleep was called\n");
-               return -EINVAL;
-       }
-
-       /* Check whether hardware is not running */
-       if ((dev->hwlock.bits != 0) || (dev->hwlock.dev != 0)) {
-               /* This is perfectly ok, the scheduled ctx should wait */
-               mfc_debug(2, "Couldn't lock HW\n");
-               return -1;
-       }
-
-       /* Choose the context to run */
-       index = s5p_mfc_get_new_ctx(dev);
-       if (index < 0) {
-               /* This is perfectly ok, the scheduled ctx should wait
-                * No contexts to run
-                */
-               mfc_debug(2, "No ctx is scheduled to be run\n");
-               ret = -1;
-               return ret;
-       }
-
-       new_ctx = dev->ctx[index];
-       if (!new_ctx) {
-               mfc_err_dev("no mfc context to run\n");
-               ret = -1;
-               return ret;
-       }
-
-       set_bit(new_ctx->num, &dev->hwlock.bits);
-       ret = index;
-
-       return ret;
-}
-
-/*
- * Should be called without hwlock holding
- *
- * Try to run an operation on hardware
- */
-void s5p_mfc_try_run(struct s5p_mfc_dev *dev)
-{
-       int new_ctx_index;
-       int ret;
-       unsigned long flags;
-
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return;
-       }
-
-       spin_lock_irqsave(&dev->hwlock.lock, flags);
-       mfc_print_hwlock(dev);
-
-       new_ctx_index = mfc_try_to_get_new_ctx_protected(dev);
-       if (new_ctx_index < 0) {
-               mfc_debug(2, "Failed to get new context to run\n");
-               mfc_print_hwlock(dev);
-               spin_unlock_irqrestore(&dev->hwlock.lock, flags);
-               return;
-       }
-
-       dev->hwlock.owned_by_irq = 1;
-
-       mfc_print_hwlock(dev);
-       spin_unlock_irqrestore(&dev->hwlock.lock, flags);
-
-       ret = s5p_mfc_just_run(dev, new_ctx_index);
-       if (ret)
-               mfc_yield_hwlock(dev, dev->ctx[new_ctx_index]);
-}
-
-/*
- * Should be called without hwlock holding
- *
- */
-void s5p_mfc_cleanup_work_bit_and_try_run(struct s5p_mfc_ctx *curr_ctx)
-{
-       struct s5p_mfc_dev *dev;
-
-       if (!curr_ctx) {
-               mfc_err_dev("no mfc context to run\n");
-               return;
-       }
-
-       dev = curr_ctx->dev;
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return;
-       }
-
-       s5p_mfc_clear_bit(curr_ctx->num, &dev->work_bits);
-
-       s5p_mfc_try_run(dev);
-}
-
-void s5p_mfc_cache_flush(struct s5p_mfc_dev *dev, int is_drm)
-{
-       s5p_mfc_cmd_cache_flush(dev);
-       if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_CACHE_FLUSH_RET)) {
-               mfc_err_dev("Failed to CACHE_FLUSH\n");
-               dev->logging_data->cause |= (1 << MFC_CAUSE_FAIL_CHACHE_FLUSH);
-               call_dop(dev, dump_and_stop_always, dev);
-       }
-
-       s5p_mfc_pm_clock_off(dev);
-       dev->curr_ctx_is_drm = is_drm;
-       s5p_mfc_pm_clock_on_with_base(dev, (is_drm ? MFCBUF_DRM : MFCBUF_NORMAL));
-}
-
-/*
- * Return value description
- *  0: NAL-Q is handled successfully
- *  1: NAL_START command should be handled
- * -1: Error
-*/
-static int mfc_nal_q_just_run(struct s5p_mfc_ctx *ctx, int need_cache_flush)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       unsigned int ret = -1;
-
-       nal_queue_handle *nal_q_handle = dev->nal_q_handle;
-
-       if (!nal_q_handle) {
-               mfc_err_dev("nal_q_handle is NULL\n");
-               return ret;
-       }
-
-       switch (nal_q_handle->nal_q_state) {
-       case NAL_Q_STATE_CREATED:
-               if (s5p_mfc_nal_q_check_enable(dev) == 0) {
-                       /* NAL START */
-                       ret = 1;
-               } else {
-                       s5p_mfc_nal_q_clock_on(dev, nal_q_handle);
-
-                       s5p_mfc_nal_q_init(dev, nal_q_handle);
-
-                       /* enable NAL QUEUE */
-                       if (need_cache_flush)
-                               s5p_mfc_cache_flush(dev, ctx->is_drm);
-
-                       mfc_info_ctx("[NALQ] start NAL QUEUE\n");
-                       s5p_mfc_nal_q_start(dev, nal_q_handle);
-
-                       if (s5p_mfc_nal_q_enqueue_in_buf(dev, ctx, nal_q_handle->nal_q_in_handle)) {
-                               mfc_debug(2, "[NALQ] Failed to enqueue input data\n");
-                               s5p_mfc_nal_q_clock_off(dev, nal_q_handle);
-                       }
-
-                       s5p_mfc_clear_bit(ctx->num, &dev->work_bits);
-                       if ((s5p_mfc_ctx_ready(ctx) && !ctx->clear_work_bit) ||
-                                       nal_q_handle->nal_q_exception)
-                               s5p_mfc_set_bit(ctx->num, &dev->work_bits);
-                       ctx->clear_work_bit = 0;
-
-                       s5p_mfc_release_hwlock_ctx(ctx);
-
-                       if (s5p_mfc_is_work_to_do(dev))
-                               queue_work(dev->butler_wq, &dev->butler_work);
-
-                       ret = 0;
-               }
-               break;
-       case NAL_Q_STATE_STARTED:
-               s5p_mfc_nal_q_clock_on(dev, nal_q_handle);
-
-               if (s5p_mfc_nal_q_check_enable(dev) == 0 ||
-                               nal_q_handle->nal_q_exception) {
-                       /* disable NAL QUEUE */
-                       s5p_mfc_nal_q_stop(dev, nal_q_handle);
-                       mfc_info_ctx("[NALQ] stop NAL QUEUE\n");
-                       if (s5p_mfc_wait_for_done_dev(dev,
-                                       S5P_FIMV_R2H_CMD_COMPLETE_QUEUE_RET)) {
-                               mfc_err_dev("[NALQ] Failed to stop queue\n");
-                               dev->logging_data->cause |= (1 << MFC_CAUSE_FAIL_STOP_NAL_Q);
-                               call_dop(dev, dump_and_stop_always, dev);
-                       }
-                       ret = 1;
-                       break;
-               } else {
-                       /* NAL QUEUE */
-                       if (s5p_mfc_nal_q_enqueue_in_buf(dev, ctx, nal_q_handle->nal_q_in_handle)) {
-                               mfc_debug(2, "[NALQ] Failed to enqueue input data\n");
-                               s5p_mfc_nal_q_clock_off(dev, nal_q_handle);
-                       }
-
-                       s5p_mfc_clear_bit(ctx->num, &dev->work_bits);
-
-                       if ((s5p_mfc_ctx_ready(ctx) && !ctx->clear_work_bit) ||
-                                       nal_q_handle->nal_q_exception)
-                               s5p_mfc_set_bit(ctx->num, &dev->work_bits);
-                       ctx->clear_work_bit = 0;
-
-                       s5p_mfc_release_hwlock_ctx(ctx);
-
-                       if (s5p_mfc_is_work_to_do(dev))
-                               queue_work(dev->butler_wq, &dev->butler_work);
-                       ret = 0;
-               }
-               break;
-       default:
-               mfc_info_ctx("[NALQ] can't try command, nal_q_state : %d\n",
-                               nal_q_handle->nal_q_state);
-               ret = -1;
-               break;
-       }
-
-       return ret;
-}
-
-static int mfc_just_run_dec(struct s5p_mfc_ctx *ctx)
-{
-       int ret = 0;
-
-       switch (ctx->state) {
-       case MFCINST_FINISHING:
-               ret = s5p_mfc_run_dec_last_frames(ctx);
-               break;
-       case MFCINST_RUNNING:
-       case MFCINST_SPECIAL_PARSING_NAL:
-               ret = s5p_mfc_run_dec_frame(ctx);
-               break;
-       case MFCINST_INIT:
-               ret = s5p_mfc_open_inst(ctx);
-               break;
-       case MFCINST_RETURN_INST:
-               ret = s5p_mfc_close_inst(ctx);
-               break;
-       case MFCINST_GOT_INST:
-       case MFCINST_SPECIAL_PARSING:
-               ret = s5p_mfc_run_dec_init(ctx);
-               break;
-       case MFCINST_HEAD_PARSED:
-               if (ctx->codec_buffer_allocated == 0) {
-                       ctx->clear_work_bit = 1;
-                       mfc_err_ctx("codec buffer is not allocated\n");
-                       ret = -EAGAIN;
-                       break;
-               }
-               ret = s5p_mfc_cmd_dec_init_buffers(ctx);
-               break;
-       case MFCINST_RES_CHANGE_INIT:
-               ret = s5p_mfc_run_dec_last_frames(ctx);
-               break;
-       case MFCINST_RES_CHANGE_FLUSH:
-               ret = s5p_mfc_run_dec_last_frames(ctx);
-               break;
-       case MFCINST_RES_CHANGE_END:
-               mfc_debug(2, "[DRC] Finished remaining frames after resolution change\n");
-               ctx->capture_state = QUEUE_FREE;
-               mfc_debug(2, "[DRC] Will re-init the codec\n");
-               ret = s5p_mfc_run_dec_init(ctx);
-               break;
-       case MFCINST_DPB_FLUSHING:
-               ret = s5p_mfc_cmd_dpb_flush(ctx);
-               break;
-       default:
-               mfc_info_ctx("can't try command(decoder just_run), state : %d\n", ctx->state);
-               ret = -EAGAIN;
-       }
-
-       return ret;
-}
-
-static int mfc_just_run_enc(struct s5p_mfc_ctx *ctx)
-{
-       int ret = 0;
-
-       switch (ctx->state) {
-               case MFCINST_FINISHING:
-                       ret = s5p_mfc_run_enc_last_frames(ctx);
-                       break;
-               case MFCINST_RUNNING:
-                       if (ctx->otf_handle) {
-                               ret = s5p_mfc_otf_run_enc_frame(ctx);
-                               break;
-                       }
-                       ret = s5p_mfc_run_enc_frame(ctx);
-                       break;
-               case MFCINST_INIT:
-                       ret = s5p_mfc_open_inst(ctx);
-                       break;
-               case MFCINST_RETURN_INST:
-                       ret = s5p_mfc_close_inst(ctx);
-                       break;
-               case MFCINST_GOT_INST:
-                       if (ctx->otf_handle) {
-                               ret = s5p_mfc_otf_run_enc_init(ctx);
-                               break;
-                       }
-                       ret = s5p_mfc_run_enc_init(ctx);
-                       break;
-               case MFCINST_HEAD_PARSED:
-                       ret = s5p_mfc_cmd_enc_init_buffers(ctx);
-                       break;
-               case MFCINST_ABORT_INST:
-                       ret = s5p_mfc_abort_inst(ctx);
-                       break;
-               default:
-                       mfc_info_ctx("can't try command(encoder just_run), state : %d\n", ctx->state);
-                       ret = -EAGAIN;
-       }
-
-       return ret;
-}
-
-/* Run an operation on hardware */
-int s5p_mfc_just_run(struct s5p_mfc_dev *dev, int new_ctx_index)
-{
-       struct s5p_mfc_ctx *ctx;
-       unsigned int ret = 0;
-       int need_cache_flush = 0;
-
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return -EINVAL;
-       }
-
-       ctx = dev->ctx[new_ctx_index];
-       if (!ctx) {
-               mfc_err_dev("no mfc context to run\n");
-               return -EINVAL;
-       }
-
-       if (ctx->state == MFCINST_RUNNING)
-               s5p_mfc_clean_ctx_int_flags(ctx);
-
-       mfc_debug(2, "New context: %d\n", new_ctx_index);
-       dev->curr_ctx = ctx->num;
-
-       /* Got context to run in ctx */
-       mfc_debug(2, "src: %d, dst: %d, state: %d, dpb_count = %d\n",
-               s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->src_buf_queue),
-               s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->dst_buf_queue),
-               ctx->state, ctx->dpb_count);
-       mfc_debug(2, "ctx->state = %d\n", ctx->state);
-       /* Last frame has already been sent to MFC
-        * Now obtaining frames from MFC buffer */
-
-       /* Check if cache flush command is needed */
-       if (dev->curr_ctx_is_drm != ctx->is_drm)
-               need_cache_flush = 1;
-       else
-               dev->curr_ctx_is_drm = ctx->is_drm;
-
-       mfc_debug(2, "need_cache_flush = %d, is_drm = %d\n", need_cache_flush, ctx->is_drm);
-
-       if (dev->nal_q_handle) {
-               ret = mfc_nal_q_just_run(ctx, need_cache_flush);
-               if (ret == 0) {
-                       mfc_debug(2, "NAL_Q was handled\n");
-                       return ret;
-               } else if (ret == 1){
-                       /* Path through */
-                       mfc_debug(2, "NAL_START will be handled\n");
-               } else {
-                       return ret;
-               }
-       }
-
-       mfc_debug(2, "continue_clock_on = %d\n", dev->continue_clock_on);
-       if (!dev->continue_clock_on) {
-               s5p_mfc_pm_clock_on(dev);
-       } else {
-               dev->continue_clock_on = false;
-       }
-
-       if (need_cache_flush)
-               s5p_mfc_cache_flush(dev, ctx->is_drm);
-
-       if (ctx->type == MFCINST_DECODER) {
-               ret = mfc_just_run_dec(ctx);
-       } else if (ctx->type == MFCINST_ENCODER) {
-               ret = mfc_just_run_enc(ctx);
-       } else {
-               mfc_err_ctx("invalid context type: %d\n", ctx->type);
-               ret = -EAGAIN;
-       }
-
-       if (ret) {
-               /* Check again the ctx condition and clear work bits
-                * if ctx is not available. */
-               if (s5p_mfc_ctx_ready(ctx) == 0 || ctx->clear_work_bit) {
-                       s5p_mfc_clear_bit(ctx->num, &dev->work_bits);
-                       ctx->clear_work_bit = 0;
-               }
-
-               s5p_mfc_pm_clock_off(dev);
-       }
-
-       return ret;
-}
-
-void s5p_mfc_hwlock_handler_irq(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *curr_ctx,
-               unsigned int reason, unsigned int err)
-{
-       int new_ctx_index;
-       unsigned long flags;
-       int ret;
-
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return;
-       }
-
-       if (!curr_ctx) {
-               mfc_err_dev("no mfc context to run\n");
-               return;
-       }
-
-       spin_lock_irqsave(&dev->hwlock.lock, flags);
-       mfc_print_hwlock(dev);
-
-       if (dev->hwlock.owned_by_irq) {
-               if (dev->preempt_ctx > MFC_NO_INSTANCE_SET) {
-                       mfc_debug(2, "There is a preempt_ctx\n");
-                       dev->continue_clock_on = true;
-                       s5p_mfc_wake_up_ctx(curr_ctx, reason, err);
-                       new_ctx_index = dev->preempt_ctx;
-                       mfc_debug(2, "preempt_ctx is : %d\n", new_ctx_index);
-
-                       spin_unlock_irqrestore(&dev->hwlock.lock, flags);
-
-                       ret = s5p_mfc_just_run(dev, new_ctx_index);
-                       if (ret) {
-                               dev->continue_clock_on = false;
-                               mfc_yield_hwlock(dev, dev->ctx[new_ctx_index]);
-                       }
-               } else if (!list_empty(&dev->hwlock.waiting_list)) {
-                       mfc_debug(2, "There is a waiting module for hwlock\n");
-                       dev->continue_clock_on = false;
-                       s5p_mfc_pm_clock_off(dev);
-
-                       spin_unlock_irqrestore(&dev->hwlock.lock, flags);
-
-                       s5p_mfc_release_hwlock_ctx(curr_ctx);
-                       s5p_mfc_wake_up_ctx(curr_ctx, reason, err);
-                       queue_work(dev->butler_wq, &dev->butler_work);
-               } else {
-                       mfc_debug(2, "No preempt_ctx and no waiting module\n");
-                       new_ctx_index = s5p_mfc_get_new_ctx(dev);
-                       if (new_ctx_index < 0) {
-                               mfc_debug(2, "No ctx to run\n");
-                               /* No contexts to run */
-                               dev->continue_clock_on = false;
-                               s5p_mfc_pm_clock_off(dev);
-
-                               spin_unlock_irqrestore(&dev->hwlock.lock, flags);
-
-                               s5p_mfc_release_hwlock_ctx(curr_ctx);
-                               s5p_mfc_wake_up_ctx(curr_ctx, reason, err);
-                               queue_work(dev->butler_wq, &dev->butler_work);
-                       } else {
-                               mfc_debug(2, "There is a ctx to run\n");
-                               dev->continue_clock_on = true;
-                               s5p_mfc_wake_up_ctx(curr_ctx, reason, err);
-
-                               /* If cache flush command is needed or there is OTF handle, handler should stop */
-                               if ((dev->curr_ctx_is_drm != dev->ctx[new_ctx_index]->is_drm) ||
-                                               dev->ctx[new_ctx_index]->otf_handle) {
-                                       mfc_debug(2, "Secure and nomal switching or OTF mode\n");
-                                       mfc_debug(2, "DRM attribute %d->%d\n",
-                                                       dev->curr_ctx_is_drm, dev->ctx[new_ctx_index]->is_drm);
-
-                                       spin_unlock_irqrestore(&dev->hwlock.lock, flags);
-
-                                       s5p_mfc_release_hwlock_ctx(curr_ctx);
-                                       queue_work(dev->butler_wq, &dev->butler_work);
-                               } else {
-                                       mfc_debug(2, "Work to do successively (next ctx: %d)\n", new_ctx_index);
-                                       mfc_transfer_hwlock_ctx_protected(dev, new_ctx_index);
-
-                                       spin_unlock_irqrestore(&dev->hwlock.lock, flags);
-
-                                       ret = s5p_mfc_just_run(dev, new_ctx_index);
-                                       if (ret) {
-                                               dev->continue_clock_on = false;
-                                               mfc_yield_hwlock(dev, dev->ctx[new_ctx_index]);
-                                       }
-                               }
-                       }
-               }
-       } else {
-               mfc_debug(2, "hwlock is NOT owned by irq\n");
-               dev->continue_clock_on = false;
-               s5p_mfc_pm_clock_off(dev);
-               s5p_mfc_wake_up_ctx(curr_ctx, reason, err);
-               queue_work(dev->butler_wq, &dev->butler_work);
-
-               spin_unlock_irqrestore(&dev->hwlock.lock, flags);
-       }
-       mfc_print_hwlock(dev);
-}
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_hwlock.h b/drivers/media/platform/exynos/mfc/s5p_mfc_hwlock.h
deleted file mode 100644 (file)
index a9616a8..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_hwlock.h
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __S5P_MFC_HWLOCK_H
-#define __S5P_MFC_HWLOCK_H __FILE__
-
-#include "s5p_mfc_common.h"
-
-static inline void s5p_mfc_init_listable_wq_dev(struct s5p_mfc_dev *dev)
-{
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return;
-       }
-
-       INIT_LIST_HEAD(&dev->hwlock_wq.list);
-       init_waitqueue_head(&dev->hwlock_wq.wait_queue);
-       mutex_init(&dev->hwlock_wq.wait_mutex);
-       dev->hwlock_wq.ctx = NULL;
-       dev->hwlock_wq.dev = dev;
-}
-
-static inline void s5p_mfc_init_listable_wq_ctx(struct s5p_mfc_ctx *curr_ctx)
-{
-       if (!curr_ctx) {
-               mfc_err_dev("no mfc context to run\n");
-               return;
-       }
-
-       INIT_LIST_HEAD(&curr_ctx->hwlock_wq.list);
-       init_waitqueue_head(&curr_ctx->hwlock_wq.wait_queue);
-       mutex_init(&curr_ctx->hwlock_wq.wait_mutex);
-       curr_ctx->hwlock_wq.ctx = curr_ctx;
-       curr_ctx->hwlock_wq.dev = NULL;
-}
-
-static inline void s5p_mfc_destroy_listable_wq_dev(struct s5p_mfc_dev *dev)
-{
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return;
-       }
-
-       mutex_destroy(&dev->hwlock_wq.wait_mutex);
-}
-
-static inline void s5p_mfc_destroy_listable_wq_ctx(struct s5p_mfc_ctx *curr_ctx)
-{
-       if (!curr_ctx) {
-               mfc_err_dev("no mfc context to run\n");
-               return;
-       }
-
-       mutex_destroy(&curr_ctx->hwlock_wq.wait_mutex);
-}
-
-void s5p_mfc_init_hwlock(struct s5p_mfc_dev *dev);
-
-int s5p_mfc_get_hwlock_dev(struct s5p_mfc_dev *dev);
-int s5p_mfc_get_hwlock_ctx(struct s5p_mfc_ctx *curr_ctx);
-
-int s5p_mfc_release_hwlock_dev(struct s5p_mfc_dev *dev);
-int s5p_mfc_release_hwlock_ctx(struct s5p_mfc_ctx *curr_ctx);
-
-void s5p_mfc_cache_flush(struct s5p_mfc_dev *dev, int is_drm);
-
-void s5p_mfc_try_run(struct s5p_mfc_dev *dev);
-void s5p_mfc_cleanup_work_bit_and_try_run(struct s5p_mfc_ctx *ctx);
-int s5p_mfc_just_run(struct s5p_mfc_dev *dev, int new_ctx_index);
-
-void s5p_mfc_hwlock_handler_irq(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx,
-               unsigned int reason, unsigned int err);
-
-#endif /* __S5P_MFC_HWLOCK_H */
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_inst.c b/drivers/media/platform/exynos/mfc/s5p_mfc_inst.c
deleted file mode 100644 (file)
index 1e9c130..0000000
+++ /dev/null
@@ -1,359 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_inst.c
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include "s5p_mfc_inst.h"
-
-#include "s5p_mfc_cmd.h"
-#include "s5p_mfc_enc_param.h"
-#include "s5p_mfc_cal.h"
-#include "s5p_mfc_perf_measure.h"
-#include "s5p_mfc_reg.h"
-
-#include "s5p_mfc_utils.h"
-
-int s5p_mfc_open_inst(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       unsigned int reg;
-       int ret;
-
-       /* Preparing decoding - getting instance number */
-       mfc_debug(2, "Getting instance number\n");
-       s5p_mfc_clean_ctx_int_flags(ctx);
-
-       reg = MFC_READL(S5P_FIMV_CODEC_CONTROL);
-       /* Clear OTF_CONTROL[2:1] & OTF_DEBUG[3] */
-       reg &= ~(0x7 << 1);
-       if (ctx->otf_handle) {
-               /* Set OTF_CONTROL[2:1], 0: Non-OTF, 1: OTF+HWFC, 2: OTF only */
-               reg |= (0x1 << 1);
-               mfc_info_ctx("HWFC + OTF enabled\n");
-               if (otf_dump && !ctx->is_drm) {
-                       /* Set OTF_DEBUG[3] for OTF path dump */
-                       reg |= (0x1 << 3);
-                       mfc_info_ctx("Debugging mode enabled\n");
-               }
-       }
-       MFC_WRITEL(reg, S5P_FIMV_CODEC_CONTROL);
-
-
-       ret = s5p_mfc_cmd_open_inst(ctx);
-       if (ret) {
-               mfc_err_ctx("Failed to create a new instance\n");
-               s5p_mfc_change_state(ctx, MFCINST_ERROR);
-       }
-
-       return ret;
-}
-
-int s5p_mfc_close_inst(struct s5p_mfc_ctx *ctx)
-{
-       int ret = -EINVAL;
-
-       /* Closing decoding instance  */
-       mfc_debug(2, "Returning instance number\n");
-       s5p_mfc_clean_ctx_int_flags(ctx);
-       if (ctx->state == MFCINST_FREE) {
-               mfc_err_ctx("ctx already free status\n");
-               return ret;
-       }
-
-       ret = s5p_mfc_cmd_close_inst(ctx);
-       if (ret) {
-               mfc_err_ctx("Failed to return an instance\n");
-               s5p_mfc_change_state(ctx, MFCINST_ERROR);
-       }
-
-       return ret;
-}
-
-int s5p_mfc_abort_inst(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev;
-
-       if (!ctx) {
-               mfc_err_dev("no mfc context to run\n");
-               return -EINVAL;
-       }
-
-       dev = ctx->dev;
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return -EINVAL;
-       }
-
-       s5p_mfc_clean_ctx_int_flags(ctx);
-
-       MFC_WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID);
-       s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_NAL_ABORT);
-
-       return 0;
-}
-
-/* Initialize decoding */
-int s5p_mfc_init_decode(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev;
-       struct s5p_mfc_dec *dec;
-       unsigned int reg = 0;
-       int fmo_aso_ctrl = 0;
-
-       mfc_debug_enter();
-       if (!ctx) {
-               mfc_err_dev("no mfc context to run\n");
-               return -EINVAL;
-       }
-
-       dev = ctx->dev;
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return -EINVAL;
-       }
-
-       dec = ctx->dec_priv;
-       if (!dec) {
-               mfc_err_dev("no mfc decoder to run\n");
-               return -EINVAL;
-       }
-       mfc_debug(2, "InstNo: %d/%d\n", ctx->inst_no, S5P_FIMV_H2R_CMD_SEQ_HEADER);
-       mfc_debug(2, "BUFs: %08x\n", MFC_READL(S5P_FIMV_D_CPB_BUFFER_ADDR));
-
-       /* When user sets desplay_delay to 0,
-        * It works as "display_delay enable" and delay set to 0.
-        * If user wants display_delay disable, It should be
-        * set to negative value. */
-       if (dec->display_delay >= 0) {
-               reg |= (0x1 << S5P_FIMV_D_DEC_OPT_DISPLAY_DELAY_EN_SHIFT);
-               MFC_WRITEL(dec->display_delay, S5P_FIMV_D_DISPLAY_DELAY);
-       }
-
-       /* FMO_ASO_CTRL - 0: Enable, 1: Disable */
-       reg |= ((fmo_aso_ctrl & S5P_FIMV_D_DEC_OPT_FMO_ASO_CTRL_MASK)
-                       << S5P_FIMV_D_DEC_OPT_FMO_ASO_CTRL_SHIFT);
-
-       reg |= ((dec->idr_decoding & S5P_FIMV_D_DEC_OPT_IDR_DECODING_MASK)
-                       << S5P_FIMV_D_DEC_OPT_IDR_DECODING_SHIFT);
-
-       /* VC1 RCV: Discard to parse additional header as default */
-       if (IS_VC1_RCV_DEC(ctx))
-               reg |= (0x1 << S5P_FIMV_D_DEC_OPT_DISCARD_RCV_HEADER_SHIFT);
-
-       /* conceal control to specific color */
-       reg |= (0x4 << S5P_FIMV_D_DEC_OPT_CONCEAL_CONTROL_SHIFT);
-
-       /* Disable parallel processing if nal_q_parallel_disable was set */
-       if (nal_q_parallel_disable)
-               reg |= (0x2 << S5P_FIMV_D_DEC_OPT_PARALLEL_DISABLE_SHIFT);
-
-       /* Realloc buffer for resolution decrease case in NAL QUEUE mode */
-       reg |= (0x1 << S5P_FIMV_D_DEC_OPT_REALLOC_CONTROL_SHIFT);
-
-       /* Parsing all including PPS */
-       reg |= (0x1 << S5P_FIMV_D_DEC_OPT_SPECIAL_PARSING_SHIFT);
-
-       MFC_WRITEL(reg, S5P_FIMV_D_DEC_OPTIONS);
-
-       MFC_WRITEL(MFC_CONCEAL_COLOR, S5P_FIMV_D_FORCE_PIXEL_VAL);
-
-       if (IS_FIMV1_DEC(ctx)) {
-               mfc_debug(2, "Setting FIMV1 resolution to %dx%d\n",
-                                       ctx->img_width, ctx->img_height);
-               MFC_WRITEL(ctx->img_width, S5P_FIMV_D_SET_FRAME_WIDTH);
-               MFC_WRITEL(ctx->img_height, S5P_FIMV_D_SET_FRAME_HEIGHT);
-       }
-
-       s5p_mfc_set_pixel_format(dev, ctx->dst_fmt->fourcc);
-
-       reg = 0;
-       /* Enable realloc interface if SEI is enabled */
-       if (dec->sei_parse)
-               reg |= (0x1 << S5P_FIMV_D_SEI_ENABLE_NEED_INIT_BUFFER_SHIFT);
-       if (MFC_FEATURE_SUPPORT(dev, dev->pdata->static_info_dec)) {
-               reg |= (0x1 << S5P_FIMV_D_SEI_ENABLE_CONTENT_LIGHT_SHIFT);
-               reg |= (0x1 << S5P_FIMV_D_SEI_ENABLE_MASTERING_DISPLAY_SHIFT);
-       }
-       reg |= (0x1 << S5P_FIMV_D_SEI_ENABLE_RECOVERY_PARSING_SHIFT);
-
-       MFC_WRITEL(reg, S5P_FIMV_D_SEI_ENABLE);
-       mfc_debug(2, "SEI enable was set, 0x%x\n", MFC_READL(S5P_FIMV_D_SEI_ENABLE));
-
-       MFC_WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID);
-
-       if (sfr_dump & MFC_DUMP_DEC_SEQ_START)
-               call_dop(dev, dump_regs, dev);
-
-       s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_SEQ_HEADER);
-
-       mfc_debug_leave();
-       return 0;
-}
-
-/* Decode a single frame */
-int s5p_mfc_decode_one_frame(struct s5p_mfc_ctx *ctx, int last_frame)
-{
-       struct s5p_mfc_dev *dev;
-       struct s5p_mfc_dec *dec;
-       u32 reg = 0;
-
-       if (!ctx) {
-               mfc_err_dev("no mfc context to run\n");
-               return -EINVAL;
-       }
-
-       dev = ctx->dev;
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return -EINVAL;
-       }
-
-       dec = ctx->dec_priv;
-       if (!dec) {
-               mfc_err_dev("no mfc decoder to run\n");
-               return -EINVAL;
-       }
-
-       mfc_debug(2, "Dynamic:0x%08x, Available:0x%lx\n",
-                       dec->dynamic_set, dec->available_dpb);
-
-       reg = MFC_READL(S5P_FIMV_D_NAL_START_OPTIONS);
-       reg &= ~(0x1 << S5P_FIMV_D_NAL_START_OPT_BLACK_BAR_SHIFT);
-       reg |= ((dec->detect_black_bar & 0x1) << S5P_FIMV_D_NAL_START_OPT_BLACK_BAR_SHIFT);
-       MFC_WRITEL(reg, S5P_FIMV_D_NAL_START_OPTIONS);
-       mfc_debug(3, "[BLACKBAR] black bar detect set: %#x\n", reg);
-
-       MFC_WRITEL(dec->dynamic_set, S5P_FIMV_D_DYNAMIC_DPB_FLAG_LOWER);
-       MFC_WRITEL(0x0, S5P_FIMV_D_DYNAMIC_DPB_FLAG_UPPER);
-       MFC_WRITEL(dec->available_dpb, S5P_FIMV_D_AVAILABLE_DPB_FLAG_LOWER);
-       MFC_WRITEL(0x0, S5P_FIMV_D_AVAILABLE_DPB_FLAG_UPPER);
-       MFC_WRITEL(dec->slice_enable, S5P_FIMV_D_SLICE_IF_ENABLE);
-       MFC_WRITEL(MFC_TIMEOUT_VALUE, S5P_FIMV_DEC_TIMEOUT_VALUE);
-
-       MFC_WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID);
-
-       if ((sfr_dump & MFC_DUMP_DEC_NAL_START) && !ctx->check_dump) {
-               call_dop(dev, dump_regs, dev);
-               ctx->check_dump = 1;
-       }
-
-       /* Issue different commands to instance basing on whether it
-        * is the last frame or not. */
-       switch (last_frame) {
-       case 0:
-               s5p_mfc_perf_measure_on(dev);
-
-               s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_NAL_START);
-               break;
-       case 1:
-               s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_LAST_FRAME);
-               break;
-       }
-
-       mfc_debug(2, "Decoding a usual frame\n");
-       return 0;
-}
-
-int s5p_mfc_init_encode(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       mfc_debug(2, "++\n");
-
-       if (IS_H264_ENC(ctx))
-               s5p_mfc_set_enc_params_h264(ctx);
-       else if (IS_MPEG4_ENC(ctx))
-               s5p_mfc_set_enc_params_mpeg4(ctx);
-       else if (IS_H263_ENC(ctx))
-               s5p_mfc_set_enc_params_h263(ctx);
-       else if (IS_VP8_ENC(ctx))
-               s5p_mfc_set_enc_params_vp8(ctx);
-       else if (IS_VP9_ENC(ctx))
-               s5p_mfc_set_enc_params_vp9(ctx);
-       else if (IS_HEVC_ENC(ctx))
-               s5p_mfc_set_enc_params_hevc(ctx);
-       else if (IS_BPG_ENC(ctx))
-               s5p_mfc_set_enc_params_bpg(ctx);
-       else {
-               mfc_err_ctx("Unknown codec for encoding (%x)\n",
-                       ctx->codec_mode);
-               return -EINVAL;
-       }
-
-       mfc_debug(5, "RC) Bitrate: %d / framerate: %#x / config %#x / mode %#x\n",
-                       MFC_READL(S5P_FIMV_E_RC_BIT_RATE),
-                       MFC_READL(S5P_FIMV_E_RC_FRAME_RATE),
-                       MFC_READL(S5P_FIMV_E_RC_CONFIG),
-                       MFC_READL(S5P_FIMV_E_RC_MODE));
-
-       MFC_WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID);
-
-       if (sfr_dump & MFC_DUMP_ENC_SEQ_START)
-               call_dop(dev, dump_regs, dev);
-
-       s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_SEQ_HEADER);
-
-       mfc_debug(2, "--\n");
-
-       return 0;
-}
-
-static int mfc_h264_set_aso_slice_order(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_enc *enc = ctx->enc_priv;
-       struct s5p_mfc_enc_params *p = &enc->params;
-       struct s5p_mfc_h264_enc_params *p_264 = &p->codec.h264;
-       int i;
-
-       if (p_264->aso_enable) {
-               for (i = 0; i < 8; i++)
-                       MFC_WRITEL(p_264->aso_slice_order[i],
-                               S5P_FIMV_E_H264_ASO_SLICE_ORDER_0 + i * 4);
-       }
-       return 0;
-}
-
-/* Encode a single frame */
-int s5p_mfc_encode_one_frame(struct s5p_mfc_ctx *ctx, int last_frame)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       mfc_debug(2, "++\n");
-
-       if (IS_H264_ENC(ctx))
-               mfc_h264_set_aso_slice_order(ctx);
-
-       s5p_mfc_set_slice_mode(ctx);
-
-       MFC_WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID);
-
-       if ((sfr_dump & MFC_DUMP_ENC_NAL_START) && !ctx->check_dump) {
-               call_dop(dev, dump_regs, dev);
-               ctx->check_dump = 1;
-       }
-
-       /* Issue different commands to instance basing on whether it
-        * is the last frame or not. */
-       switch (last_frame) {
-       case 0:
-               s5p_mfc_perf_measure_on(dev);
-
-               s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_NAL_START);
-               break;
-       case 1:
-               s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_LAST_FRAME);
-               break;
-       }
-
-       mfc_debug(2, "--\n");
-
-       return 0;
-}
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_inst.h b/drivers/media/platform/exynos/mfc/s5p_mfc_inst.h
deleted file mode 100644 (file)
index a82135e..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_inst.h
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __S5P_MFC_INST_H
-#define __S5P_MFC_INST_H __FILE__
-
-#include "s5p_mfc_common.h"
-
-int s5p_mfc_open_inst(struct s5p_mfc_ctx *ctx);
-int s5p_mfc_close_inst(struct s5p_mfc_ctx *ctx);
-int s5p_mfc_abort_inst(struct s5p_mfc_ctx *ctx);
-
-int s5p_mfc_init_decode(struct s5p_mfc_ctx *ctx);
-int s5p_mfc_decode_one_frame(struct s5p_mfc_ctx *ctx, int last_frame);
-
-int s5p_mfc_init_encode(struct s5p_mfc_ctx *ctx);
-int s5p_mfc_encode_one_frame(struct s5p_mfc_ctx *ctx, int last_frame);
-
-#endif /* __S5P_MFC_INST_H  */
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_irq.c b/drivers/media/platform/exynos/mfc/s5p_mfc_irq.c
deleted file mode 100644 (file)
index 731b119..0000000
+++ /dev/null
@@ -1,1564 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_irq.c
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include "s5p_mfc_irq.h"
-
-#include "s5p_mfc_hwlock.h"
-#include "s5p_mfc_nal_q.h"
-#include "s5p_mfc_otf.h"
-#include "s5p_mfc_opr.h"
-#include "s5p_mfc_sync.h"
-
-#include "s5p_mfc_pm.h"
-#include "s5p_mfc_cal.h"
-#include "s5p_mfc_perf_measure.h"
-#include "s5p_mfc_reg.h"
-#include "s5p_mfc_mmcache.h"
-
-#include "s5p_mfc_qos.h"
-#include "s5p_mfc_queue.h"
-#include "s5p_mfc_buf.h"
-#include "s5p_mfc_mem.h"
-
-static void mfc_handle_black_bar_info(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx)
-{
-       struct v4l2_rect new_black_bar;
-       int black_bar_info;
-       struct s5p_mfc_dec *dec = ctx->dec_priv;
-
-       black_bar_info = s5p_mfc_get_black_bar_detection();
-       mfc_debug(3, "[BLACKBAR] type: %#x\n", black_bar_info);
-
-       if (black_bar_info == S5P_FIMV_DISP_STATUS_BLACK_BAR) {
-               new_black_bar.left = s5p_mfc_get_black_bar_pos_x();
-               new_black_bar.top = s5p_mfc_get_black_bar_pos_y();
-               new_black_bar.width = s5p_mfc_get_black_bar_image_w();
-               new_black_bar.height = s5p_mfc_get_black_bar_image_h();
-       } else if (black_bar_info == S5P_FIMV_DISP_STATUS_BLACK_SCREEN) {
-               new_black_bar.left = -1;
-               new_black_bar.top = -1;
-               new_black_bar.width = ctx->img_width;
-               new_black_bar.height = ctx->img_height;
-       } else if (black_bar_info == S5P_FIMV_DISP_STATUS_NOT_DETECTED) {
-               new_black_bar.left = 0;
-               new_black_bar.top = 0;
-               new_black_bar.width = ctx->img_width;
-               new_black_bar.height = ctx->img_height;
-       } else {
-               mfc_err_ctx("[BLACKBAR] Not supported type: %#x\n", black_bar_info);
-               dec->black_bar_updated = 0;
-               return;
-       }
-
-       if ((new_black_bar.left == dec->black_bar.left) &&
-                       (new_black_bar.top == dec->black_bar.top) &&
-                       (new_black_bar.width == dec->black_bar.width) &&
-                       (new_black_bar.height == dec->black_bar.height)) {
-               mfc_debug(4, "[BLACKBAR] information was not changed\n");
-               dec->black_bar_updated = 0;
-               return;
-       }
-
-       dec->black_bar = new_black_bar;
-       dec->black_bar_updated = 1;
-}
-
-static unsigned int mfc_handle_frame_field(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       unsigned int interlace_type = 0, is_interlace = 0, is_mbaff = 0;
-       unsigned int field;
-
-       if (CODEC_INTERLACED(ctx))
-               is_interlace = s5p_mfc_is_interlace_picture();
-
-       if (CODEC_MBAFF(ctx))
-               is_mbaff = s5p_mfc_is_mbaff_picture();
-
-       if (is_interlace) {
-               interlace_type = s5p_mfc_get_interlace_type();
-               if (interlace_type)
-                       field = V4L2_FIELD_INTERLACED_TB;
-               else
-                       field = V4L2_FIELD_INTERLACED_BT;
-       } else if (is_mbaff) {
-               field = V4L2_FIELD_INTERLACED_TB;
-       } else {
-               field = V4L2_FIELD_NONE;
-       }
-
-       mfc_debug(2, "[INTERLACE] is_interlace: %d (type : %d), is_mbaff: %d, field: 0x%#x\n",
-                       is_interlace, interlace_type, is_mbaff, field);
-
-       return field;
-}
-
-static void mfc_handle_frame_all_extracted(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dec *dec = ctx->dec_priv;
-       struct s5p_mfc_buf *dst_mb;
-       int index, i, is_first = 1;
-
-       mfc_debug(2, "Decided to finish\n");
-       ctx->sequence++;
-
-       while (1) {
-               dst_mb = s5p_mfc_get_del_buf(&ctx->buf_queue_lock, &ctx->dst_buf_queue, MFC_BUF_NO_TOUCH_USED);
-               if (!dst_mb)
-                       break;
-
-               mfc_debug(2, "Cleaning up buffer: %d\n",
-                                         dst_mb->vb.vb2_buf.index);
-
-               index = dst_mb->vb.vb2_buf.index;
-
-               for (i = 0; i < ctx->dst_fmt->mem_planes; i++)
-                       vb2_set_plane_payload(&dst_mb->vb.vb2_buf, i, 0);
-
-               dst_mb->vb.sequence = (ctx->sequence++);
-               dst_mb->vb.field = mfc_handle_frame_field(ctx);
-               dst_mb->vb.reserved2 = 0;
-
-               clear_bit(dst_mb->vb.vb2_buf.index, &dec->available_dpb);
-
-               if (call_cop(ctx, get_buf_ctrls_val, ctx, &ctx->dst_ctrls[index]) < 0)
-                       mfc_err_ctx("failed in get_buf_ctrls_val\n");
-
-               if (is_first) {
-                       call_cop(ctx, get_buf_update_val, ctx,
-                               &ctx->dst_ctrls[index],
-                               V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG,
-                               dec->stored_tag);
-                       is_first = 0;
-               } else {
-                       call_cop(ctx, get_buf_update_val, ctx,
-                               &ctx->dst_ctrls[index],
-                               V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG,
-                               DEFAULT_TAG);
-                       call_cop(ctx, get_buf_update_val, ctx,
-                               &ctx->dst_ctrls[index],
-                               V4L2_CID_MPEG_VIDEO_H264_SEI_FP_AVAIL,
-                               0);
-               }
-
-               vb2_buffer_done(&dst_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
-
-               /* decoder dst buffer CFW UNPROT */
-               if (ctx->is_drm)
-                       s5p_mfc_raw_unprotect(ctx, dst_mb, index);
-
-               mfc_debug(2, "Cleaned up buffer: %d\n", index);
-       }
-
-       s5p_mfc_handle_force_change_status(ctx);
-       mfc_debug(2, "After cleanup\n");
-}
-
-static void mfc_handle_frame_copy_timestamp(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_buf *ref_mb, *src_mb;
-       dma_addr_t dec_y_addr;
-
-       dec_y_addr = (dma_addr_t)s5p_mfc_get_dec_y_addr();
-
-       /* Get the source buffer */
-       src_mb = s5p_mfc_get_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, MFC_BUF_NO_TOUCH_USED);
-       if (!src_mb) {
-               mfc_err_dev("[TS] no src buffers\n");
-               return;
-       }
-
-       ref_mb = s5p_mfc_find_buf(&ctx->buf_queue_lock, &ctx->ref_buf_queue, dec_y_addr);
-       if (ref_mb)
-               ref_mb->vb.vb2_buf.timestamp = src_mb->vb.vb2_buf.timestamp;
-}
-
-static void mfc_handle_frame_output_move(struct s5p_mfc_ctx *ctx,
-               dma_addr_t dspl_y_addr, unsigned int released_flag)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_dec *dec = ctx->dec_priv;
-       struct s5p_mfc_buf *ref_mb;
-       int index;
-
-       ref_mb = s5p_mfc_find_move_buf(&ctx->buf_queue_lock,
-                       &ctx->dst_buf_queue, &ctx->ref_buf_queue, dspl_y_addr, released_flag);
-       if (ref_mb) {
-               index = ref_mb->vb.vb2_buf.index;
-
-               /* Check if this is the buffer we're looking for */
-               mfc_debug(2, "[DPB] Found buf[%d] 0x%08llx, looking for disp addr 0x%08llx\n",
-                               index, ref_mb->addr[0][0], dspl_y_addr);
-
-               if (released_flag & (1 << index)) {
-                       dec->available_dpb &= ~(1 << index);
-                       released_flag &= ~(1 << index);
-                       mfc_debug(2, "[DPB] Corrupted frame(%d), it will be re-used(release)\n",
-                                       s5p_mfc_get_warn(s5p_mfc_get_int_err()));
-               } else {
-                       dec->err_reuse_flag |= 1 << index;
-                       mfc_debug(2, "[DPB] Corrupted frame(%d), it will be re-used(not released)\n",
-                                       s5p_mfc_get_warn(s5p_mfc_get_int_err()));
-               }
-               dec->dynamic_used |= released_flag;
-       }
-}
-
-static void mfc_handle_frame_output_del(struct s5p_mfc_ctx *ctx,
-               unsigned int err, unsigned int released_flag)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_dec *dec = ctx->dec_priv;
-       struct s5p_mfc_raw_info *raw = &ctx->raw_buf;
-       struct s5p_mfc_buf *ref_mb;
-       dma_addr_t dspl_y_addr;
-       unsigned int frame_type;
-       unsigned int dst_frame_status;
-       unsigned int is_video_signal_type = 0, is_colour_description = 0;
-       unsigned int is_content_light = 0, is_display_colour = 0;
-       unsigned int i, index;
-
-       if (MFC_FEATURE_SUPPORT(dev, dev->pdata->color_aspect_dec)) {
-               is_video_signal_type = s5p_mfc_get_video_signal_type();
-               is_colour_description = s5p_mfc_get_colour_description();
-       }
-
-       if (MFC_FEATURE_SUPPORT(dev, dev->pdata->static_info_dec)) {
-               is_content_light = s5p_mfc_get_sei_avail_content_light();
-               is_display_colour = s5p_mfc_get_sei_avail_mastering_display();
-       }
-
-       if (MFC_FEATURE_SUPPORT(dev, dev->pdata->black_bar) && dec->detect_black_bar)
-               mfc_handle_black_bar_info(dev, ctx);
-       else
-               dec->black_bar_updated = 0;
-
-       if (dec->immediate_display == 1) {
-               dspl_y_addr = (dma_addr_t)s5p_mfc_get_dec_y_addr();
-               frame_type = s5p_mfc_get_dec_frame_type();
-       } else {
-               dspl_y_addr = (dma_addr_t)s5p_mfc_get_disp_y_addr();
-               frame_type = s5p_mfc_get_disp_frame_type();
-       }
-
-       ref_mb = s5p_mfc_find_del_buf(&ctx->buf_queue_lock,
-                       &ctx->ref_buf_queue, dspl_y_addr);
-       if (ref_mb) {
-               index = ref_mb->vb.vb2_buf.index;
-               /* Check if this is the buffer we're looking for */
-               mfc_debug(2, "[BUFINFO][DPB] ctx[%d] get dst index: %d, addr[0]: 0x%08llx\n",
-                               ctx->num, index, ref_mb->addr[0][0]);
-
-               ref_mb->vb.sequence = ctx->sequence;
-               ref_mb->vb.field = mfc_handle_frame_field(ctx);
-
-               /* Set reserved2 bits in order to inform SEI information */
-               ref_mb->vb.reserved2 = 0;
-
-               if (is_content_light) {
-                       ref_mb->vb.reserved2 |= (1 << 0);
-                       mfc_debug(2, "[HDR] content light level parsed\n");
-               }
-
-               if (is_display_colour) {
-                       ref_mb->vb.reserved2 |= (1 << 1);
-                       mfc_debug(2, "[HDR] mastering display colour parsed\n");
-               }
-
-               if (is_video_signal_type) {
-                       ref_mb->vb.reserved2 |= (1 << 4);
-                       mfc_debug(2, "[HDR] video signal type parsed\n");
-                       if (is_colour_description) {
-                               ref_mb->vb.reserved2 |= (1 << 2);
-                               mfc_debug(2, "[HDR] matrix coefficients parsed\n");
-                               ref_mb->vb.reserved2 |= (1 << 3);
-                               mfc_debug(2, "[HDR] colour description parsed\n");
-                       }
-               }
-
-               if (IS_VP9_DEC(ctx) && MFC_FEATURE_SUPPORT(dev, dev->pdata->color_aspect_dec)) {
-                       if (dec->color_space != S5P_FIMV_D_COLOR_UNKNOWN) {
-                               ref_mb->vb.reserved2 |= (1 << 3);
-                               mfc_debug(2, "[HDR] color space parsed\n");
-                       }
-                       ref_mb->vb.reserved2 |= (1 << 4);
-                       mfc_debug(2, "[HDR] color range parsed\n");
-               }
-
-               if (dec->black_bar_updated) {
-                       ref_mb->vb.reserved2 |= (1 << 5);
-                       mfc_debug(3, "[BLACKBAR] black bar detected\n");
-               }
-
-               if (ctx->src_fmt->mem_planes == 1) {
-                       vb2_set_plane_payload(&ref_mb->vb.vb2_buf, 0,
-                                       raw->total_plane_size);
-                       mfc_debug(5, "single plane payload: %d\n",
-                                       raw->total_plane_size);
-               } else {
-                       for (i = 0; i < ctx->src_fmt->mem_planes; i++) {
-                               vb2_set_plane_payload(&ref_mb->vb.vb2_buf, i,
-                                               raw->plane_size[i]);
-                       }
-               }
-
-               clear_bit(index, &dec->available_dpb);
-
-               ref_mb->vb.flags &= ~(V4L2_BUF_FLAG_KEYFRAME |
-                                       V4L2_BUF_FLAG_PFRAME |
-                                       V4L2_BUF_FLAG_BFRAME |
-                                       V4L2_BUF_FLAG_ERROR);
-
-               switch (frame_type) {
-                       case S5P_FIMV_DISPLAY_FRAME_I:
-                               ref_mb->vb.flags |= V4L2_BUF_FLAG_KEYFRAME;
-                               break;
-                       case S5P_FIMV_DISPLAY_FRAME_P:
-                               ref_mb->vb.flags |= V4L2_BUF_FLAG_PFRAME;
-                               break;
-                       case S5P_FIMV_DISPLAY_FRAME_B:
-                               ref_mb->vb.flags |= V4L2_BUF_FLAG_BFRAME;
-                               break;
-                       default:
-                               break;
-               }
-
-               if (s5p_mfc_get_warn(err)) {
-                       mfc_err_ctx("Warning for displayed frame: %d\n",
-                                       s5p_mfc_get_warn(err));
-                       ref_mb->vb.flags |= V4L2_BUF_FLAG_ERROR;
-               }
-
-               if (call_cop(ctx, get_buf_ctrls_val, ctx, &ctx->dst_ctrls[index]) < 0)
-                       mfc_err_ctx("failed in get_buf_ctrls_val\n");
-
-               s5p_mfc_handle_released_info(ctx, released_flag, index);
-
-               if (dec->immediate_display == 1) {
-                       dst_frame_status = s5p_mfc_get_dec_status();
-
-                       call_cop(ctx, get_buf_update_val, ctx,
-                                       &ctx->dst_ctrls[index],
-                                       V4L2_CID_MPEG_MFC51_VIDEO_DISPLAY_STATUS,
-                                       dst_frame_status);
-
-                       call_cop(ctx, get_buf_update_val, ctx,
-                                       &ctx->dst_ctrls[index],
-                                       V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG,
-                                       dec->stored_tag);
-
-                       dec->immediate_display = 0;
-               }
-
-               /* Update frame tag for packed PB */
-               if (CODEC_MULTIFRAME(ctx) && (dec->y_addr_for_pb == dspl_y_addr)) {
-                       call_cop(ctx, get_buf_update_val, ctx,
-                                       &ctx->dst_ctrls[index],
-                                       V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG,
-                                       dec->stored_tag);
-                       dec->y_addr_for_pb = 0;
-               }
-
-               s5p_mfc_qos_update_last_framerate(ctx, ref_mb->vb.vb2_buf.timestamp);
-               vb2_buffer_done(&ref_mb->vb.vb2_buf, s5p_mfc_get_warn(err) ?
-                               VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
-       }
-}
-
-static void mfc_handle_frame_new(struct s5p_mfc_ctx *ctx, unsigned int err)
-{
-       struct s5p_mfc_dec *dec = ctx->dec_priv;
-       struct s5p_mfc_dev *dev = ctx->dev;
-       dma_addr_t dspl_y_addr;
-       unsigned int frame_type;
-       int mvc_view_id;
-       unsigned int prev_flag, released_flag = 0;
-
-       frame_type = s5p_mfc_get_disp_frame_type();
-       mvc_view_id = s5p_mfc_get_mvc_disp_view_id();
-
-       if (IS_H264_MVC_DEC(ctx)) {
-               if (mvc_view_id == 0)
-                       ctx->sequence++;
-       } else {
-               ctx->sequence++;
-       }
-
-       dspl_y_addr = s5p_mfc_get_disp_y_addr();
-
-       if (dec->immediate_display == 1) {
-               dspl_y_addr = (dma_addr_t)s5p_mfc_get_dec_y_addr();
-               frame_type = s5p_mfc_get_dec_frame_type();
-       }
-
-       mfc_debug(2, "[FRAME] frame type: %d\n", frame_type);
-
-       /* If frame is same as previous then skip and do not dequeue */
-       if (frame_type == S5P_FIMV_DISPLAY_FRAME_NOT_CODED)
-               if (!CODEC_NOT_CODED(ctx))
-                       return;
-
-       prev_flag = dec->dynamic_used;
-       dec->dynamic_used = s5p_mfc_get_dec_used_flag();
-       released_flag = prev_flag & (~dec->dynamic_used);
-
-       mfc_debug(2, "[DPB] Used flag: old = %08x, new = %08x, Released buffer = %08x\n",
-                       prev_flag, dec->dynamic_used, released_flag);
-
-       /* decoder dst buffer CFW UNPROT */
-       s5p_mfc_unprotect_released_dpb(ctx, released_flag);
-
-       if ((IS_VC1_RCV_DEC(ctx) &&
-               s5p_mfc_get_warn(err) == S5P_FIMV_ERR_SYNC_POINT_NOT_RECEIVED) ||
-               (s5p_mfc_get_warn(err) == S5P_FIMV_ERR_BROKEN_LINK))
-               mfc_handle_frame_output_move(ctx, dspl_y_addr, released_flag);
-       else
-               mfc_handle_frame_output_del(ctx, err, released_flag);
-}
-
-static void mfc_handle_frame_error(struct s5p_mfc_ctx *ctx,
-               unsigned int reason, unsigned int err)
-{
-       struct s5p_mfc_dec *dec;
-       struct s5p_mfc_buf *src_mb;
-       unsigned int index;
-
-       if (ctx->type == MFCINST_ENCODER) {
-               mfc_err_ctx("Encoder Interrupt Error: %d\n", err);
-               return;
-       }
-
-       dec = ctx->dec_priv;
-       if (!dec) {
-               mfc_err_dev("no mfc decoder to run\n");
-               return;
-       }
-
-       mfc_err_ctx("Interrupt Error: %d\n", err);
-
-       /* Get the source buffer */
-       src_mb = s5p_mfc_get_del_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, MFC_BUF_NO_TOUCH_USED);
-
-       if (!src_mb) {
-               mfc_err_dev("no src buffers\n");
-       } else {
-               index = src_mb->vb.vb2_buf.index;
-               if (call_cop(ctx, recover_buf_ctrls_val, ctx, &ctx->src_ctrls[index]) < 0)
-                       mfc_err_ctx("failed in recover_buf_ctrls_val\n");
-
-               mfc_debug(2, "MFC needs next buffer\n");
-               dec->consumed = 0;
-
-               if (call_cop(ctx, get_buf_ctrls_val, ctx, &ctx->src_ctrls[index]) < 0)
-                       mfc_err_ctx("failed in get_buf_ctrls_val\n");
-
-               /* decoder src buffer CFW UNPROT */
-               if (ctx->is_drm)
-                       s5p_mfc_stream_unprotect(ctx, src_mb, index);
-
-               vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_ERROR);
-       }
-
-       mfc_debug(2, "Assesing whether this context should be run again\n");
-}
-
-static void mfc_handle_ref_frame(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_dec *dec = ctx->dec_priv;
-       struct s5p_mfc_buf *dst_mb;
-       dma_addr_t dec_addr;
-
-       dec_addr = (dma_addr_t)s5p_mfc_get_dec_y_addr();
-
-       /* Try to search decoded address in whole dst queue */
-       dst_mb = s5p_mfc_find_move_buf_used(&ctx->buf_queue_lock,
-                       &ctx->ref_buf_queue, &ctx->dst_buf_queue, dec_addr);
-       if (dst_mb) {
-               mfc_debug(2, "[DPB] Found in dst queue = 0x%08llx, buf = 0x%08llx\n",
-                               dec_addr, dst_mb->addr[0][0]);
-
-               if (!(dec->dynamic_set & s5p_mfc_get_dec_used_flag()))
-                       dec->dynamic_used |= dec->dynamic_set;
-       } else {
-               mfc_debug(2, "[DPB] Can't find buffer for addr = 0x%08llx\n", dec_addr);
-       }
-}
-
-static void mfc_handle_reuse_buffer(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_dec *dec = ctx->dec_priv;
-       unsigned int prev_flag, released_flag = 0;
-       int i;
-
-       prev_flag = dec->dynamic_used;
-       dec->dynamic_used = s5p_mfc_get_dec_used_flag();
-       released_flag = prev_flag & (~dec->dynamic_used);
-
-       if (!released_flag)
-               return;
-
-       /* Reuse not referenced buf anymore */
-       for (i = 0; i < MFC_MAX_DPBS; i++)
-               if (released_flag & (1 << i))
-                       if (s5p_mfc_move_reuse_buffer(ctx, i))
-                               released_flag &= ~(1 << i);
-
-       /* Not reused buffer should be released when there is a display frame */
-       dec->dec_only_release_flag |= released_flag;
-       for (i = 0; i < MFC_MAX_DPBS; i++)
-               if (released_flag & (1 << i))
-                       clear_bit(i, &dec->available_dpb);
-}
-
-static void mfc_handle_frame_input(struct s5p_mfc_ctx *ctx, unsigned int err)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_dec *dec = ctx->dec_priv;
-       struct s5p_mfc_buf *src_mb;
-       unsigned int index;
-       int deleted = 0;
-       unsigned long consumed;
-
-       consumed = dec->consumed + s5p_mfc_get_consumed_stream();
-
-       if (s5p_mfc_get_err(err) == S5P_FIMV_ERR_NON_PAIRED_FIELD) {
-               /*
-                * For non-paired field, the same buffer need to be
-                * resubmitted and the consumed stream will be 0
-                */
-               mfc_debug(2, "Not paired field. Running again the same buffer\n");
-               return;
-       }
-
-       /* Get the source buffer */
-       src_mb = s5p_mfc_get_del_if_consumed(ctx, &ctx->src_buf_queue,
-                       s5p_mfc_get_consumed_stream(), STUFF_BYTE, err, &deleted);
-       if (!src_mb) {
-               mfc_err_dev("no src buffers\n");
-               return;
-       }
-
-       index = src_mb->vb.vb2_buf.index;
-       mfc_debug(2, "[BUFINFO] ctx[%d] get src index: %d, addr: 0x%08llx\n",
-                       ctx->num, index, src_mb->addr[0][0]);
-
-       if (!deleted) {
-               /* Run MFC again on the same buffer */
-               mfc_debug(2, "[MULTIFRAME] Running again the same buffer\n");
-
-               if (CODEC_MULTIFRAME(ctx))
-                       dec->y_addr_for_pb = (dma_addr_t)s5p_mfc_get_dec_y_addr();
-
-               dec->consumed = consumed;
-               dec->remained_size = src_mb->vb.vb2_buf.planes[0].bytesused
-                                       - dec->consumed;
-               dec->has_multiframe = 1;
-
-               MFC_TRACE_CTX("** consumed:%ld, remained:%ld, addr:0x%08llx\n",
-                       dec->consumed, dec->remained_size, dec->y_addr_for_pb);
-               /* Do not move src buffer to done_list */
-               return;
-       }
-
-       if (call_cop(ctx, recover_buf_ctrls_val, ctx, &ctx->src_ctrls[index]) < 0)
-               mfc_err_ctx("failed in recover_buf_ctrls_val\n");
-
-       dec->consumed = 0;
-       dec->remained_size = 0;
-
-       if (call_cop(ctx, get_buf_ctrls_val, ctx, &ctx->src_ctrls[index]) < 0)
-               mfc_err_ctx("failed in get_buf_ctrls_val\n");
-
-       /* decoder src buffer CFW UNPROT */
-       if (ctx->is_drm)
-               s5p_mfc_stream_unprotect(ctx, src_mb, index);
-
-       vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
-}
-
-/* Handle frame decoding interrupt */
-static void mfc_handle_frame(struct s5p_mfc_ctx *ctx,
-                       unsigned int reason, unsigned int err)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_dec *dec = ctx->dec_priv;
-       unsigned int dst_frame_status, sei_avail_frame_pack;
-       unsigned int res_change, need_dpb_change, need_scratch_change;
-
-       dst_frame_status = s5p_mfc_get_disp_status();
-       res_change = s5p_mfc_get_res_change();
-       need_dpb_change = s5p_mfc_get_dpb_change();
-       need_scratch_change = s5p_mfc_get_scratch_change();
-       sei_avail_frame_pack = s5p_mfc_get_sei_avail_frame_pack();
-
-       if (dec->immediate_display == 1)
-               dst_frame_status = s5p_mfc_get_dec_status();
-
-       mfc_debug(2, "[FRAME] frame status: %d\n", dst_frame_status);
-       mfc_debug(2, "[FRAME] display status: %d, type: %d, yaddr: %#x\n",
-                       s5p_mfc_get_disp_status(), s5p_mfc_get_disp_frame_type(),
-                       s5p_mfc_get_disp_y_addr());
-       mfc_debug(2, "[FRAME] decoded status: %d, type: %d, yaddr: %#x\n",
-                       s5p_mfc_get_dec_status(), s5p_mfc_get_dec_frame_type(),
-                       s5p_mfc_get_dec_y_addr());
-
-       mfc_debug(4, "[HDR] SEI available status: 0x%08x\n", s5p_mfc_get_sei_avail());
-       mfc_debug(4, "[HDR] SEI content light: 0x%08x\n", s5p_mfc_get_sei_content_light());
-       mfc_debug(4, "[HDR] SEI luminance: 0x%08x, 0x%08x white point: 0x%08x\n",
-                       s5p_mfc_get_sei_mastering0(), s5p_mfc_get_sei_mastering1(),
-                       s5p_mfc_get_sei_mastering2());
-       mfc_debug(4, "[HDR] SEI display primaries: 0x%08x, 0x%08x, 0x%08x\n",
-                       s5p_mfc_get_sei_mastering3(), s5p_mfc_get_sei_mastering4(),
-                       s5p_mfc_get_sei_mastering5());
-       mfc_debug(2, "[DPB] Used flag: old = %08x, new = %08x\n",
-                               dec->dynamic_used, s5p_mfc_get_dec_used_flag());
-
-       if (ctx->state == MFCINST_RES_CHANGE_INIT)
-               s5p_mfc_change_state(ctx, MFCINST_RES_CHANGE_FLUSH);
-
-       if (res_change) {
-               mfc_debug(2, "[DRC] Resolution change set to %d\n", res_change);
-               s5p_mfc_change_state(ctx, MFCINST_RES_CHANGE_INIT);
-               ctx->wait_state = WAIT_DECODING;
-               mfc_debug(7, "[DRC] Decoding waiting! : %d\n", ctx->wait_state);
-               return;
-       }
-
-       if (need_dpb_change || need_scratch_change)
-               mfc_debug(2, "[DRC] Interframe resolution change is not supported\n");
-
-       if (s5p_mfc_is_queue_count_same(&ctx->buf_queue_lock, &ctx->src_buf_queue, 0) &&
-               s5p_mfc_is_queue_count_same(&ctx->buf_queue_lock, &ctx->dst_buf_queue, 0)) {
-               mfc_err_dev("Queue count is zero for src and dst\n");
-               goto leave_handle_frame;
-       }
-
-       if (IS_H264_DEC(ctx) && sei_avail_frame_pack &&
-               dst_frame_status == S5P_FIMV_DEC_STATUS_DECODING_ONLY) {
-               mfc_debug(2, "Frame packing SEI exists for a frame\n");
-               mfc_debug(2, "Reallocate DPBs and issue init_buffer\n");
-               ctx->is_dpb_realloc = 1;
-               s5p_mfc_change_state(ctx, MFCINST_HEAD_PARSED);
-               ctx->capture_state = QUEUE_FREE;
-               ctx->wait_state = WAIT_DECODING;
-               mfc_handle_frame_all_extracted(ctx);
-               goto leave_handle_frame;
-       }
-
-       /* 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) {
-                       struct mfc_timestamp *temp_ts = NULL;
-
-                       mfc_debug(2, "[DRC] Last frame received after resolution change\n");
-                       mfc_handle_frame_all_extracted(ctx);
-                       s5p_mfc_change_state(ctx, MFCINST_RES_CHANGE_END);
-                       /* If there is no display frame after resolution change,
-                        * Some released frames can't be unprotected.
-                        * So, check and request unprotection in the end of DRC.
-                        */
-                       s5p_mfc_cleanup_assigned_dpb(ctx);
-
-                       /* empty the timestamp queue */
-                       while (!list_empty(&ctx->ts_list)) {
-                               temp_ts = list_entry((&ctx->ts_list)->next,
-                                               struct mfc_timestamp, list);
-                               list_del(&temp_ts->list);
-                       }
-                       ctx->ts_count = 0;
-                       ctx->ts_is_full = 0;
-                       s5p_mfc_qos_reset_last_framerate(ctx);
-                       s5p_mfc_qos_set_framerate(ctx, DEC_DEFAULT_FPS);
-
-                       goto leave_handle_frame;
-               } else {
-                       mfc_handle_frame_all_extracted(ctx);
-               }
-       }
-
-       if (s5p_mfc_get_num_of_tile() >= 4)
-               dec->num_of_tile_over_4 = 1;
-
-       switch (dst_frame_status) {
-       case S5P_FIMV_DEC_STATUS_DECODING_DISPLAY:
-               mfc_handle_ref_frame(ctx);
-               break;
-       case S5P_FIMV_DEC_STATUS_DECODING_ONLY:
-               mfc_handle_ref_frame(ctx);
-               /*
-                * Some cases can have many decoding only frames like VP9
-                * alt-ref frame. So need handling release buffer
-                * because of DPB full.
-                */
-               mfc_handle_reuse_buffer(ctx);
-               break;
-       default:
-               break;
-       }
-
-       if (s5p_mfc_dec_status_decoding(dst_frame_status))
-               mfc_handle_frame_copy_timestamp(ctx);
-
-       /* A frame has been decoded and is in the buffer  */
-       if (s5p_mfc_dec_status_display(dst_frame_status))
-               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)
-               mfc_handle_frame_input(ctx, err);
-
-leave_handle_frame:
-       mfc_debug(2, "Assesing whether this context should be run again\n");
-}
-
-static void mfc_handle_stream_copy_timestamp(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf *src_mb)
-{
-       struct s5p_mfc_dev *dev;
-       struct s5p_mfc_enc *enc = ctx->enc_priv;
-       struct s5p_mfc_enc_params *p = &enc->params;
-       struct s5p_mfc_buf *dst_mb;
-       u32 interval;
-       u64 start_timestamp;
-       u64 new_timestamp;
-
-       if (!ctx) {
-               mfc_err_dev("[BUFCON][TS] no mfc context to run\n");
-               return;
-       }
-
-       dev = ctx->dev;
-       if (!dev) {
-               mfc_err_dev("[BUFCON][TS] no device to run\n");
-               return;
-       }
-
-       start_timestamp = src_mb->vb.vb2_buf.timestamp;
-       interval = NSEC_PER_SEC / p->rc_framerate;
-       if (debug_ts == 1)
-               mfc_info_ctx("[BUFCON][TS] %dfps, start timestamp: %lld, base interval: %d\n",
-                               p->rc_framerate, start_timestamp, interval);
-
-       new_timestamp = start_timestamp + (interval * src_mb->done_index);
-       if (debug_ts == 1)
-               mfc_info_ctx("[BUFCON][TS] new timestamp: %lld, interval: %d\n",
-                               new_timestamp, interval * src_mb->done_index);
-
-       /* Get the destination buffer */
-       dst_mb = s5p_mfc_get_buf(&ctx->buf_queue_lock, &ctx->dst_buf_queue, MFC_BUF_NO_TOUCH_USED);
-       if (dst_mb)
-               dst_mb->vb.vb2_buf.timestamp = new_timestamp;
-}
-
-static void mfc_handle_stream_input(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_raw_info *raw;
-       struct s5p_mfc_buf *ref_mb, *src_mb;
-       dma_addr_t enc_addr[3] = { 0, 0, 0 };
-       int i, found_in_src_queue = 0;
-       unsigned int index;
-
-       raw = &ctx->raw_buf;
-
-       s5p_mfc_get_enc_frame_buffer(ctx, &enc_addr[0], raw->num_planes);
-       if (enc_addr[0] == 0) {
-               mfc_debug(3, "no encoded src\n");
-               goto move_buf;
-       }
-       for (i = 0; i < raw->num_planes; i++)
-               mfc_debug(2, "[BUFINFO] ctx[%d] get src addr[%d]: 0x%08llx\n",
-                               ctx->num, i, enc_addr[i]);
-
-       if (IS_BUFFER_BATCH_MODE(ctx)) {
-               src_mb = s5p_mfc_find_first_buf(&ctx->buf_queue_lock,
-                               &ctx->src_buf_queue, enc_addr[0]);
-               if (src_mb) {
-                       found_in_src_queue = 1;
-
-                       mfc_handle_stream_copy_timestamp(ctx, src_mb);
-                       src_mb->done_index++;
-                       mfc_debug(4, "[BUFCON] batch buf done_index: %d\n", src_mb->done_index);
-
-                       index = src_mb->vb.vb2_buf.index;
-
-                       if (call_cop(ctx, recover_buf_ctrls_val, ctx,
-                                               &ctx->src_ctrls[index]) < 0)
-                               mfc_err_ctx("failed in recover_buf_ctrls_val\n");
-
-                       /* single buffer || last image in a buffer container */
-                       if (!src_mb->num_valid_bufs || src_mb->done_index == src_mb->num_valid_bufs) {
-                               src_mb = s5p_mfc_find_del_buf(&ctx->buf_queue_lock,
-                                               &ctx->src_buf_queue, enc_addr[0]);
-                               for (i = 0; i < raw->num_planes; i++)
-                                       s5p_mfc_bufcon_put_daddr(ctx, src_mb, i);
-                               vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
-                       }
-
-                       /* encoder src buffer CFW UNPROT */
-                       if (ctx->is_drm)
-                               s5p_mfc_raw_unprotect(ctx, src_mb, index);
-               }
-       } else {
-               /* normal single buffer */
-               src_mb = s5p_mfc_find_del_buf(&ctx->buf_queue_lock,
-                               &ctx->src_buf_queue, enc_addr[0]);
-               if (src_mb) {
-                       found_in_src_queue = 1;
-                       index = src_mb->vb.vb2_buf.index;
-                       if (call_cop(ctx, recover_buf_ctrls_val, ctx,
-                                               &ctx->src_ctrls[index]) < 0)
-                               mfc_err_ctx("failed in recover_buf_ctrls_val\n");
-
-                       mfc_debug(3, "find src buf in src_queue\n");
-                       vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
-
-                       /* encoder src buffer CFW UNPROT */
-                       if (ctx->is_drm)
-                               s5p_mfc_raw_unprotect(ctx, src_mb, index);
-               } else {
-                       mfc_debug(3, "no src buf in src_queue\n");
-                       ref_mb = s5p_mfc_find_del_buf(&ctx->buf_queue_lock,
-                                       &ctx->ref_buf_queue, enc_addr[0]);
-                       if (ref_mb) {
-                               mfc_debug(3, "find src buf in ref_queue\n");
-                               vb2_buffer_done(&ref_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
-
-                               /* encoder src buffer CFW UNPROT */
-                               if (ctx->is_drm) {
-                                       index = ref_mb->vb.vb2_buf.index;
-                                       s5p_mfc_raw_unprotect(ctx, ref_mb, index);
-                               }
-                       } else {
-                               mfc_err_ctx("couldn't find src buffer\n");
-                       }
-               }
-       }
-
-move_buf:
-       /* move enqueued src buffer: src queue -> ref queue */
-       if (!found_in_src_queue && ctx->state != MFCINST_FINISHING) {
-               s5p_mfc_move_first_buf_used(&ctx->buf_queue_lock,
-                               &ctx->ref_buf_queue, &ctx->src_buf_queue, MFC_QUEUE_ADD_BOTTOM);
-
-               mfc_debug(2, "enc src_buf_queue(%d) -> ref_buf_queue(%d)\n",
-                               s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->src_buf_queue),
-                               s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->ref_buf_queue));
-       }
-}
-
-static void mfc_handle_stream_output(struct s5p_mfc_ctx *ctx, int slice_type,
-                                       unsigned int strm_size)
-{
-       struct s5p_mfc_enc *enc = ctx->enc_priv;
-       struct s5p_mfc_buf *dst_mb;
-       unsigned int index;
-
-       if (strm_size == 0) {
-               mfc_debug(3, "no encoded dst (reuse)\n");
-               return;
-       } else if (strm_size < 0) {
-               mfc_err_ctx("invalid stream size: %d\n", strm_size);
-               return;
-       }
-
-       /* at least one more dest. buffers exist always  */
-       dst_mb = s5p_mfc_get_del_buf(&ctx->buf_queue_lock,
-                       &ctx->dst_buf_queue, MFC_BUF_NO_TOUCH_USED);
-       if (!dst_mb) {
-               mfc_err_ctx("no dst buffers\n");
-               return;
-       }
-
-       mfc_debug(2, "[BUFINFO] ctx[%d] get dst addr: 0x%08llx\n",
-                       ctx->num, dst_mb->addr[0][0]);
-
-       dst_mb->vb.flags &= ~(V4L2_BUF_FLAG_KEYFRAME |
-                               V4L2_BUF_FLAG_PFRAME |
-                               V4L2_BUF_FLAG_BFRAME);
-       switch (slice_type) {
-       case S5P_FIMV_E_SLICE_TYPE_I:
-               dst_mb->vb.flags |= V4L2_BUF_FLAG_KEYFRAME;
-               break;
-       case S5P_FIMV_E_SLICE_TYPE_P:
-               dst_mb->vb.flags |= V4L2_BUF_FLAG_PFRAME;
-               break;
-       case S5P_FIMV_E_SLICE_TYPE_B:
-               dst_mb->vb.flags |= V4L2_BUF_FLAG_BFRAME;
-               break;
-       default:
-               dst_mb->vb.flags |= V4L2_BUF_FLAG_KEYFRAME;
-               break;
-       }
-       mfc_debug(2, "[STREAM] Slice type flag: %d\n", dst_mb->vb.flags);
-
-       if (IS_BPG_ENC(ctx)) {
-               strm_size += enc->header_size;
-               mfc_debug(2, "bpg total stream size: %d\n", strm_size);
-       }
-       vb2_set_plane_payload(&dst_mb->vb.vb2_buf, 0, strm_size);
-
-       index = dst_mb->vb.vb2_buf.index;
-       if (call_cop(ctx, get_buf_ctrls_val, ctx, &ctx->dst_ctrls[index]) < 0)
-               mfc_err_ctx("failed in get_buf_ctrls_val\n");
-
-       vb2_buffer_done(&dst_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
-
-       /* encoder dst buffer CFW UNPROT */
-       if (ctx->is_drm)
-               s5p_mfc_stream_unprotect(ctx, dst_mb, index);
-}
-
-/* Handle frame encoding interrupt */
-static int mfc_handle_stream(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_enc *enc = ctx->enc_priv;
-       int slice_type;
-       unsigned int strm_size;
-       unsigned int pic_count;
-
-       slice_type = s5p_mfc_get_enc_slice_type();
-       strm_size = s5p_mfc_get_enc_strm_size();
-       pic_count = s5p_mfc_get_enc_pic_count();
-
-       mfc_debug(2, "[STREAM] encoded slice type: %d, size: %d, display order: %d\n",
-                       slice_type, strm_size, pic_count);
-
-       /* buffer full handling */
-       if (enc->buf_full) {
-               s5p_mfc_change_state(ctx, MFCINST_ABORT_INST);
-               return 0;
-       }
-       if (ctx->state == MFCINST_RUNNING_BUF_FULL)
-               s5p_mfc_change_state(ctx, MFCINST_RUNNING);
-
-       /* set encoded frame type */
-       enc->frame_type = slice_type;
-       ctx->sequence++;
-
-       if (enc->in_slice) {
-               if (s5p_mfc_is_queue_count_same(&ctx->buf_queue_lock, &ctx->dst_buf_queue, 0)) {
-                       s5p_mfc_clear_bit(ctx->num, &dev->work_bits);
-               }
-               return 0;
-       }
-
-       /* handle source buffer */
-       mfc_handle_stream_input(ctx);
-
-       /* handle destination buffer */
-       mfc_handle_stream_output(ctx, slice_type, strm_size);
-
-       return 0;
-}
-
-/* Error handling for interrupt */
-static inline void mfc_handle_error(struct s5p_mfc_ctx *ctx,
-       unsigned int reason, unsigned int err)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_buf *src_mb;
-       int index;
-
-       mfc_err_ctx("Interrupt Error: display: %d, decoded: %d\n",
-                       s5p_mfc_get_warn(err), s5p_mfc_get_err(err));
-       err = s5p_mfc_get_err(err);
-
-       /* Error recovery is dependent on the state of context */
-       switch (ctx->state) {
-       case MFCINST_RES_CHANGE_END:
-       case MFCINST_GOT_INST:
-               /* This error had to happen while parsing the header */
-               if (!ctx->is_drm) {
-                       unsigned char *stream_vir = NULL;
-                       unsigned int strm_size = 0;
-
-                       src_mb = s5p_mfc_get_del_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, MFC_BUF_NO_TOUCH_USED);
-                       if (src_mb) {
-                               stream_vir = src_mb->vir_addr;
-                               strm_size = src_mb->vb.vb2_buf.planes[0].bytesused;
-                               if (strm_size > 32)
-                                       strm_size = 32;
-
-                               if (stream_vir && strm_size)
-                                       print_hex_dump(KERN_ERR, "No header: ",
-                                                       DUMP_PREFIX_ADDRESS, strm_size, 0,
-                                                       stream_vir, strm_size, false);
-
-                               vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
-                       }
-               } else {
-                       src_mb = s5p_mfc_get_del_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, MFC_BUF_NO_TOUCH_USED);
-                       if (src_mb) {
-                               index = src_mb->vb.vb2_buf.index;
-                               /* decoder src buffer CFW UNPROT */
-                               s5p_mfc_stream_unprotect(ctx, src_mb, index);
-                               vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
-                       }
-               }
-               break;
-       case MFCINST_INIT:
-               /* This error had to happen while acquireing instance */
-       case MFCINST_RETURN_INST:
-               /* This error had to happen while releasing instance */
-       case MFCINST_DPB_FLUSHING:
-               /* This error had to happen while flushing DPB */
-       case MFCINST_SPECIAL_PARSING:
-       case MFCINST_SPECIAL_PARSING_NAL:
-               /* This error had to happen while special parsing */
-               break;
-       case MFCINST_HEAD_PARSED:
-               /* This error had to happen while setting dst buffers */
-       case MFCINST_RES_CHANGE_INIT:
-       case MFCINST_RES_CHANGE_FLUSH:
-               /* This error has to happen while resolution change */
-       case MFCINST_ABORT_INST:
-               /* This error has to happen while buffer full handling */
-       case MFCINST_FINISHING:
-               /* It is higly probable that an error occured
-                * while decoding a frame */
-               s5p_mfc_change_state(ctx, MFCINST_ERROR);
-               /* Mark all dst buffers as having an error */
-               s5p_mfc_cleanup_queue(&ctx->buf_queue_lock, &ctx->dst_buf_queue);
-               /* Mark all src buffers as having an error */
-               s5p_mfc_cleanup_queue(&ctx->buf_queue_lock, &ctx->src_buf_queue);
-               break;
-       default:
-               mfc_err_ctx("Encountered an error interrupt which had not been handled\n");
-               mfc_err_ctx("ctx->state = %d, ctx->inst_no = %d\n",
-                                               ctx->state, ctx->inst_no);
-               break;
-       }
-
-       s5p_mfc_wake_up_dev(dev, reason, err);
-
-       return;
-}
-
-/* Handle header decoder interrupt */
-static int mfc_handle_seq_dec(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_dec *dec = ctx->dec_priv;
-       int i, is_interlace, is_mbaff;
-
-       if (ctx->src_fmt->fourcc != V4L2_PIX_FMT_FIMV1) {
-               ctx->img_width = s5p_mfc_get_img_width();
-               ctx->img_height = s5p_mfc_get_img_height();
-               ctx->crop_width = ctx->img_width;
-               ctx->crop_height = ctx->img_height;
-               mfc_info_ctx("[STREAM] resolution w: %d, h: %d\n", ctx->img_width, ctx->img_height);
-       }
-
-       ctx->dpb_count = s5p_mfc_get_dpb_count();
-       ctx->scratch_buf_size = s5p_mfc_get_scratch_size();
-       for (i = 0; i < ctx->dst_fmt->num_planes; i++)
-               ctx->min_dpb_size[i] = s5p_mfc_get_min_dpb_size(i);
-
-       s5p_mfc_dec_store_crop_info(ctx);
-       dec->mv_count = s5p_mfc_get_mv_count();
-       if (CODEC_10BIT(ctx) && dev->pdata->support_10bit) {
-               if (s5p_mfc_get_luma_bit_depth_minus8() ||
-                       s5p_mfc_get_chroma_bit_depth_minus8() ||
-                       s5p_mfc_get_profile() == S5P_FIMV_D_PROFILE_HEVC_MAIN_10) {
-                       ctx->is_10bit = 1;
-                       mfc_info_ctx("[STREAM][10BIT] 10bit contents, profile: %d, depth: %d/%d\n",
-                                       s5p_mfc_get_profile(),
-                                       s5p_mfc_get_luma_bit_depth_minus8() + 8,
-                                       s5p_mfc_get_chroma_bit_depth_minus8() + 8);
-               }
-       }
-       if (CODEC_422FORMAT(ctx) && dev->pdata->support_422) {
-               if (s5p_mfc_get_chroma_format() == S5P_FIMV_D_CHROMA_422) {
-                       ctx->is_422 = 1;
-                       mfc_info_ctx("[STREAM] 422 chroma format\n");
-               }
-       }
-
-       if (ctx->img_width == 0 || ctx->img_height == 0)
-               s5p_mfc_change_state(ctx, MFCINST_ERROR);
-       else
-               s5p_mfc_change_state(ctx, MFCINST_HEAD_PARSED);
-
-       if (ctx->state == MFCINST_HEAD_PARSED) {
-               is_interlace = s5p_mfc_is_interlace_picture();
-               is_mbaff = s5p_mfc_is_mbaff_picture();
-               if (is_interlace || is_mbaff)
-                       dec->is_interlaced = 1;
-               mfc_debug(2, "[INTERLACE] interlace: %d, mbaff: %d\n", is_interlace, is_mbaff);
-       }
-
-       if (IS_H264_DEC(ctx) || IS_H264_MVC_DEC(ctx) || IS_HEVC_DEC(ctx)) {
-               struct s5p_mfc_buf *src_mb = s5p_mfc_get_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, MFC_BUF_NO_TOUCH_USED);
-               if (src_mb) {
-                       dec->consumed += s5p_mfc_get_consumed_stream();
-                       mfc_debug(2, "[STREAM] header total size : %d, consumed : %lu\n",
-                                       src_mb->vb.vb2_buf.planes[0].bytesused, dec->consumed);
-                       if ((dec->consumed > 0) &&
-                                       (src_mb->vb.vb2_buf.planes[0].bytesused > dec->consumed)) {
-                               dec->remained_size = src_mb->vb.vb2_buf.planes[0].bytesused -
-                                       dec->consumed;
-                               mfc_debug(2, "[STREAM] there is remained bytes(%lu) after header parsing\n",
-                                               dec->remained_size);
-                       } else {
-                               dec->consumed = 0;
-                               dec->remained_size = 0;
-                       }
-               }
-       }
-
-       if (IS_VP9_DEC(ctx)) {
-               dec->color_range = s5p_mfc_get_color_range();
-               dec->color_space = s5p_mfc_get_color_space();
-               mfc_debug(2, "color range: %d, color space: %d, It's valid for VP9\n",
-                               dec->color_range, dec->color_space);
-       }
-
-       return 0;
-}
-
-/* Handle header encoder interrupt */
-static int mfc_handle_seq_enc(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_enc *enc = ctx->enc_priv;
-       struct s5p_mfc_enc_params *p = &enc->params;
-       struct s5p_mfc_buf *dst_mb;
-       int ret;
-
-       enc->header_size = s5p_mfc_get_enc_strm_size();
-       mfc_debug(2, "[STREAM] encoded slice type: %d, header size: %d, display order: %d\n",
-                       s5p_mfc_get_enc_slice_type(), enc->header_size,
-                       s5p_mfc_get_enc_pic_count());
-
-       if (IS_BPG_ENC(ctx)) {
-               dst_mb = s5p_mfc_get_buf(&ctx->buf_queue_lock, &ctx->dst_buf_queue, MFC_BUF_NO_TOUCH_USED);
-               if (!dst_mb) {
-                       mfc_err_dev("no dst buffers\n");
-                       return -EAGAIN;
-               }
-
-               dst_mb->vb.vb2_buf.planes[0].data_offset += (enc->header_size +
-                               p->codec.bpg.thumb_size + p->codec.bpg.exif_size);
-               mfc_debug(2, "offset for NAL_START: %d (header: %d + thumb: %d + exif: %d)\n",
-                               dst_mb->vb.vb2_buf.planes[0].data_offset,
-                               enc->header_size,
-                               p->codec.bpg.thumb_size,
-                               p->codec.bpg.exif_size);
-       } else {
-               if ((p->seq_hdr_mode == V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE) ||
-                       (p->seq_hdr_mode == V4L2_MPEG_VIDEO_HEADER_MODE_AT_THE_READY)) {
-                       dst_mb = s5p_mfc_get_del_buf(&ctx->buf_queue_lock,
-                                       &ctx->dst_buf_queue, MFC_BUF_NO_TOUCH_USED);
-                       if (!dst_mb) {
-                               mfc_err_dev("no dst buffers\n");
-                               return -EAGAIN;
-                       }
-
-                       vb2_set_plane_payload(&dst_mb->vb.vb2_buf, 0, s5p_mfc_get_enc_strm_size());
-                       vb2_buffer_done(&dst_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
-
-                       /* encoder dst buffer CFW UNPROT */
-                       if (ctx->is_drm) {
-                               int index = dst_mb->vb.vb2_buf.index;
-
-                               s5p_mfc_stream_unprotect(ctx, dst_mb, index);
-                       }
-               }
-       }
-
-       ctx->dpb_count = s5p_mfc_get_enc_dpb_count();
-       ctx->scratch_buf_size = s5p_mfc_get_enc_scratch_size();
-
-       /* If the ROI is enabled at SEQ_START, clear ROI_ENABLE bit */
-       s5p_mfc_clear_roi_enable(dev);
-
-       if (!ctx->codec_buffer_allocated) {
-               mfc_debug(2, "[DRC] previous codec buffer is exist\n");
-
-               if (dev->has_mmcache && dev->mmcache.is_on_status)
-                       s5p_mfc_invalidate_mmcache(dev);
-
-               s5p_mfc_release_codec_buffers(ctx);
-       }
-       ret = s5p_mfc_alloc_codec_buffers(ctx);
-       if (ret) {
-               mfc_err_ctx("Failed to allocate encoding buffers\n");
-               return ret;
-       }
-
-       s5p_mfc_change_state(ctx, MFCINST_HEAD_PARSED);
-
-       return 0;
-}
-
-static inline int is_err_condition(unsigned int err)
-{
-       if (err == S5P_FIMV_ERR_NO_AVAILABLE_DPB ||
-               err == S5P_FIMV_ERR_INSUFFICIENT_DPB_SIZE ||
-               err == S5P_FIMV_ERR_INSUFFICIENT_NUM_DPB ||
-               err == S5P_FIMV_ERR_INSUFFICIENT_MV_BUF_SIZE ||
-               err == S5P_FIMV_ERR_INSUFFICIENT_SCRATCH_BUF_SIZE)
-               return 1;
-
-       return 0;
-}
-
-irqreturn_t s5p_mfc_top_half_irq(int irq, void *priv)
-{
-       struct s5p_mfc_dev *dev = priv;
-       struct s5p_mfc_ctx *ctx;
-       unsigned int err;
-       unsigned int reason;
-
-       ctx = dev->ctx[dev->curr_ctx];
-       if (!ctx) {
-               mfc_err_dev("no mfc context to run\n");
-               return IRQ_WAKE_THREAD;
-       }
-
-       reason = s5p_mfc_get_int_reason();
-       err = s5p_mfc_get_int_err();
-       mfc_debug(2, "[c:%d] Int reason: %d (err: %d)\n",
-                       dev->curr_ctx, reason, err);
-       MFC_TRACE_CTX("<< INT(top): %d\n", reason);
-
-       s5p_mfc_perf_measure_off(dev);
-
-       return IRQ_WAKE_THREAD;
-}
-
-/*
- * Return value description
- *  0: NAL-Q is handled successfully
- *  1: NAL_START command
- * -1: Error
-*/
-static inline int mfc_nal_q_irq(struct s5p_mfc_dev *dev,
-               unsigned int reason, unsigned int err)
-{
-       int ret = -1;
-       unsigned int errcode;
-
-       nal_queue_handle *nal_q_handle = dev->nal_q_handle;
-       EncoderOutputStr *pOutStr;
-
-       switch (reason) {
-       case S5P_FIMV_R2H_CMD_QUEUE_DONE_RET:
-               pOutStr = s5p_mfc_nal_q_dequeue_out_buf(dev,
-                       nal_q_handle->nal_q_out_handle, &errcode);
-               if (pOutStr) {
-                       if (s5p_mfc_nal_q_handle_out_buf(dev, pOutStr))
-                               mfc_err_dev("[NALQ] Failed to handle out buf\n");
-               } else {
-                       mfc_err_dev("[NALQ] pOutStr is NULL\n");
-               }
-
-               if (nal_q_handle->nal_q_exception)
-                       s5p_mfc_set_bit(nal_q_handle->nal_q_out_handle->nal_q_ctx,
-                                       &dev->work_bits);
-               s5p_mfc_clear_int_sfr();
-
-               if (!nal_q_handle->nal_q_exception)
-                       s5p_mfc_nal_q_clock_off(dev, nal_q_handle);
-
-               ret = 0;
-               break;
-       case S5P_FIMV_R2H_CMD_COMPLETE_QUEUE_RET:
-               s5p_mfc_watchdog_stop_tick(dev);
-               nal_q_handle->nal_q_state = NAL_Q_STATE_CREATED;
-               MFC_TRACE_DEV("** NAL Q state : %d\n", nal_q_handle->nal_q_state);
-               mfc_debug(2, "[NALQ] return to created state\n");
-               s5p_mfc_nal_q_cleanup_queue(dev);
-               s5p_mfc_nal_q_cleanup_clock(dev);
-               s5p_mfc_clear_int_sfr();
-               s5p_mfc_pm_clock_off(dev);
-               s5p_mfc_wake_up_dev(dev, reason, err);
-
-               ret = 0;
-               break;
-       default:
-               if (nal_q_handle->nal_q_state == NAL_Q_STATE_STARTED ||
-                       nal_q_handle->nal_q_state == NAL_Q_STATE_STOPPED) {
-                       mfc_err_dev("[NALQ] Should not be here! state: %d, int reason : %d\n",
-                               nal_q_handle->nal_q_state, reason);
-                       s5p_mfc_clear_int_sfr();
-
-                       ret = -1;
-               } else {
-                       /* NAL START */
-                       ret = 1;
-               }
-
-               break;
-       }
-
-       if (ret == 0)
-               queue_work(dev->butler_wq, &dev->butler_work);
-
-       return ret;
-}
-
-static inline int mfc_handle_done_frame(struct s5p_mfc_ctx *ctx,
-                               unsigned int reason, unsigned int err)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_enc *enc = NULL;
-
-       if (ctx->type == MFCINST_DECODER) {
-               if (ctx->state == MFCINST_SPECIAL_PARSING_NAL) {
-                       s5p_mfc_clear_int_sfr();
-                       s5p_mfc_pm_clock_off(dev);
-                       s5p_mfc_clear_bit(ctx->num, &dev->work_bits);
-                       s5p_mfc_change_state(ctx, MFCINST_RUNNING);
-                       s5p_mfc_wake_up_ctx(ctx, reason, err);
-                       return 0;
-               }
-               mfc_handle_frame(ctx, reason, err);
-       } else if (ctx->type == MFCINST_ENCODER) {
-               if (ctx->otf_handle) {
-                       s5p_mfc_otf_handle_stream(ctx);
-                       return 1;
-               }
-               enc = ctx->enc_priv;
-               if (reason == S5P_FIMV_R2H_CMD_SLICE_DONE_RET) {
-                       dev->preempt_ctx = ctx->num;
-                       enc->buf_full = 0;
-                       enc->in_slice = 1;
-               } else if (reason == S5P_FIMV_R2H_CMD_ENC_BUFFER_FULL_RET) {
-                       mfc_err_ctx("stream buffer size(%d) isn't enough\n",
-                                       s5p_mfc_get_enc_strm_size());
-                       dev->preempt_ctx = ctx->num;
-                       enc->buf_full = 1;
-                       enc->in_slice = 0;
-               } else {
-                       enc->buf_full = 0;
-                       enc->in_slice = 0;
-               }
-               mfc_handle_stream(ctx);
-       }
-
-       return 1;
-}
-
-static inline void mfc_handle_nal_abort(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_enc *enc = ctx->enc_priv;
-
-       if (ctx->type == MFCINST_ENCODER) {
-               s5p_mfc_change_state(ctx, MFCINST_RUNNING_BUF_FULL);
-               enc->buf_full = 0;
-               if (IS_VP8_ENC(ctx))
-                       mfc_err_ctx("stream buffer size isn't enough\n");
-               mfc_handle_stream(ctx);
-       } else {
-               s5p_mfc_change_state(ctx, MFCINST_ABORT);
-       }
-}
-
-static int mfc_irq_dev(struct s5p_mfc_dev *dev, unsigned int reason, unsigned int err)
-{
-       /* Stop the timeout watchdog */
-       if (reason != S5P_FIMV_R2H_CMD_FW_STATUS_RET)
-               s5p_mfc_watchdog_stop_tick(dev);
-
-       switch (reason) {
-       case S5P_FIMV_R2H_CMD_CACHE_FLUSH_RET:
-       case S5P_FIMV_R2H_CMD_SYS_INIT_RET:
-       case S5P_FIMV_R2H_CMD_FW_STATUS_RET:
-       case S5P_FIMV_R2H_CMD_SLEEP_RET:
-       case S5P_FIMV_R2H_CMD_WAKEUP_RET:
-               s5p_mfc_clear_int_sfr();
-               s5p_mfc_wake_up_dev(dev, reason, err);
-               return 0;
-       }
-
-       return 1;
-}
-
-static int mfc_irq_ctx(struct s5p_mfc_ctx *ctx, unsigned int reason, unsigned int err)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       switch (reason) {
-       case S5P_FIMV_R2H_CMD_ERR_RET:
-               if (ctx->otf_handle) {
-                       s5p_mfc_otf_handle_error(ctx, reason, err);
-                       break;
-               }
-               /* An error has occured */
-               if (ctx->state == MFCINST_RUNNING || ctx->state == MFCINST_ABORT) {
-                       if ((s5p_mfc_get_err(err) >= S5P_FIMV_ERR_WARNINGS_START) &&
-                               (s5p_mfc_get_err(err) <= S5P_FIMV_ERR_WARNINGS_END))
-                               mfc_handle_frame(ctx, reason, err);
-                       else
-                               mfc_handle_frame_error(ctx, reason, err);
-               } else {
-                       mfc_handle_error(ctx, reason, err);
-               }
-               break;
-       case S5P_FIMV_R2H_CMD_SLICE_DONE_RET:
-       case S5P_FIMV_R2H_CMD_FIELD_DONE_RET:
-       case S5P_FIMV_R2H_CMD_FRAME_DONE_RET:
-       case S5P_FIMV_R2H_CMD_ENC_BUFFER_FULL_RET:
-               return mfc_handle_done_frame(ctx, reason, err);
-       case S5P_FIMV_R2H_CMD_COMPLETE_SEQ_RET:
-               if (ctx->type == MFCINST_ENCODER) {
-                       mfc_handle_stream(ctx);
-                       s5p_mfc_change_state(ctx, MFCINST_RUNNING);
-               } else if (ctx->type == MFCINST_DECODER) {
-                       return mfc_handle_done_frame(ctx, reason, err);
-               }
-               break;
-       case S5P_FIMV_R2H_CMD_SEQ_DONE_RET:
-               if (ctx->type == MFCINST_ENCODER) {
-                       if (ctx->otf_handle) {
-                               s5p_mfc_otf_handle_seq(ctx);
-                               break;
-                       }
-                       mfc_handle_seq_enc(ctx);
-               } else if (ctx->type == MFCINST_DECODER) {
-                       mfc_handle_seq_dec(ctx);
-               }
-               break;
-       case S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET:
-               ctx->inst_no = s5p_mfc_get_inst_no();
-               s5p_mfc_change_state(ctx, MFCINST_GOT_INST);
-               break;
-       case S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET:
-               s5p_mfc_change_state(ctx, MFCINST_FREE);
-               break;
-       case S5P_FIMV_R2H_CMD_NAL_ABORT_RET:
-               mfc_handle_nal_abort(ctx);
-               break;
-       case S5P_FIMV_R2H_CMD_DPB_FLUSH_RET:
-               s5p_mfc_change_state(ctx, MFCINST_ABORT);
-               break;
-       case S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET:
-               if (err != 0) {
-                       mfc_err_ctx("INIT_BUFFERS_RET error: %d\n", err);
-                       break;
-               }
-
-               s5p_mfc_change_state(ctx, MFCINST_RUNNING);
-               if (ctx->type == MFCINST_DECODER) {
-                       if (ctx->wait_state == WAIT_DECODING) {
-                               ctx->wait_state = WAIT_INITBUF_DONE;
-                               mfc_debug(2, "INIT_BUFFER has done, but can't start decoding\n");
-                       }
-                       if (ctx->is_dpb_realloc)
-                               ctx->is_dpb_realloc = 0;
-               }
-               break;
-       default:
-               mfc_err_ctx("Unknown int reason: %d\n", reason);
-       }
-
-       return 1;
-}
-
-/* Interrupt processing */
-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;
-       int ret = -1;
-
-       mfc_debug_enter();
-
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               goto irq_end;
-       }
-
-       if (s5p_mfc_pm_get_pwr_ref_cnt(dev) == 0) {
-               mfc_err_dev("no mfc power on\n");
-               call_dop(dev, dump_and_stop_debug_mode, dev);
-               goto irq_end;
-       }
-
-       /* Get the reason of interrupt and the error code */
-       reason = s5p_mfc_get_int_reason();
-       err = s5p_mfc_get_int_err();
-       mfc_debug(1, "Int reason: %d (err: %d)\n", reason, err);
-       MFC_TRACE_DEV("<< INT: %d\n", reason);
-
-       dev->preempt_ctx = MFC_NO_INSTANCE_SET;
-
-       if (dbg_enable && (reason != S5P_FIMV_R2H_CMD_QUEUE_DONE_RET))
-               s5p_mfc_dbg_disable(dev);
-
-       if ((sfr_dump & MFC_DUMP_ERR_INT) && (reason == S5P_FIMV_R2H_CMD_ERR_RET))
-               call_dop(dev, dump_regs, dev);
-
-       if ((sfr_dump & MFC_DUMP_WARN_INT) &&
-                       (err && (reason != S5P_FIMV_R2H_CMD_ERR_RET)))
-               call_dop(dev, dump_regs, dev);
-
-       if (is_err_condition(err))
-               call_dop(dev, dump_and_stop_debug_mode, dev);
-
-       if (dev->nal_q_handle) {
-               ret = mfc_nal_q_irq(dev, reason, err);
-               if (ret == 0) {
-                       mfc_debug(2, "[NALQ] command was handled\n");
-                       goto irq_end;
-               } else if (ret == 1){
-                       /* Path through */
-                       mfc_debug(2, "NAL_START command will be handled\n");
-               } else {
-                       mfc_debug(2, "[NALQ] command handling Error\n");
-                       goto irq_end;
-               }
-       }
-
-       ret = mfc_irq_dev(dev, reason, err);
-       if (!ret)
-               goto irq_end;
-
-       ctx = dev->ctx[dev->curr_ctx];
-       if (!ctx) {
-               mfc_err_dev("no mfc context to run\n");
-               s5p_mfc_clear_int_sfr();
-               s5p_mfc_pm_clock_off(dev);
-               goto irq_end;
-       }
-
-       ret = mfc_irq_ctx(ctx, reason, err);
-       if (!ret)
-               goto irq_end;
-
-       /* clean-up interrupt */
-       s5p_mfc_clear_int_sfr();
-
-       if ((ctx->state != MFCINST_RES_CHANGE_INIT) && (s5p_mfc_ctx_ready(ctx) == 0))
-               s5p_mfc_clear_bit(ctx->num, &dev->work_bits);
-
-       if (ctx->otf_handle) {
-               if (s5p_mfc_otf_ctx_ready(ctx))
-                       s5p_mfc_set_bit(ctx->num, &dev->work_bits);
-               else
-                       s5p_mfc_clear_bit(ctx->num, &dev->work_bits);
-       }
-
-       s5p_mfc_hwlock_handler_irq(dev, ctx, reason, err);
-
-irq_end:
-       mfc_debug_leave();
-       return IRQ_HANDLED;
-}
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_irq.h b/drivers/media/platform/exynos/mfc/s5p_mfc_irq.h
deleted file mode 100644 (file)
index 9ef20f8..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_irq.h
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __S5P_MFC_IRQ_H
-#define __S5P_MFC_IRQ_H __FILE__
-
-#include <linux/interrupt.h>
-
-#include "s5p_mfc_common.h"
-
-#include "s5p_mfc_utils.h"
-
-irqreturn_t s5p_mfc_top_half_irq(int irq, void *priv);
-irqreturn_t s5p_mfc_irq(int irq, void *priv);
-
-static inline void s5p_mfc_handle_force_change_status(struct s5p_mfc_ctx *ctx)
-{
-       if (ctx->state != MFCINST_ABORT && ctx->state != MFCINST_HEAD_PARSED &&
-                       ctx->state != MFCINST_RES_CHANGE_FLUSH)
-               s5p_mfc_change_state(ctx, MFCINST_RUNNING);
-}
-
-#endif /* __S5P_MFC_IRQ_H */
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_macros.h b/drivers/media/platform/exynos/mfc/s5p_mfc_macros.h
deleted file mode 100644 (file)
index cf0bb5a..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_macros.h
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __S5P_MFC_MACROS_H
-#define __S5P_MFC_MACROS_H __FILE__
-
-#define WIDTH_MB(x_size)       ((x_size + 15) / 16)
-#define HEIGHT_MB(y_size)      ((y_size + 15) / 16)
-
-/*
-   Note that lcu_width and lcu_height are defined as follows :
-   lcu_width = (frame_width + lcu_size - 1)/lcu_size
-   lcu_height = (frame_height + lcu_size - 1)/lcu_size.
-   (lcu_size is 32(encoder) or 64(decoder))
-*/
-#define DEC_LCU_WIDTH(x_size)  ((x_size + 63) / 64)
-#define ENC_LCU_WIDTH(x_size)  ((x_size + 31) / 32)
-#define DEC_LCU_HEIGHT(y_size) ((y_size + 63) / 64)
-#define ENC_LCU_HEIGHT(y_size) ((y_size + 31) / 32)
-
-#define STREAM_BUF_ALIGN               512
-#define MFC_LINEAR_BUF_SIZE            256
-#define set_strm_size_max(cpb_max)     ((cpb_max) - STREAM_BUF_ALIGN)
-
-#define DEC_STATIC_BUFFER_SIZE 20480
-
-#define DEC_MV_SIZE_MB(x, y)   (WIDTH_MB(x) * (((HEIGHT_MB(y)+1)/2)*2) * 64 + 1024)
-#define DEC_HEVC_MV_SIZE(x, y) (DEC_LCU_WIDTH(x) * DEC_LCU_HEIGHT(y) * 256 + 512)
-
-#define ENC_HEVC_LUMA_DPB_10B_SIZE(x, y)                               \
-       ((x + 63) / 64) * 64 * ((y + 31) / 32 ) * 32 +                  \
-       (((((ENC_LCU_WIDTH(x) * 32 + 3) / 4) + 15) / 16) * 16) *        \
-       ((y + 31) / 32 ) * 32 + 64
-#define ENC_HEVC_CHROMA_DPB_10B_SIZE(x, y)                             \
-       ((x + 63) / 64) * 64 * ((y + 31) / 32 ) * 32 +                  \
-       (((((ENC_LCU_WIDTH(x) * 32 + 3) / 4) + 15) / 16) * 16) *        \
-       ((y + 31) / 32 ) * 32 + 64
-#define ENC_VP9_LUMA_DPB_10B_SIZE(x, y)                                        \
-       (((x * 2 + 127) / 128) * 128) *                                 \
-       ((y + 31) / 32 ) * 32 + 64
-#define ENC_VP9_CHROMA_DPB_10B_SIZE(x, y)                              \
-       (((x * 2 + 127) / 128) * 128) *                                 \
-       ((y + 31) / 32 ) * 32 + 64
-#define ENC_LUMA_DPB_SIZE(x, y)                                                \
-       ((x + 63) / 64) * 64 * ((y + 31) / 32 ) * 32 + 64
-#define ENC_CHROMA_DPB_SIZE(x, y)                                      \
-       ((x + 63) / 64) * 64 * ((((y + 31) / 32 ) * 32) / 2) + 64
-
-#define ENC_V100_H264_ME_SIZE(x, y)                            \
-       (((x + 3) * (y + 3) * 8) + ((((x * y) + 63) / 64) * 32) + (((y * 64) + 2304) * (x + 7) / 8))
-#define ENC_V100_MPEG4_ME_SIZE(x, y)                           \
-       (((x + 3) * (y + 3) * 8) + ((((x * y) + 127) / 128) * 16) + (((y * 64) + 2304) * (x + 7) / 8))
-#define ENC_V100_VP8_ME_SIZE(x, y)                             \
-       (((x + 3) * (y + 3) * 8) + (((y * 64) + 2304) * (x + 7) / 8))
-#define ENC_V100_VP9_ME_SIZE(x, y)                             \
-       ((((x * 2) + 3) * ((y * 2) + 3) * 128) + (((y * 256) + 2304) * (x + 1) / 2))
-#define ENC_V100_HEVC_ME_SIZE(x, y)                            \
-       (((x + 3) * (y + 3) * 32) + (((y * 128) + 2304) * (x + 3) / 4))
-
-#endif /* __S5P_MFC_MACROS_H */
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_mem.c b/drivers/media/platform/exynos/mfc/s5p_mfc_mem.c
deleted file mode 100644 (file)
index f104d1a..0000000
+++ /dev/null
@@ -1,274 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_mem.c
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include "s5p_mfc_mem.h"
-
-struct vb2_mem_ops *s5p_mfc_mem_ops(void)
-{
-       return (struct vb2_mem_ops *)&vb2_dma_sg_memops;
-}
-
-void s5p_mfc_mem_clean(struct s5p_mfc_dev *dev,
-                       struct s5p_mfc_special_buf *special_buf,
-                       off_t offset, size_t size)
-{
-       __dma_map_area(special_buf->vaddr + offset, size, DMA_TO_DEVICE);
-       return;
-}
-
-void s5p_mfc_mem_invalidate(struct s5p_mfc_dev *dev,
-                       struct s5p_mfc_special_buf *special_buf,
-                       off_t offset, size_t size)
-{
-       __dma_map_area(special_buf->vaddr + offset, size, DMA_FROM_DEVICE);
-       return;
-}
-
-int s5p_mfc_mem_get_user_shared_handle(struct s5p_mfc_ctx *ctx,
-       struct mfc_user_shared_handle *handle)
-{
-       int ret = 0;
-
-       handle->dma_buf = dma_buf_get(handle->fd);
-       if (IS_ERR(handle->dma_buf)) {
-               mfc_err_ctx("Failed to import fd\n");
-               ret = PTR_ERR(handle->dma_buf);
-               goto import_dma_fail;
-       }
-
-       handle->vaddr = dma_buf_vmap(handle->dma_buf);
-       if (handle->vaddr == NULL) {
-               mfc_err_ctx("Failed to get kernel virtual address\n");
-               ret = -EINVAL;
-               goto map_kernel_fail;
-       }
-
-       return 0;
-
-map_kernel_fail:
-       handle->vaddr = NULL;
-       dma_buf_put(handle->dma_buf);
-
-import_dma_fail:
-       handle->dma_buf = NULL;
-       handle->fd = -1;
-       return ret;
-}
-
-void s5p_mfc_mem_cleanup_user_shared_handle(struct s5p_mfc_ctx *ctx,
-               struct mfc_user_shared_handle *handle)
-{
-       if (handle->vaddr)
-               dma_buf_vunmap(handle->dma_buf, handle->vaddr);
-       if (handle->dma_buf)
-               dma_buf_put(handle->dma_buf);
-
-       handle->dma_buf = NULL;
-       handle->vaddr = NULL;
-       handle->fd = -1;
-}
-
-int s5p_mfc_mem_ion_alloc(struct s5p_mfc_dev *dev,
-               struct s5p_mfc_special_buf *special_buf)
-{
-       struct s5p_mfc_ctx *ctx = dev->ctx[dev->curr_ctx];
-       int flag;
-       const char *heapname;
-
-       switch (special_buf->buftype) {
-       case MFCBUF_NORMAL:
-               heapname = "ion_system_heap";
-               flag = 0;
-               break;
-       case MFCBUF_NORMAL_FW:
-               heapname = "vnfw_heap";
-               flag = 0;
-               break;
-       case MFCBUF_DRM:
-               heapname = "vframe_heap";
-               flag = ION_FLAG_PROTECTED;
-               break;
-       case MFCBUF_DRM_FW:
-               heapname = "vfw_heap";
-               flag = ION_FLAG_PROTECTED;
-               break;
-       default:
-               mfc_err_ctx("not supported mfc mem type: %d, heapname: %s\n",
-                               special_buf->buftype, heapname);
-               return -EINVAL;
-       }
-       special_buf->dma_buf =
-                       ion_alloc_dmabuf(heapname, special_buf->size, flag);
-       if (IS_ERR(special_buf->dma_buf)) {
-               mfc_err_ctx("Failed to allocate buffer (err %ld)\n",
-                               PTR_ERR(special_buf->dma_buf));
-               call_dop(dev, dump_and_stop_debug_mode, dev);
-               goto err_ion_alloc;
-       }
-
-       special_buf->attachment = dma_buf_attach(special_buf->dma_buf, dev->device);
-       if (IS_ERR(special_buf->attachment)) {
-               mfc_err_ctx("Failed to get dma_buf_attach (err %ld)\n",
-                               PTR_ERR(special_buf->attachment));
-               call_dop(dev, dump_and_stop_debug_mode, dev);
-               goto err_attach;
-       }
-
-       special_buf->sgt = dma_buf_map_attachment(special_buf->attachment,
-                       DMA_BIDIRECTIONAL);
-       if (IS_ERR(special_buf->sgt)) {
-               mfc_err_ctx("Failed to get sgt (err %ld)\n",
-                               PTR_ERR(special_buf->sgt));
-               call_dop(dev, dump_and_stop_debug_mode, dev);
-               goto err_map;
-       }
-
-       special_buf->daddr = ion_iovmm_map(special_buf->attachment, 0,
-                       special_buf->size, DMA_BIDIRECTIONAL, 0);
-       if (IS_ERR_VALUE(special_buf->daddr)) {
-               mfc_err_ctx("Failed to allocate iova (err 0x%p)\n",
-                               &special_buf->daddr);
-               call_dop(dev, dump_and_stop_debug_mode, dev);
-               goto err_iovmm;
-       }
-
-       special_buf->vaddr = dma_buf_vmap(special_buf->dma_buf);
-       if (IS_ERR(special_buf->vaddr)) {
-               mfc_err_ctx("Failed to get vaddr (err 0x%p)\n",
-                               &special_buf->vaddr);
-               call_dop(dev, dump_and_stop_debug_mode, dev);
-               goto err_vaddr;
-       }
-
-       return 0;
-err_vaddr:
-       special_buf->vaddr = NULL;
-       ion_iovmm_unmap(special_buf->attachment, special_buf->daddr);
-
-err_iovmm:
-       special_buf->daddr = 0;
-       dma_buf_unmap_attachment(special_buf->attachment, special_buf->sgt,
-                                DMA_BIDIRECTIONAL);
-err_map:
-       special_buf->sgt = NULL;
-       dma_buf_detach(special_buf->dma_buf, special_buf->attachment);
-err_attach:
-       special_buf->attachment = NULL;
-       dma_buf_put(special_buf->dma_buf);
-err_ion_alloc:
-       special_buf->dma_buf = NULL;
-       return -ENOMEM;
-}
-
-void s5p_mfc_mem_ion_free(struct s5p_mfc_dev *dev,
-               struct s5p_mfc_special_buf *special_buf)
-{
-       if (special_buf->vaddr)
-               dma_buf_vunmap(special_buf->dma_buf, special_buf->vaddr);
-       if (special_buf->daddr)
-               ion_iovmm_unmap(special_buf->attachment, special_buf->daddr);
-       if (special_buf->sgt)
-               dma_buf_unmap_attachment(special_buf->attachment,
-                                        special_buf->sgt, DMA_BIDIRECTIONAL);
-       if (special_buf->attachment)
-               dma_buf_detach(special_buf->dma_buf, special_buf->attachment);
-       if (special_buf->dma_buf)
-               dma_buf_put(special_buf->dma_buf);
-
-       special_buf->dma_buf = NULL;
-       special_buf->attachment = NULL;
-       special_buf->sgt = NULL;
-       special_buf->daddr = 0;
-       special_buf->vaddr = NULL;
-}
-
-void s5p_mfc_bufcon_put_daddr(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf *mfc_buf, int plane)
-{
-       int i;
-
-       for (i = 0; i < mfc_buf->num_valid_bufs; i++) {
-               if (mfc_buf->addr[i][plane]) {
-                       mfc_debug(4, "[BUFCON] put batch buf addr[%d][%d]: 0x%08llx\n",
-                                       i, plane, mfc_buf->addr[i][plane]);
-                       ion_iovmm_unmap(mfc_buf->attachments[i][plane], mfc_buf->addr[i][plane]);
-               }
-               if (mfc_buf->attachments[i][plane])
-                       dma_buf_detach(mfc_buf->dmabufs[i][plane], mfc_buf->attachments[i][plane]);
-               if (mfc_buf->dmabufs[i][plane])
-                       dma_buf_put(mfc_buf->dmabufs[i][plane]);
-
-               mfc_buf->addr[i][plane] = 0;
-               mfc_buf->attachments[i][plane] = NULL;
-               mfc_buf->dmabufs[i][plane] = NULL;
-       }
-}
-
-int s5p_mfc_bufcon_get_daddr(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf *mfc_buf,
-                                       struct dma_buf *bufcon_dmabuf, int plane)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_raw_info *raw = &ctx->raw_buf;
-       int i, j = 0;
-       u32 mask;
-
-       if (dmabuf_container_get_mask(bufcon_dmabuf, &mask)) {
-               mfc_err_ctx("[BUFCON] it is not buffer container\n");
-               return -1;
-       } else {
-               mfc_debug(3, "[BUFCON] bufcon mask info %#x\n", mask);
-       }
-
-       for (i = 0; i < mfc_buf->num_bufs_in_batch; i++) {
-               if ((mask & (1 << i)) == 0) {
-                       mfc_debug(4, "[BUFCON] unmasked buf[%d]\n", i);
-                       continue;
-               }
-
-               mfc_buf->dmabufs[j][plane] = dmabuf_container_get_buffer(bufcon_dmabuf, i);
-               if (IS_ERR(mfc_buf->dmabufs[i][plane])) {
-                       mfc_err_ctx("[BUFCON] Failed to get dma_buf (err %ld)",
-                                       PTR_ERR(mfc_buf->dmabufs[i][plane]));
-                       call_dop(dev, dump_and_stop_debug_mode, dev);
-                       goto err_get_daddr;
-               }
-
-               mfc_buf->attachments[j][plane] = dma_buf_attach(mfc_buf->dmabufs[i][plane], dev->device);
-               if (IS_ERR(mfc_buf->attachments[i][plane])) {
-                       mfc_err_ctx("[BUFCON] Failed to get dma_buf_attach (err %ld)",
-                                       PTR_ERR(mfc_buf->attachments[i][plane]));
-                       call_dop(dev, dump_and_stop_debug_mode, dev);
-                       goto err_get_daddr;
-               }
-
-               mfc_buf->addr[j][plane] = ion_iovmm_map(mfc_buf->attachments[i][plane], 0,
-                               raw->plane_size[plane], DMA_BIDIRECTIONAL, 0);
-               if (IS_ERR_VALUE(mfc_buf->addr[i][plane])) {
-                       mfc_err_ctx("[BUFCON] Failed to allocate iova (err %pa)",
-                                       &mfc_buf->addr[i][plane]);
-                       call_dop(dev, dump_and_stop_debug_mode, dev);
-                       goto err_get_daddr;
-               }
-
-               mfc_debug(4, "[BUFCON] get batch buf addr[%d][%d]: 0x%08llx, size: %d\n",
-                               j, plane, mfc_buf->addr[j][plane], raw->plane_size[plane]);
-               j++;
-       }
-
-       mfc_buf->num_valid_bufs = j;
-       mfc_debug(3, "[BUFCON] batch buffer has %d buffers\n", mfc_buf->num_valid_bufs);
-
-       return 0;
-
-err_get_daddr:
-       s5p_mfc_bufcon_put_daddr(ctx, mfc_buf, plane);
-       return -1;
-}
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_mem.h b/drivers/media/platform/exynos/mfc/s5p_mfc_mem.h
deleted file mode 100644 (file)
index cca58a9..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_mem.h
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __S5P_MFC_MEM_H
-#define __S5P_MFC_MEM_H __FILE__
-
-#include "s5p_mfc_common.h"
-
-/* Offset base used to differentiate between CAPTURE and OUTPUT
-*  while mmaping */
-#define DST_QUEUE_OFF_BASE      (TASK_SIZE / 2)
-
-static inline dma_addr_t s5p_mfc_mem_get_daddr_vb(
-       struct vb2_buffer *vb, unsigned int n)
-{
-       dma_addr_t addr = 0;
-
-       addr = vb2_dma_sg_plane_dma_addr(vb, n);
-       WARN_ON((addr == 0) || IS_ERR_VALUE(addr));
-
-       return addr;
-}
-
-static inline int s5p_mfc_bufcon_get_buf_count(struct dma_buf *dmabuf)
-{
-       return dmabuf_container_get_count(dmabuf);
-}
-
-struct vb2_mem_ops *s5p_mfc_mem_ops(void);
-
-void s5p_mfc_mem_set_cacheable(bool cacheable);
-void s5p_mfc_mem_clean(struct s5p_mfc_dev *dev,
-                       struct s5p_mfc_special_buf *specail_buf,
-                       off_t offset, size_t size);
-void s5p_mfc_mem_invalidate(struct s5p_mfc_dev *dev,
-                       struct s5p_mfc_special_buf *specail_buf,
-                       off_t offset, size_t size);
-
-int s5p_mfc_mem_get_user_shared_handle(struct s5p_mfc_ctx *ctx,
-               struct mfc_user_shared_handle *handle);
-void s5p_mfc_mem_cleanup_user_shared_handle(struct s5p_mfc_ctx *ctx,
-               struct mfc_user_shared_handle *handle);
-
-int s5p_mfc_mem_ion_alloc(struct s5p_mfc_dev *dev,
-               struct s5p_mfc_special_buf *special_buf);
-void s5p_mfc_mem_ion_free(struct s5p_mfc_dev *dev,
-               struct s5p_mfc_special_buf *special_buf);
-
-void s5p_mfc_bufcon_put_daddr(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf *mfc_buf, int plane);
-int s5p_mfc_bufcon_get_daddr(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf *mfc_buf,
-                                       struct dma_buf *bufcon_dmabuf, int plane);
-#endif /* __S5P_MFC_MEM_H */
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_mmcache.c b/drivers/media/platform/exynos/mfc/s5p_mfc_mmcache.c
deleted file mode 100644 (file)
index 416bfbb..0000000
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_mmcache.c
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include "s5p_mfc_mmcache.h"
-
-#include "s5p_mfc_reg.h"
-
-static const unsigned char mmcache_SFR_0x0010[] = {
-       0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
-       0x2A, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
-
-static const unsigned char mmcache_SFR_0x0040[] = {
-       0x0E, 0x00, 0x1E, 0x00, 0x0E, 0x00, 0x1E, 0x00, 0x0E, 0x00, 0x1E, 0x00, 0x0E, 0x00, 0x1E, 0x00,
-       0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
-       0x10, 0x00, 0x1F, 0x00, 0x10, 0x00, 0x1F, 0x00, 0x10, 0x00, 0x1F, 0x00, 0x10, 0x00, 0x1F, 0x00,
-       0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
-       0x0C, 0x00, 0x1F, 0x00, 0x0C, 0x00, 0x1F, 0x00, 0x0C, 0x00, 0x1F, 0x00, 0x0C, 0x00, 0x1F, 0x00,
-       0x12, 0x00, 0x3F, 0x00, 0x08, 0x00, 0x3F, 0x00, 0x0C, 0x00, 0x3D, 0x00, 0x0C, 0x00, 0x3D, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
-
-static void mmcache_print_config(struct s5p_mfc_dev *dev)
-{
-       void __iomem *addr;
-       unsigned int size;
-
-       mfc_debug_enter();
-
-       if (!mmcache_dump)
-               return;
-
-       size = sizeof(mmcache_SFR_0x0010);
-       addr = dev->mmcache.base + MMCACHE_WAY0_CTRL;
-
-       print_hex_dump(KERN_ERR, "[MMCACHE] Config:", DUMP_PREFIX_ADDRESS, 32, 4, addr, size, false);
-
-       size = sizeof(mmcache_SFR_0x0040);
-       addr = dev->mmcache.base + MMCACHE_MASTER_GRP0_RPATH0;
-
-       print_hex_dump(KERN_ERR, "[MMCACHE] Config:", DUMP_PREFIX_ADDRESS, 32, 4, addr, size, false);
-
-       mfc_debug_leave();
-}
-
-static void mmcache_set_config(struct s5p_mfc_dev *dev)
-{
-       unsigned int data, i, size;
-       const unsigned int *sfr_dump;
-
-       mfc_debug_enter();
-
-       size = sizeof(mmcache_SFR_0x0010);
-       sfr_dump = (const unsigned int *)mmcache_SFR_0x0010;
-
-       for (i = 0; i < size; i += 4) {
-               data = sfr_dump[i / 4];
-               MMCACHE_WRITEL(data, MMCACHE_WAY0_CTRL + i);
-       }
-
-       size = sizeof(mmcache_SFR_0x0040);
-       sfr_dump = (const unsigned int *)mmcache_SFR_0x0040;
-
-       for (i = 0; i < size; i += 4) {
-               data = sfr_dump[i / 4];
-               MMCACHE_WRITEL(data, MMCACHE_MASTER_GRP0_RPATH0 + i);
-       }
-
-       mfc_debug(2, "[MMCACHE] mmcache config setting is done\n");
-
-       mfc_debug_leave();
-}
-
-static void mmcache_reset_config(struct s5p_mfc_dev *dev)
-{
-       void __iomem *addr;
-       unsigned int data;
-
-       mfc_debug_enter();
-
-       addr = dev->mmcache.base + MMCACHE_MASTER_GRP_CTRL2;
-       data = 0;
-
-       mfc_debug(2, "[MMCACHE] before write 0x%X: (0x%08llX) 0x%X\n",
-                       data, (unsigned long long)(addr),
-                       MMCACHE_READL(MMCACHE_MASTER_GRP_CTRL2));
-
-       MMCACHE_WRITEL(data, MMCACHE_MASTER_GRP_CTRL2);
-
-       mfc_debug(2, "[MMCACHE] after write 0x%X: (0x%08llX) 0x%X\n",
-                       data, (unsigned long long)(addr),
-                       MMCACHE_READL(MMCACHE_MASTER_GRP_CTRL2));
-
-       mfc_debug_leave();
-}
-
-static void mmcache_update_master_grp(struct s5p_mfc_dev *dev)
-{
-       void __iomem *addr;
-       unsigned int data;
-
-       mfc_debug_enter();
-
-       addr = dev->mmcache.base + MMCACHE_GLOBAL_CTRL;
-       data = MMCACHE_GLOBAL_CTRL_VALUE;
-
-       mfc_debug(2, "[MMCACHE] before write 0x%X: (0x%08llX) 0x%X\n",
-                       data, (unsigned long long)(addr),
-                       MMCACHE_READL(MMCACHE_GLOBAL_CTRL));
-
-       MMCACHE_WRITEL(data, MMCACHE_GLOBAL_CTRL);
-
-       mfc_debug(2, "[MMCACHE] after write 0x%X: (0x%08llX) 0x%X\n",
-                       data, (unsigned long long)(addr),
-                       MMCACHE_READL(MMCACHE_GLOBAL_CTRL));
-
-       mfc_debug_leave();
-}
-
-static void mmcache_enable_clock_gating(struct s5p_mfc_dev *dev)
-{
-       void __iomem *addr;
-       unsigned int data;
-
-       mfc_debug_enter();
-
-       addr = dev->mmcache.base + MMCACHE_CG_CONTROL;
-       data = MMCACHE_CG_CONTROL_VALUE;
-
-       mfc_debug(2, "[MMCACHE] before write 0x%X: (0x%08llX) 0x%X\n",
-                       data, (unsigned long long)(addr),
-                       MMCACHE_READL(MMCACHE_CG_CONTROL));
-
-       MMCACHE_WRITEL(data, MMCACHE_CG_CONTROL);
-
-       mfc_debug(2, "[MMCACHE] after write 0x%X: (0x%08llX) 0x%X\n",
-                       data, (unsigned long long)(addr),
-                       MMCACHE_READL(MMCACHE_CG_CONTROL));
-
-       mfc_debug_leave();
-}
-
-void s5p_mfc_mmcache_enable(struct s5p_mfc_dev *dev)
-{
-       mfc_debug_enter();
-
-       if (mmcache_disable)
-               return;
-
-       mmcache_set_config(dev);
-       mmcache_print_config(dev);
-       mmcache_update_master_grp(dev);
-       mmcache_enable_clock_gating(dev);
-
-       dev->mmcache.is_on_status = 1;
-       mfc_info_dev("[MMCACHE] enabled\n");
-       MFC_TRACE_DEV("[MMCACHE] enabled\n");
-
-       mfc_debug_leave();
-}
-
-void s5p_mfc_mmcache_disable(struct s5p_mfc_dev *dev)
-{
-       mfc_debug_enter();
-
-       mmcache_reset_config(dev);
-       mmcache_update_master_grp(dev);
-
-       dev->mmcache.is_on_status = 0;
-       mfc_info_dev("[MMCACHE] disabled\n");
-       MFC_TRACE_DEV("[MMCACHE] disabled\n");
-
-       mfc_debug_leave();
-}
-
-void s5p_mfc_invalidate_mmcache(struct s5p_mfc_dev *dev)
-{
-       void __iomem *addr;
-       unsigned int data;
-       unsigned long timeout;
-
-       mfc_debug_enter();
-
-       addr = dev->mmcache.base + MMCACHE_INVALIDATE;
-       data = MMCACHE_INVALIDATE_VALUE;
-
-       mfc_debug(2, "[MMCACHE] before write 0x%X: (0x%08llX) 0x%X\n",
-                       data, (unsigned long long)(addr),
-                       MMCACHE_READL(MMCACHE_INVALIDATE));
-
-       MMCACHE_WRITEL(data, MMCACHE_INVALIDATE);
-
-       mfc_debug(2, "[MMCACHE] after write 0x%X: (0x%08llX) 0x%X\n",
-                       data, (unsigned long long)(addr),
-                       MMCACHE_READL(MMCACHE_INVALIDATE));
-
-       addr = dev->mmcache.base + MMCACHE_INVALIDATE_STATUS;
-
-       timeout = jiffies + msecs_to_jiffies(MMCACHE_INVAL_TIMEOUT);
-       while (1) {
-               if (MMCACHE_READL(MMCACHE_INVALIDATE_STATUS) == 0) {
-                       mfc_debug(2, "[MMCACHE] invalidate done: (0x%08llX) 0x%X\n",
-                                       (unsigned long long)(addr), __raw_readl(addr));
-                       break;
-               }
-               if (time_after(jiffies, timeout)) {
-                       mfc_err_dev("[MMCACHE] Timeout while invalidation\n");
-                       call_dop(dev, dump_and_stop_debug_mode, dev);
-                       break;
-               }
-       }
-
-       mfc_debug(2, "[MMCACHE] invalidated\n");
-       MFC_TRACE_DEV("[MMCACHE] invalidated\n");
-
-       mfc_debug_leave();
-}
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_mmcache.h b/drivers/media/platform/exynos/mfc/s5p_mfc_mmcache.h
deleted file mode 100644 (file)
index f4cfa4d..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_mmcache.h
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __S5P_MFC_MMCACHE_H
-#define __S5P_MFC_MMCACHE_H __FILE__
-
-#include "s5p_mfc_common.h"
-
-#define MMCACHE_GLOBAL_CTRL            0x0000
-#define MMCACHE_INVALIDATE_STATUS      0x0008
-#define MMCACHE_WAY0_CTRL              0x0010
-#define MMCACHE_MASTER_GRP_CTRL2       0x0028
-#define MMCACHE_MASTER_GRP0_RPATH0     0x0040
-#define MMCACHE_CG_CONTROL             0x0400
-#define MMCACHE_INVALIDATE             0x0114
-
-#define MMCACHE_GLOBAL_CTRL_VALUE      0x2
-#define MMCACHE_CG_CONTROL_VALUE       0x7FF
-#define MMCACHE_INVALIDATE_VALUE       0x41
-
-/* Need HW lock to call this function */
-
-void s5p_mfc_mmcache_enable(struct s5p_mfc_dev *dev);
-void s5p_mfc_mmcache_disable(struct s5p_mfc_dev *dev);
-
-
-/* Need HW lock to call this function */
-void s5p_mfc_invalidate_mmcache(struct s5p_mfc_dev *dev);
-
-#endif /* __S5P_MFC_MMCACHE_H */
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_nal_q.c b/drivers/media/platform/exynos/mfc/s5p_mfc_nal_q.c
deleted file mode 100644 (file)
index 64e6c8f..0000000
+++ /dev/null
@@ -1,1997 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_nal_q.c
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include "s5p_mfc_nal_q.h"
-
-#include "s5p_mfc_sync.h"
-
-#include "s5p_mfc_pm.h"
-#include "s5p_mfc_cal.h"
-#include "s5p_mfc_reg.h"
-
-#include "s5p_mfc_qos.h"
-#include "s5p_mfc_queue.h"
-#include "s5p_mfc_utils.h"
-#include "s5p_mfc_buf.h"
-#include "s5p_mfc_mem.h"
-
-#define CBR_I_LIMIT_MAX                        5
-int s5p_mfc_nal_q_check_enable(struct s5p_mfc_dev *dev)
-{
-       struct s5p_mfc_ctx *temp_ctx;
-       struct s5p_mfc_dec *dec = NULL;
-       struct s5p_mfc_enc *enc = NULL;
-       struct s5p_mfc_enc_params *p = NULL;
-       int i;
-
-       mfc_debug_enter();
-
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return -EINVAL;
-       }
-
-       if (nal_q_disable)
-               return 0;
-
-       for (i = 0; i < MFC_NUM_CONTEXTS; i++) {
-               temp_ctx = dev->ctx[i];
-               if (temp_ctx) {
-                       /* NAL-Q doesn't support drm */
-                       if (temp_ctx->is_drm) {
-                               mfc_debug(2, "There is a drm ctx. Can't start NAL-Q\n");
-                               return 0;
-                       }
-                       /* NAL-Q can be enabled when all ctx are in running state */
-                       if (temp_ctx->state != MFCINST_RUNNING) {
-                               mfc_debug(2, "There is a ctx which is not in running state. "
-                                               "index: %d, state: %d\n", i, temp_ctx->state);
-                               return 0;
-                       }
-                       /* NAL-Q can't use the command about last frame */
-                       if (s5p_mfc_is_last_frame(temp_ctx) == 1) {
-                               mfc_debug(2, "There is a last frame. index: %d\n", i);
-                               return 0;
-                       }
-                       /* NAL-Q doesn't support OTF mode */
-                       if (temp_ctx->otf_handle) {
-                               mfc_debug(2, "There is a OTF node\n");
-                               return 0;
-                       }
-                       /* NAL-Q doesn't support BPG */
-                       if (IS_BPG_DEC(temp_ctx) || IS_BPG_ENC(temp_ctx)) {
-                               mfc_debug(2, "BPG codec type\n");
-                               return 0;
-                       }
-                       /* NAL-Q doesn't support multi-frame, interlaced, black bar */
-                       if (temp_ctx->type == MFCINST_DECODER) {
-                               dec = temp_ctx->dec_priv;
-                               if (!dec) {
-                                       mfc_debug(2, "There is no dec\n");
-                                       return 0;
-                               }
-                               if ((dec->has_multiframe && CODEC_MULTIFRAME(temp_ctx)) || dec->consumed) {
-                                       mfc_debug(2, "[MULTIFRAME] There is a multi frame or consumed header\n");
-                                       return 0;
-                               }
-                               if (dec->is_dpb_full) {
-                                       mfc_debug(2, "[DPB] All buffers are referenced\n");
-                                       return 0;
-                               }
-                               if (dec->is_interlaced) {
-                                       mfc_debug(2, "[INTERLACE] There is a interlaced stream\n");
-                                       return 0;
-                               }
-                               if (dec->detect_black_bar) {
-                                       mfc_debug(2, "[BLACKBAR] black bar detection is enabled\n");
-                                       return 0;
-                               }
-                       /* NAL-Q doesn't support fixed byte(slice mode), CBR_VT(rc mode) */
-                       } else if (temp_ctx->type == MFCINST_ENCODER) {
-                               enc = temp_ctx->enc_priv;
-                               if (!enc) {
-                                       mfc_debug(2, "There is no enc\n");
-                                       return 0;
-                               }
-                               if (enc->slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_FIXED_BYTES) {
-                                       mfc_debug(2, "There is fixed bytes option(slice mode)\n");
-                                       return 0;
-                               }
-                               p = &enc->params;
-                               if (p->rc_reaction_coeff <= CBR_I_LIMIT_MAX) {
-                                       mfc_debug(2, "There is CBR_VT option(rc mode)\n");
-                                       return 0;
-                               }
-                       }
-                       mfc_debug(2, "There is a ctx in running state. index: %d\n", i);
-               }
-       }
-
-       mfc_debug(2, "All working ctx are in running state!\n");
-
-       mfc_debug_leave();
-
-       return 1;
-}
-
-void s5p_mfc_nal_q_clock_on(struct s5p_mfc_dev *dev, nal_queue_handle *nal_q_handle)
-{
-       unsigned long flags;
-
-       mfc_debug_enter();
-
-       spin_lock_irqsave(&nal_q_handle->lock, flags);
-
-       mfc_debug(2, "[NALQ] continue_clock_on = %d, nal_q_clk_cnt = %d\n",
-                       dev->continue_clock_on, nal_q_handle->nal_q_clk_cnt);
-
-       if (!dev->continue_clock_on && !nal_q_handle->nal_q_clk_cnt)
-               s5p_mfc_pm_clock_on(dev);
-
-       nal_q_handle->nal_q_clk_cnt++;
-       dev->continue_clock_on = false;
-
-       mfc_debug(2, "[NALQ] nal_q_clk_cnt = %d\n", nal_q_handle->nal_q_clk_cnt);
-
-       spin_unlock_irqrestore(&nal_q_handle->lock, flags);
-
-       mfc_debug_leave();
-}
-
-void s5p_mfc_nal_q_clock_off(struct s5p_mfc_dev *dev, nal_queue_handle *nal_q_handle)
-{
-       unsigned long flags;
-
-       mfc_debug_enter();
-
-       spin_lock_irqsave(&nal_q_handle->lock, flags);
-
-       mfc_debug(2, "[NALQ] nal_q_clk_cnt = %d\n", nal_q_handle->nal_q_clk_cnt);
-
-       if (!nal_q_handle->nal_q_clk_cnt) {
-               mfc_err_dev("[NALQ] nal_q_clk_cnt is already zero\n");
-               return;
-       }
-
-       nal_q_handle->nal_q_clk_cnt--;
-
-       if (!nal_q_handle->nal_q_clk_cnt)
-               s5p_mfc_pm_clock_off(dev);
-
-       mfc_debug(2, "[NALQ] nal_q_clk_cnt = %d\n", nal_q_handle->nal_q_clk_cnt);
-
-       spin_unlock_irqrestore(&nal_q_handle->lock, flags);
-
-       mfc_debug_leave();
-}
-
-void s5p_mfc_nal_q_cleanup_clock(struct s5p_mfc_dev *dev)
-{
-       unsigned long flags;
-
-       mfc_debug_enter();
-
-       spin_lock_irqsave(&dev->nal_q_handle->lock, flags);
-
-       dev->nal_q_handle->nal_q_clk_cnt = 0;
-
-       spin_unlock_irqrestore(&dev->nal_q_handle->lock, flags);
-
-       mfc_debug_leave();
-}
-
-static int mfc_nal_q_find_ctx(struct s5p_mfc_dev *dev, EncoderOutputStr *pOutputStr)
-{
-       int i;
-
-       if (!dev) {
-               mfc_err_dev("[NALQ] no mfc device to run\n");
-               return -EINVAL;
-       }
-
-       for(i = 0; i < MFC_NUM_CONTEXTS; i++) {
-               if (dev->ctx[i] && dev->ctx[i]->inst_no == pOutputStr->InstanceId)
-                       return i;
-       }
-       return -1;
-}
-
-static nal_queue_in_handle* mfc_nal_q_create_in_q(struct s5p_mfc_dev *dev,
-               nal_queue_handle *nal_q_handle)
-{
-       nal_queue_in_handle *nal_q_in_handle;
-
-       mfc_debug_enter();
-
-       if (!dev) {
-               mfc_err_dev("[NALQ] no mfc device to run\n");
-               return NULL;
-       }
-
-       nal_q_in_handle = kzalloc(sizeof(*nal_q_in_handle), GFP_KERNEL);
-       if (!nal_q_in_handle) {
-               mfc_err_dev("[NALQ] Failed to get memory for nal_queue_in_handle\n");
-               return NULL;
-       }
-
-       nal_q_in_handle->nal_q_handle = nal_q_handle;
-       nal_q_in_handle->in_buf.buftype = MFCBUF_NORMAL;
-       nal_q_in_handle->in_buf.size = NAL_Q_IN_ENTRY_SIZE * (NAL_Q_IN_QUEUE_SIZE + 2);
-       if (s5p_mfc_mem_ion_alloc(dev, &nal_q_in_handle->in_buf)) {
-               mfc_err_dev("[NALQ] failed to get memory\n");
-               kfree(nal_q_in_handle);
-               return NULL;
-       }
-       nal_q_in_handle->nal_q_in_addr = (nal_in_queue *)nal_q_in_handle->in_buf.vaddr;
-
-       mfc_debug_leave();
-
-       return nal_q_in_handle;
-}
-
-static nal_queue_out_handle* mfc_nal_q_create_out_q(struct s5p_mfc_dev *dev,
-               nal_queue_handle *nal_q_handle)
-{
-       nal_queue_out_handle *nal_q_out_handle;
-
-       mfc_debug_enter();
-
-       if (!dev) {
-               mfc_err_dev("[NALQ] no mfc device to run\n");
-               return NULL;
-       }
-
-       nal_q_out_handle = kzalloc(sizeof(*nal_q_out_handle), GFP_KERNEL);
-       if (!nal_q_out_handle) {
-               mfc_err_dev("[NALQ] failed to get memory for nal_queue_out_handle\n");
-               return NULL;
-       }
-
-       nal_q_out_handle->nal_q_handle = nal_q_handle;
-       nal_q_out_handle->out_buf.buftype = MFCBUF_NORMAL;
-       nal_q_out_handle->out_buf.size = NAL_Q_OUT_ENTRY_SIZE * (NAL_Q_OUT_QUEUE_SIZE + 2);
-       if (s5p_mfc_mem_ion_alloc(dev, &nal_q_out_handle->out_buf)) {
-               mfc_err_dev("[NALQ] failed to get memory\n");
-               kfree(nal_q_out_handle);
-               return NULL;
-       }
-       nal_q_out_handle->nal_q_out_addr = (nal_out_queue *)nal_q_out_handle->out_buf.vaddr;
-
-       mfc_debug_leave();
-
-       return nal_q_out_handle;
-}
-
-static int mfc_nal_q_destroy_in_q(struct s5p_mfc_dev *dev,
-                       nal_queue_in_handle *nal_q_in_handle)
-{
-       mfc_debug_enter();
-
-       if (!nal_q_in_handle)
-               return -EINVAL;
-
-       s5p_mfc_mem_ion_free(dev, &nal_q_in_handle->in_buf);
-       if (nal_q_in_handle)
-               kfree(nal_q_in_handle);
-
-       mfc_debug_leave();
-
-       return 0;
-}
-
-static int mfc_nal_q_destroy_out_q(struct s5p_mfc_dev *dev,
-                       nal_queue_out_handle *nal_q_out_handle)
-{
-       mfc_debug_enter();
-
-       if (!nal_q_out_handle)
-               return -EINVAL;
-
-       s5p_mfc_mem_ion_free(dev, &nal_q_out_handle->out_buf);
-       if (nal_q_out_handle)
-               kfree(nal_q_out_handle);
-
-       mfc_debug_leave();
-
-       return 0;
-}
-
-/*
- * This function should be called after s5p_mfc_alloc_firmware() being called.
- */
-nal_queue_handle *s5p_mfc_nal_q_create(struct s5p_mfc_dev *dev)
-{
-       nal_queue_handle *nal_q_handle;
-
-       mfc_debug_enter();
-
-       if (!dev) {
-               mfc_err_dev("[NALQ] no mfc device to run\n");
-               return NULL;
-       }
-
-       nal_q_handle = kzalloc(sizeof(*nal_q_handle), GFP_KERNEL);
-       if (!nal_q_handle) {
-               mfc_err_dev("[NALQ] no nal_q_handle\n");
-               return NULL;
-       }
-
-       nal_q_handle->nal_q_in_handle = mfc_nal_q_create_in_q(dev, nal_q_handle);
-       if (!nal_q_handle->nal_q_in_handle) {
-               kfree(nal_q_handle);
-               mfc_err_dev("[NALQ] no nal_q_in_handle\n");
-               return NULL;
-       }
-
-       spin_lock_init(&nal_q_handle->lock);
-
-       nal_q_handle->nal_q_out_handle = mfc_nal_q_create_out_q(dev, nal_q_handle);
-       if (!nal_q_handle->nal_q_out_handle) {
-               mfc_nal_q_destroy_in_q(dev, nal_q_handle->nal_q_in_handle);
-               kfree(nal_q_handle);
-               mfc_err_dev("[NALQ] no nal_q_out_handle\n");
-               return NULL;
-       }
-
-       nal_q_handle->nal_q_state = NAL_Q_STATE_CREATED;
-       MFC_TRACE_DEV("** NAL Q state : %d\n", nal_q_handle->nal_q_state);
-       mfc_debug(2, "[NALQ] handle created, state = %d\n", nal_q_handle->nal_q_state);
-
-       mfc_debug_leave();
-
-       return nal_q_handle;
-}
-
-int s5p_mfc_nal_q_destroy(struct s5p_mfc_dev *dev, nal_queue_handle *nal_q_handle)
-{
-       int ret = 0;
-
-       mfc_debug_enter();
-
-       if (!dev) {
-               mfc_err_dev("[NALQ] no mfc device to run\n");
-               return -EINVAL;
-       }
-
-       if (!nal_q_handle) {
-               mfc_err_dev("[NALQ] there isn't nal_q_handle\n");
-               return -EINVAL;
-       }
-
-       ret = mfc_nal_q_destroy_out_q(dev, nal_q_handle->nal_q_out_handle);
-       if (ret) {
-               mfc_err_dev("[NALQ] failed nal_q_out_handle destroy\n");
-               return ret;
-       }
-
-       ret = mfc_nal_q_destroy_in_q(dev, nal_q_handle->nal_q_in_handle);
-       if (ret) {
-               mfc_err_dev("[NALQ] failed nal_q_in_handle destroy\n");
-               return ret;
-       }
-
-       kfree(nal_q_handle);
-       dev->nal_q_handle = NULL;
-
-       mfc_debug_leave();
-
-       return ret;
-}
-
-void s5p_mfc_nal_q_init(struct s5p_mfc_dev *dev, nal_queue_handle *nal_q_handle)
-{
-       mfc_debug_enter();
-
-       if (!dev) {
-               mfc_err_dev("[NALQ] no mfc device to run\n");
-               return;
-       }
-
-       if (!nal_q_handle) {
-               mfc_err_dev("[NALQ] There is no nal_q_handle\n");
-               return;
-       }
-
-       if ((nal_q_handle->nal_q_state != NAL_Q_STATE_CREATED)
-               && (nal_q_handle->nal_q_state != NAL_Q_STATE_STOPPED)) {
-               mfc_err_dev("[NALQ] State is wrong, state: %d\n", nal_q_handle->nal_q_state);
-               return;
-       }
-
-       s5p_mfc_reset_nal_queue_registers(dev);
-
-       nal_q_handle->nal_q_in_handle->in_exe_count = 0;
-       nal_q_handle->nal_q_out_handle->out_exe_count = 0;
-
-       mfc_debug(2, "[NALQ] S5P_FIMV_NAL_QUEUE_INPUT_COUNT=%d\n",
-               s5p_mfc_get_nal_q_input_count());
-       mfc_debug(2, "[NALQ] S5P_FIMV_NAL_QUEUE_OUTPUT_COUNT=%d\n",
-               s5p_mfc_get_nal_q_output_count());
-       mfc_debug(2, "[NALQ] S5P_FIMV_NAL_QUEUE_INPUT_EXE_COUNT=%d\n",
-               s5p_mfc_get_nal_q_input_exe_count());
-       mfc_debug(2, "[NALQ] S5P_FIMV_NAL_QUEUE_INFO=%d\n",
-               s5p_mfc_get_nal_q_info());
-
-       nal_q_handle->nal_q_exception = 0;
-
-       mfc_debug_leave();
-
-       return;
-}
-
-void s5p_mfc_nal_q_start(struct s5p_mfc_dev *dev, nal_queue_handle *nal_q_handle)
-{
-       dma_addr_t addr;
-
-       mfc_debug_enter();
-
-       if (!dev) {
-               mfc_err_dev("[NALQ] no mfc device to run\n");
-               return;
-       }
-
-       if (!nal_q_handle) {
-               mfc_err_dev("[NALQ] There is no nal_q_handle\n");
-               return;
-       }
-
-       if (nal_q_handle->nal_q_state != NAL_Q_STATE_CREATED) {
-               mfc_err_dev("[NALQ] State is wrong, state: %d\n", nal_q_handle->nal_q_state);
-               return;
-       }
-
-       addr = nal_q_handle->nal_q_in_handle->in_buf.daddr;
-
-       s5p_mfc_update_nal_queue_input(dev, addr, NAL_Q_IN_ENTRY_SIZE * NAL_Q_IN_QUEUE_SIZE);
-
-       mfc_debug(2, "[NALQ] S5P_FIMV_NAL_QUEUE_INPUT_ADDR=0x%x\n",
-               s5p_mfc_get_nal_q_input_addr());
-       mfc_debug(2, "[NALQ] S5P_FIMV_NAL_QUEUE_INPUT_SIZE=%d\n",
-               s5p_mfc_get_nal_q_input_size());
-
-       addr = nal_q_handle->nal_q_out_handle->out_buf.daddr;
-
-       s5p_mfc_update_nal_queue_output(dev, addr, NAL_Q_OUT_ENTRY_SIZE * NAL_Q_OUT_QUEUE_SIZE);
-
-       mfc_debug(2, "[NALQ] S5P_FIMV_NAL_QUEUE_OUTPUT_ADDR=0x%x\n",
-               s5p_mfc_get_nal_q_output_addr());
-       mfc_debug(2, "[NALQ] S5P_FIMV_NAL_QUEUE_OUTPUT_SIZE=%d\n",
-               s5p_mfc_get_nal_q_output_ize());
-
-       nal_q_handle->nal_q_state = NAL_Q_STATE_STARTED;
-       MFC_TRACE_DEV("** NAL Q state : %d\n", nal_q_handle->nal_q_state);
-       mfc_debug(2, "[NALQ] started, state = %d\n", nal_q_handle->nal_q_state);
-
-       MFC_WRITEL(MFC_TIMEOUT_VALUE, S5P_FIMV_DEC_TIMEOUT_VALUE);
-       s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_NAL_QUEUE);
-
-       mfc_debug_leave();
-
-       return;
-}
-
-void s5p_mfc_nal_q_stop(struct s5p_mfc_dev *dev, nal_queue_handle *nal_q_handle)
-{
-       mfc_debug_enter();
-
-       if (!dev) {
-               mfc_err_dev("[NALQ] no mfc device to run\n");
-               return;
-       }
-
-       if (!nal_q_handle) {
-               mfc_err_dev("[NALQ] There is no nal_q_handle\n");
-               return;
-       }
-
-       if (nal_q_handle->nal_q_state != NAL_Q_STATE_STARTED) {
-               mfc_err_dev("[NALQ] State is wrong, state: %d\n", nal_q_handle->nal_q_state);
-               return;
-       }
-
-       nal_q_handle->nal_q_state = NAL_Q_STATE_STOPPED;
-       MFC_TRACE_DEV("** NAL Q state : %d\n", nal_q_handle->nal_q_state);
-       mfc_debug(2, "[NALQ] stopped, state = %d\n", nal_q_handle->nal_q_state);
-
-       s5p_mfc_clean_dev_int_flags(dev);
-
-       s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_STOP_QUEUE);
-
-       mfc_debug_leave();
-
-       return;
-}
-
-void s5p_mfc_nal_q_stop_if_started(struct s5p_mfc_dev *dev)
-{
-       nal_queue_handle *nal_q_handle;
-
-       mfc_debug_enter();
-
-       if (!dev) {
-               mfc_err_dev("[NALQ] no mfc device to run\n");
-               return;
-       }
-
-       nal_q_handle = dev->nal_q_handle;
-       if (!nal_q_handle) {
-               mfc_err_dev("[NALQ] There is no nal_q_handle\n");
-               return;
-       }
-
-       if (nal_q_handle->nal_q_state != NAL_Q_STATE_STARTED) {
-               mfc_debug(2, "[NALQ] it is not running, state: %d\n",
-                               nal_q_handle->nal_q_state);
-               return;
-       }
-
-       s5p_mfc_nal_q_clock_on(dev, nal_q_handle);
-
-       s5p_mfc_nal_q_stop(dev, nal_q_handle);
-       mfc_info_dev("[NALQ] stop NAL QUEUE during get hwlock\n");
-       if (s5p_mfc_wait_for_done_dev(dev,
-                               S5P_FIMV_R2H_CMD_COMPLETE_QUEUE_RET)) {
-               mfc_err_dev("[NALQ] Failed to stop qeueue during get hwlock\n");
-               dev->logging_data->cause |= (1 << MFC_CAUSE_FAIL_STOP_NAL_Q_FOR_OTHER);
-               call_dop(dev, dump_and_stop_always, dev);
-       }
-
-       mfc_debug_leave();
-       return;
-}
-
-void s5p_mfc_nal_q_cleanup_queue(struct s5p_mfc_dev *dev)
-{
-       struct s5p_mfc_ctx *ctx;
-       int i;
-
-       mfc_debug_enter();
-
-       if (!dev) {
-               mfc_err_dev("[NALQ] no mfc device to run\n");
-               return;
-       }
-
-       for(i = 0; i < MFC_NUM_CONTEXTS; i++) {
-               ctx = dev->ctx[i];
-               if (ctx) {
-                       s5p_mfc_cleanup_nal_queue(ctx);
-                       if (s5p_mfc_ctx_ready(ctx)) {
-                               s5p_mfc_set_bit(ctx->num, &dev->work_bits);
-                               mfc_debug(2, "[NALQ] set work_bits after cleanup,"
-                                               " ctx: %d\n", ctx->num);
-                       }
-               }
-       }
-
-       mfc_debug_leave();
-
-       return;
-}
-
-static void mfc_nal_q_set_slice_mode(struct s5p_mfc_ctx *ctx, EncoderInputStr *pInStr)
-{
-       struct s5p_mfc_enc *enc = ctx->enc_priv;
-
-       /* multi-slice control */
-       if (enc->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES)
-               pInStr->MsliceMode = enc->slice_mode + 0x4;
-       else if (enc->slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB_ROW)
-               pInStr->MsliceMode = enc->slice_mode - 0x2;
-       else if (enc->slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_FIXED_BYTES)
-               pInStr->MsliceMode = enc->slice_mode + 0x3;
-       else
-               pInStr->MsliceMode = enc->slice_mode;
-
-       /* multi-slice MB number or bit size */
-       if ((enc->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB) ||
-                       (enc->slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB_ROW)) {
-               pInStr->MsliceSizeMb = enc->slice_size.mb;
-       } else if ((enc->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES) ||
-                       (enc->slice_mode == V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_FIXED_BYTES)){
-               pInStr->MsliceSizeBits = enc->slice_size.bits;
-       } else {
-               pInStr->MsliceSizeMb = 0;
-               pInStr->MsliceSizeBits = 0;
-       }
-}
-
-static int mfc_nal_q_run_in_buf_enc(struct s5p_mfc_ctx *ctx, EncoderInputStr *pInStr)
-{
-       struct s5p_mfc_dev *dev;
-       struct s5p_mfc_buf *src_mb, *dst_mb;
-       struct s5p_mfc_raw_info *raw = NULL;
-       dma_addr_t src_addr[3] = {0, 0, 0};
-       dma_addr_t addr_2bit[2] = {0, 0};
-       unsigned int index, i;
-
-       mfc_debug_enter();
-
-       if (!ctx) {
-               mfc_err_dev("[NALQ] no mfc context to run\n");
-               return -EINVAL;
-       }
-       dev = ctx->dev;
-       if (!dev) {
-               mfc_err_dev("[NALQ] no mfc device to run\n");
-               return -EINVAL;
-       }
-
-       pInStr->StartCode = 0xBBBBBBBB;
-       pInStr->CommandId = s5p_mfc_get_nal_q_input_count();
-       pInStr->InstanceId = ctx->inst_no;
-
-       raw = &ctx->raw_buf;
-
-       if (IS_BUFFER_BATCH_MODE(ctx)) {
-               src_mb = s5p_mfc_get_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, MFC_BUF_SET_USED);
-               if (!src_mb) {
-                       mfc_err_dev("[NALQ][BUFCON] no src buffers\n");
-                       return -EAGAIN;
-               }
-
-               /* last image in a buffer container */
-               /* move src_queue -> src_queue_nal_q */
-               if (src_mb->next_index == (src_mb->num_valid_bufs - 1)) {
-                       src_mb = s5p_mfc_get_move_buf(&ctx->buf_queue_lock,
-                                       &ctx->src_buf_nal_queue, &ctx->src_buf_queue,
-                                       MFC_BUF_SET_USED, MFC_QUEUE_ADD_BOTTOM);
-                       if (!src_mb) {
-                               mfc_err_dev("[NALQ][BUFCON] no src buffers\n");
-                               return -EAGAIN;
-                       }
-               }
-
-               index = src_mb->vb.vb2_buf.index;
-               for (i = 0; i < raw->num_planes; i++) {
-                       src_addr[i] = src_mb->addr[src_mb->next_index][i];
-                       mfc_debug(2, "[NALQ][BUFCON][BUFINFO] ctx[%d] set src index:%d, batch[%d], addr[%d]: 0x%08llx\n",
-                                       ctx->num, index, src_mb->next_index, i, src_addr[i]);
-               }
-               src_mb->next_index++;
-       } else {
-               /* move src_queue -> src_queue_nal_q */
-               src_mb = s5p_mfc_get_move_buf(&ctx->buf_queue_lock,
-                               &ctx->src_buf_nal_queue, &ctx->src_buf_queue,
-                               MFC_BUF_SET_USED, MFC_QUEUE_ADD_BOTTOM);
-               if (!src_mb) {
-                       mfc_err_dev("[NALQ] no src buffers\n");
-                       return -EAGAIN;
-               }
-
-               index = src_mb->vb.vb2_buf.index;
-               for (i = 0; i < raw->num_planes; i++) {
-                       src_addr[i] = src_mb->addr[0][i];
-                       mfc_debug(2, "[NALQ][BUFINFO] ctx[%d] set src index:%d, addr[%d]: 0x%08llx\n",
-                                       ctx->num, index, i, src_addr[i]);
-               }
-       }
-
-       for (i = 0; i < raw->num_planes; i++)
-               pInStr->FrameAddr[i] = src_addr[i];
-
-       if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M_S10B ||
-               ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV21M_S10B) {
-               addr_2bit[0] = src_addr[0] + NV12N_Y_SIZE(ctx->img_width, ctx->img_height);
-               addr_2bit[1] = src_addr[1] + NV12N_CBCR_SIZE(ctx->img_width, ctx->img_height);
-
-               for (i = 0; i < raw->num_planes; i++) {
-                       pInStr->Frame2bitAddr[i] = addr_2bit[i];
-                       mfc_debug(2, "[NALQ][BUFINFO] ctx[%d] set src 2bit addr[%d]: 0x%08llx\n",
-                                       ctx->num, index, i, addr_2bit[i]);
-               }
-       } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV16M_S10B ||
-               ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV61M_S10B) {
-               addr_2bit[0] = src_addr[0] + NV16M_Y_SIZE(ctx->img_width, ctx->img_height);
-               addr_2bit[1] = src_addr[1] + NV16M_CBCR_SIZE(ctx->img_width, ctx->img_height);
-
-               for (i = 0; i < raw->num_planes; i++) {
-                       pInStr->Frame2bitAddr[i] = addr_2bit[i];
-                       mfc_debug(2, "[NALQ][BUFINFO] ctx[%d] set src 2bit addr[%d]: 0x%08llx\n",
-                                       ctx->num, index, i, addr_2bit[i]);
-               }
-       }
-
-       /* move dst_queue -> dst_queue_nal_q */
-       dst_mb = s5p_mfc_get_move_buf(&ctx->buf_queue_lock,
-               &ctx->dst_buf_nal_queue, &ctx->dst_buf_queue, MFC_BUF_SET_USED, MFC_QUEUE_ADD_BOTTOM);
-       if (!dst_mb) {
-               mfc_err_dev("[NALQ] no dst buffers\n");
-               return -EAGAIN;
-       }
-
-       pInStr->StreamBufferAddr = dst_mb->addr[0][0];
-       pInStr->StreamBufferSize = (unsigned int)vb2_plane_size(&dst_mb->vb.vb2_buf, 0);
-       pInStr->StreamBufferSize = ALIGN(pInStr->StreamBufferSize, 512);
-
-       if (call_cop(ctx, set_buf_ctrls_val_nal_q_enc, ctx, &ctx->src_ctrls[index], pInStr) < 0)
-               mfc_err_ctx("[NALQ] failed in set_buf_ctrals_val in nal q\n");
-
-       mfc_debug(2, "[NALQ][BUFINFO] ctx[%d] set dst index: %d, addr: 0x%08llx\n",
-                       ctx->num, dst_mb->vb.vb2_buf.index, pInStr->StreamBufferAddr);
-       mfc_debug(2, "[NALQ] input queue, src_buf_queue -> src_buf_nal_queue, index:%d\n",
-                       src_mb->vb.vb2_buf.index);
-       mfc_debug(2, "[NALQ] input queue, dst_buf_queue -> dst_buf_nal_queue, index:%d\n",
-                       dst_mb->vb.vb2_buf.index);
-
-       mfc_nal_q_set_slice_mode(ctx, pInStr);
-
-       mfc_debug_leave();
-
-       return 0;
-}
-
-static int mfc_nal_q_run_in_buf_dec(struct s5p_mfc_ctx *ctx, DecoderInputStr *pInStr)
-{
-       struct s5p_mfc_dev *dev;
-       struct s5p_mfc_buf *src_mb, *dst_mb;
-       struct s5p_mfc_dec *dec;
-       struct s5p_mfc_raw_info *raw = &ctx->raw_buf;
-       dma_addr_t buf_addr;
-       unsigned int strm_size;
-       unsigned int cpb_buf_size;
-       int src_index, dst_index;
-       int i;
-
-       mfc_debug_enter();
-
-       if (!ctx) {
-               mfc_err_dev("[NALQ] no mfc context to run\n");
-               return -EINVAL;
-       }
-       dev = ctx->dev;
-       if (!dev) {
-               mfc_err_dev("[NALQ] no mfc device to run\n");
-               return -EINVAL;
-       }
-       dec = ctx->dec_priv;
-       if (!dec) {
-               mfc_err_dev("[NALQ] no mfc decoder to run\n");
-               return -EINVAL;
-       }
-
-       if (s5p_mfc_is_queue_count_same(&ctx->buf_queue_lock, &ctx->dst_buf_queue, 0) &&
-                       s5p_mfc_is_queue_count_smaller(&ctx->buf_queue_lock,
-                               &ctx->ref_buf_queue, (ctx->dpb_count + 5))) {
-               mfc_err_dev("[NALQ] no dst buffers\n");
-               return -EAGAIN;
-       }
-
-       if (s5p_mfc_is_queue_count_same(&ctx->buf_queue_lock, &ctx->src_buf_queue, 0)) {
-               mfc_err_dev("[NALQ] no src buffers\n");
-               return -EAGAIN;
-       }
-
-       pInStr->StartCode = 0xAAAAAAAA;
-       pInStr->CommandId = s5p_mfc_get_nal_q_input_count();
-       pInStr->InstanceId = ctx->inst_no;
-       pInStr->NalStartOptions = 0;
-
-       /* Try to use the non-referenced DPB on dst-queue */
-       dst_mb = s5p_mfc_search_move_dpb_nal_q(ctx, dec->dynamic_used);
-       if (!dst_mb) {
-               mfc_debug(2, "[NALQ][DPB] couldn't find dst buffers\n");
-               return -EAGAIN;
-       }
-
-       /* move src_queue -> src_queue_nal_q */
-       src_mb = s5p_mfc_get_move_buf(&ctx->buf_queue_lock,
-                       &ctx->src_buf_nal_queue, &ctx->src_buf_queue,
-                       MFC_BUF_SET_USED, MFC_QUEUE_ADD_BOTTOM);
-       if (!src_mb) {
-               mfc_err_dev("[NALQ] no src buffers\n");
-               return -EAGAIN;
-       }
-
-       /* src buffer setting */
-       src_index = src_mb->vb.vb2_buf.index;
-       buf_addr = src_mb->addr[0][0];
-       strm_size = src_mb->vb.vb2_buf.planes[0].bytesused;
-       cpb_buf_size = ALIGN(dec->src_buf_size, STREAM_BUF_ALIGN);
-
-       if (strm_size > set_strm_size_max(cpb_buf_size)) {
-               mfc_info_ctx("[NALQ] Decrease strm_size : %u -> %u, gap : %d\n",
-                               strm_size, set_strm_size_max(cpb_buf_size), STREAM_BUF_ALIGN);
-               strm_size = set_strm_size_max(cpb_buf_size);
-               src_mb->vb.vb2_buf.planes[0].bytesused = strm_size;
-       }
-
-       mfc_debug(2, "[NALQ][BUFINFO] ctx[%d] set src index: %d, addr: 0x%08llx\n",
-                       ctx->num, src_index, buf_addr);
-       mfc_debug(2, "[NALQ][STREAM] strm_size: %#lx(%d), buf_size: %u\n",
-                       strm_size, strm_size, cpb_buf_size);
-
-       if (strm_size == 0)
-               mfc_info_ctx("stream size is 0\n");
-
-       pInStr->StreamDataSize = strm_size;
-       pInStr->CpbBufferAddr = buf_addr;
-       pInStr->CpbBufferSize = cpb_buf_size;
-       pInStr->CpbBufferOffset = 0;
-
-       MFC_TRACE_CTX("Set src[%d] fd: %d, %#llx\n",
-                       src_index, src_mb->vb.vb2_buf.planes[0].m.fd, buf_addr);
-
-       /* dst buffer setting */
-       dst_index = dst_mb->vb.vb2_buf.index;
-       set_bit(dst_index, &dec->available_dpb);
-       dec->dynamic_set = 1 << dst_index;
-
-       for (i = 0; i < raw->num_planes; i++) {
-               pInStr->FrameSize[i] = raw->plane_size[i];
-               pInStr->FrameAddr[i] = dst_mb->addr[0][i];
-               if (ctx->is_10bit)
-                       pInStr->Frame2BitSize[i] = raw->plane_size_2bits[i];
-               mfc_debug(2, "[NALQ][BUFINFO][DPB] ctx[%d] set dst index: %d, addr[%d]: 0x%08llx\n",
-                               ctx->num, dst_index, i, dst_mb->addr[0][i]);
-       }
-
-       pInStr->ScratchBufAddr = ctx->codec_buf.daddr;
-       pInStr->ScratchBufSize = ctx->scratch_buf_size;
-
-       if (call_cop(ctx, set_buf_ctrls_val_nal_q_dec, ctx,
-                               &ctx->src_ctrls[src_index], pInStr) < 0)
-               mfc_err_ctx("[NALQ] failed in set_buf_ctrls_val\n");
-
-       pInStr->DynamicDpbFlagLower = dec->dynamic_set;
-
-       /* use dynamic_set value to available dpb in NAL Q */
-       // pInStr->AvailableDpbFlagLower = dec->available_dpb;
-       pInStr->AvailableDpbFlagLower = dec->dynamic_set;
-
-       MFC_TRACE_CTX("Set dst[%d] fd: %d, %#llx / avail %#lx used %#x\n",
-                       dst_index, dst_mb->vb.vb2_buf.planes[0].m.fd, dst_mb->addr[0][0],
-                       dec->available_dpb, dec->dynamic_used);
-
-       mfc_debug_leave();
-
-       return 0;
-}
-
-static void mfc_nal_q_get_enc_frame_buffer(struct s5p_mfc_ctx *ctx,
-               dma_addr_t addr[], int num_planes, EncoderOutputStr *pOutStr)
-{
-       unsigned long enc_recon_y_addr, enc_recon_c_addr;
-       int i;
-
-       for (i = 0; i < num_planes; i++)
-               addr[i] = pOutStr->EncodedFrameAddr[i];
-
-       enc_recon_y_addr = pOutStr->ReconLumaDpbAddr;
-       enc_recon_c_addr = pOutStr->ReconChromaDpbAddr;
-
-       mfc_debug(2, "[NALQ][MEMINFO] recon y: 0x%08lx c: 0x%08lx\n",
-                       enc_recon_y_addr, enc_recon_c_addr);
-}
-
-static void mfc_nal_q_handle_stream_copy_timestamp(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf *src_mb)
-{
-       struct s5p_mfc_dev *dev;
-       struct s5p_mfc_enc *enc = ctx->enc_priv;
-       struct s5p_mfc_enc_params *p = &enc->params;
-       struct s5p_mfc_buf *dst_mb;
-       u32 interval;
-       u64 start_timestamp;
-       u64 new_timestamp;
-
-       if (!ctx) {
-               mfc_err_dev("[NALQ][BUFCON][TS] no mfc context to run\n");
-               return;
-       }
-
-       dev = ctx->dev;
-       if (!dev) {
-               mfc_err_dev("[NALQ][BUFCON][TS] no device to run\n");
-               return;
-       }
-
-       start_timestamp = src_mb->vb.vb2_buf.timestamp;
-       interval = NSEC_PER_SEC / p->rc_framerate;
-       if (debug_ts == 1)
-               mfc_info_ctx("[NALQ][BUFCON][TS] %dfps, start timestamp: %lld, base interval: %d\n",
-                               p->rc_framerate, start_timestamp, interval);
-
-       new_timestamp = start_timestamp + (interval * src_mb->done_index);
-       if (debug_ts == 1)
-               mfc_info_ctx("[NALQ][BUFCON][TS] new timestamp: %lld, interval: %d\n",
-                               new_timestamp, interval * src_mb->done_index);
-
-       /* Get the destination buffer */
-       dst_mb = s5p_mfc_get_buf(&ctx->buf_queue_lock, &ctx->dst_buf_nal_queue, MFC_BUF_NO_TOUCH_USED);
-       if (dst_mb)
-               dst_mb->vb.vb2_buf.timestamp = new_timestamp;
-}
-
-static void mfc_nal_q_handle_stream_input(struct s5p_mfc_ctx *ctx, EncoderOutputStr *pOutStr)
-{
-       struct s5p_mfc_buf *src_mb, *ref_mb;
-       dma_addr_t enc_addr[3] = { 0, 0, 0 };
-       struct s5p_mfc_raw_info *raw;
-       int found_in_src_queue = 0;
-       unsigned int i;
-
-       raw = &ctx->raw_buf;
-
-       mfc_nal_q_get_enc_frame_buffer(ctx, &enc_addr[0], raw->num_planes, pOutStr);
-       if (enc_addr[0] == 0) {
-               mfc_debug(3, "[NALQ] no encoded src\n");
-               goto move_buf;
-       }
-
-       for (i = 0; i < raw->num_planes; i++)
-               mfc_debug(2, "[NALQ][BUFINFO] ctx[%d] get src addr[%d]: 0x%08llx\n",
-                               ctx->num, i, enc_addr[i]);
-
-       if (IS_BUFFER_BATCH_MODE(ctx)) {
-               src_mb = s5p_mfc_find_first_buf(&ctx->buf_queue_lock,
-                               &ctx->src_buf_queue, enc_addr[0]);
-               if (src_mb) {
-                       found_in_src_queue = 1;
-
-                       mfc_nal_q_handle_stream_copy_timestamp(ctx, src_mb);
-                       src_mb->done_index++;
-                       mfc_debug(4, "[NALQ][BUFCON] batch buf done_index: %d\n", src_mb->done_index);
-               } else {
-                       src_mb = s5p_mfc_find_first_buf(&ctx->buf_queue_lock,
-                                       &ctx->src_buf_nal_queue, enc_addr[0]);
-                       if (src_mb) {
-                               found_in_src_queue = 1;
-
-                               mfc_nal_q_handle_stream_copy_timestamp(ctx, src_mb);
-                               src_mb->done_index++;
-                               mfc_debug(4, "[NALQ][BUFCON] batch buf done_index: %d\n", src_mb->done_index);
-
-                               /* last image in a buffer container */
-                               if (src_mb->done_index == src_mb->num_valid_bufs) {
-                                       src_mb = s5p_mfc_find_del_buf(&ctx->buf_queue_lock,
-                                                       &ctx->src_buf_nal_queue, enc_addr[0]);
-                                       for (i = 0; i < raw->num_planes; i++)
-                                               s5p_mfc_bufcon_put_daddr(ctx, src_mb, i);
-                                       vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
-                               }
-                       }
-               }
-       } else {
-               src_mb = s5p_mfc_find_del_buf(&ctx->buf_queue_lock,
-                               &ctx->src_buf_nal_queue, enc_addr[0]);
-               if (src_mb) {
-                       mfc_debug(3, "[NALQ] find src buf in src_queue\n");
-                       found_in_src_queue = 1;
-                       vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
-               } else {
-                       mfc_debug(3, "[NALQ] no src buf in src_queue\n");
-                       ref_mb = s5p_mfc_find_del_buf(&ctx->buf_queue_lock,
-                                       &ctx->ref_buf_queue, enc_addr[0]);
-                       if (ref_mb) {
-                               mfc_debug(3, "[NALQ] find src buf in ref_queue\n");
-                               vb2_buffer_done(&ref_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
-                       } else {
-                               mfc_err_ctx("[NALQ] couldn't find src buffer\n");
-                       }
-               }
-       }
-
-move_buf:
-       /* move enqueued src buffer: src nal queue -> ref queue */
-       if (!found_in_src_queue) {
-               src_mb = s5p_mfc_get_move_buf_used(&ctx->buf_queue_lock,
-                               &ctx->ref_buf_queue, &ctx->src_buf_nal_queue);
-               if (!src_mb)
-                       mfc_err_dev("[NALQ] no src buffers\n");
-
-               mfc_debug(2, "[NALQ] enc src_buf_nal_queue(%d) -> ref_buf_queue(%d)\n",
-                               s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->src_buf_nal_queue),
-                               s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->ref_buf_queue));
-       }
-}
-
-static void mfc_nal_q_handle_stream_output(struct s5p_mfc_ctx *ctx, int slice_type,
-                               unsigned int strm_size, EncoderOutputStr *pOutStr)
-{
-       struct s5p_mfc_buf *dst_mb;
-       unsigned int index;
-
-       if (strm_size == 0) {
-               mfc_debug(3, "[NALQ] no encoded dst (reuse)\n");
-               dst_mb = s5p_mfc_get_move_buf(&ctx->buf_queue_lock,
-                               &ctx->dst_buf_queue, &ctx->dst_buf_nal_queue,
-                               MFC_BUF_RESET_USED, MFC_QUEUE_ADD_TOP);
-               if (!dst_mb) {
-                       mfc_err_dev("[NALQ] no dst buffers\n");
-                       return;
-               }
-
-               mfc_debug(2, "[NALQ] no output, dst_buf_nal_queue(%d) -> dst_buf_queue(%d) index:%d\n",
-                               s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->dst_buf_nal_queue),
-                               s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->dst_buf_queue),
-                               dst_mb->vb.vb2_buf.index);
-               return;
-       } else if (strm_size < 0) {
-               mfc_err_ctx("[NALQ] invalid stream size: %d\n", strm_size);
-               return;
-       }
-
-       /* at least one more dest. buffers exist always  */
-       dst_mb = s5p_mfc_get_del_buf(&ctx->buf_queue_lock, &ctx->dst_buf_nal_queue, MFC_BUF_NO_TOUCH_USED);
-       if (!dst_mb) {
-               mfc_err_dev("[NALQ] no dst buffers\n");
-               return;
-       }
-
-       mfc_debug(2, "[NALQ][BUFINFO] ctx[%d] get dst addr: 0x%08llx\n",
-                       ctx->num, dst_mb->addr[0][0]);
-
-       dst_mb->vb.flags &= ~(V4L2_BUF_FLAG_KEYFRAME |
-                               V4L2_BUF_FLAG_PFRAME |
-                               V4L2_BUF_FLAG_BFRAME);
-
-       switch (slice_type) {
-       case S5P_FIMV_E_SLICE_TYPE_I:
-               dst_mb->vb.flags |= V4L2_BUF_FLAG_KEYFRAME;
-               break;
-       case S5P_FIMV_E_SLICE_TYPE_P:
-               dst_mb->vb.flags |= V4L2_BUF_FLAG_PFRAME;
-               break;
-       case S5P_FIMV_E_SLICE_TYPE_B:
-               dst_mb->vb.flags |= V4L2_BUF_FLAG_BFRAME;
-               break;
-       default:
-               dst_mb->vb.flags |= V4L2_BUF_FLAG_KEYFRAME;
-               break;
-       }
-       mfc_debug(2, "[NALQ][STREAM] Slice type flag: %d\n", dst_mb->vb.flags);
-
-       vb2_set_plane_payload(&dst_mb->vb.vb2_buf, 0, strm_size);
-
-       index = dst_mb->vb.vb2_buf.index;
-       if (call_cop(ctx, get_buf_ctrls_val_nal_q_enc, ctx,
-                               &ctx->dst_ctrls[index], pOutStr) < 0)
-               mfc_err_ctx("[NALQ] failed in get_buf_ctrls_val in nal q\n");
-
-       vb2_buffer_done(&dst_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
-}
-
-static void mfc_nal_q_handle_stream(struct s5p_mfc_ctx *ctx, EncoderOutputStr *pOutStr)
-{
-       struct s5p_mfc_enc *enc = ctx->enc_priv;
-       int slice_type;
-       unsigned int strm_size;
-       unsigned int pic_count;
-
-       mfc_debug_enter();
-
-       slice_type = pOutStr->SliceType;
-       strm_size = pOutStr->StreamSize;
-       pic_count = pOutStr->EncCnt;
-
-       mfc_debug(2, "[NALQ][STREAM] encoded slice type: %d, size: %d, display order: %d\n",
-                       slice_type, strm_size, pic_count);
-
-       /* buffer full handling */
-       if (ctx->state == MFCINST_RUNNING_BUF_FULL)
-               ctx->state = MFCINST_RUNNING;
-
-       /* set encoded frame type */
-       enc->frame_type = slice_type;
-       ctx->sequence++;
-
-       /* handle input buffer */
-       mfc_nal_q_handle_stream_input(ctx, pOutStr);
-
-       /* handle output buffer */
-       mfc_nal_q_handle_stream_output(ctx, slice_type, strm_size, pOutStr);
-
-       mfc_debug_leave();
-
-       return;
-}
-
-static void mfc_nal_q_handle_reuse_buffer(struct s5p_mfc_ctx *ctx, DecoderOutputStr *pOutStr)
-{
-       struct s5p_mfc_dec *dec = ctx->dec_priv;
-       unsigned int prev_flag, released_flag = 0;
-       struct s5p_mfc_buf *dst_mb;
-       dma_addr_t disp_addr;
-       int i;
-
-       /* reuse not used buf: dst_buf_nal_queue -> dst_queue */
-       disp_addr = pOutStr->DisplayAddr[0];
-       if (disp_addr) {
-               mfc_debug(2, "[NALQ][DPB] decoding only but there is disp addr: 0x%llx\n", disp_addr);
-               dst_mb = s5p_mfc_get_move_buf_addr(&ctx->buf_queue_lock,
-                               &ctx->dst_buf_queue, &ctx->dst_buf_nal_queue,
-                               disp_addr);
-               if (dst_mb) {
-                       mfc_debug(2, "[NALQ][DPB] buf[%d] will reused. addr: 0x%08llx\n",
-                                       dst_mb->vb.vb2_buf.index, disp_addr);
-                       dst_mb->used = 0;
-                       clear_bit(dst_mb->vb.vb2_buf.index, &dec->available_dpb);
-               }
-       }
-
-       /* reuse not referenced buf anymore: ref_queue -> dst_queue */
-       prev_flag = dec->dynamic_used;
-       dec->dynamic_used = pOutStr->UsedDpbFlagLower;
-       released_flag = prev_flag & (~dec->dynamic_used);
-
-       if (!released_flag)
-               return;
-
-       for (i = 0; i < MFC_MAX_DPBS; i++)
-               if (released_flag & (1 << i))
-                       if (s5p_mfc_move_reuse_buffer(ctx, i))
-                               released_flag &= ~(1 << i);
-
-       /* Not reused buffer should be released when there is a display frame */
-       dec->dec_only_release_flag |= released_flag;
-       for (i = 0; i < MFC_MAX_DPBS; i++)
-               if (released_flag & (1 << i))
-                       clear_bit(i, &dec->available_dpb);
-}
-
-static void mfc_nal_q_handle_ref_frame(struct s5p_mfc_ctx *ctx, DecoderOutputStr *pOutStr)
-{
-       struct s5p_mfc_dec *dec = ctx->dec_priv;
-       struct s5p_mfc_buf *dst_mb;
-       dma_addr_t dec_addr;
-       int index = 0;
-
-       mfc_debug_enter();
-
-       dec_addr = pOutStr->DecodedAddr[0];
-
-       dst_mb = s5p_mfc_find_move_buf_used(&ctx->buf_queue_lock,
-               &ctx->ref_buf_queue, &ctx->dst_buf_nal_queue, dec_addr);
-       if (dst_mb) {
-               mfc_debug(2, "[NALQ][DPB] Found in dst queue = 0x%08llx, buf = 0x%08llx\n",
-                               dec_addr, dst_mb->addr[0][0]);
-
-               index = dst_mb->vb.vb2_buf.index;
-               if (!((1 << index) & pOutStr->UsedDpbFlagLower))
-                       dec->dynamic_used |= 1 << index;
-       } else {
-               mfc_debug(2, "[NALQ][DPB] Can't find buffer for addr: 0x%08llx\n", dec_addr);
-       }
-
-       mfc_debug_leave();
-}
-
-static void mfc_nal_q_handle_frame_copy_timestamp(struct s5p_mfc_ctx *ctx, DecoderOutputStr *pOutStr)
-{
-       struct s5p_mfc_dec *dec;
-       struct s5p_mfc_dev *dev;
-       struct s5p_mfc_buf *ref_mb, *src_mb;
-       dma_addr_t dec_y_addr;
-
-       mfc_debug_enter();
-
-       if (!ctx) {
-               mfc_err_dev("[TS] no mfc context to run\n");
-               return;
-       }
-
-       dec = ctx->dec_priv;
-       dev = ctx->dev;
-
-       dec_y_addr = pOutStr->DecodedAddr[0];
-
-       /* Get the next source buffer */
-       src_mb = s5p_mfc_get_buf(&ctx->buf_queue_lock, &ctx->src_buf_nal_queue, MFC_BUF_NO_TOUCH_USED);
-       if (!src_mb) {
-               mfc_err_dev("[NALQ] no src buffers\n");
-               return;
-       }
-
-       ref_mb = s5p_mfc_find_buf(&ctx->buf_queue_lock, &ctx->ref_buf_queue, dec_y_addr);
-       if (ref_mb)
-               ref_mb->vb.vb2_buf.timestamp = src_mb->vb.vb2_buf.timestamp;
-
-       mfc_debug_leave();
-}
-
-static void mfc_nal_q_handle_frame_output_move(struct s5p_mfc_ctx *ctx,
-                       dma_addr_t dspl_y_addr, unsigned int released_flag)
-{
-       struct s5p_mfc_dec *dec = ctx->dec_priv;
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_buf *dst_mb;
-       unsigned int index;
-
-       dst_mb = s5p_mfc_find_move_buf(&ctx->buf_queue_lock,
-                       &ctx->dst_buf_queue, &ctx->ref_buf_queue, dspl_y_addr, released_flag);
-       if (dst_mb) {
-               index = dst_mb->vb.vb2_buf.index;
-
-               /* Check if this is the buffer we're looking for */
-               mfc_debug(2, "[NALQ][DPB] Found buf[%d] 0x%08llx, looking for disp addr 0x%08llx\n",
-                               index, dst_mb->addr[0][0], dspl_y_addr);
-
-               if (released_flag & (1 << index)) {
-                       dec->available_dpb &= ~(1 << index);
-                       released_flag &= ~(1 << index);
-                       mfc_debug(2, "[NALQ][DPB] Corrupted frame(%d), it will be re-used(release)\n",
-                                       s5p_mfc_get_warn(s5p_mfc_get_int_err()));
-               } else {
-                       dec->err_reuse_flag |= 1 << index;
-                       mfc_debug(2, "[NALQ][DPB] Corrupted frame(%d), it will be re-used(not released)\n",
-                                       s5p_mfc_get_warn(s5p_mfc_get_int_err()));
-               }
-               dec->dynamic_used |= released_flag;
-       }
-}
-
-static void mfc_nal_q_handle_frame_output_del(struct s5p_mfc_ctx *ctx,
-               DecoderOutputStr *pOutStr, unsigned int err, unsigned int released_flag)
-{
-       struct s5p_mfc_dec *dec = ctx->dec_priv;
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_raw_info *raw = &ctx->raw_buf;
-       struct s5p_mfc_buf *ref_mb;
-       dma_addr_t dspl_y_addr;
-       unsigned int frame_type;
-       unsigned int dst_frame_status;
-       unsigned int is_video_signal_type = 0, is_colour_description = 0;
-       unsigned int is_content_light = 0, is_display_colour = 0;
-       unsigned int disp_err;
-       int i, index;
-
-       if (MFC_FEATURE_SUPPORT(dev, dev->pdata->color_aspect_dec)) {
-               is_video_signal_type = ((pOutStr->VideoSignalType
-                                       >> S5P_FIMV_D_VIDEO_SIGNAL_TYPE_FLAG_SHIFT)
-                                       & S5P_FIMV_D_VIDEO_SIGNAL_TYPE_FLAG_MASK);
-               is_colour_description = ((pOutStr->VideoSignalType
-                                       >> S5P_FIMV_D_COLOUR_DESCRIPTION_FLAG_SHIFT)
-                                       & S5P_FIMV_D_COLOUR_DESCRIPTION_FLAG_MASK);
-       }
-
-       if (MFC_FEATURE_SUPPORT(dev, dev->pdata->static_info_dec)) {
-               is_content_light = ((pOutStr->SeiAvail >> S5P_FIMV_D_SEI_AVAIL_CONTENT_LIGHT_SHIFT)
-                                       & S5P_FIMV_D_SEI_AVAIL_CONTENT_LIGHT_MASK);
-               is_display_colour = ((pOutStr->SeiAvail >> S5P_FIMV_D_SEI_AVAIL_MASTERING_DISPLAY_SHIFT)
-                                       & S5P_FIMV_D_SEI_AVAIL_MASTERING_DISPLAY_MASK);
-       }
-
-       if (dec->immediate_display == 1) {
-               dspl_y_addr = pOutStr->DecodedAddr[0];
-               frame_type = pOutStr->DecodedFrameType & S5P_FIMV_DECODED_FRAME_MASK;
-       } else {
-               dspl_y_addr = pOutStr->DisplayAddr[0];
-               frame_type = pOutStr->DisplayFrameType & S5P_FIMV_DISPLAY_FRAME_MASK;
-       }
-
-       ref_mb = s5p_mfc_find_del_buf(&ctx->buf_queue_lock, &ctx->ref_buf_queue, dspl_y_addr);
-       if (ref_mb) {
-               index = ref_mb->vb.vb2_buf.index;
-
-               /* Check if this is the buffer we're looking for */
-               mfc_debug(2, "[NALQ][BUFINFO][DPB] ctx[%d] get dst index: %d, addr[0]: 0x%08llx\n",
-                               ctx->num, index, ref_mb->addr[0][0]);
-
-               ref_mb->vb.sequence = ctx->sequence;
-
-               /* Set reserved2 bits in order to inform SEI information */
-               ref_mb->vb.reserved2 = 0;
-
-               if (is_content_light) {
-                       ref_mb->vb.reserved2 |= (1 << 0);
-                       mfc_debug(2, "[NALQ][HDR] content light level parsed\n");
-               }
-               if (is_display_colour) {
-                       ref_mb->vb.reserved2 |= (1 << 1);
-                       mfc_debug(2, "[NALQ][HDR] mastering display colour parsed\n");
-               }
-               if (is_video_signal_type) {
-                       ref_mb->vb.reserved2 |= (1 << 4);
-                       mfc_debug(2, "[NALQ][HDR] video signal type parsed\n");
-                       if (is_colour_description) {
-                               ref_mb->vb.reserved2 |= (1 << 2);
-                               mfc_debug(2, "[NALQ][HDR] matrix coefficients parsed\n");
-                               ref_mb->vb.reserved2 |= (1 << 3);
-                               mfc_debug(2, "[NALQ][HDR] colour description parsed\n");
-                       }
-               }
-
-               if (IS_VP9_DEC(ctx) && MFC_FEATURE_SUPPORT(dev, dev->pdata->color_aspect_dec)) {
-                       if (dec->color_space != S5P_FIMV_D_COLOR_UNKNOWN) {
-                               ref_mb->vb.reserved2 |= (1 << 3);
-                               mfc_debug(2, "[NALQ][HDR] color space parsed\n");
-                       }
-                       ref_mb->vb.reserved2 |= (1 << 4);
-                       mfc_debug(2, "[NALQ][HDR] color range parsed\n");
-               }
-
-               for (i = 0; i < raw->num_planes; i++)
-                       vb2_set_plane_payload(&ref_mb->vb.vb2_buf, i,
-                                       raw->plane_size[i]);
-
-               clear_bit(index, &dec->available_dpb);
-
-               ref_mb->vb.flags &= ~(V4L2_BUF_FLAG_KEYFRAME |
-                                       V4L2_BUF_FLAG_PFRAME |
-                                       V4L2_BUF_FLAG_BFRAME |
-                                       V4L2_BUF_FLAG_ERROR);
-
-               switch (frame_type) {
-                       case S5P_FIMV_DISPLAY_FRAME_I:
-                               ref_mb->vb.flags |= V4L2_BUF_FLAG_KEYFRAME;
-                               break;
-                       case S5P_FIMV_DISPLAY_FRAME_P:
-                               ref_mb->vb.flags |= V4L2_BUF_FLAG_PFRAME;
-                               break;
-                       case S5P_FIMV_DISPLAY_FRAME_B:
-                               ref_mb->vb.flags |= V4L2_BUF_FLAG_BFRAME;
-                               break;
-                       default:
-                               break;
-               }
-
-               disp_err = s5p_mfc_get_warn(pOutStr->ErrorCode);
-               if (disp_err) {
-                       mfc_err_ctx("[NALQ] Warning for displayed frame: %d\n",
-                                       disp_err);
-                       ref_mb->vb.flags |= V4L2_BUF_FLAG_ERROR;
-               }
-
-               if (call_cop(ctx, get_buf_ctrls_val_nal_q_dec, ctx,
-                                       &ctx->dst_ctrls[index], pOutStr) < 0)
-                       mfc_err_ctx("[NALQ] failed in get_buf_ctrls_val\n");
-
-               s5p_mfc_handle_released_info(ctx, released_flag, index);
-
-               if (dec->immediate_display == 1) {
-                       dst_frame_status = pOutStr->DecodedStatus
-                               & S5P_FIMV_DEC_STATUS_DECODED_STATUS_MASK;
-
-                       call_cop(ctx, get_buf_update_val, ctx,
-                                       &ctx->dst_ctrls[index],
-                                       V4L2_CID_MPEG_MFC51_VIDEO_DISPLAY_STATUS,
-                                       dst_frame_status);
-
-                       call_cop(ctx, get_buf_update_val, ctx,
-                                       &ctx->dst_ctrls[index],
-                                       V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG,
-                                       dec->stored_tag);
-
-                       dec->immediate_display = 0;
-               }
-
-               s5p_mfc_qos_update_last_framerate(ctx, ref_mb->vb.vb2_buf.timestamp);
-               vb2_buffer_done(&ref_mb->vb.vb2_buf, disp_err ?
-                               VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
-       }
-}
-
-static void mfc_nal_q_handle_frame_new(struct s5p_mfc_ctx *ctx, unsigned int err,
-                                       DecoderOutputStr *pOutStr)
-{
-       struct s5p_mfc_dec *dec = ctx->dec_priv;
-       dma_addr_t dspl_y_addr;
-       unsigned int frame_type;
-       unsigned int prev_flag, released_flag = 0;
-       unsigned int disp_err;
-
-       mfc_debug_enter();
-
-       frame_type = pOutStr->DisplayFrameType & S5P_FIMV_DISPLAY_FRAME_MASK;
-       disp_err = s5p_mfc_get_warn(pOutStr->ErrorCode);
-
-       ctx->sequence++;
-
-       dspl_y_addr = pOutStr->DisplayAddr[0];
-
-       if (dec->immediate_display == 1) {
-               dspl_y_addr = pOutStr->DecodedAddr[0];
-               frame_type = pOutStr->DecodedFrameType & S5P_FIMV_DECODED_FRAME_MASK;
-       }
-
-       mfc_debug(2, "[NALQ][FRAME] frame type: %d\n", frame_type);
-
-       /* If frame is same as previous then skip and do not dequeue */
-       if (frame_type == S5P_FIMV_DISPLAY_FRAME_NOT_CODED) {
-               if (!CODEC_NOT_CODED(ctx))
-                       return;
-       }
-
-       prev_flag = dec->dynamic_used;
-       dec->dynamic_used = pOutStr->UsedDpbFlagLower;
-       released_flag = prev_flag & (~dec->dynamic_used);
-
-       mfc_debug(2, "[NALQ][DPB] Used flag: old = %08x, new = %08x, Released buffer = %08x\n",
-                       prev_flag, dec->dynamic_used, released_flag);
-
-       if ((IS_VC1_RCV_DEC(ctx) &&
-                       (disp_err == S5P_FIMV_ERR_SYNC_POINT_NOT_RECEIVED)) ||
-                       (disp_err == S5P_FIMV_ERR_BROKEN_LINK))
-               mfc_nal_q_handle_frame_output_move(ctx, dspl_y_addr, released_flag);
-       else
-               mfc_nal_q_handle_frame_output_del(ctx, pOutStr, err, released_flag);
-
-       mfc_debug_leave();
-}
-
-static void mfc_nal_q_handle_frame_input(struct s5p_mfc_ctx *ctx, unsigned int err,
-                                       DecoderOutputStr *pOutStr)
-{
-       struct s5p_mfc_dec *dec = ctx->dec_priv;
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_buf *src_mb;
-       unsigned int index;
-       int deleted = 0;
-       unsigned long consumed;
-
-       /* If there is consumed byte, it is abnormal status,
-        * We have to return remained stream buffer
-        */
-       if (dec->consumed) {
-               mfc_err_dev("[NALQ] previous buffer was not fully consumed\n");
-               src_mb = s5p_mfc_get_del_buf(&ctx->buf_queue_lock, &ctx->src_buf_nal_queue,
-                               MFC_BUF_NO_TOUCH_USED);
-               if (src_mb)
-                       vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
-       }
-
-       /* Check multi-frame */
-       consumed = pOutStr->DecodedNalSize;
-       src_mb = s5p_mfc_get_del_if_consumed(ctx, &ctx->src_buf_nal_queue,
-                       consumed, STUFF_BYTE, err, &deleted);
-       if (!src_mb) {
-               mfc_err_dev("[NALQ] no src buffers\n");
-               return;
-       }
-
-       index = src_mb->vb.vb2_buf.index;
-       mfc_debug(2, "[NALQ][BUFINFO] ctx[%d] get src index: %d, addr: 0x%08llx\n",
-                       ctx->num, index, src_mb->addr[0][0]);
-
-       if (!deleted) {
-               /* Run MFC again on the same buffer */
-               mfc_debug(2, "[NALQ][MULTIFRAME] Running again the same buffer\n");
-
-               if (CODEC_MULTIFRAME(ctx))
-                       dec->y_addr_for_pb = (dma_addr_t)pOutStr->DecodedAddr[0];
-
-               dec->consumed = consumed;
-               dec->remained_size = src_mb->vb.vb2_buf.planes[0].bytesused
-                       - dec->consumed;
-               dec->has_multiframe = 1;
-               dev->nal_q_handle->nal_q_exception = 1;
-
-               MFC_TRACE_CTX("** consumed:%ld, remained:%ld, addr:0x%08llx\n",
-                       dec->consumed, dec->remained_size, dec->y_addr_for_pb);
-               /* Do not move src buffer to done_list */
-               return;
-       }
-
-       if (call_cop(ctx, get_buf_ctrls_val_nal_q_dec, ctx,
-                               &ctx->src_ctrls[index], pOutStr) < 0)
-               mfc_err_ctx("[NALQ] failed in get_buf_ctrls_val\n");
-
-       dec->consumed = 0;
-       dec->remained_size = 0;
-
-       vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
-}
-
-void mfc_nal_q_handle_frame(struct s5p_mfc_ctx *ctx, DecoderOutputStr *pOutStr)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_dec *dec = ctx->dec_priv;
-       unsigned int dst_frame_status, sei_avail_status, need_empty_dpb;
-       unsigned int res_change, need_dpb_change, need_scratch_change;
-       unsigned int is_interlaced, err;
-
-       mfc_debug_enter();
-
-       dst_frame_status = pOutStr->DisplayStatus
-                               & S5P_FIMV_DISP_STATUS_DISPLAY_STATUS_MASK;
-       need_empty_dpb = (pOutStr->DisplayStatus
-                               >> S5P_FIMV_DISP_STATUS_NEED_EMPTY_DPB_SHIFT)
-                               & S5P_FIMV_DISP_STATUS_NEED_EMPTY_DPB_MASK;
-       res_change = (pOutStr->DisplayStatus
-                               >> S5P_FIMV_DISP_STATUS_RES_CHANGE_SHIFT)
-                               & S5P_FIMV_DISP_STATUS_RES_CHANGE_MASK;
-       need_dpb_change = (pOutStr->DisplayStatus
-                               >> S5P_FIMV_DISP_STATUS_NEED_DPB_CHANGE_SHIFT)
-                               & S5P_FIMV_DISP_STATUS_NEED_DPB_CHANGE_MASK;
-       need_scratch_change = (pOutStr->DisplayStatus
-                                >> S5P_FIMV_DISP_STATUS_NEED_SCRATCH_CHANGE_SHIFT)
-                               & S5P_FIMV_DISP_STATUS_NEED_SCRATCH_CHANGE_MASK;
-       is_interlaced = (pOutStr->DisplayStatus
-                               >> S5P_FIMV_DISP_STATUS_INTERLACE_SHIFT)
-                               & S5P_FIMV_DISP_STATUS_INTERLACE_MASK;
-       sei_avail_status = pOutStr->SeiAvail;
-       err = pOutStr->ErrorCode;
-
-       if (dec->immediate_display == 1)
-               dst_frame_status = pOutStr->DecodedStatus
-                               & S5P_FIMV_DEC_STATUS_DECODED_STATUS_MASK;
-
-       mfc_debug(2, "[NALQ][FRAME] frame status: %d\n", dst_frame_status);
-       mfc_debug(2, "[NALQ][FRAME] display status: %d, type: %d, yaddr: %#x\n",
-                       pOutStr->DisplayStatus & S5P_FIMV_DISP_STATUS_DISPLAY_STATUS_MASK,
-                       pOutStr->DisplayFrameType & S5P_FIMV_DISPLAY_FRAME_MASK,
-                       pOutStr->DisplayAddr[0]);
-       mfc_debug(2, "[NALQ][FRAME] decoded status: %d, type: %d, yaddr: %#x\n",
-                       pOutStr->DecodedStatus & S5P_FIMV_DEC_STATUS_DECODED_STATUS_MASK,
-                       pOutStr->DecodedFrameType & S5P_FIMV_DECODED_FRAME_MASK,
-                       pOutStr->DecodedAddr[0]);
-       mfc_debug(4, "[NALQ][HDR] SEI available status: %x\n", sei_avail_status);
-       mfc_debug(2, "[NALQ][DPB] Used flag: old = %08x, new = %08x\n",
-                       dec->dynamic_used, pOutStr->UsedDpbFlagLower);
-
-       if (ctx->state == MFCINST_RES_CHANGE_INIT) {
-               mfc_debug(2, "[NALQ][DRC] return until NAL-Q stopped in try_run\n");
-               goto leave_handle_frame;
-       }
-       if (res_change) {
-               mfc_debug(2, "[NALQ][DRC] Resolution change set to %d\n", res_change);
-               s5p_mfc_change_state(ctx, MFCINST_RES_CHANGE_INIT);
-               ctx->wait_state = WAIT_DECODING;
-               dev->nal_q_handle->nal_q_exception = 1;
-               mfc_info_ctx("[NALQ][DRC] nal_q_exception is set (res change)\n");
-               goto leave_handle_frame;
-       }
-       if (need_empty_dpb) {
-               mfc_debug(2, "[NALQ][MULTIFRAME] There is multi-frame. consumed:%ld\n", dec->consumed);
-               dec->has_multiframe = 1;
-               dev->nal_q_handle->nal_q_exception = 1;
-               mfc_info_ctx("[NALQ][MULTIFRAME] nal_q_exception is set\n");
-               goto leave_handle_frame;
-       }
-       if (need_dpb_change || need_scratch_change) {
-               mfc_debug(2, "[NALQ][DRC] Interframe resolution change is not supported\n");
-               dev->nal_q_handle->nal_q_exception = 1;
-               mfc_info_ctx("[NALQ][DRC] nal_q_exception is set (interframe res change)\n");
-               goto leave_handle_frame;
-       }
-       if (is_interlaced) {
-               mfc_debug(2, "[NALQ][INTERLACE] Progressive -> Interlaced\n");
-               dec->is_interlaced = is_interlaced;
-               dev->nal_q_handle->nal_q_exception = 1;
-               mfc_info_ctx("[NALQ][INTERLACE] nal_q_exception is set\n");
-               goto leave_handle_frame;
-       }
-
-       if (s5p_mfc_is_queue_count_same(&ctx->buf_queue_lock, &ctx->src_buf_nal_queue, 0) &&
-               s5p_mfc_is_queue_count_same(&ctx->buf_queue_lock, &ctx->dst_buf_nal_queue, 0)) {
-               mfc_err_dev("[NALQ] Queue count is zero for src/dst\n");
-               goto leave_handle_frame;
-       }
-
-       switch (dst_frame_status) {
-       case S5P_FIMV_DEC_STATUS_DECODING_DISPLAY:
-               mfc_nal_q_handle_ref_frame(ctx, pOutStr);
-               mfc_nal_q_handle_frame_copy_timestamp(ctx, pOutStr);
-               break;
-       case S5P_FIMV_DEC_STATUS_DECODING_ONLY:
-               mfc_nal_q_handle_ref_frame(ctx, pOutStr);
-               mfc_nal_q_handle_reuse_buffer(ctx, pOutStr);
-               break;
-       default:
-               break;
-       }
-
-       /* A frame has been decoded and is in the buffer  */
-       if (s5p_mfc_dec_status_display(dst_frame_status))
-               mfc_nal_q_handle_frame_new(ctx, err, pOutStr);
-       else
-               mfc_debug(2, "[NALQ] No display frame\n");
-
-       /* Mark source buffer as complete */
-       if (dst_frame_status != S5P_FIMV_DEC_STATUS_DISPLAY_ONLY)
-               mfc_nal_q_handle_frame_input(ctx, err, pOutStr);
-       else
-               mfc_debug(2, "[NALQ][DPB] can't support display only in NAL-Q, is_dpb_full: %d\n",
-                               dec->is_dpb_full);
-
-leave_handle_frame:
-       mfc_debug_leave();
-}
-
-int mfc_nal_q_handle_error(struct s5p_mfc_ctx *ctx, EncoderOutputStr *pOutStr, int err)
-{
-       struct s5p_mfc_dev *dev;
-       struct s5p_mfc_dec *dec;
-       struct s5p_mfc_enc *enc;
-       struct s5p_mfc_buf *src_mb;
-       int stop_nal_q = 1;
-
-       mfc_debug_enter();
-
-       if (!ctx) {
-               mfc_err_dev("[NALQ] no mfc context to run\n");
-               goto end;
-       }
-
-       dev = ctx->dev;
-       if (!dev) {
-               mfc_err_dev("[NALQ] no mfc device to run\n");
-               goto end;
-       }
-
-       mfc_err_ctx("[NALQ] Interrupt Error: %d\n", pOutStr->ErrorCode);
-
-       dev->nal_q_handle->nal_q_exception = 1;
-       mfc_info_ctx("[NALQ] nal_q_exception is set (error)\n");
-
-       if (ctx->type == MFCINST_DECODER) {
-               dec = ctx->dec_priv;
-               if (!dec) {
-                       mfc_err_dev("[NALQ] no mfc decoder to run\n");
-                       goto end;
-               }
-               src_mb = s5p_mfc_get_del_buf(&ctx->buf_queue_lock,
-                               &ctx->src_buf_nal_queue, MFC_BUF_NO_TOUCH_USED);
-
-               if (!src_mb) {
-                       mfc_err_dev("[NALQ] no src buffers\n");
-               } else {
-                       dec->consumed = 0;
-                       vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_ERROR);
-               }
-       } else if (ctx->type == MFCINST_ENCODER) {
-               enc = ctx->enc_priv;
-               if (!enc) {
-                       mfc_err_dev("[NALQ] no mfc encoder to run\n");
-                       goto end;
-               }
-
-               /*
-                * If the buffer full error occurs in NAL-Q mode,
-                * one input buffer is returned and the NAL-Q mode continues.
-                */
-               if (err == S5P_FIMV_ERR_BUFFER_FULL) {
-                       src_mb = s5p_mfc_get_del_buf(&ctx->buf_queue_lock,
-                                       &ctx->src_buf_nal_queue, MFC_BUF_NO_TOUCH_USED);
-
-                       if (!src_mb)
-                               mfc_err_dev("[NALQ] no src buffers\n");
-                       else
-                               vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_ERROR);
-
-                       dev->nal_q_handle->nal_q_exception = 0;
-                       stop_nal_q = 0;
-               }
-       }
-
-end:
-       mfc_debug_leave();
-
-       return stop_nal_q;
-}
-
-int s5p_mfc_nal_q_handle_out_buf(struct s5p_mfc_dev *dev, EncoderOutputStr *pOutStr)
-{
-       struct s5p_mfc_ctx *ctx;
-       struct s5p_mfc_enc *enc;
-       struct s5p_mfc_dec *dec;
-       int ctx_num;
-
-       mfc_debug_enter();
-
-       if (!dev) {
-               mfc_err_dev("[NALQ] no mfc device to run\n");
-               return -EINVAL;
-       }
-
-       ctx_num = dev->nal_q_handle->nal_q_out_handle->nal_q_ctx;
-       if (ctx_num < 0) {
-               mfc_err_dev("[NALQ] Can't find ctx in nal q\n");
-               return -EINVAL;
-       }
-
-       ctx = dev->ctx[ctx_num];
-       if (!ctx) {
-               mfc_err_dev("[NALQ] no mfc context to run\n");
-               return -EINVAL;
-       }
-
-       mfc_debug(2, "[NALQ] Int ctx is %d(%s)\n", ctx_num,
-                        ctx->type == MFCINST_ENCODER ? "enc" : "dec");
-
-       if (s5p_mfc_get_err(pOutStr->ErrorCode) &&
-                       (s5p_mfc_get_err(pOutStr->ErrorCode) < S5P_FIMV_ERR_FRAME_CONCEAL)) {
-               if (mfc_nal_q_handle_error(ctx, pOutStr, s5p_mfc_get_err(pOutStr->ErrorCode)))
-                       return 0;
-       }
-
-       if (ctx->type == MFCINST_ENCODER) {
-               enc = ctx->enc_priv;
-               if (!enc) {
-                       mfc_err_dev("[NALQ] no mfc encoder to run\n");
-                       return -EINVAL;
-               }
-               mfc_nal_q_handle_stream(ctx, pOutStr);
-       } else if (ctx->type == MFCINST_DECODER) {
-               dec = ctx->dec_priv;
-               if (!dec) {
-                       mfc_err_dev("[NALQ] no mfc decoder to run\n");
-                       return -EINVAL;
-               }
-               mfc_nal_q_handle_frame(ctx, (DecoderOutputStr *)pOutStr);
-       }
-
-       mfc_debug_leave();
-
-       return 0;
-}
-
-/*
- * This function should be called in NAL_Q_STATE_STARTED state.
- */
-int s5p_mfc_nal_q_enqueue_in_buf(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx,
-       nal_queue_in_handle *nal_q_in_handle)
-{
-       unsigned long flags;
-       unsigned int input_count = 0;
-       unsigned int input_exe_count = 0;
-       int input_diff = 0;
-       unsigned int index = 0;
-       EncoderInputStr *pStr = NULL;
-       int ret = 0;
-
-       mfc_debug_enter();
-
-       if (!nal_q_in_handle) {
-               mfc_err_dev("[NALQ] There is no nal_q_handle\n");
-               return -EINVAL;
-       }
-
-       if (nal_q_in_handle->nal_q_handle->nal_q_state != NAL_Q_STATE_STARTED) {
-               mfc_err_dev("[NALQ] State is wrong, state: %d\n",
-                               nal_q_in_handle->nal_q_handle->nal_q_state);
-               return -EINVAL;
-       }
-
-       spin_lock_irqsave(&nal_q_in_handle->nal_q_handle->lock, flags);
-
-       input_count = s5p_mfc_get_nal_q_input_count();
-       input_exe_count = s5p_mfc_get_nal_q_input_exe_count();
-       input_diff = input_count - input_exe_count;
-
-       /*
-        * meaning of the variable input_diff
-        * 0:                           number of available slots = NAL_Q_IN_QUEUE_SIZE
-        * 1:                           number of available slots = NAL_Q_IN_QUEUE_SIZE - 1
-        * ...
-        * NAL_Q_IN_QUEUE_SIZE-1:       number of available slots = 1
-        * NAL_Q_IN_QUEUE_SIZE:         number of available slots = 0
-        */
-
-       mfc_debug(2, "[NALQ] input_diff = %d(in: %d, exe: %d)\n",
-                       input_diff, input_count, input_exe_count);
-
-       if ((input_diff < 0) || (input_diff >= NAL_Q_IN_QUEUE_SIZE)) {
-               mfc_err_dev("[NALQ] No available input slot(%d)\n", input_diff);
-               spin_unlock_irqrestore(&nal_q_in_handle->nal_q_handle->lock, flags);
-               return -EINVAL;
-       }
-
-       index = input_count % NAL_Q_IN_QUEUE_SIZE;
-       pStr = &(nal_q_in_handle->nal_q_in_addr->entry[index].enc);
-
-       memset(pStr, 0, NAL_Q_IN_ENTRY_SIZE);
-
-       if (ctx->type == MFCINST_ENCODER)
-               ret = mfc_nal_q_run_in_buf_enc(ctx, pStr);
-       else if (ctx->type == MFCINST_DECODER)
-               ret = mfc_nal_q_run_in_buf_dec(ctx, (DecoderInputStr *)pStr);
-
-       if (ret != 0) {
-               mfc_debug(2, "[NALQ] Failed to set input queue\n");
-               spin_unlock_irqrestore(&nal_q_in_handle->nal_q_handle->lock, flags);
-               return ret;
-       }
-
-       if (nal_q_dump == 1) {
-               mfc_err_dev("[NAL-Q][DUMP][%s INPUT][c: %d] diff: %d, count: %d, exe: %d\n",
-                               ctx->type == MFCINST_ENCODER ? "ENC" : "DEC", dev->curr_ctx,
-                               input_diff, input_count, input_exe_count);
-               print_hex_dump(KERN_ERR, "", DUMP_PREFIX_ADDRESS, 32, 4, (int *)pStr, 256, false);
-               printk("...\n");
-       }
-       input_count++;
-
-       s5p_mfc_update_nal_queue_input_count(dev, input_count);
-
-       if (input_diff == 0)
-               s5p_mfc_watchdog_start_tick(dev);
-
-       spin_unlock_irqrestore(&nal_q_in_handle->nal_q_handle->lock, flags);
-
-       MFC_TRACE_CTX("NAL %s in: diff %d count %d exe %d\n",
-                       ctx->type == MFCINST_ENCODER ? "ENC" : "DEC",
-                       input_diff, input_count, input_exe_count);
-
-       mfc_debug_leave();
-
-       return ret;
-}
-
-/*
- * This function should be called in NAL_Q_STATE_STARTED state.
- */
-EncoderOutputStr *s5p_mfc_nal_q_dequeue_out_buf(struct s5p_mfc_dev *dev,
-       nal_queue_out_handle *nal_q_out_handle, unsigned int *reason)
-{
-       struct s5p_mfc_ctx *ctx;
-       unsigned long flags;
-       unsigned int output_count = 0;
-       unsigned int output_exe_count = 0;
-       int output_diff = 0;
-       unsigned int index = 0;
-       EncoderOutputStr *pStr = NULL;
-
-       int input_diff = 0;
-
-       mfc_debug_enter();
-
-       if (!nal_q_out_handle || !nal_q_out_handle->nal_q_out_addr) {
-               mfc_err_dev("[NALQ] There is no handle\n");
-               return pStr;
-       }
-
-       spin_lock_irqsave(&nal_q_out_handle->nal_q_handle->lock, flags);
-
-       output_count = s5p_mfc_get_nal_q_output_count();
-       output_exe_count = nal_q_out_handle->out_exe_count;
-       output_diff = output_count - output_exe_count;
-
-       /*
-        * meaning of the variable output_diff
-        * 0:                           number of output slots = 0
-        * 1:                           number of output slots = 1
-        * ...
-        * NAL_Q_OUT_QUEUE_SIZE-1:      number of output slots = NAL_Q_OUT_QUEUE_SIZE - 1
-        * NAL_Q_OUT_QUEUE_SIZE:        number of output slots = NAL_Q_OUT_QUEUE_SIZE
-        */
-
-       mfc_debug(2, "[NALQ] output_diff = %d(out: %d, exe: %d)\n",
-                       output_diff, output_count, output_exe_count);
-       if ((output_diff <= 0) || (output_diff > NAL_Q_OUT_QUEUE_SIZE)) {
-               spin_unlock_irqrestore(&nal_q_out_handle->nal_q_handle->lock, flags);
-               mfc_debug(2, "[NALQ] No available output slot(%d)\n", output_diff);
-               return pStr;
-       }
-
-       index = output_exe_count % NAL_Q_OUT_QUEUE_SIZE;
-       pStr = &(nal_q_out_handle->nal_q_out_addr->entry[index].enc);
-
-       nal_q_out_handle->nal_q_ctx = mfc_nal_q_find_ctx(dev, pStr);
-       if (nal_q_out_handle->nal_q_ctx < 0) {
-               mfc_err_dev("[NALQ] Can't find ctx in nal q\n");
-               pStr = NULL;
-               return pStr;
-       }
-
-       ctx = dev->ctx[nal_q_out_handle->nal_q_ctx];
-       if (nal_q_dump == 1) {
-               mfc_err_dev("[NALQ][DUMP][%s OUTPUT][c: %d] diff: %d, count: %d, exe: %d\n",
-                               ctx->type == MFCINST_ENCODER ? "ENC" : "DEC",
-                               nal_q_out_handle->nal_q_ctx,
-                               output_diff, output_count, output_exe_count);
-               print_hex_dump(KERN_ERR, "", DUMP_PREFIX_ADDRESS, 32, 4, (int *)pStr, 256, false);
-               printk("...\n");
-       }
-       nal_q_out_handle->out_exe_count++;
-
-       if (pStr->ErrorCode) {
-               *reason = S5P_FIMV_R2H_CMD_ERR_RET;
-               mfc_err_dev("[NALQ] Error : %d\n", pStr->ErrorCode);
-       }
-
-       input_diff = s5p_mfc_get_nal_q_input_count() - s5p_mfc_get_nal_q_input_exe_count();
-       if (input_diff == 0) {
-               s5p_mfc_watchdog_stop_tick(dev);
-       } else if (input_diff > 0) {
-               s5p_mfc_watchdog_reset_tick(dev);
-       }
-
-       spin_unlock_irqrestore(&nal_q_out_handle->nal_q_handle->lock, flags);
-
-       MFC_TRACE_CTX("NAL %s out: diff %d count %d exe %d\n",
-                       ctx->type == MFCINST_ENCODER ? "ENC" : "DEC",
-                       output_diff, output_count, output_exe_count);
-
-       mfc_debug_leave();
-
-       return pStr;
-}
-
-#if 0
-/* not used function - only for reference sfr <-> structure */
-void s5p_mfc_nal_q_fill_DecoderInputStr(struct s5p_mfc_dev *dev, DecoderInputStr *pStr)
-{
-       pStr->StartCode                 = 0xAAAAAAAA; // Decoder input start
-//     pStr->CommandId                 = MFC_READL(S5P_FIMV_HOST2RISC_CMD);            // 0x1100
-       pStr->InstanceId                = MFC_READL(S5P_FIMV_INSTANCE_ID);              // 0xF008
-       pStr->PictureTag                = MFC_READL(S5P_FIMV_D_PICTURE_TAG);            // 0xF5C8
-       pStr->CpbBufferAddr             = MFC_READL(S5P_FIMV_D_CPB_BUFFER_ADDR);        // 0xF5B0
-       pStr->CpbBufferSize             = MFC_READL(S5P_FIMV_D_CPB_BUFFER_SIZE);        // 0xF5B4
-       pStr->CpbBufferOffset           = MFC_READL(S5P_FIMV_D_CPB_BUFFER_OFFSET);      // 0xF5C0
-       pStr->StreamDataSize            = MFC_READL(S5P_FIMV_D_STREAM_DATA_SIZE);       // 0xF5D0
-       pStr->AvailableDpbFlagUpper     = MFC_READL(S5P_FIMV_D_AVAILABLE_DPB_FLAG_UPPER);// 0xF5B8
-       pStr->AvailableDpbFlagLower     = MFC_READL(S5P_FIMV_D_AVAILABLE_DPB_FLAG_LOWER);// 0xF5BC
-       pStr->DynamicDpbFlagUpper       = MFC_READL(S5P_FIMV_D_DYNAMIC_DPB_FLAG_UPPER); // 0xF5D4
-       pStr->DynamicDpbFlagLower       = MFC_READL(S5P_FIMV_D_DYNAMIC_DPB_FLAG_LOWER); // 0xF5D8
-       pStr->FirstPlaneDpb             = MFC_READL(S5P_FIMV_D_FIRST_PLANE_DPB0);       // 0xF160+(index*4)
-       pStr->SecondPlaneDpb            = MFC_READL(S5P_FIMV_D_SECOND_PLANE_DPB0);      // 0xF260+(index*4)
-       pStr->ThirdPlaneDpb             = MFC_READL(S5P_FIMV_D_THIRD_PLANE_DPB0);       // 0xF360+(index*4)
-       pStr->FirstPlaneDpbSize         = MFC_READL(S5P_FIMV_D_FIRST_PLANE_DPB_SIZE);   // 0xF144
-       pStr->SecondPlaneDpbSize        = MFC_READL(S5P_FIMV_D_SECOND_PLANE_DPB_SIZE);  // 0xF148
-       pStr->ThirdPlaneDpbSize         = MFC_READL(S5P_FIMV_D_THIRD_PLANE_DPB_SIZE);   // 0xF14C
-       pStr->NalStartOptions           = MFC_READL(0xF5AC);// S5P_FIMV_D_NAL_START_OPTIONS 0xF5AC
-       pStr->FirstPlaneStrideSize      = MFC_READL(S5P_FIMV_D_FIRST_PLANE_DPB_STRIDE_SIZE);// 0xF138
-       pStr->SecondPlaneStrideSize     = MFC_READL(S5P_FIMV_D_SECOND_PLANE_DPB_STRIDE_SIZE);// 0xF13C
-       pStr->ThirdPlaneStrideSize      = MFC_READL(S5P_FIMV_D_THIRD_PLANE_DPB_STRIDE_SIZE);// 0xF140
-       pStr->FirstPlane2BitDpbSize     = MFC_READL(S5P_FIMV_D_FIRST_PLANE_2BIT_DPB_SIZE);// 0xF578
-       pStr->SecondPlane2BitDpbSize    = MFC_READL(S5P_FIMV_D_SECOND_PLANE_2BIT_DPB_SIZE);// 0xF57C
-       pStr->FirstPlane2BitStrideSize  = MFC_READL(S5P_FIMV_D_FIRST_PLANE_2BIT_DPB_STRIDE_SIZE);// 0xF580
-       pStr->SecondPlane2BitStrideSize = MFC_READL(S5P_FIMV_D_SECOND_PLANE_2BIT_DPB_STRIDE_SIZE);// 0xF584
-       pStr->ScratchBufAddr            = MFC_READL(S5P_FIMV_D_SCRATCH_BUFFER_ADDR);    // 0xF560
-       pStr->ScratchBufSize            = MFC_READL(S5P_FIMV_D_SCRATCH_BUFFER_SIZE);    // 0xF564
-}
-
-void s5p_mfc_nal_q_flush_DecoderOutputStr(struct s5p_mfc_dev *dev, DecoderOutputStr *pStr)
-{
-       //pStr->StartCode; // 0xAAAAAAAA; // Decoder output start
-//     MFC_WRITEL(pStr->CommandId, S5P_FIMV_RISC2HOST_CMD);                            // 0x1104
-       MFC_WRITEL(pStr->InstanceId, S5P_FIMV_RET_INSTANCE_ID);                         // 0xF070
-       MFC_WRITEL(pStr->ErrorCode, S5P_FIMV_ERROR_CODE);                               // 0xF074
-       MFC_WRITEL(pStr->PictureTagTop, S5P_FIMV_D_RET_PICTURE_TAG_TOP);                // 0xF674
-       MFC_WRITEL(pStr->PictureTimeTop, S5P_FIMV_D_RET_PICTURE_TIME_TOP);              // 0xF67C
-       MFC_WRITEL(pStr->DisplayFrameWidth, S5P_FIMV_D_DISPLAY_FRAME_WIDTH);            // 0xF600
-       MFC_WRITEL(pStr->DisplayFrameHeight, S5P_FIMV_D_DISPLAY_FRAME_HEIGHT);          // 0xF604
-       MFC_WRITEL(pStr->DisplayStatus, S5P_FIMV_D_DISPLAY_STATUS);                     // 0xF608
-       MFC_WRITEL(pStr->DisplayFirstPlaneAddr, S5P_FIMV_D_DISPLAY_FIRST_PLANE_ADDR);   // 0xF60C
-       MFC_WRITEL(pStr->DisplaySecondPlaneAddr, S5P_FIMV_D_DISPLAY_SECOND_PLANE_ADDR); // 0xF610
-       MFC_WRITEL(pStr->DisplayThirdPlaneAddr,S5P_FIMV_D_DISPLAY_THIRD_PLANE_ADDR);    // 0xF614
-       MFC_WRITEL(pStr->DisplayFrameType, S5P_FIMV_D_DISPLAY_FRAME_TYPE);              // 0xF618
-       MFC_WRITEL(pStr->DisplayCropInfo1, S5P_FIMV_D_DISPLAY_CROP_INFO1);              // 0xF61C
-       MFC_WRITEL(pStr->DisplayCropInfo2, S5P_FIMV_D_DISPLAY_CROP_INFO2);              // 0xF620
-       MFC_WRITEL(pStr->DisplayPictureProfile, S5P_FIMV_D_DISPLAY_PICTURE_PROFILE);    // 0xF624
-       MFC_WRITEL(pStr->DisplayAspectRatio, S5P_FIMV_D_DISPLAY_ASPECT_RATIO);          // 0xF634
-       MFC_WRITEL(pStr->DisplayExtendedAr, S5P_FIMV_D_DISPLAY_EXTENDED_AR);            // 0xF638
-       MFC_WRITEL(pStr->DecodedNalSize, S5P_FIMV_D_DECODED_NAL_SIZE);                  // 0xF664
-       MFC_WRITEL(pStr->UsedDpbFlagUpper, S5P_FIMV_D_USED_DPB_FLAG_UPPER);             // 0xF720
-       MFC_WRITEL(pStr->UsedDpbFlagLower, S5P_FIMV_D_USED_DPB_FLAG_LOWER);             // 0xF724
-       MFC_WRITEL(pStr->SeiAvail, S5P_FIMV_D_SEI_AVAIL);                               // 0xF6DC
-       MFC_WRITEL(pStr->FramePackArrgmentId, S5P_FIMV_D_FRAME_PACK_ARRGMENT_ID);       // 0xF6E0
-       MFC_WRITEL(pStr->FramePackSeiInfo, S5P_FIMV_D_FRAME_PACK_SEI_INFO);             // 0xF6E4
-       MFC_WRITEL(pStr->FramePackGridPos, S5P_FIMV_D_FRAME_PACK_GRID_POS);             // 0xF6E8
-       MFC_WRITEL(pStr->DisplayRecoverySeiInfo, S5P_FIMV_D_DISPLAY_RECOVERY_SEI_INFO); // 0xF6EC
-       MFC_WRITEL(pStr->H264Info, S5P_FIMV_D_H264_INFO);                               // 0xF690
-       MFC_WRITEL(pStr->DisplayFirstCrc, S5P_FIMV_D_DISPLAY_FIRST_PLANE_CRC);          // 0xF628
-       MFC_WRITEL(pStr->DisplaySecondCrc, S5P_FIMV_D_DISPLAY_SECOND_PLANE_CRC);        // 0xF62C
-       MFC_WRITEL(pStr->DisplayThirdCrc, S5P_FIMV_D_DISPLAY_THIRD_PLANE_CRC);          // 0xF630
-       MFC_WRITEL(pStr->DisplayFirst2BitCrc, S5P_FIMV_D_DISPLAY_FIRST_PLANE_2BIT_CRC); // 0xF6FC
-       MFC_WRITEL(pStr->DisplaySecond2BitCrc, S5P_FIMV_D_DISPLAY_SECOND_PLANE_2BIT_CRC);// 0xF700
-       MFC_WRITEL(pStr->DecodedFrameWidth, S5P_FIMV_D_DECODED_FRAME_WIDTH);            // 0xF63C
-       MFC_WRITEL(pStr->DecodedFrameHeight, S5P_FIMV_D_DECODED_FRAME_HEIGHT);          // 0xF640
-       MFC_WRITEL(pStr->DecodedStatus, S5P_FIMV_D_DECODED_STATUS);                     // 0xF644
-       MFC_WRITEL(pStr->DecodedFirstPlaneAddr, S5P_FIMV_D_DECODED_FIRST_PLANE_ADDR);   // 0xF648
-       MFC_WRITEL(pStr->DecodedSecondPlaneAddr, S5P_FIMV_D_DECODED_SECOND_PLANE_ADDR); // 0xF64C
-       MFC_WRITEL(pStr->DecodedThirdPlaneAddr, S5P_FIMV_D_DECODED_THIRD_PLANE_ADDR);   // 0xF650
-       MFC_WRITEL(pStr->DecodedFrameType, S5P_FIMV_D_DECODED_FRAME_TYPE);              // 0xF654
-       MFC_WRITEL(pStr->DecodedCropInfo1, S5P_FIMV_D_DECODED_CROP_INFO1);              // 0xF658
-       MFC_WRITEL(pStr->DecodedCropInfo2, S5P_FIMV_D_DECODED_CROP_INFO2);              // 0xF65C
-       MFC_WRITEL(pStr->DecodedPictureProfile, S5P_FIMV_D_DECODED_PICTURE_PROFILE);    // 0xF660
-       MFC_WRITEL(pStr->DecodedRecoverySeiInfo, S5P_FIMV_D_DECODED_RECOVERY_SEI_INFO); // 0xF6F0
-       MFC_WRITEL(pStr->DecodedFirstCrc, S5P_FIMV_D_DECODED_FIRST_PLANE_CRC);          // 0xF668
-       MFC_WRITEL(pStr->DecodedSecondCrc, S5P_FIMV_D_DECODED_SECOND_PLANE_CRC);        // 0xF66C
-       MFC_WRITEL(pStr->DecodedThirdCrc, S5P_FIMV_D_DECODED_THIRD_PLANE_CRC);          // 0xF670
-       MFC_WRITEL(pStr->DecodedFirst2BitCrc, S5P_FIMV_D_DECODED_FIRST_PLANE_2BIT_CRC); // 0xF704
-       MFC_WRITEL(pStr->DecodedSecond2BitCrc, S5P_FIMV_D_DECODED_SECOND_PLANE_2BIT_CRC);// 0xF708
-       MFC_WRITEL(pStr->PictureTagBot, S5P_FIMV_D_RET_PICTURE_TAG_BOT);                // 0xF678
-       MFC_WRITEL(pStr->PictureTimeBot, S5P_FIMV_D_RET_PICTURE_TIME_BOT);              // 0xF680
-}
-#endif
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_nal_q.h b/drivers/media/platform/exynos/mfc/s5p_mfc_nal_q.h
deleted file mode 100644 (file)
index f9b14a8..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_nal_q.h
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __S5P_MFC_NAL_Q_H
-#define __S5P_MFC_NAL_Q_H __FILE__
-
-#include "s5p_mfc_common.h"
-
-int s5p_mfc_nal_q_check_enable(struct s5p_mfc_dev *dev);
-
-void s5p_mfc_nal_q_clock_on(struct s5p_mfc_dev *dev, nal_queue_handle *nal_q_handle);
-void s5p_mfc_nal_q_clock_off(struct s5p_mfc_dev *dev, nal_queue_handle *nal_q_handle);
-void s5p_mfc_nal_q_cleanup_clock(struct s5p_mfc_dev *dev);
-
-nal_queue_handle *s5p_mfc_nal_q_create(struct s5p_mfc_dev *dev);
-int s5p_mfc_nal_q_destroy(struct s5p_mfc_dev *dev, nal_queue_handle *nal_q_handle);
-
-void s5p_mfc_nal_q_init(struct s5p_mfc_dev *dev, nal_queue_handle *nal_q_handle);
-void s5p_mfc_nal_q_start(struct s5p_mfc_dev *dev, nal_queue_handle *nal_q_handle);
-void s5p_mfc_nal_q_stop(struct s5p_mfc_dev *dev, nal_queue_handle *nal_q_handle);
-void s5p_mfc_nal_q_stop_if_started(struct s5p_mfc_dev *dev);
-void s5p_mfc_nal_q_cleanup_queue(struct s5p_mfc_dev *dev);
-
-int s5p_mfc_nal_q_handle_out_buf(struct s5p_mfc_dev *dev, EncoderOutputStr *pOutStr);
-int s5p_mfc_nal_q_enqueue_in_buf(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx,
-                       nal_queue_in_handle *nal_q_in_handle);
-EncoderOutputStr *s5p_mfc_nal_q_dequeue_out_buf(struct s5p_mfc_dev *dev,
-                       nal_queue_out_handle *nal_q_out_handle, unsigned int *reason);
-
-#endif /* __S5P_MFC_NAL_Q_H  */
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_opr.c b/drivers/media/platform/exynos/mfc/s5p_mfc_opr.c
deleted file mode 100644 (file)
index 2268854..0000000
+++ /dev/null
@@ -1,336 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_opr.c
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include "s5p_mfc_opr.h"
-
-#include "s5p_mfc_inst.h"
-#include "s5p_mfc_reg.h"
-
-#include "s5p_mfc_queue.h"
-#include "s5p_mfc_utils.h"
-#include "s5p_mfc_mem.h"
-
-int s5p_mfc_run_dec_init(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev;
-       struct s5p_mfc_buf *src_mb;
-       struct s5p_mfc_dec *dec = NULL;
-
-       if (!ctx) {
-               mfc_err_dev("no mfc context to run\n");
-               return -EINVAL;
-       }
-       dev = ctx->dev;
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return -EINVAL;
-       }
-       dec = ctx->dec_priv;
-       /* Initializing decoding - parsing header */
-
-       /* Get the next source buffer */
-       src_mb = s5p_mfc_get_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, MFC_BUF_NO_TOUCH_USED);
-       if (!src_mb) {
-               mfc_err_dev("no src buffers\n");
-               return -EAGAIN;
-       }
-
-       mfc_debug(2, "Preparing to init decoding\n");
-       mfc_debug(2, "Header size: %d, (offset: %lu)\n",
-               src_mb->vb.vb2_buf.planes[0].bytesused, dec->consumed);
-
-       if (dec->consumed) {
-               s5p_mfc_set_dec_stream_buffer(ctx, src_mb, dec->consumed, dec->remained_size);
-       } else {
-               /* decoder src buffer CFW PROT */
-               if (ctx->is_drm) {
-                       int index = src_mb->vb.vb2_buf.index;
-
-                       s5p_mfc_stream_protect(ctx, src_mb, index);
-               }
-
-               s5p_mfc_set_dec_stream_buffer(ctx, src_mb,
-                       0, src_mb->vb.vb2_buf.planes[0].bytesused);
-       }
-
-       mfc_debug(2, "Header addr: 0x%08llx\n", src_mb->addr[0][0]);
-       s5p_mfc_clean_ctx_int_flags(ctx);
-       s5p_mfc_init_decode(ctx);
-
-       return 0;
-}
-
-static int mfc_check_last_frame(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf *mfc_buf)
-{
-       if (mfc_buf->vb.reserved2 & FLAG_LAST_FRAME) {
-               mfc_debug(2, "Setting ctx->state to FINISHING\n");
-               s5p_mfc_change_state(ctx, MFCINST_FINISHING);
-               return 1;
-       }
-
-       return 0;
-}
-
-int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev;
-       struct s5p_mfc_buf *src_mb, *dst_mb;
-       struct s5p_mfc_dec *dec;
-       int last_frame = 0;
-       unsigned int index;
-
-       if (!ctx) {
-               mfc_err_dev("no mfc context to run\n");
-               return -EINVAL;
-       }
-       dec = ctx->dec_priv;
-       dev = ctx->dev;
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return -EINVAL;
-       }
-
-       if (s5p_mfc_is_queue_count_same(&ctx->buf_queue_lock, &ctx->dst_buf_queue, 0) &&
-                       s5p_mfc_is_queue_count_smaller(&ctx->buf_queue_lock,
-                               &ctx->ref_buf_queue, (ctx->dpb_count + 5))) {
-               return -EAGAIN;
-       }
-
-       /* Get the next source buffer */
-       src_mb = s5p_mfc_get_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, MFC_BUF_SET_USED);
-       if (!src_mb) {
-               mfc_debug(2, "no src buffers\n");
-               return -EAGAIN;
-       }
-
-       /* decoder src buffer CFW PROT */
-       if (ctx->is_drm) {
-               if (!dec->consumed) {
-                       index = src_mb->vb.vb2_buf.index;
-                       s5p_mfc_stream_protect(ctx, src_mb, index);
-               }
-       }
-
-       if (src_mb->vb.reserved2 & FLAG_EMPTY_DATA)
-               src_mb->vb.vb2_buf.planes[0].bytesused = 0;
-
-       if (dec->consumed)
-               s5p_mfc_set_dec_stream_buffer(ctx, src_mb, dec->consumed, dec->remained_size);
-       else
-               s5p_mfc_set_dec_stream_buffer(ctx, src_mb, 0, src_mb->vb.vb2_buf.planes[0].bytesused);
-
-       /* Try to use the non-referenced DPB on dst-queue */
-       dst_mb = s5p_mfc_search_for_dpb(ctx, dec->dynamic_used);
-       if (!dst_mb) {
-               mfc_debug(2, "[DPB] couldn't find dst buffers\n");
-               return -EAGAIN;
-       }
-
-       index = src_mb->vb.vb2_buf.index;
-       if (call_cop(ctx, set_buf_ctrls_val, ctx, &ctx->src_ctrls[index]) < 0)
-               mfc_err_ctx("failed in set_buf_ctrls_val\n");
-
-       s5p_mfc_set_dynamic_dpb(ctx, dst_mb);
-
-       s5p_mfc_clean_ctx_int_flags(ctx);
-
-       last_frame = mfc_check_last_frame(ctx, src_mb);
-       s5p_mfc_decode_one_frame(ctx, last_frame);
-
-       return 0;
-}
-
-int s5p_mfc_run_dec_last_frames(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev;
-       struct s5p_mfc_buf *src_mb, *dst_mb;
-       struct s5p_mfc_dec *dec;
-
-       if (!ctx) {
-               mfc_err_dev("no mfc context to run\n");
-               return -EINVAL;
-       }
-
-       dec = ctx->dec_priv;
-       if (!dec) {
-               mfc_err_dev("no decoder context to run\n");
-               return -EINVAL;
-       }
-
-       dev = ctx->dev;
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return -EINVAL;
-       }
-
-       if (s5p_mfc_is_queue_count_same(&ctx->buf_queue_lock, &ctx->dst_buf_queue, 0)) {
-               mfc_debug(2, "no dst buffer\n");
-               return -EAGAIN;
-       }
-
-       /* Get the next source buffer */
-       src_mb = s5p_mfc_get_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, MFC_BUF_SET_USED);
-
-       /* Frames are being decoded */
-       if (!src_mb) {
-               mfc_debug(2, "no src buffers\n");
-               s5p_mfc_set_dec_stream_buffer(ctx, 0, 0, 0);
-       } else {
-               if (dec->consumed) {
-                       s5p_mfc_set_dec_stream_buffer(ctx, src_mb, dec->consumed, dec->remained_size);
-               } else {
-                       /* decoder src buffer CFW PROT */
-                       if (ctx->is_drm) {
-                               int index = src_mb->vb.vb2_buf.index;
-
-                               s5p_mfc_stream_protect(ctx, src_mb, index);
-                       }
-
-                       s5p_mfc_set_dec_stream_buffer(ctx, src_mb, 0, 0);
-               }
-       }
-
-       /* Try to use the non-referenced DPB on dst-queue */
-       dst_mb = s5p_mfc_search_for_dpb(ctx, dec->dynamic_used);
-       if (!dst_mb) {
-               mfc_debug(2, "[DPB] couldn't find dst buffers\n");
-               return -EAGAIN;
-       }
-
-       s5p_mfc_set_dynamic_dpb(ctx, dst_mb);
-
-       s5p_mfc_clean_ctx_int_flags(ctx);
-       s5p_mfc_decode_one_frame(ctx, 1);
-
-       return 0;
-}
-
-int s5p_mfc_run_enc_init(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_buf *dst_mb;
-       int ret;
-
-       dst_mb = s5p_mfc_get_buf(&ctx->buf_queue_lock, &ctx->dst_buf_queue, MFC_BUF_NO_TOUCH_USED);
-       if (!dst_mb) {
-               mfc_debug(2, "no dst buffers\n");
-               return -EAGAIN;
-       }
-
-       /* encoder dst buffer CFW PROT */
-       if (ctx->is_drm) {
-               int index = dst_mb->vb.vb2_buf.index;
-
-               s5p_mfc_stream_protect(ctx, dst_mb, index);
-       }
-       s5p_mfc_set_enc_stream_buffer(ctx, dst_mb);
-
-       s5p_mfc_set_enc_stride(ctx);
-
-       mfc_debug(2, "Header addr: 0x%08llx\n", dst_mb->addr[0][0]);
-       s5p_mfc_clean_ctx_int_flags(ctx);
-
-       ret = s5p_mfc_init_encode(ctx);
-       return ret;
-}
-
-int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_buf *dst_mb;
-       struct s5p_mfc_buf *src_mb;
-       struct s5p_mfc_raw_info *raw;
-       unsigned int index, i;
-       int last_frame = 0;
-
-       raw = &ctx->raw_buf;
-
-       /* Get the next source buffer */
-       src_mb = s5p_mfc_get_buf(&ctx->buf_queue_lock, &ctx->src_buf_queue, MFC_BUF_SET_USED);
-       if (!src_mb) {
-               mfc_debug(2, "no src buffers\n");
-               return -EAGAIN;
-       }
-
-       if (src_mb->num_valid_bufs > 0) {
-               /* last image in a buffer container */
-               if (src_mb->next_index == (src_mb->num_valid_bufs - 1)) {
-                       mfc_debug(4, "[BUFCON] last image in a container\n");
-                       last_frame = mfc_check_last_frame(ctx, src_mb);
-               }
-       } else {
-               last_frame = mfc_check_last_frame(ctx, src_mb);
-       }
-
-       index = src_mb->vb.vb2_buf.index;
-
-       /* encoder src buffer CFW PROT */
-       if (ctx->is_drm)
-               s5p_mfc_raw_protect(ctx, src_mb, index);
-
-       s5p_mfc_set_enc_frame_buffer(ctx, src_mb, raw->num_planes);
-
-       dst_mb = s5p_mfc_get_buf(&ctx->buf_queue_lock, &ctx->dst_buf_queue, MFC_BUF_SET_USED);
-       if (!dst_mb) {
-               mfc_debug(2, "no dst buffers\n");
-               return -EAGAIN;
-       }
-
-       /* encoder dst buffer CFW PROT */
-       if (ctx->is_drm) {
-               i = dst_mb->vb.vb2_buf.index;
-               s5p_mfc_stream_protect(ctx, dst_mb, i);
-       }
-       mfc_debug(2, "nal start : src index from src_buf_queue:%d\n",
-               src_mb->vb.vb2_buf.index);
-       mfc_debug(2, "nal start : dst index from dst_buf_queue:%d\n",
-               dst_mb->vb.vb2_buf.index);
-
-       s5p_mfc_set_enc_stream_buffer(ctx, dst_mb);
-
-       if (call_cop(ctx, set_buf_ctrls_val, ctx, &ctx->src_ctrls[index]) < 0)
-               mfc_err_ctx("failed in set_buf_ctrls_val\n");
-
-       s5p_mfc_clean_ctx_int_flags(ctx);
-       s5p_mfc_encode_one_frame(ctx, last_frame);
-
-       return 0;
-}
-
-int s5p_mfc_run_enc_last_frames(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_buf *dst_mb;
-       struct s5p_mfc_raw_info *raw;
-
-       raw = &ctx->raw_buf;
-
-       dst_mb = s5p_mfc_get_buf(&ctx->buf_queue_lock, &ctx->dst_buf_queue, MFC_BUF_SET_USED);
-       if (!dst_mb) {
-               mfc_debug(2, "no dst buffers\n");
-               return -EAGAIN;
-       }
-
-       mfc_debug(2, "Set address zero for all planes\n");
-       s5p_mfc_set_enc_frame_buffer(ctx, 0, raw->num_planes);
-
-       /* encoder dst buffer CFW PROT */
-       if (ctx->is_drm) {
-               int index = dst_mb->vb.vb2_buf.index;
-
-               s5p_mfc_stream_protect(ctx, dst_mb, index);
-       }
-
-       s5p_mfc_set_enc_stream_buffer(ctx, dst_mb);
-
-       s5p_mfc_clean_ctx_int_flags(ctx);
-       s5p_mfc_encode_one_frame(ctx, 1);
-
-       return 0;
-}
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_opr.h b/drivers/media/platform/exynos/mfc/s5p_mfc_opr.h
deleted file mode 100644 (file)
index 76c6e35..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_opr.h
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __S5P_MFC_OPR_H
-#define __S5P_MFC_OPR_H __FILE__
-
-#include "s5p_mfc_common.h"
-
-int s5p_mfc_run_dec_init(struct s5p_mfc_ctx *ctx);
-int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx);
-int s5p_mfc_run_dec_last_frames(struct s5p_mfc_ctx *ctx);
-int s5p_mfc_run_enc_init(struct s5p_mfc_ctx *ctx);
-int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx);
-int s5p_mfc_run_enc_last_frames(struct s5p_mfc_ctx *ctx);
-
-#endif /* __S5P_MFC_OPR_H */
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_otf.c b/drivers/media/platform/exynos/mfc/s5p_mfc_otf.c
deleted file mode 100644 (file)
index 62ba98a..0000000
+++ /dev/null
@@ -1,721 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_otf.c
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifdef CONFIG_VIDEO_EXYNOS_REPEATER
-#include <media/exynos_repeater.h>
-#endif
-#ifdef CONFIG_VIDEO_EXYNOS_TSMUX
-#include <media/exynos_tsmux.h>
-#endif
-#include <media/s5p_mfc_hwfc.h>
-
-#include "s5p_mfc_otf.h"
-#include "s5p_mfc_hwfc_internal.h"
-
-#include "s5p_mfc_sync.h"
-
-#include "s5p_mfc_inst.h"
-#include "s5p_mfc_pm.h"
-#include "s5p_mfc_cmd.h"
-#include "s5p_mfc_reg.h"
-
-#include "s5p_mfc_qos.h"
-#include "s5p_mfc_queue.h"
-#include "s5p_mfc_utils.h"
-#include "s5p_mfc_buf.h"
-#include "s5p_mfc_mem.h"
-
-static struct s5p_mfc_fmt *mfc_enc_hwfc_find_format(unsigned int pixelformat)
-{
-       unsigned long i;
-
-       mfc_debug_enter();
-
-       for (i = 0; i < NUM_FORMATS; i++) {
-               if (enc_hwfc_formats[i].fourcc == pixelformat)
-                       return (struct s5p_mfc_fmt *)&enc_hwfc_formats[i];
-       }
-
-       mfc_debug_leave();
-
-       return NULL;
-}
-
-static int mfc_otf_set_buf_info(struct s5p_mfc_ctx *ctx)
-{
-       struct _otf_handle *handle = ctx->otf_handle;
-       struct _otf_buf_info *buf_info = &handle->otf_buf_info;
-
-       mfc_debug_enter();
-
-       ctx->src_fmt = mfc_enc_hwfc_find_format(buf_info->pixel_format);
-       if (!ctx->src_fmt) {
-               mfc_err_ctx("[OTF] failed to set source format\n");
-               return -EINVAL;
-       }
-
-       mfc_debug(2, "[OTF][FRAME] resolution w: %d, h: %d, format: %s, bufcnt: %d\n",
-                       buf_info->width, buf_info->height,
-                       ctx->src_fmt->name, buf_info->buffer_count);
-
-       /* set source information */
-       ctx->raw_buf.num_planes = ctx->src_fmt->num_planes;
-       ctx->img_width = buf_info->width;
-       ctx->img_height = buf_info->height;
-       ctx->crop_width = buf_info->width;
-       ctx->crop_height = buf_info->height;
-       ctx->buf_stride = ALIGN(ctx->img_width, 16);
-
-       /* calculate source size */
-       s5p_mfc_enc_calc_src_size(ctx);
-
-       mfc_debug_leave();
-
-       return 0;
-}
-
-static int mfc_otf_map_buf(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct _otf_handle *handle = ctx->otf_handle;
-       struct _otf_buf_addr *buf_addr = &handle->otf_buf_addr;
-       struct _otf_buf_info *buf_info = &handle->otf_buf_info;
-       struct s5p_mfc_raw_info *raw = &ctx->raw_buf;
-       int i;
-
-       mfc_debug_enter();
-
-       mfc_debug(2, "[OTF] buffer count: %d\n", buf_info->buffer_count);
-       /* map buffers */
-       for (i = 0; i < buf_info->buffer_count; i++) {
-               mfc_debug(2, "[OTF] dma_buf: 0x%p\n", buf_info->bufs[i]);
-               buf_addr->otf_buf_attach[i] = dma_buf_attach(buf_info->bufs[i], dev->device);
-               if (IS_ERR(buf_addr->otf_buf_attach[i])) {
-                       mfc_err_ctx("[OTF] Failed to get attachment (err %ld)",
-                               PTR_ERR(buf_addr->otf_buf_attach[i]));
-                       buf_addr->otf_buf_attach[i] = 0;
-                       return -EINVAL;
-               }
-               buf_addr->otf_daddr[i][0] = ion_iovmm_map(buf_addr->otf_buf_attach[i], 0,
-                               raw->total_plane_size, DMA_BIDIRECTIONAL, 0);
-               if (IS_ERR_VALUE(buf_addr->otf_daddr[i][0])) {
-                       mfc_err_ctx("[OTF] Failed to get daddr (0x%08llx)",
-                                       buf_addr->otf_daddr[i][0]);
-                       buf_addr->otf_daddr[i][0] = 0;
-                       return -EINVAL;
-               }
-               if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12N) {
-                       buf_addr->otf_daddr[i][1] = NV12N_CBCR_BASE(buf_addr->otf_daddr[i][0],
-                                       ctx->img_width, ctx->img_height);
-               } else {
-                       mfc_err_ctx("[OTF] not supported format(0x%x)\n", ctx->src_fmt->fourcc);
-                       return -EINVAL;
-               }
-               mfc_debug(2, "[OTF] index: %d, addr[0]: 0x%08llx, addr[1]: 0x%08llx\n",
-                               i, buf_addr->otf_daddr[i][0], buf_addr->otf_daddr[i][1]);
-       }
-
-       mfc_debug_leave();
-
-       return 0;
-}
-
-static void mfc_otf_unmap_buf(struct s5p_mfc_ctx *ctx)
-{
-       struct _otf_handle *handle = ctx->otf_handle;
-       struct _otf_buf_addr *buf_addr = &handle->otf_buf_addr;
-       struct _otf_buf_info *buf_info = &handle->otf_buf_info;
-       int i;
-
-       mfc_debug_enter();
-
-       for (i = 0; i < buf_info->buffer_count; i++) {
-               if (buf_addr->otf_daddr[i][0]) {
-                       ion_iovmm_unmap(buf_addr->otf_buf_attach[i], buf_addr->otf_daddr[i][0]);
-                       buf_addr->otf_daddr[i][0] = 0;
-               }
-               if (buf_addr->otf_buf_attach[i]) {
-                       dma_buf_detach(buf_info->bufs[i], buf_addr->otf_buf_attach[i]);
-                       buf_addr->otf_buf_attach[i] = 0;
-               }
-       }
-
-       mfc_debug_leave();
-}
-
-static void mfc_otf_put_buf(struct s5p_mfc_ctx *ctx)
-{
-       struct _otf_handle *handle = ctx->otf_handle;
-       struct _otf_buf_info *buf_info = &handle->otf_buf_info;
-       int i;
-
-       mfc_debug_enter();
-
-       for (i = 0; i < buf_info->buffer_count; i++) {
-               if (buf_info->bufs[i]) {
-                       dma_buf_put(buf_info->bufs[i]);
-                       buf_info->bufs[i] = NULL;
-               }
-       }
-
-       mfc_debug_leave();
-
-}
-
-static int mfc_otf_init_hwfc_buf(struct s5p_mfc_ctx *ctx)
-{
-#ifdef CONFIG_VIDEO_EXYNOS_REPEATER
-       struct shared_buffer_info *shared_buf_info;
-#endif
-       struct _otf_handle *handle = ctx->otf_handle;
-       struct _otf_buf_info *buf_info = &handle->otf_buf_info;
-
-       mfc_debug_enter();
-
-#ifdef CONFIG_VIDEO_EXYNOS_REPEATER
-       shared_buf_info = (struct shared_buffer_info *)buf_info;
-       /* request buffers */
-       if (hwfc_request_buffer(shared_buf_info, 1)) {
-               mfc_err_dev("[OTF] request_buffer failed\n");
-               return -EINVAL;
-       }
-#endif
-       mfc_debug(2, "[OTF] recieved buffer information\n");
-
-       /* set buffer information to ctx, and calculate buffer size */
-       if (mfc_otf_set_buf_info(ctx)) {
-               mfc_err_ctx("[OTF] failed to set buffer information\n");
-               mfc_otf_put_buf(ctx);
-               return -EINVAL;
-       }
-
-       if (mfc_otf_map_buf(ctx)) {
-               mfc_err_ctx("[OTF] failed to map buffers\n");
-               mfc_otf_unmap_buf(ctx);
-               mfc_otf_put_buf(ctx);
-               return -EINVAL;
-       }
-       mfc_debug(2, "[OTF] HWFC buffer initialized\n");
-
-       mfc_debug_leave();
-
-       return 0;
-}
-
-static void mfc_otf_deinit_hwfc_buf(struct s5p_mfc_ctx *ctx)
-{
-       mfc_debug_enter();
-
-       mfc_otf_unmap_buf(ctx);
-       mfc_otf_put_buf(ctx);
-       mfc_debug(2, "[OTF] HWFC buffer de-initialized\n");
-
-       mfc_debug_leave();
-}
-
-static int mfc_otf_create_handle(struct s5p_mfc_ctx *ctx)
-{
-       struct _otf_handle *otf_handle;
-
-       mfc_debug_enter();
-
-       if (!ctx) {
-               mfc_err_dev("[OTF] no mfc context to run\n");
-               return -EINVAL;
-       }
-
-       ctx->otf_handle = kzalloc(sizeof(*otf_handle), GFP_KERNEL);
-       if (!ctx->otf_handle) {
-               mfc_err_dev("[OTF] no otf_handle\n");
-               return -EINVAL;
-       }
-       mfc_debug(2, "[OTF] otf_handle created\n");
-
-       mfc_debug_leave();
-
-       return 0;
-}
-
-static void mfc_otf_destroy_handle(struct s5p_mfc_ctx *ctx)
-{
-       mfc_debug_enter();
-
-       if (!ctx) {
-               mfc_err_dev("[OTF] no mfc context to run\n");
-               return;
-       }
-
-       kfree(ctx->otf_handle);
-       ctx->otf_handle = NULL;
-       mfc_debug(2, "[OTF] otf_handle destroyed\n");
-
-       mfc_debug_leave();
-}
-
-int s5p_mfc_otf_create(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev;
-       int i;
-
-       mfc_debug_enter();
-
-       if (!ctx) {
-               mfc_err_dev("[OTF] no mfc context to run\n");
-               return -EINVAL;
-       }
-
-       dev = ctx->dev;
-       if (!dev) {
-               mfc_err_dev("[OTF] no mfc device to run\n");
-               return -EINVAL;
-       }
-
-       for (i = 0; i < MFC_NUM_CONTEXTS; i++) {
-               if (dev->ctx[i] && dev->ctx[i]->otf_handle) {
-                       mfc_err_dev("[OTF] otf_handle is already created, ctx: %d\n", i);
-                       return -EINVAL;
-               }
-       }
-
-       if (mfc_otf_create_handle(ctx)) {
-               mfc_err_dev("[OTF] otf_handle is not created\n");
-               return -EINVAL;
-       }
-
-       if (otf_dump) {
-               /* It is for debugging. Do not return error */
-               if (s5p_mfc_otf_alloc_stream_buf(ctx)) {
-                       mfc_err_dev("[OTF] stream buffer allocation failed\n");
-                       s5p_mfc_otf_release_stream_buf(ctx);
-               }
-       }
-
-       mfc_debug(2, "[OTF] otf_create is completed\n");
-
-       mfc_debug_leave();
-
-       return 0;
-}
-
-void s5p_mfc_otf_destroy(struct s5p_mfc_ctx *ctx)
-{
-       mfc_debug_enter();
-
-       if (!ctx) {
-               mfc_err_dev("[OTF] no mfc context to run\n");
-               return;
-       }
-
-       s5p_mfc_otf_release_stream_buf(ctx);
-       mfc_otf_destroy_handle(ctx);
-       mfc_debug(2, "[OTF] otf_destroy is completed\n");
-
-       mfc_debug_leave();
-}
-
-int s5p_mfc_otf_init(struct s5p_mfc_ctx *ctx)
-{
-       mfc_debug_enter();
-
-       if (!ctx) {
-               mfc_err_dev("[OTF] no mfc context to run\n");
-               return -EINVAL;
-       }
-
-       if (!ctx->otf_handle) {
-               mfc_err_dev("[OTF] otf_handle was not created\n");
-               return -EINVAL;
-       }
-
-       if (mfc_otf_init_hwfc_buf(ctx)) {
-               mfc_err_dev("[OTF] HWFC init failed\n");
-               return -EINVAL;
-       }
-
-       mfc_debug(2, "[OTF] otf_init is completed\n");
-
-       mfc_debug_leave();
-
-       return 0;
-}
-
-void s5p_mfc_otf_deinit(struct s5p_mfc_ctx *ctx)
-{
-       mfc_debug_enter();
-
-       if (!ctx) {
-               mfc_err_dev("[OTF] no mfc context to run\n");
-               return;
-       }
-
-       mfc_otf_deinit_hwfc_buf(ctx);
-       mfc_debug(2, "[OTF] deinit_otf is completed\n");
-
-       mfc_debug_leave();
-}
-
-int s5p_mfc_otf_ctx_ready(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct _otf_handle *handle;
-
-       mfc_debug_enter();
-
-       if (!ctx->otf_handle)
-               return 0;
-
-       handle = ctx->otf_handle;
-
-       mfc_debug(1, "[OTF] [c:%d] state = %d, otf_work_bit = %d\n",
-                       ctx->num, ctx->state, handle->otf_work_bit);
-       /* If shutdown is called, do not try any cmd */
-       if (dev->shutdown)
-               return 0;
-
-       /* Context is to parse header */
-       if (ctx->state == MFCINST_GOT_INST)
-               return 1;
-
-       /* Context is to set buffers */
-       if (ctx->state == MFCINST_HEAD_PARSED)
-               return 1;
-
-       if (ctx->state == MFCINST_RUNNING && handle->otf_work_bit)
-               return 1;
-       mfc_debug(2, "[OTF] ctx is not ready\n");
-
-       mfc_debug_leave();
-
-       return 0;
-}
-
-int s5p_mfc_otf_run_enc_init(struct s5p_mfc_ctx *ctx)
-{
-       int ret;
-
-       mfc_debug_enter();
-
-       s5p_mfc_set_enc_stride(ctx);
-       s5p_mfc_clean_ctx_int_flags(ctx);
-       ret = s5p_mfc_init_encode(ctx);
-
-       mfc_debug_leave();
-
-       return ret;
-}
-
-int s5p_mfc_otf_run_enc_frame(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct _otf_handle *handle = ctx->otf_handle;
-       struct s5p_mfc_raw_info *raw;
-
-       mfc_debug_enter();
-
-       raw = &ctx->raw_buf;
-
-       if (!handle) {
-               mfc_err_ctx("[OTF] There is no otf_handle, handle: 0x%p\n", handle);
-               return -EINVAL;
-       }
-
-       if (!handle->otf_work_bit) {
-               mfc_err_ctx("[OTF] Can't run OTF encoder, otf_work_bit: %d\n",
-                               handle->otf_work_bit);
-               return -EINVAL;
-       }
-
-       if (!dev->has_hwfc) {
-               mfc_err_ctx("[OTF] HWFC register didn't mapped\n");
-               return -EINVAL;
-       }
-
-       s5p_mfc_otf_set_frame_addr(ctx, raw->num_planes);
-       s5p_mfc_otf_set_stream_size(ctx, raw->total_plane_size);
-       s5p_mfc_otf_set_hwfc_index(ctx, handle->otf_job_id);
-
-       if (call_cop(ctx, init_buf_ctrls, ctx, MFC_CTRL_TYPE_SRC, handle->otf_buf_index) < 0)
-               mfc_err_ctx("failed in init_buf_ctrls\n");
-       if (call_cop(ctx, to_buf_ctrls, ctx, &ctx->src_ctrls[handle->otf_buf_index]) < 0)
-               mfc_err_ctx("failed in to_buf_ctrls\n");
-       if (call_cop(ctx, set_buf_ctrls_val, ctx, &ctx->src_ctrls[handle->otf_buf_index]) < 0)
-               mfc_err_ctx("[OTF] failed in set_buf_ctrls_val\n");
-
-       /* Change timestamp usec -> nsec */
-       s5p_mfc_qos_update_last_framerate(ctx, handle->otf_time_stamp * 1000);
-       s5p_mfc_qos_update_framerate(ctx);
-
-       /* Set stream buffer size to handle buffer full */
-       s5p_mfc_clean_ctx_int_flags(ctx);
-       s5p_mfc_encode_one_frame(ctx, 0);
-
-       mfc_debug_leave();
-
-       return 0;
-}
-
-int s5p_mfc_otf_handle_seq(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_enc *enc = ctx->enc_priv;
-
-       mfc_debug_enter();
-
-       enc->header_size = s5p_mfc_get_enc_strm_size();
-       ctx->dpb_count = s5p_mfc_get_enc_dpb_count();
-       ctx->scratch_buf_size = s5p_mfc_get_enc_scratch_size();
-       mfc_debug(2, "[OTF][STREAM] encoded slice type: %d, header size: %d, display order: %d\n",
-                       s5p_mfc_get_enc_slice_type(), enc->header_size,
-                       s5p_mfc_get_enc_pic_count());
-       mfc_debug(2, "[OTF] cpb_count: %d, scratch size: %zu\n",
-                       ctx->dpb_count, ctx->scratch_buf_size);
-
-       s5p_mfc_change_state(ctx, MFCINST_HEAD_PARSED);
-
-       if (s5p_mfc_alloc_codec_buffers(ctx)) {
-               mfc_err_ctx("[OTF] Failed to allocate encoding buffers\n");
-               return -EINVAL;
-       }
-
-       mfc_debug_leave();
-
-       return 0;
-}
-
-int s5p_mfc_otf_handle_stream(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_enc *enc = ctx->enc_priv;
-       struct _otf_handle *handle = ctx->otf_handle;
-       struct _otf_debug *debug = &handle->otf_debug;
-       struct s5p_mfc_special_buf *buf;
-       struct _otf_buf_addr *buf_addr = &handle->otf_buf_addr;
-       struct s5p_mfc_raw_info *raw;
-       dma_addr_t enc_addr[3] = { 0, 0, 0 };
-       int slice_type, i;
-       unsigned int strm_size;
-       unsigned int pic_count;
-       int enc_ret = HWFC_ERR_NONE;
-       unsigned int print_size;
-
-       mfc_debug_enter();
-
-#ifdef CONFIG_VIDEO_EXYNOS_TSMUX
-       mfc_encoding_end();
-#endif
-
-       slice_type = s5p_mfc_get_enc_slice_type();
-       pic_count = s5p_mfc_get_enc_pic_count();
-       strm_size = s5p_mfc_get_enc_strm_size();
-
-       mfc_debug(2, "[OTF][STREAM] encoded slice type: %d, size: %d, display order: %d\n",
-                       slice_type, strm_size, pic_count);
-
-       /* set encoded frame type */
-       enc->frame_type = slice_type;
-       raw = &ctx->raw_buf;
-
-       if (strm_size > 0) {
-               s5p_mfc_get_enc_frame_buffer(ctx, &enc_addr[0], raw->num_planes);
-
-               for (i = 0; i < raw->num_planes; i++)
-                       mfc_debug(2, "[OTF][BUFINFO] ctx[%d] get src addr[%d]: 0x%08llx\n",
-                                       ctx->num, i, enc_addr[i]);
-               if (enc_addr[0] !=  buf_addr->otf_daddr[handle->otf_buf_index][0]) {
-                       mfc_err_ctx("[OTF] address is not matched. 0x%08llx != 0x%08llx\n",
-                                       enc_addr[0], buf_addr->otf_daddr[handle->otf_buf_index][0]);
-                       enc_ret = -HWFC_ERR_MFC;
-               }
-       } else {
-               mfc_err_ctx("[OTF] stream size is zero\n");
-               enc_ret = -HWFC_ERR_MFC;
-       }
-
-       if (otf_dump && !ctx->is_drm) {
-               buf = &debug->stream_buf[debug->frame_cnt];
-               debug->stream_size[debug->frame_cnt] = strm_size;
-               debug->frame_cnt++;
-               if (debug->frame_cnt >= OTF_MAX_BUF)
-                       debug->frame_cnt = 0;
-               /* print stream dump */
-               print_size = (strm_size * 2) + 64;
-
-               if (buf->vaddr)
-                       print_hex_dump(KERN_ERR, "OTF dump: ",
-                                       DUMP_PREFIX_ADDRESS, print_size, 0,
-                                       buf->vaddr, print_size, false);
-       }
-
-       if (call_cop(ctx, recover_buf_ctrls_val, ctx,
-                               &ctx->src_ctrls[handle->otf_buf_index]) < 0)
-               mfc_err_ctx("[OTF] failed in recover_buf_ctrls_val\n");
-       if (call_cop(ctx, cleanup_buf_ctrls, ctx,
-                               MFC_CTRL_TYPE_SRC, handle->otf_buf_index) < 0)
-               mfc_err_ctx("[OTF] failed in cleanup_buf_ctrls\n");
-
-       handle->otf_work_bit = 0;
-       handle->otf_buf_index = 0;
-       handle->otf_job_id = 0;
-
-#ifdef CONFIG_VIDEO_EXYNOS_REPEATER
-       hwfc_encoding_done(enc_ret);
-#endif
-
-       mfc_debug_leave();
-
-       return 0;
-}
-
-void s5p_mfc_otf_handle_error(struct s5p_mfc_ctx *ctx,
-               unsigned int reason, unsigned int err)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct _otf_handle *handle = ctx->otf_handle;
-       int enc_ret = -HWFC_ERR_MFC;
-
-       mfc_debug_enter();
-
-       mfc_err_ctx("[OTF] Interrupt Error: display: %d, decoded: %d\n",
-                       s5p_mfc_get_warn(err), s5p_mfc_get_err(err));
-       err = s5p_mfc_get_err(err);
-
-       /* Error recovery is dependent on the state of context */
-       switch (ctx->state) {
-       case MFCINST_GOT_INST:
-       case MFCINST_INIT:
-       case MFCINST_RETURN_INST:
-       case MFCINST_HEAD_PARSED:
-               mfc_err_ctx("[OTF] error happened during init/de-init\n");
-               break;
-       case MFCINST_RUNNING:
-               if (err == S5P_FIMV_ERR_MFC_TIMEOUT) {
-                       mfc_err_ctx("[OTF] MFC TIMEOUT. go to error state\n");
-                       s5p_mfc_change_state(ctx, MFCINST_ERROR);
-                       enc_ret = -HWFC_ERR_MFC_TIMEOUT;
-               } else if (err == S5P_FIMV_ERR_TS_MUX_TIMEOUT ||
-                               err == S5P_FIMV_ERR_G2D_TIMEOUT) {
-                       mfc_err_ctx("[OTF] TS-MUX or G2D TIMEOUT. skip this frame\n");
-                       enc_ret = -HWFC_ERR_MFC_TIMEOUT;
-               } else {
-                       mfc_err_ctx("[OTF] MFC ERROR. skip this frame\n");
-                       enc_ret = -HWFC_ERR_MFC;
-               }
-
-               handle->otf_work_bit = 0;
-               handle->otf_buf_index = 0;
-               handle->otf_job_id = 0;
-
-               if (call_cop(ctx, recover_buf_ctrls_val, ctx,
-                                       &ctx->src_ctrls[handle->otf_buf_index]) < 0)
-                       mfc_err_ctx("[OTF] failed in recover_buf_ctrls_val\n");
-               if (call_cop(ctx, cleanup_buf_ctrls, ctx,
-                                       MFC_CTRL_TYPE_SRC, handle->otf_buf_index) < 0)
-                       mfc_err_ctx("[OTF] failed in cleanup_buf_ctrls\n");
-
-#ifdef CONFIG_VIDEO_EXYNOS_REPEATER
-               hwfc_encoding_done(enc_ret);
-#endif
-               break;
-       default:
-               mfc_err_ctx("Encountered an error interrupt which had not been handled\n");
-               mfc_err_ctx("ctx->state = %d, ctx->inst_no = %d\n",
-                                               ctx->state, ctx->inst_no);
-               break;
-       }
-
-       s5p_mfc_wake_up_dev(dev, reason, err);
-
-       mfc_debug_leave();
-}
-
-int mfc_hwfc_check_run(struct s5p_mfc_ctx *ctx)
-{
-       struct _otf_handle *handle = ctx->otf_handle;
-
-       mfc_debug_enter();
-
-       if (!handle) {
-               mfc_err_ctx("[OTF] there is no handle for OTF\n");
-               return -EINVAL;
-       }
-       if (handle->otf_work_bit) {
-               mfc_err_ctx("[OTF] OTF is already working\n");
-               return -EINVAL;
-       }
-       if (ctx->state != MFCINST_RUNNING) {
-               mfc_err_ctx("[OTF] mfc is not running state\n");
-               return -EINVAL;
-       }
-
-       mfc_debug_leave();
-
-       return 0;
-}
-
-int s5p_mfc_hwfc_encode(int buf_index, int job_id, struct encoding_param *param)
-{
-       struct s5p_mfc_dev *dev = g_mfc_dev;
-       struct _otf_handle *handle;
-       struct s5p_mfc_ctx *ctx = NULL;
-#ifdef CONFIG_VIDEO_EXYNOS_TSMUX
-       struct packetizing_param packet_param;
-#endif
-       int i;
-
-       mfc_debug_enter();
-
-#ifdef CONFIG_VIDEO_EXYNOS_TSMUX
-       mfc_encoding_start(buf_index);
-#endif
-
-       for (i = 0; i < MFC_NUM_CONTEXTS; i++) {
-               if (dev->ctx[i] && dev->ctx[i]->otf_handle) {
-                       ctx = dev->ctx[i];
-                       break;
-               }
-       }
-
-       if (!ctx) {
-               mfc_err_dev("[OTF] there is no context to run\n");
-               return -HWFC_ERR_MFC_NOT_PREPARED;
-       }
-
-       if (mfc_hwfc_check_run(ctx)) {
-               mfc_err_dev("[OTF] mfc is not prepared\n");
-               return -HWFC_ERR_MFC_NOT_PREPARED;
-       }
-
-#ifdef CONFIG_VIDEO_EXYNOS_TSMUX
-       packet_param.time_stamp = param->time_stamp;
-       if (debug_ts == 1)
-               mfc_info_ctx("[OTF][TS] timestamp: %llu\n", param->time_stamp);
-       if (packetize(&packet_param)) {
-               mfc_err_dev("[OTF] packetize failed\n");
-               return -HWFC_ERR_TSMUX;
-       }
-#endif
-
-       handle = ctx->otf_handle;
-       handle->otf_work_bit = 1;
-       handle->otf_buf_index = buf_index;
-       handle->otf_job_id = job_id;
-       handle->otf_time_stamp = param->time_stamp;
-
-       if (s5p_mfc_otf_ctx_ready(ctx))
-               s5p_mfc_set_bit(ctx->num, &dev->work_bits);
-       if (s5p_mfc_is_work_to_do(dev))
-               queue_work(dev->butler_wq, &dev->butler_work);
-
-       mfc_debug_leave();
-
-       return HWFC_ERR_NONE;
-}
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_otf.h b/drivers/media/platform/exynos/mfc/s5p_mfc_otf.h
deleted file mode 100644 (file)
index e7b5e57..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_otf.h
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __S5P_MFC_OTF_H
-#define __S5P_MFC_OTF_H __FILE__
-
-#include "s5p_mfc_common.h"
-
-extern struct s5p_mfc_dev *g_mfc_dev;
-
-int s5p_mfc_otf_create(struct s5p_mfc_ctx *ctx);
-void s5p_mfc_otf_destroy(struct s5p_mfc_ctx *ctx);
-int s5p_mfc_otf_init(struct s5p_mfc_ctx *ctx);
-void s5p_mfc_otf_deinit(struct s5p_mfc_ctx *ctx);
-int s5p_mfc_otf_ctx_ready(struct s5p_mfc_ctx *ctx);
-int s5p_mfc_otf_run_enc_init(struct s5p_mfc_ctx *ctx);
-int s5p_mfc_otf_run_enc_frame(struct s5p_mfc_ctx *ctx);
-int s5p_mfc_otf_handle_seq(struct s5p_mfc_ctx *ctx);
-int s5p_mfc_otf_handle_stream(struct s5p_mfc_ctx *ctx);
-void s5p_mfc_otf_handle_error(struct s5p_mfc_ctx *ctx, unsigned int reason, unsigned int err);
-
-#endif /* __S5P_MFC_OTF_H  */
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_perf_measure.c b/drivers/media/platform/exynos/mfc/s5p_mfc_perf_measure.c
deleted file mode 100644 (file)
index 47e7731..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_perf_measure.c
- *
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include "s5p_mfc_perf_measure.h"
-
-#ifndef PERF_MEASURE
-
-void s5p_mfc_perf_register(struct s5p_mfc_dev *dev) {}
-void mfc_measure_init(void) {}
-void mfc_measure_on(struct s5p_mfc_dev *dev) {}
-void mfc_measure_off(struct s5p_mfc_dev *dev) {}
-void mfc_measure_store(struct s5p_mfc_dev *dev, int diff) {}
-void s5p_mfc_perf_print(void) {}
-
-#else
-
-#endif
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_perf_measure.h b/drivers/media/platform/exynos/mfc/s5p_mfc_perf_measure.h
deleted file mode 100644 (file)
index 7c4426b..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_perf_measure.h
- *
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __S5P_MFC_PERF_MEASURE_H
-#define __S5P_MFC_PERF_MEASURE_H __FILE__
-
-#include <linux/clk.h>
-
-#include "s5p_mfc_reg.h"
-
-void s5p_mfc_perf_register(struct s5p_mfc_dev *dev);
-void mfc_measure_init(void);
-void mfc_measure_on(struct s5p_mfc_dev *dev);
-void mfc_measure_off(struct s5p_mfc_dev *dev);
-void mfc_measure_store(struct s5p_mfc_dev *dev, int diff);
-void s5p_mfc_perf_print(void);
-
-//#define PERF_MEASURE
-
-#ifndef PERF_MEASURE
-
-static inline void s5p_mfc_perf_init(struct s5p_mfc_dev *dev) {}
-static inline void s5p_mfc_perf_cancel_drv_margin(struct s5p_mfc_dev *dev) {}
-static inline void s5p_mfc_perf_measure_on(struct s5p_mfc_dev *dev) {}
-static inline void s5p_mfc_perf_measure_off(struct s5p_mfc_dev *dev) {}
-
-#else
-
-extern unsigned int perf_measure_option;
-
-static inline void s5p_mfc_perf_init(struct s5p_mfc_dev *dev)
-{
-       dev->perf.new_start = 0;
-       dev->perf.count = 0;
-       dev->perf.drv_margin = 0;
-
-       mfc_measure_init();
-
-       mfc_info_dev("MFC frequency : %ld\n", clk_get_rate(dev->pm.clock));
-}
-
-static inline void s5p_mfc_perf_cancel_drv_margin(struct s5p_mfc_dev *dev)
-{
-       dev->perf.drv_margin = 0;
-}
-
-static inline void s5p_mfc_perf_measure_on(struct s5p_mfc_dev *dev)
-{
-       int diff;
-
-       if (dev->perf.drv_margin) {
-               do_gettimeofday(&dev->perf.end);
-
-               diff = (dev->perf.end.tv_sec * 1000000 + dev->perf.end.tv_usec)
-                       - (dev->perf.begin.tv_sec * 1000000 + dev->perf.begin.tv_usec);
-
-               mfc_info_dev("IRQ -> NAL_START time(ms) = %03d.%03d\n", diff / 1000, diff % 1000);
-
-               dev->perf.drv_margin = 0;
-       }
-
-       do_gettimeofday(&dev->perf.begin);
-
-       mfc_measure_on(dev);
-
-       dev->perf.new_start = 1;
-       dev->perf.count++;
-}
-
-static inline void s5p_mfc_perf_measure_off(struct s5p_mfc_dev *dev)
-{
-       unsigned int diff;
-
-       if ((dev->perf.new_start) && (dev->perf.count > 0)) {
-               mfc_measure_off(dev);
-
-               do_gettimeofday(&dev->perf.end);
-
-               diff = (dev->perf.end.tv_sec * 1000000 + dev->perf.end.tv_usec)
-                       - (dev->perf.begin.tv_sec * 1000000 + dev->perf.begin.tv_usec);
-
-               mfc_measure_store(dev, diff);
-
-               mfc_debug(3, "uDECtype :%d, uENCtype :%d, codectype :%d\n",
-                       s5p_mfc_get_dec_frame_type(), s5p_mfc_get_enc_slice_type(), MFC_READL(S5P_FIMV_CODEC_TYPE));
-
-               dev->perf.drv_margin = 1;
-
-               do_gettimeofday(&dev->perf.begin);
-       }
-
-       dev->perf.new_start = 0;
-}
-
-#endif
-
-#endif /* __S5P_MFC_PERF_MEASURE_H */
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_pm.c b/drivers/media/platform/exynos/mfc/s5p_mfc_pm.c
deleted file mode 100644 (file)
index e301b53..0000000
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_pm.c
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/pm_runtime.h>
-#include <linux/clk.h>
-#include <linux/smc.h>
-
-#include "s5p_mfc_pm.h"
-
-#include "s5p_mfc_cal.h"
-#include "s5p_mfc_reg.h"
-
-void s5p_mfc_pm_init(struct s5p_mfc_dev *dev)
-{
-       spin_lock_init(&dev->pm.clklock);
-       atomic_set(&dev->pm.pwr_ref, 0);
-       atomic_set(&dev->clk_ref, 0);
-
-       dev->pm.device = dev->device;
-       dev->pm.clock_on_steps = 0;
-       dev->pm.clock_off_steps = 0;
-       pm_runtime_enable(dev->pm.device);
-}
-
-void s5p_mfc_pm_final(struct s5p_mfc_dev *dev)
-{
-       pm_runtime_disable(dev->pm.device);
-}
-
-int s5p_mfc_pm_clock_on(struct s5p_mfc_dev *dev)
-{
-       int ret = 0;
-       int state;
-
-       dev->pm.clock_on_steps = 1;
-       state = atomic_read(&dev->clk_ref);
-
-       MFC_TRACE_DEV("** clock_on start: ref state(%d)\n", state);
-       ret = clk_enable(dev->pm.clock);
-       if (ret < 0) {
-               mfc_err_dev("clk_enable failed (%d)\n", ret);
-               call_dop(dev, dump_and_stop_debug_mode, dev);
-               return ret;
-       }
-       dev->pm.clock_on_steps |= 0x1 << 1;
-
-       if (dev->pm.base_type != MFCBUF_INVALID)
-               s5p_mfc_set_risc_base_addr(dev, dev->pm.base_type);
-
-       dev->pm.clock_on_steps |= 0x1 << 2;
-#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
-       if (dev->curr_ctx_is_drm) {
-               unsigned long flags;
-
-               spin_lock_irqsave(&dev->pm.clklock, flags);
-               mfc_debug(3, "Begin: enable protection\n");
-               ret = exynos_smc(SMC_PROTECTION_SET, 0,
-                                       dev->id, SMC_PROTECTION_ENABLE);
-               dev->pm.clock_on_steps |= 0x1 << 3;
-               if (ret != DRMDRV_OK) {
-                       mfc_err_dev("Protection Enable failed! ret(%u)\n", ret);
-                       call_dop(dev, dump_and_stop_debug_mode, dev);
-                       spin_unlock_irqrestore(&dev->pm.clklock, flags);
-                       clk_disable(dev->pm.clock);
-                       return -EACCES;
-               }
-               mfc_debug(3, "End: enable protection\n");
-               spin_unlock_irqrestore(&dev->pm.clklock, flags);
-       }
-#endif
-       dev->pm.clock_on_steps |= 0x1 << 4;
-       atomic_inc_return(&dev->clk_ref);
-
-       dev->pm.clock_on_steps |= 0x1 << 6;
-       state = atomic_read(&dev->clk_ref);
-       mfc_debug(2, "+ %d\n", state);
-       MFC_TRACE_DEV("** clock_on end: ref state(%d)\n", state);
-
-       return 0;
-}
-
-/* Use only in functions that first instance is guaranteed, like mfc_init_hw() */
-int s5p_mfc_pm_clock_on_with_base(struct s5p_mfc_dev *dev,
-                               enum mfc_buf_usage_type buf_type)
-{
-       int ret;
-       dev->pm.base_type = buf_type;
-       ret = s5p_mfc_pm_clock_on(dev);
-       dev->pm.base_type = MFCBUF_INVALID;
-
-       return ret;
-}
-
-void s5p_mfc_pm_clock_off(struct s5p_mfc_dev *dev)
-{
-       int state;
-
-       dev->pm.clock_off_steps = 1;
-       atomic_dec_return(&dev->clk_ref);
-
-       dev->pm.clock_off_steps |= 0x1 << 1;
-       state = atomic_read(&dev->clk_ref);
-       MFC_TRACE_DEV("** clock_off start: ref state(%d)\n", state);
-       if (state < 0) {
-               mfc_err_dev("Clock state is wrong(%d)\n", state);
-               atomic_set(&dev->clk_ref, 0);
-               dev->pm.clock_off_steps |= 0x1 << 2;
-       } else {
-#ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION
-               if (dev->curr_ctx_is_drm) {
-                       unsigned long flags;
-                       int ret = 0;
-
-                       mfc_debug(3, "Begin: disable protection\n");
-                       spin_lock_irqsave(&dev->pm.clklock, flags);
-                       dev->pm.clock_off_steps |= 0x1 << 3;
-                       ret = exynos_smc(SMC_PROTECTION_SET, 0,
-                                       dev->id, SMC_PROTECTION_DISABLE);
-                       if (ret != DRMDRV_OK) {
-                               mfc_err_dev("Protection Disable failed! ret(%u)\n", ret);
-                               call_dop(dev, dump_and_stop_debug_mode, dev);
-                               spin_unlock_irqrestore(&dev->pm.clklock, flags);
-                               clk_disable(dev->pm.clock);
-                               return;
-                       }
-                       mfc_debug(3, "End: disable protection\n");
-                       dev->pm.clock_off_steps |= 0x1 << 4;
-                       spin_unlock_irqrestore(&dev->pm.clklock, flags);
-               }
-#endif
-               dev->pm.clock_off_steps |= 0x1 << 5;
-               clk_disable(dev->pm.clock);
-       }
-
-       dev->pm.clock_off_steps |= 0x1 << 6;
-       state = atomic_read(&dev->clk_ref);
-       mfc_debug(2, "- %d\n", state);
-       MFC_TRACE_DEV("** clock_off end: ref state(%d)\n", state);
-}
-
-int s5p_mfc_pm_power_on(struct s5p_mfc_dev *dev)
-{
-       int ret;
-
-       MFC_TRACE_DEV("++ Power on\n");
-       ret = pm_runtime_get_sync(dev->pm.device);
-       if (ret < 0) {
-               mfc_err_dev("Failed to get power: ret(%d)\n", ret);
-               call_dop(dev, dump_and_stop_debug_mode, dev);
-               goto err_power_on;
-       }
-
-       dev->pm.clock = clk_get(dev->device, "aclk_mfc");
-       if (IS_ERR(dev->pm.clock)) {
-               mfc_err_dev("failed to get parent clock: ret(%d)\n", ret);
-               ret = -ENOENT;
-               goto err_clk_get;
-       }
-
-       ret = clk_prepare(dev->pm.clock);
-       if (ret) {
-               mfc_err_dev("clk_prepare() failed: ret(%d)\n", ret);
-               goto err_clk_prepare;
-       }
-
-       atomic_inc(&dev->pm.pwr_ref);
-
-       MFC_TRACE_DEV("-- Power on: ret(%d)\n", ret);
-
-       return 0;
-
-err_clk_prepare:
-       clk_put(dev->pm.clock);
-
-err_clk_get:
-       pm_runtime_put_sync(dev->pm.device);
-
-err_power_on:
-       return ret;
-}
-
-int s5p_mfc_pm_power_off(struct s5p_mfc_dev *dev)
-{
-       int ret;
-
-       MFC_TRACE_DEV("++ Power off\n");
-
-       clk_unprepare(dev->pm.clock);
-       clk_put(dev->pm.clock);
-
-       ret = pm_runtime_put_sync(dev->pm.device);
-       if (ret < 0) {
-               mfc_err_dev("Failed to put power: ret(%d)\n", ret);
-               call_dop(dev, dump_and_stop_debug_mode, dev);
-               return ret;
-       }
-
-       atomic_dec(&dev->pm.pwr_ref);
-
-       MFC_TRACE_DEV("-- Power off: ret(%d)\n", ret);
-
-       return ret;
-}
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_pm.h b/drivers/media/platform/exynos/mfc/s5p_mfc_pm.h
deleted file mode 100644 (file)
index d185b57..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_pm.h
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __S5P_MFC_PM_H
-#define __S5P_MFC_PM_H __FILE__
-
-#include "s5p_mfc_common.h"
-
-static inline int s5p_mfc_pm_get_pwr_ref_cnt(struct s5p_mfc_dev *dev)
-{
-       return atomic_read(&dev->pm.pwr_ref);
-}
-
-static inline int s5p_mfc_pm_get_clk_ref_cnt(struct s5p_mfc_dev *dev)
-{
-       return atomic_read(&dev->clk_ref);
-}
-
-void s5p_mfc_pm_init(struct s5p_mfc_dev *dev);
-void s5p_mfc_pm_final(struct s5p_mfc_dev *dev);
-
-int s5p_mfc_pm_clock_on(struct s5p_mfc_dev *dev);
-int s5p_mfc_pm_clock_on_with_base(struct s5p_mfc_dev *dev,
-                       enum mfc_buf_usage_type buf_type);
-void s5p_mfc_pm_clock_off(struct s5p_mfc_dev *dev);
-int s5p_mfc_pm_power_on(struct s5p_mfc_dev *dev);
-int s5p_mfc_pm_power_off(struct s5p_mfc_dev *dev);
-
-#endif /* __S5P_MFC_PM_H */
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_qos.c b/drivers/media/platform/exynos/mfc/s5p_mfc_qos.c
deleted file mode 100644 (file)
index 8655a4b..0000000
+++ /dev/null
@@ -1,832 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_qos.c
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/err.h>
-#ifdef CONFIG_EXYNOS_BTS
-#include <soc/samsung/bts.h>
-#endif
-
-#include "s5p_mfc_qos.h"
-
-#ifdef CONFIG_MFC_USE_BUS_DEVFREQ
-enum {
-       MFC_QOS_ADD,
-       MFC_QOS_UPDATE,
-       MFC_QOS_REMOVE,
-       MFC_QOS_BW,
-};
-
-enum {
-       MFC_PERF_BOOST_DVFS     = (1 << 0),
-       MFC_PERF_BOOST_MO       = (1 << 1),
-       MFC_PERF_BOOST_CPU      = (1 << 2),
-};
-
-void s5p_mfc_perf_boost_enable(struct s5p_mfc_dev *dev)
-{
-       struct s5p_mfc_platdata *pdata = dev->pdata;
-       struct s5p_mfc_qos_boost *qos_boost_table = pdata->qos_boost_table;
-       int i;
-
-       if (perf_boost_mode & MFC_PERF_BOOST_DVFS) {
-               if (pdata->mfc_freq_control)
-                       pm_qos_add_request(&dev->qos_req_mfc, PM_QOS_MFC_THROUGHPUT,
-                                       qos_boost_table->freq_mfc);
-               pm_qos_add_request(&dev->qos_req_int, PM_QOS_DEVICE_THROUGHPUT,
-                               qos_boost_table->freq_int);
-               pm_qos_add_request(&dev->qos_req_mif, PM_QOS_BUS_THROUGHPUT,
-                               qos_boost_table->freq_mif);
-               mfc_debug(3, "[QoS][BOOST] DVFS mfc: %d, int:%d, mif:%d\n",
-                               qos_boost_table->freq_mfc, qos_boost_table->freq_int,
-                               qos_boost_table->freq_mif);
-       }
-
-#ifdef CONFIG_EXYNOS_BTS
-       if (perf_boost_mode & MFC_PERF_BOOST_MO) {
-               if (pdata->mo_control) {
-                       bts_update_scen(BS_MFC_UHD_10BIT, 1);
-                       mfc_debug(3, "[QoS][BOOST] BTS(MO): UHD_10BIT\n");
-               }
-       }
-#endif
-
-       if (perf_boost_mode & MFC_PERF_BOOST_CPU) {
-               for (i = 0; i < qos_boost_table->num_cluster; i++) {
-                       pm_qos_add_request(&dev->qos_req_cluster[i], PM_QOS_CLUSTER0_FREQ_MIN + (i * 2),
-                                       qos_boost_table->freq_cluster[i]);
-                       mfc_debug(3, "[QoS][BOOST] CPU cluster[%d]: %d\n",
-                                       i, qos_boost_table->freq_cluster[i]);
-               }
-       }
-}
-
-void s5p_mfc_perf_boost_disable(struct s5p_mfc_dev *dev)
-{
-       struct s5p_mfc_platdata *pdata = dev->pdata;
-       int i;
-
-       if (perf_boost_mode & MFC_PERF_BOOST_DVFS) {
-               if (pdata->mfc_freq_control)
-                       pm_qos_remove_request(&dev->qos_req_mfc);
-               pm_qos_remove_request(&dev->qos_req_int);
-               pm_qos_remove_request(&dev->qos_req_mif);
-               mfc_debug(3, "[QoS][BOOST] DVFS off\n");
-       }
-
-#ifdef CONFIG_EXYNOS_BTS
-       if (perf_boost_mode & MFC_PERF_BOOST_MO) {
-               if (pdata->mo_control) {
-                       bts_update_scen(BS_MFC_UHD_10BIT, 0);
-                       mfc_debug(3, "[QoS][BOOST] BTS(MO) off\n");
-               }
-       }
-#endif
-
-       if (perf_boost_mode & MFC_PERF_BOOST_CPU) {
-               for (i = 0; i < pdata->qos_boost_table->num_cluster; i++) {
-                       pm_qos_remove_request(&dev->qos_req_cluster[i]);
-                       mfc_debug(3, "[QoS][BOOST] CPU cluster[%d] off\n", i);
-               }
-       }
-}
-
-static void mfc_qos_operate(struct s5p_mfc_ctx *ctx, int opr_type, int idx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_platdata *pdata = dev->pdata;
-       struct s5p_mfc_qos *qos_table = pdata->qos_table;
-
-       switch (opr_type) {
-       case MFC_QOS_ADD:
-               if (pdata->mfc_freq_control)
-                       pm_qos_add_request(&dev->qos_req_mfc,
-                                       PM_QOS_MFC_THROUGHPUT,
-                                       qos_table[idx].freq_mfc);
-               pm_qos_add_request(&dev->qos_req_int,
-                               PM_QOS_DEVICE_THROUGHPUT,
-                               qos_table[idx].freq_int);
-               pm_qos_add_request(&dev->qos_req_mif,
-                               PM_QOS_BUS_THROUGHPUT,
-                               qos_table[idx].freq_mif);
-
-#ifdef CONFIG_EXYNOS_BTS
-               if (pdata->mo_control) {
-                       bts_update_scen(BS_MFC_UHD_ENC60, qos_table[idx].mo_uhd_enc60_value);
-                       bts_update_scen(BS_MFC_UHD_10BIT, qos_table[idx].mo_10bit_value);
-                       bts_update_scen(BS_MFC_UHD, qos_table[idx].mo_value);
-                       MFC_TRACE_CTX("BTS(MO) update - uhd:%d, uhd_10bit:%d, uhd_enc60:%d\n",
-                                       qos_table[idx].mo_value, qos_table[idx].mo_10bit_value,
-                                       qos_table[idx].mo_uhd_enc60_value);
-                       mfc_debug(2, "[QoS] BTS(MO) update - uhd:%d, uhd_10bit:%d, uhd_enc60:%d\n",
-                                       qos_table[idx].mo_value, qos_table[idx].mo_10bit_value,
-                                       qos_table[idx].mo_uhd_enc60_value);
-               }
-#endif
-
-               atomic_set(&dev->qos_req_cur, idx + 1);
-               MFC_TRACE_CTX("QoS add[%d] - mfc:%d(%s), int:%d, mif:%d\n",
-                               idx, qos_table[idx].freq_mfc, pdata->mfc_freq_control ? "used" : "un-used",
-                               qos_table[idx].freq_int, qos_table[idx].freq_mif);
-               mfc_debug(2, "[QoS] QoS add[%d] - mfc:%d(%s), int:%d, mif:%d\n",
-                               idx, qos_table[idx].freq_mfc, pdata->mfc_freq_control ? "used" : "un-used",
-                                qos_table[idx].freq_int, qos_table[idx].freq_mif);
-               break;
-       case MFC_QOS_UPDATE:
-               if (pdata->mfc_freq_control)
-                       pm_qos_update_request(&dev->qos_req_mfc,
-                                       qos_table[idx].freq_mfc);
-               pm_qos_update_request(&dev->qos_req_int,
-                               qos_table[idx].freq_int);
-               pm_qos_update_request(&dev->qos_req_mif,
-                               qos_table[idx].freq_mif);
-
-#ifdef CONFIG_EXYNOS_BTS
-               if (pdata->mo_control) {
-                       bts_update_scen(BS_MFC_UHD_ENC60, qos_table[idx].mo_uhd_enc60_value);
-                       bts_update_scen(BS_MFC_UHD_10BIT, qos_table[idx].mo_10bit_value);
-                       bts_update_scen(BS_MFC_UHD, qos_table[idx].mo_value);
-                       MFC_TRACE_CTX("BTS(MO) update - uhd:%d, uhd_10bit:%d, uhd_enc60:%d\n",
-                                       qos_table[idx].mo_value, qos_table[idx].mo_10bit_value,
-                                       qos_table[idx].mo_uhd_enc60_value);
-                       mfc_debug(2, "[QoS] BTS(MO) update - uhd:%d, uhd_10bit:%d, uhd_enc60:%d\n",
-                                       qos_table[idx].mo_value, qos_table[idx].mo_10bit_value,
-                                       qos_table[idx].mo_uhd_enc60_value);
-               }
-#endif
-
-               atomic_set(&dev->qos_req_cur, idx + 1);
-               MFC_TRACE_CTX("QoS update[%d] - mfc:%d(%s), int:%d, mif:%d\n",
-                               idx, qos_table[idx].freq_mfc, pdata->mfc_freq_control ? "used" : "un-used",
-                               qos_table[idx].freq_int, qos_table[idx].freq_mif);
-               mfc_debug(2, "[QoS] QoS update[%d] - mfc:%d(%s), int:%d, mif:%d\n",
-                               idx, qos_table[idx].freq_mfc, pdata->mfc_freq_control ? "used" : "un-used",
-                               qos_table[idx].freq_int, qos_table[idx].freq_mif);
-               break;
-       case MFC_QOS_REMOVE:
-               if (pdata->mfc_freq_control)
-                       pm_qos_remove_request(&dev->qos_req_mfc);
-               pm_qos_remove_request(&dev->qos_req_int);
-               pm_qos_remove_request(&dev->qos_req_mif);
-
-#ifdef CONFIG_EXYNOS_BTS
-               if (pdata->mo_control) {
-                       bts_update_scen(BS_MFC_UHD_ENC60, 0);
-                       bts_update_scen(BS_MFC_UHD_10BIT, 0);
-                       bts_update_scen(BS_MFC_UHD, 0);
-               }
-
-               if (pdata->bw_control) {
-                       dev->mfc_bw.peak = 0;
-                       dev->mfc_bw.read = 0;
-                       dev->mfc_bw.write = 0;
-                       bts_update_bw(BTS_BW_MFC, dev->mfc_bw);
-               }
-#endif
-
-               atomic_set(&dev->qos_req_cur, 0);
-               MFC_TRACE_CTX("QoS remove\n");
-               mfc_debug(2, "[QoS] QoS remove\n");
-               break;
-       case MFC_QOS_BW:
-#ifdef CONFIG_EXYNOS_BTS
-               if (pdata->bw_control) {
-                       bts_update_bw(BTS_BW_MFC, dev->mfc_bw);
-                       MFC_TRACE_CTX("BTS(BW) update (peak: %d, read: %d, write: %d)\n",
-                                       dev->mfc_bw.peak, dev->mfc_bw.read, dev->mfc_bw.write);
-                       mfc_debug(2, "[QoS] BTS(BW) update (peak: %d, read: %d, write: %d)\n",
-                                       dev->mfc_bw.peak, dev->mfc_bw.read, dev->mfc_bw.write);
-               }
-#endif
-               break;
-       default:
-               mfc_err_ctx("[QoS] Unknown request for opr [%d]\n", opr_type);
-               break;
-       }
-}
-
-#ifdef CONFIG_EXYNOS_BTS
-static void mfc_qos_set(struct s5p_mfc_ctx *ctx, struct bts_bw *mfc_bw, int i)
-#else
-static void mfc_qos_set(struct s5p_mfc_ctx *ctx, int i)
-#endif
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_platdata *pdata = dev->pdata;
-       struct s5p_mfc_qos *qos_table = pdata->qos_table;
-
-       mfc_debug(2, "[QoS] table[%d] covered mb %d ~ %d (mfc: %d, int:%d, mif:%d)\n",
-                       i, qos_table[i].threshold_mb,
-                       i == pdata->num_qos_steps - 1 ?
-                       pdata->max_mb : qos_table[i + 1].threshold_mb,
-                       qos_table[i].freq_mfc, qos_table[i].freq_int,
-                       qos_table[i].freq_mif);
-
-#ifdef CONFIG_EXYNOS_BTS
-       if (mfc_bw->peak != dev->mfc_bw.peak) {
-               dev->mfc_bw.peak = mfc_bw->peak;
-               dev->mfc_bw.read = mfc_bw->read;
-               dev->mfc_bw.write = mfc_bw->write;
-               mfc_qos_operate(ctx, MFC_QOS_BW, i);
-       }
-#endif
-
-       if (atomic_read(&dev->qos_req_cur) == 0)
-               mfc_qos_operate(ctx, MFC_QOS_ADD, i);
-       else if (atomic_read(&dev->qos_req_cur) != (i + 1))
-               mfc_qos_operate(ctx, MFC_QOS_UPDATE, i);
-}
-
-static inline unsigned long mfc_qos_get_weighted_mb(struct s5p_mfc_ctx *ctx,
-                                               unsigned long mb)
-{
-       struct s5p_mfc_enc *enc = ctx->enc_priv;
-       struct s5p_mfc_dec *dec = ctx->dec_priv;
-       struct s5p_mfc_enc_params *p;
-       u32 num_planes = ctx->dst_fmt->num_planes;
-       int weight = 1000;
-       unsigned long weighted_mb;
-
-       switch (ctx->codec_mode) {
-       case S5P_FIMV_CODEC_H264_DEC:
-       case S5P_FIMV_CODEC_H264_MVC_DEC:
-       case S5P_FIMV_CODEC_H264_ENC:
-       case S5P_FIMV_CODEC_H264_MVC_ENC:
-       case S5P_FIMV_CODEC_VP8_DEC:
-       case S5P_FIMV_CODEC_VP8_ENC:
-               if (num_planes == 3)
-                       weight = (weight * 100) / MFC_QOS_WEIGHT_3PLANE;
-               break;
-
-       case S5P_FIMV_CODEC_HEVC_DEC:
-       case S5P_FIMV_CODEC_HEVC_ENC:
-       case S5P_FIMV_CODEC_VP9_DEC:
-       case S5P_FIMV_CODEC_VP9_ENC:
-       case S5P_FIMV_CODEC_BPG_DEC:
-       case S5P_FIMV_CODEC_BPG_ENC:
-               if (num_planes == 3) {
-                       weight = (weight * 100) / MFC_QOS_WEIGHT_3PLANE;
-               } else {
-                       if (ctx->is_10bit)
-                               weight = (weight * 100) / MFC_QOS_WEIGHT_10BIT;
-                       else if (ctx->is_422)
-                               weight = (weight * 100) / MFC_QOS_WEIGHT_422_10INTRA;
-               }
-               break;
-
-       case S5P_FIMV_CODEC_MPEG4_DEC:
-       case S5P_FIMV_CODEC_FIMV1_DEC:
-       case S5P_FIMV_CODEC_FIMV2_DEC:
-       case S5P_FIMV_CODEC_FIMV3_DEC:
-       case S5P_FIMV_CODEC_FIMV4_DEC:
-       case S5P_FIMV_CODEC_H263_DEC:
-       case S5P_FIMV_CODEC_VC1_RCV_DEC:
-       case S5P_FIMV_CODEC_VC1_DEC:
-       case S5P_FIMV_CODEC_MPEG2_DEC:
-       case S5P_FIMV_CODEC_MPEG4_ENC:
-       case S5P_FIMV_CODEC_H263_ENC:
-               weight = (weight * 100) / MFC_QOS_WEIGHT_OTHER_CODEC;
-               break;
-
-       default:
-               mfc_err_ctx("[QoS] wrong codec_mode (%d), no weight\n", ctx->codec_mode);
-       }
-
-       if (enc) {
-               p = &enc->params;
-               if ((IS_H264_ENC(ctx) || IS_HEVC_ENC(ctx)) && p->num_b_frame) {
-                       weight = (weight * 100) / MFC_QOS_WEIGHT_BFRAME;
-                       mfc_debug(3, "[QoS] weight: B frame encoding\n");
-               }
-               if ((IS_H264_ENC(ctx) || IS_HEVC_ENC(ctx) || IS_VP8_ENC(ctx) ||
-                                       IS_VP9_ENC(ctx)) && (p->num_refs_for_p >= 2)) {
-                       weight = (weight * 100) / MFC_QOS_WEIGHT_NUM_OF_REF;
-                       mfc_debug(3, "[QoS] weight: num of ref >= 2\n");
-               }
-       }
-       if (dec) {
-               if (dec->num_of_tile_over_4) {
-                       weight = (weight * 100) / MFC_QOS_WEIGHT_NUM_OF_TILE;
-                       mfc_debug(3, "[QoS] weight: num of tile >= 4\n");
-               }
-       }
-
-       weighted_mb = (mb * weight) / 1000;
-       mfc_debug(3, "[QoS] weight: %d.%03d, codec: %d, num planes: %d, "
-                       "10bit: %d, 422format: %d (mb: %ld)\n",
-                       weight / 1000, weight % 1000, ctx->codec_mode,
-                       num_planes, ctx->is_10bit, ctx->is_422,
-                       weighted_mb);
-
-
-       return weighted_mb;
-}
-
-static inline unsigned long mfc_qos_get_mb_per_second(struct s5p_mfc_ctx *ctx)
-{
-       unsigned long mb_width, mb_height, fps, mb;
-
-       mb_width = (ctx->crop_width + 15) / 16;
-       mb_height = (ctx->crop_height + 15) / 16;
-       fps = ctx->framerate / 1000;
-
-       mb = mb_width * mb_height * fps;
-       mfc_debug(4, "[QoS] ctx[%d:%s] %d x %d @ %ld fps (mb: %ld)\n",
-                       ctx->num, ctx->type == MFCINST_ENCODER ? "ENC" : "DEC",
-                       ctx->crop_width, ctx->crop_height, fps, mb);
-
-       return mfc_qos_get_weighted_mb(ctx, mb);
-}
-
-#ifdef CONFIG_EXYNOS_BTS
-static struct s5p_mfc_qos_bw mfc_bw_info = {
-       /*                                peak   read   write   (KB/UHD frame) */
-       .h264_dec_uhd_bw        =       { 38131, 40206, 24870 },
-       .hevc_dec_uhd_bw        =       { 35055, 33741, 20511 },
-       .hevc_dec_uhd_10bit_bw  =       { 38643, 36428, 25491 },
-       .vp8_dec_uhd_bw         =       { 28693, 30464, 22331 },
-       .vp9_dec_uhd_bw         =       { 21464, 22160, 19747 },
-       .mpeg4_dec_uhd_bw       =       { 31567, 25191, 15961 },
-       .h264_enc_uhd_bw        =       { 62543, 75230, 13080 },
-       .hevc_enc_uhd_bw        =       { 54863, 65417, 11422 },
-       .hevc_enc_uhd_10bit_bw  =       { 68011, 79367, 14688 },
-       .vp8_enc_uhd_bw         =       { 63970, 67281, 22508 },
-       .vp9_enc_uhd_bw         =       { 84443, 71588, 19337 },
-       .mpeg4_enc_uhd_bw       =       { 44633, 55310, 9599  },
-};
-
-static void mfc_qos_get_bw_per_second(struct s5p_mfc_ctx *ctx, struct bts_bw *mfc_bw)
-{
-       struct mfc_qos_bw_data bw_data;
-       unsigned long mb_width, mb_height, fps, mb;
-       unsigned long peak_bw_per_sec;
-       unsigned long read_bw_per_sec;
-       unsigned long write_bw_per_sec;
-       unsigned long mb_count_per_uhd_frame = MB_COUNT_PER_UHD_FRAME;
-       unsigned long max_fps_per_uhd_frame = MAX_FPS_PER_UHD_FRAME;
-
-       mb_width = (ctx->crop_width + 15) / 16;
-       mb_height = (ctx->crop_height + 15) / 16;
-       fps = ctx->framerate / 1000;
-
-       mb = mb_width * mb_height * fps;
-
-       switch (ctx->codec_mode) {
-       case S5P_FIMV_CODEC_H264_DEC:
-       case S5P_FIMV_CODEC_H264_MVC_DEC:
-               bw_data = mfc_bw_info.h264_dec_uhd_bw;
-               break;
-       case S5P_FIMV_CODEC_H264_ENC:
-       case S5P_FIMV_CODEC_H264_MVC_ENC:
-               bw_data = mfc_bw_info.h264_enc_uhd_bw;
-               break;
-       case S5P_FIMV_CODEC_HEVC_DEC:
-       case S5P_FIMV_CODEC_BPG_DEC:
-               if (ctx->is_10bit)
-                       bw_data = mfc_bw_info.hevc_dec_uhd_10bit_bw;
-               else
-                       bw_data = mfc_bw_info.hevc_dec_uhd_bw;
-               break;
-       case S5P_FIMV_CODEC_HEVC_ENC:
-       case S5P_FIMV_CODEC_BPG_ENC:
-               if (ctx->is_10bit)
-                       bw_data = mfc_bw_info.hevc_enc_uhd_10bit_bw;
-               else
-                       bw_data = mfc_bw_info.hevc_enc_uhd_bw;
-               break;
-       case S5P_FIMV_CODEC_MPEG4_DEC:
-       case S5P_FIMV_CODEC_FIMV1_DEC:
-       case S5P_FIMV_CODEC_FIMV2_DEC:
-       case S5P_FIMV_CODEC_FIMV3_DEC:
-       case S5P_FIMV_CODEC_FIMV4_DEC:
-       case S5P_FIMV_CODEC_H263_DEC:
-       case S5P_FIMV_CODEC_VC1_RCV_DEC:
-       case S5P_FIMV_CODEC_VC1_DEC:
-       case S5P_FIMV_CODEC_MPEG2_DEC:
-               bw_data = mfc_bw_info.mpeg4_dec_uhd_bw;
-               break;
-       case S5P_FIMV_CODEC_VP8_DEC:
-               bw_data = mfc_bw_info.vp8_dec_uhd_bw;
-               break;
-       case S5P_FIMV_CODEC_VP9_DEC:
-               bw_data = mfc_bw_info.vp9_dec_uhd_bw;
-               break;
-       case S5P_FIMV_CODEC_MPEG4_ENC:
-       case S5P_FIMV_CODEC_H263_ENC:
-               bw_data = mfc_bw_info.mpeg4_enc_uhd_bw;
-               break;
-       case S5P_FIMV_CODEC_VP8_ENC:
-               bw_data = mfc_bw_info.vp8_enc_uhd_bw;
-               break;
-       case S5P_FIMV_CODEC_VP9_ENC:
-               bw_data = mfc_bw_info.vp9_enc_uhd_bw;
-               break;
-       default:
-               bw_data.peak = 0;
-               bw_data.read = 0;
-               bw_data.write = 0;
-               mfc_err_ctx("[QoS] wrong codec_mode (%d)\n", ctx->codec_mode);
-       }
-
-       if (mb > (mb_count_per_uhd_frame * max_fps_per_uhd_frame)) {
-               mfc_debug(4, "[QoS] fix upper mb bound (mb: %ld, fps: %ld)\n", mb, fps);
-               mb = mb_count_per_uhd_frame * max_fps_per_uhd_frame;
-       }
-
-       peak_bw_per_sec = (bw_data.peak * mb) / mb_count_per_uhd_frame;
-       read_bw_per_sec = (bw_data.read * mb) / mb_count_per_uhd_frame;
-       write_bw_per_sec = (bw_data.write * mb) / mb_count_per_uhd_frame;
-
-       if (peak_bw_per_sec == 0) {
-               mfc_debug(4, "[QoS] fix lower peak bound (mb: %ld, fps: %ld)\n", mb, fps);
-               peak_bw_per_sec = MIN_BW_PER_SEC;
-       }
-       if (read_bw_per_sec == 0) {
-               mfc_debug(4, "[QoS] fix lower read bound (mb: %ld, fps: %ld)\n", mb, fps);
-               read_bw_per_sec = MIN_BW_PER_SEC;
-       }
-       if (write_bw_per_sec == 0) {
-               mfc_debug(4, "[QoS] fix lower write bound (mb: %ld, fps: %ld)\n", mb, fps);
-               write_bw_per_sec = MIN_BW_PER_SEC;
-       }
-
-       mfc_bw->peak = (unsigned int)peak_bw_per_sec;
-       mfc_bw->read = (unsigned int)read_bw_per_sec;
-       mfc_bw->write = (unsigned int)write_bw_per_sec;
-}
-#endif
-
-void s5p_mfc_qos_on(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_platdata *pdata = dev->pdata;
-       struct s5p_mfc_qos *qos_table = pdata->qos_table;
-       struct s5p_mfc_ctx *qos_ctx;
-       unsigned long hw_mb = 0, total_mb = 0, total_fps = 0;
-       unsigned int fw_time, sw_time;
-       int i, found = 0, enc_found = 0;
-       int start_qos_step;
-#ifdef CONFIG_EXYNOS_BTS
-       struct bts_bw mfc_bw, mfc_bw_ctx;
-#endif
-
-       if (perf_boost_mode) {
-               mfc_info_ctx("[QoS][BOOST] skip control\n");
-               return;
-       }
-
-       list_for_each_entry(qos_ctx, &dev->qos_queue, qos_list)
-               if (qos_ctx == ctx)
-                       found = 1;
-
-       if (!found)
-               list_add_tail(&ctx->qos_list, &dev->qos_queue);
-
-#ifdef CONFIG_EXYNOS_BTS
-       mfc_bw.peak = 0;
-       mfc_bw.read = 0;
-       mfc_bw.write = 0;
-#endif
-       /* get the hw macroblock */
-       list_for_each_entry(qos_ctx, &dev->qos_queue, qos_list) {
-               if (OVER_UHD_ENC60(qos_ctx))
-                       enc_found = 1;
-               hw_mb += mfc_qos_get_mb_per_second(qos_ctx);
-               total_fps += (qos_ctx->framerate / 1000);
-#ifdef CONFIG_EXYNOS_BTS
-               mfc_qos_get_bw_per_second(qos_ctx, &mfc_bw_ctx);
-               mfc_bw.peak += mfc_bw_ctx.peak;
-               mfc_bw.read += mfc_bw_ctx.read;
-               mfc_bw.write += mfc_bw_ctx.write;
-#endif
-       }
-
-       start_qos_step = pdata->num_qos_steps;
-       if (enc_found)
-               start_qos_step = pdata->max_qos_steps;
-
-       /* search the suitable qos table */
-       for (i = start_qos_step - 1; i >= 0; i--) {
-               fw_time = qos_table[i].time_fw;
-               sw_time = (MFC_DRV_TIME + fw_time);
-
-               if ((total_fps * sw_time) >= 1000000)
-                       total_mb = pdata->max_mb;
-               else
-                       total_mb = ((1000000 * hw_mb) / (1000000 - (total_fps * sw_time)));
-
-               mfc_debug(4, "[QoS] table[%d] fw_time: %dus, hw_mb: %ld, "
-                               "sw_time: %d, total_fps: %ld, total_mb: %ld\n",
-                               i, fw_time, hw_mb, sw_time, total_fps, total_mb);
-
-               if ((total_mb > qos_table[i].threshold_mb) || (i == 0))
-                       break;
-       }
-
-       if (total_mb > pdata->max_mb)
-               mfc_debug(4, "[QoS] overspec mb %ld > %d\n", total_mb, pdata->max_mb);
-
-#ifdef CONFIG_EXYNOS_BTS
-       mfc_qos_set(ctx, &mfc_bw, i);
-#else
-       mfc_qos_set(ctx, i);
-#endif
-}
-
-void s5p_mfc_qos_off(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_platdata *pdata = dev->pdata;
-       struct s5p_mfc_qos *qos_table = pdata->qos_table;
-       struct s5p_mfc_ctx *qos_ctx;
-       unsigned long hw_mb = 0, total_mb = 0, total_fps = 0;
-       unsigned int fw_time, sw_time;
-       int i, found = 0, enc_found = 0;
-       int start_qos_step;
-#ifdef CONFIG_EXYNOS_BTS
-       struct bts_bw mfc_bw, mfc_bw_ctx;
-#endif
-
-       if (perf_boost_mode) {
-               mfc_info_ctx("[QoS][BOOST] skip control\n");
-               return;
-       }
-
-       if (list_empty(&dev->qos_queue)) {
-               if (atomic_read(&dev->qos_req_cur) != 0) {
-                       mfc_err_ctx("[QoS] MFC request count is wrong!\n");
-                       mfc_qos_operate(ctx, MFC_QOS_REMOVE, 0);
-               }
-               return;
-       }
-
-#ifdef CONFIG_EXYNOS_BTS
-       mfc_bw.peak = 0;
-       mfc_bw.read = 0;
-       mfc_bw.write = 0;
-#endif
-       /* get the hw macroblock */
-       list_for_each_entry(qos_ctx, &dev->qos_queue, qos_list) {
-               if (qos_ctx == ctx) {
-                       found = 1;
-                       continue;
-               }
-
-               if (OVER_UHD_ENC60(qos_ctx))
-                       enc_found = 1;
-               hw_mb += mfc_qos_get_mb_per_second(qos_ctx);
-               total_fps += (qos_ctx->framerate / 1000);
-#ifdef CONFIG_EXYNOS_BTS
-               mfc_qos_get_bw_per_second(qos_ctx, &mfc_bw_ctx);
-               mfc_bw.peak += mfc_bw_ctx.peak;
-               mfc_bw.read += mfc_bw_ctx.read;
-               mfc_bw.write += mfc_bw_ctx.write;
-#endif
-       }
-
-       start_qos_step = pdata->num_qos_steps;
-       if (enc_found)
-               start_qos_step = pdata->max_qos_steps;
-
-       /* search the suitable qos table */
-       for (i = start_qos_step - 1; i >= 0; i--) {
-               fw_time = qos_table[i].time_fw;
-               sw_time = (MFC_DRV_TIME + fw_time);
-
-               if ((total_fps * sw_time) >= 1000000)
-                       total_mb = pdata->max_mb;
-               else
-                       total_mb = ((1000000 * hw_mb) / (1000000 - (total_fps * sw_time)));
-
-               mfc_debug(4, "[QoS] table[%d] fw_time: %dus, hw_mb: %ld, "
-                               "sw_time: %d, total_fps: %ld, total_mb: %ld\n",
-                               i, fw_time, hw_mb, sw_time, total_fps, total_mb);
-
-               if ((total_mb > qos_table[i].threshold_mb) || (total_mb == 0) || (i == 0))
-                       break;
-       }
-
-       if (total_mb > pdata->max_mb)
-               mfc_debug(4, "[QoS] overspec mb %ld > %d\n", total_mb, pdata->max_mb);
-
-       if (found)
-               list_del(&ctx->qos_list);
-
-       if (list_empty(&dev->qos_queue) || total_mb == 0)
-               mfc_qos_operate(ctx, MFC_QOS_REMOVE, 0);
-       else
-#ifdef CONFIG_EXYNOS_BTS
-               mfc_qos_set(ctx, &mfc_bw, i);
-#else
-               mfc_qos_set(ctx, i);
-#endif
-}
-#endif
-
-#define COL_FRAME_RATE         0
-#define COL_FRAME_INTERVAL     1
-
-#define MFC_MAX_INTERVAL       (2 * USEC_PER_SEC)
-
-/*
- * A framerate table determines framerate by the interval(us) of each frame.
- * Framerate is not accurate, just rough value to seperate overload section.
- * Base line of each section are selected from middle value.
- * 40fps(25000us), 80fps(12500us), 144fps(6940us)
- * 205fps(4860us), 320fps(3125us)
- *
- * interval(us) | 0         3125          4860          6940          12500         25000          |
- * framerate    |    480fps   |    240fps   |    180fps   |    120fps   |    60fps    |    30fps   |
- */
-static unsigned long framerate_table[][2] = {
-       {  30000, 25000 },
-       {  60000, 12500 },
-       { 120000,  6940 },
-       { 180000,  4860 },
-       { 240000,  3125 },
-       { 480000,     0 },
-};
-
-static inline unsigned long mfc_qos_timeval_diff(struct timeval *to,
-                                       struct timeval *from)
-{
-       return (to->tv_sec * USEC_PER_SEC + to->tv_usec)
-               - (from->tv_sec * USEC_PER_SEC + from->tv_usec);
-}
-
-static unsigned long mfc_qos_get_framerate_by_interval(int interval)
-{
-       unsigned long i;
-
-       /* if the interval is too big (2sec), framerate set to 0 */
-       if (interval > MFC_MAX_INTERVAL)
-               return 0;
-
-       for (i = 0; i < ARRAY_SIZE(framerate_table); i++) {
-               if (interval > framerate_table[i][COL_FRAME_INTERVAL])
-                       return framerate_table[i][COL_FRAME_RATE];
-       }
-
-       return 0;
-}
-
-/* Return the minimum interval between previous and next entry */
-static int mfc_qos_get_interval(struct list_head *head, struct list_head *entry)
-{
-       int prev_interval = MFC_MAX_INTERVAL, next_interval = MFC_MAX_INTERVAL;
-       struct mfc_timestamp *prev_ts, *next_ts, *curr_ts;
-
-       curr_ts = list_entry(entry, struct mfc_timestamp, list);
-
-       if (entry->prev != head) {
-               prev_ts = list_entry(entry->prev, struct mfc_timestamp, list);
-               prev_interval = mfc_qos_timeval_diff(&curr_ts->timestamp, &prev_ts->timestamp);
-       }
-
-       if (entry->next != head) {
-               next_ts = list_entry(entry->next, struct mfc_timestamp, list);
-               next_interval = mfc_qos_timeval_diff(&next_ts->timestamp, &curr_ts->timestamp);
-       }
-
-       return (prev_interval < next_interval ? prev_interval : next_interval);
-}
-
-static int mfc_qos_add_timestamp(struct s5p_mfc_ctx *ctx,
-                       struct timeval *time, struct list_head *head)
-{
-       int replace_entry = 0;
-       struct mfc_timestamp *curr_ts = &ctx->ts_array[ctx->ts_count];
-
-       if (ctx->ts_is_full) {
-               /* Replace the entry if list of array[ts_count] is same as entry */
-               if (&curr_ts->list == head)
-                       replace_entry = 1;
-               else
-                       list_del(&curr_ts->list);
-       }
-
-       memcpy(&curr_ts->timestamp, time, sizeof(struct timeval));
-       if (!replace_entry)
-               list_add(&curr_ts->list, head);
-       curr_ts->interval =
-               mfc_qos_get_interval(&ctx->ts_list, &curr_ts->list);
-       curr_ts->index = ctx->ts_count;
-       ctx->ts_count++;
-
-       if (ctx->ts_count == MFC_TIME_INDEX) {
-               ctx->ts_is_full = 1;
-               ctx->ts_count %= MFC_TIME_INDEX;
-       }
-
-       return 0;
-}
-
-static unsigned long mfc_qos_get_fps_by_timestamp(struct s5p_mfc_ctx *ctx, struct timeval *time)
-{
-       struct mfc_timestamp *temp_ts;
-       int found;
-       int index = 0;
-       int min_interval = MFC_MAX_INTERVAL;
-       int time_diff;
-       unsigned long max_framerate;
-
-       if (debug_ts == 1) {
-               /* Debug info */
-               mfc_info_ctx("===================[TS]===================\n");
-               mfc_info_ctx("[TS] New timestamp = %ld.%06ld, count = %d \n",
-                       time->tv_sec, time->tv_usec, ctx->ts_count);
-       }
-
-       if (IS_BUFFER_BATCH_MODE(ctx)) {
-               if (debug_ts == 1)
-                       mfc_info_ctx("[BUFCON][TS] Keep framerate if buffer batch mode is used, %ldfps\n",
-                                       ctx->framerate);
-               return ctx->framerate;
-       }
-
-       if (list_empty(&ctx->ts_list)) {
-               mfc_qos_add_timestamp(ctx, time, &ctx->ts_list);
-               return mfc_qos_get_framerate_by_interval(0);
-       } else {
-               found = 0;
-               list_for_each_entry_reverse(temp_ts, &ctx->ts_list, list) {
-                       time_diff = timeval_compare(time, &temp_ts->timestamp);
-                       if (time_diff == 0) {
-                               /* Do not add if same timestamp already exists */
-                               found = 1;
-                               break;
-                       } else if (time_diff > 0) {
-                               /* Add this after temp_ts */
-                               mfc_qos_add_timestamp(ctx, time, &temp_ts->list);
-                               found = 1;
-                               break;
-                       }
-               }
-
-               if (!found)     /* Add this at first entry */
-                       mfc_qos_add_timestamp(ctx, time, &ctx->ts_list);
-       }
-
-       list_for_each_entry(temp_ts, &ctx->ts_list, list) {
-               if (temp_ts->interval < min_interval)
-                       min_interval = temp_ts->interval;
-       }
-
-       max_framerate = mfc_qos_get_framerate_by_interval(min_interval);
-
-       if (debug_ts == 1) {
-               /* Debug info */
-               index = 0;
-               list_for_each_entry(temp_ts, &ctx->ts_list, list) {
-                       mfc_info_ctx("[TS] [%d] timestamp [i:%d]: %ld.%06ld\n",
-                                       index, temp_ts->index,
-                                       temp_ts->timestamp.tv_sec,
-                                       temp_ts->timestamp.tv_usec);
-                       index++;
-               }
-               mfc_info_ctx("[TS] Min interval = %d, It is %ld fps\n",
-                               min_interval, max_framerate);
-       } else if (debug_ts == 2) {
-               mfc_info_ctx("[TS] Min interval = %d, It is %ld fps\n",
-                               min_interval, max_framerate);
-       }
-
-       if (!ctx->ts_is_full) {
-               if (debug_ts == 1)
-                       mfc_info_ctx("[TS] ts doesn't full, keep %ld fps\n", ctx->framerate);
-               return ctx->framerate;
-       }
-
-       return max_framerate;
-}
-
-void s5p_mfc_qos_update_framerate(struct s5p_mfc_ctx *ctx)
-{
-       if (ctx->last_framerate != 0 && ctx->last_framerate != ctx->framerate) {
-               mfc_debug(2, "[QoS] fps changed: %ld -> %ld, qos ratio: %d\n",
-                               ctx->framerate, ctx->last_framerate, ctx->qos_ratio);
-               ctx->framerate = ctx->last_framerate;
-               s5p_mfc_qos_on(ctx);
-       }
-}
-
-void s5p_mfc_qos_update_last_framerate(struct s5p_mfc_ctx *ctx, u64 timestamp)
-{
-       struct timeval time;
-
-       time.tv_sec = timestamp / NSEC_PER_SEC;
-       time.tv_usec = (timestamp - (time.tv_sec * NSEC_PER_SEC)) / NSEC_PER_USEC;
-
-       ctx->last_framerate = mfc_qos_get_fps_by_timestamp(ctx, &time);
-       if (ctx->last_framerate > MFC_MAX_FPS)
-               ctx->last_framerate = MFC_MAX_FPS;
-       ctx->last_framerate = (ctx->qos_ratio * ctx->last_framerate) / 100;
-}
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_qos.h b/drivers/media/platform/exynos/mfc/s5p_mfc_qos.h
deleted file mode 100644 (file)
index a733a60..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_qos.h
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __S5P_MFC_QOS_H
-#define __S5P_MFC_QOS_H __FILE__
-
-#include "s5p_mfc_common.h"
-
-#define MFC_MAX_FPS                    (480000)
-#define DEC_DEFAULT_FPS                        (240000)
-#define ENC_DEFAULT_FPS                        (240000)
-#define ENC_DEFAULT_CAM_CAPTURE_FPS    (60000)
-
-#define MB_COUNT_PER_UHD_FRAME         32400
-#define MAX_FPS_PER_UHD_FRAME          120
-#define MIN_BW_PER_SEC                 1
-
-#define MFC_DRV_TIME                   500
-
-#define MFC_QOS_WEIGHT_3PLANE          80
-#define MFC_QOS_WEIGHT_OTHER_CODEC     25
-#define MFC_QOS_WEIGHT_10BIT           75
-#define MFC_QOS_WEIGHT_422_10INTRA     70
-#define MFC_QOS_WEIGHT_BFRAME          50
-#define MFC_QOS_WEIGHT_NUM_OF_REF      50
-#define MFC_QOS_WEIGHT_NUM_OF_TILE     75
-
-#ifdef CONFIG_MFC_USE_BUS_DEVFREQ
-void s5p_mfc_perf_boost_enable(struct s5p_mfc_dev *dev);
-void s5p_mfc_perf_boost_disable(struct s5p_mfc_dev *dev);
-void s5p_mfc_qos_on(struct s5p_mfc_ctx *ctx);
-void s5p_mfc_qos_off(struct s5p_mfc_ctx *ctx);
-#else
-#define s5p_mfc_perf_boost_enable(dev) do {} while (0)
-#define s5p_mfc_perf_boost_disable(dev)        do {} while (0)
-#define s5p_mfc_qos_on(ctx)            do {} while (0)
-#define s5p_mfc_qos_off(ctx)           do {} while (0)
-#endif
-
-void s5p_mfc_qos_update_framerate(struct s5p_mfc_ctx *ctx);
-void s5p_mfc_qos_update_last_framerate(struct s5p_mfc_ctx *ctx, u64 timestamp);
-
-static inline void s5p_mfc_qos_reset_framerate(struct s5p_mfc_ctx *ctx)
-{
-       if (ctx->type == MFCINST_DECODER)
-               ctx->framerate = DEC_DEFAULT_FPS;
-       else if (ctx->type == MFCINST_ENCODER)
-               ctx->framerate = ENC_DEFAULT_FPS;
-}
-
-static inline void s5p_mfc_qos_reset_last_framerate(struct s5p_mfc_ctx *ctx)
-{
-       ctx->last_framerate = 0;
-}
-
-static inline void s5p_mfc_qos_set_framerate(struct s5p_mfc_ctx *ctx, int rate)
-{
-       ctx->framerate = rate;
-}
-
-static inline int s5p_mfc_qos_get_framerate(struct s5p_mfc_ctx *ctx)
-{
-       return ctx->framerate;
-}
-
-#endif /* __S5P_MFC_QOS_H */
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_queue.c b/drivers/media/platform/exynos/mfc/s5p_mfc_queue.c
deleted file mode 100644 (file)
index ccae643..0000000
+++ /dev/null
@@ -1,1066 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_queue.c
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include "s5p_mfc_queue.h"
-
-#include "s5p_mfc_utils.h"
-#include "s5p_mfc_mem.h"
-
-void s5p_mfc_add_tail_buf(spinlock_t *plock, struct s5p_mfc_buf_queue *queue,
-               struct s5p_mfc_buf *mfc_buf)
-{
-       unsigned long flags;
-
-       if (!mfc_buf) {
-               mfc_err_dev("mfc_buf is NULL!\n");
-               return;
-       }
-
-       spin_lock_irqsave(plock, flags);
-
-       mfc_buf->used = 0;
-       list_add_tail(&mfc_buf->list, &queue->head);
-       queue->count++;
-
-       spin_unlock_irqrestore(plock, flags);
-}
-
-int s5p_mfc_peek_buf_csd(spinlock_t *plock, struct s5p_mfc_buf_queue *queue)
-{
-       unsigned long flags;
-       int csd = -1;
-       struct s5p_mfc_buf *mfc_buf = NULL;
-
-       spin_lock_irqsave(plock, flags);
-
-       if (list_empty(&queue->head)) {
-               mfc_debug(2, "queue is empty\n");
-               spin_unlock_irqrestore(plock, flags);
-               return csd;
-       }
-
-       mfc_buf = list_entry(queue->head.next, struct s5p_mfc_buf, list);
-
-       csd = mfc_buf->vb.reserved2 & FLAG_CSD ? 1 : 0;
-
-       mfc_debug(2, "addr[0]: 0x%08llx\n", mfc_buf->addr[0][0]);
-
-       spin_unlock_irqrestore(plock, flags);
-       return csd;
-}
-
-struct s5p_mfc_buf *s5p_mfc_get_buf(spinlock_t *plock, struct s5p_mfc_buf_queue *queue,
-               enum s5p_mfc_queue_used_type used)
-{
-       unsigned long flags;
-       struct s5p_mfc_buf *mfc_buf = NULL;
-
-       spin_lock_irqsave(plock, flags);
-
-       if (list_empty(&queue->head)) {
-               mfc_debug(2, "queue is empty\n");
-               spin_unlock_irqrestore(plock, flags);
-               return NULL;
-       }
-
-       mfc_buf = list_entry(queue->head.next, struct s5p_mfc_buf, list);
-
-       if ((used == MFC_BUF_RESET_USED) || (used == MFC_BUF_SET_USED))
-               mfc_buf->used = used;
-
-       mfc_debug(2, "addr[0]: 0x%08llx\n", mfc_buf->addr[0][0]);
-
-       spin_unlock_irqrestore(plock, flags);
-       return mfc_buf;
-}
-
-struct s5p_mfc_buf *s5p_mfc_get_del_buf(spinlock_t *plock, struct s5p_mfc_buf_queue *queue,
-               enum s5p_mfc_queue_used_type used)
-{
-       unsigned long flags;
-       struct s5p_mfc_buf *mfc_buf = NULL;
-
-       spin_lock_irqsave(plock, flags);
-
-       if (list_empty(&queue->head)) {
-               mfc_debug(2, "queue is empty\n");
-               spin_unlock_irqrestore(plock, flags);
-               return NULL;
-       }
-
-       mfc_buf = list_entry(queue->head.next, struct s5p_mfc_buf, list);
-
-       if ((used == MFC_BUF_RESET_USED) || (used == MFC_BUF_SET_USED))
-               mfc_buf->used = used;
-
-       mfc_debug(2, "addr[0]: 0x%08llx\n", mfc_buf->addr[0][0]);
-
-       list_del(&mfc_buf->list);
-       queue->count--;
-
-       spin_unlock_irqrestore(plock, flags);
-       return mfc_buf;
-}
-
-struct s5p_mfc_buf *s5p_mfc_get_del_if_consumed(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf_queue *queue,
-               unsigned long consumed, unsigned int min_bytes, int error, int *deleted)
-{
-       unsigned long flags;
-       struct s5p_mfc_buf *mfc_buf = NULL;
-       struct s5p_mfc_dec *dec = ctx->dec_priv;
-       unsigned long remained;
-
-       spin_lock_irqsave(&ctx->buf_queue_lock, flags);
-
-       if (list_empty(&queue->head)) {
-               mfc_debug(2, "queue is empty\n");
-               spin_unlock_irqrestore(&ctx->buf_queue_lock, flags);
-               return NULL;
-       }
-
-       mfc_buf = list_entry(queue->head.next, struct s5p_mfc_buf, list);
-
-       mfc_debug(2, "addr[0]: 0x%08llx\n", mfc_buf->addr[0][0]);
-
-       if (dec->remained_size)
-               remained = dec->remained_size - consumed;
-       else
-               remained = mfc_buf->vb.vb2_buf.planes[0].bytesused - consumed;
-
-       mfc_debug(2, "[MULTIFRAME] Total Size: %d, consumed: %ld, remained: %ld\n",
-               mfc_buf->vb.vb2_buf.planes[0].bytesused, consumed, remained);
-
-       if ((consumed > 0) && (remained > min_bytes) && (error == 0) &&
-                       (mfc_buf->vb.vb2_buf.planes[0].bytesused > consumed)){
-               /* do not delete from queue */
-               *deleted = 0;
-       } else {
-               list_del(&mfc_buf->list);
-               queue->count--;
-
-               *deleted = 1;
-       }
-
-       spin_unlock_irqrestore(&ctx->buf_queue_lock, flags);
-       return mfc_buf;
-}
-
-struct s5p_mfc_buf *s5p_mfc_get_move_buf(spinlock_t *plock,
-               struct s5p_mfc_buf_queue *to_queue, struct s5p_mfc_buf_queue *from_queue,
-               enum s5p_mfc_queue_used_type used, enum s5p_mfc_queue_top_type top)
-{
-       unsigned long flags;
-       struct s5p_mfc_buf *mfc_buf = NULL;
-
-       spin_lock_irqsave(plock, flags);
-
-       if (list_empty(&from_queue->head)) {
-               mfc_debug(2, "from_queue is empty\n");
-               spin_unlock_irqrestore(plock, flags);
-               return NULL;
-       }
-
-       mfc_buf = list_entry(from_queue->head.next, struct s5p_mfc_buf, list);
-
-       if ((used == MFC_BUF_RESET_USED) || (used == MFC_BUF_SET_USED))
-               mfc_buf->used = used;
-
-       mfc_debug(2, "addr[0]: 0x%08llx\n", mfc_buf->addr[0][0]);
-
-       list_del(&mfc_buf->list);
-       from_queue->count--;
-
-       if (top == MFC_QUEUE_ADD_TOP)
-               list_add(&mfc_buf->list, &to_queue->head);
-       else
-               list_add_tail(&mfc_buf->list, &to_queue->head);
-
-       to_queue->count++;
-
-       spin_unlock_irqrestore(plock, flags);
-       return mfc_buf;
-}
-
-struct s5p_mfc_buf *s5p_mfc_get_move_buf_used(spinlock_t *plock,
-               struct s5p_mfc_buf_queue *to_queue, struct s5p_mfc_buf_queue *from_queue)
-{
-       unsigned long flags;
-       struct s5p_mfc_buf *mfc_buf = NULL;
-
-       spin_lock_irqsave(plock, flags);
-
-       if (list_empty(&from_queue->head)) {
-               mfc_debug(2, "from_queue is empty\n");
-               spin_unlock_irqrestore(plock, flags);
-               return NULL;
-       }
-
-       mfc_buf = list_entry(from_queue->head.next, struct s5p_mfc_buf, list);
-
-       if (mfc_buf->used) {
-               mfc_debug(2, "addr[0]: 0x%08llx\n", mfc_buf->addr[0][0]);
-
-               list_del(&mfc_buf->list);
-               from_queue->count--;
-
-               list_add_tail(&mfc_buf->list, &to_queue->head);
-               to_queue->count++;
-
-               spin_unlock_irqrestore(plock, flags);
-               return mfc_buf;
-       } else {
-               spin_unlock_irqrestore(plock, flags);
-               return NULL;
-       }
-}
-
-struct s5p_mfc_buf *s5p_mfc_get_move_buf_addr(spinlock_t *plock,
-               struct s5p_mfc_buf_queue *to_queue, struct s5p_mfc_buf_queue *from_queue,
-               dma_addr_t addr)
-{
-       unsigned long flags;
-       struct s5p_mfc_buf *mfc_buf = NULL;
-
-       spin_lock_irqsave(plock, flags);
-
-       if (list_empty(&from_queue->head)) {
-               mfc_debug(2, "[DPB] from_queue is empty\n");
-               spin_unlock_irqrestore(plock, flags);
-               return NULL;
-       }
-
-       mfc_buf = list_entry(from_queue->head.next, struct s5p_mfc_buf, list);
-
-       if (mfc_buf->addr[0][0] == addr) {
-               mfc_debug(2, "[DPB] addr[0]: 0x%08llx\n", mfc_buf->addr[0][0]);
-
-               list_del(&mfc_buf->list);
-               from_queue->count--;
-
-               list_add_tail(&mfc_buf->list, &to_queue->head);
-               to_queue->count++;
-
-               spin_unlock_irqrestore(plock, flags);
-               return mfc_buf;
-       } else {
-               spin_unlock_irqrestore(plock, flags);
-               return NULL;
-       }
-}
-
-struct s5p_mfc_buf *s5p_mfc_find_first_buf(spinlock_t *plock, struct s5p_mfc_buf_queue *queue,
-               dma_addr_t addr)
-{
-       unsigned long flags;
-       struct s5p_mfc_buf *mfc_buf = NULL;
-       dma_addr_t mb_addr;
-       int i;
-
-       spin_lock_irqsave(plock, flags);
-
-       if (list_empty(&queue->head)) {
-               mfc_debug(2, "queue is empty\n");
-               spin_unlock_irqrestore(plock, flags);
-               return mfc_buf;
-       }
-
-       mfc_debug(4, "Looking for this address: 0x%08llx\n", addr);
-       mfc_buf = list_entry(queue->head.next, struct s5p_mfc_buf, list);
-       if (mfc_buf->num_valid_bufs > 0) {
-               for (i = 0; i < mfc_buf->num_valid_bufs; i++) {
-                       mb_addr = mfc_buf->addr[i][0];
-                       mfc_debug(4, "[BUFCON] batch[%d] addr[0]: 0x%08llx\n", i, mb_addr);
-                       if (addr == mb_addr) {
-                               spin_unlock_irqrestore(plock, flags);
-                               return mfc_buf;
-                       }
-               }
-       } else {
-               mb_addr = mfc_buf->addr[0][0];
-               mfc_debug(4, "addr[0]: 0x%08llx\n", mb_addr);
-
-               if (addr == mb_addr) {
-                       spin_unlock_irqrestore(plock, flags);
-                       return mfc_buf;
-               }
-       }
-
-       spin_unlock_irqrestore(plock, flags);
-       return NULL;
-}
-
-struct s5p_mfc_buf *s5p_mfc_find_buf(spinlock_t *plock, struct s5p_mfc_buf_queue *queue,
-               dma_addr_t addr)
-{
-       unsigned long flags;
-       struct s5p_mfc_buf *mfc_buf = NULL;
-       dma_addr_t mb_addr;
-       int i;
-
-       spin_lock_irqsave(plock, flags);
-
-       mfc_debug(4, "Looking for this address: 0x%08llx\n", addr);
-       list_for_each_entry(mfc_buf, &queue->head, list) {
-               if (mfc_buf->num_valid_bufs > 0) {
-                       for (i = 0; i < mfc_buf->num_valid_bufs; i++) {
-                               mb_addr = mfc_buf->addr[i][0];
-                               mfc_debug(4, "[BUFCON] batch[%d] addr[0]: 0x%08llx\n", i, mb_addr);
-                               if (addr == mb_addr) {
-                                       spin_unlock_irqrestore(plock, flags);
-                                       return mfc_buf;
-                               }
-                       }
-               } else {
-                       mb_addr = mfc_buf->addr[0][0];
-                       mfc_debug(4, "addr[0]: 0x%08llx\n", mb_addr);
-
-                       if (addr == mb_addr) {
-                               spin_unlock_irqrestore(plock, flags);
-                               return mfc_buf;
-                       }
-               }
-       }
-
-       spin_unlock_irqrestore(plock, flags);
-       return NULL;
-}
-
-struct s5p_mfc_buf *s5p_mfc_find_del_buf(spinlock_t *plock, struct s5p_mfc_buf_queue *queue,
-               dma_addr_t addr)
-{
-       unsigned long flags;
-       struct s5p_mfc_buf *mfc_buf = NULL;
-       dma_addr_t mb_addr;
-       int found = 0, i;
-
-       spin_lock_irqsave(plock, flags);
-
-       mfc_debug(4, "Looking for this address: 0x%08llx\n", addr);
-       list_for_each_entry(mfc_buf, &queue->head, list) {
-               if (mfc_buf->num_valid_bufs > 0) {
-                       for (i = 0; i < mfc_buf->num_valid_bufs; i++) {
-                               mb_addr = mfc_buf->addr[i][0];
-                               mfc_debug(4, "batch buf[%d] plane[0] addr: 0x%08llx\n", i, mb_addr);
-
-                               if (addr == mb_addr) {
-                                       found = 1;
-                                       break;
-                               }
-                       }
-
-                       if (found)
-                               break;
-               } else {
-                       mb_addr = mfc_buf->addr[0][0];
-                       mfc_debug(4, "addr[0]: 0x%08llx\n", mb_addr);
-
-                       if (addr == mb_addr) {
-                               found = 1;
-                               break;
-                       }
-               }
-       }
-
-       if (found == 1) {
-               list_del(&mfc_buf->list);
-               queue->count--;
-
-               spin_unlock_irqrestore(plock, flags);
-               return mfc_buf;
-       } else {
-               spin_unlock_irqrestore(plock, flags);
-               return NULL;
-       }
-}
-
-struct s5p_mfc_buf *s5p_mfc_find_move_buf(spinlock_t *plock,
-               struct s5p_mfc_buf_queue *to_queue, struct s5p_mfc_buf_queue *from_queue,
-               dma_addr_t addr, unsigned int released_flag)
-{
-       unsigned long flags;
-       struct s5p_mfc_buf *mfc_buf = NULL;
-       dma_addr_t mb_addr;
-       int found = 0;
-
-       spin_lock_irqsave(plock, flags);
-
-       mfc_debug(4, "[DPB] Looking for this address: 0x%08llx\n", addr);
-       list_for_each_entry(mfc_buf, &from_queue->head, list) {
-               mb_addr = mfc_buf->addr[0][0];
-               mfc_debug(4, "[DPB] addr[0]: 0x%08llx\n", mb_addr);
-
-               if (addr == mb_addr) {
-                       found = 1;
-                       break;
-               }
-       }
-
-       if (found == 1) {
-               if (released_flag & (1 << mfc_buf->vb.vb2_buf.index)) {
-                       list_del(&mfc_buf->list);
-                       from_queue->count--;
-
-                       list_add_tail(&mfc_buf->list, &to_queue->head);
-                       to_queue->count++;
-               }
-
-               spin_unlock_irqrestore(plock, flags);
-               return mfc_buf;
-       } else {
-               spin_unlock_irqrestore(plock, flags);
-               return NULL;
-       }
-}
-
-struct s5p_mfc_buf *s5p_mfc_find_move_buf_used(spinlock_t *plock,
-               struct s5p_mfc_buf_queue *to_queue, struct s5p_mfc_buf_queue *from_queue,
-               dma_addr_t addr)
-{
-       unsigned long flags;
-       struct s5p_mfc_buf *mfc_buf = NULL;
-       dma_addr_t mb_addr;
-       int found = 0;
-
-       spin_lock_irqsave(plock, flags);
-
-       mfc_debug(4, "[DPB] Looking for this address: 0x%08llx\n", addr);
-       list_for_each_entry(mfc_buf, &from_queue->head, list) {
-               mb_addr = mfc_buf->addr[0][0];
-               mfc_debug(4, "[DPB] addr[0]: 0x%08llx, used: %d\n",
-                               mb_addr, mfc_buf->used);
-
-               if ((addr == mb_addr) && (mfc_buf->used == 1)) {
-                       found = 1;
-                       break;
-               }
-       }
-
-       if (found == 1) {
-               list_del(&mfc_buf->list);
-               from_queue->count--;
-
-               list_add_tail(&mfc_buf->list, &to_queue->head);
-               to_queue->count++;
-
-               spin_unlock_irqrestore(plock, flags);
-               return mfc_buf;
-       } else {
-               spin_unlock_irqrestore(plock, flags);
-               return NULL;
-       }
-}
-
-void s5p_mfc_move_first_buf_used(spinlock_t *plock, struct s5p_mfc_buf_queue *to_queue,
-               struct s5p_mfc_buf_queue *from_queue, enum s5p_mfc_queue_top_type top)
-{
-       unsigned long flags;
-       struct s5p_mfc_buf *mfc_buf = NULL;
-
-       spin_lock_irqsave(plock, flags);
-
-       if (list_empty(&from_queue->head)) {
-               mfc_err_dev("from_queue is empty\n");
-               spin_unlock_irqrestore(plock, flags);
-               return;
-       }
-       mfc_buf = list_entry(from_queue->head.next, struct s5p_mfc_buf, list);
-
-       if (mfc_buf->used) {
-               list_del(&mfc_buf->list);
-               from_queue->count--;
-
-               if (top == MFC_QUEUE_ADD_TOP)
-                       list_add(&mfc_buf->list, &to_queue->head);
-               else
-                       list_add_tail(&mfc_buf->list, &to_queue->head);
-
-               to_queue->count++;
-       }
-
-       spin_unlock_irqrestore(plock, flags);
-}
-
-void s5p_mfc_move_all_bufs(spinlock_t *plock, struct s5p_mfc_buf_queue *to_queue,
-               struct s5p_mfc_buf_queue *from_queue, enum s5p_mfc_queue_top_type top)
-{
-       unsigned long flags;
-       struct s5p_mfc_buf *mfc_buf = NULL;
-
-       spin_lock_irqsave(plock, flags);
-
-       if (top == MFC_QUEUE_ADD_TOP) {
-               while (!list_empty(&from_queue->head)) {
-                       mfc_buf = list_entry(from_queue->head.prev, struct s5p_mfc_buf, list);
-
-                       list_del(&mfc_buf->list);
-                       from_queue->count--;
-
-                       list_add(&mfc_buf->list, &to_queue->head);
-                       to_queue->count++;
-               }
-       } else {
-               while (!list_empty(&from_queue->head)) {
-                       mfc_buf = list_entry(from_queue->head.next, struct s5p_mfc_buf, list);
-
-                       list_del(&mfc_buf->list);
-                       from_queue->count--;
-
-                       list_add_tail(&mfc_buf->list, &to_queue->head);
-                       to_queue->count++;
-               }
-       }
-
-       INIT_LIST_HEAD(&from_queue->head);
-       from_queue->count = 0;
-
-       spin_unlock_irqrestore(plock, flags);
-}
-
-void s5p_mfc_cleanup_queue(spinlock_t *plock, struct s5p_mfc_buf_queue *queue)
-{
-       unsigned long flags;
-       struct s5p_mfc_buf *mfc_buf = NULL;
-       int i;
-
-       spin_lock_irqsave(plock, flags);
-
-       while (!list_empty(&queue->head)) {
-               mfc_buf = list_entry(queue->head.next, struct s5p_mfc_buf, list);
-
-               for (i = 0; i < mfc_buf->vb.vb2_buf.num_planes; i++)
-                       vb2_set_plane_payload(&mfc_buf->vb.vb2_buf, i, 0);
-               vb2_buffer_done(&mfc_buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
-               list_del(&mfc_buf->list);
-               queue->count--;
-       }
-
-       INIT_LIST_HEAD(&queue->head);
-       queue->count = 0;
-
-       spin_unlock_irqrestore(plock, flags);
-}
-
-static void mfc_cleanup_batch_queue(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf_queue *queue)
-{
-       unsigned long flags;
-       struct s5p_mfc_buf *mfc_buf = NULL;
-       int i;
-
-       spin_lock_irqsave(&ctx->buf_queue_lock, flags);
-
-       while (!list_empty(&queue->head)) {
-               mfc_buf = list_entry(queue->head.next, struct s5p_mfc_buf, list);
-
-               for (i = 0; i < mfc_buf->vb.vb2_buf.num_planes; i++) {
-                       s5p_mfc_bufcon_put_daddr(ctx, mfc_buf, i);
-                       vb2_set_plane_payload(&mfc_buf->vb.vb2_buf, i, 0);
-               }
-               vb2_buffer_done(&mfc_buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
-               list_del(&mfc_buf->list);
-               queue->count--;
-       }
-
-       INIT_LIST_HEAD(&queue->head);
-       queue->count = 0;
-       ctx->batch_mode = 0;
-
-       spin_unlock_irqrestore(&ctx->buf_queue_lock, flags);
-}
-
-struct s5p_mfc_buf *mfc_find_buf_index(spinlock_t *plock, struct s5p_mfc_buf_queue *queue,
-               int index)
-{
-       unsigned long flags;
-       struct s5p_mfc_buf *mfc_buf = NULL;
-       int buf_index;
-
-       spin_lock_irqsave(plock, flags);
-
-       mfc_debug(4, "[DPB] Looking for index: %d\n", index);
-       list_for_each_entry(mfc_buf, &queue->head, list) {
-               buf_index = mfc_buf->vb.vb2_buf.index;
-
-               if (index == buf_index) {
-                       mfc_debug(2, "[DPB] Found index: %d\n", buf_index);
-                       spin_unlock_irqrestore(plock, flags);
-                       return mfc_buf;
-               }
-       }
-
-       spin_unlock_irqrestore(plock, flags);
-       return NULL;
-}
-
-/*
- * Check released and enqueued buffers. (dst queue)
- * Check and move reuse buffers. (ref -> dst queue)
- */
-static void mfc_check_ref_frame(spinlock_t *plock, struct s5p_mfc_buf_queue *dst_queue,
-               struct s5p_mfc_buf_queue *ref_queue,
-               struct s5p_mfc_ctx *ctx, int ref_index)
-{
-       unsigned long flags;
-       struct s5p_mfc_dec *dec = ctx->dec_priv;
-       struct s5p_mfc_buf *ref_mb, *tmp_mb;
-       int index;
-       int found = 0;
-
-       spin_lock_irqsave(plock, flags);
-
-       /* reuse buffers : error frame, decoding only frame (ref -> dst queue) */
-       list_for_each_entry_safe(ref_mb, tmp_mb, &ref_queue->head, list) {
-               index = ref_mb->vb.vb2_buf.index;
-               if (index == ref_index) {
-                       list_del(&ref_mb->list);
-                       ref_queue->count--;
-
-                       list_add_tail(&ref_mb->list, &dst_queue->head);
-                       dst_queue->count++;
-
-                       dec->assigned_fd[index] =
-                                       ref_mb->vb.vb2_buf.planes[0].m.fd;
-                       clear_bit(index, &dec->available_dpb);
-                       mfc_debug(2, "[DPB] Move buffer[%d], fd[%d] to dst queue\n",
-                                       index, dec->assigned_fd[index]);
-                       found = 1;
-                       break;
-               }
-       }
-
-       /* released and enqueued buffers (dst queue) */
-       if (!found) {
-               list_for_each_entry_safe(ref_mb, tmp_mb, &dst_queue->head, list) {
-                       index = ref_mb->vb.vb2_buf.index;
-                       if (index == ref_index) {
-                               dec->assigned_fd[index] =
-                                       ref_mb->vb.vb2_buf.planes[0].m.fd;
-                               clear_bit(index, &dec->available_dpb);
-                               mfc_debug(2, "[DPB] re-assigned buffer[%d], fd[%d]\n",
-                                               index, dec->assigned_fd[index]);
-                               break;
-                       }
-               }
-       }
-
-       spin_unlock_irqrestore(plock, flags);
-}
-
-/* Process the released reference information */
-void s5p_mfc_handle_released_info(struct s5p_mfc_ctx *ctx,
-               unsigned int released_flag, int index)
-{
-       struct s5p_mfc_dec *dec;
-       struct dec_dpb_ref_info *refBuf;
-       int t, ncount = 0;
-
-       dec = ctx->dec_priv;
-       if (!dec) {
-               mfc_err_dev("[DPB] no decoder context to run\n");
-               return;
-       }
-       refBuf = &dec->ref_info[index];
-
-       if (dec->dec_only_release_flag) {
-               for (t = 0; t < MFC_MAX_DPBS; t++) {
-                       if (dec->dec_only_release_flag & (1 << t)) {
-                               mfc_debug(2, "[DPB] Release FD[%d] = %03d (already released in dec only)\n",
-                                               t, dec->assigned_fd[t]);
-                               refBuf->dpb[ncount].fd[0] = dec->assigned_fd[t];
-                               ncount++;
-                               dec->dec_only_release_flag &= ~(1 << t);
-                       }
-               }
-       }
-
-       if (released_flag) {
-               for (t = 0; t < MFC_MAX_DPBS; t++) {
-                       if (released_flag & (1 << t)) {
-                               if (dec->err_reuse_flag & (1 << t)) {
-                                       /* reuse buffer with error : do not update released info */
-                                       mfc_debug(2, "[DPB] Released, but reuse(error frame). FD[%d] = %03d\n",
-                                                       t, dec->assigned_fd[t]);
-                                       dec->err_reuse_flag &= ~(1 << t);
-                               } else if ((t != index) &&
-                                               mfc_find_buf_index(&ctx->buf_queue_lock, &ctx->ref_buf_queue, t)) {
-                                       /* decoding only frame: do not update released info */
-                                       mfc_debug(2, "[DPB] Released, but reuse(decoding only). FD[%d] = %03d\n",
-                                                       t, dec->assigned_fd[t]);
-                               } else {
-                                       /* displayed and released frame */
-                                       mfc_debug(2, "[DPB] Release FD[%d] = %03d\n",
-                                                       t, dec->assigned_fd[t]);
-                                       refBuf->dpb[ncount].fd[0] = dec->assigned_fd[t];
-                                       ncount++;
-                               }
-                               dec->assigned_fd[t] = MFC_INFO_INIT_FD;
-                               mfc_check_ref_frame(&ctx->buf_queue_lock, &ctx->dst_buf_queue,
-                                               &ctx->ref_buf_queue, ctx, t);
-                       }
-               }
-       }
-
-       if (ncount != MFC_MAX_DPBS)
-               refBuf->dpb[ncount].fd[0] = MFC_INFO_INIT_FD;
-}
-
-struct s5p_mfc_buf *s5p_mfc_move_reuse_buffer(struct s5p_mfc_ctx *ctx, int release_index)
-{
-       struct s5p_mfc_dec *dec = ctx->dec_priv;
-       struct s5p_mfc_buf_queue *dst_queue = &ctx->dst_buf_queue;
-       struct s5p_mfc_buf_queue *ref_queue = &ctx->ref_buf_queue;
-       struct s5p_mfc_buf *ref_mb, *tmp_mb;
-       spinlock_t *plock = &ctx->buf_queue_lock;
-       unsigned long flags;
-       int index;
-
-       spin_lock_irqsave(plock, flags);
-
-       list_for_each_entry_safe(ref_mb, tmp_mb, &ref_queue->head, list) {
-               index = ref_mb->vb.vb2_buf.index;
-               if (index == release_index) {
-                       s5p_mfc_raw_unprotect(ctx, ref_mb, index);
-
-                       ref_mb->used = 0;
-
-                       list_del(&ref_mb->list);
-                       ref_queue->count--;
-
-                       list_add_tail(&ref_mb->list, &dst_queue->head);
-                       dst_queue->count++;
-
-                       clear_bit(index, &dec->available_dpb);
-                       mfc_debug(2, "[DPB] buffer[%d] is moved to dst queue for reuse\n", index);
-
-                       spin_unlock_irqrestore(plock, flags);
-                       return ref_mb;
-               }
-       }
-
-       spin_unlock_irqrestore(plock, flags);
-       return NULL;
-}
-
-void s5p_mfc_cleanup_enc_src_queue(struct s5p_mfc_ctx *ctx)
-{
-       unsigned long flags;
-       struct s5p_mfc_buf *src_mb, *tmp_mb;
-       int i;
-
-       if (ctx->is_drm && ctx->raw_protect_flag) {
-               spin_lock_irqsave(&ctx->buf_queue_lock, flags);
-
-               mfc_debug(2, "raw_protect_flag(%#lx) will be released\n",
-                               ctx->raw_protect_flag);
-
-               list_for_each_entry_safe(src_mb, tmp_mb, &ctx->src_buf_queue.head, list) {
-                       i = src_mb->vb.vb2_buf.index;
-
-                       s5p_mfc_raw_unprotect(ctx, src_mb, i);
-
-                       for (i = 0; i < src_mb->vb.vb2_buf.num_planes; i++) {
-                               s5p_mfc_bufcon_put_daddr(ctx, src_mb, i);
-                               vb2_set_plane_payload(&src_mb->vb.vb2_buf, i, 0);
-                       }
-
-                       vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_ERROR);
-                       list_del(&src_mb->list);
-                       ctx->src_buf_queue.count--;
-               }
-
-               INIT_LIST_HEAD(&ctx->src_buf_queue.head);
-               ctx->src_buf_queue.count = 0;
-
-               spin_unlock_irqrestore(&ctx->buf_queue_lock, flags);
-       } else {
-               if (IS_BUFFER_BATCH_MODE(ctx))
-                       mfc_cleanup_batch_queue(ctx, &ctx->src_buf_queue);
-               else
-                       s5p_mfc_cleanup_queue(&ctx->buf_queue_lock, &ctx->src_buf_queue);
-       }
-}
-
-
-void s5p_mfc_cleanup_enc_dst_queue(struct s5p_mfc_ctx *ctx)
-{
-       unsigned long flags;
-       struct s5p_mfc_buf *dst_mb, *tmp_mb;
-       int i;
-
-       if (ctx->is_drm && ctx->stream_protect_flag) {
-               spin_lock_irqsave(&ctx->buf_queue_lock, flags);
-
-               mfc_debug(2, "stream_protect_flag(%#lx) will be released\n",
-                               ctx->stream_protect_flag);
-
-               list_for_each_entry_safe(dst_mb, tmp_mb, &ctx->dst_buf_queue.head, list) {
-                       i = dst_mb->vb.vb2_buf.index;
-
-                       s5p_mfc_stream_unprotect(ctx, dst_mb, i);
-
-                       for (i = 0; i < dst_mb->vb.vb2_buf.num_planes; i++)
-                               vb2_set_plane_payload(&dst_mb->vb.vb2_buf, i, 0);
-                       vb2_buffer_done(&dst_mb->vb.vb2_buf, VB2_BUF_STATE_ERROR);
-                       list_del(&dst_mb->list);
-                       ctx->dst_buf_queue.count--;
-               }
-
-               INIT_LIST_HEAD(&ctx->dst_buf_queue.head);
-               ctx->dst_buf_queue.count = 0;
-
-               spin_unlock_irqrestore(&ctx->buf_queue_lock, flags);
-       } else {
-               s5p_mfc_cleanup_queue(&ctx->buf_queue_lock, &ctx->dst_buf_queue);
-       }
-}
-
-/* Check all buffers are referenced or not */
-struct s5p_mfc_buf *mfc_check_full_refered_dpb(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dec *dec = NULL;
-       struct s5p_mfc_buf *mfc_buf = NULL;
-       int sum_dpb;
-
-       dec = ctx->dec_priv;
-       if (!dec) {
-               mfc_err_dev("[DPB] no decoder context to run\n");
-               return NULL;
-       }
-
-       sum_dpb = ctx->dst_buf_queue.count + ctx->ref_buf_queue.count;
-
-       if ((ctx->dst_buf_queue.count > 1) && (sum_dpb >= (ctx->dpb_count + 5))) {
-               if (list_empty(&ctx->dst_buf_queue.head)) {
-                       mfc_err_ctx("[DPB] dst_buf_queue is empty\n");
-                       return NULL;
-               }
-               mfc_debug(3, "[DPB] We should use this buffer\n");
-               mfc_buf = list_entry(ctx->dst_buf_queue.head.next,
-                               struct s5p_mfc_buf, list);
-       } else if ((ctx->dst_buf_queue.count == 0)
-                       && ((ctx->ref_buf_queue.count) == (ctx->dpb_count + 5))) {
-               if (list_empty(&ctx->ref_buf_queue.head)) {
-                       mfc_err_ctx("[DPB] ref_buf_queue is empty\n");
-                       return NULL;
-               }
-               mfc_debug(3, "[DPB] All buffers are referenced\n");
-               mfc_buf = list_entry(ctx->ref_buf_queue.head.next,
-                               struct s5p_mfc_buf, list);
-       } else {
-               mfc_debug(3, "[DPB] waiting for dst buffer, ref = %d, dst = %d\n",
-                               ctx->ref_buf_queue.count, ctx->dst_buf_queue.count);
-               ctx->clear_work_bit = 1;
-       }
-
-       if (mfc_buf)
-               mfc_buf->used = 1;
-
-       return mfc_buf;
-}
-
-/* Try to search non-referenced DPB on dst-queue */
-struct s5p_mfc_buf *s5p_mfc_search_for_dpb(struct s5p_mfc_ctx *ctx, unsigned int dynamic_used)
-{
-       unsigned long flags;
-       struct s5p_mfc_buf *mfc_buf = NULL;
-
-       spin_lock_irqsave(&ctx->buf_queue_lock, flags);
-
-       mfc_debug(2, "[DPB] Try to find non-referenced DPB. dynamic_used: 0x%x\n", dynamic_used);
-       list_for_each_entry(mfc_buf, &ctx->dst_buf_queue.head, list) {
-               if ((dynamic_used & (1 << mfc_buf->vb.vb2_buf.index)) == 0) {
-                       mfc_buf->used = 1;
-                       spin_unlock_irqrestore(&ctx->buf_queue_lock, flags);
-                       return mfc_buf;
-               }
-       }
-
-       mfc_buf = mfc_check_full_refered_dpb(ctx);
-
-       spin_unlock_irqrestore(&ctx->buf_queue_lock, flags);
-
-       return mfc_buf;
-}
-
-struct s5p_mfc_buf *s5p_mfc_search_move_dpb_nal_q(struct s5p_mfc_ctx *ctx, unsigned int dynamic_used)
-{
-       unsigned long flags;
-       struct s5p_mfc_buf *mfc_buf = NULL;
-       struct s5p_mfc_dec *dec = NULL;
-
-       dec = ctx->dec_priv;
-       if (!dec) {
-               mfc_err_dev("no mfc decoder to run\n");
-               return mfc_buf;
-       }
-
-       spin_lock_irqsave(&ctx->buf_queue_lock, flags);
-
-       mfc_debug(2, "[NALQ][DPB] Try to find non-referenced DPB. dynamic_used: 0x%x\n", dynamic_used);
-       list_for_each_entry(mfc_buf, &ctx->dst_buf_queue.head, list) {
-               if ((dynamic_used & (1 << mfc_buf->vb.vb2_buf.index)) == 0) {
-                       mfc_buf->used = 1;
-
-                       list_del(&mfc_buf->list);
-                       ctx->dst_buf_queue.count--;
-
-                       list_add_tail(&mfc_buf->list, &ctx->dst_buf_nal_queue.head);
-                       ctx->dst_buf_nal_queue.count++;
-
-                       spin_unlock_irqrestore(&ctx->buf_queue_lock, flags);
-                       return mfc_buf;
-               }
-       }
-
-       mfc_buf = mfc_check_full_refered_dpb(ctx);
-
-       if (mfc_buf) {
-               mfc_debug(2, "[NALQ][DPB] DPB is full. stop NAL-Q if started\n");
-               dec->is_dpb_full = 1;
-       }
-
-       spin_unlock_irqrestore(&ctx->buf_queue_lock, flags);
-
-       return mfc_buf;
-}
-
-/* Add dst buffer in dst_buf_queue */
-void s5p_mfc_store_dpb(struct s5p_mfc_ctx *ctx, struct vb2_buffer *vb)
-{
-       unsigned long flags;
-       struct s5p_mfc_dec *dec;
-       struct s5p_mfc_buf *mfc_buf;
-       int index;
-
-       if (!ctx) {
-               mfc_err_dev("[DPB] no mfc context to run\n");
-               return;
-       }
-
-       dec = ctx->dec_priv;
-       if (!dec) {
-               mfc_err_dev("[DPB] no mfc decoder to run\n");
-               return;
-       }
-
-       spin_lock_irqsave(&ctx->buf_queue_lock, flags);
-
-       mfc_buf = vb_to_mfc_buf(vb);
-       mfc_buf->used = 0;
-       index = vb->index;
-
-       dec->assigned_fd[index] = vb->planes[0].m.fd;
-       mfc_debug(2, "[DPB] Assigned FD[%d] = %d (%s)\n", index, dec->assigned_fd[index],
-                       (dec->dynamic_used & (1 << index) ? "used" : "non-used"));
-
-       list_add_tail(&mfc_buf->list, &ctx->dst_buf_queue.head);
-       ctx->dst_buf_queue.count++;
-
-       spin_unlock_irqrestore(&ctx->buf_queue_lock, flags);
-}
-
-void s5p_mfc_cleanup_nal_queue(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dec *dec = ctx->dec_priv;
-       struct s5p_mfc_buf *src_mb, *dst_mb;
-       unsigned long flags;
-       unsigned int index;
-
-       spin_lock_irqsave(&ctx->buf_queue_lock, flags);
-
-       while (!list_empty(&ctx->src_buf_nal_queue.head)) {
-               src_mb = list_entry(ctx->src_buf_nal_queue.head.prev, struct s5p_mfc_buf, list);
-
-               index = src_mb->vb.vb2_buf.index;
-               call_cop(ctx, recover_buf_ctrls_nal_q, ctx, &ctx->src_ctrls[index]);
-
-               src_mb->used = 0;
-
-               /* If it is not buffer batch mode, index is always zero */
-               if (src_mb->next_index > src_mb->done_index) {
-                       mfc_debug(2, "[NALQ][BUFCON] batch buf next index[%d] recover to [%d]\n",
-                                       src_mb->next_index, src_mb->done_index);
-                       src_mb->next_index = src_mb->done_index;
-               }
-
-               list_del(&src_mb->list);
-               ctx->src_buf_nal_queue.count--;
-
-               list_add(&src_mb->list, &ctx->src_buf_queue.head);
-               ctx->src_buf_queue.count++;
-
-               mfc_debug(2, "[NALQ] cleanup, src_buf_nal_queue -> src_buf_queue, index:%d\n",
-                               src_mb->vb.vb2_buf.index);
-       }
-
-       while (!list_empty(&ctx->dst_buf_nal_queue.head)) {
-               dst_mb = list_entry(ctx->dst_buf_nal_queue.head.prev, struct s5p_mfc_buf, list);
-
-               dst_mb->used = 0;
-               if (ctx->type == MFCINST_DECODER)
-                       clear_bit(dst_mb->vb.vb2_buf.index, &dec->available_dpb);
-               list_del(&dst_mb->list);
-               ctx->dst_buf_nal_queue.count--;
-
-               list_add(&dst_mb->list, &ctx->dst_buf_queue.head);
-               ctx->dst_buf_queue.count++;
-
-               mfc_debug(2, "[NALQ] cleanup, dst_buf_nal_queue -> dst_buf_queue, index:%d\n",
-                               dst_mb->vb.vb2_buf.index);
-       }
-
-       spin_unlock_irqrestore(&ctx->buf_queue_lock, flags);
-}
-
-int s5p_mfc_is_last_frame(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_buf *src_mb;
-       struct s5p_mfc_dev *dev;
-       unsigned long flags;
-
-       mfc_debug_enter();
-
-       if (!ctx) {
-               mfc_err_dev("no mfc context to run\n");
-               return -EINVAL;
-       }
-
-       dev = ctx->dev;
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return -EINVAL;
-       }
-
-       spin_lock_irqsave(&ctx->buf_queue_lock, flags);
-
-       if (list_empty(&ctx->src_buf_queue.head)) {
-               mfc_debug(2, "src_buf_queue is empty\n");
-               spin_unlock_irqrestore(&ctx->buf_queue_lock, flags);
-               return -EINVAL;
-       }
-
-       src_mb = list_entry(ctx->src_buf_queue.head.next, struct s5p_mfc_buf, list);
-
-       mfc_debug(4, "addr[0]: 0x%08llx\n", src_mb->addr[0][0]);
-
-       if (src_mb->vb.reserved2 & FLAG_LAST_FRAME) {
-               mfc_debug(2, "last frame!\n");
-               spin_unlock_irqrestore(&ctx->buf_queue_lock, flags);
-               return 1;
-       }
-
-       mfc_debug(4, "not last frame!\n");
-       spin_unlock_irqrestore(&ctx->buf_queue_lock, flags);
-
-       mfc_debug_leave();
-
-       return 0;
-}
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_queue.h b/drivers/media/platform/exynos/mfc/s5p_mfc_queue.h
deleted file mode 100644 (file)
index 8f50a27..0000000
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_queue.h
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __S5P_MFC_QUEUE_H
-#define __S5P_MFC_QUEUE_H __FILE__
-
-#include  "s5p_mfc_common.h"
-
-/**
- * enum s5p_mfc_queue_used_type
- */
-enum s5p_mfc_queue_used_type {
-       MFC_BUF_NO_TOUCH_USED   = -1,
-       MFC_BUF_RESET_USED      = 0,
-       MFC_BUF_SET_USED        = 1,
-};
-
-/**
- * enum s5p_mfc_queue_top_type
- */
-enum s5p_mfc_queue_top_type {
-       MFC_QUEUE_ADD_BOTTOM    = 0,
-       MFC_QUEUE_ADD_TOP       = 1,
-};
-
-static inline unsigned int s5p_mfc_get_queue_count(spinlock_t *plock, struct s5p_mfc_buf_queue *queue)
-{
-       unsigned long flags;
-       unsigned int ret = 0;
-
-       spin_lock_irqsave(plock, flags);
-       ret = queue->count;
-       spin_unlock_irqrestore(plock, flags);
-
-       return ret;
-}
-
-static inline int s5p_mfc_is_queue_count_same(spinlock_t *plock, struct s5p_mfc_buf_queue *queue,
-               unsigned int value)
-{
-       unsigned long flags;
-       int ret = 0;
-
-       spin_lock_irqsave(plock, flags);
-       if (queue->count == value)
-               ret = 1;
-       spin_unlock_irqrestore(plock, flags);
-
-       return ret;
-}
-
-static inline int s5p_mfc_is_queue_count_greater(spinlock_t *plock, struct s5p_mfc_buf_queue *queue,
-               unsigned int value)
-{
-       unsigned long flags;
-       int ret = 0;
-
-       spin_lock_irqsave(plock, flags);
-       if (queue->count > value)
-               ret = 1;
-       spin_unlock_irqrestore(plock, flags);
-
-       return ret;
-}
-
-static inline int s5p_mfc_is_queue_count_smaller(spinlock_t *plock, struct s5p_mfc_buf_queue *queue,
-               unsigned int value)
-{
-       unsigned long flags;
-       int ret = 0;
-
-       spin_lock_irqsave(plock, flags);
-       if (queue->count < value)
-               ret = 1;
-       spin_unlock_irqrestore(plock, flags);
-
-       return ret;
-}
-
-static inline void s5p_mfc_init_queue(struct s5p_mfc_buf_queue *queue)
-{
-       INIT_LIST_HEAD(&queue->head);
-       queue->count = 0;
-}
-
-static inline void s5p_mfc_create_queue(struct s5p_mfc_buf_queue *queue)
-{
-       s5p_mfc_init_queue(queue);
-}
-
-static inline void s5p_mfc_delete_queue(struct s5p_mfc_buf_queue *queue)
-{
-       s5p_mfc_init_queue(queue);
-}
-
-void s5p_mfc_add_tail_buf(spinlock_t *plock, struct s5p_mfc_buf_queue *queue,
-               struct s5p_mfc_buf *mfc_buf);
-
-int s5p_mfc_peek_buf_csd(spinlock_t *plock, struct s5p_mfc_buf_queue *queue);
-
-struct s5p_mfc_buf *s5p_mfc_get_buf(spinlock_t *plock, struct s5p_mfc_buf_queue *queue,
-               enum s5p_mfc_queue_used_type used);
-struct s5p_mfc_buf *s5p_mfc_get_del_buf(spinlock_t *plock, struct s5p_mfc_buf_queue *queue,
-               enum s5p_mfc_queue_used_type used);
-struct s5p_mfc_buf *s5p_mfc_get_del_if_consumed(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf_queue *queue,
-               unsigned long consumed, unsigned int min_bytes, int err, int *deleted);
-struct s5p_mfc_buf *s5p_mfc_get_move_buf(spinlock_t *plock,
-               struct s5p_mfc_buf_queue *to_queue, struct s5p_mfc_buf_queue *from_queue,
-               enum s5p_mfc_queue_used_type used, enum s5p_mfc_queue_top_type top);
-struct s5p_mfc_buf *s5p_mfc_get_move_buf_used(spinlock_t *plock,
-               struct s5p_mfc_buf_queue *to_queue, struct s5p_mfc_buf_queue *from_queue);
-struct s5p_mfc_buf *s5p_mfc_get_move_buf_addr(spinlock_t *plock,
-               struct s5p_mfc_buf_queue *to_queue, struct s5p_mfc_buf_queue *from_queue,
-               dma_addr_t addr);
-
-struct s5p_mfc_buf *s5p_mfc_find_first_buf(spinlock_t *plock, struct s5p_mfc_buf_queue *queue,
-               dma_addr_t addr);
-struct s5p_mfc_buf *s5p_mfc_find_buf(spinlock_t *plock, struct s5p_mfc_buf_queue *queue,
-               dma_addr_t addr);
-struct s5p_mfc_buf *s5p_mfc_find_del_buf(spinlock_t *plock, struct s5p_mfc_buf_queue *queue,
-               dma_addr_t addr);
-struct s5p_mfc_buf *s5p_mfc_find_move_buf(spinlock_t *plock,
-               struct s5p_mfc_buf_queue *to_queue, struct s5p_mfc_buf_queue *from_queue,
-               dma_addr_t addr, unsigned int released_flag);
-struct s5p_mfc_buf *s5p_mfc_find_move_buf_used(spinlock_t *plock,
-               struct s5p_mfc_buf_queue *to_queue, struct s5p_mfc_buf_queue *from_queue,
-               dma_addr_t addr);
-
-void s5p_mfc_move_first_buf_used(spinlock_t *plock, struct s5p_mfc_buf_queue *to_queue,
-               struct s5p_mfc_buf_queue *from_queue, enum s5p_mfc_queue_top_type top);
-void s5p_mfc_move_all_bufs(spinlock_t *plock, struct s5p_mfc_buf_queue *to_queue,
-               struct s5p_mfc_buf_queue *from_queue, enum s5p_mfc_queue_top_type top);
-
-void s5p_mfc_cleanup_queue(spinlock_t *plock, struct s5p_mfc_buf_queue *queue);
-
-void s5p_mfc_handle_released_info(struct s5p_mfc_ctx *ctx,
-               unsigned int released_flag, int index);
-
-struct s5p_mfc_buf *s5p_mfc_move_reuse_buffer(struct s5p_mfc_ctx *ctx, int release_index);
-
-void s5p_mfc_cleanup_enc_src_queue(struct s5p_mfc_ctx *ctx);
-void s5p_mfc_cleanup_enc_dst_queue(struct s5p_mfc_ctx *ctx);
-
-struct s5p_mfc_buf *s5p_mfc_search_for_dpb(struct s5p_mfc_ctx *ctx, unsigned int dynamic_used);
-struct s5p_mfc_buf *s5p_mfc_search_move_dpb_nal_q(struct s5p_mfc_ctx *ctx, unsigned int dynamic_used);
-void s5p_mfc_store_dpb(struct s5p_mfc_ctx *ctx, struct vb2_buffer *vb);
-
-void s5p_mfc_cleanup_nal_queue(struct s5p_mfc_ctx *ctx);
-int s5p_mfc_is_last_frame(struct s5p_mfc_ctx *ctx);
-
-#endif /* __S5P_MFC_QUEUE_H */
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_reg.c b/drivers/media/platform/exynos/mfc/s5p_mfc_reg.c
deleted file mode 100644 (file)
index bfc545d..0000000
+++ /dev/null
@@ -1,547 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_reg.c
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/delay.h>
-
-#include "s5p_mfc_reg.h"
-
-void s5p_mfc_dbg_enable(struct s5p_mfc_dev *dev)
-{
-       mfc_debug(2, "MFC debug info enable\n");
-       MFC_WRITEL(0x1, S5P_FIMV_DBG_INFO_ENABLE);
-}
-
-void s5p_mfc_dbg_disable(struct s5p_mfc_dev *dev)
-{
-       mfc_debug(2, "MFC debug info disable\n");
-       MFC_WRITEL(0x0, S5P_FIMV_DBG_INFO_ENABLE);
-}
-
-void s5p_mfc_dbg_set_addr(struct s5p_mfc_dev *dev)
-{
-       struct s5p_mfc_ctx_buf_size *buf_size = dev->variant->buf_size->ctx_buf;
-
-       memset((void *)dev->dbg_info_buf.vaddr, 0, buf_size->dbg_info_buf);
-
-       MFC_WRITEL(dev->dbg_info_buf.daddr, S5P_FIMV_DBG_BUFFER_ADDR);
-       MFC_WRITEL(buf_size->dbg_info_buf, S5P_FIMV_DBG_BUFFER_SIZE);
-}
-
-void s5p_mfc_otf_set_frame_addr(struct s5p_mfc_ctx *ctx, int num_planes)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct _otf_handle *handle = ctx->otf_handle;
-       struct _otf_buf_addr *buf_addr = &handle->otf_buf_addr;
-       int index = handle->otf_buf_index;
-       int i;
-
-       for (i = 0; i < num_planes; i++) {
-               mfc_debug(2, "[OTF][FRAME] set frame buffer[%d], 0x%08llx)\n",
-                               i, buf_addr->otf_daddr[index][i]);
-               MFC_WRITEL(buf_addr->otf_daddr[index][i],
-                               S5P_FIMV_E_SOURCE_FIRST_ADDR + (i * 4));
-       }
-}
-
-void s5p_mfc_otf_set_stream_size(struct s5p_mfc_ctx *ctx, unsigned int size)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct _otf_handle *handle = ctx->otf_handle;
-       struct _otf_debug *debug = &handle->otf_debug;
-       struct s5p_mfc_special_buf *buf;
-
-       mfc_debug(2, "[OTF] set stream buffer full size, %u\n", size);
-       MFC_WRITEL(size, S5P_FIMV_E_STREAM_BUFFER_SIZE);
-
-       if (otf_dump && !ctx->is_drm) {
-               buf = &debug->stream_buf[debug->frame_cnt];
-               mfc_debug(2, "[OTF] set stream addr for debugging\n");
-               mfc_debug(2, "[OTF][STREAM] buf[%d] daddr: 0x%08llx\n",
-                               debug->frame_cnt, buf->daddr);
-               MFC_WRITEL(buf->daddr, S5P_FIMV_E_STREAM_BUFFER_ADDR);
-       }
-}
-
-void s5p_mfc_otf_set_hwfc_index(struct s5p_mfc_ctx *ctx, int job_id)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       mfc_debug(2, "[OTF] set hwfc index, %d\n", job_id);
-       HWFC_WRITEL(job_id, HWFC_ENCODING_IDX);
-}
-
-/* Set decoding frame buffer */
-int s5p_mfc_set_dec_codec_buffers(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev;
-       struct s5p_mfc_dec *dec;
-       unsigned int i;
-       size_t frame_size_mv;
-       dma_addr_t buf_addr;
-       int buf_size;
-       int align_gap;
-       struct s5p_mfc_raw_info *raw;
-       unsigned int reg = 0;
-
-       if (!ctx) {
-               mfc_err_dev("no mfc context to run\n");
-               return -EINVAL;
-       }
-
-       dev = ctx->dev;
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return -EINVAL;
-       }
-
-       dec = ctx->dec_priv;
-       if (!dec) {
-               mfc_err_dev("no mfc decoder to run\n");
-               return -EINVAL;
-       }
-
-       raw = &ctx->raw_buf;
-       buf_addr = ctx->codec_buf.daddr;
-       buf_size = ctx->codec_buf.size;
-
-       mfc_debug(2, "[MEMINFO] codec buf 0x%llx size: %d\n", buf_addr, buf_size);
-       mfc_debug(2, "Total DPB COUNT: %d, display delay: %d\n",
-                       dec->total_dpb_count, dec->display_delay);
-
-       /* set decoder DPB size, stride */
-       MFC_WRITEL(dec->total_dpb_count, S5P_FIMV_D_NUM_DPB);
-       for (i = 0; i < raw->num_planes; i++) {
-               mfc_debug(2, "[FRAME] buf[%d] size: %d, stride: %d\n",
-                               i, raw->plane_size[i], raw->stride[i]);
-               MFC_WRITEL(raw->plane_size[i], S5P_FIMV_D_FIRST_PLANE_DPB_SIZE + (i * 4));
-               MFC_WRITEL(ctx->raw_buf.stride[i],
-                               S5P_FIMV_D_FIRST_PLANE_DPB_STRIDE_SIZE + (i * 4));
-               if (ctx->is_10bit) {
-                       MFC_WRITEL(raw->stride_2bits[i], S5P_FIMV_D_FIRST_PLANE_2BIT_DPB_STRIDE_SIZE + (i * 4));
-                       MFC_WRITEL(raw->plane_size_2bits[i], S5P_FIMV_D_FIRST_PLANE_2BIT_DPB_SIZE + (i * 4));
-                       mfc_debug(2, "[FRAME][10BIT] 2bits buf[%d] size: %d, stride: %d\n",
-                                       i, raw->plane_size_2bits[i], raw->stride_2bits[i]);
-               }
-       }
-
-       /* set codec buffers */
-       MFC_WRITEL(buf_addr, S5P_FIMV_D_SCRATCH_BUFFER_ADDR);
-       MFC_WRITEL(ctx->scratch_buf_size, S5P_FIMV_D_SCRATCH_BUFFER_SIZE);
-       buf_addr += ctx->scratch_buf_size;
-       buf_size -= ctx->scratch_buf_size;
-
-       if (IS_H264_DEC(ctx) || IS_H264_MVC_DEC(ctx) || IS_HEVC_DEC(ctx) || IS_BPG_DEC(ctx))
-               MFC_WRITEL(ctx->mv_size, S5P_FIMV_D_MV_BUFFER_SIZE);
-
-       if (IS_VP9_DEC(ctx)){
-               MFC_WRITEL(buf_addr, S5P_FIMV_D_STATIC_BUFFER_ADDR);
-               MFC_WRITEL(DEC_STATIC_BUFFER_SIZE, S5P_FIMV_D_STATIC_BUFFER_SIZE);
-               buf_addr += DEC_STATIC_BUFFER_SIZE;
-               buf_size -= DEC_STATIC_BUFFER_SIZE;
-       }
-
-       if (IS_MPEG4_DEC(ctx) && dec->loop_filter_mpeg4) {
-               mfc_debug(2, "Add DPB for loop filter of MPEG4\n");
-               for (i = 0; i < NUM_MPEG4_LF_BUF; i++) {
-                       MFC_WRITEL(buf_addr, S5P_FIMV_D_POST_FILTER_LUMA_DPB0 + (4 * i));
-                       buf_addr += ctx->loopfilter_luma_size;
-                       buf_size -= ctx->loopfilter_luma_size;
-
-                       MFC_WRITEL(buf_addr, S5P_FIMV_D_POST_FILTER_CHROMA_DPB0 + (4 * i));
-                       buf_addr += ctx->loopfilter_chroma_size;
-                       buf_size -= ctx->loopfilter_chroma_size;
-               }
-               reg |= ((dec->loop_filter_mpeg4 & S5P_FIMV_D_INIT_BUF_OPT_LF_CTRL_MASK)
-                               << S5P_FIMV_D_INIT_BUF_OPT_LF_CTRL_SHIFT);
-       }
-
-       reg |= (0x1 << S5P_FIMV_D_INIT_BUF_OPT_DYNAMIC_DPB_SET_SHIFT);
-
-       if (CODEC_NOT_CODED(ctx)) {
-               reg |= (0x1 << S5P_FIMV_D_INIT_BUF_OPT_COPY_NOT_CODED_SHIFT);
-               mfc_debug(2, "Notcoded frame copy mode start\n");
-       }
-       /* Enable 10bit Dithering */
-       if (ctx->is_10bit) {
-               reg |= (0x1 << S5P_FIMV_D_INIT_BUF_OPT_DITHERING_EN_SHIFT);
-               /* 64byte align, It is vaid only for VP9 */
-               reg |= (0x1 << S5P_FIMV_D_INIT_BUF_OPT_STRIDE_SIZE_ALIGN);
-       } else {
-               /* 16byte align, It is vaid only for VP9 */
-               reg &= ~(0x1 << S5P_FIMV_D_INIT_BUF_OPT_STRIDE_SIZE_ALIGN);
-       }
-
-       MFC_WRITEL(reg, S5P_FIMV_D_INIT_BUFFER_OPTIONS);
-
-       frame_size_mv = ctx->mv_size;
-       MFC_WRITEL(dec->mv_count, S5P_FIMV_D_NUM_MV);
-       if (IS_H264_DEC(ctx) || IS_H264_MVC_DEC(ctx) || IS_HEVC_DEC(ctx) || IS_BPG_DEC(ctx)) {
-               for (i = 0; i < dec->mv_count; i++) {
-                       /* To test alignment */
-                       align_gap = buf_addr;
-                       buf_addr = ALIGN(buf_addr, 16);
-                       align_gap = buf_addr - align_gap;
-                       buf_size -= align_gap;
-
-                       MFC_WRITEL(buf_addr, S5P_FIMV_D_MV_BUFFER0 + i * 4);
-                       buf_addr += frame_size_mv;
-                       buf_size -= frame_size_mv;
-               }
-       }
-
-       mfc_debug(2, "[MEMINFO] codec buf 0x%llx, remained size: %d\n", buf_addr, buf_size);
-       if (buf_size < 0) {
-               mfc_debug(2, "[MEMINFO] Not enough memory has been allocated\n");
-               return -ENOMEM;
-       }
-
-       return 0;
-}
-
-/* Set encoding ref & codec buffer */
-int s5p_mfc_set_enc_codec_buffers(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_enc *enc = ctx->enc_priv;
-       dma_addr_t buf_addr;
-       int buf_size;
-       int i;
-
-       mfc_debug_enter();
-
-       buf_addr = ctx->codec_buf.daddr;
-       buf_size = ctx->codec_buf.size;
-
-       mfc_debug(2, "[MEMINFO] codec buf 0x%llx, size: %d\n", buf_addr, buf_size);
-       mfc_debug(2, "DPB COUNT: %d\n", ctx->dpb_count);
-
-       MFC_WRITEL(buf_addr, S5P_FIMV_E_SCRATCH_BUFFER_ADDR);
-       MFC_WRITEL(ctx->scratch_buf_size, S5P_FIMV_E_SCRATCH_BUFFER_SIZE);
-       buf_addr += ctx->scratch_buf_size;
-       buf_size -= ctx->scratch_buf_size;
-
-       /* start address of per buffer is aligned */
-       for (i = 0; i < ctx->dpb_count; i++) {
-               MFC_WRITEL(buf_addr, S5P_FIMV_E_LUMA_DPB + (4 * i));
-               buf_addr += enc->luma_dpb_size;
-               buf_size -= enc->luma_dpb_size;
-       }
-       for (i = 0; i < ctx->dpb_count; i++) {
-               MFC_WRITEL(buf_addr, S5P_FIMV_E_CHROMA_DPB + (4 * i));
-               buf_addr += enc->chroma_dpb_size;
-               buf_size -= enc->chroma_dpb_size;
-       }
-       for (i = 0; i < ctx->dpb_count; i++) {
-               MFC_WRITEL(buf_addr, S5P_FIMV_E_ME_BUFFER + (4 * i));
-               buf_addr += enc->me_buffer_size;
-               buf_size -= enc->me_buffer_size;
-       }
-
-       MFC_WRITEL(buf_addr, S5P_FIMV_E_TMV_BUFFER0);
-       buf_addr += enc->tmv_buffer_size >> 1;
-       MFC_WRITEL(buf_addr, S5P_FIMV_E_TMV_BUFFER1);
-       buf_addr += enc->tmv_buffer_size >> 1;
-       buf_size -= enc->tmv_buffer_size;
-
-       mfc_debug(2, "[MEMINFO] codec buf 0x%llx, remained size: %d\n", buf_addr, buf_size);
-       if (buf_size < 0) {
-               mfc_debug(2, "[MEMINFO] Not enough memory has been allocated\n");
-               return -ENOMEM;
-       }
-
-       mfc_debug_leave();
-
-       return 0;
-}
-
-/* Set registers for decoding stream buffer */
-int s5p_mfc_set_dec_stream_buffer(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf *mfc_buf,
-                 unsigned int start_num_byte, unsigned int strm_size)
-{
-       struct s5p_mfc_dev *dev;
-       struct s5p_mfc_dec *dec;
-       unsigned int cpb_buf_size;
-       dma_addr_t addr;
-       int index = -1;
-
-       mfc_debug_enter();
-       if (!ctx) {
-               mfc_err_dev("no mfc context to run\n");
-               return -EINVAL;
-       }
-       dev = ctx->dev;
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return -EINVAL;
-       }
-       dec = ctx->dec_priv;
-       if (!dec) {
-               mfc_err_dev("no mfc decoder to run\n");
-               return -EINVAL;
-       }
-
-       cpb_buf_size = ALIGN(dec->src_buf_size, STREAM_BUF_ALIGN);
-
-       if (mfc_buf) {
-               index = mfc_buf->vb.vb2_buf.index;
-               addr = mfc_buf->addr[0][0];
-               if (strm_size > set_strm_size_max(cpb_buf_size)) {
-                       mfc_info_ctx("Decrease strm_size because of %d align: %u -> %u\n",
-                               STREAM_BUF_ALIGN, strm_size, set_strm_size_max(cpb_buf_size));
-                       strm_size = set_strm_size_max(cpb_buf_size);
-                       mfc_buf->vb.vb2_buf.planes[0].bytesused = strm_size;
-               }
-       } else {
-               addr = 0;
-       }
-
-       mfc_debug(2, "[BUFINFO] ctx[%d] set src index: %d, addr: 0x%08llx\n",
-                       ctx->num, index, addr);
-       mfc_debug(2, "[STREAM] strm_size: %#lx(%d), buf_size: %u, offset: %u\n",
-                       strm_size, strm_size, cpb_buf_size, start_num_byte);
-
-       if (strm_size == 0)
-               mfc_info_ctx("stream size is 0\n");
-
-       MFC_WRITEL(strm_size, S5P_FIMV_D_STREAM_DATA_SIZE);
-       MFC_WRITEL(addr, S5P_FIMV_D_CPB_BUFFER_ADDR);
-       MFC_WRITEL(cpb_buf_size, S5P_FIMV_D_CPB_BUFFER_SIZE);
-       MFC_WRITEL(start_num_byte, S5P_FIMV_D_CPB_BUFFER_OFFSET);
-
-       if (mfc_buf)
-               MFC_TRACE_CTX("Set src[%d] fd: %d, %#llx\n",
-                               index, mfc_buf->vb.vb2_buf.planes[0].m.fd, addr);
-
-       mfc_debug_leave();
-       return 0;
-}
-
-void s5p_mfc_set_enc_frame_buffer(struct s5p_mfc_ctx *ctx,
-               struct s5p_mfc_buf *mfc_buf, int num_planes)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       dma_addr_t addr[3] = { 0, 0, 0 };
-       dma_addr_t addr_2bit[2] = { 0, 0 };
-       int index, i;
-
-       if (!mfc_buf) {
-               mfc_debug(3, "enc zero buffer set\n");
-               goto buffer_set;
-       }
-
-       index = mfc_buf->vb.vb2_buf.index;
-       if (mfc_buf->num_valid_bufs > 0) {
-               for (i = 0; i < num_planes; i++) {
-                       addr[i] = mfc_buf->addr[mfc_buf->next_index][i];
-                       mfc_debug(2, "[BUFCON][BUFINFO] ctx[%d] set src index:%d, batch[%d], addr[%d]: 0x%08llx\n",
-                                       ctx->num, index, mfc_buf->next_index, i, addr[i]);
-               }
-               mfc_buf->next_index++;
-       } else {
-               for (i = 0; i < num_planes; i++) {
-                       addr[i] = mfc_buf->addr[0][i];
-                       mfc_debug(2, "[BUFINFO] ctx[%d] set src index:%d, addr[%d]: 0x%08llx\n",
-                                       ctx->num, index, i, addr[i]);
-               }
-       }
-
-buffer_set:
-       for (i = 0; i < num_planes; i++)
-               MFC_WRITEL(addr[i], S5P_FIMV_E_SOURCE_FIRST_ADDR + (i * 4));
-
-       if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M_S10B ||
-               ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV21M_S10B) {
-               addr_2bit[0] = addr[0] + NV12N_10B_Y_8B_SIZE(ctx->img_width, ctx->img_height);
-               addr_2bit[1] = addr[1] + NV12N_10B_CBCR_8B_SIZE(ctx->img_width, ctx->img_height);
-
-               for (i = 0; i < num_planes; i++) {
-                       MFC_WRITEL(addr_2bit[i], S5P_FIMV_E_SOURCE_FIRST_2BIT_ADDR + (i * 4));
-                       mfc_debug(2, "[BUFINFO][10BIT] ctx[%d] set src 2bit addr[%d]: 0x%08llx\n",
-                                       ctx->num, i, addr_2bit[i]);
-               }
-       } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV16M_S10B ||
-               ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV61M_S10B) {
-               addr_2bit[0] = addr[0] + NV16M_Y_SIZE(ctx->img_width, ctx->img_height);
-               addr_2bit[1] = addr[1] + NV16M_CBCR_SIZE(ctx->img_width, ctx->img_height);
-
-               for (i = 0; i < num_planes; i++) {
-                       MFC_WRITEL(addr_2bit[i], S5P_FIMV_E_SOURCE_FIRST_2BIT_ADDR + (i * 4));
-                       mfc_debug(2, "[BUFINFO][10BIT] ctx[%d] set src 2bit addr[%d]: 0x%08llx\n",
-                                       ctx->num, i, addr_2bit[i]);
-               }
-       }
-}
-
-/* Set registers for encoding stream buffer */
-int s5p_mfc_set_enc_stream_buffer(struct s5p_mfc_ctx *ctx,
-               struct s5p_mfc_buf *mfc_buf)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       dma_addr_t addr;
-       unsigned int size, offset, index;
-
-       index = mfc_buf->vb.vb2_buf.index;
-       addr = mfc_buf->addr[0][0];
-       offset = mfc_buf->vb.vb2_buf.planes[0].data_offset;
-       size = (unsigned int)vb2_plane_size(&mfc_buf->vb.vb2_buf, 0);
-       size = ALIGN(size, 512);
-
-       MFC_WRITEL(addr, S5P_FIMV_E_STREAM_BUFFER_ADDR); /* 16B align */
-       MFC_WRITEL(size, S5P_FIMV_E_STREAM_BUFFER_SIZE);
-       MFC_WRITEL(offset, S5P_FIMV_E_STREAM_BUFFER_OFFSET);
-
-       mfc_debug(2, "[BUFINFO] ctx[%d] set dst index: %d, addr: 0x%08llx\n",
-                       ctx->num, index, addr);
-       mfc_debug(2, "[STREAM] buf_size: %u, offset: %d\n", size, offset);
-
-       return 0;
-}
-
-void s5p_mfc_get_enc_frame_buffer(struct s5p_mfc_ctx *ctx,
-               dma_addr_t addr[], int num_planes)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       unsigned long enc_recon_y_addr, enc_recon_c_addr;
-       int i, addr_offset;
-
-       addr_offset = S5P_FIMV_E_ENCODED_SOURCE_FIRST_ADDR;
-
-       for (i = 0; i < num_planes; i++)
-               addr[i] = MFC_READL(addr_offset + (i * 4));
-
-       enc_recon_y_addr = MFC_READL(S5P_FIMV_E_RECON_LUMA_DPB_ADDR);
-       enc_recon_c_addr = MFC_READL(S5P_FIMV_E_RECON_CHROMA_DPB_ADDR);
-
-       mfc_debug(2, "[MEMINFO] recon y: 0x%08lx c: 0x%08lx\n",
-                       enc_recon_y_addr, enc_recon_c_addr);
-}
-
-void s5p_mfc_set_enc_stride(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       int i;
-
-       for (i = 0; i < ctx->raw_buf.num_planes; i++) {
-               MFC_WRITEL(ctx->raw_buf.stride[i],
-                               S5P_FIMV_E_SOURCE_FIRST_STRIDE + (i * 4));
-               mfc_debug(2, "[FRAME] enc src plane[%d] stride: %d\n",
-                               i, ctx->raw_buf.stride[i]);
-       }
-}
-
-int s5p_mfc_set_dynamic_dpb(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf *dst_mb)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_dec *dec = ctx->dec_priv;
-       struct s5p_mfc_raw_info *raw = &ctx->raw_buf;
-       int dst_index;
-       int i;
-
-       dst_index = dst_mb->vb.vb2_buf.index;
-       set_bit(dst_index, &dec->available_dpb);
-       dec->dynamic_set = 1 << dst_index;
-       mfc_debug(2, "[DPB] ADDING Flag after: 0x%lx\n", dec->available_dpb);
-
-       /* for debugging about black bar detection */
-       if (MFC_FEATURE_SUPPORT(dev, dev->pdata->black_bar) && dec->detect_black_bar) {
-               for (i = 0; i < raw->num_planes; i++) {
-                       dec->frame_vaddr[i][dec->frame_cnt] = vb2_plane_vaddr(&dst_mb->vb.vb2_buf, i);
-                       dec->frame_daddr[i][dec->frame_cnt] = dst_mb->addr[0][i];
-                       dec->frame_size[i][dec->frame_cnt] = raw->plane_size[i];
-                       dec->index[i][dec->frame_cnt] = dst_index;
-                       dec->fd[i][dec->frame_cnt] = dst_mb->vb.vb2_buf.planes[0].m.fd;
-               }
-               dec->frame_cnt++;
-               if (dec->frame_cnt >= 30)
-                       dec->frame_cnt = 0;
-       }
-
-       /* decoder dst buffer CFW PROT */
-       s5p_mfc_protect_dpb(ctx, dst_mb);
-
-       for (i = 0; i < raw->num_planes; i++) {
-               MFC_WRITEL(raw->plane_size[i],
-                               S5P_FIMV_D_FIRST_PLANE_DPB_SIZE + i * 4);
-               MFC_WRITEL(dst_mb->addr[0][i],
-                               S5P_FIMV_D_FIRST_PLANE_DPB0 + (i * 0x100 + dst_index * 4));
-               if (ctx->is_10bit)
-                       MFC_WRITEL(raw->plane_size_2bits[i],
-                                       S5P_FIMV_D_FIRST_PLANE_2BIT_DPB_SIZE + (i * 4));
-               mfc_debug(2, "[BUFINFO][DPB] ctx[%d] set dst index: %d, addr[%d]: 0x%08llx\n",
-                               ctx->num, dst_index, i, dst_mb->addr[0][i]);
-       }
-
-       MFC_TRACE_CTX("Set dst[%d] fd: %d, %#llx / avail %#lx used %#x\n",
-                       dst_index, dst_mb->vb.vb2_buf.planes[0].m.fd, dst_mb->addr[0][0],
-                       dec->available_dpb, dec->dynamic_used);
-
-       return 0;
-}
-
-void s5p_mfc_set_pixel_format(struct s5p_mfc_dev *dev, unsigned int format)
-{
-       unsigned int reg = 0;
-       unsigned int pix_val, mem_type_10bit = 0;
-
-       if (dev->pdata->P010_decoding)
-               mem_type_10bit = 1;
-
-       switch (format) {
-       case V4L2_PIX_FMT_NV12M:
-       case V4L2_PIX_FMT_NV12N:
-       case V4L2_PIX_FMT_NV12MT_16X16:
-       case V4L2_PIX_FMT_NV16M:
-               pix_val = 0;
-               break;
-       case V4L2_PIX_FMT_NV21M:
-       case V4L2_PIX_FMT_NV61M:
-               pix_val = 1;
-               break;
-       case V4L2_PIX_FMT_YVU420M:
-               pix_val = 2;
-               break;
-       case V4L2_PIX_FMT_YUV420M:
-       case V4L2_PIX_FMT_YUV420N:
-               pix_val = 3;
-               break;
-       /* For 10bit direct set */
-       case V4L2_PIX_FMT_NV12N_10B:
-       case V4L2_PIX_FMT_NV12M_S10B:
-       case V4L2_PIX_FMT_NV16M_S10B:
-               mem_type_10bit = 0;
-               pix_val = 0;
-               break;
-       case V4L2_PIX_FMT_NV12M_P010:
-       case V4L2_PIX_FMT_NV16M_P210:
-               mem_type_10bit = 1;
-               pix_val = 0;
-               break;
-       case V4L2_PIX_FMT_NV21M_S10B:
-       case V4L2_PIX_FMT_NV61M_S10B:
-               mem_type_10bit = 0;
-               pix_val = 1;
-               break;
-       case V4L2_PIX_FMT_NV21M_P010:
-       case V4L2_PIX_FMT_NV61M_P210:
-               mem_type_10bit = 1;
-               pix_val = 1;
-               break;
-       default:
-               pix_val = 0;
-               break;
-       }
-       reg |= pix_val;
-       reg |= (mem_type_10bit << 4);
-       MFC_WRITEL(reg, S5P_FIMV_PIXEL_FORMAT);
-       mfc_debug(2, "[FRAME] pixel format: %d, mem_type_10bit for 10bit: %d (reg: %#x)\n",
-                       pix_val, mem_type_10bit, reg);
-}
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_reg.h b/drivers/media/platform/exynos/mfc/s5p_mfc_reg.h
deleted file mode 100644 (file)
index c0414a3..0000000
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_reg.h
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __S5P_MFC_REG_H
-#define __S5P_MFC_REG_H __FILE__
-
-#include "s5p_mfc_common.h"
-
-#include "s5p_mfc_utils.h"
-
-#define MFC_READL(offset)              readl(dev->regs_base + (offset))
-#define MFC_WRITEL(data, offset)       writel((data), dev->regs_base + (offset))
-
-#define MFC_MMU0_READL(offset)         readl(dev->sysmmu0_base + (offset))
-#define MFC_MMU1_READL(offset)         readl(dev->sysmmu1_base + (offset))
-
-#define HWFC_WRITEL(data, offset)      writel((data), dev->hwfc_base + (offset))
-
-#define MMCACHE_READL(offset)          readl(dev->mmcache.base + (offset))
-#define MMCACHE_WRITEL(data, offset)   writel((data), dev->mmcache.base + (offset))
-
-/* version */
-#define s5p_mfc_get_fimv_info()                ((MFC_READL(S5P_FIMV_FW_VERSION)                \
-                                               >> S5P_FIMV_FW_VER_INFO_SHFT)           \
-                                               & S5P_FIMV_FW_VER_INFO_MASK)
-#define s5p_mfc_get_fw_ver_year()      ((MFC_READL(S5P_FIMV_FW_VERSION)                \
-                                               >> S5P_FIMV_FW_VER_YEAR_SHFT)           \
-                                               & S5P_FIMV_FW_VER_YEAR_MASK)
-#define s5p_mfc_get_fw_ver_month()     ((MFC_READL(S5P_FIMV_FW_VERSION)                \
-                                               >> S5P_FIMV_FW_VER_MONTH_SHFT)          \
-                                               & S5P_FIMV_FW_VER_MONTH_MASK)
-#define s5p_mfc_get_fw_ver_date()      ((MFC_READL(S5P_FIMV_FW_VERSION)                \
-                                               >> S5P_FIMV_FW_VER_DATE_SHFT)           \
-                                               & S5P_FIMV_FW_VER_DATE_MASK)
-#define s5p_mfc_get_fw_ver_all()       ((MFC_READL(S5P_FIMV_FW_VERSION)                \
-                                               >> S5P_FIMV_FW_VER_ALL_SHFT)            \
-                                               & S5P_FIMV_FW_VER_ALL_MASK)
-#define s5p_mfc_get_mfc_version()      ((MFC_READL(S5P_FIMV_MFC_VERSION)               \
-                                               >> S5P_FIMV_MFC_VER_SHFT)               \
-                                               & S5P_FIMV_MFC_VER_MASK)
-
-
-/* decoding & display information */
-#define s5p_mfc_get_dec_status()       (MFC_READL(S5P_FIMV_D_DECODED_STATUS)           \
-                                               & S5P_FIMV_DEC_STATUS_DECODED_STATUS_MASK)
-#define s5p_mfc_get_disp_status()      (MFC_READL(S5P_FIMV_D_DISPLAY_STATUS)           \
-                                               & S5P_FIMV_DISP_STATUS_DISPLAY_STATUS_MASK)
-#define s5p_mfc_get_res_change()       ((MFC_READL(S5P_FIMV_D_DISPLAY_STATUS)          \
-                                               >> S5P_FIMV_DISP_STATUS_RES_CHANGE_SHIFT)       \
-                                               & S5P_FIMV_DISP_STATUS_RES_CHANGE_MASK)
-#define s5p_mfc_get_black_bar_detection()      ((MFC_READL(S5P_FIMV_D_DISPLAY_STATUS)          \
-                                               >> S5P_FIMV_DISP_STATUS_BLACK_BAR_DETECT_SHIFT) \
-                                               & S5P_FIMV_DISP_STATUS_BLACK_BAR_DETECT_MASK)
-#define s5p_mfc_get_dpb_change()       ((MFC_READL(S5P_FIMV_D_DISPLAY_STATUS)          \
-                                               >> S5P_FIMV_DISP_STATUS_NEED_DPB_CHANGE_SHIFT)  \
-                                               & S5P_FIMV_DISP_STATUS_NEED_DPB_CHANGE_MASK)
-#define s5p_mfc_get_scratch_change()   ((MFC_READL(S5P_FIMV_D_DISPLAY_STATUS)          \
-                                               >> S5P_FIMV_DISP_STATUS_NEED_SCRATCH_CHANGE_SHIFT)      \
-                                               & S5P_FIMV_DISP_STATUS_NEED_SCRATCH_CHANGE_MASK)
-#define s5p_mfc_get_disp_frame_type()  (MFC_READL(S5P_FIMV_D_DISPLAY_FRAME_TYPE)       \
-                                               & S5P_FIMV_DISPLAY_FRAME_MASK)
-#define s5p_mfc_get_dec_frame_type()   (MFC_READL(S5P_FIMV_D_DECODED_FRAME_TYPE)       \
-                                               & S5P_FIMV_DECODED_FRAME_MASK)
-#define s5p_mfc_get_interlace_type()   ((MFC_READL(S5P_FIMV_D_DISPLAY_FRAME_TYPE)      \
-                                               >> S5P_FIMV_DISPLAY_TEMP_INFO_SHIFT)    \
-                                               & S5P_FIMV_DISPLAY_TEMP_INFO_MASK)
-#define s5p_mfc_is_interlace_picture() ((MFC_READL(S5P_FIMV_D_DISPLAY_STATUS)          \
-                                               >> S5P_FIMV_DISP_STATUS_INTERLACE_SHIFT)\
-                                               & S5P_FIMV_DISP_STATUS_INTERLACE_MASK)
-#define s5p_mfc_is_mbaff_picture()     ((MFC_READL(S5P_FIMV_D_H264_INFO)               \
-                                               >> S5P_FIMV_D_H264_INFO_MBAFF_FRAME_FLAG_SHIFT)\
-                                               & S5P_FIMV_D_H264_INFO_MBAFF_FRAME_FLAG_MASK)
-#define s5p_mfc_get_img_width()                MFC_READL(S5P_FIMV_D_DISPLAY_FRAME_WIDTH)
-#define s5p_mfc_get_img_height()       MFC_READL(S5P_FIMV_D_DISPLAY_FRAME_HEIGHT)
-#define s5p_mfc_get_disp_y_addr()      MFC_READL(S5P_FIMV_D_DISPLAY_LUMA_ADDR)
-#define s5p_mfc_get_dec_y_addr()       MFC_READL(S5P_FIMV_D_DECODED_LUMA_ADDR)
-
-
-/* kind of interrupt */
-#define s5p_mfc_get_int_err()          MFC_READL(S5P_FIMV_ERROR_CODE)
-#define s5p_mfc_get_err(x)             (((x) >> S5P_FIMV_ERR_STATUS_SHIFT)             \
-                                               & S5P_FIMV_ERR_STATUS_MASK)
-#define s5p_mfc_get_warn(x)            (((x) >> S5P_FIMV_WARN_STATUS_SHIFT)            \
-                                               & S5P_FIMV_WARN_STATUS_MASK)
-
-
-/* additional information */
-#define s5p_mfc_get_consumed_stream()          MFC_READL(S5P_FIMV_D_DECODED_NAL_SIZE)
-#define s5p_mfc_get_dpb_count()                        MFC_READL(S5P_FIMV_D_MIN_NUM_DPB)
-#define s5p_mfc_get_min_dpb_size(x)            MFC_READL(S5P_FIMV_D_MIN_FIRST_PLANE_DPB_SIZE + (x * 4))
-#define s5p_mfc_get_scratch_size()             MFC_READL(S5P_FIMV_D_MIN_SCRATCH_BUFFER_SIZE)
-#define s5p_mfc_get_mv_count()                 MFC_READL(S5P_FIMV_D_MIN_NUM_MV)
-#define s5p_mfc_get_inst_no()                  MFC_READL(S5P_FIMV_RET_INSTANCE_ID)
-#define s5p_mfc_get_enc_dpb_count()            MFC_READL(S5P_FIMV_E_NUM_DPB)
-#define s5p_mfc_get_enc_scratch_size()         MFC_READL(S5P_FIMV_E_MIN_SCRATCH_BUFFER_SIZE)
-#define s5p_mfc_get_enc_strm_size()            MFC_READL(S5P_FIMV_E_STREAM_SIZE)
-#define s5p_mfc_get_enc_slice_type()           MFC_READL(S5P_FIMV_E_SLICE_TYPE)
-#define s5p_mfc_get_enc_pic_count()            MFC_READL(S5P_FIMV_E_PICTURE_COUNT)
-#define s5p_mfc_get_sei_avail()                        MFC_READL(S5P_FIMV_D_SEI_AVAIL)
-#define s5p_mfc_get_sei_content_light()                MFC_READL(S5P_FIMV_D_CONTENT_LIGHT_LEVEL_INFO_SEI)
-#define s5p_mfc_get_sei_mastering0()           MFC_READL(S5P_FIMV_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_0)
-#define s5p_mfc_get_sei_mastering1()           MFC_READL(S5P_FIMV_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_1)
-#define s5p_mfc_get_sei_mastering2()           MFC_READL(S5P_FIMV_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_2)
-#define s5p_mfc_get_sei_mastering3()           MFC_READL(S5P_FIMV_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_3)
-#define s5p_mfc_get_sei_mastering4()           MFC_READL(S5P_FIMV_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_4)
-#define s5p_mfc_get_sei_mastering5()           MFC_READL(S5P_FIMV_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_5)
-#define s5p_mfc_get_sei_avail_frame_pack()     (MFC_READL(S5P_FIMV_D_SEI_AVAIL)        \
-                                               & S5P_FIMV_D_SEI_AVAIL_FRAME_PACK_MASK)
-#define s5p_mfc_get_sei_avail_content_light()  ((MFC_READL(S5P_FIMV_D_SEI_AVAIL)       \
-                                               >> S5P_FIMV_D_SEI_AVAIL_CONTENT_LIGHT_SHIFT)    \
-                                               & S5P_FIMV_D_SEI_AVAIL_CONTENT_LIGHT_MASK)
-#define s5p_mfc_get_sei_avail_mastering_display()      ((MFC_READL(S5P_FIMV_D_SEI_AVAIL)       \
-                                               >> S5P_FIMV_D_SEI_AVAIL_MASTERING_DISPLAY_SHIFT)        \
-                                               & S5P_FIMV_D_SEI_AVAIL_MASTERING_DISPLAY_MASK)
-#define s5p_mfc_get_video_signal_type()                ((MFC_READL(S5P_FIMV_D_VIDEO_SIGNAL_TYPE)       \
-                                               >> S5P_FIMV_D_VIDEO_SIGNAL_TYPE_FLAG_SHIFT)     \
-                                               & S5P_FIMV_D_VIDEO_SIGNAL_TYPE_FLAG_MASK)
-#define s5p_mfc_get_colour_description()       ((MFC_READL(S5P_FIMV_D_VIDEO_SIGNAL_TYPE)       \
-                                               >> S5P_FIMV_D_COLOUR_DESCRIPTION_FLAG_SHIFT)    \
-                                               & S5P_FIMV_D_COLOUR_DESCRIPTION_FLAG_MASK)
-#define s5p_mfc_get_black_bar_pos_x()          ((MFC_READL(S5P_FIMV_D_BLACK_BAR_START_POS)     \
-                                               >> S5P_FIMV_D_BLACK_BAR_START_X_SHIFT)          \
-                                               & S5P_FIMV_D_BLACK_BAR_START_X_MASK)
-#define s5p_mfc_get_black_bar_pos_y()          ((MFC_READL(S5P_FIMV_D_BLACK_BAR_START_POS)     \
-                                               >> S5P_FIMV_D_BLACK_BAR_START_Y_SHIFT)          \
-                                               & S5P_FIMV_D_BLACK_BAR_START_Y_MASK)
-#define s5p_mfc_get_black_bar_image_w()                ((MFC_READL(S5P_FIMV_D_BLACK_BAR_IMAGE_SIZE)    \
-                                               >> S5P_FIMV_D_BLACK_BAR_IMAGE_W_SHIFT)  \
-                                               & S5P_FIMV_D_BLACK_BAR_IMAGE_W_MASK)
-#define s5p_mfc_get_black_bar_image_h()                ((MFC_READL(S5P_FIMV_D_BLACK_BAR_IMAGE_SIZE)    \
-                                               >> S5P_FIMV_D_BLACK_BAR_IMAGE_H_SHIFT)  \
-                                               & S5P_FIMV_D_BLACK_BAR_IMAGE_H_MASK)
-#define s5p_mfc_get_mvc_disp_view_id()         (MFC_READL(S5P_FIMV_D_MVC_VIEW_ID)              \
-                                               & S5P_FIMV_D_MVC_VIEW_ID_DISP_MASK)
-#define s5p_mfc_get_profile()                  (MFC_READL(S5P_FIMV_D_DECODED_PICTURE_PROFILE)  \
-                                               & S5P_FIMV_D_DECODED_PIC_PROFILE_MASK)
-#define s5p_mfc_get_luma_bit_depth_minus8()    ((MFC_READL(S5P_FIMV_D_DECODED_PICTURE_PROFILE) \
-                                               >> S5P_FIMV_D_BIT_DEPTH_LUMA_MINUS8_SHIFT)      \
-                                               & S5P_FIMV_D_BIT_DEPTH_LUMA_MINUS8_MASK)
-#define s5p_mfc_get_chroma_bit_depth_minus8()  ((MFC_READL(S5P_FIMV_D_DECODED_PICTURE_PROFILE) \
-                                               >> S5P_FIMV_D_BIT_DEPTH_CHROMA_MINUS8_SHIFT)    \
-                                               & S5P_FIMV_D_BIT_DEPTH_CHROMA_MINUS8_MASK)
-#define s5p_mfc_get_dec_used_flag()            MFC_READL(S5P_FIMV_D_USED_DPB_FLAG_LOWER)
-#define s5p_mfc_get_enc_nal_done_info()                ((MFC_READL(S5P_FIMV_E_NAL_DONE_INFO) & (0x3 << 4)) >> 4)
-#define s5p_mfc_get_chroma_format()            (MFC_READL(S5P_FIMV_D_CHROMA_FORMAT)            \
-                                               & S5P_FIMV_D_CHROMA_FORMAT_MASK)
-#define s5p_mfc_get_color_range()              ((MFC_READL(S5P_FIMV_D_CHROMA_FORMAT)   \
-                                               >> S5P_FIMV_D_COLOR_RANGE_SHIFT)        \
-                                               & S5P_FIMV_D_COLOR_RANGE_MASK)
-#define s5p_mfc_get_color_space()              ((MFC_READL(S5P_FIMV_D_CHROMA_FORMAT)   \
-                                               >> S5P_FIMV_D_COLOR_SPACE_SHIFT)        \
-                                               & S5P_FIMV_D_COLOR_SPACE_MASK)
-#define s5p_mfc_get_num_of_tile()              ((MFC_READL(S5P_FIMV_D_DECODED_STATUS)          \
-                                               >> S5P_FIMV_DEC_STATUS_NUM_OF_TILE_SHIFT)       \
-                                               & S5P_FIMV_DEC_STATUS_NUM_OF_TILE_MASK)
-
-
-/* nal queue information */
-#define s5p_mfc_get_nal_q_input_count()                MFC_READL(S5P_FIMV_NAL_QUEUE_INPUT_COUNT)
-#define s5p_mfc_get_nal_q_output_count()       MFC_READL(S5P_FIMV_NAL_QUEUE_OUTPUT_COUNT)
-#define s5p_mfc_get_nal_q_input_exe_count()    MFC_READL(S5P_FIMV_NAL_QUEUE_INPUT_EXE_COUNT)
-#define s5p_mfc_get_nal_q_info()               MFC_READL(S5P_FIMV_NAL_QUEUE_INFO)
-#define s5p_mfc_get_nal_q_input_addr()         MFC_READL(S5P_FIMV_NAL_QUEUE_INPUT_ADDR)
-#define s5p_mfc_get_nal_q_input_size()         MFC_READL(S5P_FIMV_NAL_QUEUE_INPUT_SIZE)
-#define s5p_mfc_get_nal_q_output_addr()                MFC_READL(S5P_FIMV_NAL_QUEUE_OUTPUT_ADDR)
-#define s5p_mfc_get_nal_q_output_ize()         MFC_READL(S5P_FIMV_NAL_QUEUE_OUTPUT_SIZE)
-
-static inline void s5p_mfc_reset_nal_queue_registers(struct s5p_mfc_dev *dev)
-{
-       MFC_WRITEL(0x0, S5P_FIMV_NAL_QUEUE_INPUT_COUNT);
-       MFC_WRITEL(0x0, S5P_FIMV_NAL_QUEUE_OUTPUT_COUNT);
-       MFC_WRITEL(0x0, S5P_FIMV_NAL_QUEUE_INPUT_EXE_COUNT);
-       MFC_WRITEL(0x0, S5P_FIMV_NAL_QUEUE_INFO);
-}
-
-static inline void s5p_mfc_update_nal_queue_input(struct s5p_mfc_dev *dev,
-       dma_addr_t addr, unsigned int size)
-{
-       MFC_WRITEL(addr, S5P_FIMV_NAL_QUEUE_INPUT_ADDR);
-       MFC_WRITEL(size, S5P_FIMV_NAL_QUEUE_INPUT_SIZE);
-}
-
-static inline void s5p_mfc_update_nal_queue_output(struct s5p_mfc_dev *dev,
-       dma_addr_t addr, unsigned int size)
-{
-       MFC_WRITEL(addr, S5P_FIMV_NAL_QUEUE_OUTPUT_ADDR);
-       MFC_WRITEL(size, S5P_FIMV_NAL_QUEUE_OUTPUT_SIZE);
-}
-
-static inline void s5p_mfc_update_nal_queue_input_count(struct s5p_mfc_dev *dev,
-       unsigned int input_count)
-{
-       MFC_WRITEL(input_count, S5P_FIMV_NAL_QUEUE_INPUT_COUNT);
-}
-
-static inline void s5p_mfc_dec_store_crop_info(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_dec *dec = ctx->dec_priv;
-       u32 left, right, top, bottom;
-
-       left = MFC_READL(S5P_FIMV_D_DISPLAY_CROP_INFO1);
-       right = left >> S5P_FIMV_D_SHARED_CROP_RIGHT_SHIFT;
-       left = left & S5P_FIMV_D_SHARED_CROP_LEFT_MASK;
-       top = MFC_READL(S5P_FIMV_D_DISPLAY_CROP_INFO2);
-       bottom = top >> S5P_FIMV_D_SHARED_CROP_BOTTOM_SHIFT;
-       top = top & S5P_FIMV_D_SHARED_CROP_TOP_MASK;
-
-       dec->cr_left = left;
-       dec->cr_right = right;
-       dec->cr_top = top;
-       dec->cr_bot = bottom;
-}
-
-static inline void s5p_mfc_clear_enc_res_change(struct s5p_mfc_dev *dev)
-{
-       unsigned int reg = 0;
-
-       reg = MFC_READL(S5P_FIMV_E_PARAM_CHANGE);
-       reg &= ~(0x7 << 6);
-       MFC_WRITEL(reg, S5P_FIMV_E_PARAM_CHANGE);
-}
-
-static inline void s5p_mfc_clear_roi_enable(struct s5p_mfc_dev *dev)
-{
-       unsigned int reg = 0;
-
-       reg = MFC_READL(S5P_FIMV_E_RC_ROI_CTRL);
-       reg &= ~(0x1);
-       MFC_WRITEL(reg, S5P_FIMV_E_RC_ROI_CTRL);
-}
-
-void s5p_mfc_dbg_enable(struct s5p_mfc_dev *dev);
-void s5p_mfc_dbg_disable(struct s5p_mfc_dev *dev);
-void s5p_mfc_dbg_set_addr(struct s5p_mfc_dev *dev);
-
-void s5p_mfc_otf_set_frame_addr(struct s5p_mfc_ctx *ctx, int num_planes);
-void s5p_mfc_otf_set_stream_size(struct s5p_mfc_ctx *ctx, unsigned int size);
-void s5p_mfc_otf_set_hwfc_index(struct s5p_mfc_ctx *ctx, int job_id);
-
-int s5p_mfc_set_dec_codec_buffers(struct s5p_mfc_ctx *ctx);
-int s5p_mfc_set_enc_codec_buffers(struct s5p_mfc_ctx *mfc_ctx);
-
-int s5p_mfc_set_dec_stream_buffer(struct s5p_mfc_ctx *ctx,
-               struct s5p_mfc_buf *mfc_buf,
-               unsigned int start_num_byte,
-               unsigned int buf_size);
-
-void s5p_mfc_set_enc_frame_buffer(struct s5p_mfc_ctx *ctx,
-               struct s5p_mfc_buf *mfc_buf, int num_planes);
-int s5p_mfc_set_enc_stream_buffer(struct s5p_mfc_ctx *ctx,
-               struct s5p_mfc_buf *mfc_buf);
-
-void s5p_mfc_get_enc_frame_buffer(struct s5p_mfc_ctx *ctx,
-               dma_addr_t addr[], int num_planes);
-void s5p_mfc_set_enc_stride(struct s5p_mfc_ctx *ctx);
-
-int s5p_mfc_set_dynamic_dpb(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf *dst_vb);
-
-void s5p_mfc_set_pixel_format(struct s5p_mfc_dev *dev, unsigned int format);
-
-#endif /* __S5P_MFC_REG_H */
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_regs_v10.h b/drivers/media/platform/exynos/mfc/s5p_mfc_regs_v10.h
deleted file mode 100644 (file)
index 94d818e..0000000
+++ /dev/null
@@ -1,743 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/regs-mfc-v10.h
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __REGS_MFC_V10_H
-#define __REGS_MFC_V10_H __FILE__
-
-#define MFC_MMU_INTERRUPT_STATUS                               0x0060
-#define MFC_MMU_FAULT_TRANS_INFO                               0x0078
-#define MFC_MMU_FAULT_TRANS_INFO_RW_MASK                       0x100000
-#define MFC_MMU_FAULT_TRANS_INFO_AXID_MASK                     0xFFFF
-
-#define HWFC_ENCODING_IDX                                      0x4
-
-/* Codec Common Registers */
-#define S5P_FIMV_RISC_ON                                       0x0000
-#define S5P_FIMV_RISC2HOST_INT                                 0x003C
-#define S5P_FIMV_HOST2RISC_INT                                 0x0044
-#define S5P_FIMV_RISC_BASE_ADDRESS                             0x0054
-
-#define S5P_FIMV_MFC_FW_CLOCK                                  0x1060
-#define S5P_FIMV_MFC_RESET                                     0x1070
-
-#define S5P_FIMV_HOST2RISC_CMD                                 0x1100
-#define S5P_FIMV_RISC2HOST_CMD                                 0x1104
-
-#define S5P_FIMV_MFC_BUS_STATUS                                        0x7018
-#define S5P_FIMV_MFC_RPEND                                     0x7028
-#define S5P_FIMV_MFC_WPEND                                     0x702C
-#define S5P_FIMV_MFC_BUS_RESET_CTRL                            0x7110
-#define S5P_FIMV_MFC_OFF                                       0x7120
-#define S5P_FIMV_MFC_STATE                                     0x7124
-
-#define S5P_FIMV_FW_VERSION                                    0xF000
-#define S5P_FIMV_INSTANCE_ID                                   0xF008
-#define S5P_FIMV_CODEC_TYPE                                    0xF00C
-#define S5P_FIMV_CONTEXT_MEM_ADDR                              0xF014
-#define S5P_FIMV_CONTEXT_MEM_SIZE                              0xF018
-#define S5P_FIMV_SHARED_MEM_ADDR                               0xF01C
-#define S5P_FIMV_PIXEL_FORMAT                                  0xF020
-
-#define S5P_FIMV_METADATA_ENABLE                               0xF024
-#define S5P_FIMV_MFC_VERSION                                   0xF028
-#define S5P_FIMV_DBG_INFO_ENABLE                               0xF02C
-#define S5P_FIMV_DBG_BUFFER_ADDR                               0xF030
-#define S5P_FIMV_DBG_BUFFER_SIZE                               0xF034
-
-#define S5P_FIMV_CODEC_CONTROL                                 0xF038
-#define S5P_FIMV_DEC_TIMEOUT_VALUE                             0xF03C
-#define S5P_FIMV_HED_SHARED_MEM_ADDR                           0xF040
-
-/* NAL QUEUE */
-#define S5P_FIMV_NAL_QUEUE_INPUT_ADDR                          0xF044
-#define S5P_FIMV_NAL_QUEUE_INPUT_SIZE                          0xF048
-#define S5P_FIMV_NAL_QUEUE_OUTPUT_ADDR                         0xF04C
-#define S5P_FIMV_NAL_QUEUE_OUTPUT_SIZE                         0xF050
-#define S5P_FIMV_NAL_QUEUE_INPUT_COUNT                         0xF054
-
-#define S5P_FIMV_RET_INSTANCE_ID                               0xF070
-#define S5P_FIMV_ERROR_CODE                                    0xF074
-#define S5P_FIMV_DBG_BUFFER_OUTPUT_SIZE                                0xF078
-#define S5P_FIMV_METADATA_STATUS                               0xF07C
-
-#define S5P_FIMV_DBG_INFO_STAGE_COUNTER                                0xF088
-
-/* NAL QUEUE */
-#define S5P_FIMV_NAL_QUEUE_OUTPUT_COUNT                                0xF08C
-#define S5P_FIMV_NAL_QUEUE_INPUT_EXE_COUNT                     0xF090
-#define S5P_FIMV_NAL_QUEUE_INFO                                        0xF094
-
-/* Decoder Registers */
-#define S5P_FIMV_D_CRC_CTRL                                    0xF0B0
-#define S5P_FIMV_D_DEC_OPTIONS                                 0xF0B4
-
-#define S5P_FIMV_D_DISPLAY_DELAY                               0xF0B8
-
-#define S5P_FIMV_D_SET_FRAME_WIDTH                             0xF0BC
-#define S5P_FIMV_D_SET_FRAME_HEIGHT                            0xF0C0
-
-#define S5P_FIMV_D_SEI_ENABLE                                  0xF0C4
-
-#define S5P_FIMV_D_FORCE_PIXEL_VAL                             0xF0C8
-
-/* Buffer setting registers */
-/* Session return */
-#define S5P_FIMV_D_MIN_NUM_DPB                                 0xF0F0
-#define S5P_FIMV_D_MIN_FIRST_PLANE_DPB_SIZE                    0xF0F4
-#define S5P_FIMV_D_MIN_SECOND_PLANE_DPB_SIZE                   0xF0F8
-#define S5P_FIMV_D_MIN_THIRD_PLANE_DPB_SIZE                    0xF0FC
-#define S5P_FIMV_D_MIN_NUM_MV                                  0xF100
-#define S5P_FIMV_D_MVC_NUM_VIEWS                               0xF104
-#define S5P_FIMV_D_MIN_SCRATCH_BUFFER_SIZE                     0xF108
-#define S5P_FIMV_D_MIN_FIRST_PLANE_2BIT_DPB_SIZE               0xF10C
-#define S5P_FIMV_D_MIN_SECOND_PLANE_2BIT_DPB_SIZE              0xF110
-#define S5P_FIMV_D_POST_FILTER_LUMA_DPB0                       0xF120
-#define S5P_FIMV_D_POST_FILTER_LUMA_DPB1                       0xF124
-#define S5P_FIMV_D_POST_FILTER_CHROMA_DPB0                     0xF128
-#define S5P_FIMV_D_POST_FILTER_CHROMA_DPB1                     0xF12C
-
-/* Buffers */
-#define S5P_FIMV_D_NUM_DPB                                     0xF130
-#define S5P_FIMV_D_NUM_MV                                      0xF134
-#define S5P_FIMV_D_FIRST_PLANE_DPB_STRIDE_SIZE                 0xF138
-#define S5P_FIMV_D_SECOND_PLANE_DPB_STRIDE_SIZE                        0xF13C
-#define S5P_FIMV_D_THIRD_PLANE_DPB_STRIDE_SIZE                 0xF140
-#define S5P_FIMV_D_FIRST_PLANE_DPB_SIZE                                0xF144
-#define S5P_FIMV_D_SECOND_PLANE_DPB_SIZE                       0xF148
-#define S5P_FIMV_D_THIRD_PLANE_DPB_SIZE                                0xF14C
-#define S5P_FIMV_D_MV_BUFFER_SIZE                              0xF150
-#define S5P_FIMV_D_INIT_BUFFER_OPTIONS                         0xF154
-#define S5P_FIMV_D_FIRST_PLANE_DPB0                            0xF160
-#define S5P_FIMV_D_SECOND_PLANE_DPB0                           0xF260
-#define S5P_FIMV_D_THIRD_PLANE_DPB0                            0xF360
-#define S5P_FIMV_D_MV_BUFFER0                                  0xF460
-#define S5P_FIMV_D_SCRATCH_BUFFER_ADDR                         0xF560
-#define S5P_FIMV_D_SCRATCH_BUFFER_SIZE                         0xF564
-#define S5P_FIMV_D_METADATA_BUFFER_ADDR                                0xF568
-#define S5P_FIMV_D_METADATA_BUFFER_SIZE                                0xF56C
-
-#define S5P_FIMV_D_STATIC_BUFFER_ADDR                          0xF570
-#define S5P_FIMV_D_STATIC_BUFFER_SIZE                          0xF574
-#define S5P_FIMV_D_FIRST_PLANE_2BIT_DPB_SIZE                   0xF578
-#define S5P_FIMV_D_SECOND_PLANE_2BIT_DPB_SIZE                  0xF57C
-#define S5P_FIMV_D_FIRST_PLANE_2BIT_DPB_STRIDE_SIZE            0xF580
-#define S5P_FIMV_D_SECOND_PLANE_2BIT_DPB_STRIDE_SIZE           0xF584
-
-#define S5P_FIMV_D_NAL_START_OPTIONS                           0xF5AC
-
-/* Nal cmd */
-#define S5P_FIMV_D_CPB_BUFFER_ADDR                             0xF5B0
-#define S5P_FIMV_D_CPB_BUFFER_SIZE                             0xF5B4
-#define S5P_FIMV_D_AVAILABLE_DPB_FLAG_UPPER                    0xF5B8
-#define S5P_FIMV_D_AVAILABLE_DPB_FLAG_LOWER                    0xF5BC
-#define S5P_FIMV_D_CPB_BUFFER_OFFSET                           0xF5C0
-#define S5P_FIMV_D_SLICE_IF_ENABLE                             0xF5C4
-#define S5P_FIMV_D_PICTURE_TAG                                 0xF5C8
-#define S5P_FIMV_D_STREAM_DATA_SIZE                            0xF5D0
-#define S5P_FIMV_D_DYNAMIC_DPB_FLAG_UPPER                      0xF5D4
-#define S5P_FIMV_D_DYNAMIC_DPB_FLAG_LOWER                      0xF5D8
-
-/* Nal return */
-#define S5P_FIMV_D_DISPLAY_FRAME_WIDTH                         0xF600
-#define S5P_FIMV_D_DISPLAY_FRAME_HEIGHT                                0xF604
-#define S5P_FIMV_D_DISPLAY_STATUS                              0xF608
-#define S5P_FIMV_D_DISPLAY_FIRST_PLANE_ADDR                    0xF60C
-#define S5P_FIMV_D_DISPLAY_SECOND_PLANE_ADDR                   0xF610
-#define S5P_FIMV_D_DISPLAY_THIRD_PLANE_ADDR                    0xF614
-#define S5P_FIMV_D_DISPLAY_FRAME_TYPE                          0xF618
-#define S5P_FIMV_D_DISPLAY_CROP_INFO1                          0xF61C
-#define S5P_FIMV_D_DISPLAY_CROP_INFO2                          0xF620
-#define S5P_FIMV_D_DISPLAY_PICTURE_PROFILE                     0xF624
-#define S5P_FIMV_D_DISPLAY_FIRST_PLANE_CRC                     0xF628
-#define S5P_FIMV_D_DISPLAY_SECOND_PLANE_CRC                    0xF62C
-#define S5P_FIMV_D_DISPLAY_THIRD_PLANE_CRC                     0xF630
-#define S5P_FIMV_D_DISPLAY_ASPECT_RATIO                                0xF634
-#define S5P_FIMV_D_DISPLAY_EXTENDED_AR                         0xF638
-#define S5P_FIMV_D_DECODED_FRAME_WIDTH                         0xF63C
-#define S5P_FIMV_D_DECODED_FRAME_HEIGHT                                0xF640
-#define S5P_FIMV_D_DECODED_STATUS                              0xF644
-#define S5P_FIMV_D_DECODED_FIRST_PLANE_ADDR                    0xF648
-#define S5P_FIMV_D_DECODED_SECOND_PLANE_ADDR                   0xF64C
-#define S5P_FIMV_D_DECODED_THIRD_PLANE_ADDR                    0xF650
-#define S5P_FIMV_D_DECODED_FRAME_TYPE                          0xF654
-#define S5P_FIMV_D_DECODED_CROP_INFO1                          0xF658
-#define S5P_FIMV_D_DECODED_CROP_INFO2                          0xF65C
-#define S5P_FIMV_D_DECODED_PICTURE_PROFILE                     0xF660
-#define S5P_FIMV_D_DECODED_NAL_SIZE                            0xF664
-#define S5P_FIMV_D_DECODED_FIRST_PLANE_CRC                     0xF668
-#define S5P_FIMV_D_DECODED_SECOND_PLANE_CRC                    0xF66C
-#define S5P_FIMV_D_DECODED_THIRD_PLANE_CRC                     0xF670
-#define S5P_FIMV_D_RET_PICTURE_TAG_TOP                         0xF674
-#define S5P_FIMV_D_RET_PICTURE_TAG_BOT                         0xF678
-#define S5P_FIMV_D_RET_PICTURE_TIME_TOP                                0xF67C
-#define S5P_FIMV_D_RET_PICTURE_TIME_BOT                                0xF680
-#define S5P_FIMV_D_CHROMA_FORMAT                               0xF684
-
-#define S5P_FIMV_D_VC1_INFO                                    0xF688
-#define S5P_FIMV_D_MPEG4_INFO                                  0xF68C
-#define S5P_FIMV_D_H264_INFO                                   0xF690
-#define S5P_FIMV_D_HEVC_INFO                                   0xF6A0
-#define S5P_FIMV_D_BPG_INFO                                    0xF6A8
-
-#define S5P_FIMV_D_METADATA_ADDR_CONCEALED_MB                  0xF6B0
-#define S5P_FIMV_D_METADATA_SIZE_CONCEALED_MB                  0xF6B4
-#define S5P_FIMV_D_METADATA_ADDR_VC1_PARAM                     0xF6B8
-#define S5P_FIMV_D_METADATA_SIZE_VC1_PARAM                     0xF6BC
-#define S5P_FIMV_D_METADATA_ADDR_SEI_NAL                       0xF6C0
-#define S5P_FIMV_D_METADATA_SIZE_SEI_NAL                       0xF6C4
-#define S5P_FIMV_D_METADATA_ADDR_VUI                           0xF6C8
-#define S5P_FIMV_D_METADATA_SIZE_VUI                           0xF6CC
-#define S5P_FIMV_D_METADATA_ADDR_MVCVUI                                0xF6D0
-#define S5P_FIMV_D_METADATA_SIZE_MVCVUI                                0xF6D4
-
-#define S5P_FIMV_D_MVC_VIEW_ID                                 0xF6D8
-
-#define S5P_FIMV_D_SEI_AVAIL                                   0xF6DC
-#define S5P_FIMV_D_FRAME_PACK_ARRGMENT_ID                      0xF6E0
-#define S5P_FIMV_D_FRAME_PACK_SEI_INFO                         0xF6E4
-#define S5P_FIMV_D_FRAME_PACK_GRID_POS                         0xF6E8
-
-#define S5P_FIMV_D_DISPLAY_RECOVERY_SEI_INFO                   0xF6EC
-#define S5P_FIMV_D_DECODED_RECOVERY_SEI_INFO                   0xF6F0
-
-#define S5P_FIMV_D_DISPLAY_FIRST_PLANE_2BIT_CRC                        0xF6FC
-#define S5P_FIMV_D_DISPLAY_SECOND_PLANE_2BIT_CRC               0xF700
-#define S5P_FIMV_D_DECODED_FIRST_PLANE_2BIT_CRC                        0xF704
-#define S5P_FIMV_D_DECODED_SECOND_PLANE_2BIT_CRC               0xF708
-
-#define S5P_FIMV_D_VIDEO_SIGNAL_TYPE                           0xF70C
-#define S5P_FIMV_D_CONTENT_LIGHT_LEVEL_INFO_SEI                        0xF710
-#define S5P_FIMV_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_0       0xF714
-#define S5P_FIMV_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_1       0xF718
-
-#define S5P_FIMV_D_USED_DPB_FLAG_UPPER                         0xF720
-#define S5P_FIMV_D_USED_DPB_FLAG_LOWER                         0xF724
-
-#define S5P_FIMV_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_2       0xF728
-#define S5P_FIMV_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_3       0xF72C
-#define S5P_FIMV_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_4       0xF730
-#define S5P_FIMV_D_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_5       0xF734
-
-#define S5P_FIMV_D_BLACK_BAR_START_POS                         0xF738
-#define S5P_FIMV_D_BLACK_BAR_IMAGE_SIZE                                0xF73C
-
-#define S5P_FIMV_D_DISPLAY_LUMA_ADDR                           0xF60C
-#define S5P_FIMV_D_DISPLAY_CHROMA_ADDR                         0xF610
-
-#define S5P_FIMV_D_DECODED_LUMA_ADDR                           0xF648
-#define S5P_FIMV_D_DECODED_CHROMA_ADDR                         0xF64C
-
-/* Encoder Registers */
-#define S5P_FIMV_E_CROPPED_FRAME_WIDTH                         0xF778
-#define S5P_FIMV_E_CROPPED_FRAME_HEIGHT                                0xF77C
-#define S5P_FIMV_E_FRAME_CROP_OFFSET                           0xF780
-#define S5P_FIMV_E_ENC_OPTIONS                                 0xF784
-#define S5P_FIMV_E_PICTURE_PROFILE                             0xF788
-#define S5P_FIMV_E_VBV_BUFFER_SIZE                             0xF78C
-#define S5P_FIMV_E_VBV_INIT_DELAY                              0xF790
-#define S5P_FIMV_E_FIXED_PICTURE_QP                            0xF794
-#define S5P_FIMV_E_RC_CONFIG                                   0xF798
-#define S5P_FIMV_E_RC_QP_BOUND                                 0xF79C
-#define S5P_FIMV_E_RC_QP_BOUND_PB                              0xF7A0
-#define S5P_FIMV_E_RC_MODE                                     0xF7A4
-
-#define S5P_FIMV_E_MB_RC_CONFIG                                        0xF7A8
-#define S5P_FIMV_E_PADDING_CTRL                                        0xF7AC
-#define S5P_FIMV_E_AIR_THRESHOLD                               0xF7B0
-
-#define S5P_FIMV_E_MV_HOR_RANGE                                        0xF7B4
-#define S5P_FIMV_E_MV_VER_RANGE                                        0xF7B8
-
-#define S5P_FIMV_E_HIGH_QUALITY_MODE                           0xF7C0
-#define S5P_FIMV_E_VIDEO_SIGNAL_TYPE                           0xF7C4
-
-#define S5P_FIMV_E_SAO_WEIGHT0                                 0xF7C8
-#define S5P_FIMV_E_SAO_WEIGHT1                                 0xF7CC
-
-#define S5P_FIMV_E_NUM_DPB                                     0xF890
-#define S5P_FIMV_E_MIN_SCRATCH_BUFFER_SIZE                     0xF894
-
-#define S5P_FIMV_E_LUMA_DPB                                    0xF8C0
-#define S5P_FIMV_E_CHROMA_DPB                                  0xF904
-#define S5P_FIMV_E_ME_BUFFER                                   0xF948
-
-#define S5P_FIMV_E_SCRATCH_BUFFER_ADDR                         0xF98C
-#define S5P_FIMV_E_SCRATCH_BUFFER_SIZE                         0xF990
-#define S5P_FIMV_E_TMV_BUFFER0                                 0xF994
-#define S5P_FIMV_E_TMV_BUFFER1                                 0xF998
-#define S5P_FIMV_E_IR_BUFFER_ADDR                              0xF99C
-#define S5P_FIMV_E_SOURCE_FIRST_2BIT_ADDR                      0xF9D0
-#define S5P_FIMV_E_SOURCE_SECOND_2BIT_ADDR                     0xF9D4
-#define S5P_FIMV_E_SOURCE_FIRST_2BIT_STRIDE                    0xF9D8
-#define S5P_FIMV_E_SOURCE_SECOND_2BIT_STRIDE                   0xF9DC
-#define S5P_FIMV_E_SOURCE_FIRST_ADDR                           0xF9E0
-#define S5P_FIMV_E_SOURCE_SECOND_ADDR                          0xF9E4
-#define S5P_FIMV_E_SOURCE_THIRD_ADDR                           0xF9E8
-#define S5P_FIMV_E_SOURCE_FIRST_STRIDE                         0xF9EC
-#define S5P_FIMV_E_SOURCE_SECOND_STRIDE                                0xF9F0
-#define S5P_FIMV_E_SOURCE_THIRD_STRIDE                         0xF9F4
-#define S5P_FIMV_E_STREAM_BUFFER_ADDR                          0xF9F8
-#define S5P_FIMV_E_STREAM_BUFFER_SIZE                          0xF9FC
-#define S5P_FIMV_E_ROI_BUFFER_ADDR                             0xFA00
-
-#define S5P_FIMV_E_PARAM_CHANGE                                        0xFA04
-#define S5P_FIMV_E_IR_SIZE                                     0xFA08
-#define S5P_FIMV_E_GOP_CONFIG                                  0xFA0C
-#define S5P_FIMV_E_MSLICE_MODE                                 0xFA10
-#define S5P_FIMV_E_MSLICE_SIZE_MB                              0xFA14
-#define S5P_FIMV_E_MSLICE_SIZE_BITS                            0xFA18
-#define S5P_FIMV_E_FRAME_INSERTION                             0xFA1C
-
-#define S5P_FIMV_E_RC_FRAME_RATE                               0xFA20
-#define S5P_FIMV_E_RC_BIT_RATE                                 0xFA24
-#define S5P_FIMV_E_RC_ROI_CTRL                                 0xFA2C
-#define S5P_FIMV_E_PICTURE_TAG                                 0xFA30
-#define S5P_FIMV_E_BIT_COUNT_ENABLE                            0xFA34
-#define S5P_FIMV_E_MAX_BIT_COUNT                               0xFA38
-#define S5P_FIMV_E_MIN_BIT_COUNT                               0xFA3C
-
-#define S5P_FIMV_E_METADATA_BUFFER_ADDR                                0xFA40
-#define S5P_FIMV_E_METADATA_BUFFER_SIZE                                0xFA44
-
-#define S5P_FIMV_E_ENCODING_ORDER_TIME_INFO                    0xFA50
-#define S5P_FIMV_E_ENCODING_ORDER_INFO                         0xFA54
-#define S5P_FIMV_E_STREAM_BUFFER_OFFSET                                0xFA58
-#define S5P_FIMV_E_GOP_CONFIG2                                 0xFA5C
-#define S5P_FIMV_E_WEIGHT_FOR_WEIGHTED_PREDICTION              0xFA60
-
-#define S5P_FIMV_E_ENCODED_SOURCE_FIRST_ADDR                   0xFA70
-#define S5P_FIMV_E_ENCODED_SOURCE_SECOND_ADDR                  0xFA74
-#define S5P_FIMV_E_ENCODED_SOURCE_THIRD_ADDR                   0xFA78
-
-#define S5P_FIMV_E_STREAM_SIZE                                 0xFA80
-#define S5P_FIMV_E_SLICE_TYPE                                  0xFA84
-#define S5P_FIMV_E_PICTURE_COUNT                               0xFA88
-#define S5P_FIMV_E_RET_PICTURE_TAG                             0xFA8C
-
-#define S5P_FIMV_E_RECON_LUMA_DPB_ADDR                         0xFA9C
-#define S5P_FIMV_E_RECON_CHROMA_DPB_ADDR                       0xFAA0
-#define S5P_FIMV_E_METADATA_ADDR_ENC_SLICE                     0xFAA4
-#define S5P_FIMV_E_METADATA_SIZE_ENC_SLICE                     0xFAA8
-
-#define S5P_FIMV_E_NAL_DONE_INFO                               0xFAEC
-
-#define S5P_FIMV_E_MPEG4_OPTIONS                               0xFB10
-#define S5P_FIMV_E_MPEG4_HEC_PERIOD                            0xFB14
-
-#define S5P_FIMV_E_BPG_OPTIONS                                 0xFB1C
-#define S5P_FIMV_E_BPG_EXT_CTB_QP_CTRL                         0xFB20
-#define S5P_FIMV_E_BPG_CHROMA_QP_OFFSET                                0xFB24
-#define S5P_FIMV_E_BPG_EXTENSION_DATA_SIZE                     0xFB28
-
-#define S5P_FIMV_E_H264_HD_SVC_EXTENSION_0                     0xFB44
-#define S5P_FIMV_E_H264_HD_SVC_EXTENSION_1                     0xFB48
-#define S5P_FIMV_E_ASPECT_RATIO                                        0xFB4C
-#define S5P_FIMV_E_EXTENDED_SAR                                        0xFB50
-
-#define S5P_FIMV_E_H264_OPTIONS                                        0xFB54
-#define S5P_FIMV_E_H264_OPTIONS_2                              0xFB58
-#define S5P_FIMV_E_H264_LF_ALPHA_OFFSET                                0xFB5C
-#define S5P_FIMV_E_H264_LF_BETA_OFFSET                         0xFB60
-#define S5P_FIMV_E_H264_REFRESH_PERIOD                         0xFB64
-
-#define S5P_FIMV_E_H264_FMO_SLICE_GRP_MAP_TYPE                 0xFB68
-#define S5P_FIMV_E_H264_FMO_NUM_SLICE_GRP_MINUS1               0xFB6C
-#define S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_DIR               0xFB70
-#define S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_RATE_MINUS1       0xFB74
-#define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_0                        0xFB78
-#define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_1                        0xFB7C
-#define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_2                        0xFB80
-#define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_3                        0xFB84
-
-#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_0                      0xFB88
-#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_1                      0xFB8C
-#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_2                      0xFB90
-#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_3                      0xFB94
-#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_4                      0xFB98
-#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_5                      0xFB9C
-#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_6                      0xFBA0
-#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_7                      0xFBA4
-#define S5P_FIMV_E_H264_CHROMA_QP_OFFSET                       0xFBA8
-
-#define S5P_FIMV_E_NUM_T_LAYER                                 0xFBAC
-#define S5P_FIMV_E_HIERARCHICAL_QP_LAYER0                      0xFBB0
-#define S5P_FIMV_E_HIERARCHICAL_QP_LAYER1                      0xFBB4
-#define S5P_FIMV_E_HIERARCHICAL_QP_LAYER2                      0xFBB8
-#define S5P_FIMV_E_HIERARCHICAL_QP_LAYER3                      0xFBBC
-#define S5P_FIMV_E_HIERARCHICAL_QP_LAYER4                      0xFBC0
-#define S5P_FIMV_E_HIERARCHICAL_QP_LAYER5                      0xFBC4
-#define S5P_FIMV_E_HIERARCHICAL_QP_LAYER6                      0xFBC8
-
-/* For backward compatibility */
-#define S5P_FIMV_E_H264_FRAME_PACKING_SEI_INFO                 0xFC4C
-
-#define S5P_FIMV_E_H264_NAL_CONTROL                            0xFD14
-#define S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER0                        0xFD18
-#define S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER1                        0xFD1C
-#define S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER2                        0xFD20
-#define S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER3                        0xFD24
-#define S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER4                        0xFD28
-#define S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER5                        0xFD2C
-#define S5P_FIMV_E_HIERARCHICAL_BIT_RATE_LAYER6                        0xFD30
-
-#define S5P_FIMV_E_MVC_FRAME_QP_VIEW1                          0xFD40
-#define S5P_FIMV_E_MVC_RC_FRAME_RATE_VIEW1                     0xFD44
-#define S5P_FIMV_E_MVC_RC_BIT_RATE_VIEW1                       0xFD48
-#define S5P_FIMV_E_MVC_RC_QBOUND_VIEW1                         0xFD4C
-#define S5P_FIMV_E_MVC_RC_MODE_VIEW1                           0xFD50
-#define S5P_FIMV_E_MVC_INTER_VIEW_PREDICTION_ON                        0xFD80
-
-#define S5P_FIMV_E_VP9_OPTION                                  0xFD90
-#define S5P_FIMV_E_VP9_FILTER_OPTION                           0xFD94
-#define S5P_FIMV_E_VP9_GOLDEN_FRAME_OPTION                     0xFD98
-#define S5P_FIMV_E_VP8_OPTION                                  0xFDB0
-#define S5P_FIMV_E_VP8_FILTER_OPTION                           0xFDB4
-#define S5P_FIMV_E_VP8_GOLDEN_FRAME_OPTION                     0xFDB8
-
-#define S5P_FIMV_E_HEVC_OPTIONS_2                              0xFDC4
-
-#define S5P_FIMV_E_HEVC_OPTIONS                                        0xFDD4
-#define S5P_FIMV_E_HEVC_REFRESH_PERIOD                         0xFDD8
-#define S5P_FIMV_E_HEVC_CHROMA_QP_OFFSET                       0xFDDC
-#define S5P_FIMV_E_HEVC_LF_BETA_OFFSET_DIV2                    0xFDE0
-#define S5P_FIMV_E_HEVC_LF_TC_OFFSET_DIV2                      0xFDE4
-#define S5P_FIMV_E_HEVC_NAL_CONTROL                            0xFDE8
-
-#define S5P_FIMV_E_VP8_NAL_CONTROL                             0xFDF0
-#define S5P_FIMV_E_VP9_NAL_CONTROL                             0xFDF4
-#define S5P_FIMV_E_CONTENT_LIGHT_LEVEL_INFO_SEI                        0xFDF8
-#define S5P_FIMV_E_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_0       0xFDFC
-#define S5P_FIMV_E_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_1       0xFE00
-#define S5P_FIMV_E_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_2       0xFE04
-#define S5P_FIMV_E_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_3       0xFE08
-#define S5P_FIMV_E_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_4       0xFE0C
-#define S5P_FIMV_E_MASTERING_DISPLAY_COLOUR_VOLUME_SEI_5       0xFE10
-
-
-#define S5P_FIMV_REG_CLEAR_BEGIN                       0xf000
-#define S5P_FIMV_REG_CLEAR_COUNT                       1024
-
-
-/* Bit Definitions */
-/* 0x1100: S5P_FIMV_HOST2RISC_CMD */
-#define S5P_FIMV_H2R_CMD_EMPTY                         0
-#define S5P_FIMV_H2R_CMD_SYS_INIT                      1
-#define S5P_FIMV_H2R_CMD_OPEN_INSTANCE                 2
-#define S5P_FIMV_H2R_CMD_SEQ_HEADER                    3
-#define S5P_FIMV_H2R_CMD_INIT_BUFFERS                  4
-#define S5P_FIMV_H2R_CMD_NAL_START                     5
-#define S5P_FIMV_H2R_CMD_CLOSE_INSTANCE                        6
-#define S5P_FIMV_H2R_CMD_SLEEP                         7
-#define S5P_FIMV_H2R_CMD_WAKEUP                                8
-#define S5P_FIMV_H2R_CMD_LAST_FRAME                    9
-#define S5P_FIMV_H2R_CMD_DPB_FLUSH                     10
-#define S5P_FIMV_H2R_CMD_NAL_ABORT                     11
-#define S5P_FIMV_H2R_CMD_CACHE_FLUSH                   12
-#define S5P_FIMV_H2R_CMD_NAL_QUEUE                     13
-#define S5P_FIMV_H2R_CMD_STOP_QUEUE                    14
-
-
-/* 0x1104: S5P_FIMV_RISC2HOST_CMD */
-#define S5P_FIMV_RISC2HOST_CMD_MASK                    0x1FFFF
-#define S5P_FIMV_R2H_CMD_EMPTY                         0
-#define S5P_FIMV_R2H_CMD_SYS_INIT_RET                  1
-#define S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET             2
-#define S5P_FIMV_R2H_CMD_SEQ_DONE_RET                  3
-#define S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET              4
-#define S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET            6
-#define S5P_FIMV_R2H_CMD_SLEEP_RET                     7
-#define S5P_FIMV_R2H_CMD_WAKEUP_RET                    8
-#define S5P_FIMV_R2H_CMD_COMPLETE_SEQ_RET              9
-#define S5P_FIMV_R2H_CMD_DPB_FLUSH_RET                 10
-#define S5P_FIMV_R2H_CMD_NAL_ABORT_RET                 11
-#define S5P_FIMV_R2H_CMD_FW_STATUS_RET                 12
-#define S5P_FIMV_R2H_CMD_FRAME_DONE_RET                        13
-#define S5P_FIMV_R2H_CMD_FIELD_DONE_RET                        14
-#define S5P_FIMV_R2H_CMD_SLICE_DONE_RET                        15
-#define S5P_FIMV_R2H_CMD_ENC_BUFFER_FULL_RET           16
-#define S5P_FIMV_R2H_CMD_QUEUE_DONE_RET                        17
-#define S5P_FIMV_R2H_CMD_COMPLETE_QUEUE_RET            18
-#define S5P_FIMV_R2H_CMD_CACHE_FLUSH_RET               20
-#define S5P_FIMV_R2H_CMD_ERR_RET                       32
-
-
-/* 0xF000: S5P_FIMV_FW_VERSION */
-#define S5P_FIMV_FW_VER_INFO_MASK                      0xFF
-#define S5P_FIMV_FW_VER_INFO_SHFT                      24
-#define S5P_FIMV_FW_VER_YEAR_MASK                      0xFF
-#define S5P_FIMV_FW_VER_YEAR_SHFT                      16
-#define S5P_FIMV_FW_VER_MONTH_MASK                     0xFF
-#define S5P_FIMV_FW_VER_MONTH_SHFT                     8
-#define S5P_FIMV_FW_VER_DATE_MASK                      0xFF
-#define S5P_FIMV_FW_VER_DATE_SHFT                      0
-#define S5P_FIMV_FW_VER_ALL_MASK                       0xFFFFFF
-#define S5P_FIMV_FW_VER_ALL_SHFT                       0
-
-
-/* 0xF00C: S5P_FIMV_CODEC_TYPE */
-#define MFC_FORMATS_NO_CODEC                           -1
-/* Decoder */
-#define S5P_FIMV_CODEC_H264_DEC                                0
-#define S5P_FIMV_CODEC_H264_MVC_DEC                    1
-#define S5P_FIMV_CODEC_MPEG4_DEC                       3
-#define S5P_FIMV_CODEC_FIMV1_DEC                       4
-#define S5P_FIMV_CODEC_FIMV2_DEC                       5
-#define S5P_FIMV_CODEC_FIMV3_DEC                       6
-#define S5P_FIMV_CODEC_FIMV4_DEC                       7
-#define S5P_FIMV_CODEC_H263_DEC                                8
-#define S5P_FIMV_CODEC_VC1_RCV_DEC                     9
-#define S5P_FIMV_CODEC_VC1_DEC                         10
-#define S5P_FIMV_CODEC_MPEG2_DEC                       13
-#define S5P_FIMV_CODEC_VP8_DEC                         14
-#define S5P_FIMV_CODEC_HEVC_DEC                                17
-#define S5P_FIMV_CODEC_VP9_DEC                         18
-/* Encoder */
-#define S5P_FIMV_CODEC_H264_ENC                                20
-#define S5P_FIMV_CODEC_H264_MVC_ENC                    21
-#define S5P_FIMV_CODEC_MPEG4_ENC                       23
-#define S5P_FIMV_CODEC_H263_ENC                                24
-#define S5P_FIMV_CODEC_VP8_ENC                         25
-#define S5P_FIMV_CODEC_HEVC_ENC                                26
-#define S5P_FIMV_CODEC_VP9_ENC                         27
-
-#define S5P_FIMV_CODEC_BPG_DEC                         32
-#define S5P_FIMV_CODEC_BPG_ENC                         33
-
-/* 0xF028: S5P_FIMV_MFC_VERSION */
-#define S5P_FIMV_MFC_VER_MASK                          0xFFFFFFFF
-#define S5P_FIMV_MFC_VER_SHFT                          0
-
-
-/* 0xF074: S5P_FIMV_ERROR_CODE */
-#define S5P_FIMV_ERR_STATUS_MASK                       0xFFFF
-#define S5P_FIMV_ERR_STATUS_SHIFT                      0
-#define S5P_FIMV_WARN_STATUS_MASK                      0xFFFF
-#define S5P_FIMV_WARN_STATUS_SHIFT                     16
-/* Error number */
-#define S5P_FIMV_ERR_BUFFER_FULL                       18
-#define S5P_FIMV_ERR_NO_AVAILABLE_DPB                  33
-#define S5P_FIMV_ERR_NO_KEY_FRAME                      34
-#define S5P_FIMV_ERR_VPS_ONLY_ERROR                    42
-#define S5P_FIMV_ERR_INSUFFICIENT_DPB_SIZE             57
-#define S5P_FIMV_ERR_INSUFFICIENT_NUM_DPB              58
-#define S5P_FIMV_ERR_INSUFFICIENT_MV_BUF_SIZE          60
-#define S5P_FIMV_ERR_NULL_SCRATCH                      61
-#define S5P_FIMV_ERR_INSUFFICIENT_SCRATCH_BUF_SIZE     62
-
-#define S5P_FIMV_ERR_UNSUPPORTED_FEATURE               100
-#define S5P_FIMV_ERR_UNSUPPORTED_RESOLUTION            101
-#define S5P_FIMV_ERR_HEADER_NOT_FOUND                  102
-#define S5P_FIMV_ERR_INVAILD_NAL_TYPE                  103
-#define S5P_FIMV_ERR_SEQUENCE_HEADER                   104
-#define S5P_FIMV_ERR_MFC_TIMEOUT                       140
-#define S5P_FIMV_ERR_TS_MUX_TIMEOUT                    141
-#define S5P_FIMV_ERR_G2D_TIMEOUT                       142
-#define S5P_FIMV_ERR_FRAME_CONCEAL                     150
-#define S5P_FIMV_ERR_WARNINGS_START                    160
-#define S5P_FIMV_ERR_BROKEN_LINK                       161
-#define S5P_FIMV_ERR_SYNC_POINT_NOT_RECEIVED           190
-#define S5P_FIMV_ERR_NON_PAIRED_FIELD                  191
-#define S5P_FIMV_ERR_WARNINGS_END                      222
-
-
-/* 0xF0B4: S5P_FIMV_D_DEC_OPTIONS */
-#define S5P_FIMV_D_DEC_OPT_DISPLAY_DELAY_EN_SHIFT      3
-#define S5P_FIMV_D_DEC_OPT_FMO_ASO_CTRL_MASK           0x1
-#define S5P_FIMV_D_DEC_OPT_FMO_ASO_CTRL_SHIFT          4
-#define S5P_FIMV_D_DEC_OPT_IDR_DECODING_MASK           0x1
-#define S5P_FIMV_D_DEC_OPT_IDR_DECODING_SHIFT          6
-#define S5P_FIMV_D_DEC_OPT_DISCARD_RCV_HEADER_SHIFT    7
-#define S5P_FIMV_D_DEC_OPT_CONCEAL_CONTROL_SHIFT       8
-#define S5P_FIMV_D_DEC_OPT_PARALLEL_DISABLE_SHIFT      11
-#define S5P_FIMV_D_DEC_OPT_REALLOC_CONTROL_SHIFT       13
-#define S5P_FIMV_D_DEC_OPT_SPECIAL_PARSING_SHIFT       15
-#define S5P_FIMV_D_DEC_OPT_THUMBNAIL_DECODING          16
-
-
-/* 0xF0C4: S5P_FIMV_D_SEI_ENABLE */
-#define S5P_FIMV_D_SEI_ENABLE_NEED_INIT_BUFFER_SHIFT   1
-#define S5P_FIMV_D_SEI_ENABLE_RECOVERY_PARSING_SHIFT   2
-#define S5P_FIMV_D_SEI_ENABLE_CONTENT_LIGHT_SHIFT      4
-#define S5P_FIMV_D_SEI_ENABLE_MASTERING_DISPLAY_SHIFT  5
-
-
-/* 0xF154: S5P_FIMV_D_INIT_BUFFER_OPTIONS */
-#define S5P_FIMV_D_INIT_BUF_OPT_LF_CTRL_MASK           0x3
-#define S5P_FIMV_D_INIT_BUF_OPT_LF_CTRL_SHIFT          1
-#define S5P_FIMV_D_INIT_BUF_OPT_DYNAMIC_DPB_SET_SHIFT  3
-#define S5P_FIMV_D_INIT_BUF_OPT_COPY_NOT_CODED_SHIFT   4
-#define S5P_FIMV_D_INIT_BUF_OPT_DITHERING_EN_SHIFT     6
-#define S5P_FIMV_D_INIT_BUF_OPT_STRIDE_SIZE_ALIGN      7
-
-
-/* 0xF5AC: S5P_FIMV_D_NAL_START_OPTIONS */
-#define S5P_FIMV_D_NAL_START_OPT_BLACK_BAR_SHIFT       3
-
-
-/* 0xF608: S5P_FIMV_D_DISPLAY_STATUS */
-#define S5P_FIMV_DISP_STATUS_DISPLAY_STATUS_MASK       0x7
-#define S5P_FIMV_DISP_STATUS_INTERLACE_MASK            0x1
-#define S5P_FIMV_DISP_STATUS_INTERLACE_SHIFT           3
-#define S5P_FIMV_DISP_STATUS_RES_CHANGE_MASK           0x3
-#define S5P_FIMV_DISP_STATUS_RES_CHANGE_SHIFT          4
-#define S5P_FIMV_DISP_STATUS_NEED_DPB_CHANGE_MASK      0x1
-#define S5P_FIMV_DISP_STATUS_NEED_DPB_CHANGE_SHIFT     9
-#define S5P_FIMV_DISP_STATUS_NEED_SCRATCH_CHANGE_MASK  0x1
-#define S5P_FIMV_DISP_STATUS_NEED_SCRATCH_CHANGE_SHIFT 10
-#define S5P_FIMV_DISP_STATUS_NEED_EMPTY_DPB_MASK       0x1
-#define S5P_FIMV_DISP_STATUS_NEED_EMPTY_DPB_SHIFT      12
-#define S5P_FIMV_DISP_STATUS_BLACK_BAR_DETECT_MASK     0x3
-#define S5P_FIMV_DISP_STATUS_BLACK_BAR_DETECT_SHIFT    13
-#define S5P_FIMV_DISP_STATUS_NOT_DETECTED              0x0
-#define S5P_FIMV_DISP_STATUS_BLACK_BAR                 0x1
-#define S5P_FIMV_DISP_STATUS_BLACK_SCREEN              0x2
-
-
-/* 0xF618: S5P_FIMV_D_DISPLAY_FRAME_TYPE */
-#define S5P_FIMV_DISPLAY_FRAME_MASK                    0x7
-#define S5P_FIMV_DISPLAY_TEMP_INFO_MASK                        0x1
-#define S5P_FIMV_DISPLAY_TEMP_INFO_SHIFT               7
-#define S5P_FIMV_DISPLAY_FRAME_NOT_CODED               0
-#define S5P_FIMV_DISPLAY_FRAME_I                       1
-#define S5P_FIMV_DISPLAY_FRAME_P                       2
-#define S5P_FIMV_DISPLAY_FRAME_B                       3
-
-
-/* 0xF61C: S5P_FIMV_D_DISPLAY_CROP_INFO1 */
-#define S5P_FIMV_D_SHARED_CROP_LEFT_MASK               0xFFFF
-#define S5P_FIMV_D_SHARED_CROP_RIGHT_SHIFT             16
-
-
-/* 0xF620: S5P_FIMV_D_DISPLAY_CROP_INFO2 */
-#define S5P_FIMV_D_SHARED_CROP_TOP_MASK                        0xFFFF
-#define S5P_FIMV_D_SHARED_CROP_BOTTOM_SHIFT            16
-
-
-/* 0xF644: S5P_FIMV_D_DECODED_STATUS */
-#define S5P_FIMV_DEC_STATUS_DECODED_STATUS_MASK                0x7
-#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_NUM_OF_TILE_MASK           0xF
-#define S5P_FIMV_DEC_STATUS_NUM_OF_TILE_SHIFT          15
-
-
-/* 0xF654: S5P_FIMV_D_DECODED_FRAME_TYPE */
-#define S5P_FIMV_DECODED_FRAME_MASK                    0x7
-#define S5P_FIMV_DECODED_FRAME_NOT_CODED               0
-#define S5P_FIMV_DECODED_FRAME_I                       1
-#define S5P_FIMV_DECODED_FRAME_P                       2
-#define S5P_FIMV_DECODED_FRAME_B                       3
-
-
-/* 0xF660: S5P_FIMV_D_DECODED_PICTURE_PROFILE */
-#define S5P_FIMV_D_DECODED_PIC_PROFILE_MASK            0x1F
-#define S5P_FIMV_D_BIT_DEPTH_CHROMA_MINUS8_MASK                0x7
-#define S5P_FIMV_D_BIT_DEPTH_CHROMA_MINUS8_SHIFT       19
-#define S5P_FIMV_D_BIT_DEPTH_LUMA_MINUS8_MASK          0x7
-#define S5P_FIMV_D_BIT_DEPTH_LUMA_MINUS8_SHIFT         16
-#define S5P_FIMV_D_PROFILE_HEVC_MAIN                   1
-#define S5P_FIMV_D_PROFILE_HEVC_MAIN_10                        2
-#define S5P_FIMV_D_PROFILE_HEVC_RANGE_EXT              4
-
-
-/* 0xF684: S5P_FIMV_D_CHROMA_FORMAT */
-#define S5P_FIMV_D_CHROMA_FORMAT_MASK                  0x3
-#define S5P_FIMV_D_COLOR_RANGE_MASK                    0x1
-#define S5P_FIMV_D_COLOR_RANGE_SHIFT                   3
-#define S5P_FIMV_D_COLOR_SPACE_MASK                    0xF
-#define S5P_FIMV_D_COLOR_SPACE_SHIFT                   4
-#define S5P_FIMV_D_COLOR_UNKNOWN                       0
-#define S5P_FIMV_D_CHROMA_400                          0
-#define S5P_FIMV_D_CHROMA_420                          1
-#define S5P_FIMV_D_CHROMA_422                          2
-#define S5P_FIMV_D_CHROMA_444                          3
-
-
-/* 0xF690: S5P_FIMV_D_H264_INFO */
-#define S5P_FIMV_D_H264_INFO_MBAFF_FRAME_FLAG_SHIFT    9
-#define S5P_FIMV_D_H264_INFO_MBAFF_FRAME_FLAG_MASK     0x1
-
-
-/* 0xF6D8: S5P_FIMV_D_MVC_VIEW_ID */
-#define S5P_FIMV_D_MVC_VIEW_ID_DISP_MASK               0xFFFF
-
-
-/* 0xF6DC: S5P_FIMV_D_SEI_AVAIL */
-#define S5P_FIMV_D_SEI_AVAIL_FRAME_PACK_MASK           0x1
-#define S5P_FIMV_D_SEI_AVAIL_CONTENT_LIGHT_MASK                0x1
-#define S5P_FIMV_D_SEI_AVAIL_CONTENT_LIGHT_SHIFT       1
-#define S5P_FIMV_D_SEI_AVAIL_MASTERING_DISPLAY_MASK    0x1
-#define S5P_FIMV_D_SEI_AVAIL_MASTERING_DISPLAY_SHIFT   2
-
-
-/* 0xF70C: S5P_FIMV_D_VIDEO_SIGNAL_TYPE */
-#define S5P_FIMV_D_VIDEO_SIGNAL_TYPE_FLAG_MASK         0x1
-#define S5P_FIMV_D_VIDEO_SIGNAL_TYPE_FLAG_SHIFT                29
-#define S5P_FIMV_D_COLOUR_DESCRIPTION_FLAG_MASK                0x1
-#define S5P_FIMV_D_COLOUR_DESCRIPTION_FLAG_SHIFT       24
-
-
-/* 0xF738: S5P_FIMV_D_BLACK_BAR_START_POS */
-#define S5P_FIMV_D_BLACK_BAR_START_X_SHIFT             0
-#define S5P_FIMV_D_BLACK_BAR_START_X_MASK              0xFFFF
-#define S5P_FIMV_D_BLACK_BAR_START_Y_SHIFT             16
-#define S5P_FIMV_D_BLACK_BAR_START_Y_MASK              0xFFFF
-
-
-/* 0xF73C: S5P_FIMV_D_BLACK_BAR_IMAGE_SIZE */
-#define S5P_FIMV_D_BLACK_BAR_IMAGE_W_SHIFT             0
-#define S5P_FIMV_D_BLACK_BAR_IMAGE_W_MASK              0xFFFF
-#define S5P_FIMV_D_BLACK_BAR_IMAGE_H_SHIFT             16
-#define S5P_FIMV_D_BLACK_BAR_IMAGE_H_MASK              0xFFFF
-
-
-/* 0xF780:  S5P_FIMV_E_FRAME_CROP_OFFSET */
-#define S5P_FIMV_E_FRAME_CROP_OFFSET_TOP               16
-#define S5P_FIMV_E_FRAME_CROP_OFFSET_LEFT              0
-#define S5P_FIMV_E_FRAME_CROP_OFFSET_MASK              0x3FFF
-
-
-/* 0xF788: S5P_FIMV_E_PICTURE_PROFILE */
-#define S5P_FIMV_E_PROFILE_H264_BASELINE               0
-#define S5P_FIMV_E_PROFILE_H264_MAIN                   1
-#define S5P_FIMV_E_PROFILE_H264_HIGH                   2
-#define S5P_FIMV_E_PROFILE_H264_CONSTRAINED_BASELINE   3
-#define S5P_FIMV_E_PROFILE_H264_CONSTRAINED_HIGH       5
-#define S5P_FIMV_E_PROFILE_MPEG4_SIMPLE                        0
-#define S5P_FIMV_E_PROFILE_MPEG4_ADVANCED_SIMPLE       1
-#define S5P_FIMV_E_PROFILE_HEVC_MAIN_422_10_INTRA      2
-#define S5P_FIMV_E_PROFILE_HEVC_MAIN_10                        3
-#define S5P_FIMV_E_PROFILE_HEVC_MAIN_422_10            4
-#define S5P_FIMV_E_PROFILE_VP9_PROFILE0                        0
-#define S5P_FIMV_E_PROFILE_VP9_PROFILE1                        1
-#define S5P_FIMV_E_PROFILE_VP9_PROFILE2                        2
-#define S5P_FIMV_E_PROFILE_VP9_PROFILE3                        3
-
-
-/* 0xF7A4: S5P_FIMV_E_RC_MODE */
-#define S5P_FIMV_E_RC_CBR_FIX                          0
-#define S5P_FIMV_E_RC_CBR_VAR                          1
-#define S5P_FIMV_E_RC_VBR                              2
-#define S5P_FIMV_E_RC_CBR_I_LIMIT                      3
-
-
-/* 0xFA84: S5P_FIMV_E_SLICE_TYPE */
-#define S5P_FIMV_E_SLICE_TYPE_NOT_CODED                        0
-#define S5P_FIMV_E_SLICE_TYPE_I                                1
-#define S5P_FIMV_E_SLICE_TYPE_P                                2
-#define S5P_FIMV_E_SLICE_TYPE_B                                3
-#define S5P_FIMV_E_SLICE_TYPE_SKIPPED                  4
-
-
-#endif /* __REGS_MFC_V10_H */
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_sync.c b/drivers/media/platform/exynos/mfc/s5p_mfc_sync.c
deleted file mode 100644 (file)
index 978f91c..0000000
+++ /dev/null
@@ -1,342 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_intr.c
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include "s5p_mfc_sync.h"
-
-#include "s5p_mfc_cal.h"
-#include "s5p_mfc_perf_measure.h"
-
-#include "s5p_mfc_queue.h"
-
-#define R2H_BIT(x)     (((x) > 0) ? (1 << ((x) - 1)) : 0)
-
-static inline unsigned int mfc_r2h_bit_mask(int cmd)
-{
-       unsigned int mask = R2H_BIT(cmd);
-
-       if (cmd == S5P_FIMV_R2H_CMD_FRAME_DONE_RET)
-               mask |= (R2H_BIT(S5P_FIMV_R2H_CMD_FIELD_DONE_RET) |
-                        R2H_BIT(S5P_FIMV_R2H_CMD_COMPLETE_SEQ_RET) |
-                        R2H_BIT(S5P_FIMV_R2H_CMD_SLICE_DONE_RET) |
-                        R2H_BIT(S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET) |
-                        R2H_BIT(S5P_FIMV_R2H_CMD_ENC_BUFFER_FULL_RET));
-       /* FIXME: Temporal mask for S3D SEI processing */
-       else if (cmd == S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET)
-               mask |= (R2H_BIT(S5P_FIMV_R2H_CMD_FIELD_DONE_RET) |
-                        R2H_BIT(S5P_FIMV_R2H_CMD_SLICE_DONE_RET) |
-                        R2H_BIT(S5P_FIMV_R2H_CMD_FRAME_DONE_RET));
-
-       return (mask |= R2H_BIT(S5P_FIMV_R2H_CMD_ERR_RET));
-}
-
-#define wait_condition(x, c) (x->int_condition &&              \
-               (R2H_BIT(x->int_reason) & mfc_r2h_bit_mask(c)))
-#define is_err_cond(x) ((x->int_condition) && (x->int_reason == S5P_FIMV_R2H_CMD_ERR_RET))
-
-/*
- * Return value description
- * 0: waked up before timeout
- * 1: failed to get the response for the command before timeout
-*/
-int s5p_mfc_wait_for_done_dev(struct s5p_mfc_dev *dev, int command)
-{
-       int ret;
-
-       ret = wait_event_timeout(dev->cmd_wq,
-                       wait_condition(dev, command),
-                       msecs_to_jiffies(MFC_INT_TIMEOUT));
-       if (ret == 0) {
-               mfc_err_dev("Interrupt (dev->int_reason:%d, command:%d) timed out\n",
-                                                       dev->int_reason, command);
-               if (s5p_mfc_check_risc2host(dev)) {
-                       ret = wait_event_timeout(dev->cmd_wq,
-                                       wait_condition(dev, command),
-                                       msecs_to_jiffies(MFC_INT_TIMEOUT * MFC_INT_TIMEOUT_CNT));
-                       if (ret == 0) {
-                               mfc_err_dev("Timeout: MFC driver waited for upward of %dsec\n",
-                                               3 * MFC_INT_TIMEOUT);
-                       } else {
-                               goto wait_done;
-                       }
-               }
-               call_dop(dev, dump_and_stop_debug_mode, dev);
-               return 1;
-       }
-
-wait_done:
-       mfc_debug(2, "Finished waiting (dev->int_reason:%d, command: %d)\n",
-                                                       dev->int_reason, command);
-       return 0;
-}
-
-/*
- * Return value description
- *  0: waked up before timeout
- *  1: failed to get the response for the command before timeout
- * -1: got the error response for the command before timeout
-*/
-int s5p_mfc_wait_for_done_ctx(struct s5p_mfc_ctx *ctx, int command)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       int ret;
-       unsigned int timeout = MFC_INT_TIMEOUT;
-
-       if (command == S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET)
-               timeout = MFC_INT_SHORT_TIMEOUT;
-
-       ret = wait_event_timeout(ctx->cmd_wq,
-                       wait_condition(ctx, command),
-                       msecs_to_jiffies(timeout));
-       if (ret == 0) {
-               mfc_err_ctx("Interrupt (ctx->int_reason:%d, command:%d) timed out\n",
-                                                       ctx->int_reason, command);
-               if (s5p_mfc_check_risc2host(dev)) {
-                       ret = wait_event_timeout(ctx->cmd_wq,
-                                       wait_condition(ctx, command),
-                                       msecs_to_jiffies(MFC_INT_TIMEOUT * MFC_INT_TIMEOUT_CNT));
-                       if (ret == 0) {
-                               mfc_err_dev("Timeout: MFC driver waited for upward of %dsec\n",
-                                               3 * MFC_INT_TIMEOUT);
-                       } else {
-                               goto wait_done;
-                       }
-               }
-               call_dop(dev, dump_and_stop_debug_mode, dev);
-               return 1;
-       }
-
-wait_done:
-       if (is_err_cond(ctx)) {
-               mfc_err_ctx("Finished (ctx->int_reason:%d, command: %d)\n",
-                               ctx->int_reason, command);
-               mfc_err_ctx("But error (ctx->int_err:%d)\n", ctx->int_err);
-               call_dop(dev, dump_and_stop_debug_mode, dev);
-               return -1;
-       }
-
-       mfc_debug(2, "Finished waiting (ctx->int_reason:%d, command: %d)\n",
-                                                       ctx->int_reason, command);
-       return 0;
-}
-
-/* Wake up device wait_queue */
-void s5p_mfc_wake_up_dev(struct s5p_mfc_dev *dev, unsigned int reason,
-               unsigned int err)
-{
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return;
-       }
-
-       dev->int_condition = 1;
-       dev->int_reason = reason;
-       dev->int_err = err;
-       wake_up(&dev->cmd_wq);
-}
-
-/* Wake up context wait_queue */
-void s5p_mfc_wake_up_ctx(struct s5p_mfc_ctx *ctx, unsigned int reason,
-               unsigned int err)
-{
-       if (!ctx) {
-               mfc_err_dev("no mfc context to run\n");
-               return;
-       }
-
-       ctx->int_condition = 1;
-       ctx->int_reason = reason;
-       ctx->int_err = err;
-       wake_up(&ctx->cmd_wq);
-}
-
-int s5p_mfc_get_new_ctx(struct s5p_mfc_dev *dev)
-{
-       unsigned long wflags;
-       int new_ctx_index = 0;
-       int cnt = 0;
-       int i;
-
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return -EINVAL;
-       }
-
-       spin_lock_irqsave(&dev->work_bits.lock, wflags);
-
-       mfc_debug(2, "Previous context: %d (bits %08lx)\n", dev->curr_ctx,
-                                                       dev->work_bits.bits);
-
-       if (dev->preempt_ctx > MFC_NO_INSTANCE_SET) {
-               new_ctx_index = dev->preempt_ctx;
-               mfc_debug(2, "preempt_ctx is : %d\n", new_ctx_index);
-       } else {
-               for (i = 0; i < MFC_NUM_CONTEXTS; i++) {
-                       if (dev->ctx[i] && dev->ctx[i]->otf_handle) {
-                               if (test_bit(i, &dev->work_bits.bits)) {
-                                       spin_unlock_irqrestore(&dev->work_bits.lock, wflags);
-                                       return i;
-                               }
-                               break;
-                       }
-               }
-
-               new_ctx_index = (dev->curr_ctx + 1) % MFC_NUM_CONTEXTS;
-               while (!test_bit(new_ctx_index, &dev->work_bits.bits)) {
-                       new_ctx_index = (new_ctx_index + 1) % MFC_NUM_CONTEXTS;
-                       cnt++;
-                       if (cnt > MFC_NUM_CONTEXTS) {
-                               /* No contexts to run */
-                               spin_unlock_irqrestore(&dev->work_bits.lock, wflags);
-                               return -EAGAIN;
-                       }
-               }
-       }
-
-       spin_unlock_irqrestore(&dev->work_bits.lock, wflags);
-       return new_ctx_index;
-}
-
-/* Check whether a context should be run on hardware */
-int s5p_mfc_dec_ctx_ready(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-       int src_buf_queue_greater_than_0 = 0;
-       int dst_buf_queue_greater_than_0 = 0;
-       int ref_buf_queue_same_dpb_count_plus_5 = 0;
-
-       mfc_debug(1, "[c:%d] src = %d, dst = %d, src_nal = %d, dst_nal = %d, ref = %d, state = %d, capstat = %d\n",
-                 ctx->num, s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->src_buf_queue),
-                 s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->dst_buf_queue),
-                 s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->src_buf_nal_queue),
-                 s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->dst_buf_nal_queue),
-                 s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->ref_buf_queue),
-                 ctx->state, ctx->capture_state);
-       mfc_debug(2, "wait_state = %d\n", ctx->wait_state);
-
-       src_buf_queue_greater_than_0
-               = s5p_mfc_is_queue_count_greater(&ctx->buf_queue_lock, &ctx->src_buf_queue, 0);
-       dst_buf_queue_greater_than_0
-               = s5p_mfc_is_queue_count_greater(&ctx->buf_queue_lock, &ctx->dst_buf_queue, 0);
-       ref_buf_queue_same_dpb_count_plus_5
-               = s5p_mfc_is_queue_count_same(&ctx->buf_queue_lock, &ctx->ref_buf_queue, (ctx->dpb_count + 5));
-
-       /* If shutdown is called, do not try any cmd */
-       if (dev->shutdown)
-               return 0;
-
-       /* Context is to parse header */
-       if (ctx->state == MFCINST_GOT_INST &&
-               src_buf_queue_greater_than_0)
-               return 1;
-
-       /* Context is to decode a frame */
-       if (ctx->state == MFCINST_RUNNING &&
-               ctx->wait_state == WAIT_NONE && src_buf_queue_greater_than_0 &&
-               (dst_buf_queue_greater_than_0 || ref_buf_queue_same_dpb_count_plus_5))
-               return 1;
-
-       /* Context is to return last frame */
-       if (ctx->state == MFCINST_FINISHING &&
-               (dst_buf_queue_greater_than_0 || ref_buf_queue_same_dpb_count_plus_5))
-               return 1;
-
-       /* Context is to set buffers */
-       if (ctx->state == MFCINST_HEAD_PARSED &&
-               (dst_buf_queue_greater_than_0 && ctx->wait_state == WAIT_NONE))
-               return 1;
-
-       /* Resolution change */
-       if ((ctx->state == MFCINST_RES_CHANGE_INIT || ctx->state == MFCINST_RES_CHANGE_FLUSH) &&
-               dst_buf_queue_greater_than_0)
-               return 1;
-
-       if (ctx->state == MFCINST_RES_CHANGE_END &&
-               src_buf_queue_greater_than_0)
-               return 1;
-
-       s5p_mfc_perf_cancel_drv_margin(dev);
-       mfc_debug(2, "ctx is not ready\n");
-
-       return 0;
-}
-
-int s5p_mfc_enc_ctx_ready(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_enc *enc = ctx->enc_priv;
-       struct s5p_mfc_dev *dev = ctx->dev;
-       struct s5p_mfc_enc_params *p = &enc->params;
-       int src_buf_queue_greater_than_0 = 0;
-       int dst_buf_queue_greater_than_0 = 0;
-
-       mfc_debug(1, "[c:%d] src = %d, dst = %d, src_nal = %d, dst_nal = %d, ref = %d, state = %d\n",
-                 ctx->num, s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->src_buf_queue),
-                 s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->dst_buf_queue),
-                 s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->src_buf_nal_queue),
-                 s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->dst_buf_nal_queue),
-                 s5p_mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->ref_buf_queue),
-                 ctx->state);
-
-       src_buf_queue_greater_than_0
-               = s5p_mfc_is_queue_count_greater(&ctx->buf_queue_lock, &ctx->src_buf_queue, 0);
-       dst_buf_queue_greater_than_0
-               = s5p_mfc_is_queue_count_greater(&ctx->buf_queue_lock, &ctx->dst_buf_queue, 0);
-
-       /* If shutdown is called, do not try any cmd */
-       if (dev->shutdown)
-               return 0;
-
-       /* context is ready to make header */
-       if (ctx->state == MFCINST_GOT_INST &&
-               dst_buf_queue_greater_than_0) {
-               if (p->seq_hdr_mode == V4L2_MPEG_VIDEO_HEADER_MODE_AT_THE_READY) {
-                       if (src_buf_queue_greater_than_0)
-                               return 1;
-               } else {
-                       return 1;
-               }
-       }
-
-       /* context is ready to allocate DPB */
-       if (ctx->state == MFCINST_HEAD_PARSED &&
-               dst_buf_queue_greater_than_0)
-               return 1;
-
-       /* context is ready to encode a frame */
-       if (ctx->state == MFCINST_RUNNING &&
-               src_buf_queue_greater_than_0 && dst_buf_queue_greater_than_0)
-               return 1;
-
-       /* context is ready to encode a frame for NAL_ABORT command */
-       if (ctx->state == MFCINST_ABORT_INST &&
-               src_buf_queue_greater_than_0 && dst_buf_queue_greater_than_0)
-               return 1;
-
-       /* context is ready to encode remain frames */
-       if (ctx->state == MFCINST_FINISHING &&
-               src_buf_queue_greater_than_0 && dst_buf_queue_greater_than_0)
-               return 1;
-
-       s5p_mfc_perf_cancel_drv_margin(dev);
-       mfc_debug(2, "ctx is not ready\n");
-
-       return 0;
-}
-
-int s5p_mfc_ctx_ready(struct s5p_mfc_ctx *ctx)
-{
-       if (ctx->type == MFCINST_DECODER)
-               return s5p_mfc_dec_ctx_ready(ctx);
-       else if (ctx->type == MFCINST_ENCODER)
-               return s5p_mfc_enc_ctx_ready(ctx);
-
-       return 0;
-}
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_sync.h b/drivers/media/platform/exynos/mfc/s5p_mfc_sync.h
deleted file mode 100644 (file)
index c1cce5b..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_intr.h
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __S5P_MFC_INTR_H
-#define __S5P_MFC_INTR_H __FILE__
-
-#include "s5p_mfc_common.h"
-
-#define need_to_dpb_flush(ctx)         \
-       ((ctx->state == MFCINST_FINISHING) ||   \
-         (ctx->state == MFCINST_RUNNING))
-#define need_to_wait_nal_abort(ctx)             \
-       (ctx->state == MFCINST_ABORT_INST)
-#define need_to_continue(ctx)                  \
-       ((ctx->state == MFCINST_DPB_FLUSHING) ||\
-       (ctx->state == MFCINST_ABORT_INST) ||   \
-       (ctx->state == MFCINST_RETURN_INST) ||  \
-       (ctx->state == MFCINST_SPECIAL_PARSING) ||      \
-       (ctx->state == MFCINST_SPECIAL_PARSING_NAL))
-#define need_to_special_parsing(ctx)           \
-       ((ctx->state == MFCINST_GOT_INST) ||    \
-        (ctx->state == MFCINST_HEAD_PARSED))
-#define need_to_special_parsing_nal(ctx)       \
-       (ctx->state == MFCINST_RUNNING)
-#define ready_to_get_crop(ctx)                 \
-       ((ctx->state == MFCINST_HEAD_PARSED) || \
-        (ctx->state == MFCINST_RUNNING) || \
-        (ctx->state == MFCINST_FINISHING))
-
-int s5p_mfc_wait_for_done_dev(struct s5p_mfc_dev *dev, int command);
-int s5p_mfc_wait_for_done_ctx(struct s5p_mfc_ctx *ctx, int command);
-void s5p_mfc_wake_up_dev(struct s5p_mfc_dev *dev, unsigned int reason,
-               unsigned int err);
-void s5p_mfc_wake_up_ctx(struct s5p_mfc_ctx *ctx, unsigned int reason,
-               unsigned int err);
-
-int s5p_mfc_get_new_ctx(struct s5p_mfc_dev *dev);
-int s5p_mfc_dec_ctx_ready(struct s5p_mfc_ctx *ctx);
-int s5p_mfc_enc_ctx_ready(struct s5p_mfc_ctx *ctx);
-int s5p_mfc_ctx_ready(struct s5p_mfc_ctx *ctx);
-
-
-static inline void s5p_mfc_set_bit(int num, struct s5p_mfc_bits *data)
-{
-       unsigned long flags;
-       spin_lock_irqsave(&data->lock, flags);
-       __set_bit(num, &data->bits);
-       spin_unlock_irqrestore(&data->lock, flags);
-}
-
-static inline void s5p_mfc_clear_bit(int num, struct s5p_mfc_bits *data)
-{
-       unsigned long flags;
-       spin_lock_irqsave(&data->lock, flags);
-       __clear_bit(num, &data->bits);
-       spin_unlock_irqrestore(&data->lock, flags);
-}
-
-static inline int s5p_mfc_test_bit(int num, struct s5p_mfc_bits *data)
-{
-       unsigned long flags;
-       int ret;
-       spin_lock_irqsave(&data->lock, flags);
-       ret = test_bit(num, &data->bits);
-       spin_unlock_irqrestore(&data->lock, flags);
-       return ret;
-}
-
-static inline int s5p_mfc_is_all_bits_cleared(struct s5p_mfc_bits *data)
-{
-       unsigned long flags;
-       int ret;
-       spin_lock_irqsave(&data->lock, flags);
-       ret = ((data->bits) == 0) ? 1 : 0;
-       spin_unlock_irqrestore(&data->lock, flags);
-       return ret;
-}
-
-static inline void s5p_mfc_clear_all_bits(struct s5p_mfc_bits *data)
-{
-       unsigned long flags;
-       spin_lock_irqsave(&data->lock, flags);
-       data->bits = 0;
-       spin_unlock_irqrestore(&data->lock, flags);
-}
-
-static inline unsigned long s5p_mfc_get_bits(struct s5p_mfc_bits *data)
-{
-       unsigned long flags;
-       unsigned long ret;
-       spin_lock_irqsave(&data->lock, flags);
-       ret = data->bits;
-       spin_unlock_irqrestore(&data->lock, flags);
-       return ret;
-}
-
-static inline void s5p_mfc_create_bits(struct s5p_mfc_bits *data)
-{
-       spin_lock_init(&data->lock);
-       s5p_mfc_clear_all_bits(data);
-}
-
-static inline void s5p_mfc_delete_bits(struct s5p_mfc_bits *data)
-{
-       s5p_mfc_clear_all_bits(data);
-}
-
-static inline int s5p_mfc_is_work_to_do(struct s5p_mfc_dev *dev)
-{
-       return (!s5p_mfc_is_all_bits_cleared(&dev->work_bits));
-}
-
-#endif /* __S5P_MFC_INTR_H */
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_utils.c b/drivers/media/platform/exynos/mfc/s5p_mfc_utils.c
deleted file mode 100644 (file)
index 7927c42..0000000
+++ /dev/null
@@ -1,553 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_utils.c
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/smc.h>
-
-#include "s5p_mfc_utils.h"
-
-int s5p_mfc_check_vb_with_fmt(struct s5p_mfc_fmt *fmt, struct vb2_buffer *vb)
-{
-       if (!fmt)
-               return -EINVAL;
-
-       if (fmt->mem_planes != vb->num_planes) {
-               mfc_err_dev("plane number is different (%d != %d)\n",
-                               fmt->mem_planes, vb->num_planes);
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-int mfc_stream_buf_prot(struct s5p_mfc_ctx *ctx,
-                               struct s5p_mfc_buf *buf, bool en)
-{
-       return 0;
-}
-
-int mfc_raw_buf_prot(struct s5p_mfc_ctx *ctx,
-                               struct s5p_mfc_buf *buf, bool en)
-{
-       return 0;
-}
-
-void s5p_mfc_raw_protect(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf *mfc_buf,
-                                       int index)
-{
-       if (!test_bit(index, &ctx->raw_protect_flag)) {
-               if (mfc_raw_buf_prot(ctx, mfc_buf, true)) {
-                       mfc_err_ctx("failed to CFW_PROT\n");
-               } else {
-                       set_bit(index, &ctx->raw_protect_flag);
-                       mfc_debug(2, "[index:%d] raw protect, flag: %#lx\n",
-                                       index, ctx->raw_protect_flag);
-               }
-       }
-}
-
-void s5p_mfc_raw_unprotect(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf *mfc_buf,
-                                       int index)
-{
-       if (test_bit(index, &ctx->raw_protect_flag)) {
-               if (mfc_raw_buf_prot(ctx, mfc_buf, false)) {
-                       mfc_err_ctx("failed to CFW_UNPROT\n");
-               } else {
-                       clear_bit(index, &ctx->raw_protect_flag);
-                       mfc_debug(2, "[index:%d] raw unprotect, flag: %#lx\n",
-                                       index, ctx->raw_protect_flag);
-               }
-       }
-}
-
-void s5p_mfc_stream_protect(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf *mfc_buf,
-                                       int index)
-{
-       if (!test_bit(index, &ctx->stream_protect_flag)) {
-               if (mfc_stream_buf_prot(ctx, mfc_buf, true)) {
-                       mfc_err_ctx("failed to CFW_PROT\n");
-               } else {
-                       set_bit(index, &ctx->stream_protect_flag);
-                       mfc_debug(2, "[index:%d] stream protect, flag: %#lx\n",
-                                       index, ctx->stream_protect_flag);
-               }
-       }
-}
-
-void s5p_mfc_stream_unprotect(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf *mfc_buf,
-                                       int index)
-{
-       if (test_bit(index, &ctx->stream_protect_flag)) {
-               if (mfc_stream_buf_prot(ctx, mfc_buf, false)) {
-                       mfc_err_ctx("failed to CFW_UNPROT\n");
-               } else {
-                       clear_bit(index, &ctx->stream_protect_flag);
-                       mfc_debug(2, "[index:%d] stream unprotect, flag: %#lx\n",
-                                       index, ctx->stream_protect_flag);
-               }
-       }
-}
-
-static int mfc_calc_plane(int width, int height, int is_tiled)
-{
-       int mbX, mbY;
-
-       mbX = (width + 15)/16;
-       mbY = (height + 15)/16;
-
-       /* Alignment for interlaced processing */
-       if (is_tiled)
-               mbY = (mbY + 1) / 2 * 2;
-
-       return (mbX * 16) * (mbY * 16);
-}
-
-static void mfc_set_linear_stride_size(struct s5p_mfc_ctx *ctx,
-                               struct s5p_mfc_fmt *fmt)
-{
-       struct s5p_mfc_raw_info *raw;
-       int i;
-
-       raw = &ctx->raw_buf;
-
-       switch (fmt->fourcc) {
-       case V4L2_PIX_FMT_YUV420M:
-       case V4L2_PIX_FMT_YUV420N:
-       case V4L2_PIX_FMT_YVU420M:
-               raw->stride[0] = ALIGN(ctx->img_width, 16);
-               raw->stride[1] = ALIGN(raw->stride[0] >> 1, 16);
-               raw->stride[2] = ALIGN(raw->stride[0] >> 1, 16);
-               break;
-       case V4L2_PIX_FMT_NV12MT_16X16:
-       case V4L2_PIX_FMT_NV12MT:
-       case V4L2_PIX_FMT_NV12M:
-       case V4L2_PIX_FMT_NV12N:
-       case V4L2_PIX_FMT_NV21M:
-       case V4L2_PIX_FMT_NV16M:
-       case V4L2_PIX_FMT_NV61M:
-               raw->stride[0] = ALIGN(ctx->img_width, 16);
-               raw->stride[1] = ALIGN(ctx->img_width, 16);
-               raw->stride[2] = 0;
-               break;
-       case V4L2_PIX_FMT_NV12M_S10B:
-       case V4L2_PIX_FMT_NV12N_10B:
-       case V4L2_PIX_FMT_NV21M_S10B:
-       case V4L2_PIX_FMT_NV16M_S10B:
-       case V4L2_PIX_FMT_NV61M_S10B:
-               raw->stride[0] = S10B_8B_STRIDE(ctx->img_width);
-               raw->stride[1] = S10B_8B_STRIDE(ctx->img_width);
-               raw->stride[2] = 0;
-               raw->stride_2bits[0] = S10B_2B_STRIDE(ctx->img_width);
-               raw->stride_2bits[1] = S10B_2B_STRIDE(ctx->img_width);
-               raw->stride_2bits[2] = 0;
-               break;
-       case V4L2_PIX_FMT_NV12M_P010:
-       case V4L2_PIX_FMT_NV21M_P010:
-       case V4L2_PIX_FMT_NV61M_P210:
-       case V4L2_PIX_FMT_NV16M_P210:
-               raw->stride[0] = ALIGN(ctx->img_width, 16) * 2;
-               raw->stride[1] = ALIGN(ctx->img_width, 16) * 2;
-               raw->stride[2] = 0;
-               raw->stride_2bits[0] = 0;
-               raw->stride_2bits[1] = 0;
-               raw->stride_2bits[2] = 0;
-               break;
-       case V4L2_PIX_FMT_RGB24:
-               ctx->raw_buf.stride[0] = ctx->img_width * 3;
-               ctx->raw_buf.stride[1] = 0;
-               ctx->raw_buf.stride[2] = 0;
-               break;
-       case V4L2_PIX_FMT_RGB565:
-               ctx->raw_buf.stride[0] = ctx->img_width * 2;
-               ctx->raw_buf.stride[1] = 0;
-               ctx->raw_buf.stride[2] = 0;
-               break;
-       case V4L2_PIX_FMT_RGB32X:
-       case V4L2_PIX_FMT_BGR32:
-       case V4L2_PIX_FMT_ARGB32:
-               ctx->raw_buf.stride[0] = (ctx->buf_stride > ctx->img_width) ?
-                       (ALIGN(ctx->img_width, 16) * 4) : (ctx->img_width * 4);
-               ctx->raw_buf.stride[1] = 0;
-               ctx->raw_buf.stride[2] = 0;
-               break;
-       default:
-               break;
-       }
-
-       /* Decoder needs multiple of 16 alignment for stride */
-       if (ctx->type == MFCINST_DECODER) {
-               for (i = 0; i < 3; i++)
-                       ctx->raw_buf.stride[i] =
-                               ALIGN(ctx->raw_buf.stride[i], 16);
-       }
-}
-
-void s5p_mfc_dec_calc_dpb_size(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev;
-       struct s5p_mfc_dec *dec;
-       struct s5p_mfc_raw_info *raw;
-       int i;
-       int extra = MFC_LINEAR_BUF_SIZE;
-
-       if (!ctx) {
-               mfc_err_dev("no mfc context to run\n");
-               return;
-       }
-
-       dev = ctx->dev;
-       raw = &ctx->raw_buf;
-       raw->total_plane_size = 0;
-
-       dec = ctx->dec_priv;
-
-       for (i = 0; i < raw->num_planes; i++) {
-               raw->plane_size[i] = 0;
-               raw->plane_size_2bits[i] = 0;
-       }
-
-       switch (ctx->dst_fmt->fourcc) {
-       case V4L2_PIX_FMT_NV12M_S10B:
-       case V4L2_PIX_FMT_NV21M_S10B:
-               raw->plane_size[0] = NV12M_Y_SIZE(ctx->img_width, ctx->img_height);
-               raw->plane_size[1] = NV12M_CBCR_SIZE(ctx->img_width, ctx->img_height);
-               raw->plane_size_2bits[0] = NV12M_Y_2B_SIZE(ctx->img_width, ctx->img_height);
-               raw->plane_size_2bits[1] = NV12M_CBCR_2B_SIZE(ctx->img_width, ctx->img_height);
-               break;
-       case V4L2_PIX_FMT_NV12M:
-       case V4L2_PIX_FMT_NV21M:
-               raw->plane_size[0] = mfc_calc_plane(ctx->img_width, ctx->img_height, 0) + extra;
-               raw->plane_size[1] = mfc_calc_plane(ctx->img_width, ctx->img_height, 0) / 2 + extra;
-               break;
-       case V4L2_PIX_FMT_NV12M_P010:
-       case V4L2_PIX_FMT_NV21M_P010:
-               raw->plane_size[0] = mfc_calc_plane(ctx->img_width, ctx->img_height, 0) * 2 + extra;
-               raw->plane_size[1] = mfc_calc_plane(ctx->img_width, ctx->img_height, 0) + extra;
-               break;
-       case V4L2_PIX_FMT_YUV420M:
-       case V4L2_PIX_FMT_YVU420M:
-               raw->plane_size[0] = mfc_calc_plane(ctx->img_width, ctx->img_height, 0) + extra;
-               raw->plane_size[1] = mfc_calc_plane(ctx->img_width, ctx->img_height, 0) / 2 + extra;
-               raw->plane_size[2] = mfc_calc_plane(ctx->img_width, ctx->img_height, 0) / 2 + extra;
-               break;
-       case V4L2_PIX_FMT_NV16M_S10B:
-       case V4L2_PIX_FMT_NV61M_S10B:
-               raw->plane_size[0] = NV16M_Y_SIZE(ctx->img_width, ctx->img_height);
-               raw->plane_size[1] = NV16M_CBCR_SIZE(ctx->img_width, ctx->img_height);
-               raw->plane_size_2bits[0] = NV16M_Y_2B_SIZE(ctx->img_width, ctx->img_height);
-               raw->plane_size_2bits[1] = NV16M_CBCR_2B_SIZE(ctx->img_width, ctx->img_height);
-               break;
-       case V4L2_PIX_FMT_NV16M:
-       case V4L2_PIX_FMT_NV61M:
-               raw->plane_size[0] = mfc_calc_plane(ctx->img_width, ctx->img_height, 0) + extra;
-               raw->plane_size[1] = mfc_calc_plane(ctx->img_width, ctx->img_height, 0) + extra;
-               break;
-       case V4L2_PIX_FMT_NV16M_P210:
-       case V4L2_PIX_FMT_NV61M_P210:
-               raw->plane_size[0] = mfc_calc_plane(ctx->img_width, ctx->img_height, 0) * 2 + extra;
-               raw->plane_size[1] = mfc_calc_plane(ctx->img_width, ctx->img_height, 0) * 2 + extra;
-               break;
-       /* non-contiguous single fd format */
-       case V4L2_PIX_FMT_NV12N_10B:
-               raw->plane_size[0] = NV12N_10B_Y_8B_SIZE(ctx->img_width, ctx->img_height);
-               raw->plane_size[1] = NV12N_10B_CBCR_8B_SIZE(ctx->img_width, ctx->img_height);
-               raw->plane_size_2bits[0] = NV12N_10B_Y_2B_SIZE(ctx->img_width, ctx->img_height);
-               raw->plane_size_2bits[1] = NV12N_10B_CBCR_2B_SIZE(ctx->img_width, ctx->img_height);
-               break;
-       case V4L2_PIX_FMT_NV12N:
-               raw->plane_size[0] = NV12N_Y_SIZE(ctx->img_width, ctx->img_height);
-               raw->plane_size[1] = NV12N_CBCR_SIZE(ctx->img_width, ctx->img_height);
-               break;
-       case V4L2_PIX_FMT_YUV420N:
-               raw->plane_size[0] = YUV420N_Y_SIZE(ctx->img_width, ctx->img_height);
-               raw->plane_size[1] = YUV420N_CB_SIZE(ctx->img_width, ctx->img_height);
-               raw->plane_size[2] = YUV420N_CR_SIZE(ctx->img_width, ctx->img_height);
-               break;
-       default:
-               mfc_err_ctx("Invalid pixelformat : %s\n", ctx->dst_fmt->name);
-               break;
-       }
-
-       mfc_set_linear_stride_size(ctx, ctx->dst_fmt);
-
-       for (i = 0; i < raw->num_planes; i++) {
-               if (raw->plane_size[i] < ctx->min_dpb_size[i]) {
-                       mfc_info_dev("[FRAME] plane[%d] size is changed %d -> %d\n",
-                                       i, raw->plane_size[i], ctx->min_dpb_size[i]);
-                       raw->plane_size[i] = ctx->min_dpb_size[i];
-               }
-       }
-
-       for (i = 0; i < raw->num_planes; i++) {
-               raw->total_plane_size += raw->plane_size[i];
-               mfc_debug(2, "[FRAME] Plane[%d] size = %d, stride = %d\n",
-                       i, raw->plane_size[i], raw->stride[i]);
-       }
-       if (ctx->is_10bit) {
-               for (i = 0; i < raw->num_planes; i++) {
-                       raw->total_plane_size += raw->plane_size_2bits[i];
-                       mfc_debug(2, "[FRAME][10BIT] Plane[%d] 2bit size = %d, stride = %d\n",
-                                       i, raw->plane_size_2bits[i],
-                                       raw->stride_2bits[i]);
-               }
-       }
-       mfc_debug(2, "[FRAME] total plane size: %d\n", raw->total_plane_size);
-
-       if (IS_H264_DEC(ctx) || IS_H264_MVC_DEC(ctx)) {
-               ctx->mv_size = DEC_MV_SIZE_MB(ctx->img_width, ctx->img_height);
-               ctx->mv_size = ALIGN(ctx->mv_size, 32);
-       } else if (IS_HEVC_DEC(ctx) || IS_BPG_DEC(ctx)) {
-               ctx->mv_size = DEC_HEVC_MV_SIZE(ctx->img_width, ctx->img_height);
-               ctx->mv_size = ALIGN(ctx->mv_size, 32);
-       } else {
-               ctx->mv_size = 0;
-       }
-}
-
-void s5p_mfc_enc_calc_src_size(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dev *dev;
-       struct s5p_mfc_raw_info *raw;
-       unsigned int mb_width, mb_height, default_size;
-       int i, extra;
-
-       if (!ctx) {
-               mfc_err_dev("no mfc context to run\n");
-               return;
-       }
-
-       dev = ctx->dev;
-       raw = &ctx->raw_buf;
-       raw->total_plane_size = 0;
-       mb_width = WIDTH_MB(ctx->img_width);
-       mb_height = HEIGHT_MB(ctx->img_height);
-       extra = MFC_LINEAR_BUF_SIZE;
-       default_size = mb_width * mb_height * 256;
-
-       for (i = 0; i < raw->num_planes; i++) {
-               raw->plane_size[i] = 0;
-               raw->plane_size_2bits[i] = 0;
-       }
-
-       switch (ctx->src_fmt->fourcc) {
-       case V4L2_PIX_FMT_YUV420M:
-       case V4L2_PIX_FMT_YUV420N:
-       case V4L2_PIX_FMT_YVU420M:
-               raw->plane_size[0] = ALIGN(default_size, 256) + extra;
-               raw->plane_size[1] = ALIGN(default_size >> 2, 256) + extra;
-               raw->plane_size[2] = ALIGN(default_size >> 2, 256) + extra;
-               break;
-       case V4L2_PIX_FMT_NV12M_S10B:
-       case V4L2_PIX_FMT_NV21M_S10B:
-               raw->plane_size[0] = NV12M_Y_SIZE(ctx->img_width, ctx->img_height);
-               raw->plane_size[1] = NV12M_CBCR_SIZE(ctx->img_width, ctx->img_height);
-               raw->plane_size_2bits[0] = NV12M_Y_2B_SIZE(ctx->img_width, ctx->img_height);
-               raw->plane_size_2bits[1] = NV12M_CBCR_2B_SIZE(ctx->img_width, ctx->img_height);
-               break;
-       case V4L2_PIX_FMT_NV12MT_16X16:
-       case V4L2_PIX_FMT_NV12M:
-       case V4L2_PIX_FMT_NV12N:
-       case V4L2_PIX_FMT_NV21M:
-               raw->plane_size[0] = ALIGN(default_size, 256) + extra;
-               raw->plane_size[1] = ALIGN(default_size / 2, 256) + extra;
-               break;
-       case V4L2_PIX_FMT_NV12M_P010:
-       case V4L2_PIX_FMT_NV21M_P010:
-               raw->plane_size[0] = ALIGN(default_size, 256) * 2 + extra;
-               raw->plane_size[1] = ALIGN(default_size, 256) + extra;
-               break;
-       case V4L2_PIX_FMT_NV16M_S10B:
-       case V4L2_PIX_FMT_NV61M_S10B:
-               raw->plane_size[0] = NV16M_Y_SIZE(ctx->img_width, ctx->img_height);
-               raw->plane_size[1] = NV16M_CBCR_SIZE(ctx->img_width, ctx->img_height);
-               raw->plane_size_2bits[0] = NV16M_Y_2B_SIZE(ctx->img_width, ctx->img_height);
-               raw->plane_size_2bits[1] = NV16M_CBCR_2B_SIZE(ctx->img_width, ctx->img_height);
-               break;
-       case V4L2_PIX_FMT_NV16M:
-       case V4L2_PIX_FMT_NV61M:
-               raw->plane_size[0] = ALIGN(default_size, 256) + extra;
-               raw->plane_size[1] = ALIGN(default_size, 256) + extra;
-               break;
-       case V4L2_PIX_FMT_NV16M_P210:
-       case V4L2_PIX_FMT_NV61M_P210:
-               raw->plane_size[0] = ALIGN(default_size, 256) * 2 + extra;
-               raw->plane_size[1] = ALIGN(default_size, 256) * 2 + extra;
-               break;
-       default:
-               mfc_err_ctx("Invalid pixel format(%d)\n", ctx->src_fmt->fourcc);
-               break;
-       }
-
-       mfc_set_linear_stride_size(ctx, ctx->src_fmt);
-
-       for (i = 0; i < raw->num_planes; i++) {
-               raw->total_plane_size += raw->plane_size[i];
-               mfc_debug(2, "[FRAME] Plane[%d] size = %d, stride = %d\n",
-                       i, raw->plane_size[i], raw->stride[i]);
-       }
-       if (ctx->is_10bit) {
-               for (i = 0; i < raw->num_planes; i++) {
-                       raw->total_plane_size += raw->plane_size_2bits[i];
-                       mfc_debug(2, "[FRAME][10BIT] Plane[%d] 2bit size = %d, stride = %d\n",
-                                       i, raw->plane_size_2bits[i],
-                                       raw->stride_2bits[i]);
-               }
-       }
-
-       mfc_debug(2, "[FRAME] total plane size: %d\n", raw->total_plane_size);
-}
-
-void s5p_mfc_cleanup_assigned_dpb(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dec *dec;
-       struct s5p_mfc_buf *dst_mb;
-       int i;
-
-       if (!ctx) {
-               mfc_err_dev("no mfc context to run\n");
-               return;
-       }
-
-       dec = ctx->dec_priv;
-       if (!dec) {
-               mfc_err_dev("no mfc decoder to run\n");
-               return;
-       }
-
-       if (ctx->is_drm && ctx->raw_protect_flag) {
-               mfc_debug(2, "raw_protect_flag(%#lx) will be released\n",
-                               ctx->raw_protect_flag);
-               for (i = 0; i < MFC_MAX_DPBS; i++) {
-                       dst_mb = dec->assigned_dpb[i];
-
-                       s5p_mfc_raw_unprotect(ctx, dst_mb, i);
-               }
-               s5p_mfc_clear_assigned_dpb(ctx);
-       }
-}
-
-void s5p_mfc_unprotect_released_dpb(struct s5p_mfc_ctx *ctx, unsigned int released_flag)
-{
-       struct s5p_mfc_dec *dec;
-       struct s5p_mfc_buf *dst_mb;
-       int i;
-
-       if (!ctx) {
-               mfc_err_dev("no mfc context to run\n");
-               return;
-       }
-
-       dec = ctx->dec_priv;
-       if (!dec) {
-               mfc_err_dev("no mfc decoder to run\n");
-               return;
-       }
-
-       if (ctx->is_drm) {
-               for (i = 0; i < MFC_MAX_DPBS; i++) {
-                       if (released_flag & (1 << i)) {
-                               dst_mb = dec->assigned_dpb[i];
-                               s5p_mfc_raw_unprotect(ctx, dst_mb, i);
-                       }
-               }
-       }
-
-}
-
-void s5p_mfc_protect_dpb(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf *dst_mb)
-{
-       struct s5p_mfc_dec *dec;
-       int dst_index;
-
-       if (!ctx) {
-               mfc_err_dev("no mfc context to run\n");
-               return;
-       }
-
-       dec = ctx->dec_priv;
-       if (!dec) {
-               mfc_err_dev("no mfc decoder to run\n");
-               return;
-       }
-
-       dst_index = dst_mb->vb.vb2_buf.index;
-
-       if (ctx->is_drm) {
-               dec->assigned_dpb[dst_index] = dst_mb;
-               s5p_mfc_raw_protect(ctx, dst_mb, dst_index);
-       }
-}
-
-void s5p_mfc_watchdog_tick(unsigned long arg)
-{
-       struct s5p_mfc_dev *dev = (struct s5p_mfc_dev *)arg;
-
-       if (!dev) {
-               mfc_err_dev("no mfc device to run\n");
-               return;
-       }
-
-       mfc_debug(5, "watchdog is ticking!\n");
-
-       if (atomic_read(&dev->watchdog_tick_running))
-               atomic_inc(&dev->watchdog_tick_cnt);
-       else
-               atomic_set(&dev->watchdog_tick_cnt, 0);
-
-       if (atomic_read(&dev->watchdog_tick_cnt) >= WATCHDOG_TICK_CNT_TO_START_WATCHDOG) {
-               /* 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_dev("[%d] Time out during waiting for HW\n",
-                               atomic_read(&dev->watchdog_tick_cnt));
-               queue_work(dev->watchdog_wq, &dev->watchdog_work);
-       }
-
-       dev->watchdog_timer.expires = jiffies +
-                                       msecs_to_jiffies(WATCHDOG_TICK_INTERVAL);
-       add_timer(&dev->watchdog_timer);
-}
-
-void s5p_mfc_watchdog_start_tick(struct s5p_mfc_dev *dev)
-{
-       if (atomic_read(&dev->watchdog_tick_running)) {
-               mfc_debug(2, "watchdog timer was already started!\n");
-       } else {
-               mfc_debug(2, "watchdog timer is now started!\n");
-               atomic_set(&dev->watchdog_tick_running, 1);
-       }
-
-       /* Reset the timeout watchdog */
-       atomic_set(&dev->watchdog_tick_cnt, 0);
-}
-
-void s5p_mfc_watchdog_stop_tick(struct s5p_mfc_dev *dev)
-{
-       if (atomic_read(&dev->watchdog_tick_running)) {
-               mfc_debug(2, "watchdog timer is now stopped!\n");
-               atomic_set(&dev->watchdog_tick_running, 0);
-       } else {
-               mfc_debug(2, "watchdog timer was already stopped!\n");
-       }
-
-       /* Reset the timeout watchdog */
-       atomic_set(&dev->watchdog_tick_cnt, 0);
-}
-
-void s5p_mfc_watchdog_reset_tick(struct s5p_mfc_dev *dev)
-{
-       mfc_debug(2, "watchdog timer reset!\n");
-
-       /* Reset the timeout watchdog */
-       atomic_set(&dev->watchdog_tick_cnt, 0);
-}
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_utils.h b/drivers/media/platform/exynos/mfc/s5p_mfc_utils.h
deleted file mode 100644 (file)
index e933321..0000000
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_utils.h
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __S5P_MFC_UTILS_H
-#define __S5P_MFC_UTILS_H __FILE__
-
-#include "s5p_mfc_common.h"
-
-static inline void s5p_mfc_clean_dev_int_flags(struct s5p_mfc_dev *dev)
-{
-       dev->int_condition = 0;
-       dev->int_reason = 0;
-       dev->int_err = 0;
-}
-
-static inline void s5p_mfc_clean_ctx_int_flags(struct s5p_mfc_ctx *ctx)
-{
-       ctx->int_condition = 0;
-       ctx->int_reason = 0;
-       ctx->int_err = 0;
-}
-
-static inline void s5p_mfc_change_state(struct s5p_mfc_ctx *ctx, enum s5p_mfc_inst_state state)
-{
-       struct s5p_mfc_dev *dev = ctx->dev;
-
-       MFC_TRACE_CTX("** state : %d\n", state);
-       ctx->state = state;
-}
-
-static inline enum s5p_mfc_node_type s5p_mfc_get_node_type(struct file *file)
-{
-       struct video_device *vdev = video_devdata(file);
-       enum s5p_mfc_node_type node_type;
-
-       if (!vdev) {
-               mfc_err_dev("failed to get video_device\n");
-               return MFCNODE_INVALID;
-       }
-
-       mfc_debug(2, "video_device index: %d\n", vdev->index);
-
-       switch (vdev->index) {
-       case 0:
-               node_type = MFCNODE_DECODER;
-               break;
-       case 1:
-               node_type = MFCNODE_ENCODER;
-               break;
-       case 2:
-               node_type = MFCNODE_DECODER_DRM;
-               break;
-       case 3:
-               node_type = MFCNODE_ENCODER_DRM;
-               break;
-       case 4:
-               node_type = MFCNODE_ENCODER_OTF;
-               break;
-       case 5:
-               node_type = MFCNODE_ENCODER_OTF_DRM;
-               break;
-       default:
-               node_type = MFCNODE_INVALID;
-               break;
-       }
-
-       return node_type;
-}
-
-static inline int s5p_mfc_is_decoder_node(enum s5p_mfc_node_type node)
-{
-       if (node == MFCNODE_DECODER || node == MFCNODE_DECODER_DRM)
-               return 1;
-
-       return 0;
-}
-
-static inline int s5p_mfc_is_drm_node(enum s5p_mfc_node_type node)
-{
-       if (node == MFCNODE_DECODER_DRM || node == MFCNODE_ENCODER_DRM ||
-                       node == MFCNODE_ENCODER_OTF_DRM)
-               return 1;
-
-       return 0;
-}
-
-static inline int s5p_mfc_is_encoder_otf_node(enum s5p_mfc_node_type node)
-{
-       if (node == MFCNODE_ENCODER_OTF || node == MFCNODE_ENCODER_OTF_DRM)
-               return 1;
-
-       return 0;
-}
-
-int s5p_mfc_check_vb_with_fmt(struct s5p_mfc_fmt *fmt, struct vb2_buffer *vb);
-
-void s5p_mfc_raw_protect(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf *mfc_buf,
-                                       int index);
-void s5p_mfc_raw_unprotect(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf *mfc_buf,
-                                       int index);
-void s5p_mfc_stream_protect(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf *mfc_buf,
-                                       int index);
-void s5p_mfc_stream_unprotect(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf *mfc_buf,
-                                       int index);
-
-void s5p_mfc_dec_calc_dpb_size(struct s5p_mfc_ctx *ctx);
-void s5p_mfc_enc_calc_src_size(struct s5p_mfc_ctx *ctx);
-
-static inline void s5p_mfc_cleanup_assigned_fd(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dec *dec;
-       int i;
-
-       dec = ctx->dec_priv;
-
-       for (i = 0; i < MFC_MAX_DPBS; i++)
-               dec->assigned_fd[i] = MFC_INFO_INIT_FD;
-}
-
-static inline void s5p_mfc_clear_assigned_dpb(struct s5p_mfc_ctx *ctx)
-{
-       struct s5p_mfc_dec *dec;
-       int i;
-
-       if (!ctx) {
-               mfc_err_dev("no mfc context to run\n");
-               return;
-       }
-
-       dec = ctx->dec_priv;
-       if (!dec) {
-               mfc_err_dev("no mfc decoder to run\n");
-               return;
-       }
-
-       for (i = 0; i < MFC_MAX_DPBS; i++)
-               dec->assigned_dpb[i] = NULL;
-}
-
-static inline int s5p_mfc_dec_status_decoding(unsigned int dst_frame_status)
-{
-       if (dst_frame_status == S5P_FIMV_DEC_STATUS_DECODING_DISPLAY ||
-           dst_frame_status == S5P_FIMV_DEC_STATUS_DECODING_ONLY)
-               return 1;
-       return 0;
-}
-
-static inline int s5p_mfc_dec_status_display(unsigned int dst_frame_status)
-{
-       if (dst_frame_status == S5P_FIMV_DEC_STATUS_DISPLAY_ONLY ||
-           dst_frame_status == S5P_FIMV_DEC_STATUS_DECODING_DISPLAY)
-               return 1;
-
-       return 0;
-}
-
-void s5p_mfc_cleanup_assigned_dpb(struct s5p_mfc_ctx *ctx);
-void s5p_mfc_unprotect_released_dpb(struct s5p_mfc_ctx *ctx, unsigned int released_flag);
-void s5p_mfc_protect_dpb(struct s5p_mfc_ctx *ctx, struct s5p_mfc_buf *dst_mb);
-
-/* Watchdog interval */
-#define WATCHDOG_TICK_INTERVAL   1000
-/* After how many executions watchdog should assume lock up */
-#define WATCHDOG_TICK_CNT_TO_START_WATCHDOG        5
-
-void s5p_mfc_watchdog_tick(unsigned long arg);
-void s5p_mfc_watchdog_start_tick(struct s5p_mfc_dev *dev);
-void s5p_mfc_watchdog_stop_tick(struct s5p_mfc_dev *dev);
-void s5p_mfc_watchdog_reset_tick(struct s5p_mfc_dev *dev);
-
-#endif /* __S5P_MFC_UTILS_H */
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_watchdog.c b/drivers/media/platform/exynos/mfc/s5p_mfc_watchdog.c
deleted file mode 100644 (file)
index 17a1e87..0000000
+++ /dev/null
@@ -1,350 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_watchdog.c
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-#ifdef BIGDATA_LOGGING_ENABLE
-#include <linux/sec_debug.h>
-#endif
-
-#include "s5p_mfc_watchdog.h"
-
-#include "s5p_mfc_sync.h"
-
-#include "s5p_mfc_pm.h"
-#include "s5p_mfc_cmd.h"
-#include "s5p_mfc_cal.h"
-#include "s5p_mfc_reg.h"
-
-#include "s5p_mfc_queue.h"
-#include "s5p_mfc_utils.h"
-
-#define MFC_SFR_AREA_COUNT     21
-static void mfc_dump_regs(struct s5p_mfc_dev *dev)
-{
-       int i;
-       struct s5p_mfc_ctx_buf_size *buf_size = NULL;
-       int addr[MFC_SFR_AREA_COUNT][2] = {
-               { 0x0, 0x80 },
-               { 0x1000, 0xCD0 },
-               { 0xF000, 0xFF8 },
-               { 0x2000, 0xA00 },
-               { 0x2f00, 0x6C },
-               { 0x3000, 0x40 },
-               { 0x3094, 0x4 },
-               { 0x30b4, 0x8 },
-               { 0x3110, 0x10 },
-               { 0x5000, 0x100 },
-               { 0x5200, 0x300 },
-               { 0x5600, 0x100 },
-               { 0x5800, 0x100 },
-               { 0x5A00, 0x100 },
-               { 0x6000, 0xC4 },
-               { 0x7000, 0x21C },
-               { 0x8000, 0x20C },
-               { 0x9000, 0x10C },
-               { 0xA000, 0x20C },
-               { 0xB000, 0x444 },
-               { 0xC000, 0x84 },
-       };
-
-       pr_err("-----------dumping MFC registers (SFR base = 0x%p, dev = 0x%p)\n",
-                               dev->regs_base, dev);
-
-       s5p_mfc_enable_all_clocks(dev);
-
-       for (i = 0; i < MFC_SFR_AREA_COUNT; i++) {
-               printk("[%04X .. %04X]\n", addr[i][0], addr[i][0] + addr[i][1]);
-               print_hex_dump(KERN_ERR, "", DUMP_PREFIX_ADDRESS, 32, 4, dev->regs_base + addr[i][0],
-                               addr[i][1], false);
-               printk("...\n");
-       }
-
-       if (dbg_enable) {
-               buf_size = dev->variant->buf_size->ctx_buf;
-               printk("[DBG INFO dump]\n");
-               print_hex_dump(KERN_ERR, "", DUMP_PREFIX_ADDRESS, 32, 4, dev->dbg_info_buf.vaddr,
-                       buf_size->dbg_info_buf, false);
-               printk("...\n");
-       }
-}
-
-const u32 s5p_mfc_logging_sfr_set1[MFC_SFR_LOGGING_COUNT_SET1] = {
-       0x1000, 0x1004, 0x100C, 0x1010
-};
-
-const u32 s5p_mfc_logging_sfr_set2[MFC_SFR_LOGGING_COUNT_SET2] = {
-       0x0070, 0x10B4, 0x2020, 0x2028,
-       0x204C, 0x20B4, 0x3000, 0x3004,
-       0x3010, 0x301C, 0x3110, 0x5A54,
-       0x5A80, 0x5A88, 0x5A94, 0x6038,
-       0x6050, 0x6168, 0x7018, 0x7110,
-       0x7114, 0xF088, 0xFFD0
-};
-
-int mfc_change_hex_to_ascii(u32 hex, u32 byte, char *ascii, int idx)
-{
-       int i;
-       char tmp;
-
-       for (i = 0; i < byte; i++) {
-               if (idx >= MFC_LOGGING_DATA_SIZE) {
-                       pr_err("logging data size exceed: %d\n", idx);
-                       return idx;
-               }
-
-               tmp = (hex >> ((byte - 1 - i) * 4)) & 0xF;
-               if (tmp > 9)
-                       ascii[idx] = tmp + 'a' - 0xa;
-               else if (tmp <= 9)
-                       ascii[idx] = tmp + '0';
-               idx++;
-       }
-
-       /* space */
-       if (idx < MFC_LOGGING_DATA_SIZE)
-               ascii[idx] = ' ';
-
-       return ++idx;
-}
-
-static void mfc_save_logging_sfr(struct s5p_mfc_dev *dev)
-{
-       char *errorinfo;
-       int i, idx = 0;
-
-       pr_err("-----------logging MFC error info-----------\n");
-       errorinfo = dev->logging_data->errorinfo;
-       for (i = 0; i < MFC_SFR_LOGGING_COUNT_SET1; i++)
-               dev->logging_data->SFRs_set1[i] = MFC_READL(s5p_mfc_logging_sfr_set1[i]);
-       for (i = 0; i < MFC_SFR_LOGGING_COUNT_SET2; i++)
-               dev->logging_data->SFRs_set2[i] = MFC_READL(s5p_mfc_logging_sfr_set2[i]);
-
-       idx = mfc_change_hex_to_ascii(dev->logging_data->cause, 8, errorinfo, idx);
-       idx = mfc_change_hex_to_ascii(dev->logging_data->fault_status, 2, errorinfo, idx);
-       idx = mfc_change_hex_to_ascii(dev->logging_data->fault_trans_info, 8, errorinfo, idx);
-       idx = mfc_change_hex_to_ascii(dev->logging_data->fault_addr, 8, errorinfo, idx);
-       for (i = 0; i < MFC_SFR_LOGGING_COUNT_SET1; i++)
-               idx = mfc_change_hex_to_ascii(dev->logging_data->SFRs_set1[i], 2, errorinfo, idx);
-       for (i = 0; i < MFC_SFR_LOGGING_COUNT_SET2; i++)
-               idx = mfc_change_hex_to_ascii(dev->logging_data->SFRs_set2[i], 8, errorinfo, idx);
-
-       pr_err("%s\n", errorinfo);
-
-#ifdef BIGDATA_LOGGING_ENABLE
-       sec_debug_set_extra_info_mfc_error(errorinfo);
-#endif
-}
-
-static void mfc_display_state(struct s5p_mfc_dev *dev)
-{
-       nal_queue_handle *nal_q_handle = dev->nal_q_handle;
-       int i;
-
-       pr_err("-----------dumping MFC device info-----------\n");
-       pr_err("power:%d, clock:%d, num_inst:%d, num_drm_inst:%d, fw_status:%d\n",
-                       s5p_mfc_pm_get_pwr_ref_cnt(dev), s5p_mfc_pm_get_clk_ref_cnt(dev),
-                       dev->num_inst, dev->num_drm_inst, dev->fw.status);
-       pr_err("hwlock bits:%#lx / dev:%#lx, curr_ctx:%d (is_drm:%d),"
-                       " preempt_ctx:%d, work_bits:%#lx\n",
-                       dev->hwlock.bits, dev->hwlock.dev,
-                       dev->curr_ctx, dev->curr_ctx_is_drm,
-                       dev->preempt_ctx, s5p_mfc_get_bits(&dev->work_bits));
-       pr_err("options debug_level:%d, debug_mode:%d, mmcache:%d, perf_boost:%d\n",
-                       debug_level, dev->pdata->debug_mode, dev->mmcache.is_on_status, perf_boost_mode);
-       pr_err("NAL-Q state:%d, exception:%d, in_exe_cnt: %d, out_exe_cnt: %d\n",
-                       nal_q_handle->nal_q_state, nal_q_handle->nal_q_exception,
-                       nal_q_handle->nal_q_in_handle->in_exe_count,
-                       nal_q_handle->nal_q_out_handle->out_exe_count);
-
-       for (i = 0; i < MFC_NUM_CONTEXTS; i++)
-               if (dev->ctx[i])
-                       pr_err("MFC ctx[%d] %s(%d) state:%d, queue_cnt(src:%d, dst:%d, ref:%d, qsrc:%d, qdst:%d)\n"
-                               "     interrupt(cond:%d, type:%d, err:%d)\n",
-                               dev->ctx[i]->num,
-                               dev->ctx[i]->type == MFCINST_DECODER ? "DEC" : "ENC",
-                               dev->ctx[i]->codec_mode, dev->ctx[i]->state,
-                               s5p_mfc_get_queue_count(&dev->ctx[i]->buf_queue_lock, &dev->ctx[i]->src_buf_queue),
-                               s5p_mfc_get_queue_count(&dev->ctx[i]->buf_queue_lock, &dev->ctx[i]->dst_buf_queue),
-                               s5p_mfc_get_queue_count(&dev->ctx[i]->buf_queue_lock, &dev->ctx[i]->ref_buf_queue),
-                               s5p_mfc_get_queue_count(&dev->ctx[i]->buf_queue_lock, &dev->ctx[i]->src_buf_nal_queue),
-                               s5p_mfc_get_queue_count(&dev->ctx[i]->buf_queue_lock, &dev->ctx[i]->dst_buf_nal_queue),
-                               dev->ctx[i]->int_condition, dev->ctx[i]->int_reason,
-                               dev->ctx[i]->int_err);
-}
-
-static void mfc_print_trace(struct s5p_mfc_dev *dev)
-{
-       int i, cnt, trace_cnt;
-
-       pr_err("-----------dumping MFC trace info-----------\n");
-
-       trace_cnt = atomic_read(&dev->trace_ref);
-       for (i = MFC_TRACE_COUNT_PRINT - 1; i >= 0; i--) {
-               cnt = ((trace_cnt + MFC_TRACE_COUNT_MAX) - i) % MFC_TRACE_COUNT_MAX;
-               pr_err("MFC trace[%d]: time=%llu, str=%s", cnt,
-                               dev->mfc_trace[cnt].time, dev->mfc_trace[cnt].str);
-       }
-}
-
-void mfc_dump_buffer_info(struct s5p_mfc_dev *dev)
-{
-       struct s5p_mfc_ctx *ctx;
-
-       ctx = dev->ctx[dev->curr_ctx];
-       if (ctx) {
-               pr_err("-----------dumping MFC buffer info (fault at: %#x)\n",
-                               dev->logging_data->fault_addr);
-               pr_err("common:%#llx~%#llx, instance:%#llx~%#llx, codec:%#llx~%#llx\n",
-                               dev->common_ctx_buf.daddr,
-                               dev->common_ctx_buf.daddr + PAGE_ALIGN(0x7800),
-                               ctx->instance_ctx_buf.daddr,
-                               ctx->instance_ctx_buf.daddr + ctx->instance_ctx_buf.size,
-                               ctx->codec_buf.daddr,
-                               ctx->codec_buf.daddr + ctx->codec_buf.size);
-               if (ctx->type == MFCINST_DECODER) {
-                       pr_err("Decoder CPB:%#x++%#x, scratch:%#x++%#x, static(vp9):%#x++%#x\n",
-                                       MFC_READL(S5P_FIMV_D_CPB_BUFFER_ADDR),
-                                       MFC_READL(S5P_FIMV_D_CPB_BUFFER_SIZE),
-                                       MFC_READL(S5P_FIMV_D_SCRATCH_BUFFER_ADDR),
-                                       MFC_READL(S5P_FIMV_D_SCRATCH_BUFFER_SIZE),
-                                       MFC_READL(S5P_FIMV_D_STATIC_BUFFER_ADDR),
-                                       MFC_READL(S5P_FIMV_D_STATIC_BUFFER_SIZE));
-                       pr_err("DPB [0]plane:++%#x, [1]plane:++%#x, [2]plane:++%#x, MV buffer:++%#lx\n",
-                                       ctx->raw_buf.plane_size[0],
-                                       ctx->raw_buf.plane_size[1],
-                                       ctx->raw_buf.plane_size[2],
-                                       ctx->mv_size);
-                       print_hex_dump(KERN_ERR, "[0] plane ", DUMP_PREFIX_ADDRESS, 32, 4,
-                                       dev->regs_base + S5P_FIMV_D_FIRST_PLANE_DPB0,
-                                       0x100, false);
-                       print_hex_dump(KERN_ERR, "[1] plane ", DUMP_PREFIX_ADDRESS, 32, 4,
-                                       dev->regs_base + S5P_FIMV_D_SECOND_PLANE_DPB0,
-                                       0x100, false);
-                       if (ctx->dst_fmt->num_planes == 3)
-                               print_hex_dump(KERN_ERR, "[2] plane ", DUMP_PREFIX_ADDRESS, 32, 4,
-                                               dev->regs_base + S5P_FIMV_D_THIRD_PLANE_DPB0,
-                                               0x100, false);
-                       print_hex_dump(KERN_ERR, "MV buffer ", DUMP_PREFIX_ADDRESS, 32, 4,
-                                       dev->regs_base + S5P_FIMV_D_MV_BUFFER0,
-                                       0x100, false);
-               } else if (ctx->type == MFCINST_ENCODER) {
-                       pr_err("Encoder SRC %dplane, [0]:%#x++%#x, [1]:%#x++%#x, [2]:%#x++%#x\n",
-                                       ctx->src_fmt->num_planes,
-                                       MFC_READL(S5P_FIMV_E_SOURCE_FIRST_ADDR),
-                                       ctx->raw_buf.plane_size[0],
-                                       MFC_READL(S5P_FIMV_E_SOURCE_SECOND_ADDR),
-                                       ctx->raw_buf.plane_size[1],
-                                       MFC_READL(S5P_FIMV_E_SOURCE_THIRD_ADDR),
-                                       ctx->raw_buf.plane_size[2]);
-                       pr_err("DST:%#x++%#x, scratch:%#x++%#x\n",
-                                       MFC_READL(S5P_FIMV_E_STREAM_BUFFER_ADDR),
-                                       MFC_READL(S5P_FIMV_E_STREAM_BUFFER_SIZE),
-                                       MFC_READL(S5P_FIMV_E_SCRATCH_BUFFER_ADDR),
-                                       MFC_READL(S5P_FIMV_E_SCRATCH_BUFFER_SIZE));
-                       pr_err("DPB [0] plane:++%#lx, [1] plane:++%#lx, ME buffer:++%#lx\n",
-                                       ctx->enc_priv->luma_dpb_size,
-                                       ctx->enc_priv->chroma_dpb_size,
-                                       ctx->enc_priv->me_buffer_size);
-                       print_hex_dump(KERN_ERR, "[0] plane ", DUMP_PREFIX_ADDRESS, 32, 4,
-                                       dev->regs_base + S5P_FIMV_E_LUMA_DPB,
-                                       0x44, false);
-                       print_hex_dump(KERN_ERR, "[1] plane ", DUMP_PREFIX_ADDRESS, 32, 4,
-                                       dev->regs_base + S5P_FIMV_E_CHROMA_DPB,
-                                       0x44, false);
-                       print_hex_dump(KERN_ERR, "ME buffer ", DUMP_PREFIX_ADDRESS, 32, 4,
-                                       dev->regs_base + S5P_FIMV_E_ME_BUFFER,
-                                       0x44, false);
-               } else {
-                       pr_err("invalid MFC instnace type(%d)\n", ctx->type);
-               }
-       }
-}
-
-static void mfc_dump_info_without_regs(struct s5p_mfc_dev *dev)
-{
-       mfc_display_state(dev);
-       mfc_print_trace(dev);
-}
-
-static void mfc_dump_info(struct s5p_mfc_dev *dev)
-{
-       mfc_dump_info_without_regs(dev);
-       mfc_save_logging_sfr(dev);
-       mfc_dump_buffer_info(dev);
-       mfc_dump_regs(dev);
-       exynos_sysmmu_show_status(dev->device);
-}
-
-static void mfc_dump_info_and_stop_hw(struct s5p_mfc_dev *dev)
-{
-       MFC_TRACE_DEV("** mfc will stop!!!\n");
-       mfc_dump_info(dev);
-       BUG();
-}
-
-static void mfc_dump_info_and_stop_hw_debug(struct s5p_mfc_dev *dev)
-{
-       if (!dev->pdata->debug_mode)
-               return;
-
-       MFC_TRACE_DEV("** mfc will stop!!!\n");
-       mfc_dump_info(dev);
-       BUG();
-}
-
-void s5p_mfc_watchdog_worker(struct work_struct *work)
-{
-       struct s5p_mfc_dev *dev;
-       int cmd;
-
-       dev = container_of(work, struct s5p_mfc_dev, watchdog_work);
-
-       if (atomic_read(&dev->watchdog_run)) {
-               mfc_err_dev("watchdog already running???\n");
-               return;
-       }
-
-       if (!atomic_read(&dev->watchdog_tick_cnt)) {
-               mfc_err_dev("interrupt handler is called\n");
-               return;
-       }
-
-       cmd = s5p_mfc_check_risc2host(dev);
-       if (cmd) {
-               if (atomic_read(&dev->watchdog_tick_cnt) == (3 * WATCHDOG_TICK_CNT_TO_START_WATCHDOG)) {
-                       mfc_err_dev("MFC driver waited for upward of %dsec\n",
-                                       3 * WATCHDOG_TICK_CNT_TO_START_WATCHDOG);
-                       dev->logging_data->cause |= (1 << MFC_CAUSE_NO_SCHEDULING);
-               } else {
-                       mfc_err_dev("interrupt(%d) is occurred, wait scheduling\n", cmd);
-                       return;
-               }
-       } else {
-               dev->logging_data->cause |= (1 << MFC_CAUSE_NO_INTERRUPT);
-               mfc_err_dev("Driver timeout error handling\n");
-       }
-
-       /* Run watchdog worker */
-       atomic_set(&dev->watchdog_run, 1);
-
-       /* Reset the timeout watchdog */
-       atomic_set(&dev->watchdog_tick_cnt, 0);
-
-       /* Stop after dumping information */
-       mfc_dump_info_and_stop_hw(dev);
-}
-
-struct s5p_mfc_dump_ops mfc_dump_ops = {
-       .dump_regs                      = mfc_dump_regs,
-       .dump_info                      = mfc_dump_info,
-       .dump_info_without_regs         = mfc_dump_info_without_regs,
-       .dump_and_stop_always           = mfc_dump_info_and_stop_hw,
-       .dump_and_stop_debug_mode       = mfc_dump_info_and_stop_hw_debug,
-};
diff --git a/drivers/media/platform/exynos/mfc/s5p_mfc_watchdog.h b/drivers/media/platform/exynos/mfc/s5p_mfc_watchdog.h
deleted file mode 100644 (file)
index b715fb7..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * drivers/media/platform/exynos/mfc/s5p_mfc_watchdog.h
- *
- * Copyright (c) 2016 Samsung Electronics Co., Ltd.
- *              http://www.samsung.com/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __S5P_MFC_WATCHDOG_H
-#define __S5P_MFC_WATCHDOG_H __FILE__
-
-#include "s5p_mfc_common.h"
-
-void s5p_mfc_watchdog_worker(struct work_struct *work);
-
-#endif /* __S5P_MFC_WATCHDOG_H */