summaryrefslogtreecommitdiffstats
path: root/sound/soc/sh/rcar/dma.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2017-07-03 19:51:42 +0200
committerTakashi Iwai <tiwai@suse.de>2017-07-03 19:51:42 +0200
commit818a23e3882b1bf65d1719e407be04716e69a4d5 (patch)
tree6e4267b570541f779e7d85c11eb14312fa86fbb1 /sound/soc/sh/rcar/dma.c
parenta178232ddab55048e347b43b697bfa5013ef819e (diff)
parentb821d298f8864dc3c3d42643812df43289159507 (diff)
downloadlinux-stable-818a23e3882b1bf65d1719e407be04716e69a4d5.tar.gz
linux-stable-818a23e3882b1bf65d1719e407be04716e69a4d5.tar.bz2
linux-stable-818a23e3882b1bf65d1719e407be04716e69a4d5.zip
Merge tag 'asoc-v4.13' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus
ASoC: Updates for v4.13 The big news with this release is the of-graph card, this provides a replacement for simple-card that is much more flexibile and scalable, allowing many more systems to use a generic sound card than was possible before: - The of-graph card, finally merged after a long and dedicated effort by Morimoto-san. - New widget types intended mainly for use with DSPs. - New drivers for Allwinner V3s SoCs, Ensonic ES8316, several classes of x86 machine, Rockchip PDM controllers, STM32 I2S and S/PDIF controllers and ZTE AUD96P22 CODECs.
Diffstat (limited to 'sound/soc/sh/rcar/dma.c')
-rw-r--r--sound/soc/sh/rcar/dma.c32
1 files changed, 26 insertions, 6 deletions
diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c
index 241cb3b08a07..60aa5e96a49f 100644
--- a/sound/soc/sh/rcar/dma.c
+++ b/sound/soc/sh/rcar/dma.c
@@ -25,6 +25,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;
@@ -103,10 +104,6 @@ static void __rsnd_dmaen_complete(struct rsnd_mod *mod,
* In Gen2 case, it are Audio-DMAC, and Audio-DMAC-peri-peri.
* But, Audio-DMAC-peri-peri doesn't have interrupt,
* and this driver is assuming that here.
- *
- * If Audio-DMAC-peri-peri has interrpt,
- * rsnd_dai_pointer_update() will be called twice,
- * ant it will breaks io->byte_pos
*/
spin_lock_irqsave(&priv->lock, flags);
@@ -121,7 +118,7 @@ static void __rsnd_dmaen_complete(struct rsnd_mod *mod,
*/
rsnd_dmaen_sync(dmaen, io, dmaen->dma_cnt + 2);
- elapsed = rsnd_dai_pointer_update(io, io->byte_per_period);
+ elapsed = true;
dmaen->dma_cnt++;
}
@@ -292,7 +289,8 @@ static int rsnd_dmaen_start(struct rsnd_mod *mod,
for (i = 0; i < 2; i++)
rsnd_dmaen_sync(dmaen, io, i);
- if (dmaengine_submit(desc) < 0) {
+ dmaen->cookie = dmaengine_submit(desc);
+ if (dmaen->cookie < 0) {
dev_err(dev, "dmaengine_submit() fail\n");
return -EIO;
}
@@ -348,12 +346,34 @@ static int rsnd_dmaen_attach(struct rsnd_dai_stream *io,
return 0;
}
+static int rsnd_dmaen_pointer(struct rsnd_mod *mod,
+ struct rsnd_dai_stream *io,
+ snd_pcm_uframes_t *pointer)
+{
+ struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
+ struct rsnd_dma *dma = rsnd_mod_to_dma(mod);
+ struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma);
+ struct dma_tx_state state;
+ enum dma_status status;
+ unsigned int pos = 0;
+
+ status = dmaengine_tx_status(dmaen->chan, dmaen->cookie, &state);
+ if (status == DMA_IN_PROGRESS || status == DMA_PAUSED) {
+ if (state.residue > 0 && state.residue <= dmaen->dma_len)
+ pos = dmaen->dma_len - state.residue;
+ }
+ *pointer = bytes_to_frames(runtime, pos);
+
+ return 0;
+}
+
static struct rsnd_mod_ops rsnd_dmaen_ops = {
.name = "audmac",
.nolock_start = rsnd_dmaen_nolock_start,
.nolock_stop = rsnd_dmaen_nolock_stop,
.start = rsnd_dmaen_start,
.stop = rsnd_dmaen_stop,
+ .pointer= rsnd_dmaen_pointer,
};
/*