msm: vidc: Release DPBs only held by driver during reconfig

For VP9 there is a chance that firmware holds back DPBs
during port reconfig(scalability). These buffers shouldn't
be freed when firmware has ownership. Modified release
output buffer to take care of this and during close
instance we free all DPB's irrespective of ownership.

CRs-Fixed: 1010707
Change-Id: Iecb1e3784b4c4b45063694d933ee66f755a84935
Signed-off-by: Vaibhav Deshu Venkatesh <vdeshuve@codeaurora.org>
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index 564ab99..00feba6 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -1414,7 +1414,7 @@
 	put_inst(inst);
 }
 
-void validate_output_buffers(struct msm_vidc_inst *inst)
+void msm_comm_validate_output_buffers(struct msm_vidc_inst *inst)
 {
 	struct internal_buf *binfo;
 	u32 buffers_owned_by_driver = 0;
@@ -1440,11 +1440,13 @@
 	}
 	mutex_unlock(&inst->outputbufs.lock);
 
-	if (buffers_owned_by_driver != output_buf->buffer_count_actual)
+	if (buffers_owned_by_driver != output_buf->buffer_count_actual) {
 		dprintk(VIDC_WARN,
 			"OUTPUT Buffer count mismatch %d of %d\n",
 			buffers_owned_by_driver,
 			output_buf->buffer_count_actual);
+		msm_vidc_handle_hw_error(inst->core);
+	}
 }
 
 int msm_comm_queue_output_buffers(struct msm_vidc_inst *inst)
@@ -1524,7 +1526,11 @@
 
 	if (msm_comm_get_stream_output_mode(inst) ==
 			HAL_VIDEO_DECODER_SECONDARY) {
-		validate_output_buffers(inst);
+
+		if (!(inst->fmts[OUTPUT_PORT].defer_outputs &&
+				inst->in_reconfig))
+			msm_comm_validate_output_buffers(inst);
+
 		if (!inst->in_reconfig) {
 			rc = msm_comm_queue_output_buffers(inst);
 			if (rc) {
@@ -4051,7 +4057,8 @@
 	return rc;
 }
 
-int msm_comm_release_output_buffers(struct msm_vidc_inst *inst)
+int msm_comm_release_output_buffers(struct msm_vidc_inst *inst,
+	bool force_release)
 {
 	struct msm_smem *handle;
 	struct internal_buf *buf, *dummy;
@@ -4093,6 +4100,11 @@
 			goto exit;
 		}
 
+		if ((buf->buffer_ownership == FIRMWARE) && !force_release) {
+			dprintk(VIDC_INFO, "DPB is with f/w. Can't free it\n");
+			continue;
+		}
+
 		buffer_info.buffer_size = handle->size;
 		buffer_info.buffer_type = buf->buffer_type;
 		buffer_info.num_buffers = 1;
@@ -4352,13 +4364,17 @@
 int msm_comm_set_output_buffers(struct msm_vidc_inst *inst)
 {
 	int rc = 0;
+	bool force_release = true;
 
 	if (!inst || !inst->core || !inst->core->device) {
 		dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
 		return -EINVAL;
 	}
 
-	if (msm_comm_release_output_buffers(inst))
+	if (inst->fmts[OUTPUT_PORT].defer_outputs)
+		force_release = false;
+
+	if (msm_comm_release_output_buffers(inst, force_release))
 		dprintk(VIDC_WARN, "Failed to release output buffers\n");
 
 	rc = set_output_buffers(inst, HAL_BUFFER_OUTPUT);
@@ -4366,7 +4382,7 @@
 		goto error;
 	return rc;
 error:
-	msm_comm_release_output_buffers(inst);
+	msm_comm_release_output_buffers(inst, true);
 	return rc;
 }