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: <1702899149-21321-34-git-send-email-quic_dikshita@quicinc.com>
Date: Mon, 18 Dec 2023 17:02:28 +0530
From: Dikshita Agarwal <quic_dikshita@...cinc.com>
To: linux-media@...r.kernel.org, linux-kernel@...r.kernel.org,
        stanimir.k.varbanov@...il.com, quic_vgarodia@...cinc.com,
        agross@...nel.org, andersson@...nel.org, konrad.dybcio@...aro.org,
        mchehab@...nel.org, bryan.odonoghue@...aro.org
Cc: linux-arm-msm@...r.kernel.org, quic_abhinavk@...cinc.com,
        Dikshita Agarwal <quic_dikshita@...cinc.com>
Subject: [PATCH v2 33/34] media: iris: add vb2 streaming and buffer ops for encoder

During stream on, set some mandatory properties
to firmware to start a session. Set all v4l2 properties set
by client, to firmware prepared with the dependency graph.
Also, configure the hardware internal buffers required
for frame processing. Send HFI_CMD_START on capture and
output planes to start the processing on respective planes.
The instance state is changed accordingly.

During stream off, send HFI_CMD_STOP to firmware which is
a synchronous command. After the response is received from
firmware, the session is closed on firmware and
instance state is changed accordingly.

Buffers are submitted and received via HFI_CMD_BUFFER.

Add Internal buffer size calculations for Encoder.

Signed-off-by: Dikshita Agarwal <quic_dikshita@...cinc.com>
---
 .../media/platform/qcom/vcodec/iris/hfi_defines.h  |  11 +
 .../media/platform/qcom/vcodec/iris/iris_buffer.c  | 296 ++++++++--
 .../media/platform/qcom/vcodec/iris/iris_ctrls.c   |  49 +-
 .../media/platform/qcom/vcodec/iris/iris_ctrls.h   |   1 +
 .../media/platform/qcom/vcodec/iris/iris_helpers.c | 169 +++++-
 .../media/platform/qcom/vcodec/iris/iris_helpers.h |   6 +
 drivers/media/platform/qcom/vcodec/iris/iris_hfi.c |  22 +-
 .../platform/qcom/vcodec/iris/iris_hfi_packet.c    | 137 +++--
 .../platform/qcom/vcodec/iris/iris_hfi_packet.h    |   9 +-
 .../platform/qcom/vcodec/iris/iris_hfi_response.c  | 143 +++--
 drivers/media/platform/qcom/vcodec/iris/iris_vb2.c |  62 +-
 .../media/platform/qcom/vcodec/iris/iris_vdec.c    | 137 +----
 .../media/platform/qcom/vcodec/iris/iris_venc.c    | 423 ++++++++++++++
 .../media/platform/qcom/vcodec/iris/iris_venc.h    |   3 +
 .../platform/qcom/vcodec/iris/platform_common.h    |   5 +
 .../platform/qcom/vcodec/iris/platform_sm8550.c    |   2 +
 .../platform/qcom/vcodec/iris/vpu_iris3_buffer.c   | 198 ++++++-
 .../platform/qcom/vcodec/iris/vpu_iris3_buffer.h   | 624 +++++++++++++++++++++
 .../platform/qcom/vcodec/iris/vpu_iris3_power.c    |   2 +-
 19 files changed, 1992 insertions(+), 307 deletions(-)

