patch-2.0.1 linux/drivers/sound/sscape.c

Next file: linux/drivers/sound/sys_timer.c
Previous file: linux/drivers/sound/soundvers.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.0.0/linux/drivers/sound/sscape.c linux/drivers/sound/sscape.c
@@ -4,27 +4,11 @@
  * Low level driver for Ensoniq Soundscape
  */
 /*
- * Copyright by Hannu Savolainen 1993-1996
+ * Copyright (C) by Hannu Savolainen 1993-1996
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer. 2.
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * USS/Lite for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * Version 2 (June 1991). See the "COPYING" file distributed with this software
+ * for more info.
  */
 #include <linux/config.h>
 
@@ -281,7 +265,7 @@
   host_command3 (devc, CMD_SET_CONTROL, ctrl, value);
   if (host_read (devc) != CMD_ACK)
     {
-      printk ("SNDSCAPE: Setting control (%d) failed\n", ctrl);
+      /* printk ("SNDSCAPE: Setting control (%d) failed\n", ctrl); */
     }
   host_close (devc);
 }
@@ -307,10 +291,10 @@
   static int      debug = 0;
 
   bits = sscape_read (devc, GA_INTSTAT_REG);
-  if ((sscape_sleep_flag.mode & WK_SLEEP))
+  if ((sscape_sleep_flag.flags & WK_SLEEP))
     {
       {
-	sscape_sleep_flag.mode = WK_WAKEUP;
+	sscape_sleep_flag.flags = WK_WAKEUP;
 	module_wake_up (&sscape_sleeper);
       };
     }
@@ -320,10 +304,10 @@
       printk ("SSCAPE: Host interrupt, data=%02x\n", host_read (devc));
     }
 
-#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
+#if defined(CONFIG_UART401) && defined(CONFIG_MIDI)
   if (bits & 0x01)
     {
-      mpuintr (irq, NULL, NULL);
+      uart401intr (irq, NULL, NULL);
       if (debug++ > 10)		/* Temporary debugging hack */
 	{
 	  sscape_write (devc, GA_INTENA_REG, 0x00);	/* Disable all interrupts */
@@ -352,9 +336,11 @@
       return;
     }
 
+  audio_devs[devc->my_audiodev]->flags &= ~DMA_AUTOMODE;
   DMAbuf_start_dma (devc->my_audiodev,
 		    buf,
 		    blk_size, mode);
+  audio_devs[devc->my_audiodev]->flags |= DMA_AUTOMODE;
 
   temp = devc->dma << 4;	/* Setup DMA channel select bits */
   if (devc->dma <= 3)
@@ -401,10 +387,10 @@
     {
       set_mt32 (devc, 0);
       if (!verify_mpu (devc))
-	return -EIO;
+	return -(EIO);
     }
 
-  sscape_sleep_flag.mode = WK_NONE;
+  sscape_sleep_flag.flags = WK_NONE;
   return 0;
 }
 
@@ -419,11 +405,9 @@
   if (devc->dma_allocated)
     {
       sscape_write (devc, GA_DMAA_REG, 0x20);	/* DMA channel disabled */
-#ifdef CONFIG_NATIVE_PCM
-#endif
       devc->dma_allocated = 0;
     }
-  sscape_sleep_flag.mode = WK_NONE;
+  sscape_sleep_flag.flags = WK_NONE;
   restore_flags (flags);
 
   return;
@@ -440,7 +424,7 @@
   unsigned long   flags;
   unsigned char   temp;
   int             done, timeout_val;
-  static int      already_done = 0;
+  static unsigned char codec_dma_bits = 0;
 
   if (flag & CPF_FIRST)
     {
@@ -449,20 +433,14 @@
          * before continuing.
        */
 
-      if (already_done)
-	{
-	  printk ("Can't run 'ssinit' twice\n");
-	  return 0;
-	}
-      already_done = 1;
-
       save_flags (flags);
       cli ();
+      codec_dma_bits = sscape_read (devc, GA_CDCFG_REG);
+      sscape_write (devc, GA_CDCFG_REG,
+		    codec_dma_bits & ~0x08);	/* Disable codec DMA */
+
       if (devc->dma_allocated == 0)
 	{
-#ifdef CONFIG_NATIVE_PCM
-#endif
-
 	  devc->dma_allocated = 1;
 	}
       restore_flags (flags);
@@ -479,7 +457,7 @@
     }
 
   /*
-     * Transfer one code block using DMA
+   * Transfer one code block using DMA
    */
   memcpy (audio_devs[devc->my_audiodev]->dmap_out->raw_buf, block, size);
 
