summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2025-10-15 18:22:44 +0300
committerMark Brown <broonie@kernel.org>2025-10-15 18:22:44 +0300
commitcee2c8396d9c8e834fe28929bc1d8153d7e9897f (patch)
treeedf72b6a4adfdc350caf669a367c1c14d493a5c5
parent0b0eb7702a9fa410755e86124b4b7cd36e7d1cb4 (diff)
parent9797329220a2c6622411eb9ecf6a35b24ce09d04 (diff)
downloadlinux-cee2c8396d9c8e834fe28929bc1d8153d7e9897f.tar.xz
ASoC: use sof_sdw as default Intel SOF SDW machine
Merge series from Bard Liao <yung-chuan.liao@linux.intel.com>: Currently, we create a ACPI mach table for every new audio configuration. And all Intel SOF SoundWire configurations point to the same sof_sdw machine driver. Also, we don't need a specific topology for a coufguration, we can use the function topology instead. That give us a change to generate an ACPI mach table based on the SoundWire codec information reported by the ACPI table and use the sof_sdw machine driver as the default machine driver. This will reduce the effort to support a new Intel SOF SoundWire audio configuration.
-rw-r--r--include/sound/soc-acpi.h8
-rw-r--r--include/sound/soc_sdw_utils.h2
-rw-r--r--sound/soc/intel/common/sof-function-topology-lib.c8
-rw-r--r--sound/soc/sdw_utils/soc_sdw_utils.c30
-rw-r--r--sound/soc/sof/fw-file-profile.c12
-rw-r--r--sound/soc/sof/intel/apl.c1
-rw-r--r--sound/soc/sof/intel/cnl.c2
-rw-r--r--sound/soc/sof/intel/hda.c205
-rw-r--r--sound/soc/sof/intel/icl.c1
-rw-r--r--sound/soc/sof/intel/lnl.c1
-rw-r--r--sound/soc/sof/intel/mtl.c2
-rw-r--r--sound/soc/sof/intel/ptl.c2
-rw-r--r--sound/soc/sof/intel/shim.h1
-rw-r--r--sound/soc/sof/intel/skl.c1
-rw-r--r--sound/soc/sof/intel/tgl.c4
-rw-r--r--sound/soc/sof/topology.c7
16 files changed, 276 insertions, 11 deletions
diff --git a/include/sound/soc-acpi.h b/include/sound/soc-acpi.h
index b8af309c2683..90d73b9bddab 100644
--- a/include/sound/soc-acpi.h
+++ b/include/sound/soc-acpi.h
@@ -114,8 +114,8 @@ struct snd_soc_acpi_endpoint {
* @name_prefix: string used for codec controls
*/
struct snd_soc_acpi_adr_device {
- const u64 adr;
- const u8 num_endpoints;
+ u64 adr;
+ u8 num_endpoints;
const struct snd_soc_acpi_endpoint *endpoints;
const char *name_prefix;
};
@@ -131,8 +131,8 @@ struct snd_soc_acpi_adr_device {
*/
struct snd_soc_acpi_link_adr {
- const u32 mask;
- const u32 num_adr;
+ u32 mask;
+ u32 num_adr;
const struct snd_soc_acpi_adr_device *adr_d;
};
diff --git a/include/sound/soc_sdw_utils.h b/include/sound/soc_sdw_utils.h
index 3c5e9b2af7f1..76c64c5245d4 100644
--- a/include/sound/soc_sdw_utils.h
+++ b/include/sound/soc_sdw_utils.h
@@ -68,6 +68,7 @@ struct asoc_sdw_codec_info {
const int part_id;
const int version_id;
const char *codec_name;
+ const char *name_prefix;
int amp_num;
const u8 acpi_id[ACPI_ID_LEN];
const bool ignore_internal_dmic;
@@ -168,6 +169,7 @@ int asoc_sdw_count_sdw_endpoints(struct snd_soc_card *card, int *num_devs, int *
struct asoc_sdw_dailink *asoc_sdw_find_dailink(struct asoc_sdw_dailink *dailinks,
const struct snd_soc_acpi_endpoint *new);
+int asoc_sdw_get_dai_type(u32 type);
int asoc_sdw_parse_sdw_endpoints(struct snd_soc_card *card,
struct asoc_sdw_dailink *soc_dais,
diff --git a/sound/soc/intel/common/sof-function-topology-lib.c b/sound/soc/intel/common/sof-function-topology-lib.c
index 3cc81dcf047e..b10d4794159a 100644
--- a/sound/soc/intel/common/sof-function-topology-lib.c
+++ b/sound/soc/intel/common/sof-function-topology-lib.c
@@ -126,11 +126,15 @@ int sof_sdw_get_tplg_files(struct snd_soc_card *card, const struct snd_soc_acpi_
if (!ret) {
release_firmware(fw);
} else {
- dev_dbg(card->dev, "Failed to open topology file: %s\n", (*tplg_files)[i]);
+ dev_warn(card->dev,
+ "Failed to open topology file: %s, you might need to\n",
+ (*tplg_files)[i]);
+ dev_warn(card->dev,
+ "download it from https://github.com/thesofproject/sof-bin/\n");
return 0;
}
}
return tplg_num;
}
-
+EXPORT_SYMBOL_GPL(sof_sdw_get_tplg_files);
diff --git a/sound/soc/sdw_utils/soc_sdw_utils.c b/sound/soc/sdw_utils/soc_sdw_utils.c
index 56c72ef27e7b..0460e2a8c50a 100644
--- a/sound/soc/sdw_utils/soc_sdw_utils.c
+++ b/sound/soc/sdw_utils/soc_sdw_utils.c
@@ -78,6 +78,7 @@ struct asoc_sdw_codec_info codec_info_list[] = {
},
{
.part_id = 0x700,
+ .name_prefix = "rt700",
.dais = {
{
.direction = {true, true},
@@ -95,6 +96,7 @@ struct asoc_sdw_codec_info codec_info_list[] = {
},
{
.part_id = 0x711,
+ .name_prefix = "rt711",
.version_id = 3,
.dais = {
{
@@ -115,6 +117,7 @@ struct asoc_sdw_codec_info codec_info_list[] = {
},
{
.part_id = 0x711,
+ .name_prefix = "rt711",
.version_id = 2,
.dais = {
{
@@ -135,6 +138,7 @@ struct asoc_sdw_codec_info codec_info_list[] = {
},
{
.part_id = 0x712,
+ .name_prefix = "rt712",
.version_id = 3,
.dais = {
{
@@ -176,6 +180,7 @@ struct asoc_sdw_codec_info codec_info_list[] = {
},
{
.part_id = 0x1712,
+ .name_prefix = "rt712-dmic",
.version_id = 3,
.dais = {
{
@@ -190,6 +195,7 @@ struct asoc_sdw_codec_info codec_info_list[] = {
},
{
.part_id = 0x713,
+ .name_prefix = "rt713",
.version_id = 3,
.dais = {
{
@@ -217,6 +223,7 @@ struct asoc_sdw_codec_info codec_info_list[] = {
},
{
.part_id = 0x1713,
+ .name_prefix = "rt713-dmic",
.version_id = 3,
.dais = {
{
@@ -231,6 +238,7 @@ struct asoc_sdw_codec_info codec_info_list[] = {
},
{
.part_id = 0x1308,
+ .name_prefix = "rt1308",
.acpi_id = "10EC1308",
.dais = {
{
@@ -253,6 +261,7 @@ struct asoc_sdw_codec_info codec_info_list[] = {
},
{
.part_id = 0x1316,
+ .name_prefix = "rt1316",
.dais = {
{
.direction = {true, true},
@@ -273,6 +282,7 @@ struct asoc_sdw_codec_info codec_info_list[] = {
},
{
.part_id = 0x1318,
+ .name_prefix = "rt1318",
.dais = {
{
.direction = {true, true},
@@ -293,6 +303,7 @@ struct asoc_sdw_codec_info codec_info_list[] = {
},
{
.part_id = 0x1320,
+ .name_prefix = "rt1320",
.dais = {
{
.direction = {true, false},
@@ -313,6 +324,7 @@ struct asoc_sdw_codec_info codec_info_list[] = {
},
{
.part_id = 0x714,
+ .name_prefix = "rt714",
.version_id = 3,
.ignore_internal_dmic = true,
.dais = {
@@ -328,6 +340,7 @@ struct asoc_sdw_codec_info codec_info_list[] = {
},
{
.part_id = 0x715,
+ .name_prefix = "rt715",
.version_id = 3,
.ignore_internal_dmic = true,
.dais = {
@@ -343,6 +356,7 @@ struct asoc_sdw_codec_info codec_info_list[] = {
},
{
.part_id = 0x714,
+ .name_prefix = "rt714",
.version_id = 2,
.ignore_internal_dmic = true,
.dais = {
@@ -358,6 +372,7 @@ struct asoc_sdw_codec_info codec_info_list[] = {
},
{
.part_id = 0x715,
+ .name_prefix = "rt715",
.version_id = 2,
.ignore_internal_dmic = true,
.dais = {
@@ -373,6 +388,7 @@ struct asoc_sdw_codec_info codec_info_list[] = {
},
{
.part_id = 0x721,
+ .name_prefix = "rt721",
.version_id = 3,
.dais = {
{
@@ -415,6 +431,7 @@ struct asoc_sdw_codec_info codec_info_list[] = {
},
{
.part_id = 0x722,
+ .name_prefix = "rt722",
.version_id = 3,
.dais = {
{
@@ -459,6 +476,7 @@ struct asoc_sdw_codec_info codec_info_list[] = {
},
{
.part_id = 0x8373,
+ .name_prefix = "Left",
.dais = {
{
.direction = {true, true},
@@ -478,6 +496,7 @@ struct asoc_sdw_codec_info codec_info_list[] = {
},
{
.part_id = 0x8363,
+ .name_prefix = "Left",
.dais = {
{
.direction = {true, false},
@@ -497,6 +516,7 @@ struct asoc_sdw_codec_info codec_info_list[] = {
},
{
.part_id = 0x5682,
+ .name_prefix = "rt5682",
.dais = {
{
.direction = {true, true},
@@ -514,6 +534,7 @@ struct asoc_sdw_codec_info codec_info_list[] = {
},
{
.part_id = 0x3556,
+ .name_prefix = "AMP",
.dais = {
{
.direction = {true, false},
@@ -566,6 +587,7 @@ struct asoc_sdw_codec_info codec_info_list[] = {
},
{
.part_id = 0x4242,
+ .name_prefix = "cs42l42",
.dais = {
{
.direction = {true, true},
@@ -583,6 +605,7 @@ struct asoc_sdw_codec_info codec_info_list[] = {
},
{
.part_id = 0x4243,
+ .name_prefix = "cs42l43",
.codec_name = "cs42l43-codec",
.count_sidecar = asoc_sdw_bridge_cs35l56_count_sidecar,
.add_sidecar = asoc_sdw_bridge_cs35l56_add_sidecar,
@@ -634,6 +657,7 @@ struct asoc_sdw_codec_info codec_info_list[] = {
},
{
.part_id = 0xaaaa, /* generic codec mockup */
+ .name_prefix = "sdw_mockup_mmulti-function",
.version_id = 0,
.dais = {
{
@@ -659,6 +683,7 @@ struct asoc_sdw_codec_info codec_info_list[] = {
},
{
.part_id = 0xaa55, /* headset codec mockup */
+ .name_prefix = "sdw_mockup_headset0",
.version_id = 0,
.dais = {
{
@@ -672,6 +697,7 @@ struct asoc_sdw_codec_info codec_info_list[] = {
},
{
.part_id = 0x55aa, /* amplifier mockup */
+ .name_prefix = "sdw_mockup_amp1",
.version_id = 0,
.dais = {
{
@@ -685,6 +711,7 @@ struct asoc_sdw_codec_info codec_info_list[] = {
},
{
.part_id = 0x5555,
+ .name_prefix = "sdw_mockup_mic0",
.version_id = 0,
.dais = {
{
@@ -1212,7 +1239,7 @@ struct asoc_sdw_dailink *asoc_sdw_find_dailink(struct asoc_sdw_dailink *dailinks
}
EXPORT_SYMBOL_NS(asoc_sdw_find_dailink, "SND_SOC_SDW_UTILS");
-static int asoc_sdw_get_dai_type(u32 type)
+int asoc_sdw_get_dai_type(u32 type)
{
switch (type) {
case SDCA_FUNCTION_TYPE_SMART_AMP:
@@ -1230,6 +1257,7 @@ static int asoc_sdw_get_dai_type(u32 type)
return -EINVAL;
}
}
+EXPORT_SYMBOL_NS(asoc_sdw_get_dai_type, "SND_SOC_SDW_UTILS");
/*
* Check if the SDCA endpoint is present by the SDW peripheral
diff --git a/sound/soc/sof/fw-file-profile.c b/sound/soc/sof/fw-file-profile.c
index 1c0eb13ae557..4a2afc04f338 100644
--- a/sound/soc/sof/fw-file-profile.c
+++ b/sound/soc/sof/fw-file-profile.c
@@ -73,6 +73,10 @@ static int sof_test_topology_file(struct device *dev,
if (!profile->tplg_path || !profile->tplg_name)
return 0;
+ /* Dummy topology does not exist and should not be used */
+ if (strstr(profile->tplg_name, "dummy"))
+ return 0;
+
tplg_filename = kasprintf(GFP_KERNEL, "%s/%s", profile->tplg_path,
profile->tplg_name);
if (!tplg_filename)
@@ -266,6 +270,7 @@ static void sof_print_profile_info(struct snd_sof_dev *sdev,
enum sof_ipc_type ipc_type,
struct sof_loadable_file_profile *profile)
{
+ struct snd_sof_pdata *plat_data = sdev->pdata;
struct device *dev = sdev->dev;
if (ipc_type != profile->ipc_type)
@@ -282,7 +287,12 @@ static void sof_print_profile_info(struct snd_sof_dev *sdev,
if (profile->fw_lib_path)
dev_info(dev, " Firmware lib path: %s\n", profile->fw_lib_path);
- dev_info(dev, " Topology file: %s/%s\n", profile->tplg_path, profile->tplg_name);
+
+ if (plat_data->machine->get_function_tplg_files && !plat_data->disable_function_topology)
+ dev_info(dev, " Topology file: function topologies\n");
+ else
+ dev_info(dev, " Topology file: %s/%s\n",
+ profile->tplg_path, profile->tplg_name);
}
int sof_create_ipc_file_profile(struct snd_sof_dev *sdev,
diff --git a/sound/soc/sof/intel/apl.c b/sound/soc/sof/intel/apl.c
index 76a92eaa1359..0c68ae41a8a8 100644
--- a/sound/soc/sof/intel/apl.c
+++ b/sound/soc/sof/intel/apl.c
@@ -118,4 +118,5 @@ const struct sof_intel_dsp_desc apl_chip_info = {
.power_down_dsp = hda_power_down_dsp,
.disable_interrupts = hda_dsp_disable_interrupts,
.hw_ip_version = SOF_INTEL_CAVS_1_5_PLUS,
+ .platform = "apl",
};
diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c
index c4b58738d74b..0cc5725515e7 100644
--- a/sound/soc/sof/intel/cnl.c
+++ b/sound/soc/sof/intel/cnl.c
@@ -479,6 +479,7 @@ const struct sof_intel_dsp_desc cnl_chip_info = {
.power_down_dsp = hda_power_down_dsp,
.disable_interrupts = hda_dsp_disable_interrupts,
.hw_ip_version = SOF_INTEL_CAVS_1_8,
+ .platform = "cnl",
};
/*
@@ -515,5 +516,6 @@ const struct sof_intel_dsp_desc jsl_chip_info = {
.power_down_dsp = hda_power_down_dsp,
.disable_interrupts = hda_dsp_disable_interrupts,
.hw_ip_version = SOF_INTEL_CAVS_2_0,
+ .platform = "jsl",
};
EXPORT_SYMBOL_NS(jsl_chip_info, "SND_SOC_SOF_INTEL_CNL");
diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c
index 52e86fa60077..00835fc8ef8d 100644
--- a/sound/soc/sof/intel/hda.c
+++ b/sound/soc/sof/intel/hda.c
@@ -26,6 +26,7 @@
#include <sound/intel-dsp-config.h>
#include <sound/intel-nhlt.h>
#include <sound/soc-acpi-intel-ssp-common.h>
+#include <sound/soc_sdw_utils.h>
#include <sound/sof.h>
#include <sound/sof/xtensa.h>
#include <sound/hda-mlink.h>
@@ -33,6 +34,7 @@
#include "../sof-pci-dev.h"
#include "../ops.h"
#include "../ipc4-topology.h"
+#include "../../intel/common/sof-function-topology-lib.h"
#include "hda.h"
#include <trace/events/sof_intel.h>
@@ -1131,14 +1133,166 @@ static void hda_generic_machine_select(struct snd_sof_dev *sdev,
#if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE)
+static bool is_endpoint_present(struct sdw_slave *sdw_device,
+ struct asoc_sdw_codec_info *dai_info, int dai_type)
+{
+ int i;
+
+ for (i = 0; i < sdw_device->sdca_data.num_functions; i++) {
+ if (dai_type == dai_info->dais[i].dai_type)
+ return true;
+ }
+ dev_dbg(&sdw_device->dev, "Endpoint DAI type %d not found\n", dai_type);
+ return false;
+}
+
+static struct snd_soc_acpi_adr_device *find_acpi_adr_device(struct device *dev,
+ struct sdw_slave *sdw_device,
+ struct snd_soc_acpi_link_adr *link,
+ int *amp_index)
+{
+ struct snd_soc_acpi_adr_device *adr_dev;
+ const char *name_prefix = "";
+ int index = link->num_adr;
+ bool is_amp = true; /* Set it to false if the codec wiah any NON-AMP DAI type */
+ int ep_index = 0;
+ int i, j;
+
+ link->mask = BIT(sdw_device->bus->link_id);
+ /* index is 0 based, we need allocate index + 1 for the array size */
+ if (!index)
+ adr_dev = devm_kzalloc(dev, sizeof(*adr_dev), GFP_KERNEL);
+ else
+ adr_dev = devm_krealloc(dev, (struct snd_soc_acpi_adr_device *)link->adr_d,
+ (index + 1) * sizeof(*adr_dev), GFP_KERNEL);
+
+ if (!adr_dev)
+ return NULL;
+
+ for (i = 0; i < asoc_sdw_get_codec_info_list_count(); i++) {
+ struct snd_soc_acpi_endpoint *endpoints;
+ int amp_group_id = 1;
+
+ if (sdw_device->id.part_id != codec_info_list[i].part_id)
+ continue;
+
+ endpoints = devm_kcalloc(dev, codec_info_list[i].dai_num,
+ sizeof(struct snd_soc_acpi_endpoint), GFP_KERNEL);
+ if (!endpoints)
+ return NULL;
+
+ name_prefix = codec_info_list[i].name_prefix;
+ /*
+ * This should not happen, but add a paranoid check to avoid NULL pointer
+ * dereference
+ */
+ if (!name_prefix) {
+ dev_err(dev, "codec_info_list name_prefix of part id %#x is missing\n",
+ codec_info_list[i].part_id);
+ return NULL;
+ }
+ for (j = 0; j < codec_info_list[i].dai_num; j++) {
+ /* Check if the endpoint is present by the SDCA DisCo table */
+ if (!is_endpoint_present(sdw_device, &codec_info_list[i],
+ codec_info_list[i].dais[j].dai_type))
+ continue;
+
+ endpoints[ep_index].num = ep_index;
+ if (codec_info_list[i].dais[j].dai_type == SOC_SDW_DAI_TYPE_AMP) {
+ /* Assume all amp are aggregated */
+ endpoints[ep_index].aggregated = 1;
+ endpoints[ep_index].group_id = amp_group_id;
+ endpoints[ep_index].group_position = *amp_index;
+ /* Set group id = 2 for feedback capture endpoint */
+ amp_group_id++;
+ } else {
+ endpoints[ep_index].aggregated = 0;
+ endpoints[ep_index].group_id = 0;
+ endpoints[ep_index].group_position = 0;
+ is_amp = false;
+ }
+ ep_index++;
+ }
+ adr_dev[index].endpoints = endpoints;
+ adr_dev[index].num_endpoints = ep_index;
+ break;
+ }
+
+ if (i == asoc_sdw_get_codec_info_list_count()) {
+ dev_err(dev, "part id %#x is not supported\n", sdw_device->id.part_id);
+ return NULL;
+ }
+
+ adr_dev[index].adr = ((u64)sdw_device->id.class_id & 0xFF) |
+ ((u64)sdw_device->id.part_id & 0xFFFF) << 8 |
+ ((u64)sdw_device->id.mfg_id & 0xFFFF) << 24 |
+ ((u64)(sdw_device->id.unique_id & 0xF) << 40) |
+ ((u64)(sdw_device->id.sdw_version & 0xF) << 44) |
+ ((u64)(sdw_device->bus->link_id & 0xF) << 48);
+
+ if (!is_amp) {
+ /* For non-amp codecs, get name_prefix from codec_info_list[] */
+ adr_dev[index].name_prefix = devm_kasprintf(dev, GFP_KERNEL, "%s", name_prefix);
+ goto done_name_prefix;
+ }
+
+ /*
+ * The name_prefix comes from codec_info_list which has a name_prefix per codec.
+ * And we need to give a unique name_prefix for each amp and should be backwards
+ * compatible to the existing acpi match tables to not break existing UCMs.
+ * For the common name_prefix, we append the amp index to it. However, for the
+ * "Left" name_prefix, we convert the second amp name_prefix to "Right" and
+ * for the third and further amps, we set the name_prefix to "AMP<amp_index>".
+ */
+ if (!strcmp(name_prefix, "Left")) {
+ switch (*amp_index) {
+ case 1:
+ adr_dev[index].name_prefix = devm_kasprintf(dev, GFP_KERNEL,
+ "%s", "Left");
+ break;
+ case 2:
+ adr_dev[index].name_prefix = devm_kasprintf(dev, GFP_KERNEL,
+ "%s", "Right");
+ break;
+ default:
+ /* Set the name_fix to AMP<amp_index> if there are more than 2 amps */
+ adr_dev[index].name_prefix = devm_kasprintf(dev, GFP_KERNEL, "%s%d",
+ "AMP", *amp_index);
+ break;
+ }
+ } else {
+ adr_dev[index].name_prefix = devm_kasprintf(dev, GFP_KERNEL, "%s%d",
+ name_prefix,
+ *amp_index);
+ }
+ (*amp_index)++;
+
+done_name_prefix:
+ if (!adr_dev[index].name_prefix) {
+ dev_err(dev, "failed to allocate memory for name_prefix\n");
+ return NULL;
+ }
+
+ dev_dbg(dev, "adr[%d] 0x%llx link id %d name_prefix \"%s\" is found\n",
+ index, adr_dev[index].adr, sdw_device->bus->link_id, adr_dev[index].name_prefix);
+
+ link->num_adr++;
+
+ return adr_dev;
+}
+
static struct snd_soc_acpi_mach *hda_sdw_machine_select(struct snd_sof_dev *sdev)
{
struct snd_sof_pdata *pdata = sdev->pdata;
const struct snd_soc_acpi_link_adr *link;
+ const struct sof_intel_dsp_desc *chip;
+ struct snd_soc_acpi_link_adr *links;
struct sdw_peripherals *peripherals;
struct snd_soc_acpi_mach *mach;
struct sof_intel_hda_dev *hdev;
- u32 link_mask;
+ int link_index, link_num;
+ int amp_index = 1;
+ u32 link_mask = 0;
int i;
hdev = pdata->hw_pdata;
@@ -1215,7 +1369,53 @@ static struct snd_soc_acpi_mach *hda_sdw_machine_select(struct snd_sof_dev *sdev
peripherals->array[i]->id.part_id,
peripherals->array[i]->id.sdw_version);
- return NULL;
+ chip = get_chip_info(sdev->pdata);
+
+ /* SDCA was not well supported in the BIOS before ACE2.0 */
+ if (chip->hw_ip_version < SOF_INTEL_ACE_2_0)
+ return NULL;
+
+ if (!peripherals->num_peripherals)
+ return NULL;
+
+ /* Create default SDW mach */
+ mach = devm_kzalloc(sdev->dev, sizeof(*mach), GFP_KERNEL);
+ if (!mach)
+ return NULL;
+
+ /* Get link mask and link number */
+ for (i = 0; i < peripherals->num_peripherals; i++)
+ link_mask |= BIT(peripherals->array[i]->bus->link_id);
+
+ link_num = hweight32(link_mask);
+ links = devm_kcalloc(sdev->dev, link_num, sizeof(*links), GFP_KERNEL);
+ if (!links)
+ return NULL;
+
+ /* Generate snd_soc_acpi_link_adr struct for each peripheral reported by the ACPI table */
+ for (i = 0; i < peripherals->num_peripherals; i++) {
+ /* link_index = the number of used links below the current link */
+ link_index = hweight32(link_mask & (BIT(peripherals->array[i]->bus->link_id) - 1));
+ links[link_index].adr_d = find_acpi_adr_device(sdev->dev, peripherals->array[i],
+ &links[link_index], &amp_index);
+ if (!links[link_index].adr_d)
+ return NULL;
+ }
+
+ mach->drv_name = "sof_sdw";
+ mach->mach_params.links = links;
+ mach->mach_params.link_mask = link_mask;
+ mach->mach_params.platform = dev_name(sdev->dev);
+ mach->get_function_tplg_files = sof_sdw_get_tplg_files;
+ /*
+ * Set mach->sof_tplg_filename as a dummy topology to avoid tplg file checking
+ * and being used.
+ */
+ mach->sof_tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL,
+ "sof-%s-dummy.tplg", chip->platform);
+
+ dev_info(sdev->dev, "Use SoundWire default machine driver with function topologies\n");
+ return mach;
}
#else
static struct snd_soc_acpi_mach *hda_sdw_machine_select(struct snd_sof_dev *sdev)
@@ -1543,6 +1743,7 @@ MODULE_IMPORT_NS("SND_SOC_SOF_XTENSA");
MODULE_IMPORT_NS("SND_INTEL_SOUNDWIRE_ACPI");
MODULE_IMPORT_NS("SOUNDWIRE_INTEL_INIT");
MODULE_IMPORT_NS("SOUNDWIRE_INTEL");
+MODULE_IMPORT_NS("SND_SOC_SDW_UTILS");
MODULE_IMPORT_NS("SND_SOC_SOF_HDA_MLINK");
MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_HDA_COMMON");
MODULE_IMPORT_NS("SND_SOC_ACPI_INTEL_MATCH");
diff --git a/sound/soc/sof/intel/icl.c b/sound/soc/sof/intel/icl.c
index dad6bc72ad37..dbc5ad62258b 100644
--- a/sound/soc/sof/intel/icl.c
+++ b/sound/soc/sof/intel/icl.c
@@ -193,4 +193,5 @@ const struct sof_intel_dsp_desc icl_chip_info = {
.power_down_dsp = hda_power_down_dsp,
.disable_interrupts = hda_dsp_disable_interrupts,
.hw_ip_version = SOF_INTEL_CAVS_2_0,
+ .platform = "icl",
};
diff --git a/sound/soc/sof/intel/lnl.c b/sound/soc/sof/intel/lnl.c
index 2f3222040f98..c01ea7e731aa 100644
--- a/sound/soc/sof/intel/lnl.c
+++ b/sound/soc/sof/intel/lnl.c
@@ -183,6 +183,7 @@ const struct sof_intel_dsp_desc lnl_chip_info = {
.power_down_dsp = mtl_power_down_dsp,
.disable_interrupts = lnl_dsp_disable_interrupts,
.hw_ip_version = SOF_INTEL_ACE_2_0,
+ .platform = "lnl",
};
MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_MTL");
diff --git a/sound/soc/sof/intel/mtl.c b/sound/soc/sof/intel/mtl.c
index 2242c96bfa51..095dcf1a18e4 100644
--- a/sound/soc/sof/intel/mtl.c
+++ b/sound/soc/sof/intel/mtl.c
@@ -786,6 +786,7 @@ const struct sof_intel_dsp_desc mtl_chip_info = {
.power_down_dsp = mtl_power_down_dsp,
.disable_interrupts = mtl_dsp_disable_interrupts,
.hw_ip_version = SOF_INTEL_ACE_1_0,
+ .platform = "mtl",
};
const struct sof_intel_dsp_desc arl_s_chip_info = {
@@ -814,4 +815,5 @@ const struct sof_intel_dsp_desc arl_s_chip_info = {
.power_down_dsp = mtl_power_down_dsp,
.disable_interrupts = mtl_dsp_disable_interrupts,
.hw_ip_version = SOF_INTEL_ACE_1_0,
+ .platform = "arl",
};
diff --git a/sound/soc/sof/intel/ptl.c b/sound/soc/sof/intel/ptl.c
index 4633cd01e7dd..c1db735237f8 100644
--- a/sound/soc/sof/intel/ptl.c
+++ b/sound/soc/sof/intel/ptl.c
@@ -125,6 +125,7 @@ const struct sof_intel_dsp_desc ptl_chip_info = {
.power_down_dsp = mtl_power_down_dsp,
.disable_interrupts = lnl_dsp_disable_interrupts,
.hw_ip_version = SOF_INTEL_ACE_3_0,
+ .platform = "ptl",
};
const struct sof_intel_dsp_desc wcl_chip_info = {
@@ -149,6 +150,7 @@ const struct sof_intel_dsp_desc wcl_chip_info = {
.power_down_dsp = mtl_power_down_dsp,
.disable_interrupts = lnl_dsp_disable_interrupts,
.hw_ip_version = SOF_INTEL_ACE_3_0,
+ .platform = "wcl",
};
MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_MTL");
diff --git a/sound/soc/sof/intel/shim.h b/sound/soc/sof/intel/shim.h
index d4372f0bff7e..dc6a93d05bfe 100644
--- a/sound/soc/sof/intel/shim.h
+++ b/sound/soc/sof/intel/shim.h
@@ -186,6 +186,7 @@ struct sof_intel_dsp_desc {
u32 sdw_alh_base;
u32 d0i3_offset;
u32 quirks;
+ const char *platform;
enum sof_intel_hw_ip_version hw_ip_version;
int (*read_sdw_lcount)(struct snd_sof_dev *sdev);
void (*enable_sdw_irq)(struct snd_sof_dev *sdev, bool enable);
diff --git a/sound/soc/sof/intel/skl.c b/sound/soc/sof/intel/skl.c
index 0696bce65e33..90a3c2e2334c 100644
--- a/sound/soc/sof/intel/skl.c
+++ b/sound/soc/sof/intel/skl.c
@@ -113,5 +113,6 @@ const struct sof_intel_dsp_desc skl_chip_info = {
.power_down_dsp = hda_power_down_dsp,
.disable_interrupts = hda_dsp_disable_interrupts,
.hw_ip_version = SOF_INTEL_CAVS_1_5,
+ .platform = "skl",
};
EXPORT_SYMBOL_NS(skl_chip_info, "SND_SOC_SOF_INTEL_HDA_COMMON");
diff --git a/sound/soc/sof/intel/tgl.c b/sound/soc/sof/intel/tgl.c
index df2d26b78ddc..e68bbe685ba3 100644
--- a/sound/soc/sof/intel/tgl.c
+++ b/sound/soc/sof/intel/tgl.c
@@ -162,6 +162,7 @@ const struct sof_intel_dsp_desc tgl_chip_info = {
.power_down_dsp = hda_power_down_dsp,
.disable_interrupts = hda_dsp_disable_interrupts,
.hw_ip_version = SOF_INTEL_CAVS_2_5,
+ .platform = "tgl",
};
const struct sof_intel_dsp_desc tglh_chip_info = {
@@ -191,6 +192,7 @@ const struct sof_intel_dsp_desc tglh_chip_info = {
.power_down_dsp = hda_power_down_dsp,
.disable_interrupts = hda_dsp_disable_interrupts,
.hw_ip_version = SOF_INTEL_CAVS_2_5,
+ .platform = "tgl",
};
const struct sof_intel_dsp_desc ehl_chip_info = {
@@ -220,6 +222,7 @@ const struct sof_intel_dsp_desc ehl_chip_info = {
.power_down_dsp = hda_power_down_dsp,
.disable_interrupts = hda_dsp_disable_interrupts,
.hw_ip_version = SOF_INTEL_CAVS_2_5,
+ .platform = "ehl",
};
const struct sof_intel_dsp_desc adls_chip_info = {
@@ -249,4 +252,5 @@ const struct sof_intel_dsp_desc adls_chip_info = {
.power_down_dsp = hda_power_down_dsp,
.disable_interrupts = hda_dsp_disable_interrupts,
.hw_ip_version = SOF_INTEL_CAVS_2_5,
+ .platform = "adl",
};
diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c
index b6d5c8024f8c..c1083ea4624a 100644
--- a/sound/soc/sof/topology.c
+++ b/sound/soc/sof/topology.c
@@ -2523,9 +2523,14 @@ int snd_sof_load_topology(struct snd_soc_component *scomp, const char *file)
* callback or the callback returns 0.
*/
if (!tplg_cnt) {
+ if (strstr(file, "dummy")) {
+ dev_err(scomp->dev,
+ "Function topology is required, please upgrade sof-firmware\n");
+ return -EINVAL;
+ }
tplg_files[0] = file;
tplg_cnt = 1;
- dev_dbg(scomp->dev, "loading topology: %s\n", file);
+ dev_info(scomp->dev, "loading topology: %s\n", file);
} else {
dev_info(scomp->dev, "Using function topologies instead %s\n", file);
}