diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 20de0bcaa1372d86daff66b514e2484fa438633b..6cf76a41501e687826afffffb4dd655dddfc6b03 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -182,6 +182,12 @@ struct snd_soc_dai_ops { struct snd_soc_dai *); int (*trigger)(struct snd_pcm_substream *, int, struct snd_soc_dai *); + /* + * For hardware based FIFO caused delay reporting. + * Optional. + */ + snd_pcm_sframes_t (*delay)(struct snd_pcm_substream *, + struct snd_soc_dai *); }; /* diff --git a/include/sound/soc.h b/include/sound/soc.h index f792c1881b0a66874084a47962f60a2ef145475d..dbfec16015de1327b4f3ea4ec5b99c0e9be60a56 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -470,6 +470,13 @@ struct snd_soc_platform { struct snd_pcm *); void (*pcm_free)(struct snd_pcm *); + /* + * For platform caused delay reporting. + * Optional. + */ + snd_pcm_sframes_t (*delay)(struct snd_pcm_substream *, + struct snd_soc_dai *); + /* platform stream ops */ struct snd_pcm_ops *pcm_ops; }; diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index feb572c616cd0e89deb85672efaa599d9756b27e..4011ad3dc57a492d8519cb948e83eba445c73f4a 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -802,6 +802,8 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) /* * soc level wrapper for pointer callback + * If cpu_dai, codec_dai, platform driver has the delay callback, than + * the runtime->delay will be updated accordingly. */ static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream) { @@ -809,11 +811,27 @@ static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream) struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_card *card = socdev->card; struct snd_soc_platform *platform = card->platform; + struct snd_soc_dai_link *machine = rtd->dai; + struct snd_soc_dai *cpu_dai = machine->cpu_dai; + struct snd_soc_dai *codec_dai = machine->codec_dai; + struct snd_pcm_runtime *runtime = substream->runtime; snd_pcm_uframes_t offset = 0; + snd_pcm_sframes_t delay = 0; if (platform->pcm_ops->pointer) offset = platform->pcm_ops->pointer(substream); + if (cpu_dai->ops->delay) + delay += cpu_dai->ops->delay(substream, cpu_dai); + + if (codec_dai->ops->delay) + delay += codec_dai->ops->delay(substream, codec_dai); + + if (platform->delay) + delay += platform->delay(substream, codec_dai); + + runtime->delay = delay; + return offset; }