sound/isa/gus/gus_reset.c

Source file repositories/reference/linux-study-clean/sound/isa/gus/gus_reset.c

File Facts

System
Linux kernel
Corpus path
sound/isa/gus/gus_reset.c
Extension
.c
Size
12331 bytes
Lines
402
Domain
Driver Families
Bucket
sound/isa
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

if (gus->gf1.enh_mode) {
			snd_gf1_write8(gus, SNDRV_GF1_VB_ACCUMULATOR, 0);
			snd_gf1_write16(gus, SNDRV_GF1_VW_EFFECT_VOLUME, 0);
			snd_gf1_write16(gus, SNDRV_GF1_VW_EFFECT_VOLUME_FINAL, 0);
		}
	}
}

void snd_gf1_stop_voices(struct snd_gus_card * gus, unsigned short v_min, unsigned short v_max)
{
	short i, ramp_ok;
	unsigned short ramp_end;

	if (!in_interrupt()) {	/* this can't be done in interrupt */
		for (i = v_min, ramp_ok = 0; i <= v_max; i++) {
			guard(spinlock_irqsave)(&gus->reg_lock);
			snd_gf1_select_voice(gus, i);
			ramp_end = snd_gf1_read16(gus, 9) >> 8;
			if (ramp_end > SNDRV_GF1_MIN_OFFSET) {
				ramp_ok++;
				snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_RATE, 20);	/* ramp rate */
				snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_START, SNDRV_GF1_MIN_OFFSET);	/* ramp start */
				snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_END, ramp_end);	/* ramp end */
				snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_CONTROL, 0x40);	/* ramp down */
				if (gus->gf1.enh_mode) {
					snd_gf1_delay(gus);
					snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_CONTROL, 0x40);
				}
			}
		}
		msleep_interruptible(50);
	}
	snd_gf1_clear_voices(gus, v_min, v_max);
}

static void snd_gf1_alloc_voice_use(struct snd_gus_card * gus, 
				    struct snd_gus_voice * pvoice,
				    int type, int client, int port)
{
	pvoice->use = 1;
	switch (type) {
	case SNDRV_GF1_VOICE_TYPE_PCM:
		gus->gf1.pcm_alloc_voices++;
		pvoice->pcm = 1;
		break;
	case SNDRV_GF1_VOICE_TYPE_SYNTH:
		pvoice->synth = 1;
		pvoice->client = client;
		pvoice->port = port;
		break;
	case SNDRV_GF1_VOICE_TYPE_MIDI:
		pvoice->midi = 1;
		pvoice->client = client;
		pvoice->port = port;
		break;
	}
}

struct snd_gus_voice *snd_gf1_alloc_voice(struct snd_gus_card * gus, int type, int client, int port)
{
	struct snd_gus_voice *pvoice;
	int idx;

	guard(spinlock_irqsave)(&gus->voice_alloc);
	if (type == SNDRV_GF1_VOICE_TYPE_PCM) {
		if (gus->gf1.pcm_alloc_voices >= gus->gf1.pcm_channels)
			return NULL;
	}
	for (idx = 0; idx < 32; idx++) {
		pvoice = &gus->gf1.voices[idx];
		if (!pvoice->use) {
			snd_gf1_alloc_voice_use(gus, pvoice, type, client, port);
			return pvoice;
		}
	} 
	for (idx = 0; idx < 32; idx++) {
		pvoice = &gus->gf1.voices[idx];
		if (pvoice->midi && !pvoice->client) {
			snd_gf1_clear_voices(gus, pvoice->number, pvoice->number);
			snd_gf1_alloc_voice_use(gus, pvoice, type, client, port);
			return pvoice;
		}
	} 
	return NULL;
}

void snd_gf1_free_voice(struct snd_gus_card * gus, struct snd_gus_voice *voice)
{
	void (*private_free)(struct snd_gus_voice *voice);

Annotation

Implementation Notes