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-23-h.dewangan@samsung.com>
Date: Tue, 30 Sep 2025 09:33:41 +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 22/29] media: mfc: Add H.264 encoder support with buffer and
 QoS improvements

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

- Integrat H.264 encoding.
- Allocate encoder‑specific context buffers and ROI memory.
- Add detection macro and broadened codec‑type validation for
  QoS utilities.
- Introduce encoder‑aware QoS tables and refined weight calculations
  (B‑frames, reference count).
- Update source‑queue cleanup, framerate fallback, and
  timestamp‑delta handling.
- Make stride and source‑size helpers encoder‑aware; exposed B‑frame
  detection utility.
- Expand context structures with encoder buffers, private fields,
  ROI, and parameters.
- Add platform flags for encoder‑specific QoS steps and feature
  support (e.g., RGB).

Signed-off-by: Nagaraju Siddineni <nagaraju.s@...sung.com>
Signed-off-by: Himanshu Dewangan <h.dewangan@...sung.com>
---
 .../samsung/exynos-mfc/base/mfc_buf.c         | 132 ++++++++++
 .../samsung/exynos-mfc/base/mfc_buf.h         |   3 +
 .../samsung/exynos-mfc/base/mfc_common.h      |  24 +-
 .../samsung/exynos-mfc/base/mfc_data_struct.h | 231 ++++++++++++++++++
 .../samsung/exynos-mfc/base/mfc_qos.c         |  34 ++-
 .../samsung/exynos-mfc/base/mfc_queue.c       |  31 +++
 .../samsung/exynos-mfc/base/mfc_queue.h       |   2 +
 .../exynos-mfc/base/mfc_rate_calculate.c      |  30 ++-
 .../exynos-mfc/base/mfc_rate_calculate.h      |   8 +-
 .../samsung/exynos-mfc/base/mfc_utils.c       | 111 +++++++++
 .../samsung/exynos-mfc/base/mfc_utils.h       |  52 ++++
 .../media/platform/samsung/exynos-mfc/mfc.c   |   3 +
 12 files changed, 654 insertions(+), 7 deletions(-)

diff --git a/drivers/media/platform/samsung/exynos-mfc/base/mfc_buf.c b/drivers/media/platform/samsung/exynos-mfc/base/mfc_buf.c
index 84f97ca230bb..0186fe3327f1 100644
--- a/drivers/media/platform/samsung/exynos-mfc/base/mfc_buf.c
+++ b/drivers/media/platform/samsung/exynos-mfc/base/mfc_buf.c
@@ -132,6 +132,9 @@ int mfc_alloc_instance_context(struct mfc_core_ctx *core_ctx)
 	case MFC_REG_CODEC_FIMV4_DEC:
 		core_ctx->instance_ctx_buf.size = buf_size->other_dec_ctx;
 		break;
+	case MFC_REG_CODEC_H264_ENC:
+		core_ctx->instance_ctx_buf.size = buf_size->h264_enc_ctx;
+		break;
 	case MFC_REG_CODEC_AV1_DEC:
 		core_ctx->instance_ctx_buf.size = buf_size->av1_dec_ctx;
 		break;
@@ -248,6 +251,64 @@ static void __mfc_dec_calc_codec_buffer_size(struct mfc_core_ctx *core_ctx)
 			  NUM_MPEG4_LF_BUF);
 }
 
