sound/pci/ymfpci/ymfpci_main.c

Source file repositories/reference/linux-study-clean/sound/pci/ymfpci/ymfpci_main.c

File Facts

System
Linux kernel
Corpus path
sound/pci/ymfpci/ymfpci_main.c
Extension
.c
Size
68232 bytes
Lines
2318
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 (type) {
		case YMFPCI_PCM:
			voice->pcm = 1;
			if (voice2)
				voice2->pcm = 1;
			break;
		case YMFPCI_SYNTH:
			voice->synth = 1;
			break;
		case YMFPCI_MIDI:
			voice->midi = 1;
			break;
		}
		snd_ymfpci_hw_start(chip);
		if (voice2)
			snd_ymfpci_hw_start(chip);
		*rvoice = voice;
		return 0;
	}
	return -ENOMEM;
}

static int snd_ymfpci_voice_alloc(struct snd_ymfpci *chip,
				  enum snd_ymfpci_voice_type type, int pair,
				  struct snd_ymfpci_voice **rvoice)
{
	int result;
	
	if (snd_BUG_ON(!rvoice))
		return -EINVAL;
	if (snd_BUG_ON(pair && type != YMFPCI_PCM))
		return -EINVAL;
	
	guard(spinlock_irqsave)(&chip->voice_lock);
	for (;;) {
		result = voice_alloc(chip, type, pair, rvoice);
		if (result == 0 || type != YMFPCI_PCM)
			break;
		/* TODO: synth/midi voice deallocation */
		break;
	}
	return result;		
}

static int snd_ymfpci_voice_free(struct snd_ymfpci *chip, struct snd_ymfpci_voice *pvoice)
{
	if (snd_BUG_ON(!pvoice))
		return -EINVAL;
	snd_ymfpci_hw_stop(chip);
	guard(spinlock_irqsave)(&chip->voice_lock);
	if (pvoice->number == chip->src441_used) {
		chip->src441_used = -1;
		pvoice->ypcm->use_441_slot = 0;
	}
	pvoice->use = pvoice->pcm = pvoice->synth = pvoice->midi = 0;
	pvoice->ypcm = NULL;
	pvoice->interrupt = NULL;
	return 0;
}

/*
 *  PCM part
 */

static void snd_ymfpci_pcm_interrupt(struct snd_ymfpci *chip, struct snd_ymfpci_voice *voice)
{
	struct snd_ymfpci_pcm *ypcm;
	u32 pos, delta;
	
	ypcm = voice->ypcm;
	if (!ypcm)
		return;
	if (ypcm->substream == NULL)
		return;
	guard(spinlock)(&chip->reg_lock);
	if (ypcm->running) {
		pos = le32_to_cpu(voice->bank[chip->active_bank].start);
		if (pos < ypcm->last_pos)
			delta = pos + (ypcm->buffer_size - ypcm->last_pos);
		else
			delta = pos - ypcm->last_pos;
		ypcm->period_pos += delta;
		ypcm->last_pos = pos;
		if (ypcm->period_pos >= ypcm->period_size) {
			/*
			dev_dbg(chip->card->dev,
			       "done - active_bank = 0x%x, start = 0x%x\n",
			       chip->active_bank,
			       voice->bank[chip->active_bank].start);
			*/

Annotation

Implementation Notes