SoC: pcm: Add delay_blk feature

Add delay_blk() to pcm, platform and DAI ops.
The pcm delay_blk() op collects the audio DSP path
delay 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>
Signed-off-by: Meng Wang <mwang@codeaurora.org>
This commit is contained in:
Meng Wang 2017-09-07 15:15:08 +08:00 • committed by Meng Wang
commit d1eb1c2845
3 changed files with 55 additions and 1 deletions

View file

@ -64,6 +64,11 @@ 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);
#ifdef CONFIG_AUDIO_QGKI
int (*delay_blk)(struct snd_pcm_substream *substream);
int (*wall_clock)(struct snd_pcm_substream *substream,
struct timespec *audio_ts);
#endif
int (*fill_silence)(struct snd_pcm_substream *substream, int channel,
unsigned long pos, unsigned long bytes);
int (*copy_user)(struct snd_pcm_substream *substream, int channel,

View file

@ -73,7 +73,17 @@ struct snd_soc_component_driver {
int (*stream_event)(struct snd_soc_component *component, int event);
int (*set_bias_level)(struct snd_soc_component *component,
enum snd_soc_bias_level level);
#ifdef CONFIG_AUDIO_QGKI
/*
* 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 *substream,
struct snd_soc_dai *dai);
#endif
const struct snd_pcm_ops *ops;
const struct snd_compr_ops *compr_ops;

View file

@ -1113,6 +1113,10 @@ static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream)
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
struct snd_soc_dai *codec_dai;
#ifdef CONFIG_AUDIO_QGKI
struct snd_soc_component *component;
struct snd_soc_rtdcom_list *rtdcom;
#endif
struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_uframes_t offset = 0;
snd_pcm_sframes_t delay = 0;
@ -1123,7 +1127,18 @@ static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream)
runtime->delay = 0;
offset = snd_soc_pcm_component_pointer(substream);
#ifdef CONFIG_AUDIO_QGKI
for_each_rtdcom(rtd, rtdcom) {
component = rtdcom->component;
if (!component->driver->ops ||
!component->driver->ops->pointer)
continue;
if (component->driver->delay_blk)
return offset;
}
#endif
/* base delay if assigned in pointer callback */
delay = runtime->delay;
@ -1140,6 +1155,28 @@ static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream)
return offset;
}
#ifdef CONFIG_AUDIO_QGKI
static int soc_pcm_delay_blk(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_component *component;
struct snd_soc_rtdcom_list *rtdcom;
struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_sframes_t delay = 0;
for_each_rtdcom(rtd, rtdcom) {
component = rtdcom->component;
if (component->driver->delay_blk)
delay = component->driver->delay_blk(substream,
rtd->codec_dais[0]);
}
runtime->delay = delay;
return 0;
}
#endif
/* connect a FE and BE */
static int dpcm_be_connect(struct snd_soc_pcm_runtime *fe,
struct snd_soc_pcm_runtime *be, int stream)
@ -2950,6 +2987,7 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
rtd->ops.ioctl = snd_soc_pcm_component_ioctl;
#ifdef CONFIG_AUDIO_QGKI
rtd->ops.compat_ioctl = soc_pcm_compat_ioctl;
rtd->ops.delay_blk = soc_pcm_delay_blk;
#endif
} else {
rtd->ops.open = soc_pcm_open;
@ -2962,6 +3000,7 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
rtd->ops.ioctl = snd_soc_pcm_component_ioctl;
#ifdef CONFIG_AUDIO_QGKI
rtd->ops.compat_ioctl = soc_pcm_compat_ioctl;
rtd->ops.delay_blk = soc_pcm_delay_blk;
#endif
}