ASoC: mediatek: common: soundcard driver add dai_fmt support
authorTrevor Wu <trevor.wu@mediatek.com>
Fri, 26 May 2023 09:31:47 +0000 (17:31 +0800)
committerMark Brown <broonie@kernel.org>
Fri, 2 Jun 2023 12:29:08 +0000 (13:29 +0100)
There are two changes included in the patch.

First, add set_dailink_daifmt() function, so dai_fmt can be updated by
the configuration in dai-link sub node.

Second, remove codec phandle from required property in dai-link sub node.
For example, user possibly needs to update dai-format for all etdm
co-clock dai-links, but codec doesn't need to be specified in capture
dai-link for a speaker amp.

Signed-off-by: Trevor Wu <trevor.wu@mediatek.com>
Reviewed-by: Alexandre Mergnat <amergnat@baylibre.com>
Link: https://lore.kernel.org/r/20230526093150.22923-5-trevor.wu@mediatek.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/mediatek/common/mtk-soundcard-driver.c

index 7380934..a58e1e3 100644 (file)
@@ -21,8 +21,10 @@ static int set_card_codec_info(struct snd_soc_card *card,
        int ret;
 
        codec_node = of_get_child_by_name(sub_node, "codec");
-       if (!codec_node)
-               return -EINVAL;
+       if (!codec_node) {
+               dev_dbg(dev, "%s no specified codec\n", dai_link->name);
+               return 0;
+       }
 
        /* set card codec info */
        ret = snd_soc_of_get_dai_link_codecs(dev, codec_node, dai_link);
@@ -36,6 +38,47 @@ static int set_card_codec_info(struct snd_soc_card *card,
        return 0;
 }
 
+static int set_dailink_daifmt(struct snd_soc_card *card,
+                             struct device_node *sub_node,
+                             struct snd_soc_dai_link *dai_link)
+{
+       unsigned int daifmt;
+       const char *str;
+       int ret;
+       struct {
+               char *name;
+               unsigned int val;
+       } of_clk_table[] = {
+               { "cpu",        SND_SOC_DAIFMT_CBC_CFC },
+               { "codec",      SND_SOC_DAIFMT_CBP_CFP },
+       };
+
+       daifmt = snd_soc_daifmt_parse_format(sub_node, NULL);
+       if (daifmt) {
+               dai_link->dai_fmt &= SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK;
+               dai_link->dai_fmt |= daifmt;
+       }
+
+       /*
+        * check "mediatek,clk-provider = xxx"
+        * SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK area
+        */
+       ret = of_property_read_string(sub_node, "mediatek,clk-provider", &str);
+       if (ret == 0) {
+               int i;
+
+               for (i = 0; i < ARRAY_SIZE(of_clk_table); i++) {
+                       if (strcmp(str, of_clk_table[i].name) == 0) {
+                               dai_link->dai_fmt &= ~SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK;
+                               dai_link->dai_fmt |= of_clk_table[i].val;
+                               break;
+                       }
+               }
+       }
+
+       return 0;
+}
+
 int parse_dai_link_info(struct snd_soc_card *card)
 {
        struct device *dev = card->dev;
@@ -67,6 +110,12 @@ int parse_dai_link_info(struct snd_soc_card *card)
                        of_node_put(sub_node);
                        return ret;
                }
+
+               ret = set_dailink_daifmt(card, sub_node, dai_link);
+               if (ret < 0) {
+                       of_node_put(sub_node);
+                       return ret;
+               }
        }
 
        return 0;