d_opl4_write(opl4, OPL4_REG_MISC + voice[i]->number,
			       voice[i]->reg_misc);
	}
	spin_unlock_irqrestore(&opl4->reg_lock, flags);
}

static void snd_opl4_voice_off(struct snd_opl4 *opl4, struct opl4_voice *voice)
{
	list_move_tail(&voice->list, &opl4->off_voices);

	voice->reg_misc &= ~OPL4_KEY_ON_BIT;
	snd_opl4_write(opl4, OPL4_REG_MISC + voice->number, voice->reg_misc);
}

void snd_opl4_note_off(void *private_data, int note, int vel, struct snd_midi_channel *chan)
{
	struct snd_opl4 *opl4 = private_data;

	snd_opl4_do_for_note(opl4, note, chan, snd_opl4_voice_off);
}

static void snd_opl4_terminate_voice(struct snd_opl4 *opl4, struct opl4_voice *voice)
{
	list_move_tail(&voice->list, &opl4->off_voices);

	voice->reg_misc = (voice->reg_misc & ~OPL4_KEY_ON_BIT) | OPL4_DAMP_BIT;
	snd_opl4_write(opl4, OPL4_REG_MISC + voice->number, voice->reg_misc);
}

void snd_opl4_terminate_note(void *private_data, int note, struct snd_midi_channel *chan)
{
	struct snd_opl4 *opl4 = private_data;

	snd_opl4_do_for_note(opl4, note, chan, snd_opl4_terminate_voice);
}

void snd_opl4_control(void *private_data, int type, struct snd_midi_channel *chan)
{
	struct snd_opl4 *opl4 = private_data;

	switch (type) {
	case MIDI_CTL_MSB_MODWHEEL:
		chan->control[MIDI_CTL_VIBRATO_DEPTH] = chan->control[MIDI_CTL_MSB_MODWHEEL];
		snd_opl4_do_for_channel(opl4, chan, snd_opl4_update_vibrato_depth);
		break;
	case MIDI_CTL_MSB_MAIN_VOLUME:
		snd_opl4_do_for_channel(opl4, chan, snd_opl4_update_volume);
		break;
	case MIDI_CTL_MSB_PAN:
		snd_opl4_do_for_channel(opl4, chan, snd_opl4_update_pan);
		break;
	case MIDI_CTL_MSB_EXPRESSION:
		snd_opl4_do_for_channel(opl4, chan, snd_opl4_update_volume);
		break;
	case MIDI_CTL_VIBRATO_RATE:
		/* not yet supported */
		break;
	case MIDI_CTL_VIBRATO_DEPTH:
		snd_opl4_do_for_channel(opl4, chan, snd_opl4_update_vibrato_depth);
		break;
	case MIDI_CTL_VIBRATO_DELAY:
		/* not yet supported */
		break;
	case MIDI_CTL_E1_REVERB_DEPTH:
		/*
		 * Each OPL4 voice has a bit called "Pseudo-Reverb", but
		 * IMHO _no