diff options
| -rw-r--r-- | sound/drivers/opl3/opl3_midi.c | 28 |
1 files changed, 20 insertions, 8 deletions
diff --git a/sound/drivers/opl3/opl3_midi.c b/sound/drivers/opl3/opl3_midi.c index 6e7d09ae0e82..7d722a025d0d 100644 --- a/sound/drivers/opl3/opl3_midi.c +++ b/sound/drivers/opl3/opl3_midi.c | |||
| @@ -29,6 +29,8 @@ extern char snd_opl3_regmap[MAX_OPL2_VOICES][4]; | |||
| 29 | 29 | ||
| 30 | extern int use_internal_drums; | 30 | extern int use_internal_drums; |
| 31 | 31 | ||
| 32 | static void snd_opl3_note_off_unsafe(void *p, int note, int vel, | ||
| 33 | struct snd_midi_channel *chan); | ||
| 32 | /* | 34 | /* |
| 33 | * The next table looks magical, but it certainly is not. Its values have | 35 | * The next table looks magical, but it certainly is not. Its values have |
| 34 | * been calculated as table[i]=8*log(i/64)/log(2) with an obvious exception | 36 | * been calculated as table[i]=8*log(i/64)/log(2) with an obvious exception |
| @@ -242,16 +244,20 @@ void snd_opl3_timer_func(unsigned long data) | |||
| 242 | int again = 0; | 244 | int again = 0; |
| 243 | int i; | 245 | int i; |
| 244 | 246 | ||
| 245 | spin_lock_irqsave(&opl3->sys_timer_lock, flags); | 247 | spin_lock_irqsave(&opl3->voice_lock, flags); |
| 246 | for (i = 0; i < opl3->max_voices; i++) { | 248 | for (i = 0; i < opl3->max_voices; i++) { |
| 247 | struct snd_opl3_voice *vp = &opl3->voices[i]; | 249 | struct snd_opl3_voice *vp = &opl3->voices[i]; |
| 248 | if (vp->state > 0 && vp->note_off_check) { | 250 | if (vp->state > 0 && vp->note_off_check) { |
| 249 | if (vp->note_off == jiffies) | 251 | if (vp->note_off == jiffies) |
| 250 | snd_opl3_note_off(opl3, vp->note, 0, vp->chan); | 252 | snd_opl3_note_off_unsafe(opl3, vp->note, 0, |
| 253 | vp->chan); | ||
| 251 | else | 254 | else |
| 252 | again++; | 255 | again++; |
| 253 | } | 256 | } |
| 254 | } | 257 | } |
| 258 | spin_unlock_irqrestore(&opl3->voice_lock, flags); | ||
| 259 | |||
| 260 | spin_lock_irqsave(&opl3->sys_timer_lock, flags); | ||
| 255 | if (again) { | 261 | if (again) { |
| 256 | opl3->tlist.expires = jiffies + 1; /* invoke again */ | 262 | opl3->tlist.expires = jiffies + 1; /* invoke again */ |
| 257 | add_timer(&opl3->tlist); | 263 | add_timer(&opl3->tlist); |
| @@ -658,15 +664,14 @@ static void snd_opl3_kill_voice(struct snd_opl3 *opl3, int voice) | |||
| 658 | /* | 664 | /* |
| 659 | * Release a note in response to a midi note off. | 665 | * Release a note in response to a midi note off. |
| 660 | */ | 666 | */ |
| 661 | void snd_opl3_note_off(void *p, int note, int vel, struct snd_midi_channel *chan) | 667 | static void snd_opl3_note_off_unsafe(void *p, int note, int vel, |
| 668 | struct snd_midi_channel *chan) | ||
| 662 | { | 669 | { |
| 663 | struct snd_opl3 *opl3; | 670 | struct snd_opl3 *opl3; |
| 664 | 671 | ||
| 665 | int voice; | 672 | int voice; |
| 666 | struct snd_opl3_voice *vp; | 673 | struct snd_opl3_voice *vp; |
| 667 | 674 | ||
| 668 | unsigned long flags; | ||
| 669 | |||
| 670 | opl3 = p; | 675 | opl3 = p; |
| 671 | 676 | ||
| 672 | #ifdef DEBUG_MIDI | 677 | #ifdef DEBUG_MIDI |
| @@ -674,12 +679,9 @@ void snd_opl3_note_off(void *p, int note, int vel, struct snd_midi_channel *chan | |||
| 674 | chan->number, chan->midi_program, note); | 679 | chan->number, chan->midi_program, note); |
| 675 | #endif | 680 | #endif |
| 676 | 681 | ||
| 677 | spin_lock_irqsave(&opl3->voice_lock, flags); | ||
| 678 | |||
| 679 | if (opl3->synth_mode == SNDRV_OPL3_MODE_SEQ) { | 682 | if (opl3->synth_mode == SNDRV_OPL3_MODE_SEQ) { |
| 680 | if (chan->drum_channel && use_internal_drums) { | 683 | if (chan->drum_channel && use_internal_drums) { |
| 681 | snd_opl3_drum_switch(opl3, note, vel, 0, chan); | 684 | snd_opl3_drum_switch(opl3, note, vel, 0, chan); |
| 682 | spin_unlock_irqrestore(&opl3->voice_lock, flags); | ||
| 683 | return; | 685 | return; |
| 684 | } | 686 | } |
| 685 | /* this loop will hopefully kill all extra voices, because | 687 | /* this loop will hopefully kill all extra voices, because |
| @@ -697,6 +699,16 @@ void snd_opl3_note_off(void *p, int note, int vel, struct snd_midi_channel *chan | |||
| 697 | snd_opl3_kill_voice(opl3, voice); | 699 | snd_opl3_kill_voice(opl3, voice); |
| 698 | } | 700 | } |
| 699 | } | 701 | } |
| 702 | } | ||
| 703 | |||
| 704 | void snd_opl3_note_off(void *p, int note, int vel, | ||
| 705 | struct snd_midi_channel *chan) | ||
| 706 | { | ||
| 707 | struct snd_opl3 *opl3 = p; | ||
| 708 | unsigned long flags; | ||
| 709 | |||
| 710 | spin_lock_irqsave(&opl3->voice_lock, flags); | ||
| 711 | snd_opl3_note_off_unsafe(p, note, vel, chan); | ||
| 700 | spin_unlock_irqrestore(&opl3->voice_lock, flags); | 712 | spin_unlock_irqrestore(&opl3->voice_lock, flags); |
| 701 | } | 713 | } |
| 702 | 714 | ||
