sound/hda/core/controller.c

Source file repositories/reference/linux-study-clean/sound/hda/core/controller.c

File Facts

System
Linux kernel
Corpus path
sound/hda/core/controller.c
Extension
.c
Size
20173 bytes
Lines
767
Domain
Driver Families
Bucket
sound/hda
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 (snd_hdac_chip_readw(bus, IRS) & AZX_IRS_VALID) {
			/* reuse rirb.res as the response return value */
			bus->rirb.res[addr] = snd_hdac_chip_readl(bus, IR);
			return 0;
		}
		udelay(1);
	}

	dev_dbg_ratelimited(bus->dev, "get_response_pio timeout: IRS=%#x\n",
			    snd_hdac_chip_readw(bus, IRS));

	bus->rirb.res[addr] = -1;

	return -EIO;
}

/**
 * snd_hdac_bus_send_cmd_pio - send a command verb via Immediate Command
 * @bus: HD-audio core bus
 * @val: encoded verb value to send
 *
 * Returns zero for success or a negative error code.
 */
static int snd_hdac_bus_send_cmd_pio(struct hdac_bus *bus, unsigned int val)
{
	unsigned int addr = azx_command_addr(val);
	int timeout = 50;

	guard(spinlock_irq)(&bus->reg_lock);

	while (timeout--) {
		/* check ICB bit */
		if (!((snd_hdac_chip_readw(bus, IRS) & AZX_IRS_BUSY))) {
			/* Clear IRV bit */
			snd_hdac_chip_updatew(bus, IRS, AZX_IRS_VALID, AZX_IRS_VALID);
			snd_hdac_chip_writel(bus, IC, val);
			/* Set ICB bit */
			snd_hdac_chip_updatew(bus, IRS, AZX_IRS_BUSY, AZX_IRS_BUSY);

			return snd_hdac_bus_wait_for_pio_response(bus, addr);
		}
		udelay(1);
	}

	dev_dbg_ratelimited(bus->dev, "send_cmd_pio timeout: IRS=%#x, val=%#x\n",
			    snd_hdac_chip_readw(bus, IRS), val);

	return -EIO;
}

/**
 * snd_hdac_bus_get_response_pio - receive a response via Immediate Response
 * @bus: HD-audio core bus
 * @addr: codec address
 * @res: pointer to store the value, NULL when not needed
 *
 * Returns zero if a value is read, or a negative error code.
 */
static int snd_hdac_bus_get_response_pio(struct hdac_bus *bus,
					 unsigned int addr, unsigned int *res)
{
	if (res)
		*res = bus->rirb.res[addr];

	return 0;
}

/**
 * snd_hdac_bus_send_cmd_corb - send a command verb via CORB
 * @bus: HD-audio core bus
 * @val: encoded verb value to send
 *
 * Returns zero for success or a negative error code.
 */
static int snd_hdac_bus_send_cmd_corb(struct hdac_bus *bus, unsigned int val)
{
	unsigned int addr = azx_command_addr(val);
	unsigned int wp, rp;

	guard(spinlock_irq)(&bus->reg_lock);

	bus->last_cmd[azx_command_addr(val)] = val;

	/* add command to corb */
	wp = snd_hdac_chip_readw(bus, CORBWP);
	if (wp == 0xffff) {
		/* something wrong, controller likely turned to D3 */
		return -EIO;
	}
	wp++;

Annotation

Implementation Notes