Commit 547b02f7 authored by Kuninori Morimoto's avatar Kuninori Morimoto Committed by Mark Brown

ASoC: rsnd: enable multi Component support for Audio Graph Card/Card2

	+-- 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: default avatarKuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Link: https://lore.kernel.org/r/87tttub1m4.wl-kuninori.morimoto.gx@renesas.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent 6328489c
...@@ -1260,13 +1260,13 @@ int rsnd_node_count(struct rsnd_priv *priv, struct device_node *node, char *name ...@@ -1260,13 +1260,13 @@ int rsnd_node_count(struct rsnd_priv *priv, struct device_node *node, char *name
return i; return i;
} }
static struct device_node *rsnd_dai_of_node(struct rsnd_priv *priv, static int rsnd_dai_of_node(struct rsnd_priv *priv, int *is_graph)
int *nr, int *is_graph)
{ {
struct device *dev = rsnd_priv_to_dev(priv); struct device *dev = rsnd_priv_to_dev(priv);
struct device_node *np = dev->of_node; struct device_node *np = dev->of_node;
struct device_node *dai_node; struct device_node *ports, *node;
struct device_node *ret; int nr = 0;
int i = 0;
*is_graph = 0; *is_graph = 0;
...@@ -1278,30 +1278,47 @@ static struct device_node *rsnd_dai_of_node(struct rsnd_priv *priv, ...@@ -1278,30 +1278,47 @@ static struct device_node *rsnd_dai_of_node(struct rsnd_priv *priv,
/* /*
* Simple-Card * Simple-Card
*/ */
dai_node = of_get_child_by_name(np, RSND_NODE_DAI); node = of_get_child_by_name(np, RSND_NODE_DAI);
if (dai_node) { if (!node)
*nr = of_get_child_count(dai_node); goto audio_graph;
ret = dai_node;
goto of_node_compatible; 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 * Audio-Graph-Card
*/ */
dai_node = of_graph_get_next_endpoint(np, NULL); for_each_child_of_node(np, ports) {
if (dai_node) { if (!of_node_name_eq(ports, "ports") &&
*nr = of_graph_get_endpoint_count(np); !of_node_name_eq(ports, "port"))
*is_graph = 1; continue;
ret = np; priv->component_dais[i] = of_graph_get_endpoint_count(ports);
goto of_node_compatible; nr += priv->component_dais[i];
i++;
if (i >= RSND_MAX_COMPONENT) {
dev_info(dev, "reach to max component\n");
break;
}
} }
return NULL; *is_graph = 1;
of_node_compatible:
of_node_put(dai_node);
return ret; return nr;
} }
...@@ -1365,6 +1382,8 @@ static int rsnd_pcm_new(struct snd_soc_pcm_runtime *rtd, ...@@ -1365,6 +1382,8 @@ static int rsnd_pcm_new(struct snd_soc_pcm_runtime *rtd,
static void __rsnd_dai_probe(struct rsnd_priv *priv, static void __rsnd_dai_probe(struct rsnd_priv *priv,
struct device_node *dai_np, struct device_node *dai_np,
struct device_node *node_np,
uint32_t node_arg,
int dai_i) int dai_i)
{ {
struct rsnd_dai_stream *io_playback; struct rsnd_dai_stream *io_playback;
...@@ -1382,11 +1401,17 @@ static void __rsnd_dai_probe(struct rsnd_priv *priv, ...@@ -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); 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; rdai->priv = priv;
drv->name = rdai->name; drv->name = rdai->name;
drv->ops = &rsnd_soc_dai_ops; drv->ops = &rsnd_soc_dai_ops;
drv->pcm_new = rsnd_pcm_new; drv->pcm_new = rsnd_pcm_new;
drv->id = dai_i; drv->id = dai_i;
drv->dai_args = &rdai->dai_args;
io_playback->rdai = rdai; io_playback->rdai = rdai;
io_capture->rdai = rdai; io_capture->rdai = rdai;
...@@ -1450,16 +1475,15 @@ static void __rsnd_dai_probe(struct rsnd_priv *priv, ...@@ -1450,16 +1475,15 @@ static void __rsnd_dai_probe(struct rsnd_priv *priv,
static int 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 snd_soc_dai_driver *rdrv;
struct device *dev = rsnd_priv_to_dev(priv); struct device *dev = rsnd_priv_to_dev(priv);
struct device_node *np = dev->of_node;
struct rsnd_dai *rdai; struct rsnd_dai *rdai;
int nr = 0; int nr = 0;
int is_graph; int is_graph;
int dai_i; int dai_i;
dai_node = rsnd_dai_of_node(priv, &nr, &is_graph); nr = rsnd_dai_of_node(priv, &is_graph);
if (!nr) if (!nr)
return -EINVAL; return -EINVAL;
...@@ -1477,26 +1501,42 @@ static int rsnd_dai_probe(struct rsnd_priv *priv) ...@@ -1477,26 +1501,42 @@ static int rsnd_dai_probe(struct rsnd_priv *priv)
*/ */
dai_i = 0; dai_i = 0;
if (is_graph) { if (is_graph) {
for_each_endpoint_of_node(dai_node, dai_np) { struct device_node *ports;
__rsnd_dai_probe(priv, dai_np, dai_i); struct device_node *dai_np;
if (rsnd_is_gen3(priv) || rsnd_is_gen4(priv)) {
rdai = rsnd_rdai_get(priv, dai_i); for_each_child_of_node(np, ports) {
if (!of_node_name_eq(ports, "ports") &&
rsnd_parse_connect_graph(priv, &rdai->playback, dai_np); !of_node_name_eq(ports, "port"))
rsnd_parse_connect_graph(priv, &rdai->capture, dai_np); 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 { } else {
for_each_child_of_node(dai_node, dai_np) { struct device_node *node;
__rsnd_dai_probe(priv, dai_np, dai_i); struct device_node *dai_np;
if (rsnd_is_gen3(priv) || rsnd_is_gen4(priv)) {
rdai = rsnd_rdai_get(priv, dai_i); 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); for_each_child_of_node(node, dai_np) {
rsnd_parse_connect_simple(priv, &rdai->capture, 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) ...@@ -1926,6 +1966,7 @@ static int rsnd_probe(struct platform_device *pdev)
rsnd_dai_probe, rsnd_dai_probe,
}; };
int ret, i; int ret, i;
int ci;
/* /*
* init priv data * init priv data
...@@ -1962,11 +2003,18 @@ static int rsnd_probe(struct platform_device *pdev) ...@@ -1962,11 +2003,18 @@ static int rsnd_probe(struct platform_device *pdev)
/* /*
* asoc register * asoc register
*/ */
ret = devm_snd_soc_register_component(dev, &rsnd_soc_component, ci = 0;
priv->daidrv, rsnd_rdai_nr(priv)); for (i = 0; priv->component_dais[i] > 0; i++) {
if (ret < 0) { int nr = priv->component_dais[i];
dev_err(dev, "cannot snd dai register\n");
goto exit_snd_probe; 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); pm_runtime_enable(dev);
......
...@@ -545,6 +545,7 @@ struct rsnd_dai { ...@@ -545,6 +545,7 @@ struct rsnd_dai {
struct rsnd_dai_stream capture; struct rsnd_dai_stream capture;
struct rsnd_priv *priv; struct rsnd_priv *priv;
struct snd_pcm_hw_constraint_list constraint; struct snd_pcm_hw_constraint_list constraint;
struct of_phandle_args dai_args;
int max_channels; /* 2ch - 16ch */ int max_channels; /* 2ch - 16ch */
int ssi_lane; /* 1lane - 4lane */ int ssi_lane; /* 1lane - 4lane */
...@@ -702,6 +703,9 @@ struct rsnd_priv { ...@@ -702,6 +703,9 @@ struct rsnd_priv {
struct snd_soc_dai_driver *daidrv; struct snd_soc_dai_driver *daidrv;
struct rsnd_dai *rdai; struct rsnd_dai *rdai;
int rdai_nr; int rdai_nr;
#define RSND_MAX_COMPONENT 3
int component_dais[RSND_MAX_COMPONENT];
}; };
#define rsnd_priv_to_pdev(priv) ((priv)->pdev) #define rsnd_priv_to_pdev(priv) ((priv)->pdev)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment