From 7c1c1d4a7b4ca1266057a3632d27450f5575caf9 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 15 Apr 2013 19:19:48 +0200 Subject: ASoC: dmaengine-pcm: Make requesting the DMA channel at PCM open optional Refactor the dmaengine PCM library to allow the DMA channel to be requested before opening a PCM substream. snd_dmaengine_pcm_open() now expects a DMA channel instead of a filter function and filter parameter as its parameters. snd_dmaengine_pcm_close() is updated to not release the DMA channel. This allows a dmaengine based PCM driver to request its channels before the substream is opened. The patch also introduces two new functions, snd_dmaengine_pcm_open_request_chan() and snd_dmaengine_pcm_close_release_chan(), which have the same signature and behaviour of the old snd_dmaengine_pcm_{open,close}() and internally use the new variants of these functions. All users of snd_dmaengine_pcm_{open,close}() are updated to use snd_dmaengine_pcm_open_request_chan() and snd_dmaengine_pcm_close_release_chan(). Signed-off-by: Lars-Peter Clausen Tested-by: Stephen Warren Tested-by: Shawn Guo Signed-off-by: Mark Brown --- sound/soc/mxs/mxs-pcm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound/soc/mxs') diff --git a/sound/soc/mxs/mxs-pcm.c b/sound/soc/mxs/mxs-pcm.c index ebbef85..7bceb16 100644 --- a/sound/soc/mxs/mxs-pcm.c +++ b/sound/soc/mxs/mxs-pcm.c @@ -87,7 +87,7 @@ static int snd_mxs_open(struct snd_pcm_substream *substream) snd_soc_set_runtime_hwparams(substream, &snd_mxs_hardware); - return snd_dmaengine_pcm_open(substream, filter, + return snd_dmaengine_pcm_open_request_chan(substream, filter, snd_soc_dai_get_dma_data(rtd->cpu_dai, substream)); } @@ -104,7 +104,7 @@ static int snd_mxs_pcm_mmap(struct snd_pcm_substream *substream, static struct snd_pcm_ops mxs_pcm_ops = { .open = snd_mxs_open, - .close = snd_dmaengine_pcm_close, + .close = snd_dmaengine_pcm_close_release_chan, .ioctl = snd_pcm_lib_ioctl, .hw_params = snd_mxs_pcm_hw_params, .trigger = snd_dmaengine_pcm_trigger, -- cgit v1.1 From 57364f9ae24c3a29163c23d5219bccef7bccc96a Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 20 Apr 2013 19:29:01 +0200 Subject: ASoC: mxs-pcm: Set SNDRV_PCM_INFO_HALF_DUPLEX The MXS SAIF is only half-duplex so set the SNDRV_PCM_INFO_HALF_DUPLEX flag for the PCM in order to prevent playback and capture from running at the same time. Signed-off-by: Lars-Peter Clausen Tested-by: Shawn Guo Signed-off-by: Mark Brown --- sound/soc/mxs/mxs-pcm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sound/soc/mxs') diff --git a/sound/soc/mxs/mxs-pcm.c b/sound/soc/mxs/mxs-pcm.c index 7bceb16..907cdb1 100644 --- a/sound/soc/mxs/mxs-pcm.c +++ b/sound/soc/mxs/mxs-pcm.c @@ -43,7 +43,8 @@ static struct snd_pcm_hardware snd_mxs_hardware = { SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME | - SNDRV_PCM_INFO_INTERLEAVED, + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_HALF_DUPLEX, .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE, -- cgit v1.1 From 8c1bb4ecbca575ec89310a50c3d3dd475bf81fd0 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 20 Apr 2013 19:29:02 +0200 Subject: ASoC: mxs: Setup dma data in DAI probe This allows us to access the DAI DMA data when we create the PCM. We'll use this when converting mxs to generic DMA engine PCM driver. Signed-off-by: Lars-Peter Clausen Tested-by: Shawn Guo Signed-off-by: Mark Brown --- sound/soc/mxs/mxs-saif.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sound/soc/mxs') diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c index f13bd87..d796a39 100644 --- a/sound/soc/mxs/mxs-saif.c +++ b/sound/soc/mxs/mxs-saif.c @@ -369,7 +369,6 @@ static int mxs_saif_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai); - snd_soc_dai_set_dma_data(cpu_dai, substream, &saif->dma_param); /* clear error status to 0 for each re-open */ saif->fifo_underrun = 0; @@ -605,6 +604,8 @@ static int mxs_saif_dai_probe(struct snd_soc_dai *dai) struct mxs_saif *saif = dev_get_drvdata(dai->dev); snd_soc_dai_set_drvdata(dai, saif); + dai->playback_dma_data = &saif->dma_param; + dai->capture_dma_data = &saif->dma_param; return 0; } -- cgit v1.1 From a8956908bf03418d7264de79e1e988628183f537 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 20 Apr 2013 19:29:03 +0200 Subject: ASoC: mxs: Use generic dmaengine PCM Use the generic dmaengine PCM driver instead of a custom implementation. Signed-off-by: Lars-Peter Clausen Tested-by: Shawn Guo Signed-off-by: Mark Brown --- sound/soc/mxs/Kconfig | 2 +- sound/soc/mxs/mxs-pcm.c | 136 ++++-------------------------------------------- 2 files changed, 12 insertions(+), 126 deletions(-) (limited to 'sound/soc/mxs') diff --git a/sound/soc/mxs/Kconfig b/sound/soc/mxs/Kconfig index b6fa776..78d321c 100644 --- a/sound/soc/mxs/Kconfig +++ b/sound/soc/mxs/Kconfig @@ -1,7 +1,7 @@ menuconfig SND_MXS_SOC tristate "SoC Audio for Freescale MXS CPUs" depends on ARCH_MXS - select SND_SOC_DMAENGINE_PCM + select SND_SOC_GENERIC_DMAENGINE_PCM help Say Y or M if you want to add support for codecs attached to the MXS SAIF interface. diff --git a/sound/soc/mxs/mxs-pcm.c b/sound/soc/mxs/mxs-pcm.c index 907cdb1..b41fffc 100644 --- a/sound/soc/mxs/mxs-pcm.c +++ b/sound/soc/mxs/mxs-pcm.c @@ -18,27 +18,18 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include -#include #include -#include #include -#include #include -#include -#include -#include #include -#include #include -#include #include #include #include "mxs-pcm.h" -static struct snd_pcm_hardware snd_mxs_hardware = { +static const struct snd_pcm_hardware snd_mxs_hardware = { .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE | @@ -56,7 +47,6 @@ static struct snd_pcm_hardware snd_mxs_hardware = { .periods_max = 52, .buffer_bytes_max = 64 * 1024, .fifo_size = 32, - }; static bool filter(struct dma_chan *chan, void *param) @@ -74,129 +64,25 @@ static bool filter(struct dma_chan *chan, void *param) return true; } -static int snd_mxs_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); - - return 0; -} - -static int snd_mxs_open(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - - snd_soc_set_runtime_hwparams(substream, &snd_mxs_hardware); - - return snd_dmaengine_pcm_open_request_chan(substream, filter, - snd_soc_dai_get_dma_data(rtd->cpu_dai, substream)); -} - -static int snd_mxs_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 mxs_pcm_ops = { - .open = snd_mxs_open, - .close = snd_dmaengine_pcm_close_release_chan, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_mxs_pcm_hw_params, - .trigger = snd_dmaengine_pcm_trigger, - .pointer = snd_dmaengine_pcm_pointer_no_residue, - .mmap = snd_mxs_pcm_mmap, -}; - -static int mxs_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 = snd_mxs_hardware.buffer_bytes_max; - - buf->dev.type = SNDRV_DMA_TYPE_DEV; - buf->dev.dev = pcm->card->dev; - buf->private_data = NULL; - buf->area = dma_alloc_writecombine(pcm->card->dev, size, - &buf->addr, GFP_KERNEL); - if (!buf->area) - return -ENOMEM; - buf->bytes = size; - - return 0; -} - -static u64 mxs_pcm_dmamask = DMA_BIT_MASK(32); -static int mxs_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 = &mxs_pcm_dmamask; - if (!card->dev->coherent_dma_mask) - card->dev->coherent_dma_mask = DMA_BIT_MASK(32); - - if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { - ret = mxs_pcm_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_PLAYBACK); - if (ret) - goto out; - } - - if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { - ret = mxs_pcm_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_CAPTURE); - if (ret) - goto out; - } - -out: - return ret; -} - -static void mxs_pcm_free(struct snd_pcm *pcm) -{ - struct snd_pcm_substream *substream; - struct snd_dma_buffer *buf; - int stream; - - for (stream = 0; stream < 2; stream++) { - substream = pcm->streams[stream].substream; - if (!substream) - continue; - - buf = &substream->dma_buffer; - if (!buf->area) - continue; - - dma_free_writecombine(pcm->card->dev, buf->bytes, - buf->area, buf->addr); - buf->area = NULL; - } -} - -static struct snd_soc_platform_driver mxs_soc_platform = { - .ops = &mxs_pcm_ops, - .pcm_new = mxs_pcm_new, - .pcm_free = mxs_pcm_free, +static const struct snd_dmaengine_pcm_config mxs_dmaengine_pcm_config = { + .pcm_hardware = &snd_mxs_hardware, + .compat_filter_fn = filter, + .prealloc_buffer_size = 64 * 1024, }; int mxs_pcm_platform_register(struct device *dev) { - return snd_soc_register_platform(dev, &mxs_soc_platform); + return snd_dmaengine_pcm_register(dev, &mxs_dmaengine_pcm_config, + SND_DMAENGINE_PCM_FLAG_NO_RESIDUE | + SND_DMAENGINE_PCM_FLAG_NO_DT | + SND_DMAENGINE_PCM_FLAG_COMPAT | + SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX); } EXPORT_SYMBOL_GPL(mxs_pcm_platform_register); void mxs_pcm_platform_unregister(struct device *dev) { - snd_soc_unregister_platform(dev); + snd_dmaengine_pcm_unregister(dev); } EXPORT_SYMBOL_GPL(mxs_pcm_platform_unregister); -- cgit v1.1