Messages in this thread | | | Date | Mon, 02 Jul 2012 11:14:55 +0200 | From | Takashi Iwai <> | Subject | Re: [PATCH 2/2] ASoC: tegra: use sound pcm library for substream dma buffer |
| |
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 >
| |