// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) by Jaroslav Kysela <perex@perex.cz> * Lee Revell <rlrevell@joe-job.com> * Oswald Buddenhagen <oswald.buddenhagen@gmx.de> * Creative Labs, Inc. * * Routines for control of EMU10K1 chips - voice manager
*/
/* Previously the voice allocator started at 0 every time. The new voice * allocator uses a round robin scheme. The next free voice is tracked in * the card record and each allocation begins where the last left off. The * hardware requires stereo interleaved voices be aligned to an even/odd * boundary. * --rlrevell
*/
staticint voice_alloc(struct snd_emu10k1 *emu, int type, int number, struct snd_emu10k1_pcm *epcm, struct snd_emu10k1_voice **rvoice)
{ struct snd_emu10k1_voice *voice; int i, j, k, skip;
for (i = emu->next_free_voice, j = 0; j < NUM_G; i = (i + skip) % NUM_G, j += skip) { /* dev_dbg(emu->card->dev, "i %d j %d next free %d!\n", i, j, emu->next_free_voice);
*/
/* stereo voices must be even/odd */ 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;
}
}
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)
{ unsignedlong flags; int result;
if (snd_BUG_ON(!rvoice)) return -EINVAL; if (snd_BUG_ON(!count)) return -EINVAL; if (snd_BUG_ON(!channels)) return -EINVAL;
spin_lock_irqsave(&emu->voice_lock, flags); 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;
}
spin_unlock_irqrestore(&emu->voice_lock, flags);
return result;
}
EXPORT_SYMBOL(snd_emu10k1_voice_alloc);
int snd_emu10k1_voice_free(struct snd_emu10k1 *emu, struct snd_emu10k1_voice *pvoice)
{ unsignedlong flags; int last;
if (snd_BUG_ON(!pvoice)) return -EINVAL;
spin_lock_irqsave(&emu->voice_lock, flags); do {
last = pvoice->last;
voice_free(emu, pvoice++);
} while (!last);
spin_unlock_irqrestore(&emu->voice_lock, flags); return 0;
}
EXPORT_SYMBOL(snd_emu10k1_voice_free);
Messung V0.5
¤ Dauer der Verarbeitung: 0.0 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.