Skip to content

Commit 63ea027

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. Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
1 parent 5b7f361 commit 63ea027

File tree

1 file changed

+150
-1
lines changed

1 file changed

+150
-1
lines changed

sound/soc/sof/intel/hda.c

Lines changed: 150 additions & 1 deletion
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>
@@ -1117,13 +1119,127 @@ static void hda_generic_machine_select(struct snd_sof_dev *sdev,
11171119

11181120
#if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE)
11191121

1122+
static bool is_endpoint_present(struct sdw_slave *sdw_device,
1123+
struct asoc_sdw_codec_info *dai_info, int dai_type)
1124+
{
1125+
int i;
1126+
1127+
for (i = 0; i < sdw_device->sdca_data.num_functions; i++) {
1128+
if (dai_type == dai_info->dais[i].dai_type)
1129+
return true;
1130+
}
1131+
dev_dbg(&sdw_device->dev, "Endpoint DAI type %d not found\n", dai_type);
1132+
return false;
1133+
}
1134+
1135+
static struct snd_soc_acpi_adr_device *find_acpi_adr_device(struct device *dev,
1136+
struct sdw_slave *sdw_device,
1137+
struct snd_soc_acpi_link_adr *link,
1138+
int *amp_index)
1139+
{
1140+
struct snd_soc_acpi_adr_device *adr_dev;
1141+
int index = link->num_adr;
1142+
int ep_index = 0;
1143+
int i, j;
1144+
1145+
link->mask = BIT(sdw_device->bus->link_id);
1146+
if (!index)
1147+
adr_dev = devm_kzalloc(dev, sizeof(*adr_dev), GFP_KERNEL);
1148+
else
1149+
adr_dev = devm_krealloc(dev, (struct snd_soc_acpi_adr_device *)link->adr_d,
1150+
(index + 1) * sizeof(*adr_dev), GFP_KERNEL);
1151+
1152+
if (!adr_dev)
1153+
return NULL;
1154+
1155+
for (i = 0; i < asoc_sdw_get_codec_info_list_count(); i++) {
1156+
if (sdw_device->id.part_id == codec_info_list[i].part_id) {
1157+
int amp_group_id = 1;
1158+
1159+
adr_dev[index].endpoints =
1160+
devm_kzalloc(dev, codec_info_list[i].dai_num *
1161+
sizeof(struct snd_soc_acpi_endpoint), GFP_KERNEL);
1162+
adr_dev[index].name_prefix = devm_kasprintf(dev, GFP_KERNEL, "%s",
1163+
codec_info_list[i].name_prefix);
1164+
for (j = 0; j < codec_info_list[i].dai_num; j++) {
1165+
if (!is_endpoint_present(sdw_device, &codec_info_list[i],
1166+
codec_info_list[i].dais[j].dai_type))
1167+
continue;
1168+
adr_dev[index].endpoints[ep_index].num = ep_index;
1169+
/* Assume all amp are aggregated */
1170+
if (codec_info_list[i].dais[j].dai_type == SOC_SDW_DAI_TYPE_AMP) {
1171+
adr_dev[index].endpoints[ep_index].aggregated = 1;
1172+
adr_dev[index].endpoints[ep_index].group_id = amp_group_id;
1173+
amp_group_id++;
1174+
} else {
1175+
adr_dev[index].endpoints[ep_index].aggregated = 0;
1176+
adr_dev[index].endpoints[ep_index].group_id = 0;
1177+
}
1178+
adr_dev[index].endpoints[ep_index].group_position = 0;
1179+
ep_index++;
1180+
}
1181+
adr_dev[index].num_endpoints = ep_index;
1182+
break;
1183+
}
1184+
}
1185+
1186+
if (i == asoc_sdw_get_codec_info_list_count()) {
1187+
dev_err(dev, "part id %#x is not supported\n", sdw_device->id.part_id);
1188+
return NULL;
1189+
}
1190+
1191+
adr_dev[index].adr = ((u64)sdw_device->id.class_id & 0xFF) |
1192+
((u64)sdw_device->id.part_id & 0xFFFF) << 8 |
1193+
((u64)sdw_device->id.mfg_id & 0xFFFF) << 24 |
1194+
((u64)(sdw_device->id.unique_id & 0xF) << 40) |
1195+
((u64)(sdw_device->id.sdw_version & 0xF) << 44) |
1196+
((u64)(sdw_device->bus->link_id & 0xF) << 48);
1197+
1198+
if (!strcmp(adr_dev[index].name_prefix, "AMP")) {
1199+
adr_dev[index].name_prefix = devm_kasprintf(dev, GFP_KERNEL, "%s%d",
1200+
adr_dev[index].name_prefix,
1201+
*amp_index);
1202+
if (!adr_dev[index].name_prefix)
1203+
return NULL;
1204+
(*amp_index)++;
1205+
}
1206+
1207+
if (!strcmp(adr_dev[index].name_prefix, "Left")) {
1208+
/* Convert the second amp name_prefix to Right */
1209+
if ((*amp_index) == 2) {
1210+
adr_dev[index].name_prefix = devm_kasprintf(dev, GFP_KERNEL,
1211+
"%s", "Right");
1212+
if (!adr_dev[index].name_prefix)
1213+
return NULL;
1214+
}
1215+
/* Set the name_fix to AMP<amp_index> if there are more than 2 amps */
1216+
if (*amp_index > 2) {
1217+
adr_dev[index].name_prefix = devm_kasprintf(dev, GFP_KERNEL, "%s%d",
1218+
"AMP", *amp_index);
1219+
if (!adr_dev[index].name_prefix)
1220+
return NULL;
1221+
}
1222+
(*amp_index)++;
1223+
}
1224+
1225+
dev_dbg(dev, "adr[%d] 0x%llx link id %d name_prefix \"%s\" is found\n",
1226+
index, adr_dev[index].adr, sdw_device->bus->link_id, adr_dev[index].name_prefix);
1227+
1228+
link->num_adr++;
1229+
1230+
return adr_dev;
1231+
}
1232+
11201233
static struct snd_soc_acpi_mach *hda_sdw_machine_select(struct snd_sof_dev *sdev)
11211234
{
11221235
struct snd_sof_pdata *pdata = sdev->pdata;
11231236
const struct snd_soc_acpi_link_adr *link;
1237+
struct snd_soc_acpi_link_adr *links;
11241238
struct sdw_peripherals *peripherals;
11251239
struct snd_soc_acpi_mach *mach;
11261240
struct sof_intel_hda_dev *hdev;
1241+
int amp_index = 1;
1242+
int link_index;
11271243
u32 link_mask;
11281244
int i;
11291245

@@ -1201,7 +1317,39 @@ static struct snd_soc_acpi_mach *hda_sdw_machine_select(struct snd_sof_dev *sdev
12011317
peripherals->array[i]->id.part_id,
12021318
peripherals->array[i]->id.sdw_version);
12031319

1204-
return NULL;
1320+
if (!peripherals->num_peripherals)
1321+
return NULL;
1322+
1323+
/* Create default SDW mach */
1324+
mach = devm_kzalloc(sdev->dev, sizeof(*mach), GFP_KERNEL);
1325+
if (!mach)
1326+
return NULL;
1327+
1328+
links = devm_kcalloc(sdev->dev, peripherals->num_peripherals, sizeof(*links), GFP_KERNEL);
1329+
if (!links)
1330+
return NULL;
1331+
1332+
link_mask = 0;
1333+
link_index = 0;
1334+
for (i = 0; i < peripherals->num_peripherals; i++) {
1335+
links[link_index].adr_d = find_acpi_adr_device(sdev->dev, peripherals->array[i],
1336+
&links[link_index], &amp_index);
1337+
link_mask |= links[link_index].mask;
1338+
1339+
if (i < peripherals->num_peripherals - 1 &&
1340+
peripherals->array[i + 1]->bus->link_id != peripherals->array[i]->bus->link_id)
1341+
link_index++;
1342+
}
1343+
1344+
mach->drv_name = "sof_sdw";
1345+
mach->sof_tplg_filename = "sof-sdw-generic.tplg";
1346+
mach->mach_params.links = links;
1347+
mach->mach_params.link_mask = link_mask;
1348+
mach->mach_params.platform = dev_name(sdev->dev);
1349+
mach->get_function_tplg_files = sof_sdw_get_tplg_files;
1350+
dev_info(sdev->dev, "Use default SDW machine driver %s topology: %s\n",
1351+
mach->drv_name, mach->sof_tplg_filename);
1352+
return mach;
12051353
}
12061354
#else
12071355
static struct snd_soc_acpi_mach *hda_sdw_machine_select(struct snd_sof_dev *sdev)
@@ -1529,6 +1677,7 @@ MODULE_IMPORT_NS("SND_SOC_SOF_XTENSA");
15291677
MODULE_IMPORT_NS("SND_INTEL_SOUNDWIRE_ACPI");
15301678
MODULE_IMPORT_NS("SOUNDWIRE_INTEL_INIT");
15311679
MODULE_IMPORT_NS("SOUNDWIRE_INTEL");
1680+
MODULE_IMPORT_NS("SND_SOC_SDW_UTILS");
15321681
MODULE_IMPORT_NS("SND_SOC_SOF_HDA_MLINK");
15331682
MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_HDA_COMMON");
15341683
MODULE_IMPORT_NS("SND_SOC_ACPI_INTEL_MATCH");

0 commit comments

Comments
 (0)