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

video: driver: release internal buffer as part of start/resume

Change-Id: I45469c0a569fbc282aa1dbd217654e49eb50f54f
Signed-off-by: Darshana Patil <[email protected]>
Darshana Patil 3 жил өмнө
parent
commit
fb1ecb69d0

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

@@ -30,5 +30,9 @@ 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_handle_release_buffer(struct msm_vidc_inst *inst,
 	struct msm_vidc_buffer *buf);
+int msm_vdec_get_input_internal_buffers(struct msm_vidc_inst *inst);
+int msm_vdec_create_input_internal_buffers(struct msm_vidc_inst *inst);
+int msm_vdec_queue_input_internal_buffers(struct msm_vidc_inst *inst);
+int msm_vdec_release_input_internal_buffers(struct msm_vidc_inst *inst);
 
 #endif // _MSM_VDEC_H_

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

@@ -523,7 +523,8 @@ 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_streamon_input(struct msm_vidc_inst *inst);
+int msm_vidc_process_streamon_output(struct msm_vidc_inst *inst);
 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);
@@ -586,5 +587,6 @@ int msm_vidc_update_input_rate(struct msm_vidc_inst *inst, u64 time_us);
 int msm_vidc_get_input_rate(struct msm_vidc_inst *inst);
 int msm_vidc_get_frame_rate(struct msm_vidc_inst *inst);
 int msm_vidc_get_operating_rate(struct msm_vidc_inst *inst);
+int msm_vidc_alloc_and_queue_input_internal_buffers(struct msm_vidc_inst *inst);
 #endif // _MSM_VIDC_DRIVER_H_
 

+ 27 - 30
driver/vidc/src/msm_vdec.c

@@ -755,7 +755,7 @@ static int msm_vdec_set_output_properties(struct msm_vidc_inst *inst)
 	return rc;
 }
 
-static int msm_vdec_get_input_internal_buffers(struct msm_vidc_inst *inst)
+int msm_vdec_get_input_internal_buffers(struct msm_vidc_inst *inst)
 {
 	int rc = 0;
 	u32 i = 0;
@@ -790,7 +790,7 @@ static int msm_vdec_get_output_internal_buffers(struct msm_vidc_inst *inst)
 	return rc;
 }
 
-static int msm_vdec_create_input_internal_buffers(struct msm_vidc_inst *inst)
+int msm_vdec_create_input_internal_buffers(struct msm_vidc_inst *inst)
 {
 	int rc = 0;
 	u32 i = 0;
@@ -815,7 +815,7 @@ static int msm_vdec_create_output_internal_buffers(struct msm_vidc_inst *inst)
 	return 0;
 }
 
-static int msm_vdec_queue_input_internal_buffers(struct msm_vidc_inst *inst)
+int msm_vdec_queue_input_internal_buffers(struct msm_vidc_inst *inst)
 {
 	int rc = 0;
 	u32 i = 0;
@@ -840,7 +840,7 @@ static int msm_vdec_queue_output_internal_buffers(struct msm_vidc_inst *inst)
 	return 0;
 }
 
-static int msm_vdec_release_input_internal_buffers(struct msm_vidc_inst *inst)
+int msm_vdec_release_input_internal_buffers(struct msm_vidc_inst *inst)
 {
 	int rc = 0;
 	u32 i = 0;
@@ -1371,30 +1371,6 @@ int msm_vdec_input_port_settings_change(struct msm_vidc_inst *inst)
 	event.u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION;
 	v4l2_event_queue_fh(&inst->event_handler, &event);
 
-	rc = msm_vdec_get_input_internal_buffers(inst);
-	if (rc)
-		return rc;
-
-	rc = msm_vdec_release_input_internal_buffers(inst);
-	if (rc)
-		return rc;
-
-	rc = msm_vdec_create_input_internal_buffers(inst);
-	if (rc)
-		return rc;
-
-	rc = msm_vdec_queue_input_internal_buffers(inst);
-	if (rc)
-		return rc;
-
-	rc = msm_vidc_set_stage(inst, STAGE);
-	if (rc)
-		return rc;
-
-	rc = msm_vidc_set_pipe(inst, PIPE);
-	if (rc)
-		return rc;
-
 	return rc;
 }
 
@@ -1489,7 +1465,7 @@ int msm_vdec_streamon_input(struct msm_vidc_inst *inst)
 	if (rc)
 		goto error;
 
