From 6a3202ea03cba8b987a77ed4ec0010121c01dc03 Mon Sep 17 00:00:00 2001 From: Ravindra Lokhande Date: Tue, 6 May 2014 19:33:11 +0530 Subject: ASoC: Tegra: Fix concurrent pcm and compress playback - Added path between BE and codec stream - use atomic reference count Bug 1495249 Change-Id: I895d22e1854c53f41362ed2a1cff63d88feb397b Signed-off-by: Ravindra Lokhande Reviewed-on: http://git-master/r/405859 Reviewed-by: Riham Haidar Tested-by: Riham Haidar --- sound/soc/tegra/tegra30_avp.c | 61 +++++++++++++++++++++-------------------- sound/soc/tegra/tegra_offload.c | 12 ++------ sound/soc/tegra/tegra_rt5639.c | 6 ++-- 3 files changed, 38 insertions(+), 41 deletions(-) (limited to 'sound') diff --git a/sound/soc/tegra/tegra30_avp.c b/sound/soc/tegra/tegra30_avp.c index e15b66bcff24..f18952dd714a 100644 --- a/sound/soc/tegra/tegra30_avp.c +++ b/sound/soc/tegra/tegra30_avp.c @@ -105,8 +105,8 @@ struct tegra30_avp_audio_dma { struct dma_slave_config chan_slave_config; dma_cookie_t chan_cookie; - int use_count; - int active_count; + atomic_t is_dma_allocated; + atomic_t active_count; }; struct tegra30_avp_stream { @@ -141,7 +141,7 @@ struct tegra30_avp_audio { unsigned int *cmd_buf; int cmd_buf_idx; - int stream_active_count; + atomic_t stream_active_count; struct tegra30_avp_audio_dma audio_dma; spinlock_t lock; }; @@ -438,11 +438,10 @@ static int tegra30_avp_audio_alloc_dma(struct tegra_offload_dma_params *params) dma_cap_mask_t mask; int ret = 0; - dev_vdbg(audio_avp->dev, "%s : use %d", - __func__, dma->use_count); + dev_vdbg(audio_avp->dev, "%s: is_dma_allocated %d", + __func__, atomic_read(&dma->is_dma_allocated)); - dma->use_count++; - if (dma->use_count > 1) + if (atomic_read(&dma->is_dma_allocated) == 1) return 0; memcpy(&dma->params, params, sizeof(struct tegra_offload_dma_params)); @@ -469,6 +468,8 @@ static int tegra30_avp_audio_alloc_dma(struct tegra_offload_dma_params *params) return ret; } audio_engine->apb_channel_handle = dma->chan->chan_id; + atomic_set(&dma->is_dma_allocated, 1); + return 0; } @@ -477,17 +478,15 @@ static void tegra30_avp_audio_free_dma(void) struct tegra30_avp_audio *audio_avp = avp_audio_ctx; struct tegra30_avp_audio_dma *dma = &audio_avp->audio_dma; - dev_vdbg(audio_avp->dev, "%s : use %d", - __func__, dma->use_count); - - if (dma->use_count <= 0) - return; + dev_vdbg(audio_avp->dev, "%s: is_dma_allocated %d", + __func__, atomic_read(&dma->is_dma_allocated)); - dma->use_count--; - if (dma->use_count) - return; + if (atomic_read(&dma->is_dma_allocated) == 1) { + dma_release_channel(dma->chan); + atomic_set(&dma->is_dma_allocated, 0); + } - dma_release_channel(dma->chan); + return; } static int tegra30_avp_audio_start_dma(void) @@ -496,10 +495,10 @@ static int tegra30_avp_audio_start_dma(void) struct tegra30_avp_audio_dma *dma = &audio_avp->audio_dma; struct audio_engine_data *audio_engine = audio_avp->audio_engine; - dev_vdbg(audio_avp->dev, "%s: active %d.", __func__, dma->active_count); + dev_vdbg(audio_avp->dev, "%s: active %d", __func__, + atomic_read(&dma->active_count)); - dma->active_count++; - if (dma->active_count > 1) + if (atomic_inc_return(&dma->active_count) > 1) return 0; dma->chan_desc = dmaengine_prep_dma_cyclic(dma->chan, @@ -522,14 +521,12 @@ static int tegra30_avp_audio_stop_dma(void) struct tegra30_avp_audio *audio_avp = avp_audio_ctx; struct tegra30_avp_audio_dma *dma = &audio_avp->audio_dma; - dev_vdbg(audio_avp->dev, "%s : active %d", - __func__, dma->active_count); + dev_vdbg(audio_avp->dev, "%s: active %d.", __func__, + atomic_read(&dma->active_count)); - dma->active_count--; - if (dma->active_count > 0) - return 0; + if (atomic_dec_and_test(&dma->active_count)) + dmaengine_terminate_all(dma->chan); - dmaengine_terminate_all(dma->chan); return 0; } @@ -765,8 +762,11 @@ static int tegra30_avp_pcm_open(int *id) return -EBUSY; } - audio_avp->stream_active_count++; + audio_engine->stream[*id].stream_allocated = 1; + + atomic_inc(&audio_avp->stream_active_count); tegra30_avp_audio_set_state(KSSTATE_RUN); + return 0; } @@ -917,8 +917,9 @@ static int tegra30_avp_compr_open(int *id) } audio_avp->avp_stream[*id].is_drain_called = 0; - audio_avp->stream_active_count++; + atomic_inc(&audio_avp->stream_active_count); tegra30_avp_audio_set_state(KSSTATE_RUN); + return 0; } @@ -1255,13 +1256,13 @@ static void tegra30_avp_stream_close(int id) return; } tegra30_avp_mem_free(&avp_stream->source_buf); - tegra30_avp_audio_free_dma(); stream->stream_allocated = 0; tegra30_avp_stream_set_state(id, KSSTATE_STOP); - audio_avp->stream_active_count--; - if (!(audio_avp->stream_active_count)) + if (atomic_dec_and_test(&audio_avp->stream_active_count)) { + tegra30_avp_audio_free_dma(); tegra30_avp_audio_set_state(KSSTATE_STOP); + } } static struct tegra_offload_ops avp_audio_platform = { diff --git a/sound/soc/tegra/tegra_offload.c b/sound/soc/tegra/tegra_offload.c index 3940f42c44ea..fbe766e4342c 100644 --- a/sound/soc/tegra/tegra_offload.c +++ b/sound/soc/tegra/tegra_offload.c @@ -416,7 +416,7 @@ static int tegra_offload_pcm_open(struct snd_pcm_substream *substream) data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); if (!data) { - dev_vdbg(dev, "Failed to allocate tegra_offload_pcm_data."); + dev_err(dev, "Failed to allocate tegra_offload_pcm_data."); return -ENOMEM; } @@ -579,12 +579,6 @@ static int tegra_offload_pcm_ack(struct snd_pcm_substream *substream) static const struct snd_soc_dapm_widget tegra_offload_widgets[] = { - /* FrontEnd DAIs */ - SND_SOC_DAPM_AIF_IN("offload-pcm-playback", "pcm-playback", 0, - 0/*wreg*/, 0/*wshift*/, 0/*winvert*/), - SND_SOC_DAPM_AIF_IN("offload-compr-playback", "compr-playback", 0, - 0/*wreg*/, 0/*wshift*/, 0/*winvert*/), - /* BackEnd DAIs */ SND_SOC_DAPM_AIF_OUT("I2S0_OUT", "tegra30-i2s.0 Playback", 0, 0/*wreg*/, 0/*wshift*/, 0/*winvert*/), @@ -718,7 +712,7 @@ static struct snd_soc_dai_driver tegra_offload_dai[] = { .name = "tegra-offload-pcm", .id = 0, .playback = { - .stream_name = "pcm-playback", + .stream_name = "offload-pcm-playback", .channels_min = 2, .channels_max = 2, .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, @@ -730,7 +724,7 @@ static struct snd_soc_dai_driver tegra_offload_dai[] = { .id = 0, .compress_dai = 1, .playback = { - .stream_name = "compr-playback", + .stream_name = "offload-compr-playback", .channels_min = 2, .channels_max = 2, .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, diff --git a/sound/soc/tegra/tegra_rt5639.c b/sound/soc/tegra/tegra_rt5639.c index 0493b2987862..ae16793491f5 100644 --- a/sound/soc/tegra/tegra_rt5639.c +++ b/sound/soc/tegra/tegra_rt5639.c @@ -928,10 +928,10 @@ static const struct snd_soc_dapm_route ardbeg_audio_map[] = { /*{"IN1P", NULL, "micbias1"},*/ /*{"IN1N", NULL, "micbias1"},*/ /* AHUB BE connections */ - {"tegra30-i2s.1 Playback", NULL, "I2S1_OUT"}, - {"I2S1_OUT", NULL, "offload-pcm-playback"}, {"I2S1_OUT", NULL, "offload-compr-playback"}, + + {"AIF1 Playback", NULL, "I2S1_OUT"}, }; @@ -1072,6 +1072,8 @@ static struct snd_soc_dai_link tegra_rt5639_dai[NUM_DAI_LINKS] = { .cpu_dai_name = "tegra30-i2s.1", .codec_dai_name = "rt5639-aif1", .ops = &tegra_rt5639_ops, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, .no_pcm = 1, -- cgit v1.2.3