From ae38fd1e4c98588314a42097c5a5e77dcef23561 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sun, 12 Mar 2000 23:15:27 +0000 Subject: Merge with Linux 2.3.50. --- drivers/sound/Config.in | 160 +------- drivers/sound/Makefile | 86 ++--- drivers/sound/ac97_codec.c | 53 ++- drivers/sound/ad1816.c | 227 +++++------ drivers/sound/ad1848.c | 106 ++--- drivers/sound/ad1848.h | 28 ++ drivers/sound/adlib_card.c | 54 ++- drivers/sound/cs4232.c | 119 +++--- drivers/sound/cs4232.h | 11 + drivers/sound/dev_table.c | 388 +------------------ drivers/sound/dev_table.h | 328 +--------------- drivers/sound/gus.h | 30 ++ drivers/sound/gus_card.c | 131 ++++--- drivers/sound/gus_midi.c | 6 +- drivers/sound/gus_vol.c | 6 +- drivers/sound/gus_wave.c | 14 +- drivers/sound/ics2101.c | 10 +- drivers/sound/mad16.c | 150 +++---- drivers/sound/maui.c | 186 ++++----- drivers/sound/mpu401.c | 70 ++-- drivers/sound/mpu401.h | 21 + drivers/sound/nm256_audio.c | 15 +- drivers/sound/opl3.c | 47 ++- drivers/sound/opl3.h | 243 +----------- drivers/sound/opl3_hw.h | 246 ++++++++++++ drivers/sound/opl3sa.c | 88 +++-- drivers/sound/opl3sa2.c | 135 ++++--- drivers/sound/pas2.h | 23 ++ drivers/sound/pas2_card.c | 110 +++--- drivers/sound/pas2_midi.c | 3 + drivers/sound/pas2_mixer.c | 2 + drivers/sound/pas2_pcm.c | 2 + drivers/sound/pss.c | 117 +++--- drivers/sound/sb.h | 10 + drivers/sound/sb_card.c | 283 +++++++++----- drivers/sound/sb_common.c | 51 ++- drivers/sound/sgalaxy.c | 86 +++-- drivers/sound/softoss.c | 29 +- drivers/sound/sound_calls.h | 235 +---------- drivers/sound/sound_config.h | 12 - drivers/sound/sound_syms.c | 2 - drivers/sound/soundcard.c | 275 ++----------- drivers/sound/soundmodule.h | 4 +- drivers/sound/sscape.c | 137 ++++--- drivers/sound/trident.c | 837 +++++++++++++++++++--------------------- drivers/sound/trident.h | 6 +- drivers/sound/trix.c | 151 ++++---- drivers/sound/uart401.c | 81 ++-- drivers/sound/uart6850.c | 74 ++-- drivers/sound/v_midi.c | 57 +-- drivers/sound/via82cxxx_audio.c | 1 + drivers/sound/vidc.c | 23 +- drivers/sound/waveartist.c | 73 ++-- drivers/sound/wavfront.c | 50 +-- drivers/sound/wf_midi.c | 67 +--- 55 files changed, 2408 insertions(+), 3351 deletions(-) create mode 100644 drivers/sound/ad1848.h create mode 100644 drivers/sound/cs4232.h create mode 100644 drivers/sound/gus.h create mode 100644 drivers/sound/mpu401.h create mode 100644 drivers/sound/opl3_hw.h create mode 100644 drivers/sound/pas2.h (limited to 'drivers/sound') diff --git a/drivers/sound/Config.in b/drivers/sound/Config.in index c218ca69d..30ffe5cc0 100644 --- a/drivers/sound/Config.in +++ b/drivers/sound/Config.in @@ -81,79 +81,21 @@ fi dep_tristate ' OSS sound modules' CONFIG_SOUND_OSS $CONFIG_SOUND if [ "$CONFIG_SOUND_OSS" = "y" -o "$CONFIG_SOUND_OSS" = "m" ]; then - if [ "$CONFIG_SOUND_OSS" = "y" ]; then - bool ' Persistent DMA buffers' CONFIG_SOUND_DMAP - fi - if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then dep_tristate ' AD1816(A) based cards (EXPERIMENTAL)' CONFIG_SOUND_AD1816 $CONFIG_SOUND - if [ "$CONFIG_SOUND_AD1816" = "y" ]; then - hex 'AD1816 audio I/O base 530, 604, E80 or F40' CONFIG_AD1816_BASE 530 - int 'AD1816 audio IRQ 5, 7, 9, 11, 12 or 15' CONFIG_AD1816_IRQ 7 - int 'AD1816 audio DMA 0, 1 or 3' CONFIG_AD1816_DMA 0 - int 'AD1816 second (duplex) DMA 0, 1 or 3' CONFIG_AD1816_DMA2 3 - int 'AD1816 clock chip frequency' CONFIG_AD1816_CLOCK 33000 - fi fi dep_tristate ' Aztech Sound Galaxy (non-PnP) cards' CONFIG_SOUND_SGALAXY $CONFIG_SOUND_OSS - if [ "$CONFIG_SOUND_SGALAXY" = "y" ]; then - hex 'SGALAXY audio I/O base 530, 604, E80 or F40' CONFIG_SGALAXY_BASE 530 - int 'SGALAXY audio IRQ 5, 7, 9, 11, 12 or 15' CONFIG_SGALAXY_IRQ 11 - int 'SGALAXY audio DMA 0, 1 or 3' CONFIG_SGALAXY_DMA 0 - int 'SGALAXY second (duplex) DMA 0, 1 or 3' CONFIG_SGALAXY_DMA2 3 - hex 'SGALAXY SB I/O base 220 or 240' CONFIG_SGALAXY_SGBASE 220 - fi - dep_tristate ' Crystal CS4232 based (PnP) cards' CONFIG_SOUND_CS4232 $CONFIG_SOUND_OSS - if [ "$CONFIG_SOUND_CS4232" = "y" ]; then - hex 'CS4232 audio I/O base (normally 530, 604, E80 or F40)' CONFIG_CS4232_BASE 530 - int 'CS4232 audio IRQ 5, 7, 9, 11, 12 or 15' CONFIG_CS4232_IRQ 11 - int 'CS4232 audio DMA 0, 1 or 3' CONFIG_CS4232_DMA 0 - int 'CS4232 second (duplex) DMA 0, 1 or 3' CONFIG_CS4232_DMA2 3 - hex 'CS4232 MIDI I/O base 330, 370, 3B0 or 3F0' CONFIG_CS4232_MPU_BASE 330 - int 'CS4232 MIDI IRQ 5, 7, 9, 11, 12 or 15' CONFIG_CS4232_MPU_IRQ 9 - fi - dep_tristate ' Ensoniq SoundScape support' CONFIG_SOUND_SSCAPE $CONFIG_SOUND_OSS - if [ "$CONFIG_SOUND_SSCAPE" = "y" ]; then - hex 'SoundScape MIDI I/O base 320, 330, 340 or 350' CONFIG_SSCAPE_BASE 330 - int 'SoundScape MIDI IRQ ' CONFIG_SSCAPE_IRQ 9 - int 'SoundScape initialization DMA 0, 1 or 3' CONFIG_SSCAPE_DMA 3 - hex 'SoundScape audio I/O base 534, 608, E84 or F44' CONFIG_SSCAPE_MSS_BASE 534 - int 'SoundScape audio IRQ 7, 9, 10 or 11' CONFIG_SSCAPE_MSS_IRQ 11 - fi - dep_tristate ' Gravis Ultrasound support' CONFIG_SOUND_GUS $CONFIG_SOUND_OSS - if [ "$CONFIG_SOUND_GUS" = "y" -o "$CONFIG_SOUND_GUS" = "m" ]; then - bool ' 16 bit sampling option of GUS (_NOT_ GUS MAX)' CONFIG_GUS16 - bool ' GUS MAX support' CONFIG_GUSMAX + if [ "$CONFIG_SOUND_GUS" != "n" ]; then + bool ' 16 bit sampling option of GUS (_NOT_ GUS MAX)' CONFIG_SOUND_GUS16 + bool ' GUS MAX support' CONFIG_SOUND_GUSMAX fi - if [ "$CONFIG_SOUND_GUS" = "y" ]; then - hex 'I/O base for GUS 210, 220, 230, 240, 250 or 260' CONFIG_GUS_BASE 220 - int 'GUS IRQ 3, 5, 7, 9, 11, 12 or 15' CONFIG_GUS_IRQ 15 - int 'GUS DMA 1, 3, 5, 6 or 7' CONFIG_GUS_DMA 6 - int 'Second DMA channel for GUS 1, 3, 5, 6 or 7' CONFIG_GUS_DMA2 -1 - if [ "$CONFIG_GUS16" = "y" ]; then - hex 'I/O base for the 16 bit daughtercard of GUS 530, 604, E80 or F40' CONFIG_GUS16_BASE 530 - int 'GUS 16 bit daughtercard IRQ 3, 4, 5, 7, or 9' CONFIG_GUS16_IRQ 7 - int 'GUS DMA 0, 1 or 3' CONFIG_GUS16_DMA 3 - fi - fi - dep_tristate ' Loopback MIDI device support' CONFIG_SOUND_VMIDI $CONFIG_SOUND_OSS - dep_tristate ' MediaTrix AudioTrix Pro support' CONFIG_SOUND_TRIX $CONFIG_SOUND_OSS if [ "$CONFIG_SOUND_TRIX" = "y" ]; then - hex 'TRIX audio I/O base 530, 604, E80 or F40' CONFIG_TRIX_BASE 530 - int 'TRIX audio IRQ 7, 9, 10 or 11' CONFIG_TRIX_IRQ 11 - int 'TRIX audio DMA 0, 1 or 3' CONFIG_TRIX_DMA 0 - int 'TRIX second (duplex) DMA 0, 1 or 3' CONFIG_TRIX_DMA2 3 - hex 'TRIX MIDI I/O base 330, 370, 3B0 or 3F0' CONFIG_TRIX_MPU_BASE 330 - int 'TRIX MIDI IRQ 3, 4, 5, 7 or 9' CONFIG_TRIX_MPU_IRQ 9 - hex 'TRIX SB I/O base 220, 210, 230, 240, 250, 260 or 270' CONFIG_TRIX_SB_BASE 220 - int 'TRIX SB IRQ 3, 4, 5 or 7' CONFIG_TRIX_SB_IRQ 7 - int 'TRIX SB DMA 1 or 3' CONFIG_TRIX_SB_DMA 1 bool ' Have TRXPRO.HEX firmware file' CONFIG_TRIX_HAVE_BOOT if [ "$CONFIG_TRIX_HAVE_BOOT" = "y" ]; then string ' Full pathname of TRXPRO.HEX firmware file' CONFIG_TRIX_BOOT_FILE /etc/sound/trxpro.hex @@ -161,58 +103,23 @@ if [ "$CONFIG_SOUND_OSS" = "y" -o "$CONFIG_SOUND_OSS" = "m" ]; then fi dep_tristate ' Microsoft Sound System support' CONFIG_SOUND_MSS $CONFIG_SOUND_OSS - if [ "$CONFIG_SOUND_MSS" = "y" ]; then - bool ' Enable support for the SoundPro mixer' CONFIG_SOUND_SPRO - hex 'MSS/WSS I/O base 530, 604, E80 or F40' CONFIG_MSS_BASE 530 - int 'MSS/WSS IRQ 7, 9, 10 or 11' CONFIG_MSS_IRQ 11 - int 'MSS/WSS DMA 0, 1 or 3' CONFIG_MSS_DMA 3 - int 'MSS/WSS second DMA (if possible) 0, 1 or 3' CONFIG_MSS_DMA2 -1 - fi - dep_tristate ' MPU-401 support (NOT for SB16)' CONFIG_SOUND_MPU401 $CONFIG_SOUND_OSS - if [ "$CONFIG_SOUND_MPU401" = "y" ]; then - hex 'I/O base for MPU401 Check from manual of the card' CONFIG_MPU_BASE 330 - int 'MPU401 IRQ Check from manual of the card' CONFIG_MPU_IRQ 9 - fi - dep_tristate ' NM256AV/NM256ZX audio support' CONFIG_SOUND_NM256 $CONFIG_SOUND_OSS - dep_tristate ' OPTi MAD16 and/or Mozart based cards' CONFIG_SOUND_MAD16 $CONFIG_SOUND_OSS if [ "$CONFIG_SOUND_MAD16" = "y" -o "$CONFIG_SOUND_MAD16" = "m" ]; then bool ' Support MIDI in older MAD16 based cards (requires SB)' CONFIG_MAD16_OLDCARD fi - if [ "$CONFIG_SOUND_MAD16" = "y" ]; then - hex 'MAD16 audio I/O base 530, 604, E80 or F40' CONFIG_MAD16_BASE 530 - int 'MAD16 audio IRQ 7, 9, 10 or 11' CONFIG_MAD16_IRQ 11 - int 'MAD16 audio DMA 0, 1 or 3' CONFIG_MAD16_DMA 3 - int 'MAD16 second (duplex) DMA 0, 1 or 3' CONFIG_MAD16_DMA2 0 - hex 'MAD16 MIDI I/O base 300, 310, 320 or 330 (0 disables)' CONFIG_MAD16_MPU_BASE 330 - int 'MAD16 MIDI IRQ 5, 7, 9 or 10' CONFIG_MAD16_MPU_IRQ 9 - fi - dep_tristate ' ProAudioSpectrum 16 support' CONFIG_SOUND_PAS $CONFIG_SOUND_OSS - if [ "$CONFIG_SOUND_PAS" = "y" ]; then - int 'PAS16 IRQ 3, 4, 5, 7, 9, 10, 11, 12, 14 or 15' CONFIG_PAS_IRQ 10 - int 'PAS16 DMA 0, 1, 3, 5, 6 or 7' CONFIG_PAS_DMA 3 - bool ' Enable PAS16 joystick port' CONFIG_PAS_JOYSTICK - fi + dep_bool ' Enable PAS16 joystick port' CONFIG_PAS_JOYSTICK $CONFIG_SOUND_PAS dep_tristate ' PSS (AD1848, ADSP-2115, ESC614) support' CONFIG_SOUND_PSS $CONFIG_SOUND_OSS - if [ "$CONFIG_SOUND_PSS" = "y" ]; then - hex 'PSS I/O base 220 or 240' CONFIG_PSS_BASE 220 - hex 'PSS audio I/O base 530, 604, E80 or F40' CONFIG_PSS_MSS_BASE 530 - int 'PSS audio IRQ 7, 9, 10 or 11' CONFIG_PSS_MSS_IRQ 11 - int 'PSS audio DMA 0, 1 or 3' CONFIG_PSS_MSS_DMA 3 - hex 'PSS MIDI I/O base ' CONFIG_PSS_MPU_BASE 330 - int 'PSS MIDI IRQ 3, 4, 5, 7, 9, 10, 11, 12' CONFIG_PSS_MPU_IRQ 9 - bool ' Have DSPxxx.LD firmware file' CONFIG_PSS_HAVE_BOOT - if [ "$CONFIG_PSS_HAVE_BOOT" = "y" ]; then - string ' Full pathname of DSPxxx.LD firmware file' CONFIG_PSS_BOOT_FILE /etc/sound/dsp001.ld - fi - fi if [ "$CONFIG_SOUND_PSS" = "y" -o "$CONFIG_SOUND_PSS" = "m" ]; then bool ' Enable PSS mixer (Beethoven ADSP-16 and other compatibile)' CONFIG_PSS_MIXER fi + bool ' Have DSPxxx.LD firmware file' CONFIG_PSS_HAVE_BOOT + if [ "$CONFIG_PSS_HAVE_BOOT" = "y" ]; then + string ' Full pathname of DSPxxx.LD firmware file' CONFIG_PSS_BOOT_FILE /etc/sound/dsp001.ld + fi dep_tristate ' SoftOSS software wave table engine' CONFIG_SOUND_SOFTOSS $CONFIG_SOUND_OSS if [ "$CONFIG_SOUND_SOFTOSS" = "y" ]; then @@ -221,27 +128,9 @@ if [ "$CONFIG_SOUND_OSS" = "y" -o "$CONFIG_SOUND_OSS" = "m" ]; then fi dep_tristate ' 100% Sound Blaster compatibles (SB16/32/64, ESS, Jazz16) support' CONFIG_SOUND_SB $CONFIG_SOUND_OSS - if [ "$CONFIG_SOUND_SB" = "y" ]; then - hex 'I/O base for SB Check from manual of the card' CONFIG_SB_BASE 220 - int 'Sound Blaster IRQ Check from manual of the card' CONFIG_SB_IRQ 7 - int 'Sound Blaster DMA 0, 1 or 3' CONFIG_SB_DMA 1 - int 'Sound Blaster 16 bit DMA (SB16, Jazz16, SMW) 5, 6 or 7 (use 1 for 8 bit cards)' CONFIG_SB_DMA2 5 - hex 'MPU401 I/O base of SB16, Jazz16 and ES1688 Check from manual of the card' CONFIG_SB_MPU_BASE 330 - comment 'MPU401 IRQ is only required with Jazz16, SM Wave and ESS1688.' - comment 'Enter -1 to the following question if you have something else such as SB16/32.' - int 'SB MPU401 IRQ (Jazz16, SM Wave and ES1688) Check from manual of the card' CONFIG_SB_MPU_IRQ -1 - fi - dep_tristate ' Full support for Turtle Beach WaveFront (Tropez Plus, Tropez, Maui) synth/soundcards' CONFIG_SOUND_WAVEFRONT $CONFIG_SOUND_OSS m - if [ "$CONFIG_SOUND_WAVEFRONT" = "y" ]; then - hex 'I/O base for WaveFront 210, 230, 260, 290, 300, 320, 338 or 330' CONFIG_WAVEFRONT_BASE 330 - int 'WaveFront IRQ 5, 9, 12 or 15' CONFIG_WAVEFRONT_IRQ 9 - fi - dep_tristate ' Limited support for Turtle Beach Wave Front (Maui, Tropez) synthesizers' CONFIG_SOUND_MAUI $CONFIG_SOUND_OSS if [ "$CONFIG_SOUND_MAUI" = "y" ]; then - hex 'I/O base for Maui 210, 230, 260, 290, 300, 320, 338 or 330' CONFIG_MAUI_BASE 330 - int 'Maui IRQ 5, 9, 12 or 15' CONFIG_MAUI_IRQ 9 bool ' Have OSWF.MOT firmware file' CONFIG_MAUI_HAVE_BOOT if [ "$CONFIG_MAUI_HAVE_BOOT" = "y" ]; then string ' Full pathname of OSWF.MOT firmware file' CONFIG_MAUI_BOOT_FILE /etc/sound/oswf.mot @@ -249,47 +138,14 @@ if [ "$CONFIG_SOUND_OSS" = "y" -o "$CONFIG_SOUND_OSS" = "m" ]; then fi dep_tristate ' VIA 82C686 Audio Codec' CONFIG_SOUND_VIA82CXXX $CONFIG_SOUND_OSS - dep_tristate ' Yamaha FM synthesizer (YM3812/OPL-3) support' CONFIG_SOUND_YM3812 $CONFIG_SOUND_OSS - dep_tristate ' Yamaha OPL3-SA1 audio controller' CONFIG_SOUND_OPL3SA1 $CONFIG_SOUND_OSS - if [ "$CONFIG_SOUND_OPL3SA1" = "y" ]; then - hex 'OPL3-SA1 audio I/O base 530, 604, E80 or F40' CONFIG_OPL3SA1_BASE 530 - int 'OPL3-SA1 audio IRQ 7, 9, 10 or 11' CONFIG_OPL3SA1_IRQ 11 - int 'OPL3-SA1 audio DMA 0, 1 or 3' CONFIG_OPL3SA1_DMA 0 - int 'OPL3-SA1 second (duplex) DMA 0, 1 or 3' CONFIG_OPL3SA1_DMA2 3 - hex 'OPL3-SA1 MIDI I/O base 330, 370, 3B0 or 3F0' CONFIG_OPL3SA1_MPU_BASE 330 - int 'OPL3-SA1 MIDI IRQ 3, 4, 5, 7 or 9' CONFIG_OPL3SA1_MPU_IRQ 9 - fi - dep_tristate ' Yamaha OPL3-SA2, SA3, and SAx based PnP cards' CONFIG_SOUND_OPL3SA2 $CONFIG_SOUND_OSS - if [ "$CONFIG_SOUND_OPL3SA2" = "y" ]; then - int 'Chipset (-1 for autoprobe, 2, or 3)' CONFIG_OPL3SA2_CHIPSET -1 - hex 'OPL3SA2 audio I/O base (530 - F48 valid)' CONFIG_OPL3SA2_BASE 530 - int 'OPL3SA2 audio IRQ 5, 7, 9, 11, 12 or 15' CONFIG_OPL3SA2_IRQ 9 - int 'OPL3SA2 audio DMA 0, 1 or 3' CONFIG_OPL3SA2_DMA 0 - int 'OPL3SA2 second (duplex) DMA 0, 1 or 3' CONFIG_OPL3SA2_DMA2 1 - hex 'OPL3SA2 control I/O base (100 - FFE valid)' CONFIG_OPL3SA2_CTRL_BASE 370 - hex 'OPL3SA2 MIDI I/O base (300 - 334 valid)' CONFIG_OPL3SA2_MPU_BASE 330 - int 'OPL3SA2 MIDI IRQ 5, 7, 9, 11, 12 or 15' CONFIG_OPL3SA2_MPU_IRQ 9 - fi - - dep_tristate ' 6850 UART support' CONFIG_SOUND_UART6850 $CONFIG_SOUND_OSS - if [ "$CONFIG_SOUND_UART6850" = "y" ]; then - hex 'I/O base for UART 6850 MIDI port (Unknown)' CONFIG_U6850_BASE 0 - int 'UART6850 IRQ (Unknown)' CONFIG_U6850_IRQ -1 - fi if [ "$CONFIG_ARM" = "y" ]; then dep_tristate ' VIDC 16-bit sound' CONFIG_SOUND_VIDC $CONFIG_SOUND_OSS dep_tristate ' Netwinder WaveArtist' CONFIG_SOUND_WAVEARTIST $CONFIG_SOUND_OSS - if [ "$CONFIG_SOUND_WAVEARTIST" != "n" ]; then - hex ' WaveArtist I/O base' CONFIG_WAVEARTIST_BASE 250 - int ' WaveArtist IRQ' CONFIG_WAVEARTIST_IRQ 12 - int ' WaveArtist DMA' CONFIG_WAVEARTIST_DMA 3 - int ' WaveArtist second DMA' CONFIG_WAVEARTIST_DMA2 7 - fi fi diff --git a/drivers/sound/Makefile b/drivers/sound/Makefile index 41b55ea4c..2c5df3f14 100644 --- a/drivers/sound/Makefile +++ b/drivers/sound/Makefile @@ -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 diff --git a/drivers/sound/ac97_codec.c b/drivers/sound/ac97_codec.c index 95bafcf20..32a3380e9 100644 --- a/drivers/sound/ac97_codec.c +++ b/drivers/sound/ac97_codec.c @@ -20,6 +20,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * History + * v0.3 Feb 22 2000 Ollie Lho + * bug fix for record mask setting * v0.2 Feb 10 2000 Ollie Lho * add ac97_read_proc for /proc/driver/vnedor/ac97 * v0.1 Jan 14 2000 Ollie Lho @@ -40,7 +42,9 @@ static void ac97_set_mixer(struct ac97_codec *codec, unsigned int oss_mixer, uns static int ac97_recmask_io(struct ac97_codec *codec, int rw, int mask); static int ac97_mixer_ioctl(struct ac97_codec *codec, unsigned int cmd, unsigned long arg); -#define arraysize(x) (sizeof(x)/sizeof((x)[0])) +static int sigmatel_init(struct ac97_codec * codec); + +#define arraysize(x) (sizeof(x)/sizeof((x)[0])) static struct { unsigned int id; @@ -50,14 +54,16 @@ static struct { {0x414B4D00, "Asahi Kasei AK4540" , NULL}, {0x41445340, "Analog Devices AD1881" , NULL}, {0x43525900, "Cirrus Logic CS4297" , NULL}, + {0x43525903, "Cirrus Logic CS4297" , NULL}, {0x43525913, "Cirrus Logic CS4297A" , NULL}, + {0x43525923, "Cirrus Logic CS4298" , NULL}, {0x43525931, "Cirrus Logic CS4299" , NULL}, - {0x4e534331, "National Semiconductor LM4549", NULL}, + {0x4e534331, "National Semiconductor LM4549" , NULL}, {0x83847600, "SigmaTel STAC????" , NULL}, {0x83847604, "SigmaTel STAC9701/3/4/5", NULL}, {0x83847605, "SigmaTel STAC9704" , NULL}, {0x83847608, "SigmaTel STAC9708" , NULL}, - {0x83847609, "SigmaTel STAC9721/23" , NULL}, + {0x83847609, "SigmaTel STAC9721/23" , sigmatel_init}, {0x54524108, "TriTech TR28028" , NULL}, {0x574D4C00, "Wolfson WM9704" , NULL}, {0x00000000, NULL, NULL} @@ -156,11 +162,12 @@ enum ac97_recsettings { }; static unsigned int ac97_rm2oss[] = { - [AC97_REC_MIC] = SOUND_MIXER_MIC, - [AC97_REC_CD] = SOUND_MIXER_CD, - [AC97_REC_VIDEO] = SOUND_MIXER_VIDEO, - [AC97_REC_AUX] = SOUND_MIXER_LINE1, - [AC97_REC_LINE] = SOUND_MIXER_LINE, + [AC97_REC_MIC] = SOUND_MIXER_MIC, + [AC97_REC_CD] = SOUND_MIXER_CD, + [AC97_REC_VIDEO] = SOUND_MIXER_VIDEO, + [AC97_REC_AUX] = SOUND_MIXER_LINE1, + [AC97_REC_LINE] = SOUND_MIXER_LINE, + [AC97_REC_STEREO]= SOUND_MIXER_IGAIN, [AC97_REC_PHONE] = SOUND_MIXER_PHONEIN }; @@ -171,6 +178,7 @@ static unsigned int ac97_oss_rm[] = { [SOUND_MIXER_VIDEO] = AC97_REC_VIDEO, [SOUND_MIXER_LINE1] = AC97_REC_AUX, [SOUND_MIXER_LINE] = AC97_REC_LINE, + [SOUND_MIXER_IGAIN] = AC97_REC_STEREO, [SOUND_MIXER_PHONEIN] = AC97_REC_PHONE }; @@ -216,8 +224,10 @@ static int ac97_read_mixer(struct ac97_codec *codec, int oss_channel) } #ifdef DEBUG - printk("ac97_codec: read OSS mixer %2d (ac97 register 0x%02x), " - "0x%04x -> 0x%04x\n", oss_channel, mh->offset, val, ret); + printk("ac97_codec: read OSS mixer %2d (%s ac97 register 0x%02x), " + "0x%04x -> 0x%04x\n", + oss_channel, codec->id ? "Secondary" : "Primary", + mh->offset, val, ret); #endif return ret; @@ -269,6 +279,7 @@ static void ac97_write_mixer(struct ac97_codec *codec, int oss_channel, #ifdef DEBUG printk(" 0x%04x", val); #endif + codec->codec_write(codec, mh->offset, val); #ifdef DEBUG @@ -303,8 +314,11 @@ static int ac97_recmask_io(struct ac97_codec *codec, int rw, int mask) if (rw) { /* read it from the card */ - val = codec->codec_read(codec, 0x1a) & 0x7; - return ac97_rm2oss[val]; + val = codec->codec_read(codec, AC97_RECORD_SELECT); +#ifdef DEBUG + printk("ac97_codec: ac97 recmask to set to 0x%04x\n", val); +#endif + return (1 << ac97_rm2oss[val & 0x07]); } /* else, write the first set in the mask as the @@ -315,10 +329,10 @@ static int ac97_recmask_io(struct ac97_codec *codec, int rw, int mask) val |= val << 8; /* set both channels */ #ifdef DEBUG - printk("ac97_codec: setting ac97 recmask to 0x%x\n", val); + printk("ac97_codec: setting ac97 recmask to 0x%04x\n", val); #endif - codec->codec_write(codec, 0x1a, val); + codec->codec_write(codec, AC97_RECORD_SELECT, val); return 0; }; @@ -384,9 +398,9 @@ static int ac97_mixer_ioctl(struct ac97_codec *codec, unsigned int cmd, unsigned return -EINVAL; /* do we ever want to touch the hardware? */ - val = codec->read_mixer(codec, i); - /* val = codec->mixer_state[i]; */ - break; + /* val = codec->read_mixer(codec, i); */ + val = codec->mixer_state[i]; + break; } return put_user(val, (int *)arg); } @@ -497,9 +511,10 @@ int ac97_probe_codec(struct ac97_codec *codec) codec->codec_write(codec, AC97_RESET, 0L); if ((cap = codec->codec_read(codec, AC97_RESET)) & 0x8000) return 0; - + codec->name = NULL; codec->codec_init = NULL; + id1 = codec->codec_read(codec, AC97_VENDOR_ID1); id2 = codec->codec_read(codec, AC97_VENDOR_ID2); for (i = 0; i < arraysize(ac97_codec_ids); i++) { @@ -520,6 +535,8 @@ int ac97_probe_codec(struct ac97_codec *codec) codec->record_sources = AC97_RECORD_MASK; if (!(cap & 0x04)) codec->supported_mixers &= ~(SOUND_MASK_BASS|SOUND_MASK_TREBLE); + if (!(cap & 0x10)) + codec->supported_mixers &= ~SOUND_MASK_ALTPCM; /* generic OSS to AC97 wrapper */ codec->read_mixer = ac97_read_mixer; diff --git a/drivers/sound/ad1816.c b/drivers/sound/ad1816.c index 8813d519e..d44cf1389 100644 --- a/drivers/sound/ad1816.c +++ b/drivers/sound/ad1816.c @@ -1,59 +1,43 @@ /* - -AD1816 lowlevel sound driver for Linux 2.2.0 and above - -Copyright (C) 1998 by Thorsten Knabe -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 + * + * 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 +#include #include #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 diff --git a/drivers/sound/ad1848.c b/drivers/sound/ad1848.c index b7d93fdb4..b7ad6f75c 100644 --- a/drivers/sound/ad1848.c +++ b/drivers/sound/ad1848.c @@ -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 +#include #include #include @@ -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 diff --git a/drivers/sound/ad1848.h b/drivers/sound/ad1848.h new file mode 100644 index 000000000..2f2225546 --- /dev/null +++ b/drivers/sound/ad1848.h @@ -0,0 +1,28 @@ +/* + * ad1848.c + * + * Copyright: Christoph Hellwig + */ + +#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); diff --git a/drivers/sound/adlib_card.c b/drivers/sound/adlib_card.c index 087c57b68..95974d444 100644 --- a/drivers/sound/adlib_card.c +++ b/drivers/sound/adlib_card.c @@ -11,47 +11,42 @@ */ #include +#include + #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 diff --git a/drivers/sound/cs4232.c b/drivers/sound/cs4232.c index 0778273f9..2098c85a8 100644 --- a/drivers/sound/cs4232.c +++ b/drivers/sound/cs4232.c @@ -1,5 +1,7 @@ /* - * 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 #include +#include #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 diff --git a/drivers/sound/cs4232.h b/drivers/sound/cs4232.h new file mode 100644 index 000000000..7b5782199 --- /dev/null +++ b/drivers/sound/cs4232.h @@ -0,0 +1,11 @@ +/* + * cs4232.h + * + * Copyright: Christoph Hellwig + * + */ + +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); diff --git a/drivers/sound/dev_table.c b/drivers/sound/dev_table.c index 5e9657c8a..5be9a1eef 100644 --- a/drivers/sound/dev_table.c +++ b/drivers/sound/dev_table.c @@ -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 #include - #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;iio_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; } - diff --git a/drivers/sound/dev_table.h b/drivers/sound/dev_table.h index 5c0cf1d0f..b15fd505c 100644 --- a/drivers/sound/dev_table.h +++ b/drivers/sound/dev_table.h @@ -370,318 +370,6 @@ struct sound_timer_operations *sound_timer_devs[MAX_TIMER_DEV] = { int num_sound_timers = 0; #endif -/* - * List of low level drivers compiled into the kernel. - */ - -struct driver_info sound_drivers[] = -{ -#ifdef CONFIG_SOUND_PSS - {"PSS", 0, SNDCARD_PSS, "Echo Personal Sound System PSS (ESC614)", attach_pss, probe_pss, unload_pss}, - {"PSSMPU", 0, SNDCARD_PSS_MPU, "PSS-MPU", attach_pss_mpu, probe_pss_mpu, unload_pss_mpu}, - {"PSSMSS", 0, SNDCARD_PSS_MSS, "PSS-MSS", attach_pss_mss, probe_pss_mss, unload_pss_mss}, -#endif - -#ifdef CONFIG_SOUND_GUS -#ifdef CONFIG_GUS16 - {"GUS16", 0, SNDCARD_GUS16, "Ultrasound 16-bit opt.", attach_gus_db16, probe_gus_db16, unload_gus_db16}, -#endif - {"GUS", 0, SNDCARD_GUS, "Gravis Ultrasound", attach_gus_card, probe_gus, unload_gus}, - {"GUSPNP", 1, SNDCARD_GUSPNP, "GUS PnP", attach_gus_card, probe_gus, unload_gus}, -#endif - -#ifdef CONFIG_SOUND_MSS - {"MSS", 0, SNDCARD_MSS, "MS Sound System", attach_ms_sound, probe_ms_sound, unload_ms_sound}, - /* Compaq Deskpro XL */ - {"DESKPROXL", 2, SNDCARD_DESKPROXL, "Compaq Deskpro XL", attach_ms_sound, probe_ms_sound, unload_ms_sound}, -#endif - -#ifdef CONFIG_SOUND_MAD16 - {"MAD16", 0, SNDCARD_MAD16, "MAD16/Mozart (MSS)", attach_mad16, probe_mad16, unload_mad16}, - {"MAD16MPU", 0, SNDCARD_MAD16_MPU, "MAD16/Mozart (MPU)", attach_mad16_mpu, probe_mad16_mpu, unload_mad16_mpu}, -#endif - -#ifdef CONFIG_SOUND_CS4232 - {"CS4232", 0, SNDCARD_CS4232, "CS4232", attach_cs4232, probe_cs4232, unload_cs4232}, -#endif -#ifdef CONFIG_CS4232_MPU_BASE - {"CS4232MPU", 0, SNDCARD_CS4232_MPU, "CS4232 MIDI", attach_cs4232_mpu, probe_cs4232_mpu, unload_cs4232_mpu}, -#endif - -#ifdef CONFIG_SOUND_OPL3SA2 - {"OPL3SA2", 0, SNDCARD_OPL3SA2, "OPL3SA2", attach_opl3sa2, probe_opl3sa2, unload_opl3sa2}, - {"OPL3SA2MSS", 1, SNDCARD_OPL3SA2_MSS, "OPL3SA2 MSS", attach_opl3sa2_mss, probe_opl3sa2_mss, unload_opl3sa2_mss}, - {"OPL3SA2MPU", 0, SNDCARD_OPL3SA2_MPU, "OPL3SA2 MIDI", attach_opl3sa2_mpu, probe_opl3sa2_mpu, unload_opl3sa2_mpu}, -#endif - -#ifdef CONFIG_SGALAXY - {"SGALAXY", 0, SNDCARD_SGALAXY, "Sound Galaxy WSS", attach_sgalaxy, probe_sgalaxy, unload_sgalaxy}, -#endif - -#ifdef CONFIG_SOUND_AD1816 - {"AD1816", 0, SNDCARD_AD1816, "AD1816", attach_ad1816, -probe_ad1816, unload_ad1816}, -#endif - -#ifdef CONFIG_SOUND_YM3812 - {"OPL3", 0, SNDCARD_ADLIB, "OPL-2/OPL-3 FM", attach_adlib_card, probe_adlib, unload_adlib}, -#endif - -#ifdef CONFIG_SOUND_PAS - {"PAS16", 0, SNDCARD_PAS, "ProAudioSpectrum", attach_pas_card, probe_pas, unload_pas}, -#endif - -#if (defined(CONFIG_SOUND_MPU401) || defined(CONFIG_SOUND_MPU_EMU)) - {"MPU401", 0, SNDCARD_MPU401,"Roland MPU-401", attach_mpu401, probe_mpu401, unload_mpu401}, -#endif - -#if defined(CONFIG_SOUND_UART401) - {"UART401", 0, SNDCARD_UART401,"MPU-401 (UART)", - attach_uart401, probe_uart401, unload_uart401}, -#endif - -#if defined(CONFIG_SOUND_WAVEFRONT) - {"WAVEFRONT", 0, SNDCARD_WAVEFRONT,"TB WaveFront", attach_wavefront, probe_wavefront, unload_wavefront}, -#endif - -#if defined(CONFIG_SOUND_MAUI) - {"MAUI", 0, SNDCARD_MAUI,"TB Maui", attach_maui, probe_maui, unload_maui}, -#endif - -#if defined(CONFIG_SOUND_UART6850) - {"MIDI6850", 0, SNDCARD_UART6850,"6860 UART Midi", attach_uart6850, probe_uart6850, unload_uart6850}, -#endif - - - - -#ifdef CONFIG_SOUND_SBDSP - {"SBLAST", 0, SNDCARD_SB, "Sound Blaster", attach_sb_card, probe_sb, unload_sb}, - {"SBPNP", 6, SNDCARD_SBPNP, "Sound Blaster PnP", attach_sb_card, probe_sb, unload_sb}, - - {"SBMPU", 0, SNDCARD_SB16MIDI,"SB MPU-401", attach_sbmpu, probe_sbmpu, unload_sbmpu}, -#endif - -#ifdef CONFIG_SOUND_SSCAPE - {"SSCAPE", 0, SNDCARD_SSCAPE, "Ensoniq SoundScape", attach_sscape, probe_sscape, unload_sscape}, - {"SSCAPEMSS", 0, SNDCARD_SSCAPE_MSS, "MS Sound System (SoundScape)", attach_ss_ms_sound, probe_ss_ms_sound, unload_ss_ms_sound}, -#endif - -#ifdef CONFIG_SOUND_OPL3SA1 - {"OPL3SA", 0, SNDCARD_OPL3SA1, "Yamaha OPL3-SA", attach_opl3sa_wss, probe_opl3sa_wss, unload_opl3sa_wss}, -/* {"OPL3SASB", 0, SNDCARD_OPL3SA1_SB, "OPL3-SA (SB mode)", attach_opl3sa_sb, probe_opl3sa_sb, unload_opl3sa_sb}, */ - {"OPL3SAMPU", 0, SNDCARD_OPL3SA1_MPU, "OPL3-SA MIDI", attach_opl3sa_mpu, probe_opl3sa_mpu, unload_opl3sa_mpu}, -#endif - -#ifdef CONFIG_SOUND_TRIX - {"TRXPRO", 0, SNDCARD_TRXPRO, "MediaTrix AudioTrix Pro", attach_trix_wss, probe_trix_wss, unload_trix_wss}, - {"TRXPROSB", 0, SNDCARD_TRXPRO_SB, "AudioTrix (SB mode)", attach_trix_sb, probe_trix_sb, unload_trix_sb}, - {"TRXPROMPU", 0, SNDCARD_TRXPRO_MPU, "AudioTrix MIDI", attach_trix_mpu, probe_trix_mpu, unload_trix_mpu}, -#endif - -#ifdef CONFIG_SOUND_SOFTOSS - {"SOFTSYN", 0, SNDCARD_SOFTOSS, "SoftOSS Virtual Wave Table", - attach_softsyn_card, probe_softsyn, unload_softsyn}, -#endif - -#ifdef CONFIG_SOUND_VMIDI - {"VMIDI", 0, SNDCARD_VMIDI,"Loopback MIDI Device", attach_v_midi, probe_v_midi, unload_v_midi}, -#endif -#ifdef CONFIG_SOUND_VIDC - {"VIDC", 0, SNDCARD_VIDC, "ARM VIDC 16-bit D/A", attach_vidc, probe_vidc, unload_vidc }, -#endif -#ifdef CONFIG_SOUND_WAVEARTIST - {"WaveArtist", 0, SNDCARD_WAVEARTIST, "NetWinder WaveArtist", attach_waveartist, probe_waveartist, unload_waveartist }, -#endif - {NULL, 0, 0, "*?*", NULL, NULL, NULL} -}; - -int num_sound_drivers = sizeof(sound_drivers) / sizeof (struct driver_info); - - -/* - * List of devices actually configured in the system. - * - * Note! The detection order is significant. Don't change it. - */ - -struct card_info snd_installed_cards[] = -{ -#ifdef CONFIG_SOUND_PSS - {SNDCARD_PSS, {CONFIG_PSS_BASE, 0, -1, -1}, SND_DEFAULT_ENABLE}, -#ifdef CONFIG_PSS_MPU_BASE - {SNDCARD_PSS_MPU, {CONFIG_PSS_MPU_BASE, CONFIG_PSS_MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, -#endif -#ifdef CONFIG_PSS_MSS_BASE - {SNDCARD_PSS_MSS, {CONFIG_PSS_MSS_BASE, CONFIG_PSS_MSS_IRQ, CONFIG_PSS_MSS_DMA, -1}, SND_DEFAULT_ENABLE}, -#endif -#endif - -#ifdef CONFIG_SOUND_TRIX -#ifndef CONFIG_TRIX_DMA2 -#define CONFIG_TRIX_DMA2 CONFIG_TRIX_DMA -#endif - {SNDCARD_TRXPRO, {CONFIG_TRIX_BASE, CONFIG_TRIX_IRQ, CONFIG_TRIX_DMA, CONFIG_TRIX_DMA2}, SND_DEFAULT_ENABLE}, -#ifdef CONFIG_TRIX_SB_BASE - {SNDCARD_TRXPRO_SB, {CONFIG_TRIX_SB_BASE, CONFIG_TRIX_SB_IRQ, CONFIG_TRIX_SB_DMA, -1}, SND_DEFAULT_ENABLE}, -#endif -#ifdef CONFIG_TRIX_MPU_BASE - {SNDCARD_TRXPRO_MPU, {CONFIG_TRIX_MPU_BASE, CONFIG_TRIX_MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, -#endif -#endif - -#ifdef CONFIG_SOUND_OPL3SA1 - {SNDCARD_OPL3SA1, {CONFIG_OPL3SA1_BASE, CONFIG_OPL3SA1_IRQ, CONFIG_OPL3SA1_DMA, CONFIG_OPL3SA1_DMA2}, SND_DEFAULT_ENABLE}, -#ifdef CONFIG_OPL3SA1_MPU_BASE - {SNDCARD_OPL3SA1_MPU, {CONFIG_OPL3SA1_MPU_BASE, CONFIG_OPL3SA1_MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, -#endif -#endif - -#ifdef CONFIG_SOUND_SOFTOSS - {SNDCARD_SOFTOSS, {0, 0, -1, -1}, SND_DEFAULT_ENABLE}, -#endif - -#ifdef CONFIG_SOUND_SSCAPE - {SNDCARD_SSCAPE, {CONFIG_SSCAPE_BASE, CONFIG_SSCAPE_IRQ, CONFIG_SSCAPE_DMA, -1}, SND_DEFAULT_ENABLE}, - {SNDCARD_SSCAPE_MSS, {CONFIG_SSCAPE_MSS_BASE, CONFIG_SSCAPE_MSS_IRQ, CONFIG_SSCAPE_DMA, -1}, SND_DEFAULT_ENABLE}, -#endif - -#ifdef CONFIG_SOUND_MAD16 -#ifndef CONFIG_MAD16_DMA2 -#define CONFIG_MAD16_DMA2 CONFIG_MAD16_DMA -#endif - {SNDCARD_MAD16, {CONFIG_MAD16_BASE, CONFIG_MAD16_IRQ, CONFIG_MAD16_DMA, CONFIG_MAD16_DMA2}, SND_DEFAULT_ENABLE}, -#ifdef CONFIG_MAD16_MPU_BASE - {SNDCARD_MAD16_MPU, {CONFIG_MAD16_MPU_BASE, CONFIG_MAD16_MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, -#endif -#endif - -#ifdef CONFIG_SOUND_CS4232 -#ifndef CONFIG_CS4232_DMA2 -#define CONFIG_CS4232_DMA2 CONFIG_CS4232_DMA -#endif -#ifdef CONFIG_CS4232_MPU_BASE - {SNDCARD_CS4232_MPU, {CONFIG_CS4232_MPU_BASE, CONFIG_CS4232_MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, -#endif - {SNDCARD_CS4232, {CONFIG_CS4232_BASE, CONFIG_CS4232_IRQ, CONFIG_CS4232_DMA, CONFIG_CS4232_DMA2}, SND_DEFAULT_ENABLE}, -#endif - -#ifdef CONFIG_SOUND_OPL3SA2 -#ifndef CONFIG_OPL3SA2_DMA2 -#define CONFIG_OPL3SA2_DMA2 CONFIG_OPL3SA2_DMA -#endif - {SNDCARD_OPL3SA2, {CONFIG_OPL3SA2_CTRL_BASE, CONFIG_OPL3SA2_IRQ, CONFIG_OPL3SA2_DMA, CONFIG_OPL3SA2_DMA2}, SND_DEFAULT_ENABLE}, - {SNDCARD_OPL3SA2_MSS, {CONFIG_OPL3SA2_BASE, CONFIG_OPL3SA2_IRQ, CONFIG_OPL3SA2_DMA, CONFIG_OPL3SA2_DMA2}, SND_DEFAULT_ENABLE}, -#ifdef CONFIG_OPL3SA2_MPU_BASE - {SNDCARD_OPL3SA2_MPU, {CONFIG_OPL3SA2_MPU_BASE, CONFIG_OPL3SA2_MPU_IRQ, CONFIG_OPL3SA2_DMA, -1}, SND_DEFAULT_ENABLE}, -#endif -#endif - -#ifdef CONFIG_SGALAXY -#ifndef CONFIG_SGALAXY_DMA2 -#define CONFIG_SGALAXY_DMA2 CONFIG_SGALAXY_DMA -#endif - {SNDCARD_SGALAXY, {CONFIG_SGALAXY_BASE, CONFIG_SGALAXY_IRQ, CONFIG_SGALAXY_DMA, CONFIG_SGALAXY_DMA2, 0, NULL, CONFIG_SGALAXY_SGBASE}, SND_DEFAULT_ENABLE}, -#endif - - -#ifdef CONFIG_SOUND_MSS -#ifndef CONFIG_MSS_DMA2 -#define CONFIG_MSS_DMA2 -1 -#endif - -#ifdef DESKPROXL - {SNDCARD_DESKPROXL, {CONFIG_MSS_BASE, CONFIG_MSS_IRQ, CONFIG_MSS_DMA, CONFIG_MSS_DMA2}, SND_DEFAULT_ENABLE}, -#else - {SNDCARD_MSS, {CONFIG_MSS_BASE, CONFIG_MSS_IRQ, CONFIG_MSS_DMA, CONFIG_MSS_DMA2}, SND_DEFAULT_ENABLE}, -#endif - -#ifdef MSS2_BASE - {SNDCARD_MSS, {MSS2_BASE, MSS2_IRQ, MSS2_DMA, MSS2_DMA2}, SND_DEFAULT_ENABLE}, -#endif -#endif - -#ifdef CONFIG_SOUND_PAS - {SNDCARD_PAS, {CONFIG_PAS_BASE, CONFIG_PAS_IRQ, CONFIG_PAS_DMA, -1}, SND_DEFAULT_ENABLE}, -#endif - -#ifdef CONFIG_SOUND_SB -#ifndef CONFIG_SB_DMA -#define CONFIG_SB_DMA 1 -#endif -#ifndef CONFIG_SB_DMA2 -#define CONFIG_SB_DMA2 -1 -#endif - {SNDCARD_SB, {CONFIG_SB_BASE, CONFIG_SB_IRQ, CONFIG_SB_DMA, CONFIG_SB_DMA2}, SND_DEFAULT_ENABLE}, -#ifdef SB2_BASE - {SNDCARD_SB, {SB2_BASE, SB2_IRQ, SB2_DMA, SB2_DMA2}, SND_DEFAULT_ENABLE}, -#endif -#endif - -#if defined(CONFIG_WAVEFRONT) - {SNDCARD_WAVEFRONT, {WAVEFRONT_BASE, WAVEFRONT_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, -#endif - -#ifdef CONFIG_SOUND_MAUI - {SNDCARD_MAUI, {CONFIG_MAUI_BASE, CONFIG_MAUI_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, -#endif - -#ifdef CONFIG_SOUND_MPU401 - {SNDCARD_MPU401, {CONFIG_MPU_BASE, CONFIG_MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, -#ifdef MPU2_BASE - {SNDCARD_MPU401, {MPU2_BASE, MPU2_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, -#endif -#ifdef MPU3_BASE - {SNDCARD_MPU401, {MPU3_BASE, MPU3_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, -#endif -#endif - -#ifdef CONFIG_SOUND_UART6850 - {SNDCARD_UART6850, {CONFIG_U6850_BASE, CONFIG_U6850_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, -#endif - -#ifdef CONFIG_SOUND_SB -#ifdef CONFIG_SB_MPU_BASE - {SNDCARD_SB16MIDI,{CONFIG_SB_MPU_BASE, CONFIG_SB_MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE}, -#endif -#endif - -#ifdef CONFIG_SOUND_GUS -#ifndef CONFIG_GUS_DMA2 -#define CONFIG_GUS_DMA2 CONFIG_GUS_DMA -#endif -#ifdef CONFIG_GUS16 - {SNDCARD_GUS16, {CONFIG_GUS16_BASE, CONFIG_GUS16_IRQ, CONFIG_GUS16_DMA, -1}, SND_DEFAULT_ENABLE}, -#endif - {SNDCARD_GUS, {CONFIG_GUS_BASE, CONFIG_GUS_IRQ, CONFIG_GUS_DMA, CONFIG_GUS_DMA2}, SND_DEFAULT_ENABLE}, -#endif - -#ifdef CONFIG_SOUND_YM3812 - {SNDCARD_ADLIB, {FM_MONO, 0, 0, -1}, SND_DEFAULT_ENABLE}, -#endif - -#ifdef CONFIG_SOUND_VMIDI - {SNDCARD_VMIDI, {0, 0, 0, -1}, SND_DEFAULT_ENABLE}, -#endif - -#ifdef CONFIG_SOUND_VIDC - { SNDCARD_VIDC, {0, 0, 0, 0}, SND_DEFAULT_ENABLE }, -#endif - -#ifdef CONFIG_SOUND_WAVEARTIST - { SNDCARD_WAVEARTIST, { CONFIG_WAVEARTIST_BASE, CONFIG_WAVEARTIST_IRQ, CONFIG_WAVEARTIST_DMA, CONFIG_WAVEARTIST_DMA2 }, SND_DEFAULT_ENABLE }, -#endif - {0, {0}, 0} -}; - -int num_sound_cards = sizeof(snd_installed_cards) / sizeof (struct card_info); -static int max_sound_cards = sizeof(snd_installed_cards) / sizeof (struct card_info); - -#if defined(MODULE) -int trace_init = 0; -#else -int trace_init = 1; -#endif #else extern struct audio_operations * audio_devs[MAX_AUDIO_DEV]; extern int num_audiodevs; @@ -689,30 +377,16 @@ extern struct mixer_operations * mixer_devs[MAX_MIXER_DEV]; extern int num_mixer extern struct synth_operations * synth_devs[MAX_SYNTH_DEV+MAX_MIDI_DEV]; extern int num_synths; extern struct midi_operations * midi_devs[MAX_MIDI_DEV]; extern int num_midis; extern struct sound_timer_operations * sound_timer_devs[MAX_TIMER_DEV]; extern int num_sound_timers; - -extern struct driver_info sound_drivers[]; -extern int num_sound_drivers; -extern struct card_info snd_installed_cards[]; -extern int num_sound_cards; - -extern int trace_init; #endif /* _DEV_TABLE_C_ */ -void sndtable_init(void); +void setup_cards(void); int sndtable_get_cardcount (void); -struct address_info *sound_getconf(int card_type); void sound_chconf(int card_type, int ioaddr, int irq, int dma); int snd_find_driver(int type); -void sound_unload_drivers(void); void sound_unload_driver(int type); int sndtable_identify_card(char *name); -#if FIXED_FOR_2_4_0 -void sound_setup (char *str, int *ints); -#endif - extern int sound_map_buffer (int dev, struct dma_buffparms *dmap, buffmem_desc *info); int sndtable_probe (int unit, struct address_info *hw_config); -int sndtable_init_card (int unit, struct address_info *hw_config); int sndtable_start_card (int unit, struct address_info *hw_config); void sound_timer_init (struct sound_lowlev_timer *t, char *name); void sound_dma_intr (int dev, struct dma_buffparms *dmap, int chan); diff --git a/drivers/sound/gus.h b/drivers/sound/gus.h new file mode 100644 index 000000000..fe795ecdb --- /dev/null +++ b/drivers/sound/gus.h @@ -0,0 +1,30 @@ +/* + * gus.h + * + * Copyright: Christoph Hellwig + * + */ + +#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); diff --git a/drivers/sound/gus_card.c b/drivers/sound/gus_card.c index 6a42c4ce5..1029f179a 100644 --- a/drivers/sound/gus_card.c +++ b/drivers/sound/gus_card.c @@ -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 +#include #include #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 diff --git a/drivers/sound/gus_midi.c b/drivers/sound/gus_midi.c index 92987f46d..1594afb1a 100644 --- a/drivers/sound/gus_midi.c +++ b/drivers/sound/gus_midi.c @@ -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; diff --git a/drivers/sound/gus_vol.c b/drivers/sound/gus_vol.c index 8951cbfc3..6ae6924e1 100644 --- a/drivers/sound/gus_vol.c +++ b/drivers/sound/gus_vol.c @@ -1,8 +1,8 @@ /* * 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 diff --git a/drivers/sound/gus_wave.c b/drivers/sound/gus_wave.c index 16eac5769..30ba0ede3 100644 --- a/drivers/sound/gus_wave.c +++ b/drivers/sound/gus_wave.c @@ -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 + +#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, diff --git a/drivers/sound/ics2101.c b/drivers/sound/ics2101.c index a6b6fb4cc..3b97a157b 100644 --- a/drivers/sound/ics2101.c +++ b/drivers/sound/ics2101.c @@ -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 + +#include "gus.h" #include "gus_hw.h" #define MIX_DEVS (SOUND_MASK_MIC|SOUND_MASK_LINE| \ diff --git a/drivers/sound/mad16.c b/drivers/sound/mad16.c index dedf7c843..06b98aec2 100644 --- a/drivers/sound/mad16.c +++ b/drivers/sound/mad16.c @@ -1,14 +1,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. - */ -#include -#include -/* - * 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 +#include +#include + #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 diff --git a/drivers/sound/maui.c b/drivers/sound/maui.c index 532e7573b..797150997 100644 --- a/drivers/sound/maui.c +++ b/drivers/sound/maui.c @@ -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 @@ failure: 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 diff --git a/drivers/sound/mpu401.c b/drivers/sound/mpu401.c index 8a334d263..2757659ac 100644 --- a/drivers/sound/mpu401.c +++ b/drivers/sound/mpu401.c @@ -15,6 +15,7 @@ * Alan Cox modularisation, use normal request_irq, use dev_id */ +#include #include #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 diff --git a/drivers/sound/mpu401.h b/drivers/sound/mpu401.h new file mode 100644 index 000000000..a6a41cbde --- /dev/null +++ b/drivers/sound/mpu401.h @@ -0,0 +1,21 @@ +/* + * uart401.h + * + * Copyright: Christoph Hellwig + * + */ + +/* 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); diff --git a/drivers/sound/nm256_audio.c b/drivers/sound/nm256_audio.c index 53e54404a..ef0a1ce2e 100644 --- a/drivers/sound/nm256_audio.c +++ b/drivers/sound/nm256_audio.c @@ -15,6 +15,7 @@ #define __NO_VERSION__ #include +#include #include #include #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 diff --git a/drivers/sound/opl3.c b/drivers/sound/opl3.c index acaf989ca..951dfe4d3 100644 --- a/drivers/sound/opl3.c +++ b/drivers/sound/opl3.c @@ -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 #include #include @@ -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 diff --git a/drivers/sound/opl3.h b/drivers/sound/opl3.h index 5529d19d8..6ef00614b 100644 --- a/drivers/sound/opl3.h +++ b/drivers/sound/opl3.h @@ -1,244 +1,11 @@ /* - * 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 * - * 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); diff --git a/drivers/sound/opl3_hw.h b/drivers/sound/opl3_hw.h new file mode 100644 index 000000000..8b11c893e --- /dev/null +++ b/drivers/sound/opl3_hw.h @@ -0,0 +1,246 @@ +/* + * 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 + */ diff --git a/drivers/sound/opl3sa.c b/drivers/sound/opl3sa.c index 721157fdd..6b82d2a17 100644 --- a/drivers/sound/opl3sa.c +++ b/drivers/sound/opl3sa.c @@ -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 #include #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 diff --git a/drivers/sound/opl3sa2.c b/drivers/sound/opl3sa2.c index c3fff526f..23f85733e 100644 --- a/drivers/sound/opl3sa2.c +++ b/drivers/sound/opl3sa2.c @@ -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 +#include #include #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 "); -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 diff --git a/drivers/sound/pas2.h b/drivers/sound/pas2.h new file mode 100644 index 000000000..7ac521fe0 --- /dev/null +++ b/drivers/sound/pas2.h @@ -0,0 +1,23 @@ +/* + * pas2.h + * + * Copyright: Christoph Hellwig + * + */ + +/* 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); diff --git a/drivers/sound/pas2_card.c b/drivers/sound/pas2_card.c index 762871063..68936e577 100644 --- a/drivers/sound/pas2_card.c +++ b/drivers/sound/pas2_card.c @@ -5,10 +5,14 @@ */ #include +#include #include #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 diff --git a/drivers/sound/pas2_midi.c b/drivers/sound/pas2_midi.c index 83d6ff5bd..385bdd1db 100644 --- a/drivers/sound/pas2_midi.c +++ b/drivers/sound/pas2_midi.c @@ -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; diff --git a/drivers/sound/pas2_mixer.c b/drivers/sound/pas2_mixer.c index 1f2f12336..86e9a50ca 100644 --- a/drivers/sound/pas2_mixer.c +++ b/drivers/sound/pas2_mixer.c @@ -17,6 +17,8 @@ */ #include "sound_config.h" +#include "pas2.h" + #ifndef DEB #define DEB(what) /* (what) */ #endif diff --git a/drivers/sound/pas2_pcm.c b/drivers/sound/pas2_pcm.c index 36fc7f72b..5a79ebb86 100644 --- a/drivers/sound/pas2_pcm.c +++ b/drivers/sound/pas2_pcm.c @@ -16,6 +16,8 @@ #include "sound_config.h" +#include "pas2.h" + #ifndef DEB #define DEB(WHAT) #endif diff --git a/drivers/sound/pss.c b/drivers/sound/pss.c index ffbb08b77..7e883a625 100644 --- a/drivers/sound/pss.c +++ b/drivers/sound/pss.c @@ -24,16 +24,22 @@ * To probe_pss_mss added test for initialize AD1848 * 98-05-28: Vladimir Michl * Fixed computation of mixer volumes + * 00-03-03: Christoph Hellwig + * Adapted to module_init/module_exit */ #include +#include #include #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 diff --git a/drivers/sound/sb.h b/drivers/sound/sb.h index b2eef8254..282e644a3 100644 --- a/drivers/sound/sb.h +++ b/drivers/sound/sb.h @@ -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); diff --git a/drivers/sound/sb_card.c b/drivers/sound/sb_card.c index 49a55288f..7e3ecb1a1 100644 --- a/drivers/sound/sb_card.c +++ b/drivers/sound/sb_card.c @@ -11,19 +11,22 @@ * for more info. * * - * 26th November 1999 - patched to compile without ISA PnP support in the - * kernel. -Daniel Stone (tamriel@ductape.net) + * 26-11-1999 Patched to compile without ISA PnP support in the + * kernel - Daniel Stone (tamriel@ductape.net) * * 06-01-2000 Refined and bugfixed ISA PnP support, added * CMI 8330 support - Alessandro Zummo * + * 18-01-2000 Separated sb_card and sb_common + * Jeff Garzik + * * 04-02-2000 Added Soundblaster AWE 64 PnP support, isapnpjump * Alessandro Zummo * * 11-02-2000 Added Soundblaster AWE 32 PnP support, refined PnP code * Alessandro Zummo * - * 13-02-2000 Hopefully fixed awe/sb16 related bugs, code cleanup. + * 13-02-2000 Hopefully fixed awe/sb16 related bugs, code cleanup * Alessandro Zummo * */ @@ -42,14 +45,23 @@ static int sbmpu = 0; -void attach_sb_card(struct address_info *hw_config) +extern void *smw_free; + +static void __init attach_sb_card(struct address_info *hw_config) { if(!sb_dsp_init(hw_config)) hw_config->slots[0] = -1; + SOUND_LOCK; } -int probe_sb(struct address_info *hw_config) +static int __init probe_sb(struct address_info *hw_config) { + if (hw_config->io_base == -1 || hw_config->dma == -1 || hw_config->irq == -1) + { + printk(KERN_ERR "sb_card: I/O, IRQ, and DMA are mandatory\n"); + return -EINVAL; + } + #ifdef CONFIG_MCA /* MCA code added by ZP Gu (zpg@castle.net) */ if (MCA_bus) { /* no multiple REPLY card probing */ @@ -121,19 +133,16 @@ iobase=0x%x irq=%d lo_dma=%d hi_dma=%d\n", return sb_dsp_detect(hw_config, 0, 0); } -void unload_sb(struct address_info *hw_config) +static void __exit unload_sb(struct address_info *hw_config) { if(hw_config->slots[0]!=-1) sb_dsp_unload(hw_config, sbmpu); } -int sb_be_quiet=0; extern int esstype; /* ESS chip type */ -#ifdef MODULE - -static struct address_info config; -static struct address_info config_mpu; +static struct address_info cfg; +static struct address_info cfg_mpu; struct pci_dev *sb_dev = NULL, *wss_dev = NULL, @@ -146,25 +155,21 @@ struct pci_dev *sb_dev = NULL, * to the 8bit channel. */ -int mpu_io = 0; -int io = -1; -int irq = -1; -int dma = -1; -int dma16 = -1; /* Set this for modules that need it */ -int type = 0; /* Can set this to a specific card type */ -int mad16 = 0; /* Set mad16=1 to load this as support for mad16 */ -int trix = 0; /* Set trix=1 to load this as support for trix */ -int pas2 = 0; /* Set pas2=1 to load this as support for pas2 */ -int support = 0; /* Set support to load this as a support module */ -int sm_games = 0; /* Mixer - see sb_mixer.c */ -int acer = 0; /* Do acer notebook init */ +static int __initdata mpu_io = 0; +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; /* Can set this to a specific card type */ + #if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE -int isapnp = 1; -int isapnpjump = 0; -int nosbwave = 0; /* This option will be removed when the new awe_wave driver will be in the kernel tree */ +static int isapnp = 1; +static int isapnpjump = 0; +static int nosbwave = 0; /* This option will be removed when the new awe_wave driver will be + in the kernel tree */ #else -int isapnp = 0; +int isapnp = 0; #endif MODULE_DESCRIPTION("Soundblaster driver"); @@ -175,10 +180,6 @@ MODULE_PARM(dma, "i"); MODULE_PARM(dma16, "i"); MODULE_PARM(mpu_io, "i"); MODULE_PARM(type, "i"); -MODULE_PARM(mad16, "i"); -MODULE_PARM(support, "i"); -MODULE_PARM(trix, "i"); -MODULE_PARM(pas2, "i"); MODULE_PARM(sm_games, "i"); MODULE_PARM(esstype, "i"); MODULE_PARM(acer, "i"); @@ -198,16 +199,10 @@ MODULE_PARM_DESC(dma, "8-bit DMA channel (0,1,3)"); MODULE_PARM_DESC(dma16, "16-bit DMA channel (5,6,7)"); MODULE_PARM_DESC(mpu_io, "Mpu base address"); MODULE_PARM_DESC(type, "You can set this to specific card type"); -MODULE_PARM_DESC(mad16, "Enable MAD16 support"); -MODULE_PARM_DESC(trix, "Enable Audiotrix support"); -MODULE_PARM_DESC(pas2, "Enable Pas2 support"); -MODULE_PARM_DESC(support, "Set this to load as generic support module"); MODULE_PARM_DESC(sm_games, "Enable support for Logitech soundman games"); MODULE_PARM_DESC(esstype, "ESS chip type"); MODULE_PARM_DESC(acer, "Set this to detect cards in some ACER notebooks"); -void *smw_free = NULL; - #if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE /* That's useful. */ @@ -394,6 +389,97 @@ static struct pci_dev *sb_init_cmi(struct pci_bus *bus, struct pci_dev *card, st return(sb_dev); } +static struct pci_dev *sb_init_diamond(struct pci_bus *bus, struct pci_dev *card, struct address_info *hw_config, struct address_info *mpu_config) +{ + /* + * Diamonds DT0197H + * very similar to the CMI8330 above + */ + + /* @@@0001:Soundblaster. + */ + + if((sb_dev = isapnp_find_dev(bus, + ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001), NULL))) + { + sb_dev->prepare(sb_dev); + + if((sb_dev = activate_dev("DT0197H", "sb", sb_dev))) + { + hw_config->io_base = sb_dev->resource[0].start; + hw_config->irq = sb_dev->irq_resource[0].start; + hw_config->dma = sb_dev->dma_resource[0].start; + hw_config->dma2 = -1; + + show_base("DT0197H", "sb", &sb_dev->resource[0]); + } + + if(!sb_dev) return(NULL); + + } + else + printk(KERN_ERR "sb: DT0197H panic: sb base not found\n"); + + /* @X@0001:mpu + */ + +#ifdef CONFIG_MIDI + if((mpu_dev = isapnp_find_dev(bus, + ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001), NULL))) + { + mpu_dev->prepare(mpu_dev); + + if((mpu_dev = activate_dev("DT0197H", "mpu", mpu_dev))) + { + show_base("DT0197H", "mpu", &mpu_dev->resource[0]); + mpu_config->io_base = mpu_dev->resource[0].start; + } + } + else + printk(KERN_ERR "sb: DT0197H panic: mpu not found\n"); +#endif + + + /* @P@:Gameport + */ + + if((jp_dev = isapnp_find_dev(bus, + ISAPNP_VENDOR('@','P','@'), ISAPNP_FUNCTION(0x0001), NULL))) + { + jp_dev->prepare(jp_dev); + + if((jp_dev = activate_dev("DT0197H", "gameport", jp_dev))) + show_base("DT0197H", "gameport", &jp_dev->resource[0]); + } + else + printk(KERN_ERR "sb: DT0197H panic: gameport not found\n"); + + /* @H@0001:OPL3 + */ + +#if defined(CONFIG_SOUND_YM3812) || defined(CONFIG_SOUND_YM3812_MODULE) + if((wss_dev = isapnp_find_dev(bus, + ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001), NULL))) + { + wss_dev->prepare(wss_dev); + + /* Let's disable IRQ and DMA for WSS device */ + + wss_dev->irq_resource[0].flags = 0; + wss_dev->dma_resource[0].flags = 0; + + if((wss_dev = activate_dev("DT0197H", "opl3", wss_dev))) + show_base("DT0197H", "opl3", &wss_dev->resource[0]); + } + else + printk(KERN_ERR "sb: DT0197H panic: opl3 not found\n"); +#endif + + printk(KERN_INFO "sb: DT0197H mail reports to Torsten Werner \n"); + + return(sb_dev); +} + /* Specific support for awe will be dropped when: * a) The new awe_wawe driver with PnP support will be introduced in the kernel * b) The joystick driver will support PnP - a little patch is available from me....hint, hint :-) @@ -491,12 +577,14 @@ isapnp_sb_list[] __initdata = { {ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x009D), 0, &sb_init_awe, "Sound Blaster AWE 64" }, {ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x00C5), 0, &sb_init_awe, "Sound Blaster AWE 64" }, {ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x00E4), 0, &sb_init_awe, "Sound Blaster AWE 64" }, + {ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x0968), SBF_DEV, &sb_init_ess, "ESS 1688" }, {ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1868), SBF_DEV, &sb_init_ess, "ESS 1868" }, {ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x8611), SBF_DEV, &sb_init_ess, "ESS 1868" }, {ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1869), SBF_DEV, &sb_init_ess, "ESS 1869" }, {ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1878), SBF_DEV, &sb_init_ess, "ESS 1878" }, {ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1879), SBF_DEV, &sb_init_ess, "ESS 1879" }, {ISAPNP_VENDOR('C','M','I'), ISAPNP_FUNCTION(0x0001), 0, &sb_init_cmi, "CMI 8330 SoundPRO" }, + {ISAPNP_VENDOR('R','W','B'), ISAPNP_FUNCTION(0x1688), 0, &sb_init_diamond, "Diamond DT0197H" }, {0} }; @@ -538,7 +626,7 @@ static int __init sb_init_isapnp(struct address_info *hw_config, struct address_ Should this be fixed? - azummo */ -static int __init sb_probe_isapnp(struct address_info *hw_config, struct address_info *mpu_config) +int __init sb_probe_isapnp(struct address_info *hw_config, struct address_info *mpu_config) { int i; @@ -594,65 +682,55 @@ static int __init sb_probe_isapnp(struct address_info *hw_config, struct address } #endif -int init_module(void) +static int __init init_sb(void) { printk(KERN_INFO "Soundblaster audio driver Copyright (C) by Hannu Savolainen 1993-1996\n"); - if (mad16 == 0 && trix == 0 && pas2 == 0 && support == 0) - { - /* Please remember that even with CONFIG_ISAPNP defined one should still be - able to disable PNP support for this single driver! - */ + /* Please remember that even with CONFIG_ISAPNP defined one should still be + able to disable PNP support for this single driver! + */ #if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE - if(isapnp && (sb_probe_isapnp(&config, &config_mpu) < 0) ) - { - printk(KERN_NOTICE "sb_card: No ISAPnP cards found, trying standard ones...\n"); - isapnp = 0; - } + if(isapnp && (sb_probe_isapnp(&cfg, &cfg_mpu) < 0) ) { + printk(KERN_NOTICE "sb_card: No ISAPnP cards found, trying standard ones...\n"); + isapnp = 0; + } #endif - if(isapnp == 0) - { - if (io == -1 || dma == -1 || irq == -1) - { - printk(KERN_ERR "sb_card: I/O, IRQ, and DMA are mandatory\n"); - return -EINVAL; - } - config.io_base = io; - config.irq = irq; - config.dma = dma; - config.dma2 = dma16; - } + if( isapnp == 0 ) { + cfg.io_base = io; + cfg.irq = irq; + cfg.dma = dma; + cfg.dma2 = dma16; + } - config.card_subtype = type; + cfg.card_subtype = type; - if (!probe_sb(&config)) - return -ENODEV; - attach_sb_card(&config); - - if(config.slots[0]==-1) - return -ENODEV; - - if (isapnp == 0) - config_mpu.io_base = mpu_io; - if (probe_sbmpu(&config_mpu)) - sbmpu = 1; - if (sbmpu) - attach_sbmpu(&config_mpu); - } - SOUND_LOCK; + if (!probe_sb(&cfg)) + return -ENODEV; + attach_sb_card(&cfg); + + if(cfg.slots[0]==-1) + return -ENODEV; + + if (isapnp == 0) + cfg_mpu.io_base = mpu_io; + if (probe_sbmpu(&cfg_mpu)) + sbmpu = 1; + if (sbmpu) + attach_sbmpu(&cfg_mpu); return 0; } -void cleanup_module(void) +static void __exit cleanup_sb(void) { - if (smw_free) + if (smw_free) { vfree(smw_free); - if (!mad16 && !trix && !pas2 && !support) - unload_sb(&config); + smw_free = NULL; + } + unload_sb(&cfg); if (sbmpu) - unload_sbmpu(&config_mpu); + unload_sbmpu(&cfg_mpu); SOUND_LOCK_END; if(sb_dev) sb_dev->deactivate(sb_dev); @@ -662,28 +740,23 @@ void cleanup_module(void) if(wss_dev) wss_dev->deactivate(wss_dev); } -#else +module_init(init_sb); +module_exit(cleanup_sb); -#ifdef CONFIG_SM_GAMES -int sm_games = 1; -#else -int sm_games = 0; -#endif -#ifdef CONFIG_SB_ACER -int acer = 1; -#else -int acer = 0; -#endif -#endif +#ifndef MODULE +static int __init setup_sb(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]; -EXPORT_SYMBOL(sb_dsp_init); -EXPORT_SYMBOL(sb_dsp_detect); -EXPORT_SYMBOL(sb_dsp_unload); -EXPORT_SYMBOL(sb_dsp_disable_midi); -EXPORT_SYMBOL(attach_sb_card); -EXPORT_SYMBOL(probe_sb); -EXPORT_SYMBOL(unload_sb); -EXPORT_SYMBOL(sb_be_quiet); -EXPORT_SYMBOL(attach_sbmpu); -EXPORT_SYMBOL(probe_sbmpu); -EXPORT_SYMBOL(unload_sbmpu); + return 1; +} +__setup("sb=", setup_sb); +#endif diff --git a/drivers/sound/sb_common.c b/drivers/sound/sb_common.c index bda10bfad..ffb1204ad 100644 --- a/drivers/sound/sb_common.c +++ b/drivers/sound/sb_common.c @@ -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 + * */ + +/* FIXME: *grr* why can't the f**in Makefile do this for me ? */ +#define EXPORT_SYMTAB + #include -#include #include +#include +#include #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); diff --git a/drivers/sound/sgalaxy.c b/drivers/sound/sgalaxy.c index 6859b20c3..7c02ee8b2 100644 --- a/drivers/sound/sgalaxy.c +++ b/drivers/sound/sgalaxy.c @@ -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 #include #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 diff --git a/drivers/sound/softoss.c b/drivers/sound/softoss.c index ac8e4034f..0ef54e6d0 100644 --- a/drivers/sound/softoss.c +++ b/drivers/sound/softoss.c @@ -11,9 +11,12 @@ * for more info. * * - * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed) + * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed) + * Christoph Hellwig : adapted to module_init/module_exit */ + #include +#include #include /* @@ -1445,7 +1448,7 @@ static struct sound_lowlev_timer soft_tmr = soft_tmr_restart }; -int probe_softsyn(struct address_info *hw_config) +static int __init probe_softsyn(struct address_info *hw_config) { int i; @@ -1484,7 +1487,7 @@ int probe_softsyn(struct address_info *hw_config) return 1; } -void attach_softsyn_card(struct address_info *hw_config) +static void __init attach_softsyn_card(struct address_info *hw_config) { voice_alloc = &softsyn_operations.alloc; synth_devs[devc->synthdev = num_synths++] = &softsyn_operations; @@ -1497,7 +1500,7 @@ void attach_softsyn_card(struct address_info *hw_config) #endif } -void unload_softsyn(struct address_info *hw_config) +static void __exit unload_softsyn(struct address_info *hw_config) { if (!softsynth_loaded) return; @@ -1506,25 +1509,25 @@ void unload_softsyn(struct address_info *hw_config) reset_samples(devc); } -#ifdef MODULE - -static struct address_info config; +static struct address_info cfg; -int init_module(void) +static int __init init_softoss(void) { printk(KERN_INFO "SoftOSS driver Copyright (C) by Hannu Savolainen 1993-1997\n"); - if (!probe_softsyn(&config)) + if (!probe_softsyn(&cfg)) return -ENODEV; - attach_softsyn_card(&config); + attach_softsyn_card(&cfg); SOUND_LOCK; return 0; } -void cleanup_module(void) +static void __exit cleanup_softoss(void) { - unload_softsyn(&config); + unload_softsyn(&cfg); sound_unload_synthdev(devc->synthdev); sound_unload_timerdev(devc->timerdev); SOUND_LOCK_END; } -#endif /* MODULE */ + +module_init(init_softoss); +module_exit(cleanup_softoss); diff --git a/drivers/sound/sound_calls.h b/drivers/sound/sound_calls.h index 1029df1f2..8d450ca66 100644 --- a/drivers/sound/sound_calls.h +++ b/drivers/sound/sound_calls.h @@ -76,10 +76,6 @@ int MIDIbuf_avail(int dev); void MIDIbuf_bytes_received(int dev, unsigned char *buf, int count); void MIDIbuf_init(void); -/* - * - * Misc calls from various sources - */ /* From soundcard.c */ void request_sound_timer (int count); @@ -87,237 +83,16 @@ void sound_stop_timer(void); void conf_printf(char *name, struct address_info *hw_config); void conf_printf2(char *name, int base, int irq, int dma, int dma2); -/* From opl3.c */ -int opl3_detect (int ioaddr, int *osp); -int opl3_init(int ioaddr, int *osp); - -/* From sb_card.c */ -void attach_sb_card(struct address_info *hw_config); -int probe_sb(struct address_info *hw_config); - -/* 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); - -/* From uart401.c */ -void attach_uart401 (struct address_info *hw_config); -int probe_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 adlib_card.c */ -void attach_adlib_card(struct address_info *hw_config); -int probe_adlib(struct address_info *hw_config); - -/* From pas_card.c */ -void attach_pas_card(struct address_info *hw_config); -int probe_pas(struct address_info *hw_config); -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); - -/* From gus_card.c */ -void attach_gus_card(struct address_info * hw_config); -int probe_gus(struct address_info *hw_config); -int gus_set_midi_irq(int num); -void gusintr(int irq, void *dev_id, struct pt_regs * dummy); -void attach_gus_db16(struct address_info * hw_config); -int probe_gus_db16(struct address_info *hw_config); - -/* 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 mpu401.c */ -void attach_mpu401(struct address_info * hw_config); -int probe_mpu401(struct address_info *hw_config); -int intchk_mpu401(void *dev_id); -void mpuintr(int irq, void *dev_id, struct pt_regs * dummy); - -/* From uart6850.c */ -void attach_uart6850(struct address_info * hw_config); -int probe_uart6850(struct address_info *hw_config); - -/* From opl3.c */ -void enable_opl3_mode(int left, int right, int both); - -/* From ics2101.c */ -int ics2101_mixer_init(void); - /* From sound_timer.c */ void sound_timer_interrupt(void); void sound_timer_syncinterval(unsigned int new_usecs); -/* From ad1848.c */ -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); -#define AD_F_CS4231 0x0001 /* Returned if a CS4232 (or compatible) detected */ -#define AD_F_CS4248 0x0001 /* Returned if a CS4248 (or compatible) detected */ - -int ad1848_control(int cmd, int arg); -#define AD1848_SET_XTAL 1 -#define AD1848_MIXER_REROUTE 2 -#define AD1848_REROUTE(oldctl, newctl) \ - ad1848_control(AD1848_MIXER_REROUTE, ((oldctl)<<8)|(newctl)) - -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); - -/* From pss.c */ -int probe_pss (struct address_info *hw_config); -void attach_pss (struct address_info *hw_config); -int probe_pss_mpu (struct address_info *hw_config); -void attach_pss_mpu (struct address_info *hw_config); -int probe_pss_mss (struct address_info *hw_config); -void attach_pss_mss (struct address_info *hw_config); - -/* From sscape.c */ -int probe_sscape (struct address_info *hw_config); -void attach_sscape (struct address_info *hw_config); -int probe_ss_ms_sound (struct address_info *hw_config); -void attach_ss_ms_sound(struct address_info * hw_config); - -/* From ad1816.c */ -void unload_ad1816(struct address_info *hw_info); -int probe_ad1816 (struct address_info *hw_config); -void attach_ad1816 (struct address_info *hw_config); +/* From midi_synth.c */ +void do_midi_msg (int synthno, unsigned char *msg, int mlen); -/* From aedsp16.c */ +#ifdef FIXED_LOWLEVEL_SOUND +/* From aedsp16.c */ int InitAEDSP16_SBPRO(struct address_info *hw_config); int InitAEDSP16_MSS(struct address_info *hw_config); int InitAEDSP16_MPU401(struct address_info *hw_config); - -/* From midi_synth.c */ -void do_midi_msg (int synthno, unsigned char *msg, int mlen); - -/* From trix.c */ -void attach_trix_wss (struct address_info *hw_config); -int probe_trix_wss (struct address_info *hw_config); -void attach_trix_sb (struct address_info *hw_config); -int probe_trix_sb (struct address_info *hw_config); -void attach_trix_mpu (struct address_info *hw_config); -int probe_trix_mpu (struct address_info *hw_config); - -/* From mad16.c */ -void attach_mad16 (struct address_info *hw_config); -int probe_mad16 (struct address_info *hw_config); -void attach_mad16_mpu (struct address_info *hw_config); -int probe_mad16_mpu (struct address_info *hw_config); - -/* Unload routines from various source files*/ -void unload_pss(struct address_info *hw_info); -void unload_pss_mpu(struct address_info *hw_info); -void unload_pss_mss(struct address_info *hw_info); -void unload_mad16(struct address_info *hw_info); -void unload_mad16_mpu(struct address_info *hw_info); -void unload_adlib(struct address_info *hw_info); -void unload_pas(struct address_info *hw_info); -void unload_mpu401(struct address_info *hw_info); -void unload_maui(struct address_info *hw_info); -void unload_uart6850(struct address_info *hw_info); -void unload_sb(struct address_info *hw_info); -void unload_sb16(struct address_info *hw_info); -void unload_sb16midi(struct address_info *hw_info); -void unload_gus_db16(struct address_info *hw_info); -void unload_ms_sound(struct address_info *hw_info); -void unload_gus(struct address_info *hw_info); -void unload_sscape(struct address_info *hw_info); -void unload_ss_ms_sound(struct address_info *hw_info); -void unload_trix_wss(struct address_info *hw_info); -void unload_trix_sb(struct address_info *hw_info); -void unload_trix_mpu(struct address_info *hw_info); -void unload_cs4232(struct address_info *hw_info); -void unload_cs4232_mpu(struct address_info *hw_info); -void unload_opl3sa_wss(struct address_info *hw_info); -void unload_opl3sa_sb(struct address_info *hw_info); -void unload_opl3sa_mpu(struct address_info *hw_info); -void unload_opl3sa2(struct address_info *hw_info); -void unload_opl3sa2_mpu(struct address_info *hw_info); -void unload_opl3sa2_mss(struct address_info *hw_info); -void unload_softsyn (struct address_info *hw_config); - -/* From cs4232.c */ -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); - -/* From opl3sa.c */ -void attach_opl3sa_wss (struct address_info *hw_config); -int probe_opl3sa_wss (struct address_info *hw_config); -void attach_opl3sa_sb (struct address_info *hw_config); -int probe_opl3sa_sb (struct address_info *hw_config); -void attach_opl3sa_mpu (struct address_info *hw_config); -int probe_opl3sa_mpu (struct address_info *hw_config); - -/* From opl3sa2.c */ -int probe_opl3sa2 (struct address_info *hw_config); -void attach_opl3sa2 (struct address_info *hw_config); -int probe_opl3sa2_mpu (struct address_info *hw_config); -void attach_opl3sa2_mpu (struct address_info *hw_config); -int probe_opl3sa2_mss (struct address_info *hw_config); -void attach_opl3sa2_mss (struct address_info *hw_config); - -/* From softoss.c */ -void attach_softsyn_card (struct address_info *hw_config); -int probe_softsyn (struct address_info *hw_config); - -/* From maui.c */ -void attach_maui(struct address_info * hw_config); -int probe_maui(struct address_info *hw_config); - -/* From v_midi.c */ -void attach_v_midi (struct address_info *hw_config); -int probe_v_midi (struct address_info *hw_config); -void unload_v_midi (struct address_info *hw_config); - -/* From vidc.c */ -void attach_vidc(struct address_info *hw_config); -int probe_vidc(struct address_info *hw_config); -void unload_vidc(struct address_info *hw_config); - -/* From waveartist.c */ -void attach_waveartist(struct address_info *hw_config); -int probe_waveartist(struct address_info *hw_config); -void unload_waveartist(struct address_info *hw_config); - -/* From wavefront.c */ -void attach_wavefront (struct address_info *hw_config); -int probe_wavefront (struct address_info *hw_config); -void unload_wavefront (struct address_info *hw_config); - -/* From wf_midi.c */ -void attach_wf_mpu(struct address_info * hw_config); -int probe_wf_mpu(struct address_info *hw_config); -void unload_wf_mpu(struct address_info *hw_config); -int virtual_midi_enable (void); -int virtual_midi_disable (void); +#endif diff --git a/drivers/sound/sound_config.h b/drivers/sound/sound_config.h index 7621f33be..35c39e947 100644 --- a/drivers/sound/sound_config.h +++ b/drivers/sound/sound_config.h @@ -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 diff --git a/drivers/sound/sound_syms.c b/drivers/sound/sound_syms.c index bf3ff10fe..b6f2855be 100644 --- a/drivers/sound/sound_syms.c +++ b/drivers/sound/sound_syms.c @@ -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); diff --git a/drivers/sound/soundcard.c b/drivers/sound/soundcard.c index 81f9cdb19..00f8b6e7b 100644 --- a/drivers/sound/soundcard.c +++ b/drivers/sound/soundcard.c @@ -2,24 +2,24 @@ * linux/drivers/sound/soundcard.c * * Sound card driver for Linux - */ -/* + * + * * 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) + * + * + * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed) * integrated sound_switch.c - * Stefan Reinauer : integrated /proc/sound (equals to /dev/sndstat, + * Stefan Reinauer : integrated /proc/sound (equals to /dev/sndstat, * which should disappear in the near future) - * Eric Dumas : devfs support (22-Jan-98) with fixups - * by C. Scott Ananian - * Richard Gooch : moved common (non OSS-specific) devices to sound_core.c - * - * Rob Riggs Added persistent DMA buffers support (1998/10/17) + * Eric Dumas : devfs support (22-Jan-98) with + * fixups by C. Scott Ananian + * Richard Gooch : moved common (non OSS-specific) devices to sound_core.c + * Rob Riggs : Added persistent DMA buffers support (1998/10/17) + * Christoph Hellwig : Some cleanup work (2000/03/01) */ #include @@ -32,7 +32,6 @@ #include #include #include -#ifdef __KERNEL__ #include #include #include @@ -41,24 +40,23 @@ #include #include #include -#endif /* __KERNEL__ */ #include #include #include #include "soundmodule.h" + +#if defined(CONFIG_LOWLEVEL_SOUND) && !defined MODULE +extern void sound_preinit_lowlevel_drivers(void); +extern void sound_init_lowlevel_drivers(void); +#endif + /* From obsolete legacy.h */ #define SELECTED_SOUND_OPTIONS 0x0 struct notifier_block *sound_locker=(struct notifier_block *)0; static int lock_depth = 0; -#ifdef MODULE -#define modular 1 -#else -#define modular 0 -#endif - /* * This ought to be moved into include/asm/dma.h */ @@ -76,16 +74,9 @@ caddr_t sound_mem_blocks[1024]; int sound_nblocks = 0; /* Persistent DMA buffers */ -#ifdef CONFIG_SOUND_DMAP -int sound_dmap_flag = 1; -#else int sound_dmap_flag = 0; -#endif - static int soundcard_configured = 0; - -static char dma_alloc_map[MAX_DMA_CHANNELS] = -{0}; +static char dma_alloc_map[MAX_DMA_CHANNELS] = {0}; #define DMA_MAP_UNAVAIL 0 #define DMA_MAP_FREE 1 @@ -101,6 +92,8 @@ unsigned long seq_time = 0; /* Time for /dev/sequencer */ static mixer_vol_table mixer_vols[MAX_MIXER_DEV]; static int num_mixer_volumes = 0; +int traceinit = 0; + int *load_mixer_volumes(char *name, int *levels, int present) { int i, n; @@ -159,137 +152,6 @@ static int get_mixer_levels(caddr_t arg) return 0; } -static int sound_proc_get_info(char *buffer, char **start, off_t offset, int length) -{ - int len, i, drv; - off_t pos = 0; - off_t begin = 0; - -#ifdef MODULE -#define MODULEPROCSTRING "Driver loaded as a module" -#else -#define MODULEPROCSTRING "Driver compiled into kernel" -#endif - - down_read(&uts_sem); - - len = sprintf(buffer, "OSS/Free:" SOUND_VERSION_STRING "\n" - "Load type: " MODULEPROCSTRING "\n" - "Kernel: %s %s %s %s %s\n" - "Config options: %x\n\nInstalled drivers: \n", - system_utsname.sysname, system_utsname.nodename, system_utsname.release, - system_utsname.version, system_utsname.machine, SELECTED_SOUND_OPTIONS); - up_read(&uts_sem); - - for (i = 0; (i < num_sound_drivers) && (pos <= offset + length); i++) { - if (!sound_drivers[i].card_type) - continue; - len += sprintf(buffer + len, "Type %d: %s\n", - sound_drivers[i].card_type, sound_drivers[i].name); - pos = begin + len; - if (pos < offset) { - len = 0; - begin = pos; - } - } - len += sprintf(buffer + len, "\nCard config: \n"); - - for (i = 0; (i < num_sound_cards) && (pos <= offset + length); i++) - { - if (!snd_installed_cards[i].card_type) - continue; - if (!snd_installed_cards[i].enabled) - len += sprintf(buffer + len, "("); - if ((drv = snd_find_driver(snd_installed_cards[i].card_type)) != -1) - len += sprintf(buffer + len, "%s", sound_drivers[drv].name); - if (snd_installed_cards[i].config.io_base) - len += sprintf(buffer + len, " at 0x%x", snd_installed_cards[i].config.io_base); - if (snd_installed_cards[i].config.irq != 0) - len += sprintf(buffer + len, " irq %d", abs(snd_installed_cards[i].config.irq)); - if (snd_installed_cards[i].config.dma != -1) { - len += sprintf(buffer + len, " drq %d", snd_installed_cards[i].config.dma); - if (snd_installed_cards[i].config.dma2 != -1) - len += sprintf(buffer + len, ",%d", snd_installed_cards[i].config.dma2); - } - if (!snd_installed_cards[i].enabled) - len += sprintf(buffer + len, ")"); - len += sprintf(buffer + len, "\n"); - pos = begin + len; - if (pos < offset) { - len = 0; - begin = pos; - } - } - if (!sound_started) - len += sprintf(buffer + len, "\n\n***** Sound driver not started *****\n\n"); - len += sprintf(buffer + len, "\nAudio devices:\n"); - for (i = 0; (i < num_audiodevs) && (pos <= offset + length); i++) { - if (audio_devs[i] == NULL) - continue; - len += sprintf(buffer + len, "%d: %s%s\n", i, audio_devs[i]->name, - audio_devs[i]->flags & DMA_DUPLEX ? " (DUPLEX)" : ""); - pos = begin + len; - if (pos < offset) { - len = 0; - begin = pos; - } - } - - len += sprintf(buffer + len, "\nSynth devices:\n"); - for (i = 0; (i < num_synths) && (pos <= offset + length); i++) { - if (synth_devs[i] == NULL) - continue; - len += sprintf(buffer + len, "%d: %s\n", i, synth_devs[i]->info->name); - pos = begin + len; - if (pos < offset) { - len = 0; - begin = pos; - } - } - - len += sprintf(buffer + len, "\nMidi devices:\n"); - for (i = 0; (i < num_midis) && (pos <= offset + length); i++) { - if (midi_devs[i] == NULL) - continue; - len += sprintf(buffer + len, "%d: %s\n", i, midi_devs[i]->info.name); - pos = begin + len; - if (pos < offset) { - len = 0; - begin = pos; - } - } - - len += sprintf(buffer + len, "\nTimers:\n"); - - for (i = 0; (i < num_sound_timers) && (pos <= offset + length); i++) { - if (sound_timer_devs[i] == NULL) - continue; - len += sprintf(buffer + len, "%d: %s\n", i, sound_timer_devs[i]->info.name); - pos = begin + len; - if (pos < offset) { - len = 0; - begin = pos; - } - } - - len += sprintf(buffer + len, "\nMixers:\n"); - for (i = 0; (i < num_mixers) && (pos <= offset + length); i++) { - if (mixer_devs[i] == NULL) - continue; - len += sprintf(buffer + len, "%d: %s\n", i, mixer_devs[i]->name); - pos = begin + len; - if (pos < offset) { - len = 0; - begin = pos; - } - } - *start = buffer + (offset - begin); - len -= (offset - begin); - if (len > length) - len = length; - return len; -} - #ifndef MIN #define MIN(a,b) (((a) < (b)) ? (a) : (b)) #endif @@ -297,67 +159,6 @@ static int sound_proc_get_info(char *buffer, char **start, off_t offset, int len /* 4K page size but our output routines use some slack for overruns */ #define PROC_BLOCK_SIZE (3*1024) -/* - * basically copied from fs/proc/generic.c:proc_file_read - * should be removed sometime in the future together with /dev/sndstat - * (a symlink /dev/sndstat -> /proc/sound will do as well) - */ -static ssize_t sndstat_file_read(struct file * file, char * buf, size_t nbytes, loff_t *ppos) -{ - char *page; - ssize_t retval=0; - int eof=0; - ssize_t n, count; - char *start; - - if (!(page = (char*) __get_free_page(GFP_KERNEL))) - return -ENOMEM; - - while ((nbytes > 0) && !eof) - { - count = MIN(PROC_BLOCK_SIZE, nbytes); - - start = NULL; - n = sound_proc_get_info(page, &start, *ppos, count); - if (n < count) - eof = 1; - - if (!start) { - /* - * For proc files that are less than 4k - */ - start = page + *ppos; - n -= *ppos; - if (n <= 0) - break; - if (n > count) - n = count; - } - if (n == 0) - break; /* End of file */ - if (n < 0) { - if (retval == 0) - retval = n; - break; - } - - n -= copy_to_user(buf, start, n); /* BUG ??? */ - if (n == 0) { - if (retval == 0) - retval = -EFAULT; - break; - } - - *ppos += n; /* Move down the file */ - nbytes -= n; - buf += n; - retval += n; - } - free_page((unsigned long) page); - return retval; -} - - static ssize_t sound_read(struct file *file, char *buf, size_t count, loff_t *ppos) { int dev = MINOR(file->f_dentry->d_inode->i_rdev); @@ -373,10 +174,6 @@ static ssize_t sound_read(struct file *file, char *buf, size_t count, loff_t *pp DEB(printk("sound_read(dev=%d, count=%d)\n", dev, count)); switch (dev & 0x0f) { - case SND_DEV_STATUS: - ret = sndstat_file_read(file, buf, count, ppos); - break; - case SND_DEV_DSP: case SND_DEV_DSP16: case SND_DEV_AUDIO: @@ -484,10 +281,8 @@ static int sound_open(struct inode *inode, struct file *file) } in_use++; -#ifdef CONFIG_MODULES notifier_call_chain(&sound_locker, 1, 0); lock_depth++; -#endif return 0; } @@ -522,10 +317,8 @@ static int sound_release(struct inode *inode, struct file *file) } in_use--; -#ifdef CONFIG_MODULES notifier_call_chain(&sound_locker, 0, 0); lock_depth--; -#endif return 0; } @@ -844,22 +637,13 @@ soundcard_init(void) soundcard_configured = 1; - sndtable_init(); /* Initialize call tables and detect cards */ - - -#ifdef FIXME - if (sndtable_get_cardcount() == 0) - return; /* No cards detected */ +#if defined(CONFIG_LOWLEVEL_SOUND) && !defined(MODULE) + sound_preinit_lowlevel_drivers(); + sound_init_lowlevel_drivers(); #endif - if (num_audiodevs || modular) /* Audio devices present */ - { - audio_init_devices(); - } -#ifdef CONFIG_PROC_FS - if (!create_proc_info_entry("sound", 0, NULL, sound_proc_get_info)) - printk(KERN_ERR "sound: registering /proc/sound failed\n"); -#endif + audio_init_devices(); + soundcard_register_devfs(1); /* register after we know # of devices */ } @@ -876,7 +660,6 @@ static int sound[20] = { 0 }; -int traceinit = 0; static int dmabuf = 0; static int dmabug = 0; @@ -892,8 +675,6 @@ int init_module(void) int i; #endif - trace_init=traceinit; - #ifdef HAS_BRIDGE_BUGGY_FUNC if(dmabug) isa_dma_bridge_buggy = dmabug; @@ -956,7 +737,6 @@ void cleanup_module(void) sound_unload_lowlevel_drivers(); } #endif - sound_unload_drivers(); sequencer_unload(); for (i = 0; i < MAX_DMA_CHANNELS; i++) @@ -1075,9 +855,8 @@ void sound_stop_timer(void) void conf_printf(char *name, struct address_info *hw_config) { - if (!trace_init) + if (!traceinit) return; - printk("<%s> at 0x%03x", name, hw_config->io_base); if (hw_config->irq) @@ -1094,7 +873,7 @@ void conf_printf(char *name, struct address_info *hw_config) void conf_printf2(char *name, int base, int irq, int dma, int dma2) { - if (!trace_init) + if (!traceinit) return; printk("<%s> at 0x%03x", name, base); diff --git a/drivers/sound/soundmodule.h b/drivers/sound/soundmodule.h index b89e74e51..6fb0b00a0 100644 --- a/drivers/sound/soundmodule.h +++ b/drivers/sound/soundmodule.h @@ -2,12 +2,11 @@ #define _SOUNDMODULE_H #include +#include extern struct notifier_block *sound_locker; extern void sound_notifier_chain_register(struct notifier_block *); -#ifdef MODULE - #define SOUND_LOCK sound_notifier_chain_register(&sound_notifier); #define SOUND_LOCK_END notifier_chain_unregister(&sound_locker, &sound_notifier) @@ -28,4 +27,3 @@ static struct notifier_block sound_notifier= }; #endif -#endif diff --git a/drivers/sound/sscape.c b/drivers/sound/sscape.c index 1c06b7c31..5efd99dd2 100644 --- a/drivers/sound/sscape.c +++ b/drivers/sound/sscape.c @@ -2,21 +2,22 @@ * sound/sscape.c * * Low level driver for Ensoniq SoundScape - */ -/* + * + * * 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) * Sergey Smitienko : ensoniq p'n'p support + * Christoph Hellwig : adapted to module_init/module_exit */ #include +#include #include #include "sound_config.h" @@ -30,19 +31,20 @@ #include #include #include -#ifdef __KERNEL__ #include #include #include #include #include #include -#endif /* __KERNEL__ */ #include #include #include "coproc.h" +#include "ad1848.h" +#include "mpu401.h" + /* * I/O ports */ @@ -1005,7 +1007,7 @@ static int sscape_pnp_upload_file(sscape_info* devc, char* fn) return 1; } -static void sscape_pnp_init_hw(sscape_info* devc) +static void __init sscape_pnp_init_hw(sscape_info* devc) { unsigned char midi_irq = 0, sb_irq = 0; unsigned i; @@ -1127,7 +1129,7 @@ static void sscape_pnp_init_hw(sscape_info* devc) sscape_pnp_free_dma(devc); } -static int detect_sscape_pnp(sscape_info* devc) +static int __init detect_sscape_pnp(sscape_info* devc) { long i, irq_bits = 0xff; unsigned int d; @@ -1240,7 +1242,7 @@ static int detect_sscape_pnp(sscape_info* devc) return 1; } -int probe_sscape(struct address_info *hw_config) +static int __init probe_sscape(struct address_info *hw_config) { if (sscape_detected != 0 && sscape_detected != hw_config->io_base) @@ -1289,7 +1291,7 @@ int probe_sscape(struct address_info *hw_config) return 1; } -int probe_ss_ms_sound(struct address_info *hw_config) +static int __init probe_ss_ms_sound(struct address_info *hw_config) { int i, irq_bits = 0xff; int ad_flags = 0; @@ -1332,7 +1334,7 @@ int probe_ss_ms_sound(struct address_info *hw_config) } } -void attach_ss_ms_sound(struct address_info *hw_config) +static void __init attach_ss_ms_sound(struct address_info *hw_config) { /* * This routine configures the SoundScape card for use with the @@ -1413,13 +1415,13 @@ void attach_ss_ms_sound(struct address_info *hw_config) } -void unload_sscape(struct address_info *hw_config) +static void __exit unload_sscape(struct address_info *hw_config) { release_region(devc->base + 2, 6); unload_mpu401(hw_config); } -void unload_ss_ms_sound(struct address_info *hw_config) +static void __exit unload_ss_ms_sound(struct address_info *hw_config) { ad1848_unload(hw_config->io_base, hw_config->irq, @@ -1429,18 +1431,16 @@ void unload_ss_ms_sound(struct address_info *hw_config) sound_unload_audiodev(hw_config->slots[0]); } -#ifdef MODULE - -int dma = -1; -int irq = -1; -int io = -1; +static struct address_info cfg; +static struct address_info cfg_mpu; -int mpu_irq = -1; -int mpu_io = -1; - -int spea = -1; - -static int mss = 0; +static int __initdata spea = -1; +static int __initdata mss = 0; +static int __initdata dma = -1; +static int __initdata irq = -1; +static int __initdata io = -1; +static int __initdata mpu_irq = -1; +static int __initdata mpu_io = -1; MODULE_PARM(dma, "i"); MODULE_PARM(irq, "i"); @@ -1450,63 +1450,80 @@ MODULE_PARM(mpu_irq, "i"); MODULE_PARM(mpu_io, "i"); MODULE_PARM(mss, "i"); -struct address_info config; -struct address_info mpu_config; - -int init_module(void) +static int __init init_sscape(void) { printk(KERN_INFO "Soundscape driver Copyright (C) by Hannu Savolainen 1993-1996\n"); - if (dma == -1 || irq == -1 || io == -1) - { - printk(KERN_ERR "DMA, IRQ, and IO port must be specified.\n"); - return -EINVAL; - } - if (mpu_irq == -1 && mpu_io != -1) - { - printk(KERN_ERR "CONFIG_MPU_IRQ must be specified if CONFIG_MPU_IO is set.\n"); - return -EINVAL; - } - devc->codec = io; - devc->codec_irq = irq; + cfg.irq = irq; + cfg.dma = dma; + cfg.io_base = io; + + cfg_mpu.irq = mpu_irq; + cfg_mpu.io_base = mpu_io; + /* WEH - Try to get right dma channel */ + cfg_mpu.dma = dma; + + devc->codec = cfg.io_base; + devc->codec_irq = cfg.irq; devc->codec_type = 0; devc->ic_type = 0; devc->raw_buf = NULL; - - config.irq = irq; - config.dma = dma; - config.io_base = io; - mpu_config.irq = mpu_irq; - mpu_config.io_base = mpu_io; - /* WEH - Try to get right dma channel */ - mpu_config.dma = dma; - - if(spea != -1) - { + if (cfg.dma == -1 || cfg.irq == -1 || cfg.io_base == -1) { + printk(KERN_ERR "DMA, IRQ, and IO port must be specified.\n"); + return -EINVAL; + } + + if (cfg_mpu.irq == -1 && cfg_mpu.io_base != -1) { + printk(KERN_ERR "MPU_IRQ must be specified if MPU_IO is set.\n"); + return -EINVAL; + } + + if(spea != -1) { old_hardware = spea; printk(KERN_INFO "Forcing %s hardware support.\n", spea?"new":"old"); } - if (probe_sscape(&mpu_config) == 0) + if (probe_sscape(&cfg_mpu) == 0) return -ENODEV; - attach_sscape(&mpu_config); + attach_sscape(&cfg_mpu); - mss = probe_ss_ms_sound(&config); + mss = probe_ss_ms_sound(&cfg); if (mss) - attach_ss_ms_sound(&config); + attach_ss_ms_sound(&cfg); SOUND_LOCK; return 0; } -void cleanup_module(void) +static void __exit cleanup_sscape(void) { if (mss) - unload_ss_ms_sound(&config); + unload_ss_ms_sound(&cfg); SOUND_LOCK_END; - unload_sscape(&mpu_config); + unload_sscape(&cfg_mpu); +} + +module_init(init_sscape); +module_exit(cleanup_sscape); + +#ifndef MODULE +static int __init setup_sscape(char *str) +{ + /* io, irq, dma, mpu_io, mpu_irq */ + int ints[6]; + + str = get_options(str, ARRAY_SIZE(ints), ints); + + io = ints[1]; + irq = ints[2]; + dma = ints[3]; + mpu_io = ints[4]; + mpu_irq = ints[5]; + + return 1; } -#endif /* MODULE */ +__setup("sscape=", setup_sscape); +#endif diff --git a/drivers/sound/trident.c b/drivers/sound/trident.c index de01c6cbe..b3a9f7504 100644 --- a/drivers/sound/trident.c +++ b/drivers/sound/trident.c @@ -29,6 +29,12 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * History + * v0.13 Mar 03 2000 Ollie Lho + * new pci_* for 2.4 kernel, back ported to 2.2 + * v0.12 Feb 23 2000 Ollie Lho + * Preliminary Recording support + * v0.11.2 Feb 19 2000 Ollie Lho + * removed incomplete full-dulplex support * v0.11.1 Jan 28 2000 Ollie Lho * small bug in setting sample rate for 4d-nx (reported by Aaron) * v0.11 Jan 27 2000 Ollie Lho @@ -58,9 +64,10 @@ * Clean up of low level channel register access code. (done) * Fix the bug on dma buffer management in update_ptr, read/write, drain_dac (done) * Dual AC97 codecs support (done partially, need channel binding to test) - * Recording support + * Recording support (done) * Mmap support * "Channel Binding" ioctl extension + * new pci device driver interface for 2.4 kernel */ #include @@ -85,27 +92,15 @@ #include "trident.h" -#undef DEBUG - -#define DRIVER_VERSION "0.11.1" +#define DRIVER_VERSION "0.13" /* magic numbers to protect our data structures */ #define TRIDENT_CARD_MAGIC 0x5072696E /* "Prin" */ #define TRIDENT_STATE_MAGIC 0x63657373 /* "cess" */ -/* The first 32 channels are called Bank A. They are (should be) reserved - for MIDI synthesizer. But since that is not supported yet, we can (ab)use - them to play PCM samples */ -#undef ABUSE_BANK_A - -/* maxinum number of instances of opening /dev/dspN, can your CPU handle this ? - NOTE: If /dev/dsp is opened O_RDWR (i.e. full duplex) it will consume 2 HW - channels */ -#ifdef ABUSE_BANK_A -#define NR_HW_CH 64 -#else +#define TRIDENT_DMA_MASK 0x3fffffff /* DMA buffer mask for pci_alloc_consist */ + #define NR_HW_CH 32 -#endif /* maxinum nuber of AC97 codecs connected, AC97 2.0 defined 4, but 7018 and 4D-NX only have 2 SDATA_IN lines (currently) */ @@ -119,18 +114,29 @@ static const unsigned sample_shift[] = { 0, 1, 1, 2 }; static const char invalid_magic[] = KERN_CRIT "trident: invalid magic value in %s\n"; -struct pci_audio_info { - u16 vendor; - u16 device; - char *name; +enum { + TRIDENT_4D_DX = 0, + TRIDENT_4D_NX, + SIS_7018 }; -static struct pci_audio_info pci_audio_devices[] = { - {PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_DX, "Trident 4DWave DX"}, - {PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_NX, "Trident 4DWave NX"}, - {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_7018, "SiS 7018 PCI Audio"} +static char * card_names[] = { + "Trident 4DWave DX", + "Trident 4DWave NX", + "SiS 7018 PCI Audio" }; +static struct pci_device_id trident_pci_tbl [] __devinitdata = { + {PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_DX, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, TRIDENT_4D_DX}, + {PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_NX, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, TRIDENT_4D_NX}, + {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_7018, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, SIS_7018}, +}; + +MODULE_DEVICE_TABLE (pci, trident_pci_tbl); + /* "software" or virtual channel, an instance of opened /dev/dsp */ struct trident_state { unsigned int magic; @@ -156,14 +162,15 @@ struct trident_state { /* OSS buffer manangemeent stuff */ void *rawbuf; + dma_addr_t dma_handle; unsigned buforder; unsigned numfrag; unsigned fragshift; /* our buffer acts like a circular ring */ - unsigned hwptr; /* where dma last started, update by update_ptr */ + unsigned hwptr; /* where dma last started, updated by update_ptr */ unsigned swptr; /* where driver last clear/filled, updated by read/write */ - int count; /* bytes to be comsumed by dma machine */ + int count; /* bytes to be comsumed or been generated by dma machine */ unsigned total_bytes; /* total bytes dmaed by hardware */ unsigned error; /* number of over/underruns */ @@ -177,22 +184,21 @@ struct trident_state { /* OSS stuff */ unsigned mapped:1; unsigned ready:1; - unsigned endcleared:1; unsigned ossfragshift; int ossmaxfrags; unsigned subdivision; - } dma_dac, dma_adc; + } dmabuf; }; /* hardware channels */ struct trident_channel { int num; /* channel number */ - u32 lba; /* reg 0xe4 */ - u32 eso; /* reg 0xe8 */ - u32 delta; - u16 attribute; /* reg 0xec */ + u32 lba; /* Loop Begine Address, where dma buffer starts */ + u32 eso; /* End Sample Offset, wehre dma buffer ends (in the unit of samples) */ + u32 delta; /* delta value, sample rate / 48k for playback, 48k/sample rate for recording */ + u16 attribute; /* control where PCM data go and come */ u16 fm_vol; - u32 control; /* reg 0xf0 */ + u32 control; /* signed/unsigned, 8/16 bits, mono/stereo */ }; struct trident_pcm_bank_address { @@ -234,7 +240,6 @@ struct trident_card { spinlock_t lock; /* PCI device stuff */ - struct pci_audio_info *pci_info; struct pci_dev * pci_dev; u16 pci_id; @@ -422,9 +427,6 @@ static struct trident_channel * trident_alloc_pcm_channel(struct trident_card *c if (bank->bitmap == ~0UL) { /* no more free channels avaliable */ printk(KERN_ERR "trident: no more channels available on Bank B.\n"); -#ifdef ABUSE_BANK_A - goto bank_a; -#endif return NULL; } for (idx = 31; idx >= 0; idx--) { @@ -435,26 +437,6 @@ static struct trident_channel * trident_alloc_pcm_channel(struct trident_card *c return channel; } } - -#ifdef ABUSE_BANK_A - /* channels in Bank A should be reserved for synthesizer - not for normal use (channels in Bank A can't record) */ - bank_a: - bank = &card->banks[BANK_A]; - if (bank->bitmap == ~0UL) { - /* no more free channels avaliable */ - printk(KERN_ERR "trident: no more channels available on Bank A.\n"); - return NULL; - } - for (idx = 31; idx >= 0; idx--) { - if (!(bank->bitmap & (1 << idx))) { - struct trident_channel *channel = &bank->channels[idx]; - banks->bitmap |= 1 << idx; - channel->num = idx; - return channels; - } - } -#endif return NULL; } @@ -462,13 +444,8 @@ static void trident_free_pcm_channel(struct trident_card *card, int channel) { int bank; -#ifdef ABUSE_BANK_A - if (channel < 0 || channel > 63) - return; -#else if (channel < 31 || channel > 63) return; -#endif bank = channel >> 5; channel = channel & 0x1f; @@ -497,15 +474,12 @@ static int trident_load_channel_registers(struct trident_card *card, u32 *data, } /* called with spin lock held */ -static int trident_write_voice_regs(struct trident_state *state, unsigned int rec) +static int trident_write_voice_regs(struct trident_state *state) { unsigned int data[CHANNEL_REGS + 1]; struct trident_channel *channel; - if (rec) - channel = state->dma_adc.channel; - else - channel = state->dma_dac.channel; + channel = state->dmabuf.channel; data[1] = channel->lba; data[4] = channel->control; @@ -534,7 +508,7 @@ static int trident_write_voice_regs(struct trident_state *state, unsigned int re return trident_load_channel_registers(state->card, data, channel->num); } -static int compute_rate(u32 rate) +static int compute_rate_play(u32 rate) { int delta; /* We special case 44100 and 8000 since rounding with the equation @@ -552,10 +526,25 @@ static int compute_rate(u32 rate) return delta; } +static int compute_rate_rec(u32 rate) +{ + int delta; + + if (rate == 44100) + delta = 0x116a; + else if (rate == 8000) + delta = 0x6000; + else if (rate == 48000) + delta = 0x1000; + else + delta = ((48000 << 12) / rate) & 0x0000ffff; + + return delta; +} /* set playback sample rate */ static unsigned int trident_set_dac_rate(struct trident_state * state, unsigned int rate) { - struct dmabuf *dmabuf = &state->dma_dac; + struct dmabuf *dmabuf = &state->dmabuf; if (rate > 48000) rate = 48000; @@ -563,9 +552,9 @@ static unsigned int trident_set_dac_rate(struct trident_state * state, unsigned rate = 4000; dmabuf->rate = rate; - dmabuf->channel->delta = compute_rate(rate); + dmabuf->channel->delta = compute_rate_play(rate); - trident_write_voice_regs(state, 0); + trident_write_voice_regs(state); #ifdef DEBUG printk("trident: called trident_set_dac_rate : rate = %d\n", rate); @@ -577,16 +566,17 @@ static unsigned int trident_set_dac_rate(struct trident_state * state, unsigned /* set recording sample rate */ static unsigned int trident_set_adc_rate(struct trident_state * state, unsigned int rate) { - struct dmabuf *dmabuf = &state->dma_adc; + struct dmabuf *dmabuf = &state->dmabuf; + if (rate > 48000) rate = 48000; if (rate < 4000) rate = 4000; dmabuf->rate = rate; - dmabuf->channel->delta = compute_rate(rate); + dmabuf->channel->delta = compute_rate_rec(rate); - trident_write_voice_regs(state, 1); + trident_write_voice_regs(state); #ifdef DEBUG printk("trident: called trident_set_adc_rate : rate = %d\n", rate); @@ -597,18 +587,18 @@ static unsigned int trident_set_adc_rate(struct trident_state * state, unsigned /* prepare channel attributes for playback */ static void trident_play_setup(struct trident_state *state) { - struct dmabuf *dmabuf = &state->dma_dac; + struct dmabuf *dmabuf = &state->dmabuf; struct trident_channel *channel = dmabuf->channel; channel->lba = virt_to_bus(dmabuf->rawbuf); - channel->delta = compute_rate(dmabuf->rate); + channel->delta = compute_rate_play(dmabuf->rate); channel->eso = dmabuf->dmasize >> sample_shift[dmabuf->fmt]; channel->eso -= 1; if (state->card->pci_id == PCI_DEVICE_ID_SI_7018) { - /* FIXME: channel attributes are configured by ioctls, but it is not implemented - so just set to ZERO for the moment */ + /* FIXME: channel attributes are configured by ioctls, but it is not + implemented so just set to ZERO for the moment */ channel->attribute = 0; } else { channel->attribute = 0; @@ -631,7 +621,7 @@ static void trident_play_setup(struct trident_state *state) "Delat = 0x%08x, ESO = 0x%08x, Control = 0x%08x\n", channel->lba, channel->delta, channel->eso, channel->control); #endif - trident_write_voice_regs(state, 0); + trident_write_voice_regs(state); } /* prepare channel attributes for recording */ @@ -639,7 +629,7 @@ static void trident_rec_setup(struct trident_state *state) { u16 w; struct trident_card *card = state->card; - struct dmabuf *dmabuf = &state->dma_adc; + struct dmabuf *dmabuf = &state->dmabuf; struct trident_channel *channel = dmabuf->channel; /* Enable AC-97 ADC (capture) */ @@ -651,25 +641,30 @@ static void trident_rec_setup(struct trident_state *state) case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX: w = inb(TRID_REG(card, DX_ACR2_AC97_COM_STAT)); outb(w | 0x48, TRID_REG(card, DX_ACR2_AC97_COM_STAT)); + /* enable and set record channel */ + outb(0x80 | channel->num, TRID_REG(card, T4D_REC_CH)); break; case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX: w = inw(TRID_REG(card, T4D_MISCINT)); outw(w | 0x1000, TRID_REG(card, T4D_MISCINT)); + /* enable and set record channel */ + outb(0x80 | channel->num, TRID_REG(card, T4D_REC_CH)); break; default: return; } channel->lba = virt_to_bus(dmabuf->rawbuf); - channel->delta = compute_rate(dmabuf->rate); + channel->delta = compute_rate_rec(dmabuf->rate); channel->eso = dmabuf->dmasize >> sample_shift[dmabuf->fmt]; channel->eso -= 1; if (state->card->pci_id == PCI_DEVICE_ID_SI_7018) { - /* FIXME: channel attributes are configured by ioctls, but it is not implemented - so just set to ZERO for the moment */ - channel->attribute = 0; + /* FIXME: channel attributes are configured by ioctls, but it is not + implemented so just set to 0x8a80 for the moment, record from PCM L/R + input and mono = (left + right + 1)/2*/ + channel->attribute = 0x8A80; } else { channel->attribute = 0; } @@ -691,21 +686,16 @@ static void trident_rec_setup(struct trident_state *state) "Delat = 0x%08x, ESO = 0x%08x, Control = 0x%08x\n", channel->lba, channel->delta, channel->eso, channel->control); #endif - trident_write_voice_regs(state, 1); + trident_write_voice_regs(state); } /* get current playback/recording dma buffer pointer (byte offset from LBA), called with spinlock held! */ -extern __inline__ unsigned trident_get_dma_addr(struct trident_state *state, unsigned rec) +extern __inline__ unsigned trident_get_dma_addr(struct trident_state *state) { - struct dmabuf *dmabuf; + struct dmabuf *dmabuf = &state->dmabuf; u32 cso; - if (rec) - dmabuf = &state->dma_adc; - else - dmabuf = &state->dma_dac; - if (!dmabuf->enable) return 0; @@ -727,7 +717,8 @@ extern __inline__ unsigned trident_get_dma_addr(struct trident_state *state, uns } #ifdef DEBUG - printk("trident: trident_get_dma_addr: chip reported channel: %d, cso = %d\n", + printk("trident: trident_get_dma_addr: chip reported channel: %d, " + "cso = 0x%04x\n", dmabuf->channel->num, cso); #endif /* ESO and CSO are in units of Samples, convert to byte offset */ @@ -739,11 +730,11 @@ extern __inline__ unsigned trident_get_dma_addr(struct trident_state *state, uns /* Stop recording (lock held) */ extern __inline__ void __stop_adc(struct trident_state *state) { - struct dmabuf *dmabuf = &state->dma_adc; + struct dmabuf *dmabuf = &state->dmabuf; unsigned int chan_num = dmabuf->channel->num; struct trident_card *card = state->card; - dmabuf->enable &= ~DMA_RUNNING; + dmabuf->enable &= ~ADC_RUNNING; trident_stop_voice(card, chan_num); trident_disable_voice_irq(card, chan_num); } @@ -760,16 +751,14 @@ static void stop_adc(struct trident_state *state) static void start_adc(struct trident_state *state) { - struct dmabuf *dmabuf = &state->dma_adc; + struct dmabuf *dmabuf = &state->dmabuf; unsigned int chan_num = dmabuf->channel->num; struct trident_card *card = state->card; unsigned long flags; spin_lock_irqsave(&card->lock, flags); - if ((dmabuf->mapped || - dmabuf->count < (signed)(dmabuf->dmasize - 2*dmabuf->fragsize)) - && dmabuf->ready) { - dmabuf->enable |= DMA_RUNNING; + if ((dmabuf->mapped || dmabuf->count < (signed)dmabuf->dmasize) && dmabuf->ready) { + dmabuf->enable |= ADC_RUNNING; trident_enable_voice_irq(card, chan_num); trident_start_voice(card, chan_num); } @@ -779,11 +768,11 @@ static void start_adc(struct trident_state *state) /* stop playback (lock held) */ extern __inline__ void __stop_dac(struct trident_state *state) { - struct dmabuf *dmabuf = &state->dma_dac; + struct dmabuf *dmabuf = &state->dmabuf; unsigned int chan_num = dmabuf->channel->num; struct trident_card *card = state->card; - dmabuf->enable &= ~DMA_RUNNING; + dmabuf->enable &= ~DAC_RUNNING; trident_stop_voice(card, chan_num); trident_disable_voice_irq(card, chan_num); } @@ -800,14 +789,14 @@ static void stop_dac(struct trident_state *state) static void start_dac(struct trident_state *state) { - struct dmabuf *dmabuf = &state->dma_dac; + struct dmabuf *dmabuf = &state->dmabuf; unsigned int chan_num = dmabuf->channel->num; struct trident_card *card = state->card; unsigned long flags; spin_lock_irqsave(&card->lock, flags); if ((dmabuf->mapped || dmabuf->count > 0) && dmabuf->ready) { - dmabuf->enable |= DMA_RUNNING; + dmabuf->enable |= DAC_RUNNING; trident_enable_voice_irq(card, chan_num); trident_start_voice(card, chan_num); } @@ -818,39 +807,27 @@ static void start_dac(struct trident_state *state) #define DMABUF_MINORDER 1 /* allocate DMA buffer, playback and recording buffer should be allocated seperately */ -static int alloc_dmabuf(struct trident_state *state, unsigned rec) +static int alloc_dmabuf(struct trident_state *state) { - struct dmabuf *dmabuf; + struct dmabuf *dmabuf = &state->dmabuf; void *rawbuf; int order; unsigned long map, mapend; - if (rec) - dmabuf = &state->dma_adc; - else - dmabuf = &state->dma_dac; - /* alloc as big a chunk as we can, FIXME: is this necessary ?? */ for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--) - if ((rawbuf = (void *)__get_free_pages(GFP_KERNEL, order))) + if ((rawbuf = pci_alloc_consistent(state->card->pci_dev, + PAGE_SIZE << order, + &dmabuf->dma_handle))) break; if (!rawbuf) return -ENOMEM; + #ifdef DEBUG printk("trident: allocated %ld (order = %d) bytes at %p\n", PAGE_SIZE << order, order, rawbuf); #endif - /* for 4DWave and 7018, there are only 30 (31) siginifcan bits for Loop Begin Address - (LBA) which limits the address space to 1 (2) GB, bad T^2 design */ - if ((virt_to_bus(rawbuf) + (PAGE_SIZE << order) - 1) & ~0x3fffffff) { - printk(KERN_ERR "trident: DMA buffer beyond 1 GB; " - "bus address = 0x%lx, size = %ld\n", - virt_to_bus(rawbuf), PAGE_SIZE << order); - free_pages((unsigned long)rawbuf, order); - return -ENOMEM; - } - dmabuf->ready = dmabuf->mapped = 0; dmabuf->rawbuf = rawbuf; dmabuf->buforder = order; @@ -864,16 +841,18 @@ static int alloc_dmabuf(struct trident_state *state, unsigned rec) } /* free DMA buffer */ -static void dealloc_dmabuf(struct dmabuf *dmabuf) +static void dealloc_dmabuf(struct trident_state *state) { + struct dmabuf *dmabuf = &state->dmabuf; unsigned long map, mapend; if (dmabuf->rawbuf) { /* undo marking the pages as reserved */ mapend = MAP_NR(dmabuf->rawbuf + (PAGE_SIZE << dmabuf->buforder) - 1); for (map = MAP_NR(dmabuf->rawbuf); map <= mapend; map++) - clear_bit(PG_reserved, &mem_map[map].flags); - free_pages((unsigned long)dmabuf->rawbuf, dmabuf->buforder); + clear_bit(PG_reserved, &mem_map[map].flags); + pci_free_consistent(state->card->pci_dev, PAGE_SIZE << dmabuf->buforder, + dmabuf->rawbuf, dmabuf->dma_handle); } dmabuf->rawbuf = NULL; dmabuf->mapped = dmabuf->ready = 0; @@ -881,25 +860,20 @@ static void dealloc_dmabuf(struct dmabuf *dmabuf) static int prog_dmabuf(struct trident_state *state, unsigned rec) { - struct dmabuf *dmabuf; + struct dmabuf *dmabuf = &state->dmabuf; unsigned bytepersec; unsigned bufsize; unsigned long flags; int ret; - if (rec) - dmabuf = &state->dma_adc; - else - dmabuf = &state->dma_dac; - spin_lock_irqsave(&state->card->lock, flags); - dmabuf->hwptr = dmabuf->swptr = dmabuf->total_bytes = 0; - dmabuf->count = dmabuf->error = dmabuf->endcleared = 0; + dmabuf->hwptr = dmabuf->swptr = dmabuf->total_bytes = 0; + dmabuf->count = dmabuf->error = 0; spin_unlock_irqrestore(&state->card->lock, flags); /* allocate DMA buffer if not allocated yet */ if (!dmabuf->rawbuf) - if ((ret = alloc_dmabuf(state, rec))) + if ((ret = alloc_dmabuf(state))) return ret; /* FIXME: figure out all this OSS fragment stuff */ @@ -958,7 +932,7 @@ static int prog_dmabuf(struct trident_state *state, unsigned rec) */ static void trident_clear_tail(struct trident_state *state) { - struct dmabuf *dmabuf = &state->dma_dac; + struct dmabuf *dmabuf = &state->dmabuf; unsigned swptr; unsigned char silence = (dmabuf->fmt & TRIDENT_FMT_16BIT) ? 0 : 0x80; unsigned int len; @@ -971,7 +945,6 @@ static void trident_clear_tail(struct trident_state *state) if (swptr == 0 || swptr == dmabuf->dmasize / 2 || swptr == dmabuf->dmasize) return; - if (swptr < dmabuf->dmasize/2) len = dmabuf->dmasize/2 - swptr; else @@ -979,7 +952,7 @@ static void trident_clear_tail(struct trident_state *state) memset(dmabuf->rawbuf + swptr, silence, len); - spin_lock_irqsave(&state->card->lock, flags); + spin_lock_irqsave(&state->card->lock, flags); dmabuf->swptr += len; dmabuf->count += len; spin_unlock_irqrestore(&state->card->lock, flags); @@ -991,7 +964,7 @@ static void trident_clear_tail(struct trident_state *state) static int drain_dac(struct trident_state *state, int nonblock) { DECLARE_WAITQUEUE(wait, current); - struct dmabuf *dmabuf = &state->dma_dac; + struct dmabuf *dmabuf = &state->dmabuf; unsigned long flags; unsigned long tmo; int count; @@ -1038,49 +1011,49 @@ static int drain_dac(struct trident_state *state, int nonblock) return 0; } -/* call with spinlock held! */ +/* update buffer manangement pointers, especially, dmabuf->count and dmabuf->hwptr */ static void trident_update_ptr(struct trident_state *state) { - struct dmabuf *dmabuf; + struct dmabuf *dmabuf = &state->dmabuf; unsigned hwptr; int diff; - /* update ADC pointer */ - if (state->dma_adc.ready) { - dmabuf = &state->dma_adc; - hwptr = trident_get_dma_addr(state, 1); - diff = (dmabuf->dmasize + hwptr - dmabuf->hwptr) % dmabuf->dmasize; + /* update hardware pointer */ + hwptr = trident_get_dma_addr(state); + diff = (dmabuf->dmasize + hwptr - dmabuf->hwptr) % dmabuf->dmasize; + dmabuf->hwptr = hwptr; + dmabuf->total_bytes += diff; - dmabuf->hwptr = hwptr; - dmabuf->total_bytes += diff; - dmabuf->count += diff; + /* error handling and process wake up for DAC */ + if (dmabuf->enable == ADC_RUNNING) { + if (dmabuf->mapped) { + dmabuf->count -= diff; + if (dmabuf->count >= (signed)dmabuf->fragsize) + wake_up(&dmabuf->wait); + } else { + dmabuf->count += diff; - if (dmabuf->count >= (signed)dmabuf->fragsize) - wake_up(&dmabuf->wait); - if (!dmabuf->mapped) { - if (dmabuf->count > (signed)(dmabuf->dmasize - ((3 * dmabuf->fragsize) >> 1))) { - __stop_adc(state); + if (dmabuf->count < 0 || dmabuf->count > dmabuf->dmasize) { + /* buffer underrun or buffer overrun, we have no way to recover + it here, just stop the machine and let the process force hwptr + and swptr to sync */ + __stop_adc(state); dmabuf->error++; } + /* since dma machine only interrupts at ESO and ESO/2, we sure have at + least half of dma buffer free, so wake up the process unconditionally */ + wake_up(&dmabuf->wait); } } - - /* update DAC pointer */ - if (state->dma_dac.ready) { - dmabuf = &state->dma_dac; - hwptr = trident_get_dma_addr(state, 0); - diff = (dmabuf->dmasize + hwptr - dmabuf->hwptr) % dmabuf->dmasize; - - dmabuf->hwptr = hwptr; - dmabuf->total_bytes += diff; - + /* error handling and process wake up for DAC */ + if (dmabuf->enable == DAC_RUNNING) { if (dmabuf->mapped) { dmabuf->count += diff; - if (dmabuf->count >= (signed)dmabuf->fragsize) + if (dmabuf->count >= (signed)dmabuf->fragsize) wake_up(&dmabuf->wait); - } - else { + } else { dmabuf->count -= diff; + if (dmabuf->count < 0 || dmabuf->count > dmabuf->dmasize) { /* buffer underrun or buffer overrun, we have no way to recover it here, just stop the machine and let the process force hwptr @@ -1088,7 +1061,7 @@ static void trident_update_ptr(struct trident_state *state) __stop_dac(state); dmabuf->error++; } - /* since dma machine only interrupts at ESO and ESO/2, we sure have at + /* since dma machine only interrupts at ESO and ESO/2, we sure have at least half of dma buffer free, so wake up the process unconditionally */ wake_up(&dmabuf->wait); } @@ -1120,17 +1093,13 @@ static void trident_interrupt(int irq, void *dev_id, struct pt_regs *regs) } else { printk("trident: spurious channel irq %d.\n", 63 - i); - trident_stop_voice(card, i); - trident_disable_voice_irq(card, i); + trident_stop_voice(card, 63 - i); + trident_disable_voice_irq(card, 63 - i); } } } } - if (event & SB_IRQ){ - /* Midi - TODO */ - } - /* manually clear interrupt status, bad hardware design, blame T^2 */ outl((ST_TARGET_REACHED | MIXER_OVERFLOW | MIXER_UNDERFLOW), TRID_REG(card, T4D_MISCINT)); @@ -1142,18 +1111,21 @@ static loff_t trident_llseek(struct file *file, loff_t offset, int origin) return -ESPIPE; } -/* in this loop, dma_adc.count signifies the amount of data thats waiting - to be copied to the user's buffer. it is filled by the interrupt - handler and drained by this loop. */ +/* in this loop, dmabuf.count signifies the amount of data that is waiting to be copied to + the user's buffer. it is filled by the dma machine and drained by this loop. */ static ssize_t trident_read(struct file *file, char *buffer, size_t count, loff_t *ppos) { struct trident_state *state = (struct trident_state *)file->private_data; - struct dmabuf *dmabuf = &state->dma_dac; + struct dmabuf *dmabuf = &state->dmabuf; ssize_t ret; unsigned long flags; unsigned swptr; int cnt; +#ifdef DEBUG + printk("trident: trident_read called, count = %d\n", count); +#endif + VALIDATE_STATE(state); if (ppos != &file->f_pos) return -ESPIPE; @@ -1167,6 +1139,12 @@ static ssize_t trident_read(struct file *file, char *buffer, size_t count, loff_ while (count > 0) { spin_lock_irqsave(&state->card->lock, flags); + if (dmabuf->count > (signed) dmabuf->dmasize) { + /* buffer overrun, we are recovering from sleep_on_timeout, + resync hwptr and swptr, make process flush the buffer */ + dmabuf->count = dmabuf->dmasize; + dmabuf->swptr = dmabuf->hwptr; + } swptr = dmabuf->swptr; cnt = dmabuf->dmasize - swptr; if (dmabuf->count < cnt) @@ -1175,25 +1153,35 @@ static ssize_t trident_read(struct file *file, char *buffer, size_t count, loff_ if (cnt > count) cnt = count; - if (cnt <= 0) { + unsigned long tmo; + /* buffer is empty, start the dma machine and wait for data to be + recorded */ start_adc(state); if (file->f_flags & O_NONBLOCK) { - ret = ret ? ret : -EAGAIN; + if (!ret) ret = -EAGAIN; return ret; } - if (!interruptible_sleep_on_timeout(&dmabuf->wait, HZ)) { - printk(KERN_ERR - "(trident) read: chip lockup? " + /* No matter how much space left in the buffer, we have to wait untill + CSO == ESO/2 or CSO == ESO when address engine interrupts */ + tmo = (dmabuf->dmasize * HZ) / (dmabuf->rate * 2); + tmo >>= sample_shift[dmabuf->fmt]; + /* There are two situations when sleep_on_timeout returns, one is when + the interrupt is serviced correctly and the process is waked up by + ISR ON TIME. Another is when timeout is expired, which means that + either interrupt is NOT serviced correctly (pending interrupt) or it + is TOO LATE for the process to be scheduled to run (scheduler latency) + which results in a (potential) buffer overrun. And worse, there is + NOTHING we can do to prevent it. */ + if (!interruptible_sleep_on_timeout(&dmabuf->wait, tmo)) { +#ifdef DEBUG + printk(KERN_ERR "trident: recording schedule timeout, " "dmasz %u fragsz %u count %i hwptr %u swptr %u\n", dmabuf->dmasize, dmabuf->fragsize, dmabuf->count, dmabuf->hwptr, dmabuf->swptr); - stop_adc(state); - spin_lock_irqsave(&state->card->lock, flags); - dmabuf->count = 0; - dmabuf->hwptr = 0; - dmabuf->swptr = 0; - spin_unlock_irqrestore(&state->card->lock, flags); +#endif + /* a buffer overrun, we delay the recovery untill next time the + while loop begin and we REALLY have space to record */ } if (signal_pending(current)) { ret = ret ? ret : -ERESTARTSYS; @@ -1203,7 +1191,7 @@ static ssize_t trident_read(struct file *file, char *buffer, size_t count, loff_ } if (copy_to_user(buffer, dmabuf->rawbuf + swptr, cnt)) { - ret = ret ? ret : -EFAULT; + if (!ret) ret = -EFAULT; return ret; } @@ -1219,14 +1207,15 @@ static ssize_t trident_read(struct file *file, char *buffer, size_t count, loff_ ret += cnt; start_adc(state); } - return ret; } +/* in this loop, dmabuf.count signifies the amount of data that is waiting to be dma to + the soundcard. it is drained by the dma machine and filled by this loop. */ static ssize_t trident_write(struct file *file, const char *buffer, size_t count, loff_t *ppos) { struct trident_state *state = (struct trident_state *)file->private_data; - struct dmabuf *dmabuf = &state->dma_dac; + struct dmabuf *dmabuf = &state->dmabuf; ssize_t ret; unsigned long flags; unsigned swptr; @@ -1234,7 +1223,7 @@ static ssize_t trident_write(struct file *file, const char *buffer, size_t count #ifdef DEBUG printk("trident: trident_write called, count = %d\n", count); -#endif +#endif VALIDATE_STATE(state); if (ppos != &file->f_pos) @@ -1265,7 +1254,8 @@ static ssize_t trident_write(struct file *file, const char *buffer, size_t count cnt = count; if (cnt <= 0) { unsigned long tmo; - /* buffer is full, start the dma machine and wait for data to be played */ + /* buffer is full, start the dma machine and wait for data to be + played */ start_dac(state); if (file->f_flags & O_NONBLOCK) { if (!ret) ret = -EAGAIN; @@ -1275,15 +1265,16 @@ static ssize_t trident_write(struct file *file, const char *buffer, size_t count CSO == ESO/2 or CSO == ESO when address engine interrupts */ tmo = (dmabuf->dmasize * HZ) / (dmabuf->rate * 2); tmo >>= sample_shift[dmabuf->fmt]; - /* There are two situations when sleep_on_timeout returns, one is when the - interrupt is serviced correctly and the process is waked up by ISR ON TIME. - Another is when timeout is expired, which means that either interrupt is NOT - serviced correctly (pending interrupt) or it is TOO LATE for the process to - be scheduled to run (scheduler latency) which results in a (potential) buffer - underrun. And worse, there is NOTHING we can do to prevent it. */ + /* There are two situations when sleep_on_timeout returns, one is when + the interrupt is serviced correctly and the process is waked up by + ISR ON TIME. Another is when timeout is expired, which means that + either interrupt is NOT serviced correctly (pending interrupt) or it + is TOO LATE for the process to be scheduled to run (scheduler latency) + which results in a (potential) buffer underrun. And worse, there is + NOTHING we can do to prevent it. */ if (!interruptible_sleep_on_timeout(&dmabuf->wait, tmo)) { #ifdef DEBUG - printk(KERN_ERR "trident: schedule timeout, " + printk(KERN_ERR "trident: playback schedule timeout, " "dmasz %u fragsz %u count %i hwptr %u swptr %u\n", dmabuf->dmasize, dmabuf->fragsize, dmabuf->count, dmabuf->hwptr, dmabuf->swptr); @@ -1307,7 +1298,6 @@ static ssize_t trident_write(struct file *file, const char *buffer, size_t count spin_lock_irqsave(&state->card->lock, flags); dmabuf->swptr = swptr; dmabuf->count += cnt; - dmabuf->endcleared = 0; spin_unlock_irqrestore(&state->card->lock, flags); count -= cnt; @@ -1320,32 +1310,33 @@ static ssize_t trident_write(struct file *file, const char *buffer, size_t count static unsigned int trident_poll(struct file *file, struct poll_table_struct *wait) { - struct trident_state *s = (struct trident_state *)file->private_data; + struct trident_state *state = (struct trident_state *)file->private_data; + struct dmabuf *dmabuf = &state->dmabuf; unsigned long flags; unsigned int mask = 0; - VALIDATE_STATE(s); + VALIDATE_STATE(state); if (file->f_mode & FMODE_WRITE) - poll_wait(file, &s->dma_dac.wait, wait); + poll_wait(file, &dmabuf->wait, wait); if (file->f_mode & FMODE_READ) - poll_wait(file, &s->dma_adc.wait, wait); + poll_wait(file, &dmabuf->wait, wait); - spin_lock_irqsave(&s->card->lock, flags); - trident_update_ptr(s); + spin_lock_irqsave(&state->card->lock, flags); + trident_update_ptr(state); if (file->f_mode & FMODE_READ) { - if (s->dma_adc.count >= (signed)s->dma_adc.fragsize) + if (dmabuf->count >= (signed)dmabuf->fragsize) mask |= POLLIN | POLLRDNORM; } if (file->f_mode & FMODE_WRITE) { - if (s->dma_dac.mapped) { - if (s->dma_dac.count >= (signed)s->dma_dac.fragsize) + if (dmabuf->mapped) { + if (dmabuf->count >= (signed)dmabuf->fragsize) mask |= POLLOUT | POLLWRNORM; } else { - if ((signed)s->dma_dac.dmasize >= s->dma_dac.count + (signed)s->dma_dac.fragsize) + if ((signed)dmabuf->dmasize >= dmabuf->count + (signed)dmabuf->fragsize) mask |= POLLOUT | POLLWRNORM; } } - spin_unlock_irqrestore(&s->card->lock, flags); + spin_unlock_irqrestore(&state->card->lock, flags); return mask; } @@ -1353,7 +1344,7 @@ static unsigned int trident_poll(struct file *file, struct poll_table_struct *wa static int trident_mmap(struct file *file, struct vm_area_struct *vma) { struct trident_state *state = (struct trident_state *)file->private_data; - struct dmabuf *dmabuf; + struct dmabuf *dmabuf = &state->dmabuf; int ret; unsigned long size; @@ -1361,11 +1352,9 @@ static int trident_mmap(struct file *file, struct vm_area_struct *vma) if (vma->vm_flags & VM_WRITE) { if ((ret = prog_dmabuf(state, 0)) != 0) return ret; - dmabuf = &state->dma_dac; } else if (vma->vm_flags & VM_READ) { if ((ret = prog_dmabuf(state, 1)) != 0) return ret; - dmabuf = &state->dma_adc; } else return -EINVAL; @@ -1385,14 +1374,15 @@ static int trident_mmap(struct file *file, struct vm_area_struct *vma) static int trident_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { struct trident_state *state = (struct trident_state *)file->private_data; + struct dmabuf *dmabuf = &state->dmabuf; unsigned long flags; audio_buf_info abinfo; count_info cinfo; int val, mapped, ret; VALIDATE_STATE(state); - mapped = ((file->f_mode & FMODE_WRITE) && state->dma_dac.mapped) || - ((file->f_mode & FMODE_READ) && state->dma_adc.mapped); + mapped = ((file->f_mode & FMODE_WRITE) && dmabuf->mapped) || + ((file->f_mode & FMODE_READ) && dmabuf->mapped); #ifdef DEBUG printk("trident: trident_ioctl, command = %2d, arg = 0x%08x\n", _IOC_NR(cmd), arg ? *(int *)arg : 0); @@ -1404,19 +1394,20 @@ static int trident_ioctl(struct inode *inode, struct file *file, unsigned int cm return put_user(SOUND_VERSION, (int *)arg); case SNDCTL_DSP_RESET: + /* FIXME: spin_lock ? */ if (file->f_mode & FMODE_WRITE) { stop_dac(state); synchronize_irq(); - state->dma_dac.ready = 0; - state->dma_dac.swptr = state->dma_dac.hwptr = 0; - state->dma_dac.count = state->dma_dac.total_bytes = 0; + dmabuf->ready = 0; + dmabuf->swptr = dmabuf->hwptr = 0; + dmabuf->count = dmabuf->total_bytes = 0; } if (file->f_mode & FMODE_READ) { stop_adc(state); synchronize_irq(); - state->dma_adc.ready = 0; - state->dma_adc.swptr = state->dma_adc.hwptr = 0; - state->dma_adc.count = state->dma_adc.total_bytes = 0; + dmabuf->ready = 0; + dmabuf->swptr = dmabuf->hwptr = 0; + dmabuf->count = dmabuf->total_bytes = 0; } return 0; @@ -1430,40 +1421,38 @@ static int trident_ioctl(struct inode *inode, struct file *file, unsigned int cm if (val >= 0) { if (file->f_mode & FMODE_WRITE) { stop_dac(state); - state->dma_dac.ready = 0; + dmabuf->ready = 0; spin_lock_irqsave(&state->card->lock, flags); trident_set_dac_rate(state, val); spin_unlock_irqrestore(&state->card->lock, flags); } if (file->f_mode & FMODE_READ) { stop_adc(state); - state->dma_adc.ready = 0; + dmabuf->ready = 0; spin_lock_irqsave(&state->card->lock, flags); trident_set_adc_rate(state, val); spin_unlock_irqrestore(&state->card->lock, flags); } } - return put_user((file->f_mode & FMODE_READ) ? state->dma_adc.rate : - state->dma_dac.rate, - (int *)arg); + return put_user(dmabuf->rate, (int *)arg); case SNDCTL_DSP_STEREO: /* set stereo or mono channel */ get_user_ret(val, (int *)arg, -EFAULT); if (file->f_mode & FMODE_WRITE) { stop_dac(state); - state->dma_dac.ready = 0; + dmabuf->ready = 0; if (val) - state->dma_dac.fmt |= TRIDENT_FMT_STEREO; + dmabuf->fmt |= TRIDENT_FMT_STEREO; else - state->dma_dac.fmt &= ~TRIDENT_FMT_STEREO; + dmabuf->fmt &= ~TRIDENT_FMT_STEREO; } if (file->f_mode & FMODE_READ) { stop_adc(state); - state->dma_adc.ready = 0; + dmabuf->ready = 0; if (val) - state->dma_adc.fmt |= TRIDENT_FMT_STEREO; + dmabuf->fmt |= TRIDENT_FMT_STEREO; else - state->dma_adc.fmt &= ~TRIDENT_FMT_STEREO; + dmabuf->fmt &= ~TRIDENT_FMT_STEREO; } return 0; @@ -1471,12 +1460,12 @@ static int trident_ioctl(struct inode *inode, struct file *file, unsigned int cm if (file->f_mode & FMODE_WRITE) { if ((val = prog_dmabuf(state, 0))) return val; - return put_user(state->dma_dac.fragsize, (int *)arg); + return put_user(dmabuf->fragsize, (int *)arg); } if (file->f_mode & FMODE_READ) { if ((val = prog_dmabuf(state, 1))) return val; - return put_user(state->dma_adc.fragsize, (int *)arg); + return put_user(dmabuf->fragsize, (int *)arg); } case SNDCTL_DSP_GETFMTS: /* Returns a mask of supported sample format*/ @@ -1487,120 +1476,99 @@ static int trident_ioctl(struct inode *inode, struct file *file, unsigned int cm if (val != AFMT_QUERY) { if (file->f_mode & FMODE_WRITE) { stop_dac(state); - state->dma_dac.ready = 0; + dmabuf->ready = 0; if (val == AFMT_S16_LE) - state->dma_dac.fmt |= TRIDENT_FMT_16BIT; + dmabuf->fmt |= TRIDENT_FMT_16BIT; else - state->dma_dac.fmt &= ~TRIDENT_FMT_16BIT; + dmabuf->fmt &= ~TRIDENT_FMT_16BIT; } if (file->f_mode & FMODE_READ) { stop_adc(state); - state->dma_adc.ready = 0; + dmabuf->ready = 0; if (val == AFMT_S16_LE) - state->dma_adc.fmt |= TRIDENT_FMT_16BIT; + dmabuf->fmt |= TRIDENT_FMT_16BIT; else - state->dma_adc.fmt &= ~TRIDENT_FMT_16BIT; + dmabuf->fmt &= ~TRIDENT_FMT_16BIT; } } - if (file->f_mode & FMODE_WRITE) - return put_user((state->dma_dac.fmt & TRIDENT_FMT_16BIT) ? - AFMT_S16_LE : AFMT_U8, (int *)arg); - else - return put_user((state->dma_adc.fmt & TRIDENT_FMT_16BIT) ? - AFMT_S16_LE : AFMT_U8, (int *)arg); + return put_user((dmabuf->fmt & TRIDENT_FMT_16BIT) ? + AFMT_S16_LE : AFMT_U8, (int *)arg); case SNDCTL_DSP_CHANNELS: get_user_ret(val, (int *)arg, -EFAULT); if (val != 0) { if (file->f_mode & FMODE_WRITE) { stop_dac(state); - state->dma_dac.ready = 0; + dmabuf->ready = 0; if (val >= 2) - state->dma_dac.fmt |= TRIDENT_FMT_STEREO; + dmabuf->fmt |= TRIDENT_FMT_STEREO; else - state->dma_dac.fmt &= ~TRIDENT_FMT_STEREO; + dmabuf->fmt &= ~TRIDENT_FMT_STEREO; } if (file->f_mode & FMODE_READ) { stop_adc(state); - state->dma_adc.ready = 0; + dmabuf->ready = 0; if (val >= 2) - state->dma_adc.fmt |= TRIDENT_FMT_STEREO; + dmabuf->fmt |= TRIDENT_FMT_STEREO; else - state->dma_adc.fmt &= ~TRIDENT_FMT_STEREO; + dmabuf->fmt &= ~TRIDENT_FMT_STEREO; } } - if (file->f_mode & FMODE_WRITE) - return put_user((state->dma_dac.fmt & TRIDENT_FMT_STEREO) ? 2 : 1, - (int *)arg); - else - return put_user((state->dma_adc.fmt & TRIDENT_FMT_STEREO) ? 2 : 1, - (int *)arg); + return put_user((dmabuf->fmt & TRIDENT_FMT_STEREO) ? 2 : 1, + (int *)arg); + case SNDCTL_DSP_POST: /* FIXME: the same as RESET ?? */ return 0; case SNDCTL_DSP_SUBDIVIDE: - if ((file->f_mode & FMODE_READ && state->dma_adc.subdivision) || - (file->f_mode & FMODE_WRITE && state->dma_dac.subdivision)) + if (dmabuf->subdivision) return -EINVAL; get_user_ret(val, (int *)arg, -EFAULT); if (val != 1 && val != 2 && val != 4) return -EINVAL; - if (file->f_mode & FMODE_READ) - state->dma_adc.subdivision = val; - if (file->f_mode & FMODE_WRITE) - state->dma_dac.subdivision = val; + dmabuf->subdivision = val; return 0; case SNDCTL_DSP_SETFRAGMENT: get_user_ret(val, (int *)arg, -EFAULT); - if (file->f_mode & FMODE_READ) { - state->dma_adc.ossfragshift = val & 0xffff; - state->dma_adc.ossmaxfrags = (val >> 16) & 0xffff; - if (state->dma_adc.ossfragshift < 4) - state->dma_adc.ossfragshift = 4; - if (state->dma_adc.ossfragshift > 15) - state->dma_adc.ossfragshift = 15; - if (state->dma_adc.ossmaxfrags < 4) - state->dma_adc.ossmaxfrags = 4; - } - if (file->f_mode & FMODE_WRITE) { - state->dma_dac.ossfragshift = val & 0xffff; - state->dma_dac.ossmaxfrags = (val >> 16) & 0xffff; - if (state->dma_dac.ossfragshift < 4) - state->dma_dac.ossfragshift = 4; - if (state->dma_dac.ossfragshift > 15) - state->dma_dac.ossfragshift = 15; - if (state->dma_dac.ossmaxfrags < 4) - state->dma_dac.ossmaxfrags = 4; - } + + dmabuf->ossfragshift = val & 0xffff; + dmabuf->ossmaxfrags = (val >> 16) & 0xffff; + if (dmabuf->ossfragshift < 4) + dmabuf->ossfragshift = 4; + if (dmabuf->ossfragshift > 15) + dmabuf->ossfragshift = 15; + if (dmabuf->ossmaxfrags < 4) + dmabuf->ossmaxfrags = 4; + return 0; case SNDCTL_DSP_GETOSPACE: if (!(file->f_mode & FMODE_WRITE)) return -EINVAL; - if (!state->dma_dac.enable && (val = prog_dmabuf(state, 0)) != 0) + if (!dmabuf->enable && (val = prog_dmabuf(state, 0)) != 0) return val; spin_lock_irqsave(&state->card->lock, flags); trident_update_ptr(state); - abinfo.fragsize = state->dma_dac.fragsize; - abinfo.bytes = state->dma_dac.dmasize - state->dma_dac.count; - abinfo.fragstotal = state->dma_dac.numfrag; - abinfo.fragments = abinfo.bytes >> state->dma_dac.fragshift; + abinfo.fragsize = dmabuf->fragsize; + abinfo.bytes = dmabuf->dmasize - dmabuf->count; + abinfo.fragstotal = dmabuf->numfrag; + abinfo.fragments = abinfo.bytes >> dmabuf->fragshift; spin_unlock_irqrestore(&state->card->lock, flags); return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; case SNDCTL_DSP_GETISPACE: if (!(file->f_mode & FMODE_READ)) return -EINVAL; - if (!state->dma_adc.enable && (val = prog_dmabuf(state, 1)) != 0) + if (!dmabuf->enable && (val = prog_dmabuf(state, 1)) != 0) return val; spin_lock_irqsave(&state->card->lock, flags); trident_update_ptr(state); - abinfo.fragsize = state->dma_adc.fragsize; - abinfo.bytes = state->dma_adc.count; - abinfo.fragstotal = state->dma_adc.numfrag; - abinfo.fragments = abinfo.bytes >> state->dma_adc.fragshift; + abinfo.fragsize = dmabuf->fragsize; + abinfo.bytes = dmabuf->count; + abinfo.fragstotal = dmabuf->numfrag; + abinfo.fragments = abinfo.bytes >> dmabuf->fragshift; spin_unlock_irqrestore(&state->card->lock, flags); return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; @@ -1609,14 +1577,13 @@ static int trident_ioctl(struct inode *inode, struct file *file, unsigned int cm return 0; case SNDCTL_DSP_GETCAPS: - return put_user(/* DSP_CAP_DUPLEX|*/DSP_CAP_REALTIME|DSP_CAP_TRIGGER|DSP_CAP_MMAP, - (int *)arg); + return put_user(DSP_CAP_REALTIME|DSP_CAP_TRIGGER|DSP_CAP_MMAP, (int *)arg); case SNDCTL_DSP_GETTRIGGER: val = 0; - if (file->f_mode & FMODE_READ && state->dma_adc.enable) + if (file->f_mode & FMODE_READ && dmabuf->enable) val |= PCM_ENABLE_INPUT; - if (file->f_mode & FMODE_WRITE && state->dma_dac.enable) + if (file->f_mode & FMODE_WRITE && dmabuf->enable) val |= PCM_ENABLE_OUTPUT; return put_user(val, (int *)arg); @@ -1624,20 +1591,18 @@ static int trident_ioctl(struct inode *inode, struct file *file, unsigned int cm get_user_ret(val, (int *)arg, -EFAULT); if (file->f_mode & FMODE_READ) { if (val & PCM_ENABLE_INPUT) { - if (!state->dma_adc.ready && (ret = prog_dmabuf(state, 1))) + if (!dmabuf->ready && (ret = prog_dmabuf(state, 1))) return ret; start_adc(state); - } - else + } else stop_adc(state); } if (file->f_mode & FMODE_WRITE) { if (val & PCM_ENABLE_OUTPUT) { - if (!state->dma_dac.ready && (ret = prog_dmabuf(state, 0))) + if (!dmabuf->ready && (ret = prog_dmabuf(state, 0))) return ret; start_dac(state); - } - else + } else stop_dac(state); } return 0; @@ -1647,59 +1612,50 @@ static int trident_ioctl(struct inode *inode, struct file *file, unsigned int cm return -EINVAL; spin_lock_irqsave(&state->card->lock, flags); trident_update_ptr(state); - cinfo.bytes = state->dma_adc.total_bytes; - cinfo.blocks = state->dma_adc.count >> state->dma_adc.fragshift; - cinfo.ptr = state->dma_adc.hwptr; - if (state->dma_adc.mapped) - state->dma_adc.count &= state->dma_adc.fragsize-1; + cinfo.bytes = dmabuf->total_bytes; + cinfo.blocks = dmabuf->count >> dmabuf->fragshift; + cinfo.ptr = dmabuf->hwptr; + if (dmabuf->mapped) + dmabuf->count &= dmabuf->fragsize-1; spin_unlock_irqrestore(&state->card->lock, flags); return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); - + case SNDCTL_DSP_GETOPTR: if (!(file->f_mode & FMODE_WRITE)) return -EINVAL; spin_lock_irqsave(&state->card->lock, flags); trident_update_ptr(state); - cinfo.bytes = state->dma_dac.total_bytes; - cinfo.blocks = state->dma_dac.count >> state->dma_dac.fragshift; - cinfo.ptr = state->dma_dac.hwptr; - if (state->dma_dac.mapped) - state->dma_dac.count &= state->dma_dac.fragsize-1; + cinfo.bytes = dmabuf->total_bytes; + cinfo.blocks = dmabuf->count >> dmabuf->fragshift; + cinfo.ptr = dmabuf->hwptr; + if (dmabuf->mapped) + dmabuf->count &= dmabuf->fragsize-1; spin_unlock_irqrestore(&state->card->lock, flags); return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); case SNDCTL_DSP_SETDUPLEX: - /* XXX fix */ - return 0; + return -EINVAL; case SNDCTL_DSP_GETODELAY: if (!(file->f_mode & FMODE_WRITE)) return -EINVAL; spin_lock_irqsave(&state->card->lock, flags); trident_update_ptr(state); - val = state->dma_dac.count; + val = dmabuf->count; spin_unlock_irqrestore(&state->card->lock, flags); return put_user(val, (int *)arg); case SOUND_PCM_READ_RATE: - return put_user((file->f_mode & FMODE_READ) ? state->dma_adc.rate : - state->dma_dac.rate, (int *)arg); + return put_user(dmabuf->rate, (int *)arg); case SOUND_PCM_READ_CHANNELS: - if (file->f_mode & FMODE_WRITE) - return put_user((state->dma_dac.fmt & TRIDENT_FMT_STEREO) ? 2 : 1, - (int *)arg); - else - return put_user((state->dma_adc.fmt & TRIDENT_FMT_STEREO) ? 2 : 1, - (int *)arg); - + return put_user((dmabuf->fmt & TRIDENT_FMT_STEREO) ? 2 : 1, + (int *)arg); + case SOUND_PCM_READ_BITS: - if (file->f_mode & FMODE_WRITE) - return put_user((state->dma_dac.fmt & TRIDENT_FMT_16BIT) ? - AFMT_S16_LE : AFMT_U8, (int *)arg); - else - return put_user((state->dma_adc.fmt & TRIDENT_FMT_16BIT) ? - AFMT_S16_LE : AFMT_U8, (int *)arg); + return put_user((dmabuf->fmt & TRIDENT_FMT_16BIT) ? + AFMT_S16_LE : AFMT_U8, (int *)arg); + case SNDCTL_DSP_MAPINBUF: case SNDCTL_DSP_MAPOUTBUF: case SNDCTL_DSP_SETSYNCRO: @@ -1738,70 +1694,61 @@ static int trident_open(struct inode *inode, struct file *file) found_virt: /* found a free virtual channel, allocate hardware channels */ - if (file->f_mode & FMODE_READ) - if ((state->dma_adc.channel = trident_alloc_pcm_channel(card)) == NULL) { - kfree (card->states[i]); - card->states[i] = NULL;; - return -ENODEV; - } - if (file->f_mode & FMODE_WRITE) - if ((state->dma_dac.channel = trident_alloc_pcm_channel(card)) == NULL) { - kfree (card->states[i]); - card->states[i] = NULL; - if (file->f_mode & FMODE_READ) - /* free previously allocated hardware channel */ - trident_free_pcm_channel(card, state->dma_adc.channel->num); - return -ENODEV; - } + if ((state->dmabuf.channel = trident_alloc_pcm_channel(card)) == NULL) { + kfree (card->states[i]); + card->states[i] = NULL;; + return -ENODEV; + } /* initialize the virtual channel */ state->virt = i; state->card = card; state->magic = TRIDENT_STATE_MAGIC; - init_waitqueue_head(&state->dma_adc.wait); - init_waitqueue_head(&state->dma_dac.wait); + init_waitqueue_head(&state->dmabuf.wait); init_MUTEX(&state->open_sem); file->private_data = state; down(&state->open_sem); - /* set default sample format, Refer to OSS Programmer's Guide */ - if (file->f_mode & FMODE_READ) { - /* FIXME: Trident 4d can only record in singed 16-bits stereo, 48kHz sample */ - state->dma_adc.fmt = TRIDENT_FMT_STEREO|TRIDENT_FMT_16BIT; - state->dma_adc.ossfragshift = 0; - state->dma_adc.ossmaxfrags = 0; - state->dma_adc.subdivision = 0; - trident_set_adc_rate(state, 48000); - } - - /* according to OSS document, /dev/dsp should be default to unsigned 8-bits, - mono, with sample rate 8kHz and /dev/dspW will accept 16-bits sample */ + /* set default sample format. According to OSS Programmer's Guide /dev/dsp + should be default to unsigned 8-bits, mono, with sample rate 8kHz and + /dev/dspW will accept 16-bits sample */ if (file->f_mode & FMODE_WRITE) { - state->dma_dac.fmt &= ~TRIDENT_FMT_MASK; + state->dmabuf.fmt &= ~TRIDENT_FMT_MASK; if ((minor & 0xf) == SND_DEV_DSP16) - state->dma_dac.fmt |= TRIDENT_FMT_16BIT; - state->dma_dac.ossfragshift = 0; - state->dma_dac.ossmaxfrags = 0; - state->dma_dac.subdivision = 0; + state->dmabuf.fmt |= TRIDENT_FMT_16BIT; + state->dmabuf.ossfragshift = 0; + state->dmabuf.ossmaxfrags = 0; + state->dmabuf.subdivision = 0; trident_set_dac_rate(state, 8000); } + if (file->f_mode & FMODE_READ) { + /* FIXME: Trident 4d can only record in singed 16-bits stereo, 48kHz sample, + to be dealed with in trident_set_adc_rate() ?? */ + state->dmabuf.fmt &= ~TRIDENT_FMT_MASK; + if ((minor & 0xf) == SND_DEV_DSP16) + state->dmabuf.fmt |= TRIDENT_FMT_16BIT; + state->dmabuf.ossfragshift = 0; + state->dmabuf.ossmaxfrags = 0; + state->dmabuf.subdivision = 0; + trident_set_adc_rate(state, 8000); + } + state->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); up(&state->open_sem); - //FIXME put back in - //MOD_INC_USE_COUNT; + MOD_INC_USE_COUNT; return 0; } static int trident_release(struct inode *inode, struct file *file) { struct trident_state *state = (struct trident_state *)file->private_data; + struct dmabuf *dmabuf = &state->dmabuf; VALIDATE_STATE(state); - if (file->f_mode & FMODE_WRITE) { trident_clear_tail(state); drain_dac(state, file->f_flags & O_NONBLOCK); @@ -1812,13 +1759,13 @@ static int trident_release(struct inode *inode, struct file *file) if (file->f_mode & FMODE_WRITE) { stop_dac(state); - dealloc_dmabuf(&state->dma_dac); - trident_free_pcm_channel(state->card, state->dma_dac.channel->num); + dealloc_dmabuf(state); + trident_free_pcm_channel(state->card, dmabuf->channel->num); } if (file->f_mode & FMODE_READ) { stop_adc(state); - dealloc_dmabuf(&state->dma_adc); - trident_free_pcm_channel(state->card, state->dma_adc.channel->num); + dealloc_dmabuf(state); + trident_free_pcm_channel(state->card, dmabuf->channel->num); } kfree(state->card->states[state->virt]); @@ -1828,8 +1775,7 @@ static int trident_release(struct inode *inode, struct file *file) /* we're covered by the open_sem */ up(&state->open_sem); - //FIXME put back in - //MOD_DEC_USE_COUNT; + MOD_DEC_USE_COUNT; return 0; } @@ -1845,7 +1791,7 @@ static /*const*/ struct file_operations trident_audio_fops = { }; /* trident specific AC97 functions */ -/* Write AC97 mixer registers */ +/* Write AC97 codec registers */ static void trident_ac97_set(struct ac97_codec *codec, u8 reg, u16 val) { struct trident_card *card = (struct trident_card *)codec->private_data; @@ -1863,7 +1809,7 @@ static void trident_ac97_set(struct ac97_codec *codec, u8 reg, u16 val) address = SI_AC97_WRITE; mask = SI_AC97_BUSY_WRITE | SI_AC97_AUDIO_BUSY; if (codec->id) - mask |= SI_AC97_SECONDARY; + mask |= SI_AC97_SECONDARY; busy = SI_AC97_BUSY_WRITE; break; case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX: @@ -1874,7 +1820,7 @@ static void trident_ac97_set(struct ac97_codec *codec, u8 reg, u16 val) address = NX_ACR1_AC97_W; mask = NX_AC97_BUSY_WRITE; if (codec->id) - mask |= NX_AC97_WRITE_SECONDARY; + mask |= NX_AC97_WRITE_SECONDARY; busy = NX_AC97_BUSY_WRITE; break; } @@ -1968,17 +1914,13 @@ static int trident_open_mixdev(struct inode *inode, struct file *file) match: file->private_data = card->ac97_codec[i]; - //FIXME put back in - //MOD_INC_USE_COUNT; + MOD_INC_USE_COUNT; return 0; } static int trident_release_mixdev(struct inode *inode, struct file *file) { - //struct ac97_codec *codec = (struct ac97_codec *)file->private_data; - - //FIXME put back in - //MOD_DEC_USE_COUNT; + MOD_DEC_USE_COUNT; return 0; } @@ -2061,36 +2003,35 @@ static int __init trident_ac97_init(struct trident_card *card) } /* install the driver, we do not allocate hardware channel nor DMA buffer now, they are defered - untill "ACCESS" time (in prog_dmabuf calles by open/read/write/ioctl/mmap) */ -static int __init trident_install(struct pci_dev *pcidev, struct pci_audio_info *pci_info) + untill "ACCESS" time (in prog_dmabuf called by open/read/write/ioctl/mmap) */ +static int __devinit trident_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id) { - u16 w; unsigned long iobase; struct trident_card *card; - iobase = pcidev->resource[0].start; + if (!pci_dma_supported(pci_dev, TRIDENT_DMA_MASK)) { + printk(KERN_ERR "trident: architecture does not support" + " 30bit PCI busmaster DMA\n"); + return -1; + } + + iobase = pci_dev->resource[0].start; if (check_region(iobase, 256)) { printk(KERN_ERR "trident: can't allocate I/O space at 0x%4.4lx\n", iobase); - return 0; + return -1; } - /* just to be sure that IO space and bus master is on */ - pci_set_master(pcidev); - pci_read_config_word(pcidev, PCI_COMMAND, &w); - w |= PCI_COMMAND_IO|PCI_COMMAND_MASTER; - pci_write_config_word(pcidev, PCI_COMMAND, w); - if ((card = kmalloc(sizeof(struct trident_card), GFP_KERNEL)) == NULL) { printk(KERN_ERR "trident: out of memory\n"); - return 0; + return -1; } memset(card, 0, sizeof(*card)); card->iobase = iobase; - card->pci_info = pci_info; - card->pci_id = pci_info->device; - card->irq = pcidev->irq; + card->pci_dev = pci_dev; + card->pci_id = pci_id->device; + card->irq = pci_dev->irq; card->next = devs; card->magic = TRIDENT_CARD_MAGIC; card->banks[BANK_A].addresses = &bank_a_addrs; @@ -2098,14 +2039,18 @@ static int __init trident_install(struct pci_dev *pcidev, struct pci_audio_info card->banks[BANK_B].addresses = &bank_b_addrs; card->banks[BANK_B].bitmap = 0UL; spin_lock_init(&card->lock); - devs = card; + devs = card; + + pci_set_master(pci_dev); + pci_enable_device(pci_dev); printk(KERN_INFO "trident: %s found at IO 0x%04lx, IRQ %d\n", - card->pci_info->name, card->iobase, card->irq); + card_names[pci_id->driver_data], card->iobase, card->irq); /* claim our iospace and irq */ - request_region(card->iobase, 256, card->pci_info->name); - if (request_irq(card->irq, &trident_interrupt, SA_SHIRQ, card->pci_info->name, card)) { + request_region(card->iobase, 256, card_names[pci_id->driver_data]); + if (request_irq(card->irq, &trident_interrupt, SA_SHIRQ, + card_names[pci_id->driver_data], card)) { printk(KERN_ERR "trident: unable to allocate irq %d\n", card->irq); release_region(card->iobase, 256); kfree(card); @@ -2117,7 +2062,7 @@ static int __init trident_install(struct pci_dev *pcidev, struct pci_audio_info release_region(iobase, 256); free_irq(card->irq, card); kfree(card); - return 0; + return -1; } /* initilize AC97 codec and register /dev/mixer */ if (trident_ac97_init(card) <= 0) { @@ -2125,68 +2070,66 @@ static int __init trident_install(struct pci_dev *pcidev, struct pci_audio_info release_region(iobase, 256); free_irq(card->irq, card); kfree(card); - return 0; + return -1; } outl(0x00, TRID_REG(card, T4D_MUSICVOL_WAVEVOL)); + pci_dev->driver_data = card; + pci_dev->dma_mask = TRIDENT_DMA_MASK; + /* Enable Address Engine Interrupts */ trident_enable_loop_interrupts(card); - return 1; + return 0; } -static int __init init_trident(void) +static void __devexit trident_remove(struct pci_dev *pci_dev) { - struct pci_dev *pcidev = NULL; - int foundone = 0; int i; + struct trident_card *card = pci_dev->driver_data; - if (!pci_present()) /* No PCI bus in this machine! */ - return -ENODEV; + /* Kill interrupts, and SP/DIF */ + trident_disable_loop_interrupts(card); - printk(KERN_INFO "Trident 4DWave/SiS 7018 PCI Audio, version " - DRIVER_VERSION ", " __TIME__ " " __DATE__ "\n"); + /* free hardware resources */ + free_irq(card->irq, devs); + release_region(card->iobase, 256); - for (i = 0; i < sizeof (pci_audio_devices); i++) { - pcidev = NULL; - while ((pcidev = pci_find_device(pci_audio_devices[i].vendor, - pci_audio_devices[i].device, - pcidev)) != NULL) { - foundone += trident_install(pcidev, pci_audio_devices + i); + /* unregister audio devices */ + for (i = 0; i < NR_AC97; i++) + if (devs->ac97_codec[i] != NULL) { + unregister_sound_mixer(card->ac97_codec[i]->dev_mixer); + kfree (card->ac97_codec[i]); } - } + unregister_sound_dsp(card->dev_audio); - if (!foundone) - return -ENODEV; - return 0; + kfree(card); } MODULE_AUTHOR("Alan Cox, Aaron Holtzman, Ollie Lho"); MODULE_DESCRIPTION("Trident 4DWave/SiS 7018 PCI Audio Driver"); -static void __exit cleanup_trident(void) -{ - while (devs != NULL) { - int i; - /* Kill interrupts, and SP/DIF */ - trident_disable_loop_interrupts(devs); +#define TRIDENT_MODULE_NAME "trident" - /* free hardware resources */ - free_irq(devs->irq, devs); - release_region(devs->iobase, 256); +static struct pci_driver trident_pci_driver = { + name: TRIDENT_MODULE_NAME, + id_table: trident_pci_tbl, + probe: trident_probe, + remove: trident_remove, +}; - /* unregister audio devices */ - for (i = 0; i < NR_AC97; i++) - if (devs->ac97_codec[i] != NULL) { - unregister_sound_mixer(devs->ac97_codec[i]->dev_mixer); - kfree (devs->ac97_codec[i]); - } - unregister_sound_dsp(devs->dev_audio); +static int __init trident_init_module (void) +{ + printk(KERN_INFO "Trident 4DWave/SiS 7018 PCI Audio, version " + DRIVER_VERSION ", " __TIME__ " " __DATE__ "\n"); - kfree(devs); - devs = devs->next; - } + return pci_module_init (&trident_pci_driver); +} + +static void __exit trident_cleanup_module (void) +{ + pci_unregister_driver (&trident_pci_driver); } -module_init(init_trident); -module_exit(cleanup_trident); +module_init(trident_init_module); +module_exit(trident_cleanup_module); diff --git a/drivers/sound/trident.h b/drivers/sound/trident.h index 4504cb303..6bbb25bd1 100644 --- a/drivers/sound/trident.h +++ b/drivers/sound/trident.h @@ -60,13 +60,13 @@ #define TRIDENT_FMT_16BIT 0x02 #define TRIDENT_FMT_MASK 0x03 -#define DMA_ENABLE 0x01 -#define DMA_RUNNING 0x02 - +#define DAC_RUNNING 0x01 +#define ADC_RUNNING 0x02 /* Register Addresses */ /* operational registers common to DX, NX, 7018 */ enum trident_op_registers { + T4D_REC_CH = 0x70, T4D_START_A = 0x80, T4D_STOP_A = 0x84, T4D_DLY_A = 0x88, T4D_SIGN_CSO_A = 0x8c, T4D_CSPF_A = 0x90, T4D_CEBC_A = 0x94, diff --git a/drivers/sound/trix.c b/drivers/sound/trix.c index 107c6ca9e..d36da3f9c 100644 --- a/drivers/sound/trix.c +++ b/drivers/sound/trix.c @@ -13,9 +13,11 @@ * * Changes * Alan Cox Modularisation, cleanup. + * Christoph Hellwig Adapted to module_init/module_exit */ #include +#include #include #include "sound_config.h" @@ -23,9 +25,10 @@ #include "sb.h" #include "sound_firmware.h" -#include -#include "trix_boot.h" +#include "ad1848.h" +#include "mpu401.h" +#include "trix_boot.h" static int kilroy_was_here = 0; /* Don't detect twice */ static int sb_initialized = 0; @@ -35,11 +38,7 @@ static int *trix_osp = NULL; static int mpu = 0; -#ifdef TRIX_JOYSTICK -static int joystick=1; -#else static int joystick=0; -#endif static unsigned char trix_read(int addr) { @@ -137,7 +136,7 @@ static int trix_set_wss_port(struct address_info *hw_config) * AudioTrix Pro */ -int probe_trix_wss(struct address_info *hw_config) +static int __init probe_trix_wss(struct address_info *hw_config) { int ret; @@ -202,8 +201,7 @@ int probe_trix_wss(struct address_info *hw_config) return ret; } -void -attach_trix_wss(struct address_info *hw_config) +static void __init attach_trix_wss(struct address_info *hw_config) { static unsigned char interrupt_bits[12] = { 0, 0, 0, 0, 0, 0, 0, 0x08, 0, 0x10, 0x18, 0x20 @@ -273,7 +271,7 @@ attach_trix_wss(struct address_info *hw_config) } } -int probe_trix_sb(struct address_info *hw_config) +static int __init probe_trix_sb(struct address_info *hw_config) { int tmp; @@ -323,7 +321,7 @@ int probe_trix_sb(struct address_info *hw_config) return sb_dsp_detect(hw_config, 0, 0); } -void attach_trix_sb(struct address_info *hw_config) +static void __init attach_trix_sb(struct address_info *hw_config) { extern int sb_be_quiet; int old_quiet; @@ -339,13 +337,13 @@ void attach_trix_sb(struct address_info *hw_config) sb_be_quiet = old_quiet; } -void attach_trix_mpu(struct address_info *hw_config) +static void __init attach_trix_mpu(struct address_info *hw_config) { hw_config->name = "AudioTrix Pro"; attach_uart401(hw_config); } -int probe_trix_mpu(struct address_info *hw_config) +static int __init probe_trix_mpu(struct address_info *hw_config) { unsigned char conf; static char irq_bits[] = { @@ -406,7 +404,7 @@ int probe_trix_mpu(struct address_info *hw_config) return probe_uart401(hw_config); } -void unload_trix_wss(struct address_info *hw_config) +static void __exit unload_trix_wss(struct address_info *hw_config) { int dma2 = hw_config->dma2; @@ -424,31 +422,32 @@ void unload_trix_wss(struct address_info *hw_config) sound_unload_audiodev(hw_config->slots[0]); } -void unload_trix_mpu(struct address_info *hw_config) +static inline void __exit unload_trix_mpu(struct address_info *hw_config) { unload_uart401(hw_config); } -void unload_trix_sb(struct address_info *hw_config) +static inline void __exit unload_trix_sb(struct address_info *hw_config) { sb_dsp_unload(hw_config, mpu); } -#ifdef MODULE - -int io = -1; -int irq = -1; -int dma = -1; -int dma2 = -1; /* Set this for modules that need it */ - -int sb_io = -1; -int sb_dma = -1; -int sb_irq = -1; +static struct address_info cfg; +static struct address_info cfg2; +static struct address_info cfg_mpu; -int mpu_io = -1; -int mpu_irq = -1; +static int sb = 0; +static int fw_load; -EXPORT_NO_SYMBOLS; +static int __initdata io = -1; +static int __initdata irq = -1; +static int __initdata dma = -1; +static int __initdata dma2 = -1; /* Set this for modules that need it */ +static int __initdata sb_io = -1; +static int __initdata sb_dma = -1; +static int __initdata sb_irq = -1; +static int __initdata mpu_io = -1; +static int __initdata mpu_irq = -1; MODULE_PARM(io,"i"); MODULE_PARM(irq,"i"); @@ -460,42 +459,33 @@ MODULE_PARM(sb_irq,"i"); MODULE_PARM(mpu_io,"i"); MODULE_PARM(mpu_irq,"i"); MODULE_PARM(joystick, "i"); -struct address_info config; -struct address_info sb_config; -struct address_info mpu_config; -static int sb = 0; - -static int fw_load; - -int init_module(void) +static int __init init_trix(void) { printk(KERN_INFO "MediaTrix 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 = dma2; + + cfg2.io_base = sb_io; + cfg2.irq = sb_irq; + cfg2.dma = sb_dma; + + cfg_mpu.io_base = mpu_io; + cfg_mpu.irq = mpu_irq; + + 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; } - config.io_base = io; - config.irq = irq; - config.dma = dma; - config.dma2 = dma2; - - sb_config.io_base = sb_io; - sb_config.irq = sb_irq; - sb_config.dma = sb_dma; - mpu_config.io_base = mpu_io; - mpu_config.irq = mpu_irq; - - if (sb_io != -1 && (sb_irq == -1 || sb_dma == -1)) - { + if (cfg2.io_base != -1 && (cfg2.irq == -1 || cfg2.dma == -1)) { printk(KERN_INFO "CONFIG_SB_IRQ and CONFIG_SB_DMA must be specified if SB_IO is set.\n"); return -EINVAL; } - if (mpu_io != -1 && mpu_irq == -1) - { + if (cfg_mpu.io_base != -1 && cfg_mpu.irq == -1) { printk(KERN_INFO "CONFIG_MPU_IRQ must be specified if MPU_IO is set.\n"); return -EINVAL; } @@ -505,42 +495,65 @@ int init_module(void) trix_boot_len = mod_firmware_load("/etc/sound/trxpro.bin", (char **) &trix_boot); } - if (!probe_trix_wss(&config)) + if (!probe_trix_wss(&cfg)) return -ENODEV; - attach_trix_wss(&config); + attach_trix_wss(&cfg); /* * We must attach in the right order to get the firmware * loaded up in time. */ - if (sb_io != -1) - { - sb = probe_trix_sb(&sb_config); + if (cfg2.io_base != -1) { + sb = probe_trix_sb(&cfg2); if (sb) - attach_trix_sb(&sb_config); + attach_trix_sb(&cfg2); } - if (mpu_io != -1) - { - mpu = probe_trix_mpu(&mpu_config); + if (cfg_mpu.io_base != -1) { + mpu = probe_trix_mpu(&cfg_mpu); if (mpu) - attach_trix_mpu(&mpu_config); + attach_trix_mpu(&cfg_mpu); } SOUND_LOCK; return 0; } -void cleanup_module(void) +static void __exit cleanup_trix(void) { if (fw_load && trix_boot) vfree(trix_boot); if (sb) - unload_trix_sb(&sb_config); + unload_trix_sb(&cfg2); if (mpu) - unload_trix_mpu(&mpu_config); - unload_trix_wss(&config); + unload_trix_mpu(&cfg_mpu); + unload_trix_wss(&cfg); SOUND_LOCK_END; } -#endif /* MODULE */ +module_init(init_trix); +module_exit(cleanup_trix); + +#ifndef MODULE +static int __init setup_trix (char *str) +{ + /* io, irq, dma, dma2, sb_io, sb_irq, sb_dma, mpu_io, mpu_irq */ + int ints[9]; + + str = get_options(str, ARRAY_SIZE(ints), ints); + + io = ints[1]; + irq = ints[2]; + dma = ints[3]; + dma2 = ints[4]; + sb_io = ints[5]; + sb_irq = ints[6]; + sb_dma = ints[6]; + mpu_io = ints[7]; + mpu_irq = ints[8]; + + return 1; +} + +__setup("trix=", setup_trix); +#endif diff --git a/drivers/sound/uart401.c b/drivers/sound/uart401.c index c4f105ef5..71721dd3e 100644 --- a/drivers/sound/uart401.c +++ b/drivers/sound/uart401.c @@ -2,8 +2,8 @@ * sound/uart401.c * * MPU-401 UART driver (formerly uart401_midi.c) - */ -/* + * + * * Copyright (C) by Hannu Savolainen 1993-1997 * * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) @@ -11,19 +11,23 @@ * for more info. * * Changes: - * Alan Cox Reformatted, removed sound_mem usage, use normal Linux - * interrupt allocation. Protect against bogus unload - * Fixed to allow IRQ > 15 + * Alan Cox Reformatted, removed sound_mem usage, use normal Linux + * interrupt allocation. Protect against bogus unload + * Fixed to allow IRQ > 15 + * Christoph Hellwig Adapted to module_init/module_exit * * Status: * Untested */ - + +#include #include #include "sound_config.h" #include "soundmodule.h" +#include "mpu401.h" + typedef struct uart401_devc { int base; @@ -177,21 +181,21 @@ static int uart401_out(int dev, unsigned char midi_byte) return 1; } -static int uart401_start_read(int dev) +static inline int uart401_start_read(int dev) { return 0; } -static int uart401_end_read(int dev) +static inline int uart401_end_read(int dev) { return 0; } -static void uart401_kick(int dev) +static inline void uart401_kick(int dev) { } -static int uart401_buffer_status(int dev) +static inline int uart401_buffer_status(int dev) { return 0; } @@ -444,43 +448,60 @@ void unload_uart401(struct address_info *hw_config) sound_unload_mididev(hw_config->slots[4]); } -#ifdef MODULE +EXPORT_SYMBOL(attach_uart401); +EXPORT_SYMBOL(probe_uart401); +EXPORT_SYMBOL(unload_uart401); +EXPORT_SYMBOL(uart401intr); -int io = -1; -int irq = -1; +static struct address_info cfg_mpu; + +static int __initdata io = -1; +static int __initdata irq = -1; MODULE_PARM(io, "i"); MODULE_PARM(irq, "i"); -struct address_info hw; -int init_module(void) + +static int __init init_uart401(void) { + cfg_mpu.irq = irq; + cfg_mpu.io_base = io; + /* Can be loaded either for module use or to provide functions to others */ - if (io != -1 && irq != -1) - { + if (cfg_mpu.io_base != -1 && cfg_mpu.irq != -1) { printk(KERN_INFO "MPU-401 UART driver Copyright (C) Hannu Savolainen 1993-1997"); - hw.irq = irq; - hw.io_base = io; - if (probe_uart401(&hw) == 0) + if (probe_uart401(&cfg_mpu) == 0) return -ENODEV; - attach_uart401(&hw); + attach_uart401(&cfg_mpu); } SOUND_LOCK; return 0; } -void cleanup_module(void) +static void __exit cleanup_uart401(void) { - if (io != -1 && irq != -1) - unload_uart401(&hw); - /* FREE SYMTAB */ + if (cfg_mpu.io_base != -1 && cfg_mpu.irq != -1) + unload_uart401(&cfg_mpu); SOUND_LOCK_END; } -#endif /* MODULE */ +module_init(init_uart401); +module_exit(cleanup_uart401); -EXPORT_SYMBOL(attach_uart401); -EXPORT_SYMBOL(probe_uart401); -EXPORT_SYMBOL(unload_uart401); -EXPORT_SYMBOL(uart401intr); +#ifndef MODULE +static int __init setup_uart401(char *str) +{ + /* io, irq */ + int ints[3]; + + str = get_options(str, ARRAY_SIZE(ints), ints); + + io = ints[1]; + irq = ints[2]; + + return 1; +} + +__setup("uart401=", setup_uart401); +#endif diff --git a/drivers/sound/uart6850.c b/drivers/sound/uart6850.c index b0548d513..6540df0f6 100644 --- a/drivers/sound/uart6850.c +++ b/drivers/sound/uart6850.c @@ -1,7 +1,7 @@ /* * sound/uart6850.c - */ -/* + * + * * Copyright (C) by Hannu Savolainen 1993-1997 * * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) @@ -10,12 +10,15 @@ * Extended by Alan Cox for Red Hat Software. Now a loadable MIDI driver. * 28/4/97 - (C) Copyright Alan Cox. Released under the GPL version 2. * - * Alan Cox: Updated for new modular code. Removed snd_* irq handling. Now - * uses native linux resources + * Alan Cox: Updated for new modular code. Removed snd_* irq handling. Now + * uses native linux resources + * Christoph Hellwig: Adapted to module_init/module_exit * * Status: Testing required * */ + +#include #include /* Mon Nov 22 22:38:35 MET 1993 marco@driq.home.usn.nl: @@ -199,26 +202,26 @@ static int uart6850_out(int dev, unsigned char midi_byte) return 1; } -static int uart6850_command(int dev, unsigned char *midi_byte) +static inline int uart6850_command(int dev, unsigned char *midi_byte) { return 1; } -static int uart6850_start_read(int dev) +static inline int uart6850_start_read(int dev) { return 0; } -static int uart6850_end_read(int dev) +static inline int uart6850_end_read(int dev) { return 0; } -static void uart6850_kick(int dev) +static inline void uart6850_kick(int dev) { } -static int uart6850_buffer_status(int dev) +static inline int uart6850_buffer_status(int dev) { return 0; /* * No data in buffers @@ -246,7 +249,7 @@ static struct midi_operations uart6850_operations = }; -void attach_uart6850(struct address_info *hw_config) +static void __init attach_uart6850(struct address_info *hw_config) { int ok, timeout; unsigned long flags; @@ -292,7 +295,7 @@ static int reset_uart6850(void) } -int probe_uart6850(struct address_info *hw_config) +static int __init probe_uart6850(struct address_info *hw_config) { int ok = 0; @@ -308,45 +311,58 @@ int probe_uart6850(struct address_info *hw_config) return ok; } -void unload_uart6850(struct address_info *hw_config) +static void __exit unload_uart6850(struct address_info *hw_config) { free_irq(hw_config->irq, NULL); sound_unload_mididev(hw_config->slots[4]); } +static struct address_info cfg_mpu; -#ifdef MODULE - -int io = -1; -int irq = -1; +static int __initdata io = -1; +static int __initdata irq = -1; MODULE_PARM(io,"i"); MODULE_PARM(irq,"i"); -EXPORT_NO_SYMBOLS; - -struct address_info cfg; - -int init_module(void) +static int __init init_uart6850(void) { - if (io == -1 || irq == -1) - { + cfg_mpu.io_base = io; + cfg_mpu.irq = irq; + + if (cfg_mpu.io_base == -1 || cfg_mpu.irq == -1) { printk(KERN_INFO "uart6850: irq and io must be set.\n"); return -EINVAL; } - cfg.io_base = io; - cfg.irq = irq; - if (probe_uart6850(&cfg)) + if (probe_uart6850(&cfg_mpu)) return -ENODEV; SOUND_LOCK; return 0; } -void cleanup_module(void) +static void __exit cleanup_uart6850(void) { - unload_uart6850(&cfg); + unload_uart6850(&cfg_mpu); SOUND_LOCK_END; } -#endif /* MODULE */ + +module_init(init_uart6850); +module_exit(cleanup_uart6850); + +#ifndef MODULE +static int __init setup_uart6850(char *str) +{ + /* io, irq */ + int ints[3]; + + str = get_options(str, ARRAY_SIZE(ints), ints); + + io = ints[1]; + irq = ints[2]; + + return 1; +} +__setup("uart6850=", setup_uart6850); +#endif diff --git a/drivers/sound/v_midi.c b/drivers/sound/v_midi.c index 0cab16199..9c18ff5c8 100644 --- a/drivers/sound/v_midi.c +++ b/drivers/sound/v_midi.c @@ -13,11 +13,13 @@ * * Changes * Alan Cox Modularisation, changed memory allocations + * Christoph Hellwig Adapted to module_init/module_exit * * Status * Untested */ +#include #include #include "sound_config.h" @@ -29,28 +31,6 @@ static vmidi_devc *v_devc[2] = { NULL, NULL}; static int midi1,midi2; static void *midi_mem = NULL; -#ifdef MODULE - -static struct address_info config; /* dummy */ - -int init_module(void) -{ - printk("MIDI Loopback device driver\n"); - if (!probe_v_midi(&config)) - return -ENODEV; - attach_v_midi(&config); - SOUND_LOCK; - return 0; -} - -void cleanup_module(void) -{ - unload_v_midi(&config); - SOUND_LOCK_END; -} - -#endif /* MODULE */ - /* * The DSP channel can be used either for input or output. Variable * 'sb_irq_mode' will be set when the program calls read or write first time @@ -126,7 +106,7 @@ static int v_midi_out (int dev, unsigned char midi_byte) return 1; } -static int v_midi_start_read (int dev) +static inline int v_midi_start_read (int dev) { return 0; } @@ -143,7 +123,7 @@ static int v_midi_end_read (int dev) /* why -EPERM and not -EINVAL?? */ -static int v_midi_ioctl (int dev, unsigned cmd, caddr_t arg) +static inline int v_midi_ioctl (int dev, unsigned cmd, caddr_t arg) { return -EPERM; } @@ -201,7 +181,7 @@ struct vmidi_memory struct vmidi_devc v_ops[2]; }; -void attach_v_midi (struct address_info *hw_config) +static void __init attach_v_midi (struct address_info *hw_config) { struct vmidi_memory *m; /* printk("Attaching v_midi device.....\n"); */ @@ -282,15 +262,38 @@ void attach_v_midi (struct address_info *hw_config) /* printk("Attached v_midi device\n"); */ } -int probe_v_midi(struct address_info *hw_config) +static inline int __init probe_v_midi(struct address_info *hw_config) { return(1); /* always OK */ } -void unload_v_midi(struct address_info *hw_config) +static void __exit unload_v_midi(struct address_info *hw_config) { sound_unload_mididev(midi1); sound_unload_mididev(midi2); kfree(midi_mem); } + +static struct address_info cfg; /* dummy */ + +static int __init init_vmidi(void) +{ + printk("MIDI Loopback device driver\n"); + if (!probe_v_midi(&cfg)) + return -ENODEV; + attach_v_midi(&cfg); + + SOUND_LOCK; + + return 0; +} + +static void __exit cleanup_vmidi(void) +{ + unload_v_midi(&cfg); + SOUND_LOCK_END; +} + +module_init(init_vmidi); +module_exit(cleanup_vmidi); diff --git a/drivers/sound/via82cxxx_audio.c b/drivers/sound/via82cxxx_audio.c index cee2e7b0a..5745a9037 100644 --- a/drivers/sound/via82cxxx_audio.c +++ b/drivers/sound/via82cxxx_audio.c @@ -33,6 +33,7 @@ #include "soundmodule.h" #include "sb.h" #include "ac97.h" +#include "mpu401.h" #ifndef SOUND_LOCK #define SOUND_LOCK do {} while (0) diff --git a/drivers/sound/vidc.c b/drivers/sound/vidc.c index 578d4dff9..9cebcc324 100644 --- a/drivers/sound/vidc.c +++ b/drivers/sound/vidc.c @@ -14,6 +14,7 @@ */ #include +#include #include #include @@ -412,7 +413,7 @@ void vidc_update_filler(int format, int channels) } } -void attach_vidc(struct address_info *hw_config) +static void __init attach_vidc(struct address_info *hw_config) { char name[32]; int i, adev; @@ -486,7 +487,7 @@ audio_failed: return; } -int probe_vidc(struct address_info *hw_config) +static int __init probe_vidc(struct address_info *hw_config) { hw_config->irq = IRQ_DMAS0; hw_config->dma = DMA_VIRTUAL_SOUND; @@ -496,7 +497,7 @@ int probe_vidc(struct address_info *hw_config) return 1; } -void unload_vidc(struct address_info *hw_config) +static void __exit unload_vidc(struct address_info *hw_config) { int i, adev = vidc_adev; @@ -516,27 +517,27 @@ void unload_vidc(struct address_info *hw_config) } } -#ifdef MODULE -static struct address_info config; +static struct address_info cfg; /* * Note! Module use count is handled by SOUNDLOCK/SOUND_LOCK_END */ -int init_module(void) +static int __init init_vidc(void) { - if (probe_vidc(&config) == 0) + if (probe_vidc(&cfg) == 0) return -ENODEV; SOUND_LOCK; - attach_vidc(&config); + attach_vidc(&cfg); return 0; } -void cleanup_module(void) +static void __exit cleanup_vidc(void) { - unload_vidc(&config); + unload_vidc(&cfg); SOUND_LOCK_END; } -#endif +module_init(init_vidc); +module_exit(cleanup_vidc); diff --git a/drivers/sound/waveartist.c b/drivers/sound/waveartist.c index 905b9cff6..d1631defd 100644 --- a/drivers/sound/waveartist.c +++ b/drivers/sound/waveartist.c @@ -6,9 +6,8 @@ * * Cleaned up and integrated into 2.1 by Russell King (rmk@arm.linux.org.uk) * and Pat Beirne (patb@corel.ca) - */ - -/* + * + * * Copyright (C) by Rebel.com 1998-1999 * * RWA010 specs received under NDA from Rockwell @@ -31,6 +30,7 @@ #define debug_flg (0) #include +#include #include #include #include @@ -1281,8 +1281,7 @@ nomem: return -1; } -int -probe_waveartist(struct address_info *hw_config) +static int __init probe_waveartist(struct address_info *hw_config) { wavnc_info *devc = &adev_info[nr_waveartist_devs]; @@ -1316,8 +1315,7 @@ probe_waveartist(struct address_info *hw_config) return 1; } -void -attach_waveartist(struct address_info *hw) +static void __init attach_waveartist(struct address_info *hw) { wavnc_info *devc = &adev_info[nr_waveartist_devs]; @@ -1359,8 +1357,7 @@ attach_waveartist(struct address_info *hw) } } -void -unload_waveartist(struct address_info *hw) +static void __exit unload_waveartist(struct address_info *hw) { wavnc_info *devc = NULL; int i; @@ -1757,45 +1754,63 @@ vnc_private_ioctl(int dev, unsigned int cmd, caddr_t arg) return -ENOIOCTLCMD; } -#ifdef MODULE +static struct address_info cfg; + +static int attached; + +static int __initdata io; +static int __initdata irq; +static int __initdata dma; +static int __initdata dma2; + MODULE_PARM(io, "i"); /* IO base */ MODULE_PARM(irq, "i"); /* IRQ */ MODULE_PARM(dma, "i"); /* DMA */ MODULE_PARM(dma2, "i"); /* DMA2 */ -static int io = CONFIG_WAVEARTIST_BASE; -static int irq = CONFIG_WAVEARTIST_IRQ; -static int dma = CONFIG_WAVEARTIST_DMA; -static int dma2 = CONFIG_WAVEARTIST_DMA2; - -static int attached; - -static struct address_info hw_config; - -int init_module(void) +static int __init init_waveartist(void) { - hw_config.io_base = io; - hw_config.irq = irq; - hw_config.dma = dma; - hw_config.dma2 = dma2; + cfg.io_base = io; + cfg.irq = irq; + cfg.dma = dma; + cfg.dma2 = dma2; - if (!probe_waveartist(&hw_config)) + if (!probe_waveartist(&cfg)) return -ENODEV; - attach_waveartist(&hw_config); + attach_waveartist(&cfg); attached = 1; SOUND_LOCK; return 0; } -void cleanup_module(void) +static void __exit cleanup_waveartist(void) { if (attached) { SOUND_LOCK_END; - - unload_waveartist(&hw_config); + unload_waveartist(&cfg); } } + +module_init(init_waveartist); +module_exit(cleanup_waveartist); + +#ifndef MODULE +static int __init setup_waveartist(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("waveartist=", setup_waveartist); #endif diff --git a/drivers/sound/wavfront.c b/drivers/sound/wavfront.c index 2967fdf18..af1f8970d 100644 --- a/drivers/sound/wavfront.c +++ b/drivers/sound/wavfront.c @@ -65,6 +65,7 @@ #include #include +#include #include #include #include @@ -128,10 +129,6 @@ static int (*midi_load_patch) (int devno, int format, const char *addr, int offs, int count, int pmgr_flag) = NULL; #endif OSS_SUPPORT_SEQ -/* This is meant to work as a module */ - -#if defined(CONFIG_SOUND_WAVEFRONT_MODULE) && defined(MODULE) - /* if WF_DEBUG not defined, no run-time debugging messages will be available via the debug flag setting. Given the current beta state of the driver, this will remain set until a future @@ -2144,25 +2141,23 @@ static struct synth_operations wavefront_operations = #if OSS_SUPPORT_LEVEL & OSS_SUPPORT_STATIC_INSTALL -void attach_wavefront (struct address_info *hw_config) - +static void __init attach_wavefront (struct address_info *hw_config) { (void) install_wavefront (); } -int probe_wavefront (struct address_info *hw_config) - +static int __init probe_wavefront (struct address_info *hw_config) { return !detect_wavefront (hw_config->irq, hw_config->io_base); } -void unload_wavefront (struct address_info *hw_config) +static void __exit unload_wavefront (struct address_info *hw_config) { (void) uninstall_wavefront (); } #endif OSS_SUPPORT_STATIC_INSTALL - + /***********************************************************************/ /* WaveFront: Linux modular sound kernel installation interface */ /***********************************************************************/ @@ -2814,8 +2809,7 @@ wavefront_do_reset (int atboot) return 1; } -static int -wavefront_init (int atboot) +static int __init wavefront_init (int atboot) { int samples_are_from_rom; @@ -2884,9 +2878,7 @@ static int __init install_wavefront (void) return dev.oss_dev; } -void -uninstall_wavefront (void) - +static void __exit uninstall_wavefront (void) { /* the first two i/o addresses are freed by the wf_mpu code */ release_region (dev.base+2, 6); @@ -2938,7 +2930,7 @@ wffx_idle (void) return (1); } -static int __init detect_wffx (void) +int __init detect_wffx (void) { /* This is a crude check, but its the best one I have for now. Certainly on the Maui and the Tropez, wffx_idle() will @@ -2954,7 +2946,7 @@ static int __init detect_wffx (void) return 0; } -static int __init attach_wffx (void) +int __init attach_wffx (void) { if ((dev.fx_mididev = sound_alloc_mididev ()) < 0) { printk (KERN_WARNING LOGNAME "cannot install FX Midi driver\n"); @@ -2964,7 +2956,7 @@ static int __init attach_wffx (void) return 0; } -static void +void wffx_mute (int onoff) { @@ -3087,9 +3079,7 @@ wffx_ioctl (wavefront_fx_info *r) a somewhat "algorithmic" approach. */ -static int -wffx_init (void) - +static int wffx_init (void) { int i; int j; @@ -3543,18 +3533,15 @@ wffx_init (void) return (0); } -EXPORT_NO_SYMBOLS; - -int io = -1; -int irq = -1; +static int io = -1; +static int irq = -1; MODULE_AUTHOR ("Paul Barton-Davis "); MODULE_DESCRIPTION ("Turtle Beach WaveFront Linux Driver"); MODULE_PARM (io,"i"); MODULE_PARM (irq,"i"); -int init_module (void) - +static int __init init_wavfront (void) { printk ("Turtle Beach WaveFront Driver\n" "Copyright (C) by Hannu Solvainen, " @@ -3585,14 +3572,11 @@ int init_module (void) return 0; } -void cleanup_module (void) - +static void __exit cleanup_wavfront (void) { uninstall_wavefront (); - SOUND_LOCK_END; } -#endif CONFIG_SOUND_WAVEFRONT_MODULE && MODULE - - +module_init(init_wavfront); +module_exit(cleanup_wavfront); diff --git a/drivers/sound/wf_midi.c b/drivers/sound/wf_midi.c index 45db0f8b1..4b0708ec7 100644 --- a/drivers/sound/wf_midi.c +++ b/drivers/sound/wf_midi.c @@ -42,7 +42,7 @@ * Copyright (C) by Paul Barton-Davis 1998 * Some portions of this file are derived from work that is: * - * Copyright (C) by Hannu Savolainen 1993-1996 + * CopyriGht (C) by Hannu Savolainen 1993-1996 * * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) * Version 2 (June 1991). See the "COPYING" file distributed with this software @@ -56,7 +56,7 @@ #include -#if defined(CONFIG_SOUND_WAVEFRONT_MODULE) && defined(MODULE) +#ifdef MODULE struct wf_mpu_config { int base; @@ -87,37 +87,27 @@ static void start_uart_mode (void); #define MPU_ACK 0xFE #define UART_MODE_ON 0x3F -static inline int -wf_mpu_status (void) - +static inline int wf_mpu_status (void) { return inb (STATPORT (phys_dev)); } -static inline int -input_avail (void) - +static inline int input_avail (void) { return !(wf_mpu_status() & INPUT_AVAIL); } -static inline int -output_ready (void) - +static inline int output_ready (void) { return !(wf_mpu_status() & OUTPUT_READY); } -static inline int -read_data (void) - +static inline int read_data (void) { return inb (DATAPORT (phys_dev)); } -static inline void -write_data (unsigned char byte) - +static inline void write_data (unsigned char byte) { outb (byte, DATAPORT (phys_dev)); } @@ -536,28 +526,22 @@ wf_mpu_out (int dev, unsigned char midi_byte) return 1; } -static int -wf_mpu_start_read (int dev) -{ +static inline int wf_mpu_start_read (int dev) { return 0; } -static int -wf_mpu_end_read (int dev) -{ +static inline int wf_mpu_end_read (int dev) { return 0; } -static int -wf_mpu_ioctl (int dev, unsigned cmd, caddr_t arg) +static int wf_mpu_ioctl (int dev, unsigned cmd, caddr_t arg) { printk (KERN_WARNING "WF-MPU: Intelligent mode not supported by hardware.\n"); return -(EINVAL); } -static int -wf_mpu_buffer_status (int dev) +static int wf_mpu_buffer_status (int dev) { return 0; } @@ -901,31 +885,4 @@ start_uart_mode (void) restore_flags (flags); } - -#ifdef OSS_SUPPORT - -int -probe_wf_mpu (struct address_info *hw_config) - -{ - return !detect_wf_mpu (hw_config->irq, hw_config->io_base); -} - -void -attach_wf_mpu (struct address_info *hw_config) - -{ - (void) install_wf_mpu (); -} - -void -unload_wf_mpu (void) -{ - uninstall_wf_mpu (); -} - -#endif OSS_SUPPORT - -#endif CONFIG_SOUND_WAVEFRONT_MODULE_AND_MODULE - - +#endif -- cgit v1.2.3