@@ -493,7 +471,7 @@
   /*
    * Wait until transfer completes.
    */
-  sscape_sleep_flag.mode = WK_NONE;
+  sscape_sleep_flag.flags = WK_NONE;
   done = 0;
   timeout_val = 100;
   while (!done && timeout_val-- > 0)
@@ -502,24 +480,26 @@
 
 
       {
-	unsigned long   tl;
+	unsigned long   tlimit;
 
 	if (1)
-	  current_set_timeout (tl = jiffies + (1));
+	  current_set_timeout (tlimit = jiffies + (1));
 	else
-	  tl = (unsigned long) -1;
-	sscape_sleep_flag.mode = WK_SLEEP;
+	  tlimit = (unsigned long) -1;
+	sscape_sleep_flag.flags = WK_SLEEP;
 	module_interruptible_sleep_on (&sscape_sleeper);
-	if (!(sscape_sleep_flag.mode & WK_WAKEUP))
+	if (!(sscape_sleep_flag.flags & WK_WAKEUP))
 	  {
-	    if (jiffies >= tl)
-	      sscape_sleep_flag.mode |= WK_TIMEOUT;
+	    if (jiffies >= tlimit)
+	      sscape_sleep_flag.flags |= WK_TIMEOUT;
 	  }
-	sscape_sleep_flag.mode &= ~WK_SLEEP;
+	sscape_sleep_flag.flags &= ~WK_SLEEP;
       };
       clear_dma_ff (devc->dma);
       if ((resid = get_dma_residue (devc->dma)) == 0)
-	done = 1;
+	{
+	  done = 1;
+	}
     }
 
   restore_flags (flags);
@@ -550,24 +530,26 @@
 	{
 
 	  {
-	    unsigned long   tl;
+	    unsigned long   tlimit;
 
 	    if (1)
-	      current_set_timeout (tl = jiffies + (1));
+	      current_set_timeout (tlimit = jiffies + (1));
 	    else
-	      tl = (unsigned long) -1;
-	    sscape_sleep_flag.mode = WK_SLEEP;
+	      tlimit = (unsigned long) -1;
+	    sscape_sleep_flag.flags = WK_SLEEP;
 	    module_interruptible_sleep_on (&sscape_sleeper);
-	    if (!(sscape_sleep_flag.mode & WK_WAKEUP))
+	    if (!(sscape_sleep_flag.flags & WK_WAKEUP))
 	      {
-		if (jiffies >= tl)
-		  sscape_sleep_flag.mode |= WK_TIMEOUT;
+		if (jiffies >= tlimit)
+		  sscape_sleep_flag.flags |= WK_TIMEOUT;
 	      }
-	    sscape_sleep_flag.mode &= ~WK_SLEEP;
+	    sscape_sleep_flag.flags &= ~WK_SLEEP;
 	  };
 	  if (inb (PORT (HOST_DATA)) == 0xff)	/* OBP startup acknowledge */
 	    done = 1;
 	}
