Эх сурвалжийг харах

video: driver: fixes for PSC on latest fw

- post input psc, output psc and last flag
  events to response work handler
- fix issue with release and create internal
  buffers during input psc
- clear last flag after session continue

Change-Id: Ic0278a09a0f6ee8ffff8840a47cd80c046ecadc4
Signed-off-by: Darshana Patil <[email protected]>
Darshana Patil 4 жил өмнө
parent
commit
d98075c932

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

@@ -251,7 +251,7 @@ 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_streamon(struct msm_vidc_inst *inst, u32 type);
 bool msm_vidc_allow_streamoff(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);
 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_input_psc(struct msm_vidc_inst *inst);
 bool msm_vidc_allow_last_flag(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_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_streamoff(struct msm_vidc_inst *inst, u32 type);

+ 3 - 3
driver/vidc/inc/msm_vidc_inst.h

@@ -123,9 +123,9 @@ struct msm_vidc_inst {
 	struct msm_vidc_decode_batch       decode_batch;
 	struct msm_vidc_decode_batch       decode_batch;
 	struct msm_vidc_decode_vpp_delay   decode_vpp_delay;
 	struct msm_vidc_decode_vpp_delay   decode_vpp_delay;
 	struct msm_vidc_session_idle       session_idle;
 	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 delayed_work                response_work;
+	struct workqueue_struct           *response_workq;
+	struct list_head                   response_works; /* list of struct response_work */
 	struct list_head                   input_ts;
 	struct list_head                   input_ts;
 	struct list_head                   enc_input_crs;
 	struct list_head                   enc_input_crs;
 	struct list_head                   decode_bitrate_data;
 	struct list_head                   decode_bitrate_data;

+ 11 - 4
driver/vidc/inc/msm_vidc_internal.h

@@ -706,10 +706,17 @@ struct msm_vidc_buffers {
 	bool                   reuse;
 	bool                   reuse;
 };
 };
 
 
-struct input_psc_work {
-	struct list_head list;
-	void *data;
-	u32 data_size;
+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 {
 struct msm_vidc_ssr {

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

@@ -14,8 +14,8 @@ bool is_valid_port(struct msm_vidc_inst *inst, u32 port,
 	const char *func);
 	const char *func);
 bool is_valid_hfi_buffer_type(struct msm_vidc_inst *inst,
 bool is_valid_hfi_buffer_type(struct msm_vidc_inst *inst,
 	u32 buffer_type, const char *func);
 	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);
+void handle_session_response_work_handler(struct work_struct *work);
+int handle_session_response_work(struct msm_vidc_inst *inst,
+	struct response_work *work);
 
 
 #endif // __VENUS_HFI_RESPONSE_H__
 #endif // __VENUS_HFI_RESPONSE_H__

+ 19 - 7
driver/vidc/src/msm_vdec.c

@@ -769,7 +769,7 @@ static int msm_vdec_get_input_internal_buffers(struct msm_vidc_inst *inst)
 		inst->buffers.line.min_count,
 		inst->buffers.line.min_count,
 		inst->buffers.line.size,
 		inst->buffers.line.size,
 		inst->buffers.line.reuse);
 		inst->buffers.line.reuse);
-	s_vpr_h(inst->sid, "buffer: %d      %d      %d\n",
+	s_vpr_h(inst->sid, "persist buffer: %d      %d      %d\n",
 		inst->buffers.persist.min_count,
 		inst->buffers.persist.min_count,
 		inst->buffers.persist.size,
 		inst->buffers.persist.size,
 		inst->buffers.persist.reuse);
 		inst->buffers.persist.reuse);
@@ -1059,11 +1059,18 @@ static int msm_vdec_session_resume(struct msm_vidc_inst *inst,
 	return rc;
 	return rc;
 }
 }
 
 