diff --git a/drivers/media/platform/qcom/vcodec/iris/hfi_defines.h b/drivers/media/platform/qcom/vcodec/iris/hfi_defines.h
index bc32c99..59765de 100644
--- a/drivers/media/platform/qcom/vcodec/iris/hfi_defines.h
+++ b/drivers/media/platform/qcom/vcodec/iris/hfi_defines.h
@@ -284,6 +284,10 @@ enum hfi_picture_type {
 
 #define HFI_PROP_NO_OUTPUT			0x0300016a
 
+#define HFI_PROP_BUFFER_MARK			0x0300016c
+
+#define HFI_PROP_RAW_RESOLUTION			0x03000178
+
 #define HFI_PROP_DPB_LIST			0x0300017A
 
 #define HFI_PROP_TOTAL_PEAK_BITRATE		0x0300017C
@@ -372,4 +376,11 @@ enum hfi_buffer_firmware_flags {
 	HFI_BUF_FW_FLAG_PSC_LAST	= 0x20000000,
 };
 
+enum hfi_hevc_profile_type {
+	HFI_H265_PROFILE_MAIN			= 0,
+	HFI_H265_PROFILE_MAIN_STILL_PICTURE	= 1,
+	HFI_H265_PROFILE_MAIN_10		= 2,
+	HFI_H265_PROFILE_MAIN_10_STILL_PICTURE	= 3,
+};
+
 #endif
diff --git a/drivers/media/platform/qcom/vcodec/iris/iris_buffer.c b/drivers/media/platform/qcom/vcodec/iris/iris_buffer.c
index f85b52c..18418e4e 100644
--- a/drivers/media/platform/qcom/vcodec/iris/iris_buffer.c
+++ b/drivers/media/platform/qcom/vcodec/iris/iris_buffer.c
@@ -10,6 +10,7 @@
 #include "hfi_defines.h"
 #include "iris_hfi_packet.h"
 #include "iris_instance.h"
+#include "vpu_iris3_buffer.h"
 
 static const u32 dec_ip_int_buf_type[] = {
 	BUF_BIN,
@@ -22,15 +23,51 @@ static const u32 dec_op_int_buf_type[] = {
 	BUF_DPB,
 };
 
+static const u32 enc_ip_int_buf_type[] = {
+	BUF_VPSS,
+};
+
+static const u32 enc_op_int_buf_type[] = {
+	BUF_BIN,
+	BUF_COMV,
+	BUF_NON_COMV,
+	BUF_LINE,
+	BUF_DPB,
+};
+
 static int input_min_count(struct iris_inst *inst)
 {
-	return MIN_BUFFERS;
+	u32 input_min_count = 0;
+	u32 total_hb_layer = 0;
+
+	if (inst->domain == DECODER) {
+		input_min_count = MIN_BUFFERS;
+	} else if (inst->domain == ENCODER) {
+		total_hb_layer = is_hierb_type_requested(inst) ?
+			inst->cap[ENH_LAYER_COUNT].value + 1 : 0;
+		if (inst->codec == H264 &&
+		    !inst->cap[LAYER_ENABLE].value) {
+			total_hb_layer = 0;
+		}
+		input_min_count =
+			hfi_iris3_enc_min_input_buf_count(total_hb_layer);
+	} else {
+		return 0;
+	}
+
+	return input_min_count;
 }
 
 static int output_min_count(struct iris_inst *inst)
 {
 	int output_min_count;
 
+	if (inst->domain != DECODER && inst->domain != ENCODER)
+		return 0;
+
+	if (inst->domain == ENCODER)
+		return MIN_BUFFERS;
+
 	/* fw_min_count > 0 indicates reconfig event has already arrived */
 	if (inst->fw_min_count) {
 		if (is_split_mode_enabled(inst) && inst->codec == VP9)
@@ -83,16 +120,21 @@ static u32 internal_buffer_count(struct iris_inst *inst,
 {
 	u32 count = 0;
 
-	if (buffer_type == BUF_BIN || buffer_type == BUF_LINE ||
-	    buffer_type == BUF_PERSIST) {
-		count = 1;
-	} else if (buffer_type == BUF_COMV || buffer_type == BUF_NON_COMV) {
-		if (inst->codec == H264 || inst->codec == HEVC)
+	if (inst->domain == ENCODER)
+		return 1;
+
+	if (inst->domain == DECODER) {
+		if (buffer_type == BUF_BIN || buffer_type == BUF_LINE ||
+		    buffer_type == BUF_PERSIST) {
 			count = 1;
-		else
+		} else if (buffer_type == BUF_COMV || buffer_type == BUF_NON_COMV) {
+			if (inst->codec == H264 || inst->codec == HEVC)
+				count = 1;
+			else
+				count = 0;
+		} else {
 			count = 0;
-	} else {
-		count = 0;
+		}
 	}
 
 	return count;
@@ -102,6 +144,9 @@ static int dpb_count(struct iris_inst *inst)
 {
 	int count = 0;
 
+	if (inst->domain == ENCODER)
+		return get_recon_buf_count(inst);
+
 	if (is_split_mode_enabled(inst)) {
 		count = inst->fw_min_count ?
 			inst->fw_min_count : inst->buffers.output.min_count;
@@ -123,6 +168,7 @@ int iris_get_buf_min_count(struct iris_inst *inst,
 	case BUF_NON_COMV:
 	case BUF_LINE:
 	case BUF_PERSIST:
+	case BUF_ARP:
 		return internal_buffer_count(inst, buffer_type);
 	case BUF_DPB:
 		return dpb_count(inst);
@@ -131,7 +177,7 @@ int iris_get_buf_min_count(struct iris_inst *inst,
 	}
 }
 
-static u32 input_buffer_size(struct iris_inst *inst)
+static u32 dec_input_buffer_size(struct iris_inst *inst)
 {
 	u32 base_res_mbs = NUM_MBS_4k;
 	u32 frame_size, num_mbs;
@@ -163,7 +209,7 @@ static u32 input_buffer_size(struct iris_inst *inst)
 	return ALIGN(frame_size, SZ_4K);
 }
 
-static u32 output_buffer_size(struct iris_inst *inst)
+static u32 dec_output_buffer_size(struct iris_inst *inst)
 {
 	struct v4l2_format *f;
 	u32 size;
@@ -175,17 +221,97 @@ static u32 output_buffer_size(struct iris_inst *inst)
 	return size;
 }
 
+static u32 enc_input_buffer_size(struct iris_inst *inst)
+{
+	struct v4l2_format *f;
+	u32 size;
+
+	f = inst->fmt_src;
+
+	size = video_raw_buffer_size(f->fmt.pix_mp.pixelformat, f->fmt.pix_mp.width,
+				     f->fmt.pix_mp.height);
+	return size;
+}
+
+static inline
+u32 hfi_buffer_bitstream_enc(u32 frame_width, u32 frame_height,
+			     u32 rc_type, bool is_ten_bit)
+{
+	u32 aligned_width, aligned_height, bitstream_size, yuv_size;
+
+	aligned_width = ALIGN(frame_width, 32);
+	aligned_height = ALIGN(frame_height, 32);
+	bitstream_size = aligned_width * aligned_height * 3;
+	yuv_size = (aligned_width * aligned_height * 3) >> 1;
+	if (aligned_width * aligned_height > (4096 * 2176))
+		/* bitstream_size = 0.25 * yuv_size; */
+		bitstream_size = (bitstream_size >> 3);
+	else if (aligned_width * aligned_height > (1280 * 720))
+		/* bitstream_size = 0.5 * yuv_size; */
+		bitstream_size = (bitstream_size >> 2);
+
+	if ((rc_type == HFI_RC_CQ || rc_type == HFI_RC_OFF) &&
+	    bitstream_size < yuv_size)
+		bitstream_size = (bitstream_size << 1);
+
+	if (is_ten_bit)
+		bitstream_size = (bitstream_size) + (bitstream_size >> 2);
+
+	return ALIGN(bitstream_size, HFI_ALIGNMENT_4096);
+}
+
+static u32 enc_output_buffer_size(struct iris_inst *inst)
+{
+	u32 hfi_rc_type = HFI_RC_VBR_CFR;
+	enum codec_type codec;
+	int bitrate_mode, frame_rc;
+	bool is_ten_bit = false;
+	struct v4l2_format *f;
+	u32 frame_size;
+
+	f = inst->fmt_dst;
+	codec = v4l2_codec_to_driver(inst, f->fmt.pix_mp.pixelformat);
+	if (codec == HEVC)
+		is_ten_bit = true;
+
+	bitrate_mode = inst->cap[BITRATE_MODE].value;
+	frame_rc = inst->cap[FRAME_RC_ENABLE].value;
+	if (!frame_rc)
+		hfi_rc_type = HFI_RC_OFF;
+	else if (bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ)
+		hfi_rc_type = HFI_RC_CQ;
+
+	frame_size = hfi_buffer_bitstream_enc(f->fmt.pix_mp.width,
+					      f->fmt.pix_mp.height,
+					      hfi_rc_type, is_ten_bit);
+
+	return frame_size;
+}
+
 int iris_get_buffer_size(struct iris_inst *inst,
 			 enum iris_buffer_type buffer_type)
 {
-	switch (buffer_type) {
-	case BUF_INPUT:
-		return input_buffer_size(inst);
-	case BUF_OUTPUT:
-		return output_buffer_size(inst);
-	default:
-		return 0;
+	if (inst->domain == DECODER) {
+		switch (buffer_type) {
+		case BUF_INPUT:
+			return dec_input_buffer_size(inst);
+		case BUF_OUTPUT:
+			return dec_output_buffer_size(inst);
+		default:
+			break;
+		}
+	} else if (inst->domain == ENCODER) {
+		switch (buffer_type) {
+		case BUF_INPUT:
+			return enc_input_buffer_size(inst);
+		case BUF_OUTPUT:
+			return enc_output_buffer_size(inst);
+		default:
+			break;
+		}
 	}
+
+	return 0;
 }
 
 struct iris_buffers *iris_get_buffer_list(struct iris_inst *inst,
@@ -300,14 +426,30 @@ int iris_get_internal_buffers(struct iris_inst *inst,
 	int ret = 0;
 	u32 i = 0;
 
-	if (plane == INPUT_MPLANE) {
-		for (i = 0; i < ARRAY_SIZE(dec_ip_int_buf_type); i++) {
-			ret = iris_get_internal_buf_info(inst, dec_ip_int_buf_type[i]);
-			if (ret)
-				return ret;
+	if (inst->domain == DECODER) {
+		if (plane == INPUT_MPLANE) {
+			for (i = 0; i < ARRAY_SIZE(dec_ip_int_buf_type); i++) {
+				ret = iris_get_internal_buf_info(inst, dec_ip_int_buf_type[i]);
+				if (ret)
+					return ret;
+			}
+		} else {
+			return iris_get_internal_buf_info(inst, BUF_DPB);
+		}
+	} else if (inst->domain == ENCODER) {
+		if (plane == INPUT_MPLANE) {
+			for (i = 0; i < ARRAY_SIZE(enc_ip_int_buf_type); i++) {
+				ret = iris_get_internal_buf_info(inst, enc_ip_int_buf_type[i]);
+				if (ret)
+					return ret;
+			}
+		} else {
+			for (i = 0; i < ARRAY_SIZE(enc_op_int_buf_type); i++) {
+				ret = iris_get_internal_buf_info(inst, enc_op_int_buf_type[i]);
+				if (ret)
+					return ret;
+			}
 		}
-	} else {
-		return iris_get_internal_buf_info(inst, BUF_DPB);
 	}
 
 	return ret;
@@ -377,10 +519,18 @@ int iris_create_input_internal_buffers(struct iris_inst *inst)
 	int ret = 0;
 	u32 i = 0;
 
-	for (i = 0; i < ARRAY_SIZE(dec_ip_int_buf_type); i++) {
-		ret = iris_create_internal_buffers(inst, dec_ip_int_buf_type[i]);
-		if (ret)
-			return ret;
+	if (inst->domain == DECODER) {
+		for (i = 0; i < ARRAY_SIZE(dec_ip_int_buf_type); i++) {
+			ret = iris_create_internal_buffers(inst, dec_ip_int_buf_type[i]);
+			if (ret)
+				return ret;
+		}
+	} else if (inst->domain == ENCODER) {
+		for (i = 0; i < ARRAY_SIZE(enc_ip_int_buf_type); i++) {
+			ret = iris_create_internal_buffers(inst, enc_ip_int_buf_type[i]);
+			if (ret)
+				return ret;
+		}
 	}
 
 	return ret;
@@ -388,7 +538,20 @@ int iris_create_input_internal_buffers(struct iris_inst *inst)
 
 int iris_create_output_internal_buffers(struct iris_inst *inst)
 {
-	return iris_create_internal_buffers(inst, BUF_DPB);
+	int ret = 0;
+	u32 i = 0;
+
+	if (inst->domain == DECODER) {
+		return iris_create_internal_buffers(inst, BUF_DPB);
+	} else if (inst->domain == ENCODER) {
+		for (i = 0; i < ARRAY_SIZE(enc_op_int_buf_type); i++) {
+			ret = iris_create_internal_buffers(inst, enc_op_int_buf_type[i]);
+			if (ret)
+				return ret;
+		}
+	}
+
+	return ret;
 }
 
 static int set_num_comv(struct iris_inst *inst)
@@ -413,7 +576,7 @@ static int iris_queue_internal_buffers(struct iris_inst *inst,
 	struct iris_buffers *buffers;
 	int ret = 0;
 
-	if (buffer_type == BUF_COMV) {
+	if (inst->domain == DECODER && buffer_type == BUF_COMV) {
 		ret = set_num_comv(inst);
 		if (ret)
 			return ret;
@@ -442,10 +605,18 @@ int iris_queue_input_internal_buffers(struct iris_inst *inst)
 	int ret = 0;
 	u32 i;
 
-	for (i = 0; i < ARRAY_SIZE(dec_ip_int_buf_type); i++) {
-		ret = iris_queue_internal_buffers(inst, dec_ip_int_buf_type[i]);
-		if (ret)
-			return ret;
+	if (inst->domain == DECODER) {
+		for (i = 0; i < ARRAY_SIZE(dec_ip_int_buf_type); i++) {
+			ret = iris_queue_internal_buffers(inst, dec_ip_int_buf_type[i]);
+			if (ret)
+				return ret;
+		}
+	} else if (inst->domain == ENCODER) {
+		for (i = 0; i < ARRAY_SIZE(enc_ip_int_buf_type); i++) {
+			ret = iris_queue_internal_buffers(inst, enc_ip_int_buf_type[i]);
+			if (ret)
+				return ret;
+		}
 	}
 
 	return ret;
@@ -453,7 +624,20 @@ int iris_queue_input_internal_buffers(struct iris_inst *inst)
 
 int iris_queue_output_internal_buffers(struct iris_inst *inst)
 {
-	return iris_queue_internal_buffers(inst, BUF_DPB);
+	int ret = 0;
+	u32 i = 0;
+
+	if (inst->domain == DECODER) {
+		return iris_queue_internal_buffers(inst, BUF_DPB);
+	} else if (inst->domain == ENCODER) {
+		for (i = 0; i < ARRAY_SIZE(enc_op_int_buf_type); i++) {
+			ret = iris_queue_internal_buffers(inst, enc_op_int_buf_type[i]);
+			if (ret)
+				return ret;
+		}
+	}
+
+	return ret;
 }
 
 int iris_destroy_internal_buffer(struct iris_inst *inst,
@@ -489,16 +673,26 @@ int iris_destroy_internal_buffers(struct iris_inst *inst,
 {
 	struct iris_buffer *buf, *dummy;
 	struct iris_buffers *buffers;
-	const u32 *internal_buf_type;
+	const u32 *internal_buf_type = NULL;
 	int ret = 0;
-	u32 i, len;
-
-	if (plane == INPUT_MPLANE) {
-		internal_buf_type = dec_ip_int_buf_type;
-		len = ARRAY_SIZE(dec_ip_int_buf_type);
-	} else {
-		internal_buf_type = dec_op_int_buf_type;
-		len = ARRAY_SIZE(dec_op_int_buf_type);
+	u32 i, len = 0;
+
+	if (inst->domain == DECODER) {
+		if (plane == INPUT_MPLANE) {
+			internal_buf_type = dec_ip_int_buf_type;
+			len = ARRAY_SIZE(dec_ip_int_buf_type);
+		} else {
+			internal_buf_type = dec_op_int_buf_type;
+			len = ARRAY_SIZE(dec_op_int_buf_type);
+		}
+	} else if (inst->domain == ENCODER) {
+		if (plane == INPUT_MPLANE) {
+			internal_buf_type = enc_ip_int_buf_type;
+			len = ARRAY_SIZE(enc_ip_int_buf_type);
+		} else {
+			internal_buf_type = enc_op_int_buf_type;
+			len = ARRAY_SIZE(enc_op_int_buf_type);
+		}
 	}
 
 	for (i = 0; i < len; i++) {
@@ -552,10 +746,12 @@ static int iris_release_input_internal_buffers(struct iris_inst *inst)
 	int ret = 0;
 	u32 i = 0;
 
-	for (i = 0; i < ARRAY_SIZE(dec_ip_int_buf_type); i++) {
-		ret = iris_release_internal_buffers(inst, dec_ip_int_buf_type[i]);
-		if (ret)
-			return ret;
+	if (inst->domain == DECODER) {
+		for (i = 0; i < ARRAY_SIZE(dec_ip_int_buf_type); i++) {
+			ret = iris_release_internal_buffers(inst, dec_ip_int_buf_type[i]);
+			if (ret)
+				return ret;
+		}
 	}
 
 	return ret;
@@ -566,7 +762,7 @@ int iris_alloc_and_queue_session_int_bufs(struct iris_inst *inst,
 {
 	int ret;
 
-	if (buffer_type != BUF_PERSIST)
+	if (buffer_type != BUF_ARP && buffer_type != BUF_PERSIST)
 		return -EINVAL;
 
 	ret = iris_get_internal_buf_info(inst, buffer_type);
diff --git a/drivers/media/platform/qcom/vcodec/iris/iris_ctrls.c b/drivers/media/platform/qcom/vcodec/iris/iris_ctrls.c
index af99ac73..559b0dd 100644
--- a/drivers/media/platform/qcom/vcodec/iris/iris_ctrls.c
+++ b/drivers/media/platform/qcom/vcodec/iris/iris_ctrls.c
@@ -723,11 +723,20 @@ int set_stage(struct iris_inst *inst,
 
 	hfi_id = inst->cap[cap_id].hfi_id;
 
-	inp_f = inst->fmt_src;
-	height = inp_f->fmt.pix_mp.height;
-	width = inp_f->fmt.pix_mp.width;
-	if (res_is_less_than(width, height, 1280, 720))
-		work_mode = STAGE_1;
+	if (inst->domain == DECODER) {
+		inp_f = inst->fmt_src;
+		height = inp_f->fmt.pix_mp.height;
+		width = inp_f->fmt.pix_mp.width;
+		if (res_is_less_than(width, height, 1280, 720))
+			work_mode = STAGE_1;
+	} else if (inst->domain == ENCODER) {
+		if (inst->cap[SLICE_MODE].value ==
+		    V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES)
+			work_mode = STAGE_1;
+
+		if (!inst->cap[GOP_SIZE].value)
+			work_mode = STAGE_2;
+	}
 
 	return iris_hfi_set_property(inst, hfi_id, HFI_HOST_FLAGS_NONE,
 				     get_port_info(inst, cap_id),
@@ -743,6 +752,12 @@ int set_pipe(struct iris_inst *inst,
 	work_route = inst->cap[cap_id].value;
 	hfi_id = inst->cap[cap_id].hfi_id;
 
+	if (inst->domain == ENCODER) {
+		if (inst->cap[SLICE_MODE].value ==
+		    V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES)
+			work_route = PIPE_1;
+	}
+
 	return iris_hfi_set_property(inst, hfi_id, HFI_HOST_FLAGS_NONE,
 				     get_port_info(inst, cap_id),
 				     HFI_PAYLOAD_U32,
@@ -763,6 +778,30 @@ int set_level(struct iris_inst *inst, enum plat_inst_cap_type cap_id)
 					 &hfi_value, sizeof(u32));
 }
 
+int decide_quality_mode(struct iris_inst *inst)
+{
+	u32 fps, mbpf, mbps, max_hq_mbpf, max_hq_mbps;
+	u32 mode = POWER_SAVE_MODE;
+	struct iris_core *core;
+
+	if (inst->domain != ENCODER)
+		return 0;
+
+	mbpf = NUM_MBS_PER_FRAME(inst->crop.height, inst->crop.width);
+	fps = max3(inst->cap[QUEUED_RATE].value >> 16,
+		   inst->cap[FRAME_RATE].value >> 16,
+		   inst->cap[OPERATING_RATE].value >> 16);
+	mbps = mbpf * fps;
+	core = inst->core;
+	max_hq_mbpf = core->cap[MAX_MBPF_HQ].value;
+	max_hq_mbps = core->cap[MAX_MBPS_HQ].value;
+
+	if (mbpf <= max_hq_mbpf && mbps <= max_hq_mbps)
+		mode = MAX_QUALITY_MODE;
+
+	return mode;
+}
+
 int set_req_sync_frame(struct iris_inst *inst, enum plat_inst_cap_type cap_id)
 {
 	u32 hfi_id, hfi_val;
diff --git a/drivers/media/platform/qcom/vcodec/iris/iris_ctrls.h b/drivers/media/platform/qcom/vcodec/iris/iris_ctrls.h
index 5421d9f..404d98c 100644
--- a/drivers/media/platform/qcom/vcodec/iris/iris_ctrls.h
+++ b/drivers/media/platform/qcom/vcodec/iris/iris_ctrls.h
@@ -33,6 +33,7 @@ int adjust_v4l2_properties(struct iris_inst *inst);
 int ctrls_init(struct iris_inst *inst, bool init);
 int set_q16(struct iris_inst *inst, enum plat_inst_cap_type cap_id);
 int set_level(struct iris_inst *inst, enum plat_inst_cap_type cap_id);
+int decide_quality_mode(struct iris_inst *inst);
 int set_req_sync_frame(struct iris_inst *inst, enum plat_inst_cap_type cap_id);
 int set_flip(struct iris_inst *inst, enum plat_inst_cap_type cap_id);
 int set_rotation(struct iris_inst *inst, enum plat_inst_cap_type cap_id);
diff --git a/drivers/media/platform/qcom/vcodec/iris/iris_helpers.c b/drivers/media/platform/qcom/vcodec/iris/iris_helpers.c
index c84bb51..a770157 100644
--- a/drivers/media/platform/qcom/vcodec/iris/iris_helpers.c
+++ b/drivers/media/platform/qcom/vcodec/iris/iris_helpers.c
@@ -44,15 +44,15 @@ u32 get_port_info(struct iris_inst *inst,
 	if (inst->cap[cap_id].flags & CAP_FLAG_INPUT_PORT &&
 	    inst->cap[cap_id].flags & CAP_FLAG_OUTPUT_PORT) {
 		if (inst->vb2q_dst->streaming)
-			return get_hfi_port(INPUT_MPLANE);
+			return get_hfi_port(inst, INPUT_MPLANE);
 		else
-			return get_hfi_port(OUTPUT_MPLANE);
+			return get_hfi_port(inst, OUTPUT_MPLANE);
 	}
 
 	if (inst->cap[cap_id].flags & CAP_FLAG_INPUT_PORT)
-		return get_hfi_port(INPUT_MPLANE);
+		return get_hfi_port(inst, INPUT_MPLANE);
 	else if (inst->cap[cap_id].flags & CAP_FLAG_OUTPUT_PORT)
-		return get_hfi_port(OUTPUT_MPLANE);
+		return get_hfi_port(inst, OUTPUT_MPLANE);
 	else
 		return HFI_PORT_NONE;
 }
@@ -86,9 +86,14 @@ int get_mbpf(struct iris_inst *inst)
 	int height = 0, width = 0;
 	struct v4l2_format *inp_f;
 
-	inp_f = inst->fmt_src;
-	width = max(inp_f->fmt.pix_mp.width, inst->crop.width);
-	height = max(inp_f->fmt.pix_mp.height, inst->crop.height);
+	if (inst->domain == DECODER) {
+		inp_f = inst->fmt_src;
+		width = max(inp_f->fmt.pix_mp.width, inst->crop.width);
+		height = max(inp_f->fmt.pix_mp.height, inst->crop.height);
+	} else if (inst->domain == ENCODER) {
+		width = inst->crop.width;
+		height = inst->crop.height;
+	}
 
 	return NUM_MBS_PER_FRAME(height, width);
 }
@@ -100,6 +105,9 @@ inline bool is_linear_colorformat(u32 colorformat)
 
 bool is_split_mode_enabled(struct iris_inst *inst)
 {
+	if (inst->domain != DECODER)
+		return false;
+
 	if (is_linear_colorformat(inst->fmt_dst->fmt.pix_mp.pixelformat))
 		return true;
 
@@ -118,6 +126,24 @@ inline bool is_8bit_colorformat(enum colorformat_type colorformat)
 		colorformat == FMT_NV21;
 }
 
+inline bool is_scaling_enabled(struct iris_inst *inst)
+{
+	return inst->crop.left != inst->compose.left ||
+		inst->crop.top != inst->compose.top ||
+		inst->crop.width != inst->compose.width ||
+		inst->crop.height != inst->compose.height;
+}
+
+inline bool is_hierb_type_requested(struct iris_inst *inst)
+{
+	return (inst->codec == H264 &&
+		inst->cap[LAYER_TYPE].value ==
+				V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_B) ||
+		(inst->codec == HEVC &&
+		inst->cap[LAYER_TYPE].value ==
+				V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B);
+}
+
 u32 v4l2_codec_from_driver(struct iris_inst *inst, enum codec_type codec)
 {
 	const struct codec_info *codec_info;
@@ -319,17 +345,24 @@ static int check_resolution_supported(struct iris_inst *inst)
 	u32 width = 0, height = 0, min_width, min_height,
 		max_width, max_height;
 
-	width = inst->fmt_src->fmt.pix_mp.width;
-	height = inst->fmt_src->fmt.pix_mp.height;
+	if (inst->domain == DECODER) {
+		width = inst->fmt_src->fmt.pix_mp.width;
+		height = inst->fmt_src->fmt.pix_mp.height;
+	} else if (inst->domain == ENCODER) {
+		width = inst->crop.width;
+		height = inst->crop.height;
+	}
 
 	min_width = inst->cap[FRAME_WIDTH].min;
 	max_width = inst->cap[FRAME_WIDTH].max;
 	min_height = inst->cap[FRAME_HEIGHT].min;
 	max_height = inst->cap[FRAME_HEIGHT].max;
 
-	if (!(min_width <= width && width <= max_width) ||
-	    !(min_height <= height && height <= max_height))
-		return -EINVAL;
+	if (inst->domain == DECODER || inst->domain == ENCODER) {
+		if (!(min_width <= width && width <= max_width) ||
+		    !(min_height <= height && height <= max_height))
+			return -EINVAL;
+	}
 
 	return 0;
 }
@@ -470,7 +503,7 @@ int queue_buffer(struct iris_inst *inst, struct iris_buffer *buf)
 {
 	int ret;
 
-	if (buf->type == BUF_OUTPUT)
+	if (inst->domain == DECODER && buf->type == BUF_OUTPUT)
 		process_requeued_readonly_buffers(inst, buf);
 
 	ret = iris_hfi_queue_buffer(inst, buf);
@@ -653,7 +686,7 @@ static int iris_flush_read_only_buffers(struct iris_inst *inst,
 {
 	struct iris_buffer *ro_buf, *dummy;
 
-	if (type != BUF_OUTPUT)
+	if (inst->domain != DECODER || type != BUF_OUTPUT)
 		return 0;
 
 	list_for_each_entry_safe(ro_buf, dummy, &inst->buffers.read_only.list, list) {
@@ -899,6 +932,114 @@ int codec_change(struct iris_inst *inst, u32 v4l2_codec)
 	return ret;
 }
 
+int process_streamon_input(struct iris_inst *inst)
+{
+	enum iris_inst_sub_state set_sub_state = IRIS_INST_SUB_NONE;
+	int ret;
+
+	iris_scale_power(inst);
+
+	ret = iris_hfi_start(inst, INPUT_MPLANE);
+	if (ret)
+		return ret;
+
+	if (inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) {
+		ret = iris_inst_change_sub_state(inst, IRIS_INST_SUB_INPUT_PAUSE, 0);
+		if (ret)
+			return ret;
+	}
+
+	if (inst->sub_state & IRIS_INST_SUB_DRC ||
+	    inst->sub_state & IRIS_INST_SUB_DRAIN) {
+		if (!(inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE)) {
+			ret = iris_hfi_pause(inst, INPUT_MPLANE);
+			if (ret)
+				return ret;
+			set_sub_state = IRIS_INST_SUB_INPUT_PAUSE;
+		}
+	}
+
+	ret = iris_inst_state_change_streamon(inst, INPUT_MPLANE);
+	if (ret)
+		return ret;
+
+	ret = iris_inst_change_sub_state(inst, 0, set_sub_state);
+
+	return ret;
+}
+
+int process_streamon_output(struct iris_inst *inst)
+{
+	enum iris_inst_sub_state clear_sub_state = IRIS_INST_SUB_NONE;
+	bool drain_pending = false;
+	int ret;
+
+	iris_scale_power(inst);
+
+	if (inst->sub_state & IRIS_INST_SUB_DRC &&
+	    inst->sub_state & IRIS_INST_SUB_DRC_LAST)
+		clear_sub_state = IRIS_INST_SUB_DRC | IRIS_INST_SUB_DRC_LAST;
+
+	if (inst->domain == DECODER && inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) {
+		ret = iris_alloc_and_queue_input_int_bufs(inst);
+		if (ret)
+			return ret;
+		ret = set_stage(inst, STAGE);
+		if (ret)
+			return ret;
+		ret = set_pipe(inst, PIPE);
+		if (ret)
+			return ret;
+	}
+
+	drain_pending = inst->sub_state & IRIS_INST_SUB_DRAIN &&
+		inst->sub_state & IRIS_INST_SUB_DRAIN_LAST;
+
+	if (!drain_pending && inst->state == IRIS_INST_INPUT_STREAMING) {
+		if (inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) {
+			ret = iris_hfi_resume(inst, INPUT_MPLANE, HFI_CMD_SETTINGS_CHANGE);
+			if (ret)
+				return ret;
+			clear_sub_state |= IRIS_INST_SUB_INPUT_PAUSE;
+		}
+	}
+
+	ret = iris_hfi_start(inst, OUTPUT_MPLANE);
+	if (ret)
+		return ret;
+
+	if (inst->sub_state & IRIS_INST_SUB_OUTPUT_PAUSE)
+		clear_sub_state |= IRIS_INST_SUB_OUTPUT_PAUSE;
+
+	ret = iris_inst_state_change_streamon(inst, OUTPUT_MPLANE);
+	if (ret)
+		return ret;
+
+	ret = iris_inst_change_sub_state(inst, clear_sub_state, 0);
+
+	return ret;
+}
+
+int vb2_buffer_to_driver(struct vb2_buffer *vb2, struct iris_buffer *buf)
+{
+	struct vb2_v4l2_buffer *vbuf;
+
+	if (!vb2 || !buf)
+		return -EINVAL;
+
+	vbuf = to_vb2_v4l2_buffer(vb2);
+
+	buf->fd = vb2->planes[0].m.fd;
+	buf->data_offset = vb2->planes[0].data_offset;
+	buf->data_size = vb2->planes[0].bytesused - vb2->planes[0].data_offset;
+	buf->buffer_size = vb2->planes[0].length;
+	buf->timestamp = vb2->timestamp;
+	buf->flags = vbuf->flags;
+	buf->attr = 0;
+
+	return 0;
+}
+
 int iris_pm_get(struct iris_core *core)
 {
 	int ret;
diff --git a/drivers/media/platform/qcom/vcodec/iris/iris_helpers.h b/drivers/media/platform/qcom/vcodec/iris/iris_helpers.h
index 39cec8c..bf8448a 100644
--- a/drivers/media/platform/qcom/vcodec/iris/iris_helpers.h
+++ b/drivers/media/platform/qcom/vcodec/iris/iris_helpers.h
@@ -31,7 +31,9 @@ int close_session(struct iris_inst *inst);
 bool is_linear_colorformat(u32 colorformat);
 bool is_10bit_colorformat(enum colorformat_type colorformat);
 bool is_8bit_colorformat(enum colorformat_type colorformat);
+bool is_scaling_enabled(struct iris_inst *inst);
 bool is_split_mode_enabled(struct iris_inst *inst);
+bool is_hierb_type_requested(struct iris_inst *inst);
 int signal_session_msg_receipt(struct iris_inst *inst,
 			       enum signal_session_response cmd);
 struct iris_inst *to_instance(struct iris_core *core, u32 session_id);
@@ -54,6 +56,10 @@ void iris_destroy_buffers(struct iris_inst *inst);
 int session_streamoff(struct iris_inst *inst, u32 plane);
 int process_resume(struct iris_inst *inst);
 int codec_change(struct iris_inst *inst, u32 v4l2_codec);
+int process_streamon_input(struct iris_inst *inst);
+int process_streamon_output(struct iris_inst *inst);
+int vb2_buffer_to_driver(struct vb2_buffer *vb2,
+			 struct iris_buffer *buf);
 int iris_pm_get(struct iris_core *core);
 int iris_pm_put(struct iris_core *core, bool autosuspend);
 int iris_pm_get_put(struct iris_core *core);
diff --git a/drivers/media/platform/qcom/vcodec/iris/iris_hfi.c b/drivers/media/platform/qcom/vcodec/iris/iris_hfi.c
index 00e598d..4a54293 100644
--- a/drivers/media/platform/qcom/vcodec/iris/iris_hfi.c
+++ b/drivers/media/platform/qcom/vcodec/iris/iris_hfi.c
@@ -356,7 +356,7 @@ int iris_hfi_session_set_default_header(struct iris_inst *inst)
 	ret = hfi_packet_session_property(inst,
 					  HFI_PROP_DEC_DEFAULT_HEADER,
 					  HFI_HOST_FLAGS_NONE,
-					  get_hfi_port(INPUT_MPLANE),
+					  get_hfi_port(inst, INPUT_MPLANE),
 					  HFI_PAYLOAD_U32,
 					  &default_header,
 					  sizeof(u32));
@@ -394,7 +394,7 @@ int iris_hfi_start(struct iris_inst *inst, u32 plane)
 					 HFI_CMD_START,
 					 (HFI_HOST_FLAGS_RESPONSE_REQUIRED |
 					 HFI_HOST_FLAGS_INTR_REQUIRED),
-					 get_hfi_port(plane),
+					 get_hfi_port(inst, plane),
 					 inst->session_id,
 					 HFI_PAYLOAD_NONE,
 					 NULL,
@@ -434,7 +434,7 @@ int iris_hfi_stop(struct iris_inst *inst, u32 plane)
 					 (HFI_HOST_FLAGS_RESPONSE_REQUIRED |
 					 HFI_HOST_FLAGS_INTR_REQUIRED |
 					 HFI_HOST_FLAGS_NON_DISCARDABLE),
-					 get_hfi_port(plane),
+					 get_hfi_port(inst, plane),
 					 inst->session_id,
 					 HFI_PAYLOAD_NONE,
 					 NULL,
@@ -472,7 +472,7 @@ int iris_hfi_session_subscribe_mode(struct iris_inst *inst,
 					 cmd,
 					 (HFI_HOST_FLAGS_RESPONSE_REQUIRED |
 					 HFI_HOST_FLAGS_INTR_REQUIRED),
-					 get_hfi_port(plane),
+					 get_hfi_port(inst, plane),
 					 inst->session_id,
 					 payload_type,
 					 payload,
@@ -511,7 +511,7 @@ int iris_hfi_pause(struct iris_inst *inst, u32 plane)
 					 HFI_CMD_PAUSE,
 					 (HFI_HOST_FLAGS_RESPONSE_REQUIRED |
 					 HFI_HOST_FLAGS_INTR_REQUIRED),
-					 get_hfi_port(plane),
+					 get_hfi_port(inst, plane),
 					 inst->session_id,
 					 HFI_PAYLOAD_NONE,
 					 NULL,
@@ -550,7 +550,7 @@ int iris_hfi_resume(struct iris_inst *inst, u32 plane, u32 payload)
 					 HFI_CMD_RESUME,
 					 (HFI_HOST_FLAGS_RESPONSE_REQUIRED |
 					 HFI_HOST_FLAGS_INTR_REQUIRED),
-					 get_hfi_port(plane),
+					 get_hfi_port(inst, plane),
 					 inst->session_id,
 					 HFI_PAYLOAD_U32,
 					 &payload,
@@ -590,7 +590,7 @@ int iris_hfi_drain(struct iris_inst *inst, u32 plane)
 					 (HFI_HOST_FLAGS_RESPONSE_REQUIRED |
 					 HFI_HOST_FLAGS_INTR_REQUIRED |
 					 HFI_HOST_FLAGS_NON_DISCARDABLE),
-					 get_hfi_port(plane),
+					 get_hfi_port(inst, plane),
 					 inst->session_id,
 					 HFI_PAYLOAD_NONE,
 					 NULL,
@@ -739,14 +739,14 @@ int iris_hfi_queue_buffer(struct iris_inst *inst,
 		goto unlock;
 	}
 
-	ret = get_hfi_buffer(buffer, &hfi_buffer);
+	ret = get_hfi_buffer(inst, buffer, &hfi_buffer);
 	if (ret)
 		goto unlock;
 
 	ret = hfi_packet_session_command(inst,
 					 HFI_CMD_BUFFER,
 					 HFI_HOST_FLAGS_INTR_REQUIRED,
-					 get_hfi_port_from_buffer_type(buffer->type),
+					 get_hfi_port_from_buffer_type(inst, buffer->type),
 					 inst->session_id,
 					 HFI_PAYLOAD_STRUCTURE,
 					 &hfi_buffer,
@@ -780,7 +780,7 @@ int iris_hfi_release_buffer(struct iris_inst *inst,
 		goto unlock;
 	}
 
-	ret = get_hfi_buffer(buffer, &hfi_buffer);
+	ret = get_hfi_buffer(inst, buffer, &hfi_buffer);
 	if (ret)
 		goto unlock;
 
@@ -790,7 +790,7 @@ int iris_hfi_release_buffer(struct iris_inst *inst,
 					 HFI_CMD_BUFFER,
 					 (HFI_HOST_FLAGS_RESPONSE_REQUIRED |
 					 HFI_HOST_FLAGS_INTR_REQUIRED),
-					 get_hfi_port_from_buffer_type(buffer->type),
+					 get_hfi_port_from_buffer_type(inst, buffer->type),
 					 inst->session_id,
 					 HFI_PAYLOAD_STRUCTURE,
 					 &hfi_buffer,
diff --git a/drivers/media/platform/qcom/vcodec/iris/iris_hfi_packet.c b/drivers/media/platform/qcom/vcodec/iris/iris_hfi_packet.c
index dd27fa4..e9f3749 100644
--- a/drivers/media/platform/qcom/vcodec/iris/iris_hfi_packet.c
+++ b/drivers/media/platform/qcom/vcodec/iris/iris_hfi_packet.c
@@ -3,64 +3,108 @@
  * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
+#include "iris_common.h"
 #include "iris_core.h"
 #include "iris_helpers.h"
 #include "iris_hfi_packet.h"
 #include "hfi_defines.h"
 
-u32 get_hfi_port_from_buffer_type(enum iris_buffer_type buffer_type)
+u32 get_hfi_port_from_buffer_type(struct iris_inst *inst, enum iris_buffer_type buffer_type)
 {
 	u32 hfi_port = HFI_PORT_NONE;
 
-	switch (buffer_type) {
-	case BUF_INPUT:
-	case BUF_BIN:
-	case BUF_COMV:
-	case BUF_NON_COMV:
-	case BUF_LINE:
-		hfi_port = HFI_PORT_BITSTREAM;
-		break;
-	case BUF_OUTPUT:
-	case BUF_DPB:
-		hfi_port = HFI_PORT_RAW;
-		break;
-	case BUF_PERSIST:
-		hfi_port = HFI_PORT_NONE;
-		break;
-	default:
-		break;
+	if (inst->domain == DECODER) {
+		switch (buffer_type) {
+		case BUF_INPUT:
+		case BUF_BIN:
+		case BUF_COMV:
+		case BUF_NON_COMV:
+		case BUF_LINE:
+			hfi_port = HFI_PORT_BITSTREAM;
+			break;
+		case BUF_OUTPUT:
+		case BUF_DPB:
+			hfi_port = HFI_PORT_RAW;
+			break;
+		case BUF_PERSIST:
+			hfi_port = HFI_PORT_NONE;
+			break;
+		default:
+			break;
+		}
+	} else if (inst->domain == ENCODER) {
+		switch (buffer_type) {
+		case BUF_INPUT:
+		case BUF_VPSS:
+			hfi_port = HFI_PORT_RAW;
+			break;
+		case BUF_OUTPUT:
+		case BUF_BIN:
+		case BUF_COMV:
+		case BUF_NON_COMV:
+		case BUF_LINE:
+		case BUF_DPB:
+			hfi_port = HFI_PORT_BITSTREAM;
+			break;
+		case BUF_ARP:
+			hfi_port = HFI_PORT_NONE;
+			break;
+		default:
+			break;
+		}
 	}
 
 	return hfi_port;
 }
 
-u32 get_hfi_port(u32 plane)
+u32 get_hfi_port(struct iris_inst *inst, u32 plane)
 {
 	u32 hfi_port = HFI_PORT_NONE;
 
-	switch (plane) {
-	case INPUT_MPLANE:
-		hfi_port = HFI_PORT_BITSTREAM;
-		break;
-	case OUTPUT_MPLANE:
-		hfi_port = HFI_PORT_RAW;
-		break;
-	default:
-		break;
+	if (inst->domain == DECODER) {
+		switch (plane) {
+		case INPUT_MPLANE:
+			hfi_port = HFI_PORT_BITSTREAM;
+			break;
+		case OUTPUT_MPLANE:
+			hfi_port = HFI_PORT_RAW;
+			break;
+		default:
+			break;
+		}
+	} else if (inst->domain == ENCODER) {
+		switch (plane) {
+		case INPUT_MPLANE:
+			hfi_port = HFI_PORT_RAW;
+			break;
+		case OUTPUT_MPLANE:
+			hfi_port = HFI_PORT_BITSTREAM;
+			break;
+		default:
+			break;
+		}
 	}
 
 	return hfi_port;
 }
 
-static u32 hfi_buf_type_from_driver(enum iris_buffer_type buffer_type)
+static u32 hfi_buf_type_from_driver(enum domain_type domain, enum iris_buffer_type buffer_type)
 {
 	switch (buffer_type) {
 	case BUF_INPUT:
-		return HFI_BUFFER_BITSTREAM;
+		if (domain == DECODER)
+			return HFI_BUFFER_BITSTREAM;
+		else
+			return HFI_BUFFER_RAW;
 	case BUF_OUTPUT:
-		return HFI_BUFFER_RAW;
+		if (domain == DECODER)
+			return HFI_BUFFER_RAW;
+		else
+			return HFI_BUFFER_BITSTREAM;
 	case BUF_BIN:
 		return HFI_BUFFER_BIN;
+	case BUF_ARP:
+		return HFI_BUFFER_ARP;
 	case BUF_COMV:
 		return HFI_BUFFER_COMV;
 	case BUF_NON_COMV:
@@ -76,13 +120,19 @@ static u32 hfi_buf_type_from_driver(enum iris_buffer_type buffer_type)
 	}
 }
 
-u32 hfi_buf_type_to_driver(enum hfi_buffer_type buf_type)
+u32 hfi_buf_type_to_driver(enum domain_type domain, enum hfi_buffer_type buf_type)
 {
 	switch (buf_type) {
 	case HFI_BUFFER_BITSTREAM:
-		return BUF_INPUT;
+		if (domain == DECODER)
+			return BUF_INPUT;
+		else
+			return BUF_OUTPUT;
 	case HFI_BUFFER_RAW:
-		return BUF_OUTPUT;
+		if (domain == DECODER)
+			return BUF_OUTPUT;
+		else
+			return BUF_INPUT;
 	case HFI_BUFFER_BIN:
 		return BUF_BIN;
 	case HFI_BUFFER_ARP:
@@ -108,9 +158,15 @@ u32 get_hfi_codec(struct iris_inst *inst)
 {
 	switch (inst->codec) {
 	case H264:
-		return HFI_CODEC_DECODE_AVC;
+		if (inst->domain == ENCODER)
+			return HFI_CODEC_ENCODE_AVC;
+		else
+			return HFI_CODEC_DECODE_AVC;
 	case HEVC:
-		return HFI_CODEC_DECODE_HEVC;
+		if (inst->domain == ENCODER)
+			return HFI_CODEC_ENCODE_HEVC;
+		else
+			return HFI_CODEC_DECODE_HEVC;
 	case VP9:
 		return HFI_CODEC_DECODE_VP9;
 	default:
@@ -337,10 +393,11 @@ u32 get_v4l2_matrix_coefficients(u32 hfi_coefficients)
 	return coefficients;
 }
 
-int get_hfi_buffer(struct iris_buffer *buffer, struct hfi_buffer *buf)
+int get_hfi_buffer(struct iris_inst *inst,
+		   struct iris_buffer *buffer, struct hfi_buffer *buf)
 {
-	memset(buf, 0, sizeof(*buf));
-	buf->type = hfi_buf_type_from_driver(buffer->type);
+	memset(buf, 0, sizeof(struct hfi_buffer));
+	buf->type = hfi_buf_type_from_driver(inst->domain, buffer->type);
 	buf->index = buffer->index;
 	buf->base_address = buffer->device_addr;
 	buf->addr_offset = 0;
@@ -350,7 +407,7 @@ int get_hfi_buffer(struct iris_buffer *buffer, struct hfi_buffer *buf)
 	 * buffer size otherwise it will truncate or ignore the data after 256
 	 * aligned size which may lead to error concealment
 	 */
-	if (buffer->type == BUF_INPUT)
+	if (inst->domain == DECODER && buffer->type == BUF_INPUT)
 		buf->buffer_size = ALIGN(buffer->buffer_size, 256);
 	buf->data_offset = buffer->data_offset;
 	buf->data_size = buffer->data_size;
diff --git a/drivers/media/platform/qcom/vcodec/iris/iris_hfi_packet.h b/drivers/media/platform/qcom/vcodec/iris/iris_hfi_packet.h
index 82148b7..734a070 100644
--- a/drivers/media/platform/qcom/vcodec/iris/iris_hfi_packet.h
+++ b/drivers/media/platform/qcom/vcodec/iris/iris_hfi_packet.h
@@ -80,8 +80,8 @@ enum hfi_packet_port_type {
 	HFI_PORT_RAW		= 0x00000002,
 };
 
-u32 get_hfi_port_from_buffer_type(enum iris_buffer_type buffer_type);
-u32 get_hfi_port(u32 plane);
+u32 get_hfi_port_from_buffer_type(struct iris_inst *inst, enum iris_buffer_type buffer_type);
+u32 get_hfi_port(struct iris_inst *inst, u32 plane);
 u32 get_hfi_colorformat(u32 colorformat);
 u32 get_hfi_codec(struct iris_inst *inst);
 u32 get_hfi_color_primaries(u32 primaries);
@@ -90,8 +90,9 @@ u32 get_hfi_matrix_coefficients(u32 coefficients);
 u32 get_v4l2_color_primaries(u32 hfi_primaries);
 u32 get_v4l2_transfer_char(u32 hfi_characterstics);
 u32 get_v4l2_matrix_coefficients(u32 hfi_coefficients);
-u32 hfi_buf_type_to_driver(enum hfi_buffer_type buf_type);
-int get_hfi_buffer(struct iris_buffer *buffer, struct hfi_buffer *buf);
+u32 hfi_buf_type_to_driver(enum domain_type domain, enum hfi_buffer_type buf_type);
+int get_hfi_buffer(struct iris_inst *inst,
+		   struct iris_buffer *buffer, struct hfi_buffer *buf);
 
 int hfi_packet_sys_init(struct iris_core *core,
 			u8 *pkt, u32 pkt_size);
diff --git a/drivers/media/platform/qcom/vcodec/iris/iris_hfi_response.c b/drivers/media/platform/qcom/vcodec/iris/iris_hfi_response.c
index 1b667a5..08bdb8f 100644
--- a/drivers/media/platform/qcom/vcodec/iris/iris_hfi_response.c
+++ b/drivers/media/platform/qcom/vcodec/iris/iris_hfi_response.c
@@ -71,7 +71,8 @@ static bool is_valid_hfi_buffer_type(u32 buffer_type)
 static bool is_valid_hfi_port(u32 port, u32 buffer_type)
 {
 	if (port == HFI_PORT_NONE &&
-	    buffer_type != HFI_BUFFER_PERSIST)
+	    buffer_type != HFI_BUFFER_ARP &&
+		buffer_type != HFI_BUFFER_PERSIST)
 		return false;
 
 	if (port != HFI_PORT_BITSTREAM && port != HFI_PORT_RAW)
@@ -103,8 +104,9 @@ static int get_driver_buffer_flags(struct iris_inst *inst, u32 hfi_flags)
 	if (inst->hfi_frame_info.overflow)
 		driver_flags |= BUF_FLAG_ERROR;
 
-	if (hfi_flags & HFI_BUF_FW_FLAG_LAST ||
-	    hfi_flags & HFI_BUF_FW_FLAG_PSC_LAST)
+	if ((inst->domain == ENCODER && (hfi_flags & HFI_BUF_FW_FLAG_LAST)) ||
+	    (inst->domain == DECODER && (hfi_flags & HFI_BUF_FW_FLAG_LAST ||
+					 hfi_flags & HFI_BUF_FW_FLAG_PSC_LAST)))
 		driver_flags |= BUF_FLAG_LAST;
 
 	return driver_flags;
@@ -309,9 +311,12 @@ static int handle_session_close(struct iris_inst *inst,
 static int handle_read_only_buffer(struct iris_inst *inst,
 				   struct iris_buffer *buf)
 {
-	struct iris_buffer *ro_buf, *iter;
+	struct iris_buffer *ro_buf, *iter = NULL;
 	bool found = false;
 
+	if (inst->domain != DECODER && inst->domain != ENCODER)
+		return 0;
+
 	list_for_each_entry(iter, &inst->buffers.read_only.list, list) {
 		if (iter->device_addr == buf->device_addr) {
 			found = true;
@@ -344,6 +349,9 @@ static int handle_non_read_only_buffer(struct iris_inst *inst,
 {
 	struct iris_buffer *ro_buf;
 
+	if (inst->domain != DECODER && inst->domain != ENCODER)
+		return 0;
+
 	list_for_each_entry(ro_buf, &inst->buffers.read_only.list, list) {
 		if (ro_buf->device_addr == buffer->base_address) {
 			ro_buf->attr &= ~BUF_ATTR_READ_ONLY;
@@ -414,9 +422,9 @@ static int handle_input_buffer(struct iris_inst *inst,
 static int handle_output_buffer(struct iris_inst *inst,
 				struct hfi_buffer *hfi_buffer)
 {
-	struct iris_buffers *buffers;
 	struct iris_buffer *buf, *iter;
-	bool found;
+	struct iris_buffers *buffers;
+	bool found, fatal = false;
 	int ret = 0;
 
 	if (hfi_buffer->flags & HFI_BUF_FW_FLAG_LAST) {
@@ -425,17 +433,19 @@ static int handle_output_buffer(struct iris_inst *inst,
 			return ret;
 	}
 
-	if (hfi_buffer->flags & HFI_BUF_FW_FLAG_RELEASE_DONE)
-		return handle_release_output_buffer(inst, hfi_buffer);
+	if (inst->domain == DECODER) {
+		if (hfi_buffer->flags & HFI_BUF_FW_FLAG_RELEASE_DONE)
+			return handle_release_output_buffer(inst, hfi_buffer);
 
-	if (hfi_buffer->flags & HFI_BUF_FW_FLAG_PSC_LAST) {
-		ret = iris_inst_sub_state_change_drc_last(inst);
-		if (ret)
-			return ret;
-	}
+		if (hfi_buffer->flags & HFI_BUF_FW_FLAG_PSC_LAST) {
+			ret = iris_inst_sub_state_change_drc_last(inst);
+			if (ret)
+				return ret;
+		}
 
-	if (!(hfi_buffer->flags & HFI_BUF_FW_FLAG_READONLY))
-		ret = handle_non_read_only_buffer(inst, hfi_buffer);
+		if (!(hfi_buffer->flags & HFI_BUF_FW_FLAG_READONLY))
+			ret = handle_non_read_only_buffer(inst, hfi_buffer);
+	}
 
 	buffers = iris_get_buffer_list(inst, BUF_OUTPUT);
 	if (!buffers)
@@ -446,9 +456,12 @@ static int handle_output_buffer(struct iris_inst *inst,
 		if (!(iter->attr & BUF_ATTR_QUEUED))
 			continue;
 
-		found = (iter->index == hfi_buffer->index &&
-				iter->device_addr == hfi_buffer->base_address &&
-				iter->data_offset == hfi_buffer->data_offset);
+		if (inst->domain == DECODER)
+			found = (iter->index == hfi_buffer->index &&
+				 iter->device_addr == hfi_buffer->base_address &&
+				 iter->data_offset == hfi_buffer->data_offset);
+		else
+			found = iter->index == hfi_buffer->index;
 
 		if (found) {
 			buf = iter;
@@ -465,14 +478,27 @@ static int handle_output_buffer(struct iris_inst *inst,
 	buf->attr &= ~BUF_ATTR_QUEUED;
 	buf->attr |= BUF_ATTR_DEQUEUED;
 
-	if (inst->buffers.dpb.size && hfi_buffer->flags & HFI_BUF_FW_FLAG_READONLY)
-		iris_inst_change_state(inst, IRIS_INST_ERROR);
+	if (inst->domain == ENCODER) {
+		if (inst->hfi_frame_info.data_corrupt)
+			fatal = true;
+		if (inst->hfi_frame_info.overflow) {
+			if (!hfi_buffer->data_size && inst->hfi_rc_type == HFI_RC_CBR_CFR)
+				fatal = true;
+		}
+		if (fatal)
+			iris_inst_change_state(inst, IRIS_INST_ERROR);
+	}
+
+	if (inst->domain == DECODER) {
+		if (inst->buffers.dpb.size && hfi_buffer->flags & HFI_BUF_FW_FLAG_READONLY)
+			iris_inst_change_state(inst, IRIS_INST_ERROR);
 
-	if (hfi_buffer->flags & HFI_BUF_FW_FLAG_READONLY) {
-		buf->attr |= BUF_ATTR_READ_ONLY;
-		ret = handle_read_only_buffer(inst, buf);
-	} else {
-		buf->attr &= ~BUF_ATTR_READ_ONLY;
+		if (hfi_buffer->flags & HFI_BUF_FW_FLAG_READONLY) {
+			buf->attr |= BUF_ATTR_READ_ONLY;
+			ret = handle_read_only_buffer(inst, buf);
+		} else {
+			buf->attr &= ~BUF_ATTR_READ_ONLY;
+		}
 	}
 
 	buf->flags = get_driver_buffer_flags(inst, hfi_buffer->flags);
@@ -521,7 +547,7 @@ static int handle_release_internal_buffer(struct iris_inst *inst,
 	int ret = 0;
 	bool found;
 
-	buffers = iris_get_buffer_list(inst, hfi_buf_type_to_driver(buffer->type));
+	buffers = iris_get_buffer_list(inst, hfi_buf_type_to_driver(inst->domain, buffer->type));
 	if (!buffers)
 		return -EINVAL;
 
@@ -550,12 +576,22 @@ static int handle_session_stop(struct iris_inst *inst,
 	int ret = 0;
 	enum signal_session_response signal_type = -1;
 
-	if (pkt->port == HFI_PORT_RAW) {
-		signal_type = SIGNAL_CMD_STOP_OUTPUT;
-		ret = iris_inst_sub_state_change_pause(inst, OUTPUT_MPLANE);
-	} else if (pkt->port == HFI_PORT_BITSTREAM) {
-		signal_type = SIGNAL_CMD_STOP_INPUT;
-		ret = iris_inst_sub_state_change_pause(inst, INPUT_MPLANE);
+	if (inst->domain == DECODER) {
+		if (pkt->port == HFI_PORT_RAW) {
+			signal_type = SIGNAL_CMD_STOP_OUTPUT;
+			ret = iris_inst_sub_state_change_pause(inst, OUTPUT_MPLANE);
+		} else if (pkt->port == HFI_PORT_BITSTREAM) {
+			signal_type = SIGNAL_CMD_STOP_INPUT;
+			ret = iris_inst_sub_state_change_pause(inst, INPUT_MPLANE);
+		}
+	} else if (inst->domain == ENCODER) {
+		if (pkt->port == HFI_PORT_RAW) {
+			signal_type = SIGNAL_CMD_STOP_INPUT;
+			ret = iris_inst_sub_state_change_pause(inst, INPUT_MPLANE);
+		} else if (pkt->port == HFI_PORT_BITSTREAM) {
+			signal_type = SIGNAL_CMD_STOP_OUTPUT;
+			ret = iris_inst_sub_state_change_pause(inst, OUTPUT_MPLANE);
+		}
 	}
 
 	if (signal_type != -1)
@@ -571,7 +607,7 @@ static int handle_session_buffer(struct iris_inst *inst,
 	u32 hfi_handle_size = 0;
 	int i, ret = 0;
 	const struct iris_hfi_buffer_handle *hfi_handle_arr = NULL;
-	static const struct iris_hfi_buffer_handle input_hfi_handle[] = {
+	static const struct iris_hfi_buffer_handle dec_input_hfi_handle[] = {
 		{HFI_BUFFER_BITSTREAM,      handle_input_buffer               },
 		{HFI_BUFFER_BIN,            handle_release_internal_buffer    },
 		{HFI_BUFFER_COMV,           handle_release_internal_buffer    },
@@ -579,10 +615,24 @@ static int handle_session_buffer(struct iris_inst *inst,
 		{HFI_BUFFER_LINE,           handle_release_internal_buffer    },
 		{HFI_BUFFER_PERSIST,        handle_release_internal_buffer    },
 	};
-	static const struct iris_hfi_buffer_handle output_hfi_handle[] = {
+	static const struct iris_hfi_buffer_handle dec_output_hfi_handle[] = {
 		{HFI_BUFFER_RAW,            handle_output_buffer              },
 		{HFI_BUFFER_DPB,            handle_release_internal_buffer    },
 	};
+	static const struct iris_hfi_buffer_handle enc_input_hfi_handle[] = {
+		{HFI_BUFFER_RAW,            handle_input_buffer               },
+		{HFI_BUFFER_VPSS,           handle_release_internal_buffer    },
+	};
+	static const struct iris_hfi_buffer_handle enc_output_hfi_handle[] = {
+		{HFI_BUFFER_BITSTREAM,      handle_output_buffer              },
+		{HFI_BUFFER_BIN,            handle_release_internal_buffer    },
+		{HFI_BUFFER_COMV,           handle_release_internal_buffer    },
+		{HFI_BUFFER_NON_COMV,       handle_release_internal_buffer    },
+		{HFI_BUFFER_LINE,           handle_release_internal_buffer    },
+		{HFI_BUFFER_ARP,            handle_release_internal_buffer    },
+		{HFI_BUFFER_DPB,            handle_release_internal_buffer    },
+	};
+
 
 	if (pkt->payload_info == HFI_PAYLOAD_NONE)
 		return 0;
@@ -599,12 +649,22 @@ static int handle_session_buffer(struct iris_inst *inst,
 	if (!is_valid_hfi_port(pkt->port, buffer->type))
 		return 0;
 
-	if (pkt->port == HFI_PORT_BITSTREAM) {
-		hfi_handle_size = ARRAY_SIZE(input_hfi_handle);
-		hfi_handle_arr = input_hfi_handle;
-	} else if (pkt->port == HFI_PORT_RAW) {
-		hfi_handle_size = ARRAY_SIZE(output_hfi_handle);
-		hfi_handle_arr = output_hfi_handle;
+	if (inst->domain == DECODER) {
+		if (pkt->port == HFI_PORT_BITSTREAM) {
+			hfi_handle_size = ARRAY_SIZE(dec_input_hfi_handle);
+			hfi_handle_arr = dec_input_hfi_handle;
+		} else if (pkt->port == HFI_PORT_RAW) {
+			hfi_handle_size = ARRAY_SIZE(dec_output_hfi_handle);
+			hfi_handle_arr = dec_output_hfi_handle;
+		}
+	} else if (inst->domain == ENCODER) {
+		if (pkt->port == HFI_PORT_RAW) {
+			hfi_handle_size = ARRAY_SIZE(enc_input_hfi_handle);
+			hfi_handle_arr = enc_input_hfi_handle;
+		} else if (pkt->port == HFI_PORT_BITSTREAM) {
+			hfi_handle_size = ARRAY_SIZE(enc_output_hfi_handle);
+			hfi_handle_arr = enc_output_hfi_handle;
+		}
 	}
 
 	if (!hfi_handle_arr || !hfi_handle_size)
@@ -693,6 +753,9 @@ static int handle_dpb_list_property(struct iris_inst *inst,
 	u8 *payload_start;
 	u32 payload_size;
 
+	if (inst->domain != DECODER)
+		return -EINVAL;
+
 	payload_size = pkt->size - sizeof(*pkt);
 	payload_start = (u8 *)((u8 *)pkt + sizeof(*pkt));
 	memset(inst->dpb_list_payload, 0, MAX_DPB_LIST_ARRAY_SIZE);
diff --git a/drivers/media/platform/qcom/vcodec/iris/iris_vb2.c b/drivers/media/platform/qcom/vcodec/iris/iris_vb2.c
index c0878f1..1a434ff 100644
--- a/drivers/media/platform/qcom/vcodec/iris/iris_vb2.c
+++ b/drivers/media/platform/qcom/vcodec/iris/iris_vb2.c
@@ -13,6 +13,7 @@
 #include "iris_power.h"
 #include "iris_vb2.h"
 #include "iris_vdec.h"
+#include "iris_venc.h"
 
 int iris_vb2_queue_setup(struct vb2_queue *q,
 			 unsigned int *num_buffers, unsigned int *num_planes,
@@ -58,7 +59,8 @@ int iris_vb2_queue_setup(struct vb2_queue *q,
 			return ret;
 	}
 
-	if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+	if ((inst->domain == DECODER && q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ||
+	    (inst->domain == ENCODER && q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)) {
 		ret = adjust_v4l2_properties(inst);
 		if (ret)
 			return ret;
@@ -112,6 +114,11 @@ int iris_vb2_start_streaming(struct vb2_queue *q, unsigned int count)
 		goto error;
 	}
 
+	if (inst->domain != DECODER && inst->domain != ENCODER) {
+		ret = -EINVAL;
+		goto error;
+	}
+
 	ret = iris_pm_get(inst->core);
 	if (ret)
 		goto error;
@@ -122,21 +129,34 @@ int iris_vb2_start_streaming(struct vb2_queue *q, unsigned int count)
 		if (ret)
 			goto err_pm_get;
 
-		ret = iris_hfi_session_set_default_header(inst);
-		if (ret)
-			goto err_pm_get;
-
-		ret = iris_alloc_and_queue_session_int_bufs(inst, BUF_PERSIST);
-		if (ret)
-			goto err_pm_get;
+		if (inst->domain == ENCODER)  {
+			ret = iris_alloc_and_queue_session_int_bufs(inst, BUF_ARP);
+			if (ret)
+				goto err_pm_get;
+		} else if (inst->domain == DECODER) {
+			ret = iris_hfi_session_set_default_header(inst);
+			if (ret)
+				goto err_pm_get;
+
+			ret = iris_alloc_and_queue_session_int_bufs(inst, BUF_PERSIST);
+			if (ret)
+				goto err_pm_get;
+		}
 	}
 
 	iris_scale_power(inst);
 
-	if (q->type == INPUT_MPLANE)
-		ret = vdec_streamon_input(inst);
-	else if (q->type == OUTPUT_MPLANE)
-		ret = vdec_streamon_output(inst);
+	if (q->type == INPUT_MPLANE) {
+		if (inst->domain == DECODER)
+			ret = vdec_streamon_input(inst);
+		else if (inst->domain == ENCODER)
+			ret = venc_streamon_input(inst);
+	} else if (q->type == OUTPUT_MPLANE) {
+		if (inst->domain == DECODER)
+			ret = vdec_streamon_output(inst);
+		else if (inst->domain == ENCODER)
+			ret = venc_streamon_output(inst);
+	}
 	if (ret)
 		goto err_pm_get;
 
@@ -179,6 +199,11 @@ void iris_vb2_stop_streaming(struct vb2_queue *q)
 	if (q->type != INPUT_MPLANE && q->type != OUTPUT_MPLANE)
 		goto error;
 
+	if (inst->domain != DECODER && inst->domain != ENCODER) {
+		ret = -EINVAL;
+		goto error;
+	}
+
 	ret = iris_pm_get_put(inst->core);
 	if (ret)
 		goto error;
@@ -225,7 +250,10 @@ void iris_vb2_buf_queue(struct vb2_buffer *vb2)
 	if (ret)
 		goto exit;
 
-	ret = vdec_qbuf(inst, vb2);
+	if (inst->domain == DECODER)
+		ret = vdec_qbuf(inst, vb2);
+	else if (inst->domain == ENCODER)
+		ret = venc_qbuf(inst, vb2);
 
 exit:
 	if (ret) {
@@ -270,7 +298,7 @@ void *iris_vb2_attach_dmabuf(struct vb2_buffer *vb, struct device *dev,
 	buf->inst = inst;
 	buf->dmabuf = dbuf;
 
-	if (buf->type == BUF_OUTPUT) {
+	if (inst->domain == DECODER && buf->type == BUF_OUTPUT) {
 		list_for_each_entry_safe(ro_buf, dummy, &inst->buffers.read_only.list, list) {
 			if (ro_buf->dmabuf != buf->dmabuf)
 				continue;
@@ -307,7 +335,7 @@ int iris_vb2_map_dmabuf(void *buf_priv)
 		return -EINVAL;
 	}
 
-	if (buf->type == BUF_OUTPUT) {
+	if (inst->domain == DECODER && buf->type == BUF_OUTPUT) {
 		list_for_each_entry_safe(ro_buf, dummy, &inst->buffers.read_only.list, list) {
 			if (ro_buf->dmabuf != buf->dmabuf)
 				continue;
@@ -356,7 +384,7 @@ void iris_vb2_unmap_dmabuf(void *buf_priv)
 		return;
 	}
 
-	if (buf->type == BUF_OUTPUT) {
+	if (inst->domain == DECODER && buf->type == BUF_OUTPUT) {
 		list_for_each_entry_safe(ro_buf, dummy, &inst->buffers.read_only.list, list) {
 			if (ro_buf->dmabuf != buf->dmabuf)
 				continue;
@@ -393,7 +421,7 @@ void iris_vb2_detach_dmabuf(void *buf_priv)
 		buf->sg_table = NULL;
 	}
 
-	if (buf->type == BUF_OUTPUT) {
+	if (inst->domain == DECODER && buf->type == BUF_OUTPUT) {
 		list_for_each_entry_safe(ro_buf, dummy, &inst->buffers.read_only.list, list) {
 			if (ro_buf->dmabuf != buf->dmabuf)
 				continue;
diff --git a/drivers/media/platform/qcom/vcodec/iris/iris_vdec.c b/drivers/media/platform/qcom/vcodec/iris/iris_vdec.c
index 300d0e9..b2d4739 100644
--- a/drivers/media/platform/qcom/vcodec/iris/iris_vdec.c
+++ b/drivers/media/platform/qcom/vcodec/iris/iris_vdec.c
@@ -362,7 +362,7 @@ static int vdec_set_bitstream_resolution(struct iris_inst *inst)
 	return iris_hfi_set_property(inst,
 					HFI_PROP_BITSTREAM_RESOLUTION,
 					HFI_HOST_FLAGS_NONE,
-					get_hfi_port(INPUT_MPLANE),
+					get_hfi_port(inst, INPUT_MPLANE),
 					HFI_PAYLOAD_U32,
 					&resolution,
 					sizeof(u32));
@@ -388,7 +388,7 @@ static int vdec_set_crop_offsets(struct iris_inst *inst)
 	return iris_hfi_set_property(inst,
 					HFI_PROP_CROP_OFFSETS,
 					HFI_HOST_FLAGS_NONE,
-					get_hfi_port(INPUT_MPLANE),
+					get_hfi_port(inst, INPUT_MPLANE),
 					HFI_PAYLOAD_64_PACKED,
 					&payload,
 					sizeof(u64));
@@ -409,7 +409,7 @@ static int vdec_set_bit_depth(struct iris_inst *inst)
 	return iris_hfi_set_property(inst,
 					HFI_PROP_LUMA_CHROMA_BIT_DEPTH,
 					HFI_HOST_FLAGS_NONE,
-					get_hfi_port(INPUT_MPLANE),
+					get_hfi_port(inst, INPUT_MPLANE),
 					HFI_PAYLOAD_U32,
 					&bitdepth,
 					sizeof(u32));
@@ -426,7 +426,7 @@ static int vdec_set_coded_frames(struct iris_inst *inst)
 	return iris_hfi_set_property(inst,
 					HFI_PROP_CODED_FRAMES,
 					HFI_HOST_FLAGS_NONE,
-					get_hfi_port(INPUT_MPLANE),
+					get_hfi_port(inst, INPUT_MPLANE),
 					HFI_PAYLOAD_U32,
 					&coded_frames,
 					sizeof(u32));
@@ -442,7 +442,7 @@ static int vdec_set_min_output_count(struct iris_inst *inst)
 	return iris_hfi_set_property(inst,
 					HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT,
 					HFI_HOST_FLAGS_NONE,
-					get_hfi_port(INPUT_MPLANE),
+					get_hfi_port(inst, INPUT_MPLANE),
 					HFI_PAYLOAD_U32,
 					&min_output,
 					sizeof(u32));
@@ -457,7 +457,7 @@ static int vdec_set_picture_order_count(struct iris_inst *inst)
 	return iris_hfi_set_property(inst,
 					HFI_PROP_PIC_ORDER_CNT_TYPE,
 					HFI_HOST_FLAGS_NONE,
-					get_hfi_port(INPUT_MPLANE),
+					get_hfi_port(inst, INPUT_MPLANE),
 					HFI_PAYLOAD_U32,
 					&poc,
 					sizeof(u32));
@@ -509,7 +509,7 @@ static int vdec_set_colorspace(struct iris_inst *inst)
 	ret = iris_hfi_set_property(inst,
 				    HFI_PROP_SIGNAL_COLOR_INFO,
 				    HFI_HOST_FLAGS_NONE,
-				    get_hfi_port(INPUT_MPLANE),
+				    get_hfi_port(inst, INPUT_MPLANE),
 				    HFI_PAYLOAD_32_PACKED,
 				    &color_info,
 				    sizeof(u32));
@@ -527,7 +527,7 @@ static int vdec_set_profile(struct iris_inst *inst)
 	return iris_hfi_set_property(inst,
 				     HFI_PROP_PROFILE,
 				     HFI_HOST_FLAGS_NONE,
-				     get_hfi_port(INPUT_MPLANE),
+				     get_hfi_port(inst, INPUT_MPLANE),
 				     HFI_PAYLOAD_U32_ENUM,
 				     &profile,
 				     sizeof(u32));
@@ -543,7 +543,7 @@ static int vdec_set_level(struct iris_inst *inst)
 	return iris_hfi_set_property(inst,
 				     HFI_PROP_LEVEL,
 				     HFI_HOST_FLAGS_NONE,
-				     get_hfi_port(INPUT_MPLANE),
+				     get_hfi_port(inst, INPUT_MPLANE),
 				     HFI_PAYLOAD_U32_ENUM,
 				     &level,
 				     sizeof(u32));
@@ -559,7 +559,7 @@ static int vdec_set_tier(struct iris_inst *inst)
 	return iris_hfi_set_property(inst,
 				     HFI_PROP_TIER,
 				     HFI_HOST_FLAGS_NONE,
-				     get_hfi_port(INPUT_MPLANE),
+				     get_hfi_port(inst, INPUT_MPLANE),
 				     HFI_PAYLOAD_U32_ENUM,
 				     &tier,
 				     sizeof(u32));
@@ -811,7 +811,7 @@ static int vdec_set_colorformat(struct iris_inst *inst)
 	return iris_hfi_set_property(inst,
 					 HFI_PROP_COLOR_FORMAT,
 					 HFI_HOST_FLAGS_NONE,
-					 get_hfi_port(OUTPUT_MPLANE),
+					 get_hfi_port(inst, OUTPUT_MPLANE),
 					 HFI_PAYLOAD_U32,
 					 &hfi_colorformat,
 					 sizeof(u32));
@@ -839,7 +839,7 @@ static int vdec_set_linear_stride_scanline(struct iris_inst *inst)
 	return iris_hfi_set_property(inst,
 					 HFI_PROP_LINEAR_STRIDE_SCANLINE,
 					 HFI_HOST_FLAGS_NONE,
-					 get_hfi_port(OUTPUT_MPLANE),
+					 get_hfi_port(inst, OUTPUT_MPLANE),
 					 HFI_PAYLOAD_U64,
 					 &payload,
 					 sizeof(u64));
@@ -887,7 +887,7 @@ static int vdec_set_ubwc_stride_scanline(struct iris_inst *inst)
 	return iris_hfi_set_property(inst,
 				     HFI_PROP_UBWC_STRIDE_SCANLINE,
 				     HFI_HOST_FLAGS_NONE,
-				     get_hfi_port(OUTPUT_MPLANE),
+				     get_hfi_port(inst, OUTPUT_MPLANE),
 				     HFI_PAYLOAD_U32_ARRAY,
 				     &payload[0],
 				     sizeof(u32) * 4);
@@ -1020,7 +1020,7 @@ static int vdec_subscribe_dst_change_param(struct iris_inst *inst)
 			ret = iris_hfi_set_property(inst,
 						    prop_type,
 						    HFI_HOST_FLAGS_NONE,
-						    get_hfi_port(OUTPUT_MPLANE),
+						    get_hfi_port(inst, OUTPUT_MPLANE),
 						    payload_type,
 						    &payload,
 						    payload_size);
@@ -1032,42 +1032,6 @@ static int vdec_subscribe_dst_change_param(struct iris_inst *inst)
 	return ret;
 }
 
-static int process_streamon_input(struct iris_inst *inst)
-{
-	enum iris_inst_sub_state set_sub_state = IRIS_INST_SUB_NONE;
-	int ret;
-
-	iris_scale_power(inst);
-
-	ret = iris_hfi_start(inst, INPUT_MPLANE);
-	if (ret)
-		return ret;
-
-	if (inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) {
-		ret = iris_inst_change_sub_state(inst, IRIS_INST_SUB_INPUT_PAUSE, 0);
-		if (ret)
-			return ret;
-	}
-
-	if (inst->sub_state & IRIS_INST_SUB_DRC ||
-	    inst->sub_state & IRIS_INST_SUB_DRAIN) {
-		if (!(inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE)) {
-			ret = iris_hfi_pause(inst, INPUT_MPLANE);
-			if (ret)
-				return ret;
-			set_sub_state = IRIS_INST_SUB_INPUT_PAUSE;
-		}
-	}
-
-	ret = iris_inst_state_change_streamon(inst, INPUT_MPLANE);
-	if (ret)
-		return ret;
-
-	ret = iris_inst_change_sub_state(inst, 0, set_sub_state);
-
-	return ret;
-}
-
 int vdec_streamon_input(struct iris_inst *inst)
 {
 	int ret;
@@ -1114,58 +1078,6 @@ int vdec_streamon_input(struct iris_inst *inst)
 	return ret;
 }
 
-static int process_streamon_output(struct iris_inst *inst)
-{
-	enum iris_inst_sub_state clear_sub_state = IRIS_INST_SUB_NONE;
-	bool drain_pending = false;
-	int ret;
-
-	iris_scale_power(inst);
-
-	if (inst->sub_state & IRIS_INST_SUB_DRC &&
-	    inst->sub_state & IRIS_INST_SUB_DRC_LAST)
-		clear_sub_state = IRIS_INST_SUB_DRC | IRIS_INST_SUB_DRC_LAST;
-
-	if (inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) {
-		ret = iris_alloc_and_queue_input_int_bufs(inst);
-		if (ret)
-			return ret;
-		ret = set_stage(inst, STAGE);
-		if (ret)
-			return ret;
-		ret = set_pipe(inst, PIPE);
-		if (ret)
-			return ret;
-	}
-
-	drain_pending = inst->sub_state & IRIS_INST_SUB_DRAIN &&
-		inst->sub_state & IRIS_INST_SUB_DRAIN_LAST;
-
-	if (!drain_pending && inst->state == IRIS_INST_INPUT_STREAMING) {
-		if (inst->sub_state & IRIS_INST_SUB_INPUT_PAUSE) {
-			ret = iris_hfi_resume(inst, INPUT_MPLANE, HFI_CMD_SETTINGS_CHANGE);
-			if (ret)
-				return ret;
-			clear_sub_state |= IRIS_INST_SUB_INPUT_PAUSE;
-		}
-	}
-
-	ret = iris_hfi_start(inst, OUTPUT_MPLANE);
-	if (ret)
-		return ret;
-
-	if (inst->sub_state & IRIS_INST_SUB_OUTPUT_PAUSE)
-		clear_sub_state |= IRIS_INST_SUB_OUTPUT_PAUSE;
-
-	ret = iris_inst_state_change_streamon(inst, OUTPUT_MPLANE);
-	if (ret)
-		return ret;
-
-	ret = iris_inst_change_sub_state(inst, clear_sub_state, 0);
-
-	return ret;
-}
-
 int vdec_streamon_output(struct iris_inst *inst)
 {
 	int ret;
@@ -1220,27 +1132,6 @@ int vdec_streamon_output(struct iris_inst *inst)
 	return ret;
 }
 
-static int vb2_buffer_to_driver(struct vb2_buffer *vb2,
-				struct iris_buffer *buf)
-{
-	struct vb2_v4l2_buffer *vbuf;
-
-	if (!vb2 || !buf)
-		return -EINVAL;
-
-	vbuf = to_vb2_v4l2_buffer(vb2);
-
-	buf->fd = vb2->planes[0].m.fd;
-	buf->data_offset = vb2->planes[0].data_offset;
-	buf->data_size = vb2->planes[0].bytesused - vb2->planes[0].data_offset;
-	buf->buffer_size = vb2->planes[0].length;
-	buf->timestamp = vb2->timestamp;
-	buf->flags = vbuf->flags;
-	buf->attr = 0;
-
-	return 0;
-}
-
 int vdec_qbuf(struct iris_inst *inst, struct vb2_buffer *vb2)
 {
 	struct iris_buffer *buf = NULL;
diff --git a/drivers/media/platform/qcom/vcodec/iris/iris_venc.c b/drivers/media/platform/qcom/vcodec/iris/iris_venc.c
index 802db40..28c6b20 100644
--- a/drivers/media/platform/qcom/vcodec/iris/iris_venc.c
+++ b/drivers/media/platform/qcom/vcodec/iris/iris_venc.c
@@ -13,6 +13,23 @@
 #include "iris_power.h"
 #include "iris_venc.h"
 
+#define SCALE_FACTOR 8
+#define UNSPECIFIED_COLOR_FORMAT 5
+
+static const u32 enc_input_properties[] = {
+	HFI_PROP_NO_OUTPUT,
+};
+
+static const u32 enc_output_properties[] = {
+	HFI_PROP_PICTURE_TYPE,
+	HFI_PROP_BUFFER_MARK,
+};
+
+struct venc_prop_type_handle {
+	u32 type;
+	int (*handle)(struct iris_inst *inst);
+};
+
 int venc_inst_init(struct iris_inst *inst)
 {
 	struct v4l2_format *f;
@@ -523,3 +540,409 @@ int venc_stop_cmd(struct iris_inst *inst)
 
 	return ret;
 }
+
+int venc_qbuf(struct iris_inst *inst, struct vb2_buffer *vb2)
+{
+	struct iris_buffer *buf = NULL;
+	int ret;
+
+	buf = get_driver_buf(inst, vb2->type, vb2->index);
+	if (!buf)
+		return -EINVAL;
+
+	ret = vb2_buffer_to_driver(vb2, buf);
+	if (ret)
+		return ret;
+
+	if (!allow_qbuf(inst, vb2->type)) {
+		buf->attr |= BUF_ATTR_DEFERRED;
+		return 0;
+	}
+
+	iris_scale_power(inst);
+
+	return queue_buffer(inst, buf);
+}
+
+static int check_scaling_supported(struct iris_inst *inst)
+{
+	u32 iwidth, owidth, iheight, oheight;
+
+	if (!(inst->crop.left != inst->compose.left ||
+	      inst->crop.top != inst->compose.top ||
+	      inst->crop.width != inst->compose.width ||
+	      inst->crop.height != inst->compose.height))
+		return 0;
+
+	iwidth = inst->crop.width;
+	iheight = inst->crop.height;
+	owidth = inst->compose.width;
+	oheight = inst->compose.height;
+
+	if (owidth > iwidth || oheight > iheight)
+		return -EINVAL;
+
+	if (iwidth > owidth * SCALE_FACTOR || iheight > oheight * SCALE_FACTOR)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int venc_set_colorformat(struct iris_inst *inst)
+{
+	u32 hfi_colorformat;
+	u32 pixelformat;
+
+	pixelformat = inst->fmt_src->fmt.pix_mp.pixelformat;
+	hfi_colorformat = get_hfi_colorformat(pixelformat);
+
+	return iris_hfi_set_property(inst,
+				     HFI_PROP_COLOR_FORMAT,
+				     HFI_HOST_FLAGS_NONE,
+				     get_hfi_port(inst, INPUT_MPLANE),
+				     HFI_PAYLOAD_U32_ENUM,
+				     &hfi_colorformat,
+				     sizeof(u32));
+}
+
+static int venc_set_stride_scanline(struct iris_inst *inst)
+{
+	u32 color_format, stride_y, scanline_y;
+	u32 stride_uv = 0, scanline_uv = 0;
+	u32 payload[2];
+
+	color_format = inst->cap[PIX_FMTS].value;
+	if (!is_linear_colorformat(color_format))
+		return 0;
+
+	stride_y = color_format == FMT_TP10C ?
+		ALIGN(inst->fmt_src->fmt.pix_mp.width, 192) :
+		ALIGN(inst->fmt_src->fmt.pix_mp.width, 128);
+	scanline_y = color_format == FMT_TP10C ?
+		ALIGN(inst->fmt_src->fmt.pix_mp.height, 16) :
+		ALIGN(inst->fmt_src->fmt.pix_mp.height, 32);
+
+	if (color_format == FMT_NV12 ||
+	    color_format == FMT_NV21) {
+		stride_uv = stride_y;
+		scanline_uv = scanline_y / 2;
+	}
+
+	payload[0] = stride_y << 16 | scanline_y;
+	payload[1] = stride_uv << 16 | scanline_uv;
+
+	return iris_hfi_set_property(inst,
+				     HFI_PROP_LINEAR_STRIDE_SCANLINE,
+				     HFI_HOST_FLAGS_NONE,
+				     get_hfi_port(inst, INPUT_MPLANE),
+				     HFI_PAYLOAD_64_PACKED,
+				     &payload,
+				     sizeof(u64));
+}
+
+static int venc_set_raw_resolution(struct iris_inst *inst)
+{
+	u32 resolution;
+
+	resolution = (inst->fmt_src->fmt.pix_mp.width << 16) |
+		inst->fmt_src->fmt.pix_mp.height;
+
+	return iris_hfi_set_property(inst,
+				     HFI_PROP_RAW_RESOLUTION,
+				     HFI_HOST_FLAGS_NONE,
+				     get_hfi_port(inst, INPUT_MPLANE),
+				     HFI_PAYLOAD_32_PACKED,
+				     &resolution,
+				     sizeof(u32));
+}
+
+static int venc_set_bitstream_resolution(struct iris_inst *inst)
+{
+	u32 resolution;
+
+	resolution = (inst->fmt_dst->fmt.pix_mp.width << 16) |
+		inst->fmt_dst->fmt.pix_mp.height;
+
+	return iris_hfi_set_property(inst,
+				     HFI_PROP_BITSTREAM_RESOLUTION,
+				     HFI_HOST_FLAGS_NONE,
+				     get_hfi_port(inst, OUTPUT_MPLANE),
+				     HFI_PAYLOAD_32_PACKED,
+				     &resolution,
+				     sizeof(u32));
+}
+
+static int venc_set_inp_crop_offsets(struct iris_inst *inst)
+{
+	u32 left_offset, top_offset, right_offset, bottom_offset;
+	u32 crop[2] = {0};
+	u32 width, height;
+
+	left_offset = inst->crop.left;
+	top_offset = inst->crop.top;
+	width = inst->crop.width;
+	height = inst->crop.height;
+
+	right_offset = (inst->fmt_src->fmt.pix_mp.width - width);
+	bottom_offset = (inst->fmt_src->fmt.pix_mp.height - height);
+
+	crop[0] = left_offset << 16 | top_offset;
+	crop[1] = right_offset << 16 | bottom_offset;
+
+	return iris_hfi_set_property(inst,
+				     HFI_PROP_CROP_OFFSETS,
+				     HFI_HOST_FLAGS_NONE,
+				     get_hfi_port(inst, INPUT_MPLANE),
+				     HFI_PAYLOAD_64_PACKED,
+				     &crop,
+				     sizeof(u64));
+}
+
+static int venc_set_out_crop_offsets(struct iris_inst *inst)
+{
+	u32 left_offset, top_offset, right_offset, bottom_offset;
+	u32 crop[2] = {0};
+	u32 width, height;
+
+	left_offset = inst->compose.left;
+	top_offset = inst->compose.top;
+	width = inst->compose.width;
+	height = inst->compose.height;
+	if (inst->cap[ROTATION].value == 90 || inst->cap[ROTATION].value == 270) {
+		width = inst->compose.height;
+		height = inst->compose.width;
+	}
+
+	right_offset = (inst->fmt_dst->fmt.pix_mp.width - width);
+	bottom_offset = (inst->fmt_dst->fmt.pix_mp.height - height);
+
+	crop[0] = left_offset << 16 | top_offset;
+	crop[1] = right_offset << 16 | bottom_offset;
+
+	return iris_hfi_set_property(inst,
+				     HFI_PROP_CROP_OFFSETS,
+				     HFI_HOST_FLAGS_NONE,
+				     get_hfi_port(inst, OUTPUT_MPLANE),
+				     HFI_PAYLOAD_64_PACKED,
+				     &crop,
+				     sizeof(u64));
+}
+
+static int venc_set_colorspace(struct iris_inst *inst)
+{
+	u32 video_signal_type_present_flag = 0, payload = 0;
+	u32 matrix_coeff = HFI_MATRIX_COEFF_RESERVED;
+	u32 video_format = UNSPECIFIED_COLOR_FORMAT;
+	struct v4l2_pix_format_mplane *pixmp = NULL;
+	u32 transfer_char = HFI_TRANSFER_RESERVED;
+	u32 colour_description_present_flag = 0;
+	u32 primaries = HFI_PRIMARIES_RESERVED;
+	u32 full_range = 0;
+
+	pixmp = &inst->fmt_src->fmt.pix_mp;
+	if (pixmp->colorspace != V4L2_COLORSPACE_DEFAULT ||
+	    pixmp->ycbcr_enc != V4L2_YCBCR_ENC_DEFAULT ||
+	    pixmp->xfer_func != V4L2_XFER_FUNC_DEFAULT) {
+		colour_description_present_flag = 1;
+		video_signal_type_present_flag = 1;
+		primaries = get_hfi_color_primaries(pixmp->colorspace);
+		matrix_coeff = get_hfi_matrix_coefficients(pixmp->ycbcr_enc);
+		transfer_char = get_hfi_transfer_char(pixmp->xfer_func);
+	}
+
+	if (pixmp->quantization != V4L2_QUANTIZATION_DEFAULT) {
+		video_signal_type_present_flag = 1;
+		full_range = pixmp->quantization ==
+			V4L2_QUANTIZATION_FULL_RANGE ? 1 : 0;
+	}
+
+	payload = (matrix_coeff & 0xFF) |
+		((transfer_char << 8) & 0xFF00) |
+		((primaries << 16) & 0xFF0000) |
+		((colour_description_present_flag << 24) & 0x1000000) |
+		((full_range << 25) & 0x2000000) |
+		((video_format << 26) & 0x1C000000) |
+		((video_signal_type_present_flag << 29) & 0x20000000);
+
+	return iris_hfi_set_property(inst,
+				     HFI_PROP_SIGNAL_COLOR_INFO,
+				     HFI_HOST_FLAGS_NONE,
+				     get_hfi_port(inst, INPUT_MPLANE),
+				     HFI_PAYLOAD_32_PACKED,
+				     &payload,
+				     sizeof(u32));
+}
+
+static int venc_set_quality_mode(struct iris_inst *inst)
+{
+	u32 mode;
+
+	mode = decide_quality_mode(inst);
+	return iris_hfi_set_property(inst,
+				     HFI_PROP_QUALITY_MODE,
+				     HFI_HOST_FLAGS_NONE,
+				     HFI_PORT_BITSTREAM,
+				     HFI_PAYLOAD_U32_ENUM,
+				     &mode,
+				     sizeof(u32));
+}
+
+static int venc_set_input_properties(struct iris_inst *inst)
+{
+	int j, ret;
+	static const struct venc_prop_type_handle prop_type_handle_arr[] = {
+		{HFI_PROP_COLOR_FORMAT,               venc_set_colorformat                 },
+		{HFI_PROP_RAW_RESOLUTION,             venc_set_raw_resolution              },
+		{HFI_PROP_CROP_OFFSETS,               venc_set_inp_crop_offsets            },
+		{HFI_PROP_LINEAR_STRIDE_SCANLINE,     venc_set_stride_scanline             },
+		{HFI_PROP_SIGNAL_COLOR_INFO,          venc_set_colorspace                  },
+	};
+
+	for (j = 0; j < ARRAY_SIZE(prop_type_handle_arr); j++) {
+		ret = prop_type_handle_arr[j].handle(inst);
+		if (ret)
+			return ret;
+	}
+
+	return ret;
+}
+
+static int venc_property_subscription(struct iris_inst *inst, u32 plane)
+{
+	u32 payload[32] = {0};
+	u32 payload_size = 0;
+	u32 i;
+
+	payload[0] = HFI_MODE_PROPERTY;
+	if (plane == INPUT_MPLANE) {
+		for (i = 0; i < ARRAY_SIZE(enc_input_properties); i++)
+			payload[i + 1] = enc_input_properties[i];
+		payload_size = (ARRAY_SIZE(enc_input_properties) + 1) *
+				sizeof(u32);
+	} else if (plane == OUTPUT_MPLANE) {
+		for (i = 0; i < ARRAY_SIZE(enc_output_properties); i++)
+			payload[i + 1] = enc_output_properties[i];
+		payload_size = (ARRAY_SIZE(enc_output_properties) + 1) *
+				sizeof(u32);
+	} else {
+		return -EINVAL;
+	}
+
+	return iris_hfi_session_subscribe_mode(inst,
+					       HFI_CMD_SUBSCRIBE_MODE,
+					       plane,
+					       HFI_PAYLOAD_U32_ARRAY,
+					       &payload[0],
+					       payload_size);
+}
+
+int venc_streamon_input(struct iris_inst *inst)
+{
+	int ret;
+
+	ret = check_session_supported(inst);
+	if (ret)
+		goto error;
+
+	ret = check_scaling_supported(inst);
+	if (ret)
+		goto error;
+
+	ret = venc_set_input_properties(inst);
+	if (ret)
+		goto error;
+
+	ret = iris_get_internal_buffers(inst, INPUT_MPLANE);
+	if (ret)
+		goto error;
+
+	ret = iris_destroy_internal_buffers(inst, INPUT_MPLANE);
+	if (ret)
+		goto error;
+
+	ret = iris_create_input_internal_buffers(inst);
+	if (ret)
+		goto error;
+
+	ret = iris_queue_input_internal_buffers(inst);
+	if (ret)
+		goto error;
+
+	ret = venc_property_subscription(inst, INPUT_MPLANE);
+	if (ret)
+		goto error;
+
+	ret = process_streamon_input(inst);
+	if (ret)
+		goto error;
+
+	return ret;
+
+error:
+	return ret;
+}
+
+static int venc_set_output_properties(struct iris_inst *inst)
+{
+	int j, ret;
+	static const struct venc_prop_type_handle prop_type_handle_arr[] = {
+		{HFI_PROP_BITSTREAM_RESOLUTION,       venc_set_bitstream_resolution    },
+		{HFI_PROP_CROP_OFFSETS,               venc_set_out_crop_offsets        },
+	};
+
+	for (j = 0; j < ARRAY_SIZE(prop_type_handle_arr); j++) {
+		ret = prop_type_handle_arr[j].handle(inst);
+		if (ret)
+			return ret;
+	}
+
+	return ret;
+}
+
+int venc_streamon_output(struct iris_inst *inst)
+{
+	int ret;
+
+	ret = venc_set_output_properties(inst);
+	if (ret)
+		goto error;
+
+	ret = set_v4l2_properties(inst);
+	if (ret)
+		goto error;
+
+	ret = venc_set_quality_mode(inst);
+	if (ret)
+		goto error;
+
+	ret = iris_get_internal_buffers(inst, OUTPUT_MPLANE);
+	if (ret)
+		goto error;
+
+	ret = iris_destroy_internal_buffers(inst, OUTPUT_MPLANE);
+	if (ret)
+		goto error;
+
+	ret = iris_create_output_internal_buffers(inst);
+	if (ret)
+		goto error;
+
+	ret = iris_queue_output_internal_buffers(inst);
+	if (ret)
+		goto error;
+
+	ret = venc_property_subscription(inst, OUTPUT_MPLANE);
+	if (ret)
+		goto error;
+
+	ret = process_streamon_output(inst);
+	if (ret)
+		goto error;
+
+	return ret;
+
+error:
+	session_streamoff(inst, OUTPUT_MPLANE);
+
+	return ret;
+}
diff --git a/drivers/media/platform/qcom/vcodec/iris/iris_venc.h b/drivers/media/platform/qcom/vcodec/iris/iris_venc.h
index 24da63f..b289750 100644
--- a/drivers/media/platform/qcom/vcodec/iris/iris_venc.h
+++ b/drivers/media/platform/qcom/vcodec/iris/iris_venc.h
@@ -20,5 +20,8 @@ int venc_subscribe_event(struct iris_inst *inst,
 			 const struct v4l2_event_subscription *sub);
 int venc_start_cmd(struct iris_inst *inst);
 int venc_stop_cmd(struct iris_inst *inst);
+int venc_qbuf(struct iris_inst *inst, struct vb2_buffer *vb2);
+int venc_streamon_input(struct iris_inst *inst);
+int venc_streamon_output(struct iris_inst *inst);
 
 #endif
diff --git a/drivers/media/platform/qcom/vcodec/iris/platform_common.h b/drivers/media/platform/qcom/vcodec/iris/platform_common.h
index effecbb..42ac662 100644
--- a/drivers/media/platform/qcom/vcodec/iris/platform_common.h
+++ b/drivers/media/platform/qcom/vcodec/iris/platform_common.h
@@ -71,6 +71,11 @@ enum pipe_type {
 	PIPE_4 = 4,
 };
 
+enum quality_mode {
+	MAX_QUALITY_MODE = 0x1,
+	POWER_SAVE_MODE = 0x2,
+};
+
 extern struct platform_data sm8550_data;
 
 struct bw_info {
diff --git a/drivers/media/platform/qcom/vcodec/iris/platform_sm8550.c b/drivers/media/platform/qcom/vcodec/iris/platform_sm8550.c
index ef0aad7..17c5856 100644
--- a/drivers/media/platform/qcom/vcodec/iris/platform_sm8550.c
+++ b/drivers/media/platform/qcom/vcodec/iris/platform_sm8550.c
@@ -74,6 +74,8 @@ static struct plat_core_cap core_data_sm8550[] = {
 	{CP_SIZE, 0x25800000},
 	{CP_NONPIXEL_START, 0x01000000},
 	{CP_NONPIXEL_SIZE, 0x24800000},
+	{MAX_MBPF_HQ, 8160}, /* ((1920x1088)/256) */
+	{MAX_MBPS_HQ, 489600}, /* ((1920x1088)/256)@60fps */
 };
 
 static struct plat_inst_cap instance_cap_data_sm8550[] = {
diff --git a/drivers/media/platform/qcom/vcodec/iris/vpu_iris3_buffer.c b/drivers/media/platform/qcom/vcodec/iris/vpu_iris3_buffer.c
index 44f9342..9882f00 100644
--- a/drivers/media/platform/qcom/vcodec/iris/vpu_iris3_buffer.c
+++ b/drivers/media/platform/qcom/vcodec/iris/vpu_iris3_buffer.c
@@ -163,6 +163,186 @@ static u32 dec_dpb_size_iris3(struct iris_inst *inst)
 	return size;
 }
 
+static u32 enc_bin_size_iris3(struct iris_inst *inst)
+{
+	u32 width, height, num_vpp_pipes, stage, profile;
+	struct iris_core *core;
+	struct v4l2_format *f;
+	u32 size = 0;
+
+	core = inst->core;
+
+	num_vpp_pipes = core->cap[NUM_VPP_PIPE].value;
+	stage = inst->cap[STAGE].value;
+	f = inst->fmt_dst;
+	width = f->fmt.pix_mp.width;
+	height = f->fmt.pix_mp.height;
+	profile = inst->cap[PROFILE].value;
+
+	if (inst->codec == H264)
+		size = hfi_buffer_bin_h264e(inst->hfi_rc_type, width, height,
+					    stage, num_vpp_pipes, profile);
+	else if (inst->codec == HEVC)
+		size = hfi_buffer_bin_h265e(inst->hfi_rc_type, width, height,
+					    stage, num_vpp_pipes, profile);
+
+	return size;
+}
+
+u32 get_recon_buf_count(struct iris_inst *inst)
+{
+	s32 n_bframe, ltr_count, hp_layers = 0, hb_layers = 0;
+	bool is_hybrid_hp = false;
+	u32 num_buf_recon = 0;
+	u32 hfi_codec = 0;
+
+	n_bframe = inst->cap[B_FRAME].value;
+	ltr_count = inst->cap[LTR_COUNT].value;
+
+	if (inst->hfi_layer_type == HFI_HIER_B) {
+		hb_layers = inst->cap[ENH_LAYER_COUNT].value + 1;
+	} else {
+		hp_layers = inst->cap[ENH_LAYER_COUNT].value + 1;
+		if (inst->hfi_layer_type == HFI_HIER_P_HYBRID_LTR)
+			is_hybrid_hp = true;
+	}
+
+	if (inst->codec == H264)
+		hfi_codec = HFI_CODEC_ENCODE_AVC;
+	else if (inst->codec == HEVC)
+		hfi_codec = HFI_CODEC_ENCODE_HEVC;
+
+	num_buf_recon = hfi_iris3_enc_recon_buf_count(n_bframe, ltr_count,
+						      hp_layers, hb_layers,
+						      is_hybrid_hp, hfi_codec);
+
+	return num_buf_recon;
+}
+
+static u32 enc_comv_size_iris3(struct iris_inst *inst)
+{
+	u32 width, height, num_recon = 0;
+	struct v4l2_format *f;
+	u32 size = 0;
+
+	f = inst->fmt_dst;
+	width = f->fmt.pix_mp.width;
+	height = f->fmt.pix_mp.height;
+
+	num_recon = get_recon_buf_count(inst);
+	if (inst->codec == H264)
+		size = hfi_buffer_comv_h264e(width, height, num_recon);
+	else if (inst->codec == HEVC)
+		size = hfi_buffer_comv_h265e(width, height, num_recon);
+
+	return size;
+}
+
+static u32 enc_non_comv_size_iris3(struct iris_inst *inst)
+{
+	u32 width, height, num_vpp_pipes;
+	struct iris_core *core;
+	struct v4l2_format *f;
+	u32 size = 0;
+
+	core = inst->core;
+
+	num_vpp_pipes = core->cap[NUM_VPP_PIPE].value;
+	f = inst->fmt_dst;
+	width = f->fmt.pix_mp.width;
+	height = f->fmt.pix_mp.height;
+
+	if (inst->codec == H264)
+		size = hfi_buffer_non_comv_h264e(width, height, num_vpp_pipes);
+	else if (inst->codec == HEVC)
+		size = hfi_buffer_non_comv_h265e(width, height, num_vpp_pipes);
+
+	return size;
+}
+
+static u32 enc_line_size_iris3(struct iris_inst *inst)
+{
+	u32 width, height, pixfmt, num_vpp_pipes;
+	struct iris_core *core;
+	bool is_tenbit = false;
+	struct v4l2_format *f;
+	u32 size = 0;
+
+	core = inst->core;
+	num_vpp_pipes = core->cap[NUM_VPP_PIPE].value;
+	pixfmt = inst->cap[PIX_FMTS].value;
+
+	f = inst->fmt_dst;
+	width = f->fmt.pix_mp.width;
+	height = f->fmt.pix_mp.height;
+	is_tenbit = (pixfmt == FMT_TP10C);
+
+	if (inst->codec == H264)
+		size = hfi_buffer_line_h264e(width, height, is_tenbit, num_vpp_pipes);
+	else if (inst->codec == HEVC)
+		size = hfi_buffer_line_h265e(width, height, is_tenbit, num_vpp_pipes);
+
+	return size;
+}
+
+static u32 enc_dpb_size_iris3(struct iris_inst *inst)
+{
+	u32 width, height, pixfmt;
+	struct v4l2_format *f;
+	bool is_tenbit;
+	u32 size = 0;
+
+	f = inst->fmt_dst;
+	width = f->fmt.pix_mp.width;
+	height = f->fmt.pix_mp.height;
+
+	pixfmt = inst->cap[PIX_FMTS].value;
+	is_tenbit = (pixfmt == FMT_TP10C);
+
+	if (inst->codec == H264)
+		size = hfi_buffer_dpb_h264e(width, height);
+	else if (inst->codec == HEVC)
+		size = hfi_buffer_dpb_h265e(width, height, is_tenbit);
+
+	return size;
+}
+
+static u32 enc_arp_size_iris3(struct iris_inst *inst)
+{
+	u32 size = 0;
+
+	HFI_BUFFER_ARP_ENC(size);
+
+	return size;
+}
+
+static u32 enc_vpss_size_iris3(struct iris_inst *inst)
+{
+	bool ds_enable = false, is_tenbit = false;
+	struct v4l2_format *f;
+	u32 width, height;
+	u32 size = 0;
+
+	ds_enable = is_scaling_enabled(inst);
+
+	f = inst->fmt_dst;
+	if (inst->cap[ROTATION].value == 90 ||
+	    inst->cap[ROTATION].value == 270) {
+		width = f->fmt.pix_mp.height;
+		height = f->fmt.pix_mp.width;
+	} else {
+		width = f->fmt.pix_mp.width;
+		height = f->fmt.pix_mp.height;
+	}
+
+	f = inst->fmt_src;
+	is_tenbit = is_10bit_colorformat(f->fmt.pix_mp.pixelformat);
+
+	size = hfi_buffer_vpss_enc(width, height, ds_enable, 0, is_tenbit);
+
+	return size;
+}
+
 struct iris_buf_type_handle {
 	enum iris_buffer_type type;
 	u32 (*handle)(struct iris_inst *inst);
@@ -183,9 +363,23 @@ int iris_int_buf_size_iris3(struct iris_inst *inst,
 		{BUF_PERSIST,         dec_persist_size_iris3      },
 		{BUF_DPB,             dec_dpb_size_iris3          },
 	};
+	static const struct iris_buf_type_handle enc_internal_buf_type_handle[] = {
+		{BUF_BIN,             enc_bin_size_iris3          },
+		{BUF_COMV,            enc_comv_size_iris3         },
+		{BUF_NON_COMV,        enc_non_comv_size_iris3     },
+		{BUF_LINE,            enc_line_size_iris3         },
+		{BUF_DPB,             enc_dpb_size_iris3          },
+		{BUF_ARP,             enc_arp_size_iris3          },
+		{BUF_VPSS,            enc_vpss_size_iris3         },
+	};
 
-	buf_type_handle_size = ARRAY_SIZE(dec_internal_buf_type_handle);
-	buf_type_handle_arr = dec_internal_buf_type_handle;
+	if (inst->domain == DECODER) {
+		buf_type_handle_size = ARRAY_SIZE(dec_internal_buf_type_handle);
+		buf_type_handle_arr = dec_internal_buf_type_handle;
+	} else if (inst->domain == ENCODER) {
+		buf_type_handle_size = ARRAY_SIZE(enc_internal_buf_type_handle);
+		buf_type_handle_arr = enc_internal_buf_type_handle;
+	}
 
 	if (!buf_type_handle_arr || !buf_type_handle_size)
 		return size;
diff --git a/drivers/media/platform/qcom/vcodec/iris/vpu_iris3_buffer.h b/drivers/media/platform/qcom/vcodec/iris/vpu_iris3_buffer.h
index b520c79..c63b3ac 100644
--- a/drivers/media/platform/qcom/vcodec/iris/vpu_iris3_buffer.h
+++ b/drivers/media/platform/qcom/vcodec/iris/vpu_iris3_buffer.h
@@ -14,8 +14,10 @@
 
 #define DMA_ALIGNMENT 256
 
+#define BUFFER_ALIGNMENT_4096_BYTES 4096
 #define BUFFER_ALIGNMENT_512_BYTES 512
 #define BUFFER_ALIGNMENT_256_BYTES 256
+#define BUFFER_ALIGNMENT_128_BYTES 128
 #define BUFFER_ALIGNMENT_64_BYTES 64
 #define BUFFER_ALIGNMENT_32_BYTES 32
 #define BUFFER_ALIGNMENT_16_BYTES 16
@@ -26,6 +28,8 @@
 #define HFI_COL_FMT_NV12C_Y_TILE_WIDTH (32)
 #define HFI_COL_FMT_NV12C_UV_TILE_HEIGHT (8)
 #define HFI_COL_FMT_NV12C_UV_TILE_WIDTH (16)
+#define HFI_COL_FMT_TP10C_Y_TILE_HEIGHT (4)
+#define HFI_COL_FMT_TP10C_Y_TILE_WIDTH (48)
 
 #define NUM_HW_PIC_BUF 32
 #define SIZE_HW_PIC(size_per_buf) (NUM_HW_PIC_BUF * (size_per_buf))
@@ -102,6 +106,27 @@
 #define MAX_PE_NBR_DATA_LCU64_LINE_BUFFER_SIZE (64 * 2 * 3)
 #define MAX_FE_NBR_DATA_LUMA_LINE_BUFFER_SIZE 640
 
+#define HFI_BUFFER_ARP_ENC(size) (size = 204800)
+
+#define HFI_MAX_COL_FRAME 6
+#define HFI_VENUS_WIDTH_ALIGNMENT 128
+#define HFI_VENUS_HEIGHT_ALIGNMENT 32
+#define VENUS_METADATA_STRIDE_MULTIPLE 64
+#define VENUS_METADATA_HEIGHT_MULTIPLE 16
+
+#ifndef SYSTEM_LAL_TILE10
+#define SYSTEM_LAL_TILE10 192
+#endif
+
+#define SIZE_SLICE_CMD_BUFFER (ALIGN(20480, BUFFER_ALIGNMENT_256_BYTES))
+#define SIZE_SPS_PPS_SLICE_HDR (2048 + 4096)
+
+#define SIZE_BSE_SLICE_CMD_BUF ((((8192 << 2) + 7) & (~7)) * 3)
+#define SIZE_LAMBDA_LUT (256 * 11)
+
+#define HFI_WORKMODE_1 1
+#define HFI_WORKMODE_2 2
+
 static inline
 u32 size_h264d_hw_bin_buffer(u32 frame_width, u32 frame_height,
 			     u32 num_vpp_pipes)
@@ -842,4 +867,603 @@ u32 hfi_yuv420_tp10_ubwc_calc_buf_size(u32 y_stride, u32 y_buf_height,
 int iris_int_buf_size_iris3(struct iris_inst *inst,
 			    enum iris_buffer_type buffer_type);
 
+static inline
+u32 hfi_iris3_enc_recon_buf_count(s32 n_bframe, s32 ltr_count,
+				  s32 _total_hp_layers,
+				  s32 _total_hb_layers,
+				  bool hybrid_hp,
+				  u32 codec_standard)
+{
+	u32 num_ref = 1;
+
+	if (n_bframe)
+		num_ref = 2;
+
+	if (_total_hp_layers > 1) {
+		if (hybrid_hp)
+			num_ref = (_total_hp_layers + 1) >> 1;
+		else if (codec_standard == HFI_CODEC_ENCODE_HEVC)
+			num_ref = (_total_hp_layers + 1) >> 1;
+		else if (codec_standard == HFI_CODEC_ENCODE_AVC &&
+			 _total_hp_layers < 4)
+			num_ref = (_total_hp_layers - 1);
+		else
+			num_ref = _total_hp_layers;
+	}
+
+	if (ltr_count)
+		num_ref = num_ref + ltr_count;
+
+	if (_total_hb_layers > 1) {
+		if (codec_standard == HFI_CODEC_ENCODE_HEVC)
+			num_ref = (_total_hb_layers);
+		else if (codec_standard == HFI_CODEC_ENCODE_AVC)
+			num_ref = (1 << (_total_hb_layers - 2)) + 1;
+	}
+
+	return num_ref + 1;
+}
+
+static inline
+u32 size_bin_bitstream_enc(u32 rc_type, u32 frame_width, u32 frame_height,
+			   u32 work_mode, u32 lcu_size, u32 profile)
+{
+	u32 size_aligned_width = 0, size_aligned_height = 0;
+	u32 bitstream_size_eval = 0;
+
+	size_aligned_width = ALIGN((frame_width), lcu_size);
+	size_aligned_height = ALIGN((frame_height), lcu_size);
+	if (work_mode == HFI_WORKMODE_2) {
+		if (rc_type == HFI_RC_CQ || rc_type == HFI_RC_OFF) {
+			bitstream_size_eval = (((size_aligned_width) *
+						(size_aligned_height) * 3) >> 1);
+		} else {
+			bitstream_size_eval = ((size_aligned_width) *
+					       (size_aligned_height) * 3);
+			if ((size_aligned_width * size_aligned_height) > (4096 * 2176))
+				bitstream_size_eval >>= 3;
+			else if ((size_aligned_width * size_aligned_height) > (480 * 320))
+				bitstream_size_eval >>= 2;
+
+			if (profile == HFI_H265_PROFILE_MAIN_10 ||
+			    profile == HFI_H265_PROFILE_MAIN_10_STILL_PICTURE)
+				bitstream_size_eval = (bitstream_size_eval * 5 >> 2);
+		}
+	} else {
+		bitstream_size_eval = size_aligned_width * size_aligned_height * 3;
+	}
+
+	return ALIGN(bitstream_size_eval, BUFFER_ALIGNMENT_256_BYTES);
+}
+
+static inline
+u32 size_enc_single_pipe(u32 rc_type, u32 bitbin_size, u32 num_vpp_pipes,
+			 u32 frame_width, u32 frame_height, u32 lcu_size)
+{
+	u32 size_single_pipe_eval = 0, sao_bin_buffer_size = 0;
+	u32 size_aligned_width = 0, size_aligned_height = 0;
+	u32 _padded_bin_sz = 0;
+
+	size_aligned_width = ALIGN((frame_width), lcu_size);
+	size_aligned_height = ALIGN((frame_height), lcu_size);
+	if ((size_aligned_width * size_aligned_height) > (3840 * 2160))
+		size_single_pipe_eval = (bitbin_size / num_vpp_pipes);
+	else if (num_vpp_pipes > 2)
+		size_single_pipe_eval = bitbin_size / 2;
+	else
+		size_single_pipe_eval = bitbin_size;
+
+	sao_bin_buffer_size =
+		(64 * ((((frame_width) + BUFFER_ALIGNMENT_32_BYTES) *
+			((frame_height) + BUFFER_ALIGNMENT_32_BYTES)) >> 10)) + 384;
+	_padded_bin_sz = ALIGN(size_single_pipe_eval, BUFFER_ALIGNMENT_256_BYTES);
+	size_single_pipe_eval = sao_bin_buffer_size + _padded_bin_sz;
+	size_single_pipe_eval = ALIGN(size_single_pipe_eval, BUFFER_ALIGNMENT_256_BYTES);
+
+	return size_single_pipe_eval;
+}
+
+static inline
+u32 hfi_buffer_bin_enc(u32 rc_type, u32 frame_width, u32 frame_height, u32 lcu_size,
+		       u32 work_mode, u32 num_vpp_pipes, u32 profile)
+{
+	u32 bitstream_size = 0, total_bitbin_buffers = 0;
+	u32 size_single_pipe = 0, bitbin_size = 0;
+	u32 _size = 0;
+
+	bitstream_size = size_bin_bitstream_enc(rc_type, frame_width,
+						frame_height, work_mode,
+						lcu_size, profile);
+
+	if (work_mode == HFI_WORKMODE_2) {
+		total_bitbin_buffers = 3;
+		bitbin_size = bitstream_size * 12 / 10;
+		bitbin_size = ALIGN(bitbin_size, BUFFER_ALIGNMENT_256_BYTES);
+	} else if ((lcu_size == 16) || (num_vpp_pipes > 1)) {
+		total_bitbin_buffers = 1;
+		bitbin_size = bitstream_size;
+	}
+
+	if (total_bitbin_buffers > 0) {
+		size_single_pipe = size_enc_single_pipe(rc_type, bitbin_size,
+							num_vpp_pipes, frame_width,
+							frame_height, lcu_size);
+		bitbin_size = size_single_pipe * num_vpp_pipes;
+		_size = ALIGN(bitbin_size, BUFFER_ALIGNMENT_256_BYTES) *
+			      total_bitbin_buffers + 512;
+	} else {
+		/* Avoid 512 Bytes allocation in case of 1Pipe HEVC Direct Mode*/
+		_size = 0;
+	}
+
+	return _size;
+}
+
+static inline
+u32 hfi_buffer_bin_h264e(u32 rc_type, u32 frame_width, u32 frame_height,
+			 u32 work_mode, u32 num_vpp_pipes, u32 profile)
+{
+	return hfi_buffer_bin_enc(rc_type, frame_width, frame_height, 16,
+				  work_mode, num_vpp_pipes, profile);
+}
+
+static inline
+u32 hfi_buffer_bin_h265e(u32 rc_type, u32 frame_width, u32 frame_height,
+			 u32 work_mode, u32 num_vpp_pipes, u32 profile)
+{
+	return hfi_buffer_bin_enc(rc_type, frame_width, frame_height, 32,
+				  work_mode, num_vpp_pipes, profile);
+}
+
+static inline
+u32 size_enc_slice_info_buf(u32 num_lcu_in_frame)
+{
+	return ALIGN((256 + (num_lcu_in_frame << 4)), BUFFER_ALIGNMENT_256_BYTES);
+}
+
+static inline
+u32 size_line_buf_ctrl(u32 frame_width_coded)
+{
+	return ALIGN(frame_width_coded, BUFFER_ALIGNMENT_256_BYTES);
+}
+
+static inline
+u32 size_line_buf_ctrl_id2(u32 frame_width_coded)
+{
+	return ALIGN(frame_width_coded, BUFFER_ALIGNMENT_256_BYTES);
+}
+
+static inline
+u32 size_linebuff_data(bool is_ten_bit, u32 frame_width_coded)
+{
+	u32 _size = 0;
+
+	_size = is_ten_bit ?
+		(((((10 * (frame_width_coded) + 1024) + (BUFFER_ALIGNMENT_256_BYTES - 1)) &
+		   (~(BUFFER_ALIGNMENT_256_BYTES - 1))) * 1) +
+		 (((((10 * (frame_width_coded) + 1024) >> 1) + (BUFFER_ALIGNMENT_256_BYTES - 1)) &
+		   (~(BUFFER_ALIGNMENT_256_BYTES - 1))) * 2)) :
+		(((((8 * (frame_width_coded) + 1024) + (BUFFER_ALIGNMENT_256_BYTES - 1)) &
+		   (~(BUFFER_ALIGNMENT_256_BYTES - 1))) * 1) +
+		 (((((8 * (frame_width_coded) + 1024) >> 1) + (BUFFER_ALIGNMENT_256_BYTES - 1)) &
+		   (~(BUFFER_ALIGNMENT_256_BYTES - 1))) * 2));
+
+	return _size;
+}
+
+static inline
+u32 size_left_linebuff_ctrl(u32 standard, u32 frame_height_coded,
+			    u32 num_vpp_pipes_enc)
+{
+	u32 _size = 0;
+
+	_size = standard == HFI_CODEC_ENCODE_HEVC ?
+		(((frame_height_coded) +
+		 (BUFFER_ALIGNMENT_32_BYTES)) / BUFFER_ALIGNMENT_32_BYTES * 4 * 16) :
+		(((frame_height_coded) + 15) / 16 * 5 * 16);
+
+	if ((num_vpp_pipes_enc) > 1) {
+		_size += BUFFER_ALIGNMENT_512_BYTES;
+		_size = ALIGN(_size, BUFFER_ALIGNMENT_512_BYTES) *
+			num_vpp_pipes_enc;
+	}
+
+	return ALIGN(_size, BUFFER_ALIGNMENT_256_BYTES);
+}
+
+static inline
+u32 size_left_linebuff_recon_pix(bool is_ten_bit, u32 frame_height_coded,
+				 u32 num_vpp_pipes_enc)
+{
+	return (((is_ten_bit + 1) * 2 * (frame_height_coded) + BUFFER_ALIGNMENT_256_BYTES) +
+		(BUFFER_ALIGNMENT_256_BYTES << (num_vpp_pipes_enc - 1)) - 1) &
+		(~((BUFFER_ALIGNMENT_256_BYTES << (num_vpp_pipes_enc - 1)) - 1)) * 1;
+}
+
+static inline
+u32 size_top_linebuff_ctrl_fe(u32 frame_width_coded, u32 standard)
+{
+	u32 _size = 0;
+
+	_size = standard == HFI_CODEC_ENCODE_HEVC ?
+		(64 * ((frame_width_coded) >> 5)) :
+		(BUFFER_ALIGNMENT_256_BYTES + 16 * ((frame_width_coded) >> 4));
+
+	return ALIGN(_size, BUFFER_ALIGNMENT_256_BYTES);
+}
+
+static inline
+u32 size_left_linebuff_ctrl_fe(u32 frame_height_coded, u32 num_vpp_pipes_enc)
+{
+	return (((BUFFER_ALIGNMENT_256_BYTES + 64 * ((frame_height_coded) >> 4)) +
+		 (BUFFER_ALIGNMENT_256_BYTES << (num_vpp_pipes_enc - 1)) - 1) &
+		 (~((BUFFER_ALIGNMENT_256_BYTES << (num_vpp_pipes_enc - 1)) - 1)) * 1) *
+		num_vpp_pipes_enc;
+}
+
+static inline
+u32 size_left_linebuff_metadata_recon_y(u32 frame_height_coded,
+					bool is_ten_bit,
+					u32 num_vpp_pipes_enc)
+{
+	u32 _size = 0;
+
+	_size = ((BUFFER_ALIGNMENT_256_BYTES + 64 * ((frame_height_coded) /
+		  (8 * (is_ten_bit ? 4 : 8)))));
+	_size = ALIGN(_size, BUFFER_ALIGNMENT_256_BYTES);
+
+	return (_size * num_vpp_pipes_enc);
+}
+
+static inline
+u32 size_left_linebuff_metadata_recon_uv(u32 frame_height_coded,
+					 bool is_ten_bit,
+					 u32 num_vpp_pipes_enc)
+{
+	u32 _size = 0;
+
+	_size = ((BUFFER_ALIGNMENT_256_BYTES + 64 * ((frame_height_coded) /
+		  (4 * (is_ten_bit ? 4 : 8)))));
+	_size = ALIGN(_size, BUFFER_ALIGNMENT_256_BYTES);
+
+	return (_size * num_vpp_pipes_enc);
+}
+
+static inline
+u32 size_linebuff_recon_pix(bool is_ten_bit, u32 frame_width_coded)
+{
+	return ALIGN(((is_ten_bit ? 3 : 2) * (frame_width_coded)),
+		     BUFFER_ALIGNMENT_256_BYTES);
+}
+
+static inline
+u32 size_frame_rc_buf_size(u32 standard, u32 frame_height_coded,
+			   u32 num_vpp_pipes_enc)
+{
+	u32 _size = 0;
+
+	_size = (standard == HFI_CODEC_ENCODE_HEVC) ?
+		(256 + 16 * (14 + ((((frame_height_coded) >> 5) + 7) >> 3))) :
+		(256 + 16 * (14 + ((((frame_height_coded) >> 4) + 7) >> 3)));
+	_size *= 11;
+	if (num_vpp_pipes_enc > 1)
+		_size = ALIGN(_size, BUFFER_ALIGNMENT_256_BYTES) * num_vpp_pipes_enc;
+
+	return ALIGN(_size, BUFFER_ALIGNMENT_512_BYTES) * HFI_MAX_COL_FRAME;
+}
+
+static inline u32 enc_bitcnt_buf_size(u32 num_lcu_in_frame)
+{
+	return ALIGN((256 + (4 * (num_lcu_in_frame))), BUFFER_ALIGNMENT_256_BYTES);
+}
+
+static inline u32 enc_bitmap_buf_size(u32 num_lcu_in_frame)
+{
+	return ALIGN((256 + ((num_lcu_in_frame) >> 3)), BUFFER_ALIGNMENT_256_BYTES);
+}
+
+static inline u32 size_line_buf_sde(u32 frame_width_coded)
+{
+	return ALIGN((256 + (16 * ((frame_width_coded) >> 4))), BUFFER_ALIGNMENT_256_BYTES);
+}
+
+static inline u32 size_override_buf(u32 num_lcumb)
+{
+	return ALIGN(((16 * (((num_lcumb) + 7) >> 3))), BUFFER_ALIGNMENT_256_BYTES) * 2;
+}
+
+static inline u32 size_ir_buf(u32 num_lcu_in_frame)
+{
+	return ALIGN((((((num_lcu_in_frame) << 1) + 7) & (~7)) * 3), BUFFER_ALIGNMENT_256_BYTES);
+}
+
+static inline
+u32 size_vpss_line_buf(u32 num_vpp_pipes_enc, u32 frame_height_coded,
+		       u32 frame_width_coded)
+{
+	return ALIGN(((((((8192) >> 2) << 5) * (num_vpp_pipes_enc)) + 64) +
+		      (((((max_t(u32, (frame_width_coded),
+				 (frame_height_coded)) + 3) >> 2) << 5) + 256) * 16)),
+		     BUFFER_ALIGNMENT_256_BYTES);
+}
+
+static inline
+u32 size_top_line_buf_first_stg_sao(u32 frame_width_coded)
+{
+	return ALIGN((16 * ((frame_width_coded) >> 5)), BUFFER_ALIGNMENT_256_BYTES);
+}
+
+static inline
+u32 hfi_buffer_line_enc(u32 frame_width, u32 frame_height, bool is_ten_bit,
+			u32 num_vpp_pipes_enc, u32 lcu_size, u32 standard)
+{
+	u32 line_buff_data_size = 0, left_line_buff_ctrl_size = 0;
+	u32 frame_width_coded = 0, frame_height_coded = 0;
+	u32 left_line_buff_metadata_recon__uv__size = 0;
+	u32 left_line_buff_metadata_recon__y__size = 0;
+	u32 width_in_lcus = 0, height_in_lcus = 0;
+	u32 left_line_buff_recon_pix_size = 0;
+	u32 top_line_buff_ctrl_fe_size = 0;
+	u32 line_buff_recon_pix_size = 0;
+
+	width_in_lcus = ((frame_width) + (lcu_size) - 1) / (lcu_size);
+	height_in_lcus = ((frame_height) + (lcu_size) - 1) / (lcu_size);
+	frame_width_coded = width_in_lcus * (lcu_size);
+	frame_height_coded = height_in_lcus * (lcu_size);
+	line_buff_data_size = size_linebuff_data(is_ten_bit, frame_width_coded);
+	left_line_buff_ctrl_size =
+		size_left_linebuff_ctrl(standard, frame_height_coded, num_vpp_pipes_enc);
+	left_line_buff_recon_pix_size =
+		size_left_linebuff_recon_pix(is_ten_bit, frame_height_coded,
+					     num_vpp_pipes_enc);
+	top_line_buff_ctrl_fe_size =
+		size_top_linebuff_ctrl_fe(frame_width_coded, standard);
+	left_line_buff_metadata_recon__y__size =
+		size_left_linebuff_metadata_recon_y(frame_height_coded, is_ten_bit,
+						    num_vpp_pipes_enc);
+	left_line_buff_metadata_recon__uv__size =
+		size_left_linebuff_metadata_recon_uv(frame_height_coded, is_ten_bit,
+						     num_vpp_pipes_enc);
+	line_buff_recon_pix_size = size_linebuff_recon_pix(is_ten_bit, frame_width_coded);
+
+	return size_line_buf_ctrl(frame_width_coded) +
+		size_line_buf_ctrl_id2(frame_width_coded) +
+		line_buff_data_size +
+		left_line_buff_ctrl_size +
+		left_line_buff_recon_pix_size +
+		top_line_buff_ctrl_fe_size +
+		left_line_buff_metadata_recon__y__size +
+		left_line_buff_metadata_recon__uv__size +
+		line_buff_recon_pix_size +
+		size_left_linebuff_ctrl_fe(frame_height_coded,
+					   num_vpp_pipes_enc) +
+		size_line_buf_sde(frame_width_coded) +
+		size_vpss_line_buf(num_vpp_pipes_enc, frame_height_coded,
+				   frame_width_coded) +
+		size_top_line_buf_first_stg_sao(frame_width_coded);
+}
+
+static inline
+u32 hfi_buffer_line_h264e(u32 frame_width, u32 frame_height, bool is_ten_bit,
+			  u32 num_vpp_pipes)
+{
+	return hfi_buffer_line_enc(frame_width, frame_height, 0,
+				   num_vpp_pipes, 16,
+				   HFI_CODEC_ENCODE_AVC);
+}
+
+static inline
+u32 hfi_buffer_line_h265e(u32 frame_width, u32 frame_height, bool is_ten_bit,
+			  u32 num_vpp_pipes)
+{
+	return hfi_buffer_line_enc(frame_width, frame_height,
+				   is_ten_bit, num_vpp_pipes, 32,
+				   HFI_CODEC_ENCODE_HEVC);
+}
+
+static inline
+u32 hfi_buffer_comv_enc(u32 frame_width, u32 frame_height, u32 lcu_size,
+			u32 num_recon, u32 standard)
+{
+	u32 width_in_lcus, height_in_lcus, num_lcu_in_frame;
+	u32 size_colloc_mv = 0, size_colloc_rc = 0;
+	u32 mb_height = ((frame_height) + 15) >> 4;
+	u32 mb_width = ((frame_width) + 15) >> 4;
+
+	width_in_lcus = ((frame_width) + (lcu_size) - 1) / (lcu_size);
+	height_in_lcus = ((frame_height) + (lcu_size) - 1) / (lcu_size);
+	num_lcu_in_frame = width_in_lcus * height_in_lcus;
+	size_colloc_mv = (standard == HFI_CODEC_ENCODE_HEVC) ?
+		(16 * ((num_lcu_in_frame << 2) + BUFFER_ALIGNMENT_32_BYTES)) :
+		(3 * 16 * (width_in_lcus * height_in_lcus + BUFFER_ALIGNMENT_32_BYTES));
+	size_colloc_mv = ALIGN(size_colloc_mv, BUFFER_ALIGNMENT_256_BYTES) * num_recon;
+	size_colloc_rc = (((mb_width + 7) >> 3) * 16 * 2 * mb_height);
+	size_colloc_rc = ALIGN(size_colloc_rc, BUFFER_ALIGNMENT_256_BYTES) * HFI_MAX_COL_FRAME;
+
+	return size_colloc_mv + size_colloc_rc;
+}
+
+static inline
+u32 hfi_buffer_comv_h264e(u32 frame_width, u32 frame_height, u32 num_recon)
+{
+	return hfi_buffer_comv_enc(frame_width, frame_height, 16,
+				   num_recon, HFI_CODEC_ENCODE_AVC);
+}
+
+static inline
+u32 hfi_buffer_comv_h265e(u32 frame_width, u32 frame_height, u32 num_recon)
+{
+	return hfi_buffer_comv_enc(frame_width, frame_height, 32,
+				   num_recon, HFI_CODEC_ENCODE_HEVC);
+}
+
+static inline
+u32 hfi_buffer_non_comv_enc(u32 frame_width, u32 frame_height,
+			    u32 num_vpp_pipes_enc, u32 lcu_size, u32 standard)
+{
+	u32 frame_width_coded = 0, frame_height_coded = 0;
+	u32 width_in_lcus = 0, height_in_lcus = 0;
+	u32 num_lcu_in_frame = 0, num_lcumb = 0;
+	u32 frame_rc_buf_size = 0;
+
+	width_in_lcus = ((frame_width) + (lcu_size) - 1) / (lcu_size);
+	height_in_lcus = ((frame_height) + (lcu_size) - 1) / (lcu_size);
+	num_lcu_in_frame = width_in_lcus * height_in_lcus;
+	frame_width_coded = width_in_lcus * (lcu_size);
+	frame_height_coded = height_in_lcus * (lcu_size);
+	num_lcumb = (frame_height_coded / lcu_size) *
+		((frame_width_coded + lcu_size * 8) / lcu_size);
+	frame_rc_buf_size =
+		size_frame_rc_buf_size(standard, frame_height_coded,
+				       num_vpp_pipes_enc);
+	return size_enc_slice_info_buf(num_lcu_in_frame) +
+		   SIZE_SLICE_CMD_BUFFER +
+		   SIZE_SPS_PPS_SLICE_HDR +
+		   frame_rc_buf_size +
+		   enc_bitcnt_buf_size(num_lcu_in_frame) +
+		   enc_bitmap_buf_size(num_lcu_in_frame) +
+		   SIZE_BSE_SLICE_CMD_BUF +
+		   SIZE_LAMBDA_LUT +
+		   size_override_buf(num_lcumb) +
+		   size_ir_buf(num_lcu_in_frame);
+}
+
+static inline
+u32 hfi_buffer_non_comv_h264e(u32 frame_width, u32 frame_height,
+			      u32 num_vpp_pipes_enc)
+{
+	return hfi_buffer_non_comv_enc(frame_width, frame_height,
+				       num_vpp_pipes_enc, 16,
+				       HFI_CODEC_ENCODE_AVC);
+}
+
+static inline
+u32 hfi_buffer_non_comv_h265e(u32 frame_width, u32 frame_height,
+			      u32 num_vpp_pipes_enc)
+{
+	return hfi_buffer_non_comv_enc(frame_width, frame_height,
+				       num_vpp_pipes_enc, 32,
+				       HFI_CODEC_ENCODE_HEVC);
+}
+
+static inline
+u32 size_enc_ref_buffer(u32 frame_width, u32 frame_height)
+{
+	u32 u_buffer_width = 0, u_buffer_height = 0;
+	u32 u_chroma_buffer_height = 0;
+
+	u_buffer_height = ALIGN(frame_height, HFI_VENUS_HEIGHT_ALIGNMENT);
+	u_chroma_buffer_height = frame_height >> 1;
+	u_chroma_buffer_height = ALIGN(u_chroma_buffer_height, HFI_VENUS_HEIGHT_ALIGNMENT);
+	u_buffer_width = ALIGN(frame_width, HFI_VENUS_WIDTH_ALIGNMENT);
+
+	return (u_buffer_height + u_chroma_buffer_height) * u_buffer_width;
+}
+
+static inline
+u32 size_enc_ten_bit_ref_buffer(u32 frame_width, u32 frame_height)
+{
+	u32 ref_buf_height = 0, ref_luma_stride_in_bytes = 0;
+	u32 chroma_size = 0, ref_buf_size = 0;
+	u32 u_ref_stride = 0, luma_size = 0;
+	u32 ref_chrm_height_in_bytes = 0;
+
+	ref_buf_height = (frame_height + (HFI_VENUS_HEIGHT_ALIGNMENT - 1)) &
+			(~(HFI_VENUS_HEIGHT_ALIGNMENT - 1));
+	ref_luma_stride_in_bytes = ((frame_width + SYSTEM_LAL_TILE10 - 1) / SYSTEM_LAL_TILE10) *
+		SYSTEM_LAL_TILE10;
+	u_ref_stride = 4 * (ref_luma_stride_in_bytes / 3);
+	u_ref_stride = (u_ref_stride + (BUFFER_ALIGNMENT_128_BYTES - 1)) &
+		(~(BUFFER_ALIGNMENT_128_BYTES - 1));
+	luma_size = ref_buf_height * u_ref_stride;
+	ref_chrm_height_in_bytes = (((frame_height + 1) >> 1) + (BUFFER_ALIGNMENT_32_BYTES - 1)) &
+		(~(BUFFER_ALIGNMENT_32_BYTES - 1));
+	chroma_size = u_ref_stride * ref_chrm_height_in_bytes;
+	luma_size = (luma_size + (BUFFER_ALIGNMENT_4096_BYTES - 1)) &
+		(~(BUFFER_ALIGNMENT_4096_BYTES - 1));
+	chroma_size = (chroma_size + (BUFFER_ALIGNMENT_4096_BYTES - 1)) &
+		(~(BUFFER_ALIGNMENT_4096_BYTES - 1));
+	ref_buf_size = luma_size + chroma_size;
+
+	return ref_buf_size;
+}
+
+static inline
+u32 hfi_buffer_dpb_enc(u32 frame_width, u32 frame_height, bool is_ten_bit)
+{
+	u32 metadata_stride, metadata_buf_height, meta_size_y, meta_size_c;
+	u32 ten_bit_ref_buf_size = 0, ref_buf_size = 0;
+	u32 _size = 0;
+
+	if (!is_ten_bit) {
+		ref_buf_size = size_enc_ref_buffer(frame_width, frame_height);
+		metadata_stride =
+			hfi_ubwc_calc_metadata_plane_stride(frame_width, 64,
+							    HFI_COL_FMT_NV12C_Y_TILE_WIDTH);
+		metadata_buf_height =
+			hfi_ubwc_metadata_plane_bufheight(frame_height, 16,
+							  HFI_COL_FMT_NV12C_Y_TILE_HEIGHT);
+		meta_size_y =
+			hfi_ubwc_metadata_plane_buffer_size(metadata_stride, metadata_buf_height);
+		meta_size_c =
+			hfi_ubwc_metadata_plane_buffer_size(metadata_stride, metadata_buf_height);
+		_size = ref_buf_size + meta_size_y + meta_size_c;
+	} else {
+		ten_bit_ref_buf_size = size_enc_ten_bit_ref_buffer(frame_width, frame_height);
+		metadata_stride =
+			hfi_ubwc_calc_metadata_plane_stride(frame_width,
+							    VENUS_METADATA_STRIDE_MULTIPLE,
+							    HFI_COL_FMT_TP10C_Y_TILE_WIDTH);
+		metadata_buf_height =
+			hfi_ubwc_metadata_plane_bufheight(frame_height,
+							  VENUS_METADATA_HEIGHT_MULTIPLE,
+							  HFI_COL_FMT_TP10C_Y_TILE_HEIGHT);
+		meta_size_y =
+			hfi_ubwc_metadata_plane_buffer_size(metadata_stride, metadata_buf_height);
+		meta_size_c =
+			hfi_ubwc_metadata_plane_buffer_size(metadata_stride, metadata_buf_height);
+		_size = ten_bit_ref_buf_size + meta_size_y + meta_size_c;
+	}
+
+	return _size;
+}
+
+static inline
+u32 hfi_buffer_dpb_h264e(u32 frame_width, u32 frame_height)
+{
+	return hfi_buffer_dpb_enc(frame_width, frame_height, 0);
+}
+
+static inline
+u32 hfi_buffer_dpb_h265e(u32 frame_width, u32 frame_height, bool is_ten_bit)
+{
+	return hfi_buffer_dpb_enc(frame_width, frame_height, is_ten_bit);
+}
+
+static inline
+u32 hfi_buffer_vpss_enc(u32 dswidth, u32 dsheight, bool ds_enable,
+			u32 blur, bool is_ten_bit)
+{
+	u32 vpss_size = 0;
+
+	if (ds_enable || blur)
+		vpss_size = hfi_buffer_dpb_enc(dswidth, dsheight, is_ten_bit);
+
+	return vpss_size;
+}
+
+static inline
+u32 hfi_iris3_enc_min_input_buf_count(u32 totalhblayers)
+{
+	u32 numinput = 3;
+
+	if (totalhblayers >= 2)
+		numinput = (1 << (totalhblayers - 1)) + 2;
+
+	return numinput;
+}
+
+u32 enc_output_buffer_size_iris3(struct iris_inst *inst);
+u32 get_recon_buf_count(struct iris_inst *inst);
+
 #endif
diff --git a/drivers/media/platform/qcom/vcodec/iris/vpu_iris3_power.c b/drivers/media/platform/qcom/vcodec/iris/vpu_iris3_power.c
index 58498af..2828227 100644
--- a/drivers/media/platform/qcom/vcodec/iris/vpu_iris3_power.c
+++ b/drivers/media/platform/qcom/vcodec/iris/vpu_iris3_power.c
@@ -54,7 +54,7 @@ u64 iris_calc_freq_iris3(struct iris_inst *inst, u32 data_size)
 	if (inst->cap[STAGE].value == STAGE_1)
 		vsp_cycles = vsp_cycles * 3;
 
-	vsp_cycles += mbs_per_second * base_cycles;
+		vsp_cycles += mbs_per_second * base_cycles;
 
 	freq = max3(vpp_cycles, vsp_cycles, fw_cycles);
 
-- 
2.7.4


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