157 lines · 4.4 KB · C
RawDownload
// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)//// This file is provided under a dual BSD/GPLv2 license.  When using or// redistributing this file, you may do so under either license.//// Copyright(c) 2025 Intel Corporation.// #include <linux/device.h>#include <linux/errno.h>#include <linux/firmware.h>#include <sound/soc.h>#include <sound/soc-acpi.h>#include "sof-function-topology-lib.h" enum tplg_device_id {	TPLG_DEVICE_SDCA_JACK,	TPLG_DEVICE_SDCA_AMP,	TPLG_DEVICE_SDCA_MIC,	TPLG_DEVICE_INTEL_PCH_DMIC,	TPLG_DEVICE_HDMI,	TPLG_DEVICE_LOOPBACK_VIRTUAL,	TPLG_DEVICE_MAX}; #define SDCA_DEVICE_MASK (BIT(TPLG_DEVICE_SDCA_JACK) | BIT(TPLG_DEVICE_SDCA_AMP) | \			  BIT(TPLG_DEVICE_SDCA_MIC)) #define SOF_INTEL_PLATFORM_NAME_MAX 4 int sof_sdw_get_tplg_files(struct snd_soc_card *card, const struct snd_soc_acpi_mach *mach,			   const char *prefix, const char ***tplg_files, bool best_effort){	struct snd_soc_acpi_mach *card_mach = dev_get_platdata(card->dev);	/*	 * Use the acpi mach from the machine driver because the machine driver	 * may change the dmic_num based on the machine driver quirk.	 */	struct snd_soc_acpi_mach_params mach_params = card_mach->mach_params;	struct snd_soc_dai_link *dai_link;	const struct firmware *fw;	char platform[SOF_INTEL_PLATFORM_NAME_MAX];	unsigned long tplg_mask = 0;	int tplg_num = 0;	int tplg_dev;	int ret;	int i; 	ret = sscanf(mach->sof_tplg_filename, "sof-%3s-*.tplg", platform);	if (ret != 1) {		dev_err(card->dev, "Invalid platform name %s of tplg %s\n",			platform, mach->sof_tplg_filename);		return -EINVAL;	} 	for_each_card_prelinks(card, i, dai_link) {		char *tplg_dev_name; 		dev_dbg(card->dev, "dai_link %s id %d\n", dai_link->name, dai_link->id);		if (strstr(dai_link->name, "SimpleJack")) {			tplg_dev = TPLG_DEVICE_SDCA_JACK;			tplg_dev_name = "sdca-jack";		} else if (strstr(dai_link->name, "SmartAmp")) {			tplg_dev = TPLG_DEVICE_SDCA_AMP;			tplg_dev_name = devm_kasprintf(card->dev, GFP_KERNEL,						       "sdca-%damp", dai_link->num_cpus);			if (!tplg_dev_name)				return -ENOMEM;		} else if (strstr(dai_link->name, "SmartMic")) {			tplg_dev = TPLG_DEVICE_SDCA_MIC;			tplg_dev_name = "sdca-mic";		} else if (strstr(dai_link->name, "dmic")) {			switch (mach_params.dmic_num) {			case 2:				tplg_dev_name = "dmic-2ch";				break;			case 4:				tplg_dev_name = "dmic-4ch";				break;			default:				dev_warn(card->dev,					 "unsupported number of dmics: %d\n",					 mach_params.dmic_num);				continue;			}			tplg_dev = TPLG_DEVICE_INTEL_PCH_DMIC;		} else if (strstr(dai_link->name, "iDisp")) {			tplg_dev = TPLG_DEVICE_HDMI;			tplg_dev_name = "hdmi-pcm5";		} else if (strstr(dai_link->name, "Loopback_Virtual")) {			tplg_dev = TPLG_DEVICE_LOOPBACK_VIRTUAL;			/*			 * Mark the LOOPBACK_VIRTUAL device but no need to create the			 * LOOPBACK_VIRTUAL topology. Just to avoid the dai_link is not supported			 * error.			 */			tplg_mask |= BIT(tplg_dev);			continue;		} else {			/* The dai link is not supported by separated tplg yet */			dev_dbg(card->dev,				"dai_link %s is not supported by separated tplg yet\n",				dai_link->name);			if (best_effort)				continue; 			return 0;		}		if (tplg_mask & BIT(tplg_dev))			continue; 		tplg_mask |= BIT(tplg_dev); 		/*		 * The tplg file naming rule is sof-<platform>-<function>-id<BE id number>.tplg		 * where <platform> is only required for the DMIC function as the nhlt blob		 * is platform dependent.		 */		switch (tplg_dev) {		case TPLG_DEVICE_INTEL_PCH_DMIC:			(*tplg_files)[tplg_num] = devm_kasprintf(card->dev, GFP_KERNEL,								 "%s/sof-%s-%s-id%d.tplg",								 prefix, platform,								 tplg_dev_name, dai_link->id);			break;		default:			(*tplg_files)[tplg_num] = devm_kasprintf(card->dev, GFP_KERNEL,								 "%s/sof-%s-id%d.tplg",								 prefix, tplg_dev_name,								 dai_link->id);			break;		}		if (!(*tplg_files)[tplg_num])			return -ENOMEM;		tplg_num++;	} 	dev_dbg(card->dev, "tplg_mask %#lx tplg_num %d\n", tplg_mask, tplg_num); 	/* Check presence of sub-topologies */	for (i = 0; i < tplg_num; i++) {		ret = firmware_request_nowarn(&fw, (*tplg_files)[i], card->dev);		if (!ret) {			release_firmware(fw);		} else {			dev_warn(card->dev,				 "Failed to open topology file: %s, you might need to\n",				 (*tplg_files)[i]);			dev_warn(card->dev,				 "download it from https://github.com/thesofproject/sof-bin/\n");			return 0;		}	} 	return tplg_num;}EXPORT_SYMBOL_GPL(sof_sdw_get_tplg_files);