diff options
author | Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | 2017-11-15 23:36:51 -0500 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2017-11-16 06:02:04 -0500 |
commit | c20c6704bf2dafaba0d90c8310ef9e919fe4d2e2 (patch) | |
tree | 3a97c9f15ca9dbde6f98b5822f71682219386711 | |
parent | df6a3e245541ac61cc99f2887437e0a43dd08f2e (diff) |
ASoC: rcar: revert IOMMU support so far
commit 4821d914fe74 ("ASoC: rsnd: use dma_sync_single_for_xxx() for
IOMMU") had supported IOMMU, but it breaks normal sound "recorde"
and both PulseAudio's "playback/recorde". The sound will be noisy.
That commit was using dma_sync_single_for_xxx(), and driver should
make sure memory is protected during CPU or Device are using it.
But if driver returns current "residue" data size correctly on pointer
function, player/recorder will access to protected memory.
IOMMU feature should be supported, but I don't know how to handle it
without memory cache problem at this point.
Thus, this patch simply revert it to avoid current noisy sound.
Tested-by: Hiroyuki Yokoyama <hiroyuki.yokoyama.vx@renesas.com>
Tested-by: Ryo Kodama <ryo.kodama.vz@renesas.com>
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r-- | sound/soc/sh/rcar/core.c | 4 | ||||
-rw-r--r-- | sound/soc/sh/rcar/dma.c | 86 |
2 files changed, 8 insertions, 82 deletions
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index c70eb2097816..f12a88a21dfa 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c | |||
@@ -1332,8 +1332,8 @@ static int rsnd_pcm_new(struct snd_soc_pcm_runtime *rtd) | |||
1332 | 1332 | ||
1333 | return snd_pcm_lib_preallocate_pages_for_all( | 1333 | return snd_pcm_lib_preallocate_pages_for_all( |
1334 | rtd->pcm, | 1334 | rtd->pcm, |
1335 | SNDRV_DMA_TYPE_CONTINUOUS, | 1335 | SNDRV_DMA_TYPE_DEV, |
1336 | snd_dma_continuous_data(GFP_KERNEL), | 1336 | rtd->card->snd_card->dev, |
1337 | PREALLOC_BUFFER, PREALLOC_BUFFER_MAX); | 1337 | PREALLOC_BUFFER, PREALLOC_BUFFER_MAX); |
1338 | } | 1338 | } |
1339 | 1339 | ||
diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c index fd557abfe390..4d750bdf8e24 100644 --- a/sound/soc/sh/rcar/dma.c +++ b/sound/soc/sh/rcar/dma.c | |||
@@ -26,10 +26,7 @@ | |||
26 | struct rsnd_dmaen { | 26 | struct rsnd_dmaen { |
27 | struct dma_chan *chan; | 27 | struct dma_chan *chan; |
28 | dma_cookie_t cookie; | 28 | dma_cookie_t cookie; |
29 | dma_addr_t dma_buf; | ||
30 | unsigned int dma_len; | 29 | unsigned int dma_len; |
31 | unsigned int dma_period; | ||
32 | unsigned int dma_cnt; | ||
33 | }; | 30 | }; |
34 | 31 | ||
35 | struct rsnd_dmapp { | 32 | struct rsnd_dmapp { |
@@ -71,38 +68,10 @@ static struct rsnd_mod mem = { | |||
71 | /* | 68 | /* |
72 | * Audio DMAC | 69 | * Audio DMAC |
73 | */ | 70 | */ |
74 | #define rsnd_dmaen_sync(dmaen, io, i) __rsnd_dmaen_sync(dmaen, io, i, 1) | ||
75 | #define rsnd_dmaen_unsync(dmaen, io, i) __rsnd_dmaen_sync(dmaen, io, i, 0) | ||
76 | static void __rsnd_dmaen_sync(struct rsnd_dmaen *dmaen, struct rsnd_dai_stream *io, | ||
77 | int i, int sync) | ||
78 | { | ||
79 | struct device *dev = dmaen->chan->device->dev; | ||
80 | enum dma_data_direction dir; | ||
81 | int is_play = rsnd_io_is_play(io); | ||
82 | dma_addr_t buf; | ||
83 | int len, max; | ||
84 | size_t period; | ||
85 | |||
86 | len = dmaen->dma_len; | ||
87 | period = dmaen->dma_period; | ||
88 | max = len / period; | ||
89 | i = i % max; | ||
90 | buf = dmaen->dma_buf + (period * i); | ||
91 | |||
92 | dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE; | ||
93 | |||
94 | if (sync) | ||
95 | dma_sync_single_for_device(dev, buf, period, dir); | ||
96 | else | ||
97 | dma_sync_single_for_cpu(dev, buf, period, dir); | ||
98 | } | ||
99 | |||
100 | static void __rsnd_dmaen_complete(struct rsnd_mod *mod, | 71 | static void __rsnd_dmaen_complete(struct rsnd_mod *mod, |
101 | struct rsnd_dai_stream *io) | 72 | struct rsnd_dai_stream *io) |
102 | { | 73 | { |
103 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | 74 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); |
104 | struct rsnd_dma *dma = rsnd_mod_to_dma(mod); | ||
105 | struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma); | ||
106 | bool elapsed = false; | 75 | bool elapsed = false; |
107 | unsigned long flags; | 76 | unsigned long flags; |
108 | 77 | ||
@@ -115,22 +84,9 @@ static void __rsnd_dmaen_complete(struct rsnd_mod *mod, | |||
115 | */ | 84 | */ |
116 | spin_lock_irqsave(&priv->lock, flags); | 85 | spin_lock_irqsave(&priv->lock, flags); |
117 | 86 | ||
118 | if (rsnd_io_is_working(io)) { | 87 | if (rsnd_io_is_working(io)) |
119 | rsnd_dmaen_unsync(dmaen, io, dmaen->dma_cnt); | ||
120 | |||
121 | /* | ||
122 | * Next period is already started. | ||
123 | * Let's sync Next Next period | ||
124 | * see | ||
125 | * rsnd_dmaen_start() | ||
126 | */ | ||
127 | rsnd_dmaen_sync(dmaen, io, dmaen->dma_cnt + 2); | ||
128 | |||
129 | elapsed = true; | 88 | elapsed = true; |
130 | 89 | ||
131 | dmaen->dma_cnt++; | ||
132 | } | ||
133 | |||
134 | spin_unlock_irqrestore(&priv->lock, flags); | 90 | spin_unlock_irqrestore(&priv->lock, flags); |
135 | 91 | ||
136 | if (elapsed) | 92 | if (elapsed) |
@@ -165,14 +121,8 @@ static int rsnd_dmaen_stop(struct rsnd_mod *mod, | |||
165 | struct rsnd_dma *dma = rsnd_mod_to_dma(mod); | 121 | struct rsnd_dma *dma = rsnd_mod_to_dma(mod); |
166 | struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma); | 122 | struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma); |
167 | 123 | ||
168 | if (dmaen->chan) { | 124 | if (dmaen->chan) |
169 | int is_play = rsnd_io_is_play(io); | ||
170 | |||
171 | dmaengine_terminate_all(dmaen->chan); | 125 | dmaengine_terminate_all(dmaen->chan); |
172 | dma_unmap_single(dmaen->chan->device->dev, | ||
173 | dmaen->dma_buf, dmaen->dma_len, | ||
174 | is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE); | ||
175 | } | ||
176 | 126 | ||
177 | return 0; | 127 | return 0; |
178 | } | 128 | } |
@@ -237,11 +187,7 @@ static int rsnd_dmaen_start(struct rsnd_mod *mod, | |||
237 | struct device *dev = rsnd_priv_to_dev(priv); | 187 | struct device *dev = rsnd_priv_to_dev(priv); |
238 | struct dma_async_tx_descriptor *desc; | 188 | struct dma_async_tx_descriptor *desc; |
239 | struct dma_slave_config cfg = {}; | 189 | struct dma_slave_config cfg = {}; |
240 | dma_addr_t buf; | ||
241 | size_t len; | ||
242 | size_t period; | ||
243 | int is_play = rsnd_io_is_play(io); | 190 | int is_play = rsnd_io_is_play(io); |
244 | int i; | ||
245 | int ret; | 191 | int ret; |
246 | 192 | ||
247 | cfg.direction = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; | 193 | cfg.direction = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; |
@@ -258,19 +204,10 @@ static int rsnd_dmaen_start(struct rsnd_mod *mod, | |||
258 | if (ret < 0) | 204 | if (ret < 0) |
259 | return ret; | 205 | return ret; |
260 | 206 | ||
261 | len = snd_pcm_lib_buffer_bytes(substream); | ||
262 | period = snd_pcm_lib_period_bytes(substream); | ||
263 | buf = dma_map_single(dmaen->chan->device->dev, | ||
264 | substream->runtime->dma_area, | ||
265 | len, | ||
266 | is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE); | ||
267 | if (dma_mapping_error(dmaen->chan->device->dev, buf)) { | ||
268 | dev_err(dev, "dma map failed\n"); | ||
269 | return -EIO; | ||
270 | } | ||
271 | |||
272 | desc = dmaengine_prep_dma_cyclic(dmaen->chan, | 207 | desc = dmaengine_prep_dma_cyclic(dmaen->chan, |
273 | buf, len, period, | 208 | substream->runtime->dma_addr, |
209 | snd_pcm_lib_buffer_bytes(substream), | ||
210 | snd_pcm_lib_period_bytes(substream), | ||
274 | is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM, | 211 | is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM, |
275 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); | 212 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); |
276 | 213 | ||
@@ -282,18 +219,7 @@ static int rsnd_dmaen_start(struct rsnd_mod *mod, | |||
282 | desc->callback = rsnd_dmaen_complete; | 219 | desc->callback = rsnd_dmaen_complete; |
283 | desc->callback_param = rsnd_mod_get(dma); | 220 | desc->callback_param = rsnd_mod_get(dma); |
284 | 221 | ||
285 | dmaen->dma_buf = buf; | 222 | dmaen->dma_len = snd_pcm_lib_buffer_bytes(substream); |
286 | dmaen->dma_len = len; | ||
287 | dmaen->dma_period = period; | ||
288 | dmaen->dma_cnt = 0; | ||
289 | |||
290 | /* | ||
291 | * synchronize this and next period | ||
292 | * see | ||
293 | * __rsnd_dmaen_complete() | ||
294 | */ | ||
295 | for (i = 0; i < 2; i++) | ||
296 | rsnd_dmaen_sync(dmaen, io, i); | ||
297 | 223 | ||
298 | dmaen->cookie = dmaengine_submit(desc); | 224 | dmaen->cookie = dmaengine_submit(desc); |
299 | if (dmaen->cookie < 0) { | 225 | if (dmaen->cookie < 0) { |