summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--include/sound/ad1848.h111
-rw-r--r--sound/isa/Kconfig15
-rw-r--r--sound/isa/ad1848/Makefile2
-rw-r--r--sound/isa/ad1848/ad1848.c7
-rw-r--r--sound/isa/ad1848/ad1848_lib.c487
-rw-r--r--sound/isa/cmi8330.c22
-rw-r--r--sound/isa/opti9xx/opti92x-ad1848.c15
-rw-r--r--sound/isa/sc6000.c6
-rw-r--r--sound/isa/sgalaxy.c13
-rw-r--r--sound/isa/wss/wss_lib.c150
10 files changed, 150 insertions, 678 deletions
diff --git a/include/sound/ad1848.h b/include/sound/ad1848.h
index 7ff484f55b02..e69de29bb2d1 100644
--- a/include/sound/ad1848.h
+++ b/include/sound/ad1848.h
@@ -1,111 +0,0 @@
-#ifndef __SOUND_AD1848_H
-#define __SOUND_AD1848_H
-
-/*
- *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
- *  Definitions for AD1847/AD1848/CS4248 chips
- *
- *
- *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
- *
- */
-
-#include "pcm.h"
-#include <linux/interrupt.h>
-
-#include "wss.h"	/* temporary till the driver is removed */
-
-/* codec registers */
-
-#define AD1848_LEFT_INPUT	0x00	/* left input control */
-#define AD1848_RIGHT_INPUT	0x01	/* right input control */
-#define AD1848_AUX1_LEFT_INPUT	0x02	/* left AUX1 input control */
-#define AD1848_AUX1_RIGHT_INPUT	0x03	/* right AUX1 input control */
-#define AD1848_AUX2_LEFT_INPUT	0x04	/* left AUX2 input control */
-#define AD1848_AUX2_RIGHT_INPUT	0x05	/* right AUX2 input control */
-#define AD1848_LEFT_OUTPUT	0x06	/* left output control register */
-#define AD1848_RIGHT_OUTPUT	0x07	/* right output control register */
-#define AD1848_DATA_FORMAT	0x08	/* clock and data format - playback/capture - bits 7-0 MCE */
-#define AD1848_IFACE_CTRL	0x09	/* interface control - bits 7-2 MCE */
-#define AD1848_PIN_CTRL		0x0a	/* pin control */
-#define AD1848_TEST_INIT	0x0b	/* test and initialization */
-#define AD1848_MISC_INFO	0x0c	/* miscellaneous information */
-#define AD1848_LOOPBACK		0x0d	/* loopback control */
-#define AD1848_DATA_UPR_CNT	0x0e	/* playback/capture upper base count */
-#define AD1848_DATA_LWR_CNT	0x0f	/* playback/capture lower base count */
-
-/* definitions for codec register select port - CODECP( REGSEL ) */
-
-#define AD1848_INIT		0x80	/* CODEC is initializing */
-#define AD1848_MCE		0x40	/* mode change enable */
-#define AD1848_TRD		0x20	/* transfer request disable */
-
-/* definitions for codec status register - CODECP( STATUS ) */
-
-#define AD1848_GLOBALIRQ	0x01	/* IRQ is active */
-
-/* definitions for AD1848_LEFT_INPUT and AD1848_RIGHT_INPUT registers */
-
-#define AD1848_ENABLE_MIC_GAIN	0x20
-
-#define AD1848_MIXS_LINE1	0x00
-#define AD1848_MIXS_AUX1	0x40
-#define AD1848_MIXS_LINE2	0x80
-#define AD1848_MIXS_ALL		0xc0
-
-/* definitions for clock and data format register - AD1848_PLAYBK_FORMAT */
-
-#define AD1848_LINEAR_8		0x00	/* 8-bit unsigned data */
-#define AD1848_ALAW_8		0x60	/* 8-bit A-law companded */
-#define AD1848_ULAW_8		0x20	/* 8-bit U-law companded */
-#define AD1848_LINEAR_16	0x40	/* 16-bit twos complement data - little endian */
-#define AD1848_STEREO		0x10	/* stereo mode */
-/* bits 3-1 define frequency divisor */
-#define AD1848_XTAL1		0x00	/* 24.576 crystal */
-#define AD1848_XTAL2		0x01	/* 16.9344 crystal */
-
-/* definitions for interface control register - AD1848_IFACE_CTRL */
-
-#define AD1848_CAPTURE_PIO	0x80	/* capture PIO enable */
-#define AD1848_PLAYBACK_PIO	0x40	/* playback PIO enable */
-#define AD1848_CALIB_MODE	0x18	/* calibration mode bits */
-#define AD1848_AUTOCALIB	0x08	/* auto calibrate */
-#define AD1848_SINGLE_DMA	0x04	/* use single DMA channel */
-#define AD1848_CAPTURE_ENABLE	0x02	/* capture enable */
-#define AD1848_PLAYBACK_ENABLE	0x01	/* playback enable */
-
-/* definitions for pin control register - AD1848_PIN_CTRL */
-
-#define AD1848_IRQ_ENABLE	0x02	/* enable IRQ */
-#define AD1848_XCTL1		0x40	/* external control #1 */
-#define AD1848_XCTL0		0x80	/* external control #0 */
-
-/* definitions for test and init register - AD1848_TEST_INIT */
-
-#define AD1848_CALIB_IN_PROGRESS 0x20	/* auto calibrate in progress */
-#define AD1848_DMA_REQUEST	0x10	/* DMA request in progress */
-
-/* exported functions */
-
-void snd_ad1848_out(struct snd_wss *chip, unsigned char reg,
-		    unsigned char value);
-
-int snd_ad1848_create(struct snd_card *card,
-		      unsigned long port,
-		      int irq, int dma,
-		      unsigned short hardware,
-		      struct snd_wss **chip);
-
-#endif /* __SOUND_AD1848_H */
diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig
index cca11d5dc33b..ec80444c2a96 100644
--- a/sound/isa/Kconfig
+++ b/sound/isa/Kconfig
@@ -4,11 +4,6 @@ config SND_WSS_LIB
         tristate
         select SND_PCM
 
-config SND_AD1848_LIB
-        tristate
-        select SND_PCM
-        select SND_WSS_LIB
-
 config SND_SB_COMMON
         tristate
 
