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 <chaithan@codeaurora.org>
Signed-off-by: Alexy Joseph <alexyj@codeaurora.org>
Signed-off-by: Banajit Goswami <bgoswami@codeaurora.org>
Signed-off-by: Meng Wang <mengw@codeaurora.org>
This commit is contained in:
Meng Wang 2019-12-06 09:48:09 +08:00
commit 7913e574a9
4 changed files with 68 additions and 0 deletions

View file

@ -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

View file

@ -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);

View file

@ -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);

View file

@ -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,