aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/soc-generic-dmaengine-pcm.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2013-04-25 07:02:35 -0400
committerTakashi Iwai <tiwai@suse.de>2013-04-25 07:02:35 -0400
commit2fc565e4eaf8fc633bfc741b90e1f28dba732ee1 (patch)
tree98c994692f84aee07cf1c7b4cda245ae5235a94d /sound/soc/soc-generic-dmaengine-pcm.c
parent7fc7d047216aa4923d401c637be2ebc6e3d5bd9b (diff)
parent5cc50fc858a5ab37dc2744d72d7ffed96f23afd8 (diff)
Merge tag 'asoc-v3.10-3' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-next
ASoC: More updates for v3.10 A few more fixes, nothing too major though the DMA changes fix modular builds.
Diffstat (limited to 'sound/soc/soc-generic-dmaengine-pcm.c')
-rw-r--r--sound/soc/soc-generic-dmaengine-pcm.c44
1 files changed, 30 insertions, 14 deletions
diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c
index ae0c37e66ae0..e29ec3cd84b1 100644
--- a/sound/soc/soc-generic-dmaengine-pcm.c
+++ b/sound/soc/soc-generic-dmaengine-pcm.c
@@ -21,7 +21,6 @@
21#include <sound/soc.h> 21#include <sound/soc.h>
22#include <linux/dma-mapping.h> 22#include <linux/dma-mapping.h>
23#include <linux/of.h> 23#include <linux/of.h>
24#include <linux/of_dma.h>
25 24
26#include <sound/dmaengine_pcm.h> 25#include <sound/dmaengine_pcm.h>
27 26
@@ -29,7 +28,7 @@ struct dmaengine_pcm {
29 struct dma_chan *chan[SNDRV_PCM_STREAM_CAPTURE + 1]; 28 struct dma_chan *chan[SNDRV_PCM_STREAM_CAPTURE + 1];
30 const struct snd_dmaengine_pcm_config *config; 29 const struct snd_dmaengine_pcm_config *config;
31 struct snd_soc_platform platform; 30 struct snd_soc_platform platform;
32 bool compat; 31 unsigned int flags;
33}; 32};
34 33
35static struct dmaengine_pcm *soc_platform_to_pcm(struct snd_soc_platform *p) 34static struct dmaengine_pcm *soc_platform_to_pcm(struct snd_soc_platform *p)
@@ -128,6 +127,9 @@ static struct dma_chan *dmaengine_pcm_compat_request_channel(
128{ 127{
129 struct dmaengine_pcm *pcm = soc_platform_to_pcm(rtd->platform); 128 struct dmaengine_pcm *pcm = soc_platform_to_pcm(rtd->platform);
130 129
130 if ((pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX) && pcm->chan[0])
131 return pcm->chan[0];
132
131 if (pcm->config->compat_request_channel) 133 if (pcm->config->compat_request_channel)
132 return pcm->config->compat_request_channel(rtd, substream); 134 return pcm->config->compat_request_channel(rtd, substream);
133 135
@@ -148,7 +150,7 @@ static int dmaengine_pcm_new(struct snd_soc_pcm_runtime *rtd)
148 if (!substream) 150 if (!substream)
149 continue; 151 continue;
150 152
151 if (!pcm->chan[i] && pcm->compat) { 153 if (!pcm->chan[i] && (pcm->flags & SND_DMAENGINE_PCM_FLAG_COMPAT)) {
152 pcm->chan[i] = dmaengine_pcm_compat_request_channel(rtd, 154 pcm->chan[i] = dmaengine_pcm_compat_request_channel(rtd,
153 substream); 155 substream);
154 } 156 }
@@ -215,6 +217,25 @@ static const char * const dmaengine_pcm_dma_channel_names[] = {
215 [SNDRV_PCM_STREAM_CAPTURE] = "rx", 217 [SNDRV_PCM_STREAM_CAPTURE] = "rx",
216}; 218};
217 219
220static void dmaengine_pcm_request_chan_of(struct dmaengine_pcm *pcm,
221 struct device *dev)
222{
223 unsigned int i;
224
225 if ((pcm->flags & SND_DMAENGINE_PCM_FLAG_NO_DT) || !dev->of_node)
226 return;
227
228 if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX) {
229 pcm->chan[0] = dma_request_slave_channel(dev, "rx-tx");
230 pcm->chan[1] = pcm->chan[0];
231 } else {
232 for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE; i++) {
233 pcm->chan[i] = dma_request_slave_channel(dev,
234 dmaengine_pcm_dma_channel_names[i]);
235 }
236 }
237}
238
218/** 239/**
219 * snd_dmaengine_pcm_register - Register a dmaengine based PCM device 240 * snd_dmaengine_pcm_register - Register a dmaengine based PCM device
220 * @dev: The parent device for the PCM device 241 * @dev: The parent device for the PCM device
@@ -225,23 +246,15 @@ int snd_dmaengine_pcm_register(struct device *dev,
225 const struct snd_dmaengine_pcm_config *config, unsigned int flags) 246 const struct snd_dmaengine_pcm_config *config, unsigned int flags)
226{ 247{
227 struct dmaengine_pcm *pcm; 248 struct dmaengine_pcm *pcm;
228 unsigned int i;
229 249
230 pcm = kzalloc(sizeof(*pcm), GFP_KERNEL); 250 pcm = kzalloc(sizeof(*pcm), GFP_KERNEL);
231 if (!pcm) 251 if (!pcm)
232 return -ENOMEM; 252 return -ENOMEM;
233 253
234 pcm->config = config; 254 pcm->config = config;
255 pcm->flags = flags;
235 256
236 if (flags & SND_DMAENGINE_PCM_FLAG_COMPAT) 257 dmaengine_pcm_request_chan_of(pcm, dev);
237 pcm->compat = true;
238
239 if (!(flags & SND_DMAENGINE_PCM_FLAG_NO_DT) && dev->of_node) {
240 for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE; i++) {
241 pcm->chan[i] = of_dma_request_slave_channel(dev->of_node,
242 dmaengine_pcm_dma_channel_names[i]);
243 }
244 }
245 258
246 if (flags & SND_DMAENGINE_PCM_FLAG_NO_RESIDUE) 259 if (flags & SND_DMAENGINE_PCM_FLAG_NO_RESIDUE)
247 return snd_soc_add_platform(dev, &pcm->platform, 260 return snd_soc_add_platform(dev, &pcm->platform,
@@ -272,8 +285,11 @@ void snd_dmaengine_pcm_unregister(struct device *dev)
272 pcm = soc_platform_to_pcm(platform); 285 pcm = soc_platform_to_pcm(platform);
273 286
274 for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE; i++) { 287 for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE; i++) {
275 if (pcm->chan[i]) 288 if (pcm->chan[i]) {
276 dma_release_channel(pcm->chan[i]); 289 dma_release_channel(pcm->chan[i]);
290 if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX)
291 break;
292 }
277 } 293 }
278 294
279 snd_soc_remove_platform(platform); 295 snd_soc_remove_platform(platform);