Merge branch 'fix/misc' into topic/misc
authorTakashi Iwai <tiwai@suse.de>
Sun, 1 Nov 2009 10:11:07 +0000 (11:11 +0100)
committerTakashi Iwai <tiwai@suse.de>
Sun, 1 Nov 2009 10:11:07 +0000 (11:11 +0100)
19 files changed:
Documentation/sound/alsa/ALSA-Configuration.txt
include/sound/Kbuild
include/sound/sscape_ioctl.h [deleted file]
sound/core/isadma.c
sound/isa/Kconfig
sound/isa/es18xx.c
sound/isa/sscape.c
sound/isa/wss/wss_lib.c
sound/oss/Kconfig
sound/oss/Makefile
sound/oss/sh_dac_audio.c
sound/oss/sscape.c [deleted file]
sound/pci/ca0106/ca0106_proc.c
sound/pci/ctxfi/ctatc.c
sound/pci/emu10k1/emu10k1x.c
sound/pci/emu10k1/emuproc.c
sound/pci/emu10k1/io.c
sound/soc/codecs/tlv320aic23.c
sound/usb/usx2y/us122l.c

index 1c8eb45..6de56d1 100644 (file)
@@ -1631,7 +1631,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
   Module snd-sscape
   -----------------
 
-    Module for ENSONIQ SoundScape PnP cards.
+    Module for ENSONIQ SoundScape cards.
 
     port       - Port # (PnP setup)
     wss_port   - WSS Port # (PnP setup)
@@ -1639,10 +1639,11 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
     mpu_irq    - MPU-401 IRQ # (PnP setup)
     dma                - DMA # (PnP setup)
     dma2       - 2nd DMA # (PnP setup, -1 to disable)
+    joystick   - Enable gameport - 0 = disable (default), 1 = enable
+
+    This module supports multiple cards.
 
-    This module supports multiple cards.  ISA PnP must be enabled.
-    You need sscape_ctl tool in alsa-tools package for loading
-    the microcode.
+    The driver requires the firmware loader support on kernel.
 
   Module snd-sun-amd7930 (on sparc only)
   --------------------------------------
index fd054a3..e9dd936 100644 (file)
@@ -2,7 +2,6 @@ header-y += asound_fm.h
 header-y += hdsp.h
 header-y += hdspm.h
 header-y += sfnt_info.h
-header-y += sscape_ioctl.h
 
 unifdef-y += asequencer.h
 unifdef-y += asound.h
diff --git a/include/sound/sscape_ioctl.h b/include/sound/sscape_ioctl.h
deleted file mode 100644 (file)
index 0d88859..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef SSCAPE_IOCTL_H
-#define SSCAPE_IOCTL_H
-
-
-struct sscape_bootblock
-{
-  unsigned char code[256];
-  unsigned version;
-};
-
-#define SSCAPE_MICROCODE_SIZE  65536
-
-struct sscape_microcode
-{
-  unsigned char __user *code;
-};
-
-#define SND_SSCAPE_LOAD_BOOTB  _IOWR('P', 100, struct sscape_bootblock)
-#define SND_SSCAPE_LOAD_MCODE  _IOW ('P', 101, struct sscape_microcode)
-
-#endif
index 79f0f16..950e19b 100644 (file)
@@ -85,16 +85,24 @@ EXPORT_SYMBOL(snd_dma_disable);
 unsigned int snd_dma_pointer(unsigned long dma, unsigned int size)
 {
        unsigned long flags;
-       unsigned int result;
+       unsigned int result, result1;
 
        flags = claim_dma_lock();
        clear_dma_ff(dma);
        if (!isa_dma_bridge_buggy)
                disable_dma(dma);
        result = get_dma_residue(dma);
+       /*
+        * HACK - read the counter again and choose higher value in order to
+        * avoid reading during counter lower byte roll over if the
+        * isa_dma_bridge_buggy is set.
+        */
+       result1 = get_dma_residue(dma);
        if (!isa_dma_bridge_buggy)
                enable_dma(dma);
        release_dma_lock(flags);
+       if (unlikely(result < result1))
+               result = result1;
 #ifdef CONFIG_SND_DEBUG
        if (result > size)
                snd_printk(KERN_ERR "pointer (0x%x) for DMA #%ld is greater than transfer size (0x%x)\n", result, dma, size);
index 51a7e37..02fe81c 100644 (file)
@@ -372,15 +372,21 @@ config SND_SGALAXY
 
 config SND_SSCAPE
        tristate "Ensoniq SoundScape driver"
-       select SND_HWDEP
        select SND_MPU401_UART
        select SND_WSS_LIB
+       select FW_LOADER
        help
          Say Y here to include support for Ensoniq SoundScape 
-         soundcards.
+         and Ensoniq OEM soundcards.
 
          The PCM audio is supported on SoundScape Classic, Elite, PnP
-         and VIVO cards. The MIDI support is very experimental.
+         and VIVO cards. The supported OEM cards are SPEA Media FX and
+         Reveal SC-600.
+         The MIDI support is very experimental and requires binary
+         firmware files called "scope.cod" and "sndscape.co?" where the
+         ? is digit 0, 1, 2, 3 or 4. The firmware files can be found
+         in DOS or Windows driver packages. One has to put the firmware
+         files into the /lib/firmware directory.
 
          To compile this driver as a module, choose M here: the module
          will be called snd-sscape.
index 8cfbff7..5cf42b4 100644 (file)
@@ -121,7 +121,6 @@ struct snd_es18xx {
        unsigned int dma1_shift;
        unsigned int dma2_shift;
 
-       struct snd_card *card;
        struct snd_pcm *pcm;
        struct snd_pcm_substream *playback_a_substream;
        struct snd_pcm_substream *capture_a_substream;
@@ -140,10 +139,6 @@ struct snd_es18xx {
 #ifdef CONFIG_PM
        unsigned char pm_reg;
 #endif
-};
-
-struct snd_audiodrive {
-       struct snd_es18xx *chip;
 #ifdef CONFIG_PNP
        struct pnp_dev *dev;
        struct pnp_dev *devc;
@@ -755,7 +750,8 @@ static int snd_es18xx_playback_trigger(struct snd_pcm_substream *substream,
 
 static irqreturn_t snd_es18xx_interrupt(int irq, void *dev_id)
 {
-       struct snd_es18xx *chip = dev_id;
+       struct snd_card *card = dev_id;
+       struct snd_es18xx *chip = card->private_data;
        unsigned char status;
 
        if (chip->caps & ES18XX_CONTROL) {
@@ -805,12 +801,16 @@ static irqreturn_t snd_es18xx_interrupt(int irq, void *dev_id)
                int split = 0;
                if (chip->caps & ES18XX_HWV) {
                        split = snd_es18xx_mixer_read(chip, 0x64) & 0x80;
-                       snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, &chip->hw_switch->id);
-                       snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, &chip->hw_volume->id);
+                       snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
+                                       &chip->hw_switch->id);
+                       snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
+                                       &chip->hw_volume->id);
                }
                if (!split) {
-                       snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, &chip->master_switch->id);
-                       snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, &chip->master_volume->id);
+                       snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
+                                       &chip->master_switch->id);
+                       snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
+                                       &chip->master_volume->id);
                }
                /* ack interrupt */
                snd_es18xx_mixer_write(chip, 0x66, 0x00);
@@ -1691,8 +1691,10 @@ static struct snd_pcm_ops snd_es18xx_capture_ops = {
        .pointer =      snd_es18xx_capture_pointer,
 };
 
