瀏覽代碼

Merge "video: driver: misc synx fence changes"

qctecmdr 2 年之前
父節點
當前提交
50631f4a43

+ 7 - 0
driver/platform/common/inc/msm_vidc_platform.h

@@ -328,6 +328,9 @@ int msm_vidc_adjust_session_priority(void *instance, struct v4l2_ctrl *ctrl);
 int msm_vidc_adjust_roi_info(void *instance, struct v4l2_ctrl *ctrl);
 int msm_vidc_adjust_all_intra(void *instance, struct v4l2_ctrl *ctrl);
 int msm_vidc_adjust_dec_outbuf_fence(void *instance, struct v4l2_ctrl *ctrl);
+int msm_vidc_adjust_dec_outbuf_fence_type(void *instance, struct v4l2_ctrl *ctrl);
+int msm_vidc_adjust_dec_outbuf_fence_direction(void *instance,
+	struct v4l2_ctrl *ctrl);
 int msm_vidc_adjust_dec_slice_mode(void *instance, struct v4l2_ctrl *ctrl);
 int msm_vidc_adjust_preprocess(void *instance, struct v4l2_ctrl *ctrl);
 int msm_vidc_adjust_eva_stats(void *instance, struct v4l2_ctrl *ctrl);
@@ -400,5 +403,9 @@ int msm_vidc_set_q16(void *instance,
 	enum msm_vidc_inst_capability_type cap_id);
 int msm_vidc_set_vui_timing_info(void *instance,
 	enum msm_vidc_inst_capability_type cap_id);
+int msm_vidc_set_outbuf_fence_type(void *instance,
+	enum msm_vidc_inst_capability_type cap_id);
+int msm_vidc_set_outbuf_fence_direction(void *instance,
+	enum msm_vidc_inst_capability_type cap_id);
 
 #endif // _MSM_VIDC_PLATFORM_H_

+ 129 - 0
driver/platform/common/src/msm_vidc_platform.c

@@ -2632,6 +2632,83 @@ int msm_vidc_adjust_dec_outbuf_fence(void *instance, struct v4l2_ctrl *ctrl)
 	return 0;
 }
 
