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:
parent
91a38540f5
commit
4564d10f30
1 changed files with 32 additions and 46 deletions
|
@ -65,17 +65,13 @@ static bool filter(struct dma_chan *chan, void *param)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int imx_ssi_dma_alloc(struct snd_pcm_substream *substream,
|
static int imx_ssi_dma_alloc(struct snd_pcm_substream *substream)
|
||||||
struct snd_pcm_hw_params *params)
|
|
||||||
{
|
{
|
||||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||||
struct imx_pcm_dma_params *dma_params;
|
struct imx_pcm_dma_params *dma_params;
|
||||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||||
struct imx_pcm_runtime_data *iprtd = runtime->private_data;
|
struct imx_pcm_runtime_data *iprtd = runtime->private_data;
|
||||||
struct dma_slave_config slave_config;
|
|
||||||
dma_cap_mask_t mask;
|
dma_cap_mask_t mask;
|
||||||
enum dma_slave_buswidth buswidth;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
|
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;
|
iprtd->dma_data.dma_request = dma_params->dma;
|
||||||
|
|
||||||
/* Try to grab a DMA channel */
|
/* Try to grab a DMA channel */
|
||||||
if (!iprtd->dma_chan) {
|
dma_cap_zero(mask);
|
||||||
dma_cap_zero(mask);
|
dma_cap_set(DMA_SLAVE, mask);
|
||||||
dma_cap_set(DMA_SLAVE, mask);
|
iprtd->dma_chan = dma_request_channel(mask, filter, iprtd);
|
||||||
iprtd->dma_chan = dma_request_channel(mask, filter, iprtd);
|
if (!iprtd->dma_chan)
|
||||||
if (!iprtd->dma_chan)
|
return -EINVAL;
|
||||||
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)) {
|
switch (params_format(params)) {
|
||||||
case SNDRV_PCM_FORMAT_S16_LE:
|
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;
|
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)
|
if (ret)
|
||||||
return 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->periods = params_periods(params);
|
||||||
iprtd->period_bytes = params_period_bytes(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;
|
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)
|
static int snd_imx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
|
||||||
{
|
{
|
||||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||||
|
@ -251,6 +231,12 @@ static int snd_imx_open(struct snd_pcm_substream *substream)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = imx_ssi_dma_alloc(substream);
|
||||||
|
if (ret < 0) {
|
||||||
|
kfree(iprtd);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
snd_soc_set_runtime_hwparams(substream, &snd_imx_hardware);
|
snd_soc_set_runtime_hwparams(substream, &snd_imx_hardware);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -261,6 +247,7 @@ static int snd_imx_close(struct snd_pcm_substream *substream)
|
||||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||||
struct imx_pcm_runtime_data *iprtd = runtime->private_data;
|
struct imx_pcm_runtime_data *iprtd = runtime->private_data;
|
||||||
|
|
||||||
|
dma_release_channel(iprtd->dma_chan);
|
||||||
kfree(iprtd);
|
kfree(iprtd);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -271,7 +258,6 @@ static struct snd_pcm_ops imx_pcm_ops = {
|
||||||
.close = snd_imx_close,
|
.close = snd_imx_close,
|
||||||
.ioctl = snd_pcm_lib_ioctl,
|
.ioctl = snd_pcm_lib_ioctl,
|
||||||
.hw_params = snd_imx_pcm_hw_params,
|
.hw_params = snd_imx_pcm_hw_params,
|
||||||
.hw_free = snd_imx_pcm_hw_free,
|
|
||||||
.trigger = snd_imx_pcm_trigger,
|
.trigger = snd_imx_pcm_trigger,
|
||||||
.pointer = snd_imx_pcm_pointer,
|
.pointer = snd_imx_pcm_pointer,
|
||||||
.mmap = snd_imx_pcm_mmap,
|
.mmap = snd_imx_pcm_mmap,
|
||||||
|
|
Loading…
Reference in a new issue