浏览代码

video: driver: add support for instance states

Add support for all the required instance states and
move the states accordingly.

Change-Id: Iac1046ab8c7a0116df6ed3069d566c7a1b65e61c
Signed-off-by: Maheshwar Ajja <[email protected]>
Maheshwar Ajja 4 年之前
父节点
当前提交
58cd1120ee

+ 5 - 6
driver/vidc/inc/msm_vdec.h

@@ -9,19 +9,18 @@
 #include "msm_vidc_core.h"
 #include "msm_vidc_inst.h"
 
-int msm_vdec_stop_input(struct msm_vidc_inst *inst);
-int msm_vdec_start_input(struct msm_vidc_inst *inst);
-int msm_vdec_stop_output(struct msm_vidc_inst *inst);
-int msm_vdec_start_output(struct msm_vidc_inst *inst);
+int msm_vdec_streamoff_input(struct msm_vidc_inst *inst);
+int msm_vdec_streamon_input(struct msm_vidc_inst *inst);
+int msm_vdec_streamoff_output(struct msm_vidc_inst *inst);
+int msm_vdec_streamon_output(struct msm_vidc_inst *inst);
 int msm_vdec_qbuf(struct msm_vidc_inst *inst, struct vb2_buffer *vb2);
 int msm_vdec_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f);
 int msm_vdec_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f);
 int msm_vdec_enum_fmt(struct msm_vidc_inst *inst, struct v4l2_fmtdesc *f);
 int msm_vdec_inst_init(struct msm_vidc_inst *inst);
+int msm_vdec_inst_deinit(struct msm_vidc_inst *inst);
 int msm_vdec_input_port_settings_change(struct msm_vidc_inst *inst);
 int msm_vdec_output_port_settings_change(struct msm_vidc_inst *inst);
 int msm_vdec_process_cmd(struct msm_vidc_inst *inst, u32 cmd);
-int msm_vdec_subscribe_port_settings_change(struct msm_vidc_inst *inst,
-	enum msm_vidc_port_type port);
 
 #endif // _MSM_VDEC_H_

+ 5 - 4
driver/vidc/inc/msm_venc.h

@@ -9,14 +9,15 @@
 #include "msm_vidc_core.h"
 #include "msm_vidc_inst.h"
 
-int msm_venc_stop_input(struct msm_vidc_inst *inst);
-int msm_venc_start_input(struct msm_vidc_inst *inst);
-int msm_venc_stop_output(struct msm_vidc_inst *inst);
-int msm_venc_start_output(struct msm_vidc_inst *inst);
+int msm_venc_streamoff_input(struct msm_vidc_inst *inst);
+int msm_venc_streamon_input(struct msm_vidc_inst *inst);
+int msm_venc_streamoff_output(struct msm_vidc_inst *inst);
+int msm_venc_streamon_output(struct msm_vidc_inst *inst);
 int msm_venc_process_cmd(struct msm_vidc_inst *inst, u32 cmd);
 int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f);
 int msm_venc_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f);
 int msm_venc_enum_fmt(struct msm_vidc_inst *inst, struct v4l2_fmtdesc *f);
 int msm_venc_inst_init(struct msm_vidc_inst *inst);
+int msm_venc_inst_deinit(struct msm_vidc_inst *inst);
 
 #endif // _MSM_VENC_H_

+ 0 - 15
driver/vidc/inc/msm_vidc_core.h

@@ -60,18 +60,6 @@ enum msm_vidc_core_state {
 	MSM_VIDC_CORE_ERROR        = 2,
 };
 
