summaryrefslogtreecommitdiff
path: root/sound/soc/generic/simple-card-utils.c
diff options
context:
space:
mode:
authorKuninori Morimoto <kuninori.morimoto.gx@renesas.com>2023-06-14 00:02:57 +0000
committerMark Brown <broonie@kernel.org>2023-06-14 14:47:53 +0100
commitfed4be313a55e9a19fdabe99d1ec373e25889e2c (patch)
treec57add7785ce9375c2f51c4d5eca366d70f706d6 /sound/soc/generic/simple-card-utils.c
parentfd01a15164a15328fd96f9ce820f0fc9f700f00b (diff)
ASoC: simple-card-utils.c: share asoc_graph_parse_dai()
Current Audio Graph Card/Card2 implements asoc_simple_parse_dai() on each driver, but these are same function. This patch share it as asoc_graph_parse_dai(). Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Link: https://lore.kernel.org/r/87o7lihpvy.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound/soc/generic/simple-card-utils.c')
-rw-r--r--sound/soc/generic/simple-card-utils.c105
1 files changed, 105 insertions, 0 deletions
diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c
index b5ac0f0d5e8e..6a3c9e4e1cfe 100644
--- a/sound/soc/generic/simple-card-utils.c
+++ b/sound/soc/generic/simple-card-utils.c
@@ -1019,6 +1019,111 @@ int asoc_graph_is_ports0(struct device_node *np)
}
EXPORT_SYMBOL_GPL(asoc_graph_is_ports0);
+static int graph_get_dai_id(struct device_node *ep)
+{
+ struct device_node *node;
+ struct device_node *endpoint;
+ struct of_endpoint info;
+ int i, id;
+ int ret;
+
+ /* use driver specified DAI ID if exist */
+ ret = snd_soc_get_dai_id(ep);
+ if (ret != -ENOTSUPP)
+ return ret;
+
+ /* use endpoint/port reg if exist */
+ ret = of_graph_parse_endpoint(ep, &info);
+ if (ret == 0) {
+ /*
+ * Because it will count port/endpoint if it doesn't have "reg".
+ * But, we can't judge whether it has "no reg", or "reg = <0>"
+ * only of_graph_parse_endpoint().
+ * We need to check "reg" property
+ */
+ if (of_property_present(ep, "reg"))
+ return info.id;
+
+ node = of_get_parent(ep);
+ ret = of_property_present(node, "reg");
+ of_node_put(node);
+ if (ret)
+ return info.port;
+ }
+ node = of_graph_get_port_parent(ep);
+
+ /*
+ * Non HDMI sound case, counting port/endpoint on its DT
+ * is enough. Let's count it.
+ */
+ i = 0;
+ id = -1;
+ for_each_endpoint_of_node(node, endpoint) {
+ if (endpoint == ep)
+ id = i;
+ i++;
+ }
+
+ of_node_put(node);
+
+ if (id < 0)
+ return -ENODEV;
+
+ return id;
+}
+
+int asoc_graph_parse_dai(struct device_node *ep,
+ struct snd_soc_dai_link_component *dlc,
+ int *is_single_link)
+{
+ struct device_node *node;
+ struct of_phandle_args args = {};
+ int ret;
+
+ if (!ep)
+ return 0;
+
+ node = of_graph_get_port_parent(ep);
+
+ /* Get dai->name */
+ args.np = node;
+ args.args[0] = graph_get_dai_id(ep);
+ args.args_count = (of_graph_get_endpoint_count(node) > 1);
+
+ /*
+ * FIXME
+ *
+ * Here, dlc->dai_name is pointer to CPU/Codec DAI name.
+ * If user unbinded CPU or Codec driver, but not for Sound Card,
+ * dlc->dai_name is keeping unbinded CPU or Codec
+ * driver's pointer.
+ *
+ * If user re-bind CPU or Codec driver again, ALSA SoC will try
+ * to rebind Card via snd_soc_try_rebind_card(), but because of
+ * above reason, it might can't bind Sound Card.
+ * Because Sound Card is pointing to released dai_name pointer.
+ *
+ * To avoid this rebind Card issue,
+ * 1) It needs to alloc memory to keep dai_name eventhough
+ * CPU or Codec driver was unbinded, or
+ * 2) user need to rebind Sound Card everytime
+ * if he unbinded CPU or Codec.
+ */
+ ret = snd_soc_get_dai_name(&args, &dlc->dai_name);
+ if (ret < 0) {
+ of_node_put(node);
+ return ret;
+ }
+
+ dlc->of_node = node;
+
+ if (is_single_link)
+ *is_single_link = of_graph_get_endpoint_count(node) == 1;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(asoc_graph_parse_dai);
+
/* Module information */
MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
MODULE_DESCRIPTION("ALSA SoC Simple Card Utils");