Browse Source

ASoC: wm_adsp: Support streams which can start/stop with DSP active

Clear the buffer data structure on each trigger start such that the
buffer is in a sensible state even if the DSP itself didn't restart.
This is necessary to support voice control streams which can trigger
multiple times without reloading the firmware.

Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
Charles Keepax 7 years ago
parent
commit
61fc060c40
1 changed files with 18 additions and 10 deletions
  1. 18 10
      sound/soc/codecs/wm_adsp.c

+ 18 - 10
sound/soc/codecs/wm_adsp.c

@@ -3258,6 +3258,13 @@ static int wm_adsp_buffer_populate(struct wm_adsp_compr_buf *buf)
 	return 0;
 	return 0;
 }
 }
 
 
+static void wm_adsp_buffer_clear(struct wm_adsp_compr_buf *buf)
+{
+	buf->irq_count = 0xFFFFFFFF;
+	buf->read_index = -1;
+	buf->avail = 0;
+}
+
 static int wm_adsp_buffer_init(struct wm_adsp *dsp)
 static int wm_adsp_buffer_init(struct wm_adsp *dsp)
 {
 {
 	struct wm_adsp_compr_buf *buf;
 	struct wm_adsp_compr_buf *buf;
@@ -3268,8 +3275,8 @@ static int wm_adsp_buffer_init(struct wm_adsp *dsp)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
 	buf->dsp = dsp;
 	buf->dsp = dsp;
-	buf->read_index = -1;
-	buf->irq_count = 0xFFFFFFFF;
+
+	wm_adsp_buffer_clear(buf);
 
 
 	ret = wm_adsp_buffer_locate(buf);
 	ret = wm_adsp_buffer_locate(buf);
 	if (ret < 0) {
 	if (ret < 0) {
@@ -3327,16 +3334,17 @@ int wm_adsp_compr_trigger(struct snd_compr_stream *stream, int cmd)
 
 
 	switch (cmd) {
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
 	case SNDRV_PCM_TRIGGER_START:
-		if (wm_adsp_compr_attached(compr))
-			break;
-
-		ret = wm_adsp_compr_attach(compr);
-		if (ret < 0) {
-			adsp_err(dsp, "Failed to link buffer and stream: %d\n",
-				 ret);
-			break;
+		if (!wm_adsp_compr_attached(compr)) {
+			ret = wm_adsp_compr_attach(compr);
+			if (ret < 0) {
+				adsp_err(dsp, "Failed to link buffer and stream: %d\n",
+					 ret);
+				break;
+			}
 		}
 		}
 
 
+		wm_adsp_buffer_clear(compr->buf);
+
 		/* Trigger the IRQ at one fragment of data */
 		/* Trigger the IRQ at one fragment of data */
 		ret = wm_adsp_buffer_write(compr->buf,
 		ret = wm_adsp_buffer_write(compr->buf,
 					   HOST_BUFFER_FIELD(high_water_mark),
 					   HOST_BUFFER_FIELD(high_water_mark),