summaryrefslogtreecommitdiff
path: root/sound/soc
diff options
context:
space:
mode:
authorKuninori Morimoto <kuninori.morimoto.gx@renesas.com>2021-11-16 10:45:18 +0300
committerMark Brown <broonie@kernel.org>2021-11-29 15:19:41 +0300
commit403f830e7a0be5a9e33c7a9d208574f79887ec57 (patch)
tree422f4342f8e7e4fedbcf455f4dd72117fe3e9cb0 /sound/soc
parent8544f08c816292c2219f28c6eaa69236b978bfb9 (diff)
downloadlinux-403f830e7a0be5a9e33c7a9d208574f79887ec57.tar.xz
ASoC: soc-component: add snd_soc_pcm_component_delay()
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>
Diffstat (limited to 'sound/soc')
-rw-r--r--sound/soc/soc-component.c28
-rw-r--r--sound/soc/soc-pcm.c2
2 files changed, 30 insertions, 0 deletions
diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c
index c76ff9c59dfb..c0664f94990c 100644
--- a/sound/soc/soc-component.c
+++ b/sound/soc/soc-component.c
@@ -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)
{
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 82fd170e16af..493d231a2ffd 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -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;