diff options
Diffstat (limited to 'drivers/sound')
45 files changed, 6552 insertions, 5606 deletions
diff --git a/drivers/sound/Config.in b/drivers/sound/Config.in index d4678da82..8f1d2bec7 100644 --- a/drivers/sound/Config.in +++ b/drivers/sound/Config.in @@ -2,12 +2,11 @@ dep_tristate 'ProAudioSpectrum 16 support' CONFIG_PAS $CONFIG_SOUND if [ "$CONFIG_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_tristate '100% Sound Blaster compatibles (SB16/32/64, ESS, Jazz16) support' CONFIG_SB $CONFIG_SOUND if [ "$CONFIG_SB" = "y" ]; then - bool 'Is the card a Soundman Games ?' CONFIG_SM_GAMES - bool 'Are you using the IBM Mwave "emulation" of SB ?' CONFIG_SB_MWAVE 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 @@ -43,7 +42,7 @@ if [ "$CONFIG_MPU401" = "y" ]; then int 'MPU401 IRQ Check from manual of the card' CONFIG_MPU_IRQ 9 fi -dep_tristate 'PSS (ECHO-ADI2111) support' CONFIG_PSS $CONFIG_SOUND +dep_tristate 'PSS (AD1848, ADSP-2115, ESC614) support' CONFIG_PSS $CONFIG_SOUND if [ "$CONFIG_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 @@ -56,6 +55,9 @@ if [ "$CONFIG_PSS" = "y" ]; then string ' Full pathname of DSPxxx.LD firmware file' CONFIG_PSS_BOOT_FILE fi fi +if [ "$CONFIG_PSS" = "m" ] || [ "$CONFIG_PSS" = "y" ]; then + bool ' Enable PSS mixer (Beethoven ADSP-16 and other compatibile)' CONFIG_PSS_MIXER +fi dep_tristate 'Microsoft Sound System support' CONFIG_MSS $CONFIG_SOUND if [ "$CONFIG_MSS" = "y" ]; then @@ -92,6 +94,7 @@ if [ "$CONFIG_TRIX" = "y" ]; then fi dep_tristate 'Support for OPTi MAD16 and/or Mozart based cards' CONFIG_MAD16 $CONFIG_SOUND +dep_tristate 'Support MIDI in older MAD16 based cards (requires SB)' CONFIG_MAD16_OLDCARD $CONFIG_MAD16 if [ "$CONFIG_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 @@ -213,3 +216,6 @@ if [ "$CONFIG_LOWLEVEL_SOUND" = "y" ]; then fi fi +if [ "$CONFIG_ARM" = "y" ]; then + bool 'VIDC 16-bit sound' CONFIG_VIDC_SOUND +fi diff --git a/drivers/sound/Defines b/drivers/sound/Defines index 6b9ef6bb6..b2aef2dfb 100644 --- a/drivers/sound/Defines +++ b/drivers/sound/Defines @@ -231,6 +231,12 @@ CONFIG_SEQUENCER=y endif endif +ifdef CONFIG_VIDC_SOUND +ifneq ($(CONFIG_SEQUENCER),Y) +CONFIG_SEQUENCER=y +endif +endif + ifdef CONFIG_PAS ifneq ($(CONFIG_AUDIO),Y) CONFIG_AUDIO=y @@ -309,6 +315,12 @@ CONFIG_AUDIO=y endif endif +ifdef CONFIG_VIDC_SOUND +ifneq ($(CONFIG_AUDIO),Y) +CONFIG_AUDIO=y +endif +endif + ifdef CONFIG_PAS ifneq ($(CONFIG_MIDI),Y) CONFIG_MIDI=y diff --git a/drivers/sound/Makefile b/drivers/sound/Makefile index 6b09e336b..1f71965f2 100644 --- a/drivers/sound/Makefile +++ b/drivers/sound/Makefile @@ -117,6 +117,22 @@ else endif endif +ifeq ($(CONFIG_MPU401),y) +LX_OBJS += mpu401.o +else + ifeq ($(CONFIG_MPU401),m) + MX_OBJS += mpu401.o + else + ifeq ($(CONFIG_MPU_EMU),y) + LX_OBJS += mpu401.o + else + ifeq ($(CONFIG_MPU_EMU),m) + MX_OBJS += mpu401.o + endif + endif + endif +endif + ifeq ($(CONFIG_UART401),y) LX_OBJS += uart401.o else @@ -143,31 +159,9 @@ endif ifeq ($(CONFIG_SSCAPE),y) L_OBJS += sscape.o -LX_OBJS += ad1848.o -CONFIG_MPU401 = y else ifeq ($(CONFIG_SSCAPE),m) M_OBJS += sscape.o - MX_OBJS += ad1848.o - ifneq ($(CONFIG_MPU401),y) - CONFIG_MPU401 = m - endif - endif -endif - -ifeq ($(CONFIG_MPU401),y) -LX_OBJS += mpu401.o -else - ifeq ($(CONFIG_MPU401),m) - MX_OBJS += mpu401.o - else - ifeq ($(CONFIG_MPU_EMU),y) - LX_OBJS += mpu401.o - else - ifeq ($(CONFIG_MPU_EMU),m) - MX_OBJS += mpu401.o - endif - endif endif endif @@ -230,27 +224,31 @@ else endif endif +ifeq ($(CONFIG_VIDC_SOUND),y) + L_OBJS += vidc.o vidc_audio.o vidc_mixer.o vidc_synth.o vidc_fill.o +endif + include $(TOPDIR)/Rules.make softoss2.o: softoss.o softoss_rs.o - ld -r -o softoss2.o softoss.o softoss_rs.o + $(LD) -r -o softoss2.o softoss.o softoss_rs.o pas2.o: pas2_card.o pas2_midi.o pas2_mixer.o pas2_pcm.o - ld -r -o pas2.o pas2_card.o pas2_midi.o pas2_mixer.o pas2_pcm.o + $(LD) -r -o pas2.o pas2_card.o pas2_midi.o pas2_mixer.o pas2_pcm.o sb.o: sb_audio.o sb_card.o sb_common.o sb_midi.o sb_mixer.o - ld -r -o sb.o sb_audio.o sb_card.o sb_common.o sb_midi.o sb_mixer.o + $(LD) -r -o sb.o sb_audio.o sb_card.o sb_common.o sb_midi.o sb_mixer.o lowlevel/lowlevel.o: cd lowlevel; make -sound.o: soundcard.o dev_table.o audio.o dmabuf.o sequencer.o sys_timer.o sound_timer.o lowlevel/lowlevel.o midi_synth.o midibuf.o sound_firmware.o - ld -r -o sound.o soundcard.o dev_table.o audio.o dmabuf.o \ +sound.o: soundcard.o dev_table.o audio.o dmabuf.o sequencer.o sys_timer.o sound_timer.o lowlevel/lowlevel.o midi_synth.o midibuf.o sound_firmware.o sound_syms.o + $(LD) -r -o sound.o soundcard.o dev_table.o audio.o dmabuf.o \ sequencer.o sys_timer.o sound_timer.o lowlevel/lowlevel.o \ - midi_synth.o midibuf.o sound_firmware.o + midi_synth.o midibuf.o sound_firmware.o sound_syms.o gus.o: gus_card.o gus_midi.o gus_vol.o gus_wave.o ics2101.o - ld -r -o gus.o gus_card.o gus_midi.o gus_vol.o gus_wave.o ics2101.o + $(LD) -r -o gus.o gus_card.o gus_midi.o gus_vol.o gus_wave.o ics2101.o # Firmware files that need translation # diff --git a/drivers/sound/ad1848.c b/drivers/sound/ad1848.c index d839ed208..2bf9f2c52 100644 --- a/drivers/sound/ad1848.c +++ b/drivers/sound/ad1848.c @@ -12,16 +12,16 @@ * * CS4232 is a PnP audio chip which contains a CS4231A (and SB, MPU). * CS4232A is an improved version of CS4232. - */ - -/* + * + * + * * 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) * general sleep/wakeup clean up. * Alan Cox : reformatted. Fixed SMP bugs. Moved to kernel alloc/free @@ -84,7 +84,6 @@ typedef struct int irq_ok; mixer_ents *mix_devices; int mixer_output_port; - int c930_password_port; } ad1848_info; typedef struct ad1848_port_info @@ -561,6 +560,12 @@ static int ad1848_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg) val = devc->mixer_output_port; return put_user(val, (int *)arg); } + if (cmd == SOUND_MIXER_PRIVATE2) + { + if (get_user(val, (int *)arg)) + return -EFAULT; + return(ad1848_control(AD1848_MIXER_REROUTE, val)); + } if (((cmd >> 8) & 0xff) == 'M') { if (_SIOC_DIR(cmd) & _SIOC_WRITE) @@ -1409,7 +1414,6 @@ int ad1848_detect(int io_base, int *ad_flags, int *osp) devc->chip_name = devc->name = "AD1848"; devc->model = MD_1848; /* AD1848 or CS4248 */ devc->levels = NULL; - devc->c930_password_port = 0; devc->debug_flag = 0; /* @@ -1789,11 +1793,15 @@ int ad1848_init(char *name, int io_base, int irq, int dma_playback, int dma_capt if (request_irq(devc->irq, adintr, 0, devc->name, (void *)my_dev) < 0) { printk(KERN_WARNING "ad1848: Unable to allocate IRQ\n"); + /* Don't free it either then.. */ + devc->irq = 0; } if (devc->model != MD_1848 && devc->model != MD_C930) { +#ifndef __SMP__ int x; unsigned char tmp = ad_read(devc, 16); +#endif devc->timer_ticks = 0; @@ -1843,16 +1851,15 @@ int ad1848_init(char *name, int io_base, int irq, int dma_playback, int dma_capt { audio_devs[my_dev]->mixer_dev = e; } - MOD_INC_USE_COUNT; return my_dev; } -void ad1848_control(int cmd, int arg) +int ad1848_control(int cmd, int arg) { ad1848_info *devc; if (nr_ad1848_devs < 1) - return; + return -ENODEV; devc = &adev_info[nr_ad1848_devs - 1]; @@ -1860,7 +1867,7 @@ void ad1848_control(int cmd, int arg) { case AD1848_SET_XTAL: /* Change clock frequency of AD1845 (only ) */ if (devc->model != MD_1845) - return; + return -EINVAL; ad_enter_MCE(devc); ad_write(devc, 29, (ad_read(devc, 29) & 0x1f) | (arg << 5)); ad_leave_MCE(devc); @@ -1871,32 +1878,37 @@ void ad1848_control(int cmd, int arg) int o = (arg >> 8) & 0xff; int n = arg & 0xff; + if (o < 0 || o >= SOUND_MIXER_NRDEVICES) + return -EINVAL; + + if (!(devc->supported_devices & (1 << o)) && + !(devc->supported_rec_devices & (1 << o))) + return -EINVAL; + if (n == SOUND_MIXER_NONE) { /* Just hide this control */ ad1848_mixer_set(devc, o, 0); /* Shut up it */ devc->supported_devices &= ~(1 << o); devc->supported_rec_devices &= ~(1 << o); - return; + break; } - /* Make the mixer control identified by o to appear as n */ - if (o < 0 || o > SOUND_MIXER_NRDEVICES) - return; - if (n < 0 || n > SOUND_MIXER_NRDEVICES) - return; - if (!(devc->supported_devices & (1 << o))) - return; /* Not supported */ + /* Make the mixer control identified by o to appear as n */ + if (n < 0 || n >= SOUND_MIXER_NRDEVICES) + return -EINVAL; devc->mixer_reroute[n] = o; /* Rename the control */ - devc->supported_devices &= ~(1 << o); - devc->supported_devices |= (1 << n); + if (devc->supported_devices & (1 << o)) + devc->supported_devices |= (1 << n); if (devc->supported_rec_devices & (1 << o)) devc->supported_rec_devices |= (1 << n); + + devc->supported_devices &= ~(1 << o); devc->supported_rec_devices &= ~(1 << o); } break; } - return; + return 0; } void ad1848_unload(int io_base, int irq, int dma_playback, int dma_capture, int share_dma) @@ -1932,7 +1944,6 @@ void ad1848_unload(int io_base, int irq, int dma_playback, int dma_capture, int } else printk(KERN_ERR "ad1848: Can't find device to be unloaded. Base=%x\n", io_base); - MOD_DEC_USE_COUNT; } void adintr(int irq, void *dev_id, struct pt_regs *dummy) @@ -1965,37 +1976,22 @@ interrupt_again: /* Jump back here if int status doesn't reset */ save_flags(flags); cli(); - alt_stat = 0; - - if (devc->c930_password_port) - outb((0xe4), devc->c930_password_port); /* Password */ + /* 0xe0e is C930 address port + * 0xe0f is C930 data port + */ outb(11, 0xe0e); c930_stat = inb(0xe0f); + outb((~c930_stat), 0xe0f); - if (c930_stat & 0x04) - alt_stat |= 0x10; /* Playback intr */ - if (c930_stat & 0x08) - alt_stat |= 0x20; /* Playback intr */ restore_flags(flags); - } else if (devc->model != MD_1848) - alt_stat = ad_read(devc, 24); - - /* Acknowledge the intr before proceeding */ - if (devc->model == MD_C930) - { /* 82C930 has interrupt status register in MAD16 register MC11 */ - unsigned long flags; - - save_flags(flags); - cli(); - if (devc->c930_password_port) - outb((0xe4), devc->c930_password_port); /* Password */ - outb((11), 0xe0e); - outb((~c930_stat), 0xe0f); - restore_flags(flags); + alt_stat = (c930_stat << 2) & 0x30; } else if (devc->model != MD_1848) + { + alt_stat = ad_read(devc, 24); ad_write(devc, 24, ad_read(devc, 24) & ~alt_stat); /* Selective ack */ + } if (devc->open_mode & OPEN_READ && devc->audio_mode & PCM_ENABLE_INPUT && alt_stat & 0x20) { @@ -2550,11 +2546,10 @@ static int loaded = 0; struct address_info hw_config; - int init_module(void) { printk(KERN_INFO "ad1848/cs4248 codec driver Copyright (C) by Hannu Savolainen 1993-1996\n"); - if(io!=-1) + if(io != -1) { if(irq == -1 || dma == -1) { @@ -2581,12 +2576,5 @@ void cleanup_module(void) if(loaded) unload_ms_sound(&hw_config); } - -#else - -void export_ad1848_syms(void) -{ -} - #endif #endif diff --git a/drivers/sound/ad1848_mixer.h b/drivers/sound/ad1848_mixer.h index f6ea1c006..0cf54e710 100644 --- a/drivers/sound/ad1848_mixer.h +++ b/drivers/sound/ad1848_mixer.h @@ -1,6 +1,6 @@ /* * sound/ad1848_mixer.h - * + * * Definitions for the mixer of AD1848 and compatible codecs. */ @@ -77,7 +77,7 @@ typedef mixer_ent mixer_ents[2]; */ #define MIX_ENT(name, reg_l, pola_l, pos_l, len_l, reg_r, pola_r, pos_r, len_r, mute_bit) \ - {{reg_l, pola_l, pos_l, len_l}, {reg_r, pola_r, pos_r, len_r, mute_bit}} + {{reg_l, pola_l, pos_l, len_l, mute_bit}, {reg_r, pola_r, pos_r, len_r, mute_bit}} static mixer_ents ad1848_mix_devices[32] = { MIX_ENT(SOUND_MIXER_VOLUME, 27, 1, 0, 4, 29, 1, 0, 4, 8), @@ -88,13 +88,13 @@ MIX_ENT(SOUND_MIXER_PCM, 6, 1, 0, 6, 7, 1, 0, 6, 7), MIX_ENT(SOUND_MIXER_SPEAKER, 26, 1, 0, 4, 0, 0, 0, 0, 8), MIX_ENT(SOUND_MIXER_LINE, 18, 1, 0, 5, 19, 1, 0, 5, 7), MIX_ENT(SOUND_MIXER_MIC, 0, 0, 5, 1, 1, 0, 5, 1, 8), -MIX_ENT(SOUND_MIXER_CD, 2, 1, 0, 5, 3, 1, 0, 5, 7), +MIX_ENT(SOUND_MIXER_CD, 2, 1, 0, 5, 3, 1, 0, 5, 7), MIX_ENT(SOUND_MIXER_IMIX, 13, 1, 2, 6, 0, 0, 0, 0, 8), MIX_ENT(SOUND_MIXER_ALTPCM, 0, 0, 0, 0, 0, 0, 0, 0, 8), MIX_ENT(SOUND_MIXER_RECLEV, 0, 0, 0, 0, 0, 0, 0, 0, 8), MIX_ENT(SOUND_MIXER_IGAIN, 0, 0, 0, 4, 1, 0, 0, 4, 8), MIX_ENT(SOUND_MIXER_OGAIN, 0, 0, 0, 0, 0, 0, 0, 0, 8), -MIX_ENT(SOUND_MIXER_LINE1, 2, 1, 0, 5, 3, 1, 0, 5, 7), +MIX_ENT(SOUND_MIXER_LINE1, 2, 1, 0, 5, 3, 1, 0, 5, 7), MIX_ENT(SOUND_MIXER_LINE2, 4, 1, 0, 5, 5, 1, 0, 5, 7), MIX_ENT(SOUND_MIXER_LINE3, 18, 1, 0, 5, 19, 1, 0, 5, 7) }; @@ -108,13 +108,13 @@ MIX_ENT(SOUND_MIXER_PCM, 6, 1, 0, 6, 7, 1, 0, 6, 7), MIX_ENT(SOUND_MIXER_SPEAKER, 26, 1, 0, 4, 0, 0, 0, 0, 8), MIX_ENT(SOUND_MIXER_LINE, 18, 1, 0, 5, 19, 1, 0, 5, 7), MIX_ENT(SOUND_MIXER_MIC, 0, 0, 5, 1, 1, 0, 5, 1, 8), -MIX_ENT(SOUND_MIXER_CD, 2, 1, 0, 5, 3, 1, 0, 5, 7), +MIX_ENT(SOUND_MIXER_CD, 2, 1, 0, 5, 3, 1, 0, 5, 7), MIX_ENT(SOUND_MIXER_IMIX, 16, 1, 0, 5, 17, 1, 0, 5, 8), MIX_ENT(SOUND_MIXER_ALTPCM, 0, 0, 0, 0, 0, 0, 0, 0, 8), MIX_ENT(SOUND_MIXER_RECLEV, 0, 0, 0, 0, 0, 0, 0, 0, 8), MIX_ENT(SOUND_MIXER_IGAIN, 0, 0, 0, 4, 1, 0, 0, 4, 8), MIX_ENT(SOUND_MIXER_OGAIN, 0, 0, 0, 0, 0, 0, 0, 0, 8), -MIX_ENT(SOUND_MIXER_LINE1, 2, 1, 0, 5, 3, 1, 0, 5, 7), +MIX_ENT(SOUND_MIXER_LINE1, 2, 1, 0, 5, 3, 1, 0, 5, 7), MIX_ENT(SOUND_MIXER_LINE2, 4, 1, 0, 5, 5, 1, 0, 5, 7), MIX_ENT(SOUND_MIXER_LINE3, 18, 1, 0, 5, 19, 1, 0, 5, 7) }; @@ -125,21 +125,21 @@ MIX_ENT(SOUND_MIXER_LINE3, 18, 1, 0, 5, 19, 1, 0, 5, 7) * MIC is level of mic monitoring direct to output. Same for CD, LINE, etc. */ static mixer_ents c930_mix_devices[32] = { -MIX_ENT(SOUND_MIXER_VOLUME, 22, 1, 0, 5, 23, 1, 0, 5, 7), +MIX_ENT(SOUND_MIXER_VOLUME, 22, 1, 1, 5, 23, 1, 1, 5, 7), MIX_ENT(SOUND_MIXER_BASS, 0, 0, 0, 0, 0, 0, 0, 0, 8), MIX_ENT(SOUND_MIXER_TREBLE, 0, 0, 0, 0, 0, 0, 0, 0, 8), -MIX_ENT(SOUND_MIXER_SYNTH, 4, 1, 0, 5, 5, 1, 0, 5, 7), -MIX_ENT(SOUND_MIXER_PCM, 6, 1, 0, 6, 7, 1, 0, 6, 7), -MIX_ENT(SOUND_MIXER_SPEAKER, 22, 1, 0, 5, 23, 1, 0, 5, 8), +MIX_ENT(SOUND_MIXER_SYNTH, 4, 1, 1, 4, 5, 1, 1, 4, 7), +MIX_ENT(SOUND_MIXER_PCM, 6, 1, 0, 5, 7, 1, 0, 5, 7), +MIX_ENT(SOUND_MIXER_SPEAKER, 22, 1, 1, 5, 23, 1, 1, 5, 7), MIX_ENT(SOUND_MIXER_LINE, 18, 1, 1, 4, 19, 1, 1, 4, 7), -MIX_ENT(SOUND_MIXER_MIC, 20, 1, 0, 4, 21, 1, 0, 4, 8), -MIX_ENT(SOUND_MIXER_CD, 2, 1, 1, 4, 3, 1, 1, 4, 7), -MIX_ENT(SOUND_MIXER_IMIX, 0, 0, 0, 0, 0, 0, 0, 0, 8), +MIX_ENT(SOUND_MIXER_MIC, 20, 1, 1, 4, 21, 1, 1, 4, 7), +MIX_ENT(SOUND_MIXER_CD, 2, 1, 1, 4, 3, 1, 1, 4, 7), +MIX_ENT(SOUND_MIXER_IMIX, 0, 0, 0, 0, 0, 0, 0, 0, 8), MIX_ENT(SOUND_MIXER_ALTPCM, 0, 0, 0, 0, 0, 0, 0, 0, 8), MIX_ENT(SOUND_MIXER_RECLEV, 0, 0, 0, 0, 0, 0, 0, 0, 8), MIX_ENT(SOUND_MIXER_IGAIN, 0, 0, 0, 4, 1, 0, 0, 4, 8), MIX_ENT(SOUND_MIXER_OGAIN, 0, 0, 0, 0, 0, 0, 0, 0, 8), -MIX_ENT(SOUND_MIXER_LINE1, 2, 1, 1, 4, 3, 1, 1, 4, 7), +MIX_ENT(SOUND_MIXER_LINE1, 2, 1, 1, 4, 3, 1, 1, 4, 7), MIX_ENT(SOUND_MIXER_LINE2, 4, 1, 1, 4, 5, 1, 1, 4, 7), MIX_ENT(SOUND_MIXER_LINE3, 18, 1, 1, 4, 19, 1, 1, 4, 7) }; diff --git a/drivers/sound/adlib_card.c b/drivers/sound/adlib_card.c index 6d7dbb7b3..b9b16cd8e 100644 --- a/drivers/sound/adlib_card.c +++ b/drivers/sound/adlib_card.c @@ -2,19 +2,17 @@ * sound/adlib_card.c * * Detection routine for the AdLib card. - */ - -/* + * * Copyright (C) by Hannu Savolainen 1993-1997 * * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) * Version 2 (June 1991). See the "COPYING" file distributed with this software * for more info. */ -#include <linux/config.h> -#include <linux/module.h> +#include <linux/config.h> +#include <linux/module.h> #include "sound_config.h" #include "soundmodule.h" @@ -28,7 +26,8 @@ void attach_adlib_card(struct address_info *hw_config) int 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; } @@ -46,12 +45,14 @@ void unload_adlib(struct address_info *hw_config) int io = -1; MODULE_PARM(io, "i"); +EXPORT_NO_SYMBOLS; + struct address_info cfg; int init_module(void) { if (io == -1) { - printk("adlib: must specify I/O address.\n"); + printk(KERN_ERR "adlib: must specify I/O address.\n"); return -EINVAL; } cfg.io_base = io; diff --git a/drivers/sound/audio.c b/drivers/sound/audio.c index 9c9ccf095..905bd83e7 100644 --- a/drivers/sound/audio.c +++ b/drivers/sound/audio.c @@ -21,6 +21,7 @@ #include <linux/config.h> #include <linux/stddef.h> +#include <linux/kmod.h> #include "sound_config.h" @@ -164,8 +165,6 @@ void audio_release(int dev, struct file *file) DMAbuf_release(dev, mode); } -#if defined(NO_INLINE_ASM) || !defined(i386) - static void translate_bytes(const unsigned char *table, unsigned char *buff, int n) { unsigned long i; @@ -177,24 +176,6 @@ static void translate_bytes(const unsigned char *table, unsigned char *buff, int buff[i] = table[buff[i]]; } -#else -extern inline void -translate_bytes(const void *table, void *buff, int n) -{ - if (n > 0) - { - __asm__("cld\n" - "1:\tlodsb\n\t" - "xlatb\n\t" - "stosb\n\t" - "loop 1b\n\t": - : "b"((long) table), "c"(n), "D"((long) buff), "S"((long) buff) - : "bx", "cx", "di", "si", "ax"); - } -} - -#endif - int audio_write(int dev, struct file *file, const char *buf, int count) { int c, p, l, buf_size; @@ -827,8 +808,10 @@ int dma_ioctl(int dev, unsigned int cmd, caddr_t arg) DMAbuf_launch_output(dev, dmap_out); } audio_devs[dev]->enable_bits = bits; +#if 0 if (changed && audio_devs[dev]->d->trigger) audio_devs[dev]->d->trigger(dev, bits * audio_devs[dev]->go); +#endif restore_flags(flags); /* Falls through... */ diff --git a/drivers/sound/cs4232.c b/drivers/sound/cs4232.c index fdb5b738c..571a3372b 100644 --- a/drivers/sound/cs4232.c +++ b/drivers/sound/cs4232.c @@ -301,6 +301,8 @@ MODULE_PARM(irq,"i"); MODULE_PARM(dma,"i"); MODULE_PARM(dma2,"i"); +EXPORT_NO_SYMBOLS; + struct address_info cfg; /* diff --git a/drivers/sound/dev_table.c b/drivers/sound/dev_table.c index 7f3957bfd..155cf529d 100644 --- a/drivers/sound/dev_table.c +++ b/drivers/sound/dev_table.c @@ -18,7 +18,6 @@ #define _DEV_TABLE_C_ #include "sound_config.h" -int sb_be_quiet = 0; int softoss_dev = 0; int sound_started = 0; int sndtable_get_cardcount(void); @@ -148,6 +147,9 @@ void sound_unload_drivers(void) } } + for (i=0;i<num_audiodevs;i++) + DMAbuf_deinit(i); + if (trace_init) printk(KERN_DEBUG "Sound unload complete\n"); } @@ -418,13 +420,11 @@ int sound_install_audiodrv(int vers, char *name, struct audio_driver *driver, return -(EBUSY); } d = (struct audio_driver *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(struct audio_driver))); - sound_mem_sizes[sound_nblocks] = sizeof(struct audio_driver); if (sound_nblocks < 1024) sound_nblocks++; op = (struct audio_operations *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(struct audio_operations))); - sound_mem_sizes[sound_nblocks] = sizeof(struct audio_operations); if (sound_nblocks < 1024) sound_nblocks++; @@ -490,7 +490,6 @@ int sound_install_mixer(int vers, char *name, struct mixer_operations *driver, until you unload sound! */ op = (struct mixer_operations *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(struct mixer_operations))); - sound_mem_sizes[sound_nblocks] = sizeof(struct mixer_operations); if (sound_nblocks < 1024) sound_nblocks++; diff --git a/drivers/sound/dev_table.h b/drivers/sound/dev_table.h index 878cb2971..b6e273d40 100644 --- a/drivers/sound/dev_table.h +++ b/drivers/sound/dev_table.h @@ -23,6 +23,7 @@ */ #define SNDCARD_DESKPROXL 27 /* Compaq Deskpro XL */ +#define SNDCARD_VIDC 28 /* ARMs VIDC */ #define SNDCARD_SBPNP 29 #define SNDCARD_OPL3SA1 38 #define SNDCARD_OPL3SA1_SB 39 @@ -464,6 +465,9 @@ struct driver_info sound_drivers[] = #if defined(CONFIG_VMIDI) && defined(CONFIG_MIDI) && !defined(CONFIG_VMIDI_MODULE) {"VMIDI", 0, SNDCARD_VMIDI,"Loopback MIDI Device", attach_v_midi, probe_v_midi, unload_v_midi}, #endif +#ifdef CONFIG_VIDC_SOUND + {"VIDC", 0, SNDCARD_VIDC, "ARM VIDC 16-bit D/A", attach_vidc, probe_vidc, unload_vidc }, +#endif {NULL, 0, 0, "*?*", NULL, NULL, NULL} }; @@ -612,6 +616,9 @@ struct card_info snd_installed_cards[] = {SNDCARD_VMIDI, {0, 0, 0, -1}, SND_DEFAULT_ENABLE}, #endif +#ifdef CONFIG_VIDC_SOUND + { SNDCARD_VIDC, {0, 0, 0, 0}, SND_DEFAULT_ENABLE }, +#endif {0, {0}, 0} }; diff --git a/drivers/sound/dmabuf.c b/drivers/sound/dmabuf.c index db6a02d05..5066cfe5a 100644 --- a/drivers/sound/dmabuf.c +++ b/drivers/sound/dmabuf.c @@ -104,7 +104,7 @@ static int sound_alloc_dmap(struct dma_buffparms *dmap) dmap->raw_buf_phys = virt_to_bus(start_addr); for (i = MAP_NR(start_addr); i <= MAP_NR(end_addr); i++) - set_bit(PG_reserved, &mem_map[i].flags); + set_bit(PG_reserved, &mem_map[i].flags);; return 0; } @@ -115,6 +115,8 @@ static void sound_free_dmap(struct dma_buffparms *dmap) if (dmap->raw_buf == NULL) return; + if (dmap->mapping_flags & DMA_MAP_MAPPED) + return; /* Don't free mmapped buffer. Will use it next time */ for (sz = 0, size = PAGE_SIZE; size < dmap->buffsize; sz++, size <<= 1); start_addr = (unsigned long) dmap->raw_buf; @@ -125,8 +127,6 @@ static void sound_free_dmap(struct dma_buffparms *dmap) free_pages((unsigned long) dmap->raw_buf, sz); dmap->raw_buf = NULL; - /* Remember the buffer is deleted so we dont Oops later */ - dmap->fragment_size = 0; } @@ -206,7 +206,6 @@ static void close_dmap(struct audio_operations *adev, struct dma_buffparms *dmap dmap->dma_mode = DMODE_NONE; dmap->flags &= ~DMA_BUSY; disable_dma(dmap->dma); - sound_free_dmap(dmap); } @@ -1212,4 +1211,18 @@ unsigned int DMAbuf_poll(struct file * file, int dev, poll_table *wait) return poll_input(file, dev, wait) | poll_output(file, dev, wait); } +void DMAbuf_deinit(int dev) +{ + struct audio_operations *adev = audio_devs[dev]; + /* This routine is called when driver is being unloaded */ + if (!adev) + return; +#ifdef RUNTIME_DMA_ALLOC + sound_free_dmap(adev->dmap_out); + + if (adev->flags & DMA_DUPLEX) + sound_free_dmap(adev->dmap_in); +#endif +} + #endif diff --git a/drivers/sound/dmasound.c b/drivers/sound/dmasound.c index 0d4c73c1f..7805bed43 100644 --- a/drivers/sound/dmasound.c +++ b/drivers/sound/dmasound.c @@ -3,76 +3,76 @@ /* - OSS/Free compatible Atari TT/Falcon and Amiga DMA sound driver for Linux/m68k +OSS/Free compatible Atari TT/Falcon and Amiga DMA sound driver for Linux/m68k - (c) 1995 by Michael Schlueter & Michael Marte +(c) 1995 by Michael Schlueter & Michael Marte - Michael Schlueter (michael@duck.syd.de) did the basic structure of the VFS - interface and the u-law to signed byte conversion. +Michael Schlueter (michael@duck.syd.de) did the basic structure of the VFS +interface and the u-law to signed byte conversion. - Michael Marte (marte@informatik.uni-muenchen.de) did the sound queue, - /dev/mixer, /dev/sndstat and complemented the VFS interface. He would like - to thank: - Michael Schlueter for initial ideas and documentation on the MFP and - the DMA sound hardware. - Therapy? for their CD 'Troublegum' which really made me rock. +Michael Marte (marte@informatik.uni-muenchen.de) did the sound queue, +/dev/mixer, /dev/sndstat and complemented the VFS interface. He would like +to thank: +Michael Schlueter for initial ideas and documentation on the MFP and +the DMA sound hardware. +Therapy? for their CD 'Troublegum' which really made me rock. - /dev/sndstat is based on code by Hannu Savolainen, the author of the - VoxWare family of drivers. +/dev/sndstat is based on code by Hannu Savolainen, the author of the +VoxWare family of drivers. - This file is subject to the terms and conditions of the GNU General Public - License. See the file COPYING in the main directory of this archive - for more details. +This file is subject to the terms and conditions of the GNU General Public +License. See the file COPYING in the main directory of this archive +for more details. - History: - 1995/8/25 first release +History: +1995/8/25 first release - 1995/9/02 ++roman: fixed atari_stram_alloc() call, the timer programming - and several race conditions +1995/9/02 ++roman: fixed atari_stram_alloc() call, the timer programming + and several race conditions - 1995/9/14 ++roman: After some discussion with Michael Schlueter, revised - the interrupt disabling - Slightly speeded up U8->S8 translation by using long - operations where possible - Added 4:3 interpolation for /dev/audio +1995/9/14 ++roman: After some discussion with Michael Schlueter, revised + the interrupt disabling + Slightly speeded up U8->S8 translation by using long + operations where possible + Added 4:3 interpolation for /dev/audio - 1995/9/20 ++TeSche: Fixed a bug in sq_write and changed /dev/audio - converting to play at 12517Hz instead of 6258Hz. +1995/9/20 ++TeSche: Fixed a bug in sq_write and changed /dev/audio + converting to play at 12517Hz instead of 6258Hz. - 1995/9/23 ++TeSche: Changed sq_interrupt() and sq_play() to pre-program - the DMA for another frame while there's still one - running. This allows the IRQ response to be - arbitrarily delayed and playing will still continue. +1995/9/23 ++TeSche: Changed sq_interrupt() and sq_play() to pre-program + the DMA for another frame while there's still one + running. This allows the IRQ response to be + arbitrarily delayed and playing will still continue. - 1995/10/14 ++Guenther_Kelleter@ac3.maus.de, ++TeSche: better support for - Falcon audio (the Falcon doesn't raise an IRQ at the - end of a frame, but at the beginning instead!). uses - 'if (codec_dma)' in lots of places to simply switch - between Falcon and TT code. +1995/10/14 ++Guenther_Kelleter@ac3.maus.de, ++TeSche: better support for + Falcon audio (the Falcon doesn't raise an IRQ at the + end of a frame, but at the beginning instead!). uses + 'if (codec_dma)' in lots of places to simply switch + between Falcon and TT code. - 1995/11/06 ++TeSche: started introducing a hardware abstraction scheme - (may perhaps also serve for Amigas?), can now play - samples at almost all frequencies by means of a more - generalized expand routine, takes a good deal of care - to cut data only at sample sizes, buffer size is now - a kernel runtime option, implemented fsync() & several - minor improvements - ++Guenther: useful hints and bug fixes, cross-checked it for - Falcons +1995/11/06 ++TeSche: started introducing a hardware abstraction scheme + (may perhaps also serve for Amigas?), can now play + samples at almost all frequencies by means of a more + generalized expand routine, takes a good deal of care + to cut data only at sample sizes, buffer size is now + a kernel runtime option, implemented fsync() & several + minor improvements + ++Guenther: useful hints and bug fixes, cross-checked it for + Falcons - 1996/3/9 ++geert: support added for Amiga, A-law, 16-bit little endian. - Unification to drivers/sound/dmasound.c. +1996/3/9 ++geert: support added for Amiga, A-law, 16-bit little endian. + Unification to drivers/sound/dmasound.c. - 1996/4/6 ++Martin Mitchell: updated to 1.3 kernel. +1996/4/6 ++Martin Mitchell: updated to 1.3 kernel. - 1996/6/13 ++topi: fixed things that were broken (mainly the amiga - 14-bit routines), /dev/sndstat shows now the real - hardware frequency, the lowpass filter is disabled - by default now. +1996/6/13 ++topi: fixed things that were broken (mainly the amiga + 14-bit routines), /dev/sndstat shows now the real + hardware frequency, the lowpass filter is disabled + by default now. - 1996/9/25 ++geert: modularization +1996/9/25 ++geert: modularization - */ +*/ #include <linux/module.h> @@ -94,55 +94,54 @@ #ifdef CONFIG_ATARI #include <asm/atarihw.h> #include <asm/atariints.h> -#endif /* CONFIG_ATARI */ +#include <asm/atari_stram.h> +#endif /* CONFIG_ATARI */ #ifdef CONFIG_AMIGA #include <asm/amigahw.h> #include <asm/amigaints.h> -#endif /* CONFIG_AMIGA */ +#endif /* CONFIG_AMIGA */ #include "dmasound.h" #include <linux/soundcard.h> #ifdef MODULE -static int chrdev_registered = 0; -static int irq_installed = 0; - -#endif /* MODULE */ -static char **sound_buffers = NULL; +static int chrdev_registered = 0; +static int irq_installed = 0; +#endif /* MODULE */ +static char **sound_buffers = NULL; #ifdef CONFIG_ATARI -extern void atari_microwire_cmd(int cmd); - -#endif /* CONFIG_ATARI */ +extern void atari_microwire_cmd(int cmd); +#endif /* CONFIG_ATARI */ #ifdef CONFIG_AMIGA /* - * The minimum period for audio depends on htotal (for OCS/ECS/AGA) - * (Imported from arch/m68k/amiga/amisound.c) + * The minimum period for audio depends on htotal (for OCS/ECS/AGA) + * (Imported from arch/m68k/amiga/amisound.c) */ extern volatile u_short amiga_audio_min_period; /* - * amiga_mksound() should be able to restore the period after beeping - * (Imported from arch/m68k/amiga/amisound.c) + * amiga_mksound() should be able to restore the period after beeping + * (Imported from arch/m68k/amiga/amisound.c) */ -extern u_short amiga_audio_period; +extern u_short amiga_audio_period; /* - * Audio DMA masks + * Audio DMA masks */ #define AMI_AUDIO_OFF (DMAF_AUD0 | DMAF_AUD1 | DMAF_AUD2 | DMAF_AUD3) #define AMI_AUDIO_8 (DMAF_SETCLR | DMAF_MASTER | DMAF_AUD0 | DMAF_AUD1) #define AMI_AUDIO_14 (AMI_AUDIO_8 | DMAF_AUD2 | DMAF_AUD3) -#endif /* CONFIG_AMIGA */ +#endif /* CONFIG_AMIGA */ /*** Some declarations *******************************************************/ @@ -157,7 +156,7 @@ extern u_short amiga_audio_period; #define MIN_BUFSIZE 4 #define MAX_BUFSIZE 128 /* Limit for Amiga */ -static int catchRadius = 0, numBufs = 4, bufSize = 32; +static int catchRadius = 0, numBufs = 4, bufSize = 32; #define arraysize(x) (sizeof(x)/sizeof(*(x))) @@ -177,78 +176,76 @@ static int catchRadius = 0, numBufs = 4, bufSize = 32; /* 8 bit mu-law */ -static char ulaw2dma8[] = -{ - -126, -122, -118, -114, -110, -106, -102, -98, - -94, -90, -86, -82, -78, -74, -70, -66, - -63, -61, -59, -57, -55, -53, -51, -49, - -47, -45, -43, -41, -39, -37, -35, -33, - -31, -30, -29, -28, -27, -26, -25, -24, - -23, -22, -21, -20, -19, -18, -17, -16, - -16, -15, -15, -14, -14, -13, -13, -12, - -12, -11, -11, -10, -10, -9, -9, -8, - -8, -8, -7, -7, -7, -7, -6, -6, - -6, -6, -5, -5, -5, -5, -4, -4, - -4, -4, -4, -4, -3, -3, -3, -3, - -3, -3, -3, -3, -2, -2, -2, -2, - -2, -2, -2, -2, -2, -2, -2, -2, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 0, - 125, 121, 117, 113, 109, 105, 101, 97, - 93, 89, 85, 81, 77, 73, 69, 65, - 62, 60, 58, 56, 54, 52, 50, 48, - 46, 44, 42, 40, 38, 36, 34, 32, - 30, 29, 28, 27, 26, 25, 24, 23, - 22, 21, 20, 19, 18, 17, 16, 15, - 15, 14, 14, 13, 13, 12, 12, 11, - 11, 10, 10, 9, 9, 8, 8, 7, - 7, 7, 6, 6, 6, 6, 5, 5, - 5, 5, 4, 4, 4, 4, 3, 3, - 3, 3, 3, 3, 2, 2, 2, 2, - 2, 2, 2, 2, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 +static char ulaw2dma8[] = { + -126, -122, -118, -114, -110, -106, -102, -98, + -94, -90, -86, -82, -78, -74, -70, -66, + -63, -61, -59, -57, -55, -53, -51, -49, + -47, -45, -43, -41, -39, -37, -35, -33, + -31, -30, -29, -28, -27, -26, -25, -24, + -23, -22, -21, -20, -19, -18, -17, -16, + -16, -15, -15, -14, -14, -13, -13, -12, + -12, -11, -11, -10, -10, -9, -9, -8, + -8, -8, -7, -7, -7, -7, -6, -6, + -6, -6, -5, -5, -5, -5, -4, -4, + -4, -4, -4, -4, -3, -3, -3, -3, + -3, -3, -3, -3, -2, -2, -2, -2, + -2, -2, -2, -2, -2, -2, -2, -2, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 0, + 125, 121, 117, 113, 109, 105, 101, 97, + 93, 89, 85, 81, 77, 73, 69, 65, + 62, 60, 58, 56, 54, 52, 50, 48, + 46, 44, 42, 40, 38, 36, 34, 32, + 30, 29, 28, 27, 26, 25, 24, 23, + 22, 21, 20, 19, 18, 17, 16, 15, + 15, 14, 14, 13, 13, 12, 12, 11, + 11, 10, 10, 9, 9, 8, 8, 7, + 7, 7, 6, 6, 6, 6, 5, 5, + 5, 5, 4, 4, 4, 4, 3, 3, + 3, 3, 3, 3, 2, 2, 2, 2, + 2, 2, 2, 2, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }; /* 8 bit A-law */ -static char alaw2dma8[] = -{ - -22, -21, -24, -23, -18, -17, -20, -19, - -30, -29, -32, -31, -26, -25, -28, -27, - -11, -11, -12, -12, -9, -9, -10, -10, - -15, -15, -16, -16, -13, -13, -14, -14, - -86, -82, -94, -90, -70, -66, -78, -74, - -118, -114, -126, -122, -102, -98, -110, -106, - -43, -41, -47, -45, -35, -33, -39, -37, - -59, -57, -63, -61, -51, -49, -55, -53, - -2, -2, -2, -2, -2, -2, -2, -2, - -2, -2, -2, -2, -2, -2, -2, -2, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -6, -6, -6, -6, -5, -5, -5, -5, - -8, -8, -8, -8, -7, -7, -7, -7, - -3, -3, -3, -3, -3, -3, -3, -3, - -4, -4, -4, -4, -4, -4, -4, -4, - 21, 20, 23, 22, 17, 16, 19, 18, - 29, 28, 31, 30, 25, 24, 27, 26, - 10, 10, 11, 11, 8, 8, 9, 9, - 14, 14, 15, 15, 12, 12, 13, 13, - 86, 82, 94, 90, 70, 66, 78, 74, - 118, 114, 126, 122, 102, 98, 110, 106, - 43, 41, 47, 45, 35, 33, 39, 37, - 59, 57, 63, 61, 51, 49, 55, 53, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 5, 5, 5, 5, 4, 4, 4, 4, - 7, 7, 7, 7, 6, 6, 6, 6, - 2, 2, 2, 2, 2, 2, 2, 2, - 3, 3, 3, 3, 3, 3, 3, 3 +static char alaw2dma8[] = { + -22, -21, -24, -23, -18, -17, -20, -19, + -30, -29, -32, -31, -26, -25, -28, -27, + -11, -11, -12, -12, -9, -9, -10, -10, + -15, -15, -16, -16, -13, -13, -14, -14, + -86, -82, -94, -90, -70, -66, -78, -74, + -118, -114, -126, -122, -102, -98, -110, -106, + -43, -41, -47, -45, -35, -33, -39, -37, + -59, -57, -63, -61, -51, -49, -55, -53, + -2, -2, -2, -2, -2, -2, -2, -2, + -2, -2, -2, -2, -2, -2, -2, -2, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -6, -6, -6, -6, -5, -5, -5, -5, + -8, -8, -8, -8, -7, -7, -7, -7, + -3, -3, -3, -3, -3, -3, -3, -3, + -4, -4, -4, -4, -4, -4, -4, -4, + 21, 20, 23, 22, 17, 16, 19, 18, + 29, 28, 31, 30, 25, 24, 27, 26, + 10, 10, 11, 11, 8, 8, 9, 9, + 14, 14, 15, 15, 12, 12, 13, 13, + 86, 82, 94, 90, 70, 66, 78, 74, + 118, 114, 126, 122, 102, 98, 110, 106, + 43, 41, 47, 45, 35, 33, 39, 37, + 59, 57, 63, 61, 51, 49, 55, 53, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 4, 4, 4, 4, + 7, 7, 7, 7, 6, 6, 6, 6, + 2, 2, 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3 }; @@ -256,403 +253,381 @@ static char alaw2dma8[] = /* 16 bit mu-law */ -static char ulaw2dma16[] = -{ - -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956, - -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764, - -15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412, - -11900, -11388, -10876, -10364, -9852, -9340, -8828, -8316, - -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140, - -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092, - -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004, - -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980, - -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436, - -1372, -1308, -1244, -1180, -1116, -1052, -988, -924, - -876, -844, -812, -780, -748, -716, -684, -652, - -620, -588, -556, -524, -492, -460, -428, -396, - -372, -356, -340, -324, -308, -292, -276, -260, - -244, -228, -212, -196, -180, -164, -148, -132, - -120, -112, -104, -96, -88, -80, -72, -64, - -56, -48, -40, -32, -24, -16, -8, 0, - 32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956, - 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764, - 15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412, - 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316, - 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140, - 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092, - 3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004, - 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980, - 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436, - 1372, 1308, 1244, 1180, 1116, 1052, 988, 924, - 876, 844, 812, 780, 748, 716, 684, 652, - 620, 588, 556, 524, 492, 460, 428, 396, - 372, 356, 340, 324, 308, 292, 276, 260, - 244, 228, 212, 196, 180, 164, 148, 132, - 120, 112, 104, 96, 88, 80, 72, 64, - 56, 48, 40, 32, 24, 16, 8, 0, +static char ulaw2dma16[] = { + -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956, + -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764, + -15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412, + -11900, -11388, -10876, -10364, -9852, -9340, -8828, -8316, + -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140, + -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092, + -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004, + -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980, + -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436, + -1372, -1308, -1244, -1180, -1116, -1052, -988, -924, + -876, -844, -812, -780, -748, -716, -684, -652, + -620, -588, -556, -524, -492, -460, -428, -396, + -372, -356, -340, -324, -308, -292, -276, -260, + -244, -228, -212, -196, -180, -164, -148, -132, + -120, -112, -104, -96, -88, -80, -72, -64, + -56, -48, -40, -32, -24, -16, -8, 0, + 32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956, + 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764, + 15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412, + 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316, + 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140, + 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092, + 3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004, + 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980, + 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436, + 1372, 1308, 1244, 1180, 1116, 1052, 988, 924, + 876, 844, 812, 780, 748, 716, 684, 652, + 620, 588, 556, 524, 492, 460, 428, 396, + 372, 356, 340, 324, 308, 292, 276, 260, + 244, 228, 212, 196, 180, 164, 148, 132, + 120, 112, 104, 96, 88, 80, 72, 64, + 56, 48, 40, 32, 24, 16, 8, 0, }; /* 16 bit A-law */ -static char alaw2dma16[] = -{ - -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736, - -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784, - -2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368, - -3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392, - -22016, -20992, -24064, -23040, -17920, -16896, -19968, -18944, - -30208, -29184, -32256, -31232, -26112, -25088, -28160, -27136, - -11008, -10496, -12032, -11520, -8960, -8448, -9984, -9472, - -15104, -14592, -16128, -15616, -13056, -12544, -14080, -13568, - -344, -328, -376, -360, -280, -264, -312, -296, - -472, -456, -504, -488, -408, -392, -440, -424, - -88, -72, -120, -104, -24, -8, -56, -40, - -216, -200, -248, -232, -152, -136, -184, -168, - -1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184, - -1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696, - -688, -656, -752, -720, -560, -528, -624, -592, - -944, -912, -1008, -976, -816, -784, -880, -848, - 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736, - 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784, - 2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368, - 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392, - 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944, - 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136, - 11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472, - 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568, - 344, 328, 376, 360, 280, 264, 312, 296, - 472, 456, 504, 488, 408, 392, 440, 424, - 88, 72, 120, 104, 24, 8, 56, 40, - 216, 200, 248, 232, 152, 136, 184, 168, - 1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184, - 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696, - 688, 656, 752, 720, 560, 528, 624, 592, - 944, 912, 1008, 976, 816, 784, 880, 848, +static char alaw2dma16[] = { + -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736, + -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784, + -2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368, + -3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392, + -22016, -20992, -24064, -23040, -17920, -16896, -19968, -18944, + -30208, -29184, -32256, -31232, -26112, -25088, -28160, -27136, + -11008, -10496, -12032, -11520, -8960, -8448, -9984, -9472, + -15104, -14592, -16128, -15616, -13056, -12544, -14080, -13568, + -344, -328, -376, -360, -280, -264, -312, -296, + -472, -456, -504, -488, -408, -392, -440, -424, + -88, -72, -120, -104, -24, -8, -56, -40, + -216, -200, -248, -232, -152, -136, -184, -168, + -1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184, + -1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696, + -688, -656, -752, -720, -560, -528, -624, -592, + -944, -912, -1008, -976, -816, -784, -880, -848, + 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736, + 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784, + 2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368, + 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392, + 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944, + 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136, + 11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472, + 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568, + 344, 328, 376, 360, 280, 264, 312, 296, + 472, 456, 504, 488, 408, 392, 440, 424, + 88, 72, 120, 104, 24, 8, 56, 40, + 216, 200, 248, 232, 152, 136, 184, 168, + 1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184, + 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696, + 688, 656, 752, 720, 560, 528, 624, 592, + 944, 912, 1008, 976, 816, 784, 880, 848, }; - -#endif /* HAS_16BIT_TABLES */ +#endif /* HAS_16BIT_TABLES */ #ifdef HAS_14BIT_TABLES /* 14 bit mu-law (LSB) */ -static char alaw2dma14l[] = -{ - 33, 33, 33, 33, 33, 33, 33, 33, - 33, 33, 33, 33, 33, 33, 33, 33, - 33, 33, 33, 33, 33, 33, 33, 33, - 33, 33, 33, 33, 33, 33, 33, 33, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 49, 17, 49, 17, 49, 17, 49, 17, - 49, 17, 49, 17, 49, 17, 49, 17, - 41, 57, 9, 25, 41, 57, 9, 25, - 41, 57, 9, 25, 41, 57, 9, 25, - 37, 45, 53, 61, 5, 13, 21, 29, - 37, 45, 53, 61, 5, 13, 21, 29, - 35, 39, 43, 47, 51, 55, 59, 63, - 3, 7, 11, 15, 19, 23, 27, 31, - 34, 36, 38, 40, 42, 44, 46, 48, - 50, 52, 54, 56, 58, 60, 62, 0, - 31, 31, 31, 31, 31, 31, 31, 31, - 31, 31, 31, 31, 31, 31, 31, 31, - 31, 31, 31, 31, 31, 31, 31, 31, - 31, 31, 31, 31, 31, 31, 31, 31, - 63, 63, 63, 63, 63, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 63, 63, - 15, 47, 15, 47, 15, 47, 15, 47, - 15, 47, 15, 47, 15, 47, 15, 47, - 23, 7, 55, 39, 23, 7, 55, 39, - 23, 7, 55, 39, 23, 7, 55, 39, - 27, 19, 11, 3, 59, 51, 43, 35, - 27, 19, 11, 3, 59, 51, 43, 35, - 29, 25, 21, 17, 13, 9, 5, 1, - 61, 57, 53, 49, 45, 41, 37, 33, - 30, 28, 26, 24, 22, 20, 18, 16, - 14, 12, 10, 8, 6, 4, 2, 0 +static char alaw2dma14l[] = { + 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 49, 17, 49, 17, 49, 17, 49, 17, + 49, 17, 49, 17, 49, 17, 49, 17, + 41, 57, 9, 25, 41, 57, 9, 25, + 41, 57, 9, 25, 41, 57, 9, 25, + 37, 45, 53, 61, 5, 13, 21, 29, + 37, 45, 53, 61, 5, 13, 21, 29, + 35, 39, 43, 47, 51, 55, 59, 63, + 3, 7, 11, 15, 19, 23, 27, 31, + 34, 36, 38, 40, 42, 44, 46, 48, + 50, 52, 54, 56, 58, 60, 62, 0, + 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, + 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, + 15, 47, 15, 47, 15, 47, 15, 47, + 15, 47, 15, 47, 15, 47, 15, 47, + 23, 7, 55, 39, 23, 7, 55, 39, + 23, 7, 55, 39, 23, 7, 55, 39, + 27, 19, 11, 3, 59, 51, 43, 35, + 27, 19, 11, 3, 59, 51, 43, 35, + 29, 25, 21, 17, 13, 9, 5, 1, + 61, 57, 53, 49, 45, 41, 37, 33, + 30, 28, 26, 24, 22, 20, 18, 16, + 14, 12, 10, 8, 6, 4, 2, 0 }; /* 14 bit A-law (LSB) */ -static char alaw2dma14l[] = -{ - 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, - 16, 48, 16, 48, 16, 48, 16, 48, - 16, 48, 16, 48, 16, 48, 16, 48, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 42, 46, 34, 38, 58, 62, 50, 54, - 10, 14, 2, 6, 26, 30, 18, 22, - 42, 46, 34, 38, 58, 62, 50, 54, - 10, 14, 2, 6, 26, 30, 18, 22, - 40, 56, 8, 24, 40, 56, 8, 24, - 40, 56, 8, 24, 40, 56, 8, 24, - 20, 28, 4, 12, 52, 60, 36, 44, - 20, 28, 4, 12, 52, 60, 36, 44, - 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, - 48, 16, 48, 16, 48, 16, 48, 16, - 48, 16, 48, 16, 48, 16, 48, 16, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 22, 18, 30, 26, 6, 2, 14, 10, - 54, 50, 62, 58, 38, 34, 46, 42, - 22, 18, 30, 26, 6, 2, 14, 10, - 54, 50, 62, 58, 38, 34, 46, 42, - 24, 8, 56, 40, 24, 8, 56, 40, - 24, 8, 56, 40, 24, 8, 56, 40, - 44, 36, 60, 52, 12, 4, 28, 20, - 44, 36, 60, 52, 12, 4, 28, 20 +static char alaw2dma14l[] = { + 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, + 16, 48, 16, 48, 16, 48, 16, 48, + 16, 48, 16, 48, 16, 48, 16, 48, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 42, 46, 34, 38, 58, 62, 50, 54, + 10, 14, 2, 6, 26, 30, 18, 22, + 42, 46, 34, 38, 58, 62, 50, 54, + 10, 14, 2, 6, 26, 30, 18, 22, + 40, 56, 8, 24, 40, 56, 8, 24, + 40, 56, 8, 24, 40, 56, 8, 24, + 20, 28, 4, 12, 52, 60, 36, 44, + 20, 28, 4, 12, 52, 60, 36, 44, + 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, + 48, 16, 48, 16, 48, 16, 48, 16, + 48, 16, 48, 16, 48, 16, 48, 16, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 22, 18, 30, 26, 6, 2, 14, 10, + 54, 50, 62, 58, 38, 34, 46, 42, + 22, 18, 30, 26, 6, 2, 14, 10, + 54, 50, 62, 58, 38, 34, 46, 42, + 24, 8, 56, 40, 24, 8, 56, 40, + 24, 8, 56, 40, 24, 8, 56, 40, + 44, 36, 60, 52, 12, 4, 28, 20, + 44, 36, 60, 52, 12, 4, 28, 20 }; - -#endif /* HAS_14BIT_TABLES */ +#endif /* HAS_14BIT_TABLES */ /*** Translations ************************************************************/ #ifdef CONFIG_ATARI -static long ata_ct_law(const u_char * userPtr, unsigned long userCount, - u_char frame[], long *frameUsed, long frameLeft); -static long ata_ct_s8(const u_char * userPtr, unsigned long userCount, - u_char frame[], long *frameUsed, long frameLeft); -static long ata_ct_u8(const u_char * userPtr, unsigned long userCount, - u_char frame[], long *frameUsed, long frameLeft); -static long ata_ct_s16be(const u_char * userPtr, unsigned long userCount, - u_char frame[], long *frameUsed, long frameLeft); -static long ata_ct_u16be(const u_char * userPtr, unsigned long userCount, - u_char frame[], long *frameUsed, long frameLeft); -static long ata_ct_s16le(const u_char * userPtr, unsigned long userCount, - u_char frame[], long *frameUsed, long frameLeft); -static long ata_ct_u16le(const u_char * userPtr, unsigned long userCount, - u_char frame[], long *frameUsed, long frameLeft); -static long ata_ctx_law(const u_char * userPtr, unsigned long userCount, - u_char frame[], long *frameUsed, long frameLeft); -static long ata_ctx_s8(const u_char * userPtr, unsigned long userCount, - u_char frame[], long *frameUsed, long frameLeft); -static long ata_ctx_u8(const u_char * userPtr, unsigned long userCount, - u_char frame[], long *frameUsed, long frameLeft); -static long ata_ctx_s16be(const u_char * userPtr, unsigned long userCount, +static long ata_ct_law(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft); +static long ata_ct_s8(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft); +static long ata_ct_u8(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft); +static long ata_ct_s16be(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft); +static long ata_ct_u16be(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft); +static long ata_ct_s16le(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft); +static long ata_ct_u16le(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft); +static long ata_ctx_law(const u_char *userPtr, unsigned long userCount, u_char frame[], long *frameUsed, long frameLeft); -static long ata_ctx_u16be(const u_char * userPtr, unsigned long userCount, - u_char frame[], long *frameUsed, long frameLeft); -static long ata_ctx_s16le(const u_char * userPtr, unsigned long userCount, - u_char frame[], long *frameUsed, long frameLeft); -static long ata_ctx_u16le(const u_char * userPtr, unsigned long userCount, - u_char frame[], long *frameUsed, long frameLeft); - -#endif /* CONFIG_ATARI */ +static long ata_ctx_s8(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft); +static long ata_ctx_u8(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft); +static long ata_ctx_s16be(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft); +static long ata_ctx_u16be(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft); +static long ata_ctx_s16le(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft); +static long ata_ctx_u16le(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft); +#endif /* CONFIG_ATARI */ #ifdef CONFIG_AMIGA -static long ami_ct_law(const u_char * userPtr, unsigned long userCount, - u_char frame[], long *frameUsed, long frameLeft); -static long ami_ct_s8(const u_char * userPtr, unsigned long userCount, - u_char frame[], long *frameUsed, long frameLeft); -static long ami_ct_u8(const u_char * userPtr, unsigned long userCount, - u_char frame[], long *frameUsed, long frameLeft); -static long ami_ct_s16be(const u_char * userPtr, unsigned long userCount, - u_char frame[], long *frameUsed, long frameLeft); -static long ami_ct_u16be(const u_char * userPtr, unsigned long userCount, - u_char frame[], long *frameUsed, long frameLeft); -static long ami_ct_s16le(const u_char * userPtr, unsigned long userCount, - u_char frame[], long *frameUsed, long frameLeft); -static long ami_ct_u16le(const u_char * userPtr, unsigned long userCount, - u_char frame[], long *frameUsed, long frameLeft); - -#endif /* CONFIG_AMIGA */ +static long ami_ct_law(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft); +static long ami_ct_s8(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft); +static long ami_ct_u8(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft); +static long ami_ct_s16be(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft); +static long ami_ct_u16be(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft); +static long ami_ct_s16le(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft); +static long ami_ct_u16le(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft); +#endif /* CONFIG_AMIGA */ /*** Machine definitions *****************************************************/ -typedef struct - { - int type; - void *(*dma_alloc) (unsigned int, int); - void (*dma_free) (void *, unsigned int); - int (*irqinit) (void); +typedef struct { + int type; + void *(*dma_alloc)(unsigned int, int); + void (*dma_free)(void *, unsigned int); + int (*irqinit)(void); #ifdef MODULE - void (*irqcleanup) (void); -#endif /* MODULE */ - void (*init) (void); - void (*silence) (void); - int (*setFormat) (int); - int (*setVolume) (int); - int (*setBass) (int); - int (*setTreble) (int); - void (*play) (void); - } -MACHINE; + void (*irqcleanup)(void); +#endif /* MODULE */ + void (*init)(void); + void (*silence)(void); + int (*setFormat)(int); + int (*setVolume)(int); + int (*setBass)(int); + int (*setTreble)(int); + int (*setGain)(int); + void (*play)(void); +} MACHINE; /*** Low level stuff *********************************************************/ -typedef struct - { - int format; /* AFMT_* */ - int stereo; /* 0 = mono, 1 = stereo */ - int size; /* 8/16 bit */ - int speed; /* speed */ - } -SETTINGS; - -typedef struct - { - long (*ct_ulaw) (const u_char *, unsigned long, u_char *, long *, long); - long (*ct_alaw) (const u_char *, unsigned long, u_char *, long *, long); - long (*ct_s8) (const u_char *, unsigned long, u_char *, long *, long); - long (*ct_u8) (const u_char *, unsigned long, u_char *, long *, long); - long (*ct_s16be) (const u_char *, unsigned long, u_char *, long *, long); - long (*ct_u16be) (const u_char *, unsigned long, u_char *, long *, long); - long (*ct_s16le) (const u_char *, unsigned long, u_char *, long *, long); - long (*ct_u16le) (const u_char *, unsigned long, u_char *, long *, long); - } -TRANS; - -struct sound_settings - { - MACHINE mach; /* machine dependent things */ - SETTINGS hard; /* hardware settings */ - SETTINGS soft; /* software settings */ - SETTINGS dsp; /* /dev/dsp default settings */ - TRANS *trans; /* supported translations */ - int volume_left; /* volume (range is machine dependent) */ - int volume_right; - int bass; /* tone (range is machine dependent) */ - int treble; - int minDev; /* minor device number currently open */ +typedef struct { + int format; /* AFMT_* */ + int stereo; /* 0 = mono, 1 = stereo */ + int size; /* 8/16 bit*/ + int speed; /* speed */ +} SETTINGS; + +typedef struct { + long (*ct_ulaw)(const u_char *, unsigned long, u_char *, long *, long); + long (*ct_alaw)(const u_char *, unsigned long, u_char *, long *, long); + long (*ct_s8)(const u_char *, unsigned long, u_char *, long *, long); + long (*ct_u8)(const u_char *, unsigned long, u_char *, long *, long); + long (*ct_s16be)(const u_char *, unsigned long, u_char *, long *, long); + long (*ct_u16be)(const u_char *, unsigned long, u_char *, long *, long); + long (*ct_s16le)(const u_char *, unsigned long, u_char *, long *, long); + long (*ct_u16le)(const u_char *, unsigned long, u_char *, long *, long); +} TRANS; + +struct sound_settings { + MACHINE mach; /* machine dependent things */ + SETTINGS hard; /* hardware settings */ + SETTINGS soft; /* software settings */ + SETTINGS dsp; /* /dev/dsp default settings */ + TRANS *trans; /* supported translations */ + int volume_left; /* volume (range is machine dependent) */ + int volume_right; + int bass; /* tone (range is machine dependent) */ + int treble; + int gain; + int minDev; /* minor device number currently open */ #ifdef CONFIG_ATARI - int bal; /* balance factor for expanding (not volume!) */ - u_long data; /* data for expanding */ -#endif /* CONFIG_ATARI */ - }; + int bal; /* balance factor for expanding (not volume!) */ + u_long data; /* data for expanding */ +#endif /* CONFIG_ATARI */ +}; static struct sound_settings sound; #ifdef CONFIG_ATARI -static void *AtaAlloc(unsigned int size, int flags); -static void AtaFree(void *, unsigned int size); -static int AtaIrqInit(void); - +static void *AtaAlloc(unsigned int size, int flags); +static void AtaFree(void *, unsigned int size); +static int AtaIrqInit(void); #ifdef MODULE -static void AtaIrqCleanUp(void); - -#endif /* MODULE */ -static int AtaSetBass(int bass); -static int AtaSetTreble(int treble); -static void TTSilence(void); -static void TTInit(void); -static int TTSetFormat(int format); -static int TTSetVolume(int volume); -static void FalconSilence(void); -static void FalconInit(void); -static int FalconSetFormat(int format); -static int FalconSetVolume(int volume); -static void ata_sq_play_next_frame(int index); -static void AtaPlay(void); -static void ata_sq_interrupt(int irq, void *dummy, struct pt_regs *fp); - -#endif /* CONFIG_ATARI */ +static void AtaIrqCleanUp(void); +#endif /* MODULE */ +static int AtaSetBass(int bass); +static int AtaSetTreble(int treble); +static void TTSilence(void); +static void TTInit(void); +static int TTSetFormat(int format); +static int TTSetVolume(int volume); +static int TTSetGain(int gain); +static void FalconSilence(void); +static void FalconInit(void); +static int FalconSetFormat(int format); +static int FalconSetVolume(int volume); +static void ata_sq_play_next_frame(int index); +static void AtaPlay(void); +static void ata_sq_interrupt(int irq, void *dummy, struct pt_regs *fp); +#endif /* CONFIG_ATARI */ #ifdef CONFIG_AMIGA -static void *AmiAlloc(unsigned int size, int flags); -static void AmiFree(void *, unsigned int); -static int AmiIrqInit(void); - +static void *AmiAlloc(unsigned int size, int flags); +static void AmiFree(void *, unsigned int); +static int AmiIrqInit(void); #ifdef MODULE -static void AmiIrqCleanUp(void); - -#endif /* MODULE */ -static void AmiSilence(void); -static void AmiInit(void); -static int AmiSetFormat(int format); -static int AmiSetVolume(int volume); -static int AmiSetTreble(int treble); -static void ami_sq_play_next_frame(int index); -static void AmiPlay(void); -static void ami_sq_interrupt(int irq, void *dummy, struct pt_regs *fp); - -#endif /* CONFIG_AMIGA */ +static void AmiIrqCleanUp(void); +#endif /* MODULE */ +static void AmiSilence(void); +static void AmiInit(void); +static int AmiSetFormat(int format); +static int AmiSetVolume(int volume); +static int AmiSetTreble(int treble); +static void ami_sq_play_next_frame(int index); +static void AmiPlay(void); +static void ami_sq_interrupt(int irq, void *dummy, struct pt_regs *fp); +#endif /* CONFIG_AMIGA */ /*** Mid level stuff *********************************************************/ -static void sound_silence(void); -static void sound_init(void); -static int sound_set_format(int format); -static int sound_set_speed(int speed); -static int sound_set_stereo(int stereo); -static int sound_set_volume(int volume); - +static void sound_silence(void); +static void sound_init(void); +static int sound_set_format(int format); +static int sound_set_speed(int speed); +static int sound_set_stereo(int stereo); +static int sound_set_volume(int volume); #ifdef CONFIG_ATARI -static int sound_set_bass(int bass); - -#endif /* CONFIG_ATARI */ -static int sound_set_treble(int treble); -static long sound_copy_translate(const u_char * userPtr, - unsigned long userCount, - u_char frame[], long *frameUsed, - long frameLeft); +static int sound_set_bass(int bass); +#endif /* CONFIG_ATARI */ +static int sound_set_treble(int treble); +static long sound_copy_translate(const u_char *userPtr, + unsigned long userCount, + u_char frame[], long *frameUsed, + long frameLeft); /* * /dev/mixer abstraction */ -struct sound_mixer - { - int busy; - }; +struct sound_mixer { + int busy; +}; static struct sound_mixer mixer; -static void mixer_init(void); -static int mixer_open(int open_mode); -static int mixer_release(void); -static int mixer_ioctl(struct inode *inode, struct file *file, u_int cmd, - u_long arg); +static void mixer_init(void); +static int mixer_open(int open_mode); +static int mixer_release(void); +static int mixer_ioctl(struct inode *inode, struct file *file, u_int cmd, + u_long arg); /* * Sound queue stuff, the heart of the driver */ -struct sound_queue - { - int max_count, block_size; - char **buffers; - - /* it shouldn't be necessary to declare any of these volatile */ - int front, rear, count; - int rear_size; - /* - * The use of the playing field depends on the hardware - * - * Atari: The number of frames that are loaded/playing - * - * Amiga: Bit 0 is set: a frame is loaded - * Bit 1 is set: a frame is playing - */ - int playing; - struct wait_queue *write_queue, *open_queue, *sync_queue; - int open_mode; - int busy, syncing; +struct sound_queue { + int max_count, block_size; + char **buffers; + + /* it shouldn't be necessary to declare any of these volatile */ + int front, rear, count; + int rear_size; + /* + * The use of the playing field depends on the hardware + * + * Atari: The number of frames that are loaded/playing + * + * Amiga: Bit 0 is set: a frame is loaded + * Bit 1 is set: a frame is playing + */ + int playing; + struct wait_queue *write_queue, *open_queue, *sync_queue; + int open_mode; + int busy, syncing; #ifdef CONFIG_ATARI - int ignore_int; /* ++TeSche: used for Falcon */ -#endif /* CONFIG_ATARI */ + int ignore_int; /* ++TeSche: used for Falcon */ +#endif /* CONFIG_ATARI */ #ifdef CONFIG_AMIGA - int block_size_half, block_size_quarter; -#endif /* CONFIG_AMIGA */ - }; + int block_size_half, block_size_quarter; +#endif /* CONFIG_AMIGA */ +}; static struct sound_queue sq; @@ -666,72 +641,69 @@ static struct sound_queue sq; interruptible_sleep_on(&queue); #define WAKE_UP(queue) (wake_up_interruptible(&queue)) -static void sq_init(int numBufs, int bufSize, char **buffers); -static void sq_play(void); -static long sq_write(const char *src, unsigned long uLeft); -static int sq_open(int open_mode); -static void sq_reset(void); -static int sq_sync(void); -static int sq_release(void); +static void sq_init(int numBufs, int bufSize, char **buffers); +static void sq_play(void); +static long sq_write(const char *src, unsigned long uLeft); +static int sq_open(int open_mode); +static void sq_reset(void); +static int sq_sync(void); +static int sq_release(void); /* * /dev/sndstat */ -struct sound_state - { - int busy; - char buf[512]; - int len, ptr; - }; +struct sound_state { + int busy; + char buf[512]; + int len, ptr; +}; static struct sound_state state; -static void state_init(void); -static int state_open(int open_mode); -static int state_release(void); -static long state_read(char *dest, unsigned long count); +static void state_init(void); +static int state_open(int open_mode); +static int state_release(void); +static long state_read(char *dest, unsigned long count); /*** High level stuff ********************************************************/ -static int sound_open(struct inode *inode, struct file *file); -static int sound_fsync(struct inode *inode, struct file *filp); -static void sound_release(struct inode *inode, struct file *file); -static long long sound_lseek(struct inode *inode, struct file *file, - long long offset, int orig); -static long sound_read(struct inode *inode, struct file *file, char *buf, - unsigned long count); -static long sound_write(struct inode *inode, struct file *file, - const char *buf, unsigned long count); -static inline int -ioctl_return(int *addr, int value) +static int sound_open(struct inode *inode, struct file *file); +static int sound_fsync(struct file *filp, struct dentry *dentry); +static int sound_release(struct inode *inode, struct file *file); +static long long sound_lseek(struct file *file, long long offset, int orig); +static ssize_t sound_read(struct file *file, char *buf, size_t count, + loff_t *ppos); +static ssize_t sound_write(struct file *file, const char *buf, size_t count, + loff_t *ppos); +static inline int ioctl_return(int *addr, int value) { - if (value < 0) - return (value); + if (value < 0) + return(value); - return put_user(value, addr); + return put_user(value, addr); } -static int unknown_minor_dev(char *fname, int dev); -static int sound_ioctl(struct inode *inode, struct file *file, u_int cmd, - u_long arg); +static int unknown_minor_dev(char *fname, int dev); +static int sound_ioctl(struct inode *inode, struct file *file, u_int cmd, + u_long arg); /*** Config & Setup **********************************************************/ -void soundcard_init(void); -void dmasound_setup(char *str, int *ints); -void sound_setup(char *str, int *ints); /* ++Martin: stub for now */ +void soundcard_init(void); +void dmasound_setup(char *str, int *ints); +void sound_setup(char *str, int *ints); /* ++Martin: stub for now */ /*** Translations ************************************************************/ /* ++TeSche: radically changed for new expanding purposes... - + * * These two routines now deal with copying/expanding/translating the samples * from user space into our buffer at the right frequency. They take care about * how much data there's actually to read, how much buffer space there is and @@ -755,1014 +727,849 @@ void sound_setup(char *str, int *ints); /* ++Martin: stub for now */ */ #ifdef CONFIG_ATARI -static long -ata_ct_law(const u_char * userPtr, unsigned long userCount, - u_char frame[], long *frameUsed, long frameLeft) -{ - char *table = sound.soft.format == AFMT_MU_LAW ? ulaw2dma8 : alaw2dma8; - long count, used; - u_char *p = &frame[*frameUsed]; - - count = min(userCount, frameLeft); - if (sound.soft.stereo) - count &= ~1; - used = count; - while (count > 0) - { - u_char data; - - get_user(data, userPtr++); - *p++ = table[data]; - count--; - } - *frameUsed += used; - return (used); -} - - -static long -ata_ct_s8(const u_char * userPtr, unsigned long userCount, - u_char frame[], long *frameUsed, long frameLeft) -{ - long count, used; - void *p = &frame[*frameUsed]; - - count = min(userCount, frameLeft); - if (sound.soft.stereo) - count &= ~1; - used = count; - copy_from_user(p, userPtr, count); - *frameUsed += used; - return (used); -} - - -static long -ata_ct_u8(const u_char * userPtr, unsigned long userCount, - u_char frame[], long *frameUsed, long frameLeft) -{ - long count, used; - - if (!sound.soft.stereo) - { - u_char *p = &frame[*frameUsed]; - - count = min(userCount, frameLeft); - used = count; - while (count > 0) - { - u_char data; - - get_user(data, userPtr++); - *p++ = data ^ 0x80; - count--; - } - } else - { - u_short *p = (u_short *) & frame[*frameUsed]; - - count = min(userCount, frameLeft) >> 1; - used = count * 2; - while (count > 0) - { - u_short data; - - get_user(data, ((u_short *) userPtr)++); - *p++ = data ^ 0x8080; - count--; - } - } - *frameUsed += used; - return (used); -} - - -static long -ata_ct_s16be(const u_char * userPtr, unsigned long userCount, - u_char frame[], long *frameUsed, long frameLeft) -{ - long count, used; - u_long data; - - if (!sound.soft.stereo) - { - u_short *p = (u_short *) & frame[*frameUsed]; - - count = min(userCount, frameLeft) >> 1; - used = count * 2; - while (count > 0) - { - get_user(data, ((u_short *) userPtr)++); - *p++ = data; - *p++ = data; - count--; - } - *frameUsed += used * 2; - } else - { - void *p = (u_short *) & frame[*frameUsed]; - - count = min(userCount, frameLeft) & ~3; - used = count; - copy_from_user(p, userPtr, count); - *frameUsed += used; - } - return (used); -} - - -static long -ata_ct_u16be(const u_char * userPtr, unsigned long userCount, - u_char frame[], long *frameUsed, long frameLeft) -{ - long count, used; - u_long data; - - if (!sound.soft.stereo) - { - u_short *p = (u_short *) & frame[*frameUsed]; - - count = min(userCount, frameLeft) >> 1; - used = count * 2; - while (count > 0) - { - get_user(data, ((u_short *) userPtr)++); - data ^= 0x8000; - *p++ = data; - *p++ = data; - count--; - } - *frameUsed += used * 2; - } else - { - u_long *p = (u_long *) & frame[*frameUsed]; - - count = min(userCount, frameLeft) >> 2; - used = count * 4; - while (count > 0) - { - get_user(data, ((u_int *) userPtr)++); - *p++ = data ^ 0x80008000; - count--; - } - *frameUsed += used; - } - return (used); -} - - -static long -ata_ct_s16le(const u_char * userPtr, unsigned long userCount, - u_char frame[], long *frameUsed, long frameLeft) -{ - long count, used; - u_long data; - - count = frameLeft; - if (!sound.soft.stereo) - { - u_short *p = (u_short *) & frame[*frameUsed]; - - count = min(userCount, frameLeft) >> 1; - used = count * 2; - while (count > 0) - { - get_user(data, ((u_short *) userPtr)++); - data = le2be16(data); - *p++ = data; - *p++ = data; - count--; - } - *frameUsed += used * 2; - } else - { - u_long *p = (u_long *) & frame[*frameUsed]; - - count = min(userCount, frameLeft) >> 2; - used = count * 4; - while (count > 0) - { - get_user(data, ((u_int *) userPtr)++); - data = le2be16dbl(data); - *p++ = data; - count--; - } - *frameUsed += used; - } - return (used); -} - - -static long -ata_ct_u16le(const u_char * userPtr, unsigned long userCount, - u_char frame[], long *frameUsed, long frameLeft) -{ - long count, used; - u_long data; - - count = frameLeft; - if (!sound.soft.stereo) - { - u_short *p = (u_short *) & frame[*frameUsed]; - - count = min(userCount, frameLeft) >> 1; - used = count * 2; - while (count > 0) - { - get_user(data, ((u_short *) userPtr)++); - data = le2be16(data) ^ 0x8000; - *p++ = data; - *p++ = data; - } - *frameUsed += used * 2; - } else - { - u_long *p = (u_long *) & frame[*frameUsed]; - - count = min(userCount, frameLeft) >> 2; - used = count; - while (count > 0) - { - get_user(data, ((u_int *) userPtr)++); - data = le2be16dbl(data) ^ 0x80008000; - *p++ = data; - count--; - } - *frameUsed += used; - } - return (used); -} - - -static long -ata_ctx_law(const u_char * userPtr, unsigned long userCount, - u_char frame[], long *frameUsed, long frameLeft) -{ - char *table = sound.soft.format == AFMT_MU_LAW ? ulaw2dma8 : alaw2dma8; - - /* this should help gcc to stuff everything into registers */ - u_long data = sound.data; - long bal = sound.bal; - long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; - long used, usedf; - - used = userCount; - usedf = frameLeft; - if (!sound.soft.stereo) - { - u_char *p = &frame[*frameUsed]; - - while (frameLeft) - { - u_char c; - - if (bal < 0) - { - if (!userCount) - break; - get_user(c, userPtr++); - data = table[c]; - userCount--; - bal += hSpeed; - } - *p++ = data; - frameLeft--; - bal -= sSpeed; - } - } else - { - u_short *p = (u_short *) & frame[*frameUsed]; - - while (frameLeft >= 2) - { - u_char c; - - if (bal < 0) - { - if (userCount < 2) - break; - get_user(c, userPtr++); - data = table[c] << 8; - get_user(c, userPtr++); - data |= table[c]; - userCount -= 2; - bal += hSpeed; - } - *p++ = data; - frameLeft -= 2; - bal -= sSpeed; - } - } - sound.bal = bal; - sound.data = data; - used -= userCount; - *frameUsed += usedf - frameLeft; - return (used); -} - - -static long -ata_ctx_s8(const u_char * userPtr, unsigned long userCount, - u_char frame[], long *frameUsed, long frameLeft) +static long ata_ct_law(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft) { - /* this should help gcc to stuff everything into registers */ - u_long data = sound.data; - long bal = sound.bal; - long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; - long used, usedf; - - used = userCount; - usedf = frameLeft; - if (!sound.soft.stereo) - { - u_char *p = &frame[*frameUsed]; - - while (frameLeft) - { - if (bal < 0) - { - if (!userCount) - break; - get_user(data, userPtr++); - userCount--; - bal += hSpeed; - } - *p++ = data; - frameLeft--; - bal -= sSpeed; - } - } else - { - u_short *p = (u_short *) & frame[*frameUsed]; + char *table = sound.soft.format == AFMT_MU_LAW ? ulaw2dma8 : alaw2dma8; + long count, used; + u_char *p = &frame[*frameUsed]; - while (frameLeft >= 2) - { - if (bal < 0) - { - if (userCount < 2) - break; - get_user(data, ((u_short *) userPtr)++); - userCount -= 2; - bal += hSpeed; - } - *p++ = data; - frameLeft -= 2; - bal -= sSpeed; - } - } - sound.bal = bal; - sound.data = data; - used -= userCount; - *frameUsed += usedf - frameLeft; - return (used); + count = min(userCount, frameLeft); + if (sound.soft.stereo) + count &= ~1; + used = count; + while (count > 0) { + u_char data; + get_user(data, userPtr++); + *p++ = table[data]; + count--; + } + *frameUsed += used; + return(used); } -static long -ata_ctx_u8(const u_char * userPtr, unsigned long userCount, - u_char frame[], long *frameUsed, long frameLeft) +static long ata_ct_s8(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft) { - /* this should help gcc to stuff everything into registers */ - u_long data = sound.data; - long bal = sound.bal; - long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; - long used, usedf; + long count, used; + void *p = &frame[*frameUsed]; - used = userCount; - usedf = frameLeft; - if (!sound.soft.stereo) - { - u_char *p = &frame[*frameUsed]; - - while (frameLeft) - { - if (bal < 0) - { - if (!userCount) - break; - get_user(data, userPtr++); - data ^= 0x80; - userCount--; - bal += hSpeed; - } - *p++ = data; - frameLeft--; - bal -= sSpeed; - } - } else - { - u_short *p = (u_short *) & frame[*frameUsed]; - - while (frameLeft >= 2) - { - if (bal < 0) - { - if (userCount < 2) - break; - get_user(data, ((u_short *) userPtr)++); - data ^= 0x8080; - userCount -= 2; - bal += hSpeed; - } - *p++ = data; - frameLeft -= 2; - bal -= sSpeed; - } - } - sound.bal = bal; - sound.data = data; - used -= userCount; - *frameUsed += usedf - frameLeft; - return (used); + count = min(userCount, frameLeft); + if (sound.soft.stereo) + count &= ~1; + used = count; + copy_from_user(p, userPtr, count); + *frameUsed += used; + return(used); } -static long -ata_ctx_s16be(const u_char * userPtr, unsigned long userCount, - u_char frame[], long *frameUsed, long frameLeft) +static long ata_ct_u8(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft) { - /* this should help gcc to stuff everything into registers */ - u_long data = sound.data; - long bal = sound.bal; - long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; - long used, usedf; - - used = userCount; - usedf = frameLeft; - if (!sound.soft.stereo) - { - u_short *p = (u_short *) & frame[*frameUsed]; + long count, used; - while (frameLeft >= 4) - { - if (bal < 0) - { - if (userCount < 2) - break; - get_user(data, ((u_short *) userPtr)++); - userCount -= 2; - bal += hSpeed; - } - *p++ = data; - *p++ = data; - frameLeft -= 4; - bal -= sSpeed; - } - } else - { - u_long *p = (u_long *) & frame[*frameUsed]; - - while (frameLeft >= 4) - { - if (bal < 0) - { - if (userCount < 4) - break; - get_user(data, ((u_int *) userPtr)++); - userCount -= 4; - bal += hSpeed; - } - *p++ = data; - frameLeft -= 4; - bal -= sSpeed; - } - } - sound.bal = bal; - sound.data = data; - used -= userCount; - *frameUsed += usedf - frameLeft; - return (used); -} - - -static long -ata_ctx_u16be(const u_char * userPtr, unsigned long userCount, - u_char frame[], long *frameUsed, long frameLeft) -{ - /* this should help gcc to stuff everything into registers */ - u_long data = sound.data; - long bal = sound.bal; - long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; - long used, usedf; - - used = userCount; - usedf = frameLeft; - if (!sound.soft.stereo) - { - u_short *p = (u_short *) & frame[*frameUsed]; - - while (frameLeft >= 4) - { - if (bal < 0) - { - if (userCount < 2) - break; - get_user(data, ((u_short *) userPtr)++); - data ^= 0x8000; - userCount -= 2; - bal += hSpeed; - } - *p++ = data; - *p++ = data; - frameLeft -= 4; - bal -= sSpeed; - } - } else - { - u_long *p = (u_long *) & frame[*frameUsed]; - - while (frameLeft >= 4) - { - if (bal < 0) - { - if (userCount < 4) - break; - get_user(data, ((u_int *) userPtr)++); - data ^= 0x80008000; - userCount -= 4; - bal += hSpeed; - } - *p++ = data; - frameLeft -= 4; - bal -= sSpeed; - } - } - sound.bal = bal; - sound.data = data; - used -= userCount; - *frameUsed += usedf - frameLeft; - return (used); + if (!sound.soft.stereo) { + u_char *p = &frame[*frameUsed]; + count = min(userCount, frameLeft); + used = count; + while (count > 0) { + u_char data; + get_user(data, userPtr++); + *p++ = data ^ 0x80; + count--; + } + } else { + u_short *p = (u_short *)&frame[*frameUsed]; + count = min(userCount, frameLeft)>>1; + used = count*2; + while (count > 0) { + u_short data; + get_user(data, ((u_short *)userPtr)++); + *p++ = data ^ 0x8080; + count--; + } + } + *frameUsed += used; + return(used); } -static long -ata_ctx_s16le(const u_char * userPtr, unsigned long userCount, - u_char frame[], long *frameUsed, long frameLeft) +static long ata_ct_s16be(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft) { - /* this should help gcc to stuff everything into registers */ - u_long data = sound.data; - long bal = sound.bal; - long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; - long used, usedf; - - used = userCount; - usedf = frameLeft; - if (!sound.soft.stereo) - { - u_short *p = (u_short *) & frame[*frameUsed]; - - while (frameLeft >= 4) - { - if (bal < 0) - { - if (userCount < 2) - break; - get_user(data, ((u_short *) userPtr)++); - data = le2be16(data); - userCount -= 2; - bal += hSpeed; - } - *p++ = data; - *p++ = data; - frameLeft -= 4; - bal -= sSpeed; - } - } else - { - u_long *p = (u_long *) & frame[*frameUsed]; + long count, used; + u_long data; - while (frameLeft >= 4) - { - if (bal < 0) - { - if (userCount < 4) - break; - get_user(data, ((u_int *) userPtr)++); - data = le2be16dbl(data); - userCount -= 4; - bal += hSpeed; - } - *p++ = data; - frameLeft -= 4; - bal -= sSpeed; - } - } - sound.bal = bal; - sound.data = data; - used -= userCount; - *frameUsed += usedf - frameLeft; - return (used); + if (!sound.soft.stereo) { + u_short *p = (u_short *)&frame[*frameUsed]; + count = min(userCount, frameLeft)>>1; + used = count*2; + while (count > 0) { + get_user(data, ((u_short *)userPtr)++); + *p++ = data; + *p++ = data; + count--; + } + *frameUsed += used*2; + } else { + void *p = (u_short *)&frame[*frameUsed]; + count = min(userCount, frameLeft) & ~3; + used = count; + copy_from_user(p, userPtr, count); + *frameUsed += used; + } + return(used); } -static long -ata_ctx_u16le(const u_char * userPtr, unsigned long userCount, - u_char frame[], long *frameUsed, long frameLeft) +static long ata_ct_u16be(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft) { - /* this should help gcc to stuff everything into registers */ - u_long data = sound.data; - long bal = sound.bal; - long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; - long used, usedf; - - used = userCount; - usedf = frameLeft; - if (!sound.soft.stereo) - { - u_short *p = (u_short *) & frame[*frameUsed]; - - while (frameLeft >= 4) - { - if (bal < 0) - { - if (userCount < 2) - break; - get_user(data, ((u_short *) userPtr)++); - data = le2be16(data) ^ 0x8000; - userCount -= 2; - bal += hSpeed; - } - *p++ = data; - *p++ = data; - frameLeft -= 4; - bal -= sSpeed; - } - } else - { - u_long *p = (u_long *) & frame[*frameUsed]; + long count, used; + u_long data; - while (frameLeft >= 4) - { - if (bal < 0) - { - if (userCount < 4) - break; - get_user(data, ((u_int *) userPtr)++); - data = le2be16dbl(data) ^ 0x80008000; - userCount -= 4; - bal += hSpeed; - } - *p++ = data; - frameLeft -= 4; - bal -= sSpeed; - } - } - sound.bal = bal; - sound.data = data; - used -= userCount; - *frameUsed += usedf - frameLeft; - return (used); + if (!sound.soft.stereo) { + u_short *p = (u_short *)&frame[*frameUsed]; + count = min(userCount, frameLeft)>>1; + used = count*2; + while (count > 0) { + get_user(data, ((u_short *)userPtr)++); + data ^= 0x8000; + *p++ = data; + *p++ = data; + count--; + } + *frameUsed += used*2; + } else { + u_long *p = (u_long *)&frame[*frameUsed]; + count = min(userCount, frameLeft)>>2; + used = count*4; + while (count > 0) { + get_user(data, ((u_int *)userPtr)++); + *p++ = data ^ 0x80008000; + count--; + } + *frameUsed += used; + } + return(used); } -#endif /* CONFIG_ATARI */ -#ifdef CONFIG_AMIGA -static long -ami_ct_law(const u_char * userPtr, unsigned long userCount, - u_char frame[], long *frameUsed, long frameLeft) +static long ata_ct_s16le(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft) { - char *table = sound.soft.format == AFMT_MU_LAW ? ulaw2dma8 : alaw2dma8; - long count, used; - - if (!sound.soft.stereo) - { - u_char *p = &frame[*frameUsed]; - - count = min(userCount, frameLeft) & ~1; - used = count; - while (count > 0) - { - u_char data; + long count, used; + u_long data; - get_user(data, userPtr++); - *p++ = table[data]; - count--; - } - } else - { - u_char *left = &frame[*frameUsed >> 1]; - u_char *right = left + sq.block_size_half; - - count = min(userCount, frameLeft) >> 1 & ~1; - used = count * 2; - while (count > 0) - { - u_char data; - - get_user(data, userPtr++); - *left++ = table[data]; - get_user(data, userPtr++); - *right++ = table[data]; - count--; - } - } + count = frameLeft; + if (!sound.soft.stereo) { + u_short *p = (u_short *)&frame[*frameUsed]; + count = min(userCount, frameLeft)>>1; + used = count*2; + while (count > 0) { + get_user(data, ((u_short *)userPtr)++); + data = le2be16(data); + *p++ = data; + *p++ = data; + count--; + } + *frameUsed += used*2; + } else { + u_long *p = (u_long *)&frame[*frameUsed]; + count = min(userCount, frameLeft)>>2; + used = count*4; + while (count > 0) { + get_user(data, ((u_int *)userPtr)++); + data = le2be16dbl(data); + *p++ = data; + count--; + } *frameUsed += used; - return (used); + } + return(used); } -static long -ami_ct_s8(const u_char * userPtr, unsigned long userCount, - u_char frame[], long *frameUsed, long frameLeft) +static long ata_ct_u16le(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft) { - long count, used; + long count, used; + u_long data; - if (!sound.soft.stereo) - { - void *p = &frame[*frameUsed]; - - count = min(userCount, frameLeft) & ~1; - used = count; - copy_from_user(p, userPtr, count); - } else - { - u_char *left = &frame[*frameUsed >> 1]; - u_char *right = left + sq.block_size_half; - - count = min(userCount, frameLeft) >> 1 & ~1; - used = count * 2; - while (count > 0) - { - get_user(*left++, userPtr++); - get_user(*right++, userPtr++); - count--; - } - } + count = frameLeft; + if (!sound.soft.stereo) { + u_short *p = (u_short *)&frame[*frameUsed]; + count = min(userCount, frameLeft)>>1; + used = count*2; + while (count > 0) { + get_user(data, ((u_short *)userPtr)++); + data = le2be16(data) ^ 0x8000; + *p++ = data; + *p++ = data; + } + *frameUsed += used*2; + } else { + u_long *p = (u_long *)&frame[*frameUsed]; + count = min(userCount, frameLeft)>>2; + used = count; + while (count > 0) { + get_user(data, ((u_int *)userPtr)++); + data = le2be16dbl(data) ^ 0x80008000; + *p++ = data; + count--; + } *frameUsed += used; - return (used); + } + return(used); +} + + +static long ata_ctx_law(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft) +{ + char *table = sound.soft.format == AFMT_MU_LAW ? ulaw2dma8 : alaw2dma8; + /* this should help gcc to stuff everything into registers */ + u_long data = sound.data; + long bal = sound.bal; + long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; + long used, usedf; + + used = userCount; + usedf = frameLeft; + if (!sound.soft.stereo) { + u_char *p = &frame[*frameUsed]; + while (frameLeft) { + u_char c; + if (bal < 0) { + if (!userCount) + break; + get_user(c, userPtr++); + data = table[c]; + userCount--; + bal += hSpeed; + } + *p++ = data; + frameLeft--; + bal -= sSpeed; + } + } else { + u_short *p = (u_short *)&frame[*frameUsed]; + while (frameLeft >= 2) { + u_char c; + if (bal < 0) { + if (userCount < 2) + break; + get_user(c, userPtr++); + data = table[c] << 8; + get_user(c, userPtr++); + data |= table[c]; + userCount -= 2; + bal += hSpeed; + } + *p++ = data; + frameLeft -= 2; + bal -= sSpeed; + } + } + sound.bal = bal; + sound.data = data; + used -= userCount; + *frameUsed += usedf-frameLeft; + return(used); +} + + +static long ata_ctx_s8(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft) +{ + /* this should help gcc to stuff everything into registers */ + u_long data = sound.data; + long bal = sound.bal; + long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; + long used, usedf; + + used = userCount; + usedf = frameLeft; + if (!sound.soft.stereo) { + u_char *p = &frame[*frameUsed]; + while (frameLeft) { + if (bal < 0) { + if (!userCount) + break; + get_user(data, userPtr++); + userCount--; + bal += hSpeed; + } + *p++ = data; + frameLeft--; + bal -= sSpeed; + } + } else { + u_short *p = (u_short *)&frame[*frameUsed]; + while (frameLeft >= 2) { + if (bal < 0) { + if (userCount < 2) + break; + get_user(data, ((u_short *)userPtr)++); + userCount -= 2; + bal += hSpeed; + } + *p++ = data; + frameLeft -= 2; + bal -= sSpeed; + } + } + sound.bal = bal; + sound.data = data; + used -= userCount; + *frameUsed += usedf-frameLeft; + return(used); +} + + +static long ata_ctx_u8(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft) +{ + /* this should help gcc to stuff everything into registers */ + u_long data = sound.data; + long bal = sound.bal; + long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; + long used, usedf; + + used = userCount; + usedf = frameLeft; + if (!sound.soft.stereo) { + u_char *p = &frame[*frameUsed]; + while (frameLeft) { + if (bal < 0) { + if (!userCount) + break; + get_user(data, userPtr++); + data ^= 0x80; + userCount--; + bal += hSpeed; + } + *p++ = data; + frameLeft--; + bal -= sSpeed; + } + } else { + u_short *p = (u_short *)&frame[*frameUsed]; + while (frameLeft >= 2) { + if (bal < 0) { + if (userCount < 2) + break; + get_user(data, ((u_short *)userPtr)++); + data ^= 0x8080; + userCount -= 2; + bal += hSpeed; + } + *p++ = data; + frameLeft -= 2; + bal -= sSpeed; + } + } + sound.bal = bal; + sound.data = data; + used -= userCount; + *frameUsed += usedf-frameLeft; + return(used); +} + + +static long ata_ctx_s16be(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft) +{ + /* this should help gcc to stuff everything into registers */ + u_long data = sound.data; + long bal = sound.bal; + long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; + long used, usedf; + + used = userCount; + usedf = frameLeft; + if (!sound.soft.stereo) { + u_short *p = (u_short *)&frame[*frameUsed]; + while (frameLeft >= 4) { + if (bal < 0) { + if (userCount < 2) + break; + get_user(data, ((u_short *)userPtr)++); + userCount -= 2; + bal += hSpeed; + } + *p++ = data; + *p++ = data; + frameLeft -= 4; + bal -= sSpeed; + } + } else { + u_long *p = (u_long *)&frame[*frameUsed]; + while (frameLeft >= 4) { + if (bal < 0) { + if (userCount < 4) + break; + get_user(data, ((u_int *)userPtr)++); + userCount -= 4; + bal += hSpeed; + } + *p++ = data; + frameLeft -= 4; + bal -= sSpeed; + } + } + sound.bal = bal; + sound.data = data; + used -= userCount; + *frameUsed += usedf-frameLeft; + return(used); +} + + +static long ata_ctx_u16be(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft) +{ + /* this should help gcc to stuff everything into registers */ + u_long data = sound.data; + long bal = sound.bal; + long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; + long used, usedf; + + used = userCount; + usedf = frameLeft; + if (!sound.soft.stereo) { + u_short *p = (u_short *)&frame[*frameUsed]; + while (frameLeft >= 4) { + if (bal < 0) { + if (userCount < 2) + break; + get_user(data, ((u_short *)userPtr)++); + data ^= 0x8000; + userCount -= 2; + bal += hSpeed; + } + *p++ = data; + *p++ = data; + frameLeft -= 4; + bal -= sSpeed; + } + } else { + u_long *p = (u_long *)&frame[*frameUsed]; + while (frameLeft >= 4) { + if (bal < 0) { + if (userCount < 4) + break; + get_user(data, ((u_int *)userPtr)++); + data ^= 0x80008000; + userCount -= 4; + bal += hSpeed; + } + *p++ = data; + frameLeft -= 4; + bal -= sSpeed; + } + } + sound.bal = bal; + sound.data = data; + used -= userCount; + *frameUsed += usedf-frameLeft; + return(used); +} + + +static long ata_ctx_s16le(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft) +{ + /* this should help gcc to stuff everything into registers */ + u_long data = sound.data; + long bal = sound.bal; + long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; + long used, usedf; + + used = userCount; + usedf = frameLeft; + if (!sound.soft.stereo) { + u_short *p = (u_short *)&frame[*frameUsed]; + while (frameLeft >= 4) { + if (bal < 0) { + if (userCount < 2) + break; + get_user(data, ((u_short *)userPtr)++); + data = le2be16(data); + userCount -= 2; + bal += hSpeed; + } + *p++ = data; + *p++ = data; + frameLeft -= 4; + bal -= sSpeed; + } + } else { + u_long *p = (u_long *)&frame[*frameUsed]; + while (frameLeft >= 4) { + if (bal < 0) { + if (userCount < 4) + break; + get_user(data, ((u_int *)userPtr)++); + data = le2be16dbl(data); + userCount -= 4; + bal += hSpeed; + } + *p++ = data; + frameLeft -= 4; + bal -= sSpeed; + } + } + sound.bal = bal; + sound.data = data; + used -= userCount; + *frameUsed += usedf-frameLeft; + return(used); +} + + +static long ata_ctx_u16le(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft) +{ + /* this should help gcc to stuff everything into registers */ + u_long data = sound.data; + long bal = sound.bal; + long hSpeed = sound.hard.speed, sSpeed = sound.soft.speed; + long used, usedf; + + used = userCount; + usedf = frameLeft; + if (!sound.soft.stereo) { + u_short *p = (u_short *)&frame[*frameUsed]; + while (frameLeft >= 4) { + if (bal < 0) { + if (userCount < 2) + break; + get_user(data, ((u_short *)userPtr)++); + data = le2be16(data) ^ 0x8000; + userCount -= 2; + bal += hSpeed; + } + *p++ = data; + *p++ = data; + frameLeft -= 4; + bal -= sSpeed; + } + } else { + u_long *p = (u_long *)&frame[*frameUsed]; + while (frameLeft >= 4) { + if (bal < 0) { + if (userCount < 4) + break; + get_user(data, ((u_int *)userPtr)++); + data = le2be16dbl(data) ^ 0x80008000; + userCount -= 4; + bal += hSpeed; + } + *p++ = data; + frameLeft -= 4; + bal -= sSpeed; + } + } + sound.bal = bal; + sound.data = data; + used -= userCount; + *frameUsed += usedf-frameLeft; + return(used); } +#endif /* CONFIG_ATARI */ -static long -ami_ct_u8(const u_char * userPtr, unsigned long userCount, - u_char frame[], long *frameUsed, long frameLeft) +#ifdef CONFIG_AMIGA +static long ami_ct_law(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft) { - long count, used; - - if (!sound.soft.stereo) - { - char *p = &frame[*frameUsed]; - - count = min(userCount, frameLeft) & ~1; - used = count; - while (count > 0) - { - u_char data; - - get_user(data, userPtr++); - *p++ = data ^ 0x80; - count--; - } - } else - { - u_char *left = &frame[*frameUsed >> 1]; - u_char *right = left + sq.block_size_half; + char *table = sound.soft.format == AFMT_MU_LAW ? ulaw2dma8 : alaw2dma8; + long count, used; - count = min(userCount, frameLeft) >> 1 & ~1; - used = count * 2; - while (count > 0) - { - u_char data; - - get_user(data, userPtr++); - *left++ = data ^ 0x80; - get_user(data, userPtr++); - *right++ = data ^ 0x80; - count--; - } - } - *frameUsed += used; - return (used); + if (!sound.soft.stereo) { + u_char *p = &frame[*frameUsed]; + count = min(userCount, frameLeft) & ~1; + used = count; + while (count > 0) { + u_char data; + get_user(data, userPtr++); + *p++ = table[data]; + count--; + } + } else { + u_char *left = &frame[*frameUsed>>1]; + u_char *right = left+sq.block_size_half; + count = min(userCount, frameLeft)>>1 & ~1; + used = count*2; + while (count > 0) { + u_char data; + get_user(data, userPtr++); + *left++ = table[data]; + get_user(data, userPtr++); + *right++ = table[data]; + count--; + } + } + *frameUsed += used; + return(used); } -static long -ami_ct_s16be(const u_char * userPtr, unsigned long userCount, - u_char frame[], long *frameUsed, long frameLeft) +static long ami_ct_s8(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft) { - long count, used; - u_long data; + long count, used; - if (!sound.soft.stereo) - { - u_char *high = &frame[*frameUsed >> 1]; - u_char *low = high + sq.block_size_half; - - count = min(userCount, frameLeft) >> 1 & ~1; - used = count * 2; - while (count > 0) - { - get_user(data, ((u_short *) userPtr)++); - *high++ = data >> 8; - *low++ = (data >> 2) & 0x3f; - count--; - } - } else - { - u_char *lefth = &frame[*frameUsed >> 2]; - u_char *leftl = lefth + sq.block_size_quarter; - u_char *righth = lefth + sq.block_size_half; - u_char *rightl = righth + sq.block_size_quarter; - - count = min(userCount, frameLeft) >> 2 & ~1; - used = count * 4; - while (count > 0) - { - get_user(data, ((u_short *) userPtr)++); - *lefth++ = data >> 8; - *leftl++ = (data >> 2) & 0x3f; - get_user(data, ((u_short *) userPtr)++); - *righth++ = data >> 8; - *rightl++ = (data >> 2) & 0x3f; - count--; - } - } - *frameUsed += used; - return (used); + if (!sound.soft.stereo) { + void *p = &frame[*frameUsed]; + count = min(userCount, frameLeft) & ~1; + used = count; + copy_from_user(p, userPtr, count); + } else { + u_char *left = &frame[*frameUsed>>1]; + u_char *right = left+sq.block_size_half; + count = min(userCount, frameLeft)>>1 & ~1; + used = count*2; + while (count > 0) { + get_user(*left++, userPtr++); + get_user(*right++, userPtr++); + count--; + } + } + *frameUsed += used; + return(used); } -static long -ami_ct_u16be(const u_char * userPtr, unsigned long userCount, - u_char frame[], long *frameUsed, long frameLeft) +static long ami_ct_u8(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft) { - long count, used; - u_long data; + long count, used; - if (!sound.soft.stereo) - { - u_char *high = &frame[*frameUsed >> 1]; - u_char *low = high + sq.block_size_half; - - count = min(userCount, frameLeft) >> 1 & ~1; - used = count * 2; - while (count > 0) - { - get_user(data, ((u_short *) userPtr)++); - data ^= 0x8000; - *high++ = data >> 8; - *low++ = (data >> 2) & 0x3f; - count--; - } - } else - { - u_char *lefth = &frame[*frameUsed >> 2]; - u_char *leftl = lefth + sq.block_size_quarter; - u_char *righth = lefth + sq.block_size_half; - u_char *rightl = righth + sq.block_size_quarter; - - count = min(userCount, frameLeft) >> 2 & ~1; - used = count * 4; - while (count > 0) - { - get_user(data, ((u_short *) userPtr)++); - data ^= 0x8000; - *lefth++ = data >> 8; - *leftl++ = (data >> 2) & 0x3f; - get_user(data, ((u_short *) userPtr)++); - data ^= 0x8000; - *righth++ = data >> 8; - *rightl++ = (data >> 2) & 0x3f; - count--; - } - } - *frameUsed += used; - return (used); + if (!sound.soft.stereo) { + char *p = &frame[*frameUsed]; + count = min(userCount, frameLeft) & ~1; + used = count; + while (count > 0) { + u_char data; + get_user(data, userPtr++); + *p++ = data ^ 0x80; + count--; + } + } else { + u_char *left = &frame[*frameUsed>>1]; + u_char *right = left+sq.block_size_half; + count = min(userCount, frameLeft)>>1 & ~1; + used = count*2; + while (count > 0) { + u_char data; + get_user(data, userPtr++); + *left++ = data ^ 0x80; + get_user(data, userPtr++); + *right++ = data ^ 0x80; + count--; + } + } + *frameUsed += used; + return(used); +} + + +static long ami_ct_s16be(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft) +{ + long count, used; + u_long data; + + if (!sound.soft.stereo) { + u_char *high = &frame[*frameUsed>>1]; + u_char *low = high+sq.block_size_half; + count = min(userCount, frameLeft)>>1 & ~1; + used = count*2; + while (count > 0) { + get_user(data, ((u_short *)userPtr)++); + *high++ = data>>8; + *low++ = (data>>2) & 0x3f; + count--; + } + } else { + u_char *lefth = &frame[*frameUsed>>2]; + u_char *leftl = lefth+sq.block_size_quarter; + u_char *righth = lefth+sq.block_size_half; + u_char *rightl = righth+sq.block_size_quarter; + count = min(userCount, frameLeft)>>2 & ~1; + used = count*4; + while (count > 0) { + get_user(data, ((u_short *)userPtr)++); + *lefth++ = data>>8; + *leftl++ = (data>>2) & 0x3f; + get_user(data, ((u_short *)userPtr)++); + *righth++ = data>>8; + *rightl++ = (data>>2) & 0x3f; + count--; + } + } + *frameUsed += used; + return(used); +} + + +static long ami_ct_u16be(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft) +{ + long count, used; + u_long data; + + if (!sound.soft.stereo) { + u_char *high = &frame[*frameUsed>>1]; + u_char *low = high+sq.block_size_half; + count = min(userCount, frameLeft)>>1 & ~1; + used = count*2; + while (count > 0) { + get_user(data, ((u_short *)userPtr)++); + data ^= 0x8000; + *high++ = data>>8; + *low++ = (data>>2) & 0x3f; + count--; + } + } else { + u_char *lefth = &frame[*frameUsed>>2]; + u_char *leftl = lefth+sq.block_size_quarter; + u_char *righth = lefth+sq.block_size_half; + u_char *rightl = righth+sq.block_size_quarter; + count = min(userCount, frameLeft)>>2 & ~1; + used = count*4; + while (count > 0) { + get_user(data, ((u_short *)userPtr)++); + data ^= 0x8000; + *lefth++ = data>>8; + *leftl++ = (data>>2) & 0x3f; + get_user(data, ((u_short *)userPtr)++); + data ^= 0x8000; + *righth++ = data>>8; + *rightl++ = (data>>2) & 0x3f; + count--; + } + } + *frameUsed += used; + return(used); } -static long -ami_ct_s16le(const u_char * userPtr, unsigned long userCount, - u_char frame[], long *frameUsed, long frameLeft) +static long ami_ct_s16le(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft) { - long count, used; - u_long data; - - if (!sound.soft.stereo) - { - u_char *high = &frame[*frameUsed >> 1]; - u_char *low = high + sq.block_size_half; + long count, used; + u_long data; - count = min(userCount, frameLeft) >> 1 & ~1; - used = count * 2; - while (count > 0) - { - get_user(data, ((u_short *) userPtr)++); - data = le2be16(data); - *high++ = data >> 8; - *low++ = (data >> 2) & 0x3f; - count--; - } - } else - { - u_char *lefth = &frame[*frameUsed >> 2]; - u_char *leftl = lefth + sq.block_size_quarter; - u_char *righth = lefth + sq.block_size_half; - u_char *rightl = righth + sq.block_size_quarter; - - count = min(userCount, frameLeft) >> 2 & ~1; - used = count * 4; - while (count > 0) - { - get_user(data, ((u_short *) userPtr)++); - data = le2be16(data); - *lefth++ = data >> 8; - *leftl++ = (data >> 2) & 0x3f; - get_user(data, ((u_short *) userPtr)++); - data = le2be16(data); - *righth++ = data >> 8; - *rightl++ = (data >> 2) & 0x3f; - count--; - } - } - *frameUsed += used; - return (used); + if (!sound.soft.stereo) { + u_char *high = &frame[*frameUsed>>1]; + u_char *low = high+sq.block_size_half; + count = min(userCount, frameLeft)>>1 & ~1; + used = count*2; + while (count > 0) { + get_user(data, ((u_short *)userPtr)++); + data = le2be16(data); + *high++ = data>>8; + *low++ = (data>>2) & 0x3f; + count--; + } + } else { + u_char *lefth = &frame[*frameUsed>>2]; + u_char *leftl = lefth+sq.block_size_quarter; + u_char *righth = lefth+sq.block_size_half; + u_char *rightl = righth+sq.block_size_quarter; + count = min(userCount, frameLeft)>>2 & ~1; + used = count*4; + while (count > 0) { + get_user(data, ((u_short *)userPtr)++); + data = le2be16(data); + *lefth++ = data>>8; + *leftl++ = (data>>2) & 0x3f; + get_user(data, ((u_short *)userPtr)++); + data = le2be16(data); + *righth++ = data>>8; + *rightl++ = (data>>2) & 0x3f; + count--; + } + } + *frameUsed += used; + return(used); } -static long -ami_ct_u16le(const u_char * userPtr, unsigned long userCount, - u_char frame[], long *frameUsed, long frameLeft) +static long ami_ct_u16le(const u_char *userPtr, unsigned long userCount, + u_char frame[], long *frameUsed, long frameLeft) { - long count, used; - u_long data; - - if (!sound.soft.stereo) - { - u_char *high = &frame[*frameUsed >> 1]; - u_char *low = high + sq.block_size_half; + long count, used; + u_long data; - count = min(userCount, frameLeft) >> 1 & ~1; - used = count * 2; - while (count > 0) - { - get_user(data, ((u_short *) userPtr)++); - data = le2be16(data) ^ 0x8000; - *high++ = data >> 8; - *low++ = (data >> 2) & 0x3f; - count--; - } - } else - { - u_char *lefth = &frame[*frameUsed >> 2]; - u_char *leftl = lefth + sq.block_size_quarter; - u_char *righth = lefth + sq.block_size_half; - u_char *rightl = righth + sq.block_size_quarter; - - count = min(userCount, frameLeft) >> 2 & ~1; - used = count * 4; - while (count > 0) - { - get_user(data, ((u_short *) userPtr)++); - data = le2be16(data) ^ 0x8000; - *lefth++ = data >> 8; - *leftl++ = (data >> 2) & 0x3f; - get_user(data, ((u_short *) userPtr)++); - data = le2be16(data) ^ 0x8000; - *righth++ = data >> 8; - *rightl++ = (data >> 2) & 0x3f; - count--; - } - } - *frameUsed += used; - return (used); + if (!sound.soft.stereo) { + u_char *high = &frame[*frameUsed>>1]; + u_char *low = high+sq.block_size_half; + count = min(userCount, frameLeft)>>1 & ~1; + used = count*2; + while (count > 0) { + get_user(data, ((u_short *)userPtr)++); + data = le2be16(data) ^ 0x8000; + *high++ = data>>8; + *low++ = (data>>2) & 0x3f; + count--; + } + } else { + u_char *lefth = &frame[*frameUsed>>2]; + u_char *leftl = lefth+sq.block_size_quarter; + u_char *righth = lefth+sq.block_size_half; + u_char *rightl = righth+sq.block_size_quarter; + count = min(userCount, frameLeft)>>2 & ~1; + used = count*4; + while (count > 0) { + get_user(data, ((u_short *)userPtr)++); + data = le2be16(data) ^ 0x8000; + *lefth++ = data>>8; + *leftl++ = (data>>2) & 0x3f; + get_user(data, ((u_short *)userPtr)++); + data = le2be16(data) ^ 0x8000; + *righth++ = data>>8; + *rightl++ = (data>>2) & 0x3f; + count--; + } + } + *frameUsed += used; + return(used); } -#endif /* CONFIG_AMIGA */ +#endif /* CONFIG_AMIGA */ #ifdef CONFIG_ATARI -static TRANS transTTNormal = -{ - ata_ct_law, ata_ct_law, ata_ct_s8, ata_ct_u8, NULL, NULL, NULL, NULL +static TRANS transTTNormal = { + ata_ct_law, ata_ct_law, ata_ct_s8, ata_ct_u8, NULL, NULL, NULL, NULL }; -static TRANS transTTExpanding = -{ - ata_ctx_law, ata_ctx_law, ata_ctx_s8, ata_ctx_u8, NULL, NULL, NULL, NULL +static TRANS transTTExpanding = { + ata_ctx_law, ata_ctx_law, ata_ctx_s8, ata_ctx_u8, NULL, NULL, NULL, NULL }; -static TRANS transFalconNormal = -{ -ata_ct_law, ata_ct_law, ata_ct_s8, ata_ct_u8, ata_ct_s16be, ata_ct_u16be, - ata_ct_s16le, ata_ct_u16le +static TRANS transFalconNormal = { + ata_ct_law, ata_ct_law, ata_ct_s8, ata_ct_u8, ata_ct_s16be, ata_ct_u16be, + ata_ct_s16le, ata_ct_u16le }; -static TRANS transFalconExpanding = -{ - ata_ctx_law, ata_ctx_law, ata_ctx_s8, ata_ctx_u8, ata_ctx_s16be, - ata_ctx_u16be, ata_ctx_s16le, ata_ctx_u16le +static TRANS transFalconExpanding = { + ata_ctx_law, ata_ctx_law, ata_ctx_s8, ata_ctx_u8, ata_ctx_s16be, + ata_ctx_u16be, ata_ctx_s16le, ata_ctx_u16le }; - -#endif /* CONFIG_ATARI */ +#endif /* CONFIG_ATARI */ #ifdef CONFIG_AMIGA -static TRANS transAmiga = -{ -ami_ct_law, ami_ct_law, ami_ct_s8, ami_ct_u8, ami_ct_s16be, ami_ct_u16be, - ami_ct_s16le, ami_ct_u16le +static TRANS transAmiga = { + ami_ct_law, ami_ct_law, ami_ct_s8, ami_ct_u8, ami_ct_s16be, ami_ct_u16be, + ami_ct_s16le, ami_ct_u16le }; - -#endif /* CONFIG_AMIGA */ +#endif /* CONFIG_AMIGA */ /*** Low level stuff *********************************************************/ @@ -1774,68 +1581,44 @@ ami_ct_law, ami_ct_law, ami_ct_s8, ami_ct_u8, ami_ct_s16be, ami_ct_u16be, * Atari (TT/Falcon) */ -static void * -AtaAlloc(unsigned int size, int flags) -{ - int order; - unsigned int a_size; - - order = 0; - a_size = PAGE_SIZE; - while (a_size < size) - { - order++; - a_size <<= 1; - } - return (void *) __get_dma_pages(flags, order); -} - -static void -AtaFree(void *obj, unsigned int size) -{ - int order; - unsigned int a_size; - - order = 0; - a_size = PAGE_SIZE; - while (a_size < size) - { - order++; - a_size <<= 1; - } - free_pages((unsigned long) obj, order); -} - -static int -AtaIrqInit(void) -{ - /* Set up timer A. Timer A - will receive a signal upon end of playing from the sound - hardware. Furthermore Timer A is able to count events - and will cause an interrupt after a programmed number - of events. So all we need to keep the music playing is - to provide the sound hardware with new data upon - an interrupt from timer A. */ - mfp.tim_ct_a = 0; /* ++roman: Stop timer before programming! */ - mfp.tim_dt_a = 1; /* Cause interrupt after first event. */ - mfp.tim_ct_a = 8; /* Turn on event counting. */ - /* Register interrupt handler. */ - request_irq(IRQ_MFP_TIMA, ata_sq_interrupt, IRQ_TYPE_SLOW, - "DMA sound", ata_sq_interrupt); - mfp.int_en_a |= 0x20; /* Turn interrupt on. */ - mfp.int_mk_a |= 0x20; - return (1); +static void *AtaAlloc(unsigned int size, int flags) +{ + return( atari_stram_alloc( size, NULL, "dmasound" )); +} + +static void AtaFree(void *obj, unsigned int size) +{ + atari_stram_free( obj ); +} + +static int AtaIrqInit(void) +{ + /* Set up timer A. Timer A + will receive a signal upon end of playing from the sound + hardware. Furthermore Timer A is able to count events + and will cause an interrupt after a programmed number + of events. So all we need to keep the music playing is + to provide the sound hardware with new data upon + an interrupt from timer A. */ + mfp.tim_ct_a = 0; /* ++roman: Stop timer before programming! */ + mfp.tim_dt_a = 1; /* Cause interrupt after first event. */ + mfp.tim_ct_a = 8; /* Turn on event counting. */ + /* Register interrupt handler. */ + request_irq(IRQ_MFP_TIMA, ata_sq_interrupt, IRQ_TYPE_SLOW, + "DMA sound", ata_sq_interrupt); + mfp.int_en_a |= 0x20; /* Turn interrupt on. */ + mfp.int_mk_a |= 0x20; + return(1); } #ifdef MODULE -static void -AtaIrqCleanUp(void) +static void AtaIrqCleanUp(void) { - mfp.tim_ct_a = 0; /* stop timer */ - mfp.int_en_a &= ~0x20; /* turn interrupt off */ - free_irq(IRQ_MFP_TIMA, ata_sq_interrupt); + mfp.tim_ct_a = 0; /* stop timer */ + mfp.int_en_a &= ~0x20; /* turn interrupt off */ + free_irq(IRQ_MFP_TIMA, ata_sq_interrupt); } -#endif /* MODULE */ +#endif /* MODULE */ #define TONE_VOXWARE_TO_DB(v) \ @@ -1843,21 +1626,19 @@ AtaIrqCleanUp(void) #define TONE_DB_TO_VOXWARE(v) (((v) * 25 + ((v) > 0 ? 5 : -5)) / 6 + 50) -static int -AtaSetBass(int bass) +static int AtaSetBass(int bass) { - sound.bass = TONE_VOXWARE_TO_DB(bass); - atari_microwire_cmd(MW_LM1992_BASS(sound.bass)); - return (TONE_DB_TO_VOXWARE(sound.bass)); + sound.bass = TONE_VOXWARE_TO_DB(bass); + atari_microwire_cmd(MW_LM1992_BASS(sound.bass)); + return(TONE_DB_TO_VOXWARE(sound.bass)); } -static int -AtaSetTreble(int treble) +static int AtaSetTreble(int treble) { - sound.treble = TONE_VOXWARE_TO_DB(treble); - atari_microwire_cmd(MW_LM1992_TREBLE(sound.treble)); - return (TONE_DB_TO_VOXWARE(sound.treble)); + sound.treble = TONE_VOXWARE_TO_DB(treble); + atari_microwire_cmd(MW_LM1992_TREBLE(sound.treble)); + return(TONE_DB_TO_VOXWARE(sound.treble)); } @@ -1867,117 +1648,116 @@ AtaSetTreble(int treble) */ -static void -TTSilence(void) +static void TTSilence(void) { - tt_dmasnd.ctrl = DMASND_CTRL_OFF; - atari_microwire_cmd(MW_LM1992_PSG_HIGH); /* mix in PSG signal 1:1 */ + tt_dmasnd.ctrl = DMASND_CTRL_OFF; + atari_microwire_cmd(MW_LM1992_PSG_HIGH); /* mix in PSG signal 1:1 */ } -static void -TTInit(void) +static void TTInit(void) { - int mode, i, idx; - const int freq[4] = - {50066, 25033, 12517, 6258}; - - /* search a frequency that fits into the allowed error range */ + int mode, i, idx; + const int freq[4] = {50066, 25033, 12517, 6258}; - idx = -1; - for (i = 0; i < arraysize(freq); i++) - /* this isn't as much useful for a TT than for a Falcon, but - * then it doesn't hurt very much to implement it for a TT too. - */ - if ((100 * abs(sound.soft.speed - freq[i]) / freq[i]) < catchRadius) - idx = i; - if (idx > -1) - { - sound.soft.speed = freq[idx]; - sound.trans = &transTTNormal; - } else - sound.trans = &transTTExpanding; - - TTSilence(); - sound.hard = sound.soft; - - if (sound.hard.speed > 50066) - { - /* we would need to squeeze the sound, but we won't do that */ - sound.hard.speed = 50066; - mode = DMASND_MODE_50KHZ; - sound.trans = &transTTNormal; - } else if (sound.hard.speed > 25033) - { - sound.hard.speed = 50066; - mode = DMASND_MODE_50KHZ; - } else if (sound.hard.speed > 12517) - { - sound.hard.speed = 25033; - mode = DMASND_MODE_25KHZ; - } else if (sound.hard.speed > 6258) - { - sound.hard.speed = 12517; - mode = DMASND_MODE_12KHZ; - } else - { - sound.hard.speed = 6258; - mode = DMASND_MODE_6KHZ; - } + /* search a frequency that fits into the allowed error range */ - tt_dmasnd.mode = (sound.hard.stereo ? - DMASND_MODE_STEREO : DMASND_MODE_MONO) | - DMASND_MODE_8BIT | mode; + idx = -1; + for (i = 0; i < arraysize(freq); i++) + /* this isn't as much useful for a TT than for a Falcon, but + * then it doesn't hurt very much to implement it for a TT too. + */ + if ((100 * abs(sound.soft.speed - freq[i]) / freq[i]) < catchRadius) + idx = i; + if (idx > -1) { + sound.soft.speed = freq[idx]; + sound.trans = &transTTNormal; + } else + sound.trans = &transTTExpanding; + + TTSilence(); + sound.hard = sound.soft; + + if (sound.hard.speed > 50066) { + /* we would need to squeeze the sound, but we won't do that */ + sound.hard.speed = 50066; + mode = DMASND_MODE_50KHZ; + sound.trans = &transTTNormal; + } else if (sound.hard.speed > 25033) { + sound.hard.speed = 50066; + mode = DMASND_MODE_50KHZ; + } else if (sound.hard.speed > 12517) { + sound.hard.speed = 25033; + mode = DMASND_MODE_25KHZ; + } else if (sound.hard.speed > 6258) { + sound.hard.speed = 12517; + mode = DMASND_MODE_12KHZ; + } else { + sound.hard.speed = 6258; + mode = DMASND_MODE_6KHZ; + } + + tt_dmasnd.mode = (sound.hard.stereo ? + DMASND_MODE_STEREO : DMASND_MODE_MONO) | + DMASND_MODE_8BIT | mode; + + sound.bal = -sound.soft.speed; +} + + +static int TTSetFormat(int format) +{ + /* TT sound DMA supports only 8bit modes */ + + switch (format) { + case AFMT_QUERY: + return(sound.soft.format); + case AFMT_MU_LAW: + case AFMT_A_LAW: + case AFMT_S8: + case AFMT_U8: + break; + default: + format = AFMT_S8; + } + + sound.soft.format = format; + sound.soft.size = 8; + if (sound.minDev == SND_DEV_DSP) { + sound.dsp.format = format; + sound.dsp.size = 8; + } + TTInit(); - sound.bal = -sound.soft.speed; + return(format); } -static int -TTSetFormat(int format) -{ - /* TT sound DMA supports only 8bit modes */ - - switch (format) - { - case AFMT_QUERY: - return (sound.soft.format); - case AFMT_MU_LAW: - case AFMT_A_LAW: - case AFMT_S8: - case AFMT_U8: - break; - default: - format = AFMT_S8; - } +#define VOLUME_VOXWARE_TO_DB(v) \ + (((v) < 0) ? -40 : ((v) > 100) ? 0 : ((v) * 2) / 5 - 40) +#define VOLUME_DB_TO_VOXWARE(v) ((((v) + 40) * 5 + 1) / 2) - sound.soft.format = format; - sound.soft.size = 8; - if (sound.minDev == SND_DEV_DSP) - { - sound.dsp.format = format; - sound.dsp.size = 8; - } - TTInit(); - return (format); +static int TTSetVolume(int volume) +{ + sound.volume_left = VOLUME_VOXWARE_TO_DB(volume & 0xff); + atari_microwire_cmd(MW_LM1992_BALLEFT(sound.volume_left)); + sound.volume_right = VOLUME_VOXWARE_TO_DB((volume & 0xff00) >> 8); + atari_microwire_cmd(MW_LM1992_BALRIGHT(sound.volume_right)); + return(VOLUME_DB_TO_VOXWARE(sound.volume_left) | + (VOLUME_DB_TO_VOXWARE(sound.volume_right) << 8)); } -#define VOLUME_VOXWARE_TO_DB(v) \ - (((v) < 0) ? -40 : ((v) > 100) ? 0 : ((v) * 2) / 5 - 40) -#define VOLUME_DB_TO_VOXWARE(v) ((((v) + 40) * 5 + 1) / 2) - +#define GAIN_VOXWARE_TO_DB(v) \ + (((v) < 0) ? -80 : ((v) > 100) ? 0 : ((v) * 4) / 5 - 80) +#define GAIN_DB_TO_VOXWARE(v) ((((v) + 80) * 5 + 1) / 4) -static int -TTSetVolume(int volume) +static int TTSetGain(int gain) { - sound.volume_left = VOLUME_VOXWARE_TO_DB(volume & 0xff); - atari_microwire_cmd(MW_LM1992_BALLEFT(sound.volume_left)); - sound.volume_right = VOLUME_VOXWARE_TO_DB((volume & 0xff00) >> 8); - atari_microwire_cmd(MW_LM1992_BALRIGHT(sound.volume_right)); - return (VOLUME_DB_TO_VOXWARE(sound.volume_left) | - (VOLUME_DB_TO_VOXWARE(sound.volume_right) << 8)); + sound.gain = GAIN_VOXWARE_TO_DB(gain); + atari_microwire_cmd(MW_LM1992_VOLUME(sound.gain)); + return GAIN_DB_TO_VOXWARE(sound.gain); } @@ -1987,151 +1767,135 @@ TTSetVolume(int volume) */ -static void -FalconSilence(void) +static void FalconSilence(void) { - /* stop playback, set sample rate 50kHz for PSG sound */ - tt_dmasnd.ctrl = DMASND_CTRL_OFF; - tt_dmasnd.mode = DMASND_MODE_50KHZ | DMASND_MODE_STEREO | DMASND_MODE_8BIT; - tt_dmasnd.int_div = 0; /* STE compatible divider */ - tt_dmasnd.int_ctrl = 0x0; - tt_dmasnd.cbar_src = 0x0000; /* no matrix inputs */ - tt_dmasnd.cbar_dst = 0x0000; /* no matrix outputs */ - tt_dmasnd.dac_src = 1; /* connect ADC to DAC, disconnect matrix */ - tt_dmasnd.adc_src = 3; /* ADC Input = PSG */ + /* stop playback, set sample rate 50kHz for PSG sound */ + tt_dmasnd.ctrl = DMASND_CTRL_OFF; + tt_dmasnd.mode = DMASND_MODE_50KHZ | DMASND_MODE_STEREO | DMASND_MODE_8BIT; + tt_dmasnd.int_div = 0; /* STE compatible divider */ + tt_dmasnd.int_ctrl = 0x0; + tt_dmasnd.cbar_src = 0x0000; /* no matrix inputs */ + tt_dmasnd.cbar_dst = 0x0000; /* no matrix outputs */ + tt_dmasnd.dac_src = 1; /* connect ADC to DAC, disconnect matrix */ + tt_dmasnd.adc_src = 3; /* ADC Input = PSG */ } -static void -FalconInit(void) +static void FalconInit(void) { - int divider, i, idx; - const int freq[8] = - {49170, 32780, 24585, 19668, 16390, 12292, 9834, 8195}; + int divider, i, idx; + const int freq[8] = {49170, 32780, 24585, 19668, 16390, 12292, 9834, 8195}; - /* search a frequency that fits into the allowed error range */ + /* search a frequency that fits into the allowed error range */ - idx = -1; - for (i = 0; i < arraysize(freq); i++) - /* if we will tolerate 3% error 8000Hz->8195Hz (2.38%) would - * be playable without expanding, but that now a kernel runtime - * option - */ - if ((100 * abs(sound.soft.speed - freq[i]) / freq[i]) < catchRadius) - idx = i; - if (idx > -1) - { - sound.soft.speed = freq[idx]; - sound.trans = &transFalconNormal; - } else - sound.trans = &transFalconExpanding; - - FalconSilence(); - sound.hard = sound.soft; - - if (sound.hard.size == 16) - { - /* the Falcon can play 16bit samples only in stereo */ - sound.hard.stereo = 1; - } - if (sound.hard.speed > 49170) - { - /* we would need to squeeze the sound, but we won't do that */ - sound.hard.speed = 49170; - divider = 1; - sound.trans = &transFalconNormal; - } else if (sound.hard.speed > 32780) - { - sound.hard.speed = 49170; - divider = 1; - } else if (sound.hard.speed > 24585) - { - sound.hard.speed = 32780; - divider = 2; - } else if (sound.hard.speed > 19668) - { - sound.hard.speed = 24585; - divider = 3; - } else if (sound.hard.speed > 16390) - { - sound.hard.speed = 19668; - divider = 4; - } else if (sound.hard.speed > 12292) - { - sound.hard.speed = 16390; - divider = 5; - } else if (sound.hard.speed > 9834) - { - sound.hard.speed = 12292; - divider = 7; - } else if (sound.hard.speed > 8195) - { - sound.hard.speed = 9834; - divider = 9; - } else - { - sound.hard.speed = 8195; - divider = 11; - } - tt_dmasnd.int_div = divider; - - /* Setup Falcon sound DMA for playback */ - tt_dmasnd.int_ctrl = 0x4; /* Timer A int at play end */ - tt_dmasnd.track_select = 0x0; /* play 1 track, track 1 */ - tt_dmasnd.cbar_src = 0x0001; /* DMA(25MHz) --> DAC */ - tt_dmasnd.cbar_dst = 0x0000; - tt_dmasnd.rec_track_select = 0; - tt_dmasnd.dac_src = 2; /* connect matrix to DAC */ - tt_dmasnd.adc_src = 0; /* ADC Input = Mic */ - - tt_dmasnd.mode = (sound.hard.stereo ? - DMASND_MODE_STEREO : DMASND_MODE_MONO) | - ((sound.hard.size == 8) ? - DMASND_MODE_8BIT : DMASND_MODE_16BIT) | - DMASND_MODE_6KHZ; - - sound.bal = -sound.soft.speed; -} - - -static int -FalconSetFormat(int format) -{ - int size; - - /* Falcon sound DMA supports 8bit and 16bit modes */ - - switch (format) - { - case AFMT_QUERY: - return (sound.soft.format); - case AFMT_MU_LAW: - case AFMT_A_LAW: - case AFMT_U8: - case AFMT_S8: - size = 8; - break; - case AFMT_S16_BE: - case AFMT_U16_BE: - case AFMT_S16_LE: - case AFMT_U16_LE: - size = 16; - break; - default: /* :-) */ - size = 8; - format = AFMT_S8; - } - - sound.soft.format = format; - sound.soft.size = size; - if (sound.minDev == SND_DEV_DSP) - { - sound.dsp.format = format; - sound.dsp.size = sound.soft.size; - } - FalconInit(); - - return (format); + idx = -1; + for (i = 0; i < arraysize(freq); i++) + /* if we will tolerate 3% error 8000Hz->8195Hz (2.38%) would + * be playable without expanding, but that now a kernel runtime + * option + */ + if ((100 * abs(sound.soft.speed - freq[i]) / freq[i]) < catchRadius) + idx = i; + if (idx > -1) { + sound.soft.speed = freq[idx]; + sound.trans = &transFalconNormal; + } else + sound.trans = &transFalconExpanding; + + FalconSilence(); + sound.hard = sound.soft; + + if (sound.hard.size == 16) { + /* the Falcon can play 16bit samples only in stereo */ + sound.hard.stereo = 1; + } + + if (sound.hard.speed > 49170) { + /* we would need to squeeze the sound, but we won't do that */ + sound.hard.speed = 49170; + divider = 1; + sound.trans = &transFalconNormal; + } else if (sound.hard.speed > 32780) { + sound.hard.speed = 49170; + divider = 1; + } else if (sound.hard.speed > 24585) { + sound.hard.speed = 32780; + divider = 2; + } else if (sound.hard.speed > 19668) { + sound.hard.speed = 24585; + divider = 3; + } else if (sound.hard.speed > 16390) { + sound.hard.speed = 19668; + divider = 4; + } else if (sound.hard.speed > 12292) { + sound.hard.speed = 16390; + divider = 5; + } else if (sound.hard.speed > 9834) { + sound.hard.speed = 12292; + divider = 7; + } else if (sound.hard.speed > 8195) { + sound.hard.speed = 9834; + divider = 9; + } else { + sound.hard.speed = 8195; + divider = 11; + } + tt_dmasnd.int_div = divider; + + /* Setup Falcon sound DMA for playback */ + tt_dmasnd.int_ctrl = 0x4; /* Timer A int at play end */ + tt_dmasnd.track_select = 0x0; /* play 1 track, track 1 */ + tt_dmasnd.cbar_src = 0x0001; /* DMA(25MHz) --> DAC */ + tt_dmasnd.cbar_dst = 0x0000; + tt_dmasnd.rec_track_select = 0; + tt_dmasnd.dac_src = 2; /* connect matrix to DAC */ + tt_dmasnd.adc_src = 0; /* ADC Input = Mic */ + + tt_dmasnd.mode = (sound.hard.stereo ? + DMASND_MODE_STEREO : DMASND_MODE_MONO) | + ((sound.hard.size == 8) ? + DMASND_MODE_8BIT : DMASND_MODE_16BIT) | + DMASND_MODE_6KHZ; + + sound.bal = -sound.soft.speed; +} + + +static int FalconSetFormat(int format) +{ + int size; + /* Falcon sound DMA supports 8bit and 16bit modes */ + + switch (format) { + case AFMT_QUERY: + return(sound.soft.format); + case AFMT_MU_LAW: + case AFMT_A_LAW: + case AFMT_U8: + case AFMT_S8: + size = 8; + break; + case AFMT_S16_BE: + case AFMT_U16_BE: + case AFMT_S16_LE: + case AFMT_U16_LE: + size = 16; + break; + default: /* :-) */ + size = 8; + format = AFMT_S8; + } + + sound.soft.format = format; + sound.soft.size = size; + if (sound.minDev == SND_DEV_DSP) { + sound.dsp.format = format; + sound.dsp.size = sound.soft.size; + } + + FalconInit(); + + return(format); } @@ -2143,181 +1907,168 @@ FalconSetFormat(int format) #define VOLUME_ATT_TO_VOXWARE(v) (100 - (v) * 20 / 3) -static int -FalconSetVolume(int volume) +static int FalconSetVolume(int volume) { - sound.volume_left = VOLUME_VOXWARE_TO_ATT(volume & 0xff); - sound.volume_right = VOLUME_VOXWARE_TO_ATT((volume & 0xff00) >> 8); - tt_dmasnd.output_atten = sound.volume_left << 8 | sound.volume_right << 4; - return (VOLUME_ATT_TO_VOXWARE(sound.volume_left) | - VOLUME_ATT_TO_VOXWARE(sound.volume_right) << 8); + sound.volume_left = VOLUME_VOXWARE_TO_ATT(volume & 0xff); + sound.volume_right = VOLUME_VOXWARE_TO_ATT((volume & 0xff00) >> 8); + tt_dmasnd.output_atten = sound.volume_left << 8 | sound.volume_right << 4; + return(VOLUME_ATT_TO_VOXWARE(sound.volume_left) | + VOLUME_ATT_TO_VOXWARE(sound.volume_right) << 8); } -static void -ata_sq_play_next_frame(int index) +static void ata_sq_play_next_frame(int index) { - char *start, *end; + char *start, *end; - /* used by AtaPlay() if all doubts whether there really is something - * to be played are already wiped out. - */ - start = sq_block_address(sq.front); - end = start + ((sq.count == index) ? sq.rear_size : sq.block_size); - /* end might not be a legal virtual address. */ - DMASNDSetEnd(VTOP(end - 1) + 1); - DMASNDSetBase(VTOP(start)); + /* used by AtaPlay() if all doubts whether there really is something + * to be played are already wiped out. + */ + start = sq_block_address(sq.front); + end = start+((sq.count == index) ? sq.rear_size : sq.block_size); + /* end might not be a legal virtual address. */ + DMASNDSetEnd(VTOP(end - 1) + 1); + DMASNDSetBase(VTOP(start)); /* Since only an even number of samples per frame can - be played, we might lose one byte here. (TO DO) */ - sq.front = (sq.front + 1) % sq.max_count; - sq.playing++; - tt_dmasnd.ctrl = DMASND_CTRL_ON | DMASND_CTRL_REPEAT; -} - - -static void -AtaPlay(void) -{ - /* ++TeSche: Note that sq.playing is no longer just a flag but holds - * the number of frames the DMA is currently programmed for instead, - * may be 0, 1 (currently being played) or 2 (pre-programmed). - * - * Changes done to sq.count and sq.playing are a bit more subtle again - * so now I must admit I also prefer disabling the irq here rather - * than considering all possible situations. But the point is that - * disabling the irq doesn't have any bad influence on this version of - * the driver as we benefit from having pre-programmed the DMA - * wherever possible: There's no need to reload the DMA at the exact - * time of an interrupt but only at some time while the pre-programmed - * frame is playing! - */ - atari_disable_irq(IRQ_MFP_TIMA); - - if (sq.playing == 2 || /* DMA is 'full' */ - sq.count <= 0) - { /* nothing to do */ - atari_enable_irq(IRQ_MFP_TIMA); - return; - } - if (sq.playing == 0) - { - /* looks like there's nothing 'in' the DMA yet, so try - * to put two frames into it (at least one is available). - */ - if (sq.count == 1 && sq.rear_size < sq.block_size && !sq.syncing) - { - /* hmmm, the only existing frame is not - * yet filled and we're not syncing? - */ - atari_enable_irq(IRQ_MFP_TIMA); - return; - } - ata_sq_play_next_frame(1); - if (sq.count == 1) - { - /* no more frames */ - atari_enable_irq(IRQ_MFP_TIMA); - return; - } - if (sq.count == 2 && sq.rear_size < sq.block_size && !sq.syncing) - { - /* hmmm, there were two frames, but the second - * one is not yet filled and we're not syncing? - */ - atari_enable_irq(IRQ_MFP_TIMA); - return; - } - ata_sq_play_next_frame(2); - } else - { - /* there's already a frame being played so we may only stuff - * one new into the DMA, but even if this may be the last - * frame existing the previous one is still on sq.count. - */ - if (sq.count == 2 && sq.rear_size < sq.block_size && !sq.syncing) - { - /* hmmm, the only existing frame is not - * yet filled and we're not syncing? - */ - atari_enable_irq(IRQ_MFP_TIMA); - return; - } - ata_sq_play_next_frame(2); - } + be played, we might lose one byte here. (TO DO) */ + sq.front = (sq.front+1) % sq.max_count; + sq.playing++; + tt_dmasnd.ctrl = DMASND_CTRL_ON | DMASND_CTRL_REPEAT; +} + + +static void AtaPlay(void) +{ + /* ++TeSche: Note that sq.playing is no longer just a flag but holds + * the number of frames the DMA is currently programmed for instead, + * may be 0, 1 (currently being played) or 2 (pre-programmed). + * + * Changes done to sq.count and sq.playing are a bit more subtle again + * so now I must admit I also prefer disabling the irq here rather + * than considering all possible situations. But the point is that + * disabling the irq doesn't have any bad influence on this version of + * the driver as we benefit from having pre-programmed the DMA + * wherever possible: There's no need to reload the DMA at the exact + * time of an interrupt but only at some time while the pre-programmed + * frame is playing! + */ + atari_disable_irq(IRQ_MFP_TIMA); + + if (sq.playing == 2 || /* DMA is 'full' */ + sq.count <= 0) { /* nothing to do */ atari_enable_irq(IRQ_MFP_TIMA); + return; + } + + if (sq.playing == 0) { + /* looks like there's nothing 'in' the DMA yet, so try + * to put two frames into it (at least one is available). + */ + if (sq.count == 1 && sq.rear_size < sq.block_size && !sq.syncing) { + /* hmmm, the only existing frame is not + * yet filled and we're not syncing? + */ + atari_enable_irq(IRQ_MFP_TIMA); + return; + } + ata_sq_play_next_frame(1); + if (sq.count == 1) { + /* no more frames */ + atari_enable_irq(IRQ_MFP_TIMA); + return; + } + if (sq.count == 2 && sq.rear_size < sq.block_size && !sq.syncing) { + /* hmmm, there were two frames, but the second + * one is not yet filled and we're not syncing? + */ + atari_enable_irq(IRQ_MFP_TIMA); + return; + } + ata_sq_play_next_frame(2); + } else { + /* there's already a frame being played so we may only stuff + * one new into the DMA, but even if this may be the last + * frame existing the previous one is still on sq.count. + */ + if (sq.count == 2 && sq.rear_size < sq.block_size && !sq.syncing) { + /* hmmm, the only existing frame is not + * yet filled and we're not syncing? + */ + atari_enable_irq(IRQ_MFP_TIMA); + return; + } + ata_sq_play_next_frame(2); + } + atari_enable_irq(IRQ_MFP_TIMA); } -static void -ata_sq_interrupt(int irq, void *dummy, struct pt_regs *fp) +static void ata_sq_interrupt(int irq, void *dummy, struct pt_regs *fp) { #if 0 - /* ++TeSche: if you should want to test this... */ - static int cnt = 0; - - if (sq.playing == 2) - if (++cnt == 10) - { - /* simulate losing an interrupt */ - cnt = 0; - return; - } + /* ++TeSche: if you should want to test this... */ + static int cnt = 0; + if (sq.playing == 2) + if (++cnt == 10) { + /* simulate losing an interrupt */ + cnt = 0; + return; + } #endif - if (sq.ignore_int && (sound.mach.type == DMASND_FALCON)) - { - /* ++TeSche: Falcon only: ignore first irq because it comes - * immediately after starting a frame. after that, irqs come - * (almost) like on the TT. - */ - sq.ignore_int = 0; - return; - } - if (!sq.playing) - { - /* playing was interrupted and sq_reset() has already cleared - * the sq variables, so better don't do anything here. - */ - WAKE_UP(sq.sync_queue); - return; - } - /* Probably ;) one frame is finished. Well, in fact it may be that a - * pre-programmed one is also finished because there has been a long - * delay in interrupt delivery and we've completely lost one, but - * there's no way to detect such a situation. In such a case the last - * frame will be played more than once and the situation will recover - * as soon as the irq gets through. + if (sq.ignore_int && (sound.mach.type == DMASND_FALCON)) { + /* ++TeSche: Falcon only: ignore first irq because it comes + * immediately after starting a frame. after that, irqs come + * (almost) like on the TT. */ - sq.count--; - sq.playing--; + sq.ignore_int = 0; + return; + } - if (!sq.playing) - { - tt_dmasnd.ctrl = DMASND_CTRL_OFF; - sq.ignore_int = 1; - } - WAKE_UP(sq.write_queue); + if (!sq.playing) { + /* playing was interrupted and sq_reset() has already cleared + * the sq variables, so better don't do anything here. + */ + WAKE_UP(sq.sync_queue); + return; + } + + /* Probably ;) one frame is finished. Well, in fact it may be that a + * pre-programmed one is also finished because there has been a long + * delay in interrupt delivery and we've completely lost one, but + * there's no way to detect such a situation. In such a case the last + * frame will be played more than once and the situation will recover + * as soon as the irq gets through. + */ + sq.count--; + sq.playing--; + + if (!sq.playing) { + tt_dmasnd.ctrl = DMASND_CTRL_OFF; + sq.ignore_int = 1; + } + + WAKE_UP(sq.write_queue); /* At least one block of the queue is free now - so wake up a writing process blocked because - of a full queue. */ - - if ((sq.playing != 1) || (sq.count != 1)) - /* We must be a bit carefully here: sq.count indicates the - * number of buffers used and not the number of frames to - * be played. If sq.count==1 and sq.playing==1 that means - * the only remaining frame was already programmed earlier - * (and is currently running) so we mustn't call AtaPlay() - * here, otherwise we'll play one frame too much. - */ - AtaPlay(); + so wake up a writing process blocked because + of a full queue. */ + + if ((sq.playing != 1) || (sq.count != 1)) + /* We must be a bit carefully here: sq.count indicates the + * number of buffers used and not the number of frames to + * be played. If sq.count==1 and sq.playing==1 that means + * the only remaining frame was already programmed earlier + * (and is currently running) so we mustn't call AtaPlay() + * here, otherwise we'll play one frame too much. + */ + AtaPlay(); - if (!sq.playing) - WAKE_UP(sq.sync_queue); + if (!sq.playing) WAKE_UP(sq.sync_queue); /* We are not playing after AtaPlay(), so there - is nothing to play any more. Wake up a process - waiting for audio output to drain. */ + is nothing to play any more. Wake up a process + waiting for audio output to drain. */ } -#endif /* CONFIG_ATARI */ +#endif /* CONFIG_ATARI */ #ifdef CONFIG_AMIGA @@ -2327,120 +2078,109 @@ ata_sq_interrupt(int irq, void *dummy, struct pt_regs *fp) */ -static void * -AmiAlloc(unsigned int size, int flags) +static void *AmiAlloc(unsigned int size, int flags) { - return (amiga_chip_alloc((long) size)); + return(amiga_chip_alloc((long)size)); } -static void -AmiFree(void *obj, unsigned int size) +static void AmiFree(void *obj, unsigned int size) { - amiga_chip_free(obj); + amiga_chip_free (obj); } -static int -AmiIrqInit(void) +static int AmiIrqInit(void) { - /* turn off DMA for audio channels */ - custom.dmacon = AMI_AUDIO_OFF; + /* turn off DMA for audio channels */ + custom.dmacon = AMI_AUDIO_OFF; - /* Register interrupt handler. */ - if (request_irq(IRQ_AMIGA_AUD0, ami_sq_interrupt, 0, - "DMA sound", ami_sq_interrupt)) - return (0); - return (1); + /* Register interrupt handler. */ + if (request_irq(IRQ_AMIGA_AUD0, ami_sq_interrupt, 0, + "DMA sound", ami_sq_interrupt)) + return(0); + return(1); } #ifdef MODULE -static void -AmiIrqCleanUp(void) +static void AmiIrqCleanUp(void) { - /* turn off DMA for audio channels */ - custom.dmacon = AMI_AUDIO_OFF; - /* release the interrupt */ - free_irq(IRQ_AMIGA_AUD0, ami_sq_interrupt); + /* turn off DMA for audio channels */ + custom.dmacon = AMI_AUDIO_OFF; + /* release the interrupt */ + free_irq(IRQ_AMIGA_AUD0, ami_sq_interrupt); } -#endif /* MODULE */ +#endif /* MODULE */ -static void -AmiSilence(void) +static void AmiSilence(void) { - /* turn off DMA for audio channels */ - custom.dmacon = AMI_AUDIO_OFF; + /* turn off DMA for audio channels */ + custom.dmacon = AMI_AUDIO_OFF; } -static void -AmiInit(void) +static void AmiInit(void) { - int period, i; + int period, i; - AmiSilence(); + AmiSilence(); - if (sound.soft.speed) - period = amiga_colorclock / sound.soft.speed - 1; - else - period = amiga_audio_min_period; - sound.hard = sound.soft; - sound.trans = &transAmiga; + if (sound.soft.speed) + period = amiga_colorclock/sound.soft.speed-1; + else + period = amiga_audio_min_period; + sound.hard = sound.soft; + sound.trans = &transAmiga; - if (period < amiga_audio_min_period) - { - /* we would need to squeeze the sound, but we won't do that */ - period = amiga_audio_min_period; - } else if (period > 65535) - { - period = 65535; - } - sound.hard.speed = amiga_colorclock / (period + 1); + if (period < amiga_audio_min_period) { + /* we would need to squeeze the sound, but we won't do that */ + period = amiga_audio_min_period; + } else if (period > 65535) { + period = 65535; + } + sound.hard.speed = amiga_colorclock/(period+1); - for (i = 0; i < 4; i++) - custom.aud[i].audper = period; - amiga_audio_period = period; + for (i = 0; i < 4; i++) + custom.aud[i].audper = period; + amiga_audio_period = period; - AmiSetTreble(50); /* recommended for newer amiga models */ + AmiSetTreble(50); /* recommended for newer amiga models */ } -static int -AmiSetFormat(int format) +static int AmiSetFormat(int format) { - int size; + int size; - /* Amiga sound DMA supports 8bit and 16bit (pseudo 14 bit) modes */ + /* Amiga sound DMA supports 8bit and 16bit (pseudo 14 bit) modes */ - switch (format) - { - case AFMT_QUERY: - return (sound.soft.format); - case AFMT_MU_LAW: - case AFMT_A_LAW: - case AFMT_U8: - case AFMT_S8: - size = 8; - break; - case AFMT_S16_BE: - case AFMT_U16_BE: - case AFMT_S16_LE: - case AFMT_U16_LE: - size = 16; - break; - default: /* :-) */ - size = 8; - format = AFMT_S8; - } + switch (format) { + case AFMT_QUERY: + return(sound.soft.format); + case AFMT_MU_LAW: + case AFMT_A_LAW: + case AFMT_U8: + case AFMT_S8: + size = 8; + break; + case AFMT_S16_BE: + case AFMT_U16_BE: + case AFMT_S16_LE: + case AFMT_U16_LE: + size = 16; + break; + default: /* :-) */ + size = 8; + format = AFMT_S8; + } - sound.soft.format = format; - sound.soft.size = size; - if (sound.minDev == SND_DEV_DSP) - { - sound.dsp.format = format; - sound.dsp.size = sound.soft.size; - } - AmiInit(); + sound.soft.format = format; + sound.soft.size = size; + if (sound.minDev == SND_DEV_DSP) { + sound.dsp.format = format; + sound.dsp.size = sound.soft.size; + } + AmiInit(); - return (format); + return(format); } @@ -2448,26 +2188,24 @@ AmiSetFormat(int format) (((v) < 0) ? 0 : ((v) > 100) ? 64 : ((v) * 64)/100) #define VOLUME_AMI_TO_VOXWARE(v) ((v)*100/64) -static int -AmiSetVolume(int volume) +static int AmiSetVolume(int volume) { - sound.volume_left = VOLUME_VOXWARE_TO_AMI(volume & 0xff); - custom.aud[0].audvol = sound.volume_left; - sound.volume_right = VOLUME_VOXWARE_TO_AMI((volume & 0xff00) >> 8); - custom.aud[1].audvol = sound.volume_right; - return (VOLUME_AMI_TO_VOXWARE(sound.volume_left) | - (VOLUME_AMI_TO_VOXWARE(sound.volume_right) << 8)); + sound.volume_left = VOLUME_VOXWARE_TO_AMI(volume & 0xff); + custom.aud[0].audvol = sound.volume_left; + sound.volume_right = VOLUME_VOXWARE_TO_AMI((volume & 0xff00) >> 8); + custom.aud[1].audvol = sound.volume_right; + return(VOLUME_AMI_TO_VOXWARE(sound.volume_left) | + (VOLUME_AMI_TO_VOXWARE(sound.volume_right) << 8)); } -static int -AmiSetTreble(int treble) +static int AmiSetTreble(int treble) { - sound.treble = treble; - if (treble < 50) - ciaa.pra &= ~0x02; - else - ciaa.pra |= 0x02; - return (treble); + sound.treble = treble; + if (treble < 50) + ciaa.pra &= ~0x02; + else + ciaa.pra |= 0x02; + return(treble); } @@ -2476,302 +2214,286 @@ AmiSetTreble(int treble) #define AMI_PLAY_MASK 3 -static void -ami_sq_play_next_frame(int index) +static void ami_sq_play_next_frame(int index) +{ + u_char *start, *ch0, *ch1, *ch2, *ch3; + u_long size; + + /* used by AmiPlay() if all doubts whether there really is something + * to be played are already wiped out. + */ + start = sq_block_address(sq.front); + size = (sq.count == index ? sq.rear_size : sq.block_size)>>1; + + if (sound.hard.stereo) { + ch0 = start; + ch1 = start+sq.block_size_half; + size >>= 1; + } else { + ch0 = start; + ch1 = start; + } + if (sound.hard.size == 8) { + custom.aud[0].audlc = (u_short *)ZTWO_PADDR(ch0); + custom.aud[0].audlen = size; + custom.aud[1].audlc = (u_short *)ZTWO_PADDR(ch1); + custom.aud[1].audlen = size; + custom.dmacon = AMI_AUDIO_8; + } else { + size >>= 1; + custom.aud[0].audlc = (u_short *)ZTWO_PADDR(ch0); + custom.aud[0].audlen = size; + custom.aud[1].audlc = (u_short *)ZTWO_PADDR(ch1); + custom.aud[1].audlen = size; + if (sound.volume_left == 64 && sound.volume_right == 64) { + /* We can play pseudo 14-bit only with the maximum volume */ + ch3 = ch0+sq.block_size_quarter; + ch2 = ch1+sq.block_size_quarter; + custom.aud[2].audvol = 1; /* we are being affected by the beeps */ + custom.aud[3].audvol = 1; /* restoring volume here helps a bit */ + custom.aud[2].audlc = (u_short *)ZTWO_PADDR(ch2); + custom.aud[2].audlen = size; + custom.aud[3].audlc = (u_short *)ZTWO_PADDR(ch3); + custom.aud[3].audlen = size; + custom.dmacon = AMI_AUDIO_14; + } else + custom.dmacon = AMI_AUDIO_8; + } + sq.front = (sq.front+1) % sq.max_count; + sq.playing |= AMI_PLAY_LOADED; +} + + +static void AmiPlay(void) { - u_char *start, *ch0, *ch1, *ch2, *ch3; - u_long size; + int minframes = 1; - /* used by AmiPlay() if all doubts whether there really is something - * to be played are already wiped out. - */ - start = sq_block_address(sq.front); - size = (sq.count == index ? sq.rear_size : sq.block_size) >> 1; - - if (sound.hard.stereo) - { - ch0 = start; - ch1 = start + sq.block_size_half; - size >>= 1; - } else - { - ch0 = start; - ch1 = start; - } - if (sound.hard.size == 8) - { - custom.aud[0].audlc = (u_short *) ZTWO_PADDR(ch0); - custom.aud[0].audlen = size; - custom.aud[1].audlc = (u_short *) ZTWO_PADDR(ch1); - custom.aud[1].audlen = size; - custom.dmacon = AMI_AUDIO_8; - } else - { - size >>= 1; - custom.aud[0].audlc = (u_short *) ZTWO_PADDR(ch0); - custom.aud[0].audlen = size; - custom.aud[1].audlc = (u_short *) ZTWO_PADDR(ch1); - custom.aud[1].audlen = size; - if (sound.volume_left == 64 && sound.volume_right == 64) - { - /* We can play pseudo 14-bit only with the maximum volume */ - ch3 = ch0 + sq.block_size_quarter; - ch2 = ch1 + sq.block_size_quarter; - custom.aud[2].audvol = 1; /* we are being affected by the beeps */ - custom.aud[3].audvol = 1; /* restoring volume here helps a bit */ - custom.aud[2].audlc = (u_short *) ZTWO_PADDR(ch2); - custom.aud[2].audlen = size; - custom.aud[3].audlc = (u_short *) ZTWO_PADDR(ch3); - custom.aud[3].audlen = size; - custom.dmacon = AMI_AUDIO_14; - } else - custom.dmacon = AMI_AUDIO_8; - } - sq.front = (sq.front + 1) % sq.max_count; - sq.playing |= AMI_PLAY_LOADED; -} - - -static void -AmiPlay(void) -{ - int minframes = 1; - - custom.intena = IF_AUD0; - - if (sq.playing & AMI_PLAY_LOADED) - { - /* There's already a frame loaded */ - custom.intena = IF_SETCLR | IF_AUD0; - return; - } - if (sq.playing & AMI_PLAY_PLAYING) - /* Increase threshold: frame 1 is already being played */ - minframes = 2; - - if (sq.count < minframes) - { - /* Nothing to do */ - custom.intena = IF_SETCLR | IF_AUD0; - return; - } - if (sq.count <= minframes && sq.rear_size < sq.block_size && !sq.syncing) - { - /* hmmm, the only existing frame is not - * yet filled and we're not syncing? - */ - custom.intena = IF_SETCLR | IF_AUD0; - return; - } - ami_sq_play_next_frame(minframes); + custom.intena = IF_AUD0; + if (sq.playing & AMI_PLAY_LOADED) { + /* There's already a frame loaded */ custom.intena = IF_SETCLR | IF_AUD0; + return; + } + + if (sq.playing & AMI_PLAY_PLAYING) + /* Increase threshold: frame 1 is already being played */ + minframes = 2; + + if (sq.count < minframes) { + /* Nothing to do */ + custom.intena = IF_SETCLR | IF_AUD0; + return; + } + + if (sq.count <= minframes && sq.rear_size < sq.block_size && !sq.syncing) { + /* hmmm, the only existing frame is not + * yet filled and we're not syncing? + */ + custom.intena = IF_SETCLR | IF_AUD0; + return; + } + + ami_sq_play_next_frame(minframes); + + custom.intena = IF_SETCLR | IF_AUD0; } -static void -ami_sq_interrupt(int irq, void *dummy, struct pt_regs *fp) +static void ami_sq_interrupt(int irq, void *dummy, struct pt_regs *fp) { - int minframes = 1; + int minframes = 1; + + if (!sq.playing) { + /* Playing was interrupted and sq_reset() has already cleared + * the sq variables, so better don't do anything here. + */ + WAKE_UP(sq.sync_queue); + return; + } + + if (sq.playing & AMI_PLAY_PLAYING) { + /* We've just finished a frame */ + sq.count--; + WAKE_UP(sq.write_queue); + } - if (!sq.playing) - { - /* Playing was interrupted and sq_reset() has already cleared - * the sq variables, so better don't do anything here. - */ - WAKE_UP(sq.sync_queue); - return; - } - if (sq.playing & AMI_PLAY_PLAYING) - { - /* We've just finished a frame */ - sq.count--; - WAKE_UP(sq.write_queue); - } - if (sq.playing & AMI_PLAY_LOADED) - /* Increase threshold: frame 1 is already being played */ - minframes = 2; + if (sq.playing & AMI_PLAY_LOADED) + /* Increase threshold: frame 1 is already being played */ + minframes = 2; - /* Shift the flags */ - sq.playing = (sq.playing << 1) & AMI_PLAY_MASK; + /* Shift the flags */ + sq.playing = (sq.playing<<1) & AMI_PLAY_MASK; - if (!sq.playing) - /* No frame is playing, disable audio DMA */ - custom.dmacon = AMI_AUDIO_OFF; + if (!sq.playing) + /* No frame is playing, disable audio DMA */ + custom.dmacon = AMI_AUDIO_OFF; - if (sq.count >= minframes) - /* Try to play the next frame */ - AmiPlay(); + if (sq.count >= minframes) + /* Try to play the next frame */ + AmiPlay(); - if (!sq.playing) - /* Nothing to play anymore. - Wake up a process waiting for audio output to drain. */ - WAKE_UP(sq.sync_queue); + if (!sq.playing) + /* Nothing to play anymore. + Wake up a process waiting for audio output to drain. */ + WAKE_UP(sq.sync_queue); } -#endif /* CONFIG_AMIGA */ +#endif /* CONFIG_AMIGA */ /*** Machine definitions *****************************************************/ #ifdef CONFIG_ATARI -static MACHINE machTT = -{ - DMASND_TT, AtaAlloc, AtaFree, AtaIrqInit, +static MACHINE machTT = { + DMASND_TT, AtaAlloc, AtaFree, AtaIrqInit, #ifdef MODULE - AtaIrqCleanUp, -#endif /* MODULE */ - TTInit, TTSilence, TTSetFormat, TTSetVolume, AtaSetBass, AtaSetTreble, - AtaPlay + AtaIrqCleanUp, +#endif /* MODULE */ + TTInit, TTSilence, TTSetFormat, TTSetVolume, AtaSetBass, AtaSetTreble, + TTSetGain, + AtaPlay }; -static MACHINE machFalcon = -{ - DMASND_FALCON, AtaAlloc, AtaFree, AtaIrqInit, +static MACHINE machFalcon = { + DMASND_FALCON, AtaAlloc, AtaFree, AtaIrqInit, #ifdef MODULE - AtaIrqCleanUp, -#endif /* MODULE */ - FalconInit, FalconSilence, FalconSetFormat, FalconSetVolume, AtaSetBass, - AtaSetTreble, AtaPlay + AtaIrqCleanUp, +#endif /* MODULE */ + FalconInit, FalconSilence, FalconSetFormat, FalconSetVolume, AtaSetBass, + AtaSetTreble, NULL, AtaPlay }; - -#endif /* CONFIG_ATARI */ +#endif /* CONFIG_ATARI */ #ifdef CONFIG_AMIGA -static MACHINE machAmiga = -{ - DMASND_AMIGA, AmiAlloc, AmiFree, AmiIrqInit, +static MACHINE machAmiga = { + DMASND_AMIGA, AmiAlloc, AmiFree, AmiIrqInit, #ifdef MODULE - AmiIrqCleanUp, -#endif /* MODULE */ - AmiInit, AmiSilence, AmiSetFormat, AmiSetVolume, NULL, AmiSetTreble, - AmiPlay + AmiIrqCleanUp, +#endif /* MODULE */ + AmiInit, AmiSilence, AmiSetFormat, AmiSetVolume, NULL, AmiSetTreble, + NULL, + AmiPlay }; - -#endif /* CONFIG_AMIGA */ +#endif /* CONFIG_AMIGA */ /*** Mid level stuff *********************************************************/ -static void -sound_silence(void) +static void sound_silence(void) { - /* update hardware settings one more */ - (*sound.mach.init) (); + /* update hardware settings one more */ + (*sound.mach.init)(); - (*sound.mach.silence) (); + (*sound.mach.silence)(); } -static void -sound_init(void) +static void sound_init(void) { - (*sound.mach.init) (); + (*sound.mach.init)(); } -static int -sound_set_format(int format) +static int sound_set_format(int format) { - return (*sound.mach.setFormat) (format); + return(*sound.mach.setFormat)(format); } -static int -sound_set_speed(int speed) +static int sound_set_speed(int speed) { - if (speed < 0) - return (sound.soft.speed); + if (speed < 0) + return(sound.soft.speed); - sound.soft.speed = speed; - (*sound.mach.init) (); - if (sound.minDev == SND_DEV_DSP) - sound.dsp.speed = sound.soft.speed; + sound.soft.speed = speed; + (*sound.mach.init)(); + if (sound.minDev == SND_DEV_DSP) + sound.dsp.speed = sound.soft.speed; - return (sound.soft.speed); + return(sound.soft.speed); } -static int -sound_set_stereo(int stereo) +static int sound_set_stereo(int stereo) { - if (stereo < 0) - return (sound.soft.stereo); + if (stereo < 0) + return(sound.soft.stereo); - stereo = !!stereo; /* should be 0 or 1 now */ + stereo = !!stereo; /* should be 0 or 1 now */ - sound.soft.stereo = stereo; - if (sound.minDev == SND_DEV_DSP) - sound.dsp.stereo = stereo; - (*sound.mach.init) (); + sound.soft.stereo = stereo; + if (sound.minDev == SND_DEV_DSP) + sound.dsp.stereo = stereo; + (*sound.mach.init)(); - return (stereo); + return(stereo); } -static int -sound_set_volume(int volume) +static int sound_set_volume(int volume) { - return (*sound.mach.setVolume) (volume); + return(*sound.mach.setVolume)(volume); } #ifdef CONFIG_ATARI -static int -sound_set_bass(int bass) -{ - return (sound.mach.setBass ? (*sound.mach.setBass) (bass) : 50); -} -#endif /* CONFIG_ATARI */ - - -static int -sound_set_treble(int treble) -{ - return (sound.mach.setTreble ? (*sound.mach.setTreble) (treble) : 50); -} - - -static long -sound_copy_translate(const u_char * userPtr, - unsigned long userCount, - u_char frame[], long *frameUsed, - long frameLeft) -{ - long (*ct_func) (const u_char *, unsigned long, u_char *, long *, long) = NULL; - - switch (sound.soft.format) - { - case AFMT_MU_LAW: - ct_func = sound.trans->ct_ulaw; - break; - case AFMT_A_LAW: - ct_func = sound.trans->ct_alaw; - break; - case AFMT_S8: - ct_func = sound.trans->ct_s8; - break; - case AFMT_U8: - ct_func = sound.trans->ct_u8; - break; - case AFMT_S16_BE: - ct_func = sound.trans->ct_s16be; - break; - case AFMT_U16_BE: - ct_func = sound.trans->ct_u16be; - break; - case AFMT_S16_LE: - ct_func = sound.trans->ct_s16le; - break; - case AFMT_U16_LE: - ct_func = sound.trans->ct_u16le; - break; - } - if (ct_func) - return (ct_func(userPtr, userCount, frame, frameUsed, frameLeft)); - else - return (0); +static int sound_set_bass(int bass) +{ + return(sound.mach.setBass ? (*sound.mach.setBass)(bass) : 50); +} + +static int sound_set_gain(int gain) +{ + return sound.mach.setGain ? sound.mach.setGain(gain) : 100; +} +#endif /* CONFIG_ATARI */ + + +static int sound_set_treble(int treble) +{ + return(sound.mach.setTreble ? (*sound.mach.setTreble)(treble) : 50); +} + + +static long sound_copy_translate(const u_char *userPtr, + unsigned long userCount, + u_char frame[], long *frameUsed, + long frameLeft) +{ + long (*ct_func)(const u_char *, unsigned long, u_char *, long *, long) = NULL; + + switch (sound.soft.format) { + case AFMT_MU_LAW: + ct_func = sound.trans->ct_ulaw; + break; + case AFMT_A_LAW: + ct_func = sound.trans->ct_alaw; + break; + case AFMT_S8: + ct_func = sound.trans->ct_s8; + break; + case AFMT_U8: + ct_func = sound.trans->ct_u8; + break; + case AFMT_S16_BE: + ct_func = sound.trans->ct_s16be; + break; + case AFMT_U16_BE: + ct_func = sound.trans->ct_u16be; + break; + case AFMT_S16_LE: + ct_func = sound.trans->ct_s16le; + break; + case AFMT_U16_LE: + ct_func = sound.trans->ct_u16le; + break; + } + if (ct_func) + return(ct_func(userPtr, userCount, frame, frameUsed, frameLeft)); + else + return(0); } @@ -2785,215 +2507,203 @@ sound_copy_translate(const u_char * userPtr, #define RECLEVEL_GAIN_TO_VOXWARE(v) (((v) * 20 + 2) / 3) -static void -mixer_init(void) +static void mixer_init(void) { - mixer.busy = 0; - sound.treble = 0; - sound.bass = 0; - switch (sound.mach.type) - { + mixer.busy = 0; + sound.treble = 0; + sound.bass = 0; + switch (sound.mach.type) { #ifdef CONFIG_ATARI - case DMASND_TT: - atari_microwire_cmd(MW_LM1992_VOLUME(0)); - sound.volume_left = 0; - atari_microwire_cmd(MW_LM1992_BALLEFT(0)); - sound.volume_right = 0; - atari_microwire_cmd(MW_LM1992_BALRIGHT(0)); - atari_microwire_cmd(MW_LM1992_TREBLE(0)); - atari_microwire_cmd(MW_LM1992_BASS(0)); - break; - case DMASND_FALCON: - sound.volume_left = (tt_dmasnd.output_atten & 0xf00) >> 8; - sound.volume_right = (tt_dmasnd.output_atten & 0xf0) >> 4; - break; -#endif /* CONFIG_ATARI */ + case DMASND_TT: + atari_microwire_cmd(MW_LM1992_VOLUME(0)); + sound.volume_left = 0; + atari_microwire_cmd(MW_LM1992_BALLEFT(0)); + sound.volume_right = 0; + atari_microwire_cmd(MW_LM1992_BALRIGHT(0)); + atari_microwire_cmd(MW_LM1992_TREBLE(0)); + atari_microwire_cmd(MW_LM1992_BASS(0)); + break; + case DMASND_FALCON: + sound.volume_left = (tt_dmasnd.output_atten & 0xf00) >> 8; + sound.volume_right = (tt_dmasnd.output_atten & 0xf0) >> 4; + break; +#endif /* CONFIG_ATARI */ #ifdef CONFIG_AMIGA - case DMASND_AMIGA: - sound.volume_left = 64; - sound.volume_right = 64; - custom.aud[0].audvol = sound.volume_left; - custom.aud[3].audvol = 1; /* For pseudo 14bit */ - custom.aud[1].audvol = sound.volume_right; - custom.aud[2].audvol = 1; /* For pseudo 14bit */ - sound.treble = 50; - break; -#endif /* CONFIG_AMIGA */ - } + case DMASND_AMIGA: + sound.volume_left = 64; + sound.volume_right = 64; + custom.aud[0].audvol = sound.volume_left; + custom.aud[3].audvol = 1; /* For pseudo 14bit */ + custom.aud[1].audvol = sound.volume_right; + custom.aud[2].audvol = 1; /* For pseudo 14bit */ + sound.treble = 50; + break; +#endif /* CONFIG_AMIGA */ + } } -static int -mixer_open(int open_mode) +static int mixer_open(int open_mode) { - if (mixer.busy) - return (-EBUSY); - mixer.busy = 1; - return (0); + if (mixer.busy) + return(-EBUSY); + mixer.busy = 1; + return(0); } -static int -mixer_release(void) +static int mixer_release(void) { - mixer.busy = 0; - return (0); + mixer.busy = 0; + return(0); } -static int -mixer_ioctl(struct inode *inode, struct file *file, u_int cmd, - u_long arg) +static int mixer_ioctl(struct inode *inode, struct file *file, u_int cmd, + u_long arg) { - int data; - - switch (sound.mach.type) - { + int data; + switch (sound.mach.type) { #ifdef CONFIG_ATARI - case DMASND_FALCON: - switch (cmd) + case DMASND_FALCON: + switch (cmd) { + case SOUND_MIXER_READ_DEVMASK: + return(IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_MIC | SOUND_MASK_SPEAKER)); + case SOUND_MIXER_READ_RECMASK: + return(IOCTL_OUT(arg, SOUND_MASK_MIC)); + case SOUND_MIXER_READ_STEREODEVS: + return(IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_MIC)); + case SOUND_MIXER_READ_CAPS: + return(IOCTL_OUT(arg, SOUND_CAP_EXCL_INPUT)); + case SOUND_MIXER_READ_VOLUME: + return(IOCTL_OUT(arg, + VOLUME_ATT_TO_VOXWARE(sound.volume_left) | + VOLUME_ATT_TO_VOXWARE(sound.volume_right) << 8)); + case SOUND_MIXER_WRITE_MIC: + IOCTL_IN(arg, data); + tt_dmasnd.input_gain = + RECLEVEL_VOXWARE_TO_GAIN(data & 0xff) << 4 | + RECLEVEL_VOXWARE_TO_GAIN(data >> 8 & 0xff); + /* fall thru, return set value */ + case SOUND_MIXER_READ_MIC: + return(IOCTL_OUT(arg, + RECLEVEL_GAIN_TO_VOXWARE(tt_dmasnd.input_gain >> 4 & 0xf) | + RECLEVEL_GAIN_TO_VOXWARE(tt_dmasnd.input_gain & 0xf) << 8)); + case SOUND_MIXER_READ_SPEAKER: { - case SOUND_MIXER_READ_DEVMASK: - return (IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_MIC | SOUND_MASK_SPEAKER)); - case SOUND_MIXER_READ_RECMASK: - return (IOCTL_OUT(arg, SOUND_MASK_MIC)); - case SOUND_MIXER_READ_STEREODEVS: - return (IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_MIC)); - case SOUND_MIXER_READ_CAPS: - return (IOCTL_OUT(arg, SOUND_CAP_EXCL_INPUT)); - case SOUND_MIXER_READ_VOLUME: - return (IOCTL_OUT(arg, - VOLUME_ATT_TO_VOXWARE(sound.volume_left) | - VOLUME_ATT_TO_VOXWARE(sound.volume_right) << 8)); - case SOUND_MIXER_WRITE_MIC: - IOCTL_IN(arg, data); - tt_dmasnd.input_gain = - RECLEVEL_VOXWARE_TO_GAIN(data & 0xff) << 4 | - RECLEVEL_VOXWARE_TO_GAIN(data >> 8 & 0xff); - /* fall thru, return set value */ - case SOUND_MIXER_READ_MIC: - return (IOCTL_OUT(arg, - RECLEVEL_GAIN_TO_VOXWARE(tt_dmasnd.input_gain >> 4 & 0xf) | - RECLEVEL_GAIN_TO_VOXWARE(tt_dmasnd.input_gain & 0xf) << 8)); - case SOUND_MIXER_READ_SPEAKER: - { - int porta; - - cli(); - sound_ym.rd_data_reg_sel = 14; - porta = sound_ym.rd_data_reg_sel; - sti(); - return (IOCTL_OUT(arg, porta & 0x40 ? 0 : 100)); - } - case SOUND_MIXER_WRITE_VOLUME: - IOCTL_IN(arg, data); - return (IOCTL_OUT(arg, sound_set_volume(data))); - case SOUND_MIXER_WRITE_SPEAKER: - { - int porta; - - IOCTL_IN(arg, data); - cli(); - sound_ym.rd_data_reg_sel = 14; - porta = (sound_ym.rd_data_reg_sel & ~0x40) | - (data < 50 ? 0x40 : 0); - sound_ym.wd_data = porta; - sti(); - return (IOCTL_OUT(arg, porta & 0x40 ? 0 : 100)); - } + int porta; + cli(); + sound_ym.rd_data_reg_sel = 14; + porta = sound_ym.rd_data_reg_sel; + sti(); + return(IOCTL_OUT(arg, porta & 0x40 ? 0 : 100)); } - break; - - case DMASND_TT: - switch (cmd) + case SOUND_MIXER_WRITE_VOLUME: + IOCTL_IN(arg, data); + return(IOCTL_OUT(arg, sound_set_volume(data))); + case SOUND_MIXER_WRITE_SPEAKER: { - case SOUND_MIXER_READ_DEVMASK: - return (IOCTL_OUT(arg, - SOUND_MASK_VOLUME | SOUND_MASK_TREBLE | SOUND_MASK_BASS | - ((atari_mch_cookie >> 16) == ATARI_MCH_TT ? - SOUND_MASK_SPEAKER : 0))); - case SOUND_MIXER_READ_RECMASK: - return (IOCTL_OUT(arg, 0)); - case SOUND_MIXER_READ_STEREODEVS: - return (IOCTL_OUT(arg, SOUND_MASK_VOLUME)); - case SOUND_MIXER_READ_VOLUME: - return (IOCTL_OUT(arg, - VOLUME_DB_TO_VOXWARE(sound.volume_left) | - (VOLUME_DB_TO_VOXWARE(sound.volume_right) << 8))); - case SOUND_MIXER_READ_BASS: - return (IOCTL_OUT(arg, TONE_DB_TO_VOXWARE(sound.bass))); - case SOUND_MIXER_READ_TREBLE: - return (IOCTL_OUT(arg, TONE_DB_TO_VOXWARE(sound.treble))); - case SOUND_MIXER_READ_SPEAKER: - { - int porta; - - if ((atari_mch_cookie >> 16) == ATARI_MCH_TT) - { - cli(); - sound_ym.rd_data_reg_sel = 14; - porta = sound_ym.rd_data_reg_sel; - sti(); - return (IOCTL_OUT(arg, porta & 0x40 ? 0 : 100)); - } else - return (-EINVAL); - } - case SOUND_MIXER_WRITE_VOLUME: - IOCTL_IN(arg, data); - return (IOCTL_OUT(arg, sound_set_volume(data))); - case SOUND_MIXER_WRITE_BASS: - IOCTL_IN(arg, data); - return (IOCTL_OUT(arg, sound_set_bass(data))); - case SOUND_MIXER_WRITE_TREBLE: - IOCTL_IN(arg, data); - return (IOCTL_OUT(arg, sound_set_treble(data))); - case SOUND_MIXER_WRITE_SPEAKER: - if ((atari_mch_cookie >> 16) == ATARI_MCH_TT) - { - int porta; - - IOCTL_IN(arg, data); - cli(); - sound_ym.rd_data_reg_sel = 14; - porta = (sound_ym.rd_data_reg_sel & ~0x40) | - (data < 50 ? 0x40 : 0); - sound_ym.wd_data = porta; - sti(); - return (IOCTL_OUT(arg, porta & 0x40 ? 0 : 100)); - } else - return (-EINVAL); + int porta; + IOCTL_IN(arg, data); + cli(); + sound_ym.rd_data_reg_sel = 14; + porta = (sound_ym.rd_data_reg_sel & ~0x40) | + (data < 50 ? 0x40 : 0); + sound_ym.wd_data = porta; + sti(); + return(IOCTL_OUT(arg, porta & 0x40 ? 0 : 100)); } - break; -#endif /* CONFIG_ATARI */ - -#ifdef CONFIG_AMIGA - case DMASND_AMIGA: - switch (cmd) + } + break; + + case DMASND_TT: + switch (cmd) { + case SOUND_MIXER_READ_DEVMASK: + return(IOCTL_OUT(arg, + SOUND_MASK_VOLUME | SOUND_MASK_TREBLE | SOUND_MASK_BASS | + (MACH_IS_TT ? SOUND_MASK_SPEAKER : 0))); + case SOUND_MIXER_READ_RECMASK: + return(IOCTL_OUT(arg, 0)); + case SOUND_MIXER_READ_STEREODEVS: + return(IOCTL_OUT(arg, SOUND_MASK_VOLUME)); + case SOUND_MIXER_READ_VOLUME: + return(IOCTL_OUT(arg, + VOLUME_DB_TO_VOXWARE(sound.volume_left) | + (VOLUME_DB_TO_VOXWARE(sound.volume_right) << 8))); + case SOUND_MIXER_READ_BASS: + return(IOCTL_OUT(arg, TONE_DB_TO_VOXWARE(sound.bass))); + case SOUND_MIXER_READ_TREBLE: + return(IOCTL_OUT(arg, TONE_DB_TO_VOXWARE(sound.treble))); + case SOUND_MIXER_READ_OGAIN: + return(IOCTL_OUT(arg, GAIN_DB_TO_VOXWARE(sound.gain))); + case SOUND_MIXER_READ_SPEAKER: { - case SOUND_MIXER_READ_DEVMASK: - return (IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_TREBLE)); - case SOUND_MIXER_READ_RECMASK: - return (IOCTL_OUT(arg, 0)); - case SOUND_MIXER_READ_STEREODEVS: - return (IOCTL_OUT(arg, SOUND_MASK_VOLUME)); - case SOUND_MIXER_READ_VOLUME: - return (IOCTL_OUT(arg, - VOLUME_AMI_TO_VOXWARE(sound.volume_left) | - VOLUME_AMI_TO_VOXWARE(sound.volume_right) << 8)); - case SOUND_MIXER_WRITE_VOLUME: - IOCTL_IN(arg, data); - return (IOCTL_OUT(arg, sound_set_volume(data))); - case SOUND_MIXER_READ_TREBLE: - return (IOCTL_OUT(arg, sound.treble)); - case SOUND_MIXER_WRITE_TREBLE: - IOCTL_IN(arg, data); - return (IOCTL_OUT(arg, sound_set_treble(data))); + int porta; + if (MACH_IS_TT) { + cli(); + sound_ym.rd_data_reg_sel = 14; + porta = sound_ym.rd_data_reg_sel; + sti(); + return(IOCTL_OUT(arg, porta & 0x40 ? 0 : 100)); + } else + return(-EINVAL); } - break; -#endif /* CONFIG_AMIGA */ - } + case SOUND_MIXER_WRITE_VOLUME: + IOCTL_IN(arg, data); + return(IOCTL_OUT(arg, sound_set_volume(data))); + case SOUND_MIXER_WRITE_BASS: + IOCTL_IN(arg, data); + return(IOCTL_OUT(arg, sound_set_bass(data))); + case SOUND_MIXER_WRITE_TREBLE: + IOCTL_IN(arg, data); + return(IOCTL_OUT(arg, sound_set_treble(data))); + case SOUND_MIXER_WRITE_OGAIN: + IOCTL_IN(arg, data); + return(IOCTL_OUT(arg, sound_set_gain(data))); + case SOUND_MIXER_WRITE_SPEAKER: + if (MACH_IS_TT) { + int porta; + IOCTL_IN(arg, data); + cli(); + sound_ym.rd_data_reg_sel = 14; + porta = (sound_ym.rd_data_reg_sel & ~0x40) | + (data < 50 ? 0x40 : 0); + sound_ym.wd_data = porta; + sti(); + return(IOCTL_OUT(arg, porta & 0x40 ? 0 : 100)); + } else + return(-EINVAL); + } + break; +#endif /* CONFIG_ATARI */ - return (-EINVAL); +#ifdef CONFIG_AMIGA + case DMASND_AMIGA: + switch (cmd) { + case SOUND_MIXER_READ_DEVMASK: + return(IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_TREBLE)); + case SOUND_MIXER_READ_RECMASK: + return(IOCTL_OUT(arg, 0)); + case SOUND_MIXER_READ_STEREODEVS: + return(IOCTL_OUT(arg, SOUND_MASK_VOLUME)); + case SOUND_MIXER_READ_VOLUME: + return(IOCTL_OUT(arg, + VOLUME_AMI_TO_VOXWARE(sound.volume_left) | + VOLUME_AMI_TO_VOXWARE(sound.volume_right) << 8)); + case SOUND_MIXER_WRITE_VOLUME: + IOCTL_IN(arg, data); + return(IOCTL_OUT(arg, sound_set_volume(data))); + case SOUND_MIXER_READ_TREBLE: + return(IOCTL_OUT(arg, sound.treble)); + case SOUND_MIXER_WRITE_TREBLE: + IOCTL_IN(arg, data); + return(IOCTL_OUT(arg, sound_set_treble(data))); + } + break; +#endif /* CONFIG_AMIGA */ + } + + return(-EINVAL); } @@ -3003,216 +2713,198 @@ mixer_ioctl(struct inode *inode, struct file *file, u_int cmd, */ -static void -sq_init(int numBufs, int bufSize, char **buffers) +static void sq_init(int numBufs, int bufSize, char **buffers) { - sq.max_count = numBufs; - sq.block_size = bufSize; - sq.buffers = buffers; + sq.max_count = numBufs; + sq.block_size = bufSize; + sq.buffers = buffers; - sq.front = sq.count = 0; - sq.rear = -1; - sq.write_queue = sq.open_queue = sq.sync_queue = 0; - sq.busy = 0; - sq.syncing = 0; + sq.front = sq.count = 0; + sq.rear = -1; + sq.write_queue = sq.open_queue = sq.sync_queue = 0; + sq.busy = 0; + sq.syncing = 0; - sq.playing = 0; + sq.playing = 0; #ifdef CONFIG_ATARI - sq.ignore_int = 0; -#endif /* CONFIG_ATARI */ + sq.ignore_int = 0; +#endif /* CONFIG_ATARI */ #ifdef CONFIG_AMIGA - sq.block_size_half = sq.block_size >> 1; - sq.block_size_quarter = sq.block_size_half >> 1; -#endif /* CONFIG_AMIGA */ - - sound_silence(); - - /* whatever you like as startup mode for /dev/dsp, - * (/dev/audio hasn't got a startup mode). note that - * once changed a new open() will *not* restore these! - */ - sound.dsp.format = AFMT_S8; - sound.dsp.stereo = 0; - sound.dsp.size = 8; - - /* set minimum rate possible without expanding */ - switch (sound.mach.type) - { + sq.block_size_half = sq.block_size>>1; + sq.block_size_quarter = sq.block_size_half>>1; +#endif /* CONFIG_AMIGA */ + + sound_silence(); + + /* whatever you like as startup mode for /dev/dsp, + * (/dev/audio hasn't got a startup mode). note that + * once changed a new open() will *not* restore these! + */ + sound.dsp.format = AFMT_S8; + sound.dsp.stereo = 0; + sound.dsp.size = 8; + + /* set minimum rate possible without expanding */ + switch (sound.mach.type) { #ifdef CONFIG_ATARI - case DMASND_TT: - sound.dsp.speed = 6258; - break; - case DMASND_FALCON: - sound.dsp.speed = 8195; - break; -#endif /* CONFIG_ATARI */ + case DMASND_TT: + sound.dsp.speed = 6258; + break; + case DMASND_FALCON: + sound.dsp.speed = 8195; + break; +#endif /* CONFIG_ATARI */ #ifdef CONFIG_AMIGA - case DMASND_AMIGA: - sound.dsp.speed = 8000; - break; -#endif /* CONFIG_AMIGA */ - } + case DMASND_AMIGA: + sound.dsp.speed = 8000; + break; +#endif /* CONFIG_AMIGA */ + } - /* before the first open to /dev/dsp this wouldn't be set */ - sound.soft = sound.dsp; - sound.hard = sound.dsp; + /* before the first open to /dev/dsp this wouldn't be set */ + sound.soft = sound.dsp; + sound.hard = sound.dsp; } -static void -sq_play(void) +static void sq_play(void) { - (*sound.mach.play) (); + (*sound.mach.play)(); } /* ++TeSche: radically changed this one too */ -static long -sq_write(const char *src, unsigned long uLeft) -{ - long uWritten = 0; - u_char *dest; - long uUsed, bUsed, bLeft; - - /* ++TeSche: Is something like this necessary? - * Hey, that's an honest question! Or does any other part of the - * filesystem already checks this situation? I really don't know. - */ - if (uLeft == 0) - return (0); +static long sq_write(const char *src, unsigned long uLeft) +{ + long uWritten = 0; + u_char *dest; + long uUsed, bUsed, bLeft; + + /* ++TeSche: Is something like this necessary? + * Hey, that's an honest question! Or does any other part of the + * filesystem already checks this situation? I really don't know. + */ + if (uLeft == 0) + return(0); + + /* The interrupt doesn't start to play the last, incomplete frame. + * Thus we can append to it without disabling the interrupts! (Note + * also that sq.rear isn't affected by the interrupt.) + */ + + if (sq.count > 0 && (bLeft = sq.block_size-sq.rear_size) > 0) { + dest = sq_block_address(sq.rear); + bUsed = sq.rear_size; + uUsed = sound_copy_translate(src, uLeft, dest, &bUsed, bLeft); + src += uUsed; + uWritten += uUsed; + uLeft -= uUsed; + sq.rear_size = bUsed; + } + + do { + while (sq.count == sq.max_count) { + sq_play(); + if (NON_BLOCKING(sq.open_mode)) + return(uWritten > 0 ? uWritten : -EAGAIN); + SLEEP(sq.write_queue, ONE_SECOND); + if (SIGNAL_RECEIVED) + return(uWritten > 0 ? uWritten : -EINTR); + } - /* The interrupt doesn't start to play the last, incomplete frame. - * Thus we can append to it without disabling the interrupts! (Note - * also that sq.rear isn't affected by the interrupt.) + /* Here, we can avoid disabling the interrupt by first + * copying and translating the data, and then updating + * the sq variables. Until this is done, the interrupt + * won't see the new frame and we can work on it + * undisturbed. */ - if (sq.count > 0 && (bLeft = sq.block_size - sq.rear_size) > 0) - { - dest = sq_block_address(sq.rear); - bUsed = sq.rear_size; - uUsed = sound_copy_translate(src, uLeft, dest, &bUsed, bLeft); - src += uUsed; - uWritten += uUsed; - uLeft -= uUsed; - sq.rear_size = bUsed; - } - do - { - while (sq.count == sq.max_count) - { - sq_play(); - if (NON_BLOCKING(sq.open_mode)) - return (uWritten > 0 ? uWritten : -EAGAIN); - SLEEP(sq.write_queue, ONE_SECOND); - if (SIGNAL_RECEIVED) - return (uWritten > 0 ? uWritten : -EINTR); - } - - /* Here, we can avoid disabling the interrupt by first - * copying and translating the data, and then updating - * the sq variables. Until this is done, the interrupt - * won't see the new frame and we can work on it - * undisturbed. - */ - - dest = sq_block_address((sq.rear + 1) % sq.max_count); - bUsed = 0; - bLeft = sq.block_size; - uUsed = sound_copy_translate(src, uLeft, dest, &bUsed, bLeft); - src += uUsed; - uWritten += uUsed; - uLeft -= uUsed; - if (bUsed) - { - sq.rear = (sq.rear + 1) % sq.max_count; - sq.rear_size = bUsed; - sq.count++; - } - } - while (bUsed); /* uUsed may have been 0 */ + dest = sq_block_address((sq.rear+1) % sq.max_count); + bUsed = 0; + bLeft = sq.block_size; + uUsed = sound_copy_translate(src, uLeft, dest, &bUsed, bLeft); + src += uUsed; + uWritten += uUsed; + uLeft -= uUsed; + if (bUsed) { + sq.rear = (sq.rear+1) % sq.max_count; + sq.rear_size = bUsed; + sq.count++; + } + } while (bUsed); /* uUsed may have been 0 */ - sq_play(); + sq_play(); - return (uWritten); + return(uWritten); } -static int -sq_open(int open_mode) +static int sq_open(int open_mode) { - if (sq.busy) - { - if (NON_BLOCKING(open_mode)) - return (-EBUSY); - while (sq.busy) - { - SLEEP(sq.open_queue, ONE_SECOND); - if (SIGNAL_RECEIVED) - return (-EINTR); - } - } - sq.open_mode = open_mode; - sq.busy = 1; + if (sq.busy) { + if (NON_BLOCKING(open_mode)) + return(-EBUSY); + while (sq.busy) { + SLEEP(sq.open_queue, ONE_SECOND); + if (SIGNAL_RECEIVED) + return(-EINTR); + } + } + sq.open_mode = open_mode; + sq.busy = 1; #ifdef CONFIG_ATARI - sq.ignore_int = 1; -#endif /* CONFIG_ATARI */ - return (0); + sq.ignore_int = 1; +#endif /* CONFIG_ATARI */ + return(0); } -static void -sq_reset(void) +static void sq_reset(void) { - sound_silence(); - sq.playing = 0; - sq.count = 0; - sq.front = (sq.rear + 1) % sq.max_count; + sound_silence(); + sq.playing = 0; + sq.count = 0; + sq.front = (sq.rear+1) % sq.max_count; } -static int -sq_sync(void) +static int sq_sync(void) { - int rc = 0; + int rc = 0; - sq.syncing = 1; - sq_play(); /* there may be an incomplete frame waiting */ + sq.syncing = 1; + sq_play(); /* there may be an incomplete frame waiting */ - while (sq.playing) - { - SLEEP(sq.sync_queue, ONE_SECOND); - if (SIGNAL_RECEIVED) - { - /* While waiting for audio output to drain, an interrupt occurred. - Stop audio output immediately and clear the queue. */ - sq_reset(); - rc = -EINTR; - break; - } - } + while (sq.playing) { + SLEEP(sq.sync_queue, ONE_SECOND); + if (SIGNAL_RECEIVED) { + /* While waiting for audio output to drain, an interrupt occurred. + Stop audio output immediately and clear the queue. */ + sq_reset(); + rc = -EINTR; + break; + } + } - sq.syncing = 0; - return (rc); + sq.syncing = 0; + return(rc); } -static int -sq_release(void) +static int sq_release(void) { - int rc = 0; - - if (sq.busy) - { - rc = sq_sync(); - sq.busy = 0; - WAKE_UP(sq.open_queue); - /* Wake up a process waiting for the queue being released. - Note: There may be several processes waiting for a call to open() - returning. */ - } - return (rc); + int rc = 0; + if (sq.busy) { + rc = sq_sync(); + sq.busy = 0; + WAKE_UP(sq.open_queue); + /* Wake up a process waiting for the queue being released. + Note: There may be several processes waiting for a call to open() + returning. */ + } + return(rc); } @@ -3222,136 +2914,128 @@ sq_release(void) */ -static void -state_init(void) +static void state_init(void) { - state.busy = 0; + state.busy = 0; } /* state.buf should not overflow! */ -static int -state_open(int open_mode) +static int state_open(int open_mode) { - char *buffer = state.buf, *mach = ""; - int len = 0; + char *buffer = state.buf, *mach = ""; + int len = 0; - if (state.busy) - return (-EBUSY); + if (state.busy) + return(-EBUSY); - state.ptr = 0; - state.busy = 1; + state.ptr = 0; + state.busy = 1; - switch (sound.mach.type) - { + switch (sound.mach.type) { #ifdef CONFIG_ATARI - case DMASND_TT: - case DMASND_FALCON: - mach = "Atari "; - break; -#endif /* CONFIG_ATARI */ + case DMASND_TT: + case DMASND_FALCON: + mach = "Atari "; + break; +#endif /* CONFIG_ATARI */ #ifdef CONFIG_AMIGA - case DMASND_AMIGA: - mach = "Amiga "; - break; -#endif /* CONFIG_AMIGA */ - } - len += sprintf(buffer + len, "%sDMA sound driver:\n", mach); - - len += sprintf(buffer + len, "\tsound.format = 0x%x", sound.soft.format); - switch (sound.soft.format) - { - case AFMT_MU_LAW: - len += sprintf(buffer + len, " (mu-law)"); - break; - case AFMT_A_LAW: - len += sprintf(buffer + len, " (A-law)"); - break; - case AFMT_U8: - len += sprintf(buffer + len, " (unsigned 8 bit)"); - break; - case AFMT_S8: - len += sprintf(buffer + len, " (signed 8 bit)"); - break; - case AFMT_S16_BE: - len += sprintf(buffer + len, " (signed 16 bit big)"); - break; - case AFMT_U16_BE: - len += sprintf(buffer + len, " (unsigned 16 bit big)"); - break; - case AFMT_S16_LE: - len += sprintf(buffer + len, " (signed 16 bit little)"); - break; - case AFMT_U16_LE: - len += sprintf(buffer + len, " (unsigned 16 bit little)"); - break; - } - len += sprintf(buffer + len, "\n"); - len += sprintf(buffer + len, "\tsound.speed = %dHz (phys. %dHz)\n", - sound.soft.speed, sound.hard.speed); - len += sprintf(buffer + len, "\tsound.stereo = 0x%x (%s)\n", - sound.soft.stereo, sound.soft.stereo ? "stereo" : "mono"); - switch (sound.mach.type) - { + case DMASND_AMIGA: + mach = "Amiga "; + break; +#endif /* CONFIG_AMIGA */ + } + len += sprintf(buffer+len, "%sDMA sound driver:\n", mach); + + len += sprintf(buffer+len, "\tsound.format = 0x%x", sound.soft.format); + switch (sound.soft.format) { + case AFMT_MU_LAW: + len += sprintf(buffer+len, " (mu-law)"); + break; + case AFMT_A_LAW: + len += sprintf(buffer+len, " (A-law)"); + break; + case AFMT_U8: + len += sprintf(buffer+len, " (unsigned 8 bit)"); + break; + case AFMT_S8: + len += sprintf(buffer+len, " (signed 8 bit)"); + break; + case AFMT_S16_BE: + len += sprintf(buffer+len, " (signed 16 bit big)"); + break; + case AFMT_U16_BE: + len += sprintf(buffer+len, " (unsigned 16 bit big)"); + break; + case AFMT_S16_LE: + len += sprintf(buffer+len, " (signed 16 bit little)"); + break; + case AFMT_U16_LE: + len += sprintf(buffer+len, " (unsigned 16 bit little)"); + break; + } + len += sprintf(buffer+len, "\n"); + len += sprintf(buffer+len, "\tsound.speed = %dHz (phys. %dHz)\n", + sound.soft.speed, sound.hard.speed); + len += sprintf(buffer+len, "\tsound.stereo = 0x%x (%s)\n", + sound.soft.stereo, sound.soft.stereo ? "stereo" : "mono"); + switch (sound.mach.type) { #ifdef CONFIG_ATARI - case DMASND_TT: - len += sprintf(buffer + len, "\tsound.volume_left = %ddB [-40...0]\n", - sound.volume_left); - len += sprintf(buffer + len, "\tsound.volume_right = %ddB [-40...0]\n", - sound.volume_right); - len += sprintf(buffer + len, "\tsound.bass = %ddB [-12...+12]\n", - sound.bass); - len += sprintf(buffer + len, "\tsound.treble = %ddB [-12...+12]\n", - sound.treble); - break; - case DMASND_FALCON: - len += sprintf(buffer + len, "\tsound.volume_left = %ddB [-22.5...0]\n", - sound.volume_left); - len += sprintf(buffer + len, "\tsound.volume_right = %ddB [-22.5...0]\n", - sound.volume_right); - break; -#endif /* CONFIG_ATARI */ + case DMASND_TT: + len += sprintf(buffer+len, "\tsound.volume_left = %ddB [-40...0]\n", + sound.volume_left); + len += sprintf(buffer+len, "\tsound.volume_right = %ddB [-40...0]\n", + sound.volume_right); + len += sprintf(buffer+len, "\tsound.bass = %ddB [-12...+12]\n", + sound.bass); + len += sprintf(buffer+len, "\tsound.treble = %ddB [-12...+12]\n", + sound.treble); + break; + case DMASND_FALCON: + len += sprintf(buffer+len, "\tsound.volume_left = %ddB [-22.5...0]\n", + sound.volume_left); + len += sprintf(buffer+len, "\tsound.volume_right = %ddB [-22.5...0]\n", + sound.volume_right); + break; +#endif /* CONFIG_ATARI */ #ifdef CONFIG_AMIGA - case DMASND_AMIGA: - len += sprintf(buffer + len, "\tsound.volume_left = %d [0...64]\n", - sound.volume_left); - len += sprintf(buffer + len, "\tsound.volume_right = %d [0...64]\n", - sound.volume_right); - break; -#endif /* CONFIG_AMIGA */ - } - len += sprintf(buffer + len, "\tsq.block_size = %d sq.max_count = %d\n", - sq.block_size, sq.max_count); - len += sprintf(buffer + len, "\tsq.count = %d sq.rear_size = %d\n", sq.count, - sq.rear_size); - len += sprintf(buffer + len, "\tsq.playing = %d sq.syncing = %d\n", - sq.playing, sq.syncing); - state.len = len; - return (0); + case DMASND_AMIGA: + len += sprintf(buffer+len, "\tsound.volume_left = %d [0...64]\n", + sound.volume_left); + len += sprintf(buffer+len, "\tsound.volume_right = %d [0...64]\n", + sound.volume_right); + break; +#endif /* CONFIG_AMIGA */ + } + len += sprintf(buffer+len, "\tsq.block_size = %d sq.max_count = %d\n", + sq.block_size, sq.max_count); + len += sprintf(buffer+len, "\tsq.count = %d sq.rear_size = %d\n", sq.count, + sq.rear_size); + len += sprintf(buffer+len, "\tsq.playing = %d sq.syncing = %d\n", + sq.playing, sq.syncing); + state.len = len; + return(0); } -static int -state_release(void) +static int state_release(void) { - state.busy = 0; - return (0); + state.busy = 0; + return(0); } -static long -state_read(char *dest, unsigned long count) +static long state_read(char *dest, unsigned long count) { - int n = state.len - state.ptr; - - if (n > count) - n = count; - if (n <= 0) - return (0); - copy_to_user(dest, &state.buf[state.ptr], n); - state.ptr += n; - return (n); + int n = state.len-state.ptr; + if (n > count) + n = count; + if (n <= 0) + return(0); + copy_to_user(dest, &state.buf[state.ptr], n); + state.ptr += n; + return(n); } @@ -3359,241 +3043,232 @@ state_read(char *dest, unsigned long count) /*** High level stuff ********************************************************/ -static int -sound_open(struct inode *inode, struct file *file) -{ - int dev = MINOR(inode->i_rdev) & 0x0f; - int rc = 0; - - switch (dev) - { - case SND_DEV_STATUS: - rc = state_open(file->f_flags); - break; - case SND_DEV_CTL: - rc = mixer_open(file->f_flags); - break; - case SND_DEV_DSP: - case SND_DEV_AUDIO: - rc = sq_open(file->f_flags); - if (rc == 0) - { - sound.minDev = dev; - sound.soft = sound.dsp; - sound.hard = sound.dsp; - sound_init(); - if (dev == SND_DEV_AUDIO) - { - sound_set_speed(8000); - sound_set_stereo(0); - sound_set_format(AFMT_MU_LAW); - } - } - break; - default: - rc = -ENXIO; - } +static int sound_open(struct inode *inode, struct file *file) +{ + int dev = MINOR(inode->i_rdev) & 0x0f; + int rc = 0; + + switch (dev) { + case SND_DEV_STATUS: + rc = state_open(file->f_flags); + break; + case SND_DEV_CTL: + rc = mixer_open(file->f_flags); + break; + case SND_DEV_DSP: + case SND_DEV_AUDIO: + rc = sq_open(file->f_flags); + if (rc == 0) { + sound.minDev = dev; + sound.soft = sound.dsp; + sound.hard = sound.dsp; + sound_init(); + if (dev == SND_DEV_AUDIO) { + sound_set_speed(8000); + sound_set_stereo(0); + sound_set_format(AFMT_MU_LAW); + } + } + break; + default: + rc = -ENXIO; + } #ifdef MODULE - if (rc >= 0) - MOD_INC_USE_COUNT; + if (rc >= 0) + MOD_INC_USE_COUNT; #endif - return (rc); -} - - -static int -sound_fsync(struct inode *inode, struct file *filp) -{ - int dev = MINOR(inode->i_rdev) & 0x0f; - - switch (dev) - { - case SND_DEV_STATUS: - case SND_DEV_CTL: - return (0); - case SND_DEV_DSP: - case SND_DEV_AUDIO: - return (sq_sync()); - default: - return (unknown_minor_dev("sound_fsync", dev)); - } -} - - -static void -sound_release(struct inode *inode, struct file *file) -{ - int dev = MINOR(inode->i_rdev); - - switch (dev & 0x0f) - { - case SND_DEV_STATUS: - state_release(); - break; - case SND_DEV_CTL: - mixer_release(); - break; - case SND_DEV_DSP: - case SND_DEV_AUDIO: - sq_release(); - sound.soft = sound.dsp; - sound.hard = sound.dsp; - sound_silence(); - break; - default: - unknown_minor_dev("sound_release", dev); - return; - } + return(rc); +} + + +static int sound_fsync(struct file *filp, struct dentry *dentry) +{ + int dev = MINOR(dentry->d_inode->i_rdev) & 0x0f; + + switch (dev) { + case SND_DEV_STATUS: + case SND_DEV_CTL: + return(0); + case SND_DEV_DSP: + case SND_DEV_AUDIO: + return(sq_sync()); + default: + return(unknown_minor_dev("sound_fsync", dev)); + } +} + + +static int sound_release(struct inode *inode, struct file *file) +{ + int dev = MINOR(inode->i_rdev); + + switch (dev & 0x0f) { + case SND_DEV_STATUS: + state_release(); + break; + case SND_DEV_CTL: + mixer_release(); + break; + case SND_DEV_DSP: + case SND_DEV_AUDIO: + sq_release(); + sound.soft = sound.dsp; + sound.hard = sound.dsp; + sound_silence(); + break; + default: + return unknown_minor_dev("sound_release", dev); + } #ifdef MODULE - MOD_DEC_USE_COUNT; + MOD_DEC_USE_COUNT; #endif + return 0; } -static long long -sound_lseek(struct inode *inode, struct file *file, - long long offset, int orig) +static long long sound_lseek(struct file *file, long long offset, int orig) { - return -ESPIPE; + return -ESPIPE; } -static ssize_t sound_read(struct file *file, char *buf, szie_t count, loff_t *ppos) +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); + struct inode *inode = file->f_dentry->d_inode; + int dev = MINOR(inode->i_rdev); - switch (dev & 0x0f) - { - case SND_DEV_STATUS: - return (state_read(buf, count)); - case SND_DEV_CTL: - case SND_DEV_DSP: - case SND_DEV_AUDIO: - return (-EPERM); - default: - return (unknown_minor_dev("sound_read", dev)); - } + switch (dev & 0x0f) { + case SND_DEV_STATUS: + return(state_read(buf, count)); + case SND_DEV_CTL: + case SND_DEV_DSP: + case SND_DEV_AUDIO: + return(-EPERM); + default: + return(unknown_minor_dev("sound_read", dev)); + } } -static ssize_t sound_write(struct file *file, const char *buf, size_t count, loff_t *ppos) +static ssize_t sound_write(struct file *file, const char *buf, size_t count, + loff_t *ppos) { - int dev = MINOR(file->f_dentry->d_inode->i_rdev); + struct inode *inode = file->f_dentry->d_inode; + int dev = MINOR(inode->i_rdev); - switch (dev & 0x0f) - { - case SND_DEV_STATUS: - case SND_DEV_CTL: - return (-EPERM); - case SND_DEV_DSP: - case SND_DEV_AUDIO: - return (sq_write(buf, count)); - default: - return (unknown_minor_dev("sound_write", dev)); - } + switch (dev & 0x0f) { + case SND_DEV_STATUS: + case SND_DEV_CTL: + return(-EPERM); + case SND_DEV_DSP: + case SND_DEV_AUDIO: + return(sq_write(buf, count)); + default: + return(unknown_minor_dev("sound_write", dev)); + } } static int unknown_minor_dev(char *fname, int dev) { - /* printk("%s: Unknown minor device %d\n", fname, dev); */ - return (-ENXIO); -} - - -static int sound_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long arg) -{ - int dev = MINOR(inode->i_rdev); - u_long fmt; - int data; - - switch (dev & 0x0f) - { - case SND_DEV_STATUS: - return (-EPERM); - case SND_DEV_CTL: - return (mixer_ioctl(inode, file, cmd, arg)); - case SND_DEV_AUDIO: - case SND_DEV_DSP: - switch (cmd) - { - case SNDCTL_DSP_RESET: - sq_reset(); - return (0); - case SNDCTL_DSP_POST: - case SNDCTL_DSP_SYNC: - return (sound_fsync(inode, file)); - - /* ++TeSche: before changing any of these it's probably wise to - * wait until sound playing has settled down - */ - case SNDCTL_DSP_SPEED: - sound_fsync(inode, file); - IOCTL_IN(arg, data); - return (IOCTL_OUT(arg, sound_set_speed(data))); - case SNDCTL_DSP_STEREO: - sound_fsync(inode, file); - IOCTL_IN(arg, data); - return (IOCTL_OUT(arg, sound_set_stereo(data))); - case SOUND_PCM_WRITE_CHANNELS: - sound_fsync(inode, file); - IOCTL_IN(arg, data); - return (IOCTL_OUT(arg, sound_set_stereo(data - 1) + 1)); - case SNDCTL_DSP_SETFMT: - sound_fsync(inode, file); - IOCTL_IN(arg, data); - return (IOCTL_OUT(arg, sound_set_format(data))); - case SNDCTL_DSP_GETFMTS: - fmt = 0; - if (sound.trans) - { - if (sound.trans->ct_ulaw) - fmt |= AFMT_MU_LAW; - if (sound.trans->ct_alaw) - fmt |= AFMT_A_LAW; - if (sound.trans->ct_s8) - fmt |= AFMT_S8; - if (sound.trans->ct_u8) - fmt |= AFMT_U8; - if (sound.trans->ct_s16be) - fmt |= AFMT_S16_BE; - if (sound.trans->ct_u16be) - fmt |= AFMT_U16_BE; - if (sound.trans->ct_s16le) - fmt |= AFMT_S16_LE; - if (sound.trans->ct_u16le) - fmt |= AFMT_U16_LE; - } - return (IOCTL_OUT(arg, fmt)); - case SNDCTL_DSP_GETBLKSIZE: - return (IOCTL_OUT(arg, 10240)); - case SNDCTL_DSP_SUBDIVIDE: - case SNDCTL_DSP_SETFRAGMENT: - break; - default: - return (mixer_ioctl(inode, file, cmd, arg)); - } - break; + /* printk("%s: Unknown minor device %d\n", fname, dev); */ + return(-ENXIO); +} + + +static int sound_ioctl(struct inode *inode, struct file *file, u_int cmd, + u_long arg) +{ + int dev = MINOR(inode->i_rdev); + u_long fmt; + int data; + + switch (dev & 0x0f) { + case SND_DEV_STATUS: + return(-EPERM); + case SND_DEV_CTL: + return(mixer_ioctl(inode, file, cmd, arg)); + case SND_DEV_AUDIO: + case SND_DEV_DSP: + switch (cmd) { + case SNDCTL_DSP_RESET: + sq_reset(); + return(0); + case SNDCTL_DSP_POST: + case SNDCTL_DSP_SYNC: + return(sound_fsync(file, file->f_dentry)); + + /* ++TeSche: before changing any of these it's probably wise to + * wait until sound playing has settled down + */ + case SNDCTL_DSP_SPEED: + sound_fsync(file, file->f_dentry); + IOCTL_IN(arg, data); + return(IOCTL_OUT(arg, sound_set_speed(data))); + case SNDCTL_DSP_STEREO: + sound_fsync(file, file->f_dentry); + IOCTL_IN(arg, data); + return(IOCTL_OUT(arg, sound_set_stereo(data))); + case SOUND_PCM_WRITE_CHANNELS: + sound_fsync(file, file->f_dentry); + IOCTL_IN(arg, data); + return(IOCTL_OUT(arg, sound_set_stereo(data-1)+1)); + case SNDCTL_DSP_SETFMT: + sound_fsync(file, file->f_dentry); + IOCTL_IN(arg, data); + return(IOCTL_OUT(arg, sound_set_format(data))); + case SNDCTL_DSP_GETFMTS: + fmt = 0; + if (sound.trans) { + if (sound.trans->ct_ulaw) + fmt |= AFMT_MU_LAW; + if (sound.trans->ct_alaw) + fmt |= AFMT_A_LAW; + if (sound.trans->ct_s8) + fmt |= AFMT_S8; + if (sound.trans->ct_u8) + fmt |= AFMT_U8; + if (sound.trans->ct_s16be) + fmt |= AFMT_S16_BE; + if (sound.trans->ct_u16be) + fmt |= AFMT_U16_BE; + if (sound.trans->ct_s16le) + fmt |= AFMT_S16_LE; + if (sound.trans->ct_u16le) + fmt |= AFMT_U16_LE; + } + return(IOCTL_OUT(arg, fmt)); + case SNDCTL_DSP_GETBLKSIZE: + return(IOCTL_OUT(arg, 10240)); + case SNDCTL_DSP_SUBDIVIDE: + case SNDCTL_DSP_SETFRAGMENT: + break; default: - return (unknown_minor_dev("sound_ioctl", dev)); - } - return (-EINVAL); + return(mixer_ioctl(inode, file, cmd, arg)); + } + break; + + default: + return(unknown_minor_dev("sound_ioctl", dev)); + } + return(-EINVAL); } static struct file_operations sound_fops = { - sound_lseek, - sound_read, - sound_write, - NULL, - NULL, /* select */ - sound_ioctl, - NULL, - sound_open, - sound_release, - sound_fsync + sound_lseek, + sound_read, + sound_write, + NULL, + NULL, /* select */ + sound_ioctl, + NULL, + sound_open, + sound_release, + sound_fsync }; @@ -3601,186 +3276,171 @@ static struct file_operations sound_fops = /*** Config & Setup **********************************************************/ -void -soundcard_init(void) +void soundcard_init(void) { - int has_sound = 0; - int i; + int has_sound = 0; + int i; - switch (m68k_machtype) - { + switch (m68k_machtype) { #ifdef CONFIG_ATARI - case MACH_ATARI: - if (ATARIHW_PRESENT(PCM_8BIT)) - { - if (ATARIHW_PRESENT(CODEC)) - sound.mach = machFalcon; - else if (ATARIHW_PRESENT(MICROWIRE)) - sound.mach = machTT; - else - break; - if ((mfp.int_en_a & mfp.int_mk_a & 0x20) == 0) - has_sound = 1; - else - printk(KERN_ERR "DMA sound driver: Timer A interrupt already in use\n"); - } - break; - -#endif /* CONFIG_ATARI */ + case MACH_ATARI: + if (ATARIHW_PRESENT(PCM_8BIT)) { + if (ATARIHW_PRESENT(CODEC)) + sound.mach = machFalcon; + else if (ATARIHW_PRESENT(MICROWIRE)) + sound.mach = machTT; + else + break; + if ((mfp.int_en_a & mfp.int_mk_a & 0x20) == 0) + has_sound = 1; + else + printk("DMA sound driver: Timer A interrupt already in use\n"); + } + break; + +#endif /* CONFIG_ATARI */ #ifdef CONFIG_AMIGA - case MACH_AMIGA: - if (AMIGAHW_PRESENT(AMI_AUDIO)) - { - sound.mach = machAmiga; - has_sound = 1; - } - break; -#endif /* CONFIG_AMIGA */ - } - if (!has_sound) - return; - - /* Set up sound queue, /dev/audio and /dev/dsp. */ - sound_buffers = kmalloc(numBufs * sizeof(char *), GFP_KERNEL); + case MACH_AMIGA: + if (AMIGAHW_PRESENT(AMI_AUDIO)) { + sound.mach = machAmiga; + has_sound = 1; + } + break; +#endif /* CONFIG_AMIGA */ + } + if (!has_sound) + return; - if (!sound_buffers) - { + /* Set up sound queue, /dev/audio and /dev/dsp. */ + sound_buffers = kmalloc (numBufs * sizeof(char *), GFP_KERNEL); + if (!sound_buffers) { out_of_memory: - printk(KERN_ERR "DMA sound driver: Not enough buffer memory, driver disabled!\n"); - return; - } - for (i = 0; i < numBufs; i++) - { - sound_buffers[i] = sound.mach.dma_alloc(bufSize << 10, GFP_KERNEL); - if (!sound_buffers[i]) - { - while (i--) - sound.mach.dma_free(sound_buffers[i], bufSize << 10); - kfree(sound_buffers); - sound_buffers = 0; - goto out_of_memory; - } - } + printk("DMA sound driver: Not enough buffer memory, driver disabled!\n"); + return; + } + for (i = 0; i < numBufs; i++) { + sound_buffers[i] = sound.mach.dma_alloc (bufSize << 10, GFP_KERNEL); + if (!sound_buffers[i]) { + while (i--) + sound.mach.dma_free (sound_buffers[i], bufSize << 10); + kfree (sound_buffers); + sound_buffers = 0; + goto out_of_memory; + } + } #ifndef MODULE - /* Register driver with the VFS. */ - register_chrdev(SOUND_MAJOR, "sound", &sound_fops); + /* Register driver with the VFS. */ + register_chrdev(SOUND_MAJOR, "sound", &sound_fops); #endif - sq_init(numBufs, bufSize << 10, sound_buffers); + sq_init(numBufs, bufSize << 10, sound_buffers); - /* Set up /dev/sndstat. */ - state_init(); + /* Set up /dev/sndstat. */ + state_init(); - /* Set up /dev/mixer. */ - mixer_init(); + /* Set up /dev/mixer. */ + mixer_init(); - if (!sound.mach.irqinit()) - { - printk(KERN_ERR "DMA sound driver: Interrupt initialization failed\n"); - return; - } + if (!sound.mach.irqinit()) { + printk("DMA sound driver: Interrupt initialization failed\n"); + return; + } #ifdef MODULE - irq_installed = 1; + irq_installed = 1; #endif - printk(KERN_INFO "DMA sound driver installed, using %d buffers of %dk.\n", numBufs, - bufSize); + printk("DMA sound driver installed, using %d buffers of %dk.\n", numBufs, + bufSize); - return; + return; } void sound_setup(char *str, int *ints) { - /* ++Martin: stub, could possibly be merged with soundcard.c et al later */ + /* ++Martin: stub, could possibly be merged with soundcard.c et al later */ } #define MAXARGS 8 /* Should be sufficient for now */ -void -dmasound_setup(char *str, int *ints) -{ - /* check the bootstrap parameter for "dmasound=" */ - - switch (ints[0]) - { - case 3: - if ((ints[3] < 0) || (ints[3] > MAX_CATCH_RADIUS)) - printk(KERN_WARNING "dmasound_setup: illegal catch radius, using default = %d\n", catchRadius); - else - catchRadius = ints[3]; - /* fall through */ - case 2: - if (ints[1] < MIN_BUFFERS) - printk(KERN_WARNING "dmasound_setup: illegal number of buffers, using default = %d\n", numBufs); - else - numBufs = ints[1]; - if (ints[2] < MIN_BUFSIZE || ints[2] > MAX_BUFSIZE) - printk(KERN_WARNING "dmasound_setup: illegal buffer size, using default = %d\n", bufSize); - else - bufSize = ints[2]; - break; - case 0: - break; - default: - printk(KERN_WARNING "dmasound_setup: illegal number of arguments\n"); - } +void dmasound_setup(char *str, int *ints) +{ + /* check the bootstrap parameter for "dmasound=" */ + + switch (ints[0]) { + case 3: + if ((ints[3] < 0) || (ints[3] > MAX_CATCH_RADIUS)) + printk("dmasound_setup: illegal catch radius, using default = %d\n", catchRadius); + else + catchRadius = ints[3]; + /* fall through */ + case 2: + if (ints[1] < MIN_BUFFERS) + printk("dmasound_setup: illegal number of buffers, using default = %d\n", numBufs); + else + numBufs = ints[1]; + if (ints[2] < MIN_BUFSIZE || ints[2] > MAX_BUFSIZE) + printk("dmasound_setup: illegal buffer size, using default = %d\n", bufSize); + else + bufSize = ints[2]; + break; + case 0: + break; + default: + printk("dmasound_setup: illegal number of arguments\n"); + } } #ifdef MODULE -static int dmasound[MAXARGS] = { - 0 -}; +static int dmasound[MAXARGS] = { 0 }; int init_module(void) { - int err, i = 0; - int ints[MAXARGS + 1]; + int err, i = 0; + int ints[MAXARGS+1]; - while (i < MAXARGS && dmasound[i]) - ints[i + 1] = dmasound[i++]; - ints[0] = i; + while (i < MAXARGS && dmasound[i]) + ints[i + 1] = dmasound[i++]; + ints[0] = i; - if (i) - dmasound_setup("dmasound=", ints); + if (i) + dmasound_setup("dmasound=", ints); - err = register_chrdev(SOUND_MAJOR, "sound", &sound_fops); - if (err) - { - printk(KERN_ERR "dmasound: driver already loaded/included in kernel\n"); - return err; - } - chrdev_registered = 1; - soundcard_init(); + err = register_chrdev(SOUND_MAJOR, "sound", &sound_fops); + if (err) { + printk("dmasound: driver already loaded/included in kernel\n"); + return err; + } + chrdev_registered = 1; + soundcard_init(); - return 0; + return 0; } void cleanup_module(void) { - int i; + int i; - if (MOD_IN_USE) - return; + if (MOD_IN_USE) + return; - if (chrdev_registered) - unregister_chrdev(SOUND_MAJOR, "sound"); + if (chrdev_registered) + unregister_chrdev(SOUND_MAJOR, "sound"); - if (irq_installed) - { - sound_silence(); - sound.mach.irqcleanup(); - } - if (sound_buffers) - { - for (i = 0; i < numBufs; i++) - sound.mach.dma_free(sound_buffers[i], bufSize << 10); - kfree(sound_buffers); - } + if (irq_installed) { + sound_silence(); + sound.mach.irqcleanup(); + } + + if (sound_buffers) { + for (i = 0; i < numBufs; i++) + sound.mach.dma_free(sound_buffers[i], bufSize << 10); + kfree(sound_buffers); + } } -#endif /* MODULE */ +#endif /* MODULE */ diff --git a/drivers/sound/gus_card.c b/drivers/sound/gus_card.c index 92e6dbab6..62d10257d 100644 --- a/drivers/sound/gus_card.c +++ b/drivers/sound/gus_card.c @@ -3,6 +3,7 @@ * * Detection routine for the Gravis Ultrasound. */ + /* * Copyright (C) by Hannu Savolainen 1993-1997 * @@ -10,6 +11,15 @@ * 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. + * + * Status: + * Tested... + */ + + #include <linux/config.h> #include <linux/module.h> @@ -23,14 +33,19 @@ void gusintr(int irq, void *dev_id, struct pt_regs *dummy); int gus_base = 0, gus_irq = 0, gus_dma = 0; +int gus_no_wave_dma = 0; extern int gus_wave_volume; extern int gus_pcm_volume; extern int have_gus_max; int gus_pnp_flag = 0; +#ifdef CONFIG_GUS16 +static int db16 = 0; /* Has a Gus16 AD1848 on it */ +#endif void attach_gus_card(struct address_info *hw_config) { - snd_set_irq_handler(hw_config->irq, gusintr, "Gravis Ultrasound", hw_config->osp, 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); gus_wave_init(hw_config); @@ -38,10 +53,10 @@ void attach_gus_card(struct address_info *hw_config) request_region(hw_config->io_base + 0x100, 12, "GUS"); /* 0x10c-> is MAX */ if (sound_alloc_dma(hw_config->dma, "GUS")) - printk("gus_card.c: Can't allocate DMA channel\n"); + printk(KERN_ERR "gus_card.c: Can't allocate DMA channel %d\n", hw_config->dma); if (hw_config->dma2 != -1 && hw_config->dma2 != hw_config->dma) if (sound_alloc_dma(hw_config->dma2, "GUS(2)")) - printk("gus_card.c: Can't allocate DMA channel 2\n"); + printk(KERN_ERR "gus_card.c: Can't allocate DMA channel %d\n", hw_config->dma2); #if defined(CONFIG_MIDI) gus_midi_init(hw_config); #endif @@ -101,7 +116,7 @@ void unload_gus(struct address_info *hw_config) release_region(hw_config->io_base, 16); release_region(hw_config->io_base + 0x100, 12); /* 0x10c-> is MAX */ - snd_release_irq(hw_config->irq, hw_config); + free_irq(hw_config->irq, hw_config); sound_free_dma(hw_config->dma); @@ -119,6 +134,10 @@ void gusintr(int irq, void *dev_id, struct pt_regs *dummy) #ifdef CONFIG_GUSMAX if (have_gus_max) + adintr(irq, (void *)hw_config->slots[1], NULL); +#endif +#ifdef CONFIG_GUS16 + if (db16) adintr(irq, (void *)hw_config->slots[3], NULL); #endif @@ -191,6 +210,8 @@ void unload_gus_db16(struct address_info *hw_config) } #endif + + #ifdef MODULE static struct address_info config; @@ -206,7 +227,10 @@ int dma = -1; int dma16 = -1; /* Set this for modules that need it */ int type = 0; /* 1 for PnP */ int gus16 = 0; -static int db16 = 0; /* Has a Gus16 AD1848 on it */ +#ifdef CONFIG_GUSMAX +static int no_wave_dma = 0;/* Set if no dma is to be used for the + wave table (GF1 chip) */ +#endif MODULE_PARM(io, "i"); MODULE_PARM(irq, "i"); @@ -214,7 +238,12 @@ MODULE_PARM(dma, "i"); MODULE_PARM(dma16, "i"); MODULE_PARM(type, "i"); MODULE_PARM(gus16, "i"); +#ifdef CONFIG_GUSMAX +MODULE_PARM(no_wave_dma, "i"); +#endif +#ifdef CONFIG_GUS16 MODULE_PARM(db16, "i"); +#endif int init_module(void) { @@ -230,6 +259,10 @@ int init_module(void) 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) diff --git a/drivers/sound/gus_wave.c b/drivers/sound/gus_wave.c index 7b202f3ef..6dc52aef6 100644 --- a/drivers/sound/gus_wave.c +++ b/drivers/sound/gus_wave.c @@ -11,11 +11,14 @@ * for more info. */ /* - * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed) + * 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. */ + + #include <linux/config.h> - #define GUSPNP_AUTODETECT #include "sound_config.h" @@ -70,10 +73,11 @@ struct voice_info }; static struct voice_alloc_info *voice_alloc; - +static struct address_info *gus_hw_config; extern int gus_base; extern int gus_irq, gus_dma; extern int gus_pnp_flag; +extern int gus_no_wave_dma; static int gus_dma2 = -1; static int dual_dma_mode = 0; static long gus_mem_size = 0; @@ -833,7 +837,7 @@ static void gus_initialize(void) gus_select_voice(0); /* This disables writes to IRQ/DMA reg */ - gusintr(gus_irq, NULL, NULL); /* Serve pending interrupts */ + gusintr(gus_irq, (void *)gus_hw_config, NULL); /* Serve pending interrupts */ inb(u_Status); /* Touch the status register */ @@ -859,26 +863,26 @@ static void pnp_mem_init(void) int bank_sizes[4]; int i, j, bits = -1, nbanks = 0; -/* - * This routine determines what kind of RAM is installed in each of the four - * SIMM banks and configures the DRAM address decode logic accordingly. - */ + /* + * This routine determines what kind of RAM is installed in each of the four + * SIMM banks and configures the DRAM address decode logic accordingly. + */ -/* - * Place the chip into enhanced mode - */ + /* + * Place the chip into enhanced mode + */ gus_write8(0x19, gus_read8(0x19) | 0x01); gus_write8(0x53, gus_look8(0x53) & ~0x02); /* Select DRAM I/O access */ -/* - * Set memory configuration to 4 DRAM banks of 4M in each (16M total). - */ + /* + * Set memory configuration to 4 DRAM banks of 4M in each (16M total). + */ gus_write16(0x52, (gus_look16(0x52) & 0xfff0) | 0x000c); -/* - * Perform the DRAM size detection for each bank individually. - */ + /* + * Perform the DRAM size detection for each bank individually. + */ for (bank = 0; bank < 4; bank++) { int size = 0; @@ -1649,22 +1653,26 @@ static int guswave_open(int dev, int mode) voice_alloc->timestamp = 0; - if ((err = DMAbuf_open_dma(gus_devnum)) < 0) - { - /* printk( "GUS: Loading samples without DMA\n"); */ - gus_no_dma = 1; /* Upload samples using PIO */ + if (gus_no_wave_dma) { + gus_no_dma = 1; + } else { + if ((err = DMAbuf_open_dma(gus_devnum)) < 0) + { + /* printk( "GUS: Loading samples without DMA\n"); */ + gus_no_dma = 1; /* Upload samples using PIO */ + } + else + gus_no_dma = 0; } - else - gus_no_dma = 0; init_waitqueue(&dram_sleeper); gus_busy = 1; active_device = GUS_DEV_WAVE; - gusintr(gus_irq, NULL, NULL); /* Serve pending interrupts */ + gusintr(gus_irq, (void *)gus_hw_config, NULL); /* Serve pending interrupts */ gus_initialize(); gus_reset(); - gusintr(gus_irq, NULL, NULL); /* Serve pending interrupts */ + gusintr(gus_irq, (void *)gus_hw_config, NULL); /* Serve pending interrupts */ return 0; } @@ -2953,6 +2961,7 @@ void gus_wave_init(struct address_info *hw_config) gus_irq = irq; gus_dma = dma; gus_dma2 = dma2; + gus_hw_config = hw_config; if (gus_dma2 == -1) gus_dma2 = dma; @@ -3114,8 +3123,8 @@ void gus_wave_init(struct address_info *hw_config) reset_sample_memory(); gus_initialize(); - - if (gus_mem_size > 0) + + if ((gus_mem_size > 0) & !gus_no_wave_dma) { if ((dev = sound_alloc_audiodev()) != -1) { diff --git a/drivers/sound/local.h.master b/drivers/sound/local.h.master index b333f0ce0..65d8c0259 100644 --- a/drivers/sound/local.h.master +++ b/drivers/sound/local.h.master @@ -42,7 +42,7 @@ defined(CONFIG_MSS_MODULE) || defined(CONFIG_SSCAPE_MODULE) || \ defined(CONFIG_TRIX_MODULE) || defined(CONFIG_MAD16_MODULE) || \ defined(CONFIG_CS4232_MODULE) || defined(CONFIG_OPL3SA1_MODULE) || \ - defined(CONFIG_SOFTOSS_MODULE) + defined(CONFIG_SOFTOSS_MODULE) || defined(CONFIG_VIDC_SOUND) # define CONFIG_AUDIO #endif diff --git a/drivers/sound/mad16.c b/drivers/sound/mad16.c index 4870ec799..30f366964 100644 --- a/drivers/sound/mad16.c +++ b/drivers/sound/mad16.c @@ -56,6 +56,10 @@ * CD-ROM DMA (Mitsumi or IDE): 0x00=DMA5, 0x01=DMA6, 0x02=DMA7 or 0x03=disabled * * For use with sbpcd, address 0x340, set MAD16_CDSEL to 0x03 or 0x23. + * + * Changes + * + * Alan Cox Clean up, added module selections. */ #include "sound_config.h" @@ -118,48 +122,47 @@ static int c931_detected; /* minor diferences from C930 */ #define DDB(x) #endif -static unsigned char -mad_read(int port) +static unsigned char mad_read(int port) { - unsigned long flags; - unsigned char tmp; + unsigned long flags; + unsigned char tmp; save_flags(flags); cli(); switch (board_type) /* Output password */ - { - case C928: - case MOZART: - outb((0xE2), PASSWD_REG); - break; - - case C929: - outb((0xE3), PASSWD_REG); - break; - - case C930: - /* outb(( 0xE4), PASSWD_REG); */ - break; - - case C924: - outb((0xE5), PASSWD_REG); - break; - } + { + case C928: + case MOZART: + outb((0xE2), PASSWD_REG); + break; + + case C929: + outb((0xE3), PASSWD_REG); + break; + + case C930: + /* outb(( 0xE4), PASSWD_REG); */ + break; + + case C924: + outb((0xE5), PASSWD_REG); + break; + } if (board_type == C930) - { - outb((port - MC0_PORT), 0xe0e); /* Write to index reg */ - tmp = inb(0xe0f); /* Read from data reg */ - } else + { + outb((port - MC0_PORT), 0xe0e); /* Write to index reg */ + tmp = inb(0xe0f); /* Read from data reg */ + } + else tmp = inb(port); restore_flags(flags); return tmp; } -static void -mad_write(int port, int value) +static void mad_write(int port, int value) { unsigned long flags; @@ -167,65 +170,65 @@ mad_write(int port, int value) cli(); switch (board_type) /* Output password */ - { - case C928: - case MOZART: - outb((0xE2), PASSWD_REG); - break; - - case C929: - outb((0xE3), PASSWD_REG); - break; - - case C930: - /* outb(( 0xE4), PASSWD_REG); */ - break; - - case C924: - outb((0xE5), PASSWD_REG); - break; - } + { + case C928: + case MOZART: + outb((0xE2), PASSWD_REG); + break; + + case C929: + outb((0xE3), PASSWD_REG); + break; + + case C930: + /* outb(( 0xE4), PASSWD_REG); */ + break; + + case C924: + outb((0xE5), PASSWD_REG); + break; + } if (board_type == C930) - { - outb((port - MC0_PORT), 0xe0e); /* Write to index reg */ - outb(((unsigned char) (value & 0xff)), 0xe0f); - } else + { + outb((port - MC0_PORT), 0xe0e); /* Write to index reg */ + outb(((unsigned char) (value & 0xff)), 0xe0f); + } + else outb(((unsigned char) (value & 0xff)), port); restore_flags(flags); } -static int -detect_c930(void) +static int detect_c930(void) { unsigned char tmp = mad_read(MC1_PORT); if ((tmp & 0x06) != 0x06) - { - DDB(printk("Wrong C930 signature (%x)\n", tmp)); - /* return 0; */ - } + { + DDB(printk("Wrong C930 signature (%x)\n", tmp)); + /* return 0; */ + } mad_write(MC1_PORT, 0); if (mad_read(MC1_PORT) != 0x06) - { - DDB(printk("Wrong C930 signature2 (%x)\n", tmp)); - /* return 0; */ - } + { + DDB(printk("Wrong C930 signature2 (%x)\n", tmp)); + /* return 0; */ + } mad_write(MC1_PORT, tmp); /* Restore bits */ mad_write(MC7_PORT, 0); if ((tmp = mad_read(MC7_PORT)) != 0) - { - DDB(printk("MC7 not writable (%x)\n", tmp)); - return 0; - } + { + DDB(printk("MC7 not writable (%x)\n", tmp)); + return 0; + } mad_write(MC7_PORT, 0xcb); if ((tmp = mad_read(MC7_PORT)) != 0xcb) - { - DDB(printk("MC7 not writable2 (%x)\n", tmp)); - return 0; - } + { + DDB(printk("MC7 not writable2 (%x)\n", tmp)); + return 0; + } tmp = mad_read(MC0_PORT+18); if (tmp == 0xff) @@ -262,113 +265,109 @@ detect_c930(void) * the PnP bios will not recognize the chip on the next * warm boot and may assignd different resources to other * PnP/PCI cards. - */ + */ mad_write(MC0_PORT+17, 0x04); return 1; } -static int -detect_mad16(void) +static int detect_mad16(void) { - unsigned char tmp, tmp2; - int i; + unsigned char tmp, tmp2; + int i; + + /* + * Check that reading a register doesn't return bus float (0xff) + * when the card is accessed using password. This may fail in case + * the card is in low power mode. Normally at least the power saving mode + * bit should be 0. + */ -/* - * Check that reading a register doesn't return bus float (0xff) - * when the card is accessed using password. This may fail in case - * the card is in low power mode. Normally at least the power saving mode - * bit should be 0. - */ if ((tmp = mad_read(MC1_PORT)) == 0xff) - { - DDB(printk("MC1_PORT returned 0xff\n")); - return 0; - } + { + DDB(printk("MC1_PORT returned 0xff\n")); + return 0; + } for (i = 0xf8d; i <= 0xf98; i++) DDB(printk("Port %0x (init value) = %0x\n", i, mad_read(i))); if (board_type == C930) return detect_c930(); -/* - * Now check that the gate is closed on first I/O after writing - * the password. (This is how a MAD16 compatible card works). - */ + + /* + * Now check that the gate is closed on first I/O after writing + * the password. (This is how a MAD16 compatible card works). + */ if ((tmp2 = inb(MC1_PORT)) == tmp) /* It didn't close */ - { - DDB(printk("MC1_PORT didn't close after read (0x%02x)\n", tmp2)); - return 0; - } + { + DDB(printk("MC1_PORT didn't close after read (0x%02x)\n", tmp2)); + return 0; + } mad_write(MC1_PORT, tmp ^ 0x80); /* Toggle a bit */ if ((tmp2 = mad_read(MC1_PORT)) != (tmp ^ 0x80)) /* Compare the bit */ - { - mad_write(MC1_PORT, tmp); /* Restore */ - DDB(printk("Bit revert test failed (0x%02x, 0x%02x)\n", tmp, tmp2)); - return 0; - } + { + mad_write(MC1_PORT, tmp); /* Restore */ + DDB(printk("Bit revert test failed (0x%02x, 0x%02x)\n", tmp, tmp2)); + return 0; + } mad_write(MC1_PORT, tmp); /* Restore */ return 1; /* Bingo */ - } -static int -wss_init(struct address_info *hw_config) +static int wss_init(struct address_info *hw_config) { - int ad_flags = 0; + int ad_flags = 0; -/* - * Verify the WSS parameters - */ + /* + * Verify the WSS parameters + */ if (check_region(hw_config->io_base, 8)) - { - printk("MSS: I/O port conflict\n"); - return 0; - } + { + printk(KERN_ERR "MSS: I/O port conflict\n"); + return 0; + } if (!ad1848_detect(hw_config->io_base + 4, &ad_flags, mad16_osp)) return 0; /* - * Check if the IO port returns valid signature. The original MS Sound - * system returns 0x04 while some cards (AudioTrix Pro for example) - * return 0x00. + * Check if the IO port returns valid signature. The original MS Sound + * system returns 0x04 while some cards (AudioTrix Pro for example) + * return 0x00. */ if ((inb(hw_config->io_base + 3) & 0x3f) != 0x04 && (inb(hw_config->io_base + 3) & 0x3f) != 0x00) - { - DDB(printk("No MSS signature detected on port 0x%x (0x%x)\n", hw_config->io_base, inb(hw_config->io_base + 3))); - return 0; - } + { + DDB(printk("No MSS signature detected on port 0x%x (0x%x)\n", hw_config->io_base, inb(hw_config->io_base + 3))); + return 0; + } if (hw_config->irq > 11) - { - printk("MSS: Bad IRQ %d\n", hw_config->irq); - return 0; - } + { + printk(KERN_ERR "MSS: Bad IRQ %d\n", hw_config->irq); + return 0; + } if (hw_config->dma != 0 && hw_config->dma != 1 && hw_config->dma != 3) - { - printk("MSS: Bad DMA %d\n", hw_config->dma); - return 0; - } + { + printk(KERN_ERR "MSS: Bad DMA %d\n", hw_config->dma); + return 0; + } /* - * Check that DMA0 is not in use with a 8 bit board. + * Check that DMA0 is not in use with a 8 bit board. */ if (hw_config->dma == 0 && inb(hw_config->io_base + 3) & 0x80) - { - printk("MSS: Can't use DMA0 with a 8 bit card/slot\n"); - return 0; - } + { + printk("MSS: Can't use DMA0 with a 8 bit card/slot\n"); + return 0; + } if (hw_config->irq > 7 && hw_config->irq != 9 && inb(hw_config->io_base + 3) & 0x80) - { - printk("MSS: Can't use IRQ%d with a 8 bit card/slot\n", hw_config->irq); - } + printk(KERN_ERR "MSS: Can't use IRQ%d with a 8 bit card/slot\n", hw_config->irq); return 1; } -static int -init_c930(struct address_info *hw_config) +static int init_c930(struct address_info *hw_config) { - unsigned char cfg = 0; + unsigned char cfg = 0; #ifdef MAD16_CONF cfg |= (0x0f & MAD16_CONF); @@ -384,24 +383,23 @@ init_c930(struct address_info *hw_config) } switch (hw_config->io_base) - { - case 0x530: - cfg |= 0x00; - break; - case 0xe80: - cfg |= 0x10; - break; - case 0xf40: - cfg |= 0x20; - break; - case 0x604: - cfg |= 0x30; - break; - - default: - printk("MAD16: Invalid codec port %x\n", hw_config->io_base); - return 0; - } + { + case 0x530: + cfg |= 0x00; + break; + case 0xe80: + cfg |= 0x10; + break; + case 0xf40: + cfg |= 0x20; + break; + case 0x604: + cfg |= 0x30; + break; + default: + printk(KERN_ERR "MAD16: Invalid codec port %x\n", hw_config->io_base); + return 0; + } mad_write(MC1_PORT, cfg); /* MC2 is CD configuration. Don't touch it. */ @@ -423,94 +421,98 @@ init_c930(struct address_info *hw_config) return wss_init(hw_config); } -static int -chip_detect(void) +static int chip_detect(void) { - int i; + int i; -/* - * Then try to detect with the old password - */ + /* + * Then try to detect with the old password + */ board_type = C924; DDB(printk("Detect using password = 0xE5\n")); if (!detect_mad16()) /* No luck. Try different model */ - { - board_type = C928; - - DDB(printk("Detect using password = 0xE2\n")); - - if (!detect_mad16()) - { - board_type = C929; - - DDB(printk("Detect using password = 0xE3\n")); - - if (!detect_mad16()) - { - if (inb(PASSWD_REG) != 0xff) - return 0; - -/* - * First relocate MC# registers to 0xe0e/0xe0f, disable password - */ - - outb((0xE4), PASSWD_REG); - outb((0x80), PASSWD_REG); - - board_type = C930; - - DDB(printk("Detect using password = 0xE4\n")); - - for (i = 0xf8d; i <= 0xf93; i++) - DDB(printk("port %03x = %02x\n", i, mad_read(i))); - - if (!detect_mad16()) - return 0; - - DDB(printk("mad16.c: 82C930 detected\n")); - } else - { - DDB(printk("mad16.c: 82C929 detected\n")); - } - } else - { - unsigned char model; - - if (((model = mad_read(MC3_PORT)) & 0x03) == 0x03) - { - DDB(printk("mad16.c: Mozart detected\n")); - board_type = MOZART; - } else - { - DDB(printk("mad16.c: 82C928 detected???\n")); - board_type = C928; - } - } - } + { + board_type = C928; + + DDB(printk("Detect using password = 0xE2\n")); + + if (!detect_mad16()) + { + board_type = C929; + + DDB(printk("Detect using password = 0xE3\n")); + + if (!detect_mad16()) + { + if (inb(PASSWD_REG) != 0xff) + return 0; + + /* + * First relocate MC# registers to 0xe0e/0xe0f, disable password + */ + + outb((0xE4), PASSWD_REG); + outb((0x80), PASSWD_REG); + + board_type = C930; + + DDB(printk("Detect using password = 0xE4\n")); + + for (i = 0xf8d; i <= 0xf93; i++) + DDB(printk("port %03x = %02x\n", i, mad_read(i))); + + if (!detect_mad16()) + return 0; + + DDB(printk("mad16.c: 82C930 detected\n")); + } + else + { + DDB(printk("mad16.c: 82C929 detected\n")); + } + } + else + { + unsigned char model; + + if (((model = mad_read(MC3_PORT)) & 0x03) == 0x03) + { + DDB(printk("mad16.c: Mozart detected\n")); + board_type = MOZART; + } + else + { + DDB(printk("mad16.c: 82C928 detected???\n")); + board_type = C928; + } + } + } return 1; } -int -probe_mad16(struct address_info *hw_config) +int probe_mad16(struct address_info *hw_config) { - int i; - static int valid_ports[] = - {0x530, 0xe80, 0xf40, 0x604}; - unsigned char tmp; - unsigned char cs4231_mode = 0; + int i; + static int valid_ports[] = + { + 0x530, 0xe80, 0xf40, 0x604 + }; + unsigned char tmp; + unsigned char cs4231_mode = 0; - int ad_flags = 0; + int ad_flags = 0; if (already_initialized) return 0; mad16_osp = hw_config->osp; -/* - * Check that all ports return 0xff (bus float) when no password - * is written to the password register. - */ + + /* + * Check that all ports return 0xff (bus float) when no password + * is written to the password register. + */ DDB(printk("--- Detecting MAD16 / Mozart ---\n")); if (!chip_detect()) @@ -530,25 +532,25 @@ probe_mad16(struct address_info *hw_config) tmp = (mad_read(MC1_PORT) & 0x0f) | 0x80; /* Enable WSS, Disable SB */ for (i = 0; i < 5; i++) - { - if (i > 3) /* Not a valid port */ - { - printk("MAD16/Mozart: Bad WSS base address 0x%x\n", hw_config->io_base); - return 0; - } - if (valid_ports[i] == hw_config->io_base) - { - tmp |= i << 4; /* WSS port select bits */ - break; - } - } + { + if (i > 3) /* Not a valid port */ + { + printk(KERN_ERR "MAD16/Mozart: Bad WSS base address 0x%x\n", hw_config->io_base); + return 0; + } + if (valid_ports[i] == hw_config->io_base) + { + tmp |= i << 4; /* WSS port select bits */ + break; + } + } -/* - * Set optional CD-ROM and joystick settings. - */ + /* + * Set optional CD-ROM and joystick settings. + */ -#ifdef MAD16_CONF tmp &= ~0x0f; +#if defined(MAD16_CONF) tmp |= ((MAD16_CONF) & 0x0f); /* CD-ROM and joystick bits */ #endif mad_write(MC1_PORT, tmp); @@ -567,11 +569,11 @@ probe_mad16(struct address_info *hw_config) mad_write(MC3_PORT, 0xf0); /* Disable SB */ if (board_type == C924) /* Specific C924 init values */ - { - mad_write(MC4_PORT, 0xA0); - mad_write(MC5_PORT, 0x05); - mad_write(MC6_PORT, 0x03); - } + { + mad_write(MC4_PORT, 0xA0); + mad_write(MC5_PORT, 0x05); + mad_write(MC6_PORT, 0x03); + } if (!ad1848_detect(hw_config->io_base + 4, &ad_flags, mad16_osp)) return 0; @@ -579,15 +581,16 @@ probe_mad16(struct address_info *hw_config) cs4231_mode = 0x02; /* CS4248/CS4231 sync delay switch */ if (board_type == C929) - { - mad_write(MC4_PORT, 0xa2); - mad_write(MC5_PORT, 0xA5 | cs4231_mode); - mad_write(MC6_PORT, 0x03); /* Disable MPU401 */ - } else - { - mad_write(MC4_PORT, 0x02); - mad_write(MC5_PORT, 0x30 | cs4231_mode); - } + { + mad_write(MC4_PORT, 0xa2); + mad_write(MC5_PORT, 0xA5 | cs4231_mode); + mad_write(MC6_PORT, 0x03); /* Disable MPU401 */ + } + else + { + mad_write(MC4_PORT, 0x02); + mad_write(MC5_PORT, 0x30 | cs4231_mode); + } for (i = 0xf8d; i <= 0xf93; i++) DDB(printk("port %03x after init = %02x\n", i, mad_read(i))); @@ -597,24 +600,21 @@ probe_mad16(struct address_info *hw_config) return 1; } -void -attach_mad16(struct address_info *hw_config) +void attach_mad16(struct address_info *hw_config) { - static char interrupt_bits[12] = - { + static char interrupt_bits[12] = { -1, -1, -1, -1, -1, -1, -1, 0x08, -1, 0x10, 0x18, 0x20 }; - char bits; + char bits; - static char dma_bits[4] = - { + static char dma_bits[4] = { 1, 2, 0, 3 }; - int config_port = hw_config->io_base + 0, version_port = hw_config->io_base + 3; - int ad_flags = 0, dma = hw_config->dma, dma2 = hw_config->dma2; - unsigned char dma2_bit = 0; + int config_port = hw_config->io_base + 0, version_port = hw_config->io_base + 3; + int ad_flags = 0, dma = hw_config->dma, dma2 = hw_config->dma2; + unsigned char dma2_bit = 0; already_initialized = 1; @@ -622,8 +622,9 @@ attach_mad16(struct address_info *hw_config) return; /* - * Set the IRQ and DMA addresses. + * Set the IRQ and DMA addresses. */ + if (board_type == C930) interrupt_bits[5] = 0x28; /* Also IRQ5 is possible on C930 */ @@ -633,35 +634,35 @@ attach_mad16(struct address_info *hw_config) outb((bits | 0x40), config_port); if ((inb(version_port) & 0x40) == 0) - printk("[IRQ Conflict?]"); + printk(KERN_ERR "[IRQ Conflict?]\n"); -/* - * Handle the capture DMA channel - */ + /* + * Handle the capture DMA channel + */ if (ad_flags & AD_F_CS4231 && dma2 != -1 && dma2 != dma) - { - if (!((dma == 0 && dma2 == 1) || + { + if (!((dma == 0 && dma2 == 1) || (dma == 1 && dma2 == 0) || (dma == 3 && dma2 == 0))) - { /* Unsupported combination. Try to swap channels */ - int tmp = dma; - - dma = dma2; - dma2 = tmp; - } - if ((dma == 0 && dma2 == 1) || - (dma == 1 && dma2 == 0) || - (dma == 3 && dma2 == 0)) - { - dma2_bit = 0x04; /* Enable capture DMA */ - } else - { - printk("MAD16: Invalid capture DMA\n"); - dma2 = dma; - } - } else - dma2 = dma; + { /* Unsupported combination. Try to swap channels */ + int tmp = dma; + + dma = dma2; + dma2 = tmp; + } + if ((dma == 0 && dma2 == 1) || (dma == 1 && dma2 == 0) || + (dma == 3 && dma2 == 0)) + { + dma2_bit = 0x04; /* Enable capture DMA */ + } + else + { + printk("MAD16: Invalid capture DMA\n"); + dma2 = dma; + } + } + else dma2 = dma; outb((bits | dma_bits[dma] | dma2_bit), config_port); /* Write IRQ+DMA setup */ @@ -673,24 +674,23 @@ 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) +void attach_mad16_mpu(struct address_info *hw_config) { if (board_type < C929) /* Early chip. No MPU support. Just SB MIDI */ - { -#if defined(CONFIG_MIDI) + { +#if defined(CONFIG_MIDI) && defined(CONFIG_MAD16_OLDCARD) - if (mad_read(MC1_PORT) & 0x20) - hw_config->io_base = 0x240; - else - hw_config->io_base = 0x220; + if (mad_read(MC1_PORT) & 0x20) + hw_config->io_base = 0x240; + else + hw_config->io_base = 0x220; - hw_config->name = "Mad16/Mozart"; - sb_dsp_init(hw_config); + hw_config->name = "Mad16/Mozart"; + sb_dsp_init(hw_config); #endif - return; - } + return; + } #if defined(CONFIG_UART401) && defined(CONFIG_MIDI) if (!already_initialized) return; @@ -701,68 +701,67 @@ attach_mad16_mpu(struct address_info *hw_config) #endif } -int -probe_mad16_mpu(struct address_info *hw_config) +int probe_mad16_mpu(struct address_info *hw_config) { #if defined(CONFIG_UART401) && defined(CONFIG_MIDI) - static int mpu_attached = 0; - static int valid_ports[] = - {0x330, 0x320, 0x310, 0x300}; - static short valid_irqs[] = - {9, 10, 5, 7}; - unsigned char tmp; - - int i; /* A variable with secret power */ + static int mpu_attached = 0; + static int valid_ports[] = { + 0x330, 0x320, 0x310, 0x300 + }; + + static short valid_irqs[] = {9, 10, 5, 7}; + unsigned char tmp; + int i; /* A variable with secret power */ if (!already_initialized) /* The MSS port must be initialized first */ return 0; - if (mpu_attached) /* Don't let them call this twice */ + if (mpu_attached) /* Don't let them call this twice */ return 0; mpu_attached = 1; if (board_type < C929) /* Early chip. No MPU support. Just SB MIDI */ - { - -#if defined(CONFIG_MIDI) - unsigned char tmp; - - tmp = mad_read(MC3_PORT); - - /* - * MAD16 SB base is defined by the WSS base. It cannot be changed - * alone. - * Ignore configured I/O base. Use the active setting. - */ - - if (mad_read(MC1_PORT) & 0x20) - hw_config->io_base = 0x240; - else - hw_config->io_base = 0x220; - - switch (hw_config->irq) - { - case 5: - tmp = (tmp & 0x3f) | 0x80; - break; - case 7: - tmp = (tmp & 0x3f); - break; - case 11: - tmp = (tmp & 0x3f) | 0x40; - break; - default: - printk("mad16/Mozart: Invalid MIDI IRQ\n"); - return 0; - } - - mad_write(MC3_PORT, tmp | 0x04); - hw_config->driver_use_1 = SB_MIDI_ONLY; - return sb_dsp_detect(hw_config); + { + +#if defined(CONFIG_MIDI) && defined(CONFIG_MAD16_OLDCARD) + unsigned char tmp; + + tmp = mad_read(MC3_PORT); + + /* + * MAD16 SB base is defined by the WSS base. It cannot be changed + * alone. + * Ignore configured I/O base. Use the active setting. + */ + + if (mad_read(MC1_PORT) & 0x20) + hw_config->io_base = 0x240; + else + hw_config->io_base = 0x220; + + switch (hw_config->irq) + { + case 5: + tmp = (tmp & 0x3f) | 0x80; + break; + case 7: + tmp = (tmp & 0x3f); + break; + case 11: + tmp = (tmp & 0x3f) | 0x40; + break; + default: + printk(KERN_ERR "mad16/Mozart: Invalid MIDI IRQ\n"); + return 0; + } + + mad_write(MC3_PORT, tmp | 0x04); + hw_config->driver_use_1 = SB_MIDI_ONLY; + return sb_dsp_detect(hw_config); #else - return 0; + return 0; #endif - } + } tmp = mad_read(MC6_PORT) & 0x83; tmp |= 0x80; /* MPU-401 enable */ @@ -771,36 +770,36 @@ probe_mad16_mpu(struct address_info *hw_config) */ for (i = 0; i < 5; i++) - { - if (i > 3) /* Out of array bounds */ - { - printk("MAD16 / Mozart: Invalid MIDI port 0x%x\n", hw_config->io_base); - return 0; - } - if (valid_ports[i] == hw_config->io_base) - { - tmp |= i << 5; - break; - } - } + { + if (i > 3) /* Out of array bounds */ + { + printk(KERN_ERR "MAD16 / Mozart: Invalid MIDI port 0x%x\n", hw_config->io_base); + return 0; + } + if (valid_ports[i] == hw_config->io_base) + { + tmp |= i << 5; + break; + } + } /* * Set the MPU IRQ bits */ for (i = 0; i < 5; i++) - { - if (i > 3) /* Out of array bounds */ - { - printk("MAD16 / Mozart: Invalid MIDI IRQ %d\n", hw_config->irq); - return 0; - } - if (valid_irqs[i] == hw_config->irq) - { - tmp |= i << 3; - break; - } - } + { + if (i > 3) /* Out of array bounds */ + { + printk(KERN_ERR "MAD16 / Mozart: Invalid MIDI IRQ %d\n", hw_config->irq); + return 0; + } + if (valid_irqs[i] == hw_config->irq) + { + tmp |= i << 3; + break; + } + } mad_write(MC6_PORT, tmp); /* Write MPU401 config */ return probe_uart401(hw_config); @@ -809,13 +808,12 @@ probe_mad16_mpu(struct address_info *hw_config) #endif } -void -unload_mad16(struct address_info *hw_config) +void unload_mad16(struct address_info *hw_config) { ad1848_unload(hw_config->io_base + 4, - hw_config->irq, - hw_config->dma, - hw_config->dma2, 0); + hw_config->irq, + hw_config->dma, + hw_config->dma2, 0); release_region(hw_config->io_base, 4); sound_unload_audiodev(hw_config->slots[0]); @@ -824,12 +822,12 @@ unload_mad16(struct address_info *hw_config) void unload_mad16_mpu(struct address_info *hw_config) { -#if defined(CONFIG_MIDI) +#if defined(CONFIG_MIDI) && defined(CONFIG_MAD16_OLDCARD) if (board_type < C929) /* Early chip. No MPU support. Just SB MIDI */ - { - sb_dsp_unload(hw_config); - return; - } + { + sb_dsp_unload(hw_config); + return; + } #endif #if defined(CONFIG_UART401) && defined(CONFIG_MIDI) @@ -839,6 +837,8 @@ unload_mad16_mpu(struct address_info *hw_config) #ifdef MODULE +int mpu_io = 0; +int mpu_irq = 0; int io = -1; int dma = -1; int dma16 = -1; /* Set this for modules that need it */ @@ -851,6 +851,8 @@ int cddma = 3; int opl4 = 0; int joystick = 0; +MODULE_PARM(mpu_io, "i"); +MODULE_PARM(mpu_irq, "i"); MODULE_PARM(io,"i"); MODULE_PARM(dma,"i"); MODULE_PARM(dma16,"i"); @@ -862,17 +864,18 @@ MODULE_PARM(cddma,"i"); MODULE_PARM(opl4,"i"); MODULE_PARM(joystick,"i"); +EXPORT_NO_SYMBOLS; -static int found_mpu; +static int found_mpu; -static int dma_map[2][8] = +static int 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 irq_map[16] = { 0x00, -1, -1, 0x0A, -1, 0x04, -1, 0x08, @@ -881,80 +884,83 @@ static int irq_map[16] = }; struct address_info config; +struct address_info config_mpu; -int -init_module(void) +int init_module(void) { - int dmatype = 0; + int dmatype = 0; - printk("MAD16 audio driver Copyright (C) by Hannu Savolainen 1993-1996\n"); + printk(KERN_INFO "MAD16 audio driver Copyright (C) by Hannu Savolainen 1993-1996\n"); if (io == -1 || dma == -1 || irq == -1) - { - printk("I/O, DMA and irq are mandatory\n"); - return -EINVAL; - } - printk("CDROM "); + { + printk(KERN_ERR "I/O, DMA and irq are mandatory\n"); + return -EINVAL; + } + printk(KERN_INFO "CDROM "); switch (cdtype) - { - case 0x00: - printk("Disabled"); - cdirq = 0; - break; - case 0x02: - printk("Sony CDU31A"); - dmatype = 2; - break; - case 0x04: - printk("Mitsumi"); - dmatype = 1; - break; - case 0x06: - printk("Panasonic Lasermate"); - dmatype = 2; - break; - case 0x08: - printk("Secondary IDE"); - dmatype = 1; - break; - case 0x0A: - printk("Primary IDE"); - dmatype = 1; - break; - default: - printk("\nInvalid CDROM type\n"); - return -EINVAL; - } + { + case 0x00: + printk("Disabled"); + cdirq = 0; + break; + case 0x02: + printk("Sony CDU31A"); + dmatype = 2; + break; + case 0x04: + printk("Mitsumi"); + dmatype = 1; + break; + case 0x06: + printk("Panasonic Lasermate"); + dmatype = 2; + break; + case 0x08: + printk("Secondary IDE"); + dmatype = 1; + break; + case 0x0A: + printk("Primary IDE"); + dmatype = 1; + break; + default: + printk("\n"); + printk(KERN_ERR "Invalid CDROM type\n"); + return -EINVAL; + } if (dmatype) - { - if (cddma > 7 || cddma < 0 || dma_map[dmatype][cddma] == -1) - { - printk("\nInvalid CDROM DMA\n"); - return -EINVAL; - } - if (cddma) - printk(", DMA %d", cddma); - else - printk(", no DMA"); - } + { + if (cddma > 7 || cddma < 0 || dma_map[dmatype][cddma] == -1) + { + printk("\n"); + printk(KERN_ERR "Invalid CDROM DMA\n"); + return -EINVAL; + } + if (cddma) + printk(", DMA %d", cddma); + else + printk(", no DMA"); + } if (cdtype && !cdirq) printk(", no IRQ"); else if (cdirq < 0 || cdirq > 15 || irq_map[cdirq] == -1) - { + { printk(", invalid IRQ (disabling)"); cdirq = 0; - } else - printk(", IRQ %d", cdirq); + } + else printk(", IRQ %d", cdirq); - printk(".\nJoystick port "); + printk(".\n"); + printk(KERN_INFO "Joystick port "); if (joystick == 1) printk("enabled.\n"); else - { - joystick = 0; - printk("disabled.\n"); - } + { + joystick = 0; + printk("disabled.\n"); + } /* * Build the config words @@ -967,26 +973,26 @@ init_module(void) mad16_cdsel |= dma_map[dmatype][cddma]; if (cdtype < 0x08) - { - switch (cdport) - { - case 0x340: - mad16_cdsel |= 0x00; - break; - case 0x330: - mad16_cdsel |= 0x40; - break; - case 0x360: - mad16_cdsel |= 0x80; - break; - case 0x320: - mad16_cdsel |= 0xC0; - break; - default: - printk("Unknown CDROM I/O base %d\n", cdport); - return -EINVAL; - } - } + { + switch (cdport) + { + case 0x340: + mad16_cdsel |= 0x00; + break; + case 0x330: + mad16_cdsel |= 0x40; + break; + case 0x360: + mad16_cdsel |= 0x80; + break; + case 0x320: + mad16_cdsel |= 0xC0; + break; + default: + printk(KERN_ERR "Unknown CDROM I/O base %d\n", cdport); + return -EINVAL; + } + } mad16_cdsel |= irq_map[cdirq]; config.io_base = io; @@ -996,19 +1002,21 @@ init_module(void) if (!probe_mad16(&config)) return -ENODEV; - found_mpu = probe_mad16_mpu(&config); + + config_mpu.io_base = mpu_io; + config_mpu.irq = mpu_irq; + found_mpu = probe_mad16_mpu(&config_mpu); attach_mad16(&config); if (found_mpu) - attach_mad16_mpu(&config); + attach_mad16_mpu(&config_mpu); SOUND_LOCK; return 0; } -void -cleanup_module(void) +void cleanup_module(void) { if (found_mpu) unload_mad16_mpu(&config); diff --git a/drivers/sound/maui.c b/drivers/sound/maui.c index a7d37039c..4d2076273 100644 --- a/drivers/sound/maui.c +++ b/drivers/sound/maui.c @@ -20,6 +20,7 @@ #include <linux/config.h> #include <linux/module.h> +#include <asm/init.h> #define USE_SEQ_MACROS #define USE_SIMPLE_MACROS @@ -452,6 +453,11 @@ void unload_maui(struct address_info *hw_config) #ifdef MODULE +MODULE_PARM(io,"i"); +MODULE_PARM(irq,"i"); + +EXPORT_NO_SYMBOLS; + int io = -1; int irq = -1; @@ -489,7 +495,7 @@ int init_module(void) void cleanup_module(void) { if (fw_load && maui_os) - kfree(maui_os); + vfree(maui_os); unload_maui(&cfg); SOUND_LOCK_END; } diff --git a/drivers/sound/midibuf.c b/drivers/sound/midibuf.c index 09dea3a34..50d595d2f 100644 --- a/drivers/sound/midibuf.c +++ b/drivers/sound/midibuf.c @@ -15,6 +15,7 @@ */ #include <linux/config.h> #include <linux/stddef.h> +#include <linux/kmod.h> #define MIDIBUF_C diff --git a/drivers/sound/opl3sa.c b/drivers/sound/opl3sa.c index 39adf4357..86fe07f10 100644 --- a/drivers/sound/opl3sa.c +++ b/drivers/sound/opl3sa.c @@ -3,14 +3,21 @@ * * Low level driver for Yamaha YMF701B aka OPL3-SA chip * - */ -/* + * + * * 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. + * + * Changes: + * Alan Cox Modularisation + * + * FIXME: + * Check for install of mpu etc is wrong, should check result of the mss stuff */ + #include <linux/config.h> #undef SB_OK @@ -18,22 +25,21 @@ #include "sound_config.h" #ifdef SB_OK #include "sb.h" -static int sb_initialized = 0; +static int sb_initialized = 0; #endif #ifdef CONFIG_OPL3SA1 -static int kilroy_was_here = 0; /* Don't detect twice */ -static int mpu_initialized = 0; +static int kilroy_was_here = 0; /* Don't detect twice */ +static int mpu_initialized = 0; -static int *opl3sa_osp = NULL; +static int *opl3sa_osp = NULL; -static unsigned char -opl3sa_read(int addr) +static unsigned char opl3sa_read(int addr) { - unsigned long flags; - unsigned char tmp; + unsigned long flags; + unsigned char tmp; save_flags(flags); cli(); @@ -45,10 +51,9 @@ opl3sa_read(int addr) return tmp; } -static void -opl3sa_write(int addr, int data) +static void opl3sa_write(int addr, int data) { - unsigned long flags; + unsigned long flags; save_flags(flags); cli(); @@ -58,31 +63,32 @@ opl3sa_write(int addr, int data) restore_flags(flags); } -static int -opl3sa_detect(void) +static int opl3sa_detect(void) { - int tmp; + int tmp; if (((tmp = opl3sa_read(0x01)) & 0xc4) != 0x04) - { - DDB(printk("OPL3-SA detect error 1 (%x)\n", opl3sa_read(0x01))); - /* return 0; */ - } -/* - * Check that the password feature has any effect - */ + { + DDB(printk("OPL3-SA detect error 1 (%x)\n", opl3sa_read(0x01))); + /* return 0; */ + } + + /* + * Check that the password feature has any effect + */ + if (inb(0xf87) == tmp) - { - DDB(printk("OPL3-SA detect failed 2 (%x/%x)\n", tmp, inb(0xf87))); - return 0; - } + { + DDB(printk("OPL3-SA detect failed 2 (%x/%x)\n", tmp, inb(0xf87))); + return 0; + } tmp = (opl3sa_read(0x04) & 0xe0) >> 5; if (tmp != 0 && tmp != 1) - { - DDB(printk("OPL3-SA detect failed 3 (%d)\n", tmp)); - return 0; - } + { + DDB(printk("OPL3-SA detect failed 3 (%d)\n", tmp)); + return 0; + } DDB(printk("OPL3-SA mode %x detected\n", tmp)); opl3sa_write(0x01, 0x00); /* Disable MSS */ @@ -97,49 +103,50 @@ opl3sa_detect(void) * OPL3-SA */ -int -probe_opl3sa_wss(struct address_info *hw_config) +int probe_opl3sa_wss(struct address_info *hw_config) { - int ret; - unsigned char tmp = 0x24; /* WSS enable */ + int ret; + unsigned char tmp = 0x24; /* WSS enable */ if (check_region(0xf86, 2)) /* Control port is busy */ return 0; /* - * Check if the IO port returns valid signature. The original MS Sound - * system returns 0x04 while some cards (OPL3-SA for example) - * return 0x00. + * Check if the IO port returns valid signature. The original MS Sound + * system returns 0x04 while some cards (OPL3-SA for example) + * return 0x00. */ + if (check_region(hw_config->io_base, 8)) - { - printk("OPL3-SA: MSS I/O port conflict (%x)\n", hw_config->io_base); - return 0; - } + { + printk(KERN_ERR "OPL3-SA: MSS I/O port conflict (%x)\n", hw_config->io_base); + return 0; + } opl3sa_osp = hw_config->osp; if (!opl3sa_detect()) - { - printk("OSS: OPL3-SA chip not found\n"); - return 0; - } + { + printk(KERN_ERR "OSS: OPL3-SA chip not found\n"); + return 0; + } + switch (hw_config->io_base) - { - case 0x530: - tmp |= 0x00; - break; - case 0xe80: - tmp |= 0x08; - break; - case 0xf40: - tmp |= 0x10; - break; - case 0x604: - tmp |= 0x18; - break; - default: - printk("OSS: Unsupported OPL3-SA/WSS base %x\n", hw_config->io_base); + { + case 0x530: + tmp |= 0x00; + break; + case 0xe80: + tmp |= 0x08; + break; + case 0xf40: + tmp |= 0x10; + break; + case 0x604: + tmp |= 0x18; + break; + default: + printk(KERN_ERR "OSS: Unsupported OPL3-SA/WSS base %x\n", hw_config->io_base); return 0; - } + } opl3sa_write(0x01, tmp); /* WSS setup register */ kilroy_was_here = 1; @@ -151,23 +158,21 @@ probe_opl3sa_wss(struct address_info *hw_config) return ret; } -void -attach_opl3sa_wss(struct address_info *hw_config) +void attach_opl3sa_wss(struct address_info *hw_config) { - int nm = num_mixers; + int nm = num_mixers; attach_ms_sound(hw_config); if (num_mixers > nm) /* A mixer was installed */ - { - AD1848_REROUTE(SOUND_MIXER_LINE1, SOUND_MIXER_CD); - AD1848_REROUTE(SOUND_MIXER_LINE2, SOUND_MIXER_SYNTH); - AD1848_REROUTE(SOUND_MIXER_LINE3, SOUND_MIXER_LINE); - } + { + AD1848_REROUTE(SOUND_MIXER_LINE1, SOUND_MIXER_CD); + AD1848_REROUTE(SOUND_MIXER_LINE2, SOUND_MIXER_SYNTH); + AD1848_REROUTE(SOUND_MIXER_LINE3, SOUND_MIXER_LINE); + } } -void -attach_opl3sa_mpu(struct address_info *hw_config) +void attach_opl3sa_mpu(struct address_info *hw_config) { #if defined(CONFIG_UART401) && defined(CONFIG_MIDI) hw_config->name = "OPL3-SA (MPU401)"; @@ -175,55 +180,54 @@ attach_opl3sa_mpu(struct address_info *hw_config) #endif } -int -probe_opl3sa_mpu(struct address_info *hw_config) +int probe_opl3sa_mpu(struct address_info *hw_config) { #if defined(CONFIG_UART401) && defined(CONFIG_MIDI) - unsigned char conf; - static char irq_bits[] = - {-1, -1, -1, -1, -1, 1, -1, 2, -1, 3, 4}; + unsigned char conf; + static char irq_bits[] = { + -1, -1, -1, -1, -1, 1, -1, 2, -1, 3, 4 + }; if (!kilroy_was_here) - { - return 0; /* OPL3-SA has not been detected earlier */ - } + return 0; /* OPL3-SA has not been detected earlier */ + if (mpu_initialized) - { - DDB(printk("OPL3-SA: MPU mode already initialized\n")); - return 0; - } + { + DDB(printk("OPL3-SA: MPU mode already initialized\n")); + return 0; + } if (check_region(hw_config->io_base, 4)) - { - printk("OPL3-SA: MPU I/O port conflict (%x)\n", hw_config->io_base); - return 0; - } + { + printk(KERN_ERR "OPL3-SA: MPU I/O port conflict (%x)\n", hw_config->io_base); + return 0; + } if (hw_config->irq > 10) - { - printk("OPL3-SA: Bad MPU IRQ %d\n", hw_config->irq); - return 0; - } + { + printk(KERN_ERR "OPL3-SA: Bad MPU IRQ %d\n", hw_config->irq); + return 0; + } if (irq_bits[hw_config->irq] == -1) - { - printk("OPL3-SA: Bad MPU IRQ %d\n", hw_config->irq); - return 0; - } + { + printk(KERN_ERR "OPL3-SA: Bad MPU IRQ %d\n", hw_config->irq); + return 0; + } switch (hw_config->io_base) - { - case 0x330: - conf = 0x00; - break; - case 0x332: - conf = 0x20; - break; - case 0x334: - conf = 0x40; - break; - case 0x300: - conf = 0x60; - break; - default: - return 0; /* Invalid port */ - } + { + case 0x330: + conf = 0x00; + break; + case 0x332: + conf = 0x20; + break; + case 0x334: + conf = 0x40; + break; + case 0x300: + conf = 0x60; + break; + default: + return 0; /* Invalid port */ + } conf |= 0x83; /* MPU & OPL3 (synth) & game port enable */ conf |= irq_bits[hw_config->irq] << 2; @@ -238,10 +242,9 @@ probe_opl3sa_mpu(struct address_info *hw_config) #endif } -void -unload_opl3sa_wss(struct address_info *hw_config) +void unload_opl3sa_wss(struct address_info *hw_config) { - int dma2 = hw_config->dma2; + int dma2 = hw_config->dma2; if (dma2 == -1) dma2 = hw_config->dma; @@ -256,16 +259,15 @@ unload_opl3sa_wss(struct address_info *hw_config) 0); } -void -unload_opl3sa_mpu(struct address_info *hw_config) +void unload_opl3sa_mpu(struct address_info *hw_config) { #if defined(CONFIG_UART401) && defined(CONFIG_MIDI) unload_uart401(hw_config); #endif } + #ifdef SB_OK -void -unload_opl3sa_sb(struct address_info *hw_config) +void unload_opl3sa_sb(struct address_info *hw_config) { #ifdef CONFIG_SBDSP sb_dsp_unload(hw_config); @@ -273,5 +275,60 @@ unload_opl3sa_sb(struct address_info *hw_config) } #endif +#ifdef MODULE +int io = -1; +int irq = -1; +int dma = -1; +int dma2 = -1; + +int mpu_io = -1; +int mpu_irq = -1; + +MODULE_PARM(io,"i"); +MODULE_PARM(irq,"i"); +MODULE_PARM(dma,"i"); +MODULE_PARM(dma2,"i"); +MODULE_PARM(mpu_io,"i"); +MODULE_PARM(mpu_irq,"i"); + +struct address_info cfg; +struct address_info mpu_cfg; + +int init_module(void) +{ + 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; + + if (probe_opl3sa_wss(&cfg) == 0) + return -ENODEV; + + found_mpu=probe_opl3_mpu(&mpu_cfg); + + attach_opl3sa_wss(&cfg); + if(found_mpu) + attach_opl3sa_mpu(&mpu_cfg); + SOUND_LOCK; + return 0; +} + +void cleanup_module(void) +{ + if(found_mpu) + unload_opl3sa_mpu(&mpu_cfg); + unload_opl3sa(&cfg); + SOUND_LOCK_END; +} + +#endif #endif diff --git a/drivers/sound/os.h b/drivers/sound/os.h index 5bd4a27eb..31fcc81f7 100644 --- a/drivers/sound/os.h +++ b/drivers/sound/os.h @@ -18,6 +18,7 @@ #include <linux/string.h> #include <linux/fs.h> #include <asm/dma.h> +#include <asm/io.h> #include <asm/param.h> #include <linux/ptrace.h> #include <linux/sched.h> @@ -32,7 +33,6 @@ #include <asm/uaccess.h> #include <linux/poll.h> #include <linux/pci.h> -#include <linux/bios32.h> #endif #include <linux/wrapper.h> @@ -52,7 +52,6 @@ extern void reprogram_timer(void); #define USE_AUTOINIT_DMA extern caddr_t sound_mem_blocks[1024]; -extern int sound_mem_sizes[1024]; extern int sound_nblocks; #undef PSEUDO_DMA_AUTOINIT diff --git a/drivers/sound/pas2_card.c b/drivers/sound/pas2_card.c index e00108b0b..8eb29e729 100644 --- a/drivers/sound/pas2_card.c +++ b/drivers/sound/pas2_card.c @@ -37,6 +37,11 @@ int translate_code = 0; static int pas_intr_mask = 0; static int pas_irq = 0; static int pas_sb_base = 0; +#ifndef CONFIG_PAS_JOYSTICK +static int joystick = 0; +#else +static int joystick = 1; +#endif char pas_model = 0; @@ -142,9 +147,7 @@ static int config_pas_hw(struct address_info *hw_config) */ , 0xB88); pas_write(0x80 -#ifdef PAS_JOYSTICK_ENABLE - | 0x40 -#endif + | joystick?0x40:0 ,0xF388); if (pas_irq < 0 || pas_irq > 15) @@ -164,7 +167,7 @@ static int config_pas_hw(struct address_info *hw_config) } else { - if (request_irq(pas_irq, pasintr, 0, "PAS16", NULL) < 0) + if (request_irq(pas_irq, pasintr, 0, "PAS16",NULL) < 0) ok = 0; } } @@ -380,6 +383,8 @@ MODULE_PARM(sb_irq,"i"); MODULE_PARM(sb_dma,"i"); MODULE_PARM(sb_dma16,"i"); +MODULE_PARM(joystick,"i"); + struct address_info config; struct address_info sbhw_config; diff --git a/drivers/sound/pss.c b/drivers/sound/pss.c index 7a0a2e66e..9b00aa43a 100644 --- a/drivers/sound/pss.c +++ b/drivers/sound/pss.c @@ -2,18 +2,29 @@ * sound/pss.c * * The low level driver for the Personal Sound System (ECHO ESC614). - */ -/* + * + * * 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) * Alan Cox modularisation, clean up. + * + * 98-02-21: Vladimir Michl <vladimir.michl@upol.cz> + * Added mixer device for Beethoven ADSP-16 (master volume, + * bass, treble, synth), only for speakers. + * Fixed bug in pss_write (exchange parameters) + * Fixed config port of SB + * Requested two regions for PSS (PSS mixer, PSS config) + * Modified pss_download_boot + * To probe_pss_mss added test for initialize AD1848 */ + + #include <linux/config.h> #include <linux/module.h> @@ -39,7 +50,7 @@ */ #define CONF_PSS 0x10 #define CONF_WSS 0x12 -#define CONF_SB 0x13 +#define CONF_SB 0x14 #define CONF_CDROM 0x16 #define CONF_MIDI 0x18 @@ -53,6 +64,20 @@ #define PSS_WRITE_EMPTY 0x8000 #define PSS_READ_FULL 0x4000 +/* + * WSS registers + */ +#define WSS_INDEX 4 +#define WSS_DATA 5 + +/* + * WSS status bits + */ +#define WSS_INITIALIZING 0x80 +#define WSS_AUTOCALIBRATION 0x20 + +#define NO_WSS_MIXER -1 + #include "coproc.h" #ifdef CONFIG_PSS_HAVE_BOOT @@ -62,23 +87,32 @@ static unsigned char *pss_synth = NULL; static int pss_synthLen = 0; #endif -typedef struct pss_confdata -{ - int base; - int irq; - int dma; - int *osp; -} - -pss_confdata; - +unsigned char pss_mixer = 1; + +typedef struct pss_mixerdata { + unsigned int volume_l; + unsigned int volume_r; + unsigned int bass; + unsigned int treble; + unsigned int synth; +} pss_mixerdata; + +typedef struct pss_confdata { + int base; + int irq; + int dma; + int *osp; + pss_mixerdata mixer; + int ad_mixer_dev; +} pss_confdata; + static pss_confdata pss_data; static pss_confdata *devc = &pss_data; static int pss_initialized = 0; static int nonstandard_microcode = 0; -static void pss_write(int data) +static void pss_write(pss_confdata *devc, int data) { int i, limit; @@ -92,14 +126,14 @@ static void pss_write(int data) */ for (i = 0; i < 5000000 && jiffies < limit; i++) - { - if (inw(devc->base + PSS_STATUS) & PSS_WRITE_EMPTY) - { - outw(devc->base + PSS_DATA, data); - return; - } - } - printk(KERN_ERR "PSS: DSP Command (%04x) Timeout.\n", data); + { + if (inw(REG(PSS_STATUS)) & PSS_WRITE_EMPTY) + { + outw(data, REG(PSS_DATA)); + return; + } + } + printk(KERN_WARNING "PSS: DSP Command (%04x) Timeout.\n", data); } int probe_pss(struct address_info *hw_config) @@ -116,7 +150,7 @@ int probe_pss(struct address_info *hw_config) if (devc->base != 0x230 && devc->base != 0x250) /* Some cards use these */ return 0; - if (check_region(devc->base, 16)) { + if (check_region(devc->base, 0x19 /*16*/)) { printk(KERN_ERR "PSS: I/O port conflict\n"); return 0; } @@ -249,7 +283,7 @@ static int pss_download_boot(pss_confdata * devc, unsigned char *block, int size pss_reset_dsp(devc); } count = 1; - while (1) + while ((flags&CPF_LAST) || count<size ) { int j; @@ -267,12 +301,22 @@ static int pss_download_boot(pss_confdata * devc, unsigned char *block, int size break; else { - printk("\nPSS: Download timeout problems, byte %d=%d\n", count, size); + printk("\n"); + printk(KERN_ERR "PSS: Download timeout problems, byte %d=%d\n", count, size); return 0; } } /*_____ Send the next byte */ - outw(*block++, REG(PSS_DATA)); + if (count >= size) + { + /* If not data in block send 0xffff */ + outw (0xffff, REG (PSS_DATA)); + } + else + { + /*_____ Send the next byte */ + outw (*block++, REG (PSS_DATA)); + }; count++; } @@ -309,6 +353,237 @@ static int pss_download_boot(pss_confdata * devc, unsigned char *block, int size return 1; } +/* Mixer */ +static void set_master_volume(pss_confdata *devc, int left, int right) +{ + static unsigned char log_scale[101] = { + 0xdb, 0xe0, 0xe3, 0xe5, 0xe7, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xed, 0xee, + 0xef, 0xef, 0xf0, 0xf0, 0xf1, 0xf1, 0xf2, 0xf2, 0xf2, 0xf3, 0xf3, 0xf3, + 0xf4, 0xf4, 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6, 0xf7, + 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, + 0xf9, 0xf9, 0xf9, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, + 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, + 0xfc, 0xfc, 0xfc, 0xfc, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, + 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, + 0xfe, 0xfe, 0xff, 0xff, 0xff + }; + pss_write(devc, 0x0010); + pss_write(devc, log_scale[left] | 0x0000); + pss_write(devc, 0x0010); + pss_write(devc, log_scale[right] | 0x0100); +} + +static void set_synth_volume(pss_confdata *devc, int volume) +{ + /* Should use: + int vol = (int)(0x8000/100.0 * (float)volume); + + Fixme: integerise the above cleanly + */ + int vol = (0x8000/(100L*volume)); + pss_write(devc, 0x0080); + pss_write(devc, vol); + pss_write(devc, 0x0081); + pss_write(devc, vol); +} + +static void set_bass(pss_confdata *devc, int level) +{ + /* Should use + int vol = (int)((0xfd - 0xf0)/100.0 * (float)level) + 0xf0; + + Fixme: integerise cleanly + */ + int vol = (int)((0xfd - 0xf0)/100L * level) + 0xf0; + pss_write(devc, 0x0010); + pss_write(devc, vol | 0x0200); +}; + +static void set_treble(pss_confdata *devc, int level) +{ + /* Should use + int vol = (int)((0xfd - 0xf0)/100.0 * (float)level) + 0xf0; + + Fixme: integerise properly + */ + + int vol = ((0xfd - 0xf0)/100L * level) + 0xf0; + pss_write(devc, 0x0010); + pss_write(devc, vol | 0x0300); +}; + +static void pss_mixer_reset(pss_confdata *devc) +{ + set_master_volume(devc, 23, 23); + set_bass(devc, 50); + set_treble(devc, 50); + set_synth_volume(devc, 30); + pss_write (devc, 0x0010); + pss_write (devc, 0x0800 | 0xce); /* Stereo */ + + if(pss_mixer) + { + devc->mixer.volume_l = devc->mixer.volume_r = 23; + devc->mixer.bass = 50; + devc->mixer.treble = 50; + devc->mixer.synth = 30; + } +} + +static void arg_to_volume_mono(unsigned int volume, int *aleft) +{ + int left; + + left = volume & 0x00ff; + if (left > 100) + left = 100; + *aleft = left; +} + +static void arg_to_volume_stereo(unsigned int volume, int *aleft, int *aright) +{ + arg_to_volume_mono(volume, aleft); + arg_to_volume_mono(volume >> 8, aright); +} + +static int ret_vol_mono(int left) +{ + return ((left << 8) | left); +} + +static int ret_vol_stereo(int left, int right) +{ + return ((right << 8) | left); +} + +static int call_ad_mixer(pss_confdata *devc,unsigned int cmd, caddr_t arg) +{ + if (devc->ad_mixer_dev != NO_WSS_MIXER) + return mixer_devs[devc->ad_mixer_dev]->ioctl(devc->ad_mixer_dev, cmd, arg); + else + return -EINVAL; +} + +static int pss_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg) +{ + pss_confdata *devc = mixer_devs[dev]->devc; + int cmdf = cmd & 0xff; + + if ((cmdf != SOUND_MIXER_VOLUME) && (cmdf != SOUND_MIXER_BASS) && + (cmdf != SOUND_MIXER_TREBLE) && (cmdf != SOUND_MIXER_SYNTH) && + (cmdf != SOUND_MIXER_DEVMASK) && (cmdf != SOUND_MIXER_STEREODEVS) && + (cmdf != SOUND_MIXER_RECMASK) && (cmdf != SOUND_MIXER_CAPS) && + (cmdf != SOUND_MIXER_RECSRC)) + { + return call_ad_mixer(devc, cmd, arg); + } + + if (((cmd >> 8) & 0xff) != 'M') + return -EINVAL; + + if (_SIOC_DIR (cmd) & _SIOC_WRITE) + { + switch (cmdf) + { + case SOUND_MIXER_RECSRC: + if (devc->ad_mixer_dev != NO_WSS_MIXER) + return call_ad_mixer(devc, cmd, arg); + else + { + if (*(int *)arg != 0) + return -EINVAL; + return 0; + } + case SOUND_MIXER_VOLUME: + arg_to_volume_stereo(*(unsigned int *)arg, &devc->mixer.volume_l, + &devc->mixer.volume_r); + set_master_volume(devc, devc->mixer.volume_l, + devc->mixer.volume_r); + return ret_vol_stereo(devc->mixer.volume_l, + devc->mixer.volume_r); + + case SOUND_MIXER_BASS: + arg_to_volume_mono(*(unsigned int *)arg, + &devc->mixer.bass); + set_bass(devc, devc->mixer.bass); + return ret_vol_mono(devc->mixer.bass); + + case SOUND_MIXER_TREBLE: + arg_to_volume_mono(*(unsigned int *)arg, + &devc->mixer.treble); + set_treble(devc, devc->mixer.treble); + return ret_vol_mono(devc->mixer.treble); + + case SOUND_MIXER_SYNTH: + arg_to_volume_mono(*(unsigned int *)arg, + &devc->mixer.synth); + set_synth_volume(devc, devc->mixer.synth); + return ret_vol_mono(devc->mixer.synth); + + default: + return -EINVAL; + } + } + else + { + /* + * Return parameters + */ + switch (cmdf) + { + + case SOUND_MIXER_DEVMASK: + if (call_ad_mixer(devc, cmd, arg) == -EINVAL) + *(int *)arg = 0; /* no mixer devices */ + return (*(int *)arg |= SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE | SOUND_MASK_SYNTH); + + case SOUND_MIXER_STEREODEVS: + if (call_ad_mixer(devc, cmd, arg) == -EINVAL) + *(int *)arg = 0; /* no stereo devices */ + return (*(int *)arg |= SOUND_MASK_VOLUME); + + case SOUND_MIXER_RECMASK: + if (devc->ad_mixer_dev != NO_WSS_MIXER) + return call_ad_mixer(devc, cmd, arg); + else + return (*(int *)arg = 0); /* no record devices */ + + case SOUND_MIXER_CAPS: + if (devc->ad_mixer_dev != NO_WSS_MIXER) + return call_ad_mixer(devc, cmd, arg); + else + return (*(int *)arg = SOUND_CAP_EXCL_INPUT); + + case SOUND_MIXER_RECSRC: + if (devc->ad_mixer_dev != NO_WSS_MIXER) + return call_ad_mixer(devc, cmd, arg); + else + return (*(int *)arg = 0); /* no record source */ + + case SOUND_MIXER_VOLUME: + return (*(int *)arg = ret_vol_stereo(devc->mixer.volume_l, devc->mixer.volume_r)); + + case SOUND_MIXER_BASS: + return (*(int *)arg = ret_vol_mono(devc->mixer.bass)); + + case SOUND_MIXER_TREBLE: + return (*(int *)arg = ret_vol_mono(devc->mixer.treble)); + + case SOUND_MIXER_SYNTH: + return (*(int *)arg = ret_vol_mono(devc->mixer.synth)); + default: + return -EINVAL; + } + } +} + +static struct mixer_operations pss_mixer_operations = +{ + "SOUNDPORT", + "PSS-AD1848", + pss_mixer_ioctl +}; + void attach_pss(struct address_info *hw_config) { unsigned short id; @@ -318,10 +593,14 @@ void attach_pss(struct address_info *hw_config) devc->irq = hw_config->irq; devc->dma = hw_config->dma; devc->osp = hw_config->osp; + devc->ad_mixer_dev = NO_WSS_MIXER; if (!probe_pss(hw_config)) return; + request_region(hw_config->io_base, 0x10, "PSS mixer, SB emulation"); + request_region(hw_config->io_base + 0x10, 0x9, "PSS config"); + id = inw(REG(PSS_ID)) & 0x00ff; /* @@ -356,21 +635,6 @@ void attach_pss(struct address_info *hw_config) conf_printf(tmp, hw_config); } -static void pss_init_speaker(void) -{ -/* Don't ask what are these commands. I really don't know */ - pss_write(0x0010); - pss_write(0x0000 | 252); /* Left master volume */ - pss_write(0x0010); - pss_write(0x0100 | 252); /* Right master volume */ - pss_write(0x0010); - pss_write(0x0200 | 246); /* Bass */ - pss_write(0x0010); - pss_write(0x0300 | 246); /* Treble */ - pss_write(0x0010); - pss_write(0x0800 | 0x00ce); /* Stereo switch? */ -} - int probe_pss_mpu(struct address_info *hw_config) { int timeout; @@ -380,17 +644,17 @@ int probe_pss_mpu(struct address_info *hw_config) if (check_region(hw_config->io_base, 2)) { - printk("PSS: MPU I/O port conflict\n"); + printk(KERN_ERR "PSS: MPU I/O port conflict\n"); return 0; } if (!set_io_base(devc, CONF_MIDI, hw_config->io_base)) { - printk("PSS: MIDI base could not be set.\n"); + printk(KERN_ERR "PSS: MIDI base could not be set.\n"); return 0; } if (!set_irq(devc, CONF_MIDI, hw_config->irq)) { - printk("PSS: MIDI IRQ allocation error.\n"); + printk(KERN_ERR "PSS: MIDI IRQ allocation error.\n"); return 0; } if (!pss_synthLen) @@ -403,7 +667,6 @@ int probe_pss_mpu(struct address_info *hw_config) printk(KERN_ERR "PSS: Unable to load MIDI synth microcode to DSP.\n"); return 0; } - pss_init_speaker(); /* * Finally wait until the DSP algorithm has initialized itself and @@ -709,28 +972,51 @@ 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 + 3) & 0x3f) != 0x04; - 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 */ - outb((0x0b), hw_config->io_base + 4); /* Required by some cards */ + for (timeout = 0; (inb(hw_config->io_base + WSS_DATA) & WSS_AUTOCALIBRATION) && (timeout < 100000); timeout++); - for (timeout = 0; - timeout < 100000; - timeout++); return probe_ms_sound(hw_config); } void attach_pss_mss(struct address_info *hw_config) { + int my_mix = -999; /* gcc shut up */ + + devc->ad_mixer_dev = NO_WSS_MIXER; + if (pss_mixer) + { + if ((my_mix = sound_install_mixer (MIXER_DRIVER_VERSION, + "PSS-SPEAKERS and AD1848 (through MSS audio codec)", + &pss_mixer_operations, + sizeof (struct mixer_operations), + devc)) < 0) + { + printk(KERN_ERR "Could not install PSS mixer\n"); + return; + } + } + pss_mixer_reset(devc); attach_ms_sound(hw_config); /* Slot 0 */ - if (hw_config->slots[0] != -1) /* The MSS driver installed itself */ + if (hw_config->slots[0] != -1) + { + /* The MSS driver installed itself */ audio_devs[hw_config->slots[0]]->coproc = &pss_coproc_operations; + if (pss_mixer && (num_mixers == (my_mix + 2))) + { + /* The MSS mixer installed */ + devc->ad_mixer_dev = audio_devs[hw_config->slots[0]]->mixer_dev; + } + } } void 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) @@ -761,11 +1047,21 @@ 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 }; MODULE_PARM(pss_io, "i"); +MODULE_PARM_DESC(pss_io, "Set i/o base of PSS card (probably 0x220 or 0x240)"); MODULE_PARM(mss_io, "i"); +MODULE_PARM_DESC(mss_io, "Set WSS (audio) i/o base (0x530, 0x604, 0xE80, 0xF40, or other. Address must end in 0 or 4 and must be from 0x100 to 0xFF4)"); MODULE_PARM(mss_irq, "i"); +MODULE_PARM_DESC(mss_irq, "Set WSS (audio) IRQ (3, 5, 7, 9, 10, 11, 12)"); MODULE_PARM(mss_dma, "i"); +MODULE_PARM_DESC(mss_dma, "Set WSS (audio) DMA (0, 1, 3)"); MODULE_PARM(mpu_io, "i"); +MODULE_PARM_DESC(mpu_io, "Set MIDI i/o base (0x330 or other. Address must be on 4 location boundaries and must be from 0x100 to 0xFFC)"); MODULE_PARM(mpu_irq, "i"); +MODULE_PARM_DESC(mpu_irq, "Set MIDI IRQ (3, 5, 7, 9, 10, 11, 12)"); +MODULE_PARM(pss_mixer, "b"); +MODULE_PARM_DESC(pss_mixer, "Enable (1) or disable (0) PSS mixer (controlling of output volume, bass, treble synth volume). The mixer is not available on all PSS cards."); +MODULE_AUTHOR("Hannu Savolainen, Vladimir Michl"); +MODULE_DESCRIPTION("Module for PSS sound cards (based on AD1848, ADSP-2115 and ESC614). This module includes control of output amplifier and synth volume of the Beethoven ADSP-16 card (this may work with other PSS cards).\n"); static int fw_load = 0; static int pssmpu = 0, pssmss = 0; @@ -816,7 +1112,7 @@ int init_module(void) void cleanup_module(void) { if (fw_load && pss_synth) - kfree(pss_synth); + vfree(pss_synth); if (pssmss) unload_pss_mss(&cfgmss); if (pssmpu) @@ -825,5 +1121,4 @@ void cleanup_module(void) SOUND_LOCK_END; } #endif - #endif diff --git a/drivers/sound/sb.h b/drivers/sound/sb.h index 431645165..4567d3f5b 100644 --- a/drivers/sound/sb.h +++ b/drivers/sound/sb.h @@ -47,6 +47,8 @@ #define MDL_ES1868MIDI 14 /* MIDI port of ESS1868 */ #define MDL_AEDSP 15 /* Audio Excel DSP 16 */ +#define SUBMDL_ALS007 42 /* ALS-007 differs from SB16 only in mixer */ + /* register assignment */ /* * Config flags */ diff --git a/drivers/sound/sb_audio.c b/drivers/sound/sb_audio.c index bf3a8dbef..f9465cfe5 100644 --- a/drivers/sound/sb_audio.c +++ b/drivers/sound/sb_audio.c @@ -2,17 +2,22 @@ * sound/sb_audio.c * * Audio routines for Sound Blaster compatible cards. - */ -/* + * + * * 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. + * + * Changes + * Alan Cox : Formatting and clean ups + * + * Status + * Mostly working. mmap bug still present (swaps channels) */ -#include <linux/config.h> - +#include <linux/config.h> #include "sound_config.h" #if defined(CONFIG_SBDSP) || defined(MODULE) @@ -20,67 +25,84 @@ #include "sb_mixer.h" #include "sb.h" -static int -sb_audio_open(int dev, int mode) +static int sb_audio_open(int dev, int mode) { - sb_devc *devc = audio_devs[dev]->devc; - unsigned long flags; + sb_devc *devc = audio_devs[dev]->devc; + unsigned long flags; if (devc == NULL) - { - printk("SB: Incomplete initialization\n"); + { + printk(KERN_ERR "SB: Incomplete initialization\n"); return -ENXIO; - } + } if (devc->caps & SB_NO_RECORDING && mode & OPEN_READ) - { - printk("Notice: Recording is not possible with /dev/dsp%d\n", dev); - if (mode == OPEN_READ) - return -EPERM; - } + { + if (mode == OPEN_READ) + return -EPERM; + } save_flags(flags); cli(); if (devc->opened) - { + { restore_flags(flags); return -EBUSY; - } + } if (devc->dma16 != -1 && devc->dma16 != devc->dma8) - { - if (sound_open_dma(devc->dma16, "Sound Blaster 16 bit")) - { - restore_flags(flags); - return -EBUSY; - } - } + { + if (sound_open_dma(devc->dma16, "Sound Blaster 16 bit")) + { + restore_flags(flags); + return -EBUSY; + } + } devc->opened = mode; restore_flags(flags); devc->irq_mode = IMODE_NONE; sb_dsp_reset(devc); + /* The ALS007 seems to require that the DSP be removed from the output */ + /* in order for recording to be activated properly. This is done by */ + /* setting the appropriate bits of the output control register 4ch to */ + /* zero. This code assumes that the output control registers are not */ + /* used anywhere else and therefore the DSP bits are *always* ON for */ + /* output and OFF for sampling. */ + + if (devc->submodel == SUBMDL_ALS007) + { + if (mode & OPEN_READ) + sb_setmixer(devc,ALS007_OUTPUT_CTRL2, + sb_getmixer(devc,ALS007_OUTPUT_CTRL2) & 0xf9); + else + sb_setmixer(devc,ALS007_OUTPUT_CTRL2, + sb_getmixer(devc,ALS007_OUTPUT_CTRL2) | 0x06); + } return 0; } -static void -sb_audio_close(int dev) +static void sb_audio_close(int dev) { - sb_devc *devc = audio_devs[dev]->devc; + sb_devc *devc = audio_devs[dev]->devc; - audio_devs[dev]->dmap_in->dma = - audio_devs[dev]->dmap_out->dma = - devc->dma8; + audio_devs[dev]->dmap_in->dma = audio_devs[dev]->dmap_out->dma = devc->dma8; if (devc->dma16 != -1 && devc->dma16 != devc->dma8) sound_close_dma(devc->dma16); + /* For ALS007, turn DSP output back on if closing the device for read */ + + if ((devc->submodel == SUBMDL_ALS007) && (devc->opened & OPEN_READ)) + { + sb_setmixer(devc,ALS007_OUTPUT_CTRL2, + sb_getmixer(devc,ALS007_OUTPUT_CTRL2) | 0x06); + } devc->opened = 0; } -static void -sb_set_output_parms(int dev, unsigned long buf, int nr_bytes, +static void sb_set_output_parms(int dev, unsigned long buf, int nr_bytes, int intrflag) { - sb_devc *devc = audio_devs[dev]->devc; + sb_devc *devc = audio_devs[dev]->devc; devc->trg_buf = buf; devc->trg_bytes = nr_bytes; @@ -88,10 +110,9 @@ sb_set_output_parms(int dev, unsigned long buf, int nr_bytes, devc->irq_mode = IMODE_OUTPUT; } -static void -sb_set_input_parms(int dev, unsigned long buf, int count, int intrflag) +static void sb_set_input_parms(int dev, unsigned long buf, int count, int intrflag) { - sb_devc *devc = audio_devs[dev]->devc; + sb_devc *devc = audio_devs[dev]->devc; devc->trg_buf = buf; devc->trg_bytes = count; @@ -103,13 +124,11 @@ sb_set_input_parms(int dev, unsigned long buf, int count, int intrflag) * SB1.x compatible routines */ -static void -sb1_audio_output_block(int dev, unsigned long buf, int nr_bytes, - int intrflag) +static void sb1_audio_output_block(int dev, unsigned long buf, int nr_bytes, int intrflag) { - unsigned long flags; - int count = nr_bytes; - sb_devc *devc = audio_devs[dev]->devc; + unsigned long flags; + int count = nr_bytes; + sb_devc *devc = audio_devs[dev]->devc; /* DMAbuf_start_dma (dev, buf, count, DMA_MODE_WRITE); */ @@ -122,21 +141,21 @@ sb1_audio_output_block(int dev, unsigned long buf, int nr_bytes, save_flags(flags); cli(); if (sb_dsp_command(devc, 0x14)) /* 8 bit DAC using DMA */ - { - sb_dsp_command(devc, (unsigned char) (count & 0xff)); - sb_dsp_command(devc, (unsigned char) ((count >> 8) & 0xff)); - } else - printk("SB: Unable to start DAC\n"); + { + sb_dsp_command(devc, (unsigned char) (count & 0xff)); + sb_dsp_command(devc, (unsigned char) ((count >> 8) & 0xff)); + } + else + printk(KERN_WARNING "soundblaster: Unable to start DAC\n"); restore_flags(flags); devc->intr_active = 1; } -static void -sb1_audio_start_input(int dev, unsigned long buf, int nr_bytes, int intrflag) +static void sb1_audio_start_input(int dev, unsigned long buf, int nr_bytes, int intrflag) { - unsigned long flags; - int count = nr_bytes; - sb_devc *devc = audio_devs[dev]->devc; + unsigned long flags; + int count = nr_bytes; + sb_devc *devc = audio_devs[dev]->devc; /* * Start a DMA input to the buffer pointed by dmaqtail @@ -153,49 +172,47 @@ sb1_audio_start_input(int dev, unsigned long buf, int nr_bytes, int intrflag) save_flags(flags); cli(); if (sb_dsp_command(devc, 0x24)) /* 8 bit ADC using DMA */ - { - sb_dsp_command(devc, (unsigned char) (count & 0xff)); - sb_dsp_command(devc, (unsigned char) ((count >> 8) & 0xff)); - } else - printk("SB Error: Unable to start ADC\n"); + { + sb_dsp_command(devc, (unsigned char) (count & 0xff)); + sb_dsp_command(devc, (unsigned char) ((count >> 8) & 0xff)); + } + else + printk(KERN_ERR "soundblaster: Unable to start ADC\n"); restore_flags(flags); devc->intr_active = 1; } -static void -sb1_audio_trigger(int dev, int bits) +static void sb1_audio_trigger(int dev, int bits) { - sb_devc *devc = audio_devs[dev]->devc; + sb_devc *devc = audio_devs[dev]->devc; bits &= devc->irq_mode; if (!bits) sb_dsp_command(devc, 0xd0); /* Halt DMA */ else - { - switch (devc->irq_mode) - { - case IMODE_INPUT: - sb1_audio_start_input(dev, devc->trg_buf, devc->trg_bytes, - devc->trg_intrflag); - break; - - case IMODE_OUTPUT: - sb1_audio_output_block(dev, devc->trg_buf, devc->trg_bytes, - devc->trg_intrflag); - break; - } - } + { + switch (devc->irq_mode) + { + case IMODE_INPUT: + sb1_audio_start_input(dev, devc->trg_buf, devc->trg_bytes, + devc->trg_intrflag); + break; + case IMODE_OUTPUT: + sb1_audio_output_block(dev, devc->trg_buf, devc->trg_bytes, + devc->trg_intrflag); + break; + } + } devc->trigger_bits = bits; } -static int -sb1_audio_prepare_for_input(int dev, int bsize, int bcount) +static int sb1_audio_prepare_for_input(int dev, int bsize, int bcount) { - sb_devc *devc = audio_devs[dev]->devc; - unsigned long flags; + sb_devc *devc = audio_devs[dev]->devc; + unsigned long flags; save_flags(flags); cli(); @@ -208,11 +225,10 @@ sb1_audio_prepare_for_input(int dev, int bsize, int bcount) return 0; } -static int -sb1_audio_prepare_for_output(int dev, int bsize, int bcount) +static int sb1_audio_prepare_for_output(int dev, int bsize, int bcount) { - sb_devc *devc = audio_devs[dev]->devc; - unsigned long flags; + sb_devc *devc = audio_devs[dev]->devc; + unsigned long flags; save_flags(flags); cli(); @@ -224,55 +240,48 @@ sb1_audio_prepare_for_output(int dev, int bsize, int bcount) return 0; } -static int -sb1_audio_set_speed(int dev, int speed) +static int sb1_audio_set_speed(int dev, int speed) { - int max_speed = 23000; - sb_devc *devc = audio_devs[dev]->devc; - int tmp; + int max_speed = 23000; + sb_devc *devc = audio_devs[dev]->devc; + int tmp; if (devc->opened & OPEN_READ) max_speed = 13000; if (speed > 0) - { - if (speed < 4000) - speed = 4000; - - if (speed > max_speed) - speed = max_speed; + { + if (speed < 4000) + speed = 4000; - devc->tconst = (256 - ((1000000 + speed / 2) / speed)) & 0xff; + if (speed > max_speed) + speed = max_speed; - tmp = 256 - devc->tconst; - speed = (1000000 + tmp / 2) / tmp; + devc->tconst = (256 - ((1000000 + speed / 2) / speed)) & 0xff; + tmp = 256 - devc->tconst; + speed = (1000000 + tmp / 2) / tmp; - devc->speed = speed; - } + devc->speed = speed; + } return devc->speed; } -static short -sb1_audio_set_channels(int dev, short channels) +static short sb1_audio_set_channels(int dev, short channels) { - sb_devc *devc = audio_devs[dev]->devc; - + sb_devc *devc = audio_devs[dev]->devc; return devc->channels = 1; } -static unsigned int -sb1_audio_set_bits(int dev, unsigned int bits) +static unsigned int sb1_audio_set_bits(int dev, unsigned int bits) { sb_devc *devc = audio_devs[dev]->devc; - return devc->bits = 8; } -static void -sb1_audio_halt_xfer(int dev) +static void sb1_audio_halt_xfer(int dev) { - unsigned long flags; - sb_devc *devc = audio_devs[dev]->devc; + unsigned long flags; + sb_devc *devc = audio_devs[dev]->devc; save_flags(flags); cli(); @@ -284,14 +293,13 @@ sb1_audio_halt_xfer(int dev) * SB 2.0 and SB 2.01 compatible routines */ -static void -sb20_audio_output_block(int dev, unsigned long buf, int nr_bytes, +static void sb20_audio_output_block(int dev, unsigned long buf, int nr_bytes, int intrflag) { - unsigned long flags; - int count = nr_bytes; - sb_devc *devc = audio_devs[dev]->devc; - unsigned char cmd; + unsigned long flags; + int count = nr_bytes; + sb_devc *devc = audio_devs[dev]->devc; + unsigned char cmd; /* DMAbuf_start_dma (dev, buf, count, DMA_MODE_WRITE); */ @@ -304,31 +312,30 @@ sb20_audio_output_block(int dev, unsigned long buf, int nr_bytes, save_flags(flags); cli(); if (sb_dsp_command(devc, 0x48)) /* DSP Block size */ - { - sb_dsp_command(devc, (unsigned char) (count & 0xff)); - sb_dsp_command(devc, (unsigned char) ((count >> 8) & 0xff)); - - if (devc->speed * devc->channels <= 23000) - cmd = 0x1c; /* 8 bit PCM output */ - else - cmd = 0x90; /* 8 bit high speed PCM output (SB2.01/Pro) */ + { + sb_dsp_command(devc, (unsigned char) (count & 0xff)); + sb_dsp_command(devc, (unsigned char) ((count >> 8) & 0xff)); - if (!sb_dsp_command(devc, cmd)) - printk("SB: Unable to start DAC\n"); + if (devc->speed * devc->channels <= 23000) + cmd = 0x1c; /* 8 bit PCM output */ + else + cmd = 0x90; /* 8 bit high speed PCM output (SB2.01/Pro) */ - } else - printk("SB: Unable to start DAC\n"); + if (!sb_dsp_command(devc, cmd)) + printk(KERN_ERR "soundblaster: Unable to start DAC\n"); + } + else + printk(KERN_ERR "soundblaster: Unable to start DAC\n"); restore_flags(flags); devc->intr_active = 1; } -static void -sb20_audio_start_input(int dev, unsigned long buf, int nr_bytes, int intrflag) +static void sb20_audio_start_input(int dev, unsigned long buf, int nr_bytes, int intrflag) { - unsigned long flags; - int count = nr_bytes; - sb_devc *devc = audio_devs[dev]->devc; - unsigned char cmd; + unsigned long flags; + int count = nr_bytes; + sb_devc *devc = audio_devs[dev]->devc; + unsigned char cmd; /* * Start a DMA input to the buffer pointed by dmaqtail @@ -345,49 +352,46 @@ sb20_audio_start_input(int dev, unsigned long buf, int nr_bytes, int intrflag) save_flags(flags); cli(); if (sb_dsp_command(devc, 0x48)) /* DSP Block size */ - { - sb_dsp_command(devc, (unsigned char) (count & 0xff)); - sb_dsp_command(devc, (unsigned char) ((count >> 8) & 0xff)); - - if (devc->speed * devc->channels <= (devc->major == 3 ? 23000 : 13000)) - cmd = 0x2c; /* 8 bit PCM input */ - else - cmd = 0x98; /* 8 bit high speed PCM input (SB2.01/Pro) */ - - if (!sb_dsp_command(devc, cmd)) - printk("SB: Unable to start ADC\n"); - } else - printk("SB Error: Unable to start ADC\n"); - restore_flags(flags); + { + sb_dsp_command(devc, (unsigned char) (count & 0xff)); + sb_dsp_command(devc, (unsigned char) ((count >> 8) & 0xff)); + if (devc->speed * devc->channels <= (devc->major == 3 ? 23000 : 13000)) + cmd = 0x2c; /* 8 bit PCM input */ + else + cmd = 0x98; /* 8 bit high speed PCM input (SB2.01/Pro) */ + + if (!sb_dsp_command(devc, cmd)) + printk(KERN_ERR "soundblaster: Unable to start ADC\n"); + } + else + printk(KERN_ERR "soundblaster: Unable to start ADC\n"); + restore_flags(flags); devc->intr_active = 1; } -static void -sb20_audio_trigger(int dev, int bits) +static void sb20_audio_trigger(int dev, int bits) { - sb_devc *devc = audio_devs[dev]->devc; - + sb_devc *devc = audio_devs[dev]->devc; bits &= devc->irq_mode; if (!bits) sb_dsp_command(devc, 0xd0); /* Halt DMA */ else - { - switch (devc->irq_mode) - { - case IMODE_INPUT: - sb20_audio_start_input(dev, devc->trg_buf, devc->trg_bytes, - devc->trg_intrflag); - break; + { + switch (devc->irq_mode) + { + case IMODE_INPUT: + sb20_audio_start_input(dev, devc->trg_buf, devc->trg_bytes, + devc->trg_intrflag); + break; - case IMODE_OUTPUT: - sb20_audio_output_block(dev, devc->trg_buf, devc->trg_bytes, - devc->trg_intrflag); + case IMODE_OUTPUT: + sb20_audio_output_block(dev, devc->trg_buf, devc->trg_bytes, + devc->trg_intrflag); break; - } - } - + } + } devc->trigger_bits = bits; } @@ -395,32 +399,26 @@ sb20_audio_trigger(int dev, int bits) * SB2.01 specific speed setup */ -static int -sb201_audio_set_speed(int dev, int speed) +static int sb201_audio_set_speed(int dev, int speed) { - sb_devc *devc = audio_devs[dev]->devc; - int tmp; - int s = speed * devc->channels; + sb_devc *devc = audio_devs[dev]->devc; + int tmp; + int s = speed * devc->channels; if (speed > 0) - { - if (speed < 4000) - speed = 4000; - - if (speed > 44100) - speed = 44100; - - if (devc->opened & OPEN_READ && speed > 15000) - speed = 15000; - - devc->tconst = ((65536 - ((256000000 + s / 2) / - s)) >> 8) & 0xff; - - tmp = 256 - devc->tconst; - speed = ((1000000 + tmp / 2) / tmp) / devc->channels; + { + if (speed < 4000) + speed = 4000; + if (speed > 44100) + speed = 44100; + if (devc->opened & OPEN_READ && speed > 15000) + speed = 15000; + devc->tconst = ((65536 - ((256000000 + s / 2) / s)) >> 8) & 0xff; + tmp = 256 - devc->tconst; + speed = ((1000000 + tmp / 2) / tmp) / devc->channels; - devc->speed = speed; - } + devc->speed = speed; + } return devc->speed; } @@ -428,17 +426,15 @@ sb201_audio_set_speed(int dev, int speed) * SB Pro specific routines */ -static int -sbpro_audio_prepare_for_input(int dev, int bsize, int bcount) +static int sbpro_audio_prepare_for_input(int dev, int bsize, int bcount) { /* For SB Pro and Jazz16 */ - sb_devc *devc = audio_devs[dev]->devc; - unsigned long flags; - unsigned char bits = 0; + sb_devc *devc = audio_devs[dev]->devc; + unsigned long flags; + unsigned char bits = 0; if (devc->dma16 >= 0 && devc->dma16 != devc->dma8) - audio_devs[dev]->dmap_out->dma = - audio_devs[dev]->dmap_in->dma = - devc->bits == 16 ? devc->dma16 : devc->dma8; + audio_devs[dev]->dmap_out->dma = audio_devs[dev]->dmap_in->dma = + devc->bits == 16 ? devc->dma16 : devc->dma8; if (devc->model == MDL_JAZZ || devc->model == MDL_SMW) if (devc->bits == AFMT_S16_LE) @@ -459,18 +455,15 @@ sbpro_audio_prepare_for_input(int dev, int bsize, int bcount) return 0; } -static int -sbpro_audio_prepare_for_output(int dev, int bsize, int bcount) +static int sbpro_audio_prepare_for_output(int dev, int bsize, int bcount) { /* For SB Pro and Jazz16 */ - sb_devc *devc = audio_devs[dev]->devc; - unsigned long flags; - unsigned char tmp; - unsigned char bits = 0; + sb_devc *devc = audio_devs[dev]->devc; + unsigned long flags; + unsigned char tmp; + unsigned char bits = 0; if (devc->dma16 >= 0 && devc->dma16 != devc->dma8) - audio_devs[dev]->dmap_out->dma = - audio_devs[dev]->dmap_in->dma = - devc->bits == 16 ? devc->dma16 : devc->dma8; + audio_devs[dev]->dmap_out->dma = audio_devs[dev]->dmap_in->dma = devc->bits == 16 ? devc->dma16 : devc->dma8; if (devc->model == MDL_SBPRO) sb_mixer_set_stereo(devc, devc->channels == 2); @@ -481,92 +474,83 @@ sbpro_audio_prepare_for_output(int dev, int bsize, int bcount) sb_dsp_command(devc, DSP_CMD_SPKON); if (devc->model == MDL_JAZZ || devc->model == MDL_SMW) - { - if (devc->bits == AFMT_S16_LE) - bits = 0x04; /* 16 bit mode */ - - if (devc->channels == 1) - sb_dsp_command(devc, 0xa0 | bits); /* Mono output */ - else - sb_dsp_command(devc, 0xa8 | bits); /* Stereo output */ - } else - { - tmp = sb_getmixer(devc, 0x0e); - if (devc->channels == 1) - tmp &= ~0x02; - else - tmp |= 0x02; - sb_setmixer(devc, 0x0e, tmp); - } + { + if (devc->bits == AFMT_S16_LE) + bits = 0x04; /* 16 bit mode */ + + if (devc->channels == 1) + sb_dsp_command(devc, 0xa0 | bits); /* Mono output */ + else + sb_dsp_command(devc, 0xa8 | bits); /* Stereo output */ + } + else + { + tmp = sb_getmixer(devc, 0x0e); + if (devc->channels == 1) + tmp &= ~0x02; + else + tmp |= 0x02; + sb_setmixer(devc, 0x0e, tmp); + } restore_flags(flags); devc->trigger_bits = 0; return 0; } -static int -sbpro_audio_set_speed(int dev, int speed) +static int sbpro_audio_set_speed(int dev, int speed) { - sb_devc *devc = audio_devs[dev]->devc; + sb_devc *devc = audio_devs[dev]->devc; if (speed > 0) - { - if (speed < 4000) - speed = 4000; - - if (speed > 44100) - speed = 44100; - - if (devc->channels > 1 && speed > 22050) - speed = 22050; - - sb201_audio_set_speed(dev, speed); - } + { + if (speed < 4000) + speed = 4000; + if (speed > 44100) + speed = 44100; + if (devc->channels > 1 && speed > 22050) + speed = 22050; + sb201_audio_set_speed(dev, speed); + } return devc->speed; } -static short -sbpro_audio_set_channels(int dev, short channels) +static short sbpro_audio_set_channels(int dev, short channels) { - sb_devc *devc = audio_devs[dev]->devc; + sb_devc *devc = audio_devs[dev]->devc; if (channels == 1 || channels == 2) + { if (channels != devc->channels) - { - devc->channels = channels; - if (devc->model == MDL_SBPRO && devc->channels == 2) - { - if (devc->speed > 22050) - printk("OSS: Application error. Wrong ioctl call order.\n"); - sbpro_audio_set_speed(dev, devc->speed); - } - } + { + devc->channels = channels; + if (devc->model == MDL_SBPRO && devc->channels == 2) + sbpro_audio_set_speed(dev, devc->speed); + } + } return devc->channels; } -static int -jazz16_audio_set_speed(int dev, int speed) +static int jazz16_audio_set_speed(int dev, int speed) { - sb_devc *devc = audio_devs[dev]->devc; + sb_devc *devc = audio_devs[dev]->devc; if (speed > 0) - { - int tmp; - int s = speed * devc->channels; - - if (speed < 5000) - speed = 4000; + { + int tmp; + int s = speed * devc->channels; - if (speed > 44100) - speed = 44100; + if (speed < 5000) + speed = 5000; + if (speed > 44100) + speed = 44100; - devc->tconst = ((65536 - ((256000000 + s / 2) / - s)) >> 8) & 0xff; + devc->tconst = ((65536 - ((256000000 + s / 2) / s)) >> 8) & 0xff; - tmp = 256 - devc->tconst; - speed = ((1000000 + tmp / 2) / tmp) / devc->channels; + tmp = 256 - devc->tconst; + speed = ((1000000 + tmp / 2) / tmp) / devc->channels; - devc->speed = speed; - } + devc->speed = speed; + } return devc->speed; } @@ -574,124 +558,123 @@ jazz16_audio_set_speed(int dev, int speed) * ESS specific routines */ -static int -ess_audio_set_speed(int dev, int speed) +static int ess_audio_set_speed(int dev, int speed) { - sb_devc *devc = audio_devs[dev]->devc; - int divider; + sb_devc *devc = audio_devs[dev]->devc; + int divider; if (speed > 0) - { - if (speed < 5000) - speed = 4000; - - if (speed > 48000) - speed = 48000; - - if (speed > 22000) - { - divider = (795500 + speed / 2) / speed; - speed = (795500 + divider / 2) / divider; - } else - { - divider = (397700 + speed / 2) / speed; - speed = (397700 + divider / 2) / divider; - } - - devc->speed = speed; - } + { + if (speed < 5000) + speed = 5000; + if (speed > 48000) + speed = 48000; + + if (speed > 22000) + { + divider = (795500 + speed / 2) / speed; + speed = (795500 + divider / 2) / divider; + } + else + { + divider = (397700 + speed / 2) / speed; + speed = (397700 + divider / 2) / divider; + } + devc->speed = speed; + } return devc->speed; } -static void -ess_speed(sb_devc * devc) +static void ess_speed(sb_devc * devc) { - int divider; - unsigned char bits = 0; - int speed = devc->speed; + int divider; + unsigned char bits = 0; + int speed = devc->speed; if (speed < 4000) speed = 4000; else if (speed > 48000) speed = 48000; - + if (speed > 22000) - { - bits = 0x80; - divider = 256 - (795500 + speed / 2) / speed; - } else - { - divider = 128 - (397700 + speed / 2) / speed; - } + { + bits = 0x80; + divider = 256 - (795500 + speed / 2) / speed; + } + else + { + divider = 128 - (397700 + speed / 2) / speed; + } bits |= (unsigned char) divider; ess_write(devc, 0xa1, bits); -/* - * Set filter divider register - */ + /* + * Set filter divider register + */ speed = (speed * 9) / 20; /* Set filter roll-off to 90% of speed/2 */ divider = 256 - 7160000 / (speed * 82); ess_write(devc, 0xa2, divider); - return; } -static int -ess_audio_prepare_for_input(int dev, int bsize, int bcount) +static int ess_audio_prepare_for_input(int dev, int bsize, int bcount) { - sb_devc *devc = audio_devs[dev]->devc; - + sb_devc *devc = audio_devs[dev]->devc; ess_speed(devc); sb_dsp_command(devc, DSP_CMD_SPKOFF); ess_write(devc, 0xb8, 0x0e); /* Auto init DMA mode */ - ess_write(devc, 0xa8, (ess_read(devc, 0xa8) & ~0x03) | - (3 - devc->channels)); /* Mono/stereo */ + ess_write(devc, 0xa8, (ess_read(devc, 0xa8) & ~0x03) | (3 - devc->channels)); /* Mono/stereo */ ess_write(devc, 0xb9, 2); /* Demand mode (4 bytes/DMA request) */ if (devc->channels == 1) - { - if (devc->bits == AFMT_U8) - { /* 8 bit mono */ - ess_write(devc, 0xb7, 0x51); - ess_write(devc, 0xb7, 0xd0); - } else - { /* 16 bit mono */ - ess_write(devc, 0xb7, 0x71); - ess_write(devc, 0xb7, 0xf4); - } - } else - { /* Stereo */ - if (devc->bits == AFMT_U8) - { /* 8 bit stereo */ - ess_write(devc, 0xb7, 0x51); - ess_write(devc, 0xb7, 0x98); - } else - { /* 16 bit stereo */ - ess_write(devc, 0xb7, 0x71); - ess_write(devc, 0xb7, 0xbc); - } - } - + { + if (devc->bits == AFMT_U8) + { + /* 8 bit mono */ + ess_write(devc, 0xb7, 0x51); + ess_write(devc, 0xb7, 0xd0); + } + else + { + /* 16 bit mono */ + ess_write(devc, 0xb7, 0x71); + ess_write(devc, 0xb7, 0xf4); + } + } + else + { + /* Stereo */ + if (devc->bits == AFMT_U8) + { + /* 8 bit stereo */ + ess_write(devc, 0xb7, 0x51); + ess_write(devc, 0xb7, 0x98); + } + else + { + /* 16 bit stereo */ + ess_write(devc, 0xb7, 0x71); + ess_write(devc, 0xb7, 0xbc); + } + } ess_write(devc, 0xb1, (ess_read(devc, 0xb1) & 0x0f) | 0x50); ess_write(devc, 0xb2, (ess_read(devc, 0xb2) & 0x0f) | 0x50); - devc->trigger_bits = 0; return 0; } static int ess_audio_prepare_for_output(int dev, int bsize, int bcount) { - sb_devc *devc = audio_devs[dev]->devc; + sb_devc *devc = audio_devs[dev]->devc; sb_dsp_reset(devc); ess_speed(devc); ess_write(devc, 0xb8, 4); /* Auto init DMA mode */ - ess_write(devc, 0xa8, (ess_read(devc, 0xa8) & ~0x03) | - (3 - devc->channels)); /* Mono/stereo */ + ess_write(devc, 0xa8, (ess_read(devc, 0xa8) & ~0x03) | (3 - devc->channels)); /* Mono/stereo */ ess_write(devc, 0xb9, 2); /* Demand mode (4 bytes/request) */ if (devc->channels == 1) @@ -701,7 +684,8 @@ static int ess_audio_prepare_for_output(int dev, int bsize, int bcount) ess_write(devc, 0xb6, 0x80); ess_write(devc, 0xb7, 0x51); ess_write(devc, 0xb7, 0xd0); - } else + } + else { /* 16 bit mono */ ess_write(devc, 0xb6, 0x00); ess_write(devc, 0xb7, 0x71); @@ -733,11 +717,11 @@ static int ess_audio_prepare_for_output(int dev, int bsize, int bcount) } static void ess_audio_output_block(int dev, unsigned long buf, int nr_bytes, - int intrflag) + int intrflag) { - int count = nr_bytes; - sb_devc *devc = audio_devs[dev]->devc; - short c = -nr_bytes; + int count = nr_bytes; + sb_devc *devc = audio_devs[dev]->devc; + short c = -nr_bytes; /* DMAbuf_start_dma (dev, buf, count, DMA_MODE_WRITE); */ @@ -756,9 +740,9 @@ static void ess_audio_output_block(int dev, unsigned long buf, int nr_bytes, static void ess_audio_start_input(int dev, unsigned long buf, int nr_bytes, int intrflag) { - int count = nr_bytes; - sb_devc *devc = audio_devs[dev]->devc; - short c = -nr_bytes; + int count = nr_bytes; + sb_devc *devc = audio_devs[dev]->devc; + short c = -nr_bytes; /* * Start a DMA input to the buffer pointed by dmaqtail @@ -781,7 +765,7 @@ static void ess_audio_start_input(int dev, unsigned long buf, int nr_bytes, int static void ess_audio_trigger(int dev, int bits) { - sb_devc *devc = audio_devs[dev]->devc; + sb_devc *devc = audio_devs[dev]->devc; bits &= devc->irq_mode; @@ -812,7 +796,7 @@ static void ess_audio_trigger(int dev, int bits) static int sb16_audio_set_speed(int dev, int speed) { - sb_devc *devc = audio_devs[dev]->devc; + sb_devc *devc = audio_devs[dev]->devc; if (speed > 0) { @@ -829,7 +813,7 @@ static int sb16_audio_set_speed(int dev, int speed) static unsigned int sb16_audio_set_bits(int dev, unsigned int bits) { - sb_devc *devc = audio_devs[dev]->devc; + sb_devc *devc = audio_devs[dev]->devc; if (bits != 0) { @@ -844,7 +828,7 @@ static unsigned int sb16_audio_set_bits(int dev, unsigned int bits) static int sb16_audio_prepare_for_input(int dev, int bsize, int bcount) { - sb_devc *devc = audio_devs[dev]->devc; + sb_devc *devc = audio_devs[dev]->devc; audio_devs[dev]->dmap_out->dma = audio_devs[dev]->dmap_in->dma = @@ -856,11 +840,10 @@ static int sb16_audio_prepare_for_input(int dev, int bsize, int bcount) static int sb16_audio_prepare_for_output(int dev, int bsize, int bcount) { - sb_devc *devc = audio_devs[dev]->devc; + sb_devc *devc = audio_devs[dev]->devc; - audio_devs[dev]->dmap_out->dma = - audio_devs[dev]->dmap_in->dma = - devc->bits == AFMT_S16_LE ? devc->dma16 : devc->dma8; + audio_devs[dev]->dmap_out->dma = audio_devs[dev]->dmap_in->dma = + devc->bits == AFMT_S16_LE ? devc->dma16 : devc->dma8; devc->trigger_bits = 0; return 0; @@ -1098,8 +1081,8 @@ static struct audio_driver ess_audio_driver = /* ESS ES688/1688 */ void sb_audio_init(sb_devc * devc, char *name) { - int audio_flags = 0; - int format_mask = AFMT_U8; + int audio_flags = 0; + int format_mask = AFMT_U8; struct audio_driver *driver = &sb1_audio_driver; @@ -1151,14 +1134,9 @@ void sb_audio_init(sb_devc * devc, char *name) } if ((devc->my_dev = sound_install_audiodrv(AUDIO_DRIVER_VERSION, - name, - driver, - sizeof(struct audio_driver), - audio_flags, - format_mask, - devc, - devc->dma8, - devc->dma8)) < 0) + name,driver, sizeof(struct audio_driver), + audio_flags, format_mask, devc, + devc->dma8, devc->dma8)) < 0) { printk(KERN_ERR "sb: unable to install audio.\n"); return; diff --git a/drivers/sound/sb_card.c b/drivers/sound/sb_card.c index 941422c3f..ddf863372 100644 --- a/drivers/sound/sb_card.c +++ b/drivers/sound/sb_card.c @@ -2,18 +2,18 @@ * sound/sb_card.c * * Detection routine for the Sound Blaster cards. - */ -/* + * + * * Copyright (C) by Hannu Savolainen 1993-1997 * * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) * Version 2 (June 1991). See the "COPYING" file distributed with this software * for more info. */ + #include <linux/config.h> #include <linux/module.h> - #include "sound_config.h" #include "soundmodule.h" @@ -22,31 +22,30 @@ #include "sb_mixer.h" #include "sb.h" -void -attach_sb_card(struct address_info *hw_config) +void attach_sb_card(struct address_info *hw_config) { #if defined(CONFIG_AUDIO) || defined(CONFIG_MIDI) sb_dsp_init(hw_config); #endif } -int -probe_sb(struct address_info *hw_config) +int probe_sb(struct address_info *hw_config) { if (check_region(hw_config->io_base, 16)) { - printk("\n\nsb_card.c: I/O port %x is already in use\n\n", hw_config->io_base); + printk(KERN_ERR "sb_card: I/O port %x is already in use\n\n", hw_config->io_base); return 0; } return sb_dsp_detect(hw_config); } -void -unload_sb(struct address_info *hw_config) +void unload_sb(struct address_info *hw_config) { sb_dsp_unload(hw_config); } +int sb_be_quiet=0; + #ifdef MODULE static struct address_info config; @@ -58,18 +57,17 @@ static struct address_info config_mpu; * 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 sm_games = 0; /* Mixer - see sb_mixer.c */ -int acer = 0; /* Do acer notebook init */ -int mwave_bug = 0; /* Using the dreadful mwave sb emulation */ +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 sm_games = 0; /* Mixer - see sb_mixer.c */ +int acer = 0; /* Do acer notebook init */ MODULE_PARM(io, "i"); MODULE_PARM(irq, "i"); @@ -81,7 +79,6 @@ MODULE_PARM(mad16, "i"); MODULE_PARM(trix, "i"); MODULE_PARM(pas2, "i"); MODULE_PARM(sm_games, "i"); -MODULE_PARM(mwave_bug, "i"); static int sbmpu = 0; @@ -124,7 +121,7 @@ int init_module(void) void cleanup_module(void) { if (smw_free) - kfree(smw_free); + vfree(smw_free); if (!mad16 && !trix && !pas2) unload_sb(&config); if (sbmpu) @@ -144,11 +141,6 @@ int acer = 1; #else int acer = 0; #endif -#ifdef CONFIG_SB_MWAVE -int mwave_bug = 1; -#else -int mwave_bug = 0; -#endif #endif #endif @@ -159,3 +151,4 @@ EXPORT_SYMBOL(sb_dsp_disable_midi); EXPORT_SYMBOL(attach_sb_card); EXPORT_SYMBOL(probe_sb); EXPORT_SYMBOL(unload_sb); +EXPORT_SYMBOL(sb_be_quiet); diff --git a/drivers/sound/sb_common.c b/drivers/sound/sb_common.c index fcdcfcf2c..d82c9379f 100644 --- a/drivers/sound/sb_common.c +++ b/drivers/sound/sb_common.c @@ -2,17 +2,18 @@ * sound/sb_common.c * * Common routines for Sound Blaster compatible cards. - */ -/* + * + * * Copyright (C) by Hannu Savolainen 1993-1997 * * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) * Version 2 (June 1991). See the "COPYING" file distributed with this software * for more info. */ + #include <linux/config.h> #include <linux/delay.h> - +#include <asm/init.h> #include "sound_config.h" #include "sound_firmware.h" @@ -28,9 +29,11 @@ static sb_devc *detected_devc = NULL; /* For communication from probe to init */ static sb_devc *last_devc = NULL; /* For MPU401 initialization */ + static unsigned char jazz_irq_bits[] = { 0, 0, 2, 3, 0, 1, 0, 4, 0, 2, 5, 0, 0, 0, 0, 6 }; + static unsigned char jazz_dma_bits[] = { 0, 1, 0, 2, 0, 3, 0, 4 }; @@ -39,7 +42,7 @@ static unsigned char jazz_dma_bits[] = { * Jazz16 chipset specific control variables */ -static int jazz16_base = 0; /* Not detected */ +static int jazz16_base = 0; /* Not detected */ static unsigned char jazz16_bits = 0; /* I/O relocation bits */ /* @@ -57,10 +60,11 @@ static int smw_ucodeLen = 0; int sb_dsp_command(sb_devc * devc, unsigned char val) { - int i; - unsigned long limit; + int i; + unsigned long limit; limit = jiffies + HZ / 10; /* Timeout */ + /* * Note! the i<500000 is an emergency exit. The sb_dsp_command() is sometimes * called while interrupts are disabled. This means that the timer is @@ -69,7 +73,7 @@ int sb_dsp_command(sb_devc * devc, unsigned char val) * loops. */ - for (i = 0; i < 500000 && jiffies < limit; i++) + for (i = 0; i < 500000 && (limit-jiffies)>0; i++) { if ((inb(DSP_STATUS) & 0x80) == 0) { @@ -77,20 +81,19 @@ int sb_dsp_command(sb_devc * devc, unsigned char val) return 1; } } - - printk(KERN_WARNING "Sound Blaster: DSP Command(%x) Timeout.\n", val); + printk(KERN_WARNING "soundblaster: DSP Command(%x) Timeout.\n", val); return 0; } static int sb_dsp_get_byte(sb_devc * devc) { - int i; + int i; for (i = 1000; i; i--) + { if (inb(DSP_DATA_AVAIL) & 0x80) - { return inb(DSP_READ); - } + } return 0xffff; } @@ -107,7 +110,6 @@ int ess_write(sb_devc * devc, unsigned char reg, unsigned char data) int ess_read(sb_devc * devc, unsigned char reg) { /* Read a byte from an extended mode register of ES1688 */ - if (!sb_dsp_command(devc, 0xc0)) /* Read register command */ return -1; @@ -239,7 +241,7 @@ static int sb16_set_dma_hw(sb_devc * devc) if (devc->dma8 != 0 && devc->dma8 != 1 && devc->dma8 != 3) { - printk(KERN_ERR "SB16: Invalid 8 bit DMA (%d)\n", devc->dma8); + printk(KERN_ERR "sb16: Invalid 8 bit DMA (%d)\n", devc->dma8); return 0; } bits = (1 << devc->dma8); @@ -355,14 +357,12 @@ static int init_Jazz16(sb_devc * devc, struct address_info *hw_config) /* * OK so far. Now configure the IRQ and DMA channel used by the card. */ - if (hw_config->irq < 1 || hw_config->irq > 15 || - jazz_irq_bits[hw_config->irq] == 0) + if (hw_config->irq < 1 || hw_config->irq > 15 || jazz_irq_bits[hw_config->irq] == 0) { printk(KERN_ERR "Jazz16: Invalid interrupt (IRQ%d)\n", hw_config->irq); return 0; } - if (hw_config->dma < 0 || hw_config->dma > 3 || - jazz_dma_bits[hw_config->dma] == 0) + if (hw_config->dma < 0 || hw_config->dma > 3 || jazz_dma_bits[hw_config->dma] == 0) { printk(KERN_ERR "Jazz16: Invalid 8 bit DMA (DMA%d)\n", hw_config->dma); return 0; @@ -372,8 +372,7 @@ static int init_Jazz16(sb_devc * devc, struct address_info *hw_config) printk(KERN_ERR "Jazz16: No 16 bit DMA channel defined\n"); return 0; } - if (hw_config->dma2 < 5 || hw_config->dma2 > 7 || - jazz_dma_bits[hw_config->dma2] == 0) + if (hw_config->dma2 < 5 || hw_config->dma2 > 7 || jazz_dma_bits[hw_config->dma2] == 0) { printk(KERN_ERR "Jazz16: Invalid 16 bit DMA (DMA%d)\n", hw_config->dma2); return 0; @@ -384,7 +383,7 @@ static int init_Jazz16(sb_devc * devc, struct address_info *hw_config) return 0; if (!sb_dsp_command(devc, jazz_dma_bits[hw_config->dma] | - (jazz_dma_bits[hw_config->dma2] << 4))) + (jazz_dma_bits[hw_config->dma2] << 4))) return 0; if (!sb_dsp_command(devc, jazz_irq_bits[hw_config->irq])) @@ -683,11 +682,7 @@ int sb_dsp_detect(struct address_info *hw_config) */ - detected_devc = (sb_devc *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(sb_devc))); - sound_mem_sizes[sound_nblocks] = sizeof(sb_devc); - if (sound_nblocks < 1024) - sound_nblocks++;; - + detected_devc = (sb_devc *)kmalloc(sizeof(sb_devc), GFP_KERNEL); if (detected_devc == NULL) { printk(KERN_ERR "sb: Can't allocate memory for device information\n"); @@ -703,8 +698,8 @@ void sb_dsp_init(struct address_info *hw_config) sb_devc *devc; char name[100]; extern int sb_be_quiet; - extern int mwave_bug; - + int mixer3c, mixer4c; + /* * Check if we had detected a SB device earlier */ @@ -769,7 +764,7 @@ void sb_dsp_init(struct address_info *hw_config) /* Skip IRQ detection if SMP (doesn't work) */ devc->irq_ok = 1; #else - if ((devc->major == 4 && devc->minor <= 11 ) || mwave_bug ) /* Won't work */ + if (devc->major == 4 && devc->minor <= 11 ) /* Won't work */ devc->irq_ok = 1; else { @@ -819,7 +814,23 @@ void sb_dsp_init(struct address_info *hw_config) case 4: devc->model = hw_config->card_subtype = MDL_SB16; - if (hw_config->name == NULL) + /* + * The ALS007 seems to return DSP version 4.2. In addition it has 2 + * output control registers (at 0x3c and 0x4c). Both of these should + * be !=0 after a reset which forms the basis of the ALS007 test + * since a "standard" SoundBlaster does not have a register at 0x4c. + */ + mixer3c = sb_getmixer(devc,0x3c); + mixer4c = sb_getmixer(devc,0x4c); + if ((devc->minor == 2) && (mixer3c != 0) && (mixer4c != 0)) + { + sb_setmixer(devc,0x3c,0x1f); /* Enable all inputs */ + sb_setmixer(devc,0x4c,0x1f); + devc->submodel = SUBMDL_ALS007; + if (hw_config->name == NULL) + hw_config->name = "Sound Blaster (ALS-007)"; + } + else if (hw_config->name == NULL) hw_config->name = "Sound Blaster 16"; if (hw_config->dma2 == -1) @@ -885,15 +896,15 @@ void sb_dsp_init(struct address_info *hw_config) printk(KERN_WARNING "SB: Can't allocate 8 bit DMA channel %d\n", devc->dma8); } if (devc->dma16 >= 0 && devc->dma16 != devc->dma8) + { if (sound_alloc_dma(devc->dma16, "SoundBlaster16")) - { - printk(KERN_WARNING "SB: Can't allocate 16 bit DMA channel %d\n", devc->dma16); - } + printk(KERN_WARNING "soundblaster: Can't allocate 16 bit DMA channel %d\n", devc->dma16); + } sb_audio_init(devc, name); } else { - MDB(printk("sb: No audio devices found.\n")); + MDB(printk("soundblaster: No audio devices found.\n")); } } @@ -932,6 +943,8 @@ void sb_dsp_unload(struct address_info *hw_config) } else release_region(hw_config->io_base, 16); + if(detected_devc) + kfree(detected_devc); } /* @@ -940,7 +953,7 @@ void sb_dsp_unload(struct address_info *hw_config) void sb_setmixer(sb_devc * devc, unsigned int port, unsigned int value) { - unsigned long flags; + unsigned long flags; save_flags(flags); cli(); @@ -1318,5 +1331,4 @@ void attach_sbmpu(struct address_info *hw_config) { } #endif - #endif diff --git a/drivers/sound/sb_midi.c b/drivers/sound/sb_midi.c index b08f8d43f..f7c1c85a2 100644 --- a/drivers/sound/sb_midi.c +++ b/drivers/sound/sb_midi.c @@ -2,17 +2,16 @@ * sound/sb_dsp.c * * The low level driver for the Sound Blaster DS chips. - */ -/* + * + * * Copyright (C) by Hannu Savolainen 1993-1997 * * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) * Version 2 (June 1991). See the "COPYING" file distributed with this software * for more info. */ -#include <linux/config.h> - +#include <linux/config.h> #include "sound_config.h" #ifdef CONFIG_SBDSP @@ -30,14 +29,13 @@ */ -static int -sb_midi_open(int dev, int mode, +static int sb_midi_open(int dev, int mode, void (*input) (int dev, unsigned char data), void (*output) (int dev) ) { - sb_devc *devc = midi_devs[dev]->devc; - unsigned long flags; + sb_devc *devc = midi_devs[dev]->devc; + unsigned long flags; if (devc == NULL) return -ENXIO; @@ -45,10 +43,10 @@ sb_midi_open(int dev, int mode, save_flags(flags); cli(); if (devc->opened) - { - restore_flags(flags); - return -EBUSY; - } + { + restore_flags(flags); + return -EBUSY; + } devc->opened = 1; restore_flags(flags); @@ -58,25 +56,24 @@ sb_midi_open(int dev, int mode, sb_dsp_reset(devc); if (!sb_dsp_command(devc, 0x35)) /* Start MIDI UART mode */ - { + { devc->opened = 0; return -EIO; - } + } devc->intr_active = 1; if (mode & OPEN_READ) - { - devc->input_opened = 1; - devc->midi_input_intr = input; - } + { + devc->input_opened = 1; + devc->midi_input_intr = input; + } return 0; } -static void -sb_midi_close(int dev) +static void sb_midi_close(int dev) { - sb_devc *devc = midi_devs[dev]->devc; - unsigned long flags; + sb_devc *devc = midi_devs[dev]->devc; + unsigned long flags; if (devc == NULL) return; @@ -90,10 +87,9 @@ sb_midi_close(int dev) restore_flags(flags); } -static int -sb_midi_out(int dev, unsigned char midi_byte) +static int sb_midi_out(int dev, unsigned char midi_byte) { - sb_devc *devc = midi_devs[dev]->devc; + sb_devc *devc = midi_devs[dev]->devc; if (devc == NULL) return 1; @@ -102,23 +98,21 @@ sb_midi_out(int dev, unsigned char midi_byte) return 1; if (!sb_dsp_command(devc, midi_byte)) - { - devc->midi_broken = 1; - return 1; - } + { + devc->midi_broken = 1; + return 1; + } return 1; } -static int -sb_midi_start_read(int dev) +static int sb_midi_start_read(int dev) { return 0; } -static int -sb_midi_end_read(int dev) +static int sb_midi_end_read(int dev) { - sb_devc *devc = midi_devs[dev]->devc; + sb_devc *devc = midi_devs[dev]->devc; if (devc == NULL) return -ENXIO; @@ -128,14 +122,12 @@ sb_midi_end_read(int dev) return 0; } -/* why -EPERM and not -EINVAL?? */ static int sb_midi_ioctl(int dev, unsigned cmd, caddr_t arg) { - return -EPERM; + return -EINVAL; } -void -sb_midi_interrupt(sb_devc * devc) +void sb_midi_interrupt(sb_devc * devc) { unsigned long flags; unsigned char data; @@ -159,7 +151,9 @@ sb_midi_interrupt(sb_devc * devc) static struct midi_operations sb_midi_operations = { - {"Sound Blaster", 0, 0, SNDCARD_SB}, + { + "Sound Blaster", 0, 0, SNDCARD_SB + }, &std_midi_synth, {0}, sb_midi_open, @@ -174,10 +168,9 @@ static struct midi_operations sb_midi_operations = NULL }; -void -sb_dsp_midi_init(sb_devc * devc) +void sb_dsp_midi_init(sb_devc * devc) { - int dev; + int dev; if (devc->model < 2) /* No MIDI support for SB 1.x */ return; @@ -185,45 +178,34 @@ sb_dsp_midi_init(sb_devc * devc) dev = sound_alloc_mididev(); if (dev == -1) - { - printk("Sound: Too many midi devices detected\n"); - return; - } + { + printk("Sound: Too many midi devices detected\n"); + return; + } std_midi_synth.midi_dev = dev; devc->my_mididev = dev; - std_midi_synth.midi_dev = devc->my_mididev = dev; - - - midi_devs[dev] = (struct midi_operations *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(struct midi_operations))); - sound_mem_sizes[sound_nblocks] = sizeof(struct midi_operations); - - if (sound_nblocks < 1024) - sound_nblocks++;; + midi_devs[dev] = (struct midi_operations *)kmalloc(sizeof(struct midi_operations), GFP_KERNEL); if (midi_devs[dev] == NULL) - { - printk(KERN_WARNING "sb MIDI: Failed to allocate memory\n"); - sound_unload_mididev(dev); + { + printk(KERN_WARNING "soundblaster: Failed to allocate MIDI memory.\n"); + sound_unload_mididev(dev); return; - } + } memcpy((char *) midi_devs[dev], (char *) &sb_midi_operations, sizeof(struct midi_operations)); midi_devs[dev]->devc = devc; - midi_devs[dev]->converter = (struct synth_operations *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(struct synth_operations))); - sound_mem_sizes[sound_nblocks] = sizeof(struct synth_operations); - - if (sound_nblocks < 1024) - sound_nblocks++;; - + midi_devs[dev]->converter = (struct synth_operations *)kmalloc(sizeof(struct synth_operations), GFP_KERNEL); if (midi_devs[dev]->converter == NULL) - { - printk(KERN_WARNING "sb MIDI: Failed to allocate memory\n"); + { + printk(KERN_WARNING "soundblaster: Failed to allocate MIDI memory.\n"); + kfree(midi_devs[dev]); sound_unload_mididev(dev); return; - } + } memcpy((char *) midi_devs[dev]->converter, (char *) &std_midi_synth, sizeof(struct synth_operations)); diff --git a/drivers/sound/sb_mixer.c b/drivers/sound/sb_mixer.c index 2d494a0dd..5f06807ce 100644 --- a/drivers/sound/sb_mixer.c +++ b/drivers/sound/sb_mixer.c @@ -10,13 +10,12 @@ * 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 <linux/config.h> - +#include <linux/config.h> #include "sound_config.h" #if defined(CONFIG_SBDSP) || defined(MODULE) @@ -29,25 +28,22 @@ static int sbmixnum = 1; static void sb_mixer_reset(sb_devc * devc); -void -sb_mixer_set_stereo(sb_devc * devc, int mode) +void sb_mixer_set_stereo(sb_devc * devc, int mode) { sb_setmixer(devc, OUT_FILTER, ((sb_getmixer(devc, OUT_FILTER) & ~STEREO_DAC) | (mode ? STEREO_DAC : MONO_DAC))); } -static int -detect_mixer(sb_devc * devc) +static int detect_mixer(sb_devc * devc) { /* Just trust the mixer is there */ return 1; } -static void -change_bits(sb_devc * devc, unsigned char *regval, int dev, int chn, int newval) +static void change_bits(sb_devc * devc, unsigned char *regval, int dev, int chn, int newval) { - unsigned char mask; - int shift; + unsigned char mask; + int shift; mask = (1 << (*devc->iomap)[dev][chn].nbits) - 1; newval = (int) ((newval * mask) + 50) / 100; /* Scale */ @@ -58,19 +54,16 @@ change_bits(sb_devc * devc, unsigned char *regval, int dev, int chn, int newval) *regval |= (newval & mask) << shift; /* Set the new value */ } -static int -sb_mixer_get(sb_devc * devc, int dev) +static int sb_mixer_get(sb_devc * devc, int dev) { if (!((1 << dev) & devc->supported_devices)) return -EINVAL; - return devc->levels[dev]; } -void -smw_mixer_init(sb_devc * devc) +void smw_mixer_init(sb_devc * devc) { - int i; + int i; sb_setmixer(devc, 0x00, 0x18); /* Mute unused (Telephone) line */ sb_setmixer(devc, 0x10, 0x38); /* Config register 2 */ @@ -81,18 +74,15 @@ smw_mixer_init(sb_devc * devc) devc->supported_devices |= (1 << i); devc->supported_rec_devices = devc->supported_devices & - ~(SOUND_MASK_BASS | SOUND_MASK_TREBLE | SOUND_MASK_PCM | - SOUND_MASK_VOLUME); - + ~(SOUND_MASK_BASS | SOUND_MASK_TREBLE | SOUND_MASK_PCM | SOUND_MASK_VOLUME); sb_mixer_reset(devc); } -static int -smw_mixer_set(sb_devc * devc, int dev, int value) +static int smw_mixer_set(sb_devc * devc, int dev, int value) { - int left = value & 0x000000ff; - int right = (value & 0x0000ff00) >> 8; - int reg, val; + int left = value & 0x000000ff; + int right = (value & 0x0000ff00) >> 8; + int reg, val; if (left > 100) left = 100; @@ -106,46 +96,45 @@ smw_mixer_set(sb_devc * devc, int dev, int value) return -EINVAL; switch (dev) - { - case SOUND_MIXER_VOLUME: - sb_setmixer(devc, 0x0b, 96 - (96 * left / 100)); /* 96=mute, 0=max */ - sb_setmixer(devc, 0x0c, 96 - (96 * right / 100)); - break; - - case SOUND_MIXER_BASS: - case SOUND_MIXER_TREBLE: - devc->levels[dev] = left | (right << 8); - - /* Set left bass and treble values */ - val = ((devc->levels[SOUND_MIXER_TREBLE] & 0xff) * 16 / (unsigned) 100) << 4; - val |= ((devc->levels[SOUND_MIXER_BASS] & 0xff) * 16 / (unsigned) 100) & 0x0f; - sb_setmixer(devc, 0x0d, val); - - /* Set right bass and treble values */ - val = (((devc->levels[SOUND_MIXER_TREBLE] >> 8) & 0xff) * 16 / (unsigned) 100) << 4; - val |= (((devc->levels[SOUND_MIXER_BASS] >> 8) & 0xff) * 16 / (unsigned) 100) & 0x0f; - sb_setmixer(devc, 0x0e, val); - break; - - default: - reg = smw_mix_regs[dev]; - if (reg == 0) - return -EINVAL; - sb_setmixer(devc, reg, (24 - (24 * left / 100)) | 0x20); /* 24=mute, 0=max */ - sb_setmixer(devc, reg + 1, (24 - (24 * right / 100)) | 0x40); - } + { + case SOUND_MIXER_VOLUME: + sb_setmixer(devc, 0x0b, 96 - (96 * left / 100)); /* 96=mute, 0=max */ + sb_setmixer(devc, 0x0c, 96 - (96 * right / 100)); + break; + + case SOUND_MIXER_BASS: + case SOUND_MIXER_TREBLE: + devc->levels[dev] = left | (right << 8); + /* Set left bass and treble values */ + val = ((devc->levels[SOUND_MIXER_TREBLE] & 0xff) * 16 / (unsigned) 100) << 4; + val |= ((devc->levels[SOUND_MIXER_BASS] & 0xff) * 16 / (unsigned) 100) & 0x0f; + sb_setmixer(devc, 0x0d, val); + + /* Set right bass and treble values */ + val = (((devc->levels[SOUND_MIXER_TREBLE] >> 8) & 0xff) * 16 / (unsigned) 100) << 4; + val |= (((devc->levels[SOUND_MIXER_BASS] >> 8) & 0xff) * 16 / (unsigned) 100) & 0x0f; + sb_setmixer(devc, 0x0e, val); + + break; + + default: + reg = smw_mix_regs[dev]; + if (reg == 0) + return -EINVAL; + sb_setmixer(devc, reg, (24 - (24 * left / 100)) | 0x20); /* 24=mute, 0=max */ + sb_setmixer(devc, reg + 1, (24 - (24 * right / 100)) | 0x40); + } devc->levels[dev] = left | (right << 8); return left | (right << 8); } -static int -sb_mixer_set(sb_devc * devc, int dev, int value) +static int sb_mixer_set(sb_devc * devc, int dev, int value) { - int left = value & 0x000000ff; - int right = (value & 0x0000ff00) >> 8; + int left = value & 0x000000ff; + int right = (value & 0x0000ff00) >> 8; - int regoffs; + int regoffs; unsigned char val; if (devc->model == MDL_SMW) @@ -177,21 +166,21 @@ sb_mixer_set(sb_devc * devc, int dev, int value) if ((*devc->iomap)[dev][RIGHT_CHN].regno != regoffs) /* * Change register */ - { - sb_setmixer(devc, regoffs, val); /* + { + sb_setmixer(devc, regoffs, val); /* * Save the old one */ - regoffs = (*devc->iomap)[dev][RIGHT_CHN].regno; + regoffs = (*devc->iomap)[dev][RIGHT_CHN].regno; - if (regoffs == 0) - return left | (left << 8); /* + if (regoffs == 0) + return left | (left << 8); /* * Just left channel present */ - val = sb_getmixer(devc, regoffs); /* - * Read the new one + val = sb_getmixer(devc, regoffs); /* + * Read the new one */ - } + } change_bits(devc, &val, dev, RIGHT_CHN, right); sb_setmixer(devc, regoffs, val); @@ -200,86 +189,107 @@ sb_mixer_set(sb_devc * devc, int dev, int value) return left | (right << 8); } -static void -set_recsrc(sb_devc * devc, int src) +static void set_recsrc(sb_devc * devc, int src) { sb_setmixer(devc, RECORD_SRC, (sb_getmixer(devc, RECORD_SRC) & ~7) | (src & 0x7)); } -static int -set_recmask(sb_devc * devc, int mask) +static int set_recmask(sb_devc * devc, int mask) { - int devmask, i; - unsigned char regimageL, regimageR; + int devmask, i; + unsigned char regimageL, regimageR; devmask = mask & devc->supported_rec_devices; switch (devc->model) - { - case MDL_SBPRO: - case MDL_ESS: - case MDL_JAZZ: - case MDL_SMW: - - if (devmask != SOUND_MASK_MIC && - devmask != SOUND_MASK_LINE && - devmask != SOUND_MASK_CD) - { /* - * More than one devices selected. Drop the * + { + case MDL_SBPRO: + case MDL_ESS: + case MDL_JAZZ: + case MDL_SMW: + + if (devmask != SOUND_MASK_MIC && + devmask != SOUND_MASK_LINE && + devmask != SOUND_MASK_CD) + { + /* + * More than one device selected. Drop the * previous selection */ - devmask &= ~devc->recmask; - } - if (devmask != SOUND_MASK_MIC && - devmask != SOUND_MASK_LINE && - devmask != SOUND_MASK_CD) - { /* - * More than one devices selected. Default to - * * mic + devmask &= ~devc->recmask; + } + if (devmask != SOUND_MASK_MIC && + devmask != SOUND_MASK_LINE && + devmask != SOUND_MASK_CD) + { + /* + * More than one device selected. Default to + * mic */ - devmask = SOUND_MASK_MIC; - } - if (devmask ^ devc->recmask) /* - * Input source changed - */ - { - switch (devmask) - { - - case SOUND_MASK_MIC: - set_recsrc(devc, SRC__MIC); - break; - - case SOUND_MASK_LINE: - set_recsrc(devc, SRC__LINE); - break; - - case SOUND_MASK_CD: - set_recsrc(devc, SRC__CD); - break; - - default: - set_recsrc(devc, SRC__MIC); - } - } - break; - - case MDL_SB16: - if (!devmask) - devmask = SOUND_MASK_MIC; - - regimageL = regimageR = 0; - for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) - if ((1 << i) & devmask) - { - regimageL |= sb16_recmasks_L[i]; - regimageR |= sb16_recmasks_R[i]; - } - sb_setmixer(devc, SB16_IMASK_L, regimageL); - sb_setmixer(devc, SB16_IMASK_R, regimageR); - break; - } - + devmask = SOUND_MASK_MIC; + } + if (devmask ^ devc->recmask) /* + * Input source changed + */ + { + switch (devmask) + { + case SOUND_MASK_MIC: + set_recsrc(devc, SRC__MIC); + break; + + case SOUND_MASK_LINE: + set_recsrc(devc, SRC__LINE); + break; + + case SOUND_MASK_CD: + set_recsrc(devc, SRC__CD); + break; + + default: + set_recsrc(devc, SRC__MIC); + } + } + break; + + case MDL_SB16: + if (!devmask) + devmask = SOUND_MASK_MIC; + + if (devc->submodel == SUBMDL_ALS007) + { + switch (devmask) + { + case SOUND_MASK_LINE: + sb_setmixer(devc, ALS007_RECORD_SRC, ALS007_LINE); + break; + case SOUND_MASK_CD: + sb_setmixer(devc, ALS007_RECORD_SRC, ALS007_CD); + break; + case SOUND_MASK_SYNTH: + sb_setmixer(devc, ALS007_RECORD_SRC, ALS007_SYNTH); + break; + default: /* Also takes care of SOUND_MASK_MIC case */ + sb_setmixer(devc, ALS007_RECORD_SRC, ALS007_MIC); + break; + } + } + else + { + regimageL = regimageR = 0; + for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) + { + if ((1 << i) & devmask) + { + regimageL |= sb16_recmasks_L[i]; + regimageR |= sb16_recmasks_R[i]; + } + sb_setmixer (devc, SB16_IMASK_L, regimageL); + sb_setmixer (devc, SB16_IMASK_R, regimageR); + } + } + break; + } devc->recmask = devmask; return devc->recmask; } @@ -292,52 +302,57 @@ static int sb_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg) /* * Use ioctl(fd, SOUND_MIXER_PRIVATE1, &mode) to turn AGC off (0) or on (1). */ - if (cmd == SOUND_MIXER_PRIVATE1 && devc->model == MDL_SB16) { + if (cmd == SOUND_MIXER_PRIVATE1 && devc->model == MDL_SB16) + { if (get_user(val, (int *)arg)) return -EFAULT; sb_setmixer(devc, 0x43, (~val) & 0x01); return 0; } - if (((cmd >> 8) & 0xff) == 'M') { - if (_SIOC_DIR(cmd) & _SIOC_WRITE) { + if (((cmd >> 8) & 0xff) == 'M') + { + if (_SIOC_DIR(cmd) & _SIOC_WRITE) + { if (get_user(val, (int *)arg)) return -EFAULT; - switch (cmd & 0xff) { + switch (cmd & 0xff) + { + case SOUND_MIXER_RECSRC: + ret = set_recmask(devc, val); + break; + + default: + ret = sb_mixer_set(devc, cmd & 0xff, val); + } + } + else switch (cmd & 0xff) + { case SOUND_MIXER_RECSRC: - ret = set_recmask(devc, val); + ret = devc->recmask; break; - - default: - ret = sb_mixer_set(devc, cmd & 0xff, val); - } - } else - switch (cmd & 0xff) { - case SOUND_MIXER_RECSRC: - ret = devc->recmask; - break; - case SOUND_MIXER_DEVMASK: - ret = devc->supported_devices; - break; + case SOUND_MIXER_DEVMASK: + ret = devc->supported_devices; + break; - case SOUND_MIXER_STEREODEVS: - ret = devc->supported_devices; - if (devc->model != MDL_JAZZ && devc->model != MDL_SMW) - ret &= ~(SOUND_MASK_MIC | SOUND_MASK_SPEAKER | SOUND_MASK_IMIX); - break; + case SOUND_MIXER_STEREODEVS: + ret = devc->supported_devices; + if (devc->model != MDL_JAZZ && devc->model != MDL_SMW) + ret &= ~(SOUND_MASK_MIC | SOUND_MASK_SPEAKER | SOUND_MASK_IMIX); + break; - case SOUND_MIXER_RECMASK: - ret = devc->supported_rec_devices; - break; + case SOUND_MIXER_RECMASK: + ret = devc->supported_rec_devices; + break; - case SOUND_MIXER_CAPS: - ret = devc->mixer_caps; - break; + case SOUND_MIXER_CAPS: + ret = devc->mixer_caps; + break; - default: - ret = sb_mixer_get(devc, cmd & 0xff); - break; - } + default: + ret = sb_mixer_get(devc, cmd & 0xff); + break; + } return put_user(ret, (int *)arg); } else return -EINVAL; @@ -350,12 +365,18 @@ static struct mixer_operations sb_mixer_operations = sb_mixer_ioctl }; -static void -sb_mixer_reset(sb_devc * devc) +static struct mixer_operations als007_mixer_operations = { - char name[32]; - int i; - extern int sm_games; + "ALS007", + "Avance ALS-007", + sb_mixer_ioctl +}; + +static void sb_mixer_reset(sb_devc * devc) +{ + char name[32]; + int i; + extern int sm_games; sprintf(name, "SB_%d", devc->sbmixnum); @@ -366,15 +387,13 @@ sb_mixer_reset(sb_devc * devc) for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) sb_mixer_set(devc, i, devc->levels[i]); - set_recmask(devc, SOUND_MASK_MIC); } -int -sb_mixer_init(sb_devc * devc) +int sb_mixer_init(sb_devc * devc) { - int mixer_type = 0; - int m; + int mixer_type = 0; + int m; devc->sbmixnum = sbmixnum++; devc->levels = NULL; @@ -385,64 +404,69 @@ sb_mixer_init(sb_devc * devc) return 0; /* No mixer. Why? */ switch (devc->model) - { - case MDL_SBPRO: - case MDL_AZTECH: - case MDL_JAZZ: - devc->mixer_caps = SOUND_CAP_EXCL_INPUT; - devc->supported_devices = SBPRO_MIXER_DEVICES; - devc->supported_rec_devices = SBPRO_RECORDING_DEVICES; - devc->iomap = &sbpro_mix; - break; - - case MDL_ESS: - devc->mixer_caps = SOUND_CAP_EXCL_INPUT; - devc->supported_devices = ES688_MIXER_DEVICES; - devc->supported_rec_devices = ES688_RECORDING_DEVICES; - devc->iomap = &es688_mix; - break; - - case MDL_SMW: - devc->mixer_caps = SOUND_CAP_EXCL_INPUT; - devc->supported_devices = 0; - devc->supported_rec_devices = 0; - devc->iomap = &sbpro_mix; - smw_mixer_init(devc); - break; - - case MDL_SB16: - devc->mixer_caps = 0; - devc->supported_devices = SB16_MIXER_DEVICES; - devc->supported_rec_devices = SB16_RECORDING_DEVICES; - devc->iomap = &sb16_mix; - break; - - default: - printk("SB Warning: Unsupported mixer type %d\n", devc->model); - return 0; - } + { + case MDL_SBPRO: + case MDL_AZTECH: + case MDL_JAZZ: + devc->mixer_caps = SOUND_CAP_EXCL_INPUT; + devc->supported_devices = SBPRO_MIXER_DEVICES; + devc->supported_rec_devices = SBPRO_RECORDING_DEVICES; + devc->iomap = &sbpro_mix; + break; + + case MDL_ESS: + devc->mixer_caps = SOUND_CAP_EXCL_INPUT; + devc->supported_devices = ES688_MIXER_DEVICES; + devc->supported_rec_devices = ES688_RECORDING_DEVICES; + devc->iomap = &es688_mix; + break; + + case MDL_SMW: + devc->mixer_caps = SOUND_CAP_EXCL_INPUT; + devc->supported_devices = 0; + devc->supported_rec_devices = 0; + devc->iomap = &sbpro_mix; + smw_mixer_init(devc); + break; + + case MDL_SB16: + devc->mixer_caps = 0; + devc->supported_rec_devices = SB16_RECORDING_DEVICES; + if (devc->submodel != SUBMDL_ALS007) + { + devc->supported_devices = SB16_MIXER_DEVICES; + devc->iomap = &sb16_mix; + } + else + { + devc->supported_devices = ALS007_MIXER_DEVICES; + devc->iomap = &als007_mix; + } + break; + + default: + printk(KERN_WARNING "sb_mixer: Unsupported mixer type %d\n", devc->model); + return 0; + } m = sound_alloc_mixerdev(); if (m == -1) return 0; - - mixer_devs[m] = (struct mixer_operations *) (sound_mem_blocks[sound_nblocks] = vmalloc(sizeof(struct mixer_operations))); - sound_mem_sizes[sound_nblocks] = sizeof(struct mixer_operations); - - if (sound_nblocks < 1024) - sound_nblocks++;; + mixer_devs[m] = (struct mixer_operations *)kmalloc(sizeof(struct mixer_operations), GFP_KERNEL); if (mixer_devs[m] == NULL) - { - printk(KERN_ERR "sb_mixer: Can't allocate memory\n"); - sound_unload_mixerdev(m); - return 0; - } - memcpy((char *) mixer_devs[m], (char *) &sb_mixer_operations, - sizeof(struct mixer_operations)); + { + printk(KERN_ERR "sb_mixer: Can't allocate memory\n"); + sound_unload_mixerdev(m); + return 0; + } - mixer_devs[m]->devc = devc; + if (devc->submodel != SUBMDL_ALS007) + memcpy ((char *) mixer_devs[m], (char *) &sb_mixer_operations, sizeof (struct mixer_operations)); + else + memcpy ((char *) mixer_devs[m], (char *) &als007_mixer_operations, sizeof (struct mixer_operations)); + mixer_devs[m]->devc = devc; devc->my_mixerdev = m; sb_mixer_reset(devc); return 1; diff --git a/drivers/sound/sb_mixer.h b/drivers/sound/sb_mixer.h index 2f68a62f3..f92f02e7d 100644 --- a/drivers/sound/sb_mixer.h +++ b/drivers/sound/sb_mixer.h @@ -49,6 +49,13 @@ SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE | \ SOUND_MASK_IMIX) +/* These are the only devices that are working at the moment. Others could + * be added once they are identified and a method is found to control them. + */ +#define ALS007_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_LINE | \ + SOUND_MASK_PCM | SOUND_MASK_MIC | \ + SOUND_MASK_CD | \ + SOUND_MASK_VOLUME) /* * Mixer registers * @@ -97,6 +104,13 @@ #define LEFT_CHN 0 #define RIGHT_CHN 1 +/* + * Mixer registers of ALS007 + */ +#define ALS007_RECORD_SRC 0x6c +#define ALS007_OUTPUT_CTRL1 0x3c +#define ALS007_OUTPUT_CTRL2 0x4c + #define MIX_ENT(name, reg_l, bit_l, len_l, reg_r, bit_r, len_r) \ {{reg_l, bit_l, len_l}, {reg_r, bit_r, len_r}} @@ -173,6 +187,25 @@ MIX_ENT(SOUND_MIXER_IGAIN, 0x3f, 7, 2, 0x40, 7, 2), MIX_ENT(SOUND_MIXER_OGAIN, 0x41, 7, 2, 0x42, 7, 2) }; +static mixer_tab als007_mix = +{ +MIX_ENT(SOUND_MIXER_VOLUME, 0x62, 7, 4, 0x62, 3, 4), +MIX_ENT(SOUND_MIXER_BASS, 0x00, 0, 0, 0x00, 0, 0), +MIX_ENT(SOUND_MIXER_TREBLE, 0x00, 0, 0, 0x00, 0, 0), +MIX_ENT(SOUND_MIXER_SYNTH, 0x66, 7, 4, 0x66, 3, 4), +MIX_ENT(SOUND_MIXER_PCM, 0x64, 7, 4, 0x64, 3, 4), +MIX_ENT(SOUND_MIXER_SPEAKER, 0x00, 0, 0, 0x00, 0, 0), +MIX_ENT(SOUND_MIXER_LINE, 0x6e, 7, 4, 0x6e, 3, 4), +MIX_ENT(SOUND_MIXER_MIC, 0x6a, 6, 3, 0x00, 0, 0), +MIX_ENT(SOUND_MIXER_CD, 0x68, 7, 4, 0x68, 3, 4), +MIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0), +MIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0), +MIX_ENT(SOUND_MIXER_RECLEV, 0x00, 0, 0, 0x00, 0, 0), /* Obsolete. Use IGAIN */ +MIX_ENT(SOUND_MIXER_IGAIN, 0x00, 0, 0, 0x00, 0, 0), +MIX_ENT(SOUND_MIXER_OGAIN, 0x00, 0, 0, 0x00, 0, 0) +}; + + /* SM_GAMES Master volume is lower and PCM & FM volumes higher than with SB Pro. This improves the sound quality */ @@ -284,5 +317,14 @@ static char smw_mix_regs[] = /* Left mixer registers */ #define SRC__CD 3 /* Select CD recording source */ #define SRC__LINE 7 /* Use Line-in for recording source */ +/* + * Recording sources for ALS-007 + */ + +#define ALS007_MIC 4 +#define ALS007_LINE 6 +#define ALS007_CD 2 +#define ALS007_SYNTH 7 + #endif #endif diff --git a/drivers/sound/sequencer.c b/drivers/sound/sequencer.c index 22d30569f..e65995937 100644 --- a/drivers/sound/sequencer.c +++ b/drivers/sound/sequencer.c @@ -16,6 +16,10 @@ */ #include <linux/config.h> +#ifdef CONFIG_KMOD +#include <linux/kmod.h> +#endif + #define SEQUENCER_C #include "sound_config.h" @@ -478,7 +482,7 @@ static void seq_chn_voice_event(unsigned char *event_rec) parm = 64; } } - + switch (cmd) { case MIDI_NOTEON: @@ -950,7 +954,7 @@ static void setup_mode2(void) synth_devs[max_synthdev++] = midi_devs[dev]->converter; } } - + for (dev = 0; dev < max_synthdev; dev++) { int chn; @@ -993,15 +997,20 @@ int sequencer_open(int dev, struct file *file) return -ENXIO; } if (dev) /* Patch manager device (obsolete) */ - return -ENXIO; + return -ENXIO; + +#ifdef CONFIG_KMOD + if(synth_devs[dev] == NULL) + request_module("synth0"); +#endif if (mode == OPEN_READ) { if (!num_midis) { - /*printk("Sequencer: No MIDI devices. Input not possible\n");*/ - sequencer_busy = 0; - return -ENXIO; + /*printk("Sequencer: No MIDI devices. Input not possible\n");*/ + sequencer_busy = 0; + return -ENXIO; } } save_flags(flags); @@ -1033,8 +1042,8 @@ int sequencer_open(int dev, struct file *file) for (i = 0; i < num_sound_timers; i++) if (sound_timer_devs[i] && sound_timer_devs[i]->priority > best) { - tmr_no = i; - best = sound_timer_devs[i]->priority; + tmr_no = i; + best = sound_timer_devs[i]->priority; } if (tmr_no == -1) /* Should not be */ tmr_no = 0; @@ -1066,7 +1075,7 @@ int sequencer_open(int dev, struct file *file) { if (synth_devs[i]==NULL) continue; - + if ((tmp = synth_devs[i]->open(i, mode)) < 0) { printk(KERN_WARNING "Sequencer: Warning! Cannot open synth device #%d (%d)\n", i, tmp); @@ -1096,7 +1105,7 @@ int sequencer_open(int dev, struct file *file) /* * Initialize midi input devices */ - + for (i = 0; i < max_mididev; i++) if (!midi_opened[i]) { @@ -1140,7 +1149,7 @@ void seq_drain_midi_queues(void) /* * Let's have a delay */ - + if (n) { current->timeout = jiffies + HZ / 10; interruptible_sleep_on(&seq_sleeper); @@ -1173,7 +1182,7 @@ void sequencer_release(int dev, struct file *file) /* Extra delay */ } } - + if (mode != OPEN_READ) seq_drain_midi_queues(); /* * Ensure the output queues are empty @@ -1201,7 +1210,7 @@ void sequencer_release(int dev, struct file *file) for (i = 0; i < max_mididev; i++) { if (midi_opened[i]) - midi_devs[i]->close(i); + midi_devs[i]->close(i); } if (seq_mode == SEQ_2) @@ -1329,7 +1338,7 @@ static void seq_reset(void) save_flags(flags); cli(); - + if (waitqueue_active(&seq_sleeper)) { /* printk( "Sequencer Warning: Unexpected sleeping process - Waking up\n"); */ wake_up(&seq_sleeper); @@ -1368,7 +1377,7 @@ int sequencer_ioctl(int dev, struct file *file, unsigned int cmd, caddr_t arg) orig_dev = dev = dev >> 4; - switch (cmd) + switch (cmd) { case SNDCTL_TMR_TIMEBASE: case SNDCTL_TMR_TEMPO: @@ -1380,13 +1389,13 @@ int sequencer_ioctl(int dev, struct file *file, unsigned int cmd, caddr_t arg) if (seq_mode != SEQ_2) return -EINVAL; return tmr->ioctl(tmr_no, cmd, arg); - + case SNDCTL_TMR_SELECT: if (seq_mode != SEQ_2) return -EINVAL; if (get_user(pending_timer, (int *)arg)) return -EFAULT; - if (pending_timer < 0 || pending_timer >= num_sound_timers || sound_timer_devs[pending_timer] == NULL) + if (pending_timer < 0 || pending_timer >= num_sound_timers || sound_timer_devs[pending_timer] == NULL) { pending_timer = -1; return -EINVAL; @@ -1397,14 +1406,14 @@ int sequencer_ioctl(int dev, struct file *file, unsigned int cmd, caddr_t arg) case SNDCTL_SEQ_PANIC: seq_panic(); return -EINVAL; - + case SNDCTL_SEQ_SYNC: if (mode == OPEN_READ) return 0; while (qlen > 0 && !signal_pending(current)) seq_sync(); return qlen ? -EINTR : 0; - + case SNDCTL_SEQ_RESET: seq_reset(); return 0; @@ -1414,8 +1423,8 @@ int sequencer_ioctl(int dev, struct file *file, unsigned int cmd, caddr_t arg) return -EFAULT; if (midi_dev < 0 || midi_dev >= max_mididev) return -ENXIO; - - if (!midi_opened[midi_dev] && + + if (!midi_opened[midi_dev] && (err = midi_devs[midi_dev]->open(midi_dev, mode, sequencer_midi_input, sequencer_midi_output)) < 0) return err; @@ -1427,13 +1436,13 @@ int sequencer_ioctl(int dev, struct file *file, unsigned int cmd, caddr_t arg) return 0; val = iqlen; break; - + case SNDCTL_SEQ_GETOUTCOUNT: if (mode == OPEN_READ) return 0; val = SEQ_MAX_QUEUE - qlen; break; - + case SNDCTL_SEQ_GETTIME: if (seq_mode == SEQ_2) return tmr->ioctl(tmr_no, cmd, arg); @@ -1442,14 +1451,14 @@ int sequencer_ioctl(int dev, struct file *file, unsigned int cmd, caddr_t arg) else val = jiffies - seq_time; break; - + case SNDCTL_SEQ_CTRLRATE: /* * If *arg == 0, just return the current rate */ if (seq_mode == SEQ_2) return tmr->ioctl(tmr_no, cmd, arg); - + if (get_user(val, (int *)arg)) return -EFAULT; if (val != 0) @@ -1504,7 +1513,7 @@ int sequencer_ioctl(int dev, struct file *file, unsigned int cmd, caddr_t arg) if (!(synth_open_mask & (1 << dev)) && !orig_dev) return -EBUSY; return synth_devs[dev]->ioctl(dev, cmd, arg); - + /* Like SYNTH_INFO but returns ID in the name field */ case SNDCTL_SYNTH_ID: if (get_user(dev, (int *)(&(((struct synth_info *)arg)->device)))) @@ -1517,7 +1526,7 @@ int sequencer_ioctl(int dev, struct file *file, unsigned int cmd, caddr_t arg) strncpy(inf.name, synth_devs[dev]->id, sizeof(inf.name)); inf.device = dev; return copy_to_user(arg, &inf, sizeof(inf))?-EFAULT:0; - + case SNDCTL_SEQ_OUTOFBAND: if (copy_from_user(&event_rec, arg, sizeof(event_rec))) return -EFAULT; @@ -1526,7 +1535,7 @@ int sequencer_ioctl(int dev, struct file *file, unsigned int cmd, caddr_t arg) play_event(event_rec.arr); restore_flags(flags); return 0; - + case SNDCTL_MIDI_INFO: if (get_user(dev, (int *)(&(((struct synth_info *)arg)->device)))) return -EFAULT; @@ -1534,7 +1543,7 @@ int sequencer_ioctl(int dev, struct file *file, unsigned int cmd, caddr_t arg) return -ENXIO; midi_devs[dev]->info.device = dev; return copy_to_user(arg, &midi_devs[dev]->info, sizeof(struct synth_info))?-EFAULT:0; - + case SNDCTL_SEQ_THRESHOLD: if (get_user(val, (int *)arg)) return -EFAULT; @@ -1544,7 +1553,7 @@ int sequencer_ioctl(int dev, struct file *file, unsigned int cmd, caddr_t arg) val = SEQ_MAX_QUEUE - 1; output_threshold = val; return 0; - + case SNDCTL_MIDI_PRETIME: if (get_user(val, (int *)arg)) return -EFAULT; @@ -1584,7 +1593,7 @@ unsigned int sequencer_poll(int dev, struct file *file, poll_table * wait) /* output */ poll_wait(file, &seq_sleeper, wait); - if ((SEQ_MAX_QUEUE - qlen) >= output_threshold) + if ((SEQ_MAX_QUEUE - qlen) >= output_threshold) mask |= POLLOUT | POLLWRNORM; restore_flags(flags); return mask; @@ -1665,8 +1674,8 @@ unsigned long compute_finetune(unsigned long base_freq, int bend, int range, */ while (bend > 2399) { - multiplier *= 4; - bend -= 2400; + multiplier *= 4; + bend -= 2400; } semitones = bend / 100; @@ -1693,8 +1702,8 @@ void sequencer_init(void) queue = (unsigned char *)vmalloc(SEQ_MAX_QUEUE * EV_SZ); if (queue == NULL) { - printk(KERN_ERR "sequencer: Can't allocate memory for sequencer output queue\n"); - return; + printk(KERN_ERR "sequencer: Can't allocate memory for sequencer output queue\n"); + return; } iqueue = (unsigned char *)vmalloc(SEQ_MAX_QUEUE * IEV_SZ); if (iqueue == NULL) diff --git a/drivers/sound/softoss.c b/drivers/sound/softoss.c index 43c3a7ec3..630668853 100644 --- a/drivers/sound/softoss.c +++ b/drivers/sound/softoss.c @@ -2,15 +2,15 @@ * sound/softoss.c * * Software based MIDI synthsesizer driver. - */ -/* + * + * * 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 <linux/config.h> @@ -35,14 +35,15 @@ #include "softoss.h" #include <linux/ultrasound.h> -int softsynth_disabled = 0; +int softsynth_disabled = 0; static volatile int intr_pending = 0; #ifdef POLLED_MODE -static struct timer_list poll_timer = -{NULL, NULL, 0, 0, softsyn_poll}; +static struct timer_list poll_timer = { + NULL, NULL, 0, 0, softsyn_poll +}; #else #endif @@ -101,11 +102,14 @@ extern int *sound_osp; static volatile int is_running = 0; static int softsynth_loaded = 0; -static struct synth_info softsyn_info = -{"SoftOSS", 0, SYNTH_TYPE_SAMPLE, SAMPLE_TYPE_GUS, 0, 16, 0, MAX_PATCH}; +static struct synth_info softsyn_info = { + "SoftOSS", 0, SYNTH_TYPE_SAMPLE, SAMPLE_TYPE_GUS, 0, 16, 0, MAX_PATCH +}; + +static struct softsyn_devc sdev_info = { + 0 +}; -static struct softsyn_devc sdev_info = -{0}; softsyn_devc *devc = &sdev_info; /* used in softoss_rs.c */ static struct voice_alloc_info *voice_alloc; @@ -118,10 +122,9 @@ static volatile int tmr_running = 0; static int voice_limit = 24; -static void -set_max_voices(int nr) +static void set_max_voices(int nr) { - int i; + int i; if (nr < 4) nr = 4; @@ -134,19 +137,18 @@ set_max_voices(int nr) for (i = 31; i > 0; i--) if (nr & (1 << i)) - { - devc->afterscale = i + 1; - return; - } + { + devc->afterscale = i + 1; + return; + } } -static void -update_vibrato(int voice) +static void update_vibrato(int voice) { - voice_info *v = &softoss_voices[voice]; + voice_info *v = &softoss_voices[voice]; #ifdef HANDLE_LFO - int x; + int x; x = vibrato_table[v->vibrato_phase >> 8]; v->vibrato_phase = (v->vibrato_phase + v->vibrato_step) & 0x7fff; @@ -161,11 +163,10 @@ update_vibrato(int voice) } #ifdef HANDLE_LFO -static void -update_tremolo(int voice) +static void update_tremolo(int voice) { - voice_info *v = &softoss_voices[voice]; - int x; + voice_info *v = &softoss_voices[voice]; + int x; x = tremolo_table[v->tremolo_phase >> 8]; v->tremolo_phase = (v->tremolo_phase + v->tremolo_step) & 0x7fff; @@ -174,11 +175,10 @@ update_tremolo(int voice) } #endif -static void -start_vibrato(int voice) +static void start_vibrato(int voice) { - voice_info *v = &softoss_voices[voice]; - int rate; + voice_info *v = &softoss_voices[voice]; + int rate; if (!v->vibrato_depth) return; @@ -189,11 +189,10 @@ start_vibrato(int voice) devc->vibratomap |= (1 << voice); /* Enable vibrato */ } -static void -start_tremolo(int voice) +static void start_tremolo(int voice) { - voice_info *v = &softoss_voices[voice]; - int rate; + voice_info *v = &softoss_voices[voice]; + int rate; if (!v->tremolo_depth) return; @@ -204,43 +203,43 @@ start_tremolo(int voice) devc->tremolomap |= (1 << voice); /* Enable tremolo */ } -static void -update_volume(int voice) +static void update_volume(int voice) { - voice_info *v = &softoss_voices[voice]; - unsigned int vol; + voice_info *v = &softoss_voices[voice]; + unsigned int vol; -/* - * Compute plain volume - */ + /* + * Compute plain volume + */ vol = (v->velocity * v->expression_vol * v->main_vol) >> 12; #ifdef HANDLE_LFO -/* - * Handle LFO - */ + /* + * Handle LFO + */ if (devc->tremolomap & (1 << voice)) - { - int t; + { + int t; - t = 32768 - v->tremolo_level; - vol = (vol * t) >> 15; - update_tremolo(voice); - } + t = 32768 - v->tremolo_level; + vol = (vol * t) >> 15; + update_tremolo(voice); + } #endif -/* - * Envelope - */ + /* + * Envelope + */ + if (v->mode & WAVE_ENVELOPES && !v->percussive_voice) vol = (vol * (v->envelope_vol >> 16)) >> 19; else vol >>= 4; -/* - * Handle panning - */ + /* + * Handle panning + */ if (v->panning < 0) /* Pan left */ v->rightvol = (vol * (128 + v->panning)) / 128; @@ -253,45 +252,47 @@ update_volume(int voice) v->leftvol = vol; } -static void -step_envelope(int voice, int do_release, int velocity) +static void step_envelope(int voice, int do_release, int velocity) { - voice_info *v = &softoss_voices[voice]; - int r, rate, time, dif; - unsigned int vol; - unsigned long flags; + voice_info *v = &softoss_voices[voice]; + int r, rate, time, dif; + unsigned int vol; + unsigned long flags; save_flags(flags); cli(); if (!voice_active[voice] || v->sample == NULL) - { - restore_flags(flags); - return; - } + { + restore_flags(flags); + return; + } if (!do_release) + { if (v->mode & WAVE_SUSTAIN_ON && v->envelope_phase == 2) - { /* Stop envelope until note off */ - v->envelope_volstep = 0; - v->envelope_time = 0x7fffffff; - if (v->mode & WAVE_VIBRATO) - start_vibrato(voice); - if (v->mode & WAVE_TREMOLO) - start_tremolo(voice); - restore_flags(flags); - return; - } + { + /* Stop envelope until note off */ + v->envelope_volstep = 0; + v->envelope_time = 0x7fffffff; + if (v->mode & WAVE_VIBRATO) + start_vibrato(voice); + if (v->mode & WAVE_TREMOLO) + start_tremolo(voice); + restore_flags(flags); + return; + } + } if (do_release) v->envelope_phase = 3; else v->envelope_phase++; if (v->envelope_phase >= 5) /* Finished */ - { - init_voice(devc, voice); - restore_flags(flags); - return; - } + { + init_voice(devc, voice); + restore_flags(flags); + return; + } vol = v->envelope_target = v->sample->env_offset[v->envelope_phase] << 22; @@ -308,72 +309,69 @@ step_envelope(int voice, int do_release, int velocity) if (dif < 0) dif *= -1; if (dif < rate * 2) /* Too close */ - { - step_envelope(voice, 0, 60); - restore_flags(flags); - return; - } + { + step_envelope(voice, 0, 60); + restore_flags(flags); + return; + } + if (vol > v->envelope_vol) - { - v->envelope_volstep = rate; - time = (vol - v->envelope_vol) / rate; - } else - { - v->envelope_volstep = -rate; - time = (v->envelope_vol - vol) / rate; - } + { + v->envelope_volstep = rate; + time = (vol - v->envelope_vol) / rate; + } + else + { + v->envelope_volstep = -rate; + time = (v->envelope_vol - vol) / rate; + } time--; if (time <= 0) time = 1; - v->envelope_time = time; - - restore_flags(flags); } -static void -step_envelope_lfo(int voice) +static void step_envelope_lfo(int voice) { - voice_info *v = &softoss_voices[voice]; + voice_info *v = &softoss_voices[voice]; -/* - * Update pitch (vibrato) LFO - */ + /* + * Update pitch (vibrato) LFO + */ if (devc->vibratomap & (1 << voice)) update_vibrato(voice); -/* - * Update envelope - */ + /* + * Update envelope + */ if (v->mode & WAVE_ENVELOPES) - { - v->envelope_vol += v->envelope_volstep; - /* Overshoot protection */ - if (v->envelope_vol < 0) - { - v->envelope_vol = v->envelope_target; - v->envelope_volstep = 0; - } - if (v->envelope_time-- <= 0) - { - v->envelope_vol = v->envelope_target; - step_envelope(voice, 0, 60); - } - } + { + v->envelope_vol += v->envelope_volstep; + /* Overshoot protection */ + if (v->envelope_vol < 0) + { + v->envelope_vol = v->envelope_target; + v->envelope_volstep = 0; + } + if (v->envelope_time-- <= 0) + { + v->envelope_vol = v->envelope_target; + step_envelope(voice, 0, 60); + } + } } -static void -compute_step(int voice) +static void compute_step(int voice) { - voice_info *v = &softoss_voices[voice]; + voice_info *v = &softoss_voices[voice]; /* - * Since the pitch bender may have been set before playing the note, we - * have to calculate the bending now. + * Since the pitch bender may have been set before playing the note, we + * have to calculate the bending now. */ v->current_freq = compute_finetune(v->orig_freq, @@ -386,11 +384,10 @@ compute_step(int voice) v->step *= -1; /* Reversed playback */ } -static void -init_voice(softsyn_devc * devc, int voice) +static void init_voice(softsyn_devc * devc, int voice) { - voice_info *v = &softoss_voices[voice]; - unsigned long flags; + voice_info *v = &softoss_voices[voice]; + unsigned long flags; save_flags(flags); cli(); @@ -433,18 +430,17 @@ init_voice(softsyn_devc * devc, int voice) restore_flags(flags); } -static void -reset_samples(softsyn_devc * devc) +static void reset_samples(softsyn_devc * devc) { - int i; + int i; for (i = 0; i < MAX_VOICE; i++) voice_active[i] = 0; for (i = 0; i < devc->maxvoice; i++) - { - init_voice(devc, i); - softoss_voices[i].instr = 0; - } + { + init_voice(devc, i); + softoss_voices[i].instr = 0; + } devc->ram_used = 0; @@ -452,20 +448,18 @@ reset_samples(softsyn_devc * devc) devc->programs[i] = NO_SAMPLE; for (i = 0; i < devc->nrsamples; i++) - { - vfree(devc->samples[i]); - vfree(devc->wave[i]); - devc->samples[i] = NULL; - devc->wave[i] = NULL; - } - + { + vfree(devc->samples[i]); + vfree(devc->wave[i]); + devc->samples[i] = NULL; + devc->wave[i] = NULL; + } devc->nrsamples = 0; } -static void -init_engine(softsyn_devc * devc) +static void init_engine(softsyn_devc * devc) { - int i, fz, srate, sz = devc->channels; + int i, fz, srate, sz = devc->channels; set_max_voices(devc->default_max_voices); voice_alloc->timestamp = 0; @@ -480,16 +474,15 @@ init_engine(softsyn_devc * devc) devc->usecs_per_frag = (1000000 * fz) / devc->speed; for (i = 0; i < devc->maxvoice; i++) - { - init_voice(devc, i); - softoss_voices[i].instr = 0; - } - + { + init_voice(devc, i); + softoss_voices[i].instr = 0; + } devc->engine_state = ES_STOPPED; -/* - * Initialize delay - */ + /* + * Initialize delay + */ for (i = 0; i < DELAY_SIZE; i++) left_delay[i] = right_delay[i] = 0; @@ -502,34 +495,35 @@ init_engine(softsyn_devc * devc) devc->delay_size = DELAY_SIZE; } -void -softsyn_control_loop(void) +void softsyn_control_loop(void) { - int voice; + int voice; -/* - * Recompute envlope, LFO, etc. - */ + /* + * Recompute envlope, LFO, etc. + */ for (voice = 0; voice < devc->maxvoice; voice++) + { if (voice_active[voice]) - { - update_volume(voice); - step_envelope_lfo(voice); - } else + { + update_volume(voice); + step_envelope_lfo(voice); + } + else voice_alloc->map[voice] = 0; + } } -static void start_engine(softsyn_devc * devc); +static void start_engine(softsyn_devc * devc); -static void -do_resample(int dummy) +static void do_resample(int dummy) { struct dma_buffparms *dmap = audio_devs[devc->audiodev]->dmap_out; struct voice_info *vinfo; unsigned long flags, jif; - int voice, loops; - short *buf; + int voice, loops; + short *buf; if (softsynth_disabled) return; @@ -538,68 +532,70 @@ do_resample(int dummy) cli(); if (is_running) - { - printk("SoftOSS: Playback overrun\n"); - restore_flags(flags); - return; - } + { + printk(KERN_WARNING "SoftOSS: Playback overrun\n"); + restore_flags(flags); + return; + } jif = jiffies; if (jif == last_resample_jiffies) - { - if (resample_counter++ > 50) - { - for (voice = 0; voice < devc->maxvoice; voice++) - init_voice(devc, voice); - voice_limit--; - resample_counter = 0; - printk("SoftOSS: CPU overload. Limiting # of voices to %d\n", voice_limit); - - if (voice_limit < 10) - { - voice_limit = 10; - devc->speed = (devc->speed * 2) / 3; - - printk("SoftOSS: Dropping sampling rate and stopping the device.\n"); - softsynth_disabled = 1; - } - } - } else - { - last_resample_jiffies = jif; - resample_counter = 0; - } + { + if (resample_counter++ > 50) + { + for (voice = 0; voice < devc->maxvoice; voice++) + init_voice(devc, voice); + voice_limit--; + resample_counter = 0; + printk(KERN_WARNING "SoftOSS: CPU overload. Limiting # of voices to %d\n", voice_limit); + + if (voice_limit < 10) + { + voice_limit = 10; + devc->speed = (devc->speed * 2) / 3; + + printk(KERN_WARNING "SoftOSS: Dropping sampling rate and stopping the device.\n"); + softsynth_disabled = 1; + } + } + } + else + { + last_resample_jiffies = jif; + resample_counter = 0; + } /* is_running = 1; */ if (dmap->qlen > devc->max_playahead) - { - printk("SoftOSS: audio buffers full\n"); - is_running = 0; - restore_flags(flags); - return; - } -/* - * First verify that all active voices are valid (do this just once per block). - */ + { + printk(KERN_WARNING "SoftOSS: audio buffers full\n"); + is_running = 0; + restore_flags(flags); + return; + } + /* + * First verify that all active voices are valid (do this just once per block). + */ + for (voice = 0; voice < devc->maxvoice; voice++) + { if (voice_active[voice]) - { - int ptr; - - vinfo = &softoss_voices[voice]; - ptr = vinfo->ptr >> 9; - - if (vinfo->wave == NULL || - ptr < 0 || - ptr > vinfo->sample->len) - init_voice(devc, voice); - else if (!(vinfo->mode & WAVE_LOOPING) && - (vinfo->ptr + vinfo->step) > vinfo->endloop) + { + int ptr; + + vinfo = &softoss_voices[voice]; + ptr = vinfo->ptr >> 9; + + if (vinfo->wave == NULL || ptr < 0 || ptr > vinfo->sample->len) + init_voice(devc, voice); + else if (!(vinfo->mode & WAVE_LOOPING) && (vinfo->ptr + vinfo->step) > vinfo->endloop) voice_active[voice] = 0; - } -/* - * Start the resampling process - */ + } + } + + /* + * Start the resampling process + */ loops = devc->samples_per_fragment; buf = (short *) (dmap->raw_buf + (dmap->qtail * dmap->fragment_size)); @@ -613,54 +609,51 @@ do_resample(int dummy) devc->usecs += devc->usecs_per_frag; if (tmr_running) - { - sound_timer_interrupt(); - } -/* - * Execute timer - */ + sound_timer_interrupt(); + /* + * Execute timer + */ if (!tmr_running) + { if (devc->usecs >= devc->next_event_usecs) - { - devc->next_event_usecs = ~0; - sequencer_timer(0); - } + { + devc->next_event_usecs = ~0; + sequencer_timer(0); + } + } + is_running = 0; restore_flags(flags); } -static void -delayed_resample(int dummy) +static void delayed_resample(int dummy) { struct dma_buffparms *dmap = audio_devs[devc->audiodev]->dmap_out; - int n = 0; + int n = 0; if (is_running) return; - while (devc->engine_state != ES_STOPPED && - dmap->qlen < devc->max_playahead && n++ < 2) + while (devc->engine_state != ES_STOPPED && dmap->qlen < devc->max_playahead && n++ < 2) do_resample(0); intr_pending = 0; } #ifdef POLLED_MODE -static void -softsyn_poll(unsigned long dummy) +static void softsyn_poll(unsigned long dummy) { delayed_resample(0); if (devc->engine_state != ES_STOPPED) - - { - poll_timer.expires = (1) + jiffies; + { + poll_timer.expires = jiffies+1; add_timer(&poll_timer); - }; + } } + #else -static void -softsyn_callback(int dev, int parm) +static void softsyn_callback(int dev, int parm) { delayed_resample(0); } @@ -686,13 +679,14 @@ static void start_engine(softsyn_devc * devc) devc->control_rate = 64; devc->control_counter = 0; - if (devc->engine_state == ES_STOPPED) { + if (devc->engine_state == ES_STOPPED) + { n = trig = 0; fs = get_fs(); set_fs(get_ds()); dma_ioctl(devc->audiodev, SNDCTL_DSP_SETTRIGGER, (caddr_t)&trig); #ifdef POLLED_MODE - poll_timer.expires = (1) + jiffies; + poll_timer.expires = jiffies+1; add_timer(&poll_timer); /* Start polling */ #else @@ -711,13 +705,11 @@ static void start_engine(softsyn_devc * devc) } } -static void -stop_engine(softsyn_devc * devc) +static void stop_engine(softsyn_devc * devc) { } -static void -request_engine(softsyn_devc * devc, int ticks) +static void request_engine(softsyn_devc * devc, int ticks) { if (ticks < 0) /* Relative time */ devc->next_event_usecs = devc->usecs - ticks * (1000000 / HZ); @@ -728,74 +720,72 @@ request_engine(softsyn_devc * devc, int ticks) /* * Softsync hook serves mode1 (timing) calls made by sequencer.c */ -static int -softsynth_hook(int cmd, int parm1, int parm2, unsigned long parm3) + +static int softsynth_hook(int cmd, int parm1, int parm2, unsigned long parm3) { switch (cmd) - { - case SSYN_START: - start_engine(devc); - break; + { + case SSYN_START: + start_engine(devc); + break; - case SSYN_STOP: - stop_engine(devc); - break; + case SSYN_STOP: + stop_engine(devc); + break; - case SSYN_REQUEST: - request_engine(devc, parm1); - break; + case SSYN_REQUEST: + request_engine(devc, parm1); + break; - case SSYN_GETTIME: - return devc->usecs / (1000000 / HZ); - break; - - default: - printk("SoftOSS: Unknown request %d\n", cmd); - } + case SSYN_GETTIME: + return devc->usecs / (1000000 / HZ); + break; + default: + printk(KERN_WARNING "SoftOSS: Unknown request %d\n", cmd); + } return 0; } static int softsyn_ioctl(int dev, unsigned int cmd, caddr_t arg) { - switch (cmd) { - - case SNDCTL_SYNTH_INFO: - softsyn_info.nr_voices = devc->maxvoice; - if (__copy_to_user(arg, &softsyn_info, sizeof(softsyn_info))) - return -EFAULT; - return 0; - - case SNDCTL_SEQ_RESETSAMPLES: - stop_engine(devc); - reset_samples(devc); - return 0; + switch (cmd) + { + case SNDCTL_SYNTH_INFO: + softsyn_info.nr_voices = devc->maxvoice; + if (copy_to_user(arg, &softsyn_info, sizeof(softsyn_info))) + return -EFAULT; + return 0; + + case SNDCTL_SEQ_RESETSAMPLES: + stop_engine(devc); + reset_samples(devc); + return 0; - case SNDCTL_SYNTH_MEMAVL: - return devc->ram_size - devc->ram_used; + case SNDCTL_SYNTH_MEMAVL: + return devc->ram_size - devc->ram_used; - default: - return -EINVAL; + default: + return -EINVAL; } } -static int -softsyn_kill_note(int devno, int voice, int note, int velocity) +static int softsyn_kill_note(int devno, int voice, int note, int velocity) { if (voice < 0 || voice > devc->maxvoice) return 0; voice_alloc->map[voice] = 0xffff; /* Releasing */ if (softoss_voices[voice].sustain_mode & 1) /* Sustain controller on */ - { - softoss_voices[voice].sustain_mode = 3; /* Note off pending */ - return 0; - } + { + softoss_voices[voice].sustain_mode = 3; /* Note off pending */ + return 0; + } if (velocity > 127 || softoss_voices[voice].mode & WAVE_FAST_RELEASE) - { - init_voice(devc, voice); /* Mark it inactive */ - return 0; - } + { + init_voice(devc, voice); /* Mark it inactive */ + return 0; + } if (softoss_voices[voice].mode & WAVE_ENVELOPES) step_envelope(voice, 1, velocity); /* Enter sustain phase */ else @@ -803,29 +793,26 @@ softsyn_kill_note(int devno, int voice, int note, int velocity) return 0; } -static int -softsyn_set_instr(int dev, int voice, int instr) +static int softsyn_set_instr(int dev, int voice, int instr) { if (voice < 0 || voice > devc->maxvoice) return 0; if (instr < 0 || instr > MAX_PATCH) - { - printk("SoftOSS: Invalid instrument number %d\n", instr); - return 0; - } + { + printk(KERN_ERR "SoftOSS: Invalid instrument number %d\n", instr); + return 0; + } softoss_voices[voice].instr = instr; - return 0; } -static int -softsyn_start_note(int dev, int voice, int note, int volume) +static int softsyn_start_note(int dev, int voice, int note, int volume) { - int instr = 0; - int best_sample, best_delta, delta_freq, selected; - unsigned long note_freq, freq, base_note, flags; - voice_info *v = &softoss_voices[voice]; + int instr = 0; + int best_sample, best_delta, delta_freq, selected; + unsigned long note_freq, freq, base_note, flags; + voice_info *v = &softoss_voices[voice]; struct patch_info *sample; @@ -839,32 +826,32 @@ softsyn_start_note(int dev, int voice, int note, int volume) cli(); if (note == 255) - { /* Just volume update */ - v->velocity = volume; - if (voice_active[voice]) - update_volume(voice); - restore_flags(flags); - return 0; - } + { /* Just volume update */ + v->velocity = volume; + if (voice_active[voice]) + update_volume(voice); + restore_flags(flags); + return 0; + } voice_active[voice] = 0; /* Stop the voice for a while */ devc->vibratomap &= ~(1 << voice); devc->tremolomap &= ~(1 << voice); instr = v->instr; if (instr < 0 || instr > MAX_PATCH || devc->programs[instr] == NO_SAMPLE) - { - printk("SoftOSS: Undefined MIDI instrument %d\n", instr); - restore_flags(flags); - return 0; - } + { + printk(KERN_WARNING "SoftOSS: Undefined MIDI instrument %d\n", instr); + restore_flags(flags); + return 0; + } instr = devc->programs[instr]; if (instr < 0 || instr >= devc->nrsamples) - { - printk("SoftOSS: Corrupted MIDI instrument %d (%d)\n", v->instr, instr); - restore_flags(flags); - return 0; - } + { + printk(KERN_WARNING "SoftOSS: Corrupted MIDI instrument %d (%d)\n", v->instr, instr); + restore_flags(flags); + return 0; + } note_freq = note_to_freq(note); selected = -1; @@ -873,25 +860,26 @@ softsyn_start_note(int dev, int voice, int note, int volume) best_delta = 1000000; while (instr != NO_SAMPLE && instr >= 0 && selected == -1) - { - delta_freq = note_freq - devc->samples[instr]->base_note; - - if (delta_freq < 0) - delta_freq = -delta_freq; - if (delta_freq < best_delta) - { - best_sample = instr; - best_delta = delta_freq; - } - if (devc->samples[instr]->low_note <= note_freq && - note_freq <= devc->samples[instr]->high_note) - selected = instr; - else - instr = devc->samples[instr]->key; /* Link to next sample */ - - if (instr < 0 || instr >= devc->nrsamples) - instr = NO_SAMPLE; - } + { + delta_freq = note_freq - devc->samples[instr]->base_note; + + if (delta_freq < 0) + delta_freq = -delta_freq; + if (delta_freq < best_delta) + { + best_sample = instr; + best_delta = delta_freq; + } + if (devc->samples[instr]->low_note <= note_freq && + note_freq <= devc->samples[instr]->high_note) + { + selected = instr; + } + else instr = devc->samples[instr]->key; /* Link to next sample */ + + if (instr < 0 || instr >= devc->nrsamples) + instr = NO_SAMPLE; + } if (selected == -1) instr = best_sample; @@ -899,37 +887,33 @@ softsyn_start_note(int dev, int voice, int note, int volume) instr = selected; if (instr < 0 || instr == NO_SAMPLE || instr > devc->nrsamples) - { - printk("SoftOSS: Unresolved MIDI instrument %d\n", v->instr); - restore_flags(flags); - return 0; - } + { + printk(KERN_WARNING "SoftOSS: Unresolved MIDI instrument %d\n", v->instr); + restore_flags(flags); + return 0; + } sample = devc->samples[instr]; v->sample = sample; if (v->percussive_voice) /* No key tracking */ - { v->orig_freq = sample->base_freq; /* Fixed pitch */ - } else - { - base_note = sample->base_note / 100; - note_freq /= 100; + else + { + base_note = sample->base_note / 100; + note_freq /= 100; - freq = sample->base_freq * note_freq / base_note; - v->orig_freq = freq; - } + freq = sample->base_freq * note_freq / base_note; + v->orig_freq = freq; + } if (!(sample->mode & WAVE_LOOPING)) - { - sample->loop_end = sample->len; - } - v->wave = devc->wave[instr]; + sample->loop_end = sample->len; + v->wave = devc->wave[instr]; if (volume < 0) volume = 0; else if (volume > 127) volume = 127; - v->ptr = 0; v->startloop = sample->loop_start * 512; v->startbackloop = 0; @@ -954,40 +938,39 @@ softsyn_start_note(int dev, int voice, int note, int volume) if (!(v->mode & WAVE_LOOPING)) v->mode &= ~(WAVE_BIDIR_LOOP | WAVE_LOOP_BACK); else if (v->mode & WAVE_LOOP_BACK) - { - v->ptr = sample->len; - v->startbackloop = v->startloop; - } + { + v->ptr = sample->len; + v->startbackloop = v->startloop; + } if (v->mode & WAVE_VIBRATO) - { - v->vibrato_rate = sample->vibrato_rate; - v->vibrato_depth = sample->vibrato_depth; - } + { + v->vibrato_rate = sample->vibrato_rate; + v->vibrato_depth = sample->vibrato_depth; + } if (v->mode & WAVE_TREMOLO) - { - v->tremolo_rate = sample->tremolo_rate; - v->tremolo_depth = sample->tremolo_depth; - } + { + v->tremolo_rate = sample->tremolo_rate; + v->tremolo_depth = sample->tremolo_depth; + } if (v->mode & WAVE_ENVELOPES) - { - v->envelope_phase = -1; - v->envelope_vol = 0; - step_envelope(voice, 0, 60); - } + { + v->envelope_phase = -1; + v->envelope_vol = 0; + step_envelope(voice, 0, 60); + } update_volume(voice); compute_step(voice); voice_active[voice] = 1; /* Mark it active */ - restore_flags(flags); return 0; } static int softsyn_open(int synthdev, int mode) { - int err; - extern int softoss_dev; - int frags = 0x7fff0007; /* fragment size of 128 bytes */ + int err; + extern int softoss_dev; + int frags = 0x7fff0007; /* fragment size of 128 bytes */ mm_segment_t fs; if (devc->audio_opened) /* Already opened */ @@ -1007,10 +990,10 @@ static int softsyn_open(int synthdev, int mode) devc->audiodev = softoss_dev; if (!(audio_devs[devc->audiodev]->format_mask & AFMT_S16_LE)) - { - printk("SoftOSS: The audio device doesn't support 16 bits\n"); - return -ENXIO; - } + { +/* printk(KERN_ERR "SoftOSS: The audio device doesn't support 16 bits\n"); */ + return -ENXIO; + } if ((err = audio_open((devc->audiodev << 4) | SND_DEV_DSP16, &devc->finfo)) < 0) return err; @@ -1023,7 +1006,6 @@ static int softsyn_open(int synthdev, int mode) DDB(printk("SoftOSS: Using audio dev %d, speed %d, bits %d, channels %d\n", devc->audiodev, devc->speed, devc->bits, devc->channels)); - fs = get_fs(); set_fs(get_ds()); dma_ioctl(devc->audiodev, SNDCTL_DSP_SETFRAGMENT, (caddr_t) & frags); @@ -1031,11 +1013,11 @@ static int softsyn_open(int synthdev, int mode) set_fs(fs); if (devc->bits != 16 || devc->channels != 2) - { - audio_release((devc->audiodev << 4) | SND_DEV_DSP16, &devc->finfo); - printk("SoftOSS: A 16 bit stereo soundcard is required\n"); - return 0; - } + { + audio_release((devc->audiodev << 4) | SND_DEV_DSP16, &devc->finfo); +/* printk("SoftOSS: A 16 bit stereo soundcard is required\n");*/ + return -EINVAL; + } if (devc->max_playahead >= audio_devs[devc->audiodev]->dmap_out->nbufs) devc->max_playahead = audio_devs[devc->audiodev]->dmap_out->nbufs; @@ -1064,12 +1046,11 @@ static void softsyn_close(int synthdev) devc->audio_opened = 0; } -static void -softsyn_hw_control(int dev, unsigned char *event_rec) +static void softsyn_hw_control(int dev, unsigned char *event_rec) { - int voice, cmd; - unsigned short p1, p2; - unsigned int plong; + int voice, cmd; + unsigned short p1, p2; + unsigned int plong; cmd = event_rec[2]; voice = event_rec[3]; @@ -1078,48 +1059,47 @@ softsyn_hw_control(int dev, unsigned char *event_rec) plong = *(unsigned int *) &event_rec[4]; switch (cmd) - { - - case _GUS_NUMVOICES: - set_max_voices(p1); - break; + { + case _GUS_NUMVOICES: + set_max_voices(p1); + break; - default:; - } + default:; + } } -static int -softsyn_load_patch(int dev, int format, const char *addr, +static int softsyn_load_patch(int dev, int format, const char *addr, int offs, int count, int pmgr_flag) { struct patch_info *patch = NULL; - int i, p, instr; - long sizeof_patch; - int memlen, adj; + int i, p, instr; + long sizeof_patch; + int memlen, adj; unsigned short data; - short *wave = NULL; + short *wave = NULL; sizeof_patch = (long) &patch->data[0] - (long) patch; /* Header size */ if (format != GUS_PATCH) - { - printk("SoftOSS: Invalid patch format (key) 0x%x\n", format); - return -EINVAL; - } + { +/* printk(KERN_ERR "SoftOSS: Invalid patch format (key) 0x%x\n", format);*/ + return -EINVAL; + } if (count < sizeof_patch) - { - printk("SoftOSS: Patch header too short\n"); - return -EINVAL; - } + { +/* printk(KERN_ERR "SoftOSS: Patch header too short\n");*/ + return -EINVAL; + } count -= sizeof_patch; if (devc->nrsamples >= MAX_SAMPLE) - { - printk("SoftOSS: Sample table full\n"); - return -ENOSPC; - } + { +/* printk(KERN_ERR "SoftOSS: Sample table full\n");*/ + return -ENOBUFS; + } + /* * Copy the header from user space but ignore the first bytes which have * been transferred already. @@ -1128,54 +1108,55 @@ softsyn_load_patch(int dev, int format, const char *addr, patch = vmalloc(sizeof(*patch)); if (patch == NULL) - { - printk("SoftOSS: Out of memory\n"); - return -ENOSPC; - } - copy_from_user(&((char *) patch)[offs], &(addr)[offs], sizeof_patch - offs); + { +/* printk(KERN_ERR "SoftOSS: Out of memory\n");*/ + return -ENOMEM; + } + if(copy_from_user(&((char *) patch)[offs], &(addr)[offs], sizeof_patch - offs)) + return -EFAULT; if (patch->mode & WAVE_ROM) - { - vfree(patch); - return -EINVAL; - } + { + vfree(patch); + return -EINVAL; + } instr = patch->instr_no; if (instr < 0 || instr > MAX_PATCH) - { - printk("SoftOSS: Invalid patch number %d\n", instr); - vfree(patch); - return -EINVAL; - } + { +/* printk(KERN_ERR "SoftOSS: Invalid patch number %d\n", instr);*/ + vfree(patch); + return -EINVAL; + } if (count < patch->len) - { - printk("SoftOSS: Patch record too short (%d<%d)\n", count, (int) patch->len); - patch->len = count; - } + { +/* printk(KERN_ERR "SoftOSS: Patch record too short (%d<%d)\n", count, (int) patch->len);*/ + patch->len = count; + } if (patch->len <= 0 || patch->len > (devc->ram_size - devc->ram_used)) - { - printk("SoftOSS: Invalid sample length %d\n", (int) patch->len); - vfree(patch); - return -EINVAL; - } + { +/* printk(KERN_ERR "SoftOSS: Invalid sample length %d\n", (int) patch->len); */ + vfree(patch); + return -EINVAL; + } if (patch->mode & WAVE_LOOPING) - { - if (patch->loop_start < 0 || patch->loop_start >= patch->len) - { - printk("SoftOSS: Invalid loop start %d\n", patch->loop_start); - vfree(patch); - return -EINVAL; - } - if (patch->loop_end < patch->loop_start || patch->loop_end > patch->len) - { - printk("SoftOSS: Invalid loop start or end point (%d, %d)\n", patch->loop_start, patch->loop_end); - vfree(patch); - return -EINVAL; - } - } -/* - * Next load the wave data to memory - */ + { + if (patch->loop_start < 0 || patch->loop_start >= patch->len) + { +/* printk(KERN_ERR "SoftOSS: Invalid loop start %d\n", patch->loop_start);*/ + vfree(patch); + return -EINVAL; + } + if (patch->loop_end < patch->loop_start || patch->loop_end > patch->len) + { +/* printk(KERN_ERR "SoftOSS: Invalid loop start or end point (%d, %d)\n", patch->loop_start, patch->loop_end);*/ + vfree(patch); + return -EINVAL; + } + } + /* + * Next load the wave data to memory + */ memlen = patch->len; adj = 1; @@ -1188,48 +1169,47 @@ softsyn_load_patch(int dev, int format, const char *addr, wave = vmalloc(memlen); if (wave == NULL) - { - printk("SoftOSS: Can't allocate %d bytes of mem for a sample\n", memlen); - vfree(patch); - return -ENOSPC; - } + { +/* printk(KERN_ERR "SoftOSS: Can't allocate %d bytes of mem for a sample\n", memlen);*/ + vfree(patch); + return -ENOMEM; + } p = 0; for (i = 0; i < memlen / 2; i++) /* Handle words */ - { - unsigned char tmp; - - data = 0; - - if (patch->mode & WAVE_16_BITS) - { - get_user(*(unsigned char *) &tmp, (unsigned char *) &((addr)[sizeof_patch + p++])); /* Get lsb */ - data = tmp; - get_user(*(unsigned char *) &tmp, (unsigned char *) &((addr)[sizeof_patch + p++])); /* Get msb */ - if (patch->mode & WAVE_UNSIGNED) - tmp ^= 0x80; /* Convert to signed */ - data |= (tmp << 8); - } else - { - get_user(*(unsigned char *) &tmp, (unsigned char *) &((addr)[sizeof_patch + p++])); - if (patch->mode & WAVE_UNSIGNED) - tmp ^= 0x80; /* Convert to signed */ + { + unsigned char tmp; + data = 0; + if (patch->mode & WAVE_16_BITS) + { + get_user(*(unsigned char *) &tmp, (unsigned char *) &((addr)[sizeof_patch + p++])); /* Get lsb */ + data = tmp; + get_user(*(unsigned char *) &tmp, (unsigned char *) &((addr)[sizeof_patch + p++])); /* Get msb */ + if (patch->mode & WAVE_UNSIGNED) + tmp ^= 0x80; /* Convert to signed */ + data |= (tmp << 8); + } + else + { + get_user(*(unsigned char *) &tmp, (unsigned char *) &((addr)[sizeof_patch + p++])); + if (patch->mode & WAVE_UNSIGNED) + tmp ^= 0x80; /* Convert to signed */ data = (tmp << 8); /* Convert to 16 bits */ - } - - wave[i] = (short) data; - } + } + wave[i] = (short) data; + } devc->ram_used += patch->len; -/* - * Convert pointers to 16 bit indexes - */ + + /* + * Convert pointers to 16 bit indexes + */ patch->len /= adj; patch->loop_start /= adj; patch->loop_end /= adj; -/* - * Finally link the loaded patch to the chain - */ + /* + * Finally link the loaded patch to the chain + */ patch->key = devc->programs[instr]; devc->programs[instr] = devc->nrsamples; @@ -1239,8 +1219,7 @@ softsyn_load_patch(int dev, int format, const char *addr, return 0; } -static void -softsyn_panning(int dev, int voice, int pan) +static void softsyn_panning(int dev, int voice, int pan) { if (voice < 0 || voice > devc->maxvoice) return; @@ -1255,13 +1234,11 @@ softsyn_panning(int dev, int voice, int pan) update_volume(voice); } -static void -softsyn_volume_method(int dev, int mode) +static void softsyn_volume_method(int dev, int mode) { } -static void -softsyn_aftertouch(int dev, int voice, int pressure) +static void softsyn_aftertouch(int dev, int voice, int pressure) { if (voice < 0 || voice > devc->maxvoice) return; @@ -1270,10 +1247,9 @@ softsyn_aftertouch(int dev, int voice, int pressure) update_volume(voice); } -static void -softsyn_controller(int dev, int voice, int ctrl_num, int value) +static void softsyn_controller(int dev, int voice, int ctrl_num, int value) { - unsigned long flags; + unsigned long flags; if (voice < 0 || voice > devc->maxvoice) return; @@ -1281,48 +1257,46 @@ softsyn_controller(int dev, int voice, int ctrl_num, int value) cli(); switch (ctrl_num) - { - case CTRL_PITCH_BENDER: - softoss_voices[voice].bender = value; - - if (voice_active[voice]) - compute_step(voice); /* Update pitch */ - break; - - - case CTRL_PITCH_BENDER_RANGE: - softoss_voices[voice].bender_range = value; - break; - case CTL_EXPRESSION: - value /= 128; - case CTRL_EXPRESSION: - softoss_voices[voice].expression_vol = value; - if (voice_active[voice]) - update_volume(voice); - break; - - case CTL_PAN: - softsyn_panning(dev, voice, (value * 2) - 128); - break; - - case CTL_MAIN_VOLUME: - value = (value * 100) / 16383; - - case CTRL_MAIN_VOLUME: - softoss_voices[voice].main_vol = value; - if (voice_active[voice]) - update_volume(voice); - break; - - default: - break; - } - + { + case CTRL_PITCH_BENDER: + softoss_voices[voice].bender = value; + if (voice_active[voice]) + compute_step(voice); /* Update pitch */ + break; + + + case CTRL_PITCH_BENDER_RANGE: + softoss_voices[voice].bender_range = value; + break; + + case CTL_EXPRESSION: + value /= 128; + case CTRL_EXPRESSION: + softoss_voices[voice].expression_vol = value; + if (voice_active[voice]) + update_volume(voice); + break; + + case CTL_PAN: + softsyn_panning(dev, voice, (value * 2) - 128); + break; + + case CTL_MAIN_VOLUME: + value = (value * 100) / 16383; + + case CTRL_MAIN_VOLUME: + softoss_voices[voice].main_vol = value; + if (voice_active[voice]) + update_volume(voice); + break; + + default: + break; + } restore_flags(flags); } -static void -softsyn_bender(int dev, int voice, int value) +static void softsyn_bender(int dev, int voice, int value) { if (voice < 0 || voice > devc->maxvoice) return; @@ -1332,46 +1306,46 @@ softsyn_bender(int dev, int voice, int value) compute_step(voice); /* Update pitch */ } -static int -softsyn_alloc_voice(int dev, int chn, int note, struct voice_alloc_info *alloc) +static int softsyn_alloc_voice(int dev, int chn, int note, struct voice_alloc_info *alloc) { - int i, p, best = -1, best_time = 0x7fffffff; + int i, p, best = -1, best_time = 0x7fffffff; p = alloc->ptr; + /* - * First look for a completely stopped voice + * First look for a completely stopped voice */ for (i = 0; i < alloc->max_voice; i++) - { - if (alloc->map[p] == 0) - { - alloc->ptr = p; - voice_active[p] = 0; - return p; - } - if (alloc->alloc_times[p] < best_time) - { - best = p; - best_time = alloc->alloc_times[p]; - } - p = (p + 1) % alloc->max_voice; - } + { + if (alloc->map[p] == 0) + { + alloc->ptr = p; + voice_active[p] = 0; + return p; + } + if (alloc->alloc_times[p] < best_time) + { + best = p; + best_time = alloc->alloc_times[p]; + } + p = (p + 1) % alloc->max_voice; + } /* - * Then look for a releasing voice + * Then look for a releasing voice */ for (i = 0; i < alloc->max_voice; i++) - { - if (alloc->map[p] == 0xffff) - { - alloc->ptr = p; - voice_active[p] = 0; - return p; - } - p = (p + 1) % alloc->max_voice; - } + { + if (alloc->map[p] == 0xffff) + { + alloc->ptr = p; + voice_active[p] = 0; + return p; + } + p = (p + 1) % alloc->max_voice; + } if (best >= 0) p = best; @@ -1381,23 +1355,20 @@ softsyn_alloc_voice(int dev, int chn, int note, struct voice_alloc_info *alloc) return p; } -static void -softsyn_setup_voice(int dev, int voice, int chn) +static void softsyn_setup_voice(int dev, int voice, int chn) { - unsigned long flags; + unsigned long flags; - struct channel_info *info = - &synth_devs[dev]->chn_info[chn]; + struct channel_info *info = &synth_devs[dev]->chn_info[chn]; save_flags(flags); cli(); + /* init_voice(devc, voice); */ softsyn_set_instr(dev, voice, info->pgm_num); - softoss_voices[voice].expression_vol = - info->controllers[CTL_EXPRESSION]; /* Just MSB */ - softoss_voices[voice].main_vol = - (info->controllers[CTL_MAIN_VOLUME] * 100) / (unsigned) 128; + softoss_voices[voice].expression_vol = info->controllers[CTL_EXPRESSION]; /* Just MSB */ + softoss_voices[voice].main_vol = (info->controllers[CTL_MAIN_VOLUME] * 100) / (unsigned) 128; softsyn_panning(dev, voice, (info->controllers[CTL_PAN] * 2) - 128); softoss_voices[voice].bender = 0; /* info->bender_value; */ softoss_voices[voice].bender_range = info->bender_range; @@ -1407,11 +1378,10 @@ softsyn_setup_voice(int dev, int voice, int chn) restore_flags(flags); } -static void -softsyn_reset(int devno) +static void softsyn_reset(int devno) { - int i; - unsigned long flags; + int i; + unsigned long flags; save_flags(flags); cli(); @@ -1450,23 +1420,20 @@ static struct synth_operations softsyn_operations = * Timer stuff (for /dev/music). */ -static unsigned int -soft_tmr_start(int dev, unsigned int usecs) +static unsigned int soft_tmr_start(int dev, unsigned int usecs) { tmr_running = 1; start_engine(devc); return devc->usecs_per_frag; } -static void -soft_tmr_disable(int dev) +static void soft_tmr_disable(int dev) { stop_engine(devc); tmr_running = 0; } -static void -soft_tmr_restart(int dev) +static void soft_tmr_restart(int dev) { tmr_running = 1; } @@ -1480,10 +1447,9 @@ static struct sound_lowlev_timer soft_tmr = soft_tmr_restart }; -int -probe_softsyn(struct address_info *hw_config) +int probe_softsyn(struct address_info *hw_config) { - int i; + int i; if (softsynth_loaded) return 0; @@ -1492,10 +1458,10 @@ probe_softsyn(struct address_info *hw_config) devc->ram_used = 0; devc->nrsamples = 0; for (i = 0; i < MAX_PATCH; i++) - { - devc->programs[i] = NO_SAMPLE; - devc->wave[i] = NULL; - } + { + devc->programs[i] = NO_SAMPLE; + devc->wave[i] = NULL; + } devc->maxvoice = DEFAULT_VOICES; @@ -1516,15 +1482,12 @@ probe_softsyn(struct address_info *hw_config) #else devc->default_max_voices = 32; #endif - softsynth_loaded = 1; return 1; } -void -attach_softsyn_card(struct address_info *hw_config) +void attach_softsyn_card(struct address_info *hw_config) { - voice_alloc = &softsyn_operations.alloc; synth_devs[devc->synthdev = num_synths++] = &softsyn_operations; sequencer_init(); @@ -1536,14 +1499,10 @@ attach_softsyn_card(struct address_info *hw_config) #endif } -void -unload_softsyn(struct address_info *hw_config) +void unload_softsyn(struct address_info *hw_config) { if (!softsynth_loaded) return; -#ifndef POLLED_MODE -#endif - softsynthp = NULL; softsynth_loaded = 0; reset_samples(devc); @@ -1553,10 +1512,9 @@ unload_softsyn(struct address_info *hw_config) static struct address_info config; -int -init_module(void) +int init_module(void) { - printk("SoftOSS driver Copyright (C) by Hannu Savolainen 1993-1997\n"); + printk(KERN_INFO "SoftOSS driver Copyright (C) by Hannu Savolainen 1993-1997\n"); if (!probe_softsyn(&config)) return -ENODEV; attach_softsyn_card(&config); @@ -1564,8 +1522,7 @@ init_module(void) return 0; } -void -cleanup_module(void) +void cleanup_module(void) { unload_softsyn(&config); sound_unload_synthdev(devc->synthdev); diff --git a/drivers/sound/softoss_rs.c b/drivers/sound/softoss_rs.c index f8dac8ed5..17ebb8b59 100644 --- a/drivers/sound/softoss_rs.c +++ b/drivers/sound/softoss_rs.c @@ -5,8 +5,8 @@ * Software based MIDI synthsesizer driver, the actual mixing loop. * Keep the loop as simple as possible to make it easier to rewrite this * routine in assembly. - */ -/* + * + * * Copyright (C) by Hannu Savolainen 1993-1997 * * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) @@ -21,10 +21,9 @@ #if defined(CONFIG_SOFTOSS) || defined(MODULE) #include "softoss.h" -void -softsynth_resample_loop(short *buf, int loops) +void softsynth_resample_loop(short *buf, int loops) { - int iloop, voice; + int iloop, voice; volatile voice_info *v; #ifdef OSS_BIG_ENDIAN @@ -33,104 +32,102 @@ softsynth_resample_loop(short *buf, int loops) #endif for (iloop = 0; iloop < loops; iloop++) - { /* Mix one sample */ - - int accum, left = 0, right = 0; - int ix, position; - - for (voice = 0; voice < devc->maxvoice; voice++) - if (voice_active[voice]) - { /* Compute voice */ - - v = &softoss_voices[voice]; + { /* Mix one sample */ + int accum, left = 0, right = 0; + int ix, position; + + for (voice = 0; voice < devc->maxvoice; voice++) + { + if (voice_active[voice]) + { /* Compute voice */ + v = &softoss_voices[voice]; #ifdef SOFTOSS_TEST - ix = iloop << 3; - position = v->ptr; + ix = iloop << 3; + position = v->ptr; #else - ix = (position = v->ptr) >> 9; + ix = (position = v->ptr) >> 9; #endif - /* Interpolation (resolution of 512 steps) */ - { - int fract = v->ptr & 0x1f; /* 9 bits */ - - /* This method works with less arithmetic operations */ - register int v1 = v->wave[ix]; - - accum = v1 + ((((v->wave[ix + 1] - v1)) * (fract)) >> 9); - } - - left += (accum * v->leftvol); - right += (accum * v->rightvol); - - /* Update sample pointer */ - - position += v->step; - if (position <= v->endloop) - v->ptr = position; - else if (v->mode & WAVE_LOOPING) - { - if (v->mode & WAVE_BIDIR_LOOP) - { - v->mode ^= WAVE_LOOP_BACK; /* Turn around */ - v->step *= -1; - } else - { - position -= v->looplen; - v->ptr = position; - } - } - /* else leave the voice looping the current sample */ - - if (v->mode & WAVE_LOOP_BACK && position < v->startloop) - { - if (v->mode & WAVE_BIDIR_LOOP) - { - v->mode ^= WAVE_LOOP_BACK; /* Turn around */ - v->step *= -1; - } else - { - position += v->looplen; - v->ptr = position; - } - } - } /* Compute voice */ + /* Interpolation (resolution of 512 steps) */ + { + int fract = v->ptr & 0x1f; /* 9 bits */ + + /* This method works with less arithmetic operations */ + register int v1 = v->wave[ix]; + accum = v1 + ((((v->wave[ix + 1] - v1)) * (fract)) >> 9); + } + + left += (accum * v->leftvol); + right += (accum * v->rightvol); + + /* Update sample pointer */ + position += v->step; + if (position <= v->endloop) + v->ptr = position; + else if (v->mode & WAVE_LOOPING) + { + if (v->mode & WAVE_BIDIR_LOOP) + { v->mode ^= WAVE_LOOP_BACK; /* Turn around */ + v->step *= -1; + } + else + { + position -= v->looplen; + v->ptr = position; + } + } + /* else leave the voice looping the current sample */ + + if (v->mode & WAVE_LOOP_BACK && position < v->startloop) + { + if (v->mode & WAVE_BIDIR_LOOP) + { v->mode ^= WAVE_LOOP_BACK; /* Turn around */ + v->step *= -1; + } + else + { + position += v->looplen; + v->ptr = position; + } + } + } /* Compute voice */ + } #if 1 /* Delay */ - left += left_delay[delayp]; - right += right_delay[delayp]; + left += left_delay[delayp]; + right += right_delay[delayp]; - left_delay[delayp] = right >> 2; - right_delay[delayp] = left >> 2; - delayp = (delayp + 1) % devc->delay_size; + left_delay[delayp] = right >> 2; + right_delay[delayp] = left >> 2; + delayp = (delayp + 1) % devc->delay_size; #endif #define AFTERSCALE devc->afterscale; - left >>= AFTERSCALE; - right >>= AFTERSCALE; + left >>= AFTERSCALE; + right >>= AFTERSCALE; - if (left > 32767) - left = 32767; - if (left < -32768) - left = -32768; - if (right > 32767) - right = 32767; - if (right < -32768) - right = -32768; + if (left > 32767) + left = 32767; + if (left < -32768) + left = -32768; + if (right > 32767) + right = 32767; + if (right < -32768) + right = -32768; #ifdef OSS_BIG_ENDIAN - *cbuf++ = left & 0xff; - *cbuf++ = (left >> 8) & 0xff; - *cbuf++ = right & 0xff; - *cbuf++ = (right >> 8) & 0xff; + *cbuf++ = left & 0xff; + *cbuf++ = (left >> 8) & 0xff; + *cbuf++ = right & 0xff; + *cbuf++ = (right >> 8) & 0xff; #else - *buf++ = left; - *buf++ = right; + *buf++ = left; + *buf++ = right; #endif - if (devc->control_counter++ >= devc->control_rate) - { - devc->control_counter = 0; - softsyn_control_loop(); - } - } /* Mix one sample */ + if (devc->control_counter++ >= devc->control_rate) + { + devc->control_counter = 0; + softsyn_control_loop(); + } + } /* Mix one sample */ } #endif diff --git a/drivers/sound/sound_calls.h b/drivers/sound/sound_calls.h index 416737f65..2a95950e5 100644 --- a/drivers/sound/sound_calls.h +++ b/drivers/sound/sound_calls.h @@ -11,6 +11,7 @@ int DMAbuf_start_output(int dev, int buff_no, int l); int DMAbuf_move_wrpointer(int dev, int l); /* int DMAbuf_ioctl(int dev, unsigned int cmd, caddr_t arg, int local); */ void DMAbuf_init(int dev, int dma1, int dma2); +void DMAbuf_deinit(int dev); int DMAbuf_start_dma (int dev, unsigned long physaddr, int count, int dma_mode); int DMAbuf_open_dma (int dev); void DMAbuf_close_dma (int dev); @@ -83,15 +84,8 @@ void MIDIbuf_init(void); /* From soundcard.c */ void request_sound_timer (int count); void sound_stop_timer(void); -/* These two are about to die.. */ -int snd_set_irq_handler (int interrupt_level, void(*iproc)(int, void*, struct pt_regs *), char *name, int *osp, void *dev_id); -void snd_release_irq(int vect, void *ptr); -void sound_dma_malloc(int dev); -void sound_dma_free(int dev); void conf_printf(char *name, struct address_info *hw_config); void conf_printf2(char *name, int base, int irq, int dma, int dma2); -int ioctl_in(caddr_t arg); -int ioctl_out(caddr_t arg, int result); /* From opl3.c */ int opl3_detect (int ioaddr, int *osp); @@ -187,7 +181,7 @@ 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 */ -void ad1848_control(int cmd, int arg); +int ad1848_control(int cmd, int arg); #define AD1848_SET_XTAL 1 #define AD1848_MIXER_REROUTE 2 #define AD1848_REROUTE(oldctl, newctl) \ @@ -196,9 +190,6 @@ void 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 attach_pnp_ad1848(struct address_info * hw_config); -int probe_pnp_ad1848(struct address_info *hw_config); -void unload_pnp_ad1848(struct address_info *hw_info); /* From pss.c */ int probe_pss (struct address_info *hw_config); @@ -235,7 +226,6 @@ 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); -int mad16_sb_dsp_detect (struct address_info *hw_config); /* Unload routines from various source files*/ void unload_pss(struct address_info *hw_info); @@ -278,3 +268,7 @@ 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); diff --git a/drivers/sound/sound_firmware.c b/drivers/sound/sound_firmware.c index cc566e497..97ce9d657 100644 --- a/drivers/sound/sound_firmware.c +++ b/drivers/sound/sound_firmware.c @@ -1,3 +1,4 @@ +#include "os.h" #define __KERNEL_SYSCALLS__ #include <linux/fs.h> #include <linux/mm.h> @@ -19,14 +20,14 @@ static int do_mod_firmware_load(const char *fn, char **fp) return 0; } l = lseek(fd, 0L, 2); - if (l <= 0 || l > 65535) + if (l <= 0 || l > 131072) { printk(KERN_INFO "Invalid firmware '%s'\n", fn); sys_close(fd); - return 0; + return 0; } lseek(fd, 0L, 0); - dp = kmalloc(l, GFP_KERNEL); + dp = vmalloc(l); if (dp == NULL) { printk(KERN_INFO "Out of memory loading '%s'.\n", fn); @@ -36,7 +37,7 @@ static int do_mod_firmware_load(const char *fn, char **fp) if (read(fd, dp, l) != l) { printk(KERN_INFO "Failed to read '%s'.\n", fn); - kfree(dp); + vfree(dp); sys_close(fd); return 0; } @@ -45,7 +46,7 @@ static int do_mod_firmware_load(const char *fn, char **fp) return (int) l; } -int mod_firmware_load(const char *fn, char **fp) +int mod_firmware_load(const char *fn, char **fp) { int r; mm_segment_t fs = get_fs(); @@ -55,3 +56,4 @@ int mod_firmware_load(const char *fn, char **fp) set_fs(fs); return r; } + diff --git a/drivers/sound/sound_syms.c b/drivers/sound/sound_syms.c index 648a769a4..2758660d5 100644 --- a/drivers/sound/sound_syms.c +++ b/drivers/sound/sound_syms.c @@ -1,6 +1,6 @@ /* - * The sound core exports the following symbols to the rest of - * modulespace. + * The sound core exports the following symbols to the rest of + * modulespace. * * (C) Copyright 1997 Alan Cox, Licensed under the GNU GPL */ @@ -9,6 +9,8 @@ #include "sound_config.h" #define _MIDI_SYNTH_C_ #include "midi_synth.h" +#define _SEQUENCER_C_ +#include "tuning.h" #include <linux/notifier.h> #include "sound_firmware.h" @@ -31,16 +33,13 @@ EXPORT_SYMBOL(sound_install_audiodrv); EXPORT_SYMBOL(sound_install_mixer); EXPORT_SYMBOL(sound_alloc_dma); EXPORT_SYMBOL(sound_free_dma); -EXPORT_SYMBOL(snd_set_irq_handler); -EXPORT_SYMBOL(snd_release_irq); +EXPORT_SYMBOL(sound_open_dma); +EXPORT_SYMBOL(sound_close_dma); EXPORT_SYMBOL(sound_alloc_audiodev); EXPORT_SYMBOL(sound_alloc_mididev); EXPORT_SYMBOL(sound_alloc_mixerdev); EXPORT_SYMBOL(sound_alloc_timerdev); EXPORT_SYMBOL(sound_alloc_synthdev); -EXPORT_SYMBOL(sound_mem_blocks); -EXPORT_SYMBOL(sound_mem_sizes); -EXPORT_SYMBOL(sound_nblocks); EXPORT_SYMBOL(sound_unload_audiodev); EXPORT_SYMBOL(sound_unload_mididev); EXPORT_SYMBOL(sound_unload_mixerdev); @@ -90,3 +89,14 @@ EXPORT_SYMBOL(midi_synth_send_sysex); EXPORT_SYMBOL(midi_synth_bender); EXPORT_SYMBOL(midi_synth_load_patch); +/* Firmware */ + +EXPORT_SYMBOL(mod_firmware_load); + +/* Tuning */ + +EXPORT_SYMBOL(cent_tuning); +EXPORT_SYMBOL(semitone_tuning); + +MODULE_DESCRIPTION("Sound subsystem"); +MODULE_AUTHOR("Hannu Savolainen, et al."); diff --git a/drivers/sound/soundcard.c b/drivers/sound/soundcard.c index fe3622a73..42ea158cc 100644 --- a/drivers/sound/soundcard.c +++ b/drivers/sound/soundcard.c @@ -16,8 +16,8 @@ * Stefan Reinauer : integrated /proc/sound (equals to /dev/sndstat, * which should disappear in the near future) */ -#include <linux/config.h> +#include <linux/config.h> #include "sound_config.h" #include <linux/types.h> @@ -28,6 +28,7 @@ #include <linux/stddef.h> #include <linux/kmod.h> #ifdef __KERNEL__ +#include <asm/dma.h> #include <asm/io.h> #include <asm/segment.h> #include <linux/wait.h> @@ -48,6 +49,13 @@ #define modular 0 #endif +/* + * This ought to be moved into include/asm/dma.h + */ +#ifndef valid_dma +#define valid_dma(n) ((n) >= 0 && (n) < MAX_DMA_CHANNELS && (n) != 4) +#endif + static int chrdev_registered = 0; static int sound_major = SOUND_MAJOR; @@ -57,12 +65,11 @@ static int is_unloading = 0; * Table for permanently allocated memory (used when unloading the module) */ caddr_t sound_mem_blocks[1024]; -int sound_mem_sizes[1024]; int sound_nblocks = 0; static int soundcard_configured = 0; -static char dma_alloc_map[8] = +static char dma_alloc_map[MAX_DMA_CHANNELS] = {0}; #define DMA_MAP_UNAVAIL 0 @@ -788,31 +795,9 @@ soundcard_init(void) } -static unsigned int irqs = 0; - -#ifdef MODULE -static void -free_all_irqs(void) -{ - int i; - - for (i = 0; i < 31; i++) - { - if (irqs & (1ul << i)) - { - printk(KERN_WARNING "Sound warning: IRQ%d was left allocated - fixed.\n", i); - snd_release_irq(i, NULL); - } - } - irqs = 0; -} - -char kernel_version[] = UTS_RELEASE; - -#endif - -static int sound[20] = -{0}; +static int sound[20] = { + 0 +}; int init_module(void) { @@ -876,10 +861,9 @@ void cleanup_module(void) } #endif sound_unload_drivers(); - free_all_irqs(); /* If something was left allocated by accident */ sequencer_unload(); - for (i = 0; i < 8; i++) + for (i = 0; i < MAX_DMA_CHANNELS; i++) { if (dma_alloc_map[i] != DMA_MAP_UNAVAIL) { @@ -895,35 +879,6 @@ void cleanup_module(void) } #endif -int snd_set_irq_handler(int interrupt_level, void (*iproc) (int, void *, struct pt_regs *), char *name, int *osp, void *dev_id) -{ - int retcode; - unsigned long flags; - - save_flags(flags); - cli(); - retcode = request_irq(interrupt_level, iproc, 0, name, dev_id); - - if (retcode < 0) - { - printk(KERN_ERR "Sound: IRQ%d already in use\n", interrupt_level); - } - else - irqs |= (1ul << interrupt_level); - - restore_flags(flags); - return retcode; -} - -void snd_release_irq(int vect, void *dev_id) -{ - if (!(irqs & (1ul << vect))) - return; - - irqs &= ~(1ul << vect); - free_irq(vect, dev_id); -} - int sound_alloc_dma(int chn, char *deviceID) { int err; @@ -940,7 +895,7 @@ int sound_open_dma(int chn, char *deviceID) { unsigned long flags; - if (chn < 0 || chn > 7 || chn == 4) + if (!valid_dma(chn)) { printk(KERN_ERR "sound_open_dma: Invalid DMA channel %d\n", chn); return 1; diff --git a/drivers/sound/trix.c b/drivers/sound/trix.c index 9b34c4422..1c5820fcd 100644 --- a/drivers/sound/trix.c +++ b/drivers/sound/trix.c @@ -3,14 +3,18 @@ * * Low level driver for the MediaTrix AudioTrix Pro * (MT-0002-PC Control Chip) - */ -/* + * + * * 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. + * + * Changes + * Alan Cox Modularisation, cleanup. */ + #include <linux/config.h> #include <linux/module.h> @@ -35,30 +39,27 @@ static int trix_boot_len = 0; #endif -static int kilroy_was_here = 0; /* Don't detect twice */ -static int sb_initialized = 0; -static int mpu_initialized = 0; +static int kilroy_was_here = 0; /* Don't detect twice */ +static int sb_initialized = 0; +static int mpu_initialized = 0; -static int *trix_osp = NULL; +static int *trix_osp = NULL; -static unsigned char -trix_read(int addr) +static unsigned char trix_read(int addr) { outb(((unsigned char) addr), 0x390); /* MT-0002-PC ASIC address */ return inb(0x391); /* MT-0002-PC ASIC data */ } -static void -trix_write(int addr, int data) +static void trix_write(int addr, int data) { outb(((unsigned char) addr), 0x390); /* MT-0002-PC ASIC address */ outb(((unsigned char) data), 0x391); /* MT-0002-PC ASIC data */ } -static void -download_boot(int base) +static void download_boot(int base) { - int i = 0, n = trix_boot_len; + int i = 0, n = trix_boot_len; if (trix_boot_len == 0) return; @@ -83,24 +84,23 @@ download_boot(int base) } -static int -trix_set_wss_port(struct address_info *hw_config) +static int trix_set_wss_port(struct address_info *hw_config) { unsigned char addr_bits; if (check_region(0x390, 2)) - { - printk(KERN_ERR "AudioTrix: Config port I/O conflict\n"); - return 0; - } + { + printk(KERN_ERR "AudioTrix: Config port I/O conflict\n"); + return 0; + } if (kilroy_was_here) /* Already initialized */ return 0; if (trix_read(0x15) != 0x71) /* No ASIC signature */ - { - MDB(printk("No AudioTrix ASIC signature found\n")); - return 0; - } + { + MDB(printk(KERN_ERR "No AudioTrix ASIC signature found\n")); + return 0; + } kilroy_was_here = 1; /* @@ -111,26 +111,26 @@ trix_set_wss_port(struct address_info *hw_config) trix_write(0x14, 0); /* - * Configure the ASIC to place the codec to the proper I/O location + * Configure the ASIC to place the codec to the proper I/O location */ switch (hw_config->io_base) - { - case 0x530: - addr_bits = 0; - break; - case 0x604: - addr_bits = 1; - break; - case 0xE80: - addr_bits = 2; - break; - case 0xF40: - addr_bits = 3; - break; - default: - return 0; - } + { + case 0x530: + addr_bits = 0; + break; + case 0x604: + addr_bits = 1; + break; + case 0xE80: + addr_bits = 2; + break; + case 0xF40: + addr_bits = 3; + break; + default: + return 0; + } trix_write(0x19, (trix_read(0x19) & 0x03) | addr_bits); return 1; @@ -141,120 +141,123 @@ trix_set_wss_port(struct address_info *hw_config) * AudioTrix Pro */ -int -probe_trix_wss(struct address_info *hw_config) +int probe_trix_wss(struct address_info *hw_config) { - int ret; + int ret; /* - * Check if the IO port returns valid signature. The original MS Sound - * system returns 0x04 while some cards (AudioTrix Pro for example) - * return 0x00. + * Check if the IO port returns valid signature. The original MS Sound + * system returns 0x04 while some cards (AudioTrix Pro for example) + * return 0x00. */ if (check_region(hw_config->io_base, 8)) - { - printk("AudioTrix: MSS I/O port conflict (%x)\n", hw_config->io_base); - return 0; - } + { + printk(KERN_ERR "AudioTrix: MSS I/O port conflict (%x)\n", hw_config->io_base); + return 0; + } trix_osp = hw_config->osp; if (!trix_set_wss_port(hw_config)) return 0; if ((inb(hw_config->io_base + 3) & 0x3f) != 0x00) - { - MDB(printk("No MSS signature detected on port 0x%x\n", hw_config->io_base)); - return 0; - } + { + MDB(printk(KERN_ERR "No MSS signature detected on port 0x%x\n", hw_config->io_base)); + return 0; + } if (hw_config->irq > 11) - { - printk("AudioTrix: Bad WSS IRQ %d\n", hw_config->irq); - return 0; - } + { + printk(KERN_ERR "AudioTrix: Bad WSS IRQ %d\n", hw_config->irq); + return 0; + } if (hw_config->dma != 0 && hw_config->dma != 1 && hw_config->dma != 3) - { - printk("AudioTrix: Bad WSS DMA %d\n", hw_config->dma); - return 0; - } + { + printk(KERN_ERR "AudioTrix: Bad WSS DMA %d\n", hw_config->dma); + return 0; + } if (hw_config->dma2 != -1 && hw_config->dma2 != hw_config->dma) if (hw_config->dma2 != 0 && hw_config->dma2 != 1 && hw_config->dma2 != 3) - { - printk("AudioTrix: Bad capture DMA %d\n", hw_config->dma2); + { + printk(KERN_ERR "AudioTrix: Bad capture DMA %d\n", hw_config->dma2); return 0; - } + } /* - * Check that DMA0 is not in use with a 8 bit board. + * Check that DMA0 is not in use with a 8 bit board. */ if (hw_config->dma == 0 && inb(hw_config->io_base + 3) & 0x80) - { - printk("AudioTrix: Can't use DMA0 with a 8 bit card slot\n"); - return 0; - } + { + printk(KERN_ERR "AudioTrix: Can't use DMA0 with a 8 bit card slot\n"); + return 0; + } if (hw_config->irq > 7 && hw_config->irq != 9 && inb(hw_config->io_base + 3) & 0x80) - { - printk("AudioTrix: Can't use IRQ%d with a 8 bit card slot\n", hw_config->irq); - return 0; - } + { + printk(KERN_ERR "AudioTrix: Can't use IRQ%d with a 8 bit card slot\n", hw_config->irq); + return 0; + } ret = ad1848_detect(hw_config->io_base + 4, NULL, hw_config->osp); if (ret) - { + { #ifdef TRIX_ENABLE_JOYSTICK - trix_write(0x15, 0x80); + trix_write(0x15, 0x80); #endif - request_region(0x390, 2, "AudioTrix"); - } + request_region(0x390, 2, "AudioTrix"); + } return ret; } void 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}; - char bits; + static unsigned char interrupt_bits[12] = { + 0, 0, 0, 0, 0, 0, 0, 0x08, 0, 0x10, 0x18, 0x20 + }; + char bits; - static unsigned char dma_bits[4] = - {1, 2, 0, 3}; + static unsigned char dma_bits[4] = { + 1, 2, 0, 3 + }; - int config_port = hw_config->io_base + 0; - int dma1 = hw_config->dma, dma2 = hw_config->dma2; - int old_num_mixers = num_mixers; + int config_port = hw_config->io_base + 0; + int dma1 = hw_config->dma, dma2 = hw_config->dma2; + int old_num_mixers = num_mixers; trix_osp = hw_config->osp; if (!kilroy_was_here) - { - DDB(printk("AudioTrix: Attach called but not probed yet???\n")); - return; - } + { + DDB(printk("AudioTrix: Attach called but not probed yet???\n")); + return; + } + /* - * Set the IRQ and DMA addresses. + * Set the IRQ and DMA addresses. */ bits = interrupt_bits[hw_config->irq]; if (bits == 0) - { - printk("AudioTrix: Bad IRQ (%d)\n", hw_config->irq); - return; - } + { + printk("AudioTrix: Bad IRQ (%d)\n", hw_config->irq); + return; + } outb((bits | 0x40), config_port); if (hw_config->dma2 == -1 || hw_config->dma2 == hw_config->dma) - { + { bits |= dma_bits[dma1]; dma2 = dma1; - } else - { - unsigned char tmp; + } + else + { + unsigned char tmp; - tmp = trix_read(0x13) & ~30; - trix_write(0x13, tmp | 0x80 | (dma1 << 4)); + tmp = trix_read(0x13) & ~30; + trix_write(0x13, tmp | 0x80 | (dma1 << 4)); - tmp = trix_read(0x14) & ~30; - trix_write(0x14, tmp | 0x80 | (dma2 << 4)); - } + tmp = trix_read(0x14) & ~30; + trix_write(0x14, tmp | 0x80 | (dma2 << 4)); + } outb((bits), config_port); /* Write IRQ+DMA setup */ @@ -267,22 +270,22 @@ attach_trix_wss(struct address_info *hw_config) request_region(hw_config->io_base, 4, "MSS config"); if (num_mixers > old_num_mixers) /* Mixer got installed */ - { - AD1848_REROUTE(SOUND_MIXER_LINE1, SOUND_MIXER_LINE); /* Line in */ - AD1848_REROUTE(SOUND_MIXER_LINE2, SOUND_MIXER_CD); - AD1848_REROUTE(SOUND_MIXER_LINE3, SOUND_MIXER_SYNTH); /* OPL4 */ - AD1848_REROUTE(SOUND_MIXER_SPEAKER, SOUND_MIXER_ALTPCM); /* SB */ - } + { + AD1848_REROUTE(SOUND_MIXER_LINE1, SOUND_MIXER_LINE); /* Line in */ + AD1848_REROUTE(SOUND_MIXER_LINE2, SOUND_MIXER_CD); + AD1848_REROUTE(SOUND_MIXER_LINE3, SOUND_MIXER_SYNTH); /* OPL4 */ + AD1848_REROUTE(SOUND_MIXER_SPEAKER, SOUND_MIXER_ALTPCM); /* SB */ + } } -int -probe_trix_sb(struct address_info *hw_config) +int probe_trix_sb(struct address_info *hw_config) { - int tmp; - unsigned char conf; - static char irq_translate[] = - {-1, -1, -1, 0, 1, 2, -1, 3}; + int tmp; + unsigned char conf; + static char irq_translate[] = { + -1, -1, -1, 0, 1, 2, -1, 3 + }; if (trix_boot_len == 0) return 0; /* No boot code -> no fun */ @@ -294,10 +297,10 @@ probe_trix_sb(struct address_info *hw_config) return 0; if (check_region(hw_config->io_base, 16)) - { - printk("AudioTrix: SB I/O port conflict (%x)\n", hw_config->io_base); - return 0; - } + { + printk(KERN_ERR "AudioTrix: SB I/O port conflict (%x)\n", hw_config->io_base); + return 0; + } if ((hw_config->io_base & 0xffffff8f) != 0x200) return 0; @@ -329,11 +332,10 @@ probe_trix_sb(struct address_info *hw_config) #endif } -void -attach_trix_sb(struct address_info *hw_config) +void attach_trix_sb(struct address_info *hw_config) { - extern int sb_be_quiet; - int old_quiet; + extern int sb_be_quiet; + int old_quiet; #ifdef CONFIG_SBDSP hw_config->driver_use_1 = SB_NO_MIDI | SB_NO_MIXER | SB_NO_RECORDING; @@ -348,8 +350,7 @@ attach_trix_sb(struct address_info *hw_config) #endif } -void -attach_trix_mpu(struct address_info *hw_config) +void attach_trix_mpu(struct address_info *hw_config) { #if defined(CONFIG_UART401) && defined(CONFIG_MIDI) hw_config->name = "AudioTrix Pro"; @@ -357,78 +358,74 @@ attach_trix_mpu(struct address_info *hw_config) #endif } -int -probe_trix_mpu(struct address_info *hw_config) +int probe_trix_mpu(struct address_info *hw_config) { #ifdef DO_MIDI - unsigned char conf; - static char irq_bits[] = - {-1, -1, -1, 1, 2, 3, -1, 4, -1, 5}; + unsigned char conf; + static char irq_bits[] = { + -1, -1, -1, 1, 2, 3, -1, 4, -1, 5 + }; if (!kilroy_was_here) - { - DDB(printk("Trix: WSS and SB modes must be initialized before MPU\n")); - return 0; /* AudioTrix Pro has not been detected earlier */ - } + { + DDB(printk("Trix: WSS and SB modes must be initialized before MPU\n")); + return 0; /* AudioTrix Pro has not been detected earlier */ + } if (!sb_initialized) - { - DDB(printk("Trix: SB mode must be initialized before MPU\n")); - return 0; - } + { + DDB(printk("Trix: SB mode must be initialized before MPU\n")); + return 0; + } if (mpu_initialized) - { - DDB(printk("Trix: MPU mode already initialized\n")); - return 0; - } + { + DDB(printk("Trix: MPU mode already initialized\n")); + return 0; + } if (check_region(hw_config->io_base, 4)) - { - printk("AudioTrix: MPU I/O port conflict (%x)\n", hw_config->io_base); - return 0; - } + { + printk(KERN_ERR "AudioTrix: MPU I/O port conflict (%x)\n", hw_config->io_base); + return 0; + } if (hw_config->irq > 9) - { - printk("AudioTrix: Bad MPU IRQ %d\n", hw_config->irq); - return 0; - } + { + printk(KERN_ERR "AudioTrix: Bad MPU IRQ %d\n", hw_config->irq); + return 0; + } if (irq_bits[hw_config->irq] == -1) - { - printk("AudioTrix: Bad MPU IRQ %d\n", hw_config->irq); - return 0; - } + { + printk(KERN_ERR "AudioTrix: Bad MPU IRQ %d\n", hw_config->irq); + return 0; + } switch (hw_config->io_base) - { - case 0x330: - conf = 0x00; - break; - case 0x370: - conf = 0x04; - break; - case 0x3b0: - conf = 0x08; - break; - case 0x3f0: - conf = 0x0c; - break; - default: - return 0; /* Invalid port */ - } + { + case 0x330: + conf = 0x00; + break; + case 0x370: + conf = 0x04; + break; + case 0x3b0: + conf = 0x08; + break; + case 0x3f0: + conf = 0x0c; + break; + default: + return 0; /* Invalid port */ + } conf |= irq_bits[hw_config->irq] << 4; - trix_write(0x19, (trix_read(0x19) & 0x83) | conf); - mpu_initialized = 1; - return probe_uart401(hw_config); #else return 0; #endif } -void -unload_trix_wss(struct address_info *hw_config) +void unload_trix_wss(struct address_info *hw_config) { - int dma2 = hw_config->dma2; + int dma2 = hw_config->dma2; if (dma2 == -1) dma2 = hw_config->dma; @@ -444,15 +441,14 @@ unload_trix_wss(struct address_info *hw_config) sound_unload_audiodev(hw_config->slots[0]); } -void -unload_trix_mpu(struct address_info *hw_config) +void unload_trix_mpu(struct address_info *hw_config) { #ifdef DO_MIDI unload_uart401(hw_config); #endif } -void -unload_trix_sb(struct address_info *hw_config) + +void unload_trix_sb(struct address_info *hw_config) { #ifdef CONFIG_SBDSP sb_dsp_unload(hw_config); @@ -473,6 +469,18 @@ int sb_irq = -1; int mpu_io = -1; int mpu_irq = -1; +EXPORT_NO_SYMBOLS; + +MODULE_PARM(io,"i"); +MODULE_PARM(irq,"i"); +MODULE_PARM(dma,"i"); +MODULE_PARM(dma2,"i"); +MODULE_PARM(sb_io,"i"); +MODULE_PARM(sb_dma,"i"); +MODULE_PARM(sb_irq,"i"); +MODULE_PARM(mpu_io,"i"); +MODULE_PARM(mpu_irq,"i"); + struct address_info config; struct address_info sb_config; struct address_info mpu_config; @@ -482,16 +490,15 @@ static int sb = 0; static int fw_load; -int -init_module(void) +int init_module(void) { - printk("MediaTrix audio driver Copyright (C) by Hannu Savolainen 1993-1996\n"); + printk(KERN_INFO "MediaTrix audio 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; - } + { + printk(KERN_INFO "I/O, IRQ, DMA and type are mandatory\n"); + return -EINVAL; + } config.io_base = io; config.irq = irq; config.dma = dma; @@ -505,21 +512,21 @@ init_module(void) mpu_config.irq = mpu_irq; if (sb_io != -1 && (sb_irq == -1 || sb_dma == -1)) - { - printk(KERN_INFO "CONFIG_SB_IRQ and CONFIG_SB_DMA must be specified if SB_IO is set.\n"); - return -EINVAL; - } + { + 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) - { - printk(KERN_INFO "CONFIG_MPU_IRQ must be specified if MPU_IO is set.\n"); - return -EINVAL; - } + { + printk(KERN_INFO "CONFIG_MPU_IRQ must be specified if MPU_IO is set.\n"); + return -EINVAL; + } if (!trix_boot) - { - fw_load = 1; - trix_boot_len = mod_firmware_load("/etc/sound/trxpro.bin", + { + fw_load = 1; + trix_boot_len = mod_firmware_load("/etc/sound/trxpro.bin", (char **) &trix_boot); - } + } if (!probe_trix_wss(&config)) return -ENODEV; attach_trix_wss(&config); @@ -530,26 +537,26 @@ init_module(void) */ if (sb_io != -1) - { - sb = probe_trix_sb(&sb_config); - if (sb) - attach_trix_sb(&sb_config); - } + { + sb = probe_trix_sb(&sb_config); + if (sb) + attach_trix_sb(&sb_config); + } + if (mpu_io != -1) - { - mpu = probe_trix_mpu(&mpu_config); - if (mpu) - attach_trix_mpu(&mpu_config); - } + { + mpu = probe_trix_mpu(&mpu_config); + if (mpu) + attach_trix_mpu(&mpu_config); + } SOUND_LOCK; return 0; } -void -cleanup_module(void) +void cleanup_module(void) { if (fw_load && trix_boot) - kfree(trix_boot); + vfree(trix_boot); if (sb) unload_trix_sb(&sb_config); if (mpu) diff --git a/drivers/sound/uart401.c b/drivers/sound/uart401.c index 2e7ed2a27..4d8857e56 100644 --- a/drivers/sound/uart401.c +++ b/drivers/sound/uart401.c @@ -12,7 +12,8 @@ * * Changes: * Alan Cox Reformatted, removed sound_mem usage, use normal Linux - * interrupt allocation. + * interrupt allocation. Protect against bogus unload + * Fixed to allow IRQ > 15 * * Status: * Untested @@ -244,6 +245,7 @@ void attach_uart401(struct address_info *hw_config) uart401_devc *devc; char *name = "MPU-401 (UART) MIDI"; + if (hw_config->name) name = hw_config->name; @@ -269,12 +271,6 @@ void attach_uart401(struct address_info *hw_config) else devc->share_irq = 0; - if (devc->irq < 1 || devc->irq > 15) - { - kfree(devc); - return; - } - if (!devc->share_irq) { if (request_irq(devc->irq, uart401intr, 0, "MPU-401 UART", devc) < 0) @@ -345,6 +341,7 @@ static int reset_uart401(uart401_devc * devc) for (timeout = 30000; timeout > 0 && !output_ready(devc); timeout--); devc->input_byte = 0; uart401_cmd(devc, MPU_RESET); + /* * Wait at least 25 msec. This method is not accurate so let's make the * loop bit longer. Cannot sleep since this is called during boot. @@ -387,6 +384,8 @@ int probe_uart401(struct address_info *hw_config) DDB(printk("Entered probe_uart401()\n")); + /* Default to "not found" */ + hw_config->slots[4] = -1; detected_devc = NULL; if (check_region(hw_config->io_base, 4)) @@ -415,6 +414,14 @@ int probe_uart401(struct address_info *hw_config) void unload_uart401(struct address_info *hw_config) { uart401_devc *devc; + int n=hw_config->slots[4]; + + /* Not set up */ + if(n==-1 || midi_devs[n]==NULL) + return; + + /* Not allocated (erm ??) */ + devc = midi_devs[hw_config->slots[4]]->devc; if (devc == NULL) return; diff --git a/drivers/sound/uart6850.c b/drivers/sound/uart6850.c index b26e75a89..75b02ff94 100644 --- a/drivers/sound/uart6850.c +++ b/drivers/sound/uart6850.c @@ -325,6 +325,8 @@ int irq = -1; MODULE_PARM(io,"i"); MODULE_PARM(irq,"i"); +EXPORT_NO_SYMBOLS; + struct address_info cfg; int init_module(void) diff --git a/drivers/sound/vidc.c b/drivers/sound/vidc.c new file mode 100644 index 000000000..c33ed9beb --- /dev/null +++ b/drivers/sound/vidc.c @@ -0,0 +1,81 @@ +/* + * drivers/sound/vidc.c + * + * Detection routine for the VIDC. + * + * Copyright (C) 1997 by Russell King <rmk@arm.uk.linux.org> + */ + +#include <asm/io.h> +#include <asm/dma.h> +#include "sound_config.h" +#include "vidc.h" + +int vidc_busy; + +void vidc_update_filler(int bits, int channels) +{ + int filltype; + + filltype = bits + channels; + switch (filltype) + { + default: + case 9: + vidc_filler = vidc_fill_1x8; + break; + case 10: + vidc_filler = vidc_fill_2x8; + break; + case 17: + vidc_filler = vidc_fill_1x16; + break; + case 18: + vidc_filler = vidc_fill_2x16; + break; + } +} + +void attach_vidc(struct address_info *hw_config) +{ + char name[32]; + int i; + + sprintf(name, "VIDC %d-bit sound", hw_config->card_subtype); + conf_printf(name, hw_config); + + for (i = 0; i < 2; i++) + { + dma_buf[i] = get_free_page(GFP_KERNEL); + dma_pbuf[i] = virt_to_phys(dma_buf[i]); + } + + if (sound_alloc_dma(hw_config->dma, "VIDCsound")) + { + printk(KERN_ERR "VIDCsound: can't allocate virtual DMA channel\n"); + return; + } + if (request_irq(hw_config->irq, vidc_sound_dma_irq, 0, "VIDCsound", NULL)) + { + printk(KERN_ERR "VIDCsound: can't allocate DMA interrupt\n"); + return; + } + vidc_synth_init(hw_config); + vidc_audio_init(hw_config); + vidc_mixer_init(hw_config); +} + +int probe_vidc(struct address_info *hw_config) +{ + hw_config->irq = IRQ_DMAS0; + hw_config->dma = DMA_VIRTUAL_SOUND; + hw_config->dma2 = -1; + hw_config->card_subtype = 16; + return 1; +} + +void unload_vidc(struct address_info *hw_config) +{ + free_irq(hw_config->irq, NULL); + sound_free_dma(hw_config->dma); +} diff --git a/drivers/sound/vidc.h b/drivers/sound/vidc.h new file mode 100644 index 000000000..33625f392 --- /dev/null +++ b/drivers/sound/vidc.h @@ -0,0 +1,68 @@ +/* + * drivers/sound/vidc.h + * + * VIDC sound function prototypes + * + * Copyright (C) 1997 Russell King <rmk@arm.uk.linux.org> + */ + +/* vidc.c */ + +extern int vidc_busy; + +/* vidc_fill.S */ + +/* + * Filler routines for different channels and sample sizes + */ + +extern unsigned long vidc_fill_1x8(unsigned long ibuf, unsigned long iend, + unsigned long obuf, int mask); +extern unsigned long vidc_fill_2x8(unsigned long ibuf, unsigned long iend, + unsigned long obuf, int mask); +extern unsigned long vidc_fill_1x16(unsigned long ibuf, unsigned long iend, + unsigned long obuf, int mask); +extern unsigned long vidc_fill_2x16(unsigned long ibuf, unsigned long iend, + unsigned long obuf, int mask); + +/* + * DMA Interrupt handler + */ + +extern void vidc_sound_dma_irq(int irqnr, void *ref, struct pt_regs *regs); + +/* + * Filler routine pointer + */ + +extern unsigned long (*vidc_filler) (unsigned long ibuf, unsigned long iend, + unsigned long obuf, int mask); + +/* + * Virtual DMA buffer exhausted + */ + +extern void (*dma_interrupt) (void); + +/* + * Virtual DMA buffer addresses + */ + +extern unsigned long dma_start, dma_count, dma_bufsize; +extern unsigned long dma_buf[2], dma_pbuf[2]; + +/* vidc_audio.c */ + +extern void vidc_audio_init(struct address_info *hw_config); +extern int vidc_audio_get_volume(void); +extern int vidc_audio_set_volume(int vol); + +/* vidc_mixer.c */ + +extern void vidc_mixer_init(struct address_info *hw_config); + +/* vidc_synth.c */ + +extern void vidc_synth_init(struct address_info *hw_config); +extern int vidc_synth_get_volume(void); +extern int vidc_synth_set_volume(int vol); diff --git a/drivers/sound/vidc_audio.c b/drivers/sound/vidc_audio.c new file mode 100644 index 000000000..a59a077f3 --- /dev/null +++ b/drivers/sound/vidc_audio.c @@ -0,0 +1,320 @@ +/* + * drivers/sound/vidc_audio.c + * + * Audio routines for the VIDC + * + * Copyright (C) 1997 Russell King <rmk@arm.uk.linux.org> + */ + +#include <asm/hardware.h> +#include <asm/io.h> +#include "sound_config.h" +#include "vidc.h" + +/* + * VIDC sound + * + * When using SERIAL SOUND mode (external DAC), the number of physical + * channels is fixed at 2. Therefore, the sample rate = vidc sample rate. + */ + +static int vidc_adev; + +static int vidc_audio_volume; +static int vidc_audio_rate; +static char vidc_audio_bits; +static char vidc_audio_channels; + +extern void vidc_update_filler(int bits, int channels); + +int vidc_audio_get_volume(void) +{ + return vidc_audio_volume; +} + +int vidc_audio_set_volume(int newvol) +{ + vidc_audio_volume = newvol; + return vidc_audio_volume; +} + +static int vidc_audio_set_bits(int bits) +{ + switch (bits) + { + case AFMT_QUERY: + break; + case AFMT_U8: + case AFMT_S16_LE: + vidc_audio_bits = bits; + vidc_update_filler(vidc_audio_bits, vidc_audio_channels); + break; + default: + vidc_audio_bits = 16; + vidc_update_filler(vidc_audio_bits, vidc_audio_channels); + break; + } + return vidc_audio_bits; +} + +static int vidc_audio_set_rate(int rate) +{ + if (rate) + { + int newsize, new2size; + + vidc_audio_rate = ((500000 / rate) + 1) >> 1; + if (vidc_audio_rate < 3) + vidc_audio_rate = 3; + if (vidc_audio_rate > 255) + vidc_audio_rate = 255; + outl((vidc_audio_rate - 2) | 0xb0000000, VIDC_BASE); + outl(0xb1000003, VIDC_BASE); + newsize = (10000 / vidc_audio_rate) & ~3; + if (newsize < 208) + newsize = 208; + if (newsize > 4096) + newsize = 4096; + for (new2size = 128; new2size < newsize; new2size <<= 1); + if (new2size - newsize > newsize - (new2size >> 1)) + new2size >>= 1; + dma_bufsize = new2size; + } + return 250000 / vidc_audio_rate; +} + +static int vidc_audio_set_channels(int channels) +{ + switch (channels) + { + case 0: + break; + case 1: + case 2: + vidc_audio_channels = channels; + vidc_update_filler(vidc_audio_bits, vidc_audio_channels); + break; + default: + vidc_audio_channels = 2; + vidc_update_filler(vidc_audio_bits, vidc_audio_channels); + break; + } + return vidc_audio_channels; +} + +/* + * Open the device + * + * dev - device + * mode - mode to open device (logical OR of OPEN_READ and OPEN_WRITE) + * + * Called when opening the DMAbuf (dmabuf.c:259) + */ + +static int vidc_audio_open(int dev, int mode) +{ + if (vidc_busy) + return -EBUSY; + + if ((mode & OPEN_READ) && (!mode & OPEN_WRITE)) + { + /* This audio device doesn't have recording capability */ + return -EIO; + } + vidc_busy = 1; + return 0; +} + +/* + * Close the device + * + * dev - device + * + * Called when closing the DMAbuf (dmabuf.c:477) + * after halt_xfer + */ + +static void vidc_audio_close(int dev) +{ + vidc_busy = 0; +} + +static int vidc_audio_ioctl(int dev, unsigned int cmd, caddr_t arg) +{ + int ret; + + switch (cmd) + { + case SOUND_PCM_WRITE_RATE: + if (get_user(ret, (int *) arg)) + return -EFAULT; + ret = vidc_audio_set_rate(ret); + break; + + case SOUND_PCM_READ_RATE: + ret = vidc_audio_set_rate(0); + break; + + case SNDCTL_DSP_STEREO: + if (get_user(ret, (int *) arg)) + return -EFAULT; + ret = vidc_audio_set_channels(ret + 1) - 1; + break; + + case SOUND_PCM_WRITE_CHANNELS: + if (get_user(ret, (int *) arg)) + return -EFAULT; + ret = vidc_audio_set_channels(ret); + break; + + case SOUND_PCM_READ_CHANNELS: + ret = vidc_audio_set_channels(0); + break; + + case SNDCTL_DSP_SETFMT: + if (get_user(ret, (int *) arg)) + return -EFAULT; + ret = vidc_audio_set_bits(ret); + break; + + case SOUND_PCM_READ_BITS: + ret = vidc_audio_set_bits(0); + break; + + case SOUND_PCM_WRITE_FILTER: + case SOUND_PCM_READ_FILTER: + return -EINVAL; + + default: + return -EINVAL; + } + return put_user(ret, (int *) arg); +} + +/* + * Output a block via DMA to sound device + * + * dev - device number + * buf - physical address of buffer + * total_count - total byte count in buffer + * intrflag - set if this has been called from an interrupt (via DMAbuf_outputintr) + * restart_dma - set if DMA needs to be re-initialised + * + * Called when: + * 1. Starting output (dmabuf.c:1327) + * 2. (dmabuf.c:1504) + * 3. A new buffer needs to be sent to the device (dmabuf.c:1579) + */ + +static void vidc_audio_dma_interrupt(void) +{ + DMAbuf_outputintr(vidc_adev, 1); +} + +static void vidc_audio_output_block(int dev, unsigned long buf, int total_count, + int intrflag) +{ + dma_start = buf; + dma_count = total_count; + + if (!intrflag) + { + dma_interrupt = vidc_audio_dma_interrupt; + vidc_sound_dma_irq(0, NULL, NULL); + outb(DMA_CR_D | DMA_CR_E, IOMD_SD0CR); + } +} + +static void vidc_audio_start_input(int dev, unsigned long buf, int count, + int intrflag) +{ +} + +static int vidc_audio_prepare_for_input(int dev, int bsize, int bcount) +{ + return -EINVAL; +} + +/* + * Prepare for outputting samples to `dev' + * + * Each buffer that will be passed will be `bsize' bytes long, + * with a total of `bcount' buffers. + * + * Called when: + * 1. A trigger enables audio output (dmabuf.c:978) + * 2. We get a write buffer without dma_mode setup (dmabuf.c:1152) + * 3. We restart a transfer (dmabuf.c:1324) + */ + +static int vidc_audio_prepare_for_output(int dev, int bsize, int bcount) +{ + return 0; +} + +static void vidc_audio_reset(int dev) +{ +} + +/* + * Halt a DMA transfer to `dev' + * + * Called when: + * 1. We close the DMAbuf (dmabuf.c:476) + * 2. We run out of output buffers to output to the device. (dmabuf.c:1456) + * 3. We run out of output buffers and we're closing down. (dmabuf.c:1546) + * 4. We run out of input buffers in AUTOMODE. (dmabuf.c:1651) + */ + +static void vidc_audio_halt_xfer(int dev) +{ + dma_count = 0; +} + +static int vidc_audio_local_qlen(int dev) +{ + return dma_count != 0; +} + +static struct audio_driver vidc_audio_driver = +{ + vidc_audio_open, /* open */ + vidc_audio_close, /* close */ + vidc_audio_output_block, /* output_block */ + vidc_audio_start_input, /* start_input */ + vidc_audio_ioctl, /* ioctl */ + vidc_audio_prepare_for_input, /* prepare_for_input */ + vidc_audio_prepare_for_output, /* prepare_for_output */ + vidc_audio_reset, /* reset */ + vidc_audio_halt_xfer, /* halt_xfer */ + vidc_audio_local_qlen, /*+local_qlen */ + NULL, /*+copy_from_user */ + NULL, /*+halt_input */ + NULL, /*+halt_output */ + NULL, /*+trigger */ + NULL, /*+set_speed */ + NULL, /*+set_bits */ + NULL, /*+set_channels */ +}; + +static struct audio_operations vidc_audio_operations = +{ + "VIDCsound", + 0, + AFMT_U8 | AFMT_S16_LE, + NULL, + &vidc_audio_driver +}; + +void vidc_audio_init(struct address_info *hw_config) +{ + vidc_audio_volume = 100 | (100 << 8); + if ((vidc_adev = sound_alloc_audiodev())!=-1) + { + audio_devs[vidc_adev] = &vidc_audio_operations; + audio_devs[vidc_adev]->min_fragment = 10; /* 1024 bytes => 64 buffers */ + audio_devs[vidc_adev]->mixer_dev = num_mixers; + audio_devs[vidc_adev]->flags |= 0; + } + else printk(KERN_ERR "VIDCsound: Too many PCM devices available\n"); +} diff --git a/drivers/sound/vidc_fill.S b/drivers/sound/vidc_fill.S new file mode 100644 index 000000000..841fe5b96 --- /dev/null +++ b/drivers/sound/vidc_fill.S @@ -0,0 +1,184 @@ +/* + * sound/vidc_fill.S + * + * Filler routines for DMA buffers + * + * Copyright (C) 1997 Russell King + */ +#define __ASSEMBLY__ +#include <linux/linkage.h> +#include <asm/assembler.h> +#include <asm/hardware.h> + + .text + +ENTRY(vidc_fill_1x8) + mov ip, #0xff00 +1: cmp r0, r1 + bge SYMBOL_NAME(vidc_clear) + ldrb r4, [r0], #1 + and r4, ip, r4, lsl #8 + orr r4, r4, r4, lsl #16 + str r4, [r2], #4 + cmp r2, r3 + blt 1b + mov pc, lr + +ENTRY(vidc_fill_2x8) + mov ip, #0xff00 +1: cmp r0, r1 + bge SYMBOL_NAME(vidc_clear) + ldr r4, [r0], #2 + and r5, r4, ip + and r4, ip, r4, lsl #8 + orr r4, r4, r5, lsl #16 + orr r4, r4, r4, lsr #8 + str r4, [r2], #4 + cmp r2, r3 + blt 1b + mov pc, lr + +ENTRY(vidc_fill_1x16) + mov ip, #0xff00 + orr ip, ip, ip, lsr #8 +1: cmp r0, r1 + bge SYMBOL_NAME(vidc_clear) + ldr r5, [r0], #2 + and r4, r5, ip + orr r4, r4, r4, lsl #16 + str r4, [r2], #4 + cmp r0, r1 + addlt r0, r0, #2 + andlt r4, r5, ip, lsl #16 + orrlt r4, r4, r4, lsr #16 + strlt r4, [r2], #4 + cmp r2, r3 + blt 1b + mov pc, lr + +ENTRY(vidc_fill_2x16) + mov ip, #0xff00 + orr ip, ip, ip, lsr #8 +1: cmp r0, r1 + bge SYMBOL_NAME(vidc_clear) + ldr r4, [r0], #4 + str r4, [r2], #4 + cmp r0, r1 + ldrlt r4, [r0], #4 + strlt r4, [r2], #4 + cmp r2, r3 + blt 1b + mov pc, lr + +ENTRY(vidc_fill_noaudio) + mov r0, #0 + mov r1, #0 +2: mov r4, #0 + mov r5, #0 +1: cmp r2, r3 + stmltia r2!, {r0, r1, r4, r5} + blt 1b + mov pc, lr + +ENTRY(vidc_clear) + mov r0, #0 + mov r1, #0 + tst r2, #4 + str r0, [r2], #4 + tst r2, #8 + stmia r2!, {r0, r1} + b 2b + +/* + * Call filler routines with: + * r0 = phys address + * r1 = phys end + * r2 = buffer + * Returns: + * r0 = new buffer address + * r2 = new buffer finish + * r4 = corrupted + * r5 = corrupted + * ip = corrupted + */ + +ENTRY(vidc_sound_dma_irq) + stmfd sp!, {r4 - r9, lr} + ldr r9, =SYMBOL_NAME(dma_start) + ldmia r9, {r0, r1, r2, r3, r4, r5} + teq r1, #0 + adreq r4, SYMBOL_NAME(vidc_fill_noaudio) + moveq r8, #1 << 31 + movne r8, #0 + mov ip, #IOMD_BASE & 0xff000000 + orr ip, ip, #IOMD_BASE & 0x00ff0000 + ldrb r7, [ip, #IOMD_SD0ST] + tst r7, #DMA_ST_OFL @ Check for overrun + eorne r7, r7, #DMA_ST_AB + tst r7, #DMA_ST_AB + moveq r2, r3 @ DMAing A, update B + add r3, r2, r5 @ End of DMA buffer + add r1, r1, r0 @ End of virtual DMA buffer + mov lr, pc + mov pc, r4 @ Call fill routine + sub r1, r1, r0 @ Remaining length + stmia r9, {r0, r1} + mov r0, #0 + tst r2, #4 @ Round buffer up to 4 words + strne r0, [r2], #4 + tst r2, #8 + strne r0, [r2], #4 + strne r0, [r2], #4 + sub r2, r2, #16 + mov r2, r2, lsl #20 + movs r2, r2, lsr #20 + orreq r2, r2, #1 << 30 @ Set L bit + orr r2, r2, r8 + ldmdb r9, {r3, r4, r5} + tst r7, #DMA_ST_AB + mov ip, #IOMD_BASE & 0xff000000 + orr ip, ip, #IOMD_BASE & 0x00ff0000 + streq r4, [ip, #IOMD_SD0CURB] + strne r5, [ip, #IOMD_SD0CURA] + streq r2, [ip, #IOMD_SD0ENDB] + strne r2, [ip, #IOMD_SD0ENDA] + ldr r6, [ip, #IOMD_SD0ST] + tst r6, #DMA_ST_OFL + bne 1f + tst r7, #DMA_ST_AB + strne r4, [ip, #IOMD_SD0CURB] + streq r5, [ip, #IOMD_SD0CURA] + strne r2, [ip, #IOMD_SD0ENDB] + streq r2, [ip, #IOMD_SD0ENDA] +1: teq r8, #0 + mov r0, #0x10 + strneb r0, [ip, #IOMD_SD0CR] + teqeq r1, #0 + ldmfd sp!, {r4 - r9, lr} + moveq pc, r3 @ Call interrupt routine + mov pc, lr + + .data + .globl SYMBOL_NAME(dma_interrupt) +SYMBOL_NAME(dma_interrupt): + .long 0 + .globl SYMBOL_NAME(dma_pbuf) +SYMBOL_NAME(dma_pbuf): + .long 0 + .long 0 + .globl SYMBOL_NAME(dma_start) +SYMBOL_NAME(dma_start): + .long 0 + .globl SYMBOL_NAME(dma_count) +SYMBOL_NAME(dma_count): + .long 0 + .globl SYMBOL_NAME(dma_buf) +SYMBOL_NAME(dma_buf): + .long 0 + .long 0 + .globl SYMBOL_NAME(vidc_filler) +SYMBOL_NAME(vidc_filler): + .long SYMBOL_NAME(vidc_fill_noaudio) + .globl SYMBOL_NAME(dma_bufsize) +SYMBOL_NAME(dma_bufsize): + .long 0x1000 diff --git a/drivers/sound/vidc_mixer.c b/drivers/sound/vidc_mixer.c new file mode 100644 index 000000000..1bdb1e88e --- /dev/null +++ b/drivers/sound/vidc_mixer.c @@ -0,0 +1,149 @@ +/* + * drivers/sound/vidc_mixer.c + * + * Mixer routines for VIDC + * + * Copyright (C) 1997 Russell King <rmk@arm.uk.linux.org> + */ + +#include "sound_config.h" +#include "vidc.h" + +int vidc_volume; + +static int vidc_get_volume(void) +{ + return vidc_volume; +} + +static int vidc_set_volume(int newvol) +{ + vidc_volume = newvol; +/* printk ("vidc_set_volume: %X\n", newvol); */ + return newvol; +} + +static int vidc_default_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg) +{ + int ret; + + switch (cmd) + { + case SOUND_MIXER_READ_VOLUME: + ret = vidc_get_volume(); + break; + + case SOUND_MIXER_WRITE_VOLUME: + if (get_user(ret, (int *) arg)) + return -EINVAL; + ret = vidc_set_volume(ret); + break; + + case SOUND_MIXER_READ_BASS: + case SOUND_MIXER_WRITE_BASS: + case SOUND_MIXER_READ_TREBLE: + case SOUND_MIXER_WRITE_TREBLE: + ret = 50; + break; + + case SOUND_MIXER_READ_SYNTH: + ret = vidc_synth_get_volume(); + break; + + case SOUND_MIXER_WRITE_SYNTH: + if (get_user(ret, (int *) arg)) + return -EINVAL; + ret = vidc_synth_set_volume(ret); + break; + + case SOUND_MIXER_READ_PCM: + ret = vidc_audio_get_volume(); + break; + + case SOUND_MIXER_WRITE_PCM: + if (get_user(ret, (int *) arg)) + return -EINVAL; + ret = vidc_audio_set_volume(ret); + break; + + case SOUND_MIXER_READ_SPEAKER: + ret = 100; + break; + + case SOUND_MIXER_WRITE_SPEAKER: + ret = 100; + break; + + case SOUND_MIXER_READ_LINE: + case SOUND_MIXER_WRITE_LINE: + case SOUND_MIXER_READ_MIC: + case SOUND_MIXER_WRITE_MIC: + ret = 0; + break; + + case SOUND_MIXER_READ_CD: + case SOUND_MIXER_WRITE_CD: + ret = 100 | (100 << 8); + break; + + case SOUND_MIXER_READ_IMIX: + case SOUND_MIXER_WRITE_IMIX: + case SOUND_MIXER_READ_ALTPCM: + case SOUND_MIXER_WRITE_ALTPCM: + case SOUND_MIXER_READ_LINE1: + case SOUND_MIXER_WRITE_LINE1: + case SOUND_MIXER_READ_LINE2: + case SOUND_MIXER_WRITE_LINE2: + case SOUND_MIXER_READ_LINE3: + case SOUND_MIXER_WRITE_LINE3: + ret = 0; + break; + + case SOUND_MIXER_READ_RECSRC: + ret = 0; + break; + + case SOUND_MIXER_WRITE_RECSRC: + return -EINVAL; + break; + + case SOUND_MIXER_READ_DEVMASK: + ret = SOUND_MASK_VOLUME | SOUND_MASK_PCM | SOUND_MASK_SYNTH; + break; + + case SOUND_MIXER_READ_RECMASK: + ret = 0; + break; + + case SOUND_MIXER_READ_STEREODEVS: + ret = SOUND_MASK_VOLUME | SOUND_MASK_PCM | SOUND_MASK_SYNTH; + break; + + case SOUND_MIXER_READ_CAPS: + ret = 0; + break; + + case SOUND_MIXER_READ_MUTE: + return -EINVAL; + break; + + default: + return -EINVAL; + break; + } + return put_user(ret, (int *) arg); +} + +static struct mixer_operations vidc_mixer_operations = { + "VIDC", + "VIDCsound", + vidc_default_mixer_ioctl /* ioctl */ +}; + +void vidc_mixer_init(struct address_info *hw_config) +{ + int vidc_mixer = sound_alloc_mixerdev(); + vidc_volume = 100 | (100 << 8); + if (num_mixers < MAX_MIXER_DEV) + mixer_devs[vidc_mixer] = &vidc_mixer_operations; +} diff --git a/drivers/sound/vidc_synth.c b/drivers/sound/vidc_synth.c new file mode 100644 index 000000000..7e6797e8e --- /dev/null +++ b/drivers/sound/vidc_synth.c @@ -0,0 +1,89 @@ +/* + * drivers/sound/vidc_synth.c + * + * Synthesizer routines for the VIDC + * + * Copyright (C) 1997 Russell King <rmk@arm.uk.linux.org> + */ + +#include "sound_config.h" +#include "vidc.h" + +static struct synth_info vidc_info = +{ + "VIDCsound", /* name */ + 0, /* device */ + SYNTH_TYPE_SAMPLE, /* synth_type */ + 0, /* synth_subtype */ + 0, /* perc_mode */ + 16, /* nr_voices */ + 0, /* nr_drums */ + 0, /* instr_bank_size */ + 0, /* capabilities */ +}; + +int vidc_sdev; +int vidc_synth_volume; + +static int vidc_synth_open(int dev, int mode) +{ + if (vidc_busy) + return -EBUSY; + + vidc_busy = 1; + return 0; +} + +static void vidc_synth_close(int dev) +{ + vidc_busy = 0; +} + + +static struct synth_operations vidc_synth_operations = +{ + &vidc_info, /* info */ + 0, /* midi_dev */ + SYNTH_TYPE_SAMPLE, /* synth_type */ + /*SAMPLE_TYPE_XXX */ 0, + /* SAMPLE_TYPE GUS *//* synth_subtype */ + vidc_synth_open, /* open */ + vidc_synth_close, /* close */ + NULL, /* ioctl */ + NULL, /* kill_note */ + NULL, /* start_note */ + NULL, /* set_instr */ + NULL, /* reset */ + NULL, /* hw_control */ + NULL, /* load_patch */ + NULL, /* aftertouch */ + NULL, /* controller */ + NULL, /* panning */ + NULL, /* volume_method */ + NULL, /* patchmgr */ + NULL, /* bender */ + NULL, /* alloc */ + NULL, /* setup_voice */ + NULL, /* send_sysex */ + /* alloc */ + /* chn_info[16] */ +}; + +int vidc_synth_get_volume(void) +{ + return vidc_synth_volume; +} + +int vidc_synth_set_volume(int newvol) +{ + return vidc_synth_volume = newvol; +} + +void vidc_synth_init(struct address_info *hw_config) +{ + vidc_synth_volume = 100 | (100 << 8); + if ((vidc_sdev=sound_alloc_synthdev())!=-1) + synth_devs[vidc_sdev] = &vidc_synth_operations; + else + printk(KERN_ERR "VIDCsound: Too many synthesizers\n"); +} |