diff options
author | Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | 2014-06-22 20:56:41 -0400 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2014-06-28 09:41:19 -0400 |
commit | ccd01559ead29b59918458e9b412ff18b88fc6cf (patch) | |
tree | dc8e198921c52f35a52c9a58559681768edaefc6 | |
parent | d9288d0ba12de1b5efb830b9128e4cc6877318fc (diff) |
ASoC: rsnd: use dmaengine_prep_dma_cyclic() instead of original method
Current R-Car sound driver is using DMAEngine directly,
but, ASoC is requesting to use common DMA transfer method,
like snd_dmaengine_pcm_trigger() or dmaengine_pcm_ops.
It is difficult to switch at this point, since Renesas
driver is also supporting PIO transfer.
This patch uses dmaengine_prep_dma_cyclic() instead
of dmaengine_prep_slave_single().
It is used in requested method,
and is good first step to switch over.
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
-rw-r--r-- | sound/soc/sh/rcar/core.c | 76 | ||||
-rw-r--r-- | sound/soc/sh/rcar/rsnd.h | 4 |
2 files changed, 18 insertions, 62 deletions
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 8c3707a68603..5149fe2dae9f 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c | |||
@@ -164,26 +164,8 @@ void rsnd_mod_init(struct rsnd_priv *priv, | |||
164 | /* | 164 | /* |
165 | * rsnd_dma functions | 165 | * rsnd_dma functions |
166 | */ | 166 | */ |
167 | static void __rsnd_dma_start(struct rsnd_dma *dma); | ||
168 | static void rsnd_dma_continue(struct rsnd_dma *dma) | ||
169 | { | ||
170 | /* push next A or B plane */ | ||
171 | dma->submit_loop = 1; | ||
172 | schedule_work(&dma->work); | ||
173 | } | ||
174 | |||
175 | void rsnd_dma_start(struct rsnd_dma *dma) | ||
176 | { | ||
177 | /* push both A and B plane*/ | ||
178 | dma->offset = 0; | ||
179 | dma->submit_loop = 2; | ||
180 | __rsnd_dma_start(dma); | ||
181 | } | ||
182 | |||
183 | void rsnd_dma_stop(struct rsnd_dma *dma) | 167 | void rsnd_dma_stop(struct rsnd_dma *dma) |
184 | { | 168 | { |
185 | dma->submit_loop = 0; | ||
186 | cancel_work_sync(&dma->work); | ||
187 | dmaengine_terminate_all(dma->chan); | 169 | dmaengine_terminate_all(dma->chan); |
188 | } | 170 | } |
189 | 171 | ||
@@ -191,11 +173,7 @@ static void rsnd_dma_complete(void *data) | |||
191 | { | 173 | { |
192 | struct rsnd_dma *dma = (struct rsnd_dma *)data; | 174 | struct rsnd_dma *dma = (struct rsnd_dma *)data; |
193 | struct rsnd_mod *mod = rsnd_dma_to_mod(dma); | 175 | struct rsnd_mod *mod = rsnd_dma_to_mod(dma); |
194 | struct rsnd_priv *priv = rsnd_mod_to_priv(rsnd_dma_to_mod(dma)); | ||
195 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | 176 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); |
196 | unsigned long flags; | ||
197 | |||
198 | rsnd_lock(priv, flags); | ||
199 | 177 | ||
200 | /* | 178 | /* |
201 | * Renesas sound Gen1 needs 1 DMAC, | 179 | * Renesas sound Gen1 needs 1 DMAC, |
@@ -208,57 +186,40 @@ static void rsnd_dma_complete(void *data) | |||
208 | * rsnd_dai_pointer_update() will be called twice, | 186 | * rsnd_dai_pointer_update() will be called twice, |
209 | * ant it will breaks io->byte_pos | 187 | * ant it will breaks io->byte_pos |
210 | */ | 188 | */ |
211 | if (dma->submit_loop) | ||
212 | rsnd_dma_continue(dma); | ||
213 | |||
214 | rsnd_unlock(priv, flags); | ||
215 | 189 | ||
216 | rsnd_dai_pointer_update(io, io->byte_per_period); | 190 | rsnd_dai_pointer_update(io, io->byte_per_period); |
217 | } | 191 | } |
218 | 192 | ||
219 | static void __rsnd_dma_start(struct rsnd_dma *dma) | 193 | void rsnd_dma_start(struct rsnd_dma *dma) |
220 | { | 194 | { |
221 | struct rsnd_mod *mod = rsnd_dma_to_mod(dma); | 195 | struct rsnd_mod *mod = rsnd_dma_to_mod(dma); |
222 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | 196 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); |
223 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); | 197 | struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); |
224 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | 198 | struct snd_pcm_substream *substream = io->substream; |
225 | struct device *dev = rsnd_priv_to_dev(priv); | 199 | struct device *dev = rsnd_priv_to_dev(priv); |
226 | struct dma_async_tx_descriptor *desc; | 200 | struct dma_async_tx_descriptor *desc; |
227 | dma_addr_t buf; | ||
228 | size_t len = io->byte_per_period; | ||
229 | int i; | ||
230 | |||
231 | for (i = 0; i < dma->submit_loop; i++) { | ||
232 | 201 | ||
233 | buf = runtime->dma_addr + | 202 | desc = dmaengine_prep_dma_cyclic(dma->chan, |
234 | rsnd_dai_pointer_offset(io, dma->offset + len); | 203 | substream->runtime->dma_addr, |
235 | dma->offset = len; | 204 | snd_pcm_lib_buffer_bytes(substream), |
205 | snd_pcm_lib_period_bytes(substream), | ||
206 | dma->dir, | ||
207 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); | ||
236 | 208 | ||
237 | desc = dmaengine_prep_slave_single( | 209 | if (!desc) { |
238 | dma->chan, buf, len, dma->dir, | 210 | dev_err(dev, "dmaengine_prep_slave_sg() fail\n"); |
239 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); | 211 | return; |
240 | if (!desc) { | 212 | } |
241 | dev_err(dev, "dmaengine_prep_slave_sg() fail\n"); | ||
242 | return; | ||
243 | } | ||
244 | |||
245 | desc->callback = rsnd_dma_complete; | ||
246 | desc->callback_param = dma; | ||
247 | 213 | ||
248 | if (dmaengine_submit(desc) < 0) { | 214 | desc->callback = rsnd_dma_complete; |
249 | dev_err(dev, "dmaengine_submit() fail\n"); | 215 | desc->callback_param = dma; |
250 | return; | ||
251 | } | ||
252 | 216 | ||
253 | dma_async_issue_pending(dma->chan); | 217 | if (dmaengine_submit(desc) < 0) { |
218 | dev_err(dev, "dmaengine_submit() fail\n"); | ||
219 | return; | ||
254 | } | 220 | } |
255 | } | ||
256 | |||
257 | static void rsnd_dma_do_work(struct work_struct *work) | ||
258 | { | ||
259 | struct rsnd_dma *dma = container_of(work, struct rsnd_dma, work); | ||
260 | 221 | ||
261 | __rsnd_dma_start(dma); | 222 | dma_async_issue_pending(dma->chan); |
262 | } | 223 | } |
263 | 224 | ||
264 | int rsnd_dma_available(struct rsnd_dma *dma) | 225 | int rsnd_dma_available(struct rsnd_dma *dma) |
@@ -372,7 +333,6 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, | |||
372 | goto rsnd_dma_init_err; | 333 | goto rsnd_dma_init_err; |
373 | 334 | ||
374 | dma->dir = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; | 335 | dma->dir = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; |
375 | INIT_WORK(&dma->work, rsnd_dma_do_work); | ||
376 | 336 | ||
377 | return 0; | 337 | return 0; |
378 | 338 | ||
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index a1466c1570bc..60b5e9260600 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h | |||
@@ -156,12 +156,8 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod); | |||
156 | */ | 156 | */ |
157 | struct rsnd_dma { | 157 | struct rsnd_dma { |
158 | struct sh_dmae_slave slave; | 158 | struct sh_dmae_slave slave; |
159 | struct work_struct work; | ||
160 | struct dma_chan *chan; | 159 | struct dma_chan *chan; |
161 | enum dma_transfer_direction dir; | 160 | enum dma_transfer_direction dir; |
162 | |||
163 | int submit_loop; | ||
164 | int offset; /* it cares A/B plane */ | ||
165 | }; | 161 | }; |
166 | 162 | ||
167 | void rsnd_dma_start(struct rsnd_dma *dma); | 163 | void rsnd_dma_start(struct rsnd_dma *dma); |