ASoC: Intel: board_helpers: support DAI link order customization
authorBrent Lu <brent.lu@intel.com>
Thu, 8 Feb 2024 16:55:28 +0000 (10:55 -0600)
committerMark Brown <broonie@kernel.org>
Thu, 8 Feb 2024 21:23:06 +0000 (21:23 +0000)
Add an new field link_order_overwrite to sof_card_private structure to
support machine drivers which DAI link order is different from the
order used in sof_rt5682 (i.e. GLK boards or no-codec boards).

Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Signed-off-by: Brent Lu <brent.lu@intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Link: https://lore.kernel.org/r/20240208165545.93811-8-pierre-louis.bossart@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/intel/boards/sof_board_helpers.c
sound/soc/intel/boards/sof_board_helpers.h

index 4f2cb8e529713a8b045446341c0dbc2eec5a3ea1..25f9ff12618c12e14a0454b04e5aee585c2f18f5 100644 (file)
@@ -73,6 +73,16 @@ static int dmic_init(struct snd_soc_pcm_runtime *rtd)
 /*
  * DAI Link Helpers
  */
+
+/* DEFAULT_LINK_ORDER: the order used in sof_rt5682 */
+#define DEFAULT_LINK_ORDER     SOF_LINK_ORDER(SOF_LINK_CODEC, \
+                                       SOF_LINK_DMIC01,       \
+                                       SOF_LINK_DMIC16K,      \
+                                       SOF_LINK_IDISP_HDMI,   \
+                                       SOF_LINK_AMP,          \
+                                       SOF_LINK_BT_OFFLOAD,   \
+                                       SOF_LINK_HDMI_IN)
+
 static struct snd_soc_dai_link_component dmic_component[] = {
        {
                .name = "dmic-codec",
@@ -416,6 +426,7 @@ int sof_intel_board_set_dai_link(struct device *dev, struct snd_soc_card *card,
        int idx = 0;
        int ret;
        int ssp_hdmi_in = 0;
+       unsigned long link_order, link;
 
        num_links = calculate_num_links(ctx);
 
@@ -424,94 +435,140 @@ int sof_intel_board_set_dai_link(struct device *dev, struct snd_soc_card *card,
        if (!links)
                return -ENOMEM;
 
-       /* headphone codec */
-       if (ctx->codec_type != CODEC_NONE) {
-               ret = sof_intel_board_set_codec_link(dev, &links[idx], idx,
-                                                    ctx->codec_type,
-                                                    ctx->ssp_codec);
-               if (ret) {
-                       dev_err(dev, "fail to set codec link, ret %d\n", ret);
-                       return ret;
-               }
-
-               ctx->codec_link = &links[idx];
-               idx++;
-       }
-
-       /* dmic01 and dmic16k */
-       if (ctx->dmic_be_num > 0) {
-               /* at least we have dmic01 */
-               ret = sof_intel_board_set_dmic_link(dev, &links[idx], idx,
-                                                   SOF_DMIC_01);
-               if (ret) {
-                       dev_err(dev, "fail to set dmic01 link, ret %d\n", ret);
-                       return ret;
-               }
-
-               idx++;
-       }
-
-       if (ctx->dmic_be_num > 1) {
-               /* set up 2 BE links at most */
-               ret = sof_intel_board_set_dmic_link(dev, &links[idx], idx,
-                                                   SOF_DMIC_16K);
-               if (ret) {
-                       dev_err(dev, "fail to set dmic16k link, ret %d\n", ret);
-                       return ret;
-               }
-
-               idx++;
-       }
-
-       /* idisp HDMI */
-       for (i = 1; i <= ctx->hdmi_num; i++) {
-               ret = sof_intel_board_set_intel_hdmi_link(dev, &links[idx], idx,
-                                                         i,
-                                                         ctx->hdmi.idisp_codec);
-               if (ret) {
-                       dev_err(dev, "fail to set hdmi link, ret %d\n", ret);
-                       return ret;
+       if (ctx->link_order_overwrite)
+               link_order = ctx->link_order_overwrite;
+       else
+               link_order = DEFAULT_LINK_ORDER;
+
+       dev_dbg(dev, "create dai links, link_order 0x%lx\n", link_order);
+
+       while (link_order) {
+               link = link_order & SOF_LINK_ORDER_MASK;
+               link_order >>= SOF_LINK_ORDER_SHIFT;
+
+               switch (link) {
+               case SOF_LINK_CODEC:
+                       /* headphone codec */
+                       if (ctx->codec_type == CODEC_NONE)
+                               continue;
+
+                       ret = sof_intel_board_set_codec_link(dev, &links[idx],
+                                                            idx,
+                                                            ctx->codec_type,
+                                                            ctx->ssp_codec);
+                       if (ret) {
+                               dev_err(dev, "fail to set codec link, ret %d\n",
+                                       ret);
+                               return ret;
+                       }
+
+                       ctx->codec_link = &links[idx];
+                       idx++;
+                       break;
+               case SOF_LINK_DMIC01:
+                       /* dmic01 */
+                       if (ctx->dmic_be_num == 0)
+                               continue;
+
+                       /* at least we have dmic01 */
+                       ret = sof_intel_board_set_dmic_link(dev, &links[idx],
+                                                           idx, SOF_DMIC_01);
+                       if (ret) {
+                               dev_err(dev, "fail to set dmic01 link, ret %d\n",
+                                       ret);
+                               return ret;
+                       }
+
+                       idx++;
+                       break;
+               case SOF_LINK_DMIC16K:
+                       /* dmic16k */
+                       if (ctx->dmic_be_num <= 1)
+                               continue;
+
+                       /* set up 2 BE links at most */
+                       ret = sof_intel_board_set_dmic_link(dev, &links[idx],
+                                                           idx, SOF_DMIC_16K);
+                       if (ret) {
+                               dev_err(dev, "fail to set dmic16k link, ret %d\n",
+                                       ret);
+                               return ret;
+                       }
+
+                       idx++;
+                       break;
+               case SOF_LINK_IDISP_HDMI:
+                       /* idisp HDMI */
+                       for (i = 1; i <= ctx->hdmi_num; i++) {
+                               ret = sof_intel_board_set_intel_hdmi_link(dev,
+                                                                         &links[idx],
+                                                                         idx, i,
+                                                                         ctx->hdmi.idisp_codec);
+                               if (ret) {
+                                       dev_err(dev, "fail to set hdmi link, ret %d\n",
+                                               ret);
+                                       return ret;
+                               }
+
+                               idx++;
+                       }
+                       break;
+               case SOF_LINK_AMP:
+                       /* speaker amp */
+                       if (ctx->amp_type == CODEC_NONE)
+                               continue;
+
+                       ret = sof_intel_board_set_ssp_amp_link(dev, &links[idx],
+                                                              idx,
+                                                              ctx->amp_type,
+                                                              ctx->ssp_amp);
+                       if (ret) {
+                               dev_err(dev, "fail to set amp link, ret %d\n",
+                                       ret);
+                               return ret;
+                       }
+
+                       ctx->amp_link = &links[idx];
+                       idx++;
+                       break;
+               case SOF_LINK_BT_OFFLOAD:
+                       /* BT audio offload */
+                       if (!ctx->bt_offload_present)
+                               continue;
+
+                       ret = sof_intel_board_set_bt_link(dev, &links[idx], idx,
+                                                         ctx->ssp_bt);
+                       if (ret) {
+                               dev_err(dev, "fail to set bt link, ret %d\n",
+                                       ret);
+                               return ret;
+                       }
+
+                       idx++;
+                       break;
+               case SOF_LINK_HDMI_IN:
+                       /* HDMI-In */
+                       for_each_set_bit(ssp_hdmi_in, &ctx->ssp_mask_hdmi_in, 32) {
+                               ret = sof_intel_board_set_hdmi_in_link(dev,
+                                                                      &links[idx],
+                                                                      idx,
+                                                                      ssp_hdmi_in);
+                               if (ret) {
+                                       dev_err(dev, "fail to set hdmi-in link, ret %d\n",
+                                               ret);
+                                       return ret;
+                               }
+
+                               idx++;
+                       }
+                       break;
+               case SOF_LINK_NONE:
+                       /* caught here if it's not used as terminator in macro */
+                       fallthrough;
+               default:
+                       dev_err(dev, "invalid link type %ld\n", link);
+                       return -EINVAL;
                }
-
-               idx++;
-       }
-
-       /* speaker amp */
-       if (ctx->amp_type != CODEC_NONE) {
-               ret = sof_intel_board_set_ssp_amp_link(dev, &links[idx], idx,
-                                                      ctx->amp_type,
-                                                      ctx->ssp_amp);
-               if (ret) {
-                       dev_err(dev, "fail to set amp link, ret %d\n", ret);
-                       return ret;
-               }
-
-               ctx->amp_link = &links[idx];
-               idx++;
-       }
-
-       /* BT audio offload */
-       if (ctx->bt_offload_present) {
-               ret = sof_intel_board_set_bt_link(dev, &links[idx], idx,
-                                                 ctx->ssp_bt);
-               if (ret) {
-                       dev_err(dev, "fail to set bt link, ret %d\n", ret);
-                       return ret;
-               }
-
-               idx++;
-       }
-
-       /* HDMI-In */
-       for_each_set_bit(ssp_hdmi_in, &ctx->ssp_mask_hdmi_in, 32) {
-               ret = sof_intel_board_set_hdmi_in_link(dev, &links[idx], idx,
-                                                      ssp_hdmi_in);
-               if (ret) {
-                       dev_err(dev, "fail to set hdmi-in link, ret %d\n", ret);
-                       return ret;
-               }
-
-               idx++;
        }
 
        if (idx != num_links) {
index 3b36058118ca595a53aa13165f455867e92271b1..c5d6e7bec5d4cf7de57fe7d756999c65f1b80a49 100644 (file)
 #include "sof_hdmi_common.h"
 #include "sof_ssp_common.h"
 
+enum {
+       SOF_LINK_NONE = 0,
+       SOF_LINK_CODEC,
+       SOF_LINK_DMIC01,
+       SOF_LINK_DMIC16K,
+       SOF_LINK_IDISP_HDMI,
+       SOF_LINK_AMP,
+       SOF_LINK_BT_OFFLOAD,
+       SOF_LINK_HDMI_IN,
+};
+
+#define SOF_LINK_ORDER_MASK    (0xF)
+#define SOF_LINK_ORDER_SHIFT   (4)
+
+#define SOF_LINK_ORDER(k1, k2, k3, k4, k5, k6, k7) \
+       ((((k1) & SOF_LINK_ORDER_MASK) << (SOF_LINK_ORDER_SHIFT * 0)) | \
+        (((k2) & SOF_LINK_ORDER_MASK) << (SOF_LINK_ORDER_SHIFT * 1)) | \
+        (((k3) & SOF_LINK_ORDER_MASK) << (SOF_LINK_ORDER_SHIFT * 2)) | \
+        (((k4) & SOF_LINK_ORDER_MASK) << (SOF_LINK_ORDER_SHIFT * 3)) | \
+        (((k5) & SOF_LINK_ORDER_MASK) << (SOF_LINK_ORDER_SHIFT * 4)) | \
+        (((k6) & SOF_LINK_ORDER_MASK) << (SOF_LINK_ORDER_SHIFT * 5)) | \
+        (((k7) & SOF_LINK_ORDER_MASK) << (SOF_LINK_ORDER_SHIFT * 6)))
+
 /*
  * sof_rt5682_private: private data for rt5682 machine driver
  *
@@ -37,6 +60,7 @@ struct sof_rt5682_private {
  * @bt_offload_present: true to create BT offload BE link
  * @codec_link: pointer to headset codec dai link
  * @amp_link: pointer to speaker amplifier dai link
+ * @link_order_overwrite: custom DAI link order
  * @rt5682: private data for rt5682 machine driver
  */
 struct sof_card_private {
@@ -59,6 +83,8 @@ struct sof_card_private {
        struct snd_soc_dai_link *codec_link;
        struct snd_soc_dai_link *amp_link;
 
+       unsigned long link_order_overwrite;
+
        union {
                struct sof_rt5682_private rt5682;
        };