Merge remote-tracking branch 'sound-asoc/for-next'
[deliverable/linux.git] / sound / soc / generic / simple-card-utils.c
index 9599de69a880eb2a59ecb3fe142eb84a7ddacbcc..1cb39309f5d5b25151d37481c776758754783a63 100644 (file)
@@ -7,6 +7,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <linux/clk.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <sound/simple_card_utils.h>
@@ -97,6 +98,146 @@ int asoc_simple_card_parse_card_name(struct snd_soc_card *card,
 }
 EXPORT_SYMBOL_GPL(asoc_simple_card_parse_card_name);
 
+int asoc_simple_card_parse_clk(struct device_node *node,
+                              struct device_node *dai_of_node,
+                              struct asoc_simple_dai *simple_dai)
+{
+       struct clk *clk;
+       u32 val;
+
+       /*
+        * Parse dai->sysclk come from "clocks = <&xxx>"
+        * (if system has common clock)
+        *  or "system-clock-frequency = <xxx>"
+        *  or device's module clock.
+        */
+       clk = of_clk_get(node, 0);
+       if (!IS_ERR(clk)) {
+               simple_dai->sysclk = clk_get_rate(clk);
+               simple_dai->clk = clk;
+       } else if (!of_property_read_u32(node, "system-clock-frequency", &val)) {
+               simple_dai->sysclk = val;
+       } else {
+               clk = of_clk_get(dai_of_node, 0);
+               if (!IS_ERR(clk))
+                       simple_dai->sysclk = clk_get_rate(clk);
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(asoc_simple_card_parse_clk);
+
+int asoc_simple_card_parse_dai(struct device_node *node,
+                                   struct device_node **dai_of_node,
+                                   const char **dai_name,
+                                   const char *list_name,
+                                   const char *cells_name,
+                                   int *is_single_link)
+{
+       struct of_phandle_args args;
+       int ret;
+
+       if (!node)
+               return 0;
+
+       /*
+        * Get node via "sound-dai = <&phandle port>"
+        * it will be used as xxx_of_node on soc_bind_dai_link()
+        */
+       ret = of_parse_phandle_with_args(node, list_name, cells_name, 0, &args);
+       if (ret)
+               return ret;
+
+       /* Get dai->name */
+       if (dai_name) {
+               ret = snd_soc_of_get_dai_name(node, dai_name);
+               if (ret < 0)
+                       return ret;
+       }
+
+       *dai_of_node = args.np;
+
+       if (is_single_link)
+               *is_single_link = !args.args_count;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(asoc_simple_card_parse_dai);
+
+int asoc_simple_card_init_dai(struct snd_soc_dai *dai,
+                             struct asoc_simple_dai *simple_dai)
+{
+       int ret;
+
+       if (simple_dai->sysclk) {
+               ret = snd_soc_dai_set_sysclk(dai, 0, simple_dai->sysclk, 0);
+               if (ret && ret != -ENOTSUPP) {
+                       dev_err(dai->dev, "simple-card: set_sysclk error\n");
+                       return ret;
+               }
+       }
+
+       if (simple_dai->slots) {
+               ret = snd_soc_dai_set_tdm_slot(dai,
+                                              simple_dai->tx_slot_mask,
+                                              simple_dai->rx_slot_mask,
+                                              simple_dai->slots,
+                                              simple_dai->slot_width);
+               if (ret && ret != -ENOTSUPP) {
+                       dev_err(dai->dev, "simple-card: set_tdm_slot error\n");
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(asoc_simple_card_init_dai);
+
+int asoc_simple_card_canonicalize_dailink(struct snd_soc_dai_link *dai_link)
+{
+       if (!dai_link->cpu_dai_name || !dai_link->codec_dai_name)
+               return -EINVAL;
+
+       /* Assumes platform == cpu */
+       if (!dai_link->platform_of_node)
+               dai_link->platform_of_node = dai_link->cpu_of_node;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(asoc_simple_card_canonicalize_dailink);
+
+void asoc_simple_card_canonicalize_cpu(struct snd_soc_dai_link *dai_link,
+                                      int is_single_links)
+{
+       /*
+        * In soc_bind_dai_link() will check cpu name after
+        * of_node matching if dai_link has cpu_dai_name.
+        * but, it will never match if name was created by
+        * fmt_single_name() remove cpu_dai_name if cpu_args
+        * was 0. See:
+        *      fmt_single_name()
+        *      fmt_multiple_name()
+        */
+       if (is_single_links)
+               dai_link->cpu_dai_name = NULL;
+}
+EXPORT_SYMBOL_GPL(asoc_simple_card_canonicalize_cpu);
+
+int asoc_simple_card_clean_reference(struct snd_soc_card *card)
+{
+       struct snd_soc_dai_link *dai_link;
+       int num_links;
+
+       for (num_links = 0, dai_link = card->dai_link;
+            num_links < card->num_links;
+            num_links++, dai_link++) {
+               of_node_put(dai_link->cpu_of_node);
+               of_node_put(dai_link->codec_of_node);
+       }
+       return 0;
+}
+EXPORT_SYMBOL_GPL(asoc_simple_card_clean_reference);
+
 /* Module information */
 MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
 MODULE_DESCRIPTION("ALSA SoC Simple Card Utils");
This page took 0.035529 seconds and 5 git commands to generate.