ASoC: Intel: skl_hda_dsp_generic: support BT audio offload
authorBrent Lu <brent.lu@intel.com>
Tue, 27 Aug 2024 12:32:07 +0000 (20:32 +0800)
committerMark Brown <broonie@kernel.org>
Wed, 28 Aug 2024 12:01:58 +0000 (13:01 +0100)
Add BT offload BE link to dai link array if the BT offload link mask
is valid (only one bit set).

Signed-off-by: Brent Lu <brent.lu@intel.com>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Link: https://patch.msgid.link/20240827123215.258859-10-yung-chuan.liao@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/intel/boards/skl_hda_dsp_common.c
sound/soc/intel/boards/skl_hda_dsp_common.h
sound/soc/intel/boards/skl_hda_dsp_generic.c

index e9cefa4ae56dd7730b75d11a5a13a4deb0a2b055..5eb63f4df24103b221c18309765373b6fcda1e85 100644 (file)
@@ -75,6 +75,11 @@ SND_SOC_DAILINK_DEF(dmic_codec,
 SND_SOC_DAILINK_DEF(dmic16k,
        DAILINK_COMP_ARRAY(COMP_CPU("DMIC16k Pin")));
 
+SND_SOC_DAILINK_DEF(bt_offload_pin,
+       DAILINK_COMP_ARRAY(COMP_CPU(""))); /* initialized in driver probe function */
+SND_SOC_DAILINK_DEF(dummy,
+       DAILINK_COMP_ARRAY(COMP_DUMMY()));
+
 SND_SOC_DAILINK_DEF(platform,
        DAILINK_COMP_ARRAY(COMP_PLATFORM("0000:00:1f.3")));
 
@@ -132,6 +137,14 @@ struct snd_soc_dai_link skl_hda_be_dai_links[HDA_DSP_MAX_BE_DAI_LINKS] = {
                .no_pcm = 1,
                SND_SOC_DAILINK_REG(dmic16k, dmic_codec, platform),
        },
+       {
+               .name = NULL, /* initialized in driver probe function */
+               .id = 8,
+               .dpcm_playback = 1,
+               .dpcm_capture = 1,
+               .no_pcm = 1,
+               SND_SOC_DAILINK_REG(bt_offload_pin, dummy, platform),
+       },
 };
 
 int skl_hda_hdmi_jack_init(struct snd_soc_card *card)
index 19b814dee4ad6d5b1eac81b666b6cd7e0a271de5..9d714f747dcad4721a2cc3878cd1eaa200023780 100644 (file)
@@ -18,7 +18,7 @@
 #include "../../codecs/hdac_hda.h"
 #include "hda_dsp_common.h"
 
-#define HDA_DSP_MAX_BE_DAI_LINKS 7
+#define HDA_DSP_MAX_BE_DAI_LINKS 8
 
 struct skl_hda_hdmi_pcm {
        struct list_head head;
@@ -35,6 +35,8 @@ struct skl_hda_private {
        const char *platform_name;
        bool common_hdmi_codec_drv;
        bool idisp_codec;
+       bool bt_offload_present;
+       int ssp_bt;
 };
 
 extern struct snd_soc_dai_link skl_hda_be_dai_links[HDA_DSP_MAX_BE_DAI_LINKS];
index 88d91c0280bbb8b26633bcaf662984f35c1e2eba..927c73bef06514df3d9f8c30aa64cc2a074dc9e0 100644 (file)
@@ -95,6 +95,7 @@ skl_hda_add_dai_link(struct snd_soc_card *card, struct snd_soc_dai_link *link)
 #define IDISP_DAI_COUNT                3
 #define HDAC_DAI_COUNT         2
 #define DMIC_DAI_COUNT         2
+#define BT_DAI_COUNT           1
 
 /* there are two routes per iDisp output */
 #define IDISP_ROUTE_COUNT      (IDISP_DAI_COUNT * 2)
@@ -102,11 +103,12 @@ skl_hda_add_dai_link(struct snd_soc_card *card, struct snd_soc_dai_link *link)
 
 #define HDA_CODEC_AUTOSUSPEND_DELAY_MS 1000
 
-static int skl_hda_fill_card_info(struct snd_soc_card *card,
+static int skl_hda_fill_card_info(struct device *dev, struct snd_soc_card *card,
                                  struct snd_soc_acpi_mach_params *mach_params)
 {
        struct skl_hda_private *ctx = snd_soc_card_get_drvdata(card);
        struct snd_soc_dai_link *dai_link;
+       struct snd_soc_dai_link *bt_link;
        u32 codec_count, codec_mask;
        int i, num_links, num_route;
 
@@ -120,7 +122,7 @@ static int skl_hda_fill_card_info(struct snd_soc_card *card,
 
        if (codec_mask == IDISP_CODEC_MASK) {
                /* topology with iDisp as the only HDA codec */
-               num_links = IDISP_DAI_COUNT + DMIC_DAI_COUNT;
+               num_links = IDISP_DAI_COUNT + DMIC_DAI_COUNT + BT_DAI_COUNT;
                num_route = IDISP_ROUTE_COUNT;
 
                /*
@@ -129,7 +131,7 @@ static int skl_hda_fill_card_info(struct snd_soc_card *card,
                 * num_links of dai links need to be registered
                 * to ASoC.
                 */
-               for (i = 0; i < DMIC_DAI_COUNT; i++) {
+               for (i = 0; i < (DMIC_DAI_COUNT + BT_DAI_COUNT); i++) {
                        skl_hda_be_dai_links[IDISP_DAI_COUNT + i] =
                                skl_hda_be_dai_links[IDISP_DAI_COUNT +
                                        HDAC_DAI_COUNT + i];
@@ -150,6 +152,28 @@ static int skl_hda_fill_card_info(struct snd_soc_card *card,
                }
        }
 
+       if (!ctx->bt_offload_present) {
+               /* remove last link since bt audio offload is not supported */
+               num_links -= BT_DAI_COUNT;
+       } else {
+               if (codec_mask == IDISP_CODEC_MASK)
+                       bt_link = &skl_hda_be_dai_links[IDISP_DAI_COUNT + DMIC_DAI_COUNT];
+               else
+                       bt_link = &skl_hda_be_dai_links[IDISP_DAI_COUNT + HDAC_DAI_COUNT + DMIC_DAI_COUNT];
+
+               /* complete the link name and dai name with SSP port number */
+               bt_link->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-BT",
+                                              ctx->ssp_bt);
+               if (!bt_link->name)
+                       return -ENOMEM;
+
+               bt_link->cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
+                                                        "SSP%d Pin",
+                                                        ctx->ssp_bt);
+               if (!bt_link->cpus->dai_name)
+                       return -ENOMEM;
+       }
+
        card->num_links = num_links;
        card->num_dapm_routes = num_route;
 
@@ -213,7 +237,12 @@ static int skl_hda_audio_probe(struct platform_device *pdev)
 
        snd_soc_card_set_drvdata(card, ctx);
 
-       ret = skl_hda_fill_card_info(card, &mach->mach_params);
+       if (hweight_long(mach->mach_params.bt_link_mask) == 1) {
+               ctx->bt_offload_present = true;
+               ctx->ssp_bt = fls(mach->mach_params.bt_link_mask) - 1;
+       }
+
+       ret = skl_hda_fill_card_info(&pdev->dev, card, &mach->mach_params);
        if (ret < 0) {
                dev_err(&pdev->dev, "Unsupported HDAudio/iDisp configuration found\n");
                return ret;