diff options
author | Lars-Peter Clausen <lars@metafoo.de> | 2012-03-05 08:02:15 -0500 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-03-12 15:03:39 -0400 |
commit | d7a42e1033b27cea8ae137eeaa038910fe334a55 (patch) | |
tree | 403becfa4e007b3b41c5a77fabfde7c94653ebcc /sound | |
parent | 7a08cf7022b3f6863cff004cf0531f3e44a772ea (diff) |
ASoC: ep93xx-pcm: Use dmaengine PCM helper functions
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Acked-by: Vinod Koul <vinod.koul@linux.intel.com>
Tested-by: Mika Westerberg <mika.westerberg@iki.fi>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/ep93xx/Kconfig | 1 | ||||
-rw-r--r-- | sound/soc/ep93xx/ep93xx-pcm.c | 148 |
2 files changed, 23 insertions, 126 deletions
diff --git a/sound/soc/ep93xx/Kconfig b/sound/soc/ep93xx/Kconfig index 91a28de94109..88143db7e753 100644 --- a/sound/soc/ep93xx/Kconfig +++ b/sound/soc/ep93xx/Kconfig | |||
@@ -1,6 +1,7 @@ | |||
1 | config SND_EP93XX_SOC | 1 | config SND_EP93XX_SOC |
2 | tristate "SoC Audio support for the Cirrus Logic EP93xx series" | 2 | tristate "SoC Audio support for the Cirrus Logic EP93xx series" |
3 | depends on ARCH_EP93XX && SND_SOC | 3 | depends on ARCH_EP93XX && SND_SOC |
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 EP93xx I2S or AC97 interfaces. | 7 | the EP93xx I2S or AC97 interfaces. |
diff --git a/sound/soc/ep93xx/ep93xx-pcm.c b/sound/soc/ep93xx/ep93xx-pcm.c index 32adca38b48b..162dbb74f4cc 100644 --- a/sound/soc/ep93xx/ep93xx-pcm.c +++ b/sound/soc/ep93xx/ep93xx-pcm.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <sound/pcm.h> | 23 | #include <sound/pcm.h> |
24 | #include <sound/pcm_params.h> | 24 | #include <sound/pcm_params.h> |
25 | #include <sound/soc.h> | 25 | #include <sound/soc.h> |
26 | #include <sound/dmaengine_pcm.h> | ||
26 | 27 | ||
27 | #include <mach/dma.h> | 28 | #include <mach/dma.h> |
28 | #include <mach/hardware.h> | 29 | #include <mach/hardware.h> |
@@ -52,26 +53,6 @@ static const struct snd_pcm_hardware ep93xx_pcm_hardware = { | |||
52 | .fifo_size = 32, | 53 | .fifo_size = 32, |
53 | }; | 54 | }; |
54 | 55 | ||
55 | struct ep93xx_runtime_data | ||
56 | { | ||
57 | int pointer_bytes; | ||
58 | int periods; | ||
59 | int period_bytes; | ||
60 | struct dma_chan *dma_chan; | ||
61 | struct ep93xx_dma_data dma_data; | ||
62 | }; | ||
63 | |||
64 | static void ep93xx_pcm_dma_callback(void *data) | ||
65 | { | ||
66 | struct snd_pcm_substream *substream = data; | ||
67 | struct ep93xx_runtime_data *rtd = substream->runtime->private_data; | ||
68 | |||
69 | rtd->pointer_bytes += rtd->period_bytes; | ||
70 | rtd->pointer_bytes %= rtd->period_bytes * rtd->periods; | ||
71 | |||
72 | snd_pcm_period_elapsed(substream); | ||
73 | } | ||
74 | |||
75 | static bool ep93xx_pcm_dma_filter(struct dma_chan *chan, void *filter_param) | 56 | static bool ep93xx_pcm_dma_filter(struct dma_chan *chan, void *filter_param) |
76 | { | 57 | { |
77 | struct ep93xx_dma_data *data = filter_param; | 58 | struct ep93xx_dma_data *data = filter_param; |
@@ -86,98 +67,48 @@ static bool ep93xx_pcm_dma_filter(struct dma_chan *chan, void *filter_param) | |||
86 | 67 | ||
87 | static int ep93xx_pcm_open(struct snd_pcm_substream *substream) | 68 | static int ep93xx_pcm_open(struct snd_pcm_substream *substream) |
88 | { | 69 | { |
89 | struct snd_soc_pcm_runtime *soc_rtd = substream->private_data; | 70 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
90 | struct snd_soc_dai *cpu_dai = soc_rtd->cpu_dai; | 71 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
91 | struct ep93xx_pcm_dma_params *dma_params; | 72 | struct ep93xx_pcm_dma_params *dma_params; |
92 | struct ep93xx_runtime_data *rtd; | 73 | struct ep93xx_dma_data *dma_data; |
93 | dma_cap_mask_t mask; | ||
94 | int ret; | 74 | int ret; |
95 | 75 | ||
96 | ret = snd_pcm_hw_constraint_integer(substream->runtime, | ||
97 | SNDRV_PCM_HW_PARAM_PERIODS); | ||
98 | if (ret < 0) | ||
99 | return ret; | ||
100 | |||
101 | snd_soc_set_runtime_hwparams(substream, &ep93xx_pcm_hardware); | 76 | snd_soc_set_runtime_hwparams(substream, &ep93xx_pcm_hardware); |
102 | 77 | ||
103 | rtd = kmalloc(sizeof(*rtd), GFP_KERNEL); | 78 | dma_data = kmalloc(sizeof(*dma_data), GFP_KERNEL); |
104 | if (!rtd) | 79 | if (!dma_data) |
105 | return -ENOMEM; | 80 | return -ENOMEM; |
106 | 81 | ||
107 | dma_cap_zero(mask); | ||
108 | dma_cap_set(DMA_SLAVE, mask); | ||
109 | dma_cap_set(DMA_CYCLIC, mask); | ||
110 | |||
111 | dma_params = snd_soc_dai_get_dma_data(cpu_dai, substream); | 82 | dma_params = snd_soc_dai_get_dma_data(cpu_dai, substream); |
112 | rtd->dma_data.port = dma_params->dma_port; | 83 | dma_data->port = dma_params->dma_port; |
113 | rtd->dma_data.name = dma_params->name; | 84 | dma_data->name = dma_params->name; |
114 | 85 | dma_data->direction = snd_pcm_substream_to_dma_direction(substream); | |
115 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
116 | rtd->dma_data.direction = DMA_MEM_TO_DEV; | ||
117 | else | ||
118 | rtd->dma_data.direction = DMA_DEV_TO_MEM; | ||
119 | |||
120 | rtd->dma_chan = dma_request_channel(mask, ep93xx_pcm_dma_filter, | ||
121 | &rtd->dma_data); | ||
122 | if (!rtd->dma_chan) { | ||
123 | kfree(rtd); | ||
124 | return -EINVAL; | ||
125 | } | ||
126 | |||
127 | substream->runtime->private_data = rtd; | ||
128 | return 0; | ||
129 | } | ||
130 | 86 | ||
131 | static int ep93xx_pcm_close(struct snd_pcm_substream *substream) | 87 | ret = snd_dmaengine_pcm_open(substream, ep93xx_pcm_dma_filter, dma_data); |
132 | { | 88 | if (ret) { |
133 | struct ep93xx_runtime_data *rtd = substream->runtime->private_data; | 89 | kfree(dma_data); |
90 | return ret; | ||
91 | } | ||
134 | 92 | ||
135 | dma_release_channel(rtd->dma_chan); | 93 | snd_dmaengine_pcm_set_data(substream, dma_data); |
136 | kfree(rtd); | ||
137 | return 0; | ||
138 | } | ||
139 | 94 | ||
140 | static int ep93xx_pcm_dma_submit(struct snd_pcm_substream *substream) | ||
141 | { | ||
142 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
143 | struct ep93xx_runtime_data *rtd = runtime->private_data; | ||
144 | struct dma_chan *chan = rtd->dma_chan; | ||
145 | struct dma_device *dma_dev = chan->device; | ||
146 | struct dma_async_tx_descriptor *desc; | ||
147 | |||
148 | rtd->pointer_bytes = 0; | ||
149 | desc = dma_dev->device_prep_dma_cyclic(chan, runtime->dma_addr, | ||
150 | rtd->period_bytes * rtd->periods, | ||
151 | rtd->period_bytes, | ||
152 | rtd->dma_data.direction); | ||
153 | if (!desc) | ||
154 | return -EINVAL; | ||
155 | |||
156 | desc->callback = ep93xx_pcm_dma_callback; | ||
157 | desc->callback_param = substream; | ||
158 | |||
159 | dmaengine_submit(desc); | ||
160 | return 0; | 95 | return 0; |
161 | } | 96 | } |
162 | 97 | ||
163 | static void ep93xx_pcm_dma_flush(struct snd_pcm_substream *substream) | 98 | static int ep93xx_pcm_close(struct snd_pcm_substream *substream) |
164 | { | 99 | { |
165 | struct snd_pcm_runtime *runtime = substream->runtime; | 100 | struct dma_data *dma_data = snd_dmaengine_pcm_get_data(substream); |
166 | struct ep93xx_runtime_data *rtd = runtime->private_data; | ||
167 | 101 | ||
168 | dmaengine_terminate_all(rtd->dma_chan); | 102 | snd_dmaengine_pcm_close(substream); |
103 | kfree(dma_data); | ||
104 | return 0; | ||
169 | } | 105 | } |
170 | 106 | ||
171 | static int ep93xx_pcm_hw_params(struct snd_pcm_substream *substream, | 107 | static int ep93xx_pcm_hw_params(struct snd_pcm_substream *substream, |
172 | struct snd_pcm_hw_params *params) | 108 | struct snd_pcm_hw_params *params) |
173 | { | 109 | { |
174 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
175 | struct ep93xx_runtime_data *rtd = runtime->private_data; | ||
176 | |||
177 | snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); | 110 | snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); |
178 | 111 | ||
179 | rtd->periods = params_periods(params); | ||
180 | rtd->period_bytes = params_period_bytes(params); | ||
181 | return 0; | 112 | return 0; |
182 | } | 113 | } |
183 | 114 | ||
@@ -187,41 +118,6 @@ static int ep93xx_pcm_hw_free(struct snd_pcm_substream *substream) | |||
187 | return 0; | 118 | return 0; |
188 | } | 119 | } |
189 | 120 | ||
190 | static int ep93xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | ||
191 | { | ||
192 | int ret; | ||
193 | |||
194 | ret = 0; | ||
195 | switch (cmd) { | ||
196 | case SNDRV_PCM_TRIGGER_START: | ||
197 | case SNDRV_PCM_TRIGGER_RESUME: | ||
198 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
199 | ret = ep93xx_pcm_dma_submit(substream); | ||
200 | break; | ||
201 | |||
202 | case SNDRV_PCM_TRIGGER_STOP: | ||
203 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
204 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
205 | ep93xx_pcm_dma_flush(substream); | ||
206 | break; | ||
207 | |||
208 | default: | ||
209 | ret = -EINVAL; | ||
210 | break; | ||
211 | } | ||
212 | |||
213 | return ret; | ||
214 | } | ||
215 | |||
216 | static snd_pcm_uframes_t ep93xx_pcm_pointer(struct snd_pcm_substream *substream) | ||
217 | { | ||
218 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
219 | struct ep93xx_runtime_data *rtd = substream->runtime->private_data; | ||
220 | |||
221 | /* FIXME: implement this with sub-period granularity */ | ||
222 | return bytes_to_frames(runtime, rtd->pointer_bytes); | ||
223 | } | ||
224 | |||
225 | static int ep93xx_pcm_mmap(struct snd_pcm_substream *substream, | 121 | static int ep93xx_pcm_mmap(struct snd_pcm_substream *substream, |
226 | struct vm_area_struct *vma) | 122 | struct vm_area_struct *vma) |
227 | { | 123 | { |
@@ -239,8 +135,8 @@ static struct snd_pcm_ops ep93xx_pcm_ops = { | |||
239 | .ioctl = snd_pcm_lib_ioctl, | 135 | .ioctl = snd_pcm_lib_ioctl, |
240 | .hw_params = ep93xx_pcm_hw_params, | 136 | .hw_params = ep93xx_pcm_hw_params, |
241 | .hw_free = ep93xx_pcm_hw_free, | 137 | .hw_free = ep93xx_pcm_hw_free, |
242 | .trigger = ep93xx_pcm_trigger, | 138 | .trigger = snd_dmaengine_pcm_trigger, |
243 | .pointer = ep93xx_pcm_pointer, | 139 | .pointer = snd_dmaengine_pcm_pointer, |
244 | .mmap = ep93xx_pcm_mmap, | 140 | .mmap = ep93xx_pcm_mmap, |
245 | }; | 141 | }; |
246 | 142 | ||