[alsa-devel] [PATCH 0/24 v2] ASoC: rsnd: move 2nd DMAC in rsnd driver and subnode dma-name support
Hi Mark, Arnd, Vinod Cc: Laurent, SH-ML
These patches add Audio DMAC peri peri implementation in rsnd driver. I will remove current DMAEngine side Audio DMAC peri peri implement if these are accepted. http://thread.gmane.org/gmane.linux.ports.sh.devel/41063/focus=43829
Arnd, Vinod
This series adds subnode DT support for 1st DMAC, and it is based on 1) patch. can you please check it ?
Mark
Actually, 1) patch has no relationship until 20). I guess this patch-set has merge issue. Can you check 2) - 19) as 1st step ?
1) : export of_dma_request_slave_channel() for 20) 2) - 6) : cleanup / tidyup 7) - 12) : Audio DMAC peri peri implementation 13) - 14) : cleanup. these are no longer needed now 15) - 19) : prepare for 1st DMAC dma-names subnode support 20) : 1st DMAC dma-names subnode subnode 21) - 24) : DT bindings text update
Kuninori Morimoto (24): 1) dmaengine: export symbol of of_dma_request_slave_channel() 2) ASoC: rsnd: remove SH-DMA-BASE specific implementation 3) ASoC: rsnd: remove un-needed parameter from rsnd_dma_init() 4) ASoC: rsnd: remove unused rsnd_dma_available() 5) ASoC: rsnd: remove un-needed parameter from rsnd_dma_quit() 6) ASoC: rsnd: tidyup rsnd_dma_to_mod() macro declaration position 7) ASoC: rsnd: enable to get resource by name 8) ASoC: rsnd: add rsnd_gen_get_phy_addr() to get physical address 9) ASoC: rsnd: add dma.c for Audio DMAC / Audio DMAC peri peri 10) ASoC: rsnd: move rsnd_gen_dma_addr() from gen.c to dma.c 11) ASoC: rsnd: enable to care 1st / 2nd DMAC on rsnd_dma_xxx() 12) ASoC: rsnd: add Audio DMAC peri peri support rework 13) ASoC: rsnd: remove rsnd_dma::addr 14) ASoC: rsnd: remove rsnd_dma::dir 15) ASoC: rsnd: use union with rsnd_dmaen / rsnd_dmapp 16) ASoC: rsnd: enable rsnd_ssi_use_busif() for DMA 17) ASoC: rsnd: ssi: add rsnd_ssi_of_node() 18) ASoC: rsnd: src: add rsnd_src_of_node() 19) ASoC: rsnd: dvc: add rsnd_dvc_of_node() 20) ASoC: rsnd: 1st DMAC dma-names cares subnode 21) ASoC: rsnd: add sample code of rcar_sound,src irq 22) ASoC: rsnd: add sample code of missing clocks 23) ASoC: rsnd: add sample code of dma entry 24) ASoC: rsnd: add sample code of reg-names
.../devicetree/bindings/sound/renesas,rsnd.txt | 125 +++- drivers/dma/of-dma.c | 1 + include/linux/of_dma.h | 4 +- sound/soc/sh/rcar/Makefile | 2 +- sound/soc/sh/rcar/core.c | 235 +------- sound/soc/sh/rcar/dma.c | 603 ++++++++++++++++++++ sound/soc/sh/rcar/dvc.c | 12 + sound/soc/sh/rcar/gen.c | 145 +---- sound/soc/sh/rcar/rsnd.h | 72 ++- sound/soc/sh/rcar/src.c | 23 +- sound/soc/sh/rcar/ssi.c | 28 +- 11 files changed, 838 insertions(+), 412 deletions(-)
Best regards --- Kuninori Morimoto _______________________________________________ Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
Current DMAEngine implementation of DT bindings can't support DT subnode. This patch export symbols of of_dma_request_slave_channel() for subnode DMA DT bingings.
ex)
rcar_sound: rcar_sound@ec500000 { ... rcar_sound,dvc { dvc0: dvc@0 { dmas = <&audma0 0xbc>; dma-names = "tx"; }; dvc1: dvc@1 { dmas = <&audma0 0xbe>; dma-names = "tx"; }; }; ... };
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- v1 -> v2
- new patch
drivers/dma/of-dma.c | 1 + include/linux/of_dma.h | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/dma/of-dma.c b/drivers/dma/of-dma.c index ca31f1b..cbd4a8a 100644 --- a/drivers/dma/of-dma.c +++ b/drivers/dma/of-dma.c @@ -194,6 +194,7 @@ struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
return ERR_PTR(ret_no_channel); } +EXPORT_SYMBOL_GPL(of_dma_request_slave_channel);
/** * of_dma_simple_xlate - Simple DMA engine translation function diff --git a/include/linux/of_dma.h b/include/linux/of_dma.h index 56bc026..687a0ac 100644 --- a/include/linux/of_dma.h +++ b/include/linux/of_dma.h @@ -37,8 +37,8 @@ extern int of_dma_controller_register(struct device_node *np, (struct of_phandle_args *, struct of_dma *), void *data); extern void of_dma_controller_free(struct device_node *np); -extern struct dma_chan *of_dma_request_slave_channel(struct device_node *np, - const char *name); +struct dma_chan *of_dma_request_slave_channel(struct device_node *np, + const char *name); extern struct dma_chan *of_dma_simple_xlate(struct of_phandle_args *dma_spec, struct of_dma *ofdma); extern struct dma_chan *of_dma_xlate_by_chan_id(struct of_phandle_args *dma_spec,
Hi Morimoto-san,
On Fri, Feb 20, 2015 at 11:22 AM, Kuninori Morimoto kuninori.morimoto.gx@renesas.com wrote:
--- a/include/linux/of_dma.h +++ b/include/linux/of_dma.h @@ -37,8 +37,8 @@ extern int of_dma_controller_register(struct device_node *np, (struct of_phandle_args *, struct of_dma *), void *data); extern void of_dma_controller_free(struct device_node *np); -extern struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
const char *name);
+struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
const char *name);
Why have you dropped the "extern" keyword? Checkpach? All prototypes in the neighborhood have "extern" keywords, so I think it's better to keep it for consistency.
extern struct dma_chan *of_dma_simple_xlate(struct of_phandle_args *dma_spec, struct of_dma *ofdma); extern struct dma_chan *of_dma_xlate_by_chan_id(struct of_phandle_args *dma_spec,
Hi Geert, Vinod
--- a/include/linux/of_dma.h +++ b/include/linux/of_dma.h @@ -37,8 +37,8 @@ extern int of_dma_controller_register(struct device_node *np, (struct of_phandle_args *, struct of_dma *), void *data); extern void of_dma_controller_free(struct device_node *np); -extern struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
const char *name);
+struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
const char *name);
Why have you dropped the "extern" keyword? Checkpach? All prototypes in the neighborhood have "extern" keywords, so I think it's better to keep it for consistency.
OK, I can fix it. But, this is very large patchset (24 patches !). I don't want to send all patches if possible. I will send only [01/24 v3] now. Please let me know if it is not OK.
Best regards --- Kuninori Morimoto
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
Current DMAEngine implementation of DT bindings can't support DT subnode. This patch export symbols of of_dma_request_slave_channel() for subnode DMA DT bingings.
ex)
rcar_sound: rcar_sound@ec500000 { ... rcar_sound,dvc { dvc0: dvc@0 { dmas = <&audma0 0xbc>; dma-names = "tx"; }; dvc1: dvc@1 { dmas = <&audma0 0xbe>; dma-names = "tx"; }; }; ... };
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- v2 -> v3
- don't remove export from of_dma.h
drivers/dma/of-dma.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/dma/of-dma.c b/drivers/dma/of-dma.c index ca31f1b..cbd4a8a 100644 --- a/drivers/dma/of-dma.c +++ b/drivers/dma/of-dma.c @@ -194,6 +194,7 @@ struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
return ERR_PTR(ret_no_channel); } +EXPORT_SYMBOL_GPL(of_dma_request_slave_channel);
/** * of_dma_simple_xlate - Simple DMA engine translation function
On Tue, Feb 24, 2015 at 12:54:16AM +0000, Kuninori Morimoto wrote:
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
Current DMAEngine implementation of DT bindings can't support DT subnode. This patch export symbols of of_dma_request_slave_channel() for subnode DMA DT bingings.
ex)
rcar_sound: rcar_sound@ec500000 { ... rcar_sound,dvc { dvc0: dvc@0 { dmas = <&audma0 0xbc>; dma-names = "tx"; }; dvc1: dvc@1 { dmas = <&audma0 0xbe>; dma-names = "tx"; }; }; ... };
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
v2 -> v3
- don't remove export from of_dma.h
drivers/dma/of-dma.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/dma/of-dma.c b/drivers/dma/of-dma.c index ca31f1b..cbd4a8a 100644 --- a/drivers/dma/of-dma.c +++ b/drivers/dma/of-dma.c @@ -194,6 +194,7 @@ struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
return ERR_PTR(ret_no_channel); } +EXPORT_SYMBOL_GPL(of_dma_request_slave_channel);
/**
- of_dma_simple_xlate - Simple DMA engine translation function
Typically you should post whole series. Anyway, i am okay with this patch, how do you want to merge this, should i pick it up or everything goes thru ASoC tree or something else?
Hi Mark
Current DMAEngine implementation of DT bindings can't support DT subnode. This patch export symbols of of_dma_request_slave_channel() for subnode DMA DT bingings.
ex)
rcar_sound: rcar_sound@ec500000 { ... rcar_sound,dvc { dvc0: dvc@0 { dmas = <&audma0 0xbc>; dma-names = "tx"; }; dvc1: dvc@1 { dmas = <&audma0 0xbe>; dma-names = "tx"; }; }; ... };
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
(snip)
Typically you should post whole series. Anyway, i am okay with this patch, how do you want to merge this, should i pick it up or everything goes thru ASoC tree or something else?
I don't know detail of maintenance side. Which is best ?
Best regards --- Kuninori Morimoto
On Wed, Feb 25, 2015 at 12:03:03AM +0000, Kuninori Morimoto wrote:
Hi Mark
Current DMAEngine implementation of DT bindings can't support DT subnode. This patch export symbols of of_dma_request_slave_channel() for subnode DMA DT bingings.
ex)
rcar_sound: rcar_sound@ec500000 { ... rcar_sound,dvc { dvc0: dvc@0 { dmas = <&audma0 0xbc>; dma-names = "tx"; }; dvc1: dvc@1 { dmas = <&audma0 0xbe>; dma-names = "tx"; }; }; ... };
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
(snip)
Typically you should post whole series. Anyway, i am okay with this patch, how do you want to merge this, should i pick it up or everything goes thru ASoC tree or something else?
I don't know detail of maintenance side. Which is best ?
I think Mark can take the whole series with my ack on this one so
Acked-by: Vinod Koul vinod.koul@intel.com
I need I will pull Marks topic into mine but I think that may not be required..
Hi Mark
Typically you should post whole series. Anyway, i am okay with this patch, how do you want to merge this, should i pick it up or everything goes thru ASoC tree or something else?
I don't know detail of maintenance side. Which is best ?
I think Mark can take the whole series with my ack on this one so
Acked-by: Vinod Koul vinod.koul@intel.com
I need I will pull Marks topic into mine but I think that may not be required..
Please let me know if I need to resend these patches.
On Tue, Feb 24, 2015 at 12:54:16AM +0000, Kuninori Morimoto wrote:
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
Current DMAEngine implementation of DT bindings can't support DT subnode. This patch export symbols of of_dma_request_slave_channel() for subnode DMA DT bingings.
Applied, thanks.
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
Renesas R-Car sound had SH-DMA-BASE specific implementation before, but, now, it is no longer needed. Let's remove it.
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- v1 -> v2
- no change
sound/soc/sh/rcar/core.c | 1 - sound/soc/sh/rcar/rsnd.h | 1 - 2 files changed, 2 deletions(-)
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 1b53605..0b14d37 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -94,7 +94,6 @@ * */ #include <linux/pm_runtime.h> -#include <linux/shdma-base.h> #include "rsnd.h"
#define RSND_RATES SNDRV_PCM_RATE_8000_96000 diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index e7914bd..5ffde9b 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -171,7 +171,6 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod); * R-Car DMA */ struct rsnd_dma { - struct sh_dmae_slave slave; struct dma_chan *chan; enum dma_transfer_direction dir; dma_addr_t addr;
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
It can get DMA direction via rsnd_dai_stream. Remove un-needed is_play from rsnd_dma_init().
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- v1 -> v2
- no change
sound/soc/sh/rcar/core.c | 6 ++++-- sound/soc/sh/rcar/rsnd.h | 16 +--------------- sound/soc/sh/rcar/src.c | 1 - sound/soc/sh/rcar/ssi.c | 1 - 4 files changed, 5 insertions(+), 19 deletions(-)
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 0b14d37..1edf4dc 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -311,13 +311,15 @@ static void rsnd_dma_of_path(struct rsnd_dma *dma, } }
-int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, - int is_play, int id) +int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id) { struct device *dev = rsnd_priv_to_dev(priv); struct dma_slave_config cfg; + struct rsnd_mod *mod = rsnd_dma_to_mod(dma); struct rsnd_mod *mod_from; struct rsnd_mod *mod_to; + struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); + int is_play = rsnd_io_is_play(io); char dma_name[DMA_NAME_SIZE]; dma_cap_mask_t mask; int ret; diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 5ffde9b..93a1a25 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -179,8 +179,7 @@ struct rsnd_dma { 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 rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id); void rsnd_dma_quit(struct rsnd_priv *priv, struct rsnd_dma *dma);
@@ -413,19 +412,6 @@ struct rsnd_priv { #define rsnd_lock(priv, flags) spin_lock_irqsave(&priv->lock, flags) #define rsnd_unlock(priv, flags) spin_unlock_irqrestore(&priv->lock, flags)
-#define rsnd_info_is_playback(priv, type) \ -({ \ - struct rcar_snd_info *info = rsnd_priv_to_info(priv); \ - int i, is_play = 0; \ - for (i = 0; i < info->dai_info_nr; i++) { \ - if (info->dai_info[i].playback.type == (type)->info) { \ - is_play = 1; \ - break; \ - } \ - } \ - is_play; \ -}) - /* * rsnd_kctrl */ diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c index 81c182b..7fb8798 100644 --- a/sound/soc/sh/rcar/src.c +++ b/sound/soc/sh/rcar/src.c @@ -713,7 +713,6 @@ static int rsnd_src_probe_gen2(struct rsnd_mod *mod,
ret = rsnd_dma_init(priv, rsnd_mod_to_dma(mod), - rsnd_info_is_playback(priv, src), src->info->dma_id); if (ret) goto rsnd_src_probe_gen2_fail; diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 9e7b627..57e737c 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -478,7 +478,6 @@ static int rsnd_ssi_dma_probe(struct rsnd_mod *mod,
ret = rsnd_dma_init( priv, rsnd_mod_to_dma(mod), - rsnd_info_is_playback(priv, ssi), dma_id); if (ret) goto rsnd_ssi_dma_probe_fail;
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
rsnd_dma_available() is not used. Let's remove it.
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- v1 -> v2
- no change
sound/soc/sh/rcar/core.c | 5 ----- sound/soc/sh/rcar/rsnd.h | 1 - sound/soc/sh/rcar/src.c | 2 -- sound/soc/sh/rcar/ssi.c | 2 -- 4 files changed, 10 deletions(-)
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 1edf4dc..1da94bf 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -222,11 +222,6 @@ void rsnd_dma_start(struct rsnd_dma *dma) dma_async_issue_pending(dma->chan); }
-int rsnd_dma_available(struct rsnd_dma *dma) -{ - return !!dma->chan; -} - #define DMA_NAME_SIZE 16 #define MOD_MAX 4 /* MEM/SSI/SRC/DVC */ static int _rsnd_dma_of_name(char *dma_name, struct rsnd_mod *mod) diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 93a1a25..cb12861a 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -178,7 +178,6 @@ struct rsnd_dma {
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 id); void rsnd_dma_quit(struct rsnd_priv *priv, struct rsnd_dma *dma); diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c index 7fb8798..f12c8b3 100644 --- a/sound/soc/sh/rcar/src.c +++ b/sound/soc/sh/rcar/src.c @@ -30,8 +30,6 @@ struct rsnd_src { #define rsnd_src_convert_rate(p) ((p)->info->convert_rate) #define rsnd_mod_to_src(_mod) \ container_of((_mod), struct rsnd_src, mod) -#define rsnd_src_dma_available(src) \ - rsnd_dma_available(rsnd_mod_to_dma(&(src)->mod))
#define for_each_rsnd_src(pos, priv, i) \ for ((i) = 0; \ diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 57e737c..fcc77ea 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -80,8 +80,6 @@ struct rsnd_ssi { #define rsnd_mod_to_ssi(_mod) container_of((_mod), struct rsnd_ssi, mod) #define rsnd_dma_to_ssi(dma) rsnd_mod_to_ssi(rsnd_dma_to_mod(dma)) #define rsnd_ssi_pio_available(ssi) ((ssi)->info->irq > 0) -#define rsnd_ssi_dma_available(ssi) \ - rsnd_dma_available(rsnd_mod_to_dma(&(ssi)->mod)) #define rsnd_ssi_clk_from_parent(ssi) ((ssi)->parent) #define rsnd_ssi_mode_flags(p) ((p)->info->flags) #define rsnd_ssi_dai_id(ssi) ((ssi)->info->dai_id)
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
priv is not used on rsnd_dma_quit()
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- v1 -> v2
- no change
sound/soc/sh/rcar/core.c | 5 ++--- sound/soc/sh/rcar/rsnd.h | 3 +-- sound/soc/sh/rcar/src.c | 2 +- sound/soc/sh/rcar/ssi.c | 2 +- 4 files changed, 5 insertions(+), 7 deletions(-)
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 1da94bf..7db686d 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -358,7 +358,7 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id) return 0;
rsnd_dma_init_err: - rsnd_dma_quit(priv, dma); + rsnd_dma_quit(dma); rsnd_dma_channel_err:
/* @@ -370,8 +370,7 @@ rsnd_dma_channel_err: return -EAGAIN; }
-void rsnd_dma_quit(struct rsnd_priv *priv, - struct rsnd_dma *dma) +void rsnd_dma_quit(struct rsnd_dma *dma) { if (dma->chan) dma_release_channel(dma->chan); diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index cb12861a..6ee97e7 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -179,8 +179,7 @@ struct rsnd_dma { void rsnd_dma_start(struct rsnd_dma *dma); void rsnd_dma_stop(struct rsnd_dma *dma); int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id); -void rsnd_dma_quit(struct rsnd_priv *priv, - struct rsnd_dma *dma); +void rsnd_dma_quit(struct rsnd_dma *dma);
/* diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c index f12c8b3..e279205 100644 --- a/sound/soc/sh/rcar/src.c +++ b/sound/soc/sh/rcar/src.c @@ -730,7 +730,7 @@ rsnd_src_probe_gen2_fail: static int rsnd_src_remove_gen2(struct rsnd_mod *mod, struct rsnd_priv *priv) { - rsnd_dma_quit(priv, rsnd_mod_to_dma(mod)); + rsnd_dma_quit(rsnd_mod_to_dma(mod));
return 0; } diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index fcc77ea..a0d902a 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -499,7 +499,7 @@ static int rsnd_ssi_dma_remove(struct rsnd_mod *mod, struct device *dev = rsnd_priv_to_dev(priv); int irq = ssi->info->irq;
- rsnd_dma_quit(priv, rsnd_mod_to_dma(mod)); + rsnd_dma_quit(rsnd_mod_to_dma(mod));
/* PIO will request IRQ again */ devm_free_irq(dev, irq, ssi);
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- v1 -> v2
- no change
sound/soc/sh/rcar/rsnd.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 6ee97e7..ec77c9f 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -182,6 +182,8 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id); void rsnd_dma_quit(struct rsnd_dma *dma);
+#define rsnd_dma_to_mod(_dma) container_of((_dma), struct rsnd_mod, dma) + /* * R-Car sound mod */ @@ -253,7 +255,6 @@ struct rsnd_mod {
#define rsnd_mod_to_priv(mod) (rsnd_io_to_priv(rsnd_mod_to_io(mod))) #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 rsnd_mod_hw_start(mod) clk_prepare_enable((mod)->clk)
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
rsnd driver needs to support Audio DMAC peri peri inside sound driver. getting resource by name is useful for it
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- v1 -> v2
- no change
sound/soc/sh/rcar/gen.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-)
diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index de0685f..d08bcd3 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -118,11 +118,12 @@ void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, mask, data); }
-#define rsnd_gen_regmap_init(priv, id_size, reg_id, conf) \ - _rsnd_gen_regmap_init(priv, id_size, reg_id, conf, ARRAY_SIZE(conf)) +#define rsnd_gen_regmap_init(priv, id_size, reg_id, name, conf) \ + _rsnd_gen_regmap_init(priv, id_size, reg_id, name, conf, ARRAY_SIZE(conf)) static int _rsnd_gen_regmap_init(struct rsnd_priv *priv, int id_size, int reg_id, + const char *name, struct rsnd_regmap_field_conf *conf, int conf_size) { @@ -142,7 +143,9 @@ static int _rsnd_gen_regmap_init(struct rsnd_priv *priv, regc.val_bits = 32; regc.reg_stride = 4;
- res = platform_get_resource(pdev, IORESOURCE_MEM, reg_id); + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name); + if (!res) + res = platform_get_resource(pdev, IORESOURCE_MEM, reg_id); if (!res) return -ENODEV;
@@ -368,10 +371,10 @@ static int rsnd_gen2_probe(struct platform_device *pdev, int ret_adg; int ret_ssi;
- ret_ssiu = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_SSIU, conf_ssiu); - ret_scu = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_SCU, conf_scu); - ret_adg = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_ADG, conf_adg); - ret_ssi = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_SSI, conf_ssi); + ret_ssiu = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_SSIU, "ssiu", conf_ssiu); + ret_scu = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_SCU, "scu", conf_scu); + ret_adg = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_ADG, "adg", conf_adg); + ret_ssi = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_SSI, "ssi", conf_ssi); if (ret_ssiu < 0 || ret_scu < 0 || ret_adg < 0 || @@ -440,9 +443,9 @@ static int rsnd_gen1_probe(struct platform_device *pdev, int ret_adg; int ret_ssi;
- ret_sru = rsnd_gen_regmap_init(priv, 9, RSND_GEN1_SRU, conf_sru); - ret_adg = rsnd_gen_regmap_init(priv, 9, RSND_GEN1_ADG, conf_adg); - ret_ssi = rsnd_gen_regmap_init(priv, 9, RSND_GEN1_SSI, conf_ssi); + ret_sru = rsnd_gen_regmap_init(priv, 9, RSND_GEN1_SRU, "sru", conf_sru); + ret_adg = rsnd_gen_regmap_init(priv, 9, RSND_GEN1_ADG, "adg", conf_adg); + ret_ssi = rsnd_gen_regmap_init(priv, 9, RSND_GEN1_SSI, "ssi", conf_ssi); if (ret_sru < 0 || ret_adg < 0 || ret_ssi < 0)
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
physical address is required from Audio DMAC peri peri.
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- v1 -> v2
- no change
sound/soc/sh/rcar/gen.c | 16 +++++++++++----- sound/soc/sh/rcar/rsnd.h | 1 + 2 files changed, 12 insertions(+), 5 deletions(-)
diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index d08bcd3..0da04ed 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -28,6 +28,7 @@ struct rsnd_gen {
struct regmap *regmap[RSND_BASE_MAX]; struct regmap_field *regs[RSND_REG_MAX]; + phys_addr_t res[RSND_REG_MAX]; };
#define rsnd_priv_to_gen(p) ((struct rsnd_gen *)(p)->gen) @@ -118,6 +119,13 @@ void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, mask, data); }
+phys_addr_t rsnd_gen_get_phy_addr(struct rsnd_priv *priv, int reg_id) +{ + struct rsnd_gen *gen = rsnd_priv_to_gen(priv); + + return gen->res[reg_id]; +} + #define rsnd_gen_regmap_init(priv, id_size, reg_id, name, conf) \ _rsnd_gen_regmap_init(priv, id_size, reg_id, name, conf, ARRAY_SIZE(conf)) static int _rsnd_gen_regmap_init(struct rsnd_priv *priv, @@ -159,6 +167,7 @@ static int _rsnd_gen_regmap_init(struct rsnd_priv *priv,
gen->base[reg_id] = base; gen->regmap[reg_id] = regmap; + gen->res[reg_id] = res->start;
for (i = 0; i < conf_size; i++) {
@@ -216,13 +225,10 @@ rsnd_gen2_dma_addr(struct rsnd_priv *priv, struct rsnd_mod *mod, int is_play, int is_from) { - struct platform_device *pdev = rsnd_priv_to_pdev(priv); struct device *dev = rsnd_priv_to_dev(priv); struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); - dma_addr_t ssi_reg = platform_get_resource(pdev, - IORESOURCE_MEM, RSND_GEN2_SSI)->start; - dma_addr_t src_reg = platform_get_resource(pdev, - IORESOURCE_MEM, RSND_GEN2_SCU)->start; + phys_addr_t ssi_reg = rsnd_gen_get_phy_addr(priv, RSND_GEN2_SSI); + phys_addr_t src_reg = rsnd_gen_get_phy_addr(priv, RSND_GEN2_SCU); int is_ssi = !!(rsnd_io_to_mod_ssi(io) == mod); int use_src = !!rsnd_io_to_mod_src(io); int use_dvc = !!rsnd_io_to_mod_dvc(io); diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index ec77c9f..8a8a4d5 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -331,6 +331,7 @@ void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv, dma_addr_t rsnd_gen_dma_addr(struct rsnd_priv *priv, struct rsnd_mod *mod, int is_play, int is_from); +phys_addr_t rsnd_gen_get_phy_addr(struct rsnd_priv *priv, int reg_id);
#define rsnd_is_gen1(s) (((s)->info->flags & RSND_GEN_MASK) == RSND_GEN1) #define rsnd_is_gen2(s) (((s)->info->flags & RSND_GEN_MASK) == RSND_GEN2)
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
Renesas sound driver had been assumed that Audio DMAC / Audio DMAC peri peri are implemented by DMAEngine. But, result of DMA ML discussion, it was concluded that it is not a general purpose DMAC. And it should be moved from current DMAEngine to rsnd driver. So, Audio DMAC peri peri become non DMAEngine.
OTOH, ALSA SoC has soc-generic-dmaengine-pcm implementation. but it seems difficult to use this generic implementation on rsnd driver at this point, since it needs to fallback to PIO mode if DMA can't use. and additionally it needs 2 DMAC (= Audio DMAC / Audio DMAC peri peri). These are not "generic" feature.
Of course I will try to use this generic dmaengine in the future somehow, but just use current style at this point until it can formally use 2 DMACs. This patch adds new dma.c and moves current dma code to dma.c from core.c.
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- v1 -> v2
- no change
sound/soc/sh/rcar/Makefile | 2 +- sound/soc/sh/rcar/core.c | 218 ----------------------------------------- sound/soc/sh/rcar/dma.c | 231 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 232 insertions(+), 219 deletions(-) create mode 100644 sound/soc/sh/rcar/dma.c
diff --git a/sound/soc/sh/rcar/Makefile b/sound/soc/sh/rcar/Makefile index 9ac5364..7b20492 100644 --- a/sound/soc/sh/rcar/Makefile +++ b/sound/soc/sh/rcar/Makefile @@ -1,2 +1,2 @@ -snd-soc-rcar-objs := core.o gen.o src.o adg.o ssi.o dvc.o +snd-soc-rcar-objs := core.o gen.o dma.o src.o adg.o ssi.o dvc.o obj-$(CONFIG_SND_SOC_RCAR) += snd-soc-rcar.o \ No newline at end of file diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 7db686d..9beea9b 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -161,224 +161,6 @@ void rsnd_mod_init(struct rsnd_mod *mod, }
/* - * rsnd_dma functions - */ -void rsnd_dma_stop(struct rsnd_dma *dma) -{ - dmaengine_terminate_all(dma->chan); -} - -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_dai_stream *io = rsnd_mod_to_io(mod); - - /* - * 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); -} - -void rsnd_dma_start(struct rsnd_dma *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_substream *substream = io->substream; - struct device *dev = rsnd_priv_to_dev(priv); - struct dma_async_tx_descriptor *desc; - - desc = dmaengine_prep_dma_cyclic(dma->chan, - (dma->addr) ? dma->addr : - substream->runtime->dma_addr, - snd_pcm_lib_buffer_bytes(substream), - snd_pcm_lib_period_bytes(substream), - dma->dir, - DMA_PREP_INTERRUPT | DMA_CTRL_ACK); - - if (!desc) { - dev_err(dev, "dmaengine_prep_slave_sg() fail\n"); - return; - } - - desc->callback = rsnd_dma_complete; - desc->callback_param = dma; - - if (dmaengine_submit(desc) < 0) { - dev_err(dev, "dmaengine_submit() fail\n"); - return; - } - - dma_async_issue_pending(dma->chan); -} - -#define DMA_NAME_SIZE 16 -#define MOD_MAX 4 /* MEM/SSI/SRC/DVC */ -static int _rsnd_dma_of_name(char *dma_name, struct rsnd_mod *mod) -{ - if (mod) - return snprintf(dma_name, DMA_NAME_SIZE / 2, "%s%d", - rsnd_mod_dma_name(mod), rsnd_mod_id(mod)); - else - return snprintf(dma_name, DMA_NAME_SIZE / 2, "mem"); - -} - -static void rsnd_dma_of_name(struct rsnd_mod *mod_from, - struct rsnd_mod *mod_to, - char *dma_name) -{ - int index = 0; - - index = _rsnd_dma_of_name(dma_name + index, mod_from); - *(dma_name + index++) = '_'; - index = _rsnd_dma_of_name(dma_name + index, mod_to); -} - -static void rsnd_dma_of_path(struct rsnd_dma *dma, - int is_play, - struct rsnd_mod **mod_from, - struct rsnd_mod **mod_to) -{ - struct rsnd_mod *this = rsnd_dma_to_mod(dma); - struct rsnd_dai_stream *io = rsnd_mod_to_io(this); - struct rsnd_mod *ssi = rsnd_io_to_mod_ssi(io); - struct rsnd_mod *src = rsnd_io_to_mod_src(io); - struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io); - struct rsnd_mod *mod[MOD_MAX]; - int i, index; - - - for (i = 0; i < MOD_MAX; i++) - mod[i] = NULL; - - /* - * in play case... - * - * src -> dst - * - * mem -> SSI - * mem -> SRC -> SSI - * mem -> SRC -> DVC -> SSI - */ - mod[0] = NULL; /* for "mem" */ - index = 1; - for (i = 1; i < MOD_MAX; i++) { - if (!src) { - mod[i] = ssi; - } else if (!dvc) { - mod[i] = src; - src = NULL; - } else { - if ((!is_play) && (this == src)) - this = dvc; - - mod[i] = (is_play) ? src : dvc; - i++; - mod[i] = (is_play) ? dvc : src; - src = NULL; - dvc = NULL; - } - - if (mod[i] == this) - index = i; - - if (mod[i] == ssi) - break; - } - - if (is_play) { - *mod_from = mod[index - 1]; - *mod_to = mod[index]; - } else { - *mod_from = mod[index]; - *mod_to = mod[index - 1]; - } -} - -int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id) -{ - struct device *dev = rsnd_priv_to_dev(priv); - struct dma_slave_config cfg; - struct rsnd_mod *mod = rsnd_dma_to_mod(dma); - struct rsnd_mod *mod_from; - struct rsnd_mod *mod_to; - struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); - int is_play = rsnd_io_is_play(io); - char dma_name[DMA_NAME_SIZE]; - dma_cap_mask_t mask; - int ret; - - if (dma->chan) { - dev_err(dev, "it already has dma channel\n"); - return -EIO; - } - - dma_cap_zero(mask); - dma_cap_set(DMA_SLAVE, mask); - - rsnd_dma_of_path(dma, is_play, &mod_from, &mod_to); - rsnd_dma_of_name(mod_from, mod_to, dma_name); - - cfg.slave_id = id; - cfg.direction = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; - cfg.src_addr = rsnd_gen_dma_addr(priv, mod_from, is_play, 1); - cfg.dst_addr = rsnd_gen_dma_addr(priv, mod_to, is_play, 0); - cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; - cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; - - dev_dbg(dev, "dma : %s %pad -> %pad\n", - dma_name, &cfg.src_addr, &cfg.dst_addr); - - dma->chan = dma_request_slave_channel_compat(mask, shdma_chan_filter, - (void *)id, dev, - dma_name); - if (!dma->chan) { - dev_err(dev, "can't get dma channel\n"); - goto rsnd_dma_channel_err; - } - - ret = dmaengine_slave_config(dma->chan, &cfg); - if (ret < 0) - goto rsnd_dma_init_err; - - dma->addr = is_play ? cfg.src_addr : cfg.dst_addr; - dma->dir = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; - - return 0; - -rsnd_dma_init_err: - rsnd_dma_quit(dma); -rsnd_dma_channel_err: - - /* - * DMA failed. try to PIO mode - * see - * rsnd_ssi_fallback() - * rsnd_rdai_continuance_probe() - */ - return -EAGAIN; -} - -void rsnd_dma_quit(struct rsnd_dma *dma) -{ - if (dma->chan) - dma_release_channel(dma->chan); - - dma->chan = NULL; -} - -/* * settting function */ u32 rsnd_get_adinr(struct rsnd_mod *mod) diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c new file mode 100644 index 0000000..37acd40 --- /dev/null +++ b/sound/soc/sh/rcar/dma.c @@ -0,0 +1,231 @@ +/* + * Renesas R-Car Audio DMAC support + * + * Copyright (C) 2015 Renesas Electronics Corp. + * Copyright (c) 2015 Kuninori Morimoto kuninori.morimoto.gx@renesas.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include "rsnd.h" + +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_dai_stream *io = rsnd_mod_to_io(mod); + + /* + * 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); +} + +#define DMA_NAME_SIZE 16 +#define MOD_MAX 4 /* MEM/SSI/SRC/DVC */ +static int _rsnd_dma_of_name(char *dma_name, struct rsnd_mod *mod) +{ + if (mod) + return snprintf(dma_name, DMA_NAME_SIZE / 2, "%s%d", + rsnd_mod_dma_name(mod), rsnd_mod_id(mod)); + else + return snprintf(dma_name, DMA_NAME_SIZE / 2, "mem"); + +} + +static void rsnd_dma_of_name(struct rsnd_mod *mod_from, + struct rsnd_mod *mod_to, + char *dma_name) +{ + int index = 0; + + index = _rsnd_dma_of_name(dma_name + index, mod_from); + *(dma_name + index++) = '_'; + index = _rsnd_dma_of_name(dma_name + index, mod_to); +} + +void rsnd_dma_stop(struct rsnd_dma *dma) +{ + dmaengine_terminate_all(dma->chan); +} + +void rsnd_dma_start(struct rsnd_dma *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_substream *substream = io->substream; + struct device *dev = rsnd_priv_to_dev(priv); + struct dma_async_tx_descriptor *desc; + + desc = dmaengine_prep_dma_cyclic(dma->chan, + (dma->addr) ? dma->addr : + substream->runtime->dma_addr, + snd_pcm_lib_buffer_bytes(substream), + snd_pcm_lib_period_bytes(substream), + dma->dir, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + + if (!desc) { + dev_err(dev, "dmaengine_prep_slave_sg() fail\n"); + return; + } + + desc->callback = rsnd_dma_complete; + desc->callback_param = dma; + + if (dmaengine_submit(desc) < 0) { + dev_err(dev, "dmaengine_submit() fail\n"); + return; + } + + dma_async_issue_pending(dma->chan); +} + +static void rsnd_dma_of_path(struct rsnd_dma *dma, + int is_play, + struct rsnd_mod **mod_from, + struct rsnd_mod **mod_to); + +int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id) +{ + struct device *dev = rsnd_priv_to_dev(priv); + struct dma_slave_config cfg = {}; + struct rsnd_mod *mod = rsnd_dma_to_mod(dma); + struct rsnd_mod *mod_from; + struct rsnd_mod *mod_to; + struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); + int is_play = rsnd_io_is_play(io); + char dma_name[DMA_NAME_SIZE]; + dma_cap_mask_t mask; + int ret; + + if (dma->chan) { + dev_err(dev, "it already has dma channel\n"); + return -EIO; + } + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + + rsnd_dma_of_path(dma, is_play, &mod_from, &mod_to); + rsnd_dma_of_name(mod_from, mod_to, dma_name); + + cfg.direction = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; + cfg.src_addr = rsnd_gen_dma_addr(priv, mod_from, is_play, 1); + cfg.dst_addr = rsnd_gen_dma_addr(priv, mod_to, is_play, 0); + cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + + dev_dbg(dev, "dma : %s %pad -> %pad\n", + dma_name, &cfg.src_addr, &cfg.dst_addr); + + dma->chan = dma_request_slave_channel_compat(mask, shdma_chan_filter, + (void *)id, dev, + dma_name); + if (!dma->chan) { + dev_err(dev, "can't get dma channel\n"); + goto rsnd_dma_channel_err; + } + + ret = dmaengine_slave_config(dma->chan, &cfg); + if (ret < 0) + goto rsnd_dma_init_err; + + dma->addr = is_play ? cfg.src_addr : cfg.dst_addr; + dma->dir = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; + + return 0; + +rsnd_dma_init_err: + rsnd_dma_quit(dma); +rsnd_dma_channel_err: + + /* + * DMA failed. try to PIO mode + * see + * rsnd_ssi_fallback() + * rsnd_rdai_continuance_probe() + */ + return -EAGAIN; +} + +void rsnd_dma_quit(struct rsnd_dma *dma) +{ + if (dma->chan) + dma_release_channel(dma->chan); + + dma->chan = NULL; +} + +static void rsnd_dma_of_path(struct rsnd_dma *dma, + int is_play, + struct rsnd_mod **mod_from, + struct rsnd_mod **mod_to) +{ + struct rsnd_mod *this = rsnd_dma_to_mod(dma); + struct rsnd_dai_stream *io = rsnd_mod_to_io(this); + struct rsnd_mod *ssi = rsnd_io_to_mod_ssi(io); + struct rsnd_mod *src = rsnd_io_to_mod_src(io); + struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io); + struct rsnd_mod *mod[MOD_MAX]; + int i, index; + + + for (i = 0; i < MOD_MAX; i++) + mod[i] = NULL; + + /* + * in play case... + * + * src -> dst + * + * mem -> SSI + * mem -> SRC -> SSI + * mem -> SRC -> DVC -> SSI + */ + mod[0] = NULL; /* for "mem" */ + index = 1; + for (i = 1; i < MOD_MAX; i++) { + if (!src) { + mod[i] = ssi; + } else if (!dvc) { + mod[i] = src; + src = NULL; + } else { + if ((!is_play) && (this == src)) + this = dvc; + + mod[i] = (is_play) ? src : dvc; + i++; + mod[i] = (is_play) ? dvc : src; + src = NULL; + dvc = NULL; + } + + if (mod[i] == this) + index = i; + + if (mod[i] == ssi) + break; + } + + if (is_play) { + *mod_from = mod[index - 1]; + *mod_to = mod[index]; + } else { + *mod_from = mod[index]; + *mod_to = mod[index - 1]; + } +} +
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
Now, we have dma.c for Audio DMAC / Audio DMAC peri peri. rsnd_gen_dma_addr() should go there.
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- v1 -> v2
- no change
sound/soc/sh/rcar/dma.c | 120 ++++++++++++++++++++++++++++++++++++++++++++-- sound/soc/sh/rcar/gen.c | 110 ------------------------------------------ sound/soc/sh/rcar/rsnd.h | 3 -- 3 files changed, 117 insertions(+), 116 deletions(-)
diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c index 37acd40..188b463 100644 --- a/sound/soc/sh/rcar/dma.c +++ b/sound/soc/sh/rcar/dma.c @@ -32,7 +32,6 @@ static void rsnd_dma_complete(void *data) }
#define DMA_NAME_SIZE 16 -#define MOD_MAX 4 /* MEM/SSI/SRC/DVC */ static int _rsnd_dma_of_name(char *dma_name, struct rsnd_mod *mod) { if (mod) @@ -97,6 +96,10 @@ static void rsnd_dma_of_path(struct rsnd_dma *dma, struct rsnd_mod **mod_from, struct rsnd_mod **mod_to);
+static dma_addr_t rsnd_dma_addr(struct rsnd_priv *priv, + struct rsnd_mod *mod, + int is_play, int is_from); + int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id) { struct device *dev = rsnd_priv_to_dev(priv); @@ -122,8 +125,8 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id) rsnd_dma_of_name(mod_from, mod_to, dma_name);
cfg.direction = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; - cfg.src_addr = rsnd_gen_dma_addr(priv, mod_from, is_play, 1); - cfg.dst_addr = rsnd_gen_dma_addr(priv, mod_to, is_play, 0); + cfg.src_addr = rsnd_dma_addr(priv, mod_from, is_play, 1); + cfg.dst_addr = rsnd_dma_addr(priv, mod_to, is_play, 0); cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
@@ -168,6 +171,117 @@ void rsnd_dma_quit(struct rsnd_dma *dma) dma->chan = NULL; }
+/* + * DMA read/write register offset + * + * RSND_xxx_I_N for Audio DMAC input + * RSND_xxx_O_N for Audio DMAC output + * RSND_xxx_I_P for Audio DMAC peri peri input + * RSND_xxx_O_P for Audio DMAC peri peri output + * + * ex) R-Car H2 case + * mod / DMAC in / DMAC out / DMAC PP in / DMAC pp out + * SSI : 0xec541000 / 0xec241008 / 0xec24100c + * SSIU: 0xec541000 / 0xec100000 / 0xec100000 / 0xec400000 / 0xec400000 + * SCU : 0xec500000 / 0xec000000 / 0xec004000 / 0xec300000 / 0xec304000 + * CMD : 0xec500000 / / 0xec008000 0xec308000 + */ +#define RDMA_SSI_I_N(addr, i) (addr ##_reg - 0x00300000 + (0x40 * i) + 0x8) +#define RDMA_SSI_O_N(addr, i) (addr ##_reg - 0x00300000 + (0x40 * i) + 0xc) + +#define RDMA_SSIU_I_N(addr, i) (addr ##_reg - 0x00441000 + (0x1000 * i)) +#define RDMA_SSIU_O_N(addr, i) (addr ##_reg - 0x00441000 + (0x1000 * i)) + +#define RDMA_SSIU_I_P(addr, i) (addr ##_reg - 0x00141000 + (0x1000 * i)) +#define RDMA_SSIU_O_P(addr, i) (addr ##_reg - 0x00141000 + (0x1000 * i)) + +#define RDMA_SRC_I_N(addr, i) (addr ##_reg - 0x00500000 + (0x400 * i)) +#define RDMA_SRC_O_N(addr, i) (addr ##_reg - 0x004fc000 + (0x400 * i)) + +#define RDMA_SRC_I_P(addr, i) (addr ##_reg - 0x00200000 + (0x400 * i)) +#define RDMA_SRC_O_P(addr, i) (addr ##_reg - 0x001fc000 + (0x400 * i)) + +#define RDMA_CMD_O_N(addr, i) (addr ##_reg - 0x004f8000 + (0x400 * i)) +#define RDMA_CMD_O_P(addr, i) (addr ##_reg - 0x001f8000 + (0x400 * i)) + +static dma_addr_t +rsnd_gen2_dma_addr(struct rsnd_priv *priv, + struct rsnd_mod *mod, + int is_play, int is_from) +{ + struct device *dev = rsnd_priv_to_dev(priv); + struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); + phys_addr_t ssi_reg = rsnd_gen_get_phy_addr(priv, RSND_GEN2_SSI); + phys_addr_t src_reg = rsnd_gen_get_phy_addr(priv, RSND_GEN2_SCU); + int is_ssi = !!(rsnd_io_to_mod_ssi(io) == mod); + int use_src = !!rsnd_io_to_mod_src(io); + int use_dvc = !!rsnd_io_to_mod_dvc(io); + int id = rsnd_mod_id(mod); + struct dma_addr { + dma_addr_t out_addr; + dma_addr_t in_addr; + } dma_addrs[3][2][3] = { + /* SRC */ + {{{ 0, 0 }, + /* Capture */ + { RDMA_SRC_O_N(src, id), RDMA_SRC_I_P(src, id) }, + { RDMA_CMD_O_N(src, id), RDMA_SRC_I_P(src, id) } }, + /* Playback */ + {{ 0, 0, }, + { RDMA_SRC_O_P(src, id), RDMA_SRC_I_N(src, id) }, + { RDMA_CMD_O_P(src, id), RDMA_SRC_I_N(src, id) } } + }, + /* SSI */ + /* Capture */ + {{{ RDMA_SSI_O_N(ssi, id), 0 }, + { RDMA_SSIU_O_P(ssi, id), 0 }, + { RDMA_SSIU_O_P(ssi, id), 0 } }, + /* Playback */ + {{ 0, RDMA_SSI_I_N(ssi, id) }, + { 0, RDMA_SSIU_I_P(ssi, id) }, + { 0, RDMA_SSIU_I_P(ssi, id) } } + }, + /* SSIU */ + /* Capture */ + {{{ RDMA_SSIU_O_N(ssi, id), 0 }, + { RDMA_SSIU_O_P(ssi, id), 0 }, + { RDMA_SSIU_O_P(ssi, id), 0 } }, + /* Playback */ + {{ 0, RDMA_SSIU_I_N(ssi, id) }, + { 0, RDMA_SSIU_I_P(ssi, id) }, + { 0, RDMA_SSIU_I_P(ssi, id) } } }, + }; + + /* it shouldn't happen */ + if (use_dvc && !use_src) + dev_err(dev, "DVC is selected without SRC\n"); + + /* use SSIU or SSI ? */ + if (is_ssi && (0 == strcmp(rsnd_mod_dma_name(mod), "ssiu"))) + is_ssi++; + + return (is_from) ? + dma_addrs[is_ssi][is_play][use_src + use_dvc].out_addr : + dma_addrs[is_ssi][is_play][use_src + use_dvc].in_addr; +} + +static dma_addr_t rsnd_dma_addr(struct rsnd_priv *priv, + struct rsnd_mod *mod, + int is_play, int is_from) +{ + /* + * gen1 uses default DMA addr + */ + if (rsnd_is_gen1(priv)) + return 0; + + if (!mod) + return 0; + + return rsnd_gen2_dma_addr(priv, mod, is_play, is_from); +} + +#define MOD_MAX 4 /* MEM/SSI/SRC/DVC */ static void rsnd_dma_of_path(struct rsnd_dma *dma, int is_play, struct rsnd_mod **mod_from, diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index 0da04ed..0273724 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -188,116 +188,6 @@ static int _rsnd_gen_regmap_init(struct rsnd_priv *priv, }
/* - * DMA read/write register offset - * - * RSND_xxx_I_N for Audio DMAC input - * RSND_xxx_O_N for Audio DMAC output - * RSND_xxx_I_P for Audio DMAC peri peri input - * RSND_xxx_O_P for Audio DMAC peri peri output - * - * ex) R-Car H2 case - * mod / DMAC in / DMAC out / DMAC PP in / DMAC pp out - * SSI : 0xec541000 / 0xec241008 / 0xec24100c - * SSIU: 0xec541000 / 0xec100000 / 0xec100000 / 0xec400000 / 0xec400000 - * SCU : 0xec500000 / 0xec000000 / 0xec004000 / 0xec300000 / 0xec304000 - * CMD : 0xec500000 / / 0xec008000 0xec308000 - */ -#define RDMA_SSI_I_N(addr, i) (addr ##_reg - 0x00300000 + (0x40 * i) + 0x8) -#define RDMA_SSI_O_N(addr, i) (addr ##_reg - 0x00300000 + (0x40 * i) + 0xc) - -#define RDMA_SSIU_I_N(addr, i) (addr ##_reg - 0x00441000 + (0x1000 * i)) -#define RDMA_SSIU_O_N(addr, i) (addr ##_reg - 0x00441000 + (0x1000 * i)) - -#define RDMA_SSIU_I_P(addr, i) (addr ##_reg - 0x00141000 + (0x1000 * i)) -#define RDMA_SSIU_O_P(addr, i) (addr ##_reg - 0x00141000 + (0x1000 * i)) - -#define RDMA_SRC_I_N(addr, i) (addr ##_reg - 0x00500000 + (0x400 * i)) -#define RDMA_SRC_O_N(addr, i) (addr ##_reg - 0x004fc000 + (0x400 * i)) - -#define RDMA_SRC_I_P(addr, i) (addr ##_reg - 0x00200000 + (0x400 * i)) -#define RDMA_SRC_O_P(addr, i) (addr ##_reg - 0x001fc000 + (0x400 * i)) - -#define RDMA_CMD_O_N(addr, i) (addr ##_reg - 0x004f8000 + (0x400 * i)) -#define RDMA_CMD_O_P(addr, i) (addr ##_reg - 0x001f8000 + (0x400 * i)) - -static dma_addr_t -rsnd_gen2_dma_addr(struct rsnd_priv *priv, - struct rsnd_mod *mod, - int is_play, int is_from) -{ - struct device *dev = rsnd_priv_to_dev(priv); - struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); - phys_addr_t ssi_reg = rsnd_gen_get_phy_addr(priv, RSND_GEN2_SSI); - phys_addr_t src_reg = rsnd_gen_get_phy_addr(priv, RSND_GEN2_SCU); - int is_ssi = !!(rsnd_io_to_mod_ssi(io) == mod); - int use_src = !!rsnd_io_to_mod_src(io); - int use_dvc = !!rsnd_io_to_mod_dvc(io); - int id = rsnd_mod_id(mod); - struct dma_addr { - dma_addr_t out_addr; - dma_addr_t in_addr; - } dma_addrs[3][2][3] = { - /* SRC */ - {{{ 0, 0 }, - /* Capture */ - { RDMA_SRC_O_N(src, id), RDMA_SRC_I_P(src, id) }, - { RDMA_CMD_O_N(src, id), RDMA_SRC_I_P(src, id) } }, - /* Playback */ - {{ 0, 0, }, - { RDMA_SRC_O_P(src, id), RDMA_SRC_I_N(src, id) }, - { RDMA_CMD_O_P(src, id), RDMA_SRC_I_N(src, id) } } - }, - /* SSI */ - /* Capture */ - {{{ RDMA_SSI_O_N(ssi, id), 0 }, - { RDMA_SSIU_O_P(ssi, id), 0 }, - { RDMA_SSIU_O_P(ssi, id), 0 } }, - /* Playback */ - {{ 0, RDMA_SSI_I_N(ssi, id) }, - { 0, RDMA_SSIU_I_P(ssi, id) }, - { 0, RDMA_SSIU_I_P(ssi, id) } } - }, - /* SSIU */ - /* Capture */ - {{{ RDMA_SSIU_O_N(ssi, id), 0 }, - { RDMA_SSIU_O_P(ssi, id), 0 }, - { RDMA_SSIU_O_P(ssi, id), 0 } }, - /* Playback */ - {{ 0, RDMA_SSIU_I_N(ssi, id) }, - { 0, RDMA_SSIU_I_P(ssi, id) }, - { 0, RDMA_SSIU_I_P(ssi, id) } } }, - }; - - /* it shouldn't happen */ - if (use_dvc && !use_src) - dev_err(dev, "DVC is selected without SRC\n"); - - /* use SSIU or SSI ? */ - if (is_ssi && (0 == strcmp(rsnd_mod_dma_name(mod), "ssiu"))) - is_ssi++; - - return (is_from) ? - dma_addrs[is_ssi][is_play][use_src + use_dvc].out_addr : - dma_addrs[is_ssi][is_play][use_src + use_dvc].in_addr; -} - -dma_addr_t rsnd_gen_dma_addr(struct rsnd_priv *priv, - struct rsnd_mod *mod, - int is_play, int is_from) -{ - /* - * gen1 uses default DMA addr - */ - if (rsnd_is_gen1(priv)) - return 0; - - if (!mod) - return 0; - - return rsnd_gen2_dma_addr(priv, mod, is_play, is_from); -} - -/* * Gen2 */ static int rsnd_gen2_probe(struct platform_device *pdev, diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 8a8a4d5..a73e94c 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -328,9 +328,6 @@ int rsnd_gen_probe(struct platform_device *pdev, void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg); -dma_addr_t rsnd_gen_dma_addr(struct rsnd_priv *priv, - struct rsnd_mod *mod, - int is_play, int is_from); phys_addr_t rsnd_gen_get_phy_addr(struct rsnd_priv *priv, int reg_id);
#define rsnd_is_gen1(s) (((s)->info->flags & RSND_GEN_MASK) == RSND_GEN1)
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
rsnd driver needs to care about Audio DAMC (via DMAEngine), Audio DMAC peri peri (via local method) on rsnd driver. This patch adds new rsnd_dma_ops and care it.
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- v1 -> v2
- no change
sound/soc/sh/rcar/dma.c | 78 +++++++++++++++++++++++++++++++--------------- sound/soc/sh/rcar/rsnd.h | 12 +++++++ 2 files changed, 65 insertions(+), 25 deletions(-)
diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c index 188b463..c911c07 100644 --- a/sound/soc/sh/rcar/dma.c +++ b/sound/soc/sh/rcar/dma.c @@ -10,7 +10,7 @@ */ #include "rsnd.h"
-static void rsnd_dma_complete(void *data) +static void rsnd_dmaen_complete(void *data) { struct rsnd_dma *dma = (struct rsnd_dma *)data; struct rsnd_mod *mod = rsnd_dma_to_mod(dma); @@ -32,7 +32,7 @@ static void rsnd_dma_complete(void *data) }
#define DMA_NAME_SIZE 16 -static int _rsnd_dma_of_name(char *dma_name, struct rsnd_mod *mod) +static int _rsnd_dmaen_of_name(char *dma_name, struct rsnd_mod *mod) { if (mod) return snprintf(dma_name, DMA_NAME_SIZE / 2, "%s%d", @@ -42,23 +42,23 @@ static int _rsnd_dma_of_name(char *dma_name, struct rsnd_mod *mod)
}
-static void rsnd_dma_of_name(struct rsnd_mod *mod_from, +static void rsnd_dmaen_of_name(struct rsnd_mod *mod_from, struct rsnd_mod *mod_to, char *dma_name) { int index = 0;
- index = _rsnd_dma_of_name(dma_name + index, mod_from); + index = _rsnd_dmaen_of_name(dma_name + index, mod_from); *(dma_name + index++) = '_'; - index = _rsnd_dma_of_name(dma_name + index, mod_to); + index = _rsnd_dmaen_of_name(dma_name + index, mod_to); }
-void rsnd_dma_stop(struct rsnd_dma *dma) +static void rsnd_dmaen_stop(struct rsnd_dma *dma) { dmaengine_terminate_all(dma->chan); }
-void rsnd_dma_start(struct rsnd_dma *dma) +static void rsnd_dmaen_start(struct rsnd_dma *dma) { struct rsnd_mod *mod = rsnd_dma_to_mod(dma); struct rsnd_priv *priv = rsnd_mod_to_priv(mod); @@ -80,7 +80,7 @@ void rsnd_dma_start(struct rsnd_dma *dma) return; }
- desc->callback = rsnd_dma_complete; + desc->callback = rsnd_dmaen_complete; desc->callback_param = dma;
if (dmaengine_submit(desc) < 0) { @@ -91,22 +91,12 @@ void rsnd_dma_start(struct rsnd_dma *dma) dma_async_issue_pending(dma->chan); }
-static void rsnd_dma_of_path(struct rsnd_dma *dma, - int is_play, - struct rsnd_mod **mod_from, - struct rsnd_mod **mod_to); - -static dma_addr_t rsnd_dma_addr(struct rsnd_priv *priv, - struct rsnd_mod *mod, - int is_play, int is_from); - -int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id) +static int rsnd_dmaen_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id, + struct rsnd_mod *mod_from, struct rsnd_mod *mod_to) { struct device *dev = rsnd_priv_to_dev(priv); struct dma_slave_config cfg = {}; struct rsnd_mod *mod = rsnd_dma_to_mod(dma); - struct rsnd_mod *mod_from; - struct rsnd_mod *mod_to; struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); int is_play = rsnd_io_is_play(io); char dma_name[DMA_NAME_SIZE]; @@ -121,12 +111,11 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id) dma_cap_zero(mask); dma_cap_set(DMA_SLAVE, mask);
- rsnd_dma_of_path(dma, is_play, &mod_from, &mod_to); - rsnd_dma_of_name(mod_from, mod_to, dma_name); + rsnd_dmaen_of_name(mod_from, mod_to, dma_name);
cfg.direction = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; - cfg.src_addr = rsnd_dma_addr(priv, mod_from, is_play, 1); - cfg.dst_addr = rsnd_dma_addr(priv, mod_to, is_play, 0); + cfg.src_addr = dma->src_addr; + cfg.dst_addr = dma->dst_addr; cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
@@ -163,7 +152,7 @@ rsnd_dma_channel_err: return -EAGAIN; }
-void rsnd_dma_quit(struct rsnd_dma *dma) +static void rsnd_dmaen_quit(struct rsnd_dma *dma) { if (dma->chan) dma_release_channel(dma->chan); @@ -171,6 +160,13 @@ void rsnd_dma_quit(struct rsnd_dma *dma) dma->chan = NULL; }
+static struct rsnd_dma_ops rsnd_dmaen_ops = { + .start = rsnd_dmaen_start, + .stop = rsnd_dmaen_stop, + .init = rsnd_dmaen_init, + .quit = rsnd_dmaen_quit, +}; + /* * DMA read/write register offset * @@ -343,3 +339,35 @@ static void rsnd_dma_of_path(struct rsnd_dma *dma, } }
+void rsnd_dma_stop(struct rsnd_dma *dma) +{ + dma->ops->stop(dma); +} + +void rsnd_dma_start(struct rsnd_dma *dma) +{ + dma->ops->start(dma); +} + +void rsnd_dma_quit(struct rsnd_dma *dma) +{ + dma->ops->quit(dma); +} + +int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id) +{ + struct rsnd_mod *mod = rsnd_dma_to_mod(dma); + struct rsnd_mod *mod_from; + struct rsnd_mod *mod_to; + struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); + int is_play = rsnd_io_is_play(io); + + rsnd_dma_of_path(dma, is_play, &mod_from, &mod_to); + + dma->src_addr = rsnd_dma_addr(priv, mod_from, is_play, 1); + dma->dst_addr = rsnd_dma_addr(priv, mod_to, is_play, 0); + + dma->ops = &rsnd_dmaen_ops; + + return dma->ops->init(priv, dma, id, mod_from, mod_to); +} diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index a73e94c..c7299f7 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -170,10 +170,22 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod); /* * R-Car DMA */ +struct rsnd_dma; +struct rsnd_dma_ops { + void (*start)(struct rsnd_dma *dma); + void (*stop)(struct rsnd_dma *dma); + int (*init)(struct rsnd_priv *priv, struct rsnd_dma *dma, int id, + struct rsnd_mod *mod_from, struct rsnd_mod *mod_to); + void (*quit)(struct rsnd_dma *dma); +}; + struct rsnd_dma { struct dma_chan *chan; + struct rsnd_dma_ops *ops; enum dma_transfer_direction dir; dma_addr_t addr; + dma_addr_t src_addr; + dma_addr_t dst_addr; };
void rsnd_dma_start(struct rsnd_dma *dma);
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
Renesas R-Car sound (= rsnd) needs 2 DMAC which are called as Audio DMAC (= 1st DMAC) and Audio DMAC peri peri (2nd DMAC). And rsnd had assumed that 1st / 2nd DMACs are implemented as DMAEngine. But, in result of DMA ML discussion, 2nd DMAC was concluded that it is not a general purpose DMAC (2nd DMAC is for Device to Device inside sound system). Additionally, current DMAEngine can't support Device to Device, and we don't have correct DT bindings for it at this point. So the easiest solution for it is that move it from DMAEngine to rsnd driver. Audio DMAC peri peri is controlled from sound driver without DMAEngine by this patch.
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- v1 -> v2
- no change
sound/soc/sh/rcar/core.c | 1 + sound/soc/sh/rcar/dma.c | 211 +++++++++++++++++++++++++++++++++++++++++++++- sound/soc/sh/rcar/rsnd.h | 11 ++- 3 files changed, 221 insertions(+), 2 deletions(-)
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 9beea9b..3b6e219 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -974,6 +974,7 @@ static int rsnd_probe(struct platform_device *pdev) const struct rsnd_of_data *of_data, struct rsnd_priv *priv) = { rsnd_gen_probe, + rsnd_dma_probe, rsnd_ssi_probe, rsnd_src_probe, rsnd_dvc_probe, diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c index c911c07..a01bb8c 100644 --- a/sound/soc/sh/rcar/dma.c +++ b/sound/soc/sh/rcar/dma.c @@ -8,8 +8,29 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ +#include <linux/delay.h> #include "rsnd.h"
+/* + * Audio DMAC peri peri register + */ +#define PDMASAR 0x00 +#define PDMADAR 0x04 +#define PDMACHCR 0x0c + +/* PDMACHCR */ +#define PDMACHCR_DE (1 << 0) + +struct rsnd_dma_ctrl { + void __iomem *base; + int dmapp_num; +}; + +#define rsnd_priv_to_dmac(p) ((struct rsnd_dma_ctrl *)(p)->dma) + +/* + * Audio DMAC + */ static void rsnd_dmaen_complete(void *data) { struct rsnd_dma *dma = (struct rsnd_dma *)data; @@ -108,6 +129,8 @@ static int rsnd_dmaen_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id, return -EIO; }
+ dev_dbg(dev, "Audio DMAC init\n"); + dma_cap_zero(mask); dma_cap_set(DMA_SLAVE, mask);
@@ -168,6 +191,150 @@ static struct rsnd_dma_ops rsnd_dmaen_ops = { };
/* + * Audio DMAC peri peri + */ +static const u8 gen2_id_table_ssiu[] = { + 0x00, /* SSI00 */ + 0x04, /* SSI10 */ + 0x08, /* SSI20 */ + 0x0c, /* SSI3 */ + 0x0d, /* SSI4 */ + 0x0e, /* SSI5 */ + 0x0f, /* SSI6 */ + 0x10, /* SSI7 */ + 0x11, /* SSI8 */ + 0x12, /* SSI90 */ +}; +static const u8 gen2_id_table_scu[] = { + 0x2d, /* SCU_SRCI0 */ + 0x2e, /* SCU_SRCI1 */ + 0x2f, /* SCU_SRCI2 */ + 0x30, /* SCU_SRCI3 */ + 0x31, /* SCU_SRCI4 */ + 0x32, /* SCU_SRCI5 */ + 0x33, /* SCU_SRCI6 */ + 0x34, /* SCU_SRCI7 */ + 0x35, /* SCU_SRCI8 */ + 0x36, /* SCU_SRCI9 */ +}; +static const u8 gen2_id_table_cmd[] = { + 0x37, /* SCU_CMD0 */ + 0x38, /* SCU_CMD1 */ +}; + +static u32 rsnd_dmapp_get_id(struct rsnd_mod *mod) +{ + struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); + struct rsnd_mod *ssi = rsnd_io_to_mod_ssi(io); + struct rsnd_mod *src = rsnd_io_to_mod_src(io); + struct rsnd_mod *dvc = rsnd_io_to_mod_dvc(io); + const u8 *entry = NULL; + int id = rsnd_mod_id(mod); + int size = 0; + + if (mod == ssi) { + entry = gen2_id_table_ssiu; + size = ARRAY_SIZE(gen2_id_table_ssiu); + } else if (mod == src) { + entry = gen2_id_table_scu; + size = ARRAY_SIZE(gen2_id_table_scu); + } else if (mod == dvc) { + entry = gen2_id_table_cmd; + size = ARRAY_SIZE(gen2_id_table_cmd); + } + + if (!entry) + return 0xFF; + + if (size <= id) + return 0xFF; + + return entry[id]; +} + +static u32 rsnd_dmapp_get_chcr(struct rsnd_mod *mod_from, + struct rsnd_mod *mod_to) +{ + return (rsnd_dmapp_get_id(mod_from) << 24) + + (rsnd_dmapp_get_id(mod_to) << 16); +} + +#define rsnd_dmapp_addr(dmac, dma, reg) \ + (dmac->base + 0x20 + (0x10 * dma->dmapp_id) + reg) +static void rsnd_dmapp_write(struct rsnd_dma *dma, u32 data, u32 reg) +{ + struct rsnd_mod *mod = rsnd_dma_to_mod(dma); + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv); + struct device *dev = rsnd_priv_to_dev(priv); + + dev_dbg(dev, "w %p : %08x\n", rsnd_dmapp_addr(dmac, dma, reg), data); + + iowrite32(data, rsnd_dmapp_addr(dmac, dma, reg)); +} + +static u32 rsnd_dmapp_read(struct rsnd_dma *dma, u32 reg) +{ + struct rsnd_mod *mod = rsnd_dma_to_mod(dma); + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv); + + return ioread32(rsnd_dmapp_addr(dmac, dma, reg)); +} + +static void rsnd_dmapp_stop(struct rsnd_dma *dma) +{ + int i; + + rsnd_dmapp_write(dma, 0, PDMACHCR); + + for (i = 0; i < 1024; i++) { + if (0 == rsnd_dmapp_read(dma, PDMACHCR)) + return; + udelay(1); + } +} + +static void rsnd_dmapp_start(struct rsnd_dma *dma) +{ + rsnd_dmapp_write(dma, dma->src_addr, PDMASAR); + rsnd_dmapp_write(dma, dma->dst_addr, PDMADAR); + rsnd_dmapp_write(dma, dma->chcr, PDMACHCR); +} + +static int rsnd_dmapp_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id, + struct rsnd_mod *mod_from, struct rsnd_mod *mod_to) +{ + struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv); + struct device *dev = rsnd_priv_to_dev(priv); + + dev_dbg(dev, "Audio DMAC peri peri init\n"); + + dma->dmapp_id = dmac->dmapp_num; + dma->chcr = rsnd_dmapp_get_chcr(mod_from, mod_to) | PDMACHCR_DE; + + dmac->dmapp_num++; + + rsnd_dmapp_stop(dma); + + dev_dbg(dev, "id/src/dst/chcr = %d/%x/%x/%08x\n", + dma->dmapp_id, dma->src_addr, dma->dst_addr, dma->chcr); + + return 0; +} + +static struct rsnd_dma_ops rsnd_dmapp_ops = { + .start = rsnd_dmapp_start, + .stop = rsnd_dmapp_stop, + .init = rsnd_dmapp_init, + .quit = rsnd_dmapp_stop, +}; + +/* + * Common DMAC Interface + */ + +/* * DMA read/write register offset * * RSND_xxx_I_N for Audio DMAC input @@ -367,7 +534,49 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id) dma->src_addr = rsnd_dma_addr(priv, mod_from, is_play, 1); dma->dst_addr = rsnd_dma_addr(priv, mod_to, is_play, 0);
- dma->ops = &rsnd_dmaen_ops; + /* for Gen2 */ + if (mod_from && mod_to) + dma->ops = &rsnd_dmapp_ops; + else + dma->ops = &rsnd_dmaen_ops; + + /* for Gen1, overwrite */ + if (rsnd_is_gen1(priv)) + dma->ops = &rsnd_dmaen_ops;
return dma->ops->init(priv, dma, id, mod_from, mod_to); } + +int rsnd_dma_probe(struct platform_device *pdev, + const struct rsnd_of_data *of_data, + struct rsnd_priv *priv) +{ + struct device *dev = rsnd_priv_to_dev(priv); + struct rsnd_dma_ctrl *dmac; + struct resource *res; + + /* + * for Gen1 + */ + if (rsnd_is_gen1(priv)) + return 0; + + /* + * for Gen2 + */ + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "audmapp"); + dmac = devm_kzalloc(dev, sizeof(*dmac), GFP_KERNEL); + if (!dmac || !res) { + dev_err(dev, "dma allocate failed\n"); + return -ENOMEM; + } + + dmac->dmapp_num = 0; + dmac->base = devm_ioremap_resource(dev, res); + if (IS_ERR(dmac->base)) + return PTR_ERR(dmac->base); + + priv->dma = dmac; + + return 0; +} diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index c7299f7..9e67142 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -184,6 +184,8 @@ struct rsnd_dma { struct rsnd_dma_ops *ops; enum dma_transfer_direction dir; dma_addr_t addr; + int dmapp_id; + u32 chcr; dma_addr_t src_addr; dma_addr_t dst_addr; }; @@ -192,7 +194,9 @@ void rsnd_dma_start(struct rsnd_dma *dma); void rsnd_dma_stop(struct rsnd_dma *dma); int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id); void rsnd_dma_quit(struct rsnd_dma *dma); - +int rsnd_dma_probe(struct platform_device *pdev, + const struct rsnd_of_data *of_data, + struct rsnd_priv *priv);
#define rsnd_dma_to_mod(_dma) container_of((_dma), struct rsnd_mod, dma)
@@ -396,6 +400,11 @@ struct rsnd_priv { void *adg;
/* + * below value will be filled on rsnd_dma_probe() + */ + void *dma; + + /* * below value will be filled on rsnd_ssi_probe() */ void *ssi;
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
DMAEngine for Renesas R-Car driver is used only for Audio DMAC now. rsnd_dma::addr was added to support Audio DMAC peri peri, but it is no longer needed. Let's remove it
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- v1 -> v2
- no change
sound/soc/sh/rcar/dma.c | 2 -- sound/soc/sh/rcar/rsnd.h | 1 - 2 files changed, 3 deletions(-)
diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c index a01bb8c..c407fd2 100644 --- a/sound/soc/sh/rcar/dma.c +++ b/sound/soc/sh/rcar/dma.c @@ -89,7 +89,6 @@ static void rsnd_dmaen_start(struct rsnd_dma *dma) struct dma_async_tx_descriptor *desc;
desc = dmaengine_prep_dma_cyclic(dma->chan, - (dma->addr) ? dma->addr : substream->runtime->dma_addr, snd_pcm_lib_buffer_bytes(substream), snd_pcm_lib_period_bytes(substream), @@ -157,7 +156,6 @@ static int rsnd_dmaen_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id, if (ret < 0) goto rsnd_dma_init_err;
- dma->addr = is_play ? cfg.src_addr : cfg.dst_addr; dma->dir = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM;
return 0; diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 9e67142..a295491 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -183,7 +183,6 @@ struct rsnd_dma { struct dma_chan *chan; struct rsnd_dma_ops *ops; enum dma_transfer_direction dir; - dma_addr_t addr; int dmapp_id; u32 chcr; dma_addr_t src_addr;
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
DMAEngine direction can be calculated from rsnd_dai_stream, So, rsnd_dma::dir does not make sense now. Let's remove it.
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- v1 -> v2
- no change
sound/soc/sh/rcar/dma.c | 5 ++--- sound/soc/sh/rcar/rsnd.h | 1 - 2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c index c407fd2..3f1ea58 100644 --- a/sound/soc/sh/rcar/dma.c +++ b/sound/soc/sh/rcar/dma.c @@ -87,12 +87,13 @@ static void rsnd_dmaen_start(struct rsnd_dma *dma) struct snd_pcm_substream *substream = io->substream; struct device *dev = rsnd_priv_to_dev(priv); struct dma_async_tx_descriptor *desc; + int is_play = rsnd_io_is_play(io);
desc = dmaengine_prep_dma_cyclic(dma->chan, substream->runtime->dma_addr, snd_pcm_lib_buffer_bytes(substream), snd_pcm_lib_period_bytes(substream), - dma->dir, + is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!desc) { @@ -156,8 +157,6 @@ static int rsnd_dmaen_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id, if (ret < 0) goto rsnd_dma_init_err;
- dma->dir = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; - return 0;
rsnd_dma_init_err: diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index a295491..5d65a4b 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -182,7 +182,6 @@ struct rsnd_dma_ops { struct rsnd_dma { struct dma_chan *chan; struct rsnd_dma_ops *ops; - enum dma_transfer_direction dir; int dmapp_id; u32 chcr; dma_addr_t src_addr;
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
Renesas R-Car needs 2 DMACs.1st DMAC is DMAEngine, and 2nd DMAC is implemented as local code. These 2 DMACs are never shared. We can use union for these.
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- v1 -> v2
- new patch
sound/soc/sh/rcar/dma.c | 40 +++++++++++++++++++++++++--------------- sound/soc/sh/rcar/rsnd.h | 16 ++++++++++++++-- 2 files changed, 39 insertions(+), 17 deletions(-)
diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c index 3f1ea58..b449763 100644 --- a/sound/soc/sh/rcar/dma.c +++ b/sound/soc/sh/rcar/dma.c @@ -76,11 +76,14 @@ static void rsnd_dmaen_of_name(struct rsnd_mod *mod_from,
static void rsnd_dmaen_stop(struct rsnd_dma *dma) { - dmaengine_terminate_all(dma->chan); + struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma); + + dmaengine_terminate_all(dmaen->chan); }
static void rsnd_dmaen_start(struct rsnd_dma *dma) { + struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(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); @@ -89,7 +92,7 @@ static void rsnd_dmaen_start(struct rsnd_dma *dma) struct dma_async_tx_descriptor *desc; int is_play = rsnd_io_is_play(io);
- desc = dmaengine_prep_dma_cyclic(dma->chan, + desc = dmaengine_prep_dma_cyclic(dmaen->chan, substream->runtime->dma_addr, snd_pcm_lib_buffer_bytes(substream), snd_pcm_lib_period_bytes(substream), @@ -109,12 +112,13 @@ static void rsnd_dmaen_start(struct rsnd_dma *dma) return; }
- dma_async_issue_pending(dma->chan); + dma_async_issue_pending(dmaen->chan); }
static int rsnd_dmaen_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id, struct rsnd_mod *mod_from, struct rsnd_mod *mod_to) { + struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma); struct device *dev = rsnd_priv_to_dev(priv); struct dma_slave_config cfg = {}; struct rsnd_mod *mod = rsnd_dma_to_mod(dma); @@ -124,7 +128,7 @@ static int rsnd_dmaen_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id, dma_cap_mask_t mask; int ret;
- if (dma->chan) { + if (dmaen->chan) { dev_err(dev, "it already has dma channel\n"); return -EIO; } @@ -145,15 +149,15 @@ static int rsnd_dmaen_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id, dev_dbg(dev, "dma : %s %pad -> %pad\n", dma_name, &cfg.src_addr, &cfg.dst_addr);
- dma->chan = dma_request_slave_channel_compat(mask, shdma_chan_filter, + dmaen->chan = dma_request_slave_channel_compat(mask, shdma_chan_filter, (void *)id, dev, dma_name); - if (!dma->chan) { + if (!dmaen->chan) { dev_err(dev, "can't get dma channel\n"); goto rsnd_dma_channel_err; }
- ret = dmaengine_slave_config(dma->chan, &cfg); + ret = dmaengine_slave_config(dmaen->chan, &cfg); if (ret < 0) goto rsnd_dma_init_err;
@@ -174,10 +178,12 @@ rsnd_dma_channel_err:
static void rsnd_dmaen_quit(struct rsnd_dma *dma) { - if (dma->chan) - dma_release_channel(dma->chan); + struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma); + + if (dmaen->chan) + dma_release_channel(dmaen->chan);
- dma->chan = NULL; + dmaen->chan = NULL; }
static struct rsnd_dma_ops rsnd_dmaen_ops = { @@ -257,7 +263,8 @@ static u32 rsnd_dmapp_get_chcr(struct rsnd_mod *mod_from, }
#define rsnd_dmapp_addr(dmac, dma, reg) \ - (dmac->base + 0x20 + (0x10 * dma->dmapp_id) + reg) + (dmac->base + 0x20 + reg + \ + (0x10 * rsnd_dma_to_dmapp(dma)->dmapp_id)) static void rsnd_dmapp_write(struct rsnd_dma *dma, u32 data, u32 reg) { struct rsnd_mod *mod = rsnd_dma_to_mod(dma); @@ -294,28 +301,31 @@ static void rsnd_dmapp_stop(struct rsnd_dma *dma)
static void rsnd_dmapp_start(struct rsnd_dma *dma) { + struct rsnd_dmapp *dmapp = rsnd_dma_to_dmapp(dma); + rsnd_dmapp_write(dma, dma->src_addr, PDMASAR); rsnd_dmapp_write(dma, dma->dst_addr, PDMADAR); - rsnd_dmapp_write(dma, dma->chcr, PDMACHCR); + rsnd_dmapp_write(dma, dmapp->chcr, PDMACHCR); }
static int rsnd_dmapp_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id, struct rsnd_mod *mod_from, struct rsnd_mod *mod_to) { + struct rsnd_dmapp *dmapp = rsnd_dma_to_dmapp(dma); struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv); struct device *dev = rsnd_priv_to_dev(priv);
dev_dbg(dev, "Audio DMAC peri peri init\n");
- dma->dmapp_id = dmac->dmapp_num; - dma->chcr = rsnd_dmapp_get_chcr(mod_from, mod_to) | PDMACHCR_DE; + dmapp->dmapp_id = dmac->dmapp_num; + dmapp->chcr = rsnd_dmapp_get_chcr(mod_from, mod_to) | PDMACHCR_DE;
dmac->dmapp_num++;
rsnd_dmapp_stop(dma);
dev_dbg(dev, "id/src/dst/chcr = %d/%x/%x/%08x\n", - dma->dmapp_id, dma->src_addr, dma->dst_addr, dma->chcr); + dmapp->dmapp_id, dma->src_addr, dma->dst_addr, dmapp->chcr);
return 0; } diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 5d65a4b..0d36e38 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -179,14 +179,26 @@ struct rsnd_dma_ops { void (*quit)(struct rsnd_dma *dma); };
-struct rsnd_dma { +struct rsnd_dmaen { struct dma_chan *chan; - struct rsnd_dma_ops *ops; +}; + +struct rsnd_dmapp { int dmapp_id; u32 chcr; +}; + +struct rsnd_dma { + struct rsnd_dma_ops *ops; dma_addr_t src_addr; dma_addr_t dst_addr; + union { + struct rsnd_dmaen en; + struct rsnd_dmapp pp; + } dma; }; +#define rsnd_dma_to_dmaen(dma) (&(dma)->dma.en) +#define rsnd_dma_to_dmapp(dma) (&(dma)->dma.pp)
void rsnd_dma_start(struct rsnd_dma *dma); void rsnd_dma_stop(struct rsnd_dma *dma);
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
Renesas R-Car sound driver uses SSI, but the DMA interfaces are SSI/SSIU. This interface is based on SSI/SRC/DVC connection. And DMA function needs to know which interface is used somehow. This patch enables rsnd_ssi_use_busif() for DMA.
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- v1 -> v2
- new patch
sound/soc/sh/rcar/dma.c | 2 +- sound/soc/sh/rcar/rsnd.h | 1 + sound/soc/sh/rcar/ssi.c | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c index b449763..3f34461 100644 --- a/sound/soc/sh/rcar/dma.c +++ b/sound/soc/sh/rcar/dma.c @@ -427,7 +427,7 @@ rsnd_gen2_dma_addr(struct rsnd_priv *priv, dev_err(dev, "DVC is selected without SRC\n");
/* use SSIU or SSI ? */ - if (is_ssi && (0 == strcmp(rsnd_mod_dma_name(mod), "ssiu"))) + if (is_ssi && rsnd_ssi_use_busif(mod)) is_ssi++;
return (is_from) ? diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 0d36e38..68bc3f4 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -514,6 +514,7 @@ int rsnd_ssi_probe(struct platform_device *pdev, struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id); int rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod); int rsnd_ssi_is_dma_mode(struct rsnd_mod *mod); +int rsnd_ssi_use_busif(struct rsnd_mod *mod);
/* * R-Car DVC diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index a0d902a..7e48d56 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -84,7 +84,7 @@ struct rsnd_ssi { #define rsnd_ssi_mode_flags(p) ((p)->info->flags) #define rsnd_ssi_dai_id(ssi) ((ssi)->info->dai_id)
-static int rsnd_ssi_use_busif(struct rsnd_mod *mod) +int rsnd_ssi_use_busif(struct rsnd_mod *mod) { struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
This patch adds rsnd_ssi_of_node() to get SSI subnode from DT. This is prepare for new DT bindings for 1st DMAC
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- v1 -> v2
- new patch
sound/soc/sh/rcar/ssi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 7e48d56..2133eb3 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -83,6 +83,8 @@ struct rsnd_ssi { #define rsnd_ssi_clk_from_parent(ssi) ((ssi)->parent) #define rsnd_ssi_mode_flags(p) ((p)->info->flags) #define rsnd_ssi_dai_id(ssi) ((ssi)->info->dai_id) +#define rsnd_ssi_of_node(priv) \ + of_get_child_by_name(rsnd_priv_to_dev(priv)->of_node, "rcar_sound,ssi")
int rsnd_ssi_use_busif(struct rsnd_mod *mod) { @@ -633,7 +635,7 @@ static void rsnd_of_parse_ssi(struct platform_device *pdev, if (!of_data) return;
- node = of_get_child_by_name(dev->of_node, "rcar_sound,ssi"); + node = rsnd_ssi_of_node(priv); if (!node) return;
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
This patch adds rsnd_src_of_node() to get SRC subnode from DT. This is prepare for new DT bindings for 1st DMAC
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- v1 -> v2
- new patch
sound/soc/sh/rcar/src.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c index e279205..5a601be 100644 --- a/sound/soc/sh/rcar/src.c +++ b/sound/soc/sh/rcar/src.c @@ -28,6 +28,9 @@ struct rsnd_src { #define RSND_SRC_NAME_SIZE 16
#define rsnd_src_convert_rate(p) ((p)->info->convert_rate) +#define rsnd_src_of_node(priv) \ + of_get_child_by_name(rsnd_priv_to_dev(priv)->of_node, "rcar_sound,src") + #define rsnd_mod_to_src(_mod) \ container_of((_mod), struct rsnd_src, mod)
@@ -807,7 +810,7 @@ static void rsnd_of_parse_src(struct platform_device *pdev, if (!of_data) return;
- src_node = of_get_child_by_name(dev->of_node, "rcar_sound,src"); + src_node = rsnd_src_of_node(priv); if (!src_node) return;
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
This patch adds rsnd_dvc_of_node() to get DVC subnode from DT. This is prepare for new DT bindings for 1st DMAC
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- v1 -> v2
- new patch
sound/soc/sh/rcar/dvc.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/sound/soc/sh/rcar/dvc.c b/sound/soc/sh/rcar/dvc.c index d7f9ed9..e099018 100644 --- a/sound/soc/sh/rcar/dvc.c +++ b/sound/soc/sh/rcar/dvc.c @@ -24,6 +24,9 @@ struct rsnd_dvc { struct rsnd_kctrl_cfg_s rdown; /* Ramp Rate Down */ };
+#define rsnd_dvc_of_node(priv) \ + of_get_child_by_name(rsnd_priv_to_dev(priv)->of_node, "rcar_sound,dvc") + #define rsnd_mod_to_dvc(_mod) \ container_of((_mod), struct rsnd_dvc, mod)
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
Renesas R-Car sound (= rsnd) needs 2 DMAC which are called as Audio DMAC (= 1st DMAC) and Audio DMAC peri peri (2nd DMAC). And rsnd had assumed that 1st / 2nd DMACs are implemented as DMAEngine. But, in result of DMA ML discussion, 2nd DMAC was concluded that it is not a general purpose DMAC (2nd DMAC is for Device to Device inside sound system). Additionally, current DMAEngine can't support Device to Device, and we don't have correct DT bindings for it at this point. So the easiest solution for it is that move it from DMAEngine to rsnd driver.
dma-names on DT was implemented as no difference between 1st / 2nd DMAC's, since rsnd had assumed that both DMACs are implemented as DMAEngine. That style was "src_dst". But now, 2nd DMAC was implemented as non DMAEngine, and it doesn't need dma-names anymore. So, this dma-names rule is no longer needed.
And additionally, dma-names was assumed that it has all (= SSI/SSIU/SRC/DVC) nodes under sound node.
In upstream code, no SoC/platform is supporting DMA for rsnd driver yet. This means there is no compatible issue if this patch changes dma-names's rule of DT.
This patch assumes dma-names for 1st DMAC are tx/rx base, and listed in each SSI/SRC/DVC subnode ex) rcar_sound,dvc { dvc0: dvc@0 { dmas = <&audma0 0xbc>; dma-names = "tx"; }; ...
rcar_sound,src { src0: src@0 { ... dmas = <&audma0 0x85>, <&audma1 0x9a>; dma-names = "rx", "tx"; }; ...
rcar_sound,ssi { ssi0: ssi@0 { ... dmas = <&audma0 0x01>, <&audma1 0x02>, <&audma0 0x15>, <&audma1 0x16>; dma-names = "rx", "tx", "rxu", "txu"; }; ...
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- v1 -> v2
- remake version - supprts subnode dma-names
sound/soc/sh/rcar/core.c | 11 +++--- sound/soc/sh/rcar/dma.c | 88 +++++++++++++++++++++++++++------------------- sound/soc/sh/rcar/dvc.c | 9 +++++ sound/soc/sh/rcar/rsnd.h | 6 ++-- sound/soc/sh/rcar/src.c | 13 +++++++ sound/soc/sh/rcar/ssi.c | 17 +++++++-- 6 files changed, 95 insertions(+), 49 deletions(-)
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 3b6e219..7b995f0 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -137,15 +137,12 @@ char *rsnd_mod_name(struct rsnd_mod *mod) return mod->ops->name; }
-char *rsnd_mod_dma_name(struct rsnd_mod *mod) +struct dma_chan *rsnd_mod_dma_req(struct rsnd_mod *mod) { - if (!mod || !mod->ops) - return "unknown"; - - if (!mod->ops->dma_name) - return mod->ops->name; + if (!mod || !mod->ops || !mod->ops->dma_req) + return NULL;
- return mod->ops->dma_name(mod); + return mod->ops->dma_req(mod); }
void rsnd_mod_init(struct rsnd_mod *mod, diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c index 3f34461..92fd550 100644 --- a/sound/soc/sh/rcar/dma.c +++ b/sound/soc/sh/rcar/dma.c @@ -9,6 +9,7 @@ * published by the Free Software Foundation. */ #include <linux/delay.h> +#include <linux/of_dma.h> #include "rsnd.h"
/* @@ -52,28 +53,6 @@ static void rsnd_dmaen_complete(void *data) rsnd_dai_pointer_update(io, io->byte_per_period); }
-#define DMA_NAME_SIZE 16 -static int _rsnd_dmaen_of_name(char *dma_name, struct rsnd_mod *mod) -{ - if (mod) - return snprintf(dma_name, DMA_NAME_SIZE / 2, "%s%d", - rsnd_mod_dma_name(mod), rsnd_mod_id(mod)); - else - return snprintf(dma_name, DMA_NAME_SIZE / 2, "mem"); - -} - -static void rsnd_dmaen_of_name(struct rsnd_mod *mod_from, - struct rsnd_mod *mod_to, - char *dma_name) -{ - int index = 0; - - index = _rsnd_dmaen_of_name(dma_name + index, mod_from); - *(dma_name + index++) = '_'; - index = _rsnd_dmaen_of_name(dma_name + index, mod_to); -} - static void rsnd_dmaen_stop(struct rsnd_dma *dma) { struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma); @@ -115,6 +94,40 @@ static void rsnd_dmaen_start(struct rsnd_dma *dma) dma_async_issue_pending(dmaen->chan); }
+struct dma_chan *rsnd_dma_request_channel(struct device_node *of_node, + struct rsnd_mod *mod, char *name) +{ + struct dma_chan *chan; + struct device_node *np; + int i = 0; + + for_each_child_of_node(of_node, np) { + if (i == rsnd_mod_id(mod)) + break; + i++; + } + + chan = of_dma_request_slave_channel(np, name); + + of_node_put(np); + of_node_put(of_node); + + return chan; +} + +static struct dma_chan *rsnd_dmaen_request_channel(struct rsnd_mod *mod_from, + struct rsnd_mod *mod_to) +{ + if ((!mod_from && !mod_to) || + (mod_from && mod_to)) + return NULL; + + if (mod_from) + return rsnd_mod_dma_req(mod_from); + else + return rsnd_mod_dma_req(mod_to); +} + static int rsnd_dmaen_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id, struct rsnd_mod *mod_from, struct rsnd_mod *mod_to) { @@ -124,8 +137,6 @@ static int rsnd_dmaen_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id, struct rsnd_mod *mod = rsnd_dma_to_mod(dma); struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); int is_play = rsnd_io_is_play(io); - char dma_name[DMA_NAME_SIZE]; - dma_cap_mask_t mask; int ret;
if (dmaen->chan) { @@ -135,10 +146,21 @@ static int rsnd_dmaen_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id,
dev_dbg(dev, "Audio DMAC init\n");
- dma_cap_zero(mask); - dma_cap_set(DMA_SLAVE, mask); + if (dev->of_node) { + dmaen->chan = rsnd_dmaen_request_channel(mod_from, mod_to); + } else { + dma_cap_mask_t mask; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask);
- rsnd_dmaen_of_name(mod_from, mod_to, dma_name); + dmaen->chan = dma_request_channel(mask, shdma_chan_filter, + (void *)id); + } + if (IS_ERR_OR_NULL(dmaen->chan)) { + dev_err(dev, "can't get dma channel\n"); + goto rsnd_dma_channel_err; + }
cfg.direction = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM; cfg.src_addr = dma->src_addr; @@ -146,16 +168,8 @@ static int rsnd_dmaen_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id, cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
- dev_dbg(dev, "dma : %s %pad -> %pad\n", - dma_name, &cfg.src_addr, &cfg.dst_addr); - - dmaen->chan = dma_request_slave_channel_compat(mask, shdma_chan_filter, - (void *)id, dev, - dma_name); - if (!dmaen->chan) { - dev_err(dev, "can't get dma channel\n"); - goto rsnd_dma_channel_err; - } + dev_dbg(dev, "dma : %pad -> %pad\n", + &cfg.src_addr, &cfg.dst_addr);
ret = dmaengine_slave_config(dmaen->chan, &cfg); if (ret < 0) diff --git a/sound/soc/sh/rcar/dvc.c b/sound/soc/sh/rcar/dvc.c index e099018..aeeef13 100644 --- a/sound/soc/sh/rcar/dvc.c +++ b/sound/soc/sh/rcar/dvc.c @@ -272,8 +272,17 @@ static int rsnd_dvc_pcm_new(struct rsnd_mod *mod, return 0; }
+static struct dma_chan *rsnd_dvc_dma_req(struct rsnd_mod *mod) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + + return rsnd_dma_request_channel(rsnd_dvc_of_node(priv), + mod, "tx"); +} + static struct rsnd_mod_ops rsnd_dvc_ops = { .name = DVC_NAME, + .dma_req = rsnd_dvc_dma_req, .probe = rsnd_dvc_probe_gen2, .remove = rsnd_dvc_remove_gen2, .init = rsnd_dvc_init, diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 68bc3f4..52c401c 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -207,6 +207,8 @@ void rsnd_dma_quit(struct rsnd_dma *dma); int rsnd_dma_probe(struct platform_device *pdev, const struct rsnd_of_data *of_data, struct rsnd_priv *priv); +struct dma_chan *rsnd_dma_request_channel(struct device_node *of_node, + struct rsnd_mod *mod, char *name);
#define rsnd_dma_to_mod(_dma) container_of((_dma), struct rsnd_mod, dma)
@@ -222,7 +224,7 @@ enum rsnd_mod_type {
struct rsnd_mod_ops { char *name; - char* (*dma_name)(struct rsnd_mod *mod); + struct dma_chan* (*dma_req)(struct rsnd_mod *mod); int (*probe)(struct rsnd_mod *mod, struct rsnd_priv *priv); int (*remove)(struct rsnd_mod *mod, @@ -292,7 +294,7 @@ void rsnd_mod_init(struct rsnd_mod *mod, enum rsnd_mod_type type, int id); char *rsnd_mod_name(struct rsnd_mod *mod); -char *rsnd_mod_dma_name(struct rsnd_mod *mod); +struct dma_chan *rsnd_mod_dma_req(struct rsnd_mod *mod);
/* * R-Car sound DAI diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c index 5a601be..6ce8985 100644 --- a/sound/soc/sh/rcar/src.c +++ b/sound/soc/sh/rcar/src.c @@ -114,6 +114,17 @@ struct rsnd_src { /* * Gen1/Gen2 common functions */ +static struct dma_chan *rsnd_src_dma_req(struct rsnd_mod *mod) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); + int is_play = rsnd_io_is_play(io); + + return rsnd_dma_request_channel(rsnd_src_of_node(priv), + mod, + is_play ? "rx" : "tx"); +} + int rsnd_src_ssiu_start(struct rsnd_mod *ssi_mod, int use_busif) { @@ -506,6 +517,7 @@ static int rsnd_src_stop_gen1(struct rsnd_mod *mod,
static struct rsnd_mod_ops rsnd_src_gen1_ops = { .name = SRC_NAME, + .dma_req = rsnd_src_dma_req, .probe = rsnd_src_probe_gen1, .init = rsnd_src_init_gen1, .quit = rsnd_src_quit, @@ -780,6 +792,7 @@ static int rsnd_src_stop_gen2(struct rsnd_mod *mod,
static struct rsnd_mod_ops rsnd_src_gen2_ops = { .name = SRC_NAME, + .dma_req = rsnd_src_dma_req, .probe = rsnd_src_probe_gen2, .remove = rsnd_src_remove_gen2, .init = rsnd_src_init_gen2, diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 2133eb3..fea4aa5 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -553,14 +553,25 @@ static int rsnd_ssi_dma_stop(struct rsnd_mod *mod, return 0; }
-static char *rsnd_ssi_dma_name(struct rsnd_mod *mod) +static struct dma_chan *rsnd_ssi_dma_req(struct rsnd_mod *mod) { - return rsnd_ssi_use_busif(mod) ? "ssiu" : SSI_NAME; + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); + int is_play = rsnd_io_is_play(io); + char *name; + + if (rsnd_ssi_use_busif(mod)) + name = is_play ? "rxu" : "txu"; + else + name = is_play ? "rx" : "tx"; + + return rsnd_dma_request_channel(rsnd_ssi_of_node(priv), + mod, name); }
static struct rsnd_mod_ops rsnd_ssi_dma_ops = { .name = SSI_NAME, - .dma_name = rsnd_ssi_dma_name, + .dma_req = rsnd_ssi_dma_req, .probe = rsnd_ssi_dma_probe, .remove = rsnd_ssi_dma_remove, .init = rsnd_ssi_init,
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
cfcefe01265cbaf5ca7209226d043b07bfa8b587 (ASoC: rsnd: add recovery support for under/over flow error on SRC) added SRC recovery support which needs IRQ. This patch adds SRC irq sample code on DT bingdings text
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- v1 -> v2
- tidyup for subnode dma-engine
.../devicetree/bindings/sound/renesas,rsnd.txt | 40 +++++++++++++++----- 1 file changed, 30 insertions(+), 10 deletions(-)
diff --git a/Documentation/devicetree/bindings/sound/renesas,rsnd.txt b/Documentation/devicetree/bindings/sound/renesas,rsnd.txt index 2dd690b..87e0fc2 100644 --- a/Documentation/devicetree/bindings/sound/renesas,rsnd.txt +++ b/Documentation/devicetree/bindings/sound/renesas,rsnd.txt @@ -53,16 +53,36 @@ rcar_sound: rcar_sound@ec500000 { };
rcar_sound,src { - src0: src@0 { }; - src1: src@1 { }; - src2: src@2 { }; - src3: src@3 { }; - src4: src@4 { }; - src5: src@5 { }; - src6: src@6 { }; - src7: src@7 { }; - src8: src@8 { }; - src9: src@9 { }; + src0: src@0 { + interrupts = <0 352 IRQ_TYPE_LEVEL_HIGH>; + }; + src1: src@1 { + interrupts = <0 353 IRQ_TYPE_LEVEL_HIGH>; + }; + src2: src@2 { + interrupts = <0 354 IRQ_TYPE_LEVEL_HIGH>; + }; + src3: src@3 { + interrupts = <0 355 IRQ_TYPE_LEVEL_HIGH>; + }; + src4: src@4 { + interrupts = <0 356 IRQ_TYPE_LEVEL_HIGH>; + }; + src5: src@5 { + interrupts = <0 357 IRQ_TYPE_LEVEL_HIGH>; + }; + src6: src@6 { + interrupts = <0 358 IRQ_TYPE_LEVEL_HIGH>; + }; + src7: src@7 { + interrupts = <0 359 IRQ_TYPE_LEVEL_HIGH>; + }; + src8: src@8 { + interrupts = <0 360 IRQ_TYPE_LEVEL_HIGH>; + }; + src9: src@9 { + interrupts = <0 361 IRQ_TYPE_LEVEL_HIGH>; + }; };
rcar_sound,ssi {
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- v1 -> v2
- no change
.../devicetree/bindings/sound/renesas,rsnd.txt | 21 ++++++++++++++++++++ 1 file changed, 21 insertions(+)
diff --git a/Documentation/devicetree/bindings/sound/renesas,rsnd.txt b/Documentation/devicetree/bindings/sound/renesas,rsnd.txt index 87e0fc2..503967b 100644 --- a/Documentation/devicetree/bindings/sound/renesas,rsnd.txt +++ b/Documentation/devicetree/bindings/sound/renesas,rsnd.txt @@ -47,6 +47,27 @@ rcar_sound: rcar_sound@ec500000 { <0 0xec540000 0 0x1000>, /* SSIU */ <0 0xec541000 0 0x1280>; /* SSI */
+ clocks = <&mstp10_clks R8A7790_CLK_SSI_ALL>, + <&mstp10_clks R8A7790_CLK_SSI9>, <&mstp10_clks R8A7790_CLK_SSI8>, + <&mstp10_clks R8A7790_CLK_SSI7>, <&mstp10_clks R8A7790_CLK_SSI6>, + <&mstp10_clks R8A7790_CLK_SSI5>, <&mstp10_clks R8A7790_CLK_SSI4>, + <&mstp10_clks R8A7790_CLK_SSI3>, <&mstp10_clks R8A7790_CLK_SSI2>, + <&mstp10_clks R8A7790_CLK_SSI1>, <&mstp10_clks R8A7790_CLK_SSI0>, + <&mstp10_clks R8A7790_CLK_SCU_SRC9>, <&mstp10_clks R8A7790_CLK_SCU_SRC8>, + <&mstp10_clks R8A7790_CLK_SCU_SRC7>, <&mstp10_clks R8A7790_CLK_SCU_SRC6>, + <&mstp10_clks R8A7790_CLK_SCU_SRC5>, <&mstp10_clks R8A7790_CLK_SCU_SRC4>, + <&mstp10_clks R8A7790_CLK_SCU_SRC3>, <&mstp10_clks R8A7790_CLK_SCU_SRC2>, + <&mstp10_clks R8A7790_CLK_SCU_SRC1>, <&mstp10_clks R8A7790_CLK_SCU_SRC0>, + <&mstp10_clks R8A7790_CLK_SCU_DVC0>, <&mstp10_clks R8A7790_CLK_SCU_DVC1>, + <&audio_clk_a>, <&audio_clk_b>, <&audio_clk_c>, <&m2_clk>; + clock-names = "ssi-all", + "ssi.9", "ssi.8", "ssi.7", "ssi.6", "ssi.5", + "ssi.4", "ssi.3", "ssi.2", "ssi.1", "ssi.0", + "src.9", "src.8", "src.7", "src.6", "src.5", + "src.4", "src.3", "src.2", "src.1", "src.0", + "dvc.0", "dvc.1", + "clk_a", "clk_b", "clk_c", "clk_i"; + rcar_sound,dvc { dvc0: dvc@0 { }; dvc1: dvc@1 { };
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
rsnd driver supports Audio DMAC (via DMAEngine) / Audio DMAC peri peri (via rsnd driver) now. This patch adds DT binding sample code on DT binging text
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- v1 ->v2
- subnode version
.../devicetree/bindings/sound/renesas,rsnd.txt | 60 +++++++++++++++++++- 1 file changed, 57 insertions(+), 3 deletions(-)
diff --git a/Documentation/devicetree/bindings/sound/renesas,rsnd.txt b/Documentation/devicetree/bindings/sound/renesas,rsnd.txt index 503967b..6e660d4 100644 --- a/Documentation/devicetree/bindings/sound/renesas,rsnd.txt +++ b/Documentation/devicetree/bindings/sound/renesas,rsnd.txt @@ -29,9 +29,17 @@ SSI subnode properties: - shared-pin : if shared clock pin - pio-transfer : use PIO transfer mode - no-busif : BUSIF is not ussed when [mem -> SSI] via DMA case +- dma : Should contain Audio DMAC entry +- dma-names : SSI case "rx" (=playback), "tx" (=capture) + SSIU case "rxu" (=playback), "txu" (=capture)
SRC subnode properties: -no properties at this point +- dma : Should contain Audio DMAC entry +- dma-names : "rx" (=playback), "tx" (=capture) + +DVC subnode properties: +- dma : Should contain Audio DMAC entry +- dma-names : "tx" (=playback/capture)
DAI subnode properties: - playback : list of playback modules @@ -69,73 +77,119 @@ rcar_sound: rcar_sound@ec500000 { "clk_a", "clk_b", "clk_c", "clk_i";
rcar_sound,dvc { - dvc0: dvc@0 { }; - dvc1: dvc@1 { }; + dvc0: dvc@0 { + dmas = <&audma0 0xbc>; + dma-names = "tx"; + }; + dvc1: dvc@1 { + dmas = <&audma0 0xbe>; + dma-names = "tx"; + }; };
rcar_sound,src { src0: src@0 { interrupts = <0 352 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x85>, <&audma1 0x9a>; + dma-names = "rx", "tx"; }; src1: src@1 { interrupts = <0 353 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x87>, <&audma1 0x9c>; + dma-names = "rx", "tx"; }; src2: src@2 { interrupts = <0 354 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x89>, <&audma1 0x9e>; + dma-names = "rx", "tx"; }; src3: src@3 { interrupts = <0 355 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x8b>, <&audma1 0xa0>; + dma-names = "rx", "tx"; }; src4: src@4 { interrupts = <0 356 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x8d>, <&audma1 0xb0>; + dma-names = "rx", "tx"; }; src5: src@5 { interrupts = <0 357 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x8f>, <&audma1 0xb2>; + dma-names = "rx", "tx"; }; src6: src@6 { interrupts = <0 358 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x91>, <&audma1 0xb4>; + dma-names = "rx", "tx"; }; src7: src@7 { interrupts = <0 359 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x93>, <&audma1 0xb6>; + dma-names = "rx", "tx"; }; src8: src@8 { interrupts = <0 360 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x95>, <&audma1 0xb8>; + dma-names = "rx", "tx"; }; src9: src@9 { interrupts = <0 361 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x97>, <&audma1 0xba>; + dma-names = "rx", "tx"; }; };
rcar_sound,ssi { ssi0: ssi@0 { interrupts = <0 370 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x01>, <&audma1 0x02>, <&audma0 0x15>, <&audma1 0x16>; + dma-names = "rx", "tx", "rxu", "txu"; }; ssi1: ssi@1 { interrupts = <0 371 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x03>, <&audma1 0x04>, <&audma0 0x49>, <&audma1 0x4a>; + dma-names = "rx", "tx", "rxu", "txu"; }; ssi2: ssi@2 { interrupts = <0 372 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x05>, <&audma1 0x06>, <&audma0 0x63>, <&audma1 0x64>; + dma-names = "rx", "tx", "rxu", "txu"; }; ssi3: ssi@3 { interrupts = <0 373 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x07>, <&audma1 0x08>, <&audma0 0x6f>, <&audma1 0x70>; + dma-names = "rx", "tx", "rxu", "txu"; }; ssi4: ssi@4 { interrupts = <0 374 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x09>, <&audma1 0x0a>, <&audma0 0x71>, <&audma1 0x72>; + dma-names = "rx", "tx", "rxu", "txu"; }; ssi5: ssi@5 { interrupts = <0 375 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x0b>, <&audma1 0x0c>, <&audma0 0x73>, <&audma1 0x74>; + dma-names = "rx", "tx", "rxu", "txu"; }; ssi6: ssi@6 { interrupts = <0 376 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x0d>, <&audma1 0x0e>, <&audma0 0x75>, <&audma1 0x76>; + dma-names = "rx", "tx", "rxu", "txu"; }; ssi7: ssi@7 { interrupts = <0 377 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x0f>, <&audma1 0x10>, <&audma0 0x79>, <&audma1 0x7a>; + dma-names = "rx", "tx", "rxu", "txu"; }; ssi8: ssi@8 { interrupts = <0 378 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x11>, <&audma1 0x12>, <&audma0 0x7b>, <&audma1 0x7c>; + dma-names = "rx", "tx", "rxu", "txu"; }; ssi9: ssi@9 { interrupts = <0 379 IRQ_TYPE_LEVEL_HIGH>; + dmas = <&audma0 0x13>, <&audma1 0x14>, <&audma0 0x7d>, <&audma1 0x7e>; + dma-names = "rx", "tx", "rxu", "txu"; }; };
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
Current rsnd driver supports reg-names, and Audio DMAC peri peri. This patch adds sample code for it.
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com --- v1 -> v2
- no change
.../devicetree/bindings/sound/renesas,rsnd.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/sound/renesas,rsnd.txt b/Documentation/devicetree/bindings/sound/renesas,rsnd.txt index 6e660d4..f316ce1 100644 --- a/Documentation/devicetree/bindings/sound/renesas,rsnd.txt +++ b/Documentation/devicetree/bindings/sound/renesas,rsnd.txt @@ -53,7 +53,9 @@ rcar_sound: rcar_sound@ec500000 { reg = <0 0xec500000 0 0x1000>, /* SCU */ <0 0xec5a0000 0 0x100>, /* ADG */ <0 0xec540000 0 0x1000>, /* SSIU */ - <0 0xec541000 0 0x1280>; /* SSI */ + <0 0xec541000 0 0x1280>, /* SSI */ + <0 0xec740000 0 0x200>; /* Audio DMAC peri peri*/ + reg-names = "scu", "adg", "ssiu", "ssi", "audmapp";
clocks = <&mstp10_clks R8A7790_CLK_SSI_ALL>, <&mstp10_clks R8A7790_CLK_SSI9>, <&mstp10_clks R8A7790_CLK_SSI8>,
On Fri, Feb 20, 2015 at 10:21:10AM +0000, Kuninori Morimoto wrote:
These patches add Audio DMAC peri peri implementation in rsnd driver. I will remove current DMAEngine side Audio DMAC peri peri implement if these are accepted.
I've applied all of these which I think is the intention but I'm a bit confused since there's a random reply to the first patch where it's replaced by a v3 marked as patch 1/28 but there's only 24 patches in this version. I'm hoping that's a typo, this is one of the reasons to avoid trying to replace just a single patch in a series - it makes things more complicated to follow.
Hi Mark
These patches add Audio DMAC peri peri implementation in rsnd driver. I will remove current DMAEngine side Audio DMAC peri peri implement if these are accepted.
I've applied all of these which I think is the intention but I'm a bit confused since there's a random reply to the first patch where it's replaced by a v3 marked as patch 1/28 but there's only 24 patches in this version. I'm hoping that's a typo, this is one of the reasons to avoid trying to replace just a single patch in a series - it makes things more complicated to follow.
Oh my... indeed it was typo I'm so sorry about that.
Best regards --- Kuninori Morimoto
participants (4)
-
Geert Uytterhoeven
-
Kuninori Morimoto
-
Mark Brown
-
Vinod Koul