diff options
author | Takashi Iwai <tiwai@suse.de> | 2007-10-30 07:17:17 -0400 |
---|---|---|
committer | Jaroslav Kysela <perex@perex.cz> | 2008-01-31 11:29:13 -0500 |
commit | e5723b41abe559bafc52591dcf8ee19cc131d3a1 (patch) | |
tree | a1d035132ae1354c43eb9fccf60c9668e0abb266 /sound/isa | |
parent | 05c1afe75fcebf456017ec186811cf1599f4360e (diff) |
[ALSA] Remove sequencer instrument layer
Remove sequencer instrument layer from the tree.
This mechanism hasn't been used much with the actual devices. The only
reasonable user was OPL3 loader, and now it was rewritten to use hwdep
instead. So, let's remove the rest of rotten codes.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
Diffstat (limited to 'sound/isa')
-rw-r--r-- | sound/isa/gus/Makefile | 12 | ||||
-rw-r--r-- | sound/isa/gus/gus_main.c | 23 | ||||
-rw-r--r-- | sound/isa/gus/gus_sample.c | 165 | ||||
-rw-r--r-- | sound/isa/gus/gus_simple.c | 634 | ||||
-rw-r--r-- | sound/isa/gus/gus_synth.c | 314 |
5 files changed, 0 insertions, 1148 deletions
diff --git a/sound/isa/gus/Makefile b/sound/isa/gus/Makefile index df3d59f25f5e..6cd4ee03754a 100644 --- a/sound/isa/gus/Makefile +++ b/sound/isa/gus/Makefile | |||
@@ -9,7 +9,6 @@ snd-gus-lib-objs := gus_main.o \ | |||
9 | gus_pcm.o gus_mixer.o \ | 9 | gus_pcm.o gus_mixer.o \ |
10 | gus_uart.o \ | 10 | gus_uart.o \ |
11 | gus_reset.o | 11 | gus_reset.o |
12 | snd-gus-synth-objs := gus_synth.o gus_sample.o gus_simple.o gus_instr.o | ||
13 | 12 | ||
14 | snd-gusclassic-objs := gusclassic.o | 13 | snd-gusclassic-objs := gusclassic.o |
15 | snd-gusextreme-objs := gusextreme.o | 14 | snd-gusextreme-objs := gusextreme.o |
@@ -17,20 +16,9 @@ snd-gusmax-objs := gusmax.o | |||
17 | snd-interwave-objs := interwave.o | 16 | snd-interwave-objs := interwave.o |
18 | snd-interwave-stb-objs := interwave-stb.o | 17 | snd-interwave-stb-objs := interwave-stb.o |
19 | 18 | ||
20 | # | ||
21 | # this function returns: | ||
22 | # "m" - CONFIG_SND_SEQUENCER is m | ||
23 | # <empty string> - CONFIG_SND_SEQUENCER is undefined | ||
24 | # otherwise parameter #1 value | ||
25 | # | ||
26 | sequencer = $(if $(subst y,,$(CONFIG_SND_SEQUENCER)),$(if $(1),m),$(if $(CONFIG_SND_SEQUENCER),$(1))) | ||
27 | |||
28 | # Toplevel Module Dependency | 19 | # Toplevel Module Dependency |
29 | obj-$(CONFIG_SND_GUSCLASSIC) += snd-gusclassic.o snd-gus-lib.o | 20 | obj-$(CONFIG_SND_GUSCLASSIC) += snd-gusclassic.o snd-gus-lib.o |
30 | obj-$(CONFIG_SND_GUSMAX) += snd-gusmax.o snd-gus-lib.o | 21 | obj-$(CONFIG_SND_GUSMAX) += snd-gusmax.o snd-gus-lib.o |
31 | obj-$(CONFIG_SND_GUSEXTREME) += snd-gusextreme.o snd-gus-lib.o | 22 | obj-$(CONFIG_SND_GUSEXTREME) += snd-gusextreme.o snd-gus-lib.o |
32 | obj-$(CONFIG_SND_INTERWAVE) += snd-interwave.o snd-gus-lib.o | 23 | obj-$(CONFIG_SND_INTERWAVE) += snd-interwave.o snd-gus-lib.o |
33 | obj-$(CONFIG_SND_INTERWAVE_STB) += snd-interwave-stb.o snd-gus-lib.o | 24 | obj-$(CONFIG_SND_INTERWAVE_STB) += snd-interwave-stb.o snd-gus-lib.o |
34 | obj-$(call sequencer,$(CONFIG_SND_GUS_SYNTH)) += snd-gus-synth.o | ||
35 | |||
36 | obj-m := $(sort $(obj-m)) | ||
diff --git a/sound/isa/gus/gus_main.c b/sound/isa/gus/gus_main.c index b14d5d6d9a32..e4453e5e5c23 100644 --- a/sound/isa/gus/gus_main.c +++ b/sound/isa/gus/gus_main.c | |||
@@ -104,12 +104,6 @@ static int snd_gus_free(struct snd_gus_card *gus) | |||
104 | { | 104 | { |
105 | if (gus->gf1.res_port2 == NULL) | 105 | if (gus->gf1.res_port2 == NULL) |
106 | goto __hw_end; | 106 | goto __hw_end; |
107 | #if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)) | ||
108 | if (gus->seq_dev) { | ||
109 | snd_device_free(gus->card, gus->seq_dev); | ||
110 | gus->seq_dev = NULL; | ||
111 | } | ||
112 | #endif | ||
113 | snd_gf1_stop(gus); | 107 | snd_gf1_stop(gus); |
114 | snd_gus_init_dma_irq(gus, 0); | 108 | snd_gus_init_dma_irq(gus, 0); |
115 | __hw_end: | 109 | __hw_end: |
@@ -408,14 +402,6 @@ static int snd_gus_check_version(struct snd_gus_card * gus) | |||
408 | return 0; | 402 | return 0; |
409 | } | 403 | } |
410 | 404 | ||
411 | #if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)) | ||
412 | static void snd_gus_seq_dev_free(struct snd_seq_device *seq_dev) | ||
413 | { | ||
414 | struct snd_gus_card *gus = seq_dev->private_data; | ||
415 | gus->seq_dev = NULL; | ||
416 | } | ||
417 | #endif | ||
418 | |||
419 | int snd_gus_initialize(struct snd_gus_card *gus) | 405 | int snd_gus_initialize(struct snd_gus_card *gus) |
420 | { | 406 | { |
421 | int err; | 407 | int err; |
@@ -430,15 +416,6 @@ int snd_gus_initialize(struct snd_gus_card *gus) | |||
430 | } | 416 | } |
431 | if ((err = snd_gus_init_dma_irq(gus, 1)) < 0) | 417 | if ((err = snd_gus_init_dma_irq(gus, 1)) < 0) |
432 | return err; | 418 | return err; |
433 | #if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)) | ||
434 | if (snd_seq_device_new(gus->card, 1, SNDRV_SEQ_DEV_ID_GUS, | ||
435 | sizeof(struct snd_gus_card *), &gus->seq_dev) >= 0) { | ||
436 | strcpy(gus->seq_dev->name, "GUS"); | ||
437 | *(struct snd_gus_card **)SNDRV_SEQ_DEVICE_ARGPTR(gus->seq_dev) = gus; | ||
438 | gus->seq_dev->private_data = gus; | ||
439 | gus->seq_dev->private_free = snd_gus_seq_dev_free; | ||
440 | } | ||
441 | #endif | ||
442 | snd_gf1_start(gus); | 419 | snd_gf1_start(gus); |
443 | gus->initialized = 1; | 420 | gus->initialized = 1; |
444 | return 0; | 421 | return 0; |
diff --git a/sound/isa/gus/gus_sample.c b/sound/isa/gus/gus_sample.c deleted file mode 100644 index cba0829a7106..000000000000 --- a/sound/isa/gus/gus_sample.c +++ /dev/null | |||
@@ -1,165 +0,0 @@ | |||
1 | /* | ||
2 | * Routines for Gravis UltraSound soundcards - Sample support | ||
3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> | ||
4 | * | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #include <sound/driver.h> | ||
23 | #include <linux/time.h> | ||
24 | #include <sound/core.h> | ||
25 | #include <sound/gus.h> | ||
26 | |||
27 | /* | ||
28 | * | ||
29 | */ | ||
30 | |||
31 | static void select_instrument(struct snd_gus_card * gus, struct snd_gus_voice * v) | ||
32 | { | ||
33 | struct snd_seq_kinstr *instr; | ||
34 | |||
35 | #if 0 | ||
36 | printk("select instrument: cluster = %li, std = 0x%x, bank = %i, prg = %i\n", | ||
37 | v->instr.cluster, | ||
38 | v->instr.std, | ||
39 | v->instr.bank, | ||
40 | v->instr.prg); | ||
41 | #endif | ||
42 | instr = snd_seq_instr_find(gus->gf1.ilist, &v->instr, 0, 1); | ||
43 | if (instr != NULL) { | ||
44 | if (instr->ops) { | ||
45 | if (!strcmp(instr->ops->instr_type, SNDRV_SEQ_INSTR_ID_SIMPLE)) | ||
46 | snd_gf1_simple_init(v); | ||
47 | } | ||
48 | snd_seq_instr_free_use(gus->gf1.ilist, instr); | ||
49 | } | ||
50 | } | ||
51 | |||
52 | /* | ||
53 | * | ||
54 | */ | ||
55 | |||
56 | static void event_sample(struct snd_seq_event *ev, struct snd_gus_port *p, | ||
57 | struct snd_gus_voice *v) | ||
58 | { | ||
59 | if (v->sample_ops && v->sample_ops->sample_stop) | ||
60 | v->sample_ops->sample_stop(p->gus, v, SAMPLE_STOP_IMMEDIATELY); | ||
61 | v->instr.std = ev->data.sample.param.sample.std; | ||
62 | if (v->instr.std & 0xff000000) { /* private instrument */ | ||
63 | v->instr.std &= 0x00ffffff; | ||
64 | v->instr.std |= (unsigned int)ev->source.client << 24; | ||
65 | } | ||
66 | v->instr.bank = ev->data.sample.param.sample.bank; | ||
67 | v->instr.prg = ev->data.sample.param.sample.prg; | ||
68 | select_instrument(p->gus, v); | ||
69 | } | ||
70 | |||
71 | static void event_cluster(struct snd_seq_event *ev, struct snd_gus_port *p, | ||
72 | struct snd_gus_voice *v) | ||
73 | { | ||
74 | if (v->sample_ops && v->sample_ops->sample_stop) | ||
75 | v->sample_ops->sample_stop(p->gus, v, SAMPLE_STOP_IMMEDIATELY); | ||
76 | v->instr.cluster = ev->data.sample.param.cluster.cluster; | ||
77 | select_instrument(p->gus, v); | ||
78 | } | ||
79 | |||
80 | static void event_start(struct snd_seq_event *ev, struct snd_gus_port *p, | ||
81 | struct snd_gus_voice *v) | ||
82 | { | ||
83 | if (v->sample_ops && v->sample_ops->sample_start) | ||
84 | v->sample_ops->sample_start(p->gus, v, ev->data.sample.param.position); | ||
85 | } | ||
86 | |||
87 | static void event_stop(struct snd_seq_event *ev, struct snd_gus_port *p, | ||
88 | struct snd_gus_voice *v) | ||
89 | { | ||
90 | if (v->sample_ops && v->sample_ops->sample_stop) | ||
91 | v->sample_ops->sample_stop(p->gus, v, ev->data.sample.param.stop_mode); | ||
92 | } | ||
93 | |||
94 | static void event_freq(struct snd_seq_event *ev, struct snd_gus_port *p, | ||
95 | struct snd_gus_voice *v) | ||
96 | { | ||
97 | if (v->sample_ops && v->sample_ops->sample_freq) | ||
98 | v->sample_ops->sample_freq(p->gus, v, ev->data.sample.param.frequency); | ||
99 | } | ||
100 | |||
101 | static void event_volume(struct snd_seq_event *ev, struct snd_gus_port *p, | ||
102 | struct snd_gus_voice *v) | ||
103 | { | ||
104 | if (v->sample_ops && v->sample_ops->sample_volume) | ||
105 | v->sample_ops->sample_volume(p->gus, v, &ev->data.sample.param.volume); | ||
106 | } | ||
107 | |||
108 | static void event_loop(struct snd_seq_event *ev, struct snd_gus_port *p, | ||
109 | struct snd_gus_voice *v) | ||
110 | { | ||
111 | if (v->sample_ops && v->sample_ops->sample_loop) | ||
112 | v->sample_ops->sample_loop(p->gus, v, &ev->data.sample.param.loop); | ||
113 | } | ||
114 | |||
115 | static void event_position(struct snd_seq_event *ev, struct snd_gus_port *p, | ||
116 | struct snd_gus_voice *v) | ||
117 | { | ||
118 | if (v->sample_ops && v->sample_ops->sample_pos) | ||
119 | v->sample_ops->sample_pos(p->gus, v, ev->data.sample.param.position); | ||
120 | } | ||
121 | |||
122 | static void event_private1(struct snd_seq_event *ev, struct snd_gus_port *p, | ||
123 | struct snd_gus_voice *v) | ||
124 | { | ||
125 | if (v->sample_ops && v->sample_ops->sample_private1) | ||
126 | v->sample_ops->sample_private1(p->gus, v, (unsigned char *)&ev->data.sample.param.raw8); | ||
127 | } | ||
128 | |||
129 | typedef void (gus_sample_event_handler_t)(struct snd_seq_event *ev, | ||
130 | struct snd_gus_port *p, | ||
131 | struct snd_gus_voice *v); | ||
132 | static gus_sample_event_handler_t *gus_sample_event_handlers[9] = { | ||
133 | event_sample, | ||
134 | event_cluster, | ||
135 | event_start, | ||
136 | event_stop, | ||
137 | event_freq, | ||
138 | event_volume, | ||
139 | event_loop, | ||
140 | event_position, | ||
141 | event_private1 | ||
142 | }; | ||
143 | |||
144 | void snd_gus_sample_event(struct snd_seq_event *ev, struct snd_gus_port *p) | ||
145 | { | ||
146 | int idx, voice; | ||
147 | struct snd_gus_card *gus = p->gus; | ||
148 | struct snd_gus_voice *v; | ||
149 | unsigned long flags; | ||
150 | |||
151 | idx = ev->type - SNDRV_SEQ_EVENT_SAMPLE; | ||
152 | if (idx < 0 || idx > 8) | ||
153 | return; | ||
154 | for (voice = 0; voice < 32; voice++) { | ||
155 | v = &gus->gf1.voices[voice]; | ||
156 | if (v->use && v->client == ev->source.client && | ||
157 | v->port == ev->source.port && | ||
158 | v->index == ev->data.sample.channel) { | ||
159 | spin_lock_irqsave(&gus->event_lock, flags); | ||
160 | gus_sample_event_handlers[idx](ev, p, v); | ||
161 | spin_unlock_irqrestore(&gus->event_lock, flags); | ||
162 | return; | ||
163 | } | ||
164 | } | ||
165 | } | ||
diff --git a/sound/isa/gus/gus_simple.c b/sound/isa/gus/gus_simple.c deleted file mode 100644 index 39d121e2c8c4..000000000000 --- a/sound/isa/gus/gus_simple.c +++ /dev/null | |||
@@ -1,634 +0,0 @@ | |||
1 | /* | ||
2 | * Routines for Gravis UltraSound soundcards - Simple instrument handlers | ||
3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> | ||
4 | * | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #include <sound/driver.h> | ||
23 | #include <linux/time.h> | ||
24 | #include <sound/core.h> | ||
25 | #include <sound/gus.h> | ||
26 | #include "gus_tables.h" | ||
27 | |||
28 | /* | ||
29 | * | ||
30 | */ | ||
31 | |||
32 | static void interrupt_wave(struct snd_gus_card *gus, struct snd_gus_voice *voice); | ||
33 | static void interrupt_volume(struct snd_gus_card *gus, struct snd_gus_voice *voice); | ||
34 | static void interrupt_effect(struct snd_gus_card *gus, struct snd_gus_voice *voice); | ||
35 | |||
36 | static void sample_start(struct snd_gus_card *gus, struct snd_gus_voice *voice, snd_seq_position_t position); | ||
37 | static void sample_stop(struct snd_gus_card *gus, struct snd_gus_voice *voice, int mode); | ||
38 | static void sample_freq(struct snd_gus_card *gus, struct snd_gus_voice *voice, snd_seq_frequency_t freq); | ||
39 | static void sample_volume(struct snd_gus_card *card, struct snd_gus_voice *voice, struct snd_seq_ev_volume *volume); | ||
40 | static void sample_loop(struct snd_gus_card *card, struct snd_gus_voice *voice, struct snd_seq_ev_loop *loop); | ||
41 | static void sample_pos(struct snd_gus_card *card, struct snd_gus_voice *voice, snd_seq_position_t position); | ||
42 | static void sample_private1(struct snd_gus_card *card, struct snd_gus_voice *voice, unsigned char *data); | ||
43 | |||
44 | static struct snd_gus_sample_ops sample_ops = { | ||
45 | sample_start, | ||
46 | sample_stop, | ||
47 | sample_freq, | ||
48 | sample_volume, | ||
49 | sample_loop, | ||
50 | sample_pos, | ||
51 | sample_private1 | ||
52 | }; | ||
53 | |||
54 | #if 0 | ||
55 | |||
56 | static void note_stop(struct snd_gus_card *gus, struct snd_gus_voice *voice, int wait); | ||
57 | static void note_wait(struct snd_gus_card *gus, struct snd_gus_voice *voice); | ||
58 | static void note_off(struct snd_gus_card *gus, struct snd_gus_voice *voice); | ||
59 | static void note_volume(struct snd_gus_card *card, struct snd_gus_voice *voice); | ||
60 | static void note_pitchbend(struct snd_gus_card *card, struct snd_gus_voice *voice); | ||
61 | static void note_vibrato(struct snd_gus_card *card, struct snd_gus_voice *voice); | ||
62 | static void note_tremolo(struct snd_gus_card *card, struct snd_gus_voice *voice); | ||
63 | |||
64 | static struct snd_gus_note_handlers note_commands = { | ||
65 | note_stop, | ||
66 | note_wait, | ||
67 | note_off, | ||
68 | note_volume, | ||
69 | note_pitchbend, | ||
70 | note_vibrato, | ||
71 | note_tremolo | ||
72 | }; | ||
73 | |||
74 | static void chn_trigger_down(struct snd_gus_card *card, ultra_channel_t *channel, ultra_instrument_t *instrument, unsigned char note, unsigned char velocity, unsigned char priority ); | ||
75 | static void chn_trigger_up( ultra_card_t *card, ultra_note_t *note ); | ||
76 | static void chn_control( ultra_card_t *card, ultra_channel_t *channel, unsigned short p1, unsigned short p2 ); | ||
77 | |||
78 | static struct ULTRA_STRU_INSTRUMENT_CHANNEL_COMMANDS channel_commands = { | ||
79 | chn_trigger_down, | ||
80 | chn_trigger_up, | ||
81 | chn_control | ||
82 | }; | ||
83 | |||
84 | #endif | ||
85 | |||
86 | static void do_volume_envelope(struct snd_gus_card *card, struct snd_gus_voice *voice); | ||
87 | static void do_pan_envelope(struct snd_gus_card *card, struct snd_gus_voice *voice); | ||
88 | |||
89 | /* | ||
90 | * | ||
91 | */ | ||
92 | |||
93 | static void interrupt_wave(struct snd_gus_card *gus, struct snd_gus_voice *voice) | ||
94 | { | ||
95 | spin_lock(&gus->event_lock); | ||
96 | snd_gf1_stop_voice(gus, voice->number); | ||
97 | spin_lock(&gus->reg_lock); | ||
98 | snd_gf1_select_voice(gus, voice->number); | ||
99 | snd_gf1_write16(gus, SNDRV_GF1_VW_VOLUME, 0); | ||
100 | spin_unlock(&gus->reg_lock); | ||
101 | voice->flags &= ~SNDRV_GF1_VFLG_RUNNING; | ||
102 | spin_unlock(&gus->event_lock); | ||
103 | } | ||
104 | |||
105 | static void interrupt_volume(struct snd_gus_card *gus, struct snd_gus_voice *voice) | ||
106 | { | ||
107 | spin_lock(&gus->event_lock); | ||
108 | if (voice->flags & SNDRV_GF1_VFLG_RUNNING) | ||
109 | do_volume_envelope(gus, voice); | ||
110 | else | ||
111 | snd_gf1_stop_voice(gus, voice->number); | ||
112 | spin_unlock(&gus->event_lock); | ||
113 | } | ||
114 | |||
115 | static void interrupt_effect(struct snd_gus_card *gus, struct snd_gus_voice *voice) | ||
116 | { | ||
117 | spin_lock(&gus->event_lock); | ||
118 | if ((voice->flags & (SNDRV_GF1_VFLG_RUNNING|SNDRV_GF1_VFLG_EFFECT_TIMER1)) == | ||
119 | (SNDRV_GF1_VFLG_RUNNING|SNDRV_GF1_VFLG_EFFECT_TIMER1)) | ||
120 | do_pan_envelope(gus, voice); | ||
121 | spin_unlock(&gus->event_lock); | ||
122 | } | ||
123 | |||
124 | /* | ||
125 | * | ||
126 | */ | ||
127 | |||
128 | static void do_volume_envelope(struct snd_gus_card *gus, struct snd_gus_voice *voice) | ||
129 | { | ||
130 | unsigned short next, rate, old_volume; | ||
131 | int program_next_ramp; | ||
132 | unsigned long flags; | ||
133 | |||
134 | if (!gus->gf1.volume_ramp) { | ||
135 | spin_lock_irqsave(&gus->reg_lock, flags); | ||
136 | snd_gf1_select_voice(gus, voice->number); | ||
137 | snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL); | ||
138 | snd_gf1_write16(gus, SNDRV_GF1_VW_VOLUME, voice->gf1_volume); | ||
139 | /* printk("gf1_volume = 0x%x\n", voice->gf1_volume); */ | ||
140 | spin_unlock_irqrestore(&gus->reg_lock, flags); | ||
141 | return; | ||
142 | } | ||
143 | program_next_ramp = 0; | ||
144 | rate = next = 0; | ||
145 | while (1) { | ||
146 | program_next_ramp = 0; | ||
147 | rate = next = 0; | ||
148 | switch (voice->venv_state) { | ||
149 | case VENV_BEFORE: | ||
150 | voice->venv_state = VENV_ATTACK; | ||
151 | voice->venv_value_next = 0; | ||
152 | spin_lock_irqsave(&gus->reg_lock, flags); | ||
153 | snd_gf1_select_voice(gus, voice->number); | ||
154 | snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL); | ||
155 | snd_gf1_write16(gus, SNDRV_GF1_VW_VOLUME, SNDRV_GF1_MIN_VOLUME); | ||
156 | spin_unlock_irqrestore(&gus->reg_lock, flags); | ||
157 | break; | ||
158 | case VENV_ATTACK: | ||
159 | voice->venv_state = VENV_SUSTAIN; | ||
160 | program_next_ramp++; | ||
161 | next = 255; | ||
162 | rate = gus->gf1.volume_ramp; | ||
163 | break; | ||
164 | case VENV_SUSTAIN: | ||
165 | voice->venv_state = VENV_RELEASE; | ||
166 | spin_lock_irqsave(&gus->reg_lock, flags); | ||
167 | snd_gf1_select_voice(gus, voice->number); | ||
168 | snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL); | ||
169 | snd_gf1_write16(gus, SNDRV_GF1_VW_VOLUME, ((int)voice->gf1_volume * (int)voice->venv_value_next) / 255); | ||
170 | spin_unlock_irqrestore(&gus->reg_lock, flags); | ||
171 | return; | ||
172 | case VENV_RELEASE: | ||
173 | voice->venv_state = VENV_DONE; | ||
174 | program_next_ramp++; | ||
175 | next = 0; | ||
176 | rate = gus->gf1.volume_ramp; | ||
177 | break; | ||
178 | case VENV_DONE: | ||
179 | snd_gf1_stop_voice(gus, voice->number); | ||
180 | voice->flags &= ~SNDRV_GF1_VFLG_RUNNING; | ||
181 | return; | ||
182 | case VENV_VOLUME: | ||
183 | program_next_ramp++; | ||
184 | next = voice->venv_value_next; | ||
185 | rate = gus->gf1.volume_ramp; | ||
186 | voice->venv_state = voice->venv_state_prev; | ||
187 | break; | ||
188 | } | ||
189 | voice->venv_value_next = next; | ||
190 | if (!program_next_ramp) | ||
191 | continue; | ||
192 | spin_lock_irqsave(&gus->reg_lock, flags); | ||
193 | snd_gf1_select_voice(gus, voice->number); | ||
194 | snd_gf1_ctrl_stop(gus, SNDRV_GF1_VB_VOLUME_CONTROL); | ||
195 | old_volume = snd_gf1_read16(gus, SNDRV_GF1_VW_VOLUME) >> 8; | ||
196 | if (!rate) { | ||
197 | spin_unlock_irqrestore(&gus->reg_lock, flags); | ||
198 | continue; | ||
199 | } | ||
200 | next = (((int)voice->gf1_volume * (int)next) / 255) >> 8; | ||
201 | if (old_volume < SNDRV_GF1_MIN_OFFSET) | ||
202 | old_volume = SNDRV_GF1_MIN_OFFSET; | ||
203 | if (next < SNDRV_GF1_MIN_OFFSET) | ||
204 | next = SNDRV_GF1_MIN_OFFSET; | ||
205 | if (next > SNDRV_GF1_MAX_OFFSET) | ||
206 | next = SNDRV_GF1_MAX_OFFSET; | ||
207 | if (old_volume == next) { | ||
208 | spin_unlock_irqrestore(&gus->reg_lock, flags); | ||
209 | continue; | ||
210 | } | ||
211 | voice->volume_control &= ~0xc3; | ||
212 | voice->volume_control |= 0x20; | ||
213 | if (old_volume > next) { | ||
214 | snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_START, next); | ||
215 | snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_END, old_volume); | ||
216 | voice->volume_control |= 0x40; | ||
217 | } else { | ||
218 | snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_START, old_volume); | ||
219 | snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_END, next); | ||
220 | } | ||
221 | snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_RATE, rate); | ||
222 | snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_CONTROL, voice->volume_control); | ||
223 | if (!gus->gf1.enh_mode) { | ||
224 | snd_gf1_delay(gus); | ||
225 | snd_gf1_write8(gus, SNDRV_GF1_VB_VOLUME_CONTROL, voice->volume_control); | ||
226 | } | ||
227 | spin_unlock_irqrestore(&gus->reg_lock, flags); | ||
228 | return; | ||
229 | } | ||
230 | } | ||
231 | |||
232 | static void do_pan_envelope(struct snd_gus_card *gus, struct snd_gus_voice *voice) | ||
233 | { | ||
234 | unsigned long flags; | ||
235 | unsigned char old_pan; | ||
236 | |||
237 | #if 0 | ||
238 | snd_gf1_select_voice(gus, voice->number); | ||
239 | printk(" -%i- do_pan_envelope - flags = 0x%x (0x%x -> 0x%x)\n", | ||
240 | voice->number, | ||
241 | voice->flags, | ||
242 | voice->gf1_pan, | ||
243 | snd_gf1_i_read8(gus, SNDRV_GF1_VB_PAN) & 0x0f); | ||
244 | #endif | ||
245 | if (gus->gf1.enh_mode) { | ||
246 | voice->flags &= ~(SNDRV_GF1_VFLG_EFFECT_TIMER1|SNDRV_GF1_VFLG_PAN); | ||
247 | return; | ||
248 | } | ||
249 | if (!gus->gf1.smooth_pan) { | ||
250 | spin_lock_irqsave(&gus->reg_lock, flags); | ||
251 | snd_gf1_select_voice(gus, voice->number); | ||
252 | snd_gf1_write8(gus, SNDRV_GF1_VB_PAN, voice->gf1_pan); | ||
253 | spin_unlock_irqrestore(&gus->reg_lock, flags); | ||
254 | return; | ||
255 | } | ||
256 | if (!(voice->flags & SNDRV_GF1_VFLG_PAN)) /* before */ | ||
257 | voice->flags |= SNDRV_GF1_VFLG_EFFECT_TIMER1|SNDRV_GF1_VFLG_PAN; | ||
258 | spin_lock_irqsave(&gus->reg_lock, flags); | ||
259 | snd_gf1_select_voice(gus, voice->number); | ||
260 | old_pan = snd_gf1_read8(gus, SNDRV_GF1_VB_PAN) & 0x0f; | ||
261 | if (old_pan > voice->gf1_pan ) | ||
262 | old_pan--; | ||
263 | if (old_pan < voice->gf1_pan) | ||
264 | old_pan++; | ||
265 | snd_gf1_write8(gus, SNDRV_GF1_VB_PAN, old_pan); | ||
266 | spin_unlock_irqrestore(&gus->reg_lock, flags); | ||
267 | if (old_pan == voice->gf1_pan) /* the goal was reached */ | ||
268 | voice->flags &= ~(SNDRV_GF1_VFLG_EFFECT_TIMER1|SNDRV_GF1_VFLG_PAN); | ||
269 | #if 0 | ||
270 | snd_gf1_select_voice(gus, voice->number); | ||
271 | printk(" -%i- (1) do_pan_envelope - flags = 0x%x (0x%x -> 0x%x)\n", | ||
272 | voice->number, | ||
273 | voice->flags, | ||
274 | voice->gf1_pan, | ||
275 | snd_gf1_i_read8(gus, GF1_VB_PAN) & 0x0f); | ||
276 | #endif | ||
277 | } | ||
278 | |||
279 | static void set_enhanced_pan(struct snd_gus_card *gus, struct snd_gus_voice *voice, unsigned short pan) | ||
280 | { | ||
281 | unsigned long flags; | ||
282 | unsigned short vlo, vro; | ||
283 | |||
284 | vlo = SNDRV_GF1_ATTEN((SNDRV_GF1_ATTEN_TABLE_SIZE-1) - pan); | ||
285 | vro = SNDRV_GF1_ATTEN(pan); | ||
286 | if (pan != SNDRV_GF1_ATTEN_TABLE_SIZE - 1 && pan != 0) { | ||
287 | vlo >>= 1; | ||
288 | vro >>= 1; | ||
289 | } | ||
290 | vlo <<= 4; | ||
291 | vro <<= 4; | ||
292 | #if 0 | ||
293 | printk("vlo = 0x%x (0x%x), vro = 0x%x (0x%x)\n", | ||
294 | vlo, snd_gf1_i_read16(gus, GF1_VW_OFFSET_LEFT), | ||
295 | vro, snd_gf1_i_read16(gus, GF1_VW_OFFSET_RIGHT)); | ||
296 | #endif | ||
297 | spin_lock_irqsave(&gus->reg_lock, flags); | ||
298 | snd_gf1_select_voice(gus, voice->number); | ||
299 | snd_gf1_write16(gus, SNDRV_GF1_VW_OFFSET_LEFT_FINAL, vlo); | ||
300 | snd_gf1_write16(gus, SNDRV_GF1_VW_OFFSET_RIGHT_FINAL, vro); | ||
301 | spin_unlock_irqrestore(&gus->reg_lock, flags); | ||
302 | voice->vlo = vlo; | ||
303 | voice->vro = vro; | ||
304 | } | ||
305 | |||
306 | /* | ||
307 | * | ||
308 | */ | ||
309 | |||
310 | static void sample_start(struct snd_gus_card *gus, struct snd_gus_voice *voice, snd_seq_position_t position) | ||
311 | { | ||
312 | unsigned long flags; | ||
313 | unsigned int begin, addr, addr_end, addr_start; | ||
314 | int w_16; | ||
315 | struct simple_instrument *simple; | ||
316 | struct snd_seq_kinstr *instr; | ||
317 | |||
318 | instr = snd_seq_instr_find(gus->gf1.ilist, &voice->instr, 0, 1); | ||
319 | if (instr == NULL) | ||
320 | return; | ||
321 | voice->instr = instr->instr; /* copy ID to speedup aliases */ | ||
322 | simple = KINSTR_DATA(instr); | ||
323 | begin = simple->address.memory << 4; | ||
324 | w_16 = simple->format & SIMPLE_WAVE_16BIT ? 0x04 : 0; | ||
325 | addr_start = simple->loop_start; | ||
326 | if (simple->format & SIMPLE_WAVE_LOOP) { | ||
327 | addr_end = simple->loop_end; | ||
328 | } else { | ||
329 | addr_end = (simple->size << 4) - (w_16 ? 40 : 24); | ||
330 | } | ||
331 | if (simple->format & SIMPLE_WAVE_BACKWARD) { | ||
332 | addr = simple->loop_end; | ||
333 | if (position < simple->loop_end) | ||
334 | addr -= position; | ||
335 | } else { | ||
336 | addr = position; | ||
337 | } | ||
338 | voice->control = 0x00; | ||
339 | voice->mode = 0x20; /* enable offset registers */ | ||
340 | if (simple->format & SIMPLE_WAVE_16BIT) | ||
341 | voice->control |= 0x04; | ||
342 | if (simple->format & SIMPLE_WAVE_BACKWARD) | ||
343 | voice->control |= 0x40; | ||
344 | if (simple->format & SIMPLE_WAVE_LOOP) { | ||
345 | voice->control |= 0x08; | ||
346 | } else { | ||
347 | voice->control |= 0x20; | ||
348 | } | ||
349 | if (simple->format & SIMPLE_WAVE_BIDIR) | ||
350 | voice->control |= 0x10; | ||
351 | if (simple->format & SIMPLE_WAVE_ULAW) | ||
352 | voice->mode |= 0x40; | ||
353 | if (w_16) { | ||
354 | addr = ((addr << 1) & ~0x1f) | (addr & 0x0f); | ||
355 | addr_start = ((addr_start << 1) & ~0x1f) | (addr_start & 0x0f); | ||
356 | addr_end = ((addr_end << 1) & ~0x1f) | (addr_end & 0x0f); | ||
357 | } | ||
358 | addr += begin; | ||
359 | addr_start += begin; | ||
360 | addr_end += begin; | ||
361 | snd_gf1_stop_voice(gus, voice->number); | ||
362 | spin_lock_irqsave(&gus->reg_lock, flags); | ||
363 | snd_gf1_select_voice(gus, voice->number); | ||
364 | snd_gf1_write16(gus, SNDRV_GF1_VW_FREQUENCY, voice->fc_register + voice->fc_lfo); | ||
365 | voice->venv_state = VENV_BEFORE; | ||
366 | voice->volume_control = 0x03; | ||
367 | snd_gf1_write_addr(gus, SNDRV_GF1_VA_START, addr_start, w_16); | ||
368 | snd_gf1_write_addr(gus, SNDRV_GF1_VA_END, addr_end, w_16); | ||
369 | snd_gf1_write_addr(gus, SNDRV_GF1_VA_CURRENT, addr, w_16); | ||
370 | if (!gus->gf1.enh_mode) { | ||
371 | snd_gf1_write8(gus, SNDRV_GF1_VB_PAN, voice->gf1_pan); | ||
372 | } else { | ||
373 | snd_gf1_write16(gus, SNDRV_GF1_VW_OFFSET_LEFT, voice->vlo); | ||
374 | snd_gf1_write16(gus, SNDRV_GF1_VW_OFFSET_LEFT_FINAL, voice->vlo); | ||
375 | snd_gf1_write16(gus, SNDRV_GF1_VW_OFFSET_RIGHT, voice->vro); | ||
376 | snd_gf1_write16(gus, SNDRV_GF1_VW_OFFSET_RIGHT_FINAL, voice->vro); | ||
377 | snd_gf1_write8(gus, SNDRV_GF1_VB_ACCUMULATOR, voice->effect_accumulator); | ||
378 | snd_gf1_write16(gus, SNDRV_GF1_VW_EFFECT_VOLUME, voice->gf1_effect_volume); | ||
379 | snd_gf1_write16(gus, SNDRV_GF1_VW_EFFECT_VOLUME_FINAL, voice->gf1_effect_volume); | ||
380 | } | ||
381 | spin_unlock_irqrestore(&gus->reg_lock, flags); | ||
382 | do_volume_envelope(gus, voice); | ||
383 | spin_lock_irqsave(&gus->reg_lock, flags); | ||
384 | snd_gf1_select_voice(gus, voice->number); | ||
385 | if (gus->gf1.enh_mode) | ||
386 | snd_gf1_write8(gus, SNDRV_GF1_VB_MODE, voice->mode); | ||
387 | snd_gf1_write8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL, voice->control); | ||
388 | if (!gus->gf1.enh_mode) { | ||
389 | snd_gf1_delay(gus); | ||
390 | snd_gf1_write8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL, voice->control ); | ||
391 | } | ||
392 | spin_unlock_irqrestore(&gus->reg_lock, flags); | ||
393 | #if 0 | ||
394 | snd_gf1_print_voice_registers(gus); | ||
395 | #endif | ||
396 | voice->flags |= SNDRV_GF1_VFLG_RUNNING; | ||
397 | snd_seq_instr_free_use(gus->gf1.ilist, instr); | ||
398 | } | ||
399 | |||
400 | static void sample_stop(struct snd_gus_card *gus, struct snd_gus_voice *voice, int mode) | ||
401 | { | ||
402 | unsigned char control; | ||
403 | unsigned long flags; | ||
404 | |||
405 | if (!(voice->flags & SNDRV_GF1_VFLG_RUNNING)) | ||
406 | return; | ||
407 | switch (mode) { | ||
408 | default: | ||
409 | if (gus->gf1.volume_ramp > 0) { | ||
410 | if (voice->venv_state < VENV_RELEASE) { | ||
411 | voice->venv_state = VENV_RELEASE; | ||
412 | do_volume_envelope(gus, voice); | ||
413 | } | ||
414 | } | ||
415 | if (mode != SAMPLE_STOP_VENVELOPE) { | ||
416 | snd_gf1_stop_voice(gus, voice->number); | ||
417 | spin_lock_irqsave(&gus->reg_lock, flags); | ||
418 | snd_gf1_select_voice(gus, voice->number); | ||
419 | snd_gf1_write16(gus, SNDRV_GF1_VW_VOLUME, SNDRV_GF1_MIN_VOLUME); | ||
420 | spin_unlock_irqrestore(&gus->reg_lock, flags); | ||
421 | voice->flags &= ~SNDRV_GF1_VFLG_RUNNING; | ||
422 | } | ||
423 | break; | ||
424 | case SAMPLE_STOP_LOOP: /* disable loop only */ | ||
425 | spin_lock_irqsave(&gus->reg_lock, flags); | ||
426 | snd_gf1_select_voice(gus, voice->number); | ||
427 | control = snd_gf1_read8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL); | ||
428 | control &= ~(0x83 | 0x04); | ||
429 | control |= 0x20; | ||
430 | snd_gf1_write8(gus, SNDRV_GF1_VB_ADDRESS_CONTROL, control); | ||
431 | spin_unlock_irqrestore(&gus->reg_lock, flags); | ||
432 | break; | ||
433 | } | ||
434 | } | ||
435 | |||
436 | static void sample_freq(struct snd_gus_card *gus, struct snd_gus_voice *voice, snd_seq_frequency_t freq) | ||
437 | { | ||
438 | unsigned long flags; | ||
439 | |||
440 | spin_lock_irqsave(&gus->reg_lock, flags); | ||
441 | voice->fc_register = snd_gf1_translate_freq(gus, freq); | ||
442 | snd_gf1_select_voice(gus, voice->number); | ||
443 | snd_gf1_write16(gus, SNDRV_GF1_VW_FREQUENCY, voice->fc_register + voice->fc_lfo); | ||
444 | spin_unlock_irqrestore(&gus->reg_lock, flags); | ||
445 | } | ||
446 | |||
447 | static void sample_volume(struct snd_gus_card *gus, struct snd_gus_voice *voice, struct snd_seq_ev_volume *volume) | ||
448 | { | ||
449 | if (volume->volume >= 0) { | ||
450 | volume->volume &= 0x3fff; | ||
451 | voice->gf1_volume = snd_gf1_lvol_to_gvol_raw(volume->volume << 2) << 4; | ||
452 | voice->venv_state_prev = VENV_SUSTAIN; | ||
453 | voice->venv_state = VENV_VOLUME; | ||
454 | do_volume_envelope(gus, voice); | ||
455 | } | ||
456 | if (volume->lr >= 0) { | ||
457 | volume->lr &= 0x3fff; | ||
458 | if (!gus->gf1.enh_mode) { | ||
459 | voice->gf1_pan = (volume->lr >> 10) & 15; | ||
460 | if (!gus->gf1.full_range_pan) { | ||
461 | if (voice->gf1_pan == 0) | ||
462 | voice->gf1_pan++; | ||
463 | if (voice->gf1_pan == 15) | ||
464 | voice->gf1_pan--; | ||
465 | } | ||
466 | voice->flags &= ~SNDRV_GF1_VFLG_PAN; /* before */ | ||
467 | do_pan_envelope(gus, voice); | ||
468 | } else { | ||
469 | set_enhanced_pan(gus, voice, volume->lr >> 7); | ||
470 | } | ||
471 | } | ||
472 | } | ||
473 | |||
474 | static void sample_loop(struct snd_gus_card *gus, struct snd_gus_voice *voice, struct snd_seq_ev_loop *loop) | ||
475 | { | ||
476 | unsigned long flags; | ||
477 | int w_16 = voice->control & 0x04; | ||
478 | unsigned int begin, addr_start, addr_end; | ||
479 | struct simple_instrument *simple; | ||
480 | struct snd_seq_kinstr *instr; | ||
481 | |||
482 | #if 0 | ||
483 | printk("voice_loop: start = 0x%x, end = 0x%x\n", loop->start, loop->end); | ||
484 | #endif | ||
485 | instr = snd_seq_instr_find(gus->gf1.ilist, &voice->instr, 0, 1); | ||
486 | if (instr == NULL) | ||
487 | return; | ||
488 | voice->instr = instr->instr; /* copy ID to speedup aliases */ | ||
489 | simple = KINSTR_DATA(instr); | ||
490 | begin = simple->address.memory; | ||
491 | addr_start = loop->start; | ||
492 | addr_end = loop->end; | ||
493 | addr_start = (((addr_start << 1) & ~0x1f) | (addr_start & 0x0f)) + begin; | ||
494 | addr_end = (((addr_end << 1) & ~0x1f) | (addr_end & 0x0f)) + begin; | ||
495 | spin_lock_irqsave(&gus->reg_lock, flags); | ||
496 | snd_gf1_select_voice(gus, voice->number); | ||
497 | snd_gf1_write_addr(gus, SNDRV_GF1_VA_START, addr_start, w_16); | ||
498 | snd_gf1_write_addr(gus, SNDRV_GF1_VA_END, addr_end, w_16); | ||
499 | spin_unlock_irqrestore(&gus->reg_lock, flags); | ||
500 | snd_seq_instr_free_use(gus->gf1.ilist, instr); | ||
501 | } | ||
502 | |||
503 | static void sample_pos(struct snd_gus_card *gus, struct snd_gus_voice *voice, snd_seq_position_t position) | ||
504 | { | ||
505 | unsigned long flags; | ||
506 | int w_16 = voice->control & 0x04; | ||
507 | unsigned int begin, addr; | ||
508 | struct simple_instrument *simple; | ||
509 | struct snd_seq_kinstr *instr; | ||
510 | |||
511 | #if 0 | ||
512 | printk("voice_loop: start = 0x%x, end = 0x%x\n", loop->start, loop->end); | ||
513 | #endif | ||
514 | instr = snd_seq_instr_find(gus->gf1.ilist, &voice->instr, 0, 1); | ||
515 | if (instr == NULL) | ||
516 | return; | ||
517 | voice->instr = instr->instr; /* copy ID to speedup aliases */ | ||
518 | simple = KINSTR_DATA(instr); | ||
519 | begin = simple->address.memory; | ||
520 | addr = (((position << 1) & ~0x1f) | (position & 0x0f)) + begin; | ||
521 | spin_lock_irqsave(&gus->reg_lock, flags); | ||
522 | snd_gf1_select_voice(gus, voice->number); | ||
523 | snd_gf1_write_addr(gus, SNDRV_GF1_VA_CURRENT, addr, w_16); | ||
524 | spin_unlock_irqrestore(&gus->reg_lock, flags); | ||
525 | snd_seq_instr_free_use(gus->gf1.ilist, instr); | ||
526 | } | ||
527 | |||
528 | #if 0 | ||
529 | |||
530 | static unsigned char get_effects_mask( ultra_card_t *card, int value ) | ||
531 | { | ||
532 | if ( value > 7 ) return 0; | ||
533 | if ( card -> gf1.effects && card -> gf1.effects -> chip_type == ULTRA_EFFECT_CHIP_INTERWAVE ) | ||
534 | return card -> gf1.effects -> chip.interwave.voice_output[ value ]; | ||
535 | return 0; | ||
536 | } | ||
537 | |||
538 | #endif | ||
539 | |||
540 | static void sample_private1(struct snd_gus_card *card, struct snd_gus_voice *voice, unsigned char *data) | ||
541 | { | ||
542 | #if 0 | ||
543 | unsigned long flags; | ||
544 | unsigned char uc; | ||
545 | |||
546 | switch ( *data ) { | ||
547 | case ULTRA_PRIV1_IW_EFFECT: | ||
548 | uc = get_effects_mask( card, ultra_get_byte( data, 4 ) ); | ||
549 | uc |= get_effects_mask( card, ultra_get_byte( data, 4 ) >> 4 ); | ||
550 | uc |= get_effects_mask( card, ultra_get_byte( data, 5 ) ); | ||
551 | uc |= get_effects_mask( card, ultra_get_byte( data, 5 ) >> 4 ); | ||
552 | voice -> data.simple.effect_accumulator = uc; | ||
553 | voice -> data.simple.effect_volume = ultra_translate_voice_volume( card, ultra_get_word( data, 2 ) ) << 4; | ||
554 | if ( !card -> gf1.enh_mode ) return; | ||
555 | if ( voice -> flags & VFLG_WAIT_FOR_START ) return; | ||
556 | if ( voice -> flags & VFLG_RUNNING ) | ||
557 | { | ||
558 | CLI( &flags ); | ||
559 | gf1_select_voice( card, voice -> number ); | ||
560 | ultra_write8( card, GF1_VB_ACCUMULATOR, voice -> data.simple.effect_accumulator ); | ||
561 | ultra_write16( card, GF1_VW_EFFECT_VOLUME_FINAL, voice -> data.simple.effect_volume ); | ||
562 | STI( &flags ); | ||
563 | } | ||
564 | break; | ||
565 | case ULTRA_PRIV1_IW_LFO: | ||
566 | ultra_lfo_command( card, voice -> number, data ); | ||
567 | } | ||
568 | #endif | ||
569 | } | ||
570 | |||
571 | #if 0 | ||
572 | |||
573 | /* | ||
574 | * | ||
575 | */ | ||
576 | |||
577 | static void note_stop( ultra_card_t *card, ultra_voice_t *voice, int wait ) | ||
578 | { | ||
579 | } | ||
580 | |||
581 | static void note_wait( ultra_card_t *card, ultra_voice_t *voice ) | ||
582 | { | ||
583 | } | ||
584 | |||
585 | static void note_off( ultra_card_t *card, ultra_voice_t *voice ) | ||
586 | { | ||
587 | } | ||
588 | |||
589 | static void note_volume( ultra_card_t *card, ultra_voice_t *voice ) | ||
590 | { | ||
591 | } | ||
592 | |||
593 | static void note_pitchbend( ultra_card_t *card, ultra_voice_t *voice ) | ||
594 | { | ||
595 | } | ||
596 | |||
597 | static void note_vibrato( ultra_card_t *card, ultra_voice_t *voice ) | ||
598 | { | ||
599 | } | ||
600 | |||
601 | static void note_tremolo( ultra_card_t *card, ultra_voice_t *voice ) | ||
602 | { | ||
603 | } | ||
604 | |||
605 | /* | ||
606 | * | ||
607 | */ | ||
608 | |||
609 | static void chn_trigger_down( ultra_card_t *card, ultra_channel_t *channel, ultra_instrument_t *instrument, unsigned char note, unsigned char velocity, unsigned char priority ) | ||
610 | { | ||
611 | } | ||
612 | |||
613 | static void chn_trigger_up( ultra_card_t *card, ultra_note_t *note ) | ||
614 | { | ||
615 | } | ||
616 | |||
617 | static void chn_control( ultra_card_t *card, ultra_channel_t *channel, unsigned short p1, unsigned short p2 ) | ||
618 | { | ||
619 | } | ||
620 | |||
621 | /* | ||
622 | * | ||
623 | */ | ||
624 | |||
625 | #endif | ||
626 | |||
627 | void snd_gf1_simple_init(struct snd_gus_voice *voice) | ||
628 | { | ||
629 | voice->handler_wave = interrupt_wave; | ||
630 | voice->handler_volume = interrupt_volume; | ||
631 | voice->handler_effect = interrupt_effect; | ||
632 | voice->volume_change = NULL; | ||
633 | voice->sample_ops = &sample_ops; | ||
634 | } | ||
diff --git a/sound/isa/gus/gus_synth.c b/sound/isa/gus/gus_synth.c deleted file mode 100644 index 2c2051782aa2..000000000000 --- a/sound/isa/gus/gus_synth.c +++ /dev/null | |||
@@ -1,314 +0,0 @@ | |||
1 | /* | ||
2 | * Routines for Gravis UltraSound soundcards - Synthesizer | ||
3 | * Copyright (c) by Jaroslav Kysela <perex@perex.cz> | ||
4 | * | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #include <sound/driver.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/time.h> | ||
25 | #include <sound/core.h> | ||
26 | #include <sound/gus.h> | ||
27 | #include <sound/seq_device.h> | ||
28 | |||
29 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); | ||
30 | MODULE_DESCRIPTION("Routines for Gravis UltraSound soundcards - Synthesizer"); | ||
31 | MODULE_LICENSE("GPL"); | ||
32 | |||
33 | /* | ||
34 | * | ||
35 | */ | ||
36 | |||
37 | static void snd_gus_synth_free_voices(struct snd_gus_card * gus, int client, int port) | ||
38 | { | ||
39 | int idx; | ||
40 | struct snd_gus_voice * voice; | ||
41 | |||
42 | for (idx = 0; idx < 32; idx++) { | ||
43 | voice = &gus->gf1.voices[idx]; | ||
44 | if (voice->use && voice->client == client && voice->port == port) | ||
45 | snd_gf1_free_voice(gus, voice); | ||
46 | } | ||
47 | } | ||
48 | |||
49 | static int snd_gus_synth_use(void *private_data, struct snd_seq_port_subscribe *info) | ||
50 | { | ||
51 | struct snd_gus_port * port = private_data; | ||
52 | struct snd_gus_card * gus = port->gus; | ||
53 | struct snd_gus_voice * voice; | ||
54 | unsigned int idx; | ||
55 | |||
56 | if (info->voices > 32) | ||
57 | return -EINVAL; | ||
58 | mutex_lock(&gus->register_mutex); | ||
59 | if (!snd_gus_use_inc(gus)) { | ||
60 | mutex_unlock(&gus->register_mutex); | ||
61 | return -EFAULT; | ||
62 | } | ||
63 | for (idx = 0; idx < info->voices; idx++) { | ||
64 | voice = snd_gf1_alloc_voice(gus, SNDRV_GF1_VOICE_TYPE_SYNTH, info->sender.client, info->sender.port); | ||
65 | if (voice == NULL) { | ||
66 | snd_gus_synth_free_voices(gus, info->sender.client, info->sender.port); | ||
67 | snd_gus_use_dec(gus); | ||
68 | mutex_unlock(&gus->register_mutex); | ||
69 | return -EBUSY; | ||
70 | } | ||
71 | voice->index = idx; | ||
72 | } | ||
73 | mutex_unlock(&gus->register_mutex); | ||
74 | return 0; | ||
75 | } | ||
76 | |||
77 | static int snd_gus_synth_unuse(void *private_data, struct snd_seq_port_subscribe *info) | ||
78 | { | ||
79 | struct snd_gus_port * port = private_data; | ||
80 | struct snd_gus_card * gus = port->gus; | ||
81 | |||
82 | mutex_lock(&gus->register_mutex); | ||
83 | snd_gus_synth_free_voices(gus, info->sender.client, info->sender.port); | ||
84 | snd_gus_use_dec(gus); | ||
85 | mutex_unlock(&gus->register_mutex); | ||
86 | return 0; | ||
87 | } | ||
88 | |||
89 | /* | ||
90 | * | ||
91 | */ | ||
92 | |||
93 | static void snd_gus_synth_free_private_instruments(struct snd_gus_port *p, int client) | ||
94 | { | ||
95 | struct snd_seq_instr_header ifree; | ||
96 | |||
97 | memset(&ifree, 0, sizeof(ifree)); | ||
98 | ifree.cmd = SNDRV_SEQ_INSTR_FREE_CMD_PRIVATE; | ||
99 | snd_seq_instr_list_free_cond(p->gus->gf1.ilist, &ifree, client, 0); | ||
100 | } | ||
101 | |||
102 | static int snd_gus_synth_event_input(struct snd_seq_event *ev, int direct, | ||
103 | void *private_data, int atomic, int hop) | ||
104 | { | ||
105 | struct snd_gus_port * p = private_data; | ||
106 | |||
107 | snd_assert(p != NULL, return -EINVAL); | ||
108 | if (ev->type >= SNDRV_SEQ_EVENT_SAMPLE && | ||
109 | ev->type <= SNDRV_SEQ_EVENT_SAMPLE_PRIVATE1) { | ||
110 | snd_gus_sample_event(ev, p); | ||
111 | return 0; | ||
112 | } | ||
113 | if (ev->source.client == SNDRV_SEQ_CLIENT_SYSTEM && | ||
114 | ev->source.port == SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE) { | ||
115 | if (ev->type == SNDRV_SEQ_EVENT_CLIENT_EXIT) { | ||
116 | snd_gus_synth_free_private_instruments(p, ev->data.addr.client); | ||
117 | return 0; | ||
118 | } | ||
119 | } | ||
120 | if (direct) { | ||
121 | if (ev->type >= SNDRV_SEQ_EVENT_INSTR_BEGIN) { | ||
122 | snd_seq_instr_event(&p->gus->gf1.iwffff_ops.kops, | ||
123 | p->gus->gf1.ilist, | ||
124 | ev, | ||
125 | p->gus->gf1.seq_client, | ||
126 | atomic, hop); | ||
127 | return 0; | ||
128 | } | ||
129 | } | ||
130 | return 0; | ||
131 | } | ||
132 | |||
133 | static void snd_gus_synth_instr_notify(void *private_data, | ||
134 | struct snd_seq_kinstr *instr, | ||
135 | int what) | ||
136 | { | ||
137 | unsigned int idx; | ||
138 | struct snd_gus_card *gus = private_data; | ||
139 | struct snd_gus_voice *pvoice; | ||
140 | unsigned long flags; | ||
141 | |||
142 | spin_lock_irqsave(&gus->event_lock, flags); | ||
143 | for (idx = 0; idx < 32; idx++) { | ||
144 | pvoice = &gus->gf1.voices[idx]; | ||
145 | if (pvoice->use && !memcmp(&pvoice->instr, &instr->instr, sizeof(pvoice->instr))) { | ||
146 | if (pvoice->sample_ops && pvoice->sample_ops->sample_stop) { | ||
147 | pvoice->sample_ops->sample_stop(gus, pvoice, SAMPLE_STOP_IMMEDIATELY); | ||
148 | } else { | ||
149 | snd_gf1_stop_voice(gus, pvoice->number); | ||
150 | pvoice->flags &= ~SNDRV_GF1_VFLG_RUNNING; | ||
151 | } | ||
152 | } | ||
153 | } | ||
154 | spin_unlock_irqrestore(&gus->event_lock, flags); | ||
155 | } | ||
156 | |||
157 | /* | ||
158 | * | ||
159 | */ | ||
160 | |||
161 | static void snd_gus_synth_free_port(void *private_data) | ||
162 | { | ||
163 | struct snd_gus_port * p = private_data; | ||
164 | |||
165 | if (p) | ||
166 | snd_midi_channel_free_set(p->chset); | ||
167 | } | ||
168 | |||
169 | static int snd_gus_synth_create_port(struct snd_gus_card * gus, int idx) | ||
170 | { | ||
171 | struct snd_gus_port * p; | ||
172 | struct snd_seq_port_callback callbacks; | ||
173 | char name[32]; | ||
174 | int result; | ||
175 | |||
176 | p = &gus->gf1.seq_ports[idx]; | ||
177 | p->chset = snd_midi_channel_alloc_set(16); | ||
178 | if (p->chset == NULL) | ||
179 | return -ENOMEM; | ||
180 | p->chset->private_data = p; | ||
181 | p->gus = gus; | ||
182 | p->client = gus->gf1.seq_client; | ||
183 | |||
184 | memset(&callbacks, 0, sizeof(callbacks)); | ||
185 | callbacks.owner = THIS_MODULE; | ||
186 | callbacks.use = snd_gus_synth_use; | ||
187 | callbacks.unuse = snd_gus_synth_unuse; | ||
188 | callbacks.event_input = snd_gus_synth_event_input; | ||
189 | callbacks.private_free = snd_gus_synth_free_port; | ||
190 | callbacks.private_data = p; | ||
191 | |||
192 | sprintf(name, "%s port %i", gus->interwave ? "AMD InterWave" : "GF1", idx); | ||
193 | p->chset->port = snd_seq_event_port_attach(gus->gf1.seq_client, | ||
194 | &callbacks, | ||
195 | SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE, | ||
196 | SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE | | ||
197 | SNDRV_SEQ_PORT_TYPE_SYNTH | | ||
198 | SNDRV_SEQ_PORT_TYPE_HARDWARE | | ||
199 | SNDRV_SEQ_PORT_TYPE_SYNTHESIZER, | ||
200 | 16, 0, | ||
201 | name); | ||
202 | if (p->chset->port < 0) { | ||
203 | result = p->chset->port; | ||
204 | snd_gus_synth_free_port(p); | ||
205 | return result; | ||
206 | } | ||
207 | p->port = p->chset->port; | ||
208 | return 0; | ||
209 | } | ||
210 | |||
211 | /* | ||
212 | * | ||
213 | */ | ||
214 | |||
215 | static int snd_gus_synth_new_device(struct snd_seq_device *dev) | ||
216 | { | ||
217 | struct snd_gus_card *gus; | ||
218 | int client, i; | ||
219 | struct snd_seq_port_subscribe sub; | ||
220 | struct snd_iwffff_ops *iwops; | ||
221 | struct snd_gf1_ops *gf1ops; | ||
222 | struct snd_simple_ops *simpleops; | ||
223 | |||
224 | gus = *(struct snd_gus_card **)SNDRV_SEQ_DEVICE_ARGPTR(dev); | ||
225 | if (gus == NULL) | ||
226 | return -EINVAL; | ||
227 | |||
228 | mutex_init(&gus->register_mutex); | ||
229 | gus->gf1.seq_client = -1; | ||
230 | |||
231 | /* allocate new client */ | ||
232 | client = gus->gf1.seq_client = | ||
233 | snd_seq_create_kernel_client(gus->card, 1, gus->interwave ? | ||
234 | "AMD InterWave" : "GF1"); | ||
235 | if (client < 0) | ||
236 | return client; | ||
237 | |||
238 | for (i = 0; i < 4; i++) | ||
239 | snd_gus_synth_create_port(gus, i); | ||
240 | |||
241 | gus->gf1.ilist = snd_seq_instr_list_new(); | ||
242 | if (gus->gf1.ilist == NULL) { | ||
243 | snd_seq_delete_kernel_client(client); | ||
244 | gus->gf1.seq_client = -1; | ||
245 | return -ENOMEM; | ||
246 | } | ||
247 | gus->gf1.ilist->flags = SNDRV_SEQ_INSTR_FLG_DIRECT; | ||
248 | |||
249 | simpleops = &gus->gf1.simple_ops; | ||
250 | snd_seq_simple_init(simpleops, gus, NULL); | ||
251 | simpleops->put_sample = snd_gus_simple_put_sample; | ||
252 | simpleops->get_sample = snd_gus_simple_get_sample; | ||
253 | simpleops->remove_sample = snd_gus_simple_remove_sample; | ||
254 | simpleops->notify = snd_gus_synth_instr_notify; | ||
255 | |||
256 | gf1ops = &gus->gf1.gf1_ops; | ||
257 | snd_seq_gf1_init(gf1ops, gus, &simpleops->kops); | ||
258 | gf1ops->put_sample = snd_gus_gf1_put_sample; | ||
259 | gf1ops->get_sample = snd_gus_gf1_get_sample; | ||
260 | gf1ops->remove_sample = snd_gus_gf1_remove_sample; | ||
261 | gf1ops->notify = snd_gus_synth_instr_notify; | ||
262 | |||
263 | iwops = &gus->gf1.iwffff_ops; | ||
264 | snd_seq_iwffff_init(iwops, gus, &gf1ops->kops); | ||
265 | iwops->put_sample = snd_gus_iwffff_put_sample; | ||
266 | iwops->get_sample = snd_gus_iwffff_get_sample; | ||
267 | iwops->remove_sample = snd_gus_iwffff_remove_sample; | ||
268 | iwops->notify = snd_gus_synth_instr_notify; | ||
269 | |||
270 | memset(&sub, 0, sizeof(sub)); | ||
271 | sub.sender.client = SNDRV_SEQ_CLIENT_SYSTEM; | ||
272 | sub.sender.port = SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE; | ||
273 | sub.dest.client = client; | ||
274 | sub.dest.port = 0; | ||
275 | snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT, &sub); | ||
276 | |||
277 | return 0; | ||
278 | } | ||
279 | |||
280 | static int snd_gus_synth_delete_device(struct snd_seq_device *dev) | ||
281 | { | ||
282 | struct snd_gus_card *gus; | ||
283 | |||
284 | gus = *(struct snd_gus_card **)SNDRV_SEQ_DEVICE_ARGPTR(dev); | ||
285 | if (gus == NULL) | ||
286 | return -EINVAL; | ||
287 | |||
288 | if (gus->gf1.seq_client >= 0) { | ||
289 | snd_seq_delete_kernel_client(gus->gf1.seq_client); | ||
290 | gus->gf1.seq_client = -1; | ||
291 | } | ||
292 | if (gus->gf1.ilist) | ||
293 | snd_seq_instr_list_free(&gus->gf1.ilist); | ||
294 | return 0; | ||
295 | } | ||
296 | |||
297 | static int __init alsa_gus_synth_init(void) | ||
298 | { | ||
299 | static struct snd_seq_dev_ops ops = { | ||
300 | snd_gus_synth_new_device, | ||
301 | snd_gus_synth_delete_device | ||
302 | }; | ||
303 | |||
304 | return snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_GUS, &ops, | ||
305 | sizeof(struct snd_gus_card *)); | ||
306 | } | ||
307 | |||
308 | static void __exit alsa_gus_synth_exit(void) | ||
309 | { | ||
310 | snd_seq_device_unregister_driver(SNDRV_SEQ_DEV_ID_GUS); | ||
311 | } | ||
312 | |||
313 | module_init(alsa_gus_synth_init) | ||
314 | module_exit(alsa_gus_synth_exit) | ||