-	rc = msm_vidc_process_streamon(inst, INPUT_PORT);
+	rc = msm_vidc_process_streamon_input(inst);
 	if (rc)
 		goto error;
 
@@ -1809,7 +1785,7 @@ int msm_vdec_streamon_output(struct msm_vidc_inst *inst)
 	if (rc)
 		goto error;
 
-	rc = msm_vidc_process_streamon(inst, OUTPUT_PORT);
+	rc = msm_vidc_process_streamon_output(inst);
 	if (rc)
 		goto error;
 
@@ -2206,6 +2182,27 @@ int msm_vdec_process_cmd(struct msm_vidc_inst *inst, u32 cmd)
 		msm_vidc_allow_dcvs(inst);
 		msm_vidc_power_data_reset(inst);
 
+		/*
+		 * client is completing partial port reconfiguration,
+		 * hence reallocate input internal buffers before input port
+		 * is resumed.
+		 */
+		if (is_sub_state(inst, MSM_VIDC_DRC) &&
+			is_sub_state(inst, MSM_VIDC_DRC_LAST_BUFFER) &&
+			is_sub_state(inst, MSM_VIDC_INPUT_PAUSE)) {
+			rc = msm_vidc_alloc_and_queue_input_internal_buffers(inst);
+			if (rc)
+				return rc;
+
+			rc = msm_vidc_set_stage(inst, STAGE);
+			if (rc)
+				return rc;
+
+			rc = msm_vidc_set_pipe(inst, PIPE);
+			if (rc)
+				return rc;
+		}
+
 		/* allocate and queue extra dpb buffers */
 		rc = msm_vdec_alloc_and_queue_additional_dpb_buffers(inst);
 		if (rc)

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

@@ -863,7 +863,7 @@ int msm_venc_streamon_input(struct msm_vidc_inst *inst)
 	if (rc)
 		goto error;
 
-	rc = msm_vidc_process_streamon(inst, INPUT_PORT);
+	rc = msm_vidc_process_streamon_input(inst);
 	if (rc)
 		goto error;
 
@@ -1013,7 +1013,7 @@ int msm_venc_streamon_output(struct msm_vidc_inst *inst)
 	if (rc)
 		goto error;
 
-	rc = msm_vidc_process_streamon(inst, OUTPUT_PORT);
+	rc = msm_vidc_process_streamon_output(inst);
 	if (rc)
 		goto error;
 

+ 133 - 58
driver/vidc/src/msm_vidc_driver.c

@@ -1664,12 +1664,15 @@ bool msm_vidc_allow_start(struct msm_vidc_inst *inst)
 	}
 
 	/* client would call start (resume) to complete DRC/drain sequence */
-	if ((is_sub_state(inst, MSM_VIDC_DRC) &&
-		is_sub_state(inst, MSM_VIDC_DRC_LAST_BUFFER)) ||
-		(is_sub_state(inst, MSM_VIDC_DRAIN) &&
-		is_sub_state(inst, MSM_VIDC_DRAIN_LAST_BUFFER)))
-		allow = true;
-
+	if (inst->state == MSM_VIDC_INPUT_STREAMING ||
+		inst->state == MSM_VIDC_OUTPUT_STREAMING ||
+		inst->state == MSM_VIDC_STREAMING) {
+		if ((is_sub_state(inst, MSM_VIDC_DRC) &&
+			is_sub_state(inst, MSM_VIDC_DRC_LAST_BUFFER)) ||
+			(is_sub_state(inst, MSM_VIDC_DRAIN) &&
+			is_sub_state(inst, MSM_VIDC_DRAIN_LAST_BUFFER)))
+			allow = true;
+	}
 	if (!allow)
 		i_vpr_e(inst, "%s: not allowed in state %s, sub state %s\n",
 			__func__, state_name(inst->state), inst->sub_state_name);
@@ -1984,83 +1987,127 @@ int msm_vidc_process_resume(struct msm_vidc_inst *inst)
 	return rc;
 }
 
