12fbeff33SBard Liao // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
22fbeff33SBard Liao //
32fbeff33SBard Liao // This file is provided under a dual BSD/GPLv2 license. When using or
42fbeff33SBard Liao // redistributing this file, you may do so under either license.
52fbeff33SBard Liao //
62fbeff33SBard Liao // Copyright(c) 2025 Intel Corporation.
72fbeff33SBard Liao //
82fbeff33SBard Liao
92fbeff33SBard Liao #include <linux/device.h>
102fbeff33SBard Liao #include <linux/errno.h>
112fbeff33SBard Liao #include <linux/firmware.h>
122fbeff33SBard Liao #include <sound/soc.h>
132fbeff33SBard Liao #include <sound/soc-acpi.h>
142fbeff33SBard Liao #include "sof-function-topology-lib.h"
152fbeff33SBard Liao
162fbeff33SBard Liao enum tplg_device_id {
172fbeff33SBard Liao TPLG_DEVICE_SDCA_JACK,
182fbeff33SBard Liao TPLG_DEVICE_SDCA_AMP,
192fbeff33SBard Liao TPLG_DEVICE_SDCA_MIC,
202fbeff33SBard Liao TPLG_DEVICE_INTEL_PCH_DMIC,
212fbeff33SBard Liao TPLG_DEVICE_HDMI,
222fbeff33SBard Liao TPLG_DEVICE_MAX
232fbeff33SBard Liao };
242fbeff33SBard Liao
252fbeff33SBard Liao #define SDCA_DEVICE_MASK (BIT(TPLG_DEVICE_SDCA_JACK) | BIT(TPLG_DEVICE_SDCA_AMP) | \
262fbeff33SBard Liao BIT(TPLG_DEVICE_SDCA_MIC))
272fbeff33SBard Liao
282fbeff33SBard Liao #define SOF_INTEL_PLATFORM_NAME_MAX 4
292fbeff33SBard Liao
sof_sdw_get_tplg_files(struct snd_soc_card * card,const struct snd_soc_acpi_mach * mach,const char * prefix,const char *** tplg_files)302fbeff33SBard Liao int sof_sdw_get_tplg_files(struct snd_soc_card *card, const struct snd_soc_acpi_mach *mach,
312fbeff33SBard Liao const char *prefix, const char ***tplg_files)
322fbeff33SBard Liao {
332fbeff33SBard Liao struct snd_soc_acpi_mach_params mach_params = mach->mach_params;
342fbeff33SBard Liao struct snd_soc_dai_link *dai_link;
352fbeff33SBard Liao const struct firmware *fw;
362fbeff33SBard Liao char platform[SOF_INTEL_PLATFORM_NAME_MAX];
372fbeff33SBard Liao unsigned long tplg_mask = 0;
382fbeff33SBard Liao int tplg_num = 0;
392fbeff33SBard Liao int tplg_dev;
402fbeff33SBard Liao int ret;
412fbeff33SBard Liao int i;
422fbeff33SBard Liao
432fbeff33SBard Liao ret = sscanf(mach->sof_tplg_filename, "sof-%3s-*.tplg", platform);
442fbeff33SBard Liao if (ret != 1) {
452fbeff33SBard Liao dev_err(card->dev, "Invalid platform name %s of tplg %s\n",
462fbeff33SBard Liao platform, mach->sof_tplg_filename);
472fbeff33SBard Liao return -EINVAL;
482fbeff33SBard Liao }
492fbeff33SBard Liao
502fbeff33SBard Liao for_each_card_prelinks(card, i, dai_link) {
512fbeff33SBard Liao char *tplg_dev_name;
522fbeff33SBard Liao
532fbeff33SBard Liao dev_dbg(card->dev, "dai_link %s id %d\n", dai_link->name, dai_link->id);
542fbeff33SBard Liao if (strstr(dai_link->name, "SimpleJack")) {
552fbeff33SBard Liao tplg_dev = TPLG_DEVICE_SDCA_JACK;
562fbeff33SBard Liao tplg_dev_name = "sdca-jack";
572fbeff33SBard Liao } else if (strstr(dai_link->name, "SmartAmp")) {
582fbeff33SBard Liao tplg_dev = TPLG_DEVICE_SDCA_AMP;
592fbeff33SBard Liao tplg_dev_name = devm_kasprintf(card->dev, GFP_KERNEL,
602fbeff33SBard Liao "sdca-%damp", dai_link->num_cpus);
612fbeff33SBard Liao if (!tplg_dev_name)
622fbeff33SBard Liao return -ENOMEM;
632fbeff33SBard Liao } else if (strstr(dai_link->name, "SmartMic")) {
642fbeff33SBard Liao tplg_dev = TPLG_DEVICE_SDCA_MIC;
652fbeff33SBard Liao tplg_dev_name = "sdca-mic";
662fbeff33SBard Liao } else if (strstr(dai_link->name, "dmic")) {
672fbeff33SBard Liao switch (mach_params.dmic_num) {
682fbeff33SBard Liao case 2:
692fbeff33SBard Liao tplg_dev_name = "dmic-2ch";
702fbeff33SBard Liao break;
712fbeff33SBard Liao case 4:
722fbeff33SBard Liao tplg_dev_name = "dmic-4ch";
732fbeff33SBard Liao break;
742fbeff33SBard Liao default:
752fbeff33SBard Liao dev_warn(card->dev,
76*16ea4666SPeter Ujfalusi "unsupported number of dmics: %d\n",
77*16ea4666SPeter Ujfalusi mach_params.dmic_num);
782fbeff33SBard Liao continue;
792fbeff33SBard Liao }
802fbeff33SBard Liao tplg_dev = TPLG_DEVICE_INTEL_PCH_DMIC;
812fbeff33SBard Liao } else if (strstr(dai_link->name, "iDisp")) {
822fbeff33SBard Liao tplg_dev = TPLG_DEVICE_HDMI;
832fbeff33SBard Liao tplg_dev_name = "hdmi-pcm5";
842fbeff33SBard Liao
852fbeff33SBard Liao } else {
862fbeff33SBard Liao /* The dai link is not supported by separated tplg yet */
872fbeff33SBard Liao dev_dbg(card->dev,
882fbeff33SBard Liao "dai_link %s is not supported by separated tplg yet\n",
892fbeff33SBard Liao dai_link->name);
902fbeff33SBard Liao return 0;
912fbeff33SBard Liao }
922fbeff33SBard Liao if (tplg_mask & BIT(tplg_dev))
932fbeff33SBard Liao continue;
942fbeff33SBard Liao
952fbeff33SBard Liao tplg_mask |= BIT(tplg_dev);
962fbeff33SBard Liao
972fbeff33SBard Liao /*
982fbeff33SBard Liao * The tplg file naming rule is sof-<platform>-<function>-id<BE id number>.tplg
992fbeff33SBard Liao * where <platform> is only required for the DMIC function as the nhlt blob
1002fbeff33SBard Liao * is platform dependent.
1012fbeff33SBard Liao */
1022fbeff33SBard Liao switch (tplg_dev) {
1032fbeff33SBard Liao case TPLG_DEVICE_INTEL_PCH_DMIC:
1042fbeff33SBard Liao (*tplg_files)[tplg_num] = devm_kasprintf(card->dev, GFP_KERNEL,
1052fbeff33SBard Liao "%s/sof-%s-%s-id%d.tplg",
1062fbeff33SBard Liao prefix, platform,
1072fbeff33SBard Liao tplg_dev_name, dai_link->id);
1082fbeff33SBard Liao break;
1092fbeff33SBard Liao default:
1102fbeff33SBard Liao (*tplg_files)[tplg_num] = devm_kasprintf(card->dev, GFP_KERNEL,
1112fbeff33SBard Liao "%s/sof-%s-id%d.tplg",
1122fbeff33SBard Liao prefix, tplg_dev_name,
1132fbeff33SBard Liao dai_link->id);
1142fbeff33SBard Liao break;
1152fbeff33SBard Liao }
1162fbeff33SBard Liao if (!(*tplg_files)[tplg_num])
1172fbeff33SBard Liao return -ENOMEM;
1182fbeff33SBard Liao tplg_num++;
1192fbeff33SBard Liao }
1202fbeff33SBard Liao
1212fbeff33SBard Liao dev_dbg(card->dev, "tplg_mask %#lx tplg_num %d\n", tplg_mask, tplg_num);
1222fbeff33SBard Liao
1232fbeff33SBard Liao /* Check presence of sub-topologies */
1242fbeff33SBard Liao for (i = 0; i < tplg_num; i++) {
1252fbeff33SBard Liao ret = firmware_request_nowarn(&fw, (*tplg_files)[i], card->dev);
1262fbeff33SBard Liao if (!ret) {
1272fbeff33SBard Liao release_firmware(fw);
1282fbeff33SBard Liao } else {
1292fbeff33SBard Liao dev_dbg(card->dev, "Failed to open topology file: %s\n", (*tplg_files)[i]);
1302fbeff33SBard Liao return 0;
1312fbeff33SBard Liao }
1322fbeff33SBard Liao }
1332fbeff33SBard Liao
1342fbeff33SBard Liao return tplg_num;
1352fbeff33SBard Liao }
1362fbeff33SBard Liao
137