ASoC: rsnd: adjust disabled module
authorKuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Mon, 31 May 2021 04:19:32 +0000 (13:19 +0900)
committerMark Brown <broonie@kernel.org>
Tue, 1 Jun 2021 13:04:15 +0000 (14:04 +0100)
In general Renesas SoC's SSI/SRC are all enabled, but some SoC is not.

H2 E2

SRC0       <=
SRC1 SRC1
SRC2 SRC2
... ...

Renesas Sound driver is assuming that *all* modules are
enabled, and thus it is using *data array* to access each modules.
Because of it, we have been using "status = disabled" at DT,
and using *full size* array but avoiding disabled module.

ex)
rcar_sound,src {
src-0 {
=> status = "disabled";
};
src1: src-1 {
...
};
...

But R-Car D3 have many disabled modules (It has SSI3/SSI4, SRC5/SRC6),
and Renesas SoC maintainer don't want above style on DT.

ex)
rcar_sound,src {
=> src0: src-0 { status = "disabled"; };
=> src1: src-1 { status = "disabled"; };
=> src2: src-2 { status = "disabled"; };
=> src3: src-3 { status = "disabled"; };
=> src4: src-4 { status = "disabled"; };
src5: src-5 {
...
};
src6: src-6 {
...
};
};

rcar_sound,ssi {
=> ssi0: ssi-0 { status = "disabled"; };
=> ssi1: ssi-1 { status = "disabled"; };
=> ssi2: ssi-2 { status = "disabled"; };
ssi3: ssi-3 {
...
};
ssi4: ssi-4 {
...
};
};

To adjust it, it needs to care about related for_each_child_of_node()
loop on rsnd driver, and it is used from...