-enum work_type {
-	MSM_VIDC_INST_WORK_PSC = 1,
-};
-
-struct work_header {
-	void *data;
-	struct list_head list;
-	enum work_type type;
-	u32 session_id;
-	u32 data_size;
-};
-
 struct msm_vidc_core {
 	struct platform_device                *pdev;
 	struct msm_video_device                vdev[2];
@@ -120,9 +108,6 @@ struct msm_vidc_core {
 	u32                                    header_id;
 	u32                                    packet_id;
 	struct completion                      init_done;
-	struct list_head                       inst_works; /* list of struct work_header */
-	struct delayed_work                    inst_work;
-	struct workqueue_struct               *inst_workq;
 };
 
 #endif // _MSM_VIDC_CORE_H_

+ 29 - 6
driver/vidc/inc/msm_vidc_driver.h

@@ -177,6 +177,7 @@ u32 v4l2_colorformat_from_driver(enum msm_vidc_colorformat_type colorformat,
 	const char *func);
 int v4l2_type_to_driver_port(struct msm_vidc_inst *inst, u32 type,
 	const char *func);
+const char *state_name(enum msm_vidc_inst_state state);
 int msm_vidc_change_inst_state(struct msm_vidc_inst *inst,
 	enum msm_vidc_inst_state state, const char *func);
 int msm_vidc_get_input_internal_buffers(struct msm_vidc_inst *inst,
@@ -193,13 +194,14 @@ int msm_vidc_remove_session(struct msm_vidc_inst *inst);
 int msm_vidc_add_session(struct msm_vidc_inst *inst);
 int msm_vidc_session_open(struct msm_vidc_inst *inst);
 int msm_vidc_session_set_codec(struct msm_vidc_inst *inst);
-int msm_vidc_session_start(struct msm_vidc_inst* inst,
+int msm_vidc_session_streamon(struct msm_vidc_inst *inst,
 		enum msm_vidc_port_type port);
-int msm_vidc_session_stop(struct msm_vidc_inst *inst,
+int msm_vidc_session_streamoff(struct msm_vidc_inst *inst,
 		enum msm_vidc_port_type port);
 int msm_vidc_session_close(struct msm_vidc_inst *inst);
 int msm_vidc_get_inst_capability(struct msm_vidc_inst *inst);
 int msm_vidc_core_init(struct msm_vidc_core *core);
+int msm_vidc_core_deinit(struct msm_vidc_core *core);
 int msm_vidc_smmu_fault_handler(struct iommu_domain *domain,
 		struct device *dev, unsigned long iova, int flags, void *data);
 int msm_vidc_trigger_ssr(struct msm_vidc_core *core,
@@ -208,8 +210,10 @@ void msm_vidc_ssr_handler(struct work_struct *work);
 void msm_vidc_pm_work_handler(struct work_struct *work);
 void msm_vidc_fw_unload_handler(struct work_struct *work);
 void msm_vidc_batch_handler(struct work_struct *work);
-int msm_vidc_setup_event_queue(struct msm_vidc_inst *inst);
+int msm_vidc_event_queue_init(struct msm_vidc_inst *inst);
+int msm_vidc_event_queue_deinit(struct msm_vidc_inst *inst);
 int msm_vidc_vb2_queue_init(struct msm_vidc_inst *inst);
+int msm_vidc_vb2_queue_deinit(struct msm_vidc_inst *inst);
 int msm_vidc_get_control(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl);
 u32 msm_vidc_get_buffer_region(struct msm_vidc_inst *inst,
 	enum msm_vidc_buffer_type buffer_type, const char *func);
@@ -231,14 +235,33 @@ int msm_vidc_put_driver_buf(struct msm_vidc_inst *inst,
 int msm_vidc_queue_buffer(struct msm_vidc_inst *inst, struct vb2_buffer *vb2);
 int msm_vidc_destroy_internal_buffer(struct msm_vidc_inst *inst,
 	struct msm_vidc_buffer *buffer);
+void msm_vidc_destroy_buffers(struct msm_vidc_inst *inst);
 struct msm_vidc_buffer *get_meta_buffer(struct msm_vidc_inst *inst,
 	struct msm_vidc_buffer *vbuf);
+struct msm_vidc_inst *get_inst_ref(struct msm_vidc_core *core,
+		struct msm_vidc_inst *instance);
 struct msm_vidc_inst *get_inst(struct msm_vidc_core *core,
 		u32 session_id);
 void put_inst(struct msm_vidc_inst *inst);
-int msm_vidc_get_mbs_per_frame(struct msm_vidc_inst* inst);
-int msm_vidc_get_fps(struct msm_vidc_inst* inst);
-int msm_vidc_num_queued_bufs(struct msm_vidc_inst* inst, u32 type);
+bool msm_vidc_allow_s_fmt(struct msm_vidc_inst *inst, u32 type);
+bool msm_vidc_allow_s_ctrl(struct msm_vidc_inst *inst, u32 id);
+bool msm_vidc_allow_reqbufs(struct msm_vidc_inst *inst, u32 type);
+bool msm_vidc_allow_stop(struct msm_vidc_inst *inst);
+bool msm_vidc_allow_start(struct msm_vidc_inst *inst);
+bool msm_vidc_allow_streamon(struct msm_vidc_inst *inst, u32 type);
+bool msm_vidc_allow_streamoff(struct msm_vidc_inst *inst, u32 type);
+bool msm_vidc_allow_qbuf(struct msm_vidc_inst *inst);
+int msm_vidc_allow_input_psc(struct msm_vidc_inst *inst);
+bool msm_vidc_allow_last_flag(struct msm_vidc_inst *inst);
+int msm_vidc_state_change_streamon(struct msm_vidc_inst *inst, u32 type);
+int msm_vidc_state_change_streamoff(struct msm_vidc_inst *inst, u32 type);
+int msm_vidc_state_change_stop(struct msm_vidc_inst *inst);
+int msm_vidc_state_change_start(struct msm_vidc_inst *inst);
+int msm_vidc_state_change_input_psc(struct msm_vidc_inst *inst);
+int msm_vidc_state_change_last_flag(struct msm_vidc_inst *inst);
+int msm_vidc_get_mbs_per_frame(struct msm_vidc_inst *inst);
+int msm_vidc_get_fps(struct msm_vidc_inst *inst);
+int msm_vidc_num_queued_bufs(struct msm_vidc_inst *inst, u32 type);
 void core_lock(struct msm_vidc_core *core, const char *function);
 void core_unlock(struct msm_vidc_core *core, const char *function);
 void inst_lock(struct msm_vidc_inst *inst, const char *function);

+ 6 - 0
driver/vidc/inc/msm_vidc_inst.h

@@ -34,6 +34,7 @@ struct msm_vidc_allocations_info {
 	struct msm_vidc_allocations     line;
 	struct msm_vidc_allocations     dpb;
 	struct msm_vidc_allocations     persist;
+	struct msm_vidc_allocations     vpss;
 };
 
 struct msm_vidc_mappings_info {
@@ -48,6 +49,7 @@ struct msm_vidc_mappings_info {
 	struct msm_vidc_mappings        line;
 	struct msm_vidc_mappings        dpb;
 	struct msm_vidc_mappings        persist;
+	struct msm_vidc_mappings        vpss;
 };
 
 struct msm_vidc_buffers_info {
@@ -62,6 +64,7 @@ struct msm_vidc_buffers_info {
 	struct msm_vidc_buffers        line;
 	struct msm_vidc_buffers        dpb;
 	struct msm_vidc_buffers        persist;
+	struct msm_vidc_buffers        vpss;
 };
 
 enum msm_vidc_inst_state {
@@ -119,6 +122,9 @@ struct msm_vidc_inst {
 	struct msm_vidc_decode_batch       decode_batch;
 	struct msm_vidc_decode_vpp_delay   decode_vpp_delay;
 	struct msm_vidc_session_idle       session_idle;
+	struct delayed_work                input_psc_work;
+	struct workqueue_struct           *input_psc_workq;
+	struct list_head                   input_psc_works; /* list of struct input_psc_work */
 	struct list_head                   input_ts;
 	struct list_head                   enc_input_crs;
 	struct list_head                   decode_bitrate_data;

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

@@ -708,6 +708,12 @@ struct msm_vidc_buffers {
 	bool                   reuse;
 };
 
+struct input_psc_work {
+	struct list_head list;
+	void *data;
+	u32 data_size;
+};
+
 struct msm_vidc_ssr {
 	bool                               trigger;
 	enum msm_vidc_ssr_trigger_type     ssr_type;

+ 4 - 0
driver/vidc/inc/msm_vidc_vb2.h

@@ -8,6 +8,10 @@
 
 #include <media/videobuf2-core.h>
 #include <media/videobuf2-v4l2.h>
+#include "msm_vidc_inst.h"
+
+struct vb2_queue *msm_vidc_get_vb2q(struct msm_vidc_inst *inst,
+	u32 type, const char *func);
 
 /* vb2_mem_ops */
 void *msm_vb2_get_userptr(struct device *dev, unsigned long vaddr,

+ 1 - 2
driver/vidc/inc/venus_hfi.h

@@ -64,14 +64,13 @@ int venus_hfi_session_close(struct msm_vidc_inst *inst);
 int venus_hfi_session_open(struct msm_vidc_inst *inst);
 int venus_hfi_session_set_codec(struct msm_vidc_inst *inst);
 int venus_hfi_core_init(struct msm_vidc_core *core);
-int venus_hfi_core_release(struct msm_vidc_core *core);
+int venus_hfi_core_deinit(struct msm_vidc_core *core);
 int venus_hfi_suspend(struct msm_vidc_core *core);
 int venus_hfi_scale_clocks(struct msm_vidc_inst* inst, u64 freq);
 int venus_hfi_scale_buses(struct msm_vidc_inst* inst, u64 bw_ddr, u64 bw_llcc);
 
 void venus_hfi_work_handler(struct work_struct *work);
 void venus_hfi_pm_work_handler(struct work_struct *work);
-void venus_hfi_inst_work_handler(struct work_struct *work);
 irqreturn_t venus_hfi_isr(int irq, void *data);
 
 void __write_register(struct msm_vidc_core *core,

+ 3 - 0
driver/vidc/inc/venus_hfi_response.h

@@ -14,5 +14,8 @@ bool is_valid_port(struct msm_vidc_inst *inst, u32 port,
 	const char *func);
 bool is_valid_hfi_buffer_type(struct msm_vidc_inst *inst,
 	u32 buffer_type, const char *func);
+void handle_session_input_psc_work_handler(struct work_struct *work);
+int handle_session_input_psc(struct msm_vidc_inst *inst,
+		struct input_psc_work *psc_work);
 
 #endif // __VENUS_HFI_RESPONSE_H__

+ 49 - 45
driver/vidc/src/msm_vdec.c

@@ -1158,7 +1158,7 @@ int msm_vdec_output_port_settings_change(struct msm_vidc_inst *inst)
 	return 0;
 }
 
-int msm_vdec_stop_input(struct msm_vidc_inst *inst)
+int msm_vdec_streamoff_input(struct msm_vidc_inst *inst)
 {
 	int rc = 0;
 
@@ -1167,31 +1167,28 @@ int msm_vdec_stop_input(struct msm_vidc_inst *inst)
 		return -EINVAL;
 	}
 
-	rc = msm_vidc_session_stop(inst, INPUT_PORT);
+	rc = msm_vidc_session_streamoff(inst, INPUT_PORT);
 	if (rc)
 		return rc;
 
 	return 0;
 }
 
-int msm_vdec_start_input(struct msm_vidc_inst *inst)
+int msm_vdec_streamon_input(struct msm_vidc_inst *inst)
 {
 	int rc = 0;
-	struct msm_vidc_core *core;
 
 	if (!inst || !inst->core) {
 		d_vpr_e("%s: invalid params\n", __func__);
 		return -EINVAL;
 	}
-	core = inst->core;
-	s_vpr_h(inst->sid, "%s()\n", __func__);
 
 	if (is_input_meta_enabled(inst) &&
 		!inst->vb2q[INPUT_META_PORT].streaming) {
 		s_vpr_e(inst->sid,
 			"%s: Meta port must be streamed on before data port\n",
 			__func__);
-		goto error;
+		return -EINVAL;
 	}
 
 	//rc = msm_vidc_check_session_supported(inst);
@@ -1244,20 +1241,19 @@ int msm_vdec_start_input(struct msm_vidc_inst *inst)
 	if (rc)
 		return rc;
 
-	rc = msm_vidc_session_start(inst, INPUT_PORT);
+	rc = msm_vidc_session_streamon(inst, INPUT_PORT);
 	if (rc)
 		goto error;
 
-	s_vpr_h(inst->sid, "%s: done\n", __func__);
 	return 0;
 
 error:
 	s_vpr_e(inst->sid, "%s: failed\n", __func__);
-	msm_vdec_stop_input(inst);
+	msm_vdec_streamoff_input(inst);
 	return rc;
 }
 
-int msm_vdec_stop_output(struct msm_vidc_inst *inst)
+int msm_vdec_streamoff_output(struct msm_vidc_inst *inst)
 {
 	int rc = 0;
 
@@ -1266,7 +1262,7 @@ int msm_vdec_stop_output(struct msm_vidc_inst *inst)
 		return -EINVAL;
 	}
 
-	rc = msm_vidc_session_stop(inst, OUTPUT_PORT);
+	rc = msm_vidc_session_streamoff(inst, OUTPUT_PORT);
 	if (rc)
 		return rc;
 
@@ -1385,11 +1381,10 @@ static int msm_vdec_subscribe_output_port_settings_change(struct msm_vidc_inst *
 	return rc;
 }
 
-int msm_vdec_start_output(struct msm_vidc_inst *inst)
+int msm_vdec_streamon_output(struct msm_vidc_inst *inst)
 {
 	int rc = 0;
 
-	d_vpr_h("%s()\n", __func__);
 	if (!inst || !inst->core) {
 		d_vpr_e("%s: invalid params\n", __func__);
 		return -EINVAL;
@@ -1400,7 +1395,7 @@ int msm_vdec_start_output(struct msm_vidc_inst *inst)
 		s_vpr_e(inst->sid,
 			"%s: Meta port must be streamed on before data port\n",
 			__func__);
-		goto error;
+		return -EINVAL;
 	}
 
 	rc = msm_vdec_set_output_properties(inst);
@@ -1409,26 +1404,27 @@ int msm_vdec_start_output(struct msm_vidc_inst *inst)
 
 	if (!inst->opsc_properties_set) {
 		memcpy(&inst->subcr_params[OUTPUT_PORT],
-			&inst->subcr_params[INPUT_PORT], sizeof(inst->subcr_params[INPUT_PORT]));
+			   &inst->subcr_params[INPUT_PORT],
+			   sizeof(inst->subcr_params[INPUT_PORT]));
 		rc = msm_vdec_subscribe_output_port_settings_change(inst, OUTPUT_PORT);
 		if (rc)
-			return rc;
+			goto error;
 		inst->opsc_properties_set = true;
 	}
 
 	rc = msm_vdec_subscribe_metadata(inst, OUTPUT_PORT);
 	if (rc)
-		return rc;
+		goto error;
 
-	rc = msm_vidc_session_start(inst, OUTPUT_PORT);
+	rc = msm_vidc_session_streamon(inst, OUTPUT_PORT);
 	if (rc)
 		goto error;
 
-	d_vpr_h("%s: done\n", __func__);
 	return 0;
 
 error:
-	msm_vdec_stop_output(inst);
+	s_vpr_e(inst->sid, "%s: failed\n", __func__);
+	msm_vdec_streamoff_output(inst);
 	return rc;
 }
 
@@ -1468,6 +1464,8 @@ int msm_vdec_process_cmd(struct msm_vidc_inst *inst, u32 cmd)
 	}
 
 	if (cmd == V4L2_DEC_CMD_STOP) {
+		if (!msm_vidc_allow_stop(inst))
+			return -EBUSY;
 		rc = venus_hfi_session_command(inst,
 				HFI_CMD_DRAIN,
 				INPUT_PORT,
@@ -1476,6 +1474,23 @@ int msm_vdec_process_cmd(struct msm_vidc_inst *inst, u32 cmd)
 				0);
 		if (rc)
 			return rc;
+		rc = msm_vidc_state_change_stop(inst);
+		if (rc)
+			return rc;
+	} else if (cmd == V4L2_DEC_CMD_START) {
+		if (!msm_vidc_allow_start(inst))
+			return -EBUSY;
+		rc = msm_vidc_state_change_start(inst);
+		if (rc)
+			return rc;
+		rc = venus_hfi_session_command(inst,
+				HFI_CMD_RESUME,
+				OUTPUT_PORT,
+				HFI_PAYLOAD_NONE,
+				NULL,
+				0);
+		if (rc)
+			return rc;
 	} else {
 		d_vpr_e("%s: unknown cmd %d\n", __func__, cmd);
 		return -EINVAL;
@@ -1490,23 +1505,13 @@ int msm_vdec_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
 	struct msm_vidc_core *core;
 	struct v4l2_format *fmt;
 
-	d_vpr_h("%s()\n", __func__);
 	if (!inst || !inst->core) {
 		d_vpr_e("%s: invalid params\n", __func__);
 		return -EINVAL;
 	}
 	core = inst->core;
 
-	if (inst->state == MSM_VIDC_START) {
-		d_vpr_e("%s: invalid state %d\n", __func__, inst->state);
-		return -EINVAL;
-	}
-
 	if (f->type == INPUT_MPLANE) {
-		if (inst->state == MSM_VIDC_START_INPUT) {
-			d_vpr_e("%s: invalid state %d\n", __func__, inst->state);
-			return -EINVAL;
-		}
 		if (inst->fmts[INPUT_PORT].fmt.pix_mp.pixelformat !=
 			f->fmt.pix_mp.pixelformat) {
 			s_vpr_e(inst->sid,
@@ -1562,10 +1567,6 @@ int msm_vdec_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
 		//msm_vidc_update_batching(inst);
 
 	} else if (f->type == INPUT_META_PLANE) {
-		if (inst->state == MSM_VIDC_START_INPUT) {
-			d_vpr_e("%s: invalid state %d\n", __func__, inst->state);
-			return -EINVAL;
-		}
 		fmt = &inst->fmts[INPUT_META_PORT];
 		fmt->type = INPUT_META_PLANE;
 		fmt->fmt.meta.dataformat = V4L2_META_FMT_VIDC;
@@ -1592,10 +1593,6 @@ int msm_vdec_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
 			inst->buffers.input_meta.min_count,
 			inst->buffers.input_meta.extra_count);
 	} else if (f->type == OUTPUT_MPLANE) {
-		if (inst->state == MSM_VIDC_START_OUTPUT) {
-			d_vpr_e("%s: invalid state %d\n", __func__, inst->state);
-			return -EINVAL;
-		}
 		fmt = &inst->fmts[OUTPUT_PORT];
 		fmt->type = OUTPUT_MPLANE;
 		fmt->fmt.pix_mp.pixelformat = f->fmt.pix_mp.pixelformat;
@@ -1637,10 +1634,6 @@ int msm_vdec_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
 			inst->buffers.output.min_count,
 			inst->buffers.output.extra_count);
 	} else if (f->type == OUTPUT_META_PLANE) {
-		if (inst->state == MSM_VIDC_START_OUTPUT) {
-			d_vpr_e("%s: invalid state %d\n", __func__, inst->state);
-			return -EINVAL;
-		}
 		fmt = &inst->fmts[OUTPUT_META_PORT];
 		fmt->type = OUTPUT_META_PLANE;
 		fmt->fmt.meta.dataformat = V4L2_META_FMT_VIDC;
@@ -1681,7 +1674,6 @@ int msm_vdec_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
 	int rc = 0;
 	int port;
 
-	d_vpr_h("%s()\n", __func__);
 	if (!inst) {
 		d_vpr_e("%s: invalid params\n", __func__);
 		return -EINVAL;
@@ -1767,7 +1759,6 @@ int msm_vdec_inst_init(struct msm_vidc_inst *inst)
 	struct msm_vidc_core *core;
 	struct v4l2_format *f;
 
-	d_vpr_h("%s()\n", __func__);
 	if (!inst || !inst->core) {
 		d_vpr_e("%s: invalid params\n", __func__);
 		return -EINVAL;
@@ -1850,3 +1841,16 @@ int msm_vdec_inst_init(struct msm_vidc_inst *inst)
 
 	return rc;
 }
+
+int msm_vdec_inst_deinit(struct msm_vidc_inst *inst)
+{
+	int rc = 0;
+
+	if (!inst) {
+		d_vpr_e("%s: invalid params\n", __func__);
+		return -EINVAL;
+	}
+	rc = msm_vidc_ctrl_deinit(inst);
+
+	return rc;
+}

+ 43 - 45
driver/vidc/src/msm_venc.c

@@ -701,7 +701,7 @@ static int msm_venc_metadata_subscription(struct msm_vidc_inst *inst,
 	return rc;
 }
 
-int msm_venc_stop_input(struct msm_vidc_inst *inst)
+int msm_venc_streamoff_input(struct msm_vidc_inst *inst)
 {
 	int rc = 0;
 
@@ -710,31 +710,28 @@ int msm_venc_stop_input(struct msm_vidc_inst *inst)
 		return -EINVAL;
 	}
 
-	rc = msm_vidc_session_stop(inst, INPUT_PORT);
+	rc = msm_vidc_session_streamoff(inst, INPUT_PORT);
 	if (rc)
 		return rc;
 
 	return 0;
 }
 
-int msm_venc_start_input(struct msm_vidc_inst *inst)
+int msm_venc_streamon_input(struct msm_vidc_inst *inst)
 {
 	int rc = 0;
-	struct msm_vidc_core *core;
 
 	if (!inst || !inst->core) {
 		d_vpr_e("%s: invalid params\n", __func__);
 		return -EINVAL;
 	}
-	core = inst->core;
-	s_vpr_h(inst->sid, "%s()\n", __func__);
 
 	if (is_input_meta_enabled(inst) &&
 		!inst->vb2q[INPUT_META_PORT].streaming) {
 		s_vpr_e(inst->sid,
 			"%s: Meta port must be streamed on before data port\n",
 			__func__);
-		goto error;
+		return -EINVAL;
 	}
 
 	//rc = msm_vidc_check_session_supported(inst);
@@ -780,16 +777,15 @@ int msm_venc_start_input(struct msm_vidc_inst *inst)
 	if (rc)
 		return rc;
 
-	rc = msm_vidc_session_start(inst, INPUT_PORT);
+	rc = msm_vidc_session_streamon(inst, INPUT_PORT);
 	if (rc)
 		goto error;
 
-	s_vpr_h(inst->sid, "%s: done\n", __func__);
 	return 0;
 
 error:
 	s_vpr_e(inst->sid, "%s: failed\n", __func__);
-	msm_venc_stop_input(inst);
+	msm_venc_streamoff_input(inst);
 	return rc;
 }
 
@@ -803,6 +799,8 @@ int msm_venc_process_cmd(struct msm_vidc_inst *inst, u32 cmd)
 	}
 
 	if (cmd == V4L2_ENC_CMD_STOP) {
+		if (!msm_vidc_allow_stop(inst))
+			return -EBUSY;
 		rc = venus_hfi_session_command(inst,
 				HFI_CMD_DRAIN,
 				INPUT_PORT,
@@ -811,6 +809,17 @@ int msm_venc_process_cmd(struct msm_vidc_inst *inst, u32 cmd)
 				0);
 		if (rc)
 			return rc;
+	} else if (cmd == V4L2_ENC_CMD_START) {
+		if (!msm_vidc_allow_start(inst))
+			return -EBUSY;
+		rc = venus_hfi_session_command(inst,
+				HFI_CMD_RESUME,
+				INPUT_PORT,
+				HFI_PAYLOAD_NONE,
+				NULL,
+				0);
+		if (rc)
+			return rc;
 	} else {
 		d_vpr_e("%s: unknown cmd %d\n", __func__, cmd);
 		return -EINVAL;
@@ -818,7 +827,7 @@ int msm_venc_process_cmd(struct msm_vidc_inst *inst, u32 cmd)
 	return 0;
 }
 
-int msm_venc_stop_output(struct msm_vidc_inst *inst)
+int msm_venc_streamoff_output(struct msm_vidc_inst *inst)
 {
 	int rc = 0;
 
@@ -827,18 +836,17 @@ int msm_venc_stop_output(struct msm_vidc_inst *inst)
 		return -EINVAL;
 	}
 
-	rc = msm_vidc_session_stop(inst, OUTPUT_PORT);
+	rc = msm_vidc_session_streamoff(inst, OUTPUT_PORT);
 	if (rc)
 		return rc;
 
 	return 0;
 }
 
-int msm_venc_start_output(struct msm_vidc_inst *inst)
+int msm_venc_streamon_output(struct msm_vidc_inst *inst)
 {
 	int rc = 0;
 
-	d_vpr_h("%s()\n", __func__);
 	if (!inst || !inst->core) {
 		d_vpr_e("%s: invalid params\n", __func__);
 		return -EINVAL;
@@ -849,7 +857,7 @@ int msm_venc_start_output(struct msm_vidc_inst *inst)
 		s_vpr_e(inst->sid,
 			"%s: Meta port must be streamed on before data port\n",
 			__func__);
-		goto error;
+		return -EINVAL;
 	}
 
 	rc = msm_venc_set_output_properties(inst);
@@ -858,11 +866,11 @@ int msm_venc_start_output(struct msm_vidc_inst *inst)
 
 	rc = msm_vidc_adjust_v4l2_properties(inst);
 	if (rc)
-		return -EINVAL;
+		goto error;
 
 	rc = msm_vidc_set_v4l2_properties(inst);
 	if (rc)
-		return -EINVAL;
+		goto error;
 
 	rc = msm_venc_set_internal_properties(inst);
 	if (rc)
@@ -870,21 +878,21 @@ int msm_venc_start_output(struct msm_vidc_inst *inst)
 
 	rc = msm_venc_property_subscription(inst, OUTPUT_PORT);
 	if (rc)
-		return rc;
+		goto error;
 
 	rc = msm_venc_metadata_subscription(inst, OUTPUT_PORT);
 	if (rc)
-		return rc;
+		goto error;
 
-	rc = msm_vidc_session_start(inst, OUTPUT_PORT);
+	rc = msm_vidc_session_streamon(inst, OUTPUT_PORT);
 	if (rc)
 		goto error;
 
-	d_vpr_h("%s: done\n", __func__);
 	return 0;
 
 error:
-	msm_venc_stop_output(inst);
+	s_vpr_e(inst->sid, "%s: failed\n", __func__);
+	msm_venc_streamoff_output(inst);
 	return rc;
 }
 
@@ -894,23 +902,13 @@ int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
 	struct msm_vidc_core *core;
 	struct v4l2_format *fmt;
 
-	d_vpr_h("%s()\n", __func__);
 	if (!inst || !inst->core) {
 		d_vpr_e("%s: invalid params\n", __func__);
 		return -EINVAL;
 	}
 	core = inst->core;
 
-	if (inst->state == MSM_VIDC_START) {
-		d_vpr_e("%s: invalid state %d\n", __func__, inst->state);
-		return -EINVAL;
-	}
-
 	if (f->type == INPUT_MPLANE) {
-		if (inst->state == MSM_VIDC_START_INPUT) {
-			d_vpr_e("%s: invalid state %d\n", __func__, inst->state);
-			return -EINVAL;
-		}
 		fmt = &inst->fmts[INPUT_PORT];
 		fmt->type = INPUT_MPLANE;
 		fmt->fmt.pix_mp.pixelformat = f->fmt.pix_mp.pixelformat;
@@ -959,10 +957,6 @@ int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
 		//msm_vidc_update_batching(inst);
 
 	} else if (f->type == INPUT_META_PLANE) {
-		if (inst->state == MSM_VIDC_START_INPUT) {
-			d_vpr_e("%s: invalid state %d\n", __func__, inst->state);
-			return -EINVAL;
-		}
 		fmt = &inst->fmts[INPUT_META_PORT];
 		fmt->type = INPUT_META_PLANE;
 		fmt->fmt.meta.dataformat = V4L2_META_FMT_VIDC;
@@ -989,10 +983,6 @@ int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
 			inst->buffers.input_meta.min_count,
 			inst->buffers.input_meta.extra_count);
 	} else if (f->type == OUTPUT_MPLANE) {
-		if (inst->state == MSM_VIDC_START_OUTPUT) {
-			d_vpr_e("%s: invalid state %d\n", __func__, inst->state);
-			return -EINVAL;
-		}
 		fmt = &inst->fmts[OUTPUT_PORT];
 		if (fmt->fmt.pix_mp.pixelformat != f->fmt.pix_mp.pixelformat) {
 			s_vpr_e(inst->sid,
@@ -1053,10 +1043,6 @@ int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
 			inst->buffers.output.min_count,
 			inst->buffers.output.extra_count);
 	} else if (f->type == OUTPUT_META_PLANE) {
-		if (inst->state == MSM_VIDC_START_OUTPUT) {
-			d_vpr_e("%s: invalid state %d\n", __func__, inst->state);
-			return -EINVAL;
-		}
 		fmt = &inst->fmts[OUTPUT_META_PORT];
 		fmt->type = OUTPUT_META_PLANE;
 		fmt->fmt.meta.dataformat = V4L2_META_FMT_VIDC;
@@ -1097,7 +1083,6 @@ int msm_venc_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
 	int rc = 0;
 	int port;
 
-	d_vpr_h("%s()\n", __func__);
 	if (!inst) {
 		d_vpr_e("%s: invalid params\n", __func__);
 		return -EINVAL;
@@ -1265,3 +1250,16 @@ int msm_venc_inst_init(struct msm_vidc_inst *inst)
 
 	return rc;
 }
+
+int msm_venc_inst_deinit(struct msm_vidc_inst *inst)
+{
+	int rc = 0;
+
+	if (!inst) {
+		d_vpr_e("%s: invalid params\n", __func__);
+		return -EINVAL;
+	}
+	rc = msm_vidc_ctrl_deinit(inst);
+
+	return rc;
+}

+ 81 - 184
driver/vidc/src/msm_vidc.c

@@ -15,6 +15,7 @@
 #include "msm_vidc_debug.h"
 #include "msm_vidc_control.h"
 #include "msm_vidc_power.h"
+#include "venus_hfi_response.h"
 
 #define MSM_VIDC_DRV_NAME "msm_vidc_driver"
 /* kernel/msm-4.19 */
@@ -68,6 +69,10 @@ int msm_vidc_poll(void *instance, struct file *filp,
 		d_vpr_e("%s: invalid params\n", __func__);
 		return -EINVAL;
 	}
+	if (inst->state == MSM_VIDC_ERROR) {
+		s_vpr_e(inst->sid, "%s: inst in error state\n", __func__);
+		return -EINVAL;
+	}
 
 	poll_wait(filp, &inst->event_handler.wait, wait);
 	poll_wait(filp, &inst->vb2q[INPUT_META_PORT].done_wq, wait);
@@ -216,24 +221,8 @@ int msm_vidc_s_fmt(void *instance, struct v4l2_format *f)
 		return -EINVAL;
 	}
 
-	if (f->type == INPUT_MPLANE) {
-		if (inst->state != MSM_VIDC_OPEN &&
-		    inst->state != MSM_VIDC_START_OUTPUT) {
-			s_vpr_e(inst->sid,
-				"%s: s_fmt(%d) not allowed in %d state\n",
-				__func__, f->type, inst->state);
-			return -EINVAL;
-		}
-	} else if (f->type == OUTPUT_MPLANE) {
-		if (inst->state != MSM_VIDC_OPEN &&
-		    inst->state != MSM_VIDC_START_INPUT &&
-		    inst->state != MSM_VIDC_DRAIN_START_INPUT) {
-			s_vpr_e(inst->sid,
-				"%s: s_fmt(%d) not allowed in %d state\n",
-				__func__, f->type, inst->state);
-			return -EINVAL;
-		}
-	}
+	if (!msm_vidc_allow_s_fmt(inst, f->type))
+		return -EBUSY;
 
 	if (inst->domain == MSM_VIDC_DECODER)
 		rc = msm_vdec_s_fmt(inst, f);
@@ -261,8 +250,18 @@ int msm_vidc_g_fmt(void *instance, struct v4l2_format *f)
 		rc = msm_vdec_g_fmt(inst, f);
 	if (inst->domain == MSM_VIDC_ENCODER)
 		rc = msm_venc_g_fmt(inst, f);
-
-	return rc;
+	if (rc)
+		return rc;
+
+	if (f->type == INPUT_MPLANE || f->type == OUTPUT_MPLANE)
+		s_vpr_h(inst->sid,
+			"%s: type %d format %#x width %d height %d size %d\n",
+			__func__, f->fmt.pix_mp.pixelformat, f->fmt.pix_mp.width,
+			f->fmt.pix_mp.height, f->fmt.pix_mp.plane_fmt[0].sizeimage);
+	else if (f->type == INPUT_META_PLANE || f->type == OUTPUT_META_PLANE)
+		s_vpr_h(inst->sid, "%s: meta type %d size %d\n",
+			__func__, f->type, f->fmt.meta.buffersize);
+	return 0;
 }
 EXPORT_SYMBOL(msm_vidc_g_fmt);
 
@@ -273,6 +272,9 @@ int msm_vidc_s_ctrl(void *instance, struct v4l2_control *control)
 	if (!inst || !control)
 		return -EINVAL;
 
+	if (!msm_vidc_allow_s_ctrl(inst, control->id))
+		return -EBUSY;
+
 	return v4l2_s_ctrl(NULL, &inst->ctrl_handler, control);
 }
 EXPORT_SYMBOL(msm_vidc_s_ctrl);
@@ -316,25 +318,9 @@ int msm_vidc_reqbufs(void *instance, struct v4l2_requestbuffers *b)
 
 	mutex_lock(&inst->lock);
 
-	if (b->type == INPUT_MPLANE) {
-		if (inst->state != MSM_VIDC_OPEN &&
-		    inst->state != MSM_VIDC_START_OUTPUT) {
-			s_vpr_e(inst->sid,
-				"%s: reqbufs(%d) not allowed in %d state\n",
-				__func__, b->type, inst->state);
-			rc = -EINVAL;
-			goto unlock;
-		}
-	} else if (b->type == OUTPUT_MPLANE) {
-		if (inst->state != MSM_VIDC_OPEN &&
-		    inst->state != MSM_VIDC_START_INPUT &&
-		    inst->state != MSM_VIDC_DRAIN_START_INPUT) {
-			s_vpr_e(inst->sid,
-				"%s: reqbufs(%d) not allowed in %d state\n",
-				__func__, b->type, inst->state);
-			rc = -EINVAL;
-			goto unlock;
-		}
+	if (!msm_vidc_allow_reqbufs(inst, b->type)) {
+		rc = -EBUSY;
+		goto unlock;
 	}
 
 	port = v4l2_type_to_driver_port(inst, b->type, __func__);
@@ -370,22 +356,13 @@ int msm_vidc_qbuf(void *instance, struct media_device *mdev,
 
 	mutex_lock(&inst->lock);
 
-	if (inst->state == MSM_VIDC_ERROR) {
-		s_vpr_e(inst->sid, "%s: error state\n", __func__);
-		rc = -EINVAL;
+	if (!msm_vidc_allow_qbuf(inst)) {
+		rc = -EBUSY;
 		goto unlock;
 	}
-	if (b->type == INPUT_MPLANE) {
-		q = &inst->vb2q[INPUT_PORT];
-	} else if (b->type == OUTPUT_MPLANE) {
-		q = &inst->vb2q[OUTPUT_PORT];
-	} else if (b->type == INPUT_META_PLANE) {
-		q = &inst->vb2q[INPUT_META_PORT];
-	} else if (b->type == OUTPUT_META_PLANE) {
-		q = &inst->vb2q[OUTPUT_META_PORT];
-	} else {
-		s_vpr_e(inst->sid, "%s: invalid buffer type %d\n",
-			__func__, b->type);
+
+	q = msm_vidc_get_vb2q(inst, b->type, __func__);
+	if (!q) {
 		rc = -EINVAL;
 		goto unlock;
 	}
@@ -412,17 +389,9 @@ int msm_vidc_dqbuf(void *instance, struct v4l2_buffer *b)
 	}
 
 	mutex_lock(&inst->lock);
-	if (b->type == INPUT_MPLANE) {
-		q = &inst->vb2q[INPUT_PORT];
-	} else if (b->type == OUTPUT_MPLANE) {
-		q = &inst->vb2q[OUTPUT_PORT];
-	} else if (b->type == INPUT_META_PLANE) {
-		q = &inst->vb2q[INPUT_META_PORT];
-	} else if (b->type == OUTPUT_META_PLANE) {
-		q = &inst->vb2q[OUTPUT_META_PORT];
-	} else {
-		s_vpr_e(inst->sid, "%s: invalid buffer type %d\n",
-			__func__, b->type);
+
+	q = msm_vidc_get_vb2q(inst, b->type, __func__);
+	if (!q) {
 		rc = -EINVAL;
 		goto unlock;
 	}
@@ -445,7 +414,6 @@ int msm_vidc_streamon(void *instance, enum v4l2_buf_type type)
 {
 	int rc = 0;
 	struct msm_vidc_inst *inst = instance;
-	enum msm_vidc_inst_state new_state = MSM_VIDC_ERROR;
 	int port;
 
 	if (!inst) {
@@ -455,26 +423,13 @@ int msm_vidc_streamon(void *instance, enum v4l2_buf_type type)
 
 	mutex_lock(&inst->lock);
 
-	if (type == INPUT_MPLANE) {
-		if (inst->state != MSM_VIDC_OPEN &&
-		    inst->state != MSM_VIDC_START_OUTPUT) {
-			s_vpr_e(inst->sid,
-				"%s: streamon(%d) not allowed in %d state\n",
-				__func__, type, inst->state);
-			rc = -EINVAL;
-			goto unlock;
-		}
-	} else if (type == OUTPUT_MPLANE) {
-		if (inst->state != MSM_VIDC_OPEN &&
-		    inst->state != MSM_VIDC_START_INPUT &&
-		    inst->state != MSM_VIDC_DRAIN_START_INPUT) {
-			s_vpr_e(inst->sid,
-				"%s: streamon(%d) not allowed in %d state\n",
-				__func__, type, inst->state);
-			rc = -EINVAL;
-			goto unlock;
-		}
+	if (!msm_vidc_allow_streamon(inst, type)) {
+		rc = -EBUSY;
+		goto unlock;
 	}
+	rc = msm_vidc_state_change_streamon(inst, type);
+	if (rc)
+		goto unlock;
 
 	port = v4l2_type_to_driver_port(inst, type, __func__);
 	if (port < 0) {
@@ -486,34 +441,10 @@ int msm_vidc_streamon(void *instance, enum v4l2_buf_type type)
 	if (rc) {
 		s_vpr_e(inst->sid, "%s: vb2_streamon(%d) failed, %d\n",
 			__func__, type, rc);
+		msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__);
 		goto unlock;
 	}
 
-	if (type == INPUT_MPLANE) {
-		if (inst->state == MSM_VIDC_OPEN) {
-			new_state = MSM_VIDC_START_INPUT;
-		} else if (inst->state == MSM_VIDC_START_OUTPUT) {
-			new_state = MSM_VIDC_START;
-		}
-		rc = msm_vidc_change_inst_state(inst, new_state, __func__);
-		if (rc)
-			goto unlock;
-	} else if (type == OUTPUT_MPLANE) {
-		if (inst->state == MSM_VIDC_OPEN) {
-			new_state = MSM_VIDC_START_OUTPUT;
-		} else if (inst->state == MSM_VIDC_START_INPUT) {
-			new_state = MSM_VIDC_START;
-		} else if (inst->state == MSM_VIDC_DRAIN_START_INPUT) {
-			if (0 /* check if input port settings change pending */)
-				new_state = MSM_VIDC_DRC_DRAIN;
-			else
-				new_state = MSM_VIDC_DRAIN;
-		}
-		rc = msm_vidc_change_inst_state(inst, new_state, __func__);
-		if (rc)
-			goto unlock;
-	}
-
 unlock:
 	mutex_unlock(&inst->lock);
 	return rc;
@@ -524,7 +455,6 @@ int msm_vidc_streamoff(void *instance, enum v4l2_buf_type type)
 {
 	int rc = 0;
 	struct msm_vidc_inst *inst = instance;
-	enum msm_vidc_inst_state new_state = MSM_VIDC_ERROR;
 	int port;
 
 	if (!inst) {
@@ -534,25 +464,13 @@ int msm_vidc_streamoff(void *instance, enum v4l2_buf_type type)
 
 	mutex_lock(&inst->lock);
 
-	if (type == INPUT_MPLANE) {
-		if (inst->state == MSM_VIDC_OPEN ||
-		    inst->state == MSM_VIDC_START_OUTPUT) {
-			s_vpr_e(inst->sid,
-				"%s: streamoff(%d) not allowed in %d state\n",
-				__func__, type, inst->state);
-			rc = -EINVAL;
-			goto unlock;
-		}
-	} else if (type == OUTPUT_MPLANE) {
-		if (inst->state == MSM_VIDC_OPEN ||
-		    inst->state == MSM_VIDC_START_INPUT) {
-			s_vpr_e(inst->sid,
-				"%s: streamoff(%d) not allowed in %d state\n",
-				__func__, type, inst->state);
-			rc = -EINVAL;
-			goto unlock;
-		}
+	if (!msm_vidc_allow_streamoff(inst, type)) {
+		rc = -EBUSY;
+		goto unlock;
 	}
+	rc = msm_vidc_state_change_streamoff(inst, type);
+	if (rc)
+		goto unlock;
 
 	port = v4l2_type_to_driver_port(inst, type, __func__);
 	if (port < 0) {
@@ -564,45 +482,10 @@ int msm_vidc_streamoff(void *instance, enum v4l2_buf_type type)
 	if (rc) {
 		s_vpr_e(inst->sid, "%s: vb2_streamoff(%d) failed, %d\n",
 			__func__, type, rc);
+		msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__);
 		goto unlock;
 	}
 
-	if (type == INPUT_MPLANE) {
-		if (inst->state == MSM_VIDC_START_INPUT) {
-			new_state = MSM_VIDC_OPEN;
-		} else if (inst->state == MSM_VIDC_START) {
-			new_state = MSM_VIDC_START_OUTPUT;
-		} else if (inst->state == MSM_VIDC_DRC ||
-			   inst->state == MSM_VIDC_DRC_LAST_FLAG ||
-			   inst->state == MSM_VIDC_DRAIN ||
-		           inst->state == MSM_VIDC_DRAIN_LAST_FLAG ||
-			   inst->state == MSM_VIDC_DRC_DRAIN ||
-			   inst->state == MSM_VIDC_DRC_DRAIN_LAST_FLAG ||
-			   inst->state == MSM_VIDC_DRAIN_START_INPUT) {
-			new_state = MSM_VIDC_START_OUTPUT;
-			/* discard pending port settings change if any */
-		}
-		rc = msm_vidc_change_inst_state(inst, new_state, __func__);
-		if (rc)
-			goto unlock;
-	} else if (type == OUTPUT_MPLANE) {
-		if (inst->state == MSM_VIDC_START_OUTPUT) {
-			new_state = MSM_VIDC_OPEN;
-		} else if (inst->state == MSM_VIDC_START ||
-			   inst->state == MSM_VIDC_DRAIN ||
-			   inst->state == MSM_VIDC_DRAIN_LAST_FLAG ||
-			   inst->state == MSM_VIDC_DRC ||
-			   inst->state == MSM_VIDC_DRC_LAST_FLAG ||
-			   inst->state == MSM_VIDC_DRC_DRAIN) {
-			new_state = MSM_VIDC_START_INPUT;
-		} else if (inst->state == MSM_VIDC_DRC_DRAIN_LAST_FLAG) {
-			new_state = MSM_VIDC_DRAIN_START_INPUT;
-		}
-		rc = msm_vidc_change_inst_state(inst, new_state, __func__);
-		if (rc)
-			goto unlock;
-	}
-
 unlock:
 	mutex_unlock(&inst->lock);
 	return rc;
@@ -740,8 +623,10 @@ void *msm_vidc_open(void *vidc_core, u32 session_type)
 
 	if (core->state == MSM_VIDC_CORE_DEINIT) {
 		rc = msm_vidc_core_init(core);
-		if (rc)
+		if (rc) {
+			msm_vidc_core_deinit(core);
 			return NULL;
+		}
 	}
 
 	inst = kzalloc(sizeof(*inst), GFP_KERNEL);
@@ -750,25 +635,34 @@ void *msm_vidc_open(void *vidc_core, u32 session_type)
 		return NULL;
 	}
 	inst->core = core;
+	kref_init(&inst->kref);
+	mutex_init(&inst->lock);
+
+	rc = msm_vidc_add_session(inst);
+	if (rc) {
+		d_vpr_e("%s: failed to get session id\n", __func__);
+		goto error;
+	}
+	s_vpr_i(inst->sid, "Opening video instance: %d\n", session_type);
+
+	inst->input_psc_workq = create_singlethread_workqueue("input_psc_workq");
+	if (!inst->input_psc_workq) {
+		d_vpr_e("%s: create input_psc_workq failed\n", __func__);
+		goto error;
+	}
 
 	inst->capabilities = kzalloc(
 		sizeof(struct msm_vidc_inst_capability), GFP_KERNEL);
 	if (!inst->capabilities) {
 		s_vpr_e(inst->sid,
 			"%s: inst capability allocation failed\n", __func__);
-		return NULL;
-	}
-
-	rc = msm_vidc_add_session(inst);
-	if (rc) {
-		d_vpr_e("%s: failed to get session id\n", __func__);
-		return NULL;
+		goto error;
 	}
 
-	s_vpr_i(inst->sid, "Opening video instance: %d\n", session_type);
+	INIT_DELAYED_WORK(&inst->input_psc_work,
+			handle_session_input_psc_work_handler);
 
-	kref_init(&inst->kref);
-	mutex_init(&inst->lock);
+	INIT_LIST_HEAD(&inst->input_psc_works);
 	INIT_LIST_HEAD(&inst->buffers.input.list);
 	INIT_LIST_HEAD(&inst->buffers.input_meta.list);
 	INIT_LIST_HEAD(&inst->buffers.output.list);
@@ -780,6 +674,7 @@ void *msm_vidc_open(void *vidc_core, u32 session_type)
 	INIT_LIST_HEAD(&inst->buffers.line.list);
 	INIT_LIST_HEAD(&inst->buffers.dpb.list);
 	INIT_LIST_HEAD(&inst->buffers.persist.list);
+	INIT_LIST_HEAD(&inst->buffers.vpss.list);
 	INIT_LIST_HEAD(&inst->allocations.bin.list);
 	INIT_LIST_HEAD(&inst->allocations.arp.list);
 	INIT_LIST_HEAD(&inst->allocations.comv.list);
@@ -787,6 +682,7 @@ void *msm_vidc_open(void *vidc_core, u32 session_type)
 	INIT_LIST_HEAD(&inst->allocations.line.list);
 	INIT_LIST_HEAD(&inst->allocations.dpb.list);
 	INIT_LIST_HEAD(&inst->allocations.persist.list);
+	INIT_LIST_HEAD(&inst->allocations.vpss.list);
 	INIT_LIST_HEAD(&inst->mappings.input.list);
 	INIT_LIST_HEAD(&inst->mappings.input_meta.list);
 	INIT_LIST_HEAD(&inst->mappings.output.list);
@@ -798,6 +694,7 @@ void *msm_vidc_open(void *vidc_core, u32 session_type)
 	INIT_LIST_HEAD(&inst->mappings.line.list);
 	INIT_LIST_HEAD(&inst->mappings.dpb.list);
 	INIT_LIST_HEAD(&inst->mappings.persist.list);
+	INIT_LIST_HEAD(&inst->mappings.vpss.list);
 	INIT_LIST_HEAD(&inst->children.list);
 	INIT_LIST_HEAD(&inst->firmware.list);
 	inst->domain = session_type;
@@ -812,21 +709,18 @@ void *msm_vidc_open(void *vidc_core, u32 session_type)
 	//inst->debugfs_root =
 	//	msm_vidc_debugfs_init_inst(inst, core->debugfs_root);
 
-	if (is_decode_session(inst)) {
+	if (is_decode_session(inst))
 		rc = msm_vdec_inst_init(inst);
-		if (rc)
-			goto error;
-	} else if (is_encode_session(inst)) {
+	else if (is_encode_session(inst))
 		rc = msm_venc_inst_init(inst);
-		if (rc)
-			goto error;
-	}
+	if (rc)
+		goto error;
 
 	rc = msm_vidc_vb2_queue_init(inst);
 	if (rc)
 		goto error;
 
-	rc = msm_vidc_setup_event_queue(inst);
+	rc = msm_vidc_event_queue_init(inst);
 	if (rc)
 		goto error;
 
@@ -854,9 +748,12 @@ int msm_vidc_close(void *instance)
 		return -EINVAL;
 	}
 	s_vpr_h(inst->sid, "%s()\n", __func__);
+	mutex_lock(&inst->lock);
 	msm_vidc_session_close(inst);
 	msm_vidc_remove_session(inst);
-
+	msm_vidc_destroy_buffers(inst);
+	mutex_unlock(&inst->lock);
+	put_inst(inst);
 	return rc;
 }
 EXPORT_SYMBOL(msm_vidc_close);

+ 2 - 2
driver/vidc/src/msm_vidc_control.c

@@ -346,7 +346,7 @@ int msm_vidc_ctrl_deinit(struct msm_vidc_inst *inst)
 		d_vpr_e("%s: invalid parameters\n", __func__);
 		return -EINVAL;
 	}
-
+	s_vpr_h(inst->sid, "%s(): num ctrls %d\n", __func__, inst->num_ctrls);
 	v4l2_ctrl_handler_free(&inst->ctrl_handler);
 	kfree(inst->ctrls);
 
@@ -362,7 +362,6 @@ int msm_vidc_ctrl_init(struct msm_vidc_inst *inst)
 	struct v4l2_ctrl_config ctrl_cfg = {0};
 	int num_ctrls = 0, ctrl_idx = 0;
 
-	d_vpr_h("%s()\n", __func__);
 	if (!inst || !inst->core || !inst->capabilities) {
 		d_vpr_e("%s: invalid params\n", __func__);
 		return -EINVAL;
@@ -497,6 +496,7 @@ int msm_vidc_ctrl_init(struct msm_vidc_inst *inst)
 		ctrl_idx++;
 	}
 	inst->num_ctrls = num_ctrls;
+	s_vpr_h(inst->sid, "%s(): num ctrls %d\n", __func__, inst->num_ctrls);
 
 	return rc;
 }

文件差异内容过多而无法显示
+ 752 - 32
driver/vidc/src/msm_vidc_driver.c


+ 4 - 10
driver/vidc/src/msm_vidc_probe.c

@@ -20,6 +20,8 @@
 
 #define BASE_DEVICE_NUMBER 32
 
+struct msm_vidc_core *g_core;
+
 static int msm_vidc_deinit_irq(struct msm_vidc_core *core)
 {
 	struct msm_vidc_dt *dt;
@@ -214,25 +216,15 @@ static int msm_vidc_initialize_core(struct msm_vidc_core *core)
 		goto exit;
 	}
 
-	core->inst_workq = create_singlethread_workqueue("inst_workq");
-	if (!core->inst_workq) {
-		d_vpr_e("%s: create workq failed\n", __func__);
-		destroy_workqueue(core->inst_workq);
-		rc = -EINVAL;
-		goto exit;
-	}
-
 	mutex_init(&core->lock);
 	INIT_LIST_HEAD(&core->instances);
 	INIT_LIST_HEAD(&core->dangling_instances);
-	INIT_LIST_HEAD(&core->inst_works);
 
 	INIT_WORK(&core->device_work, venus_hfi_work_handler);
 	INIT_DELAYED_WORK(&core->pm_work, venus_hfi_pm_work_handler);
 	INIT_DELAYED_WORK(&core->fw_unload_work, msm_vidc_fw_unload_handler);
 	INIT_DELAYED_WORK(&core->batch_work, msm_vidc_batch_handler);
 	INIT_WORK(&core->ssr_work, msm_vidc_ssr_handler);
-	INIT_DELAYED_WORK(&core->inst_work, venus_hfi_inst_work_handler);
 
 exit:
 	return rc;
@@ -249,6 +241,7 @@ static int msm_vidc_probe_video_device(struct platform_device *pdev)
 	core = kzalloc(sizeof(*core), GFP_KERNEL);
 	if (!core)
 		return -ENOMEM;
+	g_core = core;
 
 	core->pdev = pdev;
 	dev_set_drvdata(&pdev->dev, core);
@@ -379,6 +372,7 @@ static int msm_vidc_remove(struct platform_device *pdev)
 	msm_vidc_deinitialize_core(core);
 	dev_set_drvdata(&pdev->dev, NULL);
 	kfree(core);
+	g_core = NULL;
 	return 0;
 }
 

+ 40 - 38
driver/vidc/src/msm_vidc_vb2.c

@@ -13,6 +13,30 @@
 #include "msm_vidc_debug.h"
 #include "msm_vidc_control.h"
 
+struct vb2_queue *msm_vidc_get_vb2q(struct msm_vidc_inst *inst,
+	u32 type, const char *func)
+{
+	struct vb2_queue *q = NULL;
+
+	if (!inst) {
+		d_vpr_e("%s: invalid buffer type %d\n", func);
+		return NULL;
+	}
+	if (type == INPUT_MPLANE) {
+		q = &inst->vb2q[INPUT_PORT];
+	} else if (type == OUTPUT_MPLANE) {
+		q = &inst->vb2q[OUTPUT_PORT];
+	} else if (type == INPUT_META_PLANE) {
+		q = &inst->vb2q[INPUT_META_PORT];
+	} else if (type == OUTPUT_META_PLANE) {
+		q = &inst->vb2q[OUTPUT_META_PORT];
+	} else {
+		s_vpr_e(inst->sid, "%s: invalid buffer type %d\n",
+			__func__, type);
+	}
+	return q;
+}
+
 void *msm_vb2_get_userptr(struct device *dev, unsigned long vaddr,
 			unsigned long size, enum dma_data_direction dma_dir)
 {
@@ -72,12 +96,6 @@ int msm_vidc_queue_setup(struct vb2_queue *q,
 		return -EINVAL;
 
 	if (port == INPUT_PORT) {
-		if (inst->state == MSM_VIDC_START_INPUT) {
-			d_vpr_e("%s: input invalid state %d\n",
-				__func__, inst->state);
-			return -EINVAL;
-		}
-
 		*num_planes = 1;
 		if (*num_buffers < inst->buffers.input.min_count +
 			inst->buffers.input.extra_count)
@@ -86,12 +104,6 @@ int msm_vidc_queue_setup(struct vb2_queue *q,
 		inst->buffers.input.actual_count = *num_buffers;
 
 	} else if (port == INPUT_META_PORT) {
-		if (inst->state == MSM_VIDC_START_INPUT) {
-			d_vpr_e("%s: input_meta invalid state %d\n",
-				__func__, inst->state);
-			return -EINVAL;
-		}
-
 		*num_planes = 1;
 		if (*num_buffers < inst->buffers.input_meta.min_count +
 			inst->buffers.input_meta.extra_count)
@@ -100,12 +112,6 @@ int msm_vidc_queue_setup(struct vb2_queue *q,
 		inst->buffers.input_meta.actual_count = *num_buffers;
 
 	} else if (port == OUTPUT_PORT) {
-		if (inst->state == MSM_VIDC_START_OUTPUT) {
-			d_vpr_e("%s: output invalid state %d\n",
-				__func__, inst->state);
-			return -EINVAL;
-		}
-
 		*num_planes = 1;
 		if (*num_buffers < inst->buffers.output.min_count +
 			inst->buffers.output.extra_count)
@@ -114,12 +120,6 @@ int msm_vidc_queue_setup(struct vb2_queue *q,
 		inst->buffers.output.actual_count = *num_buffers;
 
 	} else if (port == OUTPUT_META_PORT) {
-		if (inst->state == MSM_VIDC_START_OUTPUT) {
-			d_vpr_e("%s: output_meta invalid state %d\n",
-				__func__, inst->state);
-			return -EINVAL;
-		}
-
 		*num_planes = 1;
 		if (*num_buffers < inst->buffers.output_meta.min_count +
 			inst->buffers.output_meta.extra_count)
@@ -174,26 +174,29 @@ int msm_vidc_start_streaming(struct vb2_queue *q, unsigned int count)
 
 	if (q->type == INPUT_MPLANE) {
 		if (is_decode_session(inst))
-			rc = msm_vdec_start_input(inst);
+			rc = msm_vdec_streamon_input(inst);
 		else if (is_encode_session(inst))
-			rc = msm_venc_start_input(inst);
+			rc = msm_venc_streamon_input(inst);
 		else
 			goto error;
 	} else if (q->type == OUTPUT_MPLANE) {
 		if (is_decode_session(inst))
-			rc = msm_vdec_start_output(inst);
+			rc = msm_vdec_streamon_output(inst);
 		else if (is_encode_session(inst))
-			rc = msm_venc_start_output(inst);
+			rc = msm_venc_streamon_output(inst);
 		else
 			goto error;
 	} else {
+		s_vpr_e(inst->sid, "%s: invalid type %d\n", q->type);
 		goto error;
 	}
 
+	if (!rc)
+		s_vpr_h(inst->sid, "Streamon: %d successful\n", q->type);
 	return rc;
 
 error:
-	s_vpr_e(inst->sid, "%s: invalid session/qtype, qtype %d\n", __func__, q->type);
+	s_vpr_h(inst->sid, "Streamon: %d failed\n", q->type);
 	return -EINVAL;
 }
 
@@ -225,30 +228,29 @@ void msm_vidc_stop_streaming(struct vb2_queue *q)
 
 	if (q->type == INPUT_MPLANE) {
 		if (is_decode_session(inst))
-			rc = msm_vdec_stop_input(inst);
+			rc = msm_vdec_streamoff_input(inst);
 		else if (is_encode_session(inst))
-			rc = msm_venc_stop_input(inst);
+			rc = msm_venc_streamoff_input(inst);
 		else
 			goto error;
 	} else if (q->type == OUTPUT_MPLANE) {
 		if (is_decode_session(inst))
-			rc = msm_vdec_stop_output(inst);
+			rc = msm_vdec_streamoff_output(inst);
 		else if (is_encode_session(inst))
-			rc = msm_venc_stop_output(inst);
+			rc = msm_venc_streamoff_output(inst);
 		else
 			goto error;
 	} else {
+		s_vpr_e(inst->sid, "%s: invalid type %d\n", q->type);
 		goto error;
 	}
 
-	if (rc)
-		s_vpr_e(inst->sid, "%s: stop failed for qtype: %d\n",
-			__func__, q->type);
+	if (!rc)
+		s_vpr_h(inst->sid, "Streamoff: %d successful\n", q->type);
 	return;
 
 error:
-	s_vpr_e(inst->sid, "%s: invalid session/qtype, qtype: %d\n",
-			__func__, q->type);
+	s_vpr_e(inst->sid, "Streamoff: %d failed\n", q->type);
 	return;
 }
 

+ 37 - 19
driver/vidc/src/venus_hfi.c

@@ -2080,7 +2080,7 @@ static void __set_queue_hdr_defaults(struct hfi_queue_header *q_hdr)
 	q_hdr->qhdr_write_idx = 0x0;
 }
 
-static void __interface_queues_release(struct msm_vidc_core *core)
+static void __interface_queues_deinit(struct msm_vidc_core *core)
 {
 	int i;
 
@@ -2394,7 +2394,7 @@ static void __unload_fw(struct msm_vidc_core *core)
 	qcom_scm_pas_shutdown(core->dt->fw_cookie);
 	core->dt->fw_cookie = 0;
 
-	__interface_queues_release(core);
+	__interface_queues_deinit(core);
 	call_venus_op(core, power_off, core);
 
 	__deinit_resources(core);
@@ -2425,7 +2425,7 @@ irqreturn_t venus_hfi_isr(int irq, void *data)
 {
 	struct msm_vidc_core *core = data;
 
-	d_vpr_e("%s()\n", __func__);
+	d_vpr_l("%s()\n", __func__);
 
 	disable_irq_nosync(irq);
 	queue_work(core->device_workq, &core->device_work);
@@ -2443,7 +2443,6 @@ void venus_hfi_work_handler(struct work_struct *work)
 		d_vpr_e("%s: invalid params\n", __func__);
 		return;
 	}
-	d_vpr_e("%s(): core %pK\n", __func__, core);
 
 	mutex_lock(&core->lock);
 	if (__resume(core)) {
@@ -2546,12 +2545,11 @@ int venus_hfi_core_init(struct msm_vidc_core *core)
 {
 	int rc = 0;
 
-	d_vpr_h("%s(): core %p\n", __func__, core);
-
 	if (!core) {
 		d_vpr_e("%s: invalid params\n", __func__);
 		return -EINVAL;
 	}
+	d_vpr_h("%s(): core %pK\n", __func__, core);
 
 	core->packet_size = 4096;
 	core->packet = kzalloc(core->packet_size, GFP_KERNEL);
@@ -2580,27 +2578,49 @@ int venus_hfi_core_init(struct msm_vidc_core *core)
 	if (rc)
 		goto error;
 
-	__sys_init(core);
-	__sys_image_version(core);
-	__sys_set_debug(core, (msm_vidc_debug & FW_LOGMASK) >> FW_LOGSHIFT);
-	__enable_subcaches(core);
-	__set_subcaches(core);
+	rc = __enable_subcaches(core);
+	if (rc)
+		goto error;
+
+	rc = __sys_init(core);
+	if (rc)
+		goto error;
+
+	rc = __sys_image_version(core);
+	if (rc)
+		goto error;
+
+	rc = __sys_set_debug(core, (msm_vidc_debug & FW_LOGMASK) >> FW_LOGSHIFT);
+	if (rc)
+		goto error;
+
+	rc = __set_subcaches(core);
+	if (rc)
+		goto error;
 
 	d_vpr_h("%s(): successful\n", __func__);
 	return 0;
 
 error:
 	d_vpr_h("%s(): failed\n", __func__);
-	__unload_fw(core);
-	kfree(core->response_packet);
-	kfree(core->packet);
+	venus_hfi_core_deinit(core);
 	return rc;
 }
 
-int venus_hfi_core_release(struct msm_vidc_core *core)
+int venus_hfi_core_deinit(struct msm_vidc_core *core)
 {
-	d_vpr_h("%s(): core %p\n", __func__, core);
-
+	if (!core) {
+		d_vpr_h("%s(): invalid params\n", __func__);
+		return -EINVAL;
+	}
+	d_vpr_h("%s(): core %pK\n", __func__, core);
+	__disable_subcaches(core);
+	__interface_queues_deinit(core);
+	__unload_fw(core);
+	kfree(core->response_packet);
+	core->response_packet = NULL;
+	kfree(core->packet);
+	core->packet = NULL;
 	return 0;
 }
 
@@ -2867,7 +2887,6 @@ int venus_hfi_queue_buffer(struct msm_vidc_inst *inst,
 	struct msm_vidc_core *core;
 	struct hfi_buffer hfi_buffer;
 
-	d_vpr_h("%s(): inst %p\n", __func__, inst);
 	if (!inst || !inst->core || !inst->packet) {
 		d_vpr_e("%s: Invalid params\n", __func__);
 		return -EINVAL;
@@ -2927,7 +2946,6 @@ int venus_hfi_release_buffer(struct msm_vidc_inst *inst,
 	struct msm_vidc_core *core;
 	struct hfi_buffer hfi_buffer;
 
-	d_vpr_h("%s(): inst %p\n", __func__, inst);
 	if (!inst || !buffer) {
 		d_vpr_e("%s: invalid params\n", __func__);
 		return -EINVAL;

+ 51 - 52
driver/vidc/src/venus_hfi_response.c

@@ -10,6 +10,8 @@
 #include "msm_vidc_driver.h"
 #include "msm_vdec.h"
 
+extern struct msm_vidc_core *g_core;
+
 void print_psc_properties(u32 tag, const char *str, struct msm_vidc_inst *inst,
 	struct msm_vidc_subscription_params subsc_params)
 {
@@ -421,8 +423,6 @@ static int handle_output_buffer(struct msm_vidc_inst *inst,
 	//todo: moved to HFI_PROP_PICTURE_TYPE
 	/*if (buffer->flags & HFI_BUF_FW_FLAG_KEYFRAME)
 		buf->flags |= MSM_VIDC_BUF_FLAG_KEYFRAME;*/
-	if (buffer->flags & HFI_BUF_FW_FLAG_LAST)
-		buf->flags |= MSM_VIDC_BUF_FLAG_LAST;
 	//moved to HFI_INFO_DATA_CORRUPT
 	/*if (buffer->flags & HFI_BUF_FW_FLAG_CORRUPT)
 		buf->flags |= MSM_VIDC_BUF_FLAG_ERROR;*/
@@ -432,6 +432,12 @@ static int handle_output_buffer(struct msm_vidc_inst *inst,
 	/*if (buffer->flags & HFI_BUF_FW_FLAG_SUBFRAME)
 		buf->flags |= MSM_VIDC_BUF_FLAG_SUBFRAME;*/
 
+	if (buffer->flags & HFI_BUF_FW_FLAG_LAST) {
+		if (msm_vidc_allow_last_flag(inst)) {
+			buf->flags |= MSM_VIDC_BUF_FLAG_LAST;
+			msm_vidc_state_change_last_flag(inst);
+		}
+	}
 	print_vidc_buffer(VIDC_HIGH, "FBD", inst, buf);
 
 	return rc;
@@ -531,7 +537,9 @@ static int handle_dequeue_buffers(struct msm_vidc_inst* inst)
 			if (buf->attr & MSM_VIDC_ATTR_DEQUEUED) {
 				buf->attr &= ~MSM_VIDC_ATTR_DEQUEUED;
 				msm_vidc_vb2_buffer_done(inst, buf);
-				msm_vidc_put_driver_buf(inst, buf);
+				/* do not unmap / delete read only buffer */
+				if (!(buf->attr & MSM_VIDC_ATTR_READ_ONLY))
+					msm_vidc_put_driver_buf(inst, buf);
 			}
 		}
 	}
@@ -962,11 +970,10 @@ exit:
 	return rc;
 }
 
-static int venus_hfi_input_psc(struct msm_vidc_core *core,
-	struct work_header *work_hdr)
+int handle_session_input_psc(struct msm_vidc_inst *inst,
+		struct input_psc_work *psc_work)
 {
 	int rc = 0;
-	struct msm_vidc_inst *inst;
 	struct hfi_header *hdr = NULL;
 	struct hfi_packet *packet;
 	u8 *pkt, *temp_pkt;
@@ -974,32 +981,25 @@ static int venus_hfi_input_psc(struct msm_vidc_core *core,
 	u32 hfi_port = 0;
 	int i;
 
-	if (!work_hdr) {
+	if (!inst || !psc_work) {
 		d_vpr_e("%s: invalid params\n", __func__);
 		return -EINVAL;
 	}
 
-	hdr = (struct hfi_header *)work_hdr->data;
+	hdr = (struct hfi_header *)psc_work->data;
 	if (!hdr) {
 		d_vpr_e("%s: invalid params\n", __func__);
 		return -EINVAL;
 	}
 
-	inst = get_inst(core, hdr->session_id);
-	if (!inst) {
-		d_vpr_e("%s: invalid params\n", __func__);
-		return -EINVAL;
-	}
-
-	mutex_lock(&inst->lock);
 	hfi_cmd_type = 0;
 	hfi_port = 0;
 	pkt = (u8 *)((u8 *)hdr + sizeof(struct hfi_header));
 	temp_pkt = pkt;
 
 	for (i = 0; i < hdr->num_packets; i++) {
-		if (validate_packet(pkt, work_hdr->data,
-				work_hdr->data_size, __func__)) {
+		if (validate_packet(pkt, psc_work->data,
+				psc_work->data_size, __func__)) {
 			rc = -EINVAL;
 			goto exit;
 		}
@@ -1034,47 +1034,48 @@ static int venus_hfi_input_psc(struct msm_vidc_core *core,
 		pkt += packet->size;
 	}
 
-	if (hfi_cmd_type == HFI_CMD_SETTINGS_CHANGE) {
-		if (hfi_port == HFI_PORT_BITSTREAM) {
-			print_psc_properties(VIDC_HIGH, "INPUT_PSC", inst,
-				inst->subcr_params[INPUT_PORT]);
-			rc = msm_vdec_input_port_settings_change(inst);
-			if (rc)
-				goto exit;
-		}
-	}
+	print_psc_properties(VIDC_HIGH, "INPUT_PSC", inst,
+		inst->subcr_params[INPUT_PORT]);
+	rc = msm_vdec_input_port_settings_change(inst);
+	if (rc)
+		goto exit;
 
 exit:
-	mutex_unlock(&inst->lock);
-	put_inst(inst);
 	return rc;
 }
 
-void venus_hfi_inst_work_handler(struct work_struct *work)
+void handle_session_input_psc_work_handler(struct work_struct *work)
 {
-	struct msm_vidc_core *core;
-	struct work_header *work_hdr, *dummy = NULL;
+	int rc = 0;
+	struct msm_vidc_inst *inst;
+	struct input_psc_work *psc_work, *dummy = NULL;
 
-	core = container_of(work, struct msm_vidc_core, inst_work.work);
-	if (!core) {
+	inst = container_of(work, struct msm_vidc_inst, input_psc_work.work);
+	inst = get_inst_ref(g_core, inst);
+	if (!inst) {
 		d_vpr_e("%s: invalid params\n", __func__);
 		return;
 	}
 
-	list_for_each_entry_safe(work_hdr, dummy, &core->inst_works, list) {
-		switch (work_hdr->type) {
-		case MSM_VIDC_INST_WORK_PSC:
-			venus_hfi_input_psc(core, work_hdr);
-			break;
-		default:
-			d_vpr_e("%s(): invalid work type: %d\n", __func__,
-				work_hdr->type);
-			break;
+	mutex_lock(&inst->lock);
+	list_for_each_entry_safe(psc_work, dummy, &inst->input_psc_works, list) {
+		rc = msm_vidc_allow_input_psc(inst);
+		if (!rc) {
+			rc = handle_session_input_psc(inst, psc_work);
+			if (!rc)
+				rc = msm_vidc_state_change_input_psc(inst);
+
+			/* either handle input psc or state change failed */
+			if (rc)
+				msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__);
 		}
-		list_del(&work_hdr->list);
-		kfree(work_hdr->data);
-		kfree(work_hdr);
+		list_del(&psc_work->list);
+		kfree(psc_work->data);
+		kfree(psc_work);
 	}
+	mutex_unlock(&inst->lock);
+
+	put_inst(inst);
 }
 
 static int handle_session_response(struct msm_vidc_core *core,
@@ -1110,12 +1111,10 @@ static int handle_session_response(struct msm_vidc_core *core,
 		    packet->type < HFI_CMD_END) {
 			if (packet->type == HFI_CMD_SETTINGS_CHANGE &&
 				packet->port == HFI_PORT_BITSTREAM) {
-				struct work_header *work;
+				struct input_psc_work *work;
 
-				work = kzalloc(sizeof(struct work_header), GFP_KERNEL);
+				work = kzalloc(sizeof(struct input_psc_work), GFP_KERNEL);
 				INIT_LIST_HEAD(&work->list);
-				work->type = MSM_VIDC_INST_WORK_PSC;
-				work->session_id = hdr->session_id;
 				work->data_size = hdr->size;
 				work->data = kzalloc(hdr->size, GFP_KERNEL);
 				if (!work->data) {
@@ -1123,9 +1122,9 @@ static int handle_session_response(struct msm_vidc_core *core,
 					goto exit;
 				}
 				memcpy(work->data, (void *)hdr, hdr->size);
-				list_add_tail(&work->list, &core->inst_works);
-				queue_delayed_work(core->inst_workq,
-					&core->inst_work, msecs_to_jiffies(0));
+				list_add_tail(&work->list, &inst->input_psc_works);
+				queue_delayed_work(inst->input_psc_workq,
+						&inst->input_psc_work, msecs_to_jiffies(0));
 				goto exit;
 			}
 			if (hfi_cmd_type == HFI_CMD_SETTINGS_CHANGE) {

部分文件因为文件数量过多而无法显示