Browse Source

video: driver: initial state machine changes

- hierarchical state model which comprises of
  top level states and sub states
- top level states include OPEN, CLOSE, ERROR,
  INPUT_STREAMING, OUTPUT_STREAMING, STREAMING.
- sub states include DRAIN, DRC, DRAIN_LAST_BUFFER,
  DRC_LAST_BUFFER, INPUT_PAUSE, OUTPUT_PAUSE.
- follows deterministic approach for key sequences
  like DRC, DRAIN and last flag handling i.e none
  of these events are ignored or discarded.
- removal of auto start of firmware input port as
  part of ipsc handling.
- introduction of hfi commands for host controlled
  PAUSE and RESUME of firmware ports.
- introduction of information last flag packets
  for DRC and DRAIN when FW has insufficient
  output buffers.

Change-Id: Ie8c8f44af464d06f5a7bb76822f749c9874f869a
Signed-off-by: Darshana Patil <[email protected]>
Darshana Patil 3 năm trước cách đây
mục cha
commit
10794c2968

+ 5 - 0
driver/platform/kalama/src/msm_vidc_kalama.c

@@ -1455,6 +1455,11 @@ static struct msm_platform_inst_capability instance_cap_data_kalama[] = {
 		HFI_PROP_AV1_DRAP_CONFIG,
 		CAP_FLAG_INPUT_PORT},
 
+	{LAST_FLAG_EVENT_ENABLE, DEC, CODECS_ALL,
+		V4L2_MPEG_MSM_VIDC_DISABLE, V4L2_MPEG_MSM_VIDC_ENABLE,
+		1, V4L2_MPEG_MSM_VIDC_DISABLE,
+		V4L2_CID_MPEG_VIDC_LAST_FLAG_EVENT_ENABLE},
+
 	{META_BITSTREAM_RESOLUTION, DEC, AV1,
 		V4L2_MPEG_VIDC_META_DISABLE,
 		V4L2_MPEG_VIDC_META_ENABLE | V4L2_MPEG_VIDC_META_RX_INPUT |

+ 5 - 3
driver/vidc/inc/hfi_command.h

@@ -116,6 +116,7 @@ enum hfi_buffer_firmware_flags {
 	HFI_BUF_FW_FLAG_READONLY        = 0x00000010,
 	HFI_BUF_FW_FLAG_CODEC_CONFIG    = 0x00000100,
 	HFI_BUF_FW_FLAG_LAST            = 0x10000000,
+	HFI_BUF_FW_FLAG_PSC_LAST        = 0x20000000,
 };
 
 enum hfi_metapayload_header_flags {
@@ -165,22 +166,23 @@ enum hfi_reserve_type {
 #define HFI_CMD_DELIVERY_MODE                                   0x0100000A
 #define HFI_CMD_SUBSCRIBE_MODE                                  0x0100000B
 #define HFI_CMD_SETTINGS_CHANGE                                 0x0100000C
-#define HFI_CMD_RESERVE                                         0x0100000F
 
 #define HFI_SSR_TYPE_SW_ERR_FATAL       0x1
 #define HFI_SSR_TYPE_SW_DIV_BY_ZERO     0x2
 #define HFI_SSR_TYPE_CPU_WDOG_IRQ       0x3
 #define HFI_SSR_TYPE_NOC_ERROR          0x4
-
 #define HFI_BITMASK_HW_CLIENT_ID                        0x000000f0
 #define HFI_BITMASK_SSR_TYPE                            0x0000000f
 #define HFI_CMD_SSR                                             0x0100000D
 
 #define HFI_STABILITY_TYPE_VCODEC_HUNG        0x1
 #define HFI_STABILITY_TYPE_ENC_BUFFER_FULL    0x2
-#define HFI_BITMASK_STABILITY_TYPE                              0x0000000f
+#define HFI_BITMASK_STABILITY_TYPE                      0x0000000f
 #define HFI_CMD_STABILITY                                       0x0100000E
 
+#define HFI_CMD_RESERVE                                         0x0100000F
+#define HFI_CMD_FLUSH                                           0x01000010
+#define HFI_CMD_PAUSE                                           0x01000011
 #define HFI_CMD_END                                             0x01FFFFFF
 
 #endif //__H_HFI_COMMAND_H__

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

@@ -607,6 +607,10 @@ enum hfi_saliency_type {
 
 #define HFI_INFO_VCODEC_RESET                                   0x06000005
 
+#define HFI_INFO_HFI_FLAG_DRAIN_LAST                            0x06000006
+
+#define HFI_INFO_HFI_FLAG_PSC_LAST                              0x06000007
+
 #define HFI_INFORMATION_END                                     0x06FFFFFF
 
 #endif //__H_HFI_PROPERTY_H__

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

@@ -520,7 +520,6 @@ static inline unsigned int VIDEO_RAW_BUFFER_SIZE(unsigned int v4l2_fmt,
 				uv_meta_scanlines, 4096);
 			size = (y_ubwc_plane + uv_ubwc_plane + y_meta_plane +
 				uv_meta_plane);
-			size = MSM_MEDIA_ALIGN(size, 4096);
 		} else {
 			if (pix_width <= INTERLACE_WIDTH_MAX &&
 				pix_height <= INTERLACE_HEIGHT_MAX &&
@@ -597,6 +596,7 @@ static inline unsigned int VIDEO_RAW_BUFFER_SIZE(unsigned int v4l2_fmt,
 	}
 
 invalid_input:
+	size = MSM_MEDIA_ALIGN(size, 4096);
 	return size;
 }
 

+ 31 - 9
driver/vidc/inc/msm_vidc_driver.h

@@ -352,6 +352,17 @@ static inline bool is_enc_slice_delivery_mode(struct msm_vidc_inst *inst)
 			V4L2_MPEG_VIDC_HEVC_ENCODE_DELIVERY_MODE_SLICE_BASED)));
 }
 
+static inline bool is_state(struct msm_vidc_inst *inst, enum msm_vidc_state state)
+{
+	return inst->state == state;
+}
+
+static inline bool is_sub_state(struct msm_vidc_inst *inst,
+	enum msm_vidc_sub_state sub_state)
+{
+	return (inst->sub_state & sub_state);
+}
+
 const char *cap_name(enum msm_vidc_inst_capability_type cap_id);
 const char *v4l2_pixelfmt_name(u32 pixelfmt);
 const char *v4l2_type_name(u32 port);
