diff options
Diffstat (limited to 'sound/soc/mxs')
-rw-r--r-- | sound/soc/mxs/Kconfig | 2 | ||||
-rw-r--r-- | sound/soc/mxs/mxs-pcm.c | 157 | ||||
-rw-r--r-- | sound/soc/mxs/mxs-pcm.h | 16 | ||||
-rw-r--r-- | sound/soc/mxs/mxs-saif.c | 51 |
4 files changed, 38 insertions, 188 deletions
diff --git a/sound/soc/mxs/Kconfig b/sound/soc/mxs/Kconfig index e4ba8d5f25f..99a997f19bb 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_PCM + select SND_SOC_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 105f42a394d..6ca1f46d84a 100644 --- a/sound/soc/mxs/mxs-pcm.c +++ b/sound/soc/mxs/mxs-pcm.c @@ -34,10 +34,16 @@ #include <sound/pcm.h> #include <sound/pcm_params.h> #include <sound/soc.h> +#include <sound/dmaengine_pcm.h> #include <mach/dma.h> #include "mxs-pcm.h" +struct mxs_pcm_dma_data { + struct mxs_dma_data dma_data; + struct mxs_pcm_dma_params *dma_params; +}; + static struct snd_pcm_hardware snd_mxs_hardware = { .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | @@ -58,21 +64,10 @@ static struct snd_pcm_hardware snd_mxs_hardware = { }; -static void audio_dma_irq(void *data) -{ - struct snd_pcm_substream *substream = (struct snd_pcm_substream *)data; - struct snd_pcm_runtime *runtime = substream->runtime; - struct mxs_pcm_runtime_data *iprtd = runtime->private_data; - - iprtd->offset += iprtd->period_bytes; - iprtd->offset %= iprtd->period_bytes * iprtd->periods; - snd_pcm_period_elapsed(substream); -} - static bool filter(struct dma_chan *chan, void *param) { - struct mxs_pcm_runtime_data *iprtd = param; - struct mxs_pcm_dma_params *dma_params = iprtd->dma_params; + struct mxs_pcm_dma_data *pcm_dma_data = param; + struct mxs_pcm_dma_params *dma_params = pcm_dma_data->dma_params; if (!mxs_dma_is_apbx(chan)) return false; @@ -80,150 +75,51 @@ static bool filter(struct dma_chan *chan, void *param) if (chan->chan_id != dma_params->chan_num) return false; - chan->private = &iprtd->dma_data; + chan->private = &pcm_dma_data->dma_data; return true; } -static int mxs_dma_alloc(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_pcm_runtime *runtime = substream->runtime; - struct mxs_pcm_runtime_data *iprtd = runtime->private_data; - dma_cap_mask_t mask; - - iprtd->dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); - - dma_cap_zero(mask); - dma_cap_set(DMA_SLAVE, mask); - iprtd->dma_data.chan_irq = iprtd->dma_params->chan_irq; - iprtd->dma_chan = dma_request_channel(mask, filter, iprtd); - if (!iprtd->dma_chan) - return -EINVAL; - - return 0; -} - static int snd_mxs_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_pcm_runtime *runtime = substream->runtime; - struct mxs_pcm_runtime_data *iprtd = runtime->private_data; - unsigned long dma_addr; - struct dma_chan *chan; - int ret; - - ret = mxs_dma_alloc(substream, params); - if (ret) - return ret; - chan = iprtd->dma_chan; - - iprtd->size = params_buffer_bytes(params); - iprtd->periods = params_periods(params); - iprtd->period_bytes = params_period_bytes(params); - iprtd->offset = 0; - iprtd->period_time = HZ / (params_rate(params) / - params_period_size(params)); - snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); - dma_addr = runtime->dma_addr; - - iprtd->buf = substream->dma_buffer.area; - - iprtd->desc = chan->device->device_prep_dma_cyclic(chan, dma_addr, - iprtd->period_bytes * iprtd->periods, - iprtd->period_bytes, - substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? - DMA_MEM_TO_DEV : DMA_DEV_TO_MEM); - if (!iprtd->desc) { - dev_err(&chan->dev->device, "cannot prepare slave dma\n"); - return -EINVAL; - } - - iprtd->desc->callback = audio_dma_irq; - iprtd->desc->callback_param = substream; - - return 0; -} - -static int snd_mxs_pcm_hw_free(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct mxs_pcm_runtime_data *iprtd = runtime->private_data; - - if (iprtd->dma_chan) { - dma_release_channel(iprtd->dma_chan); - iprtd->dma_chan = NULL; - } - - return 0; -} - -static int snd_mxs_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct mxs_pcm_runtime_data *iprtd = runtime->private_data; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - dmaengine_submit(iprtd->desc); - - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - dmaengine_terminate_all(iprtd->dma_chan); - - break; - default: - return -EINVAL; - } - return 0; } -static snd_pcm_uframes_t snd_mxs_pcm_pointer( - struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct mxs_pcm_runtime_data *iprtd = runtime->private_data; - - return bytes_to_frames(substream->runtime, iprtd->offset); -} - static int snd_mxs_open(struct snd_pcm_substream *substream) { - struct snd_pcm_runtime *runtime = substream->runtime; - struct mxs_pcm_runtime_data *iprtd; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct mxs_pcm_dma_data *pcm_dma_data; int ret; - iprtd = kzalloc(sizeof(*iprtd), GFP_KERNEL); - if (iprtd == NULL) + pcm_dma_data = kzalloc(sizeof(*pcm_dma_data), GFP_KERNEL); + if (pcm_dma_data == NULL) return -ENOMEM; - runtime->private_data = iprtd; - ret = snd_pcm_hw_constraint_integer(substream->runtime, - SNDRV_PCM_HW_PARAM_PERIODS); - if (ret < 0) { - kfree(iprtd); + pcm_dma_data->dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); + pcm_dma_data->dma_data.chan_irq = pcm_dma_data->dma_params->chan_irq; + + ret = snd_dmaengine_pcm_open(substream, filter, pcm_dma_data); + if (ret) { + kfree(pcm_dma_data); return ret; } snd_soc_set_runtime_hwparams(substream, &snd_mxs_hardware); + snd_dmaengine_pcm_set_data(substream, pcm_dma_data); + return 0; } static int snd_mxs_close(struct snd_pcm_substream *substream) { - struct snd_pcm_runtime *runtime = substream->runtime; - struct mxs_pcm_runtime_data *iprtd = runtime->private_data; + struct mxs_pcm_dma_data *pcm_dma_data = snd_dmaengine_pcm_get_data(substream); - kfree(iprtd); + snd_dmaengine_pcm_close(substream); + kfree(pcm_dma_data); return 0; } @@ -244,9 +140,8 @@ static struct snd_pcm_ops mxs_pcm_ops = { .close = snd_mxs_close, .ioctl = snd_pcm_lib_ioctl, .hw_params = snd_mxs_pcm_hw_params, - .hw_free = snd_mxs_pcm_hw_free, - .trigger = snd_mxs_pcm_trigger, - .pointer = snd_mxs_pcm_pointer, + .trigger = snd_dmaengine_pcm_trigger, + .pointer = snd_dmaengine_pcm_pointer, .mmap = snd_mxs_pcm_mmap, }; diff --git a/sound/soc/mxs/mxs-pcm.h b/sound/soc/mxs/mxs-pcm.h index f55ac4f7a76..5f01a9124b3 100644 --- a/sound/soc/mxs/mxs-pcm.h +++ b/sound/soc/mxs/mxs-pcm.h @@ -19,25 +19,9 @@ #ifndef _MXS_PCM_H #define _MXS_PCM_H -#include <mach/dma.h> - struct mxs_pcm_dma_params { int chan_irq; int chan_num; }; -struct mxs_pcm_runtime_data { - int period_bytes; - int periods; - int dma; - unsigned long offset; - unsigned long size; - void *buf; - int period_time; - struct dma_async_tx_descriptor *desc; - struct dma_chan *dma_chan; - struct mxs_dma_data dma_data; - struct mxs_pcm_dma_params *dma_params; -}; - #endif diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c index f204dbac11d..12be05b1688 100644 --- a/sound/soc/mxs/mxs-saif.c +++ b/sound/soc/mxs/mxs-saif.c @@ -630,7 +630,7 @@ static int mxs_saif_probe(struct platform_device *pdev) if (pdev->id >= ARRAY_SIZE(mxs_saif)) return -EINVAL; - saif = kzalloc(sizeof(*saif), GFP_KERNEL); + saif = devm_kzalloc(&pdev->dev, sizeof(*saif), GFP_KERNEL); if (!saif) return -ENOMEM; @@ -655,29 +655,16 @@ static int mxs_saif_probe(struct platform_device *pdev) ret = PTR_ERR(saif->clk); dev_err(&pdev->dev, "Cannot get the clock: %d\n", ret); - goto failed_clk; + return ret; } iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!iores) { - ret = -ENODEV; - dev_err(&pdev->dev, "failed to get io resource: %d\n", - ret); - goto failed_get_resource; - } - if (!request_mem_region(iores->start, resource_size(iores), - "mxs-saif")) { - dev_err(&pdev->dev, "request_mem_region failed\n"); - ret = -EBUSY; - goto failed_get_resource; - } - - saif->base = ioremap(iores->start, resource_size(iores)); + saif->base = devm_request_and_ioremap(&pdev->dev, iores); if (!saif->base) { dev_err(&pdev->dev, "ioremap failed\n"); ret = -ENODEV; - goto failed_ioremap; + goto failed_get_resource; } dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0); @@ -685,7 +672,7 @@ static int mxs_saif_probe(struct platform_device *pdev) ret = -ENODEV; dev_err(&pdev->dev, "failed to get dma resource: %d\n", ret); - goto failed_ioremap; + goto failed_get_resource; } saif->dma_param.chan_num = dmares->start; @@ -694,14 +681,15 @@ static int mxs_saif_probe(struct platform_device *pdev) ret = saif->irq; dev_err(&pdev->dev, "failed to get irq resource: %d\n", ret); - goto failed_get_irq1; + goto failed_get_resource; } saif->dev = &pdev->dev; - ret = request_irq(saif->irq, mxs_saif_irq, 0, "mxs-saif", saif); + ret = devm_request_irq(&pdev->dev, saif->irq, mxs_saif_irq, 0, + "mxs-saif", saif); if (ret) { dev_err(&pdev->dev, "failed to request irq\n"); - goto failed_get_irq1; + goto failed_get_resource; } saif->dma_param.chan_irq = platform_get_irq(pdev, 1); @@ -709,7 +697,7 @@ static int mxs_saif_probe(struct platform_device *pdev) ret = saif->dma_param.chan_irq; dev_err(&pdev->dev, "failed to get dma irq resource: %d\n", ret); - goto failed_get_irq2; + goto failed_get_resource; } platform_set_drvdata(pdev, saif); @@ -717,7 +705,7 @@ static int mxs_saif_probe(struct platform_device *pdev) ret = snd_soc_register_dai(&pdev->dev, &mxs_saif_dai); if (ret) { dev_err(&pdev->dev, "register DAI failed\n"); - goto failed_register; + goto failed_get_resource; } saif->soc_platform_pdev = platform_device_alloc( @@ -740,36 +728,19 @@ failed_pdev_add: platform_device_put(saif->soc_platform_pdev); failed_pdev_alloc: snd_soc_unregister_dai(&pdev->dev); -failed_register: -failed_get_irq2: - free_irq(saif->irq, saif); -failed_get_irq1: - iounmap(saif->base); -failed_ioremap: - release_mem_region(iores->start, resource_size(iores)); failed_get_resource: clk_put(saif->clk); -failed_clk: - kfree(saif); return ret; } static int __devexit mxs_saif_remove(struct platform_device *pdev) { - struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); struct mxs_saif *saif = platform_get_drvdata(pdev); platform_device_unregister(saif->soc_platform_pdev); - snd_soc_unregister_dai(&pdev->dev); - - iounmap(saif->base); - release_mem_region(res->start, resource_size(res)); - free_irq(saif->irq, saif); - clk_put(saif->clk); - kfree(saif); return 0; } |