aboutsummaryrefslogtreecommitdiffstats
path: root/sound/isa
diff options
context:
space:
mode:
Diffstat (limited to 'sound/isa')
-rw-r--r--sound/isa/gus/Makefile12
-rw-r--r--sound/isa/gus/gus_main.c23
-rw-r--r--sound/isa/gus/gus_sample.c165
-rw-r--r--sound/isa/gus/gus_simple.c634
-rw-r--r--sound/isa/gus/gus_synth.c314
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
12snd-gus-synth-objs := gus_synth.o gus_sample.o gus_simple.o gus_instr.o
13 12
14snd-gusclassic-objs := gusclassic.o 13snd-gusclassic-objs := gusclassic.o
15snd-gusextreme-objs := gusextreme.o 14snd-gusextreme-objs := gusextreme.o
@@ -17,20 +16,9 @@ snd-gusmax-objs := gusmax.o
17snd-interwave-objs := interwave.o 16snd-interwave-objs := interwave.o
18snd-interwave-stb-objs := interwave-stb.o 17snd-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#
26sequencer = $(if $(subst y,,$(CONFIG_SND_SEQUENCER)),$(if $(1),m),$(if $(CONFIG_SND_SEQUENCER),$(1)))
27
28# Toplevel Module Dependency 19# Toplevel Module Dependency
29obj-$(CONFIG_SND_GUSCLASSIC) += snd-gusclassic.o snd-gus-lib.o 20obj-$(CONFIG_SND_GUSCLASSIC) += snd-gusclassic.o snd-gus-lib.o
30obj-$(CONFIG_SND_GUSMAX) += snd-gusmax.o snd-gus-lib.o 21obj-$(CONFIG_SND_GUSMAX) += snd-gusmax.o snd-gus-lib.o
31obj-$(CONFIG_SND_GUSEXTREME) += snd-gusextreme.o snd-gus-lib.o 22obj-$(CONFIG_SND_GUSEXTREME) += snd-gusextreme.o snd-gus-lib.o
32obj-$(CONFIG_SND_INTERWAVE) += snd-interwave.o snd-gus-lib.o 23obj-$(CONFIG_SND_INTERWAVE) += snd-interwave.o snd-gus-lib.o
33obj-$(CONFIG_SND_INTERWAVE_STB) += snd-interwave-stb.o snd-gus-lib.o 24obj-$(CONFIG_SND_INTERWAVE_STB) += snd-interwave-stb.o snd-gus-lib.o
34obj-$(call sequencer,$(CONFIG_SND_GUS_SYNTH)) += snd-gus-synth.o
35
36obj-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))
412static 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
419int snd_gus_initialize(struct snd_gus_card *gus) 405int 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
31static 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
56static 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
71static 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
80static 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
87static 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
94static 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
101static 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
108static 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
115static 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
122static 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
129typedef void (gus_sample_event_handler_t)(struct snd_seq_event *ev,
130 struct snd_gus_port *p,
131 struct snd_gus_voice *v);
132static 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
144void 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
32static void interrupt_wave(struct snd_gus_card *gus, struct snd_gus_voice *voice);
33static void interrupt_volume(struct snd_gus_card *gus, struct snd_gus_voice *voice);
34static void interrupt_effect(struct snd_gus_card *gus, struct snd_gus_voice *voice);
35
36static void sample_start(struct snd_gus_card *gus, struct snd_gus_voice *voice, snd_seq_position_t position);
37static void sample_stop(struct snd_gus_card *gus, struct snd_gus_voice *voice, int mode);
38static void sample_freq(struct snd_gus_card *gus, struct snd_gus_voice *voice, snd_seq_frequency_t freq);
39static void sample_volume(struct snd_gus_card *card, struct snd_gus_voice *voice, struct snd_seq_ev_volume *volume);
40static void sample_loop(struct snd_gus_card *card, struct snd_gus_voice *voice, struct snd_seq_ev_loop *loop);
41static void sample_pos(struct snd_gus_card *card, struct snd_gus_voice *voice, snd_seq_position_t position);
42static void sample_private1(struct snd_gus_card *card, struct snd_gus_voice *voice, unsigned char *data);
43
44static 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
56static void note_stop(struct snd_gus_card *gus, struct snd_gus_voice *voice, int wait);
57static void note_wait(struct snd_gus_card *gus, struct snd_gus_voice *voice);
58static void note_off(struct snd_gus_card *gus, struct snd_gus_voice *voice);
59static void note_volume(struct snd_gus_card *card, struct snd_gus_voice *voice);
60static void note_pitchbend(struct snd_gus_card *card, struct snd_gus_voice *voice);
61static void note_vibrato(struct snd_gus_card *card, struct snd_gus_voice *voice);
62static void note_tremolo(struct snd_gus_card *card, struct snd_gus_voice *voice);
63
64static 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
74static 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 );
75static void chn_trigger_up( ultra_card_t *card, ultra_note_t *note );
76static void chn_control( ultra_card_t *card, ultra_channel_t *channel, unsigned short p1, unsigned short p2 );
77
78static struct ULTRA_STRU_INSTRUMENT_CHANNEL_COMMANDS channel_commands = {
79 chn_trigger_down,
80 chn_trigger_up,
81 chn_control
82};
83
84#endif
85
86static void do_volume_envelope(struct snd_gus_card *card, struct snd_gus_voice *voice);
87static void do_pan_envelope(struct snd_gus_card *card, struct snd_gus_voice *voice);
88
89/*
90 *
91 */
92
93static 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
105static 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
115static 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
128static 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
232static 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
279static 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
310static 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
400static 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
436static 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
447static 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
474static 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
503static 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
530static 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
540static 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
577static void note_stop( ultra_card_t *card, ultra_voice_t *voice, int wait )
578{
579}
580
581static void note_wait( ultra_card_t *card, ultra_voice_t *voice )
582{
583}
584
585static void note_off( ultra_card_t *card, ultra_voice_t *voice )
586{
587}
588
589static void note_volume( ultra_card_t *card, ultra_voice_t *voice )
590{
591}
592
593static void note_pitchbend( ultra_card_t *card, ultra_voice_t *voice )
594{
595}
596
597static void note_vibrato( ultra_card_t *card, ultra_voice_t *voice )
598{
599}
600
601static void note_tremolo( ultra_card_t *card, ultra_voice_t *voice )
602{
603}
604
605/*
606 *
607 */
608
609static 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
613static void chn_trigger_up( ultra_card_t *card, ultra_note_t *note )
614{
615}
616
617static 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
627void 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
29MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
30MODULE_DESCRIPTION("Routines for Gravis UltraSound soundcards - Synthesizer");
31MODULE_LICENSE("GPL");
32
33/*
34 *
35 */
36
37static 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
49static 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
77static 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
93static 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
102static 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
133static 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
161static 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
169static 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
215static 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
280static 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
297static 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
308static void __exit alsa_gus_synth_exit(void)
309{
310 snd_seq_device_unregister_driver(SNDRV_SEQ_DEV_ID_GUS);
311}
312
313module_init(alsa_gus_synth_init)
314module_exit(alsa_gus_synth_exit)