Skip to content

Commit 1deb725

Browse files
committed
ASoC: SOF: topology: load multiple topologies
Get device information from dai links and load topology for each device. This allow user create a topology for single device. The driver will select the needed topologies and we don't need to create topologies for each product. Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
1 parent 5aea65f commit 1deb725

1 file changed

Lines changed: 129 additions & 2 deletions

File tree

sound/soc/sof/topology.c

Lines changed: 129 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <linux/errno.h>
1414
#include <linux/firmware.h>
1515
#include <linux/workqueue.h>
16+
#include <sound/soc_sdw_utils.h>
1617
#include <sound/tlv.h>
1718
#include <uapi/sound/sof/tokens.h>
1819
#include "sof-priv.h"
@@ -2286,7 +2287,7 @@ static const struct snd_soc_tplg_bytes_ext_ops sof_bytes_ext_ops[] = {
22862287
{SOF_TPLG_KCTL_BYTES_VOLATILE_RO, snd_sof_bytes_ext_volatile_get},
22872288
};
22882289

2289-
static const struct snd_soc_tplg_ops sof_tplg_ops = {
2290+
static struct snd_soc_tplg_ops sof_tplg_ops = {
22902291
/* external kcontrol init - used for any driver specific init */
22912292
.control_load = sof_control_load,
22922293
.control_unload = sof_control_unload,
@@ -2309,7 +2310,7 @@ static const struct snd_soc_tplg_ops sof_tplg_ops = {
23092310
.link_unload = sof_link_unload,
23102311

23112312
/* completion - called at completion of firmware loading */
2312-
.complete = sof_complete,
2313+
/* complete will be added in the last tplg ops */
23132314

23142315
/* manifest - optional to inform component of manifest */
23152316
.manifest = sof_manifest,
@@ -2462,14 +2463,138 @@ static const struct snd_soc_tplg_ops sof_dspless_tplg_ops = {
24622463
.bytes_ext_ops_count = ARRAY_SIZE(sof_dspless_bytes_ext_ops),
24632464
};
24642465

2466+
#define MAX_TPLG_NUM 5
2467+
2468+
enum tplg_device_id {
2469+
TPLG_DEVICE_SDW_JACK,
2470+
TPLG_DEVICE_SDW_AMP,
2471+
TPLG_DEVICE_SDW_MIC,
2472+
TPLG_DEVICE_HOST_DMIC,
2473+
TPLG_DEVICE_HDMI,
2474+
};
2475+
2476+
struct topology_file {
2477+
char *device;
2478+
char *file;
2479+
int be_id;
2480+
};
2481+
24652482
int snd_sof_load_topology(struct snd_soc_component *scomp, const char *file)
24662483
{
24672484
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
2485+
struct snd_sof_pdata *sof_pdata = sdev->pdata;
2486+
struct topology_file tplg_files[MAX_TPLG_NUM];
2487+
struct snd_soc_dai_link *dai_link;
2488+
char platform[4];
2489+
bool load_default_tplg = false;
2490+
unsigned long tplg_mask = 0;
24682491
const struct firmware *fw;
2492+
int tplg_num = 0;
2493+
int tplg_dev;
24692494
int ret;
2495+
int i;
24702496

24712497
dev_dbg(scomp->dev, "loading topology:%s\n", file);
24722498

2499+
sscanf(sof_pdata->tplg_filename, "sof-%3s-*.tplg", platform);
2500+
2501+
if (sdev->pdata->ipc_type == SOF_IPC_TYPE_3)
2502+
goto legacy_tplg;
2503+
2504+
for_each_card_prelinks(scomp->card, i, dai_link) {
2505+
char *tplg_device;
2506+
2507+
dev_dbg(scomp->dev, "dai_link %s id %d\n", dai_link->name, dai_link->id);
2508+
if (strstr(dai_link->name, "SimpleJack")) {
2509+
tplg_dev = TPLG_DEVICE_SDW_JACK;
2510+
tplg_device = "sdca-jack";
2511+
} else if (strstr(dai_link->name, "SmartAmp")) {
2512+
tplg_dev = TPLG_DEVICE_SDW_AMP;
2513+
tplg_device = "sdca-amp";
2514+
} else if (strstr(dai_link->name, "SmartMic")) {
2515+
tplg_dev |= TPLG_DEVICE_SDW_MIC;
2516+
tplg_device = "sdca-mic";
2517+
} else if (strstr(dai_link->name, "SDW")) {
2518+
int sdw_link;
2519+
2520+
sscanf(dai_link->name, "SDW%d", &sdw_link);
2521+
/* detect SDW device by dai_link id */
2522+
switch (dai_link->id) {
2523+
case SOC_SDW_JACK_OUT_DAI_ID:
2524+
case SOC_SDW_JACK_IN_DAI_ID:
2525+
tplg_dev = TPLG_DEVICE_SDW_JACK;
2526+
tplg_device = devm_kasprintf(sdev->dev, GFP_KERNEL,
2527+
"sdw%d-jack", sdw_link);
2528+
break;
2529+
case SOC_SDW_AMP_OUT_DAI_ID:
2530+
case SOC_SDW_AMP_IN_DAI_ID:
2531+
tplg_dev = TPLG_DEVICE_SDW_AMP;
2532+
tplg_device = devm_kasprintf(sdev->dev, GFP_KERNEL,
2533+
"sdw%d-amp", sdw_link);
2534+
break;
2535+
case SOC_SDW_DMIC_DAI_ID:
2536+
tplg_dev = TPLG_DEVICE_SDW_MIC;
2537+
tplg_device = devm_kasprintf(sdev->dev, GFP_KERNEL,
2538+
"sdw%d-mic", sdw_link);
2539+
break;
2540+
2541+
}
2542+
} else if (strstr(dai_link->name, "DMIC")) {
2543+
tplg_mask = TPLG_DEVICE_HOST_DMIC;
2544+
tplg_device = "host-dmic";
2545+
} else if (strstr(dai_link->name, "iDisp")) {
2546+
tplg_dev = TPLG_DEVICE_HDMI;
2547+
tplg_device = "hdmi";
2548+
} else {
2549+
/* The dai link is not supported by sperated tplg yet */
2550+
load_default_tplg = true;
2551+
continue;
2552+
}
2553+
if (tplg_mask & BIT(tplg_dev))
2554+
continue;
2555+
tplg_mask |= BIT(tplg_dev);
2556+
tplg_files[tplg_num].be_id = dai_link->id;
2557+
tplg_files[tplg_num].device = tplg_device;
2558+
tplg_num++;
2559+
}
2560+
dev_dbg(scomp->dev, "tplg_mask %#lx tplg_num %d\n", tplg_mask, tplg_num);
2561+
2562+
for (i = 0; i < tplg_num; i++) {
2563+
tplg_files[i].file = devm_kasprintf(sdev->dev, GFP_KERNEL,
2564+
"%s/sof-%s-%s-id%d.tplg",
2565+
sof_pdata->tplg_filename_prefix, platform,
2566+
tplg_files[i].device,
2567+
tplg_files[i].be_id);
2568+
ret = request_firmware(&fw, tplg_files[i].file, scomp->dev);
2569+
dev_dbg(scomp->dev, "Requesting %d %s\n", i, tplg_files[i].file);
2570+
if (ret < 0) {
2571+
dev_warn(scomp->dev, "error: tplg request firmware %s failed err: %d\n",
2572+
tplg_files[i].file, ret);
2573+
dev_warn(scomp->dev,"Fail back to the default topology\n");
2574+
goto legacy_tplg;
2575+
}
2576+
/* set complete = sof_complete if it is the last topology */
2577+
if (!load_default_tplg && i == tplg_num - 1)
2578+
sof_tplg_ops.complete = sof_complete;
2579+
if (sdev->dspless_mode_selected)
2580+
ret = snd_soc_tplg_component_load(scomp, &sof_dspless_tplg_ops, fw);
2581+
else
2582+
ret = snd_soc_tplg_component_load(scomp, &sof_tplg_ops, fw);
2583+
2584+
if (ret < 0) {
2585+
dev_err(scomp->dev, "error: tplg component load failed %d\n",
2586+
ret);
2587+
release_firmware(fw);
2588+
return -EINVAL;
2589+
}
2590+
2591+
release_firmware(fw);
2592+
}
2593+
/* Load topology successfully, goto out */
2594+
if (!load_default_tplg)
2595+
goto out;
2596+
2597+
legacy_tplg:
24732598
ret = request_firmware(&fw, file, scomp->dev);
24742599
if (ret < 0) {
24752600
dev_err(scomp->dev, "error: tplg request firmware %s failed err: %d\n",
@@ -2479,6 +2604,7 @@ int snd_sof_load_topology(struct snd_soc_component *scomp, const char *file)
24792604
return ret;
24802605
}
24812606

2607+
sof_tplg_ops.complete = sof_complete;
24822608
if (sdev->dspless_mode_selected)
24832609
ret = snd_soc_tplg_component_load(scomp, &sof_dspless_tplg_ops, fw);
24842610
else
@@ -2492,6 +2618,7 @@ int snd_sof_load_topology(struct snd_soc_component *scomp, const char *file)
24922618

24932619
release_firmware(fw);
24942620

2621+
out:
24952622
if (ret >= 0 && sdev->led_present)
24962623
ret = snd_ctl_led_request();
24972624

0 commit comments

Comments
 (0)