lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250930040348.3702923-28-h.dewangan@samsung.com>
Date: Tue, 30 Sep 2025 09:33:46 +0530
From: Himanshu Dewangan <h.dewangan@...sung.com>
To: mchehab@...nel.org, robh@...nel.org, krzk+dt@...nel.org,
	conor+dt@...nel.org, sumit.semwal@...aro.org, christian.koenig@....com,
	alim.akhtar@...sung.com, manjun@...sung.com, nagaraju.s@...sung.com,
	ih0206.lee@...sung.com, jehyung.lee@...sung.com
Cc: linux-arm-kernel@...ts.infradead.org, linux-media@...r.kernel.org,
	devicetree@...r.kernel.org, linux-samsung-soc@...r.kernel.org,
	linux-kernel@...r.kernel.org, dri-devel@...ts.freedesktop.org,
	linaro-mm-sig@...ts.linaro.org, Himanshu Dewangan <h.dewangan@...sung.com>
Subject: [PATCH 27/29] media: mfc: Add H.264 encoder support

From: Nagaraju Siddineni <nagaraju.s@...sung.com>

- Register H.264 format and V4L2/VB2 headers.
- Initialize encoder context, queues, and defaults.
- Add buffer‑control handling (layers, ROI, frame‑rate, drop,
  profile/level) and parse DT properties.
- Register encoder ioctl ops, set up QoS table, and extend debugfs.

Signed-off-by: Nagaraju Siddineni <nagaraju.s@...sung.com>
Signed-off-by: Himanshu Dewangan <h.dewangan@...sung.com>
---
 .../samsung/exynos-mfc/base/mfc_format.h      |   8 +
 .../media/platform/samsung/exynos-mfc/mfc.c   | 193 ++++++-
 .../platform/samsung/exynos-mfc/mfc_core.c    |  26 +
 .../samsung/exynos-mfc/mfc_core_buf_ctrl.c    | 321 +++++++++++
 .../samsung/exynos-mfc/mfc_core_isr.c         | 518 +++++++++++++++++-
 .../samsung/exynos-mfc/mfc_core_sync.c        |  58 +-
 .../platform/samsung/exynos-mfc/mfc_debugfs.c |  17 +-
 7 files changed, 1116 insertions(+), 25 deletions(-)

diff --git a/drivers/media/platform/samsung/exynos-mfc/base/mfc_format.h b/drivers/media/platform/samsung/exynos-mfc/base/mfc_format.h
index 0d48f2373e8d..e8573d6b6005 100644
--- a/drivers/media/platform/samsung/exynos-mfc/base/mfc_format.h
+++ b/drivers/media/platform/samsung/exynos-mfc/base/mfc_format.h
@@ -263,6 +263,14 @@ static struct mfc_fmt mfc_formats[] = {
 		.num_planes = 1,
 		.mem_planes = 1,
 	},
+	{
+		.name = "ENC H264",
+		.fourcc = V4L2_PIX_FMT_H264,
+		.codec_mode = MFC_REG_CODEC_H264_ENC,
+		.type = MFC_FMT_STREAM | MFC_FMT_ENC,
+		.num_planes = 1,
+		.mem_planes = 1,
+	},
 };
 
 #endif /* __MFC_FORMAT_H */
diff --git a/drivers/media/platform/samsung/exynos-mfc/mfc.c b/drivers/media/platform/samsung/exynos-mfc/mfc.c
index db17448eae13..68cba41b45da 100644
--- a/drivers/media/platform/samsung/exynos-mfc/mfc.c
+++ b/drivers/media/platform/samsung/exynos-mfc/mfc.c
@@ -23,6 +23,8 @@
 
 #include "mfc_dec_v4l2.h"
 #include "mfc_dec_vb2.h"
+#include "mfc_enc_v4l2.h"
+#include "mfc_enc_vb2.h"
 #include "mfc_rm.h"
 #include "mfc_debugfs.h"
 
@@ -228,6 +230,107 @@ static int __mfc_init_dec_ctx(struct mfc_ctx *ctx)
 	return ret;
 }
 
+static void __mfc_deinit_enc_ctx(struct mfc_ctx *ctx)
+{
+	struct mfc_enc *enc = ctx->enc_priv;
+
+	mfc_delete_queue(&ctx->src_buf_ready_queue);
+	mfc_delete_queue(&ctx->dst_buf_queue);
+	mfc_delete_queue(&ctx->ref_buf_queue);
+	mfc_delete_queue(&ctx->err_buf_queue);
+	mfc_delete_queue(&ctx->meminfo_inbuf_q);
+	mfc_delete_queue(&ctx->meminfo_outbuf_q);
+
+	mfc_mem_cleanup_user_shared_handle(ctx, &enc->sh_handle_svc);
+	mfc_mem_cleanup_user_shared_handle(ctx, &enc->sh_handle_roi);
+
+	kfree(enc);
+}
+
+static int __mfc_init_enc_ctx(struct mfc_ctx *ctx)
+{
+	struct mfc_enc *enc;
+	struct mfc_enc_params *p;
+	int ret = 0;
+	int i;
+
+	enc = kzalloc(sizeof(*enc), GFP_KERNEL);
+	if (!enc)
+		return -ENOMEM;
+
+	ctx->enc_priv = enc;
+	ctx->user_prio = -1;
+
+	mfc_create_queue(&ctx->src_buf_ready_queue);
+	mfc_create_queue(&ctx->dst_buf_queue);
+	mfc_create_queue(&ctx->ref_buf_queue);
+	mfc_create_queue(&ctx->err_buf_queue);
+	mfc_create_queue(&ctx->meminfo_inbuf_q);
+	mfc_create_queue(&ctx->meminfo_outbuf_q);
+
+	for (i = 0; i < MFC_MAX_BUFFERS; i++) {
+		INIT_LIST_HEAD(&ctx->src_ctrls[i]);
+		INIT_LIST_HEAD(&ctx->dst_ctrls[i]);
+	}
+	bitmap_zero(ctx->src_ctrls_avail, MFC_MAX_BUFFERS);
+	bitmap_zero(ctx->dst_ctrls_avail, MFC_MAX_BUFFERS);
+
+	ctx->type = MFCINST_ENCODER;
+	ctx->c_ops = &mfc_ctrls_ops;
+	ctx->b_ops = &mfc_bufs_ops;
+
+	mfc_enc_set_default_format(ctx);
+	mfc_rate_reset_framerate(ctx);
+
+	ctx->qos_ratio = 100;
+
+	/* disable IVF header by default (VP8, VP9) */
+	p = &enc->params;
+	p->ivf_header_disable = 1;
+
+	INIT_LIST_HEAD(&ctx->bitrate_list);
+	INIT_LIST_HEAD(&ctx->src_ts.ts_list);
+
+	enc->sh_handle_svc.fd = -1;
+	enc->sh_handle_roi.fd = -1;
+	enc->sh_handle_svc.data_size = sizeof(struct temporal_layer_info);
+	enc->sh_handle_roi.data_size = sizeof(struct mfc_enc_roi_info);
+
+	/* 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 = (unsigned int)sizeof(struct mfc_buf);
+	ctx->vq_src.io_modes = VB2_USERPTR | VB2_DMABUF;
+	ctx->vq_src.ops = mfc_get_enc_vb2_ops();
+	ctx->vq_src.mem_ops = mfc_mem_ops();
+	ctx->vq_src.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+	ret = vb2_queue_init(&ctx->vq_src);
+	if (ret) {
+		mfc_ctx_err("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 = (unsigned int)sizeof(struct mfc_buf);
+	ctx->vq_dst.io_modes = VB2_USERPTR | VB2_DMABUF;
+	ctx->vq_dst.ops = mfc_get_enc_vb2_ops();
+	ctx->vq_dst.mem_ops = mfc_mem_ops();
+	ctx->vq_dst.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+	ret = vb2_queue_init(&ctx->vq_dst);
+	if (ret) {
+		mfc_ctx_err("Failed to initialize videobuf2 queue(capture)\n");
+		goto fail_enc_init;
+	}
+
+	return 0;
+
+fail_enc_init:
+	__mfc_deinit_enc_ctx(ctx);
+	return 0;
+}
+
 /* Open an MFC node */
 static int mfc_open(struct file *file)
 {
@@ -339,6 +442,7 @@ static int mfc_open(struct file *file)
 		ret = __mfc_init_dec_ctx(ctx);
 		dev->num_dec_inst++;
 	} else {
+		ret = __mfc_init_enc_ctx(ctx);
 		dev->num_enc_inst++;
 	}
 	if (ret)
@@ -351,8 +455,8 @@ static int mfc_open(struct file *file)
 		/* idle mode */
 		spin_lock_init(&dev->idle_bits_lock);
 	}
