ASoC: rsnd: 1st DMAC dma-names cares subnode
authorKuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Fri, 20 Feb 2015 10:31:23 +0000 (10:31 +0000)
committerMark Brown <broonie@kernel.org>
Sat, 7 Mar 2015 15:04:30 +0000 (15:04 +0000)
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>
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/sh/rcar/core.c
sound/soc/sh/rcar/dma.c
sound/soc/sh/rcar/dvc.c
sound/soc/sh/rcar/rsnd.h
sound/soc/sh/rcar/src.c
sound/soc/sh/rcar/ssi.c

index 3b6e21948c71333c39fa448fb77314a2ceed3b4d..7b995f025e2276caf5fe43b3c2ff9a6e906f69b0 100644 (file)
@@ -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,
index 3f34461da1e0e0cf7a8b4d796b7a65e7a48c70c7..92fd55044ee6b4948e185408cb8ce82d082767dd 100644 (file)
@@ -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)
index e0990180e1ea2bc4ad9d2e0d14060e9681b3237d..aeeef1352eeee89280d5134954dfa2fb7fef0bb7 100644 (file)
@@ -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,
index 68bc3f46d70beb25f06eb1bd4e61a93986064d06..52c401c9eeef6249931195a347e5dee70919d0c8 100644 (file)
@@ -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
index 5a601bed415457a354748023f33e7a9fcac553ec..6ce8985757c12ba7f5928b74b9acdbe84cc7f1b1 100644 (file)
@@ -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,
index 2133eb34ed06624d238ecad4ac45cd955b6b41c8..fea4aa53918ab83a8b34eb650cab6c63fa9a1d90 100644 (file)
@@ -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,