diff options
author | Lars-Peter Clausen <lars@metafoo.de> | 2012-02-22 04:49:06 -0500 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-02-22 08:21:49 -0500 |
commit | 4564d10f3066a1abf5053936684e2c8495163def (patch) | |
tree | 622912c7aeb3b2aa1a8264954a355c3ea833ae9f /sound | |
parent | 91a38540f504cdde7cb62668f7a6d52e3bd0178b (diff) |
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>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/imx/imx-pcm-dma-mx2.c | 78 |
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) | |||
65 | return true; | 65 | return true; |
66 | } | 66 | } |
67 | 67 | ||
68 | static int imx_ssi_dma_alloc(struct snd_pcm_substream *substream, | 68 | static int imx_ssi_dma_alloc(struct snd_pcm_substream *substream) |
69 | struct snd_pcm_hw_params *params) | ||
70 | { | 69 | { |
71 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 70 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
72 | struct imx_pcm_dma_params *dma_params; | 71 | struct imx_pcm_dma_params *dma_params; |
73 | struct snd_pcm_runtime *runtime = substream->runtime; | 72 | struct snd_pcm_runtime *runtime = substream->runtime; |
74 | struct imx_pcm_runtime_data *iprtd = runtime->private_data; | 73 | struct imx_pcm_runtime_data *iprtd = runtime->private_data; |
75 | struct dma_slave_config slave_config; | ||
76 | dma_cap_mask_t mask; | 74 | dma_cap_mask_t mask; |
77 | enum dma_slave_buswidth buswidth; | ||
78 | int ret; | ||
79 | 75 | ||
80 | dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | 76 | dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); |
81 | 77 | ||
@@ -84,13 +80,29 @@ static int imx_ssi_dma_alloc(struct snd_pcm_substream *substream, | |||
84 | iprtd->dma_data.dma_request = dma_params->dma; | 80 | iprtd->dma_data.dma_request = dma_params->dma; |
85 | 81 | ||
86 | /* Try to grab a DMA channel */ | 82 | /* Try to grab a DMA channel */ |
87 | if (!iprtd->dma_chan) { | 83 | dma_cap_zero(mask); |
88 | dma_cap_zero(mask); | 84 | dma_cap_set(DMA_SLAVE, mask); |
89 | dma_cap_set(DMA_SLAVE, mask); | 85 | iprtd->dma_chan = dma_request_channel(mask, filter, iprtd); |
90 | iprtd->dma_chan = dma_request_channel(mask, filter, iprtd); | 86 | if (!iprtd->dma_chan) |
91 | if (!iprtd->dma_chan) | 87 | return -EINVAL; |
92 | return -EINVAL; | 88 | |
93 | } | 89 | return 0; |
90 | } | ||
91 | |||
92 | static int snd_imx_pcm_hw_params(struct snd_pcm_substream *substream, | ||
93 | struct snd_pcm_hw_params *params) | ||
94 | { | ||
95 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
96 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
97 | struct imx_pcm_runtime_data *iprtd = runtime->private_data; | ||
98 | struct dma_chan *chan = iprtd->dma_chan; | ||
99 | struct imx_pcm_dma_params *dma_params; | ||
100 | struct dma_slave_config slave_config; | ||
101 | enum dma_slave_buswidth buswidth; | ||
102 | unsigned long dma_addr; | ||
103 | int ret; | ||
104 | |||
105 | dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
94 | 106 | ||
95 | switch (params_format(params)) { | 107 | switch (params_format(params)) { |
96 | case SNDRV_PCM_FORMAT_S16_LE: | 108 | case SNDRV_PCM_FORMAT_S16_LE: |
@@ -116,29 +128,10 @@ static int imx_ssi_dma_alloc(struct snd_pcm_substream *substream, | |||
116 | slave_config.src_maxburst = dma_params->burstsize; | 128 | slave_config.src_maxburst = dma_params->burstsize; |
117 | } | 129 | } |
118 | 130 | ||
119 | ret = dmaengine_slave_config(iprtd->dma_chan, &slave_config); | 131 | ret = dmaengine_slave_config(chan, &slave_config); |
120 | if (ret) | 132 | if (ret) |
121 | return ret; | 133 | return ret; |
122 | 134 | ||
123 | return 0; | ||
124 | } | ||
125 | |||
126 | static int snd_imx_pcm_hw_params(struct snd_pcm_substream *substream, | ||
127 | struct snd_pcm_hw_params *params) | ||
128 | { | ||
129 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
130 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
131 | struct imx_pcm_runtime_data *iprtd = runtime->private_data; | ||
132 | unsigned long dma_addr; | ||
133 | struct dma_chan *chan; | ||
134 | struct imx_pcm_dma_params *dma_params; | ||
135 | int ret; | ||
136 | |||
137 | dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
138 | ret = imx_ssi_dma_alloc(substream, params); | ||
139 | if (ret) | ||
140 | return ret; | ||
141 | chan = iprtd->dma_chan; | ||
142 | 135 | ||
143 | iprtd->periods = params_periods(params); | 136 | iprtd->periods = params_periods(params); |
144 | iprtd->period_bytes = params_period_bytes(params); | 137 | iprtd->period_bytes = params_period_bytes(params); |
@@ -164,19 +157,6 @@ static int snd_imx_pcm_hw_params(struct snd_pcm_substream *substream, | |||
164 | return 0; | 157 | return 0; |
165 | } | 158 | } |
166 | 159 | ||
167 | static int snd_imx_pcm_hw_free(struct snd_pcm_substream *substream) | ||
168 | { | ||
169 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
170 | struct imx_pcm_runtime_data *iprtd = runtime->private_data; | ||
171 | |||
172 | if (iprtd->dma_chan) { | ||
173 | dma_release_channel(iprtd->dma_chan); | ||
174 | iprtd->dma_chan = NULL; | ||
175 | } | ||
176 | |||
177 | return 0; | ||
178 | } | ||
179 | |||
180 | static int snd_imx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | 160 | static int snd_imx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) |
181 | { | 161 | { |
182 | struct snd_pcm_runtime *runtime = substream->runtime; | 162 | struct snd_pcm_runtime *runtime = substream->runtime; |
@@ -251,6 +231,12 @@ static int snd_imx_open(struct snd_pcm_substream *substream) | |||
251 | return ret; | 231 | return ret; |
252 | } | 232 | } |
253 | 233 | ||
234 | ret = imx_ssi_dma_alloc(substream); | ||
235 | if (ret < 0) { | ||
236 | kfree(iprtd); | ||
237 | return ret; | ||
238 | } | ||
239 | |||
254 | snd_soc_set_runtime_hwparams(substream, &snd_imx_hardware); | 240 | snd_soc_set_runtime_hwparams(substream, &snd_imx_hardware); |
255 | 241 | ||
256 | return 0; | 242 | return 0; |
@@ -261,6 +247,7 @@ static int snd_imx_close(struct snd_pcm_substream *substream) | |||
261 | struct snd_pcm_runtime *runtime = substream->runtime; | 247 | struct snd_pcm_runtime *runtime = substream->runtime; |
262 | struct imx_pcm_runtime_data *iprtd = runtime->private_data; | 248 | struct imx_pcm_runtime_data *iprtd = runtime->private_data; |
263 | 249 | ||
250 | dma_release_channel(iprtd->dma_chan); | ||
264 | kfree(iprtd); | 251 | kfree(iprtd); |
265 | 252 | ||
266 | return 0; | 253 | return 0; |
@@ -271,7 +258,6 @@ static struct snd_pcm_ops imx_pcm_ops = { | |||
271 | .close = snd_imx_close, | 258 | .close = snd_imx_close, |
272 | .ioctl = snd_pcm_lib_ioctl, | 259 | .ioctl = snd_pcm_lib_ioctl, |
273 | .hw_params = snd_imx_pcm_hw_params, | 260 | .hw_params = snd_imx_pcm_hw_params, |
274 | .hw_free = snd_imx_pcm_hw_free, | ||
275 | .trigger = snd_imx_pcm_trigger, | 261 | .trigger = snd_imx_pcm_trigger, |
276 | .pointer = snd_imx_pcm_pointer, | 262 | .pointer = snd_imx_pcm_pointer, |
277 | .mmap = snd_imx_pcm_mmap, | 263 | .mmap = snd_imx_pcm_mmap, |