> grep -l for_each_child_of_node sound/soc/sh/rcar/*
sound/soc/sh/rcar/core.c
sound/soc/sh/rcar/ctu.c
sound/soc/sh/rcar/dma.c
sound/soc/sh/rcar/dvc.c
sound/soc/sh/rcar/mix.c
sound/soc/sh/rcar/src.c
sound/soc/sh/rcar/ssi.c
sound/soc/sh/rcar/ssiu.c

This patch adjust to this situation.
By this patch, we can avoid disabled modules on DT

rcar_sound,src {
src5: src-5 {
...
};
src6: src-6 {
...
};
};

rcar_sound,ssi {
ssi3: ssi-3 {
...
};
ssi4: ssi-4 {
...
};
};

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Link: https://lore.kernel.org/r/875yyzk017.wl-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/rsnd.h
sound/soc/sh/rcar/src.c
sound/soc/sh/rcar/ssi.c
sound/soc/sh/rcar/ssiu.c

index b50812c..a4ed9d8 100644 (file)
@@ -1142,6 +1142,8 @@ void rsnd_parse_connect_common(struct rsnd_dai *rdai, char *name,
        for_each_child_of_node(node, np) {
                struct rsnd_mod *mod;
 
+               i = rsnd_node_fixed_index(np, name, i);
+
                mod = mod_get(priv, i);
 
                if (np == playback)
@@ -1154,6 +1156,56 @@ void rsnd_parse_connect_common(struct rsnd_dai *rdai, char *name,
        of_node_put(node);
 }
 
+int rsnd_node_fixed_index(struct device_node *node, char *name, int idx)
+{
+       char node_name[16];
+
+       /*
+        * rsnd is assuming each device nodes are sequential numbering,
+        * but some of them are not.
+        * This function adjusts index for it.
+        *
+        * ex)
+        * Normal case,         special case
+        *      ssi-0
+        *      ssi-1
+        *      ssi-2
+        *      ssi-3           ssi-3
+        *      ssi-4           ssi-4
+        *      ...
+        *
+        * assume Max 64 node
+        */
+       for (; idx < 64; idx++) {
+               snprintf(node_name, sizeof(node_name), "%s-%d", name, idx);
+
+               if (strncmp(node_name, of_node_full_name(node), sizeof(node_name)) == 0)
+                       return idx;
+       }
+
+       return -EINVAL;
+}
+
+int rsnd_node_count(struct rsnd_priv *priv, struct device_node *node, char *name)
+{
+       struct device *dev = rsnd_priv_to_dev(priv);
+       struct device_node *np;
+       int i;
+
+       i = 0;
+       for_each_child_of_node(node, np) {
+               i = rsnd_node_fixed_index(np, name, i);
+               if (i < 0) {
+                       dev_err(dev, "strange node numbering (%s)",
+                               of_node_full_name(node));
+                       return 0;
+               }
+               i++;
+       }
+
+       return i;
+}
+
 static struct device_node *rsnd_dai_of_node(struct rsnd_priv *priv,
                                            int *is_graph)
 {
index d581f14..82d16e0 100644 (file)
@@ -245,6 +245,8 @@ struct dma_chan *rsnd_dma_request_channel(struct device_node *of_node, char *nam
        int i = 0;
 
        for_each_child_of_node(of_node, np) {
+               i = rsnd_node_fixed_index(np, name, i);
+
                if (i == rsnd_mod_id_raw(mod) && (!chan))
                        chan = of_dma_request_slave_channel(np, x);
                i++;
index 256a11b..b2fbe3b 100644 (file)
@@ -465,6 +465,8 @@ void rsnd_parse_connect_common(struct rsnd_dai *rdai, char *name,
                struct device_node *node,
                struct device_node *playback,
                struct device_node *capture);
+int rsnd_node_count(struct rsnd_priv *priv, struct device_node *node, char *name);
+int rsnd_node_fixed_index(struct device_node *node, char *name, int idx);
 
 int rsnd_channel_normalization(int chan);
 #define rsnd_runtime_channel_original(io) \
index 9ccc959..42a100c 100644 (file)
@@ -656,7 +656,7 @@ int rsnd_src_probe(struct rsnd_priv *priv)
        if (!node)
                return 0; /* not used is not error */
 
-       nr = of_get_child_count(node);
+       nr = rsnd_node_count(priv, node, SRC_NAME);
        if (!nr) {
                ret = -EINVAL;
                goto rsnd_src_probe_done;
@@ -676,6 +676,8 @@ int rsnd_src_probe(struct rsnd_priv *priv)
                if (!of_device_is_available(np))
                        goto skip;
 
+               i = rsnd_node_fixed_index(np, SRC_NAME, i);
+
                src = rsnd_src_get(priv, i);
 
                snprintf(name, RSND_SRC_NAME_SIZE, "%s.%d",
index 4c91091..27f34ca 100644 (file)
@@ -1117,6 +1117,8 @@ void rsnd_parse_connect_ssi(struct rsnd_dai *rdai,
        for_each_child_of_node(node, np) {
                struct rsnd_mod *mod;
 
+               i = rsnd_node_fixed_index(np, SSI_NAME, i);
+
                mod = rsnd_ssi_mod_get(priv, i);
 
                if (np == playback)
@@ -1160,7 +1162,7 @@ int rsnd_ssi_probe(struct rsnd_priv *priv)
        if (!node)
                return -EINVAL;
 
-       nr = of_get_child_count(node);
+       nr = rsnd_node_count(priv, node, SSI_NAME);
        if (!nr) {
                ret = -EINVAL;
                goto rsnd_ssi_probe_done;
@@ -1180,6 +1182,8 @@ int rsnd_ssi_probe(struct rsnd_priv *priv)
                if (!of_device_is_available(np))
                        goto skip;
 
+               i = rsnd_node_fixed_index(np, SSI_NAME, i);
+
                ssi = rsnd_ssi_get(priv, i);
 
                snprintf(name, RSND_SSI_NAME_SIZE, "%s.%d",
index 819739e..5682c74 100644 (file)
@@ -472,6 +472,8 @@ void rsnd_parse_connect_ssiu(struct rsnd_dai *rdai,
                for_each_child_of_node(node, np) {
                        struct rsnd_mod *mod;
 
+                       i = rsnd_node_fixed_index(np, SSIU_NAME, i);
+
                        mod = rsnd_ssiu_mod_get(priv, i);
 
                        if (np == playback)
@@ -509,7 +511,7 @@ int rsnd_ssiu_probe(struct rsnd_priv *priv)
         */
        node = rsnd_ssiu_of_node(priv);
        if (node)
-               nr = of_get_child_count(node);
+               nr = rsnd_node_count(priv, node, SSIU_NAME);
        else
                nr = priv->ssi_nr;