diff --git a/include/sound/pcm.h b/include/sound/pcm.h index 9576a47f2baf..b9863f650273 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -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, diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index 5d80b2eef525..0077f46710e5 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -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; diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 42f72c9b78ba..38a705dae4de 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -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) @@ -2460,6 +2497,30 @@ out: return ret; } +#ifdef CONFIG_AUDIO_QGKI +static int soc_pcm_compat_ioctl(struct snd_pcm_substream *substream, + unsigned int cmd, void *arg) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_component *component; + struct snd_soc_rtdcom_list *rtdcom; + + for_each_rtdcom(rtd, rtdcom) { + component = rtdcom->component; + + if (!component->driver->ops || + !component->driver->ops->compat_ioctl) + continue; + + /* FIXME: use 1st ioctl */ + return component->driver->ops->compat_ioctl( + substream, cmd, arg); + } + + return snd_pcm_lib_ioctl(substream, cmd, arg); +} +#endif + static int dpcm_run_update_shutdown(struct snd_soc_pcm_runtime *fe, int stream) { struct snd_pcm_substream *substream = @@ -2924,6 +2985,10 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) rtd->ops.close = dpcm_fe_dai_close; rtd->ops.pointer = soc_pcm_pointer; 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; rtd->ops.hw_params = soc_pcm_hw_params; @@ -2933,6 +2998,10 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) rtd->ops.close = soc_pcm_close; rtd->ops.pointer = soc_pcm_pointer; 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 } for_each_rtdcom(rtd, rtdcom) {