-static int msm_vdec_update_input_properties(struct msm_vidc_inst *inst)
+static int msm_vdec_update_properties(struct msm_vidc_inst *inst)
 {
 {
 	struct msm_vidc_subscription_params subsc_params;
 	struct msm_vidc_subscription_params subsc_params;
+	struct msm_vidc_core *core;
 	u32 width, height;
 	u32 width, height;
 
 
+	if (!inst || !inst->core) {
+		d_vpr_e("%s: invalid params\n", __func__);
+		return -EINVAL;
+	}
+	core = inst->core;
+
 	subsc_params = inst->subcr_params[INPUT_PORT];
 	subsc_params = inst->subcr_params[INPUT_PORT];
 	width = (subsc_params.bitstream_resolution &
 	width = (subsc_params.bitstream_resolution &
 		HFI_BITMASK_BITSTREAM_WIDTH) >> 16;
 		HFI_BITMASK_BITSTREAM_WIDTH) >> 16;
@@ -1081,8 +1088,11 @@ static int msm_vdec_update_input_properties(struct msm_vidc_inst *inst)
 		v4l2_colorformat_to_media(
 		v4l2_colorformat_to_media(
 		inst->fmts[OUTPUT_PORT].fmt.pix_mp.pixelformat,	__func__),
 		inst->fmts[OUTPUT_PORT].fmt.pix_mp.pixelformat,	__func__),
 		height);
 		height);
-	//inst->fmts[OUTPUT_PORT].fmt.pix_mp.bytesperline =
-		//inst->fmts[OUTPUT_PORT].fmt.pix_mp.width;
+	inst->fmts[OUTPUT_PORT].fmt.pix_mp.plane_fmt[0].bytesperline =
+		inst->fmts[OUTPUT_PORT].fmt.pix_mp.width;
+	inst->fmts[OUTPUT_PORT].fmt.pix_mp.plane_fmt[0].sizeimage =
+		call_session_op(core, buffer_size, inst, MSM_VIDC_BUF_OUTPUT);
+	//inst->buffers.output.size = inst->fmts[OUTPUT_PORT].fmt.pix_mp.plane_fmt[0].sizeimage;
 
 
 	inst->fmts[OUTPUT_PORT].fmt.pix_mp.colorspace =
 	inst->fmts[OUTPUT_PORT].fmt.pix_mp.colorspace =
 		(subsc_params.color_info & 0xFF0000) >> 16;
 		(subsc_params.color_info & 0xFF0000) >> 16;
@@ -1122,7 +1132,7 @@ int msm_vdec_input_port_settings_change(struct msm_vidc_inst *inst)
 		return 0;
 		return 0;
 	}
 	}
 
 
-	rc = msm_vdec_update_input_properties(inst);
+	rc = msm_vdec_update_properties(inst);
 	if (rc)
 	if (rc)
 		return rc;
 		return rc;
 
 
@@ -1130,11 +1140,11 @@ int msm_vdec_input_port_settings_change(struct msm_vidc_inst *inst)
 	event.u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION;
 	event.u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION;
 	v4l2_event_queue_fh(&inst->event_handler, &event);
 	v4l2_event_queue_fh(&inst->event_handler, &event);
 
 
-	rc = msm_vdec_release_input_internal_buffers(inst);
+	rc = msm_vdec_get_input_internal_buffers(inst);
 	if (rc)
 	if (rc)
 		return rc;
 		return rc;
 
 
-	rc = msm_vdec_get_input_internal_buffers(inst);
+	rc = msm_vdec_release_input_internal_buffers(inst);
 	if (rc)
 	if (rc)
 		return rc;
 		return rc;
 
 
@@ -1492,6 +1502,8 @@ int msm_vdec_process_cmd(struct msm_vidc_inst *inst, u32 cmd)
 				0);
 				0);
 		if (rc)
 		if (rc)
 			return rc;
 			return rc;
