1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * synth callback routines for the emu8000 (AWE32/64)
5 * Copyright (C) 1999 Steve Ratcliffe
6 * Copyright (C) 1999-2000 Takashi Iwai <tiwai@suse.de>
9 #include "emu8000_local.h"
10 #include <linux/export.h>
11 #include <sound/asoundef.h>
16 static struct snd_emux_voice
*get_voice(struct snd_emux
*emu
,
17 struct snd_emux_port
*port
);
18 static int start_voice(struct snd_emux_voice
*vp
);
19 static void trigger_voice(struct snd_emux_voice
*vp
);
20 static void release_voice(struct snd_emux_voice
*vp
);
21 static void update_voice(struct snd_emux_voice
*vp
, int update
);
22 static void reset_voice(struct snd_emux
*emu
, int ch
);
23 static void terminate_voice(struct snd_emux_voice
*vp
);
24 static void sysex(struct snd_emux
*emu
, char *buf
, int len
, int parsed
,
25 struct snd_midi_channel_set
*chset
);
26 #if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS)
27 static int oss_ioctl(struct snd_emux
*emu
, int cmd
, int p1
, int p2
);
29 static int load_fx(struct snd_emux
*emu
, int type
, int mode
,
30 const void __user
*buf
, long len
);
32 static void set_pitch(struct snd_emu8000
*hw
, struct snd_emux_voice
*vp
);
33 static void set_volume(struct snd_emu8000
*hw
, struct snd_emux_voice
*vp
);
34 static void set_pan(struct snd_emu8000
*hw
, struct snd_emux_voice
*vp
);
35 static void set_fmmod(struct snd_emu8000
*hw
, struct snd_emux_voice
*vp
);
36 static void set_tremfreq(struct snd_emu8000
*hw
, struct snd_emux_voice
*vp
);
37 static void set_fm2frq2(struct snd_emu8000
*hw
, struct snd_emux_voice
*vp
);
38 static void set_filterQ(struct snd_emu8000
*hw
, struct snd_emux_voice
*vp
);
39 static void snd_emu8000_tweak_voice(struct snd_emu8000
*emu
, int ch
);
42 * Ensure a value is between two points
43 * macro evaluates its args more than once, so changed to upper-case.
45 #define LIMITVALUE(x, a, b) do { if ((x) < (a)) (x) = (a); else if ((x) > (b)) (x) = (b); } while (0)
46 #define LIMITMAX(x, a) do {if ((x) > (a)) (x) = (a); } while (0)
52 static const struct snd_emux_operators emu8000_ops
= {
54 .get_voice
= get_voice
,
55 .prepare
= start_voice
,
56 .trigger
= trigger_voice
,
57 .release
= release_voice
,
58 .update
= update_voice
,
59 .terminate
= terminate_voice
,
61 .sample_new
= snd_emu8000_sample_new
,
62 .sample_free
= snd_emu8000_sample_free
,
63 .sample_reset
= snd_emu8000_sample_reset
,
66 #if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS)
67 .oss_ioctl
= oss_ioctl
,
72 snd_emu8000_ops_setup(struct snd_emu8000
*hw
)
74 hw
->emu
->ops
= emu8000_ops
;
83 release_voice(struct snd_emux_voice
*vp
)
86 struct snd_emu8000
*hw
;
89 dcysusv
= 0x8000 | (unsigned char)vp
->reg
.parm
.modrelease
;
90 EMU8000_DCYSUS_WRITE(hw
, vp
->ch
, dcysusv
);
91 dcysusv
= 0x8000 | (unsigned char)vp
->reg
.parm
.volrelease
;
92 EMU8000_DCYSUSV_WRITE(hw
, vp
->ch
, dcysusv
);
99 terminate_voice(struct snd_emux_voice
*vp
)
101 struct snd_emu8000
*hw
;
104 EMU8000_DCYSUSV_WRITE(hw
, vp
->ch
, 0x807F);
111 update_voice(struct snd_emux_voice
*vp
, int update
)
113 struct snd_emu8000
*hw
;
116 if (update
& SNDRV_EMUX_UPDATE_VOLUME
)
118 if (update
& SNDRV_EMUX_UPDATE_PITCH
)
120 if ((update
& SNDRV_EMUX_UPDATE_PAN
) &&
121 vp
->port
->ctrls
[EMUX_MD_REALTIME_PAN
])
123 if (update
& SNDRV_EMUX_UPDATE_FMMOD
)
125 if (update
& SNDRV_EMUX_UPDATE_TREMFREQ
)
126 set_tremfreq(hw
, vp
);
127 if (update
& SNDRV_EMUX_UPDATE_FM2FRQ2
)
129 if (update
& SNDRV_EMUX_UPDATE_Q
)
135 * Find a channel (voice) within the EMU that is not in use or at least
136 * less in use than other channels. Always returns a valid pointer
137 * no matter what. If there is a real shortage of voices then one
138 * will be cut. Such is life.
140 * The channel index (vp->ch) must be initialized in this routine.
141 * In Emu8k, it is identical with the array index.
143 static struct snd_emux_voice
*
144 get_voice(struct snd_emux
*emu
, struct snd_emux_port
*port
)
147 struct snd_emux_voice
*vp
;
148 struct snd_emu8000
*hw
;
150 /* what we are looking for, in order of preference */
152 OFF
=0, RELEASED
, PLAYING
, END
155 /* Keeps track of what we are finding */
164 for (i
= 0; i
< END
; i
++) {
165 best
[i
].time
= (unsigned int)(-1); /* XXX MAX_?INT really */
170 * Go through them all and get a best one to use.
172 for (i
= 0; i
< emu
->max_voices
; i
++) {
175 vp
= &emu
->voices
[i
];
178 if (state
== SNDRV_EMUX_ST_OFF
)
180 else if (state
== SNDRV_EMUX_ST_RELEASED
||
181 state
== SNDRV_EMUX_ST_PENDING
) {
182 bp
= best
+ RELEASED
;
183 val
= (EMU8000_CVCF_READ(hw
, vp
->ch
) >> 16) & 0xffff;
187 else if (state
& SNDRV_EMUX_ST_ON
)
192 /* check if sample is finished playing (non-looping only) */
193 if (state
!= SNDRV_EMUX_ST_OFF
&&
194 (vp
->reg
.sample_mode
& SNDRV_SFNT_SAMPLE_SINGLESHOT
)) {
195 val
= EMU8000_CCCA_READ(hw
, vp
->ch
) & 0xffffff;
196 if (val
>= vp
->reg
.loopstart
)
200 if (vp
->time
< bp
->time
) {
206 for (i
= 0; i
< END
; i
++) {
207 if (best
[i
].voice
>= 0) {
208 vp
= &emu
->voices
[best
[i
].voice
];
209 vp
->ch
= best
[i
].voice
;
221 start_voice(struct snd_emux_voice
*vp
)
226 struct snd_midi_channel
*chan
;
227 struct snd_emu8000
*hw
;
233 /* channel to be silent and idle */
234 EMU8000_DCYSUSV_WRITE(hw
, ch
, 0x0080);
235 EMU8000_VTFT_WRITE(hw
, ch
, 0x0000FFFF);
236 EMU8000_CVCF_WRITE(hw
, ch
, 0x0000FFFF);
237 EMU8000_PTRX_WRITE(hw
, ch
, 0);
238 EMU8000_CPF_WRITE(hw
, ch
, 0);
240 /* set pitch offset */
243 /* set envelope parameters */
244 EMU8000_ENVVAL_WRITE(hw
, ch
, vp
->reg
.parm
.moddelay
);
245 EMU8000_ATKHLD_WRITE(hw
, ch
, vp
->reg
.parm
.modatkhld
);
246 EMU8000_DCYSUS_WRITE(hw
, ch
, vp
->reg
.parm
.moddcysus
);
247 EMU8000_ENVVOL_WRITE(hw
, ch
, vp
->reg
.parm
.voldelay
);
248 EMU8000_ATKHLDV_WRITE(hw
, ch
, vp
->reg
.parm
.volatkhld
);
249 /* decay/sustain parameter for volume envelope is used
250 for triggerg the voice */
252 /* cutoff and volume */
255 /* modulation envelope heights */
256 EMU8000_PEFE_WRITE(hw
, ch
, vp
->reg
.parm
.pefe
);
259 EMU8000_LFO1VAL_WRITE(hw
, ch
, vp
->reg
.parm
.lfo1delay
);
260 EMU8000_LFO2VAL_WRITE(hw
, ch
, vp
->reg
.parm
.lfo2delay
);
262 /* lfo1 pitch & cutoff shift */
264 /* lfo1 volume & freq */
265 set_tremfreq(hw
, vp
);
266 /* lfo2 pitch & freq */
268 /* pan & loop start */
271 /* chorus & loop end (chorus 8bit, MSB) */
272 addr
= vp
->reg
.loopend
- 1;
273 temp
= vp
->reg
.parm
.chorus
;
274 temp
+= (int)chan
->control
[MIDI_CTL_E3_CHORUS_DEPTH
] * 9 / 10;
276 temp
= (temp
<<24) | (unsigned int)addr
;
277 EMU8000_CSL_WRITE(hw
, ch
, temp
);
279 /* Q & current address (Q 4bit value, MSB) */
280 addr
= vp
->reg
.start
- 1;
281 temp
= vp
->reg
.parm
.filterQ
;
282 temp
= (temp
<<28) | (unsigned int)addr
;
283 EMU8000_CCCA_WRITE(hw
, ch
, temp
);
285 /* clear unknown registers */
286 EMU8000_00A0_WRITE(hw
, ch
, 0);
287 EMU8000_0080_WRITE(hw
, ch
, 0);
290 temp
= vp
->vtarget
<< 16;
291 EMU8000_VTFT_WRITE(hw
, ch
, temp
| vp
->ftarget
);
292 EMU8000_CVCF_WRITE(hw
, ch
, temp
| 0xff00);
301 trigger_voice(struct snd_emux_voice
*vp
)
305 struct snd_emu8000
*hw
;
309 /* set reverb and pitch target */
310 temp
= vp
->reg
.parm
.reverb
;
311 temp
+= (int)vp
->chan
->control
[MIDI_CTL_E1_REVERB_DEPTH
] * 9 / 10;
313 temp
= (temp
<< 8) | (vp
->ptarget
<< 16) | vp
->aaux
;
314 EMU8000_PTRX_WRITE(hw
, ch
, temp
);
315 EMU8000_CPF_WRITE(hw
, ch
, vp
->ptarget
<< 16);
316 EMU8000_DCYSUSV_WRITE(hw
, ch
, vp
->reg
.parm
.voldcysus
);
320 * reset voice parameters
323 reset_voice(struct snd_emux
*emu
, int ch
)
325 struct snd_emu8000
*hw
;
328 EMU8000_DCYSUSV_WRITE(hw
, ch
, 0x807F);
329 snd_emu8000_tweak_voice(hw
, ch
);
333 * Set the pitch of a possibly playing note.
336 set_pitch(struct snd_emu8000
*hw
, struct snd_emux_voice
*vp
)
338 EMU8000_IP_WRITE(hw
, vp
->ch
, vp
->apitch
);
342 * Set the volume of a possibly already playing note
345 set_volume(struct snd_emu8000
*hw
, struct snd_emux_voice
*vp
)
349 ifatn
= (unsigned char)vp
->acutoff
;
350 ifatn
= (ifatn
<< 8);
351 ifatn
|= (unsigned char)vp
->avol
;
352 EMU8000_IFATN_WRITE(hw
, vp
->ch
, ifatn
);
356 * Set pan and loop start address.
359 set_pan(struct snd_emu8000
*hw
, struct snd_emux_voice
*vp
)
363 temp
= ((unsigned int)vp
->apan
<<24) | ((unsigned int)vp
->reg
.loopstart
- 1);
364 EMU8000_PSST_WRITE(hw
, vp
->ch
, temp
);
370 set_fmmod(struct snd_emu8000
*hw
, struct snd_emux_voice
*vp
)
372 unsigned short fmmod
;
374 unsigned char cutoff
;
377 pitch
= (char)(vp
->reg
.parm
.fmmod
>>8);
378 cutoff
= (vp
->reg
.parm
.fmmod
& 0xff);
379 modulation
= vp
->chan
->gm_modulation
+ vp
->chan
->midi_pressure
;
380 pitch
+= (MOD_SENSE
* modulation
) / 1200;
381 LIMITVALUE(pitch
, -128, 127);
382 fmmod
= ((unsigned char)pitch
<<8) | cutoff
;
383 EMU8000_FMMOD_WRITE(hw
, vp
->ch
, fmmod
);
386 /* set tremolo (lfo1) volume & frequency */
388 set_tremfreq(struct snd_emu8000
*hw
, struct snd_emux_voice
*vp
)
390 EMU8000_TREMFRQ_WRITE(hw
, vp
->ch
, vp
->reg
.parm
.tremfrq
);
393 /* set lfo2 pitch & frequency */
395 set_fm2frq2(struct snd_emu8000
*hw
, struct snd_emux_voice
*vp
)
397 unsigned short fm2frq2
;
402 pitch
= (char)(vp
->reg
.parm
.fm2frq2
>>8);
403 freq
= vp
->reg
.parm
.fm2frq2
& 0xff;
404 modulation
= vp
->chan
->gm_modulation
+ vp
->chan
->midi_pressure
;
405 pitch
+= (MOD_SENSE
* modulation
) / 1200;
406 LIMITVALUE(pitch
, -128, 127);
407 fm2frq2
= ((unsigned char)pitch
<<8) | freq
;
408 EMU8000_FM2FRQ2_WRITE(hw
, vp
->ch
, fm2frq2
);
413 set_filterQ(struct snd_emu8000
*hw
, struct snd_emux_voice
*vp
)
416 addr
= EMU8000_CCCA_READ(hw
, vp
->ch
) & 0xffffff;
417 addr
|= (vp
->reg
.parm
.filterQ
<< 28);
418 EMU8000_CCCA_WRITE(hw
, vp
->ch
, addr
);
422 * set the envelope & LFO parameters to the default values
425 snd_emu8000_tweak_voice(struct snd_emu8000
*emu
, int i
)
427 /* set all mod/vol envelope shape to minimum */
428 EMU8000_ENVVOL_WRITE(emu
, i
, 0x8000);
429 EMU8000_ENVVAL_WRITE(emu
, i
, 0x8000);
430 EMU8000_DCYSUS_WRITE(emu
, i
, 0x7F7F);
431 EMU8000_ATKHLDV_WRITE(emu
, i
, 0x7F7F);
432 EMU8000_ATKHLD_WRITE(emu
, i
, 0x7F7F);
433 EMU8000_PEFE_WRITE(emu
, i
, 0); /* mod envelope height to zero */
434 EMU8000_LFO1VAL_WRITE(emu
, i
, 0x8000); /* no delay for LFO1 */
435 EMU8000_LFO2VAL_WRITE(emu
, i
, 0x8000);
436 EMU8000_IP_WRITE(emu
, i
, 0xE000); /* no pitch shift */
437 EMU8000_IFATN_WRITE(emu
, i
, 0xFF00); /* volume to minimum */
438 EMU8000_FMMOD_WRITE(emu
, i
, 0);
439 EMU8000_TREMFRQ_WRITE(emu
, i
, 0);
440 EMU8000_FM2FRQ2_WRITE(emu
, i
, 0);
447 sysex(struct snd_emux
*emu
, char *buf
, int len
, int parsed
, struct snd_midi_channel_set
*chset
)
449 struct snd_emu8000
*hw
;
454 case SNDRV_MIDI_SYSEX_GS_CHORUS_MODE
:
455 hw
->chorus_mode
= chset
->gs_chorus_mode
;
456 snd_emu8000_update_chorus_mode(hw
);
459 case SNDRV_MIDI_SYSEX_GS_REVERB_MODE
:
460 hw
->reverb_mode
= chset
->gs_reverb_mode
;
461 snd_emu8000_update_reverb_mode(hw
);
467 #if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS)
472 oss_ioctl(struct snd_emux
*emu
, int cmd
, int p1
, int p2
)
474 struct snd_emu8000
*hw
;
479 case _EMUX_OSS_REVERB_MODE
:
480 hw
->reverb_mode
= p1
;
481 snd_emu8000_update_reverb_mode(hw
);
484 case _EMUX_OSS_CHORUS_MODE
:
485 hw
->chorus_mode
= p1
;
486 snd_emu8000_update_chorus_mode(hw
);
489 case _EMUX_OSS_INITIALIZE_CHIP
:
490 /* snd_emu8000_init(hw); */ /*ignored*/
493 case _EMUX_OSS_EQUALIZER
:
495 hw
->treble_level
= p2
;
496 snd_emu8000_update_equalizer(hw
);
505 * additional patch keys
508 #define SNDRV_EMU8000_LOAD_CHORUS_FX 0x10 /* optarg=mode */
509 #define SNDRV_EMU8000_LOAD_REVERB_FX 0x11 /* optarg=mode */
517 load_fx(struct snd_emux
*emu
, int type
, int mode
, const void __user
*buf
, long len
)
519 struct snd_emu8000
*hw
;
527 case SNDRV_EMU8000_LOAD_CHORUS_FX
:
528 return snd_emu8000_load_chorus_fx(hw
, mode
, buf
, len
);
529 case SNDRV_EMU8000_LOAD_REVERB_FX
:
530 return snd_emu8000_load_reverb_fx(hw
, mode
, buf
, len
);