]> bbs.cooldavid.org Git - net-next-2.6.git/blame - sound/isa/gus/gus_simple.c
[ALSA] Changed Jaroslav Kysela's e-mail from perex@suse.cz to perex@perex.cz
[net-next-2.6.git] / sound / isa / gus / gus_simple.c
CommitLineData
1da177e4
LT
1/*
2 * Routines for Gravis UltraSound soundcards - Simple instrument handlers
c1017a4c 3 * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
1da177e4
LT
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
5e2da206
TI
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 = {
1da177e4
LT
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
5e2da206
TI
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);
1da177e4
LT
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
5e2da206 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 );
1da177e4
LT
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
5e2da206
TI
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);
1da177e4
LT
88
89/*
90 *
91 */
92
5e2da206 93static void interrupt_wave(struct snd_gus_card *gus, struct snd_gus_voice *voice)
1da177e4
LT
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
5e2da206 105static void interrupt_volume(struct snd_gus_card *gus, struct snd_gus_voice *voice)
1da177e4
LT
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
5e2da206 115static void interrupt_effect(struct snd_gus_card *gus, struct snd_gus_voice *voice)
1da177e4
LT
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
5e2da206 128static void do_volume_envelope(struct snd_gus_card *gus, struct snd_gus_voice *voice)
1da177e4
LT
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);
99b359ba 139 /* printk("gf1_volume = 0x%x\n", voice->gf1_volume); */
1da177e4
LT
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
5e2da206 232static void do_pan_envelope(struct snd_gus_card *gus, struct snd_gus_voice *voice)
1da177e4
LT
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
5e2da206 279static void set_enhanced_pan(struct snd_gus_card *gus, struct snd_gus_voice *voice, unsigned short pan)
1da177e4
LT
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
5e2da206 310static void sample_start(struct snd_gus_card *gus, struct snd_gus_voice *voice, snd_seq_position_t position)
1da177e4
LT
311{
312 unsigned long flags;
313 unsigned int begin, addr, addr_end, addr_start;
314 int w_16;
5e2da206
TI
315 struct simple_instrument *simple;
316 struct snd_seq_kinstr *instr;
1da177e4
LT
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
5e2da206 400static void sample_stop(struct snd_gus_card *gus, struct snd_gus_voice *voice, int mode)
1da177e4
LT
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
5e2da206 436static void sample_freq(struct snd_gus_card *gus, struct snd_gus_voice *voice, snd_seq_frequency_t freq)
1da177e4
LT
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
5e2da206 447static void sample_volume(struct snd_gus_card *gus, struct snd_gus_voice *voice, struct snd_seq_ev_volume *volume)
1da177e4
LT
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
5e2da206 474static void sample_loop(struct snd_gus_card *gus, struct snd_gus_voice *voice, struct snd_seq_ev_loop *loop)
1da177e4
LT
475{
476 unsigned long flags;
477 int w_16 = voice->control & 0x04;
478 unsigned int begin, addr_start, addr_end;
5e2da206
TI
479 struct simple_instrument *simple;
480 struct snd_seq_kinstr *instr;
1da177e4
LT
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
5e2da206 503static void sample_pos(struct snd_gus_card *gus, struct snd_gus_voice *voice, snd_seq_position_t position)
1da177e4
LT
504{
505 unsigned long flags;
506 int w_16 = voice->control & 0x04;
507 unsigned int begin, addr;
5e2da206
TI
508 struct simple_instrument *simple;
509 struct snd_seq_kinstr *instr;
1da177e4
LT
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
5e2da206 540static void sample_private1(struct snd_gus_card *card, struct snd_gus_voice *voice, unsigned char *data)
1da177e4
LT
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
5e2da206 627void snd_gf1_simple_init(struct snd_gus_voice *voice)
1da177e4
LT
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}