Skip to content

Commit 403f830

Browse files
morimotobroonie
authored andcommitted
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>
1 parent 8544f08 commit 403f830

3 files changed

Lines changed: 34 additions & 0 deletions

File tree

include/sound/soc-component.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,8 @@ struct snd_soc_component_driver {
148148
struct vm_area_struct *vma);
149149
int (*ack)(struct snd_soc_component *component,
150150
struct snd_pcm_substream *substream);
151+
snd_pcm_sframes_t (*delay)(struct snd_soc_component *component,
152+
struct snd_pcm_substream *substream);
151153

152154
const struct snd_compress_ops *compress_ops;
153155

@@ -505,5 +507,7 @@ int snd_soc_pcm_component_pm_runtime_get(struct snd_soc_pcm_runtime *rtd,
505507
void snd_soc_pcm_component_pm_runtime_put(struct snd_soc_pcm_runtime *rtd,
506508
void *stream, int rollback);
507509
int snd_soc_pcm_component_ack(struct snd_pcm_substream *substream);
510+
void snd_soc_pcm_component_delay(struct snd_pcm_substream *substream,
511+
snd_pcm_sframes_t *cpu_delay, snd_pcm_sframes_t *codec_delay);
508512

509513
#endif /* __SOC_COMPONENT_H */

sound/soc/soc-component.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -932,6 +932,34 @@ int snd_soc_pcm_component_pointer(struct snd_pcm_substream *substream)
932932
return 0;
933933
}
934934

935+
void snd_soc_pcm_component_delay(struct snd_pcm_substream *substream,
936+
snd_pcm_sframes_t *cpu_delay,
937+
snd_pcm_sframes_t *codec_delay)
938+
{
939+
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
940+
struct snd_soc_component *component;
941+
snd_pcm_sframes_t delay;
942+
int i;
943+
944+
/*
945+
* We're looking for the delay through the full audio path so it needs to
946+
* be the maximum of the Components doing transmit and the maximum of the
947+
* Components doing receive (ie, all CPUs and all CODECs) rather than
948+
* just the maximum of all Components.
949+
*/
950+
for_each_rtd_components(rtd, i, component) {
951+
if (!component->driver->delay)
952+
continue;
953+
954+
delay = component->driver->delay(component, substream);
955+
956+
if (snd_soc_component_is_codec(component))
957+
*codec_delay = max(*codec_delay, delay);
958+
else
959+
*cpu_delay = max(*cpu_delay, delay);
960+
}
961+
}
962+
935963
int snd_soc_pcm_component_ioctl(struct snd_pcm_substream *substream,
936964
unsigned int cmd, void *arg)
937965
{

sound/soc/soc-pcm.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1098,7 +1098,9 @@ static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream)
10981098
/* base delay if assigned in pointer callback */
10991099
delay = runtime->delay;
11001100

1101+
/* should be called *after* snd_soc_pcm_component_pointer() */
11011102
snd_soc_pcm_dai_delay(substream, &cpu_delay, &codec_delay);
1103+
snd_soc_pcm_component_delay(substream, &cpu_delay, &codec_delay);
11021104

11031105
runtime->delay = delay + cpu_delay + codec_delay;
11041106

0 commit comments

Comments
 (0)