Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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)