sound/soc/sof/ipc4-loader.c

Source file repositories/reference/linux-study-clean/sound/soc/sof/ipc4-loader.c

File Facts

System
Linux kernel
Corpus path
sound/soc/sof/ipc4-loader.c
Extension
.c
Size
17777 bytes
Lines
617
Domain
Driver Families
Bucket
sound/soc
Inferred role
Driver Families: implementation source
Status
source 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

if (fm_entry->cfg_count) {
			if (remaining < (fm_entry->cfg_offset + fm_entry->cfg_count) *
			    sizeof(*fm_config)) {
				dev_err(sdev->dev, "Invalid module cfg_offset %u\n",
					fm_entry->cfg_offset);
				return -EINVAL;
			}

			fw_module->fw_mod_cfg = &fm_config[fm_entry->cfg_offset];

			dev_dbg(sdev->dev,
				"module %s: UUID %pUL cfg_count: %u, bss_size: %#x\n",
				fm_entry->name, &fm_entry->uuid, fm_entry->cfg_count,
				fm_config[fm_entry->cfg_offset].is_bytes);
		} else {
			dev_dbg(sdev->dev, "module %s: UUID %pUL\n", fm_entry->name,
				&fm_entry->uuid);
		}

		fw_module->man4_module_entry.id = i;
		ida_init(&fw_module->m_ida);
		fw_module->private = NULL;

		fw_module++;
		fm_entry++;
	}

	return ext_man_hdr->len;
}

static size_t sof_ipc4_fw_parse_basefw_ext_man(struct snd_sof_dev *sdev)
{
	struct sof_ipc4_fw_data *ipc4_data = sdev->private;
	struct sof_ipc4_fw_library *fw_lib;
	ssize_t payload_offset;
	int ret;

	fw_lib = devm_kzalloc(sdev->dev, sizeof(*fw_lib), GFP_KERNEL);
	if (!fw_lib)
		return -ENOMEM;

	fw_lib->sof_fw.fw = sdev->basefw.fw;

	payload_offset = sof_ipc4_fw_parse_ext_man(sdev, fw_lib);
	if (payload_offset > 0) {
		fw_lib->sof_fw.payload_offset = payload_offset;

		/* basefw ID is 0 */
		fw_lib->id = 0;
		ret = xa_insert(&ipc4_data->fw_lib_xa, 0, fw_lib, GFP_KERNEL);
		if (ret)
			return ret;
	}

	return payload_offset;
}

static int sof_ipc4_load_library(struct snd_sof_dev *sdev, unsigned long lib_id,
				 const char *lib_filename, bool optional)
{
	struct sof_ipc4_fw_data *ipc4_data = sdev->private;
	struct sof_ipc4_fw_library *fw_lib;
	ssize_t payload_offset;
	int ret, i;

	if (!ipc4_data->load_library) {
		dev_err(sdev->dev, "Library loading is not supported on this platform\n");
		return -EOPNOTSUPP;
	}

	fw_lib = devm_kzalloc(sdev->dev, sizeof(*fw_lib), GFP_KERNEL);
	if (!fw_lib)
		return -ENOMEM;

	if (optional) {
		ret = firmware_request_nowarn(&fw_lib->sof_fw.fw, lib_filename,
					      sdev->dev);
		if (ret < 0) {
			/* optional library, override the error */
			ret = 0;
			goto free_fw_lib;
		}
	} else {
		ret = request_firmware(&fw_lib->sof_fw.fw, lib_filename,
				       sdev->dev);
		if (ret < 0) {
			dev_err(sdev->dev, "Library file '%s' is missing\n",
				lib_filename);
			goto free_fw_lib;
		}

Annotation

Implementation Notes