audio: qdsp6v2: handle flush and eos in encoder driver

Updated encoder driver to handle the flush and eos.

CRs-fixed: 283541
Signed-off-by: Rajesha Kini <rkini@codeaurora.org>
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_utils.c b/arch/arm/mach-msm/qdsp6v2/audio_utils.c
index 2e31ba0..65a2c54 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_utils.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_utils.c
@@ -42,19 +42,26 @@
 	int rc;
 
 	pr_debug("%s:session id %d: flush\n", __func__, audio->ac->session);
-	/* Implicitly issue a pause to the decoder before flushing */
-	rc = audio_in_pause(audio);
-	if (rc < 0) {
-		pr_err("%s:session id %d: pause cmd failed rc=%d\n", __func__,
-				audio->ac->session, rc);
-		return rc;
-	}
+	/* Flush if session running */
+	if (audio->enabled) {
+		/* Implicitly issue a pause to the encoder before flushing */
+		rc = audio_in_pause(audio);
+		if (rc < 0) {
+			pr_err("%s:session id %d: pause cmd failed rc=%d\n",
+				 __func__, audio->ac->session, rc);
+			return rc;
+		}
 
-	rc = q6asm_cmd(audio->ac, CMD_FLUSH);
-	if (rc < 0) {
-		pr_err("%s:session id %d: flush cmd failed rc=%d\n", __func__,
-				audio->ac->session, rc);
-		return rc;
+		rc = q6asm_cmd(audio->ac, CMD_FLUSH);
+		if (rc < 0) {
+			pr_err("%s:session id %d: flush cmd failed rc=%d\n",
+				__func__, audio->ac->session, rc);
+			return rc;
+		}
+		/* 2nd arg: 0 -> run immediately
+		   3rd arg: 0 -> msw_ts, 4th arg: 0 ->lsw_ts */
+		q6asm_run(audio->ac, 0x00, 0x00, 0x00);
+		pr_debug("Rerun the session\n");
 	}
 	audio->rflush = 1;
 	audio->wflush = 1;
@@ -75,6 +82,7 @@
 			audio->ac->session, atomic_read(&audio->in_samples));
 	atomic_set(&audio->in_bytes, 0);
 	atomic_set(&audio->in_samples, 0);
+	atomic_set(&audio->out_count, 0);
 	return 0;
 }
 
@@ -239,6 +247,12 @@
 		if (rc < 0)
 			pr_err("%s:session id %d: Flush Fail rc=%d\n",
 					__func__, audio->ac->session, rc);
+		else { /* Register back the flushed read buffer with DSP */
+			int cnt = 0;
+			while (cnt++ < audio->str_cfg.buffer_count)
+				q6asm_read(audio->ac); /* Push buffer to DSP */
+			pr_debug("register the read buffer\n");
+		}
 		break;
 	}
 	case AUDIO_PAUSE: {
@@ -555,6 +569,27 @@
 			rc = -EBUSY;
 			break;
 		}
+		/* if no PCM data, might have only eos buffer
+		   such case do not hold cpu buffer */
+		if ((buf == start) && (count == mfield_size)) {
+			char eos_buf[sizeof(struct meta_in)];
+			/* Processing begining of user buffer */
+			if (copy_from_user(eos_buf, buf, mfield_size)) {
+				rc = -EFAULT;
+				break;
+			}
+			/* Check if EOS flag is set and buffer has
+			 * contains just meta field
+			 */
+			extract_meta_info(eos_buf, &msw_ts, &lsw_ts,
+						&nflags);
+			buf += mfield_size;
+			/* send the EOS and return */
+			pr_debug("%s:session id %d: send EOS\
+				0x%8x\n", __func__,
+				audio->ac->session, nflags);
+			break;
+		}
 		data = (unsigned char *)q6asm_is_cpu_buf_avail(IN, audio->ac,
 						&size, &idx);
 		if (!data) {
@@ -576,13 +611,6 @@
 				extract_meta_info(cpy_ptr, &msw_ts, &lsw_ts,
 						&nflags);
 				buf += mfield_size;
-				if (count == mfield_size) {
-					/* send the EOS and return */
-					pr_debug("%s:session id %d: send EOS\
-						0x%8x\n", __func__,
-						audio->ac->session, nflags);
-					break;
-				}
 				count -= mfield_size;
 			} else {
 				pr_debug("%s:session id %d: continuous\