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>
This commit is contained in:
Lars-Peter Clausen 2012-02-22 10:49:06 +01:00 committed by Mark Brown
parent 91a38540f5
commit 4564d10f30
1 changed files with 32 additions and 46 deletions

View File

@ -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,