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,