aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/mxs
diff options
context:
space:
mode:
authorLars-Peter Clausen <lars@metafoo.de>2012-02-22 04:49:10 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-03-02 08:47:36 -0500
commit016ab467aa53639d68b03386885c481b8761018e (patch)
tree22bf7880379787e5fce791139197a279478081bf /sound/soc/mxs
parentc307e8e32e11aae0f561db02898a090c9b7c9b70 (diff)
ASoC: mxs-pcm: Use dmaengine PCM helper functions
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Tested-by: Shawn Guo <shawn.guo@linaro.org> Acked-by: Vinod Koul <vinod.koul@linux.intel.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/mxs')
-rw-r--r--sound/soc/mxs/Kconfig1
-rw-r--r--sound/soc/mxs/mxs-pcm.c136
-rw-r--r--sound/soc/mxs/mxs-pcm.h12
3 files changed, 25 insertions, 124 deletions
diff --git a/sound/soc/mxs/Kconfig b/sound/soc/mxs/Kconfig
index 21d20f3e0264..99a997f19bb9 100644
--- a/sound/soc/mxs/Kconfig
+++ b/sound/soc/mxs/Kconfig
@@ -1,6 +1,7 @@
1menuconfig SND_MXS_SOC 1menuconfig SND_MXS_SOC
2 tristate "SoC Audio for Freescale MXS CPUs" 2 tristate "SoC Audio for Freescale MXS CPUs"
3 depends on ARCH_MXS 3 depends on ARCH_MXS
4 select SND_SOC_DMAENGINE_PCM
4 help 5 help
5 Say Y or M if you want to add support for codecs attached to 6 Say Y or M if you want to add support for codecs attached to
6 the MXS SAIF interface. 7 the MXS SAIF interface.
diff --git a/sound/soc/mxs/mxs-pcm.c b/sound/soc/mxs/mxs-pcm.c
index 5b8c8d314060..6ca1f46d84a4 100644
--- a/sound/soc/mxs/mxs-pcm.c
+++ b/sound/soc/mxs/mxs-pcm.c
@@ -34,10 +34,16 @@
34#include <sound/pcm.h> 34#include <sound/pcm.h>
35#include <sound/pcm_params.h> 35#include <sound/pcm_params.h>
36#include <sound/soc.h> 36#include <sound/soc.h>
37#include <sound/dmaengine_pcm.h>
37 38
38#include <mach/dma.h> 39#include <mach/dma.h>
39#include "mxs-pcm.h" 40#include "mxs-pcm.h"
40 41
42struct mxs_pcm_dma_data {
43 struct mxs_dma_data dma_data;
44 struct mxs_pcm_dma_params *dma_params;
45};
46
41static struct snd_pcm_hardware snd_mxs_hardware = { 47static struct snd_pcm_hardware snd_mxs_hardware = {
42 .info = SNDRV_PCM_INFO_MMAP | 48 .info = SNDRV_PCM_INFO_MMAP |
43 SNDRV_PCM_INFO_MMAP_VALID | 49 SNDRV_PCM_INFO_MMAP_VALID |
@@ -58,21 +64,10 @@ static struct snd_pcm_hardware snd_mxs_hardware = {
58 64
59}; 65};
60 66
61static void audio_dma_irq(void *data)
62{
63 struct snd_pcm_substream *substream = (struct snd_pcm_substream *)data;
64 struct snd_pcm_runtime *runtime = substream->runtime;
65 struct mxs_pcm_runtime_data *iprtd = runtime->private_data;
66
67 iprtd->offset += iprtd->period_bytes;
68 iprtd->offset %= iprtd->period_bytes * iprtd->periods;
69 snd_pcm_period_elapsed(substream);
70}
71
72static bool filter(struct dma_chan *chan, void *param) 67static bool filter(struct dma_chan *chan, void *param)
73{ 68{
74 struct mxs_pcm_runtime_data *iprtd = param; 69 struct mxs_pcm_dma_data *pcm_dma_data = param;
75 struct mxs_pcm_dma_params *dma_params = iprtd->dma_params; 70 struct mxs_pcm_dma_params *dma_params = pcm_dma_data->dma_params;
76 71
77 if (!mxs_dma_is_apbx(chan)) 72 if (!mxs_dma_is_apbx(chan))
78 return false; 73 return false;
@@ -80,134 +75,51 @@ static bool filter(struct dma_chan *chan, void *param)
80 if (chan->chan_id != dma_params->chan_num) 75 if (chan->chan_id != dma_params->chan_num)
81 return false; 76 return false;
82 77
83 chan->private = &iprtd->dma_data; 78 chan->private = &pcm_dma_data->dma_data;
84 79
85 return true; 80 return true;
86} 81}
87 82
88static int mxs_dma_alloc(struct snd_pcm_substream *substream)
89{
90 struct snd_soc_pcm_runtime *rtd = substream->private_data;
91 struct snd_pcm_runtime *runtime = substream->runtime;
92 struct mxs_pcm_runtime_data *iprtd = runtime->private_data;
93 dma_cap_mask_t mask;
94
95 iprtd->dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
96
97 dma_cap_zero(mask);
98 dma_cap_set(DMA_SLAVE, mask);
99 iprtd->dma_data.chan_irq = iprtd->dma_params->chan_irq;
100 iprtd->dma_chan = dma_request_channel(mask, filter, iprtd);
101 if (!iprtd->dma_chan)
102 return -EINVAL;
103
104 return 0;
105}
106
107static int snd_mxs_pcm_hw_params(struct snd_pcm_substream *substream, 83static int snd_mxs_pcm_hw_params(struct snd_pcm_substream *substream,
108 struct snd_pcm_hw_params *params) 84 struct snd_pcm_hw_params *params)
109{ 85{
110 struct snd_pcm_runtime *runtime = substream->runtime;
111 struct mxs_pcm_runtime_data *iprtd = runtime->private_data;
112 unsigned long dma_addr;
113 struct dma_chan *chan;
114
115 chan = iprtd->dma_chan;
116
117 iprtd->periods = params_periods(params);
118 iprtd->period_bytes = params_period_bytes(params);
119 iprtd->offset = 0;
120
121 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); 86 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
122 87
123 dma_addr = runtime->dma_addr;
124
125 iprtd->desc = chan->device->device_prep_dma_cyclic(chan, dma_addr,
126 iprtd->period_bytes * iprtd->periods,
127 iprtd->period_bytes,
128 substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
129 DMA_MEM_TO_DEV : DMA_DEV_TO_MEM);
130 if (!iprtd->desc) {
131 dev_err(&chan->dev->device, "cannot prepare slave dma\n");
132 return -EINVAL;
133 }
134
135 iprtd->desc->callback = audio_dma_irq;
136 iprtd->desc->callback_param = substream;
137
138 return 0; 88 return 0;
139} 89}
140 90
141static int snd_mxs_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
142{
143 struct snd_pcm_runtime *runtime = substream->runtime;
144 struct mxs_pcm_runtime_data *iprtd = runtime->private_data;
145
146 switch (cmd) {
147 case SNDRV_PCM_TRIGGER_START:
148 case SNDRV_PCM_TRIGGER_RESUME:
149 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
150 dmaengine_submit(iprtd->desc);
151
152 break;
153 case SNDRV_PCM_TRIGGER_STOP:
154 case SNDRV_PCM_TRIGGER_SUSPEND:
155 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
156 dmaengine_terminate_all(iprtd->dma_chan);
157
158 break;
159 default:
160 return -EINVAL;
161 }
162
163 return 0;
164}
165
166static snd_pcm_uframes_t snd_mxs_pcm_pointer(
167 struct snd_pcm_substream *substream)
168{
169 struct snd_pcm_runtime *runtime = substream->runtime;
170 struct mxs_pcm_runtime_data *iprtd = runtime->private_data;
171
172 return bytes_to_frames(substream->runtime, iprtd->offset);
173}
174
175static int snd_mxs_open(struct snd_pcm_substream *substream) 91static int snd_mxs_open(struct snd_pcm_substream *substream)
176{ 92{
177 struct snd_pcm_runtime *runtime = substream->runtime; 93 struct snd_soc_pcm_runtime *rtd = substream->private_data;
178 struct mxs_pcm_runtime_data *iprtd; 94 struct mxs_pcm_dma_data *pcm_dma_data;
179 int ret; 95 int ret;
180 96
181 iprtd = kzalloc(sizeof(*iprtd), GFP_KERNEL); 97 pcm_dma_data = kzalloc(sizeof(*pcm_dma_data), GFP_KERNEL);
182 if (iprtd == NULL) 98 if (pcm_dma_data == NULL)
183 return -ENOMEM; 99 return -ENOMEM;
184 runtime->private_data = iprtd;
185 100
186 ret = snd_pcm_hw_constraint_integer(substream->runtime, 101 pcm_dma_data->dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
187 SNDRV_PCM_HW_PARAM_PERIODS); 102 pcm_dma_data->dma_data.chan_irq = pcm_dma_data->dma_params->chan_irq;
188 if (ret < 0) {
189 kfree(iprtd);
190 return ret;
191 }
192 103
193 ret = mxs_dma_alloc(substream); 104 ret = snd_dmaengine_pcm_open(substream, filter, pcm_dma_data);
194 if (ret) { 105 if (ret) {
195 kfree(iprtd); 106 kfree(pcm_dma_data);
196 return ret; 107 return ret;
197 } 108 }
198 109
199 snd_soc_set_runtime_hwparams(substream, &snd_mxs_hardware); 110 snd_soc_set_runtime_hwparams(substream, &snd_mxs_hardware);
200 111
112 snd_dmaengine_pcm_set_data(substream, pcm_dma_data);
113
201 return 0; 114 return 0;
202} 115}
203 116
204static int snd_mxs_close(struct snd_pcm_substream *substream) 117static int snd_mxs_close(struct snd_pcm_substream *substream)
205{ 118{
206 struct snd_pcm_runtime *runtime = substream->runtime; 119 struct mxs_pcm_dma_data *pcm_dma_data = snd_dmaengine_pcm_get_data(substream);
207 struct mxs_pcm_runtime_data *iprtd = runtime->private_data;
208 120
209 dma_release_channel(iprtd->dma_chan); 121 snd_dmaengine_pcm_close(substream);
210 kfree(iprtd); 122 kfree(pcm_dma_data);
211 123
212 return 0; 124 return 0;
213} 125}
@@ -228,8 +140,8 @@ static struct snd_pcm_ops mxs_pcm_ops = {
228 .close = snd_mxs_close, 140 .close = snd_mxs_close,
229 .ioctl = snd_pcm_lib_ioctl, 141 .ioctl = snd_pcm_lib_ioctl,
230 .hw_params = snd_mxs_pcm_hw_params, 142 .hw_params = snd_mxs_pcm_hw_params,
231 .trigger = snd_mxs_pcm_trigger, 143 .trigger = snd_dmaengine_pcm_trigger,
232 .pointer = snd_mxs_pcm_pointer, 144 .pointer = snd_dmaengine_pcm_pointer,
233 .mmap = snd_mxs_pcm_mmap, 145 .mmap = snd_mxs_pcm_mmap,
234}; 146};
235 147
diff --git a/sound/soc/mxs/mxs-pcm.h b/sound/soc/mxs/mxs-pcm.h
index ba75e103bb3b..5f01a9124b3d 100644
--- a/sound/soc/mxs/mxs-pcm.h
+++ b/sound/soc/mxs/mxs-pcm.h
@@ -19,21 +19,9 @@
19#ifndef _MXS_PCM_H 19#ifndef _MXS_PCM_H
20#define _MXS_PCM_H 20#define _MXS_PCM_H
21 21
22#include <mach/dma.h>
23
24struct mxs_pcm_dma_params { 22struct mxs_pcm_dma_params {
25 int chan_irq; 23 int chan_irq;
26 int chan_num; 24 int chan_num;
27}; 25};
28 26
29struct mxs_pcm_runtime_data {
30 int period_bytes;
31 int periods;
32 unsigned long offset;
33 struct dma_async_tx_descriptor *desc;
34 struct dma_chan *dma_chan;
35 struct mxs_dma_data dma_data;
36 struct mxs_pcm_dma_params *dma_params;
37};
38
39#endif 27#endif