diff --git a/drivers/media/platform/qcom/vcodec/iris/hfi_defines.h b/drivers/media/platform/qcom/vcodec/iris/hfi_defines.h
index a6078a5..0ef6bad 100644
--- a/drivers/media/platform/qcom/vcodec/iris/hfi_defines.h
+++ b/drivers/media/platform/qcom/vcodec/iris/hfi_defines.h
@@ -10,6 +10,7 @@
 
 #define HFI_VIDEO_ARCH_LX			0x1
 
+#define HFI_CMD_BEGIN				0x01000000
 #define HFI_CMD_INIT				0x01000001
 #define HFI_CMD_OPEN				0x01000003
 #define HFI_CMD_CLOSE				0x01000004
@@ -31,7 +32,18 @@ enum hfi_property_mode_type {
 	HFI_MODE_PROPERTY				= 0x00000002,
 };
 
-#define HFI_CMD_SUBSCRIBE_MODE		0x0100000B
+#define HFI_CMD_SUBSCRIBE_MODE			0x0100000B
+#define HFI_CMD_SETTINGS_CHANGE			0x0100000C
+#define HFI_CMD_END				0x01FFFFFF
+
+#define HFI_BITMASK_BITSTREAM_WIDTH		0xffff0000
+#define HFI_BITMASK_BITSTREAM_HEIGHT		0x0000ffff
+
+#define HFI_BITMASK_FRAME_MBS_ONLY_FLAG		0x00000001
+
+#define HFI_PROP_BEGIN				0x03000000
+
+#define HFI_PROP_IMAGE_VERSION			0x03000001
 
 enum hfi_color_format {
 	HFI_COLOR_FMT_OPAQUE        = 0,
@@ -46,8 +58,12 @@ enum hfi_color_format {
 
 #define HFI_PROP_COLOR_FORMAT			0x03000101
 
+#define HFI_PROP_BITSTREAM_RESOLUTION		0x03000103
+
 #define HFI_PROP_LINEAR_STRIDE_SCANLINE		0x03000104
 
+#define HFI_PROP_CROP_OFFSETS			0x03000105
+
 #define HFI_PROP_PROFILE			0x03000107
 
 #define HFI_PROP_LEVEL				0x03000108
@@ -68,13 +84,83 @@ enum hfi_color_format {
 
 #define HFI_PROP_BUFFER_HOST_MAX_COUNT		0x03000123
 
+#define HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT	0x03000124
+
 #define HFI_PROP_PIC_ORDER_CNT_TYPE		0x03000128
 
+#define HFI_PROP_QUALITY_MODE			0x03000148
+
+enum hfi_color_primaries {
+	HFI_PRIMARIES_RESERVED		= 0,
+	HFI_PRIMARIES_BT709		= 1,
+	HFI_PRIMARIES_UNSPECIFIED	= 2,
+	HFI_PRIMARIES_BT470_SYSTEM_M	= 4,
+	HFI_PRIMARIES_BT470_SYSTEM_BG	= 5,
+	HFI_PRIMARIES_BT601_525		= 6,
+	HFI_PRIMARIES_SMPTE_ST240M	= 7,
+	HFI_PRIMARIES_GENERIC_FILM	= 8,
+	HFI_PRIMARIES_BT2020		= 9,
+	HFI_PRIMARIES_SMPTE_ST428_1	= 10,
+	HFI_PRIMARIES_SMPTE_RP431_2	= 11,
+	HFI_PRIMARIES_SMPTE_EG431_1	= 12,
+	HFI_PRIMARIES_SMPTE_EBU_TECH	= 22,
+};
+
+enum hfi_transfer_characteristics {
+	HFI_TRANSFER_RESERVED		= 0,
+	HFI_TRANSFER_BT709		= 1,
+	HFI_TRANSFER_UNSPECIFIED	= 2,
+	HFI_TRANSFER_BT470_SYSTEM_M	= 4,
+	HFI_TRANSFER_BT470_SYSTEM_BG	= 5,
+	HFI_TRANSFER_BT601_525_OR_625	= 6,
+	HFI_TRANSFER_SMPTE_ST240M	= 7,
+	HFI_TRANSFER_LINEAR		= 8,
+	HFI_TRANSFER_LOG_100_1		= 9,
+	HFI_TRANSFER_LOG_SQRT		= 10,
+	HFI_TRANSFER_XVYCC		= 11,
+	HFI_TRANSFER_BT1361_0		= 12,
+	HFI_TRANSFER_SRGB_SYCC		= 13,
+	HFI_TRANSFER_BT2020_14		= 14,
+	HFI_TRANSFER_BT2020_15		= 15,
+	HFI_TRANSFER_SMPTE_ST2084_PQ	= 16,
+	HFI_TRANSFER_SMPTE_ST428_1	= 17,
+	HFI_TRANSFER_BT2100_2_HLG	= 18,
+};
+
+enum hfi_matrix_coefficients {
+	HFI_MATRIX_COEFF_SRGB_SMPTE_ST428_1		= 0,
+	HFI_MATRIX_COEFF_BT709				= 1,
+	HFI_MATRIX_COEFF_UNSPECIFIED			= 2,
+	HFI_MATRIX_COEFF_RESERVED			= 3,
+	HFI_MATRIX_COEFF_FCC_TITLE_47			= 4,
+	HFI_MATRIX_COEFF_BT470_SYS_BG_OR_BT601_625	= 5,
+	HFI_MATRIX_COEFF_BT601_525_BT1358_525_OR_625	= 6,
+	HFI_MATRIX_COEFF_SMPTE_ST240			= 7,
+	HFI_MATRIX_COEFF_YCGCO				= 8,
+	HFI_MATRIX_COEFF_BT2020_NON_CONSTANT		= 9,
+	HFI_MATRIX_COEFF_BT2020_CONSTANT		= 10,
+	HFI_MATRIX_COEFF_SMPTE_ST2085			= 11,
+	HFI_MATRIX_COEFF_SMPTE_CHROM_DERV_NON_CONSTANT	= 12,
+	HFI_MATRIX_COEFF_SMPTE_CHROM_DERV_CONSTANT	= 13,
+	HFI_MATRIX_COEFF_BT2100				= 14,
+};
+
+#define HFI_PROP_SIGNAL_COLOR_INFO		0x03000155
+
 #define HFI_PROP_DECODE_ORDER_OUTPUT		0x0300015b
 
+enum hfi_picture_type {
+	HFI_PICTURE_IDR	= 0x00000001,
+	HFI_PICTURE_P	= 0x00000002,
+	HFI_PICTURE_B	= 0x00000004,
+	HFI_PICTURE_I	= 0x00000008,
+	HFI_PICTURE_CRA	= 0x00000010,
+	HFI_PICTURE_BLA	= 0x00000020,
+};
+
 #define HFI_PROP_PICTURE_TYPE			0x03000162
 
-#define HFI_PROP_DEC_DEFAULT_HEADER		0x03000168
+#define HFI_PROP_DEC_DEFAULT_HEADER             0x03000168
 
 #define HFI_PROP_DEC_START_FROM_RAP_FRAME	0x03000169
 
@@ -86,7 +172,29 @@ enum hfi_color_format {
 
 #define HFI_PROP_COMV_BUFFER_COUNT		0x03000193
 
-#define HFI_SYS_ERROR_WD_TIMEOUT		0x05000001
+#define HFI_PROP_END				0x03FFFFFF
+
+#define HFI_SESSION_ERROR_BEGIN			0x04000000
+
+#define HFI_ERROR_UNKNOWN_SESSION		0x04000001
+
+#define HFI_ERROR_MAX_SESSIONS			0x04000002
+
+#define HFI_ERROR_FATAL				0x04000003
+
+#define HFI_ERROR_INVALID_STATE			0x04000004
+
+#define HFI_ERROR_INSUFFICIENT_RESOURCES	0x04000005
+
+#define HFI_ERROR_BUFFER_NOT_SET		0x04000006
+
+#define HFI_SESSION_ERROR_END			0x04FFFFFF
+
+#define HFI_SYSTEM_ERROR_BEGIN			0x05000000
+
+#define HFI_SYS_ERROR_WD_TIMEOUT                0x05000001
+
+#define HFI_SYSTEM_ERROR_END			0x05FFFFFF
 
 struct hfi_debug_header {
 	u32   size;
diff --git a/drivers/media/platform/qcom/vcodec/iris/iris_common.h b/drivers/media/platform/qcom/vcodec/iris/iris_common.h
index 6b771f8..0fbd139 100644
--- a/drivers/media/platform/qcom/vcodec/iris/iris_common.h
+++ b/drivers/media/platform/qcom/vcodec/iris/iris_common.h
@@ -8,7 +8,6 @@
 #include <media/v4l2-dev.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-event.h>
-#include <media/v4l2-ioctl.h>
 #include <media/videobuf2-v4l2.h>
 
 #define INPUT_MPLANE V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
@@ -16,6 +15,7 @@
 #define DEFAULT_WIDTH 320
 #define DEFAULT_HEIGHT 240
 #define DEFAULT_BSE_VPP_DELAY    2
+#define IRIS_VERSION_LENGTH   128
 
 #define MAX_EVENTS   30
 
@@ -23,6 +23,9 @@
 
 #define NUM_MBS_4k (((4096 + 15) >> 4) * ((2304 + 15) >> 4))
 
+#define MAX_DPB_LIST_ARRAY_SIZE (16 * 4)
+#define MAX_DPB_LIST_PAYLOAD_SIZE (16 * 4 * 4)
+
 enum codec_type {
 	H264	= BIT(0),
 	HEVC	= BIT(1),
@@ -95,4 +98,24 @@ struct iris_buffer {
 	struct dma_buf_attachment	*attach;
 };
 
+struct subscription_params {
+	u32	bitstream_resolution;
+	u32	crop_offsets[2];
+	u32	bit_depth;
+	u32	coded_frames;
+	u32	fw_min_count;
+	u32	pic_order_cnt;
+	u32	color_info;
+	u32	profile;
+	u32	level;
+	u32	tier;
+};
+
+struct iris_hfi_frame_info {
+	u32	picture_type;
+	u32	no_output;
+	u32	data_corrupt;
+	u32	overflow;
+};
+
 #endif
diff --git a/drivers/media/platform/qcom/vcodec/iris/iris_core.h b/drivers/media/platform/qcom/vcodec/iris/iris_core.h
index 154991c..6452ea7 100644
--- a/drivers/media/platform/qcom/vcodec/iris/iris_core.h
+++ b/drivers/media/platform/qcom/vcodec/iris/iris_core.h
@@ -57,6 +57,7 @@
  * @inst_caps: a pointer to supported instance capabilities
  * @instances: a list_head of all instances
  * @intr_status: interrupt status
+ * @fw_version: firmware version
  */
 
 struct iris_core {
@@ -99,6 +100,7 @@ struct iris_core {
 	struct plat_inst_caps			*inst_caps;
 	struct list_head			instances;
 	u32					intr_status;
+	char					fw_version[IRIS_VERSION_LENGTH];
 };
 
 int iris_core_init(struct iris_core *core);
diff --git a/drivers/media/platform/qcom/vcodec/iris/iris_helpers.c b/drivers/media/platform/qcom/vcodec/iris/iris_helpers.c
index ff44cda..4cad673 100644
--- a/drivers/media/platform/qcom/vcodec/iris/iris_helpers.c
+++ b/drivers/media/platform/qcom/vcodec/iris/iris_helpers.c
@@ -3,6 +3,8 @@
  * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
+#include "hfi_defines.h"
+#include "iris_core.h"
 #include "iris_helpers.h"
 #include "iris_hfi.h"
 #include "iris_hfi_packet.h"
@@ -66,7 +68,7 @@ int get_mbpf(struct iris_inst *inst)
 	return NUM_MBS_PER_FRAME(height, width);
 }
 
-bool is_linear_colorformat(u32 colorformat)
+inline bool is_linear_colorformat(u32 colorformat)
 {
 	return colorformat == V4L2_PIX_FMT_NV12 || colorformat == V4L2_PIX_FMT_NV21;
 }
@@ -350,3 +352,28 @@ int check_session_supported(struct iris_inst *inst)
 
 	return ret;
 }
+
+int signal_session_msg_receipt(struct iris_inst *inst,
+			       enum signal_session_response cmd)
+{
+	if (cmd < MAX_SIGNAL)
+		complete(&inst->completions[cmd]);
+
+	return 0;
+}
+
+struct iris_inst *to_instance(struct iris_core *core, u32 session_id)
+{
+	struct iris_inst *inst = NULL;
+
+	mutex_lock(&core->lock);
+	list_for_each_entry(inst, &core->instances, list) {
+		if (inst->session_id == session_id) {
+			mutex_unlock(&core->lock);
+			return inst;
+		}
+	}
+	mutex_unlock(&core->lock);
+
+	return NULL;
+}
diff --git a/drivers/media/platform/qcom/vcodec/iris/iris_helpers.h b/drivers/media/platform/qcom/vcodec/iris/iris_helpers.h
index fe85d23..cb22adf 100644
--- a/drivers/media/platform/qcom/vcodec/iris/iris_helpers.h
+++ b/drivers/media/platform/qcom/vcodec/iris/iris_helpers.h
@@ -31,6 +31,10 @@ bool is_linear_colorformat(u32 colorformat);
 bool is_10bit_colorformat(enum colorformat_type colorformat);
 bool is_8bit_colorformat(enum colorformat_type colorformat);
 bool is_split_mode_enabled(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);
+
 u32 v4l2_codec_from_driver(struct iris_inst *inst, enum codec_type codec);
 enum codec_type v4l2_codec_to_driver(struct iris_inst *inst, u32 v4l2_codec);
 u32 v4l2_colorformat_from_driver(struct iris_inst *inst, enum colorformat_type colorformat);
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 d4cdfcf..dc7157d 100644
--- a/drivers/media/platform/qcom/vcodec/iris/iris_hfi_packet.c
+++ b/drivers/media/platform/qcom/vcodec/iris/iris_hfi_packet.c
@@ -100,6 +100,201 @@ u32 get_hfi_colorformat(u32 colorformat)
 	return hfi_colorformat;
 }
 
+u32 get_hfi_color_primaries(u32 primaries)
+{
+	u32 hfi_primaries = HFI_PRIMARIES_RESERVED;
+
+	switch (primaries) {
+	case V4L2_COLORSPACE_DEFAULT:
+		hfi_primaries = HFI_PRIMARIES_RESERVED;
+		break;
+	case V4L2_COLORSPACE_REC709:
+		hfi_primaries = HFI_PRIMARIES_BT709;
+		break;
+	case V4L2_COLORSPACE_470_SYSTEM_M:
+		hfi_primaries = HFI_PRIMARIES_BT470_SYSTEM_M;
+		break;
+	case V4L2_COLORSPACE_470_SYSTEM_BG:
+		hfi_primaries = HFI_PRIMARIES_BT470_SYSTEM_BG;
+		break;
+	case V4L2_COLORSPACE_SMPTE170M:
+		hfi_primaries = HFI_PRIMARIES_BT601_525;
+		break;
+	case V4L2_COLORSPACE_SMPTE240M:
+		hfi_primaries = HFI_PRIMARIES_SMPTE_ST240M;
+		break;
+	case V4L2_COLORSPACE_BT2020:
+		hfi_primaries = HFI_PRIMARIES_BT2020;
+		break;
+	case V4L2_COLORSPACE_DCI_P3:
+		hfi_primaries = HFI_PRIMARIES_SMPTE_RP431_2;
+		break;
+	default:
+		break;
+	}
+
+	return hfi_primaries;
+}
+
+u32 get_hfi_transfer_char(u32 characterstics)
+{
+	u32 hfi_characterstics = HFI_TRANSFER_RESERVED;
+
+	switch (characterstics) {
+	case V4L2_XFER_FUNC_DEFAULT:
+		hfi_characterstics = HFI_TRANSFER_RESERVED;
+		break;
+	case V4L2_XFER_FUNC_709:
+		hfi_characterstics = HFI_TRANSFER_BT709;
+		break;
+	case V4L2_XFER_FUNC_SMPTE240M:
+		hfi_characterstics = HFI_TRANSFER_SMPTE_ST240M;
+		break;
+	case V4L2_XFER_FUNC_SRGB:
+		hfi_characterstics = HFI_TRANSFER_SRGB_SYCC;
+		break;
+	case V4L2_XFER_FUNC_SMPTE2084:
+		hfi_characterstics = HFI_TRANSFER_SMPTE_ST2084_PQ;
+		break;
+	default:
+		break;
+	}
+
+	return hfi_characterstics;
+}
+
+u32 get_hfi_matrix_coefficients(u32 coefficients)
+{
+	u32 hfi_coefficients = HFI_MATRIX_COEFF_RESERVED;
+
+	switch (coefficients) {
+	case V4L2_YCBCR_ENC_DEFAULT:
+		hfi_coefficients = HFI_MATRIX_COEFF_RESERVED;
+		break;
+	case V4L2_YCBCR_ENC_709:
+		hfi_coefficients = HFI_MATRIX_COEFF_BT709;
+		break;
+	case V4L2_YCBCR_ENC_XV709:
+		hfi_coefficients = HFI_MATRIX_COEFF_BT709;
+		break;
+	case V4L2_YCBCR_ENC_XV601:
+		hfi_coefficients = HFI_MATRIX_COEFF_BT470_SYS_BG_OR_BT601_625;
+		break;
+	case V4L2_YCBCR_ENC_601:
+		hfi_coefficients = HFI_MATRIX_COEFF_BT601_525_BT1358_525_OR_625;
+		break;
+	case V4L2_YCBCR_ENC_SMPTE240M:
+		hfi_coefficients = HFI_MATRIX_COEFF_SMPTE_ST240;
+		break;
+	case V4L2_YCBCR_ENC_BT2020:
+		hfi_coefficients = HFI_MATRIX_COEFF_BT2020_NON_CONSTANT;
+		break;
+	case V4L2_YCBCR_ENC_BT2020_CONST_LUM:
+		hfi_coefficients = HFI_MATRIX_COEFF_BT2020_CONSTANT;
+		break;
+	default:
+		break;
+	}
+
+	return hfi_coefficients;
+}
+
+u32 get_v4l2_color_primaries(u32 hfi_primaries)
+{
+	u32 primaries = V4L2_COLORSPACE_DEFAULT;
+
+	switch (hfi_primaries) {
+	case HFI_PRIMARIES_RESERVED:
+		primaries = V4L2_COLORSPACE_DEFAULT;
+		break;
+	case HFI_PRIMARIES_BT709:
+		primaries = V4L2_COLORSPACE_REC709;
+		break;
+	case HFI_PRIMARIES_BT470_SYSTEM_M:
+		primaries = V4L2_COLORSPACE_470_SYSTEM_M;
+		break;
+	case HFI_PRIMARIES_BT470_SYSTEM_BG:
+		primaries = V4L2_COLORSPACE_470_SYSTEM_BG;
+		break;
+	case HFI_PRIMARIES_BT601_525:
+		primaries = V4L2_COLORSPACE_SMPTE170M;
+		break;
+	case HFI_PRIMARIES_SMPTE_ST240M:
+		primaries = V4L2_COLORSPACE_SMPTE240M;
+		break;
+	case HFI_PRIMARIES_BT2020:
+		primaries = V4L2_COLORSPACE_BT2020;
+		break;
+	case V4L2_COLORSPACE_DCI_P3:
+		primaries = HFI_PRIMARIES_SMPTE_RP431_2;
+		break;
+	default:
+		break;
+	}
+
+	return primaries;
+}
+
+u32 get_v4l2_transfer_char(u32 hfi_characterstics)
+{
+	u32 characterstics = V4L2_XFER_FUNC_DEFAULT;
+
+	switch (hfi_characterstics) {
+	case HFI_TRANSFER_RESERVED:
+		characterstics = V4L2_XFER_FUNC_DEFAULT;
+		break;
+	case HFI_TRANSFER_BT709:
+		characterstics = V4L2_XFER_FUNC_709;
+		break;
+	case HFI_TRANSFER_SMPTE_ST240M:
+		characterstics = V4L2_XFER_FUNC_SMPTE240M;
+		break;
+	case HFI_TRANSFER_SRGB_SYCC:
+		characterstics = V4L2_XFER_FUNC_SRGB;
+		break;
+	case HFI_TRANSFER_SMPTE_ST2084_PQ:
+		characterstics = V4L2_XFER_FUNC_SMPTE2084;
+		break;
+	default:
+		break;
+	}
+
+	return characterstics;
+}
+
+u32 get_v4l2_matrix_coefficients(u32 hfi_coefficients)
+{
+	u32 coefficients = V4L2_YCBCR_ENC_DEFAULT;
+
+	switch (hfi_coefficients) {
+	case HFI_MATRIX_COEFF_RESERVED:
+		coefficients = V4L2_YCBCR_ENC_DEFAULT;
+		break;
+	case HFI_MATRIX_COEFF_BT709:
+		coefficients = V4L2_YCBCR_ENC_709;
+		break;
+	case HFI_MATRIX_COEFF_BT470_SYS_BG_OR_BT601_625:
+		coefficients = V4L2_YCBCR_ENC_XV601;
+		break;
+	case HFI_MATRIX_COEFF_BT601_525_BT1358_525_OR_625:
+		coefficients = V4L2_YCBCR_ENC_601;
+		break;
+	case HFI_MATRIX_COEFF_SMPTE_ST240:
+		coefficients = V4L2_YCBCR_ENC_SMPTE240M;
+		break;
+	case HFI_MATRIX_COEFF_BT2020_NON_CONSTANT:
+		coefficients = V4L2_YCBCR_ENC_BT2020;
+		break;
+	case HFI_MATRIX_COEFF_BT2020_CONSTANT:
+		coefficients = V4L2_YCBCR_ENC_BT2020_CONST_LUM;
+		break;
+	default:
+		break;
+	}
+
+	return coefficients;
+}
+
 int get_hfi_buffer(struct iris_buffer *buffer, struct hfi_buffer *buf)
 {
 	memset(buf, 0, sizeof(*buf));
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 4276d6d..f813116 100644
--- a/drivers/media/platform/qcom/vcodec/iris/iris_hfi_packet.h
+++ b/drivers/media/platform/qcom/vcodec/iris/iris_hfi_packet.h
@@ -80,10 +80,17 @@ enum hfi_packet_port_type {
 };
 
 u32 get_hfi_port_from_buffer_type(enum iris_buffer_type buffer_type);
-int get_hfi_buffer(struct iris_buffer *buffer, struct hfi_buffer *buf);
-u32 get_hfi_colorformat(u32 colorformat);
 u32 get_hfi_port(u32 plane);
 
+u32 get_hfi_colorformat(u32 colorformat);
+u32 get_hfi_color_primaries(u32 primaries);
+u32 get_hfi_transfer_char(u32 characterstics);
+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);
+int get_hfi_buffer(struct iris_buffer *buffer, struct hfi_buffer *buf);
+
 int hfi_packet_sys_init(struct iris_core *core,
 			u8 *pkt, u32 pkt_size);
 int hfi_packet_image_version(struct iris_core *core,
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 829f3f6..4ca9314 100644
--- a/drivers/media/platform/qcom/vcodec/iris/iris_hfi_response.c
+++ b/drivers/media/platform/qcom/vcodec/iris/iris_hfi_response.c
@@ -4,8 +4,27 @@
  */
 
 #include "hfi_defines.h"
+#include "iris_helpers.h"
 #include "iris_hfi_packet.h"
 #include "iris_hfi_response.h"
+#include "iris_vdec.h"
+
+struct iris_core_hfi_range {
+	u32 begin;
+	u32 end;
+	int (*handle)(struct iris_core *core, struct hfi_packet *pkt);
+};
+
+struct iris_inst_hfi_range {
+	u32 begin;
+	u32 end;
+	int (*handle)(struct iris_inst *inst, struct hfi_packet *pkt);
+};
+
+struct iris_hfi_packet_handle {
+	enum hfi_buffer_type type;
+	int (*handle)(struct iris_inst *inst, struct hfi_packet *pkt);
+};
 
 static void print_sfr_message(struct iris_core *core)
 {
@@ -25,8 +44,7 @@ static void print_sfr_message(struct iris_core *core)
 	}
 }
 
-static int validate_packet(u8 *response_pkt, u8 *core_resp_pkt,
-			   u32 core_resp_pkt_size)
+static int validate_packet(u8 *response_pkt, u8 *core_resp_pkt, u32 core_resp_pkt_size)
 {
 	u32 response_pkt_size = 0;
 	u8 *response_limit;
@@ -52,8 +70,7 @@ static int validate_packet(u8 *response_pkt, u8 *core_resp_pkt,
 	return 0;
 }
 
-static int validate_hdr_packet(struct iris_core *core,
-			       struct hfi_header *hdr)
+static int validate_hdr_packet(struct iris_core *core, struct hfi_header *hdr)
 {
 	struct hfi_packet *packet;
 	int i, ret = 0;
@@ -76,6 +93,45 @@ static int validate_hdr_packet(struct iris_core *core,
 	return ret;
 }
 
+static int handle_session_error(struct iris_inst *inst,
+				struct hfi_packet *pkt)
+{
+	struct iris_core *core;
+	char *error;
+
+	core = inst->core;
+
+	switch (pkt->type) {
+	case HFI_ERROR_MAX_SESSIONS:
+		error = "exceeded max sessions";
+		break;
+	case HFI_ERROR_UNKNOWN_SESSION:
+		error = "unknown session id";
+		break;
+	case HFI_ERROR_INVALID_STATE:
+		error = "invalid operation for current state";
+		break;
+	case HFI_ERROR_INSUFFICIENT_RESOURCES:
+		error = "insufficient resources";
+		break;
+	case HFI_ERROR_BUFFER_NOT_SET:
+		error = "internal buffers not set";
+		break;
+	case HFI_ERROR_FATAL:
+		error = "fatal error";
+		break;
+	default:
+		error = "unknown";
+		break;
+	}
+
+	dev_err(core->dev, "session error received %#x: %s\n",
+		pkt->type, error);
+	iris_inst_change_state(inst, IRIS_INST_ERROR);
+
+	return 0;
+}
+
 static int handle_system_error(struct iris_core *core,
 			       struct hfi_packet *pkt)
 {
@@ -86,6 +142,301 @@ static int handle_system_error(struct iris_core *core,
 	return 0;
 }
 
+static int handle_system_init(struct iris_core *core,
+			      struct hfi_packet *pkt)
+{
+	if (!(pkt->flags & HFI_FW_FLAGS_SUCCESS))
+		return 0;
+
+	mutex_lock(&core->lock);
+	if (pkt->packet_id != core->sys_init_id)
+		goto unlock;
+
+	iris_change_core_state(core, IRIS_CORE_INIT);
+
+unlock:
+	mutex_unlock(&core->lock);
+
+	return 0;
+}
+
+static int handle_session_close(struct iris_inst *inst,
+				struct hfi_packet *pkt)
+{
+	signal_session_msg_receipt(inst, SIGNAL_CMD_CLOSE);
+
+	return 0;
+}
+
+static int handle_src_change(struct iris_inst *inst,
+			     struct hfi_packet *pkt)
+{
+	int ret = 0;
+
+	if (pkt->port == HFI_PORT_BITSTREAM)
+		ret = vdec_src_change(inst);
+	else if (pkt->port == HFI_PORT_RAW)
+		ret = 0;
+
+	if (ret)
+		iris_inst_change_state(inst, IRIS_INST_ERROR);
+
+	return ret;
+}
+
+static int handle_session_command(struct iris_inst *inst,
+				  struct hfi_packet *pkt)
+{
+	int i, ret = 0;
+	static const struct iris_hfi_packet_handle hfi_pkt_handle[] = {
+		{HFI_CMD_OPEN,              NULL                    },
+		{HFI_CMD_CLOSE,             handle_session_close    },
+		{HFI_CMD_SETTINGS_CHANGE,   handle_src_change       },
+		{HFI_CMD_SUBSCRIBE_MODE,    NULL                    },
+	};
+
+	for (i = 0; i < ARRAY_SIZE(hfi_pkt_handle); i++) {
+		if (hfi_pkt_handle[i].type == pkt->type) {
+			if (hfi_pkt_handle[i].handle) {
+				ret = hfi_pkt_handle[i].handle(inst, pkt);
+				if (ret)
+					return ret;
+			}
+			break;
+		}
+	}
+
+	if (i == ARRAY_SIZE(hfi_pkt_handle))
+		return -EINVAL;
+
+	return ret;
+}
+
+static int handle_dpb_list_property(struct iris_inst *inst,
+				    struct hfi_packet *pkt)
+{
+	u8 *payload_start;
+	u32 payload_size;
+
+	payload_size = pkt->size - sizeof(*pkt);
+	payload_start = (u8 *)((u8 *)pkt + sizeof(*pkt));
+	memset(inst->dpb_list_payload, 0, MAX_DPB_LIST_ARRAY_SIZE);
+
+	if (payload_size > MAX_DPB_LIST_PAYLOAD_SIZE) {
+		iris_inst_change_state(inst, IRIS_INST_ERROR);
+		return -EINVAL;
+	}
+
+	memcpy(inst->dpb_list_payload, payload_start, payload_size);
+
+	return 0;
+}
+
+static int handle_session_property(struct iris_inst *inst,
+				   struct hfi_packet *pkt)
+{
+	u32 *payload_ptr = NULL;
+	int ret = 0;
+
+	if (pkt->port != HFI_PORT_BITSTREAM)
+		return 0;
+
+	if (pkt->flags & HFI_FW_FLAGS_INFORMATION)
+		return 0;
+
+	payload_ptr = (u32 *)((u8 *)pkt + sizeof(*pkt));
+	if (!payload_ptr)
+		return -EINVAL;
+
+	switch (pkt->type) {
+	case HFI_PROP_BITSTREAM_RESOLUTION:
+		inst->src_subcr_params.bitstream_resolution = payload_ptr[0];
+		break;
+	case HFI_PROP_CROP_OFFSETS:
+		inst->src_subcr_params.crop_offsets[0] = payload_ptr[0];
+		inst->src_subcr_params.crop_offsets[1] = payload_ptr[1];
+		break;
+	case HFI_PROP_LUMA_CHROMA_BIT_DEPTH:
+		inst->src_subcr_params.bit_depth = payload_ptr[0];
+		break;
+	case HFI_PROP_CODED_FRAMES:
+		inst->src_subcr_params.coded_frames = payload_ptr[0];
+		break;
+	case HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT:
+		inst->src_subcr_params.fw_min_count = payload_ptr[0];
+		break;
+	case HFI_PROP_PIC_ORDER_CNT_TYPE:
+		inst->src_subcr_params.pic_order_cnt = payload_ptr[0];
+		break;
+	case HFI_PROP_SIGNAL_COLOR_INFO:
+		inst->src_subcr_params.color_info = payload_ptr[0];
+		break;
+	case HFI_PROP_PROFILE:
+		inst->src_subcr_params.profile = payload_ptr[0];
+		break;
+	case HFI_PROP_LEVEL:
+		inst->src_subcr_params.level = payload_ptr[0];
+		break;
+	case HFI_PROP_TIER:
+		inst->src_subcr_params.tier = payload_ptr[0];
+		break;
+	case HFI_PROP_PICTURE_TYPE:
+		inst->hfi_frame_info.picture_type = payload_ptr[0];
+		break;
+	case HFI_PROP_DPB_LIST:
+		ret = handle_dpb_list_property(inst, pkt);
+		if (ret)
+			break;
+		break;
+	case HFI_PROP_NO_OUTPUT:
+		inst->hfi_frame_info.no_output = 1;
+		break;
+	case HFI_PROP_QUALITY_MODE:
+	case HFI_PROP_STAGE:
+	case HFI_PROP_PIPE:
+		break;
+	default:
+		break;
+	}
+
+	return ret;
+}
+
+static int handle_image_version_property(struct iris_core *core,
+					 struct hfi_packet *pkt)
+{
+	u8 *str_image_version;
+	u32 req_bytes;
+	u32 i = 0;
+
+	req_bytes = pkt->size - sizeof(*pkt);
+	if (req_bytes < IRIS_VERSION_LENGTH - 1)
+		return -EINVAL;
+
+	str_image_version = (u8 *)pkt + sizeof(*pkt);
+
+	for (i = 0; i < IRIS_VERSION_LENGTH - 1; i++) {
+		if (str_image_version[i] != '\0')
+			core->fw_version[i] = str_image_version[i];
+		else
+			core->fw_version[i] = ' ';
+	}
+	core->fw_version[i] = '\0';
+
+	return 0;
+}
+
+static int handle_system_property(struct iris_core *core,
+				  struct hfi_packet *pkt)
+{
+	int ret = 0;
+
+	switch (pkt->type) {
+	case HFI_PROP_IMAGE_VERSION:
+		ret = handle_image_version_property(core, pkt);
+		break;
+	default:
+		break;
+	}
+
+	return ret;
+}
+
+static int handle_system_response(struct iris_core *core,
+				  struct hfi_header *hdr)
+{
+	struct hfi_packet *packet;
+	u8 *pkt, *start_pkt;
+	int ret = 0;
+	int i, j;
+	static const struct iris_core_hfi_range be[] = {
+		{HFI_SYSTEM_ERROR_BEGIN,   HFI_SYSTEM_ERROR_END,   handle_system_error     },
+		{HFI_PROP_BEGIN,           HFI_PROP_END,           handle_system_property  },
+		{HFI_CMD_BEGIN,            HFI_CMD_END,            handle_system_init      },
+	};
+
+	start_pkt = (u8 *)((u8 *)hdr + sizeof(*hdr));
+	for (i = 0; i < ARRAY_SIZE(be); i++) {
+		pkt = start_pkt;
+		for (j = 0; j < hdr->num_packets; j++) {
+			packet = (struct hfi_packet *)pkt;
+			if (packet->flags & HFI_FW_FLAGS_SYSTEM_ERROR) {
+				ret = handle_system_error(core, packet);
+				return ret;
+			}
+
+			if (packet->type > be[i].begin && packet->type < be[i].end) {
+				ret = be[i].handle(core, packet);
+				if (ret)
+					return ret;
+
+				if (packet->type >  HFI_SYSTEM_ERROR_BEGIN &&
+				    packet->type < HFI_SYSTEM_ERROR_END)
+					return 0;
+			}
+			pkt += packet->size;
+		}
+	}
+
+	return ret;
+}
+
+static int handle_session_response(struct iris_core *core,
+				   struct hfi_header *hdr)
+{
+	struct hfi_packet *packet;
+	struct iris_inst *inst;
+	u8 *pkt, *start_pkt;
+	int ret = 0;
+	int i, j;
+	static const struct iris_inst_hfi_range be[] = {
+		{HFI_SESSION_ERROR_BEGIN,  HFI_SESSION_ERROR_END,  handle_session_error    },
+		{HFI_PROP_BEGIN,           HFI_PROP_END,           handle_session_property },
+		{HFI_CMD_BEGIN,            HFI_CMD_END,            handle_session_command  },
+	};
+
+	inst = to_instance(core, hdr->session_id);
+	if (!inst)
+		return -EINVAL;
+
+	mutex_lock(&inst->lock);
+	memset(&inst->hfi_frame_info, 0, sizeof(struct iris_hfi_frame_info));
+
+	pkt = (u8 *)((u8 *)hdr + sizeof(*hdr));
+	for (i = 0; i < hdr->num_packets; i++) {
+		packet = (struct hfi_packet *)pkt;
+		if (packet->type == HFI_CMD_SETTINGS_CHANGE) {
+			if (packet->port == HFI_PORT_BITSTREAM) {
+				vdec_init_src_change_param(inst);
+				break;
+			}
+		}
+		pkt += packet->size;
+	}
+
+	start_pkt = (u8 *)((u8 *)hdr + sizeof(*hdr));
+	for (i = 0; i < ARRAY_SIZE(be); i++) {
+		pkt = start_pkt;
+		for (j = 0; j < hdr->num_packets; j++) {
+			packet = (struct hfi_packet *)pkt;
+			if (packet->flags & HFI_FW_FLAGS_SESSION_ERROR)
+				handle_session_error(inst, packet);
+
+			if (packet->type > be[i].begin && packet->type < be[i].end) {
+				ret = be[i].handle(inst, packet);
+				if (ret)
+					iris_inst_change_state(inst, IRIS_INST_ERROR);
+			}
+			pkt += packet->size;
+		}
+	}
+
+	memset(&inst->hfi_frame_info, 0, sizeof(struct iris_hfi_frame_info));
+	mutex_unlock(&inst->lock);
+
+	return ret;
+}
+
 static int handle_response(struct iris_core *core, void *response)
 {
 	struct hfi_header *hdr;
@@ -96,6 +447,11 @@ static int handle_response(struct iris_core *core, void *response)
 	if (ret)
 		return handle_system_error(core, NULL);
 
+	if (!hdr->session_id)
+		return handle_system_response(core, hdr);
+	else
+		return handle_session_response(core, hdr);
+
 	return ret;
 }
 
diff --git a/drivers/media/platform/qcom/vcodec/iris/iris_instance.h b/drivers/media/platform/qcom/vcodec/iris/iris_instance.h
index 365f844..4f51d68 100644
--- a/drivers/media/platform/qcom/vcodec/iris/iris_instance.h
+++ b/drivers/media/platform/qcom/vcodec/iris/iris_instance.h
@@ -40,6 +40,10 @@
  * @fw_min_count: minimnum count of buffers needed by fw
  * @state: instance state
  * @ipsc_properties_set: boolean to set ipsc properties to fw
+ * @hfi_frame_info: structure of frame info
+ * @src_subcr_params: subscription params to fw on input port
+ * @dst_subcr_params: subscription params to fw on output port
+ * @dpb_list_payload: array of dpb buffers
  */
 
 struct iris_inst {
@@ -66,6 +70,10 @@ struct iris_inst {
 	u32				fw_min_count;
 	enum iris_inst_state		state;
 	bool				ipsc_properties_set;
+	struct iris_hfi_frame_info	hfi_frame_info;
+	struct subscription_params	src_subcr_params;
+	struct subscription_params	dst_subcr_params;
+	u32				dpb_list_payload[MAX_DPB_LIST_ARRAY_SIZE];
 };
 
 #endif
diff --git a/drivers/media/platform/qcom/vcodec/iris/iris_vdec.c b/drivers/media/platform/qcom/vcodec/iris/iris_vdec.c
index 7d16c96..ac47fc0 100644
--- a/drivers/media/platform/qcom/vcodec/iris/iris_vdec.c
+++ b/drivers/media/platform/qcom/vcodec/iris/iris_vdec.c
@@ -14,6 +14,13 @@
 #include "iris_hfi_packet.h"
 #include "iris_vdec.h"
 
+#define UNSPECIFIED_COLOR_FORMAT 5
+
+struct vdec_prop_type_handle {
+	u32 type;
+	int (*handle)(struct iris_inst *inst);
+};
+
 static int vdec_codec_change(struct iris_inst *inst, u32 v4l2_codec)
 {
 	bool session_init = false;
@@ -376,6 +383,455 @@ int vdec_subscribe_property(struct iris_inst *inst, u32 plane)
 					(subscribe_prop_size + 1) * sizeof(u32));
 }
 
+static int vdec_set_bitstream_resolution(struct iris_inst *inst)
+{
+	u32 resolution;
+
+	resolution = inst->fmt_src->fmt.pix_mp.width << 16 |
+		inst->fmt_src->fmt.pix_mp.height;
+	inst->src_subcr_params.bitstream_resolution = resolution;
+
+	return iris_hfi_set_property(inst,
+					HFI_PROP_BITSTREAM_RESOLUTION,
+					HFI_HOST_FLAGS_NONE,
+					get_hfi_port(INPUT_MPLANE),
+					HFI_PAYLOAD_U32,
+					&resolution,
+					sizeof(u32));
+}
+
+static int vdec_set_crop_offsets(struct iris_inst *inst)
+{
+	u32 left_offset, top_offset, right_offset, bottom_offset;
+	u32 payload[2] = {0};
+
+	left_offset = inst->crop.left;
+	top_offset = inst->crop.top;
+	right_offset = (inst->fmt_src->fmt.pix_mp.width -
+		inst->crop.width);
+	bottom_offset = (inst->fmt_src->fmt.pix_mp.height -
+		inst->crop.height);
+
+	payload[0] = left_offset << 16 | top_offset;
+	payload[1] = right_offset << 16 | bottom_offset;
+	inst->src_subcr_params.crop_offsets[0] = payload[0];
+	inst->src_subcr_params.crop_offsets[1] = payload[1];
+
+	return iris_hfi_set_property(inst,
+					HFI_PROP_CROP_OFFSETS,
+					HFI_HOST_FLAGS_NONE,
+					get_hfi_port(INPUT_MPLANE),
+					HFI_PAYLOAD_64_PACKED,
+					&payload,
+					sizeof(u64));
+}
+
+static int vdec_set_bit_depth(struct iris_inst *inst)
+{
+	u32 bitdepth = 8 << 16 | 8;
+	u32 pix_fmt;
+
+	pix_fmt = inst->fmt_dst->fmt.pix_mp.pixelformat;
+	if (is_10bit_colorformat(pix_fmt))
+		bitdepth = 10 << 16 | 10;
+
+	inst->src_subcr_params.bit_depth = bitdepth;
+	inst->cap[BIT_DEPTH].value = bitdepth;
+
+	return iris_hfi_set_property(inst,
+					HFI_PROP_LUMA_CHROMA_BIT_DEPTH,
+					HFI_HOST_FLAGS_NONE,
+					get_hfi_port(INPUT_MPLANE),
+					HFI_PAYLOAD_U32,
+					&bitdepth,
+					sizeof(u32));
+}
+
+static int vdec_set_coded_frames(struct iris_inst *inst)
+{
+	u32 coded_frames = 0;
+
+	if (inst->cap[CODED_FRAMES].value == CODED_FRAMES_PROGRESSIVE)
+		coded_frames = HFI_BITMASK_FRAME_MBS_ONLY_FLAG;
+	inst->src_subcr_params.coded_frames = coded_frames;
+
+	return iris_hfi_set_property(inst,
+					HFI_PROP_CODED_FRAMES,
+					HFI_HOST_FLAGS_NONE,
+					get_hfi_port(INPUT_MPLANE),
+					HFI_PAYLOAD_U32,
+					&coded_frames,
+					sizeof(u32));
+}
+
+static int vdec_set_min_output_count(struct iris_inst *inst)
+{
+	u32 min_output;
+
+	min_output = inst->buffers.output.min_count;
+	inst->src_subcr_params.fw_min_count = min_output;
+
+	return iris_hfi_set_property(inst,
+					HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT,
+					HFI_HOST_FLAGS_NONE,
+					get_hfi_port(INPUT_MPLANE),
+					HFI_PAYLOAD_U32,
+					&min_output,
+					sizeof(u32));
+}
+
+static int vdec_set_picture_order_count(struct iris_inst *inst)
+{
+	u32 poc = 0;
+
+	inst->src_subcr_params.pic_order_cnt = poc;
+
+	return iris_hfi_set_property(inst,
+					HFI_PROP_PIC_ORDER_CNT_TYPE,
+					HFI_HOST_FLAGS_NONE,
+					get_hfi_port(INPUT_MPLANE),
+					HFI_PAYLOAD_U32,
+					&poc,
+					sizeof(u32));
+}
+
+static int vdec_set_colorspace(struct iris_inst *inst)
+{
+	u32 video_signal_type_present_flag = 0, color_info = 0;
+	u32 matrix_coeff = HFI_MATRIX_COEFF_RESERVED;
+	u32 video_format = UNSPECIFIED_COLOR_FORMAT;
+	struct v4l2_pix_format_mplane *pixmp = NULL;
+	u32 full_range = V4L2_QUANTIZATION_DEFAULT;
+	u32 transfer_char = HFI_TRANSFER_RESERVED;
+	u32 colour_description_present_flag = 0;
+	u32 primaries = HFI_PRIMARIES_RESERVED;
+
+	int ret;
+
+	if (inst->codec == VP9)
+		return 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;
+	}
+
+	color_info = (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);
+
+	inst->src_subcr_params.color_info = color_info;
+
+	ret = iris_hfi_set_property(inst,
+				    HFI_PROP_SIGNAL_COLOR_INFO,
+				    HFI_HOST_FLAGS_NONE,
+				    get_hfi_port(INPUT_MPLANE),
+				    HFI_PAYLOAD_32_PACKED,
+				    &color_info,
+				    sizeof(u32));
+
+	return ret;
+}
+
+static int vdec_set_profile(struct iris_inst *inst)
+{
+	u32 profile;
+
+	profile = inst->cap[PROFILE].value;
+	inst->src_subcr_params.profile = profile;
+
+	return iris_hfi_set_property(inst,
+				     HFI_PROP_PROFILE,
+				     HFI_HOST_FLAGS_NONE,
+				     get_hfi_port(INPUT_MPLANE),
+				     HFI_PAYLOAD_U32_ENUM,
+				     &profile,
+				     sizeof(u32));
+}
+
+static int vdec_set_level(struct iris_inst *inst)
+{
+	u32 level;
+
+	level = inst->cap[LEVEL].value;
+	inst->src_subcr_params.level = level;
+
+	return iris_hfi_set_property(inst,
+				     HFI_PROP_LEVEL,
+				     HFI_HOST_FLAGS_NONE,
+				     get_hfi_port(INPUT_MPLANE),
+				     HFI_PAYLOAD_U32_ENUM,
+				     &level,
+				     sizeof(u32));
+}
+
+static int vdec_set_tier(struct iris_inst *inst)
+{
+	u32 tier;
+
+	tier = inst->cap[HEVC_TIER].value;
+	inst->src_subcr_params.tier = tier;
+
+	return iris_hfi_set_property(inst,
+				     HFI_PROP_TIER,
+				     HFI_HOST_FLAGS_NONE,
+				     get_hfi_port(INPUT_MPLANE),
+				     HFI_PAYLOAD_U32_ENUM,
+				     &tier,
+				     sizeof(u32));
+}
+
+int vdec_subscribe_src_change_param(struct iris_inst *inst)
+{
+	const u32 *src_change_param;
+	u32 src_change_param_size;
+	struct iris_core *core;
+	u32 payload[32] = {0};
+	int ret;
+	u32 i, j;
+
+	static const struct vdec_prop_type_handle prop_type_handle_arr[] = {
+		{HFI_PROP_BITSTREAM_RESOLUTION,          vdec_set_bitstream_resolution   },
+		{HFI_PROP_CROP_OFFSETS,                  vdec_set_crop_offsets           },
+		{HFI_PROP_LUMA_CHROMA_BIT_DEPTH,         vdec_set_bit_depth              },
+		{HFI_PROP_CODED_FRAMES,                  vdec_set_coded_frames           },
+		{HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT,    vdec_set_min_output_count       },
+		{HFI_PROP_PIC_ORDER_CNT_TYPE,            vdec_set_picture_order_count    },
+		{HFI_PROP_SIGNAL_COLOR_INFO,             vdec_set_colorspace             },
+		{HFI_PROP_PROFILE,                       vdec_set_profile                },
+		{HFI_PROP_LEVEL,                         vdec_set_level                  },
+		{HFI_PROP_TIER,                          vdec_set_tier                   },
+	};
+
+	core = inst->core;
+
+	payload[0] = HFI_MODE_PORT_SETTINGS_CHANGE;
+	if (inst->codec == H264) {
+		src_change_param_size = core->platform_data->avc_subscribe_param_size;
+		src_change_param = core->platform_data->avc_subscribe_param;
+	} else if (inst->codec == HEVC) {
+		src_change_param_size = core->platform_data->hevc_subscribe_param_size;
+		src_change_param = core->platform_data->hevc_subscribe_param;
+	} else if (inst->codec == VP9) {
+		src_change_param_size = core->platform_data->vp9_subscribe_param_size;
+		src_change_param = core->platform_data->vp9_subscribe_param;
+	} else {
+		src_change_param = NULL;
+		return -EINVAL;
+	}
+
+	if (!src_change_param || !src_change_param_size)
+		return -EINVAL;
+
+	for (i = 0; i < src_change_param_size; i++)
+		payload[i + 1] = src_change_param[i];
+
+	ret = iris_hfi_session_subscribe_mode(inst,
+					      HFI_CMD_SUBSCRIBE_MODE,
+					      INPUT_MPLANE,
+					      HFI_PAYLOAD_U32_ARRAY,
+					      &payload[0],
+					      ((src_change_param_size + 1) * sizeof(u32)));
+	if (ret)
+		return ret;
+
+	for (i = 0; i < src_change_param_size; i++) {
+		for (j = 0; j < ARRAY_SIZE(prop_type_handle_arr); j++) {
+			if (prop_type_handle_arr[j].type == src_change_param[i]) {
+				ret = prop_type_handle_arr[j].handle(inst);
+				if (ret)
+					return ret;
+				break;
+			}
+		}
+	}
+
+	return ret;
+}
+
+int vdec_init_src_change_param(struct iris_inst *inst)
+{
+	u32 left_offset, top_offset, right_offset, bottom_offset;
+	struct v4l2_pix_format_mplane *pixmp_ip, *pixmp_op;
+	u32 primaries, matrix_coeff, transfer_char;
+	struct subscription_params *subsc_params;
+	u32 colour_description_present_flag = 0;
+	u32 video_signal_type_present_flag = 0;
+	u32 full_range = 0, video_format = 0;
+
+	subsc_params = &inst->src_subcr_params;
+	pixmp_ip = &inst->fmt_src->fmt.pix_mp;
+	pixmp_op = &inst->fmt_dst->fmt.pix_mp;
+
+	subsc_params->bitstream_resolution =
+		pixmp_ip->width << 16 | pixmp_ip->height;
+
+	left_offset = inst->crop.left;
+	top_offset = inst->crop.top;
+	right_offset = (pixmp_ip->width - inst->crop.width);
+	bottom_offset = (pixmp_ip->height - inst->crop.height);
+	subsc_params->crop_offsets[0] =
+			left_offset << 16 | top_offset;
+	subsc_params->crop_offsets[1] =
+			right_offset << 16 | bottom_offset;
+
+	subsc_params->fw_min_count = inst->buffers.output.min_count;
+
+	primaries = get_hfi_color_primaries(pixmp_op->colorspace);
+	matrix_coeff = get_hfi_matrix_coefficients(pixmp_op->ycbcr_enc);
+	transfer_char = get_hfi_transfer_char(pixmp_op->xfer_func);
+	full_range = pixmp_op->quantization == V4L2_QUANTIZATION_FULL_RANGE ? 1 : 0;
+	subsc_params->color_info =
+		(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);
+
+	subsc_params->profile = inst->cap[PROFILE].value;
+	subsc_params->level = inst->cap[LEVEL].value;
+	subsc_params->tier = inst->cap[HEVC_TIER].value;
+	subsc_params->pic_order_cnt = inst->cap[POC].value;
+	subsc_params->bit_depth = inst->cap[BIT_DEPTH].value;
+	if (inst->cap[CODED_FRAMES].value ==
+			CODED_FRAMES_PROGRESSIVE)
+		subsc_params->coded_frames = HFI_BITMASK_FRAME_MBS_ONLY_FLAG;
+	else
+		subsc_params->coded_frames = 0;
+
+	return 0;
+}
+
+static int vdec_read_input_subcr_params(struct iris_inst *inst)
+{
+	struct v4l2_pix_format_mplane *pixmp_ip, *pixmp_op;
+	u32 primaries, matrix_coeff, transfer_char;
+	struct subscription_params subsc_params;
+	u32 colour_description_present_flag = 0;
+	u32 video_signal_type_present_flag = 0;
+	u32 full_range = 0;
+	u32 width, height;
+
+	subsc_params = inst->src_subcr_params;
+	pixmp_ip = &inst->fmt_src->fmt.pix_mp;
+	pixmp_op = &inst->fmt_dst->fmt.pix_mp;
+	width = (subsc_params.bitstream_resolution &
+		HFI_BITMASK_BITSTREAM_WIDTH) >> 16;
+	height = subsc_params.bitstream_resolution &
+		HFI_BITMASK_BITSTREAM_HEIGHT;
+
+	pixmp_ip->width = width;
+	pixmp_ip->height = height;
+
+	pixmp_op->width = pixmp_op->pixelformat == V4L2_PIX_FMT_QC10C ?
+		ALIGN(width, 192) : ALIGN(width, 128);
+	pixmp_op->height = pixmp_op->pixelformat == V4L2_PIX_FMT_QC10C ?
+		ALIGN(height, 16) : ALIGN(height, 32);
+	pixmp_op->plane_fmt[0].bytesperline =
+		pixmp_op->pixelformat == V4L2_PIX_FMT_QC10C ?
+		ALIGN(ALIGN(width, 192) * 4 / 3, 256) :
+		ALIGN(width, 128);
+	pixmp_op->plane_fmt[0].sizeimage = iris_get_buffer_size(inst, BUF_OUTPUT);
+
+	matrix_coeff = subsc_params.color_info & 0xFF;
+	transfer_char = (subsc_params.color_info & 0xFF00) >> 8;
+	primaries = (subsc_params.color_info & 0xFF0000) >> 16;
+	colour_description_present_flag =
+		(subsc_params.color_info & 0x1000000) >> 24;
+	full_range = (subsc_params.color_info & 0x2000000) >> 25;
+	video_signal_type_present_flag =
+		(subsc_params.color_info & 0x20000000) >> 29;
+
+	pixmp_op->colorspace = V4L2_COLORSPACE_DEFAULT;
+	pixmp_op->xfer_func = V4L2_XFER_FUNC_DEFAULT;
+	pixmp_op->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
+	pixmp_op->quantization = V4L2_QUANTIZATION_DEFAULT;
+
+	if (video_signal_type_present_flag) {
+		pixmp_op->quantization =
+			full_range ?
+			V4L2_QUANTIZATION_FULL_RANGE :
+			V4L2_QUANTIZATION_LIM_RANGE;
+		if (colour_description_present_flag) {
+			pixmp_op->colorspace =
+				get_v4l2_color_primaries(primaries);
+			pixmp_op->xfer_func =
+				get_v4l2_transfer_char(transfer_char);
+			pixmp_op->ycbcr_enc =
+				get_v4l2_matrix_coefficients(matrix_coeff);
+		}
+	}
+
+	pixmp_ip->colorspace = pixmp_op->colorspace;
+	pixmp_ip->xfer_func = pixmp_op->xfer_func;
+	pixmp_ip->ycbcr_enc = pixmp_op->ycbcr_enc;
+	pixmp_ip->quantization = pixmp_op->quantization;
+
+	inst->crop.top = subsc_params.crop_offsets[0] & 0xFFFF;
+	inst->crop.left = (subsc_params.crop_offsets[0] >> 16) & 0xFFFF;
+	inst->crop.height = pixmp_ip->height -
+		(subsc_params.crop_offsets[1] & 0xFFFF) - inst->crop.top;
+	inst->crop.width = pixmp_ip->width -
+		((subsc_params.crop_offsets[1] >> 16) & 0xFFFF) - inst->crop.left;
+
+	inst->cap[PROFILE].value = subsc_params.profile;
+	inst->cap[LEVEL].value = subsc_params.level;
+	inst->cap[HEVC_TIER].value = subsc_params.tier;
+	inst->cap[POC].value = subsc_params.pic_order_cnt;
+
+	if (subsc_params.bit_depth == BIT_DEPTH_8)
+		inst->cap[BIT_DEPTH].value = BIT_DEPTH_8;
+	else
+		inst->cap[BIT_DEPTH].value = BIT_DEPTH_10;
+
+	if (subsc_params.coded_frames & HFI_BITMASK_FRAME_MBS_ONLY_FLAG)
+		inst->cap[CODED_FRAMES].value = CODED_FRAMES_PROGRESSIVE;
+	else
+		inst->cap[CODED_FRAMES].value = CODED_FRAMES_INTERLACE;
+
+	inst->fw_min_count = subsc_params.fw_min_count;
+	inst->buffers.output.min_count = iris_get_buf_min_count(inst, BUF_OUTPUT);
+
+	return 0;
+}
+
+int vdec_src_change(struct iris_inst *inst)
+{
+	struct v4l2_event event = {0};
+	u32 ret;
+
+	if (!inst->vb2q_src->streaming)
+		return 0;
+
+	ret = vdec_read_input_subcr_params(inst);
+	if (ret)
+		return ret;
+
+	event.type = V4L2_EVENT_SOURCE_CHANGE;
+	event.u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION;
+	v4l2_event_queue_fh(&inst->fh, &event);
+
+	return ret;
+}
+
 static int vdec_set_colorformat(struct iris_inst *inst)
 {
 	u32 hfi_colorformat;
@@ -483,3 +939,127 @@ int vdec_set_output_property(struct iris_inst *inst)
 
 	return vdec_set_ubwc_stride_scanline(inst);
 }
+
+int vdec_subscribe_dst_change_param(struct iris_inst *inst)
+{
+	u32 prop_type, payload_size, payload_type;
+	struct subscription_params subsc_params;
+	const u32 *dst_change_param = NULL;
+	u32 dst_change_param_size = 0;
+	struct iris_core *core;
+	u32 payload[32] = {0};
+	int ret;
+	u32 i;
+
+	core = inst->core;
+
+	payload[0] = HFI_MODE_PORT_SETTINGS_CHANGE;
+	if (inst->codec == H264) {
+		dst_change_param_size = core->platform_data->avc_subscribe_param_size;
+		dst_change_param = core->platform_data->avc_subscribe_param;
+	} else if (inst->codec == HEVC) {
+		dst_change_param_size = core->platform_data->hevc_subscribe_param_size;
+		dst_change_param = core->platform_data->hevc_subscribe_param;
+	} else if (inst->codec == VP9) {
+		dst_change_param_size = core->platform_data->vp9_subscribe_param_size;
+		dst_change_param = core->platform_data->vp9_subscribe_param;
+	} else {
+		dst_change_param = NULL;
+		return -EINVAL;
+	}
+
+	if (!dst_change_param || !dst_change_param_size)
+		return -EINVAL;
+
+	payload[0] = HFI_MODE_PORT_SETTINGS_CHANGE;
+	for (i = 0; i < dst_change_param_size; i++)
+		payload[i + 1] = dst_change_param[i];
+
+	ret = iris_hfi_session_subscribe_mode(inst,
+					      HFI_CMD_SUBSCRIBE_MODE,
+					      OUTPUT_MPLANE,
+					      HFI_PAYLOAD_U32_ARRAY,
+					      &payload[0],
+					      ((dst_change_param_size + 1) * sizeof(u32)));
+	if (ret)
+		return ret;
+
+	subsc_params = inst->dst_subcr_params;
+	for (i = 0; i < dst_change_param_size; i++) {
+		payload[0] = 0;
+		payload[1] = 0;
+		payload_size = 0;
+		payload_type = 0;
+		prop_type = dst_change_param[i];
+		switch (prop_type) {
+		case HFI_PROP_BITSTREAM_RESOLUTION:
+			payload[0] = subsc_params.bitstream_resolution;
+			payload_size = sizeof(u32);
+			payload_type = HFI_PAYLOAD_U32;
+			break;
+		case HFI_PROP_CROP_OFFSETS:
+			payload[0] = subsc_params.crop_offsets[0];
+			payload[1] = subsc_params.crop_offsets[1];
+			payload_size = sizeof(u64);
+			payload_type = HFI_PAYLOAD_64_PACKED;
+			break;
+		case HFI_PROP_LUMA_CHROMA_BIT_DEPTH:
+			payload[0] = subsc_params.bit_depth;
+			payload_size = sizeof(u32);
+			payload_type = HFI_PAYLOAD_U32;
+			break;
+		case HFI_PROP_CODED_FRAMES:
+			payload[0] = subsc_params.coded_frames;
+			payload_size = sizeof(u32);
+			payload_type = HFI_PAYLOAD_U32;
+			break;
+		case HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT:
+			payload[0] = subsc_params.fw_min_count;
+			payload_size = sizeof(u32);
+			payload_type = HFI_PAYLOAD_U32;
+			break;
+		case HFI_PROP_PIC_ORDER_CNT_TYPE:
+			payload[0] = subsc_params.pic_order_cnt;
+			payload_size = sizeof(u32);
+			payload_type = HFI_PAYLOAD_U32;
+			break;
+		case HFI_PROP_SIGNAL_COLOR_INFO:
+			payload[0] = subsc_params.color_info;
+			payload_size = sizeof(u32);
+			payload_type = HFI_PAYLOAD_U32;
+			break;
+		case HFI_PROP_PROFILE:
+			payload[0] = subsc_params.profile;
+			payload_size = sizeof(u32);
+			payload_type = HFI_PAYLOAD_U32;
+			break;
+		case HFI_PROP_LEVEL:
+			payload[0] = subsc_params.level;
+			payload_size = sizeof(u32);
+			payload_type = HFI_PAYLOAD_U32;
+			break;
+		case HFI_PROP_TIER:
+			payload[0] = subsc_params.tier;
+			payload_size = sizeof(u32);
+			payload_type = HFI_PAYLOAD_U32;
+			break;
+		default:
+			prop_type = 0;
+			ret = -EINVAL;
+			break;
+		}
+		if (prop_type) {
+			ret = iris_hfi_set_property(inst,
+						    prop_type,
+						    HFI_HOST_FLAGS_NONE,
+						    get_hfi_port(OUTPUT_MPLANE),
+						    payload_type,
+						    &payload,
+						    payload_size);
+			if (ret)
+				return ret;
+		}
+	}
+
+	return ret;
+}
diff --git a/drivers/media/platform/qcom/vcodec/iris/iris_vdec.h b/drivers/media/platform/qcom/vcodec/iris/iris_vdec.h
index 6b0306c..e0db653 100644
--- a/drivers/media/platform/qcom/vcodec/iris/iris_vdec.h
+++ b/drivers/media/platform/qcom/vcodec/iris/iris_vdec.h
@@ -16,5 +16,9 @@ int vdec_s_fmt(struct iris_inst *inst, struct v4l2_format *f);
 int vdec_subscribe_event(struct iris_inst *inst, const struct v4l2_event_subscription *sub);
 int vdec_subscribe_property(struct iris_inst *inst, u32 plane);
 int vdec_set_output_property(struct iris_inst *inst);
+int vdec_init_src_change_param(struct iris_inst *inst);
+int vdec_src_change(struct iris_inst *inst);
+int vdec_subscribe_src_change_param(struct iris_inst *inst);
+int vdec_subscribe_dst_change_param(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 fc12bde..22a8f5b 100644
--- a/drivers/media/platform/qcom/vcodec/iris/platform_common.h
+++ b/drivers/media/platform/qcom/vcodec/iris/platform_common.h
@@ -206,6 +206,12 @@ struct platform_data {
 	u32 core_data_size;
 	struct plat_inst_cap *inst_cap_data;
 	u32 inst_cap_data_size;
+	const u32 *avc_subscribe_param;
+	unsigned int avc_subscribe_param_size;
+	const u32 *hevc_subscribe_param;
+	unsigned int hevc_subscribe_param_size;
+	const u32 *vp9_subscribe_param;
+	unsigned int vp9_subscribe_param_size;
 	const u32 *dec_input_prop;
 	unsigned int dec_input_prop_size;
 	const u32 *dec_output_prop_avc;
diff --git a/drivers/media/platform/qcom/vcodec/iris/platform_sm8550.c b/drivers/media/platform/qcom/vcodec/iris/platform_sm8550.c
index 6a4bfa3..7ae9715 100644
--- a/drivers/media/platform/qcom/vcodec/iris/platform_sm8550.c
+++ b/drivers/media/platform/qcom/vcodec/iris/platform_sm8550.c
@@ -382,6 +382,38 @@ static struct format_capability format_data_sm8550 = {
 	.color_format_info_size = ARRAY_SIZE(color_format_data_sm8550),
 };
 
+static const u32 sm8550_vdec_src_change_param_avc[] = {
+	HFI_PROP_BITSTREAM_RESOLUTION,
+	HFI_PROP_CROP_OFFSETS,
+	HFI_PROP_CODED_FRAMES,
+	HFI_PROP_LUMA_CHROMA_BIT_DEPTH,
+	HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT,
+	HFI_PROP_PIC_ORDER_CNT_TYPE,
+	HFI_PROP_PROFILE,
+	HFI_PROP_LEVEL,
+	HFI_PROP_SIGNAL_COLOR_INFO,
+};
+
+static const u32 sm8550_vdec_src_change_param_hevc[] = {
+	HFI_PROP_BITSTREAM_RESOLUTION,
+	HFI_PROP_CROP_OFFSETS,
+	HFI_PROP_LUMA_CHROMA_BIT_DEPTH,
+	HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT,
+	HFI_PROP_PROFILE,
+	HFI_PROP_LEVEL,
+	HFI_PROP_TIER,
+	HFI_PROP_SIGNAL_COLOR_INFO,
+};
+
+static const u32 sm8550_vdec_src_change_param_vp9[] = {
+	HFI_PROP_BITSTREAM_RESOLUTION,
+	HFI_PROP_CROP_OFFSETS,
+	HFI_PROP_LUMA_CHROMA_BIT_DEPTH,
+	HFI_PROP_BUFFER_FW_MIN_OUTPUT_COUNT,
+	HFI_PROP_PROFILE,
+	HFI_PROP_LEVEL,
+};
+
 static const u32 sm8550_vdec_input_properties[] = {
 	HFI_PROP_NO_OUTPUT,
 };
@@ -430,6 +462,18 @@ struct platform_data sm8550_data = {
 	.ubwc_config = ubwc_config_sm8550,
 	.format_data = &format_data_sm8550,
 
+	.avc_subscribe_param =
+		sm8550_vdec_src_change_param_avc,
+	.avc_subscribe_param_size =
+		ARRAY_SIZE(sm8550_vdec_src_change_param_avc),
+	.hevc_subscribe_param =
+		sm8550_vdec_src_change_param_hevc,
+	.hevc_subscribe_param_size =
+		ARRAY_SIZE(sm8550_vdec_src_change_param_hevc),
+	.vp9_subscribe_param =
+		sm8550_vdec_src_change_param_vp9,
+	.vp9_subscribe_param_size =
+		ARRAY_SIZE(sm8550_vdec_src_change_param_vp9),
 	.dec_input_prop = sm8550_vdec_input_properties,
 	.dec_input_prop_size = ARRAY_SIZE(sm8550_vdec_input_properties),
 	.dec_output_prop_avc = sm8550_vdec_output_properties_avc,
