At Mon, 2 Jul 2012 14:24:33 +0530, Laxman Dewangan wrote:
The sound pcm library support the writecombine DMA buffer allocation/deallocation/mapping and hence using the APIs form sound pcm library inplace of implementing the same locally.
Signed-off-by: Laxman Dewangan ldewangan@nvidia.com
Changes from V1: Changes done to use the existing APIs for sound pcm memory management which is now supporting writecombine.
sound/soc/tegra/tegra_pcm.c | 112 ++++++++++-------------------------------- 1 files changed, 27 insertions(+), 85 deletions(-)
diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c index 127348d..ec1fa25 100644 --- a/sound/soc/tegra/tegra_pcm.c +++ b/sound/soc/tegra/tegra_pcm.c @@ -202,8 +202,14 @@ static int tegra_pcm_hw_params(struct snd_pcm_substream *substream, { struct snd_pcm_runtime *runtime = substream->runtime; struct tegra_runtime_data *prtd = runtime->private_data;
- int ret;
- snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
- ret = snd_pcm_lib_malloc_pages(substream,
params_buffer_bytes(params));
- if (ret < 0) {
pr_err("page allocation failed, err %d\n", ret);
Do you really want to spew error messages at each time?
return ret;
}
prtd->dma_req[0].size = params_period_bytes(params); prtd->dma_req[1].size = prtd->dma_req[0].size;
@@ -213,9 +219,7 @@ static int tegra_pcm_hw_params(struct snd_pcm_substream *substream,
static int tegra_pcm_hw_free(struct snd_pcm_substream *substream) {
- snd_pcm_set_runtime_buffer(substream, NULL);
- return 0;
- return snd_pcm_lib_free_pages(substream);
}
static int tegra_pcm_trigger(struct snd_pcm_substream *substream, int cmd) @@ -263,18 +267,6 @@ static snd_pcm_uframes_t tegra_pcm_pointer(struct snd_pcm_substream *substream) return prtd->period_index * runtime->period_size; }
-static int tegra_pcm_mmap(struct snd_pcm_substream *substream,
struct vm_area_struct *vma)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- return dma_mmap_writecombine(substream->pcm->card->dev, vma,
runtime->dma_area,
runtime->dma_addr,
runtime->dma_bytes);
-}
static struct snd_pcm_ops tegra_pcm_ops = { .open = tegra_pcm_open, .close = tegra_pcm_close, @@ -283,87 +275,37 @@ static struct snd_pcm_ops tegra_pcm_ops = { .hw_free = tegra_pcm_hw_free, .trigger = tegra_pcm_trigger, .pointer = tegra_pcm_pointer,
- .mmap = tegra_pcm_mmap,
- .mmap = snd_pcm_lib_default_mmap,
You can simply remove .mmap definition. NULL falls back to the default mmap handler.
};
-static int tegra_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) -{
- struct snd_pcm_substream *substream = pcm->streams[stream].substream;
- struct snd_dma_buffer *buf = &substream->dma_buffer;
- size_t size = tegra_pcm_hardware.buffer_bytes_max;
- buf->area = dma_alloc_writecombine(pcm->card->dev, size,
&buf->addr, GFP_KERNEL);
- if (!buf->area)
return -ENOMEM;
- buf->dev.type = SNDRV_DMA_TYPE_DEV;
- buf->dev.dev = pcm->card->dev;
- buf->private_data = NULL;
- buf->bytes = size;
- return 0;
-}
-static void tegra_pcm_deallocate_dma_buffer(struct snd_pcm *pcm, int stream) -{
- struct snd_pcm_substream *substream;
- struct snd_dma_buffer *buf;
- substream = pcm->streams[stream].substream;
- if (!substream)
return;
- buf = &substream->dma_buffer;
- if (!buf->area)
return;
- dma_free_writecombine(pcm->card->dev, buf->bytes,
buf->area, buf->addr);
- buf->area = NULL;
-}
-static u64 tegra_dma_mask = DMA_BIT_MASK(32);
+#define TEGRA_PCM_PREALLOC_BUFFER (32 * 1024) +#define TEGRA_PCM_PREALLOC_BUFFER_MAX (32 * 1024) static int tegra_pcm_new(struct snd_soc_pcm_runtime *rtd) {
- struct snd_card *card = rtd->card->snd_card; struct snd_pcm *pcm = rtd->pcm;
- int ret = 0;
- if (!card->dev->dma_mask)
card->dev->dma_mask = &tegra_dma_mask;
- if (!card->dev->coherent_dma_mask)
card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
The mask setup is still required even if you use the preallocation helper.
- if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
ret = tegra_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_PLAYBACK);
if (ret)
goto err;
- }
- if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
ret = tegra_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_CAPTURE);
if (ret)
goto err_free_play;
- struct snd_card *card = rtd->card->snd_card;
- int retval = 0;
- if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream ||
pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
You can omit this check. snd_pcm_lib_preallocate_pages_for_all() will ignore the streams that have no substreams assigned.
Takashi
retval = snd_pcm_lib_preallocate_pages_for_all(pcm,
SNDRV_DMA_TYPE_DEV_WC,
card->dev,
TEGRA_PCM_PREALLOC_BUFFER,
TEGRA_PCM_PREALLOC_BUFFER_MAX);
if (retval < 0)
dev_err(card->dev,
}"dma buffer pre-alloc failied %d\n", retval);
- return 0;
-err_free_play:
- tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK);
-err:
- return ret;
- return retval;
}
static void tegra_pcm_free(struct snd_pcm *pcm) {
- tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_CAPTURE);
- tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK);
- snd_pcm_lib_preallocate_free_for_all(pcm);
}
static struct snd_soc_platform_driver tegra_pcm_platform = { .ops = &tegra_pcm_ops, .pcm_new = tegra_pcm_new, -- 1.7.1.1