+      sscape_write (devc, GA_CDCFG_REG, codec_dma_bits);
+
       restore_flags (flags);
       if (!done)
 	{
@@ -583,20 +565,20 @@
 	{
 
 	  {
-	    unsigned long   tl;
+	    unsigned long   tlimit;
 
 	    if (1)
-	      current_set_timeout (tl = jiffies + (1));
+	      current_set_timeout (tlimit = jiffies + (1));
 	    else
-	      tl = (unsigned long) -1;
-	    sscape_sleep_flag.mode = WK_SLEEP;
+	      tlimit = (unsigned long) -1;
+	    sscape_sleep_flag.flags = WK_SLEEP;
 	    module_interruptible_sleep_on (&sscape_sleeper);
-	    if (!(sscape_sleep_flag.mode & WK_WAKEUP))
+	    if (!(sscape_sleep_flag.flags & WK_WAKEUP))
 	      {
-		if (jiffies >= tl)
-		  sscape_sleep_flag.mode |= WK_TIMEOUT;
+		if (jiffies >= tlimit)
+		  sscape_sleep_flag.flags |= WK_TIMEOUT;
 	      }
-	    sscape_sleep_flag.mode &= ~WK_SLEEP;
+	    sscape_sleep_flag.flags &= ~WK_SLEEP;
 	  };
 	  if (inb (PORT (HOST_DATA)) == 0xfe)	/* Host startup acknowledge */
 	    done = 1;
@@ -636,12 +618,12 @@
 download_boot_block (void *dev_info, copr_buffer * buf)
 {
   if (buf->len <= 0 || buf->len > sizeof (buf->data))
-    return -EINVAL;
+    return -(EINVAL);
 
   if (!sscape_download_boot (devc, buf->data, buf->len, buf->flags))
     {
       printk ("SSCAPE: Unable to load microcode block to the OBP.\n");
-      return -EIO;
+      return -(EIO);
     }
 
   return 0;
@@ -663,18 +645,18 @@
 	copr_buffer    *buf;
 	int             err;
 
-	buf = (copr_buffer *) kmalloc (sizeof (copr_buffer), GFP_KERNEL);
+	buf = (copr_buffer *) vmalloc (sizeof (copr_buffer));
 	if (buf == NULL)
-	  return -ENOSPC;
-	memcpy_fromfs ((char *) buf, &(((char *) arg)[0]), sizeof (*buf));
+	  return -(ENOSPC);
+	memcpy_fromfs ((char *) buf, &((char *) arg)[0], sizeof (*buf));
 	err = download_boot_block (dev_info, buf);
-	kfree (buf);
+	vfree (buf);
 	return err;
       }
       break;
 
     default:
-      return -EINVAL;
+      return -(EINVAL);
     }
 
 }
@@ -689,176 +671,11 @@
   &dev_info
 };
 
