diff options
Diffstat (limited to 'sound/soc')
-rw-r--r-- | sound/soc/soc-devres.c | 41 | ||||
-rw-r--r-- | sound/soc/soc-generic-dmaengine-pcm.c | 24 |
2 files changed, 57 insertions, 8 deletions
diff --git a/sound/soc/soc-devres.c b/sound/soc/soc-devres.c index b1d732255c02..999861942d28 100644 --- a/sound/soc/soc-devres.c +++ b/sound/soc/soc-devres.c @@ -12,6 +12,7 @@ #include <linux/module.h> #include <linux/moduleparam.h> #include <sound/soc.h> +#include <sound/dmaengine_pcm.h> static void devm_component_release(struct device *dev, void *res) { @@ -84,3 +85,43 @@ int devm_snd_soc_register_card(struct device *dev, struct snd_soc_card *card) return ret; } EXPORT_SYMBOL_GPL(devm_snd_soc_register_card); + +#ifdef CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM + +static void devm_dmaengine_pcm_release(struct device *dev, void *res) +{ + snd_dmaengine_pcm_unregister(*(struct device **)res); +} + +/** + * devm_snd_dmaengine_pcm_register - resource managed dmaengine PCM registration + * @dev: The parent device for the PCM device + * @config: Platform specific PCM configuration + * @flags: Platform specific quirks + * + * Register a dmaengine based PCM device with automatic unregistration when the + * device is unregistered. + */ +int devm_snd_dmaengine_pcm_register(struct device *dev, + const struct snd_dmaengine_pcm_config *config, unsigned int flags) +{ + struct device **ptr; + int ret; + + ptr = devres_alloc(devm_dmaengine_pcm_release, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return -ENOMEM; + + ret = snd_dmaengine_pcm_register(dev, config, flags); + if (ret == 0) { + *ptr = dev; + devres_add(dev, ptr); + } else { + devres_free(ptr); + } + + return ret; +} +EXPORT_SYMBOL_GPL(devm_snd_dmaengine_pcm_register); + +#endif diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c index 41949af3baae..1cb3494cf278 100644 --- a/sound/soc/soc-generic-dmaengine-pcm.c +++ b/sound/soc/soc-generic-dmaengine-pcm.c @@ -137,6 +137,9 @@ static int dmaengine_pcm_set_runtime_hwparams(struct snd_pcm_substream *substrea hw.buffer_bytes_max = SIZE_MAX; hw.fifo_size = dma_data->fifo_size; + if (pcm->flags & SND_DMAENGINE_PCM_FLAG_NO_RESIDUE) + hw.info |= SNDRV_PCM_INFO_BATCH; + ret = dma_get_slave_caps(chan, &dma_caps); if (ret == 0) { if (dma_caps.cmd_pause) @@ -288,21 +291,26 @@ static void dmaengine_pcm_request_chan_of(struct dmaengine_pcm *pcm, struct device *dev) { unsigned int i; + const char *name; if ((pcm->flags & (SND_DMAENGINE_PCM_FLAG_NO_DT | SND_DMAENGINE_PCM_FLAG_CUSTOM_CHANNEL_NAME)) || !dev->of_node) return; - if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX) { - pcm->chan[0] = dma_request_slave_channel(dev, "rx-tx"); - pcm->chan[1] = pcm->chan[0]; - } else { - for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE; i++) { - pcm->chan[i] = dma_request_slave_channel(dev, - dmaengine_pcm_dma_channel_names[i]); - } + for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE; + i++) { + if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX) + name = "rx-tx"; + else + name = dmaengine_pcm_dma_channel_names[i]; + pcm->chan[i] = dma_request_slave_channel(dev, name); + if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX) + break; } + + if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX) + pcm->chan[1] = pcm->chan[0]; } static void dmaengine_pcm_release_chan(struct dmaengine_pcm *pcm) |