@@ -382,10 +393,13 @@ u32 v4l2_matrix_coeff_from_driver(struct msm_vidc_inst *inst,
 int v4l2_type_to_driver_port(struct msm_vidc_inst *inst, u32 type,
 	const char *func);
 const char *allow_name(enum msm_vidc_allow allow);
-const char *state_name(enum msm_vidc_inst_state state);
+const char *state_name(enum msm_vidc_state state);
 const char *core_state_name(enum msm_vidc_core_state state);
-int msm_vidc_change_inst_state(struct msm_vidc_inst *inst,
-	enum msm_vidc_inst_state request_state, const char *func);
+int msm_vidc_change_state(struct msm_vidc_inst *inst,
+	enum msm_vidc_state request_state, const char *func);
+int msm_vidc_change_sub_state(struct msm_vidc_inst *inst,
+	enum msm_vidc_sub_state clear_sub_states,
+	enum msm_vidc_sub_state set_sub_states, const char *func);
 int msm_vidc_create_internal_buffer(struct msm_vidc_inst *inst,
 	enum msm_vidc_buffer_type buffer_type, u32 index);
 int msm_vidc_get_internal_buffers(struct msm_vidc_inst *inst,
@@ -406,8 +420,6 @@ 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_set_secure_mode(struct msm_vidc_inst *inst);
 int msm_vidc_session_set_default_header(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_streamoff(struct msm_vidc_inst *inst,
 		enum msm_vidc_port_type port);
 int msm_vidc_session_close(struct msm_vidc_inst *inst);
@@ -502,13 +514,21 @@ bool msm_vidc_allow_streamon(struct msm_vidc_inst *inst, u32 type);
 enum msm_vidc_allow msm_vidc_allow_streamoff(struct msm_vidc_inst *inst, u32 type);
 enum msm_vidc_allow msm_vidc_allow_qbuf(struct msm_vidc_inst *inst, u32 type);
 enum msm_vidc_allow msm_vidc_allow_input_psc(struct msm_vidc_inst *inst);
-bool msm_vidc_allow_last_flag(struct msm_vidc_inst *inst);
+bool msm_vidc_allow_drain_last_flag(struct msm_vidc_inst *inst);
+bool msm_vidc_allow_psc_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_state_change_drain_last_flag(struct msm_vidc_inst *inst);
+int msm_vidc_state_change_psc_last_flag(struct msm_vidc_inst *inst);
+int msm_vidc_process_drain(struct msm_vidc_inst *inst);
+int msm_vidc_process_resume(struct msm_vidc_inst *inst);
+int msm_vidc_process_streamon(struct msm_vidc_inst *inst, u32 type);
+int msm_vidc_process_stop_done(struct msm_vidc_inst *inst,
+	enum signal_session_response signal_type);
+int msm_vidc_process_drain_done(struct msm_vidc_inst *inst);
+int msm_vidc_process_drain_last_flag(struct msm_vidc_inst *inst);
+int msm_vidc_process_psc_last_flag(struct msm_vidc_inst *inst);
 int msm_vidc_get_mbs_per_frame(struct msm_vidc_inst *inst);
 u32 msm_vidc_get_max_bitrate(struct msm_vidc_inst* inst);
 int msm_vidc_get_fps(struct msm_vidc_inst *inst);
@@ -557,6 +577,8 @@ bool res_is_less_than(u32 width, u32 height,
 	u32 ref_width, u32 ref_height);
 bool res_is_less_than_or_equal_to(u32 width, u32 height,
 	u32 ref_width, u32 ref_height);
+int signal_session_msg_receipt(struct msm_vidc_inst *inst,
+	enum signal_session_response cmd);
 int msm_vidc_get_properties(struct msm_vidc_inst *inst);
 int msm_vidc_create_input_metadata_buffer(struct msm_vidc_inst *inst, int buf_fd);
 int msm_vidc_update_input_meta_buffer_index(struct msm_vidc_inst *inst, struct vb2_buffer *vb2);

+ 27 - 16
driver/vidc/inc/msm_vidc_inst.h

@@ -75,19 +75,30 @@ struct msm_vidc_buffers_info {
 	struct msm_vidc_buffers        partial_data;
 };
 
-enum msm_vidc_inst_state {
+enum msm_vidc_state {
 	MSM_VIDC_OPEN                      = 1,
-	MSM_VIDC_START_INPUT               = 2,
-	MSM_VIDC_START_OUTPUT              = 3,
-	MSM_VIDC_START                     = 4,
-	MSM_VIDC_DRC                       = 5,
-	MSM_VIDC_DRC_LAST_FLAG             = 6,
-	MSM_VIDC_DRAIN                     = 7,
-	MSM_VIDC_DRAIN_LAST_FLAG           = 8,
-	MSM_VIDC_DRC_DRAIN                 = 9,
-	MSM_VIDC_DRC_DRAIN_LAST_FLAG       = 10,
-	MSM_VIDC_DRAIN_START_INPUT         = 11,
-	MSM_VIDC_ERROR                     = 12,
+	MSM_VIDC_INPUT_STREAMING           = 2,
+	MSM_VIDC_OUTPUT_STREAMING          = 3,
+	MSM_VIDC_STREAMING                 = 4,
+	MSM_VIDC_CLOSE                     = 5,
+	MSM_VIDC_ERROR                     = 6,
+};
+
+#define MSM_VIDC_SUB_STATE_NONE          0
+#define MSM_VIDC_MAX_SUB_STATES          6
+/*
+ * max value of inst->sub_state if all
+ * the 6 valid bits are set i.e 111111==>63
+ */
+#define MSM_VIDC_MAX_SUB_STATE_VALUE     ((1 << MSM_VIDC_MAX_SUB_STATES) - 1)
+
+enum msm_vidc_sub_state {
+	MSM_VIDC_DRAIN                     = BIT(0),
+	MSM_VIDC_DRC                       = BIT(1),
+	MSM_VIDC_DRAIN_LAST_BUFFER         = BIT(2),
+	MSM_VIDC_DRC_LAST_BUFFER           = BIT(3),
+	MSM_VIDC_INPUT_PAUSE               = BIT(4),
+	MSM_VIDC_OUTPUT_PAUSE              = BIT(5),
 };
 
 struct buf_queue {
@@ -99,7 +110,9 @@ struct msm_vidc_inst {
 	struct mutex                       lock;
 	struct mutex                       request_lock;
 	struct mutex                       client_lock;
-	enum msm_vidc_inst_state           state;
+	enum msm_vidc_state                state;
+	enum msm_vidc_sub_state            sub_state;
+	char                               sub_state_name[MAX_NAME_LENGTH];
 	enum msm_vidc_domain_type          domain;
 	enum msm_vidc_codec_type           codec;
 	void                              *core;
@@ -138,12 +151,10 @@ 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                response_work;
 	struct delayed_work                stats_work;
 	struct work_struct                 stability_work;
 	struct msm_vidc_stability          stability;
-	struct workqueue_struct           *response_workq;
-	struct list_head                   response_works; /* list of struct response_work */
+	struct workqueue_struct           *workq;
 	struct list_head                   enc_input_crs;
 	struct list_head                   dmabuf_tracker; /* list of struct msm_memory_dmabuf */
 	struct list_head                   input_timer_list; /* list of struct msm_vidc_input_timer */

+ 1 - 13
driver/vidc/inc/msm_vidc_internal.h

@@ -500,6 +500,7 @@ enum msm_vidc_inst_capability_type {
 	CAVLC_MAX_BITRATE,
 	ALLINTRA_MAX_BITRATE,
 	LOWLATENCY_MAX_BITRATE,
+	LAST_FLAG_EVENT_ENABLE,
 	/* place all root(no parent) enums before this line */
 
 	PROFILE,
@@ -940,19 +941,6 @@ enum msm_vidc_allow {
 	MSM_VIDC_IGNORE,
 };
 
-enum response_work_type {
-	RESP_WORK_INPUT_PSC = 1,
-	RESP_WORK_OUTPUT_PSC,
-	RESP_WORK_LAST_FLAG,
-};
-
-struct response_work {
-	struct list_head        list;
-	enum response_work_type type;
-	void                   *data;
-	u32                     data_size;
-};
-
 struct msm_vidc_ssr {
 	bool                               trigger;
 	enum msm_vidc_ssr_trigger_type     ssr_type;

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

@@ -49,6 +49,10 @@ int venus_hfi_start(struct msm_vidc_inst *inst, enum msm_vidc_port_type port);
 int venus_hfi_stop(struct msm_vidc_inst *inst, enum msm_vidc_port_type port);
 int venus_hfi_session_close(struct msm_vidc_inst *inst);
 int venus_hfi_session_open(struct msm_vidc_inst *inst);
+int venus_hfi_session_pause(struct msm_vidc_inst *inst, enum msm_vidc_port_type port);
+int venus_hfi_session_resume(struct msm_vidc_inst *inst,
+	enum msm_vidc_port_type port, u32 payload);
+int venus_hfi_session_drain(struct msm_vidc_inst *inst, enum msm_vidc_port_type port);
 int venus_hfi_session_set_codec(struct msm_vidc_inst *inst);
 int venus_hfi_session_set_secure_mode(struct msm_vidc_inst *inst);
 int venus_hfi_core_init(struct msm_vidc_core *core);

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

@@ -16,11 +16,6 @@ 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_response_work_handler(struct work_struct *work);
-int handle_session_response_work(struct msm_vidc_inst *inst,
-	struct response_work *work);
-int cancel_response_work(struct msm_vidc_inst *inst);
-int cancel_response_work_sync(struct msm_vidc_inst *inst);
 int handle_system_error(struct msm_vidc_core *core,
 	struct hfi_packet *pkt);
 void fw_coredump(struct msm_vidc_core *core);

+ 22 - 57
driver/vidc/src/msm_vdec.c

@@ -1160,24 +1160,6 @@ static int msm_vdec_set_delivery_mode_property(struct msm_vidc_inst *inst,
 	return rc;
 }
 
-static int msm_vdec_session_resume(struct msm_vidc_inst *inst,
-	enum msm_vidc_port_type port)
-{
-	int rc = 0;
-
-	i_vpr_h(inst, "%s()\n", __func__);
-	rc = venus_hfi_session_command(inst,
-			HFI_CMD_RESUME,
-			port,
-			HFI_PAYLOAD_NONE,
-			NULL,
-			0);
-	if (rc)
-		return rc;
-
-	return rc;
-}
-
 int msm_vdec_init_input_subcr_params(struct msm_vidc_inst *inst)
 {
 	struct msm_vidc_subscription_params *subsc_params;
@@ -1330,7 +1312,7 @@ static int msm_vdec_read_input_subcr_params(struct msm_vidc_inst *inst)
 		if (inst->buffers.output.min_count != 1) {
 			i_vpr_e(inst, "%s: invalid min count %d in thumbnail case\n",
 				__func__, inst->buffers.output.min_count);
-			msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__);
+			msm_vidc_change_state(inst, MSM_VIDC_ERROR, __func__);
 		}
 	}
 	inst->crop.top = subsc_params.crop_offsets[0] & 0xFFFF;
@@ -1413,16 +1395,11 @@ int msm_vdec_input_port_settings_change(struct msm_vidc_inst *inst)
 	if (rc)
 		return rc;
 
-	rc = msm_vdec_session_resume(inst, INPUT_PORT);
-	if (rc)
-		return rc;
-
 	return rc;
 }
 
 int msm_vdec_output_port_settings_change(struct msm_vidc_inst *inst)
 {
-	//todo
 	return 0;
 }
 
@@ -1496,23 +1473,23 @@ int msm_vdec_streamon_input(struct msm_vidc_inst *inst)
 		rc = msm_vdec_subscribe_input_port_settings_change(
 			inst, INPUT_PORT);
 		if (rc)
-			return rc;
+			goto error;
 		inst->ipsc_properties_set = true;
 	}
 
 	rc = msm_vdec_subscribe_property(inst, INPUT_PORT);
 	if (rc)
-		return rc;
+		goto error;
 
 	rc = msm_vdec_subscribe_metadata(inst, INPUT_PORT);
 	if (rc)
-		return rc;
+		goto error;
 
 	rc = msm_vdec_set_delivery_mode_metadata(inst, INPUT_PORT);
 	if (rc)
-		return rc;
+		goto error;
 
-	rc = msm_vidc_session_streamon(inst, INPUT_PORT);
+	rc = msm_vidc_process_streamon(inst, INPUT_PORT);
 	if (rc)
 		goto error;
 
@@ -1788,11 +1765,11 @@ int msm_vdec_streamon_output(struct msm_vidc_inst *inst)
 
 	rc = msm_vidc_check_session_supported(inst);
 	if (rc)
-		return rc;
+		goto error;
 
 	rc = msm_vdec_update_max_map_output_count(inst);
 	if (rc)
-		return rc;
+		goto error;
 
 	rc = msm_vdec_set_output_properties(inst);
 	if (rc)
@@ -1800,8 +1777,8 @@ int msm_vdec_streamon_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)
 			goto error;
@@ -1810,7 +1787,7 @@ int msm_vdec_streamon_output(struct msm_vidc_inst *inst)
 
 	rc = msm_vdec_subscribe_property(inst, OUTPUT_PORT);
 	if (rc)
-		return rc;
+		goto error;
 
 	rc = msm_vdec_subscribe_metadata(inst, OUTPUT_PORT);
 	if (rc)
@@ -1818,11 +1795,11 @@ int msm_vdec_streamon_output(struct msm_vidc_inst *inst)
 
 	rc = msm_vdec_set_delivery_mode_property(inst, OUTPUT_PORT);
 	if (rc)
-		return rc;
+		goto error;
 
 	rc = msm_vdec_set_delivery_mode_metadata(inst, OUTPUT_PORT);
 	if (rc)
-		return rc;
+		goto error;
 
 	rc = msm_vdec_get_output_internal_buffers(inst);
 	if (rc)
@@ -1832,7 +1809,7 @@ int msm_vdec_streamon_output(struct msm_vidc_inst *inst)
 	if (rc)
 		goto error;
 
-	rc = msm_vidc_session_streamon(inst, OUTPUT_PORT);
+	rc = msm_vidc_process_streamon(inst, OUTPUT_PORT);
 	if (rc)
 		goto error;
 
@@ -1862,10 +1839,6 @@ static inline enum msm_vidc_allow msm_vdec_allow_queue_deferred_buffers(
 	if (inst->power.buffer_counter <= SKIP_BATCH_WINDOW)
 		return MSM_VIDC_ALLOW;
 
-	/* do not defer, if client waiting for last flag FBD */
-	if (inst->state != MSM_VIDC_START)
-		return MSM_VIDC_ALLOW;
-
 	/* defer qbuf, if pending buffers count less than batch size */
 	count = msm_vidc_num_buffers(inst, MSM_VIDC_BUF_OUTPUT, MSM_VIDC_ATTR_DEFERRED);
 	if (count < inst->decode_batch.size)
@@ -2192,7 +2165,6 @@ int msm_vdec_process_cmd(struct msm_vidc_inst *inst, u32 cmd)
 {
 	int rc = 0;
 	enum msm_vidc_allow allow = MSM_VIDC_DISALLOW;
-	enum msm_vidc_port_type port;
 	struct msm_vidc_inst_capability *capability;
 
 	if (!inst || !inst->core || !inst->capabilities) {
@@ -2210,15 +2182,7 @@ int msm_vdec_process_cmd(struct msm_vidc_inst *inst, u32 cmd)
 			return 0;
 		else if (allow != MSM_VIDC_ALLOW)
 			return -EINVAL;
-		rc = venus_hfi_session_command(inst,
-				HFI_CMD_DRAIN,
-				INPUT_PORT,
-				HFI_PAYLOAD_NONE,
-				NULL,
-				0);
-		if (rc)
-			return rc;
-		rc = msm_vidc_state_change_stop(inst);
+		rc = msm_vidc_process_drain(inst);
 		if (rc)
 			return rc;
 	} else if (cmd == V4L2_DEC_CMD_START) {
@@ -2236,11 +2200,6 @@ int msm_vdec_process_cmd(struct msm_vidc_inst *inst, u32 cmd)
 
 		if (!msm_vidc_allow_start(inst))
 			return -EBUSY;
-		port = (inst->state == MSM_VIDC_DRAIN_LAST_FLAG) ? INPUT_PORT : OUTPUT_PORT;
-
-		rc = msm_vidc_state_change_start(inst);
-		if (rc)
-			return rc;
 
 		/* tune power features */
 		inst->decode_batch.enable = msm_vidc_allow_decode_batch(inst);
@@ -2252,10 +2211,15 @@ int msm_vdec_process_cmd(struct msm_vidc_inst *inst, u32 cmd)
 		if (rc)
 			return rc;
 
+		/* queue pending deferred buffers */
+		rc = msm_vidc_queue_deferred_buffers(inst, MSM_VIDC_BUF_OUTPUT);
+		if (rc)
+			return rc;
+
 		/* print final buffer counts & size details */
 		msm_vidc_print_buffer_info(inst);
 
-		rc = msm_vdec_session_resume(inst, port);
+		rc = msm_vidc_process_resume(inst);
 		if (rc)
 			return rc;
 
@@ -2592,6 +2556,7 @@ int msm_vdec_subscribe_event(struct msm_vidc_inst *inst,
 	switch (sub->type) {
 	case V4L2_EVENT_EOS:
 	case V4L2_EVENT_VIDC_METADATA:
+	case V4L2_EVENT_VIDC_LAST_FLAG:
 		rc = v4l2_event_subscribe(&inst->event_handler, sub, MAX_EVENTS, NULL);
 		break;
 	case V4L2_EVENT_SOURCE_CHANGE:

+ 6 - 23
driver/vidc/src/msm_venc.c

@@ -857,13 +857,13 @@ int msm_venc_streamon_input(struct msm_vidc_inst *inst)
 
 	rc = msm_venc_property_subscription(inst, INPUT_PORT);
 	if (rc)
-		return rc;
+		goto error;
 
 	rc = msm_venc_metadata_delivery(inst, INPUT_PORT);
 	if (rc)
-		return rc;
+		goto error;
 
-	rc = msm_vidc_session_streamon(inst, INPUT_PORT);
+	rc = msm_vidc_process_streamon(inst, INPUT_PORT);
 	if (rc)
 		goto error;
 
@@ -910,15 +910,7 @@ int msm_venc_process_cmd(struct msm_vidc_inst *inst, u32 cmd)
 			return 0;
 		else if (allow != MSM_VIDC_ALLOW)
 			return -EINVAL;
-		rc = venus_hfi_session_command(inst,
-				HFI_CMD_DRAIN,
-				INPUT_PORT,
-				HFI_PAYLOAD_NONE,
-				NULL,
-				0);
-		if (rc)
-			return rc;
-		rc = msm_vidc_state_change_stop(inst);
+		rc = msm_vidc_process_drain(inst);
 		if (rc)
 			return rc;
 	} else if (cmd == V4L2_ENC_CMD_START) {
@@ -928,10 +920,6 @@ int msm_venc_process_cmd(struct msm_vidc_inst *inst, u32 cmd)
 		vb2_clear_last_buffer_dequeued(inst->bufq[OUTPUT_META_PORT].vb2q);
 		vb2_clear_last_buffer_dequeued(inst->bufq[OUTPUT_PORT].vb2q);
 
-		rc = msm_vidc_state_change_start(inst);
-		if (rc)
-			return rc;
-
 		/* tune power features */
 		msm_vidc_allow_dcvs(inst);
 		msm_vidc_power_data_reset(inst);
@@ -939,12 +927,7 @@ int msm_venc_process_cmd(struct msm_vidc_inst *inst, u32 cmd)
 		/* print final buffer counts & size details */
 		msm_vidc_print_buffer_info(inst);
 
-		rc = venus_hfi_session_command(inst,
-				HFI_CMD_RESUME,
-				INPUT_PORT,
-				HFI_PAYLOAD_NONE,
-				NULL,
-				0);
+		rc = msm_vidc_process_resume(inst);
 		if (rc)
 			return rc;
 	} else {
@@ -1030,7 +1013,7 @@ int msm_venc_streamon_output(struct msm_vidc_inst *inst)
 	if (rc)
 		goto error;
 
-	rc = msm_vidc_session_streamon(inst, OUTPUT_PORT);
+	rc = msm_vidc_process_streamon(inst, OUTPUT_PORT);
 	if (rc)
 		goto error;
 

+ 5 - 6
driver/vidc/src/msm_vidc.c

@@ -889,6 +889,8 @@ void *msm_vidc_open(void *vidc_core, u32 session_type)
 	inst->domain = session_type;
 	inst->session_id = hash32_ptr(inst);
 	inst->state = MSM_VIDC_OPEN;
+	inst->sub_state = MSM_VIDC_SUB_STATE_NONE;
+	strlcpy(inst->sub_state_name, "SUB_STATE_NONE", sizeof(inst->sub_state_name));
 	inst->active = true;
 	inst->request = false;
 	inst->ipsc_properties_set = false;
@@ -908,7 +910,6 @@ void *msm_vidc_open(void *vidc_core, u32 session_type)
 		msm_vidc_vmem_free((void **)&inst);
 		return NULL;
 	}
-	INIT_LIST_HEAD(&inst->response_works);
 	INIT_LIST_HEAD(&inst->caps_list);
 	INIT_LIST_HEAD(&inst->timestamps.list);
 	INIT_LIST_HEAD(&inst->ts_reorder.list);
@@ -959,13 +960,12 @@ void *msm_vidc_open(void *vidc_core, u32 session_type)
 	for (i = 0; i < MAX_SIGNAL; i++)
 		init_completion(&inst->completions[i]);
 
-	inst->response_workq = create_singlethread_workqueue("response_workq");
-	if (!inst->response_workq) {
-		i_vpr_e(inst, "%s: create input_psc_workq failed\n", __func__);
+	inst->workq = create_singlethread_workqueue("workq");
+	if (!inst->workq) {
+		i_vpr_e(inst, "%s: create workq failed\n", __func__);
 		goto error;
 	}
 
-	INIT_DELAYED_WORK(&inst->response_work, handle_session_response_work_handler);
 	INIT_DELAYED_WORK(&inst->stats_work, msm_vidc_stats_handler);
 	INIT_WORK(&inst->stability_work, msm_vidc_stability_handler);
 
@@ -1042,7 +1042,6 @@ int msm_vidc_close(void *instance)
 	msm_vidc_destroy_buffers(inst);
 	inst_unlock(inst, __func__);
 	client_unlock(inst, __func__);
-	cancel_response_work_sync(inst);
 	cancel_stability_work_sync(inst);
 	cancel_stats_work_sync(inst);
 	msm_vidc_show_stats(inst);

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 454 - 294
driver/vidc/src/msm_vidc_driver.c


+ 4 - 12
driver/vidc/src/msm_vidc_vb2.c

@@ -112,7 +112,7 @@ int msm_vidc_queue_setup(struct vb2_queue *q,
 		return -EINVAL;
 	}
 
-	if (inst->state == MSM_VIDC_START) {
+	if (is_state(inst, MSM_VIDC_STREAMING)) {
 		i_vpr_e(inst, "%s: invalid state %d\n", __func__, inst->state);
 		return -EINVAL;
 	}
@@ -217,10 +217,6 @@ int msm_vidc_start_streaming(struct vb2_queue *q, unsigned int count)
 		goto unlock;
 	}
 
-	rc = msm_vidc_state_change_streamon(inst, q->type);
-	if (rc)
-		goto unlock;
-
 	if (q->type == INPUT_META_PLANE &&
 		inst->capabilities->cap[INPUT_META_VIA_REQUEST].value) {
 		i_vpr_e(inst,
@@ -335,7 +331,7 @@ int msm_vidc_start_streaming(struct vb2_queue *q, unsigned int count)
 unlock:
 	if (rc) {
 		i_vpr_e(inst, "Streamon: %s failed\n", v4l2_type_name(q->type));
-		msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__);
+		msm_vidc_change_state(inst, MSM_VIDC_ERROR, __func__);
 	}
 	inst_unlock(inst, __func__);
 	client_unlock(inst, __func__);
@@ -381,10 +377,6 @@ void msm_vidc_stop_streaming(struct vb2_queue *q)
 		goto unlock;
 	}
 
-	rc = msm_vidc_state_change_streamoff(inst, q->type);
-	if (rc)
-		goto unlock;
-
 	if (!is_decode_session(inst) && !is_encode_session(inst)) {
 		i_vpr_e(inst, "%s: invalid session %d\n",
 			__func__, inst->domain);
@@ -420,7 +412,7 @@ void msm_vidc_stop_streaming(struct vb2_queue *q)
 unlock:
 	if (rc) {
 		i_vpr_e(inst, "Streamoff: %s failed\n", v4l2_type_name(q->type));
-		msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__);
+		msm_vidc_change_state(inst, MSM_VIDC_ERROR, __func__);
 	}
 	inst_unlock(inst, __func__);
 	client_unlock(inst, __func__);
@@ -531,7 +523,7 @@ void msm_vidc_buf_queue(struct vb2_buffer *vb2)
 
 unlock:
 	if (rc) {
-		msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__);
+		msm_vidc_change_state(inst, MSM_VIDC_ERROR, __func__);
 		vb2_buffer_done(vb2, VB2_BUF_STATE_ERROR);
 	}
 	inst_unlock(inst, __func__);

+ 131 - 0
driver/vidc/src/venus_hfi.c

@@ -3308,6 +3308,137 @@ unlock:
 	return rc;
 }
 
+int venus_hfi_session_pause(struct msm_vidc_inst *inst, enum msm_vidc_port_type port)
+{
+	int rc = 0;
+	struct msm_vidc_core* core;
+
+	if (!inst || !inst->core || !inst->packet) {
+		d_vpr_e("%s: invalid params\n", __func__);
+		return -EINVAL;
+	}
+	core = inst->core;
+	core_lock(core, __func__);
+
+	if (!__valdiate_session(core, inst, __func__)) {
+		rc = -EINVAL;
+		goto unlock;
+	}
+
+	if (port != INPUT_PORT && port != OUTPUT_PORT) {
+		i_vpr_e(inst, "%s: invalid port %d\n", __func__, port);
+		goto unlock;
+	}
+
+	rc = hfi_packet_session_command(inst,
+				HFI_CMD_PAUSE,
+				(HFI_HOST_FLAGS_RESPONSE_REQUIRED |
+				HFI_HOST_FLAGS_INTR_REQUIRED),
+				get_hfi_port(inst, port),
+				inst->session_id,
+				HFI_PAYLOAD_NONE,
+				NULL,
+				0);
+	if (rc)
+		goto unlock;
+
+	rc = __iface_cmdq_write(inst->core, inst->packet);
+	if (rc)
+		goto unlock;
+
+unlock:
+	core_unlock(core, __func__);
+	return rc;
+}
+
+int venus_hfi_session_resume(struct msm_vidc_inst *inst,
+	enum msm_vidc_port_type port, u32 payload)
+{
+	int rc = 0;
+	struct msm_vidc_core* core;
+
+	if (!inst || !inst->core || !inst->packet) {
+		d_vpr_e("%s: invalid params\n", __func__);
+		return -EINVAL;
+	}
+	core = inst->core;
+	core_lock(core, __func__);
+
+	if (!__valdiate_session(core, inst, __func__)) {
+		rc = -EINVAL;
+		goto unlock;
+	}
+
+	if (port != INPUT_PORT && port != OUTPUT_PORT) {
+		i_vpr_e(inst, "%s: invalid port %d\n", __func__, port);
+		goto unlock;
+	}
+
+	rc = hfi_packet_session_command(inst,
+				HFI_CMD_RESUME,
+				(HFI_HOST_FLAGS_RESPONSE_REQUIRED |
+				HFI_HOST_FLAGS_INTR_REQUIRED),
+				get_hfi_port(inst, port),
+				inst->session_id,
+				HFI_PAYLOAD_U32,
+				&payload,
+				sizeof(u32));
+	if (rc)
+		goto unlock;
+
+	rc = __iface_cmdq_write(inst->core, inst->packet);
+	if (rc)
+		goto unlock;
+
+unlock:
+	core_unlock(core, __func__);
+	return rc;
+}
+
+int venus_hfi_session_drain(struct msm_vidc_inst *inst, enum msm_vidc_port_type port)
+{
+	int rc = 0;
+	struct msm_vidc_core* core;
+
+	if (!inst || !inst->core || !inst->packet) {
+		d_vpr_e("%s: invalid params\n", __func__);
+		return -EINVAL;
+	}
+	core = inst->core;
+	core_lock(core, __func__);
+
+	if (!__valdiate_session(core, inst, __func__)) {
+		rc = -EINVAL;
+		goto unlock;
+	}
+
+	if (port != INPUT_PORT) {
+		i_vpr_e(inst, "%s: invalid port %d\n", __func__, port);
+		goto unlock;
+	}
+
+	rc = hfi_packet_session_command(inst,
+				HFI_CMD_DRAIN,
+				(HFI_HOST_FLAGS_RESPONSE_REQUIRED |
+				HFI_HOST_FLAGS_INTR_REQUIRED |
+				HFI_HOST_FLAGS_NON_DISCARDABLE),
+				get_hfi_port(inst, port),
+				inst->session_id,
+				HFI_PAYLOAD_NONE,
+				NULL,
+				0);
+	if (rc)
+		goto unlock;
+
+	rc = __iface_cmdq_write(inst->core, inst->packet);
+	if (rc)
+		goto unlock;
+
+unlock:
+	core_unlock(core, __func__);
+	return rc;
+}
+
 int venus_hfi_session_command(struct msm_vidc_inst *inst,
 	u32 cmd, enum msm_vidc_port_type port, u32 payload_type,
 	void *payload, u32 payload_size)

+ 200 - 220
driver/vidc/src/venus_hfi_response.c

@@ -178,14 +178,6 @@ bool is_valid_hfi_buffer_type(struct msm_vidc_inst *inst,
 	return true;
 }
 
-static int signal_session_msg_receipt(struct msm_vidc_inst *inst,
-	enum signal_session_response cmd)
-{
-	if (cmd < MAX_SIGNAL)
-		complete(&inst->completions[cmd]);
-	return 0;
-}
-
 int validate_packet(u8 *response_pkt, u8 *core_resp_pkt,
 	u32 core_resp_pkt_size, const char *func)
 {
@@ -304,29 +296,35 @@ static bool check_for_packet_payload(struct msm_vidc_inst *inst,
 	return true;
 }
 
-static bool check_last_flag(struct msm_vidc_inst *inst,
-	struct hfi_packet *pkt)
+static int handle_session_last_flag_info(struct msm_vidc_inst *inst,
+		struct hfi_packet *pkt)
 {
-	struct hfi_buffer *buffer;
+	int rc = 0;
 
-	if (!inst || !pkt) {
-		d_vpr_e("%s: invalid params\n", __func__);
-		return false;
+	if (pkt->type == HFI_INFO_HFI_FLAG_PSC_LAST) {
+		if (msm_vidc_allow_psc_last_flag(inst))
+			rc = msm_vidc_process_psc_last_flag(inst);
+		else
+			rc = -EINVAL;
+	} else if (pkt->type == HFI_INFO_HFI_FLAG_DRAIN_LAST) {
+		if (msm_vidc_allow_drain_last_flag(inst))
+			rc = msm_vidc_process_drain_last_flag(inst);
+		else
+			rc = -EINVAL;
+	} else {
+		i_vpr_e(inst, "%s: invalid packet type %#x\n", __func__,
+			pkt->type);
 	}
 
-	buffer = (struct hfi_buffer *)((u8 *)pkt + sizeof(struct hfi_packet));
-	if (buffer->flags & HFI_BUF_FW_FLAG_LAST) {
-		i_vpr_h(inst, "%s: received last flag on FBD, index: %d\n",
-			__func__, buffer->index);
-		return true;
-	}
-	return false;
+	if (rc)
+		msm_vidc_change_state(inst, MSM_VIDC_ERROR, __func__);
+
+	return rc;
 }
 
 static int handle_session_info(struct msm_vidc_inst *inst,
 	struct hfi_packet *pkt)
 {
-
 	int rc = 0;
 	char *info;
 
@@ -342,12 +340,20 @@ static int handle_session_info(struct msm_vidc_inst *inst,
 		info = "buffer overflow";
 		inst->hfi_frame_info.overflow = 1;
 		break;
+	case HFI_INFO_HFI_FLAG_DRAIN_LAST:
+		info = "drain last flag";
+		rc = handle_session_last_flag_info(inst, pkt);
+		break;
+	case HFI_INFO_HFI_FLAG_PSC_LAST:
+		info = "drc last flag";
+		rc = handle_session_last_flag_info(inst, pkt);
+		break;
 	default:
 		info = "unknown";
 		break;
 	}
 
-	i_vpr_e(inst, "session info (%#x): %s\n", pkt->type, info);
+	i_vpr_h(inst, "session info (%#x): %s\n", pkt->type, info);
 
 	return rc;
 }
@@ -385,7 +391,7 @@ static int handle_session_error(struct msm_vidc_inst *inst,
 	i_vpr_e(inst, "%s: session error received %#x: %s\n",
 		__func__, pkt->type, error);
 
-	rc = msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__);
+	rc = msm_vidc_change_state(inst, MSM_VIDC_ERROR, __func__);
 	return rc;
 }
 
@@ -537,7 +543,8 @@ static int handle_session_start(struct msm_vidc_inst *inst,
 static int handle_session_stop(struct msm_vidc_inst *inst,
 	struct hfi_packet *pkt)
 {
-	int signal_type = -1;
+	int rc = 0;
+	enum signal_session_response signal_type = -1;
 
 	if (pkt->flags & HFI_FW_FLAGS_SUCCESS)
 		i_vpr_h(inst, "%s: successful for port %d\n",
@@ -568,17 +575,28 @@ static int handle_session_stop(struct msm_vidc_inst *inst,
 		return -EINVAL;
 	}
 
-	if (signal_type != -1)
-		signal_session_msg_receipt(inst, signal_type);
+	if (signal_type != -1) {
+		rc = msm_vidc_process_stop_done(inst, signal_type);
+		if (rc)
+			return rc;
+	}
+
 	return 0;
 }
 
 static int handle_session_drain(struct msm_vidc_inst *inst,
 	struct hfi_packet *pkt)
 {
+	int rc = 0;
+
 	if (pkt->flags & HFI_FW_FLAGS_SUCCESS)
 		i_vpr_h(inst, "%s: successful\n", __func__);
-	return 0;
+
+	rc = msm_vidc_process_drain_done(inst);
+	if (rc)
+		return rc;
+
+	return rc;
 }
 
 static int get_driver_buffer_flags(struct msm_vidc_inst *inst, u32 hfi_flags)
@@ -618,7 +636,18 @@ static int get_driver_buffer_flags(struct msm_vidc_inst *inst, u32 hfi_flags)
 	if (hfi_flags & HFI_BUF_FW_FLAG_CODEC_CONFIG)
 		driver_flags |= MSM_VIDC_BUF_FLAG_CODECCONFIG;
 
-	if (hfi_flags & HFI_BUF_FW_FLAG_LAST)
+	/*
+	 * attach last flag to the buffer for encode session.
+	 * For decode session attach only if control(LAST_FLAG_EVENT_ENABLE)
+	 * is not set by client. If this control is enabled, last flag
+	 * info will be sent via event(V4L2_EVENT_VIDC_LAST_FLAG) to client.
+	 */
+	if ((is_encode_session(inst) &&
+		(hfi_flags & HFI_BUF_FW_FLAG_LAST)) ||
+		(is_decode_session(inst) &&
+		!inst->capabilities->cap[LAST_FLAG_EVENT_ENABLE].value &&
+		((hfi_flags & HFI_BUF_FW_FLAG_LAST) ||
+		(hfi_flags & HFI_BUF_FW_FLAG_PSC_LAST))))
 		driver_flags |= MSM_VIDC_BUF_FLAG_LAST;
 
 	return driver_flags;
@@ -714,6 +743,48 @@ static int handle_non_read_only_buffer(struct msm_vidc_inst *inst,
 	return 0;
 }
 
+static int handle_psc_last_flag_buffer(struct msm_vidc_inst *inst,
+		struct hfi_buffer *buffer)
+{
+	int rc = 0;
+
+	if (!(buffer->flags & HFI_BUF_FW_FLAG_PSC_LAST))
+		return 0;
+
+	if (!msm_vidc_allow_psc_last_flag(inst))
+		return -EINVAL;
+
+	rc = msm_vidc_process_psc_last_flag(inst);
+	if (rc)
+		return rc;
+
+	return rc;
+}
+
+static int handle_drain_last_flag_buffer(struct msm_vidc_inst *inst,
+		struct hfi_buffer *buffer)
+{
+	int rc = 0;
+
+	if (!(buffer->flags & HFI_BUF_FW_FLAG_LAST))
+		return 0;
+
+	if (!msm_vidc_allow_drain_last_flag(inst))
+		return -EINVAL;
+
+	if (is_decode_session(inst)) {
+		rc = msm_vidc_process_drain_last_flag(inst);
+		if (rc)
+			return rc;
+	} else if (is_encode_session(inst)) {
+		rc = msm_vidc_state_change_drain_last_flag(inst);
+		if (rc)
+			return rc;
+	}
+
+	return rc;
+}
+
 static int handle_input_buffer(struct msm_vidc_inst *inst,
 	struct hfi_buffer *buffer)
 {
@@ -801,11 +872,25 @@ static int handle_output_buffer(struct msm_vidc_inst *inst,
 		return -EINVAL;
 	}
 
+	/* handle drain last flag buffer */
+	if (buffer->flags & HFI_BUF_FW_FLAG_LAST) {
+		rc = handle_drain_last_flag_buffer(inst, buffer);
+		if (rc)
+			msm_vidc_change_state(inst, MSM_VIDC_ERROR, __func__);
+	}
+
 	if (is_decode_session(inst)) {
+		/* handle psc last flag buffer */
+		if (buffer->flags & HFI_BUF_FW_FLAG_PSC_LAST) {
+			rc = handle_psc_last_flag_buffer(inst, buffer);
+			if (rc)
+				msm_vidc_change_state(inst, MSM_VIDC_ERROR, __func__);
+		}
+		/* handle non-read only buffer */
 		if (!(buffer->flags & HFI_BUF_FW_FLAG_READONLY)) {
 			rc = handle_non_read_only_buffer(inst, buffer);
 			if (rc)
-				msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__);
+				msm_vidc_change_state(inst, MSM_VIDC_ERROR, __func__);
 		}
 	}
 
@@ -861,14 +946,15 @@ static int handle_output_buffer(struct msm_vidc_inst *inst,
 			}
 		}
 		if (fatal)
-			msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__);
+			msm_vidc_change_state(inst, MSM_VIDC_ERROR, __func__);
 	}
 
 	/*
 	 * reset data size to zero for last flag buffer.
 	 * reset RO flag for last flag buffer.
 	 */
-	if (buffer->flags & HFI_BUF_FW_FLAG_LAST) {
+	if ((buffer->flags & HFI_BUF_FW_FLAG_LAST) ||
+		(buffer->flags & HFI_BUF_FW_FLAG_PSC_LAST)) {
 		if (buffer->data_size) {
 			i_vpr_e(inst, "%s: reset data size to zero for last flag buffer\n",
 				__func__);
@@ -894,7 +980,7 @@ static int handle_output_buffer(struct msm_vidc_inst *inst,
 			buf->attr |= MSM_VIDC_ATTR_READ_ONLY;
 			rc = handle_read_only_buffer(inst, buf);
 			if (rc)
-				msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__);
+				msm_vidc_change_state(inst, MSM_VIDC_ERROR, __func__);
 		} else {
 			buf->attr &= ~MSM_VIDC_ATTR_READ_ONLY;
 		}
@@ -993,7 +1079,12 @@ static int handle_input_metadata_buffer(struct msm_vidc_inst *inst,
 	buf->attr &= ~MSM_VIDC_ATTR_QUEUED;
 	buf->attr |= MSM_VIDC_ATTR_DEQUEUED;
 	buf->flags = 0;
-	if (buffer->flags & HFI_BUF_FW_FLAG_LAST)
+	if ((is_encode_session(inst) &&
+		(buffer->flags & HFI_BUF_FW_FLAG_LAST)) ||
+		(is_decode_session(inst) &&
+		!inst->capabilities->cap[LAST_FLAG_EVENT_ENABLE].value &&
+		((buffer->flags & HFI_BUF_FW_FLAG_LAST) ||
+		(buffer->flags & HFI_BUF_FW_FLAG_PSC_LAST))))
 		buf->flags |= MSM_VIDC_BUF_FLAG_LAST;
 
 	print_vidc_buffer(VIDC_LOW, "low ", "dqbuf", inst, buf);
@@ -1008,6 +1099,11 @@ static int handle_output_metadata_buffer(struct msm_vidc_inst *inst,
 	struct msm_vidc_buffer *buf;
 	bool found;
 
+	if (!inst || !inst->capabilities) {
+		d_vpr_e("%s: Invalid params\n", __func__);
+		return -EINVAL;
+	}
+
 	buffers = msm_vidc_get_buffers(inst, MSM_VIDC_BUF_OUTPUT_META, __func__);
 	if (!buffers)
 		return -EINVAL;
@@ -1035,7 +1131,12 @@ static int handle_output_metadata_buffer(struct msm_vidc_inst *inst,
 	buf->attr &= ~MSM_VIDC_ATTR_QUEUED;
 	buf->attr |= MSM_VIDC_ATTR_DEQUEUED;
 	buf->flags = 0;
-	if (buffer->flags & HFI_BUF_FW_FLAG_LAST)
+	if ((is_encode_session(inst) &&
+		(buffer->flags & HFI_BUF_FW_FLAG_LAST)) ||
+		(is_decode_session(inst) &&
+		!inst->capabilities->cap[LAST_FLAG_EVENT_ENABLE].value &&
+		((buffer->flags & HFI_BUF_FW_FLAG_LAST) ||
+		(buffer->flags & HFI_BUF_FW_FLAG_PSC_LAST))))
 		buf->flags |= MSM_VIDC_BUF_FLAG_LAST;
 
 	print_vidc_buffer(VIDC_LOW, "low ", "dqbuf", inst, buf);
@@ -1267,18 +1368,18 @@ static int handle_session_buffer(struct msm_vidc_inst *inst,
 	}
 
 	if (!check_for_packet_payload(inst, pkt, __func__)) {
-		msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__);
+		msm_vidc_change_state(inst, MSM_VIDC_ERROR, __func__);
 		return 0;
 	}
 
 	buffer = (struct hfi_buffer *)((u8 *)pkt + sizeof(struct hfi_packet));
 	if (!is_valid_hfi_buffer_type(inst, buffer->type, __func__)) {
-		msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__);
+		msm_vidc_change_state(inst, MSM_VIDC_ERROR, __func__);
 		return 0;
 	}
 
 	if (!is_valid_hfi_port(inst, pkt->port, buffer->type, __func__)) {
-		msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__);
+		msm_vidc_change_state(inst, MSM_VIDC_ERROR, __func__);
 		return 0;
 	}
 	if (is_decode_session(inst) && buffer->type == HFI_BUFFER_RAW &&
@@ -1329,6 +1430,39 @@ static int handle_session_buffer(struct msm_vidc_inst *inst,
 	return rc;
 }
 
+static int handle_input_port_settings_change(struct msm_vidc_inst *inst)
+{
+	int rc = 0;
+	enum msm_vidc_allow allow = MSM_VIDC_DISALLOW;
+
+	allow = msm_vidc_allow_input_psc(inst);
+	if (allow == MSM_VIDC_DISALLOW) {
+		return -EINVAL;
+	} else if (allow == MSM_VIDC_ALLOW) {
+		rc = msm_vidc_state_change_input_psc(inst);
+		if (rc)
+			return rc;
+		print_psc_properties("INPUT_PSC", inst, inst->subcr_params[INPUT_PORT]);
+		rc = msm_vdec_input_port_settings_change(inst);
+		if (rc)
+			return rc;
+	}
+
+	return rc;
+}
+
+static int handle_output_port_settings_change(struct msm_vidc_inst *inst)
+{
+	int rc = 0;
+
+	print_psc_properties("OUTPUT_PSC", inst, inst->subcr_params[OUTPUT_PORT]);
+	rc = msm_vdec_output_port_settings_change(inst);
+	if (rc)
+		return rc;
+
+	return rc;
+}
+
 static int handle_port_settings_change(struct msm_vidc_inst *inst,
 	struct hfi_packet *pkt)
 {
@@ -1338,17 +1472,23 @@ static int handle_port_settings_change(struct msm_vidc_inst *inst,
 		__func__, pkt->port);
 
 	if (pkt->port == HFI_PORT_RAW) {
-		print_psc_properties("OUTPUT_PSC", inst, inst->subcr_params[OUTPUT_PORT]);
-		rc = msm_vdec_output_port_settings_change(inst);
+		rc = handle_output_port_settings_change(inst);
+		if (rc)
+			goto exit;
 	} else if (pkt->port == HFI_PORT_BITSTREAM) {
-		print_psc_properties("INPUT_PSC", inst, inst->subcr_params[INPUT_PORT]);
-		rc = msm_vdec_input_port_settings_change(inst);
+		rc = handle_input_port_settings_change(inst);
+		if (rc)
+			goto exit;
 	} else {
 		i_vpr_e(inst, "%s: invalid port type: %#x\n",
 			__func__, pkt->port);
 		rc = -EINVAL;
+		goto exit;
 	}
 
+exit:
+	if (rc)
+		msm_vidc_change_state(inst, MSM_VIDC_ERROR, __func__);
 	return rc;
 }
 
@@ -1368,6 +1508,14 @@ static int handle_session_delivery_mode(struct msm_vidc_inst *inst,
 	return 0;
 }
 
+static int handle_session_pause(struct msm_vidc_inst *inst,
+	struct hfi_packet *pkt)
+{
+	if (pkt->flags & HFI_FW_FLAGS_SUCCESS)
+		i_vpr_h(inst, "%s: successful\n", __func__);
+	return 0;
+}
+
 static int handle_session_resume(struct msm_vidc_inst *inst,
 	struct hfi_packet *pkt)
 {
@@ -1398,6 +1546,7 @@ static int handle_session_command(struct msm_vidc_inst *inst,
 		{HFI_CMD_SETTINGS_CHANGE,   handle_port_settings_change       },
 		{HFI_CMD_SUBSCRIBE_MODE,    handle_session_subscribe_mode     },
 		{HFI_CMD_DELIVERY_MODE,     handle_session_delivery_mode      },
+		{HFI_CMD_PAUSE,             handle_session_pause              },
 		{HFI_CMD_RESUME,            handle_session_resume             },
 		{HFI_CMD_STABILITY,         handle_session_stability          },
 	};
@@ -1437,7 +1586,7 @@ static int handle_dpb_list_property(struct msm_vidc_inst *inst,
 		i_vpr_e(inst,
 			"%s: dpb list payload size %d exceeds expected max size %d\n",
 			__func__, payload_size, MAX_DPB_LIST_PAYLOAD_SIZE);
-		msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__);
+		msm_vidc_change_state(inst, MSM_VIDC_ERROR, __func__);
 	}
 	memcpy(inst->dpb_list_payload, payload_start, payload_size);
 
@@ -1764,7 +1913,7 @@ static int __handle_session_response(struct msm_vidc_inst *inst,
 				dequeue |= (packet->type == HFI_CMD_BUFFER);
 				rc = be[i].handle(inst, packet);
 				if (rc)
-					msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__);
+					msm_vidc_change_state(inst, MSM_VIDC_ERROR, __func__);
 			}
 			pkt += packet->size;
 		}
@@ -1780,163 +1929,14 @@ static int __handle_session_response(struct msm_vidc_inst *inst,
 	return rc;
 }
 
-int handle_session_response_work(struct msm_vidc_inst *inst,
-		struct response_work *resp_work)
-{
-	int rc = 0;
-	struct hfi_header *hdr = NULL;
-
-	if (!inst || !inst->core || !resp_work) {
-		d_vpr_e("%s: invalid params\n", __func__);
-		return -EINVAL;
-	}
-
-	hdr = (struct hfi_header *)resp_work->data;
-	if (!hdr) {
-		i_vpr_e(inst, "%s: invalid params\n", __func__);
-		return -EINVAL;
-	}
-	if (resp_work->type == RESP_WORK_INPUT_PSC)
-		msm_vdec_init_input_subcr_params(inst);
-
-	rc = __handle_session_response(inst, hdr);
-	if (rc)
-		return rc;
-
-	return 0;
-}
-
-void handle_session_response_work_handler(struct work_struct *work)
-{
-	int rc = 0;
-	struct msm_vidc_inst *inst;
-	struct response_work *resp_work, *dummy = NULL;
-
-	inst = container_of(work, struct msm_vidc_inst, response_work.work);
-	inst = get_inst_ref(g_core, inst);
-	if (!inst) {
-		d_vpr_e("%s: invalid params\n", __func__);
-		return;
-	}
-
-	inst_lock(inst, __func__);
-	list_for_each_entry_safe(resp_work, dummy, &inst->response_works, list) {
-		switch (resp_work->type) {
-		case RESP_WORK_INPUT_PSC:
-		{
-			enum msm_vidc_allow allow = MSM_VIDC_DISALLOW;
-
-			allow = msm_vidc_allow_input_psc(inst);
-			if (allow == MSM_VIDC_DISALLOW) {
-				msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__);
-				break;
-			} else if (allow == MSM_VIDC_DEFER) {
-				/* continue to next entry processing */
-				continue;
-			} else if (allow == MSM_VIDC_DISCARD) {
-				/* if ipsc is discarded then override the psc properties again */
-				inst->ipsc_properties_set = false;
-				/* discard current entry processing */
-				break;
-			} else if (allow == MSM_VIDC_ALLOW) {
-				rc = handle_session_response_work(inst, resp_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__);
-			}
-			break;
-		}
-		case RESP_WORK_OUTPUT_PSC:
-			rc = handle_session_response_work(inst, resp_work);
-			if (rc)
-				msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__);
-			break;
-		case RESP_WORK_LAST_FLAG:
-			rc = handle_session_response_work(inst, resp_work);
-			if (rc) {
-				msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__);
-				break;
-			}
-			if (msm_vidc_allow_last_flag(inst)) {
-				rc = msm_vidc_state_change_last_flag(inst);
-				if (rc)
-					msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__);
-			}
-			break;
-		default:
-			i_vpr_e(inst, "%s: invalid response work type %d\n", __func__,
-				resp_work->type);
-			break;
-		}
-		list_del(&resp_work->list);
-		msm_vidc_vmem_free((void **)&resp_work->data);
-		msm_vidc_vmem_free((void **)&resp_work);
-	}
-	inst_unlock(inst, __func__);
-
-	put_inst(inst);
-}
-
-static int queue_response_work(struct msm_vidc_inst *inst,
-	enum response_work_type type, void *hdr, u32 hdr_size)
-{
-	struct response_work *work = NULL;
-
-	if (msm_vidc_vmem_alloc(sizeof(struct response_work), (void **)&work, __func__))
-		return -ENOMEM;
-	INIT_LIST_HEAD(&work->list);
-	work->type = type;
-	work->data_size = hdr_size;
-	if (msm_vidc_vmem_alloc(hdr_size, (void **)&work->data, "Work data"))
-		return -ENOMEM;
-	memcpy(work->data, hdr, hdr_size);
-	list_add_tail(&work->list, &inst->response_works);
-	queue_delayed_work(inst->response_workq,
-			&inst->response_work, msecs_to_jiffies(0));
-	return 0;
-}
-
-int cancel_response_work(struct msm_vidc_inst *inst)
-{
-	struct response_work *work, *dummy_work = NULL;
-
-	if (!inst) {
-		d_vpr_e("%s: Invalid arguments\n", __func__);
-		return -EINVAL;
-	}
-	cancel_delayed_work(&inst->response_work);
-
-	list_for_each_entry_safe(work, dummy_work, &inst->response_works, list) {
-		list_del(&work->list);
-		msm_vidc_vmem_free((void **)&work->data);
-		msm_vidc_vmem_free((void **)&work);
-	}
-
-	return 0;
-}
-
-int cancel_response_work_sync(struct msm_vidc_inst *inst)
-{
-	if (!inst || !inst->response_workq) {
-		d_vpr_e("%s: Invalid arguments\n", __func__);
-		return -EINVAL;
-	}
-	cancel_delayed_work_sync(&inst->response_work);
-
-	return 0;
-}
-
 static int handle_session_response(struct msm_vidc_core *core,
 	struct hfi_header *hdr)
 {
 	struct msm_vidc_inst *inst;
 	struct hfi_packet *packet;
 	u8 *pkt;
-	enum response_work_type type;
 	int i, rc = 0;
-	bool offload = false;
+	bool found_ipsc = false;
 
 	if (!core || !hdr) {
 		d_vpr_e("%s: Invalid params\n", __func__);
@@ -1950,42 +1950,22 @@ static int handle_session_response(struct msm_vidc_core *core,
 	}
 
 	inst_lock(inst, __func__);
-	/* search for special pkt */
+	/* search for cmd settings change pkt */
 	pkt = (u8 *)((u8 *)hdr + sizeof(struct hfi_header));
 	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) {
-				offload = true;
-				type = RESP_WORK_INPUT_PSC;
-			} else if (packet->port == HFI_PORT_RAW) {
-				offload = true;
-				type = RESP_WORK_OUTPUT_PSC;
-			}
-		} else if (packet->type == HFI_CMD_BUFFER &&
-			vidc_port_from_hfi(inst, packet->port) ==
-				OUTPUT_PORT) {
-			if (check_last_flag(inst, packet)) {
-				offload = true;
-				type = RESP_WORK_LAST_FLAG;
+				found_ipsc = true;
+				break;
 			}
 		}
-
-		if (offload)
-			break;
-
 		pkt += packet->size;
 	}
 
-	if (offload) {
-		i_vpr_h(inst, "%s: queue response work %#x\n", __func__, type);
-		rc = queue_response_work(inst, type, (void *)hdr, hdr->size);
-		if (rc)
-			i_vpr_e(inst, "%s: Offload response work failed\n", __func__);
-
-		goto exit;
-	}
+	/* if ipsc packet is found, initialise subsc_params */
+	if (found_ipsc)
+		msm_vdec_init_input_subcr_params(inst);
 
 	rc = __handle_session_response(inst, hdr);
 	if (rc)

+ 16 - 0
include/uapi/vidc/media/v4l2_vidc_extensions.h

@@ -268,6 +268,9 @@ enum v4l2_h264_encode_delivery_mode {
 #define V4L2_CID_MPEG_VIDC_CLIENT_ID                                          \
 	(V4L2_CID_MPEG_VIDC_BASE + 0x41)
 
+#define V4L2_CID_MPEG_VIDC_LAST_FLAG_EVENT_ENABLE                             \
+	(V4L2_CID_MPEG_VIDC_BASE + 0x42)
+
 /* add new controls above this line */
 /* Deprecate below controls once availble in gki and gsi bionic header */
 #ifndef V4L2_CID_MPEG_VIDEO_BASELAYER_PRIORITY_ID
@@ -461,6 +464,19 @@ struct v4l2_event_vidc_metadata {
 	__u32                                offset;
 	__u8                                 reserved[44];
 };
+
+#define V4L2_EVENT_VIDC_LAST_FLAG                                             \
+	(V4L2_EVENT_PRIVATE_START + 0x2)
+
+enum v4l2_event_last_flag {
+	LAST_FLAG_DRC         = (1 << 0),
+	LAST_FLAG_DRAIN       = (1 << 1),
+};
+
+struct v4l2_event_vidc_last_flag {
+	enum v4l2_event_last_flag flag_type;
+};
+
 /* vendor events end */
 
 /* Default metadata size (align to 4KB) */

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác