| 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 |
| |