Merge remote-tracking branches 'asoc/topic/cs42l73', 'asoc/topic/dai' and 'asoc/topic...
[cascardo/linux.git] / sound / soc / soc-core.c
index c2f800b..c29b6ca 100644 (file)
@@ -1437,11 +1437,76 @@ static int snd_soc_init_codec_cache(struct snd_soc_codec *codec)
        return 0;
 }
 
+/**
+ * snd_soc_runtime_set_dai_fmt() - Change DAI link format for a ASoC runtime
+ * @rtd: The runtime for which the DAI link format should be changed
+ * @dai_fmt: The new DAI link format
+ *
+ * This function updates the DAI link format for all DAIs connected to the DAI
+ * link for the specified runtime.
+ *
+ * Note: For setups with a static format set the dai_fmt field in the
+ * corresponding snd_dai_link struct instead of using this function.
+ *
+ * Returns 0 on success, otherwise a negative error code.
+ */
+int snd_soc_runtime_set_dai_fmt(struct snd_soc_pcm_runtime *rtd,
+       unsigned int dai_fmt)
+{
+       struct snd_soc_dai **codec_dais = rtd->codec_dais;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+       unsigned int i;
+       int ret;
+
+       for (i = 0; i < rtd->num_codecs; i++) {
+               struct snd_soc_dai *codec_dai = codec_dais[i];
+
+               ret = snd_soc_dai_set_fmt(codec_dai, dai_fmt);
+               if (ret != 0 && ret != -ENOTSUPP) {
+                       dev_warn(codec_dai->dev,
+                                "ASoC: Failed to set DAI format: %d\n", ret);
+                       return ret;
+               }
+       }
+
+       /* Flip the polarity for the "CPU" end of a CODEC<->CODEC link */
+       if (cpu_dai->codec) {
+               unsigned int inv_dai_fmt;
+
+               inv_dai_fmt = dai_fmt & ~SND_SOC_DAIFMT_MASTER_MASK;
+               switch (dai_fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+               case SND_SOC_DAIFMT_CBM_CFM:
+                       inv_dai_fmt |= SND_SOC_DAIFMT_CBS_CFS;
+                       break;
+               case SND_SOC_DAIFMT_CBM_CFS:
+                       inv_dai_fmt |= SND_SOC_DAIFMT_CBS_CFM;
+                       break;
+               case SND_SOC_DAIFMT_CBS_CFM:
+                       inv_dai_fmt |= SND_SOC_DAIFMT_CBM_CFS;
+                       break;
+               case SND_SOC_DAIFMT_CBS_CFS:
+                       inv_dai_fmt |= SND_SOC_DAIFMT_CBM_CFM;
+                       break;
+               }
+
+               dai_fmt = inv_dai_fmt;
+       }
+
+       ret = snd_soc_dai_set_fmt(cpu_dai, dai_fmt);
+       if (ret != 0 && ret != -ENOTSUPP) {
+               dev_warn(cpu_dai->dev,
+                        "ASoC: Failed to set DAI format: %d\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_runtime_set_dai_fmt);
+
 static int snd_soc_instantiate_card(struct snd_soc_card *card)
 {
        struct snd_soc_codec *codec;
-       struct snd_soc_dai_link *dai_link;
-       int ret, i, order, dai_fmt;
+       int ret, i, order;
 
        mutex_lock_nested(&card->mutex, SND_SOC_CARD_CLASS_INIT);
 
@@ -1552,60 +1617,9 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
                                        card->num_dapm_routes);
 
        for (i = 0; i < card->num_links; i++) {
-               struct snd_soc_pcm_runtime *rtd = &card->rtd[i];
-               dai_link = &card->dai_link[i];
-               dai_fmt = dai_link->dai_fmt;
-
-               if (dai_fmt) {
-                       struct snd_soc_dai **codec_dais = rtd->codec_dais;
-                       int j;
-
-                       for (j = 0; j < rtd->num_codecs; j++) {
-                               struct snd_soc_dai *codec_dai = codec_dais[j];
-
-                               ret = snd_soc_dai_set_fmt(codec_dai, dai_fmt);
-                               if (ret != 0 && ret != -ENOTSUPP)
-                                       dev_warn(codec_dai->dev,
-                                                "ASoC: Failed to set DAI format: %d\n",
-                                                ret);
-                       }
-               }
-
-               /* If this is a regular CPU link there will be a platform */
-               if (dai_fmt &&
-                   (dai_link->platform_name || dai_link->platform_of_node)) {
-                       ret = snd_soc_dai_set_fmt(card->rtd[i].cpu_dai,
-                                                 dai_fmt);
-                       if (ret != 0 && ret != -ENOTSUPP)
-                               dev_warn(card->rtd[i].cpu_dai->dev,
-                                        "ASoC: Failed to set DAI format: %d\n",
-                                        ret);
-               } else if (dai_fmt) {
-                       /* Flip the polarity for the "CPU" end */
-                       dai_fmt &= ~SND_SOC_DAIFMT_MASTER_MASK;
-                       switch (dai_link->dai_fmt &
-                               SND_SOC_DAIFMT_MASTER_MASK) {
-                       case SND_SOC_DAIFMT_CBM_CFM:
-                               dai_fmt |= SND_SOC_DAIFMT_CBS_CFS;
-                               break;
-                       case SND_SOC_DAIFMT_CBM_CFS:
-                               dai_fmt |= SND_SOC_DAIFMT_CBS_CFM;
-                               break;
-                       case SND_SOC_DAIFMT_CBS_CFM:
-                               dai_fmt |= SND_SOC_DAIFMT_CBM_CFS;
-                               break;
-                       case SND_SOC_DAIFMT_CBS_CFS:
-                               dai_fmt |= SND_SOC_DAIFMT_CBM_CFM;
-                               break;
-                       }
-
-                       ret = snd_soc_dai_set_fmt(card->rtd[i].cpu_dai,
-                                                 dai_fmt);
-                       if (ret != 0 && ret != -ENOTSUPP)
-                               dev_warn(card->rtd[i].cpu_dai->dev,
-                                        "ASoC: Failed to set DAI format: %d\n",
-                                        ret);
-               }
+               if (card->dai_link[i].dai_fmt)
+                       snd_soc_runtime_set_dai_fmt(&card->rtd[i],
+                               card->dai_link[i].dai_fmt);
        }
 
        snprintf(card->snd_card->shortname, sizeof(card->snd_card->shortname),