Path: blob/master/sound/soc/intel/common/sof-function-topology-lib.c
49628 views
// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)1//2// This file is provided under a dual BSD/GPLv2 license. When using or3// redistributing this file, you may do so under either license.4//5// Copyright(c) 2025 Intel Corporation.6//78#include <linux/device.h>9#include <linux/errno.h>10#include <linux/firmware.h>11#include <sound/soc.h>12#include <sound/soc-acpi.h>13#include "sof-function-topology-lib.h"1415enum tplg_device_id {16TPLG_DEVICE_SDCA_JACK,17TPLG_DEVICE_SDCA_AMP,18TPLG_DEVICE_SDCA_MIC,19TPLG_DEVICE_INTEL_PCH_DMIC,20TPLG_DEVICE_HDMI,21TPLG_DEVICE_MAX22};2324#define SDCA_DEVICE_MASK (BIT(TPLG_DEVICE_SDCA_JACK) | BIT(TPLG_DEVICE_SDCA_AMP) | \25BIT(TPLG_DEVICE_SDCA_MIC))2627#define SOF_INTEL_PLATFORM_NAME_MAX 42829int sof_sdw_get_tplg_files(struct snd_soc_card *card, const struct snd_soc_acpi_mach *mach,30const char *prefix, const char ***tplg_files, bool best_effort)31{32struct snd_soc_acpi_mach_params mach_params = mach->mach_params;33struct snd_soc_dai_link *dai_link;34const struct firmware *fw;35char platform[SOF_INTEL_PLATFORM_NAME_MAX];36unsigned long tplg_mask = 0;37int tplg_num = 0;38int tplg_dev;39int ret;40int i;4142ret = sscanf(mach->sof_tplg_filename, "sof-%3s-*.tplg", platform);43if (ret != 1) {44dev_err(card->dev, "Invalid platform name %s of tplg %s\n",45platform, mach->sof_tplg_filename);46return -EINVAL;47}4849for_each_card_prelinks(card, i, dai_link) {50char *tplg_dev_name;5152dev_dbg(card->dev, "dai_link %s id %d\n", dai_link->name, dai_link->id);53if (strstr(dai_link->name, "SimpleJack")) {54tplg_dev = TPLG_DEVICE_SDCA_JACK;55tplg_dev_name = "sdca-jack";56} else if (strstr(dai_link->name, "SmartAmp")) {57tplg_dev = TPLG_DEVICE_SDCA_AMP;58tplg_dev_name = devm_kasprintf(card->dev, GFP_KERNEL,59"sdca-%damp", dai_link->num_cpus);60if (!tplg_dev_name)61return -ENOMEM;62} else if (strstr(dai_link->name, "SmartMic")) {63tplg_dev = TPLG_DEVICE_SDCA_MIC;64tplg_dev_name = "sdca-mic";65} else if (strstr(dai_link->name, "dmic")) {66switch (mach_params.dmic_num) {67case 2:68tplg_dev_name = "dmic-2ch";69break;70case 4:71tplg_dev_name = "dmic-4ch";72break;73default:74dev_warn(card->dev,75"unsupported number of dmics: %d\n",76mach_params.dmic_num);77continue;78}79tplg_dev = TPLG_DEVICE_INTEL_PCH_DMIC;80} else if (strstr(dai_link->name, "iDisp")) {81tplg_dev = TPLG_DEVICE_HDMI;82tplg_dev_name = "hdmi-pcm5";8384} else {85/* The dai link is not supported by separated tplg yet */86dev_dbg(card->dev,87"dai_link %s is not supported by separated tplg yet\n",88dai_link->name);89if (best_effort)90continue;9192return 0;93}94if (tplg_mask & BIT(tplg_dev))95continue;9697tplg_mask |= BIT(tplg_dev);9899/*100* The tplg file naming rule is sof-<platform>-<function>-id<BE id number>.tplg101* where <platform> is only required for the DMIC function as the nhlt blob102* is platform dependent.103*/104switch (tplg_dev) {105case TPLG_DEVICE_INTEL_PCH_DMIC:106(*tplg_files)[tplg_num] = devm_kasprintf(card->dev, GFP_KERNEL,107"%s/sof-%s-%s-id%d.tplg",108prefix, platform,109tplg_dev_name, dai_link->id);110break;111default:112(*tplg_files)[tplg_num] = devm_kasprintf(card->dev, GFP_KERNEL,113"%s/sof-%s-id%d.tplg",114prefix, tplg_dev_name,115dai_link->id);116break;117}118if (!(*tplg_files)[tplg_num])119return -ENOMEM;120tplg_num++;121}122123dev_dbg(card->dev, "tplg_mask %#lx tplg_num %d\n", tplg_mask, tplg_num);124125/* Check presence of sub-topologies */126for (i = 0; i < tplg_num; i++) {127ret = firmware_request_nowarn(&fw, (*tplg_files)[i], card->dev);128if (!ret) {129release_firmware(fw);130} else {131dev_warn(card->dev,132"Failed to open topology file: %s, you might need to\n",133(*tplg_files)[i]);134dev_warn(card->dev,135"download it from https://github.com/thesofproject/sof-bin/\n");136return 0;137}138}139140return tplg_num;141}142EXPORT_SYMBOL_GPL(sof_sdw_get_tplg_files);143144145