@@ -56,7 +51,7 @@ config SND_AD1816A
 
 config SND_AD1848
 	tristate "Generic AD1848/CS4248 driver"
-	select SND_AD1848_LIB
+	select SND_WSS_LIB
 	help
 	  Say Y here to include support for AD1848 (Analog Devices) or
 	  CS4248 (Cirrus Logic - Crystal Semiconductors) chips.
@@ -97,7 +92,7 @@ config SND_AZT2320
 
 config SND_CMI8330
 	tristate "C-Media CMI8330"
-	select SND_AD1848_LIB
+	select SND_WSS_LIB
 	select SND_SB16_DSP
 	help
 	  Say Y here to include support for soundcards based on the
@@ -193,7 +188,7 @@ config SND_ES18XX
 config SND_SC6000
 	tristate "Gallant SC-6000, Audio Excel DSP 16"
 	depends on HAS_IOPORT
-	select SND_AD1848_LIB
+	select SND_WSS_LIB
 	select SND_OPL3_LIB
 	select SND_MPU401_UART
 	help
@@ -280,7 +275,7 @@ config SND_OPTI92X_AD1848
 	select SND_OPL3_LIB
 	select SND_OPL4_LIB
 	select SND_MPU401_UART
-	select SND_AD1848_LIB
+	select SND_WSS_LIB
 	help
 	  Say Y here to include support for soundcards based on Opti
 	  82C92x or OTI-601 chips and using an AD1848 codec.
@@ -373,7 +368,7 @@ config SND_SB16_CSP
 
 config SND_SGALAXY
 	tristate "Aztech Sound Galaxy"
-	select SND_AD1848_LIB
+	select SND_WSS_LIB
 	help
 	  Say Y here to include support for Aztech Sound Galaxy
 	  soundcards.
diff --git a/sound/isa/ad1848/Makefile b/sound/isa/ad1848/Makefile
index ae23331e9200..3d6dea3ff927 100644
--- a/sound/isa/ad1848/Makefile
+++ b/sound/isa/ad1848/Makefile
@@ -3,10 +3,8 @@
 # Copyright (c) 2001 by Jaroslav Kysela <perex@perex.cz>
 #
 
-snd-ad1848-lib-objs := ad1848_lib.o
 snd-ad1848-objs := ad1848.o
 
 # Toplevel Module Dependency
 obj-$(CONFIG_SND_AD1848) += snd-ad1848.o
-obj-$(CONFIG_SND_AD1848_LIB) += snd-ad1848-lib.o
 
diff --git a/sound/isa/ad1848/ad1848.c b/sound/isa/ad1848/ad1848.c
index 17970c2f27e7..b68d20edc20f 100644
--- a/sound/isa/ad1848/ad1848.c
+++ b/sound/isa/ad1848/ad1848.c
@@ -28,7 +28,7 @@
 #include <linux/wait.h>
 #include <linux/moduleparam.h>
 #include <sound/core.h>
-#include <sound/ad1848.h>
+#include <sound/wss.h>
 #include <sound/initval.h>
 
 #define CRD_NAME "Generic AD1848/AD1847/CS4248"
@@ -95,8 +95,9 @@ static int __devinit snd_ad1848_probe(struct device *dev, unsigned int n)
 	if (!card)
 		return -EINVAL;
 
-	error = snd_ad1848_create(card, port[n], irq[n], dma1[n],
-			thinkpad[n] ? WSS_HW_THINKPAD : WSS_HW_DETECT, &chip);
+	error = snd_wss_create(card, port[n], -1, irq[n], dma1[n], -1,
+			thinkpad[n] ? WSS_HW_THINKPAD : WSS_HW_DETECT,
+			0, &chip);
 	if (error < 0)
 		goto out;
 
