Skip to content

Commit 3e74fdd

Browse files
committed
ASoC: SOF: topology: skip feature topologies without matching BE DAI links
Before loading a user-specified feature topology, verify that the card has a matching BE DAI link. Feature topologies extend specific codec function types (amp, jack, mic) and reference widgets that only exist when the corresponding BE DAI links are present. Without this check, loading an amplifier feature topology on a card without SmartAmp DAI links would fail with -EINVAL due to missing route endpoints, killing the entire card probe. This is needed for multi-card configurations where cards are split by function type, but also provides a safety net in single-card mode when feature topologies don't match the hardware. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
1 parent 3ef4c73 commit 3e74fdd

1 file changed

Lines changed: 59 additions & 4 deletions

File tree

sound/soc/sof/topology.c

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2516,6 +2516,47 @@ static const struct snd_soc_tplg_ops sof_dspless_tplg_ops = {
25162516
.bytes_ext_ops_count = ARRAY_SIZE(sof_dspless_bytes_ext_ops),
25172517
};
25182518

2519+
/*
2520+
* Check if a feature topology is compatible with the current card by
2521+
* verifying that matching BE DAI links exist.
2522+
*
2523+
* Feature topologies extend specific codec function types. If the card
2524+
* doesn't have the corresponding BE DAI links, the topology load would
2525+
* fail due to missing routes/widgets. This works transparently for both
2526+
* multi-card and single-card configurations.
2527+
*/
2528+
static bool
2529+
sof_feature_tplg_matches_card(struct snd_soc_component *scomp,
2530+
const char *feature_tplg)
2531+
{
2532+
static const struct {
2533+
const char *tplg_key; /* substring in feature topology filename */
2534+
const char *dai_key; /* substring in BE DAI link name */
2535+
} match_table[] = {
2536+
{ "amp", "SmartAmp" },
2537+
{ "jack", "SimpleJack" },
2538+
{ "mic", "SmartMic" },
2539+
};
2540+
struct snd_soc_dai_link *dai_link;
2541+
bool needs_match = false;
2542+
int i, j;
2543+
2544+
for (i = 0; i < ARRAY_SIZE(match_table); i++) {
2545+
if (!strstr(feature_tplg, match_table[i].tplg_key))
2546+
continue;
2547+
2548+
needs_match = true;
2549+
2550+
for_each_card_prelinks(scomp->card, j, dai_link) {
2551+
if (strstr(dai_link->name, match_table[i].dai_key))
2552+
return true;
2553+
}
2554+
}
2555+
2556+
/* Unknown feature type: load it (backwards compatible) */
2557+
return !needs_match;
2558+
}
2559+
25192560
int snd_sof_load_topology(struct snd_soc_component *scomp, const char *file)
25202561
{
25212562
struct sof_client_dev *cdev = snd_sof_component_get_cdev(scomp);
@@ -2612,11 +2653,25 @@ int snd_sof_load_topology(struct snd_soc_component *scomp, const char *file)
26122653
}
26132654
}
26142655

2615-
/* Loading user defined topologies */
2656+
/*
2657+
* Loading user defined feature topologies.
2658+
* Each feature topology extends a specific function type (amp, jack,
2659+
* mic, etc.). Only load if the card has a matching BE DAI link,
2660+
* otherwise the routes would fail due to missing widgets.
2661+
*/
26162662
for (i = 0; i < feature_tplg_cnt; i++) {
2617-
const char *feature_topology = devm_kasprintf(scomp->dev, GFP_KERNEL, "%s/%s",
2618-
tplg_filename_prefix,
2619-
feature_topologies[i]);
2663+
const char *feature_topology;
2664+
2665+
if (!sof_feature_tplg_matches_card(scomp, feature_topologies[i])) {
2666+
dev_dbg(scomp->dev,
2667+
"skip feature topology %s: no matching BE DAI link\n",
2668+
feature_topologies[i]);
2669+
continue;
2670+
}
2671+
2672+
feature_topology = devm_kasprintf(scomp->dev, GFP_KERNEL, "%s/%s",
2673+
tplg_filename_prefix,
2674+
feature_topologies[i]);
26202675

26212676
if (!feature_topology) {
26222677
ret = -ENOMEM;

0 commit comments

Comments
 (0)