aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/imx
diff options
context:
space:
mode:
authorLars-Peter Clausen <lars@metafoo.de>2012-02-22 04:49:09 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-03-02 08:47:30 -0500
commitc307e8e32e11aae0f561db02898a090c9b7c9b70 (patch)
treec8ff0cda603e6681bf4489f079c2f4b0f45a1bd9 /sound/soc/imx
parente7f73a1613567ac82314f33956c0f3810bf1efb2 (diff)
ASoC: imx-pcm-dma: 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/imx')
-rw-r--r--sound/soc/imx/Kconfig1
-rw-r--r--sound/soc/imx/imx-pcm-dma-mx2.c176
2 files changed, 28 insertions, 149 deletions
diff --git a/sound/soc/imx/Kconfig b/sound/soc/imx/Kconfig
index e89139ffbce1..192861c2b4af 100644
--- a/sound/soc/imx/Kconfig
+++ b/sound/soc/imx/Kconfig
@@ -14,6 +14,7 @@ config SND_MXC_SOC_FIQ
14 tristate 14 tristate
15 15
16config SND_MXC_SOC_MX2 16config SND_MXC_SOC_MX2
17 select SND_SOC_DMAENGINE_PCM
17 tristate 18 tristate
18 19
19config SND_MXC_SOC_WM1133_EV1 20config SND_MXC_SOC_WM1133_EV1
diff --git a/sound/soc/imx/imx-pcm-dma-mx2.c b/sound/soc/imx/imx-pcm-dma-mx2.c
index f974e61fa68c..4cd5462049bc 100644
--- a/sound/soc/imx/imx-pcm-dma-mx2.c
+++ b/sound/soc/imx/imx-pcm-dma-mx2.c
@@ -27,104 +27,42 @@
27#include <sound/pcm.h> 27#include <sound/pcm.h>
28#include <sound/pcm_params.h> 28#include <sound/pcm_params.h>
29#include <sound/soc.h> 29#include <sound/soc.h>
30#include <sound/dmaengine_pcm.h>
30 31
31#include <mach/dma.h> 32#include <mach/dma.h>
32 33
33#include "imx-ssi.h" 34#include "imx-ssi.h"
34 35
35struct imx_pcm_runtime_data {
36 int period_bytes;
37 int periods;
38 unsigned long offset;
39 struct dma_async_tx_descriptor *desc;
40 struct dma_chan *dma_chan;
41 struct imx_dma_data dma_data;
42};
43
44static void audio_dma_irq(void *data)
45{
46 struct snd_pcm_substream *substream = (struct snd_pcm_substream *)data;
47 struct snd_pcm_runtime *runtime = substream->runtime;
48 struct imx_pcm_runtime_data *iprtd = runtime->private_data;
49
50 iprtd->offset += iprtd->period_bytes;
51 iprtd->offset %= iprtd->period_bytes * iprtd->periods;
52
53 snd_pcm_period_elapsed(substream);
54}
55
56static bool filter(struct dma_chan *chan, void *param) 36static bool filter(struct dma_chan *chan, void *param)
57{ 37{
58 struct imx_pcm_runtime_data *iprtd = param;
59
60 if (!imx_dma_is_general_purpose(chan)) 38 if (!imx_dma_is_general_purpose(chan))
61 return false; 39 return false;
62 40
63 chan->private = &iprtd->dma_data; 41 chan->private = param;
64 42
65 return true; 43 return true;
66}
67
68static int imx_ssi_dma_alloc(struct snd_pcm_substream *substream)
69{
70 struct snd_soc_pcm_runtime *rtd = substream->private_data;
71 struct imx_pcm_dma_params *dma_params;
72 struct snd_pcm_runtime *runtime = substream->runtime;
73 struct imx_pcm_runtime_data *iprtd = runtime->private_data;
74 dma_cap_mask_t mask;
75
76 dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
77
78 iprtd->dma_data.peripheral_type = IMX_DMATYPE_SSI;
79 iprtd->dma_data.priority = DMA_PRIO_HIGH;
80 iprtd->dma_data.dma_request = dma_params->dma;
81
82 /* Try to grab a DMA channel */
83 dma_cap_zero(mask);
84 dma_cap_set(DMA_SLAVE, mask);
85 iprtd->dma_chan = dma_request_channel(mask, filter, iprtd);
86 if (!iprtd->dma_chan)
87 return -EINVAL;
88
89 return 0;
90} 44}
91 45
92static int snd_imx_pcm_hw_params(struct snd_pcm_substream *substream, 46static int snd_imx_pcm_hw_params(struct snd_pcm_substream *substream,
93 struct snd_pcm_hw_params *params) 47 struct snd_pcm_hw_params *params)
94{ 48{
95 struct snd_soc_pcm_runtime *rtd = substream->private_data; 49 struct snd_soc_pcm_runtime *rtd = substream->private_data;
96 struct snd_pcm_runtime *runtime = substream->runtime; 50 struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream);
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; 51 struct imx_pcm_dma_params *dma_params;
100 struct dma_slave_config slave_config; 52 struct dma_slave_config slave_config;
101 enum dma_slave_buswidth buswidth;
102 unsigned long dma_addr;
103 int ret; 53 int ret;
104 54
105 dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); 55 dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
106 56
107 switch (params_format(params)) { 57 ret = snd_hwparams_to_dma_slave_config(substream, params, &slave_config);
108 case SNDRV_PCM_FORMAT_S16_LE: 58 if (ret)
109 buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES; 59 return ret;
110 break;
111 case SNDRV_PCM_FORMAT_S20_3LE:
112 case SNDRV_PCM_FORMAT_S24_LE:
113 buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
114 break;
115 default:
116 return 0;
117 }
118 60
119 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 61 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
120 slave_config.direction = DMA_MEM_TO_DEV;
121 slave_config.dst_addr = dma_params->dma_addr; 62 slave_config.dst_addr = dma_params->dma_addr;
122 slave_config.dst_addr_width = buswidth;
123 slave_config.dst_maxburst = dma_params->burstsize; 63 slave_config.dst_maxburst = dma_params->burstsize;
124 } else { 64 } else {
125 slave_config.direction = DMA_DEV_TO_MEM;
126 slave_config.src_addr = dma_params->dma_addr; 65 slave_config.src_addr = dma_params->dma_addr;
127 slave_config.src_addr_width = buswidth;
128 slave_config.src_maxburst = dma_params->burstsize; 66 slave_config.src_maxburst = dma_params->burstsize;
129 } 67 }
130 68
@@ -132,68 +70,11 @@ static int snd_imx_pcm_hw_params(struct snd_pcm_substream *substream,
132 if (ret) 70 if (ret)
133 return ret; 71 return ret;
134 72
135
136 iprtd->periods = params_periods(params);
137 iprtd->period_bytes = params_period_bytes(params);
138 iprtd->offset = 0;
139
140 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); 73 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
141 74
142 dma_addr = runtime->dma_addr;
143
144 iprtd->desc = chan->device->device_prep_dma_cyclic(chan, dma_addr,
145 iprtd->period_bytes * iprtd->periods,
146 iprtd->period_bytes,
147 substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
148 DMA_MEM_TO_DEV : DMA_DEV_TO_MEM);
149 if (!iprtd->desc) {
150 dev_err(&chan->dev->device, "cannot prepare slave dma\n");
151 return -EINVAL;
152 }
153
154 iprtd->desc->callback = audio_dma_irq;
155 iprtd->desc->callback_param = substream;
156
157 return 0;
158}
159
160static int snd_imx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
161{
162 struct snd_pcm_runtime *runtime = substream->runtime;
163 struct imx_pcm_runtime_data *iprtd = runtime->private_data;
164
165 switch (cmd) {
166 case SNDRV_PCM_TRIGGER_START:
167 case SNDRV_PCM_TRIGGER_RESUME:
168 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
169 dmaengine_submit(iprtd->desc);
170
171 break;
172
173 case SNDRV_PCM_TRIGGER_STOP:
174 case SNDRV_PCM_TRIGGER_SUSPEND:
175 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
176 dmaengine_terminate_all(iprtd->dma_chan);
177
178 break;
179 default:
180 return -EINVAL;
181 }
182
183 return 0; 75 return 0;
184} 76}
185 77
186static snd_pcm_uframes_t snd_imx_pcm_pointer(struct snd_pcm_substream *substream)
187{
188 struct snd_pcm_runtime *runtime = substream->runtime;
189 struct imx_pcm_runtime_data *iprtd = runtime->private_data;
190
191 pr_debug("%s: %ld %ld\n", __func__, iprtd->offset,
192 bytes_to_frames(substream->runtime, iprtd->offset));
193
194 return bytes_to_frames(substream->runtime, iprtd->offset);
195}
196
197static struct snd_pcm_hardware snd_imx_hardware = { 78static struct snd_pcm_hardware snd_imx_hardware = {
198 .info = SNDRV_PCM_INFO_INTERLEAVED | 79 .info = SNDRV_PCM_INFO_INTERLEAVED |
199 SNDRV_PCM_INFO_BLOCK_TRANSFER | 80 SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -215,40 +96,37 @@ static struct snd_pcm_hardware snd_imx_hardware = {
215 96
216static int snd_imx_open(struct snd_pcm_substream *substream) 97static int snd_imx_open(struct snd_pcm_substream *substream)
217{ 98{
218 struct snd_pcm_runtime *runtime = substream->runtime; 99 struct snd_soc_pcm_runtime *rtd = substream->private_data;
219 struct imx_pcm_runtime_data *iprtd; 100 struct imx_pcm_dma_params *dma_params;
101 struct imx_dma_data *dma_data;
220 int ret; 102 int ret;
221 103
222 iprtd = kzalloc(sizeof(*iprtd), GFP_KERNEL); 104 snd_soc_set_runtime_hwparams(substream, &snd_imx_hardware);
223 if (iprtd == NULL)
224 return -ENOMEM;
225 runtime->private_data = iprtd;
226 105
227 ret = snd_pcm_hw_constraint_integer(substream->runtime, 106 dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
228 SNDRV_PCM_HW_PARAM_PERIODS);
229 if (ret < 0) {
230 kfree(iprtd);
231 return ret;
232 }
233 107
234 ret = imx_ssi_dma_alloc(substream); 108 dma_data = kzalloc(sizeof(*dma_data), GFP_KERNEL);
235 if (ret < 0) { 109 dma_data->peripheral_type = IMX_DMATYPE_SSI;
236 kfree(iprtd); 110 dma_data->priority = DMA_PRIO_HIGH;
237 return ret; 111 dma_data->dma_request = dma_params->dma;
112
113 ret = snd_dmaengine_pcm_open(substream, filter, dma_data);
114 if (ret) {
115 kfree(dma_data);
116 return 0;
238 } 117 }
239 118
240 snd_soc_set_runtime_hwparams(substream, &snd_imx_hardware); 119 snd_dmaengine_pcm_set_data(substream, dma_data);
241 120
242 return 0; 121 return 0;
243} 122}
244 123
245static int snd_imx_close(struct snd_pcm_substream *substream) 124static int snd_imx_close(struct snd_pcm_substream *substream)
246{ 125{
247 struct snd_pcm_runtime *runtime = substream->runtime; 126 struct imx_dma_data *dma_data = snd_dmaengine_pcm_get_data(substream);
248 struct imx_pcm_runtime_data *iprtd = runtime->private_data;
249 127
250 dma_release_channel(iprtd->dma_chan); 128 snd_dmaengine_pcm_close(substream);
251 kfree(iprtd); 129 kfree(dma_data);
252 130
253 return 0; 131 return 0;
254} 132}
@@ -258,8 +136,8 @@ static struct snd_pcm_ops imx_pcm_ops = {
258 .close = snd_imx_close, 136 .close = snd_imx_close,
259 .ioctl = snd_pcm_lib_ioctl, 137 .ioctl = snd_pcm_lib_ioctl,
260 .hw_params = snd_imx_pcm_hw_params, 138 .hw_params = snd_imx_pcm_hw_params,
261 .trigger = snd_imx_pcm_trigger, 139 .trigger = snd_dmaengine_pcm_trigger,
262 .pointer = snd_imx_pcm_pointer, 140 .pointer = snd_dmaengine_pcm_pointer,
263 .mmap = snd_imx_pcm_mmap, 141 .mmap = snd_imx_pcm_mmap,
264}; 142};
265 143