+		vb2_clear_last_buffer_dequeued(&inst->vb2q[OUTPUT_META_PORT]);
+		vb2_clear_last_buffer_dequeued(&inst->vb2q[OUTPUT_PORT]);
 	} else {
 	} else {
 		d_vpr_e("%s: unknown cmd %d\n", __func__, cmd);
 		d_vpr_e("%s: unknown cmd %d\n", __func__, cmd);
 		return -EINVAL;
 		return -EINVAL;

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

@@ -256,7 +256,7 @@ int msm_vidc_g_fmt(void *instance, struct v4l2_format *f)
 	if (f->type == INPUT_MPLANE || f->type == OUTPUT_MPLANE)
 	if (f->type == INPUT_MPLANE || f->type == OUTPUT_MPLANE)
 		s_vpr_h(inst->sid,
 		s_vpr_h(inst->sid,
 			"%s: type %d format %#x width %d height %d size %d\n",
 			"%s: type %d format %#x width %d height %d size %d\n",
-			__func__, f->fmt.pix_mp.pixelformat, f->fmt.pix_mp.width,
+			__func__, f->type, f->fmt.pix_mp.pixelformat, f->fmt.pix_mp.width,
 			f->fmt.pix_mp.height, f->fmt.pix_mp.plane_fmt[0].sizeimage);
 			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)
 	else if (f->type == INPUT_META_PLANE || f->type == OUTPUT_META_PLANE)
 		s_vpr_h(inst->sid, "%s: meta type %d size %d\n",
 		s_vpr_h(inst->sid, "%s: meta type %d size %d\n",
@@ -683,8 +683,8 @@ void *msm_vidc_open(void *vidc_core, u32 session_type)
 	}
 	}
 	s_vpr_i(inst->sid, "Opening video instance: %d\n", session_type);
 	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) {
+	inst->response_workq = create_singlethread_workqueue("response_workq");
+	if (!inst->response_workq) {
 		d_vpr_e("%s: create input_psc_workq failed\n", __func__);
 		d_vpr_e("%s: create input_psc_workq failed\n", __func__);
 		goto error;
 		goto error;
 	}
 	}
@@ -697,10 +697,10 @@ void *msm_vidc_open(void *vidc_core, u32 session_type)
 		goto error;
 		goto error;
 	}
 	}
 
 
-	INIT_DELAYED_WORK(&inst->input_psc_work,
-			handle_session_input_psc_work_handler);
+	INIT_DELAYED_WORK(&inst->response_work,
+			handle_session_response_work_handler);
 
 
-	INIT_LIST_HEAD(&inst->input_psc_works);
+	INIT_LIST_HEAD(&inst->response_works);
 	INIT_LIST_HEAD(&inst->buffers.input.list);
 	INIT_LIST_HEAD(&inst->buffers.input.list);
 	INIT_LIST_HEAD(&inst->buffers.input_meta.list);
 	INIT_LIST_HEAD(&inst->buffers.input_meta.list);
 	INIT_LIST_HEAD(&inst->buffers.output.list);
 	INIT_LIST_HEAD(&inst->buffers.output.list);

+ 75 - 70
driver/vidc/src/msm_vidc_driver.c

@@ -695,18 +695,18 @@ 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_input_psc(struct msm_vidc_inst *inst)
 {
 {
-	int rc = 0;
+	bool allow = false;
 
 
 	if (!inst) {
 	if (!inst) {
 		d_vpr_e("%s: invalid params\n", __func__);
 		d_vpr_e("%s: invalid params\n", __func__);
-		return -EINVAL;
+		return false;
 	}
 	}
 	if (inst->state == MSM_VIDC_START ||
 	if (inst->state == MSM_VIDC_START ||
 		inst->state == MSM_VIDC_START_INPUT ||
 		inst->state == MSM_VIDC_START_INPUT ||
 		inst->state == MSM_VIDC_DRAIN) {
 		inst->state == MSM_VIDC_DRAIN) {
-		rc = 0;
+		allow = true;
 	} else if (inst->state == MSM_VIDC_DRC ||
 	} else if (inst->state == MSM_VIDC_DRC ||
 		inst->state == MSM_VIDC_DRC_LAST_FLAG ||
 		inst->state == MSM_VIDC_DRC_LAST_FLAG ||
 		inst->state == MSM_VIDC_DRC_DRAIN ||
 		inst->state == MSM_VIDC_DRC_DRAIN ||
@@ -714,14 +714,14 @@ int msm_vidc_allow_input_psc(struct msm_vidc_inst *inst)
 		inst->state == MSM_VIDC_DRAIN_START_INPUT) {
 		inst->state == MSM_VIDC_DRAIN_START_INPUT) {
 		s_vpr_h(inst->sid, "%s: input psc postponed, inst state %s\n",
 		s_vpr_h(inst->sid, "%s: input psc postponed, inst state %s\n",
 				__func__, state_name(inst->state));
 				__func__, state_name(inst->state));
-		rc = -EAGAIN;
+		allow = false;
 	} else {
 	} else {
 		s_vpr_e(inst->sid, "%s: input psc in wrong state %s\n",
 		s_vpr_e(inst->sid, "%s: input psc in wrong state %s\n",
 				__func__, state_name(inst->state));
 				__func__, state_name(inst->state));
-		rc = -EINVAL;
+		allow = false;
 	}
 	}
 
 
-	return rc;
+	return allow;
 }
 }
 
 
 bool msm_vidc_allow_last_flag(struct msm_vidc_inst *inst)
 bool msm_vidc_allow_last_flag(struct msm_vidc_inst *inst)
