ASoC: rsnd: enable multi Component support for Audio Graph Card/Card2
authorKuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Mon, 24 Jul 2023 00:21:39 +0000 (00:21 +0000)
committerMark Brown <broonie@kernel.org>
Mon, 31 Jul 2023 11:44:49 +0000 (12:44 +0100)
+-- Basic Board ---------+
|+--------+      +------+|
|| CPU ch0| <--> |CodecA||
||     ch1| <-+  +------+|
|+--------+   |          |
+-------------|----------+
+-- expansion board -----+
|             |  +------+|
|             +->|CodecB||
|                +------+|
+------------------------+

In above HW connection case, we intuitively think we want to handle these
as "2 Sound Cards".

card0,0: CPU-ch0 - CodecA
card1,0: CPU-ch1 - CodecB

But, we needed to handle it as "1 big Sound Card", because of
Component vs Card limitation.

card0,0: CPU-ch0 - CodecA
card0,1: CPU-ch1 - CodecB

This patch enables multi Component to handle multi Cards.
To support it, it needs

- Fill dai_args for each DAI on snd_soc_dai_driver
- Parse DT for each Component (Simple Card/Audio Graph Card)

Ex) Simple Card

rcar_sound {
...

/* Component0 */
rcar_sound,dai@0 {
...
};

/* Component1 */
rcar_sound,dai@1 {
...
};
};

Ex) Audio Graph Card/Card2

rcar_sound {
/* Component0 */
ports@0 {
...
};

/* Component1 */
ports@1 {
...
};
};

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Link: https://lore.kernel.org/r/87tttub1m4.wl-kuninori.morimoto.gx@renesas.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/sh/rcar/core.c
sound/soc/sh/rcar/rsnd.h

index a87d7fa55f7b487c7ed1c28182417fe8c46077f9..9f3d97bc177a096c6d5b72c0615591f37acf5001 100644 (file)
@@ -1260,13 +1260,13 @@ int rsnd_node_count(struct rsnd_priv *priv, struct device_node *node, char *name
        return i;
 }
 