+int msm_vidc_adjust_dec_outbuf_fence_type(void *instance, struct v4l2_ctrl *ctrl)
+{
+	struct msm_vidc_inst_capability *capability;
+	s32 adjusted_value, meta_outbuf_fence = 0;
+	struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance;
+	struct msm_vidc_core *core;
+
+	if (!inst || !inst->capabilities || !inst->core) {
+		d_vpr_e("%s: invalid params\n", __func__);
+		return -EINVAL;
+	}
+	capability = inst->capabilities;
+	core = inst->core;
+	if (!core->capabilities) {
+		d_vpr_e("%s: invalid core caps\n", __func__);
+		return -EINVAL;
+	}
+
+	adjusted_value = ctrl ? ctrl->val :
+		capability->cap[OUTBUF_FENCE_TYPE].value;
+
+	if (msm_vidc_get_parent_value(inst, OUTBUF_FENCE_TYPE,
+		META_OUTBUF_FENCE, &meta_outbuf_fence, __func__))
+		return -EINVAL;
+
+	if (is_meta_rx_inp_enabled(inst, META_OUTBUF_FENCE)) {
+		if (core->capabilities[SUPPORTS_SYNX_FENCE].value)
+			adjusted_value = MSM_VIDC_SYNX_V2_FENCE;
+		else
+			adjusted_value = MSM_VIDC_SW_FENCE;
+	} else {
+		adjusted_value = MSM_VIDC_FENCE_NONE;
+	}
+
+	msm_vidc_update_cap_value(inst, OUTBUF_FENCE_TYPE,
+		adjusted_value, __func__);
+
+	return 0;
+}
+
+int msm_vidc_adjust_dec_outbuf_fence_direction(void *instance, struct v4l2_ctrl *ctrl)
+{
+	struct msm_vidc_inst_capability *capability;
+	s32 adjusted_value, meta_outbuf_fence = 0;
+	struct msm_vidc_inst *inst = (struct msm_vidc_inst *) instance;
+	struct msm_vidc_core *core;
+
+	if (!inst || !inst->capabilities || !inst->core) {
+		d_vpr_e("%s: invalid params\n", __func__);
+		return -EINVAL;
+	}
+	capability = inst->capabilities;
+	core = inst->core;
+	if (!core->capabilities) {
+		d_vpr_e("%s: invalid core caps\n", __func__);
+		return -EINVAL;
+	}
+
+	adjusted_value = ctrl ? ctrl->val :
+		capability->cap[OUTBUF_FENCE_DIRECTION].value;
+
+	if (msm_vidc_get_parent_value(inst, OUTBUF_FENCE_DIRECTION,
+		META_OUTBUF_FENCE, &meta_outbuf_fence, __func__))
+		return -EINVAL;
+
+	if (is_meta_rx_inp_enabled(inst, META_OUTBUF_FENCE)) {
+		adjusted_value = MSM_VIDC_FENCE_DIR_TX;
+	} else {
+		adjusted_value = MSM_VIDC_FENCE_DIR_NONE;
+	}
+
+	msm_vidc_update_cap_value(inst, OUTBUF_FENCE_DIRECTION,
+		adjusted_value, __func__);
+
+	return 0;
+}
+
 int msm_vidc_adjust_dec_slice_mode(void *instance, struct v4l2_ctrl *ctrl)
 {
 	struct msm_vidc_inst_capability *capability;
@@ -4095,4 +4172,56 @@ int msm_vidc_set_vui_timing_info(void *instance,
 	return rc;
 }
 
+int msm_vidc_set_outbuf_fence_type(void *instance,
+	enum msm_vidc_inst_capability_type cap_id)
+{
+	int rc = 0;
+	struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance;
+	u32 hfi_value;
+
+	if (!inst || !inst->capabilities) {
+		d_vpr_e("%s: invalid params\n", __func__);
+		return -EINVAL;
+	}
+
+	if (inst->capabilities->cap[OUTBUF_FENCE_TYPE].value ==
+		MSM_VIDC_FENCE_NONE)
+		return 0;
+
+	hfi_value = inst->capabilities->cap[cap_id].value;
+
+	rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_U32_ENUM,
+		&hfi_value, sizeof(u32), __func__);
+	if (rc)
+		return rc;
+
+	return rc;
+}
+
+int msm_vidc_set_outbuf_fence_direction(void *instance,
+	enum msm_vidc_inst_capability_type cap_id)
+{
+	int rc = 0;
+	struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance;
+	u32 hfi_value;
+
+	if (!inst || !inst->capabilities) {
+		d_vpr_e("%s: invalid params\n", __func__);
+		return -EINVAL;
+	}
+
+	if (inst->capabilities->cap[OUTBUF_FENCE_DIRECTION].value ==
+		MSM_VIDC_FENCE_DIR_NONE)
+		return 0;
+
+	hfi_value = inst->capabilities->cap[cap_id].value;
+
+	rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_U32_ENUM,
+		&hfi_value, sizeof(u32), __func__);
+	if (rc)
+		return rc;
+
+	return rc;
+}
+
 /********************* End of Control Set functions **************************/

+ 71 - 4
driver/platform/pineapple/src/msm_vidc_pineapple.c

@@ -633,6 +633,47 @@ static struct msm_platform_inst_capability instance_cap_data_pineapple[] = {
 		0,
 		CAP_FLAG_VOLATILE},
 
