ASoC: soc-component: add snd_soc_pcm_component_delay()
authorKuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Tue, 16 Nov 2021 07:45:18 +0000 (16:45 +0900)
committerMark Brown <broonie@kernel.org>
Mon, 29 Nov 2021 12:19:41 +0000 (12:19 +0000)
Current soc-pcm.c :: soc_pcm_pointer() is assuming that
component driver might update runtime->delay silently in
snd_soc_pcm_component_pointer() (= A).

static snd_pcm_uframes_t soc_pcm_pointer(...)
{
...

/* clearing the previous total delay */
=> runtime->delay = 0;

(A) offset = snd_soc_pcm_component_pointer(substream);

/* base delay if assigned in pointer callback */
=> delay = runtime->delay;
...
}

1) The behavior that ".pointer callback secretly updates
   runtime->delay" is strange and confusable.

2) Current snd_soc_pcm_component_pointer() uses 1st found component's
   .pointer callback only, thus it is no problem for now.
   But runtime->delay might be overwrote if it adjusted to multiple
   components in the future.

3) Component delay is updated at .pointer callback timing (secretly).
   But some components which doesn't have .pointer callback might want
   to increase runtime->delay for some reasons.

We already have .delay function for DAI, but not have for Component.
This patch adds new snd_soc_pcm_component_delay() for it.

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Link: https://lore.kernel.org/r/874k8cy25t.wl-kuninori.morimoto.gx@renesas.com
Signed-off-by: Mark Brown <broonie@kernel.org>
include/sound/soc-component.h
sound/soc/soc-component.c
sound/soc/soc-pcm.c

index a4317144ab627d652296e963b82c2718580e736f..a52080407b98c539760f3823cc2a3c0f1765de90 100644 (file)
@@ -148,6 +148,8 @@ struct snd_soc_component_driver {
                    struct vm_area_struct *vma);
        int (*ack)(struct snd_soc_component *component,
                   struct snd_pcm_substream *substream);
+       snd_pcm_sframes_t (*delay)(struct snd_soc_component *component,
+                                  struct snd_pcm_substream *substream);
 
        const struct snd_compress_ops *compress_ops;
 
@@ -505,5 +507,7 @@ int snd_soc_pcm_component_pm_runtime_get(struct snd_soc_pcm_runtime *rtd,
 void snd_soc_pcm_component_pm_runtime_put(struct snd_soc_pcm_runtime *rtd,
                                          void *stream, int rollback);
 int snd_soc_pcm_component_ack(struct snd_pcm_substream *substream);
+void snd_soc_pcm_component_delay(struct snd_pcm_substream *substream,
+                                snd_pcm_sframes_t *cpu_delay, snd_pcm_sframes_t *codec_delay);
 
 #endif /* __SOC_COMPONENT_H */
index c76ff9c59dfb9662c8c13b594b0c4c7e8b5c36ac..c0664f94990c8eb5e2408908d9538dbbbef6c6b1 100644 (file)
@@ -932,6 +932,34 @@ int snd_soc_pcm_component_pointer(struct snd_pcm_substream *substream)
        return 0;
 }
 
+void snd_soc_pcm_component_delay(struct snd_pcm_substream *substream,
+                                snd_pcm_sframes_t *cpu_delay,
+                                snd_pcm_sframes_t *codec_delay)
+{
+       struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
+       struct snd_soc_component *component;
+       snd_pcm_sframes_t delay;
+       int i;
+
+       /*
+        * We're looking for the delay through the full audio path so it needs to
+        * be the maximum of the Components doing transmit and the maximum of the
+        * Components doing receive (ie, all CPUs and all CODECs) rather than
+        * just the maximum of all Components.
+        */
+       for_each_rtd_components(rtd, i, component) {
+               if (!component->driver->delay)
+                       continue;
+
+               delay = component->driver->delay(component, substream);
+
+               if (snd_soc_component_is_codec(component))
+                       *codec_delay = max(*codec_delay, delay);
+               else
+                       *cpu_delay = max(*cpu_delay, delay);
+       }
+}
+
 int snd_soc_pcm_component_ioctl(struct snd_pcm_substream *substream,
                                unsigned int cmd, void *arg)
 {
index 82fd170e16afa974e9d6f5a6ad23f7b2e1054266..493d231a2ffdc90f554c3dbd54a893434e065562 100644 (file)
@@ -1098,7 +1098,9 @@ static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream)
        /* base delay if assigned in pointer callback */
        delay = runtime->delay;
 
+       /* should be called *after* snd_soc_pcm_component_pointer() */
        snd_soc_pcm_dai_delay(substream, &cpu_delay, &codec_delay);
+       snd_soc_pcm_component_delay(substream, &cpu_delay, &codec_delay);
 
        runtime->delay = delay + cpu_delay + codec_delay;