@@ -744,7 +744,7 @@ int msm_vidc_state_change_streamon(struct msm_vidc_inst *inst, u32 type)
 {
 {
 	int rc = 0;
 	int rc = 0;
 	enum msm_vidc_inst_state new_state = MSM_VIDC_ERROR;
 	enum msm_vidc_inst_state new_state = MSM_VIDC_ERROR;
-	struct input_psc_work *psc_work;
+	struct response_work *resp_work;
 
 
 	if (!inst || !inst->core) {
 	if (!inst || !inst->core) {
 		d_vpr_e("%s: invalid params\n", __func__);
 		d_vpr_e("%s: invalid params\n", __func__);
@@ -765,25 +765,26 @@ int msm_vidc_state_change_streamon(struct msm_vidc_inst *inst, u32 type)
 			s_vpr_h(inst->sid,
 			s_vpr_h(inst->sid,
 				"%s: streamon(output) in DRAIN_START_INPUT state\n",
 				"%s: streamon(output) in DRAIN_START_INPUT state\n",
 				__func__);
 				__func__);
-			if (list_empty(&inst->input_psc_works)) {
-				new_state = MSM_VIDC_DRAIN;
-			} else {
-				s_vpr_h(inst->sid,
-					"%s: streamon(output) in DRAIN_START_INPUT state, input psc pending\n",
-					__func__);
-				psc_work = list_first_entry(&inst->input_psc_works,
-							struct input_psc_work, list);
-				rc = handle_session_input_psc(inst, psc_work);
-				if (rc) {
-					s_vpr_e(inst->sid,
-						"%s: handle input psc failed\n", __func__);
-					new_state = MSM_VIDC_ERROR;
-				} else {
-					new_state = MSM_VIDC_DRC_DRAIN;
+			new_state = MSM_VIDC_DRAIN;
+			if (!list_empty(&inst->response_works)) {
+				resp_work = list_first_entry(&inst->response_works,
+							struct response_work, list);
+				if (resp_work->type == RESP_WORK_INPUT_PSC) {
+					s_vpr_h(inst->sid,
+						"%s: streamon(output) in DRAIN_START_INPUT state, input psc pending\n",
+						__func__);
+					rc = handle_session_response_work(inst, resp_work);
+					if (rc) {
+						s_vpr_e(inst->sid,
+							"%s: handle input psc failed\n", __func__);
+						new_state = MSM_VIDC_ERROR;
+					} else {
+						new_state = MSM_VIDC_DRC_DRAIN;
+					}
+					list_del(&resp_work->list);
+					kfree(resp_work->data);
+					kfree(resp_work);
 				}
 				}
-				list_del(&psc_work->list);
-				kfree(psc_work->data);
-				kfree(psc_work);
 			}
 			}
 		}
 		}
 	}
 	}
