^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * synth callback routines for the emu8000 (AWE32/64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 1999 Steve Ratcliffe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 1999-2000 Takashi Iwai <tiwai@suse.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include "emu8000_local.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <sound/asoundef.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * prototypes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) static struct snd_emux_voice *get_voice(struct snd_emux *emu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) struct snd_emux_port *port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) static int start_voice(struct snd_emux_voice *vp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) static void trigger_voice(struct snd_emux_voice *vp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) static void release_voice(struct snd_emux_voice *vp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) static void update_voice(struct snd_emux_voice *vp, int update);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) static void reset_voice(struct snd_emux *emu, int ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) static void terminate_voice(struct snd_emux_voice *vp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) static void sysex(struct snd_emux *emu, char *buf, int len, int parsed,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) struct snd_midi_channel_set *chset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) static int oss_ioctl(struct snd_emux *emu, int cmd, int p1, int p2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) static int load_fx(struct snd_emux *emu, int type, int mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) const void __user *buf, long len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) static void set_pitch(struct snd_emu8000 *hw, struct snd_emux_voice *vp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) static void set_volume(struct snd_emu8000 *hw, struct snd_emux_voice *vp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) static void set_pan(struct snd_emu8000 *hw, struct snd_emux_voice *vp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) static void set_fmmod(struct snd_emu8000 *hw, struct snd_emux_voice *vp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static void set_tremfreq(struct snd_emu8000 *hw, struct snd_emux_voice *vp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) static void set_fm2frq2(struct snd_emu8000 *hw, struct snd_emux_voice *vp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) static void set_filterQ(struct snd_emu8000 *hw, struct snd_emux_voice *vp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static void snd_emu8000_tweak_voice(struct snd_emu8000 *emu, int ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * Ensure a value is between two points
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * macro evaluates its args more than once, so changed to upper-case.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define LIMITVALUE(x, a, b) do { if ((x) < (a)) (x) = (a); else if ((x) > (b)) (x) = (b); } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define LIMITMAX(x, a) do {if ((x) > (a)) (x) = (a); } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * set up operators
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) static const struct snd_emux_operators emu8000_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) .get_voice = get_voice,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) .prepare = start_voice,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) .trigger = trigger_voice,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) .release = release_voice,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) .update = update_voice,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) .terminate = terminate_voice,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) .reset = reset_voice,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) .sample_new = snd_emu8000_sample_new,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) .sample_free = snd_emu8000_sample_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) .sample_reset = snd_emu8000_sample_reset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) .load_fx = load_fx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) .sysex = sysex,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) .oss_ioctl = oss_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) snd_emu8000_ops_setup(struct snd_emu8000 *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) hw->emu->ops = emu8000_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * Terminate a voice
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) release_voice(struct snd_emux_voice *vp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) int dcysusv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) struct snd_emu8000 *hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) hw = vp->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) dcysusv = 0x8000 | (unsigned char)vp->reg.parm.modrelease;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) EMU8000_DCYSUS_WRITE(hw, vp->ch, dcysusv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) dcysusv = 0x8000 | (unsigned char)vp->reg.parm.volrelease;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) EMU8000_DCYSUSV_WRITE(hw, vp->ch, dcysusv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) terminate_voice(struct snd_emux_voice *vp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) struct snd_emu8000 *hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) hw = vp->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) EMU8000_DCYSUSV_WRITE(hw, vp->ch, 0x807F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) update_voice(struct snd_emux_voice *vp, int update)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) struct snd_emu8000 *hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) hw = vp->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) if (update & SNDRV_EMUX_UPDATE_VOLUME)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) set_volume(hw, vp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) if (update & SNDRV_EMUX_UPDATE_PITCH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) set_pitch(hw, vp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) if ((update & SNDRV_EMUX_UPDATE_PAN) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) vp->port->ctrls[EMUX_MD_REALTIME_PAN])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) set_pan(hw, vp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) if (update & SNDRV_EMUX_UPDATE_FMMOD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) set_fmmod(hw, vp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) if (update & SNDRV_EMUX_UPDATE_TREMFREQ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) set_tremfreq(hw, vp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) if (update & SNDRV_EMUX_UPDATE_FM2FRQ2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) set_fm2frq2(hw, vp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) if (update & SNDRV_EMUX_UPDATE_Q)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) set_filterQ(hw, vp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) * Find a channel (voice) within the EMU that is not in use or at least
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) * less in use than other channels. Always returns a valid pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) * no matter what. If there is a real shortage of voices then one
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) * will be cut. Such is life.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) * The channel index (vp->ch) must be initialized in this routine.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) * In Emu8k, it is identical with the array index.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) static struct snd_emux_voice *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) get_voice(struct snd_emux *emu, struct snd_emux_port *port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) struct snd_emux_voice *vp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) struct snd_emu8000 *hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) /* what we are looking for, in order of preference */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) OFF=0, RELEASED, PLAYING, END
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) /* Keeps track of what we are finding */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) struct best {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) unsigned int time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) int voice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) } best[END];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) struct best *bp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) hw = emu->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) for (i = 0; i < END; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) best[i].time = (unsigned int)(-1); /* XXX MAX_?INT really */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) best[i].voice = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) * Go through them all and get a best one to use.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) for (i = 0; i < emu->max_voices; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) int state, val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) vp = &emu->voices[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) state = vp->state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) if (state == SNDRV_EMUX_ST_OFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) bp = best + OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) else if (state == SNDRV_EMUX_ST_RELEASED ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) state == SNDRV_EMUX_ST_PENDING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) bp = best + RELEASED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) val = (EMU8000_CVCF_READ(hw, vp->ch) >> 16) & 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) if (! val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) bp = best + OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) else if (state & SNDRV_EMUX_ST_ON)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) bp = best + PLAYING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) /* check if sample is finished playing (non-looping only) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) if (state != SNDRV_EMUX_ST_OFF &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) (vp->reg.sample_mode & SNDRV_SFNT_SAMPLE_SINGLESHOT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) val = EMU8000_CCCA_READ(hw, vp->ch) & 0xffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) if (val >= vp->reg.loopstart)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) bp = best + OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) if (vp->time < bp->time) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) bp->time = vp->time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) bp->voice = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) for (i = 0; i < END; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if (best[i].voice >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) vp = &emu->voices[best[i].voice];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) vp->ch = best[i].voice;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) return vp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) /* not found */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) start_voice(struct snd_emux_voice *vp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) unsigned int temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) int ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) int addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) struct snd_midi_channel *chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) struct snd_emu8000 *hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) hw = vp->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) ch = vp->ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) chan = vp->chan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) /* channel to be silent and idle */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) EMU8000_DCYSUSV_WRITE(hw, ch, 0x0080);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) EMU8000_VTFT_WRITE(hw, ch, 0x0000FFFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) EMU8000_CVCF_WRITE(hw, ch, 0x0000FFFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) EMU8000_PTRX_WRITE(hw, ch, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) EMU8000_CPF_WRITE(hw, ch, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) /* set pitch offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) set_pitch(hw, vp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) /* set envelope parameters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) EMU8000_ENVVAL_WRITE(hw, ch, vp->reg.parm.moddelay);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) EMU8000_ATKHLD_WRITE(hw, ch, vp->reg.parm.modatkhld);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) EMU8000_DCYSUS_WRITE(hw, ch, vp->reg.parm.moddcysus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) EMU8000_ENVVOL_WRITE(hw, ch, vp->reg.parm.voldelay);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) EMU8000_ATKHLDV_WRITE(hw, ch, vp->reg.parm.volatkhld);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) /* decay/sustain parameter for volume envelope is used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) for triggerg the voice */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) /* cutoff and volume */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) set_volume(hw, vp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) /* modulation envelope heights */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) EMU8000_PEFE_WRITE(hw, ch, vp->reg.parm.pefe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) /* lfo1/2 delay */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) EMU8000_LFO1VAL_WRITE(hw, ch, vp->reg.parm.lfo1delay);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) EMU8000_LFO2VAL_WRITE(hw, ch, vp->reg.parm.lfo2delay);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) /* lfo1 pitch & cutoff shift */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) set_fmmod(hw, vp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) /* lfo1 volume & freq */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) set_tremfreq(hw, vp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) /* lfo2 pitch & freq */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) set_fm2frq2(hw, vp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) /* pan & loop start */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) set_pan(hw, vp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) /* chorus & loop end (chorus 8bit, MSB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) addr = vp->reg.loopend - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) temp = vp->reg.parm.chorus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) temp += (int)chan->control[MIDI_CTL_E3_CHORUS_DEPTH] * 9 / 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) LIMITMAX(temp, 255);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) temp = (temp <<24) | (unsigned int)addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) EMU8000_CSL_WRITE(hw, ch, temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) /* Q & current address (Q 4bit value, MSB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) addr = vp->reg.start - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) temp = vp->reg.parm.filterQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) temp = (temp<<28) | (unsigned int)addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) EMU8000_CCCA_WRITE(hw, ch, temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) /* clear unknown registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) EMU8000_00A0_WRITE(hw, ch, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) EMU8000_0080_WRITE(hw, ch, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) /* reset volume */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) temp = vp->vtarget << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) EMU8000_VTFT_WRITE(hw, ch, temp | vp->ftarget);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) EMU8000_CVCF_WRITE(hw, ch, temp | 0xff00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) * Start envelope
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) trigger_voice(struct snd_emux_voice *vp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) int ch = vp->ch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) unsigned int temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) struct snd_emu8000 *hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) hw = vp->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) /* set reverb and pitch target */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) temp = vp->reg.parm.reverb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) temp += (int)vp->chan->control[MIDI_CTL_E1_REVERB_DEPTH] * 9 / 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) LIMITMAX(temp, 255);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) temp = (temp << 8) | (vp->ptarget << 16) | vp->aaux;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) EMU8000_PTRX_WRITE(hw, ch, temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) EMU8000_CPF_WRITE(hw, ch, vp->ptarget << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) EMU8000_DCYSUSV_WRITE(hw, ch, vp->reg.parm.voldcysus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) * reset voice parameters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) reset_voice(struct snd_emux *emu, int ch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) struct snd_emu8000 *hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) hw = emu->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) EMU8000_DCYSUSV_WRITE(hw, ch, 0x807F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) snd_emu8000_tweak_voice(hw, ch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) * Set the pitch of a possibly playing note.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) set_pitch(struct snd_emu8000 *hw, struct snd_emux_voice *vp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) EMU8000_IP_WRITE(hw, vp->ch, vp->apitch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) * Set the volume of a possibly already playing note
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) set_volume(struct snd_emu8000 *hw, struct snd_emux_voice *vp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) int ifatn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) ifatn = (unsigned char)vp->acutoff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) ifatn = (ifatn << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) ifatn |= (unsigned char)vp->avol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) EMU8000_IFATN_WRITE(hw, vp->ch, ifatn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) * Set pan and loop start address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) set_pan(struct snd_emu8000 *hw, struct snd_emux_voice *vp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) unsigned int temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) temp = ((unsigned int)vp->apan<<24) | ((unsigned int)vp->reg.loopstart - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) EMU8000_PSST_WRITE(hw, vp->ch, temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) #define MOD_SENSE 18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) set_fmmod(struct snd_emu8000 *hw, struct snd_emux_voice *vp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) unsigned short fmmod;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) short pitch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) unsigned char cutoff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) int modulation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) pitch = (char)(vp->reg.parm.fmmod>>8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) cutoff = (vp->reg.parm.fmmod & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) modulation = vp->chan->gm_modulation + vp->chan->midi_pressure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) pitch += (MOD_SENSE * modulation) / 1200;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) LIMITVALUE(pitch, -128, 127);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) fmmod = ((unsigned char)pitch<<8) | cutoff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) EMU8000_FMMOD_WRITE(hw, vp->ch, fmmod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) /* set tremolo (lfo1) volume & frequency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) set_tremfreq(struct snd_emu8000 *hw, struct snd_emux_voice *vp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) EMU8000_TREMFRQ_WRITE(hw, vp->ch, vp->reg.parm.tremfrq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) /* set lfo2 pitch & frequency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) set_fm2frq2(struct snd_emu8000 *hw, struct snd_emux_voice *vp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) unsigned short fm2frq2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) short pitch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) unsigned char freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) int modulation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) pitch = (char)(vp->reg.parm.fm2frq2>>8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) freq = vp->reg.parm.fm2frq2 & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) modulation = vp->chan->gm_modulation + vp->chan->midi_pressure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) pitch += (MOD_SENSE * modulation) / 1200;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) LIMITVALUE(pitch, -128, 127);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) fm2frq2 = ((unsigned char)pitch<<8) | freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) EMU8000_FM2FRQ2_WRITE(hw, vp->ch, fm2frq2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) /* set filterQ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) set_filterQ(struct snd_emu8000 *hw, struct snd_emux_voice *vp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) unsigned int addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) addr = EMU8000_CCCA_READ(hw, vp->ch) & 0xffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) addr |= (vp->reg.parm.filterQ << 28);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) EMU8000_CCCA_WRITE(hw, vp->ch, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) * set the envelope & LFO parameters to the default values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) snd_emu8000_tweak_voice(struct snd_emu8000 *emu, int i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) /* set all mod/vol envelope shape to minimum */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) EMU8000_ENVVOL_WRITE(emu, i, 0x8000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) EMU8000_ENVVAL_WRITE(emu, i, 0x8000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) EMU8000_DCYSUS_WRITE(emu, i, 0x7F7F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) EMU8000_ATKHLDV_WRITE(emu, i, 0x7F7F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) EMU8000_ATKHLD_WRITE(emu, i, 0x7F7F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) EMU8000_PEFE_WRITE(emu, i, 0); /* mod envelope height to zero */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) EMU8000_LFO1VAL_WRITE(emu, i, 0x8000); /* no delay for LFO1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) EMU8000_LFO2VAL_WRITE(emu, i, 0x8000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) EMU8000_IP_WRITE(emu, i, 0xE000); /* no pitch shift */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) EMU8000_IFATN_WRITE(emu, i, 0xFF00); /* volume to minimum */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) EMU8000_FMMOD_WRITE(emu, i, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) EMU8000_TREMFRQ_WRITE(emu, i, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) EMU8000_FM2FRQ2_WRITE(emu, i, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) * sysex callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) sysex(struct snd_emux *emu, char *buf, int len, int parsed, struct snd_midi_channel_set *chset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) struct snd_emu8000 *hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) hw = emu->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) switch (parsed) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) case SNDRV_MIDI_SYSEX_GS_CHORUS_MODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) hw->chorus_mode = chset->gs_chorus_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) snd_emu8000_update_chorus_mode(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) case SNDRV_MIDI_SYSEX_GS_REVERB_MODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) hw->reverb_mode = chset->gs_reverb_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) snd_emu8000_update_reverb_mode(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) #if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) * OSS ioctl callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) oss_ioctl(struct snd_emux *emu, int cmd, int p1, int p2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) struct snd_emu8000 *hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) hw = emu->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) case _EMUX_OSS_REVERB_MODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) hw->reverb_mode = p1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) snd_emu8000_update_reverb_mode(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) case _EMUX_OSS_CHORUS_MODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) hw->chorus_mode = p1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) snd_emu8000_update_chorus_mode(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) case _EMUX_OSS_INITIALIZE_CHIP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) /* snd_emu8000_init(hw); */ /*ignored*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) case _EMUX_OSS_EQUALIZER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) hw->bass_level = p1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) hw->treble_level = p2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) snd_emu8000_update_equalizer(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) * additional patch keys
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) #define SNDRV_EMU8000_LOAD_CHORUS_FX 0x10 /* optarg=mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) #define SNDRV_EMU8000_LOAD_REVERB_FX 0x11 /* optarg=mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) * callback routine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) load_fx(struct snd_emux *emu, int type, int mode, const void __user *buf, long len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) struct snd_emu8000 *hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) hw = emu->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) /* skip header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) buf += 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) len -= 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) case SNDRV_EMU8000_LOAD_CHORUS_FX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) return snd_emu8000_load_chorus_fx(hw, mode, buf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) case SNDRV_EMU8000_LOAD_REVERB_FX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) return snd_emu8000_load_reverb_fx(hw, mode, buf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)