diff options
Diffstat (limited to 'sound/drivers/opl3/opl3_midi.c')
| -rw-r--r-- | sound/drivers/opl3/opl3_midi.c | 116 |
1 files changed, 64 insertions, 52 deletions
diff --git a/sound/drivers/opl3/opl3_midi.c b/sound/drivers/opl3/opl3_midi.c index 1b6f227af37..6c6d09a51f4 100644 --- a/sound/drivers/opl3/opl3_midi.c +++ b/sound/drivers/opl3/opl3_midi.c @@ -27,8 +27,10 @@ extern char snd_opl3_regmap[MAX_OPL2_VOICES][4]; -extern int use_internal_drums; +extern bool use_internal_drums; +static void snd_opl3_note_off_unsafe(void *p, int note, int vel, + struct snd_midi_channel *chan); /* * The next table looks magical, but it certainly is not. Its values have * been calculated as table[i]=8*log(i/64)/log(2) with an obvious exception @@ -125,7 +127,7 @@ static void debug_alloc(struct snd_opl3 *opl3, char *s, int voice) { int i; char *str = "x.24"; - printk("time %.5i: %s [%.2i]: ", opl3->use_time, s, voice); + printk(KERN_DEBUG "time %.5i: %s [%.2i]: ", opl3->use_time, s, voice); for (i = 0; i < opl3->max_voices; i++) printk("%c", *(str + opl3->voices[i].state + 1)); printk("\n"); @@ -161,7 +163,7 @@ static int opl3_get_voice(struct snd_opl3 *opl3, int instr_4op, struct best *bp; for (i = 0; i < END; i++) { - best[i].time = (unsigned int)(-1); /* XXX MAX_?INT really */; + best[i].time = (unsigned int)(-1); /* XXX MAX_?INT really */ best[i].voice = -1; } @@ -218,7 +220,7 @@ static int opl3_get_voice(struct snd_opl3 *opl3, int instr_4op, for (i = 0; i < END; i++) { if (best[i].voice >= 0) { #ifdef DEBUG_ALLOC - printk("%s %iop allocation on voice %i\n", + printk(KERN_DEBUG "%s %iop allocation on voice %i\n", alloc_type[i], instr_4op ? 4 : 2, best[i].voice); #endif @@ -242,16 +244,20 @@ void snd_opl3_timer_func(unsigned long data) int again = 0; int i; - spin_lock_irqsave(&opl3->sys_timer_lock, flags); + spin_lock_irqsave(&opl3->voice_lock, flags); for (i = 0; i < opl3->max_voices; i++) { struct snd_opl3_voice *vp = &opl3->voices[i]; if (vp->state > 0 && vp->note_off_check) { if (vp->note_off == jiffies) - snd_opl3_note_off(opl3, vp->note, 0, vp->chan); + snd_opl3_note_off_unsafe(opl3, vp->note, 0, + vp->chan); else again++; } } + spin_unlock_irqrestore(&opl3->voice_lock, flags); + + spin_lock_irqsave(&opl3->sys_timer_lock, flags); if (again) { opl3->tlist.expires = jiffies + 1; /* invoke again */ add_timer(&opl3->tlist); @@ -289,8 +295,6 @@ static int snd_opl3_oss_map[MAX_OPL3_VOICES] = { void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan) { struct snd_opl3 *opl3; - struct snd_seq_instr wanted; - struct snd_seq_kinstr *kinstr; int instr_4op; int voice; @@ -306,33 +310,33 @@ void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan) unsigned char voice_offset; unsigned short opl3_reg; unsigned char reg_val; + unsigned char prg, bank; int key = note; unsigned char fnum, blocknum; int i; + struct fm_patch *patch; struct fm_instrument *fm; unsigned long flags; opl3 = p; #ifdef DEBUG_MIDI - snd_printk("Note on, ch %i, inst %i, note %i, vel %i\n", + snd_printk(KERN_DEBUG "Note on, ch %i, inst %i, note %i, vel %i\n", chan->number, chan->midi_program, note, vel); #endif - wanted.cluster = 0; - wanted.std = SNDRV_SEQ_INSTR_TYPE2_OPL2_3; /* in SYNTH mode, application takes care of voices */ /* in SEQ mode, drum voice numbers are notes on drum channel */ if (opl3->synth_mode == SNDRV_OPL3_MODE_SEQ) { if (chan->drum_channel) { /* percussion instruments are located in bank 128 */ - wanted.bank = 128; - wanted.prg = note; + bank = 128; + prg = note; } else { - wanted.bank = chan->gm_bank_select; - wanted.prg = chan->midi_program; + bank = chan->gm_bank_select; + prg = chan->midi_program; } } else { /* Prepare for OSS mode */ @@ -340,8 +344,8 @@ void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan) return; /* OSS instruments are located in bank 127 */ - wanted.bank = 127; - wanted.prg = chan->midi_program; + bank = 127; + prg = chan->midi_program; } spin_lock_irqsave(&opl3->voice_lock, flags); @@ -353,15 +357,14 @@ void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan) } __extra_prg: - kinstr = snd_seq_instr_find(opl3->ilist, &wanted, 1, 0); - if (kinstr == NULL) { + patch = snd_opl3_find_patch(opl3, prg, bank, 0); + if (!patch) { spin_unlock_irqrestore(&opl3->voice_lock, flags); return; } - fm = KINSTR_DATA(kinstr); - - switch (fm->type) { + fm = &patch->inst; + switch (patch->type) { case FM_PATCH_OPL2: instr_4op = 0; break; @@ -371,14 +374,12 @@ void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan) break; } default: - snd_seq_instr_free_use(opl3->ilist, kinstr); spin_unlock_irqrestore(&opl3->voice_lock, flags); return; } - #ifdef DEBUG_MIDI - snd_printk(" --> OPL%i instrument: %s\n", - instr_4op ? 3 : 2, kinstr->name); + snd_printk(KERN_DEBUG " --> OPL%i instrument: %s\n", + instr_4op ? 3 : 2, patch->name); #endif /* in SYNTH mode, application takes care of voices */ /* in SEQ mode, allocate voice on free OPL3 channel */ @@ -389,6 +390,11 @@ void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan) voice = snd_opl3_oss_map[chan->number]; } + if (voice < 0) { + spin_unlock_irqrestore(&opl3->voice_lock, flags); + return; + } + if (voice < MAX_OPL2_VOICES) { /* Left register block for voices 0 .. 8 */ reg_side = OPL3_LEFT; @@ -436,7 +442,7 @@ void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan) } #ifdef DEBUG_MIDI - snd_printk(" --> setting OPL3 connection: 0x%x\n", + snd_printk(KERN_DEBUG " --> setting OPL3 connection: 0x%x\n", opl3->connection_reg); #endif /* @@ -471,7 +477,7 @@ void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan) /* Program the FM voice characteristics */ for (i = 0; i < (instr_4op ? 4 : 2); i++) { #ifdef DEBUG_MIDI - snd_printk(" --> programming operator %i\n", i); + snd_printk(KERN_DEBUG " --> programming operator %i\n", i); #endif op_offset = snd_opl3_regmap[voice_offset][i]; @@ -551,7 +557,7 @@ void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan) blocknum |= OPL3_KEYON_BIT; #ifdef DEBUG_MIDI - snd_printk(" --> trigger voice %i\n", voice); + snd_printk(KERN_DEBUG " --> trigger voice %i\n", voice); #endif /* Set OPL3 KEYON_BLOCK register of requested voice */ opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset); @@ -569,8 +575,6 @@ void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan) /* get extra pgm, but avoid possible loops */ extra_prg = (extra_prg) ? 0 : fm->modes; - snd_seq_instr_free_use(opl3->ilist, kinstr); - /* do the bookkeeping */ vp->time = opl3->use_time++; vp->note = key; @@ -601,15 +605,15 @@ void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan) /* allocate extra program if specified in patch library */ if (extra_prg) { if (extra_prg > 128) { - wanted.bank = 128; + bank = 128; /* percussions start at 35 */ - wanted.prg = extra_prg - 128 + 35 - 1; + prg = extra_prg - 128 + 35 - 1; } else { - wanted.bank = 0; - wanted.prg = extra_prg - 1; + bank = 0; + prg = extra_prg - 1; } #ifdef DEBUG_MIDI - snd_printk(" *** allocating extra program\n"); + snd_printk(KERN_DEBUG " *** allocating extra program\n"); #endif goto __extra_prg; } @@ -624,7 +628,8 @@ static void snd_opl3_kill_voice(struct snd_opl3 *opl3, int voice) struct snd_opl3_voice *vp, *vp2; - snd_assert(voice < MAX_OPL3_VOICES, return); + if (snd_BUG_ON(voice >= MAX_OPL3_VOICES)) + return; vp = &opl3->voices[voice]; if (voice < MAX_OPL2_VOICES) { @@ -639,7 +644,7 @@ static void snd_opl3_kill_voice(struct snd_opl3 *opl3, int voice) /* kill voice */ #ifdef DEBUG_MIDI - snd_printk(" --> kill voice %i\n", voice); + snd_printk(KERN_DEBUG " --> kill voice %i\n", voice); #endif opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset); /* clear Key ON bit */ @@ -664,28 +669,24 @@ static void snd_opl3_kill_voice(struct snd_opl3 *opl3, int voice) /* * Release a note in response to a midi note off. */ -void snd_opl3_note_off(void *p, int note, int vel, struct snd_midi_channel *chan) +static void snd_opl3_note_off_unsafe(void *p, int note, int vel, + struct snd_midi_channel *chan) { struct snd_opl3 *opl3; int voice; struct snd_opl3_voice *vp; - unsigned long flags; - opl3 = p; #ifdef DEBUG_MIDI - snd_printk("Note off, ch %i, inst %i, note %i\n", + snd_printk(KERN_DEBUG "Note off, ch %i, inst %i, note %i\n", chan->number, chan->midi_program, note); #endif - spin_lock_irqsave(&opl3->voice_lock, flags); - if (opl3->synth_mode == SNDRV_OPL3_MODE_SEQ) { if (chan->drum_channel && use_internal_drums) { snd_opl3_drum_switch(opl3, note, vel, 0, chan); - spin_unlock_irqrestore(&opl3->voice_lock, flags); return; } /* this loop will hopefully kill all extra voices, because @@ -703,6 +704,16 @@ void snd_opl3_note_off(void *p, int note, int vel, struct snd_midi_channel *chan snd_opl3_kill_voice(opl3, voice); } } +} + +void snd_opl3_note_off(void *p, int note, int vel, + struct snd_midi_channel *chan) +{ + struct snd_opl3 *opl3 = p; + unsigned long flags; + + spin_lock_irqsave(&opl3->voice_lock, flags); + snd_opl3_note_off_unsafe(p, note, vel, chan); spin_unlock_irqrestore(&opl3->voice_lock, flags); } @@ -715,7 +726,7 @@ void snd_opl3_key_press(void *p, int note, int vel, struct snd_midi_channel *cha opl3 = p; #ifdef DEBUG_MIDI - snd_printk("Key pressure, ch#: %i, inst#: %i\n", + snd_printk(KERN_DEBUG "Key pressure, ch#: %i, inst#: %i\n", chan->number, chan->midi_program); #endif } @@ -729,7 +740,7 @@ void snd_opl3_terminate_note(void *p, int note, struct snd_midi_channel *chan) opl3 = p; #ifdef DEBUG_MIDI - snd_printk("Terminate note, ch#: %i, inst#: %i\n", + snd_printk(KERN_DEBUG "Terminate note, ch#: %i, inst#: %i\n", chan->number, chan->midi_program); #endif } @@ -744,7 +755,8 @@ static void snd_opl3_update_pitch(struct snd_opl3 *opl3, int voice) struct snd_opl3_voice *vp; - snd_assert(voice < MAX_OPL3_VOICES, return); + if (snd_BUG_ON(voice >= MAX_OPL3_VOICES)) + return; vp = &opl3->voices[voice]; if (vp->chan == NULL) @@ -808,7 +820,7 @@ static void snd_opl3_pitch_ctrl(struct snd_opl3 *opl3, struct snd_midi_channel * } /* - * Deal with a controler type event. This includes all types of + * Deal with a controller type event. This includes all types of * control events, not just the midi controllers */ void snd_opl3_control(void *p, int type, struct snd_midi_channel *chan) @@ -817,7 +829,7 @@ void snd_opl3_control(void *p, int type, struct snd_midi_channel *chan) opl3 = p; #ifdef DEBUG_MIDI - snd_printk("Controller, TYPE = %i, ch#: %i, inst#: %i\n", + snd_printk(KERN_DEBUG "Controller, TYPE = %i, ch#: %i, inst#: %i\n", type, chan->number, chan->midi_program); #endif @@ -854,7 +866,7 @@ void snd_opl3_nrpn(void *p, struct snd_midi_channel *chan, opl3 = p; #ifdef DEBUG_MIDI - snd_printk("NRPN, ch#: %i, inst#: %i\n", + snd_printk(KERN_DEBUG "NRPN, ch#: %i, inst#: %i\n", chan->number, chan->midi_program); #endif } @@ -869,6 +881,6 @@ void snd_opl3_sysex(void *p, unsigned char *buf, int len, opl3 = p; #ifdef DEBUG_MIDI - snd_printk("SYSEX\n"); + snd_printk(KERN_DEBUG "SYSEX\n"); #endif } |
