summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars-Peter Clausen <lars@metafoo.de>2012-02-22 10:49:06 +0100
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-02-22 13:21:49 +0000
commit4564d10f3066a1abf5053936684e2c8495163def (patch)
tree622912c7aeb3b2aa1a8264954a355c3ea833ae9f
parent91a38540f504cdde7cb62668f7a6d52e3bd0178b (diff)
downloadblackbird-op-linux-4564d10f3066a1abf5053936684e2c8495163def.tar.gz
blackbird-op-linux-4564d10f3066a1abf5053936684e2c8495163def.zip
ASoC: imx-pcm: Request DMA channel early
Request the DMA channel in the pcm open callback. This allows us to let open fail if there is no dma channel available. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Tested-by: Shawn Guo <shawn.guo@linaro.org> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-rw-r--r--sound/soc/imx/imx-pcm-dma-mx2.c78
1 files changed, 32 insertions, 46 deletions
diff --git a/sound/soc/imx/imx-pcm-dma-mx2.c b/sound/soc/imx/imx-pcm-dma-mx2.c
index ec1394415526..f974e61fa68c 100644
--- a/sound/soc/imx/imx-pcm-dma-mx2.c
+++ b/sound/soc/imx/imx-pcm-dma-mx2.c
@@ -65,17 +65,13 @@ static bool filter(struct dma_chan *chan, void *param)
return true;
}
-static int imx_ssi_dma_alloc(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+static int imx_ssi_dma_alloc(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct imx_pcm_dma_params *dma_params;
struct snd_pcm_runtime *runtime = substream->runtime;
struct imx_pcm_runtime_data *iprtd = runtime->private_data;
- struct dma_slave_config slave_config;
dma_cap_mask_t mask;
- enum dma_slave_buswidth buswidth;
- int ret;
dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
@@ -84,13 +80,29 @@ static int imx_ssi_dma_alloc(struct snd_pcm_substream *substream,
iprtd->dma_data.dma_request = dma_params->dma;
/* Try to grab a DMA channel */
- if (!iprtd->dma_chan) {
- dma_cap_zero(mask);
- dma_cap_set(DMA_SLAVE, mask);
- iprtd->dma_chan = dma_request_channel(mask, filter, iprtd);
- if (!iprtd->dma_chan)
- return -EINVAL;
- }
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+ iprtd->dma_chan = dma_request_channel(mask, filter, iprtd);
+ if (!iprtd->dma_chan)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int snd_imx_pcm_hw_params(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 imx_pcm_runtime_data *iprtd = runtime->private_data;
+ struct dma_chan *chan = iprtd->dma_chan;
+ struct imx_pcm_dma_params *dma_params;
+ struct dma_slave_config slave_config;
+ enum dma_slave_buswidth buswidth;
+ unsigned long dma_addr;
+ int ret;
+
+ dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
@@ -116,29 +128,10 @@ static int imx_ssi_dma_alloc(struct snd_pcm_substream *substream,
slave_config.src_maxburst = dma_params->burstsize;
}
- ret = dmaengine_slave_config(iprtd->dma_chan, &slave_config);
+ ret = dmaengine_slave_config(chan, &slave_config);
if (ret)
return ret;
- return 0;
-}
-
-static int snd_imx_pcm_hw_params(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 imx_pcm_runtime_data *iprtd = runtime->private_data;
- unsigned long dma_addr;
- struct dma_chan *chan;
- struct imx_pcm_dma_params *dma_params;
- int ret;
-
- dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
- ret = imx_ssi_dma_alloc(substream, params);
- if (ret)
- return ret;
- chan = iprtd->dma_chan;
iprtd->periods = params_periods(params);
iprtd->period_bytes = params_period_bytes(params);
@@ -164,19 +157,6 @@ static int snd_imx_pcm_hw_params(struct snd_pcm_substream *substream,
return 0;
}
-static int snd_imx_pcm_hw_free(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct imx_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_imx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{
struct snd_pcm_runtime *runtime = substream->runtime;
@@ -251,6 +231,12 @@ static int snd_imx_open(struct snd_pcm_substream *substream)
return ret;
}
+ ret = imx_ssi_dma_alloc(substream);
+ if (ret < 0) {
+ kfree(iprtd);
+ return ret;
+ }
+
snd_soc_set_runtime_hwparams(substream, &snd_imx_hardware);
return 0;
@@ -261,6 +247,7 @@ static int snd_imx_close(struct snd_pcm_substream *substream)
struct snd_pcm_runtime *runtime = substream->runtime;
struct imx_pcm_runtime_data *iprtd = runtime->private_data;
+ dma_release_channel(iprtd->dma_chan);
kfree(iprtd);
return 0;
@@ -271,7 +258,6 @@ static struct snd_pcm_ops imx_pcm_ops = {
.close = snd_imx_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = snd_imx_pcm_hw_params,
- .hw_free = snd_imx_pcm_hw_free,
.trigger = snd_imx_pcm_trigger,
.pointer = snd_imx_pcm_pointer,
.mmap = snd_imx_pcm_mmap,
OpenPOWER on IntegriCloud