sound/soc/intel/avs/loader.c

Source file repositories/reference/linux-study-clean/sound/soc/intel/avs/loader.c

File Facts

System
Linux kernel
Corpus path
sound/soc/intel/avs/loader.c
Extension
.c
Size
19402 bytes
Lines
751
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

struct avs_fw_manifest {
	u32 id;
	u32 len;
	char name[AVS_LIB_NAME_SIZE];
	u32 preload_page_count;
	u32 img_flags;
	u32 feature_mask;
	struct avs_fw_version version;
} __packed;
static_assert(sizeof(struct avs_fw_manifest) == 36);

struct avs_fw_ext_manifest {
	u32 id;
	u32 len;
	u16 version_major;
	u16 version_minor;
	u32 entries;
} __packed;
static_assert(sizeof(struct avs_fw_ext_manifest) == 16);

static int avs_fw_ext_manifest_strip(struct firmware *fw)
{
	struct avs_fw_ext_manifest *man;

	if (fw->size < sizeof(*man))
		return -EINVAL;

	man = (struct avs_fw_ext_manifest *)fw->data;
	if (man->id == AVS_EXT_MANIFEST_MAGIC) {
		fw->data += man->len;
		fw->size -= man->len;
	}

	return 0;
}

static int avs_fw_manifest_offset(struct firmware *fw)
{
	/* Header type found in first DWORD of fw binary. */
	u32 magic = *(u32 *)fw->data;

	switch (magic) {
	case SKL_MANIFEST_MAGIC:
		return SKL_ADSPFW_OFFSET;
	case APL_MANIFEST_MAGIC:
		return APL_ADSPFW_OFFSET;
	default:
		return -EINVAL;
	}
}

static int avs_fw_manifest_strip_verify(struct avs_dev *adev, struct firmware *fw,
					const struct avs_fw_version *min)
{
	struct avs_fw_manifest *man;
	int offset, ret;

	ret = avs_fw_ext_manifest_strip(fw);
	if (ret)
		return ret;

	offset = avs_fw_manifest_offset(fw);
	if (offset < 0)
		return offset;

	if (fw->size < offset + sizeof(*man))
		return -EINVAL;
	if (!min)
		return 0;

	man = (struct avs_fw_manifest *)(fw->data + offset);
	if (man->version.major != min->major ||
	    man->version.minor != min->minor ||
	    man->version.hotfix != min->hotfix ||
	    man->version.build < min->build) {
		dev_warn(adev->dev, "bad FW version %d.%d.%d.%d, expected %d.%d.%d.%d or newer\n",
			 man->version.major, man->version.minor,
			 man->version.hotfix, man->version.build,
			 min->major, min->minor, min->hotfix, min->build);

		if (!debug_ignore_fw_version)
			return -EINVAL;
	}

	return 0;
}

int avs_cldma_load_basefw(struct avs_dev *adev, struct firmware *fw)
{
	struct hda_cldma *cl = &code_loader;

Annotation

Implementation Notes