diff options
Diffstat (limited to 'drivers/sound')
-rw-r--r-- | drivers/sound/Config.in | 10 | ||||
-rw-r--r-- | drivers/sound/Makefile | 1 | ||||
-rw-r--r-- | drivers/sound/audio.c | 2 | ||||
-rw-r--r-- | drivers/sound/bin2hex.c | 1 | ||||
-rw-r--r-- | drivers/sound/dev_table.c | 6 | ||||
-rw-r--r-- | drivers/sound/dev_table.h | 6 | ||||
-rw-r--r-- | drivers/sound/dmasound.c | 58 | ||||
-rw-r--r-- | drivers/sound/es1370.c | 81 | ||||
-rw-r--r-- | drivers/sound/es1371.c | 28 | ||||
-rw-r--r-- | drivers/sound/gus_wave.c | 4 | ||||
-rw-r--r-- | drivers/sound/hex2hex.c | 1 | ||||
-rw-r--r-- | drivers/sound/lowlevel/awe_compat.h | 2 | ||||
-rw-r--r-- | drivers/sound/lowlevel/awe_wave.c | 4 | ||||
-rw-r--r-- | drivers/sound/midibuf.c | 8 | ||||
-rw-r--r-- | drivers/sound/msnd.h | 5 | ||||
-rw-r--r-- | drivers/sound/msnd_pinnacle.c | 6 | ||||
-rw-r--r-- | drivers/sound/sb_common.c | 53 | ||||
-rw-r--r-- | drivers/sound/sb_ess.c | 1018 | ||||
-rw-r--r-- | drivers/sound/sequencer.c | 8 | ||||
-rw-r--r-- | drivers/sound/sonicvibes.c | 24 | ||||
-rw-r--r-- | drivers/sound/sound_core.c | 21 | ||||
-rw-r--r-- | drivers/sound/sound_timer.c | 1 | ||||
-rw-r--r-- | drivers/sound/wavfront.c | 4 |
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"); |