0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #include <linux/time.h>
0018 #include <linux/export.h>
0019 #include <sound/core.h>
0020 #include <sound/emu10k1.h>
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034 static int voice_alloc(struct snd_emu10k1 *emu, int type, int number,
0035 struct snd_emu10k1_voice **rvoice)
0036 {
0037 struct snd_emu10k1_voice *voice;
0038 int i, j, k, first_voice, last_voice, skip;
0039
0040 *rvoice = NULL;
0041 first_voice = last_voice = 0;
0042 for (i = emu->next_free_voice, j = 0; j < NUM_G ; i += number, j += number) {
0043
0044
0045
0046
0047 i %= NUM_G;
0048
0049
0050 if ((number == 2) && (i % 2)) {
0051 i++;
0052 continue;
0053 }
0054
0055 skip = 0;
0056 for (k = 0; k < number; k++) {
0057 voice = &emu->voices[(i+k) % NUM_G];
0058 if (voice->use) {
0059 skip = 1;
0060 break;
0061 }
0062 }
0063 if (!skip) {
0064
0065 first_voice = i;
0066 last_voice = (i + number) % NUM_G;
0067 emu->next_free_voice = last_voice;
0068 break;
0069 }
0070 }
0071
0072 if (first_voice == last_voice)
0073 return -ENOMEM;
0074
0075 for (i = 0; i < number; i++) {
0076 voice = &emu->voices[(first_voice + i) % NUM_G];
0077
0078
0079
0080
0081 voice->use = 1;
0082 switch (type) {
0083 case EMU10K1_PCM:
0084 voice->pcm = 1;
0085 break;
0086 case EMU10K1_SYNTH:
0087 voice->synth = 1;
0088 break;
0089 case EMU10K1_MIDI:
0090 voice->midi = 1;
0091 break;
0092 case EMU10K1_EFX:
0093 voice->efx = 1;
0094 break;
0095 }
0096 }
0097 *rvoice = &emu->voices[first_voice];
0098 return 0;
0099 }
0100
0101 int snd_emu10k1_voice_alloc(struct snd_emu10k1 *emu, int type, int number,
0102 struct snd_emu10k1_voice **rvoice)
0103 {
0104 unsigned long flags;
0105 int result;
0106
0107 if (snd_BUG_ON(!rvoice))
0108 return -EINVAL;
0109 if (snd_BUG_ON(!number))
0110 return -EINVAL;
0111
0112 spin_lock_irqsave(&emu->voice_lock, flags);
0113 for (;;) {
0114 result = voice_alloc(emu, type, number, rvoice);
0115 if (result == 0 || type == EMU10K1_SYNTH || type == EMU10K1_MIDI)
0116 break;
0117
0118
0119 if (emu->get_synth_voice) {
0120 result = emu->get_synth_voice(emu);
0121 if (result >= 0) {
0122 struct snd_emu10k1_voice *pvoice = &emu->voices[result];
0123 pvoice->interrupt = NULL;
0124 pvoice->use = pvoice->pcm = pvoice->synth = pvoice->midi = pvoice->efx = 0;
0125 pvoice->epcm = NULL;
0126 }
0127 }
0128 if (result < 0)
0129 break;
0130 }
0131 spin_unlock_irqrestore(&emu->voice_lock, flags);
0132
0133 return result;
0134 }
0135
0136 EXPORT_SYMBOL(snd_emu10k1_voice_alloc);
0137
0138 int snd_emu10k1_voice_free(struct snd_emu10k1 *emu,
0139 struct snd_emu10k1_voice *pvoice)
0140 {
0141 unsigned long flags;
0142
0143 if (snd_BUG_ON(!pvoice))
0144 return -EINVAL;
0145 spin_lock_irqsave(&emu->voice_lock, flags);
0146 pvoice->interrupt = NULL;
0147 pvoice->use = pvoice->pcm = pvoice->synth = pvoice->midi = pvoice->efx = 0;
0148 pvoice->epcm = NULL;
0149 snd_emu10k1_voice_init(emu, pvoice->number);
0150 spin_unlock_irqrestore(&emu->voice_lock, flags);
0151 return 0;
0152 }
0153
0154 EXPORT_SYMBOL(snd_emu10k1_voice_free);