Commit 5aaef326 authored by Linus Torvalds's avatar Linus Torvalds

Import 2.3.50

parent b40190e6
......@@ -67,6 +67,32 @@ Current status:
http://usbvisor.sourceforge.net/
Keyspan PDA Serial Adapter
Single port DB-9 serial adapter, pushed as a PDA adapter for iMacs (mostly
sold in Macintosh catalogs, comes in a translucent white/green dongle).
Fairly simple device. Firmware is homebrew.
Current status:
Things that work:
basic input/output (tested with 'cu')
blocking write when serial line can't keep up
changing baud rates (up to 115200)
getting/setting modem control pins (TIOCM{GET,SET,BIS,BIC})
sending break (although duration looks suspect)
Things that don't:
device strings (as logged by kernel) have trailing binary garbage
device ID isn't right, might collide with other Keyspan products
changing baud rates ought to flush tx/rx to avoid mangled half characters
Big Things on the todo list:
parity, 7 vs 8 bits per char, 1 or 2 stop bits
HW flow control
not all of the standard USB descriptors are handled: Get_Status, Set_Feature
O_NONBLOCK, select()
The device usually appears at /dev/ttyUSB1 .
Generic Serial driver
If your device is not one of the above listed devices, compatible with
......
This diff is collapsed.
......@@ -23,7 +23,7 @@ endif
# This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'.
export-objs := ad1848.o audio_syms.o midi_syms.o mpu401.o \
msnd.o opl3.o sb_card.o sequencer_syms.o \
msnd.o opl3.o sb_common.o sequencer_syms.o \
sound_core.o sound_syms.o uart401.o ad1816.o \
nm256_audio.o ac97.o ac97_codec.o
......@@ -45,39 +45,36 @@ obj-$(CONFIG_DMASOUND) += dmasound.o
obj-$(CONFIG_SOUND_OSS) += sound.o
obj-$(CONFIG_SOUND_CS4232) += cs4232.o ad1848.o
# In theory, there's probably no reason to include the uart401 code
# to support a WaveFront card's CS4232 module. However, it makes
# reconfiguring things require a recompile, so just leave this
# here and try not to worry about the extra uart401 module.
# Please leave it as is, cause the link order is significant !
obj-$(CONFIG_SOUND_CS4232) += uart401.o
obj-$(CONFIG_SOUND_PSS) += pss.o ad1848.o mpu401.o
obj-$(CONFIG_SOUND_TRIX) += trix.o ad1848.o sb_lib.o uart401.o
obj-$(CONFIG_SOUND_OPL3SA1) += opl3sa.o ad1848.o uart401.o
obj-$(CONFIG_SOUND_SOFTOSS) += softoss2.o
obj-$(CONFIG_SOUND_SSCAPE) += sscape.o ad1848.o mpu401.o
obj-$(CONFIG_SOUND_MAD16) += mad16.o ad1848.o sb_lib.o uart401.o
obj-$(CONFIG_SOUND_CS4232) += cs4232.o uart401.o
obj-$(CONFIG_SOUND_OPL3SA2) += opl3sa2.o ad1848.o uart401.o mpu401.o
obj-$(CONFIG_SOUND_MSS) += ad1848.o
obj-$(CONFIG_SOUND_PAS) += pas2.o sb_lib.o uart401.o
obj-$(CONFIG_SOUND_SB) += sb.o sb_lib.o uart401.o
obj-$(CONFIG_SOUND_WAVEFRONT) += wavefront.o
obj-$(CONFIG_SOUND_MAUI) += maui.o mpu401.o
obj-$(CONFIG_SOUND_MPU401) += mpu401.o
obj-$(CONFIG_SOUND_UART6850) += uart6850.o
obj-$(CONFIG_SOUND_GUS) += gus.o ad1848.o
obj-$(CONFIG_SOUND_MAD16) += mad16.o ad1848.o sb.o uart401.o
obj-$(CONFIG_SOUND_VIA82CXXX) += via82cxxx_audio.o sb.o uart401.o ac97.o
obj-$(CONFIG_SOUND_MAUI) += maui.o mpu401.o
obj-$(CONFIG_SOUND_MPU401) += mpu401.o
obj-$(CONFIG_SOUND_YM3812) += adlib_card.o opl3.o
obj-$(CONFIG_SOUND_VMIDI) += v_midi.o
obj-$(CONFIG_SOUND_VIDC) += vidc_mod.o
obj-$(CONFIG_SOUND_WAVEARTIST) += waveartist.o
obj-$(CONFIG_SOUND_SGALAXY) += sgalaxy.o ad1848.o
obj-$(CONFIG_SOUND_AD1816) += ad1816.o
obj-$(CONFIG_SOUND_VIA82CXXX) += via82cxxx_audio.o sb_lib.o uart401.o ac97.o
obj-$(CONFIG_SOUND_MSNDCLAS) += msnd.o msnd_classic.o
obj-$(CONFIG_SOUND_MSNDPIN) += msnd.o msnd_pinnacle.o
obj-$(CONFIG_SOUND_MSS) += ad1848.o
obj-$(CONFIG_SOUND_OPL3SA1) += opl3sa.o ad1848.o uart401.o
obj-$(CONFIG_SOUND_OPL3SA2) += opl3sa2.o ad1848.o uart401.o mpu401.o
obj-$(CONFIG_SOUND_PAS) += pas2.o sb.o uart401.o
obj-$(CONFIG_SOUND_PSS) += pss.o ad1848.o mpu401.o
obj-$(CONFIG_SOUND_SB) += sb.o uart401.o
obj-$(CONFIG_SOUND_SOFTOSS) += softoss2.o
obj-$(CONFIG_SOUND_SGALAXY) += sgalaxy.o ad1848.o
obj-$(CONFIG_SOUND_AD1816) += ad1816.o
obj-$(CONFIG_SOUND_SSCAPE) += sscape.o ad1848.o mpu401.o
obj-$(CONFIG_SOUND_TRIX) += trix.o ad1848.o sb.o uart401.o
obj-$(CONFIG_SOUND_UART6850) += uart6850.o
obj-$(CONFIG_SOUND_VMIDI) += v_midi.o
obj-$(CONFIG_SOUND_YM3812) += adlib_card.o opl3.o
obj-$(CONFIG_SOUND_VIDC) += vidc_mod.o
obj-$(CONFIG_SOUND_VWSND) += vwsnd.o
obj-$(CONFIG_SOUND_WAVEARTIST) += waveartist.o
obj-$(CONFIG_SOUND_WAVEFRONT) += wavefront.o
obj-$(CONFIG_SOUND_NM256) += nm256.o
obj-$(CONFIG_SOUND_NM256) += nm256_audio.o ac97.o
obj-$(CONFIG_SOUND_SONICVIBES) += sonicvibes.o
obj-$(CONFIG_SOUND_CMPCI) += cmpci.o
obj-$(CONFIG_SOUND_ES1370) += es1370.o
......@@ -89,7 +86,7 @@ obj-$(CONFIG_SOUND_TRIDENT) += trident.o ac97_codec.o
# Declare multi-part drivers.
list-multi := sound.o gus.o pas2.o sb.o softoss2.o vidc_mod.o \
soundcore.o wavefront.o nm256.o
soundcore.o wavefront.o
sound-objs := \
dev_table.o soundcard.o sound_syms.o \
......@@ -101,12 +98,11 @@ soundcore-objs := sound_core.o sound_firmware.o
gus-objs := gus_card.o gus_midi.o gus_vol.o gus_wave.o ics2101.o
pas2-objs := pas2_card.o pas2_midi.o pas2_mixer.o pas2_pcm.o
sb-objs := sb_audio.o sb_card.o sb_common.o sb_midi.o sb_mixer.o \
sb_ess.o
sb-objs := sb_card.o
sb_lib-objs := sb_common.o sb_audio.o sb_midi.o sb_mixer.o sb_ess.o
softoss2-objs := softoss.o softoss_rs.o
vidc_mod-objs := vidc.o vidc_fill.o
wavefront-objs := wavfront.o wf_midi.o yss225.o
nm256-objs := nm256_audio.o ac97.o
# Extract lists of the multi-part drivers.
......@@ -125,20 +121,6 @@ obj-m := $(filter-out $(obj-y), $(obj-m))
int-m := $(filter-out $(int-y), $(int-m))
# Set flags for secondary drivers.
# I have to do this before I reduce obj-y to components.
EXTRA_CFLAGS := $(sort \
$(patsubst ad1848.o, -DCONFIG_SOUND_AD1848, \
$(patsubst mpu401.o, -DCONFIG_SOUND_MPU_EMU, \
$(patsubst sb.o, -DCONFIG_SOUND_SBDSP, \
$(patsubst uart401.o, -DCONFIG_SOUND_UART401, \
$(filter ad1848.o mpu401.o sb.o uart401.o, $(obj-y)) \
)))))
# Take multi-part drivers out of obj-y and put components in.
obj-y := $(filter-out $(list-multi), $(obj-y)) $(int-y)
......@@ -155,8 +137,8 @@ O_OBJS := $(filter-out $(export-objs), $(obj-y))
OX_OBJS := $(filter $(export-objs), $(obj-y))
M_OBJS := $(sort $(filter-out $(export-objs), $(obj-m)))
MX_OBJS := $(sort $(filter $(export-objs), $(obj-m)))
MI_OBJS := $(sort $(filter-out $(export-objs), $(int-m)))
MIX_OBJS := $(sort $(filter $(export-objs), $(int-m)))
#MI_OBJS := $(sort $(filter-out $(export-objs), $(int-m)))
#MIX_OBJS := $(sort $(filter $(export-objs), $(int-m)))
ifeq ($(CONFIG_LOWLEVEL_SOUND),y)
O_OBJS += lowlevel/lowlevel.o
......@@ -183,6 +165,9 @@ pas2.o: $(pas2-objs)
sb.o: $(sb-objs)
$(LD) -r -o $@ $(sb-objs)
sb_lib.o: $(sb_lib-objs)
$(LD) -r -o $@ $(sb_lib-objs)
softoss2.o: $(softoss2-objs)
$(LD) -r -o $@ $(softoss2-objs)
......@@ -192,9 +177,6 @@ vidc_mod.o: $(vidc_mod-objs)
wavefront.o: $(wavefront-objs)
$(LD) -r -o $@ $(wavefront-objs)
nm256.o: $(nm256-objs)
$(LD) -r -o $@ $(nm256-objs)
# Firmware files that need translation
#
# The translated files are protected by a file that keeps track
......
/*
AD1816 lowlevel sound driver for Linux 2.2.0 and above
Copyright (C) 1998 by Thorsten Knabe <tek@rbg.informatik.tu-darmstadt.de>
Based on the CS4232/AD1848 driver Copyright (C) by Hannu Savolainen 1993-1996
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
-------------------------------------------------------------------------------
NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE!
This software is still under development. New versions of the driver
are available from:
http://www.student.informatik.tu-darmstadt.de/~tek/projects/linux.html
or
http://www.tu-darmstadt.de/~tek01/projects/linux.html
Please report any bugs to: tek@rbg.informatik.tu-darmstadt.de
-------------------------------------------------------------------------------
version: 1.3
cvs: $Header: /home/tek/CVSROOT/sound22/ad1816.c,v 1.3 1999/04/18 16:41:41 tek Exp $
status: experimental
date: 1999/4/18
Changes:
Oleg Drokin: Some cleanup of load/unload functions. 1998/11/24
Thorsten Knabe: attach and unload rewritten,
some argument checks added 1998/11/30
Thorsten Knabe: Buggy isa bridge workaround added 1999/01/16
David Moews/Thorsten Knabe: Introduced options
parameter. Added slightly modified patch from
David Moews to disable dsp audio sources by setting
bit 0 of options parameter. This seems to be
required by some Aztech/Newcom SC-16 cards. 1999/04/18
*/
*
* AD1816 lowlevel sound driver for Linux 2.2.0 and above
*
* Copyright (C) 1998 by Thorsten Knabe <tek@rbg.informatik.tu-darmstadt.de>
*
* Based on the CS4232/AD1848 driver Copyright (C) by Hannu Savolainen 1993-1996
*
* This software is still under development. New versions of the driver
* are available from:
* http://www.student.informatik.tu-darmstadt.de/~tek/projects/linux.html
* or http://www.tu-darmstadt.de/~tek01/projects/linux.html
*
* Please report any bugs to: tek@rbg.informatik.tu-darmstadt.de
*
*
* version: 1.3
* cvs: $Header: /home/tek/CVSROOT/sound22/ad1816.c,v 1.3 1999/04/18 16:41:41 tek Exp $
* status: experimental
* date: 1999/4/18
*
* Changes:
* Oleg Drokin: Some cleanup of load/unload functions. 1998/11/24
*
* Thorsten Knabe: attach and unload rewritten,
* some argument checks added 1998/11/30
*
* Thorsten Knabe: Buggy isa bridge workaround added 1999/01/16
*
* David Moews/Thorsten Knabe: Introduced options
* parameter. Added slightly modified patch from
* David Moews to disable dsp audio sources by setting
* bit 0 of options parameter. This seems to be
* required by some Aztech/Newcom SC-16 cards. 1999/04/18
*
* Christoph Hellwig: Adapted to module_init/module_exit. 2000/03/03
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/stddef.h>
#include "soundmodule.h"
#include "sound_config.h"
......@@ -96,14 +80,10 @@ typedef struct
int irq_ok;
int *osp;
}
ad1816_info;
static int nr_ad1816_devs = 0;
static int ad1816_clockfreq=33000;
} ad1816_info;
static int nr_ad1816_devs = 0;
static int ad1816_clockfreq=33000;
static int options=0;
/* for backward mapping of irq to sound device */
......@@ -617,7 +597,8 @@ static struct audio_driver ad1816_audio_driver =
/* Interrupt handler */
void ad1816_interrupt (int irq, void *dev_id, struct pt_regs *dummy)
static void ad1816_interrupt (int irq, void *dev_id, struct pt_regs *dummy)
{
unsigned char status;
ad1816_info *devc;
......@@ -1089,7 +1070,7 @@ static struct mixer_operations ad1816_mixer_operations =
/* replace with probe routine */
int probe_ad1816 ( struct address_info *hw_config )
static int __init probe_ad1816 ( struct address_info *hw_config )
{
ad1816_info *devc = &dev_info[nr_ad1816_devs];
int io_base=hw_config->io_base;
......@@ -1097,7 +1078,6 @@ int probe_ad1816 ( struct address_info *hw_config )
int tmp;
printk("ad1816: AD1816 sounddriver Copyright (C) 1998 by Thorsten Knabe\n");
printk("ad1816: $Header: /home/tek/CVSROOT/sound22/ad1816.c,v 1.3 1999/04/18 16:41:41 tek Exp $\n");
printk("ad1816: io=0x%x, irq=%d, dma=%d, dma2=%d, clockfreq=%d, options=%d isadmabug=%d\n",
hw_config->io_base,
hw_config->irq,
......@@ -1183,7 +1163,7 @@ int probe_ad1816 ( struct address_info *hw_config )
*/
void attach_ad1816 (struct address_info *hw_config)
static void __init attach_ad1816 (struct address_info *hw_config)
{
int my_dev;
char dev_name[100];
......@@ -1309,7 +1289,7 @@ void attach_ad1816 (struct address_info *hw_config)
}
}
void unload_card(ad1816_info *devc)
static void __exit unload_card(ad1816_info *devc)
{
int mixer, dev = 0;
......@@ -1343,51 +1323,12 @@ void unload_card(ad1816_info *devc)
}
}
void unload_ad1816 (struct address_info *hw_config)
{
int i;
ad1816_info *devc = NULL;
/* remove any soundcard */
if (hw_config==NULL) {
for (i = 0; i < nr_ad1816_devs; i++) {
devc = &dev_info[i];
unload_card(devc);
}
nr_ad1816_devs=0;
} else {
/* remove specified soundcard */
for (i = 0; i < nr_ad1816_devs; i++) {
int j;
if (dev_info[i].base == hw_config->io_base) {
devc = &dev_info[i];
unload_card(devc);
nr_ad1816_devs--;
for ( j=i; j < nr_ad1816_devs ; j++) {
dev_info[j] = dev_info[j+1];
}
i--;
}
}
}
}
/* ----------------------------- 2.1.xxx module stuff ----------------- */
EXPORT_SYMBOL(ad1816_interrupt);
EXPORT_SYMBOL(probe_ad1816);
EXPORT_SYMBOL(attach_ad1816);
EXPORT_SYMBOL(unload_ad1816);
static struct address_info cfg;
#ifdef MODULE
int io = -1;
int irq = -1;
int dma = -1;
int dma2 = -1;
static int __initdata io = -1;
static int __initdata irq = -1;
static int __initdata dma = -1;
static int __initdata dma2 = -1;
MODULE_PARM(io,"i");
MODULE_PARM(irq,"i");
......@@ -1396,33 +1337,59 @@ MODULE_PARM(dma2,"i");
MODULE_PARM(ad1816_clockfreq,"i");
MODULE_PARM(options,"i");
struct address_info cfg;
static int __init init_ad1816(void)
{
cfg.io_base = io;
cfg.irq = irq;
cfg.dma = dma;
cfg.dma2 = dma2;
if (cfg.io_base == -1 || cfg.irq == -1 || cfg.dma == -1 || cfg.dma2 == -1) {
printk(KERN_INFO "ad1816: dma, dma2, irq and io must be set.\n");
return -EINVAL;
}
if (probe_ad1816(&cfg) == 0) {
return -ENODEV;
}
attach_ad1816(&cfg);
SOUND_LOCK;
}
int init_module(void)
static void __exit cleanup_ad1816 (void)
{
if (io == -1 || irq == -1 || dma == -1 || dma2 == -1) {
printk("ad1816: dma, dma2, irq and io must be set.\n");
return -EINVAL;
}
cfg.io_base = io;
cfg.irq = irq;
cfg.dma = dma;
cfg.dma2 = dma2;
if (probe_ad1816(&cfg) == 0) {
return -ENODEV;
}
attach_ad1816(&cfg);
SOUND_LOCK;
return 0;
int i;
ad1816_info *devc = NULL;
/* remove any soundcard */
for (i = 0; i < nr_ad1816_devs; i++) {
devc = &dev_info[i];
unload_card(devc);
}
nr_ad1816_devs=0;
SOUND_LOCK_END;
}
module_init(init_ad1816);
module_exit(cleanup_ad1816);
void cleanup_module(void)
#ifndef MODULE
static int __init setup_ad1816(char *str)
{
unload_ad1816(NULL);
SOUND_LOCK_END;
/* io, irq, dma, dma2 */
int ints[5];
str = get_options(str, ARRAY_SIZE(ints), ints);
io = ints[1];
irq = ints[2];
dma = ints[3];
dma16 = ints[4];
return 1;
}
#endif /* MODULE */
__setup("ad1816=", setup_ad1816);
#endif
......@@ -22,16 +22,18 @@
* for more info.
*
*
* Thomas Sailer : ioctl code reworked (vmalloc/vfree removed)
* general sleep/wakeup clean up.
* Alan Cox : reformatted. Fixed SMP bugs. Moved to kernel alloc/free
* of irqs. Use dev_id.
* Thomas Sailer : ioctl code reworked (vmalloc/vfree removed)
* general sleep/wakeup clean up.
* Alan Cox : reformatted. Fixed SMP bugs. Moved to kernel alloc/free
* of irqs. Use dev_id.
* Christoph Hellwig : adapted to module_init/module_exit
*
* Status:
* Tested. Believed fully functional.
*/
#include <linux/config.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/stddef.h>
......@@ -40,6 +42,8 @@
#define DEB(x)
#define DEB1(x)
#include "sound_config.h"
#include "ad1848.h"
#include "ad1848_mixer.h"
typedef struct
......@@ -99,23 +103,19 @@ ad1848_port_info;
static int nr_ad1848_devs = 0;
int deskpro_xl = 0;
int deskpro_m = 0;
#ifdef CONFIG_SOUND_SPRO
int soundpro = 1;
#else
int soundpro = 0;
#endif
static volatile signed char irq2dev[17] = {
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1
};
#ifdef MODULE
#ifndef EXCLUDE_TIMERS
static int timer_installed = -1;
#endif
static int loaded = 0;
static int ad_format_mask[10 /*devc->model */ ] =
{
0,
......@@ -2502,6 +2502,11 @@ void attach_ms_sound(struct address_info *hw_config)
int dma = hw_config->dma;
int dma2 = hw_config->dma2;
if(hw_config->io_base != -1 || hw_config->irq == -1 || hw_config->dma == -1) {
printk(KERN_WARNING "ad1848: must give I/O , IRQ and DMA.\n");
return;
}
if (hw_config->card_subtype == 1) /* Has no IRQ/DMA registers */
{
hw_config->slots[0] = ad1848_init("MS Sound System", hw_config->io_base + 4,
......@@ -2568,6 +2573,9 @@ void attach_ms_sound(struct address_info *hw_config)
dma2, 0,
hw_config->osp);
request_region(hw_config->io_base, 4, "WSS config");
SOUND_LOCK;
loaded = 1;
}
void unload_ms_sound(struct address_info *hw_config)
......@@ -2702,8 +2710,6 @@ EXPORT_SYMBOL(probe_ms_sound);
EXPORT_SYMBOL(attach_ms_sound);
EXPORT_SYMBOL(unload_ms_sound);
#ifdef MODULE
MODULE_PARM(io, "i"); /* I/O for a raw AD1848 card */
MODULE_PARM(irq, "i"); /* IRQ to use */
MODULE_PARM(dma, "i"); /* First DMA channel */
......@@ -2713,45 +2719,57 @@ MODULE_PARM(deskpro_xl, "i"); /* Special magic for Deskpro XL boxen */
MODULE_PARM(deskpro_m, "i"); /* Special magic for Deskpro M box */
MODULE_PARM(soundpro, "i"); /* More special magic for SoundPro chips */
int io = -1;
int irq = -1;
int dma = -1;
int dma2 = -1;
int type = 0;
static int __initdata io = -1;
static int __initdata irq = -1;
static int __initdata dma = -1;
static int __initdata dma2 = -1;
static int __initdata type = 0;
static int loaded = 0;
struct address_info hw_config;
static struct address_info cfg;
int init_module(void)
static int __init init_ad1848(void)
{
printk(KERN_INFO "ad1848/cs4248 codec driver Copyright (C) by Hannu Savolainen 1993-1996\n");
if(io != -1)
{
if(irq == -1 || dma == -1)
{
printk(KERN_WARNING "ad1848: must give I/O , IRQ and DMA.\n");
return -EINVAL;
}
hw_config.irq = irq;
hw_config.io_base = io;
hw_config.dma = dma;
hw_config.dma2 = dma2;
hw_config.card_subtype = type;
if(!probe_ms_sound(&hw_config))
return -ENODEV;
attach_ms_sound(&hw_config);
loaded=1;
}
SOUND_LOCK;
return 0;
cfg.irq = irq;
cfg.io_base = io;
cfg.dma = dma;
cfg.dma2 = dma2;
cfg.card_subtype = type;
if(probe_ms_sound(&cfg)) {
attach_ms_sound(&cfg);
return 0;
} else
return -ENODEV;
}
void cleanup_module(void)
static void __exit cleanup_ad1848(void)
{
SOUND_LOCK_END;
if(loaded)
unload_ms_sound(&hw_config);
unload_ms_sound(&cfg);
}
#endif /* MODULE */
module_init(init_ad1848);
module_exit(cleanup_ad1848);
#ifndef MODULE
static int __init setup_ad1848(char *str)
{
/* io, irq, dma, dma2, type */
int ints[6];
str = get_options(str, ARRAY_SIZE(ints), ints);
io = ints[1];
irq = ints[2];
dma = ints[3];
dma2 = ints[4];
type = ints[5];
return 1;
}
__setup("ad1848=", setup_ad1848);
#endif
/*
* ad1848.c
*
* Copyright: Christoph Hellwig <chhellwig@gmx.net>
*/
#define AD_F_CS4231 0x0001 /* Returned if a CS4232 (or compatible) detected */
#define AD_F_CS4248 0x0001 /* Returned if a CS4248 (or compatible) detected */
#define AD1848_SET_XTAL 1
#define AD1848_MIXER_REROUTE 2
#define AD1848_REROUTE(oldctl, newctl) \
ad1848_control(AD1848_MIXER_REROUTE, ((oldctl)<<8)|(newctl))
int ad1848_init(char *name, int io_base, int irq, int dma_playback,
int dma_capture, int share_dma, int *osp);
void ad1848_unload (int io_base, int irq, int dma_playback, int dma_capture, int share_dma);
int ad1848_detect (int io_base, int *flags, int *osp);
int ad1848_control(int cmd, int arg);
void adintr(int irq, void *dev_id, struct pt_regs * dummy);
void attach_ms_sound(struct address_info * hw_config);
int probe_ms_sound(struct address_info *hw_config);
void unload_ms_sound(struct address_info *hw_info);
......@@ -11,47 +11,42 @@
*/
#include <linux/module.h>
#include <linux/init.h>
#include "sound_config.h"
#include "soundmodule.h"
void attach_adlib_card(struct address_info *hw_config)
#include "opl3.h"
static void __init attach_adlib_card(struct address_info *hw_config)
{
hw_config->slots[0] = opl3_init(hw_config->io_base, hw_config->osp);
request_region(hw_config->io_base, 4, "OPL3/OPL2");
}
int probe_adlib(struct address_info *hw_config)
static int __init probe_adlib(struct address_info *hw_config)
{
if (check_region(hw_config->io_base, 4))
{
if (check_region(hw_config->io_base, 4)) {
DDB(printk("opl3.c: I/O port %x already in use\n", hw_config->io_base));
return 0;
}
return opl3_detect(hw_config->io_base, hw_config->osp);
}
void unload_adlib(struct address_info *hw_config)
{
release_region(hw_config->io_base, 4);
sound_unload_synthdev(hw_config->slots[0]);
}
static struct address_info cfg;
#ifdef MODULE
static int __initdata io = -1;
int io = -1;
MODULE_PARM(io, "i");
EXPORT_NO_SYMBOLS;
struct address_info cfg;
int init_module(void)
static int __init init_adlib(void)
{
if (io == -1) {
cfg.io_base = io;
if (cfg.io_base == -1) {
printk(KERN_ERR "adlib: must specify I/O address.\n");
return -EINVAL;
}
cfg.io_base = io;
if (probe_adlib(&cfg) == 0)
return -ENODEV;
attach_adlib_card(&cfg);
......@@ -59,10 +54,27 @@ int init_module(void)
return 0;
}
void cleanup_module(void)
static void __exit cleanup_adlib(void)
{
unload_adlib(&cfg);
release_region(cfg.io_base, 4);
sound_unload_synthdev(cfg.slots[0]);
SOUND_LOCK_END;
}
#endif /* MODULE */
module_init(init_adlib);
module_exit(cleanup_adlib);
#ifndef MODULE
static int __init setup_adlib(char *str)
{
/* io */
int ints[2];
str = get_options(str, ARRAY_SIZE(ints), ints);
io = ints[1];
return 1;
}
__setup("adlib=", setup_adlib);
#endif
/*
* sound/cs4232.c
* Copyright (C) by Hannu Savolainen 1993-1997
*
* cs4232.c
*
* The low level driver for Crystal CS4232 based cards. The CS4232 is
* a PnP compatible chip which contains a CS4231A codec, SB emulation,
......@@ -35,22 +37,21 @@
* Alan Cox Modularisation, Basic cleanups.
* Paul Barton-Davis Separated MPU configuration, added
* Tropez+ (WaveFront) support
*/
/*
* Copyright (C) by Hannu Savolainen 1993-1997
*
* OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
* Version 2 (June 1991). See the "COPYING" file distributed with this software
* for more info.
* Christoph Hellwig Adapted to module_init/module_exit,
* simple cleanups
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include "sound_config.h"
#include "soundmodule.h"
#include "cs4232.h"
#include "ad1848.h"
#include "mpu401.h"
#define KEY_PORT 0x279 /* Same as LPT1 status port */
#define CSN_NUM 0x99 /* Just a random number */
......@@ -78,11 +79,6 @@ int probe_cs4232_mpu(struct address_info *hw_config)
return 1;
}
void attach_cs4232_mpu(struct address_info *hw_config)
{
/* Nothing needs doing */
}
static unsigned char crystal_key[] = /* A 32 byte magic key sequence */
{
0x96, 0x35, 0x9a, 0xcd, 0xe6, 0xf3, 0x79, 0xbc,
......@@ -215,8 +211,15 @@ int probe_cs4232(struct address_info *hw_config)
void attach_cs4232(struct address_info *hw_config)
{
int base = hw_config->io_base, irq = hw_config->irq;
int dma1 = hw_config->dma, dma2 = hw_config->dma2;
int base = hw_config->io_base,
irq = hw_config->irq,
dma1 = hw_config->dma,
dma2 = hw_config->dma2;
if (base == -1 || irq == -1 || dma1 == -1) {
printk(KERN_ERR "cs4232: dma, irq and io must be set.\n");
return;
}
if (dma2 == -1)
dma2 = dma1;
......@@ -263,6 +266,7 @@ void attach_cs4232(struct address_info *hw_config)
}
hw_config->slots[1] = hw_config2.slots[1];
}
SOUND_LOCK;
}
void unload_cs4232(struct address_info *hw_config)
......@@ -302,19 +306,18 @@ void unload_cs4232(struct address_info *hw_config)
}
}
void unload_cs4232_mpu(struct address_info *hw_config)
{
/* Not required. Handled by cs4232_unload */
}
static struct address_info cfg;
static struct address_info cfg_mpu;
#ifdef MODULE
static int __initdata io = -1;
static int __initdata irq = -1;
static int __initdata dma = -1;
static int __initdata dma2 = -1;
static int __initdata mpuio = -1;
static int __initdata mpuirq = -1;
static int __initdata synthio = -1;
static int __initdata synthirq = -1;
int io = -1;
int irq = -1;
int dma = -1;
int dma2 = -1;
int mpuio = -1;
int mpuirq = -1;
MODULE_PARM(io,"i");
MODULE_PARM(irq,"i");
......@@ -322,34 +325,20 @@ MODULE_PARM(dma,"i");
MODULE_PARM(dma2,"i");
MODULE_PARM(mpuio,"i");
MODULE_PARM(mpuirq,"i");
int synthio = -1;
int synthirq = -1;
MODULE_PARM(synthio,"i");
MODULE_PARM(synthirq,"i");
EXPORT_NO_SYMBOLS;
struct address_info cfg;
struct address_info mpu_cfg;
/*
* Install a CS4232 based card. Need to have ad1848 and mpu401
* loaded ready.
*/
int init_module(void)
static int __init init_cs4232(void)
{
if (io == -1 || irq == -1 || dma == -1 || dma2 == -1)
{
printk(KERN_ERR "cs4232: dma, dma2, irq and io must be set.\n");
return -EINVAL;
}
#ifdef CONFIG_SOUND_WAVEFRONT_MODULE
if(synthio == -1)
printk(KERN_WARNING "cs4232: set synthio and synthirq to use the wavefront facilities.\n");
else
{
else {
synth_base = synthio;
synth_irq = synthirq;
}
......@@ -363,32 +352,48 @@ int init_module(void)
cfg.dma = dma;
cfg.dma2 = dma2;
mpu_cfg.io_base = -1;
mpu_cfg.irq = -1;
cfg_mpu.io_base = -1;
cfg_mpu.irq = -1;
if (mpuio != -1 && mpuirq != -1) {
mpu_cfg.io_base = mpuio;
mpu_cfg.irq = mpuirq;
probe_cs4232_mpu(&mpu_cfg); /* Bug always returns 0 not OK -- AC */
cfg_mpu.io_base = mpuio;
cfg_mpu.irq = mpuirq;
probe_cs4232_mpu(&cfg_mpu); /* Bug always returns 0 not OK -- AC */
}
if (probe_cs4232(&cfg) == 0)
return -ENODEV;
attach_cs4232(&cfg);
if (mpuio != -1 && mpuirq != -1) {
attach_cs4232_mpu(&mpu_cfg);
}
SOUND_LOCK;
return 0;
}
void cleanup_module(void)
static void __exit cleanup_cs4232(void)
{
unload_cs4232(&cfg); /* unloads MPU as well, if needed */
SOUND_LOCK_END;
}
#endif /* MODULE */
module_init(init_cs4232);
module_exit(cleanup_cs4232);
#ifndef MODULE
static int __init setup_cs4232(char *str)
{
/* io, irq, dma, dma2 mpuio, mpuirq*/
int ints[7];
str = get_options(str, ARRAY_SIZE(ints), ints);
io = ints[1];
irq = ints[2];
dma = ints[3];
dma2 = ints[4];
mpuio = ints[5];
mpuirq = ints[6];
return 1;
}
__setup("cs4232=", setup_cs4232);
#endif
/*
* cs4232.h
*
* Copyright: Christoph Hellwig <chhellwig@gmx.net>
*
*/
int probe_cs4232 (struct address_info *hw_config);
void attach_cs4232 (struct address_info *hw_config);
int probe_cs4232_mpu (struct address_info *hw_config);
void attach_cs4232_mpu (struct address_info *hw_config);
......@@ -2,9 +2,8 @@
* sound/dev_table.c
*
* Device call tables.
*/
/*
*
*
* Copyright (C) by Hannu Savolainen 1993-1997
*
* OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
......@@ -15,7 +14,6 @@
#include <linux/config.h>
#include <linux/init.h>
#define _DEV_TABLE_C_
#include "sound_config.h"
......@@ -23,387 +21,6 @@ int softoss_dev = 0;
int sound_started = 0;
int sndtable_get_cardcount(void);
int snd_find_driver(int type)
{
int i, n = num_sound_drivers;
for (i = 0; i < n; i++)
if (sound_drivers[i].card_type == type)
return i;
return -1;
}
static void start_services(void)
{
#ifdef FIXME
int soundcards_installed;
if (!(soundcards_installed = sndtable_get_cardcount()))
return; /* No cards detected */
#endif
if (num_audiodevs) /* Audio devices present */
{
int dev;
for (dev = 0; dev < num_audiodevs; dev++)
{
}
audio_init_devices();
}
return;
}
static void
start_cards(void)
{
int i, n = num_sound_cards;
int drv;
sound_started = 1;
if (trace_init)
printk(KERN_DEBUG "Sound initialization started\n");
#ifdef CONFIG_LOWLEVEL_SOUND
{
extern void sound_preinit_lowlevel_drivers(void);
sound_preinit_lowlevel_drivers();
}
#endif
/*
* Check the number of cards actually defined in the table
*/
for (i = 0; i < n && snd_installed_cards[i].card_type; i++)
num_sound_cards = i + 1;
for (i = 0; i < n && snd_installed_cards[i].card_type; i++)
{
if (snd_installed_cards[i].enabled)
{
snd_installed_cards[i].for_driver_use = NULL;
if ((drv = snd_find_driver(snd_installed_cards[i].card_type)) == -1)
{
snd_installed_cards[i].enabled = 0; /*
* Mark as not detected
*/
continue;
}
snd_installed_cards[i].config.card_subtype =
sound_drivers[drv].card_subtype;
if (sound_drivers[drv].probe(&snd_installed_cards[i].config))
sound_drivers[drv].attach(&snd_installed_cards[i].config);
else
snd_installed_cards[i].enabled = 0; /*
* Mark as not detected
*/
}
}
#ifdef CONFIG_LOWLEVEL_SOUND
{
extern void sound_init_lowlevel_drivers(void);
sound_init_lowlevel_drivers();
}
#endif
if (trace_init)
printk(KERN_DEBUG "Sound initialization complete\n");
}
void sndtable_init(void)
{
start_cards();
}
void sound_unload_drivers(void)
{
int i, n = num_sound_cards;
int drv;
if (!sound_started)
return;
if (trace_init)
printk(KERN_DEBUG "Sound unload started\n");
for (i = 0; i < n && snd_installed_cards[i].card_type; i++)
{
if (snd_installed_cards[i].enabled)
{
if ((drv = snd_find_driver(snd_installed_cards[i].card_type)) != -1)
{
if (sound_drivers[drv].unload)
{
sound_drivers[drv].unload(&snd_installed_cards[i].config);
snd_installed_cards[i].enabled = 0;
}
}
}
}
for (i=0;i<num_audiodevs;i++)
DMAbuf_deinit(i);
if (trace_init)
printk(KERN_DEBUG "Sound unload complete\n");
}
void sound_unload_driver(int type)
{
int i, drv = -1, n = num_sound_cards;
DEB(printk("unload driver %d: ", type));
for (i = 0; i < n && snd_installed_cards[i].card_type; i++)
{
if (snd_installed_cards[i].card_type == type)
{
if (snd_installed_cards[i].enabled)
{
if ((drv = snd_find_driver(type)) != -1)
{
DEB(printk(" card %d", i));
if (sound_drivers[drv].unload)
{
sound_drivers[drv].unload(&snd_installed_cards[i].config);
snd_installed_cards[i].enabled = 0;
}
}
}
}
}
DEB(printk("\n"));
}
int sndtable_probe(int unit, struct address_info *hw_config)
{
int sel = -1;
DEB(printk(KERN_DEBUG "sndtable_probe(%d)\n", unit));
if (!unit)
return 1;
if (sel == -1 && num_sound_cards < max_sound_cards)
{
int i;
i = sel = (num_sound_cards++);
snd_installed_cards[sel].card_type = unit;
snd_installed_cards[sel].enabled = 1;
}
if (sel != -1)
{
int drv;
snd_installed_cards[sel].for_driver_use = NULL;
snd_installed_cards[sel].config.io_base = hw_config->io_base;
snd_installed_cards[sel].config.irq = hw_config->irq;
snd_installed_cards[sel].config.dma = hw_config->dma;
snd_installed_cards[sel].config.dma2 = hw_config->dma2;
snd_installed_cards[sel].config.name = hw_config->name;
snd_installed_cards[sel].config.always_detect = hw_config->always_detect;
snd_installed_cards[sel].config.driver_use_1 = hw_config->driver_use_1;
snd_installed_cards[sel].config.driver_use_2 = hw_config->driver_use_2;
snd_installed_cards[sel].config.card_subtype = hw_config->card_subtype;
if ((drv = snd_find_driver(snd_installed_cards[sel].card_type)) == -1)
{
snd_installed_cards[sel].enabled = 0;
DEB(printk(KERN_DEBUG "Failed to find driver\n"));
return 0;
}
DEB(printk(KERN_DEBUG "Driver name '%s'\n", sound_drivers[drv].name));
hw_config->card_subtype = snd_installed_cards[sel].config.card_subtype = sound_drivers[drv].card_subtype;
if (sound_drivers[drv].probe(hw_config))
{
DEB(printk(KERN_DEBUG "Hardware probed OK\n"));
return 1;
}
DEB(printk("Failed to find hardware\n"));
snd_installed_cards[sel].enabled = 0; /*
* Mark as not detected
*/
return 0;
}
return 0;
}
int sndtable_init_card(int unit, struct address_info *hw_config)
{
int i, n = num_sound_cards;
DEB(printk("sndtable_init_card(%d) entered\n", unit));
if (!unit)
{
sndtable_init();
return 1;
}
for (i = 0; i < n && snd_installed_cards[i].card_type; i++)
{
if (snd_installed_cards[i].card_type == unit)
{
int drv;
snd_installed_cards[i].config.io_base = hw_config->io_base;
snd_installed_cards[i].config.irq = hw_config->irq;
snd_installed_cards[i].config.dma = hw_config->dma;
snd_installed_cards[i].config.dma2 = hw_config->dma2;
snd_installed_cards[i].config.name = hw_config->name;
snd_installed_cards[i].config.always_detect = hw_config->always_detect;
snd_installed_cards[i].config.driver_use_1 = hw_config->driver_use_1;
snd_installed_cards[i].config.driver_use_2 = hw_config->driver_use_2;
snd_installed_cards[i].config.card_subtype = hw_config->card_subtype;
if ((drv = snd_find_driver(snd_installed_cards[i].card_type)) == -1)
snd_installed_cards[i].enabled = 0; /*
* Mark as not detected
*/
else
{
DEB(printk(KERN_DEBUG "Located card - calling attach routine\n"));
sound_drivers[drv].attach(hw_config);
DEB(printk("attach routine finished\n"));
}
start_services();
return 1;
}
}
DEB(printk("sndtable_init_card: No card defined with type=%d, num cards: %d\n", unit, num_sound_cards));
return 0;
}
int sndtable_get_cardcount(void)
{
return num_audiodevs + num_mixers + num_synths + num_midis;
}
int sndtable_identify_card(char *name)
{
int i, n = num_sound_drivers;
if (name == NULL)
return 0;
for (i = 0; i < n; i++)
{
if (sound_drivers[i].driver_id != NULL)
{
char *id = sound_drivers[i].driver_id;
int j;
for (j = 0; j < 80 && name[j] == id[j]; j++)
if (id[j] == 0 && name[j] == 0) /* Match */
return sound_drivers[i].card_type;
}
}
return 0;
}
static int __init sound_setup(char *str)
{
int i, n = num_sound_cards;
int ints[32];
str = get_options(str, ARRAY_SIZE(ints), ints);
/*
* First disable all drivers
*/
for (i = 0; i < n && snd_installed_cards[i].card_type; i++)
snd_installed_cards[i].enabled = 0;
if (ints[0] == 0 || ints[1] == 0)
return 1;
/*
* Then enable them one by time
*/
for (i = 1; i <= ints[0]; i++)
{
int card_type, ioaddr, irq, dma, dma2, ptr, j;
unsigned int val;
val = (unsigned int) ints[i];
card_type = (val & 0x0ff00000) >> 20;
if (card_type > 127)
{
/*
* Add any future extensions here
*/
return 1;
}
ioaddr = (val & 0x000fff00) >> 8;
irq = (val & 0x000000f0) >> 4;
dma = (val & 0x0000000f);
dma2 = (val & 0xf0000000) >> 28;
ptr = -1;
for (j = 0; j < n && ptr == -1; j++)
{
if (snd_installed_cards[j].card_type == card_type &&
!snd_installed_cards[j].enabled)/*
* Not already found
*/
ptr = j;
}
if (ptr == -1)
printk(KERN_ERR "Sound: Invalid setup parameter 0x%08x\n", val);
else
{
snd_installed_cards[ptr].enabled = 1;
snd_installed_cards[ptr].config.io_base = ioaddr;
snd_installed_cards[ptr].config.irq = irq;
snd_installed_cards[ptr].config.dma = dma;
snd_installed_cards[ptr].config.dma2 = dma2;
snd_installed_cards[ptr].config.name = NULL;
snd_installed_cards[ptr].config.always_detect = 0;
snd_installed_cards[ptr].config.driver_use_1 = 0;
snd_installed_cards[ptr].config.driver_use_2 = 0;
snd_installed_cards[ptr].config.card_subtype = 0;
}
}
return 1;
}
__setup("sound=", sound_setup);
struct address_info * sound_getconf(int card_type)
{
int j, ptr;
int n = num_sound_cards;
ptr = -1;
for (j = 0; j < n && ptr == -1 && snd_installed_cards[j].card_type; j++)
{
if (snd_installed_cards[j].card_type == card_type)
ptr = j;
}
if (ptr == -1)
return (struct address_info *) NULL;
return &snd_installed_cards[ptr].config;
}
int sound_install_audiodrv(int vers, char *name, struct audio_driver *driver,
int driver_size, int flags, unsigned int format_mask,
void *devc, int dma1, int dma2)
......@@ -619,4 +236,3 @@ void sound_unload_timerdev(int dev)
if (dev != -1)
sound_timer_devs[dev] = NULL;
}
This diff is collapsed.
/*
* gus.h
*
* Copyright: Christoph Hellwig <chhellwig@gmx.net>
*
*/
#include "ad1848.h"
/* From gus_card.c */
int gus_set_midi_irq(int num);
void gusintr(int irq, void *dev_id, struct pt_regs * dummy);
/* From gus_wave.c */
int gus_wave_detect(int baseaddr);
void gus_wave_init(struct address_info *hw_config);
void gus_wave_unload (struct address_info *hw_config);
void gus_voice_irq(void);
void gus_write8(int reg, unsigned int data);
void guswave_dma_irq(void);
void gus_delay(void);
int gus_default_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg);
void gus_timer_command (unsigned int addr, unsigned int val);
/* From gus_midi.c */
void gus_midi_init(struct address_info *hw_config);
void gus_midi_interrupt(int dummy);
/* From ics2101.c */
int ics2101_mixer_init(void);
......@@ -2,18 +2,13 @@
* sound/gus_card.c
*
* Detection routine for the Gravis Ultrasound.
*/
/*
*
* Copyright (C) by Hannu Savolainen 1993-1997
*
* OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
* Version 2 (June 1991). See the "COPYING" file distributed with this software
* for more info.
*/
/*
*
* Frank van de Pol : Fixed GUS MAX interrupt handling, enabled simultanious
* usage of CS4231A codec, GUS wave and MIDI for GUS MAX.
* Christoph Hellwig: Adapted to module_init/module_exit, simple cleanups.
*
* Status:
* Tested...
......@@ -21,11 +16,13 @@
#include <linux/config.h>
#include <linux/init.h>
#include <linux/module.h>
#include "sound_config.h"
#include "soundmodule.h"
#include "gus.h"
#include "gus_hw.h"
void gusintr(int irq, void *dev_id, struct pt_regs *dummy);
......@@ -36,13 +33,12 @@ extern int gus_wave_volume;
extern int gus_pcm_volume;
extern int have_gus_max;
int gus_pnp_flag = 0;
#ifdef CONFIG_GUS16
#ifdef CONFIG_SOUND_GUS16
static int db16 = 0; /* Has a Gus16 AD1848 on it */
#endif
void attach_gus_card(struct address_info *hw_config)
static void __init attach_gus(struct address_info *hw_config)
{
gus_wave_init(hw_config);
request_region(hw_config->io_base, 16, "GUS");
......@@ -57,9 +53,10 @@ void attach_gus_card(struct address_info *hw_config)
if(request_irq(hw_config->irq, gusintr, 0, "Gravis Ultrasound", hw_config)<0)
printk(KERN_ERR "gus_card.c: Unable to allocate IRQ %d\n", hw_config->irq);
return;
}
int probe_gus(struct address_info *hw_config)
static int __init probe_gus(struct address_info *hw_config)
{
int irq;
int io_addr;
......@@ -102,10 +99,11 @@ int probe_gus(struct address_info *hw_config)
}
#endif
printk("NO GUS card found !\n");
return 0;
}
void unload_gus(struct address_info *hw_config)
static void __exit unload_gus(struct address_info *hw_config)
{
DDB(printk("unload_gus(%x)\n", hw_config->io_base));
......@@ -128,13 +126,13 @@ void gusintr(int irq, void *dev_id, struct pt_regs *dummy)
sti();
#ifdef CONFIG_GUSMAX
#ifdef CONFIG_SOUND_GUSMAX
if (have_gus_max) {
struct address_info *hw_config = dev_id;
adintr(irq, (void *)hw_config->slots[1], NULL);
}
#endif
#ifdef CONFIG_GUS16
#ifdef CONFIG_SOUND_GUS16
if (db16) {
struct address_info *hw_config = dev_id;
adintr(irq, (void *)hw_config->slots[3], NULL);
......@@ -170,14 +168,14 @@ void gusintr(int irq, void *dev_id, struct pt_regs *dummy)
* Some extra code for the 16 bit sampling option
*/
#ifdef CONFIG_GUS16
#ifdef CONFIG_SOUND_GUS16
int probe_gus_db16(struct address_info *hw_config)
static int __init probe_gus_db16(struct address_info *hw_config)
{
return ad1848_detect(hw_config->io_base, NULL, hw_config->osp);
}
void attach_gus_db16(struct address_info *hw_config)
static void __init attach_gus_db16(struct address_info *hw_config)
{
gus_pcm_volume = 100;
gus_wave_volume = 90;
......@@ -189,7 +187,7 @@ void attach_gus_db16(struct address_info *hw_config)
hw_config->osp);
}
void unload_gus_db16(struct address_info *hw_config)
static void __exit unload_gus_db16(struct address_info *hw_config)
{
ad1848_unload(hw_config->io_base,
......@@ -200,27 +198,25 @@ void unload_gus_db16(struct address_info *hw_config)
}
#endif
static int gus16 = 0;
#ifdef CONFIG_SOUND_GUSMAX
static int no_wave_dma = 0;/* Set if no dma is to be used for the
wave table (GF1 chip) */
#endif
#ifdef MODULE
static struct address_info config;
/*
* Note DMA2 of -1 has the right meaning in the GUS driver as well
* as here.
*/
int io = -1;
int irq = -1;
int dma = -1;
int dma16 = -1; /* Set this for modules that need it */
int type = 0; /* 1 for PnP */
int gus16 = 0;
#ifdef CONFIG_GUSMAX
static int no_wave_dma = 0;/* Set if no dma is to be used for the
wave table (GF1 chip) */
#endif
static struct address_info cfg;
static int __initdata io = -1;
static int __initdata irq = -1;
static int __initdata dma = -1;
static int __initdata dma16 = -1; /* Set this for modules that need it */
static int __initdata type = 0; /* 1 for PnP */
MODULE_PARM(io, "i");
MODULE_PARM(irq, "i");
......@@ -228,54 +224,73 @@ MODULE_PARM(dma, "i");
MODULE_PARM(dma16, "i");
MODULE_PARM(type, "i");
MODULE_PARM(gus16, "i");
#ifdef CONFIG_GUSMAX
#ifdef CONFIG_SOUND_GUSMAX
MODULE_PARM(no_wave_dma, "i");
#endif
#ifdef CONFIG_GUS16
#ifdef CONFIG_SOUND_GUS16
MODULE_PARM(db16, "i");
#endif
int init_module(void)
static int __init init_gus(void)
{
printk(KERN_INFO "Gravis Ultrasound audio driver Copyright (C) by Hannu Savolainen 1993-1996\n");
if (io == -1 || dma == -1 || irq == -1)
{
cfg.io_base = io;
cfg.irq = irq;
cfg.dma = dma;
cfg.dma2 = dma16;
cfg.card_subtype = type;
#ifdef CONFIG_SOUND_GUSMAX
gus_no_wave_dma = no_wave_dma;
#endif
if (cfg.io_base == -1 || cfg.dma == -1 || cfg.irq == -1) {
printk(KERN_ERR "I/O, IRQ, and DMA are mandatory\n");
return -EINVAL;
}
config.io_base = io;
config.irq = irq;
config.dma = dma;
config.dma2 = dma16;
config.card_subtype = type;
#ifdef CONFIG_GUSMAX
gus_no_wave_dma = no_wave_dma;
#endif
#if defined(CONFIG_GUS16)
if (probe_gus_db16(&config) && gus16)
{
attach_gus_db16(&config);
#ifdef CONFIG_SOUND_GUS16
if (probe_gus_db16(&cfg) && gus16) {
/* FIXME: This can't work, can it ? -- Christoph */
attach_gus_db16(&cfg);
db16 = 1;
}
#endif
if (probe_gus(&config) == 0)
if (!probe_gus(&cfg))
return -ENODEV;
attach_gus_card(&config);
attach_gus(&cfg);
SOUND_LOCK;
return 0;
}
void cleanup_module(void)
static void __exit cleanup_gus(void)
{
#if defined(CONFIG_GUS16)
#ifdef CONFIG_SOUND_GUS16
if (db16)
unload_gus_db16(&config);
unload_gus_db16(&cfg);
#endif
unload_gus(&config);
unload_gus(&cfg);
SOUND_LOCK_END;
}
#endif /* MODULE */
module_init(init_gus);
module_exit(cleanup_gus);
#ifndef MODULE
static int __init setup_gus(char *str)
{
/* io, irq, dma, dma2 */
int ints[5];
str = get_options(str, ARRAY_SIZE(ints), ints);
io = ints[1];
irq = ints[2];
dma = ints[3];
dma16 = ints[4];
return 1;
}
__setup("gus=", setup_gus);
#endif
......@@ -2,8 +2,8 @@
* sound/gus2_midi.c
*
* The low level driver for the GUS Midi Interface.
*/
/*
*
*
* Copyright (C) by Hannu Savolainen 1993-1997
*
* OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
......@@ -11,6 +11,8 @@
* for more info.
*/
#include "sound_config.h"
#include "gus.h"
#include "gus_hw.h"
static int midi_busy = 0, input_opened = 0;
......
/*
* gus_vol.c - Compute volume for GUS.
*/
/*
*
*
* Copyright (C) by Hannu Savolainen 1993-1997
*
* OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
......@@ -10,6 +10,8 @@
* for more info.
*/
#include "sound_config.h"
#include "gus.h"
#include "gus_linearvol.h"
#define GUS_VOLUME gus_wave_volume
......
......@@ -2,15 +2,15 @@
* sound/gus_wave.c
*
* Driver for the Gravis UltraSound wave table synth.
*/
/*
*
*
* Copyright (C) by Hannu Savolainen 1993-1997
*
* OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
* Version 2 (June 1991). See the "COPYING" file distributed with this software
* for more info.
*/
/*
*
*
* Thomas Sailer : ioctl code reworked (vmalloc/vfree removed)
* Frank van de Pol : Fixed GUS MAX interrupt handling. Enabled simultanious
* usage of CS4231A codec, GUS wave and MIDI for GUS MAX.
......@@ -23,6 +23,8 @@
#include "sound_config.h"
#include <linux/ultrasound.h>
#include "gus.h"
#include "gus_hw.h"
#define GUS_BANK_SIZE (((iw_mode) ? 256*1024*1024 : 256*1024))
......@@ -3012,7 +3014,7 @@ void gus_wave_init(struct address_info *hw_config)
model_num = "MAX";
gus_type = 0x40;
mixer_type = CS4231;
#ifdef CONFIG_GUSMAX
#ifdef CONFIG_SOUND_GUSMAX
{
unsigned char max_config = 0x40; /* Codec enable */
......@@ -3164,7 +3166,7 @@ void gus_wave_init(struct address_info *hw_config)
void gus_wave_unload(struct address_info *hw_config)
{
#ifdef CONFIG_GUSMAX
#ifdef CONFIG_SOUND_GUSMAX
if (have_gus_max)
{
ad1848_unload(gus_base + 0x10c,
......
......@@ -2,20 +2,22 @@
* sound/ics2101.c
*
* Driver for the ICS2101 mixer of GUS v3.7.
*/
/*
*
*
* Copyright (C) by Hannu Savolainen 1993-1997
*
* OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
* Version 2 (June 1991). See the "COPYING" file distributed with this software
* for more info.
*/
/*
*
*
* Thomas Sailer : ioctl code reworked (vmalloc/vfree removed)
*/
#include "sound_config.h"
#include <linux/ultrasound.h>
#include "gus.h"
#include "gus_hw.h"
#define MIX_DEVS (SOUND_MASK_MIC|SOUND_MASK_LINE| \
......
/*
* Copyright (C) by Hannu Savolainen 1993-1997
*
* OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
* Version 2 (June 1991). See the "COPYING" file distributed with this software
* for more info.
*/
#include <linux/config.h>
#include <linux/module.h>
/*
* sound/mad16.c
* mad16.c
*
* Initialization code for OPTi MAD16 compatible audio chips. Including
*
......@@ -72,22 +65,23 @@
*
* Paul Grayson Added support for Midi on later Mozart cards.
* 25-Nov-1999
* Christoph Hellwig Adapted to module_init/module_exit.
*/
#include <linux/config.h>
#include <linux/init.h>
#include <linux/module.h>
#include "sound_config.h"
#include "soundmodule.h"
#ifdef MODULE
#define MAD16_CDSEL mad16_cdsel
#define MAD16_CONF mad16_conf
#include "ad1848.h"
#include "sb.h"
#include "mpu401.h"
static int mad16_conf;
static int mad16_cdsel;
#endif
#include "sb.h"
static int already_initialized = 0;
#define C928 1
......@@ -222,7 +216,7 @@ static void mad_write(int port, int value)
restore_flags(flags);
}
static int detect_c930(void)
static int __init detect_c930(void)
{
unsigned char tmp = mad_read(MC1_PORT);
......@@ -295,7 +289,7 @@ static int detect_c930(void)
return 1;
}
static int detect_mad16(void)
static int __init detect_mad16(void)
{
unsigned char tmp, tmp2, bit;
int i, port;
......@@ -346,7 +340,7 @@ static int detect_mad16(void)
return 1; /* Bingo */
}
static int wss_init(struct address_info *hw_config)
static int __init wss_init(struct address_info *hw_config)
{
int ad_flags = 0;
......@@ -397,7 +391,7 @@ static int wss_init(struct address_info *hw_config)
return 1;
}
static int init_c930(struct address_info *hw_config)
static int __init init_c930(struct address_info *hw_config)
{
unsigned char cfg = 0;
......@@ -457,7 +451,7 @@ static int init_c930(struct address_info *hw_config)
return wss_init(hw_config);
}
static int chip_detect(void)
static int __init chip_detect(void)
{
int i;
......@@ -536,7 +530,7 @@ static int chip_detect(void)
return 1;
}
int probe_mad16(struct address_info *hw_config)
static int __init probe_mad16(struct address_info *hw_config)
{
int i;
static int valid_ports[] =
......@@ -646,7 +640,7 @@ int probe_mad16(struct address_info *hw_config)
return 1;
}
void attach_mad16(struct address_info *hw_config)
static void __init attach_mad16(struct address_info *hw_config)
{
static char interrupt_bits[12] = {
......@@ -720,7 +714,7 @@ void attach_mad16(struct address_info *hw_config)
request_region(hw_config->io_base, 4, "MAD16 WSS config");
}
void attach_mad16_mpu(struct address_info *hw_config)
static void __init attach_mad16_mpu(struct address_info *hw_config)
{
#ifdef CONFIG_MAD16_OLDCARD
......@@ -742,7 +736,7 @@ void attach_mad16_mpu(struct address_info *hw_config)
attach_uart401(hw_config);
}
int probe_mad16_mpu(struct address_info *hw_config)
static int __init probe_mad16_mpu(struct address_info *hw_config)
{
static int mpu_attached = 0;
static int valid_ports[] = {
......@@ -898,7 +892,7 @@ int probe_mad16_mpu(struct address_info *hw_config)
return probe_uart401(hw_config);
}
void unload_mad16(struct address_info *hw_config)
static void __exit unload_mad16(struct address_info *hw_config)
{
ad1848_unload(hw_config->io_base + 4,
hw_config->irq,
......@@ -908,8 +902,7 @@ void unload_mad16(struct address_info *hw_config)
sound_unload_audiodev(hw_config->slots[0]);
}
void
unload_mad16_mpu(struct address_info *hw_config)
static void __exit unload_mad16_mpu(struct address_info *hw_config)
{
#ifdef CONFIG_MAD16_OLDCARD
if (board_type < C929) /* Early chip. No MPU support. Just SB MIDI */
......@@ -922,21 +915,23 @@ unload_mad16_mpu(struct address_info *hw_config)
unload_uart401(hw_config);
}
#ifdef MODULE
static struct address_info cfg;
static struct address_info cfg_mpu;
int mpu_io = 0;
int mpu_irq = 0;
int io = -1;
int dma = -1;
int dma16 = -1; /* Set this for modules that need it */
int irq = -1;
static int found_mpu;
int cdtype = 0;
int cdirq = 0;
int cdport = 0x340;
int cddma = -1;
int opl4 = 0;
int joystick = 0;
static int __initdata mpu_io = 0;
static int __initdata mpu_irq = 0;
static int __initdata io = -1;
static int __initdata dma = -1;
static int __initdata dma16 = -1; /* Set this for modules that need it */
static int __initdata irq = -1;
static int __initdata cdtype = 0;
static int __initdata cdirq = 0;
static int __initdata cdport = 0x340;
static int __initdata cddma = -1;
static int __initdata opl4 = 0;
static int __initdata joystick = 0;
MODULE_PARM(mpu_io, "i");
MODULE_PARM(mpu_irq, "i");
......@@ -952,18 +947,13 @@ MODULE_PARM(opl4,"i");
MODULE_PARM(joystick,"i");
MODULE_PARM(debug,"i");
EXPORT_NO_SYMBOLS;
static int found_mpu;
static int dma_map[2][8] =
static int __initdata dma_map[2][8] =
{
{0x03, -1, -1, -1, -1, 0x00, 0x01, 0x02},
{0x03, -1, 0x01, 0x00, -1, -1, -1, -1}
};
static int irq_map[16] =
static int __initdata irq_map[16] =
{
0x00, -1, -1, 0x0A,
-1, 0x04, -1, 0x08,
......@@ -971,20 +961,12 @@ static int irq_map[16] =
-1, -1, -1, -1
};
struct address_info config;
struct address_info config_mpu;
int init_module(void)
static int __init init_mad16(void)
{
int dmatype = 0;
printk(KERN_INFO "MAD16 audio driver Copyright (C) by Hannu Savolainen 1993-1996\n");
if (io == -1 || dma == -1 || irq == -1)
{
printk(KERN_ERR "I/O, DMA and irq are mandatory\n");
return -EINVAL;
}
printk(KERN_INFO "CDROM ");
switch (cdtype)
{
......@@ -1089,33 +1071,61 @@ int init_module(void)
printk("disabled.\n");
}
config.io_base = io;
config.irq = irq;
config.dma = dma;
config.dma2 = dma16;
cfg.io_base = io;
cfg.irq = irq;
cfg.dma = dma;
cfg.dma2 = dma16;
if (!probe_mad16(&config))
if (cfg.io_base == -1 || cfg.dma == -1 || cfg.irq == -1) {
printk(KERN_ERR "I/O, DMA and irq are mandatory\n");
return -EINVAL;
}
if (!probe_mad16(&cfg))
return -ENODEV;
config_mpu.io_base = mpu_io;
config_mpu.irq = mpu_irq;
attach_mad16(&config);
cfg_mpu.io_base = mpu_io;
cfg_mpu.irq = mpu_irq;
attach_mad16(&cfg);
found_mpu = probe_mad16_mpu(&config_mpu);
found_mpu = probe_mad16_mpu(&cfg_mpu);
if (found_mpu)
attach_mad16_mpu(&config_mpu);
attach_mad16_mpu(&cfg_mpu);
SOUND_LOCK;
return 0;
}
void cleanup_module(void)
static void __exit cleanup_mad16(void)
{
if (found_mpu)
unload_mad16_mpu(&config_mpu);
unload_mad16(&config);
unload_mad16_mpu(&cfg_mpu);
unload_mad16(&cfg);
SOUND_LOCK_END;
}
#endif /* MODULE */
module_init(init_mad16);
module_exit(exit_mad16);
#ifndef MODULE
static int __init setup_mad16(char *str)
{
/* io, irq */
int ints[7];
str = get_options(str, ARRAY_SIZE(ints), ints);
io = ints[1];
irq = ints[2];
dma = ints[3];
dma16 = ints[4];
mpu_io = ints[5];
mpu_irq = ints[6];
return 1;
}
__setup("mad16=", setup_mad16);
#endif
......@@ -2,8 +2,8 @@
* sound/maui.c
*
* The low level driver for Turtle Beach Maui and Tropez.
*/
/*
*
*
* Copyright (C) by Hannu Savolainen 1993-1997
*
* OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
......@@ -13,6 +13,7 @@
* Changes:
* Alan Cox General clean up, use kernel IRQ
* system
* Christoph Hellwig Adapted to module_init/module_exit
*
* Status:
* Andrew J. Kroll Tested 06/01/1999 with:
......@@ -32,6 +33,8 @@
#include "soundmodule.h"
#include "sound_firmware.h"
#include "mpu401.h"
static int maui_base = 0x330;
static volatile int irq_ok = 0;
......@@ -62,19 +65,14 @@ static int maui_wait(int mask)
*/
for (i = 0; i < 100; i++)
{
if (inb(HOST_STAT_PORT) & mask)
{
return 1;
}
}
/*
* Wait up to 15 seconds with sleeping
*/
for (i = 0; i < 150; i++)
{
for (i = 0; i < 150; i++) {
if (inb(HOST_STAT_PORT) & mask)
return 1;
current->state = TASK_INTERRUPTIBLE;
......@@ -94,8 +92,7 @@ static int maui_read(void)
static int maui_write(unsigned char data)
{
if (maui_wait(STAT_TX_AVAIL))
{
if (maui_wait(STAT_TX_AVAIL)) {
outb((data), HOST_DATA_PORT);
return 1;
}
......@@ -116,56 +113,45 @@ static int download_code(void)
printk(KERN_INFO "Code download (%d bytes): ", maui_osLen);
for (i = 0; i < maui_osLen; i++)
{
if (maui_os[i] != '\r')
{
if (!skip || (maui_os[i] == 'S' && (i == 0 || maui_os[i - 1] == '\n')))
{
for (i = 0; i < maui_osLen; i++) {
if (maui_os[i] != '\r') {
if (!skip || (maui_os[i] == 'S' && (i == 0 || maui_os[i - 1] == '\n'))) {
skip = 0;
if (maui_os[i] == '\n')
eol_seen = skip = 1;
else if (maui_os[i] == 'S')
{
else if (maui_os[i] == 'S') {
if (maui_os[i + 1] == '8')
done = 1;
if (!maui_write(0xF1))
goto failure;
if (!maui_write('S'))
goto failure;
}
else
{
} else {
if (!maui_write(maui_os[i]))
goto failure;
}
if (eol_seen)
{
if (eol_seen) {
int c = 0;
int n;
eol_seen = 0;
for (n = 0; n < 2; n++)
{
if (maui_wait(STAT_RX_AVAIL))
{
for (n = 0; n < 2; n++) {
if (maui_wait(STAT_RX_AVAIL)) {
c = inb(HOST_DATA_PORT);
break;
}
}
if (c != 0x80)
{
if (c != 0x80) {
printk("Download not acknowledged\n");
return 0;
}
else if (!(lines++ % 10))
printk(".");
if (done)
{
if (done) {
printk("\n");
printk(KERN_INFO "Download complete\n");
return 1;
......@@ -181,15 +167,11 @@ static int download_code(void)
return 0;
}
static int maui_init(int irq)
static int __init maui_init(int irq)
{
#ifdef CONFIG_SMP
int i;
#endif
unsigned char bits;
switch (irq)
{
switch (irq) {
case 9:
bits = 0x00;
break;
......@@ -215,10 +197,13 @@ static int maui_init(int irq)
outb((0xD0), HOST_CTRL_PORT); /* Cause interrupt */
#ifdef CONFIG_SMP
for (i = 0; i < 1000000 && !irq_ok; i++);
if (!irq_ok)
return 0;
{
int i;
for (i = 0; i < 1000000 && !irq_ok; i++)
;
if (!irq_ok)
return 0;
}
#endif
outb((0x80), HOST_CTRL_PORT); /* Leave reset */
......@@ -233,8 +218,7 @@ static int maui_init(int irq)
maui_write(0xf0);
maui_write(1);
if (maui_read() != 0x80)
{
if (maui_read() != 0x80) {
maui_write(0xf0);
maui_write(1);
if (maui_read() != 0x80)
......@@ -244,14 +228,11 @@ static int maui_init(int irq)
return 1;
}
static int maui_short_wait(int mask)
{
static int maui_short_wait(int mask) {
int i;
for (i = 0; i < 1000; i++)
{
if (inb(HOST_STAT_PORT) & mask)
{
for (i = 0; i < 1000; i++) {
if (inb(HOST_STAT_PORT) & mask) {
return 1;
}
}
......@@ -274,8 +255,7 @@ static int maui_load_patch(int dev, int format, const char *addr,
{
printk(KERN_WARNING "Maui: Unknown patch format\n");
}
if (count < hdr_size)
{
if (count < hdr_size) {
/* printk("Maui error: Patch header too short\n");*/
return -EINVAL;
}
......@@ -289,16 +269,14 @@ static int maui_load_patch(int dev, int format, const char *addr,
if(copy_from_user(&((char *) &header)[offs], &(addr)[offs], hdr_size - offs))
return -EFAULT;
if (count < header.len)
{
if (count < header.len) {
printk(KERN_ERR "Maui warning: Host command record too short (%d<%d)\n", count, (int) header.len);
header.len = count;
}
left = header.len;
src_offs = 0;
for (i = 0; i < left; i++)
{
for (i = 0; i < left; i++) {
unsigned char data;
if(get_user(*(unsigned char *) &data, (unsigned char *) &((addr)[hdr_size + i])))
......@@ -310,8 +288,7 @@ static int maui_load_patch(int dev, int format, const char *addr,
return -EIO;
}
if ((i = maui_read()) != 0x80)
{
if ((i = maui_read()) != 0x80) {
if (i != -1)
printk("Maui: Error status %02x\n", i);
return -EIO;
......@@ -319,7 +296,7 @@ static int maui_load_patch(int dev, int format, const char *addr,
return 0;
}
int probe_maui(struct address_info *hw_config)
static int __init probe_maui(struct address_info *hw_config)
{
int i;
int tmp1, tmp2, ret;
......@@ -337,55 +314,46 @@ int probe_maui(struct address_info *hw_config)
* Initialize the processor if necessary
*/
if (maui_osLen > 0)
{
if (maui_osLen > 0) {
if (!(inb(HOST_STAT_PORT) & STAT_TX_AVAIL) ||
!maui_write(0x9F) || /* Report firmware version */
!maui_short_wait(STAT_RX_AVAIL) ||
maui_read() == -1 || maui_read() == -1)
if (!maui_init(hw_config->irq))
{
if (!maui_init(hw_config->irq)) {
free_irq(hw_config->irq, NULL);
return 0;
}
}
if (!maui_write(0xCF)) /* Report hardware version */
{
if (!maui_write(0xCF)) /* Report hardware version */ {
printk(KERN_ERR "No WaveFront firmware detected (card uninitialized?)\n");
free_irq(hw_config->irq, NULL);
return 0;
}
if ((tmp1 = maui_read()) == -1 || (tmp2 = maui_read()) == -1)
{
if ((tmp1 = maui_read()) == -1 || (tmp2 = maui_read()) == -1) {
printk(KERN_ERR "No WaveFront firmware detected (card uninitialized?)\n");
free_irq(hw_config->irq, NULL);
return 0;
}
if (tmp1 == 0xff || tmp2 == 0xff)
{
if (tmp1 == 0xff || tmp2 == 0xff) {
free_irq(hw_config->irq, NULL);
return 0;
}
if (trace_init)
printk(KERN_DEBUG "WaveFront hardware version %d.%d\n", tmp1, tmp2);
printk(KERN_DEBUG "WaveFront hardware version %d.%d\n", tmp1, tmp2);
if (!maui_write(0x9F)) /* Report firmware version */
return 0;
if ((tmp1 = maui_read()) == -1 || (tmp2 = maui_read()) == -1)
return 0;
if (trace_init)
printk(KERN_DEBUG "WaveFront firmware version %d.%d\n", tmp1, tmp2);
printk(KERN_DEBUG "WaveFront firmware version %d.%d\n", tmp1, tmp2);
if (!maui_write(0x85)) /* Report free DRAM */
return 0;
tmp1 = 0;
for (i = 0; i < 4; i++)
{
for (i = 0; i < 4; i++) {
tmp1 |= maui_read() << (7 * i);
}
if (trace_init)
printk(KERN_DEBUG "Available DRAM %dk\n", tmp1 / 1024);
printk(KERN_DEBUG "Available DRAM %dk\n", tmp1 / 1024);
for (i = 0; i < 1000; i++)
if (probe_mpu401(hw_config))
......@@ -399,7 +367,7 @@ int probe_maui(struct address_info *hw_config)
return ret;
}
void attach_maui(struct address_info *hw_config)
static void __init attach_maui(struct address_info *hw_config)
{
int this_dev;
......@@ -409,8 +377,7 @@ void attach_maui(struct address_info *hw_config)
hw_config->name = "Maui";
attach_mpu401(hw_config);
if (hw_config->slots[1] != -1) /* The MPU401 driver installed itself */
{
if (hw_config->slots[1] != -1) /* The MPU401 driver installed itself */ {
struct synth_operations *synth;
this_dev = hw_config->slots[1];
......@@ -423,17 +390,15 @@ void attach_maui(struct address_info *hw_config)
synth = midi_devs[this_dev]->converter;
synth->id = "MAUI";
if (synth != NULL)
{
if (synth != NULL) {
orig_load_patch = synth->load_patch;
synth->load_patch = &maui_load_patch;
}
else
} else
printk(KERN_ERR "Maui: Can't install patch loader\n");
}
}
void unload_maui(struct address_info *hw_config)
static void __exit unload_maui(struct address_info *hw_config)
{
int irq = hw_config->irq;
release_region(hw_config->io_base + 2, 6);
......@@ -445,37 +410,33 @@ void unload_maui(struct address_info *hw_config)
free_irq(irq, NULL);
}
#ifdef MODULE
MODULE_PARM(io,"i");
MODULE_PARM(irq,"i");
EXPORT_NO_SYMBOLS;
static int fw_load = 0;
int io = -1;
int irq = -1;
static struct address_info cfg;
static int fw_load = 0;
static int __initdata io = -1;
static int __initdata irq = -1;
struct address_info cfg;
MODULE_PARM(io,"i");
MODULE_PARM(irq,"i");
/*
* Install a Maui card. Needs mpu401 loaded already.
*/
int init_module(void)
static int __init init_maui(void)
{
printk(KERN_INFO "Turtle beach Maui and Tropez driver, Copyright (C) by Hannu Savolainen 1993-1996\n");
if (io == -1 || irq == -1)
{
cfg.io_base = io;
cfg.irq = irq;
if (cfg.io_base == -1 || cfg.irq == -1) {
printk(KERN_INFO "maui: irq and io must be set.\n");
return -EINVAL;
}
cfg.io_base = io;
cfg.irq = irq;
if (maui_os == NULL)
{
if (maui_os == NULL) {
fw_load = 1;
maui_osLen = mod_firmware_load("/etc/sound/oswf.mot", (char **) &maui_os);
}
......@@ -486,11 +447,30 @@ int init_module(void)
return 0;
}
void cleanup_module(void)
static void __exit cleanup_maui(void)
{
if (fw_load && maui_os)
vfree(maui_os);
unload_maui(&cfg);
SOUND_LOCK_END;
}
#endif /* MODULE */
module_init(init_maui);
module_exit(cleanup_maui);
#ifndef MODULE
static int __init setup_maui(char *str)
{
/* io, irq */
int ints[3];
str = get_options(str, ARRAY_SIZE(ints), ints);
io = ints[1];
irq = ints[2];
return 1;
}
__setup("maui=", setup_maui);
#endif
......@@ -15,6 +15,7 @@
* Alan Cox modularisation, use normal request_irq, use dev_id
*/
#include <linux/init.h>
#include <linux/module.h>
#define USE_SEQ_MACROS
......@@ -24,7 +25,7 @@
#include "soundmodule.h"
#include "coproc.h"
#include "mpu401.h"
static int timer_mode = TMR_INTERNAL, timer_caps = TMR_INTERNAL;
......@@ -910,7 +911,7 @@ static struct midi_operations mpu401_midi_proto =
static struct midi_operations mpu401_midi_operations[MAX_MIDI_DEV];
static void mpu401_chk_version(int n, struct mpu_config *devc)
static void __init mpu401_chk_version(int n, struct mpu_config *devc)
{
int tmp;
unsigned long flags;
......@@ -941,7 +942,7 @@ static void mpu401_chk_version(int n, struct mpu_config *devc)
restore_flags(flags);
}
void attach_mpu401(struct address_info *hw_config)
void __init attach_mpu401(struct address_info *hw_config)
{
unsigned long flags;
char revision_char;
......@@ -1164,7 +1165,7 @@ static void set_uart_mode(int dev, struct mpu_config *devc, int arg)
}
int probe_mpu401(struct address_info *hw_config)
int __init probe_mpu401(struct address_info *hw_config)
{
int ok = 0;
struct mpu_config tmp_devc;
......@@ -1197,7 +1198,7 @@ int probe_mpu401(struct address_info *hw_config)
return ok;
}
void unload_mpu401(struct address_info *hw_config)
void __exit unload_mpu401(struct address_info *hw_config)
{
void *p;
int n=hw_config->slots[1];
......@@ -1659,7 +1660,7 @@ static void timer_ext_event(struct mpu_config *devc, int event, int parm)
}
}
static int mpu_timer_init(int midi_dev)
static int __init mpu_timer_init(int midi_dev)
{
struct mpu_config *devc;
int n;
......@@ -1713,39 +1714,56 @@ EXPORT_SYMBOL(unload_mpu401);
EXPORT_SYMBOL(intchk_mpu401);
EXPORT_SYMBOL(mpuintr);
#ifdef MODULE
static struct address_info cfg;
static int __initdata io = -1;
static int __initdata irq = -1;
MODULE_PARM(irq, "i");
MODULE_PARM(io, "i");
int io = -1;
int irq = -1;
struct address_info hw;
int init_module(void)
int init_mpu401(void)
{
/* Can be loaded either for module use or to provide functions
to others */
if (io != -1 && irq != -1)
{
hw.irq = irq;
hw.io_base = io;
if (probe_mpu401(&hw) == 0)
return -ENODEV;
attach_mpu401(&hw);
cfg.irq = irq;
cfg.io_base = io;
if (cfg.io_base != -1 && cfg.irq != -1) {
printk(KERN_WARNING "mpu401: need io and irq !");
return -ENODEV;
}
if (probe_mpu401(&cfg) == 0)
return -ENODEV;
attach_mpu401(&cfg);
SOUND_LOCK;
return 0;
}
void cleanup_module(void)
void cleanup_mpu401(void)
{
if (io != -1 && irq != -1)
{
unload_mpu401(&hw);
}
/* FREE SYMTAB */
unload_mpu401(&cfg);
SOUND_LOCK_END;
}
#endif /* MODULE */
module_init(init_mpu401);
module_exit(cleanup_mpu401);
#ifndef MODULE
static int __init setup_mpu401(char *str)
{
/* io, irq */
int ints[3];
str = get_options(str, ARRAY_SIZE(ints), ints);
io = ints[1];
irq = ints[2];
return 1;
}
__setup("mpu401=", setup_mpu401);
#endif
/*
* uart401.h
*
* Copyright: Christoph Hellwig <chhellwig@gmx.net>
*
*/
/* From uart401.c */
int probe_uart401 (struct address_info *hw_config);
void attach_uart401 (struct address_info *hw_config);
void unload_uart401 (struct address_info *hw_config);
void uart401intr (int irq, void *dev_id, struct pt_regs * dummy);
/* From mpu401.c */
int probe_mpu401(struct address_info *hw_config);
void attach_mpu401(struct address_info * hw_config);
void unload_mpu401(struct address_info *hw_info);
int intchk_mpu401(void *dev_id);
void mpuintr(int irq, void *dev_id, struct pt_regs * dummy);
......@@ -15,6 +15,7 @@
#define __NO_VERSION__
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/pm.h>
#include "sound_config.h"
......@@ -1639,8 +1640,6 @@ static struct audio_driver nm256_audio_driver =
EXPORT_SYMBOL(init_nm256);
#ifdef MODULE
static int loaded = 0;
MODULE_PARM (usecache, "i");
......@@ -1648,8 +1647,7 @@ MODULE_PARM (buffertop, "i");
MODULE_PARM (nm256_debug, "i");
MODULE_PARM (force_load, "i");
int
init_module (void)
static int __init do_init_nm256(void)
{
nmcard_list = NULL;
printk (KERN_INFO "NeoMagic 256AV/256ZX audio driver, version 1.1\n");
......@@ -1663,8 +1661,7 @@ init_module (void)
return -ENODEV;
}
void
cleanup_module (void)
static void __exit cleanup_nm256 (void)
{
if (loaded) {
struct nm256_info *card;
......@@ -1688,8 +1685,10 @@ cleanup_module (void)
}
pm_unregister_all (&handle_pm_event);
}
#endif
module_init(do_init_nm256);
module_exit(cleanup_nm256);
/*
* Local variables:
* c-basic-offset: 4
......
......@@ -3,7 +3,7 @@
*
* A low level driver for Yamaha YM3812 and OPL-3 -chips
*
*
*
* Copyright (C) by Hannu Savolainen 1993-1997
*
* OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
......@@ -12,14 +12,16 @@
*
*
* Changes
* Thomas Sailer ioctl code reworked (vmalloc/vfree removed)
* Alan Cox modularisation, fixed sound_mem allocs.
* Thomas Sailer ioctl code reworked (vmalloc/vfree removed)
* Alan Cox modularisation, fixed sound_mem allocs.
* Christoph Hellwig Adapted to module_init/module_exit
*
* Status
* Believed to work. Badly needs rewriting a bit to support multiple
* OPL3 devices.
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/delay.h>
......@@ -32,6 +34,7 @@
#include "soundmodule.h"
#include "opl3.h"
#include "opl3_hw.h"
#define MAX_VOICE 18
#define OFFS_4OP 11
......@@ -1171,18 +1174,19 @@ int opl3_init(int ioaddr, int *osp)
return me;
}
#ifdef MODULE
EXPORT_SYMBOL(opl3_init);
EXPORT_SYMBOL(opl3_detect);
/*
* We provide OPL3 functions.
*/
static int me;
static int io = -1;
int io = -1;
int me;
MODULE_PARM(io, "i");
int init_module (void)
static int __init init_opl3 (void)
{
printk(KERN_INFO "YM3812 and OPL-3 driver Copyright (C) by Hannu Savolainen, Rob Hooft 1993-1996\n");
if (io != -1) /* User loading pure OPL3 module */
{
if (check_region(io, 4))
......@@ -1195,14 +1199,14 @@ int init_module (void)
return -ENODEV;
}
me = opl3_init(io, NULL);
request_region(io,4,devc->fm_info.name);
request_region(io, 4, devc->fm_info.name);
}
SOUND_LOCK;
return 0;
}
void cleanup_module(void)
static void __exit cleanup_opl3(void)
{
if (devc && io != -1)
{
......@@ -1215,10 +1219,21 @@ void cleanup_module(void)
SOUND_LOCK_END;
}
MODULE_PARM(io, "i");
module_init(init_opl3);
module_exit(cleanup_opl3);
#endif /* MODULE */
#ifndef MODULE
static int __init setup_opl3(char *str)
{
/* io */
int ints[2];
str = get_options(str, ARRAY_SIZE(ints), ints);
io = ints[1];
EXPORT_SYMBOL(opl3_init);
EXPORT_SYMBOL(opl3_detect);
return 1;
}
__setup("opl3=", setup_opl3);
#endif
/*
* opl3.h - Definitions of the OPL-3 registers
*/
/*
* Copyright (C) by Hannu Savolainen 1993-1997
*
* OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
* Version 2 (June 1991). See the "COPYING" file distributed with this software
* for more info.
*/
/*
* The OPL-3 mode is switched on by writing 0x01, to the offset 5
* of the right side.
*
* Another special register at the right side is at offset 4. It contains
* a bit mask defining which voices are used as 4 OP voices.
*
* The percussive mode is implemented in the left side only.
*
* With the above exceptions the both sides can be operated independently.
*
* A 4 OP voice can be created by setting the corresponding
* bit at offset 4 of the right side.
* opl3.h
*
* For example setting the rightmost bit (0x01) changes the
* first voice on the right side to the 4 OP mode. The fourth
* voice is made inaccessible.
* Copyright: Christoph Hellwig <chhellwig@gmx.net>
*
* If a voice is set to the 2 OP mode, it works like 2 OP modes
* of the original YM3812 (AdLib). In addition the voice can
* be connected the left, right or both stereo channels. It can
* even be left unconnected. This works with 4 OP voices also.
*
* The stereo connection bits are located in the FEEDBACK_CONNECTION
* register of the voice (0xC0-0xC8). In 4 OP voices these bits are
* in the second half of the voice.
*/
/*
* Register numbers for the global registers
*/
#define TEST_REGISTER 0x01
#define ENABLE_WAVE_SELECT 0x20
#define TIMER1_REGISTER 0x02
#define TIMER2_REGISTER 0x03
#define TIMER_CONTROL_REGISTER 0x04 /* Left side */
#define IRQ_RESET 0x80
#define TIMER1_MASK 0x40
#define TIMER2_MASK 0x20
#define TIMER1_START 0x01
#define TIMER2_START 0x02
#define CONNECTION_SELECT_REGISTER 0x04 /* Right side */
#define RIGHT_4OP_0 0x01
#define RIGHT_4OP_1 0x02
#define RIGHT_4OP_2 0x04
#define LEFT_4OP_0 0x08
#define LEFT_4OP_1 0x10
#define LEFT_4OP_2 0x20
#define OPL3_MODE_REGISTER 0x05 /* Right side */
#define OPL3_ENABLE 0x01
#define OPL4_ENABLE 0x02
#define KBD_SPLIT_REGISTER 0x08 /* Left side */
#define COMPOSITE_SINE_WAVE_MODE 0x80 /* Don't use with OPL-3? */
#define KEYBOARD_SPLIT 0x40
#define PERCOSSION_REGISTER 0xbd /* Left side only */
#define TREMOLO_DEPTH 0x80
#define VIBRATO_DEPTH 0x40
#define PERCOSSION_ENABLE 0x20
#define BASSDRUM_ON 0x10
#define SNAREDRUM_ON 0x08
#define TOMTOM_ON 0x04
#define CYMBAL_ON 0x02
#define HIHAT_ON 0x01
/*
* Offsets to the register banks for operators. To get the
* register number just add the operator offset to the bank offset
*
* AM/VIB/EG/KSR/Multiple (0x20 to 0x35)
*/
#define AM_VIB 0x20
#define TREMOLO_ON 0x80
#define VIBRATO_ON 0x40
#define SUSTAIN_ON 0x20
#define KSR 0x10 /* Key scaling rate */
#define MULTIPLE_MASK 0x0f /* Frequency multiplier */
/*
* KSL/Total level (0x40 to 0x55)
*/
#define KSL_LEVEL 0x40
#define KSL_MASK 0xc0 /* Envelope scaling bits */
#define TOTAL_LEVEL_MASK 0x3f /* Strength (volume) of OP */
/*
* Attack / Decay rate (0x60 to 0x75)
*/
#define ATTACK_DECAY 0x60
#define ATTACK_MASK 0xf0
#define DECAY_MASK 0x0f
/*
* Sustain level / Release rate (0x80 to 0x95)
*/
#define SUSTAIN_RELEASE 0x80
#define SUSTAIN_MASK 0xf0
#define RELEASE_MASK 0x0f
/*
* Wave select (0xE0 to 0xF5)
*/
#define WAVE_SELECT 0xe0
/*
* Offsets to the register banks for voices. Just add to the
* voice number to get the register number.
*
* F-Number low bits (0xA0 to 0xA8).
*/
#define FNUM_LOW 0xa0
/*
* F-number high bits / Key on / Block (octave) (0xB0 to 0xB8)
*/
#define KEYON_BLOCK 0xb0
#define KEYON_BIT 0x20
#define BLOCKNUM_MASK 0x1c
#define FNUM_HIGH_MASK 0x03
/*
* Feedback / Connection (0xc0 to 0xc8)
*
* These registers have two new bits when the OPL-3 mode
* is selected. These bits controls connecting the voice
* to the stereo channels. For 4 OP voices this bit is
* defined in the second half of the voice (add 3 to the
* register offset).
*
* For 4 OP voices the connection bit is used in the
* both halves (gives 4 ways to connect the operators).
*/
#define FEEDBACK_CONNECTION 0xc0
#define FEEDBACK_MASK 0x0e /* Valid just for 1st OP of a voice */
#define CONNECTION_BIT 0x01
/*
* In the 4 OP mode there is four possible configurations how the
* operators can be connected together (in 2 OP modes there is just
* AM or FM). The 4 OP connection mode is defined by the rightmost
* bit of the FEEDBACK_CONNECTION (0xC0-0xC8) on the both halves.
*
* First half Second half Mode
*
* +---+
* v |
* 0 0 >+-1-+--2--3--4-->
*
*
*
* +---+
* | |
* 0 1 >+-1-+--2-+
* |->
* >--3----4-+
*
* +---+
* | |
* 1 0 >+-1-+-----+
* |->
* >--2--3--4-+
*
* +---+
* | |
* 1 1 >+-1-+--+
* |
* >--2--3-+->
* |
* >--4----+
*/
#define STEREO_BITS 0x30 /* OPL-3 only */
#define VOICE_TO_LEFT 0x10
#define VOICE_TO_RIGHT 0x20
/*
* Definition table for the physical voices
*/
struct physical_voice_info {
unsigned char voice_num;
unsigned char voice_mode; /* 0=unavailable, 2=2 OP, 4=4 OP */
unsigned short ioaddr; /* I/O port (left or right side) */
unsigned char op[4]; /* Operator offsets */
};
/*
* There is 18 possible 2 OP voices
* (9 in the left and 9 in the right).
* The first OP is the modulator and 2nd is the carrier.
*
* The first three voices in the both sides may be connected
* with another voice to a 4 OP voice. For example voice 0
* can be connected with voice 3. The operators of voice 3 are
* used as operators 3 and 4 of the new 4 OP voice.
* In this case the 2 OP voice number 0 is the 'first half' and
* voice 3 is the second.
*/
#define USE_LEFT 0
#define USE_RIGHT 1
static struct physical_voice_info pv_map[18] =
{
/* No Mode Side OP1 OP2 OP3 OP4 */
/* --------------------------------------------------- */
{ 0, 2, USE_LEFT, {0x00, 0x03, 0x08, 0x0b}},
{ 1, 2, USE_LEFT, {0x01, 0x04, 0x09, 0x0c}},
{ 2, 2, USE_LEFT, {0x02, 0x05, 0x0a, 0x0d}},
{ 3, 2, USE_LEFT, {0x08, 0x0b, 0x00, 0x00}},
{ 4, 2, USE_LEFT, {0x09, 0x0c, 0x00, 0x00}},
{ 5, 2, USE_LEFT, {0x0a, 0x0d, 0x00, 0x00}},
{ 6, 2, USE_LEFT, {0x10, 0x13, 0x00, 0x00}}, /* Used by percussive voices */
{ 7, 2, USE_LEFT, {0x11, 0x14, 0x00, 0x00}}, /* if the percussive mode */
{ 8, 2, USE_LEFT, {0x12, 0x15, 0x00, 0x00}}, /* is selected */
{ 0, 2, USE_RIGHT, {0x00, 0x03, 0x08, 0x0b}},
{ 1, 2, USE_RIGHT, {0x01, 0x04, 0x09, 0x0c}},
{ 2, 2, USE_RIGHT, {0x02, 0x05, 0x0a, 0x0d}},
{ 3, 2, USE_RIGHT, {0x08, 0x0b, 0x00, 0x00}},
{ 4, 2, USE_RIGHT, {0x09, 0x0c, 0x00, 0x00}},
{ 5, 2, USE_RIGHT, {0x0a, 0x0d, 0x00, 0x00}},
int opl3_detect (int ioaddr, int *osp);
int opl3_init(int ioaddr, int *osp);
{ 6, 2, USE_RIGHT, {0x10, 0x13, 0x00, 0x00}},
{ 7, 2, USE_RIGHT, {0x11, 0x14, 0x00, 0x00}},
{ 8, 2, USE_RIGHT, {0x12, 0x15, 0x00, 0x00}}
};
void enable_opl3_mode(int left, int right, int both);
/*
* opl3_hw.h - Definitions of the OPL-3 registers
*
*
* Copyright (C) by Hannu Savolainen 1993-1997
*
* OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
* Version 2 (June 1991). See the "COPYING" file distributed with this software
* for more info.
*
*
* The OPL-3 mode is switched on by writing 0x01, to the offset 5
* of the right side.
*
* Another special register at the right side is at offset 4. It contains
* a bit mask defining which voices are used as 4 OP voices.
*
* The percussive mode is implemented in the left side only.
*
* With the above exceptions the both sides can be operated independently.
*
* A 4 OP voice can be created by setting the corresponding
* bit at offset 4 of the right side.
*
* For example setting the rightmost bit (0x01) changes the
* first voice on the right side to the 4 OP mode. The fourth
* voice is made inaccessible.
*
* If a voice is set to the 2 OP mode, it works like 2 OP modes
* of the original YM3812 (AdLib). In addition the voice can
* be connected the left, right or both stereo channels. It can
* even be left unconnected. This works with 4 OP voices also.
*
* The stereo connection bits are located in the FEEDBACK_CONNECTION
* register of the voice (0xC0-0xC8). In 4 OP voices these bits are
* in the second half of the voice.
*/
/*
* Register numbers for the global registers
*/
#define TEST_REGISTER 0x01
#define ENABLE_WAVE_SELECT 0x20
#define TIMER1_REGISTER 0x02
#define TIMER2_REGISTER 0x03
#define TIMER_CONTROL_REGISTER 0x04 /* Left side */
#define IRQ_RESET 0x80
#define TIMER1_MASK 0x40
#define TIMER2_MASK 0x20
#define TIMER1_START 0x01
#define TIMER2_START 0x02
#define CONNECTION_SELECT_REGISTER 0x04 /* Right side */
#define RIGHT_4OP_0 0x01
#define RIGHT_4OP_1 0x02
#define RIGHT_4OP_2 0x04
#define LEFT_4OP_0 0x08
#define LEFT_4OP_1 0x10
#define LEFT_4OP_2 0x20
#define OPL3_MODE_REGISTER 0x05 /* Right side */
#define OPL3_ENABLE 0x01
#define OPL4_ENABLE 0x02
#define KBD_SPLIT_REGISTER 0x08 /* Left side */
#define COMPOSITE_SINE_WAVE_MODE 0x80 /* Don't use with OPL-3? */
#define KEYBOARD_SPLIT 0x40
#define PERCOSSION_REGISTER 0xbd /* Left side only */
#define TREMOLO_DEPTH 0x80
#define VIBRATO_DEPTH 0x40
#define PERCOSSION_ENABLE 0x20
#define BASSDRUM_ON 0x10
#define SNAREDRUM_ON 0x08
#define TOMTOM_ON 0x04
#define CYMBAL_ON 0x02
#define HIHAT_ON 0x01
/*
* Offsets to the register banks for operators. To get the
* register number just add the operator offset to the bank offset
*
* AM/VIB/EG/KSR/Multiple (0x20 to 0x35)
*/
#define AM_VIB 0x20
#define TREMOLO_ON 0x80
#define VIBRATO_ON 0x40
#define SUSTAIN_ON 0x20
#define KSR 0x10 /* Key scaling rate */
#define MULTIPLE_MASK 0x0f /* Frequency multiplier */
/*
* KSL/Total level (0x40 to 0x55)
*/
#define KSL_LEVEL 0x40
#define KSL_MASK 0xc0 /* Envelope scaling bits */
#define TOTAL_LEVEL_MASK 0x3f /* Strength (volume) of OP */
/*
* Attack / Decay rate (0x60 to 0x75)
*/
#define ATTACK_DECAY 0x60
#define ATTACK_MASK 0xf0
#define DECAY_MASK 0x0f
/*
* Sustain level / Release rate (0x80 to 0x95)
*/
#define SUSTAIN_RELEASE 0x80
#define SUSTAIN_MASK 0xf0
#define RELEASE_MASK 0x0f
/*
* Wave select (0xE0 to 0xF5)
*/
#define WAVE_SELECT 0xe0
/*
* Offsets to the register banks for voices. Just add to the
* voice number to get the register number.
*
* F-Number low bits (0xA0 to 0xA8).
*/
#define FNUM_LOW 0xa0
/*
* F-number high bits / Key on / Block (octave) (0xB0 to 0xB8)
*/
#define KEYON_BLOCK 0xb0
#define KEYON_BIT 0x20
#define BLOCKNUM_MASK 0x1c
#define FNUM_HIGH_MASK 0x03
/*
* Feedback / Connection (0xc0 to 0xc8)
*
* These registers have two new bits when the OPL-3 mode
* is selected. These bits controls connecting the voice
* to the stereo channels. For 4 OP voices this bit is
* defined in the second half of the voice (add 3 to the
* register offset).
*
* For 4 OP voices the connection bit is used in the
* both halves (gives 4 ways to connect the operators).
*/
#define FEEDBACK_CONNECTION 0xc0
#define FEEDBACK_MASK 0x0e /* Valid just for 1st OP of a voice */
#define CONNECTION_BIT 0x01
/*
* In the 4 OP mode there is four possible configurations how the
* operators can be connected together (in 2 OP modes there is just
* AM or FM). The 4 OP connection mode is defined by the rightmost
* bit of the FEEDBACK_CONNECTION (0xC0-0xC8) on the both halves.
*
* First half Second half Mode
*
* +---+
* v |
* 0 0 >+-1-+--2--3--4-->
*
*
*
* +---+
* | |
* 0 1 >+-1-+--2-+
* |->
* >--3----4-+
*
* +---+
* | |
* 1 0 >+-1-+-----+
* |->
* >--2--3--4-+
*
* +---+
* | |
* 1 1 >+-1-+--+
* |
* >--2--3-+->
* |
* >--4----+
*/
#define STEREO_BITS 0x30 /* OPL-3 only */
#define VOICE_TO_LEFT 0x10
#define VOICE_TO_RIGHT 0x20
/*
* Definition table for the physical voices
*/
struct physical_voice_info {
unsigned char voice_num;
unsigned char voice_mode; /* 0=unavailable, 2=2 OP, 4=4 OP */
unsigned short ioaddr; /* I/O port (left or right side) */
unsigned char op[4]; /* Operator offsets */
};
/*
* There is 18 possible 2 OP voices
* (9 in the left and 9 in the right).
* The first OP is the modulator and 2nd is the carrier.
*
* The first three voices in the both sides may be connected
* with another voice to a 4 OP voice. For example voice 0
* can be connected with voice 3. The operators of voice 3 are
* used as operators 3 and 4 of the new 4 OP voice.
* In this case the 2 OP voice number 0 is the 'first half' and
* voice 3 is the second.
*/
#define USE_LEFT 0
#define USE_RIGHT 1
static struct physical_voice_info pv_map[18] =
{
/* No Mode Side OP1 OP2 OP3 OP4 */
/* --------------------------------------------------- */
{ 0, 2, USE_LEFT, {0x00, 0x03, 0x08, 0x0b}},
{ 1, 2, USE_LEFT, {0x01, 0x04, 0x09, 0x0c}},
{ 2, 2, USE_LEFT, {0x02, 0x05, 0x0a, 0x0d}},
{ 3, 2, USE_LEFT, {0x08, 0x0b, 0x00, 0x00}},
{ 4, 2, USE_LEFT, {0x09, 0x0c, 0x00, 0x00}},
{ 5, 2, USE_LEFT, {0x0a, 0x0d, 0x00, 0x00}},
{ 6, 2, USE_LEFT, {0x10, 0x13, 0x00, 0x00}}, /* Used by percussive voices */
{ 7, 2, USE_LEFT, {0x11, 0x14, 0x00, 0x00}}, /* if the percussive mode */
{ 8, 2, USE_LEFT, {0x12, 0x15, 0x00, 0x00}}, /* is selected */
{ 0, 2, USE_RIGHT, {0x00, 0x03, 0x08, 0x0b}},
{ 1, 2, USE_RIGHT, {0x01, 0x04, 0x09, 0x0c}},
{ 2, 2, USE_RIGHT, {0x02, 0x05, 0x0a, 0x0d}},
{ 3, 2, USE_RIGHT, {0x08, 0x0b, 0x00, 0x00}},
{ 4, 2, USE_RIGHT, {0x09, 0x0c, 0x00, 0x00}},
{ 5, 2, USE_RIGHT, {0x0a, 0x0d, 0x00, 0x00}},
{ 6, 2, USE_RIGHT, {0x10, 0x13, 0x00, 0x00}},
{ 7, 2, USE_RIGHT, {0x11, 0x14, 0x00, 0x00}},
{ 8, 2, USE_RIGHT, {0x12, 0x15, 0x00, 0x00}}
};
/*
* DMA buffer calls
*/
......@@ -13,21 +13,26 @@
*
* Changes:
* Alan Cox Modularisation
* Christoph Hellwig Adapted to module_init/module_exit
*
* FIXME:
* Check for install of mpu etc is wrong, should check result of the mss stuff
*/
#include <linux/init.h>
#include <linux/module.h>
#undef SB_OK
#include "sound_config.h"
#include "soundmodule.h"
#include "ad1848.h"
#include "mpu401.h"
#ifdef SB_OK
#include "sb.h"
static int sb_initialized = 0;
#endif
static int kilroy_was_here = 0; /* Don't detect twice */
......@@ -62,7 +67,7 @@ static void opl3sa_write(int addr, int data)
restore_flags(flags);
}
static int opl3sa_detect(void)
static int __init opl3sa_detect(void)
{
int tmp;
......@@ -102,7 +107,7 @@ static int opl3sa_detect(void)
* OPL3-SA
*/
int probe_opl3sa_wss(struct address_info *hw_config)
static int __init probe_opl3sa_wss(struct address_info *hw_config)
{
int ret;
unsigned char tmp = 0x24; /* WSS enable */
......@@ -157,7 +162,7 @@ int probe_opl3sa_wss(struct address_info *hw_config)
return ret;
}
void attach_opl3sa_wss(struct address_info *hw_config)
static void __init attach_opl3sa_wss(struct address_info *hw_config)
{
int nm = num_mixers;
......@@ -172,13 +177,13 @@ void attach_opl3sa_wss(struct address_info *hw_config)
}
void attach_opl3sa_mpu(struct address_info *hw_config)
static void __init attach_opl3sa_mpu(struct address_info *hw_config)
{
hw_config->name = "OPL3-SA (MPU401)";
attach_uart401(hw_config);
}
int probe_opl3sa_mpu(struct address_info *hw_config)
static int __init probe_opl3sa_mpu(struct address_info *hw_config)
{
unsigned char conf;
static signed char irq_bits[] = {
......@@ -236,7 +241,7 @@ int probe_opl3sa_mpu(struct address_info *hw_config)
return probe_uart401(hw_config);
}
void unload_opl3sa_wss(struct address_info *hw_config)
static void __exit unload_opl3sa_wss(struct address_info *hw_config)
{
int dma2 = hw_config->dma2;
......@@ -254,26 +259,29 @@ void unload_opl3sa_wss(struct address_info *hw_config)
sound_unload_audiodev(hw_config->slots[0]);
}
void unload_opl3sa_mpu(struct address_info *hw_config)
static inline void __exit unload_opl3sa_mpu(struct address_info *hw_config)
{
unload_uart401(hw_config);
}
#ifdef SB_OK
void unload_opl3sa_sb(struct address_info *hw_config)
static inline void __exit unload_opl3sa_sb(struct address_info *hw_config)
{
sb_dsp_unload(hw_config);
}
#endif
#ifdef MODULE
int io = -1;
int irq = -1;
int dma = -1;
int dma2 = -1;
static int found_mpu;
static struct address_info cfg;
static struct address_info cfg_mpu;
int mpu_io = -1;
int mpu_irq = -1;
static int __initdata io = -1;
static int __initdata irq = -1;
static int __initdata dma = -1;
static int __initdata dma2 = -1;
static int __initdata mpu_io = -1;
static int __initdata mpu_irq = -1;
MODULE_PARM(io,"i");
MODULE_PARM(irq,"i");
......@@ -282,43 +290,61 @@ MODULE_PARM(dma2,"i");
MODULE_PARM(mpu_io,"i");
MODULE_PARM(mpu_irq,"i");
struct address_info cfg;
struct address_info mpu_cfg;
static int found_mpu;
int init_module(void)
static int __init init_opl3sa(void)
{
if (io == -1 || irq == -1 || dma == -1)
{
if (io == -1 || irq == -1 || dma == -1) {
printk(KERN_ERR "opl3sa: dma, irq and io must be set.\n");
return -EINVAL;
}
cfg.io_base = io;
cfg.irq = irq;
cfg.dma = dma;
cfg.dma2 = dma2;
mpu_cfg.io_base = mpu_io;
mpu_cfg.irq = mpu_irq;
cfg_mpu.io_base = mpu_io;
cfg_mpu.irq = mpu_irq;
if (probe_opl3sa_wss(&cfg) == 0)
return -ENODEV;
found_mpu=probe_opl3sa_mpu(&mpu_cfg);
found_mpu=probe_opl3sa_mpu(&cfg_mpu);
attach_opl3sa_wss(&cfg);
if(found_mpu)
attach_opl3sa_mpu(&mpu_cfg);
attach_opl3sa_mpu(&cfg_mpu);
SOUND_LOCK;
return 0;
}
void cleanup_module(void)
static void __exit cleanup_opl3sa(void)
{
if(found_mpu)
unload_opl3sa_mpu(&mpu_cfg);
unload_opl3sa_mpu(&cfg_mpu);
unload_opl3sa_wss(&cfg);
SOUND_LOCK_END;
}
#endif /* MODULE */
module_init(init_opl3sa);
module_exit(cleanup_opl3sa);
#ifndef MODULE
static int __init setup_opl3sa(char *str)
{
/* io, irq, dma, dma2, mpu_io, mpu_irq */
int ints[7];
str = get_options(str, ARRAY_SIZE(ints), ints);
io = ints[1];
irq = ints[2];
dma = ints[3];
dma2 = ints[4];
mpu_io = ints[5];
mpu_irq = ints[6];
return 1;
}
__setup("opl3sa=", setup_opl3sa);
#endif
......@@ -32,15 +32,20 @@
* Scott Murray Simpler detection code should work all the time now
* (with thanks to Ben Hutchings for the heuristic),
* removed now unnecessary force option. (Jan 5, 1999)
* Christoph Hellwig Adapted to module_init/module_exit (Mar 4, 2000)
*
*/
#include <linux/config.h>
#include <linux/init.h>
#include <linux/module.h>
#include "sound_config.h"
#include "soundmodule.h"
#include "ad1848.h"
#include "mpu401.h"
/* Useful control port indexes: */
#define OPL3SA2_MASTER_LEFT 0x07
#define OPL3SA2_MASTER_RIGHT 0x08
......@@ -439,31 +444,31 @@ static struct mixer_operations opl3sa2_mixer_operations =
/* End of mixer-related stuff */
int probe_opl3sa2_mpu(struct address_info *hw_config)
static inline int __init probe_opl3sa2_mpu(struct address_info *hw_config)
{
return probe_mpu401(hw_config);
}
void attach_opl3sa2_mpu(struct address_info *hw_config)
static inline void __init attach_opl3sa2_mpu(struct address_info *hw_config)
{
attach_mpu401(hw_config);
}
void unload_opl3sa2_mpu(struct address_info *hw_config)
static inline void __exit unload_opl3sa2_mpu(struct address_info *hw_config)
{
unload_mpu401(hw_config);
}
int probe_opl3sa2_mss(struct address_info *hw_config)
static inline int __init probe_opl3sa2_mss(struct address_info *hw_config)
{
return probe_ms_sound(hw_config);
}
void attach_opl3sa2_mss(struct address_info *hw_config)
static void __init attach_opl3sa2_mss(struct address_info *hw_config)
{
char mixer_name[64];
......@@ -506,13 +511,13 @@ void attach_opl3sa2_mss(struct address_info *hw_config)
}
void unload_opl3sa2_mss(struct address_info *hw_config)
static inline void __exit unload_opl3sa2_mss(struct address_info *hw_config)
{
unload_ms_sound(hw_config);
}
int probe_opl3sa2(struct address_info *hw_config)
static int __init probe_opl3sa2(struct address_info *hw_config)
{
unsigned char version = 0;
char tag;
......@@ -582,16 +587,13 @@ int probe_opl3sa2(struct address_info *hw_config)
{
/* Generate a pretty name */
sprintf(chipset_name, "OPL3-SA%c", tag);
#if defined(CONFIG_OPL3SA2_MPU_BASE) && !defined(MODULE)
sound_getconf(SNDCARD_OPL3SA2_MPU)->always_detect = 1;
#endif
return 1;
}
return 0;
}
void attach_opl3sa2(struct address_info *hw_config)
static void __init attach_opl3sa2(struct address_info *hw_config)
{
request_region(hw_config->io_base, 2, chipset_name);
......@@ -599,7 +601,7 @@ void attach_opl3sa2(struct address_info *hw_config)
}
void unload_opl3sa2(struct address_info *hw_config)
static void __exit unload_opl3sa2(struct address_info *hw_config)
{
/* Release control ports */
release_region(hw_config->io_base, 2);
......@@ -609,15 +611,16 @@ void unload_opl3sa2(struct address_info *hw_config)
sound_unload_mixerdev(opl3sa2_mixer);
}
static struct address_info cfg;
static struct address_info cfg2;
static struct address_info cfg_mpu;
#ifdef MODULE
int io = -1;
int mss_io = -1;
int mpu_io = -1;
int irq = -1;
int dma = -1;
int dma2 = -1;
static int __initdata io = -1;
static int __initdata mss_io = -1;
static int __initdata mpu_io = -1;
static int __initdata irq = -1;
static int __initdata dma = -1;
static int __initdata dma2 = -1;
MODULE_PARM(io, "i");
MODULE_PARM_DESC(io, "Set i/o base of OPL3-SA2 or SA3 card (usually 0x370)");
......@@ -640,30 +643,15 @@ MODULE_PARM_DESC(dma2, "Set MSS (audio) second DMA channel (0, 1, 3)");
MODULE_DESCRIPTION("Module for OPL3-SA2 and SA3 sound cards (uses AD1848 MSS driver).");
MODULE_AUTHOR("Scott Murray <scottm@interlog.com>");
EXPORT_NO_SYMBOLS;
struct address_info cfg;
struct address_info mss_cfg;
struct address_info mpu_cfg;
/*
* Install a OPL3SA2 based card.
*
* Need to have ad1848 and mpu401 loaded ready.
*/
int init_module(void)
static int __init init_opl3sa2(void)
{
int i;
if(io == -1 || irq == -1 || dma == -1 || dma2 == -1 || mss_io == -1)
{
printk(KERN_ERR
"%s: io, mss_io, irq, dma, and dma2 must be set.\n",
__FILE__);
return -EINVAL;
}
/* Our own config: */
cfg.io_base = io;
cfg.irq = irq;
......@@ -671,16 +659,26 @@ int init_module(void)
cfg.dma2 = dma2;
/* The MSS config: */
mss_cfg.io_base = mss_io;
mss_cfg.irq = irq;
mss_cfg.dma = dma;
mss_cfg.dma2 = dma2;
mss_cfg.card_subtype = 1; /* No IRQ or DMA setup */
cfg2.io_base = mss_io;
cfg2.irq = irq;
cfg2.dma = dma;
cfg2.dma2 = dma2;
cfg2.card_subtype = 1; /* No IRQ or DMA setup */
cfg_mpu.io_base = mpu_io;
cfg_mpu.irq = irq;
cfg_mpu.dma = dma;
cfg_mpu.always_detect = 1; /* It's there, so use shared IRQs */
if(cfg.io_base == -1 || cfg.irq == -1 || cfg.dma == -1 || cfg.dma2 == -1 || cfg2.io_base == -1) {
printk(KERN_ERR "opl3sa2: io, mss_io, irq, dma, and dma2 must be set.\n");
return -EINVAL;
}
/* Call me paranoid: */
for(i = 0; i < 6; i++)
{
cfg.slots[i] = mss_cfg.slots[i] = mpu_cfg.slots[i] = -1;
cfg.slots[i] = cfg2.slots[i] = cfg_mpu.slots[i] = -1;
}
if(probe_opl3sa2(&cfg) == 0)
......@@ -688,41 +686,54 @@ int init_module(void)
return -ENODEV;
}
if(probe_opl3sa2_mss(&mss_cfg) == 0)
if(probe_opl3sa2_mss(&cfg2) == 0)
{
return -ENODEV;
}
attach_opl3sa2(&cfg);
attach_opl3sa2_mss(&mss_cfg);
attach_opl3sa2_mss(&cfg2);
if(mpu_io != -1)
{
/* MPU config: */
mpu_cfg.io_base = mpu_io;
mpu_cfg.irq = irq;
mpu_cfg.dma = dma;
mpu_cfg.always_detect = 1; /* It's there, so use shared IRQs */
if(probe_opl3sa2_mpu(&mpu_cfg))
{
attach_opl3sa2_mpu(&mpu_cfg);
}
if(cfg_mpu.io_base != -1) {
if(probe_opl3sa2_mpu(&cfg_mpu)) {
attach_opl3sa2_mpu(&cfg_mpu);
}
}
SOUND_LOCK;
return 0;
}
void cleanup_module(void)
static void __exit cleanup_opl3sa2(void)
{
if(mpu_cfg.slots[1] != -1)
{
unload_opl3sa2_mpu(&mpu_cfg);
if(cfg_mpu.slots[1] != -1) {
unload_opl3sa2_mpu(&cfg_mpu);
}
unload_opl3sa2_mss(&mss_cfg);
unload_opl3sa2_mss(&cfg2);
unload_opl3sa2(&cfg);
SOUND_LOCK_END;
}
#endif /* MODULE */
module_init(init_opl3sa2);
module_exit(cleanup_opl3sa2);
#ifndef MODULE
static int __init setup_opl3sa2(char *str)
{
/* io, irq, dma, dma2 */
int ints[7];
str = get_options(str, ARRAY_SIZE(ints), ints);
io = ints[1];
irq = ints[2];
dma = ints[3];
dma2 = ints[4];
mss_io = ints[5];
mpu_io = ints[6];
return 1;
}
__setup("opl3sa2=", setup_opl3sa2);
#endif
/*
* pas2.h
*
* Copyright: Christoph Hellwig <chhellwig@gmx.net>
*
*/
/* From pas_card.c */
int pas_set_intr(int mask);
int pas_remove_intr(int mask);
unsigned char pas_read(int ioaddr);
void pas_write(unsigned char data, int ioaddr);
/* From pas_audio.c */
void pas_pcm_interrupt(unsigned char status, int cause);
void pas_pcm_init(struct address_info *hw_config);
/* From pas_mixer.c */
int pas_init_mixer(void);
/* From pas_midi.c */
void pas_midi_init(void);
void pas_midi_interrupt(void);
......@@ -5,10 +5,14 @@
*/
#include <linux/config.h>
#include <linux/init.h>
#include <linux/module.h>
#include "sound_config.h"
#include "soundmodule.h"
#include "pas2.h"
#include "sb.h"
static unsigned char dma_bits[] = {
4, 1, 2, 3, 0, 5, 6, 7
};
......@@ -51,6 +55,8 @@ static int broken_bus_clock = 1;
static int broken_bus_clock = 0;
#endif
static struct address_info cfg;
static struct address_info cfg2;
char pas_model = 0;
static char *pas_model_names[] = {
......@@ -81,7 +87,7 @@ void pas_write(unsigned char data, int ioaddr)
/******************* Begin of the Interrupt Handler ********************/
static void pasintr(int irq, void *dev_id, struct pt_regs *dummy)
void pasintr(int irq, void *dev_id, struct pt_regs *dummy)
{
int status;
......@@ -126,9 +132,7 @@ int pas_remove_intr(int mask)
/******************* Begin of the Initialization Code ******************/
extern struct address_info sbhw_config;
static int config_pas_hw(struct address_info *hw_config)
static int __init config_pas_hw(struct address_info *hw_config)
{
char ok = 1;
unsigned int_ptrs; /* scsi/sound interrupt pointers */
......@@ -238,12 +242,8 @@ static int config_pas_hw(struct address_info *hw_config)
{
struct address_info *sb_config;
#ifndef MODULE
if ((sb_config = sound_getconf(SNDCARD_SB)))
#else
sb_config = &sbhw_config;
sb_config = &cfg2;
if (sb_config->io_base)
#endif
{
unsigned char irq_dma;
......@@ -286,7 +286,7 @@ static int config_pas_hw(struct address_info *hw_config)
return ok;
}
static int detect_pas_hw(struct address_info *hw_config)
static int __init detect_pas_hw(struct address_info *hw_config)
{
unsigned char board_id, foo;
......@@ -327,7 +327,7 @@ static int detect_pas_hw(struct address_info *hw_config)
return pas_model;
}
void attach_pas_card(struct address_info *hw_config)
static void __init attach_pas_card(struct address_info *hw_config)
{
pas_irq = hw_config->irq;
......@@ -348,7 +348,6 @@ void attach_pas_card(struct address_info *hw_config)
pas_pcm_init(hw_config);
#if !defined(MODULE) && !defined(DISABLE_SB_EMULATION)
sb_dsp_disable_midi(pas_sb_base); /* No MIDI capability */
#endif
......@@ -358,12 +357,12 @@ void attach_pas_card(struct address_info *hw_config)
}
}
int probe_pas(struct address_info *hw_config)
static inline int __init probe_pas(struct address_info *hw_config)
{
return detect_pas_hw(hw_config);
}
void unload_pas(struct address_info *hw_config)
static void __exit unload_pas(struct address_info *hw_config)
{
extern int pas_audiodev;
extern int pas2_mididev;
......@@ -381,17 +380,15 @@ void unload_pas(struct address_info *hw_config)
sound_unload_audiodev(pas_audiodev);
}
#ifdef MODULE
int io = -1;
int irq = -1;
int dma = -1;
int dma16 = -1; /* Set this for modules that need it */
static int __initdata io = -1;
static int __initdata irq = -1;
static int __initdata dma = -1;
static int __initdata dma16 = -1; /* Set this for modules that need it */
int sb_io = 0;
int sb_irq = -1;
int sb_dma = -1;
int sb_dma16 = -1;
static int __initdata sb_io = 0;
static int __initdata sb_irq = -1;
static int __initdata sb_dma = -1;
static int __initdata sb_dma16 = -1;
MODULE_PARM(io,"i");
MODULE_PARM(irq,"i");
......@@ -407,40 +404,61 @@ MODULE_PARM(joystick,"i");
MODULE_PARM(symphony,"i");
MODULE_PARM(broken_bus_clock,"i");
struct address_info config;
struct address_info sbhw_config;
int init_module(void)
static int __init init_pas2(void)
{
printk(KERN_INFO "Pro Audio Spectrum driver Copyright (C) by Hannu Savolainen 1993-1996\n");
if (io == -1 || dma == -1 || irq == -1)
{
printk(KERN_INFO "I/O, IRQ, DMA and type are mandatory\n");
return -EINVAL;
}
config.io_base = io;
config.irq = irq;
config.dma = dma;
config.dma2 = dma16;
cfg.io_base = io;
cfg.irq = irq;
cfg.dma = dma;
cfg.dma2 = dma16;
cfg2.io_base = sb_io;
cfg2.irq = sb_irq;
cfg2.dma = sb_dma;
cfg2.dma2 = sb_dma16;
sbhw_config.io_base = sb_io;
sbhw_config.irq = sb_irq;
sbhw_config.dma = sb_dma;
sbhw_config.dma2 = sb_dma16;
if (cfg.io_base == -1 || cfg.dma == -1 || cfg.irq == -1) {
printk(KERN_INFO "I/O, IRQ, DMA and type are mandatory\n");
return -EINVAL;
}
if (!probe_pas(&config))
if (!probe_pas(&cfg))
return -ENODEV;
attach_pas_card(&config);
attach_pas_card(&cfg);
SOUND_LOCK;
return 0;
}
void cleanup_module(void)
static void __exit cleanup_pas2(void)
{
unload_pas(&config);
unload_pas(&cfg);
SOUND_LOCK_END;
}
module_init(init_pas2);
module_exit(cleanup_pas2);
#ifndef MODULE
static int __init setup_pas2(char *str)
{
/* io, irq, dma, dma2, sb_io, sb_irq, sb_dma, sb_dma2 */
int ints[9];
str = get_options(str, ARRAY_SIZE(ints), ints);
io = ints[1];
irq = ints[2];
dma = ints[3];
dma16 = ints[4];
sb_io = ints[5];
sb_irq = ints[6];
sb_dma = ints[7];
sb_dma16 = ints[8];
return 1;
}
#endif /* MODULE */
__setup("pas2=", setup_pas2);
#endif
......@@ -10,8 +10,11 @@
* Version 2 (June 1991). See the "COPYING" file distributed with this software
* for more info.
*/
#include "sound_config.h"
#include "pas2.h"
static int midi_busy = 0, input_opened = 0;
static int my_dev;
......
......@@ -17,6 +17,8 @@
*/
#include "sound_config.h"
#include "pas2.h"
#ifndef DEB
#define DEB(what) /* (what) */
#endif
......
......@@ -16,6 +16,8 @@
#include "sound_config.h"
#include "pas2.h"
#ifndef DEB
#define DEB(WHAT)
#endif
......
......@@ -24,16 +24,22 @@
* To probe_pss_mss added test for initialize AD1848
* 98-05-28: Vladimir Michl <vladimir.michl@upol.cz>
* Fixed computation of mixer volumes
* 00-03-03: Christoph Hellwig <chhellwig@gmx.net>
* Adapted to module_init/module_exit
*/
#include <linux/config.h>
#include <linux/init.h>
#include <linux/module.h>
#include "sound_config.h"
#include "sound_firmware.h"
#include "soundmodule.h"
#include "ad1848.h"
#include "mpu401.h"
/*
* PSS registers.
*/
......@@ -910,14 +916,14 @@ static coproc_operations pss_coproc_operations =
&pss_data
};
void attach_pss_mpu(struct address_info *hw_config)
static void __init attach_pss_mpu(struct address_info *hw_config)
{
attach_mpu401(hw_config); /* Slot 1 */
if (hw_config->slots[1] != -1) /* The MPU driver installed itself */
midi_devs[hw_config->slots[1]]->coproc = &pss_coproc_operations;
}
int probe_pss_mss(struct address_info *hw_config)
static int __init probe_pss_mss(struct address_info *hw_config)
{
volatile int timeout;
......@@ -950,16 +956,20 @@ int probe_pss_mss(struct address_info *hw_config)
* downloaded to the ADSP2115 spends some time initializing the card.
* Let's try to wait until it finishes this task.
*/
for (timeout = 0; timeout < 100000 && (inb(hw_config->io_base + WSS_INDEX) & WSS_INITIALIZING); timeout++);
for (timeout = 0; timeout < 100000 && (inb(hw_config->io_base + WSS_INDEX) &
WSS_INITIALIZING); timeout++)
;
outb((0x0b), hw_config->io_base + WSS_INDEX); /* Required by some cards */
for (timeout = 0; (inb(hw_config->io_base + WSS_DATA) & WSS_AUTOCALIBRATION) && (timeout < 100000); timeout++);
for (timeout = 0; (inb(hw_config->io_base + WSS_DATA) & WSS_AUTOCALIBRATION) &&
(timeout < 100000); timeout++)
;
return probe_ms_sound(hw_config);
}
void attach_pss_mss(struct address_info *hw_config)
static void __init attach_pss_mss(struct address_info *hw_config)
{
int my_mix = -999; /* gcc shut up */
......@@ -991,36 +1001,33 @@ void attach_pss_mss(struct address_info *hw_config)
}
}
void unload_pss(struct address_info *hw_config)
static inline void __exit unload_pss(struct address_info *hw_config)
{
release_region(hw_config->io_base, 0x10);
release_region(hw_config->io_base+0x10, 0x9);
}
void unload_pss_mpu(struct address_info *hw_config)
static inline void __exit unload_pss_mpu(struct address_info *hw_config)
{
unload_mpu401(hw_config);
}
void unload_pss_mss(struct address_info *hw_config)
static inline void __exit unload_pss_mss(struct address_info *hw_config)
{
unload_ms_sound(hw_config);
}
#ifdef MODULE
int pss_io = -1;
int mss_io = -1;
int mss_irq = -1;
int mss_dma = -1;
int mpu_io = -1;
int mpu_irq = -1;
static struct address_info cfg;
static struct address_info cfg2;
static struct address_info cfg_mpu;
struct address_info cfgpss = { 0 /* pss_io */, 0, -1, -1 };
struct address_info cfgmpu = { 0 /* mpu_io */, 0 /* mpu_irq */, 0, -1 };
struct address_info cfgmss = { 0 /* mss_io */, 0 /* mss_irq */, 0 /* mss_dma */, -1 };
static int pss_io __initdata = -1;
static int mss_io __initdata = -1;
static int mss_irq __initdata = -1;
static int mss_dma __initdata = -1;
static int mpu_io __initdata = -1;
static int mpu_irq __initdata = -1;
MODULE_PARM(pss_io, "i");
MODULE_PARM_DESC(pss_io, "Set i/o base of PSS card (probably 0x220 or 0x240)");
......@@ -1046,54 +1053,76 @@ static int pssmpu = 0, pssmss = 0;
* Load a PSS sound card module
*/
int init_module(void)
static int __init init_pss(void)
{
if (pss_io == -1 || mss_io == -1 || mss_irq == -1 || mss_dma == -1) {
printk(KERN_INFO "pss: mss_io, mss_dma, mss_irq and pss_io must be set.\n");
return -EINVAL;
}
cfg.io_base = pss_io;
cfgpss.io_base = pss_io;
cfg2.io_base = mss_io;
cfg2.irq = mss_irq;
cfg2.dma = mss_dma;
cfgmss.io_base = mss_io;
cfgmss.irq = mss_irq;
cfgmss.dma = mss_dma;
cfg_mpu.io_base = mpu_io;
cfg_mpu.irq = mpu_irq;
cfgmpu.io_base = mpu_io;
cfgmpu.irq = mpu_irq;
if (cfg.io_base == -1 || cfg2.io_base == -1 || cfg2.irq == -1 || cfg.dma == -1) {
printk(KERN_INFO "pss: mss_io, mss_dma, mss_irq and pss_io must be set.\n");
return -EINVAL;
}
if (!pss_synth)
{
if (!pss_synth) {
fw_load = 1;
pss_synthLen = mod_firmware_load("/etc/sound/pss_synth", (void *) &pss_synth);
}
if (!probe_pss(&cfgpss))
if (!probe_pss(&cfg))
return -ENODEV;
attach_pss(&cfgpss);
attach_pss(&cfg);
/*
* Attach stuff
*/
if (probe_pss_mpu(&cfgmpu)) {
if (probe_pss_mpu(&cfg_mpu)) {
pssmpu = 1;
attach_pss_mpu(&cfgmpu);
attach_pss_mpu(&cfg_mpu);
}
if (probe_pss_mss(&cfgmss)) {
if (probe_pss_mss(&cfg2)) {
pssmss = 1;
attach_pss_mss(&cfgmss);
attach_pss_mss(&cfg2);
}
SOUND_LOCK;
return 0;
}
void cleanup_module(void)
static void __exit cleanup_pss(void)
{
if (fw_load && pss_synth)
vfree(pss_synth);
if (pssmss)
unload_pss_mss(&cfgmss);
unload_pss_mss(&cfg2);
if (pssmpu)
unload_pss_mpu(&cfgmpu);
unload_pss(&cfgpss);
unload_pss_mpu(&cfg_mpu);
unload_pss(&cfg);
SOUND_LOCK_END;
}
#endif /* MODULE */
module_init(init_pss);
module_exit(cleanup_pss);
#ifndef MODULE
static int __init setup_pss(char *str)
{
/* io, mss_io, mss_irq, mss_dma, mpu_io, mpu_irq */
int ints[7];
str = get_options(str, ARRAY_SIZE(ints), ints);
pss_io = ints[1];
mss_io = ints[2];
mss_irq = ints[3];
mss_dma = ints[4];
mpu_io = ints[5];
mpu_irq = ints[6];
return 1;
}
__setup("pss=", setup_pss);
#endif
......@@ -164,3 +164,13 @@ void sb_audio_close(int dev);
extern int acer;
extern sb_devc *last_sb;
/* From sb_common.c */
void sb_dsp_disable_midi(int port);
void sb_dsp_disable_recording(int port);
void attach_sbmpu (struct address_info *hw_config);
int probe_sbmpu (struct address_info *hw_config);
void unload_sbmpu (struct address_info *hw_config);
void unload_sb16(struct address_info *hw_info);
void unload_sb16midi(struct address_info *hw_info);
This diff is collapsed.
......@@ -9,25 +9,42 @@
* OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
* Version 2 (June 1991). See the "COPYING" file distributed with this software
* for more info.
*/
/*
*
*
* Daniel J. Rodriksson: Modified sbintr to handle 8 and 16 bit interrupts
* for full duplex support ( only sb16 by now )
* Rolf Fokkens: Added (BETA?) support for ES1887 chips.
* (fokkensr@vertis.nl) Which means: You can adjust the recording levels.
*
* 2000/01/18 - separated sb_card and sb_common -
* Jeff Garzik <jgarzik@mandrakesoft.com>
*
*/
/* FIXME: *grr* why can't the f**in Makefile do this for me ? */
#define EXPORT_SYMTAB
#include <linux/config.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/delay.h>
#include "sound_config.h"
#include "sound_firmware.h"
#include "soundmodule.h"
#include "mpu401.h"
#include "sb_mixer.h"
#include "sb.h"
#include "sb_ess.h"
/*
* global module flag
*/
int sb_be_quiet = 0;
static sb_devc *detected_devc = NULL; /* For communication from probe to init */
static sb_devc *last_devc = NULL; /* For MPU401 initialization */
......@@ -39,6 +56,16 @@ static unsigned char jazz_dma_bits[] = {
0, 1, 0, 2, 0, 3, 0, 4
};
/* Do acer notebook init? */
int acer = 0;
/* soundman games? */
int sm_games = 0;
extern int esstype;
void *smw_free = NULL;
/*
* Jazz16 chipset specific control variables
*/
......@@ -1033,8 +1060,6 @@ static int smw_midi_init(sb_devc * devc, struct address_info *hw_config)
#ifdef MODULE
if (!smw_ucode)
{
extern void *smw_free;
smw_ucodeLen = mod_firmware_load("/etc/sound/midi0001.bin", (void *) &smw_ucode);
smw_free = smw_ucode;
}
......@@ -1272,3 +1297,17 @@ void unload_sbmpu(struct address_info *hw_config)
#endif
unload_uart401(hw_config);
}
MODULE_PARM(acer, "i");
MODULE_PARM(sm_games, "i");
MODULE_PARM(esstype, "i");
EXPORT_SYMBOL(sb_dsp_init);
EXPORT_SYMBOL(sb_dsp_detect);
EXPORT_SYMBOL(sb_dsp_unload);
EXPORT_SYMBOL(sb_dsp_disable_midi);
EXPORT_SYMBOL(sb_be_quiet);
EXPORT_SYMBOL(attach_sbmpu);
EXPORT_SYMBOL(probe_sbmpu);
EXPORT_SYMBOL(unload_sbmpu);
EXPORT_SYMBOL(smw_free);
......@@ -9,8 +9,8 @@
* Aztech Sound Galaxy Washington 16
*
* Based on cs4232.c by Hannu Savolainen and Alan Cox.
*/
/*
*
*
* Copyright (C) by Hannu Savolainen 1993-1997
*
* OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
......@@ -18,11 +18,14 @@
* for more info.
*/
#include <linux/init.h>
#include <linux/module.h>
#include "sound_config.h"
#include "soundmodule.h"
#include "ad1848.h"
static void sleep( unsigned howlong )
{
current->state = TASK_INTERRUPTIBLE;
......@@ -79,10 +82,9 @@ static int sb_cmd( int base, unsigned char val )
#define ai_sgbase driver_use_1
int probe_sgalaxy( struct address_info *ai )
static int __init probe_sgalaxy( struct address_info *ai )
{
if ( check_region( ai->io_base, 8 ) )
{
if ( check_region( ai->io_base, 8 ) ) {
printk(KERN_ERR "sgalaxy: WSS IO port 0x%03x not available\n", ai->io_base);
return 0;
}
......@@ -90,8 +92,7 @@ int probe_sgalaxy( struct address_info *ai )
if ( ad1848_detect( ai->io_base+4, NULL, ai->osp ) )
return probe_ms_sound(ai); /* The card is already active, check irq etc... */
if ( check_region( ai->ai_sgbase, 0x10 ) )
{
if ( check_region( ai->ai_sgbase, 0x10 ) ) {
printk(KERN_ERR "sgalaxy: SB IO port 0x%03x not available\n", ai->ai_sgbase);
return 0;
}
......@@ -108,7 +109,7 @@ int probe_sgalaxy( struct address_info *ai )
return probe_ms_sound(ai);
}
void attach_sgalaxy( struct address_info *ai )
static void __init attach_sgalaxy( struct address_info *ai )
{
int n;
......@@ -117,27 +118,26 @@ void attach_sgalaxy( struct address_info *ai )
attach_ms_sound( ai );
n=ai->slots[0];
if (n!=-1 && audio_devs[n]->mixer_dev != -1 )
{
if (n!=-1 && audio_devs[n]->mixer_dev != -1 ) {
AD1848_REROUTE( SOUND_MIXER_LINE1, SOUND_MIXER_LINE ); /* Line-in */
AD1848_REROUTE( SOUND_MIXER_LINE2, SOUND_MIXER_SYNTH ); /* FM+Wavetable*/
AD1848_REROUTE( SOUND_MIXER_LINE3, SOUND_MIXER_CD ); /* CD */
}
}
void unload_sgalaxy( struct address_info *ai )
static void __exit unload_sgalaxy( struct address_info *ai )
{
unload_ms_sound( ai );
release_region( ai->ai_sgbase, 0x10 );
}
#ifdef MODULE
static struct address_info cfg;
int io = -1;
int irq = -1;
int dma = -1;
int dma2 = -1;
int sgbase = -1;
static int __initdata io = -1;
static int __initdata irq = -1;
static int __initdata dma = -1;
static int __initdata dma2 = -1;
static int __initdata sgbase = -1;
MODULE_PARM(io,"i");
MODULE_PARM(irq,"i");
......@@ -145,38 +145,52 @@ MODULE_PARM(dma,"i");
MODULE_PARM(dma2,"i");
MODULE_PARM(sgbase,"i");
EXPORT_NO_SYMBOLS;
struct address_info ai;
int init_module(void)
static int __init init_sgalaxy(void)
{
if ( io==-1 || irq==-1 || dma==-1 || sgbase==-1 )
{
cfg.io_base = io;
cfg.irq = irq;
cfg.dma = dma;
cfg.dma2 = dma2;
cfg.ai_sgbase = sgbase;
if (cfg.io_base == -1 || cfg.irq == -1 || cfg.dma == -1 || cfg.ai_sgbase == -1 ) {
printk(KERN_ERR "sgalaxy: io, irq, dma and sgbase must be set.\n");
return -EINVAL;
}
ai.io_base = io;
ai.irq = irq;
ai.dma = dma;
ai.dma2 = dma2;
ai.ai_sgbase = sgbase;
if ( probe_sgalaxy( &ai )==0 )
if ( probe_sgalaxy(&cfg) == 0 )
return -ENODEV;
attach_sgalaxy( &ai );
attach_sgalaxy(&cfg);
SOUND_LOCK;
return 0;
}
void cleanup_module(void)
static void __exit cleanup_sgalaxy(void)
{
unload_sgalaxy( &ai );
unload_sgalaxy(&cfg);
SOUND_LOCK_END;
}
#endif /* MODULE */
module_init(init_sgalaxy);
module_exit(cleanup_sgalaxy);
#ifndef MODULE
static int __init setup_sgalaxy(char *str)
{
/* io, irq, dma, dma2, sgbase */
int ints[6];
str = get_options(str, ARRAY_SIZE(ints), ints);
io = ints[1];
irq = ints[2];
dma = ints[3];
dma2 = ints[4];
sgbase = ints[5];
return 1;
}
__setup("sgalaxy=", setup_sgalaxy);
#endif
This diff is collapsed.
This diff is collapsed.
......@@ -46,18 +46,6 @@
#define CONFIG_PAS_BASE 0x388
#endif
#if defined(CONFIG_SB16_DMA) && !defined(CONFIG_SB_DMA2)
# define CONFIG_SB_DMA2 CONFIG_SB16_DMA
#endif
#if defined(SB16MIDI_BASE) && !defined(CONFIG_SB_MPU_BASE)
# define CONFIG_SB_MPU_BASE SB16MIDI_BASE
#endif
#ifndef CONFIG_SB_MPU_IRQ
# define CONFIG_SB_MPU_IRQ CONFIG_SB_IRQ
#endif
/* SEQ_MAX_QUEUE is the maximum number of sequencer events buffered by the
driver. (There is no need to alter this) */
#define SEQ_MAX_QUEUE 1024
......
......@@ -46,8 +46,6 @@ EXPORT_SYMBOL(sound_unload_synthdev);
EXPORT_SYMBOL(load_mixer_volumes);
EXPORT_SYMBOL(trace_init); /* oops! this is needed for maui.c -- AJK */
EXPORT_SYMBOL(conf_printf);
EXPORT_SYMBOL(conf_printf2);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment