sound: Retire OSS
[sfrench/cifs-2.6.git] / sound / oss / waveartist.c
diff --git a/sound/oss/waveartist.c b/sound/oss/waveartist.c
deleted file mode 100644 (file)
index 4f0c3a2..0000000
+++ /dev/null
@@ -1,2043 +0,0 @@
-/*
- * linux/sound/oss/waveartist.c
- *
- * The low level driver for the RWA010 Rockwell Wave Artist
- * codec chip used in the Rebel.com NetWinder.
- *
- * Cleaned up and integrated into 2.1 by Russell King (rmk@arm.linux.org.uk)
- * and Pat Beirne (patb@corel.ca)
- *
- *
- * Copyright (C) by Rebel.com 1998-1999
- *
- * RWA010 specs received under NDA from Rockwell
- *
- * Copyright (C) by Hannu Savolainen 1993-1997
- *
- * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
- * Version 2 (June 1991). See the "COPYING" file distributed with this software
- * for more info.
- *
- * Changes:
- * 11-10-2000  Bartlomiej Zolnierkiewicz <bkz@linux-ide.org>
- *             Added __init to waveartist_init()
- */
-
-/* Debugging */
-#define DEBUG_CMD      1
-#define DEBUG_OUT      2
-#define DEBUG_IN       4
-#define DEBUG_INTR     8
-#define DEBUG_MIXER    16
-#define DEBUG_TRIGGER  32
-
-#define debug_flg (0)
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/spinlock.h>
-#include <linux/bitops.h>
-
-
-#include "sound_config.h"
-#include "waveartist.h"
-
-#ifdef CONFIG_ARM
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-#endif
-
-#ifndef NO_DMA
-#define NO_DMA 255
-#endif
-
-#define SUPPORTED_MIXER_DEVICES                (SOUND_MASK_SYNTH      |\
-                                        SOUND_MASK_PCM        |\
-                                        SOUND_MASK_LINE       |\
-                                        SOUND_MASK_MIC        |\
-                                        SOUND_MASK_LINE1      |\
-                                        SOUND_MASK_RECLEV     |\
-                                        SOUND_MASK_VOLUME     |\
-                                        SOUND_MASK_IMIX)
-
-static unsigned short levels[SOUND_MIXER_NRDEVICES] = {
-       0x5555,         /* Master Volume         */
-       0x0000,         /* Bass                  */
-       0x0000,         /* Treble                */
-       0x2323,         /* Synth (FM)            */
-       0x4b4b,         /* PCM                   */
-       0x6464,         /* PC Speaker            */
-       0x0000,         /* Ext Line              */
-       0x0000,         /* Mic                   */
-       0x0000,         /* CD                    */
-       0x6464,         /* Recording monitor     */
-       0x0000,         /* SB PCM (ALT PCM)      */
-       0x0000,         /* Recording level       */
-       0x6464,         /* Input gain            */
-       0x6464,         /* Output gain           */
-       0x0000,         /* Line1 (Aux1)          */
-       0x0000,         /* Line2 (Aux2)          */
-       0x0000,         /* Line3 (Aux3)          */
-       0x0000,         /* Digital1              */
-       0x0000,         /* Digital2              */
-       0x0000,         /* Digital3              */
-       0x0000,         /* Phone In              */
-       0x6464,         /* Phone Out             */
-       0x0000,         /* Video                 */
-       0x0000,         /* Radio                 */
-       0x0000          /* Monitor               */
-};
-
-struct wavnc_info {
-       struct address_info  hw;        /* hardware */
-       char            *chip_name;
-
-       int             xfer_count;
-       int             audio_mode;
-       int             open_mode;
-       int             audio_flags;
-       int             record_dev;
-       int             playback_dev;
-       int             dev_no;
-
-       /* Mixer parameters */
-       const struct waveartist_mixer_info *mix;
-
-       unsigned short  *levels;           /* cache of volume settings   */
-       int             recmask;           /* currently enabled recording device! */
-
-#ifdef CONFIG_ARCH_NETWINDER
-       signed int      slider_vol;        /* hardware slider volume     */
-       unsigned int    handset_detect  :1;
-       unsigned int    telephone_detect:1;
-       unsigned int    no_autoselect   :1;/* handset/telephone autoselects a path */
-       unsigned int    spkr_mute_state :1;/* set by ioctl or autoselect */
-       unsigned int    line_mute_state :1;/* set by ioctl or autoselect */
-       unsigned int    use_slider      :1;/* use slider setting for o/p vol */
-#endif
-};
-
-/*
- * This is the implementation specific mixer information.
- */
-struct waveartist_mixer_info {
-       unsigned int    supported_devs;    /* Supported devices */
-       unsigned int    recording_devs;    /* Recordable devies */
-       unsigned int    stereo_devs;       /* Stereo devices    */
-
-       unsigned int    (*select_input)(struct wavnc_info *, unsigned int,
-                                       unsigned char *, unsigned char *);
-       int             (*decode_mixer)(struct wavnc_info *, int,
-                                       unsigned char, unsigned char);
-       int             (*get_mixer)(struct wavnc_info *, int);
-};
-
-struct wavnc_port_info {
-       int             open_mode;
-       int             speed;
-       int             channels;
-       int             audio_format;
-};
-
-static int             nr_waveartist_devs;
-static struct wavnc_info       adev_info[MAX_AUDIO_DEV];
-static DEFINE_SPINLOCK(waveartist_lock);
-
-#ifndef CONFIG_ARCH_NETWINDER
-#define machine_is_netwinder() 0
-#else
-static struct timer_list vnc_timer;
-static void vnc_configure_mixer(struct wavnc_info *devc,
-                               unsigned int input_mask);
-static int vnc_private_ioctl(int dev, unsigned int cmd, int __user *arg);
-static void vnc_slider_tick(unsigned long data);
-#endif
-
-static inline void
-waveartist_set_ctlr(struct address_info *hw, unsigned char clear, unsigned char set)
-{
-       unsigned int ctlr_port = hw->io_base + CTLR;
-
-       clear = ~clear & inb(ctlr_port);
-
-       outb(clear | set, ctlr_port);
-}
-
-/* Toggle IRQ acknowledge line
- */
-static inline void
-waveartist_iack(struct wavnc_info *devc)
-{
-       unsigned int ctlr_port = devc->hw.io_base + CTLR;
-       int old_ctlr;
-
-       old_ctlr = inb(ctlr_port) & ~IRQ_ACK;
-
-       outb(old_ctlr | IRQ_ACK, ctlr_port);
-       outb(old_ctlr, ctlr_port);
-}
-
-static inline int
-waveartist_sleep(int timeout_ms)
-{
-       unsigned int timeout = msecs_to_jiffies(timeout_ms*100);
-       return schedule_timeout_interruptible(timeout);
-}
-
-static int
-waveartist_reset(struct wavnc_info *devc)
-{
-       struct address_info *hw = &devc->hw;
-       unsigned int timeout, res = -1;
-
-       waveartist_set_ctlr(hw, -1, RESET);
-       waveartist_sleep(2);
-       waveartist_set_ctlr(hw, RESET, 0);
-
-       timeout = 500;
-       do {
-               mdelay(2);
-
-               if (inb(hw->io_base + STATR) & CMD_RF) {
-                       res = inw(hw->io_base + CMDR);
-                       if (res == 0x55aa)
-                               break;
-               }
-       } while (--timeout);
-
-       if (timeout == 0) {
-               printk(KERN_WARNING "WaveArtist: reset timeout ");
-               if (res != (unsigned int)-1)
-                       printk("(res=%04X)", res);
-               printk("\n");
-               return 1;
-       }
-       return 0;
-}
-
-/* Helper function to send and receive words
- * from WaveArtist.  It handles all the handshaking
- * and can send or receive multiple words.
- */
-static int
-waveartist_cmd(struct wavnc_info *devc,
-               int nr_cmd, unsigned int *cmd,
-               int nr_resp, unsigned int *resp)
-{
-       unsigned int io_base = devc->hw.io_base;
-       unsigned int timed_out = 0;
-       unsigned int i;
-
-       if (debug_flg & DEBUG_CMD) {
-               printk("waveartist_cmd: cmd=");
-
-               for (i = 0; i < nr_cmd; i++)
-                       printk("%04X ", cmd[i]);
-
-               printk("\n");
-       }
-
-       if (inb(io_base + STATR) & CMD_RF) {
-               int old_data;
-
-               /* flush the port
-                */
-
-               old_data = inw(io_base + CMDR);
-
-               if (debug_flg & DEBUG_CMD)
-                       printk("flushed %04X...", old_data);
-
-               udelay(10);
-       }
-
-       for (i = 0; !timed_out && i < nr_cmd; i++) {
-               int count;
-
-               for (count = 5000; count; count--)
-                       if (inb(io_base + STATR) & CMD_WE)
-                               break;
-
-               if (!count)
-                       timed_out = 1;
-               else
-                       outw(cmd[i], io_base + CMDR);
-       }
-
-       for (i = 0; !timed_out && i < nr_resp; i++) {
-               int count;
-
-               for (count = 5000; count; count--)
-                       if (inb(io_base + STATR) & CMD_RF)
-                               break;
-
-               if (!count)
-                       timed_out = 1;
-               else
-                       resp[i] = inw(io_base + CMDR);
-       }
-
-       if (debug_flg & DEBUG_CMD) {
-               if (!timed_out) {
-                       printk("waveartist_cmd: resp=");
-
-                       for (i = 0; i < nr_resp; i++)
-                               printk("%04X ", resp[i]);
-
-                       printk("\n");
-               } else
-                       printk("waveartist_cmd: timed out\n");
-       }
-
-       return timed_out ? 1 : 0;
-}
-
-/*
- * Send one command word
- */
-static inline int
-waveartist_cmd1(struct wavnc_info *devc, unsigned int cmd)
-{
-       return waveartist_cmd(devc, 1, &cmd, 0, NULL);
-}
-
-/*
- * Send one command, receive one word
- */
-static inline unsigned int
-waveartist_cmd1_r(struct wavnc_info *devc, unsigned int cmd)
-{
-       unsigned int ret;
-
-       waveartist_cmd(devc, 1, &cmd, 1, &ret);
-
-       return ret;
-}
-
-/*
- * Send a double command, receive one
- * word (and throw it away)
- */
-static inline int
-waveartist_cmd2(struct wavnc_info *devc, unsigned int cmd, unsigned int arg)
-{
-       unsigned int vals[2];
-
-       vals[0] = cmd;
-       vals[1] = arg;
-
-       return waveartist_cmd(devc, 2, vals, 1, vals);
-}
-
-/*
- * Send a triple command
- */
-static inline int
-waveartist_cmd3(struct wavnc_info *devc, unsigned int cmd,
-               unsigned int arg1, unsigned int arg2)
-{
-       unsigned int vals[3];
-
-       vals[0] = cmd;
-       vals[1] = arg1;
-       vals[2] = arg2;
-
-       return waveartist_cmd(devc, 3, vals, 0, NULL);
-}
-
-static int
-waveartist_getrev(struct wavnc_info *devc, char *rev)
-{
-       unsigned int temp[2];
-       unsigned int cmd = WACMD_GETREV;
-
-       waveartist_cmd(devc, 1, &cmd, 2, temp);
-
-       rev[0] = temp[0] >> 8;
-       rev[1] = temp[0] & 255;
-       rev[2] = '\0';
-
-       return temp[0];
-}
-
-static void waveartist_halt_output(int dev);
-static void waveartist_halt_input(int dev);
-static void waveartist_halt(int dev);
-static void waveartist_trigger(int dev, int state);
-
-static int
-waveartist_open(int dev, int mode)
-{
-       struct wavnc_info       *devc;
-       struct wavnc_port_info  *portc;
-       unsigned long   flags;
-
-       if (dev < 0 || dev >= num_audiodevs)
-               return -ENXIO;
-
-       devc  = (struct wavnc_info *) audio_devs[dev]->devc;
-       portc = (struct wavnc_port_info *) audio_devs[dev]->portc;
-
-       spin_lock_irqsave(&waveartist_lock, flags);
-       if (portc->open_mode || (devc->open_mode & mode)) {
-               spin_unlock_irqrestore(&waveartist_lock, flags);
-               return -EBUSY;
-       }
-
-       devc->audio_mode  = 0;
-       devc->open_mode  |= mode;
-       portc->open_mode  = mode;
-       waveartist_trigger(dev, 0);
-
-       if (mode & OPEN_READ)
-               devc->record_dev = dev;
-       if (mode & OPEN_WRITE)
-               devc->playback_dev = dev;
-       spin_unlock_irqrestore(&waveartist_lock, flags);
-
-       return 0;
-}
-
-static void
-waveartist_close(int dev)
-{
-       struct wavnc_info       *devc = (struct wavnc_info *)
-                                       audio_devs[dev]->devc;
-       struct wavnc_port_info  *portc = (struct wavnc_port_info *)
-                                        audio_devs[dev]->portc;
-       unsigned long   flags;
-
-       spin_lock_irqsave(&waveartist_lock, flags);
-
-       waveartist_halt(dev);
-
-       devc->audio_mode = 0;
-       devc->open_mode &= ~portc->open_mode;
-       portc->open_mode = 0;
-
-       spin_unlock_irqrestore(&waveartist_lock, flags);
-}
-
-static void
-waveartist_output_block(int dev, unsigned long buf, int __count, int intrflag)
-{
-       struct wavnc_port_info  *portc = (struct wavnc_port_info *)
-                                        audio_devs[dev]->portc;
-       struct wavnc_info       *devc = (struct wavnc_info *)
-                                       audio_devs[dev]->devc;
-       unsigned long   flags;
-       unsigned int    count = __count; 
-
-       if (debug_flg & DEBUG_OUT)
-               printk("waveartist: output block, buf=0x%lx, count=0x%x...\n",
-                       buf, count);
-       /*
-        * 16 bit data
-        */
-       if (portc->audio_format & (AFMT_S16_LE | AFMT_S16_BE))
-               count >>= 1;
-
-       if (portc->channels > 1)
-               count >>= 1;
-
-       count -= 1;
-
-       if (devc->audio_mode & PCM_ENABLE_OUTPUT &&
-           audio_devs[dev]->flags & DMA_AUTOMODE &&
-           intrflag &&
-           count == devc->xfer_count) {
-               devc->audio_mode |= PCM_ENABLE_OUTPUT;
-               return; /*
-                        * Auto DMA mode on. No need to react
-                        */
-       }
-
-       spin_lock_irqsave(&waveartist_lock, flags);
-
-       /*
-        * set sample count
-        */
-       waveartist_cmd2(devc, WACMD_OUTPUTSIZE, count);
-
-       devc->xfer_count = count;
-       devc->audio_mode |= PCM_ENABLE_OUTPUT;
-
-       spin_unlock_irqrestore(&waveartist_lock, flags);
-}
-
-static void
-waveartist_start_input(int dev, unsigned long buf, int __count, int intrflag)
-{
-       struct wavnc_port_info *portc = (struct wavnc_port_info *)
-                                       audio_devs[dev]->portc;
-       struct wavnc_info       *devc = (struct wavnc_info *)
-                                       audio_devs[dev]->devc;
-       unsigned long   flags;
-       unsigned int    count = __count;
-
-       if (debug_flg & DEBUG_IN)
-               printk("waveartist: start input, buf=0x%lx, count=0x%x...\n",
-                       buf, count);
-
-       if (portc->audio_format & (AFMT_S16_LE | AFMT_S16_BE))  /* 16 bit data */
-               count >>= 1;
-
-       if (portc->channels > 1)
-               count >>= 1;
-
-       count -= 1;
-
-       if (devc->audio_mode & PCM_ENABLE_INPUT &&
-           audio_devs[dev]->flags & DMA_AUTOMODE &&
-           intrflag &&
-           count == devc->xfer_count) {
-               devc->audio_mode |= PCM_ENABLE_INPUT;
-               return; /*
-                        * Auto DMA mode on. No need to react
-                        */
-       }
-
-       spin_lock_irqsave(&waveartist_lock, flags);
-
-       /*
-        * set sample count
-        */
-       waveartist_cmd2(devc, WACMD_INPUTSIZE, count);
-
-       devc->xfer_count = count;
-       devc->audio_mode |= PCM_ENABLE_INPUT;
-
-       spin_unlock_irqrestore(&waveartist_lock, flags);
-}
-
-static int
-waveartist_ioctl(int dev, unsigned int cmd, void __user * arg)
-{
-       return -EINVAL;
-}
-
-static unsigned int
-waveartist_get_speed(struct wavnc_port_info *portc)
-{
-       unsigned int speed;
-
-       /*
-        * program the speed, channels, bits
-        */
-       if (portc->speed == 8000)
-               speed = 0x2E71;
-       else if (portc->speed == 11025)
-               speed = 0x4000;
-       else if (portc->speed == 22050)
-               speed = 0x8000;
-       else if (portc->speed == 44100)
-               speed = 0x0;
-       else {
-               /*
-                * non-standard - just calculate
-                */
-               speed = portc->speed << 16;
-
-               speed = (speed / 44100) & 65535;
-       }
-
-       return speed;
-}
-
-static unsigned int
-waveartist_get_bits(struct wavnc_port_info *portc)
-{
-       unsigned int bits;
-
-       if (portc->audio_format == AFMT_S16_LE)
-               bits = 1;
-       else if (portc->audio_format == AFMT_S8)
-               bits = 0;
-       else
-               bits = 2;       //default AFMT_U8
-
-       return bits;
-}
-
-static int
-waveartist_prepare_for_input(int dev, int bsize, int bcount)
-{
-       unsigned long   flags;
-       struct wavnc_info       *devc = (struct wavnc_info *)
-                                       audio_devs[dev]->devc;
-       struct wavnc_port_info  *portc = (struct wavnc_port_info *)
-                                        audio_devs[dev]->portc;
-       unsigned int    speed, bits;
-
-       if (devc->audio_mode)
-               return 0;
-
-       speed = waveartist_get_speed(portc);
-       bits  = waveartist_get_bits(portc);
-
-       spin_lock_irqsave(&waveartist_lock, flags);
-
-       if (waveartist_cmd2(devc, WACMD_INPUTFORMAT, bits))
-               printk(KERN_WARNING "waveartist: error setting the "
-                      "record format to %d\n", portc->audio_format);
-
-       if (waveartist_cmd2(devc, WACMD_INPUTCHANNELS, portc->channels))
-               printk(KERN_WARNING "waveartist: error setting record "
-                      "to %d channels\n", portc->channels);
-
-       /*
-        * write cmd SetSampleSpeedTimeConstant
-        */
-       if (waveartist_cmd2(devc, WACMD_INPUTSPEED, speed))
-               printk(KERN_WARNING "waveartist: error setting the record "
-                      "speed to %dHz.\n", portc->speed);
-
-       if (waveartist_cmd2(devc, WACMD_INPUTDMA, 1))
-               printk(KERN_WARNING "waveartist: error setting the record "
-                      "data path to 0x%X\n", 1);
-
-       if (waveartist_cmd2(devc, WACMD_INPUTFORMAT, bits))
-               printk(KERN_WARNING "waveartist: error setting the record "
-                      "format to %d\n", portc->audio_format);
-
-       devc->xfer_count = 0;
-       spin_unlock_irqrestore(&waveartist_lock, flags);
-       waveartist_halt_input(dev);
-
-       if (debug_flg & DEBUG_INTR) {
-               printk("WA CTLR reg: 0x%02X.\n",
-                      inb(devc->hw.io_base + CTLR));
-               printk("WA STAT reg: 0x%02X.\n",
-                      inb(devc->hw.io_base + STATR));
-               printk("WA IRQS reg: 0x%02X.\n",
-                      inb(devc->hw.io_base + IRQSTAT));
-       }
-
-       return 0;
-}
-
-static int
-waveartist_prepare_for_output(int dev, int bsize, int bcount)
-{
-       unsigned long   flags;
-       struct wavnc_info       *devc = (struct wavnc_info *)
-                                       audio_devs[dev]->devc;
-       struct wavnc_port_info  *portc = (struct wavnc_port_info *)
-                                        audio_devs[dev]->portc;
-       unsigned int    speed, bits;
-
-       /*
-        * program the speed, channels, bits
-        */
-       speed = waveartist_get_speed(portc);
-       bits  = waveartist_get_bits(portc);
-
-       spin_lock_irqsave(&waveartist_lock, flags);
-
-       if (waveartist_cmd2(devc, WACMD_OUTPUTSPEED, speed) &&
-           waveartist_cmd2(devc, WACMD_OUTPUTSPEED, speed))
-               printk(KERN_WARNING "waveartist: error setting the playback "
-                      "speed to %dHz.\n", portc->speed);
-
-       if (waveartist_cmd2(devc, WACMD_OUTPUTCHANNELS, portc->channels))
-               printk(KERN_WARNING "waveartist: error setting the playback "
-                      "to %d channels\n", portc->channels);
-
-       if (waveartist_cmd2(devc, WACMD_OUTPUTDMA, 0))
-               printk(KERN_WARNING "waveartist: error setting the playback "
-                      "data path to 0x%X\n", 0);
-
-       if (waveartist_cmd2(devc, WACMD_OUTPUTFORMAT, bits))
-               printk(KERN_WARNING "waveartist: error setting the playback "
-                      "format to %d\n", portc->audio_format);
-
-       devc->xfer_count = 0;
-       spin_unlock_irqrestore(&waveartist_lock, flags);
-       waveartist_halt_output(dev);
-
-       if (debug_flg & DEBUG_INTR) {
-               printk("WA CTLR reg: 0x%02X.\n",inb(devc->hw.io_base + CTLR));
-               printk("WA STAT reg: 0x%02X.\n",inb(devc->hw.io_base + STATR));
-               printk("WA IRQS reg: 0x%02X.\n",inb(devc->hw.io_base + IRQSTAT));
-       }
-
-       return 0;
-}
-
-static void
-waveartist_halt(int dev)
-{
-       struct wavnc_port_info  *portc = (struct wavnc_port_info *)
-                                        audio_devs[dev]->portc;
-       struct wavnc_info       *devc;
-
-       if (portc->open_mode & OPEN_WRITE)
-               waveartist_halt_output(dev);
-
-       if (portc->open_mode & OPEN_READ)
-               waveartist_halt_input(dev);
-
-       devc = (struct wavnc_info *) audio_devs[dev]->devc;
-       devc->audio_mode = 0;
-}
-
-static void
-waveartist_halt_input(int dev)
-{
-       struct wavnc_info       *devc = (struct wavnc_info *)
-                                       audio_devs[dev]->devc;
-       unsigned long   flags;
-
-       spin_lock_irqsave(&waveartist_lock, flags);
-
-       /*
-        * Stop capture
-        */
-       waveartist_cmd1(devc, WACMD_INPUTSTOP);
-
-       devc->audio_mode &= ~PCM_ENABLE_INPUT;
-
-       /*
-        * Clear interrupt by toggling
-        * the IRQ_ACK bit in CTRL
-        */
-       if (inb(devc->hw.io_base + STATR) & IRQ_REQ)
-               waveartist_iack(devc);
-
-//     devc->audio_mode &= ~PCM_ENABLE_INPUT;
-
-       spin_unlock_irqrestore(&waveartist_lock, flags);
-}
-
-static void
-waveartist_halt_output(int dev)
-{
-       struct wavnc_info       *devc = (struct wavnc_info *)
-                                       audio_devs[dev]->devc;
-       unsigned long   flags;
-
-       spin_lock_irqsave(&waveartist_lock, flags);
-
-       waveartist_cmd1(devc, WACMD_OUTPUTSTOP);
-
-       devc->audio_mode &= ~PCM_ENABLE_OUTPUT;
-
-       /*
-        * Clear interrupt by toggling
-        * the IRQ_ACK bit in CTRL
-        */
-       if (inb(devc->hw.io_base + STATR) & IRQ_REQ)
-               waveartist_iack(devc);
-
-//     devc->audio_mode &= ~PCM_ENABLE_OUTPUT;
-
-       spin_unlock_irqrestore(&waveartist_lock, flags);
-}
-
-static void
-waveartist_trigger(int dev, int state)
-{
-       struct wavnc_info       *devc = (struct wavnc_info *)
-                                       audio_devs[dev]->devc;
-       struct wavnc_port_info  *portc = (struct wavnc_port_info *)
-                                        audio_devs[dev]->portc;
-       unsigned long   flags;
-
-       if (debug_flg & DEBUG_TRIGGER) {
-               printk("wavnc: audio trigger ");
-               if (state & PCM_ENABLE_INPUT)
-                       printk("in ");
-               if (state & PCM_ENABLE_OUTPUT)
-                       printk("out");
-               printk("\n");
-       }
-
-       spin_lock_irqsave(&waveartist_lock, flags);
-
-       state &= devc->audio_mode;
-
-       if (portc->open_mode & OPEN_READ &&
-           state & PCM_ENABLE_INPUT)
-               /*
-                * enable ADC Data Transfer to PC
-                */
-               waveartist_cmd1(devc, WACMD_INPUTSTART);
-
-       if (portc->open_mode & OPEN_WRITE &&
-           state & PCM_ENABLE_OUTPUT)
-               /*
-                * enable DAC data transfer from PC
-                */
-               waveartist_cmd1(devc, WACMD_OUTPUTSTART);
-
-       spin_unlock_irqrestore(&waveartist_lock, flags);
-}
-
-static int
-waveartist_set_speed(int dev, int arg)
-{
-       struct wavnc_port_info *portc = (struct wavnc_port_info *)
-                                       audio_devs[dev]->portc;
-
-       if (arg <= 0)
-               return portc->speed;
-
-       if (arg < 5000)
-               arg = 5000;
-       if (arg > 44100)
-               arg = 44100;
-
-       portc->speed = arg;
-       return portc->speed;
-
-}
-
-static short
-waveartist_set_channels(int dev, short arg)
-{
-       struct wavnc_port_info *portc = (struct wavnc_port_info *)
-                                       audio_devs[dev]->portc;
-
-       if (arg != 1 && arg != 2)
-               return portc->channels;
-
-       portc->channels = arg;
-       return arg;
-}
-
-static unsigned int
-waveartist_set_bits(int dev, unsigned int arg)
-{
-       struct wavnc_port_info *portc = (struct wavnc_port_info *)
-                                       audio_devs[dev]->portc;
-
-       if (arg == 0)
-               return portc->audio_format;
-
-       if ((arg != AFMT_U8) && (arg != AFMT_S16_LE) && (arg != AFMT_S8))
-               arg = AFMT_U8;
-
-       portc->audio_format = arg;
-
-       return arg;
-}
-
-static struct audio_driver waveartist_audio_driver = {
-       .owner                  = THIS_MODULE,
-       .open                   = waveartist_open,
-       .close                  = waveartist_close,
-       .output_block           = waveartist_output_block,
-       .start_input            = waveartist_start_input,
-       .ioctl                  = waveartist_ioctl,
-       .prepare_for_input      = waveartist_prepare_for_input,
-       .prepare_for_output     = waveartist_prepare_for_output,
-       .halt_io                = waveartist_halt,
-       .halt_input             = waveartist_halt_input,
-       .halt_output            = waveartist_halt_output,
-       .trigger                = waveartist_trigger,
-       .set_speed              = waveartist_set_speed,
-       .set_bits               = waveartist_set_bits,
-       .set_channels           = waveartist_set_channels
-};
-
-
-static irqreturn_t
-waveartist_intr(int irq, void *dev_id)
-{
-       struct wavnc_info *devc = dev_id;
-       int        irqstatus, status;
-
-       spin_lock(&waveartist_lock);
-       irqstatus = inb(devc->hw.io_base + IRQSTAT);
-       status    = inb(devc->hw.io_base + STATR);
-
-       if (debug_flg & DEBUG_INTR)
-               printk("waveartist_intr: stat=%02x, irqstat=%02x\n",
-                      status, irqstatus);
-
-       if (status & IRQ_REQ)   /* Clear interrupt */
-               waveartist_iack(devc);
-       else
-               printk(KERN_WARNING "waveartist: unexpected interrupt\n");
-
-       if (irqstatus & 0x01) {
-               int temp = 1;
-
-               /* PCM buffer done
-                */
-               if ((status & DMA0) && (devc->audio_mode & PCM_ENABLE_OUTPUT)) {
-                       DMAbuf_outputintr(devc->playback_dev, 1);
-                       temp = 0;
-               }
-               if ((status & DMA1) && (devc->audio_mode & PCM_ENABLE_INPUT)) {
-                       DMAbuf_inputintr(devc->record_dev);
-                       temp = 0;
-               }
-               if (temp)       //default:
-                       printk(KERN_WARNING "waveartist: Unknown interrupt\n");
-       }
-       if (irqstatus & 0x2)
-               // We do not use SB mode natively...
-               printk(KERN_WARNING "waveartist: Unexpected SB interrupt...\n");
-       spin_unlock(&waveartist_lock);
-       return IRQ_HANDLED;
-}
-
-/* -------------------------------------------------------------------------
- * Mixer stuff
- */
-struct mix_ent {
-       unsigned char   reg_l;
-       unsigned char   reg_r;
-       unsigned char   shift;
-       unsigned char   max;
-};
-
-static const struct mix_ent mix_devs[SOUND_MIXER_NRDEVICES] = {
-       { 2, 6, 1,  7 }, /* SOUND_MIXER_VOLUME   */
-       { 0, 0, 0,  0 }, /* SOUND_MIXER_BASS     */
-       { 0, 0, 0,  0 }, /* SOUND_MIXER_TREBLE   */
-       { 0, 0, 0,  0 }, /* SOUND_MIXER_SYNTH    */
-       { 0, 0, 0,  0 }, /* SOUND_MIXER_PCM      */
-       { 0, 0, 0,  0 }, /* SOUND_MIXER_SPEAKER  */
-       { 0, 4, 6, 31 }, /* SOUND_MIXER_LINE     */
-       { 2, 6, 4,  3 }, /* SOUND_MIXER_MIC      */
-       { 0, 0, 0,  0 }, /* SOUND_MIXER_CD       */
-       { 0, 0, 0,  0 }, /* SOUND_MIXER_IMIX     */
-       { 0, 0, 0,  0 }, /* SOUND_MIXER_ALTPCM   */
-#if 0
-       { 3, 7, 0, 10 }, /* SOUND_MIXER_RECLEV   */
-       { 0, 0, 0,  0 }, /* SOUND_MIXER_IGAIN    */
-#else
-       { 0, 0, 0,  0 }, /* SOUND_MIXER_RECLEV   */
-       { 3, 7, 0,  7 }, /* SOUND_MIXER_IGAIN    */
-#endif
-       { 0, 0, 0,  0 }, /* SOUND_MIXER_OGAIN    */
-       { 0, 4, 1, 31 }, /* SOUND_MIXER_LINE1    */
-       { 1, 5, 6, 31 }, /* SOUND_MIXER_LINE2    */
-       { 0, 0, 0,  0 }, /* SOUND_MIXER_LINE3    */
-       { 0, 0, 0,  0 }, /* SOUND_MIXER_DIGITAL1 */
-       { 0, 0, 0,  0 }, /* SOUND_MIXER_DIGITAL2 */
-       { 0, 0, 0,  0 }, /* SOUND_MIXER_DIGITAL3 */
-       { 0, 0, 0,  0 }, /* SOUND_MIXER_PHONEIN  */
-       { 0, 0, 0,  0 }, /* SOUND_MIXER_PHONEOUT */
-       { 0, 0, 0,  0 }, /* SOUND_MIXER_VIDEO    */
-       { 0, 0, 0,  0 }, /* SOUND_MIXER_RADIO    */
-       { 0, 0, 0,  0 }  /* SOUND_MIXER_MONITOR  */
-};
-
-static void
-waveartist_mixer_update(struct wavnc_info *devc, int whichDev)
-{
-       unsigned int lev_left, lev_right;
-
-       lev_left  = devc->levels[whichDev] & 0xff;
-       lev_right = devc->levels[whichDev] >> 8;
-
-       if (lev_left > 100)
-               lev_left = 100;
-       if (lev_right > 100)
-               lev_right = 100;
-
-#define SCALE(lev,max) ((lev) * (max) / 100)
-
-       if (machine_is_netwinder() && whichDev == SOUND_MIXER_PHONEOUT)
-               whichDev = SOUND_MIXER_VOLUME;
-
-       if (mix_devs[whichDev].reg_l || mix_devs[whichDev].reg_r) {
-               const struct mix_ent *mix = mix_devs + whichDev;
-               unsigned int mask, left, right;
-
-               mask = mix->max << mix->shift;
-               lev_left  = SCALE(lev_left,  mix->max) << mix->shift;
-               lev_right = SCALE(lev_right, mix->max) << mix->shift;
-
-               /* read left setting */
-               left  = waveartist_cmd1_r(devc, WACMD_GET_LEVEL |
-                                              mix->reg_l << 8);
-
-               /* read right setting */
-               right = waveartist_cmd1_r(devc, WACMD_GET_LEVEL |
-                                               mix->reg_r << 8);
-
-               left  = (left  & ~mask) | (lev_left  & mask);
-               right = (right & ~mask) | (lev_right & mask);
-
-               /* write left,right back */
-               waveartist_cmd3(devc, WACMD_SET_MIXER, left, right);
-       } else {
-               switch(whichDev) {
-               case SOUND_MIXER_PCM:
-                       waveartist_cmd3(devc, WACMD_SET_LEVEL,
-                                       SCALE(lev_left,  32767),
-                                       SCALE(lev_right, 32767));
-                       break;
-
-               case SOUND_MIXER_SYNTH:
-                       waveartist_cmd3(devc, 0x0100 | WACMD_SET_LEVEL,
-                                       SCALE(lev_left,  32767),
-                                       SCALE(lev_right, 32767));
-                       break;
-               }
-       }
-}
-
-/*
- * Set the ADC MUX to the specified values.  We do NOT do any
- * checking of the values passed, since we assume that the
- * relevant *_select_input function has done that for us.
- */
-static void
-waveartist_set_adc_mux(struct wavnc_info *devc, char left_dev,
-                      char right_dev)
-{
-       unsigned int reg_08, reg_09;
-
-       reg_08 = waveartist_cmd1_r(devc, WACMD_GET_LEVEL | 0x0800);
-       reg_09 = waveartist_cmd1_r(devc, WACMD_GET_LEVEL | 0x0900);
-
-       reg_08 = (reg_08 & ~0x3f) | right_dev << 3 | left_dev;
-
-       waveartist_cmd3(devc, WACMD_SET_MIXER, reg_08, reg_09);
-}
-
-/*
- * Decode a recording mask into a mixer selection as follows:
- *
- *     OSS Source      WA Source       Actual source
- *  SOUND_MASK_IMIX    Mixer           Mixer output (same as AD1848)
- *  SOUND_MASK_LINE    Line            Line in
- *  SOUND_MASK_LINE1   Aux 1           Aux 1 in
- *  SOUND_MASK_LINE2   Aux 2           Aux 2 in
- *  SOUND_MASK_MIC     Mic             Microphone
- */
-static unsigned int
-waveartist_select_input(struct wavnc_info *devc, unsigned int recmask,
-                       unsigned char *dev_l, unsigned char *dev_r)
-{
-       unsigned int recdev = ADC_MUX_NONE;
-
-       if (recmask & SOUND_MASK_IMIX) {
-               recmask = SOUND_MASK_IMIX;
-               recdev = ADC_MUX_MIXER;
-       } else if (recmask & SOUND_MASK_LINE2) {
-               recmask = SOUND_MASK_LINE2;
-               recdev = ADC_MUX_AUX2;
-       } else if (recmask & SOUND_MASK_LINE1) {
-               recmask = SOUND_MASK_LINE1;
-               recdev = ADC_MUX_AUX1;
-       } else if (recmask & SOUND_MASK_LINE) {
-               recmask = SOUND_MASK_LINE;
-               recdev = ADC_MUX_LINE;
-       } else if (recmask & SOUND_MASK_MIC) {
-               recmask = SOUND_MASK_MIC;
-               recdev = ADC_MUX_MIC;
-       }
-
-       *dev_l = *dev_r = recdev;
-
-       return recmask;
-}
-
-static int
-waveartist_decode_mixer(struct wavnc_info *devc, int dev,
-                       unsigned char lev_l,
-                       unsigned char lev_r)
-{
-       switch (dev) {
-       case SOUND_MIXER_VOLUME:
-       case SOUND_MIXER_SYNTH:
-       case SOUND_MIXER_PCM:
-       case SOUND_MIXER_LINE:
-       case SOUND_MIXER_MIC:
-       case SOUND_MIXER_IGAIN:
-       case SOUND_MIXER_LINE1:
-       case SOUND_MIXER_LINE2:
-               devc->levels[dev] = lev_l | lev_r << 8;
-               break;
-
-       case SOUND_MIXER_IMIX:
-               break;
-
-       default:
-               dev = -EINVAL;
-               break;
-       }
-
-       return dev;
-}
-
-static int waveartist_get_mixer(struct wavnc_info *devc, int dev)
-{
-       return devc->levels[dev];
-}
-
-static const struct waveartist_mixer_info waveartist_mixer = {
-       .supported_devs = SUPPORTED_MIXER_DEVICES | SOUND_MASK_IGAIN,
-       .recording_devs = SOUND_MASK_LINE  | SOUND_MASK_MIC   |
-                       SOUND_MASK_LINE1 | SOUND_MASK_LINE2 |
-                       SOUND_MASK_IMIX,
-       .stereo_devs    = (SUPPORTED_MIXER_DEVICES | SOUND_MASK_IGAIN) & ~
-                       (SOUND_MASK_SPEAKER | SOUND_MASK_IMIX),
-       .select_input   = waveartist_select_input,
-       .decode_mixer   = waveartist_decode_mixer,
-       .get_mixer      = waveartist_get_mixer,
-};
-
-static void
-waveartist_set_recmask(struct wavnc_info *devc, unsigned int recmask)
-{
-       unsigned char dev_l, dev_r;
-
-       recmask &= devc->mix->recording_devs;
-
-       /*
-        * If more than one recording device selected,
-        * disable the device that is currently in use.
-        */
-       if (hweight32(recmask) > 1)
-               recmask &= ~devc->recmask;
-
-       /*
-        * Translate the recording device mask into
-        * the ADC multiplexer settings.
-        */
-       devc->recmask = devc->mix->select_input(devc, recmask,
-                                               &dev_l, &dev_r);
-
-       waveartist_set_adc_mux(devc, dev_l, dev_r);
-}
-
-static int
-waveartist_set_mixer(struct wavnc_info *devc, int dev, unsigned int level)
-{
-       unsigned int lev_left  = level & 0x00ff;
-       unsigned int lev_right = (level & 0xff00) >> 8;
-
-       if (lev_left > 100)
-               lev_left = 100;
-       if (lev_right > 100)
-               lev_right = 100;
-
-       /*
-        * Mono devices have their right volume forced to their
-        * left volume.  (from ALSA driver OSS emulation).
-        */
-       if (!(devc->mix->stereo_devs & (1 << dev)))
-               lev_right = lev_left;
-
-       dev = devc->mix->decode_mixer(devc, dev, lev_left, lev_right);
-
-       if (dev >= 0)
-               waveartist_mixer_update(devc, dev);
-
-       return dev < 0 ? dev : 0;
-}
-
-static int
-waveartist_mixer_ioctl(int dev, unsigned int cmd, void __user * arg)
-{
-       struct wavnc_info *devc = (struct wavnc_info *)audio_devs[dev]->devc;
-       int ret = 0, val, nr;
-
-       /*
-        * All SOUND_MIXER_* ioctls use type 'M'
-        */
-       if (((cmd >> 8) & 255) != 'M')
-               return -ENOIOCTLCMD;
-
-#ifdef CONFIG_ARCH_NETWINDER
-       if (machine_is_netwinder()) {
-               ret = vnc_private_ioctl(dev, cmd, arg);
-               if (ret != -ENOIOCTLCMD)
-                       return ret;
-               else
-                       ret = 0;
-       }
-#endif
-
-       nr = cmd & 0xff;
-
-       if (_SIOC_DIR(cmd) & _SIOC_WRITE) {
-               if (get_user(val, (int __user *)arg))
-                       return -EFAULT;
-
-               switch (nr) {
-               case SOUND_MIXER_RECSRC:
-                       waveartist_set_recmask(devc, val);
-                       break;
-
-               default:
-                       ret = -EINVAL;
-                       if (nr < SOUND_MIXER_NRDEVICES &&
-                           devc->mix->supported_devs & (1 << nr))
-                               ret = waveartist_set_mixer(devc, nr, val);
-               }
-       }
-
-       if (ret == 0 && _SIOC_DIR(cmd) & _SIOC_READ) {
-               ret = -EINVAL;
-
-               switch (nr) {
-               case SOUND_MIXER_RECSRC:
-                       ret = devc->recmask;
-                       break;
-
-               case SOUND_MIXER_DEVMASK:
-                       ret = devc->mix->supported_devs;
-                       break;
-
-               case SOUND_MIXER_STEREODEVS:
-                       ret = devc->mix->stereo_devs;
-                       break;
-
-               case SOUND_MIXER_RECMASK:
-                       ret = devc->mix->recording_devs;
-                       break;
-
-               case SOUND_MIXER_CAPS:
-                       ret = SOUND_CAP_EXCL_INPUT;
-                       break;
-
-               default:
-                       if (nr < SOUND_MIXER_NRDEVICES)
-                               ret = devc->mix->get_mixer(devc, nr);
-                       break;
-               }
-
-               if (ret >= 0)
-                       ret = put_user(ret, (int __user *)arg) ? -EFAULT : 0;
-       }
-
-       return ret;
-}
-
-static struct mixer_operations waveartist_mixer_operations =
-{
-       .owner  = THIS_MODULE,
-       .id     = "WaveArtist",
-       .name   = "WaveArtist",
-       .ioctl  = waveartist_mixer_ioctl
-};
-
-static void
-waveartist_mixer_reset(struct wavnc_info *devc)
-{
-       int i;
-
-       if (debug_flg & DEBUG_MIXER)
-               printk("%s: mixer_reset\n", devc->hw.name);
-
-       /*
-        * reset mixer cmd
-        */
-       waveartist_cmd1(devc, WACMD_RST_MIXER);
-
-       /*
-        * set input for ADC to come from 'quiet'
-        * turn on default modes
-        */
-       waveartist_cmd3(devc, WACMD_SET_MIXER, 0x9800, 0xa836);
-
-       /*
-        * set mixer input select to none, RX filter gains 0 dB
-        */
-       waveartist_cmd3(devc, WACMD_SET_MIXER, 0x4c00, 0x8c00);
-
-       /*
-        * set bit 0 reg 2 to 1 - unmute MonoOut
-        */
-       waveartist_cmd3(devc, WACMD_SET_MIXER, 0x2801, 0x6800);
-
-       /* set default input device = internal mic
-        * current recording device = none
-        */
-       waveartist_set_recmask(devc, 0);
-
-       for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
-               waveartist_mixer_update(devc, i);
-}
-
-static int __init waveartist_init(struct wavnc_info *devc)
-{
-       struct wavnc_port_info *portc;
-       char rev[3], dev_name[64];
-       int my_dev;
-
-       if (waveartist_reset(devc))
-               return -ENODEV;
-
-       sprintf(dev_name, "%s (%s", devc->hw.name, devc->chip_name);
-
-       if (waveartist_getrev(devc, rev)) {
-               strcat(dev_name, " rev. ");
-               strcat(dev_name, rev);
-       }
-       strcat(dev_name, ")");
-
-       conf_printf2(dev_name, devc->hw.io_base, devc->hw.irq,
-                    devc->hw.dma, devc->hw.dma2);
-
-       portc = kzalloc(sizeof(struct wavnc_port_info), GFP_KERNEL);
-       if (portc == NULL)
-               goto nomem;
-
-       my_dev = sound_install_audiodrv(AUDIO_DRIVER_VERSION, dev_name,
-                       &waveartist_audio_driver, sizeof(struct audio_driver),
-                       devc->audio_flags, AFMT_U8 | AFMT_S16_LE | AFMT_S8,
-                       devc, devc->hw.dma, devc->hw.dma2);
-
-       if (my_dev < 0)
-               goto free;
-
-       audio_devs[my_dev]->portc = portc;
-
-       waveartist_mixer_reset(devc);
-
-       /*
-        * clear any pending interrupt
-        */
-       waveartist_iack(devc);
-
-       if (request_irq(devc->hw.irq, waveartist_intr, 0, devc->hw.name, devc) < 0) {
-               printk(KERN_ERR "%s: IRQ %d in use\n",
-                       devc->hw.name, devc->hw.irq);
-               goto uninstall;
-       }
-
-       if (sound_alloc_dma(devc->hw.dma, devc->hw.name)) {
-               printk(KERN_ERR "%s: Can't allocate DMA%d\n",
-                       devc->hw.name, devc->hw.dma);
-               goto uninstall_irq;
-       }
-
-       if (devc->hw.dma != devc->hw.dma2 && devc->hw.dma2 != NO_DMA)
-               if (sound_alloc_dma(devc->hw.dma2, devc->hw.name)) {
-                       printk(KERN_ERR "%s: can't allocate DMA%d\n",
-                               devc->hw.name, devc->hw.dma2);
-                       goto uninstall_dma;
-               }
-
-       waveartist_set_ctlr(&devc->hw, 0, DMA1_IE | DMA0_IE);
-
-       audio_devs[my_dev]->mixer_dev =
-               sound_install_mixer(MIXER_DRIVER_VERSION,
-                               dev_name,
-                               &waveartist_mixer_operations,
-                               sizeof(struct mixer_operations),
-                               devc);
-
-       return my_dev;
-
-uninstall_dma:
-       sound_free_dma(devc->hw.dma);
-
-uninstall_irq:
-       free_irq(devc->hw.irq, devc);
-
-uninstall:
-       sound_unload_audiodev(my_dev);
-
-free:
-       kfree(portc);
-
-nomem:
-       return -1;
-}
-
-static int __init probe_waveartist(struct address_info *hw_config)
-{
-       struct wavnc_info *devc = &adev_info[nr_waveartist_devs];
-
-       if (nr_waveartist_devs >= MAX_AUDIO_DEV) {
-               printk(KERN_WARNING "waveartist: too many audio devices\n");
-               return 0;
-       }
-
-       if (!request_region(hw_config->io_base, 15, hw_config->name))  {
-               printk(KERN_WARNING "WaveArtist: I/O port conflict\n");
-               return 0;
-       }
-
-       if (hw_config->irq > 15 || hw_config->irq < 0) {
-               release_region(hw_config->io_base, 15);
-               printk(KERN_WARNING "WaveArtist: Bad IRQ %d\n",
-                      hw_config->irq);
-               return 0;
-       }
-
-       if (hw_config->dma != 3) {
-               release_region(hw_config->io_base, 15);
-               printk(KERN_WARNING "WaveArtist: Bad DMA %d\n",
-                      hw_config->dma);
-               return 0;
-       }
-
-       hw_config->name = "WaveArtist";
-       devc->hw = *hw_config;
-       devc->open_mode = 0;
-       devc->chip_name = "RWA-010";
-
-       return 1;
-}
-
-static void __init
-attach_waveartist(struct address_info *hw, const struct waveartist_mixer_info *mix)
-{
-       struct wavnc_info *devc = &adev_info[nr_waveartist_devs];
-
-       /*
-        * NOTE! If irq < 0, there is another driver which has allocated the
-        *   IRQ so that this driver doesn't need to allocate/deallocate it.
-        *   The actually used IRQ is ABS(irq).
-        */
-       devc->hw = *hw;
-       devc->hw.irq = (hw->irq > 0) ? hw->irq : 0;
-       devc->open_mode = 0;
-       devc->playback_dev = 0;
-       devc->record_dev = 0;
-       devc->audio_flags = DMA_AUTOMODE;
-       devc->levels = levels;
-
-       if (hw->dma != hw->dma2 && hw->dma2 != NO_DMA)
-               devc->audio_flags |= DMA_DUPLEX;
-
-       devc->mix = mix;
-       devc->dev_no = waveartist_init(devc);
-
-       if (devc->dev_no < 0)
-               release_region(hw->io_base, 15);
-       else {
-#ifdef CONFIG_ARCH_NETWINDER
-               if (machine_is_netwinder()) {
-                       setup_timer(&vnc_timer, vnc_slider_tick,
-                                   nr_waveartist_devs);
-                       mod_timer(&vnc_timer, jiffies);
-
-                       vnc_configure_mixer(devc, 0);
-
-                       devc->no_autoselect = 1;
-               }
-#endif
-               nr_waveartist_devs += 1;
-       }
-}
-
-static void __exit unload_waveartist(struct address_info *hw)
-{
-       struct wavnc_info *devc = NULL;
-       int i;
-
-       for (i = 0; i < nr_waveartist_devs; i++)
-               if (hw->io_base == adev_info[i].hw.io_base) {
-                       devc = adev_info + i;
-                       break;
-               }
-
-       if (devc != NULL) {
-               int mixer;
-
-#ifdef CONFIG_ARCH_NETWINDER
-               if (machine_is_netwinder())
-                       del_timer(&vnc_timer);
-#endif
-
-               release_region(devc->hw.io_base, 15);
-
-               waveartist_set_ctlr(&devc->hw, DMA1_IE|DMA0_IE, 0);
-
-               if (devc->hw.irq >= 0)
-                       free_irq(devc->hw.irq, devc);
-
-               sound_free_dma(devc->hw.dma);
-
-               if (devc->hw.dma != devc->hw.dma2 &&
-                   devc->hw.dma2 != NO_DMA)
-                       sound_free_dma(devc->hw.dma2);
-
-               mixer = audio_devs[devc->dev_no]->mixer_dev;
-
-               if (mixer >= 0)
-                       sound_unload_mixerdev(mixer);
-
-               if (devc->dev_no >= 0)
-                       sound_unload_audiodev(devc->dev_no);
-
-               nr_waveartist_devs -= 1;
-
-               for (; i < nr_waveartist_devs; i++)
-                       adev_info[i] = adev_info[i + 1];
-       } else
-               printk(KERN_WARNING "waveartist: can't find device "
-                      "to unload\n");
-}
-
-#ifdef CONFIG_ARCH_NETWINDER
-
-/*
- * Rebel.com Netwinder specifics...
- */
-
-#include <asm/hardware/dec21285.h>
-#define        VNC_TIMER_PERIOD (HZ/4) //check slider 4 times/sec
-
-#define        MIXER_PRIVATE3_RESET    0x53570000
-#define        MIXER_PRIVATE3_READ     0x53570001
-#define        MIXER_PRIVATE3_WRITE    0x53570002
-
-#define        VNC_MUTE_INTERNAL_SPKR  0x01    //the sw mute on/off control bit
-#define        VNC_MUTE_LINE_OUT       0x10
-#define VNC_PHONE_DETECT       0x20
-#define VNC_HANDSET_DETECT     0x40
-#define VNC_DISABLE_AUTOSWITCH 0x80
-
-static inline void
-vnc_mute_spkr(struct wavnc_info *devc)
-{
-       unsigned long flags;
-
-       raw_spin_lock_irqsave(&nw_gpio_lock, flags);
-       nw_cpld_modify(CPLD_UNMUTE, devc->spkr_mute_state ? 0 : CPLD_UNMUTE);
-       raw_spin_unlock_irqrestore(&nw_gpio_lock, flags);
-}
-
-static void
-vnc_mute_lout(struct wavnc_info *devc)
-{
-       unsigned int left, right;
-
-       left  = waveartist_cmd1_r(devc, WACMD_GET_LEVEL);
-       right = waveartist_cmd1_r(devc, WACMD_GET_LEVEL | 0x400);
-
-       if (devc->line_mute_state) {
-               left &= ~1;
-               right &= ~1;
-       } else {
-               left |= 1;
-               right |= 1;
-       }
-       waveartist_cmd3(devc, WACMD_SET_MIXER, left, right);
-               
-}
-
-static int
-vnc_volume_slider(struct wavnc_info *devc)
-{
-       static signed int old_slider_volume;
-       unsigned long flags;
-       signed int volume = 255;
-
-       *CSR_TIMER1_LOAD = 0x00ffffff;
-
-       spin_lock_irqsave(&waveartist_lock, flags);
-
-       outb(0xFF, 0x201);
-       *CSR_TIMER1_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_DIV1;
-
-       while (volume && (inb(0x201) & 0x01))
-               volume--;
-
-       *CSR_TIMER1_CNTL = 0;
-
-       spin_unlock_irqrestore(&waveartist_lock,flags);
-       
-       volume = 0x00ffffff - *CSR_TIMER1_VALUE;
-
-
-#ifndef REVERSE
-       volume = 150 - (volume >> 5);
-#else
-       volume = (volume >> 6) - 25;
-#endif
-
-       if (volume < 0)
-               volume = 0;
-
-       if (volume > 100)
-               volume = 100;
-
-       /*
-        * slider quite often reads +-8, so debounce this random noise
-        */
-       if (abs(volume - old_slider_volume) > 7) {
-               old_slider_volume = volume;
-
-               if (debug_flg & DEBUG_MIXER)
-                       printk(KERN_DEBUG "Slider volume: %d.\n", volume);
-       }
-
-       return old_slider_volume;
-}
-
-/*
- * Decode a recording mask into a mixer selection on the NetWinder
- * as follows:
- *
- *     OSS Source      WA Source       Actual source
- *  SOUND_MASK_IMIX    Mixer           Mixer output (same as AD1848)
- *  SOUND_MASK_LINE    Line            Line in
- *  SOUND_MASK_LINE1   Left Mic        Handset
- *  SOUND_MASK_PHONEIN Left Aux        Telephone microphone
- *  SOUND_MASK_MIC     Right Mic       Builtin microphone
- */
-static unsigned int
-netwinder_select_input(struct wavnc_info *devc, unsigned int recmask,
-                      unsigned char *dev_l, unsigned char *dev_r)
-{
-       unsigned int recdev_l = ADC_MUX_NONE, recdev_r = ADC_MUX_NONE;
-
-       if (recmask & SOUND_MASK_IMIX) {
-               recmask = SOUND_MASK_IMIX;
-               recdev_l = ADC_MUX_MIXER;
-               recdev_r = ADC_MUX_MIXER;
-       } else if (recmask & SOUND_MASK_LINE) {
-               recmask = SOUND_MASK_LINE;
-               recdev_l = ADC_MUX_LINE;
-               recdev_r = ADC_MUX_LINE;
-       } else if (recmask & SOUND_MASK_LINE1) {
-               recmask = SOUND_MASK_LINE1;
-               waveartist_cmd1(devc, WACMD_SET_MONO); /* left */
-               recdev_l = ADC_MUX_MIC;
-               recdev_r = ADC_MUX_NONE;
-       } else if (recmask & SOUND_MASK_PHONEIN) {
-               recmask = SOUND_MASK_PHONEIN;
-               waveartist_cmd1(devc, WACMD_SET_MONO); /* left */
-               recdev_l = ADC_MUX_AUX1;
-               recdev_r = ADC_MUX_NONE;
-       } else if (recmask & SOUND_MASK_MIC) {
-               recmask = SOUND_MASK_MIC;
-               waveartist_cmd1(devc, WACMD_SET_MONO | 0x100);  /* right */
-               recdev_l = ADC_MUX_NONE;
-               recdev_r = ADC_MUX_MIC;
-       }
-
-       *dev_l = recdev_l;
-       *dev_r = recdev_r;
-
-       return recmask;
-}
-
-static int
-netwinder_decode_mixer(struct wavnc_info *devc, int dev, unsigned char lev_l,
-                      unsigned char lev_r)
-{
-       switch (dev) {
-       case SOUND_MIXER_VOLUME:
-       case SOUND_MIXER_SYNTH:
-       case SOUND_MIXER_PCM:
-       case SOUND_MIXER_LINE:
-       case SOUND_MIXER_IGAIN:
-               devc->levels[dev] = lev_l | lev_r << 8;
-               break;
-
-       case SOUND_MIXER_MIC:           /* right mic only */
-               devc->levels[SOUND_MIXER_MIC] &= 0xff;
-               devc->levels[SOUND_MIXER_MIC] |= lev_l << 8;
-               break;
-
-       case SOUND_MIXER_LINE1:         /* left mic only  */
-               devc->levels[SOUND_MIXER_MIC] &= 0xff00;
-               devc->levels[SOUND_MIXER_MIC] |= lev_l;
-               dev = SOUND_MIXER_MIC;
-               break;
-
-       case SOUND_MIXER_PHONEIN:       /* left aux only  */
-               devc->levels[SOUND_MIXER_LINE1] = lev_l;
-               dev = SOUND_MIXER_LINE1;
-               break;
-
-       case SOUND_MIXER_IMIX:
-       case SOUND_MIXER_PHONEOUT:
-               break;
-
-       default:
-               dev = -EINVAL;
-               break;
-       }
-       return dev;
-}
-
-static int netwinder_get_mixer(struct wavnc_info *devc, int dev)
-{
-       int levels;
-
-       switch (dev) {
-       case SOUND_MIXER_VOLUME:
-       case SOUND_MIXER_SYNTH:
-       case SOUND_MIXER_PCM:
-       case SOUND_MIXER_LINE:
-       case SOUND_MIXER_IGAIN:
-               levels = devc->levels[dev];
-               break;
-
-       case SOUND_MIXER_MIC:           /* builtin mic: right mic only */
-               levels = devc->levels[SOUND_MIXER_MIC] >> 8;
-               levels |= levels << 8;
-               break;
-
-       case SOUND_MIXER_LINE1:         /* handset mic: left mic only */
-               levels = devc->levels[SOUND_MIXER_MIC] & 0xff;
-               levels |= levels << 8;
-               break;
-
-       case SOUND_MIXER_PHONEIN:       /* phone mic: left aux1 only */
-               levels = devc->levels[SOUND_MIXER_LINE1] & 0xff;
-               levels |= levels << 8;
-               break;
-
-       default:
-               levels = 0;
-       }
-
-       return levels;
-}
-
-/*
- * Waveartist specific mixer information.
- */
-static const struct waveartist_mixer_info netwinder_mixer = {
-       .supported_devs = SOUND_MASK_VOLUME  | SOUND_MASK_SYNTH   |
-                       SOUND_MASK_PCM     | SOUND_MASK_SPEAKER |
-                       SOUND_MASK_LINE    | SOUND_MASK_MIC     |
-                       SOUND_MASK_IMIX    | SOUND_MASK_LINE1   |
-                       SOUND_MASK_PHONEIN | SOUND_MASK_PHONEOUT|
-                       SOUND_MASK_IGAIN,
-
-       .recording_devs = SOUND_MASK_LINE    | SOUND_MASK_MIC     |
-                       SOUND_MASK_IMIX    | SOUND_MASK_LINE1   |
-                       SOUND_MASK_PHONEIN,
-
-       .stereo_devs    = SOUND_MASK_VOLUME  | SOUND_MASK_SYNTH   |
-                       SOUND_MASK_PCM     | SOUND_MASK_LINE    |
-                       SOUND_MASK_IMIX    | SOUND_MASK_IGAIN,
-
-       .select_input   = netwinder_select_input,
-       .decode_mixer   = netwinder_decode_mixer,
-       .get_mixer      = netwinder_get_mixer,
-};
-
-static void
-vnc_configure_mixer(struct wavnc_info *devc, unsigned int recmask)
-{
-       if (!devc->no_autoselect) {
-               if (devc->handset_detect) {
-                       recmask = SOUND_MASK_LINE1;
-                       devc->spkr_mute_state = devc->line_mute_state = 1;
-               } else if (devc->telephone_detect) {
-                       recmask = SOUND_MASK_PHONEIN;
-                       devc->spkr_mute_state = devc->line_mute_state = 1;
-               } else {
-                       /* unless someone has asked for LINE-IN,
-                        * we default to MIC
-                        */
-                       if ((devc->recmask & SOUND_MASK_LINE) == 0)
-                               devc->recmask = SOUND_MASK_MIC;
-                       devc->spkr_mute_state = devc->line_mute_state = 0;
-               }
-               vnc_mute_spkr(devc);
-               vnc_mute_lout(devc);
-
-               if (recmask != devc->recmask)
-                       waveartist_set_recmask(devc, recmask);
-       }
-}
-
-static int
-vnc_slider(struct wavnc_info *devc)
-{
-       signed int slider_volume;
-       unsigned int temp, old_hs, old_td;
-
-       /*
-        * read the "buttons" state.
-        *  Bit 4 = 0 means handset present
-        *  Bit 5 = 1 means phone offhook
-        */
-       temp = inb(0x201);
-
-       old_hs = devc->handset_detect;
-       old_td = devc->telephone_detect;
-
-       devc->handset_detect = !(temp & 0x10);
-       devc->telephone_detect = !!(temp & 0x20);
-
-       if (!devc->no_autoselect &&
-           (old_hs != devc->handset_detect ||
-            old_td != devc->telephone_detect))
-               vnc_configure_mixer(devc, devc->recmask);
-
-       slider_volume = vnc_volume_slider(devc);
-
-       /*
-        * If we're using software controlled volume, and
-        * the slider moves by more than 20%, then we
-        * switch back to slider controlled volume.
-        */
-       if (abs(devc->slider_vol - slider_volume) > 20)
-               devc->use_slider = 1;
-
-       /*
-        * use only left channel
-        */
-       temp = levels[SOUND_MIXER_VOLUME] & 0xFF;
-
-       if (slider_volume != temp && devc->use_slider) {
-               devc->slider_vol = slider_volume;
-
-               waveartist_set_mixer(devc, SOUND_MIXER_VOLUME,
-                       slider_volume | slider_volume << 8);
-
-               return 1;
-       }
-
-       return 0;
-}
-
-static void
-vnc_slider_tick(unsigned long data)
-{
-       int next_timeout;
-
-       if (vnc_slider(adev_info + data))
-               next_timeout = 5;       // mixer reported change
-       else
-               next_timeout = VNC_TIMER_PERIOD;
-
-       mod_timer(&vnc_timer, jiffies + next_timeout);
-}
-
-static int
-vnc_private_ioctl(int dev, unsigned int cmd, int __user * arg)
-{
-       struct wavnc_info *devc = (struct wavnc_info *)audio_devs[dev]->devc;
-       int val;
-
-       switch (cmd) {
-       case SOUND_MIXER_PRIVATE1:
-       {
-               u_int prev_spkr_mute, prev_line_mute, prev_auto_state;
-               int val;
-
-               if (get_user(val, arg))
-                       return -EFAULT;
-
-               /* check if parameter is logical */
-               if (val & ~(VNC_MUTE_INTERNAL_SPKR |
-                           VNC_MUTE_LINE_OUT |
-                           VNC_DISABLE_AUTOSWITCH))
-                       return -EINVAL;
-
-               prev_auto_state = devc->no_autoselect;
-               prev_spkr_mute  = devc->spkr_mute_state;
-               prev_line_mute  = devc->line_mute_state;
-
-               devc->no_autoselect   = (val & VNC_DISABLE_AUTOSWITCH) ? 1 : 0;
-               devc->spkr_mute_state = (val & VNC_MUTE_INTERNAL_SPKR) ? 1 : 0;
-               devc->line_mute_state = (val & VNC_MUTE_LINE_OUT) ? 1 : 0;
-
-               if (prev_spkr_mute != devc->spkr_mute_state)
-                       vnc_mute_spkr(devc);
-
-               if (prev_line_mute != devc->line_mute_state)
-                       vnc_mute_lout(devc);
-
-               if (prev_auto_state != devc->no_autoselect)
-                       vnc_configure_mixer(devc, devc->recmask);
-
-               return 0;
-       }
-
-       case SOUND_MIXER_PRIVATE2:
-               if (get_user(val, arg))
-                       return -EFAULT;
-
-               switch (val) {
-#define VNC_SOUND_PAUSE         0x53    //to pause the DSP
-#define VNC_SOUND_RESUME        0x57    //to unpause the DSP
-               case VNC_SOUND_PAUSE:
-                       waveartist_cmd1(devc, 0x16);
-                       break;
-
-               case VNC_SOUND_RESUME:
-                       waveartist_cmd1(devc, 0x18);
-                       break;
-
-               default:
-                       return -EINVAL;
-               }
-               return 0;
-
-       /* private ioctl to allow bulk access to waveartist */
-       case SOUND_MIXER_PRIVATE3:
-       {
-               unsigned long   flags;
-               int             mixer_reg[15], i, val;
-
-               if (get_user(val, arg))
-                       return -EFAULT;
-               if (copy_from_user(mixer_reg, (void *)val, sizeof(mixer_reg)))
-                       return -EFAULT;
-
-               switch (mixer_reg[14]) {
-               case MIXER_PRIVATE3_RESET:
-                       waveartist_mixer_reset(devc);
-                       break;
-
-               case MIXER_PRIVATE3_WRITE:
-                       waveartist_cmd3(devc, WACMD_SET_MIXER, mixer_reg[0], mixer_reg[4]);
-                       waveartist_cmd3(devc, WACMD_SET_MIXER, mixer_reg[1], mixer_reg[5]);
-                       waveartist_cmd3(devc, WACMD_SET_MIXER, mixer_reg[2], mixer_reg[6]);
-                       waveartist_cmd3(devc, WACMD_SET_MIXER, mixer_reg[3], mixer_reg[7]);
-                       waveartist_cmd3(devc, WACMD_SET_MIXER, mixer_reg[8], mixer_reg[9]);
-
-                       waveartist_cmd3(devc, WACMD_SET_LEVEL, mixer_reg[10], mixer_reg[11]);
-                       waveartist_cmd3(devc, WACMD_SET_LEVEL, mixer_reg[12], mixer_reg[13]);
-                       break;
-
-               case MIXER_PRIVATE3_READ:
-                       spin_lock_irqsave(&waveartist_lock, flags);
-
-                       for (i = 0x30; i < 14 << 8; i += 1 << 8)
-                               waveartist_cmd(devc, 1, &i, 1, mixer_reg + (i >> 8));
-
-                       spin_unlock_irqrestore(&waveartist_lock, flags);
-
-                       if (copy_to_user((void *)val, mixer_reg, sizeof(mixer_reg)))
-                               return -EFAULT;
-                       break;
-
-               default:
-                       return -EINVAL;
-               }
-               return 0;
-       }
-
-       /* read back the state from PRIVATE1 */
-       case SOUND_MIXER_PRIVATE4:
-               val = (devc->spkr_mute_state  ? VNC_MUTE_INTERNAL_SPKR : 0) |
-                     (devc->line_mute_state  ? VNC_MUTE_LINE_OUT      : 0) |
-                     (devc->handset_detect   ? VNC_HANDSET_DETECT     : 0) |
-                     (devc->telephone_detect ? VNC_PHONE_DETECT       : 0) |
-                     (devc->no_autoselect    ? VNC_DISABLE_AUTOSWITCH : 0);
-
-               return put_user(val, arg) ? -EFAULT : 0;
-       }
-
-       if (_SIOC_DIR(cmd) & _SIOC_WRITE) {
-               /*
-                * special case for master volume: if we
-                * received this call - switch from hw
-                * volume control to a software volume
-                * control, till the hw volume is modified
-                * to signal that user wants to be back in
-                * hardware...
-                */
-               if ((cmd & 0xff) == SOUND_MIXER_VOLUME)
-                       devc->use_slider = 0;
-
-               /* speaker output            */
-               if ((cmd & 0xff) == SOUND_MIXER_SPEAKER) {
-                       unsigned int val, l, r;
-
-                       if (get_user(val, arg))
-                               return -EFAULT;
-
-                       l = val & 0x7f;
-                       r = (val & 0x7f00) >> 8;
-                       val = (l + r) / 2;
-                       devc->levels[SOUND_MIXER_SPEAKER] = val | (val << 8);
-                       devc->spkr_mute_state = (val <= 50);
-                       vnc_mute_spkr(devc);
-                       return 0;
-               }
-       }
-
-       return -ENOIOCTLCMD;
-}
-
-#endif
-
-static struct address_info cfg;
-
-static int attached;
-
-static int __initdata io = 0;
-static int __initdata irq = 0;
-static int __initdata dma = 0;
-static int __initdata dma2 = 0;
-
-
-static int __init init_waveartist(void)
-{
-       const struct waveartist_mixer_info *mix;
-
-       if (!io && machine_is_netwinder()) {
-               /*
-                * The NetWinder WaveArtist is at a fixed address.
-                * If the user does not supply an address, use the
-                * well-known parameters.
-                */
-               io   = 0x250;
-               irq  = 12;
-               dma  = 3;
-               dma2 = 7;
-       }
-
-       mix = &waveartist_mixer;
-#ifdef CONFIG_ARCH_NETWINDER
-       if (machine_is_netwinder())
-               mix = &netwinder_mixer;
-#endif
-
-       cfg.io_base = io;
-       cfg.irq = irq;
-       cfg.dma = dma;
-       cfg.dma2 = dma2;
-
-       if (!probe_waveartist(&cfg))
-               return -ENODEV;
-
-       attach_waveartist(&cfg, mix);
-       attached = 1;
-
-       return 0;
-}
-
-static void __exit cleanup_waveartist(void)
-{
-       if (attached)
-               unload_waveartist(&cfg);
-}
-
-module_init(init_waveartist);
-module_exit(cleanup_waveartist);
-
-#ifndef MODULE
-static int __init setup_waveartist(char *str)
-{
-       /* io, irq, dma, dma2 */
-       int ints[5];
-       
-       str = get_options(str, ARRAY_SIZE(ints), ints);
-       
-       io      = ints[1];
-       irq     = ints[2];
-       dma     = ints[3];
-       dma2    = ints[4];
-
-       return 1;
-}
-__setup("waveartist=", setup_waveartist);
-#endif
-
-MODULE_DESCRIPTION("Rockwell WaveArtist RWA-010 sound driver");
-module_param_hw(io, int, ioport, 0);           /* IO base */
-module_param_hw(irq, int, irq, 0);             /* IRQ */
-module_param_hw(dma, int, dma, 0);             /* DMA */
-module_param_hw(dma2, int, dma, 0);            /* DMA2 */
-MODULE_LICENSE("GPL");