diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /sound/oss/awe_wave.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'sound/oss/awe_wave.c')
-rw-r--r-- | sound/oss/awe_wave.c | 6147 |
1 files changed, 6147 insertions, 0 deletions
diff --git a/sound/oss/awe_wave.c b/sound/oss/awe_wave.c new file mode 100644 index 000000000000..d2b9beda8ace --- /dev/null +++ b/sound/oss/awe_wave.c | |||
@@ -0,0 +1,6147 @@ | |||
1 | /* | ||
2 | * sound/awe_wave.c | ||
3 | * | ||
4 | * The low level driver for the AWE32/SB32/AWE64 wave table synth. | ||
5 | * version 0.4.4; Jan. 4, 2000 | ||
6 | * | ||
7 | * Copyright (C) 1996-2000 Takashi Iwai | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | */ | ||
23 | |||
24 | /* | ||
25 | * Changelog: | ||
26 | * Aug 18, 2003, Adam Belay <ambx1@neo.rr.com> | ||
27 | * - detection code rewrite | ||
28 | */ | ||
29 | |||
30 | #include <linux/awe_voice.h> | ||
31 | #include <linux/config.h> | ||
32 | #include <linux/init.h> | ||
33 | #include <linux/module.h> | ||
34 | #include <linux/string.h> | ||
35 | #include <linux/pnp.h> | ||
36 | |||
37 | #include "sound_config.h" | ||
38 | |||
39 | #include "awe_wave.h" | ||
40 | #include "awe_hw.h" | ||
41 | |||
42 | #ifdef AWE_HAS_GUS_COMPATIBILITY | ||
43 | #include "tuning.h" | ||
44 | #include <linux/ultrasound.h> | ||
45 | #endif | ||
46 | |||
47 | /* | ||
48 | * debug message | ||
49 | */ | ||
50 | |||
51 | #ifdef AWE_DEBUG_ON | ||
52 | #define DEBUG(LVL,XXX) {if (ctrls[AWE_MD_DEBUG_MODE] > LVL) { XXX; }} | ||
53 | #define ERRMSG(XXX) {if (ctrls[AWE_MD_DEBUG_MODE]) { XXX; }} | ||
54 | #define FATALERR(XXX) XXX | ||
55 | #else | ||
56 | #define DEBUG(LVL,XXX) /**/ | ||
57 | #define ERRMSG(XXX) XXX | ||
58 | #define FATALERR(XXX) XXX | ||
59 | #endif | ||
60 | |||
61 | /* | ||
62 | * bank and voice record | ||
63 | */ | ||
64 | |||
65 | typedef struct _sf_list sf_list; | ||
66 | typedef struct _awe_voice_list awe_voice_list; | ||
67 | typedef struct _awe_sample_list awe_sample_list; | ||
68 | |||
69 | /* soundfont record */ | ||
70 | struct _sf_list { | ||
71 | unsigned short sf_id; /* id number */ | ||
72 | unsigned short type; /* lock & shared flags */ | ||
73 | int num_info; /* current info table index */ | ||
74 | int num_sample; /* current sample table index */ | ||
75 | int mem_ptr; /* current word byte pointer */ | ||
76 | awe_voice_list *infos, *last_infos; /* instruments */ | ||
77 | awe_sample_list *samples, *last_samples; /* samples */ | ||
78 | #ifdef AWE_ALLOW_SAMPLE_SHARING | ||
79 | sf_list *shared; /* shared list */ | ||
80 | unsigned char name[AWE_PATCH_NAME_LEN]; /* sharing id */ | ||
81 | #endif | ||
82 | sf_list *next, *prev; | ||
83 | }; | ||
84 | |||
85 | /* instrument list */ | ||
86 | struct _awe_voice_list { | ||
87 | awe_voice_info v; /* instrument information */ | ||
88 | sf_list *holder; /* parent sf_list of this record */ | ||
89 | unsigned char bank, instr; /* preset number information */ | ||
90 | char type, disabled; /* type=normal/mapped, disabled=boolean */ | ||
91 | awe_voice_list *next; /* linked list with same sf_id */ | ||
92 | awe_voice_list *next_instr; /* instrument list */ | ||
93 | awe_voice_list *next_bank; /* hash table list */ | ||
94 | }; | ||
95 | |||
96 | /* voice list type */ | ||
97 | #define V_ST_NORMAL 0 | ||
98 | #define V_ST_MAPPED 1 | ||
99 | |||
100 | /* sample list */ | ||
101 | struct _awe_sample_list { | ||
102 | awe_sample_info v; /* sample information */ | ||
103 | sf_list *holder; /* parent sf_list of this record */ | ||
104 | awe_sample_list *next; /* linked list with same sf_id */ | ||
105 | }; | ||
106 | |||
107 | /* sample and information table */ | ||
108 | static int current_sf_id; /* current number of fonts */ | ||
109 | static int locked_sf_id; /* locked position */ | ||
110 | static sf_list *sfhead, *sftail; /* linked-lists */ | ||
111 | |||
112 | #define awe_free_mem_ptr() (sftail ? sftail->mem_ptr : 0) | ||
113 | #define awe_free_info() (sftail ? sftail->num_info : 0) | ||
114 | #define awe_free_sample() (sftail ? sftail->num_sample : 0) | ||
115 | |||
116 | #define AWE_MAX_PRESETS 256 | ||
117 | #define AWE_DEFAULT_PRESET 0 | ||
118 | #define AWE_DEFAULT_BANK 0 | ||
119 | #define AWE_DEFAULT_DRUM 0 | ||
120 | #define AWE_DRUM_BANK 128 | ||
121 | |||
122 | #define MAX_LAYERS AWE_MAX_VOICES | ||
123 | |||
124 | /* preset table index */ | ||
125 | static awe_voice_list *preset_table[AWE_MAX_PRESETS]; | ||
126 | |||
127 | /* | ||
128 | * voice table | ||
129 | */ | ||
130 | |||
131 | /* effects table */ | ||
132 | typedef struct FX_Rec { /* channel effects */ | ||
133 | unsigned char flags[AWE_FX_END]; | ||
134 | short val[AWE_FX_END]; | ||
135 | } FX_Rec; | ||
136 | |||
137 | |||
138 | /* channel parameters */ | ||
139 | typedef struct _awe_chan_info { | ||
140 | int channel; /* channel number */ | ||
141 | int bank; /* current tone bank */ | ||
142 | int instr; /* current program */ | ||
143 | int bender; /* midi pitchbend (-8192 - 8192) */ | ||
144 | int bender_range; /* midi bender range (x100) */ | ||
145 | int panning; /* panning (0-127) */ | ||
146 | int main_vol; /* channel volume (0-127) */ | ||
147 | int expression_vol; /* midi expression (0-127) */ | ||
148 | int chan_press; /* channel pressure */ | ||
149 | int sustained; /* sustain status in MIDI */ | ||
150 | FX_Rec fx; /* effects */ | ||
151 | FX_Rec fx_layer[MAX_LAYERS]; /* layer effects */ | ||
152 | } awe_chan_info; | ||
153 | |||
154 | /* voice parameters */ | ||
155 | typedef struct _voice_info { | ||
156 | int state; | ||
157 | #define AWE_ST_OFF (1<<0) /* no sound */ | ||
158 | #define AWE_ST_ON (1<<1) /* playing */ | ||
159 | #define AWE_ST_STANDBY (1<<2) /* stand by for playing */ | ||
160 | #define AWE_ST_SUSTAINED (1<<3) /* sustained */ | ||
161 | #define AWE_ST_MARK (1<<4) /* marked for allocation */ | ||
162 | #define AWE_ST_DRAM (1<<5) /* DRAM read/write */ | ||
163 | #define AWE_ST_FM (1<<6) /* reserved for FM */ | ||
164 | #define AWE_ST_RELEASED (1<<7) /* released */ | ||
165 | |||
166 | int ch; /* midi channel */ | ||
167 | int key; /* internal key for search */ | ||
168 | int layer; /* layer number (for channel mode only) */ | ||
169 | int time; /* allocated time */ | ||
170 | awe_chan_info *cinfo; /* channel info */ | ||
171 | |||
172 | int note; /* midi key (0-127) */ | ||
173 | int velocity; /* midi velocity (0-127) */ | ||
174 | int sostenuto; /* sostenuto on/off */ | ||
175 | awe_voice_info *sample; /* assigned voice */ | ||
176 | |||
177 | /* EMU8000 parameters */ | ||
178 | int apitch; /* pitch parameter */ | ||
179 | int avol; /* volume parameter */ | ||
180 | int apan; /* panning parameter */ | ||
181 | int acutoff; /* cutoff parameter */ | ||
182 | short aaux; /* aux word */ | ||
183 | } voice_info; | ||
184 | |||
185 | /* voice information */ | ||
186 | static voice_info voices[AWE_MAX_VOICES]; | ||
187 | |||
188 | #define IS_NO_SOUND(v) (voices[v].state & (AWE_ST_OFF|AWE_ST_RELEASED|AWE_ST_STANDBY|AWE_ST_SUSTAINED)) | ||
189 | #define IS_NO_EFFECT(v) (voices[v].state != AWE_ST_ON) | ||
190 | #define IS_PLAYING(v) (voices[v].state & (AWE_ST_ON|AWE_ST_SUSTAINED|AWE_ST_RELEASED)) | ||
191 | #define IS_EMPTY(v) (voices[v].state & (AWE_ST_OFF|AWE_ST_MARK|AWE_ST_DRAM|AWE_ST_FM)) | ||
192 | |||
193 | |||
194 | /* MIDI channel effects information (for hw control) */ | ||
195 | static awe_chan_info channels[AWE_MAX_CHANNELS]; | ||
196 | |||
197 | |||
198 | /* | ||
199 | * global variables | ||
200 | */ | ||
201 | |||
202 | #ifndef AWE_DEFAULT_BASE_ADDR | ||
203 | #define AWE_DEFAULT_BASE_ADDR 0 /* autodetect */ | ||
204 | #endif | ||
205 | |||
206 | #ifndef AWE_DEFAULT_MEM_SIZE | ||
207 | #define AWE_DEFAULT_MEM_SIZE -1 /* autodetect */ | ||
208 | #endif | ||
209 | |||
210 | static int io = AWE_DEFAULT_BASE_ADDR; /* Emu8000 base address */ | ||
211 | static int memsize = AWE_DEFAULT_MEM_SIZE; /* memory size in Kbytes */ | ||
212 | #ifdef CONFIG_PNP | ||
213 | static int isapnp = -1; | ||
214 | #else | ||
215 | static int isapnp; | ||
216 | #endif | ||
217 | |||
218 | MODULE_AUTHOR("Takashi Iwai <iwai@ww.uni-erlangen.de>"); | ||
219 | MODULE_DESCRIPTION("SB AWE32/64 WaveTable driver"); | ||
220 | MODULE_LICENSE("GPL"); | ||
221 | |||
222 | module_param(io, int, 0); | ||
223 | MODULE_PARM_DESC(io, "base i/o port of Emu8000"); | ||
224 | module_param(memsize, int, 0); | ||
225 | MODULE_PARM_DESC(memsize, "onboard DRAM size in Kbytes"); | ||
226 | module_param(isapnp, bool, 0); | ||
227 | MODULE_PARM_DESC(isapnp, "use ISAPnP detection"); | ||
228 | |||
229 | /* DRAM start offset */ | ||
230 | static int awe_mem_start = AWE_DRAM_OFFSET; | ||
231 | |||
232 | /* maximum channels for playing */ | ||
233 | static int awe_max_voices = AWE_MAX_VOICES; | ||
234 | |||
235 | static int patch_opened; /* sample already loaded? */ | ||
236 | |||
237 | static char atten_relative = FALSE; | ||
238 | static short atten_offset; | ||
239 | |||
240 | static int awe_present = FALSE; /* awe device present? */ | ||
241 | static int awe_busy = FALSE; /* awe device opened? */ | ||
242 | |||
243 | static int my_dev = -1; | ||
244 | |||
245 | #define DEFAULT_DRUM_FLAGS ((1 << 9) | (1 << 25)) | ||
246 | #define IS_DRUM_CHANNEL(c) (drum_flags & (1 << (c))) | ||
247 | #define DRUM_CHANNEL_ON(c) (drum_flags |= (1 << (c))) | ||
248 | #define DRUM_CHANNEL_OFF(c) (drum_flags &= ~(1 << (c))) | ||
249 | static unsigned int drum_flags = DEFAULT_DRUM_FLAGS; /* channel flags */ | ||
250 | |||
251 | static int playing_mode = AWE_PLAY_INDIRECT; | ||
252 | #define SINGLE_LAYER_MODE() (playing_mode == AWE_PLAY_INDIRECT || playing_mode == AWE_PLAY_DIRECT) | ||
253 | #define MULTI_LAYER_MODE() (playing_mode == AWE_PLAY_MULTI || playing_mode == AWE_PLAY_MULTI2) | ||
254 | |||
255 | static int current_alloc_time; /* voice allocation index for channel mode */ | ||
256 | |||
257 | static struct synth_info awe_info = { | ||
258 | "AWE32 Synth", /* name */ | ||
259 | 0, /* device */ | ||
260 | SYNTH_TYPE_SAMPLE, /* synth_type */ | ||
261 | SAMPLE_TYPE_AWE32, /* synth_subtype */ | ||
262 | 0, /* perc_mode (obsolete) */ | ||
263 | AWE_MAX_VOICES, /* nr_voices */ | ||
264 | 0, /* nr_drums (obsolete) */ | ||
265 | 400 /* instr_bank_size */ | ||
266 | }; | ||
267 | |||
268 | |||
269 | static struct voice_alloc_info *voice_alloc; /* set at initialization */ | ||
270 | |||
271 | |||
272 | /* | ||
273 | * function prototypes | ||
274 | */ | ||
275 | |||
276 | static int awe_request_region(void); | ||
277 | static void awe_release_region(void); | ||
278 | |||
279 | static void awe_reset_samples(void); | ||
280 | /* emu8000 chip i/o access */ | ||
281 | static void setup_ports(int p1, int p2, int p3); | ||
282 | static void awe_poke(unsigned short cmd, unsigned short port, unsigned short data); | ||
283 | static void awe_poke_dw(unsigned short cmd, unsigned short port, unsigned int data); | ||
284 | static unsigned short awe_peek(unsigned short cmd, unsigned short port); | ||
285 | static unsigned int awe_peek_dw(unsigned short cmd, unsigned short port); | ||
286 | static void awe_wait(unsigned short delay); | ||
287 | |||
288 | /* initialize emu8000 chip */ | ||
289 | static void awe_initialize(void); | ||
290 | |||
291 | /* set voice parameters */ | ||
292 | static void awe_init_ctrl_parms(int init_all); | ||
293 | static void awe_init_voice_info(awe_voice_info *vp); | ||
294 | static void awe_init_voice_parm(awe_voice_parm *pp); | ||
295 | #ifdef AWE_HAS_GUS_COMPATIBILITY | ||
296 | static int freq_to_note(int freq); | ||
297 | static int calc_rate_offset(int Hz); | ||
298 | /*static int calc_parm_delay(int msec);*/ | ||
299 | static int calc_parm_hold(int msec); | ||
300 | static int calc_parm_attack(int msec); | ||
301 | static int calc_parm_decay(int msec); | ||
302 | static int calc_parm_search(int msec, short *table); | ||
303 | #endif /* gus compat */ | ||
304 | |||
305 | /* turn on/off note */ | ||
306 | static void awe_note_on(int voice); | ||
307 | static void awe_note_off(int voice); | ||
308 | static void awe_terminate(int voice); | ||
309 | static void awe_exclusive_off(int voice); | ||
310 | static void awe_note_off_all(int do_sustain); | ||
311 | |||
312 | /* calculate voice parameters */ | ||
313 | typedef void (*fx_affect_func)(int voice, int forced); | ||
314 | static void awe_set_pitch(int voice, int forced); | ||
315 | static void awe_set_voice_pitch(int voice, int forced); | ||
316 | static void awe_set_volume(int voice, int forced); | ||
317 | static void awe_set_voice_vol(int voice, int forced); | ||
318 | static void awe_set_pan(int voice, int forced); | ||
319 | static void awe_fx_fmmod(int voice, int forced); | ||
320 | static void awe_fx_tremfrq(int voice, int forced); | ||
321 | static void awe_fx_fm2frq2(int voice, int forced); | ||
322 | static void awe_fx_filterQ(int voice, int forced); | ||
323 | static void awe_calc_pitch(int voice); | ||
324 | #ifdef AWE_HAS_GUS_COMPATIBILITY | ||
325 | static void awe_calc_pitch_from_freq(int voice, int freq); | ||
326 | #endif | ||
327 | static void awe_calc_volume(int voice); | ||
328 | static void awe_update_volume(void); | ||
329 | static void awe_change_master_volume(short val); | ||
330 | static void awe_voice_init(int voice, int init_all); | ||
331 | static void awe_channel_init(int ch, int init_all); | ||
332 | static void awe_fx_init(int ch); | ||
333 | static void awe_send_effect(int voice, int layer, int type, int val); | ||
334 | static void awe_modwheel_change(int voice, int value); | ||
335 | |||
336 | /* sequencer interface */ | ||
337 | static int awe_open(int dev, int mode); | ||
338 | static void awe_close(int dev); | ||
339 | static int awe_ioctl(int dev, unsigned int cmd, void __user * arg); | ||
340 | static int awe_kill_note(int dev, int voice, int note, int velocity); | ||
341 | static int awe_start_note(int dev, int v, int note_num, int volume); | ||
342 | static int awe_set_instr(int dev, int voice, int instr_no); | ||
343 | static int awe_set_instr_2(int dev, int voice, int instr_no); | ||
344 | static void awe_reset(int dev); | ||
345 | static void awe_hw_control(int dev, unsigned char *event); | ||
346 | static int awe_load_patch(int dev, int format, const char __user *addr, | ||
347 | int offs, int count, int pmgr_flag); | ||
348 | static void awe_aftertouch(int dev, int voice, int pressure); | ||
349 | static void awe_controller(int dev, int voice, int ctrl_num, int value); | ||
350 | static void awe_panning(int dev, int voice, int value); | ||
351 | static void awe_volume_method(int dev, int mode); | ||
352 | static void awe_bender(int dev, int voice, int value); | ||
353 | static int awe_alloc(int dev, int chn, int note, struct voice_alloc_info *alloc); | ||
354 | static void awe_setup_voice(int dev, int voice, int chn); | ||
355 | |||
356 | #define awe_key_pressure(dev,voice,key,press) awe_start_note(dev,voice,(key)+128,press) | ||
357 | |||
358 | /* hardware controls */ | ||
359 | #ifdef AWE_HAS_GUS_COMPATIBILITY | ||
360 | static void awe_hw_gus_control(int dev, int cmd, unsigned char *event); | ||
361 | #endif | ||
362 | static void awe_hw_awe_control(int dev, int cmd, unsigned char *event); | ||
363 | static void awe_voice_change(int voice, fx_affect_func func); | ||
364 | static void awe_sostenuto_on(int voice, int forced); | ||
365 | static void awe_sustain_off(int voice, int forced); | ||
366 | static void awe_terminate_and_init(int voice, int forced); | ||
367 | |||
368 | /* voice search */ | ||
369 | static int awe_search_key(int bank, int preset, int note); | ||
370 | static awe_voice_list *awe_search_instr(int bank, int preset, int note); | ||
371 | static int awe_search_multi_voices(awe_voice_list *rec, int note, int velocity, awe_voice_info **vlist); | ||
372 | static void awe_alloc_multi_voices(int ch, int note, int velocity, int key); | ||
373 | static void awe_alloc_one_voice(int voice, int note, int velocity); | ||
374 | static int awe_clear_voice(void); | ||
375 | |||
376 | /* load / remove patches */ | ||
377 | static int awe_open_patch(awe_patch_info *patch, const char __user *addr, int count); | ||
378 | static int awe_close_patch(awe_patch_info *patch, const char __user *addr, int count); | ||
379 | static int awe_unload_patch(awe_patch_info *patch, const char __user *addr, int count); | ||
380 | static int awe_load_info(awe_patch_info *patch, const char __user *addr, int count); | ||
381 | static int awe_remove_info(awe_patch_info *patch, const char __user *addr, int count); | ||
382 | static int awe_load_data(awe_patch_info *patch, const char __user *addr, int count); | ||
383 | static int awe_replace_data(awe_patch_info *patch, const char __user *addr, int count); | ||
384 | static int awe_load_map(awe_patch_info *patch, const char __user *addr, int count); | ||
385 | #ifdef AWE_HAS_GUS_COMPATIBILITY | ||
386 | static int awe_load_guspatch(const char __user *addr, int offs, int size, int pmgr_flag); | ||
387 | #endif | ||
388 | /*static int awe_probe_info(awe_patch_info *patch, const char __user *addr, int count);*/ | ||
389 | static int awe_probe_data(awe_patch_info *patch, const char __user *addr, int count); | ||
390 | static sf_list *check_patch_opened(int type, char *name); | ||
391 | static int awe_write_wave_data(const char __user *addr, int offset, awe_sample_list *sp, int channels); | ||
392 | static int awe_create_sf(int type, char *name); | ||
393 | static void awe_free_sf(sf_list *sf); | ||
394 | static void add_sf_info(sf_list *sf, awe_voice_list *rec); | ||
395 | static void add_sf_sample(sf_list *sf, awe_sample_list *smp); | ||
396 | static void purge_old_list(awe_voice_list *rec, awe_voice_list *next); | ||
397 | static void add_info_list(awe_voice_list *rec); | ||
398 | static void awe_remove_samples(int sf_id); | ||
399 | static void rebuild_preset_list(void); | ||
400 | static short awe_set_sample(awe_voice_list *rec); | ||
401 | static awe_sample_list *search_sample_index(sf_list *sf, int sample); | ||
402 | |||
403 | static int is_identical_holder(sf_list *sf1, sf_list *sf2); | ||
404 | #ifdef AWE_ALLOW_SAMPLE_SHARING | ||
405 | static int is_identical_name(unsigned char *name, sf_list *p); | ||
406 | static int is_shared_sf(unsigned char *name); | ||
407 | static int info_duplicated(sf_list *sf, awe_voice_list *rec); | ||
408 | #endif /* allow sharing */ | ||
409 | |||
410 | /* lowlevel functions */ | ||
411 | static void awe_init_audio(void); | ||
412 | static void awe_init_dma(void); | ||
413 | static void awe_init_array(void); | ||
414 | static void awe_send_array(unsigned short *data); | ||
415 | static void awe_tweak_voice(int voice); | ||
416 | static void awe_tweak(void); | ||
417 | static void awe_init_fm(void); | ||
418 | static int awe_open_dram_for_write(int offset, int channels); | ||
419 | static void awe_open_dram_for_check(void); | ||
420 | static void awe_close_dram(void); | ||
421 | /*static void awe_write_dram(unsigned short c);*/ | ||
422 | static int awe_detect_base(int addr); | ||
423 | static int awe_detect(void); | ||
424 | static void awe_check_dram(void); | ||
425 | static int awe_load_chorus_fx(awe_patch_info *patch, const char __user *addr, int count); | ||
426 | static void awe_set_chorus_mode(int mode); | ||
427 | static void awe_update_chorus_mode(void); | ||
428 | static int awe_load_reverb_fx(awe_patch_info *patch, const char __user *addr, int count); | ||
429 | static void awe_set_reverb_mode(int mode); | ||
430 | static void awe_update_reverb_mode(void); | ||
431 | static void awe_equalizer(int bass, int treble); | ||
432 | static void awe_update_equalizer(void); | ||
433 | |||
434 | #ifdef CONFIG_AWE32_MIXER | ||
435 | static void attach_mixer(void); | ||
436 | static void unload_mixer(void); | ||
437 | #endif | ||
438 | |||
439 | #ifdef CONFIG_AWE32_MIDIEMU | ||
440 | static void attach_midiemu(void); | ||
441 | static void unload_midiemu(void); | ||
442 | #endif | ||
443 | |||
444 | #define limitvalue(x, a, b) if ((x) < (a)) (x) = (a); else if ((x) > (b)) (x) = (b) | ||
445 | |||
446 | /* | ||
447 | * control parameters | ||
448 | */ | ||
449 | |||
450 | |||
451 | #ifdef AWE_USE_NEW_VOLUME_CALC | ||
452 | #define DEF_VOLUME_CALC TRUE | ||
453 | #else | ||
454 | #define DEF_VOLUME_CALC FALSE | ||
455 | #endif /* new volume */ | ||
456 | |||
457 | #define DEF_ZERO_ATTEN 32 /* 12dB below */ | ||
458 | #define DEF_MOD_SENSE 18 | ||
459 | #define DEF_CHORUS_MODE 2 | ||
460 | #define DEF_REVERB_MODE 4 | ||
461 | #define DEF_BASS_LEVEL 5 | ||
462 | #define DEF_TREBLE_LEVEL 9 | ||
463 | |||
464 | static struct CtrlParmsDef { | ||
465 | int value; | ||
466 | int init_each_time; | ||
467 | void (*update)(void); | ||
468 | } ctrl_parms[AWE_MD_END] = { | ||
469 | {0,0, NULL}, {0,0, NULL}, /* <-- not used */ | ||
470 | {AWE_VERSION_NUMBER, FALSE, NULL}, | ||
471 | {TRUE, FALSE, NULL}, /* exclusive */ | ||
472 | {TRUE, FALSE, NULL}, /* realpan */ | ||
473 | {AWE_DEFAULT_BANK, FALSE, NULL}, /* gusbank */ | ||
474 | {FALSE, TRUE, NULL}, /* keep effect */ | ||
475 | {DEF_ZERO_ATTEN, FALSE, awe_update_volume}, /* zero_atten */ | ||
476 | {FALSE, FALSE, NULL}, /* chn_prior */ | ||
477 | {DEF_MOD_SENSE, FALSE, NULL}, /* modwheel sense */ | ||
478 | {AWE_DEFAULT_PRESET, FALSE, NULL}, /* def_preset */ | ||
479 | {AWE_DEFAULT_BANK, FALSE, NULL}, /* def_bank */ | ||
480 | {AWE_DEFAULT_DRUM, FALSE, NULL}, /* def_drum */ | ||
481 | {FALSE, FALSE, NULL}, /* toggle_drum_bank */ | ||
482 | {DEF_VOLUME_CALC, FALSE, awe_update_volume}, /* new_volume_calc */ | ||
483 | {DEF_CHORUS_MODE, FALSE, awe_update_chorus_mode}, /* chorus mode */ | ||
484 | {DEF_REVERB_MODE, FALSE, awe_update_reverb_mode}, /* reverb mode */ | ||
485 | {DEF_BASS_LEVEL, FALSE, awe_update_equalizer}, /* bass level */ | ||
486 | {DEF_TREBLE_LEVEL, FALSE, awe_update_equalizer}, /* treble level */ | ||
487 | {0, FALSE, NULL}, /* debug mode */ | ||
488 | {FALSE, FALSE, NULL}, /* pan exchange */ | ||
489 | }; | ||
490 | |||
491 | static int ctrls[AWE_MD_END]; | ||
492 | |||
493 | |||
494 | /* | ||
495 | * synth operation table | ||
496 | */ | ||
497 | |||
498 | static struct synth_operations awe_operations = | ||
499 | { | ||
500 | .owner = THIS_MODULE, | ||
501 | .id = "EMU8K", | ||
502 | .info = &awe_info, | ||
503 | .midi_dev = 0, | ||
504 | .synth_type = SYNTH_TYPE_SAMPLE, | ||
505 | .synth_subtype = SAMPLE_TYPE_AWE32, | ||
506 | .open = awe_open, | ||
507 | .close = awe_close, | ||
508 | .ioctl = awe_ioctl, | ||
509 | .kill_note = awe_kill_note, | ||
510 | .start_note = awe_start_note, | ||
511 | .set_instr = awe_set_instr_2, | ||
512 | .reset = awe_reset, | ||
513 | .hw_control = awe_hw_control, | ||
514 | .load_patch = awe_load_patch, | ||
515 | .aftertouch = awe_aftertouch, | ||
516 | .controller = awe_controller, | ||
517 | .panning = awe_panning, | ||
518 | .volume_method = awe_volume_method, | ||
519 | .bender = awe_bender, | ||
520 | .alloc_voice = awe_alloc, | ||
521 | .setup_voice = awe_setup_voice | ||
522 | }; | ||
523 | |||
524 | static void free_tables(void) | ||
525 | { | ||
526 | if (sftail) { | ||
527 | sf_list *p, *prev; | ||
528 | for (p = sftail; p; p = prev) { | ||
529 | prev = p->prev; | ||
530 | awe_free_sf(p); | ||
531 | } | ||
532 | } | ||
533 | sfhead = sftail = NULL; | ||
534 | } | ||
535 | |||
536 | /* | ||
537 | * clear sample tables | ||
538 | */ | ||
539 | |||
540 | static void | ||
541 | awe_reset_samples(void) | ||
542 | { | ||
543 | /* free all bank tables */ | ||
544 | memset(preset_table, 0, sizeof(preset_table)); | ||
545 | free_tables(); | ||
546 | |||
547 | current_sf_id = 0; | ||
548 | locked_sf_id = 0; | ||
549 | patch_opened = 0; | ||
550 | } | ||
551 | |||
552 | |||
553 | /* | ||
554 | * EMU register access | ||
555 | */ | ||
556 | |||
557 | /* select a given AWE32 pointer */ | ||
558 | static int awe_ports[5]; | ||
559 | static int port_setuped = FALSE; | ||
560 | static int awe_cur_cmd = -1; | ||
561 | #define awe_set_cmd(cmd) \ | ||
562 | if (awe_cur_cmd != cmd) { outw(cmd, awe_ports[Pointer]); awe_cur_cmd = cmd; } | ||
563 | |||
564 | /* write 16bit data */ | ||
565 | static void | ||
566 | awe_poke(unsigned short cmd, unsigned short port, unsigned short data) | ||
567 | { | ||
568 | awe_set_cmd(cmd); | ||
569 | outw(data, awe_ports[port]); | ||
570 | } | ||
571 | |||
572 | /* write 32bit data */ | ||
573 | static void | ||
574 | awe_poke_dw(unsigned short cmd, unsigned short port, unsigned int data) | ||
575 | { | ||
576 | unsigned short addr = awe_ports[port]; | ||
577 | awe_set_cmd(cmd); | ||
578 | outw(data, addr); /* write lower 16 bits */ | ||
579 | outw(data >> 16, addr + 2); /* write higher 16 bits */ | ||
580 | } | ||
581 | |||
582 | /* read 16bit data */ | ||
583 | static unsigned short | ||
584 | awe_peek(unsigned short cmd, unsigned short port) | ||
585 | { | ||
586 | unsigned short k; | ||
587 | awe_set_cmd(cmd); | ||
588 | k = inw(awe_ports[port]); | ||
589 | return k; | ||
590 | } | ||
591 | |||
592 | /* read 32bit data */ | ||
593 | static unsigned int | ||
594 | awe_peek_dw(unsigned short cmd, unsigned short port) | ||
595 | { | ||
596 | unsigned int k1, k2; | ||
597 | unsigned short addr = awe_ports[port]; | ||
598 | awe_set_cmd(cmd); | ||
599 | k1 = inw(addr); | ||
600 | k2 = inw(addr + 2); | ||
601 | k1 |= k2 << 16; | ||
602 | return k1; | ||
603 | } | ||
604 | |||
605 | /* wait delay number of AWE32 44100Hz clocks */ | ||
606 | #ifdef WAIT_BY_LOOP /* wait by loop -- that's not good.. */ | ||
607 | static void | ||
608 | awe_wait(unsigned short delay) | ||
609 | { | ||
610 | unsigned short clock, target; | ||
611 | unsigned short port = awe_ports[AWE_WC_Port]; | ||
612 | int counter; | ||
613 | |||
614 | /* sample counter */ | ||
615 | awe_set_cmd(AWE_WC_Cmd); | ||
616 | clock = (unsigned short)inw(port); | ||
617 | target = clock + delay; | ||
618 | counter = 0; | ||
619 | if (target < clock) { | ||
620 | for (; (unsigned short)inw(port) > target; counter++) | ||
621 | if (counter > 65536) | ||
622 | break; | ||
623 | } | ||
624 | for (; (unsigned short)inw(port) < target; counter++) | ||
625 | if (counter > 65536) | ||
626 | break; | ||
627 | } | ||
628 | #else | ||
629 | |||
630 | static void awe_wait(unsigned short delay) | ||
631 | { | ||
632 | current->state = TASK_INTERRUPTIBLE; | ||
633 | schedule_timeout((HZ*(unsigned long)delay + 44099)/44100); | ||
634 | } | ||
635 | /* | ||
636 | static void awe_wait(unsigned short delay) | ||
637 | { | ||
638 | udelay(((unsigned long)delay * 1000000L + 44099) / 44100); | ||
639 | } | ||
640 | */ | ||
641 | #endif /* wait by loop */ | ||
642 | |||
643 | /* write a word data */ | ||
644 | #define awe_write_dram(c) awe_poke(AWE_SMLD, c) | ||
645 | |||
646 | /* | ||
647 | * AWE32 voice parameters | ||
648 | */ | ||
649 | |||
650 | /* initialize voice_info record */ | ||
651 | static void | ||
652 | awe_init_voice_info(awe_voice_info *vp) | ||
653 | { | ||
654 | vp->sample = 0; | ||
655 | vp->rate_offset = 0; | ||
656 | |||
657 | vp->start = 0; | ||
658 | vp->end = 0; | ||
659 | vp->loopstart = 0; | ||
660 | vp->loopend = 0; | ||
661 | vp->mode = 0; | ||
662 | vp->root = 60; | ||
663 | vp->tune = 0; | ||
664 | vp->low = 0; | ||
665 | vp->high = 127; | ||
666 | vp->vellow = 0; | ||
667 | vp->velhigh = 127; | ||
668 | |||
669 | vp->fixkey = -1; | ||
670 | vp->fixvel = -1; | ||
671 | vp->fixpan = -1; | ||
672 | vp->pan = -1; | ||
673 | |||
674 | vp->exclusiveClass = 0; | ||
675 | vp->amplitude = 127; | ||
676 | vp->attenuation = 0; | ||
677 | vp->scaleTuning = 100; | ||
678 | |||
679 | awe_init_voice_parm(&vp->parm); | ||
680 | } | ||
681 | |||
682 | /* initialize voice_parm record: | ||
683 | * Env1/2: delay=0, attack=0, hold=0, sustain=0, decay=0, release=0. | ||
684 | * Vibrato and Tremolo effects are zero. | ||
685 | * Cutoff is maximum. | ||
686 | * Chorus and Reverb effects are zero. | ||
687 | */ | ||
688 | static void | ||
689 | awe_init_voice_parm(awe_voice_parm *pp) | ||
690 | { | ||
691 | pp->moddelay = 0x8000; | ||
692 | pp->modatkhld = 0x7f7f; | ||
693 | pp->moddcysus = 0x7f7f; | ||
694 | pp->modrelease = 0x807f; | ||
695 | pp->modkeyhold = 0; | ||
696 | pp->modkeydecay = 0; | ||
697 | |||
698 | pp->voldelay = 0x8000; | ||
699 | pp->volatkhld = 0x7f7f; | ||
700 | pp->voldcysus = 0x7f7f; | ||
701 | pp->volrelease = 0x807f; | ||
702 | pp->volkeyhold = 0; | ||
703 | pp->volkeydecay = 0; | ||
704 | |||
705 | pp->lfo1delay = 0x8000; | ||
706 | pp->lfo2delay = 0x8000; | ||
707 | pp->pefe = 0; | ||
708 | |||
709 | pp->fmmod = 0; | ||
710 | pp->tremfrq = 0; | ||
711 | pp->fm2frq2 = 0; | ||
712 | |||
713 | pp->cutoff = 0xff; | ||
714 | pp->filterQ = 0; | ||
715 | |||
716 | pp->chorus = 0; | ||
717 | pp->reverb = 0; | ||
718 | } | ||
719 | |||
720 | |||
721 | #ifdef AWE_HAS_GUS_COMPATIBILITY | ||
722 | |||
723 | /* convert frequency mHz to abstract cents (= midi key * 100) */ | ||
724 | static int | ||
725 | freq_to_note(int mHz) | ||
726 | { | ||
727 | /* abscents = log(mHz/8176) / log(2) * 1200 */ | ||
728 | unsigned int max_val = (unsigned int)0xffffffff / 10000; | ||
729 | int i, times; | ||
730 | unsigned int base; | ||
731 | unsigned int freq; | ||
732 | int note, tune; | ||
733 | |||
734 | if (mHz == 0) | ||
735 | return 0; | ||
736 | if (mHz < 0) | ||
737 | return 12799; /* maximum */ | ||
738 | |||
739 | freq = mHz; | ||
740 | note = 0; | ||
741 | for (base = 8176 * 2; freq >= base; base *= 2) { | ||
742 | note += 12; | ||
743 | if (note >= 128) /* over maximum */ | ||
744 | return 12799; | ||
745 | } | ||
746 | base /= 2; | ||
747 | |||
748 | /* to avoid overflow... */ | ||
749 | times = 10000; | ||
750 | while (freq > max_val) { | ||
751 | max_val *= 10; | ||
752 | times /= 10; | ||
753 | base /= 10; | ||
754 | } | ||
755 | |||
756 | freq = freq * times / base; | ||
757 | for (i = 0; i < 12; i++) { | ||
758 | if (freq < semitone_tuning[i+1]) | ||
759 | break; | ||
760 | note++; | ||
761 | } | ||
762 | |||
763 | tune = 0; | ||
764 | freq = freq * 10000 / semitone_tuning[i]; | ||
765 | for (i = 0; i < 100; i++) { | ||
766 | if (freq < cent_tuning[i+1]) | ||
767 | break; | ||
768 | tune++; | ||
769 | } | ||
770 | |||
771 | return note * 100 + tune; | ||
772 | } | ||
773 | |||
774 | |||
775 | /* convert Hz to AWE32 rate offset: | ||
776 | * sample pitch offset for the specified sample rate | ||
777 | * rate=44100 is no offset, each 4096 is 1 octave (twice). | ||
778 | * eg, when rate is 22050, this offset becomes -4096. | ||
779 | */ | ||
780 | static int | ||
781 | calc_rate_offset(int Hz) | ||
782 | { | ||
783 | /* offset = log(Hz / 44100) / log(2) * 4096 */ | ||
784 | int freq, base, i; | ||
785 | |||
786 | /* maybe smaller than max (44100Hz) */ | ||
787 | if (Hz <= 0 || Hz >= 44100) return 0; | ||
788 | |||
789 | base = 0; | ||
790 | for (freq = Hz * 2; freq < 44100; freq *= 2) | ||
791 | base++; | ||
792 | base *= 1200; | ||
793 | |||
794 | freq = 44100 * 10000 / (freq/2); | ||
795 | for (i = 0; i < 12; i++) { | ||
796 | if (freq < semitone_tuning[i+1]) | ||
797 | break; | ||
798 | base += 100; | ||
799 | } | ||
800 | freq = freq * 10000 / semitone_tuning[i]; | ||
801 | for (i = 0; i < 100; i++) { | ||
802 | if (freq < cent_tuning[i+1]) | ||
803 | break; | ||
804 | base++; | ||
805 | } | ||
806 | return -base * 4096 / 1200; | ||
807 | } | ||
808 | |||
809 | |||
810 | /* | ||
811 | * convert envelope time parameter to AWE32 raw parameter | ||
812 | */ | ||
813 | |||
814 | /* attack & decay/release time table (msec) */ | ||
815 | static short attack_time_tbl[128] = { | ||
816 | 32767, 32767, 5989, 4235, 2994, 2518, 2117, 1780, 1497, 1373, 1259, 1154, 1058, 970, 890, 816, | ||
817 | 707, 691, 662, 634, 607, 581, 557, 533, 510, 489, 468, 448, 429, 411, 393, 377, | ||
818 | 361, 345, 331, 317, 303, 290, 278, 266, 255, 244, 234, 224, 214, 205, 196, 188, | ||
819 | 180, 172, 165, 158, 151, 145, 139, 133, 127, 122, 117, 112, 107, 102, 98, 94, | ||
820 | 90, 86, 82, 79, 75, 72, 69, 66, 63, 61, 58, 56, 53, 51, 49, 47, | ||
821 | 45, 43, 41, 39, 37, 36, 34, 33, 31, 30, 29, 28, 26, 25, 24, 23, | ||
822 | 22, 21, 20, 19, 19, 18, 17, 16, 16, 15, 15, 14, 13, 13, 12, 12, | ||
823 | 11, 11, 10, 10, 10, 9, 9, 8, 8, 8, 8, 7, 7, 7, 6, 0, | ||
824 | }; | ||
825 | |||
826 | static short decay_time_tbl[128] = { | ||
827 | 32767, 32767, 22614, 15990, 11307, 9508, 7995, 6723, 5653, 5184, 4754, 4359, 3997, 3665, 3361, 3082, | ||
828 | 2828, 2765, 2648, 2535, 2428, 2325, 2226, 2132, 2042, 1955, 1872, 1793, 1717, 1644, 1574, 1507, | ||
829 | 1443, 1382, 1324, 1267, 1214, 1162, 1113, 1066, 978, 936, 897, 859, 822, 787, 754, 722, | ||
830 | 691, 662, 634, 607, 581, 557, 533, 510, 489, 468, 448, 429, 411, 393, 377, 361, | ||
831 | 345, 331, 317, 303, 290, 278, 266, 255, 244, 234, 224, 214, 205, 196, 188, 180, | ||
832 | 172, 165, 158, 151, 145, 139, 133, 127, 122, 117, 112, 107, 102, 98, 94, 90, | ||
833 | 86, 82, 79, 75, 72, 69, 66, 63, 61, 58, 56, 53, 51, 49, 47, 45, | ||
834 | 43, 41, 39, 37, 36, 34, 33, 31, 30, 29, 28, 26, 25, 24, 23, 22, | ||
835 | }; | ||
836 | |||
837 | #define calc_parm_delay(msec) (0x8000 - (msec) * 1000 / 725); | ||
838 | |||
839 | /* delay time = 0x8000 - msec/92 */ | ||
840 | static int | ||
841 | calc_parm_hold(int msec) | ||
842 | { | ||
843 | int val = (0x7f * 92 - msec) / 92; | ||
844 | if (val < 1) val = 1; | ||
845 | if (val > 127) val = 127; | ||
846 | return val; | ||
847 | } | ||
848 | |||
849 | /* attack time: search from time table */ | ||
850 | static int | ||
851 | calc_parm_attack(int msec) | ||
852 | { | ||
853 | return calc_parm_search(msec, attack_time_tbl); | ||
854 | } | ||
855 | |||
856 | /* decay/release time: search from time table */ | ||
857 | static int | ||
858 | calc_parm_decay(int msec) | ||
859 | { | ||
860 | return calc_parm_search(msec, decay_time_tbl); | ||
861 | } | ||
862 | |||
863 | /* search an index for specified time from given time table */ | ||
864 | static int | ||
865 | calc_parm_search(int msec, short *table) | ||
866 | { | ||
867 | int left = 1, right = 127, mid; | ||
868 | while (left < right) { | ||
869 | mid = (left + right) / 2; | ||
870 | if (msec < (int)table[mid]) | ||
871 | left = mid + 1; | ||
872 | else | ||
873 | right = mid; | ||
874 | } | ||
875 | return left; | ||
876 | } | ||
877 | #endif /* AWE_HAS_GUS_COMPATIBILITY */ | ||
878 | |||
879 | |||
880 | /* | ||
881 | * effects table | ||
882 | */ | ||
883 | |||
884 | /* set an effect value */ | ||
885 | #define FX_FLAG_OFF 0 | ||
886 | #define FX_FLAG_SET 1 | ||
887 | #define FX_FLAG_ADD 2 | ||
888 | |||
889 | #define FX_SET(rec,type,value) \ | ||
890 | ((rec)->flags[type] = FX_FLAG_SET, (rec)->val[type] = (value)) | ||
891 | #define FX_ADD(rec,type,value) \ | ||
892 | ((rec)->flags[type] = FX_FLAG_ADD, (rec)->val[type] = (value)) | ||
893 | #define FX_UNSET(rec,type) \ | ||
894 | ((rec)->flags[type] = FX_FLAG_OFF, (rec)->val[type] = 0) | ||
895 | |||
896 | /* check the effect value is set */ | ||
897 | #define FX_ON(rec,type) ((rec)->flags[type]) | ||
898 | |||
899 | #define PARM_BYTE 0 | ||
900 | #define PARM_WORD 1 | ||
901 | #define PARM_SIGN 2 | ||
902 | |||
903 | static struct PARM_DEFS { | ||
904 | int type; /* byte or word */ | ||
905 | int low, high; /* value range */ | ||
906 | fx_affect_func realtime; /* realtime paramater change */ | ||
907 | } parm_defs[] = { | ||
908 | {PARM_WORD, 0, 0x8000, NULL}, /* env1 delay */ | ||
909 | {PARM_BYTE, 1, 0x7f, NULL}, /* env1 attack */ | ||
910 | {PARM_BYTE, 0, 0x7e, NULL}, /* env1 hold */ | ||
911 | {PARM_BYTE, 1, 0x7f, NULL}, /* env1 decay */ | ||
912 | {PARM_BYTE, 1, 0x7f, NULL}, /* env1 release */ | ||
913 | {PARM_BYTE, 0, 0x7f, NULL}, /* env1 sustain */ | ||
914 | {PARM_BYTE, 0, 0xff, NULL}, /* env1 pitch */ | ||
915 | {PARM_BYTE, 0, 0xff, NULL}, /* env1 cutoff */ | ||
916 | |||
917 | {PARM_WORD, 0, 0x8000, NULL}, /* env2 delay */ | ||
918 | {PARM_BYTE, 1, 0x7f, NULL}, /* env2 attack */ | ||
919 | {PARM_BYTE, 0, 0x7e, NULL}, /* env2 hold */ | ||
920 | {PARM_BYTE, 1, 0x7f, NULL}, /* env2 decay */ | ||
921 | {PARM_BYTE, 1, 0x7f, NULL}, /* env2 release */ | ||
922 | {PARM_BYTE, 0, 0x7f, NULL}, /* env2 sustain */ | ||
923 | |||
924 | {PARM_WORD, 0, 0x8000, NULL}, /* lfo1 delay */ | ||
925 | {PARM_BYTE, 0, 0xff, awe_fx_tremfrq}, /* lfo1 freq */ | ||
926 | {PARM_SIGN, -128, 127, awe_fx_tremfrq}, /* lfo1 volume */ | ||
927 | {PARM_SIGN, -128, 127, awe_fx_fmmod}, /* lfo1 pitch */ | ||
928 | {PARM_BYTE, 0, 0xff, awe_fx_fmmod}, /* lfo1 cutoff */ | ||
929 | |||
930 | {PARM_WORD, 0, 0x8000, NULL}, /* lfo2 delay */ | ||
931 | {PARM_BYTE, 0, 0xff, awe_fx_fm2frq2}, /* lfo2 freq */ | ||
932 | {PARM_SIGN, -128, 127, awe_fx_fm2frq2}, /* lfo2 pitch */ | ||
933 | |||
934 | {PARM_WORD, 0, 0xffff, awe_set_voice_pitch}, /* initial pitch */ | ||
935 | {PARM_BYTE, 0, 0xff, NULL}, /* chorus */ | ||
936 | {PARM_BYTE, 0, 0xff, NULL}, /* reverb */ | ||
937 | {PARM_BYTE, 0, 0xff, awe_set_volume}, /* initial cutoff */ | ||
938 | {PARM_BYTE, 0, 15, awe_fx_filterQ}, /* initial resonance */ | ||
939 | |||
940 | {PARM_WORD, 0, 0xffff, NULL}, /* sample start */ | ||
941 | {PARM_WORD, 0, 0xffff, NULL}, /* loop start */ | ||
942 | {PARM_WORD, 0, 0xffff, NULL}, /* loop end */ | ||
943 | {PARM_WORD, 0, 0xffff, NULL}, /* coarse sample start */ | ||
944 | {PARM_WORD, 0, 0xffff, NULL}, /* coarse loop start */ | ||
945 | {PARM_WORD, 0, 0xffff, NULL}, /* coarse loop end */ | ||
946 | {PARM_BYTE, 0, 0xff, awe_set_volume}, /* initial attenuation */ | ||
947 | }; | ||
948 | |||
949 | |||
950 | static unsigned char | ||
951 | FX_BYTE(FX_Rec *rec, FX_Rec *lay, int type, unsigned char value) | ||
952 | { | ||
953 | int effect = 0; | ||
954 | int on = 0; | ||
955 | if (lay && (on = FX_ON(lay, type)) != 0) | ||
956 | effect = lay->val[type]; | ||
957 | if (!on && (on = FX_ON(rec, type)) != 0) | ||
958 | effect = rec->val[type]; | ||
959 | if (on == FX_FLAG_ADD) { | ||
960 | if (parm_defs[type].type == PARM_SIGN) { | ||
961 | if (value > 0x7f) | ||
962 | effect += (int)value - 0x100; | ||
963 | else | ||
964 | effect += (int)value; | ||
965 | } else { | ||
966 | effect += (int)value; | ||
967 | } | ||
968 | } | ||
969 | if (on) { | ||
970 | if (effect < parm_defs[type].low) | ||
971 | effect = parm_defs[type].low; | ||
972 | else if (effect > parm_defs[type].high) | ||
973 | effect = parm_defs[type].high; | ||
974 | return (unsigned char)effect; | ||
975 | } | ||
976 | return value; | ||
977 | } | ||
978 | |||
979 | /* get word effect value */ | ||
980 | static unsigned short | ||
981 | FX_WORD(FX_Rec *rec, FX_Rec *lay, int type, unsigned short value) | ||
982 | { | ||
983 | int effect = 0; | ||
984 | int on = 0; | ||
985 | if (lay && (on = FX_ON(lay, type)) != 0) | ||
986 | effect = lay->val[type]; | ||
987 | if (!on && (on = FX_ON(rec, type)) != 0) | ||
988 | effect = rec->val[type]; | ||
989 | if (on == FX_FLAG_ADD) | ||
990 | effect += (int)value; | ||
991 | if (on) { | ||
992 | if (effect < parm_defs[type].low) | ||
993 | effect = parm_defs[type].low; | ||
994 | else if (effect > parm_defs[type].high) | ||
995 | effect = parm_defs[type].high; | ||
996 | return (unsigned short)effect; | ||
997 | } | ||
998 | return value; | ||
999 | } | ||
1000 | |||
1001 | /* get word (upper=type1/lower=type2) effect value */ | ||
1002 | static unsigned short | ||
1003 | FX_COMB(FX_Rec *rec, FX_Rec *lay, int type1, int type2, unsigned short value) | ||
1004 | { | ||
1005 | unsigned short tmp; | ||
1006 | tmp = FX_BYTE(rec, lay, type1, (unsigned char)(value >> 8)); | ||
1007 | tmp <<= 8; | ||
1008 | tmp |= FX_BYTE(rec, lay, type2, (unsigned char)(value & 0xff)); | ||
1009 | return tmp; | ||
1010 | } | ||
1011 | |||
1012 | /* address offset */ | ||
1013 | static int | ||
1014 | FX_OFFSET(FX_Rec *rec, FX_Rec *lay, int lo, int hi, int mode) | ||
1015 | { | ||
1016 | int addr = 0; | ||
1017 | if (lay && FX_ON(lay, hi)) | ||
1018 | addr = (short)lay->val[hi]; | ||
1019 | else if (FX_ON(rec, hi)) | ||
1020 | addr = (short)rec->val[hi]; | ||
1021 | addr = addr << 15; | ||
1022 | if (lay && FX_ON(lay, lo)) | ||
1023 | addr += (short)lay->val[lo]; | ||
1024 | else if (FX_ON(rec, lo)) | ||
1025 | addr += (short)rec->val[lo]; | ||
1026 | if (!(mode & AWE_SAMPLE_8BITS)) | ||
1027 | addr /= 2; | ||
1028 | return addr; | ||
1029 | } | ||
1030 | |||
1031 | |||
1032 | /* | ||
1033 | * turn on/off sample | ||
1034 | */ | ||
1035 | |||
1036 | /* table for volume target calculation */ | ||
1037 | static unsigned short voltarget[16] = { | ||
1038 | 0xEAC0, 0XE0C8, 0XD740, 0XCE20, 0XC560, 0XBD08, 0XB500, 0XAD58, | ||
1039 | 0XA5F8, 0X9EF0, 0X9830, 0X91C0, 0X8B90, 0X85A8, 0X8000, 0X7A90 | ||
1040 | }; | ||
1041 | |||
1042 | static void | ||
1043 | awe_note_on(int voice) | ||
1044 | { | ||
1045 | unsigned int temp; | ||
1046 | int addr; | ||
1047 | int vtarget, ftarget, ptarget, pitch; | ||
1048 | awe_voice_info *vp; | ||
1049 | awe_voice_parm_block *parm; | ||
1050 | FX_Rec *fx = &voices[voice].cinfo->fx; | ||
1051 | FX_Rec *fx_lay = NULL; | ||
1052 | if (voices[voice].layer < MAX_LAYERS) | ||
1053 | fx_lay = &voices[voice].cinfo->fx_layer[voices[voice].layer]; | ||
1054 | |||
1055 | /* A voice sample must assigned before calling */ | ||
1056 | if ((vp = voices[voice].sample) == NULL || vp->index == 0) | ||
1057 | return; | ||
1058 | |||
1059 | parm = (awe_voice_parm_block*)&vp->parm; | ||
1060 | |||
1061 | /* channel to be silent and idle */ | ||
1062 | awe_poke(AWE_DCYSUSV(voice), 0x0080); | ||
1063 | awe_poke(AWE_VTFT(voice), 0x0000FFFF); | ||
1064 | awe_poke(AWE_CVCF(voice), 0x0000FFFF); | ||
1065 | awe_poke(AWE_PTRX(voice), 0); | ||
1066 | awe_poke(AWE_CPF(voice), 0); | ||
1067 | |||
1068 | /* set pitch offset */ | ||
1069 | awe_set_pitch(voice, TRUE); | ||
1070 | |||
1071 | /* modulation & volume envelope */ | ||
1072 | if (parm->modatk >= 0x80 && parm->moddelay >= 0x8000) { | ||
1073 | awe_poke(AWE_ENVVAL(voice), 0xBFFF); | ||
1074 | pitch = (parm->env1pit<<4) + voices[voice].apitch; | ||
1075 | if (pitch > 0xffff) pitch = 0xffff; | ||
1076 | /* calculate filter target */ | ||
1077 | ftarget = parm->cutoff + parm->env1fc; | ||
1078 | limitvalue(ftarget, 0, 255); | ||
1079 | ftarget <<= 8; | ||
1080 | } else { | ||
1081 | awe_poke(AWE_ENVVAL(voice), | ||
1082 | FX_WORD(fx, fx_lay, AWE_FX_ENV1_DELAY, parm->moddelay)); | ||
1083 | ftarget = parm->cutoff; | ||
1084 | ftarget <<= 8; | ||
1085 | pitch = voices[voice].apitch; | ||
1086 | } | ||
1087 | |||
1088 | /* calcualte pitch target */ | ||
1089 | if (pitch != 0xffff) { | ||
1090 | ptarget = 1 << (pitch >> 12); | ||
1091 | if (pitch & 0x800) ptarget += (ptarget*0x102e)/0x2710; | ||
1092 | if (pitch & 0x400) ptarget += (ptarget*0x764)/0x2710; | ||
1093 | if (pitch & 0x200) ptarget += (ptarget*0x389)/0x2710; | ||
1094 | ptarget += (ptarget>>1); | ||
1095 | if (ptarget > 0xffff) ptarget = 0xffff; | ||
1096 | |||
1097 | } else ptarget = 0xffff; | ||
1098 | if (parm->modatk >= 0x80) | ||
1099 | awe_poke(AWE_ATKHLD(voice), | ||
1100 | FX_BYTE(fx, fx_lay, AWE_FX_ENV1_HOLD, parm->modhld) << 8 | 0x7f); | ||
1101 | else | ||
1102 | awe_poke(AWE_ATKHLD(voice), | ||
1103 | FX_COMB(fx, fx_lay, AWE_FX_ENV1_HOLD, AWE_FX_ENV1_ATTACK, | ||
1104 | vp->parm.modatkhld)); | ||
1105 | awe_poke(AWE_DCYSUS(voice), | ||
1106 | FX_COMB(fx, fx_lay, AWE_FX_ENV1_SUSTAIN, AWE_FX_ENV1_DECAY, | ||
1107 | vp->parm.moddcysus)); | ||
1108 | |||
1109 | if (parm->volatk >= 0x80 && parm->voldelay >= 0x8000) { | ||
1110 | awe_poke(AWE_ENVVOL(voice), 0xBFFF); | ||
1111 | vtarget = voltarget[voices[voice].avol%0x10]>>(voices[voice].avol>>4); | ||
1112 | } else { | ||
1113 | awe_poke(AWE_ENVVOL(voice), | ||
1114 | FX_WORD(fx, fx_lay, AWE_FX_ENV2_DELAY, vp->parm.voldelay)); | ||
1115 | vtarget = 0; | ||
1116 | } | ||
1117 | if (parm->volatk >= 0x80) | ||
1118 | awe_poke(AWE_ATKHLDV(voice), | ||
1119 | FX_BYTE(fx, fx_lay, AWE_FX_ENV2_HOLD, parm->volhld) << 8 | 0x7f); | ||
1120 | else | ||
1121 | awe_poke(AWE_ATKHLDV(voice), | ||
1122 | FX_COMB(fx, fx_lay, AWE_FX_ENV2_HOLD, AWE_FX_ENV2_ATTACK, | ||
1123 | vp->parm.volatkhld)); | ||
1124 | /* decay/sustain parameter for volume envelope must be set at last */ | ||
1125 | |||
1126 | /* cutoff and volume */ | ||
1127 | awe_set_volume(voice, TRUE); | ||
1128 | |||
1129 | /* modulation envelope heights */ | ||
1130 | awe_poke(AWE_PEFE(voice), | ||
1131 | FX_COMB(fx, fx_lay, AWE_FX_ENV1_PITCH, AWE_FX_ENV1_CUTOFF, | ||
1132 | vp->parm.pefe)); | ||
1133 | |||
1134 | /* lfo1/2 delay */ | ||
1135 | awe_poke(AWE_LFO1VAL(voice), | ||
1136 | FX_WORD(fx, fx_lay, AWE_FX_LFO1_DELAY, vp->parm.lfo1delay)); | ||
1137 | awe_poke(AWE_LFO2VAL(voice), | ||
1138 | FX_WORD(fx, fx_lay, AWE_FX_LFO2_DELAY, vp->parm.lfo2delay)); | ||
1139 | |||
1140 | /* lfo1 pitch & cutoff shift */ | ||
1141 | awe_fx_fmmod(voice, TRUE); | ||
1142 | /* lfo1 volume & freq */ | ||
1143 | awe_fx_tremfrq(voice, TRUE); | ||
1144 | /* lfo2 pitch & freq */ | ||
1145 | awe_fx_fm2frq2(voice, TRUE); | ||
1146 | /* pan & loop start */ | ||
1147 | awe_set_pan(voice, TRUE); | ||
1148 | |||
1149 | /* chorus & loop end (chorus 8bit, MSB) */ | ||
1150 | addr = vp->loopend - 1; | ||
1151 | addr += FX_OFFSET(fx, fx_lay, AWE_FX_LOOP_END, | ||
1152 | AWE_FX_COARSE_LOOP_END, vp->mode); | ||
1153 | temp = FX_BYTE(fx, fx_lay, AWE_FX_CHORUS, vp->parm.chorus); | ||
1154 | temp = (temp <<24) | (unsigned int)addr; | ||
1155 | awe_poke_dw(AWE_CSL(voice), temp); | ||
1156 | DEBUG(4,printk("AWE32: [-- loopend=%x/%x]\n", vp->loopend, addr)); | ||
1157 | |||
1158 | /* Q & current address (Q 4bit value, MSB) */ | ||
1159 | addr = vp->start - 1; | ||
1160 | addr += FX_OFFSET(fx, fx_lay, AWE_FX_SAMPLE_START, | ||
1161 | AWE_FX_COARSE_SAMPLE_START, vp->mode); | ||
1162 | temp = FX_BYTE(fx, fx_lay, AWE_FX_FILTERQ, vp->parm.filterQ); | ||
1163 | temp = (temp<<28) | (unsigned int)addr; | ||
1164 | awe_poke_dw(AWE_CCCA(voice), temp); | ||
1165 | DEBUG(4,printk("AWE32: [-- startaddr=%x/%x]\n", vp->start, addr)); | ||
1166 | |||
1167 | /* clear unknown registers */ | ||
1168 | awe_poke_dw(AWE_00A0(voice), 0); | ||
1169 | awe_poke_dw(AWE_0080(voice), 0); | ||
1170 | |||
1171 | /* reset volume */ | ||
1172 | awe_poke_dw(AWE_VTFT(voice), (vtarget<<16)|ftarget); | ||
1173 | awe_poke_dw(AWE_CVCF(voice), (vtarget<<16)|ftarget); | ||
1174 | |||
1175 | /* set reverb */ | ||
1176 | temp = FX_BYTE(fx, fx_lay, AWE_FX_REVERB, vp->parm.reverb); | ||
1177 | temp = (temp << 8) | (ptarget << 16) | voices[voice].aaux; | ||
1178 | awe_poke_dw(AWE_PTRX(voice), temp); | ||
1179 | awe_poke_dw(AWE_CPF(voice), ptarget << 16); | ||
1180 | /* turn on envelope */ | ||
1181 | awe_poke(AWE_DCYSUSV(voice), | ||
1182 | FX_COMB(fx, fx_lay, AWE_FX_ENV2_SUSTAIN, AWE_FX_ENV2_DECAY, | ||
1183 | vp->parm.voldcysus)); | ||
1184 | |||
1185 | voices[voice].state = AWE_ST_ON; | ||
1186 | |||
1187 | /* clear voice position for the next note on this channel */ | ||
1188 | if (SINGLE_LAYER_MODE()) { | ||
1189 | FX_UNSET(fx, AWE_FX_SAMPLE_START); | ||
1190 | FX_UNSET(fx, AWE_FX_COARSE_SAMPLE_START); | ||
1191 | } | ||
1192 | } | ||
1193 | |||
1194 | |||
1195 | /* turn off the voice */ | ||
1196 | static void | ||
1197 | awe_note_off(int voice) | ||
1198 | { | ||
1199 | awe_voice_info *vp; | ||
1200 | unsigned short tmp; | ||
1201 | FX_Rec *fx = &voices[voice].cinfo->fx; | ||
1202 | FX_Rec *fx_lay = NULL; | ||
1203 | if (voices[voice].layer < MAX_LAYERS) | ||
1204 | fx_lay = &voices[voice].cinfo->fx_layer[voices[voice].layer]; | ||
1205 | |||
1206 | if ((vp = voices[voice].sample) == NULL) { | ||
1207 | voices[voice].state = AWE_ST_OFF; | ||
1208 | return; | ||
1209 | } | ||
1210 | |||
1211 | tmp = 0x8000 | FX_BYTE(fx, fx_lay, AWE_FX_ENV1_RELEASE, | ||
1212 | (unsigned char)vp->parm.modrelease); | ||
1213 | awe_poke(AWE_DCYSUS(voice), tmp); | ||
1214 | tmp = 0x8000 | FX_BYTE(fx, fx_lay, AWE_FX_ENV2_RELEASE, | ||
1215 | (unsigned char)vp->parm.volrelease); | ||
1216 | awe_poke(AWE_DCYSUSV(voice), tmp); | ||
1217 | voices[voice].state = AWE_ST_RELEASED; | ||
1218 | } | ||
1219 | |||
1220 | /* force to terminate the voice (no releasing echo) */ | ||
1221 | static void | ||
1222 | awe_terminate(int voice) | ||
1223 | { | ||
1224 | awe_poke(AWE_DCYSUSV(voice), 0x807F); | ||
1225 | awe_tweak_voice(voice); | ||
1226 | voices[voice].state = AWE_ST_OFF; | ||
1227 | } | ||
1228 | |||
1229 | /* turn off other voices with the same exclusive class (for drums) */ | ||
1230 | static void | ||
1231 | awe_exclusive_off(int voice) | ||
1232 | { | ||
1233 | int i, exclass; | ||
1234 | |||
1235 | if (voices[voice].sample == NULL) | ||
1236 | return; | ||
1237 | if ((exclass = voices[voice].sample->exclusiveClass) == 0) | ||
1238 | return; /* not exclusive */ | ||
1239 | |||
1240 | /* turn off voices with the same class */ | ||
1241 | for (i = 0; i < awe_max_voices; i++) { | ||
1242 | if (i != voice && IS_PLAYING(i) && | ||
1243 | voices[i].sample && voices[i].ch == voices[voice].ch && | ||
1244 | voices[i].sample->exclusiveClass == exclass) { | ||
1245 | DEBUG(4,printk("AWE32: [exoff(%d)]\n", i)); | ||
1246 | awe_terminate(i); | ||
1247 | awe_voice_init(i, TRUE); | ||
1248 | } | ||
1249 | } | ||
1250 | } | ||
1251 | |||
1252 | |||
1253 | /* | ||
1254 | * change the parameters of an audible voice | ||
1255 | */ | ||
1256 | |||
1257 | /* change pitch */ | ||
1258 | static void | ||
1259 | awe_set_pitch(int voice, int forced) | ||
1260 | { | ||
1261 | if (IS_NO_EFFECT(voice) && !forced) return; | ||
1262 | awe_poke(AWE_IP(voice), voices[voice].apitch); | ||
1263 | DEBUG(3,printk("AWE32: [-- pitch=%x]\n", voices[voice].apitch)); | ||
1264 | } | ||
1265 | |||
1266 | /* calculate & change pitch */ | ||
1267 | static void | ||
1268 | awe_set_voice_pitch(int voice, int forced) | ||
1269 | { | ||
1270 | awe_calc_pitch(voice); | ||
1271 | awe_set_pitch(voice, forced); | ||
1272 | } | ||
1273 | |||
1274 | /* change volume & cutoff */ | ||
1275 | static void | ||
1276 | awe_set_volume(int voice, int forced) | ||
1277 | { | ||
1278 | awe_voice_info *vp; | ||
1279 | unsigned short tmp2; | ||
1280 | FX_Rec *fx = &voices[voice].cinfo->fx; | ||
1281 | FX_Rec *fx_lay = NULL; | ||
1282 | if (voices[voice].layer < MAX_LAYERS) | ||
1283 | fx_lay = &voices[voice].cinfo->fx_layer[voices[voice].layer]; | ||
1284 | |||
1285 | if (!IS_PLAYING(voice) && !forced) return; | ||
1286 | if ((vp = voices[voice].sample) == NULL || vp->index == 0) | ||
1287 | return; | ||
1288 | |||
1289 | tmp2 = FX_BYTE(fx, fx_lay, AWE_FX_CUTOFF, | ||
1290 | (unsigned char)voices[voice].acutoff); | ||
1291 | tmp2 = (tmp2 << 8); | ||
1292 | tmp2 |= FX_BYTE(fx, fx_lay, AWE_FX_ATTEN, | ||
1293 | (unsigned char)voices[voice].avol); | ||
1294 | awe_poke(AWE_IFATN(voice), tmp2); | ||
1295 | } | ||
1296 | |||
1297 | /* calculate & change volume */ | ||
1298 | static void | ||
1299 | awe_set_voice_vol(int voice, int forced) | ||
1300 | { | ||
1301 | if (IS_EMPTY(voice)) | ||
1302 | return; | ||
1303 | awe_calc_volume(voice); | ||
1304 | awe_set_volume(voice, forced); | ||
1305 | } | ||
1306 | |||
1307 | |||
1308 | /* change pan; this could make a click noise.. */ | ||
1309 | static void | ||
1310 | awe_set_pan(int voice, int forced) | ||
1311 | { | ||
1312 | unsigned int temp; | ||
1313 | int addr; | ||
1314 | awe_voice_info *vp; | ||
1315 | FX_Rec *fx = &voices[voice].cinfo->fx; | ||
1316 | FX_Rec *fx_lay = NULL; | ||
1317 | if (voices[voice].layer < MAX_LAYERS) | ||
1318 | fx_lay = &voices[voice].cinfo->fx_layer[voices[voice].layer]; | ||
1319 | |||
1320 | if (IS_NO_EFFECT(voice) && !forced) return; | ||
1321 | if ((vp = voices[voice].sample) == NULL || vp->index == 0) | ||
1322 | return; | ||
1323 | |||
1324 | /* pan & loop start (pan 8bit, MSB, 0:right, 0xff:left) */ | ||
1325 | if (vp->fixpan > 0) /* 0-127 */ | ||
1326 | temp = 255 - (int)vp->fixpan * 2; | ||
1327 | else { | ||
1328 | int pos = 0; | ||
1329 | if (vp->pan >= 0) /* 0-127 */ | ||
1330 | pos = (int)vp->pan * 2 - 128; | ||
1331 | pos += voices[voice].cinfo->panning; /* -128 - 127 */ | ||
1332 | temp = 127 - pos; | ||
1333 | } | ||
1334 | limitvalue(temp, 0, 255); | ||
1335 | if (ctrls[AWE_MD_PAN_EXCHANGE]) { | ||
1336 | temp = 255 - temp; | ||
1337 | } | ||
1338 | if (forced || temp != voices[voice].apan) { | ||
1339 | voices[voice].apan = temp; | ||
1340 | if (temp == 0) | ||
1341 | voices[voice].aaux = 0xff; | ||
1342 | else | ||
1343 | voices[voice].aaux = (-temp) & 0xff; | ||
1344 | addr = vp->loopstart - 1; | ||
1345 | addr += FX_OFFSET(fx, fx_lay, AWE_FX_LOOP_START, | ||
1346 | AWE_FX_COARSE_LOOP_START, vp->mode); | ||
1347 | temp = (temp<<24) | (unsigned int)addr; | ||
1348 | awe_poke_dw(AWE_PSST(voice), temp); | ||
1349 | DEBUG(4,printk("AWE32: [-- loopstart=%x/%x]\n", vp->loopstart, addr)); | ||
1350 | } | ||
1351 | } | ||
1352 | |||
1353 | /* effects change during playing */ | ||
1354 | static void | ||
1355 | awe_fx_fmmod(int voice, int forced) | ||
1356 | { | ||
1357 | awe_voice_info *vp; | ||
1358 | FX_Rec *fx = &voices[voice].cinfo->fx; | ||
1359 | FX_Rec *fx_lay = NULL; | ||
1360 | if (voices[voice].layer < MAX_LAYERS) | ||
1361 | fx_lay = &voices[voice].cinfo->fx_layer[voices[voice].layer]; | ||
1362 | |||
1363 | if (IS_NO_EFFECT(voice) && !forced) return; | ||
1364 | if ((vp = voices[voice].sample) == NULL || vp->index == 0) | ||
1365 | return; | ||
1366 | awe_poke(AWE_FMMOD(voice), | ||
1367 | FX_COMB(fx, fx_lay, AWE_FX_LFO1_PITCH, AWE_FX_LFO1_CUTOFF, | ||
1368 | vp->parm.fmmod)); | ||
1369 | } | ||
1370 | |||
1371 | /* set tremolo (lfo1) volume & frequency */ | ||
1372 | static void | ||
1373 | awe_fx_tremfrq(int voice, int forced) | ||
1374 | { | ||
1375 | awe_voice_info *vp; | ||
1376 | FX_Rec *fx = &voices[voice].cinfo->fx; | ||
1377 | FX_Rec *fx_lay = NULL; | ||
1378 | if (voices[voice].layer < MAX_LAYERS) | ||
1379 | fx_lay = &voices[voice].cinfo->fx_layer[voices[voice].layer]; | ||
1380 | |||
1381 | if (IS_NO_EFFECT(voice) && !forced) return; | ||
1382 | if ((vp = voices[voice].sample) == NULL || vp->index == 0) | ||
1383 | return; | ||
1384 | awe_poke(AWE_TREMFRQ(voice), | ||
1385 | FX_COMB(fx, fx_lay, AWE_FX_LFO1_VOLUME, AWE_FX_LFO1_FREQ, | ||
1386 | vp->parm.tremfrq)); | ||
1387 | } | ||
1388 | |||
1389 | /* set lfo2 pitch & frequency */ | ||
1390 | static void | ||
1391 | awe_fx_fm2frq2(int voice, int forced) | ||
1392 | { | ||
1393 | awe_voice_info *vp; | ||
1394 | FX_Rec *fx = &voices[voice].cinfo->fx; | ||
1395 | FX_Rec *fx_lay = NULL; | ||
1396 | if (voices[voice].layer < MAX_LAYERS) | ||
1397 | fx_lay = &voices[voice].cinfo->fx_layer[voices[voice].layer]; | ||
1398 | |||
1399 | if (IS_NO_EFFECT(voice) && !forced) return; | ||
1400 | if ((vp = voices[voice].sample) == NULL || vp->index == 0) | ||
1401 | return; | ||
1402 | awe_poke(AWE_FM2FRQ2(voice), | ||
1403 | FX_COMB(fx, fx_lay, AWE_FX_LFO2_PITCH, AWE_FX_LFO2_FREQ, | ||
1404 | vp->parm.fm2frq2)); | ||
1405 | } | ||
1406 | |||
1407 | |||
1408 | /* Q & current address (Q 4bit value, MSB) */ | ||
1409 | static void | ||
1410 | awe_fx_filterQ(int voice, int forced) | ||
1411 | { | ||
1412 | unsigned int addr; | ||
1413 | awe_voice_info *vp; | ||
1414 | FX_Rec *fx = &voices[voice].cinfo->fx; | ||
1415 | FX_Rec *fx_lay = NULL; | ||
1416 | if (voices[voice].layer < MAX_LAYERS) | ||
1417 | fx_lay = &voices[voice].cinfo->fx_layer[voices[voice].layer]; | ||
1418 | |||
1419 | if (IS_NO_EFFECT(voice) && !forced) return; | ||
1420 | if ((vp = voices[voice].sample) == NULL || vp->index == 0) | ||
1421 | return; | ||
1422 | |||
1423 | addr = awe_peek_dw(AWE_CCCA(voice)) & 0xffffff; | ||
1424 | addr |= (FX_BYTE(fx, fx_lay, AWE_FX_FILTERQ, vp->parm.filterQ) << 28); | ||
1425 | awe_poke_dw(AWE_CCCA(voice), addr); | ||
1426 | } | ||
1427 | |||
1428 | /* | ||
1429 | * calculate pitch offset | ||
1430 | * | ||
1431 | * 0xE000 is no pitch offset at 44100Hz sample. | ||
1432 | * Every 4096 is one octave. | ||
1433 | */ | ||
1434 | |||
1435 | static void | ||
1436 | awe_calc_pitch(int voice) | ||
1437 | { | ||
1438 | voice_info *vp = &voices[voice]; | ||
1439 | awe_voice_info *ap; | ||
1440 | awe_chan_info *cp = voices[voice].cinfo; | ||
1441 | int offset; | ||
1442 | |||
1443 | /* search voice information */ | ||
1444 | if ((ap = vp->sample) == NULL) | ||
1445 | return; | ||
1446 | if (ap->index == 0) { | ||
1447 | DEBUG(3,printk("AWE32: set sample (%d)\n", ap->sample)); | ||
1448 | if (awe_set_sample((awe_voice_list*)ap) == 0) | ||
1449 | return; | ||
1450 | } | ||
1451 | |||
1452 | /* calculate offset */ | ||
1453 | if (ap->fixkey >= 0) { | ||
1454 | DEBUG(3,printk("AWE32: p-> fixkey(%d) tune(%d)\n", ap->fixkey, ap->tune)); | ||
1455 | offset = (ap->fixkey - ap->root) * 4096 / 12; | ||
1456 | } else { | ||
1457 | DEBUG(3,printk("AWE32: p(%d)-> root(%d) tune(%d)\n", vp->note, ap->root, ap->tune)); | ||
1458 | offset = (vp->note - ap->root) * 4096 / 12; | ||
1459 | DEBUG(4,printk("AWE32: p-> ofs=%d\n", offset)); | ||
1460 | } | ||
1461 | offset = (offset * ap->scaleTuning) / 100; | ||
1462 | DEBUG(4,printk("AWE32: p-> scale* ofs=%d\n", offset)); | ||
1463 | offset += ap->tune * 4096 / 1200; | ||
1464 | DEBUG(4,printk("AWE32: p-> tune+ ofs=%d\n", offset)); | ||
1465 | if (cp->bender != 0) { | ||
1466 | DEBUG(3,printk("AWE32: p-> bend(%d) %d\n", voice, cp->bender)); | ||
1467 | /* (819200: 1 semitone) ==> (4096: 12 semitones) */ | ||
1468 | offset += cp->bender * cp->bender_range / 2400; | ||
1469 | } | ||
1470 | |||
1471 | /* add initial pitch correction */ | ||
1472 | if (FX_ON(&cp->fx_layer[vp->layer], AWE_FX_INIT_PITCH)) | ||
1473 | offset += cp->fx_layer[vp->layer].val[AWE_FX_INIT_PITCH]; | ||
1474 | else if (FX_ON(&cp->fx, AWE_FX_INIT_PITCH)) | ||
1475 | offset += cp->fx.val[AWE_FX_INIT_PITCH]; | ||
1476 | |||
1477 | /* 0xe000: root pitch */ | ||
1478 | vp->apitch = 0xe000 + ap->rate_offset + offset; | ||
1479 | DEBUG(4,printk("AWE32: p-> sum aofs=%x, rate_ofs=%d\n", vp->apitch, ap->rate_offset)); | ||
1480 | if (vp->apitch > 0xffff) | ||
1481 | vp->apitch = 0xffff; | ||
1482 | if (vp->apitch < 0) | ||
1483 | vp->apitch = 0; | ||
1484 | } | ||
1485 | |||
1486 | |||
1487 | #ifdef AWE_HAS_GUS_COMPATIBILITY | ||
1488 | /* calculate MIDI key and semitone from the specified frequency */ | ||
1489 | static void | ||
1490 | awe_calc_pitch_from_freq(int voice, int freq) | ||
1491 | { | ||
1492 | voice_info *vp = &voices[voice]; | ||
1493 | awe_voice_info *ap; | ||
1494 | FX_Rec *fx = &voices[voice].cinfo->fx; | ||
1495 | FX_Rec *fx_lay = NULL; | ||
1496 | int offset; | ||
1497 | int note; | ||
1498 | |||
1499 | if (voices[voice].layer < MAX_LAYERS) | ||
1500 | fx_lay = &voices[voice].cinfo->fx_layer[voices[voice].layer]; | ||
1501 | |||
1502 | /* search voice information */ | ||
1503 | if ((ap = vp->sample) == NULL) | ||
1504 | return; | ||
1505 | if (ap->index == 0) { | ||
1506 | DEBUG(3,printk("AWE32: set sample (%d)\n", ap->sample)); | ||
1507 | if (awe_set_sample((awe_voice_list*)ap) == 0) | ||
1508 | return; | ||
1509 | } | ||
1510 | note = freq_to_note(freq); | ||
1511 | offset = (note - ap->root * 100 + ap->tune) * 4096 / 1200; | ||
1512 | offset = (offset * ap->scaleTuning) / 100; | ||
1513 | if (fx_lay && FX_ON(fx_lay, AWE_FX_INIT_PITCH)) | ||
1514 | offset += fx_lay->val[AWE_FX_INIT_PITCH]; | ||
1515 | else if (FX_ON(fx, AWE_FX_INIT_PITCH)) | ||
1516 | offset += fx->val[AWE_FX_INIT_PITCH]; | ||
1517 | vp->apitch = 0xe000 + ap->rate_offset + offset; | ||
1518 | if (vp->apitch > 0xffff) | ||
1519 | vp->apitch = 0xffff; | ||
1520 | if (vp->apitch < 0) | ||
1521 | vp->apitch = 0; | ||
1522 | } | ||
1523 | #endif /* AWE_HAS_GUS_COMPATIBILITY */ | ||
1524 | |||
1525 | |||
1526 | /* | ||
1527 | * calculate volume attenuation | ||
1528 | * | ||
1529 | * Voice volume is controlled by volume attenuation parameter. | ||
1530 | * So volume becomes maximum when avol is 0 (no attenuation), and | ||
1531 | * minimum when 255 (-96dB or silence). | ||
1532 | */ | ||
1533 | |||
1534 | static int vol_table[128] = { | ||
1535 | 255,111,95,86,79,74,70,66,63,61,58,56,54,52,50,49, | ||
1536 | 47,46,45,43,42,41,40,39,38,37,36,35,34,34,33,32, | ||
1537 | 31,31,30,29,29,28,27,27,26,26,25,24,24,23,23,22, | ||
1538 | 22,21,21,21,20,20,19,19,18,18,18,17,17,16,16,16, | ||
1539 | 15,15,15,14,14,14,13,13,13,12,12,12,11,11,11,10, | ||
1540 | 10,10,10,9,9,9,8,8,8,8,7,7,7,7,6,6, | ||
1541 | 6,6,5,5,5,5,5,4,4,4,4,3,3,3,3,3, | ||
1542 | 2,2,2,2,2,1,1,1,1,1,0,0,0,0,0,0, | ||
1543 | }; | ||
1544 | |||
1545 | /* tables for volume->attenuation calculation */ | ||
1546 | static unsigned char voltab1[128] = { | ||
1547 | 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, | ||
1548 | 0x63, 0x2b, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, | ||
1549 | 0x21, 0x20, 0x1f, 0x1e, 0x1e, 0x1d, 0x1c, 0x1b, 0x1b, 0x1a, | ||
1550 | 0x19, 0x19, 0x18, 0x17, 0x17, 0x16, 0x16, 0x15, 0x15, 0x14, | ||
1551 | 0x14, 0x13, 0x13, 0x13, 0x12, 0x12, 0x11, 0x11, 0x11, 0x10, | ||
1552 | 0x10, 0x10, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0e, 0x0d, | ||
1553 | 0x0d, 0x0d, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, 0x0b, | ||
1554 | 0x0b, 0x0a, 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, | ||
1555 | 0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x06, | ||
1556 | 0x06, 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x04, | ||
1557 | 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02, | ||
1558 | 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, | ||
1559 | 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | ||
1560 | }; | ||
1561 | |||
1562 | static unsigned char voltab2[128] = { | ||
1563 | 0x32, 0x31, 0x30, 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x2a, | ||
1564 | 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x24, 0x23, 0x22, 0x21, | ||
1565 | 0x21, 0x20, 0x1f, 0x1e, 0x1e, 0x1d, 0x1c, 0x1c, 0x1b, 0x1a, | ||
1566 | 0x1a, 0x19, 0x19, 0x18, 0x18, 0x17, 0x16, 0x16, 0x15, 0x15, | ||
1567 | 0x14, 0x14, 0x13, 0x13, 0x13, 0x12, 0x12, 0x11, 0x11, 0x10, | ||
1568 | 0x10, 0x10, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0d, 0x0d, | ||
1569 | 0x0d, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, 0x0b, 0x0b, 0x0a, 0x0a, | ||
1570 | 0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08, | ||
1571 | 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x07, 0x06, 0x06, 0x06, | ||
1572 | 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, | ||
1573 | 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, | ||
1574 | 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, | ||
1575 | 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 | ||
1576 | }; | ||
1577 | |||
1578 | static unsigned char expressiontab[128] = { | ||
1579 | 0x7f, 0x6c, 0x62, 0x5a, 0x54, 0x50, 0x4b, 0x48, 0x45, 0x42, | ||
1580 | 0x40, 0x3d, 0x3b, 0x39, 0x38, 0x36, 0x34, 0x33, 0x31, 0x30, | ||
1581 | 0x2f, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26, 0x25, | ||
1582 | 0x24, 0x24, 0x23, 0x22, 0x21, 0x21, 0x20, 0x1f, 0x1e, 0x1e, | ||
1583 | 0x1d, 0x1d, 0x1c, 0x1b, 0x1b, 0x1a, 0x1a, 0x19, 0x18, 0x18, | ||
1584 | 0x17, 0x17, 0x16, 0x16, 0x15, 0x15, 0x15, 0x14, 0x14, 0x13, | ||
1585 | 0x13, 0x12, 0x12, 0x11, 0x11, 0x11, 0x10, 0x10, 0x0f, 0x0f, | ||
1586 | 0x0f, 0x0e, 0x0e, 0x0e, 0x0d, 0x0d, 0x0d, 0x0c, 0x0c, 0x0c, | ||
1587 | 0x0b, 0x0b, 0x0b, 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09, | ||
1588 | 0x08, 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x06, 0x06, 0x06, | ||
1589 | 0x06, 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, | ||
1590 | 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, | ||
1591 | 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | ||
1592 | }; | ||
1593 | |||
1594 | static void | ||
1595 | awe_calc_volume(int voice) | ||
1596 | { | ||
1597 | voice_info *vp = &voices[voice]; | ||
1598 | awe_voice_info *ap; | ||
1599 | awe_chan_info *cp = voices[voice].cinfo; | ||
1600 | int vol; | ||
1601 | |||
1602 | /* search voice information */ | ||
1603 | if ((ap = vp->sample) == NULL) | ||
1604 | return; | ||
1605 | |||
1606 | ap = vp->sample; | ||
1607 | if (ap->index == 0) { | ||
1608 | DEBUG(3,printk("AWE32: set sample (%d)\n", ap->sample)); | ||
1609 | if (awe_set_sample((awe_voice_list*)ap) == 0) | ||
1610 | return; | ||
1611 | } | ||
1612 | |||
1613 | if (ctrls[AWE_MD_NEW_VOLUME_CALC]) { | ||
1614 | int main_vol = cp->main_vol * ap->amplitude / 127; | ||
1615 | limitvalue(vp->velocity, 0, 127); | ||
1616 | limitvalue(main_vol, 0, 127); | ||
1617 | limitvalue(cp->expression_vol, 0, 127); | ||
1618 | |||
1619 | vol = voltab1[main_vol] + voltab2[vp->velocity]; | ||
1620 | vol = (vol * 8) / 3; | ||
1621 | vol += ap->attenuation; | ||
1622 | if (cp->expression_vol < 127) | ||
1623 | vol += ((0x100 - vol) * expressiontab[cp->expression_vol])/128; | ||
1624 | vol += atten_offset; | ||
1625 | if (atten_relative) | ||
1626 | vol += ctrls[AWE_MD_ZERO_ATTEN]; | ||
1627 | limitvalue(vol, 0, 255); | ||
1628 | vp->avol = vol; | ||
1629 | |||
1630 | } else { | ||
1631 | /* 0 - 127 */ | ||
1632 | vol = (vp->velocity * cp->main_vol * cp->expression_vol) / (127*127); | ||
1633 | vol = vol * ap->amplitude / 127; | ||
1634 | |||
1635 | if (vol < 0) vol = 0; | ||
1636 | if (vol > 127) vol = 127; | ||
1637 | |||
1638 | /* calc to attenuation */ | ||
1639 | vol = vol_table[vol]; | ||
1640 | vol += (int)ap->attenuation; | ||
1641 | vol += atten_offset; | ||
1642 | if (atten_relative) | ||
1643 | vol += ctrls[AWE_MD_ZERO_ATTEN]; | ||
1644 | if (vol > 255) vol = 255; | ||
1645 | |||
1646 | vp->avol = vol; | ||
1647 | } | ||
1648 | if (cp->bank != AWE_DRUM_BANK && ((awe_voice_parm_block*)(&ap->parm))->volatk < 0x7d) { | ||
1649 | int atten; | ||
1650 | if (vp->velocity < 70) atten = 70; | ||
1651 | else atten = vp->velocity; | ||
1652 | vp->acutoff = (atten * ap->parm.cutoff + 0xa0) >> 7; | ||
1653 | } else { | ||
1654 | vp->acutoff = ap->parm.cutoff; | ||
1655 | } | ||
1656 | DEBUG(3,printk("AWE32: [-- voice(%d) vol=%x]\n", voice, vol)); | ||
1657 | } | ||
1658 | |||
1659 | /* change master volume */ | ||
1660 | static void | ||
1661 | awe_change_master_volume(short val) | ||
1662 | { | ||
1663 | limitvalue(val, 0, 127); | ||
1664 | atten_offset = vol_table[val]; | ||
1665 | atten_relative = TRUE; | ||
1666 | awe_update_volume(); | ||
1667 | } | ||
1668 | |||
1669 | /* update volumes of all available channels */ | ||
1670 | static void awe_update_volume(void) | ||
1671 | { | ||
1672 | int i; | ||
1673 | for (i = 0; i < awe_max_voices; i++) | ||
1674 | awe_set_voice_vol(i, TRUE); | ||
1675 | } | ||
1676 | |||
1677 | /* set sostenuto on */ | ||
1678 | static void awe_sostenuto_on(int voice, int forced) | ||
1679 | { | ||
1680 | if (IS_NO_EFFECT(voice) && !forced) return; | ||
1681 | voices[voice].sostenuto = 127; | ||
1682 | } | ||
1683 | |||
1684 | |||
1685 | /* drop sustain */ | ||
1686 | static void awe_sustain_off(int voice, int forced) | ||
1687 | { | ||
1688 | if (voices[voice].state == AWE_ST_SUSTAINED) { | ||
1689 | awe_note_off(voice); | ||
1690 | awe_fx_init(voices[voice].ch); | ||
1691 | awe_voice_init(voice, FALSE); | ||
1692 | } | ||
1693 | } | ||
1694 | |||
1695 | |||
1696 | /* terminate and initialize voice */ | ||
1697 | static void awe_terminate_and_init(int voice, int forced) | ||
1698 | { | ||
1699 | awe_terminate(voice); | ||
1700 | awe_fx_init(voices[voice].ch); | ||
1701 | awe_voice_init(voice, TRUE); | ||
1702 | } | ||
1703 | |||
1704 | |||
1705 | /* | ||
1706 | * synth operation routines | ||
1707 | */ | ||
1708 | |||
1709 | #define AWE_VOICE_KEY(v) (0x8000 | (v)) | ||
1710 | #define AWE_CHAN_KEY(c,n) (((c) << 8) | ((n) + 1)) | ||
1711 | #define KEY_CHAN_MATCH(key,c) (((key) >> 8) == (c)) | ||
1712 | |||
1713 | /* initialize the voice */ | ||
1714 | static void | ||
1715 | awe_voice_init(int voice, int init_all) | ||
1716 | { | ||
1717 | voice_info *vp = &voices[voice]; | ||
1718 | |||
1719 | /* reset voice search key */ | ||
1720 | if (playing_mode == AWE_PLAY_DIRECT) | ||
1721 | vp->key = AWE_VOICE_KEY(voice); | ||
1722 | else | ||
1723 | vp->key = 0; | ||
1724 | |||
1725 | /* clear voice mapping */ | ||
1726 | voice_alloc->map[voice] = 0; | ||
1727 | |||
1728 | /* touch the timing flag */ | ||
1729 | vp->time = current_alloc_time; | ||
1730 | |||
1731 | /* initialize other parameters if necessary */ | ||
1732 | if (init_all) { | ||
1733 | vp->note = -1; | ||
1734 | vp->velocity = 0; | ||
1735 | vp->sostenuto = 0; | ||
1736 | |||
1737 | vp->sample = NULL; | ||
1738 | vp->cinfo = &channels[voice]; | ||
1739 | vp->ch = voice; | ||
1740 | vp->state = AWE_ST_OFF; | ||
1741 | |||
1742 | /* emu8000 parameters */ | ||
1743 | vp->apitch = 0; | ||
1744 | vp->avol = 255; | ||
1745 | vp->apan = -1; | ||
1746 | } | ||
1747 | } | ||
1748 | |||
1749 | /* clear effects */ | ||
1750 | static void awe_fx_init(int ch) | ||
1751 | { | ||
1752 | if (SINGLE_LAYER_MODE() && !ctrls[AWE_MD_KEEP_EFFECT]) { | ||
1753 | memset(&channels[ch].fx, 0, sizeof(channels[ch].fx)); | ||
1754 | memset(&channels[ch].fx_layer, 0, sizeof(&channels[ch].fx_layer)); | ||
1755 | } | ||
1756 | } | ||
1757 | |||
1758 | /* initialize channel info */ | ||
1759 | static void awe_channel_init(int ch, int init_all) | ||
1760 | { | ||
1761 | awe_chan_info *cp = &channels[ch]; | ||
1762 | cp->channel = ch; | ||
1763 | if (init_all) { | ||
1764 | cp->panning = 0; /* zero center */ | ||
1765 | cp->bender_range = 200; /* sense * 100 */ | ||
1766 | cp->main_vol = 127; | ||
1767 | if (MULTI_LAYER_MODE() && IS_DRUM_CHANNEL(ch)) { | ||
1768 | cp->instr = ctrls[AWE_MD_DEF_DRUM]; | ||
1769 | cp->bank = AWE_DRUM_BANK; | ||
1770 | } else { | ||
1771 | cp->instr = ctrls[AWE_MD_DEF_PRESET]; | ||
1772 | cp->bank = ctrls[AWE_MD_DEF_BANK]; | ||
1773 | } | ||
1774 | } | ||
1775 | |||
1776 | cp->bender = 0; /* zero tune skew */ | ||
1777 | cp->expression_vol = 127; | ||
1778 | cp->chan_press = 0; | ||
1779 | cp->sustained = 0; | ||
1780 | |||
1781 | if (! ctrls[AWE_MD_KEEP_EFFECT]) { | ||
1782 | memset(&cp->fx, 0, sizeof(cp->fx)); | ||
1783 | memset(&cp->fx_layer, 0, sizeof(cp->fx_layer)); | ||
1784 | } | ||
1785 | } | ||
1786 | |||
1787 | |||
1788 | /* change the voice parameters; voice = channel */ | ||
1789 | static void awe_voice_change(int voice, fx_affect_func func) | ||
1790 | { | ||
1791 | int i; | ||
1792 | switch (playing_mode) { | ||
1793 | case AWE_PLAY_DIRECT: | ||
1794 | func(voice, FALSE); | ||
1795 | break; | ||
1796 | case AWE_PLAY_INDIRECT: | ||
1797 | for (i = 0; i < awe_max_voices; i++) | ||
1798 | if (voices[i].key == AWE_VOICE_KEY(voice)) | ||
1799 | func(i, FALSE); | ||
1800 | break; | ||
1801 | default: | ||
1802 | for (i = 0; i < awe_max_voices; i++) | ||
1803 | if (KEY_CHAN_MATCH(voices[i].key, voice)) | ||
1804 | func(i, FALSE); | ||
1805 | break; | ||
1806 | } | ||
1807 | } | ||
1808 | |||
1809 | |||
1810 | /* | ||
1811 | * device open / close | ||
1812 | */ | ||
1813 | |||
1814 | /* open device: | ||
1815 | * reset status of all voices, and clear sample position flag | ||
1816 | */ | ||
1817 | static int | ||
1818 | awe_open(int dev, int mode) | ||
1819 | { | ||
1820 | if (awe_busy) | ||
1821 | return -EBUSY; | ||
1822 | |||
1823 | awe_busy = TRUE; | ||
1824 | |||
1825 | /* set default mode */ | ||
1826 | awe_init_ctrl_parms(FALSE); | ||
1827 | atten_relative = TRUE; | ||
1828 | atten_offset = 0; | ||
1829 | drum_flags = DEFAULT_DRUM_FLAGS; | ||
1830 | playing_mode = AWE_PLAY_INDIRECT; | ||
1831 | |||
1832 | /* reset voices & channels */ | ||
1833 | awe_reset(dev); | ||
1834 | |||
1835 | patch_opened = 0; | ||
1836 | |||
1837 | return 0; | ||
1838 | } | ||
1839 | |||
1840 | |||
1841 | /* close device: | ||
1842 | * reset all voices again (terminate sounds) | ||
1843 | */ | ||
1844 | static void | ||
1845 | awe_close(int dev) | ||
1846 | { | ||
1847 | awe_reset(dev); | ||
1848 | awe_busy = FALSE; | ||
1849 | } | ||
1850 | |||
1851 | |||
1852 | /* set miscellaneous mode parameters | ||
1853 | */ | ||
1854 | static void | ||
1855 | awe_init_ctrl_parms(int init_all) | ||
1856 | { | ||
1857 | int i; | ||
1858 | for (i = 0; i < AWE_MD_END; i++) { | ||
1859 | if (init_all || ctrl_parms[i].init_each_time) | ||
1860 | ctrls[i] = ctrl_parms[i].value; | ||
1861 | } | ||
1862 | } | ||
1863 | |||
1864 | |||
1865 | /* sequencer I/O control: | ||
1866 | */ | ||
1867 | static int | ||
1868 | awe_ioctl(int dev, unsigned int cmd, void __user *arg) | ||
1869 | { | ||
1870 | switch (cmd) { | ||
1871 | case SNDCTL_SYNTH_INFO: | ||
1872 | if (playing_mode == AWE_PLAY_DIRECT) | ||
1873 | awe_info.nr_voices = awe_max_voices; | ||
1874 | else | ||
1875 | awe_info.nr_voices = AWE_MAX_CHANNELS; | ||
1876 | if (copy_to_user(arg, &awe_info, sizeof(awe_info))) | ||
1877 | return -EFAULT; | ||
1878 | return 0; | ||
1879 | break; | ||
1880 | |||
1881 | case SNDCTL_SEQ_RESETSAMPLES: | ||
1882 | awe_reset(dev); | ||
1883 | awe_reset_samples(); | ||
1884 | return 0; | ||
1885 | break; | ||
1886 | |||
1887 | case SNDCTL_SEQ_PERCMODE: | ||
1888 | /* what's this? */ | ||
1889 | return 0; | ||
1890 | break; | ||
1891 | |||
1892 | case SNDCTL_SYNTH_MEMAVL: | ||
1893 | return memsize - awe_free_mem_ptr() * 2; | ||
1894 | break; | ||
1895 | |||
1896 | default: | ||
1897 | printk(KERN_WARNING "AWE32: unsupported ioctl %d\n", cmd); | ||
1898 | return -EINVAL; | ||
1899 | break; | ||
1900 | } | ||
1901 | } | ||
1902 | |||
1903 | |||
1904 | static int voice_in_range(int voice) | ||
1905 | { | ||
1906 | if (playing_mode == AWE_PLAY_DIRECT) { | ||
1907 | if (voice < 0 || voice >= awe_max_voices) | ||
1908 | return FALSE; | ||
1909 | } else { | ||
1910 | if (voice < 0 || voice >= AWE_MAX_CHANNELS) | ||
1911 | return FALSE; | ||
1912 | } | ||
1913 | return TRUE; | ||
1914 | } | ||
1915 | |||
1916 | static void release_voice(int voice, int do_sustain) | ||
1917 | { | ||
1918 | if (IS_NO_SOUND(voice)) | ||
1919 | return; | ||
1920 | if (do_sustain && (voices[voice].cinfo->sustained == 127 || | ||
1921 | voices[voice].sostenuto == 127)) | ||
1922 | voices[voice].state = AWE_ST_SUSTAINED; | ||
1923 | else { | ||
1924 | awe_note_off(voice); | ||
1925 | awe_fx_init(voices[voice].ch); | ||
1926 | awe_voice_init(voice, FALSE); | ||
1927 | } | ||
1928 | } | ||
1929 | |||
1930 | /* release all notes */ | ||
1931 | static void awe_note_off_all(int do_sustain) | ||
1932 | { | ||
1933 | int i; | ||
1934 | for (i = 0; i < awe_max_voices; i++) | ||
1935 | release_voice(i, do_sustain); | ||
1936 | } | ||
1937 | |||
1938 | /* kill a voice: | ||
1939 | * not terminate, just release the voice. | ||
1940 | */ | ||
1941 | static int | ||
1942 | awe_kill_note(int dev, int voice, int note, int velocity) | ||
1943 | { | ||
1944 | int i, v2, key; | ||
1945 | |||
1946 | DEBUG(2,printk("AWE32: [off(%d) nt=%d vl=%d]\n", voice, note, velocity)); | ||
1947 | if (! voice_in_range(voice)) | ||
1948 | return -EINVAL; | ||
1949 | |||
1950 | switch (playing_mode) { | ||
1951 | case AWE_PLAY_DIRECT: | ||
1952 | case AWE_PLAY_INDIRECT: | ||
1953 | key = AWE_VOICE_KEY(voice); | ||
1954 | break; | ||
1955 | |||
1956 | case AWE_PLAY_MULTI2: | ||
1957 | v2 = voice_alloc->map[voice] >> 8; | ||
1958 | voice_alloc->map[voice] = 0; | ||
1959 | voice = v2; | ||
1960 | if (voice < 0 || voice >= AWE_MAX_CHANNELS) | ||
1961 | return -EINVAL; | ||
1962 | /* continue to below */ | ||
1963 | default: | ||
1964 | key = AWE_CHAN_KEY(voice, note); | ||
1965 | break; | ||
1966 | } | ||
1967 | |||
1968 | for (i = 0; i < awe_max_voices; i++) { | ||
1969 | if (voices[i].key == key) | ||
1970 | release_voice(i, TRUE); | ||
1971 | } | ||
1972 | return 0; | ||
1973 | } | ||
1974 | |||
1975 | |||
1976 | static void start_or_volume_change(int voice, int velocity) | ||
1977 | { | ||
1978 | voices[voice].velocity = velocity; | ||
1979 | awe_calc_volume(voice); | ||
1980 | if (voices[voice].state == AWE_ST_STANDBY) | ||
1981 | awe_note_on(voice); | ||
1982 | else if (voices[voice].state == AWE_ST_ON) | ||
1983 | awe_set_volume(voice, FALSE); | ||
1984 | } | ||
1985 | |||
1986 | static void set_and_start_voice(int voice, int state) | ||
1987 | { | ||
1988 | /* calculate pitch & volume parameters */ | ||
1989 | voices[voice].state = state; | ||
1990 | awe_calc_pitch(voice); | ||
1991 | awe_calc_volume(voice); | ||
1992 | if (state == AWE_ST_ON) | ||
1993 | awe_note_on(voice); | ||
1994 | } | ||
1995 | |||
1996 | /* start a voice: | ||
1997 | * if note is 255, identical with aftertouch function. | ||
1998 | * Otherwise, start a voice with specified not and volume. | ||
1999 | */ | ||
2000 | static int | ||
2001 | awe_start_note(int dev, int voice, int note, int velocity) | ||
2002 | { | ||
2003 | int i, key, state, volonly; | ||
2004 | |||
2005 | DEBUG(2,printk("AWE32: [on(%d) nt=%d vl=%d]\n", voice, note, velocity)); | ||
2006 | if (! voice_in_range(voice)) | ||
2007 | return -EINVAL; | ||
2008 | |||
2009 | if (velocity == 0) | ||
2010 | state = AWE_ST_STANDBY; /* stand by for playing */ | ||
2011 | else | ||
2012 | state = AWE_ST_ON; /* really play */ | ||
2013 | volonly = FALSE; | ||
2014 | |||
2015 | switch (playing_mode) { | ||
2016 | case AWE_PLAY_DIRECT: | ||
2017 | case AWE_PLAY_INDIRECT: | ||
2018 | key = AWE_VOICE_KEY(voice); | ||
2019 | if (note == 255) | ||
2020 | volonly = TRUE; | ||
2021 | break; | ||
2022 | |||
2023 | case AWE_PLAY_MULTI2: | ||
2024 | voice = voice_alloc->map[voice] >> 8; | ||
2025 | if (voice < 0 || voice >= AWE_MAX_CHANNELS) | ||
2026 | return -EINVAL; | ||
2027 | /* continue to below */ | ||
2028 | default: | ||
2029 | if (note >= 128) { /* key volume mode */ | ||
2030 | note -= 128; | ||
2031 | volonly = TRUE; | ||
2032 | } | ||
2033 | key = AWE_CHAN_KEY(voice, note); | ||
2034 | break; | ||
2035 | } | ||
2036 | |||
2037 | /* dynamic volume change */ | ||
2038 | if (volonly) { | ||
2039 | for (i = 0; i < awe_max_voices; i++) { | ||
2040 | if (voices[i].key == key) | ||
2041 | start_or_volume_change(i, velocity); | ||
2042 | } | ||
2043 | return 0; | ||
2044 | } | ||
2045 | |||
2046 | /* if the same note still playing, stop it */ | ||
2047 | if (playing_mode != AWE_PLAY_DIRECT || ctrls[AWE_MD_EXCLUSIVE_SOUND]) { | ||
2048 | for (i = 0; i < awe_max_voices; i++) | ||
2049 | if (voices[i].key == key) { | ||
2050 | if (voices[i].state == AWE_ST_ON) { | ||
2051 | awe_note_off(i); | ||
2052 | awe_voice_init(i, FALSE); | ||
2053 | } else if (voices[i].state == AWE_ST_STANDBY) | ||
2054 | awe_voice_init(i, TRUE); | ||
2055 | } | ||
2056 | } | ||
2057 | |||
2058 | /* allocate voices */ | ||
2059 | if (playing_mode == AWE_PLAY_DIRECT) | ||
2060 | awe_alloc_one_voice(voice, note, velocity); | ||
2061 | else | ||
2062 | awe_alloc_multi_voices(voice, note, velocity, key); | ||
2063 | |||
2064 | /* turn off other voices exlusively (for drums) */ | ||
2065 | for (i = 0; i < awe_max_voices; i++) | ||
2066 | if (voices[i].key == key) | ||
2067 | awe_exclusive_off(i); | ||
2068 | |||
2069 | /* set up pitch and volume parameters */ | ||
2070 | for (i = 0; i < awe_max_voices; i++) { | ||
2071 | if (voices[i].key == key && voices[i].state == AWE_ST_OFF) | ||
2072 | set_and_start_voice(i, state); | ||
2073 | } | ||
2074 | |||
2075 | return 0; | ||
2076 | } | ||
2077 | |||
2078 | |||
2079 | /* calculate hash key */ | ||
2080 | static int | ||
2081 | awe_search_key(int bank, int preset, int note) | ||
2082 | { | ||
2083 | unsigned int key; | ||
2084 | |||
2085 | #if 1 /* new hash table */ | ||
2086 | if (bank == AWE_DRUM_BANK) | ||
2087 | key = preset + note + 128; | ||
2088 | else | ||
2089 | key = bank + preset; | ||
2090 | #else | ||
2091 | key = preset; | ||
2092 | #endif | ||
2093 | key %= AWE_MAX_PRESETS; | ||
2094 | |||
2095 | return (int)key; | ||
2096 | } | ||
2097 | |||
2098 | |||
2099 | /* search instrument from hash table */ | ||
2100 | static awe_voice_list * | ||
2101 | awe_search_instr(int bank, int preset, int note) | ||
2102 | { | ||
2103 | awe_voice_list *p; | ||
2104 | int key, key2; | ||
2105 | |||
2106 | key = awe_search_key(bank, preset, note); | ||
2107 | for (p = preset_table[key]; p; p = p->next_bank) { | ||
2108 | if (p->instr == preset && p->bank == bank) | ||
2109 | return p; | ||
2110 | } | ||
2111 | key2 = awe_search_key(bank, preset, 0); /* search default */ | ||
2112 | if (key == key2) | ||
2113 | return NULL; | ||
2114 | for (p = preset_table[key2]; p; p = p->next_bank) { | ||
2115 | if (p->instr == preset && p->bank == bank) | ||
2116 | return p; | ||
2117 | } | ||
2118 | return NULL; | ||
2119 | } | ||
2120 | |||
2121 | |||
2122 | /* assign the instrument to a voice */ | ||
2123 | static int | ||
2124 | awe_set_instr_2(int dev, int voice, int instr_no) | ||
2125 | { | ||
2126 | if (playing_mode == AWE_PLAY_MULTI2) { | ||
2127 | voice = voice_alloc->map[voice] >> 8; | ||
2128 | if (voice < 0 || voice >= AWE_MAX_CHANNELS) | ||
2129 | return -EINVAL; | ||
2130 | } | ||
2131 | return awe_set_instr(dev, voice, instr_no); | ||
2132 | } | ||
2133 | |||
2134 | /* assign the instrument to a channel; voice is the channel number */ | ||
2135 | static int | ||
2136 | awe_set_instr(int dev, int voice, int instr_no) | ||
2137 | { | ||
2138 | awe_chan_info *cinfo; | ||
2139 | |||
2140 | if (! voice_in_range(voice)) | ||
2141 | return -EINVAL; | ||
2142 | |||
2143 | if (instr_no < 0 || instr_no >= AWE_MAX_PRESETS) | ||
2144 | return -EINVAL; | ||
2145 | |||
2146 | cinfo = &channels[voice]; | ||
2147 | cinfo->instr = instr_no; | ||
2148 | DEBUG(2,printk("AWE32: [program(%d) %d]\n", voice, instr_no)); | ||
2149 | |||
2150 | return 0; | ||
2151 | } | ||
2152 | |||
2153 | |||
2154 | /* reset all voices; terminate sounds and initialize parameters */ | ||
2155 | static void | ||
2156 | awe_reset(int dev) | ||
2157 | { | ||
2158 | int i; | ||
2159 | current_alloc_time = 0; | ||
2160 | /* don't turn off voice 31 and 32. they are used also for FM voices */ | ||
2161 | for (i = 0; i < awe_max_voices; i++) { | ||
2162 | awe_terminate(i); | ||
2163 | awe_voice_init(i, TRUE); | ||
2164 | } | ||
2165 | for (i = 0; i < AWE_MAX_CHANNELS; i++) | ||
2166 | awe_channel_init(i, TRUE); | ||
2167 | for (i = 0; i < 16; i++) { | ||
2168 | awe_operations.chn_info[i].controllers[CTL_MAIN_VOLUME] = 127; | ||
2169 | awe_operations.chn_info[i].controllers[CTL_EXPRESSION] = 127; | ||
2170 | } | ||
2171 | awe_init_fm(); | ||
2172 | awe_tweak(); | ||
2173 | } | ||
2174 | |||
2175 | |||
2176 | /* hardware specific control: | ||
2177 | * GUS specific and AWE32 specific controls are available. | ||
2178 | */ | ||
2179 | static void | ||
2180 | awe_hw_control(int dev, unsigned char *event) | ||
2181 | { | ||
2182 | int cmd = event[2]; | ||
2183 | if (cmd & _AWE_MODE_FLAG) | ||
2184 | awe_hw_awe_control(dev, cmd & _AWE_MODE_VALUE_MASK, event); | ||
2185 | #ifdef AWE_HAS_GUS_COMPATIBILITY | ||
2186 | else | ||
2187 | awe_hw_gus_control(dev, cmd & _AWE_MODE_VALUE_MASK, event); | ||
2188 | #endif | ||
2189 | } | ||
2190 | |||
2191 | |||
2192 | #ifdef AWE_HAS_GUS_COMPATIBILITY | ||
2193 | |||
2194 | /* GUS compatible controls */ | ||
2195 | static void | ||
2196 | awe_hw_gus_control(int dev, int cmd, unsigned char *event) | ||
2197 | { | ||
2198 | int voice, i, key; | ||
2199 | unsigned short p1; | ||
2200 | short p2; | ||
2201 | int plong; | ||
2202 | |||
2203 | if (MULTI_LAYER_MODE()) | ||
2204 | return; | ||
2205 | if (cmd == _GUS_NUMVOICES) | ||
2206 | return; | ||
2207 | |||
2208 | voice = event[3]; | ||
2209 | if (! voice_in_range(voice)) | ||
2210 | return; | ||
2211 | |||
2212 | p1 = *(unsigned short *) &event[4]; | ||
2213 | p2 = *(short *) &event[6]; | ||
2214 | plong = *(int*) &event[4]; | ||
2215 | |||
2216 | switch (cmd) { | ||
2217 | case _GUS_VOICESAMPLE: | ||
2218 | awe_set_instr(dev, voice, p1); | ||
2219 | return; | ||
2220 | |||
2221 | case _GUS_VOICEBALA: | ||
2222 | /* 0 to 15 --> -128 to 127 */ | ||
2223 | awe_panning(dev, voice, ((int)p1 << 4) - 128); | ||
2224 | return; | ||
2225 | |||
2226 | case _GUS_VOICEVOL: | ||
2227 | case _GUS_VOICEVOL2: | ||
2228 | /* not supported yet */ | ||
2229 | return; | ||
2230 | |||
2231 | case _GUS_RAMPRANGE: | ||
2232 | case _GUS_RAMPRATE: | ||
2233 | case _GUS_RAMPMODE: | ||
2234 | case _GUS_RAMPON: | ||
2235 | case _GUS_RAMPOFF: | ||
2236 | /* volume ramping not supported */ | ||
2237 | return; | ||
2238 | |||
2239 | case _GUS_VOLUME_SCALE: | ||
2240 | return; | ||
2241 | |||
2242 | case _GUS_VOICE_POS: | ||
2243 | FX_SET(&channels[voice].fx, AWE_FX_SAMPLE_START, | ||
2244 | (short)(plong & 0x7fff)); | ||
2245 | FX_SET(&channels[voice].fx, AWE_FX_COARSE_SAMPLE_START, | ||
2246 | (plong >> 15) & 0xffff); | ||
2247 | return; | ||
2248 | } | ||
2249 | |||
2250 | key = AWE_VOICE_KEY(voice); | ||
2251 | for (i = 0; i < awe_max_voices; i++) { | ||
2252 | if (voices[i].key == key) { | ||
2253 | switch (cmd) { | ||
2254 | case _GUS_VOICEON: | ||
2255 | awe_note_on(i); | ||
2256 | break; | ||
2257 | |||
2258 | case _GUS_VOICEOFF: | ||
2259 | awe_terminate(i); | ||
2260 | awe_fx_init(voices[i].ch); | ||
2261 | awe_voice_init(i, TRUE); | ||
2262 | break; | ||
2263 | |||
2264 | case _GUS_VOICEFADE: | ||
2265 | awe_note_off(i); | ||
2266 | awe_fx_init(voices[i].ch); | ||
2267 | awe_voice_init(i, FALSE); | ||
2268 | break; | ||
2269 | |||
2270 | case _GUS_VOICEFREQ: | ||
2271 | awe_calc_pitch_from_freq(i, plong); | ||
2272 | break; | ||
2273 | } | ||
2274 | } | ||
2275 | } | ||
2276 | } | ||
2277 | |||
2278 | #endif /* gus_compat */ | ||
2279 | |||
2280 | |||
2281 | /* AWE32 specific controls */ | ||
2282 | static void | ||
2283 | awe_hw_awe_control(int dev, int cmd, unsigned char *event) | ||
2284 | { | ||
2285 | int voice; | ||
2286 | unsigned short p1; | ||
2287 | short p2; | ||
2288 | int i; | ||
2289 | |||
2290 | voice = event[3]; | ||
2291 | if (! voice_in_range(voice)) | ||
2292 | return; | ||
2293 | |||
2294 | if (playing_mode == AWE_PLAY_MULTI2) { | ||
2295 | voice = voice_alloc->map[voice] >> 8; | ||
2296 | if (voice < 0 || voice >= AWE_MAX_CHANNELS) | ||
2297 | return; | ||
2298 | } | ||
2299 | |||
2300 | p1 = *(unsigned short *) &event[4]; | ||
2301 | p2 = *(short *) &event[6]; | ||
2302 | |||
2303 | switch (cmd) { | ||
2304 | case _AWE_DEBUG_MODE: | ||
2305 | ctrls[AWE_MD_DEBUG_MODE] = p1; | ||
2306 | printk(KERN_DEBUG "AWE32: debug mode = %d\n", ctrls[AWE_MD_DEBUG_MODE]); | ||
2307 | break; | ||
2308 | case _AWE_REVERB_MODE: | ||
2309 | ctrls[AWE_MD_REVERB_MODE] = p1; | ||
2310 | awe_update_reverb_mode(); | ||
2311 | break; | ||
2312 | |||
2313 | case _AWE_CHORUS_MODE: | ||
2314 | ctrls[AWE_MD_CHORUS_MODE] = p1; | ||
2315 | awe_update_chorus_mode(); | ||
2316 | break; | ||
2317 | |||
2318 | case _AWE_REMOVE_LAST_SAMPLES: | ||
2319 | DEBUG(0,printk("AWE32: remove last samples\n")); | ||
2320 | awe_reset(0); | ||
2321 | if (locked_sf_id > 0) | ||
2322 | awe_remove_samples(locked_sf_id); | ||
2323 | break; | ||
2324 | |||
2325 | case _AWE_INITIALIZE_CHIP: | ||
2326 | awe_initialize(); | ||
2327 | break; | ||
2328 | |||
2329 | case _AWE_SEND_EFFECT: | ||
2330 | i = -1; | ||
2331 | if (p1 >= 0x100) { | ||
2332 | i = (p1 >> 8); | ||
2333 | if (i < 0 || i >= MAX_LAYERS) | ||
2334 | break; | ||
2335 | } | ||
2336 | awe_send_effect(voice, i, p1, p2); | ||
2337 | break; | ||
2338 | |||
2339 | case _AWE_RESET_CHANNEL: | ||
2340 | awe_channel_init(voice, !p1); | ||
2341 | break; | ||
2342 | |||
2343 | case _AWE_TERMINATE_ALL: | ||
2344 | awe_reset(0); | ||
2345 | break; | ||
2346 | |||
2347 | case _AWE_TERMINATE_CHANNEL: | ||
2348 | awe_voice_change(voice, awe_terminate_and_init); | ||
2349 | break; | ||
2350 | |||
2351 | case _AWE_RELEASE_ALL: | ||
2352 | awe_note_off_all(FALSE); | ||
2353 | break; | ||
2354 | case _AWE_NOTEOFF_ALL: | ||
2355 | awe_note_off_all(TRUE); | ||
2356 | break; | ||
2357 | |||
2358 | case _AWE_INITIAL_VOLUME: | ||
2359 | DEBUG(0,printk("AWE32: init attenuation %d\n", p1)); | ||
2360 | atten_relative = (char)p2; | ||
2361 | atten_offset = (short)p1; | ||
2362 | awe_update_volume(); | ||
2363 | break; | ||
2364 | |||
2365 | case _AWE_CHN_PRESSURE: | ||
2366 | channels[voice].chan_press = p1; | ||
2367 | awe_modwheel_change(voice, p1); | ||
2368 | break; | ||
2369 | |||
2370 | case _AWE_CHANNEL_MODE: | ||
2371 | DEBUG(0,printk("AWE32: channel mode = %d\n", p1)); | ||
2372 | playing_mode = p1; | ||
2373 | awe_reset(0); | ||
2374 | break; | ||
2375 | |||
2376 | case _AWE_DRUM_CHANNELS: | ||
2377 | DEBUG(0,printk("AWE32: drum flags = %x\n", p1)); | ||
2378 | drum_flags = *(unsigned int*)&event[4]; | ||
2379 | break; | ||
2380 | |||
2381 | case _AWE_MISC_MODE: | ||
2382 | DEBUG(0,printk("AWE32: ctrl parms = %d %d\n", p1, p2)); | ||
2383 | if (p1 > AWE_MD_VERSION && p1 < AWE_MD_END) { | ||
2384 | ctrls[p1] = p2; | ||
2385 | if (ctrl_parms[p1].update) | ||
2386 | ctrl_parms[p1].update(); | ||
2387 | } | ||
2388 | break; | ||
2389 | |||
2390 | case _AWE_EQUALIZER: | ||
2391 | ctrls[AWE_MD_BASS_LEVEL] = p1; | ||
2392 | ctrls[AWE_MD_TREBLE_LEVEL] = p2; | ||
2393 | awe_update_equalizer(); | ||
2394 | break; | ||
2395 | |||
2396 | default: | ||
2397 | DEBUG(0,printk("AWE32: hw control cmd=%d voice=%d\n", cmd, voice)); | ||
2398 | break; | ||
2399 | } | ||
2400 | } | ||
2401 | |||
2402 | |||
2403 | /* change effects */ | ||
2404 | static void | ||
2405 | awe_send_effect(int voice, int layer, int type, int val) | ||
2406 | { | ||
2407 | awe_chan_info *cinfo; | ||
2408 | FX_Rec *fx; | ||
2409 | int mode; | ||
2410 | |||
2411 | cinfo = &channels[voice]; | ||
2412 | if (layer >= 0 && layer < MAX_LAYERS) | ||
2413 | fx = &cinfo->fx_layer[layer]; | ||
2414 | else | ||
2415 | fx = &cinfo->fx; | ||
2416 | |||
2417 | if (type & 0x40) | ||
2418 | mode = FX_FLAG_OFF; | ||
2419 | else if (type & 0x80) | ||
2420 | mode = FX_FLAG_ADD; | ||
2421 | else | ||
2422 | mode = FX_FLAG_SET; | ||
2423 | type &= 0x3f; | ||
2424 | |||
2425 | if (type >= 0 && type < AWE_FX_END) { | ||
2426 | DEBUG(2,printk("AWE32: effects (%d) %d %d\n", voice, type, val)); | ||
2427 | if (mode == FX_FLAG_SET) | ||
2428 | FX_SET(fx, type, val); | ||
2429 | else if (mode == FX_FLAG_ADD) | ||
2430 | FX_ADD(fx, type, val); | ||
2431 | else | ||
2432 | FX_UNSET(fx, type); | ||
2433 | if (mode != FX_FLAG_OFF && parm_defs[type].realtime) { | ||
2434 | DEBUG(2,printk("AWE32: fx_realtime (%d)\n", voice)); | ||
2435 | awe_voice_change(voice, parm_defs[type].realtime); | ||
2436 | } | ||
2437 | } | ||
2438 | } | ||
2439 | |||
2440 | |||
2441 | /* change modulation wheel; voice is already mapped on multi2 mode */ | ||
2442 | static void | ||
2443 | awe_modwheel_change(int voice, int value) | ||
2444 | { | ||
2445 | int i; | ||
2446 | awe_chan_info *cinfo; | ||
2447 | |||
2448 | cinfo = &channels[voice]; | ||
2449 | i = value * ctrls[AWE_MD_MOD_SENSE] / 1200; | ||
2450 | FX_ADD(&cinfo->fx, AWE_FX_LFO1_PITCH, i); | ||
2451 | awe_voice_change(voice, awe_fx_fmmod); | ||
2452 | FX_ADD(&cinfo->fx, AWE_FX_LFO2_PITCH, i); | ||
2453 | awe_voice_change(voice, awe_fx_fm2frq2); | ||
2454 | } | ||
2455 | |||
2456 | |||
2457 | /* voice pressure change */ | ||
2458 | static void | ||
2459 | awe_aftertouch(int dev, int voice, int pressure) | ||
2460 | { | ||
2461 | int note; | ||
2462 | |||
2463 | DEBUG(2,printk("AWE32: [after(%d) %d]\n", voice, pressure)); | ||
2464 | if (! voice_in_range(voice)) | ||
2465 | return; | ||
2466 | |||
2467 | switch (playing_mode) { | ||
2468 | case AWE_PLAY_DIRECT: | ||
2469 | case AWE_PLAY_INDIRECT: | ||
2470 | awe_start_note(dev, voice, 255, pressure); | ||
2471 | break; | ||
2472 | case AWE_PLAY_MULTI2: | ||
2473 | note = (voice_alloc->map[voice] & 0xff) - 1; | ||
2474 | awe_key_pressure(dev, voice, note + 0x80, pressure); | ||
2475 | break; | ||
2476 | } | ||
2477 | } | ||
2478 | |||
2479 | |||
2480 | /* voice control change */ | ||
2481 | static void | ||
2482 | awe_controller(int dev, int voice, int ctrl_num, int value) | ||
2483 | { | ||
2484 | awe_chan_info *cinfo; | ||
2485 | |||
2486 | if (! voice_in_range(voice)) | ||
2487 | return; | ||
2488 | |||
2489 | if (playing_mode == AWE_PLAY_MULTI2) { | ||
2490 | voice = voice_alloc->map[voice] >> 8; | ||
2491 | if (voice < 0 || voice >= AWE_MAX_CHANNELS) | ||
2492 | return; | ||
2493 | } | ||
2494 | |||
2495 | cinfo = &channels[voice]; | ||
2496 | |||
2497 | switch (ctrl_num) { | ||
2498 | case CTL_BANK_SELECT: /* MIDI control #0 */ | ||
2499 | DEBUG(2,printk("AWE32: [bank(%d) %d]\n", voice, value)); | ||
2500 | if (MULTI_LAYER_MODE() && IS_DRUM_CHANNEL(voice) && | ||
2501 | !ctrls[AWE_MD_TOGGLE_DRUM_BANK]) | ||
2502 | break; | ||
2503 | if (value < 0 || value > 255) | ||
2504 | break; | ||
2505 | cinfo->bank = value; | ||
2506 | if (cinfo->bank == AWE_DRUM_BANK) | ||
2507 | DRUM_CHANNEL_ON(cinfo->channel); | ||
2508 | else | ||
2509 | DRUM_CHANNEL_OFF(cinfo->channel); | ||
2510 | awe_set_instr(dev, voice, cinfo->instr); | ||
2511 | break; | ||
2512 | |||
2513 | case CTL_MODWHEEL: /* MIDI control #1 */ | ||
2514 | DEBUG(2,printk("AWE32: [modwheel(%d) %d]\n", voice, value)); | ||
2515 | awe_modwheel_change(voice, value); | ||
2516 | break; | ||
2517 | |||
2518 | case CTRL_PITCH_BENDER: /* SEQ1 V2 contorl */ | ||
2519 | DEBUG(2,printk("AWE32: [bend(%d) %d]\n", voice, value)); | ||
2520 | /* zero centered */ | ||
2521 | cinfo->bender = value; | ||
2522 | awe_voice_change(voice, awe_set_voice_pitch); | ||
2523 | break; | ||
2524 | |||
2525 | case CTRL_PITCH_BENDER_RANGE: /* SEQ1 V2 control */ | ||
2526 | DEBUG(2,printk("AWE32: [range(%d) %d]\n", voice, value)); | ||
2527 | /* value = sense x 100 */ | ||
2528 | cinfo->bender_range = value; | ||
2529 | /* no audible pitch change yet.. */ | ||
2530 | break; | ||
2531 | |||
2532 | case CTL_EXPRESSION: /* MIDI control #11 */ | ||
2533 | if (SINGLE_LAYER_MODE()) | ||
2534 | value /= 128; | ||
2535 | case CTRL_EXPRESSION: /* SEQ1 V2 control */ | ||
2536 | DEBUG(2,printk("AWE32: [expr(%d) %d]\n", voice, value)); | ||
2537 | /* 0 - 127 */ | ||
2538 | cinfo->expression_vol = value; | ||
2539 | awe_voice_change(voice, awe_set_voice_vol); | ||
2540 | break; | ||
2541 | |||
2542 | case CTL_PAN: /* MIDI control #10 */ | ||
2543 | DEBUG(2,printk("AWE32: [pan(%d) %d]\n", voice, value)); | ||
2544 | /* (0-127) -> signed 8bit */ | ||
2545 | cinfo->panning = value * 2 - 128; | ||
2546 | if (ctrls[AWE_MD_REALTIME_PAN]) | ||
2547 | awe_voice_change(voice, awe_set_pan); | ||
2548 | break; | ||
2549 | |||
2550 | case CTL_MAIN_VOLUME: /* MIDI control #7 */ | ||
2551 | if (SINGLE_LAYER_MODE()) | ||
2552 | value = (value * 100) / 16383; | ||
2553 | case CTRL_MAIN_VOLUME: /* SEQ1 V2 control */ | ||
2554 | DEBUG(2,printk("AWE32: [mainvol(%d) %d]\n", voice, value)); | ||
2555 | /* 0 - 127 */ | ||
2556 | cinfo->main_vol = value; | ||
2557 | awe_voice_change(voice, awe_set_voice_vol); | ||
2558 | break; | ||
2559 | |||
2560 | case CTL_EXT_EFF_DEPTH: /* reverb effects: 0-127 */ | ||
2561 | DEBUG(2,printk("AWE32: [reverb(%d) %d]\n", voice, value)); | ||
2562 | FX_SET(&cinfo->fx, AWE_FX_REVERB, value * 2); | ||
2563 | break; | ||
2564 | |||
2565 | case CTL_CHORUS_DEPTH: /* chorus effects: 0-127 */ | ||
2566 | DEBUG(2,printk("AWE32: [chorus(%d) %d]\n", voice, value)); | ||
2567 | FX_SET(&cinfo->fx, AWE_FX_CHORUS, value * 2); | ||
2568 | break; | ||
2569 | |||
2570 | case 120: /* all sounds off */ | ||
2571 | awe_note_off_all(FALSE); | ||
2572 | break; | ||
2573 | case 123: /* all notes off */ | ||
2574 | awe_note_off_all(TRUE); | ||
2575 | break; | ||
2576 | |||
2577 | case CTL_SUSTAIN: /* MIDI control #64 */ | ||
2578 | cinfo->sustained = value; | ||
2579 | if (value != 127) | ||
2580 | awe_voice_change(voice, awe_sustain_off); | ||
2581 | break; | ||
2582 | |||
2583 | case CTL_SOSTENUTO: /* MIDI control #66 */ | ||
2584 | if (value == 127) | ||
2585 | awe_voice_change(voice, awe_sostenuto_on); | ||
2586 | else | ||
2587 | awe_voice_change(voice, awe_sustain_off); | ||
2588 | break; | ||
2589 | |||
2590 | default: | ||
2591 | DEBUG(0,printk("AWE32: [control(%d) ctrl=%d val=%d]\n", | ||
2592 | voice, ctrl_num, value)); | ||
2593 | break; | ||
2594 | } | ||
2595 | } | ||
2596 | |||
2597 | |||
2598 | /* voice pan change (value = -128 - 127) */ | ||
2599 | static void | ||
2600 | awe_panning(int dev, int voice, int value) | ||
2601 | { | ||
2602 | awe_chan_info *cinfo; | ||
2603 | |||
2604 | if (! voice_in_range(voice)) | ||
2605 | return; | ||
2606 | |||
2607 | if (playing_mode == AWE_PLAY_MULTI2) { | ||
2608 | voice = voice_alloc->map[voice] >> 8; | ||
2609 | if (voice < 0 || voice >= AWE_MAX_CHANNELS) | ||
2610 | return; | ||
2611 | } | ||
2612 | |||
2613 | cinfo = &channels[voice]; | ||
2614 | cinfo->panning = value; | ||
2615 | DEBUG(2,printk("AWE32: [pan(%d) %d]\n", voice, cinfo->panning)); | ||
2616 | if (ctrls[AWE_MD_REALTIME_PAN]) | ||
2617 | awe_voice_change(voice, awe_set_pan); | ||
2618 | } | ||
2619 | |||
2620 | |||
2621 | /* volume mode change */ | ||
2622 | static void | ||
2623 | awe_volume_method(int dev, int mode) | ||
2624 | { | ||
2625 | /* not impremented */ | ||
2626 | DEBUG(0,printk("AWE32: [volmethod mode=%d]\n", mode)); | ||
2627 | } | ||
2628 | |||
2629 | |||
2630 | /* pitch wheel change: 0-16384 */ | ||
2631 | static void | ||
2632 | awe_bender(int dev, int voice, int value) | ||
2633 | { | ||
2634 | awe_chan_info *cinfo; | ||
2635 | |||
2636 | if (! voice_in_range(voice)) | ||
2637 | return; | ||
2638 | |||
2639 | if (playing_mode == AWE_PLAY_MULTI2) { | ||
2640 | voice = voice_alloc->map[voice] >> 8; | ||
2641 | if (voice < 0 || voice >= AWE_MAX_CHANNELS) | ||
2642 | return; | ||
2643 | } | ||
2644 | |||
2645 | /* convert to zero centered value */ | ||
2646 | cinfo = &channels[voice]; | ||
2647 | cinfo->bender = value - 8192; | ||
2648 | DEBUG(2,printk("AWE32: [bend(%d) %d]\n", voice, cinfo->bender)); | ||
2649 | awe_voice_change(voice, awe_set_voice_pitch); | ||
2650 | } | ||
2651 | |||
2652 | |||
2653 | /* | ||
2654 | * load a sound patch: | ||
2655 | * three types of patches are accepted: AWE, GUS, and SYSEX. | ||
2656 | */ | ||
2657 | |||
2658 | static int | ||
2659 | awe_load_patch(int dev, int format, const char __user *addr, | ||
2660 | int offs, int count, int pmgr_flag) | ||
2661 | { | ||
2662 | awe_patch_info patch; | ||
2663 | int rc = 0; | ||
2664 | |||
2665 | #ifdef AWE_HAS_GUS_COMPATIBILITY | ||
2666 | if (format == GUS_PATCH) { | ||
2667 | return awe_load_guspatch(addr, offs, count, pmgr_flag); | ||
2668 | } else | ||
2669 | #endif | ||
2670 | if (format == SYSEX_PATCH) { | ||
2671 | /* no system exclusive message supported yet */ | ||
2672 | return 0; | ||
2673 | } else if (format != AWE_PATCH) { | ||
2674 | printk(KERN_WARNING "AWE32 Error: Invalid patch format (key) 0x%x\n", format); | ||
2675 | return -EINVAL; | ||
2676 | } | ||
2677 | |||
2678 | if (count < AWE_PATCH_INFO_SIZE) { | ||
2679 | printk(KERN_WARNING "AWE32 Error: Patch header too short\n"); | ||
2680 | return -EINVAL; | ||
2681 | } | ||
2682 | if (copy_from_user(((char*)&patch) + offs, addr + offs, | ||
2683 | AWE_PATCH_INFO_SIZE - offs)) | ||
2684 | return -EFAULT; | ||
2685 | |||
2686 | count -= AWE_PATCH_INFO_SIZE; | ||
2687 | if (count < patch.len) { | ||
2688 | printk(KERN_WARNING "AWE32: sample: Patch record too short (%d<%d)\n", | ||
2689 | count, patch.len); | ||
2690 | return -EINVAL; | ||
2691 | } | ||
2692 | |||
2693 | switch (patch.type) { | ||
2694 | case AWE_LOAD_INFO: | ||
2695 | rc = awe_load_info(&patch, addr, count); | ||
2696 | break; | ||
2697 | case AWE_LOAD_DATA: | ||
2698 | rc = awe_load_data(&patch, addr, count); | ||
2699 | break; | ||
2700 | case AWE_OPEN_PATCH: | ||
2701 | rc = awe_open_patch(&patch, addr, count); | ||
2702 | break; | ||
2703 | case AWE_CLOSE_PATCH: | ||
2704 | rc = awe_close_patch(&patch, addr, count); | ||
2705 | break; | ||
2706 | case AWE_UNLOAD_PATCH: | ||
2707 | rc = awe_unload_patch(&patch, addr, count); | ||
2708 | break; | ||
2709 | case AWE_REPLACE_DATA: | ||
2710 | rc = awe_replace_data(&patch, addr, count); | ||
2711 | break; | ||
2712 | case AWE_MAP_PRESET: | ||
2713 | rc = awe_load_map(&patch, addr, count); | ||
2714 | break; | ||
2715 | /* case AWE_PROBE_INFO: | ||
2716 | rc = awe_probe_info(&patch, addr, count); | ||
2717 | break;*/ | ||
2718 | case AWE_PROBE_DATA: | ||
2719 | rc = awe_probe_data(&patch, addr, count); | ||
2720 | break; | ||
2721 | case AWE_REMOVE_INFO: | ||
2722 | rc = awe_remove_info(&patch, addr, count); | ||
2723 | break; | ||
2724 | case AWE_LOAD_CHORUS_FX: | ||
2725 | rc = awe_load_chorus_fx(&patch, addr, count); | ||
2726 | break; | ||
2727 | case AWE_LOAD_REVERB_FX: | ||
2728 | rc = awe_load_reverb_fx(&patch, addr, count); | ||
2729 | break; | ||
2730 | |||
2731 | default: | ||
2732 | printk(KERN_WARNING "AWE32 Error: unknown patch format type %d\n", | ||
2733 | patch.type); | ||
2734 | rc = -EINVAL; | ||
2735 | } | ||
2736 | |||
2737 | return rc; | ||
2738 | } | ||
2739 | |||
2740 | |||
2741 | /* create an sf list record */ | ||
2742 | static int | ||
2743 | awe_create_sf(int type, char *name) | ||
2744 | { | ||
2745 | sf_list *rec; | ||
2746 | |||
2747 | /* terminate sounds */ | ||
2748 | awe_reset(0); | ||
2749 | rec = (sf_list *)kmalloc(sizeof(*rec), GFP_KERNEL); | ||
2750 | if (rec == NULL) | ||
2751 | return 1; /* no memory */ | ||
2752 | rec->sf_id = current_sf_id + 1; | ||
2753 | rec->type = type; | ||
2754 | if (/*current_sf_id == 0 ||*/ (type & AWE_PAT_LOCKED) != 0) | ||
2755 | locked_sf_id = current_sf_id + 1; | ||
2756 | rec->num_info = awe_free_info(); | ||
2757 | rec->num_sample = awe_free_sample(); | ||
2758 | rec->mem_ptr = awe_free_mem_ptr(); | ||
2759 | rec->infos = rec->last_infos = NULL; | ||
2760 | rec->samples = rec->last_samples = NULL; | ||
2761 | |||
2762 | /* add to linked-list */ | ||
2763 | rec->next = NULL; | ||
2764 | rec->prev = sftail; | ||
2765 | if (sftail) | ||
2766 | sftail->next = rec; | ||
2767 | else | ||
2768 | sfhead = rec; | ||
2769 | sftail = rec; | ||
2770 | current_sf_id++; | ||
2771 | |||
2772 | #ifdef AWE_ALLOW_SAMPLE_SHARING | ||
2773 | rec->shared = NULL; | ||
2774 | if (name) | ||
2775 | memcpy(rec->name, name, AWE_PATCH_NAME_LEN); | ||
2776 | else | ||
2777 | strcpy(rec->name, "*TEMPORARY*"); | ||
2778 | if (current_sf_id > 1 && name && (type & AWE_PAT_SHARED) != 0) { | ||
2779 | /* is the current font really a shared font? */ | ||
2780 | if (is_shared_sf(rec->name)) { | ||
2781 | /* check if the shared font is already installed */ | ||
2782 | sf_list *p; | ||
2783 | for (p = rec->prev; p; p = p->prev) { | ||
2784 | if (is_identical_name(rec->name, p)) { | ||
2785 | rec->shared = p; | ||
2786 | break; | ||
2787 | } | ||
2788 | } | ||
2789 | } | ||
2790 | } | ||
2791 | #endif /* allow sharing */ | ||
2792 | |||
2793 | return 0; | ||
2794 | } | ||
2795 | |||
2796 | |||
2797 | #ifdef AWE_ALLOW_SAMPLE_SHARING | ||
2798 | |||
2799 | /* check if the given name is a valid shared name */ | ||
2800 | #define ASC_TO_KEY(c) ((c) - 'A' + 1) | ||
2801 | static int is_shared_sf(unsigned char *name) | ||
2802 | { | ||
2803 | static unsigned char id_head[4] = { | ||
2804 | ASC_TO_KEY('A'), ASC_TO_KEY('W'), ASC_TO_KEY('E'), | ||
2805 | AWE_MAJOR_VERSION, | ||
2806 | }; | ||
2807 | if (memcmp(name, id_head, 4) == 0) | ||
2808 | return TRUE; | ||
2809 | return FALSE; | ||
2810 | } | ||
2811 | |||
2812 | /* check if the given name matches to the existing list */ | ||
2813 | static int is_identical_name(unsigned char *name, sf_list *p) | ||
2814 | { | ||
2815 | char *id = p->name; | ||
2816 | if (is_shared_sf(id) && memcmp(id, name, AWE_PATCH_NAME_LEN) == 0) | ||
2817 | return TRUE; | ||
2818 | return FALSE; | ||
2819 | } | ||
2820 | |||
2821 | /* check if the given voice info exists */ | ||
2822 | static int info_duplicated(sf_list *sf, awe_voice_list *rec) | ||
2823 | { | ||
2824 | /* search for all sharing lists */ | ||
2825 | for (; sf; sf = sf->shared) { | ||
2826 | awe_voice_list *p; | ||
2827 | for (p = sf->infos; p; p = p->next) { | ||
2828 | if (p->type == V_ST_NORMAL && | ||
2829 | p->bank == rec->bank && | ||
2830 | p->instr == rec->instr && | ||
2831 | p->v.low == rec->v.low && | ||
2832 | p->v.high == rec->v.high && | ||
2833 | p->v.sample == rec->v.sample) | ||
2834 | return TRUE; | ||
2835 | } | ||
2836 | } | ||
2837 | return FALSE; | ||
2838 | } | ||
2839 | |||
2840 | #endif /* AWE_ALLOW_SAMPLE_SHARING */ | ||
2841 | |||
2842 | |||
2843 | /* free sf_list record */ | ||
2844 | /* linked-list in this function is not cared */ | ||
2845 | static void | ||
2846 | awe_free_sf(sf_list *sf) | ||
2847 | { | ||
2848 | if (sf->infos) { | ||
2849 | awe_voice_list *p, *next; | ||
2850 | for (p = sf->infos; p; p = next) { | ||
2851 | next = p->next; | ||
2852 | kfree(p); | ||
2853 | } | ||
2854 | } | ||
2855 | if (sf->samples) { | ||
2856 | awe_sample_list *p, *next; | ||
2857 | for (p = sf->samples; p; p = next) { | ||
2858 | next = p->next; | ||
2859 | kfree(p); | ||
2860 | } | ||
2861 | } | ||
2862 | kfree(sf); | ||
2863 | } | ||
2864 | |||
2865 | |||
2866 | /* open patch; create sf list and set opened flag */ | ||
2867 | static int | ||
2868 | awe_open_patch(awe_patch_info *patch, const char __user *addr, int count) | ||
2869 | { | ||
2870 | awe_open_parm parm; | ||
2871 | int shared; | ||
2872 | |||
2873 | if (copy_from_user(&parm, addr + AWE_PATCH_INFO_SIZE, sizeof(parm))) | ||
2874 | return -EFAULT; | ||
2875 | shared = FALSE; | ||
2876 | |||
2877 | #ifdef AWE_ALLOW_SAMPLE_SHARING | ||
2878 | if (sftail && (parm.type & AWE_PAT_SHARED) != 0) { | ||
2879 | /* is the previous font the same font? */ | ||
2880 | if (is_identical_name(parm.name, sftail)) { | ||
2881 | /* then append to the previous */ | ||
2882 | shared = TRUE; | ||
2883 | awe_reset(0); | ||
2884 | if (parm.type & AWE_PAT_LOCKED) | ||
2885 | locked_sf_id = current_sf_id; | ||
2886 | } | ||
2887 | } | ||
2888 | #endif /* allow sharing */ | ||
2889 | if (! shared) { | ||
2890 | if (awe_create_sf(parm.type, parm.name)) { | ||
2891 | printk(KERN_ERR "AWE32: can't open: failed to alloc new list\n"); | ||
2892 | return -ENOMEM; | ||
2893 | } | ||
2894 | } | ||
2895 | patch_opened = TRUE; | ||
2896 | return current_sf_id; | ||
2897 | } | ||
2898 | |||
2899 | /* check if the patch is already opened */ | ||
2900 | static sf_list * | ||
2901 | check_patch_opened(int type, char *name) | ||
2902 | { | ||
2903 | if (! patch_opened) { | ||
2904 | if (awe_create_sf(type, name)) { | ||
2905 | printk(KERN_ERR "AWE32: failed to alloc new list\n"); | ||
2906 | return NULL; | ||
2907 | } | ||
2908 | patch_opened = TRUE; | ||
2909 | return sftail; | ||
2910 | } | ||
2911 | return sftail; | ||
2912 | } | ||
2913 | |||
2914 | /* close the patch; if no voice is loaded, remove the patch */ | ||
2915 | static int | ||
2916 | awe_close_patch(awe_patch_info *patch, const char __user *addr, int count) | ||
2917 | { | ||
2918 | if (patch_opened && sftail) { | ||
2919 | /* if no voice is loaded, release the current patch */ | ||
2920 | if (sftail->infos == NULL) { | ||
2921 | awe_reset(0); | ||
2922 | awe_remove_samples(current_sf_id - 1); | ||
2923 | } | ||
2924 | } | ||
2925 | patch_opened = 0; | ||
2926 | return 0; | ||
2927 | } | ||
2928 | |||
2929 | |||
2930 | /* remove the latest patch */ | ||
2931 | static int | ||
2932 | awe_unload_patch(awe_patch_info *patch, const char __user *addr, int count) | ||
2933 | { | ||
2934 | if (current_sf_id > 0 && current_sf_id > locked_sf_id) { | ||
2935 | awe_reset(0); | ||
2936 | awe_remove_samples(current_sf_id - 1); | ||
2937 | } | ||
2938 | return 0; | ||
2939 | } | ||
2940 | |||
2941 | /* allocate voice info list records */ | ||
2942 | static awe_voice_list * | ||
2943 | alloc_new_info(void) | ||
2944 | { | ||
2945 | awe_voice_list *newlist; | ||
2946 | |||
2947 | newlist = (awe_voice_list *)kmalloc(sizeof(*newlist), GFP_KERNEL); | ||
2948 | if (newlist == NULL) { | ||
2949 | printk(KERN_ERR "AWE32: can't alloc info table\n"); | ||
2950 | return NULL; | ||
2951 | } | ||
2952 | return newlist; | ||
2953 | } | ||
2954 | |||
2955 | /* allocate sample info list records */ | ||
2956 | static awe_sample_list * | ||
2957 | alloc_new_sample(void) | ||
2958 | { | ||
2959 | awe_sample_list *newlist; | ||
2960 | |||
2961 | newlist = (awe_sample_list *)kmalloc(sizeof(*newlist), GFP_KERNEL); | ||
2962 | if (newlist == NULL) { | ||
2963 | printk(KERN_ERR "AWE32: can't alloc sample table\n"); | ||
2964 | return NULL; | ||
2965 | } | ||
2966 | return newlist; | ||
2967 | } | ||
2968 | |||
2969 | /* load voice map */ | ||
2970 | static int | ||
2971 | awe_load_map(awe_patch_info *patch, const char __user *addr, int count) | ||
2972 | { | ||
2973 | awe_voice_map map; | ||
2974 | awe_voice_list *rec, *p; | ||
2975 | sf_list *sf; | ||
2976 | |||
2977 | /* get the link info */ | ||
2978 | if (count < sizeof(map)) { | ||
2979 | printk(KERN_WARNING "AWE32 Error: invalid patch info length\n"); | ||
2980 | return -EINVAL; | ||
2981 | } | ||
2982 | if (copy_from_user(&map, addr + AWE_PATCH_INFO_SIZE, sizeof(map))) | ||
2983 | return -EFAULT; | ||
2984 | |||
2985 | /* check if the identical mapping already exists */ | ||
2986 | p = awe_search_instr(map.map_bank, map.map_instr, map.map_key); | ||
2987 | for (; p; p = p->next_instr) { | ||
2988 | if (p->type == V_ST_MAPPED && | ||
2989 | p->v.start == map.src_instr && | ||
2990 | p->v.end == map.src_bank && | ||
2991 | p->v.fixkey == map.src_key) | ||
2992 | return 0; /* already present! */ | ||
2993 | } | ||
2994 | |||
2995 | if ((sf = check_patch_opened(AWE_PAT_TYPE_MAP, NULL)) == NULL) | ||
2996 | return -ENOMEM; | ||
2997 | |||
2998 | if ((rec = alloc_new_info()) == NULL) | ||
2999 | return -ENOMEM; | ||
3000 | |||
3001 | rec->bank = map.map_bank; | ||
3002 | rec->instr = map.map_instr; | ||
3003 | rec->type = V_ST_MAPPED; | ||
3004 | rec->disabled = FALSE; | ||
3005 | awe_init_voice_info(&rec->v); | ||
3006 | if (map.map_key >= 0) { | ||
3007 | rec->v.low = map.map_key; | ||
3008 | rec->v.high = map.map_key; | ||
3009 | } | ||
3010 | rec->v.start = map.src_instr; | ||
3011 | rec->v.end = map.src_bank; | ||
3012 | rec->v.fixkey = map.src_key; | ||
3013 | add_sf_info(sf, rec); | ||
3014 | add_info_list(rec); | ||
3015 | |||
3016 | return 0; | ||
3017 | } | ||
3018 | |||
3019 | #if 0 | ||
3020 | /* probe preset in the current list -- nothing to be loaded */ | ||
3021 | static int | ||
3022 | awe_probe_info(awe_patch_info *patch, const char __user *addr, int count) | ||
3023 | { | ||
3024 | #ifdef AWE_ALLOW_SAMPLE_SHARING | ||
3025 | awe_voice_map map; | ||
3026 | awe_voice_list *p; | ||
3027 | |||
3028 | if (! patch_opened) | ||
3029 | return -EINVAL; | ||
3030 | |||
3031 | /* get the link info */ | ||
3032 | if (count < sizeof(map)) { | ||
3033 | printk(KERN_WARNING "AWE32 Error: invalid patch info length\n"); | ||
3034 | return -EINVAL; | ||
3035 | } | ||
3036 | if (copy_from_user(&map, addr + AWE_PATCH_INFO_SIZE, sizeof(map))) | ||
3037 | return -EFAULT; | ||
3038 | |||
3039 | /* check if the identical mapping already exists */ | ||
3040 | if (sftail == NULL) | ||
3041 | return -EINVAL; | ||
3042 | p = awe_search_instr(map.src_bank, map.src_instr, map.src_key); | ||
3043 | for (; p; p = p->next_instr) { | ||
3044 | if (p->type == V_ST_NORMAL && | ||
3045 | is_identical_holder(p->holder, sftail) && | ||
3046 | p->v.low <= map.src_key && | ||
3047 | p->v.high >= map.src_key) | ||
3048 | return 0; /* already present! */ | ||
3049 | } | ||
3050 | #endif /* allow sharing */ | ||
3051 | return -EINVAL; | ||
3052 | } | ||
3053 | #endif | ||
3054 | |||
3055 | /* probe sample in the current list -- nothing to be loaded */ | ||
3056 | static int | ||
3057 | awe_probe_data(awe_patch_info *patch, const char __user *addr, int count) | ||
3058 | { | ||
3059 | #ifdef AWE_ALLOW_SAMPLE_SHARING | ||
3060 | if (! patch_opened) | ||
3061 | return -EINVAL; | ||
3062 | |||
3063 | /* search the specified sample by optarg */ | ||
3064 | if (search_sample_index(sftail, patch->optarg) != NULL) | ||
3065 | return 0; | ||
3066 | #endif /* allow sharing */ | ||
3067 | return -EINVAL; | ||
3068 | } | ||
3069 | |||
3070 | |||
3071 | /* remove the present instrument layers */ | ||
3072 | static int | ||
3073 | remove_info(sf_list *sf, int bank, int instr) | ||
3074 | { | ||
3075 | awe_voice_list *prev, *next, *p; | ||
3076 | int removed = 0; | ||
3077 | |||
3078 | prev = NULL; | ||
3079 | for (p = sf->infos; p; p = next) { | ||
3080 | next = p->next; | ||
3081 | if (p->type == V_ST_NORMAL && | ||
3082 | p->bank == bank && p->instr == instr) { | ||
3083 | /* remove this layer */ | ||
3084 | if (prev) | ||
3085 | prev->next = next; | ||
3086 | else | ||
3087 | sf->infos = next; | ||
3088 | if (p == sf->last_infos) | ||
3089 | sf->last_infos = prev; | ||
3090 | sf->num_info--; | ||
3091 | removed++; | ||
3092 | kfree(p); | ||
3093 | } else | ||
3094 | prev = p; | ||
3095 | } | ||
3096 | if (removed) | ||
3097 | rebuild_preset_list(); | ||
3098 | return removed; | ||
3099 | } | ||
3100 | |||
3101 | /* load voice information data */ | ||
3102 | static int | ||
3103 | awe_load_info(awe_patch_info *patch, const char __user *addr, int count) | ||
3104 | { | ||
3105 | int offset; | ||
3106 | awe_voice_rec_hdr hdr; | ||
3107 | int i; | ||
3108 | int total_size; | ||
3109 | sf_list *sf; | ||
3110 | awe_voice_list *rec; | ||
3111 | |||
3112 | if (count < AWE_VOICE_REC_SIZE) { | ||
3113 | printk(KERN_WARNING "AWE32 Error: invalid patch info length\n"); | ||
3114 | return -EINVAL; | ||
3115 | } | ||
3116 | |||
3117 | offset = AWE_PATCH_INFO_SIZE; | ||
3118 | if (copy_from_user((char*)&hdr, addr + offset, AWE_VOICE_REC_SIZE)) | ||
3119 | return -EFAULT; | ||
3120 | offset += AWE_VOICE_REC_SIZE; | ||
3121 | |||
3122 | if (hdr.nvoices <= 0 || hdr.nvoices >= 100) { | ||
3123 | printk(KERN_WARNING "AWE32 Error: Invalid voice number %d\n", hdr.nvoices); | ||
3124 | return -EINVAL; | ||
3125 | } | ||
3126 | total_size = AWE_VOICE_REC_SIZE + AWE_VOICE_INFO_SIZE * hdr.nvoices; | ||
3127 | if (count < total_size) { | ||
3128 | printk(KERN_WARNING "AWE32 Error: patch length(%d) is smaller than nvoices(%d)\n", | ||
3129 | count, hdr.nvoices); | ||
3130 | return -EINVAL; | ||
3131 | } | ||
3132 | |||
3133 | if ((sf = check_patch_opened(AWE_PAT_TYPE_MISC, NULL)) == NULL) | ||
3134 | return -ENOMEM; | ||
3135 | |||
3136 | switch (hdr.write_mode) { | ||
3137 | case AWE_WR_EXCLUSIVE: | ||
3138 | /* exclusive mode - if the instrument already exists, | ||
3139 | return error */ | ||
3140 | for (rec = sf->infos; rec; rec = rec->next) { | ||
3141 | if (rec->type == V_ST_NORMAL && | ||
3142 | rec->bank == hdr.bank && | ||
3143 | rec->instr == hdr.instr) | ||
3144 | return -EINVAL; | ||
3145 | } | ||
3146 | break; | ||
3147 | case AWE_WR_REPLACE: | ||
3148 | /* replace mode - remove the instrument if it already exists */ | ||
3149 | remove_info(sf, hdr.bank, hdr.instr); | ||
3150 | break; | ||
3151 | } | ||
3152 | |||
3153 | /* append new layers */ | ||
3154 | for (i = 0; i < hdr.nvoices; i++) { | ||
3155 | rec = alloc_new_info(); | ||
3156 | if (rec == NULL) | ||
3157 | return -ENOMEM; | ||
3158 | |||
3159 | rec->bank = hdr.bank; | ||
3160 | rec->instr = hdr.instr; | ||
3161 | rec->type = V_ST_NORMAL; | ||
3162 | rec->disabled = FALSE; | ||
3163 | |||
3164 | /* copy awe_voice_info parameters */ | ||
3165 | if (copy_from_user(&rec->v, addr + offset, AWE_VOICE_INFO_SIZE)) { | ||
3166 | kfree(rec); | ||
3167 | return -EFAULT; | ||
3168 | } | ||
3169 | offset += AWE_VOICE_INFO_SIZE; | ||
3170 | #ifdef AWE_ALLOW_SAMPLE_SHARING | ||
3171 | if (sf && sf->shared) { | ||
3172 | if (info_duplicated(sf, rec)) { | ||
3173 | kfree(rec); | ||
3174 | continue; | ||
3175 | } | ||
3176 | } | ||
3177 | #endif /* allow sharing */ | ||
3178 | if (rec->v.mode & AWE_MODE_INIT_PARM) | ||
3179 | awe_init_voice_parm(&rec->v.parm); | ||
3180 | add_sf_info(sf, rec); | ||
3181 | awe_set_sample(rec); | ||
3182 | add_info_list(rec); | ||
3183 | } | ||
3184 | |||
3185 | return 0; | ||
3186 | } | ||
3187 | |||
3188 | |||
3189 | /* remove instrument layers */ | ||
3190 | static int | ||
3191 | awe_remove_info(awe_patch_info *patch, const char __user *addr, int count) | ||
3192 | { | ||
3193 | unsigned char bank, instr; | ||
3194 | sf_list *sf; | ||
3195 | |||
3196 | if (! patch_opened || (sf = sftail) == NULL) { | ||
3197 | printk(KERN_WARNING "AWE32: remove_info: patch not opened\n"); | ||
3198 | return -EINVAL; | ||
3199 | } | ||
3200 | |||
3201 | bank = ((unsigned short)patch->optarg >> 8) & 0xff; | ||
3202 | instr = (unsigned short)patch->optarg & 0xff; | ||
3203 | if (! remove_info(sf, bank, instr)) | ||
3204 | return -EINVAL; | ||
3205 | return 0; | ||
3206 | } | ||
3207 | |||
3208 | |||
3209 | /* load wave sample data */ | ||
3210 | static int | ||
3211 | awe_load_data(awe_patch_info *patch, const char __user *addr, int count) | ||
3212 | { | ||
3213 | int offset, size; | ||
3214 | int rc; | ||
3215 | awe_sample_info tmprec; | ||
3216 | awe_sample_list *rec; | ||
3217 | sf_list *sf; | ||
3218 | |||
3219 | if ((sf = check_patch_opened(AWE_PAT_TYPE_MISC, NULL)) == NULL) | ||
3220 | return -ENOMEM; | ||
3221 | |||
3222 | size = (count - AWE_SAMPLE_INFO_SIZE) / 2; | ||
3223 | offset = AWE_PATCH_INFO_SIZE; | ||
3224 | if (copy_from_user(&tmprec, addr + offset, AWE_SAMPLE_INFO_SIZE)) | ||
3225 | return -EFAULT; | ||
3226 | offset += AWE_SAMPLE_INFO_SIZE; | ||
3227 | if (size != tmprec.size) { | ||
3228 | printk(KERN_WARNING "AWE32: load: sample size differed (%d != %d)\n", | ||
3229 | tmprec.size, size); | ||
3230 | return -EINVAL; | ||
3231 | } | ||
3232 | |||
3233 | if (search_sample_index(sf, tmprec.sample) != NULL) { | ||
3234 | #ifdef AWE_ALLOW_SAMPLE_SHARING | ||
3235 | /* if shared sample, skip this data */ | ||
3236 | if (sf->type & AWE_PAT_SHARED) | ||
3237 | return 0; | ||
3238 | #endif /* allow sharing */ | ||
3239 | DEBUG(1,printk("AWE32: sample data %d already present\n", tmprec.sample)); | ||
3240 | return -EINVAL; | ||
3241 | } | ||
3242 | |||
3243 | if ((rec = alloc_new_sample()) == NULL) | ||
3244 | return -ENOMEM; | ||
3245 | |||
3246 | memcpy(&rec->v, &tmprec, sizeof(tmprec)); | ||
3247 | |||
3248 | if (rec->v.size > 0) { | ||
3249 | if ((rc = awe_write_wave_data(addr, offset, rec, -1)) < 0) { | ||
3250 | kfree(rec); | ||
3251 | return rc; | ||
3252 | } | ||
3253 | sf->mem_ptr += rc; | ||
3254 | } | ||
3255 | |||
3256 | add_sf_sample(sf, rec); | ||
3257 | return 0; | ||
3258 | } | ||
3259 | |||
3260 | |||
3261 | /* replace wave sample data */ | ||
3262 | static int | ||
3263 | awe_replace_data(awe_patch_info *patch, const char __user *addr, int count) | ||
3264 | { | ||
3265 | int offset; | ||
3266 | int size; | ||
3267 | int rc; | ||
3268 | int channels; | ||
3269 | awe_sample_info cursmp; | ||
3270 | int save_mem_ptr; | ||
3271 | sf_list *sf; | ||
3272 | awe_sample_list *rec; | ||
3273 | |||
3274 | if (! patch_opened || (sf = sftail) == NULL) { | ||
3275 | printk(KERN_WARNING "AWE32: replace: patch not opened\n"); | ||
3276 | return -EINVAL; | ||
3277 | } | ||
3278 | |||
3279 | size = (count - AWE_SAMPLE_INFO_SIZE) / 2; | ||
3280 | offset = AWE_PATCH_INFO_SIZE; | ||
3281 | if (copy_from_user(&cursmp, addr + offset, AWE_SAMPLE_INFO_SIZE)) | ||
3282 | return -EFAULT; | ||
3283 | offset += AWE_SAMPLE_INFO_SIZE; | ||
3284 | if (cursmp.size == 0 || size != cursmp.size) { | ||
3285 | printk(KERN_WARNING "AWE32: replace: invalid sample size (%d!=%d)\n", | ||
3286 | cursmp.size, size); | ||
3287 | return -EINVAL; | ||
3288 | } | ||
3289 | channels = patch->optarg; | ||
3290 | if (channels <= 0 || channels > AWE_NORMAL_VOICES) { | ||
3291 | printk(KERN_WARNING "AWE32: replace: invalid channels %d\n", channels); | ||
3292 | return -EINVAL; | ||
3293 | } | ||
3294 | |||
3295 | for (rec = sf->samples; rec; rec = rec->next) { | ||
3296 | if (rec->v.sample == cursmp.sample) | ||
3297 | break; | ||
3298 | } | ||
3299 | if (rec == NULL) { | ||
3300 | printk(KERN_WARNING "AWE32: replace: cannot find existing sample data %d\n", | ||
3301 | cursmp.sample); | ||
3302 | return -EINVAL; | ||
3303 | } | ||
3304 | |||
3305 | if (rec->v.size != cursmp.size) { | ||
3306 | printk(KERN_WARNING "AWE32: replace: exiting size differed (%d!=%d)\n", | ||
3307 | rec->v.size, cursmp.size); | ||
3308 | return -EINVAL; | ||
3309 | } | ||
3310 | |||
3311 | save_mem_ptr = awe_free_mem_ptr(); | ||
3312 | sftail->mem_ptr = rec->v.start - awe_mem_start; | ||
3313 | memcpy(&rec->v, &cursmp, sizeof(cursmp)); | ||
3314 | rec->v.sf_id = current_sf_id; | ||
3315 | if ((rc = awe_write_wave_data(addr, offset, rec, channels)) < 0) | ||
3316 | return rc; | ||
3317 | sftail->mem_ptr = save_mem_ptr; | ||
3318 | |||
3319 | return 0; | ||
3320 | } | ||
3321 | |||
3322 | |||
3323 | /*----------------------------------------------------------------*/ | ||
3324 | |||
3325 | static const char __user *readbuf_addr; | ||
3326 | static int readbuf_offs; | ||
3327 | static int readbuf_flags; | ||
3328 | |||
3329 | /* initialize read buffer */ | ||
3330 | static int | ||
3331 | readbuf_init(const char __user *addr, int offset, awe_sample_info *sp) | ||
3332 | { | ||
3333 | readbuf_addr = addr; | ||
3334 | readbuf_offs = offset; | ||
3335 | readbuf_flags = sp->mode_flags; | ||
3336 | return 0; | ||
3337 | } | ||
3338 | |||
3339 | /* read directly from user buffer */ | ||
3340 | static unsigned short | ||
3341 | readbuf_word(int pos) | ||
3342 | { | ||
3343 | unsigned short c; | ||
3344 | /* read from user buffer */ | ||
3345 | if (readbuf_flags & AWE_SAMPLE_8BITS) { | ||
3346 | unsigned char cc; | ||
3347 | get_user(cc, (unsigned char __user *)(readbuf_addr + readbuf_offs + pos)); | ||
3348 | c = (unsigned short)cc << 8; /* convert 8bit -> 16bit */ | ||
3349 | } else { | ||
3350 | get_user(c, (unsigned short __user *)(readbuf_addr + readbuf_offs + pos * 2)); | ||
3351 | } | ||
3352 | if (readbuf_flags & AWE_SAMPLE_UNSIGNED) | ||
3353 | c ^= 0x8000; /* unsigned -> signed */ | ||
3354 | return c; | ||
3355 | } | ||
3356 | |||
3357 | #define readbuf_word_cache readbuf_word | ||
3358 | #define readbuf_end() /**/ | ||
3359 | |||
3360 | /*----------------------------------------------------------------*/ | ||
3361 | |||
3362 | #define BLANK_LOOP_START 8 | ||
3363 | #define BLANK_LOOP_END 40 | ||
3364 | #define BLANK_LOOP_SIZE 48 | ||
3365 | |||
3366 | /* loading onto memory - return the actual written size */ | ||
3367 | static int | ||
3368 | awe_write_wave_data(const char __user *addr, int offset, awe_sample_list *list, int channels) | ||
3369 | { | ||
3370 | int i, truesize, dram_offset; | ||
3371 | awe_sample_info *sp = &list->v; | ||
3372 | int rc; | ||
3373 | |||
3374 | /* be sure loop points start < end */ | ||
3375 | if (sp->loopstart > sp->loopend) { | ||
3376 | int tmp = sp->loopstart; | ||
3377 | sp->loopstart = sp->loopend; | ||
3378 | sp->loopend = tmp; | ||
3379 | } | ||
3380 | |||
3381 | /* compute true data size to be loaded */ | ||
3382 | truesize = sp->size; | ||
3383 | if (sp->mode_flags & (AWE_SAMPLE_BIDIR_LOOP|AWE_SAMPLE_REVERSE_LOOP)) | ||
3384 | truesize += sp->loopend - sp->loopstart; | ||
3385 | if (sp->mode_flags & AWE_SAMPLE_NO_BLANK) | ||
3386 | truesize += BLANK_LOOP_SIZE; | ||
3387 | if (awe_free_mem_ptr() + truesize >= memsize/2) { | ||
3388 | DEBUG(-1,printk("AWE32 Error: Sample memory full\n")); | ||
3389 | return -ENOSPC; | ||
3390 | } | ||
3391 | |||
3392 | /* recalculate address offset */ | ||
3393 | sp->end -= sp->start; | ||
3394 | sp->loopstart -= sp->start; | ||
3395 | sp->loopend -= sp->start; | ||
3396 | |||
3397 | dram_offset = awe_free_mem_ptr() + awe_mem_start; | ||
3398 | sp->start = dram_offset; | ||
3399 | sp->end += dram_offset; | ||
3400 | sp->loopstart += dram_offset; | ||
3401 | sp->loopend += dram_offset; | ||
3402 | |||
3403 | /* set the total size (store onto obsolete checksum value) */ | ||
3404 | if (sp->size == 0) | ||
3405 | sp->checksum = 0; | ||
3406 | else | ||
3407 | sp->checksum = truesize; | ||
3408 | |||
3409 | if ((rc = awe_open_dram_for_write(dram_offset, channels)) != 0) | ||
3410 | return rc; | ||
3411 | |||
3412 | if (readbuf_init(addr, offset, sp) < 0) | ||
3413 | return -ENOSPC; | ||
3414 | |||
3415 | for (i = 0; i < sp->size; i++) { | ||
3416 | unsigned short c; | ||
3417 | c = readbuf_word(i); | ||
3418 | awe_write_dram(c); | ||
3419 | if (i == sp->loopend && | ||
3420 | (sp->mode_flags & (AWE_SAMPLE_BIDIR_LOOP|AWE_SAMPLE_REVERSE_LOOP))) { | ||
3421 | int looplen = sp->loopend - sp->loopstart; | ||
3422 | /* copy reverse loop */ | ||
3423 | int k; | ||
3424 | for (k = 1; k <= looplen; k++) { | ||
3425 | c = readbuf_word_cache(i - k); | ||
3426 | awe_write_dram(c); | ||
3427 | } | ||
3428 | if (sp->mode_flags & AWE_SAMPLE_BIDIR_LOOP) { | ||
3429 | sp->end += looplen; | ||
3430 | } else { | ||
3431 | sp->start += looplen; | ||
3432 | sp->end += looplen; | ||
3433 | } | ||
3434 | } | ||
3435 | } | ||
3436 | readbuf_end(); | ||
3437 | |||
3438 | /* if no blank loop is attached in the sample, add it */ | ||
3439 | if (sp->mode_flags & AWE_SAMPLE_NO_BLANK) { | ||
3440 | for (i = 0; i < BLANK_LOOP_SIZE; i++) | ||
3441 | awe_write_dram(0); | ||
3442 | if (sp->mode_flags & AWE_SAMPLE_SINGLESHOT) { | ||
3443 | sp->loopstart = sp->end + BLANK_LOOP_START; | ||
3444 | sp->loopend = sp->end + BLANK_LOOP_END; | ||
3445 | } | ||
3446 | } | ||
3447 | |||
3448 | awe_close_dram(); | ||
3449 | |||
3450 | /* initialize FM */ | ||
3451 | awe_init_fm(); | ||
3452 | |||
3453 | return truesize; | ||
3454 | } | ||
3455 | |||
3456 | |||
3457 | /*----------------------------------------------------------------*/ | ||
3458 | |||
3459 | #ifdef AWE_HAS_GUS_COMPATIBILITY | ||
3460 | |||
3461 | /* calculate GUS envelope time: | ||
3462 | * is this correct? i have no idea.. | ||
3463 | */ | ||
3464 | static int | ||
3465 | calc_gus_envelope_time(int rate, int start, int end) | ||
3466 | { | ||
3467 | int r, p, t; | ||
3468 | r = (3 - ((rate >> 6) & 3)) * 3; | ||
3469 | p = rate & 0x3f; | ||
3470 | t = end - start; | ||
3471 | if (t < 0) t = -t; | ||
3472 | if (13 > r) | ||
3473 | t = t << (13 - r); | ||
3474 | else | ||
3475 | t = t >> (r - 13); | ||
3476 | return (t * 10) / (p * 441); | ||
3477 | } | ||
3478 | |||
3479 | #define calc_gus_sustain(val) (0x7f - vol_table[(val)/2]) | ||
3480 | #define calc_gus_attenuation(val) vol_table[(val)/2] | ||
3481 | |||
3482 | /* load GUS patch */ | ||
3483 | static int | ||
3484 | awe_load_guspatch(const char __user *addr, int offs, int size, int pmgr_flag) | ||
3485 | { | ||
3486 | struct patch_info patch; | ||
3487 | awe_voice_info *rec; | ||
3488 | awe_sample_info *smp; | ||
3489 | awe_voice_list *vrec; | ||
3490 | awe_sample_list *smprec; | ||
3491 | int sizeof_patch; | ||
3492 | int note, rc; | ||
3493 | sf_list *sf; | ||
3494 | |||
3495 | sizeof_patch = (int)((long)&patch.data[0] - (long)&patch); /* header size */ | ||
3496 | if (size < sizeof_patch) { | ||
3497 | printk(KERN_WARNING "AWE32 Error: Patch header too short\n"); | ||
3498 | return -EINVAL; | ||
3499 | } | ||
3500 | if (copy_from_user(((char*)&patch) + offs, addr + offs, sizeof_patch - offs)) | ||
3501 | return -EFAULT; | ||
3502 | size -= sizeof_patch; | ||
3503 | if (size < patch.len) { | ||
3504 | printk(KERN_WARNING "AWE32 Error: Patch record too short (%d<%d)\n", | ||
3505 | size, patch.len); | ||
3506 | return -EINVAL; | ||
3507 | } | ||
3508 | if ((sf = check_patch_opened(AWE_PAT_TYPE_GUS, NULL)) == NULL) | ||
3509 | return -ENOMEM; | ||
3510 | if ((smprec = alloc_new_sample()) == NULL) | ||
3511 | return -ENOMEM; | ||
3512 | if ((vrec = alloc_new_info()) == NULL) { | ||
3513 | kfree(smprec); | ||
3514 | return -ENOMEM; | ||
3515 | } | ||
3516 | |||
3517 | smp = &smprec->v; | ||
3518 | smp->sample = sf->num_sample; | ||
3519 | smp->start = 0; | ||
3520 | smp->end = patch.len; | ||
3521 | smp->loopstart = patch.loop_start; | ||
3522 | smp->loopend = patch.loop_end; | ||
3523 | smp->size = patch.len; | ||
3524 | |||
3525 | /* set up mode flags */ | ||
3526 | smp->mode_flags = 0; | ||
3527 | if (!(patch.mode & WAVE_16_BITS)) | ||
3528 | smp->mode_flags |= AWE_SAMPLE_8BITS; | ||
3529 | if (patch.mode & WAVE_UNSIGNED) | ||
3530 | smp->mode_flags |= AWE_SAMPLE_UNSIGNED; | ||
3531 | smp->mode_flags |= AWE_SAMPLE_NO_BLANK; | ||
3532 | if (!(patch.mode & (WAVE_LOOPING|WAVE_BIDIR_LOOP|WAVE_LOOP_BACK))) | ||
3533 | smp->mode_flags |= AWE_SAMPLE_SINGLESHOT; | ||
3534 | if (patch.mode & WAVE_BIDIR_LOOP) | ||
3535 | smp->mode_flags |= AWE_SAMPLE_BIDIR_LOOP; | ||
3536 | if (patch.mode & WAVE_LOOP_BACK) | ||
3537 | smp->mode_flags |= AWE_SAMPLE_REVERSE_LOOP; | ||
3538 | |||
3539 | DEBUG(0,printk("AWE32: [sample %d mode %x]\n", patch.instr_no, smp->mode_flags)); | ||
3540 | if (patch.mode & WAVE_16_BITS) { | ||
3541 | /* convert to word offsets */ | ||
3542 | smp->size /= 2; | ||
3543 | smp->end /= 2; | ||
3544 | smp->loopstart /= 2; | ||
3545 | smp->loopend /= 2; | ||
3546 | } | ||
3547 | smp->checksum_flag = 0; | ||
3548 | smp->checksum = 0; | ||
3549 | |||
3550 | if ((rc = awe_write_wave_data(addr, sizeof_patch, smprec, -1)) < 0) | ||
3551 | return rc; | ||
3552 | sf->mem_ptr += rc; | ||
3553 | add_sf_sample(sf, smprec); | ||
3554 | |||
3555 | /* set up voice info */ | ||
3556 | rec = &vrec->v; | ||
3557 | awe_init_voice_info(rec); | ||
3558 | rec->sample = sf->num_info; /* the last sample */ | ||
3559 | rec->rate_offset = calc_rate_offset(patch.base_freq); | ||
3560 | note = freq_to_note(patch.base_note); | ||
3561 | rec->root = note / 100; | ||
3562 | rec->tune = -(note % 100); | ||
3563 | rec->low = freq_to_note(patch.low_note) / 100; | ||
3564 | rec->high = freq_to_note(patch.high_note) / 100; | ||
3565 | DEBUG(1,printk("AWE32: [gus base offset=%d, note=%d, range=%d-%d(%d-%d)]\n", | ||
3566 | rec->rate_offset, note, | ||
3567 | rec->low, rec->high, | ||
3568 | patch.low_note, patch.high_note)); | ||
3569 | /* panning position; -128 - 127 => 0-127 */ | ||
3570 | rec->pan = (patch.panning + 128) / 2; | ||
3571 | |||
3572 | /* detuning is ignored */ | ||
3573 | /* 6points volume envelope */ | ||
3574 | if (patch.mode & WAVE_ENVELOPES) { | ||
3575 | int attack, hold, decay, release; | ||
3576 | attack = calc_gus_envelope_time | ||
3577 | (patch.env_rate[0], 0, patch.env_offset[0]); | ||
3578 | hold = calc_gus_envelope_time | ||
3579 | (patch.env_rate[1], patch.env_offset[0], | ||
3580 | patch.env_offset[1]); | ||
3581 | decay = calc_gus_envelope_time | ||
3582 | (patch.env_rate[2], patch.env_offset[1], | ||
3583 | patch.env_offset[2]); | ||
3584 | release = calc_gus_envelope_time | ||
3585 | (patch.env_rate[3], patch.env_offset[1], | ||
3586 | patch.env_offset[4]); | ||
3587 | release += calc_gus_envelope_time | ||
3588 | (patch.env_rate[4], patch.env_offset[3], | ||
3589 | patch.env_offset[4]); | ||
3590 | release += calc_gus_envelope_time | ||
3591 | (patch.env_rate[5], patch.env_offset[4], | ||
3592 | patch.env_offset[5]); | ||
3593 | rec->parm.volatkhld = (calc_parm_hold(hold) << 8) | | ||
3594 | calc_parm_attack(attack); | ||
3595 | rec->parm.voldcysus = (calc_gus_sustain(patch.env_offset[2]) << 8) | | ||
3596 | calc_parm_decay(decay); | ||
3597 | rec->parm.volrelease = 0x8000 | calc_parm_decay(release); | ||
3598 | DEBUG(2,printk("AWE32: [gusenv atk=%d, hld=%d, dcy=%d, rel=%d]\n", attack, hold, decay, release)); | ||
3599 | rec->attenuation = calc_gus_attenuation(patch.env_offset[0]); | ||
3600 | } | ||
3601 | |||
3602 | /* tremolo effect */ | ||
3603 | if (patch.mode & WAVE_TREMOLO) { | ||
3604 | int rate = (patch.tremolo_rate * 1000 / 38) / 42; | ||
3605 | rec->parm.tremfrq = ((patch.tremolo_depth / 2) << 8) | rate; | ||
3606 | DEBUG(2,printk("AWE32: [gusenv tremolo rate=%d, dep=%d, tremfrq=%x]\n", | ||
3607 | patch.tremolo_rate, patch.tremolo_depth, | ||
3608 | rec->parm.tremfrq)); | ||
3609 | } | ||
3610 | /* vibrato effect */ | ||
3611 | if (patch.mode & WAVE_VIBRATO) { | ||
3612 | int rate = (patch.vibrato_rate * 1000 / 38) / 42; | ||
3613 | rec->parm.fm2frq2 = ((patch.vibrato_depth / 6) << 8) | rate; | ||
3614 | DEBUG(2,printk("AWE32: [gusenv vibrato rate=%d, dep=%d, tremfrq=%x]\n", | ||
3615 | patch.tremolo_rate, patch.tremolo_depth, | ||
3616 | rec->parm.tremfrq)); | ||
3617 | } | ||
3618 | |||
3619 | /* scale_freq, scale_factor, volume, and fractions not implemented */ | ||
3620 | |||
3621 | /* append to the tail of the list */ | ||
3622 | vrec->bank = ctrls[AWE_MD_GUS_BANK]; | ||
3623 | vrec->instr = patch.instr_no; | ||
3624 | vrec->disabled = FALSE; | ||
3625 | vrec->type = V_ST_NORMAL; | ||
3626 | |||
3627 | add_sf_info(sf, vrec); | ||
3628 | add_info_list(vrec); | ||
3629 | |||
3630 | /* set the voice index */ | ||
3631 | awe_set_sample(vrec); | ||
3632 | |||
3633 | return 0; | ||
3634 | } | ||
3635 | |||
3636 | #endif /* AWE_HAS_GUS_COMPATIBILITY */ | ||
3637 | |||
3638 | /* | ||
3639 | * sample and voice list handlers | ||
3640 | */ | ||
3641 | |||
3642 | /* append this to the current sf list */ | ||
3643 | static void add_sf_info(sf_list *sf, awe_voice_list *rec) | ||
3644 | { | ||
3645 | if (sf == NULL) | ||
3646 | return; | ||
3647 | rec->holder = sf; | ||
3648 | rec->v.sf_id = sf->sf_id; | ||
3649 | if (sf->last_infos) | ||
3650 | sf->last_infos->next = rec; | ||
3651 | else | ||
3652 | sf->infos = rec; | ||
3653 | sf->last_infos = rec; | ||
3654 | rec->next = NULL; | ||
3655 | sf->num_info++; | ||
3656 | } | ||
3657 | |||
3658 | /* prepend this sample to sf list */ | ||
3659 | static void add_sf_sample(sf_list *sf, awe_sample_list *rec) | ||
3660 | { | ||
3661 | if (sf == NULL) | ||
3662 | return; | ||
3663 | rec->holder = sf; | ||
3664 | rec->v.sf_id = sf->sf_id; | ||
3665 | if (sf->last_samples) | ||
3666 | sf->last_samples->next = rec; | ||
3667 | else | ||
3668 | sf->samples = rec; | ||
3669 | sf->last_samples = rec; | ||
3670 | rec->next = NULL; | ||
3671 | sf->num_sample++; | ||
3672 | } | ||
3673 | |||
3674 | /* purge the old records which don't belong with the same file id */ | ||
3675 | static void purge_old_list(awe_voice_list *rec, awe_voice_list *next) | ||
3676 | { | ||
3677 | rec->next_instr = next; | ||
3678 | if (rec->bank == AWE_DRUM_BANK) { | ||
3679 | /* remove samples with the same note range */ | ||
3680 | awe_voice_list *cur, *prev = rec; | ||
3681 | int low = rec->v.low; | ||
3682 | int high = rec->v.high; | ||
3683 | for (cur = next; cur; cur = cur->next_instr) { | ||
3684 | if (cur->v.low == low && | ||
3685 | cur->v.high == high && | ||
3686 | ! is_identical_holder(cur->holder, rec->holder)) | ||
3687 | prev->next_instr = cur->next_instr; | ||
3688 | else | ||
3689 | prev = cur; | ||
3690 | } | ||
3691 | } else { | ||
3692 | if (! is_identical_holder(next->holder, rec->holder)) | ||
3693 | /* remove all samples */ | ||
3694 | rec->next_instr = NULL; | ||
3695 | } | ||
3696 | } | ||
3697 | |||
3698 | /* prepend to top of the preset table */ | ||
3699 | static void add_info_list(awe_voice_list *rec) | ||
3700 | { | ||
3701 | awe_voice_list *prev, *cur; | ||
3702 | int key; | ||
3703 | |||
3704 | if (rec->disabled) | ||
3705 | return; | ||
3706 | |||
3707 | key = awe_search_key(rec->bank, rec->instr, rec->v.low); | ||
3708 | prev = NULL; | ||
3709 | for (cur = preset_table[key]; cur; cur = cur->next_bank) { | ||
3710 | /* search the first record with the same bank number */ | ||
3711 | if (cur->instr == rec->instr && cur->bank == rec->bank) { | ||
3712 | /* replace the list with the new record */ | ||
3713 | rec->next_bank = cur->next_bank; | ||
3714 | if (prev) | ||
3715 | prev->next_bank = rec; | ||
3716 | else | ||
3717 | preset_table[key] = rec; | ||
3718 | purge_old_list(rec, cur); | ||
3719 | return; | ||
3720 | } | ||
3721 | prev = cur; | ||
3722 | } | ||
3723 | |||
3724 | /* this is the first bank record.. just add this */ | ||
3725 | rec->next_instr = NULL; | ||
3726 | rec->next_bank = preset_table[key]; | ||
3727 | preset_table[key] = rec; | ||
3728 | } | ||
3729 | |||
3730 | /* remove samples later than the specified sf_id */ | ||
3731 | static void | ||
3732 | awe_remove_samples(int sf_id) | ||
3733 | { | ||
3734 | sf_list *p, *prev; | ||
3735 | |||
3736 | if (sf_id <= 0) { | ||
3737 | awe_reset_samples(); | ||
3738 | return; | ||
3739 | } | ||
3740 | /* already removed? */ | ||
3741 | if (current_sf_id <= sf_id) | ||
3742 | return; | ||
3743 | |||
3744 | for (p = sftail; p; p = prev) { | ||
3745 | if (p->sf_id <= sf_id) | ||
3746 | break; | ||
3747 | prev = p->prev; | ||
3748 | awe_free_sf(p); | ||
3749 | } | ||
3750 | sftail = p; | ||
3751 | if (sftail) { | ||
3752 | sf_id = sftail->sf_id; | ||
3753 | sftail->next = NULL; | ||
3754 | } else { | ||
3755 | sf_id = 0; | ||
3756 | sfhead = NULL; | ||
3757 | } | ||
3758 | current_sf_id = sf_id; | ||
3759 | if (locked_sf_id > sf_id) | ||
3760 | locked_sf_id = sf_id; | ||
3761 | |||
3762 | rebuild_preset_list(); | ||
3763 | } | ||
3764 | |||
3765 | /* rebuild preset search list */ | ||
3766 | static void rebuild_preset_list(void) | ||
3767 | { | ||
3768 | sf_list *p; | ||
3769 | awe_voice_list *rec; | ||
3770 | |||
3771 | memset(preset_table, 0, sizeof(preset_table)); | ||
3772 | |||
3773 | for (p = sfhead; p; p = p->next) { | ||
3774 | for (rec = p->infos; rec; rec = rec->next) | ||
3775 | add_info_list(rec); | ||
3776 | } | ||
3777 | } | ||
3778 | |||
3779 | /* compare the given sf_id pair */ | ||
3780 | static int is_identical_holder(sf_list *sf1, sf_list *sf2) | ||
3781 | { | ||
3782 | if (sf1 == NULL || sf2 == NULL) | ||
3783 | return FALSE; | ||
3784 | if (sf1 == sf2) | ||
3785 | return TRUE; | ||
3786 | #ifdef AWE_ALLOW_SAMPLE_SHARING | ||
3787 | { | ||
3788 | /* compare with the sharing id */ | ||
3789 | sf_list *p; | ||
3790 | int counter = 0; | ||
3791 | if (sf1->sf_id < sf2->sf_id) { /* make sure id1 > id2 */ | ||
3792 | sf_list *tmp; tmp = sf1; sf1 = sf2; sf2 = tmp; | ||
3793 | } | ||
3794 | for (p = sf1->shared; p; p = p->shared) { | ||
3795 | if (counter++ > current_sf_id) | ||
3796 | break; /* strange sharing loop.. quit */ | ||
3797 | if (p == sf2) | ||
3798 | return TRUE; | ||
3799 | } | ||
3800 | } | ||
3801 | #endif /* allow sharing */ | ||
3802 | return FALSE; | ||
3803 | } | ||
3804 | |||
3805 | /* search the sample index matching with the given sample id */ | ||
3806 | static awe_sample_list * | ||
3807 | search_sample_index(sf_list *sf, int sample) | ||
3808 | { | ||
3809 | awe_sample_list *p; | ||
3810 | #ifdef AWE_ALLOW_SAMPLE_SHARING | ||
3811 | int counter = 0; | ||
3812 | while (sf) { | ||
3813 | for (p = sf->samples; p; p = p->next) { | ||
3814 | if (p->v.sample == sample) | ||
3815 | return p; | ||
3816 | } | ||
3817 | sf = sf->shared; | ||
3818 | if (counter++ > current_sf_id) | ||
3819 | break; /* strange sharing loop.. quit */ | ||
3820 | } | ||
3821 | #else | ||
3822 | if (sf) { | ||
3823 | for (p = sf->samples; p; p = p->next) { | ||
3824 | if (p->v.sample == sample) | ||
3825 | return p; | ||
3826 | } | ||
3827 | } | ||
3828 | #endif | ||
3829 | return NULL; | ||
3830 | } | ||
3831 | |||
3832 | /* search the specified sample */ | ||
3833 | /* non-zero = found */ | ||
3834 | static short | ||
3835 | awe_set_sample(awe_voice_list *rec) | ||
3836 | { | ||
3837 | awe_sample_list *smp; | ||
3838 | awe_voice_info *vp = &rec->v; | ||
3839 | |||
3840 | vp->index = 0; | ||
3841 | if ((smp = search_sample_index(rec->holder, vp->sample)) == NULL) | ||
3842 | return 0; | ||
3843 | |||
3844 | /* set the actual sample offsets */ | ||
3845 | vp->start += smp->v.start; | ||
3846 | vp->end += smp->v.end; | ||
3847 | vp->loopstart += smp->v.loopstart; | ||
3848 | vp->loopend += smp->v.loopend; | ||
3849 | /* copy mode flags */ | ||
3850 | vp->mode = smp->v.mode_flags; | ||
3851 | /* set flag */ | ||
3852 | vp->index = 1; | ||
3853 | |||
3854 | return 1; | ||
3855 | } | ||
3856 | |||
3857 | |||
3858 | /* | ||
3859 | * voice allocation | ||
3860 | */ | ||
3861 | |||
3862 | /* look for all voices associated with the specified note & velocity */ | ||
3863 | static int | ||
3864 | awe_search_multi_voices(awe_voice_list *rec, int note, int velocity, | ||
3865 | awe_voice_info **vlist) | ||
3866 | { | ||
3867 | int nvoices; | ||
3868 | |||
3869 | nvoices = 0; | ||
3870 | for (; rec; rec = rec->next_instr) { | ||
3871 | if (note >= rec->v.low && | ||
3872 | note <= rec->v.high && | ||
3873 | velocity >= rec->v.vellow && | ||
3874 | velocity <= rec->v.velhigh) { | ||
3875 | if (rec->type == V_ST_MAPPED) { | ||
3876 | /* mapper */ | ||
3877 | vlist[0] = &rec->v; | ||
3878 | return -1; | ||
3879 | } | ||
3880 | vlist[nvoices++] = &rec->v; | ||
3881 | if (nvoices >= AWE_MAX_VOICES) | ||
3882 | break; | ||
3883 | } | ||
3884 | } | ||
3885 | return nvoices; | ||
3886 | } | ||
3887 | |||
3888 | /* store the voice list from the specified note and velocity. | ||
3889 | if the preset is mapped, seek for the destination preset, and rewrite | ||
3890 | the note number if necessary. | ||
3891 | */ | ||
3892 | static int | ||
3893 | really_alloc_voices(int bank, int instr, int *note, int velocity, awe_voice_info **vlist) | ||
3894 | { | ||
3895 | int nvoices; | ||
3896 | awe_voice_list *vrec; | ||
3897 | int level = 0; | ||
3898 | |||
3899 | for (;;) { | ||
3900 | vrec = awe_search_instr(bank, instr, *note); | ||
3901 | nvoices = awe_search_multi_voices(vrec, *note, velocity, vlist); | ||
3902 | if (nvoices == 0) { | ||
3903 | if (bank == AWE_DRUM_BANK) | ||
3904 | /* search default drumset */ | ||
3905 | vrec = awe_search_instr(bank, ctrls[AWE_MD_DEF_DRUM], *note); | ||
3906 | else | ||
3907 | /* search default preset */ | ||
3908 | vrec = awe_search_instr(ctrls[AWE_MD_DEF_BANK], instr, *note); | ||
3909 | nvoices = awe_search_multi_voices(vrec, *note, velocity, vlist); | ||
3910 | } | ||
3911 | if (nvoices == 0) { | ||
3912 | if (bank == AWE_DRUM_BANK && ctrls[AWE_MD_DEF_DRUM] != 0) | ||
3913 | /* search default drumset */ | ||
3914 | vrec = awe_search_instr(bank, 0, *note); | ||
3915 | else if (bank != AWE_DRUM_BANK && ctrls[AWE_MD_DEF_BANK] != 0) | ||
3916 | /* search default preset */ | ||
3917 | vrec = awe_search_instr(0, instr, *note); | ||
3918 | nvoices = awe_search_multi_voices(vrec, *note, velocity, vlist); | ||
3919 | } | ||
3920 | if (nvoices < 0) { /* mapping */ | ||
3921 | int key = vlist[0]->fixkey; | ||
3922 | instr = vlist[0]->start; | ||
3923 | bank = vlist[0]->end; | ||
3924 | if (level++ > 5) { | ||
3925 | printk(KERN_ERR "AWE32: too deep mapping level\n"); | ||
3926 | return 0; | ||
3927 | } | ||
3928 | if (key >= 0) | ||
3929 | *note = key; | ||
3930 | } else | ||
3931 | break; | ||
3932 | } | ||
3933 | |||
3934 | return nvoices; | ||
3935 | } | ||
3936 | |||
3937 | /* allocate voices corresponding note and velocity; supports multiple insts. */ | ||
3938 | static void | ||
3939 | awe_alloc_multi_voices(int ch, int note, int velocity, int key) | ||
3940 | { | ||
3941 | int i, v, nvoices, bank; | ||
3942 | awe_voice_info *vlist[AWE_MAX_VOICES]; | ||
3943 | |||
3944 | if (MULTI_LAYER_MODE() && IS_DRUM_CHANNEL(ch)) | ||
3945 | bank = AWE_DRUM_BANK; /* always search drumset */ | ||
3946 | else | ||
3947 | bank = channels[ch].bank; | ||
3948 | |||
3949 | /* check the possible voices; note may be changeable if mapped */ | ||
3950 | nvoices = really_alloc_voices(bank, channels[ch].instr, | ||
3951 | ¬e, velocity, vlist); | ||
3952 | |||
3953 | /* set the voices */ | ||
3954 | current_alloc_time++; | ||
3955 | for (i = 0; i < nvoices; i++) { | ||
3956 | v = awe_clear_voice(); | ||
3957 | voices[v].key = key; | ||
3958 | voices[v].ch = ch; | ||
3959 | voices[v].note = note; | ||
3960 | voices[v].velocity = velocity; | ||
3961 | voices[v].time = current_alloc_time; | ||
3962 | voices[v].cinfo = &channels[ch]; | ||
3963 | voices[v].sample = vlist[i]; | ||
3964 | voices[v].state = AWE_ST_MARK; | ||
3965 | voices[v].layer = nvoices - i - 1; /* in reverse order */ | ||
3966 | } | ||
3967 | |||
3968 | /* clear the mark in allocated voices */ | ||
3969 | for (i = 0; i < awe_max_voices; i++) { | ||
3970 | if (voices[i].state == AWE_ST_MARK) | ||
3971 | voices[i].state = AWE_ST_OFF; | ||
3972 | |||
3973 | } | ||
3974 | } | ||
3975 | |||
3976 | |||
3977 | /* search an empty voice. | ||
3978 | if no empty voice is found, at least terminate a voice | ||
3979 | */ | ||
3980 | static int | ||
3981 | awe_clear_voice(void) | ||
3982 | { | ||
3983 | enum { | ||
3984 | OFF=0, RELEASED, SUSTAINED, PLAYING, END | ||
3985 | }; | ||
3986 | struct voice_candidate_t { | ||
3987 | int best; | ||
3988 | int time; | ||
3989 | int vtarget; | ||
3990 | } candidate[END]; | ||
3991 | int i, type, vtarget; | ||
3992 | |||
3993 | vtarget = 0xffff; | ||
3994 | for (type = OFF; type < END; type++) { | ||
3995 | candidate[type].best = -1; | ||
3996 | candidate[type].time = current_alloc_time + 1; | ||
3997 | candidate[type].vtarget = vtarget; | ||
3998 | } | ||
3999 | |||
4000 | for (i = 0; i < awe_max_voices; i++) { | ||
4001 | if (voices[i].state & AWE_ST_OFF) | ||
4002 | type = OFF; | ||
4003 | else if (voices[i].state & AWE_ST_RELEASED) | ||
4004 | type = RELEASED; | ||
4005 | else if (voices[i].state & AWE_ST_SUSTAINED) | ||
4006 | type = SUSTAINED; | ||
4007 | else if (voices[i].state & ~AWE_ST_MARK) | ||
4008 | type = PLAYING; | ||
4009 | else | ||
4010 | continue; | ||
4011 | #ifdef AWE_CHECK_VTARGET | ||
4012 | /* get current volume */ | ||
4013 | vtarget = (awe_peek_dw(AWE_VTFT(i)) >> 16) & 0xffff; | ||
4014 | #endif | ||
4015 | if (candidate[type].best < 0 || | ||
4016 | vtarget < candidate[type].vtarget || | ||
4017 | (vtarget == candidate[type].vtarget && | ||
4018 | voices[i].time < candidate[type].time)) { | ||
4019 | candidate[type].best = i; | ||
4020 | candidate[type].time = voices[i].time; | ||
4021 | candidate[type].vtarget = vtarget; | ||
4022 | } | ||
4023 | } | ||
4024 | |||
4025 | for (type = OFF; type < END; type++) { | ||
4026 | if ((i = candidate[type].best) >= 0) { | ||
4027 | if (voices[i].state != AWE_ST_OFF) | ||
4028 | awe_terminate(i); | ||
4029 | awe_voice_init(i, TRUE); | ||
4030 | return i; | ||
4031 | } | ||
4032 | } | ||
4033 | return 0; | ||
4034 | } | ||
4035 | |||
4036 | |||
4037 | /* search sample for the specified note & velocity and set it on the voice; | ||
4038 | * note that voice is the voice index (not channel index) | ||
4039 | */ | ||
4040 | static void | ||
4041 | awe_alloc_one_voice(int voice, int note, int velocity) | ||
4042 | { | ||
4043 | int ch, nvoices, bank; | ||
4044 | awe_voice_info *vlist[AWE_MAX_VOICES]; | ||
4045 | |||
4046 | ch = voices[voice].ch; | ||
4047 | if (MULTI_LAYER_MODE() && IS_DRUM_CHANNEL(voice)) | ||
4048 | bank = AWE_DRUM_BANK; /* always search drumset */ | ||
4049 | else | ||
4050 | bank = voices[voice].cinfo->bank; | ||
4051 | |||
4052 | nvoices = really_alloc_voices(bank, voices[voice].cinfo->instr, | ||
4053 | ¬e, velocity, vlist); | ||
4054 | if (nvoices > 0) { | ||
4055 | voices[voice].time = ++current_alloc_time; | ||
4056 | voices[voice].sample = vlist[0]; /* use the first one */ | ||
4057 | voices[voice].layer = 0; | ||
4058 | voices[voice].note = note; | ||
4059 | voices[voice].velocity = velocity; | ||
4060 | } | ||
4061 | } | ||
4062 | |||
4063 | |||
4064 | /* | ||
4065 | * sequencer2 functions | ||
4066 | */ | ||
4067 | |||
4068 | /* search an empty voice; used by sequencer2 */ | ||
4069 | static int | ||
4070 | awe_alloc(int dev, int chn, int note, struct voice_alloc_info *alloc) | ||
4071 | { | ||
4072 | playing_mode = AWE_PLAY_MULTI2; | ||
4073 | awe_info.nr_voices = AWE_MAX_CHANNELS; | ||
4074 | return awe_clear_voice(); | ||
4075 | } | ||
4076 | |||
4077 | |||
4078 | /* set up voice; used by sequencer2 */ | ||
4079 | static void | ||
4080 | awe_setup_voice(int dev, int voice, int chn) | ||
4081 | { | ||
4082 | struct channel_info *info; | ||
4083 | if (synth_devs[dev] == NULL || | ||
4084 | (info = &synth_devs[dev]->chn_info[chn]) == NULL) | ||
4085 | return; | ||
4086 | |||
4087 | if (voice < 0 || voice >= awe_max_voices) | ||
4088 | return; | ||
4089 | |||
4090 | DEBUG(2,printk("AWE32: [setup(%d) ch=%d]\n", voice, chn)); | ||
4091 | channels[chn].expression_vol = info->controllers[CTL_EXPRESSION]; | ||
4092 | channels[chn].main_vol = info->controllers[CTL_MAIN_VOLUME]; | ||
4093 | channels[chn].panning = | ||
4094 | info->controllers[CTL_PAN] * 2 - 128; /* signed 8bit */ | ||
4095 | channels[chn].bender = info->bender_value; /* zero center */ | ||
4096 | channels[chn].bank = info->controllers[CTL_BANK_SELECT]; | ||
4097 | channels[chn].sustained = info->controllers[CTL_SUSTAIN]; | ||
4098 | if (info->controllers[CTL_EXT_EFF_DEPTH]) { | ||
4099 | FX_SET(&channels[chn].fx, AWE_FX_REVERB, | ||
4100 | info->controllers[CTL_EXT_EFF_DEPTH] * 2); | ||
4101 | } | ||
4102 | if (info->controllers[CTL_CHORUS_DEPTH]) { | ||
4103 | FX_SET(&channels[chn].fx, AWE_FX_CHORUS, | ||
4104 | info->controllers[CTL_CHORUS_DEPTH] * 2); | ||
4105 | } | ||
4106 | awe_set_instr(dev, chn, info->pgm_num); | ||
4107 | } | ||
4108 | |||
4109 | |||
4110 | #ifdef CONFIG_AWE32_MIXER | ||
4111 | /* | ||
4112 | * AWE32 mixer device control | ||
4113 | */ | ||
4114 | |||
4115 | static int awe_mixer_ioctl(int dev, unsigned int cmd, void __user *arg); | ||
4116 | |||
4117 | static int my_mixerdev = -1; | ||
4118 | |||
4119 | static struct mixer_operations awe_mixer_operations = { | ||
4120 | .owner = THIS_MODULE, | ||
4121 | .id = "AWE", | ||
4122 | .name = "AWE32 Equalizer", | ||
4123 | .ioctl = awe_mixer_ioctl, | ||
4124 | }; | ||
4125 | |||
4126 | static void __init attach_mixer(void) | ||
4127 | { | ||
4128 | if ((my_mixerdev = sound_alloc_mixerdev()) >= 0) { | ||
4129 | mixer_devs[my_mixerdev] = &awe_mixer_operations; | ||
4130 | } | ||
4131 | } | ||
4132 | |||
4133 | static void unload_mixer(void) | ||
4134 | { | ||
4135 | if (my_mixerdev >= 0) | ||
4136 | sound_unload_mixerdev(my_mixerdev); | ||
4137 | } | ||
4138 | |||
4139 | static int | ||
4140 | awe_mixer_ioctl(int dev, unsigned int cmd, void __user * arg) | ||
4141 | { | ||
4142 | int i, level, value; | ||
4143 | |||
4144 | if (((cmd >> 8) & 0xff) != 'M') | ||
4145 | return -EINVAL; | ||
4146 | |||
4147 | if (get_user(level, (int __user *)arg)) | ||
4148 | return -EFAULT; | ||
4149 | level = ((level & 0xff) + (level >> 8)) / 2; | ||
4150 | DEBUG(0,printk("AWEMix: cmd=%x val=%d\n", cmd & 0xff, level)); | ||
4151 | |||
4152 | if (_SIOC_DIR(cmd) & _SIOC_WRITE) { | ||
4153 | switch (cmd & 0xff) { | ||
4154 | case SOUND_MIXER_BASS: | ||
4155 | value = level * 12 / 100; | ||
4156 | if (value >= 12) | ||
4157 | value = 11; | ||
4158 | ctrls[AWE_MD_BASS_LEVEL] = value; | ||
4159 | awe_update_equalizer(); | ||
4160 | break; | ||
4161 | case SOUND_MIXER_TREBLE: | ||
4162 | value = level * 12 / 100; | ||
4163 | if (value >= 12) | ||
4164 | value = 11; | ||
4165 | ctrls[AWE_MD_TREBLE_LEVEL] = value; | ||
4166 | awe_update_equalizer(); | ||
4167 | break; | ||
4168 | case SOUND_MIXER_VOLUME: | ||
4169 | level = level * 127 / 100; | ||
4170 | if (level >= 128) level = 127; | ||
4171 | atten_relative = FALSE; | ||
4172 | atten_offset = vol_table[level]; | ||
4173 | awe_update_volume(); | ||
4174 | break; | ||
4175 | } | ||
4176 | } | ||
4177 | switch (cmd & 0xff) { | ||
4178 | case SOUND_MIXER_BASS: | ||
4179 | level = ctrls[AWE_MD_BASS_LEVEL] * 100 / 24; | ||
4180 | level = (level << 8) | level; | ||
4181 | break; | ||
4182 | case SOUND_MIXER_TREBLE: | ||
4183 | level = ctrls[AWE_MD_TREBLE_LEVEL] * 100 / 24; | ||
4184 | level = (level << 8) | level; | ||
4185 | break; | ||
4186 | case SOUND_MIXER_VOLUME: | ||
4187 | value = atten_offset; | ||
4188 | if (atten_relative) | ||
4189 | value += ctrls[AWE_MD_ZERO_ATTEN]; | ||
4190 | for (i = 127; i > 0; i--) { | ||
4191 | if (value <= vol_table[i]) | ||
4192 | break; | ||
4193 | } | ||
4194 | level = i * 100 / 127; | ||
4195 | level = (level << 8) | level; | ||
4196 | break; | ||
4197 | case SOUND_MIXER_DEVMASK: | ||
4198 | level = SOUND_MASK_BASS|SOUND_MASK_TREBLE|SOUND_MASK_VOLUME; | ||
4199 | break; | ||
4200 | default: | ||
4201 | level = 0; | ||
4202 | break; | ||
4203 | } | ||
4204 | if (put_user(level, (int __user *)arg)) | ||
4205 | return -EFAULT; | ||
4206 | return level; | ||
4207 | } | ||
4208 | #endif /* CONFIG_AWE32_MIXER */ | ||
4209 | |||
4210 | |||
4211 | /* | ||
4212 | * initialization of Emu8000 | ||
4213 | */ | ||
4214 | |||
4215 | /* intiailize audio channels */ | ||
4216 | static void | ||
4217 | awe_init_audio(void) | ||
4218 | { | ||
4219 | int ch; | ||
4220 | |||
4221 | /* turn off envelope engines */ | ||
4222 | for (ch = 0; ch < AWE_MAX_VOICES; ch++) { | ||
4223 | awe_poke(AWE_DCYSUSV(ch), 0x80); | ||
4224 | } | ||
4225 | |||
4226 | /* reset all other parameters to zero */ | ||
4227 | for (ch = 0; ch < AWE_MAX_VOICES; ch++) { | ||
4228 | awe_poke(AWE_ENVVOL(ch), 0); | ||
4229 | awe_poke(AWE_ENVVAL(ch), 0); | ||
4230 | awe_poke(AWE_DCYSUS(ch), 0); | ||
4231 | awe_poke(AWE_ATKHLDV(ch), 0); | ||
4232 | awe_poke(AWE_LFO1VAL(ch), 0); | ||
4233 | awe_poke(AWE_ATKHLD(ch), 0); | ||
4234 | awe_poke(AWE_LFO2VAL(ch), 0); | ||
4235 | awe_poke(AWE_IP(ch), 0); | ||
4236 | awe_poke(AWE_IFATN(ch), 0); | ||
4237 | awe_poke(AWE_PEFE(ch), 0); | ||
4238 | awe_poke(AWE_FMMOD(ch), 0); | ||
4239 | awe_poke(AWE_TREMFRQ(ch), 0); | ||
4240 | awe_poke(AWE_FM2FRQ2(ch), 0); | ||
4241 | awe_poke_dw(AWE_PTRX(ch), 0); | ||
4242 | awe_poke_dw(AWE_VTFT(ch), 0); | ||
4243 | awe_poke_dw(AWE_PSST(ch), 0); | ||
4244 | awe_poke_dw(AWE_CSL(ch), 0); | ||
4245 | awe_poke_dw(AWE_CCCA(ch), 0); | ||
4246 | } | ||
4247 | |||
4248 | for (ch = 0; ch < AWE_MAX_VOICES; ch++) { | ||
4249 | awe_poke_dw(AWE_CPF(ch), 0); | ||
4250 | awe_poke_dw(AWE_CVCF(ch), 0); | ||
4251 | } | ||
4252 | } | ||
4253 | |||
4254 | |||
4255 | /* initialize DMA address */ | ||
4256 | static void | ||
4257 | awe_init_dma(void) | ||
4258 | { | ||
4259 | awe_poke_dw(AWE_SMALR, 0); | ||
4260 | awe_poke_dw(AWE_SMARR, 0); | ||
4261 | awe_poke_dw(AWE_SMALW, 0); | ||
4262 | awe_poke_dw(AWE_SMARW, 0); | ||
4263 | } | ||
4264 | |||
4265 | |||
4266 | /* initialization arrays; from ADIP */ | ||
4267 | |||
4268 | static unsigned short init1[128] = { | ||
4269 | 0x03ff, 0x0030, 0x07ff, 0x0130, 0x0bff, 0x0230, 0x0fff, 0x0330, | ||
4270 | 0x13ff, 0x0430, 0x17ff, 0x0530, 0x1bff, 0x0630, 0x1fff, 0x0730, | ||
4271 | 0x23ff, 0x0830, 0x27ff, 0x0930, 0x2bff, 0x0a30, 0x2fff, 0x0b30, | ||
4272 | 0x33ff, 0x0c30, 0x37ff, 0x0d30, 0x3bff, 0x0e30, 0x3fff, 0x0f30, | ||
4273 | |||
4274 | 0x43ff, 0x0030, 0x47ff, 0x0130, 0x4bff, 0x0230, 0x4fff, 0x0330, | ||
4275 | 0x53ff, 0x0430, 0x57ff, 0x0530, 0x5bff, 0x0630, 0x5fff, 0x0730, | ||
4276 | 0x63ff, 0x0830, 0x67ff, 0x0930, 0x6bff, 0x0a30, 0x6fff, 0x0b30, | ||
4277 | 0x73ff, 0x0c30, 0x77ff, 0x0d30, 0x7bff, 0x0e30, 0x7fff, 0x0f30, | ||
4278 | |||
4279 | 0x83ff, 0x0030, 0x87ff, 0x0130, 0x8bff, 0x0230, 0x8fff, 0x0330, | ||
4280 | 0x93ff, 0x0430, 0x97ff, 0x0530, 0x9bff, 0x0630, 0x9fff, 0x0730, | ||
4281 | 0xa3ff, 0x0830, 0xa7ff, 0x0930, 0xabff, 0x0a30, 0xafff, 0x0b30, | ||
4282 | 0xb3ff, 0x0c30, 0xb7ff, 0x0d30, 0xbbff, 0x0e30, 0xbfff, 0x0f30, | ||
4283 | |||
4284 | 0xc3ff, 0x0030, 0xc7ff, 0x0130, 0xcbff, 0x0230, 0xcfff, 0x0330, | ||
4285 | 0xd3ff, 0x0430, 0xd7ff, 0x0530, 0xdbff, 0x0630, 0xdfff, 0x0730, | ||
4286 | 0xe3ff, 0x0830, 0xe7ff, 0x0930, 0xebff, 0x0a30, 0xefff, 0x0b30, | ||
4287 | 0xf3ff, 0x0c30, 0xf7ff, 0x0d30, 0xfbff, 0x0e30, 0xffff, 0x0f30, | ||
4288 | }; | ||
4289 | |||
4290 | static unsigned short init2[128] = { | ||
4291 | 0x03ff, 0x8030, 0x07ff, 0x8130, 0x0bff, 0x8230, 0x0fff, 0x8330, | ||
4292 | 0x13ff, 0x8430, 0x17ff, 0x8530, 0x1bff, 0x8630, 0x1fff, 0x8730, | ||
4293 | 0x23ff, 0x8830, 0x27ff, 0x8930, 0x2bff, 0x8a30, 0x2fff, 0x8b30, | ||
4294 | 0x33ff, 0x8c30, 0x37ff, 0x8d30, 0x3bff, 0x8e30, 0x3fff, 0x8f30, | ||
4295 | |||
4296 | 0x43ff, 0x8030, 0x47ff, 0x8130, 0x4bff, 0x8230, 0x4fff, 0x8330, | ||
4297 | 0x53ff, 0x8430, 0x57ff, 0x8530, 0x5bff, 0x8630, 0x5fff, 0x8730, | ||
4298 | 0x63ff, 0x8830, 0x67ff, 0x8930, 0x6bff, 0x8a30, 0x6fff, 0x8b30, | ||
4299 | 0x73ff, 0x8c30, 0x77ff, 0x8d30, 0x7bff, 0x8e30, 0x7fff, 0x8f30, | ||
4300 | |||
4301 | 0x83ff, 0x8030, 0x87ff, 0x8130, 0x8bff, 0x8230, 0x8fff, 0x8330, | ||
4302 | 0x93ff, 0x8430, 0x97ff, 0x8530, 0x9bff, 0x8630, 0x9fff, 0x8730, | ||
4303 | 0xa3ff, 0x8830, 0xa7ff, 0x8930, 0xabff, 0x8a30, 0xafff, 0x8b30, | ||
4304 | 0xb3ff, 0x8c30, 0xb7ff, 0x8d30, 0xbbff, 0x8e30, 0xbfff, 0x8f30, | ||
4305 | |||
4306 | 0xc3ff, 0x8030, 0xc7ff, 0x8130, 0xcbff, 0x8230, 0xcfff, 0x8330, | ||
4307 | 0xd3ff, 0x8430, 0xd7ff, 0x8530, 0xdbff, 0x8630, 0xdfff, 0x8730, | ||
4308 | 0xe3ff, 0x8830, 0xe7ff, 0x8930, 0xebff, 0x8a30, 0xefff, 0x8b30, | ||
4309 | 0xf3ff, 0x8c30, 0xf7ff, 0x8d30, 0xfbff, 0x8e30, 0xffff, 0x8f30, | ||
4310 | }; | ||
4311 | |||
4312 | static unsigned short init3[128] = { | ||
4313 | 0x0C10, 0x8470, 0x14FE, 0xB488, 0x167F, 0xA470, 0x18E7, 0x84B5, | ||
4314 | 0x1B6E, 0x842A, 0x1F1D, 0x852A, 0x0DA3, 0x8F7C, 0x167E, 0xF254, | ||
4315 | 0x0000, 0x842A, 0x0001, 0x852A, 0x18E6, 0x8BAA, 0x1B6D, 0xF234, | ||
4316 | 0x229F, 0x8429, 0x2746, 0x8529, 0x1F1C, 0x86E7, 0x229E, 0xF224, | ||
4317 | |||
4318 | 0x0DA4, 0x8429, 0x2C29, 0x8529, 0x2745, 0x87F6, 0x2C28, 0xF254, | ||
4319 | 0x383B, 0x8428, 0x320F, 0x8528, 0x320E, 0x8F02, 0x1341, 0xF264, | ||
4320 | 0x3EB6, 0x8428, 0x3EB9, 0x8528, 0x383A, 0x8FA9, 0x3EB5, 0xF294, | ||
4321 | 0x3EB7, 0x8474, 0x3EBA, 0x8575, 0x3EB8, 0xC4C3, 0x3EBB, 0xC5C3, | ||
4322 | |||
4323 | 0x0000, 0xA404, 0x0001, 0xA504, 0x141F, 0x8671, 0x14FD, 0x8287, | ||
4324 | 0x3EBC, 0xE610, 0x3EC8, 0x8C7B, 0x031A, 0x87E6, 0x3EC8, 0x86F7, | ||
4325 | 0x3EC0, 0x821E, 0x3EBE, 0xD208, 0x3EBD, 0x821F, 0x3ECA, 0x8386, | ||
4326 | 0x3EC1, 0x8C03, 0x3EC9, 0x831E, 0x3ECA, 0x8C4C, 0x3EBF, 0x8C55, | ||
4327 | |||
4328 | 0x3EC9, 0xC208, 0x3EC4, 0xBC84, 0x3EC8, 0x8EAD, 0x3EC8, 0xD308, | ||
4329 | 0x3EC2, 0x8F7E, 0x3ECB, 0x8219, 0x3ECB, 0xD26E, 0x3EC5, 0x831F, | ||
4330 | 0x3EC6, 0xC308, 0x3EC3, 0xB2FF, 0x3EC9, 0x8265, 0x3EC9, 0x8319, | ||
4331 | 0x1342, 0xD36E, 0x3EC7, 0xB3FF, 0x0000, 0x8365, 0x1420, 0x9570, | ||
4332 | }; | ||
4333 | |||
4334 | static unsigned short init4[128] = { | ||
4335 | 0x0C10, 0x8470, 0x14FE, 0xB488, 0x167F, 0xA470, 0x18E7, 0x84B5, | ||
4336 | 0x1B6E, 0x842A, 0x1F1D, 0x852A, 0x0DA3, 0x0F7C, 0x167E, 0x7254, | ||
4337 | 0x0000, 0x842A, 0x0001, 0x852A, 0x18E6, 0x0BAA, 0x1B6D, 0x7234, | ||
4338 | 0x229F, 0x8429, 0x2746, 0x8529, 0x1F1C, 0x06E7, 0x229E, 0x7224, | ||
4339 | |||
4340 | 0x0DA4, 0x8429, 0x2C29, 0x8529, 0x2745, 0x07F6, 0x2C28, 0x7254, | ||
4341 | 0x383B, 0x8428, 0x320F, 0x8528, 0x320E, 0x0F02, 0x1341, 0x7264, | ||
4342 | 0x3EB6, 0x8428, 0x3EB9, 0x8528, 0x383A, 0x0FA9, 0x3EB5, 0x7294, | ||
4343 | 0x3EB7, 0x8474, 0x3EBA, 0x8575, 0x3EB8, 0x44C3, 0x3EBB, 0x45C3, | ||
4344 | |||
4345 | 0x0000, 0xA404, 0x0001, 0xA504, 0x141F, 0x0671, 0x14FD, 0x0287, | ||
4346 | 0x3EBC, 0xE610, 0x3EC8, 0x0C7B, 0x031A, 0x07E6, 0x3EC8, 0x86F7, | ||
4347 | 0x3EC0, 0x821E, 0x3EBE, 0xD208, 0x3EBD, 0x021F, 0x3ECA, 0x0386, | ||
4348 | 0x3EC1, 0x0C03, 0x3EC9, 0x031E, 0x3ECA, 0x8C4C, 0x3EBF, 0x0C55, | ||
4349 | |||
4350 | 0x3EC9, 0xC208, 0x3EC4, 0xBC84, 0x3EC8, 0x0EAD, 0x3EC8, 0xD308, | ||
4351 | 0x3EC2, 0x8F7E, 0x3ECB, 0x0219, 0x3ECB, 0xD26E, 0x3EC5, 0x031F, | ||
4352 | 0x3EC6, 0xC308, 0x3EC3, 0x32FF, 0x3EC9, 0x0265, 0x3EC9, 0x8319, | ||
4353 | 0x1342, 0xD36E, 0x3EC7, 0x33FF, 0x0000, 0x8365, 0x1420, 0x9570, | ||
4354 | }; | ||
4355 | |||
4356 | |||
4357 | /* send initialization arrays to start up */ | ||
4358 | static void | ||
4359 | awe_init_array(void) | ||
4360 | { | ||
4361 | awe_send_array(init1); | ||
4362 | awe_wait(1024); | ||
4363 | awe_send_array(init2); | ||
4364 | awe_send_array(init3); | ||
4365 | awe_poke_dw(AWE_HWCF4, 0); | ||
4366 | awe_poke_dw(AWE_HWCF5, 0x83); | ||
4367 | awe_poke_dw(AWE_HWCF6, 0x8000); | ||
4368 | awe_send_array(init4); | ||
4369 | } | ||
4370 | |||
4371 | /* send an initialization array */ | ||
4372 | static void | ||
4373 | awe_send_array(unsigned short *data) | ||
4374 | { | ||
4375 | int i; | ||
4376 | unsigned short *p; | ||
4377 | |||
4378 | p = data; | ||
4379 | for (i = 0; i < AWE_MAX_VOICES; i++, p++) | ||
4380 | awe_poke(AWE_INIT1(i), *p); | ||
4381 | for (i = 0; i < AWE_MAX_VOICES; i++, p++) | ||
4382 | awe_poke(AWE_INIT2(i), *p); | ||
4383 | for (i = 0; i < AWE_MAX_VOICES; i++, p++) | ||
4384 | awe_poke(AWE_INIT3(i), *p); | ||
4385 | for (i = 0; i < AWE_MAX_VOICES; i++, p++) | ||
4386 | awe_poke(AWE_INIT4(i), *p); | ||
4387 | } | ||
4388 | |||
4389 | |||
4390 | /* | ||
4391 | * set up awe32 channels to some known state. | ||
4392 | */ | ||
4393 | |||
4394 | /* set the envelope & LFO parameters to the default values; see ADIP */ | ||
4395 | static void | ||
4396 | awe_tweak_voice(int i) | ||
4397 | { | ||
4398 | /* set all mod/vol envelope shape to minimum */ | ||
4399 | awe_poke(AWE_ENVVOL(i), 0x8000); | ||
4400 | awe_poke(AWE_ENVVAL(i), 0x8000); | ||
4401 | awe_poke(AWE_DCYSUS(i), 0x7F7F); | ||
4402 | awe_poke(AWE_ATKHLDV(i), 0x7F7F); | ||
4403 | awe_poke(AWE_ATKHLD(i), 0x7F7F); | ||
4404 | awe_poke(AWE_PEFE(i), 0); /* mod envelope height to zero */ | ||
4405 | awe_poke(AWE_LFO1VAL(i), 0x8000); /* no delay for LFO1 */ | ||
4406 | awe_poke(AWE_LFO2VAL(i), 0x8000); | ||
4407 | awe_poke(AWE_IP(i), 0xE000); /* no pitch shift */ | ||
4408 | awe_poke(AWE_IFATN(i), 0xFF00); /* volume to minimum */ | ||
4409 | awe_poke(AWE_FMMOD(i), 0); | ||
4410 | awe_poke(AWE_TREMFRQ(i), 0); | ||
4411 | awe_poke(AWE_FM2FRQ2(i), 0); | ||
4412 | } | ||
4413 | |||
4414 | static void | ||
4415 | awe_tweak(void) | ||
4416 | { | ||
4417 | int i; | ||
4418 | /* reset all channels */ | ||
4419 | for (i = 0; i < awe_max_voices; i++) | ||
4420 | awe_tweak_voice(i); | ||
4421 | } | ||
4422 | |||
4423 | |||
4424 | /* | ||
4425 | * initializes the FM section of AWE32; | ||
4426 | * see Vince Vu's unofficial AWE32 programming guide | ||
4427 | */ | ||
4428 | |||
4429 | static void | ||
4430 | awe_init_fm(void) | ||
4431 | { | ||
4432 | #ifndef AWE_ALWAYS_INIT_FM | ||
4433 | /* if no extended memory is on board.. */ | ||
4434 | if (memsize <= 0) | ||
4435 | return; | ||
4436 | #endif | ||
4437 | DEBUG(3,printk("AWE32: initializing FM\n")); | ||
4438 | |||
4439 | /* Initialize the last two channels for DRAM refresh and producing | ||
4440 | the reverb and chorus effects for Yamaha OPL-3 synthesizer */ | ||
4441 | |||
4442 | /* 31: FM left channel, 0xffffe0-0xffffe8 */ | ||
4443 | awe_poke(AWE_DCYSUSV(30), 0x80); | ||
4444 | awe_poke_dw(AWE_PSST(30), 0xFFFFFFE0); /* full left */ | ||
4445 | awe_poke_dw(AWE_CSL(30), 0x00FFFFE8 | | ||
4446 | (DEF_FM_CHORUS_DEPTH << 24)); | ||
4447 | awe_poke_dw(AWE_PTRX(30), (DEF_FM_REVERB_DEPTH << 8)); | ||
4448 | awe_poke_dw(AWE_CPF(30), 0); | ||
4449 | awe_poke_dw(AWE_CCCA(30), 0x00FFFFE3); | ||
4450 | |||
4451 | /* 32: FM right channel, 0xfffff0-0xfffff8 */ | ||
4452 | awe_poke(AWE_DCYSUSV(31), 0x80); | ||
4453 | awe_poke_dw(AWE_PSST(31), 0x00FFFFF0); /* full right */ | ||
4454 | awe_poke_dw(AWE_CSL(31), 0x00FFFFF8 | | ||
4455 | (DEF_FM_CHORUS_DEPTH << 24)); | ||
4456 | awe_poke_dw(AWE_PTRX(31), (DEF_FM_REVERB_DEPTH << 8)); | ||
4457 | awe_poke_dw(AWE_CPF(31), 0x8000); | ||
4458 | awe_poke_dw(AWE_CCCA(31), 0x00FFFFF3); | ||
4459 | |||
4460 | /* skew volume & cutoff */ | ||
4461 | awe_poke_dw(AWE_VTFT(30), 0x8000FFFF); | ||
4462 | awe_poke_dw(AWE_VTFT(31), 0x8000FFFF); | ||
4463 | |||
4464 | voices[30].state = AWE_ST_FM; | ||
4465 | voices[31].state = AWE_ST_FM; | ||
4466 | |||
4467 | /* change maximum channels to 30 */ | ||
4468 | awe_max_voices = AWE_NORMAL_VOICES; | ||
4469 | if (playing_mode == AWE_PLAY_DIRECT) | ||
4470 | awe_info.nr_voices = awe_max_voices; | ||
4471 | else | ||
4472 | awe_info.nr_voices = AWE_MAX_CHANNELS; | ||
4473 | voice_alloc->max_voice = awe_max_voices; | ||
4474 | } | ||
4475 | |||
4476 | /* | ||
4477 | * AWE32 DRAM access routines | ||
4478 | */ | ||
4479 | |||
4480 | /* open DRAM write accessing mode */ | ||
4481 | static int | ||
4482 | awe_open_dram_for_write(int offset, int channels) | ||
4483 | { | ||
4484 | int vidx[AWE_NORMAL_VOICES]; | ||
4485 | int i; | ||
4486 | |||
4487 | if (channels < 0 || channels >= AWE_NORMAL_VOICES) { | ||
4488 | channels = AWE_NORMAL_VOICES; | ||
4489 | for (i = 0; i < AWE_NORMAL_VOICES; i++) | ||
4490 | vidx[i] = i; | ||
4491 | } else { | ||
4492 | for (i = 0; i < channels; i++) { | ||
4493 | vidx[i] = awe_clear_voice(); | ||
4494 | voices[vidx[i]].state = AWE_ST_MARK; | ||
4495 | } | ||
4496 | } | ||
4497 | |||
4498 | /* use all channels for DMA transfer */ | ||
4499 | for (i = 0; i < channels; i++) { | ||
4500 | if (vidx[i] < 0) continue; | ||
4501 | awe_poke(AWE_DCYSUSV(vidx[i]), 0x80); | ||
4502 | awe_poke_dw(AWE_VTFT(vidx[i]), 0); | ||
4503 | awe_poke_dw(AWE_CVCF(vidx[i]), 0); | ||
4504 | awe_poke_dw(AWE_PTRX(vidx[i]), 0x40000000); | ||
4505 | awe_poke_dw(AWE_CPF(vidx[i]), 0x40000000); | ||
4506 | awe_poke_dw(AWE_PSST(vidx[i]), 0); | ||
4507 | awe_poke_dw(AWE_CSL(vidx[i]), 0); | ||
4508 | awe_poke_dw(AWE_CCCA(vidx[i]), 0x06000000); | ||
4509 | voices[vidx[i]].state = AWE_ST_DRAM; | ||
4510 | } | ||
4511 | /* point channels 31 & 32 to ROM samples for DRAM refresh */ | ||
4512 | awe_poke_dw(AWE_VTFT(30), 0); | ||
4513 | awe_poke_dw(AWE_PSST(30), 0x1d8); | ||
4514 | awe_poke_dw(AWE_CSL(30), 0x1e0); | ||
4515 | awe_poke_dw(AWE_CCCA(30), 0x1d8); | ||
4516 | awe_poke_dw(AWE_VTFT(31), 0); | ||
4517 | awe_poke_dw(AWE_PSST(31), 0x1d8); | ||
4518 | awe_poke_dw(AWE_CSL(31), 0x1e0); | ||
4519 | awe_poke_dw(AWE_CCCA(31), 0x1d8); | ||
4520 | voices[30].state = AWE_ST_FM; | ||
4521 | voices[31].state = AWE_ST_FM; | ||
4522 | |||
4523 | /* if full bit is on, not ready to write on */ | ||
4524 | if (awe_peek_dw(AWE_SMALW) & 0x80000000) { | ||
4525 | for (i = 0; i < channels; i++) { | ||
4526 | awe_poke_dw(AWE_CCCA(vidx[i]), 0); | ||
4527 | voices[vidx[i]].state = AWE_ST_OFF; | ||
4528 | } | ||
4529 | printk("awe: not ready to write..\n"); | ||
4530 | return -EPERM; | ||
4531 | } | ||
4532 | |||
4533 | /* set address to write */ | ||
4534 | awe_poke_dw(AWE_SMALW, offset); | ||
4535 | |||
4536 | return 0; | ||
4537 | } | ||
4538 | |||
4539 | /* open DRAM for RAM size detection */ | ||
4540 | static void | ||
4541 | awe_open_dram_for_check(void) | ||
4542 | { | ||
4543 | int i; | ||
4544 | for (i = 0; i < AWE_NORMAL_VOICES; i++) { | ||
4545 | awe_poke(AWE_DCYSUSV(i), 0x80); | ||
4546 | awe_poke_dw(AWE_VTFT(i), 0); | ||
4547 | awe_poke_dw(AWE_CVCF(i), 0); | ||
4548 | awe_poke_dw(AWE_PTRX(i), 0x40000000); | ||
4549 | awe_poke_dw(AWE_CPF(i), 0x40000000); | ||
4550 | awe_poke_dw(AWE_PSST(i), 0); | ||
4551 | awe_poke_dw(AWE_CSL(i), 0); | ||
4552 | if (i & 1) /* DMA write */ | ||
4553 | awe_poke_dw(AWE_CCCA(i), 0x06000000); | ||
4554 | else /* DMA read */ | ||
4555 | awe_poke_dw(AWE_CCCA(i), 0x04000000); | ||
4556 | voices[i].state = AWE_ST_DRAM; | ||
4557 | } | ||
4558 | } | ||
4559 | |||
4560 | |||
4561 | /* close dram access */ | ||
4562 | static void | ||
4563 | awe_close_dram(void) | ||
4564 | { | ||
4565 | int i; | ||
4566 | /* wait until FULL bit in SMAxW register be false */ | ||
4567 | for (i = 0; i < 10000; i++) { | ||
4568 | if (!(awe_peek_dw(AWE_SMALW) & 0x80000000)) | ||
4569 | break; | ||
4570 | awe_wait(10); | ||
4571 | } | ||
4572 | |||
4573 | for (i = 0; i < AWE_NORMAL_VOICES; i++) { | ||
4574 | if (voices[i].state == AWE_ST_DRAM) { | ||
4575 | awe_poke_dw(AWE_CCCA(i), 0); | ||
4576 | awe_poke(AWE_DCYSUSV(i), 0x807F); | ||
4577 | voices[i].state = AWE_ST_OFF; | ||
4578 | } | ||
4579 | } | ||
4580 | } | ||
4581 | |||
4582 | |||
4583 | /* | ||
4584 | * check dram size on AWE board | ||
4585 | */ | ||
4586 | |||
4587 | /* any three numbers you like */ | ||
4588 | #define UNIQUE_ID1 0x1234 | ||
4589 | #define UNIQUE_ID2 0x4321 | ||
4590 | #define UNIQUE_ID3 0xABCD | ||
4591 | |||
4592 | static void __init | ||
4593 | awe_check_dram(void) | ||
4594 | { | ||
4595 | if (awe_present) /* already initialized */ | ||
4596 | return; | ||
4597 | |||
4598 | if (memsize >= 0) { /* given by config file or module option */ | ||
4599 | memsize *= 1024; /* convert to Kbytes */ | ||
4600 | return; | ||
4601 | } | ||
4602 | |||
4603 | awe_open_dram_for_check(); | ||
4604 | |||
4605 | memsize = 0; | ||
4606 | |||
4607 | /* set up unique two id numbers */ | ||
4608 | awe_poke_dw(AWE_SMALW, AWE_DRAM_OFFSET); | ||
4609 | awe_poke(AWE_SMLD, UNIQUE_ID1); | ||
4610 | awe_poke(AWE_SMLD, UNIQUE_ID2); | ||
4611 | |||
4612 | while (memsize < AWE_MAX_DRAM_SIZE) { | ||
4613 | awe_wait(5); | ||
4614 | /* read a data on the DRAM start address */ | ||
4615 | awe_poke_dw(AWE_SMALR, AWE_DRAM_OFFSET); | ||
4616 | awe_peek(AWE_SMLD); /* discard stale data */ | ||
4617 | if (awe_peek(AWE_SMLD) != UNIQUE_ID1) | ||
4618 | break; | ||
4619 | if (awe_peek(AWE_SMLD) != UNIQUE_ID2) | ||
4620 | break; | ||
4621 | memsize += 512; /* increment 512kbytes */ | ||
4622 | /* Write a unique data on the test address; | ||
4623 | * if the address is out of range, the data is written on | ||
4624 | * 0x200000(=AWE_DRAM_OFFSET). Then the two id words are | ||
4625 | * broken by this data. | ||
4626 | */ | ||
4627 | awe_poke_dw(AWE_SMALW, AWE_DRAM_OFFSET + memsize*512L); | ||
4628 | awe_poke(AWE_SMLD, UNIQUE_ID3); | ||
4629 | awe_wait(5); | ||
4630 | /* read a data on the just written DRAM address */ | ||
4631 | awe_poke_dw(AWE_SMALR, AWE_DRAM_OFFSET + memsize*512L); | ||
4632 | awe_peek(AWE_SMLD); /* discard stale data */ | ||
4633 | if (awe_peek(AWE_SMLD) != UNIQUE_ID3) | ||
4634 | break; | ||
4635 | } | ||
4636 | awe_close_dram(); | ||
4637 | |||
4638 | DEBUG(0,printk("AWE32: %d Kbytes memory detected\n", memsize)); | ||
4639 | |||
4640 | /* convert to Kbytes */ | ||
4641 | memsize *= 1024; | ||
4642 | } | ||
4643 | |||
4644 | |||
4645 | /*----------------------------------------------------------------*/ | ||
4646 | |||
4647 | /* | ||
4648 | * chorus and reverb controls; from VV's guide | ||
4649 | */ | ||
4650 | |||
4651 | /* 5 parameters for each chorus mode; 3 x 16bit, 2 x 32bit */ | ||
4652 | static char chorus_defined[AWE_CHORUS_NUMBERS]; | ||
4653 | static awe_chorus_fx_rec chorus_parm[AWE_CHORUS_NUMBERS] = { | ||
4654 | {0xE600, 0x03F6, 0xBC2C ,0x00000000, 0x0000006D}, /* chorus 1 */ | ||
4655 | {0xE608, 0x031A, 0xBC6E, 0x00000000, 0x0000017C}, /* chorus 2 */ | ||
4656 | {0xE610, 0x031A, 0xBC84, 0x00000000, 0x00000083}, /* chorus 3 */ | ||
4657 | {0xE620, 0x0269, 0xBC6E, 0x00000000, 0x0000017C}, /* chorus 4 */ | ||
4658 | {0xE680, 0x04D3, 0xBCA6, 0x00000000, 0x0000005B}, /* feedback */ | ||
4659 | {0xE6E0, 0x044E, 0xBC37, 0x00000000, 0x00000026}, /* flanger */ | ||
4660 | {0xE600, 0x0B06, 0xBC00, 0x0000E000, 0x00000083}, /* short delay */ | ||
4661 | {0xE6C0, 0x0B06, 0xBC00, 0x0000E000, 0x00000083}, /* short delay + feedback */ | ||
4662 | }; | ||
4663 | |||
4664 | static int | ||
4665 | awe_load_chorus_fx(awe_patch_info *patch, const char __user *addr, int count) | ||
4666 | { | ||
4667 | if (patch->optarg < AWE_CHORUS_PREDEFINED || patch->optarg >= AWE_CHORUS_NUMBERS) { | ||
4668 | printk(KERN_WARNING "AWE32 Error: invalid chorus mode %d for uploading\n", patch->optarg); | ||
4669 | return -EINVAL; | ||
4670 | } | ||
4671 | if (count < sizeof(awe_chorus_fx_rec)) { | ||
4672 | printk(KERN_WARNING "AWE32 Error: too short chorus fx parameters\n"); | ||
4673 | return -EINVAL; | ||
4674 | } | ||
4675 | if (copy_from_user(&chorus_parm[patch->optarg], addr + AWE_PATCH_INFO_SIZE, | ||
4676 | sizeof(awe_chorus_fx_rec))) | ||
4677 | return -EFAULT; | ||
4678 | chorus_defined[patch->optarg] = TRUE; | ||
4679 | return 0; | ||
4680 | } | ||
4681 | |||
4682 | static void | ||
4683 | awe_set_chorus_mode(int effect) | ||
4684 | { | ||
4685 | if (effect < 0 || effect >= AWE_CHORUS_NUMBERS || | ||
4686 | (effect >= AWE_CHORUS_PREDEFINED && !chorus_defined[effect])) | ||
4687 | return; | ||
4688 | awe_poke(AWE_INIT3(9), chorus_parm[effect].feedback); | ||
4689 | awe_poke(AWE_INIT3(12), chorus_parm[effect].delay_offset); | ||
4690 | awe_poke(AWE_INIT4(3), chorus_parm[effect].lfo_depth); | ||
4691 | awe_poke_dw(AWE_HWCF4, chorus_parm[effect].delay); | ||
4692 | awe_poke_dw(AWE_HWCF5, chorus_parm[effect].lfo_freq); | ||
4693 | awe_poke_dw(AWE_HWCF6, 0x8000); | ||
4694 | awe_poke_dw(AWE_HWCF7, 0x0000); | ||
4695 | } | ||
4696 | |||
4697 | static void | ||
4698 | awe_update_chorus_mode(void) | ||
4699 | { | ||
4700 | awe_set_chorus_mode(ctrls[AWE_MD_CHORUS_MODE]); | ||
4701 | } | ||
4702 | |||
4703 | /*----------------------------------------------------------------*/ | ||
4704 | |||
4705 | /* reverb mode settings; write the following 28 data of 16 bit length | ||
4706 | * on the corresponding ports in the reverb_cmds array | ||
4707 | */ | ||
4708 | static char reverb_defined[AWE_CHORUS_NUMBERS]; | ||
4709 | static awe_reverb_fx_rec reverb_parm[AWE_REVERB_NUMBERS] = { | ||
4710 | {{ /* room 1 */ | ||
4711 | 0xB488, 0xA450, 0x9550, 0x84B5, 0x383A, 0x3EB5, 0x72F4, | ||
4712 | 0x72A4, 0x7254, 0x7204, 0x7204, 0x7204, 0x4416, 0x4516, | ||
4713 | 0xA490, 0xA590, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429, | ||
4714 | 0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528, | ||
4715 | }}, | ||
4716 | {{ /* room 2 */ | ||
4717 | 0xB488, 0xA458, 0x9558, 0x84B5, 0x383A, 0x3EB5, 0x7284, | ||
4718 | 0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4448, 0x4548, | ||
4719 | 0xA440, 0xA540, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429, | ||
4720 | 0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528, | ||
4721 | }}, | ||
4722 | {{ /* room 3 */ | ||
4723 | 0xB488, 0xA460, 0x9560, 0x84B5, 0x383A, 0x3EB5, 0x7284, | ||
4724 | 0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4416, 0x4516, | ||
4725 | 0xA490, 0xA590, 0x842C, 0x852C, 0x842C, 0x852C, 0x842B, | ||
4726 | 0x852B, 0x842B, 0x852B, 0x842A, 0x852A, 0x842A, 0x852A, | ||
4727 | }}, | ||
4728 | {{ /* hall 1 */ | ||
4729 | 0xB488, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7284, | ||
4730 | 0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4448, 0x4548, | ||
4731 | 0xA440, 0xA540, 0x842B, 0x852B, 0x842B, 0x852B, 0x842A, | ||
4732 | 0x852A, 0x842A, 0x852A, 0x8429, 0x8529, 0x8429, 0x8529, | ||
4733 | }}, | ||
4734 | {{ /* hall 2 */ | ||
4735 | 0xB488, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7254, | ||
4736 | 0x7234, 0x7224, 0x7254, 0x7264, 0x7294, 0x44C3, 0x45C3, | ||
4737 | 0xA404, 0xA504, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429, | ||
4738 | 0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528, | ||
4739 | }}, | ||
4740 | {{ /* plate */ | ||
4741 | 0xB4FF, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7234, | ||
4742 | 0x7234, 0x7234, 0x7234, 0x7234, 0x7234, 0x4448, 0x4548, | ||
4743 | 0xA440, 0xA540, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429, | ||
4744 | 0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528, | ||
4745 | }}, | ||
4746 | {{ /* delay */ | ||
4747 | 0xB4FF, 0xA470, 0x9500, 0x84B5, 0x333A, 0x39B5, 0x7204, | ||
4748 | 0x7204, 0x7204, 0x7204, 0x7204, 0x72F4, 0x4400, 0x4500, | ||
4749 | 0xA4FF, 0xA5FF, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420, | ||
4750 | 0x8520, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420, 0x8520, | ||
4751 | }}, | ||
4752 | {{ /* panning delay */ | ||
4753 | 0xB4FF, 0xA490, 0x9590, 0x8474, 0x333A, 0x39B5, 0x7204, | ||
4754 | 0x7204, 0x7204, 0x7204, 0x7204, 0x72F4, 0x4400, 0x4500, | ||
4755 | 0xA4FF, 0xA5FF, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420, | ||
4756 | 0x8520, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420, 0x8520, | ||
4757 | }}, | ||
4758 | }; | ||
4759 | |||
4760 | static struct ReverbCmdPair { | ||
4761 | unsigned short cmd, port; | ||
4762 | } reverb_cmds[28] = { | ||
4763 | {AWE_INIT1(0x03)}, {AWE_INIT1(0x05)}, {AWE_INIT4(0x1F)}, {AWE_INIT1(0x07)}, | ||
4764 | {AWE_INIT2(0x14)}, {AWE_INIT2(0x16)}, {AWE_INIT1(0x0F)}, {AWE_INIT1(0x17)}, | ||
4765 | {AWE_INIT1(0x1F)}, {AWE_INIT2(0x07)}, {AWE_INIT2(0x0F)}, {AWE_INIT2(0x17)}, | ||
4766 | {AWE_INIT2(0x1D)}, {AWE_INIT2(0x1F)}, {AWE_INIT3(0x01)}, {AWE_INIT3(0x03)}, | ||
4767 | {AWE_INIT1(0x09)}, {AWE_INIT1(0x0B)}, {AWE_INIT1(0x11)}, {AWE_INIT1(0x13)}, | ||
4768 | {AWE_INIT1(0x19)}, {AWE_INIT1(0x1B)}, {AWE_INIT2(0x01)}, {AWE_INIT2(0x03)}, | ||
4769 | {AWE_INIT2(0x09)}, {AWE_INIT2(0x0B)}, {AWE_INIT2(0x11)}, {AWE_INIT2(0x13)}, | ||
4770 | }; | ||
4771 | |||
4772 | static int | ||
4773 | awe_load_reverb_fx(awe_patch_info *patch, const char __user *addr, int count) | ||
4774 | { | ||
4775 | if (patch->optarg < AWE_REVERB_PREDEFINED || patch->optarg >= AWE_REVERB_NUMBERS) { | ||
4776 | printk(KERN_WARNING "AWE32 Error: invalid reverb mode %d for uploading\n", patch->optarg); | ||
4777 | return -EINVAL; | ||
4778 | } | ||
4779 | if (count < sizeof(awe_reverb_fx_rec)) { | ||
4780 | printk(KERN_WARNING "AWE32 Error: too short reverb fx parameters\n"); | ||
4781 | return -EINVAL; | ||
4782 | } | ||
4783 | if (copy_from_user(&reverb_parm[patch->optarg], addr + AWE_PATCH_INFO_SIZE, | ||
4784 | sizeof(awe_reverb_fx_rec))) | ||
4785 | return -EFAULT; | ||
4786 | reverb_defined[patch->optarg] = TRUE; | ||
4787 | return 0; | ||
4788 | } | ||
4789 | |||
4790 | static void | ||
4791 | awe_set_reverb_mode(int effect) | ||
4792 | { | ||
4793 | int i; | ||
4794 | if (effect < 0 || effect >= AWE_REVERB_NUMBERS || | ||
4795 | (effect >= AWE_REVERB_PREDEFINED && !reverb_defined[effect])) | ||
4796 | return; | ||
4797 | for (i = 0; i < 28; i++) | ||
4798 | awe_poke(reverb_cmds[i].cmd, reverb_cmds[i].port, | ||
4799 | reverb_parm[effect].parms[i]); | ||
4800 | } | ||
4801 | |||
4802 | static void | ||
4803 | awe_update_reverb_mode(void) | ||
4804 | { | ||
4805 | awe_set_reverb_mode(ctrls[AWE_MD_REVERB_MODE]); | ||
4806 | } | ||
4807 | |||
4808 | /* | ||
4809 | * treble/bass equalizer control | ||
4810 | */ | ||
4811 | |||
4812 | static unsigned short bass_parm[12][3] = { | ||
4813 | {0xD26A, 0xD36A, 0x0000}, /* -12 dB */ | ||
4814 | {0xD25B, 0xD35B, 0x0000}, /* -8 */ | ||
4815 | {0xD24C, 0xD34C, 0x0000}, /* -6 */ | ||
4816 | {0xD23D, 0xD33D, 0x0000}, /* -4 */ | ||
4817 | {0xD21F, 0xD31F, 0x0000}, /* -2 */ | ||
4818 | {0xC208, 0xC308, 0x0001}, /* 0 (HW default) */ | ||
4819 | {0xC219, 0xC319, 0x0001}, /* +2 */ | ||
4820 | {0xC22A, 0xC32A, 0x0001}, /* +4 */ | ||
4821 | {0xC24C, 0xC34C, 0x0001}, /* +6 */ | ||
4822 | {0xC26E, 0xC36E, 0x0001}, /* +8 */ | ||
4823 | {0xC248, 0xC348, 0x0002}, /* +10 */ | ||
4824 | {0xC26A, 0xC36A, 0x0002}, /* +12 dB */ | ||
4825 | }; | ||
4826 | |||
4827 | static unsigned short treble_parm[12][9] = { | ||
4828 | {0x821E, 0xC26A, 0x031E, 0xC36A, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001}, /* -12 dB */ | ||
4829 | {0x821E, 0xC25B, 0x031E, 0xC35B, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001}, | ||
4830 | {0x821E, 0xC24C, 0x031E, 0xC34C, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001}, | ||
4831 | {0x821E, 0xC23D, 0x031E, 0xC33D, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001}, | ||
4832 | {0x821E, 0xC21F, 0x031E, 0xC31F, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001}, | ||
4833 | {0x821E, 0xD208, 0x031E, 0xD308, 0x021E, 0xD208, 0x831E, 0xD308, 0x0002}, | ||
4834 | {0x821E, 0xD208, 0x031E, 0xD308, 0x021D, 0xD219, 0x831D, 0xD319, 0x0002}, | ||
4835 | {0x821E, 0xD208, 0x031E, 0xD308, 0x021C, 0xD22A, 0x831C, 0xD32A, 0x0002}, | ||
4836 | {0x821E, 0xD208, 0x031E, 0xD308, 0x021A, 0xD24C, 0x831A, 0xD34C, 0x0002}, | ||
4837 | {0x821E, 0xD208, 0x031E, 0xD308, 0x0219, 0xD26E, 0x8319, 0xD36E, 0x0002}, /* +8 (HW default) */ | ||
4838 | {0x821D, 0xD219, 0x031D, 0xD319, 0x0219, 0xD26E, 0x8319, 0xD36E, 0x0002}, | ||
4839 | {0x821C, 0xD22A, 0x031C, 0xD32A, 0x0219, 0xD26E, 0x8319, 0xD36E, 0x0002}, /* +12 dB */ | ||
4840 | }; | ||
4841 | |||
4842 | |||
4843 | /* | ||
4844 | * set Emu8000 digital equalizer; from 0 to 11 [-12dB - 12dB] | ||
4845 | */ | ||
4846 | static void | ||
4847 | awe_equalizer(int bass, int treble) | ||
4848 | { | ||
4849 | unsigned short w; | ||
4850 | |||
4851 | if (bass < 0 || bass > 11 || treble < 0 || treble > 11) | ||
4852 | return; | ||
4853 | awe_poke(AWE_INIT4(0x01), bass_parm[bass][0]); | ||
4854 | awe_poke(AWE_INIT4(0x11), bass_parm[bass][1]); | ||
4855 | awe_poke(AWE_INIT3(0x11), treble_parm[treble][0]); | ||
4856 | awe_poke(AWE_INIT3(0x13), treble_parm[treble][1]); | ||
4857 | awe_poke(AWE_INIT3(0x1B), treble_parm[treble][2]); | ||
4858 | awe_poke(AWE_INIT4(0x07), treble_parm[treble][3]); | ||
4859 | awe_poke(AWE_INIT4(0x0B), treble_parm[treble][4]); | ||
4860 | awe_poke(AWE_INIT4(0x0D), treble_parm[treble][5]); | ||
4861 | awe_poke(AWE_INIT4(0x17), treble_parm[treble][6]); | ||
4862 | awe_poke(AWE_INIT4(0x19), treble_parm[treble][7]); | ||
4863 | w = bass_parm[bass][2] + treble_parm[treble][8]; | ||
4864 | awe_poke(AWE_INIT4(0x15), (unsigned short)(w + 0x0262)); | ||
4865 | awe_poke(AWE_INIT4(0x1D), (unsigned short)(w + 0x8362)); | ||
4866 | } | ||
4867 | |||
4868 | static void awe_update_equalizer(void) | ||
4869 | { | ||
4870 | awe_equalizer(ctrls[AWE_MD_BASS_LEVEL], ctrls[AWE_MD_TREBLE_LEVEL]); | ||
4871 | } | ||
4872 | |||
4873 | |||
4874 | /*----------------------------------------------------------------*/ | ||
4875 | |||
4876 | #ifdef CONFIG_AWE32_MIDIEMU | ||
4877 | |||
4878 | /* | ||
4879 | * Emu8000 MIDI Emulation | ||
4880 | */ | ||
4881 | |||
4882 | /* | ||
4883 | * midi queue record | ||
4884 | */ | ||
4885 | |||
4886 | /* queue type */ | ||
4887 | enum { Q_NONE, Q_VARLEN, Q_READ, Q_SYSEX, }; | ||
4888 | |||
4889 | #define MAX_MIDIBUF 64 | ||
4890 | |||
4891 | /* midi status */ | ||
4892 | typedef struct MidiStatus { | ||
4893 | int queue; /* queue type */ | ||
4894 | int qlen; /* queue length */ | ||
4895 | int read; /* chars read */ | ||
4896 | int status; /* current status */ | ||
4897 | int chan; /* current channel */ | ||
4898 | unsigned char buf[MAX_MIDIBUF]; | ||
4899 | } MidiStatus; | ||
4900 | |||
4901 | /* MIDI mode type */ | ||
4902 | enum { MODE_GM, MODE_GS, MODE_XG, }; | ||
4903 | |||
4904 | /* NRPN / CC -> Emu8000 parameter converter */ | ||
4905 | typedef struct { | ||
4906 | int control; | ||
4907 | int awe_effect; | ||
4908 | unsigned short (*convert)(int val); | ||
4909 | } ConvTable; | ||
4910 | |||
4911 | |||
4912 | /* | ||
4913 | * prototypes | ||
4914 | */ | ||
4915 | |||
4916 | static int awe_midi_open(int dev, int mode, void (*input)(int,unsigned char), void (*output)(int)); | ||
4917 | static void awe_midi_close(int dev); | ||
4918 | static int awe_midi_ioctl(int dev, unsigned cmd, void __user * arg); | ||
4919 | static int awe_midi_outputc(int dev, unsigned char midi_byte); | ||
4920 | |||
4921 | static void init_midi_status(MidiStatus *st); | ||
4922 | static void clear_rpn(void); | ||
4923 | static void get_midi_char(MidiStatus *st, int c); | ||
4924 | /*static void queue_varlen(MidiStatus *st, int c);*/ | ||
4925 | static void special_event(MidiStatus *st, int c); | ||
4926 | static void queue_read(MidiStatus *st, int c); | ||
4927 | static void midi_note_on(MidiStatus *st); | ||
4928 | static void midi_note_off(MidiStatus *st); | ||
4929 | static void midi_key_pressure(MidiStatus *st); | ||
4930 | static void midi_channel_pressure(MidiStatus *st); | ||
4931 | static void midi_pitch_wheel(MidiStatus *st); | ||
4932 | static void midi_program_change(MidiStatus *st); | ||
4933 | static void midi_control_change(MidiStatus *st); | ||
4934 | static void midi_select_bank(MidiStatus *st, int val); | ||
4935 | static void midi_nrpn_event(MidiStatus *st); | ||
4936 | static void midi_rpn_event(MidiStatus *st); | ||
4937 | static void midi_detune(int chan, int coarse, int fine); | ||
4938 | static void midi_system_exclusive(MidiStatus *st); | ||
4939 | static int send_converted_effect(ConvTable *table, int num_tables, MidiStatus *st, int type, int val); | ||
4940 | static int add_converted_effect(ConvTable *table, int num_tables, MidiStatus *st, int type, int val); | ||
4941 | static int xg_control_change(MidiStatus *st, int cmd, int val); | ||
4942 | |||
4943 | #define numberof(ary) (sizeof(ary)/sizeof(ary[0])) | ||
4944 | |||
4945 | |||
4946 | /* | ||
4947 | * OSS Midi device record | ||
4948 | */ | ||
4949 | |||
4950 | static struct midi_operations awe_midi_operations = | ||
4951 | { | ||
4952 | .owner = THIS_MODULE, | ||
4953 | .info = {"AWE Midi Emu", 0, 0, SNDCARD_SB}, | ||
4954 | .in_info = {0}, | ||
4955 | .open = awe_midi_open, /*open*/ | ||
4956 | .close = awe_midi_close, /*close*/ | ||
4957 | .ioctl = awe_midi_ioctl, /*ioctl*/ | ||
4958 | .outputc = awe_midi_outputc, /*outputc*/ | ||
4959 | }; | ||
4960 | |||
4961 | static int my_mididev = -1; | ||
4962 | |||
4963 | static void __init attach_midiemu(void) | ||
4964 | { | ||
4965 | if ((my_mididev = sound_alloc_mididev()) < 0) | ||
4966 | printk ("Sound: Too many midi devices detected\n"); | ||
4967 | else | ||
4968 | midi_devs[my_mididev] = &awe_midi_operations; | ||
4969 | } | ||
4970 | |||
4971 | static void unload_midiemu(void) | ||
4972 | { | ||
4973 | if (my_mididev >= 0) | ||
4974 | sound_unload_mididev(my_mididev); | ||
4975 | } | ||
4976 | |||
4977 | |||
4978 | /* | ||
4979 | * open/close midi device | ||
4980 | */ | ||
4981 | |||
4982 | static int midi_opened = FALSE; | ||
4983 | |||
4984 | static int midi_mode; | ||
4985 | static int coarsetune, finetune; | ||
4986 | |||
4987 | static int xg_mapping = TRUE; | ||
4988 | static int xg_bankmode; | ||
4989 | |||
4990 | /* effect sensitivity */ | ||
4991 | |||
4992 | #define FX_CUTOFF 0 | ||
4993 | #define FX_RESONANCE 1 | ||
4994 | #define FX_ATTACK 2 | ||
4995 | #define FX_RELEASE 3 | ||
4996 | #define FX_VIBRATE 4 | ||
4997 | #define FX_VIBDEPTH 5 | ||
4998 | #define FX_VIBDELAY 6 | ||
4999 | #define FX_NUMS 7 | ||
5000 | |||
5001 | #define DEF_FX_CUTOFF 170 | ||
5002 | #define DEF_FX_RESONANCE 6 | ||
5003 | #define DEF_FX_ATTACK 50 | ||
5004 | #define DEF_FX_RELEASE 50 | ||
5005 | #define DEF_FX_VIBRATE 30 | ||
5006 | #define DEF_FX_VIBDEPTH 4 | ||
5007 | #define DEF_FX_VIBDELAY 1500 | ||
5008 | |||
5009 | /* effect sense: */ | ||
5010 | static int gs_sense[] = | ||
5011 | { | ||
5012 | DEF_FX_CUTOFF, DEF_FX_RESONANCE, DEF_FX_ATTACK, DEF_FX_RELEASE, | ||
5013 | DEF_FX_VIBRATE, DEF_FX_VIBDEPTH, DEF_FX_VIBDELAY | ||
5014 | }; | ||
5015 | static int xg_sense[] = | ||
5016 | { | ||
5017 | DEF_FX_CUTOFF, DEF_FX_RESONANCE, DEF_FX_ATTACK, DEF_FX_RELEASE, | ||
5018 | DEF_FX_VIBRATE, DEF_FX_VIBDEPTH, DEF_FX_VIBDELAY | ||
5019 | }; | ||
5020 | |||
5021 | |||
5022 | /* current status */ | ||
5023 | static MidiStatus curst; | ||
5024 | |||
5025 | |||
5026 | static int | ||
5027 | awe_midi_open (int dev, int mode, | ||
5028 | void (*input)(int,unsigned char), | ||
5029 | void (*output)(int)) | ||
5030 | { | ||
5031 | if (midi_opened) | ||
5032 | return -EBUSY; | ||
5033 | |||
5034 | midi_opened = TRUE; | ||
5035 | |||
5036 | midi_mode = MODE_GM; | ||
5037 | |||
5038 | curst.queue = Q_NONE; | ||
5039 | curst.qlen = 0; | ||
5040 | curst.read = 0; | ||
5041 | curst.status = 0; | ||
5042 | curst.chan = 0; | ||
5043 | memset(curst.buf, 0, sizeof(curst.buf)); | ||
5044 | |||
5045 | init_midi_status(&curst); | ||
5046 | |||
5047 | return 0; | ||
5048 | } | ||
5049 | |||
5050 | static void | ||
5051 | awe_midi_close (int dev) | ||
5052 | { | ||
5053 | midi_opened = FALSE; | ||
5054 | } | ||
5055 | |||
5056 | |||
5057 | static int | ||
5058 | awe_midi_ioctl (int dev, unsigned cmd, void __user *arg) | ||
5059 | { | ||
5060 | return -EPERM; | ||
5061 | } | ||
5062 | |||
5063 | static int | ||
5064 | awe_midi_outputc (int dev, unsigned char midi_byte) | ||
5065 | { | ||
5066 | if (! midi_opened) | ||
5067 | return 1; | ||
5068 | |||
5069 | /* force to change playing mode */ | ||
5070 | playing_mode = AWE_PLAY_MULTI; | ||
5071 | |||
5072 | get_midi_char(&curst, midi_byte); | ||
5073 | return 1; | ||
5074 | } | ||
5075 | |||
5076 | |||
5077 | /* | ||
5078 | * initialize | ||
5079 | */ | ||
5080 | |||
5081 | static void init_midi_status(MidiStatus *st) | ||
5082 | { | ||
5083 | clear_rpn(); | ||
5084 | coarsetune = 0; | ||
5085 | finetune = 0; | ||
5086 | } | ||
5087 | |||
5088 | |||
5089 | /* | ||
5090 | * RPN & NRPN | ||
5091 | */ | ||
5092 | |||
5093 | #define MAX_MIDI_CHANNELS 16 | ||
5094 | |||
5095 | /* RPN & NRPN */ | ||
5096 | static unsigned char nrpn[MAX_MIDI_CHANNELS]; /* current event is NRPN? */ | ||
5097 | static int msb_bit; /* current event is msb for RPN/NRPN */ | ||
5098 | /* RPN & NRPN indeces */ | ||
5099 | static unsigned char rpn_msb[MAX_MIDI_CHANNELS], rpn_lsb[MAX_MIDI_CHANNELS]; | ||
5100 | /* RPN & NRPN values */ | ||
5101 | static int rpn_val[MAX_MIDI_CHANNELS]; | ||
5102 | |||
5103 | static void clear_rpn(void) | ||
5104 | { | ||
5105 | int i; | ||
5106 | for (i = 0; i < MAX_MIDI_CHANNELS; i++) { | ||
5107 | nrpn[i] = 0; | ||
5108 | rpn_msb[i] = 127; | ||
5109 | rpn_lsb[i] = 127; | ||
5110 | rpn_val[i] = 0; | ||
5111 | } | ||
5112 | msb_bit = 0; | ||
5113 | } | ||
5114 | |||
5115 | |||
5116 | /* | ||
5117 | * process midi queue | ||
5118 | */ | ||
5119 | |||
5120 | /* status event types */ | ||
5121 | typedef void (*StatusEvent)(MidiStatus *st); | ||
5122 | static struct StatusEventList { | ||
5123 | StatusEvent process; | ||
5124 | int qlen; | ||
5125 | } status_event[8] = { | ||
5126 | {midi_note_off, 2}, | ||
5127 | {midi_note_on, 2}, | ||
5128 | {midi_key_pressure, 2}, | ||
5129 | {midi_control_change, 2}, | ||
5130 | {midi_program_change, 1}, | ||
5131 | {midi_channel_pressure, 1}, | ||
5132 | {midi_pitch_wheel, 2}, | ||
5133 | {NULL, 0}, | ||
5134 | }; | ||
5135 | |||
5136 | |||
5137 | /* read a char from fifo and process it */ | ||
5138 | static void get_midi_char(MidiStatus *st, int c) | ||
5139 | { | ||
5140 | if (c == 0xfe) { | ||
5141 | /* ignore active sense */ | ||
5142 | st->queue = Q_NONE; | ||
5143 | return; | ||
5144 | } | ||
5145 | |||
5146 | switch (st->queue) { | ||
5147 | /* case Q_VARLEN: queue_varlen(st, c); break;*/ | ||
5148 | case Q_READ: | ||
5149 | case Q_SYSEX: | ||
5150 | queue_read(st, c); | ||
5151 | break; | ||
5152 | case Q_NONE: | ||
5153 | st->read = 0; | ||
5154 | if ((c & 0xf0) == 0xf0) { | ||
5155 | special_event(st, c); | ||
5156 | } else if (c & 0x80) { /* status change */ | ||
5157 | st->status = (c >> 4) & 0x07; | ||
5158 | st->chan = c & 0x0f; | ||
5159 | st->queue = Q_READ; | ||
5160 | st->qlen = status_event[st->status].qlen; | ||
5161 | if (st->qlen == 0) | ||
5162 | st->queue = Q_NONE; | ||
5163 | } | ||
5164 | break; | ||
5165 | } | ||
5166 | } | ||
5167 | |||
5168 | /* 0xfx events */ | ||
5169 | static void special_event(MidiStatus *st, int c) | ||
5170 | { | ||
5171 | switch (c) { | ||
5172 | case 0xf0: /* system exclusive */ | ||
5173 | st->queue = Q_SYSEX; | ||
5174 | st->qlen = 0; | ||
5175 | break; | ||
5176 | case 0xf1: /* MTC quarter frame */ | ||
5177 | case 0xf3: /* song select */ | ||
5178 | st->queue = Q_READ; | ||
5179 | st->qlen = 1; | ||
5180 | break; | ||
5181 | case 0xf2: /* song position */ | ||
5182 | st->queue = Q_READ; | ||
5183 | st->qlen = 2; | ||
5184 | break; | ||
5185 | } | ||
5186 | } | ||
5187 | |||
5188 | #if 0 | ||
5189 | /* read variable length value */ | ||
5190 | static void queue_varlen(MidiStatus *st, int c) | ||
5191 | { | ||
5192 | st->qlen += (c & 0x7f); | ||
5193 | if (c & 0x80) { | ||
5194 | st->qlen <<= 7; | ||
5195 | return; | ||
5196 | } | ||
5197 | if (st->qlen <= 0) { | ||
5198 | st->qlen = 0; | ||
5199 | st->queue = Q_NONE; | ||
5200 | } | ||
5201 | st->queue = Q_READ; | ||
5202 | st->read = 0; | ||
5203 | } | ||
5204 | #endif | ||
5205 | |||
5206 | |||
5207 | /* read a char */ | ||
5208 | static void queue_read(MidiStatus *st, int c) | ||
5209 | { | ||
5210 | if (st->read < MAX_MIDIBUF) { | ||
5211 | if (st->queue != Q_SYSEX) | ||
5212 | c &= 0x7f; | ||
5213 | st->buf[st->read] = (unsigned char)c; | ||
5214 | } | ||
5215 | st->read++; | ||
5216 | if (st->queue == Q_SYSEX && c == 0xf7) { | ||
5217 | midi_system_exclusive(st); | ||
5218 | st->queue = Q_NONE; | ||
5219 | } else if (st->queue == Q_READ && st->read >= st->qlen) { | ||
5220 | if (status_event[st->status].process) | ||
5221 | status_event[st->status].process(st); | ||
5222 | st->queue = Q_NONE; | ||
5223 | } | ||
5224 | } | ||
5225 | |||
5226 | |||
5227 | /* | ||
5228 | * status events | ||
5229 | */ | ||
5230 | |||
5231 | /* note on */ | ||
5232 | static void midi_note_on(MidiStatus *st) | ||
5233 | { | ||
5234 | DEBUG(2,printk("midi: note_on (%d) %d %d\n", st->chan, st->buf[0], st->buf[1])); | ||
5235 | if (st->buf[1] == 0) | ||
5236 | midi_note_off(st); | ||
5237 | else | ||
5238 | awe_start_note(0, st->chan, st->buf[0], st->buf[1]); | ||
5239 | } | ||
5240 | |||
5241 | /* note off */ | ||
5242 | static void midi_note_off(MidiStatus *st) | ||
5243 | { | ||
5244 | DEBUG(2,printk("midi: note_off (%d) %d %d\n", st->chan, st->buf[0], st->buf[1])); | ||
5245 | awe_kill_note(0, st->chan, st->buf[0], st->buf[1]); | ||
5246 | } | ||
5247 | |||
5248 | /* key pressure change */ | ||
5249 | static void midi_key_pressure(MidiStatus *st) | ||
5250 | { | ||
5251 | awe_key_pressure(0, st->chan, st->buf[0], st->buf[1]); | ||
5252 | } | ||
5253 | |||
5254 | /* channel pressure change */ | ||
5255 | static void midi_channel_pressure(MidiStatus *st) | ||
5256 | { | ||
5257 | channels[st->chan].chan_press = st->buf[0]; | ||
5258 | awe_modwheel_change(st->chan, st->buf[0]); | ||
5259 | } | ||
5260 | |||
5261 | /* pitch wheel change */ | ||
5262 | static void midi_pitch_wheel(MidiStatus *st) | ||
5263 | { | ||
5264 | int val = (int)st->buf[1] * 128 + st->buf[0]; | ||
5265 | awe_bender(0, st->chan, val); | ||
5266 | } | ||
5267 | |||
5268 | /* program change */ | ||
5269 | static void midi_program_change(MidiStatus *st) | ||
5270 | { | ||
5271 | int preset; | ||
5272 | preset = st->buf[0]; | ||
5273 | if (midi_mode == MODE_GS && IS_DRUM_CHANNEL(st->chan) && preset == 127) | ||
5274 | preset = 0; | ||
5275 | else if (midi_mode == MODE_XG && xg_mapping && IS_DRUM_CHANNEL(st->chan)) | ||
5276 | preset += 64; | ||
5277 | |||
5278 | awe_set_instr(0, st->chan, preset); | ||
5279 | } | ||
5280 | |||
5281 | #define send_effect(chan,type,val) awe_send_effect(chan,-1,type,val) | ||
5282 | #define add_effect(chan,type,val) awe_send_effect(chan,-1,(type)|0x80,val) | ||
5283 | #define unset_effect(chan,type) awe_send_effect(chan,-1,(type)|0x40,0) | ||
5284 | |||
5285 | /* midi control change */ | ||
5286 | static void midi_control_change(MidiStatus *st) | ||
5287 | { | ||
5288 | int cmd = st->buf[0]; | ||
5289 | int val = st->buf[1]; | ||
5290 | |||
5291 | DEBUG(2,printk("midi: control (%d) %d %d\n", st->chan, cmd, val)); | ||
5292 | if (midi_mode == MODE_XG) { | ||
5293 | if (xg_control_change(st, cmd, val)) | ||
5294 | return; | ||
5295 | } | ||
5296 | |||
5297 | /* controls #31 - #64 are LSB of #0 - #31 */ | ||
5298 | msb_bit = 1; | ||
5299 | if (cmd >= 0x20 && cmd < 0x40) { | ||
5300 | msb_bit = 0; | ||
5301 | cmd -= 0x20; | ||
5302 | } | ||
5303 | |||
5304 | switch (cmd) { | ||
5305 | case CTL_SOFT_PEDAL: | ||
5306 | if (val == 127) | ||
5307 | add_effect(st->chan, AWE_FX_CUTOFF, -160); | ||
5308 | else | ||
5309 | unset_effect(st->chan, AWE_FX_CUTOFF); | ||
5310 | break; | ||
5311 | |||
5312 | case CTL_BANK_SELECT: | ||
5313 | midi_select_bank(st, val); | ||
5314 | break; | ||
5315 | |||
5316 | /* set RPN/NRPN parameter */ | ||
5317 | case CTL_REGIST_PARM_NUM_MSB: | ||
5318 | nrpn[st->chan]=0; rpn_msb[st->chan]=val; | ||
5319 | break; | ||
5320 | case CTL_REGIST_PARM_NUM_LSB: | ||
5321 | nrpn[st->chan]=0; rpn_lsb[st->chan]=val; | ||
5322 | break; | ||
5323 | case CTL_NONREG_PARM_NUM_MSB: | ||
5324 | nrpn[st->chan]=1; rpn_msb[st->chan]=val; | ||
5325 | break; | ||
5326 | case CTL_NONREG_PARM_NUM_LSB: | ||
5327 | nrpn[st->chan]=1; rpn_lsb[st->chan]=val; | ||
5328 | break; | ||
5329 | |||
5330 | /* send RPN/NRPN entry */ | ||
5331 | case CTL_DATA_ENTRY: | ||
5332 | if (msb_bit) | ||
5333 | rpn_val[st->chan] = val * 128; | ||
5334 | else | ||
5335 | rpn_val[st->chan] |= val; | ||
5336 | if (nrpn[st->chan]) | ||
5337 | midi_nrpn_event(st); | ||
5338 | else | ||
5339 | midi_rpn_event(st); | ||
5340 | break; | ||
5341 | |||
5342 | /* increase/decrease data entry */ | ||
5343 | case CTL_DATA_INCREMENT: | ||
5344 | rpn_val[st->chan]++; | ||
5345 | midi_rpn_event(st); | ||
5346 | break; | ||
5347 | case CTL_DATA_DECREMENT: | ||
5348 | rpn_val[st->chan]--; | ||
5349 | midi_rpn_event(st); | ||
5350 | break; | ||
5351 | |||
5352 | /* default */ | ||
5353 | default: | ||
5354 | awe_controller(0, st->chan, cmd, val); | ||
5355 | break; | ||
5356 | } | ||
5357 | } | ||
5358 | |||
5359 | /* tone bank change */ | ||
5360 | static void midi_select_bank(MidiStatus *st, int val) | ||
5361 | { | ||
5362 | if (midi_mode == MODE_XG && msb_bit) { | ||
5363 | xg_bankmode = val; | ||
5364 | /* XG MSB value; not normal bank selection */ | ||
5365 | switch (val) { | ||
5366 | case 127: /* remap to drum channel */ | ||
5367 | awe_controller(0, st->chan, CTL_BANK_SELECT, 128); | ||
5368 | break; | ||
5369 | default: /* remap to normal channel */ | ||
5370 | awe_controller(0, st->chan, CTL_BANK_SELECT, val); | ||
5371 | break; | ||
5372 | } | ||
5373 | return; | ||
5374 | } else if (midi_mode == MODE_GS && !msb_bit) | ||
5375 | /* ignore LSB bank in GS mode (used for mapping) */ | ||
5376 | return; | ||
5377 | |||
5378 | /* normal bank controls; accept both MSB and LSB */ | ||
5379 | if (! IS_DRUM_CHANNEL(st->chan)) { | ||
5380 | if (midi_mode == MODE_XG) { | ||
5381 | if (xg_bankmode) return; | ||
5382 | if (val == 64 || val == 126) | ||
5383 | val = 0; | ||
5384 | } else if (midi_mode == MODE_GS && val == 127) | ||
5385 | val = 0; | ||
5386 | awe_controller(0, st->chan, CTL_BANK_SELECT, val); | ||
5387 | } | ||
5388 | } | ||
5389 | |||
5390 | |||
5391 | /* | ||
5392 | * RPN events | ||
5393 | */ | ||
5394 | |||
5395 | static void midi_rpn_event(MidiStatus *st) | ||
5396 | { | ||
5397 | int type; | ||
5398 | type = (rpn_msb[st->chan]<<8) | rpn_lsb[st->chan]; | ||
5399 | switch (type) { | ||
5400 | case 0x0000: /* Pitch bend sensitivity */ | ||
5401 | /* MSB only / 1 semitone per 128 */ | ||
5402 | if (msb_bit) { | ||
5403 | channels[st->chan].bender_range = | ||
5404 | rpn_val[st->chan] * 100 / 128; | ||
5405 | } | ||
5406 | break; | ||
5407 | |||
5408 | case 0x0001: /* fine tuning: */ | ||
5409 | /* MSB/LSB, 8192=center, 100/8192 cent step */ | ||
5410 | finetune = rpn_val[st->chan] - 8192; | ||
5411 | midi_detune(st->chan, coarsetune, finetune); | ||
5412 | break; | ||
5413 | |||
5414 | case 0x0002: /* coarse tuning */ | ||
5415 | /* MSB only / 8192=center, 1 semitone per 128 */ | ||
5416 | if (msb_bit) { | ||
5417 | coarsetune = rpn_val[st->chan] - 8192; | ||
5418 | midi_detune(st->chan, coarsetune, finetune); | ||
5419 | } | ||
5420 | break; | ||
5421 | |||
5422 | case 0x7F7F: /* "lock-in" RPN */ | ||
5423 | break; | ||
5424 | } | ||
5425 | } | ||
5426 | |||
5427 | |||
5428 | /* tuning: | ||
5429 | * coarse = -8192 to 8192 (100 cent per 128) | ||
5430 | * fine = -8192 to 8192 (max=100cent) | ||
5431 | */ | ||
5432 | static void midi_detune(int chan, int coarse, int fine) | ||
5433 | { | ||
5434 | /* 4096 = 1200 cents in AWE parameter */ | ||
5435 | int val; | ||
5436 | val = coarse * 4096 / (12 * 128); | ||
5437 | val += fine / 24; | ||
5438 | if (val) | ||
5439 | send_effect(chan, AWE_FX_INIT_PITCH, val); | ||
5440 | else | ||
5441 | unset_effect(chan, AWE_FX_INIT_PITCH); | ||
5442 | } | ||
5443 | |||
5444 | |||
5445 | /* | ||
5446 | * system exclusive message | ||
5447 | * GM/GS/XG macros are accepted | ||
5448 | */ | ||
5449 | |||
5450 | static void midi_system_exclusive(MidiStatus *st) | ||
5451 | { | ||
5452 | /* GM on */ | ||
5453 | static unsigned char gm_on_macro[] = { | ||
5454 | 0x7e,0x7f,0x09,0x01, | ||
5455 | }; | ||
5456 | /* XG on */ | ||
5457 | static unsigned char xg_on_macro[] = { | ||
5458 | 0x43,0x10,0x4c,0x00,0x00,0x7e,0x00, | ||
5459 | }; | ||
5460 | /* GS prefix | ||
5461 | * drum channel: XX=0x1?(channel), YY=0x15, ZZ=on/off | ||
5462 | * reverb mode: XX=0x01, YY=0x30, ZZ=0-7 | ||
5463 | * chorus mode: XX=0x01, YY=0x38, ZZ=0-7 | ||
5464 | */ | ||
5465 | static unsigned char gs_pfx_macro[] = { | ||
5466 | 0x41,0x10,0x42,0x12,0x40,/*XX,YY,ZZ*/ | ||
5467 | }; | ||
5468 | |||
5469 | #if 0 | ||
5470 | /* SC88 system mode set | ||
5471 | * single module mode: XX=1 | ||
5472 | * double module mode: XX=0 | ||
5473 | */ | ||
5474 | static unsigned char gs_mode_macro[] = { | ||
5475 | 0x41,0x10,0x42,0x12,0x00,0x00,0x7F,/*ZZ*/ | ||
5476 | }; | ||
5477 | /* SC88 display macro: XX=01:bitmap, 00:text | ||
5478 | */ | ||
5479 | static unsigned char gs_disp_macro[] = { | ||
5480 | 0x41,0x10,0x45,0x12,0x10,/*XX,00*/ | ||
5481 | }; | ||
5482 | #endif | ||
5483 | |||
5484 | /* GM on */ | ||
5485 | if (memcmp(st->buf, gm_on_macro, sizeof(gm_on_macro)) == 0) { | ||
5486 | if (midi_mode != MODE_GS && midi_mode != MODE_XG) | ||
5487 | midi_mode = MODE_GM; | ||
5488 | init_midi_status(st); | ||
5489 | } | ||
5490 | |||
5491 | /* GS macros */ | ||
5492 | else if (memcmp(st->buf, gs_pfx_macro, sizeof(gs_pfx_macro)) == 0) { | ||
5493 | if (midi_mode != MODE_GS && midi_mode != MODE_XG) | ||
5494 | midi_mode = MODE_GS; | ||
5495 | |||
5496 | if (st->buf[5] == 0x00 && st->buf[6] == 0x7f && st->buf[7] == 0x00) { | ||
5497 | /* GS reset */ | ||
5498 | init_midi_status(st); | ||
5499 | } | ||
5500 | |||
5501 | else if ((st->buf[5] & 0xf0) == 0x10 && st->buf[6] == 0x15) { | ||
5502 | /* drum pattern */ | ||
5503 | int p = st->buf[5] & 0x0f; | ||
5504 | if (p == 0) p = 9; | ||
5505 | else if (p < 10) p--; | ||
5506 | if (st->buf[7] == 0) | ||
5507 | DRUM_CHANNEL_OFF(p); | ||
5508 | else | ||
5509 | DRUM_CHANNEL_ON(p); | ||
5510 | |||
5511 | } else if ((st->buf[5] & 0xf0) == 0x10 && st->buf[6] == 0x21) { | ||
5512 | /* program */ | ||
5513 | int p = st->buf[5] & 0x0f; | ||
5514 | if (p == 0) p = 9; | ||
5515 | else if (p < 10) p--; | ||
5516 | if (! IS_DRUM_CHANNEL(p)) | ||
5517 | awe_set_instr(0, p, st->buf[7]); | ||
5518 | |||
5519 | } else if (st->buf[5] == 0x01 && st->buf[6] == 0x30) { | ||
5520 | /* reverb mode */ | ||
5521 | awe_set_reverb_mode(st->buf[7]); | ||
5522 | |||
5523 | } else if (st->buf[5] == 0x01 && st->buf[6] == 0x38) { | ||
5524 | /* chorus mode */ | ||
5525 | awe_set_chorus_mode(st->buf[7]); | ||
5526 | |||
5527 | } else if (st->buf[5] == 0x00 && st->buf[6] == 0x04) { | ||
5528 | /* master volume */ | ||
5529 | awe_change_master_volume(st->buf[7]); | ||
5530 | |||
5531 | } | ||
5532 | } | ||
5533 | |||
5534 | /* XG on */ | ||
5535 | else if (memcmp(st->buf, xg_on_macro, sizeof(xg_on_macro)) == 0) { | ||
5536 | midi_mode = MODE_XG; | ||
5537 | xg_mapping = TRUE; | ||
5538 | xg_bankmode = 0; | ||
5539 | } | ||
5540 | } | ||
5541 | |||
5542 | |||
5543 | /*----------------------------------------------------------------*/ | ||
5544 | |||
5545 | /* | ||
5546 | * convert NRPN/control values | ||
5547 | */ | ||
5548 | |||
5549 | static int send_converted_effect(ConvTable *table, int num_tables, MidiStatus *st, int type, int val) | ||
5550 | { | ||
5551 | int i, cval; | ||
5552 | for (i = 0; i < num_tables; i++) { | ||
5553 | if (table[i].control == type) { | ||
5554 | cval = table[i].convert(val); | ||
5555 | send_effect(st->chan, table[i].awe_effect, cval); | ||
5556 | return TRUE; | ||
5557 | } | ||
5558 | } | ||
5559 | return FALSE; | ||
5560 | } | ||
5561 | |||
5562 | static int add_converted_effect(ConvTable *table, int num_tables, MidiStatus *st, int type, int val) | ||
5563 | { | ||
5564 | int i, cval; | ||
5565 | for (i = 0; i < num_tables; i++) { | ||
5566 | if (table[i].control == type) { | ||
5567 | cval = table[i].convert(val); | ||
5568 | add_effect(st->chan, table[i].awe_effect|0x80, cval); | ||
5569 | return TRUE; | ||
5570 | } | ||
5571 | } | ||
5572 | return FALSE; | ||
5573 | } | ||
5574 | |||
5575 | |||
5576 | /* | ||
5577 | * AWE32 NRPN effects | ||
5578 | */ | ||
5579 | |||
5580 | static unsigned short fx_delay(int val); | ||
5581 | static unsigned short fx_attack(int val); | ||
5582 | static unsigned short fx_hold(int val); | ||
5583 | static unsigned short fx_decay(int val); | ||
5584 | static unsigned short fx_the_value(int val); | ||
5585 | static unsigned short fx_twice_value(int val); | ||
5586 | static unsigned short fx_conv_pitch(int val); | ||
5587 | static unsigned short fx_conv_Q(int val); | ||
5588 | |||
5589 | /* function for each NRPN */ /* [range] units */ | ||
5590 | #define fx_env1_delay fx_delay /* [0,5900] 4msec */ | ||
5591 | #define fx_env1_attack fx_attack /* [0,5940] 1msec */ | ||
5592 | #define fx_env1_hold fx_hold /* [0,8191] 1msec */ | ||
5593 | #define fx_env1_decay fx_decay /* [0,5940] 4msec */ | ||
5594 | #define fx_env1_release fx_decay /* [0,5940] 4msec */ | ||
5595 | #define fx_env1_sustain fx_the_value /* [0,127] 0.75dB */ | ||
5596 | #define fx_env1_pitch fx_the_value /* [-127,127] 9.375cents */ | ||
5597 | #define fx_env1_cutoff fx_the_value /* [-127,127] 56.25cents */ | ||
5598 | |||
5599 | #define fx_env2_delay fx_delay /* [0,5900] 4msec */ | ||
5600 | #define fx_env2_attack fx_attack /* [0,5940] 1msec */ | ||
5601 | #define fx_env2_hold fx_hold /* [0,8191] 1msec */ | ||
5602 | #define fx_env2_decay fx_decay /* [0,5940] 4msec */ | ||
5603 | #define fx_env2_release fx_decay /* [0,5940] 4msec */ | ||
5604 | #define fx_env2_sustain fx_the_value /* [0,127] 0.75dB */ | ||
5605 | |||
5606 | #define fx_lfo1_delay fx_delay /* [0,5900] 4msec */ | ||
5607 | #define fx_lfo1_freq fx_twice_value /* [0,127] 84mHz */ | ||
5608 | #define fx_lfo1_volume fx_twice_value /* [0,127] 0.1875dB */ | ||
5609 | #define fx_lfo1_pitch fx_the_value /* [-127,127] 9.375cents */ | ||
5610 | #define fx_lfo1_cutoff fx_twice_value /* [-64,63] 56.25cents */ | ||
5611 | |||
5612 | #define fx_lfo2_delay fx_delay /* [0,5900] 4msec */ | ||
5613 | #define fx_lfo2_freq fx_twice_value /* [0,127] 84mHz */ | ||
5614 | #define fx_lfo2_pitch fx_the_value /* [-127,127] 9.375cents */ | ||
5615 | |||
5616 | #define fx_init_pitch fx_conv_pitch /* [-8192,8192] cents */ | ||
5617 | #define fx_chorus fx_the_value /* [0,255] -- */ | ||
5618 | #define fx_reverb fx_the_value /* [0,255] -- */ | ||
5619 | #define fx_cutoff fx_twice_value /* [0,127] 62Hz */ | ||
5620 | #define fx_filterQ fx_conv_Q /* [0,127] -- */ | ||
5621 | |||
5622 | static unsigned short fx_delay(int val) | ||
5623 | { | ||
5624 | return (unsigned short)calc_parm_delay(val); | ||
5625 | } | ||
5626 | |||
5627 | static unsigned short fx_attack(int val) | ||
5628 | { | ||
5629 | return (unsigned short)calc_parm_attack(val); | ||
5630 | } | ||
5631 | |||
5632 | static unsigned short fx_hold(int val) | ||
5633 | { | ||
5634 | return (unsigned short)calc_parm_hold(val); | ||
5635 | } | ||
5636 | |||
5637 | static unsigned short fx_decay(int val) | ||
5638 | { | ||
5639 | return (unsigned short)calc_parm_decay(val); | ||
5640 | } | ||
5641 | |||
5642 | static unsigned short fx_the_value(int val) | ||
5643 | { | ||
5644 | return (unsigned short)(val & 0xff); | ||
5645 | } | ||
5646 | |||
5647 | static unsigned short fx_twice_value(int val) | ||
5648 | { | ||
5649 | return (unsigned short)((val * 2) & 0xff); | ||
5650 | } | ||
5651 | |||
5652 | static unsigned short fx_conv_pitch(int val) | ||
5653 | { | ||
5654 | return (short)(val * 4096 / 1200); | ||
5655 | } | ||
5656 | |||
5657 | static unsigned short fx_conv_Q(int val) | ||
5658 | { | ||
5659 | return (unsigned short)((val / 8) & 0xff); | ||
5660 | } | ||
5661 | |||
5662 | |||
5663 | static ConvTable awe_effects[] = | ||
5664 | { | ||
5665 | { 0, AWE_FX_LFO1_DELAY, fx_lfo1_delay}, | ||
5666 | { 1, AWE_FX_LFO1_FREQ, fx_lfo1_freq}, | ||
5667 | { 2, AWE_FX_LFO2_DELAY, fx_lfo2_delay}, | ||
5668 | { 3, AWE_FX_LFO2_FREQ, fx_lfo2_freq}, | ||
5669 | |||
5670 | { 4, AWE_FX_ENV1_DELAY, fx_env1_delay}, | ||
5671 | { 5, AWE_FX_ENV1_ATTACK,fx_env1_attack}, | ||
5672 | { 6, AWE_FX_ENV1_HOLD, fx_env1_hold}, | ||
5673 | { 7, AWE_FX_ENV1_DECAY, fx_env1_decay}, | ||
5674 | { 8, AWE_FX_ENV1_SUSTAIN, fx_env1_sustain}, | ||
5675 | { 9, AWE_FX_ENV1_RELEASE, fx_env1_release}, | ||
5676 | |||
5677 | {10, AWE_FX_ENV2_DELAY, fx_env2_delay}, | ||
5678 | {11, AWE_FX_ENV2_ATTACK, fx_env2_attack}, | ||
5679 | {12, AWE_FX_ENV2_HOLD, fx_env2_hold}, | ||
5680 | {13, AWE_FX_ENV2_DECAY, fx_env2_decay}, | ||
5681 | {14, AWE_FX_ENV2_SUSTAIN, fx_env2_sustain}, | ||
5682 | {15, AWE_FX_ENV2_RELEASE, fx_env2_release}, | ||
5683 | |||
5684 | {16, AWE_FX_INIT_PITCH, fx_init_pitch}, | ||
5685 | {17, AWE_FX_LFO1_PITCH, fx_lfo1_pitch}, | ||
5686 | {18, AWE_FX_LFO2_PITCH, fx_lfo2_pitch}, | ||
5687 | {19, AWE_FX_ENV1_PITCH, fx_env1_pitch}, | ||
5688 | {20, AWE_FX_LFO1_VOLUME, fx_lfo1_volume}, | ||
5689 | {21, AWE_FX_CUTOFF, fx_cutoff}, | ||
5690 | {22, AWE_FX_FILTERQ, fx_filterQ}, | ||
5691 | {23, AWE_FX_LFO1_CUTOFF, fx_lfo1_cutoff}, | ||
5692 | {24, AWE_FX_ENV1_CUTOFF, fx_env1_cutoff}, | ||
5693 | {25, AWE_FX_CHORUS, fx_chorus}, | ||
5694 | {26, AWE_FX_REVERB, fx_reverb}, | ||
5695 | }; | ||
5696 | |||
5697 | static int num_awe_effects = numberof(awe_effects); | ||
5698 | |||
5699 | |||
5700 | /* | ||
5701 | * GS(SC88) NRPN effects; still experimental | ||
5702 | */ | ||
5703 | |||
5704 | /* cutoff: quarter semitone step, max=255 */ | ||
5705 | static unsigned short gs_cutoff(int val) | ||
5706 | { | ||
5707 | return (val - 64) * gs_sense[FX_CUTOFF] / 50; | ||
5708 | } | ||
5709 | |||
5710 | /* resonance: 0 to 15(max) */ | ||
5711 | static unsigned short gs_filterQ(int val) | ||
5712 | { | ||
5713 | return (val - 64) * gs_sense[FX_RESONANCE] / 50; | ||
5714 | } | ||
5715 | |||
5716 | /* attack: */ | ||
5717 | static unsigned short gs_attack(int val) | ||
5718 | { | ||
5719 | return -(val - 64) * gs_sense[FX_ATTACK] / 50; | ||
5720 | } | ||
5721 | |||
5722 | /* decay: */ | ||
5723 | static unsigned short gs_decay(int val) | ||
5724 | { | ||
5725 | return -(val - 64) * gs_sense[FX_RELEASE] / 50; | ||
5726 | } | ||
5727 | |||
5728 | /* release: */ | ||
5729 | static unsigned short gs_release(int val) | ||
5730 | { | ||
5731 | return -(val - 64) * gs_sense[FX_RELEASE] / 50; | ||
5732 | } | ||
5733 | |||
5734 | /* vibrato freq: 0.042Hz step, max=255 */ | ||
5735 | static unsigned short gs_vib_rate(int val) | ||
5736 | { | ||
5737 | return (val - 64) * gs_sense[FX_VIBRATE] / 50; | ||
5738 | } | ||
5739 | |||
5740 | /* vibrato depth: max=127, 1 octave */ | ||
5741 | static unsigned short gs_vib_depth(int val) | ||
5742 | { | ||
5743 | return (val - 64) * gs_sense[FX_VIBDEPTH] / 50; | ||
5744 | } | ||
5745 | |||
5746 | /* vibrato delay: -0.725msec step */ | ||
5747 | static unsigned short gs_vib_delay(int val) | ||
5748 | { | ||
5749 | return -(val - 64) * gs_sense[FX_VIBDELAY] / 50; | ||
5750 | } | ||
5751 | |||
5752 | static ConvTable gs_effects[] = | ||
5753 | { | ||
5754 | {32, AWE_FX_CUTOFF, gs_cutoff}, | ||
5755 | {33, AWE_FX_FILTERQ, gs_filterQ}, | ||
5756 | {99, AWE_FX_ENV2_ATTACK, gs_attack}, | ||
5757 | {100, AWE_FX_ENV2_DECAY, gs_decay}, | ||
5758 | {102, AWE_FX_ENV2_RELEASE, gs_release}, | ||
5759 | {8, AWE_FX_LFO1_FREQ, gs_vib_rate}, | ||
5760 | {9, AWE_FX_LFO1_VOLUME, gs_vib_depth}, | ||
5761 | {10, AWE_FX_LFO1_DELAY, gs_vib_delay}, | ||
5762 | }; | ||
5763 | |||
5764 | static int num_gs_effects = numberof(gs_effects); | ||
5765 | |||
5766 | |||
5767 | /* | ||
5768 | * NRPN events: accept as AWE32/SC88 specific controls | ||
5769 | */ | ||
5770 | |||
5771 | static void midi_nrpn_event(MidiStatus *st) | ||
5772 | { | ||
5773 | if (rpn_msb[st->chan] == 127 && rpn_lsb[st->chan] <= 26) { | ||
5774 | if (! msb_bit) /* both MSB/LSB necessary */ | ||
5775 | send_converted_effect(awe_effects, num_awe_effects, | ||
5776 | st, rpn_lsb[st->chan], | ||
5777 | rpn_val[st->chan] - 8192); | ||
5778 | } else if (rpn_msb[st->chan] == 1) { | ||
5779 | if (msb_bit) /* only MSB is valid */ | ||
5780 | add_converted_effect(gs_effects, num_gs_effects, | ||
5781 | st, rpn_lsb[st->chan], | ||
5782 | rpn_val[st->chan] / 128); | ||
5783 | } | ||
5784 | } | ||
5785 | |||
5786 | |||
5787 | /* | ||
5788 | * XG control effects; still experimental | ||
5789 | */ | ||
5790 | |||
5791 | /* cutoff: quarter semitone step, max=255 */ | ||
5792 | static unsigned short xg_cutoff(int val) | ||
5793 | { | ||
5794 | return (val - 64) * xg_sense[FX_CUTOFF] / 64; | ||
5795 | } | ||
5796 | |||
5797 | /* resonance: 0(open) to 15(most nasal) */ | ||
5798 | static unsigned short xg_filterQ(int val) | ||
5799 | { | ||
5800 | return (val - 64) * xg_sense[FX_RESONANCE] / 64; | ||
5801 | } | ||
5802 | |||
5803 | /* attack: */ | ||
5804 | static unsigned short xg_attack(int val) | ||
5805 | { | ||
5806 | return -(val - 64) * xg_sense[FX_ATTACK] / 64; | ||
5807 | } | ||
5808 | |||
5809 | /* release: */ | ||
5810 | static unsigned short xg_release(int val) | ||
5811 | { | ||
5812 | return -(val - 64) * xg_sense[FX_RELEASE] / 64; | ||
5813 | } | ||
5814 | |||
5815 | static ConvTable xg_effects[] = | ||
5816 | { | ||
5817 | {71, AWE_FX_CUTOFF, xg_cutoff}, | ||
5818 | {74, AWE_FX_FILTERQ, xg_filterQ}, | ||
5819 | {72, AWE_FX_ENV2_RELEASE, xg_release}, | ||
5820 | {73, AWE_FX_ENV2_ATTACK, xg_attack}, | ||
5821 | }; | ||
5822 | |||
5823 | static int num_xg_effects = numberof(xg_effects); | ||
5824 | |||
5825 | static int xg_control_change(MidiStatus *st, int cmd, int val) | ||
5826 | { | ||
5827 | return add_converted_effect(xg_effects, num_xg_effects, st, cmd, val); | ||
5828 | } | ||
5829 | |||
5830 | #endif /* CONFIG_AWE32_MIDIEMU */ | ||
5831 | |||
5832 | |||
5833 | /*----------------------------------------------------------------*/ | ||
5834 | |||
5835 | |||
5836 | /* | ||
5837 | * initialization of AWE driver | ||
5838 | */ | ||
5839 | |||
5840 | static void | ||
5841 | awe_initialize(void) | ||
5842 | { | ||
5843 | DEBUG(0,printk("AWE32: initializing..\n")); | ||
5844 | |||
5845 | /* initialize hardware configuration */ | ||
5846 | awe_poke(AWE_HWCF1, 0x0059); | ||
5847 | awe_poke(AWE_HWCF2, 0x0020); | ||
5848 | |||
5849 | /* disable audio; this seems to reduce a clicking noise a bit.. */ | ||
5850 | awe_poke(AWE_HWCF3, 0); | ||
5851 | |||
5852 | /* initialize audio channels */ | ||
5853 | awe_init_audio(); | ||
5854 | |||
5855 | /* initialize DMA */ | ||
5856 | awe_init_dma(); | ||
5857 | |||
5858 | /* initialize init array */ | ||
5859 | awe_init_array(); | ||
5860 | |||
5861 | /* check DRAM memory size */ | ||
5862 | awe_check_dram(); | ||
5863 | |||
5864 | /* initialize the FM section of the AWE32 */ | ||
5865 | awe_init_fm(); | ||
5866 | |||
5867 | /* set up voice envelopes */ | ||
5868 | awe_tweak(); | ||
5869 | |||
5870 | /* enable audio */ | ||
5871 | awe_poke(AWE_HWCF3, 0x0004); | ||
5872 | |||
5873 | /* set default values */ | ||
5874 | awe_init_ctrl_parms(TRUE); | ||
5875 | |||
5876 | /* set equalizer */ | ||
5877 | awe_update_equalizer(); | ||
5878 | |||
5879 | /* set reverb & chorus modes */ | ||
5880 | awe_update_reverb_mode(); | ||
5881 | awe_update_chorus_mode(); | ||
5882 | } | ||
5883 | |||
5884 | |||
5885 | /* | ||
5886 | * Core Device Management Functions | ||
5887 | */ | ||
5888 | |||
5889 | /* store values to i/o port array */ | ||
5890 | static void setup_ports(int port1, int port2, int port3) | ||
5891 | { | ||
5892 | awe_ports[0] = port1; | ||
5893 | if (port2 == 0) | ||
5894 | port2 = port1 + 0x400; | ||
5895 | awe_ports[1] = port2; | ||
5896 | awe_ports[2] = port2 + 2; | ||
5897 | if (port3 == 0) | ||
5898 | port3 = port1 + 0x800; | ||
5899 | awe_ports[3] = port3; | ||
5900 | awe_ports[4] = port3 + 2; | ||
5901 | |||
5902 | port_setuped = TRUE; | ||
5903 | } | ||
5904 | |||
5905 | /* | ||
5906 | * port request | ||
5907 | * 0x620-623, 0xA20-A23, 0xE20-E23 | ||
5908 | */ | ||
5909 | |||
5910 | static int | ||
5911 | awe_request_region(void) | ||
5912 | { | ||
5913 | if (! port_setuped) | ||
5914 | return 0; | ||
5915 | if (! request_region(awe_ports[0], 4, "sound driver (AWE32)")) | ||
5916 | return 0; | ||
5917 | if (! request_region(awe_ports[1], 4, "sound driver (AWE32)")) | ||
5918 | goto err_out; | ||
5919 | if (! request_region(awe_ports[3], 4, "sound driver (AWE32)")) | ||
5920 | goto err_out1; | ||
5921 | return 1; | ||
5922 | err_out1: | ||
5923 | release_region(awe_ports[1], 4); | ||
5924 | err_out: | ||
5925 | release_region(awe_ports[0], 4); | ||
5926 | return 0; | ||
5927 | } | ||
5928 | |||
5929 | static void | ||
5930 | awe_release_region(void) | ||
5931 | { | ||
5932 | if (! port_setuped) return; | ||
5933 | release_region(awe_ports[0], 4); | ||
5934 | release_region(awe_ports[1], 4); | ||
5935 | release_region(awe_ports[3], 4); | ||
5936 | } | ||
5937 | |||
5938 | static int awe_attach_device(void) | ||
5939 | { | ||
5940 | if (awe_present) return 0; /* for OSS38.. called twice? */ | ||
5941 | |||
5942 | /* reserve I/O ports for awedrv */ | ||
5943 | if (! awe_request_region()) { | ||
5944 | printk(KERN_ERR "AWE32: I/O area already used.\n"); | ||
5945 | return 0; | ||
5946 | } | ||
5947 | |||
5948 | /* set buffers to NULL */ | ||
5949 | sfhead = sftail = NULL; | ||
5950 | |||
5951 | my_dev = sound_alloc_synthdev(); | ||
5952 | if (my_dev == -1) { | ||
5953 | printk(KERN_ERR "AWE32 Error: too many synthesizers\n"); | ||
5954 | awe_release_region(); | ||
5955 | return 0; | ||
5956 | } | ||
5957 | |||
5958 | voice_alloc = &awe_operations.alloc; | ||
5959 | voice_alloc->max_voice = awe_max_voices; | ||
5960 | synth_devs[my_dev] = &awe_operations; | ||
5961 | |||
5962 | #ifdef CONFIG_AWE32_MIXER | ||
5963 | attach_mixer(); | ||
5964 | #endif | ||
5965 | #ifdef CONFIG_AWE32_MIDIEMU | ||
5966 | attach_midiemu(); | ||
5967 | #endif | ||
5968 | |||
5969 | /* clear all samples */ | ||
5970 | awe_reset_samples(); | ||
5971 | |||
5972 | /* initialize AWE32 hardware */ | ||
5973 | awe_initialize(); | ||
5974 | |||
5975 | sprintf(awe_info.name, "AWE32-%s (RAM%dk)", | ||
5976 | AWEDRV_VERSION, memsize/1024); | ||
5977 | printk(KERN_INFO "<SoundBlaster EMU8000 (RAM%dk)>\n", memsize/1024); | ||
5978 | |||
5979 | awe_present = TRUE; | ||
5980 | |||
5981 | return 1; | ||
5982 | } | ||
5983 | |||
5984 | static void awe_dettach_device(void) | ||
5985 | { | ||
5986 | if (awe_present) { | ||
5987 | awe_reset_samples(); | ||
5988 | awe_release_region(); | ||
5989 | free_tables(); | ||
5990 | #ifdef CONFIG_AWE32_MIXER | ||
5991 | unload_mixer(); | ||
5992 | #endif | ||
5993 | #ifdef CONFIG_AWE32_MIDIEMU | ||
5994 | unload_midiemu(); | ||
5995 | #endif | ||
5996 | sound_unload_synthdev(my_dev); | ||
5997 | awe_present = FALSE; | ||
5998 | } | ||
5999 | } | ||
6000 | |||
6001 | |||
6002 | /* | ||
6003 | * Legacy device Probing | ||
6004 | */ | ||
6005 | |||
6006 | /* detect emu8000 chip on the specified address; from VV's guide */ | ||
6007 | |||
6008 | static int __init | ||
6009 | awe_detect_base(int addr) | ||
6010 | { | ||
6011 | setup_ports(addr, 0, 0); | ||
6012 | if ((awe_peek(AWE_U1) & 0x000F) != 0x000C) | ||
6013 | return 0; | ||
6014 | if ((awe_peek(AWE_HWCF1) & 0x007E) != 0x0058) | ||
6015 | return 0; | ||
6016 | if ((awe_peek(AWE_HWCF2) & 0x0003) != 0x0003) | ||
6017 | return 0; | ||
6018 | DEBUG(0,printk("AWE32 found at %x\n", addr)); | ||
6019 | return 1; | ||
6020 | } | ||
6021 | |||
6022 | static int __init awe_detect_legacy_devices(void) | ||
6023 | { | ||
6024 | int base; | ||
6025 | for (base = 0x620; base <= 0x680; base += 0x20) | ||
6026 | if (awe_detect_base(base)) { | ||
6027 | awe_attach_device(); | ||
6028 | return 1; | ||
6029 | } | ||
6030 | DEBUG(0,printk("AWE32 Legacy detection failed\n")); | ||
6031 | return 0; | ||
6032 | } | ||
6033 | |||
6034 | |||
6035 | /* | ||
6036 | * PnP device Probing | ||
6037 | */ | ||
6038 | |||
6039 | static struct pnp_device_id awe_pnp_ids[] = { | ||
6040 | {.id = "CTL0021", .driver_data = 0}, /* AWE32 WaveTable */ | ||
6041 | {.id = "CTL0022", .driver_data = 0}, /* AWE64 WaveTable */ | ||
6042 | {.id = "CTL0023", .driver_data = 0}, /* AWE64 Gold WaveTable */ | ||
6043 | { } /* terminator */ | ||
6044 | }; | ||
6045 | |||
6046 | MODULE_DEVICE_TABLE(pnp, awe_pnp_ids); | ||
6047 | |||
6048 | static int awe_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) | ||
6049 | { | ||
6050 | int io1, io2, io3; | ||
6051 | |||
6052 | if (awe_present) { | ||
6053 | printk(KERN_ERR "AWE32: This driver only supports one AWE32 device, skipping.\n"); | ||
6054 | } | ||
6055 | |||
6056 | if (!pnp_port_valid(dev,0) || | ||
6057 | !pnp_port_valid(dev,1) || | ||
6058 | !pnp_port_valid(dev,2)) { | ||
6059 | printk(KERN_ERR "AWE32: The PnP device does not have the required resources.\n"); | ||
6060 | return -EINVAL; | ||
6061 | } | ||
6062 | io1 = pnp_port_start(dev,0); | ||
6063 | io2 = pnp_port_start(dev,1); | ||
6064 | io3 = pnp_port_start(dev,2); | ||
6065 | printk(KERN_INFO "AWE32: A PnP Wave Table was detected at IO's %#x,%#x,%#x\n.", | ||
6066 | io1, io2, io3); | ||
6067 | setup_ports(io1, io2, io3); | ||
6068 | |||
6069 | awe_attach_device(); | ||
6070 | return 0; | ||
6071 | } | ||
6072 | |||
6073 | static void awe_pnp_remove(struct pnp_dev *dev) | ||
6074 | { | ||
6075 | awe_dettach_device(); | ||
6076 | } | ||
6077 | |||
6078 | static struct pnp_driver awe_pnp_driver = { | ||
6079 | .name = "AWE32", | ||
6080 | .id_table = awe_pnp_ids, | ||
6081 | .probe = awe_pnp_probe, | ||
6082 | .remove = awe_pnp_remove, | ||
6083 | }; | ||
6084 | |||
6085 | static int __init awe_detect_pnp_devices(void) | ||
6086 | { | ||
6087 | int ret; | ||
6088 | |||
6089 | ret = pnp_register_driver(&awe_pnp_driver); | ||
6090 | if (ret<0) | ||
6091 | printk(KERN_ERR "AWE32: PnP support is unavailable.\n"); | ||
6092 | return ret; | ||
6093 | } | ||
6094 | |||
6095 | |||
6096 | /* | ||
6097 | * device / lowlevel (module) interface | ||
6098 | */ | ||
6099 | |||
6100 | static int __init | ||
6101 | awe_detect(void) | ||
6102 | { | ||
6103 | printk(KERN_INFO "AWE32: Probing for WaveTable...\n"); | ||
6104 | if (isapnp) { | ||
6105 | if (awe_detect_pnp_devices()>=0) | ||
6106 | return 1; | ||
6107 | } else | ||
6108 | printk(KERN_INFO "AWE32: Skipping PnP detection.\n"); | ||
6109 | |||
6110 | if (awe_detect_legacy_devices()) | ||
6111 | return 1; | ||
6112 | |||
6113 | return 0; | ||
6114 | } | ||
6115 | |||
6116 | static int __init attach_awe(void) | ||
6117 | { | ||
6118 | return awe_detect() ? 0 : -ENODEV; | ||
6119 | } | ||
6120 | |||
6121 | static void __exit unload_awe(void) | ||
6122 | { | ||
6123 | pnp_unregister_driver(&awe_pnp_driver); | ||
6124 | awe_dettach_device(); | ||
6125 | } | ||
6126 | |||
6127 | |||
6128 | module_init(attach_awe); | ||
6129 | module_exit(unload_awe); | ||
6130 | |||
6131 | #ifndef MODULE | ||
6132 | static int __init setup_awe(char *str) | ||
6133 | { | ||
6134 | /* io, memsize, isapnp */ | ||
6135 | int ints[4]; | ||
6136 | |||
6137 | str = get_options(str, ARRAY_SIZE(ints), ints); | ||
6138 | |||
6139 | io = ints[1]; | ||
6140 | memsize = ints[2]; | ||
6141 | isapnp = ints[3]; | ||
6142 | |||
6143 | return 1; | ||
6144 | } | ||
6145 | |||
6146 | __setup("awe=", setup_awe); | ||
6147 | #endif | ||