ASoC: wm_adsp: Support streams which can start/stop with DSP active
authorCharles Keepax <ckeepax@opensource.cirrus.com>
Mon, 26 Feb 2018 10:49:47 +0000 (10:49 +0000)
committerMark Brown <broonie@kernel.org>
Mon, 26 Feb 2018 10:53:41 +0000 (10:53 +0000)
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>
sound/soc/codecs/wm_adsp.c

index 0060aeb..ab91f13 100644 (file)
@@ -3258,6 +3258,13 @@ static int wm_adsp_buffer_populate(struct wm_adsp_compr_buf *buf)
        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)
 {
        struct wm_adsp_compr_buf *buf;
@@ -3268,8 +3275,8 @@ static int wm_adsp_buffer_init(struct wm_adsp *dsp)
                return -ENOMEM;
 
        buf->dsp = dsp;
-       buf->read_index = -1;
-       buf->irq_count = 0xFFFFFFFF;
+
+       wm_adsp_buffer_clear(buf);
 
        ret = wm_adsp_buffer_locate(buf);
        if (ret < 0) {
@@ -3327,16 +3334,17 @@ int wm_adsp_compr_trigger(struct snd_compr_stream *stream, int cmd)
 
        switch (cmd) {
        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 */
                ret = wm_adsp_buffer_write(compr->buf,
                                           HOST_BUFFER_FIELD(high_water_mark),