patch-2.1.6 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: 1114
- Date:
Tue Oct 29 09:31:37 1996
- Orig file:
v2.1.5/linux/drivers/sound/gus_wave.c
- Orig date:
Wed Oct 16 10:48:23 1996
diff -u --recursive --new-file v2.1.5/linux/drivers/sound/gus_wave.c linux/drivers/sound/gus_wave.c
@@ -6,7 +6,7 @@
/*
* Copyright (C) by Hannu Savolainen 1993-1996
*
- * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
* Version 2 (June 1991). See the "COPYING" file distributed with this software
* for more info.
*/
@@ -19,7 +19,9 @@
#include <linux/ultrasound.h>
#include "gus_hw.h"
-#if defined(CONFIG_GUS)
+#if defined(CONFIG_GUSHW)
+
+#define GUS_BANK_SIZE (256*1024)
#define MAX_SAMPLE 150
#define MAX_PATCH 256
@@ -103,7 +105,7 @@
static int gus_audio_channels;
static int gus_audio_bits;
-static wait_handle *dram_sleeper = NULL;
+static struct wait_queue *dram_sleeper = NULL;
static volatile struct snd_wait dram_sleep_flag =
{0};
@@ -130,6 +132,7 @@
static int freq_div_table[] =
{
+ 44100,
44100, /* 14 */
41160, /* 15 */
38587, /* 16 */
@@ -214,13 +217,13 @@
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);
+ 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);
}
@@ -232,12 +235,12 @@
save_flags (flags);
cli ();
- outb (0x43, u_Command);
- outb (addr & 0xff, u_DataLo);
- outb ((addr >> 8) & 0xff, u_DataHi);
+ 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 ((0x44), u_Command);
+ outb (((addr >> 16) & 0xff), u_DataHi);
tmp = inb (u_DRAMIO);
restore_flags (flags);
@@ -252,8 +255,8 @@
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);
}
@@ -266,7 +269,7 @@
save_flags (flags);
cli ();
- outb (reg | 0x80, u_Command);
+ outb ((reg | 0x80), u_Command);
val = inb (u_DataHi);
restore_flags (flags);
@@ -281,7 +284,7 @@
save_flags (flags);
cli ();
- outb (reg, u_Command);
+ outb ((reg), u_Command);
val = inb (u_DataHi);
restore_flags (flags);
@@ -296,10 +299,10 @@
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);
}
@@ -313,7 +316,7 @@
save_flags (flags);
cli ();
- outb (reg | 0x80, u_Command);
+ outb ((reg | 0x80), u_Command);
lo = inb (u_DataLo);
hi = inb (u_DataHi);
@@ -332,7 +335,7 @@
save_flags (flags);
cli ();
- outb (reg, u_Command);
+ outb ((reg), u_Command);
lo = inb (u_DataLo);
hi = inb (u_DataHi);
@@ -379,7 +382,7 @@
if (voice < 0 || voice > 31)
return;
- outb (voice, u_Voice);
+ outb ((voice), u_Voice);
}
static void
@@ -746,14 +749,14 @@
* Set up for Digital ASIC
*/
- outb (0x05, gus_base + 0x0f);
+ outb ((0x05), gus_base + 0x0f);
mix_image |= 0x02; /* Disable line out (for a moment) */
- outb (mix_image, u_Mixer);
+ outb ((mix_image), u_Mixer);
- outb (0x00, u_IRQDMAControl);
+ outb ((0x00), u_IRQDMAControl);
- outb (0x00, gus_base + 0x0f);
+ outb ((0x00), gus_base + 0x0f);
/*
* Now set up the DMA and IRQ interface
@@ -810,27 +813,27 @@
* 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
*/
- 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 */
mix_image &= ~0x02; /* Enable line out */
mix_image |= 0x08; /* Enable IRQ */
- outb (mix_image, u_Mixer); /*
+ outb ((mix_image), u_Mixer); /*
* Turn mixer channels on
* Note! Mic in is left off.
*/
@@ -849,6 +852,7 @@
restore_flags (flags);
}
+
static void
pnp_mem_init (void)
{
@@ -928,6 +932,7 @@
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;
}
/*
@@ -1026,6 +1031,7 @@
{
unsigned long i, max_mem = 1024L;
unsigned long loc;
+ unsigned char val;
gus_base = baseaddr;
@@ -1037,6 +1043,24 @@
gus_delay ();
gus_delay ();
+#ifdef GUSPNP_AUTODETECT
+ 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 */
+#endif
+
if (gus_pnp_flag)
pnp_mem_init ();
@@ -1083,7 +1107,11 @@
{
case SNDCTL_SYNTH_INFO:
gus_info.nr_voices = nr_voices;
- copy_to_user (&((char *) arg)[0], &gus_info, sizeof (gus_info));
+ {
+ char *fixit = (char *) &gus_info;
+
+ copy_to_user (&((char *) arg)[0], fixit, sizeof (gus_info));
+ };
return 0;
break;
@@ -1097,10 +1125,10 @@
break;
case SNDCTL_SYNTH_MEMAVL:
- return gus_mem_size - free_mem_ptr - 32;
+ return (gus_mem_size == 0) ? 0 : gus_mem_size - free_mem_ptr - 32;
default:
- return -(EINVAL);
+ return -EINVAL;
}
}
@@ -1110,10 +1138,10 @@
int sample_no;
if (instr_no < 0 || instr_no > MAX_PATCH)
- return -(EINVAL);
+ instr_no = 0; /* Default to acoustic piano */
if (voice < 0 || voice > 31)
- return -(EINVAL);
+ return -EINVAL;
if (voices[voice].volume_irq_mode == VMODE_START_NOTE)
{
@@ -1127,14 +1155,14 @@
if (sample_no == NOT_SAMPLE)
{
printk ("GUS: Undefined patch %d for voice %d\n", instr_no, voice);
- return -(EINVAL); /* Patch not defined */
+ 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);
+ return -EINVAL;
}
sample_map[voice] = sample_no;
@@ -1388,7 +1416,7 @@
if (voice < 0 || voice > 31)
{
printk ("GUS: Invalid voice\n");
- return -(EINVAL);
+ return -EINVAL;
}
if (note_num == 255)
@@ -1406,12 +1434,12 @@
if ((patch = patch_map[voice]) == -1)
{
- return -(EINVAL);
+ return -EINVAL;
}
if ((samplep = patch_table[patch]) == NOT_SAMPLE)
{
- return -(EINVAL);
+ return -EINVAL;
}
note_freq = note_to_freq (note_num);
@@ -1492,8 +1520,8 @@
if (samples[sample].mode & WAVE_16_BITS)
{
mode |= 0x04; /* 16 bits */
- if ((sample_ptrs[sample] >> 18) !=
- ((sample_ptrs[sample] + samples[sample].len) >> 18))
+ if ((sample_ptrs[sample] / GUS_BANK_SIZE) !=
+ ((sample_ptrs[sample] + samples[sample].len) / GUS_BANK_SIZE))
printk ("GUS: Sample address error\n");
}
@@ -1660,7 +1688,7 @@
int err;
if (gus_busy)
- return -(EBUSY);
+ return -EBUSY;
voice_alloc->timestamp = 0;
@@ -1672,7 +1700,7 @@
else
gus_no_dma = 0;
- dram_sleep_flag.flags = WK_NONE;
+ dram_sleep_flag.opts = WK_NONE;
gus_busy = 1;
active_device = GUS_DEV_WAVE;
@@ -1710,21 +1738,24 @@
if (format != GUS_PATCH)
{
printk ("GUS Error: Invalid patch format (key) 0x%x\n", format);
- return -(EINVAL);
+ return -EINVAL;
}
if (count < sizeof_patch)
{
printk ("GUS Error: Patch header too short\n");
- return -(EINVAL);
+ return -EINVAL;
}
count -= sizeof_patch;
+ if (gus_mem_size == 0)
+ return -ENOSPC;
+
if (free_sample >= MAX_SAMPLE)
{
printk ("GUS: Sample table full\n");
- return -(ENOSPC);
+ return -ENOSPC;
}
/*
@@ -1739,7 +1770,7 @@
if (instr < 0 || instr > MAX_PATCH)
{
printk ("GUS: Invalid patch number %d\n", instr);
- return -(EINVAL);
+ return -EINVAL;
}
if (count < patch.len)
@@ -1752,7 +1783,7 @@
if (patch.len <= 0 || patch.len > gus_mem_size)
{
printk ("GUS: Invalid sample length %d\n", (int) patch.len);
- return -(EINVAL);
+ return -EINVAL;
}
if (patch.mode & WAVE_LOOPING)
@@ -1760,20 +1791,18 @@
if (patch.loop_start < 0 || patch.loop_start >= patch.len)
{
printk ("GUS: Invalid loop start\n");
- return -(EINVAL);
+ return -EINVAL;
}
if (patch.loop_end < patch.loop_start || patch.loop_end > patch.len)
{
printk ("GUS: Invalid loop end\n");
- return -(EINVAL);
+ return -EINVAL;
}
}
free_mem_ptr = (free_mem_ptr + 31) & ~31; /* 32 byte alignment */
-#define GUS_BANK_SIZE (256*1024)
-
if (patch.mode & WAVE_16_BITS)
{
/*
@@ -1782,7 +1811,7 @@
if (patch.len >= GUS_BANK_SIZE)
{
printk ("GUS: Sample (16 bit) too long %d\n", (int) patch.len);
- return -(ENOSPC);
+ return -ENOSPC;
}
if ((free_mem_ptr / GUS_BANK_SIZE) !=
@@ -1792,14 +1821,14 @@
((free_mem_ptr / GUS_BANK_SIZE) + 1) * GUS_BANK_SIZE;
if ((tmp_mem + patch.len) > gus_mem_size)
- return -(ENOSPC);
+ return -ENOSPC;
free_mem_ptr = tmp_mem; /* This leaves unusable memory */
}
}
if ((free_mem_ptr + patch.len) > gus_mem_size)
- return -(ENOSPC);
+ return -ENOSPC;
sample_ptrs[free_sample] = free_mem_ptr;
@@ -1839,14 +1868,14 @@
blk_sz = left;
/*
- * DMA cannot cross 256k bank boundaries. Check for that.
+ * DMA cannot cross bank (256k) boundaries. Check for that.
*/
blk_end = target + blk_sz;
- if ((target >> 18) != (blk_end >> 18))
+ if ((target / GUS_BANK_SIZE) != (blk_end / GUS_BANK_SIZE))
{ /* Split the block */
- blk_end &= ~(256 * 1024 - 1);
+ blk_end &= ~(GUS_BANK_SIZE - 1);
blk_sz = blk_end - target;
}
@@ -1858,10 +1887,9 @@
long i;
unsigned char data;
-
for (i = 0; i < blk_sz; i++)
{
- data = get_fs_byte (&((addr)[sizeof_patch + i]));
+ get_user (data, (unsigned char *) &((addr)[sizeof_patch + i]));
if (patch.mode & WAVE_UNSIGNED)
if (!(patch.mode & WAVE_16_BITS) || (i & 0x01))
@@ -1878,7 +1906,7 @@
if (audio_devs[gus_devnum]->dmap_out->raw_buf == NULL)
{
printk ("GUS: DMA buffer == NULL\n");
- return -(EINVAL);
+ return -ENOSPC;
}
/*
@@ -1923,7 +1951,7 @@
if (audio_devs[gus_devnum]->dmachan1 > 3)
dma_command |= 0x04; /* 16 bit DMA _channel_ */
- gus_write8 (0x41, dma_command); /* Lets bo luteet (=bugs) */
+ gus_write8 (0x41, dma_command); /* Lets go luteet (=bugs) */
/*
* Sleep here until the DRAM DMA done interrupt is served
@@ -1935,19 +1963,19 @@
unsigned long tlimit;
if (HZ)
- current_set_timeout (tlimit = jiffies + (HZ));
+ current->timeout = tlimit = jiffies + (HZ);
else
tlimit = (unsigned long) -1;
- dram_sleep_flag.flags = WK_SLEEP;
- module_interruptible_sleep_on (&dram_sleeper);
- if (!(dram_sleep_flag.flags & WK_WAKEUP))
+ dram_sleep_flag.opts = WK_SLEEP;
+ interruptible_sleep_on (&dram_sleeper);
+ if (!(dram_sleep_flag.opts & WK_WAKEUP))
{
if (jiffies >= tlimit)
- dram_sleep_flag.flags |= WK_TIMEOUT;
+ dram_sleep_flag.opts |= WK_TIMEOUT;
}
- dram_sleep_flag.flags &= ~WK_SLEEP;
+ dram_sleep_flag.opts &= ~WK_SLEEP;
};
- if ((dram_sleep_flag.flags & WK_TIMEOUT))
+ if ((dram_sleep_flag.opts & WK_TIMEOUT))
printk ("GUS: DMA Transfer timed out\n");
restore_flags (flags);
}
@@ -2190,59 +2218,99 @@
static int
gus_audio_ioctl (int dev, unsigned int cmd, caddr_t arg, int local)
{
+ int val;
+
switch (cmd)
{
case SOUND_PCM_WRITE_RATE:
if (local)
return gus_audio_set_speed ((int) arg);
- return snd_ioctl_return ((int *) arg, gus_audio_set_speed (get_user ((int *) arg)));
+ get_user (val, (int *) arg);
+ return ioctl_out (arg, gus_audio_set_speed (val));
break;
case SOUND_PCM_READ_RATE:
if (local)
return gus_audio_speed;
- return snd_ioctl_return ((int *) arg, gus_audio_speed);
+ return ioctl_out (arg, gus_audio_speed);
break;
case SNDCTL_DSP_STEREO:
if (local)
return gus_audio_set_channels ((int) arg + 1) - 1;
- return snd_ioctl_return ((int *) arg, gus_audio_set_channels (get_user ((int *) arg) + 1) - 1);
+ get_user (val, (int *) arg);
+ return ioctl_out (arg, gus_audio_set_channels (val + 1) - 1);
break;
case SOUND_PCM_WRITE_CHANNELS:
if (local)
return gus_audio_set_channels ((int) arg);
- return snd_ioctl_return ((int *) arg, gus_audio_set_channels (get_user ((int *) arg)));
+ get_user (val, (int *) arg);
+ return ioctl_out (arg, gus_audio_set_channels (val));
break;
case SOUND_PCM_READ_CHANNELS:
if (local)
return gus_audio_channels;
- return snd_ioctl_return ((int *) arg, gus_audio_channels);
+ return ioctl_out (arg, gus_audio_channels);
break;
case SNDCTL_DSP_SETFMT:
if (local)
return gus_audio_set_bits ((int) arg);
- return snd_ioctl_return ((int *) arg, gus_audio_set_bits (get_user ((int *) arg)));
+ get_user (val, (int *) arg);
+ return ioctl_out (arg, gus_audio_set_bits (val));
break;
case SOUND_PCM_READ_BITS:
if (local)
return gus_audio_bits;
- return snd_ioctl_return ((int *) arg, gus_audio_bits);
+ return ioctl_out (arg, gus_audio_bits);
case SOUND_PCM_WRITE_FILTER: /* NOT POSSIBLE */
- return snd_ioctl_return ((int *) arg, -(EINVAL));
+ return ioctl_out (arg, -EINVAL);
break;
case SOUND_PCM_READ_FILTER:
- return snd_ioctl_return ((int *) arg, -(EINVAL));
+ return ioctl_out (arg, -EINVAL);
+ break;
+
+/* This is just a temporary hack used for reading the ROM patch set. */
+
+ case SNDCTL_PMGR_ACCESS:
+ {
+ copr_msg *buf;
+ int i, pos;
+
+ buf = (copr_msg *) vmalloc (sizeof (copr_msg));
+ if (buf == NULL)
+ return -ENOSPC;
+
+ copy_from_user ((char *) buf, &((char *) arg)[0], sizeof (*buf));
+
+ pos = buf->len;
+
+ gus_write8 (0x53, gus_look8 (0x53) | 0x02); /* Select ROM I/O access */
+
+ for (i = 0; i < 2048; i++)
+ {
+ buf->data[i] = gus_peek (pos + i);
+ }
+ gus_write8 (0x53, gus_look8 (0x53) & ~0x02); /* Select DRAM I/O access */
+ buf->len = 2048; /* feed back number of WORDs sent */
+ {
+ char *fixit = (char *) buf;
+
+ copy_to_user (&((char *) arg)[0], fixit, sizeof (*buf));
+ };
+ vfree (buf);
+
+ return 0;
+ }
break;
}
- return -(EINVAL);
+ return -EINVAL;
}
static void
@@ -2255,16 +2323,17 @@
}
}
+
static int
gus_audio_open (int dev, int mode)
{
if (gus_busy)
- return -(EBUSY);
+ return -EBUSY;
if (gus_pnp_flag && mode & OPEN_READ)
{
printk ("Sound: This audio device doesn't have recording capability\n");
- return -(EIO);
+ return -EIO;
}
gus_initialize ();
@@ -2588,7 +2657,7 @@
if (gus_audio_bits != 8)
{
printk ("GUS Error: 16 bit recording not supported\n");
- return -(EINVAL);
+ return -EINVAL;
}
return 0;
@@ -2653,9 +2722,9 @@
for (i = 0; i < len; i++)
{
- *out_left++ = get_fs_byte (&((userbuf)[in_left]));
+ get_user (*out_left++, (unsigned char *) &((userbuf)[in_left]));
in_left += 2;
- *out_right++ = get_fs_byte (&((userbuf)[in_right]));
+ get_user (*out_right++, (unsigned char *) &((userbuf)[in_right]));
in_right += 2;
}
}
@@ -2674,9 +2743,9 @@
for (i = 0; i < len; i++)
{
- *out_left++ = get_fs_word (&((userbuf)[in_left]));
+ get_user (*out_left++, (unsigned short *) &((userbuf)[in_left]));
in_left += 4;
- *out_right++ = get_fs_word (&((userbuf)[in_right]));
+ get_user (*out_right++, (unsigned short *) &((userbuf)[in_right]));
in_right += 4;
}
}
@@ -2798,7 +2867,7 @@
struct patch_info *pat;
if (ptr < 0 || ptr >= free_sample)
- return -(EINVAL);
+ return -EINVAL;
memcpy (rec->data.data8, (char *) &samples[ptr],
sizeof (struct patch_info));
@@ -2818,12 +2887,12 @@
struct patch_info *pat;
if (ptr < 0 || ptr >= free_sample)
- return -(EINVAL);
+ return -EINVAL;
pat = (struct patch_info *) rec->data.data8;
if (pat->len > samples[ptr].len) /* Cannot expand sample */
- return -(EINVAL);
+ return -EINVAL;
pat->key = samples[ptr].key; /* Ensure the link is correct */
@@ -2843,10 +2912,10 @@
int l = rec->parm3;
if (sample < 0 || sample >= free_sample)
- return -(EINVAL);
+ return -EINVAL;
if (offs < 0 || offs >= samples[sample].len)
- return -(EINVAL); /* Invalid offset */
+ return -EINVAL; /* Invalid offset */
n = samples[sample].len - offs; /* Num of bytes left */
@@ -2857,12 +2926,12 @@
l = sizeof (rec->data.data8);
if (l <= 0)
- return -(EINVAL); /*
+ return -EINVAL; /*
* Was there a bug?
*/
offs += sample_ptrs[sample]; /*
- * Begin offsets + offset to DRAM
+ * Begin offset + offset to DRAM
*/
for (n = 0; n < l; n++)
@@ -2884,10 +2953,10 @@
int l = rec->parm3;
if (sample < 0 || sample >= free_sample)
- return -(EINVAL);
+ return -EINVAL;
if (offs < 0 || offs >= samples[sample].len)
- return -(EINVAL); /*
+ return -EINVAL; /*
* Invalid offset
*/
@@ -2902,7 +2971,7 @@
l = sizeof (rec->data.data8);
if (l <= 0)
- return -(EINVAL); /*
+ return -EINVAL; /*
* Was there a bug?
*/
@@ -2920,7 +2989,7 @@
break;
default:
- return -(EINVAL);
+ return -EINVAL;
}
}
@@ -3030,7 +3099,7 @@
mix_image &= ~0x07;
mix_image |= mask & 0x07;
- outb (mix_image, u_Mixer);
+ outb ((mix_image), u_Mixer);
restore_flags (flags);
}
@@ -3046,16 +3115,20 @@
switch (cmd & 0xff)
{
case SOUND_MIXER_RECSRC:
- gus_recmask = get_user ((int *) arg) & MIX_DEVS;
+ get_user (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 snd_ioctl_return ((int *) arg, gus_recmask);
+ return ioctl_out (arg, gus_recmask);
break;
case SOUND_MIXER_MIC:
{
- int vol = get_user ((int *) arg) & 0xff;
+ int vol;
+
+ get_user (vol, (int *) arg);
+ vol &= 0xff;
if (vol < 0)
vol = 0;
@@ -3063,13 +3136,16 @@
vol = 100;
gus_mic_vol = vol;
set_input_volumes ();
- return snd_ioctl_return ((int *) arg, vol | (vol << 8));
+ return ioctl_out (arg, vol | (vol << 8));
}
break;
case SOUND_MIXER_LINE:
{
- int vol = get_user ((int *) arg) & 0xff;
+ int vol;
+
+ get_user (vol, (int *) arg);
+ vol &= 0xff;
if (vol < 0)
vol = 0;
@@ -3077,25 +3153,27 @@
vol = 100;
gus_line_vol = vol;
set_input_volumes ();
- return snd_ioctl_return ((int *) arg, vol | (vol << 8));
+ return ioctl_out (arg, vol | (vol << 8));
}
break;
case SOUND_MIXER_PCM:
- gus_pcm_volume = get_user ((int *) arg) & 0xff;
+ get_user (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 snd_ioctl_return ((int *) arg, gus_pcm_volume | (gus_pcm_volume << 8));
+ return ioctl_out (arg, gus_pcm_volume | (gus_pcm_volume << 8));
break;
case SOUND_MIXER_SYNTH:
{
int voice;
- gus_wave_volume = get_user ((int *) arg) & 0xff;
+ get_user (gus_wave_volume, (int *) arg);
+ gus_wave_volume &= 0xff;
if (gus_wave_volume < 0)
gus_wave_volume = 0;
@@ -3106,12 +3184,12 @@
for (voice = 0; voice < nr_voices; voice++)
dynamic_volume_change (voice); /* Apply the new vol */
- return snd_ioctl_return ((int *) arg, gus_wave_volume | (gus_wave_volume << 8));
+ return ioctl_out (arg, gus_wave_volume | (gus_wave_volume << 8));
}
break;
default:
- return -(EINVAL);
+ return -EINVAL;
}
else
switch (cmd & 0xff) /*
@@ -3120,47 +3198,47 @@
{
case SOUND_MIXER_RECSRC:
- return snd_ioctl_return ((int *) arg, gus_recmask);
+ return ioctl_out (arg, gus_recmask);
break;
case SOUND_MIXER_DEVMASK:
- return snd_ioctl_return ((int *) arg, MIX_DEVS);
+ return ioctl_out (arg, MIX_DEVS);
break;
case SOUND_MIXER_STEREODEVS:
- return snd_ioctl_return ((int *) arg, 0);
+ return ioctl_out (arg, 0);
break;
case SOUND_MIXER_RECMASK:
- return snd_ioctl_return ((int *) arg, SOUND_MASK_MIC | SOUND_MASK_LINE);
+ return ioctl_out (arg, SOUND_MASK_MIC | SOUND_MASK_LINE);
break;
case SOUND_MIXER_CAPS:
- return snd_ioctl_return ((int *) arg, 0);
+ return ioctl_out (arg, 0);
break;
case SOUND_MIXER_MIC:
- return snd_ioctl_return ((int *) arg, gus_mic_vol | (gus_mic_vol << 8));
+ return ioctl_out (arg, gus_mic_vol | (gus_mic_vol << 8));
break;
case SOUND_MIXER_LINE:
- return snd_ioctl_return ((int *) arg, gus_line_vol | (gus_line_vol << 8));
+ return ioctl_out (arg, gus_line_vol | (gus_line_vol << 8));
break;
case SOUND_MIXER_PCM:
- return snd_ioctl_return ((int *) arg, gus_pcm_volume | (gus_pcm_volume << 8));
+ return ioctl_out (arg, gus_pcm_volume | (gus_pcm_volume << 8));
break;
case SOUND_MIXER_SYNTH:
- return snd_ioctl_return ((int *) arg, gus_wave_volume | (gus_wave_volume << 8));
+ return ioctl_out (arg, gus_wave_volume | (gus_wave_volume << 8));
break;
default:
- return -(EINVAL);
+ return -EINVAL;
}
}
else
- return -(EINVAL);
+ return -EINVAL;
}
static struct mixer_operations gus_mixer_operations =
@@ -3187,7 +3265,7 @@
*/
mix_image &= ~0x07;
mix_image |= 0x04; /* All channels enabled */
- outb (mix_image, u_Mixer);
+ outb ((mix_image), u_Mixer);
}
}
@@ -3197,6 +3275,7 @@
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;
@@ -3227,27 +3306,9 @@
* Versions < 3.6 don't have the digital ASIC. Try to probe it first.
*/
-#ifdef GUSPNP_AUTODETECT
- 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\n"));
- gus_pnp_flag = 0;
- }
- gus_write8 (0x5b, val); /* Restore all bits */
-#endif
-
save_flags (flags);
cli ();
- outb (0x20, gus_base + 0x0f);
+ outb ((0x20), gus_base + 0x0f);
val = inb (gus_base + 0x0f);
restore_flags (flags);
@@ -3306,12 +3367,16 @@
max_config |= (gus_base >> 4) & 0x0f; /* Extract the X from 2X0 */
- outb (max_config, gus_base + 0x106); /* UltraMax control */
+ 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;
@@ -3325,6 +3390,13 @@
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?]");
@@ -3343,15 +3415,19 @@
if (hw_config->name)
{
- char tmp[20];
- strncpy (tmp, hw_config->name, 20);
- tmp[19] = 0;
- sprintf (gus_info.name, "%s (%dk)", tmp, (int) gus_mem_size / 1024);
- gus_info.name[sizeof (gus_info.name) - 1] = 0;
+ 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 (gus_info.name, "Gravis UltraSound %s (%dk)", model_num, (int) gus_mem_size / 1024);
+ 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)));
@@ -3363,7 +3439,9 @@
return;
}
- conf_printf (gus_info.name, hw_config);
+ conf_printf (tmp2, hw_config);
+ strncpy (gus_info.name, tmp2, sizeof (tmp2));
+ gus_info.name[sizeof (tmp2) - 1] = 0;
if (num_synths >= MAX_SYNTH_DEV)
printk ("GUS Error: Too many synthesizers\n");
@@ -3380,20 +3458,21 @@
gus_initialize ();
- if (num_audiodevs < MAX_AUDIO_DEV)
- {
- audio_devs[gus_devnum = num_audiodevs++] = &gus_audio_operations;
- audio_devs[gus_devnum]->dmachan1 = dma;
- audio_devs[gus_devnum]->dmachan2 = dma2;
- audio_devs[gus_devnum]->buffsize = DSP_BUFFSIZE;
- audio_devs[gus_devnum]->min_fragment = 9;
- audio_devs[gus_devnum]->mixer_dev = num_mixers; /* Next mixer# */
- audio_devs[gus_devnum]->flags |= DMA_HARDSTOP;
- if (dma2 != dma && dma2 != -1)
- audio_devs[gus_devnum]->flags |= DMA_DUPLEX;
- }
- else
- printk ("GUS: Too many PCM devices available\n");
+ if (gus_mem_size > 0)
+ if (num_audiodevs < MAX_AUDIO_DEV)
+ {
+ audio_devs[gus_devnum = num_audiodevs++] = &gus_audio_operations;
+ audio_devs[gus_devnum]->dmachan1 = dma;
+ audio_devs[gus_devnum]->dmachan2 = dma2;
+ audio_devs[gus_devnum]->buffsize = DSP_BUFFSIZE;
+ audio_devs[gus_devnum]->min_fragment = 9;
+ audio_devs[gus_devnum]->mixer_dev = num_mixers; /* Next mixer# */
+ audio_devs[gus_devnum]->flags |= DMA_HARDSTOP;
+ if (dma2 != dma && dma2 != -1)
+ audio_devs[gus_devnum]->flags |= DMA_DUPLEX;
+ }
+ else
+ printk ("GUS: Too many audio devices available\n");
/*
* Mixer dependent initialization.
@@ -3648,10 +3727,10 @@
switch (active_device)
{
case GUS_DEV_WAVE:
- if ((dram_sleep_flag.flags & WK_SLEEP))
+ if ((dram_sleep_flag.opts & WK_SLEEP))
{
- dram_sleep_flag.flags = WK_WAKEUP;
- module_wake_up (&dram_sleeper);
+ dram_sleep_flag.opts = WK_WAKEUP;
+ wake_up (&dram_sleeper);
};
break;
@@ -3702,12 +3781,12 @@
{
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);
- outb ((unsigned char) (val & 0xff), data_addr);
+ outb (((unsigned char) (val & 0xff)), data_addr);
for (i = 0; i < 2; i++)
inb (select_addr);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov