diff options
Diffstat (limited to 'sound/soc/tegra/tegra_pcm.c')
-rw-r--r-- | sound/soc/tegra/tegra_pcm.c | 138 |
1 files changed, 29 insertions, 109 deletions
diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c index b3f36515cbc1..05d59e03b1c5 100644 --- a/sound/soc/tegra/tegra_pcm.c +++ b/sound/soc/tegra/tegra_pcm.c @@ -48,6 +48,12 @@ int tegra_pcm_platform_register(struct device *dev) } EXPORT_SYMBOL_GPL(tegra_pcm_platform_register); +int devm_tegra_pcm_platform_register(struct device *dev) +{ + return devm_snd_dmaengine_pcm_register(dev, &tegra_dmaengine_pcm_config, 0); +} +EXPORT_SYMBOL_GPL(devm_tegra_pcm_platform_register); + int tegra_pcm_platform_register_with_chan_names(struct device *dev, struct snd_dmaengine_pcm_config *config, char *txdmachan, char *rxdmachan) @@ -70,10 +76,10 @@ EXPORT_SYMBOL_GPL(tegra_pcm_platform_unregister); int tegra_pcm_open(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_dmaengine_dai_dma_data *dmap; struct dma_chan *chan; - struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); int ret; if (rtd->dai_link->no_pcm) @@ -92,8 +98,8 @@ int tegra_pcm_open(struct snd_soc_component *component, return ret; } - chan = dma_request_slave_channel(cpu_dai->dev, dmap->chan_name); - if (!chan) { + chan = dma_request_chan(cpu_dai->dev, dmap->chan_name); + if (IS_ERR(chan)) { dev_err(cpu_dai->dev, "dmaengine request slave channel failed! (%s)\n", dmap->chan_name); @@ -111,6 +117,9 @@ int tegra_pcm_open(struct snd_soc_component *component, return ret; } + /* Set wait time to 500ms by default */ + substream->wait_time = 500; + return 0; } EXPORT_SYMBOL_GPL(tegra_pcm_open); @@ -118,7 +127,7 @@ EXPORT_SYMBOL_GPL(tegra_pcm_open); int tegra_pcm_close(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); if (rtd->dai_link->no_pcm) return 0; @@ -133,7 +142,7 @@ int tegra_pcm_hw_params(struct snd_soc_component *component, struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_dmaengine_dai_dma_data *dmap; struct dma_slave_config slave_config; struct dma_chan *chan; @@ -142,7 +151,7 @@ int tegra_pcm_hw_params(struct snd_soc_component *component, if (rtd->dai_link->no_pcm) return 0; - dmap = snd_soc_dai_get_dma_data(asoc_rtd_to_cpu(rtd, 0), substream); + dmap = snd_soc_dai_get_dma_data(snd_soc_rtd_to_cpu(rtd, 0), substream); if (!dmap) return 0; @@ -171,41 +180,10 @@ int tegra_pcm_hw_params(struct snd_soc_component *component, return ret; } - snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); - return 0; } EXPORT_SYMBOL_GPL(tegra_pcm_hw_params); -int tegra_pcm_hw_free(struct snd_soc_component *component, - struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - - if (rtd->dai_link->no_pcm) - return 0; - - snd_pcm_set_runtime_buffer(substream, NULL); - - return 0; -} -EXPORT_SYMBOL_GPL(tegra_pcm_hw_free); - -int tegra_pcm_mmap(struct snd_soc_component *component, - struct snd_pcm_substream *substream, - struct vm_area_struct *vma) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_pcm_runtime *runtime = substream->runtime; - - if (rtd->dai_link->no_pcm) - return 0; - - return dma_mmap_wc(substream->pcm->card->dev, vma, runtime->dma_area, - runtime->dma_addr, runtime->dma_bytes); -} -EXPORT_SYMBOL_GPL(tegra_pcm_mmap); - snd_pcm_uframes_t tegra_pcm_pointer(struct snd_soc_component *component, struct snd_pcm_substream *substream) { @@ -213,92 +191,34 @@ snd_pcm_uframes_t tegra_pcm_pointer(struct snd_soc_component *component, } EXPORT_SYMBOL_GPL(tegra_pcm_pointer); -static int tegra_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream, - size_t size) -{ - struct snd_pcm_substream *substream = pcm->streams[stream].substream; - struct snd_dma_buffer *buf = &substream->dma_buffer; - - buf->area = dma_alloc_wc(pcm->card->dev, size, &buf->addr, GFP_KERNEL); - if (!buf->area) - return -ENOMEM; - - buf->private_data = NULL; - buf->dev.type = SNDRV_DMA_TYPE_DEV; - buf->dev.dev = pcm->card->dev; - 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_wc(pcm->card->dev, buf->bytes, buf->area, buf->addr); - buf->area = NULL; -} - -static int tegra_pcm_dma_allocate(struct snd_soc_pcm_runtime *rtd, +static int tegra_pcm_dma_allocate(struct device *dev, struct snd_soc_pcm_runtime *rtd, size_t size) { - struct snd_card *card = rtd->card->snd_card; struct snd_pcm *pcm = rtd->pcm; int ret; - ret = dma_set_mask(card->dev, DMA_BIT_MASK(32)); - if (ret < 0) - return ret; - - ret = dma_set_coherent_mask(card->dev, DMA_BIT_MASK(32)); + ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); if (ret < 0) return ret; - if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { - ret = tegra_pcm_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_PLAYBACK, size); - if (ret) - goto err; - } - - if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { - ret = tegra_pcm_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_CAPTURE, size); - if (ret) - goto err_free_play; - } - - return 0; - -err_free_play: - tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK); -err: - return ret; + return snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_WC, dev, size); } int tegra_pcm_construct(struct snd_soc_component *component, struct snd_soc_pcm_runtime *rtd) { - return tegra_pcm_dma_allocate(rtd, tegra_pcm_hardware.buffer_bytes_max); -} -EXPORT_SYMBOL_GPL(tegra_pcm_construct); + struct device *dev = component->dev; -void tegra_pcm_destruct(struct snd_soc_component *component, - struct snd_pcm *pcm) -{ - tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_CAPTURE); - tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK); + /* + * Fallback for backwards-compatibility with older device trees that + * have the iommus property in the virtual, top-level "sound" node. + */ + if (!of_property_present(dev->of_node, "iommus")) + dev = rtd->card->snd_card->dev; + + return tegra_pcm_dma_allocate(dev, rtd, tegra_pcm_hardware.buffer_bytes_max); } -EXPORT_SYMBOL_GPL(tegra_pcm_destruct); +EXPORT_SYMBOL_GPL(tegra_pcm_construct); MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>"); MODULE_DESCRIPTION("Tegra PCM ASoC driver"); |