From 7913e574a96ef54a039353ad18c3c946777e0176 Mon Sep 17 00:00:00 2001 From: Meng Wang Date: Fri, 6 Dec 2019 09:48:09 +0800 Subject: [PATCH] ALSA: compress: Add support to send codec specific data Codec specific metadata is sent only for first stream in gapless playback. This causes incorrect configuration to be set for second stream and distortions are observed due to framedrops in adsp. Add support to send codec specific format during start of next stream in gapless using set_next_track_param. Change-Id: Ic0a9286c4fd8d17df63d676d6ce14cd394dea791 Signed-off-by: Chaithanya Krishna Bacharaju Signed-off-by: Alexy Joseph Signed-off-by: Banajit Goswami Signed-off-by: Meng Wang --- .../sound/designs/compress-offload.rst | 4 +++ include/sound/compress_driver.h | 6 ++++ sound/core/compress_offload.c | 26 +++++++++++++++ sound/soc/soc-compress.c | 32 +++++++++++++++++++ 4 files changed, 68 insertions(+) diff --git a/Documentation/sound/designs/compress-offload.rst b/Documentation/sound/designs/compress-offload.rst index ad4bfbdacc83..f4e5438033e0 100644 --- a/Documentation/sound/designs/compress-offload.rst +++ b/Documentation/sound/designs/compress-offload.rst @@ -183,6 +183,10 @@ partial drain EOF is reached and now DSP can start skipping padding delay. Also next write data would belong to next track +- set_next_track_param +This routine is called to send to DSP codec specific data of subsequent track +in gapless before first write. + Sequence flow for gapless would be: - Open - Get caps / codec caps diff --git a/include/sound/compress_driver.h b/include/sound/compress_driver.h index bc88d6f964da..631e8fd60a3f 100644 --- a/include/sound/compress_driver.h +++ b/include/sound/compress_driver.h @@ -85,6 +85,8 @@ struct snd_compr_stream { * @get_params: retrieve the codec parameters, mandatory * @set_metadata: Set the metadata values for a stream * @get_metadata: retrieves the requested metadata values from stream + * @set_next_track_param: send codec specific data of subsequent track + * in gapless * @trigger: Trigger operations like start, pause, resume, drain, stop. * This callback is mandatory * @pointer: Retrieve current h/w pointer information. Mandatory @@ -107,6 +109,10 @@ struct snd_compr_ops { struct snd_compr_metadata *metadata); int (*get_metadata)(struct snd_compr_stream *stream, struct snd_compr_metadata *metadata); +#ifdef CONFIG_AUDIO_QGKI + int (*set_next_track_param)(struct snd_compr_stream *stream, + union snd_codec_options *codec_options); +#endif int (*trigger)(struct snd_compr_stream *stream, int cmd); int (*pointer)(struct snd_compr_stream *stream, struct snd_compr_tstamp *tstamp); diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index 319e4a9af0c8..1daa2b79f8e1 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c @@ -901,6 +901,27 @@ static int snd_compr_partial_drain(struct snd_compr_stream *stream) return snd_compress_wait_for_drain(stream); } +#ifdef CONFIG_AUDIO_QGKI +static int snd_compr_set_next_track_param(struct snd_compr_stream *stream, + unsigned long arg) +{ + union snd_codec_options codec_options; + int retval; + + /* set next track params when stream is running or has been setup */ + if (stream->runtime->state != SNDRV_PCM_STATE_SETUP && + stream->runtime->state != SNDRV_PCM_STATE_RUNNING) + return -EPERM; + + if (copy_from_user(&codec_options, (void __user *)arg, + sizeof(codec_options))) + return -EFAULT; + + retval = stream->ops->set_next_track_param(stream, &codec_options); + return retval; +} +#endif + static long snd_compr_ioctl(struct file *f, unsigned int cmd, unsigned long arg) { struct snd_compr_file *data = f->private_data; @@ -965,6 +986,11 @@ static long snd_compr_ioctl(struct file *f, unsigned int cmd, unsigned long arg) case _IOC_NR(SNDRV_COMPRESS_NEXT_TRACK): retval = snd_compr_next_track(stream); break; +#ifdef CONFIG_AUDIO_QGKI + case _IOC_NR(SNDRV_COMPRESS_SET_NEXT_TRACK_PARAM): + retval = snd_compr_set_next_track_param(stream, arg); + break; +#endif } mutex_unlock(&stream->device->lock); diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 0677381a8ee7..38d507dd289a 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -755,6 +755,32 @@ static int soc_compr_copy(struct snd_compr_stream *cstream, return ret; } +#ifdef CONFIG_AUDIO_QGKI +static int soc_compr_set_next_track_param(struct snd_compr_stream *cstream, + union snd_codec_options *codec_options) +{ + struct snd_soc_pcm_runtime *rtd = cstream->private_data; + struct snd_soc_platform *component; + struct snd_soc_rtdcom_list *rtdcom; + int ret = 0; + + for_each_rtdcom(rtd, rtdcom) { + component = rtdcom->component; + + if (!component->driver->compr_ops || + component->driver->compr_ops->set_next_track_param) + continue; + + ret = component->driver->compr_ops->set_next_track_param( + cstream, codec_options); + if (ret < 0) + return ret; + } + + return 0; +} +#endif + static int soc_compr_set_metadata(struct snd_compr_stream *cstream, struct snd_compr_metadata *metadata) { @@ -822,6 +848,9 @@ static struct snd_compr_ops soc_compr_ops = { .set_params = soc_compr_set_params, .set_metadata = soc_compr_set_metadata, .get_metadata = soc_compr_get_metadata, +#ifdef CONFIG_AUDIO_QGKI + .set_next_track_param = soc_compr_set_next_track_param, +#endif .get_params = soc_compr_get_params, .trigger = soc_compr_trigger, .pointer = soc_compr_pointer, @@ -838,6 +867,9 @@ static struct snd_compr_ops soc_compr_dyn_ops = { .get_params = soc_compr_get_params, .set_metadata = soc_compr_set_metadata, .get_metadata = soc_compr_get_metadata, +#ifdef CONFIG_AUDIO_QGKI + .set_next_track_param = soc_compr_set_next_track_param, +#endif .trigger = soc_compr_trigger_fe, .pointer = soc_compr_pointer, .ack = soc_compr_ack,