diff options
author | Lars-Peter Clausen <lars@metafoo.de> | 2012-02-22 04:49:10 -0500 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-03-02 08:47:36 -0500 |
commit | 016ab467aa53639d68b03386885c481b8761018e (patch) | |
tree | 22bf7880379787e5fce791139197a279478081bf /sound/soc/mxs | |
parent | c307e8e32e11aae0f561db02898a090c9b7c9b70 (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/Kconfig | 1 | ||||
-rw-r--r-- | sound/soc/mxs/mxs-pcm.c | 136 | ||||
-rw-r--r-- | sound/soc/mxs/mxs-pcm.h | 12 |
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 @@ | |||
1 | menuconfig SND_MXS_SOC | 1 | menuconfig 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 | ||
42 | struct mxs_pcm_dma_data { | ||
43 | struct mxs_dma_data dma_data; | ||
44 | struct mxs_pcm_dma_params *dma_params; | ||
45 | }; | ||
46 | |||
41 | static struct snd_pcm_hardware snd_mxs_hardware = { | 47 | static 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 | ||
61 | static 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 | |||
72 | static bool filter(struct dma_chan *chan, void *param) | 67 | static 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 | ||
88 | static 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 | |||
107 | static int snd_mxs_pcm_hw_params(struct snd_pcm_substream *substream, | 83 | static 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 | ||
141 | static 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 | |||
166 | static 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 | |||
175 | static int snd_mxs_open(struct snd_pcm_substream *substream) | 91 | static 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 | ||
204 | static int snd_mxs_close(struct snd_pcm_substream *substream) | 117 | static 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 | |||
24 | struct mxs_pcm_dma_params { | 22 | struct mxs_pcm_dma_params { |
25 | int chan_irq; | 23 | int chan_irq; |
26 | int chan_num; | 24 | int chan_num; |
27 | }; | 25 | }; |
28 | 26 | ||
29 | struct 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 |