-static int
-sscape_audio_open (int dev, int mode)
-{
-  unsigned long   flags;
-  sscape_info    *devc = (sscape_info *) audio_devs[dev]->devc;
-
-  save_flags (flags);
-  cli ();
-  if (devc->opened)
-    {
-      restore_flags (flags);
-      return -EBUSY;
-    }
-  devc->opened = 1;
-  restore_flags (flags);
-#ifdef SSCAPE_DEBUG4
-  /*
-     * Temporary debugging aid. Print contents of the registers
-     * when the device is opened.
-   */
-  {
-    int             i;
-
-    for (i = 0; i < 13; i++)
-      printk ("I%d = %02x\n", i, sscape_read (devc, i));
-  }
-#endif
-
-  return 0;
-}
-
-static void
-sscape_audio_close (int dev)
-{
-  unsigned long   flags;
-  sscape_info    *devc = (sscape_info *) audio_devs[dev]->devc;
-
-  DEB (printk ("sscape_audio_close(void)\n"));
-
-  save_flags (flags);
-  cli ();
-
-  devc->opened = 0;
-
-  restore_flags (flags);
-}
-
-static int
-set_speed (sscape_info * devc, int arg)
-{
-  return 8000;
-}
-
-static int
-set_channels (sscape_info * devc, int arg)
-{
-  return 1;
-}
-
-static int
-set_format (sscape_info * devc, int arg)
-{
-  return AFMT_U8;
-}
-
-static int
-sscape_audio_ioctl (int dev, unsigned int cmd, caddr_t arg, int local)
-{
-  sscape_info    *devc = (sscape_info *) audio_devs[dev]->devc;
-
-  switch (cmd)
-    {
-    case SOUND_PCM_WRITE_RATE:
-      if (local)
-	return set_speed (devc, (int) arg);
-      return snd_ioctl_return ((int *) arg, set_speed (devc, get_fs_long ((long *) arg)));
-
-    case SOUND_PCM_READ_RATE:
-      if (local)
-	return 8000;
-      return snd_ioctl_return ((int *) arg, 8000);
-
-    case SNDCTL_DSP_STEREO:
-      if (local)
-	return set_channels (devc, (int) arg + 1) - 1;
-      return snd_ioctl_return ((int *) arg, set_channels (devc, get_fs_long ((long *) arg) + 1) - 1);
-
-    case SOUND_PCM_WRITE_CHANNELS:
-      if (local)
-	return set_channels (devc, (int) arg);
-      return snd_ioctl_return ((int *) arg, set_channels (devc, get_fs_long ((long *) arg)));
-
-    case SOUND_PCM_READ_CHANNELS:
-      if (local)
-	return 1;
-      return snd_ioctl_return ((int *) arg, 1);
-
-    case SNDCTL_DSP_SAMPLESIZE:
-      if (local)
-	return set_format (devc, (int) arg);
-      return snd_ioctl_return ((int *) arg, set_format (devc, get_fs_long ((long *) arg)));
-
-    case SOUND_PCM_READ_BITS:
-      if (local)
-	return 8;
-      return snd_ioctl_return ((int *) arg, 8);
-
-    default:;
-    }
-  return -EINVAL;
-}
-
-static void
-sscape_audio_output_block (int dev, unsigned long buf, int count, int intrflag, int dma_restart)
-{
-}
-
-static void
-sscape_audio_start_input (int dev, unsigned long buf, int count, int intrflag, int dma_restart)
-{
-}
-
-static int
-sscape_audio_prepare_for_input (int dev, int bsize, int bcount)
-{
-  return 0;
-}
-
-static int
-sscape_audio_prepare_for_output (int dev, int bsize, int bcount)
-{
-  return 0;
-}
-
-static void
-sscape_audio_halt (int dev)
-{
-}
-
-static void
-sscape_audio_reset (int dev)
-{
-  sscape_audio_halt (dev);
-}
-
-static struct audio_operations sscape_audio_operations =
-{
-  "Not functional",
-  0,
-  AFMT_U8 | AFMT_S16_LE,
-  NULL,
-  sscape_audio_open,
-  sscape_audio_close,
-  sscape_audio_output_block,
-  sscape_audio_start_input,
-  sscape_audio_ioctl,
-  sscape_audio_prepare_for_input,
-  sscape_audio_prepare_for_output,
-  sscape_audio_reset,
-  sscape_audio_halt,
-  NULL,
-  NULL
-};
-
 static int      sscape_detected = 0;
 
-long
-attach_sscape (long mem_start, struct address_info *hw_config)
+void
+attach_sscape (struct address_info *hw_config)
 {
-  int             my_dev;
 
 #ifndef SSCAPE_REGS
   /*
@@ -894,7 +711,7 @@
   int             i, irq_bits = 0xff;
 
   if (sscape_detected != hw_config->io_base)
-    return mem_start;
+    return;
 
   if (old_hardware)
     {
@@ -914,7 +731,7 @@
   if (hw_config->irq > 15 || (regs[4] = irq_bits == 0xff))
     {
       printk ("Invalid IRQ%d\n", hw_config->irq);
-      return mem_start;
+      return;
     }
 
   save_flags (flags);
@@ -968,45 +785,27 @@
   }
 #endif
 
-#if defined(CONFIG_MIDI) && defined(CONFIG_MPU_EMU)
-  if (probe_mpu401 (hw_config))
+#if defined(CONFIG_MIDI) && defined(CONFIG_UART401)
+  if (probe_uart401 (hw_config))
     hw_config->always_detect = 1;
   {
     int             prev_devs;
 
     prev_devs = num_midis;
-    mem_start = attach_mpu401 (mem_start, hw_config);
+    hw_config->name = "Soundscape";
+
+    hw_config->irq *= -1;	/* Negative value signals IRQ sharing */
+    attach_uart401 (hw_config);
+    hw_config->irq *= -1;	/* Restore it */
 
     if (num_midis == (prev_devs + 1))	/* The MPU driver installed itself */
       midi_devs[prev_devs]->coproc = &sscape_coproc_operations;
   }
 #endif
 
