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

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.com


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 6328489c
Loading
Loading
Loading
Loading
+91 −43
Original line number Diff line number Diff line
@@ -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,8 +1501,15 @@ 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);
		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);

@@ -1487,9 +1518,17 @@ static int rsnd_dai_probe(struct rsnd_priv *priv)
				}
				dai_i++;
			}
		}
	} else {
		for_each_child_of_node(dai_node, dai_np) {
			__rsnd_dai_probe(priv, dai_np, 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;

			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);

@@ -1499,6 +1538,7 @@ static int rsnd_dai_probe(struct rsnd_priv *priv)
				dai_i++;
			}
		}
	}

	return 0;
}
@@ -1926,6 +1966,7 @@ static int rsnd_probe(struct platform_device *pdev)
		rsnd_dai_probe,
	};
	int ret, i;
	int ci;

	/*
	 *	init priv data
@@ -1962,13 +2003,20 @@ static int rsnd_probe(struct platform_device *pdev)
	/*
	 *	asoc register
	 */
	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, rsnd_rdai_nr(priv));
						      priv->daidrv + ci, nr);
		if (ret < 0) {
		dev_err(dev, "cannot snd dai register\n");
			dev_err(dev, "cannot snd component register\n");
			goto exit_snd_probe;
		}

		ci += nr;
	}

	pm_runtime_enable(dev);

	dev_info(dev, "probed\n");
+4 −0
Original line number Diff line number Diff line
@@ -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)