summaryrefslogtreecommitdiff
path: root/sound/soc/sh/rcar/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/sh/rcar/core.c')
-rw-r--r--sound/soc/sh/rcar/core.c175
1 files changed, 114 insertions, 61 deletions
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c
index 6a522e6dd85a..e29c2fee9521 100644
--- a/sound/soc/sh/rcar/core.c
+++ b/sound/soc/sh/rcar/core.c
@@ -1085,17 +1085,6 @@ static u64 rsnd_soc_dai_formats[] = {
SND_SOC_POSSIBLE_DAIFMT_DSP_B,
};
-static const struct snd_soc_dai_ops rsnd_soc_dai_ops = {
- .startup = rsnd_soc_dai_startup,
- .shutdown = rsnd_soc_dai_shutdown,
- .trigger = rsnd_soc_dai_trigger,
- .set_fmt = rsnd_soc_dai_set_fmt,
- .set_tdm_slot = rsnd_soc_set_dai_tdm_slot,
- .prepare = rsnd_soc_dai_prepare,
- .auto_selectable_formats = rsnd_soc_dai_formats,
- .num_auto_selectable_formats = ARRAY_SIZE(rsnd_soc_dai_formats),
-};
-
static void rsnd_parse_tdm_split_mode(struct rsnd_priv *priv,
struct rsnd_dai_stream *io,
struct device_node *dai_np)
@@ -1260,13 +1249,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 *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;
@@ -1274,26 +1263,53 @@ static struct device_node *rsnd_dai_of_node(struct rsnd_priv *priv,
* parse both previous dai (= rcar_sound,dai), and
* graph dai (= ports/port)
*/
- dai_node = of_get_child_by_name(np, RSND_NODE_DAI);
- if (dai_node) {
- ret = dai_node;
- goto of_node_compatible;
- }
- ret = np;
+ /*
+ * Simple-Card
+ */
+ node = of_get_child_by_name(np, RSND_NODE_DAI);
+ if (!node)
+ goto audio_graph;
- dai_node = of_graph_get_next_endpoint(np, NULL);
- if (dai_node)
- goto of_node_graph;
+ of_node_put(node);
- return NULL;
+ 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");
+ of_node_put(node);
+ break;
+ }
+ }
+
+ return nr;
+
+audio_graph:
+ /*
+ * Audio-Graph-Card
+ */
+ 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");
+ of_node_put(node);
+ break;
+ }
+ }
-of_node_graph:
*is_graph = 1;
-of_node_compatible:
- of_node_put(dai_node);
- return ret;
+ return nr;
}
@@ -1328,8 +1344,7 @@ static int rsnd_preallocate_pages(struct snd_soc_pcm_runtime *rtd,
return 0;
}
-static int rsnd_pcm_new(struct snd_soc_pcm_runtime *rtd,
- struct snd_soc_dai *dai)
+static int rsnd_soc_dai_pcm_new(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
{
struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
int ret;
@@ -1355,8 +1370,22 @@ static int rsnd_pcm_new(struct snd_soc_pcm_runtime *rtd,
return 0;
}
+static const struct snd_soc_dai_ops rsnd_soc_dai_ops = {
+ .pcm_new = rsnd_soc_dai_pcm_new,
+ .startup = rsnd_soc_dai_startup,
+ .shutdown = rsnd_soc_dai_shutdown,
+ .trigger = rsnd_soc_dai_trigger,
+ .set_fmt = rsnd_soc_dai_set_fmt,
+ .set_tdm_slot = rsnd_soc_set_dai_tdm_slot,
+ .prepare = rsnd_soc_dai_prepare,
+ .auto_selectable_formats = rsnd_soc_dai_formats,
+ .num_auto_selectable_formats = ARRAY_SIZE(rsnd_soc_dai_formats),
+};
+
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;
@@ -1374,10 +1403,16 @@ 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;
@@ -1441,21 +1476,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;
+ int nr = 0;
int is_graph;
int dai_i;
- dai_node = rsnd_dai_of_node(priv, &is_graph);
- if (is_graph)
- nr = of_graph_get_endpoint_count(dai_node);
- else
- nr = of_get_child_count(dai_node);
-
+ nr = rsnd_dai_of_node(priv, &is_graph);
if (!nr)
return -EINVAL;
@@ -1473,26 +1502,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++;
}
}
@@ -1922,6 +1967,7 @@ static int rsnd_probe(struct platform_device *pdev)
rsnd_dai_probe,
};
int ret, i;
+ int ci;
/*
* init priv data
@@ -1958,11 +2004,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);