sound/hda/controllers/acpi.c

Source file repositories/reference/linux-study-clean/sound/hda/controllers/acpi.c

File Facts

System
Linux kernel
Corpus path
sound/hda/controllers/acpi.c
Extension
.c
Size
7562 bytes
Lines
326
Domain
Driver Families
Bucket
sound/hda
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 hda_acpi {
	struct azx azx;
	struct snd_card *card;
	struct platform_device *pdev;
	void __iomem *regs;
	struct work_struct probe_work;
	const struct hda_data *data;
};

/**
 * struct hda_data - Optional device-specific data
 * @short_name: Used for the ALSA card name; defaults to KBUILD_MODNAME
 * @long_name:  Used for longer description; defaults to short_name
 * @flags:      Passed to &azx->driver_caps
 *
 * A pointer to a record of this type may be stored in the
 * &acpi_device_id->driver_data field of an ACPI match table entry in order to
 * customize the naming and behavior of a particular device. All fields are
 * optional and sensible defaults will be selected in their absence.
 */
struct hda_data {
	const char *short_name;
	const char *long_name;
	unsigned long flags;
};

static int hda_acpi_dev_disconnect(struct snd_device *device)
{
	struct azx *chip = device->device_data;

	chip->bus.shutdown = 1;
	return 0;
}

static int hda_acpi_dev_free(struct snd_device *device)
{
	struct azx *azx = device->device_data;
	struct hda_acpi *hda = container_of(azx, struct hda_acpi, azx);

	cancel_work_sync(&hda->probe_work);
	if (azx_bus(azx)->chip_init) {
		azx_stop_all_streams(azx);
		azx_stop_chip(azx);
	}

	azx_free_stream_pages(azx);
	azx_free_streams(azx);
	snd_hdac_bus_exit(azx_bus(azx));

	return 0;
}

static int hda_acpi_init(struct hda_acpi *hda)
{
	struct hdac_bus *bus = azx_bus(&hda->azx);
	struct snd_card *card = hda->azx.card;
	struct device *dev = &hda->pdev->dev;
	struct azx *azx = &hda->azx;
	struct resource *res;
	unsigned short gcap;
	const char *sname, *lname;
	int err, irq;

	/* The base address for the HDA registers and the interrupt are wrapped
	 * in an ACPI _CRS object which can be parsed by platform_get_irq() and
	 * devm_platform_get_and_ioremap_resource()
	 */

	irq = platform_get_irq(hda->pdev, 0);
	if (irq < 0)
		return irq;

	hda->regs = devm_platform_get_and_ioremap_resource(hda->pdev, 0, &res);
	if (IS_ERR(hda->regs))
		return PTR_ERR(hda->regs);

	bus->remap_addr = hda->regs;
	bus->addr = res->start;

	err = devm_request_irq(dev, irq, azx_interrupt,
			       IRQF_SHARED, KBUILD_MODNAME, azx);
	if (err) {
		dev_err(dev, "unable to request IRQ %d, disabling device\n",
			irq);
		return err;
	}
	bus->irq = irq;
	bus->dma_stop_delay = 100;
	card->sync_irq = bus->irq;

Annotation

Implementation Notes