sound/pci/emu10k1/voice.c

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

File Facts

System
Linux kernel
Corpus path
sound/pci/emu10k1/voice.c
Extension
.c
Size
3376 bytes
Lines
137
Domain
Driver Families
Bucket
sound/pci
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 ((number > 1) && (i % 2)) {
			skip = 1;
			continue;
		}

		for (k = 0; k < number; k++) {
			voice = &emu->voices[i + k];
			if (voice->use) {
				skip = k + 1;
				goto next;
			}
		}

		for (k = 0; k < number; k++) {
			voice = &emu->voices[i + k];
			voice->use = type;
			voice->epcm = epcm;
			/* dev_dbg(emu->card->dev, "allocated voice %d\n", i + k); */
		}
		voice->last = 1;

		*rvoice = &emu->voices[i];
		emu->next_free_voice = (i + number) % NUM_G;
		return 0;

	next: ;
	}
	return -ENOMEM;  // -EBUSY would have been better
}

static void voice_free(struct snd_emu10k1 *emu,
		       struct snd_emu10k1_voice *pvoice)
{
	if (pvoice->dirty)
		snd_emu10k1_voice_init(emu, pvoice->number);
	pvoice->interrupt = NULL;
	pvoice->use = pvoice->dirty = pvoice->last = 0;
	pvoice->epcm = NULL;
}

int snd_emu10k1_voice_alloc(struct snd_emu10k1 *emu, int type, int count, int channels,
			    struct snd_emu10k1_pcm *epcm, struct snd_emu10k1_voice **rvoice)
{
	int result;

	if (snd_BUG_ON(!rvoice))
		return -EINVAL;
	if (snd_BUG_ON(!count))
		return -EINVAL;
	if (snd_BUG_ON(!channels))
		return -EINVAL;

	guard(spinlock_irqsave)(&emu->voice_lock);
	for (int got = 0; got < channels; ) {
		result = voice_alloc(emu, type, count, epcm, &rvoice[got]);
		if (result == 0) {
			got++;
			/*
			dev_dbg(emu->card->dev, "voice alloc - %i, %i of %i\n",
			        rvoice[got - 1]->number, got, want);
			*/
			continue;
		}
		if (type != EMU10K1_SYNTH && emu->get_synth_voice) {
			/* free a voice from synth */
			result = emu->get_synth_voice(emu);
			if (result >= 0) {
				voice_free(emu, &emu->voices[result]);
				continue;
			}
		}
		for (int i = 0; i < got; i++) {
			for (int j = 0; j < count; j++)
				voice_free(emu, rvoice[i] + j);
			rvoice[i] = NULL;
		}
		break;
	}

	return result;
}

EXPORT_SYMBOL(snd_emu10k1_voice_alloc);

int snd_emu10k1_voice_free(struct snd_emu10k1 *emu,
			   struct snd_emu10k1_voice *pvoice)
{
	int last;

	if (snd_BUG_ON(!pvoice))

Annotation

Implementation Notes