Skip to content

Commit c09d744

Browse files
committed
ASoC: SOF: Intel: use sof_sdw as default SDW machine driver
If there is no SoundWire machine matches the existing acpi match table, get the required machine date from the acpi table and construct the link adrs and endpoints. Pass the data to the default Intel SoundWire machine driver. And we don't need to add new item to the acpi match table in common cases. We will get a topology name from the existing acpi match table. The dummy topology is just used to extract the platform name for function topology and should not be used. Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
1 parent 7059184 commit c09d744

3 files changed

Lines changed: 220 additions & 2 deletions

File tree

sound/soc/sof/fw-file-profile.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ static int sof_test_topology_file(struct device *dev,
7373
if (!profile->tplg_path || !profile->tplg_name)
7474
return 0;
7575

76+
/* Dummy topology does not exist and should not be used */
77+
if (strstr(profile->tplg_name, "dummy"))
78+
return 0;
79+
7680
tplg_filename = kasprintf(GFP_KERNEL, "%s/%s", profile->tplg_path,
7781
profile->tplg_name);
7882
if (!tplg_filename)

sound/soc/sof/intel/hda.c

Lines changed: 211 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,15 @@
2626
#include <sound/intel-dsp-config.h>
2727
#include <sound/intel-nhlt.h>
2828
#include <sound/soc-acpi-intel-ssp-common.h>
29+
#include <sound/soc_sdw_utils.h>
2930
#include <sound/sof.h>
3031
#include <sound/sof/xtensa.h>
3132
#include <sound/hda-mlink.h>
3233
#include "../sof-audio.h"
3334
#include "../sof-pci-dev.h"
3435
#include "../ops.h"
3536
#include "../ipc4-topology.h"
37+
#include "../../intel/common/sof-function-topology-lib.h"
3638
#include "hda.h"
3739

3840
#include <trace/events/sof_intel.h>
@@ -1131,14 +1133,161 @@ static void hda_generic_machine_select(struct snd_sof_dev *sdev,
11311133

11321134
#if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE)
11331135

1136+
static bool is_endpoint_present(struct sdw_slave *sdw_device,
1137+
struct asoc_sdw_codec_info *dai_info, int dai_type)
1138+
{
1139+
int i;
1140+
1141+
for (i = 0; i < sdw_device->sdca_data.num_functions; i++) {
1142+
if (dai_type == dai_info->dais[i].dai_type)
1143+
return true;
1144+
}
1145+
dev_dbg(&sdw_device->dev, "Endpoint DAI type %d not found\n", dai_type);
1146+
return false;
1147+
}
1148+
1149+
static struct snd_soc_acpi_adr_device *find_acpi_adr_device(struct device *dev,
1150+
struct sdw_slave *sdw_device,
1151+
struct snd_soc_acpi_link_adr *link,
1152+
int *amp_index)
1153+
{
1154+
struct snd_soc_acpi_adr_device *adr_dev;
1155+
const char *name_prefix = "";
1156+
int index = link->num_adr;
1157+
bool is_amp = true; /* Set it to false if the codec wiah any NON-AMP DAI type */
1158+
int ep_index = 0;
1159+
int i, j;
1160+
1161+
link->mask = BIT(sdw_device->bus->link_id);
1162+
/* index is 0 based, we need allocate index + 1 for the array size */
1163+
if (!index)
1164+
adr_dev = devm_kzalloc(dev, sizeof(*adr_dev), GFP_KERNEL);
1165+
else
1166+
adr_dev = devm_krealloc(dev, (struct snd_soc_acpi_adr_device *)link->adr_d,
1167+
(index + 1) * sizeof(*adr_dev), GFP_KERNEL);
1168+
1169+
if (!adr_dev)
1170+
return NULL;
1171+
1172+
for (i = 0; i < asoc_sdw_get_codec_info_list_count(); i++) {
1173+
struct snd_soc_acpi_endpoint *endpoints;
1174+
int amp_group_id = 1;
1175+
1176+
if (sdw_device->id.part_id != codec_info_list[i].part_id)
1177+
continue;
1178+
1179+
endpoints = devm_kcalloc(dev, codec_info_list[i].dai_num,
1180+
sizeof(struct snd_soc_acpi_endpoint), GFP_KERNEL);
1181+
if (!endpoints) {
1182+
dev_err(dev, "failed to allocate memory for endpoints\n");
1183+
return NULL;
1184+
}
1185+
1186+
name_prefix = codec_info_list[i].name_prefix;
1187+
for (j = 0; j < codec_info_list[i].dai_num; j++) {
1188+
/* Check if the endpoint is present by the SDCA DisCo table */
1189+
if (!is_endpoint_present(sdw_device, &codec_info_list[i],
1190+
codec_info_list[i].dais[j].dai_type))
1191+
continue;
1192+
1193+
endpoints[ep_index].num = ep_index;
1194+
if (codec_info_list[i].dais[j].dai_type == SOC_SDW_DAI_TYPE_AMP) {
1195+
/* Assume all amp are aggregated */
1196+
endpoints[ep_index].aggregated = 1;
1197+
endpoints[ep_index].group_id = amp_group_id;
1198+
endpoints[ep_index].group_position = *amp_index;
1199+
/* Set group id = 2 for feedback capture endpoint */
1200+
amp_group_id++;
1201+
} else {
1202+
endpoints[ep_index].aggregated = 0;
1203+
endpoints[ep_index].group_id = 0;
1204+
endpoints[ep_index].group_position = 0;
1205+
is_amp = false;
1206+
}
1207+
ep_index++;
1208+
}
1209+
adr_dev[index].endpoints = endpoints;
1210+
adr_dev[index].num_endpoints = ep_index;
1211+
break;
1212+
}
1213+
1214+
if (i == asoc_sdw_get_codec_info_list_count()) {
1215+
dev_err(dev, "part id %#x is not supported\n", sdw_device->id.part_id);
1216+
return NULL;
1217+
}
1218+
1219+
adr_dev[index].adr = ((u64)sdw_device->id.class_id & 0xFF) |
1220+
((u64)sdw_device->id.part_id & 0xFFFF) << 8 |
1221+
((u64)sdw_device->id.mfg_id & 0xFFFF) << 24 |
1222+
((u64)(sdw_device->id.unique_id & 0xF) << 40) |
1223+
((u64)(sdw_device->id.sdw_version & 0xF) << 44) |
1224+
((u64)(sdw_device->bus->link_id & 0xF) << 48);
1225+
1226+
if (!is_amp) {
1227+
/* For non-amp codecs, get name_prefix from codec_info_list[] */
1228+
adr_dev[index].name_prefix = devm_kasprintf(dev, GFP_KERNEL, "%s", name_prefix);
1229+
goto done_name_prefix;
1230+
}
1231+
1232+
/*
1233+
* The name_prefix comes from codec_info_list which has a name_prefix per codec.
1234+
* And we need to give a unique name_prefix for each amp and should be backwards
1235+
* compatible to the existing acpi match tables to not break existing UCMs.
1236+
* For the common name_prefix, we append the amp index to it. However, for the
1237+
* "Left" name_prefix, we convert the second amp name_prefix to "Right" and
1238+
* for the third and further amps, we set the name_prefix to "AMP<amp_index>".
1239+
*/
1240+
if (!strcmp(name_prefix, "Left")) {
1241+
switch (*amp_index) {
1242+
case 1:
1243+
adr_dev[index].name_prefix = devm_kasprintf(dev, GFP_KERNEL,
1244+
"%s", "Left");
1245+
break;
1246+
case 2:
1247+
adr_dev[index].name_prefix = devm_kasprintf(dev, GFP_KERNEL,
1248+
"%s", "Right");
1249+
break;
1250+
default:
1251+
/* Set the name_fix to AMP<amp_index> if there are more than 2 amps */
1252+
adr_dev[index].name_prefix = devm_kasprintf(dev, GFP_KERNEL, "%s%d",
1253+
"AMP", *amp_index);
1254+
break;
1255+
}
1256+
} else {
1257+
adr_dev[index].name_prefix = devm_kasprintf(dev, GFP_KERNEL, "%s%d",
1258+
name_prefix,
1259+
*amp_index);
1260+
}
1261+
(*amp_index)++;
1262+
1263+
done_name_prefix:
1264+
if (!adr_dev[index].name_prefix) {
1265+
dev_err(dev, "failed to allocate memory for name_prefix\n");
1266+
return NULL;
1267+
}
1268+
1269+
dev_dbg(dev, "adr[%d] 0x%llx link id %d name_prefix \"%s\" is found\n",
1270+
index, adr_dev[index].adr, sdw_device->bus->link_id, adr_dev[index].name_prefix);
1271+
1272+
link->num_adr++;
1273+
1274+
return adr_dev;
1275+
}
1276+
11341277
static struct snd_soc_acpi_mach *hda_sdw_machine_select(struct snd_sof_dev *sdev)
11351278
{
11361279
struct snd_sof_pdata *pdata = sdev->pdata;
11371280
const struct snd_soc_acpi_link_adr *link;
1281+
const struct sof_intel_dsp_desc *chip;
1282+
struct snd_soc_acpi_link_adr *links;
11381283
struct sdw_peripherals *peripherals;
11391284
struct snd_soc_acpi_mach *mach;
11401285
struct sof_intel_hda_dev *hdev;
1141-
u32 link_mask;
1286+
const char *tplg_file_name;
1287+
int link_index, link_num;
1288+
int amp_index = 1;
1289+
u32 link_mask = 0;
1290+
char temp[7];
11421291
int i;
11431292

11441293
hdev = pdata->hw_pdata;
@@ -1167,6 +1316,15 @@ static struct snd_soc_acpi_mach *hda_sdw_machine_select(struct snd_sof_dev *sdev
11671316
*/
11681317
for (mach = pdata->desc->alt_machines;
11691318
mach && mach->link_mask; mach++) {
1319+
/*
1320+
* Use an existing topology for the default SDW mach. So that we can get the
1321+
* platform name from the topology name and don't need to create new topology
1322+
* for each platform. The topology will not be use, We will use the function
1323+
* topologies instead.
1324+
*/
1325+
if (!strcmp(mach->drv_name, "sof_sdw"))
1326+
tplg_file_name = mach->sof_tplg_filename;
1327+
11701328
/*
11711329
* On some platforms such as Up Extreme all links
11721330
* are enabled but only one link can be used by
@@ -1215,7 +1373,57 @@ static struct snd_soc_acpi_mach *hda_sdw_machine_select(struct snd_sof_dev *sdev
12151373
peripherals->array[i]->id.part_id,
12161374
peripherals->array[i]->id.sdw_version);
12171375

1218-
return NULL;
1376+
/* The function topology needs the tplg file name to get the platform name for PCH DMIC */
1377+
/* FIXME: find another way to get the platform name */
1378+
if (!tplg_file_name)
1379+
return NULL;
1380+
1381+
chip = get_chip_info(sdev->pdata);
1382+
1383+
/* SDCA was not well supported in the BIOS before ACE2.0 */
1384+
if (chip->hw_ip_version < SOF_INTEL_ACE_2_0) {
1385+
return NULL;
1386+
}
1387+
1388+
if (!peripherals->num_peripherals)
1389+
return NULL;
1390+
1391+
/* Create default SDW mach */
1392+
mach = devm_kzalloc(sdev->dev, sizeof(*mach), GFP_KERNEL);
1393+
if (!mach)
1394+
return NULL;
1395+
1396+
/* Get link mask and link number */
1397+
for (i = 0; i < peripherals->num_peripherals; i++)
1398+
link_mask |= BIT(peripherals->array[i]->bus->link_id);
1399+
1400+
link_num = hweight32(link_mask);
1401+
links = devm_kcalloc(sdev->dev, link_num, sizeof(*links), GFP_KERNEL);
1402+
if (!links)
1403+
return NULL;
1404+
1405+
/* Generate snd_soc_acpi_link_adr struct for each peripheral reported by the ACPI table */
1406+
for (i = 0; i < peripherals->num_peripherals; i++) {
1407+
/* link_index = the number of used links below the current link */
1408+
link_index = hweight32(link_mask & (BIT(peripherals->array[i]->bus->link_id) - 1));
1409+
links[link_index].adr_d = find_acpi_adr_device(sdev->dev, peripherals->array[i],
1410+
&links[link_index], &amp_index);
1411+
}
1412+
1413+
mach->drv_name = "sof_sdw";
1414+
mach->mach_params.links = links;
1415+
mach->mach_params.link_mask = link_mask;
1416+
mach->mach_params.platform = dev_name(sdev->dev);
1417+
mach->get_function_tplg_files = sof_sdw_get_tplg_files;
1418+
/*
1419+
* Set mach->sof_tplg_filename as a dummy topology to avoid tplg file checking
1420+
* and being used.
1421+
*/
1422+
strncpy(temp, tplg_file_name, 7);
1423+
mach->sof_tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL, "%s-dummy.tplg", temp);
1424+
1425+
dev_info(sdev->dev, "Use SoundWire default machine driver with function topologies\n");
1426+
return mach;
12191427
}
12201428
#else
12211429
static struct snd_soc_acpi_mach *hda_sdw_machine_select(struct snd_sof_dev *sdev)
@@ -1543,6 +1751,7 @@ MODULE_IMPORT_NS("SND_SOC_SOF_XTENSA");
15431751
MODULE_IMPORT_NS("SND_INTEL_SOUNDWIRE_ACPI");
15441752
MODULE_IMPORT_NS("SOUNDWIRE_INTEL_INIT");
15451753
MODULE_IMPORT_NS("SOUNDWIRE_INTEL");
1754+
MODULE_IMPORT_NS("SND_SOC_SDW_UTILS");
15461755
MODULE_IMPORT_NS("SND_SOC_SOF_HDA_MLINK");
15471756
MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_HDA_COMMON");
15481757
MODULE_IMPORT_NS("SND_SOC_ACPI_INTEL_MATCH");

sound/soc/sof/topology.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2523,6 +2523,11 @@ int snd_sof_load_topology(struct snd_soc_component *scomp, const char *file)
25232523
* callback or the callback returns 0.
25242524
*/
25252525
if (!tplg_cnt) {
2526+
if (strstr(file, "dummy")) {
2527+
dev_err(scomp->dev,
2528+
"Function topology is required, please upgrade sof-bin\n");
2529+
return -EINVAL;
2530+
}
25262531
tplg_files[0] = file;
25272532
tplg_cnt = 1;
25282533
dev_dbg(scomp->dev, "loading topology: %s\n", file);

0 commit comments

Comments
 (0)