-	if (mfc_is_decoder_node(node))
-		ret = call_cop(ctx, init_ctx_ctrls, ctx);
+
+	ret = call_cop(ctx, init_ctx_ctrls, ctx);
 	if (ret) {
 		mfc_ctx_err("failed in init_ctx_ctrls\n");
 		goto err_ctx_init;
@@ -449,12 +553,10 @@ static int mfc_release(struct file *file)
 	 * So, we need to performed stop_streaming
 	 * before instance de-init(CLOSE_INSTANCE).
 	 */
-	if (ctx->type == MFCINST_DECODER) {
-		vb2_queue_release(&ctx->vq_src);
-		vb2_queue_release(&ctx->vq_dst);
+	vb2_queue_release(&ctx->vq_src);
+	vb2_queue_release(&ctx->vq_dst);
 
-		call_cop(ctx, cleanup_ctx_ctrls, ctx);
-	}
+	call_cop(ctx, cleanup_ctx_ctrls, ctx);
 
 	ret = mfc_rm_instance_deinit(dev, ctx);
 	if (ret) {
@@ -471,6 +573,7 @@ static int mfc_release(struct file *file)
 		__mfc_deinit_dec_ctx(ctx);
 		dev->num_dec_inst--;
 	} else if (ctx->type == MFCINST_ENCODER) {
+		__mfc_deinit_enc_ctx(ctx);
 		dev->num_enc_inst--;
 	}
 
@@ -609,6 +712,12 @@ static int __mfc_parse_dt(struct device_node *np, struct mfc_dev *mfc)
 	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);
 	of_property_read_u32_array
 		(np, "vp9_stride_align",
 		&pdata->vp9_stride_align.support, 2);
@@ -618,6 +727,30 @@ static int __mfc_parse_dt(struct device_node *np, struct mfc_dev *mfc)
 	of_property_read_u32_array
 		(np, "wait_fw_status",
 		&pdata->wait_fw_status.support, 2);
+	of_property_read_u32_array
+		(np, "average_qp",
+		&pdata->average_qp.support, 2);
+	of_property_read_u32_array
+		(np, "mv_search_mode",
+		&pdata->mv_search_mode.support, 2);
+	of_property_read_u32_array
+		(np, "enc_idr_flag",
+		&pdata->enc_idr_flag.support, 2);
+	of_property_read_u32_array
+		(np, "min_quality_mode",
+		&pdata->min_quality_mode.support, 2);
+	of_property_read_u32_array
+		(np, "enc_capability",
+		&pdata->enc_capability.support, 2);
+	of_property_read_u32_array
+		(np, "enc_ts_delta",
+		&pdata->enc_ts_delta.support, 2);
+	of_property_read_u32_array
+		(np, "wfd_rc_mode",
+		&pdata->wfd_rc_mode.support, 2);
+	of_property_read_u32_array
+		(np, "max_i_frame_size",
+		&pdata->max_i_frame_size.support, 2);
 	of_property_read_u32_array
 		(np, "hevc_pic_output_flag",
 		&pdata->hevc_pic_output_flag.support, 2);
@@ -630,10 +763,14 @@ static int __mfc_parse_dt(struct device_node *np, struct mfc_dev *mfc)
 
 	/* Formats */
 	of_property_read_u32(np, "support_422", &pdata->support_422);
+	of_property_read_u32(np, "support_rgb", &pdata->support_rgb);
 
 	/* Resolution */
 	of_property_read_u32(np, "support_check_res", &pdata->support_check_res);
 
+	/* HWAPG */
+	of_property_read_u32(np, "support_hwapg", &pdata->support_hwapg);
+
 	/* HWACG */
 	of_property_read_u32(np, "support_hwacg", &pdata->support_hwacg);
 
@@ -643,6 +780,39 @@ static int __mfc_parse_dt(struct device_node *np, struct mfc_dev *mfc)
 	/* output buffer Q framerate */
 	of_property_read_u32(np, "display_framerate", &pdata->display_framerate);
 
+	/* 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);
+	}
+
+	/* MFC bandwidth information */
+	of_property_read_u32_array
+		(np, "bw_enc_h264",
+		&pdata->mfc_bw_info.bw_enc_h264.peak, 3);
+	of_property_read_u32_array
+		(np, "bw_enc_hevc",
+		&pdata->mfc_bw_info.bw_enc_hevc.peak, 3);
+	of_property_read_u32_array
+		(np, "bw_enc_hevc_10bit",
+		&pdata->mfc_bw_info.bw_enc_hevc_10bit.peak, 3);
+	of_property_read_u32_array
+		(np, "bw_enc_vp8",
+		&pdata->mfc_bw_info.bw_enc_vp8.peak, 3);
+	of_property_read_u32_array
+		(np, "bw_enc_vp9",
+		&pdata->mfc_bw_info.bw_enc_vp9.peak, 3);
+	of_property_read_u32_array
+		(np, "bw_enc_vp9_10bit",
+		&pdata->mfc_bw_info.bw_enc_vp9_10bit.peak, 3);
+	of_property_read_u32_array
+		(np, "bw_enc_mpeg4",
+		&pdata->mfc_bw_info.bw_enc_mpeg4.peak, 3);
 	of_property_read_u32_array
 		(np, "bw_dec_h264",
 		&pdata->mfc_bw_info.bw_dec_h264.peak, 3);
@@ -745,6 +915,11 @@ static int __mfc_parse_dt(struct device_node *np, struct mfc_dev *mfc)
 	of_property_read_u32(np, "scheduler", &pdata->scheduler);
 	of_property_read_u32(np, "pbs_num_prio", &pdata->pbs_num_prio);
 
+	/* Encoder RGB CSC formula by VUI from F/W */
+	of_property_read_u32(np, "enc_rgb_csc_by_fw", &pdata->enc_rgb_csc_by_fw);
+
+	of_property_read_u32(np, "support_enc_mode1", &pdata->support_enc_mode1);
+
 	of_property_read_u32(np, "support_mv_hevc", &pdata->support_mv_hevc);
 
 	return 0;
@@ -771,7 +946,7 @@ static struct video_device *__mfc_video_device_register
 	if (IS_DEC_NODE(node_num))
 		vfd->ioctl_ops = mfc_get_dec_v4l2_ioctl_ops();
 	else if (IS_ENC_NODE(node_num))
-		vfd->ioctl_ops = NULL;
+		vfd->ioctl_ops = mfc_get_enc_v4l2_ioctl_ops();
 
 	vfd->lock = &dev->mfc_mutex;
 	vfd->v4l2_dev = &dev->v4l2_dev;
@@ -1126,7 +1301,7 @@ static const struct dev_pm_ops mfc_pm_ops = {
 struct mfc_ctx_buf_size mfc_ctx_buf_size = {
 	.dev_ctx	= PAGE_ALIGN(0x7800),	/*  30KB */
 	.h264_dec_ctx	= PAGE_ALIGN(0x200000),	/* 1.6MB */
-	.av1_dec_ctx	= PAGE_ALIGN(0x19000),	/* 100KB */
+	.av1_dec_ctx    = PAGE_ALIGN(0x19000),  /* 100KB */
 	.other_dec_ctx	= PAGE_ALIGN(0xF000),	/*  60KB */
 	.h264_enc_ctx	= PAGE_ALIGN(0x19000),	/* 100KB */
 	.hevc_enc_ctx	= PAGE_ALIGN(0xC800),	/*  50KB */
diff --git a/drivers/media/platform/samsung/exynos-mfc/mfc_core.c b/drivers/media/platform/samsung/exynos-mfc/mfc_core.c
index aad3273ce2ba..2d9c2ffef0d4 100644
--- a/drivers/media/platform/samsung/exynos-mfc/mfc_core.c
+++ b/drivers/media/platform/samsung/exynos-mfc/mfc_core.c
@@ -29,6 +29,7 @@
 #include "mfc_core_ops.h"
 #include "mfc_core_isr.h"
 #include "mfc_dec_v4l2.h"
+#include "mfc_enc_v4l2.h"
 #include "mfc_debugfs.h"
 
 #include "mfc_core_hwlock.h"
@@ -79,6 +80,8 @@ static int __mfc_core_parse_mfc_qos_platdata(struct device_node *np,
 	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);
 
 	of_property_read_string(np_qos, "bts_scen", &qosdata->name);
@@ -214,6 +217,8 @@ static int __mfc_core_parse_dt(struct device_node *np, struct mfc_core *core)
 	/* QoS */
 	of_property_read_u32(np, "num_default_qos_steps",
 			     &pdata->num_default_qos_steps);
+	of_property_read_u32(np, "num_encoder_qos_steps",
+			     &pdata->num_encoder_qos_steps);
 	of_property_read_u32(np, "max_mb", &pdata->max_mb);
 	of_property_read_u32(np, "max_hw_mb", &pdata->max_hw_mb);
 	of_property_read_u32(np, "mfc_freq_control", &pdata->mfc_freq_control);
@@ -233,6 +238,18 @@ static int __mfc_core_parse_dt(struct device_node *np, struct mfc_core *core)
 						  core);
 	}
 
