sound/pci/emu10k1/emufx.c

Source file repositories/reference/linux-study-clean/sound/pci/emu10k1/emufx.c

File Facts

System
Linux kernel
Corpus path
sound/pci/emu10k1/emufx.c
Extension
.c
Size
95510 bytes
Lines
2723
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

switch (ctl->translation) {
		case EMU10K1_GPR_TRANSLATION_NONE:
			snd_emu10k1_ptr_write(emu, emu->gpr_base + ctl->gpr[i], 0, val);
			break;
		case EMU10K1_GPR_TRANSLATION_NEGATE:
			snd_emu10k1_ptr_write(emu, emu->gpr_base + ctl->gpr[i], 0, ~val);
			break;
		case EMU10K1_GPR_TRANSLATION_TABLE100:
			snd_emu10k1_ptr_write(emu, emu->gpr_base + ctl->gpr[i], 0, db_table[val]);
			break;
		case EMU10K1_GPR_TRANSLATION_NEG_TABLE100:
			snd_emu10k1_ptr_write(emu, emu->gpr_base + ctl->gpr[i], 0,
					      val == 100 ? 0x80000000 : -(int)db_table[val]);
			break;
		case EMU10K1_GPR_TRANSLATION_BASS:
			if ((ctl->count % 5) != 0 || (ctl->count / 5) != ctl->vcount) {
				change = -EIO;
				goto __error;
			}
			for (j = 0; j < 5; j++)
				snd_emu10k1_ptr_write(emu, emu->gpr_base + ctl->gpr[j * ctl->vcount + i], 0, bass_table[val][j]);
			break;
		case EMU10K1_GPR_TRANSLATION_TREBLE:
			if ((ctl->count % 5) != 0 || (ctl->count / 5) != ctl->vcount) {
				change = -EIO;
				goto __error;
			}
			for (j = 0; j < 5; j++)
				snd_emu10k1_ptr_write(emu, emu->gpr_base + ctl->gpr[j * ctl->vcount + i], 0, treble_table[val][j]);
			break;
		case EMU10K1_GPR_TRANSLATION_ONOFF:
			snd_emu10k1_ptr_write(emu, emu->gpr_base + ctl->gpr[i], 0, onoff_table[val]);
			break;
		}
	}
      __error:
	return change;
}

/*
 *   Interrupt handler
 */

static void snd_emu10k1_fx8010_interrupt(struct snd_emu10k1 *emu)
{
	struct snd_emu10k1_fx8010_irq *irq, *nirq;

	irq = emu->fx8010.irq_handlers;
	while (irq) {
		nirq = irq->next;	/* irq ptr can be removed from list */
		if (snd_emu10k1_ptr_read(emu, emu->gpr_base + irq->gpr_running, 0) & 0xffff0000) {
			if (irq->handler)
				irq->handler(emu, irq->private_data);
			snd_emu10k1_ptr_write(emu, emu->gpr_base + irq->gpr_running, 0, 1);
		}
		irq = nirq;
	}
}

int snd_emu10k1_fx8010_register_irq_handler(struct snd_emu10k1 *emu,
					    snd_fx8010_irq_handler_t *handler,
					    unsigned char gpr_running,
					    void *private_data,
					    struct snd_emu10k1_fx8010_irq *irq)
{
	irq->handler = handler;
	irq->gpr_running = gpr_running;
	irq->private_data = private_data;
	irq->next = NULL;
	guard(spinlock_irqsave)(&emu->fx8010.irq_lock);
	if (emu->fx8010.irq_handlers == NULL) {
		emu->fx8010.irq_handlers = irq;
		emu->dsp_interrupt = snd_emu10k1_fx8010_interrupt;
		snd_emu10k1_intr_enable(emu, INTE_FXDSPENABLE);
	} else {
		irq->next = emu->fx8010.irq_handlers;
		emu->fx8010.irq_handlers = irq;
	}
	return 0;
}

int snd_emu10k1_fx8010_unregister_irq_handler(struct snd_emu10k1 *emu,
					      struct snd_emu10k1_fx8010_irq *irq)
{
	struct snd_emu10k1_fx8010_irq *tmp;
	
	guard(spinlock_irqsave)(&emu->fx8010.irq_lock);
	tmp = emu->fx8010.irq_handlers;
	if (tmp == irq) {
		emu->fx8010.irq_handlers = tmp->next;

Annotation

Implementation Notes