-static int __devinit snd_es18xx_pcm(struct snd_es18xx *chip, int device, struct snd_pcm ** rpcm)
+static int __devinit snd_es18xx_pcm(struct snd_card *card, int device,
+                                   struct snd_pcm **rpcm)
 {
+       struct snd_es18xx *chip = card->private_data;
         struct snd_pcm *pcm;
        char str[16];
        int err;
@@ -1701,9 +1703,9 @@ static int __devinit snd_es18xx_pcm(struct snd_es18xx *chip, int device, struct
                *rpcm = NULL;
        sprintf(str, "ES%x", chip->version);
        if (chip->caps & ES18XX_PCM2)
-               err = snd_pcm_new(chip->card, str, device, 2, 1, &pcm);
+               err = snd_pcm_new(card, str, device, 2, 1, &pcm);
        else
-               err = snd_pcm_new(chip->card, str, device, 1, 1, &pcm);
+               err = snd_pcm_new(card, str, device, 1, 1, &pcm);
         if (err < 0)
                 return err;
 
@@ -1734,10 +1736,9 @@ static int __devinit snd_es18xx_pcm(struct snd_es18xx *chip, int device, struct
 #ifdef CONFIG_PM
 static int snd_es18xx_suspend(struct snd_card *card, pm_message_t state)
 {
-       struct snd_audiodrive *acard = card->private_data;
-       struct snd_es18xx *chip = acard->chip;
+       struct snd_es18xx *chip = card->private_data;
 
-       snd_power_change_state(chip->card, SNDRV_CTL_POWER_D3hot);
+       snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
 
        snd_pcm_suspend_all(chip->pcm);
 
@@ -1752,24 +1753,25 @@ static int snd_es18xx_suspend(struct snd_card *card, pm_message_t state)
 
 static int snd_es18xx_resume(struct snd_card *card)
 {
-       struct snd_audiodrive *acard = card->private_data;
-       struct snd_es18xx *chip = acard->chip;
+       struct snd_es18xx *chip = card->private_data;
 
        /* restore PM register, we won't wake till (not 0x07) i/o activity though */
        snd_es18xx_write(chip, ES18XX_PM, chip->pm_reg ^= ES18XX_PM_FM);
 
-       snd_power_change_state(chip->card, SNDRV_CTL_POWER_D0);
+       snd_power_change_state(card, SNDRV_CTL_POWER_D0);
        return 0;
 }
 #endif /* CONFIG_PM */
 
-static int snd_es18xx_free(struct snd_es18xx *chip)
+static int snd_es18xx_free(struct snd_card *card)
 {
+       struct snd_es18xx *chip = card->private_data;
+
        release_and_free_resource(chip->res_port);
        release_and_free_resource(chip->res_ctrl_port);
        release_and_free_resource(chip->res_mpu_port);
        if (chip->irq >= 0)
-               free_irq(chip->irq, (void *) chip);
+               free_irq(chip->irq, (void *) card);
        if (chip->dma1 >= 0) {
                disable_dma(chip->dma1);
                free_dma(chip->dma1);
@@ -1778,37 +1780,29 @@ static int snd_es18xx_free(struct snd_es18xx *chip)
                disable_dma(chip->dma2);
                free_dma(chip->dma2);
        }
-       kfree(chip);
        return 0;
 }
 
 static int snd_es18xx_dev_free(struct snd_device *device)
 {
-       struct snd_es18xx *chip = device->device_data;
-       return snd_es18xx_free(chip);
+       return snd_es18xx_free(device->card);
 }
 
 static int __devinit snd_es18xx_new_device(struct snd_card *card,
                                           unsigned long port,
                                           unsigned long mpu_port,
                                           unsigned long fm_port,
-                                          int irq, int dma1, int dma2,
-                                          struct snd_es18xx ** rchip)
+                                          int irq, int dma1, int dma2)
 {
-        struct snd_es18xx *chip;
+       struct snd_es18xx *chip = card->private_data;
        static struct snd_device_ops ops = {
                .dev_free =     snd_es18xx_dev_free,
         };
        int err;
 
-       *rchip = NULL;
-        chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       if (chip == NULL)
-               return -ENOMEM;
        spin_lock_init(&chip->reg_lock);
        spin_lock_init(&chip->mixer_lock);
        spin_lock_init(&chip->ctrl_lock);
-        chip->card = card;
         chip->port = port;
         chip->mpu_port = mpu_port;
         chip->fm_port = fm_port;
@@ -1818,53 +1812,53 @@ static int __devinit snd_es18xx_new_device(struct snd_card *card,
         chip->audio2_vol = 0x00;
        chip->active = 0;
 
-       if ((chip->res_port = request_region(port, 16, "ES18xx")) == NULL) {
-               snd_es18xx_free(chip);
+       chip->res_port = request_region(port, 16, "ES18xx");
+       if (chip->res_port == NULL) {
+               snd_es18xx_free(card);
                snd_printk(KERN_ERR PFX "unable to grap ports 0x%lx-0x%lx\n", port, port + 16 - 1);
                return -EBUSY;
        }
 
-       if (request_irq(irq, snd_es18xx_interrupt, IRQF_DISABLED, "ES18xx", (void *) chip)) {
-               snd_es18xx_free(chip);
+       if (request_irq(irq, snd_es18xx_interrupt, IRQF_DISABLED, "ES18xx",
+                       (void *) card)) {
+               snd_es18xx_free(card);
                snd_printk(KERN_ERR PFX "unable to grap IRQ %d\n", irq);
                return -EBUSY;
        }
        chip->irq = irq;
 
        if (request_dma(dma1, "ES18xx DMA 1")) {
-               snd_es18xx_free(chip);
+               snd_es18xx_free(card);
                snd_printk(KERN_ERR PFX "unable to grap DMA1 %d\n", dma1);
                return -EBUSY;
        }
        chip->dma1 = dma1;
 
        if (dma2 != dma1 && request_dma(dma2, "ES18xx DMA 2")) {
-               snd_es18xx_free(chip);
+               snd_es18xx_free(card);
                snd_printk(KERN_ERR PFX "unable to grap DMA2 %d\n", dma2);
                return -EBUSY;
        }
        chip->dma2 = dma2;
 
         if (snd_es18xx_probe(chip) < 0) {
-                snd_es18xx_free(chip);
+               snd_es18xx_free(card);
                 return -ENODEV;
         }
-       if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
-               snd_es18xx_free(chip);
+       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, NULL, &ops);
+       if (err < 0) {
+               snd_es18xx_free(card);
                return err;
        }
-        *rchip = chip;
         return 0;
 }
 
-static int __devinit snd_es18xx_mixer(struct snd_es18xx *chip)
+static int __devinit snd_es18xx_mixer(struct snd_card *card)
 {
-       struct snd_card *card;
+       struct snd_es18xx *chip = card->private_data;
        int err;
        unsigned int idx;
 
-       card = chip->card;
-
        strcpy(card->mixername, chip->pcm->name);
 
        for (idx = 0; idx < ARRAY_SIZE(snd_es18xx_base_controls); idx++) {
@@ -2063,11 +2057,11 @@ static int __devinit snd_audiodrive_pnp_init_main(int dev, struct pnp_dev *pdev)
        return 0;
 }
 
-static int __devinit snd_audiodrive_pnp(int dev, struct snd_audiodrive *acard,
+static int __devinit snd_audiodrive_pnp(int dev, struct snd_es18xx *chip,
                                        struct pnp_dev *pdev)
 {
-       acard->dev = pdev;
-       if (snd_audiodrive_pnp_init_main(dev, acard->dev) < 0)
+       chip->dev = pdev;
+       if (snd_audiodrive_pnp_init_main(dev, chip->dev) < 0)
                return -EBUSY;
        return 0;
 }
@@ -2093,26 +2087,26 @@ static struct pnp_card_device_id snd_audiodrive_pnpids[] = {
 
 MODULE_DEVICE_TABLE(pnp_card, snd_audiodrive_pnpids);
 
-static int __devinit snd_audiodrive_pnpc(int dev, struct snd_audiodrive *acard,
+static int __devinit snd_audiodrive_pnpc(int dev, struct snd_es18xx *chip,
                                        struct pnp_card_link *card,
                                        const struct pnp_card_device_id *id)
 {
-       acard->dev = pnp_request_card_device(card, id->devs[0].id, NULL);
-       if (acard->dev == NULL)
+       chip->dev = pnp_request_card_device(card, id->devs[0].id, NULL);
+       if (chip->dev == NULL)
                return -EBUSY;
 
-       acard->devc = pnp_request_card_device(card, id->devs[1].id, NULL);
-       if (acard->devc == NULL)
+       chip->devc = pnp_request_card_device(card, id->devs[1].id, NULL);
+       if (chip->devc == NULL)
                return -EBUSY;
 
        /* Control port initialization */
-       if (pnp_activate_dev(acard->devc) < 0) {
+       if (pnp_activate_dev(chip->devc) < 0) {
                snd_printk(KERN_ERR PFX "PnP control configure failure (out of resources?)\n");
                return -EAGAIN;
        }
        snd_printdd("pnp: port=0x%llx\n",
-                       (unsigned long long)pnp_port_start(acard->devc, 0));
-       if (snd_audiodrive_pnp_init_main(dev, acard->dev) < 0)
+                       (unsigned long long)pnp_port_start(chip->devc, 0));
+       if (snd_audiodrive_pnp_init_main(dev, chip->dev) < 0)
                return -EBUSY;
 
        return 0;
@@ -2128,24 +2122,20 @@ static int __devinit snd_audiodrive_pnpc(int dev, struct snd_audiodrive *acard,
 static int snd_es18xx_card_new(int dev, struct snd_card **cardp)
 {
        return snd_card_create(index[dev], id[dev], THIS_MODULE,
-                              sizeof(struct snd_audiodrive), cardp);
+                              sizeof(struct snd_es18xx), cardp);
 }
 
 static int __devinit snd_audiodrive_probe(struct snd_card *card, int dev)
 {
-       struct snd_audiodrive *acard = card->private_data;
-       struct snd_es18xx *chip;
+       struct snd_es18xx *chip = card->private_data;
        struct snd_opl3 *opl3;
        int err;
 
-       if ((err = snd_es18xx_new_device(card,
-                                        port[dev],
-                                        mpu_port[dev],
-                                        fm_port[dev],
-                                        irq[dev], dma1[dev], dma2[dev],
-                                        &chip)) < 0)
+       err = snd_es18xx_new_device(card,
+                                   port[dev], mpu_port[dev], fm_port[dev],
+                                   irq[dev], dma1[dev], dma2[dev]);
+       if (err < 0)
                return err;
-       acard->chip = chip;
 
        sprintf(card->driver, "ES%x", chip->version);
        
@@ -2161,10 +2151,12 @@ static int __devinit snd_audiodrive_probe(struct snd_card *card, int dev)
                        chip->port,
                        irq[dev], dma1[dev]);
 
-       if ((err = snd_es18xx_pcm(chip, 0, NULL)) < 0)
+       err = snd_es18xx_pcm(card, 0, NULL);
+       if (err < 0)
                return err;
 
-       if ((err = snd_es18xx_mixer(chip)) < 0)
+       err = snd_es18xx_mixer(card);
+       if (err < 0)
                return err;
 
        if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) {
index 6618712..e2d5d2d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *   Low-level ALSA driver for the ENSONIQ SoundScape PnP
+ *   Low-level ALSA driver for the ENSONIQ SoundScape
  *   Copyright (c) by Chris Rankin
  *
  *   This driver was written in part using information obtained from
 #include <linux/err.h>
 #include <linux/isa.h>
 #include <linux/delay.h>
+#include <linux/firmware.h>
 #include <linux/pnp.h>
 #include <linux/spinlock.h>
 #include <linux/moduleparam.h>
 #include <asm/dma.h>
 #include <sound/core.h>
-#include <sound/hwdep.h>
 #include <sound/wss.h>
 #include <sound/mpu401.h>
 #include <sound/initval.h>
 
-#include <sound/sscape_ioctl.h>
-
 
 MODULE_AUTHOR("Chris Rankin");
-MODULE_DESCRIPTION("ENSONIQ SoundScape PnP driver");
+MODULE_DESCRIPTION("ENSONIQ SoundScape driver");
 MODULE_LICENSE("GPL");
-
-static int index[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_IDX;
-static char* id[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_STR;
-static long port[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_PORT;
-static long wss_port[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_PORT;
-static int irq[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_IRQ;
-static int mpu_irq[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_IRQ;
-static int dma[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_DMA;
-static int dma2[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_DMA;
+MODULE_FIRMWARE("sndscape.co0");
+MODULE_FIRMWARE("sndscape.co1");
+MODULE_FIRMWARE("sndscape.co2");
+MODULE_FIRMWARE("sndscape.co3");
+MODULE_FIRMWARE("sndscape.co4");
+MODULE_FIRMWARE("scope.cod");
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
+static char* id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
+static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
+static long wss_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
+static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
+static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
+static int dma[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;
+static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;
+static bool joystick[SNDRV_CARDS];
 
 module_param_array(index, int, NULL, 0444);
 MODULE_PARM_DESC(index, "Index number for SoundScape soundcard");
@@ -75,6 +80,9 @@ MODULE_PARM_DESC(dma, "DMA # for SoundScape driver.");
 module_param_array(dma2, int, NULL, 0444);
 MODULE_PARM_DESC(dma2, "DMA2 # for SoundScape driver.");
 
+module_param_array(joystick, bool, NULL, 0444);
+MODULE_PARM_DESC(joystick, "Enable gameport.");
+
 #ifdef CONFIG_PNP
 static int isa_registered;
 static int pnp_registered;
@@ -101,14 +109,14 @@ MODULE_DEVICE_TABLE(pnp_card, sscape_pnpids);
 #define RX_READY 0x01
 #define TX_READY 0x02
 
-#define CMD_ACK           0x80
-#define CMD_SET_MIDI_VOL  0x84
-#define CMD_GET_MIDI_VOL  0x85
-#define CMD_XXX_MIDI_VOL  0x86
-#define CMD_SET_EXTMIDI   0x8a
-#define CMD_GET_EXTMIDI   0x8b
-#define CMD_SET_MT32      0x8c
-#define CMD_GET_MT32      0x8d
+#define CMD_ACK                        0x80
+#define CMD_SET_MIDI_VOL       0x84
+#define CMD_GET_MIDI_VOL       0x85
+#define CMD_XXX_MIDI_VOL       0x86
+#define CMD_SET_EXTMIDI                0x8a
+#define CMD_GET_EXTMIDI                0x8b
+#define CMD_SET_MT32           0x8c
+#define CMD_GET_MT32           0x8d
 
 enum GA_REG {
        GA_INTSTAT_REG = 0,
@@ -127,7 +135,8 @@ enum GA_REG {
 
 
 enum card_type {
-       SSCAPE,
+       MEDIA_FX,       /* Sequoia S-1000 */
+       SSCAPE,         /* Sequoia S-2000 */
        SSCAPE_PNP,
        SSCAPE_VIVO,
 };
@@ -140,16 +149,7 @@ struct soundscape {
        struct resource *io_res;
        struct resource *wss_res;
        struct snd_wss *chip;
-       struct snd_mpu401 *mpu;
-       struct snd_hwdep *hw;
 
-       /*
-        * The MIDI device won't work until we've loaded
-        * its firmware via a hardware-dependent device IOCTL
-        */
-       spinlock_t fwlock;
-       int hw_in_use;
-       unsigned long midi_usage;
        unsigned char midi_vol;
 };
 
@@ -161,28 +161,21 @@ static inline struct soundscape *get_card_soundscape(struct snd_card *c)
        return (struct soundscape *) (c->private_data);
 }
 
-static inline struct soundscape *get_mpu401_soundscape(struct snd_mpu401 * mpu)
-{
-       return (struct soundscape *) (mpu->private_data);
-}
-
-static inline struct soundscape *get_hwdep_soundscape(struct snd_hwdep * hw)
-{
-       return (struct soundscape *) (hw->private_data);
-}
-
-
 /*
  * Allocates some kernel memory that we can use for DMA.
  * I think this means that the memory has to map to
  * contiguous pages of physical memory.
  */
-static struct snd_dma_buffer *get_dmabuf(struct snd_dma_buffer *buf, unsigned long size)
+static struct snd_dma_buffer *get_dmabuf(struct snd_dma_buffer *buf,
+                                        unsigned long size)
 {
        if (buf) {
-               if (snd_dma_alloc_pages_fallback(SNDRV_DMA_TYPE_DEV, snd_dma_isa_data(),
+               if (snd_dma_alloc_pages_fallback(SNDRV_DMA_TYPE_DEV,
+                                                snd_dma_isa_data(),
                                                 size, buf) < 0) {
-                       snd_printk(KERN_ERR "sscape: Failed to allocate %lu bytes for DMA\n", size);
+                       snd_printk(KERN_ERR "sscape: Failed to allocate "
+                                           "%lu bytes for DMA\n",
+                                           size);
                        return NULL;
                }
        }
@@ -199,13 +192,13 @@ static void free_dmabuf(struct snd_dma_buffer *buf)
                snd_dma_free_pages(buf);
 }
 
-
 /*
  * This function writes to the SoundScape's control registers,
  * but doesn't do any locking. It's up to the caller to do that.
  * This is why this function is "unsafe" ...
  */
-static inline void sscape_write_unsafe(unsigned io_base, enum GA_REG reg, unsigned char val)
+static inline void sscape_write_unsafe(unsigned io_base, enum GA_REG reg,
+                                      unsigned char val)
 {
        outb(reg, ODIE_ADDR_IO(io_base));
        outb(val, ODIE_DATA_IO(io_base));
@@ -215,7 +208,8 @@ static inline void sscape_write_unsafe(unsigned io_base, enum GA_REG reg, unsign
  * Write to the SoundScape's control registers, and do the
  * necessary locking ...
  */
-static void sscape_write(struct soundscape *s, enum GA_REG reg, unsigned char val)
+static void sscape_write(struct soundscape *s, enum GA_REG reg,
+                        unsigned char val)
 {
        unsigned long flags;
 
@@ -228,7 +222,8 @@ static void sscape_write(struct soundscape *s, enum GA_REG reg, unsigned char va
  * Read from the SoundScape's control registers, but leave any
  * locking to the caller. This is why the function is "unsafe" ...
  */
-static inline unsigned char sscape_read_unsafe(unsigned io_base, enum GA_REG reg)
+static inline unsigned char sscape_read_unsafe(unsigned io_base,
+                                              enum GA_REG reg)
 {
        outb(reg, ODIE_ADDR_IO(io_base));
        return inb(ODIE_DATA_IO(io_base));
@@ -257,9 +252,8 @@ static inline void set_midi_mode_unsafe(unsigned io_base)
 static inline int host_read_unsafe(unsigned io_base)
 {
        int data = -1;
-       if ((inb(HOST_CTRL_IO(io_base)) & RX_READY) != 0) {
+       if ((inb(HOST_CTRL_IO(io_base)) & RX_READY) != 0)
                data = inb(HOST_DATA_IO(io_base));
-       }
 
        return data;
 }
@@ -301,7 +295,7 @@ static inline int host_write_unsafe(unsigned io_base, unsigned char data)
  * Also leaves all locking-issues to the caller ...
  */
 static int host_write_ctrl_unsafe(unsigned io_base, unsigned char data,
-                                  unsigned timeout)
+                                 unsigned timeout)
 {
        int err;
 
@@ -320,7 +314,7 @@ static int host_write_ctrl_unsafe(unsigned io_base, unsigned char data,
  *
  * NOTE: This check is based upon observation, not documentation.
  */
-static inline int verify_mpu401(const struct snd_mpu401 * mpu)
+static inline int verify_mpu401(const struct snd_mpu401 *mpu)
 {
        return ((inb(MPU401C(mpu)) & 0xc0) == 0x80);
 }
@@ -328,7 +322,7 @@ static inline int verify_mpu401(const struct snd_mpu401 * mpu)
 /*
  * This is apparently the standard way to initailise an MPU-401
  */
-static inline void initialise_mpu401(const struct snd_mpu401 * mpu)
+static inline void initialise_mpu401(const struct snd_mpu401 *mpu)
 {
        outb(0, MPU401D(mpu));
 }
@@ -338,9 +332,10 @@ static inline void initialise_mpu401(const struct snd_mpu401 * mpu)
  * The AD1845 detection fails if we *don't* do this, so I
  * think that this is a good idea ...
  */
-static inline void activate_ad1845_unsafe(unsigned io_base)
+static void activate_ad1845_unsafe(unsigned io_base)
 {
-       sscape_write_unsafe(io_base, GA_HMCTL_REG, (sscape_read_unsafe(io_base, GA_HMCTL_REG) & 0xcf) | 0x10);
+       unsigned char val = sscape_read_unsafe(io_base, GA_HMCTL_REG);
+       sscape_write_unsafe(io_base, GA_HMCTL_REG, (val & 0xcf) | 0x10);
        sscape_write_unsafe(io_base, GA_CDCFG_REG, 0x80);
 }
 
@@ -359,24 +354,27 @@ static void soundscape_free(struct snd_card *c)
  * Tell the SoundScape to begin a DMA tranfer using the given channel.
  * All locking issues are left to the caller.
  */
-static inline void sscape_start_dma_unsafe(unsigned io_base, enum GA_REG reg)
+static void sscape_start_dma_unsafe(unsigned io_base, enum GA_REG reg)
 {
-       sscape_write_unsafe(io_base, reg, sscape_read_unsafe(io_base, reg) | 0x01);
-       sscape_write_unsafe(io_base, reg, sscape_read_unsafe(io_base, reg) & 0xfe);
+       sscape_write_unsafe(io_base, reg,
+                           sscape_read_unsafe(io_base, reg) | 0x01);
+       sscape_write_unsafe(io_base, reg,
+                           sscape_read_unsafe(io_base, reg) & 0xfe);
 }
 
 /*
  * Wait for a DMA transfer to complete. This is a "limited busy-wait",
  * and all locking issues are left to the caller.
  */
-static int sscape_wait_dma_unsafe(unsigned io_base, enum GA_REG reg, unsigned timeout)
+static int sscape_wait_dma_unsafe(unsigned io_base, enum GA_REG reg,
+                                 unsigned timeout)
 {
        while (!(sscape_read_unsafe(io_base, reg) & 0x01) && (timeout != 0)) {
                udelay(100);
                --timeout;
        } /* while */
 
-       return (sscape_read_unsafe(io_base, reg) & 0x01);
+       return sscape_read_unsafe(io_base, reg) & 0x01;
 }
 
 /*
@@ -392,12 +390,12 @@ static int obp_startup_ack(struct soundscape *s, unsigned timeout)
 
        do {
                unsigned long flags;
-               unsigned char x;
+               int x;
 
                spin_lock_irqsave(&s->lock, flags);
-               x = inb(HOST_DATA_IO(s->io_base));
+               x = host_read_unsafe(s->io_base);
                spin_unlock_irqrestore(&s->lock, flags);
-               if ((x & 0xfe) == 0xfe)
+               if (x == 0xfe || x == 0xff)
                        return 1;
 
                msleep(10);
@@ -419,10 +417,10 @@ static int host_startup_ack(struct soundscape *s, unsigned timeout)
 
        do {
                unsigned long flags;
-               unsigned char x;
+               int x;
 
                spin_lock_irqsave(&s->lock, flags);
-               x = inb(HOST_DATA_IO(s->io_base));
+               x = host_read_unsafe(s->io_base);
                spin_unlock_irqrestore(&s->lock, flags);
                if (x == 0xfe)
                        return 1;
@@ -436,15 +434,15 @@ static int host_startup_ack(struct soundscape *s, unsigned timeout)
 /*
  * Upload a byte-stream into the SoundScape using DMA channel A.
  */
-static int upload_dma_data(struct soundscape *s,
-                           const unsigned char __user *data,
-                           size_t size)
+static int upload_dma_data(struct soundscape *s, const unsigned char *data,
+                          size_t size)
 {
        unsigned long flags;
        struct snd_dma_buffer dma;
        int ret;
+       unsigned char val;
 
-       if (!get_dmabuf(&dma, PAGE_ALIGN(size)))
+       if (!get_dmabuf(&dma, PAGE_ALIGN(32 * 1024)))
                return -ENOMEM;
 
        spin_lock_irqsave(&s->lock, flags);
@@ -452,70 +450,57 @@ static int upload_dma_data(struct soundscape *s,
        /*
         * Reset the board ...
         */
-       sscape_write_unsafe(s->io_base, GA_HMCTL_REG, sscape_read_unsafe(s->io_base, GA_HMCTL_REG) & 0x3f);
+       val = sscape_read_unsafe(s->io_base, GA_HMCTL_REG);
+       sscape_write_unsafe(s->io_base, GA_HMCTL_REG, val & 0x3f);
 
        /*
         * Enable the DMA channels and configure them ...
         */
-       sscape_write_unsafe(s->io_base, GA_DMACFG_REG, 0x50);
-       sscape_write_unsafe(s->io_base, GA_DMAA_REG, (s->chip->dma1 << 4) | DMA_8BIT);
+       val = (s->chip->dma1 << 4) | DMA_8BIT;
+       sscape_write_unsafe(s->io_base, GA_DMAA_REG, val);
        sscape_write_unsafe(s->io_base, GA_DMAB_REG, 0x20);
 
        /*
         * Take the board out of reset ...
         */
-       sscape_write_unsafe(s->io_base, GA_HMCTL_REG, sscape_read_unsafe(s->io_base, GA_HMCTL_REG) | 0x80);
+       val = sscape_read_unsafe(s->io_base, GA_HMCTL_REG);
+       sscape_write_unsafe(s->io_base, GA_HMCTL_REG, val | 0x80);
 
        /*
-        * Upload the user's data (firmware?) to the SoundScape
+        * Upload the firmware to the SoundScape
         * board through the DMA channel ...
         */
        while (size != 0) {
                unsigned long len;
 
-               /*
-                * Apparently, copying to/from userspace can sleep.
-                * We are therefore forbidden from holding any
-                * spinlocks while we copy ...
-                */
-               spin_unlock_irqrestore(&s->lock, flags);
-
-               /*
-                * Remember that the data that we want to DMA
-                * comes from USERSPACE. We have already verified
-                * the userspace pointer ...
-                */
                len = min(size, dma.bytes);
-               len -= __copy_from_user(dma.area, data, len);
+               memcpy(dma.area, data, len);
                data += len;
                size -= len;
 
-               /*
-                * Grab that spinlock again, now that we've
-                * finished copying!
-                */
-               spin_lock_irqsave(&s->lock, flags);
-
                snd_dma_program(s->chip->dma1, dma.addr, len, DMA_MODE_WRITE);
                sscape_start_dma_unsafe(s->io_base, GA_DMAA_REG);
                if (!sscape_wait_dma_unsafe(s->io_base, GA_DMAA_REG, 5000)) {
                        /*
-                        * Don't forget to release this spinlock we're holding ...
+                        * Don't forget to release this spinlock we're holding
                         */
                        spin_unlock_irqrestore(&s->lock, flags);
 
-                       snd_printk(KERN_ERR "sscape: DMA upload has timed out\n");
+                       snd_printk(KERN_ERR
+                                       "sscape: DMA upload has timed out\n");
                        ret = -EAGAIN;
                        goto _release_dma;
                }
        } /* while */
 
        set_host_mode_unsafe(s->io_base);
+       outb(0x0, s->io_base);
 
        /*
         * Boot the board ... (I think)
         */
-       sscape_write_unsafe(s->io_base, GA_HMCTL_REG, sscape_read_unsafe(s->io_base, GA_HMCTL_REG) | 0x40);
+       val = sscape_read_unsafe(s->io_base, GA_HMCTL_REG);
+       sscape_write_unsafe(s->io_base, GA_HMCTL_REG, val | 0x40);
        spin_unlock_irqrestore(&s->lock, flags);
 
        /*
@@ -525,10 +510,12 @@ static int upload_dma_data(struct soundscape *s,
         */
        ret = 0;
        if (!obp_startup_ack(s, 5000)) {
-               snd_printk(KERN_ERR "sscape: No response from on-board processor after upload\n");
+               snd_printk(KERN_ERR "sscape: No response "
+                                   "from on-board processor after upload\n");
                ret = -EAGAIN;
        } else if (!host_startup_ack(s, 5000)) {
-               snd_printk(KERN_ERR "sscape: SoundScape failed to initialise\n");
+               snd_printk(KERN_ERR
+                               "sscape: SoundScape failed to initialise\n");
                ret = -EAGAIN;
        }
 
@@ -536,7 +523,7 @@ _release_dma:
        /*
         * NOTE!!! We are NOT holding any spinlocks at this point !!!
         */
-       sscape_write(s, GA_DMAA_REG, (s->ic_type == IC_ODIE ? 0x70 : 0x40));
+       sscape_write(s, GA_DMAA_REG, (s->ic_type == IC_OPUS ? 0x40 : 0x70));
        free_dmabuf(&dma);
 
        return ret;
@@ -546,167 +533,76 @@ _release_dma:
  * Upload the bootblock(?) into the SoundScape. The only
  * purpose of this block of code seems to be to tell
  * us which version of the microcode we should be using.
- *
- * NOTE: The boot-block data resides in USER-SPACE!!!
- *       However, we have already verified its memory
- *       addresses by the time we get here.
  */
-static int sscape_upload_bootblock(struct soundscape *sscape, struct sscape_bootblock __user *bb)
+static int sscape_upload_bootblock(struct snd_card *card)
 {
+       struct soundscape *sscape = get_card_soundscape(card);
        unsigned long flags;
+       const struct firmware *init_fw = NULL;
        int data = 0;
        int ret;
 
-       ret = upload_dma_data(sscape, bb->code, sizeof(bb->code));
-
-       spin_lock_irqsave(&sscape->lock, flags);
-       if (ret == 0) {
-               data = host_read_ctrl_unsafe(sscape->io_base, 100);
-       }
-       set_midi_mode_unsafe(sscape->io_base);
-       spin_unlock_irqrestore(&sscape->lock, flags);
-
-       if (ret == 0) {
-               if (data < 0) {
-                       snd_printk(KERN_ERR "sscape: timeout reading firmware version\n");
-                       ret = -EAGAIN;
-               }
-               else if (__copy_to_user(&bb->version, &data, sizeof(bb->version))) {
-                       ret = -EFAULT;
-               }
+       ret = request_firmware(&init_fw, "scope.cod", card->dev);
+       if (ret < 0) {
+               snd_printk(KERN_ERR "sscape: Error loading scope.cod");
+               return ret;
        }
+       ret = upload_dma_data(sscape, init_fw->data, init_fw->size);
 
-       return ret;
-}
-
-/*
- * Upload the microcode into the SoundScape. The
- * microcode is 64K of data, and if we try to copy
- * it into a local variable then we will SMASH THE
- * KERNEL'S STACK! We therefore leave it in USER
- * SPACE, and save ourselves from copying it at all.
- */
-static int sscape_upload_microcode(struct soundscape *sscape,
-                                   const struct sscape_microcode __user *mc)
-{
-       unsigned long flags;
-       char __user *code;
-       int err;
+       release_firmware(init_fw);
 
-       /*
-        * We are going to have to copy this data into a special
-        * DMA-able buffer before we can upload it. We shall therefore
-        * just check that the data pointer is valid for now.
-        *
-        * NOTE: This buffer is 64K long! That's WAY too big to
-        *       copy into a stack-temporary anyway.
-        */
-       if ( get_user(code, &mc->code) ||
-            !access_ok(VERIFY_READ, code, SSCAPE_MICROCODE_SIZE) )
-               return -EFAULT;
+       spin_lock_irqsave(&sscape->lock, flags);
+       if (ret == 0)
+               data = host_read_ctrl_unsafe(sscape->io_base, 100);
 
-       if ((err = upload_dma_data(sscape, code, SSCAPE_MICROCODE_SIZE)) == 0) {
-               snd_printk(KERN_INFO "sscape: MIDI firmware loaded\n");
-       }
+       if (data & 0x10)
+               sscape_write_unsafe(sscape->io_base, GA_SMCFGA_REG, 0x2f);
 
-       spin_lock_irqsave(&sscape->lock, flags);
-       set_midi_mode_unsafe(sscape->io_base);
        spin_unlock_irqrestore(&sscape->lock, flags);
 
-       initialise_mpu401(sscape->mpu);
+       data &= 0xf;
+       if (ret == 0 && data > 7) {
+               snd_printk(KERN_ERR
+                               "sscape: timeout reading firmware version\n");
+               ret = -EAGAIN;
+       }
 
-       return err;
+       return (ret == 0) ? data : ret;
 }
 
 /*
- * Hardware-specific device functions, to implement special
- * IOCTLs for the SoundScape card. This is how we upload
- * the microcode into the card, for example, and so we
- * must ensure that no two processes can open this device
- * simultaneously, and that we can't open it at all if
- * someone is using the MIDI device.
+ * Upload the microcode into the SoundScape.
  */
-static int sscape_hw_open(struct snd_hwdep * hw, struct file *file)
+static int sscape_upload_microcode(struct snd_card *card, int version)
 {
-       register struct soundscape *sscape = get_hwdep_soundscape(hw);
-       unsigned long flags;
+       struct soundscape *sscape = get_card_soundscape(card);
+       const struct firmware *init_fw = NULL;
+       char name[14];
        int err;
 
-       spin_lock_irqsave(&sscape->fwlock, flags);
+       snprintf(name, sizeof(name), "sndscape.co%d", version);
 
-       if ((sscape->midi_usage != 0) || sscape->hw_in_use) {
-               err = -EBUSY;
-       } else {
-               sscape->hw_in_use = 1;
-               err = 0;
+       err = request_firmware(&init_fw, name, card->dev);
+       if (err < 0) {
+               snd_printk(KERN_ERR "sscape: Error loading sndscape.co%d",
+                               version);
+               return err;
        }
+       err = upload_dma_data(sscape, init_fw->data, init_fw->size);
+       if (err == 0)
+               snd_printk(KERN_INFO "sscape: MIDI firmware loaded %d KBs\n",
+                               init_fw->size >> 10);
 
-       spin_unlock_irqrestore(&sscape->fwlock, flags);
-       return err;
-}
-
-static int sscape_hw_release(struct snd_hwdep * hw, struct file *file)
-{
-       register struct soundscape *sscape = get_hwdep_soundscape(hw);
-       unsigned long flags;
-
-       spin_lock_irqsave(&sscape->fwlock, flags);
-       sscape->hw_in_use = 0;
-       spin_unlock_irqrestore(&sscape->fwlock, flags);
-       return 0;
-}
-
-static int sscape_hw_ioctl(struct snd_hwdep * hw, struct file *file,
-                           unsigned int cmd, unsigned long arg)
-{
-       struct soundscape *sscape = get_hwdep_soundscape(hw);
-       int err = -EBUSY;
-
-       switch (cmd) {
-       case SND_SSCAPE_LOAD_BOOTB:
-               {
-                       register struct sscape_bootblock __user *bb = (struct sscape_bootblock __user *) arg;
-
-                       /*
-                        * We are going to have to copy this data into a special
-                        * DMA-able buffer before we can upload it. We shall therefore
-                        * just check that the data pointer is valid for now ...
-                        */
-                       if ( !access_ok(VERIFY_READ, bb->code, sizeof(bb->code)) )
-                               return -EFAULT;
-
-                       /*
-                        * Now check that we can write the firmware version number too...
-                        */
-                       if ( !access_ok(VERIFY_WRITE, &bb->version, sizeof(bb->version)) )
-                               return -EFAULT;
-
-                       err = sscape_upload_bootblock(sscape, bb);
-               }
-               break;
-
-       case SND_SSCAPE_LOAD_MCODE:
-               {
-                       register const struct sscape_microcode __user *mc = (const struct sscape_microcode __user *) arg;
-
-                       err = sscape_upload_microcode(sscape, mc);
-               }
-               break;
-
-       default:
-               err = -EINVAL;
-               break;
-       } /* switch */
+       release_firmware(init_fw);
 
        return err;
 }
 
-
 /*
  * Mixer control for the SoundScape's MIDI device.
  */
 static int sscape_midi_info(struct snd_kcontrol *ctl,
-                            struct snd_ctl_elem_info *uinfo)
+                           struct snd_ctl_elem_info *uinfo)
 {
        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
        uinfo->count = 1;
@@ -716,7 +612,7 @@ static int sscape_midi_info(struct snd_kcontrol *ctl,
 }
 
 static int sscape_midi_get(struct snd_kcontrol *kctl,
-                           struct snd_ctl_elem_value *uctl)
+                          struct snd_ctl_elem_value *uctl)
 {
        struct snd_wss *chip = snd_kcontrol_chip(kctl);
        struct snd_card *card = chip->card;
@@ -730,16 +626,18 @@ static int sscape_midi_get(struct snd_kcontrol *kctl,
 }
 
 static int sscape_midi_put(struct snd_kcontrol *kctl,
-                           struct snd_ctl_elem_value *uctl)
+                          struct snd_ctl_elem_value *uctl)
 {
        struct snd_wss *chip = snd_kcontrol_chip(kctl);
        struct snd_card *card = chip->card;
-       register struct soundscape *s = get_card_soundscape(card);
+       struct soundscape *s = get_card_soundscape(card);
        unsigned long flags;
        int change;
+       unsigned char new_val;
 
        spin_lock_irqsave(&s->lock, flags);
 
+       new_val = uctl->value.integer.value[0] & 127;
        /*
         * We need to put the board into HOST mode before we
         * can send any volume-changing HOST commands ...
@@ -752,15 +650,16 @@ static int sscape_midi_put(struct snd_kcontrol *kctl,
         * and then perform another volume-related command. Perhaps the
         * first command is an "open" and the second command is a "close"?
         */
-       if (s->midi_vol == ((unsigned char) uctl->value.integer. value[0] & 127)) {
+       if (s->midi_vol == new_val) {
                change = 0;
                goto __skip_change;
        }
-       change = (host_write_ctrl_unsafe(s->io_base, CMD_SET_MIDI_VOL, 100)
-                 && host_write_ctrl_unsafe(s->io_base, ((unsigned char) uctl->value.integer. value[0]) & 127, 100)
-                 && host_write_ctrl_unsafe(s->io_base, CMD_XXX_MIDI_VOL, 100));
-       s->midi_vol = (unsigned char) uctl->value.integer.value[0] & 127;
-      __skip_change:
+       change = host_write_ctrl_unsafe(s->io_base, CMD_SET_MIDI_VOL, 100)
+                && host_write_ctrl_unsafe(s->io_base, new_val, 100)
+                && host_write_ctrl_unsafe(s->io_base, CMD_XXX_MIDI_VOL, 100)
+                && host_write_ctrl_unsafe(s->io_base, new_val, 100);
+       s->midi_vol = new_val;
+__skip_change:
 
        /*
         * Take the board out of HOST mode and back into MIDI mode ...
@@ -784,20 +683,25 @@ static struct snd_kcontrol_new midi_mixer_ctl = {
  * These IRQs are encoded as bit patterns so that they can be
  * written to the control registers.
  */
-static unsigned __devinit get_irq_config(int irq)
+static unsigned __devinit get_irq_config(int sscape_type, int irq)
 {
        static const int valid_irq[] = { 9, 5, 7, 10 };
+       static const int old_irq[] = { 9, 7, 5, 15 };
        unsigned cfg;
 
-       for (cfg = 0; cfg < ARRAY_SIZE(valid_irq); ++cfg) {
-               if (irq == valid_irq[cfg])
-                       return cfg;
-       } /* for */
+       if (sscape_type == MEDIA_FX) {
+               for (cfg = 0; cfg < ARRAY_SIZE(old_irq); ++cfg)
+                       if (irq == old_irq[cfg])
+                               return cfg;
+       } else {
+               for (cfg = 0; cfg < ARRAY_SIZE(valid_irq); ++cfg)
+                       if (irq == valid_irq[cfg])
+                               return cfg;
+       }
 
        return INVALID_IRQ;
 }
 
-
 /*
  * Perform certain arcane port-checks to see whether there
  * is a SoundScape board lurking behind the given ports.
@@ -842,11 +746,38 @@ static int __devinit detect_sscape(struct soundscape *s, long wss_io)
        if (s->type != SSCAPE_VIVO && (d & 0x9f) != 0x0e)
                goto _done;
 
-       d  = sscape_read_unsafe(s->io_base, GA_HMCTL_REG) & 0x3f;
-       sscape_write_unsafe(s->io_base, GA_HMCTL_REG, d | 0xc0);
+       if (s->ic_type == IC_OPUS)
+               activate_ad1845_unsafe(s->io_base);
 
        if (s->type == SSCAPE_VIVO)
                wss_io += 4;
+
+       d  = sscape_read_unsafe(s->io_base, GA_HMCTL_REG);
+       sscape_write_unsafe(s->io_base, GA_HMCTL_REG, d | 0xc0);
+
+       /* wait for WSS codec */
+       for (d = 0; d < 500; d++) {
+               if ((inb(wss_io) & 0x80) == 0)
+                       break;
+               spin_unlock_irqrestore(&s->lock, flags);
+               msleep(1);
+               spin_lock_irqsave(&s->lock, flags);
+       }
+
+       if ((inb(wss_io) & 0x80) != 0)
+               goto _done;
+
+       if (inb(wss_io + 2) == 0xff)
+               goto _done;
+
+       d  = sscape_read_unsafe(s->io_base, GA_HMCTL_REG) & 0x3f;
+       sscape_write_unsafe(s->io_base, GA_HMCTL_REG, d);
+
+       if ((inb(wss_io) & 0x80) != 0)
+               s->type = MEDIA_FX;
+
+       d = sscape_read_unsafe(s->io_base, GA_HMCTL_REG);
+       sscape_write_unsafe(s->io_base, GA_HMCTL_REG, d | 0xc0);
        /* wait for WSS codec */
        for (d = 0; d < 500; d++) {
                if ((inb(wss_io) & 0x80) == 0)
@@ -855,14 +786,13 @@ static int __devinit detect_sscape(struct soundscape *s, long wss_io)
                msleep(1);
                spin_lock_irqsave(&s->lock, flags);
        }
-       snd_printd(KERN_INFO "init delay = %d ms\n", d);
 
        /*
         * SoundScape successfully detected!
         */
        retval = 1;
 
-       _done:
+_done:
        spin_unlock_irqrestore(&s->lock, flags);
        return retval;
 }
@@ -873,63 +803,35 @@ static int __devinit detect_sscape(struct soundscape *s, long wss_io)
  * to crash the machine. Also check that someone isn't using the hardware
  * IOCTL device.
  */
-static int mpu401_open(struct snd_mpu401 * mpu)
+static int mpu401_open(struct snd_mpu401 *mpu)
 {
-       int err;
-
        if (!verify_mpu401(mpu)) {
-               snd_printk(KERN_ERR "sscape: MIDI disabled, please load firmware\n");
-               err = -ENODEV;
-       } else {
-               register struct soundscape *sscape = get_mpu401_soundscape(mpu);
-               unsigned long flags;
-
-               spin_lock_irqsave(&sscape->fwlock, flags);
-
-               if (sscape->hw_in_use || (sscape->midi_usage == ULONG_MAX)) {
-                       err = -EBUSY;
-               } else {
-                       ++(sscape->midi_usage);
-                       err = 0;
-               }
-
-               spin_unlock_irqrestore(&sscape->fwlock, flags);
+               snd_printk(KERN_ERR "sscape: MIDI disabled, "
+                                   "please load firmware\n");
+               return -ENODEV;
        }
 
-       return err;
-}
-
-static void mpu401_close(struct snd_mpu401 * mpu)
-{
-       register struct soundscape *sscape = get_mpu401_soundscape(mpu);
-       unsigned long flags;
-
-       spin_lock_irqsave(&sscape->fwlock, flags);
-       --(sscape->midi_usage);
-       spin_unlock_irqrestore(&sscape->fwlock, flags);
+       return 0;
 }
 
 /*
  * Initialse an MPU-401 subdevice for MIDI support on the SoundScape.
  */
-static int __devinit create_mpu401(struct snd_card *card, int devnum, unsigned long port, int irq)
+static int __devinit create_mpu401(struct snd_card *card, int devnum,
+                                  unsigned long port, int irq)
 {
        struct soundscape *sscape = get_card_soundscape(card);
        struct snd_rawmidi *rawmidi;
        int err;
 
-       if ((err = snd_mpu401_uart_new(card, devnum,
-                                      MPU401_HW_MPU401,
-                                      port, MPU401_INFO_INTEGRATED,
-                                      irq, IRQF_DISABLED,
-                                      &rawmidi)) == 0) {
-               struct snd_mpu401 *mpu = (struct snd_mpu401 *) rawmidi->private_data;
+       err = snd_mpu401_uart_new(card, devnum, MPU401_HW_MPU401, port,
+                                 MPU401_INFO_INTEGRATED, irq, IRQF_DISABLED,
+                                 &rawmidi);
+       if (err == 0) {
+               struct snd_mpu401 *mpu = rawmidi->private_data;
                mpu->open_input = mpu401_open;
                mpu->open_output = mpu401_open;
-               mpu->close_input = mpu401_close;
-               mpu->close_output = mpu401_close;
                mpu->private_data = sscape;
-               sscape->mpu = mpu;
 
                initialise_mpu401(mpu);
        }
@@ -950,32 +852,34 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port,
        register struct soundscape *sscape = get_card_soundscape(card);
        struct snd_wss *chip;
        int err;
+       int codec_type = WSS_HW_DETECT;
 
-       if (sscape->type == SSCAPE_VIVO)
-               port += 4;
+       switch (sscape->type) {
+       case MEDIA_FX:
+       case SSCAPE:
+               /*
+                * There are some freak examples of early Soundscape cards
+                * with CS4231 instead of AD1848/CS4248. Unfortunately, the
+                * CS4231 works only in CS4248 compatibility mode on
+                * these cards so force it.
+                */
+               if (sscape->ic_type != IC_OPUS)
+                       codec_type = WSS_HW_AD1848;
+               break;
 
-       if (dma1 == dma2)
-               dma2 = -1;
+       case SSCAPE_VIVO:
+               port += 4;
+               break;
+       default:
+               break;
+       }
 
        err = snd_wss_create(card, port, -1, irq, dma1, dma2,
-                            WSS_HW_DETECT, WSS_HWSHARE_DMA1, &chip);
+                            codec_type, WSS_HWSHARE_DMA1, &chip);
        if (!err) {
                unsigned long flags;
                struct snd_pcm *pcm;
 
-/*
- * It turns out that the PLAYBACK_ENABLE bit is set
- * by the lowlevel driver ...
- *
-#define AD1845_IFACE_CONFIG  \
-           (CS4231_AUTOCALIB | CS4231_RECORD_ENABLE | CS4231_PLAYBACK_ENABLE)
-    snd_wss_mce_up(chip);
-    spin_lock_irqsave(&chip->reg_lock, flags);
-    snd_wss_out(chip, CS4231_IFACE_CTRL, AD1845_IFACE_CONFIG);
-    spin_unlock_irqrestore(&chip->reg_lock, flags);
-    snd_wss_mce_down(chip);
- */
-
                if (sscape->type != SSCAPE_VIVO) {
                        /*
                         * The input clock frequency on the SoundScape must
@@ -1022,17 +926,10 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port,
                        }
                }
 
-               strcpy(card->driver, "SoundScape");
-               strcpy(card->shortname, pcm->name);
-               snprintf(card->longname, sizeof(card->longname),
-                        "%s at 0x%lx, IRQ %d, DMA1 %d, DMA2 %d\n",
-                        pcm->name, chip->port, chip->irq,
-                        chip->dma1, chip->dma2);
-
                sscape->chip = chip;
        }
 
-       _error:
+_error:
        return err;
 }
 
@@ -1051,21 +948,8 @@ static int __devinit create_sscape(int dev, struct snd_card *card)
        struct resource *wss_res;
        unsigned long flags;
        int err;
-
-       /*
-        * Check that the user didn't pass us garbage data ...
-        */
-       irq_cfg = get_irq_config(irq[dev]);
-       if (irq_cfg == INVALID_IRQ) {
-               snd_printk(KERN_ERR "sscape: Invalid IRQ %d\n", irq[dev]);
-               return -ENXIO;
-       }
-
-       mpu_irq_cfg = get_irq_config(mpu_irq[dev]);
-       if (mpu_irq_cfg == INVALID_IRQ) {
-               printk(KERN_ERR "sscape: Invalid IRQ %d\n", mpu_irq[dev]);
-               return -ENXIO;
-       }
+       int val;
+       const char *name;
 
        /*
         * Grab IO ports that we will need to probe so that we
@@ -1098,41 +982,51 @@ static int __devinit create_sscape(int dev, struct snd_card *card)
        }
 
        spin_lock_init(&sscape->lock);
-       spin_lock_init(&sscape->fwlock);
        sscape->io_res = io_res;
        sscape->wss_res = wss_res;
        sscape->io_base = port[dev];
 
        if (!detect_sscape(sscape, wss_port[dev])) {
-               printk(KERN_ERR "sscape: hardware not detected at 0x%x\n", sscape->io_base);
+               printk(KERN_ERR "sscape: hardware not detected at 0x%x\n",
+                       sscape->io_base);
                err = -ENODEV;
                goto _release_dma;
        }
 
-       printk(KERN_INFO "sscape: hardware detected at 0x%x, using IRQ %d, DMA %d\n",
-                        sscape->io_base, irq[dev], dma[dev]);
+       switch (sscape->type) {
+       case MEDIA_FX:
+               name = "MediaFX/SoundFX";
+               break;
+       case SSCAPE:
+               name = "Soundscape";
+               break;
+       case SSCAPE_PNP:
+               name = "Soundscape PnP";
+               break;
+       case SSCAPE_VIVO:
+               name = "Soundscape VIVO";
+               break;
+       default:
+               name = "unknown Soundscape";
+               break;
+       }
 
-       if (sscape->type != SSCAPE_VIVO) {
-               /*
-                * Now create the hardware-specific device so that we can
-                * load the microcode into the on-board processor.
-                * We cannot use the MPU-401 MIDI system until this firmware
-                * has been loaded into the card.
-                */
-               err = snd_hwdep_new(card, "MC68EC000", 0, &(sscape->hw));
-               if (err < 0) {
-                       printk(KERN_ERR "sscape: Failed to create "
-                                       "firmware device\n");
-                       goto _release_dma;
-               }
-               strlcpy(sscape->hw->name, "SoundScape M68K",
-                       sizeof(sscape->hw->name));
-               sscape->hw->name[sizeof(sscape->hw->name) - 1] = '\0';
-               sscape->hw->iface = SNDRV_HWDEP_IFACE_SSCAPE;
-               sscape->hw->ops.open = sscape_hw_open;
-               sscape->hw->ops.release = sscape_hw_release;
-               sscape->hw->ops.ioctl = sscape_hw_ioctl;
-               sscape->hw->private_data = sscape;
+       printk(KERN_INFO "sscape: %s card detected at 0x%x, using IRQ %d, DMA %d\n",
+                        name, sscape->io_base, irq[dev], dma[dev]);
+
+       /*
+        * Check that the user didn't pass us garbage data ...
+        */
+       irq_cfg = get_irq_config(sscape->type, irq[dev]);
+       if (irq_cfg == INVALID_IRQ) {
+               snd_printk(KERN_ERR "sscape: Invalid IRQ %d\n", irq[dev]);
+               return -ENXIO;
+       }
+
+       mpu_irq_cfg = get_irq_config(sscape->type, mpu_irq[dev]);
+       if (mpu_irq_cfg == INVALID_IRQ) {
+               snd_printk(KERN_ERR "sscape: Invalid IRQ %d\n", mpu_irq[dev]);
+               return -ENXIO;
        }
 
        /*
@@ -1141,9 +1035,6 @@ static int __devinit create_sscape(int dev, struct snd_card *card)
         */
        spin_lock_irqsave(&sscape->lock, flags);
 
-       activate_ad1845_unsafe(sscape->io_base);
-
-       sscape_write_unsafe(sscape->io_base, GA_INTENA_REG, 0x00); /* disable */
        sscape_write_unsafe(sscape->io_base, GA_SMCFGA_REG, 0x2e);
        sscape_write_unsafe(sscape->io_base, GA_SMCFGB_REG, 0x00);
 
@@ -1151,15 +1042,23 @@ static int __devinit create_sscape(int dev, struct snd_card *card)
         * Enable and configure the DMA channels ...
         */
        sscape_write_unsafe(sscape->io_base, GA_DMACFG_REG, 0x50);
-       dma_cfg = (sscape->ic_type == IC_ODIE ? 0x70 : 0x40);
+       dma_cfg = (sscape->ic_type == IC_OPUS ? 0x40 : 0x70);
        sscape_write_unsafe(sscape->io_base, GA_DMAA_REG, dma_cfg);
        sscape_write_unsafe(sscape->io_base, GA_DMAB_REG, 0x20);
 
-       sscape_write_unsafe(sscape->io_base,
-                           GA_INTCFG_REG, 0xf0 | (mpu_irq_cfg << 2) | mpu_irq_cfg);
+       mpu_irq_cfg |= mpu_irq_cfg << 2;
+       val = sscape_read_unsafe(sscape->io_base, GA_HMCTL_REG) & 0xF7;
+       if (joystick[dev])
+               val |= 8;
+       sscape_write_unsafe(sscape->io_base, GA_HMCTL_REG, val | 0x10);
+       sscape_write_unsafe(sscape->io_base, GA_INTCFG_REG, 0xf0 | mpu_irq_cfg);
        sscape_write_unsafe(sscape->io_base,
                            GA_CDCFG_REG, 0x09 | DMA_8BIT
                            | (dma[dev] << 4) | (irq_cfg << 1));
+       /*
+        * Enable the master IRQ ...
+        */
+       sscape_write_unsafe(sscape->io_base, GA_INTENA_REG, 0x80);
 
        spin_unlock_irqrestore(&sscape->lock, flags);
 
@@ -1170,32 +1069,56 @@ static int __devinit create_sscape(int dev, struct snd_card *card)
        err = create_ad1845(card, wss_port[dev], irq[dev],
                            dma[dev], dma2[dev]);
        if (err < 0) {
-               printk(KERN_ERR "sscape: No AD1845 device at 0x%lx, IRQ %d\n",
-                      wss_port[dev], irq[dev]);
+               snd_printk(KERN_ERR
+                               "sscape: No AD1845 device at 0x%lx, IRQ %d\n",
+                               wss_port[dev], irq[dev]);
                goto _release_dma;
        }
+       strcpy(card->driver, "SoundScape");
+       strcpy(card->shortname, name);
+       snprintf(card->longname, sizeof(card->longname),
+                "%s at 0x%lx, IRQ %d, DMA1 %d, DMA2 %d\n",
+                name, sscape->chip->port, sscape->chip->irq,
+                sscape->chip->dma1, sscape->chip->dma2);
+
 #define MIDI_DEVNUM  0
        if (sscape->type != SSCAPE_VIVO) {
-               err = create_mpu401(card, MIDI_DEVNUM, port[dev], mpu_irq[dev]);
-               if (err < 0) {
-                       printk(KERN_ERR "sscape: Failed to create "
-                                       "MPU-401 device at 0x%lx\n",
-                                       port[dev]);
-                       goto _release_dma;
-               }
+               err = sscape_upload_bootblock(card);
+               if (err >= 0)
+                       err = sscape_upload_microcode(card, err);
 
-               /*
-                * Enable the master IRQ ...
-                */
-               sscape_write(sscape, GA_INTENA_REG, 0x80);
+               if (err == 0) {
+                       err = create_mpu401(card, MIDI_DEVNUM, port[dev],
+                                           mpu_irq[dev]);
+                       if (err < 0) {
+                               snd_printk(KERN_ERR "sscape: Failed to create "
+                                               "MPU-401 device at 0x%lx\n",
+                                               port[dev]);
+                               goto _release_dma;
+                       }
 
-               /*
-                * Initialize mixer
-                */
-               sscape->midi_vol = 0;
-               host_write_ctrl_unsafe(sscape->io_base, CMD_SET_MIDI_VOL, 100);
-               host_write_ctrl_unsafe(sscape->io_base, 0, 100);
-               host_write_ctrl_unsafe(sscape->io_base, CMD_XXX_MIDI_VOL, 100);
+                       /*
+                        * Initialize mixer
+                        */
+                       spin_lock_irqsave(&sscape->lock, flags);
+                       sscape->midi_vol = 0;
+                       host_write_ctrl_unsafe(sscape->io_base,
+                                               CMD_SET_MIDI_VOL, 100);
+                       host_write_ctrl_unsafe(sscape->io_base,
+                                               sscape->midi_vol, 100);
+                       host_write_ctrl_unsafe(sscape->io_base,
+                                               CMD_XXX_MIDI_VOL, 100);
+                       host_write_ctrl_unsafe(sscape->io_base,
+                                               sscape->midi_vol, 100);
+                       host_write_ctrl_unsafe(sscape->io_base,
+                                               CMD_SET_EXTMIDI, 100);
+                       host_write_ctrl_unsafe(sscape->io_base,
+                                               0, 100);
+                       host_write_ctrl_unsafe(sscape->io_base, CMD_ACK, 100);
+
+                       set_midi_mode_unsafe(sscape->io_base);
+                       spin_unlock_irqrestore(&sscape->lock, flags);
+               }
        }
 
        /*
@@ -1231,7 +1154,8 @@ static int __devinit snd_sscape_match(struct device *pdev, unsigned int i)
            mpu_irq[i] == SNDRV_AUTO_IRQ ||
            dma[i] == SNDRV_AUTO_DMA) {
                printk(KERN_INFO
-                      "sscape: insufficient parameters, need IO, IRQ, MPU-IRQ and DMA\n");
+                      "sscape: insufficient parameters, "
+                      "need IO, IRQ, MPU-IRQ and DMA\n");
                return 0;
        }
 
@@ -1253,13 +1177,15 @@ static int __devinit snd_sscape_probe(struct device *pdev, unsigned int dev)
        sscape->type = SSCAPE;
 
        dma[dev] &= 0x03;
+       snd_card_set_dev(card, pdev);
+
        ret = create_sscape(dev, card);
        if (ret < 0)
                goto _release_card;
 
-       snd_card_set_dev(card, pdev);
-       if ((ret = snd_card_register(card)) < 0) {
-               printk(KERN_ERR "sscape: Failed to register sound card\n");
+       ret = snd_card_register(card);
+       if (ret < 0) {
+               snd_printk(KERN_ERR "sscape: Failed to register sound card\n");
                goto _release_card;
        }
        dev_set_drvdata(pdev, card);
@@ -1311,36 +1237,20 @@ static int __devinit sscape_pnp_detect(struct pnp_card_link *pcard,
         * Allow this function to fail *quietly* if all the ISA PnP
         * devices were configured using module parameters instead.
         */
-       if ((idx = get_next_autoindex(idx)) >= SNDRV_CARDS)
+       idx = get_next_autoindex(idx);
+       if (idx >= SNDRV_CARDS)
                return -ENOSPC;
 
-       /*
-        * We have found a candidate ISA PnP card. Now we
-        * have to check that it has the devices that we
-        * expect it to have.
-        *
-        * We will NOT try and autoconfigure all of the resources
-        * needed and then activate the card as we are assuming that
-        * has already been done at boot-time using /proc/isapnp.
-        * We shall simply try to give each active card the resources
-        * that it wants. This is a sensible strategy for a modular
-        * system where unused modules are unloaded regularly.
-        *
-        * This strategy is utterly useless if we compile the driver
-        * into the kernel, of course.
-        */
-       // printk(KERN_INFO "sscape: %s\n", card->name);
-
        /*
         * Check that we still have room for another sound card ...
         */
        dev = pnp_request_card_device(pcard, pid->devs[0].id, NULL);
-       if (! dev)
+       if (!dev)
                return -ENODEV;
 
        if (!pnp_is_active(dev)) {
                if (pnp_activate_dev(dev) < 0) {
-                       printk(KERN_INFO "sscape: device is inactive\n");
+                       snd_printk(KERN_INFO "sscape: device is inactive\n");
                        return -EBUSY;
                }
        }
@@ -1378,14 +1288,15 @@ static int __devinit sscape_pnp_detect(struct pnp_card_link *pcard,
                wss_port[idx] = pnp_port_start(dev, 1);
                dma2[idx] = pnp_dma(dev, 1);
        }
+       snd_card_set_dev(card, &pcard->card->dev);
 
        ret = create_sscape(idx, card);
        if (ret < 0)
                goto _release_card;
 
-       snd_card_set_dev(card, &pcard->card->dev);
-       if ((ret = snd_card_register(card)) < 0) {
-               printk(KERN_ERR "sscape: Failed to register sound card\n");
+       ret = snd_card_register(card);
+       if (ret < 0) {
+               snd_printk(KERN_ERR "sscape: Failed to register sound card\n");
                goto _release_card;
        }
 
index 5d2ba1b..2ba1897 100644 (file)
@@ -2198,84 +2198,61 @@ EXPORT_SYMBOL(snd_wss_put_double);
 static const DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0);
 static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0);
 static const DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0);
+static const DECLARE_TLV_DB_SCALE(db_scale_4bit, -4500, 300, 0);
 
-static struct snd_kcontrol_new snd_ad1848_controls[] = {
-WSS_DOUBLE("PCM Playback Switch", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT,
-          7, 7, 1, 1),
+static struct snd_kcontrol_new snd_wss_controls[] = {
+WSS_DOUBLE("PCM Playback Switch", 0,
+               CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
 WSS_DOUBLE_TLV("PCM Playback Volume", 0,
-              CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1,
-              db_scale_6bit),
+               CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1,
+               db_scale_6bit),
 WSS_DOUBLE("Aux Playback Switch", 0,
-          CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
+               CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
 WSS_DOUBLE_TLV("Aux Playback Volume", 0,
-              CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1,
-              db_scale_5bit_12db_max),
+               CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1,
+               db_scale_5bit_12db_max),
 WSS_DOUBLE("Aux Playback Switch", 1,
-          CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
+               CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
 WSS_DOUBLE_TLV("Aux Playback Volume", 1,
-              CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1,
-              db_scale_5bit_12db_max),
+               CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1,
+               db_scale_5bit_12db_max),
 WSS_DOUBLE_TLV("Capture Volume", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT,
                0, 0, 15, 0, db_scale_rec_gain),
 {
-       .name = "Capture Source",
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .name = "Capture Source",
        .info = snd_wss_info_mux,
        .get = snd_wss_get_mux,
        .put = snd_wss_put_mux,
 },
-WSS_SINGLE("Loopback Capture Switch", 0, CS4231_LOOPBACK, 0, 1, 0),
-WSS_SINGLE_TLV("Loopback Capture Volume", 0, CS4231_LOOPBACK, 1, 63, 0,
-              db_scale_6bit),
-};
-
-static struct snd_kcontrol_new snd_wss_controls[] = {
-WSS_DOUBLE("PCM Playback Switch", 0,
-               CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
-WSS_DOUBLE("PCM Playback Volume", 0,
-               CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1),
+WSS_DOUBLE("Mic Boost", 0,
+               CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 5, 5, 1, 0),
+WSS_SINGLE("Loopback Capture Switch", 0,
+               CS4231_LOOPBACK, 0, 1, 0),
+WSS_SINGLE_TLV("Loopback Capture Volume", 0, CS4231_LOOPBACK, 2, 63, 1,
+               db_scale_6bit),
 WSS_DOUBLE("Line Playback Switch", 0,
                CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),
-WSS_DOUBLE("Line Playback Volume", 0,
-               CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1),
-WSS_DOUBLE("Aux Playback Switch", 0,
-               CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
-WSS_DOUBLE("Aux Playback Volume", 0,
-               CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1),
-WSS_DOUBLE("Aux Playback Switch", 1,
-               CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
-WSS_DOUBLE("Aux Playback Volume", 1,
-               CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1),
+WSS_DOUBLE_TLV("Line Playback Volume", 0,
+               CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1,
+               db_scale_5bit_12db_max),
 WSS_SINGLE("Mono Playback Switch", 0,
                CS4231_MONO_CTRL, 7, 1, 1),
-WSS_SINGLE("Mono Playback Volume", 0,
-               CS4231_MONO_CTRL, 0, 15, 1),
+WSS_SINGLE_TLV("Mono Playback Volume", 0,
+               CS4231_MONO_CTRL, 0, 15, 1,
+               db_scale_4bit),
 WSS_SINGLE("Mono Output Playback Switch", 0,
                CS4231_MONO_CTRL, 6, 1, 1),
 WSS_SINGLE("Mono Output Playback Bypass", 0,
                CS4231_MONO_CTRL, 5, 1, 0),
-WSS_DOUBLE("Capture Volume", 0,
-               CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0, 15, 0),
-{
-       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-       .name = "Capture Source",
-       .info = snd_wss_info_mux,
-       .get = snd_wss_get_mux,
-       .put = snd_wss_put_mux,
-},
-WSS_DOUBLE("Mic Boost", 0,
-               CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 5, 5, 1, 0),
-WSS_SINGLE("Loopback Capture Switch", 0,
-               CS4231_LOOPBACK, 0, 1, 0),
-WSS_SINGLE("Loopback Capture Volume", 0,
-               CS4231_LOOPBACK, 2, 63, 1)
 };
 
 static struct snd_kcontrol_new snd_opti93x_controls[] = {
 WSS_DOUBLE("Master Playback Switch", 0,
                OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 7, 7, 1, 1),
-WSS_DOUBLE("Master Playback Volume", 0,
-               OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 1, 1, 31, 1),
+WSS_DOUBLE_TLV("Master Playback Volume", 0,
+               OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 1, 1, 31, 1,
+               db_scale_6bit),
 WSS_DOUBLE("PCM Playback Switch", 0,
                CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
 WSS_DOUBLE("PCM Playback Volume", 0,
@@ -2334,22 +2311,21 @@ int snd_wss_mixer(struct snd_wss *chip)
                        if (err < 0)
                                return err;
                }
-       else if (chip->hardware & WSS_HW_AD1848_MASK)
-               for (idx = 0; idx < ARRAY_SIZE(snd_ad1848_controls); idx++) {
-                       err = snd_ctl_add(card,
-                                       snd_ctl_new1(&snd_ad1848_controls[idx],
-                                                    chip));
-                       if (err < 0)
-                               return err;
-               }
-       else
-               for (idx = 0; idx < ARRAY_SIZE(snd_wss_controls); idx++) {
+       else {
+               int count = ARRAY_SIZE(snd_wss_controls);
+
+               /* Use only the first 11 entries on AD1848 */
+               if (chip->hardware & WSS_HW_AD1848_MASK)
+                       count = 11;
+
+               for (idx = 0; idx < count; idx++) {
                        err = snd_ctl_add(card,
                                        snd_ctl_new1(&snd_wss_controls[idx],
                                                     chip));
                        if (err < 0)
                                return err;
                }
+       }
        return 0;
 }
 EXPORT_SYMBOL(snd_wss_mixer);
index bcf2a06..135a2b7 100644 (file)
@@ -287,18 +287,6 @@ config SOUND_DMAP
 
          Say Y unless you have 16MB or more RAM or a PCI sound card.
 
-config SOUND_SSCAPE
-       tristate "Ensoniq SoundScape support"
-       help
-         Answer Y if you have a sound card based on the Ensoniq SoundScape
-         chipset. Such cards are being manufactured at least by Ensoniq, Spea
-         and Reveal (Reveal makes also other cards).
-
-         If you compile the driver into the kernel, you have to add
-         "sscape=<io>,<irq>,<dma>,<mpuio>,<mpuirq>" to the kernel command
-         line.
-
-
 config SOUND_VMIDI
        tristate "Loopback MIDI device support"
        help
index e0ae4d4..567b8a7 100644 (file)
@@ -13,7 +13,6 @@ obj-$(CONFIG_SOUND_SH_DAC_AUDIO)      += sh_dac_audio.o
 obj-$(CONFIG_SOUND_AEDSP16)    += aedsp16.o
 obj-$(CONFIG_SOUND_PSS)                += pss.o ad1848.o mpu401.o
 obj-$(CONFIG_SOUND_TRIX)       += trix.o ad1848.o sb_lib.o uart401.o
-obj-$(CONFIG_SOUND_SSCAPE)     += sscape.o ad1848.o mpu401.o
 obj-$(CONFIG_SOUND_MSS)                += ad1848.o
 obj-$(CONFIG_SOUND_PAS)                += pas2.o sb.o sb_lib.o uart401.o
 obj-$(CONFIG_SOUND_SB)         += sb.o sb_lib.o uart401.o
index b2ed875..4153752 100644 (file)
@@ -164,9 +164,6 @@ static ssize_t dac_audio_write(struct file *file, const char *buf, size_t count,
        int free;
        int nbytes;
 
-       if (count < 0)
-               return -EINVAL;
-
        if (!count) {
                dac_audio_sync();
                return 0;
diff --git a/sound/oss/sscape.c b/sound/oss/sscape.c
deleted file mode 100644 (file)
index 30c36d1..0000000
+++ /dev/null
@@ -1,1480 +0,0 @@
-/*
- * sound/oss/sscape.c
- *
- * Low level driver for Ensoniq SoundScape
- *
- *
- * Copyright (C) by Hannu Savolainen 1993-1997
- *
- * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
- * Version 2 (June 1991). See the "COPYING" file distributed with this software
- * for more info.
- *
- *
- * Thomas Sailer       : ioctl code reworked (vmalloc/vfree removed)
- * Sergey Smitienko    : ensoniq p'n'p support
- * Christoph Hellwig   : adapted to module_init/module_exit
- * Bartlomiej Zolnierkiewicz : added __init to attach_sscape()
- * Chris Rankin                : Specify that this module owns the coprocessor
- * Arnaldo C. de Melo  : added missing restore_flags in sscape_pnp_upload_file
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-
-#include "sound_config.h"
-#include "sound_firmware.h"
-
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/fcntl.h>
-#include <linux/ctype.h>
-#include <linux/stddef.h>
-#include <linux/kmod.h>
-#include <asm/dma.h>
-#include <asm/io.h>
-#include <linux/wait.h>
-#include <linux/slab.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/proc_fs.h>
-#include <linux/mm.h>
-#include <linux/spinlock.h>
-
-#include "coproc.h"
-
-#include "ad1848.h"
-#include "mpu401.h"
-
-/*
- *    I/O ports
- */
-#define MIDI_DATA       0
-#define MIDI_CTRL       1
-#define HOST_CTRL       2
-#define TX_READY       0x02
-#define RX_READY       0x01
-#define HOST_DATA       3
-#define ODIE_ADDR       4
-#define ODIE_DATA       5
-
-/*
- *    Indirect registers
- */
-
-#define GA_INTSTAT_REG 0
-#define GA_INTENA_REG  1
-#define GA_DMAA_REG    2
-#define GA_DMAB_REG    3
-#define GA_INTCFG_REG  4
-#define GA_DMACFG_REG  5
-#define GA_CDCFG_REG   6
-#define GA_SMCFGA_REG  7
-#define GA_SMCFGB_REG  8
-#define GA_HMCTL_REG   9
-
-/*
- * DMA channel identifiers (A and B)
- */
-
-#define SSCAPE_DMA_A   0
-#define SSCAPE_DMA_B   1
-
-#define PORT(name)     (devc->base+name)
-
-/*
- * Host commands recognized by the OBP microcode
- */
-#define CMD_GEN_HOST_ACK       0x80
-#define CMD_GEN_MPU_ACK                0x81
-#define CMD_GET_BOARD_TYPE     0x82
-#define CMD_SET_CONTROL                0x88    /* Old firmware only */
-#define CMD_GET_CONTROL                0x89    /* Old firmware only */
-#define CTL_MASTER_VOL         0
-#define CTL_MIC_MODE           2
-#define CTL_SYNTH_VOL          4
-#define CTL_WAVE_VOL           7
-#define CMD_SET_EXTMIDI                0x8a
-#define CMD_GET_EXTMIDI                0x8b
-#define CMD_SET_MT32           0x8c
-#define CMD_GET_MT32           0x8d
-
-#define CMD_ACK                        0x80
-
-#define        IC_ODIE                 1
-#define        IC_OPUS                 2
-
-typedef struct sscape_info
-{
-       int     base, irq, dma;
-       
-       int     codec, codec_irq;       /* required to setup pnp cards*/
-       int     codec_type;
-       int     ic_type;
-       char*   raw_buf;
-       unsigned long   raw_buf_phys;
-       int     buffsize;               /* -------------------------- */
-       spinlock_t lock;
-       int     ok;     /* Properly detected */
-       int     failed;
-       int     dma_allocated;
-       int     codec_audiodev;
-       int     opened;
-       int     *osp;
-       int     my_audiodev;
-} sscape_info;
-
-static struct sscape_info adev_info = {
-       0
-};
-
-static struct sscape_info *devc = &adev_info;
-static int sscape_mididev = -1;
-
-/* Some older cards have assigned interrupt bits differently than new ones */
-static char valid_interrupts_old[] = {
-       9, 7, 5, 15
-};
-
-static char valid_interrupts_new[] = {
-       9, 5, 7, 10
-};
-
-static char *valid_interrupts = valid_interrupts_new;
-
-/*
- *     See the bottom of the driver. This can be set by spea =0/1.
- */
-#ifdef REVEAL_SPEA
-static char old_hardware = 1;
-#else
-static char old_hardware;
-#endif
-
-static void sleep(unsigned howlong)
-{
-       current->state = TASK_INTERRUPTIBLE;
-       schedule_timeout(howlong);
-}
-
-static unsigned char sscape_read(struct sscape_info *devc, int reg)
-{
-       unsigned long flags;
-       unsigned char val;
-
-       spin_lock_irqsave(&devc->lock,flags);
-       outb(reg, PORT(ODIE_ADDR));
-       val = inb(PORT(ODIE_DATA));
-       spin_unlock_irqrestore(&devc->lock,flags);
-       return val;
-}
-
-static void __sscape_write(int reg, int data)
-{
-       outb(reg, PORT(ODIE_ADDR));
-       outb(data, PORT(ODIE_DATA));
-}
-
-static void sscape_write(struct sscape_info *devc, int reg, int data)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&devc->lock,flags);
-       __sscape_write(reg, data);
-       spin_unlock_irqrestore(&devc->lock,flags);
-}
-
-static unsigned char sscape_pnp_read_codec(sscape_info* devc, unsigned char reg)
-{
-       unsigned char res;
-       unsigned long flags;
-
-       spin_lock_irqsave(&devc->lock,flags);
-       outb( reg, devc -> codec);
-       res = inb (devc -> codec + 1);
-       spin_unlock_irqrestore(&devc->lock,flags);
-       return res;
-
-}
-
-static void sscape_pnp_write_codec(sscape_info* devc, unsigned char reg, unsigned char data)
-{
-       unsigned long flags;
-       
-       spin_lock_irqsave(&devc->lock,flags);
-       outb( reg, devc -> codec);
-       outb( data, devc -> codec + 1);
-       spin_unlock_irqrestore(&devc->lock,flags);
-}
-
-static void host_open(struct sscape_info *devc)
-{
-       outb((0x00), PORT(HOST_CTRL));  /* Put the board to the host mode */
-}
-
-static void host_close(struct sscape_info *devc)
-{
-       outb((0x03), PORT(HOST_CTRL));  /* Put the board to the MIDI mode */
-}
-
-static int host_write(struct sscape_info *devc, unsigned char *data, int count)
-{
-       unsigned long flags;
-       int i, timeout_val;
-
-       spin_lock_irqsave(&devc->lock,flags);
-       /*
-        * Send the command and data bytes
-        */
-
-       for (i = 0; i < count; i++)
-       {
-               for (timeout_val = 10000; timeout_val > 0; timeout_val--)
-                       if (inb(PORT(HOST_CTRL)) & TX_READY)
-                               break;
-
-               if (timeout_val <= 0)
-               {
-                               spin_unlock_irqrestore(&devc->lock,flags);
-                           return 0;
-               }
-               outb(data[i], PORT(HOST_DATA));
-       }
-       spin_unlock_irqrestore(&devc->lock,flags);
-       return 1;
-}
-
-static int host_read(struct sscape_info *devc)
-{
-       unsigned long flags;
-       int timeout_val;
-       unsigned char data;
-
-       spin_lock_irqsave(&devc->lock,flags);
-       /*
-        * Read a byte
-        */
-
-       for (timeout_val = 10000; timeout_val > 0; timeout_val--)
-               if (inb(PORT(HOST_CTRL)) & RX_READY)
-                       break;
-
-       if (timeout_val <= 0)
-       {
-               spin_unlock_irqrestore(&devc->lock,flags);
-               return -1;
-       }
-       data = inb(PORT(HOST_DATA));
-       spin_unlock_irqrestore(&devc->lock,flags);
-       return data;
-}
-
-#if 0 /* unused */
-static int host_command1(struct sscape_info *devc, int cmd)
-{
-       unsigned char buf[10];
-       buf[0] = (unsigned char) (cmd & 0xff);
-       return host_write(devc, buf, 1);
-}
-#endif /* unused */
-
-
-static int host_command2(struct sscape_info *devc, int cmd, int parm1)
-{
-       unsigned char buf[10];
-
-       buf[0] = (unsigned char) (cmd & 0xff);
-       buf[1] = (unsigned char) (parm1 & 0xff);
-
-       return host_write(devc, buf, 2);
-}
-
-static int host_command3(struct sscape_info *devc, int cmd, int parm1, int parm2)
-{
-       unsigned char buf[10];
-
-       buf[0] = (unsigned char) (cmd & 0xff);
-       buf[1] = (unsigned char) (parm1 & 0xff);
-       buf[2] = (unsigned char) (parm2 & 0xff);
-       return host_write(devc, buf, 3);
-}
-
-static void set_mt32(struct sscape_info *devc, int value)
-{
-       host_open(devc);
-       host_command2(devc, CMD_SET_MT32, value ? 1 : 0);
-       if (host_read(devc) != CMD_ACK)
-       {
-               /* printk( "SNDSCAPE: Setting MT32 mode failed\n"); */
-       }
-       host_close(devc);
-}
-
-static void set_control(struct sscape_info *devc, int ctrl, int value)
-{
-       host_open(devc);
-       host_command3(devc, CMD_SET_CONTROL, ctrl, value);
-       if (host_read(devc) != CMD_ACK)
-       {
-               /* printk( "SNDSCAPE: Setting control (%d) failed\n",  ctrl); */
-       }
-       host_close(devc);
-}
-
-static void do_dma(struct sscape_info *devc, int dma_chan, unsigned long buf, int blk_size, int mode)
-{
-       unsigned char temp;
-
-       if (dma_chan != SSCAPE_DMA_A)
-       {
-               printk(KERN_WARNING "soundscape: Tried to use DMA channel  != A. Why?\n");
-               return;
-       }
-       audio_devs[devc->codec_audiodev]->flags &= ~DMA_AUTOMODE;
-       DMAbuf_start_dma(devc->codec_audiodev, buf, blk_size, mode);
-       audio_devs[devc->codec_audiodev]->flags |= DMA_AUTOMODE;
-
-       temp = devc->dma << 4;  /* Setup DMA channel select bits */
-       if (devc->dma <= 3)
-               temp |= 0x80;   /* 8 bit DMA channel */
-
-       temp |= 1;              /* Trigger DMA */
-       sscape_write(devc, GA_DMAA_REG, temp);
-       temp &= 0xfe;           /* Clear DMA trigger */
-       sscape_write(devc, GA_DMAA_REG, temp);
-}
-
-static int verify_mpu(struct sscape_info *devc)
-{
-       /*
-        * The SoundScape board could be in three modes (MPU, 8250 and host).
-        * If the card is not in the MPU mode, enabling the MPU driver will
-        * cause infinite loop (the driver believes that there is always some
-        * received data in the buffer.
-        *
-        * Detect this by looking if there are more than 10 received MIDI bytes
-        * (0x00) in the buffer.
-        */
-
-       int i;
-
-       for (i = 0; i < 10; i++)
-       {
-               if (inb(devc->base + HOST_CTRL) & 0x80)
-                       return 1;
-
-               if (inb(devc->base) != 0x00)
-                       return 1;
-       }
-       printk(KERN_WARNING "SoundScape: The device is not in the MPU-401 mode\n");
-       return 0;
-}
-
-static int sscape_coproc_open(void *dev_info, int sub_device)
-{
-       if (sub_device == COPR_MIDI)
-       {
-               set_mt32(devc, 0);
-               if (!verify_mpu(devc))
-                       return -EIO;
-       }
-       return 0;
-}
-
-static void sscape_coproc_close(void *dev_info, int sub_device)
-{
-       struct sscape_info *devc = dev_info;
-       unsigned long   flags;
-
-       spin_lock_irqsave(&devc->lock,flags);
-       if (devc->dma_allocated)
-       {
-               __sscape_write(GA_DMAA_REG, 0x20);      /* DMA channel disabled */
-               devc->dma_allocated = 0;
-       }
-       spin_unlock_irqrestore(&devc->lock,flags);
-       return;
-}
-
-static void sscape_coproc_reset(void *dev_info)
-{
-}
-
-static int sscape_download_boot(struct sscape_info *devc, unsigned char *block, int size, int flag)
-{
-       unsigned long flags;
-       unsigned char temp;
-       volatile int done, timeout_val;
-       static unsigned char codec_dma_bits;
-
-       if (flag & CPF_FIRST)
-       {
-               /*
-                * First block. Have to allocate DMA and to reset the board
-                * before continuing.
-                */
-
-               spin_lock_irqsave(&devc->lock,flags);
-               codec_dma_bits = sscape_read(devc, GA_CDCFG_REG);
-
-               if (devc->dma_allocated == 0)
-                       devc->dma_allocated = 1;
-
-               spin_unlock_irqrestore(&devc->lock,flags);
-
-               sscape_write(devc, GA_HMCTL_REG, 
-                       (temp = sscape_read(devc, GA_HMCTL_REG)) & 0x3f);       /*Reset */
-
-               for (timeout_val = 10000; timeout_val > 0; timeout_val--)
-                       sscape_read(devc, GA_HMCTL_REG);        /* Delay */
-
-               /* Take board out of reset */
-               sscape_write(devc, GA_HMCTL_REG,
-                       (temp = sscape_read(devc, GA_HMCTL_REG)) | 0x80);
-       }
-       /*
-        * Transfer one code block using DMA
-        */
-       if (audio_devs[devc->codec_audiodev]->dmap_out->raw_buf == NULL)
-       {
-               printk(KERN_WARNING "soundscape: DMA buffer not available\n");
-               return 0;
-       }
-       memcpy(audio_devs[devc->codec_audiodev]->dmap_out->raw_buf, block, size);
-
-       spin_lock_irqsave(&devc->lock,flags);
-       
-       /******** INTERRUPTS DISABLED NOW ********/
-       
-       do_dma(devc, SSCAPE_DMA_A,
-              audio_devs[devc->codec_audiodev]->dmap_out->raw_buf_phys,
-              size, DMA_MODE_WRITE);
-
-       /*
-        * Wait until transfer completes.
-        */
-       
-       done = 0;
-       timeout_val = 30;
-       while (!done && timeout_val-- > 0)
-       {
-               int resid;
-
-               if (HZ / 50)
-                       sleep(HZ / 50);
-               clear_dma_ff(devc->dma);
-               if ((resid = get_dma_residue(devc->dma)) == 0)
-                       done = 1;
-       }
-
-       spin_unlock_irqrestore(&devc->lock,flags);
-       if (!done)
-               return 0;
-
-       if (flag & CPF_LAST)
-       {
-               /*
-                * Take the board out of reset
-                */
-               outb((0x00), PORT(HOST_CTRL));
-               outb((0x00), PORT(MIDI_CTRL));
-
-               temp = sscape_read(devc, GA_HMCTL_REG);
-               temp |= 0x40;
-               sscape_write(devc, GA_HMCTL_REG, temp); /* Kickstart the board */
-
-               /*
-                * Wait until the ODB wakes up
-                */
-               spin_lock_irqsave(&devc->lock,flags);
-               done = 0;
-               timeout_val = 5 * HZ;
-               while (!done && timeout_val-- > 0)
-               {
-                       unsigned char x;
-                       
-                       sleep(1);
-                       x = inb(PORT(HOST_DATA));
-                       if (x == 0xff || x == 0xfe)             /* OBP startup acknowledge */
-                       {
-                               DDB(printk("Soundscape: Acknowledge = %x\n", x));
-                               done = 1;
-                       }
-               }
-               sscape_write(devc, GA_CDCFG_REG, codec_dma_bits);
-
-               spin_unlock_irqrestore(&devc->lock,flags);
-               if (!done)
-               {
-                       printk(KERN_ERR "soundscape: The OBP didn't respond after code download\n");
-                       return 0;
-               }
-               spin_lock_irqsave(&devc->lock,flags);
-               done = 0;
-               timeout_val = 5 * HZ;
-               while (!done && timeout_val-- > 0)
-               {
-                       sleep(1);
-                       if (inb(PORT(HOST_DATA)) == 0xfe)       /* Host startup acknowledge */
-                               done = 1;
-               }
-               spin_unlock_irqrestore(&devc->lock,flags);
-               if (!done)
-               {
-                       printk(KERN_ERR "soundscape: OBP Initialization failed.\n");
-                       return 0;
-               }
-               printk(KERN_INFO "SoundScape board initialized OK\n");
-               set_control(devc, CTL_MASTER_VOL, 100);
-               set_control(devc, CTL_SYNTH_VOL, 100);
-
-#ifdef SSCAPE_DEBUG3
-               /*
-                * Temporary debugging aid. Print contents of the registers after
-                * downloading the code.
-                */
-               {
-                       int i;
-
-                       for (i = 0; i < 13; i++)
-                               printk("I%d = %02x (new value)\n", i, sscape_read(devc, i));
-               }
-#endif
-
-       }
-       return 1;
-}
-
-static int download_boot_block(void *dev_info, copr_buffer * buf)
-{
-       if (buf->len <= 0 || buf->len > sizeof(buf->data))
-               return -EINVAL;
-
-       if (!sscape_download_boot(devc, buf->data, buf->len, buf->flags))
-       {
-               printk(KERN_ERR "soundscape: Unable to load microcode block to the OBP.\n");
-               return -EIO;
-       }
-       return 0;
-}
-
-static int sscape_coproc_ioctl(void *dev_info, unsigned int cmd, void __user *arg, int local)
-{
-       copr_buffer *buf;
-       int err;
-
-       switch (cmd) 
-       {
-               case SNDCTL_COPR_RESET:
-                       sscape_coproc_reset(dev_info);
-                       return 0;
-
-               case SNDCTL_COPR_LOAD:
-                       buf = (copr_buffer *) vmalloc(sizeof(copr_buffer));
-                       if (buf == NULL)
-                               return -ENOSPC;
-                       if (copy_from_user(buf, arg, sizeof(copr_buffer))) 
-                       {
-                               vfree(buf);
-                               return -EFAULT;
-                       }
-                       err = download_boot_block(dev_info, buf);
-                       vfree(buf);
-                       return err;
-               
-               default:
-                       return -EINVAL;
-       }
-}
-
-static coproc_operations sscape_coproc_operations =
-{
-       "SoundScape M68K",
-       THIS_MODULE,
-       sscape_coproc_open,
-       sscape_coproc_close,
-       sscape_coproc_ioctl,
-       sscape_coproc_reset,
-       &adev_info
-};
-
-static struct resource *sscape_ports;
-static int sscape_is_pnp;
-
-static void __init attach_sscape(struct address_info *hw_config)
-{
-#ifndef SSCAPE_REGS
-       /*
-        * Config register values for Spea/V7 Media FX and Ensoniq S-2000.
-        * These values are card
-        * dependent. If you have another SoundScape based card, you have to
-        * find the correct values. Do the following:
-        *  - Compile this driver with SSCAPE_DEBUG1 defined.
-        *  - Shut down and power off your machine.
-        *  - Boot with DOS so that the SSINIT.EXE program is run.
-        *  - Warm boot to {Linux|SYSV|BSD} and write down the lines displayed
-        *    when detecting the SoundScape.
-        *  - Modify the following list to use the values printed during boot.
-        *    Undefine the SSCAPE_DEBUG1
-        */
-#define SSCAPE_REGS { \
-/* I0 */       0x00, \
-/* I1 */       0xf0, /* Note! Ignored. Set always to 0xf0 */ \
-/* I2 */       0x20, /* Note! Ignored. Set always to 0x20 */ \
-/* I3 */       0x20, /* Note! Ignored. Set always to 0x20 */ \
-/* I4 */       0xf5, /* Ignored */ \
-/* I5 */       0x10, \
-/* I6 */       0x00, \
-/* I7 */       0x2e, /* I7 MEM config A. Likely to vary between models */ \
-/* I8 */       0x00, /* I8 MEM config B. Likely to vary between models */ \
-/* I9 */       0x40 /* Ignored */ \
-       }
-#endif
-
-       unsigned long   flags;
-       static unsigned char regs[10] = SSCAPE_REGS;
-
-       int i, irq_bits = 0xff;
-
-       if (old_hardware)
-       {
-               valid_interrupts = valid_interrupts_old;
-               conf_printf("Ensoniq SoundScape (old)", hw_config);
-       }
-       else
-               conf_printf("Ensoniq SoundScape", hw_config);
-
-       for (i = 0; i < 4; i++)
-       {
-               if (hw_config->irq == valid_interrupts[i])
-               {
-                       irq_bits = i;
-                       break;
-               }
-       }
-       if (hw_config->irq > 15 || (regs[4] = irq_bits == 0xff))
-       {
-               printk(KERN_ERR "Invalid IRQ%d\n", hw_config->irq);
-               release_region(devc->base, 2);
-               release_region(devc->base + 2, 6);
-               if (sscape_is_pnp)
-                       release_region(devc->codec, 2);
-               return;
-       }
-       
-       if (!sscape_is_pnp) {
-       
-               spin_lock_irqsave(&devc->lock,flags);
-               /* Host interrupt enable */
-               sscape_write(devc, 1, 0xf0);    /* All interrupts enabled */
-               /* DMA A status/trigger register */
-               sscape_write(devc, 2, 0x20);    /* DMA channel disabled */
-               /* DMA B status/trigger register */
-               sscape_write(devc, 3, 0x20);    /* DMA channel disabled */
-               /* Host interrupt config reg */
-               sscape_write(devc, 4, 0xf0 | (irq_bits << 2) | irq_bits);
-               /* Don't destroy CD-ROM DMA config bits (0xc0) */
-               sscape_write(devc, 5, (regs[5] & 0x3f) | (sscape_read(devc, 5) & 0xc0));
-               /* CD-ROM config (WSS codec actually) */
-               sscape_write(devc, 6, regs[6]);
-               sscape_write(devc, 7, regs[7]);
-               sscape_write(devc, 8, regs[8]);
-               /* Master control reg. Don't modify CR-ROM bits. Disable SB emul */
-               sscape_write(devc, 9, (sscape_read(devc, 9) & 0xf0) | 0x08);
-               spin_unlock_irqrestore(&devc->lock,flags);
-       }
-#ifdef SSCAPE_DEBUG2
-       /*
-        * Temporary debugging aid. Print contents of the registers after
-        * changing them.
-        */
-       {
-               int i;
-
-               for (i = 0; i < 13; i++)
-                       printk("I%d = %02x (new value)\n", i, sscape_read(devc, i));
-       }
-#endif
-
-       if (probe_mpu401(hw_config, sscape_ports))
-               hw_config->always_detect = 1;
-       hw_config->name = "SoundScape";
-
-       hw_config->irq *= -1;   /* Negative value signals IRQ sharing */
-       attach_mpu401(hw_config, THIS_MODULE);
-       hw_config->irq *= -1;   /* Restore it */
-
-       if (hw_config->slots[1] != -1)  /* The MPU driver installed itself */
-       {
-               sscape_mididev = hw_config->slots[1];
-               midi_devs[hw_config->slots[1]]->coproc = &sscape_coproc_operations;
-       }
-       sscape_write(devc, GA_INTENA_REG, 0x80);        /* Master IRQ enable */
-       devc->ok = 1;
-       devc->failed = 0;
-}
-
-static int detect_ga(sscape_info * devc)
-{
-       unsigned char save;
-
-       DDB(printk("Entered Soundscape detect_ga(%x)\n", devc->base));
-
-       /*
-        * First check that the address register of "ODIE" is
-        * there and that it has exactly 4 writable bits.
-        * First 4 bits
-        */
-       
-       if ((save = inb(PORT(ODIE_ADDR))) & 0xf0)
-       {
-               DDB(printk("soundscape: Detect error A\n"));
-               return 0;
-       }
-       outb((0x00), PORT(ODIE_ADDR));
-       if (inb(PORT(ODIE_ADDR)) != 0x00)
-       {
-               DDB(printk("soundscape: Detect error B\n"));
-               return 0;
-       }
-       outb((0xff), PORT(ODIE_ADDR));
-       if (inb(PORT(ODIE_ADDR)) != 0x0f)
-       {
-               DDB(printk("soundscape: Detect error C\n"));
-               return 0;
-       }
-       outb((save), PORT(ODIE_ADDR));
-
-       /*
-        * Now verify that some indirect registers return zero on some bits.
-        * This may break the driver with some future revisions of "ODIE" but...
-        */
-
-       if (sscape_read(devc, 0) & 0x0c)
-       {
-               DDB(printk("soundscape: Detect error D (%x)\n", sscape_read(devc, 0)));
-               return 0;
-       }
-       if (sscape_read(devc, 1) & 0x0f)
-       {
-               DDB(printk("soundscape: Detect error E\n"));
-               return 0;
-       }
-       if (sscape_read(devc, 5) & 0x0f)
-       {
-               DDB(printk("soundscape: Detect error F\n"));
-               return 0;
-       }
-       return 1;
-}
-
-static int sscape_read_host_ctrl(sscape_info* devc)
-{
-       return host_read(devc);
-}
-
-static void sscape_write_host_ctrl2(sscape_info *devc, int a, int b)
-{
-       host_command2(devc, a, b);
-}
-
-static int sscape_alloc_dma(sscape_info *devc)
-{
-       char *start_addr, *end_addr;
-       int dma_pagesize;
-       int sz, size;
-       struct page *page;
-
-       if (devc->raw_buf != NULL) return 0;    /* Already done */
-       dma_pagesize = (devc->dma < 4) ? (64 * 1024) : (128 * 1024);
-       devc->raw_buf = NULL;
-       devc->buffsize = 8192*4;
-       if (devc->buffsize > dma_pagesize) devc->buffsize = dma_pagesize;
-       start_addr = NULL;
-       /*
-        * Now loop until we get a free buffer. Try to get smaller buffer if
-        * it fails. Don't accept smaller than 8k buffer for performance
-        * reasons.
-        */
-       while (start_addr == NULL && devc->buffsize > PAGE_SIZE) {
-               for (sz = 0, size = PAGE_SIZE; size < devc->buffsize; sz++, size <<= 1);
-               devc->buffsize = PAGE_SIZE * (1 << sz);
-               start_addr = (char *) __get_free_pages(GFP_ATOMIC|GFP_DMA, sz);
-               if (start_addr == NULL) devc->buffsize /= 2;
-       }
-
-       if (start_addr == NULL) {
-               printk(KERN_ERR "sscape pnp init error: Couldn't allocate DMA buffer\n");
-               return 0;
-       } else {
-               /* make some checks */
-               end_addr = start_addr + devc->buffsize - 1;             
-               /* now check if it fits into the same dma-pagesize */
-
-               if (((long) start_addr & ~(dma_pagesize - 1)) != ((long) end_addr & ~(dma_pagesize - 1))
-                   || end_addr >= (char *) (MAX_DMA_ADDRESS)) {
-                       printk(KERN_ERR "sscape pnp: Got invalid address 0x%lx for %db DMA-buffer\n", (long) start_addr, devc->buffsize);
-                       return 0;
-               }
-       }
-       devc->raw_buf = start_addr;
-       devc->raw_buf_phys = virt_to_bus(start_addr);
-
-       for (page = virt_to_page(start_addr); page <= virt_to_page(end_addr); page++)
-               SetPageReserved(page);
-       return 1;
-}
-
-static void sscape_free_dma(sscape_info *devc)
-{
-       int sz, size;
-       unsigned long start_addr, end_addr;
-       struct page *page;
-
-       if (devc->raw_buf == NULL) return;
-       for (sz = 0, size = PAGE_SIZE; size < devc->buffsize; sz++, size <<= 1);
-       start_addr = (unsigned long) devc->raw_buf;
-       end_addr = start_addr + devc->buffsize;
-
-       for (page = virt_to_page(start_addr); page <= virt_to_page(end_addr); page++)
-               ClearPageReserved(page);
-
-       free_pages((unsigned long) devc->raw_buf, sz);
-       devc->raw_buf = NULL;
-}
-
-/* Intel version !!!!!!!!! */
-
-static int sscape_start_dma(int chan, unsigned long physaddr, int count, int dma_mode)
-{
-       unsigned long flags;
-
-       flags = claim_dma_lock();
-       disable_dma(chan);
-       clear_dma_ff(chan);
-       set_dma_mode(chan, dma_mode);
-       set_dma_addr(chan, physaddr);
-       set_dma_count(chan, count);
-       enable_dma(chan);
-       release_dma_lock(flags);
-       return 0;
-}
-
-static void sscape_pnp_start_dma(sscape_info* devc, int arg )
-{
-       int reg;
-       if (arg == 0) reg = 2;
-       else reg = 3;
-
-       sscape_write(devc, reg, sscape_read( devc, reg) | 0x01);
-       sscape_write(devc, reg, sscape_read( devc, reg) & 0xFE);
-}
-
-static int sscape_pnp_wait_dma (sscape_info* devc, int arg )
-{
-       int             reg;
-       unsigned long   i;
-       unsigned char   d;
-
-       if (arg == 0) reg = 2;
-       else reg = 3;
-
-       sleep ( 1 );
-       i = 0;
-       do {
-               d = sscape_read(devc, reg) & 1;
-               if ( d == 1)  break;
-               i++;
-       } while (i < 500000);
-       d = sscape_read(devc, reg) & 1; 
-       return d;
-}
-
-static int     sscape_pnp_alloc_dma(sscape_info* devc)
-{
-       /* printk(KERN_INFO "sscape: requesting dma\n"); */
-       if (request_dma(devc -> dma, "sscape")) return 0;
-       /* printk(KERN_INFO "sscape: dma channel allocated\n"); */
-       if (!sscape_alloc_dma(devc)) {
-               free_dma(devc -> dma);
-               return 0;
-       };
-       return 1;
-}
-
-static void    sscape_pnp_free_dma(sscape_info* devc)
-{
-       sscape_free_dma( devc);
-       free_dma(devc -> dma ); 
-       /* printk(KERN_INFO "sscape: dma released\n"); */
-}
-
-static int     sscape_pnp_upload_file(sscape_info* devc, char* fn)
-{      
-       int             done = 0;
-       int             timeout_val;
-       char*           data,*dt;
-       int             len,l;
-       unsigned long   flags;
-
-       sscape_write( devc, 9, sscape_read(devc, 9 )  & 0x3F );
-       sscape_write( devc, 2, (devc -> dma << 4) | 0x80 );
-       sscape_write( devc, 3, 0x20 );
-       sscape_write( devc, 9, sscape_read( devc, 9 )  | 0x80 );
-       
-       len = mod_firmware_load(fn, &data);
-       if (len == 0) {
-                   printk(KERN_ERR "sscape: file not found: %s\n", fn);
-                   return 0;
-       }
-       dt = data;
-       spin_lock_irqsave(&devc->lock,flags);
-       while ( len > 0 ) {
-               if (len > devc -> buffsize) l = devc->buffsize;
-               else l = len;
-               len -= l;               
-               memcpy(devc->raw_buf, dt, l); dt += l;
-               sscape_start_dma(devc->dma, devc->raw_buf_phys, l, 0x48);
-               sscape_pnp_start_dma ( devc, 0 );
-               if (sscape_pnp_wait_dma ( devc, 0 ) == 0) {
-                       spin_unlock_irqrestore(&devc->lock,flags);
-                       return 0;
-               }
-       }
-       
-       spin_unlock_irqrestore(&devc->lock,flags);
-       vfree(data);
-       
-       outb(0, devc -> base + 2);
-       outb(0, devc -> base);
-
-       sscape_write ( devc, 9, sscape_read( devc, 9 ) | 0x40);
-
-       timeout_val = 5 * HZ; 
-       while (!done && timeout_val-- > 0)
-       {
-               unsigned char x;
-               sleep(1);
-               x = inb( devc -> base + 3);
-               if (x == 0xff || x == 0xfe)             /* OBP startup acknowledge */
-               {
-                       //printk(KERN_ERR "Soundscape: Acknowledge = %x\n", x);
-                       done = 1;
-               }
-       }
-       timeout_val = 5 * HZ;
-       done = 0;
-       while (!done && timeout_val-- > 0)
-       {
-               unsigned char x;
-               sleep(1);
-               x = inb( devc -> base + 3);
-               if (x == 0xfe)          /* OBP startup acknowledge */
-               {
-                       //printk(KERN_ERR "Soundscape: Acknowledge = %x\n", x);
-                       done = 1;
-               }
-       }
-
-       if ( !done ) printk(KERN_ERR "soundscape: OBP Initialization failed.\n");
-
-       sscape_write( devc, 2, devc->ic_type == IC_ODIE ? 0x70 : 0x40);
-       sscape_write( devc, 3, (devc -> dma << 4) + 0x80);
-       return 1;
-}
-
-static void __init sscape_pnp_init_hw(sscape_info* devc)
-{      
-       unsigned char midi_irq = 0, sb_irq = 0;
-       unsigned i;
-       static  char code_file_name[23] = "/sndscape/sndscape.cox";
-       
-       int sscape_joystic_enable       = 0x7f;
-       int sscape_mic_enable           = 0;
-       int sscape_ext_midi             = 0;            
-
-       if ( !sscape_pnp_alloc_dma(devc) ) {
-               printk(KERN_ERR "sscape: faild to allocate dma\n");
-               return;
-       }
-
-       for (i = 0; i < 4; i++) {
-               if ( devc -> irq   == valid_interrupts[i] ) 
-                       midi_irq = i;
-               if ( devc -> codec_irq == valid_interrupts[i] ) 
-                       sb_irq = i;
-       }
-
-       sscape_write( devc, 5, 0x50);
-       sscape_write( devc, 7, 0x2e);
-       sscape_write( devc, 8, 0x00);
-
-       sscape_write( devc, 2, devc->ic_type == IC_ODIE ? 0x70 : 0x40);
-       sscape_write( devc, 3, ( devc -> dma << 4) | 0x80);
-
-       sscape_write (devc, 4, 0xF0 | (midi_irq<<2) | midi_irq);
-
-       i = 0x10; //sscape_read(devc, 9) & (devc->ic_type == IC_ODIE ? 0xf0 : 0xc0);
-       if (sscape_joystic_enable) i |= 8;
-       
-       sscape_write (devc, 9, i);
-       sscape_write (devc, 6, 0x80);
-       sscape_write (devc, 1, 0x80);
-
-       if (devc -> codec_type == 2) {
-               sscape_pnp_write_codec( devc, 0x0C, 0x50);
-               sscape_pnp_write_codec( devc, 0x10, sscape_pnp_read_codec( devc, 0x10) & 0x3F);
-               sscape_pnp_write_codec( devc, 0x11, sscape_pnp_read_codec( devc, 0x11) | 0xC0);
-               sscape_pnp_write_codec( devc, 29, 0x20);
-       }
-
-       if (sscape_pnp_upload_file(devc, "/sndscape/scope.cod") == 0 ) {
-               printk(KERN_ERR "sscape: faild to upload file /sndscape/scope.cod\n");
-               sscape_pnp_free_dma(devc);
-               return;
-       }
-
-       i = sscape_read_host_ctrl( devc );
-       
-       if ( (i & 0x0F) >  7 ) {
-               printk(KERN_ERR "sscape: scope.cod faild\n");
-               sscape_pnp_free_dma(devc);
-               return;
-       }
-       if ( i & 0x10 ) sscape_write( devc, 7, 0x2F);
-       code_file_name[21] = (char) ( i & 0x0F) + 0x30;
-       if (sscape_pnp_upload_file( devc, code_file_name) == 0) {
-               printk(KERN_ERR "sscape: faild to upload file %s\n", code_file_name);
-               sscape_pnp_free_dma(devc);
-               return;
-       }
-       
-       if (devc->ic_type != IC_ODIE) {
-               sscape_pnp_write_codec( devc, 10, (sscape_pnp_read_codec(devc, 10) & 0x7f) |
-                ( sscape_mic_enable == 0 ? 0x00 : 0x80) );
-       }
-       sscape_write_host_ctrl2( devc, 0x84, 0x64 );  /* MIDI volume */
-       sscape_write_host_ctrl2( devc, 0x86, 0x64 );  /* MIDI volume?? */
-       sscape_write_host_ctrl2( devc, 0x8A, sscape_ext_midi);
-
-       sscape_pnp_write_codec ( devc, 6, 0x3f ); //WAV_VOL
-       sscape_pnp_write_codec ( devc, 7, 0x3f ); //WAV_VOL
-       sscape_pnp_write_codec ( devc, 2, 0x1F ); //WD_CDXVOLL
-       sscape_pnp_write_codec ( devc, 3, 0x1F ); //WD_CDXVOLR
-
-       if (devc -> codec_type == 1) {
-               sscape_pnp_write_codec ( devc, 4, 0x1F );
-               sscape_pnp_write_codec ( devc, 5, 0x1F );
-               sscape_write_host_ctrl2( devc, 0x88, sscape_mic_enable);
-       } else {
-               int t;
-               sscape_pnp_write_codec ( devc, 0x10, 0x1F << 1);
-               sscape_pnp_write_codec ( devc, 0x11, 0xC0 | (0x1F << 1));
-
-               t = sscape_pnp_read_codec( devc, 0x00) & 0xDF;
-               if ( (sscape_mic_enable == 0)) t |= 0;
-               else t |= 0x20;
-               sscape_pnp_write_codec ( devc, 0x00, t);
-               t = sscape_pnp_read_codec( devc, 0x01) & 0xDF;
-               if ( (sscape_mic_enable == 0) ) t |= 0;
-               else t |= 0x20;
-               sscape_pnp_write_codec ( devc, 0x01, t);
-               sscape_pnp_write_codec ( devc, 0x40 | 29 , 0x20);
-               outb(0, devc -> codec);
-       }
-       if (devc -> ic_type == IC_OPUS ) {
-               int i = sscape_read( devc, 9 );
-               sscape_write( devc, 9, i | 3 );
-               sscape_write( devc, 3, 0x40);
-
-               if (request_region(0x228, 1, "sscape setup junk")) {
-                       outb(0, 0x228);
-                       release_region(0x228,1);
-               }
-               sscape_write( devc, 3, (devc -> dma << 4) | 0x80);
-               sscape_write( devc, 9, i );
-       }
-       
-       host_close ( devc );
-       sscape_pnp_free_dma(devc);
-}
-
-static int __init detect_sscape_pnp(sscape_info* devc)
-{
-       long     i, irq_bits = 0xff;
-       unsigned int d;
-
-       DDB(printk("Entered detect_sscape_pnp(%x)\n", devc->base));
-
-       if (!request_region(devc->codec, 2, "sscape codec")) {
-               printk(KERN_ERR "detect_sscape_pnp: port %x is not free\n", devc->codec);       
-               return 0;
-       }
-
-       if ((inb(devc->base + 2) & 0x78) != 0)
-               goto fail;
-
-       d = inb ( devc -> base + 4) & 0xF0;
-       if (d & 0x80)
-               goto fail;
-       
-       if (d == 0) {
-               devc->codec_type = 1;
-               devc->ic_type = IC_ODIE;
-       } else if ( (d & 0x60) != 0) {
-               devc->codec_type = 2;
-               devc->ic_type = IC_OPUS;
-       } else if ( (d & 0x40) != 0) {  /* WTF? */
-               devc->codec_type = 2;
-               devc->ic_type = IC_ODIE;
-       } else
-               goto fail;
-       
-       sscape_is_pnp = 1;
-               
-       outb(0xFA, devc -> base+4);
-       if  ((inb( devc -> base+4) & 0x9F) != 0x0A)
-               goto fail;
-       outb(0xFE, devc -> base+4);
-       if  ( (inb(devc -> base+4) & 0x9F) != 0x0E)
-               goto fail;
-       if  ( (inb(devc -> base+5) & 0x9F) != 0x0E)
-               goto fail;
-
-       if (devc->codec_type == 2) {
-               if (devc->codec != devc->base + 8) {
-                       printk("soundscape warning: incorrect codec port specified\n");
-                       goto fail;
-               }
-               d = 0x10 | (sscape_read(devc, 9)  & 0xCF);
-               sscape_write(devc, 9, d);
-               sscape_write(devc, 6, 0x80);
-       } else {
-               //todo: check codec is not base + 8
-       }
-
-       d  = (sscape_read(devc, 9) & 0x3F) | 0xC0;
-       sscape_write(devc, 9, d);
-
-       for (i = 0; i < 550000; i++)
-               if ( !(inb(devc -> codec) & 0x80) ) break;
-
-       d = inb(devc -> codec);
-       if (d & 0x80)
-               goto fail;
-       if ( inb(devc -> codec + 2) == 0xFF)
-               goto fail;
-
-       sscape_write(devc, 9, sscape_read(devc, 9)  & 0x3F );
-
-       d  = inb(devc -> codec) & 0x80;
-       if ( d == 0) {
-               printk(KERN_INFO "soundscape: hardware detected\n");
-               valid_interrupts = valid_interrupts_new;
-       } else  {
-               printk(KERN_INFO "soundscape: board looks like media fx\n");
-               valid_interrupts = valid_interrupts_old;
-               old_hardware = 1;
-       }
-
-       sscape_write( devc, 9, 0xC0 | (sscape_read(devc, 9)  & 0x3F) );
-
-       for (i = 0; i < 550000; i++)
-               if ( !(inb(devc -> codec) & 0x80)) 
-                       break;
-               
-       sscape_pnp_init_hw(devc);
-
-       for (i = 0; i < 4; i++)
-       {
-               if (devc->codec_irq == valid_interrupts[i]) {
-                       irq_bits = i;
-                       break;
-               }
-       }       
-       sscape_write(devc, GA_INTENA_REG, 0x00);
-       sscape_write(devc, GA_DMACFG_REG, 0x50);
-       sscape_write(devc, GA_DMAA_REG, 0x70);
-       sscape_write(devc, GA_DMAB_REG, 0x20);
-       sscape_write(devc, GA_INTCFG_REG, 0xf0);
-       sscape_write(devc, GA_CDCFG_REG, 0x89 | (devc->dma << 4) | (irq_bits << 1));
-
-       sscape_pnp_write_codec( devc, 0, sscape_pnp_read_codec( devc, 0) | 0x20);
-       sscape_pnp_write_codec( devc, 0, sscape_pnp_read_codec( devc, 1) | 0x20);
-
-       return 1;
-fail:
-       release_region(devc->codec, 2);
-       return 0;
-}
-
-static int __init probe_sscape(struct address_info *hw_config)
-{
-       devc->base = hw_config->io_base;
-       devc->irq = hw_config->irq;
-       devc->dma = hw_config->dma;
-       devc->osp = hw_config->osp;
-
-#ifdef SSCAPE_DEBUG1
-       /*
-        * Temporary debugging aid. Print contents of the registers before
-        * changing them.
-        */
-       {
-               int i;
-
-               for (i = 0; i < 13; i++)
-                       printk("I%d = %02x (old value)\n", i, sscape_read(devc, i));
-       }
-#endif
-       devc->failed = 1;
-
-       sscape_ports = request_region(devc->base, 2, "mpu401");
-       if (!sscape_ports)
-               return 0;
-
-       if (!request_region(devc->base + 2, 6, "SoundScape")) {
-               release_region(devc->base, 2);
-               return 0;
-       }
-
-       if (!detect_ga(devc)) {
-               if (detect_sscape_pnp(devc))
-                       return 1;
-               release_region(devc->base, 2);
-               release_region(devc->base + 2, 6);
-               return 0;
-       }
-
-       if (old_hardware)       /* Check that it's really an old Spea/Reveal card. */
-       {
-               unsigned char   tmp;
-               int             cc;
-
-               if (!((tmp = sscape_read(devc, GA_HMCTL_REG)) & 0xc0))
-               {
-                       sscape_write(devc, GA_HMCTL_REG, tmp | 0x80);
-                       for (cc = 0; cc < 200000; ++cc)
-                               inb(devc->base + ODIE_ADDR);
-               }
-       }
-       return 1;
-}
-
-static int __init init_ss_ms_sound(struct address_info *hw_config)
-{
-       int i, irq_bits = 0xff;
-       int ad_flags = 0;
-       struct resource *ports;
-       
-       if (devc->failed)
-       {
-               printk(KERN_ERR "soundscape: Card not detected\n");
-               return 0;
-       }
-       if (devc->ok == 0)
-       {
-               printk(KERN_ERR "soundscape: Invalid initialization order.\n");
-               return 0;
-       }
-       for (i = 0; i < 4; i++)
-       {
-               if (hw_config->irq == valid_interrupts[i])
-               {
-                       irq_bits = i;
-                       break;
-               }
-       }
-       if (irq_bits == 0xff) {
-               printk(KERN_ERR "soundscape: Invalid MSS IRQ%d\n", hw_config->irq);
-               return 0;
-       }
-       
-       if (old_hardware)
-               ad_flags = 0x12345677;  /* Tell that we may have a CS4248 chip (Spea-V7 Media FX) */
-       else if (sscape_is_pnp)
-               ad_flags = 0x87654321;  /* Tell that we have a soundscape pnp with 1845 chip */
-
-       ports = request_region(hw_config->io_base, 4, "ad1848");
-       if (!ports) {
-               printk(KERN_ERR "soundscape: ports busy\n");
-               return 0;
-       }
-
-       if (!ad1848_detect(ports, &ad_flags, hw_config->osp)) {
-               release_region(hw_config->io_base, 4);
-               return 0;
-       }
-
-       if (!sscape_is_pnp)  /*pnp is already setup*/
-       {
-               /*
-                * Setup the DMA polarity.
-                */
-               sscape_write(devc, GA_DMACFG_REG, 0x50);
-       
-               /*
-                * Take the gate-array off of the DMA channel.
-                */
-               sscape_write(devc, GA_DMAB_REG, 0x20);
-       
-               /*
-                * Init the AD1848 (CD-ROM) config reg.
-                */
-               sscape_write(devc, GA_CDCFG_REG, 0x89 | (hw_config->dma << 4) | (irq_bits << 1));
-       }
-       
-       if (hw_config->irq == devc->irq)
-               printk(KERN_WARNING "soundscape: Warning! The WSS mode can't share IRQ with MIDI\n");
-                               
-       hw_config->slots[0] = ad1848_init(
-                       sscape_is_pnp ? "SoundScape" : "SoundScape PNP",
-                       ports,
-                       hw_config->irq,
-                       hw_config->dma,
-                       hw_config->dma,
-                       0,
-                       devc->osp,
-                       THIS_MODULE);
-
-                                         
-       if (hw_config->slots[0] != -1)  /* The AD1848 driver installed itself */
-       {
-               audio_devs[hw_config->slots[0]]->coproc = &sscape_coproc_operations;
-               devc->codec_audiodev = hw_config->slots[0];
-               devc->my_audiodev = hw_config->slots[0];
-
-               /* Set proper routings here (what are they) */
-               AD1848_REROUTE(SOUND_MIXER_LINE1, SOUND_MIXER_LINE);
-       }
-               
-#ifdef SSCAPE_DEBUG5
-       /*
-        * Temporary debugging aid. Print contents of the registers
-        * after the AD1848 device has been initialized.
-        */
-       {
-               int i;
-
-               for (i = 0; i < 13; i++)
-                       printk("I%d = %02x\n", i, sscape_read(devc, i));
-       }
-#endif
-       return 1;
-}
-
-static void __exit unload_sscape(struct address_info *hw_config)
-{
-       release_region(devc->base + 2, 6);
-       unload_mpu401(hw_config);
-       if (sscape_is_pnp)
-               release_region(devc->codec, 2);
-}
-
-static void __exit unload_ss_ms_sound(struct address_info *hw_config)
-{
-       ad1848_unload(hw_config->io_base,
-                     hw_config->irq,
-                     devc->dma,
-                     devc->dma,
-                     0);
-       sound_unload_audiodev(hw_config->slots[0]);
-}
-
-static struct address_info cfg;
-static struct address_info cfg_mpu;
-
-static int __initdata spea = -1;
-static int mss = 0;
-static int __initdata dma = -1;
-static int __initdata irq = -1;
-static int __initdata io = -1;
-static int __initdata mpu_irq = -1;
-static int __initdata mpu_io = -1;
-
-module_param(dma, int, 0);
-module_param(irq, int, 0);
-module_param(io, int, 0);
-module_param(spea, int, 0);            /* spea=0/1 set the old_hardware */
-module_param(mpu_irq, int, 0);
-module_param(mpu_io, int, 0);
-module_param(mss, int, 0);
-
-static int __init init_sscape(void)
-{
-       printk(KERN_INFO "Soundscape driver Copyright (C) by Hannu Savolainen 1993-1996\n");
-       
-       cfg.irq = irq;
-       cfg.dma = dma;
-       cfg.io_base = io;
-
-       cfg_mpu.irq = mpu_irq;
-       cfg_mpu.io_base = mpu_io;
-       /* WEH - Try to get right dma channel */
-        cfg_mpu.dma = dma;
-       
-       devc->codec = cfg.io_base;
-       devc->codec_irq = cfg.irq;
-       devc->codec_type = 0;
-       devc->ic_type = 0;
-       devc->raw_buf = NULL;
-       spin_lock_init(&devc->lock);
-
-       if (cfg.dma == -1 || cfg.irq == -1 || cfg.io_base == -1) {
-               printk(KERN_ERR "DMA, IRQ, and IO port must be specified.\n");
-               return -EINVAL;
-       }
-       
-       if (cfg_mpu.irq == -1 && cfg_mpu.io_base != -1) {
-               printk(KERN_ERR "MPU_IRQ must be specified if MPU_IO is set.\n");
-               return -EINVAL;
-       }
-       
-       if(spea != -1) {
-               old_hardware = spea;
-               printk(KERN_INFO "Forcing %s hardware support.\n",
-                       spea?"new":"old");
-       }       
-       if (probe_sscape(&cfg_mpu) == 0)
-               return -ENODEV;
-
-       attach_sscape(&cfg_mpu);
-       
-       mss = init_ss_ms_sound(&cfg);
-
-       return 0;
-}
-
-static void __exit cleanup_sscape(void)
-{
-       if (mss)
-               unload_ss_ms_sound(&cfg);
-       unload_sscape(&cfg_mpu);
-}
-
-module_init(init_sscape);
-module_exit(cleanup_sscape);
-
-#ifndef MODULE
-static int __init setup_sscape(char *str)
-{
-       /* io, irq, dma, mpu_io, mpu_irq */
-       int ints[6];
-       
-       str = get_options(str, ARRAY_SIZE(ints), ints);
-       
-       io      = ints[1];
-       irq     = ints[2];
-       dma     = ints[3];
-       mpu_io  = ints[4];
-       mpu_irq = ints[5];
-
-       return 1;
-}
-
-__setup("sscape=", setup_sscape);
-#endif
-MODULE_LICENSE("GPL");
index c62b7d1..15523e6 100644 (file)
@@ -304,7 +304,7 @@ static void snd_ca0106_proc_reg_write32(struct snd_info_entry *entry,
         while (!snd_info_get_line(buffer, line, sizeof(line))) {
                 if (sscanf(line, "%x %x", &reg, &val) != 2)
                         continue;
-                if ((reg < 0x40) && (reg >=0) && (val <= 0xffffffff) ) {
+               if (reg < 0x40 && val <= 0xffffffff) {
                        spin_lock_irqsave(&emu->emu_lock, flags);
                        outl(val, emu->port + (reg & 0xfffffffc));
                        spin_unlock_irqrestore(&emu->emu_lock, flags);
@@ -405,7 +405,7 @@ static void snd_ca0106_proc_reg_write(struct snd_info_entry *entry,
         while (!snd_info_get_line(buffer, line, sizeof(line))) {
                 if (sscanf(line, "%x %x %x", &reg, &channel_id, &val) != 3)
                         continue;
-                if ((reg < 0x80) && (reg >=0) && (val <= 0xffffffff) && (channel_id >=0) && (channel_id <= 3) )
+               if (reg < 0x80 && val <= 0xffffffff && channel_id <= 3)
                         snd_ca0106_ptr_write(emu, reg, channel_id, val);
         }
 }
index 7545464..cb65bd0 100644 (file)
@@ -240,7 +240,7 @@ static int select_rom(unsigned int pitch)
        } else if (pitch == 0x02000000) {
                /* pitch == 2 */
                return 3;
-       } else if (pitch >= 0x0 && pitch <= 0x08000000) {
+       } else if (pitch <= 0x08000000) {
                /* 0 <= pitch <= 8 */
                return 0;
        } else {
index 36e08bd..6b8ae7b 100644 (file)
@@ -1040,8 +1040,7 @@ static void snd_emu10k1x_proc_reg_write(struct snd_info_entry *entry,
                if (sscanf(line, "%x %x %x", &reg, &channel_id, &val) != 3)
                        continue;
 
-               if ((reg < 0x49) && (reg >= 0) && (val <= 0xffffffff) 
-                   && (channel_id >= 0) && (channel_id <= 2) )
+               if (reg < 0x49 && val <= 0xffffffff && channel_id <= 2)
                        snd_emu10k1x_ptr_write(emu, reg, channel_id, val);
        }
 }
index 216f974..baa7cd5 100644 (file)
@@ -451,7 +451,7 @@ static void snd_emu_proc_io_reg_write(struct snd_info_entry *entry,
        while (!snd_info_get_line(buffer, line, sizeof(line))) {
                if (sscanf(line, "%x %x", &reg, &val) != 2)
                        continue;
-               if ((reg < 0x40) && (reg >= 0) && (val <= 0xffffffff) ) {
+               if (reg < 0x40 && val <= 0xffffffff) {
                        spin_lock_irqsave(&emu->emu_lock, flags);
                        outl(val, emu->port + (reg & 0xfffffffc));
                        spin_unlock_irqrestore(&emu->emu_lock, flags);
@@ -527,7 +527,7 @@ static void snd_emu_proc_ptr_reg_write(struct snd_info_entry *entry,
        while (!snd_info_get_line(buffer, line, sizeof(line))) {
                if (sscanf(line, "%x %x %x", &reg, &channel_id, &val) != 3)
                        continue;
-               if ((reg < 0xa0) && (reg >= 0) && (val <= 0xffffffff) && (channel_id >= 0) && (channel_id <= 3) )
+               if (reg < 0xa0 && val <= 0xffffffff && channel_id <= 3)
                        snd_ptr_write(emu, iobase, reg, channel_id, val);
        }
 }
index c1a5aa1..5ef7080 100644 (file)
@@ -256,7 +256,7 @@ int snd_emu1010_fpga_write(struct snd_emu10k1 * emu, u32 reg, u32 value)
        if (reg > 0x3f)
                return 1;
        reg += 0x40; /* 0x40 upwards are registers. */
-       if (value < 0 || value > 0x3f) /* 0 to 0x3f are values */
+       if (value > 0x3f) /* 0 to 0x3f are values */
                return 1;
        spin_lock_irqsave(&emu->emu_lock, flags);
        outl(reg, emu->port + A_IOCFG);
index 0b8dcb5..35606ae 100644 (file)
@@ -85,7 +85,7 @@ static int tlv320aic23_write(struct snd_soc_codec *codec, unsigned int reg,
         * of data into val
         */
 
-       if ((reg < 0 || reg > 9) && (reg != 15)) {
+       if (reg > 9 && reg != 15) {
                printk(KERN_WARNING "%s Invalid register R%u\n", __func__, reg);
                return -1;
        }
index 99f3376..00cd54c 100644 (file)
@@ -66,6 +66,28 @@ static int us122l_create_usbmidi(struct snd_card *card)
                                             iface, &quirk);
 }
 
+static int us144_create_usbmidi(struct snd_card *card)
+{
+       static struct snd_usb_midi_endpoint_info quirk_data = {
+               .out_ep = 4,
+               .in_ep = 3,
+               .out_cables =   0x001,
+               .in_cables =    0x001
+       };
+       static struct snd_usb_audio_quirk quirk = {
+               .vendor_name =  "US144",
+               .product_name = NAME_ALLCAPS,
+               .ifnum =        0,
+               .type = QUIRK_MIDI_US122L,
+               .data = &quirk_data
+       };
+       struct usb_device *dev = US122L(card)->chip.dev;
+       struct usb_interface *iface = usb_ifnum_to_if(dev, 0);
+
+       return snd_usb_create_midi_interface(&US122L(card)->chip,
+                                            iface, &quirk);
+}
+
 /*
  * Wrapper for usb_control_msg().
  * Allocates a temp buffer to prevent dmaing from/to the stack.
@@ -171,6 +193,11 @@ static int usb_stream_hwdep_open(struct snd_hwdep *hw, struct file *file)
 
        if (!us122l->first)
                us122l->first = file;
+
+       if (us122l->chip.dev->descriptor.idProduct == USB_ID_US144) {
+               iface = usb_ifnum_to_if(us122l->chip.dev, 0);
+               usb_autopm_get_interface(iface);
+       }
        iface = usb_ifnum_to_if(us122l->chip.dev, 1);
        usb_autopm_get_interface(iface);
        return 0;
@@ -179,8 +206,14 @@ static int usb_stream_hwdep_open(struct snd_hwdep *hw, struct file *file)
 static int usb_stream_hwdep_release(struct snd_hwdep *hw, struct file *file)
 {
        struct us122l   *us122l = hw->private_data;
-       struct usb_interface *iface = usb_ifnum_to_if(us122l->chip.dev, 1);
+       struct usb_interface *iface;
        snd_printdd(KERN_DEBUG "%p %p\n", hw, file);
+
+       if (us122l->chip.dev->descriptor.idProduct == USB_ID_US144) {
+               iface = usb_ifnum_to_if(us122l->chip.dev, 0);
+               usb_autopm_put_interface(iface);
+       }
+       iface = usb_ifnum_to_if(us122l->chip.dev, 1);
        usb_autopm_put_interface(iface);
        if (us122l->first == file)
                us122l->first = NULL;
@@ -443,6 +476,13 @@ static bool us122l_create_card(struct snd_card *card)
        int err;
        struct us122l *us122l = US122L(card);
 
+       if (us122l->chip.dev->descriptor.idProduct == USB_ID_US144) {
+               err = usb_set_interface(us122l->chip.dev, 0, 1);
+               if (err) {
+                       snd_printk(KERN_ERR "usb_set_interface error \n");
+                       return false;
+               }
+       }
        err = usb_set_interface(us122l->chip.dev, 1, 1);
        if (err) {
                snd_printk(KERN_ERR "usb_set_interface error \n");
@@ -455,7 +495,10 @@ static bool us122l_create_card(struct snd_card *card)
        if (!us122l_start(us122l, 44100, 256))
                return false;
 
-       err = us122l_create_usbmidi(card);
+       if (us122l->chip.dev->descriptor.idProduct == USB_ID_US144)
+               err = us144_create_usbmidi(card);
+       else
+               err = us122l_create_usbmidi(card);
        if (err < 0) {
                snd_printk(KERN_ERR "us122l_create_usbmidi error %i \n", err);
                us122l_stop(us122l);
@@ -542,6 +585,7 @@ static int us122l_usb_probe(struct usb_interface *intf,
                return err;
        }
 
+       usb_get_intf(usb_ifnum_to_if(device, 0));
        usb_get_dev(device);
        *cardp = card;
        return 0;
@@ -550,9 +594,16 @@ static int us122l_usb_probe(struct usb_interface *intf,
 static int snd_us122l_probe(struct usb_interface *intf,
                            const struct usb_device_id *id)
 {
+       struct usb_device *device = interface_to_usbdev(intf);
        struct snd_card *card;
        int err;
 
+       if (device->descriptor.idProduct == USB_ID_US144
+               && device->speed == USB_SPEED_HIGH) {
+               snd_printk(KERN_ERR "disable ehci-hcd to run US-144 \n");
+               return -ENODEV;
+       }
+
        snd_printdd(KERN_DEBUG"%p:%i\n",
                    intf, intf->cur_altsetting->desc.bInterfaceNumber);
        if (intf->cur_altsetting->desc.bInterfaceNumber != 1)
@@ -591,7 +642,8 @@ static void snd_us122l_disconnect(struct usb_interface *intf)
                snd_usbmidi_disconnect(p);
        }
 
-       usb_put_intf(intf);
+       usb_put_intf(usb_ifnum_to_if(us122l->chip.dev, 0));
+       usb_put_intf(usb_ifnum_to_if(us122l->chip.dev, 1));
        usb_put_dev(us122l->chip.dev);
 
        while (atomic_read(&us122l->mmap_count))
@@ -642,6 +694,13 @@ static int snd_us122l_resume(struct usb_interface *intf)
 
        mutex_lock(&us122l->mutex);
        /* needed, doesn't restart without: */
+       if (us122l->chip.dev->descriptor.idProduct == USB_ID_US144) {
+               err = usb_set_interface(us122l->chip.dev, 0, 1);
+               if (err) {
+                       snd_printk(KERN_ERR "usb_set_interface error \n");
+                       goto unlock;
+               }
+       }
        err = usb_set_interface(us122l->chip.dev, 1, 1);
        if (err) {
                snd_printk(KERN_ERR "usb_set_interface error \n");
@@ -675,11 +734,11 @@ static struct usb_device_id snd_us122l_usb_id_table[] = {
                .idVendor =     0x0644,
                .idProduct =    USB_ID_US122L
        },
-/*     { */            /* US-144 maybe works when @USB1.1. Untested. */
-/*             .match_flags =  USB_DEVICE_ID_MATCH_DEVICE, */
-/*             .idVendor =     0x0644, */
-/*             .idProduct =    USB_ID_US144 */
-/*     }, */
+       {       /* US-144 only works at USB1.1! Disable module ehci-hcd. */
+               .match_flags =  USB_DEVICE_ID_MATCH_DEVICE,
+               .idVendor =     0x0644,
+               .idProduct =    USB_ID_US144
+       },
        { /* terminator */ }
 };