Merge "ASoC: msm: Disable gapless offload playback by default"
This commit is contained in:
commit
850e5020fd
|
@ -67,6 +67,7 @@ struct msm_compr_gapless_state {
|
|||
uint32_t initial_samples_drop;
|
||||
uint32_t trailing_samples_drop;
|
||||
uint32_t gapless_transition;
|
||||
bool use_dsp_gapless_mode;
|
||||
};
|
||||
|
||||
struct msm_compr_pdata {
|
||||
|
@ -74,6 +75,7 @@ struct msm_compr_pdata {
|
|||
struct snd_compr_stream *cstream[MSM_FRONTEND_DAI_MAX];
|
||||
uint32_t volume[MSM_FRONTEND_DAI_MAX][2]; /* For both L & R */
|
||||
struct msm_compr_audio_effects *audio_effects[MSM_FRONTEND_DAI_MAX];
|
||||
bool use_dsp_gapless_mode;
|
||||
};
|
||||
|
||||
struct msm_compr_audio {
|
||||
|
@ -175,7 +177,7 @@ static int msm_compr_send_buffer(struct msm_compr_audio *prtd)
|
|||
|
||||
pr_debug("%s: bytes_received = %d copied_total = %d\n",
|
||||
__func__, prtd->bytes_received, prtd->copied_total);
|
||||
if (prtd->first_buffer)
|
||||
if (prtd->first_buffer && prtd->gapless_state.use_dsp_gapless_mode)
|
||||
q6asm_send_meta_data(prtd->audio_client,
|
||||
prtd->gapless_state.initial_samples_drop,
|
||||
prtd->gapless_state.trailing_samples_drop);
|
||||
|
@ -449,7 +451,8 @@ static int msm_compr_configure_dsp(struct snd_compr_stream *cstream)
|
|||
pr_debug("%s\n", __func__);
|
||||
ret = q6asm_stream_open_write_v2(ac,
|
||||
prtd->codec, bits_per_sample,
|
||||
ac->stream_id, true/*gapless*/);
|
||||
ac->stream_id,
|
||||
prtd->gapless_state.use_dsp_gapless_mode);
|
||||
if (ret < 0) {
|
||||
pr_err("%s: Session out open failed\n", __func__);
|
||||
return -ENOMEM;
|
||||
|
@ -558,6 +561,13 @@ static int msm_compr_open(struct snd_compr_stream *cstream)
|
|||
prtd->first_buffer = 1;
|
||||
prtd->partial_drain_delay = 0;
|
||||
memset(&prtd->gapless_state, 0, sizeof(struct msm_compr_gapless_state));
|
||||
/*
|
||||
* Update the use_dsp_gapless_mode from gapless struture with the value
|
||||
* part of platform data.
|
||||
*/
|
||||
prtd->gapless_state.use_dsp_gapless_mode = pdata->use_dsp_gapless_mode;
|
||||
|
||||
pr_debug("%s: gapless mode %d", __func__, pdata->use_dsp_gapless_mode);
|
||||
|
||||
spin_lock_init(&prtd->lock);
|
||||
|
||||
|
@ -872,6 +882,10 @@ static int msm_compr_trigger(struct snd_compr_stream *cstream, int cmd)
|
|||
break;
|
||||
case SND_COMPR_TRIGGER_PARTIAL_DRAIN:
|
||||
pr_debug("%s: SND_COMPR_TRIGGER_PARTIAL_DRAIN\n", __func__);
|
||||
if (!prtd->gapless_state.use_dsp_gapless_mode) {
|
||||
pr_debug("%s: set partial drain as drain\n", __func__);
|
||||
cmd = SND_COMPR_TRIGGER_DRAIN;
|
||||
}
|
||||
case SND_COMPR_TRIGGER_DRAIN:
|
||||
pr_debug("%s: SNDRV_COMPRESS_DRAIN\n", __func__);
|
||||
/* Make sure all the data is sent to DSP before sending EOS */
|
||||
|
@ -919,6 +933,7 @@ static int msm_compr_trigger(struct snd_compr_stream *cstream, int cmd)
|
|||
if ((cmd == SND_COMPR_TRIGGER_PARTIAL_DRAIN) &&
|
||||
(prtd->gapless_state.set_next_stream_id)) {
|
||||
/* wait for the last buffer to be returned */
|
||||
|
||||
if (prtd->last_buffer) {
|
||||
pr_debug("%s: last buffer drain\n", __func__);
|
||||
rc = msm_compr_drain_buffer(prtd, &flags);
|
||||
|
@ -1019,7 +1034,7 @@ static int msm_compr_trigger(struct snd_compr_stream *cstream, int cmd)
|
|||
rc = -EINTR;
|
||||
|
||||
/*FIXME : what if a flush comes while PC is here */
|
||||
if (rc == 0 && (cmd == SND_COMPR_TRIGGER_PARTIAL_DRAIN)) {
|
||||
if (rc == 0) {
|
||||
/*
|
||||
* Failed to open second stream in DSP for gapless
|
||||
* so prepare the current stream in session
|
||||
|
@ -1049,12 +1064,18 @@ static int msm_compr_trigger(struct snd_compr_stream *cstream, int cmd)
|
|||
prtd->first_buffer = 1;
|
||||
prtd->last_buffer = 0;
|
||||
atomic_set(&prtd->drain, 0);
|
||||
atomic_set(&prtd->xrun, 1);
|
||||
q6asm_run_nowait(prtd->audio_client, 0, 0, 0);
|
||||
spin_unlock_irqrestore(&prtd->lock, flags);
|
||||
}
|
||||
prtd->cmd_interrupt = 0;
|
||||
break;
|
||||
case SND_COMPR_TRIGGER_NEXT_TRACK:
|
||||
if (!prtd->gapless_state.use_dsp_gapless_mode) {
|
||||
pr_debug("%s: ignore trigger next track\n", __func__);
|
||||
rc = 0;
|
||||
break;
|
||||
}
|
||||
pr_debug("%s: SND_COMPR_TRIGGER_NEXT_TRACK\n", __func__);
|
||||
spin_lock_irqsave(&prtd->lock, flags);
|
||||
rc = 0;
|
||||
|
@ -1066,9 +1087,9 @@ static int msm_compr_trigger(struct snd_compr_stream *cstream, int cmd)
|
|||
}
|
||||
spin_unlock_irqrestore(&prtd->lock, flags);
|
||||
rc = q6asm_stream_open_write_v2(prtd->audio_client,
|
||||
prtd->codec, 16,
|
||||
stream_id,
|
||||
true /*gapless*/);
|
||||
prtd->codec, 16,
|
||||
stream_id,
|
||||
prtd->gapless_state.use_dsp_gapless_mode);
|
||||
if (rc < 0) {
|
||||
pr_err("%s: Session out open failed for gapless\n",
|
||||
__func__);
|
||||
|
@ -1323,7 +1344,6 @@ static int msm_compr_set_metadata(struct snd_compr_stream *cstream,
|
|||
prtd = cstream->runtime->private_data;
|
||||
if (!prtd && !prtd->audio_client)
|
||||
return -EINVAL;
|
||||
|
||||
ac = prtd->audio_client;
|
||||
if (metadata->key == SNDRV_COMPRESS_ENCODER_PADDING) {
|
||||
pr_debug("%s, got encoder padding %u", __func__, metadata->value[0]);
|
||||
|
@ -1479,6 +1499,13 @@ static int msm_compr_probe(struct snd_soc_platform *platform)
|
|||
pdata->cstream[i] = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* use_dsp_gapless_mode part of platform data(pdata) is updated from HAL
|
||||
* through a mixer control before compress driver is opened. The mixer
|
||||
* control is used to decide if dsp gapless mode needs to be enabled.
|
||||
* Gapless is disabled by default.
|
||||
*/
|
||||
pdata->use_dsp_gapless_mode = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1588,7 +1615,7 @@ static int msm_compr_add_audio_effects_control(struct snd_soc_pcm_runtime *rtd)
|
|||
|
||||
fe_audio_effects_config_control[0].name = mixer_str;
|
||||
fe_audio_effects_config_control[0].private_value = rtd->dai_link->be_id;
|
||||
pr_debug("Registering new mixer ctl %s", mixer_str);
|
||||
pr_debug("Registering new mixer ctl %s\n", mixer_str);
|
||||
snd_soc_add_platform_controls(rtd->platform,
|
||||
fe_audio_effects_config_control,
|
||||
ARRAY_SIZE(fe_audio_effects_config_control));
|
||||
|
@ -1596,6 +1623,38 @@ static int msm_compr_add_audio_effects_control(struct snd_soc_pcm_runtime *rtd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int msm_compr_gapless_put(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_platform *platform = snd_kcontrol_chip(kcontrol);
|
||||
struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
|
||||
snd_soc_platform_get_drvdata(platform);
|
||||
pdata->use_dsp_gapless_mode = ucontrol->value.integer.value[0];
|
||||
pr_debug("%s: value: %ld\n", __func__,
|
||||
ucontrol->value.integer.value[0]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int msm_compr_gapless_get(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct snd_soc_platform *platform = snd_kcontrol_chip(kcontrol);
|
||||
struct msm_compr_pdata *pdata =
|
||||
snd_soc_platform_get_drvdata(platform);
|
||||
pr_debug("%s:gapless mode %d\n", __func__, pdata->use_dsp_gapless_mode);
|
||||
ucontrol->value.integer.value[0] = pdata->use_dsp_gapless_mode;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_kcontrol_new msm_compr_gapless_controls[] = {
|
||||
SOC_SINGLE_EXT("Compress Gapless Playback",
|
||||
0, 0, 1, 0,
|
||||
msm_compr_gapless_get,
|
||||
msm_compr_gapless_put),
|
||||
};
|
||||
|
||||
static int msm_compr_new(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
int rc;
|
||||
|
@ -1626,7 +1685,10 @@ static struct snd_compr_ops msm_compr_ops = {
|
|||
static struct snd_soc_platform_driver msm_soc_platform = {
|
||||
.probe = msm_compr_probe,
|
||||
.compr_ops = &msm_compr_ops,
|
||||
.pcm_new = msm_compr_new,
|
||||
.pcm_new = msm_compr_new,
|
||||
.controls = msm_compr_gapless_controls,
|
||||
.num_controls = ARRAY_SIZE(msm_compr_gapless_controls),
|
||||
|
||||
};
|
||||
|
||||
static int msm_compr_dev_probe(struct platform_device *pdev)
|
||||
|
|
Loading…
Reference in New Issue