summaryrefslogtreecommitdiffstats
path: root/drivers/sound
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1999-06-17 13:25:08 +0000
committerRalf Baechle <ralf@linux-mips.org>1999-06-17 13:25:08 +0000
commit59223edaa18759982db0a8aced0e77457d10c68e (patch)
tree89354903b01fa0a447bffeefe00df3044495db2e /drivers/sound
parentdb7d4daea91e105e3859cf461d7e53b9b77454b2 (diff)
Merge with Linux 2.3.6. Sorry, this isn't tested on silicon, I don't
have a MIPS box at hand.
Diffstat (limited to 'drivers/sound')
-rw-r--r--drivers/sound/Config.in10
-rw-r--r--drivers/sound/Makefile1
-rw-r--r--drivers/sound/audio.c2
-rw-r--r--drivers/sound/bin2hex.c1
-rw-r--r--drivers/sound/dev_table.c6
-rw-r--r--drivers/sound/dev_table.h6
-rw-r--r--drivers/sound/dmasound.c58
-rw-r--r--drivers/sound/es1370.c81
-rw-r--r--drivers/sound/es1371.c28
-rw-r--r--drivers/sound/gus_wave.c4
-rw-r--r--drivers/sound/hex2hex.c1
-rw-r--r--drivers/sound/lowlevel/awe_compat.h2
-rw-r--r--drivers/sound/lowlevel/awe_wave.c4
-rw-r--r--drivers/sound/midibuf.c8
-rw-r--r--drivers/sound/msnd.h5
-rw-r--r--drivers/sound/msnd_pinnacle.c6
-rw-r--r--drivers/sound/sb_common.c53
-rw-r--r--drivers/sound/sb_ess.c1018
-rw-r--r--drivers/sound/sequencer.c8
-rw-r--r--drivers/sound/sonicvibes.c24
-rw-r--r--drivers/sound/sound_core.c21
-rw-r--r--drivers/sound/sound_timer.c1
-rw-r--r--drivers/sound/wavfront.c4
23 files changed, 658 insertions, 694 deletions
diff --git a/drivers/sound/Config.in b/drivers/sound/Config.in
index ebc695d0c..20da69d44 100644
--- a/drivers/sound/Config.in
+++ b/drivers/sound/Config.in
@@ -9,11 +9,11 @@
# Prompt user for primary drivers.
-if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
- dep_tristate 'Ensoniq AudioPCI (ES1370)' CONFIG_SOUND_ES1370 $CONFIG_SOUND
- if [ "$CONFIG_SOUND_ES1370" = "y" ]; then
- bool 'Joystick support at boot time' CONFIG_SOUND_ES1370_JOYPORT_BOOT
- fi
+dep_tristate 'C-Media PCI (CMI8338/8378)' CONFIG_SOUND_CMPCI $CONFIG_SOUND
+dep_tristate 'Ensoniq AudioPCI (ES1370)' CONFIG_SOUND_ES1370 $CONFIG_SOUND
+if [ "$CONFIG_SOUND_ES1370" = "y" ]; then
+ bool 'Joystick support at boot time' CONFIG_SOUND_ES1370_JOYPORT_BOOT
+fi
dep_tristate 'Creative Ensoniq AudioPCI 97 (ES1371)' CONFIG_SOUND_ES1371 $CONFIG_SOUND
fi
dep_tristate 'S3 SonicVibes' CONFIG_SOUND_SONICVIBES $CONFIG_SOUND
diff --git a/drivers/sound/Makefile b/drivers/sound/Makefile
index 1d56036e6..af3c37d31 100644
--- a/drivers/sound/Makefile
+++ b/drivers/sound/Makefile
@@ -76,6 +76,7 @@ obj-$(CONFIG_SOUND_WAVEARTIST) += waveartist.o
obj-$(CONFIG_SOUND_WAVEFRONT) += wavefront.o
#jnx
+obj-$(CONFIG_SOUND_CMPCI) += cmpci.o
obj-$(CONFIG_SOUND_ES1370) += es1370.o
obj-$(CONFIG_SOUND_ES1371) += es1371.o
obj-$(CONFIG_SOUND_SONICVIBES) += sonicvibes.o
diff --git a/drivers/sound/audio.c b/drivers/sound/audio.c
index ac2b6d40a..716e738e4 100644
--- a/drivers/sound/audio.c
+++ b/drivers/sound/audio.c
@@ -20,10 +20,12 @@
* Thomas Sailer : use more logical O_NONBLOCK semantics
* Daniel Rodriksson: reworked the use of the device specific copy_user
* still generic
+ * Horst von Brand: Add missing #include <linux/string.h>
*/
#include <linux/config.h>
#include <linux/stddef.h>
+#include <linux/string.h>
#include <linux/kmod.h>
#include "sound_config.h"
diff --git a/drivers/sound/bin2hex.c b/drivers/sound/bin2hex.c
index fc49c99d9..100f18f9c 100644
--- a/drivers/sound/bin2hex.c
+++ b/drivers/sound/bin2hex.c
@@ -1,4 +1,5 @@
#include <stdio.h>
+#include <string.h>
int main( int argc, const char * argv [] )
{
diff --git a/drivers/sound/dev_table.c b/drivers/sound/dev_table.c
index dd12a0c68..71d820b9e 100644
--- a/drivers/sound/dev_table.c
+++ b/drivers/sound/dev_table.c
@@ -435,9 +435,9 @@ int sound_install_audiodrv(int vers, char *name, struct audio_driver *driver,
return -(ENOMEM);
}
memset((char *) op, 0, sizeof(struct audio_operations));
- init_waitqueue(&op->in_sleeper);
- init_waitqueue(&op->out_sleeper);
- init_waitqueue(&op->poll_sleeper);
+ init_waitqueue_head(&op->in_sleeper);
+ init_waitqueue_head(&op->out_sleeper);
+ init_waitqueue_head(&op->poll_sleeper);
if (driver_size < sizeof(struct audio_driver))
memset((char *) d, 0, sizeof(struct audio_driver));
diff --git a/drivers/sound/dev_table.h b/drivers/sound/dev_table.h
index cf6475662..7043885f0 100644
--- a/drivers/sound/dev_table.h
+++ b/drivers/sound/dev_table.h
@@ -234,9 +234,9 @@ struct audio_operations
int parent_dev; /* 0 -> no parent, 1 to n -> parent=parent_dev+1 */
/* fields formerly in dmabuf.c */
- struct wait_queue *in_sleeper;
- struct wait_queue *out_sleeper;
- struct wait_queue *poll_sleeper;
+ wait_queue_head_t in_sleeper;
+ wait_queue_head_t out_sleeper;
+ wait_queue_head_t poll_sleeper;
/* fields formerly in audio.c */
int audio_mode;
diff --git a/drivers/sound/dmasound.c b/drivers/sound/dmasound.c
index 5f96b3a42..fe1cd95aa 100644
--- a/drivers/sound/dmasound.c
+++ b/drivers/sound/dmasound.c
@@ -784,6 +784,7 @@ static ssize_t sound_copy_translate(const u_char *userPtr,
struct sound_mixer {
int busy;
+ int modify_counter;
};
static struct sound_mixer mixer;
@@ -809,7 +810,7 @@ struct sound_queue {
* Bit 1 is set: a frame is playing
*/
int playing;
- struct wait_queue *write_queue, *open_queue, *sync_queue;
+ wait_queue_head_t write_queue, open_queue, sync_queue;
int open_mode;
int busy, syncing;
#ifdef CONFIG_ATARI
@@ -3811,10 +3812,23 @@ static int mixer_ioctl(struct inode *inode, struct file *file, u_int cmd,
u_long arg)
{
int data;
+ if (_SIOC_DIR(cmd) & _SIOC_WRITE)
+ mixer.modify_counter++;
+ if (cmd == OSS_GETVERSION)
+ return IOCTL_OUT(arg, SOUND_VERSION);
switch (sound.mach.type) {
#ifdef CONFIG_ATARI
case DMASND_FALCON:
switch (cmd) {
+ case SOUND_MIXER_INFO: {
+ mixer_info info;
+ strncpy(info.id, "FALCON", sizeof(info.id));
+ strncpy(info.name, "FALCON", sizeof(info.name));
+ info.name[sizeof(info.name)-1] = 0;
+ info.modify_counter = mixer.modify_counter;
+ copy_to_user_ret((int *)arg, &info, sizeof(info), -EFAULT);
+ return 0;
+ }
case SOUND_MIXER_READ_DEVMASK:
return IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_MIC | SOUND_MASK_SPEAKER);
case SOUND_MIXER_READ_RECMASK:
@@ -3866,6 +3880,15 @@ static int mixer_ioctl(struct inode *inode, struct file *file, u_int cmd,
case DMASND_TT:
switch (cmd) {
+ case SOUND_MIXER_INFO: {
+ mixer_info info;
+ strncpy(info.id, "TT", sizeof(info.id));
+ strncpy(info.name, "TT", sizeof(info.name));
+ info.name[sizeof(info.name)-1] = 0;
+ info.modify_counter = mixer.modify_counter;
+ copy_to_user_ret((int *)arg, &info, sizeof(info), -EFAULT);
+ return 0;
+ }
case SOUND_MIXER_READ_DEVMASK:
return IOCTL_OUT(arg,
SOUND_MASK_VOLUME | SOUND_MASK_TREBLE | SOUND_MASK_BASS |
@@ -3927,6 +3950,15 @@ static int mixer_ioctl(struct inode *inode, struct file *file, u_int cmd,
#ifdef CONFIG_AMIGA
case DMASND_AMIGA:
switch (cmd) {
+ case SOUND_MIXER_INFO: {
+ mixer_info info;
+ strncpy(info.id, "AMIGA", sizeof(info.id));
+ strncpy(info.name, "AMIGA", sizeof(info.name));
+ info.name[sizeof(info.name)-1] = 0;
+ info.modify_counter = mixer.modify_counter;
+ copy_to_user_ret((int *)arg, &info, sizeof(info), -EFAULT);
+ return 0;
+ }
case SOUND_MIXER_READ_DEVMASK:
return IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_TREBLE);
case SOUND_MIXER_READ_RECMASK:
@@ -3953,6 +3985,16 @@ static int mixer_ioctl(struct inode *inode, struct file *file, u_int cmd,
case DMASND_AWACS:
if (awacs_revision<AWACS_BURGUNDY) { /* Different IOCTLS for burgundy*/
switch (cmd) {
+ case SOUND_MIXER_INFO: {
+ mixer_info info;
+ strncpy(info.id, "AWACS", sizeof(info.id));
+ strncpy(info.name, "AWACS", sizeof(info.name));
+ info.name[sizeof(info.name)-1] = 0;
+ info.modify_counter = mixer.modify_counter;
+ copy_to_user_ret((int *)arg, &info,
+ sizeof(info), -EFAULT);
+ return 0;
+ }
case SOUND_MIXER_READ_DEVMASK:
data = SOUND_MASK_VOLUME | SOUND_MASK_SPEAKER
| SOUND_MASK_LINE | SOUND_MASK_MIC
@@ -4066,6 +4108,16 @@ static int mixer_ioctl(struct inode *inode, struct file *file, u_int cmd,
} else {
/* We are, we are, we are... Burgundy or better */
switch(cmd) {
+ case SOUND_MIXER_INFO: {
+ mixer_info info;
+ strncpy(info.id, "AWACS", sizeof(info.id));
+ strncpy(info.name, "AWACS", sizeof(info.name));
+ info.name[sizeof(info.name)-1] = 0;
+ info.modify_counter = mixer.modify_counter;
+ copy_to_user_ret((int *)arg, &info,
+ sizeof(info), -EFAULT);
+ return 0;
+ }
case SOUND_MIXER_READ_DEVMASK:
data = SOUND_MASK_VOLUME | SOUND_MASK_CD |
SOUND_MASK_LINE | SOUND_MASK_MIC |
@@ -4623,7 +4675,9 @@ static void __init sq_init(void)
if (sq_unit < 0)
return;
- sq.write_queue = sq.open_queue = sq.sync_queue = 0;
+ init_waitqueue_head(&sq.write_queue);
+ init_waitqueue_head(&sq.open_queue);
+ init_waitqueue_head(&sq.sync_queue);
sq.busy = 0;
/* whatever you like as startup mode for /dev/dsp,
diff --git a/drivers/sound/es1370.c b/drivers/sound/es1370.c
index 1ce70dc7b..ace8f3098 100644
--- a/drivers/sound/es1370.c
+++ b/drivers/sound/es1370.c
@@ -33,8 +33,8 @@
* to make the card a four channel one: use dsp to output two
* channels to LINE and dac to output the other two channels to
* SPKR. Set the mixer to only output synth to SPKR.
- * micz it looks like this changes the MIC input impedance. I don't know
- * any detail though.
+ * micbias sets the +5V bias to the mic if using an electretmic.
+ *
*
* Note: sync mode is not yet supported (i.e. running dsp and dac from the same
* clock source)
@@ -92,6 +92,12 @@
* Alpha fixes reported by Peter Jones <pjones@redhat.com>
* Note: joystick address handling might still be wrong on archs
* other than i386
+ * 10.05.99 0.21 Added support for an electret mic for SB PCI64
+ * to the Linux kernel sound driver. This mod also straighten
+ * out the question marks around the mic impedance setting
+ * (micz). From Kim.Berts@fisub.mail.abb.com
+ * 11.05.99 0.22 Implemented the IMIX call to mute recording monitor.
+ * Guenter Geiger <geiger@epy.co.at>
*
* some important things missing in Ensoniq documentation:
*
@@ -107,8 +113,8 @@
* The card uses a 22.5792 MHz crystal.
* The LINEIN jack may be converted to an AOUT jack by
* setting pin 47 (XCTL0) of the ES1370 to high.
- * Pin 48 (XCTL1) of the ES1370 presumably changes the input impedance of the
- * MIC jack.
+ * Pin 48 (XCTL1) of the ES1370 sets the +5V bias for an electretmic
+ *
*
*/
@@ -190,7 +196,7 @@ static const unsigned dac1_samplerate[] = { 5512, 11025, 22050, 44100 };
#define DAC2_DIVTOSR(x) (1411200/((x)+2))
#define CTRL_ADC_STOP 0x80000000 /* 1 = ADC stopped */
-#define CTRL_XCTL1 0x40000000 /* ? mic impedance */
+#define CTRL_XCTL1 0x40000000 /* electret mic bias */
#define CTRL_OPEN 0x20000000 /* no function, can be read and written */
#define CTRL_PCLKDIV 0x1fff0000 /* ADC/DAC2 clock divider */
#define CTRL_SH_PCLKDIV 16
@@ -301,6 +307,7 @@ struct es1370_state {
unsigned int recsrc;
unsigned int modcnt;
unsigned short micpreamp;
+ unsigned int imix;
} mix;
/* wave stuff */
@@ -310,7 +317,7 @@ struct es1370_state {
spinlock_t lock;
struct semaphore open_sem;
mode_t open_mode;
- struct wait_queue *open_wait;
+ wait_queue_head_t open_wait;
struct dmabuf {
void *rawbuf;
@@ -321,7 +328,7 @@ struct es1370_state {
unsigned total_bytes;
int count;
unsigned error; /* over/underrun */
- struct wait_queue *wait;
+ wait_queue_head_t wait;
/* redundant, but makes calculations easier */
unsigned fragsize;
unsigned dmasize;
@@ -339,8 +346,8 @@ struct es1370_state {
struct {
unsigned ird, iwr, icnt;
unsigned ord, owr, ocnt;
- struct wait_queue *iwait;
- struct wait_queue *owait;
+ wait_queue_head_t iwait;
+ wait_queue_head_t owait;
unsigned char ibuf[MIDIINBUF];
unsigned char obuf[MIDIOUTBUF];
} midi;
@@ -839,7 +846,8 @@ static int mixer_ioctl(struct es1370_state *s, unsigned int cmd, unsigned long a
return put_user(s->mix.recsrc, (int *)arg);
case SOUND_MIXER_DEVMASK: /* Arg contains a bit for each supported device */
- for (val = i = 0; i < SOUND_MIXER_NRDEVICES; i++)
+ val = SOUND_MASK_IMIX;
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
if (mixtable[i].avail)
val |= 1 << i;
return put_user(val, (int *)arg);
@@ -858,6 +866,9 @@ static int mixer_ioctl(struct es1370_state *s, unsigned int cmd, unsigned long a
case SOUND_MIXER_CAPS:
return put_user(0, (int *)arg);
+
+ case SOUND_MIXER_IMIX:
+ return put_user(s->mix.imix, (int *)arg);
default:
i = _IOC_NR(cmd);
@@ -870,6 +881,14 @@ static int mixer_ioctl(struct es1370_state *s, unsigned int cmd, unsigned long a
return -EINVAL;
s->mix.modcnt++;
switch (_IOC_NR(cmd)) {
+
+ case SOUND_MIXER_IMIX:
+ if (arg == 0)
+ return -EFAULT;
+ get_user_ret(s->mix.imix,(int *)arg, -EFAULT);
+ val = s->mix.recsrc;
+ /* fall through */
+
case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */
get_user_ret(val, (int *)arg, -EFAULT);
for (j = i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
@@ -886,7 +905,10 @@ static int mixer_ioctl(struct es1370_state *s, unsigned int cmd, unsigned long a
wrcodec(s, 0x13, j & 0xaa);
wrcodec(s, 0x14, (j >> 8) & 0x17);
wrcodec(s, 0x15, (j >> 8) & 0x0f);
- i = (j & 0x37f) | ((j << 1) & 0x3000) | 0xc30;
+ i = (j & 0x37f) | ((j << 1) & 0x3000) | 0xc60;
+ if (!s->mix.imix) {
+ i &= 0xff60; /* mute record and line monitor */
+ }
wrcodec(s, 0x10, i);
wrcodec(s, 0x11, i >> 8);
return 0;
@@ -1007,7 +1029,7 @@ static /*const*/ struct file_operations es1370_mixer_fops = {
static int drain_dac1(struct es1370_state *s, int nonblock)
{
- struct wait_queue wait = { current, NULL };
+ DECLARE_WAITQUEUE(wait, current);
unsigned long flags;
int count, tmo;
@@ -1042,7 +1064,7 @@ static int drain_dac1(struct es1370_state *s, int nonblock)
static int drain_dac2(struct es1370_state *s, int nonblock)
{
- struct wait_queue wait = { current, NULL };
+ DECLARE_WAITQUEUE(wait, current);
unsigned long flags;
int count, tmo;
@@ -2191,7 +2213,7 @@ static int es1370_midi_open(struct inode *inode, struct file *file)
static int es1370_midi_release(struct inode *inode, struct file *file)
{
struct es1370_state *s = (struct es1370_state *)file->private_data;
- struct wait_queue wait = { current, NULL };
+ DECLARE_WAITQUEUE(wait, current);
unsigned long flags;
unsigned count, tmo;
@@ -2262,7 +2284,7 @@ static int joystick[NR_DEVICE] = { 1, 0, };
static int joystick[NR_DEVICE] = { 0, };
#endif
static int lineout[NR_DEVICE] = { 0, };
-static int micz[NR_DEVICE] = { 0, };
+static int micbias[NR_DEVICE] = { 0, };
/* --------------------------------------------------------------------- */
@@ -2295,7 +2317,7 @@ __initfunc(int init_es1370(void))
if (!pci_present()) /* No PCI bus in this machine! */
return -ENODEV;
- printk(KERN_INFO "es1370: version v0.20 time " __TIME__ " " __DATE__ "\n");
+ printk(KERN_INFO "es1370: version v0.22 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 ||
@@ -2308,13 +2330,13 @@ __initfunc(int init_es1370(void))
continue;
}
memset(s, 0, sizeof(struct es1370_state));
- init_waitqueue(&s->dma_adc.wait);
- init_waitqueue(&s->dma_dac1.wait);
- init_waitqueue(&s->dma_dac2.wait);
- init_waitqueue(&s->open_wait);
- init_waitqueue(&s->midi.iwait);
- init_waitqueue(&s->midi.owait);
- s->open_sem = MUTEX;
+ init_waitqueue_head(&s->dma_adc.wait);
+ init_waitqueue_head(&s->dma_dac1.wait);
+ init_waitqueue_head(&s->dma_dac2.wait);
+ init_waitqueue_head(&s->open_wait);
+ init_waitqueue_head(&s->midi.iwait);
+ init_waitqueue_head(&s->midi.owait);
+ init_MUTEX(&s->open_sem);
s->magic = ES1370_MAGIC;
s->io = pcidev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
s->irq = pcidev->irq;
@@ -2328,8 +2350,10 @@ __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) | (1 << CTRL_SH_WTSRSEL);
- if (joystick[index]) {
+ /* note: setting CTRL_SERR_DIS is reported to break
+ * mic bias setting (by Kim.Berts@fisub.mail.abb.com) */
+ s->ctrl = CTRL_CDC_EN | (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");
else
@@ -2337,7 +2361,7 @@ __initfunc(int init_es1370(void))
}
if (lineout[index])
s->ctrl |= CTRL_XCTL0;
- if (micz[index])
+ if (micbias[index])
s->ctrl |= CTRL_XCTL1;
s->sctrl = 0;
printk(KERN_INFO "es1370: found adapter at io %#lx irq %u\n"
@@ -2361,6 +2385,7 @@ __initfunc(int init_es1370(void))
wrcodec(s, 0x17, 0); /* CODEC ADC and CODEC DAC use {LR,B}CLK2 and run off the LRCLK2 PLL; program DAC_SYNC=0!! */
wrcodec(s, 0x18, 0); /* recording source is mixer */
wrcodec(s, 0x19, s->mix.micpreamp = 1); /* turn on MIC preamp */
+ s->mix.imix = 1;
fs = get_fs();
set_fs(KERNEL_DS);
val = SOUND_MASK_LINE|SOUND_MASK_SYNTH|SOUND_MASK_CD;
@@ -2403,8 +2428,8 @@ 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(micbias, "1-" __MODULE_STRING(NR_DEVICE) "i");
+MODULE_PARM_DESC(micbias, "sets the +5V bias for an electret microphone");
MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");
MODULE_DESCRIPTION("ES1370 AudioPCI Driver");
diff --git a/drivers/sound/es1371.c b/drivers/sound/es1371.c
index fa2efd25f..d416d0e28 100644
--- a/drivers/sound/es1371.c
+++ b/drivers/sound/es1371.c
@@ -361,7 +361,7 @@ struct es1371_state {
spinlock_t lock;
struct semaphore open_sem;
mode_t open_mode;
- struct wait_queue *open_wait;
+ wait_queue_head_t open_wait;
struct dmabuf {
void *rawbuf;
@@ -372,7 +372,7 @@ struct es1371_state {
unsigned total_bytes;
int count;
unsigned error; /* over/underrun */
- struct wait_queue *wait;
+ wait_queue_head_t wait;
/* redundant, but makes calculations easier */
unsigned fragsize;
unsigned dmasize;
@@ -390,8 +390,8 @@ struct es1371_state {
struct {
unsigned ird, iwr, icnt;
unsigned ord, owr, ocnt;
- struct wait_queue *iwait;
- struct wait_queue *owait;
+ wait_queue_head_t iwait;
+ wait_queue_head_t owait;
unsigned char ibuf[MIDIINBUF];
unsigned char obuf[MIDIOUTBUF];
} midi;
@@ -1454,7 +1454,7 @@ static /*const*/ struct file_operations es1371_mixer_fops = {
static int drain_dac1(struct es1371_state *s, int nonblock)
{
- struct wait_queue wait = { current, NULL };
+ DECLARE_WAITQUEUE(wait, current);
unsigned long flags;
int count, tmo;
@@ -1489,7 +1489,7 @@ static int drain_dac1(struct es1371_state *s, int nonblock)
static int drain_dac2(struct es1371_state *s, int nonblock)
{
- struct wait_queue wait = { current, NULL };
+ DECLARE_WAITQUEUE(wait, current);
unsigned long flags;
int count, tmo;
@@ -2625,7 +2625,7 @@ static int es1371_midi_open(struct inode *inode, struct file *file)
static int es1371_midi_release(struct inode *inode, struct file *file)
{
struct es1371_state *s = (struct es1371_state *)file->private_data;
- struct wait_queue wait = { current, NULL };
+ DECLARE_WAITQUEUE(wait, current);
unsigned long flags;
unsigned count, tmo;
@@ -2745,13 +2745,13 @@ __initfunc(int init_es1371(void))
continue;
}
memset(s, 0, sizeof(struct es1371_state));
- init_waitqueue(&s->dma_adc.wait);
- init_waitqueue(&s->dma_dac1.wait);
- init_waitqueue(&s->dma_dac2.wait);
- init_waitqueue(&s->open_wait);
- init_waitqueue(&s->midi.iwait);
- init_waitqueue(&s->midi.owait);
- s->open_sem = MUTEX;
+ init_waitqueue_head(&s->dma_adc.wait);
+ init_waitqueue_head(&s->dma_dac1.wait);
+ init_waitqueue_head(&s->dma_dac2.wait);
+ init_waitqueue_head(&s->open_wait);
+ init_waitqueue_head(&s->midi.iwait);
+ init_waitqueue_head(&s->midi.owait);
+ init_MUTEX(&s->open_sem);
s->magic = ES1371_MAGIC;
s->io = pcidev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
s->irq = pcidev->irq;
diff --git a/drivers/sound/gus_wave.c b/drivers/sound/gus_wave.c
index b0eacde38..0dddaacaa 100644
--- a/drivers/sound/gus_wave.c
+++ b/drivers/sound/gus_wave.c
@@ -118,7 +118,7 @@ static int gus_audio_bits;
static int gus_audio_bsize;
static char bounce_buf[8 * 1024]; /* Must match value set to max_fragment */
-static struct wait_queue *dram_sleeper = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(dram_sleeper);
/*
* Variables and buffers for PCM output
@@ -1663,7 +1663,7 @@ static int guswave_open(int dev, int mode)
gus_no_dma = 0;
}
- init_waitqueue(&dram_sleeper);
+ init_waitqueue_head(&dram_sleeper);
gus_busy = 1;
active_device = GUS_DEV_WAVE;
diff --git a/drivers/sound/hex2hex.c b/drivers/sound/hex2hex.c
index 8f6cd11b1..5460faae9 100644
--- a/drivers/sound/hex2hex.c
+++ b/drivers/sound/hex2hex.c
@@ -5,6 +5,7 @@
*/
#include <stdio.h>
+#include <string.h>
#include <stdlib.h>
#define ABANDON(why) { fprintf(stderr, "%s\n", why); exit(1); }
diff --git a/drivers/sound/lowlevel/awe_compat.h b/drivers/sound/lowlevel/awe_compat.h
index 9f9c57039..6ced8d65d 100644
--- a/drivers/sound/lowlevel/awe_compat.h
+++ b/drivers/sound/lowlevel/awe_compat.h
@@ -245,7 +245,7 @@ PERMANENT_MALLOC(buffer, char*, size, _mem_start); index = (nums);\
#endif /* AWE_MODULE_SUPPORT */
#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,0)
-inline static void interruptible_sleep_on_timeout(struct wait_queue **q, unsigned long timeout)
+inline static void interruptible_sleep_on_timeout(wait_queue_head_t *q, unsigned long timeout)
{
current->timeout = jiffies + timeout;
interruptible_sleep_on(q);
diff --git a/drivers/sound/lowlevel/awe_wave.c b/drivers/sound/lowlevel/awe_wave.c
index 8fd5431e6..8608e179e 100644
--- a/drivers/sound/lowlevel/awe_wave.c
+++ b/drivers/sound/lowlevel/awe_wave.c
@@ -979,10 +979,10 @@ awe_wait(unsigned short delay)
}
#else
-static struct wait_queue *awe_sleeper = NULL;
static void awe_wait(unsigned short delay)
{
- interruptible_sleep_on_timeout(&awe_sleeper, (HZ * (unsigned long)delay + 44099) / 44100);
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout((HZ*(unsigned long)delay + 44099)/44100);
}
#endif /* wait by loop */
diff --git a/drivers/sound/midibuf.c b/drivers/sound/midibuf.c
index b1c9763e5..426821753 100644
--- a/drivers/sound/midibuf.c
+++ b/drivers/sound/midibuf.c
@@ -29,8 +29,8 @@
#define MAX_QUEUE_SIZE 4000
-static struct wait_queue *midi_sleeper[MAX_MIDI_DEV] = {NULL};
-static struct wait_queue *input_sleeper[MAX_MIDI_DEV] = {NULL};
+static wait_queue_head_t midi_sleeper[MAX_MIDI_DEV];
+static wait_queue_head_t input_sleeper[MAX_MIDI_DEV];
struct midi_buf
{
@@ -202,8 +202,8 @@ int MIDIbuf_open(int dev, struct file *file)
midi_out_buf[dev]->len = midi_out_buf[dev]->head = midi_out_buf[dev]->tail = 0;
open_devs++;
- init_waitqueue(&midi_sleeper[dev]);
- init_waitqueue(&input_sleeper[dev]);
+ init_waitqueue_head(&midi_sleeper[dev]);
+ init_waitqueue_head(&input_sleeper[dev]);
if (open_devs < 2) /* This was first open */
{
diff --git a/drivers/sound/msnd.h b/drivers/sound/msnd.h
index ae7a952ad..1379563f2 100644
--- a/drivers/sound/msnd.h
+++ b/drivers/sound/msnd.h
@@ -231,8 +231,9 @@ typedef struct multisound_dev {
#define F_EXT_MIDI_INUSE 9
#define F_INT_MIDI_INUSE 10
#define F_DISABLE_WRITE_NDELAY 11
- struct wait_queue *writeblock, *readblock;
- struct wait_queue *writeflush;
+ wait_queue_head_t writeblock;
+ wait_queue_head_t readblock;
+ wait_queue_head_t writeflush;
#ifndef LINUX20
spinlock_t lock;
#endif
diff --git a/drivers/sound/msnd_pinnacle.c b/drivers/sound/msnd_pinnacle.c
index 7bf7364ab..05845cf96 100644
--- a/drivers/sound/msnd_pinnacle.c
+++ b/drivers/sound/msnd_pinnacle.c
@@ -1913,9 +1913,9 @@ __initfunc(int msnd_pinnacle_init(void))
if (digital)
set_bit(F_HAVEDIGITAL, &dev.flags);
#endif
- init_waitqueue(&dev.writeblock);
- init_waitqueue(&dev.readblock);
- init_waitqueue(&dev.writeflush);
+ init_waitqueue_head(&dev.writeblock);
+ init_waitqueue_head(&dev.readblock);
+ init_waitqueue_head(&dev.writeflush);
msnd_fifo_init(&dev.DAPF);
msnd_fifo_init(&dev.DARF);
#ifndef LINUX20
diff --git a/drivers/sound/sb_common.c b/drivers/sound/sb_common.c
index d162e470d..e55696f36 100644
--- a/drivers/sound/sb_common.c
+++ b/drivers/sound/sb_common.c
@@ -742,10 +742,7 @@ int sb_dsp_init(struct address_info *hw_config)
hw_config->name = "Sound Blaster Pro (8 BIT ONLY)";
break;
case MDL_ESS:
- if (!ess_dsp_init(devc, hw_config)) {
- release_region (hw_config->io_base, 16);
- return 0;
- }
+ ess_dsp_init(devc, hw_config);
break;
}
break;
@@ -887,6 +884,9 @@ void sb_dsp_unload(struct address_info *hw_config, int sbmpu)
if (devc && devc->base == hw_config->io_base)
{
+ if ((devc->model & MDL_ESS) && devc->pcibase)
+ release_region(devc->pcibase, 8);
+
release_region(devc->base, 16);
if (!(devc->caps & SB_NO_AUDIO))
@@ -1190,7 +1190,16 @@ static int init_Jazz16_midi(sb_devc * devc, struct address_info *hw_config)
void attach_sbmpu(struct address_info *hw_config)
{
-#if defined(CONFIG_MIDI) && defined(CONFIG_UART401)
+ if (last_sb->model == MDL_ESS) {
+#if defined(CONFIG_SOUND_MPU401)
+ attach_mpu401(hw_config);
+ if (last_sb->irq == -hw_config->irq) {
+ last_sb->midi_irq_cookie=(void *)hw_config->slots[1];
+ }
+#endif
+ return;
+ }
+#if defined(CONFIG_UART401)
attach_uart401(hw_config);
last_sb->midi_irq_cookie=midi_devs[hw_config->slots[4]]->devc;
#endif
@@ -1198,7 +1207,6 @@ void attach_sbmpu(struct address_info *hw_config)
int probe_sbmpu(struct address_info *hw_config)
{
-#if defined(CONFIG_MIDI) && defined(CONFIG_UART401)
sb_devc *devc = last_devc;
if (last_devc == NULL)
@@ -1209,6 +1217,23 @@ int probe_sbmpu(struct address_info *hw_config)
if (hw_config->io_base <= 0)
return 0;
+#if defined(CONFIG_SOUND_MPU401)
+ if (devc->model == MDL_ESS)
+ {
+ if (check_region(hw_config->io_base, 2))
+ {
+ printk(KERN_ERR "sbmpu: I/O port conflict (%x)\n", hw_config->io_base);
+ return 0;
+ }
+ if (!ess_midi_init(devc, hw_config))
+ return 0;
+ hw_config->name = "ESS1xxx MPU";
+ devc->midi_irq_cookie = -1;
+ return probe_mpu401(hw_config);
+ }
+#endif
+
+#if defined(CONFIG_UART401)
if (check_region(hw_config->io_base, 4))
{
printk(KERN_ERR "sbmpu: I/O port conflict (%x)\n", hw_config->io_base);
@@ -1228,14 +1253,6 @@ int probe_sbmpu(struct address_info *hw_config)
sb16_set_mpu_port(devc, hw_config);
break;
- case MDL_ESS:
- if (hw_config->irq < 3 || hw_config->irq == devc->irq)
- hw_config->irq = -devc->irq;
- if (!ess_midi_init(devc, hw_config))
- return 0;
- hw_config->name = "ESS ES1688";
- break;
-
case MDL_JAZZ:
if (hw_config->irq < 3 || hw_config->irq == devc->irq)
hw_config->irq = -devc->irq;
@@ -1258,7 +1275,13 @@ int probe_sbmpu(struct address_info *hw_config)
void unload_sbmpu(struct address_info *hw_config)
{
-#if defined(CONFIG_MIDI) && defined(CONFIG_UART401)
+#if defined(CONFIG_SOUND_MPU401)
+ if (!strcmp (hw_config->name, "ESS1xxx MPU")) {
+ unload_mpu401(hw_config);
+ return;
+ }
+#endif
+#if defined(CONFIG_UART401)
unload_uart401(hw_config);
#endif
}
diff --git a/drivers/sound/sb_ess.c b/drivers/sound/sb_ess.c
index 635be8a11..c6eb5c8d5 100644
--- a/drivers/sound/sb_ess.c
+++ b/drivers/sound/sb_ess.c
@@ -40,6 +40,10 @@
* recording problems for high samplerates. I
* fixed this by removing ess_calc_best_speed ()
* and just doing what the documentation says.
+ *Javier Achirica(May 15 1999): Major cleanup, MPU IRQ sharing, hardware
+ * volume support, PNP chip configuration,
+ * full duplex in most cards, sample rate fine
+ * tuning.
*
* This files contains ESS chip specifics. It's based on the existing ESS
* handling as it resided in sb_common.c, sb_mixer.c and sb_audio.c. This
@@ -192,12 +196,27 @@
int esstype = ESSTYPE_LIKE20; /* module parameter in sb_card.c */
+#define SUBMDL_ES688 0x00 /* Subtype ES688 for specific handling */
+#define SUBMDL_ES1688 0x08 /* Subtype ES1688 for specific handling */
#define SUBMDL_ES1788 0x10 /* Subtype ES1788 for specific handling */
#define SUBMDL_ES1868 0x11 /* Subtype ES1868 for specific handling */
#define SUBMDL_ES1869 0x12 /* Subtype ES1869 for specific handling */
#define SUBMDL_ES1878 0x13 /* Subtype ES1878 for specific handling */
-#define SUBMDL_ES1887 0x14 /* Subtype ES1887 for specific handling */
-#define SUBMDL_ES1888 0x15 /* Subtype ES1888 for specific handling */
+#define SUBMDL_ES1879 0x14 /* Subtype ES1879 for specific handling */
+#define SUBMDL_ES1887 0x15 /* Subtype ES1887 for specific handling */
+#define SUBMDL_ES1888 0x16 /* Subtype ES1888 for specific handling */
+
+ /* Recording mixer, stereo full duplex */
+#define ESSCAP_NEW 0x00000100
+ /* ISA PnP configuration */
+#define ESSCAP_PNP 0x00000200
+ /* Full duplex, 6-bit volume, hardware volume controls */
+#define ESSCAP_ES18 0x00000400
+ /* New interrupt handling system (ESS 1887) */
+#define ESSCAP_IRQ 0x00000800
+
+#define ESSFMT_16 0x00000001
+#define ESSFMT_SIGNED 0x00000004
#ifdef FKS_LOGGING
static void ess_show_mixerregs (sb_devc *devc);
@@ -213,52 +232,6 @@ static void ess_chgmixer
* *
****************************************************************************/
-struct ess_command {short cmd; short data;};
-
-/*
- * Commands for initializing Audio 1 for input (record)
- */
-static struct ess_command ess_i08m[] = /* input 8 bit mono */
- { {0xb7, 0x51}, {0xb7, 0xd0}, {-1, 0} };
-static struct ess_command ess_i16m[] = /* input 16 bit mono */
- { {0xb7, 0x71}, {0xb7, 0xf4}, {-1, 0} };
-static struct ess_command ess_i08s[] = /* input 8 bit stereo */
- { {0xb7, 0x51}, {0xb7, 0x98}, {-1, 0} };
-static struct ess_command ess_i16s[] = /* input 16 bit stereo */
- { {0xb7, 0x71}, {0xb7, 0xbc}, {-1, 0} };
-
-static struct ess_command *ess_inp_cmds[] =
- { ess_i08m, ess_i16m, ess_i08s, ess_i16s };
-
-
-/*
- * Commands for initializing Audio 1 for output (playback)
- */
-static struct ess_command ess_o08m[] = /* output 8 bit mono */
- { {0xb6, 0x80}, {0xb7, 0x51}, {0xb7, 0xd0}, {-1, 0} };
-static struct ess_command ess_o16m[] = /* output 16 bit mono */
- { {0xb6, 0x00}, {0xb7, 0x71}, {0xb7, 0xf4}, {-1, 0} };
-static struct ess_command ess_o08s[] = /* output 8 bit stereo */
- { {0xb6, 0x80}, {0xb7, 0x51}, {0xb7, 0x98}, {-1, 0} };
-static struct ess_command ess_o16s[] = /* output 16 bit stereo */
- { {0xb6, 0x00}, {0xb7, 0x71}, {0xb7, 0xbc}, {-1, 0} };
-
-static struct ess_command *ess_out_cmds[] =
- { ess_o08m, ess_o16m, ess_o08s, ess_o16s };
-
-static void ess_exec_commands
- (sb_devc *devc, struct ess_command *cmdtab[])
-{
- struct ess_command *cmd;
-
- cmd = cmdtab [ ((devc->channels != 1) << 1) + (devc->bits != AFMT_U8) ];
-
- while (cmd->cmd != -1) {
- ess_write (devc, cmd->cmd, cmd->data);
- cmd++;
- }
-}
-
static void ess_change
(sb_devc *devc, unsigned int reg, unsigned int mask, unsigned int val)
{
@@ -298,56 +271,22 @@ static void ess_set_input_parms
devc->irq_mode = IMODE_INPUT;
}
-static int ess_calc_div (int clock, int revert, int *speedp, int *diffp)
+static int ess_calc_div (int clock, int *speedp, int *diffp)
{
int divider;
int speed, diff;
- int retval;
speed = *speedp;
divider = (clock + speed / 2) / speed;
- retval = revert - divider;
- if (retval > revert - 1) {
- retval = revert - 1;
- divider = revert - retval;
+ if (divider > 127) {
+ divider = 127;
}
- /* This line is suggested. Must be wrong I think
- *speedp = (clock + divider / 2) / divider;
- So I chose the next one */
-
*speedp = clock / divider;
diff = speed - *speedp;
- if (diff < 0) diff =-diff;
- *diffp = diff;
-
- return retval;
-}
-
-#ifdef OBSOLETE
-static int ess_calc_best_speed
- (int clock1, int rev1, int clock2, int rev2, int *divp, int *speedp)
-{
- int speed1 = *speedp, speed2 = *speedp;
- int div1, div2;
- int diff1, diff2;
- int retval;
-
- div1 = ess_calc_div (clock1, rev1, &speed1, &diff1);
- div2 = ess_calc_div (clock2, rev2, &speed2, &diff2);
+ *diffp = diff < 0 ? -diff : diff;
- if (diff1 < diff2) {
- *divp = div1;
- *speedp = speed1;
- retval = 1;
- } else {
- *divp = div2;
- *speedp = speed2;
- retval = 2;
- }
-
- return retval;
+ return 128 - divider;
}
-#endif
/*
* Depending on the audiochannel ESS devices can
@@ -359,21 +298,30 @@ static int ess_calc_best_speed
*/
static void ess_common_speed (sb_devc *devc, int *speedp, int *divp)
{
- int diff = 0, div;
+ int speed1 = *speedp, speed2 = *speedp;
+ int div1, div2;
+ int diff1, diff2;
- if (devc->duplex) {
- /*
- * The 0x80 is important for the first audio channel
- */
- div = 0x80 | ess_calc_div (795500, 128, speedp, &diff);
+ if (devc->caps & ESSCAP_NEW) {
+ div1 = 0x000 | ess_calc_div (793800, &speed1, &diff1);
+ div2 = 0x080 | ess_calc_div (768000, &speed2, &diff2);
} else {
if (*speedp > 22000) {
- div = 0x80 | ess_calc_div (795500, 256, speedp, &diff);
+ div1 = 0x080 | ess_calc_div (795444, &speed1, &diff1);
+ div2 = 0x180 | ess_calc_div (793800, &speed2, &diff2);
} else {
- div = 0x00 | ess_calc_div (397700, 128, speedp, &diff);
+ div1 = 0x000 | ess_calc_div (397722, &speed1, &diff1);
+ div2 = 0x100 | ess_calc_div (396900, &speed2, &diff2);
}
}
- *divp = div;
+
+ if (diff1 < diff2) {
+ *divp = div1;
+ *speedp = speed1;
+ } else {
+ *divp = div2;
+ *speedp = speed2;
+ }
}
static void ess_speed (sb_devc *devc, int audionum)
@@ -392,21 +340,13 @@ printk (KERN_INFO "FKS: ess_speed (%d) b speed = %d, div=%x\n", audionum, devc->
div2 = 256 - 7160000 / (speed * 82);
- if (!devc->duplex) audionum = 1;
-
- if (audionum == 1) {
- /* Change behaviour of register A1 *
- sb_chg_mixer(devc, 0x71, 0x20, 0x20)
- * For ES1869 only??? */
- ess_write (devc, 0xa1, div);
- ess_write (devc, 0xa2, div2);
- } else {
+ if ((devc->caps & ESSCAP_NEW) && audionum != 1) {
ess_setmixer (devc, 0x70, div);
- /*
- * FKS: fascinating: 0x72 doesn't seem to work.
- */
- ess_write (devc, 0xa2, div2);
ess_setmixer (devc, 0x72, div2);
+ } else {
+ ess_change (devc, 0xba, 0x40, (div & 0x100) ? 0x40 : 0x00);
+ ess_write (devc, 0xa1, div & 0xff);
+ ess_write (devc, 0xa2, div2);
}
}
@@ -414,77 +354,14 @@ static int ess_audio_prepare_for_input(int dev, int bsize, int bcount)
{
sb_devc *devc = audio_devs[dev]->devc;
- ess_speed(devc, 1);
-
- sb_dsp_command(devc, DSP_CMD_SPKOFF);
-
ess_write (devc, 0xb8, 0x0e); /* Auto init DMA mode */
- ess_change (devc, 0xa8, 0x03, 3 - devc->channels); /* Mono/stereo */
- ess_write (devc, 0xb9, 2); /* Demand mode (4 bytes/DMA request) */
-
- ess_exec_commands (devc, ess_inp_cmds);
+ ess_change (devc, 0xa8, 0x0b, 3 - devc->channels); /* Mono/stereo */
- ess_change (devc, 0xb1, 0xf0, 0x50);
- ess_change (devc, 0xb2, 0xf0, 0x50);
-
- devc->trigger_bits = 0;
- return 0;
-}
-
-static int ess_audio_prepare_for_output_audio1 (int dev, int bsize, int bcount)
-{
- sb_devc *devc = audio_devs[dev]->devc;
-
- sb_dsp_reset(devc);
ess_speed(devc, 1);
- ess_write (devc, 0xb8, 4); /* Auto init DMA mode */
- ess_change (devc, 0xa8, 0x03, 3 - devc->channels); /* Mono/stereo */
- ess_write (devc, 0xb9, 2); /* Demand mode (4 bytes/request) */
-
- ess_exec_commands (devc, ess_out_cmds);
-
- ess_change (devc, 0xb1, 0xf0, 0x50); /* Enable DMA */
- ess_change (devc, 0xb2, 0xf0, 0x50); /* Enable IRQ */
-
- sb_dsp_command(devc, DSP_CMD_SPKON); /* There be sound! */
- devc->trigger_bits = 0;
- return 0;
-}
-
-static int ess_audio_prepare_for_output_audio2 (int dev, int bsize, int bcount)
-{
- sb_devc *devc = audio_devs[dev]->devc;
- unsigned char bits;
-
-/* FKS: qqq
- sb_dsp_reset(devc);
-*/
-
- /*
- * Auto-Initialize:
- * DMA mode + demand mode (8 bytes/request, yes I want it all!)
- * But leave 16-bit DMA bit untouched!
- */
- ess_chgmixer (devc, 0x78, 0xd0, 0xd0);
-
- ess_speed(devc, 2);
-
- /* bits 4:3 on ES1887 represent recording source. Keep them! */
- bits = ess_getmixer (devc, 0x7a) & 0x18;
-
- /* Set stereo/mono */
- if (devc->channels != 1) bits |= 0x02;
-
- /* Init DACs; UNSIGNED mode for 8 bit; SIGNED mode for 16 bit */
- if (devc->bits != AFMT_U8) bits |= 0x05; /* 16 bit */
-
- /* Enable DMA, IRQ will be shared (hopefully)*/
- bits |= 0x60;
-
- ess_setmixer (devc, 0x7a, bits);
-
- ess_mixer_reload (devc, SOUND_MIXER_PCM); /* There be sound! */
+ ess_write (devc, 0xb7, (devc->bits & ESSFMT_SIGNED) ? 0x71 : 0x51);
+ ess_write (devc, 0xb7, 0x90 | ((devc->bits & ESSFMT_SIGNED) ? 0x20 : 0) |
+ ((devc->bits & ESSFMT_16) ? 4 : 0) | ((devc->channels > 1) ? 8 : 0x40));
devc->trigger_bits = 0;
return 0;
@@ -500,144 +377,79 @@ printk(KERN_INFO "ess_audio_prepare_for_output: dma_out=%d,dma_in=%d\n"
#endif
if (devc->duplex) {
- return ess_audio_prepare_for_output_audio2 (dev, bsize, bcount);
- } else {
- return ess_audio_prepare_for_output_audio1 (dev, bsize, bcount);
- }
-}
+ ess_speed(devc, 2);
-static void ess_audio_halt_xfer(int dev)
-{
- unsigned long flags;
- sb_devc *devc = audio_devs[dev]->devc;
-
- save_flags(flags);
- cli();
- sb_dsp_reset(devc);
- restore_flags(flags);
-
- /*
- * Audio 2 may still be operational! Creates awful sounds!
- */
- if (devc->duplex) ess_chgmixer(devc, 0x78, 0x03, 0x00);
-}
-
-static void ess_audio_start_input
- (int dev, unsigned long buf, int nr_bytes, int intrflag)
-{
- int count = nr_bytes;
- sb_devc *devc = audio_devs[dev]->devc;
- short c = -nr_bytes;
-
- /*
- * Start a DMA input to the buffer pointed by dmaqtail
- */
-
- if (audio_devs[dev]->dmap_in->dma > 3) count >>= 1;
- count--;
-
- devc->irq_mode = IMODE_INPUT;
-
- ess_write (devc, 0xa4, (unsigned char) ((unsigned short) c & 0xff));
- ess_write (devc, 0xa5, (unsigned char) (((unsigned short) c >> 8) & 0xff));
-
- ess_change (devc, 0xb8, 0x0f, 0x0f); /* Go */
- devc->intr_active = 1;
-}
-
-static void ess_audio_output_block_audio1
- (int dev, unsigned long buf, int nr_bytes, int intrflag)
-{
- int count = nr_bytes;
- sb_devc *devc = audio_devs[dev]->devc;
- short c = -nr_bytes;
+ ess_chgmixer (devc, 0x7a, 0x07, ((devc->bits & ESSFMT_SIGNED) ? 4 : 0) |
+ ((devc->bits & ESSFMT_16) ? 1 : 0) | ((devc->channels > 1) ? 2 : 0));
- if (audio_devs[dev]->dmap_out->dma > 3)
- count >>= 1;
- count--;
+ if (devc->caps & ESSCAP_NEW)
+ ess_mixer_reload (devc, SOUND_MIXER_PCM); /* There be sound! */
+ else
+ sb_dsp_command(devc, DSP_CMD_SPKON); /* There be sound! */
+ } else {
+ ess_write (devc, 0xb8, 4); /* Auto init DMA mode */
+ ess_change (devc, 0xa8, 0x03, 3 - devc->channels); /* Mono/stereo */
- devc->irq_mode = IMODE_OUTPUT;
+ ess_speed(devc, 1);
- ess_write (devc, 0xa4, (unsigned char) ((unsigned short) c & 0xff));
- ess_write (devc, 0xa5, (unsigned char) (((unsigned short) c >> 8) & 0xff));
+ ess_write (devc, 0xb6, (devc->bits & ESSFMT_SIGNED) ? 0 : 0x80);
+ ess_write (devc, 0xb7, (devc->bits & ESSFMT_SIGNED) ? 0x71 : 0x51);
+ ess_write (devc, 0xb7, 0x90 | ((devc->bits & ESSFMT_SIGNED) ? 0x20 : 0) |
+ ((devc->bits & ESSFMT_16) ? 4 : 0) | ((devc->channels > 1) ? 8 : 0x40));
- ess_change (devc, 0xb8, 0x05, 0x05); /* Go */
- devc->intr_active = 1;
+ sb_dsp_command(devc, DSP_CMD_SPKON); /* There be sound! */
+ }
+ devc->trigger_bits = 0;
+ return 0;
}
-static void ess_audio_output_block_audio2
- (int dev, unsigned long buf, int nr_bytes, int intrflag)
+static void ess_audio_halt_xfer(int dev)
{
- int count = nr_bytes;
sb_devc *devc = audio_devs[dev]->devc;
- short c = -nr_bytes;
- if (audio_devs[dev]->dmap_out->dma > 3) count >>= 1;
- count--;
+ sb_dsp_command (devc, DSP_CMD_SPKOFF);
- ess_setmixer (devc, 0x74, (unsigned char) ((unsigned short) c & 0xff));
- ess_setmixer (devc, 0x76, (unsigned char) (((unsigned short) c >> 8) & 0xff));
- ess_chgmixer (devc, 0x78, 0x03, 0x03); /* Go */
-
- devc->irq_mode_16 = IMODE_OUTPUT;
- devc->intr_active_16 = 1;
-}
+ if (devc->caps & ESSCAP_NEW) {
+ ess_setmixer (devc, 0x7c, 0);
+ }
-static void ess_audio_output_block
- (int dev, unsigned long buf, int nr_bytes, int intrflag)
-{
- sb_devc *devc = audio_devs[dev]->devc;
+ ess_change (devc, 0xb8, 0x0f, 0x00); /* Stop */
- if (devc->duplex) {
- ess_audio_output_block_audio2 (dev, buf, nr_bytes, intrflag);
- } else {
- ess_audio_output_block_audio1 (dev, buf, nr_bytes, intrflag);
+ if (devc->duplex) { /* Audio 2 may still be operational! */
+ ess_chgmixer (devc, 0x78, 0x03, 0x00);
}
}
-/*
- * FKS: the if-statements for both bits and bits_16 are quite alike.
- * Combine this...
- */
static void ess_audio_trigger(int dev, int bits)
{
sb_devc *devc = audio_devs[dev]->devc;
- int bits_16 = bits & devc->irq_mode_16;
+ int bits_16 = bits & devc->irq_mode_16 & IMODE_OUTPUT;
bits &= devc->irq_mode;
if (!bits && !bits_16) {
- /* FKS oh oh.... wrong?? for dma 16? */
- sb_dsp_command(devc, 0xd0); /* Halt DMA */
+ sb_dsp_command (devc, 0xd0); /* Halt DMA */
+ ess_chgmixer (devc, 0x78, 0x04, 0x00); /* Halt DMA 2 */
}
if (bits) {
- switch (devc->irq_mode)
- {
- case IMODE_INPUT:
- ess_audio_start_input(dev, devc->trg_buf, devc->trg_bytes,
- devc->trg_intrflag);
- break;
+ short c = -devc->trg_bytes;
- case IMODE_OUTPUT:
- ess_audio_output_block(dev, devc->trg_buf, devc->trg_bytes,
- devc->trg_intrflag);
- break;
- }
+ ess_write (devc, 0xa4, (unsigned char)((unsigned short) c & 0xff));
+ ess_write (devc, 0xa5, (unsigned char)((unsigned short) c >> 8));
+ ess_change (devc, 0xb8, 0x0f, (devc->irq_mode==IMODE_INPUT)?0x0f:0x05);
+
+ devc->intr_active = 1;
}
if (bits_16) {
- switch (devc->irq_mode_16) {
- case IMODE_INPUT:
- ess_audio_start_input(dev, devc->trg_buf_16, devc->trg_bytes_16,
- devc->trg_intrflag_16);
- break;
+ short c = -devc->trg_bytes_16;
- case IMODE_OUTPUT:
- ess_audio_output_block(dev, devc->trg_buf_16, devc->trg_bytes_16,
- devc->trg_intrflag_16);
- break;
- }
+ ess_setmixer (devc, 0x74, (unsigned char)((unsigned short) c & 0xff));
+ ess_setmixer (devc, 0x76, (unsigned char)((unsigned short) c >> 8));
+ ess_chgmixer (devc, 0x78, 0x03, 0x03); /* Go */
+
+ devc->intr_active_16 = 1;
}
devc->trigger_bits = bits | bits_16;
@@ -649,8 +461,8 @@ static int ess_audio_set_speed(int dev, int speed)
int minspeed, maxspeed, dummydiv;
if (speed > 0) {
- minspeed = (devc->duplex ? 6215 : 5000 );
- maxspeed = (devc->duplex ? 44100 : 48000);
+ minspeed = (devc->caps & ESSCAP_NEW) ? 6047 : 3125;
+ maxspeed = 48000;
if (speed < minspeed) speed = minspeed;
if (speed > maxspeed) speed = maxspeed;
@@ -661,38 +473,46 @@ static int ess_audio_set_speed(int dev, int speed)
return devc->speed;
}
-/*
- * FKS: This is a one-on-one copy of sb1_audio_set_bits
- */
static unsigned int ess_audio_set_bits(int dev, unsigned int bits)
{
sb_devc *devc = audio_devs[dev]->devc;
- if (bits != 0) {
- if (bits == AFMT_U8 || bits == AFMT_S16_LE) {
- devc->bits = bits;
- } else {
- devc->bits = AFMT_U8;
- }
+ switch (bits) {
+ case 0:
+ break;
+ case AFMT_S16_LE:
+ devc->bits = ESSFMT_16 | ESSFMT_SIGNED;
+ break;
+ case AFMT_U16_LE:
+ devc->bits = ESSFMT_16;
+ break;
+ case AFMT_S8:
+ devc->bits = ESSFMT_SIGNED;
+ break;
+ default:
+ devc->bits = 0;
+ break;
}
return devc->bits;
}
-/*
- * FKS: This is a one-on-one copy of sbpro_audio_set_channels
- * (*) Modified it!!
- */
static short ess_audio_set_channels(int dev, short channels)
{
sb_devc *devc = audio_devs[dev]->devc;
- if (channels == 1 || channels == 2) devc->channels = channels;
+ if (devc->fullduplex && !(devc->caps & ESSCAP_NEW)) {
+ devc->channels = 1;
+ } else {
+ if (channels == 1 || channels == 2) {
+ devc->channels = channels;
+ }
+ }
return devc->channels;
}
-static struct audio_driver ess_audio_driver = /* ESS ES688/1688 */
+static struct audio_driver ess_audio_driver = /* ESS ES688/1688/18xx */
{
sb_audio_open,
sb_audio_close,
@@ -719,7 +539,7 @@ struct audio_driver *ess_audio_init
(sb_devc *devc, int *audio_flags, int *format_mask)
{
*audio_flags = DMA_AUTOMODE;
- *format_mask |= AFMT_S16_LE;
+ *format_mask |= AFMT_S16_LE | AFMT_U16_LE | AFMT_S8;
if (devc->duplex) {
int tmp_dma;
@@ -742,10 +562,8 @@ struct audio_driver *ess_audio_init
* ESS common *
* *
****************************************************************************/
-static void ess_handle_channel
- (char *channel, int dev, int intr_active, unsigned char flag, int irq_mode)
+static void ess_handle_channel (int dev, int irq_mode)
{
- if (!intr_active || !flag) return;
#ifdef FKS_REG_LOGGING
printk(KERN_INFO "FKS: ess_handle_channel %s irq_mode=%d\n", channel, irq_mode);
#endif
@@ -767,48 +585,77 @@ printk(KERN_INFO "FKS: ess_handle_channel %s irq_mode=%d\n", channel, irq_mode);
}
/*
- * FKS: TODO!!! Finish this!
- *
- * I think midi stuff uses uart401, without interrupts.
- * So IMODE_MIDI isn't a value for devc->irq_mode.
+ * In the ESS 1888 model, how do we found out if the MPU interrupted ???
*/
void ess_intr (sb_devc *devc)
{
int status;
unsigned char src;
- if (devc->submodel == SUBMDL_ES1887) {
+ if (devc->caps & ESSCAP_PNP) {
+ outb (devc->pcibase + 7, 0); /* Mask IRQs */
+ src = inb (devc->pcibase + 6) & 0x0f;
+ } else if (devc->caps & ESSCAP_IRQ) {
src = ess_getmixer (devc, 0x7f) >> 4;
} else {
- src = 0xff;
+ src = inb (DSP_STATUS) & 0x01;
+ if (devc->duplex && (ess_getmixer (devc, 0x7a) & 0x80)) {
+ src |= 0x02;
+ }
+ if ((devc->caps & ESSCAP_ES18) && (ess_getmixer (devc, 0x64) & 0x10)) {
+ src |= 0x04;
+ }
+#if defined(CONFIG_MIDI) && defined(CONFIG_SOUND_MPU401)
+ /*
+ * This should work if dev_conf wasn't local to mpu401.c
+ */
+#if 0
+ if ((int)devc->midi_irq_cookie >= 0 &&
+ !(inb(dev_conf[(int)devc->midi_irq_cookie].base + 1) & 0x80)) {
+ src |= 0x08;
+ }
+#endif
+#endif
}
#ifdef FKS_REG_LOGGING
printk(KERN_INFO "FKS: sbintr src=%x\n",(int)src);
#endif
- ess_handle_channel
- ( "Audio 1"
- , devc->dev, devc->intr_active , src & 0x01, devc->irq_mode );
- ess_handle_channel
- ( "Audio 2"
- , devc->dev, devc->intr_active_16, src & 0x02, devc->irq_mode_16);
- /*
- * Acknowledge interrupts
- */
- if (devc->submodel == SUBMDL_ES1887 && (src & 0x02)) {
- ess_chgmixer (devc, 0x7a, 0x80, 0x00);
+ if (src & 0x01) {
+ status = inb(DSP_DATA_AVAIL); /* Acknowledge interrupt */
+ if (devc->intr_active)
+ ess_handle_channel (devc->dev, devc->irq_mode );
}
- if (src & 0x01) {
- status = inb(DSP_DATA_AVAIL);
+ if (src & 0x02) {
+ ess_chgmixer (devc, 0x7a, 0x80, 0x00); /* Acknowledge interrupt */
+ if (devc->intr_active_16)
+ ess_handle_channel (devc->dev, devc->irq_mode_16);
}
-}
-static void ess_extended (sb_devc * devc)
-{
- /* Enable extended mode */
+ if (src & 0x04) {
+ int left, right;
+
+ ess_setmixer (devc, 0x66, 0x00); /* Hardware volume IRQ ack */
+
+ left = ess_getmixer (devc, 0x60);
+ right = ess_getmixer (devc, 0x62);
- sb_dsp_command(devc, 0xc6);
+ left = (left & 0x40) ? 0 : ((left * 100 + 31)/ 63); /* Mute or scale */
+ right = (right & 0x40) ? 0 : ((right * 100 + 31)/ 63);
+
+ devc->levels[SOUND_MIXER_VOLUME] = left | (right << 8);
+ }
+
+#if defined(CONFIG_MIDI) && defined(CONFIG_SOUND_MPU401)
+ if ((int)devc->midi_irq_cookie >= 0 && (src & 0x08)) {
+ mpuintr (devc->irq, devc->midi_irq_cookie, NULL);
+ }
+#endif
+
+ if (devc->caps & ESSCAP_PNP) {
+ outb (devc->pcibase + 7, 0xff); /* Unmask IRQs */
+ }
}
static int ess_write (sb_devc * devc, unsigned char reg, unsigned char data)
@@ -838,7 +685,7 @@ static int ess_read (sb_devc * devc, unsigned char reg)
int ess_dsp_reset(sb_devc * devc)
{
- int loopc;
+ int loopc, val;
#ifdef FKS_REG_LOGGING
printk(KERN_INFO "FKS: ess_dsp_reset 1\n");
@@ -859,77 +706,100 @@ ess_show_mixerregs (devc);
DDB(printk("sb: No response to RESET\n"));
return 0; /* Sorry */
}
- ess_extended (devc);
-
- DEB(printk("sb_dsp_reset() OK\n"));
-
-#ifdef FKS_LOGGING
-printk(KERN_INFO "FKS: dsp_reset 2\n");
-ess_show_mixerregs (devc);
-#endif
- return 1;
-}
+ sb_dsp_command(devc, 0xc6); /* Enable extended mode */
+ if (!(devc->caps & ESSCAP_PNP)) {
+ ess_setmixer (devc, 0x40, 0x03); /* Enable joystick and OPL3 */
-static int ess_irq_bits (int irq)
-{
- switch (irq) {
- case 2:
- case 9:
- return 0;
-
- case 5:
- return 1;
+ switch (devc->irq) {
+ case 2:
+ case 9:
+ val = 1;
+ break;
+ case 5:
+ val = 2;
+ break;
+ case 7:
+ val = 3;
+ break;
+ case 10:
+ val = 4;
+ break;
+ case 11:
+ val = 5;
+ break;
+ default:
+ val = 0;
+ } /* IRQ config */
+ ess_write (devc, 0xb1, 0xf0 | ((val && val != 5) ? val - 1 : 0));
- case 7:
- return 2;
+ if (devc->caps & ESSCAP_IRQ) {
+ ess_setmixer (devc, 0x7f, 0x01 | (val << 1)); /* IRQ config */
+ }
- case 10:
- return 3;
+ switch ((devc->duplex) ? devc->dma16 : devc->dma8) {
+ case 0:
+ val = 0x54;
+ break;
+ case 1:
+ val = 0x58;
+ break;
+ case 3:
+ val = 0x5c;
+ break;
+ default:
+ val = 0;
+ }
+ ess_write (devc, 0xb2, val); /* DMA1 config */
- default:
- printk(KERN_ERR "ESS1688: Invalid IRQ %d\n", irq);
- return -1;
+ if (devc->duplex) {
+ switch (devc->dma8) {
+ case 0:
+ val = 0x04;
+ break;
+ case 1:
+ val = 0x05;
+ break;
+ case 3:
+ val = 0x06;
+ break;
+ case 5:
+ val = 0x07;
+ break;
+ default:
+ val = 0;
+ }
+ ess_write (devc, 0x7d, val); /* DMA2 config */
+ }
}
-}
-
-/*
- * Set IRQ configuration register for all ESS models
- */
-static int ess_common_set_irq_hw (sb_devc * devc)
-{
- int irq_bits;
-
- if ((irq_bits = ess_irq_bits (devc->irq)) == -1) return 0;
-
- if (!ess_write (devc, 0xb1, 0x50 | (irq_bits << 2))) {
- printk(KERN_ERR "ES1688: Failed to write to IRQ config register\n");
- return 0;
+ ess_change (devc, 0xb1, 0xf0, 0x50); /* Enable IRQ 1 */
+ ess_change (devc, 0xb2, 0xf0, 0x50); /* Enable DMA 1 */
+ ess_write (devc, 0xb9, 2); /* Demand mode (4 bytes/DMA request) */
+ ess_setmixer (devc, 0x7a, 0x40); /* Enable IRQ 2 */
+ /* Auto-Initialize DMA mode + demand mode (8 bytes/request) */
+ if (devc->caps & ESSCAP_PNP) {
+ ess_setmixer (devc, 0x78, 0xd0);
+ ess_setmixer (devc, 0x64, 0x82); /* Enable HW volume interrupt */
+ } else {
+ ess_setmixer (devc, 0x78, (devc->dma8 > 4) ? 0xf0 : 0xd0);
+ ess_setmixer (devc, 0x64, 0x42); /* Enable HW volume interrupt */
}
- return 1;
-}
-/*
- * I wanna use modern ES1887 mixer irq handling. Funny is the
- * fact that my BIOS wants the same. But suppose someone's BIOS
- * doesn't do this!
- * This is independent of duplex. If there's a 1887 this will
- * prevent it from going into 1888 mode.
- */
-static void ess_es1887_set_irq_hw (sb_devc * devc)
-{
- int irq_bits;
-
- if ((irq_bits = ess_irq_bits (devc->irq)) == -1) return;
+ if (devc->caps & ESSCAP_NEW) {
+ ess_setmixer (devc, 0x71, 0x32); /* Change behaviour of register A1 */
+ ess_setmixer (devc, 0x1c, 0x05); /* Recording source is mixer */
+ } else {
+ ess_change (devc, 0xb7, 0x80, 0x80); /* Enable DMA FIFO */
+ }
- ess_chgmixer (devc, 0x7f, 0x0f, 0x01 | ((irq_bits + 1) << 1));
-}
+ DEB(printk("sb_dsp_reset() OK\n"));
-static int ess_set_irq_hw (sb_devc * devc)
-{
- if (devc->submodel == SUBMDL_ES1887) ess_es1887_set_irq_hw (devc);
+#ifdef FKS_LOGGING
+printk(KERN_INFO "FKS: dsp_reset 2\n");
+ess_show_mixerregs (devc);
+#endif
- return ess_common_set_irq_hw (devc);
+ return 1;
}
#ifdef FKS_TEST
@@ -955,7 +825,7 @@ printk (KERN_INFO "FKS: FKS_test %02x, %02x\n", (val1 & 0x0ff), (val2 & 0x0ff));
};
#endif
-static unsigned int ess_identify (sb_devc * devc)
+static unsigned int ess_identify (sb_devc * devc, int *control)
{
unsigned int val;
unsigned long flags;
@@ -969,8 +839,15 @@ static unsigned int ess_identify (sb_devc * devc)
udelay(20);
val |= inb(MIXER_DATA);
udelay(20);
+ *control = inb(MIXER_DATA) << 8;
+ udelay(20);
+ *control |= inb(MIXER_DATA);
+ udelay(20);
restore_flags(flags);
+ if (*control < 0 || *control > 0x3ff || check_region (*control, 8))
+ *control = 0;
+
return val;
}
@@ -997,7 +874,6 @@ static int ess_probe (sb_devc * devc, int reg, int xorval)
int ess_init(sb_devc * devc, struct address_info *hw_config)
{
- unsigned char cfg;
int ess_major = 0, ess_minor = 0;
int i;
static char name[100], modelname[10];
@@ -1005,6 +881,7 @@ int ess_init(sb_devc * devc, struct address_info *hw_config)
/*
* Try to detect ESS chips.
*/
+ devc->pcibase = 0;
sb_dsp_command(devc, 0xe7); /* Return identification */
@@ -1056,10 +933,10 @@ int ess_init(sb_devc * devc, struct address_info *hw_config)
case ESSTYPE_LIKE20:
break;
case 688:
- submodel = 0x00;
+ submodel = SUBMDL_ES688;
break;
case 1688:
- submodel = 0x08;
+ submodel = SUBMDL_ES1688;
break;
case 1868:
submodel = SUBMDL_ES1868;
@@ -1070,6 +947,12 @@ int ess_init(sb_devc * devc, struct address_info *hw_config)
case 1788:
submodel = SUBMDL_ES1788;
break;
+ case 1878:
+ submodel = SUBMDL_ES1878;
+ break;
+ case 1879:
+ submodel = SUBMDL_ES1879;
+ break;
case 1887:
submodel = SUBMDL_ES1887;
break;
@@ -1102,7 +985,7 @@ FKS_test (devc);
if (chip == NULL) {
int type;
- type = ess_identify (devc);
+ type = ess_identify (devc, &devc->pcibase);
switch (type) {
case 0x1868:
@@ -1117,6 +1000,10 @@ FKS_test (devc);
chip = "ES1878";
devc->submodel = SUBMDL_ES1878;
break;
+ case 0x1879:
+ chip = "ES1879";
+ devc->submodel = SUBMDL_ES1879;
+ break;
default:
if ((type & 0x00ff) != ((type >> 8) & 0x00ff)) {
printk ("ess_init: Unrecognized %04x\n", type);
@@ -1175,130 +1062,72 @@ FKS_test (devc);
strcpy(name, "Jazz16");
}
- hw_config->name = name;
- /* FKS: sb_dsp_reset to enable extended mode???? */
- sb_dsp_reset(devc); /* Turn on extended mode */
-
- /*
- * Enable joystick and OPL3
- */
- cfg = ess_getmixer (devc, 0x40);
- ess_setmixer (devc, 0x40, cfg | 0x03);
- if (devc->submodel >= 8) { /* ES1688 */
- devc->caps |= SB_NO_MIDI; /* ES1688 uses MPU401 MIDI mode */
+ switch (devc->submodel) {
+ case SUBMDL_ES1869:
+ case SUBMDL_ES1879:
+ devc->caps |= ESSCAP_NEW;
+ case SUBMDL_ES1868:
+ case SUBMDL_ES1878:
+ devc->caps |= ESSCAP_PNP | ESSCAP_ES18;
+ break;
+ case SUBMDL_ES1887:
+ devc->caps |= ESSCAP_IRQ;
+ case SUBMDL_ES1888:
+ devc->caps |= ESSCAP_NEW | ESSCAP_ES18;
}
- sb_dsp_reset (devc);
-
- /*
- * This is important! If it's not done, the IRQ probe in sb_dsp_init
- * may fail.
- */
- return ess_set_irq_hw (devc);
-}
-
-static int ess_set_dma_hw(sb_devc * devc)
-{
- unsigned char cfg, dma_bits = 0, dma16_bits;
- int dma;
-
-#ifdef FKS_LOGGING
-printk(KERN_INFO "ess_set_dma_hw: dma8=%d,dma16=%d,dup=%d\n"
-, devc->dma8, devc->dma16, devc->duplex);
-#endif
-
- /*
- * FKS: It seems as if this duplex flag isn't set yet. Check it.
- */
- dma = devc->dma8;
-
- if (dma > 3 || dma < 0 || dma == 2) {
- dma_bits = 0;
- printk(KERN_ERR "ESS1688: Invalid DMA8 %d\n", dma);
- return 0;
- } else {
- /* Extended mode DMA enable */
- cfg = 0x50;
-
- if (dma == 3) {
- dma_bits = 3;
- } else {
- dma_bits = dma + 1;
+ if (devc->caps & ESSCAP_PNP) {
+ if (!devc->pcibase) {
+ printk (KERN_ERR "ESS PnP chip without PnP registers. Ignored\n");
+ return 0;
}
+ request_region (devc->pcibase, 8, "ESS18xx ctrl");
+
+ outb (0x07, devc->pcibase); /* Selects logical device #1 */
+ outb (0x01, devc->pcibase + 1);
+ outb (0x28, devc->pcibase);
+ i = inb (devc->pcibase + 1) & 0x0f;
+ outb (0x28, devc->pcibase); /* Sets HW volume IRQ */
+ outb (devc->irq << 4 | i, devc->pcibase + 1);
+ outb (0x70, devc->pcibase); /* Sets IRQ 1 */
+ outb (devc->irq, devc->pcibase + 1);
+ outb (0x72, devc->pcibase); /* Sets IRQ 2 */
+ outb (devc->irq, devc->pcibase + 1);
+ outb (0x74, devc->pcibase); /* Sets DMA 1 */
+ outb (hw_config->dma, devc->pcibase + 1);
+ outb (0x75, devc->pcibase); /* Sets DMA 2 */
+ outb (hw_config->dma2 >= 0 ? hw_config->dma2 : 4, devc->pcibase + 1);
+ } else if (devc->pcibase) {
+ printk (KERN_INFO "Non-PnP ESS card with PnP registers at %04Xh, ignoring them.\n", devc->pcibase);
+ devc->pcibase = 0;
}
- if (!ess_write (devc, 0xb2, cfg | (dma_bits << 2))) {
- printk(KERN_ERR "ESS1688: Failed to write to DMA config register\n");
- return 0;
- }
+ devc->caps |= SB_NO_MIDI; /* ES1688 uses MPU401 MIDI mode */
- if (devc->duplex) {
- dma = devc->dma16;
- dma16_bits = 0;
+ hw_config->name = name;
+
+ sb_dsp_reset(devc); /* Turn on extended mode */
+
+ ess_setmixer (devc, 0x00, 0x00); /* Reset mixer registers */
- if (dma >= 0) {
- switch (dma) {
- case 0:
- dma_bits = 0x04;
- break;
- case 1:
- dma_bits = 0x05;
- break;
- case 3:
- dma_bits = 0x06;
- break;
- case 5:
- dma_bits = 0x07;
- dma16_bits = 0x20;
- break;
- default:
- printk(KERN_ERR "ESS1887: Invalid DMA16 %d\n", dma);
- return 0;
- };
- ess_chgmixer (devc, 0x78, 0x20, dma16_bits);
- ess_chgmixer (devc, 0x7d, 0x07, dma_bits);
- }
- }
return 1;
}
/*
* This one is called from sb_dsp_init.
- *
- * Return values:
- * 0: Failed
- * 1: Succeeded or doesn't apply (not SUBMDL_ES1887)
*/
int ess_dsp_init (sb_devc *devc, struct address_info *hw_config)
{
/*
- * This for ES1887 to run Full Duplex. Actually ES1888
- * is allowed to do so too. I have no idea yet if this
- * will work for ES1888 however.
- *
* For SB16 having both dma8 and dma16 means enable
- * Full Duplex. Let's try this for ES1887 too
- *
+ * Full Duplex. Let's try this too
*/
- if (devc->submodel == SUBMDL_ES1887) {
- if (hw_config->dma2 != -1) {
- devc->dma16 = hw_config->dma2;
- }
- /*
- * devc->duplex initialization is put here, cause
- * ess_set_dma_hw needs it.
- */
- if (devc->dma8 != devc->dma16 && devc->dma16 != -1) {
+ if ((devc->caps & ESSCAP_ES18) && hw_config->dma2 >= 0) {
+ devc->dma16 = hw_config->dma2;
+ if (devc->dma8 != devc->dma16) {
devc->duplex = 1;
}
-
- if (!ess_set_dma_hw (devc)) {
- free_irq(devc->irq, devc);
- return 0;
- }
- return 1;
- } else {
- return -1;
}
+ return 1;
}
/****************************************************************************
@@ -1319,13 +1148,13 @@ int ess_dsp_init (sb_devc *devc, struct address_info *hw_config)
#define ES1688_MIXER_DEVICES \
( ES688_MIXER_DEVICES | SOUND_MASK_RECLEV )
-#define ES1887_RECORDING_DEVICES \
+#define ES_NEW_RECORDING_DEVICES \
( ES1688_RECORDING_DEVICES | SOUND_MASK_LINE2 | SOUND_MASK_SYNTH)
-#define ES1887_MIXER_DEVICES \
+#define ES_NEW_MIXER_DEVICES \
( ES1688_MIXER_DEVICES )
/*
- * Mixer registers of ES1887
+ * Mixer registers of ES18xx with new capabilities
*
* These registers specifically take care of recording levels. To make the
* mapping from playback devices to recording devices every recording
@@ -1455,11 +1284,11 @@ MIX_ENT(ES_REC_MIXER_RECLINE3, 0x00, 0, 0, 0x00, 0, 0)
};
/*
- * This one is for ES1887. It's little different from es_rec_mix: it
- * has 0x7c for PCM playback level. This is because ES1887 uses
+ * This one is for new ES's. It's little different from es_rec_mix: it
+ * has 0x7c for PCM playback level. This is because uses
* Audio 2 for playback.
*/
-static mixer_tab es1887_mix = {
+static mixer_tab es_new_mix = {
MIX_ENT(SOUND_MIXER_VOLUME, 0x60, 5, 6, 0x62, 5, 6),
MIX_ENT(SOUND_MIXER_BASS, 0x00, 0, 0, 0x00, 0, 0),
MIX_ENT(SOUND_MIXER_TREBLE, 0x00, 0, 0, 0x00, 0, 0),
@@ -1493,16 +1322,6 @@ MIX_ENT(ES_REC_MIXER_RECLINE2, 0x6c, 7, 4, 0x6c, 3, 4),
MIX_ENT(ES_REC_MIXER_RECLINE3, 0x00, 0, 0, 0x00, 0, 0)
};
-static int ess_has_rec_mixer (int submodel)
-{
- switch (submodel) {
- case SUBMDL_ES1887:
- return 1;
- default:
- return 0;
- };
-};
-
#ifdef FKS_LOGGING
static int ess_mixer_mon_regs[]
= { 0x70, 0x71, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7d, 0x7f
@@ -1533,15 +1352,13 @@ printk(KERN_INFO "FKS: write mixer %x: %x\n", port, value);
save_flags(flags);
cli();
- if (port >= 0xa0) {
- ess_write (devc, port, value);
- } else {
- outb(((unsigned char) (port & 0xff)), MIXER_ADDR);
- udelay(20);
- outb(((unsigned char) (value & 0xff)), MIXER_DATA);
- udelay(20);
- };
+ outb(((unsigned char) (port & 0xff)), MIXER_ADDR);
+
+ udelay(20);
+ outb(((unsigned char) (value & 0xff)), MIXER_DATA);
+ udelay(20);
+
restore_flags(flags);
}
@@ -1553,15 +1370,12 @@ unsigned int ess_getmixer (sb_devc * devc, unsigned int port)
save_flags(flags);
cli();
- if (port >= 0xa0) {
- val = ess_read (devc, port);
- } else {
- outb(((unsigned char) (port & 0xff)), MIXER_ADDR);
+ outb(((unsigned char) (port & 0xff)), MIXER_ADDR);
+
+ udelay(20);
+ val = inb(MIXER_DATA);
+ udelay(20);
- udelay(20);
- val = inb(MIXER_DATA);
- udelay(20);
- }
restore_flags(flags);
return val;
@@ -1585,23 +1399,21 @@ void ess_mixer_init (sb_devc * devc)
devc->mixer_caps = SOUND_CAP_EXCL_INPUT;
/*
- * Take care of ES1887 specifics...
+ * Take care of new ES's specifics...
*/
- switch (devc->submodel) {
- case SUBMDL_ES1887:
- devc->supported_devices = ES1887_MIXER_DEVICES;
- devc->supported_rec_devices = ES1887_RECORDING_DEVICES;
+ if (devc->caps & ESSCAP_NEW) {
+ devc->supported_devices = ES_NEW_MIXER_DEVICES;
+ devc->supported_rec_devices = ES_NEW_RECORDING_DEVICES;
#ifdef FKS_LOGGING
printk (KERN_INFO "FKS: ess_mixer_init dup = %d\n", devc->duplex);
#endif
if (devc->duplex) {
- devc->iomap = &es1887_mix;
+ devc->iomap = &es_new_mix;
} else {
devc->iomap = &es_rec_mix;
}
- break;
- default:
- if (devc->submodel < 8) {
+ } else {
+ if (devc->submodel == SUBMDL_ES688) {
devc->supported_devices = ES688_MIXER_DEVICES;
devc->supported_rec_devices = ES688_RECORDING_DEVICES;
devc->iomap = &es688_mix;
@@ -1612,10 +1424,10 @@ printk (KERN_INFO "FKS: ess_mixer_init dup = %d\n", devc->duplex);
*/
devc->supported_devices = ES1688_MIXER_DEVICES;
devc->supported_rec_devices = ES1688_RECORDING_DEVICES;
- if (devc->submodel < 0x10) {
- devc->iomap = &es1688_mix;
- } else {
+ if (devc->caps & ESSCAP_ES18) {
devc->iomap = &es1688later_mix;
+ } else {
+ devc->iomap = &es1688_mix;
}
}
}
@@ -1627,9 +1439,15 @@ printk (KERN_INFO "FKS: ess_mixer_init dup = %d\n", devc->duplex);
*/
int ess_mixer_set(sb_devc *devc, int dev, int left, int right)
{
- if (ess_has_rec_mixer (devc->submodel) && (devc->recmask & (1 << dev))) {
+ if ((devc->caps & ESSCAP_NEW) && (devc->recmask & (1 << dev))) {
sb_common_mixer_set (devc, dev + ES_REC_MIXER_RECDIFF, left, right);
}
+ /* Set & unmute master volume */
+ if ((devc->caps & ESSCAP_ES18) && (dev == SOUND_MIXER_VOLUME)) {
+ ess_chgmixer (devc, 0x60, 0x7f, 0x3f & ((left * 0x3f + 50) / 100));
+ ess_chgmixer (devc, 0x62, 0x7f, 0x3f & ((right * 0x3f + 50) / 100));
+ return left | (right << 8);
+ }
return sb_common_mixer_set (devc, dev, left, right);
}
@@ -1675,7 +1493,6 @@ printk (KERN_INFO "FKS: es_rec_set_recmask mask = %x\n", mask);
right = (value & 0x0000ff00) >> 8;
} else { /* Turn it off (3) */
left = 0;
- left = 0;
right = 0;
}
sb_common_mixer_set(devc, i + ES_REC_MIXER_RECDIFF, left, right);
@@ -1688,7 +1505,7 @@ int ess_set_recmask(sb_devc * devc, int *mask)
{
/* This applies to ESS chips with record mixers only! */
- if (ess_has_rec_mixer (devc->submodel)) {
+ if (devc->caps & ESSCAP_NEW) {
*mask = es_rec_set_recmask (devc, *mask);
return 1; /* Applied */
} else {
@@ -1704,18 +1521,7 @@ int ess_mixer_reset (sb_devc * devc)
/*
* Separate actions for ESS chips with a record mixer:
*/
- if (ess_has_rec_mixer (devc->submodel)) {
- switch (devc->submodel) {
- case SUBMDL_ES1887:
- /*
- * Separate actions for ES1887:
- * Change registers 7a and 1c to make the record mixer the
- * actual recording source.
- */
- ess_chgmixer(devc, 0x7a, 0x18, 0x08);
- ess_chgmixer(devc, 0x1c, 0x07, 0x07);
- break;
- };
+ if (devc->caps & ESSCAP_NEW) {
/*
* Call set_recmask for proper initialization
*/
@@ -1735,50 +1541,80 @@ int ess_mixer_reset (sb_devc * devc)
* *
****************************************************************************/
-/*
- * FKS: IRQ may be shared. Hm. And if so? Then What?
- */
int ess_midi_init(sb_devc * devc, struct address_info *hw_config)
{
- unsigned char cfg, tmp;
+ int val;
- cfg = ess_getmixer (devc, 0x40) & 0x03;
-
- if (devc->submodel < 8) {
- ess_setmixer (devc, 0x40, cfg | 0x03); /* Enable OPL3 & joystick */
- return 0; /* ES688 doesn't support MPU401 mode */
+ if (devc->submodel == SUBMDL_ES688) {
+ return 0; /* ES688 doesn't support MPU401 mode */
}
- tmp = (hw_config->io_base & 0x0f0) >> 4;
- if (tmp > 3) {
- ess_setmixer (devc, 0x40, cfg);
- return 0;
+ if (hw_config->irq < 2) {
+ hw_config->irq = devc->irq;
}
- cfg |= tmp << 3;
-
- tmp = 1; /* MPU enabled without interrupts */
- /* May be shared: if so the value is -ve */
+ if (devc->caps & ESSCAP_PNP) {
+ outb (0x07, devc->pcibase); /* Selects logical device #1 */
+ outb (0x01, devc->pcibase + 1);
+ outb (0x28, devc->pcibase);
+ val = inb (devc->pcibase + 1) & 0xf0;
+ outb (0x28, devc->pcibase); /* Sets MPU IRQ */
+ outb (hw_config->irq | val, devc->pcibase + 1);
+ if (hw_config->io_base) {
+ outb (0x64, devc->pcibase); /* Sets MPU I/O address */
+ outb ((hw_config->io_base & 0xf00) >> 8, devc->pcibase + 1);
+ outb (0x65, devc->pcibase); /* Sets MPU I/O address */
+ outb (hw_config->io_base & 0xfc, devc->pcibase + 1);
+ } else {
+ outb (0x64, devc->pcibase); /* Read MPU I/O address */
+ hw_config->io_base = (inb (devc->pcibase + 1) & 0x0f) << 8;
+ outb (0x65, devc->pcibase); /* Read MPU I/O address */
+ hw_config->io_base |= inb (devc->pcibase + 1) & 0xfc;
+ }
- switch (abs(hw_config->irq)) {
- case 9:
- tmp = 0x4;
- break;
- case 5:
- tmp = 0x5;
- break;
- case 7:
- tmp = 0x6;
- break;
- case 10:
- tmp = 0x7;
- break;
- default:
- return 0;
+ ess_setmixer (devc, 0x64, 0xc2); /* Enable MPU interrupt */
+ } else {
+ if (devc->irq == hw_config->irq && (devc->caps & ESSCAP_IRQ)) {
+ val = 0x43;
+ }
+ else switch (hw_config->irq) {
+ case 11:
+ if (!(devc->caps & ESSCAP_IRQ)) {
+ return 0;
+ }
+ val = 0x63;
+ break;
+ case 2:
+ case 9:
+ val = 0x83;
+ break;
+ case 5:
+ val = 0xa3;
+ break;
+ case 7:
+ val = 0xc3;
+ break;
+ case 10:
+ val = 0xe3;
+ break;
+ default:
+ return 0;
+ }
+ switch (hw_config->io_base) {
+ case 0x300:
+ case 0x310:
+ case 0x320:
+ case 0x330:
+ ess_setmixer (devc, 0x40, val
+ | ((hw_config->io_base & 0x0f0) >> 1));
+ break;
+ default:
+ return 0;
+ }
}
- cfg |= tmp << 5;
- ess_setmixer (devc, 0x40, cfg | 0x03);
+ if (devc->irq == hw_config->irq) /* Shared IRQ */
+ hw_config->irq = -devc->irq;
return 1;
}
diff --git a/drivers/sound/sequencer.c b/drivers/sound/sequencer.c
index af40a2117..8fee21c6b 100644
--- a/drivers/sound/sequencer.c
+++ b/drivers/sound/sequencer.c
@@ -53,8 +53,8 @@ static int max_synthdev = 0;
#define SEQ_2 2
static int seq_mode = SEQ_1;
-static struct wait_queue *seq_sleeper = NULL;
-static struct wait_queue *midi_sleeper = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(seq_sleeper);
+static DECLARE_WAIT_QUEUE_HEAD(midi_sleeper);
static int midi_opened[MAX_MIDI_DEV] = {
0
@@ -1117,8 +1117,8 @@ int sequencer_open(int dev, struct file *file)
if (seq_mode == SEQ_2)
tmr->open(tmr_no, seq_mode);
- init_waitqueue(&seq_sleeper);
- init_waitqueue(&midi_sleeper);
+ init_waitqueue_head(&seq_sleeper);
+ init_waitqueue_head(&midi_sleeper);
output_threshold = SEQ_MAX_QUEUE / 2;
return 0;
diff --git a/drivers/sound/sonicvibes.c b/drivers/sound/sonicvibes.c
index c6d30d43f..af5ddcea0 100644
--- a/drivers/sound/sonicvibes.c
+++ b/drivers/sound/sonicvibes.c
@@ -286,7 +286,7 @@ struct sv_state {
spinlock_t lock;
struct semaphore open_sem;
mode_t open_mode;
- struct wait_queue *open_wait;
+ wait_queue_head_t open_wait;
struct dmabuf {
void *rawbuf;
@@ -297,7 +297,7 @@ struct sv_state {
unsigned total_bytes;
int count;
unsigned error; /* over/underrun */
- struct wait_queue *wait;
+ wait_queue_head_t wait;
/* redundant, but makes calculations easier */
unsigned fragsize;
unsigned dmasize;
@@ -315,8 +315,8 @@ struct sv_state {
struct {
unsigned ird, iwr, icnt;
unsigned ord, owr, ocnt;
- struct wait_queue *iwait;
- struct wait_queue *owait;
+ wait_queue_head_t iwait;
+ wait_queue_head_t owait;
struct timer_list timer;
unsigned char ibuf[MIDIINBUF];
unsigned char obuf[MIDIOUTBUF];
@@ -1241,7 +1241,7 @@ static /*const*/ struct file_operations sv_mixer_fops = {
static int drain_dac(struct sv_state *s, int nonblock)
{
- struct wait_queue wait = { current, NULL };
+ DECLARE_WAITQUEUE(wait, current);
unsigned long flags;
int count, tmo;
@@ -2043,7 +2043,7 @@ static int sv_midi_open(struct inode *inode, struct file *file)
static int sv_midi_release(struct inode *inode, struct file *file)
{
struct sv_state *s = (struct sv_state *)file->private_data;
- struct wait_queue wait = { current, NULL };
+ DECLARE_WAITQUEUE(wait, current);
unsigned long flags;
unsigned count, tmo;
@@ -2344,12 +2344,12 @@ __initfunc(int init_sonicvibes(void))
continue;
}
memset(s, 0, sizeof(struct sv_state));
- init_waitqueue(&s->dma_adc.wait);
- init_waitqueue(&s->dma_dac.wait);
- init_waitqueue(&s->open_wait);
- init_waitqueue(&s->midi.iwait);
- init_waitqueue(&s->midi.owait);
- s->open_sem = MUTEX;
+ init_waitqueue_head(&s->dma_adc.wait);
+ init_waitqueue_head(&s->dma_dac.wait);
+ init_waitqueue_head(&s->open_wait);
+ init_waitqueue_head(&s->midi.iwait);
+ init_waitqueue_head(&s->midi.owait);
+ init_MUTEX(&s->open_sem);
s->magic = SV_MAGIC;
s->iosb = pcidev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
s->ioenh = pcidev->base_address[1] & PCI_BASE_ADDRESS_IO_MASK;
diff --git a/drivers/sound/sound_core.c b/drivers/sound/sound_core.c
index 9bc08fbd0..a1ec23557 100644
--- a/drivers/sound/sound_core.c
+++ b/drivers/sound/sound_core.c
@@ -52,6 +52,22 @@ struct sound_unit
struct sound_unit *next;
};
+#ifdef CONFIG_SOUND_SONICVIBES
+extern int init_sonicvibes(void);
+#endif
+#ifdef CONFIG_SOUND_ES1370
+extern int init_es1370(void);
+#endif
+#ifdef CONFIG_SOUND_ES1371
+extern int init_es1371(void);
+#endif
+#ifdef CONFIG_SOUND_MSNDCLAS
+extern int msnd_classic_init(void);
+#endif
+#ifdef CONFIG_SOUND_MSNDPIN
+extern int msnd_pinnacle_init(void);
+#endif
+
/*
* Low level list operator. Scan the ordered list, find a hole and
* join into it. Called with the lock asserted
@@ -132,7 +148,7 @@ static void __sound_remove_unit(struct sound_unit **list, int unit)
* This lock guards the sound loader list.
*/
-static spinlock_t sound_loader_lock = SPIN_LOCK_UNLOCKED;
+spinlock_t sound_loader_lock = SPIN_LOCK_UNLOCKED;
/*
* Allocate the controlling structure and add it to the sound driver
@@ -382,6 +398,9 @@ int soundcore_init(void)
#ifdef CONFIG_SOUND_SONICVIBES
init_sonicvibes();
#endif
+#ifdef CONFIG_SOUND_CMPCI
+ init_cmpci();
+#endif
#ifdef CONFIG_SOUND_ES1370
init_es1370();
#endif
diff --git a/drivers/sound/sound_timer.c b/drivers/sound/sound_timer.c
index 8033437f1..60f031ac8 100644
--- a/drivers/sound/sound_timer.c
+++ b/drivers/sound/sound_timer.c
@@ -12,6 +12,7 @@
* Thomas Sailer : ioctl code reworked (vmalloc/vfree removed)
*/
#include <linux/config.h>
+#include <linux/string.h>
#include "sound_config.h"
diff --git a/drivers/sound/wavfront.c b/drivers/sound/wavfront.c
index b6ec7c263..ac58b97da 100644
--- a/drivers/sound/wavfront.c
+++ b/drivers/sound/wavfront.c
@@ -290,7 +290,7 @@ 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;
+ wait_queue_head_t interrupt_sleeper;
} dev;
static int detect_wffx(void);
@@ -2535,7 +2535,7 @@ __initfunc (static int detect_wavefront (int irq, int io_base))
}
- init_waitqueue (&dev.interrupt_sleeper);
+ init_waitqueue_head (&dev.interrupt_sleeper);
if (wavefront_hw_reset ()) {
printk (KERN_WARNING LOGNAME "hardware reset failed\n");