sound/soc/sdca/sdca_fdl.c

Source file repositories/reference/linux-study-clean/sound/soc/sdca/sdca_fdl.c

File Facts

System
Linux kernel
Corpus path
sound/soc/sdca/sdca_fdl.c
Extension
.c
Size
13735 bytes
Lines
502
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

if (!time) {
				dev_dbg(dev, "no new FDL starts\n");
				nfdl--;
				continue;
			}

			time = wait_for_completion_timeout(&fdl_state->done,
							   done_timeout);
			if (!time) {
				dev_err(dev, "timed out waiting for FDL to complete\n");
				goto error;
			}
		}

		if (!nfdl)
			return 0;
	}

	dev_err(dev, "too many FDL requests\n");

error:
	for (j = 0; j < SDCA_MAX_INTERRUPTS; j++) {
		struct sdca_interrupt *interrupt = &info->irqs[j];
		struct fdl_state *fdl_state;

		if (interrupt->function != function ||
		    !interrupt->entity || !interrupt->control ||
		    interrupt->entity->type != SDCA_ENTITY_TYPE_XU ||
		    interrupt->control->sel != SDCA_CTL_XU_FDL_CURRENTOWNER)
			continue;

		disable_irq(interrupt->irq);

		fdl_state = interrupt->priv;

		sdca_ump_cancel_timeout(&fdl_state->timeout);
	}

	return -ETIMEDOUT;
}
EXPORT_SYMBOL_NS_GPL(sdca_fdl_sync, "SND_SOC_SDCA");

static char *fdl_get_sku_filename(struct device *dev,
				  struct sdca_fdl_file *fdl_file)
{
	struct device *parent = dev;
	const char *product_vendor;
	const char *product_sku;

	/*
	 * Try to find pci_dev manually because the card may not be ready to be
	 * used for snd_soc_card_get_pci_ssid yet
	 */
	while (parent) {
		if (dev_is_pci(parent)) {
			struct pci_dev *pci_dev = to_pci_dev(parent);

			return kasprintf(GFP_KERNEL, "sdca/%x/%x/%x/%x.bin",
					 fdl_file->vendor_id,
					 pci_dev->subsystem_vendor,
					 pci_dev->subsystem_device,
					 fdl_file->file_id);
		} else {
			parent = parent->parent;
		}
	}

	product_vendor = dmi_get_system_info(DMI_SYS_VENDOR);
	if (!product_vendor || !strcmp(product_vendor, "Default string"))
		product_vendor = dmi_get_system_info(DMI_BOARD_VENDOR);
	if (!product_vendor || !strcmp(product_vendor, "Default string"))
		product_vendor = dmi_get_system_info(DMI_CHASSIS_VENDOR);
	if (!product_vendor)
		product_vendor = "unknown";

	product_sku = dmi_get_system_info(DMI_PRODUCT_SKU);
	if (!product_sku || !strcmp(product_sku, "Default string"))
		product_sku = dmi_get_system_info(DMI_PRODUCT_NAME);
	if (!product_sku)
		product_sku = "unknown";

	return kasprintf(GFP_KERNEL, "sdca/%x/%s/%s/%x.bin", fdl_file->vendor_id,
			 product_vendor, product_sku, fdl_file->file_id);
}

static int fdl_load_file(struct sdca_interrupt *interrupt,
			 struct sdca_fdl_set *set, int file_index)
{
	struct device *dev = interrupt->dev;
	struct sdca_fdl_data *fdl_data = &interrupt->function->fdl_data;

Annotation

Implementation Notes