From 140b49082fd7d937d8a74b4dccc091c941dacb07 Mon Sep 17 00:00:00 2001 From: Sumit Bhattacharya Date: Wed, 16 Feb 2011 15:49:52 +0530 Subject: alsa: Set restrictions on period size Restrict period size to be multiple of 8 and period count to be integer. This is required to prevent audio breaks for playback through BT SCO. Bug 771510 Change-Id: If15631512bc5ce5a4358342b523da0a5a020cc2d Reviewed-on: http://git-master/r/19731 Reviewed-by: Varun Colbert Tested-by: Varun Colbert --- sound/soc/tegra/tegra_pcm.c | 40 ++++++++++++++++++++++++++++++---------- sound/soc/tegra/tegra_soc.h | 2 ++ 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c index 2c13ea4fc7d5..1ef79f60dd6a 100644 --- a/sound/soc/tegra/tegra_pcm.c +++ b/sound/soc/tegra/tegra_pcm.c @@ -125,7 +125,7 @@ static const struct snd_pcm_hardware tegra_pcm_hardware = { .channels_min = 1, .channels_max = 2, .buffer_bytes_max = (PAGE_SIZE * 8), - .period_bytes_min = 256, + .period_bytes_min = 128, .period_bytes_max = (PAGE_SIZE), .periods_min = 2, .periods_max = 8, @@ -218,9 +218,27 @@ static snd_pcm_uframes_t tegra_pcm_pointer(struct snd_pcm_substream *substream) static int tegra_pcm_open(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct tegra_runtime_data *prtd; + struct tegra_runtime_data *prtd = 0; int ret=0; + /* Ensure period size is multiple of minimum DMA step size */ + ret = snd_pcm_hw_constraint_step(runtime, 0, + SNDRV_PCM_HW_PARAM_PERIOD_BYTES, DMA_STEP_SIZE_MIN); + if (ret < 0) { + pr_err("%s:snd_pcm_hw_constraint_step failed: %d\n", + __func__, ret); + goto fail; + } + + /* Ensure buffer size is multiple of period size */ + ret = snd_pcm_hw_constraint_integer(runtime, + SNDRV_PCM_HW_PARAM_PERIODS); + if (ret < 0) { + pr_err("%s:snd_pcm_hw_constraint_integer failed: %d\n", + __func__, ret); + goto fail; + } + prtd = kzalloc(sizeof(struct tegra_runtime_data), GFP_KERNEL); if (prtd == NULL) return -ENOMEM; @@ -258,17 +276,19 @@ static int tegra_pcm_open(struct snd_pcm_substream *substream) goto end; fail: - prtd->state = STATE_EXIT; + if (prtd) { + prtd->state = STATE_EXIT; - if (prtd->dma_chan) { - tegra_dma_flush(prtd->dma_chan); - tegra_dma_free_channel(prtd->dma_chan); - } + if (prtd->dma_chan) { + tegra_dma_flush(prtd->dma_chan); + tegra_dma_free_channel(prtd->dma_chan); + } - /* set pins state to tristate */ - tegra_das_power_mode(false); + /* set pins state to tristate */ + tegra_das_power_mode(false); - kfree(prtd); + kfree(prtd); + } end: return ret; diff --git a/sound/soc/tegra/tegra_soc.h b/sound/soc/tegra/tegra_soc.h index 7a77723c9ea9..4910b8669dd9 100644 --- a/sound/soc/tegra/tegra_soc.h +++ b/sound/soc/tegra/tegra_soc.h @@ -75,6 +75,8 @@ SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) #define TEGRA_VOICE_SAMPLE_RATES SNDRV_PCM_RATE_8000 +#define DMA_STEP_SIZE_MIN 8 + struct tegra_dma_channel; struct tegra_runtime_data { -- cgit v1.2.3