+static void __mfc_enc_calc_codec_buffer_size(struct mfc_core_ctx *core_ctx)
+{
+	struct mfc_ctx *ctx = core_ctx->ctx;
+	struct mfc_enc *enc;
+	unsigned int mb_width, mb_height;
+
+	enc = ctx->enc_priv;
+	enc->tmv_buffer_size = 0;
+
+	mb_width = WIDTH_MB(ctx->crop_width);
+	mb_height = HEIGHT_MB(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), SZ_64);
+	enc->chroma_dpb_size =
+		ALIGN(ENC_CHROMA_DPB_SIZE(ctx->crop_width, ctx->crop_height), SZ_64);
+
+	if (ctx->min_dpb_size[0] > enc->luma_dpb_size ||
+	    ctx->min_dpb_size[1] > enc->chroma_dpb_size) {
+		mfc_debug(2,
+			  "[MEMINFO] recon DPB size changed (Luma: %zu -> %d, Chroma %zu -> %d)\n",
+			  enc->luma_dpb_size,
+			  ctx->min_dpb_size[0],
+			  enc->chroma_dpb_size,
+			  ctx->min_dpb_size[1]);
+		enc->luma_dpb_size = ctx->min_dpb_size[0];
+		enc->chroma_dpb_size = ctx->min_dpb_size[1];
+	}
+
+	/* Codecs have different memory requirements */
+	switch (ctx->codec_mode) {
+	case MFC_REG_CODEC_H264_ENC:
+		enc->me_buffer_size =
+			ALIGN(ENC_V100_H264_ME_SIZE(mb_width, mb_height), SZ_256);
+
+		ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, SZ_256);
+		core_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:
+		core_ctx->codec_buf.size = 0;
+		mfc_err("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 mfc_alloc_codec_buffers(struct mfc_core_ctx *core_ctx)
 {
@@ -259,6 +320,8 @@ int mfc_alloc_codec_buffers(struct mfc_core_ctx *core_ctx)
 
 	if (ctx->type == MFCINST_DECODER) {
 		__mfc_dec_calc_codec_buffer_size(core_ctx);
+	} else if (ctx->type == MFCINST_ENCODER) {
+		__mfc_enc_calc_codec_buffer_size(core_ctx);
 	} else {
 		mfc_err("invalid type: %d\n", ctx->type);
 		return -EINVAL;
@@ -401,6 +464,75 @@ void mfc_release_dbg_info_buffer(struct mfc_core *core)
 	mfc_mem_special_buf_free(core->dev, &core->dbg_info_buf);
 }
 
+/* Allocation buffer of ROI macroblock information */
+static int __mfc_alloc_enc_roi_buffer(struct mfc_core_ctx *core_ctx,
+				      size_t size,
+				      struct mfc_special_buf *roi_buf)
+{
+	struct mfc_core *core = core_ctx->core;
+	struct mfc_dev *dev = core->dev;
+
+	roi_buf->size = size;
+	roi_buf->buftype = MFCBUF_NORMAL;
+
+	if (!roi_buf->dma_buf) {
+		snprintf(roi_buf->name, MFC_NUM_SPECIAL_BUF_NAME, "ctx%d ROI", core_ctx->num);
+		if (mfc_mem_special_buf_alloc(dev, roi_buf)) {
+			mfc_err("[ROI] Allocating ROI buffer failed\n");
+			return -ENOMEM;
+		}
+	}
+	memset(roi_buf->vaddr, 0, roi_buf->size);
+
+	return 0;
+}
+
+/* Wrapper : allocation ROI buffers */
+int mfc_alloc_enc_roi_buffer(struct mfc_core_ctx *core_ctx)
+{
+	struct mfc_ctx *ctx = core_ctx->ctx;
+	struct mfc_enc *enc = ctx->enc_priv;
+	unsigned int mb_width, mb_height;
+	size_t size;
+	int i;
+
+	mb_width = WIDTH_MB(ctx->crop_width);
+	mb_height = HEIGHT_MB(ctx->crop_height);
+
+	switch (ctx->codec_mode) {
+	case MFC_REG_CODEC_H264_ENC:
+		size = ((((mb_width * (mb_height + 1) / 2) + 15) / 16) * 16) * 2;
+		break;
+	default:
+		mfc_debug(2,
+			  "ROI not supported codec type(%d). Allocate with default size\n",
+			  ctx->codec_mode);
+		size = mb_width * mb_height;
+		break;
+	}
+
+	for (i = 0; i < MFC_MAX_EXTRA_BUF; i++) {
+		if (__mfc_alloc_enc_roi_buffer(core_ctx, size, &enc->roi_buf[i]) < 0) {
+			mfc_err("[ROI] Allocating remapping buffer[%d] failed\n", i);
+			return -ENOMEM;
+		}
+	}
+
+	return 0;
+}
+
+/* Release buffer of ROI macroblock information */
+void mfc_release_enc_roi_buffer(struct mfc_core_ctx *core_ctx)
+{
+	struct mfc_ctx *ctx = core_ctx->ctx;
+	struct mfc_enc *enc = ctx->enc_priv;
+	int i;
+
+	for (i = 0; i < MFC_MAX_EXTRA_BUF; i++)
+		if (enc->roi_buf[i].dma_buf)
+			mfc_mem_special_buf_free(ctx->dev, &enc->roi_buf[i]);
+}
+
 /* Allocate firmware */
 int mfc_alloc_firmware(struct mfc_core *core)
 {
diff --git a/drivers/media/platform/samsung/exynos-mfc/base/mfc_buf.h b/drivers/media/platform/samsung/exynos-mfc/base/mfc_buf.h
index 6907cf6ac775..67bdfaed5dd6 100644
--- a/drivers/media/platform/samsung/exynos-mfc/base/mfc_buf.h
+++ b/drivers/media/platform/samsung/exynos-mfc/base/mfc_buf.h
@@ -26,6 +26,9 @@ void mfc_release_codec_buffers(struct mfc_core_ctx *core_ctx);
 int mfc_alloc_scratch_buffer(struct mfc_core_ctx *core_ctx);
 void mfc_release_scratch_buffer(struct mfc_core_ctx *core_ctx);
 
+int mfc_alloc_enc_roi_buffer(struct mfc_core_ctx *core_ctx);
+void mfc_release_enc_roi_buffer(struct mfc_core_ctx *core_ctx);
+
 int mfc_alloc_firmware(struct mfc_core *core);
 int mfc_load_firmware(struct mfc_core *core,
 		      struct mfc_special_buf *fw_buf,
diff --git a/drivers/media/platform/samsung/exynos-mfc/base/mfc_common.h b/drivers/media/platform/samsung/exynos-mfc/base/mfc_common.h
index 5392c8566e42..bec6f88d5e44 100644
--- a/drivers/media/platform/samsung/exynos-mfc/base/mfc_common.h
+++ b/drivers/media/platform/samsung/exynos-mfc/base/mfc_common.h
@@ -170,6 +170,9 @@
 	((ctx)->codec_mode == MFC_REG_CODEC_HEVC_DEC &&					\
 	 (profile) == MFC_REG_D_PROFILE_MULTIVIEW_HEVC_MAIN)
 
+/* Encoder codec mode check */
+#define IS_H264_ENC(ctx)	((ctx)->codec_mode == MFC_REG_CODEC_H264_ENC)
+
 #define CODEC_NOT_CODED(ctx)	({							\
 	typeof(ctx) _ctx = (ctx);							\
 	(IS_MPEG4_DEC(_ctx) || IS_VC1_DEC(_ctx) || IS_VC1_RCV_DEC(_ctx) ||		\
@@ -217,7 +220,16 @@
 })
 #define CODEC_HAS_IDR(ctx)	({							\
 	typeof(ctx) _ctx = (ctx);							\
-	(IS_H264_DEC(_ctx) || IS_H264_MVC_DEC(_ctx) || IS_HEVC_DEC(_ctx));		\
+	(IS_H264_DEC(_ctx) || IS_H264_MVC_DEC(_ctx) || IS_HEVC_DEC(_ctx) ||		\
+	 IS_H264_ENC(_ctx));					\
+})
+
+// Buffer container
+#define IS_BUFFER_BATCH_MODE(ctx)	((ctx)->batch_mode == 1)
+#define IS_NO_HEADER_GENERATE(ctx, p)	({						\
+	typeof(ctx) _ctx = (ctx);							\
+	typeof(p) _p = (p);								\
+	(_p->seq_hdr_mode == V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME);	\
 })
 
 /*
@@ -313,6 +325,13 @@
 	 (_fps >= 240));							\
 })
 
+#define IS_MULTI_MODE_ENC_RES(ctx)	({					\
+	typeof(ctx) _ctx = (ctx);						\
+	(IS_MULTI_MODE_RES(_ctx) ||						\
+	 (OVER_UHD_RES(_ctx) && _ctx->operating_framerate >= 60000)	||	\
+	 (OVER_UHD_RES(_ctx) && mfc_is_enc_bframe(_ctx)));			\
+})
+
 #define IS_BLACKBAR_OFF(ctx)	((ctx)->crop_height > 2160)
 
 #define IS_SINGLE_FD(ctx, fmt)	((!(ctx)->rgb_bpp) && ((fmt)->mem_planes == 1))
@@ -404,6 +423,9 @@ static inline int mfc_core_get_pwr_ref_cnt(struct mfc_core *core)
 
 static inline int mfc_core_get_clk_ref_cnt(struct mfc_core *core)
 {
+	if (core->dev->pdata->support_hwacg == MFC_HWACG_HWFW_CTRL)
+		return 1;
+
 	return atomic_read(&core->clk_ref);
 }
 
diff --git a/drivers/media/platform/samsung/exynos-mfc/base/mfc_data_struct.h b/drivers/media/platform/samsung/exynos-mfc/base/mfc_data_struct.h
index 6b93fe3ab138..6d34905a1cba 100644
--- a/drivers/media/platform/samsung/exynos-mfc/base/mfc_data_struct.h
+++ b/drivers/media/platform/samsung/exynos-mfc/base/mfc_data_struct.h
@@ -505,6 +505,9 @@ struct mfc_ctx_buf_size {
 	size_t h264_dec_ctx;
 	size_t av1_dec_ctx;
 	size_t other_dec_ctx;
+	size_t h264_enc_ctx;
+	size_t hevc_enc_ctx;
+	size_t other_enc_ctx;
 	size_t dbg_info_buf;
 };
 
@@ -711,6 +714,13 @@ struct mfc_bw_data {
 };
 
 struct mfc_bw_info {
+	struct mfc_bw_data bw_enc_h264;
+	struct mfc_bw_data bw_enc_hevc;
+	struct mfc_bw_data bw_enc_hevc_10bit;
+	struct mfc_bw_data bw_enc_vp8;
+	struct mfc_bw_data bw_enc_vp9;
+	struct mfc_bw_data bw_enc_vp9_10bit;
+	struct mfc_bw_data bw_enc_mpeg4;
 	struct mfc_bw_data bw_dec_h264;
 	struct mfc_bw_data bw_dec_hevc;
 	struct mfc_bw_data bw_dec_hevc_10bit;
@@ -734,6 +744,7 @@ struct mfc_qos {
 	unsigned int freq_mif;
 	unsigned int mo_value;
 	unsigned int mo_10bit_value;
+	unsigned int mo_uhd_enc60_value;
 	unsigned int time_fw;
 	unsigned int bts_scen_idx;
 	const char *name;
@@ -792,6 +803,7 @@ struct mfc_platdata {
 	/* Formats */
 	unsigned int support_10bit;
 	unsigned int support_422;