diff --git a/sound/isa/ad1848/ad1848_lib.c b/sound/isa/ad1848/ad1848_lib.c
index aa803d38a8ad..e69de29bb2d1 100644
--- a/sound/isa/ad1848/ad1848_lib.c
+++ b/sound/isa/ad1848/ad1848_lib.c
@@ -1,487 +0,0 @@
-/*
- *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
- *  Routines for control of AD1848/AD1847/CS4248
- *
- *
- *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
- *
- */
-
-#define SNDRV_MAIN_OBJECT_FILE
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/ioport.h>
-#include <sound/core.h>
-#include <sound/ad1848.h>
-#include <sound/control.h>
-#include <sound/tlv.h>
-#include <sound/pcm_params.h>
-
-#include <asm/io.h>
-#include <asm/dma.h>
-
-MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
-MODULE_DESCRIPTION("Routines for control of AD1848/AD1847/CS4248");
-MODULE_LICENSE("GPL");
-
-#if 0
-#define SNDRV_DEBUG_MCE
-#endif
-
-/*
- *  Some variables
- */
-
-static unsigned char snd_ad1848_original_image[16] =
-{
-	0x00,			/* 00 - lic */
-	0x00,			/* 01 - ric */
-	0x9f,			/* 02 - la1ic */
-	0x9f,			/* 03 - ra1ic */
-	0x9f,			/* 04 - la2ic */
-	0x9f,			/* 05 - ra2ic */
-	0xbf,			/* 06 - loc */
-	0xbf,			/* 07 - roc */
-	0x20,			/* 08 - dfr */
-	AD1848_AUTOCALIB,	/* 09 - ic */
-	0x00,			/* 0a - pc */
-	0x00,			/* 0b - ti */
-	0x00,			/* 0c - mi */
-	0x00,			/* 0d - lbc */
-	0x00,			/* 0e - dru */
-	0x00,			/* 0f - drl */
-};
-
-/*
- *  Basic I/O functions
- */
-
-static void snd_ad1848_wait(struct snd_wss *chip)
-{
-	int timeout;
-
-	for (timeout = 250; timeout > 0; timeout--) {
-		if ((inb(chip->port + CS4231P(REGSEL)) & AD1848_INIT) == 0)
-			break;
-		udelay(100);
-	}
-}
-
-void snd_ad1848_out(struct snd_wss *chip,
-			   unsigned char reg,
-			   unsigned char value)
-{
-	snd_ad1848_wait(chip);
-#ifdef CONFIG_SND_DEBUG
-	if (inb(chip->port + CS4231P(REGSEL)) & AD1848_INIT)
-		snd_printk(KERN_WARNING "auto calibration time out - "
-			   "reg = 0x%x, value = 0x%x\n", reg, value);
-#endif
-	outb(chip->mce_bit | reg, chip->port + CS4231P(REGSEL));
-	outb(chip->image[reg] = value, chip->port + CS4231P(REG));
-	mb();
-	snd_printdd("codec out - reg 0x%x = 0x%x\n",
-			chip->mce_bit | reg, value);
-}
-
-EXPORT_SYMBOL(snd_ad1848_out);
-
-static unsigned char snd_ad1848_in(struct snd_wss *chip, unsigned char reg)
-{
-	snd_ad1848_wait(chip);
-#ifdef CONFIG_SND_DEBUG
-	if (inb(chip->port + CS4231P(REGSEL)) & AD1848_INIT)
-		snd_printk(KERN_WARNING "auto calibration time out - "
-			   "reg = 0x%x\n", reg);
-#endif
-	outb(chip->mce_bit | reg, chip->port + CS4231P(REGSEL));
-	mb();
-	return inb(chip->port + CS4231P(REG));
-}
-
-#if 0
-
-static void snd_ad1848_debug(struct snd_wss *chip)
-{
-	printk(KERN_DEBUG "AD1848 REGS:      INDEX = 0x%02x  ", inb(chip->port + CS4231P(REGSEL)));
-	printk(KERN_DEBUG "                 STATUS = 0x%02x\n", inb(chip->port + CS4231P(STATUS)));
-	printk(KERN_DEBUG "  0x00: left input      = 0x%02x  ", snd_ad1848_in(chip, 0x00));
-	printk(KERN_DEBUG "  0x08: playback format = 0x%02x\n", snd_ad1848_in(chip, 0x08));
-	printk(KERN_DEBUG "  0x01: right input     = 0x%02x  ", snd_ad1848_in(chip, 0x01));
-	printk(KERN_DEBUG "  0x09: iface (CFIG 1)  = 0x%02x\n", snd_ad1848_in(chip, 0x09));
-	printk(KERN_DEBUG "  0x02: AUXA left       = 0x%02x  ", snd_ad1848_in(chip, 0x02));
-	printk(KERN_DEBUG "  0x0a: pin control     = 0x%02x\n", snd_ad1848_in(chip, 0x0a));
-	printk(KERN_DEBUG "  0x03: AUXA right      = 0x%02x  ", snd_ad1848_in(chip, 0x03));
-	printk(KERN_DEBUG "  0x0b: init & status   = 0x%02x\n", snd_ad1848_in(chip, 0x0b));
-	printk(KERN_DEBUG "  0x04: AUXB left       = 0x%02x  ", snd_ad1848_in(chip, 0x04));
-	printk(KERN_DEBUG "  0x0c: revision & mode = 0x%02x\n", snd_ad1848_in(chip, 0x0c));
-	printk(KERN_DEBUG "  0x05: AUXB right      = 0x%02x  ", snd_ad1848_in(chip, 0x05));
-	printk(KERN_DEBUG "  0x0d: loopback        = 0x%02x\n", snd_ad1848_in(chip, 0x0d));
-	printk(KERN_DEBUG "  0x06: left output     = 0x%02x  ", snd_ad1848_in(chip, 0x06));
-	printk(KERN_DEBUG "  0x0e: data upr count  = 0x%02x\n", snd_ad1848_in(chip, 0x0e));
-	printk(KERN_DEBUG "  0x07: right output    = 0x%02x  ", snd_ad1848_in(chip, 0x07));
-	printk(KERN_DEBUG "  0x0f: data lwr count  = 0x%02x\n", snd_ad1848_in(chip, 0x0f));
-}
-
-#endif
-
-/*
- *  AD1848 detection / MCE routines
- */
-
-static void snd_ad1848_mce_up(struct snd_wss *chip)
-{
-	unsigned long flags;
-	int timeout;
-
-	snd_ad1848_wait(chip);
-#ifdef CONFIG_SND_DEBUG
-	if (inb(chip->port + CS4231P(REGSEL)) & AD1848_INIT)
-		snd_printk(KERN_WARNING "mce_up - auto calibration time out (0)\n");
-#endif
-	spin_lock_irqsave(&chip->reg_lock, flags);
-	chip->mce_bit |= AD1848_MCE;
-	timeout = inb(chip->port + CS4231P(REGSEL));
-	if (timeout == 0x80)
-		snd_printk(KERN_WARNING "mce_up [0x%lx]: serious init problem - codec still busy\n", chip->port);
-	if (!(timeout & AD1848_MCE))
-		outb(chip->mce_bit | (timeout & 0x1f),
-		     chip->port + CS4231P(REGSEL));
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
-}
-
-static void snd_ad1848_mce_down(struct snd_wss *chip)
-{
-	unsigned long flags, timeout;
-	int reg;
-
-	spin_lock_irqsave(&chip->reg_lock, flags);
-	for (timeout = 5; timeout > 0; timeout--)
-		inb(chip->port + CS4231P(REGSEL));
-	/* end of cleanup sequence */
-	for (timeout = 12000;
-	     timeout > 0 && (inb(chip->port + CS4231P(REGSEL)) & AD1848_INIT);
-	     timeout--)
-		udelay(100);
-
-	snd_printdd("(1) timeout = %ld\n", timeout);
-
-#ifdef CONFIG_SND_DEBUG
-	if (inb(chip->port + CS4231P(REGSEL)) & AD1848_INIT)
-		snd_printk(KERN_WARNING
-			   "mce_down [0x%lx] - auto calibration time out (0)\n",
-			   chip->port + CS4231P(REGSEL));
-#endif
-
-	chip->mce_bit &= ~AD1848_MCE;
-	reg = inb(chip->port + CS4231P(REGSEL));
-	outb(chip->mce_bit | (reg & 0x1f), chip->port + CS4231P(REGSEL));
-	if (reg == 0x80)
-		snd_printk(KERN_WARNING "mce_down [0x%lx]: serious init problem - codec still busy\n", chip->port);
-	if ((reg & AD1848_MCE) == 0) {
-		spin_unlock_irqrestore(&chip->reg_lock, flags);
-		return;
-	}
-
-	/*
-	 * Wait for auto-calibration (AC) process to finish, i.e. ACI to go low.
-	 * It may take up to 5 sample periods (at most 907 us @ 5.5125 kHz) for
-	 * the process to _start_, so it is important to wait at least that long
-	 * before checking.  Otherwise we might think AC has finished when it
-	 * has in fact not begun.  It could take 128 (no AC) or 384 (AC) cycles
-	 * for ACI to drop.  This gives a wait of at most 70 ms with a more
-	 * typical value of 3-9 ms.
-	 */
-	timeout = jiffies + msecs_to_jiffies(250);
-	do {
-		spin_unlock_irqrestore(&chip->reg_lock, flags);
-		msleep(1);
-		spin_lock_irqsave(&chip->reg_lock, flags);
-		reg = snd_ad1848_in(chip, AD1848_TEST_INIT) &
-		      AD1848_CALIB_IN_PROGRESS;
-	} while (reg && time_before(jiffies, timeout));
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
-	if (reg)
-		snd_printk(KERN_ERR
-			   "mce_down - auto calibration time out (2)\n");
-
-	snd_printdd("(4) jiffies = %lu\n", jiffies);
-	snd_printd("mce_down - exit = 0x%x\n",
-		   inb(chip->port + CS4231P(REGSEL)));
-}
-
-static irqreturn_t snd_ad1848_interrupt(int irq, void *dev_id)
-{
-	struct snd_wss *chip = dev_id;
-
-	if ((chip->mode & WSS_MODE_PLAY) && chip->playback_substream)
-		snd_pcm_period_elapsed(chip->playback_substream);
-	if ((chip->mode & WSS_MODE_RECORD) && chip->capture_substream)
-		snd_pcm_period_elapsed(chip->capture_substream);
-	outb(0, chip->port + CS4231P(STATUS));	/* clear global interrupt bit */
-	return IRQ_HANDLED;
-}
-
-/*
-
- */
-
-static void snd_ad1848_thinkpad_twiddle(struct snd_wss *chip, int on)
-{
-	int tmp;
-
-	if (!chip->thinkpad_flag) return;
-
-	outb(0x1c, AD1848_THINKPAD_CTL_PORT1);
-	tmp = inb(AD1848_THINKPAD_CTL_PORT2);
-
-	if (on)
-		/* turn it on */
-		tmp |= AD1848_THINKPAD_CS4248_ENABLE_BIT;
-	else
-		/* turn it off */
-		tmp &= ~AD1848_THINKPAD_CS4248_ENABLE_BIT;
-	
-	outb(tmp, AD1848_THINKPAD_CTL_PORT2);
-
-}
-
-#ifdef CONFIG_PM
-static void snd_ad1848_suspend(struct snd_wss *chip)
-{
-	snd_pcm_suspend_all(chip->pcm);
-	if (chip->thinkpad_flag)
-		snd_ad1848_thinkpad_twiddle(chip, 0);
-}
-
-static void snd_ad1848_resume(struct snd_wss *chip)
-{
-	int i;
-
-	if (chip->thinkpad_flag)
-		snd_ad1848_thinkpad_twiddle(chip, 1);
-
-	/* clear any pendings IRQ */
-	inb(chip->port + CS4231P(STATUS));
-	outb(0, chip->port + CS4231P(STATUS));
-	mb();
-
-	snd_ad1848_mce_down(chip);
-	for (i = 0; i < 16; i++)
-		snd_ad1848_out(chip, i, chip->image[i]);
-	snd_ad1848_mce_up(chip);
-	snd_ad1848_mce_down(chip);
-}
-#endif /* CONFIG_PM */
-
-static int snd_ad1848_probe(struct snd_wss *chip)
-{
-	unsigned long flags;
-	int i, id, rev, ad1847;
-	unsigned char *ptr;
-
-#if 0
-	snd_ad1848_debug(chip);
-#endif
-	id = ad1847 = 0;
-	for (i = 0; i < 1000; i++) {
-		mb();
-		if (inb(chip->port + CS4231P(REGSEL)) & AD1848_INIT)
-			udelay(500);
-		else {
-			spin_lock_irqsave(&chip->reg_lock, flags);
-			snd_ad1848_out(chip, AD1848_MISC_INFO, 0x00);
-			snd_ad1848_out(chip, AD1848_LEFT_INPUT, 0xaa);
-			snd_ad1848_out(chip, AD1848_RIGHT_INPUT, 0x45);
-			rev = snd_ad1848_in(chip, AD1848_RIGHT_INPUT);
-			if (rev == 0x65) {
-				spin_unlock_irqrestore(&chip->reg_lock, flags);
-				id = 1;
-				ad1847 = 1;
-				break;
-			}
-			if (snd_ad1848_in(chip, AD1848_LEFT_INPUT) == 0xaa && rev == 0x45) {
-				spin_unlock_irqrestore(&chip->reg_lock, flags);
-				id = 1;
-				break;
-			}
-			spin_unlock_irqrestore(&chip->reg_lock, flags);
-		}
-	}
-	if (id != 1)
-		return -ENODEV;	/* no valid device found */
-	if (chip->hardware == WSS_HW_DETECT) {
-		if (ad1847) {
-			chip->hardware = WSS_HW_AD1847;
-		} else {
-			chip->hardware = WSS_HW_AD1848;
-			rev = snd_ad1848_in(chip, AD1848_MISC_INFO);
-			if (rev & 0x80) {
-				chip->hardware = WSS_HW_CS4248;
-			} else if ((rev & 0x0f) == 0x0a) {
-				snd_ad1848_out(chip, AD1848_MISC_INFO, 0x40);
-				for (i = 0; i < 16; ++i) {
-					if (snd_ad1848_in(chip, i) != snd_ad1848_in(chip, i + 16)) {
-						chip->hardware = WSS_HW_CMI8330;
-						break;
-					}
-				}
-				snd_ad1848_out(chip, AD1848_MISC_INFO, 0x00);
-			}
-		}
-	}
-	spin_lock_irqsave(&chip->reg_lock, flags);
-	inb(chip->port + CS4231P(STATUS));	/* clear any pendings IRQ */
-	outb(0, chip->port + CS4231P(STATUS));
-	mb();
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
-
-	chip->image[AD1848_MISC_INFO] = 0x00;
-	chip->image[AD1848_IFACE_CTRL] =
-	    (chip->image[AD1848_IFACE_CTRL] & ~AD1848_SINGLE_DMA) | AD1848_SINGLE_DMA;
-	ptr = (unsigned char *) &chip->image;
-	snd_ad1848_mce_down(chip);
-	spin_lock_irqsave(&chip->reg_lock, flags);
-	for (i = 0; i < 16; i++)	/* ok.. fill all AD1848 registers */
-		snd_ad1848_out(chip, i, *ptr++);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
-	snd_ad1848_mce_up(chip);
-	/* init needed for WSS pcm */
-	spin_lock_irqsave(&chip->reg_lock, flags);
-	chip->image[AD1848_IFACE_CTRL] &= ~(AD1848_PLAYBACK_ENABLE |
-				AD1848_PLAYBACK_PIO |
-				AD1848_CAPTURE_ENABLE |
-				AD1848_CAPTURE_PIO |
-				AD1848_CALIB_MODE);
-	chip->image[AD1848_IFACE_CTRL] |= AD1848_AUTOCALIB;
-	snd_ad1848_out(chip, AD1848_IFACE_CTRL, chip->image[AD1848_IFACE_CTRL]);
-	spin_unlock_irqrestore(&chip->reg_lock, flags);
-	snd_ad1848_mce_down(chip);
-	return 0;		/* all things are ok.. */
-}
-
-/*
-
- */
-
-static int snd_ad1848_free(struct snd_wss *chip)
-{
-	release_and_free_resource(chip->res_port);
-	if (chip->irq >= 0)
-		free_irq(chip->irq, (void *) chip);
-	if (chip->dma1 >= 0) {
-		snd_dma_disable(chip->dma1);
-		free_dma(chip->dma1);
-	}
-	kfree(chip);
-	return 0;
-}
-
-static int snd_ad1848_dev_free(struct snd_device *device)
-{
-	struct snd_wss *chip = device->device_data;
-	return snd_ad1848_free(chip);
-}
-
-int snd_ad1848_create(struct snd_card *card,
-		      unsigned long port,
-		      int irq, int dma,
-		      unsigned short hardware,
-		      struct snd_wss **rchip)
-{
-	static struct snd_device_ops ops = {
-		.dev_free =	snd_ad1848_dev_free,
-	};
-	struct snd_wss *chip;
-	int err;
-
-	*rchip = NULL;
-	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-	if (chip == NULL)
-		return -ENOMEM;
-	spin_lock_init(&chip->reg_lock);
-	chip->card = card;
-	chip->port = port;
-	chip->irq = -1;
-	chip->dma1 = -1;
-	chip->dma2 = -1;
-	chip->single_dma = 1;
-	chip->hardware = hardware;
-	memcpy(&chip->image, &snd_ad1848_original_image, sizeof(snd_ad1848_original_image));
-	
-	if ((chip->res_port = request_region(port, 4, "AD1848")) == NULL) {
-		snd_printk(KERN_ERR "ad1848: can't grab port 0x%lx\n", port);
-		snd_ad1848_free(chip);
-		return -EBUSY;
-	}
-	if (request_irq(irq, snd_ad1848_interrupt, IRQF_DISABLED, "AD1848", (void *) chip)) {
-		snd_printk(KERN_ERR "ad1848: can't grab IRQ %d\n", irq);
-		snd_ad1848_free(chip);
-		return -EBUSY;
-	}
-	chip->irq = irq;
-	if (request_dma(dma, "AD1848")) {
-		snd_printk(KERN_ERR "ad1848: can't grab DMA %d\n", dma);
-		snd_ad1848_free(chip);
-		return -EBUSY;
-	}
-	chip->dma1 = dma;
-	chip->dma2 = dma;
-
-	if (hardware == WSS_HW_THINKPAD) {
-		chip->thinkpad_flag = 1;
-		chip->hardware = WSS_HW_DETECT; /* reset */
-		snd_ad1848_thinkpad_twiddle(chip, 1);
-	}
-
-	if (snd_ad1848_probe(chip) < 0) {
-		snd_ad1848_free(chip);
-		return -ENODEV;
-	}
-
-	/* Register device */
-	if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
-		snd_ad1848_free(chip);
-		return err;
-	}
-
-#ifdef CONFIG_PM
-	chip->suspend = snd_ad1848_suspend;
-	chip->resume = snd_ad1848_resume;
-#endif
-
-	*rchip = chip;
-	return 0;
-}
-
-EXPORT_SYMBOL(snd_ad1848_create);
-
-/*
- *  INIT part
- */
-
-static int __init alsa_ad1848_init(void)
-{
-	return 0;
-}
-
-static void __exit alsa_ad1848_exit(void)
-{
-}
-
-module_init(alsa_ad1848_init)
-module_exit(alsa_ad1848_exit)
diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c
index 6f7e8bb6ae60..e49aec700a55 100644
--- a/sound/isa/cmi8330.c
+++ b/sound/isa/cmi8330.c
@@ -50,7 +50,7 @@
 #include <linux/pnp.h>
 #include <linux/moduleparam.h>
 #include <sound/core.h>
