From f61271a07333c0177346716e9a85da2dfea3f73e Mon Sep 17 00:00:00 2001 From: Sumit Bhattacharya Date: Fri, 20 Apr 2012 17:26:35 +0530 Subject: ASoC: Tegra: Make dma_req count easily configurable Instead of always using 2 dma_req count pass max dma_req_count through a macro. Ensure dma_req_count does not cross period_count. Bug 968814 Change-Id: Iddfbd77017992ccb8c90441213e191133dadb347 Signed-off-by: Sumit Bhattacharya Reviewed-on: http://git-master/r/97915 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Ravindra Lokhande Reviewed-by: Scott Peterson --- sound/soc/tegra/tegra_pcm.c | 39 ++++++++++++++++++++++++--------------- sound/soc/tegra/tegra_pcm.h | 5 ++++- 2 files changed, 28 insertions(+), 16 deletions(-) (limited to 'sound/soc') diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c index 00bd7aa2e59d..65d89c8b1280 100644 --- a/sound/soc/tegra/tegra_pcm.c +++ b/sound/soc/tegra/tegra_pcm.c @@ -66,7 +66,8 @@ static void tegra_pcm_queue_dma(struct tegra_runtime_data *prtd) unsigned long addr; dma_req = &prtd->dma_req[prtd->dma_req_idx]; - prtd->dma_req_idx = 1 - prtd->dma_req_idx; + if (++prtd->dma_req_idx >= prtd->dma_req_count) + prtd->dma_req_idx -= prtd->dma_req_count; addr = buf->addr + prtd->dma_pos; prtd->dma_pos += dma_req->size; @@ -137,6 +138,7 @@ static int tegra_pcm_open(struct snd_pcm_substream *substream) struct snd_soc_pcm_runtime *rtd = substream->private_data; struct tegra_pcm_dma_params * dmap; int ret = 0; + int i = 0; prtd = kzalloc(sizeof(struct tegra_runtime_data), GFP_KERNEL); if (prtd == NULL) @@ -148,10 +150,11 @@ static int tegra_pcm_open(struct snd_pcm_substream *substream) spin_lock_init(&prtd->lock); dmap = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); + prtd->dma_req_count = MAX_DMA_REQ_COUNT; if (dmap) { - prtd->dma_req[0].dev = prtd; - prtd->dma_req[1].dev = prtd; + for (i = 0; i < prtd->dma_req_count; i++) + prtd->dma_req[i].dev = prtd; prtd->dma_chan = tegra_dma_allocate_channel( TEGRA_DMA_MODE_CONTINUOUS_SINGLE, @@ -209,21 +212,25 @@ static int tegra_pcm_hw_params(struct snd_pcm_substream *substream, struct tegra_runtime_data *prtd = runtime->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data; struct tegra_pcm_dma_params * dmap; + int i; snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); + /* Limit dma_req_count to period count */ + if (prtd->dma_req_count > params_periods(params)) + prtd->dma_req_count = params_periods(params); dmap = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); if (dmap) { if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - setup_dma_tx_request(&prtd->dma_req[0], dmap); - setup_dma_tx_request(&prtd->dma_req[1], dmap); + for (i = 0; i < prtd->dma_req_count; i++) + setup_dma_tx_request(&prtd->dma_req[i], dmap); } else { - setup_dma_rx_request(&prtd->dma_req[0], dmap); - setup_dma_rx_request(&prtd->dma_req[1], dmap); + for (i = 0; i < prtd->dma_req_count; i++) + setup_dma_rx_request(&prtd->dma_req[i], dmap); } } - prtd->dma_req[0].size = params_period_bytes(params); - prtd->dma_req[1].size = prtd->dma_req[0].size; + for (i = 0; i < prtd->dma_req_count; i++) + prtd->dma_req[i].size = params_period_bytes(params); return 0; } @@ -240,6 +247,7 @@ static int tegra_pcm_trigger(struct snd_pcm_substream *substream, int cmd) struct snd_pcm_runtime *runtime = substream->runtime; struct tegra_runtime_data *prtd = runtime->private_data; unsigned long flags; + int i; switch (cmd) { case SNDRV_PCM_TRIGGER_START: @@ -253,8 +261,8 @@ static int tegra_pcm_trigger(struct snd_pcm_substream *substream, int cmd) spin_lock_irqsave(&prtd->lock, flags); prtd->running = 1; spin_unlock_irqrestore(&prtd->lock, flags); - tegra_pcm_queue_dma(prtd); - tegra_pcm_queue_dma(prtd); + for (i = 0; i < prtd->dma_req_count; i++) + tegra_pcm_queue_dma(prtd); break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: @@ -263,10 +271,11 @@ static int tegra_pcm_trigger(struct snd_pcm_substream *substream, int cmd) prtd->running = 0; spin_unlock_irqrestore(&prtd->lock, flags); tegra_dma_cancel(prtd->dma_chan); - if (prtd->dma_req[0].status == -TEGRA_DMA_REQ_ERROR_ABORTED) - prtd->dma_req[0].complete(&prtd->dma_req[0]); - if (prtd->dma_req[1].status == -TEGRA_DMA_REQ_ERROR_ABORTED) - prtd->dma_req[1].complete(&prtd->dma_req[1]); + for (i = 0; i < prtd->dma_req_count; i++) { + if (prtd->dma_req[i].status == + -TEGRA_DMA_REQ_ERROR_ABORTED) + prtd->dma_req[i].complete(&prtd->dma_req[i]); + } break; default: return -EINVAL; diff --git a/sound/soc/tegra/tegra_pcm.h b/sound/soc/tegra/tegra_pcm.h index dbb90339fe0d..5737ea7ca0bc 100644 --- a/sound/soc/tegra/tegra_pcm.h +++ b/sound/soc/tegra/tegra_pcm.h @@ -33,6 +33,8 @@ #include +#define MAX_DMA_REQ_COUNT 2 + struct tegra_pcm_dma_params { unsigned long addr; unsigned long wrap; @@ -48,8 +50,9 @@ struct tegra_runtime_data { int dma_pos_end; int period_index; int dma_req_idx; - struct tegra_dma_req dma_req[2]; + struct tegra_dma_req dma_req[MAX_DMA_REQ_COUNT]; struct tegra_dma_channel *dma_chan; + int dma_req_count; }; #endif -- cgit v1.2.3