sound/isa/sb/emu8000_callback.c

Source file repositories/reference/linux-study-clean/sound/isa/sb/emu8000_callback.c

File Facts

System
Linux kernel
Corpus path
sound/isa/sb/emu8000_callback.c
Extension
.c
Size
12894 bytes
Lines
535
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

struct best {
		unsigned int  time;
		int voice;
	} best[END];
	struct best *bp;

	hw = emu->hw;

	for (i = 0; i < END; i++) {
		best[i].time = (unsigned int)(-1); /* XXX MAX_?INT really */
		best[i].voice = -1;
	}

	/*
	 * Go through them all and get a best one to use.
	 */
	for (i = 0; i < emu->max_voices; i++) {
		int state, val;

		vp = &emu->voices[i];
		state = vp->state;

		if (state == SNDRV_EMUX_ST_OFF)
			bp = best + OFF;
		else if (state == SNDRV_EMUX_ST_RELEASED ||
			 state == SNDRV_EMUX_ST_PENDING) {
			bp = best + RELEASED;
			val = (EMU8000_CVCF_READ(hw, vp->ch) >> 16) & 0xffff;
			if (! val)
				bp = best + OFF;
		}
		else if (state & SNDRV_EMUX_ST_ON)
			bp = best + PLAYING;
		else
			continue;

		/* check if sample is finished playing (non-looping only) */
		if (state != SNDRV_EMUX_ST_OFF &&
		    (vp->reg.sample_mode & SNDRV_SFNT_SAMPLE_SINGLESHOT)) {
			val = EMU8000_CCCA_READ(hw, vp->ch) & 0xffffff;
			if (val >= vp->reg.loopstart)
				bp = best + OFF;
		}

		if (vp->time < bp->time) {
			bp->time = vp->time;
			bp->voice = i;
		}
	}

	for (i = 0; i < END; i++) {
		if (best[i].voice >= 0) {
			vp = &emu->voices[best[i].voice];
			vp->ch = best[i].voice;
			return vp;
		}
	}

	/* not found */
	return NULL;
}

/*
 */
static int
start_voice(struct snd_emux_voice *vp)
{
	unsigned int temp;
	int ch;
	int addr;
	struct snd_midi_channel *chan;
	struct snd_emu8000 *hw;

	hw = vp->hw;
	ch = vp->ch;
	chan = vp->chan;

	/* channel to be silent and idle */
	EMU8000_DCYSUSV_WRITE(hw, ch, 0x0080);
	EMU8000_VTFT_WRITE(hw, ch, 0x0000FFFF);
	EMU8000_CVCF_WRITE(hw, ch, 0x0000FFFF);
	EMU8000_PTRX_WRITE(hw, ch, 0);
	EMU8000_CPF_WRITE(hw, ch, 0);

	/* set pitch offset */
	set_pitch(hw, vp);

	/* set envelope parameters */
	EMU8000_ENVVAL_WRITE(hw, ch, vp->reg.parm.moddelay);
	EMU8000_ATKHLD_WRITE(hw, ch, vp->reg.parm.modatkhld);

Annotation

Implementation Notes