sound/soc/sof/fw-file-profile.c

Source file repositories/reference/linux-study-clean/sound/soc/sof/fw-file-profile.c

File Facts

System
Linux kernel
Corpus path
sound/soc/sof/fw-file-profile.c
Extension
.c
Size
9951 bytes
Lines
346
Domain
Driver Families
Bucket
sound/soc
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

sof_platform_uses_generic_loader(sdev)) {
		ret = sof_test_firmware_file(dev, out_profile, &ipc_type);
		if (ret)
			return ret;

		if (!(desc->ipc_supported_mask & BIT(ipc_type))) {
			dev_err(dev, "Unsupported IPC type %d needed by %s/%s\n",
				ipc_type, out_profile->fw_path,
				out_profile->fw_name);
			return -EINVAL;
		}
	}

	/* firmware library path */
	if (base_profile->fw_lib_path) {
		out_profile->fw_lib_path = base_profile->fw_lib_path;
	} else if (desc->default_lib_path[ipc_type]) {
		if (base_profile->fw_lib_path_postfix) {
			out_profile->fw_lib_path = devm_kasprintf(dev,
							GFP_KERNEL, "%s/%s",
							desc->default_lib_path[ipc_type],
							base_profile->fw_lib_path_postfix);
			if (!out_profile->fw_lib_path) {
				ret = -ENOMEM;
				goto out;
			}

			fw_lib_path_allocated = true;
		} else {
			out_profile->fw_lib_path = desc->default_lib_path[ipc_type];
		}
	}

	if (base_profile->fw_path_postfix)
		out_profile->fw_path_postfix = base_profile->fw_path_postfix;

	if (base_profile->fw_lib_path_postfix)
		out_profile->fw_lib_path_postfix = base_profile->fw_lib_path_postfix;

	/* topology path */
	if (base_profile->tplg_path)
		out_profile->tplg_path = base_profile->tplg_path;
	else
		out_profile->tplg_path = desc->default_tplg_path[ipc_type];

	/* topology name */
	out_profile->tplg_name = plat_data->tplg_filename;

	out_profile->ipc_type = ipc_type;

	/* Test only default firmware file */
	if ((!base_profile->fw_path && !base_profile->fw_name) &&
	    sof_platform_uses_generic_loader(sdev))
		ret = sof_test_firmware_file(dev, out_profile, NULL);

	if (!ret)
		ret = sof_test_topology_file(dev, out_profile);

out:
	if (ret) {
		/* Free up path strings created with devm_kasprintf */
		if (fw_path_allocated)
			devm_kfree(dev, out_profile->fw_path);
		if (fw_lib_path_allocated)
			devm_kfree(dev, out_profile->fw_lib_path);

		memset(out_profile, 0, sizeof(*out_profile));
	}

	return ret;
}

static void
sof_print_missing_firmware_info(struct snd_sof_dev *sdev,
				enum sof_ipc_type ipc_type,
				struct sof_loadable_file_profile *base_profile)
{
	struct snd_sof_pdata *plat_data = sdev->pdata;
	const struct sof_dev_desc *desc = plat_data->desc;
	struct device *dev = sdev->dev;
	int ipc_type_count, i;
	char *marker;

	dev_err(dev, "SOF firmware and/or topology file not found.\n");
	dev_info(dev, "Supported default profiles\n");

	if (IS_ENABLED(CONFIG_SND_SOC_SOF_ALLOW_FALLBACK_TO_NEWER_IPC_VERSION))
		ipc_type_count = SOF_IPC_TYPE_COUNT - 1;
	else
		ipc_type_count = base_profile->ipc_type;

Annotation

Implementation Notes