From 209a4825b3daa9dfc90c9f00b5d477189bf50649 Mon Sep 17 00:00:00 2001 From: Meng Wang Date: Thu, 7 Sep 2017 15:32:04 +0800 Subject: [PATCH] ANDROID: GKI: 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: Ieec6b2afedec156e47873efcad9b3571160b0a29 Signed-off-by: Chaithanya Krishna Bacharaju Signed-off-by: Alexy Joseph Signed-off-by: Banajit Goswami Signed-off-by: Meng Wang Bug: 151372815 (cherry picked from commit acff8e6a3c179c7f65a21d72508cd2df68ff5eae) Signed-off-by: Saravana Kannan --- .../sound/designs/compress-offload.rst | 6 +++++ include/sound/compress_driver.h | 4 ++++ include/uapi/sound/compress_offload.h | 4 ++++ sound/core/compress_offload.c | 23 ++++++++++++++++++ sound/soc/soc-compress.c | 24 +++++++++++++++++++ 5 files changed, 61 insertions(+) diff --git a/Documentation/sound/designs/compress-offload.rst b/Documentation/sound/designs/compress-offload.rst index ad4bfbdacc83..a29e4e632bf6 100644 --- a/Documentation/sound/designs/compress-offload.rst +++ b/Documentation/sound/designs/compress-offload.rst @@ -183,6 +183,11 @@ 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 @@ -194,6 +199,7 @@ Sequence flow for gapless would be: - Indicate next track data by sending set_next_track - Set metadata of the next track - then call partial_drain to flush most of buffer in DSP +- set codec specific data of subsequent track - Fill data of the next track - DSP switches to second track diff --git a/include/sound/compress_driver.h b/include/sound/compress_driver.h index f29c60bc1401..325c72ad8fda 100644 --- a/include/sound/compress_driver.h +++ b/include/sound/compress_driver.h @@ -84,6 +84,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 @@ -106,6 +108,8 @@ struct snd_compr_ops { struct snd_compr_metadata *metadata); int (*get_metadata)(struct snd_compr_stream *stream, struct snd_compr_metadata *metadata); + int (*set_next_track_param)(struct snd_compr_stream *stream, + union snd_codec_options *codec_options); int (*trigger)(struct snd_compr_stream *stream, int cmd); int (*pointer)(struct snd_compr_stream *stream, struct snd_compr_tstamp *tstamp); diff --git a/include/uapi/sound/compress_offload.h b/include/uapi/sound/compress_offload.h index 38cc30a37fcc..eac1e0166d26 100644 --- a/include/uapi/sound/compress_offload.h +++ b/include/uapi/sound/compress_offload.h @@ -172,6 +172,8 @@ struct snd_compr_metadata { * SNDRV_COMPRESS_STOP: stop a running stream, discarding ring buffer content * and the buffers currently with DSP * SNDRV_COMPRESS_DRAIN: Play till end of buffers and stop after that + * SNDRV_COMPRESS_SET_NEXT_TRACK_PARAM: send codec specific data for the next + * track in gapless * SNDRV_COMPRESS_IOCTL_VERSION: Query the API version */ #define SNDRV_COMPRESS_IOCTL_VERSION _IOR('C', 0x00, int) @@ -193,6 +195,8 @@ struct snd_compr_metadata { #define SNDRV_COMPRESS_DRAIN _IO('C', 0x34) #define SNDRV_COMPRESS_NEXT_TRACK _IO('C', 0x35) #define SNDRV_COMPRESS_PARTIAL_DRAIN _IO('C', 0x36) +#define SNDRV_COMPRESS_SET_NEXT_TRACK_PARAM\ + _IOW('C', 0x80, union snd_codec_options) /* * TODO * 1. add mmap support diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index 0716e88eef4d..1bf0397175c3 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c @@ -891,6 +891,25 @@ static int snd_compr_partial_drain(struct snd_compr_stream *stream) return snd_compress_wait_for_drain(stream); } +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; +} + static int snd_compress_simple_ioctls(struct file *file, struct snd_compr_stream *stream, unsigned int cmd, unsigned long arg) @@ -982,6 +1001,10 @@ static long snd_compr_ioctl(struct file *f, unsigned int cmd, unsigned long arg) retval = snd_compr_next_track(stream); break; + case _IOC_NR(SNDRV_COMPRESS_SET_NEXT_TRACK_PARAM): + retval = snd_compr_set_next_track_param(stream, arg); + break; + default: mutex_unlock(&stream->device->lock); return snd_compress_simple_ioctls(f, stream, cmd, arg); diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 409d082e80d1..4e6e9b6463b0 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -774,6 +774,28 @@ static int soc_compr_copy(struct snd_compr_stream *cstream, return ret; } +static int sst_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_component *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) + ret = + component->driver->compr_ops->set_next_track_param( + cstream, codec_options); + } + + return ret; +} + + static int soc_compr_set_metadata(struct snd_compr_stream *cstream, struct snd_compr_metadata *metadata) { @@ -840,6 +862,7 @@ static struct snd_compr_ops soc_compr_ops = { .free = soc_compr_free, .set_params = soc_compr_set_params, .set_metadata = soc_compr_set_metadata, + .set_next_track_param = sst_compr_set_next_track_param, .get_metadata = soc_compr_get_metadata, .get_params = soc_compr_get_params, .trigger = soc_compr_trigger, @@ -856,6 +879,7 @@ static struct snd_compr_ops soc_compr_dyn_ops = { .set_params = soc_compr_set_params_fe, .get_params = soc_compr_get_params, .set_metadata = soc_compr_set_metadata, + .set_next_track_param = sst_compr_set_next_track_param, .get_metadata = soc_compr_get_metadata, .trigger = soc_compr_trigger_fe, .pointer = soc_compr_pointer,