sound/pci/cs46xx/cs46xx_lib.c

Source file repositories/reference/linux-study-clean/sound/pci/cs46xx/cs46xx_lib.c

File Facts

System
Linux kernel
Corpus path
sound/pci/cs46xx/cs46xx_lib.c
Extension
.c
Size
107278 bytes
Lines
3925
Domain
Driver Families
Bucket
sound/pci
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 ba1_struct {
	struct {
		u32 offset;
		u32 size;
	} memory[BA1_MEMORY_COUNT];
	u32 map[BA1_DWORD_SIZE];
};

MODULE_FIRMWARE("cs46xx/ba1");

static int load_firmware(struct snd_cs46xx *chip)
{
	const struct firmware *fw;
	int i, size, err;

	err = request_firmware(&fw, "cs46xx/ba1", &chip->pci->dev);
	if (err < 0)
		return err;
	if (fw->size != sizeof(*chip->ba1)) {
		err = -EINVAL;
		goto error;
	}

	chip->ba1 = vmalloc(sizeof(*chip->ba1));
	if (!chip->ba1) {
		err = -ENOMEM;
		goto error;
	}

	memcpy_le32(chip->ba1, fw->data, sizeof(*chip->ba1));

	/* sanity check */
	size = 0;
	for (i = 0; i < BA1_MEMORY_COUNT; i++)
		size += chip->ba1->memory[i].size;
	if (size > BA1_DWORD_SIZE * 4)
		err = -EINVAL;

 error:
	release_firmware(fw);
	return err;
}

static __maybe_unused int snd_cs46xx_download_image(struct snd_cs46xx *chip)
{
	int idx, err;
	unsigned int offset = 0;
	struct ba1_struct *ba1 = chip->ba1;

	for (idx = 0; idx < BA1_MEMORY_COUNT; idx++) {
		err = snd_cs46xx_download(chip,
					  &ba1->map[offset],
					  ba1->memory[idx].offset,
					  ba1->memory[idx].size);
		if (err < 0)
			return err;
		offset += ba1->memory[idx].size >> 2;
	}	
	return 0;
}
#endif /* CONFIG_SND_CS46XX_NEW_DSP */

/*
 *  Chip reset
 */

static void snd_cs46xx_reset(struct snd_cs46xx *chip)
{
	int idx;

	/*
	 *  Write the reset bit of the SP control register.
	 */
	snd_cs46xx_poke(chip, BA1_SPCR, SPCR_RSTSP);

	/*
	 *  Write the control register.
	 */
	snd_cs46xx_poke(chip, BA1_SPCR, SPCR_DRQEN);

	/*
	 *  Clear the trap registers.
	 */
	for (idx = 0; idx < 8; idx++) {
		snd_cs46xx_poke(chip, BA1_DREG, DREG_REGID_TRAP_SELECT + idx);
		snd_cs46xx_poke(chip, BA1_TWPR, 0xFFFF);
	}
	snd_cs46xx_poke(chip, BA1_DREG, 0);

	/*

Annotation

Implementation Notes