Merge "ASoC: msm: qdsp6v2: don't assume playback started"
diff --git a/sound/soc/msm/qdsp6v2/msm-multi-ch-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-multi-ch-pcm-q6-v2.c
index 4297ddb..39e6934 100644
--- a/sound/soc/msm/qdsp6v2/msm-multi-ch-pcm-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-multi-ch-pcm-q6-v2.c
@@ -141,7 +141,7 @@
 	}
 	case ASM_DATA_EVENT_RENDERED_EOS:
 		pr_debug("ASM_DATA_CMDRSP_EOS\n");
-		prtd->cmd_ack = 1;
+		clear_bit(CMD_EOS, &prtd->cmd_pending);
 		wake_up(&the_locks.eos_wait);
 		break;
 	case ASM_DATA_EVENT_READ_DONE_V2: {
@@ -241,7 +241,7 @@
 	atomic_set(&prtd->out_count, runtime->periods);
 
 	prtd->enabled = 1;
-	prtd->cmd_ack = 0;
+	prtd->cmd_pending = 0;
 	prtd->cmd_interrupt = 0;
 
 	return 0;
@@ -299,8 +299,12 @@
 		atomic_set(&prtd->start, 0);
 		if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
 			break;
-		prtd->cmd_ack = 0;
+		/* pending CMD_EOS isn't expected */
+		WARN_ON_ONCE(test_bit(CMD_EOS, &prtd->cmd_pending));
+		set_bit(CMD_EOS, &prtd->cmd_pending);
 		q6asm_cmd_nowait(prtd->audio_client, CMD_EOS);
+		if (ret)
+			clear_bit(CMD_EOS, &prtd->cmd_pending);
 		break;
 	case SNDRV_PCM_TRIGGER_SUSPEND:
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
@@ -379,9 +383,6 @@
 			prtd->audio_client->perf_mode,
 			prtd->session_id, substream->stream);
 
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-		prtd->cmd_ack = 1;
-
 	ret = snd_pcm_hw_constraint_list(runtime, 0,
 				SNDRV_PCM_HW_PARAM_RATE,
 				&constraints_sample_rates);
@@ -502,13 +503,15 @@
 	int dir = 0;
 	int ret = 0;
 
-	pr_debug("%s\n", __func__);
+	pr_debug("%s: cmd_pending 0x%lx\n", __func__, prtd->cmd_pending);
 
 	dir = IN;
 	ret = wait_event_timeout(the_locks.eos_wait,
-				prtd->cmd_ack, 5 * HZ);
+				 !test_bit(CMD_EOS, &prtd->cmd_pending),
+				 5 * HZ);
 	if (!ret)
-		pr_err("%s: CMD_EOS failed\n", __func__);
+		pr_err("%s: CMD_EOS failed, cmd_pending 0x%lx\n",
+		       __func__, prtd->cmd_pending);
 	q6asm_cmd(prtd->audio_client, CMD_CLOSE);
 	q6asm_audio_client_buf_free_contiguous(dir,
 				prtd->audio_client);
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
index 49bc488..11326f6 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
@@ -143,7 +143,7 @@
 	}
 	case ASM_DATA_EVENT_RENDERED_EOS:
 		pr_debug("ASM_DATA_EVENT_RENDERED_EOS\n");
-		prtd->cmd_ack = 1;
+		clear_bit(CMD_EOS, &prtd->cmd_pending);
 		wake_up(&the_locks.eos_wait);
 		break;
 	case ASM_DATA_EVENT_READ_DONE_V2: {
@@ -243,7 +243,7 @@
 	atomic_set(&prtd->out_count, runtime->periods);
 
 	prtd->enabled = 1;
-	prtd->cmd_ack = 0;
+	prtd->cmd_pending = 0;
 	prtd->cmd_interrupt = 0;
 
 	return 0;
@@ -312,8 +312,12 @@
 		atomic_set(&prtd->start, 0);
 		if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
 			break;
-		prtd->cmd_ack = 0;
+		/* pending CMD_EOS isn't expected */
+		WARN_ON_ONCE(test_bit(CMD_EOS, &prtd->cmd_pending));
+		set_bit(CMD_EOS, &prtd->cmd_pending);
 		ret = q6asm_cmd_nowait(prtd->audio_client, CMD_EOS);
+		if (ret)
+			clear_bit(CMD_EOS, &prtd->cmd_pending);
 		break;
 	case SNDRV_PCM_TRIGGER_SUSPEND:
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
@@ -473,14 +477,16 @@
 	int dir = 0;
 	int ret = 0;
 
-	pr_debug("%s\n", __func__);
+	pr_debug("%s: cmd_pending 0x%lx\n", __func__, prtd->cmd_pending);
 
 	if (prtd->audio_client) {
 		dir = IN;
 		ret = wait_event_timeout(the_locks.eos_wait,
-					prtd->cmd_ack, 5 * HZ);
+					 !test_bit(CMD_EOS, &prtd->cmd_pending),
+					 5 * HZ);
 		if (!ret)
-			pr_err("%s: CMD_EOS failed\n", __func__);
+			pr_err("%s: CMD_EOS failed, cmd_pending 0x%lx\n",
+			       __func__, prtd->cmd_pending);
 		q6asm_cmd(prtd->audio_client, CMD_CLOSE);
 		q6asm_audio_client_buf_free_contiguous(dir,
 					prtd->audio_client);
@@ -701,7 +707,6 @@
 		msm_pcm_routing_reg_phy_stream(soc_prtd->dai_link->be_id,
 				prtd->audio_client->perf_mode,
 				prtd->session_id, substream->stream);
-		prtd->cmd_ack = 1;
 	}
 
 	/* Capture Path */
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h
index f7719ed..5d5c995 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h
@@ -72,6 +72,13 @@
 	int enabled;
 	int close_ack;
 	int cmd_ack;
+	/*
+	 * cmd_ack doesn't tell if paticular command has been sent so can't
+	 * determine if it needs to wait for completion.
+	 * Use cmd_pending instead when checking whether a command is been
+	 * sent or not.
+	 */
+	unsigned long cmd_pending;
 	atomic_t start;
 	atomic_t stop;
 	atomic_t out_count;