-int msm_vidc_process_streamon(struct msm_vidc_inst *inst,
-		enum msm_vidc_port_type port)
+int msm_vidc_process_streamon_input(struct msm_vidc_inst *inst)
 {
 	int rc = 0;
 	enum msm_vidc_sub_state clear_sub_state = MSM_VIDC_SUB_STATE_NONE;
 	enum msm_vidc_sub_state set_sub_state = MSM_VIDC_SUB_STATE_NONE;
-	bool drain_pending = false;
 
 	if (!inst) {
 		d_vpr_e("%s: invalid params\n", __func__);
 		return -EINVAL;
 	}
 
-	if (port == INPUT_META_PORT || port == OUTPUT_META_PORT)
-		return 0;
-
 	msm_vidc_scale_power(inst, true);
 
-	rc = venus_hfi_start(inst, port);
+	rc = venus_hfi_start(inst, INPUT_PORT);
 	if (rc)
 		return rc;
 
-	/* clear input/output pause substate immediately */
-	if (port == INPUT_PORT && is_sub_state(inst, MSM_VIDC_INPUT_PAUSE)) {
+	/* clear input pause substate immediately */
+	if (is_sub_state(inst, MSM_VIDC_INPUT_PAUSE)) {
 		rc = msm_vidc_change_sub_state(inst, MSM_VIDC_INPUT_PAUSE, 0, __func__);
 		if (rc)
 			return rc;
-	} else if (port == OUTPUT_PORT && is_sub_state(inst, MSM_VIDC_OUTPUT_PAUSE)) {
-		rc = msm_vidc_change_sub_state(inst, MSM_VIDC_OUTPUT_PAUSE, 0, __func__);
+	}
+
+	/*
+	 * if DRC sequence is not completed by the client then PAUSE
+	 * firmware input port to avoid firmware raising IPSC again.
+	 * When client completes DRC or DRAIN sequences, firmware
+	 * input port will be resumed.
+	 */
+	if (is_sub_state(inst, MSM_VIDC_DRC) ||
+		is_sub_state(inst, MSM_VIDC_DRAIN)) {
+		if (!is_sub_state(inst, MSM_VIDC_INPUT_PAUSE)) {
+			rc = venus_hfi_session_pause(inst, INPUT_PORT);
+			if (rc)
+				return rc;
+			set_sub_state = MSM_VIDC_INPUT_PAUSE;
+		}
+	}
+
+	rc = msm_vidc_state_change_streamon(inst, INPUT_PORT);
+	if (rc)
+		return rc;
+
+	rc = msm_vidc_change_sub_state(inst, clear_sub_state, set_sub_state, __func__);
+	if (rc)
+		return rc;
+
+	return rc;
+}
+
+int msm_vidc_process_streamon_output(struct msm_vidc_inst *inst)
+{
+	int rc = 0;
+	enum msm_vidc_sub_state clear_sub_state = MSM_VIDC_SUB_STATE_NONE;
+	enum msm_vidc_sub_state set_sub_state = MSM_VIDC_SUB_STATE_NONE;
+	bool drain_pending = false;
+
+	if (!inst) {
+		d_vpr_e("%s: invalid params\n", __func__);
+		return -EINVAL;
+	}
+
+	msm_vidc_scale_power(inst, true);
+
+	/*
+	 * client completed drc sequence, reset DRC and
+	 * MSM_VIDC_DRC_LAST_BUFFER substates
+	 */
+	if (is_sub_state(inst, MSM_VIDC_DRC) &&
+		is_sub_state(inst, MSM_VIDC_DRC_LAST_BUFFER)) {
+		clear_sub_state = MSM_VIDC_DRC | MSM_VIDC_DRC_LAST_BUFFER;
+	}
+	/*
+	 * Client is completing port reconfiguration, hence reallocate
+	 * input internal buffers before input port is resumed.
+	 * Drc sub-state cannot be checked because DRC sub-state will
+	 * not be set during initial port reconfiguration.
+	 */
+	if (is_decode_session(inst) &&
+		is_sub_state(inst, MSM_VIDC_INPUT_PAUSE)) {
+		rc = msm_vidc_alloc_and_queue_input_internal_buffers(inst);
+		if (rc)
+			return rc;
+		rc = msm_vidc_set_stage(inst, STAGE);
+		if (rc)
+			return rc;
+		rc = msm_vidc_set_pipe(inst, PIPE);
 		if (rc)
 			return rc;
 	}
 
-	if (port == INPUT_PORT) {
-		/*
-		 * if DRC sequence is not completed by the client then PAUSE
-		 * firmware input port to avoid firmware raising IPSC again.
-		 * When client completes DRC or DRAIN sequences, firmware
-		 * input port will be resumed.
-		 */
-		if (is_sub_state(inst, MSM_VIDC_DRC) ||
-			is_sub_state(inst, MSM_VIDC_DRAIN)) {
-			if (!is_sub_state(inst, MSM_VIDC_INPUT_PAUSE)) {
-				rc = venus_hfi_session_pause(inst, INPUT_PORT);
-				if (rc)
-					return rc;
-				set_sub_state = MSM_VIDC_INPUT_PAUSE;
-			}
-		}
-	} else if (port == OUTPUT_PORT) {
-		/*
-		 * client completed drc sequence, reset DRC and
-		 * MSM_VIDC_DRC_LAST_BUFFER substates
-		 */
-		if (is_sub_state(inst, MSM_VIDC_DRC) &&
-			is_sub_state(inst, MSM_VIDC_DRC_LAST_BUFFER)) {
-			clear_sub_state = MSM_VIDC_DRC | MSM_VIDC_DRC_LAST_BUFFER;
-		}
-		/*
-		 * fw input port is paused due to ipsc. now that client
-		 * completed drc sequence, resume fw input port provided
-		 * drain is not pending and input port is streaming.
-		 */
-		drain_pending = is_sub_state(inst, MSM_VIDC_DRAIN) &&
-			is_sub_state(inst, MSM_VIDC_DRAIN_LAST_BUFFER);
-		if (!drain_pending && is_state(inst, MSM_VIDC_INPUT_STREAMING)) {
-			if (is_sub_state(inst, MSM_VIDC_INPUT_PAUSE)) {
-				rc = venus_hfi_session_resume(inst, INPUT_PORT,
-						HFI_CMD_SETTINGS_CHANGE);
-				if (rc)
-					return rc;
-				clear_sub_state |= MSM_VIDC_INPUT_PAUSE;
-			}
+	/*
+	 * fw input port is paused due to ipsc. now that client
+	 * completed drc sequence, resume fw input port provided
+	 * drain is not pending and input port is streaming.
+	 */
+	drain_pending = is_sub_state(inst, MSM_VIDC_DRAIN) &&
+		is_sub_state(inst, MSM_VIDC_DRAIN_LAST_BUFFER);
+	if (!drain_pending && is_state(inst, MSM_VIDC_INPUT_STREAMING)) {
+		if (is_sub_state(inst, MSM_VIDC_INPUT_PAUSE)) {
+			rc = venus_hfi_session_resume(inst, INPUT_PORT,
+					HFI_CMD_SETTINGS_CHANGE);
+			if (rc)
+				return rc;
+			clear_sub_state |= MSM_VIDC_INPUT_PAUSE;
 		}
 	}
 
-	rc = msm_vidc_state_change_streamon(inst, port);
+	rc = venus_hfi_start(inst, OUTPUT_PORT);
+	if (rc)
+		return rc;
+
+	/* clear output pause substate immediately */
+	if (is_sub_state(inst, MSM_VIDC_OUTPUT_PAUSE)) {
+		rc = msm_vidc_change_sub_state(inst, MSM_VIDC_OUTPUT_PAUSE, 0, __func__);
+		if (rc)
+			return rc;
+	}
+
+	rc = msm_vidc_state_change_streamon(inst, OUTPUT_PORT);
 	if (rc)
 		return rc;
 
@@ -3587,6 +3634,34 @@ static int msm_vidc_queue_buffer(struct msm_vidc_inst *inst, struct msm_vidc_buf
 	return 0;
 }
 
+int msm_vidc_alloc_and_queue_input_internal_buffers(struct msm_vidc_inst *inst)
+{
+	int rc = 0;
+
+	if (!inst) {
+		d_vpr_e("%s: invalid params\n", __func__);
+		return -EINVAL;
+	}
+
+	rc = msm_vdec_get_input_internal_buffers(inst);
+	if (rc)
+		return rc;
+
+	rc = msm_vdec_release_input_internal_buffers(inst);
+	if (rc)
+		return rc;
+
+	rc = msm_vdec_create_input_internal_buffers(inst);
+	if (rc)
+		return rc;
+
+	rc = msm_vdec_queue_input_internal_buffers(inst);
+	if (rc)
+		return rc;
+
+	return rc;
+}
+
 int msm_vidc_queue_deferred_buffers(struct msm_vidc_inst *inst, enum msm_vidc_buffer_type buf_type)
 {
 	struct msm_vidc_buffers *buffers;