+	pdata->encoder_qos_table = devm_kzalloc(core->device,
+						sizeof(struct mfc_qos) *
+						pdata->num_encoder_qos_steps,
+						GFP_KERNEL);
+	for (i = 0; i < pdata->num_encoder_qos_steps; i++) {
+		snprintf(node_name, sizeof(node_name), "mfc_e_qos_variant_%d",
+			 i);
+		__mfc_core_parse_mfc_qos_platdata(np, node_name,
+						  &pdata->encoder_qos_table[i],
+						  core);
+	}
+
 	/* performance boost mode */
 	pdata->qos_boost_table = devm_kzalloc(core->device,
 					      sizeof(struct mfc_qos_boost),
@@ -466,6 +483,15 @@ static int mfc_core_probe(struct platform_device *pdev)
 		     core->core_pdata->default_qos_table[i].freq_mif,
 		     core->core_pdata->default_qos_table[i].name,
 		     core->core_pdata->default_qos_table[i].bts_scen_idx);
+	mfc_core_info("[QoS]-------------------Encoder only table\n");
+	for (i = 0; i < core->core_pdata->num_encoder_qos_steps; i++)
+		mfc_core_info
+		    ("[QoS] table[%d] mfc: %d, int: %d, mif: %d, bts_scen: %s(%d)\n",
+		     i, core->core_pdata->encoder_qos_table[i].freq_mfc,
+		     core->core_pdata->encoder_qos_table[i].freq_int,
+		     core->core_pdata->encoder_qos_table[i].freq_mif,
+		     core->core_pdata->encoder_qos_table[i].name,
+		     core->core_pdata->encoder_qos_table[i].bts_scen_idx);
 #if IS_ENABLED(CONFIG_SAMSUNG_IOMMU)
 	ret = samsung_iommu_register_fault_handler(core->device,
 						   mfc_core_sysmmu_fault_handler,
diff --git a/drivers/media/platform/samsung/exynos-mfc/mfc_core_buf_ctrl.c b/drivers/media/platform/samsung/exynos-mfc/mfc_core_buf_ctrl.c
index 38f09d6ef2dd..cc0a20bea33a 100644
--- a/drivers/media/platform/samsung/exynos-mfc/mfc_core_buf_ctrl.c
+++ b/drivers/media/platform/samsung/exynos-mfc/mfc_core_buf_ctrl.c
@@ -11,6 +11,250 @@
 
 #include "mfc_core_reg_api.h"
 
+static void __mfc_enc_store_buf_ctrls_temporal_svc(int id,
+						   struct mfc_enc_params *p,
+						   struct temporal_layer_info
+						   *temporal_LC)
+{
+	unsigned int num_layer = temporal_LC->temporal_layer_count;
+	int i;
+
+	switch (id) {
+	case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_CH:
+		p->codec.h264.num_hier_layer = num_layer & 0x7;
+		for (i = 0; i < (num_layer & 0x7); i++)
+			p->codec.h264.hier_bit_layer[i] =
+			    temporal_LC->temporal_layer_bitrate[i];
+		break;
+	default:
+		break;
+	}
+}
+
+static void __mfc_core_enc_set_buf_ctrls_temporal_svc(struct mfc_core *core,
+						      struct mfc_ctx *ctx,
+						      struct mfc_buf_ctrl
+						      *buf_ctrl)
+{
+	struct mfc_enc *enc = ctx->enc_priv;
+	unsigned int value = 0, value2 = 0;
+	struct temporal_layer_info temporal_LC;
+	unsigned int i;
+	struct mfc_enc_params *p = &enc->params;
+
+	if (buf_ctrl->id
+	    == V4L2_CID_MPEG_VIDEO_H264_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) {
+			/* clear NUM_T_LAYER_CHANGE */
+			value = MFC_CORE_READL(buf_ctrl->flag_addr);
+			value &= ~BIT(10);
+			MFC_CORE_WRITEL(value, buf_ctrl->flag_addr);
+			mfc_ctx_err
+			    ("[HIERARCHICAL] layer count is invalid : %d\n",
+			     temporal_LC.temporal_layer_count);
+			return;
+		}
+
+		value = MFC_CORE_READL(buf_ctrl->flag_addr);
+		value &= ~(0x3 << 21);
+
+		MFC_CORE_WRITEL(value, buf_ctrl->flag_addr);
+
+		/* Store temporal layer information */
+		__mfc_enc_store_buf_ctrls_temporal_svc(buf_ctrl->id, p,
+						       &temporal_LC);
+
+		/* enable RC_BIT_RATE_CHANGE */
+		value = MFC_CORE_READL(buf_ctrl->flag_addr);
+		if (temporal_LC.temporal_layer_bitrate[0] > 0 ||
+		    p->hier_bitrate_ctrl)
+			/* set RC_BIT_RATE_CHANGE */
+			value |= BIT(2);
+		else
+			/* clear RC_BIT_RATE_CHANGE */
+			value &= ~BIT(2);
+		MFC_CORE_WRITEL(value, buf_ctrl->flag_addr);
+
+		mfc_ctx_debug(3,
+			      "[HIERARCHICAL] layer count %d, E_PARAM_CHANGE %#x\n",
+			      temporal_LC.temporal_layer_count & 0x7, value);
+
+		value = MFC_CORE_READL(MFC_REG_E_NUM_T_LAYER);
+		buf_ctrl->old_val2 = value;
+		value &= ~(0x7);
+		value |= (temporal_LC.temporal_layer_count & 0x7);
+		value &= ~BIT(8);
+		value |= (p->hier_bitrate_ctrl & 0x1) << 8;
+		MFC_CORE_WRITEL(value, MFC_REG_E_NUM_T_LAYER);
+		mfc_ctx_debug(3, "[HIERARCHICAL] E_NUM_T_LAYER %#x\n", value);
+		for (i = 0; i < (temporal_LC.temporal_layer_count & 0x7); i++) {
+			mfc_ctx_debug(3,
+				      "[HIERARCHICAL] layer bitrate[%d] %d (FW ctrl: %d)\n",
+				      i, temporal_LC.temporal_layer_bitrate[i],
+				      p->hier_bitrate_ctrl);
+			MFC_CORE_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_CORE_WRITEL(value,
+					MFC_REG_E_H264_HD_SVC_EXTENSION_0);
+			MFC_CORE_WRITEL(value2,
+					MFC_REG_E_H264_HD_SVC_EXTENSION_1);
+			mfc_ctx_debug(3,
+				      "[HIERARCHICAL] EXTENSION0 %#x, EXTENSION1 %#x\n",
+				      value, value2);
+
+			value = MFC_CORE_READL(buf_ctrl->flag_addr);
+			value |= BIT(12);
+			MFC_CORE_WRITEL(value, buf_ctrl->flag_addr);
+			mfc_ctx_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_CORE_READL(MFC_REG_E_H264_HD_SVC_EXTENSION_0);
+		buf_ctrl->old_val |= value & 0x3FFFFFC0;
+		value &= ~(0x3FFFFFC0);
+		value2 = MFC_CORE_READL(MFC_REG_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_CORE_WRITEL(value, MFC_REG_E_H264_HD_SVC_EXTENSION_0);
+		MFC_CORE_WRITEL(value2, MFC_REG_E_H264_HD_SVC_EXTENSION_1);
+		mfc_ctx_debug(3,
+			      "[HIERARCHICAL] EXTENSION0 %#x, EXTENSION1 %#x\n",
+			      value, value2);
+	}
+}
+
+static void __mfc_core_enc_set_buf_ctrls_exception(struct mfc_core *core,
+						   struct mfc_ctx *ctx,
+						   struct mfc_buf_ctrl
+						   *buf_ctrl)
+{
+	struct mfc_enc *enc = ctx->enc_priv;
+	struct mfc_enc_params *p = &enc->params;
+	unsigned int value = 0;
+
+	/* temporal layer setting */
+	__mfc_core_enc_set_buf_ctrls_temporal_svc(core, ctx, buf_ctrl);
+
+	if (buf_ctrl->id == V4L2_CID_MPEG_MFC_H264_MARK_LTR) {
+		value = MFC_CORE_READL(MFC_REG_E_H264_NAL_CONTROL);
+		buf_ctrl->old_val2 = (value >> 8) & 0x7;
+		value &= ~(0x7 << 8);
+		value |= (buf_ctrl->val & 0x7) << 8;
+		MFC_CORE_WRITEL(value, MFC_REG_E_H264_NAL_CONTROL);
+	}
+	if (buf_ctrl->id == V4L2_CID_MPEG_MFC_H264_USE_LTR) {
+		value = MFC_CORE_READL(MFC_REG_E_H264_NAL_CONTROL);
+		buf_ctrl->old_val2 = (value >> 11) & 0xF;
+		value &= ~GENMASK(14, 11);
+		value |= (buf_ctrl->val & 0xF) << 11;
+		MFC_CORE_WRITEL(value, MFC_REG_E_H264_NAL_CONTROL);
+	}
+
+	if (buf_ctrl->id == V4L2_CID_MPEG_MFC51_VIDEO_I_PERIOD_CH) {
+		value = MFC_CORE_READL(MFC_REG_E_GOP_CONFIG2);
+		buf_ctrl->old_val |= (value << 16) & 0x3FFF0000;
+		value &= ~(0x3FFF);
+		value |= (buf_ctrl->val >> 16) & 0x3FFF;
+		MFC_CORE_WRITEL(value, MFC_REG_E_GOP_CONFIG2);
+	}
+
+	/* PROFILE & LEVEL have to be set up together */
+	if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_H264_LEVEL) {
+		value = MFC_CORE_READL(MFC_REG_E_PICTURE_PROFILE);
+		buf_ctrl->old_val |= (value & 0x000F) << 8;
+		value &= ~(0x000F);
+		value |= p->codec.h264.profile & 0x000F;
+		MFC_CORE_WRITEL(value, MFC_REG_E_PICTURE_PROFILE);
+		p->codec.h264.level = buf_ctrl->val;
+	}
+
+	if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_H264_PROFILE) {
+		value = MFC_CORE_READL(MFC_REG_E_PICTURE_PROFILE);
+		buf_ctrl->old_val |= value & 0xFF00;
+		value &= ~(0x00FF << 8);
+		value |= (p->codec.h264.level << 8) & 0xFF00;
+		MFC_CORE_WRITEL(value, MFC_REG_E_PICTURE_PROFILE);
+		p->codec.h264.profile = buf_ctrl->val;
+	}
+
+	/* set the ROI buffer DVA */
+	if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_ROI_CONTROL) {
+		MFC_CORE_DMA_WRITEL(enc->roi_buf[buf_ctrl->old_val2].daddr,
+				    MFC_REG_E_ROI_BUFFER_ADDR);
+		mfc_ctx_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);
+	}
+
+	/* set frame rate change with delta */
+	if (buf_ctrl->id == V4L2_CID_MPEG_MFC51_VIDEO_FRAME_RATE_CH) {
+		p->rc_frame_delta = p->rc_framerate_res / buf_ctrl->val;
+		value = MFC_CORE_READL(buf_ctrl->addr);
+		value &= ~(buf_ctrl->mask << buf_ctrl->shft);
+		value |=
+		    ((p->rc_frame_delta & buf_ctrl->mask) << buf_ctrl->shft);
+		MFC_CORE_WRITEL(value, buf_ctrl->addr);
+	}
+
+	/* set drop control */
+	if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_DROP_CONTROL) {
+		p->rc_frame_delta = mfc_enc_get_ts_delta(ctx);
+		value = MFC_CORE_READL(MFC_REG_E_RC_FRAME_RATE);
+		value &= ~(0xFFFF);
+		value |= (p->rc_frame_delta & 0xFFFF);
+		MFC_CORE_WRITEL(value, MFC_REG_E_RC_FRAME_RATE);
+		if (ctx->src_ts.ts_last_interval)
+			mfc_ctx_debug(3,
+				      "[DROPCTRL] fps %d -> %ld, delta: %d, reg: %#x\n",
+				      p->rc_framerate,
+				      USEC_PER_SEC /
+				      ctx->src_ts.ts_last_interval,
+				      p->rc_frame_delta, value);
+		else
+			mfc_ctx_debug(3,
+				      "[DROPCTRL] fps %d -> 0, delta: %d, reg: %#x\n",
+				      p->rc_framerate, p->rc_frame_delta,
+				      value);
+	}
+
+	/* store last config qp value in F/W */
+	if (buf_ctrl->id == V4L2_CID_MPEG_MFC_CONFIG_QP)
+		enc->config_qp = p->config_qp;
+}
+
 static int mfc_core_set_buf_ctrls(struct mfc_core *core,
 				  struct mfc_ctx *ctx, struct list_head *head)
 {
@@ -51,6 +295,10 @@ static int mfc_core_set_buf_ctrls(struct mfc_core *core,
 		if (buf_ctrl->id == V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG)
 			ctx->stored_tag = buf_ctrl->val;
 
+		if (ctx->type == MFCINST_ENCODER)
+			__mfc_core_enc_set_buf_ctrls_exception(core, ctx,
+							       buf_ctrl);
+
 		mfc_ctx_debug(6,
 			      "[CTRLS] Set buffer control id: 0x%08x, val: %d (%#x)\n",
 			      buf_ctrl->id, buf_ctrl->val, buf_ctrl->val);
@@ -64,6 +312,7 @@ static int mfc_core_get_buf_ctrls(struct mfc_core *core,
 {
 	struct mfc_buf_ctrl *buf_ctrl;
 	struct mfc_dec *dec = ctx->dec_priv;
+	struct mfc_enc *enc = ctx->enc_priv;
 	unsigned int value = 0;
 
 	list_for_each_entry(buf_ctrl, head, list) {
@@ -89,6 +338,10 @@ static int mfc_core_get_buf_ctrls(struct mfc_core *core,
 		if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_FRAME_ERROR_TYPE)
 			buf_ctrl->val = mfc_get_frame_error_type(ctx, value);
 
+		if (buf_ctrl->id == V4L2_CID_MPEG_MFC51_VIDEO_FRAME_STATUS)
+			if (enc)
+				buf_ctrl->val = !enc->in_slice;
+
 		mfc_ctx_debug(6,
 			      "[CTRLS] Get buffer control id: 0x%08x, val: %d (%#x)\n",
 			      buf_ctrl->id, buf_ctrl->val, buf_ctrl->val);
@@ -97,6 +350,69 @@ static int mfc_core_get_buf_ctrls(struct mfc_core *core,
 	return 0;
 }
 
+static void __mfc_core_enc_recover_buf_ctrls_exception(struct mfc_core *core,
+						       struct mfc_ctx *ctx,
+						       struct mfc_buf_ctrl
+						       *buf_ctrl)
+{
+	unsigned int value = 0;
+
+	if (buf_ctrl->id == V4L2_CID_MPEG_MFC51_VIDEO_I_PERIOD_CH) {
+		value = MFC_CORE_READL(MFC_REG_E_GOP_CONFIG2);
+		value &= ~(0x3FFF);
+		value |= (buf_ctrl->old_val >> 16) & 0x3FFF;
+		MFC_CORE_WRITEL(value, MFC_REG_E_GOP_CONFIG2);
+	}
+
+	if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_H264_LEVEL) {
+		value = MFC_CORE_READL(MFC_REG_E_PICTURE_PROFILE);
+		value &= ~(0x000F);
+		value |= (buf_ctrl->old_val >> 8) & 0x000F;
+		MFC_CORE_WRITEL(value, MFC_REG_E_PICTURE_PROFILE);
+	}
+
+	if (buf_ctrl->id == V4L2_CID_MPEG_VIDEO_H264_PROFILE) {
+		value = MFC_CORE_READL(MFC_REG_E_PICTURE_PROFILE);
+		value &= ~(0xFF00);
+		value |= buf_ctrl->old_val & 0xFF00;
+		MFC_CORE_WRITEL(value, MFC_REG_E_PICTURE_PROFILE);
+	}
+
+	if (buf_ctrl->id == V4L2_CID_MPEG_MFC_H264_BASE_PRIORITY) {
+		MFC_CORE_WRITEL(buf_ctrl->old_val,
+				MFC_REG_E_H264_HD_SVC_EXTENSION_0);
+		MFC_CORE_WRITEL(buf_ctrl->old_val2,
+				MFC_REG_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_CORE_WRITEL(buf_ctrl->old_val2, MFC_REG_E_NUM_T_LAYER);
+		/* clear RC_BIT_RATE_CHANGE */
+		value = MFC_CORE_READL(buf_ctrl->flag_addr);
+		value &= ~BIT(2);
+		MFC_CORE_WRITEL(value, buf_ctrl->flag_addr);
+	}
+
+	if (buf_ctrl->id == V4L2_CID_MPEG_MFC_H264_MARK_LTR) {
+		value = MFC_CORE_READL(MFC_REG_E_H264_NAL_CONTROL);
+		value &= ~(0x7 << 8);
+		value |= (buf_ctrl->old_val2 & 0x7) << 8;
+		MFC_CORE_WRITEL(value, MFC_REG_E_H264_NAL_CONTROL);
+	}
+
+	if (buf_ctrl->id == V4L2_CID_MPEG_MFC_H264_USE_LTR) {
+		value = MFC_CORE_READL(MFC_REG_E_H264_NAL_CONTROL);
+		value &= ~GENMASK(14, 11);
+		value |= (buf_ctrl->old_val2 & 0xF) << 11;
+		MFC_CORE_WRITEL(value, MFC_REG_E_H264_NAL_CONTROL);
+	}
+}
+
 static int mfc_core_recover_buf_ctrls(struct mfc_core *core,
 				      struct mfc_ctx *ctx,
 				      struct list_head *head)
@@ -125,6 +441,11 @@ static int mfc_core_recover_buf_ctrls(struct mfc_core *core,
 			MFC_CORE_WRITEL(value, buf_ctrl->flag_addr);
 		}
 
+		/* Exception */
+		if (ctx->type == MFCINST_ENCODER)
+			__mfc_core_enc_recover_buf_ctrls_exception(core, ctx,
+								   buf_ctrl);
+
 		buf_ctrl->updated = 0;
 		mfc_ctx_debug(6,
 			      "[CTRLS] Recover buffer control id: 0x%08x, old val: %d\n",
diff --git a/drivers/media/platform/samsung/exynos-mfc/mfc_core_isr.c b/drivers/media/platform/samsung/exynos-mfc/mfc_core_isr.c
index aa2c0b618c19..1a3cf7e76e29 100644
--- a/drivers/media/platform/samsung/exynos-mfc/mfc_core_isr.c
+++ b/drivers/media/platform/samsung/exynos-mfc/mfc_core_isr.c
@@ -777,6 +777,9 @@ static void __mfc_handle_error_state(struct mfc_ctx *ctx, struct mfc_core_ctx *c
 	/* Mark all src buffers as having an error */
 	mfc_cleanup_queue(&ctx->buf_queue_lock, &ctx->src_buf_ready_queue);
 	mfc_cleanup_queue(&ctx->buf_queue_lock, &core_ctx->src_buf_queue);
+	if (ctx->type == MFCINST_ENCODER)
+		mfc_cleanup_queue(&ctx->buf_queue_lock, &ctx->ref_buf_queue);
+	/* Mark all NAL_Q buffers as having an error */
 }
 
 void mfc_core_handle_error(struct mfc_core *core)
@@ -885,6 +888,11 @@ static void __mfc_handle_frame_error(struct mfc_core *core,
 	unsigned int index;
 	enum vb2_buffer_state vb2_state;
 
+	if (ctx->type == MFCINST_ENCODER) {
+		mfc_info("Encoder Interrupt Error (err: %d)\n", mfc_get_err(err));
+		return;
+	}
+
 	dec = ctx->dec_priv;
 	if (!dec) {
 		mfc_err("no mfc decoder to run\n");
@@ -1267,12 +1275,428 @@ static void __mfc_handle_frame(struct mfc_core *core,
 	mfc_debug(2, "Assesing whether this context should be run again\n");
 }
 
-static inline void __mfc_handle_done_frame(struct mfc_core *core,
-					   struct mfc_ctx *ctx,
-					   unsigned int reason,
-					   unsigned int err)
+static void __mfc_handle_error_input(struct mfc_core *core, struct mfc_ctx *ctx)
+{
+	struct mfc_buf *mfc_buf = NULL;
+	int index;
+
+	while (1) {
+		mfc_buf = mfc_get_del_buf(ctx, &ctx->err_buf_queue, MFC_BUF_NO_TOUCH_USED);
+		if (!mfc_buf)
+			break;
+
+		index = mfc_buf->vb.vb2_buf.index;
+
+		if (call_bop(ctx, core_recover_buf_ctrls, core, ctx,
+			     &ctx->src_ctrls[index]) < 0)
+			mfc_ctx_err("failed in core_recover_buf_ctrls\n");
+
+		if (call_bop(ctx, core_get_buf_ctrls, core, ctx,
+			     &ctx->src_ctrls[index]) < 0)
+			mfc_ctx_err("failed in core_get_buf_ctrls\n");
+
+		mfc_ctx_info("find src buf(fd: %d) in err_queue\n",
+			     mfc_buf->vb.vb2_buf.planes[0].m.fd);
+		mfc_clear_mb_flag(mfc_buf);
+		mfc_set_mb_flag(mfc_buf, MFC_FLAG_CONSUMED_ONLY);
+		vb2_buffer_done(&mfc_buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
+	}
+}
+
+static void __mfc_handle_stream_copy_timestamp(struct mfc_ctx *ctx, struct mfc_buf *src_mb)
+{
+	struct mfc_enc *enc = ctx->enc_priv;
+	struct mfc_enc_params *p = &enc->params;
+	struct mfc_buf *dst_mb;
+	u64 interval;
+	u64 start_timestamp;
+	u64 new_timestamp;
+
+	start_timestamp = src_mb->vb.vb2_buf.timestamp;
+	interval = NSEC_PER_SEC / p->rc_framerate;
+	if (ctx->dev->debugfs.debug_ts == 1)
+		mfc_ctx_info("[BUFCON][TS] %dfps, start timestamp: %lld, base interval: %lld\n",
+			     p->rc_framerate, start_timestamp, interval);
+
+	new_timestamp = start_timestamp + (interval * src_mb->done_index);
+	if (ctx->dev->debugfs.debug_ts == 1)
+		mfc_ctx_info("[BUFCON][TS] new timestamp: %lld, interval: %lld\n",
+			     new_timestamp, interval * src_mb->done_index);
+
+	/* Get the destination buffer */
+	dst_mb = mfc_get_buf(ctx, &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 mfc_core *core, struct mfc_ctx *ctx,
+				      int consumed_only)
 {
-	__mfc_handle_frame(core, ctx, reason, err);
+	struct mfc_core_ctx *core_ctx = core->core_ctx[ctx->num];
+	struct mfc_raw_info *raw;
+	struct mfc_buf *ref_mb, *src_mb;
+	dma_addr_t enc_addr[3] = { 0, 0, 0 };
+	struct mfc_enc *enc = ctx->enc_priv;
+	int i, found_in_src_queue = 0;
+	unsigned int index;
+
+	raw = &ctx->raw_buf;
+
+	mfc_core_get_enc_frame_buffer(core, ctx, &enc_addr[0], raw->num_planes);
+	if (enc_addr[0] == 0) {
+		mfc_debug(3, "no encoded src\n");
+
+		if (enc->fake_src && enc->params.num_b_frame) {
+			mfc_change_state(core_ctx, MFCINST_FINISHING);
+			enc->fake_src = 0;
+			mfc_debug(2, "clear fake_src and change to FINISHING\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 (ctx->multi_view_enable &&
+	    ctx->select_view == MFC_VIEW_ID_MAIN) {
+		mfc_debug(2, "not handling src_mb to reuse for VIEW_1\n");
+		return;
+	}
+
+	if (IS_BUFFER_BATCH_MODE(ctx)) {
+		src_mb = mfc_find_first_buf(ctx, &core_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;
+			/* single buffer || last image in a buffer container */
+			if (!src_mb->num_valid_bufs ||
+			    src_mb->done_index == src_mb->num_valid_bufs) {
+				if (consumed_only) {
+					mfc_clear_mb_flag(src_mb);
+					mfc_set_mb_flag(src_mb, MFC_FLAG_CONSUMED_ONLY);
+				}
+
+				if (call_bop(ctx, core_recover_buf_ctrls, core, ctx,
+					     &ctx->src_ctrls[index]) < 0)
+					mfc_err("failed in core_recover_buf_ctrls\n");
+
+				if (call_bop(ctx, core_get_buf_ctrls, core, ctx,
+					     &ctx->src_ctrls[index]) < 0)
+					mfc_err("failed in core_get_buf_ctrls\n");
+
+				src_mb = mfc_find_del_buf(ctx,
+							  &core_ctx->src_buf_queue,
+							  enc_addr[0]);
+				if (src_mb) {
+					for (i = 0; i < raw->num_planes; i++)
+						mfc_bufcon_put_daddr(ctx, src_mb, i);
+					vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
+				}
+			}
+		}
+	} else {
+		/* normal single buffer */
+		src_mb = mfc_find_del_buf(ctx, &core_ctx->src_buf_queue, enc_addr[0]);
+		if (src_mb) {
+			found_in_src_queue = 1;
+			index = src_mb->vb.vb2_buf.index;
+			if (consumed_only) {
+				mfc_clear_mb_flag(src_mb);
+				mfc_set_mb_flag(src_mb, MFC_FLAG_CONSUMED_ONLY);
+			}
+
+			if (call_bop(ctx, core_recover_buf_ctrls, core, ctx,
+				     &ctx->src_ctrls[index]) < 0)
+				mfc_err("failed in core_recover_buf_ctrls\n");
+
+			if (call_bop(ctx, core_get_buf_ctrls, core, ctx,
+				     &ctx->src_ctrls[index]) < 0)
+				mfc_err("failed in core_get_buf_ctrls\n");
+
+			mfc_debug(3, "find src buf in src_queue\n");
+			vb2_buffer_done(&src_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
+		} else {
+			mfc_debug(3, "no src buf in src_queue\n");
+			ref_mb = mfc_find_del_buf(ctx, &ctx->ref_buf_queue, enc_addr[0]);
+			if (ref_mb) {
+				index = ref_mb->vb.vb2_buf.index;
+				if (consumed_only) {
+					mfc_clear_mb_flag(ref_mb);
+					mfc_set_mb_flag(ref_mb, MFC_FLAG_CONSUMED_ONLY);
+				}
+
+				if (call_bop(ctx, core_recover_buf_ctrls, core, ctx,
+					     &ctx->src_ctrls[index]) < 0)
+					mfc_err("failed in core_recover_buf_ctrls\n");
+
+				if (call_bop(ctx, core_get_buf_ctrls, core, ctx,
+					     &ctx->src_ctrls[index]) < 0)
+					mfc_err("failed in core_get_buf_ctrls\n");
+
+				mfc_debug(3, "find src buf in ref_queue\n");
+				vb2_buffer_done(&ref_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
+			} else {
+				mfc_err("couldn't find src buffer\n");
+			}
+		}
+	}
+
+move_buf:
+	/* move enqueued src buffer: src queue -> ref queue */
+	if (!found_in_src_queue && core_ctx->state != MFCINST_FINISHING) {
+		mfc_get_move_buf_used(ctx, &ctx->ref_buf_queue, &core_ctx->src_buf_queue);
+
+		mfc_debug(2, "enc src_buf_queue(%d) -> ref_buf_queue(%d)\n",
+			  mfc_get_queue_count(&ctx->buf_queue_lock, &core_ctx->src_buf_queue),
+			  mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->ref_buf_queue));
+	}
+}
+
+static void __mfc_handle_stream_output(struct mfc_core *core,
+				       struct mfc_ctx *ctx,
+				       int slice_type,
+				       unsigned int strm_size)
+{
+	struct mfc_dev *dev = ctx->dev;
+	struct mfc_enc *enc = ctx->enc_priv;
+	struct mfc_buf *dst_mb;
+	unsigned int index, idr_flag = 1;
+
+	if (strm_size == 0) {
+		mfc_ctx_debug(3, "no encoded dst (reuse)\n");
+		return;
+	}
+
+	if (ctx->select_view == MFC_VIEW_ID_MAIN &&
+	    MFC_FEATURE_SUPPORT(dev, dev->pdata->enc_idr_flag))
+		enc->idr_flag = mfc_core_get_enc_idr_flag();
+	idr_flag = enc->idr_flag;
+
+	/* at least one more dest. buffers exist always  */
+	if (ctx->multi_view_enable &&
+	    ctx->select_view == MFC_VIEW_ID_MAIN) {
+		mfc_ctx_debug(2, "not handling dst_mb to reuse for VIEW_1\n");
+		return;
+	}
+
+	dst_mb = mfc_get_del_buf(ctx, &ctx->dst_buf_queue, MFC_BUF_NO_TOUCH_USED);
+	if (!dst_mb) {
+		mfc_ctx_err("no dst buffers\n");
+		return;
+	}
+
+	mfc_ctx_debug(2, "[BUFINFO] ctx[%d] get dst addr: 0x%08llx\n",
+		      ctx->num, dst_mb->addr[0][0]);
+
+	mfc_clear_mb_flag(dst_mb);
+	dst_mb->vb.flags &= ~(V4L2_BUF_FLAG_KEYFRAME |
+				V4L2_BUF_FLAG_PFRAME |
+				V4L2_BUF_FLAG_BFRAME);
+	switch (slice_type) {
+	case MFC_REG_E_SLICE_TYPE_I:
+		dst_mb->vb.flags |= V4L2_BUF_FLAG_KEYFRAME;
+		if (!(CODEC_HAS_IDR(ctx) && !idr_flag)) {
+			mfc_set_mb_flag(dst_mb, MFC_FLAG_SYNC_FRAME);
+			mfc_ctx_debug(2, "[STREAM] syncframe IDR\n");
+		}
+		break;
+	case MFC_REG_E_SLICE_TYPE_P:
+		dst_mb->vb.flags |= V4L2_BUF_FLAG_PFRAME;
+		break;
+	case MFC_REG_E_SLICE_TYPE_B:
+		dst_mb->vb.flags |= V4L2_BUF_FLAG_BFRAME;
+		break;
+	default:
+		dst_mb->vb.flags |= V4L2_BUF_FLAG_KEYFRAME;
+		break;
+	}
+	mfc_ctx_debug(2, "[STREAM] Slice type flag: %d\n", dst_mb->vb.flags);
+
+	if (IS_MULTI_MODE(ctx) &&
+	    !(dev->debugfs.feature_option & MFC_OPTION_STREAM_COPY_DISABLE)) {
+		unsigned int tile0_size, tile1_size;
+		unsigned int size;
+		unsigned char *vaddr;
+		struct sg_table *sgt;
+
+		tile0_size = MFC_CORE_READL(MFC_REG_E_TILE0_STREAM_SIZE);
+		tile1_size = MFC_CORE_READL(MFC_REG_E_TILE1_STREAM_SIZE);
+
+		size = (unsigned int)vb2_plane_size(&dst_mb->vb.vb2_buf, 0);
+		size = ALIGN(size, STREAM_BUF_ALIGN);
+
+		sgt = vb2_dma_sg_plane_desc(&dst_mb->vb.vb2_buf, 0);
+		dma_sync_sgtable_for_cpu(dev->device, sgt, DMA_BIDIRECTIONAL);
+
+		vaddr = vb2_plane_vaddr(&dst_mb->vb.vb2_buf, 0);
+		if (!vaddr)
+			mfc_ctx_err("failed to get vaddr for copying stream\n");
+		else
+			memmove(vaddr + tile0_size, vaddr + ALIGN(size / 2, 16), tile1_size);
+
+		mfc_ctx_debug(3, "memmove done: %d + %d\n", tile0_size, tile1_size);
+	}
+
+	vb2_set_plane_payload(&dst_mb->vb.vb2_buf, 0, strm_size);
+	mfc_rate_update_framerate(ctx);
+
+	index = dst_mb->vb.vb2_buf.index;
+	if (call_bop(ctx, core_get_buf_ctrls, core, ctx, &ctx->dst_ctrls[index]) < 0)
+		mfc_ctx_err("failed in core_get_buf_ctrls\n");
+
+	vb2_buffer_done(&dst_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
+}
+
+static void __mfc_handle_stream_last_output(struct mfc_core *core, struct mfc_ctx *ctx)
+{
+	struct mfc_buf *dst_mb;
+	unsigned int index;
+
+	/* at least one more dest. buffers exist always  */
+	dst_mb = mfc_get_del_buf(ctx, &ctx->dst_buf_queue, MFC_BUF_NO_TOUCH_USED);
+	if (!dst_mb) {
+		mfc_ctx_err("no dst buffers\n");
+		return;
+	}
+
+	mfc_ctx_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);
+
+	vb2_set_plane_payload(&dst_mb->vb.vb2_buf, 0, 0);
+
+	index = dst_mb->vb.vb2_buf.index;
+	if (call_bop(ctx, core_get_buf_ctrls, core, ctx, &ctx->dst_ctrls[index]) < 0)
+		mfc_ctx_err("failed in core_get_buf_ctrls\n");
+
+	mfc_ctx_debug(2, "[STREAM] update tag for last stream\n");
+	call_cop(ctx, update_buf_val, ctx, &ctx->dst_ctrls[index],
+		 V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG, ctx->stored_tag);
+
+	vb2_buffer_done(&dst_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
+}
+
+/* Handle frame encoding interrupt */
+static int __mfc_handle_stream(struct mfc_core *core, struct mfc_ctx *ctx, unsigned int reason)
+{
+	struct mfc_dev *dev = ctx->dev;
+	struct mfc_core *subcore;
+	struct mfc_enc *enc = ctx->enc_priv;
+	struct mfc_core_ctx *core_ctx = core->core_ctx[ctx->num];
+	int slice_type, consumed_only = 0;
+	unsigned int strm_size;
+	unsigned int pic_count;
+
+	slice_type = mfc_core_get_enc_slice_type();
+	strm_size = mfc_core_get_enc_strm_size();
+	pic_count = mfc_core_get_enc_pic_count();
+
+	mfc_debug(2, "[STREAM] encoded slice type: %d, size: %d, display order: %d\n",
+		  slice_type, strm_size, pic_count);
+
+	/* clear vOTF enable */
+	mfc_core_clear_enc_src_votf(core);
+
+	/* buffer full handling */
+	if (enc->buf_full) {
+		core_ctx->prev_state = core_ctx->state;
+		mfc_change_state(core_ctx, MFCINST_ABORT_INST);
+		return 0;
+	}
+	if (core_ctx->state == MFCINST_RUNNING_BUF_FULL)
+		mfc_change_state(core_ctx, core_ctx->prev_state);
+
+	/* set encoded frame type */
+	if (ctx->select_view == MFC_VIEW_ID_MAIN)
+		enc->frame_type = slice_type;
+	ctx->sequence++;
+
+	if (enc->in_slice) {
+		if (mfc_is_queue_count_same(&ctx->buf_queue_lock, &ctx->dst_buf_queue, 0))
+			core->sched->clear_work(core, core_ctx);
+		return 0;
+	}
+
+	if (mfc_qos_mb_calculate(core, core_ctx, mfc_core_get_processing_cycle(), slice_type)) {
+		mfc_qos_on(core, ctx);
+		if (IS_TWO_MODE1(ctx)) {
+			subcore = mfc_get_sub_core(dev, ctx);
+			if (subcore) {
+				subcore->core_ctx[ctx->num]->dynamic_weight_level =
+					core_ctx->dynamic_weight_level;
+				mfc_qos_on(subcore, ctx);
+			}
+		}
+	}
+
+	if (strm_size == 0 && !(enc->empty_data && reason == MFC_REG_R2H_CMD_COMPLETE_SEQ_RET)) {
+		mfc_debug(2, "[FRAME] dst buffer is not returned\n");
+		consumed_only = 1;
+	}
+
+	/* handle source buffer */
+	__mfc_handle_stream_input(core, ctx, consumed_only);
+
+	/* handle destination buffer */
+	if (enc->empty_data && reason == MFC_REG_R2H_CMD_COMPLETE_SEQ_RET) {
+		enc->empty_data = 0;
+		mfc_debug(2, "[FRAME] handle EOS for empty data\n");
+		__mfc_handle_stream_last_output(core, ctx);
+	} else {
+		__mfc_handle_stream_output(core, ctx, enc->frame_type, strm_size);
+	}
+	mfc_rate_update_bufq_framerate(ctx, MFC_TS_DST_DQ);
+
+	/* handle error buffer */
+	__mfc_handle_error_input(core, ctx);
+
+	if (ctx->multi_view_enable)
+		ctx->select_view = (ctx->select_view + 1) % MFC_NUM_MULTI_VIEW;
+
+	return 0;
+}
+
+static inline int __mfc_handle_done_frame(struct mfc_core *core,
+					  struct mfc_ctx *ctx,
+					  unsigned int reason,
+					  unsigned int err)
+{
+	struct mfc_core_ctx *core_ctx = core->core_ctx[ctx->num];
+	struct mfc_enc *enc = NULL;
+
+	if (ctx->type == MFCINST_DECODER) {
+		__mfc_handle_frame(core, ctx, reason, err);
+	} else if (ctx->type == MFCINST_ENCODER) {
+		enc = ctx->enc_priv;
+		if (reason == MFC_REG_R2H_CMD_SLICE_DONE_RET) {
+			core->preempt_core_ctx = ctx->num;
+			enc->buf_full = 0;
+			enc->in_slice = 1;
+		} else if (reason == MFC_REG_R2H_CMD_ENC_BUFFER_FULL_RET) {
+			mfc_err("stream buffer size(%d) isn't enough, (Bitrate: %d)\n",
+				mfc_core_get_enc_strm_size(),
+				MFC_CORE_RAW_READL(MFC_REG_E_RC_BIT_RATE));
+
+			core->preempt_core_ctx = ctx->num;
+			enc->buf_full = 1;
+			enc->in_slice = 0;
+		} else {
+			enc->buf_full = 0;
+			enc->in_slice = 0;
+		}
+		__mfc_handle_stream(core, ctx, reason);
+	}
+
+	return 1;
 }
 
 /* Handle header decoder interrupt */
@@ -1387,13 +1811,82 @@ static int __mfc_handle_seq_dec(struct mfc_core *core, struct mfc_ctx *ctx)
 	return 0;
 }
 
+/* Handle header encoder interrupt */
+static int __mfc_handle_seq_enc(struct mfc_core *core, struct mfc_ctx *ctx)
+{
+	struct mfc_core_ctx *core_ctx = core->core_ctx[ctx->num];
+	struct mfc_enc *enc = ctx->enc_priv;
+	struct mfc_enc_params *p = &enc->params;
+	struct mfc_buf *dst_mb;
+	int ret, index;
+
+	enc->header_size = mfc_core_get_enc_strm_size();
+	mfc_debug(2, "[STREAM] encoded slice type: %d, header size: %d, display order: %d\n",
+		  mfc_core_get_enc_slice_type(), enc->header_size,
+		  mfc_core_get_enc_pic_count());
+
+	/* Initialize select_view */
+	ctx->select_view = MFC_VIEW_ID_MAIN;
+
+	if (!IS_NO_HEADER_GENERATE(ctx, p) &&
+	    !(ctx->stream_op_mode == MFC_OP_TWO_MODE1 && core->id == MFC_CORE_SUB)) {
+		dst_mb = mfc_get_del_buf
+			(ctx, &ctx->dst_buf_queue, MFC_BUF_NO_TOUCH_USED);
+		if (!dst_mb) {
+			mfc_err("no dst buffers\n");
+			return -EAGAIN;
+		}
+
+		vb2_set_plane_payload
+			(&dst_mb->vb.vb2_buf, 0, mfc_core_get_enc_strm_size());
+
+		index = dst_mb->vb.vb2_buf.index;
+		if (call_bop(ctx, core_get_buf_ctrls, core, ctx,
+			     &ctx->dst_ctrls[index]) < 0)
+			mfc_err("failed in core_get_buf_ctrls\n");
+		call_cop(ctx, update_buf_val, ctx, &ctx->dst_ctrls[index],
+			 V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG, HEADER_TAG);
+
+		vb2_buffer_done(&dst_mb->vb.vb2_buf, VB2_BUF_STATE_DONE);
+	}
+
+	ctx->dpb_count = mfc_core_get_enc_dpb_count();
+	ctx->scratch_buf_size = mfc_core_get_enc_scratch_size();
+	ctx->min_dpb_size[0] = mfc_core_get_enc_luma_size();
+	ctx->min_dpb_size[1] = mfc_core_get_enc_chroma_size();
+
+	/* If the ROI is enabled at SEQ_START, clear ROI_ENABLE bit */
+	mfc_core_clear_roi_enable(core);
+
+	if (core_ctx->codec_buffer_allocated) {
+		mfc_debug(2, "[DRC] previous codec buffer is exist\n");
+
+		mfc_release_codec_buffers(core_ctx);
+	}
+
+	ret = mfc_alloc_codec_buffers(core_ctx);
+	if (ret)
+		mfc_err("Failed to allocate encoding buffers\n");
+
+	mfc_change_state(core_ctx, MFCINST_HEAD_PARSED);
+
+	return 0;
+}
+
 static inline void __mfc_handle_nal_abort(struct mfc_core *core,
 					  struct mfc_ctx *ctx,
 					  unsigned int reason)
 {
 	struct mfc_core_ctx *core_ctx = core->core_ctx[ctx->num];
+	struct mfc_enc *enc = ctx->enc_priv;
 
-	mfc_change_state(core_ctx, MFCINST_ABORT);
+	if (ctx->type == MFCINST_ENCODER) {
+		mfc_change_state(core_ctx, MFCINST_RUNNING_BUF_FULL);
+		enc->buf_full = 0;
+		__mfc_handle_stream(core, ctx, reason);
+	} else {
+		mfc_change_state(core_ctx, MFCINST_ABORT);
+	}
 }
 
 irqreturn_t mfc_core_top_half_irq(int irq, void *priv)
@@ -1479,11 +1972,20 @@ static int __mfc_irq_ctx(struct mfc_core *core,
 	case MFC_REG_R2H_CMD_SLICE_DONE_RET:
 	case MFC_REG_R2H_CMD_FIELD_DONE_RET:
 	case MFC_REG_R2H_CMD_FRAME_DONE_RET:
+	case MFC_REG_R2H_CMD_ENC_BUFFER_FULL_RET:
+		return __mfc_handle_done_frame(core, ctx, reason, err);
 	case MFC_REG_R2H_CMD_COMPLETE_SEQ_RET:
-			__mfc_handle_done_frame(core, ctx, reason, err);
+		if (ctx->type == MFCINST_ENCODER) {
+			__mfc_handle_stream(core, ctx, reason);
+			mfc_change_state(core_ctx, MFCINST_FINISHED);
+		} else if (ctx->type == MFCINST_DECODER) {
+			return __mfc_handle_done_frame(core, ctx, reason, err);
+		}
 		break;
 	case MFC_REG_R2H_CMD_SEQ_DONE_RET:
-		if (ctx->type == MFCINST_DECODER)
+		if (ctx->type == MFCINST_ENCODER)
+			__mfc_handle_seq_enc(core, ctx);
+		else if (ctx->type == MFCINST_DECODER)
 			__mfc_handle_seq_dec(core, ctx);
 		break;
 	case MFC_REG_R2H_CMD_OPEN_INSTANCE_RET:
diff --git a/drivers/media/platform/samsung/exynos-mfc/mfc_core_sync.c b/drivers/media/platform/samsung/exynos-mfc/mfc_core_sync.c
index e4b839eda2da..aedb3f56035e 100644
--- a/drivers/media/platform/samsung/exynos-mfc/mfc_core_sync.c
+++ b/drivers/media/platform/samsung/exynos-mfc/mfc_core_sync.c
@@ -30,7 +30,8 @@ static inline unsigned int __mfc_r2h_bit_mask(int cmd)
 			 R2H_BIT(MFC_REG_R2H_CMD_COMPLETE_SEQ_RET) |
 			 R2H_BIT(MFC_REG_R2H_CMD_SLICE_DONE_RET) |
 			 R2H_BIT(MFC_REG_R2H_CMD_INIT_BUFFERS_RET) |
-			 R2H_BIT(MFC_REG_R2H_CMD_NAL_ABORT_RET));
+			 R2H_BIT(MFC_REG_R2H_CMD_NAL_ABORT_RET) |
+			 R2H_BIT(MFC_REG_R2H_CMD_ENC_BUFFER_FULL_RET));
 	/* FIXME: Temporal mask for S3D SEI processing */
 	else if (cmd == MFC_REG_R2H_CMD_INIT_BUFFERS_RET)
 		mask |= (R2H_BIT(MFC_REG_R2H_CMD_FIELD_DONE_RET) |
@@ -311,6 +312,56 @@ static int __mfc_dec_ctx_ready_set_bit(struct mfc_core_ctx *core_ctx)
 	return is_ready;
 }
 
+static int __mfc_enc_ctx_ready_set_bit(struct mfc_core_ctx *core_ctx)
+{
+	struct mfc_ctx *ctx = core_ctx->ctx;
+	struct mfc_enc *enc = ctx->enc_priv;
+	struct mfc_enc_params *p = &enc->params;
+	int is_ready = 0;
+	int src_buf_cnt, dst_buf_cnt;
+
+	src_buf_cnt = mfc_get_queue_count(&ctx->buf_queue_lock, &core_ctx->src_buf_queue);
+	dst_buf_cnt = mfc_get_queue_count(&ctx->buf_queue_lock, &ctx->dst_buf_queue);
+
+	/* context is ready to make header */
+	if (core_ctx->state == MFCINST_GOT_INST && dst_buf_cnt) {
+		if (p->seq_hdr_mode == V4L2_MPEG_VIDEO_HEADER_MODE_AT_THE_READY) {
+			if (src_buf_cnt)
+				is_ready = 1;
+		} else {
+			is_ready = 1;
+		}
+	}
+
+	/* In mode1 encoding, MFC1 will run seq_start of dummy. */
+	if (core_ctx->state == MFCINST_GOT_INST &&
+	    (ctx->stream_op_mode == MFC_OP_TWO_MODE1 &&
+	    core_ctx->core->id == MFC_CORE_SUB))
+		is_ready = 1;
+
+	/* context is ready to allocate DPB */
+	else if (core_ctx->state == MFCINST_HEAD_PARSED && dst_buf_cnt &&
+		 !(ctx->stream_op_mode == MFC_OP_TWO_MODE1 &&
+		 core_ctx->core->id == MFC_CORE_SUB))
+		is_ready = 1;
+
+	/* context is ready to encode a frame */
+	else if (core_ctx->state == MFCINST_RUNNING &&
+		 src_buf_cnt && dst_buf_cnt)
+		is_ready = 1;
+
+	/* context is ready to encode a frame for NAL_ABORT command */
+	else if (core_ctx->state == MFCINST_ABORT_INST &&
+		 src_buf_cnt && dst_buf_cnt)
+		is_ready = 1;
+
+	/* context is ready to encode remain frames */
+	else if (core_ctx->state == MFCINST_FINISHING && dst_buf_cnt)
+		is_ready = 1;
+
+	return is_ready;
+}
+
 int mfc_ctx_ready_set_bit_raw(struct mfc_core_ctx *core_ctx, unsigned long *bits, bool set)
 {
 	struct mfc_core *core = core_ctx->core;
@@ -331,7 +382,10 @@ int mfc_ctx_ready_set_bit_raw(struct mfc_core_ctx *core_ctx, unsigned long *bits
 				      &ctx->dst_buf_queue),
 		  core_ctx->state, ctx->capture_state, ctx->wait_state);
 
-	is_ready = __mfc_dec_ctx_ready_set_bit(core_ctx);
+	if (ctx->type == MFCINST_DECODER)
+		is_ready = __mfc_dec_ctx_ready_set_bit(core_ctx);
+	else if (ctx->type == MFCINST_ENCODER)
+		is_ready = __mfc_enc_ctx_ready_set_bit(core_ctx);
 
 	if (is_ready && set) {
 		/* if the ctx is ready and request set_bit, set the work_bit */
diff --git a/drivers/media/platform/samsung/exynos-mfc/mfc_debugfs.c b/drivers/media/platform/samsung/exynos-mfc/mfc_debugfs.c
index 59cd6f3945ff..8967744b986b 100644
--- a/drivers/media/platform/samsung/exynos-mfc/mfc_debugfs.c
+++ b/drivers/media/platform/samsung/exynos-mfc/mfc_debugfs.c
@@ -33,15 +33,20 @@ static int __mfc_info_show(struct seq_file *s, void *unused)
 		   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)\n",
+	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);
-	seq_printf(s, "           static_info_dec: %d(0x%x)\n",
+		   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);
-	seq_printf(s, " [FORMATS] 10bit: %s, 422: %s\n",
+		   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_422 ? "supported" : "not supported",
+		   dev->pdata->support_rgb ? "supported" : "not supported");
 	seq_printf(s, " [LOWMEM] is_low_mem: %d\n", IS_LOW_MEM);
 
 	for (j = 0; j < dev->num_core; j++) {
-- 
2.34.1


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