+	/* Fence type for input buffer. Currently unsed */
+	{INBUF_FENCE_TYPE, DEC, H264|HEVC|VP9|AV1,
+		MSM_VIDC_FENCE_NONE, MSM_VIDC_FENCE_NONE,
+		BIT(MSM_VIDC_FENCE_NONE),
+		MSM_VIDC_FENCE_NONE,
+		0,
+		HFI_PROP_FENCE_TYPE,
+		CAP_FLAG_MENU | CAP_FLAG_INPUT_PORT},
+
+	{OUTBUF_FENCE_TYPE, DEC, H264|HEVC|VP9|AV1,
+		MSM_VIDC_FENCE_NONE, MSM_VIDC_SYNX_V2_FENCE,
+		BIT(MSM_VIDC_FENCE_NONE) | BIT(MSM_VIDC_SW_FENCE) |
+			BIT(MSM_VIDC_SYNX_V2_FENCE),
+		MSM_VIDC_FENCE_NONE,
+		0,
+		HFI_PROP_FENCE_TYPE,
+		CAP_FLAG_MENU | CAP_FLAG_OUTPUT_PORT},
+
+	/* Fence direction for input buffer. Currently unsed */
+	{INBUF_FENCE_DIRECTION, DEC, H264|HEVC|VP9|AV1,
+		MSM_VIDC_FENCE_DIR_NONE, MSM_VIDC_FENCE_DIR_NONE,
+		BIT(MSM_VIDC_FENCE_DIR_NONE),
+		MSM_VIDC_FENCE_DIR_NONE,
+		0,
+		HFI_PROP_FENCE_DIRECTION,
+		CAP_FLAG_MENU | CAP_FLAG_INPUT_PORT},
+
+	{OUTBUF_FENCE_DIRECTION, DEC, H264|HEVC|VP9|AV1,
+		MSM_VIDC_FENCE_DIR_NONE, MSM_VIDC_FENCE_DIR_RX,
+		BIT(MSM_VIDC_FENCE_DIR_NONE) | BIT(MSM_VIDC_FENCE_DIR_TX) |
+			BIT(MSM_VIDC_FENCE_DIR_RX),
+		MSM_VIDC_FENCE_DIR_NONE,
+		0,
+		HFI_PROP_FENCE_DIRECTION,
+		CAP_FLAG_MENU | CAP_FLAG_OUTPUT_PORT},
+
+	{FENCE_ERROR_DATA_CORRUPT, DEC, H264|HEVC|VP9|AV1,
+		0, 1, 1, 0,
+		0,
+		HFI_PROP_FENCE_ERROR_DATA_CORRUPT},
+
 	{TS_REORDER, DEC, H264|HEVC,
 		0, 1, 1, 0,
 		V4L2_CID_MPEG_VIDC_TS_REORDER},
@@ -2060,15 +2101,41 @@ static struct msm_platform_inst_cap_dependency instance_cap_dependency_data_pine
 		msm_vidc_set_u32},
 
 	{META_OUTBUF_FENCE, DEC, H264|HEVC|AV1,
-		{LOWLATENCY_MODE, SLICE_DECODE},
+		{LOWLATENCY_MODE, SLICE_DECODE,
+			OUTBUF_FENCE_TYPE, OUTBUF_FENCE_DIRECTION},
 		msm_vidc_adjust_dec_outbuf_fence,
 		NULL},
 
 	{META_OUTBUF_FENCE, DEC, VP9,
-		{LOWLATENCY_MODE},
+		{LOWLATENCY_MODE, OUTBUF_FENCE_TYPE, OUTBUF_FENCE_DIRECTION},
 		msm_vidc_adjust_dec_outbuf_fence,
 		NULL},
 
+	{INBUF_FENCE_TYPE, DEC, H264|HEVC|VP9|AV1,
+		{0},
+		NULL,
+		NULL},
+
+	{OUTBUF_FENCE_TYPE, DEC, H264|HEVC|VP9|AV1,
+		{0},
+		msm_vidc_adjust_dec_outbuf_fence_type,
+		msm_vidc_set_outbuf_fence_type},
+
+	{INBUF_FENCE_DIRECTION, DEC, H264|HEVC|VP9|AV1,
+		{0},
+		NULL,
+		NULL},
+
+	{OUTBUF_FENCE_DIRECTION, DEC, H264|HEVC|VP9|AV1,
+		{0},
+		msm_vidc_adjust_dec_outbuf_fence_direction,
+		msm_vidc_set_outbuf_fence_direction},
+
+	{FENCE_ERROR_DATA_CORRUPT, DEC, H264|HEVC|VP9|AV1,
+		{0},
+		NULL,
+		msm_vidc_set_u32},
+
 	{HFLIP, ENC, CODECS_ALL,
 		{0},
 		NULL,
@@ -2698,12 +2765,12 @@ static const struct device_region_table pineapple_device_region_table[] = {
 	},
 	{
 		"ipc_protocol4_client8_version-registers",
-		0x00508000, 0x1000, 0xFFADD000,
+		0x00508000, 0x1000, 0xFFADF000,
 		MSM_VIDC_PROTOCOL_FENCE_CLIENT_VPU
 	},
 	{
 		"qtimer_f0v1_qtmr_v1_cntpct_lo",
-		0x17421000, 0x1000, 0xFFADC000,
+		0x17421000, 0x1000, 0xFFADE000,
 		MSM_VIDC_QTIMER
 	},
 };