+	unsigned int support_rgb;
 	/* Resolution */
 	unsigned int support_check_res;
 
@@ -807,11 +819,26 @@ struct mfc_platdata {
 	struct mfc_feature black_bar;
 	struct mfc_feature color_aspect_dec;
 	struct mfc_feature static_info_dec;
+	struct mfc_feature color_aspect_enc;
+	struct mfc_feature static_info_enc;
 	struct mfc_feature vp9_stride_align;
 	struct mfc_feature mem_clear;
 	struct mfc_feature wait_fw_status;
+	struct mfc_feature average_qp;
+	struct mfc_feature mv_search_mode;
+	struct mfc_feature enc_idr_flag;
+	struct mfc_feature min_quality_mode;
+	struct mfc_feature enc_capability;
+	struct mfc_feature enc_ts_delta;
+	struct mfc_feature wfd_rc_mode;
+	struct mfc_feature max_i_frame_size;
 	struct mfc_feature hevc_pic_output_flag;
 
+	/* 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];
+
 	struct mfc_bw_info mfc_bw_info;
 	unsigned int dynamic_weight;
 	struct mfc_qos_weight qos_weight;
@@ -835,7 +862,14 @@ struct mfc_platdata {
 
 	unsigned int scheduler;
 	unsigned int pbs_num_prio;
+
+	unsigned int enc_rgb_csc_by_fw;
+	/* HWAPG */
+	unsigned int support_hwapg;
+	/* HWACG */
 	enum mfc_hwacg_type support_hwacg;
+
+	unsigned int support_enc_mode1;
 	unsigned int support_mv_hevc;
 };
 
