]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - sound/soc/codecs/wm_adsp.c
Merge remote-tracking branches 'asoc/topic/arizona', 'asoc/topic/atmel', 'asoc/topic...
[karo-tx-linux.git] / sound / soc / codecs / wm_adsp.c
index a07bd7c2c587dd9d9d0135015b1aa4b578307e93..21fbe7d070635dd7235a53bdd25db4c472eb3cc8 100644 (file)
@@ -394,6 +394,7 @@ static const struct {
        int compr_direction;
        int num_caps;
        const struct wm_adsp_fw_caps *caps;
+       bool voice_trigger;
 } wm_adsp_fw[WM_ADSP_NUM_FW] = {
        [WM_ADSP_FW_MBC_VSS] =  { .file = "mbc-vss" },
        [WM_ADSP_FW_HIFI] =     { .file = "hifi" },
@@ -406,6 +407,7 @@ static const struct {
                .compr_direction = SND_COMPRESS_CAPTURE,
                .num_caps = ARRAY_SIZE(ctrl_caps),
                .caps = ctrl_caps,
+               .voice_trigger = true,
        },
        [WM_ADSP_FW_ASR] =      { .file = "asr" },
        [WM_ADSP_FW_TRACE] =    {
@@ -2366,13 +2368,15 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
                dsp->running = false;
 
                regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
-                                  ADSP2_SYS_ENA | ADSP2_CORE_ENA |
-                                  ADSP2_START, 0);
+                                  ADSP2_CORE_ENA | ADSP2_START, 0);
 
                /* Make sure DMAs are quiesced */
+               regmap_write(dsp->regmap, dsp->base + ADSP2_RDMA_CONFIG_1, 0);
                regmap_write(dsp->regmap, dsp->base + ADSP2_WDMA_CONFIG_1, 0);
                regmap_write(dsp->regmap, dsp->base + ADSP2_WDMA_CONFIG_2, 0);
-               regmap_write(dsp->regmap, dsp->base + ADSP2_RDMA_CONFIG_1, 0);
+
+               regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
+                                  ADSP2_SYS_ENA, 0);
 
                list_for_each_entry(ctl, &dsp->ctl_list, list)
                        ctl->enabled = 0;
@@ -2998,6 +3002,9 @@ int wm_adsp_compr_handle_irq(struct wm_adsp *dsp)
                goto out;
        }
 
+       if (wm_adsp_fw[dsp->fw].voice_trigger && buf->irq_count == 2)
+               ret = WM_ADSP_COMPR_VOICE_TRIGGER;
+
 out_notify:
        if (compr && compr->stream)
                snd_compr_fragment_elapsed(compr->stream);
@@ -3037,12 +3044,8 @@ int wm_adsp_compr_pointer(struct snd_compr_stream *stream,
 
        buf = compr->buf;
 
-       if (!compr->buf) {
-               ret = -ENXIO;
-               goto out;
-       }
-
-       if (compr->buf->error) {
+       if (!compr->buf || compr->buf->error) {
+               snd_compr_stop_error(stream, SNDRV_PCM_STATE_XRUN);
                ret = -EIO;
                goto out;
        }
@@ -3060,8 +3063,12 @@ int wm_adsp_compr_pointer(struct snd_compr_stream *stream,
                 */
                if (buf->avail < wm_adsp_compr_frag_words(compr)) {
                        ret = wm_adsp_buffer_get_error(buf);
-                       if (ret < 0)
+                       if (ret < 0) {
+                               if (compr->buf->error)
+                                       snd_compr_stop_error(stream,
+                                                       SNDRV_PCM_STATE_XRUN);
                                goto out;
+                       }
 
                        ret = wm_adsp_buffer_reenable_irq(buf);
                        if (ret < 0) {
@@ -3156,11 +3163,10 @@ static int wm_adsp_compr_read(struct wm_adsp_compr *compr,
 
        adsp_dbg(dsp, "Requested read of %zu bytes\n", count);
 
-       if (!compr->buf)
-               return -ENXIO;
-
-       if (compr->buf->error)
+       if (!compr->buf || compr->buf->error) {
+               snd_compr_stop_error(compr->stream, SNDRV_PCM_STATE_XRUN);
                return -EIO;
+       }
 
        count /= WM_ADSP_DATA_WORD_SIZE;