@@ -798,7 +799,7 @@ int msm_vidc_state_change_streamoff(struct msm_vidc_inst *inst, u32 type)
 {
 {
 	int rc = 0;
 	int rc = 0;
 	enum msm_vidc_inst_state new_state = MSM_VIDC_ERROR;
 	enum msm_vidc_inst_state new_state = MSM_VIDC_ERROR;
-	struct input_psc_work *psc_work, *dummy;
+	struct response_work *resp_work, *dummy;
 
 
 	if (!inst || !inst->core) {
 	if (!inst || !inst->core) {
 		d_vpr_e("%s: invalid params\n", __func__);
 		d_vpr_e("%s: invalid params\n", __func__);
@@ -819,13 +820,15 @@ int msm_vidc_state_change_streamoff(struct msm_vidc_inst *inst, u32 type)
 				   inst->state == MSM_VIDC_DRAIN_START_INPUT) {
 				   inst->state == MSM_VIDC_DRAIN_START_INPUT) {
 			new_state = MSM_VIDC_START_OUTPUT;
 			new_state = MSM_VIDC_START_OUTPUT;
 			/* discard pending port settings change if any */
 			/* discard pending port settings change if any */
-			list_for_each_entry_safe(psc_work, dummy,
-						&inst->input_psc_works, list) {
-				s_vpr_h(inst->sid,
-					"%s: discard pending input psc\n", __func__);
-				list_del(&psc_work->list);
-				kfree(psc_work->data);
-				kfree(psc_work);
+			list_for_each_entry_safe(resp_work, dummy,
+						&inst->response_works, list) {
+				if (resp_work->type == RESP_WORK_INPUT_PSC) {
+					s_vpr_h(inst->sid,
+						"%s: discard pending input psc\n", __func__);
+					list_del(&resp_work->list);
+					kfree(resp_work->data);
+					kfree(resp_work);
+				}
 			}
 			}
 		}
 		}
 	} else if (type == OUTPUT_MPLANE) {
 	} else if (type == OUTPUT_MPLANE) {
@@ -884,7 +887,7 @@ int msm_vidc_state_change_start(struct msm_vidc_inst *inst)
 {
 {
 	int rc = 0;
 	int rc = 0;
 	enum msm_vidc_inst_state new_state = MSM_VIDC_ERROR;
 	enum msm_vidc_inst_state new_state = MSM_VIDC_ERROR;
-	struct input_psc_work *psc_work;
+	struct response_work *resp_work;
 
 
 	if (!inst || !inst->core) {
 	if (!inst || !inst->core) {
 		d_vpr_e("%s: invalid params\n", __func__);
 		d_vpr_e("%s: invalid params\n", __func__);
@@ -893,45 +896,47 @@ int msm_vidc_state_change_start(struct msm_vidc_inst *inst)
 
 
 	if (inst->state == MSM_VIDC_DRAIN_LAST_FLAG ||
 	if (inst->state == MSM_VIDC_DRAIN_LAST_FLAG ||
 		inst->state == MSM_VIDC_DRC_LAST_FLAG) {
 		inst->state == MSM_VIDC_DRC_LAST_FLAG) {
-		if (list_empty(&inst->input_psc_works)) {
 			new_state = MSM_VIDC_START;
 			new_state = MSM_VIDC_START;
-		} else {
-			s_vpr_h(inst->sid,
-				"%s: start in DRC(DRAIN)_LAST_FLAG state, input psc pending\n",
-				__func__);
-			psc_work = list_first_entry(&inst->input_psc_works,
-				struct input_psc_work, list);
-			rc = handle_session_input_psc(inst, psc_work);
-			if (rc) {
-				s_vpr_e(inst->sid,
-					"%s: handle input psc failed\n", __func__);
-				new_state = MSM_VIDC_ERROR;
-			} else {
-				new_state = MSM_VIDC_DRC;
+		if (!list_empty(&inst->response_works)) {
+			resp_work = list_first_entry(&inst->response_works,
+				struct response_work, list);
+			if (resp_work->type == RESP_WORK_INPUT_PSC) {
+				s_vpr_h(inst->sid,
+					"%s: start in DRC(DRAIN)_LAST_FLAG state, input psc pending\n",
+					__func__);
+				rc = handle_session_response_work(inst, resp_work);
+				if (rc) {
+					s_vpr_e(inst->sid,
+						"%s: handle input psc failed\n", __func__);
+					new_state = MSM_VIDC_ERROR;
+				} else {
+					new_state = MSM_VIDC_DRC;
+				}
+				list_del(&resp_work->list);
+				kfree(resp_work->data);
+				kfree(resp_work);
 			}
 			}
-			list_del(&psc_work->list);
-			kfree(psc_work->data);
-			kfree(psc_work);
 		}
 		}
 	} else if (inst->state == MSM_VIDC_DRC_DRAIN_LAST_FLAG) {
 	} else if (inst->state == MSM_VIDC_DRC_DRAIN_LAST_FLAG) {
-		if (list_empty(&inst->input_psc_works)) {
 			new_state = MSM_VIDC_DRAIN;
 			new_state = MSM_VIDC_DRAIN;
-		} else {
-			s_vpr_h(inst->sid,
-				"%s: start in DRC_DRAIN_LAST_FLAG state, input psc pending\n");
-			psc_work = list_first_entry(&inst->input_psc_works,
-				struct input_psc_work, list);
-			rc = handle_session_input_psc(inst, psc_work);
-			if (rc) {
-				s_vpr_e(inst->sid,
-					"%s: handle input psc failed\n", __func__);
-				new_state = MSM_VIDC_ERROR;
-			} else {
-				new_state = MSM_VIDC_DRC_DRAIN;
+		if (!list_empty(&inst->response_works)) {
+			resp_work = list_first_entry(&inst->response_works,
+				struct response_work, list);
+			if (resp_work->type == RESP_WORK_INPUT_PSC) {
+				s_vpr_h(inst->sid,
+					"%s: start in DRC_DRAIN_LAST_FLAG state, input psc pending\n");
+				rc = handle_session_response_work(inst, resp_work);
+				if (rc) {
+					s_vpr_e(inst->sid,
+						"%s: handle input psc failed\n", __func__);
+					new_state = MSM_VIDC_ERROR;
+				} else {
+					new_state = MSM_VIDC_DRC_DRAIN;
+				}
+				list_del(&resp_work->list);
+				kfree(resp_work->data);
+				kfree(resp_work);
 			}
 			}
-			list_del(&psc_work->list);
-			kfree(psc_work->data);
-			kfree(psc_work);
 		}
 		}
 	} else {
 	} else {
 		s_vpr_e(inst->sid, "%s: wrong state %s\n",
 		s_vpr_e(inst->sid, "%s: wrong state %s\n",
@@ -2480,8 +2485,8 @@ static void msm_vidc_close_helper(struct kref *kref)
 	else if (is_encode_session(inst))
 	else if (is_encode_session(inst))
 		msm_venc_inst_deinit(inst);
 		msm_venc_inst_deinit(inst);
 	kfree(inst->capabilities);
 	kfree(inst->capabilities);
-	if (inst->input_psc_workq)
-		destroy_workqueue(inst->input_psc_workq);
+	if (inst->response_workq)
+		destroy_workqueue(inst->response_workq);
 }
 }
 
 
 struct msm_vidc_inst *get_inst_ref(struct msm_vidc_core *core,
 struct msm_vidc_inst *get_inst_ref(struct msm_vidc_core *core,

+ 123 - 62
driver/vidc/src/venus_hfi_response.c

@@ -147,6 +147,25 @@ int validate_packet(u8 *response_pkt, u8 *core_resp_pkt,
 	return 0;
 	return 0;
 }
 }
 
 
+static bool check_last_flag(struct msm_vidc_inst *inst,
+	struct hfi_packet *pkt)
+{
+	struct hfi_buffer *buffer;
+
+	if (!inst || !pkt) {
+		d_vpr_e("%s: invalid params %d\n", __func__);
+		return false;
+	}
+
+	buffer = (struct hfi_buffer *)((u8 *)pkt + sizeof(struct hfi_packet));
+	if (buffer->flags & HFI_BUF_FW_FLAG_LAST) {
+		s_vpr_h(inst->sid, "%s: received last flag on FBD, index: %d\n",
+			__func__, buffer->index);
+		return true;
+	}
+	return false;
+}
+
 static int handle_session_info(struct msm_vidc_inst *inst,
 static int handle_session_info(struct msm_vidc_inst *inst,
 	struct hfi_packet *pkt)
 	struct hfi_packet *pkt)
 {
 {
@@ -432,12 +451,8 @@ static int handle_output_buffer(struct msm_vidc_inst *inst,
 	/*if (buffer->flags & HFI_BUF_FW_FLAG_SUBFRAME)
 	/*if (buffer->flags & HFI_BUF_FW_FLAG_SUBFRAME)
 		buf->flags |= MSM_VIDC_BUF_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);
-		}
-	}
+	if (buffer->flags & HFI_BUF_FW_FLAG_LAST)
+		buf->flags |= MSM_VIDC_BUF_FLAG_LAST;
 	print_vidc_buffer(VIDC_HIGH, "FBD", inst, buf);
 	print_vidc_buffer(VIDC_HIGH, "FBD", inst, buf);
 
 
 	return rc;
 	return rc;
@@ -970,8 +985,8 @@ exit:
 	return rc;
 	return rc;
 }
 }
 
 
-int handle_session_input_psc(struct msm_vidc_inst *inst,
-		struct input_psc_work *psc_work)
+int handle_session_response_work(struct msm_vidc_inst *inst,
+		struct response_work *resp_work)
 {
 {
 	int rc = 0;
 	int rc = 0;
 	struct hfi_header *hdr = NULL;
 	struct hfi_header *hdr = NULL;
@@ -981,12 +996,12 @@ int handle_session_input_psc(struct msm_vidc_inst *inst,
 	u32 hfi_port = 0;
 	u32 hfi_port = 0;
 	int i;
 	int i;
 
 
-	if (!inst || !psc_work) {
+	if (!inst || !resp_work) {
 		d_vpr_e("%s: invalid params\n", __func__);
 		d_vpr_e("%s: invalid params\n", __func__);
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
-	hdr = (struct hfi_header *)psc_work->data;
+	hdr = (struct hfi_header *)resp_work->data;
 	if (!hdr) {
 	if (!hdr) {
 		d_vpr_e("%s: invalid params\n", __func__);
 		d_vpr_e("%s: invalid params\n", __func__);
 		return -EINVAL;
 		return -EINVAL;
@@ -998,8 +1013,8 @@ int handle_session_input_psc(struct msm_vidc_inst *inst,
 	temp_pkt = pkt;
 	temp_pkt = pkt;
 
 
 	for (i = 0; i < hdr->num_packets; i++) {
 	for (i = 0; i < hdr->num_packets; i++) {
-		if (validate_packet(pkt, psc_work->data,
-				psc_work->data_size, __func__)) {
+		if (validate_packet(pkt, resp_work->data,
+				resp_work->data_size, __func__)) {
 			rc = -EINVAL;
 			rc = -EINVAL;
 			goto exit;
 			goto exit;
 		}
 		}
@@ -1034,23 +1049,44 @@ int handle_session_input_psc(struct msm_vidc_inst *inst,
 		pkt += packet->size;
 		pkt += packet->size;
 	}
 	}
 
 
-	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;
+
+	if (hfi_cmd_type == HFI_CMD_BUFFER) {
+		rc = handle_dequeue_buffers(inst);
+		if (rc)
+			goto exit;
+	}
+
+	if (hfi_cmd_type == HFI_CMD_SETTINGS_CHANGE) {
+		if (hfi_port == HFI_PORT_RAW) {
+			print_psc_properties(VIDC_HIGH, "OUTPUT_PSC", inst,
+				inst->subcr_params[OUTPUT_PORT]);
+			rc = msm_vdec_output_port_settings_change(inst);
+			if (rc)
+				goto exit;
+		} else 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;
+		} else {
+			s_vpr_e(inst->sid, "%s: invalid port type: %#x\n",
+				__func__, hfi_port);
+		}
+	}
 
 
 exit:
 exit:
 	return rc;
 	return rc;
 }
 }
 
 
-void handle_session_input_psc_work_handler(struct work_struct *work)
+void handle_session_response_work_handler(struct work_struct *work)
 {
 {
 	int rc = 0;
 	int rc = 0;
+	bool allow = false;
 	struct msm_vidc_inst *inst;
 	struct msm_vidc_inst *inst;
-	struct input_psc_work *psc_work, *dummy = NULL;
+	struct response_work *resp_work, *dummy = NULL;
 
 
-	inst = container_of(work, struct msm_vidc_inst, input_psc_work.work);
+	inst = container_of(work, struct msm_vidc_inst, response_work.work);
 	inst = get_inst_ref(g_core, inst);
 	inst = get_inst_ref(g_core, inst);
 	if (!inst) {
 	if (!inst) {
 		d_vpr_e("%s: invalid params\n", __func__);
 		d_vpr_e("%s: invalid params\n", __func__);
@@ -1058,26 +1094,74 @@ void handle_session_input_psc_work_handler(struct work_struct *work)
 	}
 	}
 
 
 	mutex_lock(&inst->lock);
 	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);
+	list_for_each_entry_safe(resp_work, dummy, &inst->response_works, list) {
+		switch (resp_work->type) {
+		case RESP_WORK_INPUT_PSC:
+			allow = msm_vidc_allow_input_psc(inst);
+			if (!allow) {
+				s_vpr_e(inst->sid, "%s: input psc not allowed\n", __func__);
+				break;
+			}
+			rc = handle_session_response_work(inst, resp_work);
 			if (!rc)
 			if (!rc)
 				rc = msm_vidc_state_change_input_psc(inst);
 				rc = msm_vidc_state_change_input_psc(inst);
 
 
 			/* either handle input psc or state change failed */
 			/* either handle input psc or state change failed */
 			if (rc)
 			if (rc)
 				msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__);
 				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:
+			allow = msm_vidc_allow_last_flag(inst);
+			if (!allow) {
+				s_vpr_e(inst->sid, "%s: last flag not allowed\n", __func__);
+				break;
+			}
+			rc = handle_session_response_work(inst, resp_work);
+			if (!rc)
+				rc = msm_vidc_state_change_last_flag(inst);
+
+			/* either handle last flag or state change failed */
+			if (rc)
+				msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__);
+			break;
+		default:
+			d_vpr_e("%s: invalid response work type %d\n", __func__,
+				resp_work->type);
+			break;
 		}
 		}
-		list_del(&psc_work->list);
-		kfree(psc_work->data);
-		kfree(psc_work);
+		list_del(&resp_work->list);
+		kfree(resp_work->data);
+		kfree(resp_work);
 	}
 	}
 	mutex_unlock(&inst->lock);
 	mutex_unlock(&inst->lock);
 
 
 	put_inst(inst);
 	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;
+
+	work = kzalloc(sizeof(struct response_work), GFP_KERNEL);
+	INIT_LIST_HEAD(&work->list);
+	work->type = type;
+	work->data_size = hdr_size;
+	work->data = kzalloc(hdr_size, GFP_KERNEL);
+	if (!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;
+}
+
 static int handle_session_response(struct msm_vidc_core *core,
 static int handle_session_response(struct msm_vidc_core *core,
 	struct hfi_header *hdr)
 	struct hfi_header *hdr)
 {
 {
@@ -1109,29 +1193,19 @@ static int handle_session_response(struct msm_vidc_core *core,
 		packet = (struct hfi_packet *)pkt;
 		packet = (struct hfi_packet *)pkt;
 		if (packet->type > HFI_CMD_BEGIN &&
 		if (packet->type > HFI_CMD_BEGIN &&
 		    packet->type < HFI_CMD_END) {
 		    packet->type < HFI_CMD_END) {
-			if (packet->type == HFI_CMD_SETTINGS_CHANGE &&
-				packet->port == HFI_PORT_BITSTREAM) {
-				struct input_psc_work *work;
-
-				work = kzalloc(sizeof(struct input_psc_work), GFP_KERNEL);
-				INIT_LIST_HEAD(&work->list);
-				work->data_size = hdr->size;
-				work->data = kzalloc(hdr->size, GFP_KERNEL);
-				if (!work->data) {
-					rc= -ENOMEM;
+			if (packet->type == HFI_CMD_SETTINGS_CHANGE) {
+				if (packet->port == HFI_PORT_BITSTREAM)
+					rc = queue_response_work(inst, RESP_WORK_INPUT_PSC,
+						(void *)hdr, hdr->size);
+				else if (packet->port == HFI_PORT_RAW)
+					rc = queue_response_work(inst, RESP_WORK_OUTPUT_PSC,
+						(void *)hdr, hdr->size);
 					goto exit;
 					goto exit;
-				}
-				memcpy(work->data, (void *)hdr, hdr->size);
-				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) {
-				s_vpr_e(inst->sid,
-					"%s: invalid packet type %d in port settings change\n",
-					__func__, packet->type);
-				rc = -EINVAL;
+			} else if (packet->type == HFI_CMD_BUFFER &&
+						packet->port == HFI_PORT_RAW &&
+						check_last_flag(inst, packet)) {
+				rc = queue_response_work(inst, RESP_WORK_LAST_FLAG,
+					(void *)hdr, hdr->size);
 				goto exit;
 				goto exit;
 			}
 			}
 			hfi_cmd_type = packet->type;
 			hfi_cmd_type = packet->type;
@@ -1161,19 +1235,6 @@ static int handle_session_response(struct msm_vidc_core *core,
 			goto exit;
 			goto exit;
 	}
 	}
 
 
-	if (hfi_cmd_type == HFI_CMD_SETTINGS_CHANGE) {
-		if (hfi_port == HFI_PORT_RAW) {
-			print_psc_properties(VIDC_HIGH, "OUTPUT_PSC", inst,
-				inst->subcr_params[OUTPUT_PORT]);
-			rc = msm_vdec_output_port_settings_change(inst);
-			if (rc)
-				goto exit;
-		} else {
-			s_vpr_e(inst->sid, "%s: invalid port type: %#x\n",
-				__func__, hfi_port);
-		}
-	}
-
 exit:
 exit:
 	mutex_unlock(&inst->lock);
 	mutex_unlock(&inst->lock);
 	put_inst(inst);
 	put_inst(inst);