[alsa-devel] [PATCH] ASoC: rcar: revert IOMMU support so far
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
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 --- sound/soc/sh/rcar/core.c | 4 +-- 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 8cd900d..ebdfa34 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -1329,8 +1329,8 @@ static int rsnd_pcm_new(struct snd_soc_pcm_runtime *rtd)
return snd_pcm_lib_preallocate_pages_for_all( rtd->pcm, - SNDRV_DMA_TYPE_CONTINUOUS, - snd_dma_continuous_data(GFP_KERNEL), + SNDRV_DMA_TYPE_DEV, + rtd->card->snd_card->dev, PREALLOC_BUFFER, PREALLOC_BUFFER_MAX); }
diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c index fd557ab..4d750bdf 100644 --- a/sound/soc/sh/rcar/dma.c +++ b/sound/soc/sh/rcar/dma.c @@ -26,10 +26,7 @@ struct rsnd_dmaen { struct dma_chan *chan; dma_cookie_t cookie; - dma_addr_t dma_buf; unsigned int dma_len; - unsigned int dma_period; - unsigned int dma_cnt; };
struct rsnd_dmapp { @@ -71,38 +68,10 @@ struct rsnd_dma_ctrl { /* * Audio DMAC */ -#define rsnd_dmaen_sync(dmaen, io, i) __rsnd_dmaen_sync(dmaen, io, i, 1) -#define rsnd_dmaen_unsync(dmaen, io, i) __rsnd_dmaen_sync(dmaen, io, i, 0) -static void __rsnd_dmaen_sync(struct rsnd_dmaen *dmaen, struct rsnd_dai_stream *io, - int i, int sync) -{ - struct device *dev = dmaen->chan->device->dev; - enum dma_data_direction dir; - int is_play = rsnd_io_is_play(io); - dma_addr_t buf; - int len, max; - size_t period; - - len = dmaen->dma_len; - period = dmaen->dma_period; - max = len / period; - i = i % max; - buf = dmaen->dma_buf + (period * i); - - dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE; - - if (sync) - dma_sync_single_for_device(dev, buf, period, dir); - else - dma_sync_single_for_cpu(dev, buf, period, dir); -} - static void __rsnd_dmaen_complete(struct rsnd_mod *mod, struct rsnd_dai_stream *io) { struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - struct rsnd_dma *dma = rsnd_mod_to_dma(mod); - struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma); bool elapsed = false; unsigned long flags;
@@ -115,22 +84,9 @@ static void __rsnd_dmaen_complete(struct rsnd_mod *mod, */ spin_lock_irqsave(&priv->lock, flags);
- if (rsnd_io_is_working(io)) { - rsnd_dmaen_unsync(dmaen, io, dmaen->dma_cnt); - - /* - * Next period is already started. - * Let's sync Next Next period - * see - * rsnd_dmaen_start() - */ - rsnd_dmaen_sync(dmaen, io, dmaen->dma_cnt + 2); - + if (rsnd_io_is_working(io)) elapsed = true;
- dmaen->dma_cnt++; - } - spin_unlock_irqrestore(&priv->lock, flags);
if (elapsed) @@ -165,14 +121,8 @@ static int rsnd_dmaen_stop(struct rsnd_mod *mod, struct rsnd_dma *dma = rsnd_mod_to_dma(mod); struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma);
- if (dmaen->chan) { - int is_play = rsnd_io_is_play(io); - + if (dmaen->chan) dmaengine_terminate_all(dmaen->chan); - dma_unmap_single(dmaen->chan->device->dev, - dmaen->dma_buf, dmaen->dma_len, - is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE); - }
return 0; } @@ -237,11 +187,7 @@ static int rsnd_dmaen_start(struct rsnd_mod *mod, struct device *dev = rsnd_priv_to_dev(priv); struct dma_async_tx_descriptor *desc; struct dma_slave_config cfg = {}; - dma_addr_t buf; - size_t len; - size_t period; int is_play = rsnd_io_is_play(io); - int i; int ret;
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, if (ret < 0) return ret;
- len = snd_pcm_lib_buffer_bytes(substream); - period = snd_pcm_lib_period_bytes(substream); - buf = dma_map_single(dmaen->chan->device->dev, - substream->runtime->dma_area, - len, - is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE); - if (dma_mapping_error(dmaen->chan->device->dev, buf)) { - dev_err(dev, "dma map failed\n"); - return -EIO; - } - desc = dmaengine_prep_dma_cyclic(dmaen->chan, - buf, len, period, + substream->runtime->dma_addr, + snd_pcm_lib_buffer_bytes(substream), + snd_pcm_lib_period_bytes(substream), is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
@@ -282,18 +219,7 @@ static int rsnd_dmaen_start(struct rsnd_mod *mod, desc->callback = rsnd_dmaen_complete; desc->callback_param = rsnd_mod_get(dma);
- dmaen->dma_buf = buf; - dmaen->dma_len = len; - dmaen->dma_period = period; - dmaen->dma_cnt = 0; - - /* - * synchronize this and next period - * see - * __rsnd_dmaen_complete() - */ - for (i = 0; i < 2; i++) - rsnd_dmaen_sync(dmaen, io, i); + dmaen->dma_len = snd_pcm_lib_buffer_bytes(substream);
dmaen->cookie = dmaengine_submit(desc); if (dmaen->cookie < 0) {
On Thu, 16 Nov 2017 05:36:51 +0100, Kuninori Morimoto wrote:
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
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.
The driver may return the position at the last synced point via pointer callback while keeping the finer position by compensating with status delay field. In that way, user-space can avoid to touch the in-flight memory but can know the exact position.
BTW, if the problem is only about PA, the easiest workaround would be to put SNDRV_PCM_INFO_BATCH flag. Then PA switches from tsched to normal mode.
thanks,
Takashi
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
sound/soc/sh/rcar/core.c | 4 +-- 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 8cd900d..ebdfa34 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -1329,8 +1329,8 @@ static int rsnd_pcm_new(struct snd_soc_pcm_runtime *rtd)
return snd_pcm_lib_preallocate_pages_for_all( rtd->pcm,
SNDRV_DMA_TYPE_CONTINUOUS,
snd_dma_continuous_data(GFP_KERNEL),
SNDRV_DMA_TYPE_DEV,
PREALLOC_BUFFER, PREALLOC_BUFFER_MAX);rtd->card->snd_card->dev,
}
diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c index fd557ab..4d750bdf 100644 --- a/sound/soc/sh/rcar/dma.c +++ b/sound/soc/sh/rcar/dma.c @@ -26,10 +26,7 @@ struct rsnd_dmaen { struct dma_chan *chan; dma_cookie_t cookie;
- dma_addr_t dma_buf; unsigned int dma_len;
- unsigned int dma_period;
- unsigned int dma_cnt;
};
struct rsnd_dmapp { @@ -71,38 +68,10 @@ struct rsnd_dma_ctrl { /*
Audio DMAC
*/ -#define rsnd_dmaen_sync(dmaen, io, i) __rsnd_dmaen_sync(dmaen, io, i, 1) -#define rsnd_dmaen_unsync(dmaen, io, i) __rsnd_dmaen_sync(dmaen, io, i, 0) -static void __rsnd_dmaen_sync(struct rsnd_dmaen *dmaen, struct rsnd_dai_stream *io,
int i, int sync)
-{
- struct device *dev = dmaen->chan->device->dev;
- enum dma_data_direction dir;
- int is_play = rsnd_io_is_play(io);
- dma_addr_t buf;
- int len, max;
- size_t period;
- len = dmaen->dma_len;
- period = dmaen->dma_period;
- max = len / period;
- i = i % max;
- buf = dmaen->dma_buf + (period * i);
- dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
- if (sync)
dma_sync_single_for_device(dev, buf, period, dir);
- else
dma_sync_single_for_cpu(dev, buf, period, dir);
-}
static void __rsnd_dmaen_complete(struct rsnd_mod *mod, struct rsnd_dai_stream *io) { struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
- struct rsnd_dma *dma = rsnd_mod_to_dma(mod);
- struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma); bool elapsed = false; unsigned long flags;
@@ -115,22 +84,9 @@ static void __rsnd_dmaen_complete(struct rsnd_mod *mod, */ spin_lock_irqsave(&priv->lock, flags);
- if (rsnd_io_is_working(io)) {
rsnd_dmaen_unsync(dmaen, io, dmaen->dma_cnt);
/*
* Next period is already started.
* Let's sync Next Next period
* see
* rsnd_dmaen_start()
*/
rsnd_dmaen_sync(dmaen, io, dmaen->dma_cnt + 2);
- if (rsnd_io_is_working(io)) elapsed = true;
dmaen->dma_cnt++;
}
spin_unlock_irqrestore(&priv->lock, flags);
if (elapsed)
@@ -165,14 +121,8 @@ static int rsnd_dmaen_stop(struct rsnd_mod *mod, struct rsnd_dma *dma = rsnd_mod_to_dma(mod); struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma);
- if (dmaen->chan) {
int is_play = rsnd_io_is_play(io);
- if (dmaen->chan) dmaengine_terminate_all(dmaen->chan);
dma_unmap_single(dmaen->chan->device->dev,
dmaen->dma_buf, dmaen->dma_len,
is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
}
return 0;
} @@ -237,11 +187,7 @@ static int rsnd_dmaen_start(struct rsnd_mod *mod, struct device *dev = rsnd_priv_to_dev(priv); struct dma_async_tx_descriptor *desc; struct dma_slave_config cfg = {};
dma_addr_t buf;
size_t len;
size_t period; int is_play = rsnd_io_is_play(io);
int i; int ret;
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, if (ret < 0) return ret;
- len = snd_pcm_lib_buffer_bytes(substream);
- period = snd_pcm_lib_period_bytes(substream);
- buf = dma_map_single(dmaen->chan->device->dev,
substream->runtime->dma_area,
len,
is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
- if (dma_mapping_error(dmaen->chan->device->dev, buf)) {
dev_err(dev, "dma map failed\n");
return -EIO;
- }
- desc = dmaengine_prep_dma_cyclic(dmaen->chan,
buf, len, period,
substream->runtime->dma_addr,
snd_pcm_lib_buffer_bytes(substream),
snd_pcm_lib_period_bytes(substream), is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
@@ -282,18 +219,7 @@ static int rsnd_dmaen_start(struct rsnd_mod *mod, desc->callback = rsnd_dmaen_complete; desc->callback_param = rsnd_mod_get(dma);
- dmaen->dma_buf = buf;
- dmaen->dma_len = len;
- dmaen->dma_period = period;
- dmaen->dma_cnt = 0;
- /*
* synchronize this and next period
* see
* __rsnd_dmaen_complete()
*/
- for (i = 0; i < 2; i++)
rsnd_dmaen_sync(dmaen, io, i);
dmaen->dma_len = snd_pcm_lib_buffer_bytes(substream);
dmaen->cookie = dmaengine_submit(desc); if (dmaen->cookie < 0) {
-- 1.9.1
Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
Hi Takashi-san
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.
The driver may return the position at the last synced point via pointer callback while keeping the finer position by compensating with status delay field. In that way, user-space can avoid to touch the in-flight memory but can know the exact position.
BTW, if the problem is only about PA, the easiest workaround would be to put SNDRV_PCM_INFO_BATCH flag. Then PA switches from tsched to normal mode.
The issue (= noise) is not only for PulseAudio, but NormalAudio had capture noise issue.
Maybe we can use "delay" field, but this IOMMU patch is assuming many things which is no guarantee anyway, I can say dirty. And Renesas platform is not yet enabled IOMMU at this point. Thus, removing IOMMU support has no degrade, and will be fresh.
IOMMU support on this driver was created based on local prototype SoC IOMMU support. So, I want to fresh create new IOMMU support in the future
Best regards --- Kuninori Morimoto
On Thu, 16 Nov 2017 08:55:25 +0100, Kuninori Morimoto wrote:
Hi Takashi-san
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.
The driver may return the position at the last synced point via pointer callback while keeping the finer position by compensating with status delay field. In that way, user-space can avoid to touch the in-flight memory but can know the exact position.
BTW, if the problem is only about PA, the easiest workaround would be to put SNDRV_PCM_INFO_BATCH flag. Then PA switches from tsched to normal mode.
The issue (= noise) is not only for PulseAudio, but NormalAudio had capture noise issue.
OK, it indicates that returning the value with residue is actually wrong. Basically the pointer callback needs to give the position that has been already processed where you can safely scratch at this point at most.
Maybe we can use "delay" field, but this IOMMU patch is assuming many things which is no guarantee anyway, I can say dirty. And Renesas platform is not yet enabled IOMMU at this point. Thus, removing IOMMU support has no degrade, and will be fresh.
IOMMU support on this driver was created based on local prototype SoC IOMMU support. So, I want to fresh create new IOMMU support in the future
Sure, I'm not against the revert, which is the safest option, but just wanted to mention about a right implementation in such scenarios.
Takashi
Hi Takashi-san
The driver may return the position at the last synced point via pointer callback while keeping the finer position by compensating with status delay field. In that way, user-space can avoid to touch the in-flight memory but can know the exact position.
BTW, if the problem is only about PA, the easiest workaround would be to put SNDRV_PCM_INFO_BATCH flag. Then PA switches from tsched to normal mode.
The issue (= noise) is not only for PulseAudio, but NormalAudio had capture noise issue.
OK, it indicates that returning the value with residue is actually wrong. Basically the pointer callback needs to give the position that has been already processed where you can safely scratch at this point at most.
Maybe we can use "delay" field, but this IOMMU patch is assuming many things which is no guarantee anyway, I can say dirty. And Renesas platform is not yet enabled IOMMU at this point. Thus, removing IOMMU support has no degrade, and will be fresh.
IOMMU support on this driver was created based on local prototype SoC IOMMU support. So, I want to fresh create new IOMMU support in the future
Sure, I'm not against the revert, which is the safest option, but just wanted to mention about a right implementation in such scenarios.
Thank you for your help/advice.
Best regards --- Kuninori Morimoto
The patch
ASoC: rcar: revert IOMMU support so far
has been applied to the asoc tree at
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From c20c6704bf2dafaba0d90c8310ef9e919fe4d2e2 Mon Sep 17 00:00:00 2001
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com Date: Thu, 16 Nov 2017 04:36:51 +0000 Subject: [PATCH] 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 --- sound/soc/sh/rcar/core.c | 4 +-- 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)
return snd_pcm_lib_preallocate_pages_for_all( rtd->pcm, - SNDRV_DMA_TYPE_CONTINUOUS, - snd_dma_continuous_data(GFP_KERNEL), + SNDRV_DMA_TYPE_DEV, + rtd->card->snd_card->dev, PREALLOC_BUFFER, PREALLOC_BUFFER_MAX); }
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 @@ struct rsnd_dmaen { struct dma_chan *chan; dma_cookie_t cookie; - dma_addr_t dma_buf; unsigned int dma_len; - unsigned int dma_period; - unsigned int dma_cnt; };
struct rsnd_dmapp { @@ -71,38 +68,10 @@ static struct rsnd_mod mem = { /* * Audio DMAC */ -#define rsnd_dmaen_sync(dmaen, io, i) __rsnd_dmaen_sync(dmaen, io, i, 1) -#define rsnd_dmaen_unsync(dmaen, io, i) __rsnd_dmaen_sync(dmaen, io, i, 0) -static void __rsnd_dmaen_sync(struct rsnd_dmaen *dmaen, struct rsnd_dai_stream *io, - int i, int sync) -{ - struct device *dev = dmaen->chan->device->dev; - enum dma_data_direction dir; - int is_play = rsnd_io_is_play(io); - dma_addr_t buf; - int len, max; - size_t period; - - len = dmaen->dma_len; - period = dmaen->dma_period; - max = len / period; - i = i % max; - buf = dmaen->dma_buf + (period * i); - - dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE; - - if (sync) - dma_sync_single_for_device(dev, buf, period, dir); - else - dma_sync_single_for_cpu(dev, buf, period, dir); -} - static void __rsnd_dmaen_complete(struct rsnd_mod *mod, struct rsnd_dai_stream *io) { struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - struct rsnd_dma *dma = rsnd_mod_to_dma(mod); - struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma); bool elapsed = false; unsigned long flags;
@@ -115,22 +84,9 @@ static void __rsnd_dmaen_complete(struct rsnd_mod *mod, */ spin_lock_irqsave(&priv->lock, flags);
- if (rsnd_io_is_working(io)) { - rsnd_dmaen_unsync(dmaen, io, dmaen->dma_cnt); - - /* - * Next period is already started. - * Let's sync Next Next period - * see - * rsnd_dmaen_start() - */ - rsnd_dmaen_sync(dmaen, io, dmaen->dma_cnt + 2); - + if (rsnd_io_is_working(io)) elapsed = true;
- dmaen->dma_cnt++; - } - spin_unlock_irqrestore(&priv->lock, flags);
if (elapsed) @@ -165,14 +121,8 @@ static int rsnd_dmaen_stop(struct rsnd_mod *mod, struct rsnd_dma *dma = rsnd_mod_to_dma(mod); struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma);
- if (dmaen->chan) { - int is_play = rsnd_io_is_play(io); - + if (dmaen->chan) dmaengine_terminate_all(dmaen->chan); - dma_unmap_single(dmaen->chan->device->dev, - dmaen->dma_buf, dmaen->dma_len, - is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE); - }
return 0; } @@ -237,11 +187,7 @@ static int rsnd_dmaen_start(struct rsnd_mod *mod, struct device *dev = rsnd_priv_to_dev(priv); struct dma_async_tx_descriptor *desc; struct dma_slave_config cfg = {}; - dma_addr_t buf; - size_t len; - size_t period; int is_play = rsnd_io_is_play(io); - int i; int ret;
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, if (ret < 0) return ret;
- len = snd_pcm_lib_buffer_bytes(substream); - period = snd_pcm_lib_period_bytes(substream); - buf = dma_map_single(dmaen->chan->device->dev, - substream->runtime->dma_area, - len, - is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE); - if (dma_mapping_error(dmaen->chan->device->dev, buf)) { - dev_err(dev, "dma map failed\n"); - return -EIO; - } - desc = dmaengine_prep_dma_cyclic(dmaen->chan, - buf, len, period, + substream->runtime->dma_addr, + snd_pcm_lib_buffer_bytes(substream), + snd_pcm_lib_period_bytes(substream), is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
@@ -282,18 +219,7 @@ static int rsnd_dmaen_start(struct rsnd_mod *mod, desc->callback = rsnd_dmaen_complete; desc->callback_param = rsnd_mod_get(dma);
- dmaen->dma_buf = buf; - dmaen->dma_len = len; - dmaen->dma_period = period; - dmaen->dma_cnt = 0; - - /* - * synchronize this and next period - * see - * __rsnd_dmaen_complete() - */ - for (i = 0; i < 2; i++) - rsnd_dmaen_sync(dmaen, io, i); + dmaen->dma_len = snd_pcm_lib_buffer_bytes(substream);
dmaen->cookie = dmaengine_submit(desc); if (dmaen->cookie < 0) {
participants (3)
-
Kuninori Morimoto
-
Mark Brown
-
Takashi Iwai