ASoC: pcm: Add delay_blk feature

Add delay_blk() to pcm, platform and DAI ops.
The pcm delay_blk() op collects the audio DSP path
delays from the low-level drivers and sets the
runtime->delay field to their aggregate.

Change-Id: Ib7e10f44ab8ccb46dc2f5825081d0afef662d827
Signed-off-by: Kenneth Westfield <kwestfie@codeaurora.org>
This commit is contained in:
Kenneth Westfield 2015-05-19 12:03:55 -07:00 committed by David Keitel
parent 27c5547625
commit 579b5a9417
3 changed files with 35 additions and 1 deletions

View file

@ -80,10 +80,13 @@ struct snd_pcm_ops {
struct timespec *system_ts, struct timespec *audio_ts,
struct snd_pcm_audio_tstamp_config *audio_tstamp_config,
struct snd_pcm_audio_tstamp_report *audio_tstamp_report);
int (*delay_blk)(struct snd_pcm_substream *substream);
int (*wall_clock)(struct snd_pcm_substream *substream,
struct timespec *audio_ts);
int (*copy)(struct snd_pcm_substream *substream, int channel,
snd_pcm_uframes_t pos,
void __user *buf, snd_pcm_uframes_t count);
int (*silence)(struct snd_pcm_substream *substream, int channel,
int (*silence)(struct snd_pcm_substream *substream, int channel,
snd_pcm_uframes_t pos, snd_pcm_uframes_t count);
struct page *(*page)(struct snd_pcm_substream *substream,
unsigned long offset);

View file

@ -941,6 +941,16 @@ struct snd_soc_platform_driver {
snd_pcm_sframes_t (*delay)(struct snd_pcm_substream *,
struct snd_soc_dai *);
/*
* For platform-caused delay reporting, where the thread blocks waiting
* for the delay amount to be determined. Defining this will cause the
* ASoC core to skip calling the delay callbacks for all components in
* the runtime.
* Optional.
*/
snd_pcm_sframes_t (*delay_blk)(struct snd_pcm_substream *,
struct snd_soc_dai *);
/* platform stream pcm ops */
const struct snd_pcm_ops *ops;

View file

@ -1167,6 +1167,9 @@ static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream)
if (platform->driver->ops && platform->driver->ops->pointer)
offset = platform->driver->ops->pointer(substream);
if (platform->driver->delay_blk)
return offset;
if (cpu_dai->driver->ops && cpu_dai->driver->ops->delay)
delay += cpu_dai->driver->ops->delay(substream, cpu_dai);
@ -1191,6 +1194,22 @@ static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream)
return offset;
}
static int soc_pcm_delay_blk(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_platform *platform = rtd->platform;
struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_sframes_t delay = 0;
if (platform->driver->delay_blk)
delay = platform->driver->delay_blk(substream,
rtd->codec_dais[0]);
runtime->delay = delay;
return 0;
}
/* connect a FE and BE */
static int dpcm_be_connect(struct snd_soc_pcm_runtime *fe,
struct snd_soc_pcm_runtime *be, int stream)
@ -2722,6 +2741,7 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
rtd->ops.hw_free = dpcm_fe_dai_hw_free;
rtd->ops.close = dpcm_fe_dai_close;
rtd->ops.pointer = soc_pcm_pointer;
rtd->ops.delay_blk = soc_pcm_delay_blk;
rtd->ops.ioctl = soc_pcm_ioctl;
rtd->ops.compat_ioctl = soc_pcm_compat_ioctl;
} else {
@ -2732,6 +2752,7 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
rtd->ops.hw_free = soc_pcm_hw_free;
rtd->ops.close = soc_pcm_close;
rtd->ops.pointer = soc_pcm_pointer;
rtd->ops.delay_blk = soc_pcm_delay_blk;
rtd->ops.ioctl = soc_pcm_ioctl;
rtd->ops.compat_ioctl = soc_pcm_compat_ioctl;
}