@@ -858,6 +892,7 @@ struct mfc_core_platdata {
 	unsigned int tsmux_masterid;
 	/* QoS */
 	unsigned int num_default_qos_steps;
+	unsigned int num_encoder_qos_steps;
 	unsigned int max_mb;
 	unsigned int max_hw_mb;
 	unsigned int mfc_freq_control;
@@ -994,6 +1029,9 @@ struct mfc_core_ops {
 	/* for DEC */
 	void (*instance_dpb_flush)(struct mfc_core *core, struct mfc_ctx *ctx);
 	int (*instance_init_buf)(struct mfc_core *core, struct mfc_ctx *ctx);
+	/* for ENC */
+	void (*instance_q_flush)(struct mfc_core *core, struct mfc_ctx *ctx);
+	void (*instance_finishing)(struct mfc_core *core, struct mfc_ctx *ctx);
 };
 
 struct dump_info {
@@ -1148,6 +1186,150 @@ struct mfc_core {
 	struct mfc_core_memlog memlog;
 };
 
+/**
+ *
+ */
+struct mfc_h264_enc_params {
+	enum v4l2_mpeg_video_h264_profile profile;
+	u8 level;
+	u8 interlace;
+	u16 open_gop_size;
+	u8 open_gop;
+	u8 _8x8_transform;
+	s8 loop_filter_alpha;
+	s8 loop_filter_beta;
+	enum v4l2_mpeg_video_h264_loop_filter_mode loop_filter_mode;
+	enum v4l2_mpeg_video_h264_entropy_mode entropy_mode;
+	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;
+	u8 sei_gen_enable;
+	u8 sei_fp_curr_frame_0;
+
+	enum v4l2_mpeg_video_h264_vui_sar_idc ar_vui_idc;
+	u16 ext_sar_width;
+	u16 ext_sar_height;
+
+	enum v4l2_mpeg_video_h264_hierarchical_coding_type hier_qp_type;
+	u32 hier_bit_layer[7];
+	u8 hier_qp_layer[7];
+	u8 hier_qp_enable;
+	u8 num_hier_layer;
+	u8 hier_ref_type;
+	u8 enable_ltr;
+	u8 num_of_ltr;
+	u32 set_priority;
+	u32 base_priority;
+
+	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;
+	u32 vui_enable;
+};
+
+/**
+ *
+ */
+struct mfc_enc_params {
+	enum v4l2_mpeg_video_multi_slice_mode slice_mode;
+	u32 slice_mb;
+	u32 slice_bit;
+	u32 slice_mb_row;
+
+	u32 gop_ctrl;
+	u32 gop_size;
+	u32 intra_refresh_mb;
+	u32 i_frm_ctrl_mode;
+	u32 i_frm_ctrl;
+
+	u8 pad;
+	u8 pad_luma;
+	u8 pad_cb;
+	u8 pad_cr;
+
+	u8 rc_mb;		/* H.264: MFCv5, MPEG4/H.263: MFCv6 */
+	u8 rc_pvc;
+	u8 rc_frame;
+	u8 drop_control;
+	u32 rc_bitrate;
+	u32 rc_framerate;
+	u16 rc_reaction_coeff;
+	u16 rc_frame_delta;	/* MFC6.1 Only */
+	u32 rc_framerate_res;
+	u32 max_i_frame_size;	/* when RC_MODE is 5(CBR_I_LIMIT_WFD = CBR_BS) */
+
+	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 */
+	enum v4l2_mpeg_video_header_mode seq_hdr_mode;
+	enum v4l2_mpeg_mfc51_video_frame_skip_mode frame_skip_mode;
+	u16 vbv_buf_size;
+	u8 num_hier_max_layer;
+	u8 hier_bitrate_ctrl;
+	u8 weighted_enable;
+	u8 roi_enable;
+	u8 ivf_header_disable;	/* VP8, VP9 */
+	u8 fixed_target_bit;
+	u8 min_quality_mode;	/* H.264, HEVC when RC_MODE is 2(VBR) */
+	u8 wp_two_pass_enable;
+	u8 adaptive_gop_enable;
+
+	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;
+	u32 chroma_qp_offset_cb; /* H.264, HEVC */
+	u32 chroma_qp_offset_cr; /* H.264, HEVC */
+
+	u32 mv_search_mode;
+	u32 mv_hor_pos_l0;
+	u32 mv_hor_pos_l1;
+	u32 mv_ver_pos_l0;
+	u32 mv_ver_pos_l1;
+	u32 mv_hor_range;
+	u32 mv_ver_range;
+
+	u8 timing_info_enable; /* H.264, HEVC */
+
+	union {
+		struct mfc_h264_enc_params h264;
+	} codec;
+};
+
 struct mfc_ctx_ctrl_val {
 	int has_new;
 	int val;
@@ -1234,6 +1416,14 @@ struct temporal_layer_info {
 	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;
@@ -1379,6 +1569,43 @@ struct mfc_dec {
 	unsigned char frame_cnt;
 };
 
+struct mfc_enc {
+	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;
+
+	unsigned int idr_flag;
+
+	size_t luma_dpb_size;
+	size_t chroma_dpb_size;
+	size_t me_buffer_size;
+	size_t tmv_buffer_size;
+
+	unsigned int slice_mode;
+	unsigned int slice_size_mb;
+	unsigned int slice_size_bits;
+	unsigned int in_slice;
+	unsigned int buf_full;
+
+	int config_qp;
+
+	struct mfc_fmt *uncomp_fmt;
+
+	int fake_src;
+	int empty_data;
+
+	int roi_index;
+	struct mfc_special_buf roi_buf[MFC_MAX_EXTRA_BUF];
+	struct mfc_enc_roi_info roi_info[MFC_MAX_EXTRA_BUF];
+
+	struct mfc_enc_params params;
+
+	struct mfc_user_shared_handle sh_handle_svc;
+	struct mfc_user_shared_handle sh_handle_roi;
+};
+
 struct mfc_resolution {
 	int width;
 	int height;
@@ -1414,6 +1641,7 @@ struct mfc_multi_view_buf_info {
 struct mfc_ctx {
 	struct mfc_dev *dev;
 	struct mfc_dec *dec_priv;
+	struct mfc_enc *enc_priv;
 
 	int num;
 	int prio;
@@ -1542,6 +1770,9 @@ struct mfc_ctx {
 	dma_addr_t last_src_addr;
 	dma_addr_t last_dst_addr[MFC_MAX_PLANES];
 
+	/* buffer container */
+	int batch_mode;
+
 	bool mem_type_10bit;
 
 	unsigned long gdc_ready_buf_ino;
diff --git a/drivers/media/platform/samsung/exynos-mfc/base/mfc_qos.c b/drivers/media/platform/samsung/exynos-mfc/base/mfc_qos.c
index 9922c2396b94..40541e2d626f 100644
--- a/drivers/media/platform/samsung/exynos-mfc/base/mfc_qos.c
+++ b/drivers/media/platform/samsung/exynos-mfc/base/mfc_qos.c
@@ -20,17 +20,25 @@
 
 static inline int __mfc_core_get_qos_steps(struct mfc_core *core, int table_type)
 {
-	return core->core_pdata->num_default_qos_steps;
+	if (table_type == MFC_QOS_TABLE_TYPE_ENCODER)
+		return core->core_pdata->num_encoder_qos_steps;
+	else
+		return core->core_pdata->num_default_qos_steps;
 }
 
 static inline struct mfc_qos *__mfc_core_get_qos_table(struct mfc_core *core, int table_type)
 {
-	return core->core_pdata->default_qos_table;
+	if (table_type == MFC_QOS_TABLE_TYPE_ENCODER)
+		return core->core_pdata->encoder_qos_table;
+	else
+		return core->core_pdata->default_qos_table;
 }
 
 static inline unsigned long __mfc_qos_add_weight(struct mfc_ctx *ctx, unsigned long mb)
 {
+	struct mfc_enc *enc = ctx->enc_priv;
 	struct mfc_dec *dec = ctx->dec_priv;
+	struct mfc_enc_params *p;
 	struct mfc_qos_weight *qos_weight = &ctx->dev->pdata->qos_weight;
 	u32 num_planes = ctx->dst_fmt->num_planes;
 	int weight = 1000;
@@ -39,6 +47,8 @@ static inline unsigned long __mfc_qos_add_weight(struct mfc_ctx *ctx, unsigned l
 	switch (ctx->codec_mode) {
 	case MFC_REG_CODEC_H264_DEC:
 	case MFC_REG_CODEC_H264_MVC_DEC:
+	case MFC_REG_CODEC_H264_ENC:
+	case MFC_REG_CODEC_H264_MVC_ENC:
 		weight = (weight * 100) / qos_weight->weight_h264_hevc;
 		mfc_ctx_debug(3, "[QoS] h264, hevc codec, weight: %d\n", weight / 10);
 		if (num_planes == 3) {
@@ -107,6 +117,16 @@ static inline unsigned long __mfc_qos_add_weight(struct mfc_ctx *ctx, unsigned l
 		mfc_ctx_err("[QoS] wrong codec_mode (%d), no weight\n", ctx->codec_mode);
 	}
 
+	if (enc) {
+		p = &enc->params;
+		if (mfc_is_enc_bframe(ctx)) {
+			weight = (weight * 100) / qos_weight->weight_bframe;
+			mfc_ctx_debug(3, "[QoS] B frame encoding, weight: %d\n", weight / 10);
+		} else if (IS_H264_ENC(ctx) && (p->num_refs_for_p >= 2)) {
+			weight = (weight * 100) / qos_weight->weight_num_of_ref;
+			mfc_ctx_debug(3, "[QoS] num of ref >= 2, weight: %d\n", weight / 10);
+		}
+	}
 	if (dec) {
 		if (dec->num_of_tile_over_4) {
 			weight = (weight * 100) / qos_weight->weight_num_of_tile;
@@ -223,7 +243,10 @@ void mfc_qos_get_portion(struct mfc_core *core, struct mfc_ctx *ctx)
 	if (!ctx->mfc_qos_portion)
 		return;
 
-	table_type = MFC_QOS_TABLE_TYPE_DEFAULT;
+	if (ctx->type == MFCINST_ENCODER)
+		table_type = MFC_QOS_TABLE_TYPE_ENCODER;
+	else
+		table_type = MFC_QOS_TABLE_TYPE_DEFAULT;
 
 	num_qos_steps = __mfc_core_get_qos_steps(core, table_type);
 	qos_table = __mfc_core_get_qos_table(core, table_type);
@@ -390,7 +413,8 @@ bool mfc_qos_mb_calculate(struct mfc_core *core, struct mfc_core_ctx *core_ctx,
 
 	if (ctx->type == MFCINST_DECODER)
 		table_type = MFC_QOS_TABLE_TYPE_DEFAULT;
-
+	else
+		table_type = MFC_QOS_TABLE_TYPE_ENCODER;
 	num_qos_steps = __mfc_core_get_qos_steps(core, table_type);
 
 	if (atomic_read(&core->qos_req_cur)) {
@@ -652,6 +676,8 @@ void __mfc_qos_calculate(struct mfc_core *core, struct mfc_ctx *ctx, int delete)
 
 	if (dec_found)
 		table_type = MFC_QOS_TABLE_TYPE_DEFAULT;
+	else
+		table_type = MFC_QOS_TABLE_TYPE_ENCODER;
 
 	num_qos_steps = __mfc_core_get_qos_steps(core, table_type);
 	qos_table = __mfc_core_get_qos_table(core, table_type);
diff --git a/drivers/media/platform/samsung/exynos-mfc/base/mfc_queue.c b/drivers/media/platform/samsung/exynos-mfc/base/mfc_queue.c
index 6dc9bc7a1873..81e649bb4e1e 100644
--- a/drivers/media/platform/samsung/exynos-mfc/base/mfc_queue.c
+++ b/drivers/media/platform/samsung/exynos-mfc/base/mfc_queue.c
@@ -539,6 +539,37 @@ void mfc_cleanup_queue(spinlock_t *plock, struct mfc_buf_queue *queue)
 	spin_unlock_irqrestore(plock, flags);
 }
 
+void mfc_cleanup_enc_src_queue(struct mfc_core_ctx *core_ctx)
+{
+	struct mfc_ctx *ctx = core_ctx->ctx;
+	unsigned long flags;
+	struct mfc_buf *mfc_buf = NULL;
+	struct mfc_buf_queue *queue = &core_ctx->src_buf_queue;
+	int i;
+
+	spin_lock_irqsave(&ctx->buf_queue_lock, flags);
+
+	while (!list_empty(&queue->head)) {
+		mfc_buf = list_entry(queue->head.next, struct mfc_buf, list);
+
+		for (i = 0; i < mfc_buf->vb.vb2_buf.num_planes; i++) {
+			if (IS_BUFFER_BATCH_MODE(ctx))
+				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);
+}
+
 void mfc_print_dpb_queue(struct mfc_core_ctx *core_ctx, struct mfc_dec *dec)
 {
 	struct mfc_ctx *ctx = core_ctx->ctx;
diff --git a/drivers/media/platform/samsung/exynos-mfc/base/mfc_queue.h b/drivers/media/platform/samsung/exynos-mfc/base/mfc_queue.h
index 055e7a23a527..cfe889e0dcc9 100644
--- a/drivers/media/platform/samsung/exynos-mfc/base/mfc_queue.h
+++ b/drivers/media/platform/samsung/exynos-mfc/base/mfc_queue.h
@@ -145,6 +145,8 @@ void mfc_return_buf_to_ready_queue(struct mfc_ctx *ctx,
 
 void mfc_cleanup_queue(spinlock_t *plock, struct mfc_buf_queue *queue);
 
+void mfc_cleanup_enc_src_queue(struct mfc_core_ctx *core_ctx);
+
 void mfc_print_dpb_queue(struct mfc_core_ctx *core_ctx, struct mfc_dec *dec);
 void mfc_print_dpb_queue_with_lock(struct mfc_core_ctx *core_ctx, struct mfc_dec *dec);
 int mfc_get_available_dpb_count(struct mfc_core_ctx *core_ctx);
diff --git a/drivers/media/platform/samsung/exynos-mfc/base/mfc_rate_calculate.c b/drivers/media/platform/samsung/exynos-mfc/base/mfc_rate_calculate.c
index 94a555c900d7..c88101d1d1c1 100644
--- a/drivers/media/platform/samsung/exynos-mfc/base/mfc_rate_calculate.c
+++ b/drivers/media/platform/samsung/exynos-mfc/base/mfc_rate_calculate.c
@@ -293,6 +293,7 @@ static unsigned long __mfc_rate_get_fps_by_timestamp(struct mfc_ctx *ctx,
 						     struct mfc_ts_control *ts,
 						     struct timespec64 *time, int type)
 {
+	struct list_head *head = &ts->ts_list;
 	struct mfc_timestamp *temp_ts;
 	int found;
 	int index = 0;
@@ -304,6 +305,13 @@ static unsigned long __mfc_rate_get_fps_by_timestamp(struct mfc_ctx *ctx,
 	unsigned long flags;
 	u64 current_time;
 
+	if (IS_BUFFER_BATCH_MODE(ctx)) {
+		if (ctx->dev->debugfs.debug_ts == 1)
+			mfc_ctx_info("[BUFCON][TS] Keep framerate if buffer batch mode is used, %ldfps\n",
+				     ctx->framerate);
+		return ctx->framerate;
+	}
+
 	spin_lock_irqsave(&ts->ts_lock, flags);
 	if (list_empty(&ts->ts_list)) {
 		__mfc_rate_add_timestamp(ctx, ts, time, &ts->ts_list);
@@ -362,6 +370,19 @@ static unsigned long __mfc_rate_get_fps_by_timestamp(struct mfc_ctx *ctx,
 		spin_unlock_irqrestore(&ts->ts_lock, flags);
 	}
 
+	/* Calculation the last frame fps for drop control */
+	if (ctx->type == MFCINST_ENCODER) {
+		temp_ts = list_entry(head->prev, struct mfc_timestamp, list);
+		if (temp_ts->interval > USEC_PER_SEC) {
+			if (ts->ts_is_full)
+				mfc_ctx_info("[TS] ts interval(%d) couldn't over 1sec(1fps)\n",
+					     temp_ts->interval);
+			ts->ts_last_interval = 0;
+		} else {
+			ts->ts_last_interval = temp_ts->interval;
+		}
+	}
+
 	if (!ts->ts_is_full) {
 		if (ctx->dev->debugfs.debug_ts == 1)
 			mfc_ctx_info("[TS] ts doesn't full, keep %ld fps\n", ctx->framerate);
@@ -581,7 +602,14 @@ int mfc_rate_check_perf_ctx(struct mfc_ctx *ctx, int max_runtime)
 
 	op_fps = ctx->operating_framerate;
 	if (op_fps == 0) {
-		op_fps = ctx->src_q_framerate;
+		if (ctx->type == MFCINST_ENCODER && ctx->enc_priv->params.rc_framerate)
+			op_fps = ctx->enc_priv->params.rc_framerate;
+		else
+			/*
+			 * In case of non-real-time, check the buffer queueing rate
+			 * because the non-real-time is best effort scenario. (ex. video editing)
+			 */
+			op_fps = ctx->src_q_framerate;
 		mfc_ctx_debug(2, "[PRIO][rt %d] use fps: %d\n", ctx->rt, op_fps);
 	}
 
diff --git a/drivers/media/platform/samsung/exynos-mfc/base/mfc_rate_calculate.h b/drivers/media/platform/samsung/exynos-mfc/base/mfc_rate_calculate.h
index 2452e6ee56dd..530ad6fed489 100644
--- a/drivers/media/platform/samsung/exynos-mfc/base/mfc_rate_calculate.h
+++ b/drivers/media/platform/samsung/exynos-mfc/base/mfc_rate_calculate.h
@@ -45,6 +45,8 @@ static inline void mfc_rate_reset_framerate(struct mfc_ctx *ctx)
 {
 	if (ctx->type == MFCINST_DECODER)
 		ctx->framerate = DEC_DEFAULT_FPS;
+	else if (ctx->type == MFCINST_ENCODER)
+		ctx->framerate = ENC_DEFAULT_FPS;
 
 	mfc_ctx_debug(3, "[QoS] reset ctx->framrate: %lu\n", ctx->framerate);
 }
@@ -80,7 +82,11 @@ static inline unsigned long mfc_rate_get_rt_framerate(struct mfc_ctx *ctx, enum
 
 	framerate = ctx->operating_framerate;
 
-	if (rt == MFC_RT_UNDEFINED || rt == MFC_NON_RT) {
+	if (rt == MFC_RT) {
+		if (framerate == 0 && ctx->type == MFCINST_ENCODER &&
+		    ctx->enc_priv->params.rc_framerate)
+			framerate = ctx->enc_priv->params.rc_framerate;
+	} else if (rt == MFC_RT_UNDEFINED || rt == MFC_NON_RT) {
 		framerate = ctx->framerate;
 	} else {
 		if (ctx->src_ts.ts_is_full)
diff --git a/drivers/media/platform/samsung/exynos-mfc/base/mfc_utils.c b/drivers/media/platform/samsung/exynos-mfc/base/mfc_utils.c
index 83cdae3dee57..6dba87fb951b 100644
--- a/drivers/media/platform/samsung/exynos-mfc/base/mfc_utils.c
+++ b/drivers/media/platform/samsung/exynos-mfc/base/mfc_utils.c
@@ -108,6 +108,59 @@ static void __mfc_set_dec_stride(struct mfc_ctx *ctx,
 	}
 }
 
+static void __mfc_set_enc_stride(struct mfc_ctx *ctx,
+				 struct mfc_raw_info *raw,
+				 struct mfc_fmt *fmt)
+{
+	int i, y_stride, stride_align = 16;
+
+	y_stride = ctx->bytesperline[0];
+	if (!y_stride)
+		y_stride = ALIGN(ctx->img_width, stride_align);
+
+	for (i = 0; i < MFC_MAX_PLANES; i++) {
+		raw->stride[i] = 0;
+		raw->stride_2bits[i] = 0;
+	}
+
+	switch (fmt->fourcc) {
+	case V4L2_PIX_FMT_YUV420M:
+	case V4L2_PIX_FMT_YVU420M:
+	case V4L2_PIX_FMT_NV12MT_16X16:
+	case V4L2_PIX_FMT_NV12MT:
+	case V4L2_PIX_FMT_NV12M:
+	case V4L2_PIX_FMT_NV21M:
+	case V4L2_PIX_FMT_NV16M:
+	case V4L2_PIX_FMT_NV61M:
+		/* use user stride */
+		for (i = 0; i < ctx->src_fmt->num_planes; i++) {
+			raw->stride[i] = ctx->bytesperline[i];
+			if (!raw->stride[i])
+				raw->stride[i] = ALIGN(ctx->img_width, stride_align);
+		}
+		break;
+	case V4L2_PIX_FMT_RGB24:
+	case V4L2_PIX_FMT_RGB565:
+	case V4L2_PIX_FMT_RGB32X:
+	case V4L2_PIX_FMT_BGR32:
+	case V4L2_PIX_FMT_ARGB32:
+	case V4L2_PIX_FMT_RGB32:
+		raw->stride[0] = y_stride * (ctx->rgb_bpp / 8);
+		break;
+	default:
+		mfc_ctx_err("Invalid pixelformat : %s\n", fmt->name);
+		break;
+	}
+
+	for (i = 0; i < ctx->src_fmt->num_planes; i++) {
+		if ((raw->stride[i] % stride_align) != 0) {
+			mfc_ctx_err("[FRAME] Forced to change stride[%d] %d for %dbyte alignment\n",
+				    i, raw->stride[i], stride_align);
+			raw->stride[i] = ALIGN(raw->stride[i], stride_align);
+		}
+	}
+}
+
 void mfc_set_linear_stride_size(struct mfc_ctx *ctx, struct mfc_raw_info *raw, struct mfc_fmt *fmt)
 {
 	/*
@@ -117,6 +170,8 @@ void mfc_set_linear_stride_size(struct mfc_ctx *ctx, struct mfc_raw_info *raw, s
 	 */
 	if (ctx->type == MFCINST_DECODER)
 		__mfc_set_dec_stride(ctx, raw, fmt);
+	else
+		__mfc_set_enc_stride(ctx, raw, fmt);
 }
 
 void mfc_dec_calc_dpb_size(struct mfc_ctx *ctx, struct mfc_raw_info *raw, struct mfc_fmt *fmt)
@@ -201,6 +256,62 @@ void mfc_dec_calc_dpb_size(struct mfc_ctx *ctx, struct mfc_raw_info *raw, struct
 	}
 }
 
+void mfc_enc_calc_src_size(struct mfc_ctx *ctx)
+{
+	struct mfc_raw_info *raw;
+	int i, extra;
+
+	raw = &ctx->raw_buf;
+	raw->total_plane_size = 0;
+	extra = MFC_LINEAR_BUF_SIZE;
+
+	mfc_set_linear_stride_size(ctx, raw, ctx->src_fmt);
+
+	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_YVU420M:
+		raw->plane_size[0] = raw->stride[0] * ALIGN(ctx->img_height, 16) + extra;
+		raw->plane_size[1] = raw->stride[1] * ALIGN(ctx->img_height, 16) / 2 + extra;
+		raw->plane_size[2] = raw->stride[2] * ALIGN(ctx->img_height, 16) / 2 + extra;
+		break;
+	case V4L2_PIX_FMT_NV12MT_16X16:
+	case V4L2_PIX_FMT_NV12M:
+	case V4L2_PIX_FMT_NV21M:
+		raw->plane_size[0] = raw->stride[0] * ALIGN(ctx->img_height, 16) + extra;
+		raw->plane_size[1] = raw->stride[1] * ALIGN(ctx->img_height, 16) / 2 + extra;
+		break;
+	case V4L2_PIX_FMT_NV16M:
+	case V4L2_PIX_FMT_NV61M:
+		raw->plane_size[0] = raw->stride[0] * ALIGN(ctx->img_height, 16) + extra;
+		raw->plane_size[1] = raw->stride[1] * ALIGN(ctx->img_height, 16) + extra;
+		break;
+	case V4L2_PIX_FMT_RGB24:
+	case V4L2_PIX_FMT_RGB565:
+	case V4L2_PIX_FMT_RGB32X:
+	case V4L2_PIX_FMT_BGR32:
+	case V4L2_PIX_FMT_ARGB32:
+	case V4L2_PIX_FMT_RGB32:
+		raw->plane_size[0] = raw->stride[0] * ctx->img_height;
+		break;
+	default:
+		mfc_ctx_err("Invalid pixel format(%d)\n", ctx->src_fmt->fourcc);
+		break;
+	}
+
+	for (i = 0; i < raw->num_planes; i++) {
+		raw->total_plane_size += raw->plane_size[i];
+		mfc_ctx_debug(2, "[FRAME] Plane[%d] size = %d, stride = %d\n",
+			      i, raw->plane_size[i], raw->stride[i]);
+	}
+
+	mfc_ctx_debug(2, "[FRAME] total plane size: %d\n", raw->total_plane_size);
+}
+
 void mfc_calc_base_addr(struct mfc_ctx *ctx, struct vb2_buffer *vb,
 			struct mfc_fmt *fmt)
 {
diff --git a/drivers/media/platform/samsung/exynos-mfc/base/mfc_utils.h b/drivers/media/platform/samsung/exynos-mfc/base/mfc_utils.h
index dedfb049e6fc..a127f330fe16 100644
--- a/drivers/media/platform/samsung/exynos-mfc/base/mfc_utils.h
+++ b/drivers/media/platform/samsung/exynos-mfc/base/mfc_utils.h
@@ -212,10 +212,37 @@ static inline int mfc_check_mb_flag(struct mfc_buf *mfc_buf, enum mfc_mb_flag f)
 	return 0;
 }
 
+static inline int mfc_is_enc_bframe(struct mfc_ctx *ctx)
+{
+	struct mfc_enc *enc;
+	struct mfc_enc_params *p;
+	int hier_qp_type = -EINVAL;
+	u8 num_hier_layer = 0;
+
+	if (ctx->type != MFCINST_ENCODER)
+		return 0;
+	enc = ctx->enc_priv;
+	if (!enc)
+		return 0;
+
+	p = &enc->params;
+	if (IS_H264_ENC(ctx)) {
+		num_hier_layer = p->codec.h264.num_hier_layer;
+		hier_qp_type = (int)p->codec.h264.hier_qp_type;
+	}
+	if (enc->params.num_b_frame ||
+	    (num_hier_layer >= 2 &&
+	     hier_qp_type == V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B))
+		return 1;
+
+	return 0;
+}
+
 int mfc_check_vb_with_fmt(struct mfc_fmt *fmt, struct vb2_buffer *vb);
 int mfc_check_resolution(struct mfc_ctx *ctx);
 void mfc_set_linear_stride_size(struct mfc_ctx *ctx, struct mfc_raw_info *raw, struct mfc_fmt *fmt);
 void mfc_dec_calc_dpb_size(struct mfc_ctx *ctx, struct mfc_raw_info *raw, struct mfc_fmt *fmt);
+void mfc_enc_calc_src_size(struct mfc_ctx *ctx);
 void mfc_calc_base_addr(struct mfc_ctx *ctx, struct vb2_buffer *vb, struct mfc_fmt *fmt);
 void mfc_set_view_buf_info(struct mfc_ctx *ctx, int mem_planes,
 			   int num_fd_depth_map, int num_fd_sub_view_meta);
@@ -355,6 +382,31 @@ static inline void mfc_ctx_change_idle_mode(struct mfc_ctx *ctx,
 	ctx->idle_mode = idle_mode;
 }
 
+static inline int mfc_enc_get_ts_delta(struct mfc_ctx *ctx)
+{
+	struct mfc_enc *enc = ctx->enc_priv;
+	struct mfc_enc_params *p = &enc->params;
+	int ts_delta = 0;
+
+	if (!ctx->src_ts.ts_last_interval) {
+		ts_delta = p->rc_framerate_res / p->rc_framerate;
+		mfc_ctx_debug(3, "[DFR] default delta: %d\n", ts_delta);
+	} else {
+		/*
+		 * FRAME_DELTA specifies the amount of
+		 * increment of frame modulo base time.
+		 * - delta unit = framerate resolution / fps
+		 * - fps = 1000000(usec per sec) / timestamp interval
+		 * For the sophistication of calculation, we will divide later.
+		 * Excluding H.263, resolution is fixed to 10000,
+		 * so thie is also divided into pre-calculated 100.
+		 * (Preventing both overflow and calculation duplication)
+		 */
+		ts_delta = ctx->src_ts.ts_last_interval / 100;
+	}
+	return ts_delta;
+}
+
 static inline void mfc_print_ctx_info(struct mfc_ctx *ctx)
 {
 	struct mfc_fmt *codec = NULL;
diff --git a/drivers/media/platform/samsung/exynos-mfc/mfc.c b/drivers/media/platform/samsung/exynos-mfc/mfc.c
index 293a353c49fa..db17448eae13 100644
--- a/drivers/media/platform/samsung/exynos-mfc/mfc.c
+++ b/drivers/media/platform/samsung/exynos-mfc/mfc.c
@@ -1128,6 +1128,9 @@ struct mfc_ctx_buf_size mfc_ctx_buf_size = {
 	.h264_dec_ctx	= PAGE_ALIGN(0x200000),	/* 1.6MB */
 	.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 */
+	.other_enc_ctx	= PAGE_ALIGN(0xC800),	/*  50KB */
 	.dbg_info_buf	= PAGE_ALIGN(0x1000),	/* 4KB for DEBUG INFO */
 };
 
-- 
2.34.1


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