-static struct device_node *rsnd_dai_of_node(struct rsnd_priv *priv,
-                                           int *nr, int *is_graph)
+static int rsnd_dai_of_node(struct rsnd_priv *priv, int *is_graph)
 {
        struct device *dev = rsnd_priv_to_dev(priv);
        struct device_node *np = dev->of_node;
-       struct device_node *dai_node;
-       struct device_node *ret;
+       struct device_node *ports, *node;
+       int nr = 0;
+       int i = 0;
 
        *is_graph = 0;
 
@@ -1278,30 +1278,47 @@ static struct device_node *rsnd_dai_of_node(struct rsnd_priv *priv,
        /*
         * Simple-Card
         */
-       dai_node = of_get_child_by_name(np, RSND_NODE_DAI);
-       if (dai_node) {
-               *nr = of_get_child_count(dai_node);
-               ret = dai_node;
-               goto of_node_compatible;
+       node = of_get_child_by_name(np, RSND_NODE_DAI);
+       if (!node)
+               goto audio_graph;
+
+       of_node_put(node);
+
+       for_each_child_of_node(np, node) {
+               if (!of_node_name_eq(node, RSND_NODE_DAI))
+                       continue;
+
+               priv->component_dais[i] = of_get_child_count(node);
+               nr += priv->component_dais[i];
+               i++;
+               if (i >= RSND_MAX_COMPONENT) {
+                       dev_info(dev, "reach to max component\n");
+                       break;
+               }
        }
 
+       return nr;
+
+audio_graph:
        /*
         * Audio-Graph-Card
         */
-       dai_node = of_graph_get_next_endpoint(np, NULL);
-       if (dai_node) {
-               *nr = of_graph_get_endpoint_count(np);
-               *is_graph = 1;
-               ret = np;
-               goto of_node_compatible;
+       for_each_child_of_node(np, ports) {
+               if (!of_node_name_eq(ports, "ports") &&
+                   !of_node_name_eq(ports, "port"))
+                       continue;
+               priv->component_dais[i] = of_graph_get_endpoint_count(ports);
+               nr += priv->component_dais[i];
+               i++;
+               if (i >= RSND_MAX_COMPONENT) {
+                       dev_info(dev, "reach to max component\n");
+                       break;
+               }
        }
 
-       return NULL;
-
-of_node_compatible:
-       of_node_put(dai_node);
+       *is_graph = 1;
 
-       return ret;
+       return nr;
 }
 
 
@@ -1365,6 +1382,8 @@ static int rsnd_pcm_new(struct snd_soc_pcm_runtime *rtd,
 
 static void __rsnd_dai_probe(struct rsnd_priv *priv,
                             struct device_node *dai_np,
+                            struct device_node *node_np,
+                            uint32_t node_arg,
                             int dai_i)
 {
        struct rsnd_dai_stream *io_playback;
@@ -1382,11 +1401,17 @@ static void __rsnd_dai_probe(struct rsnd_priv *priv,
 
        snprintf(rdai->name, RSND_DAI_NAME_SIZE, "rsnd-dai.%d", dai_i);
 
+       /* for multi Component */
+       rdai->dai_args.np               = node_np;
+       rdai->dai_args.args_count       = 1;
+       rdai->dai_args.args[0]          = node_arg;
+
        rdai->priv      = priv;
        drv->name       = rdai->name;
        drv->ops        = &rsnd_soc_dai_ops;
        drv->pcm_new    = rsnd_pcm_new;
        drv->id         = dai_i;
+       drv->dai_args   = &rdai->dai_args;
 
        io_playback->rdai               = rdai;
        io_capture->rdai                = rdai;
@@ -1450,16 +1475,15 @@ static void __rsnd_dai_probe(struct rsnd_priv *priv,
 
 static int rsnd_dai_probe(struct rsnd_priv *priv)
 {
-       struct device_node *dai_node;
-       struct device_node *dai_np;
        struct snd_soc_dai_driver *rdrv;
        struct device *dev = rsnd_priv_to_dev(priv);
+       struct device_node *np = dev->of_node;
        struct rsnd_dai *rdai;
        int nr = 0;
        int is_graph;
        int dai_i;
 
-       dai_node = rsnd_dai_of_node(priv, &nr, &is_graph);
+       nr = rsnd_dai_of_node(priv, &is_graph);
        if (!nr)
                return -EINVAL;
 
@@ -1477,26 +1501,42 @@ static int rsnd_dai_probe(struct rsnd_priv *priv)
         */
        dai_i = 0;
        if (is_graph) {
-               for_each_endpoint_of_node(dai_node, dai_np) {
-                       __rsnd_dai_probe(priv, dai_np, dai_i);
-                       if (rsnd_is_gen3(priv) || rsnd_is_gen4(priv)) {
-                               rdai = rsnd_rdai_get(priv, dai_i);
-
-                               rsnd_parse_connect_graph(priv, &rdai->playback, dai_np);
-                               rsnd_parse_connect_graph(priv, &rdai->capture,  dai_np);
+               struct device_node *ports;
+               struct device_node *dai_np;
+
+               for_each_child_of_node(np, ports) {
+                       if (!of_node_name_eq(ports, "ports") &&
+                           !of_node_name_eq(ports, "port"))
+                               continue;
+                       for_each_endpoint_of_node(ports, dai_np) {
+                               __rsnd_dai_probe(priv, dai_np, dai_np, 0, dai_i);
+                               if (rsnd_is_gen3(priv) || rsnd_is_gen4(priv)) {
+                                       rdai = rsnd_rdai_get(priv, dai_i);
+
+                                       rsnd_parse_connect_graph(priv, &rdai->playback, dai_np);
+                                       rsnd_parse_connect_graph(priv, &rdai->capture,  dai_np);
+                               }
+                               dai_i++;
                        }
-                       dai_i++;
                }
        } else {
-               for_each_child_of_node(dai_node, dai_np) {
-                       __rsnd_dai_probe(priv, dai_np, dai_i);
-                       if (rsnd_is_gen3(priv) || rsnd_is_gen4(priv)) {
-                               rdai = rsnd_rdai_get(priv, dai_i);
+               struct device_node *node;
+               struct device_node *dai_np;
+
+               for_each_child_of_node(np, node) {
+                       if (!of_node_name_eq(node, RSND_NODE_DAI))
+                               continue;
 
-                               rsnd_parse_connect_simple(priv, &rdai->playback, dai_np);
-                               rsnd_parse_connect_simple(priv, &rdai->capture,  dai_np);
+                       for_each_child_of_node(node, dai_np) {
+                               __rsnd_dai_probe(priv, dai_np, np, dai_i, dai_i);
+                               if (rsnd_is_gen3(priv) || rsnd_is_gen4(priv)) {
+                                       rdai = rsnd_rdai_get(priv, dai_i);
+
+                                       rsnd_parse_connect_simple(priv, &rdai->playback, dai_np);
+                                       rsnd_parse_connect_simple(priv, &rdai->capture,  dai_np);
+                               }
+                               dai_i++;
                        }
-                       dai_i++;
                }
        }
 
@@ -1926,6 +1966,7 @@ static int rsnd_probe(struct platform_device *pdev)
                rsnd_dai_probe,
        };
        int ret, i;
+       int ci;
 
        /*
         *      init priv data
@@ -1962,11 +2003,18 @@ static int rsnd_probe(struct platform_device *pdev)
        /*
         *      asoc register
         */
-       ret = devm_snd_soc_register_component(dev, &rsnd_soc_component,
-                                        priv->daidrv, rsnd_rdai_nr(priv));
-       if (ret < 0) {
-               dev_err(dev, "cannot snd dai register\n");
-               goto exit_snd_probe;
+       ci = 0;
+       for (i = 0; priv->component_dais[i] > 0; i++) {
+               int nr = priv->component_dais[i];
+
+               ret = devm_snd_soc_register_component(dev, &rsnd_soc_component,
+                                                     priv->daidrv + ci, nr);
+               if (ret < 0) {
+                       dev_err(dev, "cannot snd component register\n");
+                       goto exit_snd_probe;
+               }
+
+               ci += nr;
        }
 
        pm_runtime_enable(dev);
index 239705d5251744312a689897c8758acea8d153a7..43c0d675cc34335a69dce795a538868d749bc7d5 100644 (file)
@@ -545,6 +545,7 @@ struct rsnd_dai {
        struct rsnd_dai_stream capture;
        struct rsnd_priv *priv;
        struct snd_pcm_hw_constraint_list constraint;
+       struct of_phandle_args dai_args;
 
        int max_channels;       /* 2ch - 16ch */
        int ssi_lane;           /* 1lane - 4lane */
@@ -702,6 +703,9 @@ struct rsnd_priv {
        struct snd_soc_dai_driver *daidrv;
        struct rsnd_dai *rdai;
        int rdai_nr;
+
+#define RSND_MAX_COMPONENT 3
+       int component_dais[RSND_MAX_COMPONENT];
 };
 
 #define rsnd_priv_to_pdev(priv)        ((priv)->pdev)