patch-2.1.67 linux/drivers/sound/gus_wave.c
Next file: linux/drivers/sound/ics2101.c
Previous file: linux/drivers/sound/gus_vol.c
Back to the patch index
Back to the overall index
- Lines: 6398
- Date:
Sat Nov 29 10:33:20 1997
- Orig file:
v2.1.66/linux/drivers/sound/gus_wave.c
- Orig date:
Wed Nov 12 13:34:26 1997
diff -u --recursive --new-file v2.1.66/linux/drivers/sound/gus_wave.c linux/drivers/sound/gus_wave.c
@@ -19,7 +19,7 @@
#include <linux/ultrasound.h>
#include "gus_hw.h"
-#ifdef CONFIG_GUSHW
+#if defined(CONFIG_GUSHW) || defined(MODULE)
#define GUS_BANK_SIZE (((iw_mode) ? 256*1024*1024 : 256*1024))
@@ -30,38 +30,39 @@
struct voice_info
{
- unsigned long orig_freq;
- unsigned long current_freq;
- unsigned long mode;
- int fixed_pitch;
- int bender;
- int bender_range;
- int panning;
- int midi_volume;
- unsigned int initial_volume;
- unsigned int current_volume;
- int loop_irq_mode, loop_irq_parm;
+ unsigned long orig_freq;
+ unsigned long current_freq;
+ unsigned long mode;
+ int fixed_pitch;
+ int bender;
+ int bender_range;
+ int panning;
+ int midi_volume;
+ unsigned int initial_volume;
+ unsigned int current_volume;
+ int loop_irq_mode, loop_irq_parm;
#define LMODE_FINISH 1
#define LMODE_PCM 2
#define LMODE_PCM_STOP 3
- int volume_irq_mode, volume_irq_parm;
+ int volume_irq_mode, volume_irq_parm;
#define VMODE_HALT 1
#define VMODE_ENVELOPE 2
#define VMODE_START_NOTE 3
- int env_phase;
- unsigned char env_rate[6];
- unsigned char env_offset[6];
-
- /*
- * Volume computation parameters for gus_adagio_vol()
- */
- int main_vol, expression_vol, patch_vol;
-
- /* Variables for "Ultraclick" removal */
- int dev_pending, note_pending, volume_pending, sample_pending;
- char kill_pending;
- long offset_pending;
+ int env_phase;
+ unsigned char env_rate[6];
+ unsigned char env_offset[6];
+
+ /*
+ * Volume computation parameters for gus_adagio_vol()
+ */
+ int main_vol, expression_vol, patch_vol;
+
+ /* Variables for "Ultraclick" removal */
+ int dev_pending, note_pending, volume_pending,
+ sample_pending;
+ char kill_pending;
+ long offset_pending;
};
@@ -136,26 +137,26 @@
static int freq_div_table[] =
{
- 44100,
- 44100, /* 14 */
- 41160, /* 15 */
- 38587, /* 16 */
- 36317, /* 17 */
- 34300, /* 18 */
- 32494, /* 19 */
- 30870, /* 20 */
- 29400, /* 21 */
- 28063, /* 22 */
- 26843, /* 23 */
- 25725, /* 24 */
- 24696, /* 25 */
- 23746, /* 26 */
- 22866, /* 27 */
- 22050, /* 28 */
- 21289, /* 29 */
- 20580, /* 30 */
- 19916, /* 31 */
- 19293 /* 32 */
+ 44100,
+ 44100, /* 14 */
+ 41160, /* 15 */
+ 38587, /* 16 */
+ 36317, /* 17 */
+ 34300, /* 18 */
+ 32494, /* 19 */
+ 30870, /* 20 */
+ 29400, /* 21 */
+ 28063, /* 22 */
+ 26843, /* 23 */
+ 25725, /* 24 */
+ 24696, /* 25 */
+ 23746, /* 26 */
+ 22866, /* 27 */
+ 22050, /* 28 */
+ 21289, /* 29 */
+ 20580, /* 30 */
+ 19916, /* 31 */
+ 19293 /* 32 */
};
static struct patch_info *samples;
@@ -171,722 +172,711 @@
static struct synth_info gus_info =
{"Gravis UltraSound", 0, SYNTH_TYPE_SAMPLE, SAMPLE_TYPE_GUS, 0, 16, 0, MAX_PATCH};
-static void gus_poke (long addr, unsigned char data);
-static void compute_and_set_volume (int voice, int volume, int ramp_time);
-extern unsigned short gus_adagio_vol (int vel, int mainv, int xpn, int voicev);
-extern unsigned short gus_linear_vol (int vol, int mainvol);
-static void compute_volume (int voice, int volume);
-static void do_volume_irq (int voice);
-static void set_input_volumes (void);
-static void gus_tmr_install (int io_base);
+static void gus_poke(long addr, unsigned char data);
+static void compute_and_set_volume(int voice, int volume, int ramp_time);
+extern unsigned short gus_adagio_vol(int vel, int mainv, int xpn, int voicev);
+extern unsigned short gus_linear_vol(int vol, int mainvol);
+static void compute_volume(int voice, int volume);
+static void do_volume_irq(int voice);
+static void set_input_volumes(void);
+static void gus_tmr_install(int io_base);
#define INSTANT_RAMP -1 /* Instant change. No ramping */
#define FAST_RAMP 0 /* Fastest possible ramp */
static void
-reset_sample_memory (void)
+reset_sample_memory(void)
{
- int i;
+ int i;
- for (i = 0; i <= MAX_SAMPLE; i++)
- sample_ptrs[i] = -1;
- for (i = 0; i < 32; i++)
- sample_map[i] = -1;
- for (i = 0; i < 32; i++)
- patch_map[i] = -1;
+ for (i = 0; i <= MAX_SAMPLE; i++)
+ sample_ptrs[i] = -1;
+ for (i = 0; i < 32; i++)
+ sample_map[i] = -1;
+ for (i = 0; i < 32; i++)
+ patch_map[i] = -1;
- gus_poke (0, 0); /* Put a silent sample to the beginning */
- gus_poke (1, 0);
- free_mem_ptr = 2;
+ gus_poke(0, 0); /* Put a silent sample to the beginning */
+ gus_poke(1, 0);
+ free_mem_ptr = 2;
- free_sample = 0;
+ free_sample = 0;
- for (i = 0; i < MAX_PATCH; i++)
- patch_table[i] = NOT_SAMPLE;
+ for (i = 0; i < MAX_PATCH; i++)
+ patch_table[i] = NOT_SAMPLE;
}
void
-gus_delay (void)
+gus_delay(void)
{
- int i;
+ int i;
- for (i = 0; i < 7; i++)
- inb (u_DRAMIO);
+ for (i = 0; i < 7; i++)
+ inb(u_DRAMIO);
}
static void
-gus_poke (long addr, unsigned char data)
+gus_poke(long addr, unsigned char data)
{ /* Writes a byte to the DRAM */
- unsigned long flags;
+ unsigned long flags;
- save_flags (flags);
- cli ();
- outb ((0x43), u_Command);
- outb ((addr & 0xff), u_DataLo);
- outb (((addr >> 8) & 0xff), u_DataHi);
-
- outb ((0x44), u_Command);
- outb (((addr >> 16) & 0xff), u_DataHi);
- outb ((data), u_DRAMIO);
- restore_flags (flags);
+ save_flags(flags);
+ cli();
+ outb((0x43), u_Command);
+ outb((addr & 0xff), u_DataLo);
+ outb(((addr >> 8) & 0xff), u_DataHi);
+
+ outb((0x44), u_Command);
+ outb(((addr >> 16) & 0xff), u_DataHi);
+ outb((data), u_DRAMIO);
+ restore_flags(flags);
}
static unsigned char
-gus_peek (long addr)
+gus_peek(long addr)
{ /* Reads a byte from the DRAM */
- unsigned long flags;
- unsigned char tmp;
+ unsigned long flags;
+ unsigned char tmp;
- save_flags (flags);
- cli ();
- outb ((0x43), u_Command);
- outb ((addr & 0xff), u_DataLo);
- outb (((addr >> 8) & 0xff), u_DataHi);
-
- outb ((0x44), u_Command);
- outb (((addr >> 16) & 0xff), u_DataHi);
- tmp = inb (u_DRAMIO);
- restore_flags (flags);
+ save_flags(flags);
+ cli();
+ outb((0x43), u_Command);
+ outb((addr & 0xff), u_DataLo);
+ outb(((addr >> 8) & 0xff), u_DataHi);
+
+ outb((0x44), u_Command);
+ outb(((addr >> 16) & 0xff), u_DataHi);
+ tmp = inb(u_DRAMIO);
+ restore_flags(flags);
- return tmp;
+ return tmp;
}
void
-gus_write8 (int reg, unsigned int data)
+gus_write8(int reg, unsigned int data)
{ /* Writes to an indirect register (8 bit) */
- unsigned long flags;
+ unsigned long flags;
- save_flags (flags);
- cli ();
+ save_flags(flags);
+ cli();
- outb ((reg), u_Command);
- outb (((unsigned char) (data & 0xff)), u_DataHi);
+ outb((reg), u_Command);
+ outb(((unsigned char) (data & 0xff)), u_DataHi);
- restore_flags (flags);
+ restore_flags(flags);
}
static unsigned char
-gus_read8 (int reg)
+gus_read8(int reg)
{ /* Reads from an indirect register (8 bit). Offset 0x80. */
- unsigned long flags;
- unsigned char val;
+ unsigned long flags;
+ unsigned char val;
- save_flags (flags);
- cli ();
- outb ((reg | 0x80), u_Command);
- val = inb (u_DataHi);
- restore_flags (flags);
+ save_flags(flags);
+ cli();
+ outb((reg | 0x80), u_Command);
+ val = inb(u_DataHi);
+ restore_flags(flags);
- return val;
+ return val;
}
static unsigned char
-gus_look8 (int reg)
+gus_look8(int reg)
{ /* Reads from an indirect register (8 bit). No additional offset. */
- unsigned long flags;
- unsigned char val;
+ unsigned long flags;
+ unsigned char val;
- save_flags (flags);
- cli ();
- outb ((reg), u_Command);
- val = inb (u_DataHi);
- restore_flags (flags);
+ save_flags(flags);
+ cli();
+ outb((reg), u_Command);
+ val = inb(u_DataHi);
+ restore_flags(flags);
- return val;
+ return val;
}
static void
-gus_write16 (int reg, unsigned int data)
+gus_write16(int reg, unsigned int data)
{ /* Writes to an indirect register (16 bit) */
- unsigned long flags;
+ unsigned long flags;
- save_flags (flags);
- cli ();
+ save_flags(flags);
+ cli();
- outb ((reg), u_Command);
+ outb((reg), u_Command);
- outb (((unsigned char) (data & 0xff)), u_DataLo);
- outb (((unsigned char) ((data >> 8) & 0xff)), u_DataHi);
+ outb(((unsigned char) (data & 0xff)), u_DataLo);
+ outb(((unsigned char) ((data >> 8) & 0xff)), u_DataHi);
- restore_flags (flags);
+ restore_flags(flags);
}
static unsigned short
-gus_read16 (int reg)
+gus_read16(int reg)
{ /* Reads from an indirect register (16 bit). Offset 0x80. */
- unsigned long flags;
- unsigned char hi, lo;
+ unsigned long flags;
+ unsigned char hi, lo;
- save_flags (flags);
- cli ();
+ save_flags(flags);
+ cli();
- outb ((reg | 0x80), u_Command);
+ outb((reg | 0x80), u_Command);
- lo = inb (u_DataLo);
- hi = inb (u_DataHi);
+ lo = inb(u_DataLo);
+ hi = inb(u_DataHi);
- restore_flags (flags);
+ restore_flags(flags);
- return ((hi << 8) & 0xff00) | lo;
+ return ((hi << 8) & 0xff00) | lo;
}
static unsigned short
-gus_look16 (int reg)
+gus_look16(int reg)
{ /* Reads from an indirect register (16 bit). No additional offset. */
- unsigned long flags;
- unsigned char hi, lo;
+ unsigned long flags;
+ unsigned char hi, lo;
- save_flags (flags);
- cli ();
+ save_flags(flags);
+ cli();
- outb ((reg), u_Command);
+ outb((reg), u_Command);
- lo = inb (u_DataLo);
- hi = inb (u_DataHi);
+ lo = inb(u_DataLo);
+ hi = inb(u_DataHi);
- restore_flags (flags);
+ restore_flags(flags);
- return ((hi << 8) & 0xff00) | lo;
+ return ((hi << 8) & 0xff00) | lo;
}
static void
-gus_write_addr (int reg, unsigned long address, int frac, int is16bit)
+gus_write_addr(int reg, unsigned long address, int frac, int is16bit)
{ /* Writes an 24 bit memory address */
- unsigned long hold_address;
- unsigned long flags;
-
- save_flags (flags);
- cli ();
- if (is16bit)
- {
- if (iw_mode)
- {
- /* Interwave spesific address translations */
- address >>= 1;
- }
- else
- {
- /*
- * Special processing required for 16 bit patches
- */
+ unsigned long hold_address;
+ unsigned long flags;
- hold_address = address;
- address = address >> 1;
- address &= 0x0001ffffL;
- address |= (hold_address & 0x000c0000L);
- }
- }
-
- gus_write16 (reg, (unsigned short) ((address >> 7) & 0xffff));
- gus_write16 (reg + 1, (unsigned short) ((address << 9) & 0xffff)
- + (frac << 5));
- /* Could writing twice fix problems with GUS_VOICE_POS() ? Lets try... */
- gus_delay ();
- gus_write16 (reg, (unsigned short) ((address >> 7) & 0xffff));
- gus_write16 (reg + 1, (unsigned short) ((address << 9) & 0xffff)
- + (frac << 5));
- restore_flags (flags);
+ save_flags(flags);
+ cli();
+ if (is16bit)
+ {
+ if (iw_mode)
+ {
+ /* Interwave spesific address translations */
+ address >>= 1;
+ } else
+ {
+ /*
+ * Special processing required for 16 bit patches
+ */
+
+ hold_address = address;
+ address = address >> 1;
+ address &= 0x0001ffffL;
+ address |= (hold_address & 0x000c0000L);
+ }
+ }
+ gus_write16(reg, (unsigned short) ((address >> 7) & 0xffff));
+ gus_write16(reg + 1, (unsigned short) ((address << 9) & 0xffff)
+ + (frac << 5));
+ /* Could writing twice fix problems with GUS_VOICE_POS() ? Lets try... */
+ gus_delay();
+ gus_write16(reg, (unsigned short) ((address >> 7) & 0xffff));
+ gus_write16(reg + 1, (unsigned short) ((address << 9) & 0xffff)
+ + (frac << 5));
+ restore_flags(flags);
}
static void
-gus_select_voice (int voice)
+gus_select_voice(int voice)
{
- if (voice < 0 || voice > 31)
- return;
+ if (voice < 0 || voice > 31)
+ return;
- outb ((voice), u_Voice);
+ outb((voice), u_Voice);
}
static void
-gus_select_max_voices (int nvoices)
+gus_select_max_voices(int nvoices)
{
- if (iw_mode)
- nvoices = 32;
- if (nvoices < 14)
- nvoices = 14;
- if (nvoices > 32)
- nvoices = 32;
+ if (iw_mode)
+ nvoices = 32;
+ if (nvoices < 14)
+ nvoices = 14;
+ if (nvoices > 32)
+ nvoices = 32;
- voice_alloc->max_voice = nr_voices = nvoices;
+ voice_alloc->max_voice = nr_voices = nvoices;
- gus_write8 (0x0e, (nvoices - 1) | 0xc0);
+ gus_write8(0x0e, (nvoices - 1) | 0xc0);
}
static void
-gus_voice_on (unsigned int mode)
+gus_voice_on(unsigned int mode)
{
- gus_write8 (0x00, (unsigned char) (mode & 0xfc));
- gus_delay ();
- gus_write8 (0x00, (unsigned char) (mode & 0xfc));
+ gus_write8(0x00, (unsigned char) (mode & 0xfc));
+ gus_delay();
+ gus_write8(0x00, (unsigned char) (mode & 0xfc));
}
static void
-gus_voice_off (void)
+gus_voice_off(void)
{
- gus_write8 (0x00, gus_read8 (0x00) | 0x03);
+ gus_write8(0x00, gus_read8(0x00) | 0x03);
}
static void
-gus_voice_mode (unsigned int m)
+gus_voice_mode(unsigned int m)
{
- unsigned char mode = (unsigned char) (m & 0xff);
+ unsigned char mode = (unsigned char) (m & 0xff);
- gus_write8 (0x00, (gus_read8 (0x00) & 0x03) |
- (mode & 0xfc)); /* Don't touch last two bits */
- gus_delay ();
- gus_write8 (0x00, (gus_read8 (0x00) & 0x03) | (mode & 0xfc));
+ gus_write8(0x00, (gus_read8(0x00) & 0x03) |
+ (mode & 0xfc)); /* Don't touch last two bits */
+ gus_delay();
+ gus_write8(0x00, (gus_read8(0x00) & 0x03) | (mode & 0xfc));
}
static void
-gus_voice_freq (unsigned long freq)
+gus_voice_freq(unsigned long freq)
{
- unsigned long divisor = freq_div_table[nr_voices - 14];
- unsigned short fc;
+ unsigned long divisor = freq_div_table[nr_voices - 14];
+ unsigned short fc;
- /* Interwave plays at 44100 Hz with any number of voices */
- if (iw_mode)
- fc = (unsigned short) (((freq << 9) + (44100 >> 1)) / 44100);
- else
- fc = (unsigned short) (((freq << 9) + (divisor >> 1)) / divisor);
- fc = fc << 1;
+ /* Interwave plays at 44100 Hz with any number of voices */
+ if (iw_mode)
+ fc = (unsigned short) (((freq << 9) + (44100 >> 1)) / 44100);
+ else
+ fc = (unsigned short) (((freq << 9) + (divisor >> 1)) / divisor);
+ fc = fc << 1;
- gus_write16 (0x01, fc);
+ gus_write16(0x01, fc);
}
static void
-gus_voice_volume (unsigned int vol)
+gus_voice_volume(unsigned int vol)
{
- gus_write8 (0x0d, 0x03); /* Stop ramp before setting volume */
- gus_write16 (0x09, (unsigned short) (vol << 4));
+ gus_write8(0x0d, 0x03); /* Stop ramp before setting volume */
+ gus_write16(0x09, (unsigned short) (vol << 4));
}
static void
-gus_voice_balance (unsigned int balance)
+gus_voice_balance(unsigned int balance)
{
- gus_write8 (0x0c, (unsigned char) (balance & 0xff));
+ gus_write8(0x0c, (unsigned char) (balance & 0xff));
}
static void
-gus_ramp_range (unsigned int low, unsigned int high)
+gus_ramp_range(unsigned int low, unsigned int high)
{
- gus_write8 (0x07, (unsigned char) ((low >> 4) & 0xff));
- gus_write8 (0x08, (unsigned char) ((high >> 4) & 0xff));
+ gus_write8(0x07, (unsigned char) ((low >> 4) & 0xff));
+ gus_write8(0x08, (unsigned char) ((high >> 4) & 0xff));
}
static void
-gus_ramp_rate (unsigned int scale, unsigned int rate)
+gus_ramp_rate(unsigned int scale, unsigned int rate)
{
- gus_write8 (0x06, (unsigned char) (((scale & 0x03) << 6) | (rate & 0x3f)));
+ gus_write8(0x06, (unsigned char) (((scale & 0x03) << 6) | (rate & 0x3f)));
}
static void
-gus_rampon (unsigned int m)
+gus_rampon(unsigned int m)
{
- unsigned char mode = (unsigned char) (m & 0xff);
+ unsigned char mode = (unsigned char) (m & 0xff);
- gus_write8 (0x0d, mode & 0xfc);
- gus_delay ();
- gus_write8 (0x0d, mode & 0xfc);
+ gus_write8(0x0d, mode & 0xfc);
+ gus_delay();
+ gus_write8(0x0d, mode & 0xfc);
}
static void
-gus_ramp_mode (unsigned int m)
+gus_ramp_mode(unsigned int m)
{
- unsigned char mode = (unsigned char) (m & 0xff);
+ unsigned char mode = (unsigned char) (m & 0xff);
- gus_write8 (0x0d, (gus_read8 (0x0d) & 0x03) |
- (mode & 0xfc)); /* Leave the last 2 bits alone */
- gus_delay ();
- gus_write8 (0x0d, (gus_read8 (0x0d) & 0x03) | (mode & 0xfc));
+ gus_write8(0x0d, (gus_read8(0x0d) & 0x03) |
+ (mode & 0xfc)); /* Leave the last 2 bits alone */
+ gus_delay();
+ gus_write8(0x0d, (gus_read8(0x0d) & 0x03) | (mode & 0xfc));
}
static void
-gus_rampoff (void)
+gus_rampoff(void)
{
- gus_write8 (0x0d, 0x03);
+ gus_write8(0x0d, 0x03);
}
static void
-gus_set_voice_pos (int voice, long position)
+gus_set_voice_pos(int voice, long position)
{
- int sample_no;
+ int sample_no;
- if ((sample_no = sample_map[voice]) != -1)
- if (position < samples[sample_no].len)
- if (voices[voice].volume_irq_mode == VMODE_START_NOTE)
- voices[voice].offset_pending = position;
- else
- gus_write_addr (0x0a, sample_ptrs[sample_no] + position, 0,
- samples[sample_no].mode & WAVE_16_BITS);
+ if ((sample_no = sample_map[voice]) != -1)
+ if (position < samples[sample_no].len)
+ if (voices[voice].volume_irq_mode == VMODE_START_NOTE)
+ voices[voice].offset_pending = position;
+ else
+ gus_write_addr(0x0a, sample_ptrs[sample_no] + position, 0,
+ samples[sample_no].mode & WAVE_16_BITS);
}
static void
-gus_voice_init (int voice)
+gus_voice_init(int voice)
{
- unsigned long flags;
+ unsigned long flags;
- save_flags (flags);
- cli ();
- gus_select_voice (voice);
- gus_voice_volume (0);
- gus_voice_off ();
- gus_write_addr (0x0a, 0, 0, 0); /* Set current position to 0 */
- gus_write8 (0x00, 0x03); /* Voice off */
- gus_write8 (0x0d, 0x03); /* Ramping off */
- voice_alloc->map[voice] = 0;
- voice_alloc->alloc_times[voice] = 0;
- restore_flags (flags);
+ save_flags(flags);
+ cli();
+ gus_select_voice(voice);
+ gus_voice_volume(0);
+ gus_voice_off();
+ gus_write_addr(0x0a, 0, 0, 0); /* Set current position to 0 */
+ gus_write8(0x00, 0x03); /* Voice off */
+ gus_write8(0x0d, 0x03); /* Ramping off */
+ voice_alloc->map[voice] = 0;
+ voice_alloc->alloc_times[voice] = 0;
+ restore_flags(flags);
}
static void
-gus_voice_init2 (int voice)
+gus_voice_init2(int voice)
{
- voices[voice].panning = 0;
- voices[voice].mode = 0;
- voices[voice].orig_freq = 20000;
- voices[voice].current_freq = 20000;
- voices[voice].bender = 0;
- voices[voice].bender_range = 200;
- voices[voice].initial_volume = 0;
- voices[voice].current_volume = 0;
- voices[voice].loop_irq_mode = 0;
- voices[voice].loop_irq_parm = 0;
- voices[voice].volume_irq_mode = 0;
- voices[voice].volume_irq_parm = 0;
- voices[voice].env_phase = 0;
- voices[voice].main_vol = 127;
- voices[voice].patch_vol = 127;
- voices[voice].expression_vol = 127;
- voices[voice].sample_pending = -1;
- voices[voice].fixed_pitch = 0;
+ voices[voice].panning = 0;
+ voices[voice].mode = 0;
+ voices[voice].orig_freq = 20000;
+ voices[voice].current_freq = 20000;
+ voices[voice].bender = 0;
+ voices[voice].bender_range = 200;
+ voices[voice].initial_volume = 0;
+ voices[voice].current_volume = 0;
+ voices[voice].loop_irq_mode = 0;
+ voices[voice].loop_irq_parm = 0;
+ voices[voice].volume_irq_mode = 0;
+ voices[voice].volume_irq_parm = 0;
+ voices[voice].env_phase = 0;
+ voices[voice].main_vol = 127;
+ voices[voice].patch_vol = 127;
+ voices[voice].expression_vol = 127;
+ voices[voice].sample_pending = -1;
+ voices[voice].fixed_pitch = 0;
}
static void
-step_envelope (int voice)
+step_envelope(int voice)
{
- unsigned vol, prev_vol, phase;
- unsigned char rate;
- long int flags;
-
- if (voices[voice].mode & WAVE_SUSTAIN_ON && voices[voice].env_phase == 2)
- {
- save_flags (flags);
- cli ();
- gus_select_voice (voice);
- gus_rampoff ();
- restore_flags (flags);
- return;
- /*
- * Sustain phase begins. Continue envelope after receiving note off.
- */
- }
-
- if (voices[voice].env_phase >= 5)
- { /* Envelope finished. Shoot the voice down */
- gus_voice_init (voice);
- return;
- }
-
- prev_vol = voices[voice].current_volume;
- phase = ++voices[voice].env_phase;
- compute_volume (voice, voices[voice].midi_volume);
- vol = voices[voice].initial_volume * voices[voice].env_offset[phase] / 255;
- rate = voices[voice].env_rate[phase];
+ unsigned vol, prev_vol, phase;
+ unsigned char rate;
+ long int flags;
- save_flags (flags);
- cli ();
- gus_select_voice (voice);
+ if (voices[voice].mode & WAVE_SUSTAIN_ON && voices[voice].env_phase == 2)
+ {
+ save_flags(flags);
+ cli();
+ gus_select_voice(voice);
+ gus_rampoff();
+ restore_flags(flags);
+ return;
+ /*
+ * Sustain phase begins. Continue envelope after receiving note off.
+ */
+ }
+ if (voices[voice].env_phase >= 5)
+ { /* Envelope finished. Shoot the voice down */
+ gus_voice_init(voice);
+ return;
+ }
+ prev_vol = voices[voice].current_volume;
+ phase = ++voices[voice].env_phase;
+ compute_volume(voice, voices[voice].midi_volume);
+ vol = voices[voice].initial_volume * voices[voice].env_offset[phase] / 255;
+ rate = voices[voice].env_rate[phase];
- gus_voice_volume (prev_vol);
+ save_flags(flags);
+ cli();
+ gus_select_voice(voice);
+ gus_voice_volume(prev_vol);
- gus_write8 (0x06, rate); /* Ramping rate */
- voices[voice].volume_irq_mode = VMODE_ENVELOPE;
+ gus_write8(0x06, rate); /* Ramping rate */
- if (((vol - prev_vol) / 64) == 0) /* No significant volume change */
- {
- restore_flags (flags);
- step_envelope (voice); /* Continue the envelope on the next step */
- return;
- }
+ voices[voice].volume_irq_mode = VMODE_ENVELOPE;
- if (vol > prev_vol)
- {
- if (vol >= (4096 - 64))
- vol = 4096 - 65;
- gus_ramp_range (0, vol);
- gus_rampon (0x20); /* Increasing volume, with IRQ */
- }
- else
- {
- if (vol <= 64)
- vol = 65;
- gus_ramp_range (vol, 4030);
- gus_rampon (0x60); /* Decreasing volume, with IRQ */
- }
- voices[voice].current_volume = vol;
- restore_flags (flags);
+ if (((vol - prev_vol) / 64) == 0) /* No significant volume change */
+ {
+ restore_flags(flags);
+ step_envelope(voice); /* Continue the envelope on the next step */
+ return;
+ }
+ if (vol > prev_vol)
+ {
+ if (vol >= (4096 - 64))
+ vol = 4096 - 65;
+ gus_ramp_range(0, vol);
+ gus_rampon(0x20); /* Increasing volume, with IRQ */
+ } else
+ {
+ if (vol <= 64)
+ vol = 65;
+ gus_ramp_range(vol, 4030);
+ gus_rampon(0x60); /* Decreasing volume, with IRQ */
+ }
+ voices[voice].current_volume = vol;
+ restore_flags(flags);
}
static void
-init_envelope (int voice)
+init_envelope(int voice)
{
- voices[voice].env_phase = -1;
- voices[voice].current_volume = 64;
+ voices[voice].env_phase = -1;
+ voices[voice].current_volume = 64;
- step_envelope (voice);
+ step_envelope(voice);
}
static void
-start_release (int voice, long int flags)
+start_release(int voice, long int flags)
{
- if (gus_read8 (0x00) & 0x03)
- return; /* Voice already stopped */
+ if (gus_read8(0x00) & 0x03)
+ return; /* Voice already stopped */
- voices[voice].env_phase = 2; /* Will be incremented by step_envelope */
+ voices[voice].env_phase = 2; /* Will be incremented by step_envelope */
- voices[voice].current_volume =
- voices[voice].initial_volume =
- gus_read16 (0x09) >> 4; /* Get current volume */
+ voices[voice].current_volume =
+ voices[voice].initial_volume =
+ gus_read16(0x09) >> 4; /* Get current volume */
- voices[voice].mode &= ~WAVE_SUSTAIN_ON;
- gus_rampoff ();
- restore_flags (flags);
- step_envelope (voice);
+ voices[voice].mode &= ~WAVE_SUSTAIN_ON;
+ gus_rampoff();
+ restore_flags(flags);
+ step_envelope(voice);
}
static void
-gus_voice_fade (int voice)
+gus_voice_fade(int voice)
{
- int instr_no = sample_map[voice], is16bits;
- long int flags;
-
- save_flags (flags);
- cli ();
- gus_select_voice (voice);
-
- if (instr_no < 0 || instr_no > MAX_SAMPLE)
- {
- gus_write8 (0x00, 0x03); /* Hard stop */
- voice_alloc->map[voice] = 0;
- restore_flags (flags);
- return;
- }
-
- is16bits = (samples[instr_no].mode & WAVE_16_BITS) ? 1 : 0; /* 8 or 16 bits */
+ int instr_no = sample_map[voice], is16bits;
+ long int flags;
- if (voices[voice].mode & WAVE_ENVELOPES)
- {
- start_release (voice, flags);
- restore_flags (flags);
- return;
- }
+ save_flags(flags);
+ cli();
+ gus_select_voice(voice);
- /*
- * Ramp the volume down but not too quickly.
- */
- if ((int) (gus_read16 (0x09) >> 4) < 100) /* Get current volume */
- {
- gus_voice_off ();
- gus_rampoff ();
- gus_voice_init (voice);
- restore_flags (flags);
- return;
- }
+ if (instr_no < 0 || instr_no > MAX_SAMPLE)
+ {
+ gus_write8(0x00, 0x03); /* Hard stop */
+ voice_alloc->map[voice] = 0;
+ restore_flags(flags);
+ return;
+ }
+ is16bits = (samples[instr_no].mode & WAVE_16_BITS) ? 1 : 0; /* 8 or 16 bits */
- gus_ramp_range (65, 4030);
- gus_ramp_rate (2, 4);
- gus_rampon (0x40 | 0x20); /* Down, once, with IRQ */
- voices[voice].volume_irq_mode = VMODE_HALT;
- restore_flags (flags);
+ if (voices[voice].mode & WAVE_ENVELOPES)
+ {
+ start_release(voice, flags);
+ restore_flags(flags);
+ return;
+ }
+ /*
+ * Ramp the volume down but not too quickly.
+ */
+ if ((int) (gus_read16(0x09) >> 4) < 100) /* Get current volume */
+ {
+ gus_voice_off();
+ gus_rampoff();
+ gus_voice_init(voice);
+ restore_flags(flags);
+ return;
+ }
+ gus_ramp_range(65, 4030);
+ gus_ramp_rate(2, 4);
+ gus_rampon(0x40 | 0x20); /* Down, once, with IRQ */
+ voices[voice].volume_irq_mode = VMODE_HALT;
+ restore_flags(flags);
}
static void
-gus_reset (void)
+gus_reset(void)
{
- int i;
+ int i;
- gus_select_max_voices (24);
- volume_base = 3071;
- volume_scale = 4;
- volume_method = VOL_METHOD_ADAGIO;
+ gus_select_max_voices(24);
+ volume_base = 3071;
+ volume_scale = 4;
+ volume_method = VOL_METHOD_ADAGIO;
- for (i = 0; i < 32; i++)
- {
- gus_voice_init (i); /* Turn voice off */
- gus_voice_init2 (i);
- }
+ for (i = 0; i < 32; i++)
+ {
+ gus_voice_init(i); /* Turn voice off */
+ gus_voice_init2(i);
+ }
}
static void
-gus_initialize (void)
+gus_initialize(void)
{
- unsigned long flags;
- unsigned char dma_image, irq_image, tmp;
+ unsigned long flags;
+ unsigned char dma_image, irq_image, tmp;
- static unsigned char gus_irq_map[16] =
- {0, 0, 0, 3, 0, 2, 0, 4, 0, 1, 0, 5, 6, 0, 0, 7};
+ static unsigned char gus_irq_map[16] =
+ {0, 0, 0, 3, 0, 2, 0, 4, 0, 1, 0, 5, 6, 0, 0, 7};
- static unsigned char gus_dma_map[8] =
- {0, 1, 0, 2, 0, 3, 4, 5};
+ static unsigned char gus_dma_map[8] =
+ {0, 1, 0, 2, 0, 3, 4, 5};
+
+ save_flags(flags);
+ cli();
+ gus_write8(0x4c, 0); /* Reset GF1 */
+ gus_delay();
+ gus_delay();
+
+ gus_write8(0x4c, 1); /* Release Reset */
+ gus_delay();
+ gus_delay();
- save_flags (flags);
- cli ();
- gus_write8 (0x4c, 0); /* Reset GF1 */
- gus_delay ();
- gus_delay ();
-
- gus_write8 (0x4c, 1); /* Release Reset */
- gus_delay ();
- gus_delay ();
-
- /*
- * Clear all interrupts
- */
-
- gus_write8 (0x41, 0); /* DMA control */
- gus_write8 (0x45, 0); /* Timer control */
- gus_write8 (0x49, 0); /* Sample control */
-
- gus_select_max_voices (24);
-
- inb (u_Status); /* Touch the status register */
+ /*
+ * Clear all interrupts
+ */
- gus_look8 (0x41); /* Clear any pending DMA IRQs */
- gus_look8 (0x49); /* Clear any pending sample IRQs */
- gus_read8 (0x0f); /* Clear pending IRQs */
+ gus_write8(0x41, 0); /* DMA control */
+ gus_write8(0x45, 0); /* Timer control */
+ gus_write8(0x49, 0); /* Sample control */
- gus_reset (); /* Resets all voices */
+ gus_select_max_voices(24);
- gus_look8 (0x41); /* Clear any pending DMA IRQs */
- gus_look8 (0x49); /* Clear any pending sample IRQs */
- gus_read8 (0x0f); /* Clear pending IRQs */
+ inb(u_Status); /* Touch the status register */
- gus_write8 (0x4c, 7); /* Master reset | DAC enable | IRQ enable */
+ gus_look8(0x41); /* Clear any pending DMA IRQs */
+ gus_look8(0x49); /* Clear any pending sample IRQs */
+ gus_read8(0x0f); /* Clear pending IRQs */
- /*
- * Set up for Digital ASIC
- */
+ gus_reset(); /* Resets all voices */
- outb ((0x05), gus_base + 0x0f);
+ gus_look8(0x41); /* Clear any pending DMA IRQs */
+ gus_look8(0x49); /* Clear any pending sample IRQs */
+ gus_read8(0x0f); /* Clear pending IRQs */
- mix_image |= 0x02; /* Disable line out (for a moment) */
- outb ((mix_image), u_Mixer);
+ gus_write8(0x4c, 7); /* Master reset | DAC enable | IRQ enable */
- outb ((0x00), u_IRQDMAControl);
+ /*
+ * Set up for Digital ASIC
+ */
- outb ((0x00), gus_base + 0x0f);
+ outb((0x05), gus_base + 0x0f);
- /*
- * Now set up the DMA and IRQ interface
- *
- * The GUS supports two IRQs and two DMAs.
- *
- * Just one DMA channel is used. This prevents simultaneous ADC and DAC.
- * Adding this support requires significant changes to the dmabuf.c, dsp.c
- * and audio.c also.
- */
+ mix_image |= 0x02; /* Disable line out (for a moment) */
+ outb((mix_image), u_Mixer);
- irq_image = 0;
- tmp = gus_irq_map[gus_irq];
- if (!gus_pnp_flag && !tmp)
- printk ("Warning! GUS IRQ not selected\n");
- irq_image |= tmp;
- irq_image |= 0x40; /* Combine IRQ1 (GF1) and IRQ2 (Midi) */
+ outb((0x00), u_IRQDMAControl);
- dual_dma_mode = 1;
- if (gus_dma2 == gus_dma || gus_dma2 == -1)
- {
- dual_dma_mode = 0;
- dma_image = 0x40; /* Combine DMA1 (DRAM) and IRQ2 (ADC) */
+ outb((0x00), gus_base + 0x0f);
- tmp = gus_dma_map[gus_dma];
- if (!tmp)
- printk ("Warning! GUS DMA not selected\n");
+ /*
+ * Now set up the DMA and IRQ interface
+ *
+ * The GUS supports two IRQs and two DMAs.
+ *
+ * Just one DMA channel is used. This prevents simultaneous ADC and DAC.
+ * Adding this support requires significant changes to the dmabuf.c, dsp.c
+ * and audio.c also.
+ */
- dma_image |= tmp;
- }
- else
- /* Setup dual DMA channel mode for GUS MAX */
- {
- dma_image = gus_dma_map[gus_dma];
- if (!dma_image)
- printk ("Warning! GUS DMA not selected\n");
+ irq_image = 0;
+ tmp = gus_irq_map[gus_irq];
+ if (!gus_pnp_flag && !tmp)
+ printk("Warning! GUS IRQ not selected\n");
+ irq_image |= tmp;
+ irq_image |= 0x40; /* Combine IRQ1 (GF1) and IRQ2 (Midi) */
- tmp = gus_dma_map[gus_dma2] << 3;
- if (!tmp)
- {
- printk ("Warning! Invalid GUS MAX DMA\n");
- tmp = 0x40; /* Combine DMA channels */
- dual_dma_mode = 0;
- }
+ dual_dma_mode = 1;
+ if (gus_dma2 == gus_dma || gus_dma2 == -1)
+ {
+ dual_dma_mode = 0;
+ dma_image = 0x40; /* Combine DMA1 (DRAM) and IRQ2 (ADC) */
- dma_image |= tmp;
- }
+ tmp = gus_dma_map[gus_dma];
+ if (!tmp)
+ printk("Warning! GUS DMA not selected\n");
+
+ dma_image |= tmp;
+ } else
+ /* Setup dual DMA channel mode for GUS MAX */
+ {
+ dma_image = gus_dma_map[gus_dma];
+ if (!dma_image)
+ printk("Warning! GUS DMA not selected\n");
+
+ tmp = gus_dma_map[gus_dma2] << 3;
+ if (!tmp)
+ {
+ printk("Warning! Invalid GUS MAX DMA\n");
+ tmp = 0x40; /* Combine DMA channels */
+ dual_dma_mode = 0;
+ }
+ dma_image |= tmp;
+ }
- /*
- * For some reason the IRQ and DMA addresses must be written twice
- */
+ /*
+ * For some reason the IRQ and DMA addresses must be written twice
+ */
- /*
- * Doing it first time
- */
+ /*
+ * Doing it first time
+ */
- outb ((mix_image), u_Mixer); /* Select DMA control */
- outb ((dma_image | 0x80), u_IRQDMAControl); /* Set DMA address */
+ outb((mix_image), u_Mixer); /* Select DMA control */
+ outb((dma_image | 0x80), u_IRQDMAControl); /* Set DMA address */
- outb ((mix_image | 0x40), u_Mixer); /* Select IRQ control */
- outb ((irq_image), u_IRQDMAControl); /* Set IRQ address */
+ outb((mix_image | 0x40), u_Mixer); /* Select IRQ control */
+ outb((irq_image), u_IRQDMAControl); /* Set IRQ address */
- /*
- * Doing it second time
- */
+ /*
+ * Doing it second time
+ */
- outb ((mix_image), u_Mixer); /* Select DMA control */
- outb ((dma_image), u_IRQDMAControl); /* Set DMA address */
+ outb((mix_image), u_Mixer); /* Select DMA control */
+ outb((dma_image), u_IRQDMAControl); /* Set DMA address */
- outb ((mix_image | 0x40), u_Mixer); /* Select IRQ control */
- outb ((irq_image), u_IRQDMAControl); /* Set IRQ address */
+ outb((mix_image | 0x40), u_Mixer); /* Select IRQ control */
+ outb((irq_image), u_IRQDMAControl); /* Set IRQ address */
- gus_select_voice (0); /* This disables writes to IRQ/DMA reg */
+ gus_select_voice(0); /* This disables writes to IRQ/DMA reg */
- mix_image &= ~0x02; /* Enable line out */
- mix_image |= 0x08; /* Enable IRQ */
- outb ((mix_image), u_Mixer); /*
- * Turn mixer channels on
- * Note! Mic in is left off.
- */
+ mix_image &= ~0x02; /* Enable line out */
+ mix_image |= 0x08; /* Enable IRQ */
+ outb((mix_image), u_Mixer); /*
+ * Turn mixer channels on
+ * Note! Mic in is left off.
+ */
- gus_select_voice (0); /* This disables writes to IRQ/DMA reg */
+ gus_select_voice(0); /* This disables writes to IRQ/DMA reg */
- gusintr (gus_irq, NULL, NULL); /* Serve pending interrupts */
+ gusintr(gus_irq, NULL, NULL); /* Serve pending interrupts */
- inb (u_Status); /* Touch the status register */
+ inb(u_Status); /* Touch the status register */
- gus_look8 (0x41); /* Clear any pending DMA IRQs */
- gus_look8 (0x49); /* Clear any pending sample IRQs */
+ gus_look8(0x41); /* Clear any pending DMA IRQs */
+ gus_look8(0x49); /* Clear any pending sample IRQs */
- gus_read8 (0x0f); /* Clear pending IRQs */
+ gus_read8(0x0f); /* Clear pending IRQs */
- if (iw_mode)
- gus_write8 (0x19, gus_read8 (0x19) | 0x01);
- restore_flags (flags);
+ if (iw_mode)
+ gus_write8(0x19, gus_read8(0x19) | 0x01);
+ restore_flags(flags);
}
static void
-pnp_mem_init (void)
+pnp_mem_init(void)
{
#include "iwmem.h"
#define CHUNK_SIZE (256*1024)
#define BANK_SIZE (4*1024*1024)
#define CHUNKS_PER_BANK (BANK_SIZE/CHUNK_SIZE)
- int bank, chunk, addr, total = 0;
- int bank_sizes[4];
- int i, j, bits = -1, nbanks = 0;
+ int bank, chunk, addr, total = 0;
+ int bank_sizes[4];
+ int i, j, bits = -1, nbanks = 0;
/*
* This routine determines what kind of RAM is installed in each of the four
@@ -896,68 +886,68 @@
/*
* Place the chip into enhanced mode
*/
- gus_write8 (0x19, gus_read8 (0x19) | 0x01);
- gus_write8 (0x53, gus_look8 (0x53) & ~0x02); /* Select DRAM I/O access */
+ gus_write8(0x19, gus_read8(0x19) | 0x01);
+ gus_write8(0x53, gus_look8(0x53) & ~0x02); /* Select DRAM I/O access */
/*
* Set memory configuration to 4 DRAM banks of 4M in each (16M total).
*/
- gus_write16 (0x52, (gus_look16 (0x52) & 0xfff0) | 0x000c);
+ gus_write16(0x52, (gus_look16(0x52) & 0xfff0) | 0x000c);
/*
* Perform the DRAM size detection for each bank individually.
*/
- for (bank = 0; bank < 4; bank++)
- {
- int size = 0;
-
- addr = bank * BANK_SIZE;
-
- /* Clean check points of each chunk */
- for (chunk = 0; chunk < CHUNKS_PER_BANK; chunk++)
- {
- gus_poke (addr + chunk * CHUNK_SIZE + 0L, 0x00);
- gus_poke (addr + chunk * CHUNK_SIZE + 1L, 0x00);
- }
-
- /* Write a value to each chunk point and verify the result */
- for (chunk = 0; chunk < CHUNKS_PER_BANK; chunk++)
- {
- gus_poke (addr + chunk * CHUNK_SIZE + 0L, 0x55);
- gus_poke (addr + chunk * CHUNK_SIZE + 1L, 0xAA);
-
- if (gus_peek (addr + chunk * CHUNK_SIZE + 0L) == 0x55 &&
- gus_peek (addr + chunk * CHUNK_SIZE + 1L) == 0xAA)
- { /* OK. There is RAM. Now check for possible shadows */
- int ok = 1, chunk2;
-
- for (chunk2 = 0; ok && chunk2 < chunk; chunk2++)
- if (gus_peek (addr + chunk2 * CHUNK_SIZE + 0L) ||
- gus_peek (addr + chunk2 * CHUNK_SIZE + 1L))
- ok = 0; /* Addressing wraps */
-
- if (ok)
- size = (chunk + 1) * CHUNK_SIZE;
- }
- gus_poke (addr + chunk * CHUNK_SIZE + 0L, 0x00);
- gus_poke (addr + chunk * CHUNK_SIZE + 1L, 0x00);
- }
-
- bank_sizes[bank] = size;
- if (size)
- nbanks = bank + 1;
- DDB (printk ("Interwave: Bank %d, size=%dk\n", bank, size / 1024));
- }
-
- if (nbanks == 0) /* No RAM - Give up */
- {
- printk ("Sound: An Interwave audio chip detected but no DRAM\n");
- printk ("Sound: Unable to work with this card.\n");
- gus_write8 (0x19, gus_read8 (0x19) & ~0x01);
- gus_mem_size = 0;
- return;
- }
+ for (bank = 0; bank < 4; bank++)
+ {
+ int size = 0;
+
+ addr = bank * BANK_SIZE;
+
+ /* Clean check points of each chunk */
+ for (chunk = 0; chunk < CHUNKS_PER_BANK; chunk++)
+ {
+ gus_poke(addr + chunk * CHUNK_SIZE + 0L, 0x00);
+ gus_poke(addr + chunk * CHUNK_SIZE + 1L, 0x00);
+ }
+
+ /* Write a value to each chunk point and verify the result */
+ for (chunk = 0; chunk < CHUNKS_PER_BANK; chunk++)
+ {
+ gus_poke(addr + chunk * CHUNK_SIZE + 0L, 0x55);
+ gus_poke(addr + chunk * CHUNK_SIZE + 1L, 0xAA);
+
+ if (gus_peek(addr + chunk * CHUNK_SIZE + 0L) == 0x55 &&
+ gus_peek(addr + chunk * CHUNK_SIZE + 1L) == 0xAA)
+ { /* OK. There is RAM. Now check for possible shadows */
+ int ok = 1, chunk2;
+
+ for (chunk2 = 0; ok && chunk2 < chunk; chunk2++)
+ if (gus_peek(addr + chunk2 * CHUNK_SIZE + 0L) ||
+ gus_peek(addr + chunk2 * CHUNK_SIZE + 1L))
+ ok = 0; /* Addressing wraps */
+
+ if (ok)
+ size = (chunk + 1) * CHUNK_SIZE;
+ }
+ gus_poke(addr + chunk * CHUNK_SIZE + 0L, 0x00);
+ gus_poke(addr + chunk * CHUNK_SIZE + 1L, 0x00);
+ }
+
+ bank_sizes[bank] = size;
+ if (size)
+ nbanks = bank + 1;
+ DDB(printk("Interwave: Bank %d, size=%dk\n", bank, size / 1024));
+ }
+
+ if (nbanks == 0) /* No RAM - Give up */
+ {
+ printk("Sound: An Interwave audio chip detected but no DRAM\n");
+ printk("Sound: Unable to work with this card.\n");
+ gus_write8(0x19, gus_read8(0x19) & ~0x01);
+ gus_mem_size = 0;
+ return;
+ }
/*
* Now we know how much DRAM there is in each bank. The next step is
* to find a DRAM size encoding (0 to 12) which is best for the combination
@@ -967,665 +957,640 @@
* of memory we have.
*/
- for (i = 0; bits == -1 && i < 13; i++)
- {
- bits = i;
-
- for (j = 0; bits != -1 && j < 4; j++)
- if (mem_decode[i][j] != bank_sizes[j])
- bits = -1; /* No hit */
- }
+ for (i = 0; bits == -1 && i < 13; i++)
+ {
+ bits = i;
+
+ for (j = 0; bits != -1 && j < 4; j++)
+ if (mem_decode[i][j] != bank_sizes[j])
+ bits = -1; /* No hit */
+ }
/*
* If necessary, try to find a combination where other than the last
* bank matches our configuration and the last bank is left oversized.
* In this way we don't leave holes in the middle of memory.
*/
- if (bits == -1) /* No luck yet */
- for (i = 0; bits == -1 && i < 13; i++)
- {
- bits = i;
-
- for (j = 0; bits != -1 && j < nbanks - 1; j++)
- if (mem_decode[i][j] != bank_sizes[j])
- bits = -1; /* No hit */
- if (mem_decode[i][nbanks - 1] < bank_sizes[nbanks - 1])
- bits = -1; /* The last bank is too small */
- }
-
+ if (bits == -1) /* No luck yet */
+ for (i = 0; bits == -1 && i < 13; i++)
+ {
+ bits = i;
+
+ for (j = 0; bits != -1 && j < nbanks - 1; j++)
+ if (mem_decode[i][j] != bank_sizes[j])
+ bits = -1; /* No hit */
+ if (mem_decode[i][nbanks - 1] < bank_sizes[nbanks - 1])
+ bits = -1; /* The last bank is too small */
+ }
/*
* The last resort is to search for a combination where the last bank is
* smaller than the actual SIMM. This leaves some memory in the last bank
* unused but doesn't leave holes in the DRAM address space.
*/
- if (bits == -1) /* No luck yet */
- {
- for (i = 0; bits == -1 && i < 13; i++)
- {
- bits = i;
-
- for (j = 0; bits != -1 && j < nbanks - 1; j++)
- if (mem_decode[i][j] != bank_sizes[j])
- bits = -1; /* No hit */
- }
-
- if (bits != -1)
- {
- printk ("Interwave: Can't use all installed RAM.\n");
- printk ("Interwave: Try reordering SIMMS.\n");
- }
- }
-
- if (bits == -1)
- {
- printk ("Interwave: Can't find working DRAM encoding.\n");
- printk ("Interwave: Defaulting to 256k. Try reordering SIMMS.\n");
- bits = 0;
- }
-
- DDB (printk ("Interwave: Selecting DRAM addressing mode %d\n", bits));
-
- for (bank = 0; bank < 4; bank++)
- {
- DDB (printk (" Bank %d, mem=%dk (limit %dk)\n", bank, bank_sizes[bank] / 1024, mem_decode[bits][bank] / 1024));
-
- if (bank_sizes[bank] > mem_decode[bits][bank])
- total += mem_decode[bits][bank];
- else
- total += bank_sizes[bank];
- }
+ if (bits == -1) /* No luck yet */
+ {
+ for (i = 0; bits == -1 && i < 13; i++)
+ {
+ bits = i;
+
+ for (j = 0; bits != -1 && j < nbanks - 1; j++)
+ if (mem_decode[i][j] != bank_sizes[j])
+ bits = -1; /* No hit */
+ }
+
+ if (bits != -1)
+ {
+ printk("Interwave: Can't use all installed RAM.\n");
+ printk("Interwave: Try reordering SIMMS.\n");
+ }
+ }
+ if (bits == -1)
+ {
+ printk("Interwave: Can't find working DRAM encoding.\n");
+ printk("Interwave: Defaulting to 256k. Try reordering SIMMS.\n");
+ bits = 0;
+ }
+ DDB(printk("Interwave: Selecting DRAM addressing mode %d\n", bits));
+
+ for (bank = 0; bank < 4; bank++)
+ {
+ DDB(printk(" Bank %d, mem=%dk (limit %dk)\n", bank, bank_sizes[bank] / 1024, mem_decode[bits][bank] / 1024));
+
+ if (bank_sizes[bank] > mem_decode[bits][bank])
+ total += mem_decode[bits][bank];
+ else
+ total += bank_sizes[bank];
+ }
- DDB (printk ("Total %dk of DRAM (enhanced mode)\n", total / 1024));
+ DDB(printk("Total %dk of DRAM (enhanced mode)\n", total / 1024));
/*
* Set the memory addressing mode.
*/
- gus_write16 (0x52, (gus_look16 (0x52) & 0xfff0) | bits);
+ gus_write16(0x52, (gus_look16(0x52) & 0xfff0) | bits);
/* Leave the chip into enhanced mode. Disable LFO */
- gus_mem_size = total;
- iw_mode = 1;
- gus_write8 (0x19, (gus_read8 (0x19) | 0x01) & ~0x02);
+ gus_mem_size = total;
+ iw_mode = 1;
+ gus_write8(0x19, (gus_read8(0x19) | 0x01) & ~0x02);
}
int
-gus_wave_detect (int baseaddr)
+gus_wave_detect(int baseaddr)
{
- unsigned long i, max_mem = 1024L;
- unsigned long loc;
- unsigned char val;
+ unsigned long i, max_mem = 1024L;
+ unsigned long loc;
+ unsigned char val;
- gus_base = baseaddr;
+ gus_base = baseaddr;
- gus_write8 (0x4c, 0); /* Reset GF1 */
- gus_delay ();
- gus_delay ();
+ gus_write8(0x4c, 0); /* Reset GF1 */
+ gus_delay();
+ gus_delay();
- gus_write8 (0x4c, 1); /* Release Reset */
- gus_delay ();
- gus_delay ();
+ gus_write8(0x4c, 1); /* Release Reset */
+ gus_delay();
+ gus_delay();
#ifdef GUSPNP_AUTODETECT
- val = gus_look8 (0x5b); /* Version number register */
- gus_write8 (0x5b, ~val); /* Invert all bits */
+ val = gus_look8(0x5b); /* Version number register */
+ gus_write8(0x5b, ~val); /* Invert all bits */
- if ((gus_look8 (0x5b) & 0xf0) == (val & 0xf0)) /* No change */
- if ((gus_look8 (0x5b) & 0x0f) == ((~val) & 0x0f)) /* Change */
- {
- DDB (printk ("Interwave chip version %d detected\n", (val & 0xf0) >> 4));
- gus_pnp_flag = 1;
- }
- else
- {
- DDB (printk ("Not an Interwave chip (%x)\n", gus_look8 (0x5b)));
- gus_pnp_flag = 0;
- }
- gus_write8 (0x5b, val); /* Restore all bits */
+ if ((gus_look8(0x5b) & 0xf0) == (val & 0xf0)) /* No change */
+ if ((gus_look8(0x5b) & 0x0f) == ((~val) & 0x0f)) /* Change */
+ {
+ DDB(printk("Interwave chip version %d detected\n", (val & 0xf0) >> 4));
+ gus_pnp_flag = 1;
+ } else
+ {
+ DDB(printk("Not an Interwave chip (%x)\n", gus_look8(0x5b)));
+ gus_pnp_flag = 0;
+ }
+ gus_write8(0x5b, val); /* Restore all bits */
#endif
- if (gus_pnp_flag)
- pnp_mem_init ();
- if (iw_mode)
- return 1;
-
- /* See if there is first block there.... */
- gus_poke (0L, 0xaa);
- if (gus_peek (0L) != 0xaa)
- return (0);
-
- /* Now zero it out so that I can check for mirroring .. */
- gus_poke (0L, 0x00);
- for (i = 1L; i < max_mem; i++)
- {
- int n, failed;
-
- /* check for mirroring ... */
- if (gus_peek (0L) != 0)
- break;
- loc = i << 10;
-
- for (n = loc - 1, failed = 0; n <= loc; n++)
- {
- gus_poke (loc, 0xaa);
- if (gus_peek (loc) != 0xaa)
- failed = 1;
-
- gus_poke (loc, 0x55);
- if (gus_peek (loc) != 0x55)
- failed = 1;
- }
-
- if (failed)
- break;
- }
- gus_mem_size = i << 10;
- return 1;
+ if (gus_pnp_flag)
+ pnp_mem_init();
+ if (iw_mode)
+ return 1;
+
+ /* See if there is first block there.... */
+ gus_poke(0L, 0xaa);
+ if (gus_peek(0L) != 0xaa)
+ return (0);
+
+ /* Now zero it out so that I can check for mirroring .. */
+ gus_poke(0L, 0x00);
+ for (i = 1L; i < max_mem; i++)
+ {
+ int n, failed;
+
+ /* check for mirroring ... */
+ if (gus_peek(0L) != 0)
+ break;
+ loc = i << 10;
+
+ for (n = loc - 1, failed = 0; n <= loc; n++)
+ {
+ gus_poke(loc, 0xaa);
+ if (gus_peek(loc) != 0xaa)
+ failed = 1;
+
+ gus_poke(loc, 0x55);
+ if (gus_peek(loc) != 0x55)
+ failed = 1;
+ }
+
+ if (failed)
+ break;
+ }
+ gus_mem_size = i << 10;
+ return 1;
}
static int
-guswave_ioctl (int dev,
- unsigned int cmd, caddr_t arg)
+guswave_ioctl(int dev,
+ unsigned int cmd, caddr_t arg)
{
- switch (cmd)
- {
- case SNDCTL_SYNTH_INFO:
- gus_info.nr_voices = nr_voices;
- memcpy ((&((char *) arg)[0]), (char *) &gus_info, sizeof (gus_info));
- return 0;
- break;
-
- case SNDCTL_SEQ_RESETSAMPLES:
- reset_sample_memory ();
- return 0;
- break;
-
- case SNDCTL_SEQ_PERCMODE:
- return 0;
- break;
-
- case SNDCTL_SYNTH_MEMAVL:
- return (gus_mem_size == 0) ? 0 : gus_mem_size - free_mem_ptr - 32;
-
- default:
- return -EINVAL;
- }
+ switch (cmd)
+ {
+ case SNDCTL_SYNTH_INFO:
+ gus_info.nr_voices = nr_voices;
+ memcpy((&((char *) arg)[0]), (char *) &gus_info, sizeof(gus_info));
+ return 0;
+ break;
+
+ case SNDCTL_SEQ_RESETSAMPLES:
+ reset_sample_memory();
+ return 0;
+ break;
+
+ case SNDCTL_SEQ_PERCMODE:
+ return 0;
+ break;
+
+ case SNDCTL_SYNTH_MEMAVL:
+ return (gus_mem_size == 0) ? 0 : gus_mem_size - free_mem_ptr - 32;
+
+ default:
+ return -EINVAL;
+ }
}
static int
-guswave_set_instr (int dev, int voice, int instr_no)
+guswave_set_instr(int dev, int voice, int instr_no)
{
- int sample_no;
+ int sample_no;
- if (instr_no < 0 || instr_no > MAX_PATCH)
- instr_no = 0; /* Default to acoustic piano */
+ if (instr_no < 0 || instr_no > MAX_PATCH)
+ instr_no = 0; /* Default to acoustic piano */
- if (voice < 0 || voice > 31)
- return -EINVAL;
-
- if (voices[voice].volume_irq_mode == VMODE_START_NOTE)
- {
- voices[voice].sample_pending = instr_no;
- return 0;
- }
-
- sample_no = patch_table[instr_no];
- patch_map[voice] = -1;
-
- if (sample_no == NOT_SAMPLE)
- {
- printk ("GUS: Undefined patch %d for voice %d\n", instr_no, voice);
- return -EINVAL; /* Patch not defined */
- }
-
- if (sample_ptrs[sample_no] == -1) /* Sample not loaded */
- {
- printk ("GUS: Sample #%d not loaded for patch %d (voice %d)\n", sample_no, instr_no, voice);
- return -EINVAL;
- }
-
- sample_map[voice] = sample_no;
- patch_map[voice] = instr_no;
- return 0;
+ if (voice < 0 || voice > 31)
+ return -EINVAL;
+
+ if (voices[voice].volume_irq_mode == VMODE_START_NOTE)
+ {
+ voices[voice].sample_pending = instr_no;
+ return 0;
+ }
+ sample_no = patch_table[instr_no];
+ patch_map[voice] = -1;
+
+ if (sample_no == NOT_SAMPLE)
+ {
+ printk("GUS: Undefined patch %d for voice %d\n", instr_no, voice);
+ return -EINVAL; /* Patch not defined */
+ }
+ if (sample_ptrs[sample_no] == -1) /* Sample not loaded */
+ {
+ printk("GUS: Sample #%d not loaded for patch %d (voice %d)\n", sample_no, instr_no, voice);
+ return -EINVAL;
+ }
+ sample_map[voice] = sample_no;
+ patch_map[voice] = instr_no;
+ return 0;
}
static int
-guswave_kill_note (int dev, int voice, int note, int velocity)
+guswave_kill_note(int dev, int voice, int note, int velocity)
{
- unsigned long flags;
+ unsigned long flags;
- save_flags (flags);
- cli ();
- /* voice_alloc->map[voice] = 0xffff; */
- if (voices[voice].volume_irq_mode == VMODE_START_NOTE)
- {
- voices[voice].kill_pending = 1;
- restore_flags (flags);
- }
- else
- {
- restore_flags (flags);
- gus_voice_fade (voice);
- }
+ save_flags(flags);
+ cli();
+ /* voice_alloc->map[voice] = 0xffff; */
+ if (voices[voice].volume_irq_mode == VMODE_START_NOTE)
+ {
+ voices[voice].kill_pending = 1;
+ restore_flags(flags);
+ } else
+ {
+ restore_flags(flags);
+ gus_voice_fade(voice);
+ }
- restore_flags (flags);
- return 0;
+ restore_flags(flags);
+ return 0;
}
static void
-guswave_aftertouch (int dev, int voice, int pressure)
+guswave_aftertouch(int dev, int voice, int pressure)
{
}
static void
-guswave_panning (int dev, int voice, int value)
+guswave_panning(int dev, int voice, int value)
{
- if (voice >= 0 || voice < 32)
- voices[voice].panning = value;
+ if (voice >= 0 || voice < 32)
+ voices[voice].panning = value;
}
static void
-guswave_volume_method (int dev, int mode)
+guswave_volume_method(int dev, int mode)
{
- if (mode == VOL_METHOD_LINEAR || mode == VOL_METHOD_ADAGIO)
- volume_method = mode;
+ if (mode == VOL_METHOD_LINEAR || mode == VOL_METHOD_ADAGIO)
+ volume_method = mode;
}
static void
-compute_volume (int voice, int volume)
+compute_volume(int voice, int volume)
{
- if (volume < 128)
- voices[voice].midi_volume = volume;
-
- switch (volume_method)
- {
- case VOL_METHOD_ADAGIO:
- voices[voice].initial_volume =
- gus_adagio_vol (voices[voice].midi_volume, voices[voice].main_vol,
- voices[voice].expression_vol,
- voices[voice].patch_vol);
- break;
+ if (volume < 128)
+ voices[voice].midi_volume = volume;
- case VOL_METHOD_LINEAR: /* Totally ignores patch-volume and expression */
- voices[voice].initial_volume =
- gus_linear_vol (volume, voices[voice].main_vol);
- break;
+ switch (volume_method)
+ {
+ case VOL_METHOD_ADAGIO:
+ voices[voice].initial_volume =
+ gus_adagio_vol(voices[voice].midi_volume, voices[voice].main_vol,
+ voices[voice].expression_vol,
+ voices[voice].patch_vol);
+ break;
+
+ case VOL_METHOD_LINEAR: /* Totally ignores patch-volume and expression */
+ voices[voice].initial_volume =
+ gus_linear_vol(volume, voices[voice].main_vol);
+ break;
- default:
- voices[voice].initial_volume = volume_base +
- (voices[voice].midi_volume * volume_scale);
- }
+ default:
+ voices[voice].initial_volume = volume_base +
+ (voices[voice].midi_volume * volume_scale);
+ }
- if (voices[voice].initial_volume > 4030)
- voices[voice].initial_volume = 4030;
+ if (voices[voice].initial_volume > 4030)
+ voices[voice].initial_volume = 4030;
}
static void
-compute_and_set_volume (int voice, int volume, int ramp_time)
+compute_and_set_volume(int voice, int volume, int ramp_time)
{
- int curr, target, rate;
- unsigned long flags;
-
- compute_volume (voice, volume);
- voices[voice].current_volume = voices[voice].initial_volume;
+ int curr, target, rate;
+ unsigned long flags;
- save_flags (flags);
- cli ();
- /*
- * CAUTION! Interrupts disabled. Enable them before returning
- */
+ compute_volume(voice, volume);
+ voices[voice].current_volume = voices[voice].initial_volume;
- gus_select_voice (voice);
-
- curr = gus_read16 (0x09) >> 4;
- target = voices[voice].initial_volume;
+ save_flags(flags);
+ cli();
+ /*
+ * CAUTION! Interrupts disabled. Enable them before returning
+ */
- if (ramp_time == INSTANT_RAMP)
- {
- gus_rampoff ();
- gus_voice_volume (target);
- restore_flags (flags);
- return;
- }
+ gus_select_voice(voice);
- if (ramp_time == FAST_RAMP)
- rate = 63;
- else
- rate = 16;
- gus_ramp_rate (0, rate);
+ curr = gus_read16(0x09) >> 4;
+ target = voices[voice].initial_volume;
- if ((target - curr) / 64 == 0) /* Close enough to target. */
- {
- gus_rampoff ();
- gus_voice_volume (target);
- restore_flags (flags);
- return;
- }
+ if (ramp_time == INSTANT_RAMP)
+ {
+ gus_rampoff();
+ gus_voice_volume(target);
+ restore_flags(flags);
+ return;
+ }
+ if (ramp_time == FAST_RAMP)
+ rate = 63;
+ else
+ rate = 16;
+ gus_ramp_rate(0, rate);
- if (target > curr)
- {
- if (target > (4095 - 65))
- target = 4095 - 65;
- gus_ramp_range (curr, target);
- gus_rampon (0x00); /* Ramp up, once, no IRQ */
- }
- else
- {
- if (target < 65)
- target = 65;
+ if ((target - curr) / 64 == 0) /* Close enough to target. */
+ {
+ gus_rampoff();
+ gus_voice_volume(target);
+ restore_flags(flags);
+ return;
+ }
+ if (target > curr)
+ {
+ if (target > (4095 - 65))
+ target = 4095 - 65;
+ gus_ramp_range(curr, target);
+ gus_rampon(0x00); /* Ramp up, once, no IRQ */
+ } else
+ {
+ if (target < 65)
+ target = 65;
- gus_ramp_range (target, curr);
- gus_rampon (0x40); /* Ramp down, once, no irq */
- }
- restore_flags (flags);
+ gus_ramp_range(target, curr);
+ gus_rampon(0x40); /* Ramp down, once, no irq */
+ }
+ restore_flags(flags);
}
static void
-dynamic_volume_change (int voice)
+dynamic_volume_change(int voice)
{
- unsigned char status;
- unsigned long flags;
+ unsigned char status;
+ unsigned long flags;
+
+ save_flags(flags);
+ cli();
+ gus_select_voice(voice);
+ status = gus_read8(0x00); /* Get voice status */
+ restore_flags(flags);
+
+ if (status & 0x03)
+ return; /* Voice was not running */
+
+ if (!(voices[voice].mode & WAVE_ENVELOPES))
+ {
+ compute_and_set_volume(voice, voices[voice].midi_volume, 1);
+ return;
+ }
+ /*
+ * Voice is running and has envelopes.
+ */
- save_flags (flags);
- cli ();
- gus_select_voice (voice);
- status = gus_read8 (0x00); /* Get voice status */
- restore_flags (flags);
+ save_flags(flags);
+ cli();
+ gus_select_voice(voice);
+ status = gus_read8(0x0d); /* Ramping status */
+ restore_flags(flags);
- if (status & 0x03)
- return; /* Voice was not running */
+ if (status & 0x03) /* Sustain phase? */
+ {
+ compute_and_set_volume(voice, voices[voice].midi_volume, 1);
+ return;
+ }
+ if (voices[voice].env_phase < 0)
+ return;
- if (!(voices[voice].mode & WAVE_ENVELOPES))
- {
- compute_and_set_volume (voice, voices[voice].midi_volume, 1);
- return;
- }
+ compute_volume(voice, voices[voice].midi_volume);
- /*
- * Voice is running and has envelopes.
- */
+}
- save_flags (flags);
- cli ();
- gus_select_voice (voice);
- status = gus_read8 (0x0d); /* Ramping status */
- restore_flags (flags);
+static void
+guswave_controller(int dev, int voice, int ctrl_num, int value)
+{
+ unsigned long flags;
+ unsigned long freq;
- if (status & 0x03) /* Sustain phase? */
- {
- compute_and_set_volume (voice, voices[voice].midi_volume, 1);
- return;
- }
+ if (voice < 0 || voice > 31)
+ return;
- if (voices[voice].env_phase < 0)
- return;
+ switch (ctrl_num)
+ {
+ case CTRL_PITCH_BENDER:
+ voices[voice].bender = value;
- compute_volume (voice, voices[voice].midi_volume);
+ if (voices[voice].volume_irq_mode != VMODE_START_NOTE)
+ {
+ freq = compute_finetune(voices[voice].orig_freq, value,
+ voices[voice].bender_range, 0);
+ voices[voice].current_freq = freq;
+
+ save_flags(flags);
+ cli();
+ gus_select_voice(voice);
+ gus_voice_freq(freq);
+ restore_flags(flags);
+ }
+ break;
+
+ case CTRL_PITCH_BENDER_RANGE:
+ voices[voice].bender_range = value;
+ break;
+ case CTL_EXPRESSION:
+ value /= 128;
+ case CTRL_EXPRESSION:
+ if (volume_method == VOL_METHOD_ADAGIO)
+ {
+ voices[voice].expression_vol = value;
+ if (voices[voice].volume_irq_mode != VMODE_START_NOTE)
+ dynamic_volume_change(voice);
+ }
+ break;
+
+ case CTL_PAN:
+ voices[voice].panning = (value * 2) - 128;
+ break;
+
+ case CTL_MAIN_VOLUME:
+ value = (value * 100) / 16383;
+
+ case CTRL_MAIN_VOLUME:
+ voices[voice].main_vol = value;
+ if (voices[voice].volume_irq_mode != VMODE_START_NOTE)
+ dynamic_volume_change(voice);
+ break;
+ default:
+ break;
+ }
}
-static void
-guswave_controller (int dev, int voice, int ctrl_num, int value)
+static int
+guswave_start_note2(int dev, int voice, int note_num, int volume)
{
- unsigned long flags;
- unsigned long freq;
+ int sample, best_sample, best_delta, delta_freq;
+ int is16bits, samplep, patch, pan;
+ unsigned long note_freq, base_note, freq, flags;
+ unsigned char mode = 0;
- if (voice < 0 || voice > 31)
- return;
+ if (voice < 0 || voice > 31)
+ {
+ printk("GUS: Invalid voice\n");
+ return -EINVAL;
+ }
+ if (note_num == 255)
+ {
+ if (voices[voice].mode & WAVE_ENVELOPES)
+ {
+ voices[voice].midi_volume = volume;
+ dynamic_volume_change(voice);
+ return 0;
+ }
+ compute_and_set_volume(voice, volume, 1);
+ return 0;
+ }
+ if ((patch = patch_map[voice]) == -1)
+ {
+ return -EINVAL;
+ }
+ if ((samplep = patch_table[patch]) == NOT_SAMPLE)
+ {
+ return -EINVAL;
+ }
+ note_freq = note_to_freq(note_num);
- switch (ctrl_num)
- {
- case CTRL_PITCH_BENDER:
- voices[voice].bender = value;
+ /*
+ * Find a sample within a patch so that the note_freq is between low_note
+ * and high_note.
+ */
+ sample = -1;
- if (voices[voice].volume_irq_mode != VMODE_START_NOTE)
- {
- freq = compute_finetune (voices[voice].orig_freq, value,
- voices[voice].bender_range, 0);
- voices[voice].current_freq = freq;
+ best_sample = samplep;
+ best_delta = 1000000;
+ while (samplep != 0 && samplep != NOT_SAMPLE && sample == -1)
+ {
+ delta_freq = note_freq - samples[samplep].base_note;
+ if (delta_freq < 0)
+ delta_freq = -delta_freq;
+ if (delta_freq < best_delta)
+ {
+ best_sample = samplep;
+ best_delta = delta_freq;
+ }
+ if (samples[samplep].low_note <= note_freq &&
+ note_freq <= samples[samplep].high_note)
+ sample = samplep;
+ else
+ samplep = samples[samplep].key; /* Link to next sample */
+ }
+ if (sample == -1)
+ sample = best_sample;
- save_flags (flags);
- cli ();
- gus_select_voice (voice);
- gus_voice_freq (freq);
- restore_flags (flags);
- }
- break;
+ if (sample == -1)
+ {
+ printk("GUS: Patch %d not defined for note %d\n", patch, note_num);
+ return 0; /* Should play default patch ??? */
+ }
+ is16bits = (samples[sample].mode & WAVE_16_BITS) ? 1 : 0;
+ voices[voice].mode = samples[sample].mode;
+ voices[voice].patch_vol = samples[sample].volume;
- case CTRL_PITCH_BENDER_RANGE:
- voices[voice].bender_range = value;
- break;
- case CTL_EXPRESSION:
- value /= 128;
- case CTRL_EXPRESSION:
- if (volume_method == VOL_METHOD_ADAGIO)
- {
- voices[voice].expression_vol = value;
- if (voices[voice].volume_irq_mode != VMODE_START_NOTE)
- dynamic_volume_change (voice);
- }
- break;
+ if (iw_mode)
+ gus_write8(0x15, 0x00); /* RAM, Reset voice deactivate bit of SMSI */
- case CTL_PAN:
- voices[voice].panning = (value * 2) - 128;
- break;
+ if (voices[voice].mode & WAVE_ENVELOPES)
+ {
+ int i;
- case CTL_MAIN_VOLUME:
- value = (value * 100) / 16383;
+ for (i = 0; i < 6; i++)
+ {
+ voices[voice].env_rate[i] = samples[sample].env_rate[i];
+ voices[voice].env_offset[i] = samples[sample].env_offset[i];
+ }
+ }
+ sample_map[voice] = sample;
- case CTRL_MAIN_VOLUME:
- voices[voice].main_vol = value;
- if (voices[voice].volume_irq_mode != VMODE_START_NOTE)
- dynamic_volume_change (voice);
- break;
+ if (voices[voice].fixed_pitch) /* Fixed pitch */
+ {
+ freq = samples[sample].base_freq;
+ } else
+ {
+ base_note = samples[sample].base_note / 100;
+ note_freq /= 100;
- default:
- break;
- }
-}
+ freq = samples[sample].base_freq * note_freq / base_note;
+ }
-static int
-guswave_start_note2 (int dev, int voice, int note_num, int volume)
-{
- int sample, best_sample, best_delta, delta_freq;
- int is16bits, samplep, patch, pan;
- unsigned long note_freq, base_note, freq, flags;
- unsigned char mode = 0;
-
- if (voice < 0 || voice > 31)
- {
- printk ("GUS: Invalid voice\n");
- return -EINVAL;
- }
-
- if (note_num == 255)
- {
- if (voices[voice].mode & WAVE_ENVELOPES)
- {
- voices[voice].midi_volume = volume;
- dynamic_volume_change (voice);
- return 0;
- }
-
- compute_and_set_volume (voice, volume, 1);
- return 0;
- }
-
- if ((patch = patch_map[voice]) == -1)
- {
- return -EINVAL;
- }
-
- if ((samplep = patch_table[patch]) == NOT_SAMPLE)
- {
- return -EINVAL;
- }
-
- note_freq = note_to_freq (note_num);
-
- /*
- * Find a sample within a patch so that the note_freq is between low_note
- * and high_note.
- */
- sample = -1;
-
- best_sample = samplep;
- best_delta = 1000000;
- while (samplep != 0 && samplep != NOT_SAMPLE && sample == -1)
- {
- delta_freq = note_freq - samples[samplep].base_note;
- if (delta_freq < 0)
- delta_freq = -delta_freq;
- if (delta_freq < best_delta)
- {
- best_sample = samplep;
- best_delta = delta_freq;
- }
- if (samples[samplep].low_note <= note_freq &&
- note_freq <= samples[samplep].high_note)
- sample = samplep;
- else
- samplep = samples[samplep].key; /* Link to next sample */
- }
- if (sample == -1)
- sample = best_sample;
-
- if (sample == -1)
- {
- printk ("GUS: Patch %d not defined for note %d\n", patch, note_num);
- return 0; /* Should play default patch ??? */
- }
-
- is16bits = (samples[sample].mode & WAVE_16_BITS) ? 1 : 0;
- voices[voice].mode = samples[sample].mode;
- voices[voice].patch_vol = samples[sample].volume;
-
- if (iw_mode)
- gus_write8 (0x15, 0x00); /* RAM, Reset voice deactivate bit of SMSI */
-
- if (voices[voice].mode & WAVE_ENVELOPES)
- {
- int i;
-
- for (i = 0; i < 6; i++)
- {
- voices[voice].env_rate[i] = samples[sample].env_rate[i];
- voices[voice].env_offset[i] = samples[sample].env_offset[i];
- }
- }
-
- sample_map[voice] = sample;
-
- if (voices[voice].fixed_pitch) /* Fixed pitch */
- {
- freq = samples[sample].base_freq;
- }
- else
- {
- base_note = samples[sample].base_note / 100;
- note_freq /= 100;
-
- freq = samples[sample].base_freq * note_freq / base_note;
- }
-
- voices[voice].orig_freq = freq;
-
- /*
- * Since the pitch bender may have been set before playing the note, we
- * have to calculate the bending now.
- */
-
- freq = compute_finetune (voices[voice].orig_freq, voices[voice].bender,
- voices[voice].bender_range, 0);
- voices[voice].current_freq = freq;
-
- pan = (samples[sample].panning + voices[voice].panning) / 32;
- pan += 7;
- if (pan < 0)
- pan = 0;
- if (pan > 15)
- pan = 15;
-
- if (samples[sample].mode & WAVE_16_BITS)
- {
- mode |= 0x04; /* 16 bits */
- if ((sample_ptrs[sample] / GUS_BANK_SIZE) !=
- ((sample_ptrs[sample] + samples[sample].len) / GUS_BANK_SIZE))
- printk ("GUS: Sample address error\n");
- }
+ voices[voice].orig_freq = freq;
+ /*
+ * Since the pitch bender may have been set before playing the note, we
+ * have to calculate the bending now.
+ */
+
+ freq = compute_finetune(voices[voice].orig_freq, voices[voice].bender,
+ voices[voice].bender_range, 0);
+ voices[voice].current_freq = freq;
+
+ pan = (samples[sample].panning + voices[voice].panning) / 32;
+ pan += 7;
+ if (pan < 0)
+ pan = 0;
+ if (pan > 15)
+ pan = 15;
+
+ if (samples[sample].mode & WAVE_16_BITS)
+ {
+ mode |= 0x04; /* 16 bits */
+ if ((sample_ptrs[sample] / GUS_BANK_SIZE) !=
+ ((sample_ptrs[sample] + samples[sample].len) / GUS_BANK_SIZE))
+ printk("GUS: Sample address error\n");
+ }
/*************************************************************************
* CAUTION! Interrupts disabled. Don't return before enabling
*************************************************************************/
- save_flags (flags);
- cli ();
- gus_select_voice (voice);
- gus_voice_off ();
- gus_rampoff ();
-
- restore_flags (flags);
-
- if (voices[voice].mode & WAVE_ENVELOPES)
- {
- compute_volume (voice, volume);
- init_envelope (voice);
- }
- else
- {
- compute_and_set_volume (voice, volume, 0);
- }
-
- save_flags (flags);
- cli ();
- gus_select_voice (voice);
-
- if (samples[sample].mode & WAVE_LOOP_BACK)
- gus_write_addr (0x0a, sample_ptrs[sample] + samples[sample].len -
- voices[voice].offset_pending, 0, is16bits); /* start=end */
- else
- gus_write_addr (0x0a, sample_ptrs[sample] + voices[voice].offset_pending,
- 0, is16bits); /* Sample start=begin */
-
- if (samples[sample].mode & WAVE_LOOPING)
- {
- mode |= 0x08;
-
- if (samples[sample].mode & WAVE_BIDIR_LOOP)
- mode |= 0x10;
-
- if (samples[sample].mode & WAVE_LOOP_BACK)
- {
- gus_write_addr (0x0a,
- sample_ptrs[sample] + samples[sample].loop_end -
- voices[voice].offset_pending,
- (samples[sample].fractions >> 4) & 0x0f, is16bits);
- mode |= 0x40;
- }
-
- gus_write_addr (0x02, sample_ptrs[sample] + samples[sample].loop_start,
- samples[sample].fractions & 0x0f,
- is16bits); /* Loop start location */
- gus_write_addr (0x04, sample_ptrs[sample] + samples[sample].loop_end,
- (samples[sample].fractions >> 4) & 0x0f,
- is16bits); /* Loop end location */
- }
- else
- {
- mode |= 0x20; /* Loop IRQ at the end */
- voices[voice].loop_irq_mode = LMODE_FINISH; /* Ramp down at the end */
- voices[voice].loop_irq_parm = 1;
- gus_write_addr (0x02, sample_ptrs[sample],
- 0, is16bits); /* Loop start location */
- gus_write_addr (0x04, sample_ptrs[sample] + samples[sample].len - 1,
- (samples[sample].fractions >> 4) & 0x0f,
- is16bits); /* Loop end location */
- }
- gus_voice_freq (freq);
- gus_voice_balance (pan);
- gus_voice_on (mode);
- restore_flags (flags);
+ save_flags(flags);
+ cli();
+ gus_select_voice(voice);
+ gus_voice_off();
+ gus_rampoff();
+
+ restore_flags(flags);
+
+ if (voices[voice].mode & WAVE_ENVELOPES)
+ {
+ compute_volume(voice, volume);
+ init_envelope(voice);
+ } else
+ {
+ compute_and_set_volume(voice, volume, 0);
+ }
+
+ save_flags(flags);
+ cli();
+ gus_select_voice(voice);
+
+ if (samples[sample].mode & WAVE_LOOP_BACK)
+ gus_write_addr(0x0a, sample_ptrs[sample] + samples[sample].len -
+ voices[voice].offset_pending, 0, is16bits); /* start=end */
+ else
+ gus_write_addr(0x0a, sample_ptrs[sample] + voices[voice].offset_pending,
+ 0, is16bits); /* Sample start=begin */
+
+ if (samples[sample].mode & WAVE_LOOPING)
+ {
+ mode |= 0x08;
+
+ if (samples[sample].mode & WAVE_BIDIR_LOOP)
+ mode |= 0x10;
- return 0;
+ if (samples[sample].mode & WAVE_LOOP_BACK)
+ {
+ gus_write_addr(0x0a,
+ sample_ptrs[sample] + samples[sample].loop_end -
+ voices[voice].offset_pending,
+ (samples[sample].fractions >> 4) & 0x0f, is16bits);
+ mode |= 0x40;
+ }
+ gus_write_addr(0x02, sample_ptrs[sample] + samples[sample].loop_start,
+ samples[sample].fractions & 0x0f,
+ is16bits); /* Loop start location */
+ gus_write_addr(0x04, sample_ptrs[sample] + samples[sample].loop_end,
+ (samples[sample].fractions >> 4) & 0x0f,
+ is16bits); /* Loop end location */
+ } else
+ {
+ mode |= 0x20; /* Loop IRQ at the end */
+ voices[voice].loop_irq_mode = LMODE_FINISH; /* Ramp down at the end */
+ voices[voice].loop_irq_parm = 1;
+ gus_write_addr(0x02, sample_ptrs[sample],
+ 0, is16bits); /* Loop start location */
+ gus_write_addr(0x04, sample_ptrs[sample] + samples[sample].len - 1,
+ (samples[sample].fractions >> 4) & 0x0f,
+ is16bits); /* Loop end location */
+ }
+ gus_voice_freq(freq);
+ gus_voice_balance(pan);
+ gus_voice_on(mode);
+ restore_flags(flags);
+
+ return 0;
}
/*
@@ -1635,1946 +1600,1925 @@
*/
static int
-guswave_start_note (int dev, int voice, int note_num, int volume)
+guswave_start_note(int dev, int voice, int note_num, int volume)
+{
+ long int flags;
+ int mode;
+ int ret_val = 0;
+
+ save_flags(flags);
+ cli();
+ if (note_num == 255)
+ {
+ if (voices[voice].volume_irq_mode == VMODE_START_NOTE)
+ {
+ voices[voice].volume_pending = volume;
+ } else
+ {
+ ret_val = guswave_start_note2(dev, voice, note_num, volume);
+ }
+ } else
+ {
+ gus_select_voice(voice);
+ mode = gus_read8(0x00);
+ if (mode & 0x20)
+ gus_write8(0x00, mode & 0xdf); /* No interrupt! */
+
+ voices[voice].offset_pending = 0;
+ voices[voice].kill_pending = 0;
+ voices[voice].volume_irq_mode = 0;
+ voices[voice].loop_irq_mode = 0;
+
+ if (voices[voice].sample_pending >= 0)
+ {
+ restore_flags(flags); /* Run temporarily with interrupts enabled */
+ guswave_set_instr(voices[voice].dev_pending, voice,
+ voices[voice].sample_pending);
+ voices[voice].sample_pending = -1;
+ save_flags(flags);
+ cli();
+ gus_select_voice(voice); /* Reselect the voice (just to be sure) */
+ }
+ if ((mode & 0x01) || (int) ((gus_read16(0x09) >> 4) < (unsigned) 2065))
+ {
+ ret_val = guswave_start_note2(dev, voice, note_num, volume);
+ } else
+ {
+ voices[voice].dev_pending = dev;
+ voices[voice].note_pending = note_num;
+ voices[voice].volume_pending = volume;
+ voices[voice].volume_irq_mode = VMODE_START_NOTE;
+
+ gus_rampoff();
+ gus_ramp_range(2000, 4065);
+ gus_ramp_rate(0, 63); /* Fastest possible rate */
+ gus_rampon(0x20 | 0x40); /* Ramp down, once, irq */
+ }
+ }
+ restore_flags(flags);
+ return ret_val;
+}
+
+static void
+guswave_reset(int dev)
{
- long int flags;
- int mode;
- int ret_val = 0;
-
- save_flags (flags);
- cli ();
- if (note_num == 255)
- {
- if (voices[voice].volume_irq_mode == VMODE_START_NOTE)
- {
- voices[voice].volume_pending = volume;
- }
- else
- {
- ret_val = guswave_start_note2 (dev, voice, note_num, volume);
- }
- }
- else
- {
- gus_select_voice (voice);
- mode = gus_read8 (0x00);
- if (mode & 0x20)
- gus_write8 (0x00, mode & 0xdf); /* No interrupt! */
-
- voices[voice].offset_pending = 0;
- voices[voice].kill_pending = 0;
- voices[voice].volume_irq_mode = 0;
- voices[voice].loop_irq_mode = 0;
-
- if (voices[voice].sample_pending >= 0)
- {
- restore_flags (flags); /* Run temporarily with interrupts enabled */
- guswave_set_instr (voices[voice].dev_pending, voice,
- voices[voice].sample_pending);
- voices[voice].sample_pending = -1;
- save_flags (flags);
- cli ();
- gus_select_voice (voice); /* Reselect the voice (just to be sure) */
- }
-
- if ((mode & 0x01) || (int) ((gus_read16 (0x09) >> 4) < (unsigned) 2065))
- {
- ret_val = guswave_start_note2 (dev, voice, note_num, volume);
- }
- else
- {
- voices[voice].dev_pending = dev;
- voices[voice].note_pending = note_num;
- voices[voice].volume_pending = volume;
- voices[voice].volume_irq_mode = VMODE_START_NOTE;
-
- gus_rampoff ();
- gus_ramp_range (2000, 4065);
- gus_ramp_rate (0, 63); /* Fastest possible rate */
- gus_rampon (0x20 | 0x40); /* Ramp down, once, irq */
- }
- }
- restore_flags (flags);
- return ret_val;
-}
-
-static void
-guswave_reset (int dev)
-{
- int i;
-
- for (i = 0; i < 32; i++)
- {
- gus_voice_init (i);
- gus_voice_init2 (i);
- }
+ int i;
+
+ for (i = 0; i < 32; i++)
+ {
+ gus_voice_init(i);
+ gus_voice_init2(i);
+ }
}
static int
-guswave_open (int dev, int mode)
+guswave_open(int dev, int mode)
{
- int err;
+ int err;
- if (gus_busy)
- return -EBUSY;
+ if (gus_busy)
+ return -EBUSY;
- voice_alloc->timestamp = 0;
+ voice_alloc->timestamp = 0;
- if ((err = DMAbuf_open_dma (gus_devnum)) < 0)
- {
- /* printk( "GUS: Loading samples without DMA\n"); */
- gus_no_dma = 1; /* Upload samples using PIO */
- }
- else
- gus_no_dma = 0;
+ if ((err = DMAbuf_open_dma(gus_devnum)) < 0)
+ {
+ /* printk( "GUS: Loading samples without DMA\n"); */
+ gus_no_dma = 1; /* Upload samples using PIO */
+ } else
+ gus_no_dma = 0;
- dram_sleep_flag.opts = WK_NONE;
- gus_busy = 1;
- active_device = GUS_DEV_WAVE;
+ dram_sleep_flag.opts = WK_NONE;
+ gus_busy = 1;
+ active_device = GUS_DEV_WAVE;
- gusintr (gus_irq, NULL, NULL); /* Serve pending interrupts */
- gus_initialize ();
- gus_reset ();
- gusintr (gus_irq, NULL, NULL); /* Serve pending interrupts */
+ gusintr(gus_irq, NULL, NULL); /* Serve pending interrupts */
+ gus_initialize();
+ gus_reset();
+ gusintr(gus_irq, NULL, NULL); /* Serve pending interrupts */
- return 0;
+ return 0;
}
static void
-guswave_close (int dev)
+guswave_close(int dev)
{
- gus_busy = 0;
- active_device = 0;
- gus_reset ();
+ gus_busy = 0;
+ active_device = 0;
+ gus_reset();
- if (!gus_no_dma)
- DMAbuf_close_dma (gus_devnum);
+ if (!gus_no_dma)
+ DMAbuf_close_dma(gus_devnum);
}
static int
-guswave_load_patch (int dev, int format, const char *addr,
- int offs, int count, int pmgr_flag)
+guswave_load_patch(int dev, int format, const char *addr,
+ int offs, int count, int pmgr_flag)
{
- struct patch_info patch;
- int instr;
- long sizeof_patch;
-
- unsigned long blk_sz, blk_end, left, src_offs, target;
-
- sizeof_patch = (long) &patch.data[0] - (long) &patch; /* Header size */
-
- if (format != GUS_PATCH)
- {
- printk ("GUS Error: Invalid patch format (key) 0x%x\n", format);
- return -EINVAL;
- }
-
- if (count < sizeof_patch)
- {
- printk ("GUS Error: Patch header too short\n");
- return -EINVAL;
- }
-
- count -= sizeof_patch;
-
- if (free_sample >= MAX_SAMPLE)
- {
- printk ("GUS: Sample table full\n");
- return -ENOSPC;
- }
-
- /*
- * Copy the header from user space but ignore the first bytes which have
- * been transferred already.
- */
-
- copy_from_user (&((char *) &patch)[offs], &(addr)[offs], sizeof_patch - offs);
-
- if (patch.mode & WAVE_ROM)
- return -EINVAL;
- if (gus_mem_size == 0)
-
- return -ENOSPC;
-
- instr = patch.instr_no;
-
- if (instr < 0 || instr > MAX_PATCH)
- {
- printk ("GUS: Invalid patch number %d\n", instr);
- return -EINVAL;
- }
-
- if (count < patch.len)
- {
- printk ("GUS Warning: Patch record too short (%d<%d)\n", count, (int) patch.len);
- patch.len = count;
- }
-
- if (patch.len <= 0 || patch.len > gus_mem_size)
- {
- printk ("GUS: Invalid sample length %d\n", (int) patch.len);
- return -EINVAL;
- }
-
- if (patch.mode & WAVE_LOOPING)
- {
- if (patch.loop_start < 0 || patch.loop_start >= patch.len)
- {
- printk ("GUS: Invalid loop start\n");
- return -EINVAL;
- }
-
- if (patch.loop_end < patch.loop_start || patch.loop_end > patch.len)
- {
- printk ("GUS: Invalid loop end\n");
- return -EINVAL;
- }
- }
-
- free_mem_ptr = (free_mem_ptr + 31) & ~31; /* 32 byte alignment */
-
- if (patch.mode & WAVE_16_BITS)
- {
- /*
- * 16 bit samples must fit one 256k bank.
- */
- if (patch.len >= GUS_BANK_SIZE)
- {
- printk ("GUS: Sample (16 bit) too long %d\n", (int) patch.len);
- return -ENOSPC;
- }
-
- if ((free_mem_ptr / GUS_BANK_SIZE) !=
- ((free_mem_ptr + patch.len) / GUS_BANK_SIZE))
- {
- unsigned long tmp_mem = /* Align to 256K */
- ((free_mem_ptr / GUS_BANK_SIZE) + 1) * GUS_BANK_SIZE;
-
- if ((tmp_mem + patch.len) > gus_mem_size)
- return -ENOSPC;
-
- free_mem_ptr = tmp_mem; /* This leaves unusable memory */
- }
- }
-
- if ((free_mem_ptr + patch.len) > gus_mem_size)
- return -ENOSPC;
-
- sample_ptrs[free_sample] = free_mem_ptr;
-
- /*
- * Tremolo is not possible with envelopes
- */
-
- if (patch.mode & WAVE_ENVELOPES)
- patch.mode &= ~WAVE_TREMOLO;
-
- if (!(patch.mode & WAVE_FRACTIONS))
- {
- patch.fractions = 0;
- }
-
- memcpy ((char *) &samples[free_sample], &patch, sizeof_patch);
-
- /*
- * Link this_one sample to the list of samples for patch 'instr'.
- */
-
- samples[free_sample].key = patch_table[instr];
- patch_table[instr] = free_sample;
-
- /*
- * Use DMA to transfer the wave data to the DRAM
- */
-
- left = patch.len;
- src_offs = 0;
- target = free_mem_ptr;
-
- while (left) /* Not completely transferred yet */
- {
- blk_sz = audio_devs[gus_devnum]->dmap_out->bytes_in_use;
- if (blk_sz > left)
- blk_sz = left;
-
- /*
- * DMA cannot cross bank (256k) boundaries. Check for that.
- */
- blk_end = target + blk_sz;
-
- if ((target / GUS_BANK_SIZE) != (blk_end / GUS_BANK_SIZE))
- { /* Split the block */
-
- blk_end &= ~(GUS_BANK_SIZE - 1);
- blk_sz = blk_end - target;
- }
+ struct patch_info patch;
+ int instr;
+ long sizeof_patch;
- if (gus_no_dma)
- {
- /*
- * For some reason the DMA is not possible. We have to use PIO.
- */
- long i;
- unsigned char data;
+ unsigned long blk_sz, blk_end, left, src_offs, target;
- for (i = 0; i < blk_sz; i++)
- {
- get_user (*(unsigned char *) &data, (unsigned char *) &((addr)[sizeof_patch + i]));
- if (patch.mode & WAVE_UNSIGNED)
- if (!(patch.mode & WAVE_16_BITS) || (i & 0x01))
- data ^= 0x80; /* Convert to signed */
- gus_poke (target + i, data);
- }
- }
- else
- {
- unsigned long address, hold_address;
- unsigned char dma_command;
- unsigned long flags;
-
- if (audio_devs[gus_devnum]->dmap_out->raw_buf == NULL)
- {
- printk ("GUS: DMA buffer == NULL\n");
- return -ENOSPC;
- }
+ sizeof_patch = (long) &patch.data[0] - (long) &patch; /* Header size */
- /*
- * OK, move now. First in and then out.
- */
+ if (format != GUS_PATCH)
+ {
+ printk("GUS Error: Invalid patch format (key) 0x%x\n", format);
+ return -EINVAL;
+ }
+ if (count < sizeof_patch)
+ {
+ printk("GUS Error: Patch header too short\n");
+ return -EINVAL;
+ }
+ count -= sizeof_patch;
- copy_from_user (audio_devs[gus_devnum]->dmap_out->raw_buf, &(addr)[sizeof_patch + src_offs], blk_sz);
+ if (free_sample >= MAX_SAMPLE)
+ {
+ printk("GUS: Sample table full\n");
+ return -ENOSPC;
+ }
+ /*
+ * Copy the header from user space but ignore the first bytes which have
+ * been transferred already.
+ */
- save_flags (flags);
- cli ();
-/******** INTERRUPTS DISABLED NOW ********/
- gus_write8 (0x41, 0); /* Disable GF1 DMA */
- DMAbuf_start_dma (gus_devnum,
- audio_devs[gus_devnum]->dmap_out->raw_buf_phys,
- blk_sz, DMA_MODE_WRITE);
+ copy_from_user(&((char *) &patch)[offs], &(addr)[offs], sizeof_patch - offs);
- /*
- * Set the DRAM address for the wave data
- */
+ if (patch.mode & WAVE_ROM)
+ return -EINVAL;
+ if (gus_mem_size == 0)
- if (iw_mode)
- {
- /* Different address translation in enhanced mode */
-
- unsigned char hi;
-
- if (gus_dma > 4)
- address = target >> 1; /* Convert to 16 bit word address */
- else
- address = target;
-
- hi = (unsigned char) ((address >> 16) & 0xf0);
- hi += (unsigned char) (address & 0x0f);
-
- gus_write16 (0x42, (address >> 4) & 0xffff); /* DMA address (low) */
- gus_write8 (0x50, hi);
- }
- else
- {
- address = target;
+ return -ENOSPC;
- if (audio_devs[gus_devnum]->dmap_out->dma > 3)
- {
- hold_address = address;
- address = address >> 1;
- address &= 0x0001ffffL;
- address |= (hold_address & 0x000c0000L);
- }
+ instr = patch.instr_no;
- gus_write16 (0x42, (address >> 4) & 0xffff); /* DRAM DMA address */
- }
+ if (instr < 0 || instr > MAX_PATCH)
+ {
+ printk("GUS: Invalid patch number %d\n", instr);
+ return -EINVAL;
+ }
+ if (count < patch.len)
+ {
+ printk("GUS Warning: Patch record too short (%d<%d)\n", count, (int) patch.len);
+ patch.len = count;
+ }
+ if (patch.len <= 0 || patch.len > gus_mem_size)
+ {
+ printk("GUS: Invalid sample length %d\n", (int) patch.len);
+ return -EINVAL;
+ }
+ if (patch.mode & WAVE_LOOPING)
+ {
+ if (patch.loop_start < 0 || patch.loop_start >= patch.len)
+ {
+ printk("GUS: Invalid loop start\n");
+ return -EINVAL;
+ }
+ if (patch.loop_end < patch.loop_start || patch.loop_end > patch.len)
+ {
+ printk("GUS: Invalid loop end\n");
+ return -EINVAL;
+ }
+ }
+ free_mem_ptr = (free_mem_ptr + 31) & ~31; /* 32 byte alignment */
- /*
- * Start the DMA transfer
- */
+ if (patch.mode & WAVE_16_BITS)
+ {
+ /*
+ * 16 bit samples must fit one 256k bank.
+ */
+ if (patch.len >= GUS_BANK_SIZE)
+ {
+ printk("GUS: Sample (16 bit) too long %d\n", (int) patch.len);
+ return -ENOSPC;
+ }
+ if ((free_mem_ptr / GUS_BANK_SIZE) !=
+ ((free_mem_ptr + patch.len) / GUS_BANK_SIZE))
+ {
+ unsigned long tmp_mem = /* Align to 256K */
+ ((free_mem_ptr / GUS_BANK_SIZE) + 1) * GUS_BANK_SIZE;
- dma_command = 0x21; /* IRQ enable, DMA start */
- if (patch.mode & WAVE_UNSIGNED)
- dma_command |= 0x80; /* Invert MSB */
- if (patch.mode & WAVE_16_BITS)
- dma_command |= 0x40; /* 16 bit _DATA_ */
- if (audio_devs[gus_devnum]->dmap_out->dma > 3)
- dma_command |= 0x04; /* 16 bit DMA _channel_ */
+ if ((tmp_mem + patch.len) > gus_mem_size)
+ return -ENOSPC;
- gus_write8 (0x41, dma_command); /* Lets go luteet (=bugs) */
+ free_mem_ptr = tmp_mem; /* This leaves unusable memory */
+ }
+ }
+ if ((free_mem_ptr + patch.len) > gus_mem_size)
+ return -ENOSPC;
- /*
- * Sleep here until the DRAM DMA done interrupt is served
- */
- active_device = GUS_DEV_WAVE;
+ sample_ptrs[free_sample] = free_mem_ptr;
+
+ /*
+ * Tremolo is not possible with envelopes
+ */
+
+ if (patch.mode & WAVE_ENVELOPES)
+ patch.mode &= ~WAVE_TREMOLO;
+
+ if (!(patch.mode & WAVE_FRACTIONS))
+ {
+ patch.fractions = 0;
+ }
+ memcpy((char *) &samples[free_sample], &patch, sizeof_patch);
+
+ /*
+ * Link this_one sample to the list of samples for patch 'instr'.
+ */
+
+ samples[free_sample].key = patch_table[instr];
+ patch_table[instr] = free_sample;
+
+ /*
+ * Use DMA to transfer the wave data to the DRAM
+ */
+
+ left = patch.len;
+ src_offs = 0;
+ target = free_mem_ptr;
+
+ while (left) /* Not completely transferred yet */
+ {
+ blk_sz = audio_devs[gus_devnum]->dmap_out->bytes_in_use;
+ if (blk_sz > left)
+ blk_sz = left;
+
+ /*
+ * DMA cannot cross bank (256k) boundaries. Check for that.
+ */
+ blk_end = target + blk_sz;
+
+ if ((target / GUS_BANK_SIZE) != (blk_end / GUS_BANK_SIZE))
+ { /* Split the block */
+
+ blk_end &= ~(GUS_BANK_SIZE - 1);
+ blk_sz = blk_end - target;
+ }
+ if (gus_no_dma)
+ {
+ /*
+ * For some reason the DMA is not possible. We have to use PIO.
+ */
+ long i;
+ unsigned char data;
+
+ for (i = 0; i < blk_sz; i++)
+ {
+ get_user(*(unsigned char *) &data, (unsigned char *) &((addr)[sizeof_patch + i]));
+ if (patch.mode & WAVE_UNSIGNED)
+ if (!(patch.mode & WAVE_16_BITS) || (i & 0x01))
+ data ^= 0x80; /* Convert to signed */
+ gus_poke(target + i, data);
+ }
+ } else
+ {
+ unsigned long address, hold_address;
+ unsigned char dma_command;
+ unsigned long flags;
+
+ if (audio_devs[gus_devnum]->dmap_out->raw_buf == NULL)
+ {
+ printk("GUS: DMA buffer == NULL\n");
+ return -ENOSPC;
+ }
+ /*
+ * OK, move now. First in and then out.
+ */
+
+ copy_from_user(audio_devs[gus_devnum]->dmap_out->raw_buf, &(addr)[sizeof_patch + src_offs], blk_sz);
+
+ save_flags(flags);
+ cli();
+/******** INTERRUPTS DISABLED NOW ********/
+ gus_write8(0x41, 0); /* Disable GF1 DMA */
+ DMAbuf_start_dma(gus_devnum,
+ audio_devs[gus_devnum]->dmap_out->raw_buf_phys,
+ blk_sz, DMA_MODE_WRITE);
+
+ /*
+ * Set the DRAM address for the wave data
+ */
+
+ if (iw_mode)
+ {
+ /* Different address translation in enhanced mode */
+
+ unsigned char hi;
+
+ if (gus_dma > 4)
+ address = target >> 1; /* Convert to 16 bit word address */
+ else
+ address = target;
+
+ hi = (unsigned char) ((address >> 16) & 0xf0);
+ hi += (unsigned char) (address & 0x0f);
+
+ gus_write16(0x42, (address >> 4) & 0xffff); /* DMA address (low) */
+ gus_write8(0x50, hi);
+ } else
+ {
+ address = target;
+
+ if (audio_devs[gus_devnum]->dmap_out->dma > 3)
+ {
+ hold_address = address;
+ address = address >> 1;
+ address &= 0x0001ffffL;
+ address |= (hold_address & 0x000c0000L);
+ }
+ gus_write16(0x42, (address >> 4) & 0xffff); /* DRAM DMA address */
+ }
+
+ /*
+ * Start the DMA transfer
+ */
+
+ dma_command = 0x21; /* IRQ enable, DMA start */
+ if (patch.mode & WAVE_UNSIGNED)
+ dma_command |= 0x80; /* Invert MSB */
+ if (patch.mode & WAVE_16_BITS)
+ dma_command |= 0x40; /* 16 bit _DATA_ */
+ if (audio_devs[gus_devnum]->dmap_out->dma > 3)
+ dma_command |= 0x04; /* 16 bit DMA _channel_ */
+
+ gus_write8(0x41, dma_command); /* Lets go luteet (=bugs) */
+
+ /*
+ * Sleep here until the DRAM DMA done interrupt is served
+ */
+ active_device = GUS_DEV_WAVE;
+
+
+ {
+ unsigned long tlimit;
+
+ if (HZ)
+ current->timeout = tlimit = jiffies + (HZ);
+ else
+ tlimit = (unsigned long) -1;
+ dram_sleep_flag.opts = WK_SLEEP;
+ interruptible_sleep_on(&dram_sleeper);
+ if (!(dram_sleep_flag.opts & WK_WAKEUP))
+ {
+ if (jiffies >= tlimit)
+ dram_sleep_flag.opts |= WK_TIMEOUT;
+ }
+ dram_sleep_flag.opts &= ~WK_SLEEP;
+ };
+ if ((dram_sleep_flag.opts & WK_TIMEOUT))
+ printk("GUS: DMA Transfer timed out\n");
+ restore_flags(flags);
+ }
+
+ /*
+ * Now the next part
+ */
+
+ left -= blk_sz;
+ src_offs += blk_sz;
+ target += blk_sz;
+ gus_write8(0x41, 0); /* Stop DMA */
+ }
+
+ free_mem_ptr += patch.len;
+
+ free_sample++;
+ return 0;
+}
+
+static void
+guswave_hw_control(int dev, unsigned char *event_rec)
+{
+ int voice, cmd;
+ unsigned short p1, p2;
+ unsigned int plong;
+ unsigned flags;
+ cmd = event_rec[2];
+ voice = event_rec[3];
+ p1 = *(unsigned short *) &event_rec[4];
+ p2 = *(unsigned short *) &event_rec[6];
+ plong = *(unsigned int *) &event_rec[4];
+
+ if ((voices[voice].volume_irq_mode == VMODE_START_NOTE) &&
+ (cmd != _GUS_VOICESAMPLE) && (cmd != _GUS_VOICE_POS))
+ do_volume_irq(voice);
+
+ switch (cmd)
{
- unsigned long tlimit;
- if (HZ)
- current->timeout = tlimit = jiffies + (HZ);
- else
- tlimit = (unsigned long) -1;
- dram_sleep_flag.opts = WK_SLEEP;
- interruptible_sleep_on (&dram_sleeper);
- if (!(dram_sleep_flag.opts & WK_WAKEUP))
- {
- if (jiffies >= tlimit)
- dram_sleep_flag.opts |= WK_TIMEOUT;
- }
- dram_sleep_flag.opts &= ~WK_SLEEP;
- };
- if ((dram_sleep_flag.opts & WK_TIMEOUT))
- printk ("GUS: DMA Transfer timed out\n");
- restore_flags (flags);
- }
-
- /*
- * Now the next part
- */
-
- left -= blk_sz;
- src_offs += blk_sz;
- target += blk_sz;
-
- gus_write8 (0x41, 0); /* Stop DMA */
- }
-
- free_mem_ptr += patch.len;
-
- free_sample++;
- return 0;
-}
-
-static void
-guswave_hw_control (int dev, unsigned char *event_rec)
-{
- int voice, cmd;
- unsigned short p1, p2;
- unsigned int plong;
- unsigned flags;
-
- cmd = event_rec[2];
- voice = event_rec[3];
- p1 = *(unsigned short *) &event_rec[4];
- p2 = *(unsigned short *) &event_rec[6];
- plong = *(unsigned int *) &event_rec[4];
-
- if ((voices[voice].volume_irq_mode == VMODE_START_NOTE) &&
- (cmd != _GUS_VOICESAMPLE) && (cmd != _GUS_VOICE_POS))
- do_volume_irq (voice);
-
- switch (cmd)
- {
-
- case _GUS_NUMVOICES:
- save_flags (flags);
- cli ();
- gus_select_voice (voice);
- gus_select_max_voices (p1);
- restore_flags (flags);
- break;
-
- case _GUS_VOICESAMPLE:
- guswave_set_instr (dev, voice, p1);
- break;
-
- case _GUS_VOICEON:
- save_flags (flags);
- cli ();
- gus_select_voice (voice);
- p1 &= ~0x20; /* Don't allow interrupts */
- gus_voice_on (p1);
- restore_flags (flags);
- break;
-
- case _GUS_VOICEOFF:
- save_flags (flags);
- cli ();
- gus_select_voice (voice);
- gus_voice_off ();
- restore_flags (flags);
- break;
-
- case _GUS_VOICEFADE:
- gus_voice_fade (voice);
- break;
-
- case _GUS_VOICEMODE:
- save_flags (flags);
- cli ();
- gus_select_voice (voice);
- p1 &= ~0x20; /* Don't allow interrupts */
- gus_voice_mode (p1);
- restore_flags (flags);
- break;
-
- case _GUS_VOICEBALA:
- save_flags (flags);
- cli ();
- gus_select_voice (voice);
- gus_voice_balance (p1);
- restore_flags (flags);
- break;
-
- case _GUS_VOICEFREQ:
- save_flags (flags);
- cli ();
- gus_select_voice (voice);
- gus_voice_freq (plong);
- restore_flags (flags);
- break;
-
- case _GUS_VOICEVOL:
- save_flags (flags);
- cli ();
- gus_select_voice (voice);
- gus_voice_volume (p1);
- restore_flags (flags);
- break;
-
- case _GUS_VOICEVOL2: /* Just update the software voice level */
- voices[voice].initial_volume =
- voices[voice].current_volume = p1;
- break;
-
- case _GUS_RAMPRANGE:
- if (voices[voice].mode & WAVE_ENVELOPES)
- break; /* NO-NO */
- save_flags (flags);
- cli ();
- gus_select_voice (voice);
- gus_ramp_range (p1, p2);
- restore_flags (flags);
- break;
-
- case _GUS_RAMPRATE:
- if (voices[voice].mode & WAVE_ENVELOPES)
- break; /* NJET-NJET */
- save_flags (flags);
- cli ();
- gus_select_voice (voice);
- gus_ramp_rate (p1, p2);
- restore_flags (flags);
- break;
-
- case _GUS_RAMPMODE:
- if (voices[voice].mode & WAVE_ENVELOPES)
- break; /* NO-NO */
- save_flags (flags);
- cli ();
- gus_select_voice (voice);
- p1 &= ~0x20; /* Don't allow interrupts */
- gus_ramp_mode (p1);
- restore_flags (flags);
- break;
-
- case _GUS_RAMPON:
- if (voices[voice].mode & WAVE_ENVELOPES)
- break; /* EI-EI */
- save_flags (flags);
- cli ();
- gus_select_voice (voice);
- p1 &= ~0x20; /* Don't allow interrupts */
- gus_rampon (p1);
- restore_flags (flags);
- break;
-
- case _GUS_RAMPOFF:
- if (voices[voice].mode & WAVE_ENVELOPES)
- break; /* NEJ-NEJ */
- save_flags (flags);
- cli ();
- gus_select_voice (voice);
- gus_rampoff ();
- restore_flags (flags);
- break;
-
- case _GUS_VOLUME_SCALE:
- volume_base = p1;
- volume_scale = p2;
- break;
-
- case _GUS_VOICE_POS:
- save_flags (flags);
- cli ();
- gus_select_voice (voice);
- gus_set_voice_pos (voice, plong);
- restore_flags (flags);
- break;
+ case _GUS_NUMVOICES:
+ save_flags(flags);
+ cli();
+ gus_select_voice(voice);
+ gus_select_max_voices(p1);
+ restore_flags(flags);
+ break;
+
+ case _GUS_VOICESAMPLE:
+ guswave_set_instr(dev, voice, p1);
+ break;
+
+ case _GUS_VOICEON:
+ save_flags(flags);
+ cli();
+ gus_select_voice(voice);
+ p1 &= ~0x20; /* Don't allow interrupts */
+ gus_voice_on(p1);
+ restore_flags(flags);
+ break;
+
+ case _GUS_VOICEOFF:
+ save_flags(flags);
+ cli();
+ gus_select_voice(voice);
+ gus_voice_off();
+ restore_flags(flags);
+ break;
+
+ case _GUS_VOICEFADE:
+ gus_voice_fade(voice);
+ break;
+
+ case _GUS_VOICEMODE:
+ save_flags(flags);
+ cli();
+ gus_select_voice(voice);
+ p1 &= ~0x20; /* Don't allow interrupts */
+ gus_voice_mode(p1);
+ restore_flags(flags);
+ break;
+
+ case _GUS_VOICEBALA:
+ save_flags(flags);
+ cli();
+ gus_select_voice(voice);
+ gus_voice_balance(p1);
+ restore_flags(flags);
+ break;
+
+ case _GUS_VOICEFREQ:
+ save_flags(flags);
+ cli();
+ gus_select_voice(voice);
+ gus_voice_freq(plong);
+ restore_flags(flags);
+ break;
+
+ case _GUS_VOICEVOL:
+ save_flags(flags);
+ cli();
+ gus_select_voice(voice);
+ gus_voice_volume(p1);
+ restore_flags(flags);
+ break;
+
+ case _GUS_VOICEVOL2: /* Just update the software voice level */
+ voices[voice].initial_volume =
+ voices[voice].current_volume = p1;
+ break;
+
+ case _GUS_RAMPRANGE:
+ if (voices[voice].mode & WAVE_ENVELOPES)
+ break; /* NO-NO */
+ save_flags(flags);
+ cli();
+ gus_select_voice(voice);
+ gus_ramp_range(p1, p2);
+ restore_flags(flags);
+ break;
+
+ case _GUS_RAMPRATE:
+ if (voices[voice].mode & WAVE_ENVELOPES)
+ break; /* NJET-NJET */
+ save_flags(flags);
+ cli();
+ gus_select_voice(voice);
+ gus_ramp_rate(p1, p2);
+ restore_flags(flags);
+ break;
+
+ case _GUS_RAMPMODE:
+ if (voices[voice].mode & WAVE_ENVELOPES)
+ break; /* NO-NO */
+ save_flags(flags);
+ cli();
+ gus_select_voice(voice);
+ p1 &= ~0x20; /* Don't allow interrupts */
+ gus_ramp_mode(p1);
+ restore_flags(flags);
+ break;
+
+ case _GUS_RAMPON:
+ if (voices[voice].mode & WAVE_ENVELOPES)
+ break; /* EI-EI */
+ save_flags(flags);
+ cli();
+ gus_select_voice(voice);
+ p1 &= ~0x20; /* Don't allow interrupts */
+ gus_rampon(p1);
+ restore_flags(flags);
+ break;
+
+ case _GUS_RAMPOFF:
+ if (voices[voice].mode & WAVE_ENVELOPES)
+ break; /* NEJ-NEJ */
+ save_flags(flags);
+ cli();
+ gus_select_voice(voice);
+ gus_rampoff();
+ restore_flags(flags);
+ break;
+
+ case _GUS_VOLUME_SCALE:
+ volume_base = p1;
+ volume_scale = p2;
+ break;
+
+ case _GUS_VOICE_POS:
+ save_flags(flags);
+ cli();
+ gus_select_voice(voice);
+ gus_set_voice_pos(voice, plong);
+ restore_flags(flags);
+ break;
- default:;
- }
+ default:;
+ }
}
static int
-gus_audio_set_speed (int speed)
+gus_audio_set_speed(int speed)
{
- if (speed <= 0)
- speed = gus_audio_speed;
+ if (speed <= 0)
+ speed = gus_audio_speed;
- if (speed < 4000)
- speed = 4000;
+ if (speed < 4000)
+ speed = 4000;
- if (speed > 44100)
- speed = 44100;
+ if (speed > 44100)
+ speed = 44100;
- gus_audio_speed = speed;
+ gus_audio_speed = speed;
- if (only_read_access)
- {
- /* Compute nearest valid recording speed and return it */
+ if (only_read_access)
+ {
+ /* Compute nearest valid recording speed and return it */
- /* speed = (9878400 / (gus_audio_speed + 2)) / 16; */
- speed = (((9878400 + gus_audio_speed / 2) / (gus_audio_speed + 2)) + 8) / 16;
- speed = (9878400 / (speed * 16)) - 2;
- }
- return speed;
+ /* speed = (9878400 / (gus_audio_speed + 2)) / 16; */
+ speed = (((9878400 + gus_audio_speed / 2) / (gus_audio_speed + 2)) + 8) / 16;
+ speed = (9878400 / (speed * 16)) - 2;
+ }
+ return speed;
}
static int
-gus_audio_set_channels (int channels)
+gus_audio_set_channels(int channels)
{
- if (!channels)
- return gus_audio_channels;
- if (channels > 2)
- channels = 2;
- if (channels < 1)
- channels = 1;
- gus_audio_channels = channels;
- return channels;
+ if (!channels)
+ return gus_audio_channels;
+ if (channels > 2)
+ channels = 2;
+ if (channels < 1)
+ channels = 1;
+ gus_audio_channels = channels;
+ return channels;
}
static int
-gus_audio_set_bits (int bits)
+gus_audio_set_bits(int bits)
{
- if (!bits)
- return gus_audio_bits;
+ if (!bits)
+ return gus_audio_bits;
- if (bits != 8 && bits != 16)
- bits = 8;
+ if (bits != 8 && bits != 16)
+ bits = 8;
- if (only_8_bits)
- bits = 8;
+ if (only_8_bits)
+ bits = 8;
- gus_audio_bits = bits;
- return bits;
+ gus_audio_bits = bits;
+ return bits;
}
static int
-gus_audio_ioctl (int dev, unsigned int cmd, caddr_t arg)
+gus_audio_ioctl(int dev, unsigned int cmd, caddr_t arg)
{
- int val;
+ int val;
- switch (cmd)
- {
- case SOUND_PCM_WRITE_RATE:
- val = *(int *) arg;
- return (*(int *) arg = gus_audio_set_speed (val));
- break;
+ switch (cmd)
+ {
+ case SOUND_PCM_WRITE_RATE:
+ val = *(int *) arg;
+ return (*(int *) arg = gus_audio_set_speed(val));
+ break;
+
+ case SOUND_PCM_READ_RATE:
+ return (*(int *) arg = gus_audio_speed);
+ break;
+
+ case SNDCTL_DSP_STEREO:
+ val = *(int *) arg;
+ return (*(int *) arg = gus_audio_set_channels(val + 1) - 1);
+ break;
+
+ case SOUND_PCM_WRITE_CHANNELS:
+ val = *(int *) arg;
+ return (*(int *) arg = gus_audio_set_channels(val));
+ break;
+
+ case SOUND_PCM_READ_CHANNELS:
+ return (*(int *) arg = gus_audio_channels);
+ break;
+
+ case SNDCTL_DSP_SETFMT:
+ val = *(int *) arg;
+ return (*(int *) arg = gus_audio_set_bits(val));
+ break;
+
+ case SOUND_PCM_READ_BITS:
+ return (*(int *) arg = gus_audio_bits);
+
+ case SOUND_PCM_WRITE_FILTER: /* NOT POSSIBLE */
+ return (*(int *) arg = -EINVAL);
+ break;
+
+ case SOUND_PCM_READ_FILTER:
+ return (*(int *) arg = -EINVAL);
+ break;
- case SOUND_PCM_READ_RATE:
- return (*(int *) arg = gus_audio_speed);
- break;
+ }
+ return -EINVAL;
+}
- case SNDCTL_DSP_STEREO:
- val = *(int *) arg;
- return (*(int *) arg = gus_audio_set_channels (val + 1) - 1);
- break;
+static void
+gus_audio_reset(int dev)
+{
+ if (recording_active)
+ {
+ gus_write8(0x49, 0x00); /* Halt recording */
+ set_input_volumes();
+ }
+}
- case SOUND_PCM_WRITE_CHANNELS:
- val = *(int *) arg;
- return (*(int *) arg = gus_audio_set_channels (val));
- break;
+static int saved_iw_mode; /* A hack hack hack */
- case SOUND_PCM_READ_CHANNELS:
- return (*(int *) arg = gus_audio_channels);
- break;
+static int
+gus_audio_open(int dev, int mode)
+{
+ if (gus_busy)
+ return -EBUSY;
- case SNDCTL_DSP_SETFMT:
- val = *(int *) arg;
- return (*(int *) arg = gus_audio_set_bits (val));
- break;
+ if (gus_pnp_flag && mode & OPEN_READ)
+ {
+ printk("GUS: Audio device #%d is playback only.\n", dev);
+ return -EIO;
+ }
+ gus_initialize();
- case SOUND_PCM_READ_BITS:
- return (*(int *) arg = gus_audio_bits);
+ gus_busy = 1;
+ active_device = 0;
- case SOUND_PCM_WRITE_FILTER: /* NOT POSSIBLE */
- return (*(int *) arg = -EINVAL);
- break;
+ gus_reset();
+ reset_sample_memory();
+ gus_select_max_voices(14);
+ saved_iw_mode = iw_mode;
+ if (iw_mode)
+ {
+ /* There are some problems with audio in enhanced mode so disable it */
+ gus_write8(0x19, gus_read8(0x19) & ~0x01); /* Disable enhanced mode */
+ iw_mode = 0;
+ }
+ pcm_active = 0;
+ dma_active = 0;
+ pcm_opened = 1;
+ if (mode & OPEN_READ)
+ {
+ recording_active = 1;
+ set_input_volumes();
+ }
+ only_read_access = !(mode & OPEN_WRITE);
+ only_8_bits = mode & OPEN_READ;
+ if (only_8_bits)
+ audio_devs[dev]->format_mask = AFMT_U8;
+ else
+ audio_devs[dev]->format_mask = AFMT_U8 | AFMT_S16_LE;
- case SOUND_PCM_READ_FILTER:
- return (*(int *) arg = -EINVAL);
- break;
+ return 0;
+}
- }
- return -EINVAL;
+static void
+gus_audio_close(int dev)
+{
+ iw_mode = saved_iw_mode;
+ gus_reset();
+ gus_busy = 0;
+ pcm_opened = 0;
+ active_device = 0;
+
+ if (recording_active)
+ {
+ gus_write8(0x49, 0x00); /* Halt recording */
+ set_input_volumes();
+ }
+ recording_active = 0;
}
static void
-gus_audio_reset (int dev)
+gus_audio_update_volume(void)
{
- if (recording_active)
- {
- gus_write8 (0x49, 0x00); /* Halt recording */
- set_input_volumes ();
- }
+ unsigned long flags;
+ int voice;
+
+ if (pcm_active && pcm_opened)
+ for (voice = 0; voice < gus_audio_channels; voice++)
+ {
+ save_flags(flags);
+ cli();
+ gus_select_voice(voice);
+ gus_rampoff();
+ gus_voice_volume(1530 + (25 * gus_pcm_volume));
+ gus_ramp_range(65, 1530 + (25 * gus_pcm_volume));
+ restore_flags(flags);
+ }
}
-static int saved_iw_mode; /* A hack hack hack */
+static void
+play_next_pcm_block(void)
+{
+ unsigned long flags;
+ int speed = gus_audio_speed;
+ int this_one, is16bits, chn;
+ unsigned long dram_loc;
+ unsigned char mode[2], ramp_mode[2];
-static int
-gus_audio_open (int dev, int mode)
+ if (!pcm_qlen)
+ return;
+
+ this_one = pcm_head;
+
+ for (chn = 0; chn < gus_audio_channels; chn++)
+ {
+ mode[chn] = 0x00;
+ ramp_mode[chn] = 0x03; /* Ramping and rollover off */
+
+ if (chn == 0)
+ {
+ mode[chn] |= 0x20; /* Loop IRQ */
+ voices[chn].loop_irq_mode = LMODE_PCM;
+ }
+ if (gus_audio_bits != 8)
+ {
+ is16bits = 1;
+ mode[chn] |= 0x04; /* 16 bit data */
+ } else
+ is16bits = 0;
+
+ dram_loc = this_one * pcm_bsize;
+ dram_loc += chn * pcm_banksize;
+
+ if (this_one == (pcm_nblk - 1)) /* Last fragment of the DRAM buffer */
+ {
+ mode[chn] |= 0x08; /* Enable loop */
+ ramp_mode[chn] = 0x03; /* Disable rollover bit */
+ } else
+ {
+ if (chn == 0)
+ ramp_mode[chn] = 0x04; /* Enable rollover bit */
+ }
+
+ save_flags(flags);
+ cli();
+ gus_select_voice(chn);
+ gus_voice_freq(speed);
+
+ if (gus_audio_channels == 1)
+ gus_voice_balance(7); /* mono */
+ else if (chn == 0)
+ gus_voice_balance(0); /* left */
+ else
+ gus_voice_balance(15); /* right */
+
+ if (!pcm_active) /* Playback not already active */
+ {
+ /*
+ * The playback was not started yet (or there has been a pause).
+ * Start the voice (again) and ask for a rollover irq at the end of
+ * this_one block. If this_one one is last of the buffers, use just
+ * the normal loop with irq.
+ */
+
+ gus_voice_off();
+ gus_rampoff();
+ gus_voice_volume(1530 + (25 * gus_pcm_volume));
+ gus_ramp_range(65, 1530 + (25 * gus_pcm_volume));
+
+ gus_write_addr(0x0a, chn * pcm_banksize, 0, is16bits); /* Starting position */
+ gus_write_addr(0x02, chn * pcm_banksize, 0, is16bits); /* Loop start */
+
+ if (chn != 0)
+ gus_write_addr(0x04, pcm_banksize + (pcm_bsize * pcm_nblk) - 1,
+ 0, is16bits); /* Loop end location */
+ }
+ if (chn == 0)
+ gus_write_addr(0x04, dram_loc + pcm_bsize - 1,
+ 0, is16bits); /* Loop end location */
+ else
+ mode[chn] |= 0x08; /* Enable looping */
+
+
+ restore_flags(flags);
+ }
+
+ for (chn = 0; chn < gus_audio_channels; chn++)
+ {
+ save_flags(flags);
+ cli();
+ gus_select_voice(chn);
+ gus_write8(0x0d, ramp_mode[chn]);
+ if (iw_mode)
+ gus_write8(0x15, 0x00); /* Reset voice deactivate bit of SMSI */
+ gus_voice_on(mode[chn]);
+ restore_flags(flags);
+ }
+
+ pcm_active = 1;
+}
+
+static void
+gus_transfer_output_block(int dev, unsigned long buf,
+ int total_count, int intrflag, int chn)
{
- if (gus_busy)
- return -EBUSY;
+ /*
+ * This routine transfers one block of audio data to the DRAM. In mono mode
+ * it's called just once. When in stereo mode, this_one routine is called
+ * once for both channels.
+ *
+ * The left/mono channel data is transferred to the beginning of dram and the
+ * right data to the area pointed by gus_page_size.
+ */
- if (gus_pnp_flag && mode & OPEN_READ)
- {
- printk ("GUS: Audio device #%d is playback only.\n", dev);
- return -EIO;
- }
- gus_initialize ();
-
- gus_busy = 1;
- active_device = 0;
-
- gus_reset ();
- reset_sample_memory ();
- gus_select_max_voices (14);
- saved_iw_mode = iw_mode;
- if (iw_mode)
- {
- /* There are some problems with audio in enhanced mode so disable it */
- gus_write8 (0x19, gus_read8 (0x19) & ~0x01); /* Disable enhanced mode */
- iw_mode = 0;
- }
-
- pcm_active = 0;
- dma_active = 0;
- pcm_opened = 1;
- if (mode & OPEN_READ)
- {
- recording_active = 1;
- set_input_volumes ();
- }
- only_read_access = !(mode & OPEN_WRITE);
- only_8_bits = mode & OPEN_READ;
- if (only_8_bits)
- audio_devs[dev]->format_mask = AFMT_U8;
- else
- audio_devs[dev]->format_mask = AFMT_U8 | AFMT_S16_LE;
-
- return 0;
-}
-
-static void
-gus_audio_close (int dev)
-{
- iw_mode = saved_iw_mode;
- gus_reset ();
- gus_busy = 0;
- pcm_opened = 0;
- active_device = 0;
-
- if (recording_active)
- {
- gus_write8 (0x49, 0x00); /* Halt recording */
- set_input_volumes ();
- }
-
- recording_active = 0;
-}
-
-static void
-gus_audio_update_volume (void)
-{
- unsigned long flags;
- int voice;
-
- if (pcm_active && pcm_opened)
- for (voice = 0; voice < gus_audio_channels; voice++)
- {
- save_flags (flags);
- cli ();
- gus_select_voice (voice);
- gus_rampoff ();
- gus_voice_volume (1530 + (25 * gus_pcm_volume));
- gus_ramp_range (65, 1530 + (25 * gus_pcm_volume));
- restore_flags (flags);
- }
-}
-
-static void
-play_next_pcm_block (void)
-{
- unsigned long flags;
- int speed = gus_audio_speed;
- int this_one, is16bits, chn;
- unsigned long dram_loc;
- unsigned char mode[2], ramp_mode[2];
-
- if (!pcm_qlen)
- return;
-
- this_one = pcm_head;
-
- for (chn = 0; chn < gus_audio_channels; chn++)
- {
- mode[chn] = 0x00;
- ramp_mode[chn] = 0x03; /* Ramping and rollover off */
-
- if (chn == 0)
- {
- mode[chn] |= 0x20; /* Loop IRQ */
- voices[chn].loop_irq_mode = LMODE_PCM;
- }
-
- if (gus_audio_bits != 8)
- {
- is16bits = 1;
- mode[chn] |= 0x04; /* 16 bit data */
- }
- else
- is16bits = 0;
-
- dram_loc = this_one * pcm_bsize;
- dram_loc += chn * pcm_banksize;
-
- if (this_one == (pcm_nblk - 1)) /* Last fragment of the DRAM buffer */
- {
- mode[chn] |= 0x08; /* Enable loop */
- ramp_mode[chn] = 0x03; /* Disable rollover bit */
- }
- else
- {
- if (chn == 0)
- ramp_mode[chn] = 0x04; /* Enable rollover bit */
- }
-
- save_flags (flags);
- cli ();
- gus_select_voice (chn);
- gus_voice_freq (speed);
-
- if (gus_audio_channels == 1)
- gus_voice_balance (7); /* mono */
- else if (chn == 0)
- gus_voice_balance (0); /* left */
- else
- gus_voice_balance (15); /* right */
+ int this_one, count;
+ unsigned long flags;
+ unsigned char dma_command;
+ unsigned long address, hold_address;
- if (!pcm_active) /* Playback not already active */
- {
- /*
- * The playback was not started yet (or there has been a pause).
- * Start the voice (again) and ask for a rollover irq at the end of
- * this_one block. If this_one one is last of the buffers, use just
- * the normal loop with irq.
- */
+ save_flags(flags);
+ cli();
+
+ count = total_count / gus_audio_channels;
+
+ if (chn == 0)
+ {
+ if (pcm_qlen >= pcm_nblk)
+ printk("GUS Warning: PCM buffers out of sync\n");
- gus_voice_off ();
- gus_rampoff ();
- gus_voice_volume (1530 + (25 * gus_pcm_volume));
- gus_ramp_range (65, 1530 + (25 * gus_pcm_volume));
-
- gus_write_addr (0x0a, chn * pcm_banksize, 0, is16bits); /* Starting position */
- gus_write_addr (0x02, chn * pcm_banksize, 0, is16bits); /* Loop start */
-
- if (chn != 0)
- gus_write_addr (0x04, pcm_banksize + (pcm_bsize * pcm_nblk) - 1,
- 0, is16bits); /* Loop end location */
- }
-
- if (chn == 0)
- gus_write_addr (0x04, dram_loc + pcm_bsize - 1,
- 0, is16bits); /* Loop end location */
- else
- mode[chn] |= 0x08; /* Enable looping */
-
-
- restore_flags (flags);
- }
-
- for (chn = 0; chn < gus_audio_channels; chn++)
- {
- save_flags (flags);
- cli ();
- gus_select_voice (chn);
- gus_write8 (0x0d, ramp_mode[chn]);
- if (iw_mode)
- gus_write8 (0x15, 0x00); /* Reset voice deactivate bit of SMSI */
- gus_voice_on (mode[chn]);
- restore_flags (flags);
- }
-
- pcm_active = 1;
-}
-
-static void
-gus_transfer_output_block (int dev, unsigned long buf,
- int total_count, int intrflag, int chn)
-{
- /*
- * This routine transfers one block of audio data to the DRAM. In mono mode
- * it's called just once. When in stereo mode, this_one routine is called
- * once for both channels.
- *
- * The left/mono channel data is transferred to the beginning of dram and the
- * right data to the area pointed by gus_page_size.
- */
-
- int this_one, count;
- unsigned long flags;
- unsigned char dma_command;
- unsigned long address, hold_address;
-
- save_flags (flags);
- cli ();
-
- count = total_count / gus_audio_channels;
-
- if (chn == 0)
- {
- if (pcm_qlen >= pcm_nblk)
- printk ("GUS Warning: PCM buffers out of sync\n");
-
- this_one = pcm_current_block = pcm_tail;
- pcm_qlen++;
- pcm_tail = (pcm_tail + 1) % pcm_nblk;
- pcm_datasize[this_one] = count;
- }
- else
- this_one = pcm_current_block;
-
- gus_write8 (0x41, 0); /* Disable GF1 DMA */
- DMAbuf_start_dma (dev, buf + (chn * count), count, DMA_MODE_WRITE);
-
- address = this_one * pcm_bsize;
- address += chn * pcm_banksize;
-
- if (audio_devs[dev]->dmap_out->dma > 3)
- {
- hold_address = address;
- address = address >> 1;
- address &= 0x0001ffffL;
- address |= (hold_address & 0x000c0000L);
- }
-
- gus_write16 (0x42, (address >> 4) & 0xffff); /* DRAM DMA address */
-
- dma_command = 0x21; /* IRQ enable, DMA start */
-
- if (gus_audio_bits != 8)
- dma_command |= 0x40; /* 16 bit _DATA_ */
- else
- dma_command |= 0x80; /* Invert MSB */
-
- if (audio_devs[dev]->dmap_out->dma > 3)
- dma_command |= 0x04; /* 16 bit DMA channel */
-
- gus_write8 (0x41, dma_command); /* Kick start */
-
- if (chn == (gus_audio_channels - 1)) /* Last channel */
- {
- /*
- * Last (right or mono) channel data
- */
- dma_active = 1; /* DMA started. There is a unacknowledged buffer */
- active_device = GUS_DEV_PCM_DONE;
- if (!pcm_active && (pcm_qlen > 1 || count < pcm_bsize))
- {
- play_next_pcm_block ();
- }
- }
- else
- {
- /*
- * Left channel data. The right channel
- * is transferred after DMA interrupt
- */
- active_device = GUS_DEV_PCM_CONTINUE;
- }
+ this_one = pcm_current_block = pcm_tail;
+ pcm_qlen++;
+ pcm_tail = (pcm_tail + 1) % pcm_nblk;
+ pcm_datasize[this_one] = count;
+ } else
+ this_one = pcm_current_block;
- restore_flags (flags);
+ gus_write8(0x41, 0); /* Disable GF1 DMA */
+ DMAbuf_start_dma(dev, buf + (chn * count), count, DMA_MODE_WRITE);
+
+ address = this_one * pcm_bsize;
+ address += chn * pcm_banksize;
+
+ if (audio_devs[dev]->dmap_out->dma > 3)
+ {
+ hold_address = address;
+ address = address >> 1;
+ address &= 0x0001ffffL;
+ address |= (hold_address & 0x000c0000L);
+ }
+ gus_write16(0x42, (address >> 4) & 0xffff); /* DRAM DMA address */
+
+ dma_command = 0x21; /* IRQ enable, DMA start */
+
+ if (gus_audio_bits != 8)
+ dma_command |= 0x40; /* 16 bit _DATA_ */
+ else
+ dma_command |= 0x80; /* Invert MSB */
+
+ if (audio_devs[dev]->dmap_out->dma > 3)
+ dma_command |= 0x04; /* 16 bit DMA channel */
+
+ gus_write8(0x41, dma_command); /* Kick start */
+
+ if (chn == (gus_audio_channels - 1)) /* Last channel */
+ {
+ /*
+ * Last (right or mono) channel data
+ */
+ dma_active = 1; /* DMA started. There is a unacknowledged buffer */
+ active_device = GUS_DEV_PCM_DONE;
+ if (!pcm_active && (pcm_qlen > 1 || count < pcm_bsize))
+ {
+ play_next_pcm_block();
+ }
+ } else
+ {
+ /*
+ * Left channel data. The right channel
+ * is transferred after DMA interrupt
+ */
+ active_device = GUS_DEV_PCM_CONTINUE;
+ }
+
+ restore_flags(flags);
}
static void
-gus_uninterleave8 (char *buf, int l)
+gus_uninterleave8(char *buf, int l)
{
/* This routine uninterleaves 8 bit stereo output (LRLRLR->LLLRRR) */
- int i, p = 0, halfsize = l / 2;
- char *buf2 = buf + halfsize, *src = bounce_buf;
+ int i, p = 0, halfsize = l / 2;
+ char *buf2 = buf + halfsize, *src = bounce_buf;
- memcpy (bounce_buf, buf, l);
+ memcpy(bounce_buf, buf, l);
- for (i = 0; i < halfsize; i++)
- {
- buf[i] = src[p++]; /* Left channel */
- buf2[i] = src[p++]; /* Right channel */
- }
+ for (i = 0; i < halfsize; i++)
+ {
+ buf[i] = src[p++]; /* Left channel */
+ buf2[i] = src[p++]; /* Right channel */
+ }
}
static void
-gus_uninterleave16 (short *buf, int l)
+gus_uninterleave16(short *buf, int l)
{
/* This routine uninterleaves 16 bit stereo output (LRLRLR->LLLRRR) */
- int i, p = 0, halfsize = l / 2;
- short *buf2 = buf + halfsize, *src = (short *) bounce_buf;
+ int i, p = 0, halfsize = l / 2;
+ short *buf2 = buf + halfsize, *src = (short *) bounce_buf;
- memcpy (bounce_buf, (char *) buf, l * 2);
+ memcpy(bounce_buf, (char *) buf, l * 2);
- for (i = 0; i < halfsize; i++)
- {
- buf[i] = src[p++]; /* Left channel */
- buf2[i] = src[p++]; /* Right channel */
- }
+ for (i = 0; i < halfsize; i++)
+ {
+ buf[i] = src[p++]; /* Left channel */
+ buf2[i] = src[p++]; /* Right channel */
+ }
}
static void
-gus_audio_output_block (int dev, unsigned long buf, int total_count,
- int intrflag)
+gus_audio_output_block(int dev, unsigned long buf, int total_count,
+ int intrflag)
{
- struct dma_buffparms *dmap = audio_devs[dev]->dmap_out;
+ struct dma_buffparms *dmap = audio_devs[dev]->dmap_out;
- dmap->flags |= DMA_NODMA | DMA_NOTIMEOUT;
+ dmap->flags |= DMA_NODMA | DMA_NOTIMEOUT;
- pcm_current_buf = buf;
- pcm_current_count = total_count;
- pcm_current_intrflag = intrflag;
- pcm_current_dev = dev;
- if (gus_audio_channels == 2)
- {
- char *b = dmap->raw_buf + (buf - dmap->raw_buf_phys);
+ pcm_current_buf = buf;
+ pcm_current_count = total_count;
+ pcm_current_intrflag = intrflag;
+ pcm_current_dev = dev;
+ if (gus_audio_channels == 2)
+ {
+ char *b = dmap->raw_buf + (buf - dmap->raw_buf_phys);
- if (gus_audio_bits == 8)
- gus_uninterleave8 (b, total_count);
- else
- gus_uninterleave16 ((short *) b, total_count / 2);
- }
- gus_transfer_output_block (dev, buf, total_count, intrflag, 0);
+ if (gus_audio_bits == 8)
+ gus_uninterleave8(b, total_count);
+ else
+ gus_uninterleave16((short *) b, total_count / 2);
+ }
+ gus_transfer_output_block(dev, buf, total_count, intrflag, 0);
}
static void
-gus_audio_start_input (int dev, unsigned long buf, int count,
- int intrflag)
+gus_audio_start_input(int dev, unsigned long buf, int count,
+ int intrflag)
{
- unsigned long flags;
- unsigned char mode;
+ unsigned long flags;
+ unsigned char mode;
- save_flags (flags);
- cli ();
+ save_flags(flags);
+ cli();
- DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ);
+ DMAbuf_start_dma(dev, buf, count, DMA_MODE_READ);
- mode = 0xa0; /* DMA IRQ enabled, invert MSB */
+ mode = 0xa0; /* DMA IRQ enabled, invert MSB */
- if (audio_devs[dev]->dmap_in->dma > 3)
- mode |= 0x04; /* 16 bit DMA channel */
- if (gus_audio_channels > 1)
- mode |= 0x02; /* Stereo */
- mode |= 0x01; /* DMA enable */
+ if (audio_devs[dev]->dmap_in->dma > 3)
+ mode |= 0x04; /* 16 bit DMA channel */
+ if (gus_audio_channels > 1)
+ mode |= 0x02; /* Stereo */
+ mode |= 0x01; /* DMA enable */
- gus_write8 (0x49, mode);
+ gus_write8(0x49, mode);
- restore_flags (flags);
+ restore_flags(flags);
}
static int
-gus_audio_prepare_for_input (int dev, int bsize, int bcount)
+gus_audio_prepare_for_input(int dev, int bsize, int bcount)
{
- unsigned int rate;
-
- gus_audio_bsize = bsize;
- audio_devs[dev]->dmap_in->flags |= DMA_NODMA;
- rate = (((9878400 + gus_audio_speed / 2) / (gus_audio_speed + 2)) + 8) / 16;
+ unsigned int rate;
- gus_write8 (0x48, rate & 0xff); /* Set sampling rate */
+ gus_audio_bsize = bsize;
+ audio_devs[dev]->dmap_in->flags |= DMA_NODMA;
+ rate = (((9878400 + gus_audio_speed / 2) / (gus_audio_speed + 2)) + 8) / 16;
- if (gus_audio_bits != 8)
- {
- printk ("GUS Error: 16 bit recording not supported\n");
- return -EINVAL;
- }
+ gus_write8(0x48, rate & 0xff); /* Set sampling rate */
- return 0;
+ if (gus_audio_bits != 8)
+ {
+ printk("GUS Error: 16 bit recording not supported\n");
+ return -EINVAL;
+ }
+ return 0;
}
static int
-gus_audio_prepare_for_output (int dev, int bsize, int bcount)
+gus_audio_prepare_for_output(int dev, int bsize, int bcount)
{
- int i;
+ int i;
- long mem_ptr, mem_size;
+ long mem_ptr, mem_size;
- audio_devs[dev]->dmap_out->flags |= DMA_NODMA | DMA_NOTIMEOUT;
- mem_ptr = 0;
- mem_size = gus_mem_size / gus_audio_channels;
+ audio_devs[dev]->dmap_out->flags |= DMA_NODMA | DMA_NOTIMEOUT;
+ mem_ptr = 0;
+ mem_size = gus_mem_size / gus_audio_channels;
- if (mem_size > (256 * 1024))
- mem_size = 256 * 1024;
+ if (mem_size > (256 * 1024))
+ mem_size = 256 * 1024;
- pcm_bsize = bsize / gus_audio_channels;
- pcm_head = pcm_tail = pcm_qlen = 0;
+ pcm_bsize = bsize / gus_audio_channels;
+ pcm_head = pcm_tail = pcm_qlen = 0;
- pcm_nblk = 2; /* MAX_PCM_BUFFERS; */
- if ((pcm_bsize * pcm_nblk) > mem_size)
- pcm_nblk = mem_size / pcm_bsize;
+ pcm_nblk = 2; /* MAX_PCM_BUFFERS; */
+ if ((pcm_bsize * pcm_nblk) > mem_size)
+ pcm_nblk = mem_size / pcm_bsize;
- for (i = 0; i < pcm_nblk; i++)
- pcm_datasize[i] = 0;
+ for (i = 0; i < pcm_nblk; i++)
+ pcm_datasize[i] = 0;
- pcm_banksize = pcm_nblk * pcm_bsize;
+ pcm_banksize = pcm_nblk * pcm_bsize;
- if (gus_audio_bits != 8 && pcm_banksize == (256 * 1024))
- pcm_nblk--;
- gus_write8 (0x41, 0); /* Disable GF1 DMA */
+ if (gus_audio_bits != 8 && pcm_banksize == (256 * 1024))
+ pcm_nblk--;
+ gus_write8(0x41, 0); /* Disable GF1 DMA */
- return 0;
+ return 0;
}
static int
-gus_local_qlen (int dev)
+gus_local_qlen(int dev)
{
- return pcm_qlen;
+ return pcm_qlen;
}
static struct audio_driver gus_audio_driver =
{
- gus_audio_open,
- gus_audio_close,
- gus_audio_output_block,
- gus_audio_start_input,
- gus_audio_ioctl,
- gus_audio_prepare_for_input,
- gus_audio_prepare_for_output,
- gus_audio_reset,
- gus_local_qlen,
- NULL
+ gus_audio_open,
+ gus_audio_close,
+ gus_audio_output_block,
+ gus_audio_start_input,
+ gus_audio_ioctl,
+ gus_audio_prepare_for_input,
+ gus_audio_prepare_for_output,
+ gus_audio_reset,
+ gus_local_qlen,
+ NULL
};
static void
-guswave_setup_voice (int dev, int voice, int chn)
+guswave_setup_voice(int dev, int voice, int chn)
{
- struct channel_info *info =
- &synth_devs[dev]->chn_info[chn];
+ struct channel_info *info =
+ &synth_devs[dev]->chn_info[chn];
- guswave_set_instr (dev, voice, info->pgm_num);
+ guswave_set_instr(dev, voice, info->pgm_num);
- voices[voice].expression_vol =
- info->controllers[CTL_EXPRESSION]; /* Just MSB */
- voices[voice].main_vol =
- (info->controllers[CTL_MAIN_VOLUME] * 100) / (unsigned) 128;
- voices[voice].panning =
- (info->controllers[CTL_PAN] * 2) - 128;
- voices[voice].bender = 0;
- voices[voice].bender_range = info->bender_range;
+ voices[voice].expression_vol =
+ info->controllers[CTL_EXPRESSION]; /* Just MSB */
+ voices[voice].main_vol =
+ (info->controllers[CTL_MAIN_VOLUME] * 100) / (unsigned) 128;
+ voices[voice].panning =
+ (info->controllers[CTL_PAN] * 2) - 128;
+ voices[voice].bender = 0;
+ voices[voice].bender_range = info->bender_range;
- if (chn == 9)
- voices[voice].fixed_pitch = 1;
+ if (chn == 9)
+ voices[voice].fixed_pitch = 1;
}
static void
-guswave_bender (int dev, int voice, int value)
+guswave_bender(int dev, int voice, int value)
{
- int freq;
- unsigned long flags;
+ int freq;
+ unsigned long flags;
- voices[voice].bender = value - 8192;
- freq = compute_finetune (voices[voice].orig_freq, value - 8192,
- voices[voice].bender_range, 0);
- voices[voice].current_freq = freq;
+ voices[voice].bender = value - 8192;
+ freq = compute_finetune(voices[voice].orig_freq, value - 8192,
+ voices[voice].bender_range, 0);
+ voices[voice].current_freq = freq;
- save_flags (flags);
- cli ();
- gus_select_voice (voice);
- gus_voice_freq (freq);
- restore_flags (flags);
+ save_flags(flags);
+ cli();
+ gus_select_voice(voice);
+ gus_voice_freq(freq);
+ restore_flags(flags);
}
static int
-guswave_alloc (int dev, int chn, int note, struct voice_alloc_info *alloc)
+guswave_alloc(int dev, int chn, int note, struct voice_alloc_info *alloc)
{
- int i, p, best = -1, best_time = 0x7fffffff;
+ int i, p, best = -1, best_time = 0x7fffffff;
+
+ p = alloc->ptr;
+ /*
+ * First look for a completely stopped voice
+ */
+
+ for (i = 0; i < alloc->max_voice; i++)
+ {
+ if (alloc->map[p] == 0)
+ {
+ alloc->ptr = p;
+ return p;
+ }
+ if (alloc->alloc_times[p] < best_time)
+ {
+ best = p;
+ best_time = alloc->alloc_times[p];
+ }
+ p = (p + 1) % alloc->max_voice;
+ }
- p = alloc->ptr;
- /*
- * First look for a completely stopped voice
- */
-
- for (i = 0; i < alloc->max_voice; i++)
- {
- if (alloc->map[p] == 0)
- {
- alloc->ptr = p;
- return p;
- }
- if (alloc->alloc_times[p] < best_time)
- {
- best = p;
- best_time = alloc->alloc_times[p];
- }
- p = (p + 1) % alloc->max_voice;
- }
-
- /*
- * Then look for a releasing voice
- */
-
- for (i = 0; i < alloc->max_voice; i++)
- {
- if (alloc->map[p] == 0xffff)
- {
- alloc->ptr = p;
- return p;
- }
- p = (p + 1) % alloc->max_voice;
- }
+ /*
+ * Then look for a releasing voice
+ */
- if (best >= 0)
- p = best;
+ for (i = 0; i < alloc->max_voice; i++)
+ {
+ if (alloc->map[p] == 0xffff)
+ {
+ alloc->ptr = p;
+ return p;
+ }
+ p = (p + 1) % alloc->max_voice;
+ }
+
+ if (best >= 0)
+ p = best;
- alloc->ptr = p;
- return p;
+ alloc->ptr = p;
+ return p;
}
static struct synth_operations guswave_operations =
{
- "GUS",
- &gus_info,
- 0,
- SYNTH_TYPE_SAMPLE,
- SAMPLE_TYPE_GUS,
- guswave_open,
- guswave_close,
- guswave_ioctl,
- guswave_kill_note,
- guswave_start_note,
- guswave_set_instr,
- guswave_reset,
- guswave_hw_control,
- guswave_load_patch,
- guswave_aftertouch,
- guswave_controller,
- guswave_panning,
- guswave_volume_method,
- guswave_bender,
- guswave_alloc,
- guswave_setup_voice
+ "GUS",
+ &gus_info,
+ 0,
+ SYNTH_TYPE_SAMPLE,
+ SAMPLE_TYPE_GUS,
+ guswave_open,
+ guswave_close,
+ guswave_ioctl,
+ guswave_kill_note,
+ guswave_start_note,
+ guswave_set_instr,
+ guswave_reset,
+ guswave_hw_control,
+ guswave_load_patch,
+ guswave_aftertouch,
+ guswave_controller,
+ guswave_panning,
+ guswave_volume_method,
+ guswave_bender,
+ guswave_alloc,
+ guswave_setup_voice
};
static void
-set_input_volumes (void)
+set_input_volumes(void)
{
- unsigned long flags;
- unsigned char mask = 0xff & ~0x06; /* Just line out enabled */
+ unsigned long flags;
+ unsigned char mask = 0xff & ~0x06; /* Just line out enabled */
+
+ if (have_gus_max) /* Don't disturb GUS MAX */
+ return;
- if (have_gus_max) /* Don't disturb GUS MAX */
- return;
+ save_flags(flags);
+ cli();
- save_flags (flags);
- cli ();
-
- /*
- * Enable channels having vol > 10%
- * Note! bit 0x01 means the line in DISABLED while 0x04 means
- * the mic in ENABLED.
- */
- if (gus_line_vol > 10)
- mask &= ~0x01;
- if (gus_mic_vol > 10)
- mask |= 0x04;
-
- if (recording_active)
- {
- /*
- * Disable channel, if not selected for recording
- */
- if (!(gus_recmask & SOUND_MASK_LINE))
- mask |= 0x01;
- if (!(gus_recmask & SOUND_MASK_MIC))
- mask &= ~0x04;
- }
-
- mix_image &= ~0x07;
- mix_image |= mask & 0x07;
- outb ((mix_image), u_Mixer);
+ /*
+ * Enable channels having vol > 10%
+ * Note! bit 0x01 means the line in DISABLED while 0x04 means
+ * the mic in ENABLED.
+ */
+ if (gus_line_vol > 10)
+ mask &= ~0x01;
+ if (gus_mic_vol > 10)
+ mask |= 0x04;
- restore_flags (flags);
+ if (recording_active)
+ {
+ /*
+ * Disable channel, if not selected for recording
+ */
+ if (!(gus_recmask & SOUND_MASK_LINE))
+ mask |= 0x01;
+ if (!(gus_recmask & SOUND_MASK_MIC))
+ mask &= ~0x04;
+ }
+ mix_image &= ~0x07;
+ mix_image |= mask & 0x07;
+ outb((mix_image), u_Mixer);
+
+ restore_flags(flags);
}
int
-gus_default_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg)
+gus_default_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg)
{
#define MIX_DEVS (SOUND_MASK_MIC|SOUND_MASK_LINE| \
SOUND_MASK_SYNTH|SOUND_MASK_PCM)
- if (((cmd >> 8) & 0xff) == 'M')
- {
- if (_SIOC_DIR (cmd) & _SIOC_WRITE)
- switch (cmd & 0xff)
- {
- case SOUND_MIXER_RECSRC:
- gus_recmask = *(int *) arg;
- gus_recmask &= MIX_DEVS;
- if (!(gus_recmask & (SOUND_MASK_MIC | SOUND_MASK_LINE)))
- gus_recmask = SOUND_MASK_MIC;
- /* Note! Input volumes are updated during next open for recording */
- return (*(int *) arg = gus_recmask);
- break;
-
- case SOUND_MIXER_MIC:
- {
- int vol;
-
- vol = *(int *) arg;
- vol &= 0xff;
-
- if (vol < 0)
- vol = 0;
- if (vol > 100)
- vol = 100;
- gus_mic_vol = vol;
- set_input_volumes ();
- return (*(int *) arg = vol | (vol << 8));
- }
- break;
-
- case SOUND_MIXER_LINE:
- {
- int vol;
-
- vol = *(int *) arg;
- vol &= 0xff;
-
- if (vol < 0)
- vol = 0;
- if (vol > 100)
- vol = 100;
- gus_line_vol = vol;
- set_input_volumes ();
- return (*(int *) arg = vol | (vol << 8));
- }
- break;
-
- case SOUND_MIXER_PCM:
- gus_pcm_volume = *(int *) arg;
- gus_pcm_volume &= 0xff;
- if (gus_pcm_volume < 0)
- gus_pcm_volume = 0;
- if (gus_pcm_volume > 100)
- gus_pcm_volume = 100;
- gus_audio_update_volume ();
- return (*(int *) arg = gus_pcm_volume | (gus_pcm_volume << 8));
- break;
-
- case SOUND_MIXER_SYNTH:
- {
- int voice;
-
- gus_wave_volume = *(int *) arg;
- gus_wave_volume &= 0xff;
-
- if (gus_wave_volume < 0)
- gus_wave_volume = 0;
- if (gus_wave_volume > 100)
- gus_wave_volume = 100;
-
- if (active_device == GUS_DEV_WAVE)
- for (voice = 0; voice < nr_voices; voice++)
- dynamic_volume_change (voice); /* Apply the new vol */
-
- return (*(int *) arg = gus_wave_volume | (gus_wave_volume << 8));
- }
- break;
-
- default:
- return -EINVAL;
- }
- else
- switch (cmd & 0xff) /*
- * Return parameters
- */
+ if (((cmd >> 8) & 0xff) == 'M')
{
-
- case SOUND_MIXER_RECSRC:
- return (*(int *) arg = gus_recmask);
- break;
-
- case SOUND_MIXER_DEVMASK:
- return (*(int *) arg = MIX_DEVS);
- break;
-
- case SOUND_MIXER_STEREODEVS:
- return (*(int *) arg = 0);
- break;
-
- case SOUND_MIXER_RECMASK:
- return (*(int *) arg = SOUND_MASK_MIC | SOUND_MASK_LINE);
- break;
-
- case SOUND_MIXER_CAPS:
- return (*(int *) arg = 0);
- break;
-
- case SOUND_MIXER_MIC:
- return (*(int *) arg = gus_mic_vol | (gus_mic_vol << 8));
- break;
-
- case SOUND_MIXER_LINE:
- return (*(int *) arg = gus_line_vol | (gus_line_vol << 8));
- break;
-
- case SOUND_MIXER_PCM:
- return (*(int *) arg = gus_pcm_volume | (gus_pcm_volume << 8));
- break;
-
- case SOUND_MIXER_SYNTH:
- return (*(int *) arg = gus_wave_volume | (gus_wave_volume << 8));
- break;
-
- default:
- return -EINVAL;
- }
- }
- else
- return -EINVAL;
+ if (_SIOC_DIR(cmd) & _SIOC_WRITE)
+ switch (cmd & 0xff)
+ {
+ case SOUND_MIXER_RECSRC:
+ gus_recmask = *(int *) arg;
+ gus_recmask &= MIX_DEVS;
+ if (!(gus_recmask & (SOUND_MASK_MIC | SOUND_MASK_LINE)))
+ gus_recmask = SOUND_MASK_MIC;
+ /* Note! Input volumes are updated during next open for recording */
+ return (*(int *) arg = gus_recmask);
+ break;
+
+ case SOUND_MIXER_MIC:
+ {
+ int vol;
+
+ vol = *(int *) arg;
+ vol &= 0xff;
+
+ if (vol < 0)
+ vol = 0;
+ if (vol > 100)
+ vol = 100;
+ gus_mic_vol = vol;
+ set_input_volumes();
+ return (*(int *) arg = vol | (vol << 8));
+ }
+ break;
+
+ case SOUND_MIXER_LINE:
+ {
+ int vol;
+
+ vol = *(int *) arg;
+ vol &= 0xff;
+
+ if (vol < 0)
+ vol = 0;
+ if (vol > 100)
+ vol = 100;
+ gus_line_vol = vol;
+ set_input_volumes();
+ return (*(int *) arg = vol | (vol << 8));
+ }
+ break;
+
+ case SOUND_MIXER_PCM:
+ gus_pcm_volume = *(int *) arg;
+ gus_pcm_volume &= 0xff;
+ if (gus_pcm_volume < 0)
+ gus_pcm_volume = 0;
+ if (gus_pcm_volume > 100)
+ gus_pcm_volume = 100;
+ gus_audio_update_volume();
+ return (*(int *) arg = gus_pcm_volume | (gus_pcm_volume << 8));
+ break;
+
+ case SOUND_MIXER_SYNTH:
+ {
+ int voice;
+
+ gus_wave_volume = *(int *) arg;
+ gus_wave_volume &= 0xff;
+
+ if (gus_wave_volume < 0)
+ gus_wave_volume = 0;
+ if (gus_wave_volume > 100)
+ gus_wave_volume = 100;
+
+ if (active_device == GUS_DEV_WAVE)
+ for (voice = 0; voice < nr_voices; voice++)
+ dynamic_volume_change(voice); /* Apply the new vol */
+
+ return (*(int *) arg = gus_wave_volume | (gus_wave_volume << 8));
+ }
+ break;
+
+ default:
+ return -EINVAL;
+ } else
+ switch (cmd & 0xff) /*
+ * Return parameters
+ */
+ {
+
+ case SOUND_MIXER_RECSRC:
+ return (*(int *) arg = gus_recmask);
+ break;
+
+ case SOUND_MIXER_DEVMASK:
+ return (*(int *) arg = MIX_DEVS);
+ break;
+
+ case SOUND_MIXER_STEREODEVS:
+ return (*(int *) arg = 0);
+ break;
+
+ case SOUND_MIXER_RECMASK:
+ return (*(int *) arg = SOUND_MASK_MIC | SOUND_MASK_LINE);
+ break;
+
+ case SOUND_MIXER_CAPS:
+ return (*(int *) arg = 0);
+ break;
+
+ case SOUND_MIXER_MIC:
+ return (*(int *) arg = gus_mic_vol | (gus_mic_vol << 8));
+ break;
+
+ case SOUND_MIXER_LINE:
+ return (*(int *) arg = gus_line_vol | (gus_line_vol << 8));
+ break;
+
+ case SOUND_MIXER_PCM:
+ return (*(int *) arg = gus_pcm_volume | (gus_pcm_volume << 8));
+ break;
+
+ case SOUND_MIXER_SYNTH:
+ return (*(int *) arg = gus_wave_volume | (gus_wave_volume << 8));
+ break;
+
+ default:
+ return -EINVAL;
+ }
+ } else
+ return -EINVAL;
}
static struct mixer_operations gus_mixer_operations =
{
- "GUS",
- "Gravis Ultrasound",
- gus_default_mixer_ioctl
+ "GUS",
+ "Gravis Ultrasound",
+ gus_default_mixer_ioctl
};
-static void
-gus_default_mixer_init (void)
+static int
+gus_default_mixer_init(void)
{
- if (num_mixers < MAX_MIXER_DEV) /*
- * Don't install if there is another
- * mixer
- */
- mixer_devs[num_mixers++] = &gus_mixer_operations;
+ int n;
- if (have_gus_max)
- {
+ if ((n = sound_alloc_mixerdev()) != -1)
+ { /*
+ * Don't install if there is another
+ * mixer
+ */
+ mixer_devs[n] = &gus_mixer_operations;
+ }
+ if (have_gus_max)
+ {
/*
* Enable all mixer channels on the GF1 side. Otherwise recording will
* not be possible using GUS MAX.
*/
- mix_image &= ~0x07;
- mix_image |= 0x04; /* All channels enabled */
- outb ((mix_image), u_Mixer);
- }
+ mix_image &= ~0x07;
+ mix_image |= 0x04; /* All channels enabled */
+ outb((mix_image), u_Mixer);
+ }
+ return n;
}
void
-gus_wave_init (struct address_info *hw_config)
+gus_wave_init(struct address_info *hw_config)
{
- unsigned long flags;
- unsigned char val;
- char *model_num = "2.4";
- char tmp[64], tmp2[64];
- int gus_type = 0x24; /* 2.4 */
-
- int irq = hw_config->irq, dma = hw_config->dma, dma2 = hw_config->dma2;
-
- if (!gus_pnp_flag)
- if (irq < 0 || irq > 15)
- {
- printk ("ERROR! Invalid IRQ#%d. GUS Disabled", irq);
- return;
- }
-
- if (dma < 0 || dma > 7 || dma == 4)
- {
- printk ("ERROR! Invalid DMA#%d. GUS Disabled", dma);
- return;
- }
-
- gus_irq = irq;
- gus_dma = dma;
- gus_dma2 = dma2;
-
- if (gus_dma2 == -1)
- gus_dma2 = dma;
-
- /*
- * Try to identify the GUS model.
- *
- * Versions < 3.6 don't have the digital ASIC. Try to probe it first.
- */
-
- save_flags (flags);
- cli ();
- outb ((0x20), gus_base + 0x0f);
- val = inb (gus_base + 0x0f);
- restore_flags (flags);
-
- if (gus_pnp_flag || (val != 0xff && (val & 0x06))) /* Should be 0x02?? */
- {
- int ad_flags = 0;
-
- if (gus_pnp_flag)
- ad_flags = 0x12345678; /* Interwave "magic" */
- /*
- * It has the digital ASIC so the card is at least v3.4.
- * Next try to detect the true model.
- */
-
- if (gus_pnp_flag) /* Hack hack hack */
- val = 10;
- else
- val = inb (u_MixSelect);
-
- /*
- * Value 255 means pre-3.7 which don't have mixer.
- * Values 5 thru 9 mean v3.7 which has a ICS2101 mixer.
- * 10 and above is GUS MAX which has the CS4231 codec/mixer.
- *
- */
-
- if (val == 255 || val < 5)
- {
- model_num = "3.4";
- gus_type = 0x34;
- }
- else if (val < 10)
- {
- model_num = "3.7";
- gus_type = 0x37;
- mixer_type = ICS2101;
- request_region (u_MixSelect, 1, "GUS mixer");
- }
- else
- {
- model_num = "MAX";
- gus_type = 0x40;
- mixer_type = CS4231;
-#ifdef CONFIG_GUSMAX
+ unsigned long flags;
+ unsigned char val;
+ char *model_num = "2.4";
+ char tmp[64], tmp2[64];
+ int gus_type = 0x24; /* 2.4 */
+
+ int irq = hw_config->irq, dma = hw_config->dma,
+ dma2 = hw_config->dma2;
+ int dev;
+ int sdev;
+
+ hw_config->slots[0] = -1; /* No wave */
+ hw_config->slots[1] = -1; /* No ad1848 */
+ hw_config->slots[4] = -1; /* No audio */
+ hw_config->slots[5] = -1; /* No mixer */
+
+ if (!gus_pnp_flag)
+ if (irq < 0 || irq > 15)
+ {
+ printk("ERROR! Invalid IRQ#%d. GUS Disabled", irq);
+ return;
+ }
+ if (dma < 0 || dma > 7 || dma == 4)
{
- unsigned char max_config = 0x40; /* Codec enable */
+ printk("ERROR! Invalid DMA#%d. GUS Disabled", dma);
+ return;
+ }
+ gus_irq = irq;
+ gus_dma = dma;
+ gus_dma2 = dma2;
+
+ if (gus_dma2 == -1)
+ gus_dma2 = dma;
+
+ /*
+ * Try to identify the GUS model.
+ *
+ * Versions < 3.6 don't have the digital ASIC. Try to probe it first.
+ */
+
+ save_flags(flags);
+ cli();
+ outb((0x20), gus_base + 0x0f);
+ val = inb(gus_base + 0x0f);
+ restore_flags(flags);
+
+ if (gus_pnp_flag || (val != 0xff && (val & 0x06))) /* Should be 0x02?? */
+ {
+ int ad_flags = 0;
+
+ if (gus_pnp_flag)
+ ad_flags = 0x12345678; /* Interwave "magic" */
+ /*
+ * It has the digital ASIC so the card is at least v3.4.
+ * Next try to detect the true model.
+ */
+
+ if (gus_pnp_flag) /* Hack hack hack */
+ val = 10;
+ else
+ val = inb(u_MixSelect);
+
+ /*
+ * Value 255 means pre-3.7 which don't have mixer.
+ * Values 5 thru 9 mean v3.7 which has a ICS2101 mixer.
+ * 10 and above is GUS MAX which has the CS4231 codec/mixer.
+ *
+ */
+
+ if (val == 255 || val < 5)
+ {
+ model_num = "3.4";
+ gus_type = 0x34;
+ } else if (val < 10)
+ {
+ model_num = "3.7";
+ gus_type = 0x37;
+ mixer_type = ICS2101;
+ request_region(u_MixSelect, 1, "GUS mixer");
+ } else
+ {
+ model_num = "MAX";
+ gus_type = 0x40;
+ mixer_type = CS4231;
+#ifdef CONFIG_GUSMAX
+ {
+ unsigned char max_config = 0x40; /* Codec enable */
- if (gus_dma2 == -1)
- gus_dma2 = gus_dma;
+ if (gus_dma2 == -1)
+ gus_dma2 = gus_dma;
- if (gus_dma > 3)
- max_config |= 0x10; /* 16 bit capture DMA */
+ if (gus_dma > 3)
+ max_config |= 0x10; /* 16 bit capture DMA */
- if (gus_dma2 > 3)
- max_config |= 0x20; /* 16 bit playback DMA */
-
- max_config |= (gus_base >> 4) & 0x0f; /* Extract the X from 2X0 */
-
- outb ((max_config), gus_base + 0x106); /* UltraMax control */
- }
-
- if (ad1848_detect (gus_base + 0x10c, &ad_flags, hw_config->osp))
- {
- char *name = "GUS MAX";
- int old_num_mixers = num_mixers;
-
- if (gus_pnp_flag)
- name = "GUS PnP";
-
- gus_mic_vol = gus_line_vol = gus_pcm_volume = 100;
- gus_wave_volume = 90;
- have_gus_max = 1;
- if (hw_config->name)
- name = hw_config->name;
-
- ad1848_init (name, gus_base + 0x10c,
- -irq,
- gus_dma2, /* Playback DMA */
- gus_dma, /* Capture DMA */
- 1, /* Share DMA channels with GF1 */
- hw_config->osp);
-
- if (num_mixers > old_num_mixers)
- { /* GUS has it's own mixer map */
- AD1848_REROUTE (SOUND_MIXER_LINE1, SOUND_MIXER_SYNTH);
- AD1848_REROUTE (SOUND_MIXER_LINE2, SOUND_MIXER_CD);
- AD1848_REROUTE (SOUND_MIXER_LINE3, SOUND_MIXER_LINE);
- }
- }
- else
- printk ("[Where's the CS4231?]");
+ if (gus_dma2 > 3)
+ max_config |= 0x20; /* 16 bit playback DMA */
+
+ max_config |= (gus_base >> 4) & 0x0f; /* Extract the X from 2X0 */
+
+ outb((max_config), gus_base + 0x106); /* UltraMax control */
+ }
+
+ if (ad1848_detect(gus_base + 0x10c, &ad_flags, hw_config->osp))
+ {
+ char *name = "GUS MAX";
+ int old_num_mixers = num_mixers;
+
+ if (gus_pnp_flag)
+ name = "GUS PnP";
+
+ gus_mic_vol = gus_line_vol = gus_pcm_volume = 100;
+ gus_wave_volume = 90;
+ have_gus_max = 1;
+ if (hw_config->name)
+ name = hw_config->name;
+
+ hw_config->slots[1] = ad1848_init(name, gus_base + 0x10c,
+ -irq,
+ gus_dma2, /* Playback DMA */
+ gus_dma, /* Capture DMA */
+ 1, /* Share DMA channels with GF1 */
+ hw_config->osp);
+
+ if (num_mixers > old_num_mixers)
+ { /* GUS has it's own mixer map */
+ AD1848_REROUTE(SOUND_MIXER_LINE1, SOUND_MIXER_SYNTH);
+ AD1848_REROUTE(SOUND_MIXER_LINE2, SOUND_MIXER_CD);
+ AD1848_REROUTE(SOUND_MIXER_LINE3, SOUND_MIXER_LINE);
+ }
+ } else
+ printk("[Where's the CS4231?]");
#else
- printk ("\n\n\nGUS MAX support was not compiled in!!!\n\n\n\n");
+ printk("\n\n\nGUS MAX support was not compiled in!!!\n\n\n\n");
#endif
- }
- }
- else
- {
- /*
- * ASIC not detected so the card must be 2.2 or 2.4.
- * There could still be the 16-bit/mixer daughter card.
- */
- }
-
- if (hw_config->name)
- {
-
- strncpy (tmp, hw_config->name, 45);
- tmp[45] = 0;
- sprintf (tmp2, "%s (%dk)", tmp, (int) gus_mem_size / 1024);
- tmp2[sizeof (tmp2) - 1] = 0;
- }
- else if (gus_pnp_flag)
- {
- sprintf (tmp2, "Gravis UltraSound PnP (%dk)",
- (int) gus_mem_size / 1024);
- }
- else
- sprintf (tmp2, "Gravis UltraSound %s (%dk)", model_num, (int) gus_mem_size / 1024);
-
-
- samples = (struct patch_info *) (sound_mem_blocks[sound_nblocks] = vmalloc ((MAX_SAMPLE + 1) * sizeof (*samples)));
- sound_mem_sizes[sound_nblocks] = (MAX_SAMPLE + 1) * sizeof (*samples);
- if (sound_nblocks < 1024)
- sound_nblocks++;;
- if (samples == NULL)
- {
- printk ("GUS Error: Cant allocate memory for instrument tables\n");
- return;
- }
-
- conf_printf (tmp2, hw_config);
- tmp2[sizeof (gus_info.name) - 1] = 0;
- strcpy (gus_info.name, tmp2);
-
- if (num_synths >= MAX_SYNTH_DEV)
- printk ("GUS Error: Too many synthesizers\n");
- else
- {
- voice_alloc = &guswave_operations.alloc;
- if (iw_mode)
- guswave_operations.id = "IWAVE";
- synth_devs[num_synths++] = &guswave_operations;
- sequencer_init ();
-#ifdef CONFIG_SEQUENCER
- gus_tmr_install (gus_base + 8);
+ }
+ } else
+ {
+ /*
+ * ASIC not detected so the card must be 2.2 or 2.4.
+ * There could still be the 16-bit/mixer daughter card.
+ */
+ }
+
+ if (hw_config->name)
+ {
+
+ strncpy(tmp, hw_config->name, 45);
+ tmp[45] = 0;
+ sprintf(tmp2, "%s (%dk)", tmp, (int) gus_mem_size / 1024);
+ tmp2[sizeof(tmp2) - 1] = 0;
+ } else if (gus_pnp_flag)
+ {
+ sprintf(tmp2, "Gravis UltraSound PnP (%dk)",
+ (int) gus_mem_size / 1024);
+ } else
+ sprintf(tmp2, "Gravis UltraSound %s (%dk)", model_num, (int) gus_mem_size / 1024);
+
+
+ samples = (struct patch_info *) (sound_mem_blocks[sound_nblocks] = vmalloc((MAX_SAMPLE + 1) * sizeof(*samples)));
+ sound_mem_sizes[sound_nblocks] = (MAX_SAMPLE + 1) * sizeof(*samples);
+ if (sound_nblocks < 1024)
+ sound_nblocks++;;
+ if (samples == NULL)
+ {
+ printk(KERN_WARNING "gus_init: Cant allocate memory for instrument tables\n");
+ return;
+ }
+ conf_printf(tmp2, hw_config);
+ tmp2[sizeof(gus_info.name) - 1] = 0;
+ strcpy(gus_info.name, tmp2);
+
+ if ((sdev = sound_alloc_synthdev()) == -1)
+ printk(KERN_WARNING "gus_init: Too many synthesizers\n");
+ else
+ {
+ voice_alloc = &guswave_operations.alloc;
+ if (iw_mode)
+ guswave_operations.id = "IWAVE";
+ hw_config->slots[0] = sdev;
+ synth_devs[sdev] = &guswave_operations;
+ sequencer_init();
+#if defined(CONFIG_SEQUENCER) || defined(MODULE)
+ gus_tmr_install(gus_base + 8);
#endif
- }
+ }
+
+ reset_sample_memory();
+
+ gus_initialize();
+
+ if (gus_mem_size > 0)
+ if ((dev = sound_alloc_audiodev()) != -1)
+ {
+ hw_config->slots[4] = dev;
+ if ((gus_devnum = sound_install_audiodrv(AUDIO_DRIVER_VERSION,
+ "Ultrasound",
+ &gus_audio_driver,
+ sizeof(struct audio_driver),
+ NEEDS_RESTART |
+ ((!iw_mode && dma2 != dma && dma2 != -1) ?
+ DMA_DUPLEX : 0),
+ AFMT_U8 | AFMT_S16_LE,
+ NULL,
+ dma,
+ dma2)) < 0)
+ return;
+
+ audio_devs[gus_devnum]->min_fragment = 9; /* 512k */
+ audio_devs[gus_devnum]->max_fragment = 11; /* 8k (must match size of bounce_buf */
+ audio_devs[gus_devnum]->mixer_dev = -1; /* Next mixer# */
+ audio_devs[gus_devnum]->flags |= DMA_HARDSTOP;
+ } else
+ printk("GUS: Too many audio devices available\n");
- reset_sample_memory ();
+ /*
+ * Mixer dependent initialization.
+ */
- gus_initialize ();
+ switch (mixer_type)
+ {
+ case ICS2101:
+ gus_mic_vol = gus_line_vol = gus_pcm_volume = 100;
+ gus_wave_volume = 90;
+ request_region(u_MixSelect, 1, "GUS mixer");
+ hw_config->slots[5] = ics2101_mixer_init();
+ audio_devs[gus_devnum]->mixer_dev = hw_config->slots[5]; /* Next mixer# */
+ return;
- if (gus_mem_size > 0)
- if (num_audiodevs < MAX_AUDIO_DEV)
- {
-
- if ((gus_devnum = sound_install_audiodrv (AUDIO_DRIVER_VERSION,
- "Ultrasound",
- &gus_audio_driver,
- sizeof (struct audio_driver),
- NEEDS_RESTART |
- ((!iw_mode && dma2 != dma && dma2 != -1) ?
- DMA_DUPLEX : 0),
- AFMT_U8 | AFMT_S16_LE,
- NULL,
- dma,
- dma2)) < 0)
- return;
-
- audio_devs[gus_devnum]->min_fragment = 9; /* 512k */
- audio_devs[gus_devnum]->max_fragment = 11; /* 8k (must match size of bounce_buf */
- audio_devs[gus_devnum]->mixer_dev = num_mixers; /* Next mixer# */
- audio_devs[gus_devnum]->flags |= DMA_HARDSTOP;
- }
- else
- printk ("GUS: Too many audio devices available\n");
-
- /*
- * Mixer dependent initialization.
- */
-
- switch (mixer_type)
- {
- case ICS2101:
- gus_mic_vol = gus_line_vol = gus_pcm_volume = 100;
- gus_wave_volume = 90;
- request_region (u_MixSelect, 1, "GUS mixer");
- ics2101_mixer_init ();
- return;
-
- case CS4231:
- /* Initialized elsewhere (ad1848.c) */
- default:
- gus_default_mixer_init ();
- return;
- }
+ case CS4231:
+ /* Initialized elsewhere (ad1848.c) */
+ default:
+ hw_config->slots[5] = gus_default_mixer_init();
+ audio_devs[gus_devnum]->mixer_dev = hw_config->slots[5]; /* Next mixer# */
+ return;
+ }
}
void
-gus_wave_unload (void)
+gus_wave_unload(struct address_info *hw_config)
{
#ifdef CONFIG_GUSMAX
- if (have_gus_max)
- {
- ad1848_unload (gus_base + 0x10c,
- -gus_irq,
- gus_dma2, /* Playback DMA */
- gus_dma, /* Capture DMA */
- 1); /* Share DMA channels with GF1 */
- }
+ if (have_gus_max)
+ {
+ ad1848_unload(gus_base + 0x10c,
+ -gus_irq,
+ gus_dma2, /* Playback DMA */
+ gus_dma, /* Capture DMA */
+ 1); /* Share DMA channels with GF1 */
+ }
#endif
- if (mixer_type == ICS2101)
- {
- release_region (u_MixSelect, 1);
- }
+ if (mixer_type == ICS2101)
+ {
+ release_region(u_MixSelect, 1);
+ }
+ if (hw_config->slots[0] != -1)
+ sound_unload_synthdev(hw_config->slots[0]);
+ if (hw_config->slots[1] != -1)
+ sound_unload_audiodev(hw_config->slots[1]);
+ if (hw_config->slots[2] != -1)
+ sound_unload_mididev(hw_config->slots[2]);
+ if (hw_config->slots[4] != -1)
+ sound_unload_audiodev(hw_config->slots[4]);
+ if (hw_config->slots[5] != -1)
+ sound_unload_mixerdev(hw_config->slots[4]);
}
static void
-do_loop_irq (int voice)
-{
- unsigned char tmp;
- int mode, parm;
- unsigned long flags;
-
- save_flags (flags);
- cli ();
- gus_select_voice (voice);
+do_loop_irq(int voice)
+{
+ unsigned char tmp;
+ int mode, parm;
+ unsigned long flags;
+
+ save_flags(flags);
+ cli();
+ gus_select_voice(voice);
- tmp = gus_read8 (0x00);
- tmp &= ~0x20; /*
+ tmp = gus_read8(0x00);
+ tmp &= ~0x20; /*
* Disable wave IRQ for this_one voice
*/
- gus_write8 (0x00, tmp);
+ gus_write8(0x00, tmp);
- if (tmp & 0x03) /* Voice stopped */
- voice_alloc->map[voice] = 0;
+ if (tmp & 0x03) /* Voice stopped */
+ voice_alloc->map[voice] = 0;
- mode = voices[voice].loop_irq_mode;
- voices[voice].loop_irq_mode = 0;
- parm = voices[voice].loop_irq_parm;
+ mode = voices[voice].loop_irq_mode;
+ voices[voice].loop_irq_mode = 0;
+ parm = voices[voice].loop_irq_parm;
- switch (mode)
- {
+ switch (mode)
+ {
- case LMODE_FINISH: /*
+ case LMODE_FINISH: /*
* Final loop finished, shoot volume down
*/
- if ((int) (gus_read16 (0x09) >> 4) < 100) /*
- * Get current volume
- */
- {
- gus_voice_off ();
- gus_rampoff ();
- gus_voice_init (voice);
- break;
- }
- gus_ramp_range (65, 4065);
- gus_ramp_rate (0, 63); /*
- * Fastest possible rate
- */
- gus_rampon (0x20 | 0x40); /*
- * Ramp down, once, irq
- */
- voices[voice].volume_irq_mode = VMODE_HALT;
- break;
+ if ((int) (gus_read16(0x09) >> 4) < 100) /*
+ * Get current volume
+ */
+ {
+ gus_voice_off();
+ gus_rampoff();
+ gus_voice_init(voice);
+ break;
+ }
+ gus_ramp_range(65, 4065);
+ gus_ramp_rate(0, 63); /*
+ * Fastest possible rate
+ */
+ gus_rampon(0x20 | 0x40); /*
+ * Ramp down, once, irq
+ */
+ voices[voice].volume_irq_mode = VMODE_HALT;
+ break;
+
+ case LMODE_PCM_STOP:
+ pcm_active = 0; /* Signal to the play_next_pcm_block routine */
+ case LMODE_PCM:
+ {
+
+ pcm_qlen--;
+ pcm_head = (pcm_head + 1) % pcm_nblk;
+ if (pcm_qlen && pcm_active)
+ {
+ play_next_pcm_block();
+ } else
+ { /* Underrun. Just stop the voice */
+ gus_select_voice(0); /* Left channel */
+ gus_voice_off();
+ gus_rampoff();
+ gus_select_voice(1); /* Right channel */
+ gus_voice_off();
+ gus_rampoff();
+ pcm_active = 0;
+ }
+
+ /*
+ * If the queue was full before this interrupt, the DMA transfer was
+ * suspended. Let it continue now.
+ */
+ if (audio_devs[gus_devnum]->dmap_out->qlen > 0)
+ DMAbuf_outputintr(gus_devnum, 0);
+ }
+ break;
- case LMODE_PCM_STOP:
- pcm_active = 0; /* Signal to the play_next_pcm_block routine */
- case LMODE_PCM:
- {
-
- pcm_qlen--;
- pcm_head = (pcm_head + 1) % pcm_nblk;
- if (pcm_qlen && pcm_active)
- {
- play_next_pcm_block ();
- }
- else
- { /* Underrun. Just stop the voice */
- gus_select_voice (0); /* Left channel */
- gus_voice_off ();
- gus_rampoff ();
- gus_select_voice (1); /* Right channel */
- gus_voice_off ();
- gus_rampoff ();
- pcm_active = 0;
+ default:;
}
-
- /*
- * If the queue was full before this interrupt, the DMA transfer was
- * suspended. Let it continue now.
- */
- if (audio_devs[gus_devnum]->dmap_out->qlen > 0)
- DMAbuf_outputintr (gus_devnum, 0);
- }
- break;
-
- default:;
- }
- restore_flags (flags);
+ restore_flags(flags);
}
static void
-do_volume_irq (int voice)
+do_volume_irq(int voice)
{
- unsigned char tmp;
- int mode, parm;
- unsigned long flags;
+ unsigned char tmp;
+ int mode, parm;
+ unsigned long flags;
- save_flags (flags);
- cli ();
+ save_flags(flags);
+ cli();
- gus_select_voice (voice);
+ gus_select_voice(voice);
- tmp = gus_read8 (0x0d);
- tmp &= ~0x20; /*
+ tmp = gus_read8(0x0d);
+ tmp &= ~0x20; /*
* Disable volume ramp IRQ
*/
- gus_write8 (0x0d, tmp);
+ gus_write8(0x0d, tmp);
- mode = voices[voice].volume_irq_mode;
- voices[voice].volume_irq_mode = 0;
- parm = voices[voice].volume_irq_parm;
-
- switch (mode)
- {
- case VMODE_HALT: /* Decay phase finished */
- if (iw_mode)
- gus_write8 (0x15, 0x02); /* Set voice deactivate bit of SMSI */
- restore_flags (flags);
- gus_voice_init (voice);
- break;
-
- case VMODE_ENVELOPE:
- gus_rampoff ();
- restore_flags (flags);
- step_envelope (voice);
- break;
-
- case VMODE_START_NOTE:
- restore_flags (flags);
- guswave_start_note2 (voices[voice].dev_pending, voice,
- voices[voice].note_pending, voices[voice].volume_pending);
- if (voices[voice].kill_pending)
- guswave_kill_note (voices[voice].dev_pending, voice,
- voices[voice].note_pending, 0);
-
- if (voices[voice].sample_pending >= 0)
- {
- guswave_set_instr (voices[voice].dev_pending, voice,
- voices[voice].sample_pending);
- voices[voice].sample_pending = -1;
- }
- break;
-
- default:;
- }
- restore_flags (flags);
+ mode = voices[voice].volume_irq_mode;
+ voices[voice].volume_irq_mode = 0;
+ parm = voices[voice].volume_irq_parm;
+
+ switch (mode)
+ {
+ case VMODE_HALT: /* Decay phase finished */
+ if (iw_mode)
+ gus_write8(0x15, 0x02); /* Set voice deactivate bit of SMSI */
+ restore_flags(flags);
+ gus_voice_init(voice);
+ break;
+
+ case VMODE_ENVELOPE:
+ gus_rampoff();
+ restore_flags(flags);
+ step_envelope(voice);
+ break;
+
+ case VMODE_START_NOTE:
+ restore_flags(flags);
+ guswave_start_note2(voices[voice].dev_pending, voice,
+ voices[voice].note_pending, voices[voice].volume_pending);
+ if (voices[voice].kill_pending)
+ guswave_kill_note(voices[voice].dev_pending, voice,
+ voices[voice].note_pending, 0);
+
+ if (voices[voice].sample_pending >= 0)
+ {
+ guswave_set_instr(voices[voice].dev_pending, voice,
+ voices[voice].sample_pending);
+ voices[voice].sample_pending = -1;
+ }
+ break;
+
+ default:
+ restore_flags(flags);
+ }
+ restore_flags(flags);
}
void
-gus_voice_irq (void)
+gus_voice_irq(void)
{
- unsigned long wave_ignore = 0, volume_ignore = 0;
- unsigned long voice_bit;
-
- unsigned char src, voice;
+ unsigned long wave_ignore = 0, volume_ignore = 0;
+ unsigned long voice_bit;
- while (1)
- {
- src = gus_read8 (0x0f); /*
- * Get source info
- */
- voice = src & 0x1f;
- src &= 0xc0;
+ unsigned char src, voice;
- if (src == (0x80 | 0x40))
- return; /*
- * No interrupt
- */
-
- voice_bit = 1 << voice;
-
- if (!(src & 0x80)) /*
- * Wave IRQ pending
- */
- if (!(wave_ignore & voice_bit) && (int) voice < nr_voices) /*
- * Not done
- * yet
- */
+ while (1)
{
- wave_ignore |= voice_bit;
- do_loop_irq (voice);
- }
+ src = gus_read8(0x0f); /*
+ * Get source info
+ */
+ voice = src & 0x1f;
+ src &= 0xc0;
+
+ if (src == (0x80 | 0x40))
+ return; /*
+ * No interrupt
+ */
- if (!(src & 0x40)) /*
- * Volume IRQ pending
- */
- if (!(volume_ignore & voice_bit) && (int) voice < nr_voices) /*
- * Not done
- * yet
- */
- {
- volume_ignore |= voice_bit;
- do_volume_irq (voice);
+ voice_bit = 1 << voice;
+
+ if (!(src & 0x80)) /*
+ * Wave IRQ pending
+ */
+ if (!(wave_ignore & voice_bit) && (int) voice < nr_voices) /*
+ * Not done
+ * yet
+ */
+ {
+ wave_ignore |= voice_bit;
+ do_loop_irq(voice);
+ }
+ if (!(src & 0x40)) /*
+ * Volume IRQ pending
+ */
+ if (!(volume_ignore & voice_bit) && (int) voice < nr_voices) /*
+ * Not done
+ * yet
+ */
+ {
+ volume_ignore |= voice_bit;
+ do_volume_irq(voice);
+ }
}
- }
}
void
-guswave_dma_irq (void)
+guswave_dma_irq(void)
{
- unsigned char status;
-
- status = gus_look8 (0x41); /* Get DMA IRQ Status */
- if (status & 0x40) /* DMA interrupt pending */
- switch (active_device)
- {
- case GUS_DEV_WAVE:
- if ((dram_sleep_flag.opts & WK_SLEEP))
- {
- dram_sleep_flag.opts = WK_WAKEUP;
- wake_up (&dram_sleeper);
- };
- break;
-
- case GUS_DEV_PCM_CONTINUE: /* Left channel data transferred */
- gus_write8 (0x41, 0); /* Disable GF1 DMA */
- gus_transfer_output_block (pcm_current_dev, pcm_current_buf,
- pcm_current_count,
- pcm_current_intrflag, 1);
- break;
-
- case GUS_DEV_PCM_DONE: /* Right or mono channel data transferred */
- gus_write8 (0x41, 0); /* Disable GF1 DMA */
- if (pcm_qlen < pcm_nblk)
- {
- dma_active = 0;
- if (gus_busy)
- {
- if (audio_devs[gus_devnum]->dmap_out->qlen > 0)
- DMAbuf_outputintr (gus_devnum, 0);
- }
- }
- break;
-
- default:;
- }
+ unsigned char status;
- status = gus_look8 (0x49); /*
- * Get Sampling IRQ Status
- */
- if (status & 0x40) /*
+ status = gus_look8(0x41); /* Get DMA IRQ Status */
+ if (status & 0x40) /* DMA interrupt pending */
+ switch (active_device)
+ {
+ case GUS_DEV_WAVE:
+ if ((dram_sleep_flag.opts & WK_SLEEP))
+ {
+ dram_sleep_flag.opts = WK_WAKEUP;
+ wake_up(&dram_sleeper);
+ };
+ break;
+
+ case GUS_DEV_PCM_CONTINUE: /* Left channel data transferred */
+ gus_write8(0x41, 0); /* Disable GF1 DMA */
+ gus_transfer_output_block(pcm_current_dev, pcm_current_buf,
+ pcm_current_count,
+ pcm_current_intrflag, 1);
+ break;
+
+ case GUS_DEV_PCM_DONE: /* Right or mono channel data transferred */
+ gus_write8(0x41, 0); /* Disable GF1 DMA */
+ if (pcm_qlen < pcm_nblk)
+ {
+ dma_active = 0;
+ if (gus_busy)
+ {
+ if (audio_devs[gus_devnum]->dmap_out->qlen > 0)
+ DMAbuf_outputintr(gus_devnum, 0);
+ }
+ }
+ break;
+
+ default:;
+ }
+ status = gus_look8(0x49); /*
+ * Get Sampling IRQ Status
+ */
+ if (status & 0x40) /*
* Sampling Irq pending
*/
- {
- DMAbuf_inputintr (gus_devnum);
- }
-
+ {
+ DMAbuf_inputintr(gus_devnum);
+ }
}
-#ifdef CONFIG_SEQUENCER
+#if defined(CONFIG_SEQUENCER) || defined(MODULE)
+
/*
* Timer stuff
*/
@@ -3583,105 +3527,103 @@
static volatile int curr_timer = 0;
void
-gus_timer_command (unsigned int addr, unsigned int val)
+gus_timer_command(unsigned int addr, unsigned int val)
{
- int i;
+ int i;
- outb (((unsigned char) (addr & 0xff)), select_addr);
+ outb(((unsigned char) (addr & 0xff)), select_addr);
- for (i = 0; i < 2; i++)
- inb (select_addr);
+ for (i = 0; i < 2; i++)
+ inb(select_addr);
- outb (((unsigned char) (val & 0xff)), data_addr);
+ outb(((unsigned char) (val & 0xff)), data_addr);
- for (i = 0; i < 2; i++)
- inb (select_addr);
+ for (i = 0; i < 2; i++)
+ inb(select_addr);
}
static void
-arm_timer (int timer, unsigned int interval)
+arm_timer(int timer, unsigned int interval)
{
- curr_timer = timer;
+ curr_timer = timer;
- if (timer == 1)
- {
- gus_write8 (0x46, 256 - interval); /* Set counter for timer 1 */
- gus_write8 (0x45, 0x04); /* Enable timer 1 IRQ */
- gus_timer_command (0x04, 0x01); /* Start timer 1 */
- }
- else
- {
- gus_write8 (0x47, 256 - interval); /* Set counter for timer 2 */
- gus_write8 (0x45, 0x08); /* Enable timer 2 IRQ */
- gus_timer_command (0x04, 0x02); /* Start timer 2 */
- }
+ if (timer == 1)
+ {
+ gus_write8(0x46, 256 - interval); /* Set counter for timer 1 */
+ gus_write8(0x45, 0x04); /* Enable timer 1 IRQ */
+ gus_timer_command(0x04, 0x01); /* Start timer 1 */
+ } else
+ {
+ gus_write8(0x47, 256 - interval); /* Set counter for timer 2 */
+ gus_write8(0x45, 0x08); /* Enable timer 2 IRQ */
+ gus_timer_command(0x04, 0x02); /* Start timer 2 */
+ }
- gus_timer_enabled = 1;
+ gus_timer_enabled = 1;
}
static unsigned int
-gus_tmr_start (int dev, unsigned int usecs_per_tick)
+gus_tmr_start(int dev, unsigned int usecs_per_tick)
{
- int timer_no, resolution;
- int divisor;
+ int timer_no, resolution;
+ int divisor;
- if (usecs_per_tick > (256 * 80))
- {
- timer_no = 2;
- resolution = 320; /* usec */
- }
- else
- {
- timer_no = 1;
- resolution = 80; /* usec */
- }
+ if (usecs_per_tick > (256 * 80))
+ {
+ timer_no = 2;
+ resolution = 320; /* usec */
+ } else
+ {
+ timer_no = 1;
+ resolution = 80; /* usec */
+ }
- divisor = (usecs_per_tick + (resolution / 2)) / resolution;
+ divisor = (usecs_per_tick + (resolution / 2)) / resolution;
- arm_timer (timer_no, divisor);
+ arm_timer(timer_no, divisor);
- return divisor * resolution;
+ return divisor * resolution;
}
static void
-gus_tmr_disable (int dev)
+gus_tmr_disable(int dev)
{
- gus_write8 (0x45, 0); /* Disable both timers */
- gus_timer_enabled = 0;
+ gus_write8(0x45, 0); /* Disable both timers */
+ gus_timer_enabled = 0;
}
static void
-gus_tmr_restart (int dev)
+gus_tmr_restart(int dev)
{
- if (curr_timer == 1)
- gus_write8 (0x45, 0x04); /* Start timer 1 again */
- else
- gus_write8 (0x45, 0x08); /* Start timer 2 again */
- gus_timer_enabled = 1;
+ if (curr_timer == 1)
+ gus_write8(0x45, 0x04); /* Start timer 1 again */
+ else
+ gus_write8(0x45, 0x08); /* Start timer 2 again */
+ gus_timer_enabled = 1;
}
static struct sound_lowlev_timer gus_tmr =
{
- 0,
- 1,
- gus_tmr_start,
- gus_tmr_disable,
- gus_tmr_restart
+ 0,
+ 1,
+ gus_tmr_start,
+ gus_tmr_disable,
+ gus_tmr_restart
};
static void
-gus_tmr_install (int io_base)
+gus_tmr_install(int io_base)
{
- struct sound_lowlev_timer *tmr;
+ struct sound_lowlev_timer *tmr;
- select_addr = io_base;
- data_addr = io_base + 1;
+ select_addr = io_base;
+ data_addr = io_base + 1;
- tmr = &gus_tmr;
+ tmr = &gus_tmr;
#ifdef THIS_GETS_FIXED
- sound_timer_init (&gus_tmr, "GUS");
+ sound_timer_init(&gus_tmr, "GUS");
#endif
}
#endif
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov