blob: 85b932fceb45e847f3983b50d16b8e5192e31bd1 [file] [log] [blame]
From 61b2df02c0b40d872eeb1e70c8569653e285f4b6 Mon Sep 17 00:00:00 2001
From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date: Thu, 23 Jan 2014 18:41:44 -0800
Subject: ASoC: rsnd: remove SSI dependent DMAEngine callback
Renesas Gen2 sound will use 2 DMAC
which are Audio-DMAC, and Audio-DMAC-peri-peri.
Current driver has callback function for each DMAC,
because it assumed each DMAC needs special settings.
But it became clear that these can share settings.
This patch removes unnecessary callback
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
(cherry picked from commit 4686a0ad9aaee89495f181e5755d153e7fe7ffe6)
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
---
sound/soc/sh/rcar/core.c | 38 +++++++++++++++++++++++++++-----------
sound/soc/sh/rcar/rsnd.h | 10 +++++-----
sound/soc/sh/rcar/ssi.c | 47 ++++++++---------------------------------------
3 files changed, 40 insertions(+), 55 deletions(-)
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c
index 11eb0e35b9ce..b5af6f5145ea 100644
--- a/sound/soc/sh/rcar/core.c
+++ b/sound/soc/sh/rcar/core.c
@@ -143,6 +143,7 @@ static void rsnd_dma_continue(struct rsnd_dma *dma)
void rsnd_dma_start(struct rsnd_dma *dma)
{
/* push both A and B plane*/
+ dma->offset = 0;
dma->submit_loop = 2;
__rsnd_dma_start(dma);
}
@@ -157,12 +158,26 @@ void rsnd_dma_stop(struct rsnd_dma *dma)
static void rsnd_dma_complete(void *data)
{
struct rsnd_dma *dma = (struct rsnd_dma *)data;
+ struct rsnd_mod *mod = rsnd_dma_to_mod(dma);
struct rsnd_priv *priv = rsnd_mod_to_priv(rsnd_dma_to_mod(dma));
+ struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
unsigned long flags;
rsnd_lock(priv, flags);
- dma->complete(dma);
+ /*
+ * Renesas sound Gen1 needs 1 DMAC,
+ * Gen2 needs 2 DMAC.
+ * 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
+ */
+
+ rsnd_dai_pointer_update(io, io->byte_per_period);
if (dma->submit_loop)
rsnd_dma_continue(dma);
@@ -172,17 +187,21 @@ static void rsnd_dma_complete(void *data)
static void __rsnd_dma_start(struct rsnd_dma *dma)
{
- struct rsnd_priv *priv = rsnd_mod_to_priv(rsnd_dma_to_mod(dma));
+ struct rsnd_mod *mod = rsnd_dma_to_mod(dma);
+ struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
+ struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
+ struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
struct device *dev = rsnd_priv_to_dev(priv);
struct dma_async_tx_descriptor *desc;
dma_addr_t buf;
- size_t len;
+ size_t len = io->byte_per_period;
int i;
for (i = 0; i < dma->submit_loop; i++) {
- if (dma->inquiry(dma, &buf, &len) < 0)
- return;
+ buf = runtime->dma_addr +
+ rsnd_dai_pointer_offset(io, dma->offset + len);
+ dma->offset = len;
desc = dmaengine_prep_slave_single(
dma->chan, buf, len, dma->dir,
@@ -217,10 +236,7 @@ int rsnd_dma_available(struct rsnd_dma *dma)
}
int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma,
- int is_play, int id,
- int (*inquiry)(struct rsnd_dma *dma,
- dma_addr_t *buf, int *len),
- int (*complete)(struct rsnd_dma *dma))
+ int is_play, int id)
{
struct device *dev = rsnd_priv_to_dev(priv);
struct dma_slave_config cfg;
@@ -253,8 +269,6 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma,
goto rsnd_dma_init_err;
dma->dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
- dma->inquiry = inquiry;
- dma->complete = complete;
INIT_WORK(&dma->work, rsnd_dma_do_work);
return 0;
@@ -307,6 +321,7 @@ int rsnd_dai_connect(struct rsnd_dai *rdai,
}
list_add_tail(&mod->list, &io->head);
+ mod->io = io;
return 0;
}
@@ -314,6 +329,7 @@ int rsnd_dai_connect(struct rsnd_dai *rdai,
int rsnd_dai_disconnect(struct rsnd_mod *mod)
{
list_del_init(&mod->list);
+ mod->io = NULL;
return 0;
}
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h
index c397dc8edee5..b2c717d2ba7e 100644
--- a/sound/soc/sh/rcar/rsnd.h
+++ b/sound/soc/sh/rcar/rsnd.h
@@ -100,19 +100,16 @@ struct rsnd_dma {
struct work_struct work;
struct dma_chan *chan;
enum dma_data_direction dir;
- int (*inquiry)(struct rsnd_dma *dma, dma_addr_t *buf, int *len);
- int (*complete)(struct rsnd_dma *dma);
int submit_loop;
+ int offset; /* it cares A/B plane */
};
void rsnd_dma_start(struct rsnd_dma *dma);
void rsnd_dma_stop(struct rsnd_dma *dma);
int rsnd_dma_available(struct rsnd_dma *dma);
int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma,
- int is_play, int id,
- int (*inquiry)(struct rsnd_dma *dma, dma_addr_t *buf, int *len),
- int (*complete)(struct rsnd_dma *dma));
+ int is_play, int id);
void rsnd_dma_quit(struct rsnd_priv *priv,
struct rsnd_dma *dma);
@@ -137,17 +134,20 @@ struct rsnd_mod_ops {
struct rsnd_dai_stream *io);
};
+struct rsnd_dai_stream;
struct rsnd_mod {
int id;
struct rsnd_priv *priv;
struct rsnd_mod_ops *ops;
struct list_head list; /* connect to rsnd_dai playback/capture */
struct rsnd_dma dma;
+ struct rsnd_dai_stream *io;
};
#define rsnd_mod_to_priv(mod) ((mod)->priv)
#define rsnd_mod_to_dma(mod) (&(mod)->dma)
#define rsnd_dma_to_mod(_dma) container_of((_dma), struct rsnd_mod, dma)
+#define rsnd_mod_to_io(mod) ((mod)->io)
#define rsnd_mod_id(mod) ((mod)->id)
#define for_each_rsnd_mod(pos, n, io) \
list_for_each_entry_safe(pos, n, &(io)->head, list)
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c
index b7f464ebcdc0..d3371d798d54 100644
--- a/sound/soc/sh/rcar/ssi.c
+++ b/sound/soc/sh/rcar/ssi.c
@@ -64,12 +64,10 @@ struct rsnd_ssi {
struct rsnd_mod mod;
struct rsnd_dai *rdai;
- struct rsnd_dai_stream *io;
u32 cr_own;
u32 cr_clk;
u32 cr_etc;
int err;
- int dma_offset;
unsigned int usrcnt;
unsigned int rate;
};
@@ -286,7 +284,6 @@ static int rsnd_ssi_init(struct rsnd_mod *mod,
* set ssi parameter
*/
ssi->rdai = rdai;
- ssi->io = io;
ssi->cr_own = cr;
ssi->err = -1; /* ignore 1st error */
@@ -305,7 +302,6 @@ static int rsnd_ssi_quit(struct rsnd_mod *mod,
dev_warn(dev, "ssi under/over flow err = %d\n", ssi->err);
ssi->rdai = NULL;
- ssi->io = NULL;
ssi->cr_own = 0;
ssi->err = 0;
@@ -329,8 +325,9 @@ static void rsnd_ssi_record_error(struct rsnd_ssi *ssi, u32 status)
static irqreturn_t rsnd_ssi_pio_interrupt(int irq, void *data)
{
struct rsnd_ssi *ssi = data;
- struct rsnd_dai_stream *io = ssi->io;
- u32 status = rsnd_mod_read(&ssi->mod, SSISR);
+ struct rsnd_mod *mod = &ssi->mod;
+ struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
+ u32 status = rsnd_mod_read(mod, SSISR);
irqreturn_t ret = IRQ_NONE;
if (io && (status & DIRQ)) {
@@ -347,9 +344,9 @@ static irqreturn_t rsnd_ssi_pio_interrupt(int irq, void *data)
* see rsnd_ssi_init()
*/
if (rsnd_dai_is_play(rdai, io))
- rsnd_mod_write(&ssi->mod, SSITDR, *buf);
+ rsnd_mod_write(mod, SSITDR, *buf);
else
- *buf = rsnd_mod_read(&ssi->mod, SSIRDR);
+ *buf = rsnd_mod_read(mod, SSIRDR);
rsnd_dai_pointer_update(io, sizeof(*buf));
@@ -394,33 +391,6 @@ static struct rsnd_mod_ops rsnd_ssi_pio_ops = {
.stop = rsnd_ssi_pio_stop,
};
-static int rsnd_ssi_dma_inquiry(struct rsnd_dma *dma, dma_addr_t *buf, int *len)
-{
- struct rsnd_ssi *ssi = rsnd_dma_to_ssi(dma);
- struct rsnd_dai_stream *io = ssi->io;
- struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
-
- *len = io->byte_per_period;
- *buf = runtime->dma_addr +
- rsnd_dai_pointer_offset(io, ssi->dma_offset + *len);
- ssi->dma_offset = *len; /* it cares A/B plane */
-
- return 0;
-}
-
-static int rsnd_ssi_dma_complete(struct rsnd_dma *dma)
-{
- struct rsnd_ssi *ssi = rsnd_dma_to_ssi(dma);
- struct rsnd_dai_stream *io = ssi->io;
- u32 status = rsnd_mod_read(&ssi->mod, SSISR);
-
- rsnd_ssi_record_error(ssi, status);
-
- rsnd_dai_pointer_update(ssi->io, io->byte_per_period);
-
- return 0;
-}
-
static int rsnd_ssi_dma_start(struct rsnd_mod *mod,
struct rsnd_dai *rdai,
struct rsnd_dai_stream *io)
@@ -430,7 +400,6 @@ static int rsnd_ssi_dma_start(struct rsnd_mod *mod,
/* enable DMA transfer */
ssi->cr_etc = DMEN;
- ssi->dma_offset = 0;
rsnd_dma_start(dma);
@@ -452,6 +421,8 @@ static int rsnd_ssi_dma_stop(struct rsnd_mod *mod,
ssi->cr_etc = 0;
+ rsnd_ssi_record_error(ssi, rsnd_mod_read(mod, SSISR));
+
rsnd_ssi_hw_stop(ssi, rdai);
rsnd_dma_stop(dma);
@@ -585,9 +556,7 @@ int rsnd_ssi_probe(struct platform_device *pdev,
ret = rsnd_dma_init(
priv, rsnd_mod_to_dma(&ssi->mod),
rsnd_ssi_is_play(&ssi->mod),
- pinfo->dma_id,
- rsnd_ssi_dma_inquiry,
- rsnd_ssi_dma_complete);
+ pinfo->dma_id);
if (ret < 0)
dev_info(dev, "SSI DMA failed. try PIO transter\n");
else
--
2.1.2