scheduled OSS driver removal

This patch contains the scheduled removal of OSS drivers whose config
options have been removed in 2.6.23.

Signed-off-by: Adrian Bunk <bunk@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index a7d9d17..68ce130 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -208,13 +208,6 @@
 
 ---------------------------
 
-What:  drivers depending on OSS_OBSOLETE
-When:  options in 2.6.23, code in 2.6.25
-Why:   obsolete OSS drivers
-Who:   Adrian Bunk <bunk@stusta.de>
-
----------------------------
-
 What: libata spindown skipping and warning
 When: Dec 2008
 Why:  Some halt(8) implementations synchronize caches for and spin
diff --git a/arch/ppc/platforms/prep_setup.c b/arch/ppc/platforms/prep_setup.c
index 3c56654..3844985 100644
--- a/arch/ppc/platforms/prep_setup.c
+++ b/arch/ppc/platforms/prep_setup.c
@@ -91,20 +91,11 @@
 #define cached_21	(((char *)(ppc_cached_irq_mask))[3])
 #define cached_A1	(((char *)(ppc_cached_irq_mask))[2])
 
-#ifdef CONFIG_SOUND_CS4232
-long ppc_cs4232_dma, ppc_cs4232_dma2;
-#endif
-
 extern PTE *Hash, *Hash_end;
 extern unsigned long Hash_size, Hash_mask;
 extern int probingmem;
 extern unsigned long loops_per_jiffy;
 
-#ifdef CONFIG_SOUND_CS4232
-EXPORT_SYMBOL(ppc_cs4232_dma);
-EXPORT_SYMBOL(ppc_cs4232_dma2);
-#endif
-
 /* useful ISA ports */
 #define PREP_SYSCTL	0x81c
 /* present in the IBM reference design; possibly identical in Mot boxes: */
@@ -569,74 +560,6 @@
 	return 0;
 }
 
-#ifdef CONFIG_SOUND_CS4232
-static long __init masktoint(unsigned int i)
-{
-	int t = -1;
-	while (i >> ++t)
-		;
-	return (t-1);
-}
-
-/*
- * ppc_cs4232_dma and ppc_cs4232_dma2 are used in include/asm/dma.h
- * to distinguish sound dma-channels from others. This is because
- * blocksize on 16 bit dma-channels 5,6,7 is 128k, but
- * the cs4232.c uses 64k like on 8 bit dma-channels 0,1,2,3
- */
-
-static void __init prep_init_sound(void)
-{
-	PPC_DEVICE *audiodevice = NULL;
-
-	/*
-	 * Get the needed resource information from residual data.
-	 *
-	 */
-	if (have_residual_data)
-		audiodevice = residual_find_device(~0, NULL,
-				MultimediaController, AudioController, -1, 0);
-
-	if (audiodevice != NULL) {
-		PnP_TAG_PACKET *pkt;
-
-		pkt = PnP_find_packet((unsigned char *)&res->DevicePnPHeap[audiodevice->AllocatedOffset],
-				S5_Packet, 0);
-		if (pkt != NULL)
-			ppc_cs4232_dma = masktoint(pkt->S5_Pack.DMAMask);
-		pkt = PnP_find_packet((unsigned char*)&res->DevicePnPHeap[audiodevice->AllocatedOffset],
-				S5_Packet, 1);
-		if (pkt != NULL)
-			ppc_cs4232_dma2 = masktoint(pkt->S5_Pack.DMAMask);
-	}
-
-	/*
-	 * These are the PReP specs' defaults for the cs4231.  We use these
-	 * as fallback incase we don't have residual data.
-	 * At least the IBM Thinkpad 850 with IDE DMA Channels at 6 and 7
-	 * will use the other values.
-	 */
-	if (audiodevice == NULL) {
-		switch (_prep_type) {
-		case _PREP_IBM:
-			ppc_cs4232_dma = 1;
-			ppc_cs4232_dma2 = -1;
-			break;
-		default:
-			ppc_cs4232_dma = 6;
-			ppc_cs4232_dma2 = 7;
-		}
-	}
-
-	/*
-	 * Find a way to push this information to the cs4232 driver
-	 * Give it out with printk, when not in cmd_line?
-	 * Append it to cmd_line and boot_command_line?
-	 * Format is cs4232=io,irq,dma,dma2
-	 */
-}
-#endif /* CONFIG_SOUND_CS4232 */
-
 /*
  * Fill out screen_info according to the residual data. This allows us to use
  * at least vesafb.
@@ -898,10 +821,6 @@
 		}
 	}
 
-#ifdef CONFIG_SOUND_CS4232
-	prep_init_sound();
-#endif /* CONFIG_SOUND_CS4232 */
-
 	prep_init_vesa();
 
 	switch (_prep_type) {
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index 28ddd14..850b8c6 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -22,7 +22,6 @@
 obj-$(CONFIG_VIDEO_TVAUDIO) += tvaudio.o
 obj-$(CONFIG_VIDEO_TDA7432) += tda7432.o
 obj-$(CONFIG_VIDEO_TDA9875) += tda9875.o
-obj-$(CONFIG_SOUND_TVMIXER) += tvmixer.o
 
 obj-$(CONFIG_VIDEO_SAA6588) += saa6588.o
 obj-$(CONFIG_VIDEO_SAA5246A) += saa5246a.o
diff --git a/drivers/media/video/tvmixer.c b/drivers/media/video/tvmixer.c
deleted file mode 100644
index 9fa5b70..0000000
--- a/drivers/media/video/tvmixer.c
+++ /dev/null
@@ -1,336 +0,0 @@
-/*
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/videodev.h>
-#include <linux/init.h>
-#include <linux/kdev_t.h>
-#include <linux/sound.h>
-#include <linux/soundcard.h>
-
-#include <asm/semaphore.h>
-#include <asm/uaccess.h>
-
-
-#define DEV_MAX  4
-
-static int devnr = -1;
-module_param(devnr, int, 0644);
-
-MODULE_AUTHOR("Gerd Knorr");
-MODULE_LICENSE("GPL");
-
-/* ----------------------------------------------------------------------- */
-
-struct TVMIXER {
-	struct i2c_client *dev;
-	int minor;
-	int count;
-};
-
-static struct TVMIXER devices[DEV_MAX];
-
-static int tvmixer_adapters(struct i2c_adapter *adap);
-static int tvmixer_clients(struct i2c_client *client);
-
-/* ----------------------------------------------------------------------- */
-
-static int mix_to_v4l(int i)
-{
-	int r;
-
-	r = ((i & 0xff) * 65536 + 50) / 100;
-	if (r > 65535) r = 65535;
-	if (r <     0) r =     0;
-	return r;
-}
-
-static int v4l_to_mix(int i)
-{
-	int r;
-
-	r = (i * 100 + 32768) / 65536;
-	if (r > 100) r = 100;
-	if (r <   0) r =   0;
-	return r | (r << 8);
-}
-
-static int v4l_to_mix2(int l, int r)
-{
-	r = (r * 100 + 32768) / 65536;
-	if (r > 100) r = 100;
-	if (r <   0) r =   0;
-	l = (l * 100 + 32768) / 65536;
-	if (l > 100) l = 100;
-	if (l <   0) l =   0;
-	return (r << 8) | l;
-}
-
-static int tvmixer_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
-	struct video_audio va;
-	int left,right,ret,val = 0;
-	struct TVMIXER *mix = file->private_data;
-	struct i2c_client *client = mix->dev;
-	void __user *argp = (void __user *)arg;
-	int __user *p = argp;
-
-	if (NULL == client)
-		return -ENODEV;
-
-	if (cmd == SOUND_MIXER_INFO) {
-		mixer_info info;
-		strlcpy(info.id, "tv card", sizeof(info.id));
-		strlcpy(info.name, client->name, sizeof(info.name));
-		info.modify_counter = 42 /* FIXME */;
-		if (copy_to_user(argp, &info, sizeof(info)))
-			return -EFAULT;
-		return 0;
-	}
-	if (cmd == SOUND_OLD_MIXER_INFO) {
-		_old_mixer_info info;
-		strlcpy(info.id, "tv card", sizeof(info.id));
-		strlcpy(info.name, client->name, sizeof(info.name));
-		if (copy_to_user(argp, &info, sizeof(info)))
-			return -EFAULT;
-		return 0;
-	}
-	if (cmd == OSS_GETVERSION)
-		return put_user(SOUND_VERSION, p);
-
-	if (_SIOC_DIR(cmd) & _SIOC_WRITE)
-		if (get_user(val, p))
-			return -EFAULT;
-
-	/* read state */
-	memset(&va,0,sizeof(va));
-	client->driver->command(client,VIDIOCGAUDIO,&va);
-
-	switch (cmd) {
-	case MIXER_READ(SOUND_MIXER_RECMASK):
-	case MIXER_READ(SOUND_MIXER_CAPS):
-	case MIXER_READ(SOUND_MIXER_RECSRC):
-	case MIXER_WRITE(SOUND_MIXER_RECSRC):
-		ret = 0;
-		break;
-
-	case MIXER_READ(SOUND_MIXER_STEREODEVS):
-		ret = SOUND_MASK_VOLUME;
-		break;
-	case MIXER_READ(SOUND_MIXER_DEVMASK):
-		ret = SOUND_MASK_VOLUME;
-		if (va.flags & VIDEO_AUDIO_BASS)
-			ret |= SOUND_MASK_BASS;
-		if (va.flags & VIDEO_AUDIO_TREBLE)
-			ret |= SOUND_MASK_TREBLE;
-		break;
-
-	case MIXER_WRITE(SOUND_MIXER_VOLUME):
-		left  = mix_to_v4l(val);
-		right = mix_to_v4l(val >> 8);
-		va.volume  = max(left,right);
-		va.balance = (32768*min(left,right)) / (va.volume ? va.volume : 1);
-		va.balance = (left<right) ? (65535-va.balance) : va.balance;
-		if (va.volume)
-			va.flags &= ~VIDEO_AUDIO_MUTE;
-		client->driver->command(client,VIDIOCSAUDIO,&va);
-		client->driver->command(client,VIDIOCGAUDIO,&va);
-		/* fall throuth */
-	case MIXER_READ(SOUND_MIXER_VOLUME):
-		left  = (min(65536 - va.balance,32768) *
-			 va.volume) / 32768;
-		right = (min(va.balance,(u16)32768) *
-			 va.volume) / 32768;
-		ret = v4l_to_mix2(left,right);
-		break;
-
-	case MIXER_WRITE(SOUND_MIXER_BASS):
-		va.bass = mix_to_v4l(val);
-		client->driver->command(client,VIDIOCSAUDIO,&va);
-		client->driver->command(client,VIDIOCGAUDIO,&va);
-		/* fall throuth  */
-	case MIXER_READ(SOUND_MIXER_BASS):
-		ret = v4l_to_mix(va.bass);
-		break;
-
-	case MIXER_WRITE(SOUND_MIXER_TREBLE):
-		va.treble = mix_to_v4l(val);
-		client->driver->command(client,VIDIOCSAUDIO,&va);
-		client->driver->command(client,VIDIOCGAUDIO,&va);
-		/* fall throuth */
-	case MIXER_READ(SOUND_MIXER_TREBLE):
-		ret = v4l_to_mix(va.treble);
-		break;
-
-	default:
-		return -EINVAL;
-	}
-	if (put_user(ret, p))
-		return -EFAULT;
-	return 0;
-}
-
-static int tvmixer_open(struct inode *inode, struct file *file)
-{
-	int i, minor = iminor(inode);
-	struct TVMIXER *mix = NULL;
-	struct i2c_client *client = NULL;
-
-	for (i = 0; i < DEV_MAX; i++) {
-		if (devices[i].minor == minor) {
-			mix = devices+i;
-			client = mix->dev;
-			break;
-		}
-	}
-
-	if (NULL == client)
-		return -ENODEV;
-
-	/* lock bttv in memory while the mixer is in use  */
-	file->private_data = mix;
-	if (client->adapter->owner)
-		try_module_get(client->adapter->owner);
-	return 0;
-}
-
-static int tvmixer_release(struct inode *inode, struct file *file)
-{
-	struct TVMIXER *mix = file->private_data;
-	struct i2c_client *client;
-
-	client = mix->dev;
-	if (NULL == client) {
-		return -ENODEV;
-	}
-
-	module_put(client->adapter->owner);
-	return 0;
-}
-
-static struct i2c_driver driver = {
-	.driver = {
-		.name    = "tvmixer",
-	},
-	.id              = I2C_DRIVERID_TVMIXER,
-	.detach_adapter  = tvmixer_adapters,
-	.attach_adapter  = tvmixer_adapters,
-	.detach_client   = tvmixer_clients,
-};
-
-static const struct file_operations tvmixer_fops = {
-	.owner		= THIS_MODULE,
-	.llseek         = no_llseek,
-	.ioctl          = tvmixer_ioctl,
-	.open           = tvmixer_open,
-	.release        = tvmixer_release,
-};
-
-/* ----------------------------------------------------------------------- */
-
-static int tvmixer_adapters(struct i2c_adapter *adap)
-{
-	struct i2c_client *client;
-
-	list_for_each_entry(client, &adap->clients, list)
-		tvmixer_clients(client);
-	return 0;
-}
-
-static int tvmixer_clients(struct i2c_client *client)
-{
-	struct video_audio va;
-	int i,minor;
-
-	if (!(client->adapter->class & I2C_CLASS_TV_ANALOG))
-		return -1;
-
-	/* unregister ?? */
-	for (i = 0; i < DEV_MAX; i++) {
-		if (devices[i].dev == client) {
-			/* unregister */
-			unregister_sound_mixer(devices[i].minor);
-			devices[i].dev = NULL;
-			devices[i].minor = -1;
-			printk("tvmixer: %s unregistered (#1)\n",
-			       client->name);
-			return 0;
-		}
-	}
-
-	/* look for a free slot */
-	for (i = 0; i < DEV_MAX; i++)
-		if (NULL == devices[i].dev)
-			break;
-	if (i == DEV_MAX) {
-		printk(KERN_WARNING "tvmixer: DEV_MAX too small\n");
-		return -1;
-	}
-
-	/* audio chip with mixer ??? */
-	if (NULL == client->driver->command)
-		return -1;
-	memset(&va,0,sizeof(va));
-	if (0 != client->driver->command(client,VIDIOCGAUDIO,&va))
-		return -1;
-	if (0 == (va.flags & VIDEO_AUDIO_VOLUME))
-		return -1;
-
-	/* everything is fine, register */
-	if ((minor = register_sound_mixer(&tvmixer_fops,devnr)) < 0) {
-		printk(KERN_ERR "tvmixer: cannot allocate mixer device\n");
-		return -1;
-	}
-
-	devices[i].minor = minor;
-	devices[i].count = 0;
-	devices[i].dev   = client;
-	printk("tvmixer: %s (%s) registered with minor %d\n",
-	       client->name,client->adapter->name,minor);
-
-	return 0;
-}
-
-/* ----------------------------------------------------------------------- */
-
-static int __init tvmixer_init_module(void)
-{
-	int i;
-
-	for (i = 0; i < DEV_MAX; i++)
-		devices[i].minor = -1;
-
-	return i2c_add_driver(&driver);
-}
-
-static void __exit tvmixer_cleanup_module(void)
-{
-	int i;
-
-	i2c_del_driver(&driver);
-	for (i = 0; i < DEV_MAX; i++) {
-		if (devices[i].minor != -1) {
-			unregister_sound_mixer(devices[i].minor);
-			printk("tvmixer: %s unregistered (#2)\n",
-			       devices[i].dev->name);
-		}
-	}
-}
-
-module_init(tvmixer_init_module);
-module_exit(tvmixer_cleanup_module);
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/include/asm-powerpc/dma.h b/include/asm-powerpc/dma.h
index 7a4374b..a7e06e2 100644
--- a/include/asm-powerpc/dma.h
+++ b/include/asm-powerpc/dma.h
@@ -93,16 +93,6 @@
  *
  */
 
-/* see prep_setup_arch() for detailed informations */
-#if defined(CONFIG_SOUND_CS4232) && defined(CONFIG_PPC_PREP)
-extern long ppc_cs4232_dma, ppc_cs4232_dma2;
-#define SND_DMA1 ppc_cs4232_dma
-#define SND_DMA2 ppc_cs4232_dma2
-#else
-#define SND_DMA1 -1
-#define SND_DMA2 -1
-#endif
-
 /* 8237 DMA controllers */
 #define IO_DMA1_BASE	0x00	/* 8 bit slave DMA, channels 0..3 */
 #define IO_DMA2_BASE	0xC0	/* 16 bit master DMA, ch 4(=slave input)..7 */
@@ -269,24 +259,15 @@
 		dma_outb(pagenr >> 8, DMA_HI_PAGE_3);
 		break;
 	case 5:
-		if (SND_DMA1 == 5 || SND_DMA2 == 5)
-			dma_outb(pagenr, DMA_LO_PAGE_5);
-		else
-			dma_outb(pagenr & 0xfe, DMA_LO_PAGE_5);
+		dma_outb(pagenr & 0xfe, DMA_LO_PAGE_5);
 		dma_outb(pagenr >> 8, DMA_HI_PAGE_5);
 		break;
 	case 6:
-		if (SND_DMA1 == 6 || SND_DMA2 == 6)
-			dma_outb(pagenr, DMA_LO_PAGE_6);
-		else
-			dma_outb(pagenr & 0xfe, DMA_LO_PAGE_6);
+		dma_outb(pagenr & 0xfe, DMA_LO_PAGE_6);
 		dma_outb(pagenr >> 8, DMA_HI_PAGE_6);
 		break;
 	case 7:
-		if (SND_DMA1 == 7 || SND_DMA2 == 7)
-			dma_outb(pagenr, DMA_LO_PAGE_7);
-		else
-			dma_outb(pagenr & 0xfe, DMA_LO_PAGE_7);
+		dma_outb(pagenr & 0xfe, DMA_LO_PAGE_7);
 		dma_outb(pagenr >> 8, DMA_HI_PAGE_7);
 		break;
 	}
@@ -302,12 +283,6 @@
 			 ((dmanr & 3) << 1) + IO_DMA1_BASE);
 		dma_outb((phys >> 8) & 0xff,
 			 ((dmanr & 3) << 1) + IO_DMA1_BASE);
-	} else if (dmanr == SND_DMA1 || dmanr == SND_DMA2) {
-		dma_outb(phys & 0xff,
-			 ((dmanr & 3) << 2) + IO_DMA2_BASE);
-		dma_outb((phys >> 8) & 0xff,
-			 ((dmanr & 3) << 2) + IO_DMA2_BASE);
-		dma_outb((dmanr & 3), DMA2_EXT_REG);
 	} else {
 		dma_outb((phys >> 1) & 0xff,
 			 ((dmanr & 3) << 2) + IO_DMA2_BASE);
@@ -334,11 +309,6 @@
 			 ((dmanr & 3) << 1) + 1 + IO_DMA1_BASE);
 		dma_outb((count >> 8) & 0xff,
 			 ((dmanr & 3) << 1) + 1 + IO_DMA1_BASE);
-	} else if (dmanr == SND_DMA1 || dmanr == SND_DMA2) {
-		dma_outb(count & 0xff,
-			 ((dmanr & 3) << 2) + 2 + IO_DMA2_BASE);
-		dma_outb((count >> 8) & 0xff,
-			 ((dmanr & 3) << 2) + 2 + IO_DMA2_BASE);
 	} else {
 		dma_outb((count >> 1) & 0xff,
 			 ((dmanr & 3) << 2) + 2 + IO_DMA2_BASE);
@@ -368,8 +338,7 @@
 	count = 1 + dma_inb(io_port);
 	count += dma_inb(io_port) << 8;
 
-	return (dmanr <= 3 || dmanr == SND_DMA1 || dmanr == SND_DMA2)
-	    ? count : (count << 1);
+	return (dmanr <= 3) ? count : (count << 1);
 }
 
 /* These are in kernel/dma.c: */
diff --git a/include/linux/ac97_codec.h b/include/linux/ac97_codec.h
index 22eb936..0260c3e 100644
--- a/include/linux/ac97_codec.h
+++ b/include/linux/ac97_codec.h
@@ -326,11 +326,7 @@
 #define AC97_DEFAULT_POWER_OFF 4 /* Needs warm reset to power up */
 };
 
-extern int ac97_read_proc (char *page_out, char **start, off_t off,
-			   int count, int *eof, void *data);
 extern int ac97_probe_codec(struct ac97_codec *);
-extern unsigned int ac97_set_adc_rate(struct ac97_codec *codec, unsigned int rate);
-extern unsigned int ac97_set_dac_rate(struct ac97_codec *codec, unsigned int rate);
 
 extern struct ac97_codec *ac97_alloc_codec(void);
 extern void ac97_release_codec(struct ac97_codec *codec);
@@ -363,7 +359,4 @@
 	int type;               /* quirk type above */
 };
 
-struct pci_dev;
-extern int ac97_tune_hardware(struct pci_dev *pdev, struct ac97_quirk *quirk, int override);
-
 #endif /* _AC97_CODEC_H_ */
diff --git a/sound/oss/Makefile b/sound/oss/Makefile
index f883c4b..1f86299 100644
--- a/sound/oss/Makefile
+++ b/sound/oss/Makefile
@@ -6,7 +6,6 @@
 # Each configuration option enables a list of files.
 
 obj-$(CONFIG_SOUND_OSS)		+= sound.o
-obj-$(CONFIG_SOUND_CS4232)	+= cs4232.o ad1848.o 
 
 # Please leave it as is, cause the link order is significant !
 
@@ -16,7 +15,6 @@
 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_CS4232)	+= cs4232.o uart401.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
@@ -27,19 +25,12 @@
 obj-$(CONFIG_SOUND_VMIDI)	+= v_midi.o
 obj-$(CONFIG_SOUND_VIDC)	+= vidc_mod.o
 obj-$(CONFIG_SOUND_WAVEARTIST)	+= waveartist.o
-
-obj-$(CONFIG_SOUND_VIA82CXXX)	+= via82cxxx_audio.o ac97_codec.o
-ifeq ($(CONFIG_MIDI_VIA82CXXX),y)
-  obj-$(CONFIG_SOUND_VIA82CXXX) += sound.o uart401.o
-endif
 obj-$(CONFIG_SOUND_MSNDCLAS)	+= msnd.o msnd_classic.o
 obj-$(CONFIG_SOUND_MSNDPIN)	+= msnd.o msnd_pinnacle.o
 obj-$(CONFIG_SOUND_VWSND)	+= vwsnd.o
-obj-$(CONFIG_SOUND_ICH)		+= i810_audio.o ac97_codec.o
 obj-$(CONFIG_SOUND_AU1550_AC97)	+= au1550_ac97.o ac97_codec.o
 obj-$(CONFIG_SOUND_TRIDENT)	+= trident.o ac97_codec.o
 obj-$(CONFIG_SOUND_BCM_CS4297A)	+= swarm_cs4297a.o
-obj-$(CONFIG_SOUND_BT878)	+= btaudio.o
 
 obj-$(CONFIG_SOUND_WM97XX)	+= ac97_plugin_wm97xx.o
 
diff --git a/sound/oss/ac97_codec.c b/sound/oss/ac97_codec.c
index fef56ca..87a6726 100644
--- a/sound/oss/ac97_codec.c
+++ b/sound/oss/ac97_codec.c
@@ -189,42 +189,6 @@
 	{0x57454301, "Winbond 83971D",		&null_ops},
 };
 
-static const char *ac97_stereo_enhancements[] =
-{
-	/*   0 */ "No 3D Stereo Enhancement",
-	/*   1 */ "Analog Devices Phat Stereo",
-	/*   2 */ "Creative Stereo Enhancement",
-	/*   3 */ "National Semi 3D Stereo Enhancement",
-	/*   4 */ "YAMAHA Ymersion",
-	/*   5 */ "BBE 3D Stereo Enhancement",
-	/*   6 */ "Crystal Semi 3D Stereo Enhancement",
-	/*   7 */ "Qsound QXpander",
-	/*   8 */ "Spatializer 3D Stereo Enhancement",
-	/*   9 */ "SRS 3D Stereo Enhancement",
-	/*  10 */ "Platform Tech 3D Stereo Enhancement",
-	/*  11 */ "AKM 3D Audio",
-	/*  12 */ "Aureal Stereo Enhancement",
-	/*  13 */ "Aztech 3D Enhancement",
-	/*  14 */ "Binaura 3D Audio Enhancement",
-	/*  15 */ "ESS Technology Stereo Enhancement",
-	/*  16 */ "Harman International VMAx",
-	/*  17 */ "Nvidea 3D Stereo Enhancement",
-	/*  18 */ "Philips Incredible Sound",
-	/*  19 */ "Texas Instruments 3D Stereo Enhancement",
-	/*  20 */ "VLSI Technology 3D Stereo Enhancement",
-	/*  21 */ "TriTech 3D Stereo Enhancement",
-	/*  22 */ "Realtek 3D Stereo Enhancement",
-	/*  23 */ "Samsung 3D Stereo Enhancement",
-	/*  24 */ "Wolfson Microelectronics 3D Enhancement",
-	/*  25 */ "Delta Integration 3D Enhancement",
-	/*  26 */ "SigmaTel 3D Enhancement",
-	/*  27 */ "Winbond 3D Stereo Enhancement",
-	/*  28 */ "Rockwell 3D Stereo Enhancement",
-	/*  29 */ "Reserved 29",
-	/*  30 */ "Reserved 30",
-	/*  31 */ "Reserved 31"
-};
-
 /* this table has default mixer values for all OSS mixers. */
 static struct mixer_defaults {
 	int mixer;
@@ -614,83 +578,6 @@
 	return -EINVAL;
 }
 
-/* entry point for /proc/driver/controller_vendor/ac97/%d */
-int ac97_read_proc (char *page, char **start, off_t off,
-		    int count, int *eof, void *data)
-{
-	int len = 0, cap, extid, val, id1, id2;
-	struct ac97_codec *codec;
-	int is_ac97_20 = 0;
-
-	if ((codec = data) == NULL)
-		return -ENODEV;
-
-	id1 = codec->codec_read(codec, AC97_VENDOR_ID1);
-	id2 = codec->codec_read(codec, AC97_VENDOR_ID2);
-	len += sprintf (page+len, "Vendor name      : %s\n", codec->name);
-	len += sprintf (page+len, "Vendor id        : %04X %04X\n", id1, id2);
-
-	extid = codec->codec_read(codec, AC97_EXTENDED_ID);
-	extid &= ~((1<<2)|(1<<4)|(1<<5)|(1<<10)|(1<<11)|(1<<12)|(1<<13));
-	len += sprintf (page+len, "AC97 Version     : %s\n",
-			extid ? "2.0 or later" : "1.0");
-	if (extid) is_ac97_20 = 1;
-
-	cap = codec->codec_read(codec, AC97_RESET);
-	len += sprintf (page+len, "Capabilities     :%s%s%s%s%s%s\n",
-			cap & 0x0001 ? " -dedicated MIC PCM IN channel-" : "",
-			cap & 0x0002 ? " -reserved1-" : "",
-			cap & 0x0004 ? " -bass & treble-" : "",
-			cap & 0x0008 ? " -simulated stereo-" : "",
-			cap & 0x0010 ? " -headphone out-" : "",
-			cap & 0x0020 ? " -loudness-" : "");
-	val = cap & 0x00c0;
-	len += sprintf (page+len, "DAC resolutions  :%s%s%s\n",
-			" -16-bit-",
-			val & 0x0040 ? " -18-bit-" : "",
-			val & 0x0080 ? " -20-bit-" : "");
-	val = cap & 0x0300;
-	len += sprintf (page+len, "ADC resolutions  :%s%s%s\n",
-			" -16-bit-",
-			val & 0x0100 ? " -18-bit-" : "",
-			val & 0x0200 ? " -20-bit-" : "");
-	len += sprintf (page+len, "3D enhancement   : %s\n",
-			ac97_stereo_enhancements[(cap >> 10) & 0x1f]);
-
-	val = codec->codec_read(codec, AC97_GENERAL_PURPOSE);
-	len += sprintf (page+len, "POP path         : %s 3D\n"
-			"Sim. stereo      : %s\n"
-			"3D enhancement   : %s\n"
-			"Loudness         : %s\n"
-			"Mono output      : %s\n"
-			"MIC select       : %s\n"
-			"ADC/DAC loopback : %s\n",
-			val & 0x8000 ? "post" : "pre",
-			val & 0x4000 ? "on" : "off",
-			val & 0x2000 ? "on" : "off",
-			val & 0x1000 ? "on" : "off",
-			val & 0x0200 ? "MIC" : "MIX",
-			val & 0x0100 ? "MIC2" : "MIC1",
-			val & 0x0080 ? "on" : "off");
-
-	extid = codec->codec_read(codec, AC97_EXTENDED_ID);
-	cap = extid;
-	len += sprintf (page+len, "Ext Capabilities :%s%s%s%s%s%s%s\n",
-			cap & 0x0001 ? " -var rate PCM audio-" : "",
-			cap & 0x0002 ? " -2x PCM audio out-" : "",
-			cap & 0x0008 ? " -var rate MIC in-" : "",
-			cap & 0x0040 ? " -PCM center DAC-" : "",
-			cap & 0x0080 ? " -PCM surround DAC-" : "",
-			cap & 0x0100 ? " -PCM LFE DAC-" : "",
-			cap & 0x0200 ? " -slot/DAC mappings-" : "");
-	if (is_ac97_20) {
-		len += sprintf (page+len, "Front DAC rate   : %d\n",
-				codec->codec_read(codec, AC97_PCM_FRONT_DAC_RATE));
-	}
-
-	return len;
-}
-
 /**
  *	codec_id	-  Turn id1/id2 into a PnP string
  *	@id1: Vendor ID1
@@ -1313,176 +1200,5 @@
 #endif
 	
 
-EXPORT_SYMBOL(ac97_read_proc);
 EXPORT_SYMBOL(ac97_probe_codec);
 
-/*
- *	AC97 library support routines
- */	
- 
-/**
- *	ac97_set_dac_rate	-	set codec rate adaption
- *	@codec: ac97 code
- *	@rate: rate in hertz
- *
- *	Set the DAC rate. Assumes the codec supports VRA. The caller is
- *	expected to have checked this little detail.
- */
- 
-unsigned int ac97_set_dac_rate(struct ac97_codec *codec, unsigned int rate)
-{
-	unsigned int new_rate = rate;
-	u32 dacp;
-	u32 mast_vol, phone_vol, mono_vol, pcm_vol;
-	u32 mute_vol = 0x8000;	/* The mute volume? */
-
-	if(rate != codec->codec_read(codec, AC97_PCM_FRONT_DAC_RATE))
-	{
-		/* Mute several registers */
-		mast_vol = codec->codec_read(codec, AC97_MASTER_VOL_STEREO);
-		mono_vol = codec->codec_read(codec, AC97_MASTER_VOL_MONO);
-		phone_vol = codec->codec_read(codec, AC97_HEADPHONE_VOL);
-		pcm_vol = codec->codec_read(codec, AC97_PCMOUT_VOL);
-		codec->codec_write(codec, AC97_MASTER_VOL_STEREO, mute_vol);
-		codec->codec_write(codec, AC97_MASTER_VOL_MONO, mute_vol);
-		codec->codec_write(codec, AC97_HEADPHONE_VOL, mute_vol);
-		codec->codec_write(codec, AC97_PCMOUT_VOL, mute_vol);
-		
-		/* Power down the DAC */
-		dacp=codec->codec_read(codec, AC97_POWER_CONTROL);
-		codec->codec_write(codec, AC97_POWER_CONTROL, dacp|0x0200);
-		/* Load the rate and read the effective rate */
-		codec->codec_write(codec, AC97_PCM_FRONT_DAC_RATE, rate);
-		new_rate=codec->codec_read(codec, AC97_PCM_FRONT_DAC_RATE);
-		/* Power it back up */
-		codec->codec_write(codec, AC97_POWER_CONTROL, dacp);
-
-		/* Restore volumes */
-		codec->codec_write(codec, AC97_MASTER_VOL_STEREO, mast_vol);
-		codec->codec_write(codec, AC97_MASTER_VOL_MONO, mono_vol);
-		codec->codec_write(codec, AC97_HEADPHONE_VOL, phone_vol);
-		codec->codec_write(codec, AC97_PCMOUT_VOL, pcm_vol);
-	}
-	return new_rate;
-}
-
-EXPORT_SYMBOL(ac97_set_dac_rate);
-
-/**
- *	ac97_set_adc_rate	-	set codec rate adaption
- *	@codec: ac97 code
- *	@rate: rate in hertz
- *
- *	Set the ADC rate. Assumes the codec supports VRA. The caller is
- *	expected to have checked this little detail.
- */
-
-unsigned int ac97_set_adc_rate(struct ac97_codec *codec, unsigned int rate)
-{
-	unsigned int new_rate = rate;
-	u32 dacp;
-
-	if(rate != codec->codec_read(codec, AC97_PCM_LR_ADC_RATE))
-	{
-		/* Power down the ADC */
-		dacp=codec->codec_read(codec, AC97_POWER_CONTROL);
-		codec->codec_write(codec, AC97_POWER_CONTROL, dacp|0x0100);
-		/* Load the rate and read the effective rate */
-		codec->codec_write(codec, AC97_PCM_LR_ADC_RATE, rate);
-		new_rate=codec->codec_read(codec, AC97_PCM_LR_ADC_RATE);
-		/* Power it back up */
-		codec->codec_write(codec, AC97_POWER_CONTROL, dacp);
-	}
-	return new_rate;
-}
-
-EXPORT_SYMBOL(ac97_set_adc_rate);
-
-static int swap_headphone(int remove_master)
-{
-	struct list_head *l;
-	struct ac97_codec *c;
-	
-	if (remove_master) {
-		mutex_lock(&codec_mutex);
-		list_for_each(l, &codecs)
-		{
-			c = list_entry(l, struct ac97_codec, list);
-			if (supported_mixer(c, SOUND_MIXER_PHONEOUT))
-				c->supported_mixers &= ~SOUND_MASK_PHONEOUT;
-		}
-		mutex_unlock(&codec_mutex);
-	} else
-		ac97_hw[SOUND_MIXER_PHONEOUT].offset = AC97_MASTER_VOL_STEREO;
-
-	/* Scale values already match */
-	ac97_hw[SOUND_MIXER_VOLUME].offset = AC97_MASTER_VOL_MONO;
-	return 0;
-}
-
-static int apply_quirk(int quirk)
-{
-	switch (quirk) {
-	case AC97_TUNE_NONE:
-		return 0;
-	case AC97_TUNE_HP_ONLY:
-		return swap_headphone(1);
-	case AC97_TUNE_SWAP_HP:
-		return swap_headphone(0);
-	case AC97_TUNE_SWAP_SURROUND:
-		return -ENOSYS; /* not yet implemented */
-	case AC97_TUNE_AD_SHARING:
-		return -ENOSYS; /* not yet implemented */
-	case AC97_TUNE_ALC_JACK:
-		return -ENOSYS; /* not yet implemented */
-	}
-	return -EINVAL;
-}
-
-/**
- *	ac97_tune_hardware - tune up the hardware
- *	@pdev: pci_dev pointer
- *	@quirk: quirk list
- *	@override: explicit quirk value (overrides if not AC97_TUNE_DEFAULT)
- *
- *	Do some workaround for each pci device, such as renaming of the
- *	headphone (true line-out) control as "Master".
- *	The quirk-list must be terminated with a zero-filled entry.
- *
- *	Returns zero if successful, or a negative error code on failure.
- */
-
-int ac97_tune_hardware(struct pci_dev *pdev, struct ac97_quirk *quirk, int override)
-{
-	int result;
-
-	if (!quirk)
-		return -EINVAL;
-
-	if (override != AC97_TUNE_DEFAULT) {
-		result = apply_quirk(override);
-		if (result < 0)
-			printk(KERN_ERR "applying quirk type %d failed (%d)\n", override, result);
-		return result;
-	}
-
-	for (; quirk->vendor; quirk++) {
-		if (quirk->vendor != pdev->subsystem_vendor)
-			continue;
-		if ((! quirk->mask && quirk->device == pdev->subsystem_device) ||
-		    quirk->device == (quirk->mask & pdev->subsystem_device)) {
-#ifdef DEBUG
-			printk("ac97 quirk for %s (%04x:%04x)\n", quirk->name, ac97->subsystem_vendor, pdev->subsystem_device);
-#endif
-			result = apply_quirk(quirk->type);
-			if (result < 0)
-				printk(KERN_ERR "applying quirk type %d for %s failed (%d)\n", quirk->type, quirk->name, result);
-			return result;
-		}
-	}
-	return 0;
-}
-
-EXPORT_SYMBOL_GPL(ac97_tune_hardware);
-
-MODULE_LICENSE("GPL");
diff --git a/sound/oss/btaudio.c b/sound/oss/btaudio.c
deleted file mode 100644
index 4d5cf05..0000000
--- a/sound/oss/btaudio.c
+++ /dev/null
@@ -1,1139 +0,0 @@
-/*
-    btaudio - bt878 audio dma driver for linux 2.4.x
-
-    (c) 2000-2002 Gerd Knorr <kraxel@bytesex.org>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/pci.h>
-#include <linux/sched.h>
-#include <linux/signal.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/poll.h>
-#include <linux/sound.h>
-#include <linux/soundcard.h>
-#include <linux/slab.h>
-#include <linux/kdev_t.h>
-#include <linux/mutex.h>
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
-
-
-/* mmio access */
-#define btwrite(dat,adr)    writel((dat), (bta->mmio+(adr)))
-#define btread(adr)         readl(bta->mmio+(adr))
-
-#define btand(dat,adr)      btwrite((dat) & btread(adr), adr)
-#define btor(dat,adr)       btwrite((dat) | btread(adr), adr)
-#define btaor(dat,mask,adr) btwrite((dat) | ((mask) & btread(adr)), adr)
-
-/* registers (shifted because bta->mmio is long) */
-#define REG_INT_STAT      (0x100 >> 2)
-#define REG_INT_MASK      (0x104 >> 2)
-#define REG_GPIO_DMA_CTL  (0x10c >> 2)
-#define REG_PACKET_LEN    (0x110 >> 2)
-#define REG_RISC_STRT_ADD (0x114 >> 2)
-#define REG_RISC_COUNT    (0x120 >> 2)
-
-/* IRQ bits - REG_INT_(STAT|MASK) */
-#define IRQ_SCERR         (1 << 19)
-#define IRQ_OCERR         (1 << 18)
-#define IRQ_PABORT        (1 << 17)
-#define IRQ_RIPERR        (1 << 16)
-#define IRQ_PPERR         (1 << 15)
-#define IRQ_FDSR          (1 << 14)
-#define IRQ_FTRGT         (1 << 13)
-#define IRQ_FBUS          (1 << 12)
-#define IRQ_RISCI         (1 << 11)
-#define IRQ_OFLOW         (1 <<  3)
-
-#define IRQ_BTAUDIO       (IRQ_SCERR | IRQ_OCERR | IRQ_PABORT | IRQ_RIPERR |\
-			   IRQ_PPERR | IRQ_FDSR  | IRQ_FTRGT  | IRQ_FBUS   |\
-			   IRQ_RISCI)
-
-/* REG_GPIO_DMA_CTL bits */
-#define DMA_CTL_A_PWRDN   (1 << 26)
-#define DMA_CTL_DA_SBR    (1 << 14)
-#define DMA_CTL_DA_ES2    (1 << 13)
-#define DMA_CTL_ACAP_EN   (1 <<  4)
-#define DMA_CTL_RISC_EN   (1 <<  1)
-#define DMA_CTL_FIFO_EN   (1 <<  0)
-
-/* RISC instructions */
-#define RISC_WRITE        (0x01 << 28)
-#define RISC_JUMP         (0x07 << 28)
-#define RISC_SYNC         (0x08 << 28)
-
-/* RISC bits */
-#define RISC_WR_SOL       (1 << 27)
-#define RISC_WR_EOL       (1 << 26)
-#define RISC_IRQ          (1 << 24)
-#define RISC_SYNC_RESYNC  (1 << 15)
-#define RISC_SYNC_FM1     0x06
-#define RISC_SYNC_VRO     0x0c
-
-#define HWBASE_AD (448000)
-
-/* -------------------------------------------------------------- */
-
-struct btaudio {
-	/* linked list */
-	struct btaudio *next;
-
-	/* device info */
-	int            dsp_digital;
-	int            dsp_analog;
-	int            mixer_dev;
-	struct pci_dev *pci;
-	unsigned int   irq;
-	unsigned long  mem;
-	unsigned long  __iomem *mmio;
-
-	/* locking */
-	int            users;
-	struct mutex lock;
-
-	/* risc instructions */
-	unsigned int   risc_size;
-	unsigned long  *risc_cpu;
-	dma_addr_t     risc_dma;
-
-	/* audio data */
-	unsigned int   buf_size;
-	unsigned char  *buf_cpu;
-	dma_addr_t     buf_dma;
-
-	/* buffer setup */
-	int line_bytes;
-	int line_count;
-	int block_bytes;
-	int block_count;
-
-	/* read fifo management */
-	int recording;
-	int dma_block;
-	int read_offset;
-	int read_count;
-	wait_queue_head_t readq;
-
-	/* settings */
-	int gain[3];
-	int source;
-	int bits;
-	int decimation;
-	int mixcount;
-	int sampleshift;
-	int channels;
-	int analog;
-	int rate;
-};
-
-struct cardinfo {
-	char *name;
-	int rate;
-};
-
-static struct btaudio *btaudios;
-static unsigned int debug;
-static unsigned int irq_debug;
-
-/* -------------------------------------------------------------- */
-
-#define BUF_DEFAULT 128*1024
-#define BUF_MIN         8192
-
-static int alloc_buffer(struct btaudio *bta)
-{
-	if (NULL == bta->buf_cpu) {
-		for (bta->buf_size = BUF_DEFAULT; bta->buf_size >= BUF_MIN;
-		     bta->buf_size = bta->buf_size >> 1) {
-			bta->buf_cpu = pci_alloc_consistent
-				(bta->pci, bta->buf_size, &bta->buf_dma);
-			if (NULL != bta->buf_cpu)
-				break;
-		}
-		if (NULL == bta->buf_cpu)
-			return -ENOMEM;
-		memset(bta->buf_cpu,0,bta->buf_size);
-	}
-	if (NULL == bta->risc_cpu) {
-		bta->risc_size = PAGE_SIZE;
-		bta->risc_cpu = pci_alloc_consistent
-			(bta->pci, bta->risc_size, &bta->risc_dma);
-		if (NULL == bta->risc_cpu) {
-			pci_free_consistent(bta->pci, bta->buf_size, bta->buf_cpu, bta->buf_dma);
-			bta->buf_cpu = NULL;
-			return -ENOMEM;
-		}
-	}
-	return 0;
-}
-
-static void free_buffer(struct btaudio *bta)
-{
-	if (NULL != bta->buf_cpu) {
-		pci_free_consistent(bta->pci, bta->buf_size,
-				    bta->buf_cpu, bta->buf_dma);
-		bta->buf_cpu = NULL;
-	}
-	if (NULL != bta->risc_cpu) {
-		pci_free_consistent(bta->pci, bta->risc_size,
-				    bta->risc_cpu, bta->risc_dma);
-		bta->risc_cpu = NULL;
-	}
-}
-
-static int make_risc(struct btaudio *bta)
-{
-	int rp, bp, line, block;
-	unsigned long risc;
-
-	bta->block_bytes = bta->buf_size >> 4;
-	bta->block_count = 1 << 4;
-	bta->line_bytes  = bta->block_bytes;
-	bta->line_count  = bta->block_count;
-	while (bta->line_bytes > 4095) {
-		bta->line_bytes >>= 1;
-		bta->line_count <<= 1;
-	}
-	if (bta->line_count > 255)
-		return -EINVAL;
-	if (debug)
-		printk(KERN_DEBUG
-		       "btaudio: bufsize=%d - bs=%d bc=%d - ls=%d, lc=%d\n",
-		       bta->buf_size,bta->block_bytes,bta->block_count,
-		       bta->line_bytes,bta->line_count);
-        rp = 0; bp = 0;
-	block = 0;
-	bta->risc_cpu[rp++] = cpu_to_le32(RISC_SYNC|RISC_SYNC_FM1);
-	bta->risc_cpu[rp++] = cpu_to_le32(0);
-	for (line = 0; line < bta->line_count; line++) {
-		risc  = RISC_WRITE | RISC_WR_SOL | RISC_WR_EOL;
-		risc |= bta->line_bytes;
-		if (0 == (bp & (bta->block_bytes-1))) {
-			risc |= RISC_IRQ;
-			risc |= (block  & 0x0f) << 16;
-			risc |= (~block & 0x0f) << 20;
-			block++;
-		}
-		bta->risc_cpu[rp++] = cpu_to_le32(risc);
-		bta->risc_cpu[rp++] = cpu_to_le32(bta->buf_dma + bp);
-		bp += bta->line_bytes;
-	}
-	bta->risc_cpu[rp++] = cpu_to_le32(RISC_SYNC|RISC_SYNC_VRO);
-	bta->risc_cpu[rp++] = cpu_to_le32(0);
-	bta->risc_cpu[rp++] = cpu_to_le32(RISC_JUMP); 
-	bta->risc_cpu[rp++] = cpu_to_le32(bta->risc_dma);
-	return 0;
-}
-
-static int start_recording(struct btaudio *bta)
-{
-	int ret;
-
-	if (0 != (ret = alloc_buffer(bta)))
-		return ret;
-	if (0 != (ret = make_risc(bta)))
-		return ret;
-
-	btwrite(bta->risc_dma, REG_RISC_STRT_ADD);
-	btwrite((bta->line_count << 16) | bta->line_bytes,
-		REG_PACKET_LEN);
-	btwrite(IRQ_BTAUDIO, REG_INT_MASK);
-	if (bta->analog) {
-		btwrite(DMA_CTL_ACAP_EN |
-			DMA_CTL_RISC_EN |
-			DMA_CTL_FIFO_EN |
-			DMA_CTL_DA_ES2  |
-			((bta->bits == 8) ? DMA_CTL_DA_SBR : 0) |
-			(bta->gain[bta->source] << 28) |
-			(bta->source            << 24) |
-			(bta->decimation        <<  8),
-			REG_GPIO_DMA_CTL);
-	} else {
-		btwrite(DMA_CTL_ACAP_EN |
-			DMA_CTL_RISC_EN |
-			DMA_CTL_FIFO_EN |
-			DMA_CTL_DA_ES2  |
-			DMA_CTL_A_PWRDN |
-			(1 << 6)   |
-			((bta->bits == 8) ? DMA_CTL_DA_SBR : 0) |
-			(bta->gain[bta->source] << 28) |
-			(bta->source            << 24) |
-			(bta->decimation        <<  8),
-			REG_GPIO_DMA_CTL);
-	}
-	bta->dma_block = 0;
-	bta->read_offset = 0;
-	bta->read_count = 0;
-	bta->recording = 1;
-	if (debug)
-		printk(KERN_DEBUG "btaudio: recording started\n");
-	return 0;
-}
-
-static void stop_recording(struct btaudio *bta)
-{
-        btand(~15, REG_GPIO_DMA_CTL);
-	bta->recording = 0;
-	if (debug)
-		printk(KERN_DEBUG "btaudio: recording stopped\n");
-}
-
-
-/* -------------------------------------------------------------- */
-
-static int btaudio_mixer_open(struct inode *inode, struct file *file)
-{
-	int minor = iminor(inode);
-	struct btaudio *bta;
-
-	for (bta = btaudios; bta != NULL; bta = bta->next)
-		if (bta->mixer_dev == minor)
-			break;
-	if (NULL == bta)
-		return -ENODEV;
-
-	if (debug)
-		printk("btaudio: open mixer [%d]\n",minor);
-	file->private_data = bta;
-	return 0;
-}
-
-static int btaudio_mixer_release(struct inode *inode, struct file *file)
-{
-	return 0;
-}
-
-static int btaudio_mixer_ioctl(struct inode *inode, struct file *file,
-			       unsigned int cmd, unsigned long arg)
-{
-	struct btaudio *bta = file->private_data;
-	int ret,val=0,i=0;
-	void __user *argp = (void __user *)arg;
-
-	if (cmd == SOUND_MIXER_INFO) {
-		mixer_info info;
-		memset(&info,0,sizeof(info));
-                strlcpy(info.id,"bt878",sizeof(info.id));
-                strlcpy(info.name,"Brooktree Bt878 audio",sizeof(info.name));
-                info.modify_counter = bta->mixcount;
-                if (copy_to_user(argp, &info, sizeof(info)))
-                        return -EFAULT;
-		return 0;
-	}
-	if (cmd == SOUND_OLD_MIXER_INFO) {
-		_old_mixer_info info;
-		memset(&info,0,sizeof(info));
-                strlcpy(info.id, "bt878", sizeof(info.id));
-                strlcpy(info.name,"Brooktree Bt878 audio",sizeof(info.name));
-                if (copy_to_user(argp, &info, sizeof(info)))
-                        return -EFAULT;
-		return 0;
-	}
-	if (cmd == OSS_GETVERSION)
-		return put_user(SOUND_VERSION, (int __user *)argp);
-
-	/* read */
-	if (_SIOC_DIR(cmd) & _SIOC_WRITE)
-		if (get_user(val, (int __user *)argp))
-			return -EFAULT;
-
-	switch (cmd) {
-	case MIXER_READ(SOUND_MIXER_CAPS):
-		ret = SOUND_CAP_EXCL_INPUT;
-		break;
-	case MIXER_READ(SOUND_MIXER_STEREODEVS):
-		ret = 0;
-		break;
-	case MIXER_READ(SOUND_MIXER_RECMASK):
-	case MIXER_READ(SOUND_MIXER_DEVMASK):
-		ret = SOUND_MASK_LINE1|SOUND_MASK_LINE2|SOUND_MASK_LINE3;
-		break;
-
-	case MIXER_WRITE(SOUND_MIXER_RECSRC):
-		if (val & SOUND_MASK_LINE1 && bta->source != 0)
-			bta->source = 0;
-		else if (val & SOUND_MASK_LINE2 && bta->source != 1)
-			bta->source = 1;
-		else if (val & SOUND_MASK_LINE3 && bta->source != 2)
-			bta->source = 2;
-		btaor((bta->gain[bta->source] << 28) |
-		      (bta->source            << 24),
-		      0x0cffffff, REG_GPIO_DMA_CTL);
-	case MIXER_READ(SOUND_MIXER_RECSRC):
-		switch (bta->source) {
-		case 0:  ret = SOUND_MASK_LINE1; break;
-		case 1:  ret = SOUND_MASK_LINE2; break;
-		case 2:  ret = SOUND_MASK_LINE3; break;
-		default: ret = 0;
-		}
-		break;
-
-	case MIXER_WRITE(SOUND_MIXER_LINE1):
-	case MIXER_WRITE(SOUND_MIXER_LINE2):
-	case MIXER_WRITE(SOUND_MIXER_LINE3):
-		if (MIXER_WRITE(SOUND_MIXER_LINE1) == cmd)
-			i = 0;
-		if (MIXER_WRITE(SOUND_MIXER_LINE2) == cmd)
-			i = 1;
-		if (MIXER_WRITE(SOUND_MIXER_LINE3) == cmd)
-			i = 2;
-		bta->gain[i] = (val & 0xff) * 15 / 100;
-		if (bta->gain[i] > 15) bta->gain[i] = 15;
-		if (bta->gain[i] <  0) bta->gain[i] =  0;
-		if (i == bta->source)
-			btaor((bta->gain[bta->source]<<28),
-			      0x0fffffff, REG_GPIO_DMA_CTL);
-		ret  = bta->gain[i] * 100 / 15;
-		ret |= ret << 8;
-		break;
-
-	case MIXER_READ(SOUND_MIXER_LINE1):
-	case MIXER_READ(SOUND_MIXER_LINE2):
-	case MIXER_READ(SOUND_MIXER_LINE3):
-		if (MIXER_READ(SOUND_MIXER_LINE1) == cmd)
-			i = 0;
-		if (MIXER_READ(SOUND_MIXER_LINE2) == cmd)
-			i = 1;
-		if (MIXER_READ(SOUND_MIXER_LINE3) == cmd)
-			i = 2;
-		ret  = bta->gain[i] * 100 / 15;
-		ret |= ret << 8;
-		break;
-
-	default:
-		return -EINVAL;
-	}
-	if (put_user(ret, (int __user *)argp))
-		return -EFAULT;
-	return 0;
-}
-
-static const struct file_operations btaudio_mixer_fops = {
-	.owner		= THIS_MODULE,
-	.llseek		= no_llseek,
-	.open		= btaudio_mixer_open,
-	.release	= btaudio_mixer_release,
-	.ioctl		= btaudio_mixer_ioctl,
-};
-
-/* -------------------------------------------------------------- */
-
-static int btaudio_dsp_open(struct inode *inode, struct file *file,
-			    struct btaudio *bta, int analog)
-{
-	mutex_lock(&bta->lock);
-	if (bta->users)
-		goto busy;
-	bta->users++;
-	file->private_data = bta;
-
-	bta->analog = analog;
-	bta->dma_block = 0;
-	bta->read_offset = 0;
-	bta->read_count = 0;
-	bta->sampleshift = 0;
-
-	mutex_unlock(&bta->lock);
-	return 0;
-
- busy:
-	mutex_unlock(&bta->lock);
-	return -EBUSY;
-}
-
-static int btaudio_dsp_open_digital(struct inode *inode, struct file *file)
-{
-	int minor = iminor(inode);
-	struct btaudio *bta;
-
-	for (bta = btaudios; bta != NULL; bta = bta->next)
-		if (bta->dsp_digital == minor)
-			break;
-	if (NULL == bta)
-		return -ENODEV;
-	
-	if (debug)
-		printk("btaudio: open digital dsp [%d]\n",minor);
-	return btaudio_dsp_open(inode,file,bta,0);
-}
-
-static int btaudio_dsp_open_analog(struct inode *inode, struct file *file)
-{
-	int minor = iminor(inode);
-	struct btaudio *bta;
-
-	for (bta = btaudios; bta != NULL; bta = bta->next)
-		if (bta->dsp_analog == minor)
-			break;
-	if (NULL == bta)
-		return -ENODEV;
-
-	if (debug)
-		printk("btaudio: open analog dsp [%d]\n",minor);
-	return btaudio_dsp_open(inode,file,bta,1);
-}
-
-static int btaudio_dsp_release(struct inode *inode, struct file *file)
-{
-	struct btaudio *bta = file->private_data;
-
-	mutex_lock(&bta->lock);
-	if (bta->recording)
-		stop_recording(bta);
-	bta->users--;
-	mutex_unlock(&bta->lock);
-	return 0;
-}
-
-static ssize_t btaudio_dsp_read(struct file *file, char __user *buffer,
-				size_t swcount, loff_t *ppos)
-{
-	struct btaudio *bta = file->private_data;
-	int hwcount = swcount << bta->sampleshift;
-	int nsrc, ndst, err, ret = 0;
-	DECLARE_WAITQUEUE(wait, current);
-
-	add_wait_queue(&bta->readq, &wait);
-	mutex_lock(&bta->lock);
-	while (swcount > 0) {
-		if (0 == bta->read_count) {
-			if (!bta->recording) {
-				if (0 != (err = start_recording(bta))) {
-					if (0 == ret)
-						ret = err;
-					break;
-				}
-			}
-			if (file->f_flags & O_NONBLOCK) {
-				if (0 == ret)
-					ret = -EAGAIN;
-				break;
-			}
-			mutex_unlock(&bta->lock);
-			current->state = TASK_INTERRUPTIBLE;
-			schedule();
-			mutex_lock(&bta->lock);
-			if(signal_pending(current)) {
-				if (0 == ret)
-					ret = -EINTR;
-				break;
-			}
-		}
-		nsrc = (bta->read_count < hwcount) ? bta->read_count : hwcount;
-		if (nsrc > bta->buf_size - bta->read_offset)
-			nsrc = bta->buf_size - bta->read_offset;
-		ndst = nsrc >> bta->sampleshift;
-		
-		if ((bta->analog  && 0 == bta->sampleshift) ||
-		    (!bta->analog && 2 == bta->channels)) {
-			/* just copy */
-			if (copy_to_user(buffer + ret, bta->buf_cpu + bta->read_offset, nsrc)) {
-				if (0 == ret)
-					ret = -EFAULT;
-				break;
-			}
-
-		} else if (!bta->analog) {
-			/* stereo => mono (digital audio) */
-			__s16 *src = (__s16*)(bta->buf_cpu + bta->read_offset);
-			__s16 __user *dst = (__s16 __user *)(buffer + ret);
-			__s16 avg;
-			int n = ndst>>1;
-			if (!access_ok(VERIFY_WRITE, dst, ndst)) {
-				if (0 == ret)
-					ret = -EFAULT;
-				break;
-			}
-			for (; n; n--, dst++) {
-				avg  = (__s16)le16_to_cpu(*src) / 2; src++;
-				avg += (__s16)le16_to_cpu(*src) / 2; src++;
-				__put_user(cpu_to_le16(avg),dst);
-			}
-
-		} else if (8 == bta->bits) {
-			/* copy + byte downsampling (audio A/D) */
-			__u8 *src = bta->buf_cpu + bta->read_offset;
-			__u8 __user *dst = buffer + ret;
-			int n = ndst;
-			if (!access_ok(VERIFY_WRITE, dst, ndst)) {
-				if (0 == ret)
-					ret = -EFAULT;
-				break;
-			}
-			for (; n; n--, src += (1 << bta->sampleshift), dst++)
-				__put_user(*src, dst);
-
-		} else {
-			/* copy + word downsampling (audio A/D) */
-			__u16 *src = (__u16*)(bta->buf_cpu + bta->read_offset);
-			__u16 __user *dst = (__u16 __user *)(buffer + ret);
-			int n = ndst>>1;
-			if (!access_ok(VERIFY_WRITE,dst,ndst)) {
-				if (0 == ret)
-					ret = -EFAULT;
-				break;
-			}
-			for (; n; n--, src += (1 << bta->sampleshift), dst++)
-				__put_user(*src, dst);
-		}
-
-		ret     += ndst;
-		swcount -= ndst;
-		hwcount -= nsrc;
-		bta->read_count  -= nsrc;
-		bta->read_offset += nsrc;
-		if (bta->read_offset == bta->buf_size)
-			bta->read_offset = 0;
-	}
-	mutex_unlock(&bta->lock);
-	remove_wait_queue(&bta->readq, &wait);
-	current->state = TASK_RUNNING;
-	return ret;
-}
-
-static ssize_t btaudio_dsp_write(struct file *file, const char __user *buffer,
-				 size_t count, loff_t *ppos)
-{
-	return -EINVAL;
-}
-
-static int btaudio_dsp_ioctl(struct inode *inode, struct file *file,
-			     unsigned int cmd, unsigned long arg)
-{
-	struct btaudio *bta = file->private_data;
-	int s, i, ret, val = 0;
-	void __user *argp = (void __user *)arg;
-	int __user *p = argp;
-	
-        switch (cmd) {
-        case OSS_GETVERSION:
-                return put_user(SOUND_VERSION, p);
-        case SNDCTL_DSP_GETCAPS:
-		return 0;
-
-        case SNDCTL_DSP_SPEED:
-		if (get_user(val, p))
-			return -EFAULT;
-		if (bta->analog) {
-			for (s = 0; s < 16; s++)
-				if (val << s >= HWBASE_AD*4/15)
-					break;
-			for (i = 15; i >= 5; i--)
-				if (val << s <= HWBASE_AD*4/i)
-					break;
-			bta->sampleshift = s;
-			bta->decimation  = i;
-			if (debug)
-				printk(KERN_DEBUG "btaudio: rate: req=%d  "
-				       "dec=%d shift=%d hwrate=%d swrate=%d\n",
-				       val,i,s,(HWBASE_AD*4/i),(HWBASE_AD*4/i)>>s);
-		} else {
-			bta->sampleshift = (bta->channels == 2) ? 0 : 1;
-			bta->decimation  = 0;
-		}
-		if (bta->recording) {
-			mutex_lock(&bta->lock);
-			stop_recording(bta);
-			start_recording(bta);
-			mutex_unlock(&bta->lock);
-		}
-		/* fall through */
-        case SOUND_PCM_READ_RATE:
-		if (bta->analog) {
-			return put_user(HWBASE_AD*4/bta->decimation>>bta->sampleshift, p);
-		} else {
-			return put_user(bta->rate, p);
-		}
-
-        case SNDCTL_DSP_STEREO:
-		if (!bta->analog) {
-			if (get_user(val, p))
-				return -EFAULT;
-			bta->channels    = (val > 0) ? 2 : 1;
-			bta->sampleshift = (bta->channels == 2) ? 0 : 1;
-			if (debug)
-				printk(KERN_INFO
-				       "btaudio: stereo=%d channels=%d\n",
-				       val,bta->channels);
-		} else {
-			if (val == 1)
-				return -EFAULT;
-			else {
-				bta->channels = 1;
-				if (debug)
-					printk(KERN_INFO
-					       "btaudio: stereo=0 channels=1\n");
-			}
-		}
-		return put_user((bta->channels)-1, p);
-
-        case SNDCTL_DSP_CHANNELS:
-		if (!bta->analog) {
-			if (get_user(val, p))
-				return -EFAULT;
-			bta->channels    = (val > 1) ? 2 : 1;
-			bta->sampleshift = (bta->channels == 2) ? 0 : 1;
-			if (debug)
-				printk(KERN_DEBUG
-				       "btaudio: val=%d channels=%d\n",
-				       val,bta->channels);
-		}
-		/* fall through */
-        case SOUND_PCM_READ_CHANNELS:
-		return put_user(bta->channels, p);
-		
-        case SNDCTL_DSP_GETFMTS: /* Returns a mask */
-		if (bta->analog)
-			return put_user(AFMT_S16_LE|AFMT_S8, p);
-		else
-			return put_user(AFMT_S16_LE, p);
-
-        case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/
-		if (get_user(val, p))
-			return -EFAULT;
-                if (val != AFMT_QUERY) {
-			if (bta->analog)
-				bta->bits = (val == AFMT_S8) ? 8 : 16;
-			else
-				bta->bits = 16;
-			if (bta->recording) {
-				mutex_lock(&bta->lock);
-				stop_recording(bta);
-				start_recording(bta);
-				mutex_unlock(&bta->lock);
-			}
-		}
-		if (debug)
-			printk(KERN_DEBUG "btaudio: fmt: bits=%d\n",bta->bits);
-                return put_user((bta->bits==16) ? AFMT_S16_LE : AFMT_S8,
-				p);
-		break;
-        case SOUND_PCM_READ_BITS:
-		return put_user(bta->bits, p);
-
-        case SNDCTL_DSP_NONBLOCK:
-                file->f_flags |= O_NONBLOCK;
-                return 0;
-
-        case SNDCTL_DSP_RESET:
-		if (bta->recording) {
-			mutex_lock(&bta->lock);
-			stop_recording(bta);
-			mutex_unlock(&bta->lock);
-		}
-		return 0;
-        case SNDCTL_DSP_GETBLKSIZE:
-		if (!bta->recording) {
-			if (0 != (ret = alloc_buffer(bta)))
-				return ret;
-			if (0 != (ret = make_risc(bta)))
-				return ret;
-		}
-		return put_user(bta->block_bytes>>bta->sampleshift,p);
-
-        case SNDCTL_DSP_SYNC:
-		/* NOP */
-		return 0;
-	case SNDCTL_DSP_GETISPACE:
-	{
-		audio_buf_info info;
-		if (!bta->recording)
-			return -EINVAL;
-		info.fragsize = bta->block_bytes>>bta->sampleshift;
-		info.fragstotal = bta->block_count;
-		info.bytes = bta->read_count;
-		info.fragments = info.bytes / info.fragsize;
-		if (debug)
-			printk(KERN_DEBUG "btaudio: SNDCTL_DSP_GETISPACE "
-			       "returns %d/%d/%d/%d\n",
-			       info.fragsize, info.fragstotal,
-			       info.bytes, info.fragments);
-		if (copy_to_user(argp, &info, sizeof(info)))
-			return -EFAULT;
-		return 0;
-	}
-#if 0 /* TODO */
-        case SNDCTL_DSP_GETTRIGGER:
-        case SNDCTL_DSP_SETTRIGGER:
-        case SNDCTL_DSP_SETFRAGMENT:
-#endif
-	default:
-		return -EINVAL;
-	}
-}
-
-static unsigned int btaudio_dsp_poll(struct file *file, struct poll_table_struct *wait)
-{
-	struct btaudio *bta = file->private_data;
-	unsigned int mask = 0;
-
-	poll_wait(file, &bta->readq, wait);
-
-	if (0 != bta->read_count)
-		mask |= (POLLIN | POLLRDNORM);
-
-	return mask;
-}
-
-static const struct file_operations btaudio_digital_dsp_fops = {
-	.owner		= THIS_MODULE,
-	.llseek		= no_llseek,
-	.open		= btaudio_dsp_open_digital,
-	.release	= btaudio_dsp_release,
-	.read		= btaudio_dsp_read,
-	.write		= btaudio_dsp_write,
-	.ioctl		= btaudio_dsp_ioctl,
-	.poll		= btaudio_dsp_poll,
-};
-
-static const struct file_operations btaudio_analog_dsp_fops = {
-	.owner		= THIS_MODULE,
-	.llseek		= no_llseek,
-	.open		= btaudio_dsp_open_analog,
-	.release	= btaudio_dsp_release,
-	.read		= btaudio_dsp_read,
-	.write		= btaudio_dsp_write,
-	.ioctl		= btaudio_dsp_ioctl,
-	.poll		= btaudio_dsp_poll,
-};
-
-/* -------------------------------------------------------------- */
-
-static char *irq_name[] = { "", "", "", "OFLOW", "", "", "", "", "", "", "",
-			    "RISCI", "FBUS", "FTRGT", "FDSR", "PPERR",
-			    "RIPERR", "PABORT", "OCERR", "SCERR" };
-
-static irqreturn_t btaudio_irq(int irq, void *dev_id)
-{
-	int count = 0;
-	u32 stat,astat;
-	struct btaudio *bta = dev_id;
-	int handled = 0;
-
-	for (;;) {
-		count++;
-		stat  = btread(REG_INT_STAT);
-		astat = stat & btread(REG_INT_MASK);
-		if (!astat)
-			return IRQ_RETVAL(handled);
-		handled = 1;
-		btwrite(astat,REG_INT_STAT);
-
-		if (irq_debug) {
-			int i;
-			printk(KERN_DEBUG "btaudio: irq loop=%d risc=%x, bits:",
-			       count, stat>>28);
-			for (i = 0; i < (sizeof(irq_name)/sizeof(char*)); i++) {
-				if (stat & (1 << i))
-					printk(" %s",irq_name[i]);
-				if (astat & (1 << i))
-					printk("*");
-			}
-			printk("\n");
-		}
-		if (stat & IRQ_RISCI) {
-			int blocks;
-			blocks = (stat >> 28) - bta->dma_block;
-			if (blocks < 0)
-				blocks += bta->block_count;
-			bta->dma_block = stat >> 28;
-			if (bta->read_count + 2*bta->block_bytes > bta->buf_size) {
-				stop_recording(bta);
-				printk(KERN_INFO "btaudio: buffer overrun\n");
-			}
-			if (blocks > 0) {
-				bta->read_count += blocks * bta->block_bytes;
-				wake_up_interruptible(&bta->readq);
-			}
-		}
-		if (count > 10) {
-			printk(KERN_WARNING
-			       "btaudio: Oops - irq mask cleared\n");
-			btwrite(0, REG_INT_MASK);
-		}
-	}
-	return IRQ_NONE;
-}
-
-/* -------------------------------------------------------------- */
-
-static unsigned int dsp1 = -1;
-static unsigned int dsp2 = -1;
-static unsigned int mixer = -1;
-static int latency = -1;
-static int digital = 1;
-static int analog = 1;
-static int rate;
-
-#define BTA_OSPREY200 1
-
-static struct cardinfo cards[] = {
-	[0] = {
-		.name	= "default",
-		.rate	= 32000,
-	},
-	[BTA_OSPREY200] = {
-		.name	= "Osprey 200",
-		.rate	= 44100,
-	},
-};
-
-static int __devinit btaudio_probe(struct pci_dev *pci_dev,
-				   const struct pci_device_id *pci_id)
-{
-	struct btaudio *bta;
-	struct cardinfo *card = &cards[pci_id->driver_data];
-	unsigned char revision,lat;
-	int rc = -EBUSY;
-
-	if (pci_enable_device(pci_dev))
-		return -EIO;
-	if (!request_mem_region(pci_resource_start(pci_dev,0),
-				pci_resource_len(pci_dev,0),
-				"btaudio")) {
-		return -EBUSY;
-	}
-
-	bta = kzalloc(sizeof(*bta),GFP_ATOMIC);
-	if (!bta) {
-		rc = -ENOMEM;
-		goto fail0;
-	}
-
-	bta->pci  = pci_dev;
-	bta->irq  = pci_dev->irq;
-	bta->mem  = pci_resource_start(pci_dev,0);
-	bta->mmio = ioremap(pci_resource_start(pci_dev,0),
-			    pci_resource_len(pci_dev,0));
-
-	bta->source     = 1;
-	bta->bits       = 8;
-	bta->channels   = 1;
-	if (bta->analog) {
-		bta->decimation  = 15;
-	} else {
-		bta->decimation  = 0;
-		bta->sampleshift = 1;
-	}
-
-	/* sample rate */
-	bta->rate = card->rate;
-	if (rate)
-		bta->rate = rate;
-	
-	mutex_init(&bta->lock);
-        init_waitqueue_head(&bta->readq);
-
-	if (-1 != latency) {
-		printk(KERN_INFO "btaudio: setting pci latency timer to %d\n",
-		       latency);
-		pci_write_config_byte(pci_dev, PCI_LATENCY_TIMER, latency);
-	}
-        pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &revision);
-        pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &lat);
-        printk(KERN_INFO "btaudio: Bt%x (rev %d) at %02x:%02x.%x, ",
-	       pci_dev->device,revision,pci_dev->bus->number,
-	       PCI_SLOT(pci_dev->devfn),PCI_FUNC(pci_dev->devfn));
-        printk("irq: %d, latency: %d, mmio: 0x%lx\n",
-	       bta->irq, lat, bta->mem);
-	printk("btaudio: using card config \"%s\"\n", card->name);
-
-	/* init hw */
-        btwrite(0, REG_GPIO_DMA_CTL);
-        btwrite(0, REG_INT_MASK);
-        btwrite(~0U, REG_INT_STAT);
-	pci_set_master(pci_dev);
-
-	if ((rc = request_irq(bta->irq, btaudio_irq, IRQF_SHARED|IRQF_DISABLED,
-			      "btaudio",(void *)bta)) < 0) {
-		printk(KERN_WARNING
-		       "btaudio: can't request irq (rc=%d)\n",rc);
-		goto fail1;
-	}
-
-	/* register devices */
-	if (digital) {
-		rc = bta->dsp_digital =
-			register_sound_dsp(&btaudio_digital_dsp_fops,dsp1);
-		if (rc < 0) {
-			printk(KERN_WARNING
-			       "btaudio: can't register digital dsp (rc=%d)\n",rc);
-			goto fail2;
-		}
-		printk(KERN_INFO "btaudio: registered device dsp%d [digital]\n",
-		       bta->dsp_digital >> 4);
-	}
-	if (analog) {
-		rc = bta->dsp_analog =
-			register_sound_dsp(&btaudio_analog_dsp_fops,dsp2);
-		if (rc < 0) {
-			printk(KERN_WARNING
-			       "btaudio: can't register analog dsp (rc=%d)\n",rc);
-			goto fail3;
-		}
-		printk(KERN_INFO "btaudio: registered device dsp%d [analog]\n",
-		       bta->dsp_analog >> 4);
-		rc = bta->mixer_dev = register_sound_mixer(&btaudio_mixer_fops,mixer);
-		if (rc < 0) {
-			printk(KERN_WARNING
-			       "btaudio: can't register mixer (rc=%d)\n",rc);
-			goto fail4;
-		}
-		printk(KERN_INFO "btaudio: registered device mixer%d\n",
-		       bta->mixer_dev >> 4);
-	}
-
-	/* hook into linked list */
-	bta->next = btaudios;
-	btaudios = bta;
-
-	pci_set_drvdata(pci_dev,bta);
-        return 0;
-
- fail4:
-	unregister_sound_dsp(bta->dsp_analog);
- fail3:
-	if (digital)
-		unregister_sound_dsp(bta->dsp_digital);
- fail2:
-        free_irq(bta->irq,bta);	
- fail1:
-	iounmap(bta->mmio);
-	kfree(bta);
- fail0:
-	release_mem_region(pci_resource_start(pci_dev,0),
-			   pci_resource_len(pci_dev,0));
-	return rc;
-}
-
-static void __devexit btaudio_remove(struct pci_dev *pci_dev)
-{
-	struct btaudio *bta = pci_get_drvdata(pci_dev);
-	struct btaudio *walk;
-
-	/* turn off all DMA / IRQs */
-        btand(~15, REG_GPIO_DMA_CTL);
-        btwrite(0, REG_INT_MASK);
-        btwrite(~0U, REG_INT_STAT);
-
-	/* unregister devices */
-	if (digital) {
-		unregister_sound_dsp(bta->dsp_digital);
-	}
-	if (analog) {
-		unregister_sound_dsp(bta->dsp_analog);
-		unregister_sound_mixer(bta->mixer_dev);
-	}
-
-	/* free resources */
-	free_buffer(bta);
-        free_irq(bta->irq,bta);
-	release_mem_region(pci_resource_start(pci_dev,0),
-			   pci_resource_len(pci_dev,0));
-	iounmap(bta->mmio);
-
-	/* remove from linked list */
-	if (bta == btaudios) {
-		btaudios = NULL;
-	} else {
-		for (walk = btaudios; walk->next != bta; walk = walk->next)
-			; /* if (NULL == walk->next) BUG(); */
-		walk->next = bta->next;
-	}
-
-	pci_set_drvdata(pci_dev, NULL);
-	kfree(bta);
-	return;
-}
-
-/* -------------------------------------------------------------- */
-
-static struct pci_device_id btaudio_pci_tbl[] = {
-        {
-		.vendor		= PCI_VENDOR_ID_BROOKTREE,
-		.device		= 0x0878,
-		.subvendor	= 0x0070,
-		.subdevice	= 0xff01,
-		.driver_data	= BTA_OSPREY200,
-	},{
-		.vendor		= PCI_VENDOR_ID_BROOKTREE,
-		.device		= 0x0878,
-		.subvendor	= PCI_ANY_ID,
-		.subdevice	= PCI_ANY_ID,
-	},{
-		.vendor		= PCI_VENDOR_ID_BROOKTREE,
-		.device		= 0x0878,
-		.subvendor	= PCI_ANY_ID,
-		.subdevice	= PCI_ANY_ID,
-        },{
-		/* --- end of list --- */
-	}
-};
-
-static struct pci_driver btaudio_pci_driver = {
-        .name		= "btaudio",
-        .id_table	= btaudio_pci_tbl,
-        .probe		= btaudio_probe,
-        .remove		=  __devexit_p(btaudio_remove),
-};
-
-static int btaudio_init_module(void)
-{
-	printk(KERN_INFO "btaudio: driver version 0.7 loaded [%s%s%s]\n",
-	       digital ? "digital" : "",
-	       analog && digital ? "+" : "",
-	       analog ? "analog" : "");
-	return pci_register_driver(&btaudio_pci_driver);
-}
-
-static void btaudio_cleanup_module(void)
-{
-	pci_unregister_driver(&btaudio_pci_driver);
-	return;
-}
-
-module_init(btaudio_init_module);
-module_exit(btaudio_cleanup_module);
-
-module_param(dsp1, int, S_IRUGO);
-module_param(dsp2, int, S_IRUGO);
-module_param(mixer, int, S_IRUGO);
-module_param(debug, int, S_IRUGO | S_IWUSR);
-module_param(irq_debug, int, S_IRUGO | S_IWUSR);
-module_param(digital, int, S_IRUGO);
-module_param(analog, int, S_IRUGO);
-module_param(rate, int, S_IRUGO);
-module_param(latency, int, S_IRUGO);
-MODULE_PARM_DESC(latency,"pci latency timer");
-
-MODULE_DEVICE_TABLE(pci, btaudio_pci_tbl);
-MODULE_DESCRIPTION("bt878 audio dma driver");
-MODULE_AUTHOR("Gerd Knorr");
-MODULE_LICENSE("GPL");
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/sound/oss/cs4232.c b/sound/oss/cs4232.c
deleted file mode 100644
index de40e21..0000000
--- a/sound/oss/cs4232.c
+++ /dev/null
@@ -1,526 +0,0 @@
-/*
- * Copyright (C) by Hannu Savolainen 1993-1997
- *
- *	cs4232.c
- *
- * The low level driver for Crystal CS4232 based cards. The CS4232 is
- * a PnP compatible chip which contains a CS4231A codec, SB emulation,
- * a MPU401 compatible MIDI port, joystick and synthesizer and IDE CD-ROM 
- * interfaces. This is just a temporary driver until full PnP support
- * gets implemented. Just the WSS codec, FM synth and the MIDI ports are
- * supported. Other interfaces are left uninitialized.
- *
- * ifdef ...WAVEFRONT...
- * 
- *   Support is provided for initializing the WaveFront synth
- *   interface as well, which is logical device #4. Note that if
- *   you have a Tropez+ card, you probably don't need to setup
- *   the CS4232-supported MIDI interface, since it corresponds to
- *   the internal 26-pin header that's hard to access. Using this
- *   requires an additional IRQ, a resource none too plentiful in
- *   this environment. Just don't set module parameters mpuio and
- *   mpuirq, and the MIDI port will be left uninitialized. You can
- *   still use the ICS2115 hosted MIDI interface which corresponds
- *   to the 9-pin D connector on the back of the card.
- *
- * endif  ...WAVEFRONT...
- *
- * Supported chips are:
- *      CS4232
- *      CS4236
- *      CS4236B
- *
- * Note: You will need a PnP config setup to initialise some CS4232 boards
- * anyway.
- *
- * Changes
- *      John Rood               Added Bose Sound System Support.
- *      Toshio Spoor
- *	Alan Cox		Modularisation, Basic cleanups.
- *      Paul Barton-Davis	Separated MPU configuration, added
- *                                       Tropez+ (WaveFront) support
- *	Christoph Hellwig	Adapted to module_init/module_exit,
- * 					simple cleanups
- * 	Arnaldo C. de Melo	got rid of attach_uart401
- *	Bartlomiej Zolnierkiewicz
- *				Added some __init/__initdata/__exit
- *	Marcus Meissner		Added ISA PnP support.
- */
-
-#include <linux/pnp.h>
-#include <linux/module.h>
-#include <linux/init.h>
-
-#include "sound_config.h"
-
-#include "ad1848.h"
-#include "mpu401.h"
-
-#define KEY_PORT	0x279	/* Same as LPT1 status port */
-#define CSN_NUM		0x99	/* Just a random number */
-#define INDEX_ADDRESS   0x00    /* (R0) Index Address Register */
-#define INDEX_DATA      0x01    /* (R1) Indexed Data Register */
-#define PIN_CONTROL     0x0a    /* (I10) Pin Control */
-#define ENABLE_PINS     0xc0    /* XCTRL0/XCTRL1 enable */
-
-static void CS_OUT(unsigned char a)
-{
-	outb(a, KEY_PORT);
-}
-
-#define CS_OUT2(a, b)		{CS_OUT(a);CS_OUT(b);}
-#define CS_OUT3(a, b, c)	{CS_OUT(a);CS_OUT(b);CS_OUT(c);}
-
-static int __initdata bss       = 0;
-static int mpu_base, mpu_irq;
-static int synth_base, synth_irq;
-static int mpu_detected;
-
-static int probe_cs4232_mpu(struct address_info *hw_config)
-{
-	/*
-	 *	Just write down the config values.
-	 */
-
-	mpu_base = hw_config->io_base;
-	mpu_irq = hw_config->irq;
-
-	return 1;
-}
-
-static unsigned char crystal_key[] =	/* A 32 byte magic key sequence */
-{
-	0x96, 0x35, 0x9a, 0xcd, 0xe6, 0xf3, 0x79, 0xbc,
-	0x5e, 0xaf, 0x57, 0x2b, 0x15, 0x8a, 0xc5, 0xe2,
-	0xf1, 0xf8, 0x7c, 0x3e, 0x9f, 0x4f, 0x27, 0x13,
-	0x09, 0x84, 0x42, 0xa1, 0xd0, 0x68, 0x34, 0x1a
-};
-
-static void sleep(unsigned howlong)
-{
-	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(howlong);
-}
-
-static void enable_xctrl(int baseio)
-{
-        unsigned char regd;
-                
-        /*
-         * Some IBM Aptiva's have the Bose Sound System. By default
-         * the Bose Amplifier is disabled. The amplifier will be 
-         * activated, by setting the XCTRL0 and XCTRL1 bits.
-         * Volume of the monitor bose speakers/woofer, can then
-         * be set by changing the PCM volume.
-         *
-         */
-                
-        printk("cs4232: enabling Bose Sound System Amplifier.\n");
-        
-        /* Switch to Pin Control Address */                   
-        regd = inb(baseio + INDEX_ADDRESS) & 0xe0;
-        outb(((unsigned char) (PIN_CONTROL | regd)), baseio + INDEX_ADDRESS );
-        
-        /* Activate the XCTRL0 and XCTRL1 Pins */
-        regd = inb(baseio + INDEX_DATA);
-        outb(((unsigned char) (ENABLE_PINS | regd)), baseio + INDEX_DATA );
-}
-
-static int __init probe_cs4232(struct address_info *hw_config, int isapnp_configured)
-{
-	int i, n;
-	int base = hw_config->io_base, irq = hw_config->irq;
-	int dma1 = hw_config->dma, dma2 = hw_config->dma2;
-	struct resource *ports;
-
-	if (base == -1 || irq == -1 || dma1 == -1) {
-		printk(KERN_ERR "cs4232: dma, irq and io must be set.\n");
-		return 0;
-	}
-
-	/*
-	 * Verify that the I/O port range is free.
-	 */
-
-	ports = request_region(base, 4, "ad1848");
-	if (!ports) {
-		printk(KERN_ERR "cs4232.c: I/O port 0x%03x not free\n", base);
-		return 0;
-	}
-	if (ad1848_detect(ports, NULL, hw_config->osp)) {
-		goto got_it;	/* The card is already active */
-	}
-	if (isapnp_configured) {
-		printk(KERN_ERR "cs4232.c: ISA PnP configured, but not detected?\n");
-		goto fail;
-	}
-
-	/*
-	 * This version of the driver doesn't use the PnP method when configuring
-	 * the card but a simplified method defined by Crystal. This means that
-	 * just one CS4232 compatible device can exist on the system. Also this
-	 * method conflicts with possible PnP support in the OS. For this reason 
-	 * driver is just a temporary kludge.
-	 *
-	 * Also the Cirrus/Crystal method doesn't always work. Try ISA PnP first ;)
-	 */
-
-	/*
-	 * Repeat initialization few times since it doesn't always succeed in
-	 * first time.
-	 */
-
-	for (n = 0; n < 4; n++)
-	{	
-		/*
-		 *	Wake up the card by sending a 32 byte Crystal key to the key port.
-		 */
-		
-		for (i = 0; i < 32; i++)
-			CS_OUT(crystal_key[i]);
-
-		sleep(HZ / 10);
-
-		/*
-		 *	Now set the CSN (Card Select Number).
-		 */
-
-		CS_OUT2(0x06, CSN_NUM);
-
-		/*
-		 *	Then set some config bytes. First logical device 0 
-		 */
-
-		CS_OUT2(0x15, 0x00);	/* Select logical device 0 (WSS/SB/FM) */
-		CS_OUT3(0x47, (base >> 8) & 0xff, base & 0xff);	/* WSS base */
-
-		if (!request_region(0x388, 4, "FM"))	/* Not free */
-			CS_OUT3(0x48, 0x00, 0x00)	/* FM base off */
-		else {
-			release_region(0x388, 4);
-			CS_OUT3(0x48, 0x03, 0x88);	/* FM base 0x388 */
-		}
-
-		CS_OUT3(0x42, 0x00, 0x00);	/* SB base off */
-		CS_OUT2(0x22, irq);		/* SB+WSS IRQ */
-		CS_OUT2(0x2a, dma1);		/* SB+WSS DMA */
-
-		if (dma2 != -1)
-			CS_OUT2(0x25, dma2)	/* WSS DMA2 */
-		else
-			CS_OUT2(0x25, 4);	/* No WSS DMA2 */
-
-		CS_OUT2(0x33, 0x01);	/* Activate logical dev 0 */
-
-		sleep(HZ / 10);
-
-		/*
-		 * Initialize logical device 3 (MPU)
-		 */
-
-		if (mpu_base != 0 && mpu_irq != 0)
-		{
-			CS_OUT2(0x15, 0x03);	/* Select logical device 3 (MPU) */
-			CS_OUT3(0x47, (mpu_base >> 8) & 0xff, mpu_base & 0xff);	/* MPU base */
-			CS_OUT2(0x22, mpu_irq);	/* MPU IRQ */
-			CS_OUT2(0x33, 0x01);	/* Activate logical dev 3 */
-		}
-
-		if(synth_base != 0)
-		{
-		    CS_OUT2 (0x15, 0x04);	        /* logical device 4 (WaveFront) */
-		    CS_OUT3 (0x47, (synth_base >> 8) & 0xff,
-			     synth_base & 0xff);	/* base */
-		    CS_OUT2 (0x22, synth_irq);     	/* IRQ */
-		    CS_OUT2 (0x33, 0x01);	        /* Activate logical dev 4 */
-		}
-
-		/*
-		 * Finally activate the chip
-		 */
-		
-		CS_OUT(0x79);
-
-		sleep(HZ / 5);
-
-		/*
-		 * Then try to detect the codec part of the chip
-		 */
-
-		if (ad1848_detect(ports, NULL, hw_config->osp))
-			goto got_it;
-		
-		sleep(HZ);
-	}
-fail:
-	release_region(base, 4);
-	return 0;
-
-got_it:
-	if (dma2 == -1)
-		dma2 = dma1;
-
-	hw_config->slots[0] = ad1848_init("Crystal audio controller", ports,
-					  irq,
-					  dma1,		/* Playback DMA */
-					  dma2,		/* Capture DMA */
-					  0,
-					  hw_config->osp,
-					  THIS_MODULE);
-
-	if (hw_config->slots[0] != -1 &&
-		audio_devs[hw_config->slots[0]]->mixer_dev!=-1)
-	{	
-		/* Assume the mixer map is as suggested in the CS4232 databook */
-		AD1848_REROUTE(SOUND_MIXER_LINE1, SOUND_MIXER_LINE);
-		AD1848_REROUTE(SOUND_MIXER_LINE2, SOUND_MIXER_CD);
-		AD1848_REROUTE(SOUND_MIXER_LINE3, SOUND_MIXER_SYNTH);		/* FM synth */
-	}
-	if (mpu_base != 0 && mpu_irq != 0)
-	{
-		static struct address_info hw_config2 = {
-			0
-		};		/* Ensure it's initialized */
-
-		hw_config2.io_base = mpu_base;
-		hw_config2.irq = mpu_irq;
-		hw_config2.dma = -1;
-		hw_config2.dma2 = -1;
-		hw_config2.always_detect = 0;
-		hw_config2.name = NULL;
-		hw_config2.driver_use_1 = 0;
-		hw_config2.driver_use_2 = 0;
-		hw_config2.card_subtype = 0;
-
-		if (probe_uart401(&hw_config2, THIS_MODULE))
-		{
-			mpu_detected = 1;
-		}
-		else
-		{
-			mpu_base = mpu_irq = 0;
-		}
-		hw_config->slots[1] = hw_config2.slots[1];
-	}
-	
-	if (bss)
-        	enable_xctrl(base);
-
-	return 1;
-}
-
-static void __devexit unload_cs4232(struct address_info *hw_config)
-{
-	int base = hw_config->io_base, irq = hw_config->irq;
-	int dma1 = hw_config->dma, dma2 = hw_config->dma2;
-
-	if (dma2 == -1)
-		dma2 = dma1;
-
-	ad1848_unload(base,
-		      irq,
-		      dma1,	/* Playback DMA */
-		      dma2,	/* Capture DMA */
-		      0);
-
-	sound_unload_audiodev(hw_config->slots[0]);
-	if (mpu_base != 0 && mpu_irq != 0 && mpu_detected)
-	{
-		static struct address_info hw_config2 =
-		{
-			0
-		};		/* Ensure it's initialized */
-
-		hw_config2.io_base = mpu_base;
-		hw_config2.irq = mpu_irq;
-		hw_config2.dma = -1;
-		hw_config2.dma2 = -1;
-		hw_config2.always_detect = 0;
-		hw_config2.name = NULL;
-		hw_config2.driver_use_1 = 0;
-		hw_config2.driver_use_2 = 0;
-		hw_config2.card_subtype = 0;
-		hw_config2.slots[1] = hw_config->slots[1];
-
-		unload_uart401(&hw_config2);
-	}
-}
-
-static struct address_info cfg;
-static struct address_info cfg_mpu;
-
-static int __initdata io	= -1;
-static int __initdata irq	= -1;
-static int __initdata dma	= -1;
-static int __initdata dma2	= -1;
-static int __initdata mpuio	= -1;
-static int __initdata mpuirq	= -1;
-static int __initdata synthio	= -1;
-static int __initdata synthirq	= -1;
-static int __initdata isapnp	= 1;
-
-static unsigned int cs4232_devices;
-
-MODULE_DESCRIPTION("CS4232 based soundcard driver"); 
-MODULE_AUTHOR("Hannu Savolainen, Paul Barton-Davis"); 
-MODULE_LICENSE("GPL");
-
-module_param(io, int, 0);
-MODULE_PARM_DESC(io,"base I/O port for AD1848");
-module_param(irq, int, 0);
-MODULE_PARM_DESC(irq,"IRQ for AD1848 chip");
-module_param(dma, int, 0);
-MODULE_PARM_DESC(dma,"8 bit DMA for AD1848 chip");
-module_param(dma2, int, 0);
-MODULE_PARM_DESC(dma2,"16 bit DMA for AD1848 chip");
-module_param(mpuio, int, 0);
-MODULE_PARM_DESC(mpuio,"MPU 401 base address");
-module_param(mpuirq, int, 0);
-MODULE_PARM_DESC(mpuirq,"MPU 401 IRQ");
-module_param(synthio, int, 0);
-MODULE_PARM_DESC(synthio,"Maui WaveTable base I/O port");
-module_param(synthirq, int, 0);
-MODULE_PARM_DESC(synthirq,"Maui WaveTable IRQ");
-module_param(isapnp, bool, 0);
-MODULE_PARM_DESC(isapnp,"Enable ISAPnP probing (default 1)");
-module_param(bss, bool, 0);
-MODULE_PARM_DESC(bss,"Enable Bose Sound System Support (default 0)");
-
-/*
- *	Install a CS4232 based card. Need to have ad1848 and mpu401
- *	loaded ready.
- */
-
-/* All cs4232 based cards have the main ad1848 card either as CSC0000 or
- * CSC0100. */
-static const struct pnp_device_id cs4232_pnp_table[] = {
-	{ .id = "CSC0100", .driver_data = 0 },
-	{ .id = "CSC0000", .driver_data = 0 },
-	/* Guillemot Turtlebeach something appears to be cs4232 compatible
-	 * (untested) */
-	{ .id = "GIM0100", .driver_data = 0 },
-	{ .id = ""}
-};
-
-MODULE_DEVICE_TABLE(pnp, cs4232_pnp_table);
-
-static int __init cs4232_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
-{
-	struct address_info *isapnpcfg;
-
-	isapnpcfg = kmalloc(sizeof(*isapnpcfg),GFP_KERNEL);
-	if (!isapnpcfg)
-		return -ENOMEM;
-
-	isapnpcfg->irq		= pnp_irq(dev, 0);
-	isapnpcfg->dma		= pnp_dma(dev, 0);
-	isapnpcfg->dma2		= pnp_dma(dev, 1);
-	isapnpcfg->io_base	= pnp_port_start(dev, 0);
-	if (probe_cs4232(isapnpcfg,TRUE) == 0) {
-		printk(KERN_ERR "cs4232: ISA PnP card found, but not detected?\n");
-		kfree(isapnpcfg);
-		return -ENODEV;
-	}
-	pnp_set_drvdata(dev,isapnpcfg);
-	cs4232_devices++;
-	return 0;
-}
-
-static void __devexit cs4232_pnp_remove(struct pnp_dev *dev)
-{
-	struct address_info *cfg = pnp_get_drvdata(dev);
-	if (cfg) {
-		unload_cs4232(cfg);
-		kfree(cfg);
-	}
-}
-
-static struct pnp_driver cs4232_driver = {
-	.name		= "cs4232",
-	.id_table	= cs4232_pnp_table,
-	.probe		= cs4232_pnp_probe,
-	.remove		= __devexit_p(cs4232_pnp_remove),
-};
-
-static int __init init_cs4232(void)
-{
-#ifdef CONFIG_SOUND_WAVEFRONT_MODULE
-	if(synthio == -1)
-		printk(KERN_INFO "cs4232: set synthio and synthirq to use the wavefront facilities.\n");
-	else {
-		synth_base = synthio;
-		synth_irq =  synthirq;
-	}
-#else
-	if(synthio != -1)
-		printk(KERN_WARNING "cs4232: wavefront support not enabled in this driver.\n");
-#endif
-	cfg.irq = -1;
-
-	if (isapnp) {
-		pnp_register_driver(&cs4232_driver);
-		if (cs4232_devices)
-			return 0;
-	}
-
-	if(io==-1||irq==-1||dma==-1)
-	{
-		printk(KERN_ERR "cs4232: Must set io, irq and dma.\n");
-		return -ENODEV;
-	}
-
-	cfg.io_base = io;
-	cfg.irq = irq;
-	cfg.dma = dma;
-	cfg.dma2 = dma2;
-
-	cfg_mpu.io_base = -1;
-	cfg_mpu.irq = -1;
-
-	if (mpuio != -1 && mpuirq != -1) {
-		cfg_mpu.io_base = mpuio;
-		cfg_mpu.irq = mpuirq;
-		probe_cs4232_mpu(&cfg_mpu); /* Bug always returns 0 not OK -- AC */
-	}
-
-	if (probe_cs4232(&cfg,FALSE) == 0)
-		return -ENODEV;
-
-	return 0;
-}
-
-static void __exit cleanup_cs4232(void)
-{
-	pnp_unregister_driver(&cs4232_driver);
-        if (cfg.irq != -1)
-		unload_cs4232(&cfg); /* Unloads global MPU as well, if needed */
-}
-
-module_init(init_cs4232);
-module_exit(cleanup_cs4232);
-
-#ifndef MODULE
-static int __init setup_cs4232(char *str)
-{
-	/* io, irq, dma, dma2 mpuio, mpuirq*/
-	int ints[7];
-
-	/* If we have isapnp cards, no need for options */
-	pnp_register_driver(&cs4232_driver);
-	if (cs4232_devices)
-		return 1;
-	
-	str = get_options(str, ARRAY_SIZE(ints), ints);
-	
-	io	= ints[1];
-	irq	= ints[2];
-	dma	= ints[3];
-	dma2	= ints[4];
-	mpuio	= ints[5];
-	mpuirq	= ints[6];
-
-	return 1;
-}
-
-__setup("cs4232=", setup_cs4232);
-#endif
diff --git a/sound/oss/i810_audio.c b/sound/oss/i810_audio.c
deleted file mode 100644
index f5e31f1..0000000
--- a/sound/oss/i810_audio.c
+++ /dev/null
@@ -1,3656 +0,0 @@
-/*
- *	Intel i810 and friends ICH driver for Linux
- *	Alan Cox <alan@redhat.com>
- *
- *  Built from:
- *	Low level code:  Zach Brown (original nonworking i810 OSS driver)
- *			 Jaroslav Kysela <perex@suse.cz> (working ALSA driver)
- *
- *	Framework: Thomas Sailer <sailer@ife.ee.ethz.ch>
- *	Extended by: Zach Brown <zab@redhat.com>  
- *			and others..
- *
- *  Hardware Provided By:
- *	Analog Devices (A major AC97 codec maker)
- *	Intel Corp  (you've probably heard of them already)
- *
- *  AC97 clues and assistance provided by
- *	Analog Devices
- *	Zach 'Fufu' Brown
- *	Jeff Garzik
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	This program is distributed in the hope that it will be useful,
- *	but WITHOUT ANY WARRANTY; without even the implied warranty of
- *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *	GNU General Public License for more details.
- *
- *	You should have received a copy of the GNU General Public License
- *	along with this program; if not, write to the Free Software
- *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *
- *	Intel 810 theory of operation
- *
- *	The chipset provides three DMA channels that talk to an AC97
- *	CODEC (AC97 is a digital/analog mixer standard). At its simplest
- *	you get 48Khz audio with basic volume and mixer controls. At the
- *	best you get rate adaption in the codec. We set the card up so
- *	that we never take completion interrupts but instead keep the card
- *	chasing its tail around a ring buffer. This is needed for mmap
- *	mode audio and happens to work rather well for non-mmap modes too.
- *
- *	The board has one output channel for PCM audio (supported) and
- *	a stereo line in and mono microphone input. Again these are normally
- *	locked to 48Khz only. Right now recording is not finished.
- *
- *	There is no midi support, no synth support. Use timidity. To get
- *	esd working you need to use esd -r 48000 as it won't probe 48KHz
- *	by default. mpg123 can't handle 48Khz only audio so use xmms.
- *
- *	Fix The Sound On Dell
- *
- *	Not everyone uses 48KHz. We know of no way to detect this reliably
- *	and certainly not to get the right data. If your i810 audio sounds
- *	stupid you may need to investigate other speeds. According to Analog
- *	they tend to use a 14.318MHz clock which gives you a base rate of
- *	41194Hz.
- *
- *	This is available via the 'ftsodell=1' option. 
- *
- *	If you need to force a specific rate set the clocking= option
- *
- *	This driver is cursed. (Ben LaHaise)
- *
- *  ICH 3 caveats
- *	Intel errata #7 for ICH3 IO. We need to disable SMI stuff
- *	when codec probing. [Not Yet Done]
- *
- *  ICH 4 caveats
- *
- *	The ICH4 has the feature, that the codec ID doesn't have to be 
- *	congruent with the IO connection.
- * 
- *	Therefore, from driver version 0.23 on, there is a "codec ID" <->
- *	"IO register base offset" mapping (card->ac97_id_map) field.
- *   
- *	Juergen "George" Sawinski (jsaw) 
- */
- 
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/ctype.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/delay.h>
-#include <linux/sound.h>
-#include <linux/slab.h>
-#include <linux/soundcard.h>
-#include <linux/pci.h>
-#include <linux/interrupt.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <linux/init.h>
-#include <linux/poll.h>
-#include <linux/spinlock.h>
-#include <linux/smp_lock.h>
-#include <linux/ac97_codec.h>
-#include <linux/bitops.h>
-#include <linux/mutex.h>
-#include <linux/mm.h>
-
-#include <asm/uaccess.h>
-
-#define DRIVER_VERSION "1.01"
-
-#define MODULOP2(a, b) ((a) & ((b) - 1))
-#define MASKP2(a, b) ((a) & ~((b) - 1))
-
-static int ftsodell;
-static int strict_clocking;
-static unsigned int clocking;
-static int spdif_locked;
-static int ac97_quirk = AC97_TUNE_DEFAULT;
-
-//#define DEBUG
-//#define DEBUG2
-//#define DEBUG_INTERRUPTS
-//#define DEBUG_MMAP
-//#define DEBUG_MMIO
-
-#define ADC_RUNNING	1
-#define DAC_RUNNING	2
-
-#define I810_FMT_16BIT	1
-#define I810_FMT_STEREO	2
-#define I810_FMT_MASK	3
-
-#define SPDIF_ON	0x0004
-#define SURR_ON		0x0010
-#define CENTER_LFE_ON	0x0020
-#define VOL_MUTED	0x8000
-
-/* the 810's array of pointers to data buffers */
-
-struct sg_item {
-#define BUSADDR_MASK	0xFFFFFFFE
-	u32 busaddr;	
-#define CON_IOC 	0x80000000 /* interrupt on completion */
-#define CON_BUFPAD	0x40000000 /* pad underrun with last sample, else 0 */
-#define CON_BUFLEN_MASK	0x0000ffff /* buffer length in samples */
-	u32 control;
-};
-
-/* an instance of the i810 channel */
-#define SG_LEN 32
-struct i810_channel 
-{
-	/* these sg guys should probably be allocated
-	   separately as nocache. Must be 8 byte aligned */
-	struct sg_item sg[SG_LEN];	/* 32*8 */
-	u32 offset;			/* 4 */
-	u32 port;			/* 4 */
-	u32 used;
-	u32 num;
-};
-
-/*
- * we have 3 separate dma engines.  pcm in, pcm out, and mic.
- * each dma engine has controlling registers.  These goofy
- * names are from the datasheet, but make it easy to write
- * code while leafing through it.
- *
- * ICH4 has 6 dma engines, pcm in, pcm out, mic, pcm in 2, 
- * mic in 2, s/pdif.   Of special interest is the fact that
- * the upper 3 DMA engines on the ICH4 *must* be accessed
- * via mmio access instead of pio access.
- */
-
-#define ENUM_ENGINE(PRE,DIG) 									\
-enum {												\
-	PRE##_BASE =	0x##DIG##0,		/* Base Address */				\
-	PRE##_BDBAR =	0x##DIG##0,		/* Buffer Descriptor list Base Address */	\
-	PRE##_CIV =	0x##DIG##4,		/* Current Index Value */			\
-	PRE##_LVI =	0x##DIG##5,		/* Last Valid Index */				\
-	PRE##_SR =	0x##DIG##6,		/* Status Register */				\
-	PRE##_PICB =	0x##DIG##8,		/* Position In Current Buffer */		\
-	PRE##_PIV =	0x##DIG##a,		/* Prefetched Index Value */			\
-	PRE##_CR =	0x##DIG##b		/* Control Register */				\
-}
-
-ENUM_ENGINE(OFF,0);	/* Offsets */
-ENUM_ENGINE(PI,0);	/* PCM In */
-ENUM_ENGINE(PO,1);	/* PCM Out */
-ENUM_ENGINE(MC,2);	/* Mic In */
-
-enum {
-	GLOB_CNT =	0x2c,			/* Global Control */
-	GLOB_STA = 	0x30,			/* Global Status */
-	CAS	 = 	0x34			/* Codec Write Semaphore Register */
-};
-
-ENUM_ENGINE(MC2,4);     /* Mic In 2 */
-ENUM_ENGINE(PI2,5);     /* PCM In 2 */
-ENUM_ENGINE(SP,6);      /* S/PDIF */
-
-enum {
-	SDM =           0x80                    /* SDATA_IN Map Register */
-};
-
-/* interrupts for a dma engine */
-#define DMA_INT_FIFO		(1<<4)  /* fifo under/over flow */
-#define DMA_INT_COMPLETE	(1<<3)  /* buffer read/write complete and ioc set */
-#define DMA_INT_LVI		(1<<2)  /* last valid done */
-#define DMA_INT_CELV		(1<<1)  /* last valid is current */
-#define DMA_INT_DCH		(1)	/* DMA Controller Halted (happens on LVI interrupts) */
-#define DMA_INT_MASK (DMA_INT_FIFO|DMA_INT_COMPLETE|DMA_INT_LVI)
-
-/* interrupts for the whole chip */
-#define INT_SEC		(1<<11)
-#define INT_PRI		(1<<10)
-#define INT_MC		(1<<7)
-#define INT_PO		(1<<6)
-#define INT_PI		(1<<5)
-#define INT_MO		(1<<2)
-#define INT_NI		(1<<1)
-#define INT_GPI		(1<<0)
-#define INT_MASK (INT_SEC|INT_PRI|INT_MC|INT_PO|INT_PI|INT_MO|INT_NI|INT_GPI)
-
-/* magic numbers to protect our data structures */
-#define I810_CARD_MAGIC		0x5072696E /* "Prin" */
-#define I810_STATE_MAGIC	0x63657373 /* "cess" */
-#define I810_DMA_MASK		0xffffffff /* DMA buffer mask for pci_alloc_consist */
-#define NR_HW_CH		3
-
-/* maxinum number of AC97 codecs connected, AC97 2.0 defined 4 */
-#define NR_AC97                 4
-
-/* Please note that an 8bit mono stream is not valid on this card, you must have a 16bit */
-/* stream at a minimum for this card to be happy */
-static const unsigned sample_size[] = { 1, 2, 2, 4 };
-/* Samples are 16bit values, so we are shifting to a word, not to a byte, hence shift */
-/* values are one less than might be expected */
-static const unsigned sample_shift[] = { -1, 0, 0, 1 };
-
-enum {
-	ICH82801AA = 0,
-	ICH82901AB,
-	INTEL440MX,
-	INTELICH2,
-	INTELICH3,
-	INTELICH4,
-	INTELICH5,
-	SI7012,
-	NVIDIA_NFORCE,
-	AMD768,
-	AMD8111
-};
-
-static char * card_names[] = {
-	"Intel ICH 82801AA",
-	"Intel ICH 82901AB",
-	"Intel 440MX",
-	"Intel ICH2",
-	"Intel ICH3",
-	"Intel ICH4",
-	"Intel ICH5",
-	"SiS 7012",
-	"NVIDIA nForce Audio",
-	"AMD 768",
-	"AMD-8111 IOHub"
-};
-
-/* These are capabilities (and bugs) the chipsets _can_ have */
-static struct {
-	int16_t      nr_ac97;
-#define CAP_MMIO                 0x0001
-#define CAP_20BIT_AUDIO_SUPPORT  0x0002
-	u_int16_t flags;
-} card_cap[] = {
-	{  1, 0x0000 }, /* ICH82801AA */
-	{  1, 0x0000 }, /* ICH82901AB */
-	{  1, 0x0000 }, /* INTEL440MX */
-	{  1, 0x0000 }, /* INTELICH2 */
-	{  2, 0x0000 }, /* INTELICH3 */
- 	{  3, 0x0003 }, /* INTELICH4 */
-	{  3, 0x0003 }, /* INTELICH5 */
-	/*@FIXME to be verified*/	{  2, 0x0000 }, /* SI7012 */
-	/*@FIXME to be verified*/	{  2, 0x0000 }, /* NVIDIA_NFORCE */
-	/*@FIXME to be verified*/	{  2, 0x0000 }, /* AMD768 */
-	/*@FIXME to be verified*/	{  3, 0x0001 }, /* AMD8111 */
-};
-
-static struct pci_device_id i810_pci_tbl [] = {
-	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_5,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, ICH82801AA},
-	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_5,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, ICH82901AB},
-	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_440MX,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTEL440MX},
-	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_4,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH2},
-	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_5,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH3},
-	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_5,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH4},
-	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_5,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH5},
-	{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_7012,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, SI7012},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_MCP1_AUDIO,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_NFORCE},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_NFORCE},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_NFORCE},
-	{PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_OPUS_7445,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD768},
-	{PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_AUDIO,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD8111},
-	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_5,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH4},
-	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_18,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, INTELICH4},
-	{PCI_VENDOR_ID_NVIDIA,  PCI_DEVICE_ID_NVIDIA_CK804_AUDIO,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_NFORCE},
-	{0,}
-};
-
-MODULE_DEVICE_TABLE (pci, i810_pci_tbl);
-
-#ifdef CONFIG_PM
-#define PM_SUSPENDED(card) (card->pm_suspended)
-#else
-#define PM_SUSPENDED(card) (0)
-#endif
-
-/* "software" or virtual channel, an instance of opened /dev/dsp */
-struct i810_state {
-	unsigned int magic;
-	struct i810_card *card;	/* Card info */
-
-	/* single open lock mechanism, only used for recording */
-	struct mutex open_mutex;
-	wait_queue_head_t open_wait;
-
-	/* file mode */
-	mode_t open_mode;
-
-	/* virtual channel number */
-	int virt;
-
-#ifdef CONFIG_PM
-	unsigned int pm_saved_dac_rate,pm_saved_adc_rate;
-#endif
-	struct dmabuf {
-		/* wave sample stuff */
-		unsigned int rate;
-		unsigned char fmt, enable, trigger;
-
-		/* hardware channel */
-		struct i810_channel *read_channel;
-		struct i810_channel *write_channel;
-
-		/* OSS buffer management stuff */
-		void *rawbuf;
-		dma_addr_t dma_handle;
-		unsigned buforder;
-		unsigned numfrag;
-		unsigned fragshift;
-
-		/* our buffer acts like a circular ring */
-		unsigned hwptr;		/* where dma last started, updated by update_ptr */
-		unsigned swptr;		/* where driver last clear/filled, updated by read/write */
-		int count;		/* bytes to be consumed or been generated by dma machine */
-		unsigned total_bytes;	/* total bytes dmaed by hardware */
-
-		unsigned error;		/* number of over/underruns */
-		wait_queue_head_t wait;	/* put process on wait queue when no more space in buffer */
-
-		/* redundant, but makes calculations easier */
-		/* what the hardware uses */
-		unsigned dmasize;
-		unsigned fragsize;
-		unsigned fragsamples;
-
-		/* what we tell the user to expect */
-		unsigned userfrags;
-		unsigned userfragsize;
-
-		/* OSS stuff */
-		unsigned mapped:1;
-		unsigned ready:1;
-		unsigned update_flag;
-		unsigned ossfragsize;
-		unsigned ossmaxfrags;
-		unsigned subdivision;
-	} dmabuf;
-};
-
-
-struct i810_card {
-	unsigned int magic;
-
-	/* We keep i810 cards in a linked list */
-	struct i810_card *next;
-
-	/* The i810 has a certain amount of cross channel interaction
-	   so we use a single per card lock */
-	spinlock_t lock;
-	
-	/* Control AC97 access serialization */
-	spinlock_t ac97_lock;
-
-	/* PCI device stuff */
-	struct pci_dev * pci_dev;
-	u16 pci_id;
-	u16 pci_id_internal; /* used to access card_cap[] */
-#ifdef CONFIG_PM	
-	u16 pm_suspended;
-	int pm_saved_mixer_settings[SOUND_MIXER_NRDEVICES][NR_AC97];
-#endif
-	/* soundcore stuff */
-	int dev_audio;
-
-	/* structures for abstraction of hardware facilities, codecs, banks and channels*/
-	u16    ac97_id_map[NR_AC97];
-	struct ac97_codec *ac97_codec[NR_AC97];
-	struct i810_state *states[NR_HW_CH];
-	struct i810_channel *channel;	/* 1:1 to states[] but diff. lifetime */
-	dma_addr_t chandma;
-
-	u16 ac97_features;
-	u16 ac97_status;
-	u16 channels;
-	
-	/* hardware resources */
-	unsigned long ac97base;
-	unsigned long iobase;
-	u32 irq;
-
-	unsigned long ac97base_mmio_phys;
-	unsigned long iobase_mmio_phys;
-	u_int8_t __iomem *ac97base_mmio;
-	u_int8_t __iomem *iobase_mmio;
-
-	int           use_mmio;
-	
-	/* Function support */
-	struct i810_channel *(*alloc_pcm_channel)(struct i810_card *);
-	struct i810_channel *(*alloc_rec_pcm_channel)(struct i810_card *);
-	struct i810_channel *(*alloc_rec_mic_channel)(struct i810_card *);
-	void (*free_pcm_channel)(struct i810_card *, int chan);
-
-	/* We have a *very* long init time possibly, so use this to block */
-	/* attempts to open our devices before we are ready (stops oops'es) */
-	int initializing;
-};
-
-/* extract register offset from codec struct */
-#define IO_REG_OFF(codec) (((struct i810_card *) codec->private_data)->ac97_id_map[codec->id])
-
-#define I810_IOREAD(size, type, card, off)				\
-({									\
-	type val;							\
-	if (card->use_mmio)						\
-		val=read##size(card->iobase_mmio+off);			\
-	else								\
-		val=in##size(card->iobase+off);				\
-	val;								\
-})
-
-#define I810_IOREADL(card, off)		I810_IOREAD(l, u32, card, off)
-#define I810_IOREADW(card, off)		I810_IOREAD(w, u16, card, off)
-#define I810_IOREADB(card, off)		I810_IOREAD(b, u8,  card, off)
-
-#define I810_IOWRITE(size, val, card, off)				\
-({									\
-	if (card->use_mmio)						\
-		write##size(val, card->iobase_mmio+off);		\
-	else								\
-		out##size(val, card->iobase+off);			\
-})
-
-#define I810_IOWRITEL(val, card, off)	I810_IOWRITE(l, val, card, off)
-#define I810_IOWRITEW(val, card, off)	I810_IOWRITE(w, val, card, off)
-#define I810_IOWRITEB(val, card, off)	I810_IOWRITE(b, val, card, off)
-
-#define GET_CIV(card, port) MODULOP2(I810_IOREADB((card), (port) + OFF_CIV), SG_LEN)
-#define GET_LVI(card, port) MODULOP2(I810_IOREADB((card), (port) + OFF_LVI), SG_LEN)
-
-/* set LVI from CIV */
-#define CIV_TO_LVI(card, port, off) \
-	I810_IOWRITEB(MODULOP2(GET_CIV((card), (port)) + (off), SG_LEN), (card), (port) + OFF_LVI)
-
-static struct ac97_quirk ac97_quirks[] __devinitdata = {
-	{
-		.vendor = 0x0e11,
-		.device = 0x00b8,
-		.name = "Compaq Evo D510C",
-		.type = AC97_TUNE_HP_ONLY
-	},
-	{
-		.vendor = 0x1028,
-		.device = 0x00d8,
-		.name = "Dell Precision 530",   /* AD1885 */
-		.type = AC97_TUNE_HP_ONLY
-	},
-	{
-		.vendor = 0x1028,
-		.device = 0x0126,
-		.name = "Dell Optiplex GX260",  /* AD1981A */
-		.type = AC97_TUNE_HP_ONLY
-	},
-	{
-		.vendor = 0x1028,
-		.device = 0x012d,
-		.name = "Dell Precision 450",   /* AD1981B*/
-		.type = AC97_TUNE_HP_ONLY
-	},
-	{       /* FIXME: which codec? */
-		.vendor = 0x103c,
-		.device = 0x00c3,
-		.name = "Hewlett-Packard onboard",
-		.type = AC97_TUNE_HP_ONLY
-	},
-	{
-		.vendor = 0x103c,
-		.device = 0x12f1,
-		.name = "HP xw8200",    /* AD1981B*/
-		.type = AC97_TUNE_HP_ONLY
-	},
-	{
-		.vendor = 0x103c,
-		.device = 0x3008,
-		.name = "HP xw4200",    /* AD1981B*/
-		.type = AC97_TUNE_HP_ONLY
-	},
-	{
-		.vendor = 0x10f1,
-		.device = 0x2665,
-		.name = "Fujitsu-Siemens Celsius",      /* AD1981? */
-		.type = AC97_TUNE_HP_ONLY
-	},
-	{
-		.vendor = 0x10f1,
-		.device = 0x2885,
-		.name = "AMD64 Mobo",   /* ALC650 */
-		.type = AC97_TUNE_HP_ONLY
-	},
-	{
-		.vendor = 0x110a,
-		.device = 0x0056,
-		.name = "Fujitsu-Siemens Scenic",       /* AD1981? */
-		.type = AC97_TUNE_HP_ONLY
-	},
-	{
-		.vendor = 0x11d4,
-		.device = 0x5375,
-		.name = "ADI AD1985 (discrete)",
-		.type = AC97_TUNE_HP_ONLY
-	},
-	{
-		.vendor = 0x1462,
-		.device = 0x5470,
-		.name = "MSI P4 ATX 645 Ultra",
-		.type = AC97_TUNE_HP_ONLY
-	},
-	{
-		.vendor = 0x1734,
-		.device = 0x0088,
-		.name = "Fujitsu-Siemens D1522",	/* AD1981 */
-		.type = AC97_TUNE_HP_ONLY
-	},
-	{
-		.vendor = 0x8086,
-		.device = 0x4856,
-		.name = "Intel D845WN (82801BA)",
-		.type = AC97_TUNE_SWAP_HP
-	},
-	{
-		.vendor = 0x8086,
-		.device = 0x4d44,
-		.name = "Intel D850EMV2",       /* AD1885 */
-		.type = AC97_TUNE_HP_ONLY
-	},
-	{
-		.vendor = 0x8086,
-		.device = 0x4d56,
-		.name = "Intel ICH/AD1885",
-		.type = AC97_TUNE_HP_ONLY
-	},
-	{
-		.vendor = 0x1028,
-		.device = 0x012d,
-		.name = "Dell Precision 450",   /* AD1981B*/
-		.type = AC97_TUNE_HP_ONLY
-	},
-	{
-		.vendor = 0x103c,
-		.device = 0x3008,
-		.name = "HP xw4200",    /* AD1981B*/
-		.type = AC97_TUNE_HP_ONLY
-	},
-	{
-		.vendor = 0x103c,
-		.device = 0x12f1,
-		.name = "HP xw8200",    /* AD1981B*/
-		.type = AC97_TUNE_HP_ONLY
-	},
-	{ } /* terminator */
-};
-
-static struct i810_card *devs = NULL;
-
-static int i810_open_mixdev(struct inode *inode, struct file *file);
-static int i810_ioctl_mixdev(struct inode *inode, struct file *file,
-			     unsigned int cmd, unsigned long arg);
-static u16 i810_ac97_get(struct ac97_codec *dev, u8 reg);
-static void i810_ac97_set(struct ac97_codec *dev, u8 reg, u16 data);
-static u16 i810_ac97_get_mmio(struct ac97_codec *dev, u8 reg);
-static void i810_ac97_set_mmio(struct ac97_codec *dev, u8 reg, u16 data);
-static u16 i810_ac97_get_io(struct ac97_codec *dev, u8 reg);
-static void i810_ac97_set_io(struct ac97_codec *dev, u8 reg, u16 data);
-
-static struct i810_channel *i810_alloc_pcm_channel(struct i810_card *card)
-{
-	if(card->channel[1].used==1)
-		return NULL;
-	card->channel[1].used=1;
-	return &card->channel[1];
-}
-
-static struct i810_channel *i810_alloc_rec_pcm_channel(struct i810_card *card)
-{
-	if(card->channel[0].used==1)
-		return NULL;
-	card->channel[0].used=1;
-	return &card->channel[0];
-}
-
-static struct i810_channel *i810_alloc_rec_mic_channel(struct i810_card *card)
-{
-	if(card->channel[2].used==1)
-		return NULL;
-	card->channel[2].used=1;
-	return &card->channel[2];
-}
-
-static void i810_free_pcm_channel(struct i810_card *card, int channel)
-{
-	card->channel[channel].used=0;
-}
-
-static int i810_valid_spdif_rate ( struct ac97_codec *codec, int rate )
-{
-	unsigned long id = 0L;
-
-	id = (i810_ac97_get(codec, AC97_VENDOR_ID1) << 16);
-	id |= i810_ac97_get(codec, AC97_VENDOR_ID2) & 0xffff;
-#ifdef DEBUG
-	printk ( "i810_audio: codec = %s, codec_id = 0x%08lx\n", codec->name, id);
-#endif
-	switch ( id ) {
-		case 0x41445361: /* AD1886 */
-			if (rate == 48000) {
-				return 1;
-			}
-			break;
-		default: /* all other codecs, until we know otherwiae */
-			if (rate == 48000 || rate == 44100 || rate == 32000) {
-				return 1;
-			}
-			break;
-	}
-	return (0);
-}
-
-/* i810_set_spdif_output
- * 
- *  Configure the S/PDIF output transmitter. When we turn on
- *  S/PDIF, we turn off the analog output. This may not be
- *  the right thing to do.
- *
- *  Assumptions:
- *     The DSP sample rate must already be set to a supported
- *     S/PDIF rate (32kHz, 44.1kHz, or 48kHz) or we abort.
- */
-static int i810_set_spdif_output(struct i810_state *state, int slots, int rate)
-{
-	int	vol;
-	int	aud_reg;
-	int	r = 0;
-	struct ac97_codec *codec = state->card->ac97_codec[0];
-
-	if(!codec->codec_ops->digital) {
-		state->card->ac97_status &= ~SPDIF_ON;
-	} else {
-		if ( slots == -1 ) { /* Turn off S/PDIF */
-			codec->codec_ops->digital(codec, 0, 0, 0);
-			/* If the volume wasn't muted before we turned on S/PDIF, unmute it */
-			if ( !(state->card->ac97_status & VOL_MUTED) ) {
-				aud_reg = i810_ac97_get(codec, AC97_MASTER_VOL_STEREO);
-				i810_ac97_set(codec, AC97_MASTER_VOL_STEREO, (aud_reg & ~VOL_MUTED));
-			}
-			state->card->ac97_status &= ~(VOL_MUTED | SPDIF_ON);
-			return 0;
-		}
-
-		vol = i810_ac97_get(codec, AC97_MASTER_VOL_STEREO);
-		state->card->ac97_status = vol & VOL_MUTED;
-		
-		r = codec->codec_ops->digital(codec, slots, rate, 0);
-
-		if(r)
-			state->card->ac97_status |= SPDIF_ON;
-		else
-			state->card->ac97_status &= ~SPDIF_ON;
-
-		/* Mute the analog output */
-		/* Should this only mute the PCM volume??? */
-		i810_ac97_set(codec, AC97_MASTER_VOL_STEREO, (vol | VOL_MUTED));
-	}
-	return r;
-}
-
-/* i810_set_dac_channels
- *
- *  Configure the codec's multi-channel DACs
- *
- *  The logic is backwards. Setting the bit to 1 turns off the DAC. 
- *
- *  What about the ICH? We currently configure it using the
- *  SNDCTL_DSP_CHANNELS ioctl.  If we're turnning on the DAC, 
- *  does that imply that we want the ICH set to support
- *  these channels?
- *  
- *  TODO:
- *    vailidate that the codec really supports these DACs
- *    before turning them on. 
- */
-static void i810_set_dac_channels(struct i810_state *state, int channel)
-{
-	int	aud_reg;
-	struct ac97_codec *codec = state->card->ac97_codec[0];
-	
-	/* No codec, no setup */
-	
-	if(codec == NULL)
-		return;
-
-	aud_reg = i810_ac97_get(codec, AC97_EXTENDED_STATUS);
-	aud_reg |= AC97_EA_PRI | AC97_EA_PRJ | AC97_EA_PRK;
-	state->card->ac97_status &= ~(SURR_ON | CENTER_LFE_ON);
-
-	switch ( channel ) {
-		case 2: /* always enabled */
-			break;
-		case 4:
-			aud_reg &= ~AC97_EA_PRJ;
-			state->card->ac97_status |= SURR_ON;
-			break;
-		case 6:
-			aud_reg &= ~(AC97_EA_PRJ | AC97_EA_PRI | AC97_EA_PRK);
-			state->card->ac97_status |= SURR_ON | CENTER_LFE_ON;
-			break;
-		default:
-			break;
-	}
-	i810_ac97_set(codec, AC97_EXTENDED_STATUS, aud_reg);
-
-}
-
-
-/* set playback sample rate */
-static unsigned int i810_set_dac_rate(struct i810_state * state, unsigned int rate)
-{	
-	struct dmabuf *dmabuf = &state->dmabuf;
-	u32 new_rate;
-	struct ac97_codec *codec=state->card->ac97_codec[0];
-	
-	if(!(state->card->ac97_features&0x0001))
-	{
-		dmabuf->rate = clocking;
-#ifdef DEBUG
-		printk("Asked for %d Hz, but ac97_features says we only do %dHz.  Sorry!\n",
-		       rate,clocking);
-#endif		       
-		return clocking;
-	}
-			
-	if (rate > 48000)
-		rate = 48000;
-	if (rate < 8000)
-		rate = 8000;
-	dmabuf->rate = rate;
-		
-	/*
-	 *	Adjust for misclocked crap
-	 */
-	rate = ( rate * clocking)/48000;
-	if(strict_clocking && rate < 8000) {
-		rate = 8000;
-		dmabuf->rate = (rate * 48000)/clocking;
-	}
-
-        new_rate=ac97_set_dac_rate(codec, rate);
-	if(new_rate != rate) {
-		dmabuf->rate = (new_rate * 48000)/clocking;
-	}
-#ifdef DEBUG
-	printk("i810_audio: called i810_set_dac_rate : asked for %d, got %d\n", rate, dmabuf->rate);
-#endif
-	rate = new_rate;
-	return dmabuf->rate;
-}
-
-/* set recording sample rate */
-static unsigned int i810_set_adc_rate(struct i810_state * state, unsigned int rate)
-{
-	struct dmabuf *dmabuf = &state->dmabuf;
-	u32 new_rate;
-	struct ac97_codec *codec=state->card->ac97_codec[0];
-	
-	if(!(state->card->ac97_features&0x0001))
-	{
-		dmabuf->rate = clocking;
-		return clocking;
-	}
-			
-	if (rate > 48000)
-		rate = 48000;
-	if (rate < 8000)
-		rate = 8000;
-	dmabuf->rate = rate;
-
-	/*
-	 *	Adjust for misclocked crap
-	 */
-	 
-	rate = ( rate * clocking)/48000;
-	if(strict_clocking && rate < 8000) {
-		rate = 8000;
-		dmabuf->rate = (rate * 48000)/clocking;
-	}
-
-	new_rate = ac97_set_adc_rate(codec, rate);
-	
-	if(new_rate != rate) {
-		dmabuf->rate = (new_rate * 48000)/clocking;
-		rate = new_rate;
-	}
-#ifdef DEBUG
-	printk("i810_audio: called i810_set_adc_rate : rate = %d/%d\n", dmabuf->rate, rate);
-#endif
-	return dmabuf->rate;
-}
-
-/* get current playback/recording dma buffer pointer (byte offset from LBA),
-   called with spinlock held! */
-   
-static inline unsigned i810_get_dma_addr(struct i810_state *state, int rec)
-{
-	struct dmabuf *dmabuf = &state->dmabuf;
-	unsigned int civ, offset, port, port_picb, bytes = 2;
-	
-	if (!dmabuf->enable)
-		return 0;
-
-	if (rec)
-		port = dmabuf->read_channel->port;
-	else
-		port = dmabuf->write_channel->port;
-
-	if(state->card->pci_id == PCI_DEVICE_ID_SI_7012) {
-		port_picb = port + OFF_SR;
-		bytes = 1;
-	} else
-		port_picb = port + OFF_PICB;
-
-	do {
-		civ = GET_CIV(state->card, port);
-		offset = I810_IOREADW(state->card, port_picb);
-		/* Must have a delay here! */ 
-		if(offset == 0)
-			udelay(1);
-		/* Reread both registers and make sure that that total
-		 * offset from the first reading to the second is 0.
-		 * There is an issue with SiS hardware where it will count
-		 * picb down to 0, then update civ to the next value,
-		 * then set the new picb to fragsize bytes.  We can catch
-		 * it between the civ update and the picb update, making
-		 * it look as though we are 1 fragsize ahead of where we
-		 * are.  The next to we get the address though, it will
-		 * be back in the right place, and we will suddenly think
-		 * we just went forward dmasize - fragsize bytes, causing
-		 * totally stupid *huge* dma overrun messages.  We are
-		 * assuming that the 1us delay is more than long enough
-		 * that we won't have to worry about the chip still being
-		 * out of sync with reality ;-)
-		 */
-	} while (civ != GET_CIV(state->card, port) || offset != I810_IOREADW(state->card, port_picb));
-		 
-	return (((civ + 1) * dmabuf->fragsize - (bytes * offset))
-		% dmabuf->dmasize);
-}
-
-/* Stop recording (lock held) */
-static inline void __stop_adc(struct i810_state *state)
-{
-	struct dmabuf *dmabuf = &state->dmabuf;
-	struct i810_card *card = state->card;
-
-	dmabuf->enable &= ~ADC_RUNNING;
-	I810_IOWRITEB(0, card, PI_CR);
-	// wait for the card to acknowledge shutdown
-	while( I810_IOREADB(card, PI_CR) != 0 ) ;
-	// now clear any latent interrupt bits (like the halt bit)
-	if(card->pci_id == PCI_DEVICE_ID_SI_7012)
-		I810_IOWRITEB( I810_IOREADB(card, PI_PICB), card, PI_PICB );
-	else
-		I810_IOWRITEB( I810_IOREADB(card, PI_SR), card, PI_SR );
-	I810_IOWRITEL( I810_IOREADL(card, GLOB_STA) & INT_PI, card, GLOB_STA);
-}
-
-static void stop_adc(struct i810_state *state)
-{
-	struct i810_card *card = state->card;
-	unsigned long flags;
-
-	spin_lock_irqsave(&card->lock, flags);
-	__stop_adc(state);
-	spin_unlock_irqrestore(&card->lock, flags);
-}
-
-static inline void __start_adc(struct i810_state *state)
-{
-	struct dmabuf *dmabuf = &state->dmabuf;
-
-	if (dmabuf->count < dmabuf->dmasize && dmabuf->ready && !dmabuf->enable &&
-	    (dmabuf->trigger & PCM_ENABLE_INPUT)) {
-		dmabuf->enable |= ADC_RUNNING;
-		// Interrupt enable, LVI enable, DMA enable
-		I810_IOWRITEB(0x10 | 0x04 | 0x01, state->card, PI_CR);
-	}
-}
-
-static void start_adc(struct i810_state *state)
-{
-	struct i810_card *card = state->card;
-	unsigned long flags;
-
-	spin_lock_irqsave(&card->lock, flags);
-	__start_adc(state);
-	spin_unlock_irqrestore(&card->lock, flags);
-}
-
-/* stop playback (lock held) */
-static inline void __stop_dac(struct i810_state *state)
-{
-	struct dmabuf *dmabuf = &state->dmabuf;
-	struct i810_card *card = state->card;
-
-	dmabuf->enable &= ~DAC_RUNNING;
-	I810_IOWRITEB(0, card, PO_CR);
-	// wait for the card to acknowledge shutdown
-	while( I810_IOREADB(card, PO_CR) != 0 ) ;
-	// now clear any latent interrupt bits (like the halt bit)
-	if(card->pci_id == PCI_DEVICE_ID_SI_7012)
-		I810_IOWRITEB( I810_IOREADB(card, PO_PICB), card, PO_PICB );
-	else
-		I810_IOWRITEB( I810_IOREADB(card, PO_SR), card, PO_SR );
-	I810_IOWRITEL( I810_IOREADL(card, GLOB_STA) & INT_PO, card, GLOB_STA);
-}
-
-static void stop_dac(struct i810_state *state)
-{
-	struct i810_card *card = state->card;
-	unsigned long flags;
-
-	spin_lock_irqsave(&card->lock, flags);
-	__stop_dac(state);
-	spin_unlock_irqrestore(&card->lock, flags);
-}	
-
-static inline void __start_dac(struct i810_state *state)
-{
-	struct dmabuf *dmabuf = &state->dmabuf;
-
-	if (dmabuf->count > 0 && dmabuf->ready && !dmabuf->enable &&
-	    (dmabuf->trigger & PCM_ENABLE_OUTPUT)) {
-		dmabuf->enable |= DAC_RUNNING;
-		// Interrupt enable, LVI enable, DMA enable
-		I810_IOWRITEB(0x10 | 0x04 | 0x01, state->card, PO_CR);
-	}
-}
-static void start_dac(struct i810_state *state)
-{
-	struct i810_card *card = state->card;
-	unsigned long flags;
-
-	spin_lock_irqsave(&card->lock, flags);
-	__start_dac(state);
-	spin_unlock_irqrestore(&card->lock, flags);
-}
-
-#define DMABUF_DEFAULTORDER (16-PAGE_SHIFT)
-#define DMABUF_MINORDER 1
-
-/* allocate DMA buffer, playback and recording buffer should be allocated separately */
-static int alloc_dmabuf(struct i810_state *state)
-{
-	struct dmabuf *dmabuf = &state->dmabuf;
-	void *rawbuf= NULL;
-	int order, size;
-	struct page *page, *pend;
-
-	/* If we don't have any oss frag params, then use our default ones */
-	if(dmabuf->ossmaxfrags == 0)
-		dmabuf->ossmaxfrags = 4;
-	if(dmabuf->ossfragsize == 0)
-		dmabuf->ossfragsize = (PAGE_SIZE<<DMABUF_DEFAULTORDER)/dmabuf->ossmaxfrags;
-	size = dmabuf->ossfragsize * dmabuf->ossmaxfrags;
-
-	if(dmabuf->rawbuf && (PAGE_SIZE << dmabuf->buforder) == size)
-		return 0;
-	/* alloc enough to satisfy the oss params */
-	for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--) {
-		if ( (PAGE_SIZE<<order) > size )
-			continue;
-		if ((rawbuf = pci_alloc_consistent(state->card->pci_dev,
-						   PAGE_SIZE << order,
-						   &dmabuf->dma_handle)))
-			break;
-	}
-	if (!rawbuf)
-		return -ENOMEM;
-
-
-#ifdef DEBUG
-	printk("i810_audio: allocated %ld (order = %d) bytes at %p\n",
-	       PAGE_SIZE << order, order, rawbuf);
-#endif
-
-	dmabuf->ready  = dmabuf->mapped = 0;
-	dmabuf->rawbuf = rawbuf;
-	dmabuf->buforder = order;
-	
-	/* now mark the pages as reserved; otherwise remap_pfn_range doesn't do what we want */
-	pend = virt_to_page(rawbuf + (PAGE_SIZE << order) - 1);
-	for (page = virt_to_page(rawbuf); page <= pend; page++)
-		SetPageReserved(page);
-
-	return 0;
-}
-
-/* free DMA buffer */
-static void dealloc_dmabuf(struct i810_state *state)
-{
-	struct dmabuf *dmabuf = &state->dmabuf;
-	struct page *page, *pend;
-
-	if (dmabuf->rawbuf) {
-		/* undo marking the pages as reserved */
-		pend = virt_to_page(dmabuf->rawbuf + (PAGE_SIZE << dmabuf->buforder) - 1);
-		for (page = virt_to_page(dmabuf->rawbuf); page <= pend; page++)
-			ClearPageReserved(page);
-		pci_free_consistent(state->card->pci_dev, PAGE_SIZE << dmabuf->buforder,
-				    dmabuf->rawbuf, dmabuf->dma_handle);
-	}
-	dmabuf->rawbuf = NULL;
-	dmabuf->mapped = dmabuf->ready = 0;
-}
-
-static int prog_dmabuf(struct i810_state *state, unsigned rec)
-{
-	struct dmabuf *dmabuf = &state->dmabuf;
-	struct i810_channel *c;
-	struct sg_item *sg;
-	unsigned long flags;
-	int ret;
-	unsigned fragint;
-	int i;
-
-	spin_lock_irqsave(&state->card->lock, flags);
-	if(dmabuf->enable & DAC_RUNNING)
-		__stop_dac(state);
-	if(dmabuf->enable & ADC_RUNNING)
-		__stop_adc(state);
-	dmabuf->total_bytes = 0;
-	dmabuf->count = dmabuf->error = 0;
-	dmabuf->swptr = dmabuf->hwptr = 0;
-	spin_unlock_irqrestore(&state->card->lock, flags);
-
-	/* allocate DMA buffer, let alloc_dmabuf determine if we are already
-	 * allocated well enough or if we should replace the current buffer
-	 * (assuming one is already allocated, if it isn't, then allocate it).
-	 */
-	if ((ret = alloc_dmabuf(state)))
-		return ret;
-
-	/* FIXME: figure out all this OSS fragment stuff */
-	/* I did, it now does what it should according to the OSS API.  DL */
-	/* We may not have realloced our dmabuf, but the fragment size to
-	 * fragment number ratio may have changed, so go ahead and reprogram
-	 * things
-	 */
-	dmabuf->dmasize = PAGE_SIZE << dmabuf->buforder;
-	dmabuf->numfrag = SG_LEN;
-	dmabuf->fragsize = dmabuf->dmasize/dmabuf->numfrag;
-	dmabuf->fragsamples = dmabuf->fragsize >> 1;
-	dmabuf->fragshift = ffs(dmabuf->fragsize) - 1;
-	dmabuf->userfragsize = dmabuf->ossfragsize;
-	dmabuf->userfrags = dmabuf->dmasize/dmabuf->ossfragsize;
-
-	memset(dmabuf->rawbuf, 0, dmabuf->dmasize);
-
-	if(dmabuf->ossmaxfrags == 4) {
-		fragint = 8;
-	} else if (dmabuf->ossmaxfrags == 8) {
-		fragint = 4;
-	} else if (dmabuf->ossmaxfrags == 16) {
-		fragint = 2;
-	} else {
-		fragint = 1;
-	}
-	/*
-	 *	Now set up the ring 
-	 */
-	if(dmabuf->read_channel)
-		c = dmabuf->read_channel;
-	else
-		c = dmabuf->write_channel;
-	while(c != NULL) {
-		sg=&c->sg[0];
-		/*
-		 *	Load up 32 sg entries and take an interrupt at half
-		 *	way (we might want more interrupts later..) 
-		 */
-	  
-		for(i=0;i<dmabuf->numfrag;i++)
-		{
-			sg->busaddr=(u32)dmabuf->dma_handle+dmabuf->fragsize*i;
-			// the card will always be doing 16bit stereo
-			sg->control=dmabuf->fragsamples;
-			if(state->card->pci_id == PCI_DEVICE_ID_SI_7012)
-				sg->control <<= 1;
-			sg->control|=CON_BUFPAD;
-			// set us up to get IOC interrupts as often as needed to
-			// satisfy numfrag requirements, no more
-			if( ((i+1) % fragint) == 0) {
-				sg->control|=CON_IOC;
-			}
-			sg++;
-		}
-		spin_lock_irqsave(&state->card->lock, flags);
-		I810_IOWRITEB(2, state->card, c->port+OFF_CR);   /* reset DMA machine */
-		while( I810_IOREADB(state->card, c->port+OFF_CR) & 0x02 ) ;
-		I810_IOWRITEL((u32)state->card->chandma +
-		    c->num*sizeof(struct i810_channel),
-		    state->card, c->port+OFF_BDBAR);
-		CIV_TO_LVI(state->card, c->port, 0);
-
-		spin_unlock_irqrestore(&state->card->lock, flags);
-
-		if(c != dmabuf->write_channel)
-			c = dmabuf->write_channel;
-		else
-			c = NULL;
-	}
-	
-	/* set the ready flag for the dma buffer */
-	dmabuf->ready = 1;
-
-#ifdef DEBUG
-	printk("i810_audio: prog_dmabuf, sample rate = %d, format = %d,\n\tnumfrag = %d, "
-	       "fragsize = %d dmasize = %d\n",
-	       dmabuf->rate, dmabuf->fmt, dmabuf->numfrag,
-	       dmabuf->fragsize, dmabuf->dmasize);
-#endif
-
-	return 0;
-}
-
-static void __i810_update_lvi(struct i810_state *state, int rec)
-{
-	struct dmabuf *dmabuf = &state->dmabuf;
-	int x, port;
-	int trigger;
-	int count, fragsize;
-	void (*start)(struct i810_state *);
-
-	count = dmabuf->count;
-	if (rec) {
-		port = dmabuf->read_channel->port;
-		trigger = PCM_ENABLE_INPUT;
-		start = __start_adc;
-		count = dmabuf->dmasize - count;
-	} else {
-		port = dmabuf->write_channel->port;
-		trigger = PCM_ENABLE_OUTPUT;
-		start = __start_dac;
-	}
-
-	/* Do not process partial fragments. */
-	fragsize = dmabuf->fragsize;
-	if (count < fragsize)
-		return;
-
-	/* if we are currently stopped, then our CIV is actually set to our
-	 * *last* sg segment and we are ready to wrap to the next.  However,
-	 * if we set our LVI to the last sg segment, then it won't wrap to
-	 * the next sg segment, it won't even get a start.  So, instead, when
-	 * we are stopped, we set both the LVI value and also we increment
-	 * the CIV value to the next sg segment to be played so that when
-	 * we call start, things will operate properly.  Since the CIV can't
-	 * be written to directly for this purpose, we set the LVI to CIV + 1
-	 * temporarily.  Once the engine has started we set the LVI to its
-	 * final value.
-	 */
-	if (!dmabuf->enable && dmabuf->ready) {
-		if (!(dmabuf->trigger & trigger))
-			return;
-
-		CIV_TO_LVI(state->card, port, 1);
-
-		start(state);
-		while (!(I810_IOREADB(state->card, port + OFF_CR) & ((1<<4) | (1<<2))))
-			;
-	}
-
-	/* MASKP2(swptr, fragsize) - 1 is the tail of our transfer */
-	x = MODULOP2(MASKP2(dmabuf->swptr, fragsize) - 1, dmabuf->dmasize);
-	x >>= dmabuf->fragshift;
-	I810_IOWRITEB(x, state->card, port + OFF_LVI);
-}
-
-static void i810_update_lvi(struct i810_state *state, int rec)
-{
-	struct dmabuf *dmabuf = &state->dmabuf;
-	unsigned long flags;
-
-	if(!dmabuf->ready)
-		return;
-	spin_lock_irqsave(&state->card->lock, flags);
-	__i810_update_lvi(state, rec);
-	spin_unlock_irqrestore(&state->card->lock, flags);
-}
-
-/* update buffer manangement pointers, especially, dmabuf->count and dmabuf->hwptr */
-static void i810_update_ptr(struct i810_state *state)
-{
-	struct dmabuf *dmabuf = &state->dmabuf;
-	unsigned hwptr;
-	unsigned fragmask, dmamask;
-	int diff;
-
-	fragmask = MASKP2(~0, dmabuf->fragsize);
-	dmamask = MODULOP2(~0, dmabuf->dmasize);
-
-	/* error handling and process wake up for ADC */
-	if (dmabuf->enable == ADC_RUNNING) {
-		/* update hardware pointer */
-		hwptr = i810_get_dma_addr(state, 1) & fragmask;
-		diff = (hwptr - dmabuf->hwptr) & dmamask;
-#if defined(DEBUG_INTERRUPTS) || defined(DEBUG_MMAP)
-		printk("ADC HWP %d,%d,%d\n", hwptr, dmabuf->hwptr, diff);
-#endif
-		dmabuf->hwptr = hwptr;
-		dmabuf->total_bytes += diff;
-		dmabuf->count += diff;
-		if (dmabuf->count > dmabuf->dmasize) {
-			/* buffer underrun or buffer overrun */
-			/* this is normal for the end of a read */
-			/* only give an error if we went past the */
-			/* last valid sg entry */
-			if (GET_CIV(state->card, PI_BASE) !=
-			    GET_LVI(state->card, PI_BASE)) {
-				printk(KERN_WARNING "i810_audio: DMA overrun on read\n");
-				dmabuf->error++;
-			}
-		}
-		if (diff)
-			wake_up(&dmabuf->wait);
-	}
-	/* error handling and process wake up for DAC */
-	if (dmabuf->enable == DAC_RUNNING) {
-		/* update hardware pointer */
-		hwptr = i810_get_dma_addr(state, 0) & fragmask;
-		diff = (hwptr - dmabuf->hwptr) & dmamask;
-#if defined(DEBUG_INTERRUPTS) || defined(DEBUG_MMAP)
-		printk("DAC HWP %d,%d,%d\n", hwptr, dmabuf->hwptr, diff);
-#endif
-		dmabuf->hwptr = hwptr;
-		dmabuf->total_bytes += diff;
-		dmabuf->count -= diff;
-		if (dmabuf->count < 0) {
-			/* buffer underrun or buffer overrun */
-			/* this is normal for the end of a write */
-			/* only give an error if we went past the */
-			/* last valid sg entry */
-			if (GET_CIV(state->card, PO_BASE) !=
-			    GET_LVI(state->card, PO_BASE)) {
-				printk(KERN_WARNING "i810_audio: DMA overrun on write\n");
-				printk("i810_audio: CIV %d, LVI %d, hwptr %x, "
-					"count %d\n",
-					GET_CIV(state->card, PO_BASE),
-					GET_LVI(state->card, PO_BASE),
-					dmabuf->hwptr, dmabuf->count);
-				dmabuf->error++;
-			}
-		}
-		if (diff)
-			wake_up(&dmabuf->wait);
-	}
-}
-
-static inline int i810_get_free_write_space(struct i810_state *state)
-{
-	struct dmabuf *dmabuf = &state->dmabuf;
-	int free;
-
-	i810_update_ptr(state);
-	// catch underruns during playback
-	if (dmabuf->count < 0) {
-		dmabuf->count = 0;
-		dmabuf->swptr = dmabuf->hwptr;
-	}
-	free = dmabuf->dmasize - dmabuf->count;
-	if(free < 0)
-		return(0);
-	return(free);
-}
-
-static inline int i810_get_available_read_data(struct i810_state *state)
-{
-	struct dmabuf *dmabuf = &state->dmabuf;
-	int avail;
-
-	i810_update_ptr(state);
-	// catch overruns during record
-	if (dmabuf->count > dmabuf->dmasize) {
-		dmabuf->count = dmabuf->dmasize;
-		dmabuf->swptr = dmabuf->hwptr;
-	}
-	avail = dmabuf->count;
-	if(avail < 0)
-		return(0);
-	return(avail);
-}
-
-static inline void fill_partial_frag(struct dmabuf *dmabuf)
-{
-	unsigned fragsize;
-	unsigned swptr, len;
-
-	fragsize = dmabuf->fragsize;
-	swptr = dmabuf->swptr;
-	len = fragsize - MODULOP2(dmabuf->swptr, fragsize);
-	if (len == fragsize)
-		return;
-
-	memset(dmabuf->rawbuf + swptr, '\0', len);
-	dmabuf->swptr = MODULOP2(swptr + len, dmabuf->dmasize);
-	dmabuf->count += len;
-}
-
-static int drain_dac(struct i810_state *state, int signals_allowed)
-{
-	DECLARE_WAITQUEUE(wait, current);
-	struct dmabuf *dmabuf = &state->dmabuf;
-	unsigned long flags;
-	unsigned long tmo;
-	int count;
-
-	if (!dmabuf->ready)
-		return 0;
-	if(dmabuf->mapped) {
-		stop_dac(state);
-		return 0;
-	}
-
-	spin_lock_irqsave(&state->card->lock, flags);
-
-	fill_partial_frag(dmabuf);
-
-	/* 
-	 * This will make sure that our LVI is correct, that our
-	 * pointer is updated, and that the DAC is running.  We
-	 * have to force the setting of dmabuf->trigger to avoid
-	 * any possible deadlocks.
-	 */
-	dmabuf->trigger = PCM_ENABLE_OUTPUT;
-	__i810_update_lvi(state, 0);
-
-	spin_unlock_irqrestore(&state->card->lock, flags);
-
-	add_wait_queue(&dmabuf->wait, &wait);
-	for (;;) {
-
-		spin_lock_irqsave(&state->card->lock, flags);
-		i810_update_ptr(state);
-		count = dmabuf->count;
-
-		/* It seems that we have to set the current state to
-		 * TASK_INTERRUPTIBLE every time to make the process
-		 * really go to sleep.  This also has to be *after* the
-		 * update_ptr() call because update_ptr is likely to
-		 * do a wake_up() which will unset this before we ever
-		 * try to sleep, resuling in a tight loop in this code
-		 * instead of actually sleeping and waiting for an
-		 * interrupt to wake us up!
-		 */
-		__set_current_state(signals_allowed ?
-				    TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
-		spin_unlock_irqrestore(&state->card->lock, flags);
-
-		if (count <= 0)
-			break;
-
-                if (signal_pending(current) && signals_allowed) {
-                        break;
-                }
-
-		/*
-		 * set the timeout to significantly longer than it *should*
-		 * take for the DAC to drain the DMA buffer
-		 */
-		tmo = (count * HZ) / (dmabuf->rate);
-		if (!schedule_timeout(tmo >= 2 ? tmo : 2)){
-			printk(KERN_ERR "i810_audio: drain_dac, dma timeout?\n");
-			count = 0;
-			break;
-		}
-	}
-	set_current_state(TASK_RUNNING);
-	remove_wait_queue(&dmabuf->wait, &wait);
-	if(count > 0 && signal_pending(current) && signals_allowed)
-		return -ERESTARTSYS;
-	stop_dac(state);
-	return 0;
-}
-
-static void i810_channel_interrupt(struct i810_card *card)
-{
-	int i, count;
-	
-#ifdef DEBUG_INTERRUPTS
-	printk("CHANNEL ");
-#endif
-	for(i=0;i<NR_HW_CH;i++)
-	{
-		struct i810_state *state = card->states[i];
-		struct i810_channel *c;
-		struct dmabuf *dmabuf;
-		unsigned long port;
-		u16 status;
-		
-		if(!state)
-			continue;
-		if(!state->dmabuf.ready)
-			continue;
-		dmabuf = &state->dmabuf;
-		if(dmabuf->enable & DAC_RUNNING) {
-			c=dmabuf->write_channel;
-		} else if(dmabuf->enable & ADC_RUNNING) {
-			c=dmabuf->read_channel;
-		} else	/* This can occur going from R/W to close */
-			continue;
-		
-		port = c->port;
-
-		if(card->pci_id == PCI_DEVICE_ID_SI_7012)
-			status = I810_IOREADW(card, port + OFF_PICB);
-		else
-			status = I810_IOREADW(card, port + OFF_SR);
-
-#ifdef DEBUG_INTERRUPTS
-		printk("NUM %d PORT %X IRQ ( ST%d ", c->num, c->port, status);
-#endif
-		if(status & DMA_INT_COMPLETE)
-		{
-			/* only wake_up() waiters if this interrupt signals
-			 * us being beyond a userfragsize of data open or
-			 * available, and i810_update_ptr() does that for
-			 * us
-			 */
-			i810_update_ptr(state);
-#ifdef DEBUG_INTERRUPTS
-			printk("COMP %d ", dmabuf->hwptr /
-					dmabuf->fragsize);
-#endif
-		}
-		if(status & (DMA_INT_LVI | DMA_INT_DCH))
-		{
-			/* wake_up() unconditionally on LVI and DCH */
-			i810_update_ptr(state);
-			wake_up(&dmabuf->wait);
-#ifdef DEBUG_INTERRUPTS
-			if(status & DMA_INT_LVI)
-				printk("LVI ");
-			if(status & DMA_INT_DCH)
-				printk("DCH -");
-#endif
-			count = dmabuf->count;
-			if(dmabuf->enable & ADC_RUNNING)
-				count = dmabuf->dmasize - count;
-			if (count >= (int)dmabuf->fragsize) {
-				I810_IOWRITEB(I810_IOREADB(card, port+OFF_CR) | 1, card, port+OFF_CR);
-#ifdef DEBUG_INTERRUPTS
-				printk(" CONTINUE ");
-#endif
-			} else {
-				if (dmabuf->enable & DAC_RUNNING)
-					__stop_dac(state);
-				if (dmabuf->enable & ADC_RUNNING)
-					__stop_adc(state);
-				dmabuf->enable = 0;
-#ifdef DEBUG_INTERRUPTS
-				printk(" STOP ");
-#endif
-			}
-		}
-		if(card->pci_id == PCI_DEVICE_ID_SI_7012)
-			I810_IOWRITEW(status & DMA_INT_MASK, card, port + OFF_PICB);
-		else
-			I810_IOWRITEW(status & DMA_INT_MASK, card, port + OFF_SR);
-	}
-#ifdef DEBUG_INTERRUPTS
-	printk(")\n");
-#endif
-}
-
-static irqreturn_t i810_interrupt(int irq, void *dev_id)
-{
-	struct i810_card *card = dev_id;
-	u32 status;
-
-	spin_lock(&card->lock);
-
-	status = I810_IOREADL(card, GLOB_STA);
-
-	if(!(status & INT_MASK)) 
-	{
-		spin_unlock(&card->lock);
-		return IRQ_NONE;  /* not for us */
-	}
-
-	if(status & (INT_PO|INT_PI|INT_MC))
-		i810_channel_interrupt(card);
-
- 	/* clear 'em */
-	I810_IOWRITEL(status & INT_MASK, card, GLOB_STA);
-	spin_unlock(&card->lock);
-	return IRQ_HANDLED;
-}
-
-/* in this loop, dmabuf.count signifies the amount of data that is
-   waiting to be copied to the user's buffer.  It is filled by the dma
-   machine and drained by this loop. */
-
-static ssize_t i810_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
-{
-	struct i810_state *state = (struct i810_state *)file->private_data;
-	struct i810_card *card=state ? state->card : NULL;
-	struct dmabuf *dmabuf = &state->dmabuf;
-	ssize_t ret;
-	unsigned long flags;
-	unsigned int swptr;
-	int cnt;
-	int pending;
-        DECLARE_WAITQUEUE(waita, current);
-
-#ifdef DEBUG2
-	printk("i810_audio: i810_read called, count = %d\n", count);
-#endif
-
-	if (dmabuf->mapped)
-		return -ENXIO;
-	if (dmabuf->enable & DAC_RUNNING)
-		return -ENODEV;
-	if (!dmabuf->read_channel) {
-		dmabuf->ready = 0;
-		dmabuf->read_channel = card->alloc_rec_pcm_channel(card);
-		if (!dmabuf->read_channel) {
-			return -EBUSY;
-		}
-	}
-	if (!dmabuf->ready && (ret = prog_dmabuf(state, 1)))
-		return ret;
-	if (!access_ok(VERIFY_WRITE, buffer, count))
-		return -EFAULT;
-	ret = 0;
-
-	pending = 0;
-
-        add_wait_queue(&dmabuf->wait, &waita);
-	while (count > 0) {
-		set_current_state(TASK_INTERRUPTIBLE);
-		spin_lock_irqsave(&card->lock, flags);
-                if (PM_SUSPENDED(card)) {
-                        spin_unlock_irqrestore(&card->lock, flags);
-                        schedule();
-                        if (signal_pending(current)) {
-                                if (!ret) ret = -EAGAIN;
-                                break;
-                        }
-                        continue;
-                }
-		cnt = i810_get_available_read_data(state);
-		swptr = dmabuf->swptr;
-		// this is to make the copy_to_user simpler below
-		if(cnt > (dmabuf->dmasize - swptr))
-			cnt = dmabuf->dmasize - swptr;
-		spin_unlock_irqrestore(&card->lock, flags);
-
-		if (cnt > count)
-			cnt = count;
-		if (cnt <= 0) {
-			unsigned long tmo;
-			/*
-			 * Don't let us deadlock.  The ADC won't start if
-			 * dmabuf->trigger isn't set.  A call to SETTRIGGER
-			 * could have turned it off after we set it to on
-			 * previously.
-			 */
-			dmabuf->trigger = PCM_ENABLE_INPUT;
-			/*
-			 * This does three things.  Updates LVI to be correct,
-			 * makes sure the ADC is running, and updates the
-			 * hwptr.
-			 */
-			i810_update_lvi(state,1);
-			if (file->f_flags & O_NONBLOCK) {
-				if (!ret) ret = -EAGAIN;
-				goto done;
-			}
-			/* Set the timeout to how long it would take to fill
-			 * two of our buffers.  If we haven't been woke up
-			 * by then, then we know something is wrong.
-			 */
-			tmo = (dmabuf->dmasize * HZ * 2) / (dmabuf->rate * 4);
-			/* There are two situations when sleep_on_timeout returns, one is when
-			   the interrupt is serviced correctly and the process is waked up by
-			   ISR ON TIME. Another is when timeout is expired, which means that
-			   either interrupt is NOT serviced correctly (pending interrupt) or it
-			   is TOO LATE for the process to be scheduled to run (scheduler latency)
-			   which results in a (potential) buffer overrun. And worse, there is
-			   NOTHING we can do to prevent it. */
-			if (!schedule_timeout(tmo >= 2 ? tmo : 2)) {
-#ifdef DEBUG
-				printk(KERN_ERR "i810_audio: recording schedule timeout, "
-				       "dmasz %u fragsz %u count %i hwptr %u swptr %u\n",
-				       dmabuf->dmasize, dmabuf->fragsize, dmabuf->count,
-				       dmabuf->hwptr, dmabuf->swptr);
-#endif
-				/* a buffer overrun, we delay the recovery until next time the
-				   while loop begin and we REALLY have space to record */
-			}
-			if (signal_pending(current)) {
-				ret = ret ? ret : -ERESTARTSYS;
-				goto done;
-			}
-			continue;
-		}
-
-		if (copy_to_user(buffer, dmabuf->rawbuf + swptr, cnt)) {
-			if (!ret) ret = -EFAULT;
-			goto done;
-		}
-
-		swptr = MODULOP2(swptr + cnt, dmabuf->dmasize);
-
-		spin_lock_irqsave(&card->lock, flags);
-
-                if (PM_SUSPENDED(card)) {
-                        spin_unlock_irqrestore(&card->lock, flags);
-                        continue;
-                }
-		dmabuf->swptr = swptr;
-		pending = dmabuf->count -= cnt;
-		spin_unlock_irqrestore(&card->lock, flags);
-
-		count -= cnt;
-		buffer += cnt;
-		ret += cnt;
-	}
- done:
-	pending = dmabuf->dmasize - pending;
-	if (dmabuf->enable || pending >= dmabuf->userfragsize)
-		i810_update_lvi(state, 1);
-        set_current_state(TASK_RUNNING);
-        remove_wait_queue(&dmabuf->wait, &waita);
-
-	return ret;
-}
-
-/* in this loop, dmabuf.count signifies the amount of data that is waiting to be dma to
-   the soundcard.  it is drained by the dma machine and filled by this loop. */
-static ssize_t i810_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
-{
-	struct i810_state *state = (struct i810_state *)file->private_data;
-	struct i810_card *card=state ? state->card : NULL;
-	struct dmabuf *dmabuf = &state->dmabuf;
-	ssize_t ret;
-	unsigned long flags;
-	unsigned int swptr = 0;
-	int pending;
-	int cnt;
-        DECLARE_WAITQUEUE(waita, current);
-
-#ifdef DEBUG2
-	printk("i810_audio: i810_write called, count = %d\n", count);
-#endif
-
-	if (dmabuf->mapped)
-		return -ENXIO;
-	if (dmabuf->enable & ADC_RUNNING)
-		return -ENODEV;
-	if (!dmabuf->write_channel) {
-		dmabuf->ready = 0;
-		dmabuf->write_channel = card->alloc_pcm_channel(card);
-		if(!dmabuf->write_channel)
-			return -EBUSY;
-	}
-	if (!dmabuf->ready && (ret = prog_dmabuf(state, 0)))
-		return ret;
-	if (!access_ok(VERIFY_READ, buffer, count))
-		return -EFAULT;
-	ret = 0;
-
-	pending = 0;
-
-        add_wait_queue(&dmabuf->wait, &waita);
-	while (count > 0) {
-		set_current_state(TASK_INTERRUPTIBLE);
-		spin_lock_irqsave(&state->card->lock, flags);
-                if (PM_SUSPENDED(card)) {
-                        spin_unlock_irqrestore(&card->lock, flags);
-                        schedule();
-                        if (signal_pending(current)) {
-                                if (!ret) ret = -EAGAIN;
-                                break;
-                        }
-                        continue;
-                }
-
-		cnt = i810_get_free_write_space(state);
-		swptr = dmabuf->swptr;
-		/* Bound the maximum size to how much we can copy to the
-		 * dma buffer before we hit the end.  If we have more to
-		 * copy then it will get done in a second pass of this
-		 * loop starting from the beginning of the buffer.
-		 */
-		if(cnt > (dmabuf->dmasize - swptr))
-			cnt = dmabuf->dmasize - swptr;
-		spin_unlock_irqrestore(&state->card->lock, flags);
-
-#ifdef DEBUG2
-		printk(KERN_INFO "i810_audio: i810_write: %d bytes available space\n", cnt);
-#endif
-		if (cnt > count)
-			cnt = count;
-		if (cnt <= 0) {
-			unsigned long tmo;
-			// There is data waiting to be played
-			/*
-			 * Force the trigger setting since we would
-			 * deadlock with it set any other way
-			 */
-			dmabuf->trigger = PCM_ENABLE_OUTPUT;
-			i810_update_lvi(state,0);
-			if (file->f_flags & O_NONBLOCK) {
-				if (!ret) ret = -EAGAIN;
-				goto ret;
-			}
-			/* Not strictly correct but works */
-			tmo = (dmabuf->dmasize * HZ * 2) / (dmabuf->rate * 4);
-			/* There are two situations when sleep_on_timeout returns, one is when
-			   the interrupt is serviced correctly and the process is waked up by
-			   ISR ON TIME. Another is when timeout is expired, which means that
-			   either interrupt is NOT serviced correctly (pending interrupt) or it
-			   is TOO LATE for the process to be scheduled to run (scheduler latency)
-			   which results in a (potential) buffer underrun. And worse, there is
-			   NOTHING we can do to prevent it. */
-			if (!schedule_timeout(tmo >= 2 ? tmo : 2)) {
-#ifdef DEBUG
-				printk(KERN_ERR "i810_audio: playback schedule timeout, "
-				       "dmasz %u fragsz %u count %i hwptr %u swptr %u\n",
-				       dmabuf->dmasize, dmabuf->fragsize, dmabuf->count,
-				       dmabuf->hwptr, dmabuf->swptr);
-#endif
-				/* a buffer underrun, we delay the recovery until next time the
-				   while loop begin and we REALLY have data to play */
-				//return ret;
-			}
-			if (signal_pending(current)) {
-				if (!ret) ret = -ERESTARTSYS;
-				goto ret;
-			}
-			continue;
-		}
-		if (copy_from_user(dmabuf->rawbuf+swptr,buffer,cnt)) {
-			if (!ret) ret = -EFAULT;
-			goto ret;
-		}
-
-		swptr = MODULOP2(swptr + cnt, dmabuf->dmasize);
-
-		spin_lock_irqsave(&state->card->lock, flags);
-                if (PM_SUSPENDED(card)) {
-                        spin_unlock_irqrestore(&card->lock, flags);
-                        continue;
-                }
-
-		dmabuf->swptr = swptr;
-		pending = dmabuf->count += cnt;
-
-		count -= cnt;
-		buffer += cnt;
-		ret += cnt;
-		spin_unlock_irqrestore(&state->card->lock, flags);
-	}
-ret:
-	if (dmabuf->enable || pending >= dmabuf->userfragsize)
-		i810_update_lvi(state, 0);
-        set_current_state(TASK_RUNNING);
-        remove_wait_queue(&dmabuf->wait, &waita);
-
-	return ret;
-}
-
-/* No kernel lock - we have our own spinlock */
-static unsigned int i810_poll(struct file *file, struct poll_table_struct *wait)
-{
-	struct i810_state *state = (struct i810_state *)file->private_data;
-	struct dmabuf *dmabuf = &state->dmabuf;
-	unsigned long flags;
-	unsigned int mask = 0;
-
-	if(!dmabuf->ready)
-		return 0;
-	poll_wait(file, &dmabuf->wait, wait);
-	spin_lock_irqsave(&state->card->lock, flags);
-	if (dmabuf->enable & ADC_RUNNING ||
-	    dmabuf->trigger & PCM_ENABLE_INPUT) {
-		if (i810_get_available_read_data(state) >= 
-		    (signed)dmabuf->userfragsize)
-			mask |= POLLIN | POLLRDNORM;
-	}
-	if (dmabuf->enable & DAC_RUNNING ||
-	    dmabuf->trigger & PCM_ENABLE_OUTPUT) {
-		if (i810_get_free_write_space(state) >=
-		    (signed)dmabuf->userfragsize)
-			mask |= POLLOUT | POLLWRNORM;
-	}
-	spin_unlock_irqrestore(&state->card->lock, flags);
-	return mask;
-}
-
-static int i810_mmap(struct file *file, struct vm_area_struct *vma)
-{
-	struct i810_state *state = (struct i810_state *)file->private_data;
-	struct dmabuf *dmabuf = &state->dmabuf;
-	int ret = -EINVAL;
-	unsigned long size;
-
-	lock_kernel();
-	if (vma->vm_flags & VM_WRITE) {
-		if (!dmabuf->write_channel &&
-		    (dmabuf->write_channel =
-		     state->card->alloc_pcm_channel(state->card)) == NULL) {
-			ret = -EBUSY;
-			goto out;
-		}
-	}
-	if (vma->vm_flags & VM_READ) {
-		if (!dmabuf->read_channel &&
-		    (dmabuf->read_channel = 
-		     state->card->alloc_rec_pcm_channel(state->card)) == NULL) {
-			ret = -EBUSY;
-			goto out;
-		}
-	}
-	if ((ret = prog_dmabuf(state, 0)) != 0)
-		goto out;
-
-	ret = -EINVAL;
-	if (vma->vm_pgoff != 0)
-		goto out;
-	size = vma->vm_end - vma->vm_start;
-	if (size > (PAGE_SIZE << dmabuf->buforder))
-		goto out;
-	ret = -EAGAIN;
-	if (remap_pfn_range(vma, vma->vm_start,
-			     virt_to_phys(dmabuf->rawbuf) >> PAGE_SHIFT,
-			     size, vma->vm_page_prot))
-		goto out;
-	dmabuf->mapped = 1;
-	dmabuf->trigger = 0;
-	ret = 0;
-#ifdef DEBUG_MMAP
-	printk("i810_audio: mmap'ed %ld bytes of data space\n", size);
-#endif
-out:
-	unlock_kernel();
-	return ret;
-}
-
-static int i810_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
-	struct i810_state *state = (struct i810_state *)file->private_data;
-	struct i810_channel *c = NULL;
-	struct dmabuf *dmabuf = &state->dmabuf;
-	unsigned long flags;
-	audio_buf_info abinfo;
-	count_info cinfo;
-	unsigned int i_glob_cnt;
-	int val = 0, ret;
-	struct ac97_codec *codec = state->card->ac97_codec[0];
-	void __user *argp = (void __user *)arg;
-	int __user *p = argp;
-
-#ifdef DEBUG
-	printk("i810_audio: i810_ioctl, arg=0x%x, cmd=", arg ? *p : 0);
-#endif
-
-	switch (cmd) 
-	{
-	case OSS_GETVERSION:
-#ifdef DEBUG
-		printk("OSS_GETVERSION\n");
-#endif
-		return put_user(SOUND_VERSION, p);
-
-	case SNDCTL_DSP_RESET:
-#ifdef DEBUG
-		printk("SNDCTL_DSP_RESET\n");
-#endif
-		spin_lock_irqsave(&state->card->lock, flags);
-		if (dmabuf->enable == DAC_RUNNING) {
-			c = dmabuf->write_channel;
-			__stop_dac(state);
-		}
-		if (dmabuf->enable == ADC_RUNNING) {
-			c = dmabuf->read_channel;
-			__stop_adc(state);
-		}
-		if (c != NULL) {
-			I810_IOWRITEB(2, state->card, c->port+OFF_CR);   /* reset DMA machine */
-			while ( I810_IOREADB(state->card, c->port+OFF_CR) & 2 )
-				cpu_relax();
-			I810_IOWRITEL((u32)state->card->chandma +
-			    c->num*sizeof(struct i810_channel),
-			    state->card, c->port+OFF_BDBAR);
-			CIV_TO_LVI(state->card, c->port, 0);
-		}
-
-		spin_unlock_irqrestore(&state->card->lock, flags);
-		synchronize_irq(state->card->pci_dev->irq);
-		dmabuf->ready = 0;
-		dmabuf->swptr = dmabuf->hwptr = 0;
-		dmabuf->count = dmabuf->total_bytes = 0;
-		return 0;
-
-	case SNDCTL_DSP_SYNC:
-#ifdef DEBUG
-		printk("SNDCTL_DSP_SYNC\n");
-#endif
-		if (dmabuf->enable != DAC_RUNNING || file->f_flags & O_NONBLOCK)
-			return 0;
-		if((val = drain_dac(state, 1)))
-			return val;
-		dmabuf->total_bytes = 0;
-		return 0;
-
-	case SNDCTL_DSP_SPEED: /* set smaple rate */
-#ifdef DEBUG
-		printk("SNDCTL_DSP_SPEED\n");
-#endif
-		if (get_user(val, p))
-			return -EFAULT;
-		if (val >= 0) {
-			if (file->f_mode & FMODE_WRITE) {
-				if ( (state->card->ac97_status & SPDIF_ON) ) {  /* S/PDIF Enabled */
-					/* AD1886 only supports 48000, need to check that */
-					if ( i810_valid_spdif_rate ( codec, val ) ) {
-						/* Set DAC rate */
-                                        	i810_set_spdif_output ( state, -1, 0 );
-						stop_dac(state);
-						dmabuf->ready = 0;
-						spin_lock_irqsave(&state->card->lock, flags);
-						i810_set_dac_rate(state, val);
-						spin_unlock_irqrestore(&state->card->lock, flags);
-						/* Set S/PDIF transmitter rate. */
-						i810_set_spdif_output ( state, AC97_EA_SPSA_3_4, val );
-	                                        if ( ! (state->card->ac97_status & SPDIF_ON) ) {
-							val = dmabuf->rate;
-						}
-					} else { /* Not a valid rate for S/PDIF, ignore it */
-						val = dmabuf->rate;
-					}
-				} else {
-					stop_dac(state);
-					dmabuf->ready = 0;
-					spin_lock_irqsave(&state->card->lock, flags);
-					i810_set_dac_rate(state, val);
-					spin_unlock_irqrestore(&state->card->lock, flags);
-				}
-			}
-			if (file->f_mode & FMODE_READ) {
-				stop_adc(state);
-				dmabuf->ready = 0;
-				spin_lock_irqsave(&state->card->lock, flags);
-				i810_set_adc_rate(state, val);
-				spin_unlock_irqrestore(&state->card->lock, flags);
-			}
-		}
-		return put_user(dmabuf->rate, p);
-
-	case SNDCTL_DSP_STEREO: /* set stereo or mono channel */
-#ifdef DEBUG
-		printk("SNDCTL_DSP_STEREO\n");
-#endif
-		if (dmabuf->enable & DAC_RUNNING) {
-			stop_dac(state);
-		}
-		if (dmabuf->enable & ADC_RUNNING) {
-			stop_adc(state);
-		}
-		return put_user(1, p);
-
-	case SNDCTL_DSP_GETBLKSIZE:
-		if (file->f_mode & FMODE_WRITE) {
-			if (!dmabuf->ready && (val = prog_dmabuf(state, 0)))
-				return val;
-		}
-		if (file->f_mode & FMODE_READ) {
-			if (!dmabuf->ready && (val = prog_dmabuf(state, 1)))
-				return val;
-		}
-#ifdef DEBUG
-		printk("SNDCTL_DSP_GETBLKSIZE %d\n", dmabuf->userfragsize);
-#endif
-		return put_user(dmabuf->userfragsize, p);
-
-	case SNDCTL_DSP_GETFMTS: /* Returns a mask of supported sample format*/
-#ifdef DEBUG
-		printk("SNDCTL_DSP_GETFMTS\n");
-#endif
-		return put_user(AFMT_S16_LE, p);
-
-	case SNDCTL_DSP_SETFMT: /* Select sample format */
-#ifdef DEBUG
-		printk("SNDCTL_DSP_SETFMT\n");
-#endif
-		return put_user(AFMT_S16_LE, p);
-
-	case SNDCTL_DSP_CHANNELS:
-#ifdef DEBUG
-		printk("SNDCTL_DSP_CHANNELS\n");
-#endif
-		if (get_user(val, p))
-			return -EFAULT;
-
-		if (val > 0) {
-			if (dmabuf->enable & DAC_RUNNING) {
-				stop_dac(state);
-			}
-			if (dmabuf->enable & ADC_RUNNING) {
-				stop_adc(state);
-			}
-		} else {
-			return put_user(state->card->channels, p);
-		}
-
-		/* ICH and ICH0 only support 2 channels */
-		if ( state->card->pci_id == PCI_DEVICE_ID_INTEL_82801AA_5
-		     || state->card->pci_id == PCI_DEVICE_ID_INTEL_82801AB_5) 
-			return put_user(2, p);
-	
-		/* Multi-channel support was added with ICH2. Bits in */
-		/* Global Status and Global Control register are now  */
-		/* used to indicate this.                             */
-
-                i_glob_cnt = I810_IOREADL(state->card, GLOB_CNT);
-
-		/* Current # of channels enabled */
-		if ( i_glob_cnt & 0x0100000 )
-			ret = 4;
-		else if ( i_glob_cnt & 0x0200000 )
-			ret = 6;
-		else
-			ret = 2;
-
-		switch ( val ) {
-			case 2: /* 2 channels is always supported */
-				I810_IOWRITEL(i_glob_cnt & 0xffcfffff,
-				     state->card, GLOB_CNT);
-				/* Do we need to change mixer settings????  */
-				break;
-			case 4: /* Supported on some chipsets, better check first */
-				if ( state->card->channels >= 4 ) {
-					I810_IOWRITEL((i_glob_cnt & 0xffcfffff) | 0x100000,
-					      state->card, GLOB_CNT);
-					/* Do we need to change mixer settings??? */
-				} else {
-					val = ret;
-				}
-				break;
-			case 6: /* Supported on some chipsets, better check first */
-				if ( state->card->channels >= 6 ) {
-					I810_IOWRITEL((i_glob_cnt & 0xffcfffff) | 0x200000,
-					      state->card, GLOB_CNT);
-					/* Do we need to change mixer settings??? */
-				} else {
-					val = ret;
-				}
-				break;
-			default: /* nothing else is ever supported by the chipset */
-				val = ret;
-				break;
-		}
-
-		return put_user(val, p);
-
-	case SNDCTL_DSP_POST: /* the user has sent all data and is notifying us */
-		/* we update the swptr to the end of the last sg segment then return */
-#ifdef DEBUG
-		printk("SNDCTL_DSP_POST\n");
-#endif
-		if(!dmabuf->ready || (dmabuf->enable != DAC_RUNNING))
-			return 0;
-		if((dmabuf->swptr % dmabuf->fragsize) != 0) {
-			val = dmabuf->fragsize - (dmabuf->swptr % dmabuf->fragsize);
-			dmabuf->swptr += val;
-			dmabuf->count += val;
-		}
-		return 0;
-
-	case SNDCTL_DSP_SUBDIVIDE:
-		if (dmabuf->subdivision)
-			return -EINVAL;
-		if (get_user(val, p))
-			return -EFAULT;
-		if (val != 1 && val != 2 && val != 4)
-			return -EINVAL;
-#ifdef DEBUG
-		printk("SNDCTL_DSP_SUBDIVIDE %d\n", val);
-#endif
-		dmabuf->subdivision = val;
-		dmabuf->ready = 0;
-		return 0;
-
-	case SNDCTL_DSP_SETFRAGMENT:
-		if (get_user(val, p))
-			return -EFAULT;
-
-		dmabuf->ossfragsize = 1<<(val & 0xffff);
-		dmabuf->ossmaxfrags = (val >> 16) & 0xffff;
-		if (!dmabuf->ossfragsize || !dmabuf->ossmaxfrags)
-			return -EINVAL;
-		/*
-		 * Bound the frag size into our allowed range of 256 - 4096
-		 */
-		if (dmabuf->ossfragsize < 256)
-			dmabuf->ossfragsize = 256;
-		else if (dmabuf->ossfragsize > 4096)
-			dmabuf->ossfragsize = 4096;
-		/*
-		 * The numfrags could be something reasonable, or it could
-		 * be 0xffff meaning "Give me as much as possible".  So,
-		 * we check the numfrags * fragsize doesn't exceed our
-		 * 64k buffer limit, nor is it less than our 8k minimum.
-		 * If it fails either one of these checks, then adjust the
-		 * number of fragments, not the size of them.  It's OK if
-		 * our number of fragments doesn't equal 32 or anything
-		 * like our hardware based number now since we are using
-		 * a different frag count for the hardware.  Before we get
-		 * into this though, bound the maxfrags to avoid overflow
-		 * issues.  A reasonable bound would be 64k / 256 since our
-		 * maximum buffer size is 64k and our minimum frag size is
-		 * 256.  On the other end, our minimum buffer size is 8k and
-		 * our maximum frag size is 4k, so the lower bound should
-		 * be 2.
-		 */
-
-		if(dmabuf->ossmaxfrags > 256)
-			dmabuf->ossmaxfrags = 256;
-		else if (dmabuf->ossmaxfrags < 2)
-			dmabuf->ossmaxfrags = 2;
-
-		val = dmabuf->ossfragsize * dmabuf->ossmaxfrags;
-		while (val < 8192) {
-		    val <<= 1;
-		    dmabuf->ossmaxfrags <<= 1;
-		}
-		while (val > 65536) {
-		    val >>= 1;
-		    dmabuf->ossmaxfrags >>= 1;
-		}
-		dmabuf->ready = 0;
-#ifdef DEBUG
-		printk("SNDCTL_DSP_SETFRAGMENT 0x%x, %d, %d\n", val,
-			dmabuf->ossfragsize, dmabuf->ossmaxfrags);
-#endif
-
-		return 0;
-
-	case SNDCTL_DSP_GETOSPACE:
-		if (!(file->f_mode & FMODE_WRITE))
-			return -EINVAL;
-		if (!dmabuf->ready && (val = prog_dmabuf(state, 0)) != 0)
-			return val;
-		spin_lock_irqsave(&state->card->lock, flags);
-		i810_update_ptr(state);
-		abinfo.fragsize = dmabuf->userfragsize;
-		abinfo.fragstotal = dmabuf->userfrags;
-		if (dmabuf->mapped)
- 			abinfo.bytes = dmabuf->dmasize;
-  		else
- 			abinfo.bytes = i810_get_free_write_space(state);
-		abinfo.fragments = abinfo.bytes / dmabuf->userfragsize;
-		spin_unlock_irqrestore(&state->card->lock, flags);
-#if defined(DEBUG) || defined(DEBUG_MMAP)
-		printk("SNDCTL_DSP_GETOSPACE %d, %d, %d, %d\n", abinfo.bytes,
-			abinfo.fragsize, abinfo.fragments, abinfo.fragstotal);
-#endif
-		return copy_to_user(argp, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
-
-	case SNDCTL_DSP_GETOPTR:
-		if (!(file->f_mode & FMODE_WRITE))
-			return -EINVAL;
-		if (!dmabuf->ready && (val = prog_dmabuf(state, 0)) != 0)
-			return val;
-		spin_lock_irqsave(&state->card->lock, flags);
-		val = i810_get_free_write_space(state);
-		cinfo.bytes = dmabuf->total_bytes;
-		cinfo.ptr = dmabuf->hwptr;
-		cinfo.blocks = val/dmabuf->userfragsize;
-		if (dmabuf->mapped && (dmabuf->trigger & PCM_ENABLE_OUTPUT)) {
-			dmabuf->count += val;
-			dmabuf->swptr = (dmabuf->swptr + val) % dmabuf->dmasize;
-			__i810_update_lvi(state, 0);
-		}
-		spin_unlock_irqrestore(&state->card->lock, flags);
-#if defined(DEBUG) || defined(DEBUG_MMAP)
-		printk("SNDCTL_DSP_GETOPTR %d, %d, %d, %d\n", cinfo.bytes,
-			cinfo.blocks, cinfo.ptr, dmabuf->count);
-#endif
-		return copy_to_user(argp, &cinfo, sizeof(cinfo)) ? -EFAULT : 0;
-
-	case SNDCTL_DSP_GETISPACE:
-		if (!(file->f_mode & FMODE_READ))
-			return -EINVAL;
-		if (!dmabuf->ready && (val = prog_dmabuf(state, 1)) != 0)
-			return val;
-		spin_lock_irqsave(&state->card->lock, flags);
-		abinfo.bytes = i810_get_available_read_data(state);
-		abinfo.fragsize = dmabuf->userfragsize;
-		abinfo.fragstotal = dmabuf->userfrags;
-		abinfo.fragments = abinfo.bytes / dmabuf->userfragsize;
-		spin_unlock_irqrestore(&state->card->lock, flags);
-#if defined(DEBUG) || defined(DEBUG_MMAP)
-		printk("SNDCTL_DSP_GETISPACE %d, %d, %d, %d\n", abinfo.bytes,
-			abinfo.fragsize, abinfo.fragments, abinfo.fragstotal);
-#endif
-		return copy_to_user(argp, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
-
-	case SNDCTL_DSP_GETIPTR:
-		if (!(file->f_mode & FMODE_READ))
-			return -EINVAL;
-		if (!dmabuf->ready && (val = prog_dmabuf(state, 0)) != 0)
-			return val;
-		spin_lock_irqsave(&state->card->lock, flags);
-		val = i810_get_available_read_data(state);
-		cinfo.bytes = dmabuf->total_bytes;
-		cinfo.blocks = val/dmabuf->userfragsize;
-		cinfo.ptr = dmabuf->hwptr;
-		if (dmabuf->mapped && (dmabuf->trigger & PCM_ENABLE_INPUT)) {
-			dmabuf->count -= val;
-			dmabuf->swptr = (dmabuf->swptr + val) % dmabuf->dmasize;
-			__i810_update_lvi(state, 1);
-		}
-		spin_unlock_irqrestore(&state->card->lock, flags);
-#if defined(DEBUG) || defined(DEBUG_MMAP)
-		printk("SNDCTL_DSP_GETIPTR %d, %d, %d, %d\n", cinfo.bytes,
-			cinfo.blocks, cinfo.ptr, dmabuf->count);
-#endif
-		return copy_to_user(argp, &cinfo, sizeof(cinfo)) ? -EFAULT : 0;
-
-	case SNDCTL_DSP_NONBLOCK:
-#ifdef DEBUG
-		printk("SNDCTL_DSP_NONBLOCK\n");
-#endif
-		file->f_flags |= O_NONBLOCK;
-		return 0;
-
-	case SNDCTL_DSP_GETCAPS:
-#ifdef DEBUG
-		printk("SNDCTL_DSP_GETCAPS\n");
-#endif
-	    return put_user(DSP_CAP_REALTIME|DSP_CAP_TRIGGER|DSP_CAP_MMAP|DSP_CAP_BIND,
-			    p);
-
-	case SNDCTL_DSP_GETTRIGGER:
-		val = 0;
-#ifdef DEBUG
-		printk("SNDCTL_DSP_GETTRIGGER 0x%x\n", dmabuf->trigger);
-#endif
-		return put_user(dmabuf->trigger, p);
-
-	case SNDCTL_DSP_SETTRIGGER:
-		if (get_user(val, p))
-			return -EFAULT;
-#if defined(DEBUG) || defined(DEBUG_MMAP)
-		printk("SNDCTL_DSP_SETTRIGGER 0x%x\n", val);
-#endif
-		/* silently ignore invalid PCM_ENABLE_xxx bits,
-		 * like the other drivers do
-		 */
-		if (!(file->f_mode & FMODE_READ ))
-			val &= ~PCM_ENABLE_INPUT;
-		if (!(file->f_mode & FMODE_WRITE ))
-			val &= ~PCM_ENABLE_OUTPUT;
-		if((file->f_mode & FMODE_READ) && !(val & PCM_ENABLE_INPUT) && dmabuf->enable == ADC_RUNNING) {
-			stop_adc(state);
-		}
-		if((file->f_mode & FMODE_WRITE) && !(val & PCM_ENABLE_OUTPUT) && dmabuf->enable == DAC_RUNNING) {
-			stop_dac(state);
-		}
-		dmabuf->trigger = val;
-		if((val & PCM_ENABLE_OUTPUT) && !(dmabuf->enable & DAC_RUNNING)) {
-			if (!dmabuf->write_channel) {
-				dmabuf->ready = 0;
-				dmabuf->write_channel = state->card->alloc_pcm_channel(state->card);
-				if (!dmabuf->write_channel)
-					return -EBUSY;
-			}
-			if (!dmabuf->ready && (ret = prog_dmabuf(state, 0)))
-				return ret;
-			if (dmabuf->mapped) {
-				spin_lock_irqsave(&state->card->lock, flags);
-				i810_update_ptr(state);
-				dmabuf->count = 0;
-				dmabuf->swptr = dmabuf->hwptr;
-				dmabuf->count = i810_get_free_write_space(state);
-				dmabuf->swptr = (dmabuf->swptr + dmabuf->count) % dmabuf->dmasize;
-				spin_unlock_irqrestore(&state->card->lock, flags);
-			}
-			i810_update_lvi(state, 0);
-			start_dac(state);
-		}
-		if((val & PCM_ENABLE_INPUT) && !(dmabuf->enable & ADC_RUNNING)) {
-			if (!dmabuf->read_channel) {
-				dmabuf->ready = 0;
-				dmabuf->read_channel = state->card->alloc_rec_pcm_channel(state->card);
-				if (!dmabuf->read_channel)
-					return -EBUSY;
-			}
-			if (!dmabuf->ready && (ret = prog_dmabuf(state, 1)))
-				return ret;
-			if (dmabuf->mapped) {
-				spin_lock_irqsave(&state->card->lock, flags);
-				i810_update_ptr(state);
-				dmabuf->swptr = dmabuf->hwptr;
-				dmabuf->count = 0;
-				spin_unlock_irqrestore(&state->card->lock, flags);
-			}
-			i810_update_lvi(state, 1);
-			start_adc(state);
-		}
-		return 0;
-
-	case SNDCTL_DSP_SETDUPLEX:
-#ifdef DEBUG
-		printk("SNDCTL_DSP_SETDUPLEX\n");
-#endif
-		return -EINVAL;
-
-	case SNDCTL_DSP_GETODELAY:
-		if (!(file->f_mode & FMODE_WRITE))
-			return -EINVAL;
-		spin_lock_irqsave(&state->card->lock, flags);
-		i810_update_ptr(state);
-		val = dmabuf->count;
-		spin_unlock_irqrestore(&state->card->lock, flags);
-#ifdef DEBUG
-		printk("SNDCTL_DSP_GETODELAY %d\n", dmabuf->count);
-#endif
-		return put_user(val, p);
-
-	case SOUND_PCM_READ_RATE:
-#ifdef DEBUG
-		printk("SOUND_PCM_READ_RATE %d\n", dmabuf->rate);
-#endif
-		return put_user(dmabuf->rate, p);
-
-	case SOUND_PCM_READ_CHANNELS:
-#ifdef DEBUG
-		printk("SOUND_PCM_READ_CHANNELS\n");
-#endif
-		return put_user(2, p);
-
-	case SOUND_PCM_READ_BITS:
-#ifdef DEBUG
-		printk("SOUND_PCM_READ_BITS\n");
-#endif
-		return put_user(AFMT_S16_LE, p);
-
-	case SNDCTL_DSP_SETSPDIF: /* Set S/PDIF Control register */
-#ifdef DEBUG
-		printk("SNDCTL_DSP_SETSPDIF\n");
-#endif
-		if (get_user(val, p))
-			return -EFAULT;
-
-		/* Check to make sure the codec supports S/PDIF transmitter */
-
-		if((state->card->ac97_features & 4)) {
-			/* mask out the transmitter speed bits so the user can't set them */
-			val &= ~0x3000;
-
-			/* Add the current transmitter speed bits to the passed value */
-			ret = i810_ac97_get(codec, AC97_SPDIF_CONTROL);
-			val |= (ret & 0x3000);
-
-			i810_ac97_set(codec, AC97_SPDIF_CONTROL, val);
-			if(i810_ac97_get(codec, AC97_SPDIF_CONTROL) != val ) {
-				printk(KERN_ERR "i810_audio: Unable to set S/PDIF configuration to 0x%04x.\n", val);
-				return -EFAULT;
-			}
-		}
-#ifdef DEBUG
-		else 
-			printk(KERN_WARNING "i810_audio: S/PDIF transmitter not avalible.\n");
-#endif
-		return put_user(val, p);
-
-	case SNDCTL_DSP_GETSPDIF: /* Get S/PDIF Control register */
-#ifdef DEBUG
-		printk("SNDCTL_DSP_GETSPDIF\n");
-#endif
-		if (get_user(val, p))
-			return -EFAULT;
-
-		/* Check to make sure the codec supports S/PDIF transmitter */
-
-		if(!(state->card->ac97_features & 4)) {
-#ifdef DEBUG
-			printk(KERN_WARNING "i810_audio: S/PDIF transmitter not avalible.\n");
-#endif
-			val = 0;
-		} else {
-			val = i810_ac97_get(codec, AC97_SPDIF_CONTROL);
-		}
-		//return put_user((val & 0xcfff), p);
-		return put_user(val, p);
-   			
-	case SNDCTL_DSP_GETCHANNELMASK:
-#ifdef DEBUG
-		printk("SNDCTL_DSP_GETCHANNELMASK\n");
-#endif
-		if (get_user(val, p))
-			return -EFAULT;
-		
-		/* Based on AC'97 DAC support, not ICH hardware */
-		val = DSP_BIND_FRONT;
-		if ( state->card->ac97_features & 0x0004 )
-			val |= DSP_BIND_SPDIF;
-
-		if ( state->card->ac97_features & 0x0080 )
-			val |= DSP_BIND_SURR;
-		if ( state->card->ac97_features & 0x0140 )
-			val |= DSP_BIND_CENTER_LFE;
-
-		return put_user(val, p);
-
-	case SNDCTL_DSP_BIND_CHANNEL:
-#ifdef DEBUG
-		printk("SNDCTL_DSP_BIND_CHANNEL\n");
-#endif
-		if (get_user(val, p))
-			return -EFAULT;
-		if ( val == DSP_BIND_QUERY ) {
-			val = DSP_BIND_FRONT; /* Always report this as being enabled */
-			if ( state->card->ac97_status & SPDIF_ON ) 
-				val |= DSP_BIND_SPDIF;
-			else {
-				if ( state->card->ac97_status & SURR_ON )
-					val |= DSP_BIND_SURR;
-				if ( state->card->ac97_status & CENTER_LFE_ON )
-					val |= DSP_BIND_CENTER_LFE;
-			}
-		} else {  /* Not a query, set it */
-			if (!(file->f_mode & FMODE_WRITE))
-				return -EINVAL;
-			if ( dmabuf->enable == DAC_RUNNING ) {
-				stop_dac(state);
-			}
-			if ( val & DSP_BIND_SPDIF ) {  /* Turn on SPDIF */
-				/*  Ok, this should probably define what slots
-				 *  to use. For now, we'll only set it to the
-				 *  defaults:
-				 * 
-				 *   non multichannel codec maps to slots 3&4
-				 *   2 channel codec maps to slots 7&8
-				 *   4 channel codec maps to slots 6&9
-				 *   6 channel codec maps to slots 10&11
-				 *
-				 *  there should be some way for the app to
-				 *  select the slot assignment.
-				 */
-	
-				i810_set_spdif_output ( state, AC97_EA_SPSA_3_4, dmabuf->rate );
-				if ( !(state->card->ac97_status & SPDIF_ON) )
-					val &= ~DSP_BIND_SPDIF;
-			} else {
-				int mask;
-				int channels;
-
-				/* Turn off S/PDIF if it was on */
-				if ( state->card->ac97_status & SPDIF_ON ) 
-					i810_set_spdif_output ( state, -1, 0 );
-				
-				mask = val & (DSP_BIND_FRONT | DSP_BIND_SURR | DSP_BIND_CENTER_LFE);
-				switch (mask) {
-					case DSP_BIND_FRONT:
-						channels = 2;
-						break;
-					case DSP_BIND_FRONT|DSP_BIND_SURR:
-						channels = 4;
-						break;
-					case DSP_BIND_FRONT|DSP_BIND_SURR|DSP_BIND_CENTER_LFE:
-						channels = 6;
-						break;
-					default:
-						val = DSP_BIND_FRONT;
-						channels = 2;
-						break;
-				}
-				i810_set_dac_channels ( state, channels );
-
-				/* check that they really got turned on */
-				if (!(state->card->ac97_status & SURR_ON))
-					val &= ~DSP_BIND_SURR;
-				if (!(state->card->ac97_status & CENTER_LFE_ON))
-					val &= ~DSP_BIND_CENTER_LFE;
-			}
-		}
-		return put_user(val, p);
-		
-	case SNDCTL_DSP_MAPINBUF:
-	case SNDCTL_DSP_MAPOUTBUF:
-	case SNDCTL_DSP_SETSYNCRO:
-	case SOUND_PCM_WRITE_FILTER:
-	case SOUND_PCM_READ_FILTER:
-#ifdef DEBUG
-		printk("SNDCTL_* -EINVAL\n");
-#endif
-		return -EINVAL;
-	}
-	return -EINVAL;
-}
-
-static int i810_open(struct inode *inode, struct file *file)
-{
-	int i = 0;
-	struct i810_card *card = devs;
-	struct i810_state *state = NULL;
-	struct dmabuf *dmabuf = NULL;
-
-	/* find an avaiable virtual channel (instance of /dev/dsp) */
-	while (card != NULL) {
-		/*
-		 * If we are initializing and then fail, card could go
-		 * away unuexpectedly while we are in the for() loop.
-		 * So, check for card on each iteration before we check
-		 * for card->initializing to avoid a possible oops.
-		 * This usually only matters for times when the driver is
-		 * autoloaded by kmod.
-		 */
-		for (i = 0; i < 50 && card && card->initializing; i++) {
-			set_current_state(TASK_UNINTERRUPTIBLE);
-			schedule_timeout(HZ/20);
-		}
-		for (i = 0; i < NR_HW_CH && card && !card->initializing; i++) {
-			if (card->states[i] == NULL) {
-				state = card->states[i] = (struct i810_state *)
-					kzalloc(sizeof(struct i810_state), GFP_KERNEL);
-				if (state == NULL)
-					return -ENOMEM;
-				dmabuf = &state->dmabuf;
-				goto found_virt;
-			}
-		}
-		card = card->next;
-	}
-	/* no more virtual channel avaiable */
-	if (!state)
-		return -ENODEV;
-
-found_virt:
-	/* initialize the virtual channel */
-	state->virt = i;
-	state->card = card;
-	state->magic = I810_STATE_MAGIC;
-	init_waitqueue_head(&dmabuf->wait);
-	mutex_init(&state->open_mutex);
-	file->private_data = state;
-	dmabuf->trigger = 0;
-
-	/* allocate hardware channels */
-	if(file->f_mode & FMODE_READ) {
-		if((dmabuf->read_channel = card->alloc_rec_pcm_channel(card)) == NULL) {
-			kfree (card->states[i]);
-			card->states[i] = NULL;
-			return -EBUSY;
-		}
-		dmabuf->trigger |= PCM_ENABLE_INPUT;
-		i810_set_adc_rate(state, 8000);
-	}
-	if(file->f_mode & FMODE_WRITE) {
-		if((dmabuf->write_channel = card->alloc_pcm_channel(card)) == NULL) {
-			/* make sure we free the record channel allocated above */
-			if(file->f_mode & FMODE_READ)
-				card->free_pcm_channel(card,dmabuf->read_channel->num);
-			kfree (card->states[i]);
-			card->states[i] = NULL;
-			return -EBUSY;
-		}
-		/* Initialize to 8kHz?  What if we don't support 8kHz? */
-		/*  Let's change this to check for S/PDIF stuff */
-	
-		dmabuf->trigger |= PCM_ENABLE_OUTPUT;
-		if ( spdif_locked ) {
-			i810_set_dac_rate(state, spdif_locked);
-			i810_set_spdif_output(state, AC97_EA_SPSA_3_4, spdif_locked);
-		} else {
-			i810_set_dac_rate(state, 8000);
-			/* Put the ACLink in 2 channel mode by default */
-			i = I810_IOREADL(card, GLOB_CNT);
-			I810_IOWRITEL(i & 0xffcfffff, card, GLOB_CNT);
-		}
-	}
-		
-	/* set default sample format. According to OSS Programmer's Guide  /dev/dsp
-	   should be default to unsigned 8-bits, mono, with sample rate 8kHz and
-	   /dev/dspW will accept 16-bits sample, but we don't support those so we
-	   set it immediately to stereo and 16bit, which is all we do support */
-	dmabuf->fmt |= I810_FMT_16BIT | I810_FMT_STEREO;
-	dmabuf->ossfragsize = 0;
-	dmabuf->ossmaxfrags  = 0;
-	dmabuf->subdivision  = 0;
-
-	state->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
-
-	return nonseekable_open(inode, file);
-}
-
-static int i810_release(struct inode *inode, struct file *file)
-{
-	struct i810_state *state = (struct i810_state *)file->private_data;
-	struct i810_card *card = state->card;
-	struct dmabuf *dmabuf = &state->dmabuf;
-	unsigned long flags;
-
-	lock_kernel();
-
-	/* stop DMA state machine and free DMA buffers/channels */
-	if(dmabuf->trigger & PCM_ENABLE_OUTPUT) {
-		drain_dac(state, 0);
-	}
-	if(dmabuf->trigger & PCM_ENABLE_INPUT) {
-		stop_adc(state);
-	}
-	spin_lock_irqsave(&card->lock, flags);
-	dealloc_dmabuf(state);
-	if (file->f_mode & FMODE_WRITE) {
-		state->card->free_pcm_channel(state->card, dmabuf->write_channel->num);
-	}
-	if (file->f_mode & FMODE_READ) {
-		state->card->free_pcm_channel(state->card, dmabuf->read_channel->num);
-	}
-
-	state->card->states[state->virt] = NULL;
-	kfree(state);
-	spin_unlock_irqrestore(&card->lock, flags);
-	unlock_kernel();
-
-	return 0;
-}
-
-static /*const*/ struct file_operations i810_audio_fops = {
-	.owner		= THIS_MODULE,
-	.llseek		= no_llseek,
-	.read		= i810_read,
-	.write		= i810_write,
-	.poll		= i810_poll,
-	.ioctl		= i810_ioctl,
-	.mmap		= i810_mmap,
-	.open		= i810_open,
-	.release	= i810_release,
-};
-
-/* Write AC97 codec registers */
-
-static u16 i810_ac97_get_mmio(struct ac97_codec *dev, u8 reg)
-{
-	struct i810_card *card = dev->private_data;
-	int count = 100;
-	u16 reg_set = IO_REG_OFF(dev) | (reg&0x7f);
-	
-	while(count-- && (readb(card->iobase_mmio + CAS) & 1)) 
-		udelay(1);
-	
-#ifdef DEBUG_MMIO
-	{
-		u16 ans = readw(card->ac97base_mmio + reg_set);
-		printk(KERN_DEBUG "i810_audio: ac97_get_mmio(%d) -> 0x%04X\n", ((int) reg_set) & 0xffff, (u32) ans);
-		return ans;
-	}
-#else
-	return readw(card->ac97base_mmio + reg_set);
-#endif
-}
-
-static u16 i810_ac97_get_io(struct ac97_codec *dev, u8 reg)
-{
-	struct i810_card *card = dev->private_data;
-	int count = 100;
-	u16 reg_set = IO_REG_OFF(dev) | (reg&0x7f);
-	
-	while(count-- && (I810_IOREADB(card, CAS) & 1)) 
-		udelay(1);
-	
-	return inw(card->ac97base + reg_set);
-}
-
-static void i810_ac97_set_mmio(struct ac97_codec *dev, u8 reg, u16 data)
-{
-	struct i810_card *card = dev->private_data;
-	int count = 100;
-	u16 reg_set = IO_REG_OFF(dev) | (reg&0x7f);
-	
-	while(count-- && (readb(card->iobase_mmio + CAS) & 1)) 
-		udelay(1);
-	
-	writew(data, card->ac97base_mmio + reg_set);
-
-#ifdef DEBUG_MMIO
-	printk(KERN_DEBUG "i810_audio: ac97_set_mmio(0x%04X, %d)\n", (u32) data, ((int) reg_set) & 0xffff);
-#endif
-}
-
-static void i810_ac97_set_io(struct ac97_codec *dev, u8 reg, u16 data)
-{
-	struct i810_card *card = dev->private_data;
-	int count = 100;
-	u16 reg_set = IO_REG_OFF(dev) | (reg&0x7f);
-	
-	while(count-- && (I810_IOREADB(card, CAS) & 1)) 
-		udelay(1);
-	
-        outw(data, card->ac97base + reg_set);
-}
-
-static u16 i810_ac97_get(struct ac97_codec *dev, u8 reg)
-{
-	struct i810_card *card = dev->private_data;
-	u16 ret;
-	
-	spin_lock(&card->ac97_lock);
-	if (card->use_mmio) {
-		ret = i810_ac97_get_mmio(dev, reg);
-	}
-	else {
-		ret = i810_ac97_get_io(dev, reg);
-	}
-	spin_unlock(&card->ac97_lock);
-	
-	return ret;
-}
-
-static void i810_ac97_set(struct ac97_codec *dev, u8 reg, u16 data)
-{
-	struct i810_card *card = dev->private_data;
-	
-	spin_lock(&card->ac97_lock);
-	if (card->use_mmio) {
-		i810_ac97_set_mmio(dev, reg, data);
-	}
-	else {
-		i810_ac97_set_io(dev, reg, data);
-	}
-	spin_unlock(&card->ac97_lock);
-}
-
-
-/* OSS /dev/mixer file operation methods */
-
-static int i810_open_mixdev(struct inode *inode, struct file *file)
-{
-	int i;
-	int minor = iminor(inode);
-	struct i810_card *card = devs;
-
-	for (card = devs; card != NULL; card = card->next) {
-		/*
-		 * If we are initializing and then fail, card could go
-		 * away unuexpectedly while we are in the for() loop.
-		 * So, check for card on each iteration before we check
-		 * for card->initializing to avoid a possible oops.
-		 * This usually only matters for times when the driver is
-		 * autoloaded by kmod.
-		 */
-		for (i = 0; i < 50 && card && card->initializing; i++) {
-			set_current_state(TASK_UNINTERRUPTIBLE);
-			schedule_timeout(HZ/20);
-		}
-		for (i = 0; i < NR_AC97 && card && !card->initializing; i++) 
-			if (card->ac97_codec[i] != NULL &&
-			    card->ac97_codec[i]->dev_mixer == minor) {
-				file->private_data = card->ac97_codec[i];
-				return nonseekable_open(inode, file);
-			}
-	}
-	return -ENODEV;
-}
-
-static int i810_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd,
-				unsigned long arg)
-{
-	struct ac97_codec *codec = (struct ac97_codec *)file->private_data;
-
-	return codec->mixer_ioctl(codec, cmd, arg);
-}
-
-static /*const*/ struct file_operations i810_mixer_fops = {
-	.owner		= THIS_MODULE,
-	.llseek		= no_llseek,
-	.ioctl		= i810_ioctl_mixdev,
-	.open		= i810_open_mixdev,
-};
-
-/* AC97 codec initialisation.  These small functions exist so we don't
-   duplicate code between module init and apm resume */
-
-static inline int i810_ac97_exists(struct i810_card *card, int ac97_number)
-{
-	u32 reg = I810_IOREADL(card, GLOB_STA);
-	switch (ac97_number) {
-	case 0:
-		return reg & (1<<8);
-	case 1: 
-		return reg & (1<<9);
-	case 2:
-		return reg & (1<<28);
-	}
-	return 0;
-}
-
-static inline int i810_ac97_enable_variable_rate(struct ac97_codec *codec)
-{
-	i810_ac97_set(codec, AC97_EXTENDED_STATUS, 9);
-	i810_ac97_set(codec,AC97_EXTENDED_STATUS,
-		      i810_ac97_get(codec, AC97_EXTENDED_STATUS)|0xE800);
-	
-	return (i810_ac97_get(codec, AC97_EXTENDED_STATUS)&1);
-}
-
-
-static int i810_ac97_probe_and_powerup(struct i810_card *card,struct ac97_codec *codec)
-{
-	/* Returns 0 on failure */
-	int i;
-
-	if (ac97_probe_codec(codec) == 0) return 0;
-	
-	/* power it all up */
-	i810_ac97_set(codec, AC97_POWER_CONTROL,
-		      i810_ac97_get(codec, AC97_POWER_CONTROL) & ~0x7f00);
-
-	/* wait for analog ready */
-	for (i=100; i && ((i810_ac97_get(codec, AC97_POWER_CONTROL) & 0xf) != 0xf); i--)
-	{
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(HZ/20);
-	} 
-	return i;
-}
-
-static int is_new_ich(u16 pci_id)
-{
-	switch (pci_id) {
-	case PCI_DEVICE_ID_INTEL_82801DB_5:
-	case PCI_DEVICE_ID_INTEL_82801EB_5:
-	case PCI_DEVICE_ID_INTEL_ESB_5:
-	case PCI_DEVICE_ID_INTEL_ICH6_18:
-		return 1;
-	default:
-		break;
-	}
-
-	return 0;
-}
-
-static inline int ich_use_mmio(struct i810_card *card)
-{
-	return is_new_ich(card->pci_id) && card->use_mmio;
-}
-
-/**
- *	i810_ac97_power_up_bus	-	bring up AC97 link
- *	@card : ICH audio device to power up
- *
- *	Bring up the ACLink AC97 codec bus
- */
- 
-static int i810_ac97_power_up_bus(struct i810_card *card)
-{	
-	u32 reg = I810_IOREADL(card, GLOB_CNT);
-	int i;
-	int primary_codec_id = 0;
-
-	if((reg&2)==0)	/* Cold required */
-		reg|=2;
-	else
-		reg|=4;	/* Warm */
-		
-	reg&=~8;	/* ACLink on */
-	
-	/* At this point we deassert AC_RESET # */
-	I810_IOWRITEL(reg , card, GLOB_CNT);
-
-	/* We must now allow time for the Codec initialisation.
-	   600mS is the specified time */
-	   	
-	for(i=0;i<10;i++)
-	{
-		if((I810_IOREADL(card, GLOB_CNT)&4)==0)
-			break;
-
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(HZ/20);
-	}
-	if(i==10)
-	{
-		printk(KERN_ERR "i810_audio: AC'97 reset failed.\n");
-		return 0;
-	}
-
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(HZ/2);
-
-	/*
-	 *	See if the primary codec comes ready. This must happen
-	 *	before we start doing DMA stuff
-	 */	
-	/* see i810_ac97_init for the next 10 lines (jsaw) */
-	if (card->use_mmio)
-		readw(card->ac97base_mmio);
-	else
-		inw(card->ac97base);
-	if (ich_use_mmio(card)) {
-		primary_codec_id = (int) readl(card->iobase_mmio + SDM) & 0x3;
-		printk(KERN_INFO "i810_audio: Primary codec has ID %d\n",
-		       primary_codec_id);
-	}
-
-	if(! i810_ac97_exists(card, primary_codec_id))
-	{
-		printk(KERN_INFO "i810_audio: Codec not ready.. wait.. ");
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(HZ);	/* actually 600mS by the spec */
-
-		if(i810_ac97_exists(card, primary_codec_id))
-			printk("OK\n");
-		else 
-			printk("no response.\n");
-	}
-	if (card->use_mmio)
-		readw(card->ac97base_mmio);
-	else
-		inw(card->ac97base);
-	return 1;
-}
-
-static int __devinit i810_ac97_init(struct i810_card *card)
-{
-	int num_ac97 = 0;
-	int ac97_id;
-	int total_channels = 0;
-	int nr_ac97_max = card_cap[card->pci_id_internal].nr_ac97;
-	struct ac97_codec *codec;
-	u16 eid;
-	u32 reg;
-
-	if(!i810_ac97_power_up_bus(card)) return 0;
-
-	/* Number of channels supported */
-	/* What about the codec?  Just because the ICH supports */
-	/* multiple channels doesn't mean the codec does.       */
-	/* we'll have to modify this in the codec section below */
-	/* to reflect what the codec has.                       */
-	/* ICH and ICH0 only support 2 channels so don't bother */
-	/* to check....                                         */
-
-	card->channels = 2;
-	reg = I810_IOREADL(card, GLOB_STA);
-	if ( reg & 0x0200000 )
-		card->channels = 6;
-	else if ( reg & 0x0100000 )
-		card->channels = 4;
-	printk(KERN_INFO "i810_audio: Audio Controller supports %d channels.\n", card->channels);
-	printk(KERN_INFO "i810_audio: Defaulting to base 2 channel mode.\n");
-	reg = I810_IOREADL(card, GLOB_CNT);
-	I810_IOWRITEL(reg & 0xffcfffff, card, GLOB_CNT);
-		
-	for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) 
-		card->ac97_codec[num_ac97] = NULL;
-
-	/*@FIXME I don't know, if I'm playing to safe here... (jsaw) */
-	if ((nr_ac97_max > 2) && !card->use_mmio) nr_ac97_max = 2;
-
-	for (num_ac97 = 0; num_ac97 < nr_ac97_max; num_ac97++) {
-		/* codec reset */
-		printk(KERN_INFO "i810_audio: Resetting connection %d\n", num_ac97);
-		if (card->use_mmio)
-			readw(card->ac97base_mmio + 0x80*num_ac97);
-		else
-			inw(card->ac97base + 0x80*num_ac97);
-
-		/* If we have the SDATA_IN Map Register, as on ICH4, we
-		   do not loop thru all possible codec IDs but thru all 
-		   possible IO channels. Bit 0:1 of SDM then holds the 
-		   last codec ID spoken to. 
-		*/
-		if (ich_use_mmio(card)) {
-			ac97_id = (int) readl(card->iobase_mmio + SDM) & 0x3;
-			printk(KERN_INFO "i810_audio: Connection %d with codec id %d\n",
-			       num_ac97, ac97_id);
-		}
-		else {
-			ac97_id = num_ac97;
-		}
-
-		/* The ICH programmer's reference says you should   */
-		/* check the ready status before probing. So we chk */
-		/*   What do we do if it's not ready?  Wait and try */
-		/*   again, or abort?                               */
-		if (!i810_ac97_exists(card, ac97_id)) {
-			if(num_ac97 == 0)
-				printk(KERN_ERR "i810_audio: Primary codec not ready.\n");
-		}
-		
-		if ((codec = ac97_alloc_codec()) == NULL)
-			return -ENOMEM;
-
-		/* initialize some basic codec information, other fields will be filled
-		   in ac97_probe_codec */
-		codec->private_data = card;
-		codec->id = ac97_id;
-		card->ac97_id_map[ac97_id] = num_ac97 * 0x80;
-
-		if (card->use_mmio) {	
-			codec->codec_read = i810_ac97_get_mmio;
-			codec->codec_write = i810_ac97_set_mmio;
-		}
-		else {
-			codec->codec_read = i810_ac97_get_io;
-			codec->codec_write = i810_ac97_set_io;
-		}
-	
-		if(!i810_ac97_probe_and_powerup(card,codec)) {
-			printk(KERN_ERR "i810_audio: timed out waiting for codec %d analog ready.\n", ac97_id);
-			ac97_release_codec(codec);
-			break;	/* it didn't work */
-		}
-		/* Store state information about S/PDIF transmitter */
-		card->ac97_status = 0;
-		
-		/* Don't attempt to get eid until powerup is complete */
-		eid = i810_ac97_get(codec, AC97_EXTENDED_ID);
-
-		if(eid==0xFFFF)
-		{
-			printk(KERN_WARNING "i810_audio: no codec attached ?\n");
-			ac97_release_codec(codec);
-			break;
-		}
-		
-		/* Check for an AC97 1.0 soft modem (ID1) */
-		
-		if(codec->modem)
-		{
-			printk(KERN_WARNING "i810_audio: codec %d is a softmodem - skipping.\n", ac97_id);
-			ac97_release_codec(codec);
-			continue;
-		}
-		
-		card->ac97_features = eid;
-
-		/* Now check the codec for useful features to make up for
-		   the dumbness of the 810 hardware engine */
-
-		if(!(eid&0x0001))
-			printk(KERN_WARNING "i810_audio: only 48Khz playback available.\n");
-		else
-		{
-			if(!i810_ac97_enable_variable_rate(codec)) {
-				printk(KERN_WARNING "i810_audio: Codec refused to allow VRA, using 48Khz only.\n");
-				card->ac97_features&=~1;
-			}			
-		}
-   		
-		/* Turn on the amplifier */
-
-		codec->codec_write(codec, AC97_POWER_CONTROL, 
-			 codec->codec_read(codec, AC97_POWER_CONTROL) & ~0x8000);
-				
-		/* Determine how many channels the codec(s) support   */
-		/*   - The primary codec always supports 2            */
-		/*   - If the codec supports AMAP, surround DACs will */
-		/*     automaticlly get assigned to slots.            */
-		/*     * Check for surround DACs and increment if     */
-		/*       found.                                       */
-		/*   - Else check if the codec is revision 2.2        */
-		/*     * If surround DACs exist, assign them to slots */
-		/*       and increment channel count.                 */
-
-		/* All of this only applies to ICH2 and above. ICH    */
-		/* and ICH0 only support 2 channels.  ICH2 will only  */
-		/* support multiple codecs in a "split audio" config. */
-		/* as described above.                                */
-
-		/* TODO: Remove all the debugging messages!           */
-
-		if((eid & 0xc000) == 0) /* primary codec */
-			total_channels += 2; 
-
-		if(eid & 0x200) { /* GOOD, AMAP support */
-			if (eid & 0x0080) /* L/R Surround channels */
-				total_channels += 2;
-			if (eid & 0x0140) /* LFE and Center channels */
-				total_channels += 2;
-			printk("i810_audio: AC'97 codec %d supports AMAP, total channels = %d\n", ac97_id, total_channels);
-		} else if (eid & 0x0400) {  /* this only works on 2.2 compliant codecs */
-			eid &= 0xffcf;
-			if((eid & 0xc000) != 0)	{
-				switch ( total_channels ) {
-					case 2:
-						/* Set dsa1, dsa0 to 01 */
-						eid |= 0x0010;
-						break;
-					case 4:
-						/* Set dsa1, dsa0 to 10 */
-						eid |= 0x0020;
-						break;
-					case 6:
-						/* Set dsa1, dsa0 to 11 */
-						eid |= 0x0030;
-						break;
-				}
-				total_channels += 2;
-			}
-			i810_ac97_set(codec, AC97_EXTENDED_ID, eid);
-			eid = i810_ac97_get(codec, AC97_EXTENDED_ID);
-			printk("i810_audio: AC'97 codec %d, new EID value = 0x%04x\n", ac97_id, eid);
-			if (eid & 0x0080) /* L/R Surround channels */
-				total_channels += 2;
-			if (eid & 0x0140) /* LFE and Center channels */
-				total_channels += 2;
-			printk("i810_audio: AC'97 codec %d, DAC map configured, total channels = %d\n", ac97_id, total_channels);
-		} else {
-			printk("i810_audio: AC'97 codec %d Unable to map surround DAC's (or DAC's not present), total channels = %d\n", ac97_id, total_channels);
-		}
-
-		if ((codec->dev_mixer = register_sound_mixer(&i810_mixer_fops, -1)) < 0) {
-			printk(KERN_ERR "i810_audio: couldn't register mixer!\n");
-			ac97_release_codec(codec);
-			break;
-		}
-
-		card->ac97_codec[num_ac97] = codec;
-	}
-
-	/* tune up the primary codec */
-	ac97_tune_hardware(card->pci_dev, ac97_quirks, ac97_quirk);
-
-	/* pick the minimum of channels supported by ICHx or codec(s) */
-	card->channels = (card->channels > total_channels)?total_channels:card->channels;
-
-	return num_ac97;
-}
-
-static void __devinit i810_configure_clocking (void)
-{
-	struct i810_card *card;
-	struct i810_state *state;
-	struct dmabuf *dmabuf;
-	unsigned int i, offset, new_offset;
-	unsigned long flags;
-
-	card = devs;
-	/* We could try to set the clocking for multiple cards, but can you even have
-	 * more than one i810 in a machine?  Besides, clocking is global, so unless
-	 * someone actually thinks more than one i810 in a machine is possible and
-	 * decides to rewrite that little bit, setting the rate for more than one card
-	 * is a waste of time.
-	 */
-	if(card != NULL) {
-		state = card->states[0] = (struct i810_state *)
-					kzalloc(sizeof(struct i810_state), GFP_KERNEL);
-		if (state == NULL)
-			return;
-		dmabuf = &state->dmabuf;
-
-		dmabuf->write_channel = card->alloc_pcm_channel(card);
-		state->virt = 0;
-		state->card = card;
-		state->magic = I810_STATE_MAGIC;
-		init_waitqueue_head(&dmabuf->wait);
-		mutex_init(&state->open_mutex);
-		dmabuf->fmt = I810_FMT_STEREO | I810_FMT_16BIT;
-		dmabuf->trigger = PCM_ENABLE_OUTPUT;
-		i810_set_spdif_output(state, -1, 0);
-		i810_set_dac_channels(state, 2);
-		i810_set_dac_rate(state, 48000);
-		if(prog_dmabuf(state, 0) != 0) {
-			goto config_out_nodmabuf;
-		}
-		if(dmabuf->dmasize < 16384) {
-			goto config_out;
-		}
-		dmabuf->count = dmabuf->dmasize;
-		CIV_TO_LVI(card, dmabuf->write_channel->port, -1);
-		local_irq_save(flags);
-		start_dac(state);
-		offset = i810_get_dma_addr(state, 0);
-		mdelay(50);
-		new_offset = i810_get_dma_addr(state, 0);
-		stop_dac(state);
-		local_irq_restore(flags);
-		i = new_offset - offset;
-#ifdef DEBUG_INTERRUPTS
-		printk("i810_audio: %d bytes in 50 milliseconds\n", i);
-#endif
-		if(i == 0)
-			goto config_out;
-		i = i / 4 * 20;
-		if (i > 48500 || i < 47500) {
-			clocking = clocking * clocking / i;
-			printk("i810_audio: setting clocking to %d\n", clocking);
-		}
-config_out:
-		dealloc_dmabuf(state);
-config_out_nodmabuf:
-		state->card->free_pcm_channel(state->card,state->dmabuf.write_channel->num);
-		kfree(state);
-		card->states[0] = NULL;
-	}
-}
-
-/* install the driver, we do not allocate hardware channel nor DMA buffer now, they are defered 
-   until "ACCESS" time (in prog_dmabuf called by open/read/write/ioctl/mmap) */
-   
-static int __devinit i810_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id)
-{
-	struct i810_card *card;
-
-	if (pci_enable_device(pci_dev))
-		return -EIO;
-
-	if (pci_set_dma_mask(pci_dev, I810_DMA_MASK)) {
-		printk(KERN_ERR "i810_audio: architecture does not support"
-		       " 32bit PCI busmaster DMA\n");
-		return -ENODEV;
-	}
-	
-	if ((card = kzalloc(sizeof(struct i810_card), GFP_KERNEL)) == NULL) {
-		printk(KERN_ERR "i810_audio: out of memory\n");
-		return -ENOMEM;
-	}
-
-	card->initializing = 1;
-	card->pci_dev = pci_dev;
-	card->pci_id = pci_id->device;
-	card->ac97base = pci_resource_start (pci_dev, 0);
-	card->iobase = pci_resource_start (pci_dev, 1);
-
-	if (!(card->ac97base) || !(card->iobase)) {
-		card->ac97base = 0;
-		card->iobase = 0;
-	}
-
-	/* if chipset could have mmio capability, check it */ 
-	if (card_cap[pci_id->driver_data].flags & CAP_MMIO) {
-		card->ac97base_mmio_phys = pci_resource_start (pci_dev, 2);
-		card->iobase_mmio_phys = pci_resource_start (pci_dev, 3);
-
-		if ((card->ac97base_mmio_phys) && (card->iobase_mmio_phys)) {
-			card->use_mmio = 1;
-		}
-		else {
-			card->ac97base_mmio_phys = 0;
-			card->iobase_mmio_phys = 0;
-		}
-	}
-
-	if (!(card->use_mmio) && (!(card->iobase) || !(card->ac97base))) {
-		printk(KERN_ERR "i810_audio: No I/O resources available.\n");
-		goto out_mem;
-	}
-
-	card->irq = pci_dev->irq;
-	card->next = devs;
-	card->magic = I810_CARD_MAGIC;
-#ifdef CONFIG_PM
-	card->pm_suspended=0;
-#endif
-	spin_lock_init(&card->lock);
-	spin_lock_init(&card->ac97_lock);
-	devs = card;
-
-	pci_set_master(pci_dev);
-
-	printk(KERN_INFO "i810: %s found at IO 0x%04lx and 0x%04lx, "
-	       "MEM 0x%04lx and 0x%04lx, IRQ %d\n",
-	       card_names[pci_id->driver_data], 
-	       card->iobase, card->ac97base, 
-	       card->ac97base_mmio_phys, card->iobase_mmio_phys,
-	       card->irq);
-
-	card->alloc_pcm_channel = i810_alloc_pcm_channel;
-	card->alloc_rec_pcm_channel = i810_alloc_rec_pcm_channel;
-	card->alloc_rec_mic_channel = i810_alloc_rec_mic_channel;
-	card->free_pcm_channel = i810_free_pcm_channel;
-
-	if ((card->channel = pci_alloc_consistent(pci_dev,
-	    sizeof(struct i810_channel)*NR_HW_CH, &card->chandma)) == NULL) {
-		printk(KERN_ERR "i810: cannot allocate channel DMA memory\n");
-		goto out_mem;
-	}
-
-	{ /* We may dispose of this altogether some time soon, so... */
-		struct i810_channel *cp = card->channel;
-
-		cp[0].offset = 0;
-		cp[0].port = 0x00;
-		cp[0].num = 0;
-		cp[1].offset = 0;
-		cp[1].port = 0x10;
-		cp[1].num = 1;
-		cp[2].offset = 0;
-		cp[2].port = 0x20;
-		cp[2].num = 2;
-	}
-
-	/* claim our iospace and irq */
-	if (!request_region(card->iobase, 64, card_names[pci_id->driver_data])) {
-		printk(KERN_ERR "i810_audio: unable to allocate region %lx\n", card->iobase);
-		goto out_region1;
-	}
-	if (!request_region(card->ac97base, 256, card_names[pci_id->driver_data])) {
-		printk(KERN_ERR "i810_audio: unable to allocate region %lx\n", card->ac97base);
-		goto out_region2;
-	}
-
-	if (card->use_mmio) {
-		if (request_mem_region(card->ac97base_mmio_phys, 512, "ich_audio MMBAR")) {
-			if ((card->ac97base_mmio = ioremap(card->ac97base_mmio_phys, 512))) { /*@FIXME can ioremap fail? don't know (jsaw) */
-				if (request_mem_region(card->iobase_mmio_phys, 256, "ich_audio MBBAR")) {
-					if ((card->iobase_mmio = ioremap(card->iobase_mmio_phys, 256))) {
-						printk(KERN_INFO "i810: %s mmio at 0x%04lx and 0x%04lx\n",
-						       card_names[pci_id->driver_data], 
-						       (unsigned long) card->ac97base_mmio, 
-						       (unsigned long) card->iobase_mmio); 
-					}
-					else {
-						iounmap(card->ac97base_mmio);
-						release_mem_region(card->ac97base_mmio_phys, 512);
-						release_mem_region(card->iobase_mmio_phys, 512);
-						card->use_mmio = 0;
-					}
-				}
-				else {
-					iounmap(card->ac97base_mmio);
-					release_mem_region(card->ac97base_mmio_phys, 512);
-					card->use_mmio = 0;
-				}
-			}
-		}
-		else {
-			card->use_mmio = 0;
-		}
-	}
-
-	/* initialize AC97 codec and register /dev/mixer */
-	if (i810_ac97_init(card) <= 0)
-		goto out_iospace;
-	pci_set_drvdata(pci_dev, card);
-
-	if(clocking == 0) {
-		clocking = 48000;
-		i810_configure_clocking();
-	}
-
-	/* register /dev/dsp */
-	if ((card->dev_audio = register_sound_dsp(&i810_audio_fops, -1)) < 0) {
-		int i;
-		printk(KERN_ERR "i810_audio: couldn't register DSP device!\n");
-		for (i = 0; i < NR_AC97; i++)
-		if (card->ac97_codec[i] != NULL) {
-			unregister_sound_mixer(card->ac97_codec[i]->dev_mixer);
-			ac97_release_codec(card->ac97_codec[i]);
-		}
-		goto out_iospace;
-	}
-
-	if (request_irq(card->irq, &i810_interrupt, IRQF_SHARED,
-			card_names[pci_id->driver_data], card)) {
-		printk(KERN_ERR "i810_audio: unable to allocate irq %d\n", card->irq);
-		goto out_iospace;
-	}
-
-
- 	card->initializing = 0;
-	return 0;
-
-out_iospace:
-	if (card->use_mmio) {
-		iounmap(card->ac97base_mmio);
-		iounmap(card->iobase_mmio);
-		release_mem_region(card->ac97base_mmio_phys, 512);
-		release_mem_region(card->iobase_mmio_phys, 256);
-	}
-	release_region(card->ac97base, 256);
-out_region2:
-	release_region(card->iobase, 64);
-out_region1:
-	pci_free_consistent(pci_dev, sizeof(struct i810_channel)*NR_HW_CH,
-	    card->channel, card->chandma);
-out_mem:
-	kfree(card);
-	return -ENODEV;
-}
-
-static void __devexit i810_remove(struct pci_dev *pci_dev)
-{
-	int i;
-	struct i810_card *card = pci_get_drvdata(pci_dev);
-	/* free hardware resources */
-	free_irq(card->irq, devs);
-	release_region(card->iobase, 64);
-	release_region(card->ac97base, 256);
-	pci_free_consistent(pci_dev, sizeof(struct i810_channel)*NR_HW_CH,
-			    card->channel, card->chandma);
-	if (card->use_mmio) {
-		iounmap(card->ac97base_mmio);
-		iounmap(card->iobase_mmio);
-		release_mem_region(card->ac97base_mmio_phys, 512);
-		release_mem_region(card->iobase_mmio_phys, 256);
-	}
-
-	/* unregister audio devices */
-	for (i = 0; i < NR_AC97; i++)
-		if (card->ac97_codec[i] != NULL) {
-			unregister_sound_mixer(card->ac97_codec[i]->dev_mixer);
-			ac97_release_codec(card->ac97_codec[i]);
-			card->ac97_codec[i] = NULL;
-		}
-	unregister_sound_dsp(card->dev_audio);
-	kfree(card);
-}
-
-#ifdef CONFIG_PM
-static int i810_pm_suspend(struct pci_dev *dev, pm_message_t pm_state)
-{
-        struct i810_card *card = pci_get_drvdata(dev);
-        struct i810_state *state;
-	unsigned long flags;
-	struct dmabuf *dmabuf;
-	int i,num_ac97;
-#ifdef DEBUG
-	printk("i810_audio: i810_pm_suspend called\n");
-#endif
-	if(!card) return 0;
-	spin_lock_irqsave(&card->lock, flags);
-	card->pm_suspended=1;
-	for(i=0;i<NR_HW_CH;i++) {
-		state = card->states[i];
-		if(!state) continue;
-		/* this happens only if there are open files */
-		dmabuf = &state->dmabuf;
-		if(dmabuf->enable & DAC_RUNNING ||
-		   (dmabuf->count && (dmabuf->trigger & PCM_ENABLE_OUTPUT))) {
-			state->pm_saved_dac_rate=dmabuf->rate;
-			stop_dac(state);
-		} else {
-			state->pm_saved_dac_rate=0;
-		}
-		if(dmabuf->enable & ADC_RUNNING) {
-			state->pm_saved_adc_rate=dmabuf->rate;	
-			stop_adc(state);
-		} else {
-			state->pm_saved_adc_rate=0;
-		}
-		dmabuf->ready = 0;
-		dmabuf->swptr = dmabuf->hwptr = 0;
-		dmabuf->count = dmabuf->total_bytes = 0;
-	}
-
-	spin_unlock_irqrestore(&card->lock, flags);
-
-	/* save mixer settings */
-	for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) {
-		struct ac97_codec *codec = card->ac97_codec[num_ac97];
-		if(!codec) continue;
-		for(i=0;i< SOUND_MIXER_NRDEVICES ;i++) {
-			if((supported_mixer(codec,i)) &&
-			   (codec->read_mixer)) {
-				card->pm_saved_mixer_settings[i][num_ac97]=
-					codec->read_mixer(codec,i);
-			}
-		}
-	}
-	pci_save_state(dev); /* XXX do we need this? */
-	pci_disable_device(dev); /* disable busmastering */
-	pci_set_power_state(dev,3); /* Zzz. */
-
-	return 0;
-}
-
-
-static int i810_pm_resume(struct pci_dev *dev)
-{
-	int num_ac97,i=0;
-	struct i810_card *card=pci_get_drvdata(dev);
-	pci_enable_device(dev);
-	pci_restore_state (dev);
-
-	/* observation of a toshiba portege 3440ct suggests that the 
-	   hardware has to be more or less completely reinitialized from
-	   scratch after an apm suspend.  Works For Me.   -dan */
-
-	i810_ac97_power_up_bus(card);
-
-	for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) {
-		struct ac97_codec *codec = card->ac97_codec[num_ac97];
-		/* check they haven't stolen the hardware while we were
-		   away */
-		if(!codec || !i810_ac97_exists(card,num_ac97)) {
-			if(num_ac97) continue;
-			else BUG();
-		}
-		if(!i810_ac97_probe_and_powerup(card,codec)) BUG();
-		
-		if((card->ac97_features&0x0001)) {
-			/* at probe time we found we could do variable
-			   rates, but APM suspend has made it forget
-			   its magical powers */
-			if(!i810_ac97_enable_variable_rate(codec)) BUG();
-		}
-		/* we lost our mixer settings, so restore them */
-		for(i=0;i< SOUND_MIXER_NRDEVICES ;i++) {
-			if(supported_mixer(codec,i)){
-				int val=card->
-					pm_saved_mixer_settings[i][num_ac97];
-				codec->mixer_state[i]=val;
-				codec->write_mixer(codec,i,
-						   (val  & 0xff) ,
-						   ((val >> 8)  & 0xff) );
-			}
-		}
-	}
-
-	/* we need to restore the sample rate from whatever it was */
-	for(i=0;i<NR_HW_CH;i++) {
-		struct i810_state * state=card->states[i];
-		if(state) {
-			if(state->pm_saved_adc_rate)
-				i810_set_adc_rate(state,state->pm_saved_adc_rate);
-			if(state->pm_saved_dac_rate)
-				i810_set_dac_rate(state,state->pm_saved_dac_rate);
-		}
-	}
-
-	
-        card->pm_suspended = 0;
-
-	/* any processes that were reading/writing during the suspend
-	   probably ended up here */
-	for(i=0;i<NR_HW_CH;i++) {
-		struct i810_state *state = card->states[i];
-		if(state) wake_up(&state->dmabuf.wait);
-        }
-
-	return 0;
-}	
-#endif /* CONFIG_PM */
-
-MODULE_AUTHOR("The Linux kernel team");
-MODULE_DESCRIPTION("Intel 810 audio support");
-MODULE_LICENSE("GPL");
-module_param(ftsodell, int, 0444);
-module_param(clocking, uint, 0444);
-module_param(strict_clocking, int, 0444);
-module_param(spdif_locked, int, 0444);
-
-#define I810_MODULE_NAME "i810_audio"
-
-static struct pci_driver i810_pci_driver = {
-	.name		= I810_MODULE_NAME,
-	.id_table	= i810_pci_tbl,
-	.probe		= i810_probe,
-	.remove		= __devexit_p(i810_remove),
-#ifdef CONFIG_PM
-	.suspend	= i810_pm_suspend,
-	.resume		= i810_pm_resume,
-#endif /* CONFIG_PM */
-};
-
-
-static int __init i810_init_module (void)
-{
-	int retval;
-
-	printk(KERN_INFO "Intel 810 + AC97 Audio, version "
-	       DRIVER_VERSION ", " __TIME__ " " __DATE__ "\n");
-
-	retval = pci_register_driver(&i810_pci_driver);
-	if (retval)
-		return retval;
-
-	if(ftsodell != 0) {
-		printk("i810_audio: ftsodell is now a deprecated option.\n");
-	}
-	if(spdif_locked > 0 ) {
-		if(spdif_locked == 32000 || spdif_locked == 44100 || spdif_locked == 48000) {
-			printk("i810_audio: Enabling S/PDIF at sample rate %dHz.\n", spdif_locked);
-		} else {
-			printk("i810_audio: S/PDIF can only be locked to 32000, 44100, or 48000Hz.\n");
-			spdif_locked = 0;
-		}
-	}
-	
-	return 0;
-}
-
-static void __exit i810_cleanup_module (void)
-{
-	pci_unregister_driver(&i810_pci_driver);
-}
-
-module_init(i810_init_module);
-module_exit(i810_cleanup_module);
-
-/*
-Local Variables:
-c-basic-offset: 8
-End:
-*/
diff --git a/sound/oss/via82cxxx_audio.c b/sound/oss/via82cxxx_audio.c
deleted file mode 100644
index f95aa09..0000000
--- a/sound/oss/via82cxxx_audio.c
+++ /dev/null
@@ -1,3616 +0,0 @@
-/*
- * Support for VIA 82Cxxx Audio Codecs
- * Copyright 1999,2000 Jeff Garzik
- *
- * Updated to support the VIA 8233/8235 audio subsystem
- * Alan Cox <alan@redhat.com> (C) Copyright 2002, 2003 Red Hat Inc
- *
- * Distributed under the GNU GENERAL PUBLIC LICENSE (GPL) Version 2.
- * See the "COPYING" file distributed with this software for more info.
- * NO WARRANTY
- *
- * For a list of known bugs (errata) and documentation,
- * see via-audio.pdf in Documentation/DocBook.
- * If this documentation does not exist, run "make pdfdocs".
- */
-
-
-#define VIA_VERSION	"1.9.1-ac4-2.5"
-
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/pci.h>
-#include <linux/poison.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/proc_fs.h>
-#include <linux/spinlock.h>
-#include <linux/sound.h>
-#include <linux/poll.h>
-#include <linux/soundcard.h>
-#include <linux/ac97_codec.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <linux/mutex.h>
-
-#include "sound_config.h"
-#include "dev_table.h"
-#include "mpu401.h"
-
-
-#undef VIA_DEBUG	/* define to enable debugging output and checks */
-#ifdef VIA_DEBUG
-/* note: prints function name for you */
-#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
-#else
-#define DPRINTK(fmt, args...)
-#endif
-
-#undef VIA_NDEBUG	/* define to disable lightweight runtime checks */
-#ifdef VIA_NDEBUG
-#define assert(expr)
-#else
-#define assert(expr) \
-        if(!(expr)) {					\
-        printk( "Assertion failed! %s,%s,%s,line=%d\n",	\
-        #expr,__FILE__,__FUNCTION__,__LINE__);		\
-        }
-#endif
-
-#define VIA_SUPPORT_MMAP 1 /* buggy, for now... */
-
-#define MAX_CARDS	1
-
-#define VIA_CARD_NAME	"VIA 82Cxxx Audio driver " VIA_VERSION
-#define VIA_MODULE_NAME "via82cxxx"
-#define PFX		VIA_MODULE_NAME ": "
-
-#define VIA_COUNTER_LIMIT	100000
-
-/* size of DMA buffers */
-#define VIA_MAX_BUFFER_DMA_PAGES	32
-
-/* buffering default values in ms */
-#define VIA_DEFAULT_FRAG_TIME		20
-#define VIA_DEFAULT_BUFFER_TIME		500
-
-/* the hardware has a 256 fragment limit */
-#define VIA_MIN_FRAG_NUMBER		2
-#define VIA_MAX_FRAG_NUMBER		128
-
-#define VIA_MAX_FRAG_SIZE		PAGE_SIZE
-#define VIA_MIN_FRAG_SIZE		(VIA_MAX_BUFFER_DMA_PAGES * PAGE_SIZE / VIA_MAX_FRAG_NUMBER)
-
-
-/* 82C686 function 5 (audio codec) PCI configuration registers */
-#define VIA_ACLINK_STATUS	0x40
-#define VIA_ACLINK_CTRL		0x41
-#define VIA_FUNC_ENABLE		0x42
-#define VIA_PNP_CONTROL		0x43
-#define VIA_FM_NMI_CTRL		0x48
-
-/*
- * controller base 0 (scatter-gather) registers
- *
- * NOTE: Via datasheet lists first channel as "read"
- * channel and second channel as "write" channel.
- * I changed the naming of the constants to be more
- * clear than I felt the datasheet to be.
- */
-
-#define VIA_BASE0_PCM_OUT_CHAN	0x00 /* output PCM to user */
-#define VIA_BASE0_PCM_OUT_CHAN_STATUS 0x00
-#define VIA_BASE0_PCM_OUT_CHAN_CTRL	0x01
-#define VIA_BASE0_PCM_OUT_CHAN_TYPE	0x02
-
-#define VIA_BASE0_PCM_IN_CHAN		0x10 /* input PCM from user */
-#define VIA_BASE0_PCM_IN_CHAN_STATUS	0x10
-#define VIA_BASE0_PCM_IN_CHAN_CTRL	0x11
-#define VIA_BASE0_PCM_IN_CHAN_TYPE	0x12
-
-/* offsets from base */
-#define VIA_PCM_STATUS			0x00
-#define VIA_PCM_CONTROL			0x01
-#define VIA_PCM_TYPE			0x02
-#define VIA_PCM_LEFTVOL			0x02
-#define VIA_PCM_RIGHTVOL		0x03
-#define VIA_PCM_TABLE_ADDR		0x04
-#define VIA_PCM_STOPRATE		0x08	/* 8233+ */
-#define VIA_PCM_BLOCK_COUNT		0x0C
-
-/* XXX unused DMA channel for FM PCM data */
-#define VIA_BASE0_FM_OUT_CHAN		0x20
-#define VIA_BASE0_FM_OUT_CHAN_STATUS	0x20
-#define VIA_BASE0_FM_OUT_CHAN_CTRL	0x21
-#define VIA_BASE0_FM_OUT_CHAN_TYPE	0x22
-
-/* Six channel audio output on 8233 */
-#define VIA_BASE0_MULTI_OUT_CHAN		0x40
-#define VIA_BASE0_MULTI_OUT_CHAN_STATUS		0x40
-#define VIA_BASE0_MULTI_OUT_CHAN_CTRL		0x41
-#define VIA_BASE0_MULTI_OUT_CHAN_TYPE		0x42
-
-#define VIA_BASE0_AC97_CTRL		0x80
-#define VIA_BASE0_SGD_STATUS_SHADOW	0x84
-#define VIA_BASE0_GPI_INT_ENABLE	0x8C
-#define VIA_INTR_OUT			((1<<0) |  (1<<4) |  (1<<8))
-#define VIA_INTR_IN			((1<<1) |  (1<<5) |  (1<<9))
-#define VIA_INTR_FM			((1<<2) |  (1<<6) | (1<<10))
-#define VIA_INTR_MASK		(VIA_INTR_OUT | VIA_INTR_IN | VIA_INTR_FM)
-
-/* Newer VIA we need to monitor the low 3 bits of each channel. This
-   mask covers the channels we don't yet use as well 
- */
- 
-#define VIA_NEW_INTR_MASK		0x77077777UL
-
-/* VIA_BASE0_AUDIO_xxx_CHAN_TYPE bits */
-#define VIA_IRQ_ON_FLAG			(1<<0)	/* int on each flagged scatter block */
-#define VIA_IRQ_ON_EOL			(1<<1)	/* int at end of scatter list */
-#define VIA_INT_SEL_PCI_LAST_LINE_READ	(0)	/* int at PCI read of last line */
-#define VIA_INT_SEL_LAST_SAMPLE_SENT	(1<<2)	/* int at last sample sent */
-#define VIA_INT_SEL_ONE_LINE_LEFT	(1<<3)	/* int at less than one line to send */
-#define VIA_PCM_FMT_STEREO		(1<<4)	/* PCM stereo format (bit clear == mono) */
-#define VIA_PCM_FMT_16BIT		(1<<5)	/* PCM 16-bit format (bit clear == 8-bit) */
-#define VIA_PCM_REC_FIFO		(1<<6)	/* PCM Recording FIFO */
-#define VIA_RESTART_SGD_ON_EOL		(1<<7)	/* restart scatter-gather at EOL */
-#define VIA_PCM_FMT_MASK		(VIA_PCM_FMT_STEREO|VIA_PCM_FMT_16BIT)
-#define VIA_CHAN_TYPE_MASK		(VIA_RESTART_SGD_ON_EOL | \
-					 VIA_IRQ_ON_FLAG | \
-					 VIA_IRQ_ON_EOL)
-#define VIA_CHAN_TYPE_INT_SELECT	(VIA_INT_SEL_LAST_SAMPLE_SENT)
-
-/* PCI configuration register bits and masks */
-#define VIA_CR40_AC97_READY	0x01
-#define VIA_CR40_AC97_LOW_POWER	0x02
-#define VIA_CR40_SECONDARY_READY 0x04
-
-#define VIA_CR41_AC97_ENABLE	0x80 /* enable AC97 codec */
-#define VIA_CR41_AC97_RESET	0x40 /* clear bit to reset AC97 */
-#define VIA_CR41_AC97_WAKEUP	0x20 /* wake up from power-down mode */
-#define VIA_CR41_AC97_SDO	0x10 /* force Serial Data Out (SDO) high */
-#define VIA_CR41_VRA		0x08 /* enable variable sample rate */
-#define VIA_CR41_PCM_ENABLE	0x04 /* AC Link SGD Read Channel PCM Data Output */
-#define VIA_CR41_FM_PCM_ENABLE	0x02 /* AC Link FM Channel PCM Data Out */
-#define VIA_CR41_SB_PCM_ENABLE	0x01 /* AC Link SB PCM Data Output */
-#define VIA_CR41_BOOT_MASK	(VIA_CR41_AC97_ENABLE | \
-				 VIA_CR41_AC97_WAKEUP | \
-				 VIA_CR41_AC97_SDO)
-#define VIA_CR41_RUN_MASK	(VIA_CR41_AC97_ENABLE | \
-				 VIA_CR41_AC97_RESET | \
-				 VIA_CR41_VRA | \
-				 VIA_CR41_PCM_ENABLE)
-
-#define VIA_CR42_SB_ENABLE	0x01
-#define VIA_CR42_MIDI_ENABLE	0x02
-#define VIA_CR42_FM_ENABLE	0x04
-#define VIA_CR42_GAME_ENABLE	0x08
-#define VIA_CR42_MIDI_IRQMASK   0x40
-#define VIA_CR42_MIDI_PNP	0x80
-
-#define VIA_CR44_SECOND_CODEC_SUPPORT	(1 << 6)
-#define VIA_CR44_AC_LINK_ACCESS		(1 << 7)
-
-#define VIA_CR48_FM_TRAP_TO_NMI		(1 << 2)
-
-/* controller base 0 register bitmasks */
-#define VIA_INT_DISABLE_MASK		(~(0x01|0x02))
-#define VIA_SGD_STOPPED			(1 << 2)
-#define VIA_SGD_PAUSED			(1 << 6)
-#define VIA_SGD_ACTIVE			(1 << 7)
-#define VIA_SGD_TERMINATE		(1 << 6)
-#define VIA_SGD_FLAG			(1 << 0)
-#define VIA_SGD_EOL			(1 << 1)
-#define VIA_SGD_START			(1 << 7)
-
-#define VIA_CR80_FIRST_CODEC		0
-#define VIA_CR80_SECOND_CODEC		(1 << 30)
-#define VIA_CR80_FIRST_CODEC_VALID	(1 << 25)
-#define VIA_CR80_VALID			(1 << 25)
-#define VIA_CR80_SECOND_CODEC_VALID	(1 << 27)
-#define VIA_CR80_BUSY			(1 << 24)
-#define VIA_CR83_BUSY			(1)
-#define VIA_CR83_FIRST_CODEC_VALID	(1 << 1)
-#define VIA_CR80_READ			(1 << 23)
-#define VIA_CR80_WRITE_MODE		0
-#define VIA_CR80_REG_IDX(idx)		((((idx) & 0xFF) >> 1) << 16)
-
-/* capabilities we announce */
-#ifdef VIA_SUPPORT_MMAP
-#define VIA_DSP_CAP (DSP_CAP_REVISION | DSP_CAP_DUPLEX | DSP_CAP_MMAP | \
-		     DSP_CAP_TRIGGER | DSP_CAP_REALTIME)
-#else
-#define VIA_DSP_CAP (DSP_CAP_REVISION | DSP_CAP_DUPLEX | \
-		     DSP_CAP_TRIGGER | DSP_CAP_REALTIME)
-#endif
-
-/* scatter-gather DMA table entry, exactly as passed to hardware */
-struct via_sgd_table {
-	u32 addr;
-	u32 count;	/* includes additional VIA_xxx bits also */
-};
-
-#define VIA_EOL (1 << 31)
-#define VIA_FLAG (1 << 30)
-#define VIA_STOP (1 << 29)
-
-
-enum via_channel_states {
-	sgd_stopped = 0,
-	sgd_in_progress = 1,
-};
-
-
-struct via_buffer_pgtbl {
-	dma_addr_t handle;
-	void *cpuaddr;
-};
-
-
-struct via_channel {
-	atomic_t n_frags;
-	atomic_t hw_ptr;
-	wait_queue_head_t wait;
-
-	unsigned int sw_ptr;
-	unsigned int slop_len;
-	unsigned int n_irqs;
-	int bytes;
-
-	unsigned is_active : 1;
-	unsigned is_record : 1;
-	unsigned is_mapped : 1;
-	unsigned is_enabled : 1;
-	unsigned is_multi: 1;	/* 8233 6 channel */
-	u8 pcm_fmt;		/* VIA_PCM_FMT_xxx */
-	u8 channels;		/* Channel count */
-
-	unsigned rate;		/* sample rate */
-	unsigned int frag_size;
-	unsigned int frag_number;
-	
-	unsigned char intmask;
-
-	volatile struct via_sgd_table *sgtable;
-	dma_addr_t sgt_handle;
-
-	unsigned int page_number;
-	struct via_buffer_pgtbl pgtbl[VIA_MAX_BUFFER_DMA_PAGES];
-
-	long iobase;
-
-	const char *name;
-};
-
-
-/* data stored for each chip */
-struct via_info {
-	struct pci_dev *pdev;
-	long baseaddr;
-
-	struct ac97_codec *ac97;
-	spinlock_t ac97_lock;
-	spinlock_t lock;
-	int card_num;		/* unique card number, from 0 */
-
-	int dev_dsp;		/* /dev/dsp index from register_sound_dsp() */
-
-	unsigned rev_h : 1;
-	unsigned legacy: 1;	/* Has legacy ports */
-	unsigned intmask: 1;	/* Needs int bits */
-	unsigned sixchannel: 1;	/* 8233/35 with 6 channel support */
-	unsigned volume: 1;
-
-	unsigned locked_rate : 1;
-	
-	int mixer_vol;		/* 8233/35 volume  - not yet implemented */
-
-	struct mutex syscall_mutex;
-	struct mutex open_mutex;
-
-	/* The 8233/8235 have 4 DX audio channels, two record and
-	   one six channel out. We bind ch_in to DX 1, ch_out to multichannel
-	   and ch_fm to DX 2. DX 3 and REC0/REC1 are unused at the
-	   moment */
-	   
-	struct via_channel ch_in;
-	struct via_channel ch_out;
-	struct via_channel ch_fm;
-
-#ifdef CONFIG_MIDI_VIA82CXXX
-        void *midi_devc;
-        struct address_info midi_info;
-#endif
-};
-
-
-/* number of cards, used for assigning unique numbers to cards */
-static unsigned via_num_cards;
-
-
-
-/****************************************************************
- *
- * prototypes
- *
- *
- */
-
-static int via_init_one (struct pci_dev *dev, const struct pci_device_id *id);
-static void __devexit via_remove_one (struct pci_dev *pdev);
-
-static ssize_t via_dsp_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos);
-static ssize_t via_dsp_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos);
-static unsigned int via_dsp_poll(struct file *file, struct poll_table_struct *wait);
-static int via_dsp_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
-static int via_dsp_open (struct inode *inode, struct file *file);
-static int via_dsp_release(struct inode *inode, struct file *file);
-static int via_dsp_mmap(struct file *file, struct vm_area_struct *vma);
-
-static u16 via_ac97_read_reg (struct ac97_codec *codec, u8 reg);
-static void via_ac97_write_reg (struct ac97_codec *codec, u8 reg, u16 value);
-static u8 via_ac97_wait_idle (struct via_info *card);
-
-static void via_chan_free (struct via_info *card, struct via_channel *chan);
-static void via_chan_clear (struct via_info *card, struct via_channel *chan);
-static void via_chan_pcm_fmt (struct via_channel *chan, int reset);
-static void via_chan_buffer_free (struct via_info *card, struct via_channel *chan);
-
-
-/****************************************************************
- *
- * Various data the driver needs
- *
- *
- */
-
-
-static struct pci_device_id via_pci_tbl[] = {
-	{ PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{ PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8233_5,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
-	{ 0, }
-};
-MODULE_DEVICE_TABLE(pci,via_pci_tbl);
-
-
-static struct pci_driver via_driver = {
-	.name		= VIA_MODULE_NAME,
-	.id_table	= via_pci_tbl,
-	.probe		= via_init_one,
-	.remove		= __devexit_p(via_remove_one),
-};
-
-
-/****************************************************************
- *
- * Low-level base 0 register read/write helpers
- *
- *
- */
-
-/**
- *	via_chan_stop - Terminate DMA on specified PCM channel
- *	@iobase: PCI base address for SGD channel registers
- *
- *	Terminate scatter-gather DMA operation for given
- *	channel (derived from @iobase), if DMA is active.
- *
- *	Note that @iobase is not the PCI base address,
- *	but the PCI base address plus an offset to
- *	one of three PCM channels supported by the chip.
- *
- */
-
-static inline void via_chan_stop (long iobase)
-{
-	if (inb (iobase + VIA_PCM_STATUS) & VIA_SGD_ACTIVE)
-		outb (VIA_SGD_TERMINATE, iobase + VIA_PCM_CONTROL);
-}
-
-
-/**
- *	via_chan_status_clear - Clear status flags on specified DMA channel
- *	@iobase: PCI base address for SGD channel registers
- *
- *	Clear any pending status flags for the given
- *	DMA channel (derived from @iobase), if any
- *	flags are asserted.
- *
- *	Note that @iobase is not the PCI base address,
- *	but the PCI base address plus an offset to
- *	one of three PCM channels supported by the chip.
- *
- */
-
-static inline void via_chan_status_clear (long iobase)
-{
-	u8 tmp = inb (iobase + VIA_PCM_STATUS);
-
-	if (tmp != 0)
-		outb (tmp, iobase + VIA_PCM_STATUS);
-}
-
-
-/**
- *	sg_begin - Begin recording or playback on a PCM channel
- *	@chan: Channel for which DMA operation shall begin
- *
- *	Start scatter-gather DMA for the given channel.
- *
- */
-
-static inline void sg_begin (struct via_channel *chan)
-{
-	DPRINTK("Start with intmask %d\n", chan->intmask);
-	DPRINTK("About to start from %d to %d\n", 
-		inl(chan->iobase + VIA_PCM_BLOCK_COUNT),
-		inb(chan->iobase + VIA_PCM_STOPRATE + 3));
-	outb (VIA_SGD_START|chan->intmask, chan->iobase + VIA_PCM_CONTROL);
-	DPRINTK("Status is now %02X\n", inb(chan->iobase + VIA_PCM_STATUS));
-	DPRINTK("Control is now %02X\n", inb(chan->iobase + VIA_PCM_CONTROL));
-}
-
-
-static int sg_active (long iobase)
-{
-	u8 tmp = inb (iobase + VIA_PCM_STATUS);
-	if ((tmp & VIA_SGD_STOPPED) || (tmp & VIA_SGD_PAUSED)) {
-		printk(KERN_WARNING "via82cxxx warning: SG stopped or paused\n");
-		return 0;
-	}
-	if (tmp & VIA_SGD_ACTIVE)
-		return 1;
-	return 0;
-}
-
-static int via_sg_offset(struct via_channel *chan)
-{
-	return inl (chan->iobase + VIA_PCM_BLOCK_COUNT) & 0x00FFFFFF;
-}
-
-/****************************************************************
- *
- * Miscellaneous debris
- *
- *
- */
-
-
-/**
- *	via_syscall_down - down the card-specific syscell semaphore
- *	@card: Private info for specified board
- *	@nonblock: boolean, non-zero if O_NONBLOCK is set
- *
- *	Encapsulates standard method of acquiring the syscall sem.
- *
- *	Returns negative errno on error, or zero for success.
- */
-
-static inline int via_syscall_down (struct via_info *card, int nonblock)
-{
-	/* Thomas Sailer:
-	 * EAGAIN is supposed to be used if IO is pending,
-	 * not if there is contention on some internal
-	 * synchronization primitive which should be
-	 * held only for a short time anyway
-	 */
-	nonblock = 0;
-
-	if (nonblock) {
-		if (!mutex_trylock(&card->syscall_mutex))
-			return -EAGAIN;
-	} else {
-		if (mutex_lock_interruptible(&card->syscall_mutex))
-			return -ERESTARTSYS;
-	}
-
-	return 0;
-}
-
-
-/**
- *	via_stop_everything - Stop all audio operations
- *	@card: Private info for specified board
- *
- *	Stops all DMA operations and interrupts, and clear
- *	any pending status bits resulting from those operations.
- */
-
-static void via_stop_everything (struct via_info *card)
-{
-	u8 tmp, new_tmp;
-
-	DPRINTK ("ENTER\n");
-
-	assert (card != NULL);
-
-	/*
-	 * terminate any existing operations on audio read/write channels
-	 */
-	via_chan_stop (card->baseaddr + VIA_BASE0_PCM_OUT_CHAN);
-	via_chan_stop (card->baseaddr + VIA_BASE0_PCM_IN_CHAN);
-	via_chan_stop (card->baseaddr + VIA_BASE0_FM_OUT_CHAN);
-	if(card->sixchannel)
-		via_chan_stop (card->baseaddr + VIA_BASE0_MULTI_OUT_CHAN);
-
-	/*
-	 * clear any existing stops / flags (sanity check mainly)
-	 */
-	via_chan_status_clear (card->baseaddr + VIA_BASE0_PCM_OUT_CHAN);
-	via_chan_status_clear (card->baseaddr + VIA_BASE0_PCM_IN_CHAN);
-	via_chan_status_clear (card->baseaddr + VIA_BASE0_FM_OUT_CHAN);
-	if(card->sixchannel)
-		via_chan_status_clear (card->baseaddr + VIA_BASE0_MULTI_OUT_CHAN);
-
-	/*
-	 * clear any enabled interrupt bits
-	 */
-	tmp = inb (card->baseaddr + VIA_BASE0_PCM_OUT_CHAN_TYPE);
-	new_tmp = tmp & ~(VIA_IRQ_ON_FLAG|VIA_IRQ_ON_EOL|VIA_RESTART_SGD_ON_EOL);
-	if (tmp != new_tmp)
-		outb (0, card->baseaddr + VIA_BASE0_PCM_OUT_CHAN_TYPE);
-
-	tmp = inb (card->baseaddr + VIA_BASE0_PCM_IN_CHAN_TYPE);
-	new_tmp = tmp & ~(VIA_IRQ_ON_FLAG|VIA_IRQ_ON_EOL|VIA_RESTART_SGD_ON_EOL);
-	if (tmp != new_tmp)
-		outb (0, card->baseaddr + VIA_BASE0_PCM_IN_CHAN_TYPE);
-
-	tmp = inb (card->baseaddr + VIA_BASE0_FM_OUT_CHAN_TYPE);
-	new_tmp = tmp & ~(VIA_IRQ_ON_FLAG|VIA_IRQ_ON_EOL|VIA_RESTART_SGD_ON_EOL);
-	if (tmp != new_tmp)
-		outb (0, card->baseaddr + VIA_BASE0_FM_OUT_CHAN_TYPE);
-
-	if(card->sixchannel)
-	{
-		tmp = inb (card->baseaddr + VIA_BASE0_MULTI_OUT_CHAN_TYPE);
-		new_tmp = tmp & ~(VIA_IRQ_ON_FLAG|VIA_IRQ_ON_EOL|VIA_RESTART_SGD_ON_EOL);
-		if (tmp != new_tmp)
-			outb (0, card->baseaddr + VIA_BASE0_MULTI_OUT_CHAN_TYPE);
-	}
-
-	udelay(10);
-
-	/*
-	 * clear any existing flags
-	 */
-	via_chan_status_clear (card->baseaddr + VIA_BASE0_PCM_OUT_CHAN);
-	via_chan_status_clear (card->baseaddr + VIA_BASE0_PCM_IN_CHAN);
-	via_chan_status_clear (card->baseaddr + VIA_BASE0_FM_OUT_CHAN);
-
-	DPRINTK ("EXIT\n");
-}
-
-
-/**
- *	via_set_rate - Set PCM rate for given channel
- *	@ac97: Pointer to generic codec info struct
- *	@chan: Private info for specified channel
- *	@rate: Desired PCM sample rate, in Khz
- *
- *	Sets the PCM sample rate for a channel.
- *
- *	Values for @rate are clamped to a range of 4000 Khz through 48000 Khz,
- *	due to hardware constraints.
- */
-
-static int via_set_rate (struct ac97_codec *ac97,
-			 struct via_channel *chan, unsigned rate)
-{
-	struct via_info *card = ac97->private_data;
-	int rate_reg;
-	u32 dacp;
-	u32 mast_vol, phone_vol, mono_vol, pcm_vol;
-	u32 mute_vol = 0x8000;	/* The mute volume? -- Seems to work! */
-
-	DPRINTK ("ENTER, rate = %d\n", rate);
-
-	if (chan->rate == rate)
-		goto out;
-	if (card->locked_rate) {
-		chan->rate = 48000;
-		goto out;
-	}
-
-	if (rate > 48000)		rate = 48000;
-	if (rate < 4000) 		rate = 4000;
-
-	rate_reg = chan->is_record ? AC97_PCM_LR_ADC_RATE :
-			    AC97_PCM_FRONT_DAC_RATE;
-
-	/* Save current state */
-	dacp=via_ac97_read_reg(ac97, AC97_POWER_CONTROL);
-	mast_vol = via_ac97_read_reg(ac97, AC97_MASTER_VOL_STEREO);
-	mono_vol = via_ac97_read_reg(ac97, AC97_MASTER_VOL_MONO);
-	phone_vol = via_ac97_read_reg(ac97, AC97_HEADPHONE_VOL);
-	pcm_vol = via_ac97_read_reg(ac97, AC97_PCMOUT_VOL);
-	/* Mute - largely reduces popping */
-	via_ac97_write_reg(ac97, AC97_MASTER_VOL_STEREO, mute_vol);
-	via_ac97_write_reg(ac97, AC97_MASTER_VOL_MONO, mute_vol);
-	via_ac97_write_reg(ac97, AC97_HEADPHONE_VOL, mute_vol);
-       	via_ac97_write_reg(ac97, AC97_PCMOUT_VOL, mute_vol);
-	/* Power down the DAC */
-	via_ac97_write_reg(ac97, AC97_POWER_CONTROL, dacp|0x0200);
-
-        /* Set new rate */
-	via_ac97_write_reg (ac97, rate_reg, rate);
-
-	/* Power DAC back up */
-	via_ac97_write_reg(ac97, AC97_POWER_CONTROL, dacp);
-	udelay (200); /* reduces popping */
-
-	/* Restore volumes */
-	via_ac97_write_reg(ac97, AC97_MASTER_VOL_STEREO, mast_vol);
-	via_ac97_write_reg(ac97, AC97_MASTER_VOL_MONO, mono_vol);
-	via_ac97_write_reg(ac97, AC97_HEADPHONE_VOL, phone_vol);
-	via_ac97_write_reg(ac97, AC97_PCMOUT_VOL, pcm_vol);
-
-	/* the hardware might return a value different than what we
-	 * passed to it, so read the rate value back from hardware
-	 * to see what we came up with
-	 */
-	chan->rate = via_ac97_read_reg (ac97, rate_reg);
-
-	if (chan->rate == 0) {
-		card->locked_rate = 1;
-		chan->rate = 48000;
-		printk (KERN_WARNING PFX "Codec rate locked at 48Khz\n");
-	}
-
-out:
-	DPRINTK ("EXIT, returning rate %d Hz\n", chan->rate);
-	return chan->rate;
-}
-
-
-/****************************************************************
- *
- * Channel-specific operations
- *
- *
- */
-
-
-/**
- *	via_chan_init_defaults - Initialize a struct via_channel
- *	@card: Private audio chip info
- *	@chan: Channel to be initialized
- *
- *	Zero @chan, and then set all static defaults for the structure.
- */
-
-static void via_chan_init_defaults (struct via_info *card, struct via_channel *chan)
-{
-	memset (chan, 0, sizeof (*chan));
-
-	if(card->intmask)
-		chan->intmask = 0x23;	/* Turn on the IRQ bits */
-		
-	if (chan == &card->ch_out) {
-		chan->name = "PCM-OUT";
-		if(card->sixchannel)
-		{
-			chan->iobase = card->baseaddr + VIA_BASE0_MULTI_OUT_CHAN;
-			chan->is_multi = 1;
-			DPRINTK("Using multichannel for pcm out\n");
-		}
-		else
-			chan->iobase = card->baseaddr + VIA_BASE0_PCM_OUT_CHAN;
-	} else if (chan == &card->ch_in) {
-		chan->name = "PCM-IN";
-		chan->iobase = card->baseaddr + VIA_BASE0_PCM_IN_CHAN;
-		chan->is_record = 1;
-	} else if (chan == &card->ch_fm) {
-		chan->name = "PCM-OUT-FM";
-		chan->iobase = card->baseaddr + VIA_BASE0_FM_OUT_CHAN;
-	} else {
-		BUG();
-	}
-
-	init_waitqueue_head (&chan->wait);
-
-	chan->pcm_fmt = VIA_PCM_FMT_MASK;
-	chan->is_enabled = 1;
-
-	chan->frag_number = 0;
-        chan->frag_size = 0;
-	atomic_set(&chan->n_frags, 0);
-	atomic_set (&chan->hw_ptr, 0);
-}
-
-/**
- *      via_chan_init - Initialize PCM channel
- *      @card: Private audio chip info
- *      @chan: Channel to be initialized
- *
- *      Performs some of the preparations necessary to begin
- *      using a PCM channel.
- *
- *      Currently the preparations consist of
- *      setting the PCM channel to a known state.
- */
-
-
-static void via_chan_init (struct via_info *card, struct via_channel *chan)
-{
-
-        DPRINTK ("ENTER\n");
-
-	/* bzero channel structure, and init members to defaults */
-        via_chan_init_defaults (card, chan);
-
-        /* stop any existing channel output */
-        via_chan_clear (card, chan);
-        via_chan_status_clear (chan->iobase);
-        via_chan_pcm_fmt (chan, 1);
-
-	DPRINTK ("EXIT\n");
-}
-
-/**
- *	via_chan_buffer_init - Initialize PCM channel buffer
- *	@card: Private audio chip info
- *	@chan: Channel to be initialized
- *
- *	Performs some of the preparations necessary to begin
- *	using a PCM channel.
- *
- *	Currently the preparations include allocating the
- *	scatter-gather DMA table and buffers,
- *	and passing the
- *	address of the DMA table to the hardware.
- *
- *	Note that special care is taken when passing the
- *	DMA table address to hardware, because it was found
- *	during driver development that the hardware did not
- *	always "take" the address.
- */
-
-static int via_chan_buffer_init (struct via_info *card, struct via_channel *chan)
-{
-	int page, offset;
-	int i;
-
-	DPRINTK ("ENTER\n");
-
-
-	chan->intmask = 0;
-	if(card->intmask)
-		chan->intmask = 0x23;	/* Turn on the IRQ bits */
-		
-	if (chan->sgtable != NULL) {
-		DPRINTK ("EXIT\n");
-		return 0;
-	}
-
-	/* alloc DMA-able memory for scatter-gather table */
-	chan->sgtable = pci_alloc_consistent (card->pdev,
-		(sizeof (struct via_sgd_table) * chan->frag_number),
-		&chan->sgt_handle);
-	if (!chan->sgtable) {
-		printk (KERN_ERR PFX "DMA table alloc fail, aborting\n");
-		DPRINTK ("EXIT\n");
-		return -ENOMEM;
-	}
-
-	memset ((void*)chan->sgtable, 0,
-		(sizeof (struct via_sgd_table) * chan->frag_number));
-
-	/* alloc DMA-able memory for scatter-gather buffers */
-
-	chan->page_number = (chan->frag_number * chan->frag_size) / PAGE_SIZE +
-			    (((chan->frag_number * chan->frag_size) % PAGE_SIZE) ? 1 : 0);
-
-	for (i = 0; i < chan->page_number; i++) {
-		chan->pgtbl[i].cpuaddr = pci_alloc_consistent (card->pdev, PAGE_SIZE,
-					      &chan->pgtbl[i].handle);
-
-		if (!chan->pgtbl[i].cpuaddr) {
-			chan->page_number = i;
-			goto err_out_nomem;
-		}
-
-#ifndef VIA_NDEBUG
-                memset (chan->pgtbl[i].cpuaddr, 0xBC, chan->frag_size);
-#endif
-
-#if 1
-                DPRINTK ("dmabuf_pg #%d (h=%lx, v2p=%lx, a=%p)\n",
-			i, (long)chan->pgtbl[i].handle,
-			virt_to_phys(chan->pgtbl[i].cpuaddr),
-			chan->pgtbl[i].cpuaddr);
-#endif
-	}
-
-	for (i = 0; i < chan->frag_number; i++) {
-
-		page = i / (PAGE_SIZE / chan->frag_size);
-		offset = (i % (PAGE_SIZE / chan->frag_size)) * chan->frag_size;
-
-		chan->sgtable[i].count = cpu_to_le32 (chan->frag_size | VIA_FLAG);
-		chan->sgtable[i].addr = cpu_to_le32 (chan->pgtbl[page].handle + offset);
-
-#if 1
-		DPRINTK ("dmabuf #%d (32(h)=%lx)\n",
-			 i,
-			 (long)chan->sgtable[i].addr);
-#endif
-	}
-
-	/* overwrite the last buffer information */
-	chan->sgtable[chan->frag_number - 1].count = cpu_to_le32 (chan->frag_size | VIA_EOL);
-
-	/* set location of DMA-able scatter-gather info table */
-	DPRINTK ("outl (0x%X, 0x%04lX)\n",
-		chan->sgt_handle, chan->iobase + VIA_PCM_TABLE_ADDR);
-
-	via_ac97_wait_idle (card);
-	outl (chan->sgt_handle, chan->iobase + VIA_PCM_TABLE_ADDR);
-	udelay (20);
-	via_ac97_wait_idle (card);
-	/* load no rate adaption, stereo 16bit, set up ring slots */
-	if(card->sixchannel)
-	{
-		if(!chan->is_multi)
-		{
-			outl (0xFFFFF | (0x3 << 20) | (chan->frag_number << 24), chan->iobase + VIA_PCM_STOPRATE);
-			udelay (20);
-			via_ac97_wait_idle (card);
-		}
-	}
-
-	DPRINTK ("inl (0x%lX) = %x\n",
-		chan->iobase + VIA_PCM_TABLE_ADDR,
-		inl(chan->iobase + VIA_PCM_TABLE_ADDR));
-
-	DPRINTK ("EXIT\n");
-	return 0;
-
-err_out_nomem:
-	printk (KERN_ERR PFX "DMA buffer alloc fail, aborting\n");
-	via_chan_buffer_free (card, chan);
-	DPRINTK ("EXIT\n");
-	return -ENOMEM;
-}
-
-
-/**
- *	via_chan_free - Release a PCM channel
- *	@card: Private audio chip info
- *	@chan: Channel to be released
- *
- *	Performs all the functions necessary to clean up
- *	an initialized channel.
- *
- *	Currently these functions include disabled any
- *	active DMA operations, setting the PCM channel
- *	back to a known state, and releasing any allocated
- *	sound buffers.
- */
-
-static void via_chan_free (struct via_info *card, struct via_channel *chan)
-{
-	DPRINTK ("ENTER\n");
-
-	spin_lock_irq (&card->lock);
-
-	/* stop any existing channel output */
-	via_chan_status_clear (chan->iobase);
-	via_chan_stop (chan->iobase);
-	via_chan_status_clear (chan->iobase);
-
-	spin_unlock_irq (&card->lock);
-
-	synchronize_irq(card->pdev->irq);
-
-	DPRINTK ("EXIT\n");
-}
-
-static void via_chan_buffer_free (struct via_info *card, struct via_channel *chan)
-{
-	int i;
-
-        DPRINTK ("ENTER\n");
-
-	/* zero location of DMA-able scatter-gather info table */
-	via_ac97_wait_idle(card);
-	outl (0, chan->iobase + VIA_PCM_TABLE_ADDR);
-
-	for (i = 0; i < chan->page_number; i++)
-		if (chan->pgtbl[i].cpuaddr) {
-			pci_free_consistent (card->pdev, PAGE_SIZE,
-					     chan->pgtbl[i].cpuaddr,
-					     chan->pgtbl[i].handle);
-			chan->pgtbl[i].cpuaddr = NULL;
-			chan->pgtbl[i].handle = 0;
-		}
-
-	chan->page_number = 0;
-
-	if (chan->sgtable) {
-		pci_free_consistent (card->pdev,
-			(sizeof (struct via_sgd_table) * chan->frag_number),
-			(void*)chan->sgtable, chan->sgt_handle);
-		chan->sgtable = NULL;
-	}
-
-	DPRINTK ("EXIT\n");
-}
-
-
-/**
- *	via_chan_pcm_fmt - Update PCM channel settings
- *	@chan: Channel to be updated
- *	@reset: Boolean.  If non-zero, channel will be reset
- *		to 8-bit mono mode.
- *
- *	Stores the settings of the current PCM format,
- *	8-bit or 16-bit, and mono/stereo, into the
- *	hardware settings for the specified channel.
- *	If @reset is non-zero, the channel is reset
- *	to 8-bit mono mode.  Otherwise, the channel
- *	is set to the values stored in the channel
- *	information struct @chan.
- */
-
-static void via_chan_pcm_fmt (struct via_channel *chan, int reset)
-{
-	DPRINTK ("ENTER, pcm_fmt=0x%02X, reset=%s\n",
-		 chan->pcm_fmt, reset ? "yes" : "no");
-
-	assert (chan != NULL);
-
-	if (reset)
-	{
-		/* reset to 8-bit mono mode */
-		chan->pcm_fmt = 0;
-		chan->channels = 1;
-	}
-
-	/* enable interrupts on FLAG and EOL */
-	chan->pcm_fmt |= VIA_CHAN_TYPE_MASK;
-
-	/* if we are recording, enable recording fifo bit */
-	if (chan->is_record)
-		chan->pcm_fmt |= VIA_PCM_REC_FIFO;
-	/* set interrupt select bits where applicable (PCM in & out channels) */
-	if (!chan->is_record)
-		chan->pcm_fmt |= VIA_CHAN_TYPE_INT_SELECT;
-	
-	DPRINTK("SET FMT - %02x %02x\n", chan->intmask , chan->is_multi);
-	
-	if(chan->intmask)
-	{
-		u32 m;
-
-		/*
-		 *	Channel 0x4 is up to 6 x 16bit and has to be
-		 *	programmed differently 
-		 */
-		 		
-		if(chan->is_multi)
-		{
-			u8 c = 0;
-			
-			/*
-			 *	Load the type bit for num channels
-			 *	and 8/16bit
-			 */
-			 
-			if(chan->pcm_fmt & VIA_PCM_FMT_16BIT)
-				c = 1 << 7;
-			if(chan->pcm_fmt & VIA_PCM_FMT_STEREO)
-				c |= (2<<4);
-			else
-				c |= (1<<4);
-				
-			outb(c, chan->iobase + VIA_PCM_TYPE);
-			
-			/*
-			 *	Set the channel steering
-			 *	Mono
-			 *		Channel 0 to slot 3
-			 *		Channel 0 to slot 4
-			 *	Stereo
-			 *		Channel 0 to slot 3
-			 *		Channel 1 to slot 4
-			 */
-			 
-			switch(chan->channels)
-			{
-				case 1:
-					outl(0xFF000000 | (1<<0) | (1<<4) , chan->iobase + VIA_PCM_STOPRATE);
-					break;
-				case 2:
-					outl(0xFF000000 | (1<<0) | (2<<4) , chan->iobase + VIA_PCM_STOPRATE);
-					break;
-				case 4:
-					outl(0xFF000000 | (1<<0) | (2<<4) | (3<<8) | (4<<12), chan->iobase + VIA_PCM_STOPRATE);
-					break;
-				case 6:
-					outl(0xFF000000 | (1<<0) | (2<<4) | (5<<8) | (6<<12) | (3<<16) | (4<<20), chan->iobase + VIA_PCM_STOPRATE);
-					break;
-			}				
-		}
-		else
-		{
-			/*
-			 *	New style, turn off channel volume
-			 *	control, set bits in the right register
-			 */	
-			outb(0x0, chan->iobase + VIA_PCM_LEFTVOL);
-			outb(0x0, chan->iobase + VIA_PCM_RIGHTVOL);
-
-			m = inl(chan->iobase + VIA_PCM_STOPRATE);
-			m &= ~(3<<20);
-			if(chan->pcm_fmt & VIA_PCM_FMT_STEREO)
-				m |= (1 << 20);
-			if(chan->pcm_fmt & VIA_PCM_FMT_16BIT)
-				m |= (1 << 21);
-			outl(m, chan->iobase + VIA_PCM_STOPRATE);
-		}		
-	}
-	else
-		outb (chan->pcm_fmt, chan->iobase + VIA_PCM_TYPE);
-
-
-	DPRINTK ("EXIT, pcm_fmt = 0x%02X, reg = 0x%02X\n",
-		 chan->pcm_fmt,
-		 inb (chan->iobase + VIA_PCM_TYPE));
-}
-
-
-/**
- *	via_chan_clear - Stop DMA channel operation, and reset pointers
- *	@card: the chip to accessed
- *	@chan: Channel to be cleared
- *
- *	Call via_chan_stop to halt DMA operations, and then resets
- *	all software pointers which track DMA operation.
- */
-
-static void via_chan_clear (struct via_info *card, struct via_channel *chan)
-{
-	DPRINTK ("ENTER\n");
-	via_chan_stop (chan->iobase);
-	via_chan_buffer_free(card, chan);
-	chan->is_active = 0;
-	chan->is_mapped = 0;
-	chan->is_enabled = 1;
-	chan->slop_len = 0;
-	chan->sw_ptr = 0;
-	chan->n_irqs = 0;
-	atomic_set (&chan->hw_ptr, 0);
-	DPRINTK ("EXIT\n");
-}
-
-
-/**
- *	via_chan_set_speed - Set PCM sample rate for given channel
- *	@card: Private info for specified board
- *	@chan: Channel whose sample rate will be adjusted
- *	@val: New sample rate, in Khz
- *
- *	Helper function for the %SNDCTL_DSP_SPEED ioctl.  OSS semantics
- *	demand that all audio operations halt (if they are not already
- *	halted) when the %SNDCTL_DSP_SPEED is given.
- *
- *	This function halts all audio operations for the given channel
- *	@chan, and then calls via_set_rate to set the audio hardware
- *	to the new rate.
- */
-
-static int via_chan_set_speed (struct via_info *card,
-			       struct via_channel *chan, int val)
-{
-	DPRINTK ("ENTER, requested rate = %d\n", val);
-
-	via_chan_clear (card, chan);
-
-	val = via_set_rate (card->ac97, chan, val);
-
-	DPRINTK ("EXIT, returning %d\n", val);
-	return val;
-}
-
-
-/**
- *	via_chan_set_fmt - Set PCM sample size for given channel
- *	@card: Private info for specified board
- *	@chan: Channel whose sample size will be adjusted
- *	@val: New sample size, use the %AFMT_xxx constants
- *
- *	Helper function for the %SNDCTL_DSP_SETFMT ioctl.  OSS semantics
- *	demand that all audio operations halt (if they are not already
- *	halted) when the %SNDCTL_DSP_SETFMT is given.
- *
- *	This function halts all audio operations for the given channel
- *	@chan, and then calls via_chan_pcm_fmt to set the audio hardware
- *	to the new sample size, either 8-bit or 16-bit.
- */
-
-static int via_chan_set_fmt (struct via_info *card,
-			     struct via_channel *chan, int val)
-{
-	DPRINTK ("ENTER, val=%s\n",
-		 val == AFMT_U8 ? "AFMT_U8" :
-	 	 val == AFMT_S16_LE ? "AFMT_S16_LE" :
-		 "unknown");
-
-	via_chan_clear (card, chan);
-
-	assert (val != AFMT_QUERY); /* this case is handled elsewhere */
-
-	switch (val) {
-	case AFMT_S16_LE:
-		if ((chan->pcm_fmt & VIA_PCM_FMT_16BIT) == 0) {
-			chan->pcm_fmt |= VIA_PCM_FMT_16BIT;
-			via_chan_pcm_fmt (chan, 0);
-		}
-		break;
-
-	case AFMT_U8:
-		if (chan->pcm_fmt & VIA_PCM_FMT_16BIT) {
-			chan->pcm_fmt &= ~VIA_PCM_FMT_16BIT;
-			via_chan_pcm_fmt (chan, 0);
-		}
-		break;
-
-	default:
-		DPRINTK ("unknown AFMT: 0x%X\n", val);
-		val = AFMT_S16_LE;
-	}
-
-	DPRINTK ("EXIT\n");
-	return val;
-}
-
-
-/**
- *	via_chan_set_stereo - Enable or disable stereo for a DMA channel
- *	@card: Private info for specified board
- *	@chan: Channel whose stereo setting will be adjusted
- *	@val: New sample size, use the %AFMT_xxx constants
- *
- *	Helper function for the %SNDCTL_DSP_CHANNELS and %SNDCTL_DSP_STEREO ioctls.  OSS semantics
- *	demand that all audio operations halt (if they are not already
- *	halted) when %SNDCTL_DSP_CHANNELS or SNDCTL_DSP_STEREO is given.
- *
- *	This function halts all audio operations for the given channel
- *	@chan, and then calls via_chan_pcm_fmt to set the audio hardware
- *	to enable or disable stereo.
- */
-
-static int via_chan_set_stereo (struct via_info *card,
-			        struct via_channel *chan, int val)
-{
-	DPRINTK ("ENTER, channels = %d\n", val);
-
-	via_chan_clear (card, chan);
-
-	switch (val) {
-
-	/* mono */
-	case 1:
-		chan->pcm_fmt &= ~VIA_PCM_FMT_STEREO;
-		chan->channels = 1;
-		via_chan_pcm_fmt (chan, 0);
-		break;
-
-	/* stereo */
-	case 2:
-		chan->pcm_fmt |= VIA_PCM_FMT_STEREO;
-		chan->channels = 2;
-		via_chan_pcm_fmt (chan, 0);
-		break;
-
-	case 4:
-	case 6:
-		if(chan->is_multi)
-		{
-			chan->pcm_fmt |= VIA_PCM_FMT_STEREO;
-			chan->channels = val;
-			break;
-		}
-	/* unknown */
-	default:
-		val = -EINVAL;
-		break;
-	}
-
-	DPRINTK ("EXIT, returning %d\n", val);
-	return val;
-}
-
-static int via_chan_set_buffering (struct via_info *card,
-                                struct via_channel *chan, int val)
-{
-	int shift;
-
-        DPRINTK ("ENTER\n");
-
-	/* in both cases the buffer cannot be changed */
-	if (chan->is_active || chan->is_mapped) {
-		DPRINTK ("EXIT\n");
-		return -EINVAL;
-	}
-
-	/* called outside SETFRAGMENT */
-	/* set defaults or do nothing */
-	if (val < 0) {
-
-		if (chan->frag_size && chan->frag_number)
-			goto out;
-
-		DPRINTK ("\n");
-
-		chan->frag_size = (VIA_DEFAULT_FRAG_TIME * chan->rate * chan->channels
-				   * ((chan->pcm_fmt & VIA_PCM_FMT_16BIT) ? 2 : 1)) / 1000 - 1;
-
-		shift = 0;
-		while (chan->frag_size) {
-			chan->frag_size >>= 1;
-			shift++;
-		}
-		chan->frag_size = 1 << shift;
-
-		chan->frag_number = (VIA_DEFAULT_BUFFER_TIME / VIA_DEFAULT_FRAG_TIME);
-
-		DPRINTK ("setting default values %d %d\n", chan->frag_size, chan->frag_number);
-	} else {
-		chan->frag_size = 1 << (val & 0xFFFF);
-		chan->frag_number = (val >> 16) & 0xFFFF;
-
-		DPRINTK ("using user values %d %d\n", chan->frag_size, chan->frag_number);
-	}
-
-	/* quake3 wants frag_number to be a power of two */
-	shift = 0;
-	while (chan->frag_number) {
-		chan->frag_number >>= 1;
-		shift++;
-	}
-	chan->frag_number = 1 << shift;
-
-	if (chan->frag_size > VIA_MAX_FRAG_SIZE)
-		chan->frag_size = VIA_MAX_FRAG_SIZE;
-	else if (chan->frag_size < VIA_MIN_FRAG_SIZE)
-		chan->frag_size = VIA_MIN_FRAG_SIZE;
-
-	if (chan->frag_number < VIA_MIN_FRAG_NUMBER)
-                chan->frag_number = VIA_MIN_FRAG_NUMBER;
-        if (chan->frag_number > VIA_MAX_FRAG_NUMBER)
-        	chan->frag_number = VIA_MAX_FRAG_NUMBER;
-
-	if ((chan->frag_number * chan->frag_size) / PAGE_SIZE > VIA_MAX_BUFFER_DMA_PAGES)
-		chan->frag_number = (VIA_MAX_BUFFER_DMA_PAGES * PAGE_SIZE) / chan->frag_size;
-
-out:
-	if (chan->is_record)
-		atomic_set (&chan->n_frags, 0);
-	else
-		atomic_set (&chan->n_frags, chan->frag_number);
-
-	DPRINTK ("EXIT\n");
-
-	return 0;
-}
-
-#ifdef VIA_CHAN_DUMP_BUFS
-/**
- *	via_chan_dump_bufs - Display DMA table contents
- *	@chan: Channel whose DMA table will be displayed
- *
- *	Debugging function which displays the contents of the
- *	scatter-gather DMA table for the given channel @chan.
- */
-
-static void via_chan_dump_bufs (struct via_channel *chan)
-{
-	int i;
-
-	for (i = 0; i < chan->frag_number; i++) {
-		DPRINTK ("#%02d: addr=%x, count=%u, flag=%d, eol=%d\n",
-			 i, chan->sgtable[i].addr,
-			 chan->sgtable[i].count & 0x00FFFFFF,
-			 chan->sgtable[i].count & VIA_FLAG ? 1 : 0,
-			 chan->sgtable[i].count & VIA_EOL ? 1 : 0);
-	}
-	DPRINTK ("buf_in_use = %d, nextbuf = %d\n",
-		 atomic_read (&chan->buf_in_use),
-		 atomic_read (&chan->sw_ptr));
-}
-#endif /* VIA_CHAN_DUMP_BUFS */
-
-
-/**
- *	via_chan_flush_frag - Flush partially-full playback buffer to hardware
- *	@chan: Channel whose DMA table will be flushed
- *
- *	Flushes partially-full playback buffer to hardware.
- */
-
-static void via_chan_flush_frag (struct via_channel *chan)
-{
-	DPRINTK ("ENTER\n");
-
-	assert (chan->slop_len > 0);
-
-	if (chan->sw_ptr == (chan->frag_number - 1))
-		chan->sw_ptr = 0;
-	else
-		chan->sw_ptr++;
-
-	chan->slop_len = 0;
-
-	assert (atomic_read (&chan->n_frags) > 0);
-	atomic_dec (&chan->n_frags);
-
-	DPRINTK ("EXIT\n");
-}
-
-
-
-/**
- *	via_chan_maybe_start - Initiate audio hardware DMA operation
- *	@chan: Channel whose DMA is to be started
- *
- *	Initiate DMA operation, if the DMA engine for the given
- *	channel @chan is not already active.
- */
-
-static inline void via_chan_maybe_start (struct via_channel *chan)
-{
-	assert (chan->is_active == sg_active(chan->iobase));
-
-	DPRINTK ("MAYBE START %s\n", chan->name);
-	if (!chan->is_active && chan->is_enabled) {
-		chan->is_active = 1;
-		sg_begin (chan);
-		DPRINTK ("starting channel %s\n", chan->name);
-	}
-}
-
-
-/****************************************************************
- *
- * Interface to ac97-codec module
- *
- *
- */
-
-/**
- *	via_ac97_wait_idle - Wait until AC97 codec is not busy
- *	@card: Private info for specified board
- *
- *	Sleep until the AC97 codec is no longer busy.
- *	Returns the final value read from the SGD
- *	register being polled.
- */
-
-static u8 via_ac97_wait_idle (struct via_info *card)
-{
-	u8 tmp8;
-	int counter = VIA_COUNTER_LIMIT;
-
-	DPRINTK ("ENTER/EXIT\n");
-
-	assert (card != NULL);
-	assert (card->pdev != NULL);
-
-	do {
-		udelay (15);
-
-		tmp8 = inb (card->baseaddr + 0x83);
-	} while ((tmp8 & VIA_CR83_BUSY) && (counter-- > 0));
-
-	if (tmp8 & VIA_CR83_BUSY)
-		printk (KERN_WARNING PFX "timeout waiting on AC97 codec\n");
-	return tmp8;
-}
-
-
-/**
- *	via_ac97_read_reg - Read AC97 standard register
- *	@codec: Pointer to generic AC97 codec info
- *	@reg: Index of AC97 register to be read
- *
- *	Read the value of a single AC97 codec register,
- *	as defined by the Intel AC97 specification.
- *
- *	Defines the standard AC97 read-register operation
- *	required by the kernel's ac97_codec interface.
- *
- *	Returns the 16-bit value stored in the specified
- *	register.
- */
-
-static u16 via_ac97_read_reg (struct ac97_codec *codec, u8 reg)
-{
-	unsigned long data;
-	struct via_info *card;
-	int counter;
-
-	DPRINTK ("ENTER\n");
-
-	assert (codec != NULL);
-	assert (codec->private_data != NULL);
-
-	card = codec->private_data;
-	
-	spin_lock(&card->ac97_lock);
-
-	/* Every time we write to register 80 we cause a transaction.
-	   The only safe way to clear the valid bit is to write it at
-	   the same time as the command */
-	data = (reg << 16) | VIA_CR80_READ | VIA_CR80_VALID;
-
-	outl (data, card->baseaddr + VIA_BASE0_AC97_CTRL);
-	udelay (20);
-
-	for (counter = VIA_COUNTER_LIMIT; counter > 0; counter--) {
-		udelay (1);
-		if ((((data = inl(card->baseaddr + VIA_BASE0_AC97_CTRL)) &
-		      (VIA_CR80_VALID|VIA_CR80_BUSY)) == VIA_CR80_VALID))
-			goto out;
-	}
-
-	printk (KERN_WARNING PFX "timeout while reading AC97 codec (0x%lX)\n", data);
-	goto err_out;
-
-out:
-	/* Once the valid bit has become set, we must wait a complete AC97
-	   frame before the data has settled. */
-	udelay(25);
-	data = (unsigned long) inl (card->baseaddr + VIA_BASE0_AC97_CTRL);
-
-	outb (0x02, card->baseaddr + 0x83);
-
-	if (((data & 0x007F0000) >> 16) == reg) {
-		DPRINTK ("EXIT, success, data=0x%lx, retval=0x%lx\n",
-			 data, data & 0x0000FFFF);
-		spin_unlock(&card->ac97_lock);
-		return data & 0x0000FFFF;
-	}
-
-	printk (KERN_WARNING "via82cxxx_audio: not our index: reg=0x%x, newreg=0x%lx\n",
-		reg, ((data & 0x007F0000) >> 16));
-
-err_out:
-	spin_unlock(&card->ac97_lock);
-	DPRINTK ("EXIT, returning 0\n");
-	return 0;
-}
-
-
-/**
- *	via_ac97_write_reg - Write AC97 standard register
- *	@codec: Pointer to generic AC97 codec info
- *	@reg: Index of AC97 register to be written
- *	@value: Value to be written to AC97 register
- *
- *	Write the value of a single AC97 codec register,
- *	as defined by the Intel AC97 specification.
- *
- *	Defines the standard AC97 write-register operation
- *	required by the kernel's ac97_codec interface.
- */
-
-static void via_ac97_write_reg (struct ac97_codec *codec, u8 reg, u16 value)
-{
-	u32 data;
-	struct via_info *card;
-	int counter;
-
-	DPRINTK ("ENTER\n");
-
-	assert (codec != NULL);
-	assert (codec->private_data != NULL);
-
-	card = codec->private_data;
-
-	spin_lock(&card->ac97_lock);
-	
-	data = (reg << 16) + value;
-	outl (data, card->baseaddr + VIA_BASE0_AC97_CTRL);
-	udelay (10);
-
-	for (counter = VIA_COUNTER_LIMIT; counter > 0; counter--) {
-		if ((inb (card->baseaddr + 0x83) & VIA_CR83_BUSY) == 0)
-			goto out;
-
-		udelay (15);
-	}
-
-	printk (KERN_WARNING PFX "timeout after AC97 codec write (0x%X, 0x%X)\n", reg, value);
-
-out:
-	spin_unlock(&card->ac97_lock);
-	DPRINTK ("EXIT\n");
-}
-
-
-static int via_mixer_open (struct inode *inode, struct file *file)
-{
-	int minor = iminor(inode);
-	struct via_info *card;
-	struct pci_dev *pdev = NULL;
-	struct pci_driver *drvr;
-
-	DPRINTK ("ENTER\n");
-
-	while ((pdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL) {
-		drvr = pci_dev_driver (pdev);
-		if (drvr == &via_driver) {
-			assert (pci_get_drvdata (pdev) != NULL);
-
-			card = pci_get_drvdata (pdev);
-			if (card->ac97->dev_mixer == minor)
-				goto match;
-		}
-	}
-
-	DPRINTK ("EXIT, returning -ENODEV\n");
-	return -ENODEV;
-
-match:
-	pci_dev_put(pdev);
-	file->private_data = card->ac97;
-
-	DPRINTK ("EXIT, returning 0\n");
-	return nonseekable_open(inode, file);
-}
-
-static int via_mixer_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
-			    unsigned long arg)
-{
-	struct ac97_codec *codec = file->private_data;
-	struct via_info *card;
-	int nonblock = (file->f_flags & O_NONBLOCK);
-	int rc;
-
-	DPRINTK ("ENTER\n");
-
-	assert (codec != NULL);
-	card = codec->private_data;
-	assert (card != NULL);
-
-	rc = via_syscall_down (card, nonblock);
-	if (rc) goto out;
-	
-#if 0
-	/*
-	 *	Intercept volume control on 8233 and 8235
-	 */
-	if(card->volume)
-	{
-		switch(cmd)
-		{
-			case SOUND_MIXER_READ_VOLUME:
-				return card->mixer_vol;
-			case SOUND_MIXER_WRITE_VOLUME:
-			{
-				int v;
-				if(get_user(v, (int *)arg))
-				{
-					rc = -EFAULT;
-					goto out;
-				}
-				card->mixer_vol = v;
-			}
-		}
-	}		
-#endif
-	rc = codec->mixer_ioctl(codec, cmd, arg);
-
-	mutex_unlock(&card->syscall_mutex);
-
-out:
-	DPRINTK ("EXIT, returning %d\n", rc);
-	return rc;
-}
-
-
-static const struct file_operations via_mixer_fops = {
-	.owner		= THIS_MODULE,
-	.open		= via_mixer_open,
-	.llseek		= no_llseek,
-	.ioctl		= via_mixer_ioctl,
-};
-
-
-static int __devinit via_ac97_reset (struct via_info *card)
-{
-	struct pci_dev *pdev = card->pdev;
-	u8 tmp8;
-	u16 tmp16;
-
-	DPRINTK ("ENTER\n");
-
-	assert (pdev != NULL);
-
-#ifndef NDEBUG
-	{
-		u8 r40,r41,r42,r43,r44,r48;
-		pci_read_config_byte (card->pdev, 0x40, &r40);
-		pci_read_config_byte (card->pdev, 0x41, &r41);
-		pci_read_config_byte (card->pdev, 0x42, &r42);
-		pci_read_config_byte (card->pdev, 0x43, &r43);
-		pci_read_config_byte (card->pdev, 0x44, &r44);
-		pci_read_config_byte (card->pdev, 0x48, &r48);
-		DPRINTK ("PCI config: %02X %02X %02X %02X %02X %02X\n",
-			r40,r41,r42,r43,r44,r48);
-
-		spin_lock_irq (&card->lock);
-		DPRINTK ("regs==%02X %02X %02X %08X %08X %08X %08X\n",
-			 inb (card->baseaddr + 0x00),
-			 inb (card->baseaddr + 0x01),
-			 inb (card->baseaddr + 0x02),
-			 inl (card->baseaddr + 0x04),
-			 inl (card->baseaddr + 0x0C),
-			 inl (card->baseaddr + 0x80),
-			 inl (card->baseaddr + 0x84));
-		spin_unlock_irq (&card->lock);
-
-	}
-#endif
-
-        /*
-         * Reset AC97 controller: enable, disable, enable,
-         * pausing after each command for good luck.  Only
-	 * do this if the codec is not ready, because it causes
-	 * loud pops and such due to such a hard codec reset.
-         */
-	pci_read_config_byte (pdev, VIA_ACLINK_STATUS, &tmp8);
-	if ((tmp8 & VIA_CR40_AC97_READY) == 0) {
-        	pci_write_config_byte (pdev, VIA_ACLINK_CTRL,
-				       VIA_CR41_AC97_ENABLE |
-                		       VIA_CR41_AC97_RESET |
-				       VIA_CR41_AC97_WAKEUP);
-        	udelay (100);
-
-        	pci_write_config_byte (pdev, VIA_ACLINK_CTRL, 0);
-        	udelay (100);
-
-        	pci_write_config_byte (pdev, VIA_ACLINK_CTRL,
-				       VIA_CR41_AC97_ENABLE |
-				       VIA_CR41_PCM_ENABLE |
-                		       VIA_CR41_VRA | VIA_CR41_AC97_RESET);
-        	udelay (100);
-	}
-
-	/* Make sure VRA is enabled, in case we didn't do a
-	 * complete codec reset, above
-	 */
-	pci_read_config_byte (pdev, VIA_ACLINK_CTRL, &tmp8);
-	if (((tmp8 & VIA_CR41_VRA) == 0) ||
-	    ((tmp8 & VIA_CR41_AC97_ENABLE) == 0) ||
-	    ((tmp8 & VIA_CR41_PCM_ENABLE) == 0) ||
-	    ((tmp8 & VIA_CR41_AC97_RESET) == 0)) {
-        	pci_write_config_byte (pdev, VIA_ACLINK_CTRL,
-				       VIA_CR41_AC97_ENABLE |
-				       VIA_CR41_PCM_ENABLE |
-                		       VIA_CR41_VRA | VIA_CR41_AC97_RESET);
-        	udelay (100);
-	}
-
-	if(card->legacy)
-	{
-#if 0 /* this breaks on K7M */
-		/* disable legacy stuff */
-		pci_write_config_byte (pdev, 0x42, 0x00);
-		udelay(10);
-#endif
-
-		/* route FM trap to IRQ, disable FM trap */
-		pci_write_config_byte (pdev, 0x48, 0x05);
-		udelay(10);
-	}
-	
-	/* disable all codec GPI interrupts */
-	outl (0, pci_resource_start (pdev, 0) + 0x8C);
-
-	/* WARNING: this line is magic.  Remove this
-	 * and things break. */
-	/* enable variable rate */
- 	tmp16 = via_ac97_read_reg (card->ac97, AC97_EXTENDED_STATUS);
- 	if ((tmp16 & 1) == 0)
- 		via_ac97_write_reg (card->ac97, AC97_EXTENDED_STATUS, tmp16 | 1);
-
-	DPRINTK ("EXIT, returning 0\n");
-	return 0;
-}
-
-
-static void via_ac97_codec_wait (struct ac97_codec *codec)
-{
-	assert (codec->private_data != NULL);
-	via_ac97_wait_idle (codec->private_data);
-}
-
-
-static int __devinit via_ac97_init (struct via_info *card)
-{
-	int rc;
-	u16 tmp16;
-
-	DPRINTK ("ENTER\n");
-
-	assert (card != NULL);
-
-	card->ac97 = ac97_alloc_codec();
-	if(card->ac97 == NULL)
-		return -ENOMEM;
-		
-	card->ac97->private_data = card;
-	card->ac97->codec_read = via_ac97_read_reg;
-	card->ac97->codec_write = via_ac97_write_reg;
-	card->ac97->codec_wait = via_ac97_codec_wait;
-
-	card->ac97->dev_mixer = register_sound_mixer (&via_mixer_fops, -1);
-	if (card->ac97->dev_mixer < 0) {
-		printk (KERN_ERR PFX "unable to register AC97 mixer, aborting\n");
-		DPRINTK ("EXIT, returning -EIO\n");
-		ac97_release_codec(card->ac97);
-		return -EIO;
-	}
-
-	rc = via_ac97_reset (card);
-	if (rc) {
-		printk (KERN_ERR PFX "unable to reset AC97 codec, aborting\n");
-		goto err_out;
-	}
-	
-	mdelay(10);
-	
-	if (ac97_probe_codec (card->ac97) == 0) {
-		printk (KERN_ERR PFX "unable to probe AC97 codec, aborting\n");
-		rc = -EIO;
-		goto err_out;
-	}
-
-	/* enable variable rate */
-	tmp16 = via_ac97_read_reg (card->ac97, AC97_EXTENDED_STATUS);
-	via_ac97_write_reg (card->ac97, AC97_EXTENDED_STATUS, tmp16 | 1);
-
- 	/*
- 	 * If we cannot enable VRA, we have a locked-rate codec.
- 	 * We try again to enable VRA before assuming so, however.
- 	 */
- 	tmp16 = via_ac97_read_reg (card->ac97, AC97_EXTENDED_STATUS);
- 	if ((tmp16 & 1) == 0) {
- 		via_ac97_write_reg (card->ac97, AC97_EXTENDED_STATUS, tmp16 | 1);
- 		tmp16 = via_ac97_read_reg (card->ac97, AC97_EXTENDED_STATUS);
- 		if ((tmp16 & 1) == 0) {
- 			card->locked_rate = 1;
- 			printk (KERN_WARNING PFX "Codec rate locked at 48Khz\n");
- 		}
- 	}
-
-	DPRINTK ("EXIT, returning 0\n");
-	return 0;
-
-err_out:
-	unregister_sound_mixer (card->ac97->dev_mixer);
-	DPRINTK ("EXIT, returning %d\n", rc);
-	ac97_release_codec(card->ac97);
-	return rc;
-}
-
-
-static void via_ac97_cleanup (struct via_info *card)
-{
-	DPRINTK ("ENTER\n");
-
-	assert (card != NULL);
-	assert (card->ac97->dev_mixer >= 0);
-
-	unregister_sound_mixer (card->ac97->dev_mixer);
-	ac97_release_codec(card->ac97);
-
-	DPRINTK ("EXIT\n");
-}
-
-
-
-/****************************************************************
- *
- * Interrupt-related code
- *
- */
-
-/**
- *	via_intr_channel - handle an interrupt for a single channel
- *      @card: unused
- *	@chan: handle interrupt for this channel
- *
- *	This is the "meat" of the interrupt handler,
- *	containing the actions taken each time an interrupt
- *	occurs.  All communication and coordination with
- *	userspace takes place here.
- *
- *	Locking: inside card->lock
- */
-
-static void via_intr_channel (struct via_info *card, struct via_channel *chan)
-{
-	u8 status;
-	int n;
-	
-	/* check pertinent bits of status register for action bits */
-	status = inb (chan->iobase) & (VIA_SGD_FLAG | VIA_SGD_EOL | VIA_SGD_STOPPED);
-	if (!status)
-		return;
-
-	/* acknowledge any flagged bits ASAP */
-	outb (status, chan->iobase);
-
-	if (!chan->sgtable) /* XXX: temporary solution */
-		return;
-
-	/* grab current h/w ptr value */
-	n = atomic_read (&chan->hw_ptr);
-
-	/* sanity check: make sure our h/w ptr doesn't have a weird value */
-	assert (n >= 0);
-	assert (n < chan->frag_number);
-
-	
-	/* reset SGD data structure in memory to reflect a full buffer,
-	 * and advance the h/w ptr, wrapping around to zero if needed
-	 */
-	if (n == (chan->frag_number - 1)) {
-		chan->sgtable[n].count = cpu_to_le32(chan->frag_size | VIA_EOL);
-		atomic_set (&chan->hw_ptr, 0);
-	} else {
-		chan->sgtable[n].count = cpu_to_le32(chan->frag_size | VIA_FLAG);
-		atomic_inc (&chan->hw_ptr);
-	}
-
-	/* accounting crap for SNDCTL_DSP_GETxPTR */
-	chan->n_irqs++;
-	chan->bytes += chan->frag_size;
-	/* FIXME - signed overflow is undefined */
-	if (chan->bytes < 0) /* handle overflow of 31-bit value */
-		chan->bytes = chan->frag_size;
-	/* all following checks only occur when not in mmap(2) mode */
-	if (!chan->is_mapped)
-	{
-		/* If we are recording, then n_frags represents the number
-		 * of fragments waiting to be handled by userspace.
-		 * If we are playback, then n_frags represents the number
-		 * of fragments remaining to be filled by userspace.
-		 * We increment here.  If we reach max number of fragments,
-		 * this indicates an underrun/overrun.  For this case under OSS,
-		 * we stop the record/playback process.
-		 */
-		if (atomic_read (&chan->n_frags) < chan->frag_number)
-			atomic_inc (&chan->n_frags);
-		assert (atomic_read (&chan->n_frags) <= chan->frag_number);
-		if (atomic_read (&chan->n_frags) == chan->frag_number) {
-			chan->is_active = 0;
-			via_chan_stop (chan->iobase);
-		}
-	}
-	/* wake up anyone listening to see when interrupts occur */
-	wake_up_all (&chan->wait);
-
-	DPRINTK ("%s intr, status=0x%02X, hwptr=0x%lX, chan->hw_ptr=%d\n",
-		 chan->name, status, (long) inl (chan->iobase + 0x04),
-		 atomic_read (&chan->hw_ptr));
-
-	DPRINTK ("%s intr, channel n_frags == %d, missed %d\n", chan->name,
-		 atomic_read (&chan->n_frags), missed);
-}
-
-
-static irqreturn_t  via_interrupt(int irq, void *dev_id)
-{
-	struct via_info *card = dev_id;
-	u32 status32;
-
-	/* to minimize interrupt sharing costs, we use the SGD status
-	 * shadow register to check the status of all inputs and
-	 * outputs with a single 32-bit bus read.  If no interrupt
-	 * conditions are flagged, we exit immediately
-	 */
-	status32 = inl (card->baseaddr + VIA_BASE0_SGD_STATUS_SHADOW);
-	if (!(status32 & VIA_INTR_MASK))
-        {
-#ifdef CONFIG_MIDI_VIA82CXXX
-	    	 if (card->midi_devc)
-                    	uart401intr(irq, card->midi_devc);
-#endif
-		return IRQ_HANDLED;
-    	}
-	DPRINTK ("intr, status32 == 0x%08X\n", status32);
-
-	/* synchronize interrupt handling under SMP.  this spinlock
-	 * goes away completely on UP
-	 */
-	spin_lock (&card->lock);
-
-	if (status32 & VIA_INTR_OUT)
-		via_intr_channel (card, &card->ch_out);
-	if (status32 & VIA_INTR_IN)
-		via_intr_channel (card, &card->ch_in);
-	if (status32 & VIA_INTR_FM)
-		via_intr_channel (card, &card->ch_fm);
-
-	spin_unlock (&card->lock);
-	
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t via_new_interrupt(int irq, void *dev_id)
-{
-	struct via_info *card = dev_id;
-	u32 status32;
-
-	/* to minimize interrupt sharing costs, we use the SGD status
-	 * shadow register to check the status of all inputs and
-	 * outputs with a single 32-bit bus read.  If no interrupt
-	 * conditions are flagged, we exit immediately
-	 */
-	status32 = inl (card->baseaddr + VIA_BASE0_SGD_STATUS_SHADOW);
-	if (!(status32 & VIA_NEW_INTR_MASK))
-		return IRQ_NONE;
-	/*
-	 * goes away completely on UP
-	 */
-	spin_lock (&card->lock);
-
-	via_intr_channel (card, &card->ch_out);
-	via_intr_channel (card, &card->ch_in);
-	via_intr_channel (card, &card->ch_fm);
-
-	spin_unlock (&card->lock);
-	return IRQ_HANDLED;
-}
-
-
-/**
- *	via_interrupt_init - Initialize interrupt handling
- *	@card: Private info for specified board
- *
- *	Obtain and reserve IRQ for using in handling audio events.
- *	Also, disable any IRQ-generating resources, to make sure
- *	we don't get interrupts before we want them.
- */
-
-static int via_interrupt_init (struct via_info *card)
-{
-	u8 tmp8;
-
-	DPRINTK ("ENTER\n");
-
-	assert (card != NULL);
-	assert (card->pdev != NULL);
-
-	/* check for sane IRQ number. can this ever happen? */
-	if (card->pdev->irq < 2) {
-		printk (KERN_ERR PFX "insane IRQ %d, aborting\n",
-			card->pdev->irq);
-		DPRINTK ("EXIT, returning -EIO\n");
-		return -EIO;
-	}
-
-	/* VIA requires this is done */
-	pci_write_config_byte(card->pdev, PCI_INTERRUPT_LINE, card->pdev->irq);
-	
-	if(card->legacy)
-	{
-		/* make sure FM irq is not routed to us */
-		pci_read_config_byte (card->pdev, VIA_FM_NMI_CTRL, &tmp8);
-		if ((tmp8 & VIA_CR48_FM_TRAP_TO_NMI) == 0) {
-			tmp8 |= VIA_CR48_FM_TRAP_TO_NMI;
-			pci_write_config_byte (card->pdev, VIA_FM_NMI_CTRL, tmp8);
-		}
-		if (request_irq (card->pdev->irq, via_interrupt, IRQF_SHARED, VIA_MODULE_NAME, card)) {
-			printk (KERN_ERR PFX "unable to obtain IRQ %d, aborting\n",
-				card->pdev->irq);
-			DPRINTK ("EXIT, returning -EBUSY\n");
-			return -EBUSY;
-		}
-	}
-	else 
-	{
-		if (request_irq (card->pdev->irq, via_new_interrupt, IRQF_SHARED, VIA_MODULE_NAME, card)) {
-			printk (KERN_ERR PFX "unable to obtain IRQ %d, aborting\n",
-				card->pdev->irq);
-			DPRINTK ("EXIT, returning -EBUSY\n");
-			return -EBUSY;
-		}
-	}
-
-	DPRINTK ("EXIT, returning 0\n");
-	return 0;
-}
-
-
-/****************************************************************
- *
- * OSS DSP device
- *
- */
-
-static const struct file_operations via_dsp_fops = {
-	.owner		= THIS_MODULE,
-	.open		= via_dsp_open,
-	.release	= via_dsp_release,
-	.read		= via_dsp_read,
-	.write		= via_dsp_write,
-	.poll		= via_dsp_poll,
-	.llseek		= no_llseek,
-	.ioctl		= via_dsp_ioctl,
-	.mmap		= via_dsp_mmap,
-};
-
-
-static int __devinit via_dsp_init (struct via_info *card)
-{
-	u8 tmp8;
-
-	DPRINTK ("ENTER\n");
-
-	assert (card != NULL);
-
-	if(card->legacy)
-	{
-		/* turn off legacy features, if not already */
-		pci_read_config_byte (card->pdev, VIA_FUNC_ENABLE, &tmp8);
-		if (tmp8 & (VIA_CR42_SB_ENABLE |  VIA_CR42_FM_ENABLE)) {
-			tmp8 &= ~(VIA_CR42_SB_ENABLE | VIA_CR42_FM_ENABLE);
-			pci_write_config_byte (card->pdev, VIA_FUNC_ENABLE, tmp8);
-		}
-	}
-
-	via_stop_everything (card);
-
-	card->dev_dsp = register_sound_dsp (&via_dsp_fops, -1);
-	if (card->dev_dsp < 0) {
-		DPRINTK ("EXIT, returning -ENODEV\n");
-		return -ENODEV;
-	}
-	DPRINTK ("EXIT, returning 0\n");
-	return 0;
-}
-
-
-static void via_dsp_cleanup (struct via_info *card)
-{
-	DPRINTK ("ENTER\n");
-
-	assert (card != NULL);
-	assert (card->dev_dsp >= 0);
-
-	via_stop_everything (card);
-
-	unregister_sound_dsp (card->dev_dsp);
-
-	DPRINTK ("EXIT\n");
-}
-
-
-static struct page * via_mm_nopage (struct vm_area_struct * vma,
-				    unsigned long address, int *type)
-{
-	struct via_info *card = vma->vm_private_data;
-	struct via_channel *chan = &card->ch_out;
-	unsigned long max_bufs;
-	struct page *dmapage;
-	unsigned long pgoff;
-	int rd, wr;
-
-	DPRINTK ("ENTER, start %lXh, ofs %lXh, pgoff %ld, addr %lXh\n",
-		 vma->vm_start,
-		 address - vma->vm_start,
-		 (address - vma->vm_start) >> PAGE_SHIFT,
-		 address);
-
-        if (address > vma->vm_end) {
-		DPRINTK ("EXIT, returning NOPAGE_SIGBUS\n");
-		return NOPAGE_SIGBUS; /* Disallow mremap */
-	}
-        if (!card) {
-		DPRINTK ("EXIT, returning NOPAGE_SIGBUS\n");
-		return NOPAGE_SIGBUS;	/* Nothing allocated */
-	}
-
-	pgoff = vma->vm_pgoff + ((address - vma->vm_start) >> PAGE_SHIFT);
-	rd = card->ch_in.is_mapped;
-	wr = card->ch_out.is_mapped;
-
-	max_bufs = chan->frag_number;
-	if (rd && wr)
-		max_bufs *= 2;
-	if (pgoff >= max_bufs)
-		return NOPAGE_SIGBUS;
-
-	/* if full-duplex (read+write) and we have two sets of bufs,
-	 * then the playback buffers come first, sez soundcard.c */
-	if (pgoff >= chan->page_number) {
-		pgoff -= chan->page_number;
-		chan = &card->ch_in;
-	} else if (!wr)
-		chan = &card->ch_in;
-
-	assert ((((unsigned long)chan->pgtbl[pgoff].cpuaddr) % PAGE_SIZE) == 0);
-
-	dmapage = virt_to_page (chan->pgtbl[pgoff].cpuaddr);
-	DPRINTK ("EXIT, returning page %p for cpuaddr %lXh\n",
-		 dmapage, (unsigned long) chan->pgtbl[pgoff].cpuaddr);
-	get_page (dmapage);
-	if (type)
-		*type = VM_FAULT_MINOR;
-	return dmapage;
-}
-
-
-#ifndef VM_RESERVED
-static int via_mm_swapout (struct page *page, struct file *filp)
-{
-	return 0;
-}
-#endif /* VM_RESERVED */
-
-
-static struct vm_operations_struct via_mm_ops = {
-	.nopage		= via_mm_nopage,
-
-#ifndef VM_RESERVED
-	.swapout	= via_mm_swapout,
-#endif
-};
-
-
-static int via_dsp_mmap(struct file *file, struct vm_area_struct *vma)
-{
-	struct via_info *card;
-	int nonblock = (file->f_flags & O_NONBLOCK);
-	int rc = -EINVAL, rd=0, wr=0;
-	unsigned long max_size, size, start, offset;
-
-	assert (file != NULL);
-	assert (vma != NULL);
-	card = file->private_data;
-	assert (card != NULL);
-
-	DPRINTK ("ENTER, start %lXh, size %ld, pgoff %ld\n",
-		 vma->vm_start,
-		 vma->vm_end - vma->vm_start,
-		 vma->vm_pgoff);
-
-	max_size = 0;
-	if (vma->vm_flags & VM_READ) {
-		rd = 1;
-		via_chan_set_buffering(card, &card->ch_in, -1);
-		via_chan_buffer_init (card, &card->ch_in);
-		max_size += card->ch_in.page_number << PAGE_SHIFT;
-	}
-	if (vma->vm_flags & VM_WRITE) {
-		wr = 1;
-		via_chan_set_buffering(card, &card->ch_out, -1);
-		via_chan_buffer_init (card, &card->ch_out);
-		max_size += card->ch_out.page_number << PAGE_SHIFT;
-	}
-
-	start = vma->vm_start;
-	offset = (vma->vm_pgoff << PAGE_SHIFT);
-	size = vma->vm_end - vma->vm_start;
-
-	/* some basic size/offset sanity checks */
-	if (size > max_size)
-		goto out;
-	if (offset > max_size - size)
-		goto out;
-
-	rc = via_syscall_down (card, nonblock);
-	if (rc) goto out;
-
-	vma->vm_ops = &via_mm_ops;
-	vma->vm_private_data = card;
-
-#ifdef VM_RESERVED
-	vma->vm_flags |= VM_RESERVED;
-#endif
-
-	if (rd)
-		card->ch_in.is_mapped = 1;
-	if (wr)
-		card->ch_out.is_mapped = 1;
-
-	mutex_unlock(&card->syscall_mutex);
-	rc = 0;
-
-out:
-	DPRINTK ("EXIT, returning %d\n", rc);
-	return rc;
-}
-
-
-static ssize_t via_dsp_do_read (struct via_info *card,
-				char __user *userbuf, size_t count,
-				int nonblock)
-{
-        DECLARE_WAITQUEUE(wait, current);
-	const char __user *orig_userbuf = userbuf;
-	struct via_channel *chan = &card->ch_in;
-	size_t size;
-	int n, tmp;
-	ssize_t ret = 0;
-
-	/* if SGD has not yet been started, start it */
-	via_chan_maybe_start (chan);
-
-handle_one_block:
-	/* just to be a nice neighbor */
-	/* Thomas Sailer:
-	 * But also to ourselves, release semaphore if we do so */
-	if (need_resched()) {
-		mutex_unlock(&card->syscall_mutex);
-		schedule ();
-		ret = via_syscall_down (card, nonblock);
-		if (ret)
-			goto out;
-	}
-
-	/* grab current channel software pointer.  In the case of
-	 * recording, this is pointing to the next buffer that
-	 * will receive data from the audio hardware.
-	 */
-	n = chan->sw_ptr;
-
-	/* n_frags represents the number of fragments waiting
-	 * to be copied to userland.  sleep until at least
-	 * one buffer has been read from the audio hardware.
-	 */
-	add_wait_queue(&chan->wait, &wait);
-	for (;;) {
-		__set_current_state(TASK_INTERRUPTIBLE);
-		tmp = atomic_read (&chan->n_frags);
-		assert (tmp >= 0);
-		assert (tmp <= chan->frag_number);
-		if (tmp)
-			break;
-		if (nonblock || !chan->is_active) {
-			ret = -EAGAIN;
-			break;
-		}
-
-		mutex_unlock(&card->syscall_mutex);
-
-		DPRINTK ("Sleeping on block %d\n", n);
-		schedule();
-
-		ret = via_syscall_down (card, nonblock);
-		if (ret)
-			break;
-
-		if (signal_pending (current)) {
-			ret = -ERESTARTSYS;
-			break;
-		}
-	}
-	set_current_state(TASK_RUNNING);
-	remove_wait_queue(&chan->wait, &wait);
-	if (ret)
-		goto out;
-
-	/* Now that we have a buffer we can read from, send
-	 * as much as sample data possible to userspace.
-	 */
-	while ((count > 0) && (chan->slop_len < chan->frag_size)) {
-		size_t slop_left = chan->frag_size - chan->slop_len;
-		void *base = chan->pgtbl[n / (PAGE_SIZE / chan->frag_size)].cpuaddr;
-		unsigned ofs = (n % (PAGE_SIZE / chan->frag_size)) * chan->frag_size;
-
-		size = (count < slop_left) ? count : slop_left;
-		if (copy_to_user (userbuf,
-				  base + ofs + chan->slop_len,
-				  size)) {
-			ret = -EFAULT;
-			goto out;
-		}
-
-		count -= size;
-		chan->slop_len += size;
-		userbuf += size;
-	}
-
-	/* If we didn't copy the buffer completely to userspace,
-	 * stop now.
-	 */
-	if (chan->slop_len < chan->frag_size)
-		goto out;
-
-	/*
-	 * If we get to this point, we copied one buffer completely
-	 * to userspace, give the buffer back to the hardware.
-	 */
-
-	/* advance channel software pointer to point to
-	 * the next buffer from which we will copy
-	 */
-	if (chan->sw_ptr == (chan->frag_number - 1))
-		chan->sw_ptr = 0;
-	else
-		chan->sw_ptr++;
-
-	/* mark one less buffer waiting to be processed */
-	assert (atomic_read (&chan->n_frags) > 0);
-	atomic_dec (&chan->n_frags);
-
-	/* we are at a block boundary, there is no fragment data */
-	chan->slop_len = 0;
-
-	DPRINTK ("Flushed block %u, sw_ptr now %u, n_frags now %d\n",
-		n, chan->sw_ptr, atomic_read (&chan->n_frags));
-
-	DPRINTK ("regs==%02X %02X %02X %08X %08X %08X %08X\n",
-		 inb (card->baseaddr + 0x00),
-		 inb (card->baseaddr + 0x01),
-		 inb (card->baseaddr + 0x02),
-		 inl (card->baseaddr + 0x04),
-		 inl (card->baseaddr + 0x0C),
-		 inl (card->baseaddr + 0x80),
-		 inl (card->baseaddr + 0x84));
-
-	if (count > 0)
-		goto handle_one_block;
-
-out:
-	return (userbuf != orig_userbuf) ? (userbuf - orig_userbuf) : ret;
-}
-
-
-static ssize_t via_dsp_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
-{
-	struct via_info *card;
-	int nonblock = (file->f_flags & O_NONBLOCK);
-	int rc;
-
-	DPRINTK ("ENTER, file=%p, buffer=%p, count=%u, ppos=%lu\n",
-		 file, buffer, count, ppos ? ((unsigned long)*ppos) : 0);
-
-	assert (file != NULL);
-	card = file->private_data;
-	assert (card != NULL);
-
-	rc = via_syscall_down (card, nonblock);
-	if (rc) goto out;
-
-	if (card->ch_in.is_mapped) {
-		rc = -ENXIO;
-		goto out_up;
-	}
-
-	via_chan_set_buffering(card, &card->ch_in, -1);
-        rc = via_chan_buffer_init (card, &card->ch_in);
-
-	if (rc)
-		goto out_up;
-
-	rc = via_dsp_do_read (card, buffer, count, nonblock);
-
-out_up:
-	mutex_unlock(&card->syscall_mutex);
-out:
-	DPRINTK ("EXIT, returning %ld\n",(long) rc);
-	return rc;
-}
-
-
-static ssize_t via_dsp_do_write (struct via_info *card,
-				 const char __user *userbuf, size_t count,
-				 int nonblock)
-{
-        DECLARE_WAITQUEUE(wait, current);
-	const char __user *orig_userbuf = userbuf;
-	struct via_channel *chan = &card->ch_out;
-	volatile struct via_sgd_table *sgtable = chan->sgtable;
-	size_t size;
-	int n, tmp;
-	ssize_t ret = 0;
-
-handle_one_block:
-	/* just to be a nice neighbor */
-	/* Thomas Sailer:
-	 * But also to ourselves, release semaphore if we do so */
-	if (need_resched()) {
-		mutex_unlock(&card->syscall_mutex);
-		schedule ();
-		ret = via_syscall_down (card, nonblock);
-		if (ret)
-			goto out;
-	}
-
-	/* grab current channel fragment pointer.  In the case of
-	 * playback, this is pointing to the next fragment that
-	 * should receive data from userland.
-	 */
-	n = chan->sw_ptr;
-
-	/* n_frags represents the number of fragments remaining
-	 * to be filled by userspace.  Sleep until
-	 * at least one fragment is available for our use.
-	 */
-	add_wait_queue(&chan->wait, &wait);
-	for (;;) {
-		__set_current_state(TASK_INTERRUPTIBLE);
-		tmp = atomic_read (&chan->n_frags);
-		assert (tmp >= 0);
-		assert (tmp <= chan->frag_number);
-		if (tmp)
-			break;
-		if (nonblock || !chan->is_active) {
-			ret = -EAGAIN;
-			break;
-		}
-
-		mutex_unlock(&card->syscall_mutex);
-
-		DPRINTK ("Sleeping on page %d, tmp==%d, ir==%d\n", n, tmp, chan->is_record);
-		schedule();
-
-		ret = via_syscall_down (card, nonblock);
-		if (ret)
-			break;
-
-		if (signal_pending (current)) {
-			ret = -ERESTARTSYS;
-			break;
-		}
-	}
-	set_current_state(TASK_RUNNING);
-	remove_wait_queue(&chan->wait, &wait);
-	if (ret)
-		goto out;
-
-	/* Now that we have at least one fragment we can write to, fill the buffer
-	 * as much as possible with data from userspace.
-	 */
-	while ((count > 0) && (chan->slop_len < chan->frag_size)) {
-		size_t slop_left = chan->frag_size - chan->slop_len;
-
-		size = (count < slop_left) ? count : slop_left;
-		if (copy_from_user (chan->pgtbl[n / (PAGE_SIZE / chan->frag_size)].cpuaddr + (n % (PAGE_SIZE / chan->frag_size)) * chan->frag_size + chan->slop_len,
-				    userbuf, size)) {
-			ret = -EFAULT;
-			goto out;
-		}
-
-		count -= size;
-		chan->slop_len += size;
-		userbuf += size;
-	}
-
-	/* If we didn't fill up the buffer with data, stop now.
-         * Put a 'stop' marker in the DMA table too, to tell the
-         * audio hardware to stop if it gets here.
-         */
-	if (chan->slop_len < chan->frag_size) {
-		sgtable[n].count = cpu_to_le32 (chan->slop_len | VIA_EOL | VIA_STOP);
-		goto out;
-	}
-
-	/*
-         * If we get to this point, we have filled a buffer with
-         * audio data, flush the buffer to audio hardware.
-         */
-
-	/* Record the true size for the audio hardware to notice */
-        if (n == (chan->frag_number - 1))
-                sgtable[n].count = cpu_to_le32 (chan->frag_size | VIA_EOL);
-        else
-                sgtable[n].count = cpu_to_le32 (chan->frag_size | VIA_FLAG);
-
-	/* advance channel software pointer to point to
-	 * the next buffer we will fill with data
-	 */
-	if (chan->sw_ptr == (chan->frag_number - 1))
-		chan->sw_ptr = 0;
-	else
-		chan->sw_ptr++;
-
-	/* mark one less buffer as being available for userspace consumption */
-	assert (atomic_read (&chan->n_frags) > 0);
-	atomic_dec (&chan->n_frags);
-
-	/* we are at a block boundary, there is no fragment data */
-	chan->slop_len = 0;
-
-	/* if SGD has not yet been started, start it */
-	via_chan_maybe_start (chan);
-
-	DPRINTK ("Flushed block %u, sw_ptr now %u, n_frags now %d\n",
-		n, chan->sw_ptr, atomic_read (&chan->n_frags));
-
-	DPRINTK ("regs==S=%02X C=%02X TP=%02X BP=%08X RT=%08X SG=%08X CC=%08X SS=%08X\n",
-		 inb (card->baseaddr + 0x00),
-		 inb (card->baseaddr + 0x01),
-		 inb (card->baseaddr + 0x02),
-		 inl (card->baseaddr + 0x04),
-		 inl (card->baseaddr + 0x08),
-		 inl (card->baseaddr + 0x0C),
-		 inl (card->baseaddr + 0x80),
-		 inl (card->baseaddr + 0x84));
-
-	if (count > 0)
-		goto handle_one_block;
-
-out:
-	if (userbuf - orig_userbuf)
-		return userbuf - orig_userbuf;
-	else
-		return ret;
-}
-
-
-static ssize_t via_dsp_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
-{
-	struct via_info *card;
-	ssize_t rc;
-	int nonblock = (file->f_flags & O_NONBLOCK);
-
-	DPRINTK ("ENTER, file=%p, buffer=%p, count=%u, ppos=%lu\n",
-		 file, buffer, count, ppos ? ((unsigned long)*ppos) : 0);
-
-	assert (file != NULL);
-	card = file->private_data;
-	assert (card != NULL);
-
-	rc = via_syscall_down (card, nonblock);
-	if (rc) goto out;
-
-	if (card->ch_out.is_mapped) {
-		rc = -ENXIO;
-		goto out_up;
-	}
-
-	via_chan_set_buffering(card, &card->ch_out, -1);
-	rc = via_chan_buffer_init (card, &card->ch_out);
-
-	if (rc)
-		goto out_up;
-
-	rc = via_dsp_do_write (card, buffer, count, nonblock);
-
-out_up:
-	mutex_unlock(&card->syscall_mutex);
-out:
-	DPRINTK ("EXIT, returning %ld\n",(long) rc);
-	return rc;
-}
-
-
-static unsigned int via_dsp_poll(struct file *file, struct poll_table_struct *wait)
-{
-	struct via_info *card;
-	struct via_channel *chan;
-	unsigned int mask = 0;
-
-	DPRINTK ("ENTER\n");
-
-	assert (file != NULL);
-	card = file->private_data;
-	assert (card != NULL);
-
-	if (file->f_mode & FMODE_READ) {
-		chan = &card->ch_in;
-		if (sg_active (chan->iobase))
-	                poll_wait(file, &chan->wait, wait);
-		if (atomic_read (&chan->n_frags) > 0)
-			mask |= POLLIN | POLLRDNORM;
-	}
-
-	if (file->f_mode & FMODE_WRITE) {
-		chan = &card->ch_out;
-		if (sg_active (chan->iobase))
-	                poll_wait(file, &chan->wait, wait);
-		if (atomic_read (&chan->n_frags) > 0)
-			mask |= POLLOUT | POLLWRNORM;
-	}
-
-	DPRINTK ("EXIT, returning %u\n", mask);
-	return mask;
-}
-
-
-/**
- *	via_dsp_drain_playback - sleep until all playback samples are flushed
- *	@card: Private info for specified board
- *	@chan: Channel to drain
- *	@nonblock: boolean, non-zero if O_NONBLOCK is set
- *
- *	Sleeps until all playback has been flushed to the audio
- *	hardware.
- *
- *	Locking: inside card->syscall_mutex
- */
-
-static int via_dsp_drain_playback (struct via_info *card,
-				   struct via_channel *chan, int nonblock)
-{
-        DECLARE_WAITQUEUE(wait, current);
-	int ret = 0;
-
-	DPRINTK ("ENTER, nonblock = %d\n", nonblock);
-
-	if (chan->slop_len > 0)
-		via_chan_flush_frag (chan);
-
-	if (atomic_read (&chan->n_frags) == chan->frag_number)
-		goto out;
-
-	via_chan_maybe_start (chan);
-
-	add_wait_queue(&chan->wait, &wait);
-	for (;;) {
-		DPRINTK ("FRAGS %d FRAGNUM %d\n", atomic_read(&chan->n_frags), chan->frag_number);
-		__set_current_state(TASK_INTERRUPTIBLE);
-		if (atomic_read (&chan->n_frags) >= chan->frag_number)
-			break;
-
-		if (nonblock) {
-			DPRINTK ("EXIT, returning -EAGAIN\n");
-			ret = -EAGAIN;
-			break;
-		}
-
-#ifdef VIA_DEBUG
-		{
-		u8 r40,r41,r42,r43,r44,r48;
-		pci_read_config_byte (card->pdev, 0x40, &r40);
-		pci_read_config_byte (card->pdev, 0x41, &r41);
-		pci_read_config_byte (card->pdev, 0x42, &r42);
-		pci_read_config_byte (card->pdev, 0x43, &r43);
-		pci_read_config_byte (card->pdev, 0x44, &r44);
-		pci_read_config_byte (card->pdev, 0x48, &r48);
-		DPRINTK ("PCI config: %02X %02X %02X %02X %02X %02X\n",
-			r40,r41,r42,r43,r44,r48);
-
-		DPRINTK ("regs==%02X %02X %02X %08X %08X %08X %08X\n",
-			 inb (card->baseaddr + 0x00),
-			 inb (card->baseaddr + 0x01),
-			 inb (card->baseaddr + 0x02),
-			 inl (card->baseaddr + 0x04),
-			 inl (card->baseaddr + 0x0C),
-			 inl (card->baseaddr + 0x80),
-			 inl (card->baseaddr + 0x84));
-		}
-
-		if (!chan->is_active)
-			printk (KERN_ERR "sleeping but not active\n");
-#endif
-
-		mutex_unlock(&card->syscall_mutex);
-
-		DPRINTK ("sleeping, nbufs=%d\n", atomic_read (&chan->n_frags));
-		schedule();
-
-		if ((ret = via_syscall_down (card, nonblock)))
-			break;
-
-		if (signal_pending (current)) {
-			DPRINTK ("EXIT, returning -ERESTARTSYS\n");
-			ret = -ERESTARTSYS;
-			break;
-		}
-	}
-	set_current_state(TASK_RUNNING);
-	remove_wait_queue(&chan->wait, &wait);
-
-#ifdef VIA_DEBUG
-	{
-		u8 r40,r41,r42,r43,r44,r48;
-		pci_read_config_byte (card->pdev, 0x40, &r40);
-		pci_read_config_byte (card->pdev, 0x41, &r41);
-		pci_read_config_byte (card->pdev, 0x42, &r42);
-		pci_read_config_byte (card->pdev, 0x43, &r43);
-		pci_read_config_byte (card->pdev, 0x44, &r44);
-		pci_read_config_byte (card->pdev, 0x48, &r48);
-		DPRINTK ("PCI config: %02X %02X %02X %02X %02X %02X\n",
-			r40,r41,r42,r43,r44,r48);
-
-		DPRINTK ("regs==%02X %02X %02X %08X %08X %08X %08X\n",
-			 inb (card->baseaddr + 0x00),
-			 inb (card->baseaddr + 0x01),
-			 inb (card->baseaddr + 0x02),
-			 inl (card->baseaddr + 0x04),
-			 inl (card->baseaddr + 0x0C),
-			 inl (card->baseaddr + 0x80),
-			 inl (card->baseaddr + 0x84));
-
-		DPRINTK ("final nbufs=%d\n", atomic_read (&chan->n_frags));
-	}
-#endif
-
-out:
-	DPRINTK ("EXIT, returning %d\n", ret);
-	return ret;
-}
-
-
-/**
- *	via_dsp_ioctl_space - get information about channel buffering
- *	@card: Private info for specified board
- *	@chan: pointer to channel-specific info
- *	@arg: user buffer for returned information
- *
- *	Handles SNDCTL_DSP_GETISPACE and SNDCTL_DSP_GETOSPACE.
- *
- *	Locking: inside card->syscall_mutex
- */
-
-static int via_dsp_ioctl_space (struct via_info *card,
-				struct via_channel *chan,
-				void __user *arg)
-{
-	audio_buf_info info;
-
-	via_chan_set_buffering(card, chan, -1);
-
-	info.fragstotal = chan->frag_number;
-	info.fragsize = chan->frag_size;
-
-	/* number of full fragments we can read/write without blocking */
-	info.fragments = atomic_read (&chan->n_frags);
-
-	if ((chan->slop_len % chan->frag_size > 0) && (info.fragments > 0))
-		info.fragments--;
-
-	/* number of bytes that can be read or written immediately
-	 * without blocking.
-	 */
-	info.bytes = (info.fragments * chan->frag_size);
-	if (chan->slop_len % chan->frag_size > 0)
-		info.bytes += chan->frag_size - (chan->slop_len % chan->frag_size);
-
-	DPRINTK ("EXIT, returning fragstotal=%d, fragsize=%d, fragments=%d, bytes=%d\n",
-		info.fragstotal,
-		info.fragsize,
-		info.fragments,
-		info.bytes);
-
-	return copy_to_user (arg, &info, sizeof (info))?-EFAULT:0;
-}
-
-
-/**
- *	via_dsp_ioctl_ptr - get information about hardware buffer ptr
- *	@card: Private info for specified board
- *	@chan: pointer to channel-specific info
- *	@arg: user buffer for returned information
- *
- *	Handles SNDCTL_DSP_GETIPTR and SNDCTL_DSP_GETOPTR.
- *
- *	Locking: inside card->syscall_mutex
- */
-
-static int via_dsp_ioctl_ptr (struct via_info *card,
-				struct via_channel *chan,
-				void __user *arg)
-{
-	count_info info;
-
-	spin_lock_irq (&card->lock);
-
-	info.bytes = chan->bytes;
-	info.blocks = chan->n_irqs;
-	chan->n_irqs = 0;
-
-	spin_unlock_irq (&card->lock);
-
-	if (chan->is_active) {
-		unsigned long extra;
-		info.ptr = atomic_read (&chan->hw_ptr) * chan->frag_size;
-		extra = chan->frag_size - via_sg_offset(chan);
-		info.ptr += extra;
-		info.bytes += extra;
-	} else {
-		info.ptr = 0;
-	}
-
-	DPRINTK ("EXIT, returning bytes=%d, blocks=%d, ptr=%d\n",
-		info.bytes,
-		info.blocks,
-		info.ptr);
-
-	return copy_to_user (arg, &info, sizeof (info))?-EFAULT:0;
-}
-
-
-static int via_dsp_ioctl_trigger (struct via_channel *chan, int val)
-{
-	int enable, do_something;
-
-	if (chan->is_record)
-		enable = (val & PCM_ENABLE_INPUT);
-	else
-		enable = (val & PCM_ENABLE_OUTPUT);
-
-	if (!chan->is_enabled && enable) {
-		do_something = 1;
-	} else if (chan->is_enabled && !enable) {
-		do_something = -1;
-	} else {
-		do_something = 0;
-	}
-
-	DPRINTK ("enable=%d, do_something=%d\n",
-		 enable, do_something);
-
-	if (chan->is_active && do_something)
-		return -EINVAL;
-
-	if (do_something == 1) {
-		chan->is_enabled = 1;
-		via_chan_maybe_start (chan);
-		DPRINTK ("Triggering input\n");
-	}
-
-	else if (do_something == -1) {
-		chan->is_enabled = 0;
-		DPRINTK ("Setup input trigger\n");
-	}
-
-	return 0;
-}
-
-
-static int via_dsp_ioctl (struct inode *inode, struct file *file,
-			  unsigned int cmd, unsigned long arg)
-{
-	int rc, rd=0, wr=0, val=0;
-	struct via_info *card;
-	struct via_channel *chan;
-	int nonblock = (file->f_flags & O_NONBLOCK);
-	int __user *ip = (int __user *)arg;
-	void __user *p = (void __user *)arg;
-
-	assert (file != NULL);
-	card = file->private_data;
-	assert (card != NULL);
-
-	if (file->f_mode & FMODE_WRITE)
-		wr = 1;
-	if (file->f_mode & FMODE_READ)
-		rd = 1;
-
-	rc = via_syscall_down (card, nonblock);
-	if (rc)
-		return rc;
-	rc = -EINVAL;
-
-	switch (cmd) {
-
-	/* OSS API version.  XXX unverified */
-	case OSS_GETVERSION:
-		DPRINTK ("ioctl OSS_GETVERSION, EXIT, returning SOUND_VERSION\n");
-		rc = put_user (SOUND_VERSION, ip);
-		break;
-
-	/* list of supported PCM data formats */
-	case SNDCTL_DSP_GETFMTS:
-		DPRINTK ("DSP_GETFMTS, EXIT, returning AFMT U8|S16_LE\n");
-                rc = put_user (AFMT_U8 | AFMT_S16_LE, ip);
-		break;
-
-	/* query or set current channel's PCM data format */
-	case SNDCTL_DSP_SETFMT:
-		if (get_user(val, ip)) {
-			rc = -EFAULT;
-			break;
-		}
-		DPRINTK ("DSP_SETFMT, val==%d\n", val);
-		if (val != AFMT_QUERY) {
-			rc = 0;
-
-			if (rd)
-				rc = via_chan_set_fmt (card, &card->ch_in, val);
-
-			if (rc >= 0 && wr)
-				rc = via_chan_set_fmt (card, &card->ch_out, val);
-
-			if (rc < 0)
-				break;
-
-			val = rc;
-		} else {
-			if ((rd && (card->ch_in.pcm_fmt & VIA_PCM_FMT_16BIT)) ||
-			    (wr && (card->ch_out.pcm_fmt & VIA_PCM_FMT_16BIT)))
-				val = AFMT_S16_LE;
-			else
-				val = AFMT_U8;
-		}
-		DPRINTK ("SETFMT EXIT, returning %d\n", val);
-                rc = put_user (val, ip);
-		break;
-
-	/* query or set number of channels (1=mono, 2=stereo, 4/6 for multichannel) */
-        case SNDCTL_DSP_CHANNELS:
-		if (get_user(val, ip)) {
-			rc = -EFAULT;
-			break;
-		}
-		DPRINTK ("DSP_CHANNELS, val==%d\n", val);
-		if (val != 0) {
-			rc = 0;
-
-			if (rd)
-				rc = via_chan_set_stereo (card, &card->ch_in, val);
-
-			if (rc >= 0 && wr)
-				rc = via_chan_set_stereo (card, &card->ch_out, val);
-
-			if (rc < 0)
-				break;
-
-			val = rc;
-		} else {
-			if (rd)
-				val = card->ch_in.channels;
-			else
-				val = card->ch_out.channels;
-		}
-		DPRINTK ("CHANNELS EXIT, returning %d\n", val);
-                rc = put_user (val, ip);
-		break;
-
-	/* enable (val is not zero) or disable (val == 0) stereo */
-        case SNDCTL_DSP_STEREO:
-		if (get_user(val, ip)) {
-			rc = -EFAULT;
-			break;
-		}
-		DPRINTK ("DSP_STEREO, val==%d\n", val);
-		rc = 0;
-
-		if (rd)
-			rc = via_chan_set_stereo (card, &card->ch_in, val ? 2 : 1);
-		if (rc >= 0 && wr)
-			rc = via_chan_set_stereo (card, &card->ch_out, val ? 2 : 1);
-
-		if (rc < 0)
-			break;
-
-		val = rc - 1;
-
-		DPRINTK ("STEREO EXIT, returning %d\n", val);
-		rc = put_user(val, ip);
-		break;
-
-	/* query or set sampling rate */
-        case SNDCTL_DSP_SPEED:
-		if (get_user(val, ip)) {
-			rc = -EFAULT;
-			break;
-		}
-		DPRINTK ("DSP_SPEED, val==%d\n", val);
-		if (val < 0) {
-			rc = -EINVAL;
-			break;
-		}
-		if (val > 0) {
-			rc = 0;
-
-			if (rd)
-				rc = via_chan_set_speed (card, &card->ch_in, val);
-			if (rc >= 0 && wr)
-				rc = via_chan_set_speed (card, &card->ch_out, val);
-
-			if (rc < 0)
-				break;
-
-			val = rc;
-		} else {
-			if (rd)
-				val = card->ch_in.rate;
-			else if (wr)
-				val = card->ch_out.rate;
-			else
-				val = 0;
-		}
-		DPRINTK ("SPEED EXIT, returning %d\n", val);
-                rc = put_user (val, ip);
-		break;
-
-	/* wait until all buffers have been played, and then stop device */
-	case SNDCTL_DSP_SYNC:
-		DPRINTK ("DSP_SYNC\n");
-		rc = 0;
-		if (wr) {
-			DPRINTK ("SYNC EXIT (after calling via_dsp_drain_playback)\n");
-			rc = via_dsp_drain_playback (card, &card->ch_out, nonblock);
-		}
-		break;
-
-	/* stop recording/playback immediately */
-        case SNDCTL_DSP_RESET:
-		DPRINTK ("DSP_RESET\n");
-		if (rd) {
-			via_chan_clear (card, &card->ch_in);
-			card->ch_in.frag_number = 0;
-			card->ch_in.frag_size = 0;
-			atomic_set(&card->ch_in.n_frags, 0);
-		}
-
-		if (wr) {
-			via_chan_clear (card, &card->ch_out);
-			card->ch_out.frag_number = 0;
-			card->ch_out.frag_size = 0;
-			atomic_set(&card->ch_out.n_frags, 0);
-		}
-
-		rc = 0;
-		break;
-
-	case SNDCTL_DSP_NONBLOCK:
-		file->f_flags |= O_NONBLOCK;
-		rc = 0;
-		break;
-
-	/* obtain bitmask of device capabilities, such as mmap, full duplex, etc. */
-	case SNDCTL_DSP_GETCAPS:
-		DPRINTK ("DSP_GETCAPS\n");
-		rc = put_user(VIA_DSP_CAP, ip);
-		break;
-
-	/* obtain buffer fragment size */
-	case SNDCTL_DSP_GETBLKSIZE:
-		DPRINTK ("DSP_GETBLKSIZE\n");
-
-		if (rd) {
-			via_chan_set_buffering(card, &card->ch_in, -1);
-			rc = put_user(card->ch_in.frag_size, ip);
-		} else if (wr) {
-			via_chan_set_buffering(card, &card->ch_out, -1);
-			rc = put_user(card->ch_out.frag_size, ip);
-		}
-		break;
-
-	/* obtain information about input buffering */
-	case SNDCTL_DSP_GETISPACE:
-		DPRINTK ("DSP_GETISPACE\n");
-		if (rd)
-			rc = via_dsp_ioctl_space (card, &card->ch_in, p);
-		break;
-
-	/* obtain information about output buffering */
-	case SNDCTL_DSP_GETOSPACE:
-		DPRINTK ("DSP_GETOSPACE\n");
-		if (wr)
-			rc = via_dsp_ioctl_space (card, &card->ch_out, p);
-		break;
-
-	/* obtain information about input hardware pointer */
-	case SNDCTL_DSP_GETIPTR:
-		DPRINTK ("DSP_GETIPTR\n");
-		if (rd)
-			rc = via_dsp_ioctl_ptr (card, &card->ch_in, p);
-		break;
-
-	/* obtain information about output hardware pointer */
-	case SNDCTL_DSP_GETOPTR:
-		DPRINTK ("DSP_GETOPTR\n");
-		if (wr)
-			rc = via_dsp_ioctl_ptr (card, &card->ch_out, p);
-		break;
-
-	/* return number of bytes remaining to be played by DMA engine */
-	case SNDCTL_DSP_GETODELAY:
-		{
-		DPRINTK ("DSP_GETODELAY\n");
-
-		chan = &card->ch_out;
-
-		if (!wr)
-			break;
-
-		if (chan->is_active) {
-
-			val = chan->frag_number - atomic_read (&chan->n_frags);
-
-			assert(val >= 0);
-				
-			if (val > 0) {
-				val *= chan->frag_size;
-				val -= chan->frag_size - via_sg_offset(chan);
-			}
-			val += chan->slop_len % chan->frag_size;
-		} else
-			val = 0;
-
-		assert (val <= (chan->frag_size * chan->frag_number));
-
-		DPRINTK ("GETODELAY EXIT, val = %d bytes\n", val);
-                rc = put_user (val, ip);
-		break;
-		}
-
-	/* handle the quick-start of a channel,
-	 * or the notification that a quick-start will
-	 * occur in the future
-	 */
-	case SNDCTL_DSP_SETTRIGGER:
-		if (get_user(val, ip)) {
-			rc = -EFAULT;
-			break;
-		}
-		DPRINTK ("DSP_SETTRIGGER, rd=%d, wr=%d, act=%d/%d, en=%d/%d\n",
-			rd, wr, card->ch_in.is_active, card->ch_out.is_active,
-			card->ch_in.is_enabled, card->ch_out.is_enabled);
-
-		rc = 0;
-
-		if (rd)
-			rc = via_dsp_ioctl_trigger (&card->ch_in, val);
-
-		if (!rc && wr)
-			rc = via_dsp_ioctl_trigger (&card->ch_out, val);
-
-		break;
-
-	case SNDCTL_DSP_GETTRIGGER:
-		val = 0;
-		if ((file->f_mode & FMODE_READ) && card->ch_in.is_enabled)
-			val |= PCM_ENABLE_INPUT;
-		if ((file->f_mode & FMODE_WRITE) && card->ch_out.is_enabled)
-			val |= PCM_ENABLE_OUTPUT;
-		rc = put_user(val, ip);
-		break;
-
-	/* Enable full duplex.  Since we do this as soon as we are opened
-	 * with O_RDWR, this is mainly a no-op that always returns success.
-	 */
-	case SNDCTL_DSP_SETDUPLEX:
-		DPRINTK ("DSP_SETDUPLEX\n");
-		if (!rd || !wr)
-			break;
-		rc = 0;
-		break;
-
-	/* set fragment size.  implemented as a successful no-op for now */
-	case SNDCTL_DSP_SETFRAGMENT:
-		if (get_user(val, ip)) {
-			rc = -EFAULT;
-			break;
-		}
-		DPRINTK ("DSP_SETFRAGMENT, val==%d\n", val);
-
-		if (rd)
-			rc = via_chan_set_buffering(card, &card->ch_in, val);
-
-		if (wr)
-			rc = via_chan_set_buffering(card, &card->ch_out, val);
-
-		DPRINTK ("SNDCTL_DSP_SETFRAGMENT (fragshift==0x%04X (%d), maxfrags==0x%04X (%d))\n",
-			 val & 0xFFFF,
-			 val & 0xFFFF,
-			 (val >> 16) & 0xFFFF,
-			 (val >> 16) & 0xFFFF);
-
-		rc = 0;
-		break;
-
-	/* inform device of an upcoming pause in input (or output). */
-	case SNDCTL_DSP_POST:
-		DPRINTK ("DSP_POST\n");
-		if (wr) {
-			if (card->ch_out.slop_len > 0)
-				via_chan_flush_frag (&card->ch_out);
-			via_chan_maybe_start (&card->ch_out);
-		}
-
-		rc = 0;
-		break;
-
-	/* not implemented */
-	default:
-		DPRINTK ("unhandled ioctl, cmd==%u, arg==%p\n",
-			 cmd, p);
-		break;
-	}
-
-	mutex_unlock(&card->syscall_mutex);
-	DPRINTK ("EXIT, returning %d\n", rc);
-	return rc;
-}
-
-
-static int via_dsp_open (struct inode *inode, struct file *file)
-{
-	int minor = iminor(inode);
-	struct via_info *card;
-	struct pci_dev *pdev = NULL;
-	struct via_channel *chan;
-	struct pci_driver *drvr;
-	int nonblock = (file->f_flags & O_NONBLOCK);
-
-	DPRINTK ("ENTER, minor=%d, file->f_mode=0x%x\n", minor, file->f_mode);
-
-	if (!(file->f_mode & (FMODE_READ | FMODE_WRITE))) {
-		DPRINTK ("EXIT, returning -EINVAL\n");
-		return -EINVAL;
-	}
-
-	card = NULL;
-	while ((pdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL) {
-		drvr = pci_dev_driver (pdev);
-		if (drvr == &via_driver) {
-			assert (pci_get_drvdata (pdev) != NULL);
-
-			card = pci_get_drvdata (pdev);
-			DPRINTK ("dev_dsp = %d, minor = %d, assn = %d\n",
-				 card->dev_dsp, minor,
-				 (card->dev_dsp ^ minor) & ~0xf);
-
-			if (((card->dev_dsp ^ minor) & ~0xf) == 0)
-				goto match;
-		}
-	}
-
-	DPRINTK ("no matching %s found\n", card ? "minor" : "driver");
-	return -ENODEV;
-
-match:
-	pci_dev_put(pdev);
-	if (nonblock) {
-		if (!mutex_trylock(&card->open_mutex)) {
-			DPRINTK ("EXIT, returning -EAGAIN\n");
-			return -EAGAIN;
-		}
-	} else {
-		if (mutex_lock_interruptible(&card->open_mutex)) {
-			DPRINTK ("EXIT, returning -ERESTARTSYS\n");
-			return -ERESTARTSYS;
-		}
-	}
-
-	file->private_data = card;
-	DPRINTK ("file->f_mode == 0x%x\n", file->f_mode);
-
-	/* handle input from analog source */
-	if (file->f_mode & FMODE_READ) {
-		chan = &card->ch_in;
-
-		via_chan_init (card, chan);
-
-		/* why is this forced to 16-bit stereo in all drivers? */
-		chan->pcm_fmt = VIA_PCM_FMT_16BIT | VIA_PCM_FMT_STEREO;
-		chan->channels = 2;
-
-		// TO DO - use FIFO: via_capture_fifo(card, 1);
-		via_chan_pcm_fmt (chan, 0);
-		via_set_rate (card->ac97, chan, 44100);
-	}
-
-	/* handle output to analog source */
-	if (file->f_mode & FMODE_WRITE) {
-		chan = &card->ch_out;
-
-		via_chan_init (card, chan);
-
-		if (file->f_mode & FMODE_READ) {
-			/* if in duplex mode make the recording and playback channels
-			   have the same settings */
-			chan->pcm_fmt = VIA_PCM_FMT_16BIT | VIA_PCM_FMT_STEREO;
-			chan->channels = 2;
-			via_chan_pcm_fmt (chan, 0);
-                        via_set_rate (card->ac97, chan, 44100);
-		} else {
-			 if ((minor & 0xf) == SND_DEV_DSP16) {
-				chan->pcm_fmt = VIA_PCM_FMT_16BIT;
-				via_chan_pcm_fmt (chan, 0);
-				via_set_rate (card->ac97, chan, 44100);
-			} else {
-				via_chan_pcm_fmt (chan, 1);
-				via_set_rate (card->ac97, chan, 8000);
-			}
-		}
-	}
-
-	DPRINTK ("EXIT, returning 0\n");
-	return nonseekable_open(inode, file);
-}
-
-
-static int via_dsp_release(struct inode *inode, struct file *file)
-{
-	struct via_info *card;
-	int nonblock = (file->f_flags & O_NONBLOCK);
-	int rc;
-
-	DPRINTK ("ENTER\n");
-
-	assert (file != NULL);
-	card = file->private_data;
-	assert (card != NULL);
-
-	rc = via_syscall_down (card, nonblock);
-	if (rc) {
-		DPRINTK ("EXIT (syscall_down error), rc=%d\n", rc);
-		return rc;
-	}
-
-	if (file->f_mode & FMODE_WRITE) {
-		rc = via_dsp_drain_playback (card, &card->ch_out, nonblock);
-		if (rc && rc != -ERESTARTSYS)	/* Nobody needs to know about ^C */
-			printk (KERN_DEBUG "via_audio: ignoring drain playback error %d\n", rc);
-
-		via_chan_free (card, &card->ch_out);
-		via_chan_buffer_free(card, &card->ch_out);
-	}
-
-	if (file->f_mode & FMODE_READ) {
-		via_chan_free (card, &card->ch_in);
-		via_chan_buffer_free (card, &card->ch_in);
-	}
-
-	mutex_unlock(&card->syscall_mutex);
-	mutex_unlock(&card->open_mutex);
-
-	DPRINTK ("EXIT, returning 0\n");
-	return 0;
-}
-
-
-/****************************************************************
- *
- * Chip setup and kernel registration
- *
- *
- */
-
-static int __devinit via_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
-{
-#ifdef CONFIG_MIDI_VIA82CXXX
-	u8 r42;
-#endif
-	int rc;
-	struct via_info *card;
-	static int printed_version;
-
-	DPRINTK ("ENTER\n");
-
-	if (printed_version++ == 0)
-		printk (KERN_INFO "Via 686a/8233/8235 audio driver " VIA_VERSION "\n");
-
-	rc = pci_enable_device (pdev);
-	if (rc)
-		goto err_out;
-
-	rc = pci_request_regions (pdev, "via82cxxx_audio");
-	if (rc)
-		goto err_out_disable;
-
-	rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
-	if (rc)
-		goto err_out_res;
-	rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
-	if (rc)
-		goto err_out_res;
-
-	card = kmalloc (sizeof (*card), GFP_KERNEL);
-	if (!card) {
-		printk (KERN_ERR PFX "out of memory, aborting\n");
-		rc = -ENOMEM;
-		goto err_out_res;
-	}
-
-	pci_set_drvdata (pdev, card);
-
-	memset (card, 0, sizeof (*card));
-	card->pdev = pdev;
-	card->baseaddr = pci_resource_start (pdev, 0);
-	card->card_num = via_num_cards++;
-	spin_lock_init (&card->lock);
-	spin_lock_init (&card->ac97_lock);
-	mutex_init(&card->syscall_mutex);
-	mutex_init(&card->open_mutex);
-
-	/* we must init these now, in case the intr handler needs them */
-	via_chan_init_defaults (card, &card->ch_out);
-	via_chan_init_defaults (card, &card->ch_in);
-	via_chan_init_defaults (card, &card->ch_fm);
-
-	/* if BAR 2 is present, chip is Rev H or later,
-	 * which means it has a few extra features */
-	if (pci_resource_start (pdev, 2) > 0)
-		card->rev_h = 1;
-		
-	/* Overkill for now, but more flexible done right */
-	
-	card->intmask = id->driver_data;
-	card->legacy = !card->intmask;
-	card->sixchannel = id->driver_data;
-	
-	if(card->sixchannel)
-		printk(KERN_INFO PFX "Six channel audio available\n");
-	if (pdev->irq < 1) {
-		printk (KERN_ERR PFX "invalid PCI IRQ %d, aborting\n", pdev->irq);
-		rc = -ENODEV;
-		goto err_out_kfree;
-	}
-
-	if (!(pci_resource_flags (pdev, 0) & IORESOURCE_IO)) {
-		printk (KERN_ERR PFX "unable to locate I/O resources, aborting\n");
-		rc = -ENODEV;
-		goto err_out_kfree;
-	}
-
-	pci_set_master(pdev);
-	
-	/*
-	 * init AC97 mixer and codec
-	 */
-	rc = via_ac97_init (card);
-	if (rc) {
-		printk (KERN_ERR PFX "AC97 init failed, aborting\n");
-		goto err_out_kfree;
-	}
-
-	/*
-	 * init DSP device
-	 */
-	rc = via_dsp_init (card);
-	if (rc) {
-		printk (KERN_ERR PFX "DSP device init failed, aborting\n");
-		goto err_out_have_mixer;
-	}
-
-	/*
-	 * init and turn on interrupts, as the last thing we do
-	 */
-	rc = via_interrupt_init (card);
-	if (rc) {
-		printk (KERN_ERR PFX "interrupt init failed, aborting\n");
-		goto err_out_have_dsp;
-	}
-
-	printk (KERN_INFO PFX "board #%d at 0x%04lX, IRQ %d\n",
-		card->card_num + 1, card->baseaddr, pdev->irq);
-
-#ifdef CONFIG_MIDI_VIA82CXXX
-	/* Disable by default */
-	card->midi_info.io_base = 0;
-
-	if(card->legacy)
-	{
-		pci_read_config_byte (pdev, 0x42, &r42);
-		/* Disable MIDI interrupt */
-		pci_write_config_byte (pdev, 0x42, r42 | VIA_CR42_MIDI_IRQMASK);
-		if (r42 & VIA_CR42_MIDI_ENABLE)
-		{
-			if (r42 & VIA_CR42_MIDI_PNP) /* Address selected by iobase 2 - not tested */
-				card->midi_info.io_base = pci_resource_start (pdev, 2);
-			else /* Address selected by byte 0x43 */
-			{
-				u8 r43;
-				pci_read_config_byte (pdev, 0x43, &r43);
-				card->midi_info.io_base = 0x300 + ((r43 & 0x0c) << 2);
-			}
-
-			card->midi_info.irq = -pdev->irq;
-			if (probe_uart401(& card->midi_info, THIS_MODULE))
-			{
-				card->midi_devc=midi_devs[card->midi_info.slots[4]]->devc;
-				pci_write_config_byte(pdev, 0x42, r42 & ~VIA_CR42_MIDI_IRQMASK);
-				printk("Enabled Via MIDI\n");
-			}
-		}
-	}
-#endif
-
-	DPRINTK ("EXIT, returning 0\n");
-	return 0;
-
-err_out_have_dsp:
-	via_dsp_cleanup (card);
-
-err_out_have_mixer:
-	via_ac97_cleanup (card);
-
-err_out_kfree:
-#ifndef VIA_NDEBUG
-	memset (card, OSS_POISON_FREE, sizeof (*card)); /* poison memory */
-#endif
-	kfree (card);
-
-err_out_res:
-	pci_release_regions (pdev);
-
-err_out_disable:
-	pci_disable_device (pdev);
-
-err_out:
-	pci_set_drvdata (pdev, NULL);
-	DPRINTK ("EXIT - returning %d\n", rc);
-	return rc;
-}
-
-
-static void __devexit via_remove_one (struct pci_dev *pdev)
-{
-	struct via_info *card;
-
-	DPRINTK ("ENTER\n");
-
-	assert (pdev != NULL);
-	card = pci_get_drvdata (pdev);
-	assert (card != NULL);
-
-#ifdef CONFIG_MIDI_VIA82CXXX
-	if (card->midi_info.io_base)
-		unload_uart401(&card->midi_info);
-#endif
-
-	free_irq (card->pdev->irq, card);
-	via_dsp_cleanup (card);
-	via_ac97_cleanup (card);
-
-#ifndef VIA_NDEBUG
-	memset (card, OSS_POISON_FREE, sizeof (*card)); /* poison memory */
-#endif
-	kfree (card);
-
-	pci_set_drvdata (pdev, NULL);
-
-	pci_release_regions (pdev);
-	pci_disable_device (pdev);
-	pci_set_power_state (pdev, 3); /* ...zzzzzz */
-
-	DPRINTK ("EXIT\n");
-	return;
-}
-
-
-/****************************************************************
- *
- * Driver initialization and cleanup
- *
- *
- */
-
-static int __init init_via82cxxx_audio(void)
-{
-	int rc;
-
-	DPRINTK ("ENTER\n");
-
-	rc = pci_register_driver (&via_driver);
-	if (rc) {
-		DPRINTK ("EXIT, returning %d\n", rc);
-		return rc;
-	}
-
-	DPRINTK ("EXIT, returning 0\n");
-	return 0;
-}
-
-
-static void __exit cleanup_via82cxxx_audio(void)
-{
-	DPRINTK ("ENTER\n");
-
-	pci_unregister_driver (&via_driver);
-
-	DPRINTK ("EXIT\n");
-}
-
-
-module_init(init_via82cxxx_audio);
-module_exit(cleanup_via82cxxx_audio);
-
-MODULE_AUTHOR("Jeff Garzik");
-MODULE_DESCRIPTION("DSP audio and mixer driver for Via 82Cxxx audio devices");
-MODULE_LICENSE("GPL");
-