mirror of
git://git.yoctoproject.org/linux-yocto.git
synced 2025-07-18 19:49:40 +02:00
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: 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>
This commit is contained in:
parent
6328489c13
commit
547b02f74e
|
@ -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,
|
||||||
/*
|
/*
|
||||||
* 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:
|
return nr;
|
||||||
of_node_put(dai_node);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
|
||||||
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,
|
||||||
|
|
||||||
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,8 +1501,15 @@ 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;
|
||||||
|
|
||||||
|
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)) {
|
if (rsnd_is_gen3(priv) || rsnd_is_gen4(priv)) {
|
||||||
rdai = rsnd_rdai_get(priv, dai_i);
|
rdai = rsnd_rdai_get(priv, dai_i);
|
||||||
|
|
||||||
|
@ -1487,9 +1518,17 @@ static int rsnd_dai_probe(struct rsnd_priv *priv)
|
||||||
}
|
}
|
||||||
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;
|
||||||
|
|
||||||
|
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)) {
|
if (rsnd_is_gen3(priv) || rsnd_is_gen4(priv)) {
|
||||||
rdai = rsnd_rdai_get(priv, dai_i);
|
rdai = rsnd_rdai_get(priv, dai_i);
|
||||||
|
|
||||||
|
@ -1499,6 +1538,7 @@ static int rsnd_dai_probe(struct rsnd_priv *priv)
|
||||||
dai_i++;
|
dai_i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -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,13 +2003,20 @@ static int rsnd_probe(struct platform_device *pdev)
|
||||||
/*
|
/*
|
||||||
* asoc register
|
* 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,
|
ret = devm_snd_soc_register_component(dev, &rsnd_soc_component,
|
||||||
priv->daidrv, rsnd_rdai_nr(priv));
|
priv->daidrv + ci, nr);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(dev, "cannot snd dai register\n");
|
dev_err(dev, "cannot snd component register\n");
|
||||||
goto exit_snd_probe;
|
goto exit_snd_probe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ci += nr;
|
||||||
|
}
|
||||||
|
|
||||||
pm_runtime_enable(dev);
|
pm_runtime_enable(dev);
|
||||||
|
|
||||||
dev_info(dev, "probed\n");
|
dev_info(dev, "probed\n");
|
||||||
|
|
|
@ -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 {
|
||||||
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)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user