summaryrefslogtreecommitdiffstats
path: root/drivers/sound
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1998-09-19 19:15:08 +0000
committerRalf Baechle <ralf@linux-mips.org>1998-09-19 19:15:08 +0000
commit03ba4131783cc9e872f8bb26a03f15bc11f27564 (patch)
tree88db8dba75ae06ba3bad08e42c5e52efc162535c /drivers/sound
parent257730f99381dd26e10b832fce4c94cae7ac1176 (diff)
- Merge with Linux 2.1.121.
- Bugfixes.
Diffstat (limited to 'drivers/sound')
-rw-r--r--drivers/sound/Config.in16
-rw-r--r--drivers/sound/Makefile3
-rw-r--r--drivers/sound/README.FIRST2
-rw-r--r--drivers/sound/audio.c13
-rw-r--r--drivers/sound/dev_table.h2
-rw-r--r--drivers/sound/dmabuf.c1
-rw-r--r--drivers/sound/dmasound.c3
-rw-r--r--drivers/sound/es1370.c130
-rw-r--r--drivers/sound/es1371.c101
-rw-r--r--drivers/sound/gus_wave.c1
-rw-r--r--drivers/sound/lowlevel/README7
-rw-r--r--drivers/sound/lowlevel/README.aedsp16137
-rw-r--r--drivers/sound/lowlevel/aci.c125
-rw-r--r--drivers/sound/lowlevel/aedsp16.c149
-rw-r--r--drivers/sound/lowlevel/awe_compat.h2
-rw-r--r--drivers/sound/lowlevel/miroaci.h6
-rw-r--r--drivers/sound/lowlevel/soundlow.c5
-rw-r--r--drivers/sound/msnd.c23
-rw-r--r--drivers/sound/msnd.h87
-rw-r--r--drivers/sound/msnd_classic.h236
-rw-r--r--drivers/sound/msnd_pinnacle.c821
-rw-r--r--drivers/sound/msnd_pinnacle.h375
-rw-r--r--drivers/sound/opl3.c29
-rw-r--r--drivers/sound/sb.h2
-rw-r--r--drivers/sound/sb_card.c11
-rw-r--r--drivers/sound/sb_common.c29
-rw-r--r--drivers/sound/sequencer.c3
-rw-r--r--drivers/sound/sonicvibes.c86
-rw-r--r--drivers/sound/sound_core.c16
-rw-r--r--drivers/sound/soundcard.c5
-rw-r--r--drivers/sound/wavfront.c1088
-rw-r--r--drivers/sound/wf_midi.c13
32 files changed, 2092 insertions, 1435 deletions
diff --git a/drivers/sound/Config.in b/drivers/sound/Config.in
index 4f511f3ab..b23a61f74 100644
--- a/drivers/sound/Config.in
+++ b/drivers/sound/Config.in
@@ -35,6 +35,18 @@ if [ "$CONFIG_SOUND_MSNDPIN" = "y" ]; then
int 'MSND Pinnacle IRQ 5,7,9,10,11,12' CONFIG_MSNDPIN_IRQ 5
hex 'MSND Pinnacle Memory B0000,C8000,D0000,D8000,E0000,E8000' CONFIG_MSNDPIN_MEM D0000
hex 'MSND Pinnacle I/O 210,220,230,240,250,260,290,3E0' CONFIG_MSNDPIN_IO 290
+ bool 'MSND Pinnacle Non-PnP Mode' CONFIG_MSNDPIN_NONPNP
+ if [ "$CONFIG_MSNDPIN_NONPNP" = "y" ]; then
+ comment 'MSND Pinnacle DSP section will be configured to above parameters.'
+ hex 'MSDN Pinnacle Config Port 250,260,270' CONFIG_MSNDPIN_CFG 250
+ comment 'Pinnacle-specific Device Configuration (0 disables)'
+ hex 'MSDN Pinnacle MPU I/O (e.g. 330)' CONFIG_MSNDPIN_MPU_IO 0
+ int 'MSDN Pinnacle MPU IRQ (e.g. 9)' CONFIG_MSNDPIN_MPU_IRQ 0
+ hex 'MSDN Pinnacle IDE I/O 0 (e.g. 170)' CONFIG_MSNDPIN_IDE_IO0 0
+ hex 'MSDN Pinnacle IDE I/O 1 (e.g. 376)' CONFIG_MSNDPIN_IDE_IO1 0
+ int 'MSDN Pinnacle IDE IRQ (e.g. 15)' CONFIG_MSNDPIN_IDE_IRQ 0
+ hex 'MSDN Pinnacle Joystick I/O (e.g. 200)' CONFIG_MSNDPIN_JOYSTICK_IO 0
+ fi
fi
dep_tristate 'OSS sound modules' CONFIG_SOUND_OSS $CONFIG_SOUND
@@ -156,7 +168,7 @@ if [ "$CONFIG_SOUND_OSS" = "y" -o "$CONFIG_SOUND_OSS" = "m" ]; then
dep_tristate 'Support for Crystal CS4232 based (PnP) cards' CONFIG_SOUND_CS4232 $CONFIG_SOUND_OSS
if [ "$CONFIG_SOUND_CS4232" = "y" ]; then
- hex 'CS4232 audio I/O base 530, 604, E80 or F40' CONFIG_CS4232_BASE 530
+ hex 'CS4232 audio I/O base (normally 530, 604, E80 or F40)' CONFIG_CS4232_BASE 530
int 'CS4232 audio IRQ 5, 7, 9, 11, 12 or 15' CONFIG_CS4232_IRQ 11
int 'CS4232 audio DMA 0, 1 or 3' CONFIG_CS4232_DMA 0
int 'CS4232 second (duplex) DMA 0, 1 or 3' CONFIG_CS4232_DMA2 3
@@ -205,7 +217,7 @@ if [ "$CONFIG_SOUND_OSS" = "y" -o "$CONFIG_SOUND_OSS" = "m" ]; then
dep_tristate 'Loopback MIDI device support' CONFIG_SOUND_VMIDI $CONFIG_SOUND_OSS
dep_tristate '6850 UART support' CONFIG_SOUND_UART6850 $CONFIG_SOUND_OSS
- if [ "$CONFIG_UART6850" = "y" ]; then
+ if [ "$CONFIG_SOUND_UART6850" = "y" ]; then
hex 'I/O base for UART 6850 MIDI port (Unknown)' CONFIG_U6850_BASE 0
int 'UART6850 IRQ (Unknown)' CONFIG_U6850_IRQ -1
fi
diff --git a/drivers/sound/Makefile b/drivers/sound/Makefile
index d04efe300..f072b7fad 100644
--- a/drivers/sound/Makefile
+++ b/drivers/sound/Makefile
@@ -79,7 +79,7 @@ obj-$(CONFIG_SOUND_SOFTOSS) += softoss2.o
obj-$(CONFIG_SOUND_SGALAXY) += sgalaxy.o
obj-$(CONFIG_SOUND_SSCAPE) += sscape.o ad1848.o mpu401.o
obj-$(CONFIG_SOUND_TRIX) += trix.o ad1848.o sb.o uart401.o
-obj-$(CONFIG_SOUND_UART6850) += uart6850.c
+obj-$(CONFIG_SOUND_UART6850) += uart6850.o
obj-$(CONFIG_SOUND_VMIDI) += v_midi.o
obj-$(CONFIG_SOUND_YM3812) += adlib_card.o opl3.o
obj-$(CONFIG_VIDC_SOUND) += vidc_mod.o
@@ -92,7 +92,6 @@ obj-$(CONFIG_SOUND_SONICVIBES) += sonicvibes.o
endif
endif
-
# Declare multi-part drivers.
list-multi := sound.o gus.o pas2.o sb.o softoss2.o vidc_mod.o \
diff --git a/drivers/sound/README.FIRST b/drivers/sound/README.FIRST
index 3a6b60483..85ecccdfc 100644
--- a/drivers/sound/README.FIRST
+++ b/drivers/sound/README.FIRST
@@ -1,4 +1,4 @@
-The modular sound driver patches where funded by Red Hat Software
+The modular sound driver patches were funded by Red Hat Software
(www.redhat.com). The sound driver here is thus a modified version of
Hannu's code. Please bear that in mind when considering the appropriate
forums for bug reporting.
diff --git a/drivers/sound/audio.c b/drivers/sound/audio.c
index f08f6aaca..54d8e5f5b 100644
--- a/drivers/sound/audio.c
+++ b/drivers/sound/audio.c
@@ -17,6 +17,7 @@
* (which is grossly misnamed btw.) because they have the same
* lifetime as the rest in there and dynamic allocation saves
* 12k or so
+ * Thomas Sailer : use more logical O_NONBLOCK semantics
*/
#include <linux/config.h>
@@ -99,7 +100,6 @@ int audio_open(int dev, struct file *file)
set_format(dev, bits);
audio_devs[dev]->audio_mode = AM_NONE;
- audio_devs[dev]->dev_nblock = 0;
return ret;
@@ -203,10 +203,10 @@ int audio_write(int dev, struct file *file, const char *buf, int count)
while (c)
{
- if ((err = DMAbuf_getwrbuffer(dev, &dma_buf, &buf_size, audio_devs[dev]->dev_nblock)) < 0)
+ if ((err = DMAbuf_getwrbuffer(dev, &dma_buf, &buf_size, !!(file->f_flags & O_NONBLOCK))) < 0)
{
/* Handle nonblocking mode */
- if (audio_devs[dev]->dev_nblock && err == -EAGAIN)
+ if ((file->f_flags & O_NONBLOCK) && err == -EAGAIN)
return p; /* No more space. Return # of accepted bytes */
return err;
}
@@ -273,14 +273,13 @@ int audio_read(int dev, struct file *file, char *buf, int count)
while(c)
{
- if ((buf_no = DMAbuf_getrdbuffer(dev, &dmabuf, &l,
- audio_devs[dev]->dev_nblock)) < 0)
+ if ((buf_no = DMAbuf_getrdbuffer(dev, &dmabuf, &l, !!(file->f_flags & O_NONBLOCK))) < 0)
{
/*
* Nonblocking mode handling. Return current # of bytes
*/
- if (audio_devs[dev]->dev_nblock && buf_no == -EAGAIN)
+ if (file->f_flags & O_NONBLOCK && buf_no == -EAGAIN)
return p;
if (p > 0) /* Avoid throwing away data */
@@ -388,7 +387,7 @@ int audio_ioctl(int dev, struct file *file, unsigned int cmd, caddr_t arg)
return dma_ioctl(dev, cmd, arg);
case SNDCTL_DSP_NONBLOCK:
- audio_devs[dev]->dev_nblock = 1;
+ file->f_flags |= O_NONBLOCK;
return 0;
case SNDCTL_DSP_GETCAPS:
diff --git a/drivers/sound/dev_table.h b/drivers/sound/dev_table.h
index bf5d62bff..215df408a 100644
--- a/drivers/sound/dev_table.h
+++ b/drivers/sound/dev_table.h
@@ -230,8 +230,6 @@ struct audio_operations
/* fields formerly in audio.c */
int audio_mode;
- /* why don't we use file->f_flags & O_NONBLOCK for the following? - ts */
- int dev_nblock; /* 1 if in nonblocking mode */
#define AM_NONE 0
#define AM_WRITE OPEN_WRITE
diff --git a/drivers/sound/dmabuf.c b/drivers/sound/dmabuf.c
index ecabf72ab..51b9d87de 100644
--- a/drivers/sound/dmabuf.c
+++ b/drivers/sound/dmabuf.c
@@ -206,6 +206,7 @@ static void close_dmap(struct audio_operations *adev, struct dma_buffparms *dmap
dmap->dma_mode = DMODE_NONE;
dmap->flags &= ~DMA_BUSY;
disable_dma(dmap->dma);
+ sound_free_dmap(dmap);
}
diff --git a/drivers/sound/dmasound.c b/drivers/sound/dmasound.c
index f944252bf..b351c73db 100644
--- a/drivers/sound/dmasound.c
+++ b/drivers/sound/dmasound.c
@@ -3808,6 +3808,7 @@ static struct file_operations mixer_fops =
mixer_ioctl,
NULL, /* mixer_mmap */
mixer_open,
+ NULL, /* flush */
mixer_release,
};
@@ -4169,6 +4170,7 @@ static struct file_operations sq_fops =
sq_ioctl,
NULL, /* sq_mmap */
sq_open,
+ NULL, /* flush */
sq_release,
};
@@ -4363,6 +4365,7 @@ static struct file_operations state_fops =
NULL, /* state_ioctl */
NULL, /* state_mmap */
state_open,
+ NULL, /* flush */
state_release,
};
diff --git a/drivers/sound/es1370.c b/drivers/sound/es1370.c
index 5a9b4ec9e..00794bf39 100644
--- a/drivers/sound/es1370.c
+++ b/drivers/sound/es1370.c
@@ -1,7 +1,7 @@
/*****************************************************************************/
/*
- * es1370.c -- Ensoniq ES1370/Ashai Kasei AK4531 audio driver.
+ * es1370.c -- Ensoniq ES1370/Asahi Kasei AK4531 audio driver.
*
* Copyright (C) 1998 Thomas Sailer (sailer@ife.ee.ethz.ch)
*
@@ -67,6 +67,15 @@
* settings (not sure if this should be standard)
* Fixed many references: f_flags should be f_mode
* -- Gerald Britton <gbritton@mit.edu>
+ * 03.08.98 0.11 Now mixer behaviour can basically be selected between
+ * "OSS documented" and "OSS actual" behaviour
+ * Fixed mixer table thanks to Hakan.Lennestal@lu.erisoft.se
+ * On module startup, set DAC2 to 11kSPS instead of 5.5kSPS,
+ * as it produces an annoying ssssh in the lower sampling rate
+ * Do not include modversions.h
+ * 22.08.98 0.12 Mixer registers actually have 5 instead of 4 bits
+ * pointed out by Itai Nahshon
+ * 31.08.98 0.13 Fix realplayer problems - dac.count issues
*
* some important things missing in Ensoniq documentation:
*
@@ -91,7 +100,6 @@
#include <linux/version.h>
#include <linux/module.h>
-#include <linux/modversions.h>
#include <linux/string.h>
#include <linux/ioport.h>
#include <linux/sched.h>
@@ -110,6 +118,10 @@
/* --------------------------------------------------------------------- */
+#undef OSS_DOCUMENTED_MIXER_SEMANTICS
+
+/* --------------------------------------------------------------------- */
+
#ifndef PCI_VENDOR_ID_ENSONIQ
#define PCI_VENDOR_ID_ENSONIQ 0x1274
#endif
@@ -316,7 +328,7 @@ struct es1370_state {
/* --------------------------------------------------------------------- */
-struct es1370_state *devs = NULL;
+static struct es1370_state *devs = NULL;
/* --------------------------------------------------------------------- */
@@ -446,7 +458,7 @@ static void start_adc(struct es1370_state *s)
unsigned fragremain, fshift;
spin_lock_irqsave(&s->lock, flags);
- if (!(s->ctrl & CTRL_ADC_EN) && (s->dma_adc.mapped || s->dma_adc.count < s->dma_adc.dmasize - 2*s->dma_adc.fragsize)
+ if (!(s->ctrl & CTRL_ADC_EN) && (s->dma_adc.mapped || s->dma_adc.count < (signed)(s->dma_adc.dmasize - 2*s->dma_adc.fragsize))
&& s->dma_adc.ready) {
s->ctrl |= CTRL_ADC_EN;
s->sctrl = (s->sctrl & ~SCTRL_R1LOOPSEL) | SCTRL_R1INTEN;
@@ -464,10 +476,9 @@ static void start_adc(struct es1370_state *s)
/* --------------------------------------------------------------------- */
-#define DMABUF_DEFAULTORDER 8
+#define DMABUF_DEFAULTORDER (17-PAGE_SHIFT)
#define DMABUF_MINORDER 1
-
extern inline void dealloc_dmabuf(struct dmabuf *db)
{
unsigned long map, mapend;
@@ -588,10 +599,10 @@ static void es1370_update_ptr(struct es1370_state *s)
s->dma_adc.total_bytes += diff;
s->dma_adc.count += diff;
if (s->dma_adc.mapped) {
- if (s->dma_adc.count >= s->dma_adc.fragsize)
+ if (s->dma_adc.count >= (signed)s->dma_adc.fragsize)
wake_up(&s->dma_adc.wait);
} else {
- if (s->dma_adc.count > s->dma_adc.dmasize - ((3 * s->dma_adc.fragsize) >> 1)) {
+ if (s->dma_adc.count > (signed)(s->dma_adc.dmasize - ((3 * s->dma_adc.fragsize) >> 1))) {
s->ctrl &= ~CTRL_ADC_EN;
outl(s->ctrl, s->io+ES1370_REG_CONTROL);
s->dma_adc.error++;
@@ -606,7 +617,7 @@ static void es1370_update_ptr(struct es1370_state *s)
s->dma_dac1.total_bytes += diff;
if (s->dma_dac1.mapped) {
s->dma_dac1.count += diff;
- if (s->dma_dac1.count >= s->dma_dac1.fragsize)
+ if (s->dma_dac1.count >= (signed)s->dma_dac1.fragsize)
wake_up(&s->dma_dac1.wait);
} else {
s->dma_dac1.count -= diff;
@@ -614,12 +625,12 @@ static void es1370_update_ptr(struct es1370_state *s)
s->ctrl &= ~CTRL_DAC1_EN;
outl(s->ctrl, s->io+ES1370_REG_CONTROL);
s->dma_dac1.error++;
- } else if (s->dma_dac1.count <= s->dma_dac1.fragsize && !s->dma_dac1.endcleared) {
+ } else if (s->dma_dac1.count <= (signed)s->dma_dac1.fragsize && !s->dma_dac1.endcleared) {
clear_advance(s->dma_dac1.rawbuf, s->dma_dac1.dmasize, s->dma_dac1.swptr,
s->dma_dac1.fragsize, (s->sctrl & SCTRL_P1SEB) ? 0 : 0x80);
s->dma_dac1.endcleared = 1;
}
- if (s->dma_dac1.count < s->dma_dac1.dmasize)
+ if (s->dma_dac1.count < (signed)s->dma_dac1.dmasize)
wake_up(&s->dma_dac1.wait);
}
}
@@ -629,7 +640,7 @@ static void es1370_update_ptr(struct es1370_state *s)
s->dma_dac2.total_bytes += diff;
if (s->dma_dac2.mapped) {
s->dma_dac2.count += diff;
- if (s->dma_dac2.count >= s->dma_dac2.fragsize)
+ if (s->dma_dac2.count >= (signed)s->dma_dac2.fragsize)
wake_up(&s->dma_dac2.wait);
} else {
s->dma_dac2.count -= diff;
@@ -637,12 +648,12 @@ static void es1370_update_ptr(struct es1370_state *s)
s->ctrl &= ~CTRL_DAC2_EN;
outl(s->ctrl, s->io+ES1370_REG_CONTROL);
s->dma_dac2.error++;
- } else if (s->dma_dac2.count <= s->dma_dac2.fragsize && !s->dma_dac2.endcleared) {
+ } else if (s->dma_dac2.count <= (signed)s->dma_dac2.fragsize && !s->dma_dac2.endcleared) {
clear_advance(s->dma_dac2.rawbuf, s->dma_dac2.dmasize, s->dma_dac2.swptr,
s->dma_dac2.fragsize, (s->sctrl & SCTRL_P2SEB) ? 0 : 0x80);
s->dma_dac2.endcleared = 1;
}
- if (s->dma_dac2.count < s->dma_dac2.dmasize)
+ if (s->dma_dac2.count < (signed)s->dma_dac2.dmasize)
wake_up(&s->dma_dac2.wait);
}
}
@@ -734,20 +745,21 @@ static const struct {
[SOUND_MIXER_CD] = { 3, 0x6, 0x7, 1, 0x0006, 1 }, /* CD */
[SOUND_MIXER_LINE] = { 4, 0x8, 0x9, 1, 0x0018, 1 }, /* Line */
[SOUND_MIXER_LINE1] = { 5, 0xa, 0xb, 1, 0x1800, 1 }, /* AUX */
- [SOUND_MIXER_LINE2] = { 6, 0xc, 0x0, 1, 0x0100, 1 }, /* Mono1 */
- [SOUND_MIXER_LINE3] = { 7, 0xd, 0x0, 1, 0x0200, 1 }, /* Mono2 */
- [SOUND_MIXER_MIC] = { 8, 0xe, 0x0, 1, 0x0001, 1 }, /* Mic */
- [SOUND_MIXER_OGAIN] = { 9, 0xf, 0x0, 1, 0x0000, 1 } /* mono out */
+ [SOUND_MIXER_LINE2] = { 6, 0xc, 0x0, 0, 0x0100, 1 }, /* Mono1 */
+ [SOUND_MIXER_LINE3] = { 7, 0xd, 0x0, 0, 0x0200, 1 }, /* Mono2 */
+ [SOUND_MIXER_MIC] = { 8, 0xe, 0x0, 0, 0x0001, 1 }, /* Mic */
+ [SOUND_MIXER_OGAIN] = { 9, 0xf, 0x0, 0, 0x0000, 1 } /* mono out */
};
static int mixer_ioctl(struct es1370_state *s, unsigned int cmd, unsigned long arg)
{
+ unsigned long flags;
int i, val, j;
- unsigned char l, r, rl, rr, sr, sl;
+ unsigned char l, r, rl, rr;
VALIDATE_STATE(s);
-
if (cmd == SOUND_MIXER_PRIVATE1) {
+ /* enable/disable/query mixer preamp */
get_user_ret(val, (int *)arg, -EFAULT);
if (val != -1) {
s->mix.micpreamp = !!val;
@@ -755,6 +767,34 @@ static int mixer_ioctl(struct es1370_state *s, unsigned int cmd, unsigned long a
}
return put_user(s->mix.micpreamp, (int *)arg);
}
+ if (cmd == SOUND_MIXER_PRIVATE2) {
+ /* enable/disable/query use of linein as second lineout */
+ get_user_ret(val, (int *)arg, -EFAULT);
+ if (val != -1) {
+ spin_lock_irqsave(&s->lock, flags);
+ if (val)
+ s->ctrl |= CTRL_XCTL0;
+ else
+ s->ctrl &= ~CTRL_XCTL0;
+ outl(s->ctrl, s->io+ES1370_REG_CONTROL);
+ spin_unlock_irqrestore(&s->lock, flags);
+ }
+ return put_user((s->ctrl & CTRL_XCTL0) ? 1 : 0, (int *)arg);
+ }
+ if (cmd == SOUND_MIXER_PRIVATE3) {
+ /* enable/disable/query microphone impedance setting */
+ get_user_ret(val, (int *)arg, -EFAULT);
+ if (val != -1) {
+ spin_lock_irqsave(&s->lock, flags);
+ if (val)
+ s->ctrl |= CTRL_XCTL1;
+ else
+ s->ctrl &= ~CTRL_XCTL1;
+ outl(s->ctrl, s->io+ES1370_REG_CONTROL);
+ spin_unlock_irqrestore(&s->lock, flags);
+ }
+ return put_user((s->ctrl & CTRL_XCTL1) ? 1 : 0, (int *)arg);
+ }
if (cmd == SOUND_MIXER_INFO) {
mixer_info info;
strncpy(info.id, "ES1370", sizeof(info.id));
@@ -842,25 +882,23 @@ static int mixer_ioctl(struct es1370_state *s, unsigned int cmd, unsigned long a
l = val & 0xff;
if (l > 100)
l = 100;
- sl = sr = l;
if (mixtable[i].stereo) {
r = (val >> 8) & 0xff;
if (r > 100)
r = 100;
- sr = r;
- if (l < 10) {
+ if (l < 7) {
rl = 0x80;
l = 0;
} else {
- rl = 15 - ((l - 10) / 6);
- l = (15 - rl) * 6 + 10;
+ rl = 31 - ((l - 7) / 3);
+ l = (31 - rl) * 3 + 7;
}
- if (r < 10) {
+ if (r < 7) {
rr = 0x80;
r = 0;
} else {
- rr = 15 - ((r - 10) / 6);
- r = (15 - rr) * 6 + 10;
+ rr = 31 - ((r - 7) / 3);
+ r = (31 - rr) * 3 + 7;
}
wrcodec(s, mixtable[i].right, rr);
} else {
@@ -873,17 +911,21 @@ static int mixer_ioctl(struct es1370_state *s, unsigned int cmd, unsigned long a
r = l = (7 - rl) * 14 + 2;
}
} else {
- if (l < 10) {
+ if (l < 7) {
rl = 0x80;
r = l = 0;
} else {
- rl = 15 - ((l - 10) / 6);
- r = l = (15 - rl) * 6 + 10;
+ rl = 31 - ((l - 7) / 3);
+ r = l = (31 - rl) * 3 + 7;
}
}
- }
+ }
wrcodec(s, mixtable[i].left, rl);
- s->mix.vol[mixtable[i].volidx] = ((unsigned int)sr << 8) | sl;
+#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS
+ s->mix.vol[mixtable[i].volidx] = ((unsigned int)r << 8) | l;
+#else
+ s->mix.vol[mixtable[i].volidx] = val;
+#endif
return put_user(s->mix.vol[mixtable[i].volidx], (int *)arg);
}
}
@@ -935,14 +977,13 @@ static /*const*/ struct file_operations es1370_mixer_fops = {
&es1370_ioctl_mixdev,
NULL, /* mmap */
&es1370_open_mixdev,
+ NULL, /* flush */
&es1370_release_mixdev,
NULL, /* fsync */
NULL, /* fasync */
NULL, /* check_media_change */
-#if 0
NULL, /* revalidate */
NULL, /* lock */
-#endif
};
/* --------------------------------------------------------------------- */
@@ -1147,7 +1188,7 @@ static unsigned int es1370_poll(struct file *file, struct poll_table_struct *wai
es1370_update_ptr(s);
if (file->f_mode & FMODE_READ) {
if (s->dma_adc.mapped) {
- if (s->dma_adc.count >= s->dma_adc.fragsize)
+ if (s->dma_adc.count >= (signed)s->dma_adc.fragsize)
mask |= POLLIN | POLLRDNORM;
} else {
if (s->dma_adc.count > 0)
@@ -1156,10 +1197,10 @@ static unsigned int es1370_poll(struct file *file, struct poll_table_struct *wai
}
if (file->f_mode & FMODE_WRITE) {
if (s->dma_dac2.mapped) {
- if (s->dma_dac2.count >= s->dma_dac2.fragsize)
+ if (s->dma_dac2.count >= (signed)s->dma_dac2.fragsize)
mask |= POLLOUT | POLLWRNORM;
} else {
- if (s->dma_dac2.dmasize > s->dma_dac2.count)
+ if ((signed)s->dma_dac2.dmasize > s->dma_dac2.count)
mask |= POLLOUT | POLLWRNORM;
}
}
@@ -1584,6 +1625,7 @@ static /*const*/ struct file_operations es1370_audio_fops = {
&es1370_ioctl,
&es1370_mmap,
&es1370_open,
+ NULL, /* flush */
&es1370_release,
NULL, /* fsync */
NULL, /* fasync */
@@ -1660,10 +1702,10 @@ static unsigned int es1370_poll_dac(struct file *file, struct poll_table_struct
spin_lock_irqsave(&s->lock, flags);
es1370_update_ptr(s);
if (s->dma_dac1.mapped) {
- if (s->dma_dac1.count >= s->dma_dac1.fragsize)
+ if (s->dma_dac1.count >= (signed)s->dma_dac1.fragsize)
mask |= POLLOUT | POLLWRNORM;
} else {
- if (s->dma_dac1.dmasize > s->dma_dac1.count)
+ if ((signed)s->dma_dac1.dmasize > s->dma_dac1.count)
mask |= POLLOUT | POLLWRNORM;
}
spin_unlock_irqrestore(&s->lock, flags);
@@ -1950,6 +1992,7 @@ static /*const*/ struct file_operations es1370_dac_fops = {
&es1370_ioctl_dac,
&es1370_mmap_dac,
&es1370_open_dac,
+ NULL, /* flush */
&es1370_release_dac,
NULL, /* fsync */
NULL, /* fasync */
@@ -2186,6 +2229,7 @@ static /*const*/ struct file_operations es1370_midi_fops = {
NULL, /* ioctl */
NULL, /* mmap */
&es1370_midi_open,
+ NULL, /* flush */
&es1370_midi_release,
NULL, /* fsync */
NULL, /* fasync */
@@ -2234,7 +2278,7 @@ __initfunc(int init_es1370(void))
if (!pci_present()) /* No PCI bus in this machine! */
return -ENODEV;
- printk(KERN_INFO "es1370: version v0.10 time " __TIME__ " " __DATE__ "\n");
+ printk(KERN_INFO "es1370: version v0.13 time " __TIME__ " " __DATE__ "\n");
while (index < NR_DEVICE &&
(pcidev = pci_find_device(PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1370, pcidev))) {
if (pcidev->base_address[0] == 0 ||
@@ -2267,7 +2311,7 @@ __initfunc(int init_es1370(void))
goto err_irq;
}
/* initialize codec registers */
- s->ctrl = CTRL_CDC_EN | CTRL_SERR_DIS | (DAC2_SRTODIV(8000) << CTRL_SH_PCLKDIV);
+ s->ctrl = CTRL_CDC_EN | CTRL_SERR_DIS | (DAC2_SRTODIV(8000) << CTRL_SH_PCLKDIV) | (1 << CTRL_SH_WTSRSEL);
if (joystick[index]) {
if (check_region(0x200, JOY_EXTENT))
printk(KERN_ERR "es1370: io port 0x200 in use\n");
@@ -2356,7 +2400,7 @@ void cleanup_module(void)
while ((s = devs)) {
devs = devs->next;
- outl(CTRL_SERR_DIS, s->io+ES1370_REG_CONTROL); /* switch everything off */
+ outl(CTRL_SERR_DIS | (1 << CTRL_SH_WTSRSEL), s->io+ES1370_REG_CONTROL); /* switch everything off */
outl(0, s->io+ES1370_REG_SERIAL_CONTROL); /* clear serial interrupts */
synchronize_irq();
free_irq(s->irq, s);
diff --git a/drivers/sound/es1371.c b/drivers/sound/es1371.c
index 8fcc03541..1c025fa2e 100644
--- a/drivers/sound/es1371.c
+++ b/drivers/sound/es1371.c
@@ -45,8 +45,10 @@
* should be detected. This results in strange behaviour of some mixer
* settings, like master volume and mic.
* 08.06.98 0.2 First release using Alan Cox' soundcore instead of miscdevice
- *
- *
+ * 03.08.98 0.3 Do not include modversions.h
+ * Now mixer behaviour can basically be selected between
+ * "OSS documented" and "OSS actual" behaviour
+ * 31.08.98 0.4 Fix realplayer problems - dac.count issues
*
*/
@@ -54,7 +56,6 @@
#include <linux/version.h>
#include <linux/module.h>
-#include <linux/modversions.h>
#include <linux/string.h>
#include <linux/ioport.h>
#include <linux/sched.h>
@@ -73,6 +74,10 @@
/* --------------------------------------------------------------------- */
+#undef OSS_DOCUMENTED_MIXER_SEMANTICS
+
+/* --------------------------------------------------------------------- */
+
#ifndef PCI_VENDOR_ID_ENSONIQ
#define PCI_VENDOR_ID_ENSONIQ 0x1274
#endif
@@ -325,6 +330,9 @@ struct es1371_state {
struct {
unsigned short codec_id;
unsigned int modcnt;
+#ifndef OSS_DOCUMENTED_MIXER_SEMANTICS
+ unsigned short vol[13];
+#endif /* OSS_DOCUMENTED_MIXER_SEMANTICS */
} mix;
/* wave stuff */
@@ -373,7 +381,7 @@ struct es1371_state {
/* --------------------------------------------------------------------- */
-struct es1371_state *devs = NULL;
+static struct es1371_state *devs = NULL;
/* --------------------------------------------------------------------- */
@@ -686,7 +694,7 @@ static void start_adc(struct es1371_state *s)
unsigned fragremain, fshift;
spin_lock_irqsave(&s->lock, flags);
- if (!(s->ctrl & CTRL_ADC_EN) && (s->dma_adc.mapped || s->dma_adc.count < s->dma_adc.dmasize - 2*s->dma_adc.fragsize)
+ if (!(s->ctrl & CTRL_ADC_EN) && (s->dma_adc.mapped || s->dma_adc.count < (signed)(s->dma_adc.dmasize - 2*s->dma_adc.fragsize))
&& s->dma_adc.ready) {
s->ctrl |= CTRL_ADC_EN;
s->sctrl = (s->sctrl & ~SCTRL_R1LOOPSEL) | SCTRL_R1INTEN;
@@ -704,7 +712,7 @@ static void start_adc(struct es1371_state *s)
/* --------------------------------------------------------------------- */
-#define DMABUF_DEFAULTORDER 8
+#define DMABUF_DEFAULTORDER (17-PAGE_SHIFT)
#define DMABUF_MINORDER 1
@@ -831,7 +839,7 @@ static void es1371_update_ptr(struct es1371_state *s)
if (s->dma_adc.count >= s->dma_adc.fragsize)
wake_up(&s->dma_adc.wait);
} else {
- if (s->dma_adc.count > s->dma_adc.dmasize - ((3 * s->dma_adc.fragsize) >> 1)) {
+ if (s->dma_adc.count > (signed)(s->dma_adc.dmasize - ((3 * s->dma_adc.fragsize) >> 1))) {
s->ctrl &= ~CTRL_ADC_EN;
outl(s->ctrl, s->io+ES1371_REG_CONTROL);
s->dma_adc.error++;
@@ -846,7 +854,7 @@ static void es1371_update_ptr(struct es1371_state *s)
s->dma_dac1.total_bytes += diff;
if (s->dma_dac1.mapped) {
s->dma_dac1.count += diff;
- if (s->dma_dac1.count >= s->dma_dac1.fragsize)
+ if (s->dma_dac1.count >= (signed)s->dma_dac1.fragsize)
wake_up(&s->dma_dac1.wait);
} else {
s->dma_dac1.count -= diff;
@@ -854,12 +862,12 @@ static void es1371_update_ptr(struct es1371_state *s)
s->ctrl &= ~CTRL_DAC1_EN;
outl(s->ctrl, s->io+ES1371_REG_CONTROL);
s->dma_dac1.error++;
- } else if (s->dma_dac1.count <= s->dma_dac1.fragsize && !s->dma_dac1.endcleared) {
+ } else if (s->dma_dac1.count <= (signed)s->dma_dac1.fragsize && !s->dma_dac1.endcleared) {
clear_advance(s->dma_dac1.rawbuf, s->dma_dac1.dmasize, s->dma_dac1.swptr,
s->dma_dac1.fragsize, (s->sctrl & SCTRL_P1SEB) ? 0 : 0x80);
s->dma_dac1.endcleared = 1;
}
- if (s->dma_dac1.count < s->dma_dac1.dmasize)
+ if (s->dma_dac1.count < (signed)s->dma_dac1.dmasize)
wake_up(&s->dma_dac1.wait);
}
}
@@ -869,7 +877,7 @@ static void es1371_update_ptr(struct es1371_state *s)
s->dma_dac2.total_bytes += diff;
if (s->dma_dac2.mapped) {
s->dma_dac2.count += diff;
- if (s->dma_dac2.count >= s->dma_dac2.fragsize)
+ if (s->dma_dac2.count >= (signed)s->dma_dac2.fragsize)
wake_up(&s->dma_dac2.wait);
} else {
s->dma_dac2.count -= diff;
@@ -877,12 +885,12 @@ static void es1371_update_ptr(struct es1371_state *s)
s->ctrl &= ~CTRL_DAC2_EN;
outl(s->ctrl, s->io+ES1371_REG_CONTROL);
s->dma_dac2.error++;
- } else if (s->dma_dac2.count <= s->dma_dac2.fragsize && !s->dma_dac2.endcleared) {
+ } else if (s->dma_dac2.count <= (signed)s->dma_dac2.fragsize && !s->dma_dac2.endcleared) {
clear_advance(s->dma_dac2.rawbuf, s->dma_dac2.dmasize, s->dma_dac2.swptr,
s->dma_dac2.fragsize, (s->sctrl & SCTRL_P2SEB) ? 0 : 0x80);
s->dma_dac2.endcleared = 1;
}
- if (s->dma_dac2.count < s->dma_dac2.dmasize)
+ if (s->dma_dac2.count < (signed)s->dma_dac2.dmasize)
wake_up(&s->dma_dac2.wait);
}
}
@@ -982,7 +990,7 @@ static const unsigned int recsrc[8] =
SOUND_MASK_PHONEIN
};
-static const unsigned char volreg[] =
+static const unsigned char volreg[SOUND_MIXER_NRDEVICES] =
{
/* 5 bit stereo */
[SOUND_MIXER_LINE] = 0x10,
@@ -1006,6 +1014,8 @@ static const unsigned char volreg[] =
[SOUND_MIXER_IGAIN] = 0x1e
};
+#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS
+
#define swab(x) ((((x) >> 8) & 0xff) | (((x) << 8) & 0xff00))
static int mixer_rdch(struct es1371_state *s, unsigned int ch, int *arg)
@@ -1093,6 +1103,34 @@ static int mixer_rdch(struct es1371_state *s, unsigned int ch, int *arg)
}
}
+#else /* OSS_DOCUMENTED_MIXER_SEMANTICS */
+
+static const unsigned char volidx[SOUND_MIXER_NRDEVICES] =
+{
+ /* 5 bit stereo */
+ [SOUND_MIXER_LINE] = 1,
+ [SOUND_MIXER_CD] = 2,
+ [SOUND_MIXER_VIDEO] = 3,
+ [SOUND_MIXER_LINE1] = 4,
+ [SOUND_MIXER_PCM] = 5,
+ /* 6 bit stereo */
+ [SOUND_MIXER_VOLUME] = 6,
+ [SOUND_MIXER_PHONEOUT] = 7,
+ /* 6 bit mono */
+ [SOUND_MIXER_OGAIN] = 8,
+ [SOUND_MIXER_PHONEIN] = 9,
+ /* 4 bit mono but shifted by 1 */
+ [SOUND_MIXER_SPEAKER] = 10,
+ /* 6 bit mono + preamp */
+ [SOUND_MIXER_MIC] = 11,
+ /* 4 bit stereo */
+ [SOUND_MIXER_RECLEV] = 12,
+ /* 4 bit mono */
+ [SOUND_MIXER_IGAIN] = 13
+};
+
+#endif /* OSS_DOCUMENTED_MIXER_SEMANTICS */
+
static int mixer_wrch(struct es1371_state *s, unsigned int ch, int val)
{
int i;
@@ -1295,7 +1333,13 @@ static int mixer_ioctl(struct es1371_state *s, unsigned int cmd, unsigned long a
i = _IOC_NR(cmd);
if (i >= SOUND_MIXER_NRDEVICES)
return -EINVAL;
+#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS
return mixer_rdch(s, i, (int *)arg);
+#else /* OSS_DOCUMENTED_MIXER_SEMANTICS */
+ if (!volidx[i])
+ return -EINVAL;
+ return put_user(s->mix.vol[volidx[i]-1], (int *)arg);
+#endif /* OSS_DOCUMENTED_MIXER_SEMANTICS */
}
}
if (_IOC_DIR(cmd) != (_IOC_READ|_IOC_WRITE))
@@ -1324,7 +1368,14 @@ static int mixer_ioctl(struct es1371_state *s, unsigned int cmd, unsigned long a
get_user_ret(val, (int *)arg, -EFAULT);
if (mixer_wrch(s, i, val))
return -EINVAL;
+#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS
return mixer_rdch(s, i, (int *)arg);
+#else /* OSS_DOCUMENTED_MIXER_SEMANTICS */
+ if (!volidx[i])
+ return -EINVAL;
+ s->mix.vol[volidx[i]-1] = val;
+ return put_user(s->mix.vol[volidx[i]-1], (int *)arg);
+#endif /* OSS_DOCUMENTED_MIXER_SEMANTICS */
}
}
@@ -1375,6 +1426,7 @@ static /*const*/ struct file_operations es1371_mixer_fops = {
&es1371_ioctl_mixdev,
NULL, /* mmap */
&es1371_open_mixdev,
+ NULL, /* flush */
&es1371_release_mixdev,
NULL, /* fsync */
NULL, /* fasync */
@@ -1585,7 +1637,7 @@ static unsigned int es1371_poll(struct file *file, struct poll_table_struct *wai
es1371_update_ptr(s);
if (file->f_flags & FMODE_READ) {
if (s->dma_adc.mapped) {
- if (s->dma_adc.count >= s->dma_adc.fragsize)
+ if (s->dma_adc.count >= (signed)s->dma_adc.fragsize)
mask |= POLLIN | POLLRDNORM;
} else {
if (s->dma_adc.count > 0)
@@ -1594,10 +1646,10 @@ static unsigned int es1371_poll(struct file *file, struct poll_table_struct *wai
}
if (file->f_flags & FMODE_WRITE) {
if (s->dma_dac2.mapped) {
- if (s->dma_dac2.count >= s->dma_dac2.fragsize)
+ if (s->dma_dac2.count >= (signed)s->dma_dac2.fragsize)
mask |= POLLOUT | POLLWRNORM;
} else {
- if (s->dma_dac2.dmasize > s->dma_dac2.count)
+ if ((signed)s->dma_dac2.dmasize > s->dma_dac2.count)
mask |= POLLOUT | POLLWRNORM;
}
}
@@ -2022,6 +2074,7 @@ static /*const*/ struct file_operations es1371_audio_fops = {
&es1371_ioctl,
&es1371_mmap,
&es1371_open,
+ NULL, /* flush */
&es1371_release,
NULL, /* fsync */
NULL, /* fasync */
@@ -2098,10 +2151,10 @@ static unsigned int es1371_poll_dac(struct file *file, struct poll_table_struct
spin_lock_irqsave(&s->lock, flags);
es1371_update_ptr(s);
if (s->dma_dac1.mapped) {
- if (s->dma_dac1.count >= s->dma_dac1.fragsize)
+ if (s->dma_dac1.count >= (signed)s->dma_dac1.fragsize)
mask |= POLLOUT | POLLWRNORM;
} else {
- if (s->dma_dac1.dmasize > s->dma_dac1.count)
+ if ((signed)s->dma_dac1.dmasize > s->dma_dac1.count)
mask |= POLLOUT | POLLWRNORM;
}
spin_unlock_irqrestore(&s->lock, flags);
@@ -2378,6 +2431,7 @@ static /*const*/ struct file_operations es1371_dac_fops = {
&es1371_ioctl_dac,
&es1371_mmap_dac,
&es1371_open_dac,
+ NULL, /* flush */
&es1371_release_dac,
NULL, /* fsync */
NULL, /* fasync */
@@ -2613,6 +2667,7 @@ static /*const*/ struct file_operations es1371_midi_fops = {
NULL, /* ioctl */
NULL, /* mmap */
&es1371_midi_open,
+ NULL, /* flush */
&es1371_midi_release,
NULL, /* fsync */
NULL, /* fasync */
@@ -2662,7 +2717,7 @@ __initfunc(int init_es1371(void))
if (!pci_present()) /* No PCI bus in this machine! */
return -ENODEV;
- printk(KERN_INFO "es1371: version v0.2 time " __TIME__ " " __DATE__ "\n");
+ printk(KERN_INFO "es1371: version v0.4 time " __TIME__ " " __DATE__ "\n");
while (index < NR_DEVICE &&
(pcidev = pci_find_device(PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1371, pcidev))) {
if (pcidev->base_address[0] == 0 ||
@@ -2818,11 +2873,7 @@ __initfunc(int init_es1371(void))
#ifdef MODULE
MODULE_PARM(joystick, "1-" __MODULE_STRING(NR_DEVICE) "i");
-MODULE_PARM_DESC(joystick, "if 1 enables joystick interface (still need separate driver)");
-MODULE_PARM(lineout, "1-" __MODULE_STRING(NR_DEVICE) "i");
-MODULE_PARM_DESC(lineout, "if 1 the LINE input is converted to LINE out");
-MODULE_PARM(micz, "1-" __MODULE_STRING(NR_DEVICE) "i");
-MODULE_PARM_DESC(micz, "changes (??) the microphone impedance");
+MODULE_PARM_DESC(joystick, "sets address and enables joystick interface (still need separate driver)");
MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");
MODULE_DESCRIPTION("ES1371 AudioPCI97 Driver");
diff --git a/drivers/sound/gus_wave.c b/drivers/sound/gus_wave.c
index c15bced88..c73e6f06b 100644
--- a/drivers/sound/gus_wave.c
+++ b/drivers/sound/gus_wave.c
@@ -3142,6 +3142,7 @@ void gus_wave_init(struct address_info *hw_config)
return;
}
+ hw_config->slots[4] = gus_devnum;
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# */
diff --git a/drivers/sound/lowlevel/README b/drivers/sound/lowlevel/README
index 86c93b55b..76fba8dee 100644
--- a/drivers/sound/lowlevel/README
+++ b/drivers/sound/lowlevel/README
@@ -11,7 +11,8 @@ Hannu Savolainen (hannu@voxware.pp.fi) for more info.
The following low level drivers are included:
- ACI MIXER for miroPCM12 by Markus Kuhn
-(mskuhn@cip.informatik.uni-erlangen.de).
+ (mskuhn@cip.informatik.uni-erlangen.de).
+- Audio Excel DSP 16 initialization driver by Riccardo Facchetti
+ (fizban@tin.it)
- SB32/AWE synthesizer driver (Emu8000) by Takashi Iwai
-(iwai@dragon.mm.t.u-tokyo.ac.jp). See README.awe for more
-info.
+ (iwai@dragon.mm.t.u-tokyo.ac.jp). See README.awe for more info.
diff --git a/drivers/sound/lowlevel/README.aedsp16 b/drivers/sound/lowlevel/README.aedsp16
deleted file mode 100644
index 8f5b05afd..000000000
--- a/drivers/sound/lowlevel/README.aedsp16
+++ /dev/null
@@ -1,137 +0,0 @@
-Driver
-------
-
-Informations about Audio Excel DSP 16 driver can be found in the source
-file lowlevel/aedsp16.c
-Please, read the head of the source before using it. It contain useful
-informations.
-
-Configuration
--------------
-
-The Audio Excel configuration, is now done with the standard Linux setup.
-You have to configure the sound card (Sound Blaster or Microsoft Sound System)
-and, if you want it, the Roland MPU-401 (do not use the Sound Blaster MPU-401,
-SB-MPU401) in the main driver menu. Activate the lowlevel drivers then select
-the Audio Excel hardware that you want to initialize. Check the IRQ/DMA/MIRQ
-of the Audio Excel initialization: it must be the same as the SBPRO (or MSS)
-setup. If the parameters are different, correct it.
-I you own a Gallant's audio card based on SC-6600, activate the SC-6600 support.
-If you want to change the configuration of the sound board, be sure to
-check off all the configuration items before re-configure it.
-
-Module parameters
------------------
-To use this driver as a module, you must configure some module parameters, to
-set up I/O addresses, IRQ lines and DMA channels. Some parameters are
-mandatory while some others are optional. Here a list of parameters you can
-use with this module:
-
-Name Description
-==== ===========
-MANDATORY
-io I/O base address (0x220 or 0x240)
-irq irq line (5, 7, 9, 10 or 11)
-dma dma channel (0, 1 or 3)
-
-OPTIONAL
-mss_base I/O base address for activate MSS mode (default SBPRO)
- (0x530 or 0xE80)
-mpu_base I/O base address for activate MPU-401 mode
- (0x300, 0x310, 0x320 or 0x330)
-mpu_irq MPU-401 irq line (5, 7, 9, 10 or 0)
-
-The /etc/conf.modules will have a line like this:
-
-options aedsp16 io=0x220 irq=10 dma=3 mss_base=0x530
-
-Of course, you must write the 'options' for all other subsequent modules,
-opl3, ad1848, adlib_card, sb
-
-Then you must load the sound modules stack in this order:
-sound -> aedsp16 -> [ ad1848, opl3 ]
-
-Sound cards supported
----------------------
-This driver supports the SC-6000 and SC-6600 based Gallant's sound card.
-It don't support the Audio Excel DSP 16 III (try the SC-6600 code).
-I'm working on the III version of the card: if someone have useful
-informations about it, please let me know.
-For all the non-supported audio cards, you have to boot MS-DOS (or WIN95)
-activating the audio card with the MS-DOS device driver, then you have to
-<ctrl>-<alt>-<del> and boot Linux.
-Follow these steps:
-
-1) Compile Linux kernel with standard sound driver, using the emulation
- you want, with the parameters of your audio card,
- e.g. Microsoft Sound System irq10 dma3
-2) Install your new kernel as the default boot kernel.
-3) Boot MS-DOS and configure the audio card with the boot time device
- driver, for MSS irq10 dma3 in our example.
-4) <ctrl>-<alt>-<del> and boot Linux. This will mantain the DOS configuration
- and will boot the new kernel with sound driver. The sound driver will find
- the audio card and will recognize and attach it.
-
-Reports on User successes
--------------------------
-
-[--------------------------------------------------------------------------]
-
-From POPmail Mon Jul 29 18:23:12 1996
-Received: from cdc8g5.cdc.polimi.it by mbox.vol.it with SMTP
- (1.39.111.2/16.2) id AA257995686; Mon, 29 Jul 1996 09:34:46 +0200
-Return-Path: <sjg95@unixfe.rl.ac.uk>
-Received: from [130.246.12.16] by cdc8g5.cdc.polimi.it with SMTP
- (1.38.193.4/15.6) id AA27426; Mon, 29 Jul 1996 09:42:49 +0200
-Posted-Date: Mon, 29 Jul 1996 08:35:40 +0100
-Received-Date: Mon, 29 Jul 1996 09:42:49 +0200
-Received: (from sjg95@localhost) by unixfe.rl.ac.uk (8.7.3/8.7.3)
- id IAA58788 for riccardo@cdc8g5.cdc.polimi.it; Mon, 29 Jul 1996 08:35:40 +0100
-Date: Mon, 29 Jul 1996 08:35:40 +0100
-From: Mr S J Greenaway <sjg95@unixfe.rl.ac.uk>
-Message-Id: <199607290735.IAA58788@unixfe.rl.ac.uk>
-To: riccardo@cdc8g5.cdc.polimi.it (Riccardo Facchetti)
-Subject: Re: Audio Excel DSP 16 initialization code
-Newsgroups: comp.os.linux.announce
-X-Newsreader: TIN [version 1.2 PL2]
-Status: RO
-X-Status: A
-
-Just to let you know got my Audio Excel (emulating a MSS) working
-with my original SB16, thanks for the driver!
-
-/dev/sndstat:
-
-Linux huey 2.0.9 #10 Sat Jul 27 11:41:42 BST 1996 i586)
-Kernel: Linux huey 2.0.9 #14 Sun Jul 28 12:50:43 BST 1996 i586
-Config options: c0202
-
-Installed drivers:
-Type 10: MS Sound System
-Type 24: MS Sound System (AXP)
-Type 27: Compaq Deskpro XL
-Type 2: Sound Blaster
-
-Card config:
-MS Sound System at 0x530 irq 11 drq 3
-Sound Blaster at 0x240 irq 5 drq 1,5
-
-Audio devices:
-0: MSS audio codec (CS4231A)
-1: Sound Blaster 16 (4.12)
-
-Synth devices:
-
-Midi devices: NOT ENABLED IN CONFIG
-
-Timers:
-0: System clock
-1: MSS audio codec (CS4231A)
-
-Mixers:
-0: MSS audio codec (CS4231A)
-1: Sound Blaster
-
-[--------------------------------------------------------------------------]
-
- Riccardo
diff --git a/drivers/sound/lowlevel/aci.c b/drivers/sound/lowlevel/aci.c
index d46088b8e..c65fbd84a 100644
--- a/drivers/sound/lowlevel/aci.c
+++ b/drivers/sound/lowlevel/aci.c
@@ -4,17 +4,25 @@
* ACI is a protocol used to communicate with the microcontroller on
* some sound cards produced by miro, e.g. the miroSOUND PCM12 and
* PCM20. The ACI has been developed for miro by Norberto Pellicci
- * <pellicci@ix.netcom.com>. Special thanks to both him and miro for
+ * <pellicci@home.com>. Special thanks to both him and miro for
* providing the ACI specification.
*
* The main function of the ACI is to control the mixer and to get a
* product identification. On the PCM20, ACI also controls the radio
- * tuner on this card, however this is not yet supported in this
- * software.
+ * tuner on this card, this is supported in the Video for Linux
+ * radio-miropcm20 driver.
*
* This Voxware ACI driver currently only supports the ACI functions
- * on the miroSOUND PCM12 card. Support for miro sound cards with
- * additional ACI functions can easily be added later.
+ * on the miroSOUND PCM12 and PCM20 card. Support for miro sound cards
+ * with additional ACI functions can easily be added later.
+ *
+ * / NOTE / When compiling as a module, make sure to load the module
+ * after loading the mad16 module. The initialisation code expects the
+ * MAD16 default mixer to be already available.
+ *
+ * / NOTE / When compiling as a module, make sure to load the module
+ * after loading the mad16 module. The initialisation code expects the
+ * MAD16 default mixer to be already available.
*
* Revision history:
*
@@ -27,6 +35,9 @@
* 1996-05-28 Markus Kuhn
* Initialize CS4231A mixer, make ACI first mixer,
* use new private mixer API for solo mode.
+ * 1998-08-18 Ruurd Reitsma <R.A.Reitsma@wbmt.tudelft.nl>
+ * Small modification to export ACI functions and
+ * complete modularisation.
*/
/*
@@ -59,10 +70,11 @@
*/
#include <linux/config.h> /* for CONFIG_ACI_MIXER */
+#include <linux/module.h>
#include "lowlevel.h"
#include "../sound_config.h"
-#include "lowlevel.h"
-#ifdef CONFIG_ACI_MIXER
+
+#if defined(CONFIG_ACI_MIXER) || defined(CONFIG_ACI_MIXER_MODULE)
#undef DEBUG /* if defined, produce a verbose report via syslog */
@@ -77,7 +89,7 @@ static int aci_present = 0;
#ifdef MODULE /* Whether the aci mixer is to be reset. */
int aci_reset = 0; /* Default: don't reset if the driver is a */
MODULE_PARM(aci_reset,"i");
-#else /* module; use "insmod sound.o aci_reset=1" */
+#else /* module; use "insmod aci.o aci_reset=1" */
int aci_reset = 1; /* to override. */
#endif
@@ -143,12 +155,12 @@ static int read_general_status(void)
* If a problem occurred, they return -1.
*/
-static int implied_cmd(unsigned char opcode)
+int aci_implied_cmd(unsigned char opcode)
{
unsigned long flags;
#ifdef DEBUG
- printk("ACI: implied_cmd(0x%02x)\n", opcode);
+ printk("ACI: aci_implied_cmd(0x%02x)\n", opcode);
#endif
save_flags(flags);
@@ -165,13 +177,13 @@ static int implied_cmd(unsigned char opcode)
}
-static int write_cmd(unsigned char opcode, unsigned char parameter)
+int aci_write_cmd(unsigned char opcode, unsigned char parameter)
{
unsigned long flags;
int status;
#ifdef DEBUG
- printk("ACI: write_cmd(0x%02x, 0x%02x)\n", opcode, parameter);
+ printk("ACI: aci_write_cmd(0x%02x, 0x%02x)\n", opcode, parameter);
#endif
save_flags(flags);
@@ -202,8 +214,53 @@ static int write_cmd(unsigned char opcode, unsigned char parameter)
return 0;
}
+/*
+ * This write command send 2 parameters instead of one.
+ * Only used in PCM20 radio frequency tuning control
+ */
+
+int aci_write_cmd_d(unsigned char opcode, unsigned char parameter, unsigned char parameter2)
+{
+ unsigned long flags;
+ int status;
+
+#ifdef DEBUG
+ printk("ACI: aci_write_cmd_d(0x%02x, 0x%02x)\n", opcode, parameter, parameter2);
+#endif
+
+ save_flags(flags);
+ cli();
+
+ if (read_general_status() < 0 || busy_wait()) {
+ restore_flags(flags);
+ return -1;
+ }
+ outb_p(opcode, COMMAND_REGISTER);
+ if (busy_wait()) { restore_flags(flags); return -1; }
+ outb_p(parameter, COMMAND_REGISTER);
+ if (busy_wait()) { restore_flags(flags); return -1; }
+ outb_p(parameter2, COMMAND_REGISTER);
+
+ if ((status = read_general_status()) < 0) {
+ restore_flags(flags);
+ return -1;
+ }
+ /* polarity of the INVALID flag depends on ACI version */
+ if ((aci_version < 0xb0 && (status & 0x40) != 0) ||
+ (aci_version >= 0xb0 && (status & 0x40) == 0)) {
+ restore_flags(flags);
+#if 0 /* Frequency tuning works, but the INVALID flag is set ??? */
+ printk("ACI: invalid write (double) command 0x%02x, 0x%02x, 0x%02x.\n",
+ opcode, parameter, parameter2);
+#endif
+ return -1;
+ }
+
+ restore_flags(flags);
+ return 0;
+}
-static int read_cmd(unsigned char opcode, int length, unsigned char *parameter)
+int aci_read_cmd(unsigned char opcode, int length, unsigned char *parameter)
{
unsigned long flags;
int i = 0;
@@ -219,10 +276,10 @@ static int read_cmd(unsigned char opcode, int length, unsigned char *parameter)
parameter[i++] = inb_p(STATUS_REGISTER);
#ifdef DEBUG
if (i == 1)
- printk("ACI: read_cmd(0x%02x, %d) = 0x%02x\n", opcode, length,
+ printk("ACI: aci_read_cmd(0x%02x, %d) = 0x%02x\n", opcode, length,
parameter[i-1]);
else
- printk("ACI: read_cmd cont.: 0x%02x\n", parameter[i-1]);
+ printk("ACI: aci_read_cmd cont.: 0x%02x\n", parameter[i-1]);
#endif
}
@@ -231,7 +288,7 @@ static int read_cmd(unsigned char opcode, int length, unsigned char *parameter)
}
-static int indexed_cmd(unsigned char opcode, unsigned char index,
+int aci_indexed_cmd(unsigned char opcode, unsigned char index,
unsigned char *parameter)
{
unsigned long flags;
@@ -249,7 +306,7 @@ static int indexed_cmd(unsigned char opcode, unsigned char index,
if (busy_wait()) { restore_flags(flags); return -1; }
*parameter = inb_p(STATUS_REGISTER);
#ifdef DEBUG
- printk("ACI: indexed_cmd(0x%02x, 0x%02x) = 0x%02x\n", opcode, index,
+ printk("ACI: aci_indexed_cmd(0x%02x, 0x%02x) = 0x%02x\n", opcode, index,
*parameter);
#endif
@@ -285,10 +342,10 @@ static int getvolume(caddr_t arg,
unsigned char buf;
/* left channel */
- if (indexed_cmd(0xf0, left_index, &buf)) return -EIO;
+ if (aci_indexed_cmd(0xf0, left_index, &buf)) return -EIO;
vol = SCALE(0x20, 100, buf < 0x20 ? 0x20-buf : 0);
/* right channel */
- if (indexed_cmd(0xf0, right_index, &buf)) return -EIO;
+ if (aci_indexed_cmd(0xf0, right_index, &buf)) return -EIO;
vol |= SCALE(0x20, 100, buf < 0x20 ? 0x20-buf : 0) << 8;
return (*(int *) arg = vol);
@@ -304,13 +361,13 @@ static int setvolume(caddr_t arg,
vol = *(int *)arg & 0xff;
if (vol > 100) vol = 100;
vol = SCALE(100, 0x20, vol);
- if (write_cmd(left_index, 0x20 - vol)) return -EIO;
+ if (aci_write_cmd(left_index, 0x20 - vol)) return -EIO;
ret = SCALE(0x20, 100, vol);
/* right channel */
vol = (*(int *)arg >> 8) & 0xff;
if (vol > 100) vol = 100;
vol = SCALE(100, 0x20, vol);
- if (write_cmd(right_index, 0x20 - vol)) return -EIO;
+ if (aci_write_cmd(right_index, 0x20 - vol)) return -EIO;
ret |= SCALE(0x20, 100, vol) << 8;
return (*(int *) arg = ret);
@@ -327,7 +384,7 @@ aci_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg)
if (cmd == SOUND_MIXER_PRIVATE1) {
if (*(int *) arg >= 0) {
aci_solo = !!*(int *) arg;
- if (write_cmd(0xd2, aci_solo)) return -EIO;
+ if (aci_write_cmd(0xd2, aci_solo)) return -EIO;
} else if (aci_version >= 0xb0) {
if ((status = read_general_status()) < 0) return -EIO;
return (*(int *) arg = (status & 0x20) == 0);
@@ -359,7 +416,7 @@ aci_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg)
vol = *(int *) arg & 0xff;
if (vol > 100) vol = 100;
vol = SCALE(100, 3, vol);
- if (write_cmd(0x03, vol)) return -EIO;
+ if (aci_write_cmd(0x03, vol)) return -EIO;
vol = SCALE(3, 100, vol);
return (*(int *) arg = vol | (vol << 8));
case SOUND_MIXER_RECSRC:
@@ -414,7 +471,7 @@ aci_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg)
case SOUND_MIXER_LINE2: /* AUX2 */
return getvolume(arg, 0x13, 0x12);
case SOUND_MIXER_IGAIN: /* MIC pre-amp */
- if (indexed_cmd(0xf0, 0x21, &buf)) return -EIO;
+ if (aci_indexed_cmd(0xf0, 0x21, &buf)) return -EIO;
vol = SCALE(3, 100, buf <= 3 ? buf : 3);
vol |= vol << 8;
return (*(int *) arg = vol);
@@ -478,13 +535,13 @@ int attach_aci(void)
return 0;
}
- if (read_cmd(0xf2, 2, aci_idcode)) {
+ if (aci_read_cmd(0xf2, 2, aci_idcode)) {
#ifdef DEBUG
printk("ACI: Failed to read idcode.\n");
#endif
return 0;
}
- if (read_cmd(0xf1, 1, &aci_version)) {
+ if (aci_read_cmd(0xf1, 1, &aci_version)) {
#ifdef DEBUG
printk("ACI: Failed to read version.\n");
#endif
@@ -516,7 +573,7 @@ int attach_aci(void)
if (aci_reset) {
/* initialize ACI mixer */
- implied_cmd(0xff);
+ aci_implied_cmd(0xff);
aci_solo = 0;
}
@@ -606,3 +663,17 @@ void unload_aci(void)
}
#endif
+
+#if defined(MODULE)
+
+int init_module(void) {
+ attach_aci();
+ return(0);
+}
+
+void cleanup_module(void) {
+ unload_aci();
+}
+
+#endif /* MODULE */
+
diff --git a/drivers/sound/lowlevel/aedsp16.c b/drivers/sound/lowlevel/aedsp16.c
index cb919507e..48ef93f19 100644
--- a/drivers/sound/lowlevel/aedsp16.c
+++ b/drivers/sound/lowlevel/aedsp16.c
@@ -26,6 +26,7 @@
#include <linux/config.h>
#include <linux/delay.h>
#include <linux/module.h>
+#include <linux/init.h>
#include "../sound_config.h"
#include "../soundmodule.h"
@@ -248,6 +249,10 @@
the flexibility of modular version, I have removed all the conditional
compilation for SBPRO, MPU and MSS code. Now it is all managed with
the ae_config structure.
+ v1.2
+ - Module informations added.
+ - Removed aedsp16_delay_10msec(), now using mdelay(10)
+ - All data and funcs moved to .*.init section.
Known Problems:
- Audio Excel DSP 16 III don't work with this driver.
@@ -259,7 +264,7 @@
*/
-#define VERSION "1.1" /* Version of Audio Excel DSP 16 driver */
+#define VERSION "1.2" /* Version of Audio Excel DSP 16 driver */
#undef AEDSP16_DEBUG 1 /* Define this to enable debug code */
#undef AEDSP16_DEBUG_MORE 1 /* Define this to enable more debug */
@@ -421,14 +426,14 @@
#define INIT_MSS (1<<1)
#define INIT_MPU401 (1<<2)
-static int soft_cfg = 0; /* Will contain or'ed values of soft cf */
-static int soft_cfg_1 = 0; /* Will contain or'ed values of some cf */
-static int gc = 0; /* generic counter (utility counter) */
-static int ver[3]; /* DSP Version, hi<-ver[0], lo<-ver[1] */
+static int soft_cfg __initdata = 0; /* bitmapped config */
+static int soft_cfg_mss __initdata = 0; /* bitmapped mss config */
+static int ver[CARDVERLEN] __initdata = {0, 0}; /* DSP Ver:
+ hi->ver[0] lo->ver[1] */
#if defined(CONFIG_SC6600)
static int hard_cfg[2] /* lo<-hard_cfg[0] hi<-hard_cfg[1] */
- = { 0, 0};
+ __initdata = { 0, 0};
#endif /* CONFIG_SC6600 */
#if defined(CONFIG_SC6600)
@@ -440,7 +445,10 @@ struct d_hcfg {
int wssbase;
int cdrom;
int cdrombase;
-} decoded_hcfg;
+};
+
+struct d_hcfg decoded_hcfg __initdata = {0, };
+
#endif /* CONFIG_SC6600 */
/* orVals contain the values to be or'ed */
@@ -464,7 +472,7 @@ struct aedsp16_info {
* Magic values that the DSP will eat when configuring irq/mirq/dma
*/
/* DSP IRQ conversion array */
-static struct orVals orIRQ[] = {
+static struct orVals orIRQ[] __initdata = {
{0x05, 0x28},
{0x07, 0x08},
{0x09, 0x10},
@@ -474,7 +482,7 @@ static struct orVals orIRQ[] = {
};
/* MPU-401 IRQ conversion array */
-static struct orVals orMIRQ[] = {
+static struct orVals orMIRQ[] __initdata = {
{0x05, 0x04},
{0x07, 0x44},
{0x09, 0x84},
@@ -483,14 +491,14 @@ static struct orVals orMIRQ[] = {
};
/* DMA Channels conversion array */
-static struct orVals orDMA[] = {
+static struct orVals orDMA[] __initdata = {
{0x00, 0x01},
{0x01, 0x02},
{0x03, 0x03},
{0x00, 0x00}
};
-static struct aedsp16_info ae_config = {
+static struct aedsp16_info ae_config __initdata = {
DEF_AEDSP16_IOB,
DEF_AEDSP16_IRQ,
DEF_AEDSP16_MRQ,
@@ -503,16 +511,10 @@ static struct aedsp16_info ae_config = {
/*
* Buffers to store audio card informations
*/
-static char DSPCopyright[CARDNAMELEN + 1];
-static char DSPVersion[CARDVERLEN + 1];
+static char DSPCopyright[CARDNAMELEN + 1] __initdata = {0, };
+static char DSPVersion[CARDVERLEN + 1] __initdata = {0, };
-static void aedsp16_delay_10msec(void)
-{
- for (gc = 0; gc < 1000; gc++)
- udelay(10);
-}
-
-static int aedsp16_wait_data(int port)
+static int __init aedsp16_wait_data(int port)
{
int loop = STATUSRETRY;
unsigned char ret = 0;
@@ -535,7 +537,7 @@ static int aedsp16_wait_data(int port)
return FALSE;
}
-static int aedsp16_read(int port)
+static int __init aedsp16_read(int port)
{
int inbyte;
@@ -553,12 +555,12 @@ static int aedsp16_read(int port)
return inbyte;
}
-static int aedsp16_test_dsp(int port)
+static int __init aedsp16_test_dsp(int port)
{
return ((aedsp16_read(port) == 0xaa) ? TRUE : FALSE);
}
-static int aedsp16_dsp_reset(int port)
+static int __init aedsp16_dsp_reset(int port)
{
/*
* Reset DSP
@@ -579,7 +581,7 @@ static int aedsp16_dsp_reset(int port)
return FALSE;
}
-static int aedsp16_write(int port, int cmd)
+static int __init aedsp16_write(int port, int cmd)
{
unsigned char ret;
int loop = HARDRETRY;
@@ -607,7 +609,7 @@ static int aedsp16_write(int port, int cmd)
#if defined(CONFIG_SC6600)
#if defined(AEDSP16_INFO) || defined(AEDSP16_DEBUG)
-void aedsp16_pinfo(void) {
+void __init aedsp16_pinfo(void) {
DBG(("\n Base address: %x\n", decoded_hcfg.iobase));
DBG((" Joystick : %s present\n", decoded_hcfg.joystick?"":" not"));
DBG((" WSS addr : %x\n", decoded_hcfg.wssbase));
@@ -617,7 +619,7 @@ void aedsp16_pinfo(void) {
}
#endif
-void aedsp16_hard_decode(void) {
+void __init aedsp16_hard_decode(void) {
DBG((" aedsp16_hard_decode: 0x%x, 0x%x\n", hard_cfg[0], hard_cfg[1]));
@@ -661,7 +663,7 @@ void aedsp16_hard_decode(void) {
DBG(("success.\n"));
}
-void aedsp16_hard_encode(void) {
+void __init aedsp16_hard_encode(void) {
DBG((" aedsp16_hard_encode: 0x%x, 0x%x\n", hard_cfg[0], hard_cfg[1]));
@@ -686,7 +688,7 @@ void aedsp16_hard_encode(void) {
}
-static int aedsp16_hard_write(int port) {
+static int __init aedsp16_hard_write(int port) {
DBG(("aedsp16_hard_write:\n"));
@@ -721,7 +723,7 @@ static int aedsp16_hard_write(int port) {
return TRUE;
}
-static int aedsp16_hard_read(int port) {
+static int __init aedsp16_hard_read(int port) {
DBG(("aedsp16_hard_read:\n"));
@@ -755,7 +757,7 @@ static int aedsp16_hard_read(int port) {
return TRUE;
}
-static int aedsp16_ext_cfg_write(int port) {
+static int __init aedsp16_ext_cfg_write(int port) {
int extcfg, val;
@@ -809,7 +811,7 @@ static int aedsp16_ext_cfg_write(int port) {
#endif /* CONFIG_SC6600 */
-static int aedsp16_cfg_write(int port) {
+static int __init aedsp16_cfg_write(int port) {
if (aedsp16_write(port, WRITE_MDIRQ_CFG)) {
printk("[AEDSP16] CMD 0x%x: failed!\n", WRITE_MDIRQ_CFG);
return FALSE;
@@ -821,11 +823,11 @@ static int aedsp16_cfg_write(int port) {
return TRUE;
}
-static int aedsp16_init_mss(int port)
+static int __init aedsp16_init_mss(int port)
{
DBG(("aedsp16_init_mss:\n"));
- aedsp16_delay_10msec();
+ mdelay(10);
if (aedsp16_write(port, DSP_INIT_MSS)) {
printk("[AEDSP16] aedsp16_init_mss [0x%x]: failed!\n",
@@ -833,19 +835,20 @@ static int aedsp16_init_mss(int port)
DBG(("failure.\n"));
return FALSE;
}
- aedsp16_delay_10msec();
+
+ mdelay(10);
if (aedsp16_cfg_write(port) == FALSE)
return FALSE;
- outb(soft_cfg_1, ae_config.mss_base);
+ outb(soft_cfg_mss, ae_config.mss_base);
DBG(("success.\n"));
return TRUE;
}
-static int aedsp16_setup_board(int port) {
+static int __init aedsp16_setup_board(int port) {
int loop = RETRY;
#if defined(CONFIG_SC6600)
@@ -873,7 +876,7 @@ static int aedsp16_setup_board(int port) {
printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_88);
return FALSE;
}
- aedsp16_delay_10msec();
+ mdelay(10);
} while ((aedsp16_wait_data(port) == FALSE) && loop--);
if (aedsp16_read(port) == -1) {
@@ -934,7 +937,7 @@ static int aedsp16_setup_board(int port) {
return TRUE;
}
-static int aedsp16_stdcfg(int port) {
+static int __init aedsp16_stdcfg(int port) {
if (aedsp16_write(port, WRITE_MDIRQ_CFG)) {
printk("[AEDSP16] CMD 0x%x: failed!\n", WRITE_MDIRQ_CFG);
return FALSE;
@@ -949,7 +952,7 @@ static int aedsp16_stdcfg(int port) {
return TRUE;
}
-static int aedsp16_dsp_version(int port)
+static int __init aedsp16_dsp_version(int port)
{
int len = 0;
int ret;
@@ -980,7 +983,7 @@ static int aedsp16_dsp_version(int port)
return TRUE;
}
-static int aedsp16_dsp_copyright(int port)
+static int __init aedsp16_dsp_copyright(int port)
{
int len = 0;
int ret;
@@ -1016,29 +1019,31 @@ static int aedsp16_dsp_copyright(int port)
return TRUE;
}
-static void aedsp16_init_tables(void)
+static void __init aedsp16_init_tables(void)
{
+ int i = 0;
+
memset(DSPCopyright, 0, CARDNAMELEN + 1);
memset(DSPVersion, 0, CARDVERLEN + 1);
- for (gc = 0; orIRQ[gc].or; gc++)
- if (orIRQ[gc].val == ae_config.irq) {
- soft_cfg |= orIRQ[gc].or;
- soft_cfg_1 |= orIRQ[gc].or;
+ for (i = 0; orIRQ[i].or; i++)
+ if (orIRQ[i].val == ae_config.irq) {
+ soft_cfg |= orIRQ[i].or;
+ soft_cfg_mss |= orIRQ[i].or;
}
- for (gc = 0; orMIRQ[gc].or; gc++)
- if (orMIRQ[gc].or == ae_config.mpu_irq)
- soft_cfg |= orMIRQ[gc].or;
+ for (i = 0; orMIRQ[i].or; i++)
+ if (orMIRQ[i].or == ae_config.mpu_irq)
+ soft_cfg |= orMIRQ[i].or;
- for (gc = 0; orDMA[gc].or; gc++)
- if (orDMA[gc].val == ae_config.dma) {
- soft_cfg |= orDMA[gc].or;
- soft_cfg_1 |= orDMA[gc].or;
+ for (i = 0; orDMA[i].or; i++)
+ if (orDMA[i].val == ae_config.dma) {
+ soft_cfg |= orDMA[i].or;
+ soft_cfg_mss |= orDMA[i].or;
}
}
-static int aedsp16_init_board(void)
+static int __init aedsp16_init_board(void)
{
aedsp16_init_tables();
@@ -1134,12 +1139,12 @@ static int aedsp16_init_board(void)
printk("]\n");
#endif /* MODULE || AEDSP16_INFO || AEDSP16_DEBUG */
- aedsp16_delay_10msec();
+ mdelay(10);
return TRUE;
}
-static int init_aedsp16_sb(void)
+static int __init init_aedsp16_sb(void)
{
DBG(("init_aedsp16_sb: "));
@@ -1159,7 +1164,7 @@ static int init_aedsp16_sb(void)
return TRUE;
}
-static void uninit_aedsp16_sb(void)
+static void __init uninit_aedsp16_sb(void)
{
DBG(("uninit_aedsp16_sb: "));
@@ -1168,7 +1173,7 @@ static void uninit_aedsp16_sb(void)
DBG(("done.\n"));
}
-static int init_aedsp16_mss(void)
+static int __init init_aedsp16_mss(void)
{
DBG(("init_aedsp16_mss: "));
@@ -1207,7 +1212,7 @@ static int init_aedsp16_mss(void)
return TRUE;
}
-static void uninit_aedsp16_mss(void)
+static void __init uninit_aedsp16_mss(void)
{
DBG(("uninit_aedsp16_mss: "));
@@ -1221,7 +1226,7 @@ static void uninit_aedsp16_mss(void)
DBG(("done.\n"));
}
-static int init_aedsp16_mpu(void)
+static int __init init_aedsp16_mpu(void)
{
DBG(("init_aedsp16_mpu: "));
@@ -1251,7 +1256,7 @@ static int init_aedsp16_mpu(void)
return TRUE;
}
-static void uninit_aedsp16_mpu(void)
+static void __init uninit_aedsp16_mpu(void)
{
DBG(("uninit_aedsp16_mpu: "));
@@ -1266,7 +1271,7 @@ static void uninit_aedsp16_mpu(void)
DBG(("done.\n"));
}
-int init_aedsp16(void)
+int __init init_aedsp16(void)
{
int initialized = FALSE;
@@ -1324,7 +1329,7 @@ int init_aedsp16(void)
return initialized;
}
-void uninit_aedsp16(void)
+void __init uninit_aedsp16(void)
{
if (ae_config.mss_base != -1)
uninit_aedsp16_mss();
@@ -1344,12 +1349,20 @@ int mss_base = -1;
int mpu_base = -1;
-MODULE_PARM(io,"i");
-MODULE_PARM(irq,"i");
-MODULE_PARM(dma,"i");
-MODULE_PARM(mpu_irq,"i");
-MODULE_PARM(mss_base,"i");
-MODULE_PARM(mpu_base,"i");
+MODULE_PARM(io, "i");
+MODULE_PARM_DESC(io, "I/O base address (0x220 0x240)");
+MODULE_PARM(irq, "i");
+MODULE_PARM_DESC(irq, "IRQ line (5 7 9 10 11)");
+MODULE_PARM(dma, "i");
+MODULE_PARM_DESC(dma, "dma line (0 1 3)");
+MODULE_PARM(mpu_irq, "i");
+MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ line (5 7 9 10 0)");
+MODULE_PARM(mss_base, "i");
+MODULE_PARM_DESC(mss_base, "MSS emulation I/O base address (0x530 0xE80)");
+MODULE_PARM(mpu_base, "i");
+MODULE_PARM_DESC(mpu_base,"MPU-401 I/O base address (0x300 0x310 0x320 0x330)");
+MODULE_AUTHOR("Riccardo Facchetti <fizban@tin.it>");
+MODULE_DESCRIPTION("Audio Excel DSP 16 Driver Version " VERSION);
int init_module(void) {
printk("Audio Excel DSP 16 init driver Copyright (C) Riccardo Facchetti 1995-98\n");
diff --git a/drivers/sound/lowlevel/awe_compat.h b/drivers/sound/lowlevel/awe_compat.h
index d0c34a1fa..0107bd2c1 100644
--- a/drivers/sound/lowlevel/awe_compat.h
+++ b/drivers/sound/lowlevel/awe_compat.h
@@ -92,7 +92,7 @@ static void *my_realloc(void *buf, int oldsize, int size)
get_user(target, (unsigned char*)&((addr)[offs]))
#define GET_SHORT_FROM_USER(target,addr,offs) \
get_user(target, (unsigned short*)&((addr)[offs]))
-#ifdef AWE_OSS38
+#ifdef AWE_OSS38_AND_IM_A_BANANA
#define IOCTL_TO_USER(target,offs,source,count) \
memcpy(target, (source)+(offs), count)
#define IO_WRITE_CHECK(cmd) (_SIOC_DIR(cmd) & _IOC_WRITE)
diff --git a/drivers/sound/lowlevel/miroaci.h b/drivers/sound/lowlevel/miroaci.h
new file mode 100644
index 000000000..9d64eaa1e
--- /dev/null
+++ b/drivers/sound/lowlevel/miroaci.h
@@ -0,0 +1,6 @@
+extern int aci_implied_cmd(unsigned char opcode);
+extern int aci_write_cmd(unsigned char opcode, unsigned char parameter);
+extern int aci_write_cmd_d(unsigned char opcode, unsigned char parameter, unsigned char parameter2);
+extern int aci_read_cmd(unsigned char opcode, int length, unsigned char *parameter);
+extern int aci_indexed_cmd(unsigned char opcode, unsigned char index, unsigned char *parameter);
+
diff --git a/drivers/sound/lowlevel/soundlow.c b/drivers/sound/lowlevel/soundlow.c
index 64ac00ccd..96fdb94be 100644
--- a/drivers/sound/lowlevel/soundlow.c
+++ b/drivers/sound/lowlevel/soundlow.c
@@ -5,6 +5,7 @@
#include "lowlevel.h"
#include <linux/config.h>
#include <linux/module.h>
+#include <linux/init.h>
#include "../soundvers.h"
#ifdef LOWLEVEL_MODULE
@@ -15,8 +16,8 @@ extern int attach_aci(void);
extern void unload_aci(void);
extern int attach_awe(void);
extern void unload_awe(void);
-extern int init_aedsp16(void);
-extern void uninit_aedsp16(void);
+extern int init_aedsp16(void) __init;
+extern void uninit_aedsp16(void) __init;
/*
* There are two places where you can insert initialization calls of
diff --git a/drivers/sound/msnd.c b/drivers/sound/msnd.c
index 8c0f99ed8..ad7ceaa48 100644
--- a/drivers/sound/msnd.c
+++ b/drivers/sound/msnd.c
@@ -20,7 +20,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * $Id: msnd.c,v 1.5 1998/07/18 00:12:15 andrewtv Exp $
+ * $Id: msnd.c,v 1.9 1998/09/04 18:41:27 andrewtv Exp $
*
********************************************************************/
@@ -168,16 +168,8 @@ int msnd_fifo_write(msnd_fifo *f, const char *buf, size_t len, int user)
}
if (user) {
-#ifdef LINUX20
- if (verify_area(VERIFY_READ, buf , nwritten))
- return nwritten;
-
- memcpy_fromfs(f->data + f->tail, buf, nwritten);
-#else
if (copy_from_user(f->data + f->tail, buf, nwritten))
return -EFAULT;
-#endif
-
} else
memcpy(f->data + f->tail, buf, nwritten);
@@ -214,15 +206,8 @@ int msnd_fifo_read(msnd_fifo *f, char *buf, size_t len, int user)
}
if (user) {
-#ifdef LINUX20
- if (verify_area(VERIFY_WRITE, buf, nread))
- return nread;
-
- memcpy_tofs(buf, f->data + f->head, nread);
-#else
if (copy_to_user(buf, f->data + f->head, nread))
return -EFAULT;
-#endif
} else
memcpy(buf, f->data + f->head, nread);
@@ -356,8 +341,10 @@ int msnd_disable_irq(multisound_dev_t *dev)
if (--dev->irq_ref > 0)
return 0;
- if (dev->irq_ref < 0)
- dev->irq_ref = 0;
+ if (dev->irq_ref < 0) {
+ printk(KERN_WARNING LOGNAME ": IRQ ref count is %d\n", dev->irq_ref);
+/* dev->irq_ref = 0; */
+ }
printk(KERN_DEBUG LOGNAME ": Disabling IRQ\n");
diff --git a/drivers/sound/msnd.h b/drivers/sound/msnd.h
index b0a330ca4..804cff425 100644
--- a/drivers/sound/msnd.h
+++ b/drivers/sound/msnd.h
@@ -24,16 +24,16 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * $Id: msnd.h,v 1.6 1998/07/18 00:12:15 andrewtv Exp $
+ * $Id: msnd.h,v 1.18 1998/09/04 18:43:40 andrewtv Exp $
*
********************************************************************/
#ifndef __MSND_H
#define __MSND_H
-#define VERSION "0.7.0"
+#define VERSION "0.7.13"
#define DEFSAMPLERATE DSP_DEFAULT_SPEED
-#define DEFSAMPLESIZE 8
+#define DEFSAMPLESIZE AFMT_U8
#define DEFCHANNELS 1
#define DEFFIFOSIZE 64
@@ -142,9 +142,9 @@
#define HDEX_MIDI_OUT_STOP (9 + HDEX_BASE)
#define HDEX_AUX_REQ (10 + HDEX_BASE)
-#define HIWORD(l) ((WORD)((((DWORD)(l)) >> 16) & 0xFFFF ))
+#define HIWORD(l) ((WORD)((((DWORD)(l)) >> 16) & 0xFFFF))
#define LOWORD(l) ((WORD)(DWORD)(l))
-#define HIBYTE(w) ((BYTE)(((WORD)(w) >> 8 ) & 0xFF ))
+#define HIBYTE(w) ((BYTE)(((WORD)(w) >> 8) & 0xFF))
#define LOBYTE(w) ((BYTE)(w))
#define MAKELONG(low,hi) ((long)(((WORD)(low))|(((DWORD)((WORD)(hi)))<<16)))
#define MAKEWORD(low,hi) ((WORD)(((BYTE)(low))|(((WORD)((BYTE)(hi)))<<8)))
@@ -166,33 +166,31 @@
# define spin_unlock_irqrestore(junk,flags) do { restore_flags(flags); } while (0)
#endif
-typedef unsigned char BYTE;
-typedef unsigned short USHORT;
-typedef unsigned short WORD;
-typedef unsigned int DWORD;
-typedef
-struct DAQueueDataStruct * LPDAQD;
-
-#define GCC_PACKED __attribute__ ((packed))
-
-struct JobQueueStruct {
- WORD wStart;
- WORD wSize;
- WORD wHead;
- WORD wTail;
-} GCC_PACKED;
-
-struct DAQueueDataStruct {
- WORD wStart;
- WORD wSize;
- WORD wFormat;
- WORD wSampleSize;
- WORD wChannels;
- WORD wSampleRate;
- WORD wIntMsg;
- WORD wFlags;
-} GCC_PACKED;
-
+/* JobQueueStruct */
+#define JQS_wStart 0x00
+#define JQS_wSize 0x02
+#define JQS_wHead 0x04
+#define JQS_wTail 0x06
+#define JQS__size 0x08
+
+/* DAQueueDataStruct */
+#define DAQDS_wStart 0x00
+#define DAQDS_wSize 0x02
+#define DAQDS_wFormat 0x04
+#define DAQDS_wSampleSize 0x06
+#define DAQDS_wChannels 0x08
+#define DAQDS_wSampleRate 0x0A
+#define DAQDS_wIntMsg 0x0C
+#define DAQDS_wFlags 0x0E
+#define DAQDS__size 0x10
+
+typedef u8 BYTE;
+typedef u16 USHORT;
+typedef u16 WORD;
+typedef u32 DWORD;
+typedef volatile BYTE * LPDAQD;
+
+/* Generic FIFO */
typedef struct {
size_t n, len;
char *data;
@@ -200,12 +198,12 @@ typedef struct {
} msnd_fifo;
typedef struct multisound_dev {
-
+ /* Linux device info */
char *name;
int dsp_minor, mixer_minor;
/* Hardware resources */
- unsigned int io, numio;
+ int io, numio;
int memid, irqid;
int irq, irq_ref;
unsigned char info;
@@ -214,16 +212,14 @@ typedef struct multisound_dev {
spinlock_t lock;
#endif
- /* MultiSound DDK variables */
- enum { msndClassic, msndPinnacle } type;
- struct SMA0_CommonData *SMA; /* diff. structure for classic vs. pinnacle */
- struct DAQueueDataStruct *CurDAQD;
- struct DAQueueDataStruct *CurDARQD;
- volatile WORD *pwDSPQData , *pwMIDQData , *pwMODQData;
- volatile struct JobQueueStruct *DAPQ , *DARQ , *MODQ , *MIDQ , *DSPQ;
- BYTE bCurrentMidiPatch;
+ /* Motorola 56k DSP SMA */
+ volatile BYTE *SMA;
+ volatile BYTE *CurDAQD, *CurDARQD;
+ volatile BYTE *DAPQ, *DARQ, *MODQ, *MIDQ, *DSPQ;
+ volatile WORD *pwDSPQData, *pwMIDQData, *pwMODQData;
/* State variables */
+ enum { msndClassic, msndPinnacle } type;
mode_t mode;
unsigned long flags;
#define F_BANKONE 0
@@ -236,27 +232,28 @@ typedef struct multisound_dev {
#define F_EXT_MIDI_INUSE 7
#define F_INT_MIDI_INUSE 8
#define F_WRITEFLUSH 9
-
+#define F_HAVEDIGITAL 10
struct wait_queue *writeblock, *readblock;
struct wait_queue *writeflush;
unsigned long recsrc;
int left_levels[16];
int right_levels[16];
+ int mixer_mod_count;
int calibrate_signal;
int sample_size;
int sample_rate;
int channels;
+ BYTE bCurrentMidiPatch;
void (*inc_ref)(void);
void (*dec_ref)(void);
/* Digital audio FIFOs */
- int fifosize;
msnd_fifo DAPF, DARF;
+ int fifosize;
int lastbank;
/* MIDI in callback */
void (*midi_in_interrupt)(struct multisound_dev *);
-
} multisound_dev_t;
#ifndef mdelay
diff --git a/drivers/sound/msnd_classic.h b/drivers/sound/msnd_classic.h
index 3ae0e0b3b..bdc28ffd0 100644
--- a/drivers/sound/msnd_classic.h
+++ b/drivers/sound/msnd_classic.h
@@ -24,7 +24,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * $Id: msnd_classic.h,v 1.5 1998/07/18 00:12:15 andrewtv Exp $
+ * $Id: msnd_classic.h,v 1.7 1998/09/03 06:39:47 andrewtv Exp $
*
********************************************************************/
#ifndef __MSND_CLASSIC_H
@@ -32,133 +32,133 @@
#include <linux/config.h>
-#define DSP_NUMIO 0x10
+#define DSP_NUMIO 0x10
-#define HP_MEMM 0x08
+#define HP_MEMM 0x08
-#define HP_BITM 0x0E
-#define HP_WAIT 0x0D
-#define HP_DSPR 0x0A
-#define HP_PROR 0x0B
-#define HP_BLKS 0x0C
+#define HP_BITM 0x0E
+#define HP_WAIT 0x0D
+#define HP_DSPR 0x0A
+#define HP_PROR 0x0B
+#define HP_BLKS 0x0C
-#define HPPRORESET_OFF 0
-#define HPPRORESET_ON 1
+#define HPPRORESET_OFF 0
+#define HPPRORESET_ON 1
-#define HPDSPRESET_OFF 0
-#define HPDSPRESET_ON 1
+#define HPDSPRESET_OFF 0
+#define HPDSPRESET_ON 1
-#define HPBLKSEL_0 0
-#define HPBLKSEL_1 1
+#define HPBLKSEL_0 0
+#define HPBLKSEL_1 1
-#define HPWAITSTATE_0 0
-#define HPWAITSTATE_1 1
+#define HPWAITSTATE_0 0
+#define HPWAITSTATE_1 1
-#define HPBITMODE_16 0
-#define HPBITMODE_8 1
+#define HPBITMODE_16 0
+#define HPBITMODE_8 1
-#define HIDSP_INT_PLAY_UNDER 0x00
-#define HIDSP_INT_RECORD_OVER 0x01
-#define HIDSP_INPUT_CLIPPING 0x02
-#define HIDSP_MIDI_IN_OVER 0x10
+#define HIDSP_INT_PLAY_UNDER 0x00
+#define HIDSP_INT_RECORD_OVER 0x01
+#define HIDSP_INPUT_CLIPPING 0x02
+#define HIDSP_MIDI_IN_OVER 0x10
#define HIDSP_MIDI_OVERRUN_ERR 0x13
-#define HDEXAR_CLEAR_PEAKS 1
-#define HDEXAR_IN_SET_POTS 2
-#define HDEXAR_AUX_SET_POTS 3
-#define HDEXAR_CAL_A_TO_D 4
-#define HDEXAR_RD_EXT_DSP_BITS 5
-
-#define TIME_PRO_RESET_DONE 0x028A
-#define TIME_PRO_SYSEX 0x0040
-#define TIME_PRO_RESET 0x0032
-
-#define AGND 0x01
-#define SIGNAL 0x02
-
-#define EXT_DSP_BIT_DCAL 0x0001
-#define EXT_DSP_BIT_MIDI_CON 0x0002
-
-#define BUFFSIZE 0x8000
-#define HOSTQ_SIZE 0x40
-
-#define SRAM_CNTL_START 0x7F00
-#define SMA_STRUCT_START 0x7F40
-
-#define DAP_BUFF_SIZE 0x2400
-#define DAR_BUFF_SIZE 0x2000
-
-#define DAPQ_STRUCT_SIZE 0x10
-#define DARQ_STRUCT_SIZE 0x10
-#define DAPQ_BUFF_SIZE (3 * 0x10)
-#define DARQ_BUFF_SIZE (3 * 0x10)
-#define MODQ_BUFF_SIZE 0x400
-#define MIDQ_BUFF_SIZE 0x200
-#define DSPQ_BUFF_SIZE 0x40
-
-#define DAPQ_DATA_BUFF 0x6C00
-#define DARQ_DATA_BUFF 0x6C30
-#define MODQ_DATA_BUFF 0x6C60
-#define MIDQ_DATA_BUFF 0x7060
-#define DSPQ_DATA_BUFF 0x7260
-
-#define DAPQ_OFFSET SRAM_CNTL_START
-#define DARQ_OFFSET (SRAM_CNTL_START + 0x08)
-#define MODQ_OFFSET (SRAM_CNTL_START + 0x10)
-#define MIDQ_OFFSET (SRAM_CNTL_START + 0x18)
-#define DSPQ_OFFSET (SRAM_CNTL_START + 0x20)
-
-#define MOP_PROTEUS 0x10
-#define MOP_EXTOUT 0x32
-#define MOP_EXTTHRU 0x02
-#define MOP_OUTMASK 0x01
-
-#define MIP_EXTIN 0x01
-#define MIP_PROTEUS 0x00
-#define MIP_INMASK 0x32
-
-struct SMA0_CommonData {
- WORD wCurrPlayBytes;
- WORD wCurrRecordBytes;
- WORD wCurrPlayVolLeft;
- WORD wCurrPlayVolRight;
- WORD wCurrInVolLeft;
- WORD wCurrInVolRight;
- WORD wUser_3;
- WORD wUser_4;
- DWORD dwUser_5;
- DWORD dwUser_6;
- WORD wUser_7;
- WORD wReserved_A;
- WORD wReserved_B;
- WORD wReserved_C;
- WORD wReserved_D;
- WORD wReserved_E;
- WORD wReserved_F;
- WORD wReserved_G;
- WORD wReserved_H;
- WORD wCurrDSPStatusFlags;
- WORD wCurrHostStatusFlags;
- WORD wCurrInputTagBits;
- WORD wCurrLeftPeak;
- WORD wCurrRightPeak;
- WORD wExtDSPbits;
- BYTE bExtHostbits;
- BYTE bBoardLevel;
- BYTE bInPotPosRight;
- BYTE bInPotPosLeft;
- BYTE bAuxPotPosRight;
- BYTE bAuxPotPosLeft;
- WORD wCurrMastVolLeft;
- WORD wCurrMastVolRight;
- BYTE bUser_12;
- BYTE bUser_13;
- WORD wUser_14;
- WORD wUser_15;
- WORD wCalFreqAtoD;
- WORD wUser_16;
- WORD wUser_17;
-} GCC_PACKED;
+#define HDEXAR_CLEAR_PEAKS 1
+#define HDEXAR_IN_SET_POTS 2
+#define HDEXAR_AUX_SET_POTS 3
+#define HDEXAR_CAL_A_TO_D 4
+#define HDEXAR_RD_EXT_DSP_BITS 5
+
+#define TIME_PRO_RESET_DONE 0x028A
+#define TIME_PRO_SYSEX 0x0040
+#define TIME_PRO_RESET 0x0032
+
+#define AGND 0x01
+#define SIGNAL 0x02
+
+#define EXT_DSP_BIT_DCAL 0x0001
+#define EXT_DSP_BIT_MIDI_CON 0x0002
+
+#define BUFFSIZE 0x8000
+#define HOSTQ_SIZE 0x40
+
+#define SRAM_CNTL_START 0x7F00
+#define SMA_STRUCT_START 0x7F40
+
+#define DAP_BUFF_SIZE 0x2400
+#define DAR_BUFF_SIZE 0x2000
+
+#define DAPQ_STRUCT_SIZE 0x10
+#define DARQ_STRUCT_SIZE 0x10
+#define DAPQ_BUFF_SIZE (3 * 0x10)
+#define DARQ_BUFF_SIZE (3 * 0x10)
+#define MODQ_BUFF_SIZE 0x400
+#define MIDQ_BUFF_SIZE 0x200
+#define DSPQ_BUFF_SIZE 0x40
+
+#define DAPQ_DATA_BUFF 0x6C00
+#define DARQ_DATA_BUFF 0x6C30
+#define MODQ_DATA_BUFF 0x6C60
+#define MIDQ_DATA_BUFF 0x7060
+#define DSPQ_DATA_BUFF 0x7260
+
+#define DAPQ_OFFSET SRAM_CNTL_START
+#define DARQ_OFFSET (SRAM_CNTL_START + 0x08)
+#define MODQ_OFFSET (SRAM_CNTL_START + 0x10)
+#define MIDQ_OFFSET (SRAM_CNTL_START + 0x18)
+#define DSPQ_OFFSET (SRAM_CNTL_START + 0x20)
+
+#define MOP_PROTEUS 0x10
+#define MOP_EXTOUT 0x32
+#define MOP_EXTTHRU 0x02
+#define MOP_OUTMASK 0x01
+
+#define MIP_EXTIN 0x01
+#define MIP_PROTEUS 0x00
+#define MIP_INMASK 0x32
+
+/* Classic SMA Common Data */
+#define SMA_wCurrPlayBytes 0x0000
+#define SMA_wCurrRecordBytes 0x0002
+#define SMA_wCurrPlayVolLeft 0x0004
+#define SMA_wCurrPlayVolRight 0x0006
+#define SMA_wCurrInVolLeft 0x0008
+#define SMA_wCurrInVolRight 0x000a
+#define SMA_wUser_3 0x000c
+#define SMA_wUser_4 0x000e
+#define SMA_dwUser_5 0x0010
+#define SMA_dwUser_6 0x0014
+#define SMA_wUser_7 0x0018
+#define SMA_wReserved_A 0x001a
+#define SMA_wReserved_B 0x001c
+#define SMA_wReserved_C 0x001e
+#define SMA_wReserved_D 0x0020
+#define SMA_wReserved_E 0x0022
+#define SMA_wReserved_F 0x0024
+#define SMA_wReserved_G 0x0026
+#define SMA_wReserved_H 0x0028
+#define SMA_wCurrDSPStatusFlags 0x002a
+#define SMA_wCurrHostStatusFlags 0x002c
+#define SMA_wCurrInputTagBits 0x002e
+#define SMA_wCurrLeftPeak 0x0030
+#define SMA_wCurrRightPeak 0x0032
+#define SMA_wExtDSPbits 0x0034
+#define SMA_bExtHostbits 0x0036
+#define SMA_bBoardLevel 0x0037
+#define SMA_bInPotPosRight 0x0038
+#define SMA_bInPotPosLeft 0x0039
+#define SMA_bAuxPotPosRight 0x003a
+#define SMA_bAuxPotPosLeft 0x003b
+#define SMA_wCurrMastVolLeft 0x003c
+#define SMA_wCurrMastVolRight 0x003e
+#define SMA_bUser_12 0x0040
+#define SMA_bUser_13 0x0041
+#define SMA_wUser_14 0x0042
+#define SMA_wUser_15 0x0044
+#define SMA_wCalFreqAtoD 0x0046
+#define SMA_wUser_16 0x0048
+#define SMA_wUser_17 0x004a
+#define SMA__size 0x004c
#ifdef HAVE_DSPCODEH
# include "msndperm.c"
diff --git a/drivers/sound/msnd_pinnacle.c b/drivers/sound/msnd_pinnacle.c
index ac33dcab8..bebb5d49c 100644
--- a/drivers/sound/msnd_pinnacle.c
+++ b/drivers/sound/msnd_pinnacle.c
@@ -29,7 +29,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * $Id: msnd_pinnacle.c,v 1.5 1998/07/18 00:12:16 andrewtv Exp $
+ * $Id: msnd_pinnacle.c,v 1.17 1998/09/04 18:41:27 andrewtv Exp $
*
********************************************************************/
@@ -59,11 +59,7 @@
# define LOGNAME "msnd_pinnacle"
#endif
-#define DEVNAME dev.name
-#define MIXERMINOR dev.mixer_minor
-#define DSPMINOR dev.dsp_minor
-
-multisound_dev_t dev;
+static multisound_dev_t dev;
#ifndef HAVE_DSPCODEH
static char *dspini, *permini;
@@ -76,25 +72,22 @@ static void reset_play_queue(void)
LPDAQD lpDAQ;
msnd_fifo_make_empty(&dev.DAPF);
- dev.DAPQ->wHead = 0;
- dev.DAPQ->wTail = PCTODSP_OFFSET(2 * DAPQ_STRUCT_SIZE);
+ writew(0, dev.DAPQ + JQS_wHead);
+ writew(PCTODSP_OFFSET(2 * DAPQ_STRUCT_SIZE), dev.DAPQ + JQS_wTail);
dev.CurDAQD = (LPDAQD)(dev.base + 1 * DAPQ_DATA_BUFF);
outb(HPBLKSEL_0, dev.io + HP_BLKS);
memset_io(dev.base, 0, DAP_BUFF_SIZE * 3);
- for (n = 0, lpDAQ = dev.CurDAQD; n < 3; ++n, ++lpDAQ) {
-
- writew(PCTODSP_BASED((DWORD)(DAP_BUFF_SIZE * n)), &lpDAQ->wStart);
- writew(DAP_BUFF_SIZE, &lpDAQ->wSize);
- writew(1, &lpDAQ->wFormat);
- writew(dev.sample_size, &lpDAQ->wSampleSize);
- writew(dev.channels, &lpDAQ->wChannels);
- writew(dev.sample_rate, &lpDAQ->wSampleRate);
- writew(HIMT_PLAY_DONE * 0x100 + n, &lpDAQ->wIntMsg);
- writew(n + 1, &lpDAQ->wFlags);
-
+ for (n = 0, lpDAQ = dev.CurDAQD; n < 3; ++n, lpDAQ += DAQDS__size) {
+ writew(PCTODSP_BASED((DWORD)(DAP_BUFF_SIZE * n)), lpDAQ + DAQDS_wStart);
+ writew(DAP_BUFF_SIZE, lpDAQ + DAQDS_wSize);
+ writew(1, lpDAQ + DAQDS_wFormat);
+ writew(dev.sample_size, lpDAQ + DAQDS_wSampleSize);
+ writew(dev.channels, lpDAQ + DAQDS_wChannels);
+ writew(dev.sample_rate, lpDAQ + DAQDS_wSampleRate);
+ writew(HIMT_PLAY_DONE * 0x100 + n, lpDAQ + DAQDS_wIntMsg);
+ writew(n + 1, lpDAQ + DAQDS_wFlags);
}
-
dev.lastbank = -1;
}
@@ -104,34 +97,62 @@ static void reset_record_queue(void)
LPDAQD lpDAQ;
msnd_fifo_make_empty(&dev.DARF);
- dev.DARQ->wHead = 0;
- dev.DARQ->wTail = PCTODSP_OFFSET(2 * DARQ_STRUCT_SIZE);
+ writew(0, dev.DARQ + JQS_wHead);
+ writew(PCTODSP_OFFSET(2 * DARQ_STRUCT_SIZE), dev.DARQ + JQS_wTail);
dev.CurDARQD = (LPDAQD)(dev.base + 1 * DARQ_DATA_BUFF);
outb(HPBLKSEL_1, dev.io + HP_BLKS);
memset_io(dev.base, 0, DAR_BUFF_SIZE * 3);
outb(HPBLKSEL_0, dev.io + HP_BLKS);
- for (n = 0, lpDAQ = dev.CurDARQD; n < 3; ++n, ++lpDAQ) {
-
- writew(PCTODSP_BASED((DWORD)(DAR_BUFF_SIZE * n)) + 0x4000, &lpDAQ->wStart);
- writew(DAR_BUFF_SIZE, &lpDAQ->wSize);
- writew(1, &lpDAQ->wFormat);
- writew(dev.sample_size, &lpDAQ->wSampleSize);
- writew(dev.channels, &lpDAQ->wChannels);
- writew(dev.sample_rate, &lpDAQ->wSampleRate);
- writew(HIMT_RECORD_DONE * 0x100 + n, &lpDAQ->wIntMsg);
- writew(n + 1, &lpDAQ->wFlags);
-
+ for (n = 0, lpDAQ = dev.CurDARQD; n < 3; ++n, lpDAQ += DAQDS__size) {
+ writew(PCTODSP_BASED((DWORD)(DAR_BUFF_SIZE * n)) + 0x4000, lpDAQ + DAQDS_wStart);
+ writew(DAR_BUFF_SIZE, lpDAQ + DAQDS_wSize);
+ writew(1, lpDAQ + DAQDS_wFormat);
+ writew(dev.sample_size, lpDAQ + DAQDS_wSampleSize);
+ writew(dev.channels, lpDAQ + DAQDS_wChannels);
+ writew(dev.sample_rate, lpDAQ + DAQDS_wSampleRate);
+ writew(HIMT_RECORD_DONE * 0x100 + n, lpDAQ + DAQDS_wIntMsg);
+ writew(n + 1, lpDAQ + DAQDS_wFlags);
}
}
static void reset_queues(void)
{
- dev.DSPQ->wHead = dev.DSPQ->wTail = 0;
+ writew(0, dev.DSPQ + JQS_wHead);
+ writew(0, dev.DSPQ + JQS_wTail);
reset_play_queue();
reset_record_queue();
}
+static int dsp_set_format(int val)
+{
+ int data, i;
+ LPDAQD lpDAQ, lpDARQ;
+
+ lpDAQ = (LPDAQD)(dev.base + DAPQ_DATA_BUFF);
+ lpDARQ = (LPDAQD)(dev.base + DARQ_DATA_BUFF);
+
+ switch (val) {
+ case AFMT_U8:
+ case AFMT_S16_LE:
+ data = val;
+ break;
+ default:
+ data = DEFSAMPLESIZE;
+ break;
+ }
+
+ for (i = 0; i < 3; ++i, lpDAQ += DAQDS__size, lpDARQ += DAQDS__size) {
+
+ writew(data, lpDAQ + DAQDS_wSampleSize);
+ writew(data, lpDARQ + DAQDS_wSampleSize);
+ }
+
+ dev.sample_size = data;
+
+ return data;
+}
+
static int dsp_ioctl(unsigned int cmd, unsigned long arg)
{
int val, i, data, tmp;
@@ -154,64 +175,43 @@ static int dsp_ioctl(unsigned int cmd, unsigned long arg)
case SNDCTL_DSP_SYNC:
case SNDCTL_DSP_RESET:
-
reset_play_queue();
reset_record_queue();
-
return 0;
case SNDCTL_DSP_GETBLKSIZE:
-
tmp = dev.fifosize / 4;
if (put_user(tmp, (int *)arg))
return -EFAULT;
-
return 0;
- case SNDCTL_DSP_NONBLOCK:
-
- dev.mode |= O_NONBLOCK;
-
- return 0;
-
- case SNDCTL_DSP_GETCAPS:
-
- val = DSP_CAP_DUPLEX | DSP_CAP_BATCH;
+ case SNDCTL_DSP_GETFMTS:
+ val = AFMT_S16_LE | AFMT_U8;
if (put_user(val, (int *)arg))
return -EFAULT;
-
return 0;
- case SNDCTL_DSP_SAMPLESIZE:
-
+ case SNDCTL_DSP_SETFMT:
if (get_user(val, (int *)arg))
return -EFAULT;
- switch (val) {
- case 16:
- case 8:
- data = val;
- break;
- default:
- data = DEFSAMPLESIZE;
- break;
- }
-
- for (i = 0; i < 3; ++i, ++lpDAQ, ++lpDARQ) {
+ data = (val == AFMT_QUERY) ? dev.sample_size : dsp_set_format(val);
- lpDAQ->wSampleSize = data;
- lpDARQ->wSampleSize = data;
- }
-
- dev.sample_size = data;
-
if (put_user(data, (int *)arg))
return -EFAULT;
+ return 0;
+
+ case SNDCTL_DSP_NONBLOCK:
+ dev.mode |= O_NONBLOCK;
+ return 0;
+ case SNDCTL_DSP_GETCAPS:
+ val = DSP_CAP_DUPLEX | DSP_CAP_BATCH;
+ if (put_user(val, (int *)arg))
+ return -EFAULT;
return 0;
case SNDCTL_DSP_SPEED:
-
if (get_user(val, (int *)arg))
return -EFAULT;
@@ -223,21 +223,19 @@ static int dsp_ioctl(unsigned int cmd, unsigned long arg)
data = val;
- for (i = 0; i < 3; ++i, ++lpDAQ, ++lpDARQ) {
-
- lpDAQ->wSampleRate = data;
- lpDARQ->wSampleRate = data;
+ for (i = 0; i < 3; ++i, lpDAQ += DAQDS__size, lpDARQ += DAQDS__size) {
+
+ writew(data, lpDAQ + DAQDS_wSampleRate);
+ writew(data, lpDARQ + DAQDS_wSampleRate);
}
dev.sample_rate = data;
if (put_user(data, (int *)arg))
return -EFAULT;
-
return 0;
case SNDCTL_DSP_CHANNELS:
-
if (get_user(val, (int *)arg))
return -EFAULT;
@@ -251,21 +249,19 @@ static int dsp_ioctl(unsigned int cmd, unsigned long arg)
break;
}
- for (i = 0; i < 3; ++i, ++lpDAQ, ++lpDARQ) {
+ for (i = 0; i < 3; ++i, lpDAQ += DAQDS__size, lpDARQ += DAQDS__size) {
- lpDAQ->wChannels = data;
- lpDARQ->wChannels = data;
+ writew(data, lpDAQ + DAQDS_wChannels);
+ writew(data, lpDARQ + DAQDS_wChannels);
}
dev.channels = data;
if (put_user(val, (int *)arg))
return -EFAULT;
-
return 0;
case SNDCTL_DSP_STEREO:
-
if (get_user(val, (int *)arg))
return -EFAULT;
@@ -280,17 +276,16 @@ static int dsp_ioctl(unsigned int cmd, unsigned long arg)
break;
}
- for (i = 0; i < 3; ++i, ++lpDAQ, ++lpDARQ) {
+ for (i = 0; i < 3; ++i, lpDAQ += DAQDS__size, lpDARQ += DAQDS__size) {
- lpDAQ->wChannels = data;
- lpDARQ->wChannels = data;
+ writew(data, lpDAQ + DAQDS_wChannels);
+ writew(data, lpDARQ + DAQDS_wChannels);
}
dev.channels = data;
if (put_user(val, (int *)arg))
return -EFAULT;
-
return 0;
}
@@ -319,11 +314,11 @@ static int mixer_get(int d)
}
}
-#define update_vol(a,b,s) \
- writew(dev.left_levels[a] * readw(&dev.SMA->wCurrMastVolLeft) / 0xffff / s, \
- &dev.SMA->b##Left); \
- writew(dev.right_levels[a] * readw(&dev.SMA->wCurrMastVolRight) / 0xffff / s, \
- &dev.SMA->b##Right);
+#define update_vol(a,b,s) \
+ writew(dev.left_levels[a] * readw(dev.SMA + SMA_wCurrMastVolLeft) / 0xffff / s, \
+ dev.SMA + SMA_##b##Left); \
+ writew(dev.right_levels[a] * readw(dev.SMA + SMA_wCurrMastVolRight) / 0xffff / s, \
+ dev.SMA + SMA_##b##Right);
static int mixer_set(int d, int value)
{
@@ -346,30 +341,30 @@ static int mixer_set(int d, int value)
switch (d) {
case SOUND_MIXER_VOLUME: /* master volume */
- writew(wLeft / 2, &dev.SMA->wCurrMastVolLeft);
- writew(wRight / 2, &dev.SMA->wCurrMastVolRight);
+ writew(wLeft / 2, dev.SMA + SMA_wCurrMastVolLeft);
+ writew(wRight / 2, dev.SMA + SMA_wCurrMastVolRight);
break;
/* pot controls */
case SOUND_MIXER_LINE: /* aux pot control */
- writeb(bLeft, &dev.SMA->bInPotPosLeft);
- writeb(bRight, &dev.SMA->bInPotPosRight);
+ writeb(bLeft, dev.SMA + SMA_bInPotPosLeft);
+ writeb(bRight, dev.SMA + SMA_bInPotPosRight);
if (msnd_send_word(&dev, 0, 0, HDEXAR_IN_SET_POTS) == 0)
msnd_send_dsp_cmd(&dev, HDEX_AUX_REQ);
break;
#ifndef MSND_CLASSIC
case SOUND_MIXER_MIC: /* mic pot control */
- writeb(bLeft, &dev.SMA->bMicPotPosLeft);
- writeb(bRight, &dev.SMA->bMicPotPosRight);
+ writeb(bLeft, dev.SMA + SMA_bMicPotPosLeft);
+ writeb(bRight, dev.SMA + SMA_bMicPotPosRight);
if (msnd_send_word(&dev, 0, 0, HDEXAR_MIC_SET_POTS) == 0)
msnd_send_dsp_cmd(&dev, HDEX_AUX_REQ);
break;
#endif
case SOUND_MIXER_LINE1: /* line pot control */
- writeb(bLeft, &dev.SMA->bAuxPotPosLeft);
- writeb(bRight, &dev.SMA->bAuxPotPosRight);
+ writeb(bLeft, dev.SMA + SMA_bAuxPotPosLeft);
+ writeb(bRight, dev.SMA + SMA_bAuxPotPosRight);
if (msnd_send_word(&dev, 0, 0, HDEXAR_AUX_SET_POTS) == 0)
msnd_send_dsp_cmd(&dev, HDEX_AUX_REQ);
break;
@@ -396,25 +391,29 @@ static int mixer_set(int d, int value)
static unsigned long set_recsrc(unsigned long recsrc)
{
+ if (dev.recsrc == recsrc)
+ return dev.recsrc;
#ifdef HAVE_NORECSRC
- if (recsrc == 0)
+ else if (recsrc == 0)
dev.recsrc = 0;
- else
#endif
+ else
dev.recsrc ^= recsrc;
#ifndef MSND_CLASSIC
if (dev.recsrc & SOUND_MASK_LINE) {
-
if (msnd_send_word(&dev, 0, 0, HDEXAR_SET_ANA_IN) == 0)
msnd_send_dsp_cmd(&dev, HDEX_AUX_REQ);
-
}
else if (dev.recsrc & SOUND_MASK_SYNTH) {
-
if (msnd_send_word(&dev, 0, 0, HDEXAR_SET_SYNTH_IN) == 0)
msnd_send_dsp_cmd(&dev, HDEX_AUX_REQ);
-
+ }
+ else if ((dev.recsrc & SOUND_MASK_DIGITAL1) && test_bit(F_HAVEDIGITAL, &dev.flags)) {
+ if (msnd_send_word(&dev, 0, 0, HDEXAR_SET_DAT_IN) == 0) {
+ udelay(50);
+ msnd_send_dsp_cmd(&dev, HDEX_AUX_REQ);
+ }
}
else {
#ifdef HAVE_NORECSRC
@@ -431,14 +430,31 @@ static unsigned long set_recsrc(unsigned long recsrc)
return dev.recsrc;
}
+#define set_mixer_info() \
+ strncpy(info.id, "MSNDMIXER", sizeof(info.id)); \
+ strncpy(info.name, "MultiSound Mixer", sizeof(info.name));
+
static int mixer_ioctl(unsigned int cmd, unsigned long arg)
{
- int val = 0;
-
- if (((cmd >> 8) & 0xff) == 'M') {
+ if (cmd == SOUND_MIXER_INFO) {
+ mixer_info info;
+ set_mixer_info();
+ info.modify_counter = dev.mixer_mod_count;
+ return copy_to_user((void *)arg, &info, sizeof(info));
+ }
+ else if (cmd == SOUND_OLD_MIXER_INFO) {
+ _old_mixer_info info;
+ set_mixer_info();
+ return copy_to_user((void *)arg, &info, sizeof(info));
+ }
+ else if (cmd == OSS_GETVERSION) {
+ int sound_version = SOUND_VERSION;
+ return put_user(sound_version, (int *)arg);
+ }
+ else if (((cmd >> 8) & 0xff) == 'M') {
+ int val = 0;
if (_SIOC_DIR(cmd) & _SIOC_WRITE) {
-
switch (cmd & 0xff) {
case SOUND_MIXER_RECSRC:
if (get_user(val, (int *)arg))
@@ -452,7 +468,7 @@ static int mixer_ioctl(unsigned int cmd, unsigned long arg)
val = mixer_set(cmd & 0xff, val);
break;
}
-
+ ++dev.mixer_mod_count;
return put_user(val, (int *)arg);
}
else {
@@ -479,6 +495,8 @@ static int mixer_ioctl(unsigned int cmd, unsigned long arg)
#else
val = SOUND_MASK_LINE |
SOUND_MASK_SYNTH;
+ if (test_bit(F_HAVEDIGITAL, &dev.flags))
+ val |= SOUND_MASK_DIGITAL1;
#endif
break;
@@ -503,9 +521,9 @@ static int dev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u
{
int minor = MINOR(inode->i_rdev);
- if (minor == DSPMINOR)
+ if (minor == dev.dsp_minor)
return dsp_ioctl(cmd, arg);
- else if (minor == MIXERMINOR)
+ else if (minor == dev.mixer_minor)
return mixer_ioctl(cmd, arg);
return -EINVAL;
@@ -568,14 +586,14 @@ static int dev_open(struct inode *inode, struct file *file)
int minor = MINOR(inode->i_rdev);
int err = 0;
- if (minor == DSPMINOR) {
+ if (minor == dev.dsp_minor) {
if (test_bit(F_AUDIO_INUSE, &dev.flags))
return -EBUSY;
err = dsp_open(file);
}
- else if (minor == MIXERMINOR) {
+ else if (minor == dev.mixer_minor) {
/* nothing */
} else
err = -EINVAL;
@@ -597,13 +615,13 @@ static int dev_close(struct inode *inode, struct file *file)
int err = 0;
#endif
- if (minor == DSPMINOR) {
+ if (minor == dev.dsp_minor) {
#ifndef LINUX20
err =
#endif
dsp_close();
}
- else if (minor == MIXERMINOR) {
+ else if (minor == dev.mixer_minor) {
/* nothing */
}
#ifndef LINUX20
@@ -741,7 +759,7 @@ static ssize_t dev_read(struct file *file, char *buf, size_t count, loff_t *off)
int minor = MINOR(file->f_dentry->d_inode->i_rdev);
#endif
- if (minor == DSPMINOR) {
+ if (minor == dev.dsp_minor) {
return dsp_read(buf, count);
@@ -759,7 +777,7 @@ static ssize_t dev_write(struct file *file, const char *buf, size_t count, loff_
int minor = MINOR(file->f_dentry->d_inode->i_rdev);
#endif
- if (minor == DSPMINOR) {
+ if (minor == dev.dsp_minor) {
return dsp_write(buf, count);
@@ -769,32 +787,32 @@ static ssize_t dev_write(struct file *file, const char *buf, size_t count, loff_
static void eval_dsp_msg(WORD wMessage)
{
+ WORD wTmp;
+
switch (HIBYTE(wMessage)) {
case HIMT_PLAY_DONE:
-
if (dev.lastbank == LOBYTE(wMessage))
break;
dev.lastbank = LOBYTE(wMessage);
- dev.CurDAQD->wSize = DAP_BUFF_SIZE;
+ writew(DAP_BUFF_SIZE, dev.CurDAQD + DAQDS_wSize);
- if ((dev.DAPQ->wTail += PCTODSP_OFFSET(DAPQ_STRUCT_SIZE)) > dev.DAPQ->wSize)
- dev.DAPQ->wTail = 0;
+ wTmp = readw(dev.DAPQ + JQS_wTail) + PCTODSP_OFFSET(DAPQ_STRUCT_SIZE);
+ if (wTmp > readw(dev.DAPQ + JQS_wSize))
+ writew(0, dev.DAPQ + JQS_wTail);
+ else
+ writew(wTmp, dev.DAPQ + JQS_wTail);
- if (++dev.CurDAQD > (LPDAQD)(dev.base + DAPQ_DATA_BUFF + 2 * DAPQ_STRUCT_SIZE))
+ if ((dev.CurDAQD += DAQDS__size) > (LPDAQD)(dev.base + DAPQ_DATA_BUFF + 2 * DAPQ_STRUCT_SIZE))
dev.CurDAQD = (LPDAQD)(dev.base + DAPQ_DATA_BUFF);
if (dev.lastbank < 3) {
-
if (DAPF_to_bank(dev.lastbank) > 0) {
-
mdelay(1);
msnd_send_dsp_cmd(&dev, HDEX_PLAY_START);
-
}
else if (!test_bit(F_WRITEBLOCK, &dev.flags)) {
-
clear_bit(F_WRITING, &dev.flags);
#ifdef LINUX20
if (test_bit(F_WRITEFLUSH, &dev.flags)) {
@@ -805,44 +823,33 @@ static void eval_dsp_msg(WORD wMessage)
if (test_and_clear_bit(F_WRITEFLUSH, &dev.flags))
wake_up_interruptible(&dev.writeflush);
#endif
- msnd_disable_irq(&dev);
-
}
}
if (test_bit(F_WRITEBLOCK, &dev.flags))
wake_up_interruptible(&dev.writeblock);
-
break;
- case HIMT_RECORD_DONE: {
-
- WORD wTemp;
-
- wTemp = dev.DARQ->wTail + (DARQ_STRUCT_SIZE / 2);
+ case HIMT_RECORD_DONE:
+ wTmp = readw(dev.DARQ + JQS_wTail) + DARQ_STRUCT_SIZE / 2;
- if (wTemp > dev.DARQ->wSize)
- wTemp = 0;
+ if (wTmp > readw(dev.DARQ + JQS_wSize))
+ wTmp = 0;
- while (wTemp == dev.DARQ->wHead);
+ while (wTmp == readw(dev.DARQ + JQS_wHead));
- dev.DARQ->wTail = wTemp;
+ writew(wTmp, dev.DARQ + JQS_wTail);
outb(HPBLKSEL_1, dev.io + HP_BLKS);
- if (bank_to_DARF(LOBYTE(wMessage)) == 0 &&
- !test_bit(F_READBLOCK, &dev.flags)) {
-
+ if (bank_to_DARF(LOBYTE(wMessage)) == 0 && !test_bit(F_READBLOCK, &dev.flags)) {
memset_io(dev.base, 0, DAR_BUFF_SIZE * 3);
clear_bit(F_READING, &dev.flags);
- msnd_disable_irq(&dev);
-
}
outb(HPBLKSEL_0, dev.io + HP_BLKS);
if (test_bit(F_READBLOCK, &dev.flags))
wake_up_interruptible(&dev.readblock);
-
- } break;
+ break;
case HIMT_DSP:
switch (LOBYTE(wMessage)) {
@@ -850,12 +857,12 @@ static void eval_dsp_msg(WORD wMessage)
case HIDSP_PLAY_UNDER:
#endif
case HIDSP_INT_PLAY_UNDER:
- printk(KERN_INFO LOGNAME ": Write underflow\n");
+/* printk(KERN_INFO LOGNAME ": Write underflow\n"); */
reset_play_queue();
break;
case HIDSP_INT_RECORD_OVER:
- printk(KERN_INFO LOGNAME ": Read overflow\n");
+/* printk(KERN_INFO LOGNAME ": Read overflow\n"); */
reset_record_queue();
break;
@@ -892,12 +899,16 @@ static void intr(int irq, void *dev_id, struct pt_regs *regs)
inb(dev.io + HP_RXL);
- while (dev.DSPQ->wTail != dev.DSPQ->wHead) {
-
- eval_dsp_msg(*(dev.pwDSPQData + dev.DSPQ->wHead));
+ while (readw(dev.DSPQ + JQS_wTail) != readw(dev.DSPQ + JQS_wHead)) {
+ WORD wTmp;
- if (++dev.DSPQ->wHead > dev.DSPQ->wSize)
- dev.DSPQ->wHead = 0;
+ eval_dsp_msg(*(dev.pwDSPQData + readw(dev.DSPQ + JQS_wHead)));
+
+ wTmp = readw(dev.DSPQ + JQS_wHead) + 1;
+ if (wTmp > readw(dev.DSPQ + JQS_wSize))
+ writew(0, dev.DSPQ + JQS_wHead);
+ else
+ writew(wTmp, dev.DSPQ + JQS_wHead);
}
if (test_bit(F_BANKONE, &dev.flags))
@@ -915,12 +926,17 @@ static struct file_operations dev_fileops = {
dev_ioctl,
NULL,
dev_open,
+#ifndef LINUX20
+# if LINUX_VERSION_CODE >= 0x020100 + 118
+ NULL,
+# endif /* >= 2.1.118 */
+#endif
dev_close,
};
__initfunc(static int reset_dsp(void))
{
- int timeout = 20000;
+ int timeout = 100;
outb(HPDSPRESET_ON, dev.io + HP_DSPR);
@@ -954,7 +970,6 @@ __initfunc(static int probe_multisound(void))
#endif
if (check_region(dev.io, dev.numio)) {
-
printk(KERN_ERR LOGNAME ": I/O port conflict\n");
return -ENODEV;
}
@@ -962,7 +977,6 @@ __initfunc(static int probe_multisound(void))
request_region(dev.io, dev.numio, "probing");
if (reset_dsp() < 0) {
-
release_region(dev.io, dev.numio);
return -ENODEV;
}
@@ -1026,13 +1040,12 @@ __initfunc(static int init_sma(void))
outb(HPBLKSEL_0, dev.io + HP_BLKS);
- dev.DAPQ = (struct JobQueueStruct *)(dev.base + DAPQ_OFFSET);
- dev.DARQ = (struct JobQueueStruct *)(dev.base + DARQ_OFFSET);
- dev.MODQ = (struct JobQueueStruct *)(dev.base + MODQ_OFFSET);
- dev.MIDQ = (struct JobQueueStruct *)(dev.base + MIDQ_OFFSET);
- dev.DSPQ = (struct JobQueueStruct *)(dev.base + DSPQ_OFFSET);
-
- dev.SMA = (struct SMA0_CommonData *)(dev.base + SMA_STRUCT_START);
+ dev.DAPQ = (BYTE *)(dev.base + DAPQ_OFFSET);
+ dev.DARQ = (BYTE *)(dev.base + DARQ_OFFSET);
+ dev.MODQ = (BYTE *)(dev.base + MODQ_OFFSET);
+ dev.MIDQ = (BYTE *)(dev.base + MIDQ_OFFSET);
+ dev.DSPQ = (BYTE *)(dev.base + DSPQ_OFFSET);
+ dev.SMA = (BYTE *)(dev.base + SMA_STRUCT_START);
dev.CurDAQD = (LPDAQD)(dev.base + DAPQ_DATA_BUFF);
dev.CurDARQD = (LPDAQD)(dev.base + DARQ_DATA_BUFF);
@@ -1041,28 +1054,28 @@ __initfunc(static int init_sma(void))
dev.sample_rate = DEFSAMPLERATE;
dev.channels = DEFCHANNELS;
- for (n = 0, lpDAQ = dev.CurDAQD; n < 3; ++n, ++lpDAQ) {
+ for (n = 0, lpDAQ = dev.CurDAQD; n < 3; ++n, lpDAQ += DAQDS__size) {
- writew(PCTODSP_BASED((DWORD)(DAP_BUFF_SIZE * n)), &lpDAQ->wStart);
- writew(DAP_BUFF_SIZE, &lpDAQ->wSize);
- writew(1, &lpDAQ->wFormat);
- writew(dev.sample_size, &lpDAQ->wSampleSize);
- writew(dev.channels, &lpDAQ->wChannels);
- writew(dev.sample_rate, &lpDAQ->wSampleRate);
- writew(HIMT_PLAY_DONE * 0x100 + n, &lpDAQ->wIntMsg);
- writew(n + 1, &lpDAQ->wFlags);
+ writew(PCTODSP_BASED((DWORD)(DAP_BUFF_SIZE * n)), lpDAQ + DAQDS_wStart);
+ writew(DAP_BUFF_SIZE, lpDAQ + DAQDS_wSize);
+ writew(1, lpDAQ + DAQDS_wFormat);
+ writew(dev.sample_size, lpDAQ + DAQDS_wSampleSize);
+ writew(dev.channels, lpDAQ + DAQDS_wChannels);
+ writew(dev.sample_rate, lpDAQ + DAQDS_wSampleRate);
+ writew(HIMT_PLAY_DONE * 0x100 + n, lpDAQ + DAQDS_wIntMsg);
+ writew(n + 1, lpDAQ + DAQDS_wFlags);
}
- for (n = 0, lpDAQ = dev.CurDARQD; n < 3; ++n, ++lpDAQ) {
+ for (n = 0, lpDAQ = dev.CurDARQD; n < 3; ++n, lpDAQ += DAQDS__size) {
- writew(PCTODSP_BASED((DWORD)(DAR_BUFF_SIZE * n)) + 0x4000, &lpDAQ->wStart);
- writew(DAR_BUFF_SIZE, &lpDAQ->wSize);
- writew(1, &lpDAQ->wFormat);
- writew(dev.sample_size, &lpDAQ->wSampleSize);
- writew(dev.channels, &lpDAQ->wChannels);
- writew(dev.sample_rate, &lpDAQ->wSampleRate);
- writew(HIMT_RECORD_DONE * 0x100 + n, &lpDAQ->wIntMsg);
- writew(n + 1, &lpDAQ->wFlags);
+ writew(PCTODSP_BASED((DWORD)(DAR_BUFF_SIZE * n)) + 0x4000, lpDAQ + DAQDS_wStart);
+ writew(DAR_BUFF_SIZE, lpDAQ + DAQDS_wSize);
+ writew(1, lpDAQ + DAQDS_wFormat);
+ writew(dev.sample_size, lpDAQ + DAQDS_wSampleSize);
+ writew(dev.channels, lpDAQ + DAQDS_wChannels);
+ writew(dev.sample_rate, lpDAQ + DAQDS_wSampleRate);
+ writew(HIMT_RECORD_DONE * 0x100 + n, lpDAQ + DAQDS_wIntMsg);
+ writew(n + 1, lpDAQ + DAQDS_wFlags);
}
@@ -1070,68 +1083,68 @@ __initfunc(static int init_sma(void))
dev.pwMODQData = (WORD *)(dev.base + MODQ_DATA_BUFF);
dev.pwMIDQData = (WORD *)(dev.base + MIDQ_DATA_BUFF);
- writew(PCTODSP_BASED(MIDQ_DATA_BUFF), &dev.MIDQ->wStart);
- writew(PCTODSP_OFFSET(MIDQ_BUFF_SIZE) - 1, &dev.MIDQ->wSize);
- writew(0, &dev.MIDQ->wHead);
- writew(0, &dev.MIDQ->wTail);
+ writew(PCTODSP_BASED(MIDQ_DATA_BUFF), dev.MIDQ + JQS_wStart);
+ writew(PCTODSP_OFFSET(MIDQ_BUFF_SIZE) - 1, dev.MIDQ + JQS_wSize);
+ writew(0, dev.MIDQ + JQS_wHead);
+ writew(0, dev.MIDQ + JQS_wTail);
- writew(PCTODSP_BASED(MODQ_DATA_BUFF), &dev.MODQ->wStart);
- writew(PCTODSP_OFFSET(MODQ_BUFF_SIZE) - 1, &dev.MODQ->wSize);
- writew(0, &dev.MODQ->wHead);
- writew(0, &dev.MODQ->wTail);
+ writew(PCTODSP_BASED(MODQ_DATA_BUFF), dev.MODQ + JQS_wStart);
+ writew(PCTODSP_OFFSET(MODQ_BUFF_SIZE) - 1, dev.MODQ + JQS_wSize);
+ writew(0, dev.MODQ + JQS_wHead);
+ writew(0, dev.MODQ + JQS_wTail);
- writew(PCTODSP_BASED(DAPQ_DATA_BUFF), &dev.DAPQ->wStart);
- writew(PCTODSP_OFFSET(DAPQ_BUFF_SIZE) - 1, &dev.DAPQ->wSize);
- writew(0, &dev.DAPQ->wHead);
- writew(0, &dev.DAPQ->wTail);
+ writew(PCTODSP_BASED(DAPQ_DATA_BUFF), dev.DAPQ + JQS_wStart);
+ writew(PCTODSP_OFFSET(DAPQ_BUFF_SIZE) - 1, dev.DAPQ + JQS_wSize);
+ writew(0, dev.DAPQ + JQS_wHead);
+ writew(0, dev.DAPQ + JQS_wTail);
- writew(PCTODSP_BASED(DARQ_DATA_BUFF), &dev.DARQ->wStart);
- writew(PCTODSP_OFFSET(DARQ_BUFF_SIZE) - 1, &dev.DARQ->wSize);
- writew(0, &dev.DARQ->wHead);
- writew(0, &dev.DARQ->wTail);
+ writew(PCTODSP_BASED(DARQ_DATA_BUFF), dev.DARQ + JQS_wStart);
+ writew(PCTODSP_OFFSET(DARQ_BUFF_SIZE) - 1, dev.DARQ + JQS_wSize);
+ writew(0, dev.DARQ + JQS_wHead);
+ writew(0, dev.DARQ + JQS_wTail);
- writew(PCTODSP_BASED(DSPQ_DATA_BUFF), &dev.DSPQ->wStart);
- writew(PCTODSP_OFFSET(DSPQ_BUFF_SIZE) - 1, &dev.DSPQ->wSize);
- writew(0, &dev.DSPQ->wHead);
- writew(0, &dev.DSPQ->wTail);
+ writew(PCTODSP_BASED(DSPQ_DATA_BUFF), dev.DSPQ + JQS_wStart);
+ writew(PCTODSP_OFFSET(DSPQ_BUFF_SIZE) - 1, dev.DSPQ + JQS_wSize);
+ writew(0, dev.DSPQ + JQS_wHead);
+ writew(0, dev.DSPQ + JQS_wTail);
- writew(0, &dev.SMA->wCurrPlayBytes);
- writew(0, &dev.SMA->wCurrRecordBytes);
+ writew(0, dev.SMA + SMA_wCurrPlayBytes);
+ writew(0, dev.SMA + SMA_wCurrRecordBytes);
- writew(0, &dev.SMA->wCurrPlayVolLeft);
- writew(0, &dev.SMA->wCurrPlayVolRight);
+ writew(0, dev.SMA + SMA_wCurrPlayVolLeft);
+ writew(0, dev.SMA + SMA_wCurrPlayVolRight);
- writew(0, &dev.SMA->wCurrInVolLeft);
- writew(0, &dev.SMA->wCurrInVolRight);
+ writew(0, dev.SMA + SMA_wCurrInVolLeft);
+ writew(0, dev.SMA + SMA_wCurrInVolRight);
- writew(0, &dev.SMA->wCurrMastVolLeft);
- writew(0, &dev.SMA->wCurrMastVolRight);
+ writew(0, dev.SMA + SMA_wCurrMastVolLeft);
+ writew(0, dev.SMA + SMA_wCurrMastVolRight);
#ifndef MSND_CLASSIC
- writel(0x00010000, &dev.SMA->dwCurrPlayPitch);
- writel(0x00000001, &dev.SMA->dwCurrPlayRate);
+ writel(0x00010000, dev.SMA + SMA_dwCurrPlayPitch);
+ writel(0x00000001, dev.SMA + SMA_dwCurrPlayRate);
#endif
- writew(0x0000, &dev.SMA->wCurrDSPStatusFlags);
- writew(0x0000, &dev.SMA->wCurrHostStatusFlags);
+ writew(0x0000, dev.SMA + SMA_wCurrDSPStatusFlags);
+ writew(0x0000, dev.SMA + SMA_wCurrHostStatusFlags);
- writew(0x303, &dev.SMA->wCurrInputTagBits);
- writew(0, &dev.SMA->wCurrLeftPeak);
- writew(0, &dev.SMA->wCurrRightPeak);
+ writew(0x303, dev.SMA + SMA_wCurrInputTagBits);
+ writew(0, dev.SMA + SMA_wCurrLeftPeak);
+ writew(0, dev.SMA + SMA_wCurrRightPeak);
- writeb(0, &dev.SMA->bInPotPosRight);
- writeb(0, &dev.SMA->bInPotPosLeft);
+ writeb(0, dev.SMA + SMA_bInPotPosRight);
+ writeb(0, dev.SMA + SMA_bInPotPosLeft);
- writeb(0, &dev.SMA->bAuxPotPosRight);
- writeb(0, &dev.SMA->bAuxPotPosLeft);
+ writeb(0, dev.SMA + SMA_bAuxPotPosRight);
+ writeb(0, dev.SMA + SMA_bAuxPotPosLeft);
#ifndef MSND_CLASSIC
- writew(1, &dev.SMA->wCurrPlayFormat);
- writew(dev.sample_size, &dev.SMA->wCurrPlaySampleSize);
- writew(dev.channels, &dev.SMA->wCurrPlayChannels);
- writew(dev.sample_rate, &dev.SMA->wCurrPlaySampleRate);
+ writew(1, dev.SMA + SMA_wCurrPlayFormat);
+ writew(dev.sample_size, dev.SMA + SMA_wCurrPlaySampleSize);
+ writew(dev.channels, dev.SMA + SMA_wCurrPlayChannels);
+ writew(dev.sample_rate, dev.SMA + SMA_wCurrPlaySampleRate);
#endif
- writew(dev.sample_rate, &dev.SMA->wCalFreqAtoD);
+ writew(dev.sample_rate, dev.SMA + SMA_wCalFreqAtoD);
return 0;
}
@@ -1139,25 +1152,21 @@ __initfunc(static int init_sma(void))
__initfunc(static int calibrate_adc(WORD srate))
{
if (!dev.calibrate_signal) {
-
printk(KERN_INFO LOGNAME ": ADC calibration to board ground ");
- writew(readw(&dev.SMA->wCurrHostStatusFlags)
- | 0x0001, &dev.SMA->wCurrHostStatusFlags);
- }
- else {
-
+ writew(readw(dev.SMA + SMA_wCurrHostStatusFlags)
+ | 0x0001, dev.SMA + SMA_wCurrHostStatusFlags);
+ } else {
printk(KERN_INFO LOGNAME ": ADC calibration to signal ground ");
- writew(readw(&dev.SMA->wCurrHostStatusFlags)
- & ~0x0001, &dev.SMA->wCurrHostStatusFlags);
+ writew(readw(dev.SMA + SMA_wCurrHostStatusFlags)
+ & ~0x0001, dev.SMA + SMA_wCurrHostStatusFlags);
}
- writew(srate, &dev.SMA->wCalFreqAtoD);
+ writew(srate, dev.SMA + SMA_wCalFreqAtoD);
if (msnd_send_word(&dev, 0, 0, HDEXAR_CAL_A_TO_D) == 0 &&
msnd_send_dsp_cmd(&dev, HDEX_AUX_REQ) == 0) {
-
current->state = TASK_INTERRUPTIBLE;
- current->timeout = jiffies + HZ;
+ current->timeout = jiffies + HZ / 3;
schedule();
current->timeout = 0;
printk("successful\n");
@@ -1191,9 +1200,7 @@ __initfunc(static int upload_dsp_code(void))
}
#endif
memcpy_toio(dev.base, PERMCODE, PERMCODESIZE);
-
if (msnd_upload_host(&dev, INITCODE, INITCODESIZE) < 0) {
-
printk(KERN_WARNING LOGNAME ": Error uploading to DSP\n");
return -ENODEV;
}
@@ -1228,7 +1235,6 @@ __initfunc(static int initialize(void))
#endif
if ((err = init_sma()) < 0) {
-
printk(KERN_WARNING LOGNAME ": Cannot initialize SMA\n");
return err;
}
@@ -1237,17 +1243,15 @@ __initfunc(static int initialize(void))
return err;
if ((err = upload_dsp_code()) < 0) {
-
printk(KERN_WARNING LOGNAME ": Cannot upload DSP code\n");
return err;
} else
printk(KERN_INFO LOGNAME ": DSP upload successful\n");
- timeout = 2000;
+ timeout = 200;
while (readw(dev.base)) {
-
mdelay(1);
if (--timeout < 0)
return -EIO;
@@ -1262,17 +1266,15 @@ __initfunc(static int attach_multisound(void))
printk(KERN_DEBUG LOGNAME ": Intializing DSP\n");
- if ((err = request_irq(dev.irq, intr, SA_SHIRQ, DEVNAME, &dev)) < 0) {
-
+ if ((err = request_irq(dev.irq, intr, SA_SHIRQ, dev.name, &dev)) < 0) {
printk(KERN_ERR LOGNAME ": Couldn't grab IRQ %d\n", dev.irq);
return err;
}
- request_region(dev.io, dev.numio, DEVNAME);
+ request_region(dev.io, dev.numio, dev.name);
if ((err = initialize()) < 0) {
-
printk(KERN_WARNING LOGNAME ": Initialization failure\n");
release_region(dev.io, dev.numio);
free_irq(dev.irq, &dev);
@@ -1281,35 +1283,35 @@ __initfunc(static int attach_multisound(void))
}
if ((err = msnd_register(&dev)) < 0) {
-
printk(KERN_ERR LOGNAME ": Unable to register MultiSound\n");
release_region(dev.io, dev.numio);
free_irq(dev.irq, &dev);
return err;
}
- if ((DSPMINOR = register_sound_dsp(&dev_fileops)) < 0) {
-
+ if ((dev.dsp_minor = register_sound_dsp(&dev_fileops)) < 0) {
printk(KERN_ERR LOGNAME ": Unable to register DSP operations\n");
msnd_unregister(&dev);
release_region(dev.io, dev.numio);
free_irq(dev.irq, &dev);
- return DSPMINOR;
+ return dev.dsp_minor;
}
- if ((MIXERMINOR = register_sound_mixer(&dev_fileops)) < 0) {
-
+ if ((dev.mixer_minor = register_sound_mixer(&dev_fileops)) < 0) {
printk(KERN_ERR LOGNAME ": Unable to register mixer operations\n");
- unregister_sound_mixer(MIXERMINOR);
+ unregister_sound_mixer(dev.mixer_minor);
msnd_unregister(&dev);
release_region(dev.io, dev.numio);
free_irq(dev.irq, &dev);
- return MIXERMINOR;
+ return dev.mixer_minor;
}
- printk(KERN_INFO LOGNAME ": Using DSP minor %d, mixer minor %d\n", MIXERMINOR, DSPMINOR);
+ printk(KERN_INFO LOGNAME ": Using DSP minor %d, mixer minor %d\n", dev.dsp_minor, dev.mixer_minor);
calibrate_adc(dev.sample_rate);
- set_recsrc(0);
+#ifndef MSND_CLASSIC
+ printk(KERN_INFO LOGNAME ": Setting initial recording source to Line In\n");
+ set_recsrc(SOUND_MASK_LINE);
+#endif
return 0;
}
@@ -1318,8 +1320,8 @@ static void unload_multisound(void)
{
release_region(dev.io, dev.numio);
free_irq(dev.irq, &dev);
- unregister_sound_mixer(MIXERMINOR);
- unregister_sound_dsp(DSPMINOR);
+ unregister_sound_mixer(dev.mixer_minor);
+ unregister_sound_dsp(dev.dsp_minor);
msnd_unregister(&dev);
}
@@ -1333,6 +1335,155 @@ static void mod_dec_ref(void)
MOD_DEC_USE_COUNT;
}
+#ifndef MSND_CLASSIC
+
+/* Pinnacle/Fiji Logical Device Configuration */
+
+__initfunc(static int msnd_write_cfg(int cfg, int reg, int value))
+{
+ outb(reg, cfg);
+ outb(value, cfg + 1);
+ if (value != inb(cfg + 1)) {
+ printk(KERN_ERR LOGNAME ": msnd_write_cfg: I/O error\n");
+ return -EIO;
+ }
+ return 0;
+}
+
+__initfunc(static int msnd_write_cfg_io0(int cfg, int num, WORD io))
+{
+ if (msnd_write_cfg(cfg, IREG_LOGDEVICE, num))
+ return -EIO;
+ if (msnd_write_cfg(cfg, IREG_IO0_BASEHI, HIBYTE(io)))
+ return -EIO;
+ if (msnd_write_cfg(cfg, IREG_IO0_BASELO, LOBYTE(io)))
+ return -EIO;
+ return 0;
+}
+
+__initfunc(static int msnd_write_cfg_io1(int cfg, int num, WORD io))
+{
+ if (msnd_write_cfg(cfg, IREG_LOGDEVICE, num))
+ return -EIO;
+ if (msnd_write_cfg(cfg, IREG_IO1_BASEHI, HIBYTE(io)))
+ return -EIO;
+ if (msnd_write_cfg(cfg, IREG_IO1_BASELO, LOBYTE(io)))
+ return -EIO;
+ return 0;
+}
+
+__initfunc(static int msnd_write_cfg_irq(int cfg, int num, WORD irq))
+{
+ if (msnd_write_cfg(cfg, IREG_LOGDEVICE, num))
+ return -EIO;
+ if (msnd_write_cfg(cfg, IREG_IRQ_NUMBER, LOBYTE(irq)))
+ return -EIO;
+ if (msnd_write_cfg(cfg, IREG_IRQ_TYPE, IRQTYPE_EDGE))
+ return -EIO;
+ return 0;
+}
+
+__initfunc(static int msnd_write_cfg_mem(int cfg, int num, int mem))
+{
+ WORD wmem;
+
+ mem >>= 8;
+ mem &= 0xfff;
+ wmem = (WORD)mem;
+ if (msnd_write_cfg(cfg, IREG_LOGDEVICE, num))
+ return -EIO;
+ if (msnd_write_cfg(cfg, IREG_MEMBASEHI, HIBYTE(wmem)))
+ return -EIO;
+ if (msnd_write_cfg(cfg, IREG_MEMBASELO, LOBYTE(wmem)))
+ return -EIO;
+ if (wmem && msnd_write_cfg(cfg, IREG_MEMCONTROL, (MEMTYPE_HIADDR | MEMTYPE_16BIT)))
+ return -EIO;
+ return 0;
+}
+
+__initfunc(static int msnd_activate_logical(int cfg, int num))
+{
+ if (msnd_write_cfg(cfg, IREG_LOGDEVICE, num))
+ return -EIO;
+ if (msnd_write_cfg(cfg, IREG_ACTIVATE, LD_ACTIVATE))
+ return -EIO;
+ return 0;
+}
+
+__initfunc(static int msnd_write_cfg_logical(int cfg, int num, WORD io0, WORD io1, WORD irq, int mem))
+{
+ if (msnd_write_cfg(cfg, IREG_LOGDEVICE, num))
+ return -EIO;
+ if (msnd_write_cfg_io0(cfg, num, io0))
+ return -EIO;
+ if (msnd_write_cfg_io1(cfg, num, io1))
+ return -EIO;
+ if (msnd_write_cfg_irq(cfg, num, irq))
+ return -EIO;
+ if (msnd_write_cfg_mem(cfg, num, mem))
+ return -EIO;
+ if (msnd_activate_logical(cfg, num))
+ return -EIO;
+ return 0;
+}
+
+typedef struct msnd_pinnacle_cfg_device {
+ WORD io0, io1, irq;
+ int mem;
+} msnd_pinnacle_cfg_t[4];
+
+__initfunc(static int msnd_pinnacle_cfg_devices(int cfg, int reset, msnd_pinnacle_cfg_t device))
+{
+ int i;
+
+ /* Reset devices if told to */
+ if (reset) {
+ printk(KERN_INFO LOGNAME ": Resetting all devices\n");
+ for (i = 0; i < 4; ++i)
+ if (msnd_write_cfg_logical(cfg, i, 0, 0, 0, 0))
+ return -EIO;
+ }
+
+ /* Configure specified devices */
+ for (i = 0; i < 4; ++i) {
+
+ switch (i) {
+ case 0: /* DSP */
+ if (!(device[i].io0 && device[i].irq && device[i].mem))
+ continue;
+ break;
+ case 1: /* MPU */
+ if (!(device[i].io0 && device[i].irq))
+ continue;
+ printk(KERN_INFO LOGNAME
+ ": Configuring MPU to I/O 0x%x IRQ %d\n",
+ device[i].io0, device[i].irq);
+ break;
+ case 2: /* IDE */
+ if (!(device[i].io0 && device[i].io1 && device[i].irq))
+ continue;
+ printk(KERN_INFO LOGNAME
+ ": Configuring IDE to I/O 0x%x, 0x%x IRQ %d\n",
+ device[i].io0, device[i].io1, device[i].irq);
+ break;
+ case 3: /* Joystick */
+ if (!(device[i].io0))
+ continue;
+ printk(KERN_INFO LOGNAME
+ ": Configuring joystick to I/O 0x%x\n",
+ device[i].io0);
+ break;
+ }
+
+ /* Configure the device */
+ if (msnd_write_cfg_logical(cfg, i, device[i].io0, device[i].io1, device[i].irq, device[i].mem))
+ return -EIO;
+ }
+
+ return 0;
+}
+#endif
+
#ifdef MODULE
MODULE_AUTHOR ("Andrew Veliath <andrewtv@usa.net>");
MODULE_DESCRIPTION ("Turtle Beach " LONGNAME " Linux Driver");
@@ -1342,35 +1493,135 @@ MODULE_PARM (mem, "i");
MODULE_PARM (major, "i");
MODULE_PARM (fifosize, "i");
MODULE_PARM (calibrate_signal, "i");
+#ifndef MSND_CLASSIC
+MODULE_PARM (digital, "i");
+MODULE_PARM (cfg, "i");
+MODULE_PARM (reset, "i");
+MODULE_PARM (mpu_io, "i");
+MODULE_PARM (mpu_irq, "i");
+MODULE_PARM (ide_io0, "i");
+MODULE_PARM (ide_io1, "i");
+MODULE_PARM (ide_irq, "i");
+MODULE_PARM (joystick_io, "i");
+#endif
static int io __initdata = -1;
static int irq __initdata = -1;
static int mem __initdata = -1;
+
+#ifndef MSND_CLASSIC
+/* Pinnacle/Fiji non-PnP Config Port */
+static int cfg __initdata = -1;
+
+/* Extra Peripheral Configuration */
+static int reset __initdata;
+static int mpu_io __initdata;
+static int mpu_irq __initdata;
+static int ide_io0 __initdata;
+static int ide_io1 __initdata;
+static int ide_irq __initdata;
+static int joystick_io __initdata;
+
+/* If we have the digital daugherboard... */
+static int digital __initdata;
+#endif
+
static int fifosize __initdata = DEFFIFOSIZE;
static int calibrate_signal __initdata;
+/* If we're a module, this is just init_module */
+
int init_module(void)
+
#else /* not a module */
+
#ifdef MSND_CLASSIC
static int io __initdata = CONFIG_MSNDCLAS_IO;
static int irq __initdata = CONFIG_MSNDCLAS_IRQ;
static int mem __initdata = CONFIG_MSNDCLAS_MEM;
-#else
+#else /* Pinnacle/Fiji */
+
static int io __initdata = CONFIG_MSNDPIN_IO;
static int irq __initdata = CONFIG_MSNDPIN_IRQ;
static int mem __initdata = CONFIG_MSNDPIN_MEM;
+
+/* Pinnacle/Fiji non-PnP Config Port */
+#ifdef CONFIG_MSNDPIN_NONPNP
+# ifndef CONFIG_MSNDPIN_CFG
+# define CONFIG_MSNDPIN_CFG 0x250
+# endif
+#else
+# ifdef CONFIG_MSNDPIN_CFG
+# undef CONFIG_MSNDPIN_CFG
+# endif
+# define CONFIG_MSNDPIN_CFG -1
#endif
-static int fifosize __initdata = DEFFIFOSIZE;
-static int calibrate_signal __initdata;
+static int cfg __initdata = CONFIG_MSNDPIN_CFG;
+/* If not a module, we don't need to bother with reset=1 */
+static int reset __initdata;
+
+/* Extra Peripheral Configuration (Default: Disable) */
+#ifndef CONFIG_MSNDPIN_MPU_IO
+# define CONFIG_MSNDPIN_MPU_IO 0
+#endif
+static int mpu_io __initdata = CONFIG_MSNDPIN_MPU_IO;
+
+#ifndef CONFIG_MSNDPIN_MPU_IRQ
+# define CONFIG_MSNDPIN_MPU_IRQ 0
+#endif
+static int mpu_irq __initdata = CONFIG_MSNDPIN_MPU_IRQ;
+
+#ifndef CONFIG_MSNDPIN_IDE_IO0
+# define CONFIG_MSNDPIN_IDE_IO0 0
+#endif
+static int ide_io0 __initdata = CONFIG_MSNDPIN_IDE_IO0;
+
+#ifndef CONFIG_MSNDPIN_IDE_IO1
+# define CONFIG_MSNDPIN_IDE_IO1 0
+#endif
+static int ide_io1 __initdata = CONFIG_MSNDPIN_IDE_IO1;
+
+#ifndef CONFIG_MSNDPIN_IDE_IRQ
+# define CONFIG_MSNDPIN_IDE_IRQ 0
+#endif
+static int ide_irq __initdata = CONFIG_MSNDPIN_IDE_IRQ;
+
+#ifndef CONFIG_MSNDPIN_JOYSTICK_IO
+# define CONFIG_MSNDPIN_JOYSTICK_IO 0
+#endif
+static int joystick_io __initdata = CONFIG_MSNDPIN_JOYSTICK_IO;
+
+/* Have SPDIF (Digital) Daughterboard */
+#ifndef CONFIG_MSNDPIN_DIGITAL
+# define CONFIG_MSNDPIN_DIGITAL 0
+#endif
+static int digital __initdata = CONFIG_MSNDPIN_DIGITAL;
+
+#endif /* MSND_CLASSIC */
+
+#ifndef CONFIG_MSND_FIFOSIZE
+# define CONFIG_MSND_FIFOSIZE DEFFIFOSIZE
+#endif
+static int fifosize __initdata = CONFIG_MSND_FIFOSIZE;
+
+#ifndef CONFIG_MSND_CALSIGNAL
+# define CONFIG_MSND_CALSIGNAL 0
+#endif
+static int
+calibrate_signal __initdata = CONFIG_MSND_CALSIGNAL;
#ifdef MSND_CLASSIC
__initfunc(int msnd_classic_init(void))
#else
__initfunc(int msnd_pinnacle_init(void))
#endif /* MSND_CLASSIC */
-#endif
+
+#endif /* MODULE */
{
int err;
+#ifndef MSND_CLASSIC
+ static msnd_pinnacle_cfg_t pinnacle_devs;
+#endif /* MSND_CLASSIC */
printk(KERN_INFO LOGNAME ": Turtle Beach " LONGNAME " Linux Driver Version "
VERSION ", Copyright (C) 1998 Andrew Veliath\n");
@@ -1379,7 +1630,7 @@ __initfunc(int msnd_pinnacle_init(void))
printk(KERN_WARNING LOGNAME ": io, irq and mem must be set\n");
}
-
+
if (io == -1 ||
!(io == 0x290 ||
io == 0x260 ||
@@ -1390,7 +1641,7 @@ __initfunc(int msnd_pinnacle_init(void))
io == 0x210 ||
io == 0x3e0)) {
- printk(KERN_ERR LOGNAME ": \"io\" - DSP I/O base must be set\n");
+ printk(KERN_ERR LOGNAME ": \"io\" - DSP I/O base must be set to 0x210, 0x220, 0x230, 0x240, 0x250, 0x260, 0x290, or 0x3E0\n");
return -EINVAL;
}
@@ -1437,6 +1688,47 @@ __initfunc(int msnd_pinnacle_init(void))
case 0xe0000: dev.memid = HPMEM_E000; break;
case 0xe8000: dev.memid = HPMEM_E800; break;
}
+#else
+ if (cfg == -1) {
+ printk(KERN_INFO LOGNAME ": Assuming PnP mode\n");
+ } else if (cfg != 0x250 && cfg != 0x260 && cfg != 0x270) {
+ printk(KERN_INFO LOGNAME ": Config port must be 0x250, 0x260 or 0x270 (or unspecified for PnP mode)\n");
+ return -EINVAL;
+ } else {
+ printk(KERN_INFO LOGNAME ": Non-PnP mode: configuring at port 0x%x\n", cfg);
+
+ /* DSP */
+ pinnacle_devs[0].io0 = io;
+ pinnacle_devs[0].irq = irq;
+ pinnacle_devs[0].mem = mem;
+
+ /* The following are Pinnacle specific */
+
+ /* MPU */
+ pinnacle_devs[1].io0 = mpu_io;
+ pinnacle_devs[1].irq = mpu_irq;
+
+ /* IDE */
+ pinnacle_devs[2].io0 = ide_io0;
+ pinnacle_devs[2].io1 = ide_io1;
+ pinnacle_devs[2].irq = ide_irq;
+
+ /* Joystick */
+ pinnacle_devs[3].io0 = joystick_io;
+
+ if (check_region(cfg, 2)) {
+ printk(KERN_ERR LOGNAME ": Config port 0x%x conflict\n", cfg);
+ return -EIO;
+ }
+
+ request_region(cfg, 2, "Pinnacle/Fiji Config");
+ if (msnd_pinnacle_cfg_devices(cfg, reset, pinnacle_devs)) {
+ printk(KERN_ERR LOGNAME ": Device configuration error\n");
+ release_region(cfg, 2);
+ return -EIO;
+ }
+ release_region(cfg, 2);
+ }
#endif /* MSND_CLASSIC */
if (fifosize < 16)
@@ -1460,6 +1752,13 @@ __initfunc(int msnd_pinnacle_init(void))
dev.inc_ref = mod_inc_ref;
dev.dec_ref = mod_dec_ref;
+#ifndef MSND_CLASSIC
+ if (digital) {
+ set_bit(F_HAVEDIGITAL, &dev.flags);
+ printk(KERN_INFO LOGNAME ": Digital I/O access enabled\n");
+ }
+#endif
+
init_waitqueue(&dev.writeblock);
init_waitqueue(&dev.readblock);
init_waitqueue(&dev.writeflush);
diff --git a/drivers/sound/msnd_pinnacle.h b/drivers/sound/msnd_pinnacle.h
index f6971c949..0ae9a1026 100644
--- a/drivers/sound/msnd_pinnacle.h
+++ b/drivers/sound/msnd_pinnacle.h
@@ -24,7 +24,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * $Id: msnd_pinnacle.h,v 1.5 1998/07/18 00:12:16 andrewtv Exp $
+ * $Id: msnd_pinnacle.h,v 1.8 1998/09/03 06:39:47 andrewtv Exp $
*
********************************************************************/
#ifndef __MSND_PINNACLE_H
@@ -32,189 +32,196 @@
#include <linux/config.h>
-#define DSP_NUMIO 0x08
-
-#define HP_DSPR 0x04
-#define HP_BLKS 0x04
-
-#define HPDSPRESET_OFF 2
-#define HPDSPRESET_ON 0
-
-#define HPBLKSEL_0 2
-#define HPBLKSEL_1 3
-
-#define HIMT_DAT_OFF 0x03
-
-#define HIDSP_PLAY_UNDER 0x00
-#define HIDSP_INT_PLAY_UNDER 0x01
-#define HIDSP_SSI_TX_UNDER 0x02
-#define HIDSP_RECQ_OVERFLOW 0x08
-#define HIDSP_INT_RECORD_OVER 0x09
-#define HIDSP_SSI_RX_OVERFLOW 0x0a
-
-#define HIDSP_MIDI_IN_OVER 0x10
-
-#define HIDSP_MIDI_FRAME_ERR 0x11
-#define HIDSP_MIDI_PARITY_ERR 0x12
-#define HIDSP_MIDI_OVERRUN_ERR 0x13
-
-#define HIDSP_INPUT_CLIPPING 0x20
-#define HIDSP_MIX_CLIPPING 0x30
-#define HIDSP_DAT_IN_OFF 0x21
-
-#define HDEXAR_SET_ANA_IN 0
-#define HDEXAR_CLEAR_PEAKS 1
-#define HDEXAR_IN_SET_POTS 2
-#define HDEXAR_AUX_SET_POTS 3
-#define HDEXAR_CAL_A_TO_D 4
-#define HDEXAR_RD_EXT_DSP_BITS 5
-
-#define HDEXAR_SET_SYNTH_IN 4
-#define HDEXAR_READ_DAT_IN 5
-#define HDEXAR_MIC_SET_POTS 6
-#define HDEXAR_SET_DAT_IN 7
-
-#define HDEXAR_SET_SYNTH_48 8
-#define HDEXAR_SET_SYNTH_44 9
-
-#define TIME_PRO_RESET_DONE 0x028A
-#define TIME_PRO_SYSEX 0x001E
-#define TIME_PRO_RESET 0x0032
-
-#define AGND 0x01
-#define SIGNAL 0x02
-
-#define EXT_DSP_BIT_DCAL 0x0001
-#define EXT_DSP_BIT_MIDI_CON 0x0002
-
-#define BUFFSIZE 0x8000
-#define HOSTQ_SIZE 0x40
-
-#define SRAM_CNTL_START 0x7F00
-#define SMA_STRUCT_START 0x7F40
-
-#define DAP_BUFF_SIZE 0x2400
-#define DAR_BUFF_SIZE 0x2000
-
-#define DAPQ_STRUCT_SIZE 0x10
-#define DARQ_STRUCT_SIZE 0x10
-#define DAPQ_BUFF_SIZE (3 * 0x10)
-#define DARQ_BUFF_SIZE (3 * 0x10)
-#define MODQ_BUFF_SIZE 0x400
-#define MIDQ_BUFF_SIZE 0x800
-#define DSPQ_BUFF_SIZE 0x5A0
-
-#define DAPQ_DATA_BUFF 0x6C00
-#define DARQ_DATA_BUFF 0x6C30
-#define MODQ_DATA_BUFF 0x6C60
-#define MIDQ_DATA_BUFF 0x7060
-#define DSPQ_DATA_BUFF 0x7860
-
-#define DAPQ_OFFSET SRAM_CNTL_START
-#define DARQ_OFFSET (SRAM_CNTL_START + 0x08)
-#define MODQ_OFFSET (SRAM_CNTL_START + 0x10)
-#define MIDQ_OFFSET (SRAM_CNTL_START + 0x18)
-#define DSPQ_OFFSET (SRAM_CNTL_START + 0x20)
-
-#define WAVEHDR_MOP 0
-#define EXTOUT_MOP 1
-#define HWINIT_MOP 0xFE
-#define NO_MOP 0xFF
-
-#define MAX_MOP 1
-
-#define EXTIN_MIP 0
-#define WAVEHDR_MIP 1
-#define HWINIT_MIP 0xFE
-
-#define MAX_MIP 1
-
-struct SMA0_CommonData {
- WORD wCurrPlayBytes;
- WORD wCurrRecordBytes;
- WORD wCurrPlayVolLeft;
- WORD wCurrPlayVolRight;
-
- WORD wCurrInVolLeft;
- WORD wCurrInVolRight;
- WORD wCurrMHdrVolLeft;
- WORD wCurrMHdrVolRight;
-
- DWORD dwCurrPlayPitch;
- DWORD dwCurrPlayRate;
-
- WORD wCurrMIDIIOPatch;
-
- WORD wCurrPlayFormat;
- WORD wCurrPlaySampleSize;
- WORD wCurrPlayChannels;
- WORD wCurrPlaySampleRate;
-
- WORD wCurrRecordFormat;
- WORD wCurrRecordSampleSize;
- WORD wCurrRecordChannels;
- WORD wCurrRecordSampleRate;
-
- WORD wCurrDSPStatusFlags;
- WORD wCurrHostStatusFlags;
-
- WORD wCurrInputTagBits;
- WORD wCurrLeftPeak;
- WORD wCurrRightPeak;
-
- BYTE bMicPotPosLeft;
- BYTE bMicPotPosRight;
-
- BYTE bMicPotMaxLeft;
- BYTE bMicPotMaxRight;
-
- BYTE bInPotPosLeft;
- BYTE bInPotPosRight;
-
- BYTE bAuxPotPosLeft;
- BYTE bAuxPotPosRight;
-
- BYTE bInPotMaxLeft;
- BYTE bInPotMaxRight;
- BYTE bAuxPotMaxLeft;
- BYTE bAuxPotMaxRight;
- BYTE bInPotMaxMethod;
- BYTE bAuxPotMaxMethod;
-
- WORD wCurrMastVolLeft;
- WORD wCurrMastVolRight;
-
- WORD wCalFreqAtoD;
-
- WORD wCurrAuxVolLeft;
- WORD wCurrAuxVolRight;
-
- WORD wCurrPlay1VolLeft;
- WORD wCurrPlay1VolRight;
- WORD wCurrPlay2VolLeft;
- WORD wCurrPlay2VolRight;
- WORD wCurrPlay3VolLeft;
- WORD wCurrPlay3VolRight;
- WORD wCurrPlay4VolLeft;
- WORD wCurrPlay4VolRight;
- WORD wCurrPlay1PeakLeft;
- WORD wCurrPlay1PeakRight;
- WORD wCurrPlay2PeakLeft;
- WORD wCurrPlay2PeakRight;
- WORD wCurrPlay3PeakLeft;
- WORD wCurrPlay3PeakRight;
- WORD wCurrPlay4PeakLeft;
- WORD wCurrPlay4PeakRight;
- WORD wCurrPlayPeakLeft;
- WORD wCurrPlayPeakRight;
-
- WORD wCurrDATSR;
- WORD wCurrDATRXCHNL;
- WORD wCurrDATTXCHNL;
- WORD wCurrDATRXRate;
-
- DWORD dwDSPPlayCount;
-} GCC_PACKED;
+#define DSP_NUMIO 0x08
+
+#define IREG_LOGDEVICE 0x07
+#define IREG_ACTIVATE 0x30
+#define LD_ACTIVATE 0x01
+#define LD_DISACTIVATE 0x00
+#define IREG_EECONTROL 0x3F
+#define IREG_MEMBASEHI 0x40
+#define IREG_MEMBASELO 0x41
+#define IREG_MEMCONTROL 0x42
+#define IREG_MEMRANGEHI 0x43
+#define IREG_MEMRANGELO 0x44
+#define MEMTYPE_8BIT 0x00
+#define MEMTYPE_16BIT 0x02
+#define MEMTYPE_RANGE 0x00
+#define MEMTYPE_HIADDR 0x01
+#define IREG_IO0_BASEHI 0x60
+#define IREG_IO0_BASELO 0x61
+#define IREG_IO1_BASEHI 0x62
+#define IREG_IO1_BASELO 0x63
+#define IREG_IRQ_NUMBER 0x70
+#define IREG_IRQ_TYPE 0x71
+#define IRQTYPE_HIGH 0x02
+#define IRQTYPE_LOW 0x00
+#define IRQTYPE_LEVEL 0x01
+#define IRQTYPE_EDGE 0x00
+
+#define HP_DSPR 0x04
+#define HP_BLKS 0x04
+
+#define HPDSPRESET_OFF 2
+#define HPDSPRESET_ON 0
+
+#define HPBLKSEL_0 2
+#define HPBLKSEL_1 3
+
+#define HIMT_DAT_OFF 0x03
+
+#define HIDSP_PLAY_UNDER 0x00
+#define HIDSP_INT_PLAY_UNDER 0x01
+#define HIDSP_SSI_TX_UNDER 0x02
+#define HIDSP_RECQ_OVERFLOW 0x08
+#define HIDSP_INT_RECORD_OVER 0x09
+#define HIDSP_SSI_RX_OVERFLOW 0x0a
+
+#define HIDSP_MIDI_IN_OVER 0x10
+
+#define HIDSP_MIDI_FRAME_ERR 0x11
+#define HIDSP_MIDI_PARITY_ERR 0x12
+#define HIDSP_MIDI_OVERRUN_ERR 0x13
+
+#define HIDSP_INPUT_CLIPPING 0x20
+#define HIDSP_MIX_CLIPPING 0x30
+#define HIDSP_DAT_IN_OFF 0x21
+
+#define HDEXAR_SET_ANA_IN 0
+#define HDEXAR_CLEAR_PEAKS 1
+#define HDEXAR_IN_SET_POTS 2
+#define HDEXAR_AUX_SET_POTS 3
+#define HDEXAR_CAL_A_TO_D 4
+#define HDEXAR_RD_EXT_DSP_BITS 5
+
+#define HDEXAR_SET_SYNTH_IN 4
+#define HDEXAR_READ_DAT_IN 5
+#define HDEXAR_MIC_SET_POTS 6
+#define HDEXAR_SET_DAT_IN 7
+
+#define HDEXAR_SET_SYNTH_48 8
+#define HDEXAR_SET_SYNTH_44 9
+
+#define TIME_PRO_RESET_DONE 0x028A
+#define TIME_PRO_SYSEX 0x001E
+#define TIME_PRO_RESET 0x0032
+
+#define AGND 0x01
+#define SIGNAL 0x02
+
+#define EXT_DSP_BIT_DCAL 0x0001
+#define EXT_DSP_BIT_MIDI_CON 0x0002
+
+#define BUFFSIZE 0x8000
+#define HOSTQ_SIZE 0x40
+
+#define SRAM_CNTL_START 0x7F00
+#define SMA_STRUCT_START 0x7F40
+
+#define DAP_BUFF_SIZE 0x2400
+#define DAR_BUFF_SIZE 0x2000
+
+#define DAPQ_STRUCT_SIZE 0x10
+#define DARQ_STRUCT_SIZE 0x10
+#define DAPQ_BUFF_SIZE (3 * 0x10)
+#define DARQ_BUFF_SIZE (3 * 0x10)
+#define MODQ_BUFF_SIZE 0x400
+#define MIDQ_BUFF_SIZE 0x800
+#define DSPQ_BUFF_SIZE 0x5A0
+
+#define DAPQ_DATA_BUFF 0x6C00
+#define DARQ_DATA_BUFF 0x6C30
+#define MODQ_DATA_BUFF 0x6C60
+#define MIDQ_DATA_BUFF 0x7060
+#define DSPQ_DATA_BUFF 0x7860
+
+#define DAPQ_OFFSET SRAM_CNTL_START
+#define DARQ_OFFSET (SRAM_CNTL_START + 0x08)
+#define MODQ_OFFSET (SRAM_CNTL_START + 0x10)
+#define MIDQ_OFFSET (SRAM_CNTL_START + 0x18)
+#define DSPQ_OFFSET (SRAM_CNTL_START + 0x20)
+
+#define WAVEHDR_MOP 0
+#define EXTOUT_MOP 1
+#define HWINIT_MOP 0xFE
+#define NO_MOP 0xFF
+
+#define MAX_MOP 1
+
+#define EXTIN_MIP 0
+#define WAVEHDR_MIP 1
+#define HWINIT_MIP 0xFE
+
+#define MAX_MIP 1
+
+/* Pinnacle/Fiji SMA Common Data */
+#define SMA_wCurrPlayBytes 0x0000
+#define SMA_wCurrRecordBytes 0x0002
+#define SMA_wCurrPlayVolLeft 0x0004
+#define SMA_wCurrPlayVolRight 0x0006
+#define SMA_wCurrInVolLeft 0x0008
+#define SMA_wCurrInVolRight 0x000a
+#define SMA_wCurrMHdrVolLeft 0x000c
+#define SMA_wCurrMHdrVolRight 0x000e
+#define SMA_dwCurrPlayPitch 0x0010
+#define SMA_dwCurrPlayRate 0x0014
+#define SMA_wCurrMIDIIOPatch 0x0018
+#define SMA_wCurrPlayFormat 0x001a
+#define SMA_wCurrPlaySampleSize 0x001c
+#define SMA_wCurrPlayChannels 0x001e
+#define SMA_wCurrPlaySampleRate 0x0020
+#define SMA_wCurrRecordFormat 0x0022
+#define SMA_wCurrRecordSampleSize 0x0024
+#define SMA_wCurrRecordChannels 0x0026
+#define SMA_wCurrRecordSampleRate 0x0028
+#define SMA_wCurrDSPStatusFlags 0x002a
+#define SMA_wCurrHostStatusFlags 0x002c
+#define SMA_wCurrInputTagBits 0x002e
+#define SMA_wCurrLeftPeak 0x0030
+#define SMA_wCurrRightPeak 0x0032
+#define SMA_bMicPotPosLeft 0x0034
+#define SMA_bMicPotPosRight 0x0035
+#define SMA_bMicPotMaxLeft 0x0036
+#define SMA_bMicPotMaxRight 0x0037
+#define SMA_bInPotPosLeft 0x0038
+#define SMA_bInPotPosRight 0x0039
+#define SMA_bAuxPotPosLeft 0x003a
+#define SMA_bAuxPotPosRight 0x003b
+#define SMA_bInPotMaxLeft 0x003c
+#define SMA_bInPotMaxRight 0x003d
+#define SMA_bAuxPotMaxLeft 0x003e
+#define SMA_bAuxPotMaxRight 0x003f
+#define SMA_bInPotMaxMethod 0x0040
+#define SMA_bAuxPotMaxMethod 0x0041
+#define SMA_wCurrMastVolLeft 0x0042
+#define SMA_wCurrMastVolRight 0x0044
+#define SMA_wCalFreqAtoD 0x0046
+#define SMA_wCurrAuxVolLeft 0x0048
+#define SMA_wCurrAuxVolRight 0x004a
+#define SMA_wCurrPlay1VolLeft 0x004c
+#define SMA_wCurrPlay1VolRight 0x004e
+#define SMA_wCurrPlay2VolLeft 0x0050
+#define SMA_wCurrPlay2VolRight 0x0052
+#define SMA_wCurrPlay3VolLeft 0x0054
+#define SMA_wCurrPlay3VolRight 0x0056
+#define SMA_wCurrPlay4VolLeft 0x0058
+#define SMA_wCurrPlay4VolRight 0x005a
+#define SMA_wCurrPlay1PeakLeft 0x005c
+#define SMA_wCurrPlay1PeakRight 0x005e
+#define SMA_wCurrPlay2PeakLeft 0x0060
+#define SMA_wCurrPlay2PeakRight 0x0062
+#define SMA_wCurrPlay3PeakLeft 0x0064
+#define SMA_wCurrPlay3PeakRight 0x0066
+#define SMA_wCurrPlay4PeakLeft 0x0068
+#define SMA_wCurrPlay4PeakRight 0x006a
+#define SMA_wCurrPlayPeakLeft 0x006c
+#define SMA_wCurrPlayPeakRight 0x006e
+#define SMA_wCurrDATSR 0x0070
+#define SMA_wCurrDATRXCHNL 0x0072
+#define SMA_wCurrDATTXCHNL 0x0074
+#define SMA_wCurrDATRXRate 0x0076
+#define SMA_dwDSPPlayCount 0x0078
+#define SMA__size 0x007c
#ifdef HAVE_DSPCODEH
# include "pndsperm.c"
diff --git a/drivers/sound/opl3.c b/drivers/sound/opl3.c
index bc6382f99..8898c655a 100644
--- a/drivers/sound/opl3.c
+++ b/drivers/sound/opl3.c
@@ -169,7 +169,7 @@ int opl3_detect(int ioaddr, int *osp)
if (devc == NULL)
{
- printk(KERN_ERR "OPL3: Can't allocate memory for the device control "
+ printk(KERN_ERR "opl3: Can't allocate memory for the device control "
"structure \n ");
return 0;
}
@@ -495,7 +495,7 @@ static int opl3_start_note (int dev, int voice, int note, int volume)
if (instr->channel < 0)
{
- printk(KERN_WARNING "OPL3: Initializing voice %d with undefined instrument\n", voice);
+ printk(KERN_WARNING "opl3: Initializing voice %d with undefined instrument\n", voice);
return 0;
}
@@ -1091,7 +1091,7 @@ int opl3_init(int ioaddr, int *osp)
if (devc == NULL)
{
- printk(KERN_ERR "opl3_init: Device control structure not initialized.\n");
+ printk(KERN_ERR "opl3: Device control structure not initialized.\n");
return -1;
}
@@ -1137,16 +1137,15 @@ int opl3_init(int ioaddr, int *osp)
if (devc->model == 2)
{
- if (devc->is_opl4)
- conf_printf2("Yamaha OPL4/OPL3 FM", ioaddr, 0, -1, -1);
- else
- conf_printf2("Yamaha OPL3 FM", ioaddr, 0, -1, -1);
+ if (devc->is_opl4)
+ strcpy(devc->fm_info.name, "Yamaha OPL4/OPL3 FM");
+ else
+ strcpy(devc->fm_info.name, "Yamaha OPL3");
devc->v_alloc->max_voice = devc->nr_voice = 18;
devc->fm_info.nr_drums = 0;
devc->fm_info.synth_subtype = FM_TYPE_OPL3;
devc->fm_info.capabilities |= SYNTH_CAP_OPL3;
- strcpy(devc->fm_info.name, "Yamaha OPL-3");
for (i = 0; i < 18; i++)
{
@@ -1160,13 +1159,14 @@ int opl3_init(int ioaddr, int *osp)
}
else
{
- conf_printf2("Yamaha OPL2 FM", ioaddr, 0, -1, -1);
+ strcpy(devc->fm_info.name, "Yamaha OPL2");
devc->v_alloc->max_voice = devc->nr_voice = 9;
devc->fm_info.nr_drums = 0;
for (i = 0; i < 18; i++)
pv_map[i].ioaddr = devc->left_io;
};
+ conf_printf2(devc->fm_info.name, ioaddr, 0, -1, -1);
for (i = 0; i < SBFM_MAXINSTR; i++)
devc->i_map[i].channel = -1;
@@ -1185,14 +1185,21 @@ int me;
int init_module (void)
{
- printk("YM3812 and OPL-3 driver Copyright (C) by Hannu Savolainen, Rob Hooft 1993-1996\n");
+ printk(KERN_INFO "YM3812 and OPL-3 driver Copyright (C) by Hannu Savolainen, Rob Hooft 1993-1996\n");
if (io != -1) /* User loading pure OPL3 module */
{
+ if (check_region(io, 4))
+ {
+ printk(KERN_WARNING "opl3: I/O port 0x%x already in use\n", io);
+ return 0;
+ }
if (!opl3_detect(io, NULL))
{
return -ENODEV;
}
me = opl3_init(io, NULL);
+ request_region(io,4,devc->fm_info.name);
+
}
SOUND_LOCK;
return 0;
@@ -1202,6 +1209,8 @@ void cleanup_module(void)
{
if (devc)
{
+ if(devc->base)
+ release_region(devc->base,4);
kfree(devc);
devc = NULL;
sound_unload_synthdev(me);
diff --git a/drivers/sound/sb.h b/drivers/sound/sb.h
index 8d7ffe1a7..19f8ee825 100644
--- a/drivers/sound/sb.h
+++ b/drivers/sound/sb.h
@@ -121,7 +121,7 @@ int sb_dsp_reset (sb_devc *devc);
void sb_setmixer (sb_devc *devc, unsigned int port, unsigned int value);
unsigned int sb_getmixer (sb_devc *devc, unsigned int port);
int sb_dsp_detect (struct address_info *hw_config);
-void sb_dsp_init (struct address_info *hw_config);
+int sb_dsp_init (struct address_info *hw_config);
void sb_dsp_unload(struct address_info *hw_config);
int sb_mixer_init(sb_devc *devc);
void sb_mixer_set_stereo (sb_devc *devc, int mode);
diff --git a/drivers/sound/sb_card.c b/drivers/sound/sb_card.c
index 432501ebc..2fc88cb24 100644
--- a/drivers/sound/sb_card.c
+++ b/drivers/sound/sb_card.c
@@ -25,7 +25,8 @@
void attach_sb_card(struct address_info *hw_config)
{
#if defined(CONFIG_AUDIO) || defined(CONFIG_MIDI)
- sb_dsp_init(hw_config);
+ if(!sb_dsp_init(hw_config))
+ hw_config->slots[0] = -1;
#endif
}
@@ -41,7 +42,8 @@ int probe_sb(struct address_info *hw_config)
void unload_sb(struct address_info *hw_config)
{
- sb_dsp_unload(hw_config);
+ if(hw_config->slots[0]!=-1)
+ sb_dsp_unload(hw_config);
}
int sb_be_quiet=0;
@@ -92,7 +94,7 @@ int init_module(void)
{
if (io == -1 || dma == -1 || irq == -1)
{
- printk(KERN_ERR "I/O, IRQ, and DMA are mandatory\n");
+ printk(KERN_ERR "sb_card: I/O, IRQ, and DMA are mandatory\n");
return -EINVAL;
}
config.io_base = io;
@@ -104,6 +106,9 @@ int init_module(void)
if (!probe_sb(&config))
return -ENODEV;
attach_sb_card(&config);
+
+ if(config.slots[0]==-1)
+ return -ENODEV;
#ifdef CONFIG_MIDI
config_mpu.io_base = mpu_io;
if (mpu_io && probe_sbmpu(&config_mpu))
diff --git a/drivers/sound/sb_common.c b/drivers/sound/sb_common.c
index 8fe5a44f0..04b3d7854 100644
--- a/drivers/sound/sb_common.c
+++ b/drivers/sound/sb_common.c
@@ -162,7 +162,7 @@ static void sbintr(int irq, void *dev_id, struct pt_regs *dummy)
break;
default:
- /* printk( "Sound Blaster: Unexpected interrupt\n"); */
+ /* printk(KERN_WARN "Sound Blaster: Unexpected interrupt\n"); */
;
}
}
@@ -242,7 +242,7 @@ static int sb16_set_dma_hw(sb_devc * devc)
if (devc->dma8 != 0 && devc->dma8 != 1 && devc->dma8 != 3)
{
- printk(KERN_ERR "sb16: Invalid 8 bit DMA (%d)\n", devc->dma8);
+ printk(KERN_ERR "SB16: Invalid 8 bit DMA (%d)\n", devc->dma8);
return 0;
}
bits = (1 << devc->dma8);
@@ -298,7 +298,7 @@ static int sb16_set_irq_hw(sb_devc * devc, int level)
ival = 8;
break;
default:
- printk(KERN_ERR "SB16 IRQ%d is not possible\n", level);
+ printk(KERN_ERR "SB16: Invalid IRQ%d\n", level);
return 0;
}
sb_setmixer(devc, IRQ_NR, ival);
@@ -694,7 +694,7 @@ int sb_dsp_detect(struct address_info *hw_config)
return 1;
}
-void sb_dsp_init(struct address_info *hw_config)
+int sb_dsp_init(struct address_info *hw_config)
{
sb_devc *devc;
char name[100];
@@ -710,7 +710,7 @@ void sb_dsp_init(struct address_info *hw_config)
if (detected_devc == NULL)
{
MDB(printk("No detected device\n"));
- return;
+ return 0;
}
devc = detected_devc;
detected_devc = NULL;
@@ -718,7 +718,7 @@ void sb_dsp_init(struct address_info *hw_config)
if (devc->base != hw_config->io_base)
{
DDB(printk("I/O port mismatch\n"));
- return;
+ return 0;
}
/*
* Now continue initialization of the device
@@ -731,7 +731,7 @@ void sb_dsp_init(struct address_info *hw_config)
if (request_irq(hw_config->irq, sbintr, 0, "soundblaster", devc) < 0)
{
printk(KERN_ERR "SB: Can't allocate IRQ%d\n", hw_config->irq);
- return;
+ return 0;
}
devc->irq_ok = 0;
@@ -739,7 +739,7 @@ void sb_dsp_init(struct address_info *hw_config)
if (!sb16_set_irq_hw(devc, devc->irq)) /* Unsupported IRQ */
{
free_irq(devc->irq, devc);
- return;
+ return 0;
}
if ((devc->type == 0 || devc->type == MDL_ESS) &&
devc->major == 3 && devc->minor == 1)
@@ -853,7 +853,11 @@ void sb_dsp_init(struct address_info *hw_config)
else
devc->dma16 = hw_config->dma2;
- sb16_set_dma_hw(devc);
+ if(!sb16_set_dma_hw(devc)) {
+ free_irq(devc->irq, devc);
+ return 0;
+ }
+
devc->caps |= SB_NO_MIDI;
}
@@ -903,7 +907,7 @@ void sb_dsp_init(struct address_info *hw_config)
{
if (sound_alloc_dma(devc->dma8, "SoundBlaster8"))
{
- printk(KERN_WARNING "SB: Can't allocate 8 bit DMA channel %d\n", devc->dma8);
+ printk(KERN_WARNING "Sound Blaster: Can't allocate 8 bit DMA channel %d\n", devc->dma8);
}
if (devc->dma16 >= 0 && devc->dma16 != devc->dma8)
{
@@ -917,6 +921,7 @@ void sb_dsp_init(struct address_info *hw_config)
{
MDB(printk("Sound Blaster: no audio devices found.\n"));
}
+ return 1;
}
void sb_dsp_disable_midi(int io_base)
@@ -1160,7 +1165,9 @@ static int ess_midi_init(sb_devc * devc, struct address_info *hw_config)
tmp = 1; /* MPU enabled without interrupts */
- switch (hw_config->irq)
+ /* May be shared: if so the value is -ve */
+
+ switch(abs(hw_config->irq))
{
case 9:
tmp = 0x4;
diff --git a/drivers/sound/sequencer.c b/drivers/sound/sequencer.c
index e4f962035..514333512 100644
--- a/drivers/sound/sequencer.c
+++ b/drivers/sound/sequencer.c
@@ -1061,7 +1061,10 @@ int sequencer_open(int dev, struct file *file)
setup_mode2();
}
if (!max_synthdev && !max_mididev)
+ {
+ sequencer_busy=0;
return -ENXIO;
+ }
synth_open_mask = 0;
diff --git a/drivers/sound/sonicvibes.c b/drivers/sound/sonicvibes.c
index 4f81fcdf3..82d0461a4 100644
--- a/drivers/sound/sonicvibes.c
+++ b/drivers/sound/sonicvibes.c
@@ -43,6 +43,10 @@
* Fix hwptr out of bounds (now mpg123 works)
* 14.05.98 0.4 Don't allow excessive interrupt rates
* 08.06.98 0.5 First release using Alan Cox' soundcore instead of miscdevice
+ * 03.08.98 0.6 Do not include modversions.h
+ * Now mixer behaviour can basically be selected between
+ * "OSS documented" and "OSS actual" behaviour
+ * 31.08.98 0.7 Fix realplayer problems - dac.count issues
*
*/
@@ -50,7 +54,6 @@
#include <linux/version.h>
#include <linux/module.h>
-#include <linux/modversions.h>
#include <linux/string.h>
#include <linux/ioport.h>
#include <linux/sched.h>
@@ -71,6 +74,10 @@
/* --------------------------------------------------------------------- */
+#undef OSS_DOCUMENTED_MIXER_SEMANTICS
+
+/* --------------------------------------------------------------------- */
+
#ifndef PCI_VENDOR_ID_S3
#define PCI_VENDOR_ID_S3 0x5333
#endif
@@ -245,6 +252,9 @@ struct sv_state {
/* mixer stuff */
struct {
unsigned int modcnt;
+#ifndef OSS_DOCUMENTED_MIXER_SEMANTICS
+ unsigned short vol[13];
+#endif /* OSS_DOCUMENTED_MIXER_SEMANTICS */
} mix;
/* wave stuff */
@@ -471,6 +481,7 @@ static unsigned setpll(struct sv_state *s, unsigned char reg, unsigned rate)
unsigned long flags;
unsigned char r, m, n;
unsigned xm, xn, xr, xd, metric = ~0U;
+ /* the warnings about m and n used uninitialized are bogus and may safely be ignored */
if (rate < 625000/ADCMULT)
rate = 625000/ADCMULT;
@@ -609,7 +620,7 @@ static void start_adc(struct sv_state *s)
unsigned long flags;
spin_lock_irqsave(&s->lock, flags);
- if ((s->dma_adc.mapped || s->dma_adc.count < s->dma_adc.dmasize - 2*s->dma_adc.fragsize)
+ if ((s->dma_adc.mapped || s->dma_adc.count < (signed)(s->dma_adc.dmasize - 2*s->dma_adc.fragsize))
&& s->dma_adc.ready) {
s->enable |= SV_CENABLE_RE;
wrindir(s, SV_CIENABLE, s->enable);
@@ -619,10 +630,9 @@ static void start_adc(struct sv_state *s)
/* --------------------------------------------------------------------- */
-#define DMABUF_DEFAULTORDER 8
+#define DMABUF_DEFAULTORDER (17-PAGE_SHIFT)
#define DMABUF_MINORDER 1
-
static void dealloc_dmabuf(struct dmabuf *db)
{
unsigned long map, mapend;
@@ -754,10 +764,10 @@ static void sv_update_ptr(struct sv_state *s)
s->dma_adc.total_bytes += diff;
s->dma_adc.count += diff;
if (s->dma_adc.mapped) {
- if (s->dma_adc.count >= s->dma_adc.fragsize)
+ if (s->dma_adc.count >= (signed)s->dma_adc.fragsize)
wake_up(&s->dma_adc.wait);
} else {
- if (s->dma_adc.count > s->dma_adc.dmasize - ((3 * s->dma_adc.fragsize) >> 1)) {
+ if (s->dma_adc.count > (signed)(s->dma_adc.dmasize - ((3 * s->dma_adc.fragsize) >> 1))) {
s->enable &= ~SV_CENABLE_RE;
wrindir(s, SV_CIENABLE, s->enable);
s->dma_adc.error++;
@@ -774,7 +784,7 @@ static void sv_update_ptr(struct sv_state *s)
s->dma_dac.total_bytes += diff;
if (s->dma_dac.mapped) {
s->dma_dac.count += diff;
- if (s->dma_dac.count >= s->dma_dac.fragsize)
+ if (s->dma_dac.count >= (signed)s->dma_dac.fragsize)
wake_up(&s->dma_dac.wait);
} else {
s->dma_dac.count -= diff;
@@ -782,11 +792,11 @@ static void sv_update_ptr(struct sv_state *s)
s->enable &= ~SV_CENABLE_PE;
wrindir(s, SV_CIENABLE, s->enable);
s->dma_dac.error++;
- } else if (s->dma_dac.count <= s->dma_dac.fragsize && !s->dma_dac.endcleared) {
+ } else if (s->dma_dac.count <= (signed)s->dma_dac.fragsize && !s->dma_dac.endcleared) {
clear_advance(s);
s->dma_dac.endcleared = 1;
}
- if (s->dma_dac.count < s->dma_dac.dmasize)
+ if (s->dma_dac.count < (signed)s->dma_dac.dmasize)
wake_up(&s->dma_dac.wait);
}
}
@@ -885,6 +895,8 @@ static const struct {
[SOUND_MIXER_PCM] = { SV_CIMIX_PCMINL, SV_CIMIX_PCMINR, MT_6MUTE, 0 }
};
+#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS
+
static int return_mixval(struct sv_state *s, unsigned i, int *arg)
{
unsigned long flags;
@@ -928,6 +940,23 @@ static int return_mixval(struct sv_state *s, unsigned i, int *arg)
return put_user((rr << 8) | rl, arg);
}
+#else /* OSS_DOCUMENTED_MIXER_SEMANTICS */
+
+static const unsigned char volidx[SOUND_MIXER_NRDEVICES] =
+{
+ [SOUND_MIXER_RECLEV] = 1,
+ [SOUND_MIXER_LINE1] = 2,
+ [SOUND_MIXER_CD] = 3,
+ [SOUND_MIXER_LINE] = 4,
+ [SOUND_MIXER_MIC] = 5,
+ [SOUND_MIXER_SYNTH] = 6,
+ [SOUND_MIXER_LINE2] = 7,
+ [SOUND_MIXER_VOLUME] = 8,
+ [SOUND_MIXER_PCM] = 9
+};
+
+#endif /* OSS_DOCUMENTED_MIXER_SEMANTICS */
+
static unsigned mixer_recmask(struct sv_state *s)
{
unsigned long flags;
@@ -1022,7 +1051,13 @@ static int mixer_ioctl(struct sv_state *s, unsigned int cmd, unsigned long arg)
i = _IOC_NR(cmd);
if (i >= SOUND_MIXER_NRDEVICES || !mixtable[i].type)
return -EINVAL;
+#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS
return return_mixval(s, i, (int *)arg);
+#else /* OSS_DOCUMENTED_MIXER_SEMANTICS */
+ if (!volidx[i])
+ return -EINVAL;
+ return put_user(s->mix.vol[volidx[i]-1], (int *)arg);
+#endif /* OSS_DOCUMENTED_MIXER_SEMANTICS */
}
}
if (_IOC_DIR(cmd) != (_IOC_READ|_IOC_WRITE))
@@ -1116,7 +1151,14 @@ static int mixer_ioctl(struct sv_state *s, unsigned int cmd, unsigned long arg)
break;
}
spin_unlock_irqrestore(&s->lock, flags);
+#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS
return return_mixval(s, i, (int *)arg);
+#else /* OSS_DOCUMENTED_MIXER_SEMANTICS */
+ if (!volidx[i])
+ return -EINVAL;
+ s->mix.vol[volidx[i]-1] = val;
+ return put_user(s->mix.vol[volidx[i]-1], (int *)arg);
+#endif /* OSS_DOCUMENTED_MIXER_SEMANTICS */
}
}
@@ -1167,6 +1209,7 @@ static /*const*/ struct file_operations sv_mixer_fops = {
&sv_ioctl_mixdev,
NULL, /* mmap */
&sv_open_mixdev,
+ NULL, /* flush */
&sv_release_mixdev,
NULL, /* fsync */
NULL, /* fasync */
@@ -1349,7 +1392,7 @@ static unsigned int sv_poll(struct file *file, struct poll_table_struct *wait)
sv_update_ptr(s);
if (file->f_flags & FMODE_READ) {
if (s->dma_adc.mapped) {
- if (s->dma_adc.count >= s->dma_adc.fragsize)
+ if (s->dma_adc.count >= (signed)s->dma_adc.fragsize)
mask |= POLLIN | POLLRDNORM;
} else {
if (s->dma_adc.count > 0)
@@ -1358,10 +1401,10 @@ static unsigned int sv_poll(struct file *file, struct poll_table_struct *wait)
}
if (file->f_flags & FMODE_WRITE) {
if (s->dma_dac.mapped) {
- if (s->dma_dac.count >= s->dma_dac.fragsize)
+ if (s->dma_dac.count >= (signed)s->dma_dac.fragsize)
mask |= POLLOUT | POLLWRNORM;
} else {
- if (s->dma_dac.dmasize > s->dma_dac.count)
+ if ((signed)s->dma_dac.dmasize > s->dma_dac.count)
mask |= POLLOUT | POLLWRNORM;
}
}
@@ -1769,6 +1812,7 @@ static /*const*/ struct file_operations sv_audio_fops = {
&sv_ioctl,
&sv_mmap,
&sv_open,
+ NULL, /* flush */
&sv_release,
NULL, /* fsync */
NULL, /* fasync */
@@ -2013,6 +2057,7 @@ static /*const*/ struct file_operations sv_midi_fops = {
NULL, /* ioctl */
NULL, /* mmap */
&sv_midi_open,
+ NULL, /* flush */
&sv_midi_release,
NULL, /* fsync */
NULL, /* fasync */
@@ -2186,6 +2231,7 @@ static /*const*/ struct file_operations sv_dmfm_fops = {
&sv_dmfm_ioctl,
NULL, /* mmap */
&sv_dmfm_open,
+ NULL, /* flush */
&sv_dmfm_release,
NULL, /* fsync */
NULL, /* fasync */
@@ -2200,7 +2246,10 @@ static /*const*/ struct file_operations sv_dmfm_fops = {
#define NR_DEVICE 5
static int reverb[NR_DEVICE] = { 0, };
+
+#if 0
static int wavetable[NR_DEVICE] = { 0, };
+#endif
static unsigned dmaio = 0xac00;
@@ -2234,7 +2283,7 @@ __initfunc(int init_sonicvibes(void))
if (!pci_present()) /* No PCI bus in this machine! */
return -ENODEV;
- printk(KERN_INFO "sv: version v0.5 time " __TIME__ " " __DATE__ "\n");
+ printk(KERN_INFO "sv: version v0.7 time " __TIME__ " " __DATE__ "\n");
#if 0
if (!(wavetable_mem = __get_free_pages(GFP_KERNEL, 20-PAGE_SHIFT)))
printk(KERN_INFO "sv: cannot allocate 1MB of contiguous nonpageable memory for wavetable data\n");
@@ -2297,7 +2346,6 @@ __initfunc(int init_sonicvibes(void))
/* hack */
pci_write_config_dword(pcidev, 0x60, wavetable_mem >> 12); /* wavetable base address */
-
if (check_region(s->ioenh, SV_EXTENT_ENH)) {
printk(KERN_ERR "sv: io ports %#x-%#x in use\n", s->ioenh, s->ioenh+SV_EXTENT_ENH-1);
goto err_region5;
@@ -2328,8 +2376,8 @@ __initfunc(int init_sonicvibes(void))
udelay(50);
outb(0x00, s->ioenh + SV_CODEC_CONTROL); /* deassert reset */
udelay(50);
- outb(SV_CCTRL_INTADRIVE | SV_CCTRL_ENHANCED /*| SV_CCTRL_WAVETABLE | SV_CCTRL_REVERB*/,
- s->ioenh + SV_CODEC_CONTROL);
+ outb(SV_CCTRL_INTADRIVE | SV_CCTRL_ENHANCED /*| SV_CCTRL_WAVETABLE */
+ | (reverb[index] ? SV_CCTRL_REVERB : 0), s->ioenh + SV_CODEC_CONTROL);
inb(s->ioenh + SV_CODEC_STATUS); /* clear ints */
wrindir(s, SV_CIDRIVECONTROL, 0); /* drive current 16mA */
wrindir(s, SV_CIENABLE, s->enable = 0); /* disable DMAA and DMAC */
@@ -2412,9 +2460,11 @@ __initfunc(int init_sonicvibes(void))
#ifdef MODULE
MODULE_PARM(reverb, "1-" __MODULE_STRING(NR_DEVICE) "i");
-MODULE_PARM_DESC(reverb, "if 1 enables joystick interface (still need separate driver)");
+MODULE_PARM_DESC(reverb, "if 1 enables the reverb circuitry. NOTE: your card must have the reverb RAM");
+#if 0
MODULE_PARM(wavetable, "1-" __MODULE_STRING(NR_DEVICE) "i");
-MODULE_PARM_DESC(wavetable, "if 1 the LINE input is converted to LINE out");
+MODULE_PARM_DESC(wavetable, "if 1 the wavetable synth is enabled");
+#endif
MODULE_PARM(dmaio, "i");
MODULE_PARM_DESC(dmaio, "if the motherboard BIOS did not allocate DDMA io, allocate them starting at this address");
diff --git a/drivers/sound/sound_core.c b/drivers/sound/sound_core.c
index 95ef40a0f..360028421 100644
--- a/drivers/sound/sound_core.c
+++ b/drivers/sound/sound_core.c
@@ -168,7 +168,7 @@ static void sound_remove_unit(struct sound_unit **list, int unit)
* 6 -- sndstat (obsolete)
* 7 *16 unused
* 8 -- alternate sequencer (see above)
- * 9 *16 unused
+ * 9 *16 raw synthesizer access
* 10 *16 unused
* 11 *16 unused
* 12 *16 unused
@@ -212,6 +212,13 @@ int register_sound_dsp(struct file_operations *fops)
EXPORT_SYMBOL(register_sound_dsp);
+int register_sound_synth(struct file_operations *fops)
+{
+ return sound_insert_unit(&chains[9], fops, 9, 137);
+}
+
+EXPORT_SYMBOL(register_sound_synth);
+
void unregister_sound_special(int unit)
{
sound_remove_unit(&chains[unit&15], unit);
@@ -240,6 +247,12 @@ void unregister_sound_dsp(int unit)
EXPORT_SYMBOL(unregister_sound_dsp);
+void unregister_sound_synth(int unit)
+{
+ return sound_remove_unit(&chains[9], unit);
+}
+
+EXPORT_SYMBOL(unregister_sound_synth);
/*
* Now our file operations
@@ -262,6 +275,7 @@ static struct file_operations soundcore_fops=
NULL,
NULL,
NULL,
+ NULL,
NULL
};
diff --git a/drivers/sound/soundcard.c b/drivers/sound/soundcard.c
index 2abd7fa22..1fbb368d8 100644
--- a/drivers/sound/soundcard.c
+++ b/drivers/sound/soundcard.c
@@ -769,6 +769,7 @@ struct file_operations oss_sound_fops =
sound_ioctl,
sound_mmap,
sound_open,
+ NULL, /* flush */
sound_release
};
@@ -846,12 +847,16 @@ static int sound[20] = {
#ifdef MODULE
+int traceinit = 0;
+MODULE_PARM(traceinit, "i");
+
int init_module(void)
{
int err;
int ints[21];
int i;
+ trace_init=traceinit;
/*
* "sound=" command line handling by Harald Milz.
*/
diff --git a/drivers/sound/wavfront.c b/drivers/sound/wavfront.c
index 735dcd93f..3740dd263 100644
--- a/drivers/sound/wavfront.c
+++ b/drivers/sound/wavfront.c
@@ -1,8 +1,8 @@
-/*
- * sound/wavefront.c
+/* -*- linux-c -*-
*
- * A low level driver for Turtle Beach WaveFront Series
- * (Maui, Tropez, Tropez Plus, and perhaps the Monterey & Rio)
+ * sound/wavfront.c
+ *
+ * A Linux driver for Turtle Beach WaveFront Series (Maui, Tropez, Tropez Plus)
*
* This driver supports the onboard wavetable synthesizer (an ICS2115),
* including patch, sample and program loading and unloading, conversion
@@ -26,18 +26,6 @@
* This chip also controls the configuration of the card: the wavefront
* synth is logical unit 4.
*
- * NOTE: this driver has been written to support multiple WaveFront
- * cards, but without using PnP to configure the CS4232, all of them
- * would end up with the same configuration. Further, the current
- * module loading interface doesn't permit this, since it only allows
- * once instance of a module (which happens to be equivalent to a
- * single hardware configuration) to be installed at one time.In
- * addition, there is a hard limit on the available DMA channels that
- * also makes installing more than 1 card limited to purely MIDI/synth
- * activities on the second card. Still, the coding style gets rid of
- * virtually all globals, which I believe is a better way to code
- * device drivers (or anything else, for that matter).
- *
**********************************************************************
*
* Copyright (C) by Paul Barton-Davis 1998
@@ -61,9 +49,12 @@
* aspects of configuring a WaveFront soundcard, particularly the
* effects processor.
*
+ * $Id: wavfront.c,v 0.4 1998/07/22 02:12:11 pbd Exp $
+ *
* This program is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
* Version 2 (June 1991). See the "COPYING" file distributed with this software
- * for more info. */
+ * for more info.
+ */
#include <linux/config.h>
#include <linux/module.h>
@@ -78,23 +69,26 @@
#define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT
#include "midi_synth.h"
-#define COPY_FROM_USER(a,b,c) copy_from_user ((a),(b),(c))
-#define COPY_TO_USER(a,b,c) copy_to_user ((a),(b),(c))
+/* This thing is meant to work as a module */
-#if defined(CONFIG_SOUND_WAVEFRONT) || defined(CONFIG_SOUND_WAVEFRONT_MODULE)
+#if defined(CONFIG_SOUND_WAVEFRONT_MODULE) && defined(MODULE)
-/* This thing is meant to work as a module */
+/* if WF_DEBUG not defined, no run-time debugging messages will
+ be available via the debug flag setting. Given the current
+ beta state of the driver, this will remain set until a future
+ version.
+*/
-#ifdef MODULE
+#define WF_DEBUG 1
/* bitmasks for WaveFront status port value */
#define STAT_INTR_WRITE 0x40
#define STAT_CAN_WRITE 0x20
-#define STAT_RINTR_ENABLED 0x10
+#define STAT_WINTR_ENABLED 0x10
#define STAT_INTR_READ 0x04
#define STAT_CAN_READ 0x02
-#define STAT_WINTR_ENABLED 0x01
+#define STAT_RINTR_ENABLED 0x01
/*** Module-accessible parameters ***************************************/
@@ -111,7 +105,7 @@ int fx_raw = 1; /* if this is zero, we'll leave the FX processor in
operation, whatever that means.
*/
-int wf_debug_default = 0; /* you can set this to control debugging
+int debug_default = 0; /* you can set this to control debugging
during driver loading. it takes any combination
of the WF_DEBUG_* flags defined in
wavefront.h
@@ -119,27 +113,33 @@ int wf_debug_default = 0; /* you can set this to control debugging
/* XXX this needs to be made firmware and hardware version dependent */
-char *wf_ospath = "/etc/sound/wavefront.os"; /* where to find a processed
- version of the WaveFront OS
- */
+char *ospath = "/etc/sound/wavefront.os"; /* where to find a processed
+ version of the WaveFront OS
+ */
-/* These three don't need to be messed with unless you're trying to
- tweak the driver for optimal I/O performance. Read wavefront_wait()
- and wavefront_sleep() to see what they do. You may need or want to
- tweak them for CPU's different than the 486/66Mhz that I run on.
-*/
+int sleep_interval = 100; /* HZ/sleep_interval seconds per sleep */
+int sleep_tries = 50; /* number of times we'll try to sleep */
+
+int wait_usecs = 150; /* This magic number seems to give pretty optimal
+ throughput based on my limited experimentation.
+ If you want to play around with it and find a better
+ value, be my guest. Remember, the idea is to
+ get a number that causes us to just busy wait
+ for as many WaveFront commands as possible, without
+ coming up with a number so large that we hog the
+ whole CPU.
-int wf_short_wait_count = 5000; /* loops, CPU dependent */
-int wf_sleep_interval = 50; /* HZ/wf_sleep_interval seconds per sleep */
-int wf_sleep_tries = 100; /*2sec*/ /* number of times we'll try to sleep */
+ Specifically, with this number, out of about 134,000
+ status waits, only about 250 result in a sleep.
+ */
MODULE_PARM(wf_raw,"i");
MODULE_PARM(fx_raw,"i");
-MODULE_PARM(wf_debug_default,"i");
-MODULE_PARM(wf_ospath,"s");
-MODULE_PARM(wf_short_wait_count,"i");
-MODULE_PARM(wf_sleep_interval,"i");
-MODULE_PARM(wf_sleep_tries,"i");
+MODULE_PARM(debug_default,"i");
+MODULE_PARM(sleep_interval,"i");
+MODULE_PARM(sleep_tries,"i");
+MODULE_PARM(wait_usecs,"i");
+MODULE_PARM(ospath,"s");
/***************************************************************************/
@@ -150,9 +150,7 @@ static struct synth_info wavefront_info =
static int (*midi_load_patch) (int dev, int format, const char *addr,
int offs, int count, int pmgr_flag) = NULL;
-
typedef struct wf_config {
- int installed; /* well, is it ? note: doesn't mean "working" */
int devno; /* device number from kernel */
int irq; /* "you were one, one of the few ..." */
int base; /* low i/o port address */
@@ -185,7 +183,7 @@ typedef struct wf_config {
volatile int irq_ok; /* set by interrupt handler */
int opened; /* flag, holds open(1) mode */
char debug; /* debugging flags */
- unsigned int freemem; /* installed RAM, in bytes */
+ int freemem; /* installed RAM, in bytes */
int synthdev; /* OSS minor devnum for synth */
int mididev; /* OSS minor devno for internal MIDI */
int ext_mididev; /* OSS minor devno for external MIDI */
@@ -198,9 +196,20 @@ typedef struct wf_config {
int samples_used; /* how many */
char interrupts_on; /* h/w MPU interrupts enabled ? */
char rom_samples_rdonly; /* can we write on ROM samples */
+ struct wait_queue *interrupt_sleeper;
+#ifdef WF_STATS
+ unsigned long status_found_during_loop;
+ unsigned long status_found_during_sleep[4];
+#endif WF_STATS
+
} wf_config;
-static wf_config wfs[WAVEFRONT_MAX_DEVICES];
+/* Note: because this module doesn't export any symbols, this really isn't
+ a global variable, even if it looks like one. I was quite confused by
+ this when I started writing this as a (newer) module -- pbd.
+*/
+
+static wf_config wavefront_configuration;
#define wavefront_status(hw) (inb (hw->status_port))
@@ -210,14 +219,6 @@ static int wffx_ioctl (struct wf_config *, wavefront_fx_info *);
static int wffx_init (struct wf_config *hw);
static int wavefront_delete_sample (struct wf_config *hw, int sampnum);
-static volatile int irq2hw[17] =
-{-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1};
-
-static volatile int dev2hw[17] =
-{-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1};
-
typedef struct {
int cmd;
char *action;
@@ -304,25 +305,10 @@ static wavefront_command wavefront_commands[] = {
{ WFC_DISABLE_DRUM_PROGRAM, "disable drum program", 0, 1, NEEDS_ACK },
{ WFC_REPORT_CHANNEL_PROGRAMS, "report channel program numbers",
32, 0, 0 },
+ { WFC_NOOP, "the no-op command", 0, 0, NEEDS_ACK },
{ 0x00 }
};
-wf_config *
-hw_from_dev (int dev)
-
-{
- int i;
-
- if ((i = dev2hw[dev]) == -1) {
- printk (KERN_ERR
- "WaveFront: no hardware associated with device %d.\n",
- dev);
- return 0;
- }
-
- return &wfs[i];
-}
-
static const char *
wavefront_errorstr (int errnum)
@@ -370,21 +356,35 @@ wavefront_wait (wf_config *hw, int mask)
{
int i;
+ static int short_loop_cnt = 0;
+
+ if (short_loop_cnt == 0) {
+ short_loop_cnt = (int) (((double) wait_usecs / 1000000.0) *
+ (double) current_cpu_data.loops_per_sec);
+ }
- for (i = 0; i < wf_short_wait_count; i++) {
+ for (i = 0; i < short_loop_cnt; i++) {
if (wavefront_status(hw) & mask) {
+#ifdef WF_STATS
+ hw->status_found_during_loop++;
+#endif WF_STATS
return 1;
}
}
- for (i = 0; i < wf_sleep_tries; i++) {
+ for (i = 0; i < sleep_tries; i++) {
if (wavefront_status(hw) & mask) {
+#ifdef WF_STATS
+ if (i < 4) {
+ hw->status_found_during_sleep[i]++;
+ }
+#endif WF_STATS
return 1;
}
- if (wavefront_sleep (hw, HZ/wf_sleep_interval)) {
- return 0;
+ if (wavefront_sleep (hw, HZ/sleep_interval)) {
+ return (0);
}
}
@@ -397,23 +397,30 @@ wavefront_read (wf_config *hw)
if (wavefront_wait (hw, STAT_CAN_READ))
return inb (hw->data_port);
+#ifdef WF_DEBUG
if (hw->debug & WF_DEBUG_DATA) {
printk (KERN_DEBUG "WaveFront: read timeout.\n");
}
+#endif WF_DEBUG
+
return -1;
}
static int
wavefront_write (wf_config *hw, unsigned char data)
+
{
if (wavefront_wait (hw, STAT_CAN_WRITE)) {
outb (data, hw->data_port);
return 1;
}
+#ifdef WF_DEBUG
if (hw->debug & WF_DEBUG_DATA) {
printk (KERN_DEBUG "WaveFront: write timeout.\n");
}
+#endif WF_DEBUG
+
return 0;
}
@@ -444,60 +451,74 @@ wavefront_cmd (wf_config *hw, int cmd,
rbuf = 0;
}
+#ifdef WF_DEBUG
if (hw->debug & WF_DEBUG_CMD) {
printk (KERN_DEBUG "Wavefront: 0x%x [%s] (%d,%d,%d)\n",
cmd, wfcmd->action, wfcmd->read_cnt, wfcmd->write_cnt,
wfcmd->need_ack);
}
+#endif WF_DEBUG
if (!wavefront_write (hw, cmd)) {
+#ifdef WF_DEBUG
if (hw->debug & (WF_DEBUG_IO|WF_DEBUG_CMD)) {
printk (KERN_DEBUG "WaveFront: cannot request "
"0x%x [%s].\n",
cmd, wfcmd->action);
}
+#endif WF_DEBUG
return 1;
}
if (wfcmd->write_cnt > 0) {
+#ifdef WF_DEBUG
if (hw->debug & WF_DEBUG_DATA) {
printk (KERN_DEBUG "WaveFront: writing %d bytes "
"for 0x%x\n",
wfcmd->write_cnt, cmd);
}
+#endif WF_DEBUG
for (i = 0; i < wfcmd->write_cnt; i++) {
if (!wavefront_write (hw, wbuf[i])) {
+#ifdef WF_DEBUG
if (hw->debug & WF_DEBUG_IO) {
printk (KERN_DEBUG
"WaveFront: bad write for byte %d of 0x%x [%s].\n",
i, cmd, wfcmd->action);
}
+#endif WF_DEBUG
return 1;
}
+#ifdef WF_DEBUG
if (hw->debug & WF_DEBUG_DATA) {
printk (KERN_DEBUG
"WaveFront: write[%d] = 0x%x\n",
i, wbuf[i]);
+#endif WF_DEBUG
}
}
}
if (wfcmd->read_cnt > 0) {
+#ifdef WF_DEBUG
if (hw->debug & WF_DEBUG_DATA) {
printk (KERN_DEBUG "WaveFront: reading %d ints "
"for 0x%x\n",
wfcmd->read_cnt, cmd);
}
+#endif WF_DEBUG
for (i = 0; i < wfcmd->read_cnt; i++) {
if ((c = wavefront_read(hw)) == -1) {
+#ifdef WF_DEBUG
if (hw->debug & WF_DEBUG_IO) {
printk (KERN_DEBUG
"WaveFront: bad read for byte %d of 0x%x [%s].\n",
i, cmd, wfcmd->action);
}
+#endif WF_DEBUG
return 1;
}
@@ -505,12 +526,14 @@ wavefront_cmd (wf_config *hw, int cmd,
if (c == 0xff) {
if ((c = wavefront_read (hw)) == -1) {
+#ifdef WF_DEBUG
if (hw->debug & WF_DEBUG_IO) {
printk (KERN_DEBUG
"WaveFront: bad read for error byte at "
"read byte %d of 0x%x [%s].\n",
i, cmd, wfcmd->action);
}
+#endif WF_DEBUG
return 1;
}
@@ -519,7 +542,7 @@ wavefront_cmd (wf_config *hw, int cmd,
if (c == 1 &&
wfcmd->cmd == WFC_IDENTIFY_SAMPLE_TYPE) {
rbuf[0] = WF_ST_EMPTY;
- return 0;
+ return (0);
} else if (c == 3 &&
wfcmd->cmd == WFC_UPLOAD_PATCH) {
@@ -533,6 +556,7 @@ wavefront_cmd (wf_config *hw, int cmd,
} else {
+#ifdef WF_DEBUG
if (hw->debug & WF_DEBUG_IO) {
printk (KERN_DEBUG
"WaveFront: error %d (%s) during "
@@ -542,6 +566,7 @@ wavefront_cmd (wf_config *hw, int cmd,
wavefront_errorstr (c),
i, cmd, wfcmd->action);
}
+#endif WF_DEBUG
return 1;
}
@@ -549,20 +574,24 @@ wavefront_cmd (wf_config *hw, int cmd,
rbuf[i] = c;
}
+#ifdef WF_DEBUG
if (hw->debug & WF_DEBUG_DATA) {
printk (KERN_DEBUG
"WaveFront: read[%d] = 0x%x\n",
i, rbuf[i]);
}
+#endif WF_DEBUG
}
}
if ((wfcmd->read_cnt == 0 && wfcmd->write_cnt == 0) || wfcmd->need_ack) {
+#ifdef WF_DEBUG
if (hw->debug & WF_DEBUG_CMD) {
printk (KERN_DEBUG "WaveFront: reading ACK for 0x%x\n",
cmd);
}
+#endif WF_DEBUG
/* Some commands need an ACK, but return zero instead
of the standard value.
@@ -574,11 +603,13 @@ wavefront_cmd (wf_config *hw, int cmd,
if (ack != WF_ACK) {
if (ack == -1) {
+#ifdef WF_DEBUG
if (hw->debug & WF_DEBUG_IO) {
printk (KERN_DEBUG
"WaveFront: cannot read ack for 0x%x [%s].\n",
cmd, wfcmd->action);
}
+#endif WF_DEBUG
return 1;
} else {
@@ -587,14 +618,17 @@ wavefront_cmd (wf_config *hw, int cmd,
if (ack == 0xff) { /* explicit error */
if ((err = wavefront_read (hw)) == -1) {
+#ifdef WF_DEBUG
if (hw->debug & WF_DEBUG_DATA) {
printk (KERN_DEBUG
"WaveFront: cannot read err for 0x%x [%s].\n",
cmd, wfcmd->action);
}
+#endif WF_DEBUG
}
}
+#ifdef WF_DEBUG
if (hw->debug & WF_DEBUG_IO) {
printk (KERN_DEBUG
"WaveFront: 0x%x [%s] "
@@ -602,22 +636,27 @@ wavefront_cmd (wf_config *hw, int cmd,
cmd, wfcmd->action, ack, err,
wavefront_errorstr (err));
}
+#endif WF_DEBUG
return -err;
}
}
+#ifdef WF_DEBUG
if (hw->debug & WF_DEBUG_DATA) {
printk (KERN_DEBUG "WaveFront: ack received "
"for 0x%x [%s]\n",
cmd, wfcmd->action);
}
+#endif WF_DEBUG
} else {
+#ifdef WF_DEBUG
if (hw->debug & WF_DEBUG_CMD) {
printk (KERN_DEBUG
"Wavefront: 0x%x [%s] does not need "
"ACK (%d,%d,%d)\n",
cmd, wfcmd->action, wfcmd->read_cnt,
wfcmd->write_cnt, wfcmd->need_ack);
+#endif WF_DEBUG
}
}
@@ -795,7 +834,7 @@ wavefront_get_sample_status (struct wf_config *hw, int assume_rom)
WF_MAX_SAMPLE - hw->samples_used);
- return 0;
+ return (0);
}
@@ -826,6 +865,7 @@ wavefront_get_patch_status (struct wf_config *hw)
printk (KERN_ERR "WaveFront: upload patch "
"error 0x%x\n", x);
hw->patch_status[i] = 0;
+ return 1;
}
}
@@ -843,7 +883,7 @@ wavefront_get_patch_status (struct wf_config *hw)
printk (KERN_INFO
"WaveFront: %d patch slots filled, %d in use\n", cnt, cnt2);
- return 0;
+ return (0);
}
static int
@@ -889,7 +929,7 @@ wavefront_get_program_status (struct wf_config *hw)
printk (KERN_INFO "WaveFront: %d programs slots in use\n", cnt);
- return 0;
+ return (0);
}
static int
@@ -900,10 +940,12 @@ wavefront_send_patch (wf_config *hw,
unsigned char buf[WF_PATCH_BYTES+2];
unsigned char *bptr;
+#ifdef WF_DEBUG
if (hw->debug & WF_DEBUG_LOAD_PATCH) {
printk (KERN_DEBUG "WaveFront: downloading patch %d\n",
header->number);
}
+#endif WF_DEBUG
hw->patch_status[header->number] |= WF_SLOT_FILLED;
@@ -913,10 +955,10 @@ wavefront_send_patch (wf_config *hw,
if (wavefront_cmd (hw, WFC_DOWNLOAD_PATCH, 0, buf)) {
printk (KERN_ERR "WaveFront: download patch failed\n");
- return -EIO;
+ return -(EIO);
}
- return 0;
+ return (0);
}
static int
@@ -927,10 +969,12 @@ wavefront_send_program (wf_config *hw,
unsigned char buf[WF_PROGRAM_BYTES+1];
int i;
+#ifdef WF_DEBUG
if (hw->debug & WF_DEBUG_LOAD_PATCH) {
printk (KERN_DEBUG
"WaveFront: downloading program %d\n", header->number);
}
+#endif WF_DEBUG
hw->prog_status[header->number] = WF_SLOT_USED;
@@ -954,10 +998,10 @@ wavefront_send_program (wf_config *hw,
if (wavefront_cmd (hw, WFC_DOWNLOAD_PROGRAM, 0, buf)) {
printk (KERN_WARNING "WaveFront: download patch failed\n");
- return -EIO;
+ return -(EIO);
}
- return 0;
+ return (0);
}
static int
@@ -1004,6 +1048,7 @@ wavefront_send_sample (wf_config *hw,
int skip = 0;
int initial_skip = 0;
+#ifdef WF_DEBUG
if (hw->debug & WF_DEBUG_LOAD_PATCH) {
printk (KERN_DEBUG "WaveFront: sample %sdownload for slot %d, "
"type %d, %d bytes from 0x%x\n",
@@ -1011,6 +1056,7 @@ wavefront_send_sample (wf_config *hw,
header->number, header->subkey, header->size,
(int) header->dataptr);
}
+#endif WF_DEBUG
if (header->size) {
@@ -1032,10 +1078,9 @@ wavefront_send_sample (wf_config *hw,
or theoretically some other configuration) is the
responsibility of the user level library.
- To try to do this in the kernel would be a little crazy:
- we'd need 24 * 512 bytes (12K) of kernel space just to
- hold copies of the original sample headers; the whole
- patch/program/sample header data is about 158K!!!
+ To try to do this in the kernel would be a little
+ crazy: we'd need 158K of kernel space just to hold
+ a copy of the patch/program/sample header data.
*/
if (hw->rom_samples_rdonly) {
@@ -1073,7 +1118,7 @@ wavefront_send_sample (wf_config *hw,
printk (KERN_ERR
"WaveFront: channel selection only possible "
"on 16-bit samples");
- return -EINVAL;
+ return -(EINVAL);
}
}
@@ -1108,11 +1153,13 @@ wavefront_send_sample (wf_config *hw,
break;
}
+#ifdef WF_DEBUG
if (hw->debug & WF_DEBUG_LOAD_PATCH) {
printk (KERN_DEBUG "WaveFront: channel selection: %d => "
"initial skip = %d, skip = %d\n",
WF_GET_CHANNEL (&header->hdr.s), initial_skip, skip);
}
+#endif WF_DEBUG
/* Be safe, and zero the "Unused" bits ... */
@@ -1153,7 +1200,7 @@ wavefront_send_sample (wf_config *hw,
/* This one is truly weird. What kind of weirdo decided that in
a system dominated by 16- and 32-bit integers, they would use
- a 12-bit transfer size ?
+ just 12 bits ?
*/
shptr = munge_int32 (header->hdr.s.FrequencyBias, shptr, 3);
@@ -1171,7 +1218,7 @@ wavefront_send_sample (wf_config *hw,
0, sample_hdr)) {
printk (KERN_WARNING "WaveFront: sample %sdownload refused.\n",
header->size ? "" : "header ");
- return -EIO;
+ return -(EIO);
}
if (header->size == 0) {
@@ -1197,7 +1244,7 @@ wavefront_send_sample (wf_config *hw,
if (wavefront_cmd (hw, WFC_DOWNLOAD_BLOCK, 0, 0)) {
printk (KERN_WARNING "WaveFront: download block "
"request refused.\n");
- return -EIO;
+ return -(EIO);
}
for (i = 0; i < blocksize; i++) {
@@ -1207,7 +1254,7 @@ wavefront_send_sample (wf_config *hw,
get_user (sample_short, dataptr);
dataptr += skip;
- if (data_is_unsigned) {
+ if (data_is_unsigned) { /* GUS ? */
if (WF_SAMPLE_IS_8BIT(&header->hdr.s)) {
@@ -1255,12 +1302,12 @@ wavefront_send_sample (wf_config *hw,
if (dma_ack == -1) {
printk (KERN_ERR "WaveFront: upload sample "
"DMA ack timeout\n");
- return -EIO;
+ return -(EIO);
} else {
printk (KERN_ERR "WaveFront: upload sample "
"DMA ack error 0x%x\n",
dma_ack);
- return -EIO;
+ return -(EIO);
}
}
}
@@ -1272,7 +1319,7 @@ wavefront_send_sample (wf_config *hw,
*/
sent:
- return 0;
+ return (0);
}
static int
@@ -1282,12 +1329,14 @@ wavefront_send_alias (struct wf_config *hw,
{
unsigned char alias_hdr[WF_ALIAS_BYTES];
+#ifdef WF_DEBUG
if (hw->debug & WF_DEBUG_LOAD_PATCH) {
printk (KERN_DEBUG "WaveFront: download alias, %d is "
"alias for %d\n",
header->number,
header->hdr.a.OriginalSample);
}
+#endif WF_DEBUG
munge_int32 (header->number, &alias_hdr[0], 2);
munge_int32 (header->hdr.a.OriginalSample, &alias_hdr[2], 2);
@@ -1304,12 +1353,12 @@ wavefront_send_alias (struct wf_config *hw,
if (wavefront_cmd (hw, WFC_DOWNLOAD_SAMPLE_ALIAS, 0, alias_hdr)) {
printk (KERN_ERR "WaveFront: download alias failed.\n");
- return -EIO;
+ return -(EIO);
}
hw->sample_status[header->number] = (WF_SLOT_FILLED|WF_ST_ALIAS);
- return 0;
+ return (0);
}
static int
@@ -1330,17 +1379,21 @@ wavefront_send_multisample (struct wf_config *hw,
num_samples = (1<<(header->hdr.ms.NumberOfSamples&7));
msample_hdr[2] = (unsigned char) header->hdr.ms.NumberOfSamples;
+#ifdef WF_DEBUG
if (hw->debug & WF_DEBUG_LOAD_PATCH) {
printk (KERN_DEBUG "WaveFront: multi %d with %d=%d samples\n",
header->number, header->hdr.ms.NumberOfSamples, num_samples);
}
+#endif WF_DEBUG
for (i = 0; i < num_samples; i++) {
+#ifdef WF_DEBUG
if ((hw->debug & (WF_DEBUG_LOAD_PATCH|WF_DEBUG_DATA)) ==
(WF_DEBUG_LOAD_PATCH|WF_DEBUG_DATA)) {
printk (KERN_DEBUG "WaveFront: sample[%d] = %d\n",
i, header->hdr.ms.SampleNumber[i]);
}
+#endif WF_DEBUG
munge_int32 (header->hdr.ms.SampleNumber[i],
&msample_hdr[3+(i*2)], 2);
}
@@ -1354,12 +1407,12 @@ wavefront_send_multisample (struct wf_config *hw,
(unsigned char *) ((num_samples*2)+3),
msample_hdr)) {
printk (KERN_ERR "WaveFront: download of multisample failed.\n");
- return -EIO;
+ return -(EIO);
}
hw->sample_status[header->number] = (WF_SLOT_FILLED|WF_ST_MULTISAMPLE);
- return 0;
+ return (0);
}
static int
@@ -1375,13 +1428,15 @@ wavefront_fetch_multisample (struct wf_config *hw,
if (wavefront_cmd (hw, WFC_UPLOAD_MULTISAMPLE, log_ns, number)) {
printk (KERN_ERR "WaveFront: upload multisample failed.\n");
- return -EIO;
+ return -(EIO);
}
+#ifdef WF_DEBUG
if (hw->debug & WF_DEBUG_DATA) {
printk (KERN_DEBUG "WaveFront: msample %d has %d samples\n",
header->number, log_ns[0]);
}
+#endif WF_DEBUG
header->hdr.ms.NumberOfSamples = log_ns[0];
@@ -1395,26 +1450,28 @@ wavefront_fetch_multisample (struct wf_config *hw,
if ((d[0] = wavefront_read (hw)) == -1) {
printk (KERN_ERR "WaveFront: upload multisample failed "
"during sample loop.\n");
- return -EIO;
+ return -(EIO);
}
if ((d[1] = wavefront_read (hw)) == -1) {
printk (KERN_ERR "WaveFront: upload multisample failed "
"during sample loop.\n");
- return -EIO;
+ return -(EIO);
}
header->hdr.ms.SampleNumber[i] =
demunge_int32 ((unsigned char *) d, 2);
+#ifdef WF_DEBUG
if (hw->debug & WF_DEBUG_DATA) {
printk (KERN_DEBUG "WaveFront: msample "
"sample[%d] = %d\n",
i, header->hdr.ms.SampleNumber[i]);
}
+#endif WF_DEBUG
}
- return 0;
+ return (0);
}
@@ -1426,12 +1483,14 @@ wavefront_send_drum (struct wf_config *hw, wavefront_patch_info *header)
wavefront_drum *drum = &header->hdr.d;
int i;
+#ifdef WF_DEBUG
if (hw->debug & WF_DEBUG_LOAD_PATCH) {
printk (KERN_DEBUG
"WaveFront: downloading edrum for MIDI "
"note %d, patch = %d\n",
header->number, drum->PatchNumber);
}
+#endif WF_DEBUG
drumbuf[0] = header->number & 0x7f;
@@ -1441,10 +1500,10 @@ wavefront_send_drum (struct wf_config *hw, wavefront_patch_info *header)
if (wavefront_cmd (hw, WFC_DOWNLOAD_EDRUM_PROGRAM, 0, drumbuf)) {
printk (KERN_ERR "WaveFront: download drum failed.\n");
- return -EIO;
+ return -(EIO);
}
- return 0;
+ return (0);
}
static int
@@ -1468,7 +1527,7 @@ wavefront_find_free_patch (struct wf_config *hw)
{
int i;
- for (i = 0; i < WF_MAX_SAMPLE; i++) {
+ for (i = 0; i < WF_MAX_PATCH; i++) {
if (!(hw->patch_status[i] & WF_SLOT_FILLED)) {
return i;
}
@@ -1522,7 +1581,7 @@ wavefront_load_gus_patch (struct wf_config *hw,
/* Copy in the header of the GUS patch */
sizeof_patch = (long) &guspatch.data[0] - (long) &guspatch;
- COPY_FROM_USER (&((char *) &guspatch)[offs],
+ copy_from_user (&((char *) &guspatch)[offs],
&(addr)[offs], sizeof_patch - offs);
if ((i = wavefront_find_free_patch (hw)) == -1) {
@@ -1656,19 +1715,15 @@ wavefront_load_patch (int dev, int format, const char *addr,
int offs, int count, int pmgr_flag)
{
- struct wf_config *hw;
+ struct wf_config *hw = &wavefront_configuration;
wavefront_patch_info header;
- if ((hw = hw_from_dev (dev)) == 0) {
- return -EINVAL;
- }
-
if (format == SYSEX_PATCH) { /* Handled by midi_synth.c */
if (midi_load_patch == NULL) {
printk (KERN_ERR
"WaveFront: SYSEX not loadable: "
"no midi patch loader!\n");
- return -EINVAL;
+ return -(EINVAL);
}
return midi_load_patch (dev, format, addr,
offs, count, pmgr_flag);
@@ -1679,12 +1734,12 @@ wavefront_load_patch (int dev, int format, const char *addr,
} else if (format != WAVEFRONT_PATCH) {
printk (KERN_ERR "WaveFront: unknown patch format %d\n", format);
- return -EINVAL;
+ return -(EINVAL);
}
if (count < sizeof (wavefront_patch_info)) {
printk (KERN_ERR "WaveFront: sample header too short\n");
- return -EINVAL;
+ return -(EINVAL);
}
/* copied in so far: `offs' bytes from `addr'. We shouldn't copy
@@ -1694,10 +1749,11 @@ wavefront_load_patch (int dev, int format, const char *addr,
through the 'hdrptr' field.
*/
- COPY_FROM_USER (&((char *) &header)[offs], &(addr)[offs],
+ copy_from_user (&((char *) &header)[offs], &(addr)[offs],
sizeof(wavefront_patch_info) -
sizeof(wavefront_any) - offs);
+#ifdef WF_DEBUG
if (hw->debug & WF_DEBUG_LOAD_PATCH) {
printk (KERN_DEBUG "WaveFront: download "
"Sample type: %d "
@@ -1707,11 +1763,12 @@ wavefront_load_patch (int dev, int format, const char *addr,
header.number,
header.size);
}
+#endif WF_DEBUG
switch (header.subkey) {
case WF_ST_SAMPLE: /* sample or sample_header, based on patch->size */
- COPY_FROM_USER ((unsigned char *) &header.hdr.s,
+ copy_from_user ((unsigned char *) &header.hdr.s,
(unsigned char *) header.hdrptr,
sizeof (wavefront_sample));
@@ -1719,7 +1776,7 @@ wavefront_load_patch (int dev, int format, const char *addr,
case WF_ST_MULTISAMPLE:
- COPY_FROM_USER ((unsigned char *) &header.hdr.s,
+ copy_from_user ((unsigned char *) &header.hdr.s,
(unsigned char *) header.hdrptr,
sizeof (wavefront_multisample));
@@ -1728,28 +1785,28 @@ wavefront_load_patch (int dev, int format, const char *addr,
case WF_ST_ALIAS:
- COPY_FROM_USER ((unsigned char *) &header.hdr.a,
+ copy_from_user ((unsigned char *) &header.hdr.a,
(unsigned char *) header.hdrptr,
sizeof (wavefront_alias));
return wavefront_send_alias (hw, &header);
case WF_ST_DRUM:
- COPY_FROM_USER ((unsigned char *) &header.hdr.d,
+ copy_from_user ((unsigned char *) &header.hdr.d,
(unsigned char *) header.hdrptr,
sizeof (wavefront_drum));
return wavefront_send_drum (hw, &header);
case WF_ST_PATCH:
- COPY_FROM_USER ((unsigned char *) &header.hdr.p,
+ copy_from_user ((unsigned char *) &header.hdr.p,
(unsigned char *) header.hdrptr,
sizeof (wavefront_patch));
return wavefront_send_patch (hw, &header);
case WF_ST_PROGRAM:
- COPY_FROM_USER ((unsigned char *) &header.hdr.pr,
+ copy_from_user ((unsigned char *) &header.hdr.pr,
(unsigned char *) header.hdrptr,
sizeof (wavefront_program));
@@ -1758,7 +1815,7 @@ wavefront_load_patch (int dev, int format, const char *addr,
default:
printk (KERN_ERR "WaveFront: unknown patch type %d.\n",
header.subkey);
- return -EINVAL;
+ return -(EINVAL);
}
return 0;
@@ -1804,24 +1861,19 @@ static int
wavefront_synth_control (int dev, int cmd, caddr_t arg)
{
- struct wf_config *hw;
+ struct wf_config *hw = &wavefront_configuration;
wavefront_control wc;
unsigned char patchnumbuf[2];
int i;
- if ((hw = hw_from_dev (dev)) == 0) {
- printk (KERN_ERR
- "WaveFront: synth_control with unknown "
- "device number %d\n", dev);
- return -EINVAL;
- }
-
- COPY_FROM_USER (&wc, arg, sizeof (wc));
+ copy_from_user (&wc, arg, sizeof (wc));
+#ifdef WF_DEBUG
if (hw->debug & WF_DEBUG_CMD) {
printk (KERN_DEBUG "WaveFront: synth control with "
"cmd 0x%x\n", wc.cmd);
}
+#endif WF_DEBUG
/* special case handling of or for various commands */
@@ -1940,7 +1992,7 @@ wavefront_synth_control (int dev, int cmd, caddr_t arg)
is a low priority fix.
*/
- COPY_TO_USER (arg, &wc, sizeof (wc));
+ copy_to_user (arg, &wc, sizeof (wc));
return 0;
}
@@ -1953,13 +2005,9 @@ WaveFront: MIDI synth interface
static int
wavefront_ioctl (int dev, unsigned int cmd, caddr_t arg)
{
- wf_config *hw;
+ wf_config *hw = &wavefront_configuration;
unsigned char rbuf[4];
- if ((hw = hw_from_dev (dev)) == 0) {
- return -EINVAL;
- }
-
switch (cmd) {
case SNDCTL_SYNTH_INFO:
memcpy (&((char *) arg)[0], &wavefront_info,
@@ -1992,7 +2040,7 @@ wavefront_ioctl (int dev, unsigned int cmd, caddr_t arg)
return wavefront_synth_control (dev, cmd, arg);
default:
- return -EINVAL;
+ return -(EINVAL);
}
}
@@ -2000,32 +2048,30 @@ static int
wavefront_open (int dev, int mode)
{
- struct wf_config *hw;
-
- if ((hw = hw_from_dev (dev)) == 0) {
- return -EINVAL;
- }
+ struct wf_config *hw = &wavefront_configuration;
if (hw->opened) {
- printk (KERN_ERR "WaveFront: warning: device in use\n");
+ printk (KERN_WARNING "WaveFront: warning: device in use\n");
}
hw->opened = mode;
- return 0;
+ return (0);
}
static void
wavefront_close (int dev)
{
- struct wf_config *hw;
+ struct wf_config *hw = &wavefront_configuration;
+ int i;
- if ((hw = hw_from_dev (dev)) == 0) {
- printk (KERN_ERR
- "WaveFront: close() called on non-existent dev %d", dev);
- return;
+#ifdef WF_STATS
+ printk ("Status during loop: %ld\n", hw->status_found_during_loop);
+ for (i = 0; i < 4; i++) {
+ printk ("Status during sleep[%d]: %ld\n",
+ i, hw->status_found_during_sleep[i]);
}
-
+#endif WF_STATS
hw->opened = 0;
hw->debug = 0;
@@ -2035,70 +2081,65 @@ wavefront_close (int dev)
static void
wavefront_aftertouch (int dev, int channel, int pressure)
{
- struct wf_config *hw = hw_from_dev (dev);
- if (!hw) return;
- midi_synth_aftertouch (hw->mididev,channel,pressure);
+ midi_synth_aftertouch (wavefront_configuration.mididev,channel,pressure);
};
static void
wavefront_bender (int dev, int chn, int value)
{
- struct wf_config *hw = hw_from_dev (dev);
- if (!hw) return;
- midi_synth_bender (hw->mididev, chn, value);
+ midi_synth_bender (wavefront_configuration.mididev, chn, value);
};
static void
wavefront_controller (int dev, int channel, int ctrl_num, int value)
{
- struct wf_config *hw = hw_from_dev (dev);
- if (!hw) return;
if(ctrl_num==CTRL_PITCH_BENDER) wavefront_bender(0,channel,value);
- midi_synth_controller (hw->mididev, channel,ctrl_num,value);
+ midi_synth_controller (wavefront_configuration.mididev,
+ channel,ctrl_num,value);
};
static void
wavefront_panning(int dev, int channel, int pressure)
{
- struct wf_config *hw = hw_from_dev (dev);
- if (!hw) return;
- midi_synth_controller(hw->mididev,channel,CTL_PAN,pressure);
+ midi_synth_controller (wavefront_configuration.mididev,
+ channel,CTL_PAN,pressure);
};
static int
wavefront_set_instr (int dev, int channel, int instr_no)
{
- struct wf_config *hw = hw_from_dev (dev);
- if (!hw) return 1;
- return(midi_synth_set_instr(hw->mididev,channel,instr_no));
+ return(midi_synth_set_instr (wavefront_configuration.mididev,
+ channel,instr_no));
};
static int
wavefront_kill_note (int dev, int channel, int note, int volume)
{
- struct wf_config *hw = hw_from_dev (dev);
- if (!hw) return 1;
if (note==255)
- return(midi_synth_start_note(hw->mididev, channel, 0, 0));
- return(midi_synth_kill_note(hw->mididev, channel, note, volume));
+ return (midi_synth_start_note (wavefront_configuration.mididev,
+ channel, 0, 0));
+ return(midi_synth_kill_note (wavefront_configuration.mididev,
+ channel, note, volume));
};
static int
wavefront_start_note (int dev, int channel, int note, int volume)
{
- struct wf_config *hw = hw_from_dev (dev);
- if (!hw) return 1;
-
if (note==255) {
- /*midi_synth_controller(hw->mididev,channel,7,volume);*/
- midi_synth_aftertouch(hw->mididev,channel,volume);
+ midi_synth_aftertouch (wavefront_configuration.mididev,
+ channel,volume);
return(0);
};
+
if (volume==0) {
volume=127;
- midi_synth_aftertouch(hw->mididev,channel,0);
+ midi_synth_aftertouch
+ (wavefront_configuration.mididev,
+ channel,0);
};
- midi_synth_start_note (hw->mididev, channel, note, volume);
+
+ midi_synth_start_note (wavefront_configuration.mididev,
+ channel, note, volume);
return(0);
};
@@ -2111,7 +2152,8 @@ static void wavefront_reset (int dev)
{
int i;
- for(i=0;i<16;i++) {
+
+ for (i = 0; i < 16; i++) {
midi_synth_kill_note (dev,i,0,0);
};
};
@@ -2149,16 +2191,18 @@ WaveFront: OSS/Free and/or Linux kernel installation interface
void
wavefrontintr (int irq, void *dev_id, struct pt_regs *dummy)
{
- int i;
+ /* We don't use this handler except during device
+ configuration. While the module is installed, the
+ interrupt is used to signal MIDI interrupts, and is
+ handled by the interrupt routine in wf_midi.c
+ */
+
+ wf_config *hw = (wf_config *) dev_id;
+ hw->irq_ok = 1;
- if (irq < 0 || irq > 16) {
- printk (KERN_WARNING "WaveFront: bogus interrupt %d recv'd\n",
- irq);
- } else if ((i = irq2hw[irq]) == -1) {
- printk (KERN_ALERT
- "WaveFront: interrupt from unknown hw (irq=%d).\n", irq);
- } else {
- wfs[i].irq_ok = 1;
+ if ((wavefront_status(hw) & STAT_INTR_WRITE) ||
+ (wavefront_status(hw) & STAT_INTR_READ)) {
+ wake_up (&hw->interrupt_sleeper);
}
}
@@ -2173,106 +2217,24 @@ wavefrontintr (int irq, void *dev_id, struct pt_regs *dummy)
6 Host Tx Interrupt Pending (1=Interrupt)
7 Unused
-*/
+11111001
+ Rx Intr enable
+ nothing to read from board
+ no rx interrupt pending
+ unused
+ tx interrupt enabled
+ space to transmit
+ tx interrupt pending
-/* CONTROL REGISTER
-0 Host Rx Interrupt Enable (1=Enabled) 0x1
-1 Unused 0x2
-2 Unused 0x4
-3 Unused 0x8
-4 Host Tx Interrupt Enable 0x10
-5 Mute (0=Mute; 1=Play) 0x20
-6 Master Interrupt Enable (1=Enabled) 0x40
-7 Master Reset (0=Reset; 1=Run) 0x80
*/
int
-probe_wavefront (struct address_info *hw_config)
+wavefront_interrupt_bits (int irq)
{
- int i;
- int tmp1, tmp2;
- unsigned char bits;
- unsigned char rbuf[32], wbuf[32];
- wf_config *hw;
-
- if (hw_config->irq < 0 || hw_config->irq > 16) {
- printk (KERN_WARNING "WaveFront: impossible IRQ suggested(%d)\n",
- hw_config->irq);
- return 0;
- }
-
- /* Yeah yeah, TB docs say 8, but the FX device on the Tropez Plus
- takes up another 8 ...
- */
-
- if (check_region (hw_config->io_base, 16)) {
- printk (KERN_ERR "WaveFront: IO address range 0x%x - 0x%x "
- "already in use - ignored\n", hw_config->io_base,
- hw_config->io_base+15);
- return 0;
- }
-
- for (i = 0; i < WAVEFRONT_MAX_DEVICES; i++) {
- if (!wfs[i].installed) {
- wfs[i].installed = 1;
- break;
- }
- }
-
- if (i == WAVEFRONT_MAX_DEVICES) {
- printk (KERN_WARNING "WaveFront: no device slots available (max = %d).\n",
- WAVEFRONT_MAX_DEVICES);
- return 0;
- }
-
- hw = &wfs[i];
-
- hw->irq = hw_config->irq;
- hw->base = hw_config->io_base;
-
- hw->israw = 0;
- hw->debug = wf_debug_default;
- hw->interrupts_on = 0;
- hw->rom_samples_rdonly = 1; /* XXX default lock on ROM sample slots */
-
- hw_config->slots[WF_SYNTH_SLOT] = hw->synthdev = -1;
- hw_config->slots[WF_INTERNAL_MIDI_SLOT] = hw->mididev = -1;
- hw_config->slots[WF_EXTERNAL_MIDI_SLOT] = hw->ext_mididev = -1;
+ int bits;
- irq2hw[hw_config->irq] = i;
-
- if (wavefront_cmd (hw, WFC_FIRMWARE_VERSION, rbuf, wbuf) == 0) {
- hw->fw_version[0] = rbuf[0];
- hw->fw_version[1] = rbuf[1];
- printk (KERN_INFO "WaveFront: firmware %d.%d already loaded.\n",
- rbuf[0], rbuf[1]);
-
- if (wavefront_cmd (hw, WFC_HARDWARE_VERSION, rbuf, wbuf) == 0) {
- hw->hw_version[0] = rbuf[0];
- hw->hw_version[1] = rbuf[1];
- } else {
- printk (KERN_INFO "WaveFront: not raw, but no hardware version!\n");
- return 0;
- }
- if (!wf_raw) {
- return 1;
- }
- } else {
- hw->israw = 1;
- printk (KERN_INFO
- "WaveFront: no response to firmware probe, "
- "assume raw.\n");
- }
-
- if (request_irq (hw_config->irq, wavefrontintr,
- 0, "WaveFront", NULL) < 0) {
- printk (KERN_WARNING "WaveFront: IRQ %d not available!\n",
- hw_config->irq);
- return 0;
- }
-
- switch (hw_config->irq) {
+ switch (irq) {
case 9:
bits = 0x00;
break;
@@ -2287,11 +2249,42 @@ probe_wavefront (struct address_info *hw_config)
break;
default:
- printk (KERN_WARNING "WaveFront: invalid IRQ %d\n",
- hw_config->irq);
- return 0;
+ printk (KERN_WARNING "WaveFront: invalid IRQ %d\n", irq);
+ bits = -1;
}
-
+
+ return bits;
+}
+
+void
+wavefront_should_cause_interrupt (wf_config *hw, int val, int port, int timeout)
+
+{
+ unsigned long flags;
+
+ save_flags (flags);
+ cli();
+ hw->irq_ok = 0;
+ outb (val,port);
+ current->timeout = jiffies + timeout;
+ interruptible_sleep_on (&hw->interrupt_sleeper);
+ restore_flags (flags);
+}
+
+static int
+wavefront_hw_reset (wf_config *hw)
+
+{
+ int bits;
+ int hwv[2];
+
+ if (request_irq (hw->irq, wavefrontintr,
+ 0, "WaveFront", (void *) hw) < 0) {
+ printk (KERN_WARNING "WaveFront: IRQ %d not available!\n",
+ hw->irq);
+ return 1;
+ }
+
/* try reset of port */
outb (0x0, hw->control_port);
@@ -2305,9 +2298,6 @@ probe_wavefront (struct address_info *hw_config)
Bit 6 - MIDI Interface Select
- XXX PBD: I think this documentation is backwards. I leave bit
- 6 unset, and get MIDI data from the 9 pin D connector.
-
0 - Use the MIDI Input from the 26-pin WaveBlaster
compatible header as the serial MIDI source
1 - Use the MIDI Input from the 9-pin D connector as the serial MIDI
@@ -2331,101 +2321,270 @@ probe_wavefront (struct address_info *hw_config)
*/
- /* configure hardware: IRQ, plus external MIDI interface selected */
-
- outb (bits | 0x80, hw->data_port);
-
- /* take us out of reset, unmute, master + TX + RX interrupts on */
-
- outb (0x80|0x20|0x40|0x10|0x1, hw->control_port);
-
- for (i = 0; i < 1000000 && !hw->irq_ok; i++);
-
- /* Data port is now the data port, not the h/w initialization port
-
- The boot ROM will check the OSRAM, and will then
- wait for the either the "download OS" or
- "report h/w version" commands.
-
- Any other command will supposedly be ignored.
+ /* configure hardware: IRQ, enable interrupts,
+ plus external 9-pin MIDI interface selected
*/
+
+ if ((bits = wavefront_interrupt_bits (hw->irq)) < 0) {
+ return 1;
+ }
+
+ outb (0x80 | 0x40 | bits, hw->data_port);
+ /* CONTROL REGISTER
+
+ 0 Host Rx Interrupt Enable (1=Enabled) 0x1
+ 1 Unused 0x2
+ 2 Unused 0x4
+ 3 Unused 0x8
+ 4 Host Tx Interrupt Enable 0x10
+ 5 Mute (0=Mute; 1=Play) 0x20
+ 6 Master Interrupt Enable (1=Enabled) 0x40
+ 7 Master Reset (0=Reset; 1=Run) 0x80
+
+ Take us out of reset, unmute, master + TX + RX interrupts on.
+
+ We'll get an interrupt presumably to tell us that the TX
+ register is clear. However, this doesn't mean that the
+ board is ready. We actually have to send it a command, and
+ wait till it gets back to use. After a cold boot, this can
+ take some time.
+
+
+ I think this is because its only after a cold boot that the
+ onboard ROM does its memory check, which can take "up to 4
+ seconds" according to the WaveFront SDK. So, since sleeping
+ doesn't cost us much, we'll give it *plenty* of time. It
+ turns out that with 12MB of RAM, it can take up to 16
+ seconds or so!! See the code after "ABOUT INTERRUPTS"
+ */
+
+ wavefront_should_cause_interrupt(hw,
+ 0x80|0x40|0x10|0x1,
+ hw->control_port,
+ (2*HZ)/100);
+
+ /* Note: data port is now the data port, not the h/w initialization
+ port.
+ */
+
if (!hw->irq_ok) {
printk (KERN_WARNING
"WaveFront: intr not received after h/w un-reset.\n");
- free_irq (hw_config->irq, NULL);
- return 0;
- } else {
- hw->irq_ok = 0;
- }
+ goto gone_bad;
+ }
hw->interrupts_on = 1;
-
- /* WaveFront SDK says:
-
- "When the Master Reset is set to zero (0), the audio board is held
- in reset, which is the power-up condition. Setting Master Reset to one
- (1) allows the on-board processor to run. It takes approximately two
- to four seconds, depending on the memory configuration, for the
- on-board processor to complete it's initialization routine before it
- will respond to commands after a reset."
-
- Actually, it seems that most of the time, even with 8MB of RAM,
- its actually ready immediately.
+
+ /* ABOUT INTERRUPTS:
+ -----------------
+
+ When we talk about interrupts, there are two kinds
+ generated by the ICS2115. The first is to signal MPU data
+ ready to read, and the second is to signal RX or TX status
+ changes. We *always* want interrupts for MPU stuff but we
+ generally avoid using RX/TX interrupts.
+
+ In theory, we could use the TX and RX interrupts for all
+ communication with the card. However, there are 2 good
+ reasons not to do this.
+
+ First of all, the MIDI interface is going to use the same
+ interrupt. This presents no practical problem since Linux
+ allows us to share IRQ's. However, there are times when it
+ makes sense for a user to ask the driver to disable
+ interrupts, to avoid bothering Linux with a stream of MIDI
+ interrupts that aren't going to be used because nothing
+ cares about them. If we rely on them for communication with
+ the WaveFront synth as well, this disabling would be
+ crippling. Since being able to disable them can save quite
+ a bit of overhead (consider the interrupt frequency of a
+ physical MIDI controller like a modwheel being shunted back
+ and forth - its higher than the mouse, and much of
+ the time is of absolutely no interest to the kernel or any
+ user space processes whatsoever), we don't want to do this.
+
+ Secondly, much of the time, there's no reason to go to
+ sleep on a TX or RX status: the WaveFront gets back to us
+ quickly enough that its a lot more efficient to just busy
+ wait on the relevant status. Once we go to sleep, all is
+ lost anyway, and so interrupts don't really help us much anyway.
+
+ Therefore, we don't use interrupts for communication with
+ the WaveFront synth. We just poll the relevant RX/TX status.
+
+ However, there is one broad exception to this. During module
+ loading, to deal with several situations where timing would
+ be an issue, we use TX/RX interrupts to help us avoid busy
+ waiting for indeterminate and hard to manage periods of
+ time. So, TX/RX interrupts are enabled until the end of
+ wavefront_init(), and not used again after that.
+
+ */
+
+ /* Note: data port is now the data port, not the h/w initialization
+ port.
+
+ At this point, only "HW VERSION" or "DOWNLOAD OS" commands
+ will work. So, issue one of them, and wait for TX
+ interrupt. This can take a *long* time after a cold boot,
+ while the ISC ROM does its RAM test. The SDK says up to 4
+ seconds - with 12MB of RAM on a Tropez+, it takes a lot
+ longer than that (~16secs). Note that the card understands
+ the difference between a warm and a cold boot, so
+ subsequent ISC2115 reboots (say, caused by module
+ reloading) will get through this much faster.
+
+ Interesting question: why is no RX interrupt received first ?
*/
+
+ wavefront_should_cause_interrupt(hw, WFC_HARDWARE_VERSION,
+ hw->data_port, 20*HZ);
- if (!wavefront_wait (hw, STAT_CAN_WRITE)) {
- if (!wavefront_wait (hw, STAT_CAN_WRITE)) {
- if (!wavefront_wait (hw, STAT_CAN_WRITE)) {
- printk (KERN_WARNING
- "WaveFront: OS not ready after "
- "memory check.\n");
- free_irq (hw_config->irq, NULL);
- return 0;
- }
- }
+ if (!hw->irq_ok) {
+ printk (KERN_WARNING
+ "WaveFront: post-RAM-check interrupt not received.\n");
+ goto gone_bad;
+ }
+
+ if (!(wavefront_status(hw) & STAT_CAN_READ)) {
+ printk (KERN_WARNING
+ "WaveFront: no response to HW version cmd.\n");
+ goto gone_bad;
+ }
+
+ if ((hwv[0] = wavefront_read (hw)) == -1) {
+ printk (KERN_WARNING
+ "WaveFront: board not responding correctly.\n");
+ goto gone_bad;
}
- /* get H/W version, and check we get an interrupt */
-
- outb (WFC_HARDWARE_VERSION, hw->data_port);
-
- for (i = 0; i < 1000000 && !hw->irq_ok; i++);
-
- /* We don't need the IRQ anymore for the WaveFront code,
- and to allow an MPU-401 driver to attach to it later, lets
- give it back ....
+ if (hwv[0] == 0xFF) { /* NAK */
- DO NOT alter irq2hw[], since we'll still use this to lookup
- the config struct from an address_info struct.
- */
+ /* Board's RAM test failed. Try to read error code,
+ and tell us about it either way.
+ */
+
+ if ((hwv[0] = wavefront_read (hw)) == -1) {
+ printk (KERN_WARNING
+ "WaveFront: on-board RAM test failed "
+ "(bad error code).\n");
+ } else {
+ printk (KERN_WARNING
+ "WaveFront: on-board RAM test failed "
+ "(error code: 0x%x).\n",
+ hwv[0]);
+ }
+ goto gone_bad;
+ }
- free_irq (hw_config->irq, NULL);
+ /* We're OK, just get the next byte of the HW version response */
- if (!hw->irq_ok) {
+ if ((hwv[1] = wavefront_read (hw)) == -1) {
printk (KERN_WARNING
- "WaveFront: interrupt not received after "
- "h/w version cmd.\n");
- return 0;
- } else {
- hw->irq_ok = 0;
+ "WaveFront: board not responding correctly(2).\n");
+ goto gone_bad;
+ }
+
+ printk (KERN_INFO "WaveFront: hardware version %d.%d\n",
+ hwv[0], hwv[1]);
+
+ return 0;
+
+
+ gone_bad:
+ free_irq (hw->irq, hw);
+ return (1);
+ }
+
+int
+probe_wavefront (struct address_info *hw_config)
+
+{
+ unsigned char rbuf[4], wbuf[4];
+ wf_config *hw;
+
+ if (hw_config->irq < 0 || hw_config->irq > 16) {
+ printk (KERN_WARNING "WaveFront: impossible IRQ suggested(%d)\n",
+ hw_config->irq);
+ return 0;
}
- if ((tmp1 = wavefront_read(hw)) == -1) {
- printk (KERN_WARNING
- "WaveFront @ 0x%x not ready, ignoring\n", hw->base);
+ /* Yeah yeah, TB docs say 8, but the FX device on the Tropez Plus
+ takes up another 8 ...
+ */
+
+ if (check_region (hw_config->io_base, 16)) {
+ printk (KERN_ERR "WaveFront: IO address range 0x%x - 0x%x "
+ "already in use - ignored\n", hw_config->io_base,
+ hw_config->io_base+15);
return 0;
}
- if ((tmp2 = wavefront_read(hw)) == -1) {
- printk (KERN_WARNING
- "WaveFront @ 0x%x not responding correctly, ignoring\n",
- hw->base);
+ hw = &wavefront_configuration;
+
+ hw->irq = hw_config->irq;
+ hw->base = hw_config->io_base;
+
+ hw->israw = 0;
+ hw->debug = debug_default;
+ hw->interrupts_on = 0;
+ hw->rom_samples_rdonly = 1; /* XXX default lock on ROM sample slots */
+
+#ifdef WF_STATS
+ hw->status_found_during_sleep[0] = 0;
+ hw->status_found_during_sleep[1] = 0;
+ hw->status_found_during_sleep[2] = 0;
+ hw->status_found_during_sleep[3] = 0;
+ hw->status_found_during_loop = 0;
+#endif WF_STATS
+
+ hw_config->slots[WF_SYNTH_SLOT] = hw->synthdev = -1;
+ hw_config->slots[WF_INTERNAL_MIDI_SLOT] = hw->mididev = -1;
+ hw_config->slots[WF_EXTERNAL_MIDI_SLOT] = hw->ext_mididev = -1;
+
+ if (wavefront_cmd (hw, WFC_FIRMWARE_VERSION, rbuf, wbuf) == 0) {
+
+ hw->fw_version[0] = rbuf[0];
+ hw->fw_version[1] = rbuf[1];
+ printk (KERN_INFO
+ "WaveFront: firmware %d.%d already loaded.\n",
+ rbuf[0], rbuf[1]);
+
+ /* check that a command actually works */
+
+ if (wavefront_cmd (hw, WFC_HARDWARE_VERSION,
+ rbuf, wbuf) == 0) {
+ hw->hw_version[0] = rbuf[0];
+ hw->hw_version[1] = rbuf[1];
+ } else {
+ printk (KERN_INFO "WaveFront: not raw, but no "
+ "hardware version!\n");
+ return 0;
+ }
+
+ if (!wf_raw) {
+ return 1;
+ } else {
+ printk (KERN_INFO
+ "WaveFront: reloading firmware anyway.\n");
+ }
+
+ } else {
+
+ hw->israw = 1;
+ printk (KERN_INFO "WaveFront: no response to firmware probe, "
+ "assume raw.\n");
+
+ }
+
+ init_waitqueue (&hw->interrupt_sleeper);
+
+ if (wavefront_hw_reset (hw)) {
+ printk (KERN_WARNING "WaveFront: hardware reset failed\n");
return 0;
}
-
- printk (KERN_INFO "WaveFront: hardware version %d.%d\n", tmp1, tmp2);
-
+
return 1;
}
@@ -2465,7 +2624,8 @@ wavefront_download_firmware (wf_config *hw, char *path)
set_fs (get_ds());
if ((fd = open (path, 0, 0)) < 0) {
- printk (KERN_WARNING "WaveFront: Unable to load \"%s\".\n", path);
+ printk (KERN_WARNING "WaveFront: Unable to load \"%s\".\n",
+ path);
return 1;
}
@@ -2512,9 +2672,13 @@ wavefront_download_firmware (wf_config *hw, char *path)
section_cnt_downloaded + 1, c);
goto failure;
- } else if ((hw->debug & WF_DEBUG_IO) &&
+ } else {
+#ifdef WF_DEBUG
+ if ((hw->debug & WF_DEBUG_IO) &&
!(++section_cnt_downloaded % 10)) {
printk (KERN_DEBUG ".");
+ }
+#endif WF_DEBUG
}
} else {
@@ -2526,9 +2690,11 @@ wavefront_download_firmware (wf_config *hw, char *path)
close (fd);
set_fs (fs);
+#ifdef WF_DEBUG
if (hw->debug & WF_DEBUG_IO) {
printk (KERN_DEBUG "\n");
}
+#endif WF_DEBUG
return 0;
failure:
@@ -2618,81 +2784,137 @@ wavefront_config_midi (wf_config *hw, struct address_info *hw_config)
}
static int
-wavefront_init (wf_config *hw, struct address_info *hw_config)
+wavefront_do_reset (wf_config *hw, int atboot)
{
- int samples_are_from_rom = 0;
+ char voices[1];
- /* XXX what state does the board need to be in before
- I can download the firmware ? I think any state
- after it acknowledges a hardware version command
- post-booting.
- */
+ if (!atboot && wavefront_hw_reset (hw)) {
+ printk (KERN_WARNING "WaveFront: hw reset failed.\n");
+ goto gone_bad;
+ }
if (hw->israw || wf_raw) {
- samples_are_from_rom = 1;
-
- if (wavefront_download_firmware (hw, wf_ospath)) {
+ if (wavefront_download_firmware (hw, ospath)) {
+ goto gone_bad;
return 1;
}
-
- /* enter normal operation:
- bit 7: (on) reset 0x80
- bit 6: interrupts enabled 0x40
- bit 5: (on) mute (i.e. in play mode) 0x20
- bits 4-0: zero
+ }
+
+ if (fx_raw) {
+ wffx_init (hw);
+ }
+
+ /* If we loaded the OS, we now have to wait for it to be ready
+ to roll. We can't guarantee that interrupts are enabled,
+ because we might be reloading the module without forcing a
+ reset/reload of the firmware.
- note: tx and rx interrupts turned off
- */
+ Rather than busy-wait, lets just turn interrupts on.
+ */
+
+ outb (0x80|0x40|0x10|0x1, hw->control_port);
+
+ wavefront_should_cause_interrupt (hw, WFC_NOOP,
+ hw->data_port, (10*HZ));
- outb (0x80|0x40|0x20, hw->control_port);
+ if (!hw->irq_ok) {
+ printk (KERN_WARNING "WaveFront: no post-OS interrupt.\n");
+ goto gone_bad;
+ }
+
+ /* Now, do it again ! */
+
+ wavefront_should_cause_interrupt (hw, WFC_NOOP,
+ hw->data_port, (10*HZ));
- /* Set up MPU-401 emulation mode. For some reason, this always
- fails the first time, and generates no ACK, so we'll
- treat it as a special case by sleeping for a while, and then
- trying again.
- */
+ if (!hw->irq_ok) {
+ printk (KERN_WARNING "WaveFront: no post-OS interrupt(2).\n");
+ goto gone_bad;
+ }
- wavefront_write (hw, 0xf0);
- wavefront_write (hw, 1);
- wavefront_sleep (hw, (HZ/wf_sleep_interval) * wf_sleep_tries);
- wavefront_write (hw, 0xf0);
- wavefront_write (hw, 1);
- if (wavefront_read (hw) != 0x80) {
- printk (KERN_ERR
- "WaveFront: set MPU emulation mode "
- "command failed.\n");
- return (1);
+ /* OK, no (RX/TX) interrupts any more, but leave mute
+ on. Master interrupts get enabled when we're done here.
+ */
+
+ outb (0x80, hw->control_port);
+
+ /* No need for the IRQ anymore */
+
+ free_irq (hw->irq, hw);
+
+ /* SETUPSND.EXE asks for sample memory config here, but since i
+ have no idea how to interpret the result, we'll forget
+ about it.
+ */
+
+ if ((hw->freemem = wavefront_freemem (hw)) < 0) {
+ goto gone_bad;
+ }
+
+ printk (KERN_INFO "WaveFront: available DRAM %dk\n", hw->freemem / 1024);
+
+ if (!wavefront_write (hw, 0xf0) ||
+ !wavefront_write (hw, 1) ||
+ (wavefront_read (hw) < 0)) {
+ hw->debug = 0;
+ printk (KERN_WARNING "WaveFront: MPU emulation mode not set.\n");
+ goto gone_bad;
+ }
+
+ voices[0] = 32;
+
+ if (wavefront_cmd (hw, WFC_SET_NVOICES, 0, voices)) {
+ printk (KERN_WARNING
+ "WaveFront: cannot set number of voices to 32.\n");
+ }
+
+ return 0;
+
+ gone_bad:
+ /* reset that sucker so that it doesn't bother us. */
+
+ outb (0x0, hw->control_port);
+ free_irq (hw->irq, hw);
+ return 1;
+}
+
+static int
+wavefront_init (wf_config *hw, int atboot)
+
+{
+ int samples_are_from_rom;
+
+ if (hw->israw || wf_raw) {
+ samples_are_from_rom = 1;
+ } else {
+ samples_are_from_rom = 0;
+ }
+
+ if (hw->israw || wf_raw || fx_raw) {
+ if (wavefront_do_reset (hw, atboot)) {
+ return 1;
}
}
- hw->freemem = wavefront_freemem (hw);
- printk (KERN_INFO "WaveFront: available DRAM %dk\n", hw->freemem / 1024);
-
wavefront_get_sample_status (hw, samples_are_from_rom);
wavefront_get_program_status (hw);
wavefront_get_patch_status (hw);
- if (fx_raw) {
- wffx_init (hw);
- }
-
- return 0;
+ /* Start normal operation: unreset, master interrupt enable
+ (for MPU interrupts) no mute
+ */
+
+ outb (0x80|0x40|0x20, hw->control_port);
+
+ return (0);
}
void
attach_wavefront (struct address_info *hw_config)
{
int i;
- struct wf_config *hw;
-
- if ((i = irq2hw[hw_config->irq]) == -1) {
- printk (KERN_ERR "WaveFront: cannot attach unknown irq 0x%x.\n",
- hw_config->irq);
- return;
- }
-
- hw = &wfs[i];
+ struct wf_config *hw = &wavefront_configuration;
if ((i = sound_alloc_synthdev()) == -1) {
printk (KERN_ERR "WaveFront: Too many synthesizers\n");
@@ -2700,15 +2922,13 @@ attach_wavefront (struct address_info *hw_config)
} else {
hw_config->slots[WF_SYNTH_SLOT] = i;
hw->synthdev = i;
- dev2hw[hw->synthdev] = i;
synth_devs[hw->synthdev] = &wavefront_operations;
}
- if (wavefront_init (hw, hw_config)) {
+ if (wavefront_init (hw, 1)) {
printk (KERN_WARNING "WaveFront: board could not "
"be initialized.\n");
sound_unload_synthdev (i);
- hw->installed = 0;
return;
}
@@ -2731,18 +2951,11 @@ attach_wavefront (struct address_info *hw_config)
void
unload_wavefront (struct address_info *hw_config)
{
- struct wf_config *hw;
- int i;
-
- if ((i = irq2hw[hw_config->irq]) == -1) {
- printk (KERN_ERR "WaveFront: unloading unrecognized device!\n");
- return;
- }
- hw = &wfs[i];
+ struct wf_config *hw = &wavefront_configuration;
/* the first two are freed by the wf_mpu code */
- release_region (hw_config->io_base+2, 6);
- release_region (hw_config->io_base+8, 8);
+ release_region (hw->base+2, 6);
+ release_region (hw->base+8, 8);
sound_unload_synthdev (hw->synthdev);
#if defined(CONFIG_MIDI)
unload_wf_mpu (hw_config);
@@ -2802,13 +3015,13 @@ wffx_memset (struct wf_config *hw, int page,
if (page < 0 || page > 7) {
printk (KERN_ERR "WaveFront: FX memset: "
"page must be >= 0 and <= 7\n");
- return -EINVAL;
+ return -(EINVAL);
}
if (addr < 0 || addr > 0x7f) {
printk (KERN_ERR "WaveFront: FX memset: "
"addr must be >= 0 and <= 7f\n");
- return -EINVAL;
+ return -(EINVAL);
}
if (cnt == 1) {
@@ -2842,7 +3055,7 @@ wffx_memset (struct wf_config *hw, int page,
"WaveFront: FX memset "
"(0x%x, 0x%x, 0x%x, %d) incomplete\n",
page, addr, (int) data, cnt);
- return -EIO;
+ return -(EIO);
}
}
@@ -2866,18 +3079,17 @@ wffx_ioctl (struct wf_config *hw, wavefront_fx_info *r)
if (r->data[2] <= 0) {
printk (KERN_ERR "WaveFront: cannot write "
"<= 0 bytes to FX\n");
- return -EINVAL;
+ return -(EINVAL);
} else if (r->data[2] == 1) {
pd = (unsigned short *) &r->data[3];
} else {
if (r->data[2] > sizeof (page_data)) {
- printk (KERN_ERR
- "WaveFront: cannot write "
+ printk (KERN_ERR "WaveFront: cannot write "
"> 255 bytes to FX\n");
- return -EINVAL;
+ return -(EINVAL);
}
- COPY_FROM_USER(page_data, (unsigned char *) r->data[3],
- r->data[2]);
+ copy_from_user (page_data, (unsigned char *) r->data[3],
+ r->data[2]);
pd = page_data;
}
@@ -2891,7 +3103,7 @@ wffx_ioctl (struct wf_config *hw, wavefront_fx_info *r)
printk (KERN_WARNING
"WaveFront: FX: ioctl %d not yet supported\n",
r->request);
- return -EINVAL;
+ return -(EINVAL);
}
}
@@ -3364,7 +3576,7 @@ wffx_init (struct wf_config *hw)
outb (0x00, hw->fx_op); /* mute off */
- return 0;
+ return (0);
}
EXPORT_NO_SYMBOLS;
@@ -3388,6 +3600,7 @@ int init_module (void)
"options must be set.\n");
return -EINVAL;
}
+
cfg.io_base = io;
cfg.irq = irq;
@@ -3406,7 +3619,6 @@ void cleanup_module (void)
SOUND_LOCK_END;
}
-#endif MODULE
-#endif CONFIG_SOUND_WAVEFRONT
+#endif CONFIG_SOUND_WAVEFRONT_MODULE_AND_MODULE
diff --git a/drivers/sound/wf_midi.c b/drivers/sound/wf_midi.c
index c525abc97..2333fd118 100644
--- a/drivers/sound/wf_midi.c
+++ b/drivers/sound/wf_midi.c
@@ -454,12 +454,12 @@ wf_mpu_open (int dev, int mode,
struct wf_mpu_config *devc;
if (dev < 0 || dev >= num_midis || midi_devs[dev]==NULL)
- return -ENXIO;
+ return -(ENXIO);
devc = &dev_conf[dev];
if (devc->opened) {
- return -EBUSY;
+ return -(EBUSY);
}
devc->mode = MODE_MIDI;
@@ -678,8 +678,8 @@ static struct synth_operations wf_mpu_synth_proto =
midi_synth_send_sysex
};
-static struct synth_operations wf_mpu_synth_operations[WAVEFRONT_MAX_DEVICES*2];
-static struct midi_operations wf_mpu_midi_operations[WAVEFRONT_MAX_DEVICES*2];
+static struct synth_operations wf_mpu_synth_operations[2];
+static struct midi_operations wf_mpu_midi_operations[2];
static int wfmpu_cnt = 0;
static struct midi_operations wf_mpu_midi_proto =
@@ -707,9 +707,8 @@ config_wf_mpu (int dev, struct address_info *hw_config)
struct wf_mpu_config *devc;
int internal;
- if (wfmpu_cnt >= WAVEFRONT_MAX_DEVICES * 2) {
- printk (KERN_ERR "WF-MPU: eh ? more MPU devices "
- "than cards ?!!\n");
+ if (wfmpu_cnt >= 2) {
+ printk (KERN_ERR "WF-MPU: more MPU devices than cards ?!!\n");
return (-1);
}