+ 2 - 1
driver/variant/iris33/src/msm_vidc_iris33.c

@@ -954,7 +954,8 @@ static int __boot_firmware_iris33(struct msm_vidc_core *vidc_core)
 			return rc;
 
 		if ((ctrl_status & HFI_CTRL_ERROR_FATAL) ||
-			(ctrl_status & HFI_CTRL_ERROR_UC_REGION_NOT_SET)) {
+			(ctrl_status & HFI_CTRL_ERROR_UC_REGION_NOT_SET) ||
+			(ctrl_status & HFI_CTRL_ERROR_HW_FENCE_QUEUE)) {
 			d_vpr_e("%s: boot firmware failed, ctrl status %#x\n",
 				__func__, ctrl_status);
 			return -EINVAL;

+ 1 - 1
driver/vidc/inc/msm_vidc_debug.h

@@ -39,7 +39,7 @@ extern int msm_vidc_ddr_bw;
 extern int msm_vidc_llc_bw;
 extern bool msm_vidc_fw_dump;
 extern unsigned int msm_vidc_enable_bugon;
-extern bool msm_vidc_disable_synx_fence;
+extern bool msm_vidc_synx_fence_enable;
 
 /* do not modify the log message as it is used in test scripts */
 #define FMT_STRING_SET_CTRL \

+ 18 - 0
driver/vidc/inc/msm_vidc_internal.h

@@ -258,6 +258,10 @@ enum msm_vidc_metadata_bits {
 	CAP(DELIVERY_MODE)                        \
 	CAP(VUI_TIMING_INFO)                      \
 	CAP(SLICE_DECODE)                         \
+	CAP(INBUF_FENCE_TYPE)                     \
+	CAP(OUTBUF_FENCE_TYPE)                    \
+	CAP(INBUF_FENCE_DIRECTION)                \
+	CAP(OUTBUF_FENCE_DIRECTION)               \
 	CAP(PROFILE)                              \
 	CAP(ENH_LAYER_COUNT)                      \
 	CAP(BIT_RATE)                             \
@@ -299,6 +303,7 @@ enum msm_vidc_metadata_bits {
 	CAP(SECURE_MODE)                          \
 	CAP(FENCE_ID)                             \
 	CAP(FENCE_FD)                             \
+	CAP(FENCE_ERROR_DATA_CORRUPT)             \
 	CAP(TS_REORDER)                           \
 	CAP(HFLIP)                                \
 	CAP(VFLIP)                                \
@@ -794,6 +799,7 @@ struct msm_vidc_hfi_frame_info {
 	u32                    data_corrupt;
 	u32                    overflow;
 	u32                    fence_id;
+	u32                    fence_error;
 };
 
 struct msm_vidc_decode_vpp_delay {
@@ -853,6 +859,18 @@ struct msm_vidc_power {
 	u32                    fw_cf;
 };
 
+enum msm_vidc_fence_type {
+	MSM_VIDC_FENCE_NONE         = 0,
+	MSM_VIDC_SW_FENCE           = 1,
+	MSM_VIDC_SYNX_V2_FENCE      = 2,
+};
+
+enum msm_vidc_fence_direction {
+	MSM_VIDC_FENCE_DIR_NONE    = 0,
+	MSM_VIDC_FENCE_DIR_TX      = 1,
+	MSM_VIDC_FENCE_DIR_RX      = 2,
+};
+
 struct msm_vidc_fence_context {
 	char                      name[MAX_NAME_LENGTH];
 	u64                       ctx_num;

+ 20 - 1
driver/vidc/src/hfi_packet.c

@@ -401,8 +401,9 @@ int hfi_packet_sys_init(struct msm_vidc_core *core,
 {
 	int rc = 0;
 	u32 payload = 0;
+	u32 synx_client_data[2];
 
-	if (!core || !pkt) {
+	if (!core || !pkt || !core->capabilities) {
 		d_vpr_e("%s: Invalid params\n", __func__);
 		return -EINVAL;
 	}
@@ -528,6 +529,24 @@ int hfi_packet_sys_init(struct msm_vidc_core *core,
 	if (rc)
 		goto err_sys_init;
 
+	/* HFI_PROP_FENCE_CLIENT_DATA */
+	if (core->capabilities[SUPPORTS_SYNX_FENCE].value) {
+		synx_client_data[0] = core->synx_fence_data.client_id;
+		synx_client_data[1] = core->synx_fence_data.client_flags;
+		d_vpr_h("%s: synx fence client id: %u client flags: %u\n",
+			__func__, synx_client_data[0], synx_client_data[1]);
+		rc = hfi_create_packet(pkt, pkt_size,
+					HFI_PROP_FENCE_CLIENT_DATA,
+					HFI_HOST_FLAGS_NONE,
+					HFI_PAYLOAD_U32_ARRAY,
+					HFI_PORT_NONE,
+					core->packet_id++,
+					synx_client_data,
+					sizeof(u32) * 2);
+		if (rc)
+			goto err_sys_init;
+	}
+
 	d_vpr_h("System init packet created\n");
 	return rc;
 

+ 41 - 19
driver/vidc/src/msm_vidc_debug.c

@@ -22,6 +22,8 @@ extern struct msm_vidc_core *g_core;
 #define MSM_VIDC_MAX_STATS_DELAY_MS     10000
 
 unsigned int msm_vidc_debug = (DRV_LOG | FW_LOG);
+/* disabled synx fence by default temporarily */
+bool msm_vidc_synx_fence_enable = false;
 
 static int debug_level_set(const char *val,
 	const struct kernel_param *kp)
@@ -34,12 +36,6 @@ static int debug_level_set(const char *val,
 		d_vpr_e("%s: Invalid params\n", __func__);
 		return -EINVAL;
 	}
-	core = *(struct msm_vidc_core **)kp->arg;
-
-	if (!core || !core->capabilities) {
-		d_vpr_e("%s: Invalid core/capabilities\n", __func__);
-		return -EINVAL;
-	}
 
 	ret = kstrtouint(val, 0, &dvalue);
 	if (ret)
@@ -47,6 +43,13 @@ static int debug_level_set(const char *val,
 
 	msm_vidc_debug = dvalue;
 
+	core = *(struct msm_vidc_core **)kp->arg;
+
+	if (!core || !core->capabilities) {
+		d_vpr_e("%s: Invalid core/capabilities\n", __func__);
+		return 0;
+	}
+
 	/* check if driver or FW logmask is more than default level */
 	if (((dvalue & DRV_LOGMASK) & ~(DRV_LOG)) ||
 		((dvalue & FW_LOGMASK) & ~(FW_LOG))) {
@@ -82,7 +85,6 @@ static const struct kernel_param_ops msm_vidc_debug_fops = {
 static int fw_dump_set(const char *val,
 	const struct kernel_param *kp)
 {
-	struct msm_vidc_core *core = NULL;
 	unsigned int dvalue;
 	int ret;
 
@@ -90,12 +92,6 @@ static int fw_dump_set(const char *val,
 		d_vpr_e("%s: Invalid params\n", __func__);
 		return -EINVAL;
 	}
-	core = *(struct msm_vidc_core **) kp->arg;
-
-	if (!core || !core->capabilities) {
-		d_vpr_e("%s: Invalid core/capabilities\n", __func__);
-		return -EINVAL;
-	}
 
 	ret = kstrtouint(val, 0, &dvalue);
 	if (ret)
@@ -118,16 +114,44 @@ static const struct kernel_param_ops msm_vidc_fw_dump_fops = {
 	.get = fw_dump_get,
 };
 
+static int synx_fence_set(const char *val,
+	const struct kernel_param *kp)
+{
+	unsigned int dvalue;
+	int ret;
+
+	if (!kp || !kp->arg || !val) {
+		d_vpr_e("%s: Invalid params\n", __func__);
+		return -EINVAL;
+	}
+
+	ret = kstrtouint(val, 0, &dvalue);
+	if (ret)
+		return ret;
+
+	msm_vidc_synx_fence_enable = dvalue;
+
+	return 0;
+}
+
+static int synx_fence_get(char *buffer, const struct kernel_param *kp)
+{
+	return scnprintf(buffer, PAGE_SIZE, "%#x", msm_vidc_synx_fence_enable);
+}
+
+static const struct kernel_param_ops msm_vidc_synx_fence_debug_fops = {
+	.set = synx_fence_set,
+	.get = synx_fence_get,
+};
+
 module_param_cb(msm_vidc_debug, &msm_vidc_debug_fops, &g_core, 0644);
 module_param_cb(msm_vidc_fw_dump, &msm_vidc_fw_dump_fops, &g_core, 0644);
+module_param_cb(msm_vidc_synx_fence_enable,
+	&msm_vidc_synx_fence_debug_fops, &g_core, 0644);
 
 bool msm_vidc_lossless_encode = !true;
 EXPORT_SYMBOL(msm_vidc_lossless_encode);
 
-/* disabled synx fence by default temporarily */
-bool msm_vidc_disable_synx_fence = !false;
-EXPORT_SYMBOL(msm_vidc_disable_synx_fence);
-
 bool msm_vidc_syscache_disable = !true;
 EXPORT_SYMBOL(msm_vidc_syscache_disable);
 
@@ -402,8 +426,6 @@ struct dentry* msm_vidc_debugfs_init_drv(void)
 			&msm_vidc_syscache_disable);
 	debugfs_create_bool("lossless_encoding", 0644, dir,
 			&msm_vidc_lossless_encode);
-	debugfs_create_bool("disable_synx_v2_fence", 0644, dir,
-			&msm_vidc_disable_synx_fence);
 	debugfs_create_u32("enable_bugon", 0644, dir,
 			&msm_vidc_enable_bugon);
 

+ 9 - 22
driver/vidc/src/msm_vidc_probe.c

@@ -569,36 +569,23 @@ static int msm_vidc_component_master_bind(struct device *dev)
 	}
 
 	if (core->capabilities[SUPPORTS_SYNX_FENCE].value) {
-		if (msm_vidc_disable_synx_fence) {
-			/* override synx fence ops with dma fence ops */
-			core->fence_ops = get_dma_fence_ops();
-			if (!core->fence_ops) {
-				d_vpr_e("%s: invalid dma fence ops\n", __func__);
-				return -EINVAL;
-			}
-			core->capabilities[SUPPORTS_SYNX_FENCE].value = 0;
-		} else {
+		if (msm_vidc_synx_fence_enable) {
 			/* register for synx fence */
 			rc = call_fence_op(core, fence_register, core);
 			if (rc) {
 				d_vpr_e("%s: failed to register synx fence\n",
 					__func__);
 				core->capabilities[SUPPORTS_SYNX_FENCE].value = 0;
-				/*
-				 * - Bail out the session for time being for this
-				 *   case where synx fence register call retunrs error
-				 *   to help with debugging
-				 * - Re-initialize fence ops with dma_fence_ops.
-				 *   This is required once we start ignoring this
-				 *   synx fence register call error.
-				 */
-				core->fence_ops = get_dma_fence_ops();
-				if (!core->fence_ops) {
-					d_vpr_e("%s: invalid dma fence ops\n", __func__);
-					return -EINVAL;
-				}
 				return rc;
 			}
+		} else {
+			/* override synx fence ops with dma fence ops */
+			core->fence_ops = get_dma_fence_ops();
+			if (!core->fence_ops) {
+				d_vpr_e("%s: invalid dma fence ops\n", __func__);
+				return -EINVAL;
+			}
+			core->capabilities[SUPPORTS_SYNX_FENCE].value = 0;
 		}
 	}
 

+ 2 - 0
driver/vidc/src/msm_vidc_synx.c

@@ -145,6 +145,7 @@ static int msm_vidc_synx_fence_register(struct msm_vidc_core *core)
 		"video synx fence");
 	params.name = synx_session_name;
 	params.ptr = &queue_desc;
+	params.flags = SYNX_INIT_MAX; /* unused */
 
 	session =
 		(struct synx_session *)synx_hwfence_initialize(&params);
@@ -155,6 +156,7 @@ static int msm_vidc_synx_fence_register(struct msm_vidc_core *core)
 
 	/* fill core synx fence data */
 	core->synx_fence_data.client_id = (u32)params.id;
+	core->synx_fence_data.client_flags = (u32)params.flags;
 	core->synx_fence_data.session = (void *)session;
 	core->synx_fence_data.queue.size = (u32)queue_desc.size;
 	core->synx_fence_data.queue.kvaddr = queue_desc.vaddr;

+ 77 - 12
driver/vidc/src/venus_hfi_response.c

@@ -342,6 +342,10 @@ static int handle_session_info(struct msm_vidc_inst *inst,
 		info = "buffer overflow";
 		inst->hfi_frame_info.overflow = 1;
 		break;
+	case HFI_INFO_FENCE_SIGNAL_ERROR:
+		info = "synx v2 fence error";
+		inst->hfi_frame_info.fence_error = 1;
+		break;
 	case HFI_INFO_HFI_FLAG_DRAIN_LAST:
 		info = "drain last flag";
 		rc = handle_session_last_flag_info(inst, pkt);
@@ -856,6 +860,76 @@ static int handle_input_buffer(struct msm_vidc_inst *inst,
 	return rc;
 }
 
+static int msm_vidc_handle_fence_signal(struct msm_vidc_inst *inst,
+	struct msm_vidc_buffer *buf)
+{
+	int rc = 0;
+	bool signal_error = false;
+	struct msm_vidc_core *core = inst->core;
+
+	if (!buf) {
+		i_vpr_e(inst, "%s: invalid params\n", __func__);
+		return -EINVAL;
+	}
+
+	if (inst->capabilities->cap[OUTBUF_FENCE_TYPE].value ==
+		MSM_VIDC_FENCE_NONE)
+		return 0;
+
+	if (is_meta_rx_inp_enabled(inst, META_OUTBUF_FENCE)) {
+		if (!inst->hfi_frame_info.fence_id) {
+			i_vpr_e(inst,
+				"%s: fence id is not received although fencing is enabled\n",
+				__func__);
+			return -EINVAL;
+		}
+	} else {
+		if (inst->hfi_frame_info.fence_id)
+			i_vpr_e(inst,
+				"%s: fence id is received although fencing is not enabled\n",
+				__func__);
+		return 0;
+	}
+
+	if (inst->capabilities->cap[OUTBUF_FENCE_TYPE].value ==
+		MSM_VIDC_SYNX_V2_FENCE) {
+		if (inst->hfi_frame_info.fence_error)
+			signal_error = true;
+	} else if (inst->capabilities->cap[OUTBUF_FENCE_TYPE].value ==
+		MSM_VIDC_SW_FENCE) {
+		if (!buf->data_size)
+			signal_error = true;
+
+		if (inst->hfi_frame_info.fence_error)
+			i_vpr_e(inst,
+				"%s: fence error info recieved for SW fence\n",
+				__func__);
+	} else {
+		i_vpr_e(inst, "%s: invalid fence type\n", __func__);
+		return -EINVAL;
+	}
+
+	/* fence signalling */
+	if (signal_error) {
+		/* signal fence error */
+		i_vpr_l(inst,
+			"%s: signalling fence error for buf idx %d daddr %#llx\n",
+			__func__, buf->index, buf->device_addr);
+		call_fence_op(core, fence_destroy, inst,
+			inst->hfi_frame_info.fence_id);
+	} else {
+		/* signal fence success*/
+		rc = call_fence_op(core, fence_signal, inst,
+			inst->hfi_frame_info.fence_id);
+		if (rc) {
+			i_vpr_e(inst, "%s: failed to signal fence\n", __func__);
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
 static int handle_output_buffer(struct msm_vidc_inst *inst,
 	struct hfi_buffer *buffer)
 {
@@ -997,18 +1071,9 @@ static int handle_output_buffer(struct msm_vidc_inst *inst,
 	buf->flags = 0;
 	buf->flags = get_driver_buffer_flags(inst, buffer->flags);
 
-	/* fence signalling */
-	if (inst->hfi_frame_info.fence_id) {
-		if (buf->data_size) {
-			/* signal fence */
-			call_fence_op(core, fence_signal, inst,
-				inst->hfi_frame_info.fence_id);
-		} else {
-			/* destroy fence */
-			call_fence_op(core, fence_destroy, inst,
-				inst->hfi_frame_info.fence_id);
-		}
-	}
+	rc = msm_vidc_handle_fence_signal(inst, buf);
+	if (rc)
+		msm_vidc_change_state(inst, MSM_VIDC_ERROR, __func__);
 
 	if (is_decode_session(inst)) {
 		inst->power.fw_cr = inst->hfi_frame_info.cr;