-#include <sound/ad1848.h>
+#include <sound/wss.h>
 #include <sound/sb.h>
 #include <sound/initval.h>
 
@@ -180,9 +180,9 @@ WSS_DOUBLE("Master Playback Volume", 0,
 WSS_SINGLE("Loud Playback Switch", 0,
 		CMI8330_MUTEMUX, 6, 1, 1),
 WSS_DOUBLE("PCM Playback Switch", 0,
-		AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 7, 7, 1, 1),
+		CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
 WSS_DOUBLE("PCM Playback Volume", 0,
-		AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 0, 0, 63, 1),
+		CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1),
 WSS_DOUBLE("Line Playback Switch", 0,
 		CMI8330_MUTEMUX, CMI8330_MUTEMUX, 4, 3, 1, 0),
 WSS_DOUBLE("Line Playback Volume", 0,
@@ -489,12 +489,11 @@ static int __devinit snd_cmi8330_probe(struct snd_card *card, int dev)
 	int i, err;
 
 	acard = card->private_data;
-	if ((err = snd_ad1848_create(card,
-				     wssport[dev] + 4,
-				     wssirq[dev],
-				     wssdma[dev],
-				     WSS_HW_DETECT,
-				     &acard->wss)) < 0) {
+	err = snd_wss_create(card, wssport[dev] + 4, -1,
+			     wssirq[dev],
+			     wssdma[dev], -1,
+			     WSS_HW_DETECT, 0, &acard->wss);
+	if (err < 0) {
 		snd_printk(KERN_ERR PFX "(AD1848) device busy??\n");
 		return err;
 	}
@@ -517,9 +516,10 @@ static int __devinit snd_cmi8330_probe(struct snd_card *card, int dev)
 		return err;
 	}
 
-	snd_ad1848_out(acard->wss, AD1848_MISC_INFO, 0x40); /* switch on MODE2 */
+	snd_wss_out(acard->wss, CS4231_MISC_INFO, 0x40); /* switch on MODE2 */
 	for (i = CMI8330_RMUX3D; i <= CMI8330_CDINGAIN; i++)
-		snd_ad1848_out(acard->wss, i, snd_cmi8330_image[i - CMI8330_RMUX3D]);
+		snd_wss_out(acard->wss, i,
+			    snd_cmi8330_image[i - CMI8330_RMUX3D]);
 
 	if ((err = snd_cmi8330_mixer(card, acard)) < 0) {
 		snd_printk(KERN_ERR PFX "failed to create mixers\n");
diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c
index 561d4b3ed098..cb5f66bde5d3 100644
--- a/sound/isa/opti9xx/opti92x-ad1848.c
+++ b/sound/isa/opti9xx/opti92x-ad1848.c
@@ -33,11 +33,7 @@
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <sound/core.h>
-#if defined(CS4231) || defined(OPTi93X)
 #include <sound/wss.h>
-#else
-#include <sound/ad1848.h>
-#endif	/* CS4231 */
 #include <sound/mpu401.h>
 #include <sound/opl3.h>
 #ifndef OPTi93X
@@ -148,9 +144,7 @@ struct snd_opti9xx {
 	long wss_base;
 	int irq;
 	int dma1;
-#if defined(CS4231) || defined(OPTi93X)
 	int dma2;
-#endif	/* CS4231 || OPTi93X */
 
 	long fm_port;
 
@@ -225,9 +219,7 @@ static int __devinit snd_opti9xx_init(struct snd_opti9xx *chip,
 	chip->wss_base = -1;
 	chip->irq = -1;
 	chip->dma1 = -1;
-#if defined(CS4231) || defined (OPTi93X)
 	chip->dma2 = -1;
-#endif 	/* CS4231 || OPTi93X */
 	chip->fm_port = -1;
 	chip->mpu_port = -1;
 	chip->mpu_irq = -1;
@@ -740,7 +732,6 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card)
 	if (error)
 		return error;
 
-#if defined(CS4231) || defined(OPTi93X)
 	error = snd_wss_create(card, chip->wss_base + 4, -1,
 			       chip->irq, chip->dma1, chip->dma2,
 #ifdef CS4231
@@ -754,12 +745,6 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card)
 #ifdef OPTi93X
 	chip->codec = codec;
 #endif
-#else
-	error = snd_ad1848_create(card, chip->wss_base + 4, chip->irq,
-				  chip->dma1, WSS_HW_DETECT, &codec);
-	if (error < 0)
-		return error;
-#endif
 	error = snd_wss_pcm(codec, 0, &pcm);
 	if (error < 0)
 		return error;
diff --git a/sound/isa/sc6000.c b/sound/isa/sc6000.c
index 2f89ecb95ded..ca35924dc3b3 100644
--- a/sound/isa/sc6000.c
+++ b/sound/isa/sc6000.c
@@ -29,7 +29,7 @@
 #include <linux/io.h>
 #include <asm/dma.h>
 #include <sound/core.h>
-#include <sound/ad1848.h>
+#include <sound/wss.h>
 #include <sound/opl3.h>
 #include <sound/mpu401.h>
 #include <sound/control.h>
@@ -548,8 +548,8 @@ static int __devinit snd_sc6000_probe(struct device *devptr, unsigned int dev)
 	if (err < 0)
 		goto err_unmap2;
 
-	err = snd_ad1848_create(card, mss_port[dev] + 4, xirq, xdma,
-				WSS_HW_DETECT, &chip);
+	err = snd_wss_create(card, mss_port[dev] + 4,  -1, xirq, xdma, -1,
+			     WSS_HW_DETECT, 0, &chip);
 	if (err < 0)
 		goto err_unmap2;
 	card->private_data = chip;
diff --git a/sound/isa/sgalaxy.c b/sound/isa/sgalaxy.c
index b43d6678ba20..2c7503bf1271 100644
--- a/sound/isa/sgalaxy.c
+++ b/sound/isa/sgalaxy.c
@@ -31,7 +31,7 @@
 #include <asm/dma.h>
 #include <sound/core.h>
 #include <sound/sb.h>
-#include <sound/ad1848.h>
+#include <sound/wss.h>
 #include <sound/control.h>
 #define SNDRV_LEGACY_FIND_FREE_IRQ
 #define SNDRV_LEGACY_FIND_FREE_DMA
@@ -267,9 +267,10 @@ static int __devinit snd_sgalaxy_probe(struct device *devptr, unsigned int dev)
 	if ((err = snd_sgalaxy_detect(dev, xirq, xdma1)) < 0)
 		goto _err;
 
-	if ((err = snd_ad1848_create(card, wssport[dev] + 4,
-				     xirq, xdma1,
-				     WSS_HW_DETECT, &chip)) < 0)
+	err = snd_wss_create(card, wssport[dev] + 4, -1,
+			     xirq, xdma1, -1,
+			     WSS_HW_DETECT, 0, &chip);
+	if (err < 0)
 		goto _err;
 	card->private_data = chip;
 
@@ -331,8 +332,8 @@ static int snd_sgalaxy_resume(struct device *pdev, unsigned int n)
 	struct snd_wss *chip = card->private_data;
 
 	chip->resume(chip);
-	snd_ad1848_out(chip, SGALAXY_AUXC_LEFT, chip->image[SGALAXY_AUXC_LEFT]);
-	snd_ad1848_out(chip, SGALAXY_AUXC_RIGHT, chip->image[SGALAXY_AUXC_RIGHT]);
+	snd_wss_out(chip, SGALAXY_AUXC_LEFT, chip->image[SGALAXY_AUXC_LEFT]);
+	snd_wss_out(chip, SGALAXY_AUXC_RIGHT, chip->image[SGALAXY_AUXC_RIGHT]);
 
 	snd_power_change_state(card, SNDRV_CTL_POWER_D0);
 	return 0;
diff --git a/sound/isa/wss/wss_lib.c b/sound/isa/wss/wss_lib.c
index 57d1e8ee6bbb..a5602f515f49 100644
--- a/sound/isa/wss/wss_lib.c
+++ b/sound/isa/wss/wss_lib.c
@@ -1073,7 +1073,11 @@ irqreturn_t snd_wss_interrupt(int irq, void *dev_id)
 	struct snd_wss *chip = dev_id;
 	unsigned char status;
 
-	status = snd_wss_in(chip, CS4231_IRQ_STATUS);
+	if (chip->hardware & WSS_HW_AD1848_MASK)
+		/* pretend it was the only possible irq for AD1848 */
+		status = CS4231_PLAYBACK_IRQ;
+	else
+		status = snd_wss_in(chip, CS4231_IRQ_STATUS);
 	if (status & CS4231_TIMER_IRQ) {
 		if (chip->timer)
 			snd_timer_interrupt(chip->timer, chip->timer->sticks);
@@ -1105,7 +1109,11 @@ irqreturn_t snd_wss_interrupt(int irq, void *dev_id)
 	}
 
 	spin_lock(&chip->reg_lock);
-	snd_wss_outm(chip, CS4231_IRQ_STATUS, ~CS4231_ALL_IRQS | ~status, 0);
+	status = ~CS4231_ALL_IRQS | ~status;
+	if (chip->hardware & WSS_HW_AD1848_MASK)
+		wss_outb(chip, CS4231P(STATUS), 0);
+	else
+		snd_wss_outm(chip, CS4231_IRQ_STATUS, status, 0);
 	spin_unlock(&chip->reg_lock);
 	return IRQ_HANDLED;
 }
@@ -1137,36 +1145,112 @@ static snd_pcm_uframes_t snd_wss_capture_pointer(struct snd_pcm_substream *subst
 
  */
 
-static int snd_wss_probe(struct snd_wss *chip)
+static int snd_ad1848_probe(struct snd_wss *chip)
 {
 	unsigned long flags;
-	int i, id, rev;
-	unsigned char *ptr;
-	unsigned int hw;
+	int i, id, rev, ad1847;
 
-#if 0
-	snd_wss_debug(chip);
-#endif
 	id = 0;
-	for (i = 0; i < 50; i++) {
+	ad1847 = 0;
+	for (i = 0; i < 1000; i++) {
 		mb();
-		if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
-			udelay(2000);
+		if (inb(chip->port + CS4231P(REGSEL)) & CS4231_INIT)
+			msleep(1);
 		else {
 			spin_lock_irqsave(&chip->reg_lock, flags);
-			snd_wss_out(chip, CS4231_MISC_INFO, CS4231_MODE2);
-			id = snd_wss_in(chip, CS4231_MISC_INFO) & 0x0f;
+			snd_wss_out(chip, CS4231_MISC_INFO, 0x00);
+			snd_wss_out(chip, CS4231_LEFT_INPUT, 0xaa);
+			snd_wss_out(chip, CS4231_RIGHT_INPUT, 0x45);
+			rev = snd_wss_in(chip, CS4231_RIGHT_INPUT);
+			if (rev == 0x65) {
+				spin_unlock_irqrestore(&chip->reg_lock, flags);
+				id = 1;
+				ad1847 = 1;
+				break;
+			}
+			if (snd_wss_in(chip, CS4231_LEFT_INPUT) == 0xaa &&
+			    rev == 0x45) {
+				spin_unlock_irqrestore(&chip->reg_lock, flags);
+				id = 1;
+				break;
+			}
 			spin_unlock_irqrestore(&chip->reg_lock, flags);
-			if (id == 0x0a)
-				break;	/* this is valid value */
 		}
 	}
-	snd_printdd("wss: port = 0x%lx, id = 0x%x\n", chip->port, id);
-	if (id != 0x0a)
+	if (id != 1)
 		return -ENODEV;	/* no valid device found */
+	id = 0;
+	if (chip->hardware == WSS_HW_DETECT)
+		id = ad1847 ? WSS_HW_AD1847 : WSS_HW_AD1848;
+
+	spin_lock_irqsave(&chip->reg_lock, flags);
+	inb(chip->port + CS4231P(STATUS));	/* clear any pendings IRQ */
+	outb(0, chip->port + CS4231P(STATUS));
+	mb();
+	if (id == WSS_HW_AD1848) {
+		/* check if there are more than 16 registers */
+		rev = snd_wss_in(chip, CS4231_MISC_INFO);
+		snd_wss_out(chip, CS4231_MISC_INFO, 0x40);
+		for (i = 0; i < 16; ++i) {
+			if (snd_wss_in(chip, i) != snd_wss_in(chip, i + 16)) {
+				id = WSS_HW_CMI8330;
+				break;
+			}
+		}
+		snd_wss_out(chip, CS4231_MISC_INFO, 0x00);
+		if (id != WSS_HW_CMI8330 && (rev & 0x80))
+			id = WSS_HW_CS4248;
+		if (id == WSS_HW_CMI8330 && (rev & 0x0f) != 0x0a)
+			id = 0;
+	}
+	if (id == WSS_HW_CMI8330) {
+		/* verify it is not CS4231 by changing the version register */
+		/* on CMI8330 it is volume control register and can be set 0 */
+		snd_wss_out(chip, CS4231_MISC_INFO, CS4231_MODE2);
+		snd_wss_dout(chip, CS4231_VERSION, 0x00);
+		rev = snd_wss_in(chip, CS4231_VERSION) & 0xe7;
+		if (rev)
+			id = 0;
+		snd_wss_out(chip, CS4231_MISC_INFO, 0);
+	}
+	if (id)
+		chip->hardware = id;
+
+	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	return 0;		/* all things are ok.. */
+}
+
+static int snd_wss_probe(struct snd_wss *chip)
+{
+	unsigned long flags;
+	int i, id, rev, regnum;
+	unsigned char *ptr;
+	unsigned int hw;
+
+	id = snd_ad1848_probe(chip);
+	if (id < 0)
+		return id;
 
 	hw = chip->hardware;
 	if ((hw & WSS_HW_TYPE_MASK) == WSS_HW_DETECT) {
+		for (i = 0; i < 50; i++) {
+			mb();
+			if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
+				msleep(2);
+			else {
+				spin_lock_irqsave(&chip->reg_lock, flags);
+				snd_wss_out(chip, CS4231_MISC_INFO,
+					    CS4231_MODE2);
+				id = snd_wss_in(chip, CS4231_MISC_INFO) & 0x0f;
+				spin_unlock_irqrestore(&chip->reg_lock, flags);
+				if (id == 0x0a)
+					break;	/* this is valid value */
+			}
+		}
+		snd_printdd("wss: port = 0x%lx, id = 0x%x\n", chip->port, id);
+		if (id != 0x0a)
+			return -ENODEV;	/* no valid device found */
+
 		rev = snd_wss_in(chip, CS4231_VERSION) & 0xe7;
 		snd_printdd("CS4231: VERSION (I25) = 0x%x\n", rev);
 		if (rev == 0x80) {
@@ -1197,7 +1281,8 @@ static int snd_wss_probe(struct snd_wss *chip)
 	mb();
 	spin_unlock_irqrestore(&chip->reg_lock, flags);
 
-	chip->image[CS4231_MISC_INFO] = CS4231_MODE2;
+	if (!(chip->hardware & WSS_HW_AD1848_MASK))
+		chip->image[CS4231_MISC_INFO] = CS4231_MODE2;
 	switch (chip->hardware) {
 	case WSS_HW_INTERWAVE:
 		chip->image[CS4231_MISC_INFO] = CS4231_IW_MODE3;
@@ -1223,9 +1308,10 @@ static int snd_wss_probe(struct snd_wss *chip)
 			chip->hardware == WSS_HW_INTERWAVE ? 0xc2 : 0x01;
 	}
 	ptr = (unsigned char *) &chip->image;
+	regnum = (chip->hardware & WSS_HW_AD1848_MASK) ? 16 : 32;
 	snd_wss_mce_down(chip);
 	spin_lock_irqsave(&chip->reg_lock, flags);
-	for (i = 0; i < 32; i++)	/* ok.. fill all CS4231 registers */
+	for (i = 0; i < regnum; i++)	/* ok.. fill all registers */
 		snd_wss_out(chip, i, *ptr++);
 	spin_unlock_irqrestore(&chip->reg_lock, flags);
 	snd_wss_mce_up(chip);
@@ -1635,6 +1721,10 @@ static int snd_wss_new(struct snd_card *card,
 	else
 		memcpy(&chip->image, &snd_wss_original_image,
 		       sizeof(snd_wss_original_image));
+	if (chip->hardware & WSS_HW_AD1848_MASK) {
+		chip->image[CS4231_PIN_CTRL] = 0;
+		chip->image[CS4231_TEST_INIT] = 0;
+	}
 
 	*rchip = chip;
 	return 0;
@@ -1662,7 +1752,7 @@ int snd_wss_create(struct snd_card *card,
 	chip->dma1 = -1;
 	chip->dma2 = -1;
 
-	chip->res_port = request_region(port, 4, "CS4231");
+	chip->res_port = request_region(port, 4, "WSS");
 	if (!chip->res_port) {
 		snd_printk(KERN_ERR "wss: can't grab port 0x%lx\n", port);
 		snd_wss_free(chip);
@@ -1681,20 +1771,20 @@ int snd_wss_create(struct snd_card *card,
 	chip->cport = cport;
 	if (!(hwshare & WSS_HWSHARE_IRQ))
 		if (request_irq(irq, snd_wss_interrupt, IRQF_DISABLED,
-				"CS4231", (void *) chip)) {
+				"WSS", (void *) chip)) {
 			snd_printk(KERN_ERR "wss: can't grab IRQ %d\n", irq);
 			snd_wss_free(chip);
 			return -EBUSY;
 		}
 	chip->irq = irq;
-	if (!(hwshare & WSS_HWSHARE_DMA1) && request_dma(dma1, "CS4231 - 1")) {
+	if (!(hwshare & WSS_HWSHARE_DMA1) && request_dma(dma1, "WSS - 1")) {
 		snd_printk(KERN_ERR "wss: can't grab DMA1 %d\n", dma1);
 		snd_wss_free(chip);
 		return -EBUSY;
 	}
 	chip->dma1 = dma1;
 	if (!(hwshare & WSS_HWSHARE_DMA2) && dma1 != dma2 &&
-	      dma2 >= 0 && request_dma(dma2, "CS4231 - 2")) {
+	      dma2 >= 0 && request_dma(dma2, "WSS - 2")) {
 		snd_printk(KERN_ERR "wss: can't grab DMA2 %d\n", dma2);
 		snd_wss_free(chip);
 		return -EBUSY;
@@ -1705,6 +1795,12 @@ int snd_wss_create(struct snd_card *card,
 	} else
 		chip->dma2 = dma2;
 
+	if (hardware == WSS_HW_THINKPAD) {
+		chip->thinkpad_flag = 1;
+		chip->hardware = WSS_HW_DETECT; /* reset */
+		snd_wss_thinkpad_twiddle(chip, 1);
+	}
+
 	/* global setup */
 	if (snd_wss_probe(chip) < 0) {
 		snd_wss_free(chip);
@@ -1775,12 +1871,6 @@ int snd_wss_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm)
 	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_wss_playback_ops);
 	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_wss_capture_ops);
 
-	/* temporary */
-	if (chip->hardware & WSS_HW_AD1848_MASK) {
-		chip->rate_constraint = snd_wss_xrate;
-		chip->set_playback_format = snd_wss_playback_format;
-		chip->set_capture_format = snd_wss_capture_format;
-	}
 	/* global setup */
 	pcm->private_data = chip;
 	pcm->info_flags = 0;