]> www.infradead.org Git - users/hch/configfs.git/commitdiff
ASoC: meson: axg-tdm-interface: manage formatters in trigger
authorJerome Brunet <jbrunet@baylibre.com>
Fri, 26 Apr 2024 15:29:40 +0000 (17:29 +0200)
committerMark Brown <broonie@kernel.org>
Mon, 29 Apr 2024 14:48:49 +0000 (23:48 +0900)
So far, the formatters have been reset/enabled using the .prepare()
callback. This was done in this callback because walking the formatters use
a mutex. A mutex is used because formatter handling require dealing
possibly slow clock operation.

With the support of non-atomic, .trigger() callback may be used which also
allows to properly enable and disable formatters on start but also
pause/resume.

This solve a random shift on TDMIN as well repeated samples on for TDMOUT.

Fixes: d60e4f1e4be5 ("ASoC: meson: add tdm interface driver")
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
Link: https://lore.kernel.org/r/20240426152946.3078805-4-jbrunet@baylibre.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/meson/axg-tdm-interface.c

index bf708717635bf6531195a1039aee41c3166d8154..8bf3735dedaaf5c10b17bce5122edb1c366e6e9b 100644 (file)
@@ -349,26 +349,31 @@ static int axg_tdm_iface_hw_params(struct snd_pcm_substream *substream,
        return 0;
 }
 
-static int axg_tdm_iface_hw_free(struct snd_pcm_substream *substream,
+static int axg_tdm_iface_trigger(struct snd_pcm_substream *substream,
+                                int cmd,
                                 struct snd_soc_dai *dai)
 {
-       struct axg_tdm_stream *ts = snd_soc_dai_get_dma_data(dai, substream);
+       struct axg_tdm_stream *ts =
+               snd_soc_dai_get_dma_data(dai, substream);
 
-       /* Stop all attached formatters */
-       axg_tdm_stream_stop(ts);
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+       case SNDRV_PCM_TRIGGER_RESUME:
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+               axg_tdm_stream_start(ts);
+               break;
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+       case SNDRV_PCM_TRIGGER_STOP:
+               axg_tdm_stream_stop(ts);
+               break;
+       default:
+               return -EINVAL;
+       }
 
        return 0;
 }
 
-static int axg_tdm_iface_prepare(struct snd_pcm_substream *substream,
-                                struct snd_soc_dai *dai)
-{
-       struct axg_tdm_stream *ts = snd_soc_dai_get_dma_data(dai, substream);
-
-       /* Force all attached formatters to update */
-       return axg_tdm_stream_reset(ts);
-}
-
 static int axg_tdm_iface_remove_dai(struct snd_soc_dai *dai)
 {
        int stream;
@@ -412,8 +417,7 @@ static const struct snd_soc_dai_ops axg_tdm_iface_ops = {
        .set_fmt        = axg_tdm_iface_set_fmt,
        .startup        = axg_tdm_iface_startup,
        .hw_params      = axg_tdm_iface_hw_params,
-       .prepare        = axg_tdm_iface_prepare,
-       .hw_free        = axg_tdm_iface_hw_free,
+       .trigger        = axg_tdm_iface_trigger,
 };
 
 /* TDM Backend DAIs */