-#ifndef EXCLUDE_NATIVE_PCM
-  /* Not supported yet */
-
-#ifdef CONFIG_AUDIO
-  if (num_audiodevs < MAX_AUDIO_DEV)
-    {
-      audio_devs[my_dev = num_audiodevs++] = &sscape_audio_operations;
-      audio_devs[my_dev]->dmachan1 = hw_config->dma;
-      audio_devs[my_dev]->buffsize = DSP_BUFFSIZE;
-      audio_devs[my_dev]->devc = devc;
-      devc->my_audiodev = my_dev;
-      devc->opened = 0;
-      audio_devs[my_dev]->coproc = &sscape_coproc_operations;
-      if (snd_set_irq_handler (hw_config->irq, sscapeintr, "SoundScape", devc->osp) < 0)
-	printk ("Error: Can't allocate IRQ for SoundScape\n");
-
-      sscape_write (devc, GA_INTENA_REG, 0x80);		/* Master IRQ enable */
-    }
-  else
-    printk ("SoundScape: More than enough audio devices detected\n");
-#endif
-#endif
+  sscape_write (devc, GA_INTENA_REG, 0x80);	/* Master IRQ enable */
   devc->ok = 1;
   devc->failed = 0;
-  return mem_start;
 }
 
 int
@@ -1083,11 +882,6 @@
 	old_hardware = 0;
     }
 
-  if (sound_alloc_dma (hw_config->dma, "soundscape"))
-    {
-      printk ("sscape.c: Can't allocate DMA channel\n");
-      return 0;
-    }
 
   sscape_detected = hw_config->io_base;
 
@@ -1123,8 +917,8 @@
   return ad1848_detect (hw_config->io_base, NULL, hw_config->osp);
 }
 
-long
-attach_ss_ms_sound (long mem_start, struct address_info *hw_config)
+void
+attach_ss_ms_sound (struct address_info *hw_config)
 {
   /*
      * This routine configures the SoundScape card for use with the
@@ -1134,18 +928,17 @@
 
   int             i, irq_bits = 0xff;
 
-#ifndef CONFIG_NATIVE_PCM
   int             prev_devs = num_audiodevs;
 
-#endif
+  hw_config->dma = devc->dma;	/* Share the DMA with the ODIE/OPUS chip */
 
   /*
-     * Setup the DMA polarity.
+   * Setup the DMA polarity.
    */
   sscape_write (devc, GA_DMACFG_REG, 0x50);
 
   /*
-     * Take the gate-array off of the DMA channel.
+     * Take the gate-arry off of the DMA channel.
    */
   sscape_write (devc, GA_DMAB_REG, 0x20);
 
@@ -1173,10 +966,10 @@
 	       0,
 	       devc->osp);
 
-#ifndef CONFIG_NATIVE_PCM
   if (num_audiodevs == (prev_devs + 1))		/* The AD1848 driver installed itself */
     audio_devs[prev_devs]->coproc = &sscape_coproc_operations;
-#endif
+  devc->my_audiodev = prev_devs;
+
 #ifdef SSCAPE_DEBUG5
   /*
      * Temporary debugging aid. Print contents of the registers
@@ -1190,17 +983,15 @@
   }
 #endif
 
-  return mem_start;
 }
 
 void
 unload_sscape (struct address_info *hw_config)
 {
-#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
-  unload_mpu401 (hw_config);
+#if defined(CONFIG_UART401) && defined(CONFIG_MIDI)
+  unload_uart401 (hw_config);
 #endif
   snd_release_irq (hw_config->irq);
-  sound_free_dma (hw_config->dma);
 }
 
 void
@@ -1208,9 +999,10 @@
 {
   ad1848_unload (hw_config->io_base,
 		 hw_config->irq,
-		 hw_config->dma,
-		 hw_config->dma,
+		 devc->dma,
+		 devc->dma,
 		 0);
 }
+
 
 #endif

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov