summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Documentation/sound/alsa/ALSA-Configuration.txt21
-rw-r--r--Documentation/sound/alsa/Bt87x.txt4
-rw-r--r--MAINTAINERS6
-rw-r--r--include/linux/i2c-id.h1
-rw-r--r--include/sound/ak4114.h4
-rw-r--r--include/sound/mpu401.h1
-rw-r--r--include/sound/pcm.h7
-rw-r--r--include/sound/version.h4
-rw-r--r--sound/aoa/codecs/snd-aoa-codec-onyx.c4
-rw-r--r--sound/aoa/codecs/snd-aoa-codec-tas.c4
-rw-r--r--sound/aoa/soundbus/core.c2
-rw-r--r--sound/aoa/soundbus/i2sbus/i2sbus-core.c5
-rw-r--r--sound/aoa/soundbus/soundbus.h2
-rw-r--r--sound/core/pcm_native.c30
-rw-r--r--sound/core/rtctimer.c3
-rw-r--r--sound/drivers/mpu401/mpu401.c12
-rw-r--r--sound/drivers/mpu401/mpu401_uart.c18
-rw-r--r--sound/drivers/mts64.c4
-rw-r--r--sound/drivers/portman2x4.c4
-rw-r--r--sound/drivers/vx/vx_hwdep.c14
-rw-r--r--sound/i2c/other/ak4114.c114
-rw-r--r--sound/isa/Kconfig22
-rw-r--r--sound/isa/ad1816a/ad1816a.c8
-rw-r--r--sound/isa/ad1848/ad1848.c167
-rw-r--r--sound/isa/adlib.c122
-rw-r--r--sound/isa/cmi8330.c115
-rw-r--r--sound/isa/cs423x/cs4231.c213
-rw-r--r--sound/isa/cs423x/cs4231_lib.c4
-rw-r--r--sound/isa/cs423x/cs4236.c131
-rw-r--r--sound/isa/es1688/es1688.c251
-rw-r--r--sound/isa/es18xx.c110
-rw-r--r--sound/isa/gus/gusclassic.c292
-rw-r--r--sound/isa/gus/gusextreme.c379
-rw-r--r--sound/isa/gus/gusmax.c71
-rw-r--r--sound/isa/gus/interwave.c101
-rw-r--r--sound/isa/opl3sa2.c127
-rw-r--r--sound/isa/opti9xx/miro.c80
-rw-r--r--sound/isa/opti9xx/opti92x-ad1848.c108
-rw-r--r--sound/isa/sb/sb16.c113
-rw-r--r--sound/isa/sb/sb16_csp.c30
-rw-r--r--sound/isa/sb/sb8.c90
-rw-r--r--sound/isa/sgalaxy.c107
-rw-r--r--sound/isa/sscape.c120
-rw-r--r--sound/isa/wavefront/wavefront.c113
-rw-r--r--sound/isa/wavefront/wavefront_fx.c23
-rw-r--r--sound/pci/Kconfig33
-rw-r--r--sound/pci/ac97/Makefile2
-rw-r--r--sound/pci/ac97/ac97_codec.c43
-rw-r--r--sound/pci/ac97/ac97_local.h55
-rw-r--r--sound/pci/ac97/ac97_patch.c194
-rw-r--r--sound/pci/ac97/ac97_patch.h110
-rw-r--r--sound/pci/ac97/ac97_pcm.c1
-rw-r--r--sound/pci/ali5451/ali5451.c869
-rw-r--r--sound/pci/au88x0/au88x0_sb.h40
-rw-r--r--sound/pci/azt3328.c34
-rw-r--r--sound/pci/azt3328.h4
-rw-r--r--sound/pci/bt87x.c4
-rw-r--r--sound/pci/ca0106/ca0106_main.c4
-rw-r--r--sound/pci/cs46xx/cs46xx_lib.c2
-rw-r--r--sound/pci/cs46xx/imgs/cwcemb80.h1607
-rw-r--r--sound/pci/echoaudio/darla20.c2
-rw-r--r--sound/pci/echoaudio/darla24.c2
-rw-r--r--sound/pci/echoaudio/echo3g.c4
-rw-r--r--sound/pci/echoaudio/echoaudio.c4
-rw-r--r--sound/pci/echoaudio/echoaudio_3g.c4
-rw-r--r--sound/pci/echoaudio/gina20.c2
-rw-r--r--sound/pci/echoaudio/gina24.c6
-rw-r--r--sound/pci/echoaudio/indigo.c3
-rw-r--r--sound/pci/echoaudio/indigodj.c3
-rw-r--r--sound/pci/echoaudio/indigoio.c3
-rw-r--r--sound/pci/echoaudio/layla20.c3
-rw-r--r--sound/pci/echoaudio/layla24.c6
-rw-r--r--sound/pci/echoaudio/mia.c3
-rw-r--r--sound/pci/echoaudio/mona.c9
-rw-r--r--sound/pci/emu10k1/emu10k1_main.c24
-rw-r--r--sound/pci/emu10k1/p16v.c4
-rw-r--r--sound/pci/ens1370.c8
-rw-r--r--sound/pci/es1968.c11
-rw-r--r--sound/pci/hda/Makefile9
-rw-r--r--sound/pci/hda/hda_codec.c729
-rw-r--r--sound/pci/hda/hda_codec.h2
-rw-r--r--sound/pci/hda/hda_generic.c2
-rw-r--r--sound/pci/hda/hda_intel.c31
-rw-r--r--sound/pci/hda/hda_local.h12
-rw-r--r--sound/pci/hda/patch_analog.c85
-rw-r--r--sound/pci/hda/patch_atihdmi.c17
-rw-r--r--sound/pci/hda/patch_cmedia.c14
-rw-r--r--sound/pci/hda/patch_conexant.c310
-rw-r--r--sound/pci/hda/patch_realtek.c2269
-rw-r--r--sound/pci/hda/patch_sigmatel.c178
-rw-r--r--sound/pci/hda/patch_via.c14
-rw-r--r--sound/pci/ice1712/amp.c2
-rw-r--r--sound/pci/ice1712/amp.h2
-rw-r--r--sound/pci/ice1712/aureon.c18
-rw-r--r--sound/pci/ice1712/aureon.h2
-rw-r--r--sound/pci/ice1712/delta.c34
-rw-r--r--sound/pci/ice1712/delta.h2
-rw-r--r--sound/pci/ice1712/ews.c24
-rw-r--r--sound/pci/ice1712/ews.h2
-rw-r--r--sound/pci/ice1712/hoontech.c6
-rw-r--r--sound/pci/ice1712/hoontech.h2
-rw-r--r--sound/pci/ice1712/ice1712.c50
-rw-r--r--sound/pci/ice1712/ice1712.h3
-rw-r--r--sound/pci/ice1712/ice1724.c47
-rw-r--r--sound/pci/ice1712/juli.c24
-rw-r--r--sound/pci/ice1712/juli.h2
-rw-r--r--sound/pci/ice1712/phase.c14
-rw-r--r--sound/pci/ice1712/phase.h2
-rw-r--r--sound/pci/ice1712/pontis.c6
-rw-r--r--sound/pci/ice1712/pontis.h2
-rw-r--r--sound/pci/ice1712/prodigy192.c360
-rw-r--r--sound/pci/ice1712/prodigy192.h10
-rw-r--r--sound/pci/ice1712/revo.c26
-rw-r--r--sound/pci/ice1712/revo.h2
-rw-r--r--sound/pci/ice1712/vt1720_mobo.c6
-rw-r--r--sound/pci/ice1712/vt1720_mobo.h2
-rw-r--r--sound/pci/ice1712/wtm.c2
-rw-r--r--sound/pci/intel8x0.c20
-rw-r--r--sound/pci/korg1212/korg1212.c25
-rw-r--r--sound/pci/maestro3.c38
-rw-r--r--sound/pci/mixart/mixart_hwdep.c3
-rw-r--r--sound/pci/pcxhr/pcxhr.c28
-rw-r--r--sound/pci/pcxhr/pcxhr_hwdep.c6
-rw-r--r--sound/pci/riptide/riptide.c1
-rw-r--r--sound/pci/rme32.c7
-rw-r--r--sound/pci/rme9652/hdsp.c99
-rw-r--r--sound/pci/rme9652/hdspm.c185
-rw-r--r--sound/pci/rme9652/rme9652.c8
-rw-r--r--sound/pci/trident/trident_main.c4
-rw-r--r--sound/pci/ymfpci/ymfpci_main.c55
-rw-r--r--sound/pcmcia/vx/vxpocket.c2
-rw-r--r--sound/soc/Kconfig18
-rw-r--r--sound/soc/Makefile2
-rw-r--r--sound/soc/at91/Kconfig10
-rw-r--r--sound/soc/at91/Makefile4
-rw-r--r--sound/soc/at91/at91-ssc.c (renamed from sound/soc/at91/at91-i2s.c)259
-rw-r--r--sound/soc/at91/at91-ssc.h (renamed from sound/soc/at91/at91-i2s.h)14
-rw-r--r--sound/soc/at91/eti_b1_wm8731.c8
-rw-r--r--sound/soc/codecs/Kconfig4
-rw-r--r--sound/soc/codecs/Makefile2
-rw-r--r--sound/soc/codecs/ac97.c1
-rw-r--r--sound/soc/codecs/ac97.h1
-rw-r--r--sound/soc/codecs/wm8750.c2
-rw-r--r--sound/soc/codecs/wm8753.c1811
-rw-r--r--sound/soc/codecs/wm8753.h126
-rw-r--r--sound/soc/codecs/wm9712.c7
-rw-r--r--sound/soc/pxa/Kconfig4
-rw-r--r--sound/soc/s3c24xx/Kconfig10
-rw-r--r--sound/soc/s3c24xx/Makefile6
-rw-r--r--sound/soc/s3c24xx/s3c24xx-i2s.c441
-rw-r--r--sound/soc/s3c24xx/s3c24xx-i2s.h37
-rw-r--r--sound/soc/s3c24xx/s3c24xx-pcm.c468
-rw-r--r--sound/soc/s3c24xx/s3c24xx-pcm.h31
-rw-r--r--sound/soc/soc-dapm.c6
-rw-r--r--sound/sparc/cs4231.c4
-rw-r--r--sound/usb/Kconfig28
-rw-r--r--sound/usb/Makefile2
-rw-r--r--sound/usb/caiaq/Makefile3
-rw-r--r--sound/usb/caiaq/caiaq-audio.c707
-rw-r--r--sound/usb/caiaq/caiaq-audio.h7
-rw-r--r--sound/usb/caiaq/caiaq-device.c436
-rw-r--r--sound/usb/caiaq/caiaq-device.h116
-rw-r--r--sound/usb/caiaq/caiaq-input.c246
-rw-r--r--sound/usb/caiaq/caiaq-input.h8
-rw-r--r--sound/usb/caiaq/caiaq-midi.c177
-rw-r--r--sound/usb/caiaq/caiaq-midi.h8
-rw-r--r--sound/usb/usbaudio.c3
-rw-r--r--sound/usb/usbmidi.c58
-rw-r--r--sound/usb/usbquirks.h23
169 files changed, 10637 insertions, 5530 deletions
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index 73e9a174b642..57b878cc393c 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -821,6 +821,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
 	  6stack-dig	6-jack digital with SPDIF I/O
 	  arima		Arima W820Di1
 	  macpro	MacPro support
+	  w2jc		ASUS W2JC
 	  auto		auto-config reading BIOS (default)
 
 	ALC883/888
@@ -852,6 +853,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
 	  3stack-dig	3-jack with SPDIF OUT
 	  6stack-dig	6-jack with SPDIF OUT
 	  3stack-660	3-jack (for ALC660VD)
+	  lenovo	Lenovo 3000 C200
 	  auto		auto-config reading BIOS (default)
 
 	CMI9880
@@ -909,6 +911,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
 	  macbook	Intel Mac Book
 	  macbook-pro-v1 Intel Mac Book Pro 1st generation
 	  macbook-pro	Intel Mac Book Pro 2nd generation
+	  imac-intel	Intel iMac
 
 	STAC9202/9250/9251
 	  ref		Reference board, base config
@@ -924,6 +927,10 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
 	  vaio		Setup for VAIO FE550G/SZ110
 	  vaio-ar Setup for VAIO AR
 
+    The model name "genric" is treated as a special case.  When this
+    model is given, the driver uses the generic codec parser without
+    "codec-patch".  It's sometimes good for testing and debugging.
+
     If the default configuration doesn't work and one of the above
     matches with your device, report it together with the PCI
     subsystem ID (output of "lspci -nv") to ALSA BTS or alsa-devel
@@ -1278,6 +1285,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
     port	- port number or -1 (disable)
     irq		- IRQ number or -1 (disable)
     pnp		- PnP detection - 0 = disable, 1 = enable (default)
+    uart_enter	- Issue UART_ENTER command at open - bool, default = on
 
     This module supports multiple devices and PnP.
     
@@ -1692,6 +1700,17 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
 
     This module supports multiple devices, autoprobe and hotplugging.
 
+  Module snd-usb-caiaq
+  --------------------
+
+    Module for caiaq UB audio interfaces,
+	    * Native Instruments RigKontrol2
+	    * Native Instruments Kore Controller
+	    * Native Instruments Audio Kontrol 1
+	    * Native Instruments Audio 8 DJ
+
+    This module supports multiple devices, autoprobe and hotplugging.
+
   Module snd-usb-usx2y
   --------------------
 
@@ -2046,4 +2065,4 @@ Links and Addresses
        https://bugtrack.alsa-project.org/bugs/
 
   ALSA Developers ML
-       mailto:alsa-devel@lists.sourceforge.net
+       mailto:alsa-devel@alsa-project.org
diff --git a/Documentation/sound/alsa/Bt87x.txt b/Documentation/sound/alsa/Bt87x.txt
index 11edb2fd2a5a..f158cde8b065 100644
--- a/Documentation/sound/alsa/Bt87x.txt
+++ b/Documentation/sound/alsa/Bt87x.txt
@@ -36,8 +36,8 @@ recorded data is not right, try to specify the digital_rate option with
 other values than the default 32000 (often it's 44100 or 64000).
 
 If you have an unknown card, please mail the ID and board name to
-<alsa-devel@lists.sf.net>, regardless of whether audio capture works or
-not, so that future versions of this driver know about your card.
+<alsa-devel@alsa-project.org>, regardless of whether audio capture works
+or not, so that future versions of this driver know about your card.
 
 
 Audio modes
diff --git a/MAINTAINERS b/MAINTAINERS
index bd558ac5bb73..975f263f5c21 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -372,7 +372,7 @@ AOA (Apple Onboard Audio) ALSA DRIVER
 P:	Johannes Berg
 M:	johannes@sipsolutions.net
 L:	linuxppc-dev@ozlabs.org
-L:	alsa-devel@alsa-project.org
+L:	alsa-devel@alsa-project.org (subscribers-only)
 S:	Maintained
 
 APM DRIVER
@@ -3239,13 +3239,13 @@ S:	Maintained
 SOUND
 P:	Jaroslav Kysela
 M:	perex@suse.cz
-L:	alsa-devel@alsa-project.org
+L:	alsa-devel@alsa-project.org (subscribers-only)
 S:	Maintained
 
 SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT
 P:	Liam Girdwood
 M:	liam.girdwood@wolfsonmicro.com
-L:	alsa-devel@alsa-project.org
+L:	alsa-devel@alsa-project.org (subscribers-only)
 S:	Supported
 
 SPI SUBSYSTEM
diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h
index 0e8da684ce68..aa83d4163096 100644
--- a/include/linux/i2c-id.h
+++ b/include/linux/i2c-id.h
@@ -117,6 +117,7 @@
 #define I2C_DRIVERID_ISL1208	88	/* Intersil ISL1208 RTC		*/
 #define I2C_DRIVERID_WM8731		89	/* Wolfson WM8731 audio codec */
 #define I2C_DRIVERID_WM8750		90	/* Wolfson WM8750 audio codec */
+#define I2C_DRIVERID_WM8753		91	/* Wolfson WM8753 audio codec */
 
 #define I2C_DRIVERID_I2CDEV	900
 #define I2C_DRIVERID_ARP        902    /* SMBus ARP Client              */
diff --git a/include/sound/ak4114.h b/include/sound/ak4114.h
index c149d3b2558b..d647dae912b9 100644
--- a/include/sound/ak4114.h
+++ b/include/sound/ak4114.h
@@ -73,7 +73,7 @@
 
 /* AK4114_REQ_FORMAT bits */
 #define AK4114_MONO		(1<<7)	/* Double Sampling Frequency Mode: 0 = stereo, 1 = mono */
-#define AK4114_DIF2		(1<<5)	/* Audio Data Control */
+#define AK4114_DIF2		(1<<6)	/* Audio Data Control */
 #define AK4114_DIF1		(1<<5)	/* Audio Data Control */
 #define AK4114_DIF0		(1<<4)	/* Audio Data Control */
 #define AK4114_DIF_16R		(0)				/* STDO: 16-bit, right justified */
@@ -158,7 +158,7 @@
 #define AK4114_CHECK_NO_STAT	(1<<0)	/* no statistics */
 #define AK4114_CHECK_NO_RATE	(1<<1)	/* no rate check */
 
-#define AK4114_CONTROLS		14
+#define AK4114_CONTROLS		15
 
 typedef void (ak4114_write_t)(void *private_data, unsigned char addr, unsigned char data);
 typedef unsigned char (ak4114_read_t)(void *private_data, unsigned char addr);
diff --git a/include/sound/mpu401.h b/include/sound/mpu401.h
index 8c88267e9bea..d5c1396c4c9e 100644
--- a/include/sound/mpu401.h
+++ b/include/sound/mpu401.h
@@ -50,6 +50,7 @@
 #define MPU401_INFO_INTEGRATED	(1 << 2)	/* integrated h/w port */
 #define MPU401_INFO_MMIO	(1 << 3)	/* MMIO access */
 #define MPU401_INFO_TX_IRQ	(1 << 4)	/* independent TX irq */
+#define MPU401_INFO_UART_ONLY	(1 << 5)	/* No ENTER_UART cmd needed */
 
 #define MPU401_MODE_BIT_INPUT		0
 #define MPU401_MODE_BIT_OUTPUT		1
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index deff5a92efa6..73334e0f823f 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -603,11 +603,8 @@ do { \
 	read_unlock_irqrestore(&snd_pcm_link_rwlock, (flags)); \
 } while (0)
 
-#define snd_pcm_group_for_each(pos, substream) \
-	list_for_each(pos, &substream->group->substreams)
-
-#define snd_pcm_group_substream_entry(pos) \
-	list_entry(pos, struct snd_pcm_substream, link_list)
+#define snd_pcm_group_for_each_entry(s, substream) \
+	list_for_each_entry(s, &substream->group->substreams, link_list)
 
 static inline int snd_pcm_running(struct snd_pcm_substream *substream)
 {
diff --git a/include/sound/version.h b/include/sound/version.h
index 42a18cc95f38..e820f0e7bdd3 100644
--- a/include/sound/version.h
+++ b/include/sound/version.h
@@ -1,3 +1,3 @@
 /* include/version.h.  Generated by alsa/ksync script.  */
-#define CONFIG_SND_VERSION "1.0.14rc3"
-#define CONFIG_SND_DATE " (Wed Mar 14 07:25:50 2007 UTC)"
+#define CONFIG_SND_VERSION "1.0.14rc4"
+#define CONFIG_SND_DATE " (Wed May 09 09:51:39 2007 UTC)"
diff --git a/sound/aoa/codecs/snd-aoa-codec-onyx.c b/sound/aoa/codecs/snd-aoa-codec-onyx.c
index e91f9f66f395..ded516717940 100644
--- a/sound/aoa/codecs/snd-aoa-codec-onyx.c
+++ b/sound/aoa/codecs/snd-aoa-codec-onyx.c
@@ -1018,7 +1018,7 @@ static int onyx_create(struct i2c_adapter *adapter,
 	onyx->i2c.driver = &onyx_driver;
 	onyx->i2c.adapter = adapter;
 	onyx->i2c.addr = addr & 0x7f;
-	strlcpy(onyx->i2c.name, "onyx audio codec", I2C_NAME_SIZE-1);
+	strlcpy(onyx->i2c.name, "onyx audio codec", I2C_NAME_SIZE);
 
 	if (i2c_attach_client(&onyx->i2c)) {
 		printk(KERN_ERR PFX "failed to attach to i2c\n");
@@ -1033,7 +1033,7 @@ static int onyx_create(struct i2c_adapter *adapter,
 		goto fail;
 	}
 
-	strlcpy(onyx->codec.name, "onyx", MAX_CODEC_NAME_LEN-1);
+	strlcpy(onyx->codec.name, "onyx", MAX_CODEC_NAME_LEN);
 	onyx->codec.owner = THIS_MODULE;
 	onyx->codec.init = onyx_init_codec;
 	onyx->codec.exit = onyx_exit_codec;
diff --git a/sound/aoa/codecs/snd-aoa-codec-tas.c b/sound/aoa/codecs/snd-aoa-codec-tas.c
index 041fe52cbf29..2f771f57c76f 100644
--- a/sound/aoa/codecs/snd-aoa-codec-tas.c
+++ b/sound/aoa/codecs/snd-aoa-codec-tas.c
@@ -899,14 +899,14 @@ static int tas_create(struct i2c_adapter *adapter,
 	tas->i2c.addr = addr;
 	/* seems that half is a saner default */
 	tas->drc_range = TAS3004_DRC_MAX / 2;
-	strlcpy(tas->i2c.name, "tas audio codec", I2C_NAME_SIZE-1);
+	strlcpy(tas->i2c.name, "tas audio codec", I2C_NAME_SIZE);
 
 	if (i2c_attach_client(&tas->i2c)) {
 		printk(KERN_ERR PFX "failed to attach to i2c\n");
 		goto fail;
 	}
 
-	strlcpy(tas->codec.name, "tas", MAX_CODEC_NAME_LEN-1);
+	strlcpy(tas->codec.name, "tas", MAX_CODEC_NAME_LEN);
 	tas->codec.owner = THIS_MODULE;
 	tas->codec.init = tas_init_codec;
 	tas->codec.exit = tas_exit_codec;
diff --git a/sound/aoa/soundbus/core.c b/sound/aoa/soundbus/core.c
index 8b2e9b905cda..64d163914335 100644
--- a/sound/aoa/soundbus/core.c
+++ b/sound/aoa/soundbus/core.c
@@ -163,8 +163,6 @@ static int soundbus_device_resume(struct device * dev)
 
 #endif /* CONFIG_PM */
 
-extern struct device_attribute soundbus_dev_attrs[];
-
 static struct bus_type soundbus_bus_type = {
 	.name		= "aoa-soundbus",
 	.probe		= soundbus_probe,
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-core.c b/sound/aoa/soundbus/i2sbus/i2sbus-core.c
index 0fccdbf51663..efb9441b3acf 100644
--- a/sound/aoa/soundbus/i2sbus/i2sbus-core.c
+++ b/sound/aoa/soundbus/i2sbus/i2sbus-core.c
@@ -23,9 +23,6 @@
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
 MODULE_DESCRIPTION("Apple Soundbus: I2S support");
-/* for auto-loading, declare that we handle this weird
- * string that macio puts into the relevant device */
-MODULE_ALIAS("of:Ni2sTi2sC");
 
 static int force;
 module_param(force, int, 0444);
@@ -37,6 +34,8 @@ static struct of_device_id i2sbus_match[] = {
 	{ }
 };
 
+MODULE_DEVICE_TABLE(of, i2sbus_match);
+
 static int alloc_dbdma_descriptor_ring(struct i2sbus_dev *i2sdev,
 				       struct dbdma_command_mem *r,
 				       int numcmds)
diff --git a/sound/aoa/soundbus/soundbus.h b/sound/aoa/soundbus/soundbus.h
index 5c27297835d7..622cd37a0118 100644
--- a/sound/aoa/soundbus/soundbus.h
+++ b/sound/aoa/soundbus/soundbus.h
@@ -199,4 +199,6 @@ struct soundbus_driver {
 extern int soundbus_register_driver(struct soundbus_driver *drv);
 extern void soundbus_unregister_driver(struct soundbus_driver *drv);
 
+extern struct device_attribute soundbus_dev_attrs[];
+
 #endif /* __SOUNDBUS_H */
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 905234817c89..a96733a5beb8 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -712,26 +712,23 @@ static int snd_pcm_action_group(struct action_ops *ops,
 				struct snd_pcm_substream *substream,
 				int state, int do_lock)
 {
-	struct list_head *pos;
 	struct snd_pcm_substream *s = NULL;
 	struct snd_pcm_substream *s1;
 	int res = 0;
 
-	snd_pcm_group_for_each(pos, substream) {
-		s = snd_pcm_group_substream_entry(pos);
+	snd_pcm_group_for_each_entry(s, substream) {
 		if (do_lock && s != substream)
-			spin_lock(&s->self_group.lock);
+			spin_lock_nested(&s->self_group.lock,
+					 SINGLE_DEPTH_NESTING);
 		res = ops->pre_action(s, state);
 		if (res < 0)
 			goto _unlock;
 	}
-	snd_pcm_group_for_each(pos, substream) {
-		s = snd_pcm_group_substream_entry(pos);
+	snd_pcm_group_for_each_entry(s, substream) {
 		res = ops->do_action(s, state);
 		if (res < 0) {
 			if (ops->undo_action) {
-				snd_pcm_group_for_each(pos, substream) {
-					s1 = snd_pcm_group_substream_entry(pos);
+				snd_pcm_group_for_each_entry(s1, substream) {
 					if (s1 == s) /* failed stream */
 						break;
 					ops->undo_action(s1, state);
@@ -741,15 +738,13 @@ static int snd_pcm_action_group(struct action_ops *ops,
 			goto _unlock;
 		}
 	}
-	snd_pcm_group_for_each(pos, substream) {
-		s = snd_pcm_group_substream_entry(pos);
+	snd_pcm_group_for_each_entry(s, substream) {
 		ops->post_action(s, state);
 	}
  _unlock:
 	if (do_lock) {
 		/* unlock streams */
-		snd_pcm_group_for_each(pos, substream) {
-			s1 = snd_pcm_group_substream_entry(pos);
+		snd_pcm_group_for_each_entry(s1, substream) {
 			if (s1 != substream)
 				spin_unlock(&s1->self_group.lock);
 			if (s1 == s)	/* end */
@@ -1438,7 +1433,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream)
 {
 	struct snd_card *card;
 	struct snd_pcm_runtime *runtime;
-	struct list_head *pos;
+	struct snd_pcm_substream *s;
 	int result = 0;
 	int i, num_drecs;
 	struct drain_rec *drec, drec_tmp, *d;
@@ -1473,8 +1468,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream)
 
 	/* count only playback streams */
 	num_drecs = 0;
-	snd_pcm_group_for_each(pos, substream) {
-		struct snd_pcm_substream *s = snd_pcm_group_substream_entry(pos);
+	snd_pcm_group_for_each_entry(s, substream) {
 		runtime = s->runtime;
 		if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 			d = &drec[num_drecs++];
@@ -1674,7 +1668,7 @@ static void relink_to_local(struct snd_pcm_substream *substream)
 
 static int snd_pcm_unlink(struct snd_pcm_substream *substream)
 {
-	struct list_head *pos;
+	struct snd_pcm_substream *s;
 	int res = 0;
 
 	down_write(&snd_pcm_link_rwsem);
@@ -1686,8 +1680,8 @@ static int snd_pcm_unlink(struct snd_pcm_substream *substream)
 	list_del(&substream->link_list);
 	substream->group->count--;
 	if (substream->group->count == 1) {	/* detach the last stream, too */
-		snd_pcm_group_for_each(pos, substream) {
-			relink_to_local(snd_pcm_group_substream_entry(pos));
+		snd_pcm_group_for_each_entry(s, substream) {
+			relink_to_local(s);
 			break;
 		}
 		kfree(substream->group);
diff --git a/sound/core/rtctimer.c b/sound/core/rtctimer.c
index 9f7b32e1ccde..7cd5e8f5d4ce 100644
--- a/sound/core/rtctimer.c
+++ b/sound/core/rtctimer.c
@@ -24,6 +24,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/moduleparam.h>
+#include <linux/log2.h>
 #include <sound/core.h>
 #include <sound/timer.h>
 
@@ -129,7 +130,7 @@ static int __init rtctimer_init(void)
 	struct snd_timer *timer;
 
 	if (rtctimer_freq < 2 || rtctimer_freq > 8192 ||
-	    (rtctimer_freq & (rtctimer_freq - 1)) != 0) {
+	    !is_power_of_2(rtctimer_freq)) {
 		snd_printk(KERN_ERR "rtctimer: invalid frequency %d\n",
 			   rtctimer_freq);
 		return -EINVAL;
diff --git a/sound/drivers/mpu401/mpu401.c b/sound/drivers/mpu401/mpu401.c
index 2de181ad0b05..1d563e515c17 100644
--- a/sound/drivers/mpu401/mpu401.c
+++ b/sound/drivers/mpu401/mpu401.c
@@ -42,6 +42,7 @@ static int pnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
 #endif
 static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;	/* MPU-401 port number */
 static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;	/* MPU-401 IRQ */
+static int uart_enter[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
 
 module_param_array(index, int, NULL, 0444);
 MODULE_PARM_DESC(index, "Index value for MPU-401 device.");
@@ -57,6 +58,8 @@ module_param_array(port, long, NULL, 0444);
 MODULE_PARM_DESC(port, "Port # for MPU-401 device.");
 module_param_array(irq, int, NULL, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for MPU-401 device.");
+module_param_array(uart_enter, bool, NULL, 0444);
+MODULE_PARM_DESC(uart_enter, "Issue UART_ENTER command at open.");
 
 static struct platform_device *platform_devices[SNDRV_CARDS];
 static int pnp_registered;
@@ -80,10 +83,11 @@ static int snd_mpu401_create(int dev, struct snd_card **rcard)
 		strcat(card->longname, "polled");
 	}
 
-	if ((err = snd_mpu401_uart_new(card, 0,
-				       MPU401_HW_MPU401,
-				       port[dev], 0,
-				       irq[dev], irq[dev] >= 0 ? IRQF_DISABLED : 0, NULL)) < 0) {
+	err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, port[dev],
+				  uart_enter[dev] ? 0 : MPU401_INFO_UART_ONLY,
+				  irq[dev], irq[dev] >= 0 ? IRQF_DISABLED : 0,
+				  NULL);
+	if (err < 0) {
 		printk(KERN_ERR "MPU401 not detected at 0x%lx\n", port[dev]);
 		goto _err;
 	}
diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c
index 3daa9fa56c0b..85aedc348e2d 100644
--- a/sound/drivers/mpu401/mpu401_uart.c
+++ b/sound/drivers/mpu401/mpu401_uart.c
@@ -266,6 +266,16 @@ static int snd_mpu401_uart_cmd(struct snd_mpu401 * mpu, unsigned char cmd,
 	return 0;
 }
 
+static int snd_mpu401_do_reset(struct snd_mpu401 *mpu)
+{
+	if (snd_mpu401_uart_cmd(mpu, MPU401_RESET, 1))
+		return -EIO;
+	if (!(mpu->info_flags & MPU401_INFO_UART_ONLY) &&
+	    snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1))
+		return -EIO;
+	return 0;
+}
+
 /*
  * input/output open/close - protected by open_mutex in rawmidi.c
  */
@@ -278,9 +288,7 @@ static int snd_mpu401_uart_input_open(struct snd_rawmidi_substream *substream)
 	if (mpu->open_input && (err = mpu->open_input(mpu)) < 0)
 		return err;
 	if (! test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode)) {
-		if (snd_mpu401_uart_cmd(mpu, MPU401_RESET, 1))
-			goto error_out;
-		if (snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1))
+		if (snd_mpu401_do_reset(mpu) < 0)
 			goto error_out;
 	}
 	mpu->substream_input = substream;
@@ -302,9 +310,7 @@ static int snd_mpu401_uart_output_open(struct snd_rawmidi_substream *substream)
 	if (mpu->open_output && (err = mpu->open_output(mpu)) < 0)
 		return err;
 	if (! test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) {
-		if (snd_mpu401_uart_cmd(mpu, MPU401_RESET, 1))
-			goto error_out;
-		if (snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1))
+		if (snd_mpu401_do_reset(mpu) < 0)
 			goto error_out;
 	}
 	mpu->substream_output = substream;
diff --git a/sound/drivers/mts64.c b/sound/drivers/mts64.c
index 6c9f4c9bfeb6..ebb1bdac7237 100644
--- a/sound/drivers/mts64.c
+++ b/sound/drivers/mts64.c
@@ -892,13 +892,13 @@ static void __devinit snd_mts64_attach(struct parport *p)
 	struct platform_device *device;
 
 	device = platform_device_alloc(PLATFORM_DRIVER, device_count);
-	if (!device) 
+	if (!device)
 		return;
 
 	/* Temporary assignment to forward the parport */
 	platform_set_drvdata(device, p);
 
-	if (platform_device_register(device) < 0) {
+	if (platform_device_add(device) < 0) {
 		platform_device_put(device);
 		return;
 	}
diff --git a/sound/drivers/portman2x4.c b/sound/drivers/portman2x4.c
index b2d0ba4bd184..497cafb57d9b 100644
--- a/sound/drivers/portman2x4.c
+++ b/sound/drivers/portman2x4.c
@@ -676,13 +676,13 @@ static void __devinit snd_portman_attach(struct parport *p)
 	struct platform_device *device;
 
 	device = platform_device_alloc(PLATFORM_DRIVER, device_count);
-	if (!device) 
+	if (!device)
 		return;
 
 	/* Temporary assignment to forward the parport */
 	platform_set_drvdata(device, p);
 
-	if (platform_device_register(device) < 0) {
+	if (platform_device_add(device) < 0) {
 		platform_device_put(device);
 		return;
 	}
diff --git a/sound/drivers/vx/vx_hwdep.c b/sound/drivers/vx/vx_hwdep.c
index e1920af4501d..9a8154c9416e 100644
--- a/sound/drivers/vx/vx_hwdep.c
+++ b/sound/drivers/vx/vx_hwdep.c
@@ -30,6 +30,20 @@
 
 #ifdef SND_VX_FW_LOADER
 
+MODULE_FIRMWARE("vx/bx_1_vxp.b56");
+MODULE_FIRMWARE("vx/bx_1_vp4.b56");
+MODULE_FIRMWARE("vx/x1_1_vx2.xlx");
+MODULE_FIRMWARE("vx/x1_2_v22.xlx");
+MODULE_FIRMWARE("vx/x1_1_vxp.xlx");
+MODULE_FIRMWARE("vx/x1_1_vp4.xlx");
+MODULE_FIRMWARE("vx/bd56002.boot");
+MODULE_FIRMWARE("vx/bd563v2.boot");
+MODULE_FIRMWARE("vx/bd563s3.boot");
+MODULE_FIRMWARE("vx/l_1_vx2.d56");
+MODULE_FIRMWARE("vx/l_1_v22.d56");
+MODULE_FIRMWARE("vx/l_1_vxp.d56");
+MODULE_FIRMWARE("vx/l_1_vp4.d56");
+
 int snd_vx_setup_firmware(struct vx_core *chip)
 {
 	static char *fw_files[VX_TYPE_NUMS][4] = {
diff --git a/sound/i2c/other/ak4114.c b/sound/i2c/other/ak4114.c
index adbfd5884d06..1efb973137a6 100644
--- a/sound/i2c/other/ak4114.c
+++ b/sound/i2c/other/ak4114.c
@@ -36,6 +36,7 @@ MODULE_LICENSE("GPL");
 #define AK4114_ADDR			0x00 /* fixed address */
 
 static void ak4114_stats(struct work_struct *work);
+static void ak4114_init_regs(struct ak4114 *chip);
 
 static void reg_write(struct ak4114 *ak4114, unsigned char reg, unsigned char val)
 {
@@ -105,7 +106,7 @@ int snd_ak4114_create(struct snd_card *card,
 	for (reg = 0; reg < 5; reg++)
 		chip->txcsb[reg] = txcsb[reg];
 
-	snd_ak4114_reinit(chip);
+	ak4114_init_regs(chip);
 
 	chip->rcs0 = reg_read(chip, AK4114_REG_RCS0) & ~(AK4114_QINT | AK4114_CINT);
 	chip->rcs1 = reg_read(chip, AK4114_REG_RCS1);
@@ -131,13 +132,10 @@ void snd_ak4114_reg_write(struct ak4114 *chip, unsigned char reg, unsigned char
 			  (chip->txcsb[reg-AK4114_REG_TXCSB0] & ~mask) | val);
 }
 
-void snd_ak4114_reinit(struct ak4114 *chip)
+static void ak4114_init_regs(struct ak4114 *chip)
 {
 	unsigned char old = chip->regmap[AK4114_REG_PWRDN], reg;
 
-	chip->init = 1;
-	mb();
-	flush_scheduled_work();
 	/* bring the chip to reset state and powerdown state */
 	reg_write(chip, AK4114_REG_PWRDN, old & ~(AK4114_RST|AK4114_PWN));
 	udelay(200);
@@ -150,9 +148,18 @@ void snd_ak4114_reinit(struct ak4114 *chip)
 		reg_write(chip, reg + AK4114_REG_TXCSB0, chip->txcsb[reg]);
 	/* release powerdown, everything is initialized now */
 	reg_write(chip, AK4114_REG_PWRDN, old | AK4114_RST | AK4114_PWN);
+}
+
+void snd_ak4114_reinit(struct ak4114 *chip)
+{
+	chip->init = 1;
+	mb();
+	flush_scheduled_work();
+	ak4114_init_regs(chip);
 	/* bring up statistics / event queing */
 	chip->init = 0;
-	schedule_delayed_work(&chip->work, HZ / 10);
+	if (chip->kctls[0])
+		schedule_delayed_work(&chip->work, HZ / 10);
 }
 
 static unsigned int external_rate(unsigned char rcs1)
@@ -428,7 +435,7 @@ static struct snd_kcontrol_new snd_ak4114_iec958_controls[] = {
 	.access =	SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
 	.info =		snd_ak4114_in_bit_info,
 	.get =		snd_ak4114_in_bit_get,
-	.private_value = (6<<8) | AK4114_REG_RCS1,
+	.private_value = (6<<8) | AK4114_REG_RCS0,
 },
 {
 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
@@ -436,7 +443,15 @@ static struct snd_kcontrol_new snd_ak4114_iec958_controls[] = {
 	.access =	SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
 	.info =		snd_ak4114_in_bit_info,
 	.get =		snd_ak4114_in_bit_get,
-	.private_value = (3<<8) | AK4114_REG_RCS1,
+	.private_value = (3<<8) | AK4114_REG_RCS0,
+},
+{
+	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
+	.name =		"IEC958 PPL Lock Status",
+	.access =	SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+	.info =		snd_ak4114_in_bit_info,
+	.get =		snd_ak4114_in_bit_get,
+	.private_value = (1<<31) | (4<<8) | AK4114_REG_RCS0,
 }
 };
 
@@ -455,7 +470,7 @@ int snd_ak4114_build(struct ak4114 *ak4114,
 		kctl = snd_ctl_new1(&snd_ak4114_iec958_controls[idx], ak4114);
 		if (kctl == NULL)
 			return -ENOMEM;
-		if (!strstr(kctl->id.name, "Playback")) {
+		if (strstr(kctl->id.name, "Playback")) {
 			if (ply_substream == NULL) {
 				snd_ctl_free_one(kctl);
 				ak4114->kctls[idx] = NULL;
@@ -472,9 +487,58 @@ int snd_ak4114_build(struct ak4114 *ak4114,
 			return err;
 		ak4114->kctls[idx] = kctl;
 	}
+	/* trigger workq */
+	schedule_delayed_work(&ak4114->work, HZ / 10);
 	return 0;
 }
 
+/* notify kcontrols if any parameters are changed */
+static void ak4114_notify(struct ak4114 *ak4114,
+			  unsigned char rcs0, unsigned char rcs1,
+			  unsigned char c0, unsigned char c1)
+{
+	if (!ak4114->kctls[0])
+		return;
+
+	if (rcs0 & AK4114_PAR)
+		snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE,
+			       &ak4114->kctls[0]->id);
+	if (rcs0 & AK4114_V)
+		snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE,
+			       &ak4114->kctls[1]->id);
+	if (rcs1 & AK4114_CCRC)
+		snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE,
+			       &ak4114->kctls[2]->id);
+	if (rcs1 & AK4114_QCRC)
+		snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE,
+			       &ak4114->kctls[3]->id);
+
+	/* rate change */
+	if (c1 & 0xf0)
+		snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE,
+			       &ak4114->kctls[4]->id);
+
+	if ((c0 & AK4114_PEM) | (c0 & AK4114_CINT))
+		snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE,
+			       &ak4114->kctls[9]->id);
+	if (c0 & AK4114_QINT)
+		snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE,
+			       &ak4114->kctls[10]->id);
+
+	if (c0 & AK4114_AUDION)
+		snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE,
+			       &ak4114->kctls[11]->id);
+	if (c0 & AK4114_AUTO)
+		snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE,
+			       &ak4114->kctls[12]->id);
+	if (c0 & AK4114_DTSCD)
+		snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE,
+			       &ak4114->kctls[13]->id);
+	if (c0 & AK4114_UNLCK)
+		snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE,
+			       &ak4114->kctls[14]->id);
+}
+
 int snd_ak4114_external_rate(struct ak4114 *ak4114)
 {
 	unsigned char rcs1;
@@ -511,31 +575,7 @@ int snd_ak4114_check_rate_and_errors(struct ak4114 *ak4114, unsigned int flags)
 	ak4114->rcs1 = rcs1;
 	spin_unlock_irqrestore(&ak4114->lock, _flags);
 
-	if (rcs0 & AK4114_PAR)
-		snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[0]->id);
-	if (rcs0 & AK4114_V)
-		snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[1]->id);
-	if (rcs1 & AK4114_CCRC)
-		snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[2]->id);
-	if (rcs1 & AK4114_QCRC)
-		snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[3]->id);
-
-	/* rate change */
-	if (c1 & 0xf0)
-		snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[4]->id);
-
-	if ((c0 & AK4114_PEM) | (c0 & AK4114_CINT))
-		snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[9]->id);
-	if (c0 & AK4114_QINT)
-		snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[10]->id);
-
-	if (c0 & AK4114_AUDION)
-		snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[11]->id);
-	if (c0 & AK4114_AUTO)
-		snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[12]->id);
-	if (c0 & AK4114_DTSCD)
-		snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[13]->id);
-
+	ak4114_notify(ak4114, rcs0, rcs1, c0, c1);
 	if (ak4114->change_callback && (c0 | c1) != 0)
 		ak4114->change_callback(ak4114, c0, c1);
 
@@ -558,9 +598,9 @@ static void ak4114_stats(struct work_struct *work)
 {
 	struct ak4114 *chip = container_of(work, struct ak4114, work.work);
 
-	if (chip->init)
-		return;
-	snd_ak4114_check_rate_and_errors(chip, 0);
+	if (!chip->init)
+		snd_ak4114_check_rate_and_errors(chip, 0);
+
 	schedule_delayed_work(&chip->work, HZ / 10);
 }
 
diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig
index 4e3a9729f569..cf3803cd579c 100644
--- a/sound/isa/Kconfig
+++ b/sound/isa/Kconfig
@@ -358,12 +358,21 @@ config SND_SBAWE
 config SND_SB16_CSP
 	bool "Sound Blaster 16/AWE CSP support"
 	depends on (SND_SB16 || SND_SBAWE) && (BROKEN || !PPC)
-	select FW_LOADER
+	select FW_LOADER if !SND_SB16_CSP_FIRMWARE_IN_KERNEL
 	help
 	  Say Y here to include support for the CSP core.  This special
 	  coprocessor can do variable tasks like various compression and
 	  decompression algorithms.
 
+config SND_SB16_CSP_FIRMWARE_IN_KERNEL
+	bool "In-kernel firmware for SB16 CSP"
+	depends on SND_SB16_CSP
+	default y
+	help
+	  Say Y here to include the static firmware built in the kernel
+	  for the SB16 CSP controller.  If you choose N here, you need
+	  to install the firmware files from the alsa-firmware package.
+
 config SND_SGALAXY
 	tristate "Aztech Sound Galaxy"
 	depends on SND
@@ -391,7 +400,7 @@ config SND_SSCAPE
 config SND_WAVEFRONT
 	tristate "Turtle Beach Maui,Tropez,Tropez+ (Wavefront)"
 	depends on SND
-	select FW_LOADER
+	select FW_LOADER if !SND_WAVEFRONT_FIRMWARE_IN_KERNEL
 	select SND_OPL3_LIB
 	select SND_MPU401_UART
 	select SND_CS4231_LIB
@@ -402,4 +411,13 @@ config SND_WAVEFRONT
 	  To compile this driver as a module, choose M here: the module
 	  will be called snd-wavefront.
 
+config SND_WAVEFRONT_FIRMWARE_IN_KERNEL
+	bool "In-kernel firmware for Wavefront"
+	depends on SND_WAVEFRONT
+	default y
+	help
+	  Say Y here to include the static firmware built in the kernel
+	  for the Wavefront driver.  If you choose N here, you need to
+	  install the firmware files from the alsa-firmware package.
+
 endmenu
diff --git a/sound/isa/ad1816a/ad1816a.c b/sound/isa/ad1816a/ad1816a.c
index 59034507175b..fc88a31da6f5 100644
--- a/sound/isa/ad1816a/ad1816a.c
+++ b/sound/isa/ad1816a/ad1816a.c
@@ -129,8 +129,8 @@ static int __devinit snd_card_ad1816a_pnp(int dev, struct snd_card_ad1816a *acar
 	}
 	acard->devmpu = pnp_request_card_device(card, id->devs[1].id, NULL);
 	if (acard->devmpu == NULL) {
-		kfree(cfg);
-		return -EBUSY;
+		mpu_port[dev] = -1;
+		snd_printk(KERN_WARNING PFX "MPU401 device busy, skipping.\n");
 	}
 
 	pdev = acard->dev;
@@ -162,6 +162,10 @@ static int __devinit snd_card_ad1816a_pnp(int dev, struct snd_card_ad1816a *acar
 	dma2[dev] = pnp_dma(pdev, 1);
 	irq[dev] = pnp_irq(pdev, 0);
 
+	if (acard->devmpu == NULL) {
+		kfree(cfg);
+		return 0;
+	}
 	pdev = acard->devmpu;
 	pnp_init_resource_table(cfg);
 
diff --git a/sound/isa/ad1848/ad1848.c b/sound/isa/ad1848/ad1848.c
index 74e501dea8b1..d09a7fa86545 100644
--- a/sound/isa/ad1848/ad1848.c
+++ b/sound/isa/ad1848/ad1848.c
@@ -24,7 +24,7 @@
 #include <sound/driver.h>
 #include <linux/init.h>
 #include <linux/err.h>
-#include <linux/platform_device.h>
+#include <linux/isa.h>
 #include <linux/time.h>
 #include <linux/wait.h>
 #include <linux/moduleparam.h>
@@ -32,8 +32,11 @@
 #include <sound/ad1848.h>
 #include <sound/initval.h>
 
+#define CRD_NAME "Generic AD1848/AD1847/CS4248"
+#define DEV_NAME "ad1848"
+
+MODULE_DESCRIPTION(CRD_NAME);
 MODULE_AUTHOR("Tugrul Galatali <galatalt@stuy.edu>, Jaroslav Kysela <perex@suse.cz>");
-MODULE_DESCRIPTION("AD1848/AD1847/CS4248");
 MODULE_LICENSE("GPL");
 MODULE_SUPPORTED_DEVICE("{{Analog Devices,AD1848},"
 	        "{Analog Devices,AD1847},"
@@ -48,95 +51,98 @@ static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;	/* 0,1,3,5,6,7 */
 static int thinkpad[SNDRV_CARDS];			/* Thinkpad special case */
 
 module_param_array(index, int, NULL, 0444);
-MODULE_PARM_DESC(index, "Index value for AD1848 soundcard.");
+MODULE_PARM_DESC(index, "Index value for " CRD_NAME " soundcard.");
 module_param_array(id, charp, NULL, 0444);
-MODULE_PARM_DESC(id, "ID string for AD1848 soundcard.");
+MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard.");
 module_param_array(enable, bool, NULL, 0444);
-MODULE_PARM_DESC(enable, "Enable AD1848 soundcard.");
+MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard.");
 module_param_array(port, long, NULL, 0444);
-MODULE_PARM_DESC(port, "Port # for AD1848 driver.");
+MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver.");
 module_param_array(irq, int, NULL, 0444);
-MODULE_PARM_DESC(irq, "IRQ # for AD1848 driver.");
+MODULE_PARM_DESC(irq, "IRQ # for " CRD_NAME " driver.");
 module_param_array(dma1, int, NULL, 0444);
-MODULE_PARM_DESC(dma1, "DMA1 # for AD1848 driver.");
+MODULE_PARM_DESC(dma1, "DMA1 # for " CRD_NAME " driver.");
 module_param_array(thinkpad, bool, NULL, 0444);
 MODULE_PARM_DESC(thinkpad, "Enable only for the onboard CS4248 of IBM Thinkpad 360/750/755 series.");
 
-static struct platform_device *devices[SNDRV_CARDS];
+static int __devinit snd_ad1848_match(struct device *dev, unsigned int n)
+{
+	if (!enable[n])
+		return 0;
 
+	if (port[n] == SNDRV_AUTO_PORT) {
+		snd_printk(KERN_ERR "%s: please specify port\n", dev->bus_id);
+		return 0;
+	}
+	if (irq[n] == SNDRV_AUTO_IRQ) {
+		snd_printk(KERN_ERR "%s: please specify irq\n", dev->bus_id);
+		return 0;	
+	}
+	if (dma1[n] == SNDRV_AUTO_DMA) {
+		snd_printk(KERN_ERR "%s: please specify dma1\n", dev->bus_id);
+		return 0;
+	}
+	return 1;
+}
 
-static int __devinit snd_ad1848_probe(struct platform_device *pdev)
+static int __devinit snd_ad1848_probe(struct device *dev, unsigned int n)
 {
-	int dev = pdev->id;
 	struct snd_card *card;
 	struct snd_ad1848 *chip;
 	struct snd_pcm *pcm;
-	int err;
+	int error;
 
-	if (port[dev] == SNDRV_AUTO_PORT) {
-		snd_printk(KERN_ERR "ad1848: specify port\n");
+	card = snd_card_new(index[n], id[n], THIS_MODULE, 0);
+	if (!card)
 		return -EINVAL;
-	}
-	if (irq[dev] == SNDRV_AUTO_IRQ) {
-		snd_printk(KERN_ERR "ad1848: specify irq\n");
-		return -EINVAL;
-	}
-	if (dma1[dev] == SNDRV_AUTO_DMA) {
-		snd_printk(KERN_ERR "ad1848: specify dma1\n");
-		return -EINVAL;
-	}
 
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-	if (card == NULL)
-		return -ENOMEM;
+	error = snd_ad1848_create(card, port[n], irq[n], dma1[n],
+			thinkpad[n] ? AD1848_HW_THINKPAD : AD1848_HW_DETECT, &chip);
+	if (error < 0)
+		goto out;
 
-	if ((err = snd_ad1848_create(card, port[dev],
-				     irq[dev],
-				     dma1[dev],
-				     thinkpad[dev] ? AD1848_HW_THINKPAD : AD1848_HW_DETECT,
-				     &chip)) < 0)
-		goto _err;
 	card->private_data = chip;
 
-	if ((err = snd_ad1848_pcm(chip, 0, &pcm)) < 0)
-		goto _err;
+	error = snd_ad1848_pcm(chip, 0, &pcm);
+	if (error < 0)
+		goto out;
 
-	if ((err = snd_ad1848_mixer(chip)) < 0)
-		goto _err;
+	error = snd_ad1848_mixer(chip);
+	if (error < 0)
+		goto out;
 
 	strcpy(card->driver, "AD1848");
 	strcpy(card->shortname, pcm->name);
 
 	sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d",
-		pcm->name, chip->port, irq[dev], dma1[dev]);
-
-	if (thinkpad[dev])
+		pcm->name, chip->port, irq[n], dma1[n]);
+	if (thinkpad[n])
 		strcat(card->longname, " [Thinkpad]");
 
-	snd_card_set_dev(card, &pdev->dev);
+	snd_card_set_dev(card, dev);
 
-	if ((err = snd_card_register(card)) < 0)
-		goto _err;
+	error = snd_card_register(card);
+	if (error < 0)
+		goto out;
 
-	platform_set_drvdata(pdev, card);
+	dev_set_drvdata(dev, card);
 	return 0;
 
- _err:
-	snd_card_free(card);
-	return err;
+out:	snd_card_free(card);
+	return error;
 }
 
-static int __devexit snd_ad1848_remove(struct platform_device *devptr)
+static int __devexit snd_ad1848_remove(struct device *dev, unsigned int n)
 {
-	snd_card_free(platform_get_drvdata(devptr));
-	platform_set_drvdata(devptr, NULL);
+	snd_card_free(dev_get_drvdata(dev));
+	dev_set_drvdata(dev, NULL);
 	return 0;
 }
 
 #ifdef CONFIG_PM
-static int snd_ad1848_suspend(struct platform_device *pdev, pm_message_t state)
+static int snd_ad1848_suspend(struct device *dev, unsigned int n, pm_message_t state)
 {
-	struct snd_card *card = platform_get_drvdata(pdev);
+	struct snd_card *card = dev_get_drvdata(dev);
 	struct snd_ad1848 *chip = card->private_data;
 
 	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
@@ -144,9 +150,9 @@ static int snd_ad1848_suspend(struct platform_device *pdev, pm_message_t state)
 	return 0;
 }
 
-static int snd_ad1848_resume(struct platform_device *pdev)
+static int snd_ad1848_resume(struct device *dev, unsigned int n)
 {
-	struct snd_card *card = platform_get_drvdata(pdev);
+	struct snd_card *card = dev_get_drvdata(dev);
 	struct snd_ad1848 *chip = card->private_data;
 
 	chip->resume(chip);
@@ -155,9 +161,8 @@ static int snd_ad1848_resume(struct platform_device *pdev)
 }
 #endif
 
-#define SND_AD1848_DRIVER	"snd_ad1848"
-
-static struct platform_driver snd_ad1848_driver = {
+static struct isa_driver snd_ad1848_driver = {
+	.match		= snd_ad1848_match,
 	.probe		= snd_ad1848_probe,
 	.remove		= __devexit_p(snd_ad1848_remove),
 #ifdef CONFIG_PM
@@ -165,57 +170,19 @@ static struct platform_driver snd_ad1848_driver = {
 	.resume		= snd_ad1848_resume,
 #endif
 	.driver		= {
-		.name	= SND_AD1848_DRIVER
-	},
+		.name	= DEV_NAME
+	}
 };
 
-static void __init_or_module snd_ad1848_unregister_all(void)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(devices); ++i)
-		platform_device_unregister(devices[i]);
-	platform_driver_unregister(&snd_ad1848_driver);
-}
-
 static int __init alsa_card_ad1848_init(void)
 {
-	int i, cards, err;
-
-	err = platform_driver_register(&snd_ad1848_driver);
-	if (err < 0)
-		return err;
-
-	cards = 0;
-	for (i = 0; i < SNDRV_CARDS; i++) {
-		struct platform_device *device;
-		if (! enable[i])
-			continue;
-		device = platform_device_register_simple(SND_AD1848_DRIVER,
-							 i, NULL, 0);
-		if (IS_ERR(device))
-			continue;
-		if (!platform_get_drvdata(device)) {
-			platform_device_unregister(device);
-			continue;
-		}
-		devices[i] = device;
-		cards++;
-	}
-	if (!cards) {
-#ifdef MODULE
-		printk(KERN_ERR "AD1848 soundcard not found or device busy\n");
-#endif
-		snd_ad1848_unregister_all();
-		return -ENODEV;
-	}
-	return 0;
+	return isa_register_driver(&snd_ad1848_driver, SNDRV_CARDS);
 }
 
 static void __exit alsa_card_ad1848_exit(void)
 {
-	snd_ad1848_unregister_all();
+	isa_unregister_driver(&snd_ad1848_driver);
 }
 
-module_init(alsa_card_ad1848_init)
-module_exit(alsa_card_ad1848_exit)
+module_init(alsa_card_ad1848_init);
+module_exit(alsa_card_ad1848_exit);
diff --git a/sound/isa/adlib.c b/sound/isa/adlib.c
index 1124344ed948..d68720724c91 100644
--- a/sound/isa/adlib.c
+++ b/sound/isa/adlib.c
@@ -5,13 +5,13 @@
 #include <sound/driver.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/platform_device.h>
+#include <linux/isa.h>
 #include <sound/core.h>
 #include <sound/initval.h>
 #include <sound/opl3.h>
 
 #define CRD_NAME "AdLib FM"
-#define DRV_NAME "snd_adlib"
+#define DEV_NAME "adlib"
 
 MODULE_DESCRIPTION(CRD_NAME);
 MODULE_AUTHOR("Rene Herman");
@@ -31,133 +31,99 @@ MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard.");
 module_param_array(port, long, NULL, 0444);
 MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver.");
 
-static struct platform_device *devices[SNDRV_CARDS];
+static int __devinit snd_adlib_match(struct device *dev, unsigned int n)
+{
+	if (!enable[n])
+		return 0;
+
+	if (port[n] == SNDRV_AUTO_PORT) {
+		snd_printk(KERN_ERR "%s: please specify port\n", dev->bus_id);
+		return 0;
+	}
+	return 1;
+}
 
 static void snd_adlib_free(struct snd_card *card)
 {
 	release_and_free_resource(card->private_data);
 }
 
-static int __devinit snd_adlib_probe(struct platform_device *device)
+static int __devinit snd_adlib_probe(struct device *dev, unsigned int n)
 {
 	struct snd_card *card;
 	struct snd_opl3 *opl3;
+	int error;
 
-	int error, i = device->id;
-
-	if (port[i] == SNDRV_AUTO_PORT) {
-		snd_printk(KERN_ERR DRV_NAME ": please specify port\n");
-		error = -EINVAL;
-		goto out0;
-	}
-
-	card = snd_card_new(index[i], id[i], THIS_MODULE, 0);
+	card = snd_card_new(index[n], id[n], THIS_MODULE, 0);
 	if (!card) {
-		snd_printk(KERN_ERR DRV_NAME ": could not create card\n");
-		error = -EINVAL;
-		goto out0;
+		snd_printk(KERN_ERR "%s: could not create card\n", dev->bus_id);
+		return -EINVAL;
 	}
 
-	card->private_data = request_region(port[i], 4, CRD_NAME);
+	card->private_data = request_region(port[n], 4, CRD_NAME);
 	if (!card->private_data) {
-		snd_printk(KERN_ERR DRV_NAME ": could not grab ports\n");
+		snd_printk(KERN_ERR "%s: could not grab ports\n", dev->bus_id);
 		error = -EBUSY;
-		goto out1;
+		goto out;
 	}
 	card->private_free = snd_adlib_free;
 
-	error = snd_opl3_create(card, port[i], port[i] + 2, OPL3_HW_AUTO, 1, &opl3);
+	strcpy(card->driver, DEV_NAME);
+	strcpy(card->shortname, CRD_NAME);
+	sprintf(card->longname, CRD_NAME " at %#lx", port[n]);
+
+	error = snd_opl3_create(card, port[n], port[n] + 2, OPL3_HW_AUTO, 1, &opl3);
 	if (error < 0) {
-		snd_printk(KERN_ERR DRV_NAME ": could not create OPL\n");
-		goto out1;
+		snd_printk(KERN_ERR "%s: could not create OPL\n", dev->bus_id);
+		goto out;
 	}
 
 	error = snd_opl3_hwdep_new(opl3, 0, 0, NULL);
 	if (error < 0) {
-		snd_printk(KERN_ERR DRV_NAME ": could not create FM\n");
-		goto out1;
+		snd_printk(KERN_ERR "%s: could not create FM\n", dev->bus_id);
+		goto out;
 	}
 
-	strcpy(card->driver, DRV_NAME);
-	strcpy(card->shortname, CRD_NAME);
-	sprintf(card->longname, CRD_NAME " at %#lx", port[i]);
-
-	snd_card_set_dev(card, &device->dev);
+	snd_card_set_dev(card, dev);
 
 	error = snd_card_register(card);
 	if (error < 0) {
-		snd_printk(KERN_ERR DRV_NAME ": could not register card\n");
-		goto out1;
+		snd_printk(KERN_ERR "%s: could not register card\n", dev->bus_id);
+		goto out;
 	}
 
-	platform_set_drvdata(device, card);
+	dev_set_drvdata(dev, card);
 	return 0;
 
-out1:	snd_card_free(card);
-out0:	return error;
+out:	snd_card_free(card);
+	return error;
 }
 
-static int __devexit snd_adlib_remove(struct platform_device *device)
+static int __devexit snd_adlib_remove(struct device *dev, unsigned int n)
 {
-	snd_card_free(platform_get_drvdata(device));
-	platform_set_drvdata(device, NULL);
+	snd_card_free(dev_get_drvdata(dev));
+	dev_set_drvdata(dev, NULL);
 	return 0;
 }
 
-static struct platform_driver snd_adlib_driver = {
+static struct isa_driver snd_adlib_driver = {
+	.match		= snd_adlib_match,
 	.probe		= snd_adlib_probe,
 	.remove		= __devexit_p(snd_adlib_remove),
 
 	.driver		= {
-		.name	= DRV_NAME
+		.name	= DEV_NAME
 	}
 };
 
 static int __init alsa_card_adlib_init(void)
 {
-	int i, cards;
-
-	if (platform_driver_register(&snd_adlib_driver) < 0) {
-		snd_printk(KERN_ERR DRV_NAME ": could not register driver\n");
-		return -ENODEV;
-	}
-
-	for (cards = 0, i = 0; i < SNDRV_CARDS; i++) {
-		struct platform_device *device;
-
-		if (!enable[i])
-			continue;
-
-		device = platform_device_register_simple(DRV_NAME, i, NULL, 0);
-		if (IS_ERR(device))
-			continue;
-
-		if (!platform_get_drvdata(device)) {
-			platform_device_unregister(device);
-			continue;
-		}
-
-		devices[i] = device;
-		cards++;
-	}
-
-	if (!cards) {
-#ifdef MODULE
-		printk(KERN_ERR CRD_NAME " soundcard not found or device busy\n");
-#endif
-		platform_driver_unregister(&snd_adlib_driver);
-		return -ENODEV;
-	}
-	return 0;
+	return isa_register_driver(&snd_adlib_driver, SNDRV_CARDS);
 }
 
 static void __exit alsa_card_adlib_exit(void)
 {
-	int i;
-
-	for (i = 0; i < SNDRV_CARDS; i++)
-		platform_device_unregister(devices[i]);
-	platform_driver_unregister(&snd_adlib_driver);
+	isa_unregister_driver(&snd_adlib_driver);
 }
 
 module_init(alsa_card_adlib_init);
diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c
index c09a8009d2fa..214d65d94c45 100644
--- a/sound/isa/cmi8330.c
+++ b/sound/isa/cmi8330.c
@@ -46,7 +46,7 @@
 #include <sound/driver.h>
 #include <linux/init.h>
 #include <linux/err.h>
-#include <linux/platform_device.h>
+#include <linux/isa.h>
 #include <linux/slab.h>
 #include <linux/pnp.h>
 #include <linux/moduleparam.h>
@@ -108,7 +108,6 @@ MODULE_PARM_DESC(wssirq, "IRQ # for CMI8330 WSS driver.");
 module_param_array(wssdma, int, NULL, 0444);
 MODULE_PARM_DESC(wssdma, "DMA for CMI8330 WSS driver.");
 
-static struct platform_device *platform_devices[SNDRV_CARDS];
 #ifdef CONFIG_PNP
 static int pnp_registered;
 #endif
@@ -547,70 +546,78 @@ static int __devinit snd_cmi8330_probe(struct snd_card *card, int dev)
 	return snd_card_register(card);
 }
 
-static int __devinit snd_cmi8330_nonpnp_probe(struct platform_device *pdev)
+static int __devinit snd_cmi8330_isa_match(struct device *pdev,
+					   unsigned int dev)
 {
-	struct snd_card *card;
-	int err;
-	int dev = pdev->id;
-
+	if (!enable[dev] || is_isapnp_selected(dev))
+		return 0;
 	if (wssport[dev] == SNDRV_AUTO_PORT) {
 		snd_printk(KERN_ERR PFX "specify wssport\n");
-		return -EINVAL;
+		return 0;
 	}
 	if (sbport[dev] == SNDRV_AUTO_PORT) {
 		snd_printk(KERN_ERR PFX "specify sbport\n");
-		return -EINVAL;
+		return 0;
 	}
+	return 1;
+}
+
+static int __devinit snd_cmi8330_isa_probe(struct device *pdev,
+					   unsigned int dev)
+{
+	struct snd_card *card;
+	int err;
 
 	card = snd_cmi8330_card_new(dev);
 	if (! card)
 		return -ENOMEM;
-	snd_card_set_dev(card, &pdev->dev);
+	snd_card_set_dev(card, pdev);
 	if ((err = snd_cmi8330_probe(card, dev)) < 0) {
 		snd_card_free(card);
 		return err;
 	}
-	platform_set_drvdata(pdev, card);
+	dev_set_drvdata(pdev, card);
 	return 0;
 }
 
-static int __devexit snd_cmi8330_nonpnp_remove(struct platform_device *devptr)
+static int __devexit snd_cmi8330_isa_remove(struct device *devptr,
+					    unsigned int dev)
 {
-	snd_card_free(platform_get_drvdata(devptr));
-	platform_set_drvdata(devptr, NULL);
+	snd_card_free(dev_get_drvdata(devptr));
+	dev_set_drvdata(devptr, NULL);
 	return 0;
 }
 
 #ifdef CONFIG_PM
-static int snd_cmi8330_nonpnp_suspend(struct platform_device *dev, pm_message_t state)
+static int snd_cmi8330_isa_suspend(struct device *dev, unsigned int n,
+				   pm_message_t state)
 {
-	return snd_cmi8330_suspend(platform_get_drvdata(dev));
+	return snd_cmi8330_suspend(dev_get_drvdata(dev));
 }
 
-static int snd_cmi8330_nonpnp_resume(struct platform_device *dev)
+static int snd_cmi8330_isa_resume(struct device *dev, unsigned int n)
 {
-	return snd_cmi8330_resume(platform_get_drvdata(dev));
+	return snd_cmi8330_resume(dev_get_drvdata(dev));
 }
 #endif
 
-#define CMI8330_DRIVER	"snd_cmi8330"
+#define DEV_NAME	"cmi8330"
 
-static struct platform_driver snd_cmi8330_driver = {
-	.probe		= snd_cmi8330_nonpnp_probe,
-	.remove		= __devexit_p(snd_cmi8330_nonpnp_remove),
+static struct isa_driver snd_cmi8330_driver = {
+	.match		= snd_cmi8330_isa_match,
+	.probe		= snd_cmi8330_isa_probe,
+	.remove		= __devexit_p(snd_cmi8330_isa_remove),
 #ifdef CONFIG_PM
-	.suspend	= snd_cmi8330_nonpnp_suspend,
-	.resume		= snd_cmi8330_nonpnp_resume,
+	.suspend	= snd_cmi8330_isa_suspend,
+	.resume		= snd_cmi8330_isa_resume,
 #endif
 	.driver		= {
-		.name	= CMI8330_DRIVER
+		.name	= DEV_NAME
 	},
 };
 
 
 #ifdef CONFIG_PNP
-static unsigned int __devinitdata cmi8330_pnp_devices;
-
 static int __devinit snd_cmi8330_pnp_detect(struct pnp_card_link *pcard,
 					    const struct pnp_card_device_id *pid)
 {
@@ -640,7 +647,6 @@ static int __devinit snd_cmi8330_pnp_detect(struct pnp_card_link *pcard,
 	}
 	pnp_set_card_drvdata(pcard, card);
 	dev++;
-	cmi8330_pnp_devices++;
 	return 0;
 }
 
@@ -675,63 +681,28 @@ static struct pnp_card_driver cmi8330_pnpc_driver = {
 };
 #endif /* CONFIG_PNP */
 
-static void __init_or_module snd_cmi8330_unregister_all(void)
-{
-	int i;
-
-#ifdef CONFIG_PNP
-	if (pnp_registered)
-		pnp_unregister_card_driver(&cmi8330_pnpc_driver);
-#endif
-	for (i = 0; i < ARRAY_SIZE(platform_devices); ++i)
-		platform_device_unregister(platform_devices[i]);
-	platform_driver_unregister(&snd_cmi8330_driver);
-}
-
 static int __init alsa_card_cmi8330_init(void)
 {
-	int i, err, cards = 0;
+	int err;
 
-	if ((err = platform_driver_register(&snd_cmi8330_driver)) < 0)
+	err = isa_register_driver(&snd_cmi8330_driver, SNDRV_CARDS);
+	if (err < 0)
 		return err;
-
-	for (i = 0; i < SNDRV_CARDS; i++) {
-		struct platform_device *device;
-		if (! enable[i] || is_isapnp_selected(i))
-			continue;
-		device = platform_device_register_simple(CMI8330_DRIVER,
-							 i, NULL, 0);
-		if (IS_ERR(device))
-			continue;
-		if (!platform_get_drvdata(device)) {
-			platform_device_unregister(device);
-			continue;
-		}
-		platform_devices[i] = device;
-		cards++;
-	}
-
 #ifdef CONFIG_PNP
 	err = pnp_register_card_driver(&cmi8330_pnpc_driver);
-	if (!err) {
+	if (!err)
 		pnp_registered = 1;
-		cards += cmi8330_pnp_devices;
-	}
 #endif
-
-	if (!cards) {
-#ifdef MODULE
-		snd_printk(KERN_ERR "CMI8330 not found or device busy\n");
-#endif
-		snd_cmi8330_unregister_all();
-		return -ENODEV;
-	}
 	return 0;
 }
 
 static void __exit alsa_card_cmi8330_exit(void)
 {
-	snd_cmi8330_unregister_all();
+#ifdef CONFIG_PNP
+	if (pnp_registered)
+		pnp_unregister_card_driver(&cmi8330_pnpc_driver);
+#endif
+	isa_unregister_driver(&snd_cmi8330_driver);
 }
 
 module_init(alsa_card_cmi8330_init)
diff --git a/sound/isa/cs423x/cs4231.c b/sound/isa/cs423x/cs4231.c
index 696a5c86bcfa..ac4041134150 100644
--- a/sound/isa/cs423x/cs4231.c
+++ b/sound/isa/cs423x/cs4231.c
@@ -23,7 +23,7 @@
 #include <sound/driver.h>
 #include <linux/init.h>
 #include <linux/err.h>
-#include <linux/platform_device.h>
+#include <linux/isa.h>
 #include <linux/time.h>
 #include <linux/wait.h>
 #include <linux/moduleparam.h>
@@ -32,8 +32,11 @@
 #include <sound/mpu401.h>
 #include <sound/initval.h>
 
+#define CRD_NAME "Generic CS4231"
+#define DEV_NAME "cs4231"
+
+MODULE_DESCRIPTION(CRD_NAME);
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
-MODULE_DESCRIPTION("Generic CS4231");
 MODULE_LICENSE("GPL");
 MODULE_SUPPORTED_DEVICE("{{Crystal Semiconductors,CS4231}}");
 
@@ -48,132 +51,136 @@ static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;	/* 0,1,3,5,6,7 */
 static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;	/* 0,1,3,5,6,7 */
 
 module_param_array(index, int, NULL, 0444);
-MODULE_PARM_DESC(index, "Index value for CS4231 soundcard.");
+MODULE_PARM_DESC(index, "Index value for " CRD_NAME " soundcard.");
 module_param_array(id, charp, NULL, 0444);
-MODULE_PARM_DESC(id, "ID string for CS4231 soundcard.");
+MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard.");
 module_param_array(enable, bool, NULL, 0444);
-MODULE_PARM_DESC(enable, "Enable CS4231 soundcard.");
+MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard.");
 module_param_array(port, long, NULL, 0444);
-MODULE_PARM_DESC(port, "Port # for CS4231 driver.");
+MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver.");
 module_param_array(mpu_port, long, NULL, 0444);
-MODULE_PARM_DESC(mpu_port, "MPU-401 port # for CS4231 driver.");
+MODULE_PARM_DESC(mpu_port, "MPU-401 port # for " CRD_NAME " driver.");
 module_param_array(irq, int, NULL, 0444);
-MODULE_PARM_DESC(irq, "IRQ # for CS4231 driver.");
+MODULE_PARM_DESC(irq, "IRQ # for " CRD_NAME " driver.");
 module_param_array(mpu_irq, int, NULL, 0444);
-MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for CS4231 driver.");
+MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for " CRD_NAME " driver.");
 module_param_array(dma1, int, NULL, 0444);
-MODULE_PARM_DESC(dma1, "DMA1 # for CS4231 driver.");
+MODULE_PARM_DESC(dma1, "DMA1 # for " CRD_NAME " driver.");
 module_param_array(dma2, int, NULL, 0444);
-MODULE_PARM_DESC(dma2, "DMA2 # for CS4231 driver.");
+MODULE_PARM_DESC(dma2, "DMA2 # for " CRD_NAME " driver.");
 
-static struct platform_device *devices[SNDRV_CARDS];
+static int __devinit snd_cs4231_match(struct device *dev, unsigned int n)
+{
+	if (!enable[n])
+		return 0;
 
+	if (port[n] == SNDRV_AUTO_PORT) {
+		snd_printk(KERN_ERR "%s: please specify port\n", dev->bus_id);
+		return 0;
+	}
+	if (irq[n] == SNDRV_AUTO_IRQ) {
+		snd_printk(KERN_ERR "%s: please specify irq\n", dev->bus_id);
+		return 0;
+	}
+	if (dma1[n] == SNDRV_AUTO_DMA) {
+		snd_printk(KERN_ERR "%s: please specify dma1\n", dev->bus_id);
+		return 0;
+	}
+	return 1;
+}
 
-static int __init snd_cs4231_probe(struct platform_device *pdev)
+static int __devinit snd_cs4231_probe(struct device *dev, unsigned int n)
 {
-	int dev = pdev->id;
 	struct snd_card *card;
-	struct snd_pcm *pcm;
 	struct snd_cs4231 *chip;
-	int err;
+	struct snd_pcm *pcm;
+	int error;
 
-	if (port[dev] == SNDRV_AUTO_PORT) {
-		snd_printk(KERN_ERR "specify port\n");
-		return -EINVAL;
-	}
-	if (irq[dev] == SNDRV_AUTO_IRQ) {
-		snd_printk(KERN_ERR "specify irq\n");
-		return -EINVAL;
-	}
-	if (dma1[dev] == SNDRV_AUTO_DMA) {
-		snd_printk(KERN_ERR "specify dma1\n");
+	card = snd_card_new(index[n], id[n], THIS_MODULE, 0);
+	if (!card)
 		return -EINVAL;
-	}
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-	if (card == NULL)
-		return -ENOMEM;
-	if ((err = snd_cs4231_create(card, port[dev], -1,
-				     irq[dev],
-				     dma1[dev],
-				     dma2[dev],
-				     CS4231_HW_DETECT,
-				     0, &chip)) < 0)
-		goto _err;
+
+	error = snd_cs4231_create(card, port[n], -1, irq[n], dma1[n], dma2[n],
+			CS4231_HW_DETECT, 0, &chip);
+	if (error < 0)
+		goto out;
+
 	card->private_data = chip;
 
-	if ((err = snd_cs4231_pcm(chip, 0, &pcm)) < 0)
-		goto _err;
+	error = snd_cs4231_pcm(chip, 0, &pcm);
+	if (error < 0)
+		goto out;
 
 	strcpy(card->driver, "CS4231");
 	strcpy(card->shortname, pcm->name);
+
 	sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d",
-		pcm->name, chip->port, irq[dev], dma1[dev]);
-	if (dma2[dev] >= 0)
-		sprintf(card->longname + strlen(card->longname), "&%d", dma2[dev]);
-
-	if ((err = snd_cs4231_mixer(chip)) < 0)
-		goto _err;
-	if ((err = snd_cs4231_timer(chip, 0, NULL)) < 0)
-		goto _err;
-
-	if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) {
-		if (mpu_irq[dev] == SNDRV_AUTO_IRQ)
-			mpu_irq[dev] = -1;
+		pcm->name, chip->port, irq[n], dma1[n]);
+	if (dma2[n] >= 0)
+		sprintf(card->longname + strlen(card->longname), "&%d", dma2[n]);
+
+	error = snd_cs4231_mixer(chip);
+	if (error < 0)
+		goto out;
+
+	error = snd_cs4231_timer(chip, 0, NULL);
+	if (error < 0)
+		goto out;
+
+	if (mpu_port[n] > 0 && mpu_port[n] != SNDRV_AUTO_PORT) {
+		if (mpu_irq[n] == SNDRV_AUTO_IRQ)
+			mpu_irq[n] = -1;
 		if (snd_mpu401_uart_new(card, 0, MPU401_HW_CS4232,
-					mpu_port[dev], 0,
-					mpu_irq[dev],
-					mpu_irq[dev] >= 0 ? IRQF_DISABLED : 0,
+					mpu_port[n], 0, mpu_irq[n],
+					mpu_irq[n] >= 0 ? IRQF_DISABLED : 0,
 					NULL) < 0)
-			printk(KERN_WARNING "cs4231: MPU401 not detected\n");
+			printk(KERN_WARNING "%s: MPU401 not detected\n", dev->bus_id);
 	}
 
-	snd_card_set_dev(card, &pdev->dev);
+	snd_card_set_dev(card, dev);
 
-	if ((err = snd_card_register(card)) < 0)
-		goto _err;
+	error = snd_card_register(card);
+	if (error < 0)
+		goto out;
 
-	platform_set_drvdata(pdev, card);
+	dev_set_drvdata(dev, card);
 	return 0;
 
- _err:
-	snd_card_free(card);
-	return err;
+out:	snd_card_free(card);
+	return error;
 }
 
-static int __devexit snd_cs4231_remove(struct platform_device *devptr)
+static int __devexit snd_cs4231_remove(struct device *dev, unsigned int n)
 {
-	snd_card_free(platform_get_drvdata(devptr));
-	platform_set_drvdata(devptr, NULL);
+	snd_card_free(dev_get_drvdata(dev));
+	dev_set_drvdata(dev, NULL);
 	return 0;
 }
 
 #ifdef CONFIG_PM
-static int snd_cs4231_suspend(struct platform_device *dev, pm_message_t state)
+static int snd_cs4231_suspend(struct device *dev, unsigned int n, pm_message_t state)
 {
-	struct snd_card *card;
-	struct snd_cs4231 *chip;
-	card = platform_get_drvdata(dev);
+	struct snd_card *card = dev_get_drvdata(dev);
+	struct snd_cs4231 *chip = card->private_data;
+
 	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
-	chip = card->private_data;
 	chip->suspend(chip);
 	return 0;
 }
 
-static int snd_cs4231_resume(struct platform_device *dev)
+static int snd_cs4231_resume(struct device *dev, unsigned int n)
 {
-	struct snd_card *card;
-	struct snd_cs4231 *chip;
-	card = platform_get_drvdata(dev);
-	chip = card->private_data;
+	struct snd_card *card = dev_get_drvdata(dev);
+	struct snd_cs4231 *chip = card->private_data;
+
 	chip->resume(chip);
 	snd_power_change_state(card, SNDRV_CTL_POWER_D0);
 	return 0;
 }
 #endif
 
-#define SND_CS4231_DRIVER	"snd_cs4231"
-
-static struct platform_driver snd_cs4231_driver = {
+static struct isa_driver snd_cs4231_driver = {
+	.match		= snd_cs4231_match,
 	.probe		= snd_cs4231_probe,
 	.remove		= __devexit_p(snd_cs4231_remove),
 #ifdef CONFIG_PM
@@ -181,57 +188,19 @@ static struct platform_driver snd_cs4231_driver = {
 	.resume		= snd_cs4231_resume,
 #endif
 	.driver		= {
-		.name	= SND_CS4231_DRIVER
-	},
+		.name	= DEV_NAME
+	}
 };
 
-static void __init_or_module snd_cs4231_unregister_all(void)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(devices); ++i)
-		platform_device_unregister(devices[i]);
-	platform_driver_unregister(&snd_cs4231_driver);
-}
-
 static int __init alsa_card_cs4231_init(void)
 {
-	int i, cards, err;
-
-	err = platform_driver_register(&snd_cs4231_driver);
-	if (err < 0)
-		return err;
-
-	cards = 0;
-	for (i = 0; i < SNDRV_CARDS; i++) {
-		struct platform_device *device;
-		if (! enable[i])
-			continue;
-		device = platform_device_register_simple(SND_CS4231_DRIVER,
-							 i, NULL, 0);
-		if (IS_ERR(device))
-			continue;
-		if (!platform_get_drvdata(device)) {
-			platform_device_unregister(device);
-			continue;
-		}
-		devices[i] = device;
-		cards++;
-	}
-	if (!cards) {
-#ifdef MODULE
-		printk(KERN_ERR "CS4231 soundcard not found or device busy\n");
-#endif
-		snd_cs4231_unregister_all();
-		return -ENODEV;
-	}
-	return 0;
+	return isa_register_driver(&snd_cs4231_driver, SNDRV_CARDS);
 }
 
 static void __exit alsa_card_cs4231_exit(void)
 {
-	snd_cs4231_unregister_all();
+	isa_unregister_driver(&snd_cs4231_driver);
 }
 
-module_init(alsa_card_cs4231_init)
-module_exit(alsa_card_cs4231_exit)
+module_init(alsa_card_cs4231_init);
+module_exit(alsa_card_cs4231_exit);
diff --git a/sound/isa/cs423x/cs4231_lib.c b/sound/isa/cs423x/cs4231_lib.c
index 75c7c5f01989..914d77b61b0c 100644
--- a/sound/isa/cs423x/cs4231_lib.c
+++ b/sound/isa/cs423x/cs4231_lib.c
@@ -405,7 +405,6 @@ static int snd_cs4231_trigger(struct snd_pcm_substream *substream,
 	struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
 	int result = 0;
 	unsigned int what;
-	struct list_head *pos;
 	struct snd_pcm_substream *s;
 	int do_start;
 
@@ -425,8 +424,7 @@ static int snd_cs4231_trigger(struct snd_pcm_substream *substream,
 	}
 
 	what = 0;
-	snd_pcm_group_for_each(pos, substream) {
-		s = snd_pcm_group_substream_entry(pos);
+	snd_pcm_group_for_each_entry(s, substream) {
 		if (s == chip->playback_substream) {
 			what |= CS4231_PLAYBACK_ENABLE;
 			snd_pcm_trigger_done(s, substream);
diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c
index 07ffd5c22e81..87f1392a2fa7 100644
--- a/sound/isa/cs423x/cs4236.c
+++ b/sound/isa/cs423x/cs4236.c
@@ -22,7 +22,7 @@
 #include <sound/driver.h>
 #include <linux/init.h>
 #include <linux/err.h>
-#include <linux/platform_device.h>
+#include <linux/isa.h>
 #include <linux/slab.h>
 #include <linux/pnp.h>
 #include <linux/moduleparam.h>
@@ -75,10 +75,10 @@ MODULE_SUPPORTED_DEVICE("{{Crystal Semiconductors,CS4235},"
 
 #ifdef CS4232
 #define IDENT "CS4232"
-#define CS423X_DRIVER "snd_cs4232"
+#define DEV_NAME "cs4232"
 #else
 #define IDENT "CS4236+"
-#define CS423X_DRIVER "snd_cs4236"
+#define DEV_NAME "cs4236"
 #endif
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
@@ -126,14 +126,12 @@ MODULE_PARM_DESC(dma1, "DMA1 # for " IDENT " driver.");
 module_param_array(dma2, int, NULL, 0444);
 MODULE_PARM_DESC(dma2, "DMA2 # for " IDENT " driver.");
 
-static struct platform_device *platform_devices[SNDRV_CARDS];
 #ifdef CONFIG_PNP
 static int pnpc_registered;
 #ifdef CS4232
 static int pnp_registered;
 #endif
 #endif /* CONFIG_PNP */
-static unsigned int snd_cs423x_devices;
 
 struct snd_card_cs4236 {
 	struct snd_cs4231 *chip;
@@ -542,38 +540,55 @@ static int __devinit snd_cs423x_probe(struct snd_card *card, int dev)
 	return snd_card_register(card);
 }
 
-static int __init snd_cs423x_nonpnp_probe(struct platform_device *pdev)
+static int __devinit snd_cs423x_isa_match(struct device *pdev,
+					  unsigned int dev)
 {
-	int dev = pdev->id;
-	struct snd_card *card;
-	int err;
+	if (!enable[dev] || is_isapnp_selected(dev))
+		return 0;
 
 	if (port[dev] == SNDRV_AUTO_PORT) {
-		snd_printk(KERN_ERR "specify port\n");
-		return -EINVAL;
+		snd_printk(KERN_ERR "%s: please specify port\n", pdev->bus_id);
+		return 0;
 	}
 	if (cport[dev] == SNDRV_AUTO_PORT) {
-		snd_printk(KERN_ERR "specify cport\n");
-		return -EINVAL;
+		snd_printk(KERN_ERR "%s: please specify cport\n", pdev->bus_id);
+		return 0;
+	}
+	if (irq[dev] == SNDRV_AUTO_IRQ) {
+		snd_printk(KERN_ERR "%s: please specify irq\n", pdev->bus_id);
+		return 0;
 	}
+	if (dma1[dev] == SNDRV_AUTO_DMA) {
+		snd_printk(KERN_ERR "%s: please specify dma1\n", pdev->bus_id);
+		return 0;
+	}
+	return 1;
+}
+
+static int __devinit snd_cs423x_isa_probe(struct device *pdev,
+					  unsigned int dev)
+{
+	struct snd_card *card;
+	int err;
 
 	card = snd_cs423x_card_new(dev);
 	if (! card)
 		return -ENOMEM;
-	snd_card_set_dev(card, &pdev->dev);
+	snd_card_set_dev(card, pdev);
 	if ((err = snd_cs423x_probe(card, dev)) < 0) {
 		snd_card_free(card);
 		return err;
 	}
 
-	platform_set_drvdata(pdev, card);
+	dev_set_drvdata(pdev, card);
 	return 0;
 }
 
-static int __devexit snd_cs423x_nonpnp_remove(struct platform_device *devptr)
+static int __devexit snd_cs423x_isa_remove(struct device *pdev,
+					   unsigned int dev)
 {
-	snd_card_free(platform_get_drvdata(devptr));
-	platform_set_drvdata(devptr, NULL);
+	snd_card_free(dev_get_drvdata(pdev));
+	dev_set_drvdata(pdev, NULL);
 	return 0;
 }
 
@@ -594,26 +609,28 @@ static int snd_cs423x_resume(struct snd_card *card)
 	return 0;
 }
 
-static int snd_cs423x_nonpnp_suspend(struct platform_device *dev, pm_message_t state)
+static int snd_cs423x_isa_suspend(struct device *dev, unsigned int n,
+				  pm_message_t state)
 {
-	return snd_cs423x_suspend(platform_get_drvdata(dev));
+	return snd_cs423x_suspend(dev_get_drvdata(dev));
 }
 
-static int snd_cs423x_nonpnp_resume(struct platform_device *dev)
+static int snd_cs423x_isa_resume(struct device *dev, unsigned int n)
 {
-	return snd_cs423x_resume(platform_get_drvdata(dev));
+	return snd_cs423x_resume(dev_get_drvdata(dev));
 }
 #endif
 
-static struct platform_driver cs423x_nonpnp_driver = {
-	.probe		= snd_cs423x_nonpnp_probe,
-	.remove		= __devexit_p(snd_cs423x_nonpnp_remove),
+static struct isa_driver cs423x_isa_driver = {
+	.match		= snd_cs423x_isa_match,
+	.probe		= snd_cs423x_isa_probe,
+	.remove		= __devexit_p(snd_cs423x_isa_remove),
 #ifdef CONFIG_PM
-	.suspend	= snd_cs423x_nonpnp_suspend,
-	.resume		= snd_cs423x_nonpnp_resume,
+	.suspend	= snd_cs423x_isa_suspend,
+	.resume		= snd_cs423x_isa_resume,
 #endif
 	.driver		= {
-		.name	= CS423X_DRIVER
+		.name	= DEV_NAME
 	},
 };
 
@@ -651,7 +668,6 @@ static int __devinit snd_cs4232_pnpbios_detect(struct pnp_dev *pdev,
 	}
 	pnp_set_drvdata(pdev, card);
 	dev++;
-	snd_cs423x_devices++;
 	return 0;
 }
 
@@ -715,7 +731,6 @@ static int __devinit snd_cs423x_pnpc_detect(struct pnp_card_link *pcard,
 	}
 	pnp_set_card_drvdata(pcard, card);
 	dev++;
-	snd_cs423x_devices++;
 	return 0;
 }
 
@@ -750,45 +765,13 @@ static struct pnp_card_driver cs423x_pnpc_driver = {
 };
 #endif /* CONFIG_PNP */
 
-static void __init_or_module snd_cs423x_unregister_all(void)
-{
-	int i;
-
-#ifdef CONFIG_PNP
-	if (pnpc_registered)
-		pnp_unregister_card_driver(&cs423x_pnpc_driver);
-#ifdef CS4232
-	if (pnp_registered)
-		pnp_unregister_driver(&cs4232_pnp_driver);
-#endif
-#endif /* CONFIG_PNP */
-	for (i = 0; i < ARRAY_SIZE(platform_devices); ++i)
-		platform_device_unregister(platform_devices[i]);
-	platform_driver_unregister(&cs423x_nonpnp_driver);
-}
-
 static int __init alsa_card_cs423x_init(void)
 {
-	int i, err;
+	int err;
 
-	if ((err = platform_driver_register(&cs423x_nonpnp_driver)) < 0)
+	err = isa_register_driver(&cs423x_isa_driver, SNDRV_CARDS);
+	if (err < 0)
 		return err;
-
-	for (i = 0; i < SNDRV_CARDS; i++) {
-		struct platform_device *device;
-		if (! enable[i] || is_isapnp_selected(i))
-			continue;
-		device = platform_device_register_simple(CS423X_DRIVER,
-							 i, NULL, 0);
-		if (IS_ERR(device))
-			continue;
-		if (!platform_get_drvdata(device)) {
-			platform_device_unregister(device);
-			continue;
-		}
-		platform_devices[i] = device;
-		snd_cs423x_devices++;
-	}
 #ifdef CONFIG_PNP
 #ifdef CS4232
 	err = pnp_register_driver(&cs4232_pnp_driver);
@@ -799,20 +782,20 @@ static int __init alsa_card_cs423x_init(void)
 	if (!err)
 		pnpc_registered = 1;
 #endif /* CONFIG_PNP */
-
-	if (!snd_cs423x_devices) {
-#ifdef MODULE
-		printk(KERN_ERR IDENT " soundcard not found or device busy\n");
-#endif
-		snd_cs423x_unregister_all();
-		return -ENODEV;
-	}
 	return 0;
 }
 
 static void __exit alsa_card_cs423x_exit(void)
 {
-	snd_cs423x_unregister_all();
+#ifdef CONFIG_PNP
+	if (pnpc_registered)
+		pnp_unregister_card_driver(&cs423x_pnpc_driver);
+#ifdef CS4232
+	if (pnp_registered)
+		pnp_unregister_driver(&cs4232_pnp_driver);
+#endif
+#endif /* CONFIG_PNP */
+	isa_unregister_driver(&cs423x_isa_driver);
 }
 
 module_init(alsa_card_cs423x_init)
diff --git a/sound/isa/es1688/es1688.c b/sound/isa/es1688/es1688.c
index 65f97ff4eef1..edc398712e8b 100644
--- a/sound/isa/es1688/es1688.c
+++ b/sound/isa/es1688/es1688.c
@@ -22,7 +22,7 @@
 #include <sound/driver.h>
 #include <linux/init.h>
 #include <linux/err.h>
-#include <linux/platform_device.h>
+#include <linux/isa.h>
 #include <linux/time.h>
 #include <linux/wait.h>
 #include <linux/moduleparam.h>
@@ -35,8 +35,11 @@
 #define SNDRV_LEGACY_FIND_FREE_DMA
 #include <sound/initval.h>
 
+#define CRD_NAME "Generic ESS ES1688/ES688 AudioDrive"
+#define DEV_NAME "es1688"
+
+MODULE_DESCRIPTION(CRD_NAME);
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
-MODULE_DESCRIPTION("ESS ESx688 AudioDrive");
 MODULE_LICENSE("GPL");
 MODULE_SUPPORTED_DEVICE("{{ESS,ES688 PnP AudioDrive,pnp:ESS0100},"
 	        "{ESS,ES1688 PnP AudioDrive,pnp:ESS0102},"
@@ -53,189 +56,157 @@ static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;	/* 5,7,9,10 */
 static int dma8[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;	/* 0,1,3 */
 
 module_param_array(index, int, NULL, 0444);
-MODULE_PARM_DESC(index, "Index value for ESx688 soundcard.");
+MODULE_PARM_DESC(index, "Index value for " CRD_NAME " soundcard.");
 module_param_array(id, charp, NULL, 0444);
-MODULE_PARM_DESC(id, "ID string for ESx688 soundcard.");
+MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard.");
 module_param_array(enable, bool, NULL, 0444);
-MODULE_PARM_DESC(enable, "Enable ESx688 soundcard.");
+MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard.");
 module_param_array(port, long, NULL, 0444);
-MODULE_PARM_DESC(port, "Port # for ESx688 driver.");
+MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver.");
 module_param_array(mpu_port, long, NULL, 0444);
-MODULE_PARM_DESC(mpu_port, "MPU-401 port # for ESx688 driver.");
+MODULE_PARM_DESC(mpu_port, "MPU-401 port # for " CRD_NAME " driver.");
 module_param_array(irq, int, NULL, 0444);
-MODULE_PARM_DESC(irq, "IRQ # for ESx688 driver.");
+MODULE_PARM_DESC(irq, "IRQ # for " CRD_NAME " driver.");
 module_param_array(mpu_irq, int, NULL, 0444);
-MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for ESx688 driver.");
+MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for " CRD_NAME " driver.");
 module_param_array(dma8, int, NULL, 0444);
-MODULE_PARM_DESC(dma8, "8-bit DMA # for ESx688 driver.");
-
-static struct platform_device *devices[SNDRV_CARDS];
+MODULE_PARM_DESC(dma8, "8-bit DMA # for " CRD_NAME " driver.");
 
-#define PFX	"es1688: "
+static int __devinit snd_es1688_match(struct device *dev, unsigned int n)
+{
+	return enable[n];
+}
 
-static int __devinit snd_es1688_probe(struct platform_device *pdev)
+static int __devinit snd_es1688_legacy_create(struct snd_card *card, 
+		struct device *dev, unsigned int n, struct snd_es1688 **rchip)
 {
-	int dev = pdev->id;
+	static long possible_ports[] = {0x220, 0x240, 0x260};
 	static int possible_irqs[] = {5, 9, 10, 7, -1};
 	static int possible_dmas[] = {1, 3, 0, -1};
-	int xirq, xdma, xmpu_irq;
-	struct snd_card *card;
-	struct snd_es1688 *chip;
-	struct snd_opl3 *opl3;
-	struct snd_pcm *pcm;
-	int err;
-
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-	if (card == NULL)
-		return -ENOMEM;
-
-	xirq = irq[dev];
-	if (xirq == SNDRV_AUTO_IRQ) {
-		if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
-			snd_printk(KERN_ERR PFX "unable to find a free IRQ\n");
-			err = -EBUSY;
-			goto _err;
+
+	int i, error;
+
+	if (irq[n] == SNDRV_AUTO_IRQ) {
+		irq[n] = snd_legacy_find_free_irq(possible_irqs);
+		if (irq[n] < 0) {
+			snd_printk(KERN_ERR "%s: unable to find a free IRQ\n",
+				dev->bus_id);
+			return -EBUSY;
 		}
 	}
-	xmpu_irq = mpu_irq[dev];
-	xdma = dma8[dev];
-	if (xdma == SNDRV_AUTO_DMA) {
-		if ((xdma = snd_legacy_find_free_dma(possible_dmas)) < 0) {
-			snd_printk(KERN_ERR PFX "unable to find a free DMA\n");
-			err = -EBUSY;
-			goto _err;
+	if (dma8[n] == SNDRV_AUTO_DMA) {
+		dma8[n] = snd_legacy_find_free_dma(possible_dmas);
+		if (dma8[n] < 0) {
+			snd_printk(KERN_ERR "%s: unable to find a free DMA\n",
+				dev->bus_id);
+			return -EBUSY;
 		}
 	}
 
-	if (port[dev] != SNDRV_AUTO_PORT) {
-		if ((err = snd_es1688_create(card, port[dev], mpu_port[dev],
-					     xirq, xmpu_irq, xdma,
-					     ES1688_HW_AUTO, &chip)) < 0)
-			goto _err;
-	} else {
-		/* auto-probe legacy ports */
-		static unsigned long possible_ports[] = {
-			0x220, 0x240, 0x260,
-		};
-		int i;
-		for (i = 0; i < ARRAY_SIZE(possible_ports); i++) {
-			err = snd_es1688_create(card, possible_ports[i],
-						mpu_port[dev],
-						xirq, xmpu_irq, xdma,
-						ES1688_HW_AUTO, &chip);
-			if (err >= 0) {
-				port[dev] = possible_ports[i];
-				break;
-			}
-		}
-		if (i >= ARRAY_SIZE(possible_ports))
-			goto _err;
-	}
+	if (port[n] != SNDRV_AUTO_PORT)
+		return snd_es1688_create(card, port[n], mpu_port[n], irq[n],
+				mpu_irq[n], dma8[n], ES1688_HW_AUTO, rchip);
+
+	i = 0;
+	do {
+		port[n] = possible_ports[i];
+		error = snd_es1688_create(card, port[n], mpu_port[n], irq[n],
+				mpu_irq[n], dma8[n], ES1688_HW_AUTO, rchip);
+	} while (error < 0 && ++i < ARRAY_SIZE(possible_ports));
+
+	return error;
+}
+
+static int __devinit snd_es1688_probe(struct device *dev, unsigned int n)
+{
+	struct snd_card *card;
+	struct snd_es1688 *chip;
+	struct snd_opl3 *opl3;
+	struct snd_pcm *pcm;
+	int error;
+
+	card = snd_card_new(index[n], id[n], THIS_MODULE, 0);
+	if (!card)
+		return -EINVAL;
+
+	error = snd_es1688_legacy_create(card, dev, n, &chip);
+	if (error < 0)
+		goto out;
 
-	if ((err = snd_es1688_pcm(chip, 0, &pcm)) < 0)
-		goto _err;
+	error = snd_es1688_pcm(chip, 0, &pcm);
+	if (error < 0)
+		goto out;
 
-	if ((err = snd_es1688_mixer(chip)) < 0)
-		goto _err;
+	error = snd_es1688_mixer(chip);
+	if (error < 0)
+		goto out;
 
 	strcpy(card->driver, "ES1688");
 	strcpy(card->shortname, pcm->name);
-	sprintf(card->longname, "%s at 0x%lx, irq %i, dma %i", pcm->name, chip->port, xirq, xdma);
-
-	if ((snd_opl3_create(card, chip->port, chip->port + 2, OPL3_HW_OPL3, 0, &opl3)) < 0) {
-		printk(KERN_WARNING PFX "opl3 not detected at 0x%lx\n", chip->port);
-	} else {
-		if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0)
-			goto _err;
+	sprintf(card->longname, "%s at 0x%lx, irq %i, dma %i", pcm->name,
+		chip->port, chip->irq, chip->dma8);
+
+	if (snd_opl3_create(card, chip->port, chip->port + 2,
+			OPL3_HW_OPL3, 0, &opl3) < 0)
+		printk(KERN_WARNING "%s: opl3 not detected at 0x%lx\n",
+			dev->bus_id, chip->port);
+	else {
+		error =	snd_opl3_hwdep_new(opl3, 0, 1, NULL);
+		if (error < 0)
+			goto out;
 	}
 
-	if (xmpu_irq >= 0 && xmpu_irq != SNDRV_AUTO_IRQ && chip->mpu_port > 0) {
-		if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_ES1688,
-					       chip->mpu_port, 0,
-					       xmpu_irq,
-					       IRQF_DISABLED,
-					       NULL)) < 0)
-			goto _err;
+	if (mpu_irq[n] >= 0 && mpu_irq[n] != SNDRV_AUTO_IRQ &&
+			chip->mpu_port > 0) {
+		error = snd_mpu401_uart_new(card, 0, MPU401_HW_ES1688,
+				chip->mpu_port, 0,
+				mpu_irq[n], IRQF_DISABLED, NULL);
+		if (error < 0)
+			goto out;
 	}
 
-	snd_card_set_dev(card, &pdev->dev);
+	snd_card_set_dev(card, dev);
 
-	if ((err = snd_card_register(card)) < 0)
-		goto _err;
+	error = snd_card_register(card);
+	if (error < 0)
+		goto out;
 
-	platform_set_drvdata(pdev, card);
+	dev_set_drvdata(dev, card);
 	return 0;
 
- _err:
-	snd_card_free(card);
-	return err;
+out:	snd_card_free(card);
+	return error;
 }
 
-static int __devexit snd_es1688_remove(struct platform_device *devptr)
+static int __devexit snd_es1688_remove(struct device *dev, unsigned int n)
 {
-	snd_card_free(platform_get_drvdata(devptr));
-	platform_set_drvdata(devptr, NULL);
+	snd_card_free(dev_get_drvdata(dev));
+	dev_set_drvdata(dev, NULL);
 	return 0;
 }
 
-#define ES1688_DRIVER	"snd_es1688"
-
-static struct platform_driver snd_es1688_driver = {
+static struct isa_driver snd_es1688_driver = {
+	.match		= snd_es1688_match,
 	.probe		= snd_es1688_probe,
-	.remove		= __devexit_p(snd_es1688_remove),
-	/* FIXME: suspend/resume */
+	.remove		= snd_es1688_remove,
+#if 0	/* FIXME */
+	.suspend	= snd_es1688_suspend,
+	.resume		= snd_es1688_resume,
+#endif
 	.driver		= {
-		.name	= ES1688_DRIVER
-	},
+		.name	= DEV_NAME
+	}
 };
 
-static void __init_or_module snd_es1688_unregister_all(void)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(devices); ++i)
-		platform_device_unregister(devices[i]);
-	platform_driver_unregister(&snd_es1688_driver);
-}
-
 static int __init alsa_card_es1688_init(void)
 {
-	int i, cards, err;
-
-	err = platform_driver_register(&snd_es1688_driver);
-	if (err < 0)
-		return err;
-
-	cards = 0;
-	for (i = 0; i < SNDRV_CARDS; i++) {
-		struct platform_device *device;
-		if (! enable[i])
-			continue;
-		device = platform_device_register_simple(ES1688_DRIVER,
-							 i, NULL, 0);
-		if (IS_ERR(device))
-			continue;
-		if (!platform_get_drvdata(device)) {
-			platform_device_unregister(device);
-			continue;
-		}
-		devices[i] = device;
-		cards++;
-	}
-	if (!cards) {
-#ifdef MODULE
-		printk(KERN_ERR "ESS AudioDrive ES1688 soundcard not found or device busy\n");
-#endif
-		snd_es1688_unregister_all();
-		return -ENODEV;
-	}
-	return 0;
+	return isa_register_driver(&snd_es1688_driver, SNDRV_CARDS);
 }
 
 static void __exit alsa_card_es1688_exit(void)
 {
-	snd_es1688_unregister_all();
+	isa_unregister_driver(&snd_es1688_driver);
 }
 
-module_init(alsa_card_es1688_init)
-module_exit(alsa_card_es1688_exit)
+module_init(alsa_card_es1688_init);
+module_exit(alsa_card_es1688_exit);
diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c
index 725c115ff97d..d2a9c7df0ce5 100644
--- a/sound/isa/es18xx.c
+++ b/sound/isa/es18xx.c
@@ -80,7 +80,7 @@
 #include <sound/driver.h>
 #include <linux/init.h>
 #include <linux/err.h>
-#include <linux/platform_device.h>
+#include <linux/isa.h>
 #include <linux/slab.h>
 #include <linux/pnp.h>
 #include <linux/isapnp.h>
@@ -2035,8 +2035,6 @@ MODULE_PARM_DESC(dma1, "DMA 1 # for ES18xx driver.");
 module_param_array(dma2, int, NULL, 0444);
 MODULE_PARM_DESC(dma2, "DMA 2 # for ES18xx driver.");
 
-static struct platform_device *platform_devices[SNDRV_CARDS];
-
 #ifdef CONFIG_PNP
 static int pnp_registered, pnpc_registered;
 
@@ -2237,7 +2235,12 @@ static int __devinit snd_audiodrive_probe(struct snd_card *card, int dev)
 	return snd_card_register(card);
 }
 
-static int __devinit snd_es18xx_nonpnp_probe1(int dev, struct platform_device *devptr)
+static int __devinit snd_es18xx_isa_match(struct device *pdev, unsigned int dev)
+{
+	return enable[dev] && !is_isapnp_selected(dev);
+}
+
+static int __devinit snd_es18xx_isa_probe1(int dev, struct device *devptr)
 {
 	struct snd_card *card;
 	int err;
@@ -2245,18 +2248,17 @@ static int __devinit snd_es18xx_nonpnp_probe1(int dev, struct platform_device *d
 	card = snd_es18xx_card_new(dev);
 	if (! card)
 		return -ENOMEM;
-	snd_card_set_dev(card, &devptr->dev);
+	snd_card_set_dev(card, devptr);
 	if ((err = snd_audiodrive_probe(card, dev)) < 0) {
 		snd_card_free(card);
 		return err;
 	}
-	platform_set_drvdata(devptr, card);
+	dev_set_drvdata(devptr, card);
 	return 0;
 }
 
-static int __devinit snd_es18xx_nonpnp_probe(struct platform_device *pdev)
+static int __devinit snd_es18xx_isa_probe(struct device *pdev, unsigned int dev)
 {
-	int dev = pdev->id;
 	int err;
 	static int possible_irqs[] = {5, 9, 10, 7, 11, 12, -1};
 	static int possible_dmas[] = {1, 0, 3, 5, -1};
@@ -2281,13 +2283,13 @@ static int __devinit snd_es18xx_nonpnp_probe(struct platform_device *pdev)
 	}
 
 	if (port[dev] != SNDRV_AUTO_PORT) {
-		return snd_es18xx_nonpnp_probe1(dev, pdev);
+		return snd_es18xx_isa_probe1(dev, pdev);
 	} else {
 		static unsigned long possible_ports[] = {0x220, 0x240, 0x260, 0x280};
 		int i;
 		for (i = 0; i < ARRAY_SIZE(possible_ports); i++) {
 			port[dev] = possible_ports[i];
-			err = snd_es18xx_nonpnp_probe1(dev, pdev);
+			err = snd_es18xx_isa_probe1(dev, pdev);
 			if (! err)
 				return 0;
 		}
@@ -2295,43 +2297,44 @@ static int __devinit snd_es18xx_nonpnp_probe(struct platform_device *pdev)
 	}
 }
 
-static int __devexit snd_es18xx_nonpnp_remove(struct platform_device *devptr)
+static int __devexit snd_es18xx_isa_remove(struct device *devptr,
+					   unsigned int dev)
 {
-	snd_card_free(platform_get_drvdata(devptr));
-	platform_set_drvdata(devptr, NULL);
+	snd_card_free(dev_get_drvdata(devptr));
+	dev_set_drvdata(devptr, NULL);
 	return 0;
 }
 
 #ifdef CONFIG_PM
-static int snd_es18xx_nonpnp_suspend(struct platform_device *dev, pm_message_t state)
+static int snd_es18xx_isa_suspend(struct device *dev, unsigned int n,
+				  pm_message_t state)
 {
-	return snd_es18xx_suspend(platform_get_drvdata(dev), state);
+	return snd_es18xx_suspend(dev_get_drvdata(dev), state);
 }
 
-static int snd_es18xx_nonpnp_resume(struct platform_device *dev)
+static int snd_es18xx_isa_resume(struct device *dev, unsigned int n)
 {
-	return snd_es18xx_resume(platform_get_drvdata(dev));
+	return snd_es18xx_resume(dev_get_drvdata(dev));
 }
 #endif
 
-#define ES18XX_DRIVER	"snd_es18xx"
+#define DEV_NAME "es18xx"
 
-static struct platform_driver snd_es18xx_nonpnp_driver = {
-	.probe		= snd_es18xx_nonpnp_probe,
-	.remove		= __devexit_p(snd_es18xx_nonpnp_remove),
+static struct isa_driver snd_es18xx_isa_driver = {
+	.match		= snd_es18xx_isa_match,
+	.probe		= snd_es18xx_isa_probe,
+	.remove		= __devexit_p(snd_es18xx_isa_remove),
 #ifdef CONFIG_PM
-	.suspend	= snd_es18xx_nonpnp_suspend,
-	.resume		= snd_es18xx_nonpnp_resume,
+	.suspend	= snd_es18xx_isa_suspend,
+	.resume		= snd_es18xx_isa_resume,
 #endif
 	.driver		= {
-		.name	= ES18XX_DRIVER
+		.name	= DEV_NAME
 	},
 };
 
 
 #ifdef CONFIG_PNP
-static unsigned int __devinitdata es18xx_pnp_devices;
-
 static int __devinit snd_audiodrive_pnp_detect(struct pnp_dev *pdev,
 					    const struct pnp_device_id *id)
 {
@@ -2362,7 +2365,6 @@ static int __devinit snd_audiodrive_pnp_detect(struct pnp_dev *pdev,
 	}
 	pnp_set_drvdata(pdev, card);
 	dev++;
-	es18xx_pnp_devices++;
 	return 0;
 }
 
@@ -2424,7 +2426,6 @@ static int __devinit snd_audiodrive_pnpc_detect(struct pnp_card_link *pcard,
 
 	pnp_set_card_drvdata(pcard, card);
 	dev++;
-	es18xx_pnp_devices++;
 	return 0;
 }
 
@@ -2460,44 +2461,14 @@ static struct pnp_card_driver es18xx_pnpc_driver = {
 };
 #endif /* CONFIG_PNP */
 
-static void __init_or_module snd_es18xx_unregister_all(void)
-{
-	int i;
-
-#ifdef CONFIG_PNP
-	if (pnpc_registered)
-		pnp_unregister_card_driver(&es18xx_pnpc_driver);
-	if (pnp_registered)
-		pnp_unregister_driver(&es18xx_pnp_driver);
-#endif
-	for (i = 0; i < ARRAY_SIZE(platform_devices); ++i)
-		platform_device_unregister(platform_devices[i]);
-	platform_driver_unregister(&snd_es18xx_nonpnp_driver);
-}
-
 static int __init alsa_card_es18xx_init(void)
 {
-	int i, err, cards = 0;
+	int err;
 
-	if ((err = platform_driver_register(&snd_es18xx_nonpnp_driver)) < 0)
+	err = isa_register_driver(&snd_es18xx_isa_driver, SNDRV_CARDS);
+	if (err < 0)
 		return err;
 
-	for (i = 0; i < SNDRV_CARDS; i++) {
-		struct platform_device *device;
-		if (! enable[i] || is_isapnp_selected(i))
-			continue;
-		device = platform_device_register_simple(ES18XX_DRIVER,
-							 i, NULL, 0);
-		if (IS_ERR(device))
-	       		continue;
-		if (!platform_get_drvdata(device)) {
-			platform_device_unregister(device);
-			continue;
-		}
-		platform_devices[i] = device;
-		cards++;
-	}
-
 #ifdef CONFIG_PNP
 	err = pnp_register_driver(&es18xx_pnp_driver);
 	if (!err)
@@ -2505,22 +2476,19 @@ static int __init alsa_card_es18xx_init(void)
 	err = pnp_register_card_driver(&es18xx_pnpc_driver);
 	if (!err)
 		pnpc_registered = 1;
-	cards += es18xx_pnp_devices;
-#endif
-
-	if(!cards) {
-#ifdef MODULE
-		snd_printk(KERN_ERR "ESS AudioDrive ES18xx soundcard not found or device busy\n");
 #endif
-		snd_es18xx_unregister_all();
-		return -ENODEV;
-	}
 	return 0;
 }
 
 static void __exit alsa_card_es18xx_exit(void)
 {
-	snd_es18xx_unregister_all();
+#ifdef CONFIG_PNP
+	if (pnpc_registered)
+		pnp_unregister_card_driver(&es18xx_pnpc_driver);
+	if (pnp_registered)
+		pnp_unregister_driver(&es18xx_pnp_driver);
+#endif
+	isa_unregister_driver(&snd_es18xx_isa_driver);
 }
 
 module_init(alsa_card_es18xx_init)
diff --git a/sound/isa/gus/gusclassic.c b/sound/isa/gus/gusclassic.c
index 0395e2e0dd03..8f23f433d491 100644
--- a/sound/isa/gus/gusclassic.c
+++ b/sound/isa/gus/gusclassic.c
@@ -22,7 +22,7 @@
 #include <sound/driver.h>
 #include <linux/init.h>
 #include <linux/err.h>
-#include <linux/platform_device.h>
+#include <linux/isa.h>
 #include <linux/delay.h>
 #include <linux/time.h>
 #include <linux/moduleparam.h>
@@ -33,8 +33,11 @@
 #define SNDRV_LEGACY_FIND_FREE_DMA
 #include <sound/initval.h>
 
+#define CRD_NAME "Gravis UltraSound Classic"
+#define DEV_NAME "gusclassic"
+
+MODULE_DESCRIPTION(CRD_NAME);
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
-MODULE_DESCRIPTION("Gravis UltraSound Classic");
 MODULE_LICENSE("GPL");
 MODULE_SUPPORTED_DEVICE("{{Gravis,UltraSound Classic}}");
 
@@ -51,32 +54,80 @@ static int channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 24};
 static int pcm_channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2};
 
 module_param_array(index, int, NULL, 0444);
-MODULE_PARM_DESC(index, "Index value for GUS Classic soundcard.");
+MODULE_PARM_DESC(index, "Index value for " CRD_NAME " soundcard.");
 module_param_array(id, charp, NULL, 0444);
-MODULE_PARM_DESC(id, "ID string for GUS Classic soundcard.");
+MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard.");
 module_param_array(enable, bool, NULL, 0444);
-MODULE_PARM_DESC(enable, "Enable GUS Classic soundcard.");
+MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard.");
 module_param_array(port, long, NULL, 0444);
-MODULE_PARM_DESC(port, "Port # for GUS Classic driver.");
+MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver.");
 module_param_array(irq, int, NULL, 0444);
-MODULE_PARM_DESC(irq, "IRQ # for GUS Classic driver.");
+MODULE_PARM_DESC(irq, "IRQ # for " CRD_NAME " driver.");
 module_param_array(dma1, int, NULL, 0444);
-MODULE_PARM_DESC(dma1, "DMA1 # for GUS Classic driver.");
+MODULE_PARM_DESC(dma1, "DMA1 # for " CRD_NAME " driver.");
 module_param_array(dma2, int, NULL, 0444);
-MODULE_PARM_DESC(dma2, "DMA2 # for GUS Classic driver.");
+MODULE_PARM_DESC(dma2, "DMA2 # for " CRD_NAME " driver.");
 module_param_array(joystick_dac, int, NULL, 0444);
-MODULE_PARM_DESC(joystick_dac, "Joystick DAC level 0.59V-4.52V or 0.389V-2.98V for GUS Classic driver.");
+MODULE_PARM_DESC(joystick_dac, "Joystick DAC level 0.59V-4.52V or 0.389V-2.98V for " CRD_NAME " driver.");
 module_param_array(channels, int, NULL, 0444);
-MODULE_PARM_DESC(channels, "GF1 channels for GUS Classic driver.");
+MODULE_PARM_DESC(channels, "GF1 channels for " CRD_NAME " driver.");
 module_param_array(pcm_channels, int, NULL, 0444);
-MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for GUS Classic driver.");
+MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for " CRD_NAME " driver.");
+
+static int __devinit snd_gusclassic_match(struct device *dev, unsigned int n)
+{
+	return enable[n];
+}
+
+static int __devinit snd_gusclassic_create(struct snd_card *card,
+		struct device *dev, unsigned int n, struct snd_gus_card **rgus)
+{
+	static long possible_ports[] = {0x220, 0x230, 0x240, 0x250, 0x260};
+	static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, 4, -1};
+	static int possible_dmas[] = {5, 6, 7, 1, 3, -1};
+
+	int i, error;
+
+	if (irq[n] == SNDRV_AUTO_IRQ) {
+		irq[n] = snd_legacy_find_free_irq(possible_irqs);
+		if (irq[n] < 0) {
+			snd_printk(KERN_ERR "%s: unable to find a free IRQ\n",
+				dev->bus_id);
+			return -EBUSY;
+		}
+	}
+	if (dma1[n] == SNDRV_AUTO_DMA) {
+		dma1[n] = snd_legacy_find_free_dma(possible_dmas);
+		if (dma1[n] < 0) {
+			snd_printk(KERN_ERR "%s: unable to find a free DMA1\n",
+				dev->bus_id);
+			return -EBUSY;
+		}
+	}
+	if (dma2[n] == SNDRV_AUTO_DMA) {
+		dma2[n] = snd_legacy_find_free_dma(possible_dmas);
+		if (dma2[n] < 0) {
+			snd_printk(KERN_ERR "%s: unable to find a free DMA2\n",
+				dev->bus_id);
+			return -EBUSY;
+		}
+	}
 
-static struct platform_device *devices[SNDRV_CARDS];
+	if (port[n] != SNDRV_AUTO_PORT)
+		return snd_gus_create(card, port[n], irq[n], dma1[n], dma2[n],
+				0, channels[n], pcm_channels[n], 0, rgus);
 
+	i = 0;
+	do {
+		port[n] = possible_ports[i];
+		error = snd_gus_create(card, port[n], irq[n], dma1[n], dma2[n],
+				0, channels[n], pcm_channels[n], 0, rgus);
+	} while (error < 0 && ++i < ARRAY_SIZE(possible_ports));
 
-#define PFX	"gusclassic: "
+	return error;
+}
 
-static int __devinit snd_gusclassic_detect(struct snd_gus_card * gus)
+static int __devinit snd_gusclassic_detect(struct snd_gus_card *gus)
 {
 	unsigned char d;
 
@@ -95,187 +146,104 @@ static int __devinit snd_gusclassic_detect(struct snd_gus_card * gus)
 	return 0;
 }
 
-static void __devinit snd_gusclassic_init(int dev, struct snd_gus_card * gus)
-{
-	gus->equal_irq = 0;
-	gus->codec_flag = 0;
-	gus->max_flag = 0;
-	gus->joystick_dac = joystick_dac[dev];
-}
-
-static int __devinit snd_gusclassic_probe(struct platform_device *pdev)
+static int __devinit snd_gusclassic_probe(struct device *dev, unsigned int n)
 {
-	int dev = pdev->id;
-	static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, 4, -1};
-	static int possible_dmas[] = {5, 6, 7, 1, 3, -1};
-	int xirq, xdma1, xdma2;
 	struct snd_card *card;
-	struct snd_gus_card *gus = NULL;
-	int err;
-
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-	if (card == NULL)
-		return -ENOMEM;
-	if (pcm_channels[dev] < 2)
-		pcm_channels[dev] = 2;
-
-	xirq = irq[dev];
-	if (xirq == SNDRV_AUTO_IRQ) {
-		if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
-			snd_printk(KERN_ERR PFX "unable to find a free IRQ\n");
-			err = -EBUSY;
-			goto _err;
-		}
-	}
-	xdma1 = dma1[dev];
-	if (xdma1 == SNDRV_AUTO_DMA) {
-		if ((xdma1 = snd_legacy_find_free_dma(possible_dmas)) < 0) {
-			snd_printk(KERN_ERR PFX "unable to find a free DMA1\n");
-			err = -EBUSY;
-			goto _err;
-		}
-	}
-	xdma2 = dma2[dev];
-	if (xdma2 == SNDRV_AUTO_DMA) {
-		if ((xdma2 = snd_legacy_find_free_dma(possible_dmas)) < 0) {
-			snd_printk(KERN_ERR PFX "unable to find a free DMA2\n");
-			err = -EBUSY;
-			goto _err;
-		}
-	}
+	struct snd_gus_card *gus;
+	int error;
 
-	if (port[dev] != SNDRV_AUTO_PORT) {
-		err = snd_gus_create(card,
-				     port[dev],
-				     xirq, xdma1, xdma2,
-				     0, channels[dev], pcm_channels[dev],
-				     0, &gus);
-	} else {
-		/* auto-probe legacy ports */
-		static unsigned long possible_ports[] = {
-			0x220, 0x230, 0x240, 0x250, 0x260,
-		};
-		int i;
-		for (i = 0; i < ARRAY_SIZE(possible_ports); i++) {
-			err = snd_gus_create(card,
-					     possible_ports[i],
-					     xirq, xdma1, xdma2,
-					     0, channels[dev], pcm_channels[dev],
-					     0, &gus);
-			if (err >= 0) {
-				port[dev] = possible_ports[i];
-				break;
-			}
-		}
-	}
-	if (err < 0)
-		goto _err;
+	card = snd_card_new(index[n], id[n], THIS_MODULE, 0);
+	if (!card)
+		return -EINVAL;
 
-	if ((err = snd_gusclassic_detect(gus)) < 0)
-		goto _err;
+	if (pcm_channels[n] < 2)
+		pcm_channels[n] = 2;
 
-	snd_gusclassic_init(dev, gus);
-	if ((err = snd_gus_initialize(gus)) < 0)
-		goto _err;
+	error = snd_gusclassic_create(card, dev, n, &gus);
+	if (error < 0)
+		goto out;
 
+	error = snd_gusclassic_detect(gus);
+	if (error < 0)
+		goto out;
+
+	gus->joystick_dac = joystick_dac[n];
+
+	error = snd_gus_initialize(gus);
+	if (error < 0)
+		goto out;
+
+	error = -ENODEV;
 	if (gus->max_flag || gus->ess_flag) {
-		snd_printk(KERN_ERR PFX "GUS Classic or ACE soundcard was not detected at 0x%lx\n", gus->gf1.port);
-		err = -ENODEV;
-		goto _err;
+		snd_printk(KERN_ERR "%s: GUS Classic or ACE soundcard was "
+			"not detected at 0x%lx\n", dev->bus_id, gus->gf1.port);
+		goto out;
 	}
 
-	if ((err = snd_gf1_new_mixer(gus)) < 0)
-		goto _err;
+	error = snd_gf1_new_mixer(gus);
+	if (error < 0)
+		goto out;
 
-	if ((err = snd_gf1_pcm_new(gus, 0, 0, NULL)) < 0)
-		goto _err;
+	error = snd_gf1_pcm_new(gus, 0, 0, NULL);
+	if (error < 0)
+		goto out;
 
 	if (!gus->ace_flag) {
-		if ((err = snd_gf1_rawmidi_new(gus, 0, NULL)) < 0)
-			goto _err;
+		error = snd_gf1_rawmidi_new(gus, 0, NULL);
+		if (error < 0)
+			goto out;
 	}
-	sprintf(card->longname + strlen(card->longname), " at 0x%lx, irq %d, dma %d", gus->gf1.port, xirq, xdma1);
-	if (xdma2 >= 0)
-		sprintf(card->longname + strlen(card->longname), "&%d", xdma2);
 
-	snd_card_set_dev(card, &pdev->dev);
+	sprintf(card->longname + strlen(card->longname),
+		" at 0x%lx, irq %d, dma %d",
+		gus->gf1.port, gus->gf1.irq, gus->gf1.dma1);
 
-	if ((err = snd_card_register(card)) < 0)
-		goto _err;
+	if (gus->gf1.dma2 >= 0)
+		sprintf(card->longname + strlen(card->longname),
+			"&%d", gus->gf1.dma2);
 
-	platform_set_drvdata(pdev, card);
+	snd_card_set_dev(card, dev);
+
+	error = snd_card_register(card);
+	if (error < 0)
+		goto out;
+
+	dev_set_drvdata(dev, card);
 	return 0;
 
- _err:
-	snd_card_free(card);
-	return err;
+out:	snd_card_free(card);
+	return error;
 }
 
-static int __devexit snd_gusclassic_remove(struct platform_device *devptr)
+static int __devexit snd_gusclassic_remove(struct device *dev, unsigned int n)
 {
-	snd_card_free(platform_get_drvdata(devptr));
-	platform_set_drvdata(devptr, NULL);
+	snd_card_free(dev_get_drvdata(dev));
+	dev_set_drvdata(dev, NULL);
 	return 0;
 }
 
-#define GUSCLASSIC_DRIVER	"snd_gusclassic"
-
-static struct platform_driver snd_gusclassic_driver = {
+static struct isa_driver snd_gusclassic_driver = {
+	.match		= snd_gusclassic_match,
 	.probe		= snd_gusclassic_probe,
 	.remove		= __devexit_p(snd_gusclassic_remove),
-	/* FIXME: suspend/resume */
+#if 0	/* FIXME */
+	.suspend	= snd_gusclassic_suspend,
+	.remove		= snd_gusclassic_remove,
+#endif
 	.driver		= {
-		.name	= GUSCLASSIC_DRIVER
-	},
+		.name	= DEV_NAME
+	}
 };
 
-static void __init_or_module snd_gusclassic_unregister_all(void)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(devices); ++i)
-		platform_device_unregister(devices[i]);
-	platform_driver_unregister(&snd_gusclassic_driver);
-}
-
 static int __init alsa_card_gusclassic_init(void)
 {
-	int i, cards, err;
-
-	err = platform_driver_register(&snd_gusclassic_driver);
-	if (err < 0)
-		return err;
-
-	cards = 0;
-	for (i = 0; i < SNDRV_CARDS; i++) {
-		struct platform_device *device;
-		if (! enable[i])
-			continue;
-		device = platform_device_register_simple(GUSCLASSIC_DRIVER,
-							 i, NULL, 0);
-		if (IS_ERR(device))
-			continue;
-		if (!platform_get_drvdata(device)) {
-			platform_device_unregister(device);
-			continue;
-		}
-		devices[i] = device;
-		cards++;
-	}
-	if (!cards) {
-#ifdef MODULE
-		printk(KERN_ERR "GUS Classic soundcard not found or device busy\n");
-#endif
-		snd_gusclassic_unregister_all();
-		return -ENODEV;
-	}
-	return 0;
+	return isa_register_driver(&snd_gusclassic_driver, SNDRV_CARDS);
 }
 
 static void __exit alsa_card_gusclassic_exit(void)
 {
-	snd_gusclassic_unregister_all();
+	isa_unregister_driver(&snd_gusclassic_driver);
 }
 
-module_init(alsa_card_gusclassic_init)
-module_exit(alsa_card_gusclassic_exit)
+module_init(alsa_card_gusclassic_init);
+module_exit(alsa_card_gusclassic_exit);
diff --git a/sound/isa/gus/gusextreme.c b/sound/isa/gus/gusextreme.c
index 4f55fc3e66c1..0aeaa6cf6cf0 100644
--- a/sound/isa/gus/gusextreme.c
+++ b/sound/isa/gus/gusextreme.c
@@ -22,7 +22,7 @@
 #include <sound/driver.h>
 #include <linux/init.h>
 #include <linux/err.h>
-#include <linux/platform_device.h>
+#include <linux/isa.h>
 #include <linux/delay.h>
 #include <linux/time.h>
 #include <linux/moduleparam.h>
@@ -37,8 +37,11 @@
 #define SNDRV_LEGACY_FIND_FREE_DMA
 #include <sound/initval.h>
 
+#define CRD_NAME "Gravis UltraSound Extreme"
+#define DEV_NAME "gusextreme"
+
+MODULE_DESCRIPTION(CRD_NAME);
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
-MODULE_DESCRIPTION("Gravis UltraSound Extreme");
 MODULE_LICENSE("GPL");
 MODULE_SUPPORTED_DEVICE("{{Gravis,UltraSound Extreme}}");
 
@@ -59,43 +62,107 @@ static int channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 24};
 static int pcm_channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2};
 
 module_param_array(index, int, NULL, 0444);
-MODULE_PARM_DESC(index, "Index value for GUS Extreme soundcard.");
+MODULE_PARM_DESC(index, "Index value for " CRD_NAME " soundcard.");
 module_param_array(id, charp, NULL, 0444);
-MODULE_PARM_DESC(id, "ID string for GUS Extreme soundcard.");
+MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard.");
 module_param_array(enable, bool, NULL, 0444);
-MODULE_PARM_DESC(enable, "Enable GUS Extreme soundcard.");
+MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard.");
 module_param_array(port, long, NULL, 0444);
-MODULE_PARM_DESC(port, "Port # for GUS Extreme driver.");
+MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver.");
 module_param_array(gf1_port, long, NULL, 0444);
-MODULE_PARM_DESC(gf1_port, "GF1 port # for GUS Extreme driver (optional).");
+MODULE_PARM_DESC(gf1_port, "GF1 port # for " CRD_NAME " driver (optional).");
 module_param_array(mpu_port, long, NULL, 0444);
-MODULE_PARM_DESC(mpu_port, "MPU-401 port # for GUS Extreme driver.");
+MODULE_PARM_DESC(mpu_port, "MPU-401 port # for " CRD_NAME " driver.");
 module_param_array(irq, int, NULL, 0444);
-MODULE_PARM_DESC(irq, "IRQ # for GUS Extreme driver.");
+MODULE_PARM_DESC(irq, "IRQ # for " CRD_NAME " driver.");
 module_param_array(mpu_irq, int, NULL, 0444);
-MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for GUS Extreme driver.");
+MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for " CRD_NAME " driver.");
 module_param_array(gf1_irq, int, NULL, 0444);
-MODULE_PARM_DESC(gf1_irq, "GF1 IRQ # for GUS Extreme driver.");
+MODULE_PARM_DESC(gf1_irq, "GF1 IRQ # for " CRD_NAME " driver.");
 module_param_array(dma8, int, NULL, 0444);
-MODULE_PARM_DESC(dma8, "8-bit DMA # for GUS Extreme driver.");
+MODULE_PARM_DESC(dma8, "8-bit DMA # for " CRD_NAME " driver.");
 module_param_array(dma1, int, NULL, 0444);
-MODULE_PARM_DESC(dma1, "GF1 DMA # for GUS Extreme driver.");
+MODULE_PARM_DESC(dma1, "GF1 DMA # for " CRD_NAME " driver.");
 module_param_array(joystick_dac, int, NULL, 0444);
-MODULE_PARM_DESC(joystick_dac, "Joystick DAC level 0.59V-4.52V or 0.389V-2.98V for GUS Extreme driver.");
+MODULE_PARM_DESC(joystick_dac, "Joystick DAC level 0.59V-4.52V or 0.389V-2.98V for " CRD_NAME " driver.");
 module_param_array(channels, int, NULL, 0444);
-MODULE_PARM_DESC(channels, "GF1 channels for GUS Extreme driver.");
+MODULE_PARM_DESC(channels, "GF1 channels for " CRD_NAME " driver.");
 module_param_array(pcm_channels, int, NULL, 0444);
-MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for GUS Extreme driver.");
+MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for " CRD_NAME " driver.");
+
+static int __devinit snd_gusextreme_match(struct device *dev, unsigned int n)
+{
+	return enable[n];
+}
+
+static int __devinit snd_gusextreme_es1688_create(struct snd_card *card,
+		struct device *dev, unsigned int n, struct snd_es1688 **rchip)
+{
+	static long possible_ports[] = {0x220, 0x240, 0x260};
+	static int possible_irqs[] = {5, 9, 10, 7, -1};
+	static int possible_dmas[] = {1, 3, 0, -1};
+
+	int i, error;
+
+	if (irq[n] == SNDRV_AUTO_IRQ) {
+		irq[n] = snd_legacy_find_free_irq(possible_irqs);
+		if (irq[n] < 0) {
+			snd_printk(KERN_ERR "%s: unable to find a free IRQ "
+				"for ES1688\n", dev->bus_id);
+			return -EBUSY;
+		}
+	}
+	if (dma8[n] == SNDRV_AUTO_DMA) {
+		dma8[n] = snd_legacy_find_free_dma(possible_dmas);
+		if (dma8[n] < 0) {
+			snd_printk(KERN_ERR "%s: unable to find a free DMA "
+				"for ES1688\n", dev->bus_id);
+			return -EBUSY;
+		}
+	}
 
-static struct platform_device *devices[SNDRV_CARDS];
+	if (port[n] != SNDRV_AUTO_PORT)
+		return snd_es1688_create(card, port[n], mpu_port[n], irq[n],
+				mpu_irq[n], dma8[n], ES1688_HW_1688, rchip);
 
+	i = 0;
+	do {
+		port[n] = possible_ports[i];
+		error = snd_es1688_create(card, port[n], mpu_port[n], irq[n],
+				mpu_irq[n], dma8[n], ES1688_HW_1688, rchip);
+	} while (error < 0 && ++i < ARRAY_SIZE(possible_ports));
 
-#define PFX	"gusextreme: "
+	return error;
+}
 
-static int __devinit snd_gusextreme_detect(int dev,
-					struct snd_card *card,
-					struct snd_gus_card * gus,
-					struct snd_es1688 *es1688)
+static int __devinit snd_gusextreme_gus_card_create(struct snd_card *card,
+		struct device *dev, unsigned int n, struct snd_gus_card **rgus)
+{
+	static int possible_irqs[] = {11, 12, 15, 9, 5, 7, 3, -1};
+	static int possible_dmas[] = {5, 6, 7, 3, 1, -1};
+
+	if (gf1_irq[n] == SNDRV_AUTO_IRQ) {
+		gf1_irq[n] = snd_legacy_find_free_irq(possible_irqs);
+		if (gf1_irq[n] < 0) {
+			snd_printk(KERN_ERR "%s: unable to find a free IRQ "
+				"for GF1\n", dev->bus_id);
+			return -EBUSY;
+		}
+	}
+	if (dma1[n] == SNDRV_AUTO_DMA) {
+		dma1[n] = snd_legacy_find_free_dma(possible_dmas);
+		if (dma1[n] < 0) {
+			snd_printk(KERN_ERR "%s: unable to find a free DMA "
+				"for GF1\n", dev->bus_id);
+			return -EBUSY;
+		}
+	}
+	return snd_gus_create(card, gf1_port[n], gf1_irq[n], dma1[n], -1,
+			0, channels[n], pcm_channels[n], 0, rgus);
+}
+
+static int __devinit snd_gusextreme_detect(struct snd_gus_card *gus,
+	struct snd_es1688 *es1688)
 {
 	unsigned long flags;
 	unsigned char d;
@@ -117,12 +184,13 @@ static int __devinit snd_gusextreme_detect(int dev,
 	spin_lock_irqsave(&es1688->mixer_lock, flags);
 	snd_es1688_mixer_write(es1688, 0x40, 0x0b);	/* don't change!!! */
 	spin_unlock_irqrestore(&es1688->mixer_lock, flags);
+
 	spin_lock_irqsave(&es1688->reg_lock, flags);
-	outb(gf1_port[dev] & 0x040 ? 2 : 0, ES1688P(es1688, INIT1));
+	outb(gus->gf1.port & 0x040 ? 2 : 0, ES1688P(es1688, INIT1));
 	outb(0, 0x201);
-	outb(gf1_port[dev] & 0x020 ? 2 : 0, ES1688P(es1688, INIT1));
+	outb(gus->gf1.port & 0x020 ? 2 : 0, ES1688P(es1688, INIT1));
 	outb(0, 0x201);
-	outb(gf1_port[dev] & 0x010 ? 3 : 1, ES1688P(es1688, INIT1));
+	outb(gus->gf1.port & 0x010 ? 3 : 1, ES1688P(es1688, INIT1));
 	spin_unlock_irqrestore(&es1688->reg_lock, flags);
 
 	udelay(100);
@@ -139,253 +207,172 @@ static int __devinit snd_gusextreme_detect(int dev,
 		snd_printdd("[0x%lx] check 2 failed - 0x%x\n", gus->gf1.port, d);
 		return -EIO;
 	}
-	return 0;
-}
 
-static void __devinit snd_gusextreme_init(int dev, struct snd_gus_card * gus)
-{
-	gus->joystick_dac = joystick_dac[dev];
+	return 0;
 }
 
 static int __devinit snd_gusextreme_mixer(struct snd_es1688 *chip)
 {
 	struct snd_card *card = chip->card;
 	struct snd_ctl_elem_id id1, id2;
-	int err;
+	int error;
 
 	memset(&id1, 0, sizeof(id1));
 	memset(&id2, 0, sizeof(id2));
 	id1.iface = id2.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+
 	/* reassign AUX to SYNTHESIZER */
 	strcpy(id1.name, "Aux Playback Volume");
 	strcpy(id2.name, "Synth Playback Volume");
-	if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
-		return err;
+	error = snd_ctl_rename_id(card, &id1, &id2);
+	if (error < 0)
+		return error;
+
 	/* reassign Master Playback Switch to Synth Playback Switch */
 	strcpy(id1.name, "Master Playback Switch");
 	strcpy(id2.name, "Synth Playback Switch");
-	if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
-		return err;
+	error = snd_ctl_rename_id(card, &id1, &id2);
+	if (error < 0)
+		return error;
+
 	return 0;
 }
 
-static int __devinit snd_gusextreme_probe(struct platform_device *pdev)
+static int __devinit snd_gusextreme_probe(struct device *dev, unsigned int n)
 {
-	int dev = pdev->id;
-	static int possible_ess_irqs[] = {5, 9, 10, 7, -1};
-	static int possible_ess_dmas[] = {1, 3, 0, -1};
-	static int possible_gf1_irqs[] = {5, 11, 12, 9, 7, 15, 3, -1};
-	static int possible_gf1_dmas[] = {5, 6, 7, 1, 3, -1};
-	int xgf1_irq, xgf1_dma, xess_irq, xmpu_irq, xess_dma;
 	struct snd_card *card;
 	struct snd_gus_card *gus;
 	struct snd_es1688 *es1688;
 	struct snd_opl3 *opl3;
-	int err;
+	int error;
 
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-	if (card == NULL)
-		return -ENOMEM;
+	card = snd_card_new(index[n], id[n], THIS_MODULE, 0);
+	if (!card)
+		return -EINVAL;
 
-	xgf1_irq = gf1_irq[dev];
-	if (xgf1_irq == SNDRV_AUTO_IRQ) {
-		if ((xgf1_irq = snd_legacy_find_free_irq(possible_gf1_irqs)) < 0) {
-			snd_printk(KERN_ERR PFX "unable to find a free IRQ for GF1\n");
-			err = -EBUSY;
-			goto out;
-		}
-	}
-	xess_irq = irq[dev];
-	if (xess_irq == SNDRV_AUTO_IRQ) {
-		if ((xess_irq = snd_legacy_find_free_irq(possible_ess_irqs)) < 0) {
-			snd_printk(KERN_ERR PFX "unable to find a free IRQ for ES1688\n");
-			err = -EBUSY;
-			goto out;
-		}
-	}
-	if (mpu_port[dev] == SNDRV_AUTO_PORT)
-		mpu_port[dev] = 0;
-	xmpu_irq = mpu_irq[dev];
-	if (xmpu_irq > 15)
-		xmpu_irq = -1;
-	xgf1_dma = dma1[dev];
-	if (xgf1_dma == SNDRV_AUTO_DMA) {
-		if ((xgf1_dma = snd_legacy_find_free_dma(possible_gf1_dmas)) < 0) {
-			snd_printk(KERN_ERR PFX "unable to find a free DMA for GF1\n");
-			err = -EBUSY;
-			goto out;
-		}
-	}
-	xess_dma = dma8[dev];
-	if (xess_dma == SNDRV_AUTO_DMA) {
-		if ((xess_dma = snd_legacy_find_free_dma(possible_ess_dmas)) < 0) {
-			snd_printk(KERN_ERR PFX "unable to find a free DMA for ES1688\n");
-			err = -EBUSY;
-			goto out;
-		}
-	}
+	if (mpu_port[n] == SNDRV_AUTO_PORT)
+		mpu_port[n] = 0;
 
-	if (port[dev] != SNDRV_AUTO_PORT) {
-		err = snd_es1688_create(card, port[dev], mpu_port[dev],
-					xess_irq, xmpu_irq, xess_dma,
-					ES1688_HW_1688, &es1688);
-	} else {
-		/* auto-probe legacy ports */
-		static unsigned long possible_ports[] = {0x220, 0x240, 0x260};
-		int i;
-		for (i = 0; i < ARRAY_SIZE(possible_ports); i++) {
-			err = snd_es1688_create(card,
-						possible_ports[i],
-						mpu_port[dev],
-						xess_irq, xmpu_irq, xess_dma,
-						ES1688_HW_1688, &es1688);
-			if (err >= 0) {
-				port[dev] = possible_ports[i];
-				break;
-			}
-		}
-	}
-	if (err < 0)
+	if (mpu_irq[n] > 15)
+		mpu_irq[n] = -1;
+
+	error = snd_gusextreme_es1688_create(card, dev, n, &es1688);
+	if (error < 0)
 		goto out;
 
-	if (gf1_port[dev] < 0)
-		gf1_port[dev] = port[dev] + 0x20;
-	if ((err = snd_gus_create(card,
-				  gf1_port[dev],
-				  xgf1_irq,
-				  xgf1_dma,
-				  -1,
-				  0, channels[dev],
-				  pcm_channels[dev], 0,
-				  &gus)) < 0)
+	if (gf1_port[n] < 0)
+		gf1_port[n] = es1688->port + 0x20;
+
+	error = snd_gusextreme_gus_card_create(card, dev, n, &gus);
+	if (error < 0)
 		goto out;
 
-	if ((err = snd_gusextreme_detect(dev, card, gus, es1688)) < 0)
+	error = snd_gusextreme_detect(gus, es1688);
+	if (error < 0)
 		goto out;
 
-	snd_gusextreme_init(dev, gus);
-	if ((err = snd_gus_initialize(gus)) < 0)
+	gus->joystick_dac = joystick_dac[n];
+
+	error = snd_gus_initialize(gus);
+	if (error < 0)
 		goto out;
 
+	error = -ENODEV;
 	if (!gus->ess_flag) {
-		snd_printk(KERN_ERR PFX "GUS Extreme soundcard was not detected at 0x%lx\n", gus->gf1.port);
-		err = -ENODEV;
+		snd_printk(KERN_ERR "%s: GUS Extreme soundcard was not "
+			"detected at 0x%lx\n", dev->bus_id, gus->gf1.port);
 		goto out;
 	}
-	if ((err = snd_es1688_pcm(es1688, 0, NULL)) < 0)
+	gus->codec_flag = 1;
+
+	error = snd_es1688_pcm(es1688, 0, NULL);
+	if (error < 0)
 		goto out;
 
-	if ((err = snd_es1688_mixer(es1688)) < 0)
+	error = snd_es1688_mixer(es1688);
+	if (error < 0)
 		goto out;
 
 	snd_component_add(card, "ES1688");
-	if (pcm_channels[dev] > 0) {
-		if ((err = snd_gf1_pcm_new(gus, 1, 1, NULL)) < 0)
+
+	if (pcm_channels[n] > 0) {
+		error = snd_gf1_pcm_new(gus, 1, 1, NULL);
+		if (error < 0)
 			goto out;
 	}
-	if ((err = snd_gf1_new_mixer(gus)) < 0)
+
+	error = snd_gf1_new_mixer(gus);
+	if (error < 0)
 		goto out;
 
-	if ((err = snd_gusextreme_mixer(es1688)) < 0)
+	error = snd_gusextreme_mixer(es1688);
+	if (error < 0)
 		goto out;
 
 	if (snd_opl3_create(card, es1688->port, es1688->port + 2,
-			    OPL3_HW_OPL3, 0, &opl3) < 0) {
-		printk(KERN_ERR PFX "gusextreme: opl3 not detected at 0x%lx\n", es1688->port);
-	} else {
-		if ((err = snd_opl3_hwdep_new(opl3, 0, 2, NULL)) < 0)
+			OPL3_HW_OPL3, 0, &opl3) < 0)
+		printk(KERN_ERR "%s: opl3 not detected at 0x%lx\n",
+			dev->bus_id, es1688->port);
+	else {
+		error = snd_opl3_hwdep_new(opl3, 0, 2, NULL);
+		if (error < 0)
 			goto out;
 	}
 
-	if (es1688->mpu_port >= 0x300 &&
-	    (err = snd_mpu401_uart_new(card, 0, MPU401_HW_ES1688,
-					       es1688->mpu_port, 0,
-					       xmpu_irq,
-					       IRQF_DISABLED,
-					       NULL)) < 0)
-		goto out;
+	if (es1688->mpu_port >= 0x300) {
+		error = snd_mpu401_uart_new(card, 0, MPU401_HW_ES1688,
+				es1688->mpu_port, 0,
+				mpu_irq[n], IRQF_DISABLED, NULL);
+		if (error < 0)
+			goto out;
+	}
 
-	sprintf(card->longname, "Gravis UltraSound Extreme at 0x%lx, irq %i&%i, dma %i&%i",
-		es1688->port, xgf1_irq, xess_irq, xgf1_dma, xess_dma);
+	sprintf(card->longname, "Gravis UltraSound Extreme at 0x%lx, "
+		"irq %i&%i, dma %i&%i", es1688->port,
+		gus->gf1.irq, es1688->irq, gus->gf1.dma1, es1688->dma8);
 
-	snd_card_set_dev(card, &pdev->dev);
+	snd_card_set_dev(card, dev);
 
-	if ((err = snd_card_register(card)) < 0)
+	error = snd_card_register(card);
+	if (error < 0)
 		goto out;
 
-	platform_set_drvdata(pdev, card);
+	dev_set_drvdata(dev, card);
 	return 0;
 
-      out:
-	snd_card_free(card);
-	return err;
+out:	snd_card_free(card);
+	return error;
 }
 
-static int __devexit snd_gusextreme_remove(struct platform_device *devptr)
+static int __devexit snd_gusextreme_remove(struct device *dev, unsigned int n)
 {
-	snd_card_free(platform_get_drvdata(devptr));
-	platform_set_drvdata(devptr, NULL);
+	snd_card_free(dev_get_drvdata(dev));
+	dev_set_drvdata(dev, NULL);
 	return 0;
 }
 
-#define GUSEXTREME_DRIVER	"snd_gusextreme"
-
-static struct platform_driver snd_gusextreme_driver = {
+static struct isa_driver snd_gusextreme_driver = {
+	.match		= snd_gusextreme_match,
 	.probe		= snd_gusextreme_probe,
-	.remove		= __devexit_p(snd_gusextreme_remove),
-	/* FIXME: suspend/resume */
+	.remove		= snd_gusextreme_remove,
+#if 0	/* FIXME */
+	.suspend	= snd_gusextreme_suspend,
+	.resume		= snd_gusextreme_resume,
+#endif
 	.driver		= {
-		.name	= GUSEXTREME_DRIVER
-	},
+		.name	= DEV_NAME
+	}
 };
 
-static void __init_or_module snd_gusextreme_unregister_all(void)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(devices); ++i)
-		platform_device_unregister(devices[i]);
-	platform_driver_unregister(&snd_gusextreme_driver);
-}
-
 static int __init alsa_card_gusextreme_init(void)
 {
-	int i, cards, err;
-
-	err = platform_driver_register(&snd_gusextreme_driver);
-	if (err < 0)
-		return err;
-
-	cards = 0;
-	for (i = 0; i < SNDRV_CARDS; i++) {
-		struct platform_device *device;
-		if (! enable[i])
-			continue;
-		device = platform_device_register_simple(GUSEXTREME_DRIVER,
-							 i, NULL, 0);
-		if (IS_ERR(device))
-			continue;
-		if (!platform_get_drvdata(device)) {
-			platform_device_unregister(device);
-			continue;
-		}
-		devices[i] = device;
-		cards++;
-	}
-	if (!cards) {
-#ifdef MODULE
-		printk(KERN_ERR "GUS Extreme soundcard not found or device busy\n");
-#endif
-		snd_gusextreme_unregister_all();
-		return -ENODEV;
-	}
-	return 0;
+	return isa_register_driver(&snd_gusextreme_driver, SNDRV_CARDS);
 }
 
 static void __exit alsa_card_gusextreme_exit(void)
 {
-	snd_gusextreme_unregister_all();
+	isa_unregister_driver(&snd_gusextreme_driver);
 }
 
-module_init(alsa_card_gusextreme_init)
-module_exit(alsa_card_gusextreme_exit)
+module_init(alsa_card_gusextreme_init);
+module_exit(alsa_card_gusextreme_exit);
diff --git a/sound/isa/gus/gusmax.c b/sound/isa/gus/gusmax.c
index d1ad90ca035d..708783d4351f 100644
--- a/sound/isa/gus/gusmax.c
+++ b/sound/isa/gus/gusmax.c
@@ -22,7 +22,7 @@
 #include <sound/driver.h>
 #include <linux/init.h>
 #include <linux/err.h>
-#include <linux/platform_device.h>
+#include <linux/isa.h>
 #include <linux/delay.h>
 #include <linux/time.h>
 #include <linux/moduleparam.h>
@@ -72,8 +72,6 @@ MODULE_PARM_DESC(channels, "Used GF1 channels for GUS MAX driver.");
 module_param_array(pcm_channels, int, NULL, 0444);
 MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for GUS MAX driver.");
 
-static struct platform_device *devices[SNDRV_CARDS];
-
 struct snd_gusmax {
 	int irq;
 	struct snd_card *card;
@@ -205,9 +203,13 @@ static void snd_gusmax_free(struct snd_card *card)
 		free_irq(maxcard->irq, (void *)maxcard);
 }
 
-static int __devinit snd_gusmax_probe(struct platform_device *pdev)
+static int __devinit snd_gusmax_match(struct device *pdev, unsigned int dev)
+{
+	return enable[dev];
+}
+
+static int __devinit snd_gusmax_probe(struct device *pdev, unsigned int dev)
 {
-	int dev = pdev->id;
 	static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, -1};
 	static int possible_dmas[] = {5, 6, 7, 1, 3, -1};
 	int xirq, xdma1, xdma2, err;
@@ -333,7 +335,7 @@ static int __devinit snd_gusmax_probe(struct platform_device *pdev)
 	if (xdma2 >= 0)
 		sprintf(card->longname + strlen(card->longname), "&%i", xdma2);
 
-	snd_card_set_dev(card, &pdev->dev);
+	snd_card_set_dev(card, pdev);
 
 	if ((err = snd_card_register(card)) < 0)
 		goto _err;
@@ -341,7 +343,7 @@ static int __devinit snd_gusmax_probe(struct platform_device *pdev)
 	maxcard->gus = gus;
 	maxcard->cs4231 = cs4231;
 
-	platform_set_drvdata(pdev, card);
+	dev_set_drvdata(pdev, card);
 	return 0;
 
  _err:
@@ -349,70 +351,33 @@ static int __devinit snd_gusmax_probe(struct platform_device *pdev)
 	return err;
 }
 
-static int __devexit snd_gusmax_remove(struct platform_device *devptr)
+static int __devexit snd_gusmax_remove(struct device *devptr, unsigned int dev)
 {
-	snd_card_free(platform_get_drvdata(devptr));
-	platform_set_drvdata(devptr, NULL);
+	snd_card_free(dev_get_drvdata(devptr));
+	dev_set_drvdata(devptr, NULL);
 	return 0;
 }
 
-#define GUSMAX_DRIVER	"snd_gusmax"
+#define DEV_NAME "gusmax"
 
-static struct platform_driver snd_gusmax_driver = {
+static struct isa_driver snd_gusmax_driver = {
+	.match		= snd_gusmax_match,
 	.probe		= snd_gusmax_probe,
 	.remove		= __devexit_p(snd_gusmax_remove),
 	/* FIXME: suspend/resume */
 	.driver		= {
-		.name	= GUSMAX_DRIVER
+		.name	= DEV_NAME
 	},
 };
 
-static void __init_or_module snd_gusmax_unregister_all(void)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(devices); ++i)
-		platform_device_unregister(devices[i]);
-	platform_driver_unregister(&snd_gusmax_driver);
-}
-
 static int __init alsa_card_gusmax_init(void)
 {
-	int i, cards, err;
-
-	err = platform_driver_register(&snd_gusmax_driver);
-	if (err < 0)
-		return err;
-
-	cards = 0;
-	for (i = 0; i < SNDRV_CARDS; i++) {
-		struct platform_device *device;
-		if (! enable[i])
-			continue;
-		device = platform_device_register_simple(GUSMAX_DRIVER,
-							 i, NULL, 0);
-		if (IS_ERR(device))
-			continue;
-		if (!platform_get_drvdata(device)) {
-			platform_device_unregister(device);
-			continue;
-		}
-		devices[i] = device;
-		cards++;
-	}
-	if (!cards) {
-#ifdef MODULE
-		printk(KERN_ERR "GUS MAX soundcard not found or device busy\n");
-#endif
-		snd_gusmax_unregister_all();
-		return -ENODEV;
-	}
-	return 0;
+	return isa_register_driver(&snd_gusmax_driver, SNDRV_CARDS);
 }
 
 static void __exit alsa_card_gusmax_exit(void)
 {
-	snd_gusmax_unregister_all();
+	isa_unregister_driver(&snd_gusmax_driver);
 }
 
 module_init(alsa_card_gusmax_init)
diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c
index 4ec2d79431fc..3e4657255536 100644
--- a/sound/isa/gus/interwave.c
+++ b/sound/isa/gus/interwave.c
@@ -25,7 +25,7 @@
 #include <sound/driver.h>
 #include <linux/init.h>
 #include <linux/err.h>
-#include <linux/platform_device.h>
+#include <linux/isa.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/pnp.h>
@@ -115,9 +115,6 @@ MODULE_PARM_DESC(pcm_channels, "Reserved PCM channels for InterWave driver.");
 module_param_array(effect, int, NULL, 0444);
 MODULE_PARM_DESC(effect, "Effects enable for InterWave driver.");
 
-static struct platform_device *platform_devices[SNDRV_CARDS];
-static int pnp_registered;
-
 struct snd_interwave {
 	int irq;
 	struct snd_card *card;
@@ -138,6 +135,7 @@ struct snd_interwave {
 
 
 #ifdef CONFIG_PNP
+static int pnp_registered;
 
 static struct pnp_card_device_id snd_interwave_pnpids[] = {
 #ifndef SNDRV_STB
@@ -793,7 +791,7 @@ static int __devinit snd_interwave_probe(struct snd_card *card, int dev)
 	return 0;
 }
 
-static int __devinit snd_interwave_nonpnp_probe1(int dev, struct platform_device *devptr)
+static int __devinit snd_interwave_isa_probe1(int dev, struct device *devptr)
 {
 	struct snd_card *card;
 	int err;
@@ -802,18 +800,30 @@ static int __devinit snd_interwave_nonpnp_probe1(int dev, struct platform_device
 	if (! card)
 		return -ENOMEM;
 
-	snd_card_set_dev(card, &devptr->dev);
+	snd_card_set_dev(card, devptr);
 	if ((err = snd_interwave_probe(card, dev)) < 0) {
 		snd_card_free(card);
 		return err;
 	}
-	platform_set_drvdata(devptr, card);
+	dev_set_drvdata(devptr, card);
 	return 0;
 }
 
-static int __devinit snd_interwave_nonpnp_probe(struct platform_device *pdev)
+static int __devinit snd_interwave_isa_match(struct device *pdev,
+					     unsigned int dev)
+{
+	if (!enable[dev])
+		return 0;
+#ifdef CONFIG_PNP
+	if (isapnp[dev])
+		return 0;
+#endif
+	return 1;
+}
+
+static int __devinit snd_interwave_isa_probe(struct device *pdev,
+					     unsigned int dev)
 {
-	int dev = pdev->id;
 	int err;
 	static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, -1};
 	static int possible_dmas[] = {0, 1, 3, 5, 6, 7, -1};
@@ -838,13 +848,13 @@ static int __devinit snd_interwave_nonpnp_probe(struct platform_device *pdev)
 	}
 
 	if (port[dev] != SNDRV_AUTO_PORT)
-		return snd_interwave_nonpnp_probe1(dev, pdev);
+		return snd_interwave_isa_probe1(dev, pdev);
 	else {
 		static long possible_ports[] = {0x210, 0x220, 0x230, 0x240, 0x250, 0x260};
 		int i;
 		for (i = 0; i < ARRAY_SIZE(possible_ports); i++) {
 			port[dev] = possible_ports[i];
-			err = snd_interwave_nonpnp_probe1(dev, pdev);
+			err = snd_interwave_isa_probe1(dev, pdev);
 			if (! err)
 				return 0;
 		}
@@ -852,16 +862,17 @@ static int __devinit snd_interwave_nonpnp_probe(struct platform_device *pdev)
 	}
 }
 
-static int __devexit snd_interwave_nonpnp_remove(struct platform_device *devptr)
+static int __devexit snd_interwave_isa_remove(struct device *devptr, unsigned int dev)
 {
-	snd_card_free(platform_get_drvdata(devptr));
-	platform_set_drvdata(devptr, NULL);
+	snd_card_free(dev_get_drvdata(devptr));
+	dev_set_drvdata(devptr, NULL);
 	return 0;
 }
 
-static struct platform_driver snd_interwave_driver = {
-	.probe		= snd_interwave_nonpnp_probe,
-	.remove		= __devexit_p(snd_interwave_nonpnp_remove),
+static struct isa_driver snd_interwave_driver = {
+	.match		= snd_interwave_isa_match,
+	.probe		= snd_interwave_isa_probe,
+	.remove		= __devexit_p(snd_interwave_isa_remove),
 	/* FIXME: suspend,resume */
 	.driver		= {
 		.name	= INTERWAVE_DRIVER
@@ -869,8 +880,6 @@ static struct platform_driver snd_interwave_driver = {
 };
 
 #ifdef CONFIG_PNP
-static unsigned int __devinitdata interwave_pnp_devices;
-
 static int __devinit snd_interwave_pnp_detect(struct pnp_card_link *pcard,
 					      const struct pnp_card_device_id *pid)
 {
@@ -900,7 +909,6 @@ static int __devinit snd_interwave_pnp_detect(struct pnp_card_link *pcard,
 	}
 	pnp_set_card_drvdata(pcard, card);
 	dev++;
-	interwave_pnp_devices++;
 	return 0;
 }
 
@@ -921,64 +929,29 @@ static struct pnp_card_driver interwave_pnpc_driver = {
 
 #endif /* CONFIG_PNP */
 
-static void __init_or_module snd_interwave_unregister_all(void)
-{
-	int i;
-
-	if (pnp_registered)
-		pnp_unregister_card_driver(&interwave_pnpc_driver);
-	for (i = 0; i < ARRAY_SIZE(platform_devices); ++i)
-		platform_device_unregister(platform_devices[i]);
-	platform_driver_unregister(&snd_interwave_driver);
-}
-
 static int __init alsa_card_interwave_init(void)
 {
-	int i, err, cards = 0;
+	int err;
 
-	if ((err = platform_driver_register(&snd_interwave_driver)) < 0)
+	err = isa_register_driver(&snd_interwave_driver, SNDRV_CARDS);
+	if (err < 0)
 		return err;
-
-	for (i = 0; i < SNDRV_CARDS; i++) {
-		struct platform_device *device;
-		if (! enable[i])
-			continue;
 #ifdef CONFIG_PNP
-		if (isapnp[i])
-			continue;
-#endif
-		device = platform_device_register_simple(INTERWAVE_DRIVER,
-							 i, NULL, 0);
-		if (IS_ERR(device))
-			continue;
-		if (!platform_get_drvdata(device)) {
-			platform_device_unregister(device);
-			continue;
-		}
-		platform_devices[i] = device;
-		cards++;
-	}
-
 	/* ISA PnP cards */
 	err = pnp_register_card_driver(&interwave_pnpc_driver);
-	if (!err) {
+	if (!err)
 		pnp_registered = 1;
-		cards += interwave_pnp_devices;;
-	}
-
-	if (!cards) {
-#ifdef MODULE
-		printk(KERN_ERR "InterWave soundcard not found or device busy\n");
 #endif
-		snd_interwave_unregister_all();
-		return -ENODEV;
-	}
 	return 0;
 }
 
 static void __exit alsa_card_interwave_exit(void)
 {
-	snd_interwave_unregister_all();
+#ifdef CONFIG_PNP
+	if (pnp_registered)
+		pnp_unregister_card_driver(&interwave_pnpc_driver);
+#endif
+	isa_unregister_driver(&snd_interwave_driver);
 }
 
 module_init(alsa_card_interwave_init)
diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c
index f3db686b1c0c..48743eb85fb6 100644
--- a/sound/isa/opl3sa2.c
+++ b/sound/isa/opl3sa2.c
@@ -22,7 +22,7 @@
 #include <sound/driver.h>
 #include <linux/init.h>
 #include <linux/err.h>
-#include <linux/platform_device.h>
+#include <linux/isa.h>
 #include <linux/interrupt.h>
 #include <linux/pm.h>
 #include <linux/slab.h>
@@ -91,12 +91,10 @@ MODULE_PARM_DESC(dma2, "DMA2 # for OPL3-SA driver.");
 module_param_array(opl3sa3_ymode, int, NULL, 0444);
 MODULE_PARM_DESC(opl3sa3_ymode, "Speaker size selection for 3D Enhancement mode: Desktop/Large Notebook/Small Notebook/HiFi.");
 
-static struct platform_device *platform_devices[SNDRV_CARDS];
 #ifdef CONFIG_PNP
 static int pnp_registered;
 static int pnpc_registered;
 #endif
-static unsigned int snd_opl3sa2_devices;
 
 /* control ports */
 #define OPL3SA2_PM_CTRL		0x01
@@ -783,7 +781,6 @@ static int __devinit snd_opl3sa2_pnp_detect(struct pnp_dev *pdev,
 	}
 	pnp_set_drvdata(pdev, card);
 	dev++;
-	snd_opl3sa2_devices++;
 	return 0;
 }
 
@@ -850,7 +847,6 @@ static int __devinit snd_opl3sa2_pnp_cdetect(struct pnp_card_link *pcard,
 	}
 	pnp_set_card_drvdata(pcard, card);
 	dev++;
-	snd_opl3sa2_devices++;
 	return 0;
 }
 
@@ -884,116 +880,95 @@ static struct pnp_card_driver opl3sa2_pnpc_driver = {
 };
 #endif /* CONFIG_PNP */
 
-static int __devinit snd_opl3sa2_nonpnp_probe(struct platform_device *pdev)
+static int __devinit snd_opl3sa2_isa_match(struct device *pdev,
+					   unsigned int dev)
 {
-	struct snd_card *card;
-	int err;
-	int dev = pdev->id;
-
+	if (!enable[dev])
+		return 0;
+#ifdef CONFIG_PNP
+	if (isapnp[dev])
+		return 0;
+#endif
 	if (port[dev] == SNDRV_AUTO_PORT) {
 		snd_printk(KERN_ERR PFX "specify port\n");
-		return -EINVAL;
+		return 0;
 	}
 	if (wss_port[dev] == SNDRV_AUTO_PORT) {
 		snd_printk(KERN_ERR PFX "specify wss_port\n");
-		return -EINVAL;
+		return 0;
 	}
 	if (fm_port[dev] == SNDRV_AUTO_PORT) {
 		snd_printk(KERN_ERR PFX "specify fm_port\n");
-		return -EINVAL;
+		return 0;
 	}
 	if (midi_port[dev] == SNDRV_AUTO_PORT) {
 		snd_printk(KERN_ERR PFX "specify midi_port\n");
-		return -EINVAL;
+		return 0;
 	}
+	return 1;
+}
+
+static int __devinit snd_opl3sa2_isa_probe(struct device *pdev,
+					   unsigned int dev)
+{
+	struct snd_card *card;
+	int err;
 
 	card = snd_opl3sa2_card_new(dev);
 	if (! card)
 		return -ENOMEM;
-	snd_card_set_dev(card, &pdev->dev);
+	snd_card_set_dev(card, pdev);
 	if ((err = snd_opl3sa2_probe(card, dev)) < 0) {
 		snd_card_free(card);
 		return err;
 	}
-	platform_set_drvdata(pdev, card);
+	dev_set_drvdata(pdev, card);
 	return 0;
 }
 
-static int __devexit snd_opl3sa2_nonpnp_remove(struct platform_device *devptr)
+static int __devexit snd_opl3sa2_isa_remove(struct device *devptr,
+					    unsigned int dev)
 {
-	snd_card_free(platform_get_drvdata(devptr));
-	platform_set_drvdata(devptr, NULL);
+	snd_card_free(dev_get_drvdata(devptr));
+	dev_set_drvdata(devptr, NULL);
 	return 0;
 }
 
 #ifdef CONFIG_PM
-static int snd_opl3sa2_nonpnp_suspend(struct platform_device *dev, pm_message_t state)
+static int snd_opl3sa2_isa_suspend(struct device *dev, unsigned int n,
+				   pm_message_t state)
 {
-	return snd_opl3sa2_suspend(platform_get_drvdata(dev), state);
+	return snd_opl3sa2_suspend(dev_get_drvdata(dev), state);
 }
 
-static int snd_opl3sa2_nonpnp_resume(struct platform_device *dev)
+static int snd_opl3sa2_isa_resume(struct device *dev, unsigned int n)
 {
-	return snd_opl3sa2_resume(platform_get_drvdata(dev));
+	return snd_opl3sa2_resume(dev_get_drvdata(dev));
 }
 #endif
 
-#define OPL3SA2_DRIVER	"snd_opl3sa2"
+#define DEV_NAME "opl3sa2"
 
-static struct platform_driver snd_opl3sa2_nonpnp_driver = {
-	.probe		= snd_opl3sa2_nonpnp_probe,
-	.remove		= __devexit( snd_opl3sa2_nonpnp_remove),
+static struct isa_driver snd_opl3sa2_isa_driver = {
+	.match		= snd_opl3sa2_isa_match,
+	.probe		= snd_opl3sa2_isa_probe,
+	.remove		= __devexit( snd_opl3sa2_isa_remove),
 #ifdef CONFIG_PM
-	.suspend	= snd_opl3sa2_nonpnp_suspend,
-	.resume		= snd_opl3sa2_nonpnp_resume,
+	.suspend	= snd_opl3sa2_isa_suspend,
+	.resume		= snd_opl3sa2_isa_resume,
 #endif
 	.driver		= {
-		.name	= OPL3SA2_DRIVER
+		.name	= DEV_NAME
 	},
 };
 
-static void __init_or_module snd_opl3sa2_unregister_all(void)
-{
-	int i;
-
-#ifdef CONFIG_PNP
-	if (pnpc_registered)
-		pnp_unregister_card_driver(&opl3sa2_pnpc_driver);
-	if (pnp_registered)
-		pnp_unregister_driver(&opl3sa2_pnp_driver);
-#endif
-	for (i = 0; i < ARRAY_SIZE(platform_devices); ++i)
-		platform_device_unregister(platform_devices[i]);
-	platform_driver_unregister(&snd_opl3sa2_nonpnp_driver);
-}
-
 static int __init alsa_card_opl3sa2_init(void)
 {
-	int i, err;
+	int err;
 
-	if ((err = platform_driver_register(&snd_opl3sa2_nonpnp_driver)) < 0)
+	err = isa_register_driver(&snd_opl3sa2_isa_driver, SNDRV_CARDS);
+	if (err < 0)
 		return err;
-
-	for (i = 0; i < SNDRV_CARDS; i++) {
-		struct platform_device *device;
-		if (! enable[i])
-			continue;
-#ifdef CONFIG_PNP
-		if (isapnp[i])
-			continue;
-#endif
-		device = platform_device_register_simple(OPL3SA2_DRIVER,
-							 i, NULL, 0);
-		if (IS_ERR(device))
-			continue;
-		if (!platform_get_drvdata(device)) {
-			platform_device_unregister(device);
-			continue;
-		}
-		platform_devices[i] = device;
-		snd_opl3sa2_devices++;
-	}
-
 #ifdef CONFIG_PNP
 	err = pnp_register_driver(&opl3sa2_pnp_driver);
 	if (!err)
@@ -1002,20 +977,18 @@ static int __init alsa_card_opl3sa2_init(void)
 	if (!err)
 		pnpc_registered = 1;
 #endif
-
-	if (!snd_opl3sa2_devices) {
-#ifdef MODULE
-		snd_printk(KERN_ERR "Yamaha OPL3-SA soundcard not found or device busy\n");
-#endif
-		snd_opl3sa2_unregister_all();
-		return -ENODEV;
-	}
 	return 0;
 }
 
 static void __exit alsa_card_opl3sa2_exit(void)
 {
-	snd_opl3sa2_unregister_all();
+#ifdef CONFIG_PNP
+	if (pnpc_registered)
+		pnp_unregister_card_driver(&opl3sa2_pnpc_driver);
+	if (pnp_registered)
+		pnp_unregister_driver(&opl3sa2_pnp_driver);
+#endif
+	isa_unregister_driver(&snd_opl3sa2_isa_driver);
 }
 
 module_init(alsa_card_opl3sa2_init)
diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c
index 1dd98375ac85..cd29b30b362e 100644
--- a/sound/isa/opti9xx/miro.c
+++ b/sound/isa/opti9xx/miro.c
@@ -25,7 +25,7 @@
 #include <sound/driver.h>
 #include <linux/init.h>
 #include <linux/err.h>
-#include <linux/platform_device.h>
+#include <linux/isa.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/ioport.h>
@@ -137,10 +137,6 @@ struct snd_miro {
 
 static void snd_miro_proc_init(struct snd_miro * miro);
 
-#define DRIVER_NAME "snd-miro"
-
-static struct platform_device *device;
-
 static char * snd_opti9xx_names[] = {
 	"unkown",
 	"82C928", "82C929",
@@ -558,7 +554,7 @@ static int snd_miro_put_double(struct snd_kcontrol *kcontrol,
 	return change;
 }
 
-static struct snd_kcontrol_new snd_miro_controls[] = {
+static struct snd_kcontrol_new snd_miro_controls[] __devinitdata = {
 MIRO_DOUBLE("Master Playback Volume", 0, ACI_GET_MASTER, ACI_SET_MASTER),
 MIRO_DOUBLE("Mic Playback Volume", 1, ACI_GET_MIC, ACI_SET_MIC),
 MIRO_DOUBLE("Line Playback Volume", 1, ACI_GET_LINE, ACI_SET_LINE),
@@ -570,7 +566,7 @@ MIRO_DOUBLE("Aux Playback Volume", 2, ACI_GET_LINE2, ACI_SET_LINE2),
 
 /* Equalizer with seven bands (only PCM20) 
    from -12dB up to +12dB on each band */
-static struct snd_kcontrol_new snd_miro_eq_controls[] = {
+static struct snd_kcontrol_new snd_miro_eq_controls[] __devinitdata = {
 MIRO_DOUBLE("Tone Control - 28 Hz", 0, ACI_GET_EQ1, ACI_SET_EQ1),
 MIRO_DOUBLE("Tone Control - 160 Hz", 0, ACI_GET_EQ2, ACI_SET_EQ2),
 MIRO_DOUBLE("Tone Control - 400 Hz", 0, ACI_GET_EQ3, ACI_SET_EQ3),
@@ -580,15 +576,15 @@ MIRO_DOUBLE("Tone Control - 6.3 kHz", 0, ACI_GET_EQ6, ACI_SET_EQ6),
 MIRO_DOUBLE("Tone Control - 16 kHz", 0, ACI_GET_EQ7, ACI_SET_EQ7),
 };
 
-static struct snd_kcontrol_new snd_miro_radio_control[] = {
+static struct snd_kcontrol_new snd_miro_radio_control[] __devinitdata = {
 MIRO_DOUBLE("Radio Playback Volume", 0, ACI_GET_LINE1, ACI_SET_LINE1),
 };
 
-static struct snd_kcontrol_new snd_miro_line_control[] = {
+static struct snd_kcontrol_new snd_miro_line_control[] __devinitdata = {
 MIRO_DOUBLE("Line Playback Volume", 2, ACI_GET_LINE1, ACI_SET_LINE1),
 };
 
-static struct snd_kcontrol_new snd_miro_preamp_control[] = {
+static struct snd_kcontrol_new snd_miro_preamp_control[] __devinitdata = {
 {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = "Mic Boost",
@@ -598,7 +594,7 @@ static struct snd_kcontrol_new snd_miro_preamp_control[] = {
 	.put = snd_miro_put_preamp,
 }};
 
-static struct snd_kcontrol_new snd_miro_amp_control[] = {
+static struct snd_kcontrol_new snd_miro_amp_control[] __devinitdata = {
 {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = "Line Boost",
@@ -608,7 +604,7 @@ static struct snd_kcontrol_new snd_miro_amp_control[] = {
 	.put = snd_miro_put_amp,
 }};
 
-static struct snd_kcontrol_new snd_miro_capture_control[] = {
+static struct snd_kcontrol_new snd_miro_capture_control[] __devinitdata = {
 {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = "PCM Capture Switch",
@@ -618,7 +614,7 @@ static struct snd_kcontrol_new snd_miro_capture_control[] = {
 	.put = snd_miro_put_capture,
 }};
 
-static unsigned char aci_init_values[][2] __initdata = {
+static unsigned char aci_init_values[][2] __devinitdata = {
 	{ ACI_SET_MUTE, 0x00 },
 	{ ACI_SET_POWERAMP, 0x00 },
 	{ ACI_SET_PREAMP, 0x00 },
@@ -641,7 +637,7 @@ static unsigned char aci_init_values[][2] __initdata = {
 	{ ACI_SET_MASTER + 1, 0x20 },
 };
 
-static int __init snd_set_aci_init_values(struct snd_miro *miro)
+static int __devinit snd_set_aci_init_values(struct snd_miro *miro)
 {
 	int idx, error;
 
@@ -751,7 +747,8 @@ static long snd_legacy_find_free_ioport(long *port_table, long size)
 	return -1;
 }
 
-static int __init snd_miro_init(struct snd_miro *chip, unsigned short hardware)
+static int __devinit snd_miro_init(struct snd_miro *chip,
+				   unsigned short hardware)
 {
 	static int opti9xx_mc_size[] = {7, 7, 10, 10, 2, 2, 2};
 
@@ -962,7 +959,7 @@ static void snd_miro_proc_read(struct snd_info_entry * entry,
 	snd_iprintf(buffer, "  preamp  : 0x%x\n", miro->aci_preamp);
 }
 
-static void __init snd_miro_proc_init(struct snd_miro * miro)
+static void __devinit snd_miro_proc_init(struct snd_miro * miro)
 {
 	struct snd_info_entry *entry;
 
@@ -974,7 +971,7 @@ static void __init snd_miro_proc_init(struct snd_miro * miro)
  *  Init
  */
 
-static int __init snd_miro_configure(struct snd_miro *chip)
+static int __devinit snd_miro_configure(struct snd_miro *chip)
 {
 	unsigned char wss_base_bits;
 	unsigned char irq_bits;
@@ -1131,7 +1128,8 @@ __skip_mpu:
 	return 0;
 }
 
-static int __init snd_card_miro_detect(struct snd_card *card, struct snd_miro *chip)
+static int __devinit snd_card_miro_detect(struct snd_card *card,
+					  struct snd_miro *chip)
 {
 	int i, err;
 	unsigned char value;
@@ -1157,7 +1155,8 @@ static int __init snd_card_miro_detect(struct snd_card *card, struct snd_miro *c
 	return -ENODEV;
 }
 
-static int __init snd_card_miro_aci_detect(struct snd_card *card, struct snd_miro * miro)
+static int __devinit snd_card_miro_aci_detect(struct snd_card *card,
+					      struct snd_miro * miro)
 {
 	unsigned char regval;
 	int i;
@@ -1213,7 +1212,12 @@ static void snd_card_miro_free(struct snd_card *card)
 	release_and_free_resource(miro->res_mc_base);
 }
 
-static int __init snd_miro_probe(struct platform_device *devptr)
+static int __devinit snd_miro_match(struct device *devptr, unsigned int n)
+{
+	return 1;
+}
+
+static int __devinit snd_miro_probe(struct device *devptr, unsigned int n)
 {
 	static long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1};
 	static long possible_mpu_ports[] = {0x330, 0x300, 0x310, 0x320, -1};
@@ -1399,56 +1403,44 @@ static int __init snd_miro_probe(struct platform_device *devptr)
                 return error;
 	}
 
-	snd_card_set_dev(card, &devptr->dev);
+	snd_card_set_dev(card, devptr);
 
 	if ((error = snd_card_register(card))) {
 		snd_card_free(card);
 		return error;
 	}
 
-	platform_set_drvdata(devptr, card);
+	dev_set_drvdata(devptr, card);
 	return 0;
 }
 
-static int __devexit snd_miro_remove(struct platform_device *devptr)
+static int __devexit snd_miro_remove(struct device *devptr, unsigned int dev)
 {
-	snd_card_free(platform_get_drvdata(devptr));
-	platform_set_drvdata(devptr, NULL);
+	snd_card_free(dev_get_drvdata(devptr));
+	dev_set_drvdata(devptr, NULL);
 	return 0;
 }
 
-static struct platform_driver snd_miro_driver = {
+#define DEV_NAME "miro"
+
+static struct isa_driver snd_miro_driver = {
+	.match		= snd_miro_match,
 	.probe		= snd_miro_probe,
 	.remove		= __devexit_p(snd_miro_remove),
 	/* FIXME: suspend/resume */
 	.driver		= {
-		.name	= DRIVER_NAME
+		.name	= DEV_NAME
 	},
 };
 
 static int __init alsa_card_miro_init(void)
 {
-	int error;
-
-	if ((error = platform_driver_register(&snd_miro_driver)) < 0)
-		return error;
-	device = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0);
-	if (! IS_ERR(device)) {
-		if (platform_get_drvdata(device))
-			return 0;
-		platform_device_unregister(device);
-	}
-#ifdef MODULE
-	printk(KERN_ERR "no miro soundcard found\n");
-#endif
-	platform_driver_unregister(&snd_miro_driver);
-	return PTR_ERR(device);
+	return isa_register_driver(&snd_miro_driver, 1);
 }
 
 static void __exit alsa_card_miro_exit(void)
 {
-	platform_device_unregister(device);
-	platform_driver_unregister(&snd_miro_driver);
+	isa_unregister_driver(&snd_miro_driver);
 }
 
 module_init(alsa_card_miro_init)
diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c
index df227377c333..60c120ffb9de 100644
--- a/sound/isa/opti9xx/opti92x-ad1848.c
+++ b/sound/isa/opti9xx/opti92x-ad1848.c
@@ -26,7 +26,7 @@
 #include <sound/driver.h>
 #include <linux/init.h>
 #include <linux/err.h>
-#include <linux/platform_device.h>
+#include <linux/isa.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/pnp.h>
@@ -259,7 +259,6 @@ struct snd_opti9xx {
 };
 
 static int snd_opti9xx_pnp_is_probed;
-static struct platform_device *snd_opti9xx_platform_device;
 
 #ifdef CONFIG_PNP
 
@@ -281,10 +280,10 @@ MODULE_DEVICE_TABLE(pnp_card, snd_opti9xx_pnpids);
 #endif	/* CONFIG_PNP */
 
 #ifdef OPTi93X
-#define DRIVER_NAME	"snd-card-opti93x"
+#define DEV_NAME "opti93x"
 #else
-#define DRIVER_NAME	"snd-card-opti92x"
-#endif	/* OPTi93X */
+#define DEV_NAME "opti92x"
+#endif
 
 static char * snd_opti9xx_names[] = {
 	"unkown",
@@ -294,7 +293,7 @@ static char * snd_opti9xx_names[] = {
 };
 
 
-static long __init snd_legacy_find_free_ioport(long *port_table, long size)
+static long __devinit snd_legacy_find_free_ioport(long *port_table, long size)
 {
 	while (*port_table != -1) {
 		if (request_region(*port_table, size, "ALSA test")) {
@@ -306,7 +305,8 @@ static long __init snd_legacy_find_free_ioport(long *port_table, long size)
 	return -1;
 }
 
-static int __init snd_opti9xx_init(struct snd_opti9xx *chip, unsigned short hardware)
+static int __devinit snd_opti9xx_init(struct snd_opti9xx *chip,
+				      unsigned short hardware)
 {
 	static int opti9xx_mc_size[] = {7, 7, 10, 10, 2, 2, 2};
 
@@ -451,7 +451,7 @@ static void snd_opti9xx_write(struct snd_opti9xx *chip, unsigned char reg,
 		(snd_opti9xx_read(chip, reg) & ~(mask)) | ((value) & (mask)))
 
 
-static int __init snd_opti9xx_configure(struct snd_opti9xx *chip)
+static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip)
 {
 	unsigned char wss_base_bits;
 	unsigned char irq_bits;
@@ -934,10 +934,8 @@ static int snd_opti93x_trigger(struct snd_pcm_substream *substream,
 	case SNDRV_PCM_TRIGGER_STOP:
 	{
 		unsigned int what = 0;
-		struct list_head *pos;
 		struct snd_pcm_substream *s;
-		snd_pcm_group_for_each(pos, substream) {
-			s = snd_pcm_group_substream_entry(pos);
+		snd_pcm_group_for_each_entry(s, substream) {
 			if (s == chip->playback_substream) {
 				what |= OPTi93X_PLAYBACK_ENABLE;
 				snd_pcm_trigger_done(s, substream);
@@ -1291,7 +1289,7 @@ static int snd_opti93x_create(struct snd_card *card, struct snd_opti9xx *chip,
 	}
 	codec->dma2 = chip->dma2;
 
-	if (request_irq(chip->irq, snd_opti93x_interrupt, IRQF_DISABLED, DRIVER_NAME" - WSS", codec)) {
+	if (request_irq(chip->irq, snd_opti93x_interrupt, IRQF_DISABLED, DEV_NAME" - WSS", codec)) {
 		snd_printk(KERN_ERR "opti9xx: can't grab IRQ %d\n", chip->irq);
 		snd_opti93x_free(codec);
 		return -EBUSY;
@@ -1561,7 +1559,7 @@ static int snd_opti93x_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_
 	return change;
 }
 
-static struct snd_kcontrol_new snd_opti93x_controls[] = {
+static struct snd_kcontrol_new snd_opti93x_controls[] __devinitdata = {
 OPTi93X_DOUBLE("Master Playback Switch", 0, OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 7, 7, 1, 1),
 OPTi93X_DOUBLE("Master Playback Volume", 0, OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 1, 1, 31, 1), 
 OPTi93X_DOUBLE("PCM Playback Switch", 0, OPTi93X_DAC_LEFT, OPTi93X_DAC_RIGHT, 7, 7, 1, 1),
@@ -1622,7 +1620,8 @@ static int snd_opti93x_mixer(struct snd_opti93x *chip)
 
 #endif /* OPTi93X */
 
-static int __init snd_card_opti9xx_detect(struct snd_card *card, struct snd_opti9xx *chip)
+static int __devinit snd_card_opti9xx_detect(struct snd_card *card,
+					     struct snd_opti9xx *chip)
 {
 	int i, err;
 
@@ -1676,8 +1675,9 @@ static int __init snd_card_opti9xx_detect(struct snd_card *card, struct snd_opti
 }
 
 #ifdef CONFIG_PNP
-static int __init snd_card_opti9xx_pnp(struct snd_opti9xx *chip, struct pnp_card_link *card,
-				       const struct pnp_card_device_id *pid)
+static int __devinit snd_card_opti9xx_pnp(struct snd_opti9xx *chip,
+					  struct pnp_card_link *card,
+					  const struct pnp_card_device_id *pid)
 {
 	struct pnp_dev *pdev;
 	struct pnp_resource_table *cfg = kmalloc(sizeof(*cfg), GFP_KERNEL);
@@ -1778,7 +1778,7 @@ static void snd_card_opti9xx_free(struct snd_card *card)
 		release_and_free_resource(chip->res_mc_base);
 }
 
-static int __init snd_opti9xx_probe(struct snd_card *card)
+static int __devinit snd_opti9xx_probe(struct snd_card *card)
 {
 	static long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1};
 	int error;
@@ -1924,7 +1924,18 @@ static struct snd_card *snd_opti9xx_card_new(void)
 	return card;
 }
 
-static int __init snd_opti9xx_nonpnp_probe(struct platform_device *devptr)
+static int __devinit snd_opti9xx_isa_match(struct device *devptr,
+					   unsigned int dev)
+{
+	if (snd_opti9xx_pnp_is_probed)
+		return 0;
+	if (isapnp)
+		return 0;
+	return 1;
+}
+
+static int __devinit snd_opti9xx_isa_probe(struct device *devptr,
+					   unsigned int dev)
 {
 	struct snd_card *card;
 	int error;
@@ -1940,9 +1951,6 @@ static int __init snd_opti9xx_nonpnp_probe(struct platform_device *devptr)
 	static int possible_dma2s[][2] = {{1,-1}, {0,-1}, {-1,-1}, {0,-1}};
 #endif	/* CS4231 || OPTi93X */
 
-	if (snd_opti9xx_pnp_is_probed)
-		return -EBUSY;
-
 	if (mpu_port == SNDRV_AUTO_PORT) {
 		if ((mpu_port = snd_legacy_find_free_ioport(possible_mpu_ports, 2)) < 0) {
 			snd_printk(KERN_ERR "unable to find a free MPU401 port\n");
@@ -1984,34 +1992,36 @@ static int __init snd_opti9xx_nonpnp_probe(struct platform_device *devptr)
 		snd_card_free(card);
 		return error;
 	}
-	snd_card_set_dev(card, &devptr->dev);
+	snd_card_set_dev(card, devptr);
 	if ((error = snd_opti9xx_probe(card)) < 0) {
 		snd_card_free(card);
 		return error;
 	}
-	platform_set_drvdata(devptr, card);
+	dev_set_drvdata(devptr, card);
 	return 0;
 }
 
-static int __devexit snd_opti9xx_nonpnp_remove(struct platform_device *devptr)
+static int __devexit snd_opti9xx_isa_remove(struct device *devptr,
+					    unsigned int dev)
 {
-	snd_card_free(platform_get_drvdata(devptr));
-	platform_set_drvdata(devptr, NULL);
+	snd_card_free(dev_get_drvdata(devptr));
+	dev_set_drvdata(devptr, NULL);
 	return 0;
 }
 
-static struct platform_driver snd_opti9xx_driver = {
-	.probe		= snd_opti9xx_nonpnp_probe,
-	.remove		= __devexit_p(snd_opti9xx_nonpnp_remove),
+static struct isa_driver snd_opti9xx_driver = {
+	.match		= snd_opti9xx_isa_match,
+	.probe		= snd_opti9xx_isa_probe,
+	.remove		= __devexit_p(snd_opti9xx_isa_remove),
 	/* FIXME: suspend/resume */
 	.driver		= {
-		.name	= DRIVER_NAME
+		.name	= DEV_NAME
 	},
 };
 
 #ifdef CONFIG_PNP
-static int __init snd_opti9xx_pnp_probe(struct pnp_card_link *pcard,
-					const struct pnp_card_device_id *pid)
+static int __devinit snd_opti9xx_pnp_probe(struct pnp_card_link *pcard,
+					   const struct pnp_card_device_id *pid)
 {
 	struct snd_card *card;
 	int error, hw;
@@ -2074,11 +2084,6 @@ static struct pnp_card_driver opti9xx_pnpc_driver = {
 };
 #endif
 
-#ifdef CONFIG_PNP
-#define is_isapnp_selected()	isapnp
-#else
-#define is_isapnp_selected()	0
-#endif
 #ifdef OPTi93X
 #define CHIP_NAME	"82C93x"
 #else
@@ -2087,42 +2092,19 @@ static struct pnp_card_driver opti9xx_pnpc_driver = {
 
 static int __init alsa_card_opti9xx_init(void)
 {
-	int error;
-	struct platform_device *device;
-
 #ifdef CONFIG_PNP
 	pnp_register_card_driver(&opti9xx_pnpc_driver);
 	if (snd_opti9xx_pnp_is_probed)
 		return 0;
 #endif
-	if (! is_isapnp_selected()) {
-		error = platform_driver_register(&snd_opti9xx_driver);
-		if (error < 0)
-			return error;
-		device = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0);
-		if (!IS_ERR(device)) {
-			if (platform_get_drvdata(device)) {
-				snd_opti9xx_platform_device = device;
-				return 0;
-			}
-			platform_device_unregister(device);
-		}
-		platform_driver_unregister(&snd_opti9xx_driver);
-	}
-#ifdef CONFIG_PNP
-	pnp_unregister_card_driver(&opti9xx_pnpc_driver);
-#endif
-#ifdef MODULE
-	printk(KERN_ERR "no OPTi " CHIP_NAME " soundcard found\n");
-#endif
-	return -ENODEV;
+	return isa_register_driver(&snd_opti9xx_driver, 1);
 }
 
 static void __exit alsa_card_opti9xx_exit(void)
 {
 	if (!snd_opti9xx_pnp_is_probed) {
-		platform_device_unregister(snd_opti9xx_platform_device);
-		platform_driver_unregister(&snd_opti9xx_driver);
+		isa_unregister_driver(&snd_opti9xx_driver);
+		return;
 	}
 #ifdef CONFIG_PNP
 	pnp_unregister_card_driver(&opti9xx_pnpc_driver);
diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c
index d64e67f2bafa..2a19b0a39eda 100644
--- a/sound/isa/sb/sb16.c
+++ b/sound/isa/sb/sb16.c
@@ -25,7 +25,7 @@
 #include <linux/slab.h>
 #include <linux/pnp.h>
 #include <linux/err.h>
-#include <linux/platform_device.h>
+#include <linux/isa.h>
 #include <linux/moduleparam.h>
 #include <sound/core.h>
 #include <sound/sb.h>
@@ -128,7 +128,6 @@ module_param_array(seq_ports, int, NULL, 0444);
 MODULE_PARM_DESC(seq_ports, "Number of sequencer ports for WaveTable synth.");
 #endif
 
-static struct platform_device *platform_devices[SNDRV_CARDS];
 #ifdef CONFIG_PNP
 static int pnp_registered;
 #endif
@@ -519,7 +518,7 @@ static int snd_sb16_resume(struct snd_card *card)
 }
 #endif
 
-static int __devinit snd_sb16_nonpnp_probe1(int dev, struct platform_device *devptr)
+static int __devinit snd_sb16_isa_probe1(int dev, struct device *pdev)
 {
 	struct snd_card_sb16 *acard;
 	struct snd_card *card;
@@ -539,19 +538,23 @@ static int __devinit snd_sb16_nonpnp_probe1(int dev, struct platform_device *dev
 	awe_port[dev] = port[dev] + 0x400;
 #endif
 
-	snd_card_set_dev(card, &devptr->dev);
+	snd_card_set_dev(card, pdev);
 	if ((err = snd_sb16_probe(card, dev)) < 0) {
 		snd_card_free(card);
 		return err;
 	}
-	platform_set_drvdata(devptr, card);
+	dev_set_drvdata(pdev, card);
 	return 0;
 }
 
 
-static int __devinit snd_sb16_nonpnp_probe(struct platform_device *pdev)
+static int __devinit snd_sb16_isa_match(struct device *pdev, unsigned int dev)
+{
+	return enable[dev] && !is_isapnp_selected(dev);
+}
+
+static int __devinit snd_sb16_isa_probe(struct device *pdev, unsigned int dev)
 {
-	int dev = pdev->id;
 	int err;
 	static int possible_irqs[] = {5, 9, 10, 7, -1};
 	static int possible_dmas8[] = {1, 3, 0, -1};
@@ -577,13 +580,13 @@ static int __devinit snd_sb16_nonpnp_probe(struct platform_device *pdev)
 	}
 
 	if (port[dev] != SNDRV_AUTO_PORT)
-		return snd_sb16_nonpnp_probe1(dev, pdev);
+		return snd_sb16_isa_probe1(dev, pdev);
 	else {
 		static int possible_ports[] = {0x220, 0x240, 0x260, 0x280};
 		int i;
 		for (i = 0; i < ARRAY_SIZE(possible_ports); i++) {
 			port[dev] = possible_ports[i];
-			err = snd_sb16_nonpnp_probe1(dev, pdev);
+			err = snd_sb16_isa_probe1(dev, pdev);
 			if (! err)
 				return 0;
 		}
@@ -591,47 +594,47 @@ static int __devinit snd_sb16_nonpnp_probe(struct platform_device *pdev)
 	}
 }
 
-static int __devexit snd_sb16_nonpnp_remove(struct platform_device *devptr)
+static int __devexit snd_sb16_isa_remove(struct device *pdev, unsigned int dev)
 {
-	snd_card_free(platform_get_drvdata(devptr));
-	platform_set_drvdata(devptr, NULL);
+	snd_card_free(dev_get_drvdata(pdev));
+	dev_set_drvdata(pdev, NULL);
 	return 0;
 }
 
 #ifdef CONFIG_PM
-static int snd_sb16_nonpnp_suspend(struct platform_device *dev, pm_message_t state)
+static int snd_sb16_isa_suspend(struct device *dev, unsigned int n,
+				pm_message_t state)
 {
-	return snd_sb16_suspend(platform_get_drvdata(dev), state);
+	return snd_sb16_suspend(dev_get_drvdata(dev), state);
 }
 
-static int snd_sb16_nonpnp_resume(struct platform_device *dev)
+static int snd_sb16_isa_resume(struct device *dev, unsigned int n)
 {
-	return snd_sb16_resume(platform_get_drvdata(dev));
+	return snd_sb16_resume(dev_get_drvdata(dev));
 }
 #endif
 
 #ifdef SNDRV_SBAWE
-#define SND_SB16_DRIVER	"snd_sbawe"
+#define DEV_NAME "sbawe"
 #else
-#define SND_SB16_DRIVER	"snd_sb16"
+#define DEV_NAME "sb16"
 #endif
 
-static struct platform_driver snd_sb16_nonpnp_driver = {
-	.probe		= snd_sb16_nonpnp_probe,
-	.remove		= __devexit_p(snd_sb16_nonpnp_remove),
+static struct isa_driver snd_sb16_isa_driver = {
+	.match		= snd_sb16_isa_match,
+	.probe		= snd_sb16_isa_probe,
+	.remove		= __devexit_p(snd_sb16_isa_remove),
 #ifdef CONFIG_PM
-	.suspend	= snd_sb16_nonpnp_suspend,
-	.resume		= snd_sb16_nonpnp_resume,
+	.suspend	= snd_sb16_isa_suspend,
+	.resume		= snd_sb16_isa_resume,
 #endif
 	.driver		= {
-		.name	= SND_SB16_DRIVER
+		.name	= DEV_NAME
 	},
 };
 
 
 #ifdef CONFIG_PNP
-static unsigned int __devinitdata sb16_pnp_devices;
-
 static int __devinit snd_sb16_pnp_detect(struct pnp_card_link *pcard,
 					 const struct pnp_card_device_id *pid)
 {
@@ -653,7 +656,6 @@ static int __devinit snd_sb16_pnp_detect(struct pnp_card_link *pcard,
 		}
 		pnp_set_card_drvdata(pcard, card);
 		dev++;
-		sb16_pnp_devices++;
 		return 0;
 	}
 
@@ -695,68 +697,29 @@ static struct pnp_card_driver sb16_pnpc_driver = {
 
 #endif /* CONFIG_PNP */
 
-static void __init_or_module snd_sb16_unregister_all(void)
-{
-	int i;
-
-#ifdef CONFIG_PNP
-	if (pnp_registered)
-		pnp_unregister_card_driver(&sb16_pnpc_driver);
-#endif
-	for (i = 0; i < ARRAY_SIZE(platform_devices); ++i)
-		platform_device_unregister(platform_devices[i]);
-	platform_driver_unregister(&snd_sb16_nonpnp_driver);
-}
-
 static int __init alsa_card_sb16_init(void)
 {
-	int i, err, cards = 0;
+	int err;
 
-	if ((err = platform_driver_register(&snd_sb16_nonpnp_driver)) < 0)
+	err = isa_register_driver(&snd_sb16_isa_driver, SNDRV_CARDS);
+	if (err < 0)
 		return err;
-
-	for (i = 0; i < SNDRV_CARDS; i++) {
-		struct platform_device *device;
-		if (! enable[i] || is_isapnp_selected(i))
-			continue;
-		device = platform_device_register_simple(SND_SB16_DRIVER,
-							 i, NULL, 0);
-		if (IS_ERR(device))
-			continue;
-		if (!platform_get_drvdata(device)) {
-			platform_device_unregister(device);
-			continue;
-		}
-		platform_devices[i] = device;
-		cards++;
-	}
 #ifdef CONFIG_PNP
 	/* PnP cards at last */
 	err = pnp_register_card_driver(&sb16_pnpc_driver);
-	if (!err) {
+	if (!err)
 		pnp_registered = 1;
-		cards += sb16_pnp_devices;
-	}
-#endif
-
-	if (!cards) {
-#ifdef MODULE
-		snd_printk(KERN_ERR "Sound Blaster 16 soundcard not found or device busy\n");
-#ifdef SNDRV_SBAWE_EMU8000
-		snd_printk(KERN_ERR "In case, if you have non-AWE card, try snd-sb16 module\n");
-#else
-		snd_printk(KERN_ERR "In case, if you have AWE card, try snd-sbawe module\n");
 #endif
-#endif
-		snd_sb16_unregister_all();
-		return -ENODEV;
-	}
 	return 0;
 }
 
 static void __exit alsa_card_sb16_exit(void)
 {
-	snd_sb16_unregister_all();
+#ifdef CONFIG_PNP
+	if (pnp_registered)
+		pnp_unregister_card_driver(&sb16_pnpc_driver);
+#endif
+	isa_unregister_driver(&snd_sb16_isa_driver);
 }
 
 module_init(alsa_card_sb16_init)
diff --git a/sound/isa/sb/sb16_csp.c b/sound/isa/sb/sb16_csp.c
index 3d9d7e0107ca..b279f2308aef 100644
--- a/sound/isa/sb/sb16_csp.c
+++ b/sound/isa/sb/sb16_csp.c
@@ -36,6 +36,13 @@
 MODULE_AUTHOR("Uros Bizjak <uros@kss-loka.si>");
 MODULE_DESCRIPTION("ALSA driver for SB16 Creative Signal Processor");
 MODULE_LICENSE("GPL");
+#ifndef CONFIG_SND_SB16_CSP_FIRMWARE_IN_KERNEL
+MODULE_FIRMWARE("sb16/mulaw_main.csp");
+MODULE_FIRMWARE("sb16/alaw_main.csp");
+MODULE_FIRMWARE("sb16/ima_adpcm_init.csp");
+MODULE_FIRMWARE("sb16/ima_adpcm_playback.csp");
+MODULE_FIRMWARE("sb16/ima_adpcm_capture.csp");
+#endif
 
 #ifdef SNDRV_LITTLE_ENDIAN
 #define CSP_HDR_VALUE(a,b,c,d)	((a) | ((b)<<8) | ((c)<<16) | ((d)<<24))
@@ -161,13 +168,17 @@ int snd_sb_csp_new(struct snd_sb *chip, int device, struct snd_hwdep ** rhwdep)
  */
 static void snd_sb_csp_free(struct snd_hwdep *hwdep)
 {
+#ifndef CONFIG_SND_SB16_CSP_FIRMWARE_IN_KERNEL
 	int i;
+#endif
 	struct snd_sb_csp *p = hwdep->private_data;
 	if (p) {
 		if (p->running & SNDRV_SB_CSP_ST_RUNNING)
 			snd_sb_csp_stop(p);
+#ifndef CONFIG_SND_SB16_CSP_FIRMWARE_IN_KERNEL
 		for (i = 0; i < ARRAY_SIZE(p->csp_programs); ++i)
 			release_firmware(p->csp_programs[i]);
+#endif
 		kfree(p);
 	}
 }
@@ -690,9 +701,7 @@ static int snd_sb_csp_load_user(struct snd_sb_csp * p, const unsigned char __use
 	return err;
 }
 
-#define FIRMWARE_IN_THE_KERNEL
-
-#ifdef FIRMWARE_IN_THE_KERNEL
+#ifdef CONFIG_SND_SB16_CSP_FIRMWARE_IN_KERNEL
 #include "sb16_csp_codecs.h"
 
 static const struct firmware snd_sb_csp_static_programs[] = {
@@ -714,22 +723,19 @@ static int snd_sb_csp_firmware_load(struct snd_sb_csp *p, int index, int flags)
 		"sb16/ima_adpcm_capture.csp",
 	};
 	const struct firmware *program;
-	int err;
 
 	BUILD_BUG_ON(ARRAY_SIZE(names) != CSP_PROGRAM_COUNT);
 	program = p->csp_programs[index];
 	if (!program) {
-		err = request_firmware(&program, names[index],
-				       p->chip->card->dev);
-		if (err >= 0)
-			p->csp_programs[index] = program;
-		else {
-#ifdef FIRMWARE_IN_THE_KERNEL
-			program = &snd_sb_csp_static_programs[index];
+#ifdef CONFIG_SND_SB16_CSP_FIRMWARE_IN_KERNEL
+		program = &snd_sb_csp_static_programs[index];
 #else
+		int err = request_firmware(&program, names[index],
+				       p->chip->card->dev);
+		if (err < 0)
 			return err;
 #endif
-		}
+		p->csp_programs[index] = program;
 	}
 	return snd_sb_csp_load(p, program->data, program->size, flags);
 }
diff --git a/sound/isa/sb/sb8.c b/sound/isa/sb/sb8.c
index be1e83e6dea3..a1b3786b391e 100644
--- a/sound/isa/sb/sb8.c
+++ b/sound/isa/sb/sb8.c
@@ -22,7 +22,7 @@
 #include <sound/driver.h>
 #include <linux/init.h>
 #include <linux/err.h>
-#include <linux/platform_device.h>
+#include <linux/isa.h>
 #include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/moduleparam.h>
@@ -56,8 +56,6 @@ MODULE_PARM_DESC(irq, "IRQ # for SB8 driver.");
 module_param_array(dma8, int, NULL, 0444);
 MODULE_PARM_DESC(dma8, "8-bit DMA # for SB8 driver.");
 
-static struct platform_device *devices[SNDRV_CARDS];
-
 struct snd_sb8 {
 	struct resource *fm_res;	/* used to block FM i/o region for legacy cards */
 	struct snd_sb *chip;
@@ -83,9 +81,23 @@ static void snd_sb8_free(struct snd_card *card)
 	release_and_free_resource(acard->fm_res);
 }
 
-static int __devinit snd_sb8_probe(struct platform_device *pdev)
+static int __devinit snd_sb8_match(struct device *pdev, unsigned int dev)
+{
+	if (!enable[dev])
+		return 0;
+	if (irq[dev] == SNDRV_AUTO_IRQ) {
+		snd_printk(KERN_ERR "%s: please specify irq\n", pdev->bus_id);
+		return 0;
+	}
+	if (dma8[dev] == SNDRV_AUTO_DMA) {
+		snd_printk(KERN_ERR "%s: please specify dma8\n", pdev->bus_id);
+		return 0;
+	}
+	return 1;
+}
+
+static int __devinit snd_sb8_probe(struct device *pdev, unsigned int dev)
 {
-	int dev = pdev->id;
 	struct snd_sb *chip;
 	struct snd_card *card;
 	struct snd_sb8 *acard;
@@ -180,12 +192,12 @@ static int __devinit snd_sb8_probe(struct platform_device *pdev)
 		chip->port,
 		irq[dev], dma8[dev]);
 
-	snd_card_set_dev(card, &pdev->dev);
+	snd_card_set_dev(card, pdev);
 
 	if ((err = snd_card_register(card)) < 0)
 		goto _err;
 
-	platform_set_drvdata(pdev, card);
+	dev_set_drvdata(pdev, card);
 	return 0;
 
  _err:
@@ -193,17 +205,18 @@ static int __devinit snd_sb8_probe(struct platform_device *pdev)
 	return err;
 }
 
-static int __devexit snd_sb8_remove(struct platform_device *pdev)
+static int __devexit snd_sb8_remove(struct device *pdev, unsigned int dev)
 {
-	snd_card_free(platform_get_drvdata(pdev));
-	platform_set_drvdata(pdev, NULL);
+	snd_card_free(dev_get_drvdata(pdev));
+	dev_set_drvdata(pdev, NULL);
 	return 0;
 }
 
 #ifdef CONFIG_PM
-static int snd_sb8_suspend(struct platform_device *dev, pm_message_t state)
+static int snd_sb8_suspend(struct device *dev, unsigned int n,
+			   pm_message_t state)
 {
-	struct snd_card *card = platform_get_drvdata(dev);
+	struct snd_card *card = dev_get_drvdata(dev);
 	struct snd_sb8 *acard = card->private_data;
 	struct snd_sb *chip = acard->chip;
 
@@ -213,9 +226,9 @@ static int snd_sb8_suspend(struct platform_device *dev, pm_message_t state)
 	return 0;
 }
 
-static int snd_sb8_resume(struct platform_device *dev)
+static int snd_sb8_resume(struct device *dev, unsigned int n)
 {
-	struct snd_card *card = platform_get_drvdata(dev);
+	struct snd_card *card = dev_get_drvdata(dev);
 	struct snd_sb8 *acard = card->private_data;
 	struct snd_sb *chip = acard->chip;
 
@@ -226,9 +239,10 @@ static int snd_sb8_resume(struct platform_device *dev)
 }
 #endif
 
-#define SND_SB8_DRIVER	"snd_sb8"
+#define DEV_NAME "sb8"
 
-static struct platform_driver snd_sb8_driver = {
+static struct isa_driver snd_sb8_driver = {
+	.match		= snd_sb8_match,
 	.probe		= snd_sb8_probe,
 	.remove		= __devexit_p(snd_sb8_remove),
 #ifdef CONFIG_PM
@@ -236,56 +250,18 @@ static struct platform_driver snd_sb8_driver = {
 	.resume		= snd_sb8_resume,
 #endif
 	.driver		= {
-		.name	= SND_SB8_DRIVER
+		.name	= DEV_NAME 
 	},
 };
 
-static void __init_or_module snd_sb8_unregister_all(void)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(devices); ++i)
-		platform_device_unregister(devices[i]);
-	platform_driver_unregister(&snd_sb8_driver);
-}
-
 static int __init alsa_card_sb8_init(void)
 {
-	int i, cards, err;
-
-	err = platform_driver_register(&snd_sb8_driver);
-	if (err < 0)
-		return err;
-
-	cards = 0;
-	for (i = 0; i < SNDRV_CARDS; i++) {
-		struct platform_device *device;
-		if (! enable[i])
-			continue;
-		device = platform_device_register_simple(SND_SB8_DRIVER,
-							 i, NULL, 0);
-		if (IS_ERR(device))
-			continue;
-		if (!platform_get_drvdata(device)) {
-			platform_device_unregister(device);
-			continue;
-		}
-		devices[i] = device;
-		cards++;
-	}
-	if (!cards) {
-#ifdef MODULE
-		snd_printk(KERN_ERR "Sound Blaster soundcard not found or device busy\n");
-#endif
-		snd_sb8_unregister_all();
-		return -ENODEV;
-	}
-	return 0;
+	return isa_register_driver(&snd_sb8_driver, SNDRV_CARDS);
 }
 
 static void __exit alsa_card_sb8_exit(void)
 {
-	snd_sb8_unregister_all();
+	isa_unregister_driver(&snd_sb8_driver);
 }
 
 module_init(alsa_card_sb8_init)
diff --git a/sound/isa/sgalaxy.c b/sound/isa/sgalaxy.c
index 4fcd0f4e868c..922519def099 100644
--- a/sound/isa/sgalaxy.c
+++ b/sound/isa/sgalaxy.c
@@ -24,7 +24,7 @@
 #include <sound/driver.h>
 #include <linux/init.h>
 #include <linux/err.h>
-#include <linux/platform_device.h>
+#include <linux/isa.h>
 #include <linux/delay.h>
 #include <linux/time.h>
 #include <linux/interrupt.h>
@@ -64,8 +64,6 @@ MODULE_PARM_DESC(irq, "IRQ # for Sound Galaxy driver.");
 module_param_array(dma1, int, NULL, 0444);
 MODULE_PARM_DESC(dma1, "DMA1 # for Sound Galaxy driver.");
 
-static struct platform_device *devices[SNDRV_CARDS];
-
 #define SGALAXY_AUXC_LEFT 18
 #define SGALAXY_AUXC_RIGHT 19
 
@@ -96,7 +94,8 @@ static int snd_sgalaxy_sbdsp_reset(unsigned long port)
 	return 0;
 }
 
-static int __init snd_sgalaxy_sbdsp_command(unsigned long port, unsigned char val)
+static int __devinit snd_sgalaxy_sbdsp_command(unsigned long port,
+					       unsigned char val)
 {
 	int i;
        	
@@ -114,7 +113,7 @@ static irqreturn_t snd_sgalaxy_dummy_interrupt(int irq, void *dev_id)
 	return IRQ_NONE;
 }
 
-static int __init snd_sgalaxy_setup_wss(unsigned long port, int irq, int dma)
+static int __devinit snd_sgalaxy_setup_wss(unsigned long port, int irq, int dma)
 {
 	static int interrupt_bits[] = {-1, -1, -1, -1, -1, -1, -1, 0x08, -1, 
 				       0x10, 0x18, 0x20, -1, -1, -1, -1};
@@ -161,7 +160,7 @@ static int __init snd_sgalaxy_setup_wss(unsigned long port, int irq, int dma)
 	return 0;
 }
 
-static int __init snd_sgalaxy_detect(int dev, int irq, int dma)
+static int __devinit snd_sgalaxy_detect(int dev, int irq, int dma)
 {
 #if 0
 	snd_printdd(PFX "switching to WSS mode\n");
@@ -182,7 +181,7 @@ AD1848_DOUBLE("Aux Playback Switch", 0, SGALAXY_AUXC_LEFT, SGALAXY_AUXC_RIGHT, 7
 AD1848_DOUBLE("Aux Playback Volume", 0, SGALAXY_AUXC_LEFT, SGALAXY_AUXC_RIGHT, 0, 0, 31, 0)
 };
 
-static int __init snd_sgalaxy_mixer(struct snd_ad1848 *chip)
+static int __devinit snd_sgalaxy_mixer(struct snd_ad1848 *chip)
 {
 	struct snd_card *card = chip->card;
 	struct snd_ctl_elem_id id1, id2;
@@ -218,23 +217,29 @@ static int __init snd_sgalaxy_mixer(struct snd_ad1848 *chip)
 	return 0;
 }
 
-static int __init snd_sgalaxy_probe(struct platform_device *devptr)
+static int __devinit snd_sgalaxy_match(struct device *devptr, unsigned int dev)
 {
-	int dev = devptr->id;
-	static int possible_irqs[] = {7, 9, 10, 11, -1};
-	static int possible_dmas[] = {1, 3, 0, -1};
-	int err, xirq, xdma1;
-	struct snd_card *card;
-	struct snd_ad1848 *chip;
-
+	if (!enable[dev])
+		return 0;
 	if (sbport[dev] == SNDRV_AUTO_PORT) {
 		snd_printk(KERN_ERR PFX "specify SB port\n");
-		return -EINVAL;
+		return 0;
 	}
 	if (wssport[dev] == SNDRV_AUTO_PORT) {
 		snd_printk(KERN_ERR PFX "specify WSS port\n");
-		return -EINVAL;
+		return 0;
 	}
+	return 1;
+}
+
+static int __devinit snd_sgalaxy_probe(struct device *devptr, unsigned int dev)
+{
+	static int possible_irqs[] = {7, 9, 10, 11, -1};
+	static int possible_dmas[] = {1, 3, 0, -1};
+	int err, xirq, xdma1;
+	struct snd_card *card;
+	struct snd_ad1848 *chip;
+
 	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
 	if (card == NULL)
 		return -ENOMEM;
@@ -283,12 +288,12 @@ static int __init snd_sgalaxy_probe(struct platform_device *devptr)
 	sprintf(card->longname, "Sound Galaxy at 0x%lx, irq %d, dma %d",
 		wssport[dev], xirq, xdma1);
 
-	snd_card_set_dev(card, &devptr->dev);
+	snd_card_set_dev(card, devptr);
 
 	if ((err = snd_card_register(card)) < 0)
 		goto _err;
 
-	platform_set_drvdata(devptr, card);
+	dev_set_drvdata(devptr, card);
 	return 0;
 
  _err:
@@ -296,17 +301,18 @@ static int __init snd_sgalaxy_probe(struct platform_device *devptr)
 	return err;
 }
 
-static int __devexit snd_sgalaxy_remove(struct platform_device *devptr)
+static int __devexit snd_sgalaxy_remove(struct device *devptr, unsigned int dev)
 {
-	snd_card_free(platform_get_drvdata(devptr));
-	platform_set_drvdata(devptr, NULL);
+	snd_card_free(dev_get_drvdata(devptr));
+	dev_set_drvdata(devptr, NULL);
 	return 0;
 }
 
 #ifdef CONFIG_PM
-static int snd_sgalaxy_suspend(struct platform_device *pdev, pm_message_t state)
+static int snd_sgalaxy_suspend(struct device *pdev, unsigned int n,
+			       pm_message_t state)
 {
-	struct snd_card *card = platform_get_drvdata(pdev);
+	struct snd_card *card = dev_get_drvdata(pdev);
 	struct snd_ad1848 *chip = card->private_data;
 
 	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
@@ -314,9 +320,9 @@ static int snd_sgalaxy_suspend(struct platform_device *pdev, pm_message_t state)
 	return 0;
 }
 
-static int snd_sgalaxy_resume(struct platform_device *pdev)
+static int snd_sgalaxy_resume(struct device *pdev, unsigned int n)
 {
-	struct snd_card *card = platform_get_drvdata(pdev);
+	struct snd_card *card = dev_get_drvdata(pdev);
 	struct snd_ad1848 *chip = card->private_data;
 
 	chip->resume(chip);
@@ -328,9 +334,10 @@ static int snd_sgalaxy_resume(struct platform_device *pdev)
 }
 #endif
 
-#define SND_SGALAXY_DRIVER	"snd_sgalaxy"
+#define DEV_NAME "sgalaxy"
 
-static struct platform_driver snd_sgalaxy_driver = {
+static struct isa_driver snd_sgalaxy_driver = {
+	.match		= snd_sgalaxy_match,
 	.probe		= snd_sgalaxy_probe,
 	.remove		= __devexit_p(snd_sgalaxy_remove),
 #ifdef CONFIG_PM
@@ -338,56 +345,18 @@ static struct platform_driver snd_sgalaxy_driver = {
 	.resume		= snd_sgalaxy_resume,
 #endif
 	.driver		= {
-		.name	= SND_SGALAXY_DRIVER
+		.name	= DEV_NAME
 	},
 };
 
-static void __init_or_module snd_sgalaxy_unregister_all(void)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(devices); ++i)
-		platform_device_unregister(devices[i]);
-	platform_driver_unregister(&snd_sgalaxy_driver);
-}
-
 static int __init alsa_card_sgalaxy_init(void)
 {
-	int i, cards, err;
-
-	err = platform_driver_register(&snd_sgalaxy_driver);
-	if (err < 0)
-		return err;
-
-	cards = 0;
-	for (i = 0; i < SNDRV_CARDS; i++) {
-		struct platform_device *device;
-		if (! enable[i])
-			continue;
-		device = platform_device_register_simple(SND_SGALAXY_DRIVER,
-							 i, NULL, 0);
-		if (IS_ERR(device))
-			continue;
-		if (!platform_get_drvdata(device)) {
-			platform_device_unregister(device);
-			continue;
-		}
-		devices[i] = device;
-		cards++;
-	}
-	if (!cards) {
-#ifdef MODULE
-		snd_printk(KERN_ERR "Sound Galaxy soundcard not found or device busy\n");
-#endif
-		snd_sgalaxy_unregister_all();
-		return -ENODEV;
-	}
-	return 0;
+	return isa_register_driver(&snd_sgalaxy_driver, SNDRV_CARDS);
 }
 
 static void __exit alsa_card_sgalaxy_exit(void)
 {
-	snd_sgalaxy_unregister_all();
+	isa_unregister_driver(&snd_sgalaxy_driver);
 }
 
 module_init(alsa_card_sgalaxy_init)
diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c
index b1f25823c652..08c14978558c 100644
--- a/sound/isa/sscape.c
+++ b/sound/isa/sscape.c
@@ -24,7 +24,7 @@
 #include <sound/driver.h>
 #include <linux/init.h>
 #include <linux/err.h>
-#include <linux/platform_device.h>
+#include <linux/isa.h>
 #include <linux/delay.h>
 #include <linux/pnp.h>
 #include <linux/spinlock.h>
@@ -68,8 +68,6 @@ MODULE_PARM_DESC(mpu_irq, "MPU401 IRQ # for SoundScape driver.");
 module_param_array(dma, int, NULL, 0444);
 MODULE_PARM_DESC(dma, "DMA # for SoundScape driver.");
 
-static struct platform_device *platform_devices[SNDRV_CARDS];
-  
 #ifdef CONFIG_PNP
 static int pnp_registered;
 static struct pnp_card_device_id sscape_pnpids[] = {
@@ -1254,9 +1252,27 @@ static int __devinit create_sscape(int dev, struct snd_card **rcardp)
 }
 
 
-static int __devinit snd_sscape_probe(struct platform_device *pdev)
+static int __devinit snd_sscape_match(struct device *pdev, unsigned int i)
+{
+	/*
+	 * Make sure we were given ALL of the other parameters.
+	 */
+	if (port[i] == SNDRV_AUTO_PORT)
+		return 0;
+
+	if (irq[i] == SNDRV_AUTO_IRQ ||
+	    mpu_irq[i] == SNDRV_AUTO_IRQ ||
+	    dma[i] == SNDRV_AUTO_DMA) {
+		printk(KERN_INFO
+		       "sscape: insufficient parameters, need IO, IRQ, MPU-IRQ and DMA\n");
+		return 0;
+	}
+
+	return 1;
+}
+
+static int __devinit snd_sscape_probe(struct device *pdev, unsigned int dev)
 {
-	int dev = pdev->id;
 	struct snd_card *card;
 	int ret;
 
@@ -1264,30 +1280,31 @@ static int __devinit snd_sscape_probe(struct platform_device *pdev)
 	ret = create_sscape(dev, &card);
 	if (ret < 0)
 		return ret;
-	snd_card_set_dev(card, &pdev->dev);
+	snd_card_set_dev(card, pdev);
 	if ((ret = snd_card_register(card)) < 0) {
 		printk(KERN_ERR "sscape: Failed to register sound card\n");
 		return ret;
 	}
-	platform_set_drvdata(pdev, card);
+	dev_set_drvdata(pdev, card);
 	return 0;
 }
 
-static int __devexit snd_sscape_remove(struct platform_device *devptr)
+static int __devexit snd_sscape_remove(struct device *devptr, unsigned int dev)
 {
-	snd_card_free(platform_get_drvdata(devptr));
-	platform_set_drvdata(devptr, NULL);
+	snd_card_free(dev_get_drvdata(devptr));
+	dev_set_drvdata(devptr, NULL);
 	return 0;
 }
 
-#define SSCAPE_DRIVER	"snd_sscape"
+#define DEV_NAME "sscape"
 
-static struct platform_driver snd_sscape_driver = {
+static struct isa_driver snd_sscape_driver = {
+	.match		= snd_sscape_match,
 	.probe		= snd_sscape_probe,
 	.remove		= __devexit_p(snd_sscape_remove),
 	/* FIXME: suspend/resume */
 	.driver		= {
-		.name	= SSCAPE_DRIVER
+		.name	= DEV_NAME
 	},
 };
 
@@ -1386,72 +1403,6 @@ static struct pnp_card_driver sscape_pnpc_driver = {
 
 #endif /* CONFIG_PNP */
 
-static void __init_or_module sscape_unregister_all(void)
-{
-	int i;
-
-#ifdef CONFIG_PNP
-	if (pnp_registered)
-		pnp_unregister_card_driver(&sscape_pnpc_driver);
-#endif
-	for (i = 0; i < ARRAY_SIZE(platform_devices); ++i)
-		platform_device_unregister(platform_devices[i]);
-	platform_driver_unregister(&snd_sscape_driver);
-}
-
-static int __init sscape_manual_probe(void)
-{
-	struct platform_device *device;
-	int i, ret;
-
-	ret = platform_driver_register(&snd_sscape_driver);
-	if (ret < 0)
-		return ret;
-
-	for (i = 0; i < SNDRV_CARDS; ++i) {
-		/*
-		 * We do NOT probe for ports.
-		 * If we're not given a port number for this
-		 * card then we completely ignore this line
-		 * of parameters.
-		 */
-		if (port[i] == SNDRV_AUTO_PORT)
-			continue;
-
-		/*
-		 * Make sure we were given ALL of the other parameters.
-		 */
-		if (irq[i] == SNDRV_AUTO_IRQ ||
-		    mpu_irq[i] == SNDRV_AUTO_IRQ ||
-		    dma[i] == SNDRV_AUTO_DMA) {
-			printk(KERN_INFO
-			       "sscape: insufficient parameters, need IO, IRQ, MPU-IRQ and DMA\n");
-			sscape_unregister_all();
-			return -ENXIO;
-		}
-
-		/*
-		 * This cards looks OK ...
-		 */
-		device = platform_device_register_simple(SSCAPE_DRIVER,
-							 i, NULL, 0);
-		if (IS_ERR(device))
-			continue;
-		if (!platform_get_drvdata(device)) {
-			platform_device_unregister(device);
-			continue;
-		}
-		platform_devices[i] = device;
-	}
-	return 0;
-}
-
-static void sscape_exit(void)
-{
-	sscape_unregister_all();
-}
-
-
 static int __init sscape_init(void)
 {
 	int ret;
@@ -1462,7 +1413,7 @@ static int __init sscape_init(void)
 	 * of allocating cards, because the operator is
 	 * S-P-E-L-L-I-N-G it out for us...
 	 */
-	ret = sscape_manual_probe();
+	ret = isa_register_driver(&snd_sscape_driver, SNDRV_CARDS);
 	if (ret < 0)
 		return ret;
 #ifdef CONFIG_PNP
@@ -1472,5 +1423,14 @@ static int __init sscape_init(void)
 	return 0;
 }
 
+static void __exit sscape_exit(void)
+{
+#ifdef CONFIG_PNP
+	if (pnp_registered)
+		pnp_unregister_card_driver(&sscape_pnpc_driver);
+#endif
+	isa_unregister_driver(&snd_sscape_driver);
+}
+
 module_init(sscape_init);
 module_exit(sscape_exit);
diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c
index e2fdd5fd39d0..75673f723857 100644
--- a/sound/isa/wavefront/wavefront.c
+++ b/sound/isa/wavefront/wavefront.c
@@ -24,7 +24,7 @@
 #include <linux/interrupt.h>
 #include <linux/slab.h>
 #include <linux/err.h>
-#include <linux/platform_device.h>
+#include <linux/isa.h>
 #include <linux/pnp.h>
 #include <linux/moduleparam.h>
 #include <sound/core.h>
@@ -40,7 +40,9 @@ MODULE_SUPPORTED_DEVICE("{{Turtle Beach,Maui/Tropez/Tropez+}}");
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	    /* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	    /* ID for this card */
 static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE;	    /* Enable this card */
+#ifdef CONFIG_PNP
 static int isapnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
+#endif
 static long cs4232_pcm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;	/* PnP setup */
 static int cs4232_pcm_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,11,12,15 */
 static long cs4232_mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
@@ -83,8 +85,6 @@ MODULE_PARM_DESC(fm_port, "FM port #.");
 module_param_array(use_cs4232_midi, bool, NULL, 0444);
 MODULE_PARM_DESC(use_cs4232_midi, "Use CS4232 MPU-401 interface (inaccessibly located inside your computer)");
 
-static struct platform_device *platform_devices[SNDRV_CARDS];
-
 #ifdef CONFIG_PNP
 static int pnp_registered;
 
@@ -588,56 +588,67 @@ snd_wavefront_probe (struct snd_card *card, int dev)
 	return snd_card_register(card);
 }	
 
-static int __devinit snd_wavefront_nonpnp_probe(struct platform_device *pdev)
+static int __devinit snd_wavefront_isa_match(struct device *pdev,
+					     unsigned int dev)
 {
-	int dev = pdev->id;
-	struct snd_card *card;
-	int err;
-
+	if (!enable[dev])
+		return 0;
+#ifdef CONFIG_PNP
+	if (isapnp[dev])
+		return 0;
+#endif
 	if (cs4232_pcm_port[dev] == SNDRV_AUTO_PORT) {
 		snd_printk("specify CS4232 port\n");
-		return -EINVAL;
+		return 0;
 	}
 	if (ics2115_port[dev] == SNDRV_AUTO_PORT) {
 		snd_printk("specify ICS2115 port\n");
-		return -ENODEV;
+		return 0;
 	}
+	return 1;
+}
+
+static int __devinit snd_wavefront_isa_probe(struct device *pdev,
+					     unsigned int dev)
+{
+	struct snd_card *card;
+	int err;
 
 	card = snd_wavefront_card_new(dev);
 	if (! card)
 		return -ENOMEM;
-	snd_card_set_dev(card, &pdev->dev);
+	snd_card_set_dev(card, pdev);
 	if ((err = snd_wavefront_probe(card, dev)) < 0) {
 		snd_card_free(card);
 		return err;
 	}
 	
-	platform_set_drvdata(pdev, card);
+	dev_set_drvdata(pdev, card);
 	return 0;
 }
 
-static int __devexit snd_wavefront_nonpnp_remove(struct platform_device *devptr)
+static int __devexit snd_wavefront_isa_remove(struct device *devptr,
+					      unsigned int dev)
 {
-	snd_card_free(platform_get_drvdata(devptr));
-	platform_set_drvdata(devptr, NULL);
+	snd_card_free(dev_get_drvdata(devptr));
+	dev_set_drvdata(devptr, NULL);
 	return 0;
 }
 
-#define WAVEFRONT_DRIVER	"snd_wavefront"
+#define DEV_NAME "wavefront"
 
-static struct platform_driver snd_wavefront_driver = {
-	.probe		= snd_wavefront_nonpnp_probe,
-	.remove		= __devexit_p(snd_wavefront_nonpnp_remove),
+static struct isa_driver snd_wavefront_driver = {
+	.match		= snd_wavefront_isa_match,
+	.probe		= snd_wavefront_isa_probe,
+	.remove		= __devexit_p(snd_wavefront_isa_remove),
 	/* FIXME: suspend, resume */
 	.driver		= {
-		.name	= WAVEFRONT_DRIVER
+		.name	= DEV_NAME
 	},
 };
 
 
 #ifdef CONFIG_PNP
-static unsigned int __devinitdata wavefront_pnp_devices;
-
 static int __devinit snd_wavefront_pnp_detect(struct pnp_card_link *pcard,
                                               const struct pnp_card_device_id *pid)
 {
@@ -670,7 +681,6 @@ static int __devinit snd_wavefront_pnp_detect(struct pnp_card_link *pcard,
 
 	pnp_set_card_drvdata(pcard, card);
 	dev++;
-	wavefront_pnp_devices++;
 	return 0;
 }
 
@@ -691,67 +701,28 @@ static struct pnp_card_driver wavefront_pnpc_driver = {
 
 #endif /* CONFIG_PNP */
 
-static void __init_or_module snd_wavefront_unregister_all(void)
-{
-	int i;
-
-#ifdef CONFIG_PNP
-	if (pnp_registered)
-		pnp_unregister_card_driver(&wavefront_pnpc_driver);
-#endif
-	for (i = 0; i < ARRAY_SIZE(platform_devices); ++i)
-		platform_device_unregister(platform_devices[i]);
-	platform_driver_unregister(&snd_wavefront_driver);
-}
-
 static int __init alsa_card_wavefront_init(void)
 {
-	int i, err, cards = 0;
+	int err;
 
-	if ((err = platform_driver_register(&snd_wavefront_driver)) < 0)
+	err = isa_register_driver(&snd_wavefront_driver, SNDRV_CARDS);
+	if (err < 0)
 		return err;
-
-	for (i = 0; i < SNDRV_CARDS; i++) {
-		struct platform_device *device;
-		if (! enable[i])
-			continue;
-#ifdef CONFIG_PNP
-		if (isapnp[i])
-			continue;
-#endif
-		device = platform_device_register_simple(WAVEFRONT_DRIVER,
-							 i, NULL, 0);
-		if (IS_ERR(device))
-			continue;
-		if (!platform_get_drvdata(device)) {
-			platform_device_unregister(device);
-			continue;
-		}
-		platform_devices[i] = device;
-		cards++;
-	}
-
 #ifdef CONFIG_PNP
 	err = pnp_register_card_driver(&wavefront_pnpc_driver);
-	if (!err) {
+	if (!err)
 		pnp_registered = 1;
-		cards += wavefront_pnp_devices;
-	}
-#endif
-
-	if (!cards) {
-#ifdef MODULE
-		printk (KERN_ERR "No WaveFront cards found or devices busy\n");
 #endif
-		snd_wavefront_unregister_all();
-		return -ENODEV;
-	}
 	return 0;
 }
 
 static void __exit alsa_card_wavefront_exit(void)
 {
-	snd_wavefront_unregister_all();
+#ifdef CONFIG_PNP
+	if (pnp_registered)
+		pnp_unregister_card_driver(&wavefront_pnpc_driver);
+#endif
+	isa_unregister_driver(&snd_wavefront_driver);
 }
 
 module_init(alsa_card_wavefront_init)
diff --git a/sound/isa/wavefront/wavefront_fx.c b/sound/isa/wavefront/wavefront_fx.c
index 15331ed88194..fc95a870f690 100644
--- a/sound/isa/wavefront/wavefront_fx.c
+++ b/sound/isa/wavefront/wavefront_fx.c
@@ -35,9 +35,7 @@
 
 #define WAIT_IDLE	0xff
 
-#define FIRMWARE_IN_THE_KERNEL
-
-#ifdef FIRMWARE_IN_THE_KERNEL
+#ifdef CONFIG_SND_WAVEFRONT_FIRMWARE_IN_KERNEL
 #include "yss225.c"
 static const struct firmware yss225_registers_firmware = {
 	.data = (u8 *)yss225_registers,
@@ -258,21 +256,21 @@ snd_wavefront_fx_start (snd_wavefront_t *dev)
 {
 	unsigned int i;
 	int err;
-	const struct firmware *firmware;
+	const struct firmware *firmware = NULL;
 
 	if (dev->fx_initialized)
 		return 0;
 
+#ifdef CONFIG_SND_WAVEFRONT_FIRMWARE_IN_KERNEL
+	firmware = &yss225_registers_firmware;
+#else
 	err = request_firmware(&firmware, "yamaha/yss225_registers.bin",
 			       dev->card->dev);
 	if (err < 0) {
-#ifdef FIRMWARE_IN_THE_KERNEL
-		firmware = &yss225_registers_firmware;
-#else
 		err = -1;
 		goto out;
-#endif
 	}
+#endif
 
 	for (i = 0; i + 1 < firmware->size; i += 2) {
 		if (firmware->data[i] >= 8 && firmware->data[i] < 16) {
@@ -295,9 +293,12 @@ snd_wavefront_fx_start (snd_wavefront_t *dev)
 	err = 0;
 
 out:
-#ifdef FIRMWARE_IN_THE_KERNEL
-	if (firmware != &yss225_registers_firmware)
+#ifndef CONFIG_SND_WAVEFRONT_FIRMWARE_IN_KERNEL
+	release_firmware(firmware);
 #endif
-		release_firmware(firmware);
 	return err;
 }
+
+#ifndef CONFIG_SND_WAVEFRONT_FIRMWARE_IN_KERNEL
+MODULE_FIRMWARE("yamaha/yss225_registers.bin");
+#endif
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index 1bcfb3aac18d..61e35ecc57b8 100644
--- a/sound/pci/Kconfig
+++ b/sound/pci/Kconfig
@@ -576,7 +576,7 @@ config SND_INTEL8X0M
 config SND_KORG1212
 	tristate "Korg 1212 IO"
 	depends on SND
-	select FW_LOADER
+	select FW_LOADER if !SND_KORG1212_FIRMWARE_IN_KERNEL
 	select SND_PCM
 	help
 	  Say Y here to include support for Korg 1212IO soundcards.
@@ -584,10 +584,19 @@ config SND_KORG1212
 	  To compile this driver as a module, choose M here: the module
 	  will be called snd-korg1212.
 
+config SND_KORG1212_FIRMWARE_IN_KERNEL
+	bool "In-kernel firmware for Korg1212 driver"
+	depends on SND_KORG1212
+	default y
+	help
+	  Say Y here to include the static firmware built in the kernel
+	  for the Korg1212 driver.  If you choose N here, you need to
+	  install the firmware files from the alsa-firmware package.
+
 config SND_MAESTRO3
 	tristate "ESS Allegro/Maestro3"
 	depends on SND
-	select FW_LOADER
+	select FW_LOADER if !SND_MAESTRO3_FIRMWARE_IN_KERNEL
 	select SND_AC97_CODEC
 	help
 	  Say Y here to include support for soundcards based on ESS Maestro 3
@@ -596,6 +605,15 @@ config SND_MAESTRO3
 	  To compile this driver as a module, choose M here: the module
 	  will be called snd-maestro3.
 
+config SND_MAESTRO3_FIRMWARE_IN_KERNEL
+	bool "In-kernel firmware for Maestro3 driver"
+	depends on SND_MAESTRO3
+	default y
+	help
+	  Say Y here to include the static firmware built in the kernel
+	  for the Maestro3 driver.  If you choose N here, you need to
+	  install the firmware files from the alsa-firmware package.
+
 config SND_MIXART
 	tristate "Digigram miXart"
 	depends on SND
@@ -737,7 +755,7 @@ config SND_VX222
 config SND_YMFPCI
 	tristate "Yamaha YMF724/740/744/754"
 	depends on SND
-	select FW_LOADER
+	select FW_LOADER if !SND_YMFPCI_FIRMWARE_IN_KERNEL
 	select SND_OPL3_LIB
 	select SND_MPU401_UART
 	select SND_AC97_CODEC
@@ -748,6 +766,15 @@ config SND_YMFPCI
 	  To compile this driver as a module, choose M here: the module
 	  will be called snd-ymfpci.
 
+config SND_YMFPCI_FIRMWARE_IN_KERNEL
+	bool "In-kernel firmware for YMFPCI driver"
+	depends on SND_YMFPCI
+	default y
+	help
+	  Say Y here to include the static firmware built in the kernel
+	  for the YMFPCI driver.  If you choose N here, you need to
+	  install the firmware files from the alsa-firmware package.
+
 config SND_AC97_POWER_SAVE
 	bool "AC97 Power-Saving Mode"
 	depends on SND_AC97_CODEC && EXPERIMENTAL
diff --git a/sound/pci/ac97/Makefile b/sound/pci/ac97/Makefile
index 3c3222122d8b..f5d471896b95 100644
--- a/sound/pci/ac97/Makefile
+++ b/sound/pci/ac97/Makefile
@@ -3,7 +3,7 @@
 # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
 #
 
-snd-ac97-codec-objs := ac97_codec.o ac97_pcm.o ac97_patch.o
+snd-ac97-codec-objs := ac97_codec.o ac97_pcm.o
 
 ifneq ($(CONFIG_PROC_FS),)
 snd-ac97-codec-objs += ac97_proc.o
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c
index 3bfb2102fc5d..bbed644bf9c5 100644
--- a/sound/pci/ac97/ac97_codec.c
+++ b/sound/pci/ac97/ac97_codec.c
@@ -35,9 +35,9 @@
 #include <sound/ac97_codec.h>
 #include <sound/asoundef.h>
 #include <sound/initval.h>
-#include "ac97_local.h"
 #include "ac97_id.h"
-#include "ac97_patch.h"
+
+#include "ac97_patch.c"
 
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("Universal interface for Audio Codec '97");
@@ -432,7 +432,8 @@ static int snd_ac97_ad18xx_update_pcm_bits(struct snd_ac97 *ac97, int codec, uns
  * Controls
  */
 
-int snd_ac97_info_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
+static int snd_ac97_info_enum_double(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_info *uinfo)
 {
 	struct ac97_enum *e = (struct ac97_enum *)kcontrol->private_value;
 	
@@ -446,7 +447,8 @@ int snd_ac97_info_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem
 	return 0;
 }
 
-int snd_ac97_get_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+static int snd_ac97_get_enum_double(struct snd_kcontrol *kcontrol,
+				    struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
 	struct ac97_enum *e = (struct ac97_enum *)kcontrol->private_value;
@@ -462,7 +464,8 @@ int snd_ac97_get_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_
 	return 0;
 }
 
-int snd_ac97_put_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+static int snd_ac97_put_enum_double(struct snd_kcontrol *kcontrol,
+				    struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
 	struct ac97_enum *e = (struct ac97_enum *)kcontrol->private_value;
@@ -508,7 +511,8 @@ static void snd_ac97_page_restore(struct snd_ac97 *ac97, int page_save)
 }
 
 /* volume and switch controls */
-int snd_ac97_info_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
+static int snd_ac97_info_volsw(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_info *uinfo)
 {
 	int mask = (kcontrol->private_value >> 16) & 0xff;
 	int shift = (kcontrol->private_value >> 8) & 0x0f;
@@ -521,7 +525,8 @@ int snd_ac97_info_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info
 	return 0;
 }
 
-int snd_ac97_get_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+static int snd_ac97_get_volsw(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
 	int reg = kcontrol->private_value & 0xff;
@@ -544,7 +549,8 @@ int snd_ac97_get_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value
 	return 0;
 }
 
-int snd_ac97_put_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+static int snd_ac97_put_volsw(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
 	int reg = kcontrol->private_value & 0xff;
@@ -646,7 +652,7 @@ AC97_ENUM("Mic Select", std_enum[3]),
 AC97_SINGLE("ADC/DAC Loopback", AC97_GENERAL_PURPOSE, 7, 1, 0)
 };
 
-const struct snd_kcontrol_new snd_ac97_controls_3d[2] = {
+static const struct snd_kcontrol_new snd_ac97_controls_3d[2] = {
 AC97_SINGLE("3D Control - Center", AC97_3D_CONTROL, 8, 15, 0),
 AC97_SINGLE("3D Control - Depth", AC97_3D_CONTROL, 0, 15, 0)
 };
@@ -817,7 +823,7 @@ static int snd_ac97_put_spsa(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_
 	return change;
 }
 
-const struct snd_kcontrol_new snd_ac97_controls_spdif[5] = {
+static const struct snd_kcontrol_new snd_ac97_controls_spdif[5] = {
 	{
 		.access = SNDRV_CTL_ELEM_ACCESS_READ,
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -1097,7 +1103,7 @@ static void check_volume_resolution(struct snd_ac97 *ac97, int reg, unsigned cha
 	}
 }
 
-int snd_ac97_try_bit(struct snd_ac97 * ac97, int reg, int bit)
+static int snd_ac97_try_bit(struct snd_ac97 * ac97, int reg, int bit)
 {
 	unsigned short mask, val, orig, res;
 
@@ -1137,7 +1143,8 @@ static inline int printable(unsigned int x)
 	return x;
 }
 
-struct snd_kcontrol *snd_ac97_cnew(const struct snd_kcontrol_new *_template, struct snd_ac97 * ac97)
+static struct snd_kcontrol *snd_ac97_cnew(const struct snd_kcontrol_new *_template,
+					  struct snd_ac97 * ac97)
 {
 	struct snd_kcontrol_new template;
 	memcpy(&template, _template, sizeof(template));
@@ -2544,7 +2551,8 @@ static void set_ctl_name(char *dst, const char *src, const char *suffix)
 }	
 
 /* remove the control with the given name and optional suffix */
-int snd_ac97_remove_ctl(struct snd_ac97 *ac97, const char *name, const char *suffix)
+static int snd_ac97_remove_ctl(struct snd_ac97 *ac97, const char *name,
+			       const char *suffix)
 {
 	struct snd_ctl_elem_id id;
 	memset(&id, 0, sizeof(id));
@@ -2563,7 +2571,8 @@ static struct snd_kcontrol *ctl_find(struct snd_ac97 *ac97, const char *name, co
 }
 
 /* rename the control with the given name and optional suffix */
-int snd_ac97_rename_ctl(struct snd_ac97 *ac97, const char *src, const char *dst, const char *suffix)
+static int snd_ac97_rename_ctl(struct snd_ac97 *ac97, const char *src,
+			       const char *dst, const char *suffix)
 {
 	struct snd_kcontrol *kctl = ctl_find(ac97, src, suffix);
 	if (kctl) {
@@ -2574,14 +2583,16 @@ int snd_ac97_rename_ctl(struct snd_ac97 *ac97, const char *src, const char *dst,
 }
 
 /* rename both Volume and Switch controls - don't check the return value */
-void snd_ac97_rename_vol_ctl(struct snd_ac97 *ac97, const char *src, const char *dst)
+static void snd_ac97_rename_vol_ctl(struct snd_ac97 *ac97, const char *src,
+				    const char *dst)
 {
 	snd_ac97_rename_ctl(ac97, src, dst, "Switch");
 	snd_ac97_rename_ctl(ac97, src, dst, "Volume");
 }
 
 /* swap controls */
-int snd_ac97_swap_ctl(struct snd_ac97 *ac97, const char *s1, const char *s2, const char *suffix)
+static int snd_ac97_swap_ctl(struct snd_ac97 *ac97, const char *s1,
+			     const char *s2, const char *suffix)
 {
 	struct snd_kcontrol *kctl1, *kctl2;
 	kctl1 = ctl_find(ac97, s1, suffix);
diff --git a/sound/pci/ac97/ac97_local.h b/sound/pci/ac97/ac97_local.h
index a6244c720a1d..78745c5c6df8 100644
--- a/sound/pci/ac97/ac97_local.h
+++ b/sound/pci/ac97/ac97_local.h
@@ -22,59 +22,8 @@
  *
  */
 
-#define AC97_SINGLE_VALUE(reg,shift,mask,invert) ((reg) | ((shift) << 8) | ((shift) << 12) | ((mask) << 16) | ((invert) << 24))
-#define AC97_PAGE_SINGLE_VALUE(reg,shift,mask,invert,page) (AC97_SINGLE_VALUE(reg,shift,mask,invert) | (1<<25) | ((page) << 26))
-#define AC97_SINGLE(xname, reg, shift, mask, invert) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_info_volsw, \
-  .get = snd_ac97_get_volsw, .put = snd_ac97_put_volsw, \
-  .private_value =  AC97_SINGLE_VALUE(reg, shift, mask, invert) }
-#define AC97_PAGE_SINGLE(xname, reg, shift, mask, invert, page)		\
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_info_volsw, \
-  .get = snd_ac97_get_volsw, .put = snd_ac97_put_volsw, \
-  .private_value =  AC97_PAGE_SINGLE_VALUE(reg, shift, mask, invert, page) }
-#define AC97_DOUBLE(xname, reg, shift_left, shift_right, mask, invert) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), .info = snd_ac97_info_volsw, \
-  .get = snd_ac97_get_volsw, .put = snd_ac97_put_volsw, \
-  .private_value = (reg) | ((shift_left) << 8) | ((shift_right) << 12) | ((mask) << 16) | ((invert) << 24) }
-
-/* enum control */
-struct ac97_enum {
-	unsigned char reg;
-	unsigned char shift_l;
-	unsigned char shift_r;
-	unsigned short mask;
-	const char **texts;
-};
-
-#define AC97_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xtexts) \
-{ .reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \
-  .mask = xmask, .texts = xtexts }
-#define AC97_ENUM_SINGLE(xreg, xshift, xmask, xtexts) \
-	AC97_ENUM_DOUBLE(xreg, xshift, xshift, xmask, xtexts)
-#define AC97_ENUM(xname, xenum) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_info_enum_double, \
-  .get = snd_ac97_get_enum_double, .put = snd_ac97_put_enum_double, \
-  .private_value = (unsigned long)&xenum }
-
-/* ac97_codec.c */
-extern const struct snd_kcontrol_new snd_ac97_controls_3d[];
-extern const struct snd_kcontrol_new snd_ac97_controls_spdif[];
-struct snd_kcontrol *snd_ac97_cnew(const struct snd_kcontrol_new *_template, struct snd_ac97 * ac97);
-void snd_ac97_get_name(struct snd_ac97 *ac97, unsigned int id, char *name, int modem);
-int snd_ac97_info_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo);
-int snd_ac97_get_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
-int snd_ac97_put_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
-int snd_ac97_try_bit(struct snd_ac97 * ac97, int reg, int bit);
-int snd_ac97_remove_ctl(struct snd_ac97 *ac97, const char *name, const char *suffix);
-int snd_ac97_rename_ctl(struct snd_ac97 *ac97, const char *src, const char *dst, const char *suffix);
-int snd_ac97_swap_ctl(struct snd_ac97 *ac97, const char *s1, const char *s2, const char *suffix);
-void snd_ac97_rename_vol_ctl(struct snd_ac97 *ac97, const char *src, const char *dst);
-void snd_ac97_restore_status(struct snd_ac97 *ac97);
-void snd_ac97_restore_iec958(struct snd_ac97 *ac97);
-int snd_ac97_info_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo);
-int snd_ac97_get_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
-int snd_ac97_put_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
-
+void snd_ac97_get_name(struct snd_ac97 *ac97, unsigned int id, char *name,
+		       int modem);
 int snd_ac97_update_bits_nolock(struct snd_ac97 *ac97, unsigned short reg,
 				unsigned short mask, unsigned short value);
 
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c
index b188a4df58cb..3eac0f86266c 100644
--- a/sound/pci/ac97/ac97_patch.c
+++ b/sound/pci/ac97/ac97_patch.c
@@ -23,20 +23,8 @@
  *
  */
 
-#include <sound/driver.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/mutex.h>
-
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/control.h>
-#include <sound/tlv.h>
-#include <sound/ac97_codec.h>
-#include "ac97_patch.h"
-#include "ac97_id.h"
 #include "ac97_local.h"
+#include "ac97_patch.h"
 
 /*
  *  Chip specific initialization
@@ -390,7 +378,7 @@ static struct snd_ac97_build_ops patch_yamaha_ymf753_ops = {
 	.build_post_spdif = patch_yamaha_ymf753_post_spdif
 };
 
-int patch_yamaha_ymf753(struct snd_ac97 * ac97)
+static int patch_yamaha_ymf753(struct snd_ac97 * ac97)
 {
 	/* Patch for Yamaha YMF753, Copyright (c) by David Shust, dshust@shustring.com.
 	   This chip has nonstandard and extended behaviour with regard to its S/PDIF output.
@@ -436,7 +424,7 @@ static struct snd_ac97_build_ops patch_wolfson_wm9703_ops = {
 	.build_specific = patch_wolfson_wm9703_specific,
 };
 
-int patch_wolfson03(struct snd_ac97 * ac97)
+static int patch_wolfson03(struct snd_ac97 * ac97)
 {
 	ac97->build_ops = &patch_wolfson_wm9703_ops;
 	return 0;
@@ -467,7 +455,7 @@ static struct snd_ac97_build_ops patch_wolfson_wm9704_ops = {
 	.build_specific = patch_wolfson_wm9704_specific,
 };
 
-int patch_wolfson04(struct snd_ac97 * ac97)
+static int patch_wolfson04(struct snd_ac97 * ac97)
 {
 	/* WM9704M/9704Q */
 	ac97->build_ops = &patch_wolfson_wm9704_ops;
@@ -489,7 +477,7 @@ static struct snd_ac97_build_ops patch_wolfson_wm9705_ops = {
 	.build_specific = patch_wolfson_wm9705_specific,
 };
 
-int patch_wolfson05(struct snd_ac97 * ac97)
+static int patch_wolfson05(struct snd_ac97 * ac97)
 {
 	/* WM9705, WM9710 */
 	ac97->build_ops = &patch_wolfson_wm9705_ops;
@@ -625,7 +613,7 @@ static struct snd_ac97_build_ops patch_wolfson_wm9711_ops = {
 	.build_specific = patch_wolfson_wm9711_specific,
 };
 
-int patch_wolfson11(struct snd_ac97 * ac97)
+static int patch_wolfson11(struct snd_ac97 * ac97)
 {
 	/* WM9711, WM9712 */
 	ac97->build_ops = &patch_wolfson_wm9711_ops;
@@ -824,7 +812,7 @@ static struct snd_ac97_build_ops patch_wolfson_wm9713_ops = {
 #endif
 };
 
-int patch_wolfson13(struct snd_ac97 * ac97)
+static int patch_wolfson13(struct snd_ac97 * ac97)
 {
 	/* WM9713, WM9714 */
 	ac97->build_ops = &patch_wolfson_wm9713_ops;
@@ -844,7 +832,7 @@ int patch_wolfson13(struct snd_ac97 * ac97)
 /*
  * Tritech codec
  */
-int patch_tritech_tr28028(struct snd_ac97 * ac97)
+static int patch_tritech_tr28028(struct snd_ac97 * ac97)
 {
 	snd_ac97_write_cache(ac97, 0x26, 0x0300);
 	snd_ac97_write_cache(ac97, 0x26, 0x0000);
@@ -922,7 +910,7 @@ static struct snd_ac97_build_ops patch_sigmatel_stac9700_ops = {
 	.build_specific	= patch_sigmatel_stac97xx_specific
 };
 
-int patch_sigmatel_stac9700(struct snd_ac97 * ac97)
+static int patch_sigmatel_stac9700(struct snd_ac97 * ac97)
 {
 	ac97->build_ops = &patch_sigmatel_stac9700_ops;
 	return 0;
@@ -969,7 +957,7 @@ static struct snd_ac97_build_ops patch_sigmatel_stac9708_ops = {
 	.build_specific	= patch_sigmatel_stac9708_specific
 };
 
-int patch_sigmatel_stac9708(struct snd_ac97 * ac97)
+static int patch_sigmatel_stac9708(struct snd_ac97 * ac97)
 {
 	unsigned int codec72, codec6c;
 
@@ -995,7 +983,7 @@ int patch_sigmatel_stac9708(struct snd_ac97 * ac97)
 	return 0;
 }
 
-int patch_sigmatel_stac9721(struct snd_ac97 * ac97)
+static int patch_sigmatel_stac9721(struct snd_ac97 * ac97)
 {
 	ac97->build_ops = &patch_sigmatel_stac9700_ops;
 	if (snd_ac97_read(ac97, AC97_SIGMATEL_ANALOG) == 0) {
@@ -1009,7 +997,7 @@ int patch_sigmatel_stac9721(struct snd_ac97 * ac97)
 	return 0;
 }
 
-int patch_sigmatel_stac9744(struct snd_ac97 * ac97)
+static int patch_sigmatel_stac9744(struct snd_ac97 * ac97)
 {
 	// patch for SigmaTel
 	ac97->build_ops = &patch_sigmatel_stac9700_ops;
@@ -1021,7 +1009,7 @@ int patch_sigmatel_stac9744(struct snd_ac97 * ac97)
 	return 0;
 }
 
-int patch_sigmatel_stac9756(struct snd_ac97 * ac97)
+static int patch_sigmatel_stac9756(struct snd_ac97 * ac97)
 {
 	// patch for SigmaTel
 	ac97->build_ops = &patch_sigmatel_stac9700_ops;
@@ -1198,7 +1186,7 @@ static struct snd_ac97_build_ops patch_sigmatel_stac9758_ops = {
 	.build_specific	= patch_sigmatel_stac9758_specific
 };
 
-int patch_sigmatel_stac9758(struct snd_ac97 * ac97)
+static int patch_sigmatel_stac9758(struct snd_ac97 * ac97)
 {
 	static unsigned short regs[4] = {
 		AC97_SIGMATEL_OUTSEL,
@@ -1272,7 +1260,7 @@ static struct snd_ac97_build_ops patch_cirrus_ops = {
 	.build_spdif = patch_cirrus_build_spdif
 };
 
-int patch_cirrus_spdif(struct snd_ac97 * ac97)
+static int patch_cirrus_spdif(struct snd_ac97 * ac97)
 {
 	/* Basically, the cs4201/cs4205/cs4297a has non-standard sp/dif registers.
 	   WHY CAN'T ANYONE FOLLOW THE BLOODY SPEC?  *sigh*
@@ -1293,7 +1281,7 @@ int patch_cirrus_spdif(struct snd_ac97 * ac97)
 	return 0;
 }
 
-int patch_cirrus_cs4299(struct snd_ac97 * ac97)
+static int patch_cirrus_cs4299(struct snd_ac97 * ac97)
 {
 	/* force the detection of PC Beep */
 	ac97->flags |= AC97_HAS_PC_BEEP;
@@ -1329,7 +1317,7 @@ static struct snd_ac97_build_ops patch_conexant_ops = {
 	.build_spdif = patch_conexant_build_spdif
 };
 
-int patch_conexant(struct snd_ac97 * ac97)
+static int patch_conexant(struct snd_ac97 * ac97)
 {
 	ac97->build_ops = &patch_conexant_ops;
 	ac97->flags |= AC97_CX_SPDIF;
@@ -1338,7 +1326,7 @@ int patch_conexant(struct snd_ac97 * ac97)
 	return 0;
 }
 
-int patch_cx20551(struct snd_ac97 *ac97)
+static int patch_cx20551(struct snd_ac97 *ac97)
 {
 	snd_ac97_update_bits(ac97, 0x5c, 0x01, 0x01);
 	return 0;
@@ -1430,7 +1418,7 @@ static const struct snd_ac97_res_table ad1819_restbl[] = {
 	{ } /* terminator */
 };
 
-int patch_ad1819(struct snd_ac97 * ac97)
+static int patch_ad1819(struct snd_ac97 * ac97)
 {
 	unsigned short scfg;
 
@@ -1507,7 +1495,7 @@ static struct snd_ac97_build_ops patch_ad1881_build_ops = {
 #endif
 };
 
-int patch_ad1881(struct snd_ac97 * ac97)
+static int patch_ad1881(struct snd_ac97 * ac97)
 {
 	static const char cfg_idxs[3][2] = {
 		{2, 1},
@@ -1595,7 +1583,7 @@ static struct snd_ac97_build_ops patch_ad1885_build_ops = {
 #endif
 };
 
-int patch_ad1885(struct snd_ac97 * ac97)
+static int patch_ad1885(struct snd_ac97 * ac97)
 {
 	patch_ad1881(ac97);
 	/* This is required to deal with the Intel D815EEAL2 */
@@ -1622,7 +1610,7 @@ static struct snd_ac97_build_ops patch_ad1886_build_ops = {
 #endif
 };
 
-int patch_ad1886(struct snd_ac97 * ac97)
+static int patch_ad1886(struct snd_ac97 * ac97)
 {
 	patch_ad1881(ac97);
 	/* Presario700 workaround */
@@ -1844,7 +1832,7 @@ static void check_ad1981_hp_jack_sense(struct snd_ac97 *ac97)
 		snd_ac97_update_bits(ac97, AC97_AD_JACK_SPDIF, 1<<11, 1<<11);
 }
 
-int patch_ad1981a(struct snd_ac97 *ac97)
+static int patch_ad1981a(struct snd_ac97 *ac97)
 {
 	patch_ad1881(ac97);
 	ac97->build_ops = &patch_ad1981a_build_ops;
@@ -1877,7 +1865,7 @@ static struct snd_ac97_build_ops patch_ad1981b_build_ops = {
 #endif
 };
 
-int patch_ad1981b(struct snd_ac97 *ac97)
+static int patch_ad1981b(struct snd_ac97 *ac97)
 {
 	patch_ad1881(ac97);
 	ac97->build_ops = &patch_ad1981b_build_ops;
@@ -2014,7 +2002,7 @@ static struct snd_ac97_build_ops patch_ad1888_build_ops = {
 	.update_jacks = ad1888_update_jacks,
 };
 
-int patch_ad1888(struct snd_ac97 * ac97)
+static int patch_ad1888(struct snd_ac97 * ac97)
 {
 	unsigned short misc;
 	
@@ -2052,7 +2040,7 @@ static struct snd_ac97_build_ops patch_ad1980_build_ops = {
 	.update_jacks = ad1888_update_jacks,
 };
 
-int patch_ad1980(struct snd_ac97 * ac97)
+static int patch_ad1980(struct snd_ac97 * ac97)
 {
 	patch_ad1888(ac97);
 	ac97->build_ops = &patch_ad1980_build_ops;
@@ -2168,7 +2156,7 @@ static struct snd_ac97_build_ops patch_ad1985_build_ops = {
 	.update_jacks = ad1985_update_jacks,
 };
 
-int patch_ad1985(struct snd_ac97 * ac97)
+static int patch_ad1985(struct snd_ac97 * ac97)
 {
 	unsigned short misc;
 	
@@ -2468,7 +2456,7 @@ static struct snd_ac97_build_ops patch_ad1986_build_ops = {
 	.update_jacks = ad1986_update_jacks,
 };
 
-int patch_ad1986(struct snd_ac97 * ac97)
+static int patch_ad1986(struct snd_ac97 * ac97)
 {
 	patch_ad1881(ac97);
 	ac97->build_ops = &patch_ad1986_build_ops;
@@ -2561,7 +2549,7 @@ static struct snd_ac97_build_ops patch_alc650_ops = {
 	.update_jacks = alc650_update_jacks
 };
 
-int patch_alc650(struct snd_ac97 * ac97)
+static int patch_alc650(struct snd_ac97 * ac97)
 {
 	unsigned short val;
 
@@ -2713,7 +2701,7 @@ static struct snd_ac97_build_ops patch_alc655_ops = {
 	.update_jacks = alc655_update_jacks
 };
 
-int patch_alc655(struct snd_ac97 * ac97)
+static int patch_alc655(struct snd_ac97 * ac97)
 {
 	unsigned int val;
 
@@ -2739,6 +2727,7 @@ int patch_alc655(struct snd_ac97 * ac97)
 		    (ac97->subsystem_device == 0x0131 || /* MSI S270 laptop */
 		     ac97->subsystem_device == 0x0161 || /* LG K1 Express */
 		     ac97->subsystem_device == 0x0351 || /* MSI L725 laptop */
+		     ac97->subsystem_device == 0x0471 || /* MSI L720 laptop */
 		     ac97->subsystem_device == 0x0061))  /* MSI S250 laptop */
 			val &= ~(1 << 1); /* Pin 47 is EAPD (for internal speaker) */
 		else
@@ -2815,7 +2804,7 @@ static struct snd_ac97_build_ops patch_alc850_ops = {
 	.update_jacks = alc850_update_jacks
 };
 
-int patch_alc850(struct snd_ac97 *ac97)
+static int patch_alc850(struct snd_ac97 *ac97)
 {
 	ac97->build_ops = &patch_alc850_ops;
 
@@ -2875,7 +2864,7 @@ static struct snd_ac97_build_ops patch_cm9738_ops = {
 	.update_jacks = cm9738_update_jacks
 };
 
-int patch_cm9738(struct snd_ac97 * ac97)
+static int patch_cm9738(struct snd_ac97 * ac97)
 {
 	ac97->build_ops = &patch_cm9738_ops;
 	/* FIXME: can anyone confirm below? */
@@ -2967,7 +2956,7 @@ static struct snd_ac97_build_ops patch_cm9739_ops = {
 	.update_jacks = cm9739_update_jacks
 };
 
-int patch_cm9739(struct snd_ac97 * ac97)
+static int patch_cm9739(struct snd_ac97 * ac97)
 {
 	unsigned short val;
 
@@ -3141,7 +3130,7 @@ static struct snd_ac97_build_ops patch_cm9761_ops = {
 	.update_jacks = cm9761_update_jacks
 };
 
-int patch_cm9761(struct snd_ac97 *ac97)
+static int patch_cm9761(struct snd_ac97 *ac97)
 {
 	unsigned short val;
 
@@ -3236,7 +3225,7 @@ static struct snd_ac97_build_ops patch_cm9780_ops = {
 	.build_post_spdif = patch_cm9761_post_spdif	/* identical with CM9761 */
 };
 
-int patch_cm9780(struct snd_ac97 *ac97)
+static int patch_cm9780(struct snd_ac97 *ac97)
 {
 	unsigned short val;
 
@@ -3279,7 +3268,7 @@ static struct snd_ac97_build_ops patch_vt1616_ops = {
 	.build_specific	= patch_vt1616_specific
 };
 
-int patch_vt1616(struct snd_ac97 * ac97)
+static int patch_vt1616(struct snd_ac97 * ac97)
 {
 	ac97->build_ops = &patch_vt1616_ops;
 	return 0;
@@ -3288,16 +3277,111 @@ int patch_vt1616(struct snd_ac97 * ac97)
 /*
  * VT1617A codec
  */
+
+/*
+ * unfortunately, the vt1617a stashes the twiddlers required for
+ * nooding the i/o jacks on 2 different regs. * thameans that we cant
+ * use the easy way provided by AC97_ENUM_DOUBLE() we have to write
+ * are own funcs.
+ *
+ * NB: this is absolutely and utterly different from the vt1618. dunno
+ * about the 1616.
+ */
+
+/* copied from ac97_surround_jack_mode_info() */
+static int snd_ac97_vt1617a_smart51_info(struct snd_kcontrol *kcontrol,
+					 struct snd_ctl_elem_info *uinfo)
+{
+	/* ordering in this list reflects vt1617a docs for Reg 20 and
+	 * 7a and Table 6 that lays out the matrix NB WRT Table6: SM51
+	 * is SM51EN *AND* it's Bit14, not Bit15 so the table is very
+	 * counter-intuitive */ 
+
+	static const char* texts[] = { "LineIn Mic1", "LineIn Mic1 Mic3",
+				       "Surr LFE/C Mic3", "LineIn LFE/C Mic3",
+				       "LineIn Mic2", "LineIn Mic2 Mic1",
+				       "Surr LFE Mic1", "Surr LFE Mic1 Mic2"};
+	return ac97_enum_text_info(kcontrol, uinfo, texts, 8);
+}
+
+static int snd_ac97_vt1617a_smart51_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	ushort usSM51, usMS;  
+
+	struct snd_ac97 *pac97;
+	
+	pac97 = snd_kcontrol_chip(kcontrol); /* grab codec handle */
+
+	/* grab our desirec bits, then mash them together in a manner
+	 * consistent with Table 6 on page 17 in the 1617a docs */
+ 
+	usSM51 = snd_ac97_read(pac97, 0x7a) >> 14;
+	usMS   = snd_ac97_read(pac97, 0x20) >> 8;
+  
+	ucontrol->value.enumerated.item[0] = (usSM51 << 1) + usMS;
+
+	return 0;
+}
+
+static int snd_ac97_vt1617a_smart51_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	ushort usSM51, usMS, usReg;  
+
+	struct snd_ac97 *pac97;
+
+	pac97 = snd_kcontrol_chip(kcontrol); /* grab codec handle */
+
+	usSM51 = ucontrol->value.enumerated.item[0] >> 1;
+	usMS   = ucontrol->value.enumerated.item[0] &  1;
+
+	/* push our values into the register - consider that things will be left
+	 * in a funky state if the write fails */
+
+	usReg = snd_ac97_read(pac97, 0x7a);
+	snd_ac97_write_cache(pac97, 0x7a, (usReg & 0x3FFF) + (usSM51 << 14));
+	usReg = snd_ac97_read(pac97, 0x20);
+	snd_ac97_write_cache(pac97, 0x20, (usReg & 0xFEFF) + (usMS   <<  8));
+
+	return 0;
+}
+
+static const struct snd_kcontrol_new snd_ac97_controls_vt1617a[] = {
+
+	AC97_SINGLE("Center/LFE Exchange", 0x5a, 8, 1, 0),
+	/*
+	 * These are used to enable/disable surround sound on motherboards
+	 * that have 3 bidirectional analog jacks
+	 */
+	{
+		.iface         = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name          = "Smart 5.1 Select",
+		.info          = snd_ac97_vt1617a_smart51_info,
+		.get           = snd_ac97_vt1617a_smart51_get,
+		.put           = snd_ac97_vt1617a_smart51_put,
+	},
+};
+
 int patch_vt1617a(struct snd_ac97 * ac97)
 {
-	/* bring analog power consumption to normal, like WinXP driver
-	 * for EPIA SP
+	int err = 0;
+
+	/* we choose to not fail out at this point, but we tell the
+	   caller when we return */
+
+	err = patch_build_controls(ac97, &snd_ac97_controls_vt1617a[0],
+				   ARRAY_SIZE(snd_ac97_controls_vt1617a));
+
+	/* bring analog power consumption to normal by turning off the
+	 * headphone amplifier, like WinXP driver for EPIA SP
 	 */
 	snd_ac97_write_cache(ac97, 0x5c, 0x20);
 	ac97->ext_id |= AC97_EI_SPDIF;	/* force the detection of spdif */
 	ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000;
 	ac97->build_ops = &patch_vt1616_ops;
-	return 0;
+
+	return err;
 }
 
 /*
@@ -3338,7 +3422,7 @@ static struct snd_ac97_build_ops patch_it2646_ops = {
 	.update_jacks = it2646_update_jacks
 };
 
-int patch_it2646(struct snd_ac97 * ac97)
+static int patch_it2646(struct snd_ac97 * ac97)
 {
 	ac97->build_ops = &patch_it2646_ops;
 	/* full DAC volume */
@@ -3371,7 +3455,7 @@ static struct snd_ac97_build_ops patch_si3036_ops = {
 	.build_specific	= patch_si3036_specific,
 };
 
-int mpatch_si3036(struct snd_ac97 * ac97)
+static int mpatch_si3036(struct snd_ac97 * ac97)
 {
 	ac97->build_ops = &patch_si3036_ops;
 	snd_ac97_write_cache(ac97, 0x5c, 0xf210 );
@@ -3403,7 +3487,7 @@ static struct snd_ac97_res_table lm4550_restbl[] = {
 	{ } /* terminator */
 };
 
-int patch_lm4550(struct snd_ac97 *ac97)
+static int patch_lm4550(struct snd_ac97 *ac97)
 {
 	ac97->res_table = lm4550_restbl;
 	return 0;
@@ -3438,7 +3522,7 @@ static struct snd_ac97_build_ops patch_ucb1400_ops = {
 	.build_specific	= patch_ucb1400_specific,
 };
 
-int patch_ucb1400(struct snd_ac97 * ac97)
+static int patch_ucb1400(struct snd_ac97 * ac97)
 {
 	ac97->build_ops = &patch_ucb1400_ops;
 	/* enable headphone driver and smart low power mode by default */
diff --git a/sound/pci/ac97/ac97_patch.h b/sound/pci/ac97/ac97_patch.h
index 555d1c9a98fd..fd341ce63762 100644
--- a/sound/pci/ac97/ac97_patch.h
+++ b/sound/pci/ac97/ac97_patch.h
@@ -22,44 +22,72 @@
  *
  */
 
-int patch_yamaha_ymf753(struct snd_ac97 * ac97);
-int patch_wolfson00(struct snd_ac97 * ac97);
-int patch_wolfson03(struct snd_ac97 * ac97);
-int patch_wolfson04(struct snd_ac97 * ac97);
-int patch_wolfson05(struct snd_ac97 * ac97);
-int patch_wolfson11(struct snd_ac97 * ac97);
-int patch_wolfson13(struct snd_ac97 * ac97);
-int patch_tritech_tr28028(struct snd_ac97 * ac97);
-int patch_sigmatel_stac9700(struct snd_ac97 * ac97);
-int patch_sigmatel_stac9708(struct snd_ac97 * ac97);
-int patch_sigmatel_stac9721(struct snd_ac97 * ac97);
-int patch_sigmatel_stac9744(struct snd_ac97 * ac97);
-int patch_sigmatel_stac9756(struct snd_ac97 * ac97);
-int patch_sigmatel_stac9758(struct snd_ac97 * ac97);
-int patch_cirrus_cs4299(struct snd_ac97 * ac97);
-int patch_cirrus_spdif(struct snd_ac97 * ac97);
-int patch_conexant(struct snd_ac97 * ac97);
-int patch_cx20551(struct snd_ac97 * ac97);
-int patch_ad1819(struct snd_ac97 * ac97);
-int patch_ad1881(struct snd_ac97 * ac97);
-int patch_ad1885(struct snd_ac97 * ac97);
-int patch_ad1886(struct snd_ac97 * ac97);
-int patch_ad1888(struct snd_ac97 * ac97);
-int patch_ad1980(struct snd_ac97 * ac97);
-int patch_ad1981a(struct snd_ac97 * ac97);
-int patch_ad1981b(struct snd_ac97 * ac97);
-int patch_ad1985(struct snd_ac97 * ac97);
-int patch_ad1986(struct snd_ac97 * ac97);
-int patch_alc650(struct snd_ac97 * ac97);
-int patch_alc655(struct snd_ac97 * ac97);
-int patch_alc850(struct snd_ac97 * ac97);
-int patch_cm9738(struct snd_ac97 * ac97);
-int patch_cm9739(struct snd_ac97 * ac97);
-int patch_cm9761(struct snd_ac97 * ac97);
-int patch_cm9780(struct snd_ac97 * ac97);
-int patch_vt1616(struct snd_ac97 * ac97);
-int patch_vt1617a(struct snd_ac97 * ac97);
-int patch_it2646(struct snd_ac97 * ac97);
-int patch_ucb1400(struct snd_ac97 * ac97);
-int mpatch_si3036(struct snd_ac97 * ac97);
-int patch_lm4550(struct snd_ac97 * ac97);
+#define AC97_SINGLE_VALUE(reg,shift,mask,invert) \
+	((reg) | ((shift) << 8) | ((shift) << 12) | ((mask) << 16) | \
+	 ((invert) << 24))
+#define AC97_PAGE_SINGLE_VALUE(reg,shift,mask,invert,page) \
+	(AC97_SINGLE_VALUE(reg,shift,mask,invert) | (1<<25) | ((page) << 26))
+#define AC97_SINGLE(xname, reg, shift, mask, invert) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+  .info = snd_ac97_info_volsw,		\
+  .get = snd_ac97_get_volsw, .put = snd_ac97_put_volsw, \
+  .private_value =  AC97_SINGLE_VALUE(reg, shift, mask, invert) }
+#define AC97_PAGE_SINGLE(xname, reg, shift, mask, invert, page)		\
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+  .info = snd_ac97_info_volsw,		\
+  .get = snd_ac97_get_volsw, .put = snd_ac97_put_volsw, \
+  .private_value =  AC97_PAGE_SINGLE_VALUE(reg, shift, mask, invert, page) }
+#define AC97_DOUBLE(xname, reg, shift_left, shift_right, mask, invert) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
+  .info = snd_ac97_info_volsw,		\
+  .get = snd_ac97_get_volsw, .put = snd_ac97_put_volsw, \
+  .private_value = (reg) | ((shift_left) << 8) | ((shift_right) << 12) | ((mask) << 16) | ((invert) << 24) }
+
+/* enum control */
+struct ac97_enum {
+	unsigned char reg;
+	unsigned char shift_l;
+	unsigned char shift_r;
+	unsigned short mask;
+	const char **texts;
+};
+
+#define AC97_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xtexts) \
+{ .reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \
+  .mask = xmask, .texts = xtexts }
+#define AC97_ENUM_SINGLE(xreg, xshift, xmask, xtexts) \
+	AC97_ENUM_DOUBLE(xreg, xshift, xshift, xmask, xtexts)
+#define AC97_ENUM(xname, xenum) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+  .info = snd_ac97_info_enum_double,		    \
+  .get = snd_ac97_get_enum_double, .put = snd_ac97_put_enum_double, \
+  .private_value = (unsigned long)&xenum }
+
+/* ac97_codec.c */
+static const struct snd_kcontrol_new snd_ac97_controls_3d[];
+static const struct snd_kcontrol_new snd_ac97_controls_spdif[];
+static struct snd_kcontrol *snd_ac97_cnew(const struct snd_kcontrol_new *_template,
+					  struct snd_ac97 * ac97);
+static int snd_ac97_info_volsw(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_info *uinfo);
+static int snd_ac97_get_volsw(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_value *ucontrol);
+static int snd_ac97_put_volsw(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_value *ucontrol);
+static int snd_ac97_try_bit(struct snd_ac97 * ac97, int reg, int bit);
+static int snd_ac97_remove_ctl(struct snd_ac97 *ac97, const char *name,
+			       const char *suffix);
+static int snd_ac97_rename_ctl(struct snd_ac97 *ac97, const char *src,
+			       const char *dst, const char *suffix);
+static int snd_ac97_swap_ctl(struct snd_ac97 *ac97, const char *s1,
+			     const char *s2, const char *suffix);
+static void snd_ac97_rename_vol_ctl(struct snd_ac97 *ac97, const char *src,
+				    const char *dst);
+static void snd_ac97_restore_status(struct snd_ac97 *ac97);
+static void snd_ac97_restore_iec958(struct snd_ac97 *ac97);
+static int snd_ac97_info_enum_double(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_info *uinfo);
+static int snd_ac97_get_enum_double(struct snd_kcontrol *kcontrol,
+				    struct snd_ctl_elem_value *ucontrol);
+static int snd_ac97_put_enum_double(struct snd_kcontrol *kcontrol,
+				    struct snd_ctl_elem_value *ucontrol);
diff --git a/sound/pci/ac97/ac97_pcm.c b/sound/pci/ac97/ac97_pcm.c
index 3758d07182f8..4281e6d0c5b6 100644
--- a/sound/pci/ac97/ac97_pcm.c
+++ b/sound/pci/ac97/ac97_pcm.c
@@ -34,7 +34,6 @@
 #include <sound/control.h>
 #include <sound/ac97_codec.h>
 #include <sound/asoundef.h>
-#include "ac97_patch.h"
 #include "ac97_id.h"
 #include "ac97_local.h"
 
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c
index ba7fa22b285d..e1ed59549c50 100644
--- a/sound/pci/ali5451/ali5451.c
+++ b/sound/pci/ali5451/ali5451.c
@@ -69,10 +69,10 @@ module_param(enable, bool, 0444);
  *  Debug part definitions
  */
 
-//#define ALI_DEBUG
+/* #define ALI_DEBUG */
 
 #ifdef ALI_DEBUG
-#define snd_ali_printk(format, args...) printk(format, ##args);
+#define snd_ali_printk(format, args...) printk(KERN_DEBUG format, ##args);
 #else
 #define snd_ali_printk(format, args...)
 #endif
@@ -105,10 +105,10 @@ module_param(enable, bool, 0444);
  *  Direct Registers
  */
 
-#define ALI_LEGACY_DMAR0        0x00  // ADR0
-#define ALI_LEGACY_DMAR4        0x04  // CNT0
-#define ALI_LEGACY_DMAR11       0x0b  // MOD 
-#define ALI_LEGACY_DMAR15       0x0f  // MMR 
+#define ALI_LEGACY_DMAR0        0x00  /* ADR0 */
+#define ALI_LEGACY_DMAR4        0x04  /* CNT0 */
+#define ALI_LEGACY_DMAR11       0x0b  /* MOD  */
+#define ALI_LEGACY_DMAR15       0x0f  /* MMR  */
 #define ALI_MPUR0		0x20
 #define ALI_MPUR1		0x21
 #define ALI_MPUR2		0x22
@@ -175,7 +175,7 @@ struct snd_ali;
 struct snd_ali_voice;
 
 struct snd_ali_channel_control {
-	// register data
+	/* register data */
 	struct REGDATA {
 		unsigned int start;
 		unsigned int stop;
@@ -183,7 +183,7 @@ struct snd_ali_channel_control {
 		unsigned int ainten;
 	} data;
 		
-	// register addresses
+	/* register addresses */
 	struct REGS {
 		unsigned int start;
 		unsigned int stop;
@@ -197,19 +197,18 @@ struct snd_ali_channel_control {
 
 struct snd_ali_voice {
 	unsigned int number;
-	unsigned int use: 1,
-	    pcm: 1,
-	    midi: 1,
-	    mode: 1,
-	    synth: 1;
+	unsigned int use :1,
+		pcm :1,
+		midi :1,
+		mode :1,
+		synth :1,
+		running :1;
 
 	/* PCM data */
 	struct snd_ali *codec;
 	struct snd_pcm_substream *substream;
 	struct snd_ali_voice *extra;
 	
-	unsigned int running: 1;
-
 	int eso;                /* final ESO value for channel */
 	int count;              /* runtime->period_size */
 
@@ -231,14 +230,12 @@ struct snd_alidev {
 };
 
 
-#ifdef CONFIG_PM
 #define ALI_GLOBAL_REGS		56
 #define ALI_CHANNEL_REGS	8
 struct snd_ali_image {
-	unsigned long regs[ALI_GLOBAL_REGS];
-	unsigned long channel_regs[ALI_CHANNELS][ALI_CHANNEL_REGS];
+	u32 regs[ALI_GLOBAL_REGS];
+	u32 channel_regs[ALI_CHANNELS][ALI_CHANNEL_REGS];
 };
-#endif
 
 
 struct snd_ali {
@@ -246,8 +243,8 @@ struct snd_ali {
 	unsigned long	port;
 	unsigned char	revision;
 
-	unsigned int hw_initialized: 1;
-	unsigned int spdif_support: 1;
+	unsigned int hw_initialized :1;
+	unsigned int spdif_support :1;
 
 	struct pci_dev	*pci;
 	struct pci_dev	*pci_m1533;
@@ -287,108 +284,28 @@ MODULE_DEVICE_TABLE(pci, snd_ali_ids);
 
 static void snd_ali_clear_voices(struct snd_ali *, unsigned int, unsigned int);
 static unsigned short snd_ali_codec_peek(struct snd_ali *, int, unsigned short);
-static void snd_ali_codec_poke(struct snd_ali *, int, unsigned short, unsigned short);
-
-/*
- *  Debug Part
- */
-
-#ifdef ALI_DEBUG
-
-static void ali_read_regs(struct snd_ali *codec, int channel)
-{
-	int i,j;
-	unsigned int dwVal;
-
-	printk("channel %d registers map:\n", channel);
-	outb((unsigned char)(channel & 0x001f), ALI_REG(codec,ALI_GC_CIR));
-
-	printk("    ");
-	for(j=0;j<8;j++)
-		printk("%2.2x       ", j*4);
-	printk("\n");
-
-	for (i=0; i<=0xf8/4;i++) {
-		if(i%8 == 0)
-			printk("%2.2x  ", (i*4/0x10)*0x10);
-		dwVal = inl(ALI_REG(codec,i*4));
-		printk("%8.8x ", dwVal);
-		if ((i+1)%8 == 0)
-			printk("\n");
-	}
-	printk("\n");
-}
-static void ali_read_cfg(unsigned int vendor, unsigned deviceid)
-{
-	unsigned int dwVal;
-	struct pci_dev *pci_dev;
-	int i,j;
-
-	pci_dev = pci_get_device(vendor, deviceid, NULL);
-	if (pci_dev == NULL)
-		return ;
-
-	printk("\nM%x PCI CFG\n", deviceid);
-	printk("    ");
-	for(j=0;j<8;j++)
-		printk("%d        ",j);
-	printk("\n");
-
-	for(i=0;i<8;i++) {
-		printk("%d   ",i);
-		for(j=0;j<8;j++)
-		{
-			pci_read_config_dword(pci_dev, i*0x20+j*4, &dwVal);
-			printk("%8.8x ", dwVal);
-		}
-		printk("\n");
-	}
-	pci_dev_put(pci_dev);
- }
-static void ali_read_ac97regs(struct snd_ali *codec, int secondary)
-{
-	unsigned short i,j;
-	unsigned short wVal;
-
-	printk("\ncodec %d registers map:\n", secondary);
-
-	printk("    ");
-	for(j=0;j<8;j++)
-		printk("%2.2x   ",j*2);
-	printk("\n");
-
-	for (i=0; i<64;i++) {
-		if(i%8 == 0)
-			printk("%2.2x  ", (i/8)*0x10);
-		wVal = snd_ali_codec_peek(codec, secondary, i*2);
-		printk("%4.4x ", wVal);
-		if ((i+1)%8 == 0)
-			printk("\n");
-	}
-	printk("\n");
-}
-
-#endif
+static void snd_ali_codec_poke(struct snd_ali *, int, unsigned short,
+			       unsigned short);
 
 /*
  *  AC97 ACCESS
  */
 
 static inline unsigned int snd_ali_5451_peek(struct snd_ali *codec,
-						unsigned int port )
+					     unsigned int port)
 {
 	return (unsigned int)inl(ALI_REG(codec, port)); 
 }
 
-static inline void snd_ali_5451_poke(	struct snd_ali *codec,
-					unsigned int port,
-					unsigned int val )
+static inline void snd_ali_5451_poke(struct snd_ali *codec,
+				     unsigned int port,
+				     unsigned int val)
 {
 	outl((unsigned int)val, ALI_REG(codec, port));
 }
 
-static int snd_ali_codec_ready(	struct snd_ali *codec,
-				unsigned int port )
+static int snd_ali_codec_ready(struct snd_ali *codec,
+			       unsigned int port)
 {
 	unsigned long end_time;
 	unsigned int res;
@@ -396,7 +313,7 @@ static int snd_ali_codec_ready(	struct snd_ali *codec,
 	end_time = jiffies + msecs_to_jiffies(250);
 	do {
 		res = snd_ali_5451_peek(codec,port);
-		if (! (res & 0x8000))
+		if (!(res & 0x8000))
 			return 0;
 		schedule_timeout_uninterruptible(1);
 	} while (time_after_eq(end_time, jiffies));
@@ -425,11 +342,11 @@ static int snd_ali_stimer_ready(struct snd_ali *codec)
 }
 
 static void snd_ali_codec_poke(struct snd_ali *codec,int secondary,
-				     unsigned short reg,
-				     unsigned short val)
+			       unsigned short reg,
+			       unsigned short val)
 {
-	unsigned int dwVal = 0;
-	unsigned int port = 0;
+	unsigned int dwVal;
+	unsigned int port;
 
 	if (reg >= 0x80) {
 		snd_printk(KERN_ERR "ali_codec_poke: reg(%xh) invalid.\n", reg);
@@ -445,20 +362,22 @@ static void snd_ali_codec_poke(struct snd_ali *codec,int secondary,
 
 	dwVal  = (unsigned int) (reg & 0xff);
 	dwVal |= 0x8000 | (val << 16);
-	if (secondary) dwVal |= 0x0080;
-	if (codec->revision == ALI_5451_V02) dwVal |= 0x0100;
+	if (secondary)
+		dwVal |= 0x0080;
+	if (codec->revision == ALI_5451_V02)
+		dwVal |= 0x0100;
 
-	snd_ali_5451_poke(codec,port,dwVal);
+	snd_ali_5451_poke(codec, port, dwVal);
 
 	return ;
 }
 
-static unsigned short snd_ali_codec_peek( struct snd_ali *codec,
-					  int secondary,
-					  unsigned short reg)
+static unsigned short snd_ali_codec_peek(struct snd_ali *codec,
+					 int secondary,
+					 unsigned short reg)
 {
-	unsigned int dwVal = 0;
-	unsigned int port = 0;
+	unsigned int dwVal;
+	unsigned int port;
 
 	if (reg >= 0x80) {
 		snd_printk(KERN_ERR "ali_codec_peek: reg(%xh) invalid.\n", reg);
@@ -474,7 +393,8 @@ static unsigned short snd_ali_codec_peek( struct snd_ali *codec,
 
 	dwVal  = (unsigned int) (reg & 0xff);
 	dwVal |= 0x8000;				/* bit 15*/
-	if (secondary) dwVal |= 0x0080;
+	if (secondary)
+		dwVal |= 0x0080;
 
 	snd_ali_5451_poke(codec, port, dwVal);
 
@@ -483,7 +403,7 @@ static unsigned short snd_ali_codec_peek( struct snd_ali *codec,
 	if (snd_ali_codec_ready(codec, port) < 0)
 		return ~0;
 	
-	return (snd_ali_5451_peek(codec, port) & 0xffff0000)>>16;
+	return (snd_ali_5451_peek(codec, port) & 0xffff0000) >> 16;
 }
 
 static void snd_ali_codec_write(struct snd_ac97 *ac97,
@@ -493,9 +413,9 @@ static void snd_ali_codec_write(struct snd_ac97 *ac97,
 	struct snd_ali *codec = ac97->private_data;
 
 	snd_ali_printk("codec_write: reg=%xh data=%xh.\n", reg, val);
-	if(reg == AC97_GPIO_STATUS) {
-		outl((val << ALI_AC97_GPIO_DATA_SHIFT)|ALI_AC97_GPIO_ENABLE,
-			ALI_REG(codec, ALI_AC97_GPIO));
+	if (reg == AC97_GPIO_STATUS) {
+		outl((val << ALI_AC97_GPIO_DATA_SHIFT) | ALI_AC97_GPIO_ENABLE,
+		     ALI_REG(codec, ALI_AC97_GPIO));
 		return;
 	}
 	snd_ali_codec_poke(codec, ac97->num, reg, val);
@@ -503,12 +423,13 @@ static void snd_ali_codec_write(struct snd_ac97 *ac97,
 }
 
 
-static unsigned short snd_ali_codec_read(struct snd_ac97 *ac97, unsigned short reg)
+static unsigned short snd_ali_codec_read(struct snd_ac97 *ac97,
+					 unsigned short reg)
 {
 	struct snd_ali *codec = ac97->private_data;
 
 	snd_ali_printk("codec_read reg=%xh.\n", reg);
-	return (snd_ali_codec_peek(codec, ac97->num, reg));
+	return snd_ali_codec_peek(codec, ac97->num, reg);
 }
 
 /*
@@ -517,11 +438,12 @@ static unsigned short snd_ali_codec_read(struct snd_ac97 *ac97, unsigned short r
 
 static int snd_ali_reset_5451(struct snd_ali *codec)
 {
-	struct pci_dev *pci_dev = NULL;
+	struct pci_dev *pci_dev;
 	unsigned short wCount, wReg;
 	unsigned int   dwVal;
 	
-	if ((pci_dev = codec->pci_m1533) != NULL) {
+	pci_dev = codec->pci_m1533;
+	if (pci_dev) {
 		pci_read_config_dword(pci_dev, 0x7c, &dwVal);
 		pci_write_config_dword(pci_dev, 0x7c, dwVal | 0x08000000);
 		udelay(5000);
@@ -541,7 +463,7 @@ static int snd_ali_reset_5451(struct snd_ali *codec)
 	wCount = 200;
 	while(wCount--) {
 		wReg = snd_ali_codec_peek(codec, 0, AC97_POWERDOWN);
-		if((wReg & 0x000f) == 0x000f)
+		if ((wReg & 0x000f) == 0x000f)
 			return 0;
 		udelay(5000);
 	}
@@ -555,8 +477,8 @@ static int snd_ali_reset_5451(struct snd_ali *codec)
 
 static int snd_ali_reset_codec(struct snd_ali *codec)
 {
-	struct pci_dev *pci_dev = NULL;
-	unsigned char bVal = 0;
+	struct pci_dev *pci_dev;
+	unsigned char bVal;
 	unsigned int   dwVal;
 	unsigned short wCount, wReg;
 
@@ -579,9 +501,9 @@ static int snd_ali_reset_codec(struct snd_ali *codec)
 	udelay(15000);
 
 	wCount = 200;
-	while(wCount--) {
+	while (wCount--) {
 		wReg = snd_ali_codec_read(codec->ac97, AC97_POWERDOWN);
-		if((wReg & 0x000f) == 0x000f)
+		if ((wReg & 0x000f) == 0x000f)
 			return 0;
 		udelay(5000);
 	}
@@ -594,25 +516,27 @@ static int snd_ali_reset_codec(struct snd_ali *codec)
  *  ALI 5451 Controller
  */
 
-static void snd_ali_enable_special_channel(struct snd_ali *codec, unsigned int channel)
+static void snd_ali_enable_special_channel(struct snd_ali *codec,
+					   unsigned int channel)
 {
-	unsigned long dwVal = 0;
+	unsigned long dwVal;
 
-	dwVal  = inl(ALI_REG(codec,ALI_GLOBAL_CONTROL));
+	dwVal  = inl(ALI_REG(codec, ALI_GLOBAL_CONTROL));
 	dwVal |= 1 << (channel & 0x0000001f);
-	outl(dwVal, ALI_REG(codec,ALI_GLOBAL_CONTROL));
+	outl(dwVal, ALI_REG(codec, ALI_GLOBAL_CONTROL));
 }
 
-static void snd_ali_disable_special_channel(struct snd_ali *codec, unsigned int channel)
+static void snd_ali_disable_special_channel(struct snd_ali *codec,
+					    unsigned int channel)
 {
-	unsigned long dwVal = 0;
+	unsigned long dwVal;
 
-	dwVal  = inl(ALI_REG(codec,ALI_GLOBAL_CONTROL));
+	dwVal  = inl(ALI_REG(codec, ALI_GLOBAL_CONTROL));
 	dwVal &= ~(1 << (channel & 0x0000001f));
-	outl(dwVal, ALI_REG(codec,ALI_GLOBAL_CONTROL));
+	outl(dwVal, ALI_REG(codec, ALI_GLOBAL_CONTROL));
 }
 
-static void snd_ali_enable_address_interrupt(struct snd_ali * codec)
+static void snd_ali_enable_address_interrupt(struct snd_ali *codec)
 {
 	unsigned int gc;
 
@@ -622,7 +546,7 @@ static void snd_ali_enable_address_interrupt(struct snd_ali * codec)
 	outl( gc, ALI_REG(codec, ALI_GC_CIR));
 }
 
-static void snd_ali_disable_address_interrupt(struct snd_ali * codec)
+static void snd_ali_disable_address_interrupt(struct snd_ali *codec)
 {
 	unsigned int gc;
 
@@ -632,8 +556,9 @@ static void snd_ali_disable_address_interrupt(struct snd_ali * codec)
 	outl(gc, ALI_REG(codec, ALI_GC_CIR));
 }
 
-#if 0 // not used
-static void snd_ali_enable_voice_irq(struct snd_ali *codec, unsigned int channel)
+#if 0 /* not used */
+static void snd_ali_enable_voice_irq(struct snd_ali *codec,
+				     unsigned int channel)
 {
 	unsigned int mask;
 	struct snd_ali_channel_control *pchregs = &(codec->chregs);
@@ -641,13 +566,14 @@ static void snd_ali_enable_voice_irq(struct snd_ali *codec, unsigned int channel
 	snd_ali_printk("enable_voice_irq channel=%d\n",channel);
 	
 	mask = 1 << (channel & 0x1f);
-	pchregs->data.ainten  = inl(ALI_REG(codec,pchregs->regs.ainten));
+	pchregs->data.ainten  = inl(ALI_REG(codec, pchregs->regs.ainten));
 	pchregs->data.ainten |= mask;
-	outl(pchregs->data.ainten,ALI_REG(codec,pchregs->regs.ainten));
+	outl(pchregs->data.ainten, ALI_REG(codec, pchregs->regs.ainten));
 }
 #endif
 
-static void snd_ali_disable_voice_irq(struct snd_ali *codec, unsigned int channel)
+static void snd_ali_disable_voice_irq(struct snd_ali *codec,
+				      unsigned int channel)
 {
 	unsigned int mask;
 	struct snd_ali_channel_control *pchregs = &(codec->chregs);
@@ -655,9 +581,9 @@ static void snd_ali_disable_voice_irq(struct snd_ali *codec, unsigned int channe
 	snd_ali_printk("disable_voice_irq channel=%d\n",channel);
 
 	mask = 1 << (channel & 0x1f);
-	pchregs->data.ainten  = inl(ALI_REG(codec,pchregs->regs.ainten));
+	pchregs->data.ainten  = inl(ALI_REG(codec, pchregs->regs.ainten));
 	pchregs->data.ainten &= ~mask;
-	outl(pchregs->data.ainten,ALI_REG(codec,pchregs->regs.ainten));
+	outl(pchregs->data.ainten, ALI_REG(codec, pchregs->regs.ainten));
 }
 
 static int snd_ali_alloc_pcm_channel(struct snd_ali *codec, int channel)
@@ -665,7 +591,8 @@ static int snd_ali_alloc_pcm_channel(struct snd_ali *codec, int channel)
 	unsigned int idx =  channel & 0x1f;
 
 	if (codec->synth.chcnt >= ALI_CHANNELS){
-		snd_printk(KERN_ERR "ali_alloc_pcm_channel: no free channels.\n");
+		snd_printk(KERN_ERR
+			   "ali_alloc_pcm_channel: no free channels.\n");
 		return -1;
 	}
 
@@ -685,35 +612,41 @@ static int snd_ali_find_free_channel(struct snd_ali * codec, int rec)
 
 	snd_ali_printk("find_free_channel: for %s\n",rec ? "rec" : "pcm");
 
-	// recording
+	/* recording */
 	if (rec) {
 		if (codec->spdif_support &&
-		    (inl(ALI_REG(codec, ALI_GLOBAL_CONTROL)) & ALI_SPDIF_IN_SUPPORT))
+		    (inl(ALI_REG(codec, ALI_GLOBAL_CONTROL)) &
+		     ALI_SPDIF_IN_SUPPORT))
 			idx = ALI_SPDIF_IN_CHANNEL;
 		else
 			idx = ALI_PCM_IN_CHANNEL;
 
-		if ((result = snd_ali_alloc_pcm_channel(codec,idx)) >= 0) {
+		result = snd_ali_alloc_pcm_channel(codec, idx);
+		if (result >= 0)
 			return result;
-		} else {
-			snd_printk(KERN_ERR "ali_find_free_channel: record channel is busy now.\n");
+		else {
+			snd_printk(KERN_ERR "ali_find_free_channel: "
+				   "record channel is busy now.\n");
 			return -1;
 		}
 	}
 
-	//playback...
+	/* playback... */
 	if (codec->spdif_support &&
-	    (inl(ALI_REG(codec, ALI_GLOBAL_CONTROL)) & ALI_SPDIF_OUT_CH_ENABLE)) {
+	    (inl(ALI_REG(codec, ALI_GLOBAL_CONTROL)) &
+	     ALI_SPDIF_OUT_CH_ENABLE)) {
 		idx = ALI_SPDIF_OUT_CHANNEL;
-		if ((result = snd_ali_alloc_pcm_channel(codec,idx)) >= 0) {
+		result = snd_ali_alloc_pcm_channel(codec, idx);
+		if (result >= 0)
 			return result;
-		} else {
-			snd_printk(KERN_ERR "ali_find_free_channel: S/PDIF out channel is in busy now.\n");
-		}
+		else
+			snd_printk(KERN_ERR "ali_find_free_channel: "
+				   "S/PDIF out channel is in busy now.\n");
 	}
 
 	for (idx = 0; idx < ALI_CHANNELS; idx++) {
-		if ((result = snd_ali_alloc_pcm_channel(codec,idx)) >= 0)
+		result = snd_ali_alloc_pcm_channel(codec, idx);
+		if (result >= 0)
 			return result;
 	}
 	snd_printk(KERN_ERR "ali_find_free_channel: no free channels.\n");
@@ -730,7 +663,8 @@ static void snd_ali_free_channel_pcm(struct snd_ali *codec, int channel)
 		return;
 
 	if (!(codec->synth.chmap & (1 << idx))) {
-		snd_printk(KERN_ERR "ali_free_channel_pcm: channel %d is not in use.\n",channel);
+		snd_printk(KERN_ERR "ali_free_channel_pcm: "
+			   "channel %d is not in use.\n", channel);
 		return;
 	} else {
 		codec->synth.chmap &= ~(1 << idx);
@@ -738,8 +672,8 @@ static void snd_ali_free_channel_pcm(struct snd_ali *codec, int channel)
 	}
 }
 
-#if 0 // not used
-static void snd_ali_start_voice(struct snd_ali * codec, unsigned int channel)
+#if 0 /* not used */
+static void snd_ali_start_voice(struct snd_ali *codec, unsigned int channel)
 {
 	unsigned int mask = 1 << (channel & 0x1f);
 	
@@ -748,7 +682,7 @@ static void snd_ali_start_voice(struct snd_ali * codec, unsigned int channel)
 }
 #endif
 
-static void snd_ali_stop_voice(struct snd_ali * codec, unsigned int channel)
+static void snd_ali_stop_voice(struct snd_ali *codec, unsigned int channel)
 {
 	unsigned int mask = 1 << (channel & 0x1f);
 
@@ -768,26 +702,27 @@ static void snd_ali_delay(struct snd_ali *codec,int interval)
 	currenttimer = inl(ALI_REG(codec, ALI_STIMER));
 
 	while (currenttimer < begintimer + interval) {
-		if(snd_ali_stimer_ready(codec) < 0)
+		if (snd_ali_stimer_ready(codec) < 0)
 			break;
 		currenttimer = inl(ALI_REG(codec,  ALI_STIMER));
+		cpu_relax();
 	}
 }
 
 static void snd_ali_detect_spdif_rate(struct snd_ali *codec)
 {
-	u16 wval  = 0;
+	u16 wval;
 	u16 count = 0;
-	u8  bval = 0, R1 = 0, R2 = 0;
+	u8  bval, R1 = 0, R2;
 
-	bval  = inb(ALI_REG(codec,ALI_SPDIF_CTRL + 1));
+	bval  = inb(ALI_REG(codec, ALI_SPDIF_CTRL + 1));
 	bval |= 0x1F;
-	outb(bval,ALI_REG(codec,ALI_SPDIF_CTRL + 1));
+	outb(bval, ALI_REG(codec, ALI_SPDIF_CTRL + 1));
 
-	while (((R1 < 0x0B )||(R1 > 0x0E)) && (R1 != 0x12) && count <= 50000) {
+	while ((R1 < 0x0b || R1 > 0x0e) && R1 != 0x12 && count <= 50000) {
 		count ++;
 		snd_ali_delay(codec, 6);
-		bval = inb(ALI_REG(codec,ALI_SPDIF_CTRL + 1));
+		bval = inb(ALI_REG(codec, ALI_SPDIF_CTRL + 1));
 		R1 = bval & 0x1F;
 	}
 
@@ -801,7 +736,10 @@ static void snd_ali_detect_spdif_rate(struct snd_ali *codec)
 		snd_ali_delay(codec, 6);
 		bval = inb(ALI_REG(codec,ALI_SPDIF_CTRL + 1));
 		R2 = bval & 0x1F;
-		if (R2 != R1) R1 = R2; else break;
+		if (R2 != R1)
+			R1 = R2;
+		else
+			break;
 	}
 
 	if (count > 50000) {
@@ -810,42 +748,45 @@ static void snd_ali_detect_spdif_rate(struct snd_ali *codec)
 	}
 
 	if (R2 >= 0x0b && R2 <= 0x0e) {
-		wval  = inw(ALI_REG(codec,ALI_SPDIF_CTRL + 2));
-		wval &= 0xE0F0;
-		wval |= (u16)0x09 << 8 | (u16)0x05;
-		outw(wval,ALI_REG(codec,ALI_SPDIF_CTRL + 2));
+		wval  = inw(ALI_REG(codec, ALI_SPDIF_CTRL + 2));
+		wval &= 0xe0f0;
+		wval |= (0x09 << 8) | 0x05;
+		outw(wval, ALI_REG(codec, ALI_SPDIF_CTRL + 2));
 
-		bval  = inb(ALI_REG(codec,ALI_SPDIF_CS +3)) & 0xF0;
-		outb(bval|0x02,ALI_REG(codec,ALI_SPDIF_CS + 3));
+		bval  = inb(ALI_REG(codec, ALI_SPDIF_CS + 3)) & 0xf0;
+		outb(bval | 0x02, ALI_REG(codec, ALI_SPDIF_CS + 3));
 	} else if (R2 == 0x12) {
-		wval  = inw(ALI_REG(codec,ALI_SPDIF_CTRL + 2));
-		wval &= 0xE0F0;
-		wval |= (u16)0x0E << 8 | (u16)0x08;
-		outw(wval,ALI_REG(codec,ALI_SPDIF_CTRL + 2));
+		wval  = inw(ALI_REG(codec, ALI_SPDIF_CTRL + 2));
+		wval &= 0xe0f0;
+		wval |= (0x0e << 8) | 0x08;
+		outw(wval, ALI_REG(codec, ALI_SPDIF_CTRL + 2));
 
-		bval  = inb(ALI_REG(codec,ALI_SPDIF_CS +3)) & 0xF0;
-		outb(bval|0x03,ALI_REG(codec,ALI_SPDIF_CS + 3));
+		bval  = inb(ALI_REG(codec,ALI_SPDIF_CS + 3)) & 0xf0;
+		outb(bval | 0x03, ALI_REG(codec, ALI_SPDIF_CS + 3));
 	}
 }
 
 static unsigned int snd_ali_get_spdif_in_rate(struct snd_ali *codec)
 {
-	u32	dwRate = 0;
-	u8	bval = 0;
+	u32	dwRate;
+	u8	bval;
 
-	bval  = inb(ALI_REG(codec,ALI_SPDIF_CTRL));
-	bval &= 0x7F;
+	bval  = inb(ALI_REG(codec, ALI_SPDIF_CTRL));
+	bval &= 0x7f;
 	bval |= 0x40;
-	outb(bval, ALI_REG(codec,ALI_SPDIF_CTRL));
+	outb(bval, ALI_REG(codec, ALI_SPDIF_CTRL));
 
 	snd_ali_detect_spdif_rate(codec);
 
-	bval  = inb(ALI_REG(codec,ALI_SPDIF_CS + 3));
-	bval &= 0x0F;
+	bval  = inb(ALI_REG(codec, ALI_SPDIF_CS + 3));
+	bval &= 0x0f;
 
-	if (bval == 0) dwRate = 44100;
-	if (bval == 1) dwRate = 48000;
-	if (bval == 2) dwRate = 32000;
+	switch (bval) {
+	case 0: dwRate = 44100; break;
+	case 1: dwRate = 48000; break;
+	case 2: dwRate = 32000; break;
+	default: dwRate = 0; break;
+	}
 
 	return dwRate;
 }
@@ -880,20 +821,22 @@ static void snd_ali_disable_spdif_in(struct snd_ali *codec)
 static void snd_ali_set_spdif_out_rate(struct snd_ali *codec, unsigned int rate)
 {
 	unsigned char  bVal;
-	unsigned int  dwRate = 0;
+	unsigned int  dwRate;
 	
-	if (rate == 32000) dwRate = 0x300;
-	if (rate == 44100) dwRate = 0;
-	if (rate == 48000) dwRate = 0x200;
+	switch (rate) {
+	case 32000: dwRate = 0x300; break;
+	case 48000: dwRate = 0x200; break;
+	default: dwRate = 0; break;
+	}
 	
 	bVal  = inb(ALI_REG(codec, ALI_SPDIF_CTRL));
 	bVal &= (unsigned char)(~(1<<6));
 	
-	bVal |= 0x80;		//select right
+	bVal |= 0x80;		/* select right */
 	outb(bVal, ALI_REG(codec, ALI_SPDIF_CTRL));
 	outb(dwRate | 0x20, ALI_REG(codec, ALI_SPDIF_CS + 2));
 	
-	bVal &= (~0x80);	//select left
+	bVal &= ~0x80;	/* select left */
 	outb(bVal, ALI_REG(codec, ALI_SPDIF_CTRL));
 	outw(rate | 0x10, ALI_REG(codec, ALI_SPDIF_CS + 2));
 }
@@ -902,8 +845,7 @@ static void snd_ali_enable_spdif_out(struct snd_ali *codec)
 {
 	unsigned short wVal;
 	unsigned char bVal;
-
-        struct pci_dev *pci_dev = NULL;
+        struct pci_dev *pci_dev;
 
         pci_dev = codec->pci_m1533;
         if (pci_dev == NULL)
@@ -926,17 +868,15 @@ static void snd_ali_enable_spdif_out(struct snd_ali *codec)
 	bVal = inb(ALI_REG(codec, ALI_SPDIF_CTRL));
 	outb(bVal & ALI_SPDIF_OUT_CH_STATUS, ALI_REG(codec, ALI_SPDIF_CTRL));
    
-	{
-   		wVal = inw(ALI_REG(codec, ALI_GLOBAL_CONTROL));
-   		wVal |= ALI_SPDIF_OUT_SEL_PCM;
-   		outw(wVal, ALI_REG(codec, ALI_GLOBAL_CONTROL));
-		snd_ali_disable_special_channel(codec,ALI_SPDIF_OUT_CHANNEL);
-   	}
+	wVal = inw(ALI_REG(codec, ALI_GLOBAL_CONTROL));
+	wVal |= ALI_SPDIF_OUT_SEL_PCM;
+	outw(wVal, ALI_REG(codec, ALI_GLOBAL_CONTROL));
+	snd_ali_disable_special_channel(codec, ALI_SPDIF_OUT_CHANNEL);
 }
 
 static void snd_ali_enable_spdif_chnout(struct snd_ali *codec)
 {
-	unsigned short wVal = 0;
+	unsigned short wVal;
 
 	wVal  = inw(ALI_REG(codec, ALI_GLOBAL_CONTROL));
    	wVal &= ~ALI_SPDIF_OUT_SEL_PCM;
@@ -949,12 +889,13 @@ static void snd_ali_enable_spdif_chnout(struct snd_ali *codec)
 		wVal &= (~0x0002);
    	outw(wVal, ALI_REG(codec, ALI_SPDIF_CS));
 */
-	snd_ali_enable_special_channel(codec,ALI_SPDIF_OUT_CHANNEL);
+	snd_ali_enable_special_channel(codec, ALI_SPDIF_OUT_CHANNEL);
 }
 
 static void snd_ali_disable_spdif_chnout(struct snd_ali *codec)
 {
-	unsigned short wVal = 0;
+	unsigned short wVal;
+
   	wVal  = inw(ALI_REG(codec, ALI_GLOBAL_CONTROL));
    	wVal |= ALI_SPDIF_OUT_SEL_PCM;
    	outw(wVal, ALI_REG(codec, ALI_GLOBAL_CONTROL));
@@ -972,11 +913,11 @@ static void snd_ali_disable_spdif_out(struct snd_ali *codec)
 	snd_ali_disable_spdif_chnout(codec);
 }
 
-static void snd_ali_update_ptr(struct snd_ali *codec,int channel)
+static void snd_ali_update_ptr(struct snd_ali *codec, int channel)
 {
-	struct snd_ali_voice *pvoice = NULL;
+	struct snd_ali_voice *pvoice;
 	struct snd_pcm_runtime *runtime;
-	struct snd_ali_channel_control *pchregs = NULL;
+	struct snd_ali_channel_control *pchregs;
 	unsigned int old, mask;
 #ifdef ALI_DEBUG
 	unsigned int temp, cspf;
@@ -984,9 +925,9 @@ static void snd_ali_update_ptr(struct snd_ali *codec,int channel)
 
 	pchregs = &(codec->chregs);
 
-	// check if interrupt occurred for channel
+	/* check if interrupt occurred for channel */
 	old  = pchregs->data.aint;
-	mask = ((unsigned int) 1L) << (channel & 0x1f);
+	mask = 1U << (channel & 0x1f);
 
 	if (!(old & mask))
 		return;
@@ -1005,7 +946,8 @@ static void snd_ali_update_ptr(struct snd_ali *codec,int channel)
 		cspf = (inl(ALI_REG(codec, ALI_CSPF)) & mask) == mask;
 #endif
 		if (pvoice->running) {
-			snd_ali_printk("update_ptr: cso=%4.4x cspf=%d.\n",(u16)temp,cspf);
+			snd_ali_printk("update_ptr: cso=%4.4x cspf=%d.\n",
+				       (u16)temp, cspf);
 			spin_unlock(&codec->reg_lock);
 			snd_pcm_period_elapsed(pvoice->substream);
 			spin_lock(&codec->reg_lock);
@@ -1027,49 +969,47 @@ static void snd_ali_update_ptr(struct snd_ali *codec,int channel)
 	pchregs->data.aint = old & (~mask);
 }
 
-static void snd_ali_interrupt(struct snd_ali * codec)
+static irqreturn_t snd_ali_card_interrupt(int irq, void *dev_id)
 {
+	struct snd_ali 	*codec = dev_id;
 	int channel;
 	unsigned int audio_int;
-	struct snd_ali_channel_control *pchregs = NULL;
-	pchregs = &(codec->chregs);
+	struct snd_ali_channel_control *pchregs;
+
+	if (codec == NULL || !codec->hw_initialized)
+		return IRQ_NONE;
 
 	audio_int = inl(ALI_REG(codec, ALI_MISCINT));
+	if (!audio_int)
+		return IRQ_NONE;
+
+	pchregs = &(codec->chregs);
 	if (audio_int & ADDRESS_IRQ) {
-		// get interrupt status for all channels
-		pchregs->data.aint = inl(ALI_REG(codec,pchregs->regs.aint));
-		for (channel = 0; channel < ALI_CHANNELS; channel++) {
+		/* get interrupt status for all channels */
+		pchregs->data.aint = inl(ALI_REG(codec, pchregs->regs.aint));
+		for (channel = 0; channel < ALI_CHANNELS; channel++)
 			snd_ali_update_ptr(codec, channel);
-		}
 	}
 	outl((TARGET_REACHED | MIXER_OVERFLOW | MIXER_UNDERFLOW),
-		ALI_REG(codec,ALI_MISCINT));
-}
-
-
-static irqreturn_t snd_ali_card_interrupt(int irq, void *dev_id)
-{
-	struct snd_ali 	*codec = dev_id;
+		ALI_REG(codec, ALI_MISCINT));
 
-	if (codec == NULL)
-		return IRQ_NONE;
-	snd_ali_interrupt(codec);
 	return IRQ_HANDLED;
 }
 
 
-static struct snd_ali_voice *snd_ali_alloc_voice(struct snd_ali * codec, int type, int rec, int channel)
+static struct snd_ali_voice *snd_ali_alloc_voice(struct snd_ali * codec,
+						 int type, int rec, int channel)
 {
-	struct snd_ali_voice *pvoice = NULL;
+	struct snd_ali_voice *pvoice;
 	int idx;
 
-	snd_ali_printk("alloc_voice: type=%d rec=%d\n",type,rec);
+	snd_ali_printk("alloc_voice: type=%d rec=%d\n", type, rec);
 
 	spin_lock_irq(&codec->voice_alloc);
 	if (type == SNDRV_ALI_VOICE_TYPE_PCM) {
 		idx = channel > 0 ? snd_ali_alloc_pcm_channel(codec, channel) :
 			snd_ali_find_free_channel(codec,rec);
-		if(idx < 0) {
+		if (idx < 0) {
 			snd_printk(KERN_ERR "ali_alloc_voice: err.\n");
 			spin_unlock_irq(&codec->voice_alloc);
 			return NULL;
@@ -1087,7 +1027,8 @@ static struct snd_ali_voice *snd_ali_alloc_voice(struct snd_ali * codec, int typ
 }
 
 
-static void snd_ali_free_voice(struct snd_ali * codec, struct snd_ali_voice *pvoice)
+static void snd_ali_free_voice(struct snd_ali * codec,
+			       struct snd_ali_voice *pvoice)
 {
 	void (*private_free)(void *);
 	void *private_data;
@@ -1101,9 +1042,8 @@ static void snd_ali_free_voice(struct snd_ali * codec, struct snd_ali_voice *pvo
 	private_data = pvoice->private_data;
 	pvoice->private_free = NULL;
 	pvoice->private_data = NULL;
-	if (pvoice->pcm) {
+	if (pvoice->pcm)
 		snd_ali_free_channel_pcm(codec, pvoice->number);
-	}
 	pvoice->use = pvoice->pcm = pvoice->synth = 0;
 	pvoice->substream = NULL;
 	spin_unlock_irq(&codec->voice_alloc);
@@ -1112,9 +1052,9 @@ static void snd_ali_free_voice(struct snd_ali * codec, struct snd_ali_voice *pvo
 }
 
 
-static void snd_ali_clear_voices(struct snd_ali * codec,
-			  unsigned int v_min,
-			  unsigned int v_max)
+static void snd_ali_clear_voices(struct snd_ali *codec,
+				 unsigned int v_min,
+				 unsigned int v_max)
 {
 	unsigned int i;
 
@@ -1124,7 +1064,7 @@ static void snd_ali_clear_voices(struct snd_ali * codec,
 	}
 }
 
-static void snd_ali_write_voice_regs(struct snd_ali * codec,
+static void snd_ali_write_voice_regs(struct snd_ali *codec,
 			 unsigned int Channel,
 			 unsigned int LBA,
 			 unsigned int CSO,
@@ -1139,7 +1079,7 @@ static void snd_ali_write_voice_regs(struct snd_ali * codec,
 {
 	unsigned int ctlcmds[4];
 	
-	outb((unsigned char)(Channel & 0x001f),ALI_REG(codec,ALI_GC_CIR));
+	outb((unsigned char)(Channel & 0x001f), ALI_REG(codec, ALI_GC_CIR));
 
 	ctlcmds[0] =  (CSO << 16) | (ALPHA_FMS & 0x0000ffff);
 	ctlcmds[1] =  LBA;
@@ -1152,10 +1092,10 @@ static void snd_ali_write_voice_regs(struct snd_ali * codec,
 
 	outb(Channel, ALI_REG(codec, ALI_GC_CIR));
 
-	outl(ctlcmds[0], ALI_REG(codec,ALI_CSO_ALPHA_FMS));
-	outl(ctlcmds[1], ALI_REG(codec,ALI_LBA));
-	outl(ctlcmds[2], ALI_REG(codec,ALI_ESO_DELTA));
-	outl(ctlcmds[3], ALI_REG(codec,ALI_GVSEL_PAN_VOC_CTRL_EC));
+	outl(ctlcmds[0], ALI_REG(codec, ALI_CSO_ALPHA_FMS));
+	outl(ctlcmds[1], ALI_REG(codec, ALI_LBA));
+	outl(ctlcmds[2], ALI_REG(codec, ALI_ESO_DELTA));
+	outl(ctlcmds[3], ALI_REG(codec, ALI_GVSEL_PAN_VOC_CTRL_EC));
 
 	outl(0x30000000, ALI_REG(codec, ALI_EBUF1));	/* Still Mode */
 	outl(0x30000000, ALI_REG(codec, ALI_EBUF2));	/* Still Mode */
@@ -1165,8 +1105,10 @@ static unsigned int snd_ali_convert_rate(unsigned int rate, int rec)
 {
 	unsigned int delta;
 
-	if (rate < 4000)  rate = 4000;
-	if (rate > 48000) rate = 48000;
+	if (rate < 4000)
+		rate = 4000;
+	if (rate > 48000)
+		rate = 48000;
 
 	if (rec) {
 		if (rate == 44100)
@@ -1201,11 +1143,11 @@ static unsigned int snd_ali_control_mode(struct snd_pcm_substream *substream)
 	 */
 	CTRL = 0x00000001;
 	if (snd_pcm_format_width(runtime->format) == 16)
-		CTRL |= 0x00000008;	// 16-bit data
+		CTRL |= 0x00000008;	/* 16-bit data */
 	if (!snd_pcm_format_unsigned(runtime->format))
-		CTRL |= 0x00000002;	// signed data
+		CTRL |= 0x00000002;	/* signed data */
 	if (runtime->channels > 1)
-		CTRL |= 0x00000004;	// stereo data
+		CTRL |= 0x00000004;	/* stereo data */
 	return CTRL;
 }
 
@@ -1213,45 +1155,39 @@ static unsigned int snd_ali_control_mode(struct snd_pcm_substream *substream)
  *  PCM part
  */
 
-static int snd_ali_ioctl(struct snd_pcm_substream *substream,
-				  unsigned int cmd, void *arg)
-{
-	return snd_pcm_lib_ioctl(substream, cmd, arg);
-}
-
 static int snd_ali_trigger(struct snd_pcm_substream *substream,
 			       int cmd)
 				    
 {
 	struct snd_ali *codec = snd_pcm_substream_chip(substream);
-	struct list_head *pos;
 	struct snd_pcm_substream *s;
 	unsigned int what, whati, capture_flag;
-	struct snd_ali_voice *pvoice = NULL, *evoice = NULL;
+	struct snd_ali_voice *pvoice, *evoice;
 	unsigned int val;
 	int do_start;
 
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
 	case SNDRV_PCM_TRIGGER_RESUME:
-		do_start = 1; break;
+		do_start = 1;
+		break;
 	case SNDRV_PCM_TRIGGER_STOP:
 	case SNDRV_PCM_TRIGGER_SUSPEND:
-		do_start = 0; break;
+		do_start = 0;
+		break;
 	default:
 		return -EINVAL;
 	}
 
 	what = whati = capture_flag = 0;
-	snd_pcm_group_for_each(pos, substream) {
-		s = snd_pcm_group_substream_entry(pos);
+	snd_pcm_group_for_each_entry(s, substream) {
 		if ((struct snd_ali *) snd_pcm_substream_chip(s) == codec) {
 			pvoice = s->runtime->private_data;
 			evoice = pvoice->extra;
 			what |= 1 << (pvoice->number & 0x1f);
-			if (evoice == NULL) {
+			if (evoice == NULL)
 				whati |= 1 << (pvoice->number & 0x1f);
-			} else {
+			else {
 				whati |= 1 << (evoice->number & 0x1f);
 				what |= 1 << (evoice->number & 0x1f);
 			}
@@ -1270,48 +1206,51 @@ static int snd_ali_trigger(struct snd_pcm_substream *substream,
 		}
 	}
 	spin_lock(&codec->reg_lock);
-	if (! do_start) {
+	if (!do_start)
 		outl(what, ALI_REG(codec, ALI_STOP));
-	}
 	val = inl(ALI_REG(codec, ALI_AINTEN));
-	if (do_start) {
+	if (do_start)
 		val |= whati;
-	} else {
+	else
 		val &= ~whati;
-	}
 	outl(val, ALI_REG(codec, ALI_AINTEN));
-	if (do_start) {
+	if (do_start)
 		outl(what, ALI_REG(codec, ALI_START));
-	}
-	snd_ali_printk("trigger: what=%xh whati=%xh\n",what,whati);
+	snd_ali_printk("trigger: what=%xh whati=%xh\n", what, whati);
 	spin_unlock(&codec->reg_lock);
 
 	return 0;
 }
 
 static int snd_ali_playback_hw_params(struct snd_pcm_substream *substream,
-				 struct snd_pcm_hw_params *hw_params)
+				      struct snd_pcm_hw_params *hw_params)
 {
 	struct snd_ali *codec = snd_pcm_substream_chip(substream);
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct snd_ali_voice *pvoice = runtime->private_data;
 	struct snd_ali_voice *evoice = pvoice->extra;
 	int err;
-	err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
-	if (err < 0) return err;
+
+	err = snd_pcm_lib_malloc_pages(substream,
+				       params_buffer_bytes(hw_params));
+	if (err < 0)
+		return err;
 	
 	/* voice management */
 
-	if (params_buffer_size(hw_params)/2 != params_period_size(hw_params)) {
-		if (evoice == NULL) {
-			evoice = snd_ali_alloc_voice(codec, SNDRV_ALI_VOICE_TYPE_PCM, 0, -1);
-			if (evoice == NULL)
+	if (params_buffer_size(hw_params) / 2 !=
+	    params_period_size(hw_params)) {
+		if (!evoice) {
+			evoice = snd_ali_alloc_voice(codec,
+						     SNDRV_ALI_VOICE_TYPE_PCM,
+						     0, -1);
+			if (!evoice)
 				return -ENOMEM;
 			pvoice->extra = evoice;
 			evoice->substream = substream;
 		}
 	} else {
-		if (evoice != NULL) {
+		if (!evoice) {
 			snd_ali_free_voice(codec, evoice);
 			pvoice->extra = evoice = NULL;
 		}
@@ -1328,7 +1267,7 @@ static int snd_ali_playback_hw_free(struct snd_pcm_substream *substream)
 	struct snd_ali_voice *evoice = pvoice ? pvoice->extra : NULL;
 
 	snd_pcm_lib_free_pages(substream);
-	if (evoice != NULL) {
+	if (!evoice) {
 		snd_ali_free_voice(codec, evoice);
 		pvoice->extra = NULL;
 	}
@@ -1336,9 +1275,10 @@ static int snd_ali_playback_hw_free(struct snd_pcm_substream *substream)
 }
 
 static int snd_ali_hw_params(struct snd_pcm_substream *substream,
-				 struct snd_pcm_hw_params *hw_params)
+			     struct snd_pcm_hw_params *hw_params)
 {
-	return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
+	return snd_pcm_lib_malloc_pages(substream,
+					params_buffer_bytes(hw_params));
 }
 
 static int snd_ali_hw_free(struct snd_pcm_substream *substream)
@@ -1369,12 +1309,13 @@ static int snd_ali_playback_prepare(struct snd_pcm_substream *substream)
 	/* set Delta (rate) value */
 	Delta = snd_ali_convert_rate(runtime->rate, 0);
 
-	if ((pvoice->number == ALI_SPDIF_IN_CHANNEL) || 
-	    (pvoice->number == ALI_PCM_IN_CHANNEL))
+	if (pvoice->number == ALI_SPDIF_IN_CHANNEL || 
+	    pvoice->number == ALI_PCM_IN_CHANNEL)
 		snd_ali_disable_special_channel(codec, pvoice->number);
 	else if (codec->spdif_support &&
-		 (inl(ALI_REG(codec, ALI_GLOBAL_CONTROL)) & ALI_SPDIF_OUT_CH_ENABLE)
-		 && (pvoice->number == ALI_SPDIF_OUT_CHANNEL)) {
+		 (inl(ALI_REG(codec, ALI_GLOBAL_CONTROL)) &
+		  ALI_SPDIF_OUT_CH_ENABLE)
+		 && pvoice->number == ALI_SPDIF_OUT_CHANNEL) {
 		snd_ali_set_spdif_out_rate(codec, runtime->rate);
 		Delta = 0x1000;
 	}
@@ -1388,7 +1329,8 @@ static int snd_ali_playback_prepare(struct snd_pcm_substream *substream)
 	/* set target ESO for channel */
 	pvoice->eso = runtime->buffer_size; 
 
-	snd_ali_printk("playback_prepare: eso=%xh count=%xh\n",pvoice->eso,pvoice->count);
+	snd_ali_printk("playback_prepare: eso=%xh count=%xh\n",
+		       pvoice->eso, pvoice->count);
 
 	/* set ESO to capture first MIDLP interrupt */
 	ESO = pvoice->eso -1;
@@ -1399,35 +1341,37 @@ static int snd_ali_playback_prepare(struct snd_pcm_substream *substream)
 	PAN = 0;
 	VOL = 0;
 	EC = 0;
-	snd_ali_printk("playback_prepare:\n    ch=%d, Rate=%d Delta=%xh,GVSEL=%xh,PAN=%xh,CTRL=%xh\n",pvoice->number,runtime->rate,Delta,GVSEL,PAN,CTRL);
-	snd_ali_write_voice_regs(    codec,
-				     pvoice->number,
-				     LBA,
-				     0,	/* cso */
-				     ESO,
-				     Delta,
-				     0,	/* alpha */
-				     GVSEL,
-				     PAN,
-				     VOL,
-				     CTRL,
-				     EC);
-	if (evoice != NULL) {
+	snd_ali_printk("playback_prepare:\n");
+	snd_ali_printk("ch=%d, Rate=%d Delta=%xh,GVSEL=%xh,PAN=%xh,CTRL=%xh\n",
+		       pvoice->number,runtime->rate,Delta,GVSEL,PAN,CTRL);
+	snd_ali_write_voice_regs(codec,
+				 pvoice->number,
+				 LBA,
+				 0,	/* cso */
+				 ESO,
+				 Delta,
+				 0,	/* alpha */
+				 GVSEL,
+				 PAN,
+				 VOL,
+				 CTRL,
+				 EC);
+	if (!evoice) {
 		evoice->count = pvoice->count;
 		evoice->eso = pvoice->count << 1;
 		ESO = evoice->eso - 1;
 		snd_ali_write_voice_regs(codec,
-				     evoice->number,
-				     LBA,
-				     0,	/* cso */
-				     ESO,
-				     Delta,
-				     0,	/* alpha */
-				     GVSEL,
-				     (unsigned int)0x7f,
-				     (unsigned int)0x3ff,
-				     CTRL,
-				     EC);
+					 evoice->number,
+					 LBA,
+					 0,	/* cso */
+					 ESO,
+					 Delta,
+					 0,	/* alpha */
+					 GVSEL,
+					 0x7f,
+					 0x3ff,
+					 CTRL,
+					 EC);
 	}
 	spin_unlock_irq(&codec->reg_lock);
 	return 0;
@@ -1459,7 +1403,7 @@ static int snd_ali_prepare(struct snd_pcm_substream *substream)
 		 pvoice->number == ALI_MODEM_OUT_CHANNEL) ? 
 		0x1000 : snd_ali_convert_rate(runtime->rate, pvoice->mode);
 
-	// Prepare capture intr channel
+	/* Prepare capture intr channel */
 	if (pvoice->number == ALI_SPDIF_IN_CHANNEL) {
 
 		unsigned int rate;
@@ -1470,7 +1414,8 @@ static int snd_ali_prepare(struct snd_pcm_substream *substream)
 
 		rate = snd_ali_get_spdif_in_rate(codec);
 		if (rate == 0) {
-			snd_printk(KERN_WARNING "ali_capture_preapre: spdif rate detect err!\n");
+			snd_printk(KERN_WARNING "ali_capture_preapre: "
+				   "spdif rate detect err!\n");
 			rate = 48000;
 		}
 		spin_lock_irq(&codec->reg_lock);
@@ -1481,19 +1426,19 @@ static int snd_ali_prepare(struct snd_pcm_substream *substream)
 		}
 
 		if (rate != 48000)
-			Delta = ((rate << 12)/runtime->rate)&0x00ffff;
+			Delta = ((rate << 12) / runtime->rate) & 0x00ffff;
 	}
 
-	// set target ESO for channel 
+	/* set target ESO for channel  */
 	pvoice->eso = runtime->buffer_size; 
 
-	// set interrupt count size 
+	/* set interrupt count size  */
 	pvoice->count = runtime->period_size;
 
-	// set Loop Back Address 
+	/* set Loop Back Address  */
 	LBA = runtime->dma_addr;
 
-	// set ESO to capture first MIDLP interrupt 
+	/* set ESO to capture first MIDLP interrupt  */
 	ESO = pvoice->eso - 1;
 	CTRL = snd_ali_control_mode(substream);
 	GVSEL = 0;
@@ -1514,14 +1459,14 @@ static int snd_ali_prepare(struct snd_pcm_substream *substream)
 				     CTRL,
 				     EC);
 
-
 	spin_unlock_irq(&codec->reg_lock);
 
 	return 0;
 }
 
 
-static snd_pcm_uframes_t snd_ali_playback_pointer(struct snd_pcm_substream *substream)
+static snd_pcm_uframes_t
+snd_ali_playback_pointer(struct snd_pcm_substream *substream)
 {
 	struct snd_ali *codec = snd_pcm_substream_chip(substream);
 	struct snd_pcm_runtime *runtime = substream->runtime;
@@ -1563,14 +1508,14 @@ static snd_pcm_uframes_t snd_ali_pointer(struct snd_pcm_substream *substream)
 
 static struct snd_pcm_hardware snd_ali_playback =
 {
-	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
-				 SNDRV_PCM_INFO_BLOCK_TRANSFER |
-				 SNDRV_PCM_INFO_MMAP_VALID |
-				 SNDRV_PCM_INFO_RESUME |
-				 SNDRV_PCM_INFO_SYNC_START),
-	.formats =		(SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE |
-				 SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U16_LE),
-	.rates =		SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
+	.info =		(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+			 SNDRV_PCM_INFO_BLOCK_TRANSFER |
+			 SNDRV_PCM_INFO_MMAP_VALID |
+			 SNDRV_PCM_INFO_RESUME |
+			 SNDRV_PCM_INFO_SYNC_START),
+	.formats =	(SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE |
+			 SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U16_LE),
+	.rates =	SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
 	.rate_min =		4000,
 	.rate_max =		48000,
 	.channels_min =		1,
@@ -1589,14 +1534,14 @@ static struct snd_pcm_hardware snd_ali_playback =
 
 static struct snd_pcm_hardware snd_ali_capture =
 {
-	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
-				 SNDRV_PCM_INFO_BLOCK_TRANSFER |
-				 SNDRV_PCM_INFO_MMAP_VALID |
-				 SNDRV_PCM_INFO_RESUME |
-				 SNDRV_PCM_INFO_SYNC_START),
-	.formats =		(SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE |
-				 SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U16_LE),
-	.rates =		SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
+	.info =		(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+			 SNDRV_PCM_INFO_BLOCK_TRANSFER |
+			 SNDRV_PCM_INFO_MMAP_VALID |
+			 SNDRV_PCM_INFO_RESUME |
+			 SNDRV_PCM_INFO_SYNC_START),
+	.formats =	(SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE |
+			 SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U16_LE),
+	.rates =	SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
 	.rate_min =		4000,
 	.rate_max =		48000,
 	.channels_min =		1,
@@ -1620,15 +1565,16 @@ static void snd_ali_pcm_free_substream(struct snd_pcm_runtime *runtime)
 	}
 }
 
-static int snd_ali_open(struct snd_pcm_substream *substream, int rec, int channel,
-		struct snd_pcm_hardware *phw)
+static int snd_ali_open(struct snd_pcm_substream *substream, int rec,
+			int channel, struct snd_pcm_hardware *phw)
 {
 	struct snd_ali *codec = snd_pcm_substream_chip(substream);
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct snd_ali_voice *pvoice;
 
-	pvoice = snd_ali_alloc_voice(codec, SNDRV_ALI_VOICE_TYPE_PCM, rec, channel);
-	if (pvoice == NULL)
+	pvoice = snd_ali_alloc_voice(codec, SNDRV_ALI_VOICE_TYPE_PCM, rec,
+				     channel);
+	if (!pvoice)
 		return -EAGAIN;
 
 	pvoice->substream = substream;
@@ -1637,7 +1583,8 @@ static int snd_ali_open(struct snd_pcm_substream *substream, int rec, int channe
 
 	runtime->hw = *phw;
 	snd_pcm_set_sync(substream);
-	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 64*1024);
+	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
+				     0, 64*1024);
 	return 0;
 }
 
@@ -1669,7 +1616,7 @@ static int snd_ali_close(struct snd_pcm_substream *substream)
 static struct snd_pcm_ops snd_ali_playback_ops = {
 	.open =		snd_ali_playback_open,
 	.close =	snd_ali_playback_close,
-	.ioctl =	snd_ali_ioctl,
+	.ioctl =	snd_pcm_lib_ioctl,
 	.hw_params =	snd_ali_playback_hw_params,
 	.hw_free =	snd_ali_playback_hw_free,
 	.prepare =	snd_ali_playback_prepare,
@@ -1680,7 +1627,7 @@ static struct snd_pcm_ops snd_ali_playback_ops = {
 static struct snd_pcm_ops snd_ali_capture_ops = {
 	.open =		snd_ali_capture_open,
 	.close =	snd_ali_close,
-	.ioctl =	snd_ali_ioctl,
+	.ioctl =	snd_pcm_lib_ioctl,
 	.hw_params =	snd_ali_hw_params,
 	.hw_free =	snd_ali_hw_free,
 	.prepare =	snd_ali_prepare,
@@ -1697,20 +1644,22 @@ static int snd_ali_modem_hw_params(struct snd_pcm_substream *substream,
 {
 	struct snd_ali *chip = snd_pcm_substream_chip(substream);
 	unsigned int modem_num = chip->num_of_codecs - 1;
-	snd_ac97_write(chip->ac97[modem_num], AC97_LINE1_RATE, params_rate(hw_params));
+	snd_ac97_write(chip->ac97[modem_num], AC97_LINE1_RATE,
+		       params_rate(hw_params));
 	snd_ac97_write(chip->ac97[modem_num], AC97_LINE1_LEVEL, 0);
 	return snd_ali_hw_params(substream, hw_params);
 }
 
 static struct snd_pcm_hardware snd_ali_modem =
 {
-	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
-				 SNDRV_PCM_INFO_BLOCK_TRANSFER |
-				 SNDRV_PCM_INFO_MMAP_VALID |
-				 SNDRV_PCM_INFO_RESUME |
-				 SNDRV_PCM_INFO_SYNC_START),
-	.formats =		SNDRV_PCM_FMTBIT_S16_LE,
-	.rates =		SNDRV_PCM_RATE_KNOT|SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000,
+	.info =		(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+			 SNDRV_PCM_INFO_BLOCK_TRANSFER |
+			 SNDRV_PCM_INFO_MMAP_VALID |
+			 SNDRV_PCM_INFO_RESUME |
+			 SNDRV_PCM_INFO_SYNC_START),
+	.formats =	SNDRV_PCM_FMTBIT_S16_LE,
+	.rates =	(SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000 |
+			 SNDRV_PCM_RATE_16000),
 	.rate_min =		8000,
 	.rate_max =		16000,
 	.channels_min =		1,
@@ -1723,15 +1672,17 @@ static struct snd_pcm_hardware snd_ali_modem =
 	.fifo_size =		0,
 };
 
-static int snd_ali_modem_open(struct snd_pcm_substream *substream, int rec, int channel)
+static int snd_ali_modem_open(struct snd_pcm_substream *substream, int rec,
+			      int channel)
 {
-	static unsigned int rates [] = {8000,9600,12000,16000};
+	static unsigned int rates[] = {8000, 9600, 12000, 16000};
 	static struct snd_pcm_hw_constraint_list hw_constraint_rates = {
 		.count = ARRAY_SIZE(rates),
 		.list = rates,
 		.mask = 0,
 	};
 	int err = snd_ali_open(substream, rec, channel, &snd_ali_modem);
+
 	if (err)
 		return err;
 	return snd_pcm_hw_constraint_list(substream->runtime, 0,
@@ -1788,7 +1739,8 @@ static void snd_ali_pcm_free(struct snd_pcm *pcm)
 }
 
 
-static int __devinit snd_ali_pcm(struct snd_ali * codec, int device, struct ali_pcm_description *desc)
+static int __devinit snd_ali_pcm(struct snd_ali * codec, int device,
+				 struct ali_pcm_description *desc)
 {
 	struct snd_pcm *pcm;
 	int err;
@@ -1802,12 +1754,15 @@ static int __devinit snd_ali_pcm(struct snd_ali * codec, int device, struct ali_
 	pcm->private_data = codec;
 	pcm->private_free = snd_ali_pcm_free;
 	if (desc->playback_ops)
-		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, desc->playback_ops);
+		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+				desc->playback_ops);
 	if (desc->capture_ops)
-		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, desc->capture_ops);
+		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
+				desc->capture_ops);
 
 	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-					      snd_dma_pci_data(codec->pci), 64*1024, 128*1024);
+					      snd_dma_pci_data(codec->pci),
+					      64*1024, 128*1024);
 
 	pcm->info_flags = 0;
 	pcm->dev_class = desc->class;
@@ -1818,16 +1773,29 @@ static int __devinit snd_ali_pcm(struct snd_ali * codec, int device, struct ali_
 }
 
 static struct ali_pcm_description ali_pcms[] = {
-	{ "ALI 5451", ALI_CHANNELS, 1, &snd_ali_playback_ops, &snd_ali_capture_ops },
-	{ "ALI 5451 modem", 1, 1, &snd_ali_modem_playback_ops, &snd_ali_modem_capture_ops, SNDRV_PCM_CLASS_MODEM }
+	{ .name = "ALI 5451",
+	  .playback_num = ALI_CHANNELS,
+	  .capture_num = 1,
+	  .playback_ops = &snd_ali_playback_ops,
+	  .capture_ops = &snd_ali_capture_ops
+	},
+	{ .name = "ALI 5451 modem",
+	  .playback_num = 1,
+	  .capture_num = 1,
+	  .playback_ops = &snd_ali_modem_playback_ops,
+	  .capture_ops = &snd_ali_modem_capture_ops,
+	  .class = SNDRV_PCM_CLASS_MODEM
+	}
 };
 
 static int __devinit snd_ali_build_pcms(struct snd_ali *codec)
 {
 	int i, err;
-	for(i = 0 ; i < codec->num_of_codecs && i < ARRAY_SIZE(ali_pcms) ; i++)
-		if((err = snd_ali_pcm(codec, i, &ali_pcms[i])) < 0)
+	for (i = 0; i < codec->num_of_codecs && i < ARRAY_SIZE(ali_pcms); i++) {
+		err = snd_ali_pcm(codec, i, &ali_pcms[i]);
+		if (err < 0)
 			return err;
+	}
 	return 0;
 }
 
@@ -1837,7 +1805,8 @@ static int __devinit snd_ali_build_pcms(struct snd_ali *codec)
 .info = snd_ali5451_spdif_info, .get = snd_ali5451_spdif_get, \
 .put = snd_ali5451_spdif_put, .private_value = value}
 
-static int snd_ali5451_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
+static int snd_ali5451_spdif_info(struct snd_kcontrol *kcontrol,
+				  struct snd_ctl_elem_info *uinfo)
 {
         uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
         uinfo->count = 1;
@@ -1846,7 +1815,8 @@ static int snd_ali5451_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_
         return 0;
 }
 
-static int snd_ali5451_spdif_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+static int snd_ali5451_spdif_get(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_ali *codec = kcontrol->private_data;
 	unsigned int enable;
@@ -1854,12 +1824,13 @@ static int snd_ali5451_spdif_get(struct snd_kcontrol *kcontrol, struct snd_ctl_e
 	enable = ucontrol->value.integer.value[0] ? 1 : 0;
 
 	spin_lock_irq(&codec->reg_lock);
-	switch(kcontrol->private_value) {
+	switch (kcontrol->private_value) {
 	case 0:
 		enable = (codec->spdif_mask & 0x02) ? 1 : 0;
 		break;
 	case 1:
-		enable = ((codec->spdif_mask & 0x02) && (codec->spdif_mask & 0x04)) ? 1 : 0;
+		enable = ((codec->spdif_mask & 0x02) &&
+			  (codec->spdif_mask & 0x04)) ? 1 : 0;
 		break;
 	case 2:
 		enable = (codec->spdif_mask & 0x01) ? 1 : 0;
@@ -1872,7 +1843,8 @@ static int snd_ali5451_spdif_get(struct snd_kcontrol *kcontrol, struct snd_ctl_e
 	return 0;
 }
 
-static int snd_ali5451_spdif_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+static int snd_ali5451_spdif_put(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_ali *codec = kcontrol->private_data;
 	unsigned int change = 0, enable = 0;
@@ -1939,18 +1911,6 @@ static struct snd_kcontrol_new snd_ali5451_mixer_spdif[] __devinitdata = {
 	ALI5451_SPDIF(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), 0, 2)
 };
 
-static void snd_ali_mixer_free_ac97_bus(struct snd_ac97_bus *bus)
-{
-	struct snd_ali *codec = bus->private_data;
-	codec->ac97_bus = NULL;
-}
-
-static void snd_ali_mixer_free_ac97(struct snd_ac97 *ac97)
-{
-	struct snd_ali *codec = ac97->private_data;
-	codec->ac97[ac97->num] = NULL;
-}
-
 static int __devinit snd_ali_mixer(struct snd_ali * codec)
 {
 	struct snd_ac97_template ac97;
@@ -1961,19 +1921,20 @@ static int __devinit snd_ali_mixer(struct snd_ali * codec)
 		.read = snd_ali_codec_read,
 	};
 
-	if ((err = snd_ac97_bus(codec->card, 0, &ops, codec, &codec->ac97_bus)) < 0)
+	err = snd_ac97_bus(codec->card, 0, &ops, codec, &codec->ac97_bus);
+	if (err < 0)
 		return err;
-	codec->ac97_bus->private_free = snd_ali_mixer_free_ac97_bus;
 
 	memset(&ac97, 0, sizeof(ac97));
 	ac97.private_data = codec;
-	ac97.private_free = snd_ali_mixer_free_ac97;
 
-	for ( i = 0 ; i < codec->num_of_codecs ; i++) {
+	for (i = 0; i < codec->num_of_codecs; i++) {
 		ac97.num = i;
-		if ((err = snd_ac97_mixer(codec->ac97_bus, &ac97, &codec->ac97[i])) < 0) {
-			snd_printk(KERN_ERR "ali mixer %d creating error.\n", i);
-			if(i == 0)
+		err = snd_ac97_mixer(codec->ac97_bus, &ac97, &codec->ac97[i]);
+		if (err < 0) {
+			snd_printk(KERN_ERR
+				   "ali mixer %d creating error.\n", i);
+			if (i == 0)
 				return err;
 			codec->num_of_codecs = 1;
 			break;
@@ -1981,9 +1942,11 @@ static int __devinit snd_ali_mixer(struct snd_ali * codec)
 	}
 
 	if (codec->spdif_support) {
-		for(idx = 0; idx < ARRAY_SIZE(snd_ali5451_mixer_spdif); idx++) {
-			err=snd_ctl_add(codec->card, snd_ctl_new1(&snd_ali5451_mixer_spdif[idx], codec));
-			if (err < 0) return err;
+		for (idx = 0; idx < ARRAY_SIZE(snd_ali5451_mixer_spdif); idx++) {
+			err = snd_ctl_add(codec->card,
+					  snd_ctl_new1(&snd_ali5451_mixer_spdif[idx], codec));
+			if (err < 0)
+				return err;
 		}
 	}
 	return 0;
@@ -1998,11 +1961,11 @@ static int ali_suspend(struct pci_dev *pci, pm_message_t state)
 	int i, j;
 
 	im = chip->image;
-	if (! im)
+	if (!im)
 		return 0;
 
 	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
-	for(i = 0 ; i < chip->num_of_codecs ; i++) {
+	for (i = 0; i < chip->num_of_codecs; i++) {
 		snd_pcm_suspend_all(chip->pcm[i]);
 		snd_ac97_suspend(chip->ac97[i]);
 	}
@@ -2010,10 +1973,10 @@ static int ali_suspend(struct pci_dev *pci, pm_message_t state)
 	spin_lock_irq(&chip->reg_lock);
 	
 	im->regs[ALI_MISCINT >> 2] = inl(ALI_REG(chip, ALI_MISCINT));
-	// im->regs[ALI_START >> 2] = inl(ALI_REG(chip, ALI_START));
+	/* im->regs[ALI_START >> 2] = inl(ALI_REG(chip, ALI_START)); */
 	im->regs[ALI_STOP >> 2] = inl(ALI_REG(chip, ALI_STOP));
 	
-	// disable all IRQ bits
+	/* disable all IRQ bits */
 	outl(0, ALI_REG(chip, ALI_MISCINT));
 	
 	for (i = 0; i < ALI_GLOBAL_REGS; i++) {	
@@ -2028,7 +1991,7 @@ static int ali_suspend(struct pci_dev *pci, pm_message_t state)
 			im->channel_regs[i][j] = inl(ALI_REG(chip, j*4 + 0xe0));
 	}
 
-	// stop all HW channel
+	/* stop all HW channel */
 	outl(0xffffffff, ALI_REG(chip, ALI_STOP));
 
 	spin_unlock_irq(&chip->reg_lock);
@@ -2047,7 +2010,7 @@ static int ali_resume(struct pci_dev *pci)
 	int i, j;
 
 	im = chip->image;
-	if (! im)
+	if (!im)
 		return 0;
 
 	pci_set_power_state(pci, PCI_D0);
@@ -2069,19 +2032,20 @@ static int ali_resume(struct pci_dev *pci)
 	}
 	
 	for (i = 0; i < ALI_GLOBAL_REGS; i++) {	
-		if ((i*4 == ALI_MISCINT) || (i*4 == ALI_STOP) || (i*4 == ALI_START))
+		if ((i*4 == ALI_MISCINT) || (i*4 == ALI_STOP) ||
+		    (i*4 == ALI_START))
 			continue;
 		outl(im->regs[i], ALI_REG(chip, i*4));
 	}
 	
-	// start HW channel
+	/* start HW channel */
 	outl(im->regs[ALI_START >> 2], ALI_REG(chip, ALI_START));
-	// restore IRQ enable bits
+	/* restore IRQ enable bits */
 	outl(im->regs[ALI_MISCINT >> 2], ALI_REG(chip, ALI_MISCINT));
 	
 	spin_unlock_irq(&chip->reg_lock);
 
-	for(i = 0 ; i < chip->num_of_codecs ; i++)
+	for (i = 0 ; i < chip->num_of_codecs; i++)
 		snd_ac97_resume(chip->ac97[i]);
 	
 	snd_power_change_state(card, SNDRV_CTL_POWER_D0);
@@ -2113,7 +2077,7 @@ static int snd_ali_chip_init(struct snd_ali *codec)
 {
 	unsigned int legacy;
 	unsigned char temp;
-	struct pci_dev *pci_dev = NULL;
+	struct pci_dev *pci_dev;
 
 	snd_ali_printk("chip initializing ... \n");
 
@@ -2146,7 +2110,8 @@ static int snd_ali_chip_init(struct snd_ali *codec)
 	outb(0x10, 	 ALI_REG(codec, ALI_MPUR2));
 
 	codec->ac97_ext_id = snd_ali_codec_peek(codec, 0, AC97_EXTENDED_ID);
-	codec->ac97_ext_status = snd_ali_codec_peek(codec, 0, AC97_EXTENDED_STATUS);
+	codec->ac97_ext_status = snd_ali_codec_peek(codec, 0,
+						    AC97_EXTENDED_STATUS);
 	if (codec->spdif_support) {
 		snd_ali_enable_spdif_out(codec);
 		codec->spdif_mask = 0x00000002;
@@ -2158,8 +2123,9 @@ static int snd_ali_chip_init(struct snd_ali *codec)
 	if (inl(ALI_REG(codec, ALI_SCTRL)) & ALI_SCTRL_CODEC2_READY) {
 		codec->num_of_codecs++;
 		outl(inl(ALI_REG(codec, ALI_SCTRL)) |
-			(ALI_SCTRL_LINE_IN2|ALI_SCTRL_GPIO_IN2|ALI_SCTRL_LINE_OUT_EN),
-			ALI_REG(codec, ALI_SCTRL));
+		     (ALI_SCTRL_LINE_IN2 | ALI_SCTRL_GPIO_IN2 |
+		      ALI_SCTRL_LINE_OUT_EN),
+		     ALI_REG(codec, ALI_SCTRL));
 	}
 
 	snd_ali_printk("chip initialize succeed.\n");
@@ -2168,18 +2134,19 @@ static int snd_ali_chip_init(struct snd_ali *codec)
 }
 
 /* proc for register dump */
-static void snd_ali_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buf)
+static void snd_ali_proc_read(struct snd_info_entry *entry,
+			      struct snd_info_buffer *buf)
 {
 	struct snd_ali *codec = entry->private_data;
 	int i;
-	for(i = 0 ; i < 256 ; i+= 4)
+	for (i = 0; i < 256 ; i+= 4)
 		snd_iprintf(buf, "%02x: %08x\n", i, inl(ALI_REG(codec, i)));
 }
 
 static void __devinit snd_ali_proc_init(struct snd_ali *codec)
 {
 	struct snd_info_entry *entry;
-	if(!snd_card_proc_new(codec->card, "ali5451", &entry))
+	if (!snd_card_proc_new(codec->card, "ali5451", &entry))
 		snd_info_set_text_ops(entry, codec, snd_ali_proc_read);
 }
 
@@ -2188,7 +2155,8 @@ static int __devinit snd_ali_resources(struct snd_ali *codec)
 	int err;
 
 	snd_ali_printk("resouces allocation ...\n");
-	if ((err = pci_request_regions(codec->pci, "ALI 5451")) < 0)
+	err = pci_request_regions(codec->pci, "ALI 5451");
+	if (err < 0)
 		return err;
 	codec->port = pci_resource_start(codec->pci, 0);
 
@@ -2201,9 +2169,9 @@ static int __devinit snd_ali_resources(struct snd_ali *codec)
 	snd_ali_printk("resouces allocated.\n");
 	return 0;
 }
-static int snd_ali_dev_free(struct snd_device *device) 
+static int snd_ali_dev_free(struct snd_device *device)
 {
-	struct snd_ali *codec=device->device_data;
+	struct snd_ali *codec = device->device_data;
 	snd_ali_free(codec);
 	return 0;
 }
@@ -2226,17 +2194,20 @@ static int __devinit snd_ali_create(struct snd_card *card,
 	snd_ali_printk("creating ...\n");
 
 	/* enable PCI device */
-	if ((err = pci_enable_device(pci)) < 0)
+	err = pci_enable_device(pci);
+	if (err < 0)
 		return err;
 	/* check, if we can restrict PCI DMA transfers to 31 bits */
 	if (pci_set_dma_mask(pci, DMA_31BIT_MASK) < 0 ||
 	    pci_set_consistent_dma_mask(pci, DMA_31BIT_MASK) < 0) {
-		snd_printk(KERN_ERR "architecture does not support 31bit PCI busmaster DMA\n");
+		snd_printk(KERN_ERR "architecture does not support "
+			   "31bit PCI busmaster DMA\n");
 		pci_disable_device(pci);
 		return -ENXIO;
 	}
 
-	if ((codec = kzalloc(sizeof(*codec), GFP_KERNEL)) == NULL) {
+	codec = kzalloc(sizeof(*codec), GFP_KERNEL);
+	if (!codec) {
 		pci_disable_device(pci);
 		return -ENOMEM;
 	}
@@ -2293,21 +2264,22 @@ static int __devinit snd_ali_create(struct snd_card *card,
 
 	/* M1533: southbridge */
 	codec->pci_m1533 = pci_get_device(0x10b9, 0x1533, NULL);
-	if (! codec->pci_m1533) {
+	if (!codec->pci_m1533) {
 		snd_printk(KERN_ERR "ali5451: cannot find ALi 1533 chip.\n");
 		snd_ali_free(codec);
 		return -ENODEV;
 	}
 	/* M7101: power management */
 	codec->pci_m7101 = pci_get_device(0x10b9, 0x7101, NULL);
-	if (! codec->pci_m7101 && codec->revision == ALI_5451_V02) {
+	if (!codec->pci_m7101 && codec->revision == ALI_5451_V02) {
 		snd_printk(KERN_ERR "ali5451: cannot find ALi 7101 chip.\n");
 		snd_ali_free(codec);
 		return -ENODEV;
 	}
 
 	snd_ali_printk("snd_device_new is called.\n");
-	if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, codec, &ops)) < 0) {
+	err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, codec, &ops);
+	if (err < 0) {
 		snd_ali_free(codec);
 		return err;
 	}
@@ -2315,18 +2287,18 @@ static int __devinit snd_ali_create(struct snd_card *card,
 	snd_card_set_dev(card, &pci->dev);
 
 	/* initialise synth voices*/
-	for (i = 0; i < ALI_CHANNELS; i++ ) {
+	for (i = 0; i < ALI_CHANNELS; i++)
 		codec->synth.voices[i].number = i;
-	}
 
-	if ((err = snd_ali_chip_init(codec)) < 0) {
+	err = snd_ali_chip_init(codec);
+	if (err < 0) {
 		snd_printk(KERN_ERR "ali create: chip init error.\n");
 		return err;
 	}
 
 #ifdef CONFIG_PM
 	codec->image = kmalloc(sizeof(*codec->image), GFP_KERNEL);
-	if (! codec->image)
+	if (!codec->image)
 		snd_printk(KERN_WARNING "can't allocate apm buffer\n");
 #endif
 
@@ -2348,26 +2320,23 @@ static int __devinit snd_ali_probe(struct pci_dev *pci,
 	snd_ali_printk("probe ...\n");
 
 	card = snd_card_new(index, id, THIS_MODULE, 0);
-	if (card == NULL)
+	if (!card)
 		return -ENOMEM;
 
-	if ((err = snd_ali_create(card, pci, pcm_channels, spdif, &codec)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+	err = snd_ali_create(card, pci, pcm_channels, spdif, &codec);
+	if (err < 0)
+		goto error;
 	card->private_data = codec;
 
 	snd_ali_printk("mixer building ...\n");
-	if ((err = snd_ali_mixer(codec)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+	err = snd_ali_mixer(codec);
+	if (err < 0)
+		goto error;
 	
 	snd_ali_printk("pcm building ...\n");
-	if ((err = snd_ali_build_pcms(codec)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+	err = snd_ali_build_pcms(codec);
+	if (err < 0)
+		goto error;
 
 	snd_ali_proc_init(codec);
 
@@ -2378,12 +2347,16 @@ static int __devinit snd_ali_probe(struct pci_dev *pci,
 		card->shortname, codec->port, codec->irq);
 
 	snd_ali_printk("register card.\n");
-	if ((err = snd_card_register(card)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+	err = snd_card_register(card);
+	if (err < 0)
+		goto error;
+
 	pci_set_drvdata(pci, card);
 	return 0;
+
+ error:
+	snd_card_free(card);
+	return err;
 }
 
 static void __devexit snd_ali_remove(struct pci_dev *pci)
diff --git a/sound/pci/au88x0/au88x0_sb.h b/sound/pci/au88x0/au88x0_sb.h
deleted file mode 100644
index 5a4d8fc2bbfc..000000000000
--- a/sound/pci/au88x0/au88x0_sb.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/***************************************************************************
- *            au88x0_sb.h
- *
- *  Wed Oct 29 22:10:42 2003
- *  
- ****************************************************************************/
-
-#ifdef CHIP_AU8820
-/* AU8820 starting @ 64KiB offset */
-#define SBEMU_BASE 0x10000
-#else
-/* AU8810? and AU8830 starting @ 164KiB offset */
-#define SBEMU_BASE 0x29000
-#endif
-
-#define FM_A_STATUS			(SBEMU_BASE + 0x00)	/* read */
-#define FM_A_ADDRESS		(SBEMU_BASE + 0x00)	/* write */
-#define FM_A_DATA			(SBEMU_BASE + 0x04)
-#define FM_B_STATUS			(SBEMU_BASE + 0x08)
-#define FM_B_ADDRESS		(SBEMU_BASE + 0x08)
-#define FM_B_DATA			(SBEMU_BASE + 0x0C)
-#define SB_MIXER_ADDR		(SBEMU_BASE + 0x10)
-#define SB_MIXER_DATA		(SBEMU_BASE + 0x14)
-#define SB_RESET			(SBEMU_BASE + 0x18)
-#define SB_RESET_ALIAS		(SBEMU_BASE + 0x1C)
-#define FM_STATUS2			(SBEMU_BASE + 0x20)
-#define FM_ADDR2			(SBEMU_BASE + 0x20)
-#define FM_DATA2			(SBEMU_BASE + 0x24)
-#define SB_DSP_READ			(SBEMU_BASE + 0x28)
-#define SB_DSP_WRITE		(SBEMU_BASE + 0x30)
-#define SB_DSP_WRITE_STATUS	(SBEMU_BASE + 0x30)	/* bit 7 */
-#define SB_DSP_READ_STATUS	(SBEMU_BASE + 0x38)	/* bit 7 */
-#define SB_LACR				(SBEMU_BASE + 0x40)	/* ? */
-#define SB_LADCR			(SBEMU_BASE + 0x44)	/* ? */
-#define SB_LAMR				(SBEMU_BASE + 0x48)	/* ? */
-#define SB_LARR				(SBEMU_BASE + 0x4C)	/* ? */
-#define SB_VERSION			(SBEMU_BASE + 0x50)
-#define SB_CTRLSTAT			(SBEMU_BASE + 0x54)
-#define SB_TIMERSTAT		(SBEMU_BASE + 0x58)
-#define FM_RAM				(SBEMU_BASE + 0x100)	/* 0x40 ULONG */
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c
index 43edd2839b5a..36d3666a5b77 100644
--- a/sound/pci/azt3328.c
+++ b/sound/pci/azt3328.c
@@ -1,6 +1,6 @@
 /*
  *  azt3328.c - driver for Aztech AZF3328 based soundcards (e.g. PCI168).
- *  Copyright (C) 2002, 2005 by Andreas Mohr <andi AT lisas.de>
+ *  Copyright (C) 2002, 2005, 2006, 2007 by Andreas Mohr <andi AT lisas.de>
  *
  *  Framework borrowed from Bart Hartgers's als4000.c.
  *  Driver developed on PCI168 AP(W) version (PCI rev. 10, subsystem ID 1801),
@@ -52,6 +52,9 @@
  *  - full duplex 16bit playback/record at independent sampling rate
  *  - MPU401 (+ legacy address support) FIXME: how to enable legacy addr??
  *  - game port (legacy address support)
+ *  - builtin 3D enhancement (said to be YAMAHA Ymersion)
+ *  - builtin DirectInput support, helps reduce CPU overhead (interrupt-driven
+ *    features supported)
  *  - built-in General DirectX timer having a 20 bits counter
  *    with 1us resolution (see below!)
  *  - I2S serial port for external DAC
@@ -94,6 +97,10 @@
  * 
  * BUGS
  *  - full-duplex might *still* be problematic, not fully tested recently
+ *  - (non-bug) "Bass/Treble or 3D settings don't work" - they do get evaluated
+ *    if you set PCM output switch to "pre 3D" instead of "post 3D".
+ *    If this can't be set, then get a mixer application that Isn't Stupid (tm)
+ *    (e.g. kmix, gamix) - unfortunately several are!!
  * 
  * TODO
  *  - test MPU401 MIDI playback etc.
@@ -622,7 +629,7 @@ snd_azf3328_put_mixer_enum(struct snd_kcontrol *kcontrol,
 	return (nreg != oreg);
 }
 
-static const struct snd_kcontrol_new snd_azf3328_mixer_controls[] __devinitdata = {
+static struct snd_kcontrol_new snd_azf3328_mixer_controls[] __devinitdata = {
 	AZF3328_MIXER_SWITCH("Master Playback Switch", IDX_MIXER_PLAY_MASTER, 15, 1),
 	AZF3328_MIXER_VOL_STEREO("Master Playback Volume", IDX_MIXER_PLAY_MASTER, 0x1f, 1),
 	AZF3328_MIXER_SWITCH("Wave Playback Switch", IDX_MIXER_WAVEOUT, 15, 1),
@@ -652,7 +659,7 @@ static const struct snd_kcontrol_new snd_azf3328_mixer_controls[] __devinitdata
 	AZF3328_MIXER_VOL_MONO("Modem Capture Volume", IDX_MIXER_MODEMIN, 0x1f, 1),
 	AZF3328_MIXER_ENUM("Mic Select", IDX_MIXER_ADVCTL2, 2, 8),
 	AZF3328_MIXER_ENUM("Mono Output Select", IDX_MIXER_ADVCTL2, 2, 9),
-	AZF3328_MIXER_ENUM("PCM", IDX_MIXER_ADVCTL2, 2, 15), /* PCM Out Path, place in front since it controls *both* 3D and Bass/Treble! */
+	AZF3328_MIXER_ENUM("PCM Output Route", IDX_MIXER_ADVCTL2, 2, 15), /* PCM Out Path, place in front since it controls *both* 3D and Bass/Treble! */
 	AZF3328_MIXER_VOL_SPECIAL("Tone Control - Treble", IDX_MIXER_BASSTREBLE, 0x07, 1, 0),
 	AZF3328_MIXER_VOL_SPECIAL("Tone Control - Bass", IDX_MIXER_BASSTREBLE, 0x07, 9, 0),
 	AZF3328_MIXER_SWITCH("3D Control - Switch", IDX_MIXER_ADVCTL2, 13, 0),
@@ -678,7 +685,7 @@ static const struct snd_kcontrol_new snd_azf3328_mixer_controls[] __devinitdata
 #endif
 };
 
-static const u16 __devinitdata snd_azf3328_init_values[][2] = {
+static u16 __devinitdata snd_azf3328_init_values[][2] = {
         { IDX_MIXER_PLAY_MASTER,	MIXER_MUTE_MASK|0x1f1f },
         { IDX_MIXER_MODEMOUT,		MIXER_MUTE_MASK|0x1f1f },
 	{ IDX_MIXER_BASSTREBLE,		0x0000 },
@@ -1369,7 +1376,6 @@ snd_azf3328_playback_close(struct snd_pcm_substream *substream)
 	struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);
 
 	snd_azf3328_dbgcallenter();
-
 	chip->playback_substream = NULL;
 	snd_azf3328_dbgcallleave();
 	return 0;
@@ -1660,10 +1666,10 @@ snd_azf3328_test_bit(unsigned int reg, int bit)
 }
 #endif
 
+#if DEBUG_MISC
 static void
 snd_azf3328_debug_show_ports(const struct snd_azf3328 *chip)
 {
-#if DEBUG_MISC
 	u16 tmp;
 
 	snd_azf3328_dbgmisc("codec_port 0x%lx, io2_port 0x%lx, mpu_port 0x%lx, synth_port 0x%lx, mixer_port 0x%lx, irq %d\n", chip->codec_port, chip->io2_port, chip->mpu_port, chip->synth_port, chip->mixer_port, chip->irq);
@@ -1673,10 +1679,16 @@ snd_azf3328_debug_show_ports(const struct snd_azf3328 *chip)
 	for (tmp=0; tmp <= 0x01; tmp += 1)
 		snd_azf3328_dbgmisc("0x%02x: opl 0x%04x, mpu300 0x%04x, mpu310 0x%04x, mpu320 0x%04x, mpu330 0x%04x\n", tmp, inb(0x388 + tmp), inb(0x300 + tmp), inb(0x310 + tmp), inb(0x320 + tmp), inb(0x330 + tmp));
 
-	for (tmp = 0; tmp <= 0x6E; tmp += 2)
-		snd_azf3328_dbgmisc("0x%02x: 0x%04x\n", tmp, snd_azf3328_codec_inb(chip, tmp));
-#endif
+	for (tmp = 0; tmp < AZF_IO_SIZE_CODEC; tmp += 2)
+		snd_azf3328_dbgmisc("codec 0x%02x: 0x%04x\n", tmp, snd_azf3328_codec_inw(chip, tmp));
+
+	for (tmp = 0; tmp < AZF_IO_SIZE_MIXER; tmp += 2)
+		snd_azf3328_dbgmisc("mixer 0x%02x: 0x%04x\n", tmp, snd_azf3328_mixer_inw(chip, tmp));
 }
+#else
+static inline void
+snd_azf3328_debug_show_ports(const struct snd_azf3328 *chip) {}
+#endif
 
 static int __devinit
 snd_azf3328_create(struct snd_card *card,
@@ -1842,8 +1854,8 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
 
 #ifdef MODULE
 	printk(
-"azt3328: Sound driver for Aztech AZF3328-based soundcards such as PCI168\n"
-"azt3328: (hardware was completely undocumented - ZERO support from Aztech).\n"
+"azt3328: Sound driver for Aztech AZF3328-based soundcards such as PCI168.\n"
+"azt3328: Hardware was completely undocumented, unfortunately.\n"
 "azt3328: Feel free to contact andi AT lisas.de for bug reports etc.!\n"
 "azt3328: User-scalable sequencer timer set to %dHz (1024000Hz / %d).\n",
 	1024000 / seqtimer_scaling, seqtimer_scaling);
diff --git a/sound/pci/azt3328.h b/sound/pci/azt3328.h
index b4f3e3cd006b..679fa992e2bc 100644
--- a/sound/pci/azt3328.h
+++ b/sound/pci/azt3328.h
@@ -106,8 +106,8 @@
   #define IRQ_RECORDING			0x0002
   #define IRQ_MPU401			0x0010
   #define IRQ_TIMER			0x0020 /* DirectX timer */
-  #define IRQ_UNKNOWN1			0x0040 /* probably unused */
-  #define IRQ_UNKNOWN2			0x0080 /* probably unused */
+  #define IRQ_UNKNOWN1			0x0040 /* probably unused, or possibly I2S port? or gameport IRQ? */
+  #define IRQ_UNKNOWN2			0x0080 /* probably unused, or possibly I2S port? or gameport IRQ? */
 #define IDX_IO_66H		0x66    /* writing 0xffff returns 0x0000 */
 #define IDX_IO_SOME_VALUE	0x68	/* this is set to e.g. 0x3ff or 0x300, and writable; maybe some buffer limit, but I couldn't find out more, PU:0x00ff */
 #define IDX_IO_6AH		0x6A	/* this WORD can be set to have bits 0x0028 activated (FIXME: correct??); actually inhibits PCM playback!!! maybe power management?? */
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c
index e9b029e1cd6d..6523ba07db96 100644
--- a/sound/pci/bt87x.c
+++ b/sound/pci/bt87x.c
@@ -781,6 +781,8 @@ static struct pci_device_id snd_bt87x_ids[] = {
 	BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_879, 0x0070, 0x13eb, 32000),
 	/* Viewcast Osprey 200 */
 	BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0xff01, 44100),
+	/* ATI TV-Wonder */
+	BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x1002, 0x0001, 32000),
 	/* Leadtek Winfast tv 2000xp delux */
 	BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x107d, 0x6606, 32000),
 	/* Voodoo TV 200 */
@@ -833,7 +835,7 @@ static int __devinit snd_bt87x_detect_card(struct pci_dev *pci)
 	           pci->device, pci->subsystem_vendor, pci->subsystem_device);
 	snd_printk(KERN_DEBUG "please mail id, board name, and, "
 		   "if it works, the correct digital_rate option to "
-		   "<alsa-devel@lists.sf.net>\n");
+		   "<alsa-devel@alsa-project.org>\n");
 	return 32000; /* default rate */
 }
 
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
index ea6712b63c9f..48f3f17c5170 100644
--- a/sound/pci/ca0106/ca0106_main.c
+++ b/sound/pci/ca0106/ca0106_main.c
@@ -775,7 +775,6 @@ static int snd_ca0106_pcm_trigger_playback(struct snd_pcm_substream *substream,
 	struct snd_ca0106_pcm *epcm;
 	int channel;
 	int result = 0;
-	struct list_head *pos;
         struct snd_pcm_substream *s;
 	u32 basic = 0;
 	u32 extended = 0;
@@ -790,8 +789,7 @@ static int snd_ca0106_pcm_trigger_playback(struct snd_pcm_substream *substream,
 		running=0;
 		break;
 	}
-        snd_pcm_group_for_each(pos, substream) {
-                s = snd_pcm_group_substream_entry(pos);
+        snd_pcm_group_for_each_entry(s, substream) {
 		runtime = s->runtime;
 		epcm = runtime->private_data;
 		channel = epcm->channel_id;
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c
index 2ae539b195fd..bef1f6d1859c 100644
--- a/sound/pci/cs46xx/cs46xx_lib.c
+++ b/sound/pci/cs46xx/cs46xx_lib.c
@@ -3107,7 +3107,7 @@ static int snd_cs46xx_chip_init(struct snd_cs46xx *chip)
 	snd_printk(KERN_ERR "ERROR: snd-cs46xx: never read ISV3 & ISV4 from AC'97\n");
 	snd_printk(KERN_ERR "       Try reloading the ALSA driver, if you find something\n");
         snd_printk(KERN_ERR "       broken or not working on your soundcard upon\n");
-	snd_printk(KERN_ERR "       this message please report to alsa-devel@lists.sourceforge.net\n");
+	snd_printk(KERN_ERR "       this message please report to alsa-devel@alsa-project.org\n");
 
 	return -EIO;
 #endif
diff --git a/sound/pci/cs46xx/imgs/cwcemb80.h b/sound/pci/cs46xx/imgs/cwcemb80.h
deleted file mode 100644
index a64c6ff9983a..000000000000
--- a/sound/pci/cs46xx/imgs/cwcemb80.h
+++ /dev/null
@@ -1,1607 +0,0 @@
-/* generated from cwcemb80.osp DO NOT MODIFY */
-
-#ifndef __HEADER_cwcemb80_H__
-#define __HEADER_cwcemb80_H__
-
-static struct dsp_symbol_entry cwcemb80_symbols[] = {
-  { 0x0000, "BEGINADDRESS",0x00 },
-  { 0x8000, "EXECCHILD",0x03 },
-  { 0x8001, "EXECCHILD_98",0x03 },
-  { 0x8003, "EXECCHILD_PUSH1IND",0x03 },
-  { 0x8008, "EXECSIBLING",0x03 },
-  { 0x800a, "EXECSIBLING_298",0x03 },
-  { 0x800b, "EXECSIBLING_2IND1",0x03 },
-  { 0x8010, "TIMINGMASTER",0x03 },
-  { 0x804f, "S16_CODECINPUTTASK",0x03 },
-  { 0x805e, "PCMSERIALINPUTTASK",0x03 },
-  { 0x806d, "S16_MIX_TO_OSTREAM",0x03 },
-  { 0x809a, "S16_MIX",0x03 },
-  { 0x80bb, "S16_UPSRC",0x03 },
-  { 0x813b, "MIX3_EXP",0x03 },
-  { 0x8164, "DECIMATEBYPOW2",0x03 },
-  { 0x8197, "VARIDECIMATE",0x03 },
-  { 0x81f2, "_3DINPUTTASK",0x03 },
-  { 0x820a, "_3DPRLGCINPTASK",0x03 },
-  { 0x8227, "_3DSTEREOINPUTTASK",0x03 },
-  { 0x8242, "_3DOUTPUTTASK",0x03 },
-  { 0x82c4, "HRTF_MORPH_TASK",0x03 },
-  { 0x82c6, "WAIT4DATA",0x03 },
-  { 0x82fa, "PROLOGIC",0x03 },
-  { 0x8496, "DECORRELATOR",0x03 },
-  { 0x84a4, "STEREO2MONO",0x03 },
-  { 0x0070, "SPOSCB",0x02 },
-  { 0x0105, "TASKTREETHREAD",0x03 },
-  { 0x0136, "TASKTREEHEADERCODE",0x03 },
-  { 0x013f, "FGTASKTREEHEADERCODE",0x03 },
-  { 0x0163, "NULLALGORITHM",0x03 },
-  { 0x0167, "HFGEXECCHILD",0x03 },
-  { 0x0168, "HFGEXECCHILD_98",0x03 },
-  { 0x016a, "HFGEXECCHILD_PUSH1IND",0x03 },
-  { 0x016d, "HFGEXECSIBLING",0x03 },
-  { 0x016f, "HFGEXECSIBLING_298",0x03 },
-  { 0x0170, "HFGEXECSIBLING_2IND1",0x03 },
-  { 0x0173, "S16_CODECOUTPUTTASK",0x03 },
-  { 0x018e, "#CODE_END",0x00 },
-}; /* cwcemb80 symbols */
-
-static u32 cwcemb80_code[] = {
-/* BEGINADDRESS */
-/* 0000 */ 0x00040730,0x00001002,0x000f619e,0x00001003,
-/* 0002 */ 0x00001705,0x00001400,0x000a411e,0x00001003,
-/* 0004 */ 0x00040730,0x00001002,0x000f619e,0x00001003,
-/* 0006 */ 0x00009705,0x00001400,0x000a411e,0x00001003,
-/* 0008 */ 0x00040730,0x00001002,0x000f619e,0x00001003,
-/* 000A */ 0x00011705,0x00001400,0x000a411e,0x00001003,
-/* 000C */ 0x00040730,0x00001002,0x000f619e,0x00001003,
-/* 000E */ 0x00019705,0x00001400,0x000a411e,0x00001003,
-/* 0010 */ 0x00040730,0x00001002,0x000f619e,0x00001003,
-/* 0012 */ 0x00021705,0x00001400,0x000a411e,0x00001003,
-/* 0014 */ 0x00040730,0x00001002,0x000f619e,0x00001003,
-/* 0016 */ 0x00029705,0x00001400,0x000a411e,0x00001003,
-/* 0018 */ 0x00040730,0x00001002,0x000f619e,0x00001003,
-/* 001A */ 0x00031705,0x00001400,0x000a411e,0x00001003,
-/* 001C */ 0x00040730,0x00001002,0x000f619e,0x00001003,
-/* 001E */ 0x00039705,0x00001400,0x000a411e,0x00001003,
-/* 0020 */ 0x000fe19e,0x00001003,0x0009c730,0x00001003,
-/* 0022 */ 0x0008e19c,0x00001003,0x000083c1,0x00093040,
-/* 0024 */ 0x00098730,0x00001002,0x000ee19e,0x00001003,
-/* 0026 */ 0x00009705,0x00001400,0x000a211e,0x00001003,
-/* 0028 */ 0x00098730,0x00001002,0x000ee19e,0x00001003,
-/* 002A */ 0x00011705,0x00001400,0x000a211e,0x00001003,
-/* 002C */ 0x00098730,0x00001002,0x000ee19e,0x00001003,
-/* 002E */ 0x00019705,0x00001400,0x000a211e,0x00001003,
-/* 0030 */ 0x00098730,0x00001002,0x000ee19e,0x00001003,
-/* 0032 */ 0x00021705,0x00001400,0x000a211e,0x00001003,
-/* 0034 */ 0x00098730,0x00001002,0x000ee19e,0x00001003,
-/* 0036 */ 0x00029705,0x00001400,0x000a211e,0x00001003,
-/* 0038 */ 0x00098730,0x00001002,0x000ee19e,0x00001003,
-/* 003A */ 0x00031705,0x00001400,0x000a211e,0x00001003,
-/* 003C */ 0x00098730,0x00001002,0x000ee19e,0x00001003,
-/* 003E */ 0x00039705,0x00001400,0x000a211e,0x00001003,
-/* 0040 */ 0x0000a730,0x00001008,0x000e2730,0x00001002,
-/* 0042 */ 0x0000a731,0x00001002,0x0000a731,0x00001002,
-/* 0044 */ 0x0000a731,0x00001002,0x0000a731,0x00001002,
-/* 0046 */ 0x0000a731,0x00001002,0x0000a731,0x00001002,
-/* 0048 */ 0x00000000,0x00000000,0x000f619c,0x00001003,
-/* 004A */ 0x0007f801,0x000c0000,0x00000037,0x00001000,
-/* 004C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 004E */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0050 */ 0x00000000,0x000c0000,0x00000000,0x00000000,
-/* 0052 */ 0x0000373c,0x00001000,0x00000000,0x00000000,
-/* 0054 */ 0x000ee19c,0x00001003,0x0007f801,0x000c0000,
-/* 0056 */ 0x00000037,0x00001000,0x00000000,0x00000000,
-/* 0058 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 005A */ 0x00000000,0x00000000,0x0000273c,0x00001000,
-/* 005C */ 0x00000033,0x00001000,0x000e679e,0x00001003,
-/* 005E */ 0x00007705,0x00001400,0x000ac71e,0x00001003,
-/* 0060 */ 0x00087fc1,0x000c3be0,0x0007f801,0x000c0000,
-/* 0062 */ 0x00000037,0x00001000,0x00000000,0x00000000,
-/* 0064 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0066 */ 0x00000000,0x00000000,0x0000a730,0x00001003,
-/* 0068 */ 0x00000033,0x00001000,0x0007f801,0x000c0000,
-/* 006A */ 0x00000037,0x00001000,0x00000000,0x00000000,
-/* 006C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 006E */ 0x00000000,0x00000000,0x00000000,0x000c0000,
-/* 0070 */ 0x00000032,0x00001000,0x0000273d,0x00001000,
-/* 0072 */ 0x0004a730,0x00001003,0x00000f41,0x00097140,
-/* 0074 */ 0x0000a841,0x0009b240,0x0000a0c1,0x0009f040,
-/* 0076 */ 0x0001c641,0x00093540,0x0001cec1,0x0009b5c0,
-/* 0078 */ 0x00000000,0x00000000,0x0001bf05,0x0003fc40,
-/* 007A */ 0x00002725,0x000aa400,0x00013705,0x00093a00,
-/* 007C */ 0x0000002e,0x0009d6c0,0x00038630,0x00001004,
-/* 007E */ 0x0004ef0a,0x000eb785,0x0003fc8a,0x00000000,
-/* 0080 */ 0x00000000,0x000c70e0,0x0007d182,0x0002c640,
-/* 0082 */ 0x00000630,0x00001004,0x000799b8,0x0002c6c0,
-/* 0084 */ 0x00031705,0x00092240,0x00039f05,0x000932c0,
-/* 0086 */ 0x0003520a,0x00000000,0x00040731,0x0000100b,
-/* 0088 */ 0x00010705,0x000b20c0,0x00000000,0x000eba44,
-/* 008A */ 0x00032108,0x000c60c4,0x00065208,0x000c2917,
-/* 008C */ 0x000406b0,0x00001007,0x00012f05,0x00036880,
-/* 008E */ 0x0002818e,0x000c0000,0x0004410a,0x00000000,
-/* 0090 */ 0x00040630,0x00001007,0x00029705,0x000c0000,
-/* 0092 */ 0x00000000,0x00000000,0x00003fc1,0x0003fc40,
-/* 0094 */ 0x000037c1,0x00091b40,0x00003fc1,0x000911c0,
-/* 0096 */ 0x000037c1,0x000957c0,0x00003fc1,0x000951c0,
-/* 0098 */ 0x000037c1,0x00000000,0x00003fc1,0x000991c0,
-/* 009A */ 0x000037c1,0x00000000,0x00003fc1,0x0009d1c0,
-/* 009C */ 0x000037c1,0x00000000,0x0001ccc1,0x000915c0,
-/* 009E */ 0x0001c441,0x0009d800,0x0009cdc1,0x00091240,
-/* 00A0 */ 0x0001c541,0x00091d00,0x0009cfc1,0x00095240,
-/* 00A2 */ 0x0001c741,0x00095c80,0x000e8ca9,0x00099240,
-/* 00A4 */ 0x000e85ad,0x00095640,0x00069ca9,0x00099d80,
-/* 00A6 */ 0x000e952d,0x00099640,0x000eaca9,0x0009d6c0,
-/* 00A8 */ 0x000ea5ad,0x00091a40,0x0006bca9,0x0009de80,
-/* 00AA */ 0x000eb52d,0x00095a40,0x000ecca9,0x00099ac0,
-/* 00AC */ 0x000ec5ad,0x0009da40,0x000edca9,0x0009d300,
-/* 00AE */ 0x000a6e0a,0x00001000,0x000ed52d,0x00091e40,
-/* 00B0 */ 0x000eeca9,0x00095ec0,0x000ee5ad,0x00099e40,
-/* 00B2 */ 0x0006fca9,0x00002500,0x000fb208,0x000c59a0,
-/* 00B4 */ 0x000ef52d,0x0009de40,0x00068ca9,0x000912c1,
-/* 00B6 */ 0x000683ad,0x00095241,0x00020f05,0x000991c1,
-/* 00B8 */ 0x00000000,0x00000000,0x00086f88,0x00001000,
-/* 00BA */ 0x0009cf81,0x000b5340,0x0009c701,0x000b92c0,
-/* 00BC */ 0x0009de81,0x000bd300,0x0009d601,0x000b1700,
-/* 00BE */ 0x0001fd81,0x000b9d80,0x0009f501,0x000b57c0,
-/* 00C0 */ 0x000a0f81,0x000bd740,0x00020701,0x000b5c80,
-/* 00C2 */ 0x000a1681,0x000b97c0,0x00021601,0x00002500,
-/* 00C4 */ 0x000a0701,0x000b9b40,0x000a0f81,0x000b1bc0,
-/* 00C6 */ 0x00021681,0x00002d00,0x00020f81,0x000bd800,
-/* 00C8 */ 0x000a0701,0x000b5bc0,0x00021601,0x00003500,
-/* 00CA */ 0x000a0f81,0x000b5f40,0x000a0701,0x000bdbc0,
-/* 00CC */ 0x00021681,0x00003d00,0x00020f81,0x000b1d00,
-/* 00CE */ 0x000a0701,0x000b1fc0,0x00021601,0x00020500,
-/* 00D0 */ 0x00020f81,0x000b1341,0x000a0701,0x000b9fc0,
-/* 00D2 */ 0x00021681,0x00020d00,0x00020f81,0x000bde80,
-/* 00D4 */ 0x000a0701,0x000bdfc0,0x00021601,0x00021500,
-/* 00D6 */ 0x00020f81,0x000b9341,0x00020701,0x000b53c1,
-/* 00D8 */ 0x00021681,0x00021d00,0x000a0f81,0x000d0380,
-/* 00DA */ 0x0000b601,0x000b15c0,0x00007b01,0x00000000,
-/* 00DC */ 0x00007b81,0x000bd1c0,0x00007b01,0x00000000,
-/* 00DE */ 0x00007b81,0x000b91c0,0x00007b01,0x000b57c0,
-/* 00E0 */ 0x00007b81,0x000b51c0,0x00007b01,0x000b1b40,
-/* 00E2 */ 0x00007b81,0x000b11c0,0x00087b01,0x000c3dc0,
-/* 00E4 */ 0x0007e488,0x000d7e45,0x00000000,0x000d7a44,
-/* 00E6 */ 0x0007e48a,0x00000000,0x00011f05,0x00084080,
-/* 00E8 */ 0x00000000,0x00000000,0x00001705,0x000b3540,
-/* 00EA */ 0x00008a01,0x000bf040,0x00007081,0x000bb5c0,
-/* 00EC */ 0x00055488,0x00000000,0x0000d482,0x0003fc40,
-/* 00EE */ 0x0003fc88,0x00000000,0x0001e401,0x000b3a00,
-/* 00F0 */ 0x0001ec81,0x000bd6c0,0x0004ef08,0x000eb784,
-/* 00F2 */ 0x000c86b0,0x00001007,0x00008281,0x000bb240,
-/* 00F4 */ 0x0000b801,0x000b7140,0x00007888,0x00000000,
-/* 00F6 */ 0x0000073c,0x00001000,0x0007f188,0x000c0000,
-/* 00F8 */ 0x00000000,0x00000000,0x00055288,0x000c555c,
-/* 00FA */ 0x0005528a,0x000c0000,0x0009fa88,0x000c5d00,
-/* 00FC */ 0x0000fa88,0x00000000,0x00000032,0x00001000,
-/* 00FE */ 0x0000073d,0x00001000,0x0007f188,0x000c0000,
-/* 0100 */ 0x00000000,0x00000000,0x0008c01c,0x00001003,
-/* 0102 */ 0x00002705,0x00001008,0x0008b201,0x000c1392,
-/* 0104 */ 0x0000ba01,0x00000000,
-/* TASKTREETHREAD */
-/* 0105 */ 0x00008731,0x00001400,0x0004c108,0x000fe0c4,
-/* 0107 */ 0x00057488,0x00000000,0x000a6388,0x00001001,
-/* 0109 */ 0x0008b334,0x000bc141,0x0003020e,0x00000000,
-/* 010B */ 0x000886b0,0x00001008,0x00003625,0x000c5dfa,
-/* 010D */ 0x000a638a,0x00001001,0x0008020e,0x00001002,
-/* 010F */ 0x0008a6b0,0x00001008,0x0007f301,0x00000000,
-/* 0111 */ 0x00000000,0x00000000,0x00002725,0x000a8c40,
-/* 0113 */ 0x000000ae,0x00000000,0x000d8630,0x00001008,
-/* 0115 */ 0x00000000,0x000c74e0,0x0007d182,0x0002d640,
-/* 0117 */ 0x000a8630,0x00001008,0x000799b8,0x0002d6c0,
-/* 0119 */ 0x0000748a,0x000c3ec5,0x0007420a,0x000c0000,
-/* 011B */ 0x00062208,0x000c4117,0x00070630,0x00001009,
-/* 011D */ 0x00000000,0x000c0000,0x0001022e,0x00000000,
-/* 011F */ 0x0003a630,0x00001009,0x00000000,0x000c0000,
-/* 0121 */ 0x00000036,0x00001000,0x00000000,0x00000000,
-/* 0123 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0125 */ 0x00000000,0x00000000,0x0002a730,0x00001008,
-/* 0127 */ 0x0007f801,0x000c0000,0x00000037,0x00001000,
-/* 0129 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 012B */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 012D */ 0x0002a730,0x00001008,0x00000033,0x00001000,
-/* 012F */ 0x0002a705,0x00001008,0x00007a01,0x000c0000,
-/* 0131 */ 0x000e6288,0x000d550a,0x0006428a,0x00000000,
-/* 0133 */ 0x00060730,0x0000100a,0x00000000,0x000c0000,
-/* 0135 */ 0x00000000,0x00000000,
-/* TASKTREEHEADERCODE */
-/* 0136 */ 0x0007aab0,0x00034880,0x00078fb0,0x0000100b,
-/* 0138 */ 0x00057488,0x00000000,0x00033b94,0x00081140,
-/* 013A */ 0x000183ae,0x00000000,0x000786b0,0x0000100b,
-/* 013C */ 0x00022f05,0x000c3545,0x0000eb8a,0x00000000,
-/* 013E */ 0x00042731,0x00001003,
-/* FGTASKTREEHEADERCODE */
-/* 013F */ 0x0007aab0,0x00034880,0x00048fb0,0x0000100a,
-/* 0141 */ 0x00057488,0x00000000,0x00033b94,0x00081140,
-/* 0143 */ 0x000183ae,0x00000000,0x000806b0,0x0000100b,
-/* 0145 */ 0x00022f05,0x00000000,0x00007401,0x00091140,
-/* 0147 */ 0x00048f05,0x000951c0,0x00042731,0x00001003,
-/* 0149 */ 0x0000473d,0x00001000,0x000f19b0,0x000bbc47,
-/* 014B */ 0x00080000,0x000bffc7,0x000fe19e,0x00001003,
-/* 014D */ 0x00000000,0x00000000,0x0008e19c,0x00001003,
-/* 014F */ 0x000083c1,0x00093040,0x00000f41,0x00097140,
-/* 0151 */ 0x0000a841,0x0009b240,0x0000a0c1,0x0009f040,
-/* 0153 */ 0x0001c641,0x00093540,0x0001cec1,0x0009b5c0,
-/* 0155 */ 0x00000000,0x000fdc44,0x00055208,0x00000000,
-/* 0157 */ 0x00010705,0x000a2880,0x0000a23a,0x00093a00,
-/* 0159 */ 0x0003fc8a,0x000df6c5,0x0004ef0a,0x000c0000,
-/* 015B */ 0x00012f05,0x00036880,0x00065308,0x000c2997,
-/* 015D */ 0x000d86b0,0x0000100a,0x0004410a,0x000d40c7,
-/* 015F */ 0x00000000,0x00000000,0x00080730,0x00001004,
-/* 0161 */ 0x00056f0a,0x000ea105,0x00000000,0x00000000,
-/* NULLALGORITHM */
-/* 0163 */ 0x0000473d,0x00001000,0x000f19b0,0x000bbc47,
-/* 0165 */ 0x00080000,0x000bffc7,0x0000273d,0x00001000,
-/* HFGEXECCHILD */
-/* 0167 */ 0x00000000,0x000eba44,
-/* HFGEXECCHILD_98 */
-/* 0168 */ 0x00048f05,0x0000f440,0x00007401,0x0000f7c0,
-/* HFGEXECCHILD_PUSH1IND */
-/* 016A */ 0x00000734,0x00001000,0x00010705,0x000a6880,
-/* 016C */ 0x00006a88,0x000c75c4,
-/* HFGEXECSIBLING */
-/* 016D */ 0x00000000,0x000e5084,0x00000000,0x000eba44,
-/* HFGEXECSIBLING_298 */
-/* 016F */ 0x00087401,0x000e4782,
-/* HFGEXECSIBLING_2IND1 */
-/* 0170 */ 0x00000734,0x00001000,0x00010705,0x000a6880,
-/* 0172 */ 0x00006a88,0x000c75c4,
-/* S16_CODECOUTPUTTASK */
-/* 0173 */ 0x0007c108,0x000c0000,0x0007e721,0x000bed40,
-/* 0175 */ 0x00005f25,0x000badc0,0x0003ba97,0x000beb80,
-/* 0177 */ 0x00065590,0x000b2e00,0x00033217,0x00003ec0,
-/* 0179 */ 0x00065590,0x000b8e40,0x0003ed80,0x000491c0,
-/* 017B */ 0x00073fb0,0x00074c80,0x000283a0,0x0000100c,
-/* 017D */ 0x000ee388,0x00042970,0x00008301,0x00021ef2,
-/* 017F */ 0x000b8f14,0x0000000f,0x000c4d8d,0x0000001b,
-/* 0181 */ 0x000d6dc2,0x000e06c6,0x000032ac,0x000c3916,
-/* 0183 */ 0x0004edc2,0x00074c80,0x00078898,0x00001000,
-/* 0185 */ 0x00038894,0x00000032,0x000c4d8d,0x00092e1b,
-/* 0187 */ 0x000d6dc2,0x000e06c6,0x0004edc2,0x000c1956,
-/* 0189 */ 0x0000722c,0x00034a00,0x00041705,0x0009ed40,
-/* 018B */ 0x00058730,0x00001400,0x000d7488,0x000c3a00,
-/* 018D */ 0x00048f05,0x00000000
-};
-/* #CODE_END */
-
-static u32 cwcemb80_parameter[] = {
-/* 0000 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0004 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0008 */ 0x00000000,0x00000000,0x00000163,0x00000000,
-/* 000C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0010 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0014 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0018 */ 0x00000000,0x00200040,0x00008010,0x00000000,
-/* 001C */ 0x00000000,0x80000001,0x00000001,0x00060000,
-/* 0020 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0024 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0028 */ 0x00000000,0x00900080,0x00000173,0x00000000,
-/* 002C */ 0x00000000,0x00000010,0x00800000,0x00900000,
-/* 0030 */ 0xf2c0000f,0x00000200,0x00000000,0x00010600,
-/* 0034 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0038 */ 0x00000000,0x00000000,0x00000163,0x330300c2,
-/* 003C */ 0x06000000,0x00000000,0x80008000,0x80008000,
-/* 0040 */ 0x3fc0000f,0x00000301,0x00010400,0x00000000,
-/* 0044 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0048 */ 0x00000000,0x00b00000,0x00d0806d,0x330480c3,
-/* 004C */ 0x04800000,0x00000001,0x00800001,0x0000ffff,
-/* 0050 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0054 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0058 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 005C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0060 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0064 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0068 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 006C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0070 */ 0x066a0600,0x06350070,0x0000929d,0x929d929d,
-/* 0074 */ 0x00000000,0x0000735a,0x00000600,0x00000000,
-/* 0078 */ 0x929d735a,0x00000000,0x00010000,0x735a735a,
-/* 007C */ 0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-/* 0080 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0084 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0088 */ 0x00000000,0x00000000,0x0000804f,0x000000c3,
-/* 008C */ 0x05000000,0x00a00010,0x00000000,0x80008000,
-/* 0090 */ 0x00000000,0x00000000,0x00000700,0x00000000,
-/* 0094 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0098 */ 0x00000080,0x00a00000,0x0000809a,0x000000c2,
-/* 009C */ 0x07400000,0x00000000,0x80008000,0xffffffff,
-/* 00A0 */ 0x00c80028,0x00005555,0x00000000,0x000107a0,
-/* 00A4 */ 0x00c80028,0x000000c2,0x06800000,0x00000000,
-/* 00A8 */ 0x06e00080,0x00300000,0x000080bb,0x000000c9,
-/* 00AC */ 0x07a00000,0x04000000,0x80008000,0xffffffff,
-/* 00B0 */ 0x00c80028,0x00005555,0x00000000,0x00000780,
-/* 00B4 */ 0x00c80028,0x000000c5,0xff800000,0x00000000,
-/* 00B8 */ 0x00640080,0x00c00000,0x00008197,0x000000c9,
-/* 00BC */ 0x07800000,0x04000000,0x80008000,0xffffffff,
-/* 00C0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 00C4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 00C8 */ 0x00000000,0x00000000,0x0000805e,0x000000c1,
-/* 00CC */ 0x00000000,0x00800000,0x80008000,0x80008000,
-/* 00D0 */ 0x00020000,0x0000ffff,0x00000000,0x00000000,
-/* 00D4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 00D8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 00DC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 00E0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 00E4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 00E8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 00EC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 00F0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 00F4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 00F8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 00FC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0100 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0104 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0108 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 010C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0110 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0114 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0118 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 011C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0120 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0124 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0128 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 012C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0130 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0134 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0138 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 013C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0140 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0144 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0148 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 014C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0150 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0154 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0158 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 015C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0160 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0164 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0168 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 016C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0170 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0174 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0178 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 017C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0180 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0184 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0188 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 018C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0190 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0194 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0198 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 019C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 01A0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 01A4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 01A8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 01AC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 01B0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 01B4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 01B8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 01BC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 01C0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 01C4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 01C8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 01CC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 01D0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 01D4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 01D8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 01DC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 01E0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 01E4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 01E8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 01EC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 01F0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 01F4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 01F8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 01FC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0200 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0204 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0208 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 020C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0210 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0214 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0218 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 021C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0220 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0224 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0228 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 022C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0230 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0234 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0238 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 023C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0240 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0244 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0248 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 024C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0250 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0254 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0258 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 025C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0260 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0264 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0268 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 026C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0270 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0274 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0278 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 027C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0280 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0284 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0288 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 028C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0290 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0294 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0298 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 029C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 02A0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 02A4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 02A8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 02AC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 02B0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 02B4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 02B8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 02BC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 02C0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 02C4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 02C8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 02CC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 02D0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 02D4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 02D8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 02DC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 02E0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 02E4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 02E8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 02EC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 02F0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 02F4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 02F8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 02FC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0300 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0304 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0308 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 030C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0310 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0314 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0318 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 031C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0320 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0324 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0328 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 032C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0330 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0334 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0338 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 033C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0340 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0344 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0348 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 034C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0350 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0354 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0358 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 035C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0360 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0364 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0368 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 036C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0370 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0374 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0378 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 037C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0380 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0384 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0388 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 038C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0390 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0394 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0398 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 039C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 03A0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 03A4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 03A8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 03AC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 03B0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 03B4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 03B8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 03BC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 03C0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 03C4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 03C8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 03CC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 03D0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 03D4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 03D8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 03DC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 03E0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 03E4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 03E8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 03EC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 03F0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 03F4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 03F8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 03FC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0400 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0404 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0408 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 040C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0410 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0414 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0418 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 041C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0420 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0424 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0428 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 042C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0430 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0434 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0438 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 043C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0440 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0444 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0448 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 044C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0450 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0454 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0458 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 045C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0460 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0464 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0468 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 046C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0470 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0474 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0478 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 047C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0480 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0484 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0488 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 048C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0490 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0494 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0498 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 049C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 04A0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 04A4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 04A8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 04AC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 04B0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 04B4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 04B8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 04BC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 04C0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 04C4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 04C8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 04CC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 04D0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 04D4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 04D8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 04DC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 04E0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 04E4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 04E8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 04EC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 04F0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 04F4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 04F8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 04FC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0500 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0504 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0508 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 050C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0510 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0514 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0518 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 051C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0520 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0524 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0528 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 052C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0530 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0534 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0538 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 053C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0540 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0544 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0548 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 054C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0550 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0554 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0558 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 055C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0560 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0564 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0568 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 056C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0570 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0574 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0578 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 057C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0580 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0584 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0588 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 058C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0590 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0594 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0598 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 059C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 05A0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 05A4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 05A8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 05AC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 05B0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 05B4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 05B8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 05BC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 05C0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 05C4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 05C8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 05CC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 05D0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 05D4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 05D8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 05DC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 05E0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 05E4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 05E8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 05EC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 05F0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 05F4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 05F8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 05FC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0600 */ 0x929d0600,0x929d929d,0x929d929d,0x929d0000,
-/* 0604 */ 0x929d929d,0x929d929d,0x929d929d,0x929d929d,
-/* 0608 */ 0x929d929d,0x00100635,0x060b013f,0x00000004,
-/* 060C */ 0x00000001,0x007a0002,0x00000000,0x066e0610,
-/* 0610 */ 0x0105929d,0x929d929d,0x929d929d,0x929d929d,
-/* 0614 */ 0x929d929d,0xa431ac75,0x0001735a,0xa431ac75,
-/* 0618 */ 0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-/* 061C */ 0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-/* 0620 */ 0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-/* 0624 */ 0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-/* 0628 */ 0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-/* 062C */ 0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-/* 0630 */ 0xa431ac75,0xa431ac75,0xa431ac75,0x735a0051,
-/* 0634 */ 0x00000000,0x929d929d,0x929d929d,0x929d929d,
-/* 0638 */ 0x929d929d,0x929d929d,0x929d929d,0x929d929d,
-/* 063C */ 0x929d929d,0x929d929d,0x00000000,0x06400136,
-/* 0640 */ 0x0000270f,0x00010000,0x007a0000,0x00000000,
-/* 0644 */ 0x068e0645,0x0105929d,0x929d929d,0x929d929d,
-/* 0648 */ 0x929d929d,0x929d929d,0xa431ac75,0x0001735a,
-/* 064C */ 0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-/* 0650 */ 0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-/* 0654 */ 0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-/* 0658 */ 0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-/* 065C */ 0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-/* 0660 */ 0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-/* 0664 */ 0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75,
-/* 0668 */ 0x735a0100,0x00000000,0x00000000,0x00000000,
-/* 066C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0670 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0674 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0678 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 067C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0680 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0684 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0688 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 068C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0690 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0694 */ 0x00000000,0x00000000,0x00000000
-}; /* #PARAMETER_END */
-
-static u32 cwcemb80_sample[] = {
-/* 0000 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0004 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0008 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 000C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0010 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0014 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0018 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 001C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0020 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0024 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0028 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 002C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0030 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0034 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0038 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 003C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0040 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0044 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0048 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 004C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0050 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0054 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0058 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 005C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0060 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0064 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0068 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 006C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0070 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0074 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0078 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 007C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0080 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0084 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0088 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 008C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0090 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0094 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0098 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 009C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 00A0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 00A4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 00A8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 00AC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 00B0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 00B4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 00B8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 00BC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 00C0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 00C4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 00C8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 00CC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 00D0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 00D4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 00D8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 00DC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 00E0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 00E4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 00E8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 00EC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 00F0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 00F4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 00F8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 00FC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0100 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0104 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0108 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 010C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0110 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0114 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0118 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 011C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0120 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0124 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0128 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 012C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0130 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0134 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0138 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 013C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0140 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0144 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0148 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 014C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0150 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0154 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0158 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 015C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0160 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0164 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0168 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 016C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0170 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0174 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0178 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 017C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0180 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0184 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0188 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 018C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0190 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0194 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0198 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 019C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 01A0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 01A4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 01A8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 01AC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 01B0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 01B4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 01B8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 01BC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 01C0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 01C4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 01C8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 01CC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 01D0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 01D4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 01D8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 01DC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 01E0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 01E4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 01E8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 01EC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 01F0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 01F4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 01F8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 01FC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0200 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0204 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0208 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 020C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0210 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0214 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0218 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 021C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0220 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0224 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0228 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 022C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0230 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0234 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0238 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 023C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0240 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0244 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0248 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 024C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0250 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0254 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0258 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 025C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0260 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0264 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0268 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 026C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0270 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0274 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0278 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 027C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0280 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0284 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0288 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 028C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0290 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0294 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0298 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 029C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 02A0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 02A4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 02A8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 02AC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 02B0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 02B4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 02B8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 02BC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 02C0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 02C4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 02C8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 02CC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 02D0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 02D4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 02D8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 02DC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 02E0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 02E4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 02E8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 02EC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 02F0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 02F4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 02F8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 02FC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0300 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0304 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0308 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 030C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0310 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0314 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0318 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 031C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0320 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0324 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0328 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 032C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0330 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0334 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0338 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 033C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0340 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0344 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0348 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 034C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0350 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0354 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0358 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 035C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0360 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0364 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0368 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 036C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0370 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0374 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0378 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 037C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0380 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0384 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0388 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 038C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0390 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0394 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0398 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 039C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 03A0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 03A4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 03A8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 03AC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 03B0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 03B4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 03B8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 03BC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 03C0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 03C4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 03C8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 03CC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 03D0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 03D4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 03D8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 03DC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 03E0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 03E4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 03E8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 03EC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 03F0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 03F4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 03F8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 03FC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0400 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0404 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0408 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 040C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0410 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0414 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0418 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 041C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0420 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0424 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0428 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 042C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0430 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0434 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0438 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 043C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0440 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0444 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0448 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 044C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0450 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0454 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0458 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 045C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0460 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0464 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0468 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 046C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0470 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0474 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0478 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 047C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0480 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0484 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0488 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 048C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0490 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0494 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0498 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 049C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 04A0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 04A4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 04A8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 04AC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 04B0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 04B4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 04B8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 04BC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 04C0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 04C4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 04C8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 04CC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 04D0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 04D4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 04D8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 04DC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 04E0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 04E4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 04E8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 04EC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 04F0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 04F4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 04F8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 04FC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0500 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0504 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0508 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 050C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0510 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0514 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0518 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 051C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0520 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0524 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0528 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 052C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0530 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0534 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0538 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 053C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0540 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0544 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0548 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 054C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0550 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0554 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0558 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 055C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0560 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0564 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0568 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 056C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0570 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0574 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0578 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 057C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0580 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0584 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0588 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 058C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0590 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0594 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0598 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 059C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 05A0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 05A4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 05A8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 05AC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 05B0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 05B4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 05B8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 05BC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 05C0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 05C4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 05C8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 05CC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 05D0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 05D4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 05D8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 05DC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 05E0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 05E4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 05E8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 05EC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 05F0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 05F4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 05F8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 05FC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0600 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0604 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0608 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 060C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0610 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0614 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0618 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 061C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0620 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0624 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0628 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 062C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0630 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0634 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0638 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 063C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0640 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0644 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0648 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 064C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0650 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0654 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0658 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 065C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0660 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0664 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0668 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 066C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0670 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0674 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0678 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 067C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0680 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0684 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0688 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 068C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0690 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0694 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0698 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 069C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 06A0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 06A4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 06A8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 06AC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 06B0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 06B4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 06B8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 06BC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 06C0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 06C4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 06C8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 06CC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 06D0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 06D4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 06D8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 06DC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 06E0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 06E4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 06E8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 06EC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 06F0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 06F4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 06F8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 06FC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0700 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0704 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0708 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 070C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0710 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0714 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0718 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 071C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0720 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0724 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0728 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 072C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0730 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0734 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0738 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 073C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0740 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0744 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0748 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 074C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0750 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0754 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0758 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 075C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0760 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0764 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0768 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 076C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0770 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0774 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0778 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 077C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0780 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0784 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0788 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 078C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0790 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0794 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0798 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 079C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 07A0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 07A4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 07A8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 07AC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 07B0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 07B4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 07B8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 07BC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 07C0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 07C4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 07C8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 07CC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 07D0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 07D4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 07D8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 07DC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 07E0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 07E4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 07E8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 07EC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 07F0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 07F4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 07F8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 07FC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0800 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0804 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0808 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 080C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0810 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0814 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0818 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 081C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0820 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0824 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0828 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 082C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0830 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0834 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0838 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 083C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0840 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0844 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0848 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 084C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0850 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0854 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0858 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 085C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0860 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0864 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0868 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 086C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0870 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0874 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0878 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 087C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0880 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0884 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0888 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 088C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0890 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0894 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0898 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 089C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 08A0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 08A4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 08A8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 08AC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 08B0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 08B4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 08B8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 08BC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 08C0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 08C4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 08C8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 08CC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 08D0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 08D4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 08D8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 08DC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 08E0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 08E4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 08E8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 08EC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 08F0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 08F4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 08F8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 08FC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0900 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0904 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0908 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 090C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0910 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0914 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0918 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 091C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0920 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0924 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0928 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 092C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0930 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0934 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0938 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 093C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0940 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0944 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0948 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 094C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0950 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0954 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0958 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 095C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0960 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0964 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0968 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 096C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0970 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0974 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0978 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 097C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0980 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0984 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0988 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 098C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0990 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0994 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0998 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 099C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 09A0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 09A4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 09A8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 09AC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 09B0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 09B4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 09B8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 09BC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 09C0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 09C4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 09C8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 09CC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 09D0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 09D4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 09D8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 09DC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 09E0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 09E4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 09E8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 09EC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 09F0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 09F4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 09F8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 09FC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0A00 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0A04 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0A08 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0A0C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0A10 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0A14 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0A18 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0A1C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0A20 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0A24 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0A28 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0A2C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0A30 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0A34 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0A38 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0A3C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0A40 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0A44 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0A48 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0A4C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0A50 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0A54 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0A58 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0A5C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0A60 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0A64 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0A68 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0A6C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0A70 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0A74 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0A78 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0A7C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0A80 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0A84 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0A88 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0A8C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0A90 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0A94 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0A98 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0A9C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0AA0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0AA4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0AA8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0AAC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0AB0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0AB4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0AB8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0ABC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0AC0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0AC4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0AC8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0ACC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0AD0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0AD4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0AD8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0ADC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0AE0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0AE4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0AE8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0AEC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0AF0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0AF4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0AF8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0AFC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0B00 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0B04 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0B08 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0B0C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0B10 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0B14 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0B18 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0B1C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0B20 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0B24 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0B28 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0B2C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0B30 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0B34 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0B38 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0B3C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0B40 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0B44 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0B48 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0B4C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0B50 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0B54 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0B58 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0B5C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0B60 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0B64 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0B68 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0B6C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0B70 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0B74 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0B78 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0B7C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0B80 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0B84 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0B88 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0B8C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0B90 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0B94 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0B98 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0B9C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0BA0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0BA4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0BA8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0BAC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0BB0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0BB4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0BB8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0BBC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0BC0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0BC4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0BC8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0BCC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0BD0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0BD4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0BD8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0BDC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0BE0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0BE4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0BE8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0BEC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0BF0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0BF4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0BF8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0BFC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0C00 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0C04 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0C08 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0C0C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0C10 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0C14 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0C18 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0C1C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0C20 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0C24 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0C28 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0C2C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0C30 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0C34 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0C38 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0C3C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0C40 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0C44 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0C48 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0C4C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0C50 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0C54 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0C58 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0C5C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0C60 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0C64 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0C68 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0C6C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0C70 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0C74 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0C78 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0C7C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0C80 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0C84 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0C88 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0C8C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0C90 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0C94 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0C98 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0C9C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0CA0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0CA4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0CA8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0CAC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0CB0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0CB4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0CB8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0CBC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0CC0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0CC4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0CC8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0CCC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0CD0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0CD4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0CD8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0CDC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0CE0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0CE4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0CE8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0CEC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0CF0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0CF4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0CF8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0CFC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0D00 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0D04 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0D08 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0D0C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0D10 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0D14 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0D18 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0D1C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0D20 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0D24 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0D28 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0D2C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0D30 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0D34 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0D38 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0D3C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0D40 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0D44 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0D48 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0D4C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0D50 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0D54 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0D58 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0D5C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0D60 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0D64 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0D68 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0D6C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0D70 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0D74 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0D78 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0D7C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0D80 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0D84 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0D88 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0D8C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0D90 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0D94 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0D98 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0D9C */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0DA0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0DA4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0DA8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0DAC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0DB0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0DB4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0DB8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0DBC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0DC0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0DC4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0DC8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0DCC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0DD0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0DD4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0DD8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0DDC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0DE0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0DE4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0DE8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0DEC */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0DF0 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0DF4 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0DF8 */ 0x00000000,0x00000000,0x00000000,0x00000000,
-/* 0DFC */ 0x00000000,0x00000000,0x00000000,0x00010004
-}; /* #SAMPLE_END */
-
-
-static struct dsp_segment_desc cwcemb80_segments[] = {
-  { SEGTYPE_SP_PROGRAM, 0x00000000, 0x0000031c, cwcemb80_code },
-  { SEGTYPE_SP_PARAMETER, 0x00000000, 0x00000697, cwcemb80_parameter },
-  { SEGTYPE_SP_SAMPLE, 0x00000000, 0x00000e00, cwcemb80_sample },
-};
-
-static struct dsp_module_desc cwcemb80_module = {
-  "cwcemb80",
-  {
-    38,
-    cwcemb80_symbols
-  },
-  3,
-  cwcemb80_segments,
-};
-
-#endif /* __HEADER_cwcemb80_H__ */
diff --git a/sound/pci/echoaudio/darla20.c b/sound/pci/echoaudio/darla20.c
index 8e7fe033270f..87078d3a6854 100644
--- a/sound/pci/echoaudio/darla20.c
+++ b/sound/pci/echoaudio/darla20.c
@@ -56,6 +56,8 @@
 #include <asm/atomic.h>
 #include "echoaudio.h"
 
+MODULE_FIRMWARE("ea/darla20_dsp.fw");
+
 #define FW_DARLA20_DSP	0
 
 static const struct firmware card_fw[] = {
diff --git a/sound/pci/echoaudio/darla24.c b/sound/pci/echoaudio/darla24.c
index a13c623eb999..42b48f9d2128 100644
--- a/sound/pci/echoaudio/darla24.c
+++ b/sound/pci/echoaudio/darla24.c
@@ -60,6 +60,8 @@
 #include <asm/atomic.h>
 #include "echoaudio.h"
 
+MODULE_FIRMWARE("ea/darla24_dsp.fw");
+
 #define FW_DARLA24_DSP	0
 
 static const struct firmware card_fw[] = {
diff --git a/sound/pci/echoaudio/echo3g.c b/sound/pci/echoaudio/echo3g.c
index 8fb15823aca5..8dbb7ac865c1 100644
--- a/sound/pci/echoaudio/echo3g.c
+++ b/sound/pci/echoaudio/echo3g.c
@@ -68,6 +68,10 @@
 #include <asm/atomic.h>
 #include "echoaudio.h"
 
+MODULE_FIRMWARE("ea/loader_dsp.fw");
+MODULE_FIRMWARE("ea/echo3g_dsp.fw");
+MODULE_FIRMWARE("ea/3g_asic.fw");
+
 #define FW_361_LOADER	0
 #define FW_ECHO3G_DSP	1
 #define FW_3G_ASIC	2
diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c
index e413da00759b..f27b6a733b96 100644
--- a/sound/pci/echoaudio/echoaudio.c
+++ b/sound/pci/echoaudio/echoaudio.c
@@ -705,11 +705,9 @@ static int pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 	struct audiopipe *pipe = runtime->private_data;
 	int i, err;
 	u32 channelmask = 0;
-	struct list_head *pos;
 	struct snd_pcm_substream *s;
 
-	snd_pcm_group_for_each(pos, substream) {
-		s = snd_pcm_group_substream_entry(pos);
+	snd_pcm_group_for_each_entry(s, substream) {
 		for (i = 0; i < DSP_MAXPIPES; i++) {
 			if (s == chip->substream[i]) {
 				channelmask |= 1 << i;
diff --git a/sound/pci/echoaudio/echoaudio_3g.c b/sound/pci/echoaudio/echoaudio_3g.c
index 9f439ea459f4..52a933189576 100644
--- a/sound/pci/echoaudio/echoaudio_3g.c
+++ b/sound/pci/echoaudio/echoaudio_3g.c
@@ -233,8 +233,8 @@ static int load_asic(struct echoaudio *chip)
 
 	chip->asic_code = &card_fw[FW_3G_ASIC];
 
-	/* Now give the new ASIC a little time to set up */
-	mdelay(2);
+	/* Now give the new ASIC some time to set up */
+	msleep(1000);
 	/* See if it worked */
 	box_type = check_asic_status(chip);
 
diff --git a/sound/pci/echoaudio/gina20.c b/sound/pci/echoaudio/gina20.c
index af4d32026e4a..fee2d4831732 100644
--- a/sound/pci/echoaudio/gina20.c
+++ b/sound/pci/echoaudio/gina20.c
@@ -60,6 +60,8 @@
 #include <asm/atomic.h>
 #include "echoaudio.h"
 
+MODULE_FIRMWARE("ea/gina20_dsp.fw");
+
 #define FW_GINA20_DSP	0
 
 static const struct firmware card_fw[] = {
diff --git a/sound/pci/echoaudio/gina24.c b/sound/pci/echoaudio/gina24.c
index 9ff454a947ed..d5eae470fe9a 100644
--- a/sound/pci/echoaudio/gina24.c
+++ b/sound/pci/echoaudio/gina24.c
@@ -66,6 +66,12 @@
 #include <asm/atomic.h>
 #include "echoaudio.h"
 
+MODULE_FIRMWARE("ea/loader_dsp.fw");
+MODULE_FIRMWARE("ea/gina24_301_dsp.fw");
+MODULE_FIRMWARE("ea/gina24_361_dsp.fw");
+MODULE_FIRMWARE("ea/gina24_301_asic.fw");
+MODULE_FIRMWARE("ea/gina24_361_asic.fw");
+
 #define FW_361_LOADER		0
 #define FW_GINA24_301_DSP	1
 #define FW_GINA24_361_DSP	2
diff --git a/sound/pci/echoaudio/indigo.c b/sound/pci/echoaudio/indigo.c
index 37eb726fd03d..40f601cd016f 100644
--- a/sound/pci/echoaudio/indigo.c
+++ b/sound/pci/echoaudio/indigo.c
@@ -58,6 +58,9 @@
 #include <asm/atomic.h>
 #include "echoaudio.h"
 
+MODULE_FIRMWARE("ea/loader_dsp.fw");
+MODULE_FIRMWARE("ea/indigo_dsp.fw");
+
 #define FW_361_LOADER	0
 #define FW_INDIGO_DSP	1
 
diff --git a/sound/pci/echoaudio/indigodj.c b/sound/pci/echoaudio/indigodj.c
index dc8b91824181..771c5383210d 100644
--- a/sound/pci/echoaudio/indigodj.c
+++ b/sound/pci/echoaudio/indigodj.c
@@ -58,6 +58,9 @@
 #include <asm/atomic.h>
 #include "echoaudio.h"
 
+MODULE_FIRMWARE("ea/loader_dsp.fw");
+MODULE_FIRMWARE("ea/indigo_dj_dsp.fw");
+
 #define FW_361_LOADER		0
 #define FW_INDIGO_DJ_DSP	1
 
diff --git a/sound/pci/echoaudio/indigoio.c b/sound/pci/echoaudio/indigoio.c
index eadf3263453a..49c550defcf9 100644
--- a/sound/pci/echoaudio/indigoio.c
+++ b/sound/pci/echoaudio/indigoio.c
@@ -59,6 +59,9 @@
 #include <asm/atomic.h>
 #include "echoaudio.h"
 
+MODULE_FIRMWARE("ea/loader_dsp.fw");
+MODULE_FIRMWARE("ea/indigo_io_dsp.fw");
+
 #define FW_361_LOADER		0
 #define FW_INDIGO_IO_DSP	1
 
diff --git a/sound/pci/echoaudio/layla20.c b/sound/pci/echoaudio/layla20.c
index 6cede497579e..8f5483a405ae 100644
--- a/sound/pci/echoaudio/layla20.c
+++ b/sound/pci/echoaudio/layla20.c
@@ -66,6 +66,9 @@
 #include <asm/atomic.h>
 #include "echoaudio.h"
 
+MODULE_FIRMWARE("ea/layla20_dsp.fw");
+MODULE_FIRMWARE("ea/layla20_asic.fw");
+
 #define FW_LAYLA20_DSP	0
 #define FW_LAYLA20_ASIC	1
 
diff --git a/sound/pci/echoaudio/layla24.c b/sound/pci/echoaudio/layla24.c
index 44f735426aa0..0524667c02f7 100644
--- a/sound/pci/echoaudio/layla24.c
+++ b/sound/pci/echoaudio/layla24.c
@@ -68,6 +68,12 @@
 #include <asm/atomic.h>
 #include "echoaudio.h"
 
+MODULE_FIRMWARE("ea/loader_dsp.fw");
+MODULE_FIRMWARE("ea/layla24_dsp.fw");
+MODULE_FIRMWARE("ea/layla24_1_asic.fw");
+MODULE_FIRMWARE("ea/layla24_2A_asic.fw");
+MODULE_FIRMWARE("ea/layla24_2S_asic.fw");
+
 #define FW_361_LOADER		0
 #define FW_LAYLA24_DSP		1
 #define FW_LAYLA24_1_ASIC	2
diff --git a/sound/pci/echoaudio/mia.c b/sound/pci/echoaudio/mia.c
index dc172d03ac3f..893c7c20dd70 100644
--- a/sound/pci/echoaudio/mia.c
+++ b/sound/pci/echoaudio/mia.c
@@ -66,6 +66,9 @@
 #include <asm/atomic.h>
 #include "echoaudio.h"
 
+MODULE_FIRMWARE("ea/loader_dsp.fw");
+MODULE_FIRMWARE("ea/mia_dsp.fw");
+
 #define FW_361_LOADER	0
 #define FW_MIA_DSP	1
 
diff --git a/sound/pci/echoaudio/mona.c b/sound/pci/echoaudio/mona.c
index c856ed50dd9a..3a5d5b0020df 100644
--- a/sound/pci/echoaudio/mona.c
+++ b/sound/pci/echoaudio/mona.c
@@ -64,6 +64,15 @@
 #include <asm/atomic.h>
 #include "echoaudio.h"
 
+MODULE_FIRMWARE("ea/loader_dsp.fw");
+MODULE_FIRMWARE("ea/mona_301_dsp.fw");
+MODULE_FIRMWARE("ea/mona_361_dsp.fw");
+MODULE_FIRMWARE("ea/mona_301_1_asic_48.fw");
+MODULE_FIRMWARE("ea/mona_301_1_asic_96.fw");
+MODULE_FIRMWARE("ea/mona_361_1_asic_48.fw");
+MODULE_FIRMWARE("ea/mona_361_1_asic_96.fw");
+MODULE_FIRMWARE("ea/mona_2_asic.fw");
+
 #define FW_361_LOADER		0
 #define FW_MONA_301_DSP		1
 #define FW_MONA_361_DSP		2
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
index 80aa585eade4..dbc805c33fc4 100644
--- a/sound/pci/emu10k1/emu10k1_main.c
+++ b/sound/pci/emu10k1/emu10k1_main.c
@@ -49,6 +49,13 @@
 #include "p17v.h"
 
 
+#define HANA_FILENAME "emu/hana.fw"
+#define DOCK_FILENAME "emu/audio_dock.fw"
+
+MODULE_FIRMWARE(HANA_FILENAME);
+MODULE_FIRMWARE(DOCK_FILENAME);
+
+
 /*************************************************************************
  * EMU10K1 init / done
  *************************************************************************/
@@ -693,8 +700,6 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu)
 	int tmp,tmp2;
 	int reg;
 	int err;
-	const char *hana_filename = "emu/hana.fw";
-	const char *dock_filename = "emu/audio_dock.fw";
 
 	snd_printk(KERN_INFO "emu1010: Special config.\n");
 	/* AC97 2.1, Any 16Meg of 4Gig address, Auto-Mute, EMU32 Slave,
@@ -735,8 +740,8 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu)
 		return -ENODEV;
 	}
 	snd_printk(KERN_INFO "emu1010: EMU_HANA_ID=0x%x\n",reg);
-	if ((err = snd_emu1010_load_firmware(emu, hana_filename)) != 0) {
-		snd_printk(KERN_INFO "emu1010: Loading Hana Firmware file %s failed\n", hana_filename);
+	if ((err = snd_emu1010_load_firmware(emu, HANA_FILENAME)) != 0) {
+		snd_printk(KERN_INFO "emu1010: Loading Hana Firmware file %s failed\n", HANA_FILENAME);
 		return err;
 	}
 
@@ -938,7 +943,7 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu)
 		/* Return to Audio Dock programming mode */
 		snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware\n");
 		snd_emu1010_fpga_write(emu,  EMU_HANA_FPGA_CONFIG, EMU_HANA_FPGA_CONFIG_AUDIODOCK );
-		if ((err = snd_emu1010_load_firmware(emu, dock_filename)) != 0) {
+		if ((err = snd_emu1010_load_firmware(emu, DOCK_FILENAME)) != 0) {
 			return err;
 		}
 		snd_emu1010_fpga_write(emu,  EMU_HANA_FPGA_CONFIG, 0 );
@@ -1216,6 +1221,15 @@ static struct snd_emu_chip_details emu_chip_details[] = {
 	 .spi_dac = 1,
 	 .i2c_adc = 1,
 	 .spk71 = 1} ,
+	{.vendor = 0x1102, .device = 0x0008, .subsystem = 0x42011102,
+	 .driver = "Audigy2", .name = "E-mu 1010 Notebook [MAEM8950]", 
+	 .id = "EMU1010",
+	 .emu10k2_chip = 1,
+	 .ca0108_chip = 1,
+	 .ca_cardbus_chip = 1,
+	 .spi_dac = 1,
+	 .i2c_adc = 1,
+	 .spk71 = 1} ,
 	{.vendor = 0x1102, .device = 0x0008, 
 	 .driver = "Audigy2", .name = "Audigy 2 Value [Unknown]", 
 	 .id = "Audigy2",
diff --git a/sound/pci/emu10k1/p16v.c b/sound/pci/emu10k1/p16v.c
index 465f8d505329..7ee19c63c2c8 100644
--- a/sound/pci/emu10k1/p16v.c
+++ b/sound/pci/emu10k1/p16v.c
@@ -433,7 +433,6 @@ static int snd_p16v_pcm_trigger_playback(struct snd_pcm_substream *substream,
 	struct snd_emu10k1_pcm *epcm;
 	int channel;
 	int result = 0;
-	struct list_head *pos;
         struct snd_pcm_substream *s;
 	u32 basic = 0;
 	u32 inte = 0;
@@ -448,8 +447,7 @@ static int snd_p16v_pcm_trigger_playback(struct snd_pcm_substream *substream,
 		running = 0;
 		break;
 	}
-        snd_pcm_group_for_each(pos, substream) {
-                s = snd_pcm_group_substream_entry(pos);
+        snd_pcm_group_for_each_entry(s, substream) {
 		runtime = s->runtime;
 		epcm = runtime->private_data;
 		channel = substream->pcm->device-emu->p16v_device_offset;
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c
index 425b167522d5..6a0ddcf00884 100644
--- a/sound/pci/ens1370.c
+++ b/sound/pci/ens1370.c
@@ -798,10 +798,8 @@ static int snd_ensoniq_trigger(struct snd_pcm_substream *substream, int cmd)
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 	{
 		unsigned int what = 0;
-		struct list_head *pos;
 		struct snd_pcm_substream *s;
-		snd_pcm_group_for_each(pos, substream) {
-			s = snd_pcm_group_substream_entry(pos);
+		snd_pcm_group_for_each_entry(s, substream) {
 			if (s == ensoniq->playback1_substream) {
 				what |= ES_P1_PAUSE;
 				snd_pcm_trigger_done(s, substream);
@@ -824,10 +822,8 @@ static int snd_ensoniq_trigger(struct snd_pcm_substream *substream, int cmd)
 	case SNDRV_PCM_TRIGGER_STOP:
 	{
 		unsigned int what = 0;
-		struct list_head *pos;
 		struct snd_pcm_substream *s;
-		snd_pcm_group_for_each(pos, substream) {
-			s = snd_pcm_group_substream_entry(pos);
+		snd_pcm_group_for_each_entry(s, substream) {
 			if (s == ensoniq->playback1_substream) {
 				what |= ES_DAC1_EN;
 				snd_pcm_trigger_done(s, substream);
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
index dc84c189b05f..2faf009076bb 100644
--- a/sound/pci/es1968.c
+++ b/sound/pci/es1968.c
@@ -1554,10 +1554,7 @@ static int snd_es1968_playback_open(struct snd_pcm_substream *substream)
 	runtime->hw = snd_es1968_playback;
 	runtime->hw.buffer_bytes_max = runtime->hw.period_bytes_max =
 		calc_available_memory_size(chip);
-#if 0
-	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
-				   1024);
-#endif
+
 	spin_lock_irq(&chip->substream_lock);
 	list_add(&es->list, &chip->substream_list);
 	spin_unlock_irq(&chip->substream_lock);
@@ -1613,10 +1610,8 @@ static int snd_es1968_capture_open(struct snd_pcm_substream *substream)
 	runtime->hw = snd_es1968_capture;
 	runtime->hw.buffer_bytes_max = runtime->hw.period_bytes_max =
 		calc_available_memory_size(chip) - 1024; /* keep MIXBUF size */
-#if 0
-	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
-				   1024);
-#endif
+	snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES);
+
 	spin_lock_irq(&chip->substream_lock);
 	list_add(&es->list, &chip->substream_list);
 	spin_unlock_irq(&chip->substream_lock);
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile
index 60d7b05a204a..b2484bbdcc1d 100644
--- a/sound/pci/hda/Makefile
+++ b/sound/pci/hda/Makefile
@@ -1,5 +1,8 @@
 snd-hda-intel-objs := hda_intel.o
-snd-hda-codec-objs := hda_codec.o \
+# since snd-hda-intel is the only driver using hda-codec,
+# merge it into a single module although it was originally
+# designed to be individual modules
+snd-hda-intel-objs += hda_codec.o \
 	hda_generic.o \
 	patch_realtek.o \
 	patch_cmedia.o \
@@ -10,7 +13,7 @@ snd-hda-codec-objs := hda_codec.o \
 	patch_conexant.o \
 	patch_via.o
 ifdef CONFIG_PROC_FS
-snd-hda-codec-objs += hda_proc.o
+snd-hda-intel-objs += hda_proc.o
 endif
 
-obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-intel.o snd-hda-codec.o
+obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-intel.o
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 8f34fb447983..14649d54b493 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -24,7 +24,6 @@
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/pci.h>
-#include <linux/moduleparam.h>
 #include <linux/mutex.h>
 #include <sound/core.h>
 #include "hda_codec.h"
@@ -34,11 +33,6 @@
 #include "hda_local.h"
 
 
-MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
-MODULE_DESCRIPTION("Universal interface for High Definition Audio Codec");
-MODULE_LICENSE("GPL");
-
-
 /*
  * vendor / preset table
  */
@@ -77,12 +71,13 @@ static struct hda_vendor_id hda_vendor_ids[] = {
  *
  * Returns the obtained response value, or -1 for an error.
  */
-unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid, int direct,
+unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid,
+				int direct,
 				unsigned int verb, unsigned int parm)
 {
 	unsigned int res;
 	mutex_lock(&codec->bus->cmd_mutex);
-	if (! codec->bus->ops.command(codec, nid, direct, verb, parm))
+	if (!codec->bus->ops.command(codec, nid, direct, verb, parm))
 		res = codec->bus->ops.get_response(codec);
 	else
 		res = (unsigned int)-1;
@@ -90,8 +85,6 @@ unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid, int dire
 	return res;
 }
 
-EXPORT_SYMBOL(snd_hda_codec_read);
-
 /**
  * snd_hda_codec_write - send a single command without waiting for response
  * @codec: the HDA codec
@@ -114,8 +107,6 @@ int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct,
 	return err;
 }
 
-EXPORT_SYMBOL(snd_hda_codec_write);
-
 /**
  * snd_hda_sequence_write - sequence writes
  * @codec: the HDA codec
@@ -130,8 +121,6 @@ void snd_hda_sequence_write(struct hda_codec *codec, const struct hda_verb *seq)
 		snd_hda_codec_write(codec, seq->nid, 0, seq->verb, seq->param);
 }
 
-EXPORT_SYMBOL(snd_hda_sequence_write);
-
 /**
  * snd_hda_get_sub_nodes - get the range of sub nodes
  * @codec: the HDA codec
@@ -141,7 +130,8 @@ EXPORT_SYMBOL(snd_hda_sequence_write);
  * Parse the NID and store the start NID of its sub-nodes.
  * Returns the number of sub-nodes.
  */
-int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid, hda_nid_t *start_id)
+int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid,
+			  hda_nid_t *start_id)
 {
 	unsigned int parm;
 
@@ -150,8 +140,6 @@ int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid, hda_nid_t *sta
 	return (int)(parm & 0x7fff);
 }
 
-EXPORT_SYMBOL(snd_hda_get_sub_nodes);
-
 /**
  * snd_hda_get_connections - get connection list
  * @codec: the HDA codec
@@ -187,12 +175,13 @@ int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
 	conn_len = parm & AC_CLIST_LENGTH;
 	mask = (1 << (shift-1)) - 1;
 
-	if (! conn_len)
+	if (!conn_len)
 		return 0; /* no connection */
 
 	if (conn_len == 1) {
 		/* single connection */
-		parm = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_LIST, 0);
+		parm = snd_hda_codec_read(codec, nid, 0,
+					  AC_VERB_GET_CONNECT_LIST, 0);
 		conn_list[0] = parm & mask;
 		return 1;
 	}
@@ -207,18 +196,21 @@ int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
 		if (i % num_elems == 0)
 			parm = snd_hda_codec_read(codec, nid, 0,
 						  AC_VERB_GET_CONNECT_LIST, i);
-		range_val = !! (parm & (1 << (shift-1))); /* ranges */
+		range_val = !!(parm & (1 << (shift-1))); /* ranges */
 		val = parm & mask;
 		parm >>= shift;
 		if (range_val) {
 			/* ranges between the previous and this one */
-			if (! prev_nid || prev_nid >= val) {
-				snd_printk(KERN_WARNING "hda_codec: invalid dep_range_val %x:%x\n", prev_nid, val);
+			if (!prev_nid || prev_nid >= val) {
+				snd_printk(KERN_WARNING "hda_codec: "
+					   "invalid dep_range_val %x:%x\n",
+					   prev_nid, val);
 				continue;
 			}
 			for (n = prev_nid + 1; n <= val; n++) {
 				if (conns >= max_conns) {
-					snd_printk(KERN_ERR "Too many connections\n");
+					snd_printk(KERN_ERR
+						   "Too many connections\n");
 					return -EINVAL;
 				}
 				conn_list[conns++] = n;
@@ -253,7 +245,8 @@ int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex)
 	struct hda_bus_unsolicited *unsol;
 	unsigned int wp;
 
-	if ((unsol = bus->unsol) == NULL)
+	unsol = bus->unsol;
+	if (!unsol)
 		return 0;
 
 	wp = (unsol->wp + 1) % HDA_UNSOL_QUEUE_SIZE;
@@ -268,8 +261,6 @@ int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex)
 	return 0;
 }
 
-EXPORT_SYMBOL(snd_hda_queue_unsol_event);
-
 /*
  * process queueud unsolicited events
  */
@@ -287,7 +278,7 @@ static void process_unsol_events(struct work_struct *work)
 		rp <<= 1;
 		res = unsol->queue[rp];
 		caddr = unsol->queue[rp + 1];
-		if (! (caddr & (1 << 4))) /* no unsolicited event? */
+		if (!(caddr & (1 << 4))) /* no unsolicited event? */
 			continue;
 		codec = bus->caddr_tbl[caddr & 0x0f];
 		if (codec && codec->patch_ops.unsol_event)
@@ -298,7 +289,7 @@ static void process_unsol_events(struct work_struct *work)
 /*
  * initialize unsolicited queue
  */
-static int init_unsol_queue(struct hda_bus *bus)
+static int __devinit init_unsol_queue(struct hda_bus *bus)
 {
 	struct hda_bus_unsolicited *unsol;
 
@@ -306,8 +297,9 @@ static int init_unsol_queue(struct hda_bus *bus)
 		return 0;
 
 	unsol = kzalloc(sizeof(*unsol), GFP_KERNEL);
-	if (! unsol) {
-		snd_printk(KERN_ERR "hda_codec: can't allocate unsolicited queue\n");
+	if (!unsol) {
+		snd_printk(KERN_ERR "hda_codec: "
+			   "can't allocate unsolicited queue\n");
 		return -ENOMEM;
 	}
 	INIT_WORK(&unsol->work, process_unsol_events);
@@ -323,16 +315,15 @@ static void snd_hda_codec_free(struct hda_codec *codec);
 
 static int snd_hda_bus_free(struct hda_bus *bus)
 {
-	struct list_head *p, *n;
+	struct hda_codec *codec, *n;
 
-	if (! bus)
+	if (!bus)
 		return 0;
 	if (bus->unsol) {
 		flush_scheduled_work();
 		kfree(bus->unsol);
 	}
-	list_for_each_safe(p, n, &bus->codec_list) {
-		struct hda_codec *codec = list_entry(p, struct hda_codec, list);
+	list_for_each_entry_safe(codec, n, &bus->codec_list, list) {
 		snd_hda_codec_free(codec);
 	}
 	if (bus->ops.private_free)
@@ -355,8 +346,9 @@ static int snd_hda_bus_dev_free(struct snd_device *device)
  *
  * Returns 0 if successful, or a negative error code.
  */
-int snd_hda_bus_new(struct snd_card *card, const struct hda_bus_template *temp,
-		    struct hda_bus **busp)
+int __devinit snd_hda_bus_new(struct snd_card *card,
+			      const struct hda_bus_template *temp,
+			      struct hda_bus **busp)
 {
 	struct hda_bus *bus;
 	int err;
@@ -385,7 +377,8 @@ int snd_hda_bus_new(struct snd_card *card, const struct hda_bus_template *temp,
 	mutex_init(&bus->cmd_mutex);
 	INIT_LIST_HEAD(&bus->codec_list);
 
-	if ((err = snd_device_new(card, SNDRV_DEV_BUS, bus, &dev_ops)) < 0) {
+	err = snd_device_new(card, SNDRV_DEV_BUS, bus, &dev_ops);
+	if (err < 0) {
 		snd_hda_bus_free(bus);
 		return err;
 	}
@@ -394,22 +387,24 @@ int snd_hda_bus_new(struct snd_card *card, const struct hda_bus_template *temp,
 	return 0;
 }
 
-EXPORT_SYMBOL(snd_hda_bus_new);
-
 /*
  * find a matching codec preset
  */
-static const struct hda_codec_preset *find_codec_preset(struct hda_codec *codec)
+static const struct hda_codec_preset __devinit *
+find_codec_preset(struct hda_codec *codec)
 {
 	const struct hda_codec_preset **tbl, *preset;
 
+	if (codec->bus->modelname && !strcmp(codec->bus->modelname, "generic"))
+		return NULL; /* use the generic parser */
+
 	for (tbl = hda_preset_tables; *tbl; tbl++) {
 		for (preset = *tbl; preset->id; preset++) {
 			u32 mask = preset->mask;
-			if (! mask)
+			if (!mask)
 				mask = ~0;
 			if (preset->id == (codec->vendor_id & mask) &&
-			    (! preset->rev ||
+			    (!preset->rev ||
 			     preset->rev == codec->revision_id))
 				return preset;
 		}
@@ -434,27 +429,30 @@ void snd_hda_get_codec_name(struct hda_codec *codec,
 			break;
 		}
 	}
-	if (! vendor) {
+	if (!vendor) {
 		sprintf(tmp, "Generic %04x", vendor_id);
 		vendor = tmp;
 	}
 	if (codec->preset && codec->preset->name)
 		snprintf(name, namelen, "%s %s", vendor, codec->preset->name);
 	else
-		snprintf(name, namelen, "%s ID %x", vendor, codec->vendor_id & 0xffff);
+		snprintf(name, namelen, "%s ID %x", vendor,
+			 codec->vendor_id & 0xffff);
 }
 
 /*
  * look for an AFG and MFG nodes
  */
-static void setup_fg_nodes(struct hda_codec *codec)
+static void __devinit setup_fg_nodes(struct hda_codec *codec)
 {
 	int i, total_nodes;
 	hda_nid_t nid;
 
 	total_nodes = snd_hda_get_sub_nodes(codec, AC_NODE_ROOT, &nid);
 	for (i = 0; i < total_nodes; i++, nid++) {
-		switch((snd_hda_param_read(codec, nid, AC_PAR_FUNCTION_TYPE) & 0xff)) {
+		unsigned int func;
+		func = snd_hda_param_read(codec, nid, AC_PAR_FUNCTION_TYPE);
+		switch (func & 0xff) {
 		case AC_GRP_AUDIO_FUNCTION:
 			codec->afg = nid;
 			break;
@@ -478,7 +476,7 @@ static int read_widget_caps(struct hda_codec *codec, hda_nid_t fg_node)
 	codec->num_nodes = snd_hda_get_sub_nodes(codec, fg_node,
 						 &codec->start_nid);
 	codec->wcaps = kmalloc(codec->num_nodes * 4, GFP_KERNEL);
-	if (! codec->wcaps)
+	if (!codec->wcaps)
 		return -ENOMEM;
 	nid = codec->start_nid;
 	for (i = 0; i < codec->num_nodes; i++, nid++)
@@ -493,7 +491,7 @@ static int read_widget_caps(struct hda_codec *codec, hda_nid_t fg_node)
  */
 static void snd_hda_codec_free(struct hda_codec *codec)
 {
-	if (! codec)
+	if (!codec)
 		return;
 	list_del(&codec->list);
 	codec->bus->caddr_tbl[codec->addr] = NULL;
@@ -514,8 +512,8 @@ static void init_amp_hash(struct hda_codec *codec);
  *
  * Returns 0 if successful, or a negative error code.
  */
-int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
-		      struct hda_codec **codecp)
+int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
+				struct hda_codec **codecp)
 {
 	struct hda_codec *codec;
 	char component[13];
@@ -525,7 +523,8 @@ int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
 	snd_assert(codec_addr <= HDA_MAX_CODEC_ADDRESS, return -EINVAL);
 
 	if (bus->caddr_tbl[codec_addr]) {
-		snd_printk(KERN_ERR "hda_codec: address 0x%x is already occupied\n", codec_addr);
+		snd_printk(KERN_ERR "hda_codec: "
+			   "address 0x%x is already occupied\n", codec_addr);
 		return -EBUSY;
 	}
 
@@ -543,18 +542,21 @@ int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
 	list_add_tail(&codec->list, &bus->codec_list);
 	bus->caddr_tbl[codec_addr] = codec;
 
-	codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT, AC_PAR_VENDOR_ID);
+	codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT,
+					      AC_PAR_VENDOR_ID);
 	if (codec->vendor_id == -1)
 		/* read again, hopefully the access method was corrected
 		 * in the last read...
 		 */
 		codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT,
 						      AC_PAR_VENDOR_ID);
-	codec->subsystem_id = snd_hda_param_read(codec, AC_NODE_ROOT, AC_PAR_SUBSYSTEM_ID);
-	codec->revision_id = snd_hda_param_read(codec, AC_NODE_ROOT, AC_PAR_REV_ID);
+	codec->subsystem_id = snd_hda_param_read(codec, AC_NODE_ROOT,
+						 AC_PAR_SUBSYSTEM_ID);
+	codec->revision_id = snd_hda_param_read(codec, AC_NODE_ROOT,
+						AC_PAR_REV_ID);
 
 	setup_fg_nodes(codec);
-	if (! codec->afg && ! codec->mfg) {
+	if (!codec->afg && !codec->mfg) {
 		snd_printdd("hda_codec: no AFG or MFG node found\n");
 		snd_hda_codec_free(codec);
 		return -ENODEV;
@@ -566,15 +568,16 @@ int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
 		return -ENOMEM;
 	}
 
-	if (! codec->subsystem_id) {
+	if (!codec->subsystem_id) {
 		hda_nid_t nid = codec->afg ? codec->afg : codec->mfg;
-		codec->subsystem_id = snd_hda_codec_read(codec, nid, 0,
-							 AC_VERB_GET_SUBSYSTEM_ID,
-							 0);
+		codec->subsystem_id =
+			snd_hda_codec_read(codec, nid, 0,
+					   AC_VERB_GET_SUBSYSTEM_ID, 0);
 	}
 
 	codec->preset = find_codec_preset(codec);
-	if (! *bus->card->mixername)
+	/* audio codec should override the mixer name */
+	if (codec->afg || !*bus->card->mixername)
 		snd_hda_get_codec_name(codec, bus->card->mixername,
 				       sizeof(bus->card->mixername));
 
@@ -600,8 +603,6 @@ int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
 	return 0;
 }
 
-EXPORT_SYMBOL(snd_hda_codec_new);
-
 /**
  * snd_hda_codec_setup_stream - set up the codec for streaming
  * @codec: the CODEC to set up
@@ -610,13 +611,15 @@ EXPORT_SYMBOL(snd_hda_codec_new);
  * @channel_id: channel id to pass, zero based.
  * @format: stream format.
  */
-void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, u32 stream_tag,
+void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
+				u32 stream_tag,
 				int channel_id, int format)
 {
-	if (! nid)
+	if (!nid)
 		return;
 
-	snd_printdd("hda_codec_setup_stream: NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n",
+	snd_printdd("hda_codec_setup_stream: "
+		    "NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n",
 		    nid, stream_tag, channel_id, format);
 	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID,
 			    (stream_tag << 4) | channel_id);
@@ -624,8 +627,6 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, u32 stre
 	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, format);
 }
 
-EXPORT_SYMBOL(snd_hda_codec_setup_stream);
-
 /*
  * amp access functions
  */
@@ -636,7 +637,7 @@ EXPORT_SYMBOL(snd_hda_codec_setup_stream);
 #define INFO_AMP_VOL(ch)	(1 << (1 + (ch)))
 
 /* initialize the hash table */
-static void init_amp_hash(struct hda_codec *codec)
+static void __devinit init_amp_hash(struct hda_codec *codec)
 {
 	memset(codec->amp_hash, 0xff, sizeof(codec->amp_hash));
 	codec->num_amp_entries = 0;
@@ -662,15 +663,18 @@ static struct hda_amp_info *get_alloc_amp_hash(struct hda_codec *codec, u32 key)
 	if (codec->num_amp_entries >= codec->amp_info_size) {
 		/* reallocate the array */
 		int new_size = codec->amp_info_size + 64;
-		struct hda_amp_info *new_info = kcalloc(new_size, sizeof(struct hda_amp_info),
-							GFP_KERNEL);
-		if (! new_info) {
-			snd_printk(KERN_ERR "hda_codec: can't malloc amp_info\n");
+		struct hda_amp_info *new_info;
+		new_info = kcalloc(new_size, sizeof(struct hda_amp_info),
+				   GFP_KERNEL);
+		if (!new_info) {
+			snd_printk(KERN_ERR "hda_codec: "
+				   "can't malloc amp_info\n");
 			return NULL;
 		}
 		if (codec->amp_info) {
 			memcpy(new_info, codec->amp_info,
-			       codec->amp_info_size * sizeof(struct hda_amp_info));
+			       codec->amp_info_size *
+			       sizeof(struct hda_amp_info));
 			kfree(codec->amp_info);
 		}
 		codec->amp_info_size = new_size;
@@ -691,15 +695,18 @@ static struct hda_amp_info *get_alloc_amp_hash(struct hda_codec *codec, u32 key)
  */
 static u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction)
 {
-	struct hda_amp_info *info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, 0));
+	struct hda_amp_info *info;
 
-	if (! info)
+	info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, 0));
+	if (!info)
 		return 0;
-	if (! (info->status & INFO_AMP_CAPS)) {
-		if (! (get_wcaps(codec, nid) & AC_WCAP_AMP_OVRD))
+	if (!(info->status & INFO_AMP_CAPS)) {
+		if (!(get_wcaps(codec, nid) & AC_WCAP_AMP_OVRD))
 			nid = codec->afg;
-		info->amp_caps = snd_hda_param_read(codec, nid, direction == HDA_OUTPUT ?
-						    AC_PAR_AMP_OUT_CAP : AC_PAR_AMP_IN_CAP);
+		info->amp_caps = snd_hda_param_read(codec, nid,
+						    direction == HDA_OUTPUT ?
+						    AC_PAR_AMP_OUT_CAP :
+						    AC_PAR_AMP_IN_CAP);
 		info->status |= INFO_AMP_CAPS;
 	}
 	return info->amp_caps;
@@ -709,8 +716,9 @@ static u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction)
  * read the current volume to info
  * if the cache exists, read the cache value.
  */
-static unsigned int get_vol_mute(struct hda_codec *codec, struct hda_amp_info *info,
-			 hda_nid_t nid, int ch, int direction, int index)
+static unsigned int get_vol_mute(struct hda_codec *codec,
+				 struct hda_amp_info *info, hda_nid_t nid,
+				 int ch, int direction, int index)
 {
 	u32 val, parm;
 
@@ -720,7 +728,8 @@ static unsigned int get_vol_mute(struct hda_codec *codec, struct hda_amp_info *i
 	parm = ch ? AC_AMP_GET_RIGHT : AC_AMP_GET_LEFT;
 	parm |= direction == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT;
 	parm |= index;
-	val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE, parm);
+	val = snd_hda_codec_read(codec, nid, 0,
+				 AC_VERB_GET_AMP_GAIN_MUTE, parm);
 	info->vol[ch] = val & 0xff;
 	info->status |= INFO_AMP_VOL(ch);
 	return info->vol[ch];
@@ -730,7 +739,8 @@ static unsigned int get_vol_mute(struct hda_codec *codec, struct hda_amp_info *i
  * write the current volume in info to the h/w and update the cache
  */
 static void put_vol_mute(struct hda_codec *codec, struct hda_amp_info *info,
-			 hda_nid_t nid, int ch, int direction, int index, int val)
+			 hda_nid_t nid, int ch, int direction, int index,
+			 int val)
 {
 	u32 parm;
 
@@ -748,8 +758,9 @@ static void put_vol_mute(struct hda_codec *codec, struct hda_amp_info *info,
 int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch,
 			   int direction, int index)
 {
-	struct hda_amp_info *info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, index));
-	if (! info)
+	struct hda_amp_info *info;
+	info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, index));
+	if (!info)
 		return 0;
 	return get_vol_mute(codec, info, nid, ch, direction, index);
 }
@@ -760,13 +771,14 @@ int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch,
 int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
 			     int direction, int idx, int mask, int val)
 {
-	struct hda_amp_info *info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx));
+	struct hda_amp_info *info;
 
-	if (! info)
+	info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx));
+	if (!info)
 		return 0;
 	val &= mask;
 	val |= get_vol_mute(codec, info, nid, ch, direction, idx) & ~mask;
-	if (info->vol[ch] == val && ! codec->in_resume)
+	if (info->vol[ch] == val && !codec->in_resume)
 		return 0;
 	put_vol_mute(codec, info, nid, ch, direction, idx, val);
 	return 1;
@@ -783,7 +795,8 @@ int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
 #define get_amp_index(kc)	(((kc)->private_value >> 19) & 0xf)
 
 /* volume */
-int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
+int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol,
+				  struct snd_ctl_elem_info *uinfo)
 {
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 	u16 nid = get_amp_nid(kcontrol);
@@ -792,9 +805,11 @@ int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_
 	u32 caps;
 
 	caps = query_amp_caps(codec, nid, dir);
-	caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT; /* num steps */
-	if (! caps) {
-		printk(KERN_WARNING "hda_codec: num_steps = 0 for NID=0x%x\n", nid);
+	/* num steps */
+	caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
+	if (!caps) {
+		printk(KERN_WARNING "hda_codec: "
+		       "num_steps = 0 for NID=0x%x\n", nid);
 		return -EINVAL;
 	}
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
@@ -804,7 +819,8 @@ int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_
 	return 0;
 }
 
-int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
 {
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 	hda_nid_t nid = get_amp_nid(kcontrol);
@@ -820,7 +836,8 @@ int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_e
 	return 0;
 }
 
-int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
 {
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 	hda_nid_t nid = get_amp_nid(kcontrol);
@@ -852,7 +869,8 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
 	if (size < 4 * sizeof(unsigned int))
 		return -ENOMEM;
 	caps = query_amp_caps(codec, nid, dir);
-	val2 = (((caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT) + 1) * 25;
+	val2 = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
+	val2 = (val2 + 1) * 25;
 	val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT);
 	val1 = ((int)val1) * ((int)val2);
 	if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv))
@@ -867,7 +885,8 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
 }
 
 /* switch */
-int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
+int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol,
+				  struct snd_ctl_elem_info *uinfo)
 {
 	int chs = get_amp_channels(kcontrol);
 
@@ -878,7 +897,8 @@ int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_
 	return 0;
 }
 
-int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
 {
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 	hda_nid_t nid = get_amp_nid(kcontrol);
@@ -888,13 +908,16 @@ int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_e
 	long *valp = ucontrol->value.integer.value;
 
 	if (chs & 1)
-		*valp++ = (snd_hda_codec_amp_read(codec, nid, 0, dir, idx) & 0x80) ? 0 : 1;
+		*valp++ = (snd_hda_codec_amp_read(codec, nid, 0, dir, idx) &
+			   0x80) ? 0 : 1;
 	if (chs & 2)
-		*valp = (snd_hda_codec_amp_read(codec, nid, 1, dir, idx) & 0x80) ? 0 : 1;
+		*valp = (snd_hda_codec_amp_read(codec, nid, 1, dir, idx) &
+			 0x80) ? 0 : 1;
 	return 0;
 }
 
-int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
 {
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 	hda_nid_t nid = get_amp_nid(kcontrol);
@@ -925,7 +948,8 @@ int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
 #define AMP_VAL_IDX_SHIFT	19
 #define AMP_VAL_IDX_MASK	(0x0f<<19)
 
-int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol,
+				  struct snd_ctl_elem_value *ucontrol)
 {
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 	unsigned long pval;
@@ -940,7 +964,8 @@ int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_
 	return err;
 }
 
-int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
+				  struct snd_ctl_elem_value *ucontrol)
 {
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 	unsigned long pval;
@@ -950,7 +975,8 @@ int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_
 	pval = kcontrol->private_value;
 	indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT;
 	for (i = 0; i < indices; i++) {
-		kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) | (i << AMP_VAL_IDX_SHIFT);
+		kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) |
+			(i << AMP_VAL_IDX_SHIFT);
 		err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
 		if (err < 0)
 			break;
@@ -965,14 +991,16 @@ int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_
  * SPDIF out controls
  */
 
-static int snd_hda_spdif_mask_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
+static int snd_hda_spdif_mask_info(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_info *uinfo)
 {
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
 	uinfo->count = 1;
 	return 0;
 }
 
-static int snd_hda_spdif_cmask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+static int snd_hda_spdif_cmask_get(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
 {
 	ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
 					   IEC958_AES0_NONAUDIO |
@@ -983,7 +1011,8 @@ static int snd_hda_spdif_cmask_get(struct snd_kcontrol *kcontrol, struct snd_ctl
 	return 0;
 }
 
-static int snd_hda_spdif_pmask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+static int snd_hda_spdif_pmask_get(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
 {
 	ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
 					   IEC958_AES0_NONAUDIO |
@@ -991,7 +1020,8 @@ static int snd_hda_spdif_pmask_get(struct snd_kcontrol *kcontrol, struct snd_ctl
 	return 0;
 }
 
-static int snd_hda_spdif_default_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+static int snd_hda_spdif_default_get(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_value *ucontrol)
 {
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 
@@ -1011,19 +1041,21 @@ static unsigned short convert_from_spdif_status(unsigned int sbits)
 	unsigned short val = 0;
 
 	if (sbits & IEC958_AES0_PROFESSIONAL)
-		val |= 1 << 6;
+		val |= AC_DIG1_PROFESSIONAL;
 	if (sbits & IEC958_AES0_NONAUDIO)
-		val |= 1 << 5;
+		val |= AC_DIG1_NONAUDIO;
 	if (sbits & IEC958_AES0_PROFESSIONAL) {
-		if ((sbits & IEC958_AES0_PRO_EMPHASIS) == IEC958_AES0_PRO_EMPHASIS_5015)
-			val |= 1 << 3;
+		if ((sbits & IEC958_AES0_PRO_EMPHASIS) ==
+		    IEC958_AES0_PRO_EMPHASIS_5015)
+			val |= AC_DIG1_EMPHASIS;
 	} else {
-		if ((sbits & IEC958_AES0_CON_EMPHASIS) == IEC958_AES0_CON_EMPHASIS_5015)
-			val |= 1 << 3;
-		if (! (sbits & IEC958_AES0_CON_NOT_COPYRIGHT))
-			val |= 1 << 4;
+		if ((sbits & IEC958_AES0_CON_EMPHASIS) ==
+		    IEC958_AES0_CON_EMPHASIS_5015)
+			val |= AC_DIG1_EMPHASIS;
+		if (!(sbits & IEC958_AES0_CON_NOT_COPYRIGHT))
+			val |= AC_DIG1_COPYRIGHT;
 		if (sbits & (IEC958_AES1_CON_ORIGINAL << 8))
-			val |= 1 << 7;
+			val |= AC_DIG1_LEVEL;
 		val |= sbits & (IEC958_AES1_CON_CATEGORY << 8);
 	}
 	return val;
@@ -1035,26 +1067,27 @@ static unsigned int convert_to_spdif_status(unsigned short val)
 {
 	unsigned int sbits = 0;
 
-	if (val & (1 << 5))
+	if (val & AC_DIG1_NONAUDIO)
 		sbits |= IEC958_AES0_NONAUDIO;
-	if (val & (1 << 6))
+	if (val & AC_DIG1_PROFESSIONAL)
 		sbits |= IEC958_AES0_PROFESSIONAL;
 	if (sbits & IEC958_AES0_PROFESSIONAL) {
-		if (sbits & (1 << 3))
+		if (sbits & AC_DIG1_EMPHASIS)
 			sbits |= IEC958_AES0_PRO_EMPHASIS_5015;
 	} else {
-		if (val & (1 << 3))
+		if (val & AC_DIG1_EMPHASIS)
 			sbits |= IEC958_AES0_CON_EMPHASIS_5015;
-		if (! (val & (1 << 4)))
+		if (!(val & AC_DIG1_COPYRIGHT))
 			sbits |= IEC958_AES0_CON_NOT_COPYRIGHT;
-		if (val & (1 << 7))
+		if (val & AC_DIG1_LEVEL)
 			sbits |= (IEC958_AES1_CON_ORIGINAL << 8);
 		sbits |= val & (0x7f << 8);
 	}
 	return sbits;
 }
 
-static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_value *ucontrol)
 {
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 	hda_nid_t nid = kcontrol->private_value;
@@ -1072,15 +1105,18 @@ static int snd_hda_spdif_default_put(struct snd_kcontrol *kcontrol, struct snd_c
 	codec->spdif_ctls = val;
 
 	if (change || codec->in_resume) {
-		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, val & 0xff);
-		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_2, val >> 8);
+		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1,
+				    val & 0xff);
+		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_2,
+				    val >> 8);
 	}
 
 	mutex_unlock(&codec->spdif_mutex);
 	return change;
 }
 
-static int snd_hda_spdif_out_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
+static int snd_hda_spdif_out_switch_info(struct snd_kcontrol *kcontrol,
+					 struct snd_ctl_elem_info *uinfo)
 {
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
 	uinfo->count = 1;
@@ -1089,15 +1125,17 @@ static int snd_hda_spdif_out_switch_info(struct snd_kcontrol *kcontrol, struct s
 	return 0;
 }
 
-static int snd_hda_spdif_out_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+static int snd_hda_spdif_out_switch_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
 {
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 
-	ucontrol->value.integer.value[0] = codec->spdif_ctls & 1;
+	ucontrol->value.integer.value[0] = codec->spdif_ctls & AC_DIG1_ENABLE;
 	return 0;
 }
 
-static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
 {
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 	hda_nid_t nid = kcontrol->private_value;
@@ -1105,16 +1143,21 @@ static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol, struct sn
 	int change;
 
 	mutex_lock(&codec->spdif_mutex);
-	val = codec->spdif_ctls & ~1;
+	val = codec->spdif_ctls & ~AC_DIG1_ENABLE;
 	if (ucontrol->value.integer.value[0])
-		val |= 1;
+		val |= AC_DIG1_ENABLE;
 	change = codec->spdif_ctls != val;
 	if (change || codec->in_resume) {
 		codec->spdif_ctls = val;
-		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, val & 0xff);
-		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
-				    AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT |
-				    AC_AMP_SET_OUTPUT | ((val & 1) ? 0 : 0x80));
+		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1,
+				    val & 0xff);
+		/* unmute amp switch (if any) */
+		if ((get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) &&
+		    (val & AC_DIG1_ENABLE))
+			snd_hda_codec_write(codec, nid, 0,
+					    AC_VERB_SET_AMP_GAIN_MUTE,
+					    AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT |
+					    AC_AMP_SET_OUTPUT);
 	}
 	mutex_unlock(&codec->spdif_mutex);
 	return change;
@@ -1162,7 +1205,8 @@ static struct snd_kcontrol_new dig_mixes[] = {
  *
  * Returns 0 if successful, or a negative error code.
  */
-int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
+int __devinit snd_hda_create_spdif_out_ctls(struct hda_codec *codec,
+					    hda_nid_t nid)
 {
 	int err;
 	struct snd_kcontrol *kctl;
@@ -1171,10 +1215,12 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
 	for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) {
 		kctl = snd_ctl_new1(dig_mix, codec);
 		kctl->private_value = nid;
-		if ((err = snd_ctl_add(codec->bus->card, kctl)) < 0)
+		err = snd_ctl_add(codec->bus->card, kctl);
+		if (err < 0)
 			return err;
 	}
-	codec->spdif_ctls = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DIGI_CONVERT, 0);
+	codec->spdif_ctls =
+		snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DIGI_CONVERT, 0);
 	codec->spdif_status = convert_to_spdif_status(codec->spdif_ctls);
 	return 0;
 }
@@ -1185,7 +1231,8 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
 
 #define snd_hda_spdif_in_switch_info	snd_hda_spdif_out_switch_info
 
-static int snd_hda_spdif_in_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+static int snd_hda_spdif_in_switch_get(struct snd_kcontrol *kcontrol,
+				       struct snd_ctl_elem_value *ucontrol)
 {
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 
@@ -1193,7 +1240,8 @@ static int snd_hda_spdif_in_switch_get(struct snd_kcontrol *kcontrol, struct snd
 	return 0;
 }
 
-static int snd_hda_spdif_in_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+static int snd_hda_spdif_in_switch_put(struct snd_kcontrol *kcontrol,
+				       struct snd_ctl_elem_value *ucontrol)
 {
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 	hda_nid_t nid = kcontrol->private_value;
@@ -1204,13 +1252,15 @@ static int snd_hda_spdif_in_switch_put(struct snd_kcontrol *kcontrol, struct snd
 	change = codec->spdif_in_enable != val;
 	if (change || codec->in_resume) {
 		codec->spdif_in_enable = val;
-		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, val);
+		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1,
+				    val);
 	}
 	mutex_unlock(&codec->spdif_mutex);
 	return change;
 }
 
-static int snd_hda_spdif_in_status_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+static int snd_hda_spdif_in_status_get(struct snd_kcontrol *kcontrol,
+				       struct snd_ctl_elem_value *ucontrol)
 {
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 	hda_nid_t nid = kcontrol->private_value;
@@ -1254,7 +1304,8 @@ static struct snd_kcontrol_new dig_in_ctls[] = {
  *
  * Returns 0 if successful, or a negative error code.
  */
-int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
+int __devinit snd_hda_create_spdif_in_ctls(struct hda_codec *codec,
+					   hda_nid_t nid)
 {
 	int err;
 	struct snd_kcontrol *kctl;
@@ -1263,10 +1314,13 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
 	for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) {
 		kctl = snd_ctl_new1(dig_mix, codec);
 		kctl->private_value = nid;
-		if ((err = snd_ctl_add(codec->bus->card, kctl)) < 0)
+		err = snd_ctl_add(codec->bus->card, kctl);
+		if (err < 0)
 			return err;
 	}
-	codec->spdif_in_enable = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DIGI_CONVERT, 0) & 1;
+	codec->spdif_in_enable =
+		snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DIGI_CONVERT, 0) &
+		AC_DIG1_ENABLE;
 	return 0;
 }
 
@@ -1304,15 +1358,14 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
  *
  * Returns 0 if successful, otherwise a negative error code.
  */
-int snd_hda_build_controls(struct hda_bus *bus)
+int __devinit snd_hda_build_controls(struct hda_bus *bus)
 {
-	struct list_head *p;
+	struct hda_codec *codec;
 
 	/* build controls */
-	list_for_each(p, &bus->codec_list) {
-		struct hda_codec *codec = list_entry(p, struct hda_codec, list);
+	list_for_each_entry(codec, &bus->codec_list, list) {
 		int err;
-		if (! codec->patch_ops.build_controls)
+		if (!codec->patch_ops.build_controls)
 			continue;
 		err = codec->patch_ops.build_controls(codec);
 		if (err < 0)
@@ -1320,13 +1373,12 @@ int snd_hda_build_controls(struct hda_bus *bus)
 	}
 
 	/* initialize */
-	list_for_each(p, &bus->codec_list) {
-		struct hda_codec *codec = list_entry(p, struct hda_codec, list);
+	list_for_each_entry(codec, &bus->codec_list, list) {
 		int err;
 		hda_set_power_state(codec,
 				    codec->afg ? codec->afg : codec->mfg,
 				    AC_PWRST_D0);
-		if (! codec->patch_ops.init)
+		if (!codec->patch_ops.init)
 			continue;
 		err = codec->patch_ops.init(codec);
 		if (err < 0)
@@ -1335,8 +1387,6 @@ int snd_hda_build_controls(struct hda_bus *bus)
 	return 0;
 }
 
-EXPORT_SYMBOL(snd_hda_build_controls);
-
 /*
  * stream formats
  */
@@ -1361,6 +1411,11 @@ static struct hda_rate_tbl rate_bits[] = {
 	{ 96000, SNDRV_PCM_RATE_96000, 0x0800 }, /* 2 x 48 */
 	{ 176400, SNDRV_PCM_RATE_176400, 0x5800 },/* 4 x 44 */
 	{ 192000, SNDRV_PCM_RATE_192000, 0x1800 }, /* 4 x 48 */
+#define AC_PAR_PCM_RATE_BITS	11
+	/* up to bits 10, 384kHZ isn't supported properly */
+
+	/* not autodetected value */
+	{ 9600, SNDRV_PCM_RATE_KNOT, 0x0400 }, /* 1/5 x 48 */
 
 	{ 0 } /* terminator */
 };
@@ -1389,7 +1444,7 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate,
 			val = rate_bits[i].hda_fmt;
 			break;
 		}
-	if (! rate_bits[i].hz) {
+	if (!rate_bits[i].hz) {
 		snd_printdd("invalid rate %d\n", rate);
 		return 0;
 	}
@@ -1414,15 +1469,14 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate,
 			val |= 0x20;
 		break;
 	default:
-		snd_printdd("invalid format width %d\n", snd_pcm_format_width(format));
+		snd_printdd("invalid format width %d\n",
+			    snd_pcm_format_width(format));
 		return 0;
 	}
 
 	return val;
 }
 
-EXPORT_SYMBOL(snd_hda_calc_stream_format);
-
 /**
  * snd_hda_query_supported_pcm - query the supported PCM rates and formats
  * @codec: the HDA codec
@@ -1449,12 +1503,12 @@ int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
 		if (val == -1)
 			return -EIO;
 	}
-	if (! val)
+	if (!val)
 		val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM);
 
 	if (ratesp) {
 		u32 rates = 0;
-		for (i = 0; rate_bits[i].hz; i++) {
+		for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++) {
 			if (val & (1 << i))
 				rates |= rate_bits[i].alsa_bits;
 		}
@@ -1470,8 +1524,9 @@ int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
 		streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
 		if (streams == -1)
 			return -EIO;
-		if (! streams) {
-			streams = snd_hda_param_read(codec, codec->afg, AC_PAR_STREAM);
+		if (!streams) {
+			streams = snd_hda_param_read(codec, codec->afg,
+						     AC_PAR_STREAM);
 			if (streams == -1)
 				return -EIO;
 		}
@@ -1495,7 +1550,8 @@ int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
 					bps = 24;
 				else if (val & AC_SUPPCM_BITS_20)
 					bps = 20;
-			} else if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24|AC_SUPPCM_BITS_32)) {
+			} else if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24|
+					  AC_SUPPCM_BITS_32)) {
 				formats |= SNDRV_PCM_FMTBIT_S32_LE;
 				if (val & AC_SUPPCM_BITS_32)
 					bps = 32;
@@ -1505,10 +1561,12 @@ int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
 					bps = 20;
 			}
 		}
-		else if (streams == AC_SUPFMT_FLOAT32) { /* should be exclusive */
+		else if (streams == AC_SUPFMT_FLOAT32) {
+			/* should be exclusive */
 			formats |= SNDRV_PCM_FMTBIT_FLOAT_LE;
 			bps = 32;
-		} else if (streams == AC_SUPFMT_AC3) { /* should be exclusive */
+		} else if (streams == AC_SUPFMT_AC3) {
+			/* should be exclusive */
 			/* temporary hack: we have still no proper support
 			 * for the direct AC3 stream...
 			 */
@@ -1525,7 +1583,8 @@ int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
 }
 
 /**
- * snd_hda_is_supported_format - check whether the given node supports the format val
+ * snd_hda_is_supported_format - check whether the given node supports
+ * the format val
  *
  * Returns 1 if supported, 0 if not.
  */
@@ -1541,50 +1600,50 @@ int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
 		if (val == -1)
 			return 0;
 	}
-	if (! val) {
+	if (!val) {
 		val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM);
 		if (val == -1)
 			return 0;
 	}
 
 	rate = format & 0xff00;
-	for (i = 0; rate_bits[i].hz; i++)
+	for (i = 0; i < AC_PAR_PCM_RATE_BITS; i++)
 		if (rate_bits[i].hda_fmt == rate) {
 			if (val & (1 << i))
 				break;
 			return 0;
 		}
-	if (! rate_bits[i].hz)
+	if (i >= AC_PAR_PCM_RATE_BITS)
 		return 0;
 
 	stream = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
 	if (stream == -1)
 		return 0;
-	if (! stream && nid != codec->afg)
+	if (!stream && nid != codec->afg)
 		stream = snd_hda_param_read(codec, codec->afg, AC_PAR_STREAM);
-	if (! stream || stream == -1)
+	if (!stream || stream == -1)
 		return 0;
 
 	if (stream & AC_SUPFMT_PCM) {
 		switch (format & 0xf0) {
 		case 0x00:
-			if (! (val & AC_SUPPCM_BITS_8))
+			if (!(val & AC_SUPPCM_BITS_8))
 				return 0;
 			break;
 		case 0x10:
-			if (! (val & AC_SUPPCM_BITS_16))
+			if (!(val & AC_SUPPCM_BITS_16))
 				return 0;
 			break;
 		case 0x20:
-			if (! (val & AC_SUPPCM_BITS_20))
+			if (!(val & AC_SUPPCM_BITS_20))
 				return 0;
 			break;
 		case 0x30:
-			if (! (val & AC_SUPPCM_BITS_24))
+			if (!(val & AC_SUPPCM_BITS_24))
 				return 0;
 			break;
 		case 0x40:
-			if (! (val & AC_SUPPCM_BITS_32))
+			if (!(val & AC_SUPPCM_BITS_32))
 				return 0;
 			break;
 		default:
@@ -1625,15 +1684,15 @@ static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo,
 	return 0;
 }
 
-static int set_pcm_default_values(struct hda_codec *codec, struct hda_pcm_stream *info)
+static int __devinit set_pcm_default_values(struct hda_codec *codec,
+					    struct hda_pcm_stream *info)
 {
-	if (info->nid) {
-		/* query support PCM information from the given NID */
-		if (! info->rates || ! info->formats)
-			snd_hda_query_supported_pcm(codec, info->nid,
-						    info->rates ? NULL : &info->rates,
-						    info->formats ? NULL : &info->formats,
-						    info->maxbps ? NULL : &info->maxbps);
+	/* query support PCM information from the given NID */
+	if (info->nid && (!info->rates || !info->formats)) {
+		snd_hda_query_supported_pcm(codec, info->nid,
+				info->rates ? NULL : &info->rates,
+				info->formats ? NULL : &info->formats,
+				info->maxbps ? NULL : &info->maxbps);
 	}
 	if (info->ops.open == NULL)
 		info->ops.open = hda_pcm_default_open_close;
@@ -1676,15 +1735,14 @@ static int set_pcm_default_values(struct hda_codec *codec, struct hda_pcm_stream
  *
  * This function returns 0 if successfull, or a negative error code.
  */
-int snd_hda_build_pcms(struct hda_bus *bus)
+int __devinit snd_hda_build_pcms(struct hda_bus *bus)
 {
-	struct list_head *p;
+	struct hda_codec *codec;
 
-	list_for_each(p, &bus->codec_list) {
-		struct hda_codec *codec = list_entry(p, struct hda_codec, list);
+	list_for_each_entry(codec, &bus->codec_list, list) {
 		unsigned int pcm, s;
 		int err;
-		if (! codec->patch_ops.build_pcms)
+		if (!codec->patch_ops.build_pcms)
 			continue;
 		err = codec->patch_ops.build_pcms(codec);
 		if (err < 0)
@@ -1693,7 +1751,7 @@ int snd_hda_build_pcms(struct hda_bus *bus)
 			for (s = 0; s < 2; s++) {
 				struct hda_pcm_stream *info;
 				info = &codec->pcm_info[pcm].stream[s];
-				if (! info->substreams)
+				if (!info->substreams)
 					continue;
 				err = set_pcm_default_values(codec, info);
 				if (err < 0)
@@ -1704,8 +1762,6 @@ int snd_hda_build_pcms(struct hda_bus *bus)
 	return 0;
 }
 
-EXPORT_SYMBOL(snd_hda_build_pcms);
-
 /**
  * snd_hda_check_board_config - compare the current codec with the config table
  * @codec: the HDA codec
@@ -1719,9 +1775,9 @@ EXPORT_SYMBOL(snd_hda_build_pcms);
  *
  * If no entries are matching, the function returns a negative value.
  */
-int snd_hda_check_board_config(struct hda_codec *codec,
-			       int num_configs, const char **models,
-			       const struct snd_pci_quirk *tbl)
+int __devinit snd_hda_check_board_config(struct hda_codec *codec,
+					 int num_configs, const char **models,
+					 const struct snd_pci_quirk *tbl)
 {
 	if (codec->bus->modelname && models) {
 		int i;
@@ -1771,24 +1827,26 @@ int snd_hda_check_board_config(struct hda_codec *codec,
  *
  * Returns 0 if successful, or a negative error code.
  */
-int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew)
+int __devinit snd_hda_add_new_ctls(struct hda_codec *codec,
+				   struct snd_kcontrol_new *knew)
 {
 	int err;
 
 	for (; knew->name; knew++) {
 		struct snd_kcontrol *kctl;
 		kctl = snd_ctl_new1(knew, codec);
-		if (! kctl)
+		if (!kctl)
 			return -ENOMEM;
 		err = snd_ctl_add(codec->bus->card, kctl);
 		if (err < 0) {
-			if (! codec->addr)
+			if (!codec->addr)
 				return err;
 			kctl = snd_ctl_new1(knew, codec);
-			if (! kctl)
+			if (!kctl)
 				return -ENOMEM;
 			kctl->id.device = codec->addr;
-			if ((err = snd_ctl_add(codec->bus->card, kctl)) < 0)
+			err = snd_ctl_add(codec->bus->card, kctl);
+			if (err < 0)
 				return err;
 		}
 	}
@@ -1799,8 +1857,10 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew)
 /*
  * Channel mode helper
  */
-int snd_hda_ch_mode_info(struct hda_codec *codec, struct snd_ctl_elem_info *uinfo,
-			 const struct hda_channel_mode *chmode, int num_chmodes)
+int snd_hda_ch_mode_info(struct hda_codec *codec,
+			 struct snd_ctl_elem_info *uinfo,
+			 const struct hda_channel_mode *chmode,
+			 int num_chmodes)
 {
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 	uinfo->count = 1;
@@ -1812,8 +1872,10 @@ int snd_hda_ch_mode_info(struct hda_codec *codec, struct snd_ctl_elem_info *uinf
 	return 0;
 }
 
-int snd_hda_ch_mode_get(struct hda_codec *codec, struct snd_ctl_elem_value *ucontrol,
-			const struct hda_channel_mode *chmode, int num_chmodes,
+int snd_hda_ch_mode_get(struct hda_codec *codec,
+			struct snd_ctl_elem_value *ucontrol,
+			const struct hda_channel_mode *chmode,
+			int num_chmodes,
 			int max_channels)
 {
 	int i;
@@ -1827,15 +1889,17 @@ int snd_hda_ch_mode_get(struct hda_codec *codec, struct snd_ctl_elem_value *ucon
 	return 0;
 }
 
-int snd_hda_ch_mode_put(struct hda_codec *codec, struct snd_ctl_elem_value *ucontrol,
-			const struct hda_channel_mode *chmode, int num_chmodes,
+int snd_hda_ch_mode_put(struct hda_codec *codec,
+			struct snd_ctl_elem_value *ucontrol,
+			const struct hda_channel_mode *chmode,
+			int num_chmodes,
 			int *max_channelsp)
 {
 	unsigned int mode;
 
 	mode = ucontrol->value.enumerated.item[0];
 	snd_assert(mode < num_chmodes, return -EINVAL);
-	if (*max_channelsp == chmode[mode].channels && ! codec->in_resume)
+	if (*max_channelsp == chmode[mode].channels && !codec->in_resume)
 		return 0;
 	/* change the current channel setting */
 	*max_channelsp = chmode[mode].channels;
@@ -1847,7 +1911,8 @@ int snd_hda_ch_mode_put(struct hda_codec *codec, struct snd_ctl_elem_value *ucon
 /*
  * input MUX helper
  */
-int snd_hda_input_mux_info(const struct hda_input_mux *imux, struct snd_ctl_elem_info *uinfo)
+int snd_hda_input_mux_info(const struct hda_input_mux *imux,
+			   struct snd_ctl_elem_info *uinfo)
 {
 	unsigned int index;
 
@@ -1861,8 +1926,10 @@ int snd_hda_input_mux_info(const struct hda_input_mux *imux, struct snd_ctl_elem
 	return 0;
 }
 
-int snd_hda_input_mux_put(struct hda_codec *codec, const struct hda_input_mux *imux,
-			  struct snd_ctl_elem_value *ucontrol, hda_nid_t nid,
+int snd_hda_input_mux_put(struct hda_codec *codec,
+			  const struct hda_input_mux *imux,
+			  struct snd_ctl_elem_value *ucontrol,
+			  hda_nid_t nid,
 			  unsigned int *cur_val)
 {
 	unsigned int idx;
@@ -1870,7 +1937,7 @@ int snd_hda_input_mux_put(struct hda_codec *codec, const struct hda_input_mux *i
 	idx = ucontrol->value.enumerated.item[0];
 	if (idx >= imux->num_items)
 		idx = imux->num_items - 1;
-	if (*cur_val == idx && ! codec->in_resume)
+	if (*cur_val == idx && !codec->in_resume)
 		return 0;
 	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL,
 			    imux->items[idx].index);
@@ -1883,25 +1950,53 @@ int snd_hda_input_mux_put(struct hda_codec *codec, const struct hda_input_mux *i
  * Multi-channel / digital-out PCM helper functions
  */
 
+/* setup SPDIF output stream */
+static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid,
+				 unsigned int stream_tag, unsigned int format)
+{
+	/* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
+	if (codec->spdif_ctls & AC_DIG1_ENABLE)
+		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1,
+				    codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff);
+	snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
+	/* turn on again (if needed) */
+	if (codec->spdif_ctls & AC_DIG1_ENABLE)
+		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1,
+				    codec->spdif_ctls & 0xff);
+}
+
 /*
  * open the digital out in the exclusive mode
  */
-int snd_hda_multi_out_dig_open(struct hda_codec *codec, struct hda_multi_out *mout)
+int snd_hda_multi_out_dig_open(struct hda_codec *codec,
+			       struct hda_multi_out *mout)
 {
 	mutex_lock(&codec->spdif_mutex);
-	if (mout->dig_out_used) {
-		mutex_unlock(&codec->spdif_mutex);
-		return -EBUSY; /* already being used */
-	}
+	if (mout->dig_out_used == HDA_DIG_ANALOG_DUP)
+		/* already opened as analog dup; reset it once */
+		snd_hda_codec_setup_stream(codec, mout->dig_out_nid, 0, 0, 0);
 	mout->dig_out_used = HDA_DIG_EXCLUSIVE;
 	mutex_unlock(&codec->spdif_mutex);
 	return 0;
 }
 
+int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
+				  struct hda_multi_out *mout,
+				  unsigned int stream_tag,
+				  unsigned int format,
+				  struct snd_pcm_substream *substream)
+{
+	mutex_lock(&codec->spdif_mutex);
+	setup_dig_out_stream(codec, mout->dig_out_nid, stream_tag, format);
+	mutex_unlock(&codec->spdif_mutex);
+	return 0;
+}
+
 /*
  * release the digital out
  */
-int snd_hda_multi_out_dig_close(struct hda_codec *codec, struct hda_multi_out *mout)
+int snd_hda_multi_out_dig_close(struct hda_codec *codec,
+				struct hda_multi_out *mout)
 {
 	mutex_lock(&codec->spdif_mutex);
 	mout->dig_out_used = 0;
@@ -1912,7 +2007,8 @@ int snd_hda_multi_out_dig_close(struct hda_codec *codec, struct hda_multi_out *m
 /*
  * set up more restrictions for analog out
  */
-int snd_hda_multi_out_analog_open(struct hda_codec *codec, struct hda_multi_out *mout,
+int snd_hda_multi_out_analog_open(struct hda_codec *codec,
+				  struct hda_multi_out *mout,
 				  struct snd_pcm_substream *substream)
 {
 	substream->runtime->hw.channels_max = mout->max_channels;
@@ -1924,7 +2020,8 @@ int snd_hda_multi_out_analog_open(struct hda_codec *codec, struct hda_multi_out
  * set up the i/o for analog out
  * when the digital out is available, copy the front out to digital out, too.
  */
-int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, struct hda_multi_out *mout,
+int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
+				     struct hda_multi_out *mout,
 				     unsigned int stream_tag,
 				     unsigned int format,
 				     struct snd_pcm_substream *substream)
@@ -1936,24 +2033,27 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, struct hda_multi_o
 	mutex_lock(&codec->spdif_mutex);
 	if (mout->dig_out_nid && mout->dig_out_used != HDA_DIG_EXCLUSIVE) {
 		if (chs == 2 &&
-		    snd_hda_is_supported_format(codec, mout->dig_out_nid, format) &&
-		    ! (codec->spdif_status & IEC958_AES0_NONAUDIO)) {
+		    snd_hda_is_supported_format(codec, mout->dig_out_nid,
+						format) &&
+		    !(codec->spdif_status & IEC958_AES0_NONAUDIO)) {
 			mout->dig_out_used = HDA_DIG_ANALOG_DUP;
-			/* setup digital receiver */
-			snd_hda_codec_setup_stream(codec, mout->dig_out_nid,
-						   stream_tag, 0, format);
+			setup_dig_out_stream(codec, mout->dig_out_nid,
+					     stream_tag, format);
 		} else {
 			mout->dig_out_used = 0;
-			snd_hda_codec_setup_stream(codec, mout->dig_out_nid, 0, 0, 0);
+			snd_hda_codec_setup_stream(codec, mout->dig_out_nid,
+						   0, 0, 0);
 		}
 	}
 	mutex_unlock(&codec->spdif_mutex);
 
 	/* front */
-	snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag, 0, format);
+	snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag,
+				   0, format);
 	if (mout->hp_nid && mout->hp_nid != nids[HDA_FRONT])
 		/* headphone out will just decode front left/right (stereo) */
-		snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag, 0, format);
+		snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag,
+					   0, format);
 	/* extra outputs copied from front */
 	for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
 		if (mout->extra_out_nid[i])
@@ -1964,11 +2064,11 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, struct hda_multi_o
 	/* surrounds */
 	for (i = 1; i < mout->num_dacs; i++) {
 		if (chs >= (i + 1) * 2) /* independent out */
-			snd_hda_codec_setup_stream(codec, nids[i], stream_tag, i * 2,
-						   format);
+			snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
+						   i * 2, format);
 		else /* copy front */
-			snd_hda_codec_setup_stream(codec, nids[i], stream_tag, 0,
-						   format);
+			snd_hda_codec_setup_stream(codec, nids[i], stream_tag,
+						   0, format);
 	}
 	return 0;
 }
@@ -1976,7 +2076,8 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, struct hda_multi_o
 /*
  * clean up the setting for analog out
  */
-int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec, struct hda_multi_out *mout)
+int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
+				     struct hda_multi_out *mout)
 {
 	hda_nid_t *nids = mout->dac_nids;
 	int i;
@@ -2003,7 +2104,7 @@ int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec, struct hda_multi_o
  * Helper for automatic ping configuration
  */
 
-static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list)
+static int __devinit is_in_nid_list(hda_nid_t nid, hda_nid_t *list)
 {
 	for (; *list; list++)
 		if (*list == nid)
@@ -2011,6 +2112,32 @@ static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list)
 	return 0;
 }
 
+
+/*
+ * Sort an associated group of pins according to their sequence numbers.
+ */
+static void sort_pins_by_sequence(hda_nid_t * pins, short * sequences,
+				  int num_pins)
+{
+	int i, j;
+	short seq;
+	hda_nid_t nid;
+	
+	for (i = 0; i < num_pins; i++) {
+		for (j = i + 1; j < num_pins; j++) {
+			if (sequences[i] > sequences[j]) {
+				seq = sequences[i];
+				sequences[i] = sequences[j];
+				sequences[j] = seq;
+				nid = pins[i];
+				pins[i] = pins[j];
+				pins[j] = nid;
+			}
+		}
+	}
+}
+
+
 /*
  * Parse all pin widgets and store the useful pin nids to cfg
  *
@@ -2028,22 +2155,27 @@ static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list)
  * The digital input/output pins are assigned to dig_in_pin and dig_out_pin,
  * respectively.
  */
-int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *cfg,
-				 hda_nid_t *ignore_nids)
+int __devinit snd_hda_parse_pin_def_config(struct hda_codec *codec,
+					   struct auto_pin_cfg *cfg,
+					   hda_nid_t *ignore_nids)
 {
 	hda_nid_t nid, nid_start;
-	int i, j, nodes;
-	short seq, assoc_line_out, sequences[ARRAY_SIZE(cfg->line_out_pins)];
+	int nodes;
+	short seq, assoc_line_out, assoc_speaker;
+	short sequences_line_out[ARRAY_SIZE(cfg->line_out_pins)];
+	short sequences_speaker[ARRAY_SIZE(cfg->speaker_pins)];
 
 	memset(cfg, 0, sizeof(*cfg));
 
-	memset(sequences, 0, sizeof(sequences));
-	assoc_line_out = 0;
+	memset(sequences_line_out, 0, sizeof(sequences_line_out));
+	memset(sequences_speaker, 0, sizeof(sequences_speaker));
+	assoc_line_out = assoc_speaker = 0;
 
 	nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid_start);
 	for (nid = nid_start; nid < nodes + nid_start; nid++) {
 		unsigned int wid_caps = get_wcaps(codec, nid);
-		unsigned int wid_type = (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
+		unsigned int wid_type =
+			(wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
 		unsigned int def_conf;
 		short assoc, loc;
 
@@ -2054,7 +2186,8 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *c
 		if (ignore_nids && is_in_nid_list(nid, ignore_nids))
 			continue;
 
-		def_conf = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
+		def_conf = snd_hda_codec_read(codec, nid, 0,
+					      AC_VERB_GET_CONFIG_DEFAULT, 0);
 		if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE)
 			continue;
 		loc = get_defcfg_location(def_conf);
@@ -2062,22 +2195,31 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *c
 		case AC_JACK_LINE_OUT:
 			seq = get_defcfg_sequence(def_conf);
 			assoc = get_defcfg_association(def_conf);
-			if (! assoc)
+			if (!assoc)
 				continue;
-			if (! assoc_line_out)
+			if (!assoc_line_out)
 				assoc_line_out = assoc;
 			else if (assoc_line_out != assoc)
 				continue;
 			if (cfg->line_outs >= ARRAY_SIZE(cfg->line_out_pins))
 				continue;
 			cfg->line_out_pins[cfg->line_outs] = nid;
-			sequences[cfg->line_outs] = seq;
+			sequences_line_out[cfg->line_outs] = seq;
 			cfg->line_outs++;
 			break;
 		case AC_JACK_SPEAKER:
+			seq = get_defcfg_sequence(def_conf);
+			assoc = get_defcfg_association(def_conf);
+			if (! assoc)
+				continue;
+			if (! assoc_speaker)
+				assoc_speaker = assoc;
+			else if (assoc_speaker != assoc)
+				continue;
 			if (cfg->speaker_outs >= ARRAY_SIZE(cfg->speaker_pins))
 				continue;
 			cfg->speaker_pins[cfg->speaker_outs] = nid;
+			sequences_speaker[cfg->speaker_outs] = seq;
 			cfg->speaker_outs++;
 			break;
 		case AC_JACK_HP_OUT:
@@ -2123,34 +2265,45 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *c
 	}
 
 	/* sort by sequence */
-	for (i = 0; i < cfg->line_outs; i++)
-		for (j = i + 1; j < cfg->line_outs; j++)
-			if (sequences[i] > sequences[j]) {
-				seq = sequences[i];
-				sequences[i] = sequences[j];
-				sequences[j] = seq;
-				nid = cfg->line_out_pins[i];
-				cfg->line_out_pins[i] = cfg->line_out_pins[j];
-				cfg->line_out_pins[j] = nid;
-			}
+	sort_pins_by_sequence(cfg->line_out_pins, sequences_line_out,
+			      cfg->line_outs);
+	sort_pins_by_sequence(cfg->speaker_pins, sequences_speaker,
+			      cfg->speaker_outs);
+	
+	/*
+	 * FIX-UP: if no line-outs are detected, try to use speaker or HP pin
+	 * as a primary output
+	 */
+	if (!cfg->line_outs) {
+		if (cfg->speaker_outs) {
+			cfg->line_outs = cfg->speaker_outs;
+			memcpy(cfg->line_out_pins, cfg->speaker_pins,
+			       sizeof(cfg->speaker_pins));
+			cfg->speaker_outs = 0;
+			memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
+			cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
+		} else if (cfg->hp_outs) {
+			cfg->line_outs = cfg->hp_outs;
+			memcpy(cfg->line_out_pins, cfg->hp_pins,
+			       sizeof(cfg->hp_pins));
+			cfg->hp_outs = 0;
+			memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
+			cfg->line_out_type = AUTO_PIN_HP_OUT;
+		}
+	}
 
 	/* Reorder the surround channels
 	 * ALSA sequence is front/surr/clfe/side
 	 * HDA sequence is:
 	 *    4-ch: front/surr  =>  OK as it is
 	 *    6-ch: front/clfe/surr
-	 *    8-ch: front/clfe/side/surr
+	 *    8-ch: front/clfe/rear/side|fc
 	 */
 	switch (cfg->line_outs) {
 	case 3:
-		nid = cfg->line_out_pins[1];
-		cfg->line_out_pins[1] = cfg->line_out_pins[2];
-		cfg->line_out_pins[2] = nid;
-		break;
 	case 4:
 		nid = cfg->line_out_pins[1];
-		cfg->line_out_pins[1] = cfg->line_out_pins[3];
-		cfg->line_out_pins[3] = cfg->line_out_pins[2];
+		cfg->line_out_pins[1] = cfg->line_out_pins[2];
 		cfg->line_out_pins[2] = nid;
 		break;
 	}
@@ -2179,26 +2332,6 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *c
 		   cfg->input_pins[AUTO_PIN_CD],
 		   cfg->input_pins[AUTO_PIN_AUX]);
 
-	/*
-	 * FIX-UP: if no line-outs are detected, try to use speaker or HP pin
-	 * as a primary output
-	 */
-	if (! cfg->line_outs) {
-		if (cfg->speaker_outs) {
-			cfg->line_outs = cfg->speaker_outs;
-			memcpy(cfg->line_out_pins, cfg->speaker_pins,
-			       sizeof(cfg->speaker_pins));
-			cfg->speaker_outs = 0;
-			memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
-		} else if (cfg->hp_outs) {
-			cfg->line_outs = cfg->hp_outs;
-			memcpy(cfg->line_out_pins, cfg->hp_pins,
-			       sizeof(cfg->hp_pins));
-			cfg->hp_outs = 0;
-			memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
-		}
-	}
-
 	return 0;
 }
 
@@ -2222,11 +2355,10 @@ const char *auto_pin_cfg_labels[AUTO_PIN_LAST] = {
  */
 int snd_hda_suspend(struct hda_bus *bus, pm_message_t state)
 {
-	struct list_head *p;
+	struct hda_codec *codec;
 
 	/* FIXME: should handle power widget capabilities */
-	list_for_each(p, &bus->codec_list) {
-		struct hda_codec *codec = list_entry(p, struct hda_codec, list);
+	list_for_each_entry(codec, &bus->codec_list, list) {
 		if (codec->patch_ops.suspend)
 			codec->patch_ops.suspend(codec, state);
 		hda_set_power_state(codec,
@@ -2236,8 +2368,6 @@ int snd_hda_suspend(struct hda_bus *bus, pm_message_t state)
 	return 0;
 }
 
-EXPORT_SYMBOL(snd_hda_suspend);
-
 /**
  * snd_hda_resume - resume the codecs
  * @bus: the HDA bus
@@ -2247,10 +2377,9 @@ EXPORT_SYMBOL(snd_hda_suspend);
  */
 int snd_hda_resume(struct hda_bus *bus)
 {
-	struct list_head *p;
+	struct hda_codec *codec;
 
-	list_for_each(p, &bus->codec_list) {
-		struct hda_codec *codec = list_entry(p, struct hda_codec, list);
+	list_for_each_entry(codec, &bus->codec_list, list) {
 		hda_set_power_state(codec,
 				    codec->afg ? codec->afg : codec->mfg,
 				    AC_PWRST_D0);
@@ -2260,8 +2389,6 @@ int snd_hda_resume(struct hda_bus *bus)
 	return 0;
 }
 
-EXPORT_SYMBOL(snd_hda_resume);
-
 /**
  * snd_hda_resume_ctls - resume controls in the new control list
  * @codec: the HDA codec
@@ -2276,7 +2403,7 @@ int snd_hda_resume_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew)
 	struct snd_ctl_elem_value *val;
 
 	val = kmalloc(sizeof(*val), GFP_KERNEL);
-	if (! val)
+	if (!val)
 		return -ENOMEM;
 	codec->in_resume = 1;
 	for (; knew->name; knew++) {
@@ -2320,19 +2447,3 @@ int snd_hda_resume_spdif_in(struct hda_codec *codec)
 	return snd_hda_resume_ctls(codec, dig_in_ctls);
 }
 #endif
-
-/*
- *  INIT part
- */
-
-static int __init alsa_hda_init(void)
-{
-	return 0;
-}
-
-static void __exit alsa_hda_exit(void)
-{
-}
-
-module_init(alsa_hda_init)
-module_exit(alsa_hda_exit)
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index c12bc4e8840f..56c26e7ccdf1 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -233,7 +233,7 @@ enum {
  */
 
 /* Amp gain/mute */
-#define AC_AMP_MUTE			(1<<8)
+#define AC_AMP_MUTE			(1<<7)
 #define AC_AMP_GAIN			(0x7f)
 #define AC_AMP_GET_INDEX		(0xf<<0)
 
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index 1e5ff0cd3709..000287f7da43 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -133,7 +133,7 @@ static int add_new_node(struct hda_codec *codec, struct hda_gspec *spec, hda_nid
 			return -ENOMEM;
 		}
 	}
-	memcpy(node->conn_list, conn_list, nconns);
+	memcpy(node->conn_list, conn_list, nconns * sizeof(hda_nid_t));
 	node->nconns = nconns;
 	node->wid_caps = get_wcaps(codec, nid);
 	node->type = (node->wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 1672cace1ae7..2fa281cbef91 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -88,6 +88,8 @@ MODULE_SUPPORTED_DEVICE("{{Intel, ICH6},"
 			 "{ATI, SB600},"
 			 "{ATI, RS600},"
 			 "{ATI, RS690},"
+			 "{ATI, RS780},"
+			 "{ATI, R600},"
 			 "{VIA, VT8251},"
 			 "{VIA, VT8237A},"
 			 "{SiS, SIS966},"
@@ -198,6 +200,7 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
 #define RIRB_INT_MASK		0x05
 
 /* STATESTS int mask: SD2,SD1,SD0 */
+#define AZX_MAX_CODECS		3
 #define STATESTS_INT_MASK	0x07
 
 /* SD_CTL bits */
@@ -978,7 +981,7 @@ static unsigned int azx_max_codecs[] __devinitdata = {
 static int __devinit azx_codec_create(struct azx *chip, const char *model)
 {
 	struct hda_bus_template bus_temp;
-	int c, codecs, err;
+	int c, codecs, audio_codecs, err;
 
 	memset(&bus_temp, 0, sizeof(bus_temp));
 	bus_temp.private_data = chip;
@@ -990,16 +993,30 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model)
 	if ((err = snd_hda_bus_new(chip->card, &bus_temp, &chip->bus)) < 0)
 		return err;
 
-	codecs = 0;
-	for (c = 0; c < azx_max_codecs[chip->driver_type]; c++) {
+	codecs = audio_codecs = 0;
+	for (c = 0; c < AZX_MAX_CODECS; c++) {
 		if ((chip->codec_mask & (1 << c)) & probe_mask) {
-			err = snd_hda_codec_new(chip->bus, c, NULL);
+			struct hda_codec *codec;
+			err = snd_hda_codec_new(chip->bus, c, &codec);
 			if (err < 0)
 				continue;
 			codecs++;
+			if (codec->afg)
+				audio_codecs++;
 		}
 	}
-	if (! codecs) {
+	if (!audio_codecs) {
+		/* probe additional slots if no codec is found */
+		for (; c < azx_max_codecs[chip->driver_type]; c++) {
+			if ((chip->codec_mask & (1 << c)) & probe_mask) {
+				err = snd_hda_codec_new(chip->bus, c, NULL);
+				if (err < 0)
+					continue;
+				codecs++;
+			}
+		}
+	}
+	if (!codecs) {
 		snd_printk(KERN_ERR SFX "no codecs initialized\n");
 		return -ENXIO;
 	}
@@ -1518,7 +1535,7 @@ static int azx_dev_free(struct snd_device *device)
 /*
  * white/black-listing for position_fix
  */
-static const struct snd_pci_quirk position_fix_list[] __devinitdata = {
+static struct snd_pci_quirk position_fix_list[] __devinitdata = {
 	SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_NONE),
 	{}
 };
@@ -1758,6 +1775,8 @@ static struct pci_device_id azx_ids[] = {
 	{ 0x1002, 0x4383, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB600 */
 	{ 0x1002, 0x793b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RS600 HDMI */
 	{ 0x1002, 0x7919, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RS690 HDMI */
+	{ 0x1002, 0x960c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RS780 HDMI */
+	{ 0x1002, 0xaa00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI R600 HDMI */
 	{ 0x1106, 0x3288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_VIA }, /* VIA VT8251/VT8237A */
 	{ 0x1039, 0x7502, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_SIS }, /* SIS966 */
 	{ 0x10b9, 0x5461, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ULI }, /* ULI M5461 */
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index 39718d6cdadd..be12b8814c39 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -148,6 +148,11 @@ struct hda_multi_out {
 
 int snd_hda_multi_out_dig_open(struct hda_codec *codec, struct hda_multi_out *mout);
 int snd_hda_multi_out_dig_close(struct hda_codec *codec, struct hda_multi_out *mout);
+int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
+				  struct hda_multi_out *mout,
+				  unsigned int stream_tag,
+				  unsigned int format,
+				  struct snd_pcm_substream *substream);
 int snd_hda_multi_out_analog_open(struct hda_codec *codec, struct hda_multi_out *mout,
 				  struct snd_pcm_substream *substream);
 int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, struct hda_multi_out *mout,
@@ -217,6 +222,12 @@ enum {
 	AUTO_PIN_LAST
 };
 
+enum {
+	AUTO_PIN_LINE_OUT,
+	AUTO_PIN_SPEAKER_OUT,
+	AUTO_PIN_HP_OUT
+};
+
 extern const char *auto_pin_cfg_labels[AUTO_PIN_LAST];
 
 struct auto_pin_cfg {
@@ -225,6 +236,7 @@ struct auto_pin_cfg {
 	int speaker_outs;
 	hda_nid_t speaker_pins[5];
 	int hp_outs;
+	int line_out_type;	/* AUTO_PIN_XXX_OUT */
 	hda_nid_t hp_pins[5];
 	hda_nid_t input_pins[AUTO_PIN_LAST];
 	hda_nid_t dig_out_pin;
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index f94f1f22889e..0e1a879663fa 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -192,6 +192,17 @@ static int ad198x_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
 	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
 }
 
+static int ad198x_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
+					   struct hda_codec *codec,
+					   unsigned int stream_tag,
+					   unsigned int format,
+					   struct snd_pcm_substream *substream)
+{
+	struct ad198x_spec *spec = codec->spec;
+	return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag,
+					     format, substream);
+}
+
 /*
  * Analog capture
  */
@@ -250,7 +261,8 @@ static struct hda_pcm_stream ad198x_pcm_digital_playback = {
 	.nid = 0, /* fill later */
 	.ops = {
 		.open = ad198x_dig_playback_pcm_open,
-		.close = ad198x_dig_playback_pcm_close
+		.close = ad198x_dig_playback_pcm_close,
+		.prepare = ad198x_dig_playback_pcm_prepare
 	},
 };
 
@@ -739,41 +751,35 @@ static struct hda_verb ad1986a_init_verbs[] = {
 	{ } /* end */
 };
 
-/* additional verbs for 3-stack model */
-static struct hda_verb ad1986a_3st_init_verbs[] = {
- 	/* Mic and line-in selectors */
-	{0x0f, AC_VERB_SET_CONNECT_SEL, 0x2},
-	{0x10, AC_VERB_SET_CONNECT_SEL, 0x1},
- 	{ } /* end */
-};
-
 static struct hda_verb ad1986a_ch2_init[] = {
 	/* Surround out -> Line In */
-	{ 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
-	{ 0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+	{ 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
+ 	/* Line-in selectors */
+	{ 0x10, AC_VERB_SET_CONNECT_SEL, 0x1 },
 	/* CLFE -> Mic in */
-	{ 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
-	{ 0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+	{ 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
+	/* Mic selector, mix C/LFE (backmic) and Mic (frontmic) */
+	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x4 },
 	{ } /* end */
 };
 
 static struct hda_verb ad1986a_ch4_init[] = {
 	/* Surround out -> Surround */
-	{ 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
-	{ 0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+	{ 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 },
 	/* CLFE -> Mic in */
-	{ 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
-	{ 0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+	{ 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
+	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x4 },
 	{ } /* end */
 };
 
 static struct hda_verb ad1986a_ch6_init[] = {
 	/* Surround out -> Surround out */
-	{ 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
-	{ 0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+	{ 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 },
 	/* CLFE -> CLFE */
-	{ 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
-	{ 0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+	{ 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x0 },
 	{ } /* end */
 };
 
@@ -828,6 +834,7 @@ static struct snd_pci_quirk ad1986a_cfg_tbl[] = {
 	SND_PCI_QUIRK(0x1043, 0x1297, "ASUS Z62F", AD1986A_LAPTOP_EAPD),
 	SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS V1j", AD1986A_LAPTOP_EAPD),
 	SND_PCI_QUIRK(0x1043, 0x1302, "ASUS W3j", AD1986A_LAPTOP_EAPD),
+	SND_PCI_QUIRK(0x1043, 0x1447, "ASUS A8J", AD1986A_3STACK),
 	SND_PCI_QUIRK(0x1043, 0x817f, "ASUS P5", AD1986A_3STACK),
 	SND_PCI_QUIRK(0x1043, 0x818f, "ASUS P5", AD1986A_LAPTOP),
 	SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS P5", AD1986A_3STACK),
@@ -882,9 +889,8 @@ static int patch_ad1986a(struct hda_codec *codec)
 	case AD1986A_3STACK:
 		spec->num_mixers = 2;
 		spec->mixers[1] = ad1986a_3st_mixers;
-		spec->num_init_verbs = 3;
-		spec->init_verbs[1] = ad1986a_3st_init_verbs;
-		spec->init_verbs[2] = ad1986a_ch2_init;
+		spec->num_init_verbs = 2;
+		spec->init_verbs[1] = ad1986a_ch2_init;
 		spec->channel_mode = ad1986a_modes;
 		spec->num_channel_mode = ARRAY_SIZE(ad1986a_modes);
 		spec->need_dac_fix = 1;
@@ -1892,8 +1898,9 @@ static int ad1988_spdif_playback_source_get(struct snd_kcontrol *kcontrol,
 
 	sel = snd_hda_codec_read(codec, 0x02, 0, AC_VERB_GET_CONNECT_SEL, 0);
 	if (sel > 0) {
-		sel = snd_hda_codec_read(codec, 0x0b, 0, AC_VERB_GET_CONNECT_SEL, 0);
-		if (sel <= 3)
+		sel = snd_hda_codec_read(codec, 0x0b, 0,
+					 AC_VERB_GET_CONNECT_SEL, 0);
+		if (sel < 3)
 			sel++;
 		else
 			sel = 0;
@@ -1906,23 +1913,27 @@ static int ad1988_spdif_playback_source_put(struct snd_kcontrol *kcontrol,
 					    struct snd_ctl_elem_value *ucontrol)
 {
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	unsigned int sel;
+	unsigned int val, sel;
 	int change;
 
+	val = ucontrol->value.enumerated.item[0];
 	sel = snd_hda_codec_read(codec, 0x02, 0, AC_VERB_GET_CONNECT_SEL, 0);
-	if (! ucontrol->value.enumerated.item[0]) {
+	if (!val) {
 		change = sel != 0;
-		if (change)
-			snd_hda_codec_write(codec, 0x02, 0, AC_VERB_SET_CONNECT_SEL, 0);
+		if (change || codec->in_resume)
+			snd_hda_codec_write(codec, 0x02, 0,
+					    AC_VERB_SET_CONNECT_SEL, 0);
 	} else {
 		change = sel == 0;
-		if (change)
-			snd_hda_codec_write(codec, 0x02, 0, AC_VERB_SET_CONNECT_SEL, 1);
-		sel = snd_hda_codec_read(codec, 0x0b, 0, AC_VERB_GET_CONNECT_SEL, 0) + 1;
-		change |= sel == ucontrol->value.enumerated.item[0];
-		if (change)
-			snd_hda_codec_write(codec, 0x02, 0, AC_VERB_SET_CONNECT_SEL,
-					    ucontrol->value.enumerated.item[0] - 1);
+		if (change || codec->in_resume)
+			snd_hda_codec_write(codec, 0x02, 0,
+					    AC_VERB_SET_CONNECT_SEL, 1);
+		sel = snd_hda_codec_read(codec, 0x0b, 0,
+					 AC_VERB_GET_CONNECT_SEL, 0) + 1;
+		change |= sel != val;
+		if (change || codec->in_resume)
+			snd_hda_codec_write(codec, 0x0b, 0,
+					    AC_VERB_SET_CONNECT_SEL, val - 1);
 	}
 	return change;
 }
diff --git a/sound/pci/hda/patch_atihdmi.c b/sound/pci/hda/patch_atihdmi.c
index 831469d3a923..f8eb4c90f801 100644
--- a/sound/pci/hda/patch_atihdmi.c
+++ b/sound/pci/hda/patch_atihdmi.c
@@ -94,6 +94,17 @@ static int atihdmi_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
 	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
 }
 
+static int atihdmi_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
+					    struct hda_codec *codec,
+					    unsigned int stream_tag,
+					    unsigned int format,
+					    struct snd_pcm_substream *substream)
+{
+	struct atihdmi_spec *spec = codec->spec;
+	return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag,
+					     format, substream);
+}
+
 static struct hda_pcm_stream atihdmi_pcm_digital_playback = {
 	.substreams = 1,
 	.channels_min = 2,
@@ -101,7 +112,8 @@ static struct hda_pcm_stream atihdmi_pcm_digital_playback = {
 	.nid = 0x2, /* NID to query formats and rates and setup streams */
 	.ops = {
 		.open = atihdmi_dig_playback_pcm_open,
-		.close = atihdmi_dig_playback_pcm_close
+		.close = atihdmi_dig_playback_pcm_close,
+		.prepare = atihdmi_dig_playback_pcm_prepare
 	},
 };
 
@@ -160,6 +172,7 @@ static int patch_atihdmi(struct hda_codec *codec)
  */
 struct hda_codec_preset snd_hda_preset_atihdmi[] = {
 	{ .id = 0x1002793c, .name = "ATI RS600 HDMI", .patch = patch_atihdmi },
-	{ .id = 0x1002791a, .name = "ATI RS690 HDMI", .patch = patch_atihdmi },
+	{ .id = 0x1002791a, .name = "ATI RS690/780 HDMI", .patch = patch_atihdmi },
+	{ .id = 0x1002aa01, .name = "ATI R600 HDMI", .patch = patch_atihdmi },
 	{} /* terminator */
 };
diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c
index 5b9d3a31a1ae..3c722e667bc8 100644
--- a/sound/pci/hda/patch_cmedia.c
+++ b/sound/pci/hda/patch_cmedia.c
@@ -497,6 +497,17 @@ static int cmi9880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
 	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
 }
 
+static int cmi9880_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
+					    struct hda_codec *codec,
+					    unsigned int stream_tag,
+					    unsigned int format,
+					    struct snd_pcm_substream *substream)
+{
+	struct cmi_spec *spec = codec->spec;
+	return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag,
+					     format, substream);
+}
+
 /*
  * Analog capture
  */
@@ -556,7 +567,8 @@ static struct hda_pcm_stream cmi9880_pcm_digital_playback = {
 	/* NID is set in cmi9880_build_pcms */
 	.ops = {
 		.open = cmi9880_dig_playback_pcm_open,
-		.close = cmi9880_dig_playback_pcm_close
+		.close = cmi9880_dig_playback_pcm_close,
+		.prepare = cmi9880_dig_playback_pcm_prepare
 	},
 };
 
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index 46e93c6b9a42..a5a4b2bddf20 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -136,6 +136,18 @@ static int conexant_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
 	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
 }
 
+static int conexant_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
+					 struct hda_codec *codec,
+					 unsigned int stream_tag,
+					 unsigned int format,
+					 struct snd_pcm_substream *substream)
+{
+	struct conexant_spec *spec = codec->spec;
+	return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
+					     stream_tag,
+					     format, substream);
+}
+
 /*
  * Analog capture
  */
@@ -194,7 +206,8 @@ static struct hda_pcm_stream conexant_pcm_digital_playback = {
 	.nid = 0, /* fill later */
 	.ops = {
 		.open = conexant_dig_playback_pcm_open,
-		.close = conexant_dig_playback_pcm_close
+		.close = conexant_dig_playback_pcm_close,
+		.prepare = conexant_dig_playback_pcm_prepare
 	},
 };
 
@@ -452,115 +465,6 @@ static int conexant_ch_mode_put(struct snd_kcontrol *kcontrol,
 	  .put = conexant_ch_mode_put, \
 	  .private_value = nid | (dir<<16) }
 
-static int cxt_gpio_data_info(struct snd_kcontrol *kcontrol,
-			      struct snd_ctl_elem_info *uinfo)
-{
-	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
-	uinfo->count = 1;
-	uinfo->value.integer.min = 0;
-	uinfo->value.integer.max = 1;
-	return 0;
-}                                
-
-static int cxt_gpio_data_get(struct snd_kcontrol *kcontrol,
-			     struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	hda_nid_t nid = kcontrol->private_value & 0xffff;
-	unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
-	long *valp = ucontrol->value.integer.value;
-	unsigned int val = snd_hda_codec_read(codec, nid, 0,
-					      AC_VERB_GET_GPIO_DATA, 0x00);
-
-	*valp = (val & mask) != 0;
-	return 0;
-}
-
-static int cxt_gpio_data_put(struct snd_kcontrol *kcontrol,
-			     struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	hda_nid_t nid = kcontrol->private_value & 0xffff;
-	unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
-	long val = *ucontrol->value.integer.value;
-	unsigned int gpio_data = snd_hda_codec_read(codec, nid, 0,
-						    AC_VERB_GET_GPIO_DATA,
-						    0x00);
-	unsigned int old_data = gpio_data;
-
-	/* Set/unset the masked GPIO bit(s) as needed */
-	if (val == 0)
-		gpio_data &= ~mask;
-	else
-		gpio_data |= mask;
-	if (gpio_data == old_data && !codec->in_resume)
-		return 0;
-	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_GPIO_DATA, gpio_data);
-	return 1;
-}
-
-#define CXT_GPIO_DATA_SWITCH(xname, nid, mask) \
-	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
-	  .info = cxt_gpio_data_info, \
-	  .get = cxt_gpio_data_get, \
-	  .put = cxt_gpio_data_put, \
-	  .private_value = nid | (mask<<16) }
-#if 0
-static int cxt_spdif_ctrl_info(struct snd_kcontrol *kcontrol,
-			       struct snd_ctl_elem_info *uinfo)
-{
-	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
-	uinfo->count = 1;
-	uinfo->value.integer.min = 0;
-	uinfo->value.integer.max = 1;
-	return 0;
-}                                
-
-static int cxt_spdif_ctrl_get(struct snd_kcontrol *kcontrol,
-			      struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	hda_nid_t nid = kcontrol->private_value & 0xffff;
-	unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
-	long *valp = ucontrol->value.integer.value;
-	unsigned int val = snd_hda_codec_read(codec, nid, 0,
-					      AC_VERB_GET_DIGI_CONVERT, 0x00);
-
-	*valp = (val & mask) != 0;
-	return 0;
-}
-
-static int cxt_spdif_ctrl_put(struct snd_kcontrol *kcontrol,
-			      struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	hda_nid_t nid = kcontrol->private_value & 0xffff;
-	unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
-	long val = *ucontrol->value.integer.value;
-	unsigned int ctrl_data = snd_hda_codec_read(codec, nid, 0,
-						    AC_VERB_GET_DIGI_CONVERT,
-						    0x00);
-	unsigned int old_data = ctrl_data;
-
-	/* Set/unset the masked control bit(s) as needed */
-	if (val == 0)
-		ctrl_data &= ~mask;
-	else
-		ctrl_data |= mask;
-	if (ctrl_data == old_data && !codec->in_resume)
-		return 0;
-	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1,
-			    ctrl_data);
-	return 1;
-}
-
-#define CXT_SPDIF_CTRL_SWITCH(xname, nid, mask) \
-	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
-	  .info = cxt_spdif_ctrl_info, \
-	  .get = cxt_spdif_ctrl_get, \
-	  .put = cxt_spdif_ctrl_put, \
-	  .private_value = nid | (mask<<16) }
-#endif
 #endif /* CONFIG_SND_DEBUG */
 
 /* Conexant 5045 specific */
@@ -599,6 +503,7 @@ static int cxt5045_hp_master_sw_put(struct snd_kcontrol *kcontrol,
 	bits = (!spec->hp_present && spec->cur_eapd) ? 0 : 0x80;
 	snd_hda_codec_amp_update(codec, 0x10, 0, HDA_OUTPUT, 0, 0x80, bits);
 	snd_hda_codec_amp_update(codec, 0x10, 1, HDA_OUTPUT, 0, 0x80, bits);
+
 	bits = spec->cur_eapd ? 0 : 0x80;
 	snd_hda_codec_amp_update(codec, 0x11, 0, HDA_OUTPUT, 0, 0x80, bits);
 	snd_hda_codec_amp_update(codec, 0x11, 1, HDA_OUTPUT, 0, 0x80, bits);
@@ -624,6 +529,29 @@ static int cxt5045_hp_master_vol_put(struct snd_kcontrol *kcontrol,
 	return change;
 }
 
+/* toggle input of built-in and mic jack appropriately */
+static void cxt5045_hp_automic(struct hda_codec *codec)
+{
+	static struct hda_verb mic_jack_on[] = {
+		{0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+		{0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+		{}
+	};
+	static struct hda_verb mic_jack_off[] = {
+		{0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+		{0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+		{}
+	};
+	unsigned int present;
+
+	present = snd_hda_codec_read(codec, 0x12, 0,
+				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+	if (present)
+		snd_hda_sequence_write(codec, mic_jack_on);
+	else
+		snd_hda_sequence_write(codec, mic_jack_off);
+}
+
 
 /* mute internal speaker if HP is plugged */
 static void cxt5045_hp_automute(struct hda_codec *codec)
@@ -634,7 +562,7 @@ static void cxt5045_hp_automute(struct hda_codec *codec)
 	spec->hp_present = snd_hda_codec_read(codec, 0x11, 0,
 				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
 
-	bits = (spec->hp_present || !spec->cur_eapd) ? 0x80 : 0;
+	bits = (spec->hp_present || !spec->cur_eapd) ? 0x80 : 0; 
 	snd_hda_codec_amp_update(codec, 0x10, 0, HDA_OUTPUT, 0, 0x80, bits);
 	snd_hda_codec_amp_update(codec, 0x10, 1, HDA_OUTPUT, 0, 0x80, bits);
 }
@@ -648,6 +576,10 @@ static void cxt5045_hp_unsol_event(struct hda_codec *codec,
 	case CONEXANT_HP_EVENT:
 		cxt5045_hp_automute(codec);
 		break;
+	case CONEXANT_MIC_EVENT:
+		cxt5045_hp_automic(codec);
+		break;
+
 	}
 }
 
@@ -659,12 +591,10 @@ static struct snd_kcontrol_new cxt5045_mixers[] = {
 		.get = conexant_mux_enum_get,
 		.put = conexant_mux_enum_put
 	},
-	HDA_CODEC_VOLUME("Int Mic Volume", 0x17, 0x01, HDA_INPUT),
-	HDA_CODEC_MUTE("Int Mic Switch", 0x17, 0x01, HDA_INPUT),
-	HDA_CODEC_VOLUME("Ext Mic Volume", 0x17, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Ext Mic Switch", 0x17, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Capture Volume", 0x1a, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x1a, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Int Mic Volume", 0x1a, 0x01, HDA_INPUT),
+	HDA_CODEC_MUTE("Int Mic Switch", 0x1a, 0x01, HDA_INPUT),
+	HDA_CODEC_VOLUME("Ext Mic Volume", 0x1a, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Ext Mic Switch", 0x1a, 0x02, HDA_INPUT),
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "Master Playback Volume",
@@ -688,7 +618,7 @@ static struct snd_kcontrol_new cxt5045_mixers[] = {
 static struct hda_verb cxt5045_init_verbs[] = {
 	/* Line in, Mic */
 	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 },
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 },
 	/* HP, Amp  */
 	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
 	{0x17, AC_VERB_SET_CONNECT_SEL,0x01},
@@ -701,18 +631,29 @@ static struct hda_verb cxt5045_init_verbs[] = {
 	{0x17, AC_VERB_SET_AMP_GAIN_MUTE,
 	 AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x04},
 	/* Record selector: Int mic */
-	{0x1a, AC_VERB_SET_CONNECT_SEL,0x0},
+	{0x1a, AC_VERB_SET_CONNECT_SEL,0x1},
 	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE,
 	 AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17},
 	/* SPDIF route: PCM */
 	{ 0x13, AC_VERB_SET_CONNECT_SEL, 0x0 },
-	/* pin sensing on HP and Mic jacks */
-	{0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
 	/* EAPD */
 	{0x10, AC_VERB_SET_EAPD_BTLENABLE, 0x2 }, /* default on */ 
 	{ } /* end */
 };
 
+
+static struct hda_verb cxt5045_hp_sense_init_verbs[] = {
+	/* pin sensing on HP jack */
+	{0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
+	{ } /* end */
+};
+
+static struct hda_verb cxt5045_mic_sense_init_verbs[] = {
+	/* pin sensing on HP jack */
+	{0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
+	{ } /* end */
+};
+
 #ifdef CONFIG_SND_DEBUG
 /* Test configuration for debugging, modelled after the ALC260 test
  * configuration.
@@ -733,6 +674,10 @@ static struct snd_kcontrol_new cxt5045_test_mixer[] = {
 	/* Output controls */
 	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x10, 0x0, HDA_OUTPUT),
 	HDA_CODEC_MUTE("Speaker Playback Switch", 0x10, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Node 11 Playback Volume", 0x11, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Node 11 Playback Switch", 0x11, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Node 12 Playback Volume", 0x12, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Node 12 Playback Switch", 0x12, 0x0, HDA_OUTPUT),
 	
 	/* Modes for retasking pin widgets */
 	CXT_PIN_MODE("HP-OUT pin mode", 0x11, CXT_PIN_DIR_INOUT),
@@ -742,25 +687,17 @@ static struct snd_kcontrol_new cxt5045_test_mixer[] = {
 	CXT_EAPD_SWITCH("External Amplifier", 0x10, 0x0),
 
 	/* Loopback mixer controls */
-	HDA_CODEC_VOLUME("MIC1 Playback Volume", 0x17, 0x01, HDA_INPUT),
-	HDA_CODEC_MUTE("MIC1 Playback Switch", 0x17, 0x01, HDA_INPUT),
-	HDA_CODEC_VOLUME("LINE loopback Playback Volume", 0x17, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("LINE loopback Playback Switch", 0x17, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("HP-OUT loopback Playback Volume", 0x17, 0x03, HDA_INPUT),
-	HDA_CODEC_MUTE("HP-OUT loopback Playback Switch", 0x17, 0x03, HDA_INPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x17, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x17, 0x04, HDA_INPUT),
-
-	HDA_CODEC_VOLUME("Capture-1 Volume", 0x17, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture-1 Switch", 0x17, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Capture-2 Volume", 0x17, 0x1, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture-2 Switch", 0x17, 0x1, HDA_INPUT),
-	HDA_CODEC_VOLUME("Capture-3 Volume", 0x17, 0x2, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture-3 Switch", 0x17, 0x2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Capture-4 Volume", 0x17, 0x3, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture-4 Switch", 0x17, 0x3, HDA_INPUT),
-	HDA_CODEC_VOLUME("Capture-5 Volume", 0x17, 0x4, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture-5 Switch", 0x17, 0x4, HDA_INPUT),
+
+	HDA_CODEC_VOLUME("Mixer-1 Volume", 0x17, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mixer-1 Switch", 0x17, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mixer-2 Volume", 0x17, 0x1, HDA_INPUT),
+	HDA_CODEC_MUTE("Mixer-2 Switch", 0x17, 0x1, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mixer-3 Volume", 0x17, 0x2, HDA_INPUT),
+	HDA_CODEC_MUTE("Mixer-3 Switch", 0x17, 0x2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mixer-4 Volume", 0x17, 0x3, HDA_INPUT),
+	HDA_CODEC_MUTE("Mixer-4 Switch", 0x17, 0x3, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mixer-5 Volume", 0x17, 0x4, HDA_INPUT),
+	HDA_CODEC_MUTE("Mixer-5 Switch", 0x17, 0x4, HDA_INPUT),
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "Input Source",
@@ -768,14 +705,17 @@ static struct snd_kcontrol_new cxt5045_test_mixer[] = {
 		.get = conexant_mux_enum_get,
 		.put = conexant_mux_enum_put,
 	},
-
 	{ } /* end */
 };
 
 static struct hda_verb cxt5045_test_init_verbs[] = {
+	/* Set connections */
+	{ 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 },
+	{ 0x11, AC_VERB_SET_CONNECT_SEL, 0x0 },
+	{ 0x12, AC_VERB_SET_CONNECT_SEL, 0x0 },
 	/* Enable retasking pins as output, initially without power amp */
 	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
 
 	/* Disable digital (SPDIF) pins initially, but users can enable
 	 * them via a mixer switch.  In the case of SPDIF-out, this initverb
@@ -804,6 +744,7 @@ static struct hda_verb cxt5045_test_init_verbs[] = {
 	 * pin)
 	 */
 	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x17, AC_VERB_SET_CONNECT_SEL, 0x00},
 
 	/* Mute all inputs to mixer widget (even unconnected ones) */
 	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* Mixer pin */
@@ -827,7 +768,8 @@ static int cxt5045_init(struct hda_codec *codec)
 
 
 enum {
-	CXT5045_LAPTOP,	/* Laptops w/ EAPD support */
+	CXT5045_LAPTOP,	 /* Laptops w/ EAPD support */
+	CXT5045_FUJITSU, /* Laptops w/ EAPD support */ 
 #ifdef CONFIG_SND_DEBUG
 	CXT5045_TEST,
 #endif
@@ -836,6 +778,7 @@ enum {
 
 static const char *cxt5045_models[CXT5045_MODELS] = {
 	[CXT5045_LAPTOP]	= "laptop",
+	[CXT5045_FUJITSU]	= "fujitsu",
 #ifdef CONFIG_SND_DEBUG
 	[CXT5045_TEST]		= "test",
 #endif
@@ -844,7 +787,11 @@ static const char *cxt5045_models[CXT5045_MODELS] = {
 static struct snd_pci_quirk cxt5045_cfg_tbl[] = {
 	SND_PCI_QUIRK(0x103c, 0x30b7, "HP DV6000Z", CXT5045_LAPTOP),
 	SND_PCI_QUIRK(0x103c, 0x30bb, "HP DV8000", CXT5045_LAPTOP),
-	SND_PCI_QUIRK(0x1734, 0x10ad, "Fujitsu Si1520", CXT5045_LAPTOP),
+	SND_PCI_QUIRK(0x103c, 0x30b2, "HP DV Series", CXT5045_LAPTOP),
+	SND_PCI_QUIRK(0x103c, 0x30b5, "HP DV2120", CXT5045_LAPTOP),
+	SND_PCI_QUIRK(0x103c, 0x30cd, "HP DV Series", CXT5045_LAPTOP),
+	SND_PCI_QUIRK(0x1734, 0x10ad, "Fujitsu Si1520", CXT5045_FUJITSU),
+	SND_PCI_QUIRK(0x8086, 0x2111, "Conexant Reference board", CXT5045_LAPTOP),
 	{}
 };
 
@@ -877,16 +824,23 @@ static int patch_cxt5045(struct hda_codec *codec)
 
 
 	codec->patch_ops = conexant_patch_ops;
-	codec->patch_ops.unsol_event = cxt5045_hp_unsol_event;
 
 	board_config = snd_hda_check_board_config(codec, CXT5045_MODELS,
 						  cxt5045_models,
 						  cxt5045_cfg_tbl);
 	switch (board_config) {
 	case CXT5045_LAPTOP:
+		codec->patch_ops.unsol_event = cxt5045_hp_unsol_event;
+		spec->input_mux = &cxt5045_capture_source;
+		spec->num_init_verbs = 2;
+		spec->init_verbs[1] = cxt5045_hp_sense_init_verbs;
+		spec->mixers[0] = cxt5045_mixers;
+		codec->patch_ops.init = cxt5045_init;
+		break;
+	case CXT5045_FUJITSU:
 		spec->input_mux = &cxt5045_capture_source;
 		spec->num_init_verbs = 2;
-		spec->init_verbs[1] = cxt5045_init_verbs;
+		spec->init_verbs[1] = cxt5045_mic_sense_init_verbs;
 		spec->mixers[0] = cxt5045_mixers;
 		codec->patch_ops.init = cxt5045_init;
 		break;
@@ -913,10 +867,9 @@ static struct hda_channel_mode cxt5047_modes[1] = {
 };
 
 static struct hda_input_mux cxt5047_capture_source = {
-	.num_items = 2,
+	.num_items = 1,
 	.items = {
-		{ "ExtMic", 0x0 },
-		{ "IntMic", 0x1 },
+		{ "Mic", 0x2 },
 	}
 };
 
@@ -1009,7 +962,7 @@ static void cxt5047_hp_automic(struct hda_codec *codec)
 	};
 	unsigned int present;
 
-	present = snd_hda_codec_read(codec, 0x08, 0,
+	present = snd_hda_codec_read(codec, 0x15, 0,
 				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
 	if (present)
 		snd_hda_sequence_write(codec, mic_jack_on);
@@ -1033,37 +986,20 @@ static void cxt5047_hp_unsol_event(struct hda_codec *codec,
 }
 
 static struct snd_kcontrol_new cxt5047_mixers[] = {
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Capture Source",
-		.info = conexant_mux_enum_info,
-		.get = conexant_mux_enum_get,
-		.put = conexant_mux_enum_put
-	},
 	HDA_CODEC_VOLUME("Mic Bypass Capture Volume", 0x19, 0x02, HDA_INPUT),
 	HDA_CODEC_MUTE("Mic Bypass Capture Switch", 0x19, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Gain Volume", 0x1a, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Mic Gain Switch", 0x1a, 0x0, HDA_OUTPUT),
 	HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x03, HDA_INPUT),
 	HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT),
 	HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT),
 	HDA_CODEC_MUTE("PCM Switch", 0x10, 0x00, HDA_OUTPUT),
 	HDA_CODEC_VOLUME("PCM-2 Volume", 0x1c, 0x00, HDA_OUTPUT),
 	HDA_CODEC_MUTE("PCM-2 Switch", 0x1c, 0x00, HDA_OUTPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Master Playback Volume",
-		.info = snd_hda_mixer_amp_volume_info,
-		.get = snd_hda_mixer_amp_volume_get,
-		.put = cxt5047_hp_master_vol_put,
-		.private_value = HDA_COMPOSE_AMP_VAL(0x13, 3, 0, HDA_OUTPUT),
-	},
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Master Playback Switch",
-		.info = cxt_eapd_info,
-		.get = cxt_eapd_get,
-		.put = cxt5047_hp_master_sw_put,
-		.private_value = 0x13,
-	},
+	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x1d, 0x00, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Speaker Playback Switch", 0x1d, 0x00, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x13, 0x00, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x13, 0x00, HDA_OUTPUT),
 
 	{}
 };
@@ -1133,18 +1069,19 @@ static struct hda_verb cxt5047_init_verbs[] = {
 	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
 	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 },
 	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 },
-	/* HP, Amp, Speaker  */
-	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	{0x1A, AC_VERB_SET_CONNECT_SEL,0x00},
-	{0x1A, AC_VERB_SET_AMP_GAIN_MUTE,
-	 AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x00},
-	{0x1A, AC_VERB_SET_AMP_GAIN_MUTE,
-	 AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x03},
+	/* HP, Speaker  */
+	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
+	{0x13, AC_VERB_SET_CONNECT_SEL,0x1},
 	{0x1d, AC_VERB_SET_CONNECT_SEL,0x0},
-	/* Record selector: Front mic */
+	/* Record selector: Mic */
 	{0x12, AC_VERB_SET_CONNECT_SEL,0x03},
 	{0x19, AC_VERB_SET_AMP_GAIN_MUTE,
 	 AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17},
+	{0x1A, AC_VERB_SET_CONNECT_SEL,0x02},
+	{0x1A, AC_VERB_SET_AMP_GAIN_MUTE,
+	 AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x00},
+	{0x1A, AC_VERB_SET_AMP_GAIN_MUTE,
+	 AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x03},
 	/* SPDIF route: PCM */
 	{ 0x18, AC_VERB_SET_CONNECT_SEL, 0x0 },
 	/* Enable unsolicited events */
@@ -1161,8 +1098,6 @@ static struct hda_verb cxt5047_toshiba_init_verbs[] = {
 	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
 	/* Speaker routing */
 	{0x1d, AC_VERB_SET_CONNECT_SEL,0x1},
-	/* Change default to ExtMic for recording */
-	{0x1a, AC_VERB_SET_CONNECT_SEL,0x2},
 	{}
 };
 
@@ -1172,7 +1107,6 @@ static struct hda_verb cxt5047_hp_init_verbs[] = {
 	{0x13, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
 	/* Record selector: Ext Mic */
 	{0x12, AC_VERB_SET_CONNECT_SEL,0x03},
-	{0x1a, AC_VERB_SET_CONNECT_SEL,0x02},
 	{0x19, AC_VERB_SET_AMP_GAIN_MUTE,
 	 AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17},
 	/* Speaker routing */
@@ -1242,14 +1176,6 @@ static struct snd_kcontrol_new cxt5047_test_mixer[] = {
 		.get = conexant_mux_enum_get,
 		.put = conexant_mux_enum_put,
 	},
-       /* Controls for GPIO pins, assuming they exist and are configured
-	* as outputs
-	*/
-	CXT_GPIO_DATA_SWITCH("GPIO pin 0", 0x01, 0x01),
-	CXT_GPIO_DATA_SWITCH("GPIO pin 1", 0x01, 0x02),
-	CXT_GPIO_DATA_SWITCH("GPIO pin 2", 0x01, 0x04),
-	CXT_GPIO_DATA_SWITCH("GPIO pin 3", 0x01, 0x08),
-
 	{ } /* end */
 };
 
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index fba3cb11bc2a..a4ede27af021 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -74,6 +74,8 @@ enum {
 	ALC260_HP_3013,
 	ALC260_FUJITSU_S702X,
 	ALC260_ACER,
+	ALC260_WILL,
+	ALC260_REPLACER_672V,
 #ifdef CONFIG_SND_DEBUG
 	ALC260_TEST,
 #endif
@@ -115,15 +117,28 @@ enum {
 	ALC861VD_3ST,
 	ALC861VD_3ST_DIG,
 	ALC861VD_6ST_DIG,
+	ALC861VD_LENOVO,
 	ALC861VD_AUTO,
 	ALC861VD_MODEL_LAST,
 };
 
+/* ALC662 models */
+enum {
+	ALC662_3ST_2ch_DIG,
+	ALC662_3ST_6ch_DIG,
+	ALC662_3ST_6ch,
+	ALC662_5ST_DIG,
+	ALC662_LENOVO_101E,
+	ALC662_AUTO,
+	ALC662_MODEL_LAST,
+};
+
 /* ALC882 models */
 enum {
 	ALC882_3ST_DIG,
 	ALC882_6ST_DIG,
 	ALC882_ARIMA,
+	ALC882_W2JC,
 	ALC882_AUTO,
 	ALC885_MACPRO,
 	ALC882_MODEL_LAST,
@@ -141,6 +156,7 @@ enum {
 	ALC883_ACER,
 	ALC883_MEDION,
 	ALC883_LAPTOP_EAPD,
+	ALC883_LENOVO_101E_2ch,
 	ALC883_AUTO,
 	ALC883_MODEL_LAST,
 };
@@ -163,7 +179,7 @@ struct alc_spec {
 	struct hda_pcm_stream *stream_analog_playback;
 	struct hda_pcm_stream *stream_analog_capture;
 
-	char *stream_name_digital;	/* digital PCM stream */ 
+	char *stream_name_digital;	/* digital PCM stream */
 	struct hda_pcm_stream *stream_digital_playback;
 	struct hda_pcm_stream *stream_digital_capture;
 
@@ -401,7 +417,7 @@ static int alc_pin_mode_put(struct snd_kcontrol *kcontrol,
 						 AC_VERB_GET_PIN_WIDGET_CONTROL,
 						 0x00);
 
-	if (val < alc_pin_mode_min(dir) || val > alc_pin_mode_max(dir)) 
+	if (val < alc_pin_mode_min(dir) || val > alc_pin_mode_max(dir))
 		val = alc_pin_mode_min(dir);
 
 	change = pinctl != alc_pin_mode_values[val];
@@ -460,7 +476,8 @@ static int alc_gpio_data_info(struct snd_kcontrol *kcontrol,
 	uinfo->value.integer.min = 0;
 	uinfo->value.integer.max = 1;
 	return 0;
-}                                
+}
+
 static int alc_gpio_data_get(struct snd_kcontrol *kcontrol,
 			     struct snd_ctl_elem_value *ucontrol)
 {
@@ -520,7 +537,8 @@ static int alc_spdif_ctrl_info(struct snd_kcontrol *kcontrol,
 	uinfo->value.integer.min = 0;
 	uinfo->value.integer.max = 1;
 	return 0;
-}                                
+}
+
 static int alc_spdif_ctrl_get(struct snd_kcontrol *kcontrol,
 			      struct snd_ctl_elem_value *ucontrol)
 {
@@ -592,7 +610,7 @@ static void setup_preset(struct alc_spec *spec,
 	spec->multiout.hp_nid = preset->hp_nid;
 	
 	spec->num_mux_defs = preset->num_mux_defs;
-	if (! spec->num_mux_defs)
+	if (!spec->num_mux_defs)
 		spec->num_mux_defs = 1;
 	spec->input_mux = preset->input_mux;
 
@@ -604,6 +622,90 @@ static void setup_preset(struct alc_spec *spec,
 	spec->init_hook = preset->init_hook;
 }
 
+/* Enable GPIO mask and set output */
+static struct hda_verb alc_gpio1_init_verbs[] = {
+	{0x01, AC_VERB_SET_GPIO_MASK, 0x01},
+	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
+	{0x01, AC_VERB_SET_GPIO_DATA, 0x01},
+	{ }
+};
+
+static struct hda_verb alc_gpio2_init_verbs[] = {
+	{0x01, AC_VERB_SET_GPIO_MASK, 0x02},
+	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
+	{0x01, AC_VERB_SET_GPIO_DATA, 0x02},
+	{ }
+};
+
+static struct hda_verb alc_gpio3_init_verbs[] = {
+	{0x01, AC_VERB_SET_GPIO_MASK, 0x03},
+	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03},
+	{0x01, AC_VERB_SET_GPIO_DATA, 0x03},
+	{ }
+};
+
+/* 32-bit subsystem ID for BIOS loading in HD Audio codec.
+ *	31 ~ 16 :	Manufacture ID
+ *	15 ~ 8	:	SKU ID
+ *	7  ~ 0	:	Assembly ID
+ *	port-A --> pin 39/41, port-E --> pin 14/15, port-D --> pin 35/36
+ */
+static void alc_subsystem_id(struct hda_codec *codec,
+			     unsigned int porta, unsigned int porte,
+			     unsigned int portd)
+{
+	unsigned int ass, tmp;
+
+	ass = codec->subsystem_id;
+	if (!(ass & 1))
+		return;
+
+	/* Override */
+	tmp = (ass & 0x38) >> 3;	/* external Amp control */
+	switch (tmp) {
+	case 1:
+		snd_hda_sequence_write(codec, alc_gpio1_init_verbs);
+		break;
+	case 3:
+		snd_hda_sequence_write(codec, alc_gpio2_init_verbs);
+		break;
+	case 7:
+		snd_hda_sequence_write(codec, alc_gpio3_init_verbs);
+		break;
+	case 5:
+		switch (codec->vendor_id) {
+		case 0x10ec0862:
+		case 0x10ec0660:
+		case 0x10ec0662:	
+		case 0x10ec0267:
+		case 0x10ec0268:
+			snd_hda_codec_write(codec, 0x14, 0,
+					    AC_VERB_SET_EAPD_BTLENABLE, 2);
+			snd_hda_codec_write(codec, 0x15, 0,
+					    AC_VERB_SET_EAPD_BTLENABLE, 2);
+			return;
+		}
+	case 6:
+		if (ass & 4) {	/* bit 2 : 0 = Desktop, 1 = Laptop */
+			hda_nid_t port = 0;
+			tmp = (ass & 0x1800) >> 11;
+			switch (tmp) {
+			case 0: port = porta; break;
+			case 1: port = porte; break;
+			case 2: port = portd; break;
+			}
+			if (port)
+				snd_hda_codec_write(codec, port, 0,
+						    AC_VERB_SET_EAPD_BTLENABLE,
+						    2);
+		}
+		snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
+		snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PROC_COEF,
+				    (tmp == 5 ? 0x3040 : 0x3050));
+		break;
+	}
+}
+
 /*
  * ALC880 3-stack model
  *
@@ -801,7 +903,7 @@ static struct hda_channel_mode alc880_fivestack_modes[2] = {
 static hda_nid_t alc880_6st_dac_nids[4] = {
 	/* front, rear, clfe, rear_surr */
 	0x02, 0x03, 0x04, 0x05
-};	
+};
 
 static struct hda_input_mux alc880_6stack_capture_source = {
 	.num_items = 4,
@@ -1409,25 +1511,43 @@ static struct hda_verb alc880_beep_init_verbs[] = {
 };
 
 /* toggle speaker-output according to the hp-jack state */
-static void alc880_uniwill_automute(struct hda_codec *codec)
+static void alc880_uniwill_hp_automute(struct hda_codec *codec)
 {
  	unsigned int present;
+	unsigned char bits;
 
  	present = snd_hda_codec_read(codec, 0x14, 0,
 				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+	bits = present ? 0x80 : 0;
 	snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0,
-				 0x80, present ? 0x80 : 0);
+				 0x80, bits);
 	snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0,
-				 0x80, present ? 0x80 : 0);
+				 0x80, bits);
 	snd_hda_codec_amp_update(codec, 0x16, 0, HDA_OUTPUT, 0,
-				 0x80, present ? 0x80 : 0);
+				 0x80, bits);
 	snd_hda_codec_amp_update(codec, 0x16, 1, HDA_OUTPUT, 0,
-				 0x80, present ? 0x80 : 0);
+				 0x80, bits);
+}
+
+/* auto-toggle front mic */
+static void alc880_uniwill_mic_automute(struct hda_codec *codec)
+{
+ 	unsigned int present;
+	unsigned char bits;
 
 	present = snd_hda_codec_read(codec, 0x18, 0,
 				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
-	snd_hda_codec_write(codec, 0x0b, 0, AC_VERB_SET_AMP_GAIN_MUTE,
-			    0x7000 | (0x01 << 8) | (present ? 0x80 : 0));
+	bits = present ? 0x80 : 0;
+	snd_hda_codec_amp_update(codec, 0x0b, 0, HDA_INPUT, 1,
+				 0x80, bits);
+	snd_hda_codec_amp_update(codec, 0x0b, 1, HDA_INPUT, 1,
+				 0x80, bits);
+}
+
+static void alc880_uniwill_automute(struct hda_codec *codec)
+{
+	alc880_uniwill_hp_automute(codec);
+	alc880_uniwill_mic_automute(codec);
 }
 
 static void alc880_uniwill_unsol_event(struct hda_codec *codec,
@@ -1436,22 +1556,28 @@ static void alc880_uniwill_unsol_event(struct hda_codec *codec,
 	/* Looks like the unsol event is incompatible with the standard
 	 * definition.  4bit tag is placed at 28 bit!
 	 */
-	if ((res >> 28) == ALC880_HP_EVENT ||
-	    (res >> 28) == ALC880_MIC_EVENT)
-		alc880_uniwill_automute(codec);
+	switch (res >> 28) {
+	case ALC880_HP_EVENT:
+		alc880_uniwill_hp_automute(codec);
+		break;
+	case ALC880_MIC_EVENT:
+		alc880_uniwill_mic_automute(codec);
+		break;
+	}
 }
 
 static void alc880_uniwill_p53_hp_automute(struct hda_codec *codec)
 {
  	unsigned int present;
+	unsigned char bits;
 
  	present = snd_hda_codec_read(codec, 0x14, 0,
 				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
-
+	bits = present ? 0x80 : 0;
 	snd_hda_codec_amp_update(codec, 0x15, 0, HDA_INPUT, 0,
-				 0x80, present ? 0x80 : 0);
+				 0x80, bits);
 	snd_hda_codec_amp_update(codec, 0x15, 1, HDA_INPUT, 0,
-				 0x80, present ? 0x80 : 0);
+				 0x80, bits);
 }
 
 static void alc880_uniwill_p53_dcvol_automute(struct hda_codec *codec)
@@ -1480,7 +1606,7 @@ static void alc880_uniwill_p53_unsol_event(struct hda_codec *codec,
 	 */
 	if ((res >> 28) == ALC880_HP_EVENT)
 		alc880_uniwill_p53_hp_automute(codec);
-	if ((res >> 28) == ALC880_DCVOL_EVENT) 
+	if ((res >> 28) == ALC880_DCVOL_EVENT)
 		alc880_uniwill_p53_dcvol_automute(codec);
 }
 
@@ -1547,22 +1673,8 @@ static struct hda_verb alc880_pin_asus_init_verbs[] = {
 };
 
 /* Enable GPIO mask and set output */
-static struct hda_verb alc880_gpio1_init_verbs[] = {
-	{0x01, AC_VERB_SET_GPIO_MASK, 0x01},
-	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
-	{0x01, AC_VERB_SET_GPIO_DATA, 0x01},
-
-	{ }
-};
-
-/* Enable GPIO mask and set output */
-static struct hda_verb alc880_gpio2_init_verbs[] = {
-	{0x01, AC_VERB_SET_GPIO_MASK, 0x02},
-	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
-	{0x01, AC_VERB_SET_GPIO_DATA, 0x02},
-
-	{ }
-};
+#define alc880_gpio1_init_verbs	alc_gpio1_init_verbs
+#define alc880_gpio2_init_verbs	alc_gpio2_init_verbs
 
 /* Clevo m520g init */
 static struct hda_verb alc880_pin_clevo_init_verbs[] = {
@@ -1734,13 +1846,15 @@ static struct hda_verb alc880_lg_init_verbs[] = {
 static void alc880_lg_automute(struct hda_codec *codec)
 {
 	unsigned int present;
+	unsigned char bits;
 
 	present = snd_hda_codec_read(codec, 0x1b, 0,
 				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+	bits = present ? 0x80 : 0;
 	snd_hda_codec_amp_update(codec, 0x17, 0, HDA_OUTPUT, 0,
-				 0x80, present ? 0x80 : 0);
+				 0x80, bits);
 	snd_hda_codec_amp_update(codec, 0x17, 1, HDA_OUTPUT, 0,
-				 0x80, present ? 0x80 : 0);
+				 0x80, bits);
 }
 
 static void alc880_lg_unsol_event(struct hda_codec *codec, unsigned int res)
@@ -1810,13 +1924,15 @@ static struct hda_verb alc880_lg_lw_init_verbs[] = {
 static void alc880_lg_lw_automute(struct hda_codec *codec)
 {
 	unsigned int present;
+	unsigned char bits;
 
 	present = snd_hda_codec_read(codec, 0x1b, 0,
 				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+	bits = present ? 0x80 : 0;
 	snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
-				 0x80, present ? 0x80 : 0);
+				 0x80, bits);
 	snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
-				 0x80, present ? 0x80 : 0);
+				 0x80, bits);
 }
 
 static void alc880_lg_lw_unsol_event(struct hda_codec *codec, unsigned int res)
@@ -1916,6 +2032,17 @@ static int alc880_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
 	return snd_hda_multi_out_dig_open(codec, &spec->multiout);
 }
 
+static int alc880_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
+					   struct hda_codec *codec,
+					   unsigned int stream_tag,
+					   unsigned int format,
+					   struct snd_pcm_substream *substream)
+{
+	struct alc_spec *spec = codec->spec;
+	return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
+					     stream_tag, format, substream);
+}
+
 static int alc880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
 					 struct hda_codec *codec,
 					 struct snd_pcm_substream *substream)
@@ -1984,7 +2111,8 @@ static struct hda_pcm_stream alc880_pcm_digital_playback = {
 	/* NID is set in alc_build_pcms */
 	.ops = {
 		.open = alc880_dig_playback_pcm_open,
-		.close = alc880_dig_playback_pcm_close
+		.close = alc880_dig_playback_pcm_close,
+		.prepare = alc880_dig_playback_pcm_prepare
 	},
 };
 
@@ -2075,7 +2203,7 @@ static void alc_free(struct hda_codec *codec)
 	struct alc_spec *spec = codec->spec;
 	unsigned int i;
 
-	if (! spec)
+	if (!spec)
 		return;
 
 	if (spec->kctl_alloc) {
@@ -2477,7 +2605,8 @@ static struct snd_pci_quirk alc880_cfg_tbl[] = {
 static struct alc_config_preset alc880_presets[] = {
 	[ALC880_3ST] = {
 		.mixers = { alc880_three_stack_mixer },
-		.init_verbs = { alc880_volume_init_verbs, alc880_pin_3stack_init_verbs },
+		.init_verbs = { alc880_volume_init_verbs,
+				alc880_pin_3stack_init_verbs },
 		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
 		.dac_nids = alc880_dac_nids,
 		.num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
@@ -2487,7 +2616,8 @@ static struct alc_config_preset alc880_presets[] = {
 	},
 	[ALC880_3ST_DIG] = {
 		.mixers = { alc880_three_stack_mixer },
-		.init_verbs = { alc880_volume_init_verbs, alc880_pin_3stack_init_verbs },
+		.init_verbs = { alc880_volume_init_verbs,
+				alc880_pin_3stack_init_verbs },
 		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
 		.dac_nids = alc880_dac_nids,
 		.dig_out_nid = ALC880_DIGOUT_NID,
@@ -2509,8 +2639,10 @@ static struct alc_config_preset alc880_presets[] = {
 		.input_mux = &alc880_capture_source,
 	},
 	[ALC880_5ST] = {
-		.mixers = { alc880_three_stack_mixer, alc880_five_stack_mixer},
-		.init_verbs = { alc880_volume_init_verbs, alc880_pin_5stack_init_verbs },
+		.mixers = { alc880_three_stack_mixer,
+			    alc880_five_stack_mixer},
+		.init_verbs = { alc880_volume_init_verbs,
+				alc880_pin_5stack_init_verbs },
 		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
 		.dac_nids = alc880_dac_nids,
 		.num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes),
@@ -2518,8 +2650,10 @@ static struct alc_config_preset alc880_presets[] = {
 		.input_mux = &alc880_capture_source,
 	},
 	[ALC880_5ST_DIG] = {
-		.mixers = { alc880_three_stack_mixer, alc880_five_stack_mixer },
-		.init_verbs = { alc880_volume_init_verbs, alc880_pin_5stack_init_verbs },
+		.mixers = { alc880_three_stack_mixer,
+			    alc880_five_stack_mixer },
+		.init_verbs = { alc880_volume_init_verbs,
+				alc880_pin_5stack_init_verbs },
 		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
 		.dac_nids = alc880_dac_nids,
 		.dig_out_nid = ALC880_DIGOUT_NID,
@@ -2529,7 +2663,8 @@ static struct alc_config_preset alc880_presets[] = {
 	},
 	[ALC880_6ST] = {
 		.mixers = { alc880_six_stack_mixer },
-		.init_verbs = { alc880_volume_init_verbs, alc880_pin_6stack_init_verbs },
+		.init_verbs = { alc880_volume_init_verbs,
+				alc880_pin_6stack_init_verbs },
 		.num_dacs = ARRAY_SIZE(alc880_6st_dac_nids),
 		.dac_nids = alc880_6st_dac_nids,
 		.num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes),
@@ -2538,7 +2673,8 @@ static struct alc_config_preset alc880_presets[] = {
 	},
 	[ALC880_6ST_DIG] = {
 		.mixers = { alc880_six_stack_mixer },
-		.init_verbs = { alc880_volume_init_verbs, alc880_pin_6stack_init_verbs },
+		.init_verbs = { alc880_volume_init_verbs,
+				alc880_pin_6stack_init_verbs },
 		.num_dacs = ARRAY_SIZE(alc880_6st_dac_nids),
 		.dac_nids = alc880_6st_dac_nids,
 		.dig_out_nid = ALC880_DIGOUT_NID,
@@ -2548,7 +2684,8 @@ static struct alc_config_preset alc880_presets[] = {
 	},
 	[ALC880_W810] = {
 		.mixers = { alc880_w810_base_mixer },
-		.init_verbs = { alc880_volume_init_verbs, alc880_pin_w810_init_verbs,
+		.init_verbs = { alc880_volume_init_verbs,
+				alc880_pin_w810_init_verbs,
 				alc880_gpio2_init_verbs },
 		.num_dacs = ARRAY_SIZE(alc880_w810_dac_nids),
 		.dac_nids = alc880_w810_dac_nids,
@@ -2559,7 +2696,8 @@ static struct alc_config_preset alc880_presets[] = {
 	},
 	[ALC880_Z71V] = {
 		.mixers = { alc880_z71v_mixer },
-		.init_verbs = { alc880_volume_init_verbs, alc880_pin_z71v_init_verbs },
+		.init_verbs = { alc880_volume_init_verbs,
+				alc880_pin_z71v_init_verbs },
 		.num_dacs = ARRAY_SIZE(alc880_z71v_dac_nids),
 		.dac_nids = alc880_z71v_dac_nids,
 		.dig_out_nid = ALC880_DIGOUT_NID,
@@ -2570,7 +2708,8 @@ static struct alc_config_preset alc880_presets[] = {
 	},
 	[ALC880_F1734] = {
 		.mixers = { alc880_f1734_mixer },
-		.init_verbs = { alc880_volume_init_verbs, alc880_pin_f1734_init_verbs },
+		.init_verbs = { alc880_volume_init_verbs,
+				alc880_pin_f1734_init_verbs },
 		.num_dacs = ARRAY_SIZE(alc880_f1734_dac_nids),
 		.dac_nids = alc880_f1734_dac_nids,
 		.hp_nid = 0x02,
@@ -2580,7 +2719,8 @@ static struct alc_config_preset alc880_presets[] = {
 	},
 	[ALC880_ASUS] = {
 		.mixers = { alc880_asus_mixer },
-		.init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs,
+		.init_verbs = { alc880_volume_init_verbs,
+				alc880_pin_asus_init_verbs,
 				alc880_gpio1_init_verbs },
 		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
 		.dac_nids = alc880_asus_dac_nids,
@@ -2591,7 +2731,8 @@ static struct alc_config_preset alc880_presets[] = {
 	},
 	[ALC880_ASUS_DIG] = {
 		.mixers = { alc880_asus_mixer },
-		.init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs,
+		.init_verbs = { alc880_volume_init_verbs,
+				alc880_pin_asus_init_verbs,
 				alc880_gpio1_init_verbs },
 		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
 		.dac_nids = alc880_asus_dac_nids,
@@ -2603,7 +2744,8 @@ static struct alc_config_preset alc880_presets[] = {
 	},
 	[ALC880_ASUS_DIG2] = {
 		.mixers = { alc880_asus_mixer },
-		.init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs,
+		.init_verbs = { alc880_volume_init_verbs,
+				alc880_pin_asus_init_verbs,
 				alc880_gpio2_init_verbs }, /* use GPIO2 */
 		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
 		.dac_nids = alc880_asus_dac_nids,
@@ -2615,7 +2757,8 @@ static struct alc_config_preset alc880_presets[] = {
 	},
 	[ALC880_ASUS_W1V] = {
 		.mixers = { alc880_asus_mixer, alc880_asus_w1v_mixer },
-		.init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs,
+		.init_verbs = { alc880_volume_init_verbs,
+				alc880_pin_asus_init_verbs,
 				alc880_gpio1_init_verbs },
 		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
 		.dac_nids = alc880_asus_dac_nids,
@@ -2664,7 +2807,7 @@ static struct alc_config_preset alc880_presets[] = {
 		.init_hook = alc880_uniwill_p53_hp_automute,
 	},
 	[ALC880_FUJITSU] = {
-		.mixers = { alc880_fujitsu_mixer, 
+		.mixers = { alc880_fujitsu_mixer,
 			    alc880_pcbeep_mixer, },
 		.init_verbs = { alc880_volume_init_verbs,
 				alc880_uniwill_p53_init_verbs,
@@ -2707,7 +2850,7 @@ static struct alc_config_preset alc880_presets[] = {
 		.mixers = { alc880_lg_lw_mixer },
 		.init_verbs = { alc880_volume_init_verbs,
 				alc880_lg_lw_init_verbs },
-		.num_dacs = 1, 
+		.num_dacs = 1,
 		.dac_nids = alc880_dac_nids,
 		.dig_out_nid = ALC880_DIGOUT_NID,
 		.num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
@@ -2749,18 +2892,21 @@ static struct snd_kcontrol_new alc880_control_templates[] = {
 };
 
 /* add dynamic controls */
-static int add_control(struct alc_spec *spec, int type, const char *name, unsigned long val)
+static int add_control(struct alc_spec *spec, int type, const char *name,
+		       unsigned long val)
 {
 	struct snd_kcontrol_new *knew;
 
 	if (spec->num_kctl_used >= spec->num_kctl_alloc) {
 		int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC;
 
-		knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); /* array + terminator */
-		if (! knew)
+		/* array + terminator */
+		knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL);
+		if (!knew)
 			return -ENOMEM;
 		if (spec->kctl_alloc) {
-			memcpy(knew, spec->kctl_alloc, sizeof(*knew) * spec->num_kctl_alloc);
+			memcpy(knew, spec->kctl_alloc,
+			       sizeof(*knew) * spec->num_kctl_alloc);
 			kfree(spec->kctl_alloc);
 		}
 		spec->kctl_alloc = knew;
@@ -2770,7 +2916,7 @@ static int add_control(struct alc_spec *spec, int type, const char *name, unsign
 	knew = &spec->kctl_alloc[spec->num_kctl_used];
 	*knew = alc880_control_templates[type];
 	knew->name = kstrdup(name, GFP_KERNEL);
-	if (! knew->name)
+	if (!knew->name)
 		return -ENOMEM;
 	knew->private_value = val;
 	spec->num_kctl_used++;
@@ -2790,7 +2936,8 @@ static int add_control(struct alc_spec *spec, int type, const char *name, unsign
 #define ALC880_PIN_CD_NID		0x1c
 
 /* fill in the dac_nids table from the parsed pin configuration */
-static int alc880_auto_fill_dac_nids(struct alc_spec *spec, const struct auto_pin_cfg *cfg)
+static int alc880_auto_fill_dac_nids(struct alc_spec *spec,
+				     const struct auto_pin_cfg *cfg)
 {
 	hda_nid_t nid;
 	int assigned[4];
@@ -2815,8 +2962,9 @@ static int alc880_auto_fill_dac_nids(struct alc_spec *spec, const struct auto_pi
 			continue;
 		/* search for an empty channel */
 		for (j = 0; j < cfg->line_outs; j++) {
-			if (! assigned[j]) {
-				spec->multiout.dac_nids[i] = alc880_idx_to_dac(j);
+			if (!assigned[j]) {
+				spec->multiout.dac_nids[i] =
+					alc880_idx_to_dac(j);
 				assigned[j] = 1;
 				break;
 			}
@@ -2831,36 +2979,54 @@ static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec,
 					     const struct auto_pin_cfg *cfg)
 {
 	char name[32];
-	static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" };
+	static const char *chname[4] = {
+		"Front", "Surround", NULL /*CLFE*/, "Side"
+	};
 	hda_nid_t nid;
 	int i, err;
 
 	for (i = 0; i < cfg->line_outs; i++) {
-		if (! spec->multiout.dac_nids[i])
+		if (!spec->multiout.dac_nids[i])
 			continue;
 		nid = alc880_idx_to_mixer(alc880_dac_to_idx(spec->multiout.dac_nids[i]));
 		if (i == 2) {
 			/* Center/LFE */
-			if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Center Playback Volume",
-					       HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT))) < 0)
+			err = add_control(spec, ALC_CTL_WIDGET_VOL,
+					  "Center Playback Volume",
+					  HDA_COMPOSE_AMP_VAL(nid, 1, 0,
+							      HDA_OUTPUT));
+			if (err < 0)
 				return err;
-			if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "LFE Playback Volume",
-					       HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0)
+			err = add_control(spec, ALC_CTL_WIDGET_VOL,
+					  "LFE Playback Volume",
+					  HDA_COMPOSE_AMP_VAL(nid, 2, 0,
+							      HDA_OUTPUT));
+			if (err < 0)
 				return err;
-			if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "Center Playback Switch",
-					       HDA_COMPOSE_AMP_VAL(nid, 1, 2, HDA_INPUT))) < 0)
+			err = add_control(spec, ALC_CTL_BIND_MUTE,
+					  "Center Playback Switch",
+					  HDA_COMPOSE_AMP_VAL(nid, 1, 2,
+							      HDA_INPUT));
+			if (err < 0)
 				return err;
-			if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "LFE Playback Switch",
-					       HDA_COMPOSE_AMP_VAL(nid, 2, 2, HDA_INPUT))) < 0)
+			err = add_control(spec, ALC_CTL_BIND_MUTE,
+					  "LFE Playback Switch",
+					  HDA_COMPOSE_AMP_VAL(nid, 2, 2,
+							      HDA_INPUT));
+			if (err < 0)
 				return err;
 		} else {
 			sprintf(name, "%s Playback Volume", chname[i]);
-			if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
-					       HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
+			err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
+					  HDA_COMPOSE_AMP_VAL(nid, 3, 0,
+							      HDA_OUTPUT));
+			if (err < 0)
 				return err;
 			sprintf(name, "%s Playback Switch", chname[i]);
-			if ((err = add_control(spec, ALC_CTL_BIND_MUTE, name,
-					       HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0)
+			err = add_control(spec, ALC_CTL_BIND_MUTE, name,
+					  HDA_COMPOSE_AMP_VAL(nid, 3, 2,
+							      HDA_INPUT));
+			if (err < 0)
 				return err;
 		}
 	}
@@ -2875,51 +3041,57 @@ static int alc880_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin,
 	int err;
 	char name[32];
 
-	if (! pin)
+	if (!pin)
 		return 0;
 
 	if (alc880_is_fixed_pin(pin)) {
 		nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));
 		/* specify the DAC as the extra output */
-		if (! spec->multiout.hp_nid)
+		if (!spec->multiout.hp_nid)
 			spec->multiout.hp_nid = nid;
 		else
 			spec->multiout.extra_out_nid[0] = nid;
 		/* control HP volume/switch on the output mixer amp */
 		nid = alc880_idx_to_mixer(alc880_fixed_pin_idx(pin));
 		sprintf(name, "%s Playback Volume", pfx);
-		if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
-				       HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
+		err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
+				  HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
+		if (err < 0)
 			return err;
 		sprintf(name, "%s Playback Switch", pfx);
-		if ((err = add_control(spec, ALC_CTL_BIND_MUTE, name,
-				       HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0)
+		err = add_control(spec, ALC_CTL_BIND_MUTE, name,
+				  HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT));
+		if (err < 0)
 			return err;
 	} else if (alc880_is_multi_pin(pin)) {
 		/* set manual connection */
 		/* we have only a switch on HP-out PIN */
 		sprintf(name, "%s Playback Switch", pfx);
-		if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
-				       HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT))) < 0)
+		err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
+				  HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
+		if (err < 0)
 			return err;
 	}
 	return 0;
 }
 
 /* create input playback/capture controls for the given pin */
-static int new_analog_input(struct alc_spec *spec, hda_nid_t pin, const char *ctlname,
+static int new_analog_input(struct alc_spec *spec, hda_nid_t pin,
+			    const char *ctlname,
 			    int idx, hda_nid_t mix_nid)
 {
 	char name[32];
 	int err;
 
 	sprintf(name, "%s Playback Volume", ctlname);
-	if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
-			       HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT))) < 0)
+	err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
+			  HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
+	if (err < 0)
 		return err;
 	sprintf(name, "%s Playback Switch", ctlname);
-	if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
-			       HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT))) < 0)
+	err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
+			  HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
+	if (err < 0)
 		return err;
 	return 0;
 }
@@ -2939,8 +3111,10 @@ static int alc880_auto_create_analog_input_ctls(struct alc_spec *spec,
 					       idx, 0x0b);
 			if (err < 0)
 				return err;
-			imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
-			imux->items[imux->num_items].index = alc880_input_pin_idx(cfg->input_pins[i]);
+			imux->items[imux->num_items].label =
+				auto_pin_cfg_labels[i];
+			imux->items[imux->num_items].index =
+				alc880_input_pin_idx(cfg->input_pins[i]);
 			imux->num_items++;
 		}
 	}
@@ -2952,8 +3126,10 @@ static void alc880_auto_set_output_and_unmute(struct hda_codec *codec,
 					      int dac_idx)
 {
 	/* set as output */
-	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
-	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
+	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
+			    pin_type);
+	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+			    AMP_OUT_UNMUTE);
 	/* need the manual connection? */
 	if (alc880_is_multi_pin(nid)) {
 		struct alc_spec *spec = codec->spec;
@@ -2964,14 +3140,24 @@ static void alc880_auto_set_output_and_unmute(struct hda_codec *codec,
 	}
 }
 
+static int get_pin_type(int line_out_type)
+{
+	if (line_out_type == AUTO_PIN_HP_OUT)
+		return PIN_HP;
+	else
+		return PIN_OUT;
+}
+
 static void alc880_auto_init_multi_out(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
 	int i;
-
+	
+	alc_subsystem_id(codec, 0x15, 0x1b, 0x14);
 	for (i = 0; i < spec->autocfg.line_outs; i++) {
 		hda_nid_t nid = spec->autocfg.line_out_pins[i];
-		alc880_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
+		int pin_type = get_pin_type(spec->autocfg.line_out_type);
+		alc880_auto_set_output_and_unmute(codec, nid, pin_type, i);
 	}
 }
 
@@ -2996,37 +3182,52 @@ static void alc880_auto_init_analog_input(struct hda_codec *codec)
 	for (i = 0; i < AUTO_PIN_LAST; i++) {
 		hda_nid_t nid = spec->autocfg.input_pins[i];
 		if (alc880_is_input_pin(nid)) {
-			snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
-					    i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
+			snd_hda_codec_write(codec, nid, 0,
+					    AC_VERB_SET_PIN_WIDGET_CONTROL,
+					    i <= AUTO_PIN_FRONT_MIC ?
+					    PIN_VREF80 : PIN_IN);
 			if (nid != ALC880_PIN_CD_NID)
-				snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+				snd_hda_codec_write(codec, nid, 0,
+						    AC_VERB_SET_AMP_GAIN_MUTE,
 						    AMP_OUT_MUTE);
 		}
 	}
 }
 
 /* parse the BIOS configuration and set up the alc_spec */
-/* return 1 if successful, 0 if the proper config is not found, or a negative error code */
+/* return 1 if successful, 0 if the proper config is not found,
+ * or a negative error code
+ */
 static int alc880_parse_auto_config(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
 	int err;
 	static hda_nid_t alc880_ignore[] = { 0x1d, 0 };
 
-	if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
-						alc880_ignore)) < 0)
+	err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
+					   alc880_ignore);
+	if (err < 0)
 		return err;
-	if (! spec->autocfg.line_outs)
+	if (!spec->autocfg.line_outs)
 		return 0; /* can't find valid BIOS pin config */
 
-	if ((err = alc880_auto_fill_dac_nids(spec, &spec->autocfg)) < 0 ||
-	    (err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
-	    (err = alc880_auto_create_extra_out(spec,
-						spec->autocfg.speaker_pins[0],
-						"Speaker")) < 0 ||
-	    (err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pins[0],
-						"Headphone")) < 0 ||
-	    (err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
+	err = alc880_auto_fill_dac_nids(spec, &spec->autocfg);
+	if (err < 0)
+		return err;
+	err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg);
+	if (err < 0)
+		return err;
+	err = alc880_auto_create_extra_out(spec,
+					   spec->autocfg.speaker_pins[0],
+					   "Speaker");
+	if (err < 0)
+		return err;
+	err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pins[0],
+					   "Headphone");
+	if (err < 0)
+		return err;
+	err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg);
+	if (err < 0)
 		return err;
 
 	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
@@ -3086,7 +3287,7 @@ static int patch_alc880(struct hda_codec *codec)
 		if (err < 0) {
 			alc_free(codec);
 			return err;
-		} else if (! err) {
+		} else if (!err) {
 			printk(KERN_INFO
 			       "hda_codec: Cannot set up configuration "
 			       "from BIOS.  Using 3-stack mode...\n");
@@ -3105,14 +3306,16 @@ static int patch_alc880(struct hda_codec *codec)
 	spec->stream_digital_playback = &alc880_pcm_digital_playback;
 	spec->stream_digital_capture = &alc880_pcm_digital_capture;
 
-	if (! spec->adc_nids && spec->input_mux) {
+	if (!spec->adc_nids && spec->input_mux) {
 		/* check whether NID 0x07 is valid */
 		unsigned int wcap = get_wcaps(codec, alc880_adc_nids[0]);
-		wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */
+		/* get type */
+		wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
 		if (wcap != AC_WID_AUD_IN) {
 			spec->adc_nids = alc880_adc_nids_alt;
 			spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids_alt);
-			spec->mixers[spec->num_mixers] = alc880_capture_alt_mixer;
+			spec->mixers[spec->num_mixers] =
+				alc880_capture_alt_mixer;
 			spec->num_mixers++;
 		} else {
 			spec->adc_nids = alc880_adc_nids;
@@ -3254,7 +3457,7 @@ static struct snd_kcontrol_new alc260_base_output_mixer[] = {
 	HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
 	HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT),
 	{ } /* end */
-};	
+};
 
 static struct snd_kcontrol_new alc260_input_mixer[] = {
 	HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
@@ -3349,6 +3552,42 @@ static struct snd_kcontrol_new alc260_acer_mixer[] = {
 	{ } /* end */
 };
 
+/* Packard bell V7900  ALC260 pin usage: HP = 0x0f, Mic jack = 0x12,
+ * Line In jack = 0x14, CD audio =  0x16, pc beep = 0x17.
+ */
+static struct snd_kcontrol_new alc260_will_mixer[] = {
+	HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Master Playback Switch", 0x08, 0x2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
+	ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
+	ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Beep Playback Volume", 0x07, 0x05, HDA_INPUT),
+	HDA_CODEC_MUTE("Beep Playback Switch", 0x07, 0x05, HDA_INPUT),
+	{ } /* end */
+};
+
+/* Replacer 672V ALC260 pin usage: Mic jack = 0x12,
+ * Line In jack = 0x14, ATAPI Mic = 0x13, speaker = 0x0f.
+ */
+static struct snd_kcontrol_new alc260_replacer_672v_mixer[] = {
+	HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Master Playback Switch", 0x08, 0x2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
+	ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
+	HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x07, 0x1, HDA_INPUT),
+	HDA_CODEC_MUTE("ATATI Mic Playback Switch", 0x07, 0x1, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
+	ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
+	{ } /* end */
+};
+
 /* capture mixer elements */
 static struct snd_kcontrol_new alc260_capture_mixer[] = {
 	HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT),
@@ -3434,7 +3673,9 @@ static struct hda_verb alc260_init_verbs[] = {
 	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
 	/* unmute LINE-2 out pin */
 	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
+	/* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 &
+	 * Line In 2 = 0x03
+	 */
 	/* mute CD */
 	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
 	/* mute Line In */
@@ -3482,7 +3723,9 @@ static struct hda_verb alc260_hp_init_verbs[] = {
 	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
 	/* mute pin widget amp left and right (no gain on this amp) */
 	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
-	/* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
+	/* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 &
+	 * Line In 2 = 0x03
+	 */
 	/* unmute CD */
 	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
 	/* unmute Line In */
@@ -3530,7 +3773,9 @@ static struct hda_verb alc260_hp_3013_init_verbs[] = {
 	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
 	/* mute pin widget amp left and right (no gain on this amp) */
 	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
-	/* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
+	/* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 &
+	 * Line In 2 = 0x03
+	 */
 	/* unmute CD */
 	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
 	/* unmute Line In */
@@ -3680,7 +3925,9 @@ static struct hda_verb alc260_acer_init_verbs[] = {
 	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
 	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
 
-	/* Unmute Line-out pin widget amp left and right (no equiv mixer ctrl) */
+	/* Unmute Line-out pin widget amp left and right
+	 * (no equiv mixer ctrl)
+	 */
 	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
 	/* Unmute mono pin widget amp output (no equiv mixer ctrl) */
 	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
@@ -3719,6 +3966,55 @@ static struct hda_verb alc260_acer_init_verbs[] = {
 	{ }
 };
 
+static struct hda_verb alc260_will_verbs[] = {
+	{0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x0b, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x0f, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
+	{0x1a, AC_VERB_SET_COEF_INDEX, 0x07},
+	{0x1a, AC_VERB_SET_PROC_COEF, 0x3040},
+	{}
+};
+
+static struct hda_verb alc260_replacer_672v_verbs[] = {
+	{0x0f, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
+	{0x1a, AC_VERB_SET_COEF_INDEX, 0x07},
+	{0x1a, AC_VERB_SET_PROC_COEF, 0x3050},
+
+	{0x01, AC_VERB_SET_GPIO_MASK, 0x01},
+	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
+	{0x01, AC_VERB_SET_GPIO_DATA, 0x00},
+
+	{0x0f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
+	{}
+};
+
+/* toggle speaker-output according to the hp-jack state */
+static void alc260_replacer_672v_automute(struct hda_codec *codec)
+{
+        unsigned int present;
+
+	/* speaker --> GPIO Data 0, hp or spdif --> GPIO data 1 */
+        present = snd_hda_codec_read(codec, 0x0f, 0,
+                                     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+	if (present) {
+		snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 1);
+		snd_hda_codec_write(codec, 0x0f, 0,
+				    AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP);
+	} else {
+		snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 0);
+		snd_hda_codec_write(codec, 0x0f, 0,
+				    AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
+	}
+}
+
+static void alc260_replacer_672v_unsol_event(struct hda_codec *codec,
+                                       unsigned int res)
+{
+        if ((res >> 26) == ALC880_HP_EVENT)
+                alc260_replacer_672v_automute(codec);
+}
+
 /* Test configuration for debugging, modelled after the ALC880 test
  * configuration.
  */
@@ -3946,10 +4242,12 @@ static int alc260_add_playback_controls(struct alc_spec *spec, hda_nid_t nid,
 		return 0; /* N/A */
 	
 	snprintf(name, sizeof(name), "%s Playback Volume", pfx);
-	if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name, vol_val)) < 0)
+	err = add_control(spec, ALC_CTL_WIDGET_VOL, name, vol_val);
+	if (err < 0)
 		return err;
 	snprintf(name, sizeof(name), "%s Playback Switch", pfx);
-	if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, sw_val)) < 0)
+	err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, sw_val);
+	if (err < 0)
 		return err;
 	return 1;
 }
@@ -3985,7 +4283,7 @@ static int alc260_auto_create_multi_out_ctls(struct alc_spec *spec,
 		if (err < 0)
 			return err;
 	}
-	return 0;	
+	return 0;
 }
 
 /* create playback/capture controls for input pins */
@@ -3999,20 +4297,24 @@ static int alc260_auto_create_analog_input_ctls(struct alc_spec *spec,
 		if (cfg->input_pins[i] >= 0x12) {
 			idx = cfg->input_pins[i] - 0x12;
 			err = new_analog_input(spec, cfg->input_pins[i],
-					       auto_pin_cfg_labels[i], idx, 0x07);
+					       auto_pin_cfg_labels[i], idx,
+					       0x07);
 			if (err < 0)
 				return err;
-			imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
+			imux->items[imux->num_items].label =
+				auto_pin_cfg_labels[i];
 			imux->items[imux->num_items].index = idx;
 			imux->num_items++;
 		}
-		if ((cfg->input_pins[i] >= 0x0f) && (cfg->input_pins[i] <= 0x10)){
+		if (cfg->input_pins[i] >= 0x0f && cfg->input_pins[i] <= 0x10){
 			idx = cfg->input_pins[i] - 0x09;
 			err = new_analog_input(spec, cfg->input_pins[i],
-					       auto_pin_cfg_labels[i], idx, 0x07);
+					       auto_pin_cfg_labels[i], idx,
+					       0x07);
 			if (err < 0)
 				return err;
-			imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
+			imux->items[imux->num_items].label =
+				auto_pin_cfg_labels[i];
 			imux->items[imux->num_items].index = idx;
 			imux->num_items++;
 		}
@@ -4025,14 +4327,15 @@ static void alc260_auto_set_output_and_unmute(struct hda_codec *codec,
 					      int sel_idx)
 {
 	/* set as output */
-	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
-	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
+	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
+			    pin_type);
+	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+			    AMP_OUT_UNMUTE);
 	/* need the manual connection? */
 	if (nid >= 0x12) {
 		int idx = nid - 0x12;
 		snd_hda_codec_write(codec, idx + 0x0b, 0,
 				    AC_VERB_SET_CONNECT_SEL, sel_idx);
-				    
 	}
 }
 
@@ -4041,9 +4344,12 @@ static void alc260_auto_init_multi_out(struct hda_codec *codec)
 	struct alc_spec *spec = codec->spec;
 	hda_nid_t nid;
 
-	nid = spec->autocfg.line_out_pins[0];	
-	if (nid)
-		alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0);
+	alc_subsystem_id(codec, 0x10, 0x15, 0x0f);
+	nid = spec->autocfg.line_out_pins[0];
+	if (nid) {
+		int pin_type = get_pin_type(spec->autocfg.line_out_type);
+		alc260_auto_set_output_and_unmute(codec, nid, pin_type, 0);
+	}
 	
 	nid = spec->autocfg.speaker_pins[0];
 	if (nid)
@@ -4051,8 +4357,8 @@ static void alc260_auto_init_multi_out(struct hda_codec *codec)
 
 	nid = spec->autocfg.hp_pins[0];
 	if (nid)
-		alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0);
-}	
+		alc260_auto_set_output_and_unmute(codec, nid, PIN_HP, 0);
+}
 
 #define ALC260_PIN_CD_NID		0x16
 static void alc260_auto_init_analog_input(struct hda_codec *codec)
@@ -4063,10 +4369,13 @@ static void alc260_auto_init_analog_input(struct hda_codec *codec)
 	for (i = 0; i < AUTO_PIN_LAST; i++) {
 		hda_nid_t nid = spec->autocfg.input_pins[i];
 		if (nid >= 0x12) {
-			snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
-					    i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
+			snd_hda_codec_write(codec, nid, 0,
+					    AC_VERB_SET_PIN_WIDGET_CONTROL,
+					    i <= AUTO_PIN_FRONT_MIC ?
+					    PIN_VREF80 : PIN_IN);
 			if (nid != ALC260_PIN_CD_NID)
-				snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+				snd_hda_codec_write(codec, nid, 0,
+						    AC_VERB_SET_AMP_GAIN_MUTE,
 						    AMP_OUT_MUTE);
 		}
 	}
@@ -4086,8 +4395,8 @@ static struct hda_verb alc260_volume_init_verbs[] = {
 	
 	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
 	 * mixer widget
-	 * Note: PASD motherboards uses the Line In 2 as the input for front panel
-	 * mic (mic 2)
+	 * Note: PASD motherboards uses the Line In 2 as the input for
+	 * front panel mic (mic 2)
 	 */
 	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
 	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
@@ -4122,14 +4431,17 @@ static int alc260_parse_auto_config(struct hda_codec *codec)
 	int err;
 	static hda_nid_t alc260_ignore[] = { 0x17, 0 };
 
-	if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
-						alc260_ignore)) < 0)
+	err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
+					   alc260_ignore);
+	if (err < 0)
 		return err;
-	if ((err = alc260_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0)
+	err = alc260_auto_create_multi_out_ctls(spec, &spec->autocfg);
+	if (err < 0)
 		return err;
-	if (! spec->kctl_alloc)
+	if (!spec->kctl_alloc)
 		return 0; /* can't find valid BIOS pin config */
-	if ((err = alc260_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
+	err = alc260_auto_create_analog_input_ctls(spec, &spec->autocfg);
+	if (err < 0)
 		return err;
 
 	spec->multiout.max_channels = 2;
@@ -4177,6 +4489,8 @@ static const char *alc260_models[ALC260_MODEL_LAST] = {
 	[ALC260_HP_3013]	= "hp-3013",
 	[ALC260_FUJITSU_S702X]	= "fujitsu",
 	[ALC260_ACER]		= "acer",
+	[ALC260_WILL]		= "will",
+	[ALC260_REPLACER_672V]	= "replacer",
 #ifdef CONFIG_SND_DEBUG
 	[ALC260_TEST]		= "test",
 #endif
@@ -4200,6 +4514,8 @@ static struct snd_pci_quirk alc260_cfg_tbl[] = {
 	SND_PCI_QUIRK(0x104d, 0x81cd, "Sony VAIO", ALC260_BASIC),
 	SND_PCI_QUIRK(0x10cf, 0x1326, "Fujitsu S702X", ALC260_FUJITSU_S702X),
 	SND_PCI_QUIRK(0x152d, 0x0729, "CTL U553W", ALC260_BASIC),
+	SND_PCI_QUIRK(0x1631, 0xc017, "PB V7900", ALC260_WILL),
+	SND_PCI_QUIRK(0x161f, 0x2057, "Replacer 672V", ALC260_REPLACER_672V),
 	{}
 };
 
@@ -4270,6 +4586,34 @@ static struct alc_config_preset alc260_presets[] = {
 		.num_mux_defs = ARRAY_SIZE(alc260_acer_capture_sources),
 		.input_mux = alc260_acer_capture_sources,
 	},
+	[ALC260_WILL] = {
+		.mixers = { alc260_will_mixer,
+			    alc260_capture_mixer },
+		.init_verbs = { alc260_init_verbs, alc260_will_verbs },
+		.num_dacs = ARRAY_SIZE(alc260_dac_nids),
+		.dac_nids = alc260_dac_nids,
+		.num_adc_nids = ARRAY_SIZE(alc260_adc_nids),
+		.adc_nids = alc260_adc_nids,
+		.dig_out_nid = ALC260_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc260_modes),
+		.channel_mode = alc260_modes,
+		.input_mux = &alc260_capture_source,
+	},
+	[ALC260_REPLACER_672V] = {
+		.mixers = { alc260_replacer_672v_mixer,
+			    alc260_capture_mixer },
+		.init_verbs = { alc260_init_verbs, alc260_replacer_672v_verbs },
+		.num_dacs = ARRAY_SIZE(alc260_dac_nids),
+		.dac_nids = alc260_dac_nids,
+		.num_adc_nids = ARRAY_SIZE(alc260_adc_nids),
+		.adc_nids = alc260_adc_nids,
+		.dig_out_nid = ALC260_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc260_modes),
+		.channel_mode = alc260_modes,
+		.input_mux = &alc260_capture_source,
+		.unsol_event = alc260_replacer_672v_unsol_event,
+		.init_hook = alc260_replacer_672v_automute,
+	},
 #ifdef CONFIG_SND_DEBUG
 	[ALC260_TEST] = {
 		.mixers = { alc260_test_mixer,
@@ -4313,7 +4657,7 @@ static int patch_alc260(struct hda_codec *codec)
 		if (err < 0) {
 			alc_free(codec);
 			return err;
-		} else if (! err) {
+		} else if (!err) {
 			printk(KERN_INFO
 			       "hda_codec: Cannot set up configuration "
 			       "from BIOS.  Using base mode...\n");
@@ -4382,7 +4726,8 @@ static struct hda_input_mux alc882_capture_source = {
 #define alc882_mux_enum_info alc_mux_enum_info
 #define alc882_mux_enum_get alc_mux_enum_get
 
-static int alc882_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+static int alc882_mux_enum_put(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
 {
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 	struct alc_spec *spec = codec->spec;
@@ -4396,7 +4741,7 @@ static int alc882_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ele
 	idx = ucontrol->value.enumerated.item[0];
 	if (idx >= imux->num_items)
 		idx = imux->num_items - 1;
-	if (*cur_val == idx && ! codec->in_resume)
+	if (*cur_val == idx && !codec->in_resume)
 		return 0;
 	for (i = 0; i < imux->num_items; i++) {
 		unsigned int v = (i == idx) ? 0x7000 : 0x7080;
@@ -4464,6 +4809,21 @@ static struct snd_kcontrol_new alc882_base_mixer[] = {
 	{ } /* end */
 };
 
+static struct snd_kcontrol_new alc882_w2jc_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
+	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
+	{ } /* end */
+};
+
 static struct snd_kcontrol_new alc882_chmode_mixer[] = {
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -4559,7 +4919,7 @@ static struct hda_verb alc882_eapd_verbs[] = {
 	/* change to EAPD mode */
 	{0x20, AC_VERB_SET_COEF_INDEX, 0x07},
 	{0x20, AC_VERB_SET_PROC_COEF, 0x3060},
-	{ } 
+	{ }
 };
 
 /* Mac Pro test */
@@ -4624,6 +4984,7 @@ static struct hda_verb alc882_macpro_init_verbs[] = {
 
 	{ }
 };
+
 static void alc882_gpio_mute(struct hda_codec *codec, int pin, int muted)
 {
 	unsigned int gpiostate, gpiomask, gpiodir;
@@ -4672,8 +5033,8 @@ static struct hda_verb alc882_auto_init_verbs[] = {
 
 	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
 	 * mixer widget
-	 * Note: PASD motherboards uses the Line In 2 as the input for front panel
-	 * mic (mic 2)
+	 * Note: PASD motherboards uses the Line In 2 as the input for
+	 * front panel mic (mic 2)
 	 */
 	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
 	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
@@ -4782,6 +5143,7 @@ static const char *alc882_models[ALC882_MODEL_LAST] = {
 	[ALC882_3ST_DIG]	= "3stack-dig",
 	[ALC882_6ST_DIG]	= "6stack-dig",
 	[ALC882_ARIMA]		= "arima",
+	[ALC882_W2JC]		= "w2jc",
 	[ALC885_MACPRO]		= "macpro",
 	[ALC882_AUTO]		= "auto",
 };
@@ -4792,6 +5154,7 @@ static struct snd_pci_quirk alc882_cfg_tbl[] = {
 	SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC882_6ST_DIG),
 	SND_PCI_QUIRK(0x161f, 0x2054, "Arima W820", ALC882_ARIMA),
 	SND_PCI_QUIRK(0x1043, 0x81d8, "Asus P5WD", ALC882_6ST_DIG),
+	SND_PCI_QUIRK(0x1043, 0x1971, "Asus W2JC", ALC882_W2JC),
 	{}
 };
 
@@ -4828,6 +5191,18 @@ static struct alc_config_preset alc882_presets[] = {
 		.channel_mode = alc882_sixstack_modes,
 		.input_mux = &alc882_capture_source,
 	},
+	[ALC882_W2JC] = {
+		.mixers = { alc882_w2jc_mixer, alc882_chmode_mixer },
+		.init_verbs = { alc882_init_verbs, alc882_eapd_verbs,
+				alc880_gpio1_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc882_dac_nids),
+		.dac_nids = alc882_dac_nids,
+		.num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
+		.channel_mode = alc880_threestack_modes,
+		.need_dac_fix = 1,
+		.input_mux = &alc882_capture_source,
+		.dig_out_nid = ALC882_DIGOUT_NID,
+	},
 	[ALC885_MACPRO] = {
 		.mixers = { alc882_macpro_mixer },
 		.init_verbs = { alc882_macpro_init_verbs },
@@ -4851,15 +5226,17 @@ static void alc882_auto_set_output_and_unmute(struct hda_codec *codec,
 {
 	/* set as output */
 	struct alc_spec *spec = codec->spec;
-	int idx; 
-	
+	int idx;
+
 	if (spec->multiout.dac_nids[dac_idx] == 0x25)
 		idx = 4;
 	else
 		idx = spec->multiout.dac_nids[dac_idx] - 2;
 
-	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
-	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
+	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
+			    pin_type);
+	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+			    AMP_OUT_UNMUTE);
 	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, idx);
 
 }
@@ -4869,10 +5246,13 @@ static void alc882_auto_init_multi_out(struct hda_codec *codec)
 	struct alc_spec *spec = codec->spec;
 	int i;
 
+	alc_subsystem_id(codec, 0x15, 0x1b, 0x14);
 	for (i = 0; i <= HDA_SIDE; i++) {
-		hda_nid_t nid = spec->autocfg.line_out_pins[i];	
+		hda_nid_t nid = spec->autocfg.line_out_pins[i];
+		int pin_type = get_pin_type(spec->autocfg.line_out_type);
 		if (nid)
-			alc882_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
+			alc882_auto_set_output_and_unmute(codec, nid, pin_type,
+							  i);
 	}
 }
 
@@ -4883,7 +5263,8 @@ static void alc882_auto_init_hp_out(struct hda_codec *codec)
 
 	pin = spec->autocfg.hp_pins[0];
 	if (pin) /* connect to front */
-		alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); /* use dac 0 */
+		/* use dac 0 */
+		alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
 }
 
 #define alc882_is_input_pin(nid)	alc880_is_input_pin(nid)
@@ -4897,10 +5278,13 @@ static void alc882_auto_init_analog_input(struct hda_codec *codec)
 	for (i = 0; i < AUTO_PIN_LAST; i++) {
 		hda_nid_t nid = spec->autocfg.input_pins[i];
 		if (alc882_is_input_pin(nid)) {
-			snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
-					    i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
+			snd_hda_codec_write(codec, nid, 0,
+					    AC_VERB_SET_PIN_WIDGET_CONTROL,
+					    i <= AUTO_PIN_FRONT_MIC ?
+					    PIN_VREF80 : PIN_IN);
 			if (nid != ALC882_PIN_CD_NID)
-				snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+				snd_hda_codec_write(codec, nid, 0,
+						    AC_VERB_SET_AMP_GAIN_MUTE,
 						    AMP_OUT_MUTE);
 		}
 	}
@@ -4962,7 +5346,7 @@ static int patch_alc882(struct hda_codec *codec)
 		if (err < 0) {
 			alc_free(codec);
 			return err;
-		} else if (! err) {
+		} else if (!err) {
 			printk(KERN_INFO
 			       "hda_codec: Cannot set up configuration "
 			       "from BIOS.  Using base mode...\n");
@@ -4986,14 +5370,16 @@ static int patch_alc882(struct hda_codec *codec)
 	spec->stream_digital_playback = &alc882_pcm_digital_playback;
 	spec->stream_digital_capture = &alc882_pcm_digital_capture;
 
-	if (! spec->adc_nids && spec->input_mux) {
+	if (!spec->adc_nids && spec->input_mux) {
 		/* check whether NID 0x07 is valid */
 		unsigned int wcap = get_wcaps(codec, 0x07);
-		wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */
+		/* get type */
+		wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
 		if (wcap != AC_WID_AUD_IN) {
 			spec->adc_nids = alc882_adc_nids_alt;
 			spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids_alt);
-			spec->mixers[spec->num_mixers] = alc882_capture_alt_mixer;
+			spec->mixers[spec->num_mixers] =
+				alc882_capture_alt_mixer;
 			spec->num_mixers++;
 		} else {
 			spec->adc_nids = alc882_adc_nids;
@@ -5033,6 +5419,7 @@ static hda_nid_t alc883_adc_nids[2] = {
 	/* ADC1-2 */
 	0x08, 0x09,
 };
+
 /* input MUX */
 /* FIXME: should be a matrix-type input source selection */
 
@@ -5045,6 +5432,15 @@ static struct hda_input_mux alc883_capture_source = {
 		{ "CD", 0x4 },
 	},
 };
+
+static struct hda_input_mux alc883_lenovo_101e_capture_source = {
+	.num_items = 2,
+	.items = {
+		{ "Mic", 0x1 },
+		{ "Line", 0x2 },
+	},
+};
+
 #define alc883_mux_enum_info alc_mux_enum_info
 #define alc883_mux_enum_get alc_mux_enum_get
 
@@ -5063,7 +5459,7 @@ static int alc883_mux_enum_put(struct snd_kcontrol *kcontrol,
 	idx = ucontrol->value.enumerated.item[0];
 	if (idx >= imux->num_items)
 		idx = imux->num_items - 1;
-	if (*cur_val == idx && ! codec->in_resume)
+	if (*cur_val == idx && !codec->in_resume)
 		return 0;
 	for (i = 0; i < imux->num_items; i++) {
 		unsigned int v = (i == idx) ? 0x7000 : 0x7080;
@@ -5073,6 +5469,7 @@ static int alc883_mux_enum_put(struct snd_kcontrol *kcontrol,
 	*cur_val = idx;
 	return 1;
 }
+
 /*
  * 2ch mode
  */
@@ -5325,7 +5722,7 @@ static struct snd_kcontrol_new alc883_tagra_mixer[] = {
 		.put = alc883_mux_enum_put,
 	},
 	{ } /* end */
-};	
+};
 
 static struct snd_kcontrol_new alc883_tagra_2ch_mixer[] = {
 	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
@@ -5350,7 +5747,30 @@ static struct snd_kcontrol_new alc883_tagra_2ch_mixer[] = {
 		.put = alc883_mux_enum_put,
 	},
 	{ } /* end */
-};	
+};
+
+static struct snd_kcontrol_new alc883_lenovo_101e_2ch_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("iSpeaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("iSpeaker Playback Switch", 0x0d, 2, HDA_INPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		/* .name = "Capture Source", */
+		.name = "Input Source",
+		.count = 1,
+		.info = alc883_mux_enum_info,
+		.get = alc883_mux_enum_get,
+		.put = alc883_mux_enum_put,
+	},
+	{ } /* end */
+};
 
 static struct snd_kcontrol_new alc883_chmode_mixer[] = {
 	{
@@ -5452,10 +5872,17 @@ static struct hda_verb alc883_tagra_verbs[] = {
 	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
 
 	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
-	{0x01, AC_VERB_SET_GPIO_MASK, 0x03}, 
-	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03}, 
-	{0x01, AC_VERB_SET_GPIO_DATA, 0x03}, 
+	{0x01, AC_VERB_SET_GPIO_MASK, 0x03},
+	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03},
+	{0x01, AC_VERB_SET_GPIO_DATA, 0x03},
+
+	{ } /* end */
+};
 
+static struct hda_verb alc883_lenovo_101e_verbs[] = {
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_FRONT_EVENT|AC_USRSP_EN},
+        {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT|AC_USRSP_EN},
 	{ } /* end */
 };
 
@@ -5463,14 +5890,17 @@ static struct hda_verb alc883_tagra_verbs[] = {
 static void alc883_tagra_automute(struct hda_codec *codec)
 {
  	unsigned int present;
+	unsigned char bits;
 
  	present = snd_hda_codec_read(codec, 0x14, 0,
 				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+	bits = present ? 0x80 : 0;
 	snd_hda_codec_amp_update(codec, 0x1b, 0, HDA_OUTPUT, 0,
-				 0x80, present ? 0x80 : 0);
+				 0x80, bits);
 	snd_hda_codec_amp_update(codec, 0x1b, 1, HDA_OUTPUT, 0,
-				 0x80, present ? 0x80 : 0);
-	snd_hda_codec_write(codec, 1, 0, AC_VERB_SET_GPIO_DATA, present ? 1 : 3);
+				 0x80, bits);
+	snd_hda_codec_write(codec, 1, 0, AC_VERB_SET_GPIO_DATA,
+			    present ? 1 : 3);
 }
 
 static void alc883_tagra_unsol_event(struct hda_codec *codec, unsigned int res)
@@ -5479,6 +5909,47 @@ static void alc883_tagra_unsol_event(struct hda_codec *codec, unsigned int res)
 		alc883_tagra_automute(codec);
 }
 
+static void alc883_lenovo_101e_ispeaker_automute(struct hda_codec *codec)
+{
+ 	unsigned int present;
+	unsigned char bits;
+
+ 	present = snd_hda_codec_read(codec, 0x14, 0,
+				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+	bits = present ? 0x80 : 0;
+	snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0,
+				 0x80, bits);
+	snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0,
+				 0x80, bits);
+}
+
+static void alc883_lenovo_101e_all_automute(struct hda_codec *codec)
+{
+ 	unsigned int present;
+	unsigned char bits;
+
+ 	present = snd_hda_codec_read(codec, 0x1b, 0,
+				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+	bits = present ? 0x80 : 0;
+	snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0,
+				 0x80, bits);
+	snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0,
+				 0x80, bits);
+	snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
+				 0x80, bits);
+	snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
+				 0x80, bits);
+}
+
+static void alc883_lenovo_101e_unsol_event(struct hda_codec *codec,
+					   unsigned int res)
+{
+	if ((res >> 26) == ALC880_HP_EVENT)
+		alc883_lenovo_101e_all_automute(codec);
+	if ((res >> 26) == ALC880_FRONT_EVENT)
+		alc883_lenovo_101e_ispeaker_automute(codec);
+}
+
 /*
  * generic initialization of ADC, input mixers and output mixers
  */
@@ -5493,8 +5964,8 @@ static struct hda_verb alc883_auto_init_verbs[] = {
 
 	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
 	 * mixer widget
-	 * Note: PASD motherboards uses the Line In 2 as the input for front panel
-	 * mic (mic 2)
+	 * Note: PASD motherboards uses the Line In 2 as the input for
+	 * front panel mic (mic 2)
 	 */
 	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
 	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
@@ -5530,13 +6001,13 @@ static struct hda_verb alc883_auto_init_verbs[] = {
 	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
 	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
-	//{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
+	/* {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, */
 	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
 	/* Input mixer2 */
 	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
 	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
-	//{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
+	/* {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, */
 	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
 
 	{ }
@@ -5584,6 +6055,7 @@ static const char *alc883_models[ALC883_MODEL_LAST] = {
 	[ALC883_ACER]		= "acer",
 	[ALC883_MEDION]		= "medion",
 	[ALC883_LAPTOP_EAPD]	= "laptop-eapd",
+	[ALC883_LENOVO_101E_2ch] = "lenovo-101e",
 	[ALC883_AUTO]		= "auto",
 };
 
@@ -5592,6 +6064,7 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
 	SND_PCI_QUIRK(0x108e, 0x534d, NULL, ALC883_3ST_6ch),
 	SND_PCI_QUIRK(0x1558, 0, "Clevo laptop", ALC883_LAPTOP_EAPD),
 	SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC883_6ST_DIG),
+	SND_PCI_QUIRK(0x1458, 0xa002, "MSI", ALC883_6ST_DIG),
 	SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC883_6ST_DIG),
 	SND_PCI_QUIRK(0x1462, 0x7187, "MSI", ALC883_6ST_DIG),
 	SND_PCI_QUIRK(0x1462, 0x7280, "MSI", ALC883_6ST_DIG),
@@ -5609,6 +6082,7 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
 	SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION),
 	SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC883_LAPTOP_EAPD),
 	SND_PCI_QUIRK(0x8086, 0xd601, "D102GGC", ALC883_3ST_6ch),
+	SND_PCI_QUIRK(0x17aa, 0x101e, "lenovo 101e", ALC883_LENOVO_101E_2ch),
 	{}
 };
 
@@ -5639,7 +6113,7 @@ static struct alc_config_preset alc883_presets[] = {
 		.channel_mode = alc883_3ST_6ch_modes,
 		.need_dac_fix = 1,
 		.input_mux = &alc883_capture_source,
-	},	
+	},
 	[ALC883_3ST_6ch] = {
 		.mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
 		.init_verbs = { alc883_init_verbs },
@@ -5651,7 +6125,7 @@ static struct alc_config_preset alc883_presets[] = {
 		.channel_mode = alc883_3ST_6ch_modes,
 		.need_dac_fix = 1,
 		.input_mux = &alc883_capture_source,
-	},	
+	},
 	[ALC883_6ST_DIG] = {
 		.mixers = { alc883_base_mixer, alc883_chmode_mixer },
 		.init_verbs = { alc883_init_verbs },
@@ -5749,6 +6223,19 @@ static struct alc_config_preset alc883_presets[] = {
 		.channel_mode = alc883_3ST_2ch_modes,
 		.input_mux = &alc883_capture_source,
 	},
+	[ALC883_LENOVO_101E_2ch] = {
+		.mixers = { alc883_lenovo_101e_2ch_mixer},
+		.init_verbs = { alc883_init_verbs, alc883_lenovo_101e_verbs},
+		.num_dacs = ARRAY_SIZE(alc883_dac_nids),
+		.dac_nids = alc883_dac_nids,
+		.num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+		.adc_nids = alc883_adc_nids,
+		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
+		.channel_mode = alc883_3ST_2ch_modes,
+		.input_mux = &alc883_lenovo_101e_capture_source,
+		.unsol_event = alc883_lenovo_101e_unsol_event,
+		.init_hook = alc883_lenovo_101e_all_automute,
+	},
 };
 
 
@@ -5761,8 +6248,8 @@ static void alc883_auto_set_output_and_unmute(struct hda_codec *codec,
 {
 	/* set as output */
 	struct alc_spec *spec = codec->spec;
-	int idx; 
-	
+	int idx;
+
 	if (spec->multiout.dac_nids[dac_idx] == 0x25)
 		idx = 4;
 	else
@@ -5781,10 +6268,13 @@ static void alc883_auto_init_multi_out(struct hda_codec *codec)
 	struct alc_spec *spec = codec->spec;
 	int i;
 
+	alc_subsystem_id(codec, 0x15, 0x1b, 0x14);
 	for (i = 0; i <= HDA_SIDE; i++) {
-		hda_nid_t nid = spec->autocfg.line_out_pins[i];	
+		hda_nid_t nid = spec->autocfg.line_out_pins[i];
+		int pin_type = get_pin_type(spec->autocfg.line_out_type);
 		if (nid)
-			alc883_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
+			alc883_auto_set_output_and_unmute(codec, nid, pin_type,
+							  i);
 	}
 }
 
@@ -5833,8 +6323,8 @@ static int alc883_parse_auto_config(struct hda_codec *codec)
 	else if (err > 0)
 		/* hack - override the init verbs */
 		spec->init_verbs[0] = alc883_auto_init_verbs;
-                spec->mixers[spec->num_mixers] = alc883_capture_mixer;
-		spec->num_mixers++;
+	spec->mixers[spec->num_mixers] = alc883_capture_mixer;
+	spec->num_mixers++;
 	return err;
 }
 
@@ -5872,7 +6362,7 @@ static int patch_alc883(struct hda_codec *codec)
 		if (err < 0) {
 			alc_free(codec);
 			return err;
-		} else if (! err) {
+		} else if (!err) {
 			printk(KERN_INFO
 			       "hda_codec: Cannot set up configuration "
 			       "from BIOS.  Using base mode...\n");
@@ -5891,7 +6381,7 @@ static int patch_alc883(struct hda_codec *codec)
 	spec->stream_digital_playback = &alc883_pcm_digital_playback;
 	spec->stream_digital_capture = &alc883_pcm_digital_capture;
 
-	if (! spec->adc_nids && spec->input_mux) {
+	if (!spec->adc_nids && spec->input_mux) {
 		spec->adc_nids = alc883_adc_nids;
 		spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids);
 	}
@@ -6028,8 +6518,8 @@ static struct hda_verb alc262_init_verbs[] = {
 
 	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
 	 * mixer widget
-	 * Note: PASD motherboards uses the Line In 2 as the input for front panel
-	 * mic (mic 2)
+	 * Note: PASD motherboards uses the Line In 2 as the input for
+	 * front panel mic (mic 2)
 	 */
 	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
 	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
@@ -6086,7 +6576,7 @@ static struct hda_verb alc262_init_verbs[] = {
 	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
 	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
 	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},	
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
 
 	{ }
 };
@@ -6113,7 +6603,7 @@ static void alc262_hippo_automute(struct hda_codec *codec, int force)
 	struct alc_spec *spec = codec->spec;
 	unsigned int mute;
 
-	if (force || ! spec->sense_updated) {
+	if (force || !spec->sense_updated) {
 		unsigned int present;
 		/* need to execute and sync at first */
 		snd_hda_codec_read(codec, 0x15, 0, AC_VERB_SET_PIN_SENSE, 0);
@@ -6153,7 +6643,7 @@ static void alc262_hippo1_automute(struct hda_codec *codec, int force)
 	struct alc_spec *spec = codec->spec;
 	unsigned int mute;
 
-	if (force || ! spec->sense_updated) {
+	if (force || !spec->sense_updated) {
 		unsigned int present;
 		/* need to execute and sync at first */
 		snd_hda_codec_read(codec, 0x1b, 0, AC_VERB_SET_PIN_SENSE, 0);
@@ -6226,7 +6716,7 @@ static void alc262_fujitsu_automute(struct hda_codec *codec, int force)
 	struct alc_spec *spec = codec->spec;
 	unsigned int mute;
 
-	if (force || ! spec->sense_updated) {
+	if (force || !spec->sense_updated) {
 		unsigned int present;
 		/* need to execute and sync at first */
 		snd_hda_codec_read(codec, 0x14, 0, AC_VERB_SET_PIN_SENSE, 0);
@@ -6331,7 +6821,8 @@ static struct hda_verb alc262_EAPD_verbs[] = {
 };
 
 /* add playback controls from the parsed DAC table */
-static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg)
+static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec,
+					     const struct auto_pin_cfg *cfg)
 {
 	hda_nid_t nid;
 	int err;
@@ -6342,26 +6833,39 @@ static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, const struct
 
 	nid = cfg->line_out_pins[0];
 	if (nid) {
-		if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Front Playback Volume",
-				       HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT))) < 0)
+		err = add_control(spec, ALC_CTL_WIDGET_VOL,
+				  "Front Playback Volume",
+				  HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT));
+		if (err < 0)
 			return err;
-		if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Front Playback Switch",
-				       HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
+		err = add_control(spec, ALC_CTL_WIDGET_MUTE,
+				  "Front Playback Switch",
+				  HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
+		if (err < 0)
 			return err;
 	}
 
 	nid = cfg->speaker_pins[0];
 	if (nid) {
 		if (nid == 0x16) {
-			if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Speaker Playback Volume",
-					       HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, HDA_OUTPUT))) < 0)
+			err = add_control(spec, ALC_CTL_WIDGET_VOL,
+					  "Speaker Playback Volume",
+					  HDA_COMPOSE_AMP_VAL(0x0e, 2, 0,
+							      HDA_OUTPUT));
+			if (err < 0)
 				return err;
-			if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Speaker Playback Switch",
-					       HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0)
+			err = add_control(spec, ALC_CTL_WIDGET_MUTE,
+					  "Speaker Playback Switch",
+					  HDA_COMPOSE_AMP_VAL(nid, 2, 0,
+							      HDA_OUTPUT));
+			if (err < 0)
 				return err;
 		} else {
-			if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Speaker Playback Switch",
-					       HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
+			err = add_control(spec, ALC_CTL_WIDGET_MUTE,
+					  "Speaker Playback Switch",
+					  HDA_COMPOSE_AMP_VAL(nid, 3, 0,
+							      HDA_OUTPUT));
+			if (err < 0)
 				return err;
 		}
 	}
@@ -6369,23 +6873,33 @@ static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, const struct
 	if (nid) {
 		/* spec->multiout.hp_nid = 2; */
 		if (nid == 0x16) {
-			if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Headphone Playback Volume",
-					       HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, HDA_OUTPUT))) < 0)
+			err = add_control(spec, ALC_CTL_WIDGET_VOL,
+					  "Headphone Playback Volume",
+					  HDA_COMPOSE_AMP_VAL(0x0e, 2, 0,
+							      HDA_OUTPUT));
+			if (err < 0)
 				return err;
-			if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Headphone Playback Switch",
-					       HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0)
+			err = add_control(spec, ALC_CTL_WIDGET_MUTE,
+					  "Headphone Playback Switch",
+					  HDA_COMPOSE_AMP_VAL(nid, 2, 0,
+							      HDA_OUTPUT));
+			if (err < 0)
 				return err;
 		} else {
-			if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Headphone Playback Switch",
-					       HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
+			err = add_control(spec, ALC_CTL_WIDGET_MUTE,
+					  "Headphone Playback Switch",
+					  HDA_COMPOSE_AMP_VAL(nid, 3, 0,
+							      HDA_OUTPUT));
+			if (err < 0)
 				return err;
 		}
 	}
-	return 0;	
+	return 0;
 }
 
 /* identical with ALC880 */
-#define alc262_auto_create_analog_input_ctls alc880_auto_create_analog_input_ctls
+#define alc262_auto_create_analog_input_ctls \
+	alc880_auto_create_analog_input_ctls
 
 /*
  * generic initialization of ADC, input mixers and output mixers
@@ -6403,8 +6917,8 @@ static struct hda_verb alc262_volume_init_verbs[] = {
 
 	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
 	 * mixer widget
-	 * Note: PASD motherboards uses the Line In 2 as the input for front panel
-	 * mic (mic 2)
+	 * Note: PASD motherboards uses the Line In 2 as the input for
+	 * front panel mic (mic 2)
 	 */
 	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
 	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
@@ -6464,8 +6978,8 @@ static struct hda_verb alc262_HP_BPC_init_verbs[] = {
 
 	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
 	 * mixer widget
-	 * Note: PASD motherboards uses the Line In 2 as the input for front panel
-	 * mic (mic 2)
+	 * Note: PASD motherboards uses the Line In 2 as the input for
+	 * front panel mic (mic 2)
 	 */
 	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
 	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
@@ -6647,13 +7161,17 @@ static int alc262_parse_auto_config(struct hda_codec *codec)
 	int err;
 	static hda_nid_t alc262_ignore[] = { 0x1d, 0 };
 
-	if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
-						alc262_ignore)) < 0)
+	err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
+					   alc262_ignore);
+	if (err < 0)
 		return err;
-	if (! spec->autocfg.line_outs)
+	if (!spec->autocfg.line_outs)
 		return 0; /* can't find valid BIOS pin config */
-	if ((err = alc262_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
-	    (err = alc262_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
+	err = alc262_auto_create_multi_out_ctls(spec, &spec->autocfg);
+	if (err < 0)
+		return err;
+	err = alc262_auto_create_analog_input_ctls(spec, &spec->autocfg);
+	if (err < 0)
 		return err;
 
 	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
@@ -6777,7 +7295,7 @@ static struct alc_config_preset alc262_presets[] = {
 		.num_channel_mode = ARRAY_SIZE(alc262_modes),
 		.channel_mode = alc262_modes,
 		.input_mux = &alc262_HP_capture_source,
-	},	
+	},
 	[ALC262_HP_BPC_D7000_WF] = {
 		.mixers = { alc262_HP_BPC_WildWest_mixer },
 		.init_verbs = { alc262_HP_BPC_WildWest_init_verbs },
@@ -6787,7 +7305,7 @@ static struct alc_config_preset alc262_presets[] = {
 		.num_channel_mode = ARRAY_SIZE(alc262_modes),
 		.channel_mode = alc262_modes,
 		.input_mux = &alc262_HP_capture_source,
-	},	
+	},
 	[ALC262_HP_BPC_D7000_WL] = {
 		.mixers = { alc262_HP_BPC_WildWest_mixer,
 			    alc262_HP_BPC_WildWest_option_mixer },
@@ -6798,7 +7316,7 @@ static struct alc_config_preset alc262_presets[] = {
 		.num_channel_mode = ARRAY_SIZE(alc262_modes),
 		.channel_mode = alc262_modes,
 		.input_mux = &alc262_HP_capture_source,
-	},	
+	},
 	[ALC262_BENQ_ED8] = {
 		.mixers = { alc262_base_mixer },
 		.init_verbs = { alc262_init_verbs, alc262_EAPD_verbs },
@@ -6808,7 +7326,7 @@ static struct alc_config_preset alc262_presets[] = {
 		.num_channel_mode = ARRAY_SIZE(alc262_modes),
 		.channel_mode = alc262_modes,
 		.input_mux = &alc262_capture_source,
-	},		
+	},
 };
 
 static int patch_alc262(struct hda_codec *codec)
@@ -6823,7 +7341,9 @@ static int patch_alc262(struct hda_codec *codec)
 
 	codec->spec = spec;
 #if 0
-	/* pshou 07/11/05  set a zero PCM sample to DAC when FIFO is under-run */
+	/* pshou 07/11/05  set a zero PCM sample to DAC when FIFO is
+	 * under-run
+	 */
 	{
 	int tmp;
 	snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_COEF_INDEX, 7);
@@ -6849,7 +7369,7 @@ static int patch_alc262(struct hda_codec *codec)
 		if (err < 0) {
 			alc_free(codec);
 			return err;
-		} else if (! err) {
+		} else if (!err) {
 			printk(KERN_INFO
 			       "hda_codec: Cannot set up configuration "
 			       "from BIOS.  Using base mode...\n");
@@ -6868,15 +7388,17 @@ static int patch_alc262(struct hda_codec *codec)
 	spec->stream_digital_playback = &alc262_pcm_digital_playback;
 	spec->stream_digital_capture = &alc262_pcm_digital_capture;
 
-	if (! spec->adc_nids && spec->input_mux) {
+	if (!spec->adc_nids && spec->input_mux) {
 		/* check whether NID 0x07 is valid */
 		unsigned int wcap = get_wcaps(codec, 0x07);
 
-		wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */
+		/* get type */
+		wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
 		if (wcap != AC_WID_AUD_IN) {
 			spec->adc_nids = alc262_adc_nids_alt;
 			spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids_alt);
-			spec->mixers[spec->num_mixers] = alc262_capture_alt_mixer;
+			spec->mixers[spec->num_mixers] =
+				alc262_capture_alt_mixer;
 			spec->num_mixers++;
 		} else {
 			spec->adc_nids = alc262_adc_nids;
@@ -6904,7 +7426,9 @@ static int patch_alc262(struct hda_codec *codec)
 static struct hda_verb alc861_threestack_ch2_init[] = {
 	/* set pin widget 1Ah (line in) for input */
 	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
-	/* set pin widget 18h (mic1/2) for input, for mic also enable the vref */
+	/* set pin widget 18h (mic1/2) for input, for mic also enable
+	 * the vref
+	 */
 	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
 
 	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c },
@@ -6961,7 +7485,9 @@ static struct hda_channel_mode alc861_uniwill_m31_modes[2] = {
 static struct hda_verb alc861_asus_ch2_init[] = {
 	/* set pin widget 1Ah (line in) for input */
 	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
-	/* set pin widget 18h (mic1/2) for input, for mic also enable the vref */
+	/* set pin widget 18h (mic1/2) for input, for mic also enable
+	 * the vref
+	 */
 	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
 
 	{ 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c },
@@ -7016,7 +7542,7 @@ static struct snd_kcontrol_new alc861_base_mixer[] = {
 	HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
 	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
 	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
- 
+
         /* Capture mixer control */
 	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
 	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
@@ -7050,7 +7576,7 @@ static struct snd_kcontrol_new alc861_3ST_mixer[] = {
 	HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
 	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
 	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
- 
+
 	/* Capture mixer control */
 	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
 	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
@@ -7092,7 +7618,7 @@ static struct snd_kcontrol_new alc861_toshiba_mixer[] = {
 	},
 
 	{ } /* end */
-};	
+};
 
 static struct snd_kcontrol_new alc861_uniwill_m31_mixer[] = {
         /* output mixer control */
@@ -7113,7 +7639,7 @@ static struct snd_kcontrol_new alc861_uniwill_m31_mixer[] = {
 	HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
 	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
 	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
- 
+
 	/* Capture mixer control */
 	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
 	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
@@ -7134,7 +7660,7 @@ static struct snd_kcontrol_new alc861_uniwill_m31_mixer[] = {
                 .private_value = ARRAY_SIZE(alc861_uniwill_m31_modes),
 	},
 	{ } /* end */
-};			
+};
 
 static struct snd_kcontrol_new alc861_asus_mixer[] = {
         /* output mixer control */
@@ -7154,8 +7680,8 @@ static struct snd_kcontrol_new alc861_asus_mixer[] = {
 	HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
 	HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
 	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_OUTPUT), /* was HDA_INPUT (why?) */
- 
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_OUTPUT),
+
 	/* Capture mixer control */
 	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
 	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
@@ -7239,7 +7765,7 @@ static struct hda_verb alc861_base_init_verbs[] = {
 	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
 	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c          }, //Output 0~12 step
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
 
 	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
@@ -7249,7 +7775,8 @@ static struct hda_verb alc861_base_init_verbs[] = {
 	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
 	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, // hp used DAC 3 (Front)
+	/* hp used DAC 3 (Front) */
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
         {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
 
 	{ }
@@ -7300,7 +7827,7 @@ static struct hda_verb alc861_threestack_init_verbs[] = {
 	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
 	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c          }, //Output 0~12 step
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
 
 	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
@@ -7310,7 +7837,8 @@ static struct hda_verb alc861_threestack_init_verbs[] = {
 	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
 	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, // hp used DAC 3 (Front)
+	/* hp used DAC 3 (Front) */
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
         {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
 	{ }
 };
@@ -7329,7 +7857,8 @@ static struct hda_verb alc861_uniwill_m31_init_verbs[] = {
 	{ 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
 	{ 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
 	/* port-E for HP out (front panel) */
-	{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, // this has to be set to VREF80
+	/* this has to be set to VREF80 */
+	{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
 	/* route front PCM to HP */
 	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
 	/* port-F for mic-in (front panel) with vref */
@@ -7360,7 +7889,7 @@ static struct hda_verb alc861_uniwill_m31_init_verbs[] = {
 	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
 	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c          }, //Output 0~12 step
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
 
 	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
@@ -7370,7 +7899,8 @@ static struct hda_verb alc861_uniwill_m31_init_verbs[] = {
 	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
 	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, // hp used DAC 3 (Front)
+	/* hp used DAC 3 (Front) */
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
         {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
 	{ }
 };
@@ -7379,7 +7909,9 @@ static struct hda_verb alc861_asus_init_verbs[] = {
 	/*
 	 * Unmute ADC0 and set the default input to mic-in
 	 */
-	/* port-A for surround (rear panel) | according to codec#0 this is the HP jack*/
+	/* port-A for surround (rear panel)
+	 * according to codec#0 this is the HP jack
+	 */
 	{ 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, /* was 0x00 */
 	/* route front PCM to HP */
 	{ 0x0e, AC_VERB_SET_CONNECT_SEL, 0x01 },
@@ -7391,7 +7923,8 @@ static struct hda_verb alc861_asus_init_verbs[] = {
 	{ 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
 	{ 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
 	/* port-E for HP out (front panel) */
-	{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, /* this has to be set to VREF80 */
+	/* this has to be set to VREF80 */
+	{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
 	/* route front PCM to HP */
 	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
 	/* port-F for mic-in (front panel) with vref */
@@ -7421,7 +7954,7 @@ static struct hda_verb alc861_asus_init_verbs[] = {
 	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
 	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c          }, /* Output 0~12 step */
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
 
 	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
@@ -7431,7 +7964,8 @@ static struct hda_verb alc861_asus_init_verbs[] = {
 	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
 	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, /* hp used DAC 3 (Front) */
+	/* hp used DAC 3 (Front) */
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
 	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
 	{ }
 };
@@ -7450,7 +7984,7 @@ static struct hda_verb alc861_auto_init_verbs[] = {
 	/*
 	 * Unmute ADC0 and set the default input to mic-in
 	 */
-//	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, */
 	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 	
 	/* Unmute DAC0~3 & spdif out*/
@@ -7483,21 +8017,21 @@ static struct hda_verb alc861_auto_init_verbs[] = {
 
 	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
 	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},	
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},		
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
 	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
 	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},	
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},	
+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
 
-	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},	// set Mic 1
+	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},	/* set Mic 1 */
 
 	{ }
 };
 
 static struct hda_verb alc861_toshiba_init_verbs[] = {
 	{0x0f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
-        
+
 	{ }
 };
 
@@ -7521,9 +8055,6 @@ static void alc861_toshiba_automute(struct hda_codec *codec)
 static void alc861_toshiba_unsol_event(struct hda_codec *codec,
 				       unsigned int res)
 {
-	/* Looks like the unsol event is incompatible with the standard
-	 * definition.  6bit tag is placed at 26 bit!
-	 */
 	if ((res >> 26) == ALC880_HP_EVENT)
 		alc861_toshiba_automute(codec);
 }
@@ -7568,7 +8099,8 @@ static struct hda_input_mux alc861_capture_source = {
 };
 
 /* fill in the dac_nids table from the parsed pin configuration */
-static int alc861_auto_fill_dac_nids(struct alc_spec *spec, const struct auto_pin_cfg *cfg)
+static int alc861_auto_fill_dac_nids(struct alc_spec *spec,
+				     const struct auto_pin_cfg *cfg)
 {
 	int i;
 	hda_nid_t nid;
@@ -7591,29 +8123,40 @@ static int alc861_auto_create_multi_out_ctls(struct alc_spec *spec,
 					     const struct auto_pin_cfg *cfg)
 {
 	char name[32];
-	static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" };
+	static const char *chname[4] = {
+		"Front", "Surround", NULL /*CLFE*/, "Side"
+	};
 	hda_nid_t nid;
 	int i, idx, err;
 
 	for (i = 0; i < cfg->line_outs; i++) {
 		nid = spec->multiout.dac_nids[i];
-		if (! nid)
+		if (!nid)
 			continue;
 		if (nid == 0x05) {
 			/* Center/LFE */
-			if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "Center Playback Switch",
-					       HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT))) < 0)
+			err = add_control(spec, ALC_CTL_BIND_MUTE,
+					  "Center Playback Switch",
+					  HDA_COMPOSE_AMP_VAL(nid, 1, 0,
+							      HDA_OUTPUT));
+			if (err < 0)
 				return err;
-			if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "LFE Playback Switch",
-					       HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0)
+			err = add_control(spec, ALC_CTL_BIND_MUTE,
+					  "LFE Playback Switch",
+					  HDA_COMPOSE_AMP_VAL(nid, 2, 0,
+							      HDA_OUTPUT));
+			if (err < 0)
 				return err;
 		} else {
-			for (idx = 0; idx < ARRAY_SIZE(alc861_dac_nids) - 1; idx++)
+			for (idx = 0; idx < ARRAY_SIZE(alc861_dac_nids) - 1;
+			     idx++)
 				if (nid == alc861_dac_nids[idx])
 					break;
 			sprintf(name, "%s Playback Switch", chname[idx]);
-			if ((err = add_control(spec, ALC_CTL_BIND_MUTE, name,
-					       HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
+			err = add_control(spec, ALC_CTL_BIND_MUTE, name,
+					  HDA_COMPOSE_AMP_VAL(nid, 3, 0,
+							      HDA_OUTPUT));
+			if (err < 0)
 				return err;
 		}
 	}
@@ -7625,13 +8168,15 @@ static int alc861_auto_create_hp_ctls(struct alc_spec *spec, hda_nid_t pin)
 	int err;
 	hda_nid_t nid;
 
-	if (! pin)
+	if (!pin)
 		return 0;
 
 	if ((pin >= 0x0b && pin <= 0x10) || pin == 0x1f || pin == 0x20) {
 		nid = 0x03;
-		if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Headphone Playback Switch",
-				       HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
+		err = add_control(spec, ALC_CTL_WIDGET_MUTE,
+				  "Headphone Playback Switch",
+				  HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
+		if (err < 0)
 			return err;
 		spec->multiout.hp_nid = nid;
 	}
@@ -7639,32 +8184,33 @@ static int alc861_auto_create_hp_ctls(struct alc_spec *spec, hda_nid_t pin)
 }
 
 /* create playback/capture controls for input pins */
-static int alc861_auto_create_analog_input_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg)
+static int alc861_auto_create_analog_input_ctls(struct alc_spec *spec,
+						const struct auto_pin_cfg *cfg)
 {
 	struct hda_input_mux *imux = &spec->private_imux;
 	int i, err, idx, idx1;
 
 	for (i = 0; i < AUTO_PIN_LAST; i++) {
-		switch(cfg->input_pins[i]) {
+		switch (cfg->input_pins[i]) {
 		case 0x0c:
 			idx1 = 1;
-			idx = 2;	// Line In
+			idx = 2;	/* Line In */
 			break;
 		case 0x0f:
 			idx1 = 2;
-			idx = 2;	// Line In
+			idx = 2;	/* Line In */
 			break;
 		case 0x0d:
 			idx1 = 0;
-			idx = 1;	// Mic In 
+			idx = 1;	/* Mic In */
 			break;
-		case 0x10:	
+		case 0x10:
 			idx1 = 3;
-			idx = 1;	// Mic In 
+			idx = 1;	/* Mic In */
 			break;
 		case 0x11:
 			idx1 = 4;
-			idx = 0;	// CD
+			idx = 0;	/* CD */
 			break;
 		default:
 			continue;
@@ -7677,7 +8223,7 @@ static int alc861_auto_create_analog_input_ctls(struct alc_spec *spec, const str
 
 		imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
 		imux->items[imux->num_items].index = idx1;
-		imux->num_items++;	
+		imux->num_items++;
 	}
 	return 0;
 }
@@ -7702,13 +8248,16 @@ static struct snd_kcontrol_new alc861_capture_mixer[] = {
 	{ } /* end */
 };
 
-static void alc861_auto_set_output_and_unmute(struct hda_codec *codec, hda_nid_t nid,
+static void alc861_auto_set_output_and_unmute(struct hda_codec *codec,
+					      hda_nid_t nid,
 					      int pin_type, int dac_idx)
 {
 	/* set as output */
 
-	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
-	snd_hda_codec_write(codec, dac_idx, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
+	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
+			    pin_type);
+	snd_hda_codec_write(codec, dac_idx, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+			    AMP_OUT_UNMUTE);
 
 }
 
@@ -7717,10 +8266,13 @@ static void alc861_auto_init_multi_out(struct hda_codec *codec)
 	struct alc_spec *spec = codec->spec;
 	int i;
 
+	alc_subsystem_id(codec, 0x0e, 0x0f, 0x0b);
 	for (i = 0; i < spec->autocfg.line_outs; i++) {
 		hda_nid_t nid = spec->autocfg.line_out_pins[i];
+		int pin_type = get_pin_type(spec->autocfg.line_out_type);
 		if (nid)
-			alc861_auto_set_output_and_unmute(codec, nid, PIN_OUT, spec->multiout.dac_nids[i]);
+			alc861_auto_set_output_and_unmute(codec, nid, pin_type,
+							  spec->multiout.dac_nids[i]);
 	}
 }
 
@@ -7731,7 +8283,8 @@ static void alc861_auto_init_hp_out(struct hda_codec *codec)
 
 	pin = spec->autocfg.hp_pins[0];
 	if (pin) /* connect to front */
-		alc861_auto_set_output_and_unmute(codec, pin, PIN_HP, spec->multiout.dac_nids[0]);
+		alc861_auto_set_output_and_unmute(codec, pin, PIN_HP,
+						  spec->multiout.dac_nids[0]);
 }
 
 static void alc861_auto_init_analog_input(struct hda_codec *codec)
@@ -7741,31 +8294,43 @@ static void alc861_auto_init_analog_input(struct hda_codec *codec)
 
 	for (i = 0; i < AUTO_PIN_LAST; i++) {
 		hda_nid_t nid = spec->autocfg.input_pins[i];
-		if ((nid>=0x0c) && (nid <=0x11)) {
-			snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
-					    i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
+		if (nid >= 0x0c && nid <= 0x11) {
+			snd_hda_codec_write(codec, nid, 0,
+					    AC_VERB_SET_PIN_WIDGET_CONTROL,
+					    i <= AUTO_PIN_FRONT_MIC ?
+					    PIN_VREF80 : PIN_IN);
 		}
 	}
 }
 
 /* parse the BIOS configuration and set up the alc_spec */
-/* return 1 if successful, 0 if the proper config is not found, or a negative error code */
+/* return 1 if successful, 0 if the proper config is not found,
+ * or a negative error code
+ */
 static int alc861_parse_auto_config(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
 	int err;
 	static hda_nid_t alc861_ignore[] = { 0x1d, 0 };
 
-	if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
-						alc861_ignore)) < 0)
+	err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
+					   alc861_ignore);
+	if (err < 0)
 		return err;
-	if (! spec->autocfg.line_outs)
+	if (!spec->autocfg.line_outs)
 		return 0; /* can't find valid BIOS pin config */
 
-	if ((err = alc861_auto_fill_dac_nids(spec, &spec->autocfg)) < 0 ||
-	    (err = alc861_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
-	    (err = alc861_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0])) < 0 ||
-	    (err = alc861_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
+	err = alc861_auto_fill_dac_nids(spec, &spec->autocfg);
+	if (err < 0)
+		return err;
+	err = alc861_auto_create_multi_out_ctls(spec, &spec->autocfg);
+	if (err < 0)
+		return err;
+	err = alc861_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
+	if (err < 0)
+		return err;
+	err = alc861_auto_create_analog_input_ctls(spec, &spec->autocfg);
+	if (err < 0)
 		return err;
 
 	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
@@ -7817,12 +8382,14 @@ static struct snd_pci_quirk alc861_cfg_tbl[] = {
 	SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC861_3ST),
 	SND_PCI_QUIRK(0x1043, 0x1335, "ASUS F2/3", ALC861_ASUS_LAPTOP),
 	SND_PCI_QUIRK(0x1043, 0x1338, "ASUS F2/3", ALC861_ASUS_LAPTOP),
+	SND_PCI_QUIRK(0x1043, 0x13d7, "ASUS A9rp", ALC861_ASUS_LAPTOP),
 	SND_PCI_QUIRK(0x1043, 0x1393, "ASUS", ALC861_ASUS),
 	SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS", ALC660_3ST),
 	SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba", ALC861_TOSHIBA),
 	SND_PCI_QUIRK(0x1179, 0xff10, "Toshiba", ALC861_TOSHIBA),
 	SND_PCI_QUIRK(0x1584, 0x9072, "Uniwill m31", ALC861_UNIWILL_M31),
 	SND_PCI_QUIRK(0x1584, 0x2b01, "Uniwill X40AIx", ALC861_UNIWILL_M31),
+	SND_PCI_QUIRK(0x1849, 0x0660, "Asrock 939SLI32", ALC660_3ST),
 	SND_PCI_QUIRK(0x8086, 0xd600, "Intel", ALC861_3ST),
 	{}
 };
@@ -7892,7 +8459,8 @@ static struct alc_config_preset alc861_presets[] = {
 	},
 	[ALC861_TOSHIBA] = {
 		.mixers = { alc861_toshiba_mixer },
-		.init_verbs = { alc861_base_init_verbs, alc861_toshiba_init_verbs },
+		.init_verbs = { alc861_base_init_verbs,
+				alc861_toshiba_init_verbs },
 		.num_dacs = ARRAY_SIZE(alc861_dac_nids),
 		.dac_nids = alc861_dac_nids,
 		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
@@ -7944,7 +8512,7 @@ static int patch_alc861(struct hda_codec *codec)
 	if (spec == NULL)
 		return -ENOMEM;
 
-	codec->spec = spec;	
+	codec->spec = spec;
 
         board_config = snd_hda_check_board_config(codec, ALC861_MODEL_LAST,
 						  alc861_models,
@@ -7962,7 +8530,7 @@ static int patch_alc861(struct hda_codec *codec)
 		if (err < 0) {
 			alc_free(codec);
 			return err;
-		} else if (! err) {
+		} else if (!err) {
 			printk(KERN_INFO
 			       "hda_codec: Cannot set up configuration "
 			       "from BIOS.  Using base mode...\n");
@@ -8049,7 +8617,7 @@ static int alc861vd_mux_enum_put(struct snd_kcontrol *kcontrol,
 	idx = ucontrol->value.enumerated.item[0];
 	if (idx >= imux->num_items)
 		idx = imux->num_items - 1;
-	if (*cur_val == idx && ! codec->in_resume)
+	if (*cur_val == idx && !codec->in_resume)
 		return 0;
 	for (i = 0; i < imux->num_items; i++) {
 		unsigned int v = (i == idx) ? 0x7000 : 0x7080;
@@ -8193,6 +8761,27 @@ static struct snd_kcontrol_new alc861vd_3st_mixer[] = {
 	{ } /* end */
 };
 
+static struct snd_kcontrol_new alc861vd_lenovo_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
+	/*HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),*/
+	HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+
+	HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+
+	HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+
+	{ } /* end */
+};
+
 /*
  * generic initialization of ADC, input mixers and output mixers
  */
@@ -8214,10 +8803,10 @@ static struct hda_verb alc861vd_volume_init_verbs[] = {
 	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
 
 	/* Capture mixer: unmute Mic, F-Mic, Line, CD inputs */
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
 	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(6)},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(8)},
 
 	/*
 	 * Set up output mixers (0x02 - 0x05)
@@ -8318,6 +8907,68 @@ static struct hda_verb alc861vd_6stack_init_verbs[] = {
 	{ }
 };
 
+static struct hda_verb alc861vd_eapd_verbs[] = {
+	{0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
+	{ }
+};
+
+static struct hda_verb alc861vd_lenovo_unsol_verbs[] = {
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
+	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
+	{0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},	
+	{}
+};
+
+/* toggle speaker-output according to the hp-jack state */
+static void alc861vd_lenovo_hp_automute(struct hda_codec *codec)
+{
+	unsigned int present;
+	unsigned char bits;
+
+	present = snd_hda_codec_read(codec, 0x1b, 0,
+				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+	bits = present ? 0x80 : 0;
+	snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
+				 0x80, bits);
+	snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
+				 0x80, bits);
+}
+
+static void alc861vd_lenovo_mic_automute(struct hda_codec *codec)
+{
+	unsigned int present;
+	unsigned char bits;
+
+	present = snd_hda_codec_read(codec, 0x18, 0,
+				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+	bits = present ? 0x80 : 0;
+	snd_hda_codec_amp_update(codec, 0x0b, 0, HDA_INPUT, 1,
+				 0x80, bits);
+	snd_hda_codec_amp_update(codec, 0x0b, 1, HDA_INPUT, 1,
+				 0x80, bits);
+}
+
+static void alc861vd_lenovo_automute(struct hda_codec *codec)
+{
+	alc861vd_lenovo_hp_automute(codec);
+	alc861vd_lenovo_mic_automute(codec);
+}
+
+static void alc861vd_lenovo_unsol_event(struct hda_codec *codec,
+					unsigned int res)
+{
+	switch (res >> 26) {
+	case ALC880_HP_EVENT:
+		alc861vd_lenovo_hp_automute(codec);
+		break;
+	case ALC880_MIC_EVENT:
+		alc861vd_lenovo_mic_automute(codec);
+		break;
+	}
+}
+
 /* pcm configuration: identiacal with ALC880 */
 #define alc861vd_pcm_analog_playback	alc880_pcm_analog_playback
 #define alc861vd_pcm_analog_capture	alc880_pcm_analog_capture
@@ -8332,15 +8983,18 @@ static const char *alc861vd_models[ALC861VD_MODEL_LAST] = {
 	[ALC861VD_3ST]		= "3stack",
 	[ALC861VD_3ST_DIG]	= "3stack-digout",
 	[ALC861VD_6ST_DIG]	= "6stack-digout",
+	[ALC861VD_LENOVO]	= "lenovo",
 	[ALC861VD_AUTO]		= "auto",
 };
 
 static struct snd_pci_quirk alc861vd_cfg_tbl[] = {
+	SND_PCI_QUIRK(0x1043, 0x12e2, "Asus z35m", ALC660VD_3ST),
 	SND_PCI_QUIRK(0x1043, 0x1339, "Asus G1", ALC660VD_3ST),
 	SND_PCI_QUIRK(0x10de, 0x03f0, "Realtek ALC660 demo", ALC660VD_3ST),
 	SND_PCI_QUIRK(0x1019, 0xa88d, "Realtek ALC660 demo", ALC660VD_3ST),
 
-	SND_PCI_QUIRK(0x17aa, 0x3802, "Lenovo 3000 C200", ALC861VD_3ST),
+	SND_PCI_QUIRK(0x17aa, 0x3802, "Lenovo 3000 C200", ALC861VD_LENOVO),
+	SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo", ALC861VD_LENOVO),
 	{}
 };
 
@@ -8389,6 +9043,22 @@ static struct alc_config_preset alc861vd_presets[] = {
 		.channel_mode = alc861vd_6stack_modes,
 		.input_mux = &alc861vd_capture_source,
 	},
+	[ALC861VD_LENOVO] = {
+		.mixers = { alc861vd_lenovo_mixer },
+		.init_verbs = { alc861vd_volume_init_verbs,
+				alc861vd_3stack_init_verbs,
+				alc861vd_eapd_verbs,
+				alc861vd_lenovo_unsol_verbs },
+		.num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
+		.dac_nids = alc660vd_dac_nids,
+		.num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids),
+		.adc_nids = alc861vd_adc_nids,
+		.num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
+		.channel_mode = alc861vd_3stack_2ch_modes,
+		.input_mux = &alc861vd_capture_source,
+		.unsol_event = alc861vd_lenovo_unsol_event,
+		.init_hook = alc861vd_lenovo_automute,
+	},
 };
 
 /*
@@ -8409,11 +9079,13 @@ static void alc861vd_auto_init_multi_out(struct hda_codec *codec)
 	struct alc_spec *spec = codec->spec;
 	int i;
 
+	alc_subsystem_id(codec, 0x15, 0x1b, 0x14);
 	for (i = 0; i <= HDA_SIDE; i++) {
 		hda_nid_t nid = spec->autocfg.line_out_pins[i];
+		int pin_type = get_pin_type(spec->autocfg.line_out_type);
 		if (nid)
 			alc861vd_auto_set_output_and_unmute(codec, nid,
-								PIN_OUT, i);
+							    pin_type, i);
 	}
 }
 
@@ -8466,7 +9138,7 @@ static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec,
 	int i, err;
 
 	for (i = 0; i < cfg->line_outs; i++) {
-		if (! spec->multiout.dac_nids[i])
+		if (!spec->multiout.dac_nids[i])
 			continue;
 		nid_v = alc861vd_idx_to_mixer_vol(
 				alc880_dac_to_idx(
@@ -8477,36 +9149,42 @@ static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec,
 
 		if (i == 2) {
 			/* Center/LFE */
-			if ((err = add_control(spec, ALC_CTL_WIDGET_VOL,
-						"Center Playback Volume",
-						HDA_COMPOSE_AMP_VAL(nid_v, 1,
-							0, HDA_OUTPUT))) < 0)
+			err = add_control(spec, ALC_CTL_WIDGET_VOL,
+					  "Center Playback Volume",
+					  HDA_COMPOSE_AMP_VAL(nid_v, 1, 0,
+							      HDA_OUTPUT));
+			if (err < 0)
 				return err;
-			if ((err = add_control(spec, ALC_CTL_WIDGET_VOL,
-						"LFE Playback Volume",
-						HDA_COMPOSE_AMP_VAL(nid_v, 2,
-							0, HDA_OUTPUT))) < 0)
+			err = add_control(spec, ALC_CTL_WIDGET_VOL,
+					  "LFE Playback Volume",
+					  HDA_COMPOSE_AMP_VAL(nid_v, 2, 0,
+							      HDA_OUTPUT));
+			if (err < 0)
 				return err;
-			if ((err = add_control(spec, ALC_CTL_BIND_MUTE,
-						"Center Playback Switch",
-						HDA_COMPOSE_AMP_VAL(nid_s, 1,
-						2, HDA_INPUT))) < 0)
+			err = add_control(spec, ALC_CTL_BIND_MUTE,
+					  "Center Playback Switch",
+					  HDA_COMPOSE_AMP_VAL(nid_s, 1, 2,
+							      HDA_INPUT));
+			if (err < 0)
 				return err;
-			if ((err = add_control(spec, ALC_CTL_BIND_MUTE,
-						"LFE Playback Switch",
-						HDA_COMPOSE_AMP_VAL(nid_s, 2,
-						2, HDA_INPUT))) < 0)
+			err = add_control(spec, ALC_CTL_BIND_MUTE,
+					  "LFE Playback Switch",
+					  HDA_COMPOSE_AMP_VAL(nid_s, 2, 2,
+							      HDA_INPUT));
+			if (err < 0)
 				return err;
 		} else {
 			sprintf(name, "%s Playback Volume", chname[i]);
-			if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
-						HDA_COMPOSE_AMP_VAL(nid_v, 3,
-							0, HDA_OUTPUT))) < 0)
+			err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
+					  HDA_COMPOSE_AMP_VAL(nid_v, 3, 0,
+							      HDA_OUTPUT));
+			if (err < 0)
 				return err;
 			sprintf(name, "%s Playback Switch", chname[i]);
-			if ((err = add_control(spec, ALC_CTL_BIND_MUTE, name,
-						HDA_COMPOSE_AMP_VAL(nid_v, 3,
-							2, HDA_INPUT))) < 0)
+			err = add_control(spec, ALC_CTL_BIND_MUTE, name,
+					  HDA_COMPOSE_AMP_VAL(nid_s, 3, 2,
+							      HDA_INPUT));
+			if (err < 0)
 				return err;
 		}
 	}
@@ -8523,13 +9201,13 @@ static int alc861vd_auto_create_extra_out(struct alc_spec *spec,
 	int err;
 	char name[32];
 
-	if (! pin)
+	if (!pin)
 		return 0;
 
 	if (alc880_is_fixed_pin(pin)) {
 		nid_v = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));
 		/* specify the DAC as the extra output */
-		if (! spec->multiout.hp_nid)
+		if (!spec->multiout.hp_nid)
 			spec->multiout.hp_nid = nid_v;
 		else
 			spec->multiout.extra_out_nid[0] = nid_v;
@@ -8540,22 +9218,22 @@ static int alc861vd_auto_create_extra_out(struct alc_spec *spec,
 				alc880_fixed_pin_idx(pin));
 
 		sprintf(name, "%s Playback Volume", pfx);
-		if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
-				HDA_COMPOSE_AMP_VAL(nid_v, 3, 0,
-							HDA_OUTPUT))) < 0)
+		err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
+				  HDA_COMPOSE_AMP_VAL(nid_v, 3, 0, HDA_OUTPUT));
+		if (err < 0)
 			return err;
 		sprintf(name, "%s Playback Switch", pfx);
-		if ((err = add_control(spec, ALC_CTL_BIND_MUTE, name,
-				HDA_COMPOSE_AMP_VAL(nid_s, 3, 2,
-							HDA_INPUT))) < 0)
+		err = add_control(spec, ALC_CTL_BIND_MUTE, name,
+				  HDA_COMPOSE_AMP_VAL(nid_s, 3, 2, HDA_INPUT));
+		if (err < 0)
 			return err;
 	} else if (alc880_is_multi_pin(pin)) {
 		/* set manual connection */
 		/* we have only a switch on HP-out PIN */
 		sprintf(name, "%s Playback Switch", pfx);
-		if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
-				HDA_COMPOSE_AMP_VAL(pin, 3, 0,
-							HDA_OUTPUT))) < 0)
+		err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
+				  HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
+		if (err < 0)
 			return err;
 	}
 	return 0;
@@ -8572,21 +9250,31 @@ static int alc861vd_parse_auto_config(struct hda_codec *codec)
 	int err;
 	static hda_nid_t alc861vd_ignore[] = { 0x1d, 0 };
 
-	if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
-						alc861vd_ignore)) < 0)
+	err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
+					   alc861vd_ignore);
+	if (err < 0)
 		return err;
-	if (! spec->autocfg.line_outs)
+	if (!spec->autocfg.line_outs)
 		return 0; /* can't find valid BIOS pin config */
 
-	if ((err = alc880_auto_fill_dac_nids(spec, &spec->autocfg)) < 0 ||
-		(err = alc861vd_auto_create_multi_out_ctls(spec,
-			&spec->autocfg)) < 0 ||
-		(err = alc861vd_auto_create_extra_out(spec,
-			spec->autocfg.speaker_pins[0], "Speaker")) < 0 ||
-		(err = alc861vd_auto_create_extra_out(spec,
-			spec->autocfg.hp_pins[0], "Headphone")) < 0 ||
-		(err = alc880_auto_create_analog_input_ctls(spec,
-			&spec->autocfg)) < 0)
+	err = alc880_auto_fill_dac_nids(spec, &spec->autocfg);
+	if (err < 0)
+		return err;
+	err = alc861vd_auto_create_multi_out_ctls(spec, &spec->autocfg);
+	if (err < 0)
+		return err;
+	err = alc861vd_auto_create_extra_out(spec,
+					     spec->autocfg.speaker_pins[0],
+					     "Speaker");
+	if (err < 0)
+		return err;
+	err = alc861vd_auto_create_extra_out(spec,
+					     spec->autocfg.hp_pins[0],
+					     "Headphone");
+	if (err < 0)
+		return err;
+	err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg);
+	if (err < 0)
 		return err;
 
 	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
@@ -8641,7 +9329,7 @@ static int patch_alc861vd(struct hda_codec *codec)
 		if (err < 0) {
 			alc_free(codec);
 			return err;
-		} else if (! err) {
+		} else if (!err) {
 			printk(KERN_INFO
 			       "hda_codec: Cannot set up configuration "
 			       "from BIOS.  Using base mode...\n");
@@ -8675,16 +9363,875 @@ static int patch_alc861vd(struct hda_codec *codec)
 }
 
 /*
+ * ALC662 support
+ *
+ * ALC662 is almost identical with ALC880 but has cleaner and more flexible
+ * configuration.  Each pin widget can choose any input DACs and a mixer.
+ * Each ADC is connected from a mixer of all inputs.  This makes possible
+ * 6-channel independent captures.
+ *
+ * In addition, an independent DAC for the multi-playback (not used in this
+ * driver yet).
+ */
+#define ALC662_DIGOUT_NID	0x06
+#define ALC662_DIGIN_NID	0x0a
+
+static hda_nid_t alc662_dac_nids[4] = {
+	/* front, rear, clfe, rear_surr */
+	0x02, 0x03, 0x04
+};
+
+static hda_nid_t alc662_adc_nids[1] = {
+	/* ADC1-2 */
+	0x09,
+};
+/* input MUX */
+/* FIXME: should be a matrix-type input source selection */
+
+static struct hda_input_mux alc662_capture_source = {
+	.num_items = 4,
+	.items = {
+		{ "Mic", 0x0 },
+		{ "Front Mic", 0x1 },
+		{ "Line", 0x2 },
+		{ "CD", 0x4 },
+	},
+};
+
+static struct hda_input_mux alc662_lenovo_101e_capture_source = {
+	.num_items = 2,
+	.items = {
+		{ "Mic", 0x1 },
+		{ "Line", 0x2 },
+	},
+};
+#define alc662_mux_enum_info alc_mux_enum_info
+#define alc662_mux_enum_get alc_mux_enum_get
+
+static int alc662_mux_enum_put(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct alc_spec *spec = codec->spec;
+	const struct hda_input_mux *imux = spec->input_mux;
+	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+	static hda_nid_t capture_mixers[3] = { 0x24, 0x23, 0x22 };
+	hda_nid_t nid = capture_mixers[adc_idx];
+	unsigned int *cur_val = &spec->cur_mux[adc_idx];
+	unsigned int i, idx;
+
+	idx = ucontrol->value.enumerated.item[0];
+	if (idx >= imux->num_items)
+		idx = imux->num_items - 1;
+	if (*cur_val == idx && !codec->in_resume)
+		return 0;
+	for (i = 0; i < imux->num_items; i++) {
+		unsigned int v = (i == idx) ? 0x7000 : 0x7080;
+		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+				    v | (imux->items[i].index << 8));
+	}
+	*cur_val = idx;
+	return 1;
+}
+/*
+ * 2ch mode
+ */
+static struct hda_channel_mode alc662_3ST_2ch_modes[1] = {
+	{ 2, NULL }
+};
+
+/*
+ * 2ch mode
+ */
+static struct hda_verb alc662_3ST_ch2_init[] = {
+	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
+	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
+	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
+	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
+	{ } /* end */
+};
+
+/*
+ * 6ch mode
+ */
+static struct hda_verb alc662_3ST_ch6_init[] = {
+	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+	{ 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
+	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+	{ 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
+	{ } /* end */
+};
+
+static struct hda_channel_mode alc662_3ST_6ch_modes[2] = {
+	{ 2, alc662_3ST_ch2_init },
+	{ 6, alc662_3ST_ch6_init },
+};
+
+/*
+ * 2ch mode
+ */
+static struct hda_verb alc662_sixstack_ch6_init[] = {
+	{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
+	{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
+	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ } /* end */
+};
+
+/*
+ * 6ch mode
+ */
+static struct hda_verb alc662_sixstack_ch8_init[] = {
+	{ 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ } /* end */
+};
+
+static struct hda_channel_mode alc662_5stack_modes[2] = {
+	{ 2, alc662_sixstack_ch6_init },
+	{ 6, alc662_sixstack_ch8_init },
+};
+
+/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
+ *                 Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
+ */
+
+static struct snd_kcontrol_new alc662_base_mixer[] = {
+	/* output mixer control */
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Front Playback Switch", 0x02, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Surround Playback Volume", 0x3, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Surround Playback Switch", 0x03, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x04, 1, 2, HDA_INPUT),
+	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x04, 2, 2, HDA_INPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+
+	/*Input mixer control */
+	HDA_CODEC_VOLUME("CD Playback Volume", 0xb, 0x4, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0xb, 0x4, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0xb, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0xb, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0xb, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0xb, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0xb, 0x01, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0xb, 0x01, HDA_INPUT),
+
+	/* Capture mixer control */
+	HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Capture Source",
+		.count = 1,
+		.info = alc_mux_enum_info,
+		.get = alc_mux_enum_get,
+		.put = alc_mux_enum_put,
+	},
+	{ } /* end */
+};
+
+static struct snd_kcontrol_new alc662_3ST_2ch_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Front Playback Switch", 0x02, 2, HDA_INPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
+	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
+	HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		/* .name = "Capture Source", */
+		.name = "Input Source",
+		.count = 1,
+		.info = alc662_mux_enum_info,
+		.get = alc662_mux_enum_get,
+		.put = alc662_mux_enum_put,
+	},
+	{ } /* end */
+};
+
+static struct snd_kcontrol_new alc662_3ST_6ch_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Front Playback Switch", 0x02, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Surround Playback Switch", 0x03, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x04, 1, 2, HDA_INPUT),
+	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x04, 2, 2, HDA_INPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
+	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
+	HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		/* .name = "Capture Source", */
+		.name = "Input Source",
+		.count = 1,
+		.info = alc662_mux_enum_info,
+		.get = alc662_mux_enum_get,
+		.put = alc662_mux_enum_put,
+	},
+	{ } /* end */
+};
+
+static struct snd_kcontrol_new alc662_lenovo_101e_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("Front Playback Switch", 0x02, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("iSpeaker Playback Volume", 0x03, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE("iSpeaker Playback Switch", 0x03, 2, HDA_INPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		/* .name = "Capture Source", */
+		.name = "Input Source",
+		.count = 1,
+		.info = alc662_mux_enum_info,
+		.get = alc662_mux_enum_get,
+		.put = alc662_mux_enum_put,
+	},
+	{ } /* end */
+};
+
+static struct snd_kcontrol_new alc662_chmode_mixer[] = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Channel Mode",
+		.info = alc_ch_mode_info,
+		.get = alc_ch_mode_get,
+		.put = alc_ch_mode_put,
+	},
+	{ } /* end */
+};
+
+static struct hda_verb alc662_init_verbs[] = {
+	/* ADC: mute amp left and right */
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* Front mixer: unmute input/output amp left and right (volume = 0) */
+
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
+
+	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+
+	/* Front Pin: output 0 (0x0c) */
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+
+	/* Rear Pin: output 1 (0x0d) */
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+
+	/* CLFE Pin: output 2 (0x0e) */
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+
+	/* Mic (rear) pin: input vref at 80% */
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* Front Mic pin: input vref at 80% */
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* Line In pin: input */
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* Line-2 In: Headphone output (output 0 - 0x0c) */
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* CD pin widget for input */
+	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+
+	/* FIXME: use matrix-type input source selection */
+	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
+	/* Input mixer */
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
+	{ }
+};
+
+static struct hda_verb alc662_sue_init_verbs[] = {
+	{0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_FRONT_EVENT},
+	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC880_HP_EVENT},
+        {}
+};
+
+/*
+ * generic initialization of ADC, input mixers and output mixers
+ */
+static struct hda_verb alc662_auto_init_verbs[] = {
+	/*
+	 * Unmute ADC and set the default input to mic-in
+	 */
+	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+
+	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
+	 * mixer widget
+	 * Note: PASD motherboards uses the Line In 2 as the input for front
+	 * panel mic (mic 2)
+	 */
+	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
+
+	/*
+	 * Set up output mixers (0x0c - 0x0f)
+	 */
+	/* set vol=0 to output mixers */
+	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+
+	/* set up input amps for analog loopback */
+	/* Amp Indices: DAC = 0, mixer = 1 */
+	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+
+
+	/* FIXME: use matrix-type input source selection */
+	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
+	/* Input mixer */
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
+	/*{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},*/
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
+
+	{ }
+};
+
+/* capture mixer elements */
+static struct snd_kcontrol_new alc662_capture_mixer[] = {
+	HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		/* The multiple "Capture Source" controls confuse alsamixer
+		 * So call somewhat different..
+		 * FIXME: the controls appear in the "playback" view!
+		 */
+		/* .name = "Capture Source", */
+		.name = "Input Source",
+		.count = 1,
+		.info = alc882_mux_enum_info,
+		.get = alc882_mux_enum_get,
+		.put = alc882_mux_enum_put,
+	},
+	{ } /* end */
+};
+
+static void alc662_lenovo_101e_ispeaker_automute(struct hda_codec *codec)
+{
+	unsigned int present;
+	unsigned char bits;
+
+	present = snd_hda_codec_read(codec, 0x14, 0,
+				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+	bits = present ? 0x80 : 0;
+	snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0,
+				 0x80, bits);
+	snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0,
+				 0x80, bits);
+}
+
+static void alc662_lenovo_101e_all_automute(struct hda_codec *codec)
+{
+	unsigned int present;
+	unsigned char bits;
+
+ 	present = snd_hda_codec_read(codec, 0x1b, 0,
+				     AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
+	bits = present ? 0x80 : 0;
+	snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0,
+				 0x80, bits);
+	snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0,
+				 0x80, bits);
+	snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
+				 0x80, bits);
+	snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
+				 0x80, bits);
+}
+
+static void alc662_lenovo_101e_unsol_event(struct hda_codec *codec,
+					   unsigned int res)
+{
+	if ((res >> 26) == ALC880_HP_EVENT)
+		alc662_lenovo_101e_all_automute(codec);
+	if ((res >> 26) == ALC880_FRONT_EVENT)
+		alc662_lenovo_101e_ispeaker_automute(codec);
+}
+
+
+/* pcm configuration: identiacal with ALC880 */
+#define alc662_pcm_analog_playback	alc880_pcm_analog_playback
+#define alc662_pcm_analog_capture	alc880_pcm_analog_capture
+#define alc662_pcm_digital_playback	alc880_pcm_digital_playback
+#define alc662_pcm_digital_capture	alc880_pcm_digital_capture
+
+/*
+ * configuration and preset
+ */
+static const char *alc662_models[ALC662_MODEL_LAST] = {
+	[ALC662_3ST_2ch_DIG]	= "3stack-dig",
+	[ALC662_3ST_6ch_DIG]	= "3stack-6ch-dig",
+	[ALC662_3ST_6ch]	= "3stack-6ch",
+	[ALC662_5ST_DIG]	= "6stack-dig",
+	[ALC662_LENOVO_101E]	= "lenovo-101e",
+	[ALC662_AUTO]		= "auto",
+};
+
+static struct snd_pci_quirk alc662_cfg_tbl[] = {
+	SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E),
+	{}
+};
+
+static struct alc_config_preset alc662_presets[] = {
+	[ALC662_3ST_2ch_DIG] = {
+		.mixers = { alc662_3ST_2ch_mixer },
+		.init_verbs = { alc662_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
+		.dac_nids = alc662_dac_nids,
+		.dig_out_nid = ALC662_DIGOUT_NID,
+		.num_adc_nids = ARRAY_SIZE(alc662_adc_nids),
+		.adc_nids = alc662_adc_nids,
+		.dig_in_nid = ALC662_DIGIN_NID,
+		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
+		.channel_mode = alc662_3ST_2ch_modes,
+		.input_mux = &alc662_capture_source,
+	},
+	[ALC662_3ST_6ch_DIG] = {
+		.mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer },
+		.init_verbs = { alc662_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
+		.dac_nids = alc662_dac_nids,
+		.dig_out_nid = ALC662_DIGOUT_NID,
+		.num_adc_nids = ARRAY_SIZE(alc662_adc_nids),
+		.adc_nids = alc662_adc_nids,
+		.dig_in_nid = ALC662_DIGIN_NID,
+		.num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
+		.channel_mode = alc662_3ST_6ch_modes,
+		.need_dac_fix = 1,
+		.input_mux = &alc662_capture_source,
+	},
+	[ALC662_3ST_6ch] = {
+		.mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer },
+		.init_verbs = { alc662_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
+		.dac_nids = alc662_dac_nids,
+		.num_adc_nids = ARRAY_SIZE(alc662_adc_nids),
+		.adc_nids = alc662_adc_nids,
+		.num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
+		.channel_mode = alc662_3ST_6ch_modes,
+		.need_dac_fix = 1,
+		.input_mux = &alc662_capture_source,
+	},
+	[ALC662_5ST_DIG] = {
+		.mixers = { alc662_base_mixer, alc662_chmode_mixer },
+		.init_verbs = { alc662_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
+		.dac_nids = alc662_dac_nids,
+		.dig_out_nid = ALC662_DIGOUT_NID,
+		.num_adc_nids = ARRAY_SIZE(alc662_adc_nids),
+		.adc_nids = alc662_adc_nids,
+		.dig_in_nid = ALC662_DIGIN_NID,
+		.num_channel_mode = ARRAY_SIZE(alc662_5stack_modes),
+		.channel_mode = alc662_5stack_modes,
+		.input_mux = &alc662_capture_source,
+	},
+	[ALC662_LENOVO_101E] = {
+		.mixers = { alc662_lenovo_101e_mixer },
+		.init_verbs = { alc662_init_verbs, alc662_sue_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc662_dac_nids),
+		.dac_nids = alc662_dac_nids,
+		.num_adc_nids = ARRAY_SIZE(alc662_adc_nids),
+		.adc_nids = alc662_adc_nids,
+		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
+		.channel_mode = alc662_3ST_2ch_modes,
+		.input_mux = &alc662_lenovo_101e_capture_source,
+		.unsol_event = alc662_lenovo_101e_unsol_event,
+		.init_hook = alc662_lenovo_101e_all_automute,
+	},
+
+};
+
+
+/*
+ * BIOS auto configuration
+ */
+
+/* add playback controls from the parsed DAC table */
+static int alc662_auto_create_multi_out_ctls(struct alc_spec *spec,
+					     const struct auto_pin_cfg *cfg)
+{
+	char name[32];
+	static const char *chname[4] = {
+		"Front", "Surround", NULL /*CLFE*/, "Side"
+	};
+	hda_nid_t nid;
+	int i, err;
+
+	for (i = 0; i < cfg->line_outs; i++) {
+		if (!spec->multiout.dac_nids[i])
+			continue;
+		nid = alc880_idx_to_dac(i);
+		if (i == 2) {
+			/* Center/LFE */
+			err = add_control(spec, ALC_CTL_WIDGET_VOL,
+					  "Center Playback Volume",
+					  HDA_COMPOSE_AMP_VAL(nid, 1, 0,
+							      HDA_OUTPUT));
+			if (err < 0)
+				return err;
+			err = add_control(spec, ALC_CTL_WIDGET_VOL,
+					  "LFE Playback Volume",
+					  HDA_COMPOSE_AMP_VAL(nid, 2, 0,
+							      HDA_OUTPUT));
+			if (err < 0)
+				return err;
+			err = add_control(spec, ALC_CTL_BIND_MUTE,
+					  "Center Playback Switch",
+					  HDA_COMPOSE_AMP_VAL(nid, 1, 2,
+							      HDA_INPUT));
+			if (err < 0)
+				return err;
+			err = add_control(spec, ALC_CTL_BIND_MUTE,
+					  "LFE Playback Switch",
+					  HDA_COMPOSE_AMP_VAL(nid, 2, 2,
+							      HDA_INPUT));
+			if (err < 0)
+				return err;
+		} else {
+			sprintf(name, "%s Playback Volume", chname[i]);
+			err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
+					  HDA_COMPOSE_AMP_VAL(nid, 3, 0,
+							      HDA_OUTPUT));
+			if (err < 0)
+				return err;
+			sprintf(name, "%s Playback Switch", chname[i]);
+			err = add_control(spec, ALC_CTL_BIND_MUTE, name,
+					  HDA_COMPOSE_AMP_VAL(nid, 3, 2,
+							      HDA_INPUT));
+			if (err < 0)
+				return err;
+		}
+	}
+	return 0;
+}
+
+/* add playback controls for speaker and HP outputs */
+static int alc662_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin,
+					const char *pfx)
+{
+	hda_nid_t nid;
+	int err;
+	char name[32];
+
+	if (!pin)
+		return 0;
+
+	if (alc880_is_fixed_pin(pin)) {
+		nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));
+                /* printk("DAC nid=%x\n",nid); */
+		/* specify the DAC as the extra output */
+		if (!spec->multiout.hp_nid)
+			spec->multiout.hp_nid = nid;
+		else
+			spec->multiout.extra_out_nid[0] = nid;
+		/* control HP volume/switch on the output mixer amp */
+		nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));
+		sprintf(name, "%s Playback Volume", pfx);
+		err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
+				  HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
+		if (err < 0)
+			return err;
+		sprintf(name, "%s Playback Switch", pfx);
+		err = add_control(spec, ALC_CTL_BIND_MUTE, name,
+				  HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT));
+		if (err < 0)
+			return err;
+	} else if (alc880_is_multi_pin(pin)) {
+		/* set manual connection */
+		/* we have only a switch on HP-out PIN */
+		sprintf(name, "%s Playback Switch", pfx);
+		err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
+				  HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
+		if (err < 0)
+			return err;
+	}
+	return 0;
+}
+
+/* create playback/capture controls for input pins */
+static int alc662_auto_create_analog_input_ctls(struct alc_spec *spec,
+						const struct auto_pin_cfg *cfg)
+{
+	struct hda_input_mux *imux = &spec->private_imux;
+	int i, err, idx;
+
+	for (i = 0; i < AUTO_PIN_LAST; i++) {
+		if (alc880_is_input_pin(cfg->input_pins[i])) {
+			idx = alc880_input_pin_idx(cfg->input_pins[i]);
+			err = new_analog_input(spec, cfg->input_pins[i],
+					       auto_pin_cfg_labels[i],
+					       idx, 0x0b);
+			if (err < 0)
+				return err;
+			imux->items[imux->num_items].label =
+				auto_pin_cfg_labels[i];
+			imux->items[imux->num_items].index =
+				alc880_input_pin_idx(cfg->input_pins[i]);
+			imux->num_items++;
+		}
+	}
+	return 0;
+}
+
+static void alc662_auto_set_output_and_unmute(struct hda_codec *codec,
+					      hda_nid_t nid, int pin_type,
+					      int dac_idx)
+{
+	/* set as output */
+	snd_hda_codec_write(codec, nid, 0,
+			    AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
+	snd_hda_codec_write(codec, nid, 0,
+			    AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
+	/* need the manual connection? */
+	if (alc880_is_multi_pin(nid)) {
+		struct alc_spec *spec = codec->spec;
+		int idx = alc880_multi_pin_idx(nid);
+		snd_hda_codec_write(codec, alc880_idx_to_selector(idx), 0,
+				    AC_VERB_SET_CONNECT_SEL,
+				    alc880_dac_to_idx(spec->multiout.dac_nids[dac_idx]));
+	}
+}
+
+static void alc662_auto_init_multi_out(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	int i;
+
+	for (i = 0; i <= HDA_SIDE; i++) {
+		hda_nid_t nid = spec->autocfg.line_out_pins[i];
+		int pin_type = get_pin_type(spec->autocfg.line_out_type);
+		if (nid)
+			alc662_auto_set_output_and_unmute(codec, nid, pin_type,
+							  i);
+	}
+}
+
+static void alc662_auto_init_hp_out(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	hda_nid_t pin;
+
+	pin = spec->autocfg.hp_pins[0];
+	if (pin) /* connect to front */
+		/* use dac 0 */
+		alc662_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
+}
+
+#define alc662_is_input_pin(nid)	alc880_is_input_pin(nid)
+#define ALC662_PIN_CD_NID		ALC880_PIN_CD_NID
+
+static void alc662_auto_init_analog_input(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	int i;
+
+	for (i = 0; i < AUTO_PIN_LAST; i++) {
+		hda_nid_t nid = spec->autocfg.input_pins[i];
+		if (alc662_is_input_pin(nid)) {
+			snd_hda_codec_write(codec, nid, 0,
+					    AC_VERB_SET_PIN_WIDGET_CONTROL,
+					    (i <= AUTO_PIN_FRONT_MIC ?
+					     PIN_VREF80 : PIN_IN));
+			if (nid != ALC662_PIN_CD_NID)
+				snd_hda_codec_write(codec, nid, 0,
+						    AC_VERB_SET_AMP_GAIN_MUTE,
+						    AMP_OUT_MUTE);
+		}
+	}
+}
+
+static int alc662_parse_auto_config(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	int err;
+	static hda_nid_t alc662_ignore[] = { 0x1d, 0 };
+
+	err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
+					   alc662_ignore);
+	if (err < 0)
+		return err;
+	if (!spec->autocfg.line_outs)
+		return 0; /* can't find valid BIOS pin config */
+
+	err = alc880_auto_fill_dac_nids(spec, &spec->autocfg);
+	if (err < 0)
+		return err;
+	err = alc662_auto_create_multi_out_ctls(spec, &spec->autocfg);
+	if (err < 0)
+		return err;
+	err = alc662_auto_create_extra_out(spec,
+					   spec->autocfg.speaker_pins[0],
+					   "Speaker");
+	if (err < 0)
+		return err;
+	err = alc662_auto_create_extra_out(spec, spec->autocfg.hp_pins[0],
+					   "Headphone");
+	if (err < 0)
+		return err;
+	err = alc662_auto_create_analog_input_ctls(spec, &spec->autocfg);
+	if (err < 0)
+		return err;
+
+	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
+
+	if (spec->autocfg.dig_out_pin)
+		spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;
+
+	if (spec->kctl_alloc)
+		spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
+
+	spec->num_mux_defs = 1;
+	spec->input_mux = &spec->private_imux;
+	
+	if (err < 0)
+		return err;
+	else if (err > 0)
+		/* hack - override the init verbs */
+		spec->init_verbs[0] = alc662_auto_init_verbs;
+	spec->mixers[spec->num_mixers] = alc662_capture_mixer;
+	spec->num_mixers++;
+	return err;
+}
+
+/* additional initialization for auto-configuration model */
+static void alc662_auto_init(struct hda_codec *codec)
+{
+	alc662_auto_init_multi_out(codec);
+	alc662_auto_init_hp_out(codec);
+	alc662_auto_init_analog_input(codec);
+}
+
+static int patch_alc662(struct hda_codec *codec)
+{
+	struct alc_spec *spec;
+	int err, board_config;
+
+	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
+	if (!spec)
+		return -ENOMEM;
+
+	codec->spec = spec;
+
+	board_config = snd_hda_check_board_config(codec, ALC662_MODEL_LAST,
+						  alc662_models,
+			  	                  alc662_cfg_tbl);
+	if (board_config < 0) {
+		printk(KERN_INFO "hda_codec: Unknown model for ALC662, "
+		       "trying auto-probe from BIOS...\n");
+		board_config = ALC662_AUTO;
+	}
+
+	if (board_config == ALC662_AUTO) {
+		/* automatic parse from the BIOS config */
+		err = alc662_parse_auto_config(codec);
+		if (err < 0) {
+			alc_free(codec);
+			return err;
+		} else if (err) {
+			printk(KERN_INFO
+			       "hda_codec: Cannot set up configuration "
+			       "from BIOS.  Using base mode...\n");
+			board_config = ALC662_3ST_2ch_DIG;
+		}
+	}
+
+	if (board_config != ALC662_AUTO)
+		setup_preset(spec, &alc662_presets[board_config]);
+
+	spec->stream_name_analog = "ALC662 Analog";
+	spec->stream_analog_playback = &alc662_pcm_analog_playback;
+	spec->stream_analog_capture = &alc662_pcm_analog_capture;
+
+	spec->stream_name_digital = "ALC662 Digital";
+	spec->stream_digital_playback = &alc662_pcm_digital_playback;
+	spec->stream_digital_capture = &alc662_pcm_digital_capture;
+
+	if (!spec->adc_nids && spec->input_mux) {
+		spec->adc_nids = alc662_adc_nids;
+		spec->num_adc_nids = ARRAY_SIZE(alc662_adc_nids);
+	}
+
+	codec->patch_ops = alc_patch_ops;
+	if (board_config == ALC662_AUTO)
+		spec->init_hook = alc662_auto_init;
+
+	return 0;
+}
+
+/*
  * patch entries
  */
 struct hda_codec_preset snd_hda_preset_realtek[] = {
 	{ .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
 	{ .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 },
 	{ .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
-		.patch = patch_alc861 },
+	  .patch = patch_alc861 },
 	{ .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd },
 	{ .id = 0x10ec0861, .name = "ALC861", .patch = patch_alc861 },
 	{ .id = 0x10ec0862, .name = "ALC861-VD", .patch = patch_alc861vd },
+	{ .id = 0x10ec0662, .rev = 0x100002, .name = "ALC662 rev2",
+	  .patch = patch_alc883 },
+	{ .id = 0x10ec0662, .rev = 0x100101, .name = "ALC662 rev1",
+	  .patch = patch_alc662 },
 	{ .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
 	{ .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
 	{ .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc883 },
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index c94291bc5367..93ae9c250767 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -62,6 +62,7 @@ enum {
 	STAC_MACBOOK,
 	STAC_MACBOOK_PRO_V1,
 	STAC_MACBOOK_PRO_V2,
+	STAC_IMAC_INTEL,
 	STAC_922X_MODELS
 };
 
@@ -175,8 +176,8 @@ static hda_nid_t stac9205_mux_nids[2] = {
         0x19, 0x1a
 };
 
-static hda_nid_t stac9205_dmic_nids[3] = {
-        0x17, 0x18, 0
+static hda_nid_t stac9205_dmic_nids[2] = {
+        0x17, 0x18,
 };
 
 static hda_nid_t stac9200_pin_nids[8] = {
@@ -524,12 +525,6 @@ static unsigned int d945gtp5_pin_configs[10] = {
 	0x02a19320, 0x40000100,
 };
 
-static unsigned int macbook_pin_configs[10] = {
-	0x0321e230, 0x03a1e020, 0x400000fd, 0x9017e110,
-	0x400000fe, 0x0381e021, 0x1345e240, 0x13c5e22e,
-	0x400000fc, 0x400000fb,
-};
-
 static unsigned int macbook_pro_v1_pin_configs[10] = {
 	0x0321e230, 0x03a1e020, 0x9017e110, 0x01014010,
 	0x01a19021, 0x0381e021, 0x1345e240, 0x13c5e22e,
@@ -542,14 +537,21 @@ static unsigned int macbook_pro_v2_pin_configs[10] = {
 	0x400000fc, 0x400000fb,
 };
 
+static unsigned int imac_intel_pin_configs[10] = {
+	0x0121e230, 0x90a70120, 0x9017e110, 0x400000fe,
+	0x400000fd, 0x0181e021, 0x1145e040, 0x400000fa,
+	0x400000fc, 0x400000fb,
+};
+
 static unsigned int *stac922x_brd_tbl[STAC_922X_MODELS] = {
 	[STAC_D945_REF] = ref922x_pin_configs,
 	[STAC_D945GTP3] = d945gtp3_pin_configs,
 	[STAC_D945GTP5] = d945gtp5_pin_configs,
-	[STAC_MACMINI] = d945gtp5_pin_configs,
-	[STAC_MACBOOK] = macbook_pin_configs,
+	[STAC_MACMINI] = macbook_pro_v1_pin_configs,
+	[STAC_MACBOOK] = macbook_pro_v1_pin_configs,
 	[STAC_MACBOOK_PRO_V1] = macbook_pro_v1_pin_configs,
 	[STAC_MACBOOK_PRO_V2] = macbook_pro_v2_pin_configs,
+	[STAC_IMAC_INTEL] = imac_intel_pin_configs,
 };
 
 static const char *stac922x_models[STAC_922X_MODELS] = {
@@ -560,6 +562,7 @@ static const char *stac922x_models[STAC_922X_MODELS] = {
 	[STAC_MACBOOK]	= "macbook",
 	[STAC_MACBOOK_PRO_V1]	= "macbook-pro-v1",
 	[STAC_MACBOOK_PRO_V2]	= "macbook-pro",
+	[STAC_IMAC_INTEL] = "imac-intel",
 };
 
 static struct snd_pci_quirk stac922x_cfg_tbl[] = {
@@ -820,6 +823,17 @@ static int stac92xx_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
 	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
 }
 
+static int stac92xx_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
+					 struct hda_codec *codec,
+					 unsigned int stream_tag,
+					 unsigned int format,
+					 struct snd_pcm_substream *substream)
+{
+	struct sigmatel_spec *spec = codec->spec;
+	return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
+					     stream_tag, format, substream);
+}
+
 
 /*
  * Analog capture callbacks
@@ -854,7 +868,8 @@ static struct hda_pcm_stream stac92xx_pcm_digital_playback = {
 	/* NID is set in stac92xx_build_pcms */
 	.ops = {
 		.open = stac92xx_dig_playback_pcm_open,
-		.close = stac92xx_dig_playback_pcm_close
+		.close = stac92xx_dig_playback_pcm_close,
+		.prepare = stac92xx_dig_playback_pcm_prepare
 	},
 };
 
@@ -1055,11 +1070,23 @@ static int stac92xx_add_control(struct sigmatel_spec *spec, int type, const char
 static int stac92xx_add_dyn_out_pins(struct hda_codec *codec, struct auto_pin_cfg *cfg)
 {
 	struct sigmatel_spec *spec = codec->spec;
+	unsigned int wcaps, wtype;
+	int i, num_dacs = 0;
+	
+	/* use the wcaps cache to count all DACs available for line-outs */
+	for (i = 0; i < codec->num_nodes; i++) {
+		wcaps = codec->wcaps[i];
+		wtype = (wcaps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
+		if (wtype == AC_WID_AUD_OUT && !(wcaps & AC_WCAP_DIGITAL))
+			num_dacs++;
+	}
 
+	snd_printdd("%s: total dac count=%d\n", __func__, num_dacs);
+	
 	switch (cfg->line_outs) {
 	case 3:
 		/* add line-in as side */
-		if (cfg->input_pins[AUTO_PIN_LINE]) {
+		if (cfg->input_pins[AUTO_PIN_LINE] && num_dacs > 3) {
 			cfg->line_out_pins[3] = cfg->input_pins[AUTO_PIN_LINE];
 			spec->line_switch = 1;
 			cfg->line_outs++;
@@ -1067,12 +1094,12 @@ static int stac92xx_add_dyn_out_pins(struct hda_codec *codec, struct auto_pin_cf
 		break;
 	case 2:
 		/* add line-in as clfe and mic as side */
-		if (cfg->input_pins[AUTO_PIN_LINE]) {
+		if (cfg->input_pins[AUTO_PIN_LINE] && num_dacs > 2) {
 			cfg->line_out_pins[2] = cfg->input_pins[AUTO_PIN_LINE];
 			spec->line_switch = 1;
 			cfg->line_outs++;
 		}
-		if (cfg->input_pins[AUTO_PIN_MIC]) {
+		if (cfg->input_pins[AUTO_PIN_MIC] && num_dacs > 3) {
 			cfg->line_out_pins[3] = cfg->input_pins[AUTO_PIN_MIC];
 			spec->mic_switch = 1;
 			cfg->line_outs++;
@@ -1080,12 +1107,12 @@ static int stac92xx_add_dyn_out_pins(struct hda_codec *codec, struct auto_pin_cf
 		break;
 	case 1:
 		/* add line-in as surr and mic as clfe */
-		if (cfg->input_pins[AUTO_PIN_LINE]) {
+		if (cfg->input_pins[AUTO_PIN_LINE] && num_dacs > 1) {
 			cfg->line_out_pins[1] = cfg->input_pins[AUTO_PIN_LINE];
 			spec->line_switch = 1;
 			cfg->line_outs++;
 		}
-		if (cfg->input_pins[AUTO_PIN_MIC]) {
+		if (cfg->input_pins[AUTO_PIN_MIC] && num_dacs > 2) {
 			cfg->line_out_pins[2] = cfg->input_pins[AUTO_PIN_MIC];
 			spec->mic_switch = 1;
 			cfg->line_outs++;
@@ -1096,33 +1123,76 @@ static int stac92xx_add_dyn_out_pins(struct hda_codec *codec, struct auto_pin_cf
 	return 0;
 }
 
+
+static int is_in_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid)
+{
+	int i;
+	
+	for (i = 0; i < spec->multiout.num_dacs; i++) {
+		if (spec->multiout.dac_nids[i] == nid)
+			return 1;
+	}
+
+	return 0;
+}
+
 /*
- * XXX The line_out pin widget connection list may not be set to the
- * desired DAC nid. This is the case on 927x where ports A and B can
- * be routed to several DACs.
- *
- * This requires an analysis of the line-out/hp pin configuration
- * to provide a best fit for pin/DAC configurations that are routable.
- * For now, 927x DAC4 is not supported and 927x DAC1 output to ports
- * A and B is not supported.
+ * Fill in the dac_nids table from the parsed pin configuration
+ * This function only works when every pin in line_out_pins[]
+ * contains atleast one DAC in its connection list. Some 92xx
+ * codecs are not connected directly to a DAC, such as the 9200
+ * and 9202/925x. For those, dac_nids[] must be hard-coded.
  */
-/* fill in the dac_nids table from the parsed pin configuration */
 static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec,
 				       const struct auto_pin_cfg *cfg)
 {
 	struct sigmatel_spec *spec = codec->spec;
-	hda_nid_t nid;
-	int i;
-
-	/* check the pins hardwired to audio widget */
+	int i, j, conn_len = 0; 
+	hda_nid_t nid, conn[HDA_MAX_CONNECTIONS];
+	unsigned int wcaps, wtype;
+	
 	for (i = 0; i < cfg->line_outs; i++) {
 		nid = cfg->line_out_pins[i];
-		spec->multiout.dac_nids[i] = snd_hda_codec_read(codec, nid, 0,
-					AC_VERB_GET_CONNECT_LIST, 0) & 0xff;
-	}
+		conn_len = snd_hda_get_connections(codec, nid, conn,
+						   HDA_MAX_CONNECTIONS);
+		for (j = 0; j < conn_len; j++) {
+			wcaps = snd_hda_param_read(codec, conn[j],
+						   AC_PAR_AUDIO_WIDGET_CAP);
+			wtype = (wcaps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
+
+			if (wtype != AC_WID_AUD_OUT ||
+			    (wcaps & AC_WCAP_DIGITAL))
+				continue;
+			/* conn[j] is a DAC routed to this line-out */
+			if (!is_in_dac_nids(spec, conn[j]))
+				break;
+		}
+
+		if (j == conn_len) {
+			/* error out, no available DAC found */
+			snd_printk(KERN_ERR
+				   "%s: No available DAC for pin 0x%x\n",
+				   __func__, nid);
+			return -ENODEV;
+		}
 
-	spec->multiout.num_dacs = cfg->line_outs;
+		spec->multiout.dac_nids[i] = conn[j];
+		spec->multiout.num_dacs++;
+		if (conn_len > 1) {
+			/* select this DAC in the pin's input mux */
+			snd_hda_codec_write(codec, nid, 0,
+					    AC_VERB_SET_CONNECT_SEL, j);
+
+		}
+	}
 
+	snd_printd("dac_nids=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
+		   spec->multiout.num_dacs,
+		   spec->multiout.dac_nids[0],
+		   spec->multiout.dac_nids[1],
+		   spec->multiout.dac_nids[2],
+		   spec->multiout.dac_nids[3],
+		   spec->multiout.dac_nids[4]);
 	return 0;
 }
 
@@ -1189,12 +1259,8 @@ static int stac92xx_auto_create_multi_out_ctls(struct sigmatel_spec *spec,
 
 static int check_in_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid)
 {
-	int i;
-
-	for (i = 0; i < spec->multiout.num_dacs; i++) {
-		if (spec->multiout.dac_nids[i] == nid)
-			return 1;
-	}
+	if (is_in_dac_nids(spec, nid))
+		return 1;
 	if (spec->multiout.hp_nid == nid)
 		return 1;
 	return 0;
@@ -1236,12 +1302,10 @@ static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec,
 		add_spec_dacs(spec, nid);
 	}
 	for (i = 0; i < cfg->speaker_outs; i++) {
-		nid = snd_hda_codec_read(codec, cfg->speaker_pins[0], 0,
+		nid = snd_hda_codec_read(codec, cfg->speaker_pins[i], 0,
 					 AC_VERB_GET_CONNECT_LIST, 0) & 0xff;
 		if (check_in_dac_nids(spec, nid))
 			nid = 0;
-		if (check_in_dac_nids(spec, nid))
-			nid = 0;
 		if (! nid)
 			continue;
 		add_spec_dacs(spec, nid);
@@ -1355,7 +1419,7 @@ static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const
 		imux->num_items++;
 	}
 
-	if (imux->num_items == 1) {
+	if (imux->num_items) {
 		/*
 		 * Set the current input for the muxes.
 		 * The STAC9221 has two input muxes with identical source
@@ -1675,8 +1739,12 @@ static void stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid,
 {
 	unsigned int pin_ctl = snd_hda_codec_read(codec, nid,
 			0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00);
-	if (flag == AC_PINCTL_OUT_EN && (pin_ctl & AC_PINCTL_IN_EN))
-		return;
+
+	/* if setting pin direction bits, clear the current
+	   direction bits first */
+	if (flag & (AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN))
+		pin_ctl &= ~(AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN);
+	
 	snd_hda_codec_write(codec, nid, 0,
 			AC_VERB_SET_PIN_WIDGET_CONTROL,
 			pin_ctl | flag);
@@ -1751,6 +1819,7 @@ static int stac92xx_resume(struct hda_codec *codec)
 
 	stac92xx_init(codec);
 	stac92xx_set_config_regs(codec);
+	snd_hda_resume_ctls(codec, spec->mixer);
 	for (i = 0; i < spec->num_mixers; i++)
 		snd_hda_resume_ctls(codec, spec->mixers[i]);
 	if (spec->multiout.dig_out_nid)
@@ -1905,12 +1974,18 @@ static int patch_stac922x(struct hda_codec *codec)
 		 */
 		printk(KERN_INFO "hda_codec: STAC922x, Apple subsys_id=%x\n", codec->subsystem_id);
 		switch (codec->subsystem_id) {
+		case 0x106b0a00: /* MacBook First generatoin */
+			spec->board_config = STAC_MACBOOK;
+			break;
 		case 0x106b0200: /* MacBook Pro first generation */
 			spec->board_config = STAC_MACBOOK_PRO_V1;
 			break;
 		case 0x106b1e00: /* MacBook Pro second generation */
 			spec->board_config = STAC_MACBOOK_PRO_V2;
 			break;
+		case 0x106b0700: /* Intel-based iMac */
+			spec->board_config = STAC_IMAC_INTEL;
+			break;
 		}
 	}
 
@@ -1931,7 +2006,7 @@ static int patch_stac922x(struct hda_codec *codec)
 
 	spec->adc_nids = stac922x_adc_nids;
 	spec->mux_nids = stac922x_mux_nids;
-	spec->num_muxes = 2;
+	spec->num_muxes = ARRAY_SIZE(stac922x_mux_nids);
 	spec->num_dmics = 0;
 
 	spec->init = stac922x_core_init;
@@ -1992,7 +2067,7 @@ static int patch_stac927x(struct hda_codec *codec)
 	case STAC_D965_3ST:
 		spec->adc_nids = stac927x_adc_nids;
 		spec->mux_nids = stac927x_mux_nids;
-		spec->num_muxes = 3;
+		spec->num_muxes = ARRAY_SIZE(stac927x_mux_nids);
 		spec->num_dmics = 0;
 		spec->init = d965_core_init;
 		spec->mixer = stac9227_mixer;
@@ -2000,7 +2075,7 @@ static int patch_stac927x(struct hda_codec *codec)
 	case STAC_D965_5ST:
 		spec->adc_nids = stac927x_adc_nids;
 		spec->mux_nids = stac927x_mux_nids;
-		spec->num_muxes = 3;
+		spec->num_muxes = ARRAY_SIZE(stac927x_mux_nids);
 		spec->num_dmics = 0;
 		spec->init = d965_core_init;
 		spec->mixer = stac9227_mixer;
@@ -2008,7 +2083,7 @@ static int patch_stac927x(struct hda_codec *codec)
 	default:
 		spec->adc_nids = stac927x_adc_nids;
 		spec->mux_nids = stac927x_mux_nids;
-		spec->num_muxes = 3;
+		spec->num_muxes = ARRAY_SIZE(stac927x_mux_nids);
 		spec->num_dmics = 0;
 		spec->init = stac927x_core_init;
 		spec->mixer = stac927x_mixer;
@@ -2067,9 +2142,9 @@ static int patch_stac9205(struct hda_codec *codec)
 
 	spec->adc_nids = stac9205_adc_nids;
 	spec->mux_nids = stac9205_mux_nids;
-	spec->num_muxes = 2;
+	spec->num_muxes = ARRAY_SIZE(stac9205_mux_nids);
 	spec->dmic_nids = stac9205_dmic_nids;
-	spec->num_dmics = 2;
+	spec->num_dmics = ARRAY_SIZE(stac9205_dmic_nids);
 	spec->dmux_nid = 0x1d;
 
 	spec->init = stac9205_core_init;
@@ -2294,6 +2369,7 @@ static struct snd_pci_quirk stac9872_cfg_tbl[] = {
 	SND_PCI_QUIRK(0x104d, 0x81e6, "Sony VAIO F/S", CXD9872RD_VAIO),
 	SND_PCI_QUIRK(0x104d, 0x81ef, "Sony VAIO F/S", CXD9872RD_VAIO),
 	SND_PCI_QUIRK(0x104d, 0x81fd, "Sony VAIO AR", CXD9872AKD_VAIO),
+	SND_PCI_QUIRK(0x104d, 0x8205, "Sony VAIO AR", CXD9872AKD_VAIO),
 	{}
 };
 
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index 2b11ac8689b9..ba32d1e52cb8 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -377,6 +377,17 @@ static int via_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
 	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
 }
 
+static int via_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
+					struct hda_codec *codec,
+					unsigned int stream_tag,
+					unsigned int format,
+					struct snd_pcm_substream *substream)
+{
+	struct via_spec *spec = codec->spec;
+	return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
+					     stream_tag, format, substream);
+}
+
 /*
  * Analog capture
  */
@@ -433,7 +444,8 @@ static struct hda_pcm_stream vt1708_pcm_digital_playback = {
 	/* NID is set in via_build_pcms */
 	.ops = {
 		.open = via_dig_playback_pcm_open,
-		.close = via_dig_playback_pcm_close
+		.close = via_dig_playback_pcm_close,
+		.prepare = via_dig_playback_pcm_prepare
 	},
 };
 
diff --git a/sound/pci/ice1712/amp.c b/sound/pci/ice1712/amp.c
index 6e22d326df32..44bbb630b949 100644
--- a/sound/pci/ice1712/amp.c
+++ b/sound/pci/ice1712/amp.c
@@ -75,7 +75,7 @@ static int __devinit snd_vt1724_amp_add_controls(struct snd_ice1712 *ice)
 
 
 /* entry point */
-const struct snd_ice1712_card_info snd_vt1724_amp_cards[] __devinitdata = {
+struct snd_ice1712_card_info snd_vt1724_amp_cards[] __devinitdata = {
 	{
 		.subvendor = VT1724_SUBDEVICE_AV710,
 		.name = "Chaintech AV-710",
diff --git a/sound/pci/ice1712/amp.h b/sound/pci/ice1712/amp.h
index 7b667bad0c6b..a0fc89b48122 100644
--- a/sound/pci/ice1712/amp.h
+++ b/sound/pci/ice1712/amp.h
@@ -42,7 +42,7 @@
 #define WM_DAC_CTRL	0x02
 #define WM_INT_CTRL	0x03
 
-extern const struct snd_ice1712_card_info  snd_vt1724_amp_cards[];
+extern struct snd_ice1712_card_info  snd_vt1724_amp_cards[];
 
 
 #endif /* __SOUND_AMP_H */
diff --git a/sound/pci/ice1712/aureon.c b/sound/pci/ice1712/aureon.c
index 6941d85dfec9..66bacde1ead3 100644
--- a/sound/pci/ice1712/aureon.c
+++ b/sound/pci/ice1712/aureon.c
@@ -1411,7 +1411,7 @@ static int aureon_oversampling_put(struct snd_kcontrol *kcontrol, struct snd_ctl
  * mixers
  */
 
-static const struct snd_kcontrol_new aureon_dac_controls[] __devinitdata = {
+static struct snd_kcontrol_new aureon_dac_controls[] __devinitdata = {
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "Master Playback Switch",
@@ -1526,7 +1526,7 @@ static const struct snd_kcontrol_new aureon_dac_controls[] __devinitdata = {
 	}
 };
 
-static const struct snd_kcontrol_new wm_controls[] __devinitdata = {
+static struct snd_kcontrol_new wm_controls[] __devinitdata = {
  	{
  		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "PCM Playback Switch",
@@ -1592,7 +1592,7 @@ static const struct snd_kcontrol_new wm_controls[] __devinitdata = {
 	}
 };
 
-static const struct snd_kcontrol_new ac97_controls[] __devinitdata = {
+static struct snd_kcontrol_new ac97_controls[] __devinitdata = {
  	{
  		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "AC97 Playback Switch",
@@ -1697,7 +1697,7 @@ static const struct snd_kcontrol_new ac97_controls[] __devinitdata = {
  	}
 };
 
-static const struct snd_kcontrol_new universe_ac97_controls[] __devinitdata = {
+static struct snd_kcontrol_new universe_ac97_controls[] __devinitdata = {
  	{
  		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "AC97 Playback Switch",
@@ -1829,7 +1829,7 @@ static const struct snd_kcontrol_new universe_ac97_controls[] __devinitdata = {
 
 };
 
-static const struct snd_kcontrol_new cs8415_controls[] __devinitdata = {
+static struct snd_kcontrol_new cs8415_controls[] __devinitdata = {
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH),
@@ -2107,7 +2107,7 @@ static int __devinit aureon_init(struct snd_ice1712 *ice)
  * hence the driver needs to sets up it properly.
  */
 
-static const unsigned char aureon51_eeprom[] __devinitdata = {
+static unsigned char aureon51_eeprom[] __devinitdata = {
 	[ICE_EEP2_SYSCONF]     = 0x0a,	/* clock 512, spdif-in/ADC, 3DACs */
 	[ICE_EEP2_ACLINK]      = 0x80,	/* I2S */
 	[ICE_EEP2_I2S]         = 0xfc,	/* vol, 96k, 24bit, 192k */
@@ -2123,7 +2123,7 @@ static const unsigned char aureon51_eeprom[] __devinitdata = {
 	[ICE_EEP2_GPIO_STATE2] = 0x00,
 };
 
-static const unsigned char aureon71_eeprom[] __devinitdata = {
+static unsigned char aureon71_eeprom[] __devinitdata = {
 	[ICE_EEP2_SYSCONF]     = 0x0b,	/* clock 512, spdif-in/ADC, 4DACs */
 	[ICE_EEP2_ACLINK]      = 0x80,	/* I2S */
 	[ICE_EEP2_I2S]         = 0xfc,	/* vol, 96k, 24bit, 192k */
@@ -2140,7 +2140,7 @@ static const unsigned char aureon71_eeprom[] __devinitdata = {
 };
 #define prodigy71_eeprom aureon71_eeprom
 
-static const unsigned char prodigy71lt_eeprom[] __devinitdata = {
+static unsigned char prodigy71lt_eeprom[] __devinitdata = {
 	[ICE_EEP2_SYSCONF]     = 0x4b,	/* clock 384, spdif-in/ADC, 4DACs */
 	[ICE_EEP2_ACLINK]      = 0x80,	/* I2S */
 	[ICE_EEP2_I2S]         = 0xfc,	/* vol, 96k, 24bit, 192k */
@@ -2158,7 +2158,7 @@ static const unsigned char prodigy71lt_eeprom[] __devinitdata = {
 #define prodigy71xt_eeprom prodigy71lt_eeprom
 
 /* entry point */
-const struct snd_ice1712_card_info snd_vt1724_aureon_cards[] __devinitdata = {
+struct snd_ice1712_card_info snd_vt1724_aureon_cards[] __devinitdata = {
 	{
 		.subvendor = VT1724_SUBDEVICE_AUREON51_SKY,
 		.name = "Terratec Aureon 5.1-Sky",
diff --git a/sound/pci/ice1712/aureon.h b/sound/pci/ice1712/aureon.h
index 79e58e88ed47..c253b8e2c789 100644
--- a/sound/pci/ice1712/aureon.h
+++ b/sound/pci/ice1712/aureon.h
@@ -38,7 +38,7 @@
 #define VT1724_SUBDEVICE_PRODIGY71LT	0x32315441	/* PRODIGY 7.1 LT */
 #define VT1724_SUBDEVICE_PRODIGY71XT	0x36315441	/* PRODIGY 7.1 XT*/
 
-extern const struct snd_ice1712_card_info  snd_vt1724_aureon_cards[];
+extern struct snd_ice1712_card_info  snd_vt1724_aureon_cards[];
 
 /* GPIO bits */
 #define AUREON_CS8415_CS	(1 << 22)
diff --git a/sound/pci/ice1712/delta.c b/sound/pci/ice1712/delta.c
index 3eeb36c6e985..af659800c9b0 100644
--- a/sound/pci/ice1712/delta.c
+++ b/sound/pci/ice1712/delta.c
@@ -416,7 +416,7 @@ static int snd_ice1712_delta1010lt_wordclock_status_get(struct snd_kcontrol *kco
 	return 0;
 }
 
-static const struct snd_kcontrol_new snd_ice1712_delta1010lt_wordclock_status __devinitdata =
+static struct snd_kcontrol_new snd_ice1712_delta1010lt_wordclock_status __devinitdata =
 {
 	.access =	(SNDRV_CTL_ELEM_ACCESS_READ),
 	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -429,7 +429,7 @@ static const struct snd_kcontrol_new snd_ice1712_delta1010lt_wordclock_status __
  * initialize the chips on M-Audio cards
  */
 
-static const struct snd_akm4xxx akm_audiophile __devinitdata = {
+static struct snd_akm4xxx akm_audiophile __devinitdata = {
 	.type = SND_AK4528,
 	.num_adcs = 2,
 	.num_dacs = 2,
@@ -438,7 +438,7 @@ static const struct snd_akm4xxx akm_audiophile __devinitdata = {
 	}
 };
 
-static const struct snd_ak4xxx_private akm_audiophile_priv __devinitdata = {
+static struct snd_ak4xxx_private akm_audiophile_priv __devinitdata = {
 	.caddr = 2,
 	.cif = 0,
 	.data_mask = ICE1712_DELTA_AP_DOUT,
@@ -450,7 +450,7 @@ static const struct snd_ak4xxx_private akm_audiophile_priv __devinitdata = {
 	.mask_flags = 0,
 };
 
-static const struct snd_akm4xxx akm_delta410 __devinitdata = {
+static struct snd_akm4xxx akm_delta410 __devinitdata = {
 	.type = SND_AK4529,
 	.num_adcs = 2,
 	.num_dacs = 8,
@@ -459,7 +459,7 @@ static const struct snd_akm4xxx akm_delta410 __devinitdata = {
 	}
 };
 
-static const struct snd_ak4xxx_private akm_delta410_priv __devinitdata = {
+static struct snd_ak4xxx_private akm_delta410_priv __devinitdata = {
 	.caddr = 0,
 	.cif = 0,
 	.data_mask = ICE1712_DELTA_AP_DOUT,
@@ -471,7 +471,7 @@ static const struct snd_ak4xxx_private akm_delta410_priv __devinitdata = {
 	.mask_flags = 0,
 };
 
-static const struct snd_akm4xxx akm_delta1010lt __devinitdata = {
+static struct snd_akm4xxx akm_delta1010lt __devinitdata = {
 	.type = SND_AK4524,
 	.num_adcs = 8,
 	.num_dacs = 8,
@@ -481,7 +481,7 @@ static const struct snd_akm4xxx akm_delta1010lt __devinitdata = {
 	}
 };
 
-static const struct snd_ak4xxx_private akm_delta1010lt_priv __devinitdata = {
+static struct snd_ak4xxx_private akm_delta1010lt_priv __devinitdata = {
 	.caddr = 2,
 	.cif = 0, /* the default level of the CIF pin from AK4524 */
 	.data_mask = ICE1712_DELTA_1010LT_DOUT,
@@ -493,7 +493,7 @@ static const struct snd_ak4xxx_private akm_delta1010lt_priv __devinitdata = {
 	.mask_flags = 0,
 };
 
-static const struct snd_akm4xxx akm_delta44 __devinitdata = {
+static struct snd_akm4xxx akm_delta44 __devinitdata = {
 	.type = SND_AK4524,
 	.num_adcs = 4,
 	.num_dacs = 4,
@@ -503,7 +503,7 @@ static const struct snd_akm4xxx akm_delta44 __devinitdata = {
 	}
 };
 
-static const struct snd_ak4xxx_private akm_delta44_priv __devinitdata = {
+static struct snd_ak4xxx_private akm_delta44_priv __devinitdata = {
 	.caddr = 2,
 	.cif = 0, /* the default level of the CIF pin from AK4524 */
 	.data_mask = ICE1712_DELTA_CODEC_SERIAL_DATA,
@@ -515,7 +515,7 @@ static const struct snd_ak4xxx_private akm_delta44_priv __devinitdata = {
 	.mask_flags = 0,
 };
 
-static const struct snd_akm4xxx akm_vx442 __devinitdata = {
+static struct snd_akm4xxx akm_vx442 __devinitdata = {
 	.type = SND_AK4524,
 	.num_adcs = 4,
 	.num_dacs = 4,
@@ -525,7 +525,7 @@ static const struct snd_akm4xxx akm_vx442 __devinitdata = {
 	}
 };
 
-static const struct snd_ak4xxx_private akm_vx442_priv __devinitdata = {
+static struct snd_ak4xxx_private akm_vx442_priv __devinitdata = {
 	.caddr = 2,
 	.cif = 0,
 	.data_mask = ICE1712_VX442_DOUT,
@@ -650,15 +650,15 @@ static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice)
  * additional controls for M-Audio cards
  */
 
-static const struct snd_kcontrol_new snd_ice1712_delta1010_wordclock_select __devinitdata =
+static struct snd_kcontrol_new snd_ice1712_delta1010_wordclock_select __devinitdata =
 ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "Word Clock Sync", 0, ICE1712_DELTA_WORD_CLOCK_SELECT, 1, 0);
-static const struct snd_kcontrol_new snd_ice1712_delta1010lt_wordclock_select __devinitdata =
+static struct snd_kcontrol_new snd_ice1712_delta1010lt_wordclock_select __devinitdata =
 ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "Word Clock Sync", 0, ICE1712_DELTA_1010LT_WORDCLOCK, 0, 0);
-static const struct snd_kcontrol_new snd_ice1712_delta1010_wordclock_status __devinitdata =
+static struct snd_kcontrol_new snd_ice1712_delta1010_wordclock_status __devinitdata =
 ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "Word Clock Status", 0, ICE1712_DELTA_WORD_CLOCK_STATUS, 1, SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE);
-static const struct snd_kcontrol_new snd_ice1712_deltadio2496_spdif_in_select __devinitdata =
+static struct snd_kcontrol_new snd_ice1712_deltadio2496_spdif_in_select __devinitdata =
 ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "IEC958 Input Optical", 0, ICE1712_DELTA_SPDIF_INPUT_SELECT, 0, 0);
-static const struct snd_kcontrol_new snd_ice1712_delta_spdif_in_status __devinitdata =
+static struct snd_kcontrol_new snd_ice1712_delta_spdif_in_status __devinitdata =
 ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "Delta IEC958 Input Status", 0, ICE1712_DELTA_SPDIF_IN_STAT, 1, SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE);
 
 
@@ -735,7 +735,7 @@ static int __devinit snd_ice1712_delta_add_controls(struct snd_ice1712 *ice)
 
 
 /* entry point */
-const struct snd_ice1712_card_info snd_ice1712_delta_cards[] __devinitdata = {
+struct snd_ice1712_card_info snd_ice1712_delta_cards[] __devinitdata = {
 	{
 		.subvendor = ICE1712_SUBDEVICE_DELTA1010,
 		.name = "M Audio Delta 1010",
diff --git a/sound/pci/ice1712/delta.h b/sound/pci/ice1712/delta.h
index e47861ccd6e7..2697156607e4 100644
--- a/sound/pci/ice1712/delta.h
+++ b/sound/pci/ice1712/delta.h
@@ -46,7 +46,7 @@
 #define ICE1712_SUBDEVICE_MEDIASTATION	0x694c0100
 
 /* entry point */
-extern const struct snd_ice1712_card_info snd_ice1712_delta_cards[];
+extern struct snd_ice1712_card_info snd_ice1712_delta_cards[];
 
 
 /*
diff --git a/sound/pci/ice1712/ews.c b/sound/pci/ice1712/ews.c
index 9b7ff302c072..b135389fec6c 100644
--- a/sound/pci/ice1712/ews.c
+++ b/sound/pci/ice1712/ews.c
@@ -332,7 +332,7 @@ static void ews88_setup_spdif(struct snd_ice1712 *ice, int rate)
 
 /*
  */
-static const struct snd_akm4xxx akm_ews88mt __devinitdata = {
+static struct snd_akm4xxx akm_ews88mt __devinitdata = {
 	.num_adcs = 8,
 	.num_dacs = 8,
 	.type = SND_AK4524,
@@ -342,7 +342,7 @@ static const struct snd_akm4xxx akm_ews88mt __devinitdata = {
 	}
 };
 
-static const struct snd_ak4xxx_private akm_ews88mt_priv __devinitdata = {
+static struct snd_ak4xxx_private akm_ews88mt_priv __devinitdata = {
 	.caddr = 2,
 	.cif = 1, /* CIF high */
 	.data_mask = ICE1712_EWS88_SERIAL_DATA,
@@ -354,7 +354,7 @@ static const struct snd_ak4xxx_private akm_ews88mt_priv __devinitdata = {
 	.mask_flags = 0,
 };
 
-static const struct snd_akm4xxx akm_ewx2496 __devinitdata = {
+static struct snd_akm4xxx akm_ewx2496 __devinitdata = {
 	.num_adcs = 2,
 	.num_dacs = 2,
 	.type = SND_AK4524,
@@ -363,7 +363,7 @@ static const struct snd_akm4xxx akm_ewx2496 __devinitdata = {
 	}
 };
 
-static const struct snd_ak4xxx_private akm_ewx2496_priv __devinitdata = {
+static struct snd_ak4xxx_private akm_ewx2496_priv __devinitdata = {
 	.caddr = 2,
 	.cif = 1, /* CIF high */
 	.data_mask = ICE1712_EWS88_SERIAL_DATA,
@@ -375,7 +375,7 @@ static const struct snd_ak4xxx_private akm_ewx2496_priv __devinitdata = {
 	.mask_flags = 0,
 };
 
-static const struct snd_akm4xxx akm_6fire __devinitdata = {
+static struct snd_akm4xxx akm_6fire __devinitdata = {
 	.num_adcs = 6,
 	.num_dacs = 6,
 	.type = SND_AK4524,
@@ -384,7 +384,7 @@ static const struct snd_akm4xxx akm_6fire __devinitdata = {
 	}
 };
 
-static const struct snd_ak4xxx_private akm_6fire_priv __devinitdata = {
+static struct snd_ak4xxx_private akm_6fire_priv __devinitdata = {
 	.caddr = 2,
 	.cif = 1, /* CIF high */
 	.data_mask = ICE1712_6FIRE_SERIAL_DATA,
@@ -578,7 +578,7 @@ static int snd_ice1712_ewx_io_sense_put(struct snd_kcontrol *kcontrol, struct sn
 	return val != nval;
 }
 
-static const struct snd_kcontrol_new snd_ice1712_ewx2496_controls[] __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_ewx2496_controls[] __devinitdata = {
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "Input Sensitivity Switch",
@@ -678,7 +678,7 @@ static int snd_ice1712_ews88mt_input_sense_put(struct snd_kcontrol *kcontrol, st
 	return ndata != data;
 }
 
-static const struct snd_kcontrol_new snd_ice1712_ews88mt_input_sense __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_ews88mt_input_sense __devinitdata = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = "Input Sensitivity Switch",
 	.info = snd_ice1712_ewx_io_sense_info,
@@ -687,7 +687,7 @@ static const struct snd_kcontrol_new snd_ice1712_ews88mt_input_sense __devinitda
 	.count = 8,
 };
 
-static const struct snd_kcontrol_new snd_ice1712_ews88mt_output_sense __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_ews88mt_output_sense __devinitdata = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = "Output Sensitivity Switch",
 	.info = snd_ice1712_ewx_io_sense_info,
@@ -769,7 +769,7 @@ static int snd_ice1712_ews88d_control_put(struct snd_kcontrol *kcontrol, struct
   .private_value = xshift | (xinvert << 8),\
 }
 
-static const struct snd_kcontrol_new snd_ice1712_ews88d_controls[] __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_ews88d_controls[] __devinitdata = {
 	EWS88D_CONTROL(SNDRV_CTL_ELEM_IFACE_MIXER, "IEC958 Input Optical", 0, 1, 0), /* inverted */
 	EWS88D_CONTROL(SNDRV_CTL_ELEM_IFACE_MIXER, "ADAT Output Optical", 1, 0, 0),
 	EWS88D_CONTROL(SNDRV_CTL_ELEM_IFACE_MIXER, "ADAT External Master Clock", 2, 0, 0),
@@ -909,7 +909,7 @@ static int snd_ice1712_6fire_select_input_put(struct snd_kcontrol *kcontrol, str
   .private_value = xshift | (xinvert << 8),\
 }
 
-static const struct snd_kcontrol_new snd_ice1712_6fire_controls[] __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_6fire_controls[] __devinitdata = {
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "Analog Input Select",
@@ -989,7 +989,7 @@ static int __devinit snd_ice1712_ews_add_controls(struct snd_ice1712 *ice)
 
 
 /* entry point */
-const struct snd_ice1712_card_info snd_ice1712_ews_cards[] __devinitdata = {
+struct snd_ice1712_card_info snd_ice1712_ews_cards[] __devinitdata = {
 	{
 		.subvendor = ICE1712_SUBDEVICE_EWX2496,
 		.name = "TerraTec EWX24/96",
diff --git a/sound/pci/ice1712/ews.h b/sound/pci/ice1712/ews.h
index df449b4741f6..a12a0b053558 100644
--- a/sound/pci/ice1712/ews.h
+++ b/sound/pci/ice1712/ews.h
@@ -40,7 +40,7 @@
 #define ICE1712_SUBDEVICE_PHASE88	0x3b155111
 
 /* entry point */
-extern const struct snd_ice1712_card_info snd_ice1712_ews_cards[];
+extern struct snd_ice1712_card_info snd_ice1712_ews_cards[];
 
 
 /* TerraTec EWX 24/96 configuration definitions */
diff --git a/sound/pci/ice1712/hoontech.c b/sound/pci/ice1712/hoontech.c
index df97313aaf83..8203562ef7e7 100644
--- a/sound/pci/ice1712/hoontech.c
+++ b/sound/pci/ice1712/hoontech.c
@@ -239,7 +239,7 @@ static void stdsp24_ak4524_lock(struct snd_akm4xxx *ak, int chip)
 static int __devinit snd_ice1712_value_init(struct snd_ice1712 *ice)
 {
 	/* Hoontech STDSP24 with modified hardware */
-	static const struct snd_akm4xxx akm_stdsp24_mv __devinitdata = {
+	static struct snd_akm4xxx akm_stdsp24_mv __devinitdata = {
 		.num_adcs = 2,
 		.num_dacs = 2,
 		.type = SND_AK4524,
@@ -248,7 +248,7 @@ static int __devinit snd_ice1712_value_init(struct snd_ice1712 *ice)
 		}
 	};
 
-	static const struct snd_ak4xxx_private akm_stdsp24_mv_priv __devinitdata = {
+	static struct snd_ak4xxx_private akm_stdsp24_mv_priv __devinitdata = {
 		.caddr = 2,
 		.cif = 1, /* CIF high */
 		.data_mask = ICE1712_STDSP24_SERIAL_DATA,
@@ -298,7 +298,7 @@ static int __devinit snd_ice1712_ez8_init(struct snd_ice1712 *ice)
 
 
 /* entry point */
-const struct snd_ice1712_card_info snd_ice1712_hoontech_cards[] __devinitdata = {
+struct snd_ice1712_card_info snd_ice1712_hoontech_cards[] __devinitdata = {
 	{
 		.subvendor = ICE1712_SUBDEVICE_STDSP24,
 		.name = "Hoontech SoundTrack Audio DSP24",
diff --git a/sound/pci/ice1712/hoontech.h b/sound/pci/ice1712/hoontech.h
index b62d6e4f6c71..1ee538b20fbf 100644
--- a/sound/pci/ice1712/hoontech.h
+++ b/sound/pci/ice1712/hoontech.h
@@ -35,7 +35,7 @@
 #define ICE1712_SUBDEVICE_STDSP24_MEDIA7_1	0x16141217	/* Hoontech ST Audio DSP24 Media 7.1 */
 #define ICE1712_SUBDEVICE_EVENT_EZ8		0x00010001	/* A dummy id for EZ8 */
 
-extern const struct snd_ice1712_card_info snd_ice1712_hoontech_cards[];
+extern struct snd_ice1712_card_info snd_ice1712_hoontech_cards[];
 
 
 /* Hoontech SoundTrack Audio DSP 24 GPIO definitions */
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c
index 830a1bbd7110..6630a0ae9527 100644
--- a/sound/pci/ice1712/ice1712.c
+++ b/sound/pci/ice1712/ice1712.c
@@ -287,7 +287,7 @@ static int snd_ice1712_digmix_route_ac97_put(struct snd_kcontrol *kcontrol, stru
 	return val != nval;
 }
 
-static const struct snd_kcontrol_new snd_ice1712_mixer_digmix_route_ac97 __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_mixer_digmix_route_ac97 __devinitdata = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = "Digital Mixer To AC97",
 	.info = snd_ice1712_digmix_route_ac97_info,
@@ -977,11 +977,9 @@ static int snd_ice1712_pro_trigger(struct snd_pcm_substream *substream,
 	{
 		unsigned int what = 0;
 		unsigned int old;
-		struct list_head *pos;
 		struct snd_pcm_substream *s;
 
-		snd_pcm_group_for_each(pos, substream) {
-			s = snd_pcm_group_substream_entry(pos);
+		snd_pcm_group_for_each_entry(s, substream) {
 			if (s == ice->playback_pro_substream) {
 				what |= ICE1712_PLAYBACK_START;
 				snd_pcm_trigger_done(s, substream);
@@ -1380,7 +1378,7 @@ static int snd_ice1712_pro_mixer_volume_put(struct snd_kcontrol *kcontrol, struc
 
 static const DECLARE_TLV_DB_SCALE(db_scale_playback, -14400, 150, 0);
 
-static const struct snd_kcontrol_new snd_ice1712_multi_playback_ctrls[] __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_multi_playback_ctrls[] __devinitdata = {
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "Multi Playback Switch",
@@ -1404,7 +1402,7 @@ static const struct snd_kcontrol_new snd_ice1712_multi_playback_ctrls[] __devini
 	},
 };
 
-static const struct snd_kcontrol_new snd_ice1712_multi_capture_analog_switch __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_multi_capture_analog_switch __devinitdata = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = "H/W Multi Capture Switch",
 	.info = snd_ice1712_pro_mixer_switch_info,
@@ -1413,7 +1411,7 @@ static const struct snd_kcontrol_new snd_ice1712_multi_capture_analog_switch __d
 	.private_value = 10,
 };
 
-static const struct snd_kcontrol_new snd_ice1712_multi_capture_spdif_switch __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_multi_capture_spdif_switch __devinitdata = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = SNDRV_CTL_NAME_IEC958("Multi ",CAPTURE,SWITCH),
 	.info = snd_ice1712_pro_mixer_switch_info,
@@ -1423,7 +1421,7 @@ static const struct snd_kcontrol_new snd_ice1712_multi_capture_spdif_switch __de
 	.count = 2,
 };
 
-static const struct snd_kcontrol_new snd_ice1712_multi_capture_analog_volume __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_multi_capture_analog_volume __devinitdata = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
 		   SNDRV_CTL_ELEM_ACCESS_TLV_READ),
@@ -1435,7 +1433,7 @@ static const struct snd_kcontrol_new snd_ice1712_multi_capture_analog_volume __d
 	.tlv = { .p = db_scale_playback }
 };
 
-static const struct snd_kcontrol_new snd_ice1712_multi_capture_spdif_volume __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_multi_capture_spdif_volume __devinitdata = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = SNDRV_CTL_NAME_IEC958("Multi ",CAPTURE,VOLUME),
 	.info = snd_ice1712_pro_mixer_volume_info,
@@ -1627,7 +1625,7 @@ static int snd_ice1712_eeprom_get(struct snd_kcontrol *kcontrol,
 	return 0;
 }
 
-static const struct snd_kcontrol_new snd_ice1712_eeprom __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_eeprom __devinitdata = {
 	.iface = SNDRV_CTL_ELEM_IFACE_CARD,
 	.name = "ICE1712 EEPROM",
 	.access = SNDRV_CTL_ELEM_ACCESS_READ,
@@ -1663,7 +1661,7 @@ static int snd_ice1712_spdif_default_put(struct snd_kcontrol *kcontrol,
 	return 0;
 }
 
-static const struct snd_kcontrol_new snd_ice1712_spdif_default __devinitdata =
+static struct snd_kcontrol_new snd_ice1712_spdif_default __devinitdata =
 {
 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
 	.name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
@@ -1714,7 +1712,7 @@ static int snd_ice1712_spdif_maskp_get(struct snd_kcontrol *kcontrol,
 	return 0;
 }
 
-static const struct snd_kcontrol_new snd_ice1712_spdif_maskc __devinitdata =
+static struct snd_kcontrol_new snd_ice1712_spdif_maskc __devinitdata =
 {
 	.access =	SNDRV_CTL_ELEM_ACCESS_READ,
 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
@@ -1723,7 +1721,7 @@ static const struct snd_kcontrol_new snd_ice1712_spdif_maskc __devinitdata =
 	.get =		snd_ice1712_spdif_maskc_get,
 };
 
-static const struct snd_kcontrol_new snd_ice1712_spdif_maskp __devinitdata =
+static struct snd_kcontrol_new snd_ice1712_spdif_maskp __devinitdata =
 {
 	.access =	SNDRV_CTL_ELEM_ACCESS_READ,
 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
@@ -1750,7 +1748,7 @@ static int snd_ice1712_spdif_stream_put(struct snd_kcontrol *kcontrol,
 	return 0;
 }
 
-static const struct snd_kcontrol_new snd_ice1712_spdif_stream __devinitdata =
+static struct snd_kcontrol_new snd_ice1712_spdif_stream __devinitdata =
 {
 	.access =	(SNDRV_CTL_ELEM_ACCESS_READWRITE |
 			 SNDRV_CTL_ELEM_ACCESS_INACTIVE),
@@ -1891,7 +1889,7 @@ static int snd_ice1712_pro_internal_clock_put(struct snd_kcontrol *kcontrol,
 	return change;
 }
 
-static const struct snd_kcontrol_new snd_ice1712_pro_internal_clock __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_pro_internal_clock __devinitdata = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = "Multi Track Internal Clock",
 	.info = snd_ice1712_pro_internal_clock_info,
@@ -1962,7 +1960,7 @@ static int snd_ice1712_pro_internal_clock_default_put(struct snd_kcontrol *kcont
 	return change;
 }
 
-static const struct snd_kcontrol_new snd_ice1712_pro_internal_clock_default __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_pro_internal_clock_default __devinitdata = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = "Multi Track Internal Clock Default",
 	.info = snd_ice1712_pro_internal_clock_default_info,
@@ -2001,7 +1999,7 @@ static int snd_ice1712_pro_rate_locking_put(struct snd_kcontrol *kcontrol,
 	return change;
 }
 
-static const struct snd_kcontrol_new snd_ice1712_pro_rate_locking __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_pro_rate_locking __devinitdata = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = "Multi Track Rate Locking",
 	.info = snd_ice1712_pro_rate_locking_info,
@@ -2040,7 +2038,7 @@ static int snd_ice1712_pro_rate_reset_put(struct snd_kcontrol *kcontrol,
 	return change;
 }
 
-static const struct snd_kcontrol_new snd_ice1712_pro_rate_reset __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_pro_rate_reset __devinitdata = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = "Multi Track Rate Reset",
 	.info = snd_ice1712_pro_rate_reset_info,
@@ -2207,7 +2205,7 @@ static int snd_ice1712_pro_route_spdif_put(struct snd_kcontrol *kcontrol,
 	return change;
 }
 
-static const struct snd_kcontrol_new snd_ice1712_mixer_pro_analog_route __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_mixer_pro_analog_route __devinitdata = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = "H/W Playback Route",
 	.info = snd_ice1712_pro_route_info,
@@ -2215,7 +2213,7 @@ static const struct snd_kcontrol_new snd_ice1712_mixer_pro_analog_route __devini
 	.put = snd_ice1712_pro_route_analog_put,
 };
 
-static const struct snd_kcontrol_new snd_ice1712_mixer_pro_spdif_route __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_mixer_pro_spdif_route __devinitdata = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Route",
 	.info = snd_ice1712_pro_route_info,
@@ -2257,7 +2255,7 @@ static int snd_ice1712_pro_volume_rate_put(struct snd_kcontrol *kcontrol,
 	return change;
 }
 
-static const struct snd_kcontrol_new snd_ice1712_mixer_pro_volume_rate __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_mixer_pro_volume_rate __devinitdata = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = "Multi Track Volume Rate",
 	.info = snd_ice1712_pro_volume_rate_info,
@@ -2290,7 +2288,7 @@ static int snd_ice1712_pro_peak_get(struct snd_kcontrol *kcontrol,
 	return 0;
 }
 
-static const struct snd_kcontrol_new snd_ice1712_mixer_pro_peak __devinitdata = {
+static struct snd_kcontrol_new snd_ice1712_mixer_pro_peak __devinitdata = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = "Multi Track Peak",
 	.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
@@ -2305,7 +2303,7 @@ static const struct snd_kcontrol_new snd_ice1712_mixer_pro_peak __devinitdata =
 /*
  * list of available boards
  */
-static const struct snd_ice1712_card_info *card_tables[] __devinitdata = {
+static struct snd_ice1712_card_info *card_tables[] __devinitdata = {
 	snd_ice1712_hoontech_cards,
 	snd_ice1712_delta_cards,
 	snd_ice1712_ews_cards,
@@ -2329,7 +2327,7 @@ static int __devinit snd_ice1712_read_eeprom(struct snd_ice1712 *ice,
 {
 	int dev = 0xa0;		/* EEPROM device address */
 	unsigned int i, size;
-	const struct snd_ice1712_card_info **tbl, *c;
+	struct snd_ice1712_card_info * const *tbl, *c;
 
 	if (! modelname || ! *modelname) {
 		ice->eeprom.subvendor = 0;
@@ -2658,7 +2656,7 @@ static int __devinit snd_ice1712_create(struct snd_card *card,
  *
  */
 
-static const struct snd_ice1712_card_info no_matched __devinitdata;
+static struct snd_ice1712_card_info no_matched __devinitdata;
 
 static int __devinit snd_ice1712_probe(struct pci_dev *pci,
 				       const struct pci_device_id *pci_id)
@@ -2667,7 +2665,7 @@ static int __devinit snd_ice1712_probe(struct pci_dev *pci,
 	struct snd_card *card;
 	struct snd_ice1712 *ice;
 	int pcm_dev = 0, err;
-	const struct snd_ice1712_card_info **tbl, *c;
+	struct snd_ice1712_card_info * const *tbl, *c;
 
 	if (dev >= SNDRV_CARDS)
 		return -ENODEV;
diff --git a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h
index c3d9feaaf57d..6ac486d9c138 100644
--- a/sound/pci/ice1712/ice1712.h
+++ b/sound/pci/ice1712/ice1712.h
@@ -397,6 +397,9 @@ struct snd_ice1712 {
 			struct ak4114 *ak4114;
 			unsigned int analog: 1;
 		} juli;
+		struct {
+			struct ak4114 *ak4114;
+		} prodigy192;
 	} spec;
 
 };
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
index 1127ebdf5fec..ee620dea7ef3 100644
--- a/sound/pci/ice1712/ice1724.c
+++ b/sound/pci/ice1712/ice1724.c
@@ -337,13 +337,11 @@ static int snd_vt1724_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 	struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
 	unsigned char what;
 	unsigned char old;
-	struct list_head *pos;
 	struct snd_pcm_substream *s;
 
 	what = 0;
-	snd_pcm_group_for_each(pos, substream) {
+	snd_pcm_group_for_each_entry(s, substream) {
 		const struct vt1724_pcm_reg *reg;
-		s = snd_pcm_group_substream_entry(pos);
 		reg = s->runtime->private_data;
 		what |= reg->start;
 		snd_pcm_trigger_done(s, substream);
@@ -1318,7 +1316,7 @@ static int snd_vt1724_eeprom_get(struct snd_kcontrol *kcontrol,
 	return 0;
 }
 
-static const struct snd_kcontrol_new snd_vt1724_eeprom __devinitdata = {
+static struct snd_kcontrol_new snd_vt1724_eeprom __devinitdata = {
 	.iface = SNDRV_CTL_ELEM_IFACE_CARD,
 	.name = "ICE1724 EEPROM",
 	.access = SNDRV_CTL_ELEM_ACCESS_READ,
@@ -1431,7 +1429,7 @@ static int snd_vt1724_spdif_default_put(struct snd_kcontrol *kcontrol,
 	return (val != old);
 }
 
-static const struct snd_kcontrol_new snd_vt1724_spdif_default __devinitdata =
+static struct snd_kcontrol_new snd_vt1724_spdif_default __devinitdata =
 {
 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
 	.name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
@@ -1463,7 +1461,7 @@ static int snd_vt1724_spdif_maskp_get(struct snd_kcontrol *kcontrol,
 	return 0;
 }
 
-static const struct snd_kcontrol_new snd_vt1724_spdif_maskc __devinitdata =
+static struct snd_kcontrol_new snd_vt1724_spdif_maskc __devinitdata =
 {
 	.access =	SNDRV_CTL_ELEM_ACCESS_READ,
 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
@@ -1472,7 +1470,7 @@ static const struct snd_kcontrol_new snd_vt1724_spdif_maskc __devinitdata =
 	.get =		snd_vt1724_spdif_maskc_get,
 };
 
-static const struct snd_kcontrol_new snd_vt1724_spdif_maskp __devinitdata =
+static struct snd_kcontrol_new snd_vt1724_spdif_maskp __devinitdata =
 {
 	.access =	SNDRV_CTL_ELEM_ACCESS_READ,
 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
@@ -1517,7 +1515,7 @@ static int snd_vt1724_spdif_sw_put(struct snd_kcontrol *kcontrol,
 	return old != val;
 }
 
-static const struct snd_kcontrol_new snd_vt1724_spdif_switch __devinitdata =
+static struct snd_kcontrol_new snd_vt1724_spdif_switch __devinitdata =
 {
 	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
 	/* FIXME: the following conflict with IEC958 Playback Route */
@@ -1668,7 +1666,12 @@ static int snd_vt1724_pro_internal_clock_put(struct snd_kcontrol *kcontrol,
 	spin_lock_irq(&ice->reg_lock);
 	oval = inb(ICEMT1724(ice, RATE));
 	if (ucontrol->value.enumerated.item[0] == spdif) {
+		unsigned char i2s_oval;
 		outb(oval | VT1724_SPDIF_MASTER, ICEMT1724(ice, RATE));
+		/* setting 256fs */
+		i2s_oval = inb(ICEMT1724(ice, I2S_FORMAT));
+		outb(i2s_oval & ~VT1724_MT_I2S_MCLK_128X,
+		     ICEMT1724(ice, I2S_FORMAT));
 	} else {
 		rate = rates[ucontrol->value.integer.value[0] % 15];
 		if (rate <= get_max_rate(ice)) {
@@ -1695,7 +1698,7 @@ static int snd_vt1724_pro_internal_clock_put(struct snd_kcontrol *kcontrol,
 	return change;
 }
 
-static const struct snd_kcontrol_new snd_vt1724_pro_internal_clock __devinitdata = {
+static struct snd_kcontrol_new snd_vt1724_pro_internal_clock __devinitdata = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = "Multi Track Internal Clock",
 	.info = snd_vt1724_pro_internal_clock_info,
@@ -1734,7 +1737,7 @@ static int snd_vt1724_pro_rate_locking_put(struct snd_kcontrol *kcontrol,
 	return change;
 }
 
-static const struct snd_kcontrol_new snd_vt1724_pro_rate_locking __devinitdata = {
+static struct snd_kcontrol_new snd_vt1724_pro_rate_locking __devinitdata = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = "Multi Track Rate Locking",
 	.info = snd_vt1724_pro_rate_locking_info,
@@ -1773,7 +1776,7 @@ static int snd_vt1724_pro_rate_reset_put(struct snd_kcontrol *kcontrol,
 	return change;
 }
 
-static const struct snd_kcontrol_new snd_vt1724_pro_rate_reset __devinitdata = {
+static struct snd_kcontrol_new snd_vt1724_pro_rate_reset __devinitdata = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = "Multi Track Rate Reset",
 	.info = snd_vt1724_pro_rate_reset_info,
@@ -1892,7 +1895,7 @@ static int snd_vt1724_pro_route_spdif_put(struct snd_kcontrol *kcontrol,
 			     digital_route_shift(idx));
 }
 
-static const struct snd_kcontrol_new snd_vt1724_mixer_pro_analog_route __devinitdata = {
+static struct snd_kcontrol_new snd_vt1724_mixer_pro_analog_route __devinitdata = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = "H/W Playback Route",
 	.info = snd_vt1724_pro_route_info,
@@ -1900,7 +1903,7 @@ static const struct snd_kcontrol_new snd_vt1724_mixer_pro_analog_route __devinit
 	.put = snd_vt1724_pro_route_analog_put,
 };
 
-static const struct snd_kcontrol_new snd_vt1724_mixer_pro_spdif_route __devinitdata = {
+static struct snd_kcontrol_new snd_vt1724_mixer_pro_spdif_route __devinitdata = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Route",
 	.info = snd_vt1724_pro_route_info,
@@ -1936,7 +1939,7 @@ static int snd_vt1724_pro_peak_get(struct snd_kcontrol *kcontrol,
 	return 0;
 }
 
-static const struct snd_kcontrol_new snd_vt1724_mixer_pro_peak __devinitdata = {
+static struct snd_kcontrol_new snd_vt1724_mixer_pro_peak __devinitdata = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = "Multi Track Peak",
 	.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
@@ -1948,9 +1951,9 @@ static const struct snd_kcontrol_new snd_vt1724_mixer_pro_peak __devinitdata = {
  *
  */
 
-static const struct snd_ice1712_card_info no_matched __devinitdata;
+static struct snd_ice1712_card_info no_matched __devinitdata;
 
-static const struct snd_ice1712_card_info *card_tables[] __devinitdata = {
+static struct snd_ice1712_card_info *card_tables[] __devinitdata = {
 	snd_vt1724_revo_cards,
 	snd_vt1724_amp_cards, 
 	snd_vt1724_aureon_cards,
@@ -2009,7 +2012,7 @@ static int __devinit snd_vt1724_read_eeprom(struct snd_ice1712 *ice,
 {
 	const int dev = 0xa0;		/* EEPROM device address */
 	unsigned int i, size;
-	const struct snd_ice1712_card_info **tbl, *c;
+	struct snd_ice1712_card_info * const *tbl, *c;
 
 	if (! modelname || ! *modelname) {
 		ice->eeprom.subvendor = 0;
@@ -2308,7 +2311,7 @@ static int __devinit snd_vt1724_probe(struct pci_dev *pci,
 	struct snd_card *card;
 	struct snd_ice1712 *ice;
 	int pcm_dev = 0, err;
-	const struct snd_ice1712_card_info **tbl, *c;
+	struct snd_ice1712_card_info * const *tbl, *c;
 
 	if (dev >= SNDRV_CARDS)
 		return -ENODEV;
@@ -2347,6 +2350,14 @@ static int __devinit snd_vt1724_probe(struct pci_dev *pci,
 	}
 	c = &no_matched;
  __found:
+       /*
+        * VT1724 has separate DMAs for the analog and the SPDIF streams while
+        * ICE1712 has only one for both (mixed up).
+        *
+        * Confusingly the analog PCM is named "professional" here because it
+        * was called so in ice1712 driver, and vt1724 driver is derived from
+        * ice1712 driver.
+        */
 
 	if ((err = snd_vt1724_pcm_profi(ice, pcm_dev++)) < 0) {
 		snd_card_free(card);
diff --git a/sound/pci/ice1712/juli.c b/sound/pci/ice1712/juli.c
index d88172fa95da..3d8e74e493d7 100644
--- a/sound/pci/ice1712/juli.c
+++ b/sound/pci/ice1712/juli.c
@@ -125,7 +125,7 @@ static void juli_akm_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate)
 	snd_akm4xxx_reset(ak, 0);
 }
 
-static const struct snd_akm4xxx akm_juli_dac __devinitdata = {
+static struct snd_akm4xxx akm_juli_dac __devinitdata = {
 	.type = SND_AK4358,
 	.num_dacs = 2,
 	.ops = {
@@ -138,7 +138,16 @@ static const struct snd_akm4xxx akm_juli_dac __devinitdata = {
 
 static int __devinit juli_add_controls(struct snd_ice1712 *ice)
 {
-	return snd_ice1712_akm4xxx_build_controls(ice);
+	int err;
+	err = snd_ice1712_akm4xxx_build_controls(ice);
+	if (err < 0)
+		return err;
+	/* only capture SPDIF over AK4114 */
+	err = snd_ak4114_build(ice->spec.juli.ak4114, NULL,
+			       ice->pcm_pro->streams[SNDRV_PCM_STREAM_CAPTURE].substream);
+	if (err < 0)
+		return err;
+	return 0;
 }
 
 /*
@@ -160,13 +169,6 @@ static int __devinit juli_init(struct snd_ice1712 *ice)
 	int err;
 	struct snd_akm4xxx *ak;
 
-#if 0
-	for (err = 0; err < 0x20; err++)
-		juli_ak4114_read(ice, err);
-	juli_ak4114_write(ice, 0, 0x0f);
-	juli_ak4114_read(ice, 0);
-	juli_ak4114_read(ice, 1);
-#endif
 	err = snd_ak4114_create(ice->card,
 				juli_ak4114_read,
 				juli_ak4114_write,
@@ -206,7 +208,7 @@ static int __devinit juli_init(struct snd_ice1712 *ice)
  * hence the driver needs to sets up it properly.
  */
 
-static const unsigned char juli_eeprom[] __devinitdata = {
+static unsigned char juli_eeprom[] __devinitdata = {
 	[ICE_EEP2_SYSCONF]     = 0x20,	/* clock 512, mpu401, 1xADC, 1xDACs */
 	[ICE_EEP2_ACLINK]      = 0x80,	/* I2S */
 	[ICE_EEP2_I2S]         = 0xf8,	/* vol, 96k, 24bit, 192k */
@@ -223,7 +225,7 @@ static const unsigned char juli_eeprom[] __devinitdata = {
 };
 
 /* entry point */
-const struct snd_ice1712_card_info snd_vt1724_juli_cards[] __devinitdata = {
+struct snd_ice1712_card_info snd_vt1724_juli_cards[] __devinitdata = {
 	{
 		.subvendor = VT1724_SUBDEVICE_JULI,
 		.name = "ESI Juli@",
diff --git a/sound/pci/ice1712/juli.h b/sound/pci/ice1712/juli.h
index 1b9294f8bce3..d9f8534fd92e 100644
--- a/sound/pci/ice1712/juli.h
+++ b/sound/pci/ice1712/juli.h
@@ -5,6 +5,6 @@
 
 #define VT1724_SUBDEVICE_JULI		0x31305345	/* Juli@ */
 
-extern const struct snd_ice1712_card_info  snd_vt1724_juli_cards[];
+extern struct snd_ice1712_card_info  snd_vt1724_juli_cards[];
 
 #endif	/* __SOUND_JULI_H */
diff --git a/sound/pci/ice1712/phase.c b/sound/pci/ice1712/phase.c
index 0751718f4d7b..40a9098af777 100644
--- a/sound/pci/ice1712/phase.c
+++ b/sound/pci/ice1712/phase.c
@@ -89,13 +89,13 @@ static const unsigned char wm_vol[256] = {
 #define WM_VOL_MAX	(sizeof(wm_vol) - 1)
 #define WM_VOL_MUTE	0x8000
 
-static const struct snd_akm4xxx akm_phase22 __devinitdata = {
+static struct snd_akm4xxx akm_phase22 __devinitdata = {
 	.type = SND_AK4524,
 	.num_dacs = 2,
 	.num_adcs = 2,
 };
 
-static const struct snd_ak4xxx_private akm_phase22_priv __devinitdata = {
+static struct snd_ak4xxx_private akm_phase22_priv __devinitdata = {
 	.caddr =	2,
 	.cif =		1,
 	.data_mask =	1 << 4,
@@ -152,7 +152,7 @@ static int __devinit phase22_add_controls(struct snd_ice1712 *ice)
 	return 0;
 }
 
-static const unsigned char phase22_eeprom[] __devinitdata = {
+static unsigned char phase22_eeprom[] __devinitdata = {
 	[ICE_EEP2_SYSCONF]     = 0x00,	/* 1xADC, 1xDACs */
 	[ICE_EEP2_ACLINK]      = 0x80,	/* I2S */
 	[ICE_EEP2_I2S]         = 0xf8,	/* vol, 96k, 24bit */
@@ -168,7 +168,7 @@ static const unsigned char phase22_eeprom[] __devinitdata = {
 	[ICE_EEP2_GPIO_STATE2] = 0x00,
 };
 
-static const unsigned char phase28_eeprom[] __devinitdata = {
+static unsigned char phase28_eeprom[] __devinitdata = {
 	[ICE_EEP2_SYSCONF]     = 0x0b,	/* clock 512, spdif-in/ADC, 4DACs */
 	[ICE_EEP2_ACLINK]      = 0x80,	/* I2S */
 	[ICE_EEP2_I2S]         = 0xfc,	/* vol, 96k, 24bit, 192k */
@@ -700,7 +700,7 @@ static int phase28_oversampling_put(struct snd_kcontrol *kcontrol, struct snd_ct
 static const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1);
 static const DECLARE_TLV_DB_SCALE(db_scale_wm_pcm, -6400, 50, 1);
 
-static const struct snd_kcontrol_new phase28_dac_controls[] __devinitdata = {
+static struct snd_kcontrol_new phase28_dac_controls[] __devinitdata = {
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "Master Playback Switch",
@@ -815,7 +815,7 @@ static const struct snd_kcontrol_new phase28_dac_controls[] __devinitdata = {
 	}
 };
 
-static const struct snd_kcontrol_new wm_controls[] __devinitdata = {
+static struct snd_kcontrol_new wm_controls[] __devinitdata = {
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "PCM Playback Switch",
@@ -870,7 +870,7 @@ static int __devinit phase28_add_controls(struct snd_ice1712 *ice)
 	return 0;
 }
 
-const struct snd_ice1712_card_info snd_vt1724_phase_cards[] __devinitdata = {
+struct snd_ice1712_card_info snd_vt1724_phase_cards[] __devinitdata = {
 	{
 		.subvendor = VT1724_SUBDEVICE_PHASE22,
 		.name = "Terratec PHASE 22",
diff --git a/sound/pci/ice1712/phase.h b/sound/pci/ice1712/phase.h
index ad379a99bf92..13e841b55488 100644
--- a/sound/pci/ice1712/phase.h
+++ b/sound/pci/ice1712/phase.h
@@ -31,7 +31,7 @@
 #define VT1724_SUBDEVICE_PHASE28	0x3b154911
 
 /* entry point */
-extern const struct snd_ice1712_card_info snd_vt1724_phase_cards[];
+extern struct snd_ice1712_card_info snd_vt1724_phase_cards[];
 
 /* PHASE28 GPIO bits */
 #define PHASE28_SPI_MISO	(1 << 21)
diff --git a/sound/pci/ice1712/pontis.c b/sound/pci/ice1712/pontis.c
index 9552497f0765..01c69453ddeb 100644
--- a/sound/pci/ice1712/pontis.c
+++ b/sound/pci/ice1712/pontis.c
@@ -571,7 +571,7 @@ static const DECLARE_TLV_DB_SCALE(db_scale_volume, -6400, 50, 1);
  * mixers
  */
 
-static const struct snd_kcontrol_new pontis_controls[] __devinitdata = {
+static struct snd_kcontrol_new pontis_controls[] __devinitdata = {
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
@@ -826,7 +826,7 @@ static int __devinit pontis_init(struct snd_ice1712 *ice)
  * hence the driver needs to sets up it properly.
  */
 
-static const unsigned char pontis_eeprom[] __devinitdata = {
+static unsigned char pontis_eeprom[] __devinitdata = {
 	[ICE_EEP2_SYSCONF]     = 0x08,	/* clock 256, mpu401, spdif-in/ADC, 1DAC */
 	[ICE_EEP2_ACLINK]      = 0x80,	/* I2S */
 	[ICE_EEP2_I2S]         = 0xf8,	/* vol, 96k, 24bit, 192k */
@@ -843,7 +843,7 @@ static const unsigned char pontis_eeprom[] __devinitdata = {
 };
 
 /* entry point */
-const struct snd_ice1712_card_info snd_vt1720_pontis_cards[] __devinitdata = {
+struct snd_ice1712_card_info snd_vt1720_pontis_cards[] __devinitdata = {
 	{
 		.subvendor = VT1720_SUBDEVICE_PONTIS_MS300,
 		.name = "Pontis MS300",
diff --git a/sound/pci/ice1712/pontis.h b/sound/pci/ice1712/pontis.h
index 1a418255c19e..d0d1378b935c 100644
--- a/sound/pci/ice1712/pontis.h
+++ b/sound/pci/ice1712/pontis.h
@@ -28,6 +28,6 @@
 
 #define VT1720_SUBDEVICE_PONTIS_MS300	0x00020002	/* a dummy id for MS300 */
 
-extern const struct snd_ice1712_card_info  snd_vt1720_pontis_cards[];
+extern struct snd_ice1712_card_info  snd_vt1720_pontis_cards[];
 
 #endif /* __SOUND_PONTIS_H */
diff --git a/sound/pci/ice1712/prodigy192.c b/sound/pci/ice1712/prodigy192.c
index 31cc66eb9f8f..f03c02c07743 100644
--- a/sound/pci/ice1712/prodigy192.c
+++ b/sound/pci/ice1712/prodigy192.c
@@ -2,6 +2,37 @@
  *   ALSA driver for ICEnsemble VT1724 (Envy24HT)
  *
  *   Lowlevel functions for AudioTrak Prodigy 192 cards
+ *   Supported IEC958 input from optional MI/ODI/O add-on card.
+ *
+ *   Specifics (SW, HW):
+ *   -------------------
+ *   	* 49.5MHz crystal
+ *   	* SPDIF-OUT on the card:
+ *  	  - coax (through isolation transformer)/toslink supplied by
+ *          74HC04 gates - 3 in parallel
+ *   	  - output switched between on-board CD drive dig-out connector
+ *          and ice1724 SPDTX pin, using 74HC02 NOR gates, controlled
+ *          by GPIO20 (0 = CD dig-out, 1 = SPDTX)
+ *   	* SPDTX goes straight to MI/ODI/O card's SPDIF-OUT coax
+ *
+ *   	* MI/ODI/O card: AK4114 based, used for iec958 input only
+ *   		- toslink input -> RX0
+ *   		- coax input -> RX1
+ *   		- 4wire protocol:
+ *   			AK4114		ICE1724
+ *   			------------------------------
+ * 			CDTO (pin 32) -- GPIO11 pin 86
+ * 			CDTI (pin 33) -- GPIO10 pin 77
+ * 			CCLK (pin 34) -- GPIO9 pin 76
+ * 			CSN  (pin 35) -- GPIO8 pin 75
+ *   		- output data Mode 7 (24bit, I2S, slave)
+ *		- both MCKO1 and MCKO2 of ak4114 are fed to FPGA, which
+ *		  outputs master clock to SPMCLKIN of ice1724.
+ *		  Experimentally I found out that only a combination of
+ *		  OCKS0=1, OCKS1=1 (128fs, 64fs output) and ice1724 -
+ *		  VT1724_MT_I2S_MCLK_128X=0 (256fs input) yields correct
+ *		  sampling rate. That means the the FPGA doubles the
+ *		  MCK01 rate.
  *
  *	Copyright (c) 2003 Takashi Iwai <tiwai@suse.de>
  *      Copyright (c) 2003 Dimitromanolakis Apostolos <apostol@cs.utoronto.ca>
@@ -356,6 +387,47 @@ static int aureon_oversampling_put(struct snd_kcontrol *kcontrol, struct snd_ctl
 	return 0;
 }
 #endif
+static int stac9460_mic_sw_info(struct snd_kcontrol *kcontrol,
+	       			struct snd_ctl_elem_info *uinfo)
+{
+	static char *texts[2] = { "Line In", "Mic" };
+
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = 2;
+
+	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+		uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
+	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+
+        return 0;
+}
+
+
+static int stac9460_mic_sw_get(struct snd_kcontrol *kcontrol,
+	       		struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
+	unsigned char val;
+		
+	val = stac9460_get(ice, STAC946X_GENERAL_PURPOSE);
+	ucontrol->value.enumerated.item[0] = (val >> 7) & 0x1;
+	return 0;
+}
+
+static int stac9460_mic_sw_put(struct snd_kcontrol *kcontrol,
+	       		struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
+	unsigned char new, old;
+	int change;
+	old = stac9460_get(ice, STAC946X_GENERAL_PURPOSE);
+	new = (ucontrol->value.enumerated.item[0] << 7 & 0x80) | (old & ~0x80);
+	change = (new != old);
+	if (change)
+		stac9460_put(ice, STAC946X_GENERAL_PURPOSE, new);
+	return change;
+}
 
 static const DECLARE_TLV_DB_SCALE(db_scale_dac, -19125, 75, 0);
 static const DECLARE_TLV_DB_SCALE(db_scale_adc, 0, 150, 0);
@@ -364,7 +436,7 @@ static const DECLARE_TLV_DB_SCALE(db_scale_adc, 0, 150, 0);
  * mixers
  */
 
-static const struct snd_kcontrol_new stac_controls[] __devinitdata = {
+static struct snd_kcontrol_new stac_controls[] __devinitdata = {
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "Master Playback Switch",
@@ -406,7 +478,7 @@ static const struct snd_kcontrol_new stac_controls[] __devinitdata = {
 	},
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "ADC Switch",
+		.name = "ADC Capture Switch",
 		.count = 1,
 		.info = stac9460_adc_mute_info,
 		.get = stac9460_adc_mute_get,
@@ -417,13 +489,21 @@ static const struct snd_kcontrol_new stac_controls[] __devinitdata = {
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
 			   SNDRV_CTL_ELEM_ACCESS_TLV_READ),
-		.name = "ADC Volume",
+		.name = "ADC Capture Volume",
 		.count = 1,
 		.info = stac9460_adc_vol_info,
 		.get = stac9460_adc_vol_get,
 		.put = stac9460_adc_vol_put,
 		.tlv = { .p = db_scale_adc }
 	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Analog Capture Input",
+		.info = stac9460_mic_sw_info,
+		.get = stac9460_mic_sw_get,
+		.put = stac9460_mic_sw_put,
+
+	},
 #if 0
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -456,19 +536,261 @@ static const struct snd_kcontrol_new stac_controls[] __devinitdata = {
 #endif
 };
 
+
+/* AK4114 - ICE1724 connections on Prodigy192 + MI/ODI/O */
+/* CDTO (pin 32) -- GPIO11 pin 86
+ * CDTI (pin 33) -- GPIO10 pin 77
+ * CCLK (pin 34) -- GPIO9 pin 76
+ * CSN  (pin 35) -- GPIO8 pin 75
+ */
+#define AK4114_ADDR	0x00 /* C1-C0: Chip Address
+			      * (According to datasheet fixed to “00”)
+			      */
+
+/*
+ * 4wire ak4114 protocol - writing data
+ */
+static void write_data(struct snd_ice1712 *ice, unsigned int gpio,
+		       unsigned int data, int idx)
+{
+	for (; idx >= 0; idx--) {
+		/* drop clock */
+		gpio &= ~VT1724_PRODIGY192_CCLK;
+		snd_ice1712_gpio_write(ice, gpio);
+		udelay(1);
+		/* set data */
+		if (data & (1 << idx))
+			gpio |= VT1724_PRODIGY192_CDOUT;
+		else
+			gpio &= ~VT1724_PRODIGY192_CDOUT;
+		snd_ice1712_gpio_write(ice, gpio);
+		udelay(1);
+		/* raise clock */
+		gpio |= VT1724_PRODIGY192_CCLK;
+		snd_ice1712_gpio_write(ice, gpio);
+		udelay(1);
+	}
+}
+
+/*
+ * 4wire ak4114 protocol - reading data
+ */
+static unsigned char read_data(struct snd_ice1712 *ice, unsigned int gpio,
+			       int idx)
+{
+	unsigned char data = 0;
+
+	for (; idx >= 0; idx--) {
+		/* drop clock */
+		gpio &= ~VT1724_PRODIGY192_CCLK;
+		snd_ice1712_gpio_write(ice, gpio);
+		udelay(1);
+		/* read data */
+		if (snd_ice1712_gpio_read(ice) & VT1724_PRODIGY192_CDIN)
+			data |= (1 << idx);
+		udelay(1);
+		/* raise clock */
+		gpio |= VT1724_PRODIGY192_CCLK;
+		snd_ice1712_gpio_write(ice, gpio);
+		udelay(1);
+	}
+	return data;
+}
+/*
+ * 4wire ak4114 protocol - starting sequence
+ */
+static unsigned int prodigy192_4wire_start(struct snd_ice1712 *ice)
+{
+	unsigned int tmp;
+
+	snd_ice1712_save_gpio_status(ice);
+	tmp = snd_ice1712_gpio_read(ice);
+
+	tmp |= VT1724_PRODIGY192_CCLK; /* high at init */
+	tmp &= ~VT1724_PRODIGY192_CS; /* drop chip select */
+	snd_ice1712_gpio_write(ice, tmp);
+	udelay(1);
+	return tmp;
+}
+
+/*
+ * 4wire ak4114 protocol - final sequence
+ */
+static void prodigy192_4wire_finish(struct snd_ice1712 *ice, unsigned int tmp)
+{
+	tmp |= VT1724_PRODIGY192_CS; /* raise chip select */
+	snd_ice1712_gpio_write(ice, tmp);
+	udelay(1);
+	snd_ice1712_restore_gpio_status(ice);
+}
+
+/*
+ * Write data to addr register of ak4114
+ */
+static void prodigy192_ak4114_write(void *private_data, unsigned char addr,
+			       unsigned char data)
+{
+	struct snd_ice1712 *ice = private_data;
+	unsigned int tmp, addrdata;
+	tmp = prodigy192_4wire_start(ice);
+	addrdata = (AK4114_ADDR << 6) | 0x20 | (addr & 0x1f);
+	addrdata = (addrdata << 8) | data;
+	write_data(ice, tmp, addrdata, 15);
+	prodigy192_4wire_finish(ice, tmp);
+}
+
+/*
+ * Read data from addr register of ak4114
+ */
+static unsigned char prodigy192_ak4114_read(void *private_data,
+					    unsigned char addr)
+{
+	struct snd_ice1712 *ice = private_data;
+	unsigned int tmp;
+	unsigned char data;
+
+	tmp = prodigy192_4wire_start(ice);
+	write_data(ice, tmp, (AK4114_ADDR << 6) | (addr & 0x1f), 7);
+	data = read_data(ice, tmp, 7);
+	prodigy192_4wire_finish(ice, tmp);
+	return data;
+}
+
+
+static int ak4114_input_sw_info(struct snd_kcontrol *kcontrol,
+	       			struct snd_ctl_elem_info *uinfo)
+{
+	static char *texts[2] = { "Toslink", "Coax" };
+
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = 2;
+	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+		uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
+	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+        return 0;
+}
+
+
+static int ak4114_input_sw_get(struct snd_kcontrol *kcontrol,
+	       		struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
+	unsigned char val;
+		
+	val = prodigy192_ak4114_read(ice, AK4114_REG_IO1);
+	/* AK4114_IPS0 bit = 0 -> RX0 = Toslink
+	 * AK4114_IPS0 bit = 1 -> RX1 = Coax
+	 */
+	ucontrol->value.enumerated.item[0] = (val & AK4114_IPS0) ? 1 : 0;
+	return 0;
+}
+
+static int ak4114_input_sw_put(struct snd_kcontrol *kcontrol,
+	       		struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
+	unsigned char new, old, itemvalue;
+	int change;
+
+	old = prodigy192_ak4114_read(ice, AK4114_REG_IO1);
+	/* AK4114_IPS0 could be any bit */
+	itemvalue = (ucontrol->value.enumerated.item[0]) ? 0xff : 0x00;
+
+	new = (itemvalue & AK4114_IPS0) | (old & ~AK4114_IPS0);
+	change = (new != old);
+	if (change)
+		prodigy192_ak4114_write(ice, AK4114_REG_IO1, new);
+	return change;
+}
+
+
+static const struct snd_kcontrol_new ak4114_controls[] __devinitdata = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "MIODIO IEC958 Capture Input",
+		.info = ak4114_input_sw_info,
+		.get = ak4114_input_sw_get,
+		.put = ak4114_input_sw_put,
+
+	}
+};
+
+
+static int prodigy192_ak4114_init(struct snd_ice1712 *ice)
+{
+	static const unsigned char ak4114_init_vals[] = {
+		AK4114_RST | AK4114_PWN | AK4114_OCKS0 | AK4114_OCKS1,
+		/* ice1724 expects I2S and provides clock,
+		 * DEM0 disables the deemphasis filter
+		 */
+		AK4114_DIF_I24I2S | AK4114_DEM0 ,
+		AK4114_TX1E,
+		AK4114_EFH_1024 | AK4114_DIT, /* default input RX0 */
+		0,
+		0
+	};
+	static const unsigned char ak4114_init_txcsb[] = {
+		0x41, 0x02, 0x2c, 0x00, 0x00
+	};
+
+	return snd_ak4114_create(ice->card,
+				 prodigy192_ak4114_read,
+				 prodigy192_ak4114_write,
+				 ak4114_init_vals, ak4114_init_txcsb,
+				 ice, &ice->spec.prodigy192.ak4114);
+}
+
 static int __devinit prodigy192_add_controls(struct snd_ice1712 *ice)
 {
 	unsigned int i;
 	int err;
 
 	for (i = 0; i < ARRAY_SIZE(stac_controls); i++) {
-		err = snd_ctl_add(ice->card, snd_ctl_new1(&stac_controls[i], ice));
+		err = snd_ctl_add(ice->card,
+				  snd_ctl_new1(&stac_controls[i], ice));
+		if (err < 0)
+			return err;
+	}
+	if (ice->spec.prodigy192.ak4114) {
+		/* ak4114 is connected */
+		for (i = 0; i < ARRAY_SIZE(ak4114_controls); i++) {
+			err = snd_ctl_add(ice->card,
+					  snd_ctl_new1(&ak4114_controls[i],
+						       ice));
+			if (err < 0)
+				return err;
+		}
+		err = snd_ak4114_build(ice->spec.prodigy192.ak4114,
+				NULL, /* ak4114 in MIO/DI/O handles no IEC958 output */
+				ice->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream);
 		if (err < 0)
 			return err;
 	}
 	return 0;
 }
 
+/*
+ * check for presence of MI/ODI/O add-on card with digital inputs
+ */
+static int prodigy192_miodio_exists(struct snd_ice1712 *ice)
+{
+
+	unsigned char orig_value;
+	const unsigned char test_data = 0xd1;	/* random value */
+	unsigned char addr = AK4114_REG_INT0_MASK; /* random SAFE address */
+	int exists = 0;
+
+	orig_value = prodigy192_ak4114_read(ice, addr);
+	prodigy192_ak4114_write(ice, addr, test_data);
+	if (prodigy192_ak4114_read(ice, addr) == test_data) {
+		/* ak4114 seems to communicate, apparently exists */
+		/* writing back original value */
+		prodigy192_ak4114_write(ice, addr, orig_value);
+		exists = 1;
+	}
+	return exists;
+}
 
 /*
  * initialize the chip
@@ -487,16 +809,30 @@ static int __devinit prodigy192_init(struct snd_ice1712 *ice)
 		(unsigned short)-1
 	};
 	const unsigned short *p;
+	int err = 0;
 
 	/* prodigy 192 */
 	ice->num_total_dacs = 6;
 	ice->num_total_adcs = 2;
+	ice->vt1720 = 0;  /* ice1724, e.g. 23 GPIOs */
 	
 	/* initialize codec */
 	p = stac_inits_prodigy;
 	for (; *p != (unsigned short)-1; p += 2)
 		stac9460_put(ice, p[0], p[1]);
 
+	/* MI/ODI/O add on card with AK4114 */
+	if (prodigy192_miodio_exists(ice)) {
+		err = prodigy192_ak4114_init(ice);
+		/* from this moment if err = 0 then
+		 * ice->spec.prodigy192.ak4114 should not be null
+		 */
+		snd_printdd("AK4114 initialized with status %d\n", err);
+	} else
+		snd_printdd("AK4114 not found\n");
+	if (err < 0)
+		return err;
+
 	return 0;
 }
 
@@ -506,25 +842,31 @@ static int __devinit prodigy192_init(struct snd_ice1712 *ice)
  * hence the driver needs to sets up it properly.
  */
 
-static const unsigned char prodigy71_eeprom[] __devinitdata = {
-	[ICE_EEP2_SYSCONF]     = 0x2b,	/* clock 512, mpu401, spdif-in/ADC, 4DACs */
+static unsigned char prodigy71_eeprom[] __devinitdata = {
+	[ICE_EEP2_SYSCONF]     = 0x6a,	/* 49MHz crystal, mpu401,
+					 * spdif-in+ 1 stereo ADC,
+					 * 3 stereo DACs
+					 */
 	[ICE_EEP2_ACLINK]      = 0x80,	/* I2S */
 	[ICE_EEP2_I2S]         = 0xf8,	/* vol, 96k, 24bit, 192k */
 	[ICE_EEP2_SPDIF]       = 0xc3,	/* out-en, out-int, spdif-in */
 	[ICE_EEP2_GPIO_DIR]    = 0xff,
-	[ICE_EEP2_GPIO_DIR1]   = 0xff,
+	[ICE_EEP2_GPIO_DIR1]   = ~(VT1724_PRODIGY192_CDIN >> 8) ,
 	[ICE_EEP2_GPIO_DIR2]   = 0xbf,
 	[ICE_EEP2_GPIO_MASK]   = 0x00,
 	[ICE_EEP2_GPIO_MASK1]  = 0x00,
 	[ICE_EEP2_GPIO_MASK2]  = 0x00,
 	[ICE_EEP2_GPIO_STATE]  = 0x00,
 	[ICE_EEP2_GPIO_STATE1] = 0x00,
-	[ICE_EEP2_GPIO_STATE2] = 0x00,
+	[ICE_EEP2_GPIO_STATE2] = 0x10,  /* GPIO20: 0 = CD drive dig. input
+					 * passthrough,
+					 * 1 = SPDIF-OUT from ice1724
+					 */
 };
 
 
 /* entry point */
-const struct snd_ice1712_card_info snd_vt1724_prodigy192_cards[] __devinitdata = {
+struct snd_ice1712_card_info snd_vt1724_prodigy192_cards[] __devinitdata = {
 	{
 		.subvendor = VT1724_SUBDEVICE_PRODIGY192VE,
 		.name = "Audiotrak Prodigy 192",
diff --git a/sound/pci/ice1712/prodigy192.h b/sound/pci/ice1712/prodigy192.h
index 2fa2e62b9e04..16a53b459c72 100644
--- a/sound/pci/ice1712/prodigy192.h
+++ b/sound/pci/ice1712/prodigy192.h
@@ -5,7 +5,15 @@
 #define PRODIGY192_STAC9460_ADDR	0x54
 
 #define VT1724_SUBDEVICE_PRODIGY192VE	 0x34495345	/* PRODIGY 192 VE */
+/*
+ *  AudioTrak Prodigy192 GPIO definitions for MI/ODI/O card with
+ *  AK4114 (SPDIF-IN)
+ */
+#define VT1724_PRODIGY192_CS	(1 << 8)	/* GPIO8, pin 75 */
+#define VT1724_PRODIGY192_CCLK	(1 << 9)	/* GPIO9, pin 76 */
+#define VT1724_PRODIGY192_CDOUT	(1 << 10)	/* GPIO10, pin 77 */
+#define VT1724_PRODIGY192_CDIN	(1 << 11)	/* GPIO11, pin 86 */
 
-extern const struct snd_ice1712_card_info  snd_vt1724_prodigy192_cards[];
+extern struct snd_ice1712_card_info  snd_vt1724_prodigy192_cards[];
 
 #endif	/* __SOUND_PRODIGY192_H */
diff --git a/sound/pci/ice1712/revo.c b/sound/pci/ice1712/revo.c
index 025a7e8497c3..690ceb340644 100644
--- a/sound/pci/ice1712/revo.c
+++ b/sound/pci/ice1712/revo.c
@@ -219,7 +219,7 @@ static const struct snd_akm4xxx_adc_channel revo51_adc[] = {
 	},
 };
 
-static const struct snd_akm4xxx akm_revo_front __devinitdata = {
+static struct snd_akm4xxx akm_revo_front __devinitdata = {
 	.type = SND_AK4381,
 	.num_dacs = 2,
 	.ops = {
@@ -228,7 +228,7 @@ static const struct snd_akm4xxx akm_revo_front __devinitdata = {
 	.dac_info = revo71_front,
 };
 
-static const struct snd_ak4xxx_private akm_revo_front_priv __devinitdata = {
+static struct snd_ak4xxx_private akm_revo_front_priv __devinitdata = {
 	.caddr = 1,
 	.cif = 0,
 	.data_mask = VT1724_REVO_CDOUT,
@@ -240,7 +240,7 @@ static const struct snd_ak4xxx_private akm_revo_front_priv __devinitdata = {
 	.mask_flags = 0,
 };
 
-static const struct snd_akm4xxx akm_revo_surround __devinitdata = {
+static struct snd_akm4xxx akm_revo_surround __devinitdata = {
 	.type = SND_AK4355,
 	.idx_offset = 1,
 	.num_dacs = 6,
@@ -250,7 +250,7 @@ static const struct snd_akm4xxx akm_revo_surround __devinitdata = {
 	.dac_info = revo71_surround,
 };
 
-static const struct snd_ak4xxx_private akm_revo_surround_priv __devinitdata = {
+static struct snd_ak4xxx_private akm_revo_surround_priv __devinitdata = {
 	.caddr = 3,
 	.cif = 0,
 	.data_mask = VT1724_REVO_CDOUT,
@@ -262,7 +262,7 @@ static const struct snd_ak4xxx_private akm_revo_surround_priv __devinitdata = {
 	.mask_flags = 0,
 };
 
-static const struct snd_akm4xxx akm_revo51 __devinitdata = {
+static struct snd_akm4xxx akm_revo51 __devinitdata = {
 	.type = SND_AK4358,
 	.num_dacs = 6,
 	.ops = {
@@ -271,7 +271,7 @@ static const struct snd_akm4xxx akm_revo51 __devinitdata = {
 	.dac_info = revo51_dac,
 };
 
-static const struct snd_ak4xxx_private akm_revo51_priv __devinitdata = {
+static struct snd_ak4xxx_private akm_revo51_priv __devinitdata = {
 	.caddr = 2,
 	.cif = 0,
 	.data_mask = VT1724_REVO_CDOUT,
@@ -283,13 +283,13 @@ static const struct snd_ak4xxx_private akm_revo51_priv __devinitdata = {
 	.mask_flags = 0,
 };
 
-static const struct snd_akm4xxx akm_revo51_adc __devinitdata = {
+static struct snd_akm4xxx akm_revo51_adc __devinitdata = {
 	.type = SND_AK5365,
 	.num_adcs = 2,
 	.adc_info = revo51_adc,
 };
 
-static const struct snd_ak4xxx_private akm_revo51_adc_priv __devinitdata = {
+static struct snd_ak4xxx_private akm_revo51_adc_priv __devinitdata = {
 	.caddr = 2,
 	.cif = 0,
 	.data_mask = VT1724_REVO_CDOUT,
@@ -324,7 +324,7 @@ static const struct snd_akm4xxx_dac_channel ap192_dac[] = {
 	AK_DAC("PCM Playback Volume", 2)
 };
 
-static const struct snd_akm4xxx akm_ap192 __devinitdata = {
+static struct snd_akm4xxx akm_ap192 __devinitdata = {
 	.type = SND_AK4358,
 	.num_dacs = 2,
 	.ops = {
@@ -333,7 +333,7 @@ static const struct snd_akm4xxx akm_ap192 __devinitdata = {
 	.dac_info = ap192_dac,
 };
 
-static const struct snd_ak4xxx_private akm_ap192_priv __devinitdata = {
+static struct snd_ak4xxx_private akm_ap192_priv __devinitdata = {
 	.caddr = 2,
 	.cif = 0,
 	.data_mask = VT1724_REVO_CDOUT,
@@ -405,7 +405,7 @@ static unsigned char read_data(struct snd_ice1712 *ice, unsigned int gpio,
 	return data;
 }
 
-static unsigned char ap192_4wire_start(struct snd_ice1712 *ice)
+static unsigned int ap192_4wire_start(struct snd_ice1712 *ice)
 {
 	unsigned int tmp;
 
@@ -454,7 +454,7 @@ static unsigned char ap192_ak4114_read(void *private_data, unsigned char addr)
 	return data;
 }
 
-static int ap192_ak4114_init(struct snd_ice1712 *ice)
+static int __devinit ap192_ak4114_init(struct snd_ice1712 *ice)
 {
 	static const unsigned char ak4114_init_vals[] = {
 		AK4114_RST | AK4114_PWN | AK4114_OCKS0 | AK4114_OCKS1,
@@ -582,7 +582,7 @@ static int __devinit revo_add_controls(struct snd_ice1712 *ice)
 }
 
 /* entry point */
-const struct snd_ice1712_card_info snd_vt1724_revo_cards[] __devinitdata = {
+struct snd_ice1712_card_info snd_vt1724_revo_cards[] __devinitdata = {
 	{
 		.subvendor = VT1724_SUBDEVICE_REVOLUTION71,
 		.name = "M Audio Revolution-7.1",
diff --git a/sound/pci/ice1712/revo.h b/sound/pci/ice1712/revo.h
index 2a24488fad80..a3ba425911cc 100644
--- a/sound/pci/ice1712/revo.h
+++ b/sound/pci/ice1712/revo.h
@@ -34,7 +34,7 @@
 #define VT1724_SUBDEVICE_AUDIOPHILE192	0x12143236
 
 /* entry point */
-extern const struct snd_ice1712_card_info snd_vt1724_revo_cards[];
+extern struct snd_ice1712_card_info snd_vt1724_revo_cards[];
 
 
 /*
diff --git a/sound/pci/ice1712/vt1720_mobo.c b/sound/pci/ice1712/vt1720_mobo.c
index 72b060d63c29..239524158fe7 100644
--- a/sound/pci/ice1712/vt1720_mobo.c
+++ b/sound/pci/ice1712/vt1720_mobo.c
@@ -56,7 +56,7 @@ static int __devinit k8x800_add_controls(struct snd_ice1712 *ice)
 
 /* EEPROM image */
 
-static const unsigned char k8x800_eeprom[] __devinitdata = {
+static unsigned char k8x800_eeprom[] __devinitdata = {
 	[ICE_EEP2_SYSCONF]     = 0x01,	/* clock 256, 1ADC, 2DACs */
 	[ICE_EEP2_ACLINK]      = 0x02,	/* ACLINK, packed */
 	[ICE_EEP2_I2S]         = 0x00,	/* - */
@@ -72,7 +72,7 @@ static const unsigned char k8x800_eeprom[] __devinitdata = {
 	[ICE_EEP2_GPIO_STATE2] = 0x00,	/* - */
 };
 
-static const unsigned char sn25p_eeprom[] __devinitdata = {
+static unsigned char sn25p_eeprom[] __devinitdata = {
 	[ICE_EEP2_SYSCONF]     = 0x01,	/* clock 256, 1ADC, 2DACs */
 	[ICE_EEP2_ACLINK]      = 0x02,	/* ACLINK, packed */
 	[ICE_EEP2_I2S]         = 0x00,	/* - */
@@ -90,7 +90,7 @@ static const unsigned char sn25p_eeprom[] __devinitdata = {
 
 
 /* entry point */
-const struct snd_ice1712_card_info snd_vt1720_mobo_cards[] __devinitdata = {
+struct snd_ice1712_card_info snd_vt1720_mobo_cards[] __devinitdata = {
 	{
 		.subvendor = VT1720_SUBDEVICE_K8X800,
 		.name = "Albatron K8X800 Pro II",
diff --git a/sound/pci/ice1712/vt1720_mobo.h b/sound/pci/ice1712/vt1720_mobo.h
index 70af3ad64a5d..0b1b0ee1bea7 100644
--- a/sound/pci/ice1712/vt1720_mobo.h
+++ b/sound/pci/ice1712/vt1720_mobo.h
@@ -36,6 +36,6 @@
 #define VT1720_SUBDEVICE_9CJS		0x0f272327
 #define VT1720_SUBDEVICE_SN25P		0x97123650
 
-extern const struct snd_ice1712_card_info  snd_vt1720_mobo_cards[];
+extern struct snd_ice1712_card_info  snd_vt1720_mobo_cards[];
 
 #endif /* __SOUND_VT1720_MOBO_H */
diff --git a/sound/pci/ice1712/wtm.c b/sound/pci/ice1712/wtm.c
index 4a706b16a0b9..04e535c8542b 100644
--- a/sound/pci/ice1712/wtm.c
+++ b/sound/pci/ice1712/wtm.c
@@ -409,7 +409,7 @@ static int stac9460_mic_sw_put(struct snd_kcontrol *kcontrol,
 /*
  * Control tabs
  */
-static const struct snd_kcontrol_new stac9640_controls[] __devinitdata = {
+static struct snd_kcontrol_new stac9640_controls[] __devinitdata = {
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "Master Playback Switch",
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index 7cf2dcb9d8d4..202f720b34b9 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -2493,6 +2493,7 @@ static int intel8x0_resume(struct pci_dev *pci)
 		return -EIO;
 	}
 	pci_set_master(pci);
+	snd_intel8x0_chip_init(chip, 0);
 	if (request_irq(pci->irq, snd_intel8x0_interrupt,
 			IRQF_SHARED, card->shortname, chip)) {
 		printk(KERN_ERR "intel8x0: unable to grab IRQ %d, "
@@ -2502,7 +2503,6 @@ static int intel8x0_resume(struct pci_dev *pci)
 	}
 	chip->irq = pci->irq;
 	synchronize_irq(chip->irq);
-	snd_intel8x0_chip_init(chip, 0);
 
 	/* re-initialize mixer stuff */
 	if (chip->device_type == DEVICE_INTEL_ICH4 && !spdif_aclink) {
@@ -2862,16 +2862,7 @@ static int __devinit snd_intel8x0_create(struct snd_card *card,
 		ICH_REG_ALI_INTERRUPTSR : ICH_REG_GLOB_STA;
 	chip->int_sta_mask = int_sta_masks;
 
-	/* request irq after initializaing int_sta_mask, etc */
-	if (request_irq(pci->irq, snd_intel8x0_interrupt,
-			IRQF_SHARED, card->shortname, chip)) {
-		snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
-		snd_intel8x0_free(chip);
-		return -EBUSY;
-	}
-	chip->irq = pci->irq;
 	pci_set_master(pci);
-	synchronize_irq(chip->irq);
 
 	switch(chip->device_type) {
 	case DEVICE_INTEL_ICH4:
@@ -2901,6 +2892,15 @@ static int __devinit snd_intel8x0_create(struct snd_card *card,
 		return err;
 	}
 
+	/* request irq after initializaing int_sta_mask, etc */
+	if (request_irq(pci->irq, snd_intel8x0_interrupt,
+			IRQF_SHARED, card->shortname, chip)) {
+		snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
+		snd_intel8x0_free(chip);
+		return -EBUSY;
+	}
+	chip->irq = pci->irq;
+
 	if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
 		snd_intel8x0_free(chip);
 		return err;
diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c
index 21d0899ac382..5338243fb035 100644
--- a/sound/pci/korg1212/korg1212.c
+++ b/sound/pci/korg1212/korg1212.c
@@ -264,9 +264,7 @@ enum MonitorModeSelector {
 #define COMMAND_ACK_DELAY   13         // number of RTC ticks to wait for an acknowledgement
                                        //    from the card after sending a command.
 
-#define FIRMWARE_IN_THE_KERNEL
-
-#ifdef FIRMWARE_IN_THE_KERNEL
+#ifdef CONFIG_SND_KORG1212_FIRMWARE_IN_KERNEL
 #include "korg1212-firmware.h"
 static const struct firmware static_dsp_code = {
 	.data = (u8 *)dspCode,
@@ -418,6 +416,9 @@ struct snd_korg1212 {
 MODULE_DESCRIPTION("korg1212");
 MODULE_LICENSE("GPL");
 MODULE_SUPPORTED_DEVICE("{{KORG,korg1212}}");
+#ifndef CONFIG_SND_KORG1212_FIRMWARE_IN_KERNEL
+MODULE_FIRMWARE("korg/k1212.dsp");
+#endif
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;     /* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	   /* ID for this card */
@@ -2342,26 +2343,25 @@ static int __devinit snd_korg1212_create(struct snd_card *card, struct pci_dev *
         korg1212->AdatTimeCodePhy = korg1212->sharedBufferPhy +
 		offsetof(struct KorgSharedBuffer, AdatTimeCode);
 
+#ifdef CONFIG_SND_KORG1212_FIRMWARE_IN_KERNEL
+	dsp_code = &static_dsp_code;
+#else
 	err = request_firmware(&dsp_code, "korg/k1212.dsp", &pci->dev);
 	if (err < 0) {
 		release_firmware(dsp_code);
-#ifdef FIRMWARE_IN_THE_KERNEL
-		dsp_code = &static_dsp_code;
-#else
 		snd_printk(KERN_ERR "firmware not available\n");
 		snd_korg1212_free(korg1212);
 		return err;
-#endif
 	}
+#endif
 
 	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
 				dsp_code->size, &korg1212->dma_dsp) < 0) {
 		snd_printk(KERN_ERR "korg1212: cannot allocate dsp code memory (%zd bytes)\n", dsp_code->size);
                 snd_korg1212_free(korg1212);
-#ifdef FIRMWARE_IN_THE_KERNEL
-		if (dsp_code != &static_dsp_code)
+#ifndef CONFIG_SND_KORG1212_FIRMWARE_IN_KERNEL
+		release_firmware(dsp_code);
 #endif
-			release_firmware(dsp_code);
                 return -ENOMEM;
         }
 
@@ -2371,10 +2371,9 @@ static int __devinit snd_korg1212_create(struct snd_card *card, struct pci_dev *
 
 	memcpy(korg1212->dma_dsp.area, dsp_code->data, dsp_code->size);
 
-#ifdef FIRMWARE_IN_THE_KERNEL
-	if (dsp_code != &static_dsp_code)
+#ifndef CONFIG_SND_KORG1212_FIRMWARE_IN_KERNEL
+	release_firmware(dsp_code);
 #endif
-		release_firmware(dsp_code);
 
 	rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_RebootCard, 0, 0, 0, 0);
 
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c
index 4526904e3f86..8a5ff1cb5362 100644
--- a/sound/pci/maestro3.c
+++ b/sound/pci/maestro3.c
@@ -59,6 +59,10 @@ MODULE_SUPPORTED_DEVICE("{{ESS,Maestro3 PCI},"
 		"{ESS,Allegro PCI},"
 		"{ESS,Allegro-1 PCI},"
 	        "{ESS,Canyon3D-2/LE PCI}}");
+#ifndef CONFIG_SND_MAESTRO3_FIRMWARE_IN_KERNEL
+MODULE_FIRMWARE("ess/maestro3_assp_kernel.fw");
+MODULE_FIRMWARE("ess/maestro3_assp_minisrc.fw");
+#endif
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
@@ -2101,9 +2105,7 @@ static int __devinit snd_m3_mixer(struct snd_m3 *chip)
 }
 
 
-#define FIRMWARE_IN_THE_KERNEL
-
-#ifdef FIRMWARE_IN_THE_KERNEL
+#ifdef CONFIG_SND_MAESTRO3_FIRMWARE_IN_KERNEL
 
 /*
  * DSP Code images
@@ -2242,7 +2244,7 @@ static const struct firmware assp_minisrc = {
 	.size = sizeof assp_minisrc_image
 };
 
-#endif /* FIRMWARE_IN_THE_KERNEL */
+#else /* CONFIG_SND_MAESTRO3_FIRMWARE_IN_KERNEL */
 
 #ifdef __LITTLE_ENDIAN
 static inline void snd_m3_convert_from_le(const struct firmware *fw) { }
@@ -2257,6 +2259,8 @@ static void snd_m3_convert_from_le(const struct firmware *fw)
 }
 #endif
 
+#endif /* CONFIG_SND_MAESTRO3_FIRMWARE_IN_KERNEL */
+
 
 /*
  * initialize ASSP
@@ -2550,14 +2554,10 @@ static int snd_m3_free(struct snd_m3 *chip)
 	if (chip->iobase)
 		pci_release_regions(chip->pci);
 
-#ifdef FIRMWARE_IN_THE_KERNEL
-	if (chip->assp_kernel_image != &assp_kernel)
+#ifndef CONFIG_SND_MAESTRO3_FIRMWARE_IN_KERNEL
+	release_firmware(chip->assp_kernel_image);
+	release_firmware(chip->assp_minisrc_image);
 #endif
-		release_firmware(chip->assp_kernel_image);
-#ifdef FIRMWARE_IN_THE_KERNEL
-	if (chip->assp_minisrc_image != &assp_minisrc)
-#endif
-		release_firmware(chip->assp_minisrc_image);
 
 	pci_disable_device(chip->pci);
 	kfree(chip);
@@ -2747,29 +2747,29 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci,
 		return -ENOMEM;
 	}
 
+#ifdef CONFIG_SND_MAESTRO3_FIRMWARE_IN_KERNEL
+	chip->assp_kernel_image = &assp_kernel;
+#else
 	err = request_firmware(&chip->assp_kernel_image,
 			       "ess/maestro3_assp_kernel.fw", &pci->dev);
 	if (err < 0) {
-#ifdef FIRMWARE_IN_THE_KERNEL
-		chip->assp_kernel_image = &assp_kernel;
-#else
 		snd_m3_free(chip);
 		return err;
-#endif
 	} else
 		snd_m3_convert_from_le(chip->assp_kernel_image);
+#endif
 
+#ifdef CONFIG_SND_MAESTRO3_FIRMWARE_IN_KERNEL
+	chip->assp_minisrc_image = &assp_minisrc;
+#else
 	err = request_firmware(&chip->assp_minisrc_image,
 			       "ess/maestro3_assp_minisrc.fw", &pci->dev);
 	if (err < 0) {
-#ifdef FIRMWARE_IN_THE_KERNEL
-		chip->assp_minisrc_image = &assp_minisrc;
-#else
 		snd_m3_free(chip);
 		return err;
-#endif
 	} else
 		snd_m3_convert_from_le(chip->assp_minisrc_image);
+#endif
 
 	if ((err = pci_request_regions(pci, card->driver)) < 0) {
 		snd_m3_free(chip);
diff --git a/sound/pci/mixart/mixart_hwdep.c b/sound/pci/mixart/mixart_hwdep.c
index ca05075c67c6..1d9232d2db34 100644
--- a/sound/pci/mixart/mixart_hwdep.c
+++ b/sound/pci/mixart/mixart_hwdep.c
@@ -565,6 +565,9 @@ int snd_mixart_setup_firmware(struct mixart_mgr *mgr)
 	return 0;
 }
 
+MODULE_FIRMWARE("mixart/miXart8.xlx");
+MODULE_FIRMWARE("mixart/miXart8.elf");
+MODULE_FIRMWARE("mixart/miXart8AES.xlx");
 
 #else /* old style firmware loading */
 
diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c
index d97413484ae9..f7f6a687f033 100644
--- a/sound/pci/pcxhr/pcxhr.c
+++ b/sound/pci/pcxhr/pcxhr.c
@@ -638,22 +638,22 @@ static void pcxhr_trigger_tasklet(unsigned long arg)
 static int pcxhr_trigger(struct snd_pcm_substream *subs, int cmd)
 {
 	struct pcxhr_stream *stream;
-	struct list_head *pos;
 	struct snd_pcm_substream *s;
-	int i;
 
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
 		snd_printdd("SNDRV_PCM_TRIGGER_START\n");
-		i = 0;
-		snd_pcm_group_for_each(pos, subs) {
-			s = snd_pcm_group_substream_entry(pos);
-			stream = s->runtime->private_data;
-			stream->status = PCXHR_STREAM_STATUS_SCHEDULE_RUN;
-			snd_pcm_trigger_done(s, subs);
-			i++;
-		}
-		if (i==1) {
+		if (snd_pcm_stream_linked(subs)) {
+			struct snd_pcxhr *chip = snd_pcm_substream_chip(subs);
+			snd_pcm_group_for_each_entry(s, subs) {
+				stream = s->runtime->private_data;
+				stream->status =
+					PCXHR_STREAM_STATUS_SCHEDULE_RUN;
+				snd_pcm_trigger_done(s, subs);
+			}
+			tasklet_hi_schedule(&chip->mgr->trigger_taskq);
+		} else {
+			stream = subs->runtime->private_data;
 			snd_printdd("Only one Substream %c %d\n",
 				    stream->pipe->is_capture ? 'C' : 'P',
 				    stream->pipe->first_audio);
@@ -665,15 +665,11 @@ static int pcxhr_trigger(struct snd_pcm_substream *subs, int cmd)
 			if (pcxhr_set_stream_state(stream))
 				return -EINVAL;
 			stream->status = PCXHR_STREAM_STATUS_RUNNING;
-		} else {
-			struct snd_pcxhr *chip = snd_pcm_substream_chip(subs);
-			tasklet_hi_schedule(&chip->mgr->trigger_taskq);
 		}
 		break;
 	case SNDRV_PCM_TRIGGER_STOP:
 		snd_printdd("SNDRV_PCM_TRIGGER_STOP\n");
-		snd_pcm_group_for_each(pos, subs) {
-			s = snd_pcm_group_substream_entry(pos);
+		snd_pcm_group_for_each_entry(s, subs) {
 			stream = s->runtime->private_data;
 			stream->status = PCXHR_STREAM_STATUS_SCHEDULE_STOP;
 			if (pcxhr_set_stream_state(stream))
diff --git a/sound/pci/pcxhr/pcxhr_hwdep.c b/sound/pci/pcxhr/pcxhr_hwdep.c
index 369c19fea985..d55d8bc90eee 100644
--- a/sound/pci/pcxhr/pcxhr_hwdep.c
+++ b/sound/pci/pcxhr/pcxhr_hwdep.c
@@ -356,6 +356,12 @@ int pcxhr_setup_firmware(struct pcxhr_mgr *mgr)
 	return 0;
 }
 
+MODULE_FIRMWARE("pcxhr/xi_1_882.dat");
+MODULE_FIRMWARE("pcxhr/xc_1_882.dat");
+MODULE_FIRMWARE("pcxhr/e321_512.e56");
+MODULE_FIRMWARE("pcxhr/b321_512.b56");
+MODULE_FIRMWARE("pcxhr/d321_512.d56");
+
 #else /* old style firmware loading */
 
 /* pcxhr hwdep interface id string */
diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c
index 952625dead58..8e5410483e67 100644
--- a/sound/pci/riptide/riptide.c
+++ b/sound/pci/riptide/riptide.c
@@ -117,6 +117,7 @@ MODULE_AUTHOR("Peter Gruber <nokos@gmx.net>");
 MODULE_DESCRIPTION("riptide");
 MODULE_LICENSE("GPL");
 MODULE_SUPPORTED_DEVICE("{{Conexant,Riptide}}");
+MODULE_FIRMWARE("riptide.hex");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c
index 6bb7ac650ec4..618653e22561 100644
--- a/sound/pci/rme32.c
+++ b/sound/pci/rme32.c
@@ -1078,12 +1078,10 @@ static int
 snd_rme32_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 {
 	struct rme32 *rme32 = snd_pcm_substream_chip(substream);
-	struct list_head *pos;
 	struct snd_pcm_substream *s;
 
 	spin_lock(&rme32->lock);
-	snd_pcm_group_for_each(pos, substream) {
-		s = snd_pcm_group_substream_entry(pos);
+	snd_pcm_group_for_each_entry(s, substream) {
 		if (s != rme32->playback_substream &&
 		    s != rme32->capture_substream)
 			continue;
@@ -1110,8 +1108,7 @@ snd_rme32_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 	
 	/* prefill playback buffer */
 	if (cmd == SNDRV_PCM_TRIGGER_START && rme32->fullduplex_mode) {
-		snd_pcm_group_for_each(pos, substream) {
-			s = snd_pcm_group_substream_entry(pos);
+		snd_pcm_group_for_each_entry(s, substream) {
 			if (s == rme32->playback_substream) {
 				s->ops->ack(s);
 				break;
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
index 89b3c7ff5037..3b3ef657f73e 100644
--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -60,6 +60,12 @@ MODULE_LICENSE("GPL");
 MODULE_SUPPORTED_DEVICE("{{RME Hammerfall-DSP},"
 	        "{RME HDSP-9652},"
 		"{RME HDSP-9632}}");
+#ifdef HDSP_FW_LOADER
+MODULE_FIRMWARE("multiface_firmware.bin");
+MODULE_FIRMWARE("multiface_firmware_rev11.bin");
+MODULE_FIRMWARE("digiface_firmware.bin");
+MODULE_FIRMWARE("digiface_firmware_rev11.bin");
+#endif
 
 #define HDSP_MAX_CHANNELS        26
 #define HDSP_MAX_DS_CHANNELS     14
@@ -275,6 +281,11 @@ MODULE_SUPPORTED_DEVICE("{{RME Hammerfall-DSP},"
 #define HDSP_Frequency128KHz   (HDSP_QuadSpeed|HDSP_DoubleSpeed|HDSP_Frequency0)
 #define HDSP_Frequency176_4KHz (HDSP_QuadSpeed|HDSP_DoubleSpeed|HDSP_Frequency1)
 #define HDSP_Frequency192KHz   (HDSP_QuadSpeed|HDSP_DoubleSpeed|HDSP_Frequency1|HDSP_Frequency0)
+/* RME says n = 104857600000000, but in the windows MADI driver, I see:
+	return 104857600000000 / rate; // 100 MHz
+	return 110100480000000 / rate; // 105 MHz
+*/
+#define DDS_NUMERATOR 104857600000000ULL;  /*  =  2^20 * 10^8 */
 
 #define hdsp_encode_latency(x)       (((x)<<1) & HDSP_LatencyMask)
 #define hdsp_decode_latency(x)       (((x) & HDSP_LatencyMask)>>1)
@@ -1001,11 +1012,7 @@ static void hdsp_set_dds_value(struct hdsp *hdsp, int rate)
 	else if (rate >= 56000)
 		rate /= 2;
 
-	/* RME says n = 104857600000000, but in the windows MADI driver, I see:
-//	return 104857600000000 / rate; // 100 MHz
-	return 110100480000000 / rate; // 105 MHz
-        */	   
-	n = 104857600000000ULL;  /*  =  2^20 * 10^8 */
+	n = DDS_NUMERATOR;
 	div64_32(&n, rate, &r);
 	/* n should be less than 2^32 for being written to FREQ register */
 	snd_assert((n >> 32) == 0);
@@ -3085,11 +3092,83 @@ static int snd_hdsp_get_adat_sync_check(struct snd_kcontrol *kcontrol, struct sn
 	return 0;
 }
 
+#define HDSP_DDS_OFFSET(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+  .name = xname, \
+  .index = xindex, \
+  .info = snd_hdsp_info_dds_offset, \
+  .get = snd_hdsp_get_dds_offset, \
+  .put = snd_hdsp_put_dds_offset \
+}
+
+static int hdsp_dds_offset(struct hdsp *hdsp)
+{
+	u64 n;
+	u32 r;
+	unsigned int dds_value = hdsp->dds_value;
+	int system_sample_rate = hdsp->system_sample_rate;
+
+	n = DDS_NUMERATOR;
+	/*
+	 * dds_value = n / rate
+	 * rate = n / dds_value
+	 */
+	div64_32(&n, dds_value, &r);
+	if (system_sample_rate >= 112000)
+		n *= 4;
+	else if (system_sample_rate >= 56000)
+		n *= 2;
+	return ((int)n) - system_sample_rate;
+}
+
+static int hdsp_set_dds_offset(struct hdsp *hdsp, int offset_hz)
+{
+	int rate = hdsp->system_sample_rate + offset_hz;
+	hdsp_set_dds_value(hdsp, rate);
+	return 0;
+}
+
+static int snd_hdsp_info_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 1;
+	uinfo->value.integer.min = -5000;
+	uinfo->value.integer.max = 5000;
+	return 0;
+}
+
+static int snd_hdsp_get_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+{
+	struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
+	
+	ucontrol->value.enumerated.item[0] = hdsp_dds_offset(hdsp);
+	return 0;
+}
+
+static int snd_hdsp_put_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
+{
+	struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
+	int change;
+	int val;
+	
+	if (!snd_hdsp_use_is_exclusive(hdsp))
+		return -EBUSY;
+	val = ucontrol->value.enumerated.item[0];
+	spin_lock_irq(&hdsp->lock);
+	if (val != hdsp_dds_offset(hdsp))
+		change = (hdsp_set_dds_offset(hdsp, val) == 0) ? 1 : 0;
+	else
+		change = 0;
+	spin_unlock_irq(&hdsp->lock);
+	return change;
+}
+
 static struct snd_kcontrol_new snd_hdsp_9632_controls[] = {
 HDSP_DA_GAIN("DA Gain", 0),
 HDSP_AD_GAIN("AD Gain", 0),
 HDSP_PHONE_GAIN("Phones Gain", 0),
-HDSP_XLR_BREAKOUT_CABLE("XLR Breakout Cable", 0)
+HDSP_XLR_BREAKOUT_CABLE("XLR Breakout Cable", 0),
+HDSP_DDS_OFFSET("DDS Sample Rate Offset", 0)
 };
 
 static struct snd_kcontrol_new snd_hdsp_controls[] = {
@@ -3780,11 +3859,9 @@ static int snd_hdsp_reset(struct snd_pcm_substream *substream)
 	else
 		runtime->status->hw_ptr = 0;
 	if (other) {
-		struct list_head *pos;
 		struct snd_pcm_substream *s;
 		struct snd_pcm_runtime *oruntime = other->runtime;
-		snd_pcm_group_for_each(pos, substream) {
-			s = snd_pcm_group_substream_entry(pos);
+		snd_pcm_group_for_each_entry(s, substream) {
 			if (s == other) {
 				oruntime->status->hw_ptr = runtime->status->hw_ptr;
 				break;
@@ -3933,10 +4010,8 @@ static int snd_hdsp_trigger(struct snd_pcm_substream *substream, int cmd)
 		other = hdsp->playback_substream;
 
 	if (other) {
-		struct list_head *pos;
 		struct snd_pcm_substream *s;
-		snd_pcm_group_for_each(pos, substream) {
-			s = snd_pcm_group_substream_entry(pos);
+		snd_pcm_group_for_each_entry(s, substream) {
 			if (s == other) {
 				snd_pcm_trigger_done(s, substream);
 				if (cmd == SNDRV_PCM_TRIGGER_START)
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
index 6e95857e4e67..143185e7e4dc 100644
--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -91,8 +91,10 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
 #define HDSPM_controlRegister	     64
 #define HDSPM_interruptConfirmation  96
 #define HDSPM_control2Reg	     256  /* not in specs ???????? */
+#define HDSPM_freqReg                256  /* for AES32 */
 #define HDSPM_midiDataOut0  	     352  /* just believe in old code */
 #define HDSPM_midiDataOut1  	     356
+#define HDSPM_eeprom_wr		     384  /* for AES32 */
 
 /* DMA enable for 64 channels, only Bit 0 is relevant */
 #define HDSPM_outputEnableBase       512  /* 512-767  input  DMA */ 
@@ -389,9 +391,8 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
    size is the same regardless of the number of channels, and
    also the latency to use. 
    for one direction !!!
-   => need to mupltiply by 2!!
 */
-#define HDSPM_DMA_AREA_BYTES (2 * HDSPM_MAX_CHANNELS * HDSPM_CHANNEL_BUFFER_BYTES)
+#define HDSPM_DMA_AREA_BYTES (HDSPM_MAX_CHANNELS * HDSPM_CHANNEL_BUFFER_BYTES)
 #define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024)
 
 /* revisions >= 230 indicate AES32 card */
@@ -484,28 +485,6 @@ static char channel_map_madi_ss[HDSPM_MAX_CHANNELS] = {
    56, 57, 58, 59, 60, 61, 62, 63
 };
 
-static char channel_map_madi_ds[HDSPM_MAX_CHANNELS] = {
-  0, 2, 4, 6, 8, 10, 12, 14,
-  16, 18, 20, 22, 24, 26, 28, 30,
-  32, 34, 36, 38, 40, 42, 44, 46,
-  48, 50, 52, 54, 56, 58, 60, 62,
-  -1, -1, -1, -1, -1, -1, -1, -1,
-  -1, -1, -1, -1, -1, -1, -1, -1,
-  -1, -1, -1, -1, -1, -1, -1, -1,
-  -1, -1, -1, -1, -1, -1, -1, -1
-};
-
-static char channel_map_madi_qs[HDSPM_MAX_CHANNELS] = {
-  0,   4,  8, 12, 16, 20, 24,  28,  
-  32, 36, 40, 44, 48, 52, 56,  60
-  -1, -1, -1, -1, -1, -1, -1, -1,  
-  -1, -1, -1, -1, -1, -1, -1, -1,  
-  -1, -1, -1, -1, -1, -1, -1, -1, 
-  -1, -1, -1, -1, -1, -1, -1, -1, 
-  -1, -1, -1, -1, -1, -1, -1, -1, 
-  -1, -1, -1, -1, -1, -1, -1, -1
-};
-
 
 static struct pci_device_id snd_hdspm_ids[] __devinitdata = {
 	{
@@ -818,6 +797,27 @@ static int hdspm_set_interrupt_interval(struct hdspm * s, unsigned int frames)
 	return 0;
 }
 
+static void hdspm_set_dds_value(struct hdspm *hdspm, int rate)
+{
+	u64 n;
+	u32 r;
+	
+	if (rate >= 112000)
+		rate /= 4;
+	else if (rate >= 56000)
+		rate /= 2;
+
+	/* RME says n = 104857600000000, but in the windows MADI driver, I see:
+//	return 104857600000000 / rate; // 100 MHz
+	return 110100480000000 / rate; // 105 MHz
+        */	   
+	//n = 104857600000000ULL;  /*  =  2^20 * 10^8 */
+	n = 110100480000000ULL;    /* Value checked for AES32 and MADI */
+	div64_32(&n, rate, &r);
+	/* n should be less than 2^32 for being written to FREQ register */
+	snd_assert((n >> 32) == 0);
+	hdspm_write(hdspm, HDSPM_freqReg, (u32)n);
+}
 
 /* dummy set rate lets see what happens */
 static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally)
@@ -943,12 +943,16 @@ static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally)
 	hdspm->control_register |= rate_bits;
 	hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
 
-	if (rate > 96000 /* 64000*/)
-		hdspm->channel_map = channel_map_madi_qs;
-	else if (rate > 48000)
-		hdspm->channel_map = channel_map_madi_ds;
-	else 
-		hdspm->channel_map = channel_map_madi_ss;
+	/* For AES32, need to set DDS value in FREQ register
+	   For MADI, also apparently */
+	hdspm_set_dds_value(hdspm, rate);
+	
+	if (hdspm->is_aes32 && rate != current_rate)
+		hdspm_write(hdspm, HDSPM_eeprom_wr, 0);
+	
+	/* For AES32 and for MADI (at least rev 204), channel_map needs to
+	 * always be channel_map_madi_ss, whatever the sample rate */
+	hdspm->channel_map = channel_map_madi_ss;
 
 	hdspm->system_sample_rate = rate;
 
@@ -3184,8 +3188,8 @@ snd_hdspm_proc_read_aes32(struct snd_info_entry * entry,
 		    hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
 		    hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
 	snd_iprintf(buffer,
-		    "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, status2=0x%x, timecode=0x%x\n",
-		    hdspm->control_register, hdspm->control2_register,
+		    "Register: ctrl1=0x%x, status1=0x%x, status2=0x%x, timecode=0x%x\n",
+		    hdspm->control_register,
 		    status, status2, timecode);
 
 	snd_iprintf(buffer, "--- Settings ---\n");
@@ -3377,13 +3381,16 @@ static int snd_hdspm_set_defaults(struct hdspm * hdspm)
 
 	hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
 
+        if (!hdspm->is_aes32) {
+		/* No control2 register for AES32 */
 #ifdef SNDRV_BIG_ENDIAN
-	hdspm->control2_register = HDSPM_BIGENDIAN_MODE;
+		hdspm->control2_register = HDSPM_BIGENDIAN_MODE;
 #else
-	hdspm->control2_register = 0;
+		hdspm->control2_register = 0;
 #endif
 
-	hdspm_write(hdspm, HDSPM_control2Reg, hdspm->control2_register);
+		hdspm_write(hdspm, HDSPM_control2Reg, hdspm->control2_register);
+	}
 	hdspm_compute_period_size(hdspm);
 
 	/* silence everything */
@@ -3575,11 +3582,9 @@ static int snd_hdspm_reset(struct snd_pcm_substream *substream)
 	else
 		runtime->status->hw_ptr = 0;
 	if (other) {
-		struct list_head *pos;
 		struct snd_pcm_substream *s;
 		struct snd_pcm_runtime *oruntime = other->runtime;
-		snd_pcm_group_for_each(pos, substream) {
-			s = snd_pcm_group_substream_entry(pos);
+		snd_pcm_group_for_each_entry(s, substream) {
 			if (s == other) {
 				oruntime->status->hw_ptr =
 				    runtime->status->hw_ptr;
@@ -3658,11 +3663,10 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream,
 
 	/* Memory allocation, takashi's method, dont know if we should spinlock  */
 	/* malloc all buffer even if not enabled to get sure */
-	/* malloc only needed bytes */
+	/* Update for MADI rev 204: we need to allocate for all channels,
+	 * otherwise it doesn't work at 96kHz */
 	err =
-	    snd_pcm_lib_malloc_pages(substream,
-				     HDSPM_CHANNEL_BUFFER_BYTES *
-				     params_channels(params));
+	    snd_pcm_lib_malloc_pages(substream, HDSPM_DMA_AREA_BYTES);
 	if (err < 0)
 		return err;
 
@@ -3698,6 +3702,13 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream,
 	   "playback" : "capture",
 	   snd_pcm_sgbuf_get_addr(sgbuf, 0));
 	 */
+	/*
+	snd_printdd("set_hwparams: %s %d Hz, %d channels, bs = %d\n",
+			substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
+			  "playback" : "capture",
+			params_rate(params), params_channels(params),
+			params_buffer_size(params));
+	*/
 	return 0;
 }
 
@@ -3791,10 +3802,8 @@ static int snd_hdspm_trigger(struct snd_pcm_substream *substream, int cmd)
 		other = hdspm->playback_substream;
 
 	if (other) {
-		struct list_head *pos;
 		struct snd_pcm_substream *s;
-		snd_pcm_group_for_each(pos, substream) {
-			s = snd_pcm_group_substream_entry(pos);
+		snd_pcm_group_for_each_entry(s, substream) {
 			if (s == other) {
 				snd_pcm_trigger_done(s, substream);
 				if (cmd == SNDRV_PCM_TRIGGER_START)
@@ -3904,16 +3913,16 @@ static int snd_hdspm_hw_rule_channels_rate(struct snd_pcm_hw_params *params,
 	struct snd_interval *r =
 	    hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
 
-	if (r->min > 48000) {
+	if (r->min > 48000 && r->max <= 96000) {
 		struct snd_interval t = {
-			.min = 1,
+			.min = hdspm->ds_channels,
 			.max = hdspm->ds_channels,
 			.integer = 1,
 		};
 		return snd_interval_refine(c, &t);
 	} else if (r->max < 64000) {
 		struct snd_interval t = {
-			.min = 1,
+			.min = hdspm->ss_channels,
 			.max = hdspm->ss_channels,
 			.integer = 1,
 		};
@@ -3931,14 +3940,14 @@ static int snd_hdspm_hw_rule_rate_channels(struct snd_pcm_hw_params *params,
 	struct snd_interval *r =
 	    hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
 
-	if (c->min <= hdspm->ss_channels) {
+	if (c->min >= hdspm->ss_channels) {
 		struct snd_interval t = {
 			.min = 32000,
 			.max = 48000,
 			.integer = 1,
 		};
 		return snd_interval_refine(r, &t);
-	} else if (c->max > hdspm->ss_channels) {
+	} else if (c->max <= hdspm->ds_channels) {
 		struct snd_interval t = {
 			.min = 64000,
 			.max = 96000,
@@ -3950,13 +3959,39 @@ static int snd_hdspm_hw_rule_rate_channels(struct snd_pcm_hw_params *params,
 	return 0;
 }
 
+static int snd_hdspm_hw_rule_channels(struct snd_pcm_hw_params *params,
+				      struct snd_pcm_hw_rule *rule)
+{
+	unsigned int list[3];
+	struct hdspm *hdspm = rule->private;
+	struct snd_interval *c = hw_param_interval(params,
+			SNDRV_PCM_HW_PARAM_CHANNELS);
+	if (hdspm->is_aes32) {
+		list[0] = hdspm->qs_channels;
+		list[1] = hdspm->ds_channels;
+		list[2] = hdspm->ss_channels;
+		return snd_interval_list(c, 3, list, 0);
+	} else {
+		list[0] = hdspm->ds_channels;
+		list[1] = hdspm->ss_channels;
+		return snd_interval_list(c, 2, list, 0);
+	}
+}
+
+
+static unsigned int hdspm_aes32_sample_rates[] = { 32000, 44100, 48000, 64000, 88200, 96000, 128000, 176400, 192000 };
+
+static struct snd_pcm_hw_constraint_list hdspm_hw_constraints_aes32_sample_rates = {
+	.count = ARRAY_SIZE(hdspm_aes32_sample_rates),
+	.list = hdspm_aes32_sample_rates,
+	.mask = 0
+};
+
 static int snd_hdspm_playback_open(struct snd_pcm_substream *substream)
 {
 	struct hdspm *hdspm = snd_pcm_substream_chip(substream);
 	struct snd_pcm_runtime *runtime = substream->runtime;
 
-	snd_printdd("Open device substream %d\n", substream->stream);
-
 	spin_lock_irq(&hdspm->lock);
 
 	snd_pcm_set_sync(substream);
@@ -3977,14 +4012,21 @@ static int snd_hdspm_playback_open(struct snd_pcm_substream *substream)
 				   SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
 				   &hw_constraints_period_sizes);
 
-	snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
-			    snd_hdspm_hw_rule_channels_rate, hdspm,
-			    SNDRV_PCM_HW_PARAM_RATE, -1);
-
-	snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
-			    snd_hdspm_hw_rule_rate_channels, hdspm,
-			    SNDRV_PCM_HW_PARAM_CHANNELS, -1);
-
+	if (hdspm->is_aes32) {
+		snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+				&hdspm_hw_constraints_aes32_sample_rates);
+	} else {
+		snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+				     snd_hdspm_hw_rule_channels, hdspm,
+				     SNDRV_PCM_HW_PARAM_CHANNELS, -1);
+		snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+				    snd_hdspm_hw_rule_channels_rate, hdspm,
+				    SNDRV_PCM_HW_PARAM_RATE, -1);
+
+		snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+				    snd_hdspm_hw_rule_rate_channels, hdspm,
+				    SNDRV_PCM_HW_PARAM_CHANNELS, -1);
+	}
 	return 0;
 }
 
@@ -4024,14 +4066,21 @@ static int snd_hdspm_capture_open(struct snd_pcm_substream *substream)
 	snd_pcm_hw_constraint_list(runtime, 0,
 				   SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
 				   &hw_constraints_period_sizes);
-
-	snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
-			    snd_hdspm_hw_rule_channels_rate, hdspm,
-			    SNDRV_PCM_HW_PARAM_RATE, -1);
-
-	snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
-			    snd_hdspm_hw_rule_rate_channels, hdspm,
-			    SNDRV_PCM_HW_PARAM_CHANNELS, -1);
+	if (hdspm->is_aes32) {
+		snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+				&hdspm_hw_constraints_aes32_sample_rates);
+	} else {
+		snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+				     snd_hdspm_hw_rule_channels, hdspm,
+				     SNDRV_PCM_HW_PARAM_CHANNELS, -1);
+		snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+				    snd_hdspm_hw_rule_channels_rate, hdspm,
+				    SNDRV_PCM_HW_PARAM_RATE, -1);
+
+		snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+				    snd_hdspm_hw_rule_rate_channels, hdspm,
+				    SNDRV_PCM_HW_PARAM_CHANNELS, -1);
+	}
 	return 0;
 }
 
diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c
index cc3bdececce7..bd7dbd267ed1 100644
--- a/sound/pci/rme9652/rme9652.c
+++ b/sound/pci/rme9652/rme9652.c
@@ -1992,11 +1992,9 @@ static int snd_rme9652_reset(struct snd_pcm_substream *substream)
 	else
 		runtime->status->hw_ptr = 0;
 	if (other) {
-		struct list_head *pos;
 		struct snd_pcm_substream *s;
 		struct snd_pcm_runtime *oruntime = other->runtime;
-		snd_pcm_group_for_each(pos, substream) {
-			s = snd_pcm_group_substream_entry(pos);
+		snd_pcm_group_for_each_entry(s, substream) {
 			if (s == other) {
 				oruntime->status->hw_ptr = runtime->status->hw_ptr;
 				break;
@@ -2140,10 +2138,8 @@ static int snd_rme9652_trigger(struct snd_pcm_substream *substream,
 		other = rme9652->playback_substream;
 
 	if (other) {
-		struct list_head *pos;
 		struct snd_pcm_substream *s;
-		snd_pcm_group_for_each(pos, substream) {
-			s = snd_pcm_group_substream_entry(pos);
+		snd_pcm_group_for_each_entry(s, substream) {
 			if (s == other) {
 				snd_pcm_trigger_done(s, substream);
 				if (cmd == SNDRV_PCM_TRIGGER_START)
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c
index 3bff32167f66..7ca606272460 100644
--- a/sound/pci/trident/trident_main.c
+++ b/sound/pci/trident/trident_main.c
@@ -1540,7 +1540,6 @@ static int snd_trident_trigger(struct snd_pcm_substream *substream,
 				    
 {
 	struct snd_trident *trident = snd_pcm_substream_chip(substream);
-	struct list_head *pos;
 	struct snd_pcm_substream *s;
 	unsigned int what, whati, capture_flag, spdif_flag;
 	struct snd_trident_voice *voice, *evoice;
@@ -1563,8 +1562,7 @@ static int snd_trident_trigger(struct snd_pcm_substream *substream,
 	what = whati = capture_flag = spdif_flag = 0;
 	spin_lock(&trident->reg_lock);
 	val = inl(TRID_REG(trident, T4D_STIMER)) & 0x00ffffff;
-	snd_pcm_group_for_each(pos, substream) {
-		s = snd_pcm_group_substream_entry(pos);
+	snd_pcm_group_for_each_entry(s, substream) {
 		if ((struct snd_trident *) snd_pcm_substream_chip(s) == trident) {
 			voice = s->runtime->private_data;
 			evoice = voice->extra;
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c
index fd12674d0394..ea861bceaddf 100644
--- a/sound/pci/ymfpci/ymfpci_main.c
+++ b/sound/pci/ymfpci/ymfpci_main.c
@@ -1998,9 +1998,7 @@ static void snd_ymfpci_disable_dsp(struct snd_ymfpci *chip)
 	}
 }
 
-#define FIRMWARE_IN_THE_KERNEL
-
-#ifdef FIRMWARE_IN_THE_KERNEL
+#ifdef CONFIG_SND_YMFPCI_FIRMWARE_IN_KERNEL
 
 #include "ymfpci_image.h"
 
@@ -2018,6 +2016,24 @@ static struct firmware snd_ymfpci_controller_1e_microcode = {
 };
 #endif
 
+#ifdef CONFIG_SND_YMFPCI_FIRMWARE_IN_KERNEL
+static int snd_ymfpci_request_firmware(struct snd_ymfpci *chip)
+{
+	chip->dsp_microcode = &snd_ymfpci_dsp_microcode;
+	if (chip->device_id == PCI_DEVICE_ID_YAMAHA_724F ||
+	    chip->device_id == PCI_DEVICE_ID_YAMAHA_740C ||
+	    chip->device_id == PCI_DEVICE_ID_YAMAHA_744 ||
+	    chip->device_id == PCI_DEVICE_ID_YAMAHA_754)
+		chip->controller_microcode =
+			&snd_ymfpci_controller_1e_microcode;
+	else
+		chip->controller_microcode =
+			&snd_ymfpci_controller_microcode;
+	return 0;
+}
+
+#else /* use fw_loader */
+
 #ifdef __LITTLE_ENDIAN
 static inline void snd_ymfpci_convert_from_le(const struct firmware *fw) { }
 #else
@@ -2046,13 +2062,8 @@ static int snd_ymfpci_request_firmware(struct snd_ymfpci *chip)
 			err = -EINVAL;
 		}
 	}
-	if (err < 0) {
-#ifdef FIRMWARE_IN_THE_KERNEL
-		chip->dsp_microcode = &snd_ymfpci_dsp_microcode;
-#else
+	if (err < 0)
 		return err;
-#endif
-	}
 	is_1e = chip->device_id == PCI_DEVICE_ID_YAMAHA_724F ||
 		chip->device_id == PCI_DEVICE_ID_YAMAHA_740C ||
 		chip->device_id == PCI_DEVICE_ID_YAMAHA_744 ||
@@ -2069,18 +2080,17 @@ static int snd_ymfpci_request_firmware(struct snd_ymfpci *chip)
 			err = -EINVAL;
 		}
 	}
-	if (err < 0) {
-#ifdef FIRMWARE_IN_THE_KERNEL
-		chip->controller_microcode =
-			is_1e ? &snd_ymfpci_controller_1e_microcode
-			      : &snd_ymfpci_controller_microcode;
-#else
+	if (err < 0)
 		return err;
-#endif
-	}
 	return 0;
 }
 
+MODULE_FIRMWARE("yamaha/ds1_dsp.fw");
+MODULE_FIRMWARE("yamaha/ds1_ctrl.fw");
+MODULE_FIRMWARE("yamaha/ds1e_ctrl.fw");
+
+#endif
+
 static void snd_ymfpci_download_image(struct snd_ymfpci *chip)
 {
 	int i;
@@ -2259,15 +2269,10 @@ static int snd_ymfpci_free(struct snd_ymfpci *chip)
 	pci_write_config_word(chip->pci, 0x40, chip->old_legacy_ctrl);
 	
 	pci_disable_device(chip->pci);
-#ifdef FIRMWARE_IN_THE_KERNEL
-	if (chip->dsp_microcode != &snd_ymfpci_dsp_microcode)
-#endif
-		release_firmware(chip->dsp_microcode);
-#ifdef FIRMWARE_IN_THE_KERNEL
-	if (chip->controller_microcode != &snd_ymfpci_controller_microcode &&
-	    chip->controller_microcode != &snd_ymfpci_controller_1e_microcode)
+#ifndef CONFIG_SND_YMFPCI_FIRMWARE_IN_KERNEL
+	release_firmware(chip->dsp_microcode);
+	release_firmware(chip->controller_microcode);
 #endif
-		release_firmware(chip->controller_microcode);
 	kfree(chip);
 	return 0;
 }
diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c
index 363bcb5f08e6..c57e127d9ccb 100644
--- a/sound/pcmcia/vx/vxpocket.c
+++ b/sound/pcmcia/vx/vxpocket.c
@@ -297,7 +297,7 @@ static int vxpocket_probe(struct pcmcia_device *p_dev)
 
 	/* find an empty slot from the card list */
 	for (i = 0; i < SNDRV_CARDS; i++) {
-		if (! card_alloc & (1 << i))
+		if (!(card_alloc & (1 << i)))
 			break;
 	}
 	if (i >= SNDRV_CARDS) {
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index dccaa4be679e..10cffc087181 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -2,31 +2,31 @@
 # SoC audio configuration
 #
 
-menu "SoC audio support"
+menu "System on Chip audio support"
 	depends on SND!=n
 
 config SND_SOC_AC97_BUS
 	bool
 
 config SND_SOC
-	tristate "SoC audio support"
+	tristate "ALSA for SoC audio support"
 	depends on SND
 	select SND_PCM
 	---help---
 
-	  If you want SoC support, you should say Y here and also to the
-	  specific driver for your SoC below. You will also need to select the
-	  specific codec(s) attached to the SoC
+	  If you want ASoC support, you should say Y here and also to the
+	  specific driver for your SoC platform below.
+	  
+	  ASoC provides power efficient ALSA support for embedded battery powered
+	  SoC based systems like PDA's, Phones and Personal Media Players.
 
-	  This SoC audio support can also be built as a module.  If so, the module
+	  This ASoC audio support can also be built as a module.  If so, the module
 	  will be called snd-soc-core.
 
 # All the supported Soc's
-menu "SoC Platforms"
-depends on SND_SOC
 source "sound/soc/at91/Kconfig"
 source "sound/soc/pxa/Kconfig"
-endmenu
+source "sound/soc/s3c24xx/Kconfig"
 
 # Supported codecs
 source "sound/soc/codecs/Kconfig"
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index 98e6f49dafc2..0ae2e49036f9 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -1,4 +1,4 @@
 snd-soc-core-objs := soc-core.o soc-dapm.o
 
 obj-$(CONFIG_SND_SOC)	+= snd-soc-core.o
-obj-$(CONFIG_SND_SOC)	+= codecs/ at91/ pxa/
+obj-$(CONFIG_SND_SOC)	+= codecs/ at91/ pxa/ s3c24xx/
diff --git a/sound/soc/at91/Kconfig b/sound/soc/at91/Kconfig
index a5b2558916c1..5cb93fd3a407 100644
--- a/sound/soc/at91/Kconfig
+++ b/sound/soc/at91/Kconfig
@@ -1,5 +1,3 @@
-menu "SoC Audio for the Atmel AT91"
-
 config SND_AT91_SOC
 	tristate "SoC Audio for the Atmel AT91 System-on-Chip"
 	depends on ARCH_AT91 && SND_SOC
@@ -8,13 +6,13 @@ config SND_AT91_SOC
 	  the AT91 SSC interface. You will also need
 	  to select the audio interfaces to support below.
 
-config SND_AT91_SOC_I2S
+config SND_AT91_SOC_SSC
 	tristate
 
 config SND_AT91_SOC_ETI_B1_WM8731
-	tristate "SoC I2S Audio support for WM8731-based Endrelia ETI-B1 boards"
+	tristate "SoC Audio support for WM8731-based Endrelia ETI-B1 boards"
 	depends on SND_AT91_SOC && (MACH_ETI_B1 || MACH_ETI_C1)
-	select SND_AT91_SOC_I2S
+	select SND_AT91_SOC_SSC
 	select SND_SOC_WM8731
 	help
 	  Say Y if you want to add support for SoC audio on WM8731-based
@@ -27,5 +25,3 @@ config SND_AT91_SOC_ETI_SLAVE
 	help
 	  Say Y if you want to run with the AT91 SSC generating the BCLK
 	  and LRC signals on Endrelia boards.
-
-endmenu
diff --git a/sound/soc/at91/Makefile b/sound/soc/at91/Makefile
index b77b01ab2028..f23da17cc328 100644
--- a/sound/soc/at91/Makefile
+++ b/sound/soc/at91/Makefile
@@ -1,9 +1,9 @@
 # AT91 Platform Support
 snd-soc-at91-objs := at91-pcm.o
-snd-soc-at91-i2s-objs := at91-i2s.o
+snd-soc-at91-ssc-objs := at91-ssc.o
 
 obj-$(CONFIG_SND_AT91_SOC) += snd-soc-at91.o
-obj-$(CONFIG_SND_AT91_SOC_I2S) += snd-soc-at91-i2s.o
+obj-$(CONFIG_SND_AT91_SOC_SSC) += snd-soc-at91-ssc.o
 
 # AT91 Machine Support
 snd-soc-eti-b1-wm8731-objs := eti_b1_wm8731.o
diff --git a/sound/soc/at91/at91-i2s.c b/sound/soc/at91/at91-ssc.c
index 9fc0c0388881..3d4e32cff75e 100644
--- a/sound/soc/at91/at91-i2s.c
+++ b/sound/soc/at91/at91-ssc.c
@@ -1,5 +1,5 @@
 /*
- * at91-i2s.c  --  ALSA SoC I2S Audio Layer Platform driver
+ * at91-ssc.c  --  ALSA SoC AT91 SSC Audio Layer Platform driver
  *
  * Author: Frank Mandarino <fmandarino@endrelia.com>
  *         Endrelia Technologies Inc.
@@ -25,6 +25,7 @@
 #include <sound/driver.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
+#include <sound/pcm_params.h>
 #include <sound/initval.h>
 #include <sound/soc.h>
 
@@ -33,10 +34,10 @@
 #include <asm/arch/at91_ssc.h>
 
 #include "at91-pcm.h"
-#include "at91-i2s.h"
+#include "at91-ssc.h"
 
 #if 0
-#define	DBG(x...)	printk(KERN_DEBUG "at91-i2s:" x)
+#define	DBG(x...)	printk(KERN_DEBUG "at91-ssc:" x)
 #else
 #define	DBG(x...)
 #endif
@@ -92,33 +93,33 @@ static struct at91_ssc_mask ssc_rx_mask = {
  */
 static struct at91_pcm_dma_params ssc_dma_params[NUM_SSC_DEVICES][2] = {
 	{{
-	.name		= "SSC0/I2S PCM Stereo out",
+	.name		= "SSC0 PCM out",
 	.pdc		= &pdc_tx_reg,
 	.mask		= &ssc_tx_mask,
 	},
 	{
-	.name		= "SSC0/I2S PCM Stereo in",
+	.name		= "SSC0 PCM in",
 	.pdc		= &pdc_rx_reg,
 	.mask		= &ssc_rx_mask,
 	}},
 #if NUM_SSC_DEVICES == 3
 	{{
-	.name		= "SSC1/I2S PCM Stereo out",
+	.name		= "SSC1 PCM out",
 	.pdc		= &pdc_tx_reg,
 	.mask		= &ssc_tx_mask,
 	},
 	{
-	.name		= "SSC1/I2S PCM Stereo in",
+	.name		= "SSC1 PCM in",
 	.pdc		= &pdc_rx_reg,
 	.mask		= &ssc_rx_mask,
 	}},
 	{{
-	.name		= "SSC2/I2S PCM Stereo out",
+	.name		= "SSC2 PCM out",
 	.pdc		= &pdc_tx_reg,
 	.mask		= &ssc_tx_mask,
 	},
 	{
-	.name		= "SSC1/I2S PCM Stereo in",
+	.name		= "SSC2 PCM in",
 	.pdc		= &pdc_rx_reg,
 	.mask		= &ssc_rx_mask,
 	}},
@@ -151,33 +152,33 @@ static struct at91_ssc_info {
 } ssc_info[NUM_SSC_DEVICES] = {
 	{
 	.name		= "ssc0",
-	.lock		= SPIN_LOCK_UNLOCKED,
+	.lock		= __SPIN_LOCK_UNLOCKED(ssc_info[0].lock),
 	.dir_mask	= 0,
 	.initialized	= 0,
 	},
 #if NUM_SSC_DEVICES == 3
 	{
 	.name		= "ssc1",
-	.lock		= SPIN_LOCK_UNLOCKED,
+	.lock		= __SPIN_LOCK_UNLOCKED(ssc_info[1].lock),
 	.dir_mask	= 0,
 	.initialized	= 0,
 	},
 	{
 	.name		= "ssc2",
-	.lock		= SPIN_LOCK_UNLOCKED,
+	.lock		= __SPIN_LOCK_UNLOCKED(ssc_info[2].lock),
 	.dir_mask	= 0,
 	.initialized	= 0,
 	},
 #endif
 };
 
-static unsigned int at91_i2s_sysclk;
+static unsigned int at91_ssc_sysclk;
 
 /*
  * SSC interrupt handler.  Passes PDC interrupts to the DMA
  * interrupt handler in the PCM driver.
  */
-static irqreturn_t at91_i2s_interrupt(int irq, void *dev_id)
+static irqreturn_t at91_ssc_interrupt(int irq, void *dev_id)
 {
 	struct at91_ssc_info *ssc_p = dev_id;
 	struct at91_pcm_dma_params *dma_params;
@@ -209,13 +210,13 @@ static irqreturn_t at91_i2s_interrupt(int irq, void *dev_id)
 /*
  * Startup.  Only that one substream allowed in each direction.
  */
-static int at91_i2s_startup(struct snd_pcm_substream *substream)
+static int at91_ssc_startup(struct snd_pcm_substream *substream)
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct at91_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
 	int dir_mask;
 
-	DBG("i2s_startup: SSC_SR=0x%08lx\n",
+	DBG("ssc_startup: SSC_SR=0x%08lx\n",
 			at91_ssc_read(ssc_p->ssc.base + AT91_SSC_SR));
 	dir_mask = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0x1 : 0x2;
 
@@ -234,7 +235,7 @@ static int at91_i2s_startup(struct snd_pcm_substream *substream)
  * Shutdown.  Clear DMA parameters and shutdown the SSC if there
  * are no other substreams open.
  */
-static void at91_i2s_shutdown(struct snd_pcm_substream *substream)
+static void at91_ssc_shutdown(struct snd_pcm_substream *substream)
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct at91_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
@@ -281,7 +282,7 @@ static void at91_i2s_shutdown(struct snd_pcm_substream *substream)
 /*
  * Record the SSC system clock rate.
  */
-static int at91_i2s_set_dai_sysclk(struct snd_soc_cpu_dai *cpu_dai,
+static int at91_ssc_set_dai_sysclk(struct snd_soc_cpu_dai *cpu_dai,
 		int clk_id, unsigned int freq, int dir)
 {
 	/*
@@ -291,7 +292,7 @@ static int at91_i2s_set_dai_sysclk(struct snd_soc_cpu_dai *cpu_dai,
 	 */
 	switch (clk_id) {
 	case AT91_SYSCLK_MCK:
-		at91_i2s_sysclk = freq;
+		at91_ssc_sysclk = freq;
 		break;
 	default:
 		return -EINVAL;
@@ -303,14 +304,11 @@ static int at91_i2s_set_dai_sysclk(struct snd_soc_cpu_dai *cpu_dai,
 /*
  * Record the DAI format for use in hw_params().
  */
-static int at91_i2s_set_dai_fmt(struct snd_soc_cpu_dai *cpu_dai,
+static int at91_ssc_set_dai_fmt(struct snd_soc_cpu_dai *cpu_dai,
 		unsigned int fmt)
 {
 	struct at91_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
 
-	if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) != SND_SOC_DAIFMT_I2S)
-		return -EINVAL;
-
 	ssc_p->daifmt = fmt;
 	return 0;
 }
@@ -318,7 +316,7 @@ static int at91_i2s_set_dai_fmt(struct snd_soc_cpu_dai *cpu_dai,
 /*
  * Record SSC clock dividers for use in hw_params().
  */
-static int at91_i2s_set_dai_clkdiv(struct snd_soc_cpu_dai *cpu_dai,
+static int at91_ssc_set_dai_clkdiv(struct snd_soc_cpu_dai *cpu_dai,
 	int div_id, int div)
 {
 	struct at91_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
@@ -355,7 +353,7 @@ static int at91_i2s_set_dai_clkdiv(struct snd_soc_cpu_dai *cpu_dai,
 /*
  * Configure the SSC.
  */
-static int at91_i2s_hw_params(struct snd_pcm_substream *substream,
+static int at91_ssc_hw_params(struct snd_pcm_substream *substream,
 	struct snd_pcm_hw_params *params)
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
@@ -391,20 +389,50 @@ static int at91_i2s_hw_params(struct snd_pcm_substream *substream,
 	channels = params_channels(params);
 
 	/*
+	 * Determine sample size in bits and the PDC increment.
+	 */
+	switch(params_format(params)) {
+	case SNDRV_PCM_FORMAT_S8:
+		bits = 8;
+		dma_params->pdc_xfer_size = 1;
+		break;
+	case SNDRV_PCM_FORMAT_S16_LE:
+		bits = 16;
+		dma_params->pdc_xfer_size = 2;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		bits = 24;
+		dma_params->pdc_xfer_size = 4;
+		break;
+	case SNDRV_PCM_FORMAT_S32_LE:
+		bits = 32;
+		dma_params->pdc_xfer_size = 4;
+		break;
+	default:
+		printk(KERN_WARNING "at91-ssc: unsupported PCM format");
+		return -EINVAL;
+	}
+
+	/*
 	 * The SSC only supports up to 16-bit samples in I2S format, due
-	 * to the size of the Frame Mode Register FSLEN field.  Also, I2S
-	 * implies signed data.
+	 * to the size of the Frame Mode Register FSLEN field.
 	 */
-	bits = 16;
-	dma_params->pdc_xfer_size = 2;
+	if ((ssc_p->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S
+		&& bits > 16) {
+		printk(KERN_WARNING
+			"at91-ssc: sample size %d is too large for I2S\n", bits);
+		return -EINVAL;
+	}
 
 	/*
 	 * Compute SSC register settings.
 	 */
-	switch (ssc_p->daifmt) {
-	case SND_SOC_DAIFMT_CBS_CFS:
+	switch (ssc_p->daifmt
+		& (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_MASTER_MASK)) {
+
+	case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS:
 		/*
-		 * SSC provides BCLK and LRC clocks.
+		 * I2S format, SSC provides BCLK and LRC clocks.
 		 *
 		 * The SSC transmit and receive clocks are generated from the
 		 * MCK divider, and the BCLK signal is output on the SSC TK line.
@@ -441,10 +469,9 @@ static int at91_i2s_hw_params(struct snd_pcm_substream *substream,
 			| (((bits - 1)			<<  0) & AT91_SSC_DATALEN);
 		break;
 
-	case SND_SOC_DAIFMT_CBM_CFM:
-
+	case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM:
 		/*
-		 * CODEC supplies BCLK and LRC clocks.
+		 * I2S format, CODEC supplies BCLK and LRC clocks.
 		 *
 		 * The SSC transmit clock is obtained from the BCLK signal on
 		 * on the TK line, and the SSC receive clock is generated from the
@@ -490,10 +517,51 @@ static int at91_i2s_hw_params(struct snd_pcm_substream *substream,
 			| (((bits - 1)			<<  0) & AT91_SSC_DATALEN);
 		break;
 
-	case SND_SOC_DAIFMT_CBS_CFM:
-	case SND_SOC_DAIFMT_CBM_CFS:
+	case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS:
+		/*
+		 * DSP/PCM Mode A format, SSC provides BCLK and LRC clocks.
+		 *
+		 * The SSC transmit and receive clocks are generated from the
+		 * MCK divider, and the BCLK signal is output on the SSC TK line.
+		 */
+		rcmr =	  (( ssc_p->rcmr_period		<< 24) & AT91_SSC_PERIOD)
+			| (( 1				<< 16) & AT91_SSC_STTDLY)
+			| (( AT91_SSC_START_RISING_RF	     ) & AT91_SSC_START)
+			| (( AT91_SSC_CK_RISING		     ) & AT91_SSC_CKI)
+			| (( AT91_SSC_CKO_NONE		     ) & AT91_SSC_CKO)
+			| (( AT91_SSC_CKS_DIV		     ) & AT91_SSC_CKS);
+
+		rfmr =	  (( AT91_SSC_FSEDGE_POSITIVE	     ) & AT91_SSC_FSEDGE)
+			| (( AT91_SSC_FSOS_POSITIVE	     ) & AT91_SSC_FSOS)
+			| (( 0				<< 16) & AT91_SSC_FSLEN)
+			| (((channels - 1)		<<  8) & AT91_SSC_DATNB)
+			| (( 1				<<  7) & AT91_SSC_MSBF)
+			| (( 0				<<  5) & AT91_SSC_LOOP)
+			| (((bits - 1)			<<  0) & AT91_SSC_DATALEN);
+
+		tcmr =	  (( ssc_p->tcmr_period		<< 24) & AT91_SSC_PERIOD)
+			| (( 1				<< 16) & AT91_SSC_STTDLY)
+			| (( AT91_SSC_START_RISING_RF        ) & AT91_SSC_START)
+			| (( AT91_SSC_CK_RISING		     ) & AT91_SSC_CKI)
+			| (( AT91_SSC_CKO_CONTINUOUS	     ) & AT91_SSC_CKO)
+			| (( AT91_SSC_CKS_DIV		     ) & AT91_SSC_CKS);
+
+		tfmr =	  (( AT91_SSC_FSEDGE_POSITIVE	     ) & AT91_SSC_FSEDGE)
+			| (( 0				<< 23) & AT91_SSC_FSDEN)
+			| (( AT91_SSC_FSOS_POSITIVE	     ) & AT91_SSC_FSOS)
+			| (( 0				<< 16) & AT91_SSC_FSLEN)
+			| (((channels - 1)		<<  8) & AT91_SSC_DATNB)
+			| (( 1				<<  7) & AT91_SSC_MSBF)
+			| (( 0				<<  5) & AT91_SSC_DATDEF)
+			| (((bits - 1)			<<  0) & AT91_SSC_DATALEN);
+
+
+
+			break;
+
+	case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM:
 	default:
-		printk(KERN_WARNING "at91-i2s: unsupported DAI format 0x%x.\n",
+		printk(KERN_WARNING "at91-ssc: unsupported DAI format 0x%x.\n",
 			ssc_p->daifmt);
 		return -EINVAL;
 		break;
@@ -518,9 +586,9 @@ static int at91_i2s_hw_params(struct snd_pcm_substream *substream,
 		at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_TNPR, 0);
 		at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_TNCR, 0);
 
-		if ((ret = request_irq(ssc_p->ssc.pid, at91_i2s_interrupt,
+		if ((ret = request_irq(ssc_p->ssc.pid, at91_ssc_interrupt,
 					0, ssc_p->name, ssc_p)) < 0) {
-			printk(KERN_WARNING "at91-i2s: request_irq failure\n");
+			printk(KERN_WARNING "at91-ssc: request_irq failure\n");
 
 			DBG("Stopping pid %d clock\n", ssc_p->ssc.pid);
 			at91_sys_write(AT91_PMC_PCER, 1<<ssc_p->ssc.pid);
@@ -546,7 +614,7 @@ static int at91_i2s_hw_params(struct snd_pcm_substream *substream,
 }
 
 
-static int at91_i2s_prepare(struct snd_pcm_substream *substream)
+static int at91_ssc_prepare(struct snd_pcm_substream *substream)
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct at91_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
@@ -566,7 +634,7 @@ static int at91_i2s_prepare(struct snd_pcm_substream *substream)
 
 
 #ifdef CONFIG_PM
-static int at91_i2s_suspend(struct platform_device *pdev,
+static int at91_ssc_suspend(struct platform_device *pdev,
 	struct snd_soc_cpu_dai *cpu_dai)
 {
 	struct at91_ssc_info *ssc_p;
@@ -594,7 +662,7 @@ static int at91_i2s_suspend(struct platform_device *pdev,
 	return 0;
 }
 
-static int at91_i2s_resume(struct platform_device *pdev,
+static int at91_ssc_resume(struct platform_device *pdev,
 	struct snd_soc_cpu_dai *cpu_dai)
 {
 	struct at91_ssc_info *ssc_p;
@@ -620,102 +688,105 @@ static int at91_i2s_resume(struct platform_device *pdev,
 }
 
 #else
-#define at91_i2s_suspend	NULL
-#define at91_i2s_resume		NULL
+#define at91_ssc_suspend	NULL
+#define at91_ssc_resume		NULL
 #endif
 
-#define AT91_I2S_RATES (SNDRV_PCM_RATE_8000  | SNDRV_PCM_RATE_11025 |\
+#define AT91_SSC_RATES (SNDRV_PCM_RATE_8000  | SNDRV_PCM_RATE_11025 |\
 			SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\
 			SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\
 			SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\
 			SNDRV_PCM_RATE_96000)
 
-struct snd_soc_cpu_dai at91_i2s_dai[NUM_SSC_DEVICES] = {
-	{	.name = "at91_ssc0/i2s",
+#define AT91_SSC_FORMATS (SNDRV_PCM_FMTBIT_S8     | SNDRV_PCM_FMTBIT_S16_LE |\
+			  SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+struct snd_soc_cpu_dai at91_ssc_dai[NUM_SSC_DEVICES] = {
+	{	.name = "at91-ssc0",
 		.id = 0,
-		.type = SND_SOC_DAI_I2S,
-		.suspend = at91_i2s_suspend,
-		.resume = at91_i2s_resume,
+		.type = SND_SOC_DAI_PCM,
+		.suspend = at91_ssc_suspend,
+		.resume = at91_ssc_resume,
 		.playback = {
 			.channels_min = 1,
 			.channels_max = 2,
-			.rates = AT91_I2S_RATES,
-			.formats = SNDRV_PCM_FMTBIT_S16_LE,},
+			.rates = AT91_SSC_RATES,
+			.formats = AT91_SSC_FORMATS,},
 		.capture = {
 			.channels_min = 1,
 			.channels_max = 2,
-			.rates = AT91_I2S_RATES,
-			.formats = SNDRV_PCM_FMTBIT_S16_LE,},
+			.rates = AT91_SSC_RATES,
+			.formats = AT91_SSC_FORMATS,},
 		.ops = {
-			.startup = at91_i2s_startup,
-			.shutdown = at91_i2s_shutdown,
-			.prepare = at91_i2s_prepare,
-			.hw_params = at91_i2s_hw_params,},
+			.startup = at91_ssc_startup,
+			.shutdown = at91_ssc_shutdown,
+			.prepare = at91_ssc_prepare,
+			.hw_params = at91_ssc_hw_params,},
 		.dai_ops = {
-			.set_sysclk = at91_i2s_set_dai_sysclk,
-			.set_fmt = at91_i2s_set_dai_fmt,
-			.set_clkdiv = at91_i2s_set_dai_clkdiv,},
+			.set_sysclk = at91_ssc_set_dai_sysclk,
+			.set_fmt = at91_ssc_set_dai_fmt,
+			.set_clkdiv = at91_ssc_set_dai_clkdiv,},
 		.private_data = &ssc_info[0].ssc,
 	},
 #if NUM_SSC_DEVICES == 3
-	{	.name = "at91_ssc1/i2s",
+	{	.name = "at91-ssc1",
 		.id = 1,
-		.type = SND_SOC_DAI_I2S,
-		.suspend = at91_i2s_suspend,
-		.resume = at91_i2s_resume,
+		.type = SND_SOC_DAI_PCM,
+		.suspend = at91_ssc_suspend,
+		.resume = at91_ssc_resume,
 		.playback = {
 			.channels_min = 1,
 			.channels_max = 2,
-			.rates = AT91_I2S_RATES,
-			.formats = SNDRV_PCM_FMTBIT_S16_LE,},
+			.rates = AT91_SSC_RATES,
+			.formats = AT91_SSC_FORMATS,},
 		.capture = {
 			.channels_min = 1,
 			.channels_max = 2,
-			.rates = AT91_I2S_RATES,
-			.formats = SNDRV_PCM_FMTBIT_S16_LE,},
+			.rates = AT91_SSC_RATES,
+			.formats = AT91_SSC_FORMATS,},
 		.ops = {
-			.startup = at91_i2s_startup,
-			.shutdown = at91_i2s_shutdown,
-			.prepare = at91_i2s_prepare,
-			.hw_params = at91_i2s_hw_params,},
+			.startup = at91_ssc_startup,
+			.shutdown = at91_ssc_shutdown,
+			.prepare = at91_ssc_prepare,
+			.hw_params = at91_ssc_hw_params,},
 		.dai_ops = {
-			.set_sysclk = at91_i2s_set_dai_sysclk,
-			.set_fmt = at91_i2s_set_dai_fmt,
-			.set_clkdiv = at91_i2s_set_dai_clkdiv,},
+			.set_sysclk = at91_ssc_set_dai_sysclk,
+			.set_fmt = at91_ssc_set_dai_fmt,
+			.set_clkdiv = at91_ssc_set_dai_clkdiv,},
 		.private_data = &ssc_info[1].ssc,
 	},
-	{	.name = "at91_ssc2/i2s",
+	{	.name = "at91-ssc2",
 		.id = 2,
-		.type = SND_SOC_DAI_I2S,
-		.suspend = at91_i2s_suspend,
-		.resume = at91_i2s_resume,
+		.type = SND_SOC_DAI_PCM,
+		.suspend = at91_ssc_suspend,
+		.resume = at91_ssc_resume,
 		.playback = {
 			.channels_min = 1,
 			.channels_max = 2,
-			.rates = AT91_I2S_RATES,
-			.formats = SNDRV_PCM_FMTBIT_S16_LE,},
+			.rates = AT91_SSC_RATES,
+			.formats = AT91_SSC_FORMATS,},
 		.capture = {
 			.channels_min = 1,
 			.channels_max = 2,
-			.rates = AT91_I2S_RATES,
-			.formats = SNDRV_PCM_FMTBIT_S16_LE,},
+			.rates = AT91_SSC_RATES,
+			.formats = AT91_SSC_FORMATS,},
 		.ops = {
-			.startup = at91_i2s_startup,
-			.shutdown = at91_i2s_shutdown,
-			.prepare = at91_i2s_prepare,
-			.hw_params = at91_i2s_hw_params,},
+			.startup = at91_ssc_startup,
+			.shutdown = at91_ssc_shutdown,
+			.prepare = at91_ssc_prepare,
+			.hw_params = at91_ssc_hw_params,},
 		.dai_ops = {
-			.set_sysclk = at91_i2s_set_dai_sysclk,
-			.set_fmt = at91_i2s_set_dai_fmt,
-			.set_clkdiv = at91_i2s_set_dai_clkdiv,},
+			.set_sysclk = at91_ssc_set_dai_sysclk,
+			.set_fmt = at91_ssc_set_dai_fmt,
+			.set_clkdiv = at91_ssc_set_dai_clkdiv,},
 		.private_data = &ssc_info[2].ssc,
 	},
 #endif
 };
 
-EXPORT_SYMBOL_GPL(at91_i2s_dai);
+EXPORT_SYMBOL_GPL(at91_ssc_dai);
 
 /* Module information */
 MODULE_AUTHOR("Frank Mandarino, fmandarino@endrelia.com, www.endrelia.com");
-MODULE_DESCRIPTION("AT91 I2S ASoC Interface");
+MODULE_DESCRIPTION("AT91 SSC ASoC Interface");
 MODULE_LICENSE("GPL");
diff --git a/sound/soc/at91/at91-i2s.h b/sound/soc/at91/at91-ssc.h
index f8a875ba0ccc..b188f973df9f 100644
--- a/sound/soc/at91/at91-i2s.h
+++ b/sound/soc/at91/at91-ssc.h
@@ -1,5 +1,5 @@
 /*
- * at91-i2s.h - ALSA I2S interface for the Atmel AT91 SoC
+ * at91-ssc.h - ALSA SSC interface for the Atmel AT91 SoC
  *
  * Author:	Frank Mandarino <fmandarino@endrelia.com>
  *		Endrelia Technologies Inc.
@@ -10,18 +10,18 @@
  * published by the Free Software Foundation.
  */
 
-#ifndef _AT91_I2S_H
-#define _AT91_I2S_H
+#ifndef _AT91_SSC_H
+#define _AT91_SSC_H
 
-/* I2S system clock ids */
+/* SSC system clock ids */
 #define AT91_SYSCLK_MCK		0 /* SSC uses AT91 MCK as system clock */
 
-/* I2S divider ids */
+/* SSC divider ids */
 #define AT91SSC_CMR_DIV		0 /* MCK divider for BCLK */
 #define AT91SSC_TCMR_PERIOD	1 /* BCLK divider for transmit FS */
 #define AT91SSC_RCMR_PERIOD	2 /* BCLK divider for receive FS */
 
-extern struct snd_soc_cpu_dai at91_i2s_dai[];
+extern struct snd_soc_cpu_dai at91_ssc_dai[];
 
-#endif /* _AT91_I2S_H */
+#endif /* _AT91_SSC_H */
 
diff --git a/sound/soc/at91/eti_b1_wm8731.c b/sound/soc/at91/eti_b1_wm8731.c
index 8179df3bb2f3..820a676c56bf 100644
--- a/sound/soc/at91/eti_b1_wm8731.c
+++ b/sound/soc/at91/eti_b1_wm8731.c
@@ -40,7 +40,7 @@
 
 #include "../codecs/wm8731.h"
 #include "at91-pcm.h"
-#include "at91-i2s.h"
+#include "at91-ssc.h"
 
 #if 0
 #define	DBG(x...)	printk(KERN_INFO "eti_b1_wm8731: " x)
@@ -248,15 +248,15 @@ static int eti_b1_wm8731_init(struct snd_soc_codec *codec)
 
 static struct snd_soc_dai_link eti_b1_dai = {
 	.name = "WM8731",
-	.stream_name = "WM8731",
-	.cpu_dai = &at91_i2s_dai[1],
+	.stream_name = "WM8731 PCM",
+	.cpu_dai = &at91_ssc_dai[1],
 	.codec_dai = &wm8731_dai,
 	.init = eti_b1_wm8731_init,
 	.ops = &eti_b1_ops,
 };
 
 static struct snd_soc_machine snd_soc_machine_eti_b1 = {
-	.name = "ETI_B1",
+	.name = "ETI_B1_WM8731",
 	.dai_link = &eti_b1_dai,
 	.num_links = 1,
 };
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index ec2a2787957a..e5fb437b86e8 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -10,6 +10,10 @@ config SND_SOC_WM8750
 	tristate
 	depends on SND_SOC
 
+config SND_SOC_WM8753
+	tristate
+	depends on SND_SOC
+
 config SND_SOC_WM9712
 	tristate
 	depends on SND_SOC
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 3249a6e4f1d0..e39a747a17cf 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -1,9 +1,11 @@
 snd-soc-ac97-objs := ac97.o
 snd-soc-wm8731-objs := wm8731.o
 snd-soc-wm8750-objs := wm8750.o
+snd-soc-wm8753-objs := wm8753.o
 snd-soc-wm9712-objs := wm9712.o
 
 obj-$(CONFIG_SND_SOC_AC97_CODEC)	+= snd-soc-ac97.o
 obj-$(CONFIG_SND_SOC_WM8731)	+= snd-soc-wm8731.o
 obj-$(CONFIG_SND_SOC_WM8750)	+= snd-soc-wm8750.o
+obj-$(CONFIG_SND_SOC_WM8753)	+= snd-soc-wm8753.o
 obj-$(CONFIG_SND_SOC_WM9712)	+= snd-soc-wm9712.o
diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c
index 55bc55eb6e24..0cdef971cbd3 100644
--- a/sound/soc/codecs/ac97.c
+++ b/sound/soc/codecs/ac97.c
@@ -60,6 +60,7 @@ static struct snd_soc_codec_dai ac97_dai = {
 	.ops = {
 		.prepare = ac97_prepare,},
 };
+EXPORT_SYMBOL_GPL(ac97_dai);
 
 static unsigned int ac97_read(struct snd_soc_codec *codec,
 	unsigned int reg)
diff --git a/sound/soc/codecs/ac97.h b/sound/soc/codecs/ac97.h
index 930ddfc2321a..2bf6d69fd069 100644
--- a/sound/soc/codecs/ac97.h
+++ b/sound/soc/codecs/ac97.h
@@ -14,5 +14,6 @@
 #define __LINUX_SND_SOC_AC97_H
 
 extern struct snd_soc_codec_device soc_codec_dev_ac97;
+extern struct snd_soc_codec_dai ac97_dai;
 
 #endif
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c
index 7073e8e294fc..28684eeda738 100644
--- a/sound/soc/codecs/wm8750.c
+++ b/sound/soc/codecs/wm8750.c
@@ -808,7 +808,7 @@ static int wm8750_init(struct snd_soc_device *socdev)
 	codec->dai = &wm8750_dai;
 	codec->num_dai = 1;
 	codec->reg_cache_size = sizeof(wm8750_reg);
-	codec->reg_cache = kmemdup(wm8750_reg, sizeof(wm8750_reg), GFP_KRENEL);
+	codec->reg_cache = kmemdup(wm8750_reg, sizeof(wm8750_reg), GFP_KERNEL);
 	if (codec->reg_cache == NULL)
 		return -ENOMEM;
 
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
new file mode 100644
index 000000000000..efced934566d
--- /dev/null
+++ b/sound/soc/codecs/wm8753.c
@@ -0,0 +1,1811 @@
+/*
+ * wm8753.c  --  WM8753 ALSA Soc Audio driver
+ *
+ * Copyright 2003 Wolfson Microelectronics PLC.
+ * Author: Liam Girdwood
+ *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ *
+ *  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.
+ *
+ * Notes:
+ *  The WM8753 is a low power, high quality stereo codec with integrated PCM
+ *  codec designed for portable digital telephony applications.
+ *
+ * Dual DAI:-
+ *
+ * This driver support 2 DAI PCM's. This makes the default PCM available for
+ * HiFi audio (e.g. MP3, ogg) playback/capture and the other PCM available for
+ * voice.
+ *
+ * Please note that the voice PCM can be connected directly to a Bluetooth
+ * codec or GSM modem and thus cannot be read or written to, although it is
+ * available to be configured with snd_hw_params(), etc and kcontrols in the
+ * normal alsa manner.
+ *
+ * Fast DAI switching:-
+ *
+ * The driver can now fast switch between the DAI configurations via a
+ * an alsa kcontrol. This allows the PCM to remain open.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <asm/div64.h>
+
+#include "wm8753.h"
+
+#define AUDIO_NAME "wm8753"
+#define WM8753_VERSION "0.16"
+
+/*
+ * Debug
+ */
+
+#define WM8753_DEBUG 0
+
+#ifdef WM8753_DEBUG
+#define dbg(format, arg...) \
+	printk(KERN_DEBUG AUDIO_NAME ": " format "\n" , ## arg)
+#else
+#define dbg(format, arg...) do {} while (0)
+#endif
+#define err(format, arg...) \
+	printk(KERN_ERR AUDIO_NAME ": " format "\n" , ## arg)
+#define info(format, arg...) \
+	printk(KERN_INFO AUDIO_NAME ": " format "\n" , ## arg)
+#define warn(format, arg...) \
+	printk(KERN_WARNING AUDIO_NAME ": " format "\n" , ## arg)
+
+static int caps_charge = 2000;
+module_param(caps_charge, int, 0);
+MODULE_PARM_DESC(caps_charge, "WM8753 cap charge time (msecs)");
+
+static void wm8753_set_dai_mode(struct snd_soc_codec *codec,
+	unsigned int mode);
+
+/* codec private data */
+struct wm8753_priv {
+	unsigned int sysclk;
+	unsigned int pcmclk;
+};
+
+/*
+ * wm8753 register cache
+ * We can't read the WM8753 register space when we
+ * are using 2 wire for device control, so we cache them instead.
+ */
+static const u16 wm8753_reg[] = {
+	0x0008, 0x0000, 0x000a, 0x000a,
+	0x0033, 0x0000, 0x0007, 0x00ff,
+	0x00ff, 0x000f, 0x000f, 0x007b,
+	0x0000, 0x0032, 0x0000, 0x00c3,
+	0x00c3, 0x00c0, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0055,
+	0x0005, 0x0050, 0x0055, 0x0050,
+	0x0055, 0x0050, 0x0055, 0x0079,
+	0x0079, 0x0079, 0x0079, 0x0079,
+	0x0000, 0x0000, 0x0000, 0x0000,
+	0x0097, 0x0097, 0x0000, 0x0004,
+	0x0000, 0x0083, 0x0024, 0x01ba,
+	0x0000, 0x0083, 0x0024, 0x01ba,
+	0x0000, 0x0000
+};
+
+/*
+ * read wm8753 register cache
+ */
+static inline unsigned int wm8753_read_reg_cache(struct snd_soc_codec *codec,
+	unsigned int reg)
+{
+	u16 *cache = codec->reg_cache;
+	if (reg < 1 || reg > (ARRAY_SIZE(wm8753_reg) + 1))
+		return -1;
+	return cache[reg - 1];
+}
+
+/*
+ * write wm8753 register cache
+ */
+static inline void wm8753_write_reg_cache(struct snd_soc_codec *codec,
+	unsigned int reg, unsigned int value)
+{
+	u16 *cache = codec->reg_cache;
+	if (reg < 1 || reg > 0x3f)
+		return;
+	cache[reg - 1] = value;
+}
+
+/*
+ * write to the WM8753 register space
+ */
+static int wm8753_write(struct snd_soc_codec *codec, unsigned int reg,
+	unsigned int value)
+{
+	u8 data[2];
+
+	/* data is
+	 *   D15..D9 WM8753 register offset
+	 *   D8...D0 register data
+	 */
+	data[0] = (reg << 1) | ((value >> 8) & 0x0001);
+	data[1] = value & 0x00ff;
+
+	wm8753_write_reg_cache (codec, reg, value);
+	if (codec->hw_write(codec->control_data, data, 2) == 2)
+		return 0;
+	else
+		return -EIO;
+}
+
+#define wm8753_reset(c) wm8753_write(c, WM8753_RESET, 0)
+
+/*
+ * WM8753 Controls
+ */
+static const char *wm8753_base[] = {"Linear Control", "Adaptive Boost"};
+static const char *wm8753_base_filter[] =
+	{"130Hz @ 48kHz", "200Hz @ 48kHz", "100Hz @ 16kHz", "400Hz @ 48kHz",
+	"100Hz @ 8kHz", "200Hz @ 8kHz"};
+static const char *wm8753_treble[] = {"8kHz", "4kHz"};
+static const char *wm8753_alc_func[] = {"Off", "Right", "Left", "Stereo"};
+static const char *wm8753_ng_type[] = {"Constant PGA Gain", "Mute ADC Output"};
+static const char *wm8753_3d_func[] = {"Capture", "Playback"};
+static const char *wm8753_3d_uc[] = {"2.2kHz", "1.5kHz"};
+static const char *wm8753_3d_lc[] = {"200Hz", "500Hz"};
+static const char *wm8753_deemp[] = {"None", "32kHz", "44.1kHz", "48kHz"};
+static const char *wm8753_mono_mix[] = {"Stereo", "Left", "Right", "Mono"};
+static const char *wm8753_dac_phase[] = {"Non Inverted", "Inverted"};
+static const char *wm8753_line_mix[] = {"Line 1 + 2", "Line 1 - 2",
+	"Line 1", "Line 2"};
+static const char *wm8753_mono_mux[] = {"Line Mix", "Rx Mix"};
+static const char *wm8753_right_mux[] = {"Line 2", "Rx Mix"};
+static const char *wm8753_left_mux[] = {"Line 1", "Rx Mix"};
+static const char *wm8753_rxmsel[] = {"RXP - RXN", "RXP + RXN", "RXP", "RXN"};
+static const char *wm8753_sidetone_mux[] = {"Left PGA", "Mic 1", "Mic 2",
+	"Right PGA"};
+static const char *wm8753_mono2_src[] = {"Inverted Mono 1", "Left", "Right",
+	"Left + Right"};
+static const char *wm8753_out3[] = {"VREF", "ROUT2", "Left + Right"};
+static const char *wm8753_out4[] = {"VREF", "Capture ST", "LOUT2"};
+static const char *wm8753_radcsel[] = {"PGA", "Line or RXP-RXN", "Sidetone"};
+static const char *wm8753_ladcsel[] = {"PGA", "Line or RXP-RXN", "Line"};
+static const char *wm8753_mono_adc[] = {"Stereo", "Analogue Mix Left",
+	"Analogue Mix Right", "Digital Mono Mix"};
+static const char *wm8753_adc_hp[] = {"3.4Hz @ 48kHz", "82Hz @ 16k",
+	"82Hz @ 8kHz", "170Hz @ 8kHz"};
+static const char *wm8753_adc_filter[] = {"HiFi", "Voice"};
+static const char *wm8753_mic_sel[] = {"Mic 1", "Mic 2", "Mic 3"};
+static const char *wm8753_dai_mode[] = {"DAI 0", "DAI 1", "DAI 2", "DAI 3"};
+static const char *wm8753_dat_sel[] = {"Stereo", "Left ADC", "Right ADC",
+	"Channel Swap"};
+
+static const struct soc_enum wm8753_enum[] = {
+SOC_ENUM_SINGLE(WM8753_BASS, 7, 2, wm8753_base),
+SOC_ENUM_SINGLE(WM8753_BASS, 4, 6, wm8753_base_filter),
+SOC_ENUM_SINGLE(WM8753_TREBLE, 6, 2, wm8753_treble),
+SOC_ENUM_SINGLE(WM8753_ALC1, 7, 4, wm8753_alc_func),
+SOC_ENUM_SINGLE(WM8753_NGATE, 1, 2, wm8753_ng_type),
+SOC_ENUM_SINGLE(WM8753_3D, 7, 2, wm8753_3d_func),
+SOC_ENUM_SINGLE(WM8753_3D, 6, 2, wm8753_3d_uc),
+SOC_ENUM_SINGLE(WM8753_3D, 5, 2, wm8753_3d_lc),
+SOC_ENUM_SINGLE(WM8753_DAC, 1, 4, wm8753_deemp),
+SOC_ENUM_SINGLE(WM8753_DAC, 4, 4, wm8753_mono_mix),
+SOC_ENUM_SINGLE(WM8753_DAC, 6, 2, wm8753_dac_phase),
+SOC_ENUM_SINGLE(WM8753_INCTL1, 3, 4, wm8753_line_mix),
+SOC_ENUM_SINGLE(WM8753_INCTL1, 2, 2, wm8753_mono_mux),
+SOC_ENUM_SINGLE(WM8753_INCTL1, 1, 2, wm8753_right_mux),
+SOC_ENUM_SINGLE(WM8753_INCTL1, 0, 2, wm8753_left_mux),
+SOC_ENUM_SINGLE(WM8753_INCTL2, 6, 4, wm8753_rxmsel),
+SOC_ENUM_SINGLE(WM8753_INCTL2, 4, 4, wm8753_sidetone_mux),
+SOC_ENUM_SINGLE(WM8753_OUTCTL, 7, 4, wm8753_mono2_src),
+SOC_ENUM_SINGLE(WM8753_OUTCTL, 0, 3, wm8753_out3),
+SOC_ENUM_SINGLE(WM8753_ADCTL2, 7, 3, wm8753_out4),
+SOC_ENUM_SINGLE(WM8753_ADCIN, 2, 3, wm8753_radcsel),
+SOC_ENUM_SINGLE(WM8753_ADCIN, 0, 3, wm8753_ladcsel),
+SOC_ENUM_SINGLE(WM8753_ADCIN, 4, 4, wm8753_mono_adc),
+SOC_ENUM_SINGLE(WM8753_ADC, 2, 4, wm8753_adc_hp),
+SOC_ENUM_SINGLE(WM8753_ADC, 4, 2, wm8753_adc_filter),
+SOC_ENUM_SINGLE(WM8753_MICBIAS, 6, 3, wm8753_mic_sel),
+SOC_ENUM_SINGLE(WM8753_IOCTL, 2, 4, wm8753_dai_mode),
+SOC_ENUM_SINGLE(WM8753_ADC, 7, 4, wm8753_dat_sel),
+};
+
+
+static int wm8753_get_dai(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
+	int mode = wm8753_read_reg_cache(codec, WM8753_IOCTL);
+
+	ucontrol->value.integer.value[0] = (mode & 0xc) >> 2;
+	return 0;
+}
+
+static int wm8753_set_dai(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
+	int mode = wm8753_read_reg_cache(codec, WM8753_IOCTL);
+
+	if (((mode &0xc) >> 2) == ucontrol->value.integer.value[0])
+		return 0;
+
+	mode &= 0xfff3;
+	mode |= (ucontrol->value.integer.value[0] << 2);
+
+	wm8753_write(codec, WM8753_IOCTL, mode);
+	wm8753_set_dai_mode(codec, ucontrol->value.integer.value[0]);
+	return 1;
+}
+
+static const struct snd_kcontrol_new wm8753_snd_controls[] = {
+SOC_DOUBLE_R("PCM Volume", WM8753_LDAC, WM8753_RDAC, 0, 255, 0),
+
+SOC_DOUBLE_R("ADC Capture Volume", WM8753_LADC, WM8753_RADC, 0, 255, 0),
+
+SOC_DOUBLE_R("Headphone Playback Volume", WM8753_LOUT1V, WM8753_ROUT1V, 0, 127, 0),
+SOC_DOUBLE_R("Speaker Playback Volume", WM8753_LOUT2V, WM8753_ROUT2V, 0, 127, 0),
+
+SOC_SINGLE("Mono Playback Volume", WM8753_MOUTV, 0, 127, 0),
+
+SOC_DOUBLE_R("Bypass Playback Volume", WM8753_LOUTM1, WM8753_ROUTM1, 4, 7, 1),
+SOC_DOUBLE_R("Sidetone Playback Volume", WM8753_LOUTM2, WM8753_ROUTM2, 4, 7, 1),
+SOC_DOUBLE_R("Voice Playback Volume", WM8753_LOUTM2, WM8753_ROUTM2, 0, 7, 1),
+
+SOC_DOUBLE_R("Headphone Playback ZC Switch", WM8753_LOUT1V, WM8753_ROUT1V, 7, 1, 0),
+SOC_DOUBLE_R("Speaker Playback ZC Switch", WM8753_LOUT2V, WM8753_ROUT2V, 7, 1, 0),
+
+SOC_SINGLE("Mono Bypass Playback Volume", WM8753_MOUTM1, 4, 7, 1),
+SOC_SINGLE("Mono Sidetone Playback Volume", WM8753_MOUTM2, 4, 7, 1),
+SOC_SINGLE("Mono Voice Playback Volume", WM8753_MOUTM2, 4, 7, 1),
+SOC_SINGLE("Mono Playback ZC Switch", WM8753_MOUTV, 7, 1, 0),
+
+SOC_ENUM("Bass Boost", wm8753_enum[0]),
+SOC_ENUM("Bass Filter", wm8753_enum[1]),
+SOC_SINGLE("Bass Volume", WM8753_BASS, 0, 15, 1),
+
+SOC_SINGLE("Treble Volume", WM8753_TREBLE, 0, 15, 1),
+SOC_ENUM("Treble Cut-off", wm8753_enum[2]),
+
+SOC_DOUBLE("Sidetone Capture Volume", WM8753_RECMIX1, 0, 4, 7, 1),
+SOC_SINGLE("Voice Sidetone Capture Volume", WM8753_RECMIX2, 0, 7, 1),
+
+SOC_DOUBLE_R("Capture Volume", WM8753_LINVOL, WM8753_RINVOL, 0, 63, 0),
+SOC_DOUBLE_R("Capture ZC Switch", WM8753_LINVOL, WM8753_RINVOL, 6, 1, 0),
+SOC_DOUBLE_R("Capture Switch", WM8753_LINVOL, WM8753_RINVOL, 7, 1, 1),
+
+SOC_ENUM("Capture Filter Select", wm8753_enum[23]),
+SOC_ENUM("Capture Filter Cut-off", wm8753_enum[24]),
+SOC_SINGLE("Capture Filter Switch", WM8753_ADC, 0, 1, 1),
+
+SOC_SINGLE("ALC Capture Target Volume", WM8753_ALC1, 0, 7, 0),
+SOC_SINGLE("ALC Capture Max Volume", WM8753_ALC1, 4, 7, 0),
+SOC_ENUM("ALC Capture Function", wm8753_enum[3]),
+SOC_SINGLE("ALC Capture ZC Switch", WM8753_ALC2, 8, 1, 0),
+SOC_SINGLE("ALC Capture Hold Time", WM8753_ALC2, 0, 15, 1),
+SOC_SINGLE("ALC Capture Decay Time", WM8753_ALC3, 4, 15, 1),
+SOC_SINGLE("ALC Capture Attack Time", WM8753_ALC3, 0, 15, 0),
+SOC_SINGLE("ALC Capture NG Threshold", WM8753_NGATE, 3, 31, 0),
+SOC_ENUM("ALC Capture NG Type", wm8753_enum[4]),
+SOC_SINGLE("ALC Capture NG Switch", WM8753_NGATE, 0, 1, 0),
+
+SOC_ENUM("3D Function", wm8753_enum[5]),
+SOC_ENUM("3D Upper Cut-off", wm8753_enum[6]),
+SOC_ENUM("3D Lower Cut-off", wm8753_enum[7]),
+SOC_SINGLE("3D Volume", WM8753_3D, 1, 15, 0),
+SOC_SINGLE("3D Switch", WM8753_3D, 0, 1, 0),
+
+SOC_SINGLE("Capture 6dB Attenuate", WM8753_ADCTL1, 2, 1, 0),
+SOC_SINGLE("Playback 6dB Attenuate", WM8753_ADCTL1, 1, 1, 0),
+
+SOC_ENUM("De-emphasis", wm8753_enum[8]),
+SOC_ENUM("Playback Mono Mix", wm8753_enum[9]),
+SOC_ENUM("Playback Phase", wm8753_enum[10]),
+
+SOC_SINGLE("Mic2 Capture Volume", WM8753_INCTL1, 7, 3, 0),
+SOC_SINGLE("Mic1 Capture Volume", WM8753_INCTL1, 5, 3, 0),
+
+SOC_ENUM_EXT("DAI Mode", wm8753_enum[26], wm8753_get_dai, wm8753_set_dai),
+
+SOC_ENUM("ADC Data Select", wm8753_enum[27]),
+};
+
+/* add non dapm controls */
+static int wm8753_add_controls(struct snd_soc_codec *codec)
+{
+	int err, i;
+
+	for (i = 0; i < ARRAY_SIZE(wm8753_snd_controls); i++) {
+		err = snd_ctl_add(codec->card,
+				snd_soc_cnew(&wm8753_snd_controls[i],codec, NULL));
+		if (err < 0)
+			return err;
+	}
+	return 0;
+}
+
+/*
+ * _DAPM_ Controls
+ */
+
+/* Left Mixer */
+static const struct snd_kcontrol_new wm8753_left_mixer_controls[] = {
+SOC_DAPM_SINGLE("Voice Playback Switch", WM8753_LOUTM2, 8, 1, 0),
+SOC_DAPM_SINGLE("Sidetone Playback Switch", WM8753_LOUTM2, 7, 1, 0),
+SOC_DAPM_SINGLE("Left Playback Switch", WM8753_LOUTM1, 8, 1, 0),
+SOC_DAPM_SINGLE("Bypass Playback Switch", WM8753_LOUTM1, 7, 1, 0),
+};
+
+/* Right mixer */
+static const struct snd_kcontrol_new wm8753_right_mixer_controls[] = {
+SOC_DAPM_SINGLE("Voice Playback Switch", WM8753_ROUTM2, 8, 1, 0),
+SOC_DAPM_SINGLE("Sidetone Playback Switch", WM8753_ROUTM2, 7, 1, 0),
+SOC_DAPM_SINGLE("Right Playback Switch", WM8753_ROUTM1, 8, 1, 0),
+SOC_DAPM_SINGLE("Bypass Playback Switch", WM8753_ROUTM1, 7, 1, 0),
+};
+
+/* Mono mixer */
+static const struct snd_kcontrol_new wm8753_mono_mixer_controls[] = {
+SOC_DAPM_SINGLE("Left Playback Switch", WM8753_MOUTM1, 8, 1, 0),
+SOC_DAPM_SINGLE("Right Playback Switch", WM8753_MOUTM2, 8, 1, 0),
+SOC_DAPM_SINGLE("Voice Playback Switch", WM8753_MOUTM2, 3, 1, 0),
+SOC_DAPM_SINGLE("Sidetone Playback Switch", WM8753_MOUTM2, 7, 1, 0),
+SOC_DAPM_SINGLE("Bypass Playback Switch", WM8753_MOUTM1, 7, 1, 0),
+};
+
+/* Mono 2 Mux */
+static const struct snd_kcontrol_new wm8753_mono2_controls =
+SOC_DAPM_ENUM("Route", wm8753_enum[17]);
+
+/* Out 3 Mux */
+static const struct snd_kcontrol_new wm8753_out3_controls =
+SOC_DAPM_ENUM("Route", wm8753_enum[18]);
+
+/* Out 4 Mux */
+static const struct snd_kcontrol_new wm8753_out4_controls =
+SOC_DAPM_ENUM("Route", wm8753_enum[19]);
+
+/* ADC Mono Mix */
+static const struct snd_kcontrol_new wm8753_adc_mono_controls =
+SOC_DAPM_ENUM("Route", wm8753_enum[22]);
+
+/* Record mixer */
+static const struct snd_kcontrol_new wm8753_record_mixer_controls[] = {
+SOC_DAPM_SINGLE("Voice Capture Switch", WM8753_RECMIX2, 3, 1, 0),
+SOC_DAPM_SINGLE("Left Capture Switch", WM8753_RECMIX1, 3, 1, 0),
+SOC_DAPM_SINGLE("Right Capture Switch", WM8753_RECMIX1, 7, 1, 0),
+};
+
+/* Left ADC mux */
+static const struct snd_kcontrol_new wm8753_adc_left_controls =
+SOC_DAPM_ENUM("Route", wm8753_enum[21]);
+
+/* Right ADC mux */
+static const struct snd_kcontrol_new wm8753_adc_right_controls =
+SOC_DAPM_ENUM("Route", wm8753_enum[20]);
+
+/* MIC mux */
+static const struct snd_kcontrol_new wm8753_mic_mux_controls =
+SOC_DAPM_ENUM("Route", wm8753_enum[16]);
+
+/* ALC mixer */
+static const struct snd_kcontrol_new wm8753_alc_mixer_controls[] = {
+SOC_DAPM_SINGLE("Line Capture Switch", WM8753_INCTL2, 3, 1, 0),
+SOC_DAPM_SINGLE("Mic2 Capture Switch", WM8753_INCTL2, 2, 1, 0),
+SOC_DAPM_SINGLE("Mic1 Capture Switch", WM8753_INCTL2, 1, 1, 0),
+SOC_DAPM_SINGLE("Rx Capture Switch", WM8753_INCTL2, 0, 1, 0),
+};
+
+/* Left Line mux */
+static const struct snd_kcontrol_new wm8753_line_left_controls =
+SOC_DAPM_ENUM("Route", wm8753_enum[14]);
+
+/* Right Line mux */
+static const struct snd_kcontrol_new wm8753_line_right_controls =
+SOC_DAPM_ENUM("Route", wm8753_enum[13]);
+
+/* Mono Line mux */
+static const struct snd_kcontrol_new wm8753_line_mono_controls =
+SOC_DAPM_ENUM("Route", wm8753_enum[12]);
+
+/* Line mux and mixer */
+static const struct snd_kcontrol_new wm8753_line_mux_mix_controls =
+SOC_DAPM_ENUM("Route", wm8753_enum[11]);
+
+/* Rx mux and mixer */
+static const struct snd_kcontrol_new wm8753_rx_mux_mix_controls =
+SOC_DAPM_ENUM("Route", wm8753_enum[15]);
+
+/* Mic Selector Mux */
+static const struct snd_kcontrol_new wm8753_mic_sel_mux_controls =
+SOC_DAPM_ENUM("Route", wm8753_enum[25]);
+
+static const struct snd_soc_dapm_widget wm8753_dapm_widgets[] = {
+SND_SOC_DAPM_MICBIAS("Mic Bias", WM8753_PWR1, 5, 0),
+SND_SOC_DAPM_MIXER("Left Mixer", WM8753_PWR4, 0, 0,
+	&wm8753_left_mixer_controls[0], ARRAY_SIZE(wm8753_left_mixer_controls)),
+SND_SOC_DAPM_PGA("Left Out 1", WM8753_PWR3, 8, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Left Out 2", WM8753_PWR3, 6, 0, NULL, 0),
+SND_SOC_DAPM_DAC("Left DAC", "Left HiFi Playback", WM8753_PWR1, 3, 0),
+SND_SOC_DAPM_OUTPUT("LOUT1"),
+SND_SOC_DAPM_OUTPUT("LOUT2"),
+SND_SOC_DAPM_MIXER("Right Mixer", WM8753_PWR4, 1, 0,
+	&wm8753_right_mixer_controls[0], ARRAY_SIZE(wm8753_right_mixer_controls)),
+SND_SOC_DAPM_PGA("Right Out 1", WM8753_PWR3, 7, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Right Out 2", WM8753_PWR3, 5, 0, NULL, 0),
+SND_SOC_DAPM_DAC("Right DAC", "Right HiFi Playback", WM8753_PWR1, 2, 0),
+SND_SOC_DAPM_OUTPUT("ROUT1"),
+SND_SOC_DAPM_OUTPUT("ROUT2"),
+SND_SOC_DAPM_MIXER("Mono Mixer", WM8753_PWR4, 2, 0,
+	&wm8753_mono_mixer_controls[0], ARRAY_SIZE(wm8753_mono_mixer_controls)),
+SND_SOC_DAPM_PGA("Mono Out 1", WM8753_PWR3, 2, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Mono Out 2", WM8753_PWR3, 1, 0, NULL, 0),
+SND_SOC_DAPM_DAC("Voice DAC", "Voice Playback", WM8753_PWR1, 4, 0),
+SND_SOC_DAPM_OUTPUT("MONO1"),
+SND_SOC_DAPM_MUX("Mono 2 Mux", SND_SOC_NOPM, 0, 0, &wm8753_mono2_controls),
+SND_SOC_DAPM_OUTPUT("MONO2"),
+SND_SOC_DAPM_MIXER("Out3 Left + Right", -1, 0, 0, NULL, 0),
+SND_SOC_DAPM_MUX("Out3 Mux", SND_SOC_NOPM, 0, 0, &wm8753_out3_controls),
+SND_SOC_DAPM_PGA("Out 3", WM8753_PWR3, 4, 0, NULL, 0),
+SND_SOC_DAPM_OUTPUT("OUT3"),
+SND_SOC_DAPM_MUX("Out4 Mux", SND_SOC_NOPM, 0, 0, &wm8753_out4_controls),
+SND_SOC_DAPM_PGA("Out 4", WM8753_PWR3, 3, 0, NULL, 0),
+SND_SOC_DAPM_OUTPUT("OUT4"),
+SND_SOC_DAPM_MIXER("Playback Mixer", WM8753_PWR4, 3, 0,
+	&wm8753_record_mixer_controls[0],
+	ARRAY_SIZE(wm8753_record_mixer_controls)),
+SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8753_PWR2, 3, 0),
+SND_SOC_DAPM_ADC("Right ADC", "Right Capture", WM8753_PWR2, 2, 0),
+SND_SOC_DAPM_MUX("Capture Left Mixer", SND_SOC_NOPM, 0, 0,
+	&wm8753_adc_mono_controls),
+SND_SOC_DAPM_MUX("Capture Right Mixer", SND_SOC_NOPM, 0, 0,
+	&wm8753_adc_mono_controls),
+SND_SOC_DAPM_MUX("Capture Left Mux", SND_SOC_NOPM, 0, 0,
+	&wm8753_adc_left_controls),
+SND_SOC_DAPM_MUX("Capture Right Mux", SND_SOC_NOPM, 0, 0,
+	&wm8753_adc_right_controls),
+SND_SOC_DAPM_MUX("Mic Sidetone Mux", SND_SOC_NOPM, 0, 0,
+	&wm8753_mic_mux_controls),
+SND_SOC_DAPM_PGA("Left Capture Volume", WM8753_PWR2, 5, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Right Capture Volume", WM8753_PWR2, 4, 0, NULL, 0),
+SND_SOC_DAPM_MIXER("ALC Mixer", WM8753_PWR2, 6, 0,
+	&wm8753_alc_mixer_controls[0], ARRAY_SIZE(wm8753_alc_mixer_controls)),
+SND_SOC_DAPM_MUX("Line Left Mux", SND_SOC_NOPM, 0, 0,
+	&wm8753_line_left_controls),
+SND_SOC_DAPM_MUX("Line Right Mux", SND_SOC_NOPM, 0, 0,
+	&wm8753_line_right_controls),
+SND_SOC_DAPM_MUX("Line Mono Mux", SND_SOC_NOPM, 0, 0,
+	&wm8753_line_mono_controls),
+SND_SOC_DAPM_MUX("Line Mixer", WM8753_PWR2, 0, 0,
+	&wm8753_line_mux_mix_controls),
+SND_SOC_DAPM_MUX("Rx Mixer", WM8753_PWR2, 1, 0,
+	&wm8753_rx_mux_mix_controls),
+SND_SOC_DAPM_PGA("Mic 1 Volume", WM8753_PWR2, 8, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Mic 2 Volume", WM8753_PWR2, 7, 0, NULL, 0),
+SND_SOC_DAPM_MUX("Mic Selection Mux", SND_SOC_NOPM, 0, 0,
+	&wm8753_mic_sel_mux_controls),
+SND_SOC_DAPM_INPUT("LINE1"),
+SND_SOC_DAPM_INPUT("LINE2"),
+SND_SOC_DAPM_INPUT("RXP"),
+SND_SOC_DAPM_INPUT("RXN"),
+SND_SOC_DAPM_INPUT("ACIN"),
+SND_SOC_DAPM_OUTPUT("ACOP"),
+SND_SOC_DAPM_INPUT("MIC1N"),
+SND_SOC_DAPM_INPUT("MIC1"),
+SND_SOC_DAPM_INPUT("MIC2N"),
+SND_SOC_DAPM_INPUT("MIC2"),
+SND_SOC_DAPM_VMID("VREF"),
+};
+
+static const char *audio_map[][3] = {
+	/* left mixer */
+	{"Left Mixer", "Left Playback Switch", "Left DAC"},
+	{"Left Mixer", "Voice Playback Switch", "Voice DAC"},
+	{"Left Mixer", "Sidetone Playback Switch", "Mic Sidetone Mux"},
+	{"Left Mixer", "Bypass Playback Switch", "Line Left Mux"},
+
+	/* right mixer */
+	{"Right Mixer", "Right Playback Switch", "Right DAC"},
+	{"Right Mixer", "Voice Playback Switch", "Voice DAC"},
+	{"Right Mixer", "Sidetone Playback Switch", "Mic Sidetone Mux"},
+	{"Right Mixer", "Bypass Playback Switch", "Line Right Mux"},
+
+	/* mono mixer */
+	{"Mono Mixer", "Voice Playback Switch", "Voice DAC"},
+	{"Mono Mixer", "Left Playback Switch", "Left DAC"},
+	{"Mono Mixer", "Right Playback Switch", "Right DAC"},
+	{"Mono Mixer", "Sidetone Playback Switch", "Mic Sidetone Mux"},
+	{"Mono Mixer", "Bypass Playback Switch", "Line Mono Mux"},
+
+	/* left out */
+	{"Left Out 1", NULL, "Left Mixer"},
+	{"Left Out 2", NULL, "Left Mixer"},
+	{"LOUT1", NULL, "Left Out 1"},
+	{"LOUT2", NULL, "Left Out 2"},
+
+	/* right out */
+	{"Right Out 1", NULL, "Right Mixer"},
+	{"Right Out 2", NULL, "Right Mixer"},
+	{"ROUT1", NULL, "Right Out 1"},
+	{"ROUT2", NULL, "Right Out 2"},
+
+	/* mono 1 out */
+	{"Mono Out 1", NULL, "Mono Mixer"},
+	{"MONO1", NULL, "Mono Out 1"},
+
+	/* mono 2 out */
+	{"Mono 2 Mux", "Left + Right", "Out3 Left + Right"},
+	{"Mono 2 Mux", "Inverted Mono 1", "MONO1"},
+	{"Mono 2 Mux", "Left", "Left Mixer"},
+	{"Mono 2 Mux", "Right", "Right Mixer"},
+	{"Mono Out 2", NULL, "Mono 2 Mux"},
+	{"MONO2", NULL, "Mono Out 2"},
+
+	/* out 3 */
+	{"Out3 Left + Right", NULL, "Left Mixer"},
+	{"Out3 Left + Right", NULL, "Right Mixer"},
+	{"Out3 Mux", "VREF", "VREF"},
+	{"Out3 Mux", "Left + Right", "Out3 Left + Right"},
+	{"Out3 Mux", "ROUT2", "ROUT2"},
+	{"Out 3", NULL, "Out3 Mux"},
+	{"OUT3", NULL, "Out 3"},
+
+	/* out 4 */
+	{"Out4 Mux", "VREF", "VREF"},
+	{"Out4 Mux", "Capture ST", "Capture ST Mixer"},
+	{"Out4 Mux", "LOUT2", "LOUT2"},
+	{"Out 4", NULL, "Out4 Mux"},
+	{"OUT4", NULL, "Out 4"},
+
+	/* record mixer  */
+	{"Playback Mixer", "Left Capture Switch", "Left Mixer"},
+	{"Playback Mixer", "Voice Capture Switch", "Mono Mixer"},
+	{"Playback Mixer", "Right Capture Switch", "Right Mixer"},
+
+	/* Mic/SideTone Mux */
+	{"Mic Sidetone Mux", "Left PGA", "Left Capture Volume"},
+	{"Mic Sidetone Mux", "Right PGA", "Right Capture Volume"},
+	{"Mic Sidetone Mux", "Mic 1", "Mic 1 Volume"},
+	{"Mic Sidetone Mux", "Mic 2", "Mic 2 Volume"},
+
+	/* Capture Left Mux */
+	{"Capture Left Mux", "PGA", "Left Capture Volume"},
+	{"Capture Left Mux", "Line or RXP-RXN", "Line Left Mux"},
+	{"Capture Left Mux", "Line", "LINE1"},
+
+	/* Capture Right Mux */
+	{"Capture Right Mux", "PGA", "Right Capture Volume"},
+	{"Capture Right Mux", "Line or RXP-RXN", "Line Right Mux"},
+	{"Capture Right Mux", "Sidetone", "Capture ST Mixer"},
+
+	/* Mono Capture mixer-mux */
+	{"Capture Right Mixer", "Stereo", "Capture Right Mux"},
+	{"Capture Left Mixer", "Analogue Mix Left", "Capture Left Mux"},
+	{"Capture Left Mixer", "Analogue Mix Left", "Capture Right Mux"},
+	{"Capture Right Mixer", "Analogue Mix Right", "Capture Left Mux"},
+	{"Capture Right Mixer", "Analogue Mix Right", "Capture Right Mux"},
+	{"Capture Left Mixer", "Digital Mono Mix", "Capture Left Mux"},
+	{"Capture Left Mixer", "Digital Mono Mix", "Capture Right Mux"},
+	{"Capture Right Mixer", "Digital Mono Mix", "Capture Left Mux"},
+	{"Capture Right Mixer", "Digital Mono Mix", "Capture Right Mux"},
+
+	/* ADC */
+	{"Left ADC", NULL, "Capture Left Mixer"},
+	{"Right ADC", NULL, "Capture Right Mixer"},
+
+	/* Left Capture Volume */
+	{"Left Capture Volume", NULL, "ACIN"},
+
+	/* Right Capture Volume */
+	{"Right Capture Volume", NULL, "Mic 2 Volume"},
+
+	/* ALC Mixer */
+	{"ALC Mixer", "Line Capture Switch", "Line Mixer"},
+	{"ALC Mixer", "Mic2 Capture Switch", "Mic 2 Volume"},
+	{"ALC Mixer", "Mic1 Capture Switch", "Mic 1 Volume"},
+	{"ALC Mixer", "Rx Capture Switch", "Rx Mixer"},
+
+	/* Line Left Mux */
+	{"Line Left Mux", "Line 1", "LINE1"},
+	{"Line Left Mux", "Rx Mix", "Rx Mixer"},
+
+	/* Line Right Mux */
+	{"Line Right Mux", "Line 2", "LINE2"},
+	{"Line Right Mux", "Rx Mix", "Rx Mixer"},
+
+	/* Line Mono Mux */
+	{"Line Mono Mux", "Line Mix", "Line Mixer"},
+	{"Line Mono Mux", "Rx Mix", "Rx Mixer"},
+
+	/* Line Mixer/Mux */
+	{"Line Mixer", "Line 1 + 2", "LINE1"},
+	{"Line Mixer", "Line 1 - 2", "LINE1"},
+	{"Line Mixer", "Line 1 + 2", "LINE2"},
+	{"Line Mixer", "Line 1 - 2", "LINE2"},
+	{"Line Mixer", "Line 1", "LINE1"},
+	{"Line Mixer", "Line 2", "LINE2"},
+
+	/* Rx Mixer/Mux */
+	{"Rx Mixer", "RXP - RXN", "RXP"},
+	{"Rx Mixer", "RXP + RXN", "RXP"},
+	{"Rx Mixer", "RXP - RXN", "RXN"},
+	{"Rx Mixer", "RXP + RXN", "RXN"},
+	{"Rx Mixer", "RXP", "RXP"},
+	{"Rx Mixer", "RXN", "RXN"},
+
+	/* Mic 1 Volume */
+	{"Mic 1 Volume", NULL, "MIC1N"},
+	{"Mic 1 Volume", NULL, "Mic Selection Mux"},
+
+	/* Mic 2 Volume */
+	{"Mic 2 Volume", NULL, "MIC2N"},
+	{"Mic 2 Volume", NULL, "MIC2"},
+
+	/* Mic Selector Mux */
+	{"Mic Selection Mux", "Mic 1", "MIC1"},
+	{"Mic Selection Mux", "Mic 2", "MIC2N"},
+	{"Mic Selection Mux", "Mic 3", "MIC2"},
+
+	/* ACOP */
+	{"ACOP", NULL, "ALC Mixer"},
+
+	/* terminator */
+	{NULL, NULL, NULL},
+};
+
+static int wm8753_add_widgets(struct snd_soc_codec *codec)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(wm8753_dapm_widgets); i++)
+		snd_soc_dapm_new_control(codec, &wm8753_dapm_widgets[i]);
+
+	/* set up the WM8753 audio map */
+	for (i = 0; audio_map[i][0] != NULL; i++) {
+		snd_soc_dapm_connect_input(codec, audio_map[i][0],
+			audio_map[i][1], audio_map[i][2]);
+	}
+
+	snd_soc_dapm_new_widgets(codec);
+	return 0;
+}
+
+/* PLL divisors */
+struct _pll_div {
+	u32 div2:1;
+	u32 n:4;
+	u32 k:24;
+};
+
+/* The size in bits of the pll divide multiplied by 10
+ * to allow rounding later */
+#define FIXED_PLL_SIZE ((1 << 22) * 10)
+
+static void pll_factors(struct _pll_div *pll_div, unsigned int target,
+	unsigned int source)
+{
+	u64 Kpart;
+	unsigned int K, Ndiv, Nmod;
+
+	Ndiv = target / source;
+	if (Ndiv < 6) {
+		source >>= 1;
+		pll_div->div2 = 1;
+		Ndiv = target / source;
+	} else
+		pll_div->div2 = 0;
+
+	if ((Ndiv < 6) || (Ndiv > 12))
+		printk(KERN_WARNING
+			"WM8753 N value outwith recommended range! N = %d\n",Ndiv);
+
+	pll_div->n = Ndiv;
+	Nmod = target % source;
+	Kpart = FIXED_PLL_SIZE * (long long)Nmod;
+
+	do_div(Kpart, source);
+
+	K = Kpart & 0xFFFFFFFF;
+
+	/* Check if we need to round */
+	if ((K % 10) >= 5)
+		K += 5;
+
+	/* Move down to proper range now rounding is done */
+	K /= 10;
+
+	pll_div->k = K;
+}
+
+static int wm8753_set_dai_pll(struct snd_soc_codec_dai *codec_dai,
+		int pll_id, unsigned int freq_in, unsigned int freq_out)
+{
+	u16 reg, enable;
+	int offset;
+	struct snd_soc_codec *codec = codec_dai->codec;
+
+	if (pll_id < WM8753_PLL1 || pll_id > WM8753_PLL2)
+		return -ENODEV;
+
+	if (pll_id == WM8753_PLL1) {
+		offset = 0;
+		enable = 0x10;
+		reg = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xffef;
+	} else {
+		offset = 4;
+		enable = 0x8;
+		reg = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfff7;
+	}
+
+	if (!freq_in || !freq_out) {
+		/* disable PLL  */
+		wm8753_write(codec, WM8753_PLL1CTL1 + offset, 0x0026);
+		wm8753_write(codec, WM8753_CLOCK, reg);
+		return 0;
+	} else {
+		u16 value = 0;
+		struct _pll_div pll_div;
+
+		pll_factors(&pll_div, freq_out * 8, freq_in);
+
+		/* set up N and K PLL divisor ratios */
+		/* bits 8:5 = PLL_N, bits 3:0 = PLL_K[21:18] */
+		value = (pll_div.n << 5) + ((pll_div.k & 0x3c0000) >> 18);
+		wm8753_write(codec, WM8753_PLL1CTL2 + offset, value);
+
+		/* bits 8:0 = PLL_K[17:9] */
+		value = (pll_div.k & 0x03fe00) >> 9;
+		wm8753_write(codec, WM8753_PLL1CTL3 + offset, value);
+
+		/* bits 8:0 = PLL_K[8:0] */
+		value = pll_div.k & 0x0001ff;
+		wm8753_write(codec, WM8753_PLL1CTL4 + offset, value);
+
+		/* set PLL as input and enable */
+		wm8753_write(codec, WM8753_PLL1CTL1 + offset, 0x0027 |
+			(pll_div.div2 << 3));
+		wm8753_write(codec, WM8753_CLOCK, reg | enable);
+	}
+	return 0;
+}
+
+struct _coeff_div {
+	u32 mclk;
+	u32 rate;
+	u8 sr:5;
+	u8 usb:1;
+};
+
+/* codec hifi mclk (after PLL) clock divider coefficients */
+static const struct _coeff_div coeff_div[] = {
+	/* 8k */
+	{12288000, 8000, 0x6, 0x0},
+	{11289600, 8000, 0x16, 0x0},
+	{18432000, 8000, 0x7, 0x0},
+	{16934400, 8000, 0x17, 0x0},
+	{12000000, 8000, 0x6, 0x1},
+
+	/* 11.025k */
+	{11289600, 11025, 0x18, 0x0},
+	{16934400, 11025, 0x19, 0x0},
+	{12000000, 11025, 0x19, 0x1},
+
+	/* 16k */
+	{12288000, 16000, 0xa, 0x0},
+	{18432000, 16000, 0xb, 0x0},
+	{12000000, 16000, 0xa, 0x1},
+
+	/* 22.05k */
+	{11289600, 22050, 0x1a, 0x0},
+	{16934400, 22050, 0x1b, 0x0},
+	{12000000, 22050, 0x1b, 0x1},
+
+	/* 32k */
+	{12288000, 32000, 0xc, 0x0},
+	{18432000, 32000, 0xd, 0x0},
+	{12000000, 32000, 0xa, 0x1},
+
+	/* 44.1k */
+	{11289600, 44100, 0x10, 0x0},
+	{16934400, 44100, 0x11, 0x0},
+	{12000000, 44100, 0x11, 0x1},
+
+	/* 48k */
+	{12288000, 48000, 0x0, 0x0},
+	{18432000, 48000, 0x1, 0x0},
+	{12000000, 48000, 0x0, 0x1},
+
+	/* 88.2k */
+	{11289600, 88200, 0x1e, 0x0},
+	{16934400, 88200, 0x1f, 0x0},
+	{12000000, 88200, 0x1f, 0x1},
+
+	/* 96k */
+	{12288000, 96000, 0xe, 0x0},
+	{18432000, 96000, 0xf, 0x0},
+	{12000000, 96000, 0xe, 0x1},
+};
+
+static int get_coeff(int mclk, int rate)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(coeff_div); i++) {
+		if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk)
+			return i;
+	}
+	return -EINVAL;
+}
+
+/*
+ * Clock after PLL and dividers
+ */
+static int wm8753_set_dai_sysclk(struct snd_soc_codec_dai *codec_dai,
+		int clk_id, unsigned int freq, int dir)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	struct wm8753_priv *wm8753 = codec->private_data;
+
+	switch (freq) {
+	case 11289600:
+	case 12000000:
+	case 12288000:
+	case 16934400:
+	case 18432000:
+		if (clk_id == WM8753_MCLK) {
+			wm8753->sysclk = freq;
+			return 0;
+		} else if (clk_id == WM8753_PCMCLK) {
+			wm8753->pcmclk = freq;
+			return 0;
+		}
+		break;
+	}
+	return -EINVAL;
+}
+
+/*
+ * Set's ADC and Voice DAC format.
+ */
+static int wm8753_vdac_adc_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
+		unsigned int fmt)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	u16 voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x01ec;
+
+	/* interface format */
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		voice |= 0x0002;
+		break;
+	case SND_SOC_DAIFMT_RIGHT_J:
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		voice |= 0x0001;
+		break;
+	case SND_SOC_DAIFMT_DSP_A:
+		voice |= 0x0003;
+		break;
+	case SND_SOC_DAIFMT_DSP_B:
+		voice |= 0x0013;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	wm8753_write(codec, WM8753_PCM, voice);
+	return 0;
+}
+
+/*
+ * Set PCM DAI bit size and sample rate.
+ */
+static int wm8753_pcm_hw_params(struct snd_pcm_substream *substream,
+	struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_device *socdev = rtd->socdev;
+	struct snd_soc_codec *codec = socdev->codec;
+	struct wm8753_priv *wm8753 = codec->private_data;
+	u16 voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x01f3;
+	u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x017f;
+
+	/* bit size */
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		break;
+	case SNDRV_PCM_FORMAT_S20_3LE:
+		voice |= 0x0004;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		voice |= 0x0008;
+		break;
+	case SNDRV_PCM_FORMAT_S32_LE:
+		voice |= 0x000c;
+		break;
+	}
+
+	/* sample rate */
+	if (params_rate(params) * 384 == wm8753->pcmclk)
+		srate |= 0x80;
+	wm8753_write(codec, WM8753_SRATE1, srate);
+
+	wm8753_write(codec, WM8753_PCM, voice);
+	return 0;
+}
+
+/*
+ * Set's PCM dai fmt and BCLK.
+ */
+static int wm8753_pcm_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
+		unsigned int fmt)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	u16 voice, ioctl;
+
+	voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x011f;
+	ioctl = wm8753_read_reg_cache(codec, WM8753_IOCTL) & 0x015d;
+
+	/* set master/slave audio interface */
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBS_CFS:
+		break;
+	case SND_SOC_DAIFMT_CBM_CFM:
+		ioctl |= 0x2;
+	case SND_SOC_DAIFMT_CBM_CFS:
+		voice |= 0x0040;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* clock inversion */
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_DSP_A:
+	case SND_SOC_DAIFMT_DSP_B:
+		/* frame inversion not valid for DSP modes */
+		switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+		case SND_SOC_DAIFMT_NB_NF:
+			break;
+		case SND_SOC_DAIFMT_IB_NF:
+			voice |= 0x0080;
+			break;
+		default:
+			return -EINVAL;
+		}
+		break;
+	case SND_SOC_DAIFMT_I2S:
+	case SND_SOC_DAIFMT_RIGHT_J:
+	case SND_SOC_DAIFMT_LEFT_J:
+		voice &= ~0x0010;
+		switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+		case SND_SOC_DAIFMT_NB_NF:
+			break;
+		case SND_SOC_DAIFMT_IB_IF:
+			voice |= 0x0090;
+			break;
+		case SND_SOC_DAIFMT_IB_NF:
+			voice |= 0x0080;
+			break;
+		case SND_SOC_DAIFMT_NB_IF:
+			voice |= 0x0010;
+			break;
+		default:
+			return -EINVAL;
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	wm8753_write(codec, WM8753_PCM, voice);
+	wm8753_write(codec, WM8753_IOCTL, ioctl);
+	return 0;
+}
+
+static int wm8753_set_dai_clkdiv(struct snd_soc_codec_dai *codec_dai,
+		int div_id, int div)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	u16 reg;
+
+	switch (div_id) {
+	case WM8753_PCMDIV:
+		reg = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0x003f;
+		wm8753_write(codec, WM8753_CLOCK, reg | div);
+		break;
+	case WM8753_BCLKDIV:
+		reg = wm8753_read_reg_cache(codec, WM8753_SRATE2) & 0x01c7;
+		wm8753_write(codec, WM8753_SRATE2, reg | div);
+		break;
+	case WM8753_VXCLKDIV:
+		reg = wm8753_read_reg_cache(codec, WM8753_SRATE2) & 0x003f;
+		wm8753_write(codec, WM8753_SRATE2, reg | div);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/*
+ * Set's HiFi DAC format.
+ */
+static int wm8753_hdac_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
+		unsigned int fmt)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	u16 hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x01e0;
+
+	/* interface format */
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		hifi |= 0x0002;
+		break;
+	case SND_SOC_DAIFMT_RIGHT_J:
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		hifi |= 0x0001;
+		break;
+	case SND_SOC_DAIFMT_DSP_A:
+		hifi |= 0x0003;
+		break;
+	case SND_SOC_DAIFMT_DSP_B:
+		hifi |= 0x0013;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	wm8753_write(codec, WM8753_HIFI, hifi);
+	return 0;
+}
+
+/*
+ * Set's I2S DAI format.
+ */
+static int wm8753_i2s_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
+		unsigned int fmt)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	u16 ioctl, hifi;
+
+	hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x011f;
+	ioctl = wm8753_read_reg_cache(codec, WM8753_IOCTL) & 0x00ae;
+
+	/* set master/slave audio interface */
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBS_CFS:
+		break;
+	case SND_SOC_DAIFMT_CBM_CFM:
+		ioctl |= 0x1;
+	case SND_SOC_DAIFMT_CBM_CFS:
+		hifi |= 0x0040;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* clock inversion */
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_DSP_A:
+	case SND_SOC_DAIFMT_DSP_B:
+		/* frame inversion not valid for DSP modes */
+		switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+		case SND_SOC_DAIFMT_NB_NF:
+			break;
+		case SND_SOC_DAIFMT_IB_NF:
+			hifi |= 0x0080;
+			break;
+		default:
+			return -EINVAL;
+		}
+		break;
+	case SND_SOC_DAIFMT_I2S:
+	case SND_SOC_DAIFMT_RIGHT_J:
+	case SND_SOC_DAIFMT_LEFT_J:
+		hifi &= ~0x0010;
+		switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+		case SND_SOC_DAIFMT_NB_NF:
+			break;
+		case SND_SOC_DAIFMT_IB_IF:
+			hifi |= 0x0090;
+			break;
+		case SND_SOC_DAIFMT_IB_NF:
+			hifi |= 0x0080;
+			break;
+		case SND_SOC_DAIFMT_NB_IF:
+			hifi |= 0x0010;
+			break;
+		default:
+			return -EINVAL;
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	wm8753_write(codec, WM8753_HIFI, hifi);
+	wm8753_write(codec, WM8753_IOCTL, ioctl);
+	return 0;
+}
+
+/*
+ * Set PCM DAI bit size and sample rate.
+ */
+static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream,
+	struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_device *socdev = rtd->socdev;
+	struct snd_soc_codec *codec = socdev->codec;
+	struct wm8753_priv *wm8753 = codec->private_data;
+	u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x01c0;
+	u16 hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x01f3;
+	int coeff;
+
+	/* is digital filter coefficient valid ? */
+	coeff = get_coeff(wm8753->sysclk, params_rate(params));
+	if (coeff < 0) {
+		printk(KERN_ERR "wm8753 invalid MCLK or rate\n");
+		return coeff;
+	}
+	wm8753_write(codec, WM8753_SRATE1, srate | (coeff_div[coeff].sr << 1) |
+		coeff_div[coeff].usb);
+
+	/* bit size */
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		break;
+	case SNDRV_PCM_FORMAT_S20_3LE:
+		hifi |= 0x0004;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		hifi |= 0x0008;
+		break;
+	case SNDRV_PCM_FORMAT_S32_LE:
+		hifi |= 0x000c;
+		break;
+	}
+
+	wm8753_write(codec, WM8753_HIFI, hifi);
+	return 0;
+}
+
+static int wm8753_mode1v_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
+		unsigned int fmt)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	u16 clock;
+
+	/* set clk source as pcmclk */
+	clock = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfffb;
+	wm8753_write(codec, WM8753_CLOCK, clock);
+
+	if (wm8753_vdac_adc_set_dai_fmt(codec_dai, fmt) < 0)
+		return -EINVAL;
+	return wm8753_pcm_set_dai_fmt(codec_dai, fmt);
+}
+
+static int wm8753_mode1h_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
+		unsigned int fmt)
+{
+	if (wm8753_hdac_set_dai_fmt(codec_dai, fmt) < 0)
+		return -EINVAL;
+	return wm8753_i2s_set_dai_fmt(codec_dai, fmt);
+}
+
+static int wm8753_mode2_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
+		unsigned int fmt)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	u16 clock;
+
+	/* set clk source as pcmclk */
+	clock = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfffb;
+	wm8753_write(codec, WM8753_CLOCK, clock);
+
+	if (wm8753_vdac_adc_set_dai_fmt(codec_dai, fmt) < 0)
+		return -EINVAL;
+	return wm8753_i2s_set_dai_fmt(codec_dai, fmt);
+}
+
+static int wm8753_mode3_4_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
+		unsigned int fmt)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	u16 clock;
+
+	/* set clk source as mclk */
+	clock = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfffb;
+	wm8753_write(codec, WM8753_CLOCK, clock | 0x4);
+
+	if (wm8753_hdac_set_dai_fmt(codec_dai, fmt) < 0)
+		return -EINVAL;
+	if (wm8753_vdac_adc_set_dai_fmt(codec_dai, fmt) < 0)
+		return -EINVAL;
+	return wm8753_i2s_set_dai_fmt(codec_dai, fmt);
+}
+
+static int wm8753_mute(struct snd_soc_codec_dai *dai, int mute)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	u16 mute_reg = wm8753_read_reg_cache(codec, WM8753_DAC) & 0xfff7;
+
+	/* the digital mute covers the HiFi and Voice DAC's on the WM8753.
+	 * make sure we check if they are not both active when we mute */
+	if (mute && dai->id == 1) {
+		if (!wm8753_dai[WM8753_DAI_VOICE].playback.active ||
+			!wm8753_dai[WM8753_DAI_HIFI].playback.active)
+			wm8753_write(codec, WM8753_DAC, mute_reg | 0x8);
+	} else {
+		if (mute)
+			wm8753_write(codec, WM8753_DAC, mute_reg | 0x8);
+		else
+			wm8753_write(codec, WM8753_DAC, mute_reg);
+	}
+
+	return 0;
+}
+
+static int wm8753_dapm_event(struct snd_soc_codec *codec, int event)
+{
+	u16 pwr_reg = wm8753_read_reg_cache(codec, WM8753_PWR1) & 0xfe3e;
+
+	switch (event) {
+	case SNDRV_CTL_POWER_D0: /* full On */
+		/* set vmid to 50k and unmute dac */
+		wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x00c0);
+		break;
+	case SNDRV_CTL_POWER_D1: /* partial On */
+	case SNDRV_CTL_POWER_D2: /* partial On */
+		/* set vmid to 5k for quick power up */
+		wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x01c1);
+		break;
+	case SNDRV_CTL_POWER_D3hot: /* Off, with power */
+		/* mute dac and set vmid to 500k, enable VREF */
+		wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x0141);
+		break;
+	case SNDRV_CTL_POWER_D3cold: /* Off, without power */
+		wm8753_write(codec, WM8753_PWR1, 0x0001);
+		break;
+	}
+	codec->dapm_state = event;
+	return 0;
+}
+
+#define WM8753_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
+		SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \
+		SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
+
+#define WM8753_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
+	SNDRV_PCM_FMTBIT_S24_LE)
+
+/*
+ * The WM8753 supports upto 4 different and mutually exclusive DAI
+ * configurations. This gives 2 PCM's available for use, hifi and voice.
+ * NOTE: The Voice PCM cannot play or capture audio to the CPU as it's DAI
+ * is connected between the wm8753 and a BT codec or GSM modem.
+ *
+ * 1. Voice over PCM DAI - HIFI DAC over HIFI DAI
+ * 2. Voice over HIFI DAI - HIFI disabled
+ * 3. Voice disabled - HIFI over HIFI
+ * 4. Voice disabled - HIFI over HIFI, uses voice DAI LRC for capture
+ */
+static const struct snd_soc_codec_dai wm8753_all_dai[] = {
+/* DAI HiFi mode 1 */
+{	.name = "WM8753 HiFi",
+	.id = 1,
+	.playback = {
+		.stream_name = "HiFi Playback",
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = WM8753_RATES,
+		.formats = WM8753_FORMATS,},
+	.capture = { /* dummy for fast DAI switching */
+		.stream_name = "Capture",
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = WM8753_RATES,
+		.formats = WM8753_FORMATS,},
+	.ops = {
+		.hw_params = wm8753_i2s_hw_params,},
+	.dai_ops = {
+		.digital_mute = wm8753_mute,
+		.set_fmt = wm8753_mode1h_set_dai_fmt,
+		.set_clkdiv = wm8753_set_dai_clkdiv,
+		.set_pll = wm8753_set_dai_pll,
+		.set_sysclk = wm8753_set_dai_sysclk,
+	},
+},
+/* DAI Voice mode 1 */
+{	.name = "WM8753 Voice",
+	.id = 1,
+	.playback = {
+		.stream_name = "Voice Playback",
+		.channels_min = 1,
+		.channels_max = 1,
+		.rates = WM8753_RATES,
+		.formats = WM8753_FORMATS,},
+	.capture = {
+		.stream_name = "Capture",
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = WM8753_RATES,
+		.formats = WM8753_FORMATS,},
+	.ops = {
+		.hw_params = wm8753_pcm_hw_params,},
+	.dai_ops = {
+		.digital_mute = wm8753_mute,
+		.set_fmt = wm8753_mode1v_set_dai_fmt,
+		.set_clkdiv = wm8753_set_dai_clkdiv,
+		.set_pll = wm8753_set_dai_pll,
+		.set_sysclk = wm8753_set_dai_sysclk,
+	},
+},
+/* DAI HiFi mode 2 - dummy */
+{	.name = "WM8753 HiFi",
+	.id = 2,
+},
+/* DAI Voice mode 2 */
+{	.name = "WM8753 Voice",
+	.id = 2,
+	.playback = {
+		.stream_name = "Voice Playback",
+		.channels_min = 1,
+		.channels_max = 1,
+		.rates = WM8753_RATES,
+		.formats = WM8753_FORMATS,},
+	.capture = {
+		.stream_name = "Capture",
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = WM8753_RATES,
+		.formats = WM8753_FORMATS,},
+	.ops = {
+		.hw_params = wm8753_pcm_hw_params,},
+	.dai_ops = {
+		.digital_mute = wm8753_mute,
+		.set_fmt = wm8753_mode2_set_dai_fmt,
+		.set_clkdiv = wm8753_set_dai_clkdiv,
+		.set_pll = wm8753_set_dai_pll,
+		.set_sysclk = wm8753_set_dai_sysclk,
+	},
+},
+/* DAI HiFi mode 3 */
+{	.name = "WM8753 HiFi",
+	.id = 3,
+	.playback = {
+		.stream_name = "HiFi Playback",
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = WM8753_RATES,
+		.formats = WM8753_FORMATS,},
+	.capture = {
+		.stream_name = "Capture",
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = WM8753_RATES,
+		.formats = WM8753_FORMATS,},
+	.ops = {
+		.hw_params = wm8753_i2s_hw_params,},
+	.dai_ops = {
+		.digital_mute = wm8753_mute,
+		.set_fmt = wm8753_mode3_4_set_dai_fmt,
+		.set_clkdiv = wm8753_set_dai_clkdiv,
+		.set_pll = wm8753_set_dai_pll,
+		.set_sysclk = wm8753_set_dai_sysclk,
+	},
+},
+/* DAI Voice mode 3 - dummy */
+{	.name = "WM8753 Voice",
+	.id = 3,
+},
+/* DAI HiFi mode 4 */
+{	.name = "WM8753 HiFi",
+	.id = 4,
+	.playback = {
+		.stream_name = "HiFi Playback",
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = WM8753_RATES,
+		.formats = WM8753_FORMATS,},
+	.capture = {
+		.stream_name = "Capture",
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = WM8753_RATES,
+		.formats = WM8753_FORMATS,},
+	.ops = {
+		.hw_params = wm8753_i2s_hw_params,},
+	.dai_ops = {
+		.digital_mute = wm8753_mute,
+		.set_fmt = wm8753_mode3_4_set_dai_fmt,
+		.set_clkdiv = wm8753_set_dai_clkdiv,
+		.set_pll = wm8753_set_dai_pll,
+		.set_sysclk = wm8753_set_dai_sysclk,
+	},
+},
+/* DAI Voice mode 4 - dummy */
+{	.name = "WM8753 Voice",
+	.id = 4,
+},
+};
+
+struct snd_soc_codec_dai wm8753_dai[2];
+EXPORT_SYMBOL_GPL(wm8753_dai);
+
+static void wm8753_set_dai_mode(struct snd_soc_codec *codec, unsigned int mode)
+{
+	if (mode < 4) {
+		int playback_active, capture_active, codec_active, pop_wait;
+		void *private_data;
+
+		playback_active = wm8753_dai[0].playback.active;
+		capture_active = wm8753_dai[0].capture.active;
+		codec_active = wm8753_dai[0].active;
+		private_data = wm8753_dai[0].private_data;
+		pop_wait = wm8753_dai[0].pop_wait;
+		wm8753_dai[0] = wm8753_all_dai[mode << 1];
+		wm8753_dai[0].playback.active = playback_active;
+		wm8753_dai[0].capture.active = capture_active;
+		wm8753_dai[0].active = codec_active;
+		wm8753_dai[0].private_data = private_data;
+		wm8753_dai[0].pop_wait = pop_wait;
+
+		playback_active = wm8753_dai[1].playback.active;
+		capture_active = wm8753_dai[1].capture.active;
+		codec_active = wm8753_dai[1].active;
+		private_data = wm8753_dai[1].private_data;
+		pop_wait = wm8753_dai[1].pop_wait;
+		wm8753_dai[1] = wm8753_all_dai[(mode << 1) + 1];
+		wm8753_dai[1].playback.active = playback_active;
+		wm8753_dai[1].capture.active = capture_active;
+		wm8753_dai[1].active = codec_active;
+		wm8753_dai[1].private_data = private_data;
+		wm8753_dai[1].pop_wait = pop_wait;
+	}
+	wm8753_dai[0].codec = codec;
+	wm8753_dai[1].codec = codec;
+}
+
+static void wm8753_work(struct work_struct *work)
+{
+	struct snd_soc_codec *codec =
+		container_of(work, struct snd_soc_codec, delayed_work.work);
+	wm8753_dapm_event(codec, codec->dapm_state);
+}
+
+static int wm8753_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+	struct snd_soc_codec *codec = socdev->codec;
+
+	/* we only need to suspend if we are a valid card */
+	if(!codec->card)
+		return 0;
+		
+	wm8753_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
+	return 0;
+}
+
+static int wm8753_resume(struct platform_device *pdev)
+{
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+	struct snd_soc_codec *codec = socdev->codec;
+	int i;
+	u8 data[2];
+	u16 *cache = codec->reg_cache;
+
+	/* we only need to resume if we are a valid card */
+	if(!codec->card)
+		return 0;
+
+	/* Sync reg_cache with the hardware */
+	for (i = 0; i < ARRAY_SIZE(wm8753_reg); i++) {
+		if (i + 1 == WM8753_RESET)
+			continue;
+		data[0] = ((i + 1) << 1) | ((cache[i] >> 8) & 0x0001);
+		data[1] = cache[i] & 0x00ff;
+		codec->hw_write(codec->control_data, data, 2);
+	}
+
+	wm8753_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
+
+	/* charge wm8753 caps */
+	if (codec->suspend_dapm_state == SNDRV_CTL_POWER_D0) {
+		wm8753_dapm_event(codec, SNDRV_CTL_POWER_D2);
+		codec->dapm_state = SNDRV_CTL_POWER_D0;
+		schedule_delayed_work(&codec->delayed_work,
+			msecs_to_jiffies(caps_charge));
+	}
+
+	return 0;
+}
+
+/*
+ * initialise the WM8753 driver
+ * register the mixer and dsp interfaces with the kernel
+ */
+static int wm8753_init(struct snd_soc_device *socdev)
+{
+	struct snd_soc_codec *codec = socdev->codec;
+	int reg, ret = 0;
+
+	codec->name = "WM8753";
+	codec->owner = THIS_MODULE;
+	codec->read = wm8753_read_reg_cache;
+	codec->write = wm8753_write;
+	codec->dapm_event = wm8753_dapm_event;
+	codec->dai = wm8753_dai;
+	codec->num_dai = 2;
+	codec->reg_cache_size = sizeof(wm8753_reg);
+	codec->reg_cache = kmemdup(wm8753_reg, sizeof(wm8753_reg), GFP_KERNEL);
+
+	if (codec->reg_cache == NULL)
+		return -ENOMEM;
+
+	wm8753_set_dai_mode(codec, 0);
+
+	wm8753_reset(codec);
+
+	/* register pcms */
+	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
+	if (ret < 0) {
+		printk(KERN_ERR "wm8753: failed to create pcms\n");
+		goto pcm_err;
+	}
+
+	/* charge output caps */
+	wm8753_dapm_event(codec, SNDRV_CTL_POWER_D2);
+	codec->dapm_state = SNDRV_CTL_POWER_D3hot;
+	schedule_delayed_work(&codec->delayed_work,
+		msecs_to_jiffies(caps_charge));
+
+	/* set the update bits */
+	reg = wm8753_read_reg_cache(codec, WM8753_LDAC);
+	wm8753_write(codec, WM8753_LDAC, reg | 0x0100);
+	reg = wm8753_read_reg_cache(codec, WM8753_RDAC);
+	wm8753_write(codec, WM8753_RDAC, reg | 0x0100);
+	reg = wm8753_read_reg_cache(codec, WM8753_LADC);
+	wm8753_write(codec, WM8753_LADC, reg | 0x0100);
+	reg = wm8753_read_reg_cache(codec, WM8753_RADC);
+	wm8753_write(codec, WM8753_RADC, reg | 0x0100);
+	reg = wm8753_read_reg_cache(codec, WM8753_LOUT1V);
+	wm8753_write(codec, WM8753_LOUT1V, reg | 0x0100);
+	reg = wm8753_read_reg_cache(codec, WM8753_ROUT1V);
+	wm8753_write(codec, WM8753_ROUT1V, reg | 0x0100);
+	reg = wm8753_read_reg_cache(codec, WM8753_LOUT2V);
+	wm8753_write(codec, WM8753_LOUT2V, reg | 0x0100);
+	reg = wm8753_read_reg_cache(codec, WM8753_ROUT2V);
+	wm8753_write(codec, WM8753_ROUT2V, reg | 0x0100);
+	reg = wm8753_read_reg_cache(codec, WM8753_LINVOL);
+	wm8753_write(codec, WM8753_LINVOL, reg | 0x0100);
+	reg = wm8753_read_reg_cache(codec, WM8753_RINVOL);
+	wm8753_write(codec, WM8753_RINVOL, reg | 0x0100);
+
+	wm8753_add_controls(codec);
+	wm8753_add_widgets(codec);
+	ret = snd_soc_register_card(socdev);
+	if (ret < 0) {
+      	printk(KERN_ERR "wm8753: failed to register card\n");
+		goto card_err;
+    }
+	return ret;
+
+card_err:
+	snd_soc_free_pcms(socdev);
+	snd_soc_dapm_free(socdev);
+pcm_err:
+	kfree(codec->reg_cache);
+	return ret;
+}
+
+/* If the i2c layer weren't so broken, we could pass this kind of data
+   around */
+static struct snd_soc_device *wm8753_socdev;
+
+#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
+
+/*
+ * WM8753 2 wire address is determined by GPIO5
+ * state during powerup.
+ *    low  = 0x1a
+ *    high = 0x1b
+ */
+static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END };
+
+/* Magic definition of all other variables and things */
+I2C_CLIENT_INSMOD;
+
+static struct i2c_driver wm8753_i2c_driver;
+static struct i2c_client client_template;
+
+static int wm8753_codec_probe(struct i2c_adapter *adap, int addr, int kind)
+{
+	struct snd_soc_device *socdev = wm8753_socdev;
+	struct wm8753_setup_data *setup = socdev->codec_data;
+	struct snd_soc_codec *codec = socdev->codec;
+	struct i2c_client *i2c;
+	int ret;
+
+	if (addr != setup->i2c_address)
+		return -ENODEV;
+
+	client_template.adapter = adap;
+	client_template.addr = addr;
+
+	i2c =  kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
+	if (i2c == NULL){
+		kfree(codec);
+		return -ENOMEM;
+	}
+	i2c_set_clientdata(i2c, codec);
+	codec->control_data = i2c;
+
+	ret = i2c_attach_client(i2c);
+	if (ret < 0) {
+		err("failed to attach codec at addr %x\n", addr);
+		goto err;
+	}
+
+	ret = wm8753_init(socdev);
+	if (ret < 0) {
+		err("failed to initialise WM8753\n");
+		goto err;
+	}
+
+	return ret;
+
+err:
+	kfree(codec);
+	kfree(i2c);
+	return ret;
+}
+
+static int wm8753_i2c_detach(struct i2c_client *client)
+{
+	struct snd_soc_codec *codec = i2c_get_clientdata(client);
+	i2c_detach_client(client);
+	kfree(codec->reg_cache);
+	kfree(client);
+	return 0;
+}
+
+static int wm8753_i2c_attach(struct i2c_adapter *adap)
+{
+	return i2c_probe(adap, &addr_data, wm8753_codec_probe);
+}
+
+/* corgi i2c codec control layer */
+static struct i2c_driver wm8753_i2c_driver = {
+	.driver = {
+		.name = "WM8753 I2C Codec",
+		.owner = THIS_MODULE,
+	},
+	.id =             I2C_DRIVERID_WM8753,
+	.attach_adapter = wm8753_i2c_attach,
+	.detach_client =  wm8753_i2c_detach,
+	.command =        NULL,
+};
+
+static struct i2c_client client_template = {
+	.name =   "WM8753",
+	.driver = &wm8753_i2c_driver,
+};
+#endif
+
+static int wm8753_probe(struct platform_device *pdev)
+{
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+	struct wm8753_setup_data *setup;
+	struct snd_soc_codec *codec;
+	struct wm8753_priv *wm8753;
+	int ret = 0;
+
+	info("WM8753 Audio Codec %s", WM8753_VERSION);
+
+	setup = socdev->codec_data;
+	codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
+	if (codec == NULL)
+		return -ENOMEM;
+
+	wm8753 = kzalloc(sizeof(struct wm8753_priv), GFP_KERNEL);
+	if (wm8753 == NULL) {
+		kfree(codec);
+		return -ENOMEM;
+	}
+
+	codec->private_data = wm8753;
+	socdev->codec = codec;
+	mutex_init(&codec->mutex);
+	INIT_LIST_HEAD(&codec->dapm_widgets);
+	INIT_LIST_HEAD(&codec->dapm_paths);
+	wm8753_socdev = socdev;
+	INIT_DELAYED_WORK(&codec->delayed_work, wm8753_work);
+
+#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
+	if (setup->i2c_address) {
+		normal_i2c[0] = setup->i2c_address;
+		codec->hw_write = (hw_write_t)i2c_master_send;
+		ret = i2c_add_driver(&wm8753_i2c_driver);
+		if (ret != 0)
+			printk(KERN_ERR "can't add i2c driver");
+	}
+#else
+		/* Add other interfaces here */
+#endif
+	return ret;
+}
+
+/*
+ * This function forces any delayed work to be queued and run.
+ */
+static int run_delayed_work(struct delayed_work *dwork)
+{
+	int ret;
+
+	/* cancel any work waiting to be queued. */
+	ret = cancel_delayed_work(dwork);
+
+	/* if there was any work waiting then we run it now and
+	 * wait for it's completion */
+	if (ret) {
+		schedule_delayed_work(dwork, 0);
+		flush_scheduled_work();
+	}
+	return ret;
+}
+
+/* power down chip */
+static int wm8753_remove(struct platform_device *pdev)
+{
+	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+	struct snd_soc_codec *codec = socdev->codec;
+
+	if (codec->control_data)
+		wm8753_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
+	run_delayed_work(&codec->delayed_work);
+	snd_soc_free_pcms(socdev);
+	snd_soc_dapm_free(socdev);
+#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
+	i2c_del_driver(&wm8753_i2c_driver);
+#endif
+	kfree(codec->private_data);
+	kfree(codec);
+
+	return 0;
+}
+
+struct snd_soc_codec_device soc_codec_dev_wm8753 = {
+	.probe = 	wm8753_probe,
+	.remove = 	wm8753_remove,
+	.suspend = 	wm8753_suspend,
+	.resume =	wm8753_resume,
+};
+
+EXPORT_SYMBOL_GPL(soc_codec_dev_wm8753);
+
+MODULE_DESCRIPTION("ASoC WM8753 driver");
+MODULE_AUTHOR("Liam Girdwood");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8753.h b/sound/soc/codecs/wm8753.h
new file mode 100644
index 000000000000..95e2a1f53169
--- /dev/null
+++ b/sound/soc/codecs/wm8753.h
@@ -0,0 +1,126 @@
+/*
+ * wm8753.h  --  audio driver for WM8753
+ *
+ * Copyright 2003 Wolfson Microelectronics PLC.
+ * Author: Liam Girdwood
+ *         liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
+ *
+ *  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.
+ *
+ */
+
+#ifndef _WM8753_H
+#define _WM8753_H
+
+/* WM8753 register space */
+
+#define WM8753_DAC		0x01
+#define WM8753_ADC		0x02
+#define WM8753_PCM		0x03
+#define WM8753_HIFI		0x04
+#define WM8753_IOCTL		0x05
+#define WM8753_SRATE1		0x06
+#define WM8753_SRATE2		0x07
+#define WM8753_LDAC		0x08
+#define WM8753_RDAC		0x09
+#define WM8753_BASS		0x0a
+#define WM8753_TREBLE		0x0b
+#define WM8753_ALC1		0x0c
+#define WM8753_ALC2		0x0d
+#define WM8753_ALC3		0x0e
+#define WM8753_NGATE		0x0f
+#define WM8753_LADC		0x10
+#define WM8753_RADC		0x11
+#define WM8753_ADCTL1		0x12
+#define WM8753_3D		0x13
+#define WM8753_PWR1		0x14
+#define WM8753_PWR2		0x15
+#define WM8753_PWR3		0x16
+#define WM8753_PWR4		0x17
+#define WM8753_ID		0x18
+#define WM8753_INTPOL		0x19
+#define WM8753_INTEN		0x1a
+#define WM8753_GPIO1		0x1b
+#define WM8753_GPIO2		0x1c
+#define WM8753_RESET		0x1f
+#define WM8753_RECMIX1		0x20
+#define WM8753_RECMIX2		0x21
+#define WM8753_LOUTM1		0x22
+#define WM8753_LOUTM2		0x23
+#define WM8753_ROUTM1		0x24
+#define WM8753_ROUTM2		0x25
+#define WM8753_MOUTM1		0x26
+#define WM8753_MOUTM2		0x27
+#define WM8753_LOUT1V		0x28
+#define WM8753_ROUT1V		0x29
+#define WM8753_LOUT2V		0x2a
+#define WM8753_ROUT2V		0x2b
+#define WM8753_MOUTV		0x2c
+#define WM8753_OUTCTL		0x2d
+#define WM8753_ADCIN		0x2e
+#define WM8753_INCTL1		0x2f
+#define WM8753_INCTL2		0x30
+#define WM8753_LINVOL		0x31
+#define WM8753_RINVOL		0x32
+#define WM8753_MICBIAS		0x33
+#define WM8753_CLOCK		0x34
+#define WM8753_PLL1CTL1		0x35
+#define WM8753_PLL1CTL2		0x36
+#define WM8753_PLL1CTL3		0x37
+#define WM8753_PLL1CTL4		0x38
+#define WM8753_PLL2CTL1		0x39
+#define WM8753_PLL2CTL2		0x3a
+#define WM8753_PLL2CTL3		0x3b
+#define WM8753_PLL2CTL4		0x3c
+#define WM8753_BIASCTL		0x3d
+#define WM8753_ADCTL2		0x3f
+
+struct wm8753_setup_data {
+	unsigned short i2c_address;
+};
+
+#define WM8753_PLL1			0
+#define WM8753_PLL2			1
+
+/* clock inputs */
+#define WM8753_MCLK		0
+#define WM8753_PCMCLK		1
+
+/* clock divider id's */
+#define WM8753_PCMDIV		0
+#define WM8753_BCLKDIV		1
+#define WM8753_VXCLKDIV		2
+
+/* PCM clock dividers */
+#define WM8753_PCM_DIV_1	(0 << 6)
+#define WM8753_PCM_DIV_3	(2 << 6)
+#define WM8753_PCM_DIV_5_5	(3 << 6)
+#define WM8753_PCM_DIV_2	(4 << 6)
+#define WM8753_PCM_DIV_4	(5 << 6)
+#define WM8753_PCM_DIV_6	(6 << 6)
+#define WM8753_PCM_DIV_8	(7 << 6)
+
+/* BCLK clock dividers */
+#define WM8753_BCLK_DIV_1	(0 << 3)
+#define WM8753_BCLK_DIV_2	(1 << 3)
+#define WM8753_BCLK_DIV_4	(2 << 3)
+#define WM8753_BCLK_DIV_8	(3 << 3)
+#define WM8753_BCLK_DIV_16	(4 << 3)
+
+/* VXCLK clock dividers */
+#define WM8753_VXCLK_DIV_1	(0 << 6)
+#define WM8753_VXCLK_DIV_2	(1 << 6)
+#define WM8753_VXCLK_DIV_4	(2 << 6)
+#define WM8753_VXCLK_DIV_8	(3 << 6)
+#define WM8753_VXCLK_DIV_16	(4 << 6)
+
+#define WM8753_DAI_HIFI		0
+#define WM8753_DAI_VOICE		1
+
+extern struct snd_soc_codec_dai wm8753_dai[2];
+extern struct snd_soc_codec_device soc_codec_dev_wm8753;
+
+#endif
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c
index ee7a691a9ba1..264413a00cac 100644
--- a/sound/soc/codecs/wm9712.c
+++ b/sound/soc/codecs/wm9712.c
@@ -676,14 +676,13 @@ static int wm9712_soc_probe(struct platform_device *pdev)
 	codec = socdev->codec;
 	mutex_init(&codec->mutex);
 
-	codec->reg_cache =
-		kzalloc(sizeof(u16) * ARRAY_SIZE(wm9712_reg), GFP_KERNEL);
+	codec->reg_cache = kmemdup(wm9712_reg, sizeof(wm9712_reg), GFP_KERNEL);
+
 	if (codec->reg_cache == NULL) {
 		ret = -ENOMEM;
 		goto cache_err;
 	}
-	memcpy(codec->reg_cache, wm9712_reg, sizeof(u16) * ARRAY_SIZE(wm9712_reg));
-	codec->reg_cache_size = sizeof(u16) * ARRAY_SIZE(wm9712_reg);
+	codec->reg_cache_size = sizeof(wm9712_reg);
 	codec->reg_cache_step = 2;
 
 	codec->name = "WM9712";
diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig
index b9ab3b8e1d3e..a83e22937c27 100644
--- a/sound/soc/pxa/Kconfig
+++ b/sound/soc/pxa/Kconfig
@@ -1,5 +1,3 @@
-menu "SoC Audio for the Intel PXA2xx"
-
 config SND_PXA2XX_SOC
 	tristate "SoC Audio for the Intel PXA2xx chip"
 	depends on ARCH_PXA && SND_SOC
@@ -55,5 +53,3 @@ config SND_PXA2XX_SOC_TOSA
 	help
 	  Say Y if you want to add support for SoC audio on Sharp
 	  Zaurus SL-C6000x models (Tosa).
-
-endmenu
diff --git a/sound/soc/s3c24xx/Kconfig b/sound/soc/s3c24xx/Kconfig
new file mode 100644
index 000000000000..044a3712077a
--- /dev/null
+++ b/sound/soc/s3c24xx/Kconfig
@@ -0,0 +1,10 @@
+config SND_S3C24XX_SOC
+	tristate "SoC Audio for the Samsung S3C24XX chips"
+	depends on ARCH_S3C2410 && SND_SOC
+	help
+	  Say Y or M if you want to add support for codecs attached to
+	  the S3C24XX AC97, I2S or SSP interface. You will also need
+	  to select the audio interfaces to support below.
+
+config SND_S3C24XX_SOC_I2S
+	tristate
diff --git a/sound/soc/s3c24xx/Makefile b/sound/soc/s3c24xx/Makefile
new file mode 100644
index 000000000000..6f0fffcb30f5
--- /dev/null
+++ b/sound/soc/s3c24xx/Makefile
@@ -0,0 +1,6 @@
+# S3c24XX Platform Support
+snd-soc-s3c24xx-objs := s3c24xx-pcm.o
+snd-soc-s3c24xx-i2s-objs := s3c24xx-i2s.o
+
+obj-$(CONFIG_SND_S3C24XX_SOC) += snd-soc-s3c24xx.o
+obj-$(CONFIG_SND_S3C24XX_SOC_I2S) += snd-soc-s3c24xx-i2s.o
diff --git a/sound/soc/s3c24xx/s3c24xx-i2s.c b/sound/soc/s3c24xx/s3c24xx-i2s.c
new file mode 100644
index 000000000000..8ca314dc8891
--- /dev/null
+++ b/sound/soc/s3c24xx/s3c24xx-i2s.c
@@ -0,0 +1,441 @@
+/*
+ * s3c24xx-i2s.c  --  ALSA Soc Audio Layer
+ *
+ * (c) 2006 Wolfson Microelectronics PLC.
+ * Graeme Gregory graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
+ *
+ * (c) 2004-2005 Simtec Electronics
+ *	http://armlinux.simtec.co.uk/
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ *  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.
+ *
+ *
+ *  Revision history
+ *    11th Dec 2006   Merged with Simtec driver
+ *    10th Nov 2006   Initial version.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/arch/regs-iis.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-clock.h>
+#include <asm/arch/audio.h>
+#include <asm/dma.h>
+#include <asm/arch/dma.h>
+
+#include "s3c24xx-pcm.h"
+#include "s3c24xx-i2s.h"
+
+#define S3C24XX_I2S_DEBUG 0
+#if S3C24XX_I2S_DEBUG
+#define DBG(x...) printk(KERN_DEBUG x)
+#else
+#define DBG(x...)
+#endif
+
+static struct s3c2410_dma_client s3c24xx_dma_client_out = {
+	.name = "I2S PCM Stereo out"
+};
+
+static struct s3c2410_dma_client s3c24xx_dma_client_in = {
+	.name = "I2S PCM Stereo in"
+};
+
+static struct s3c24xx_pcm_dma_params s3c24xx_i2s_pcm_stereo_out = {
+	.client		= &s3c24xx_dma_client_out,
+	.channel	= DMACH_I2S_OUT,
+	.dma_addr	= S3C2410_PA_IIS + S3C2410_IISFIFO,
+	.dma_size	= 2,
+};
+
+static struct s3c24xx_pcm_dma_params s3c24xx_i2s_pcm_stereo_in = {
+	.client		= &s3c24xx_dma_client_in,
+	.channel	= DMACH_I2S_IN,
+	.dma_addr	= S3C2410_PA_IIS + S3C2410_IISFIFO,
+	.dma_size	= 2,
+};
+
+struct s3c24xx_i2s_info {
+	void __iomem	*regs;
+	struct clk	*iis_clk;
+};
+static struct s3c24xx_i2s_info s3c24xx_i2s;
+
+static void s3c24xx_snd_txctrl(int on)
+{
+	u32 iisfcon;
+	u32 iiscon;
+	u32 iismod;
+
+	DBG("Entered %s\n", __FUNCTION__);
+
+	iisfcon = readl(s3c24xx_i2s.regs + S3C2410_IISFCON);
+	iiscon  = readl(s3c24xx_i2s.regs + S3C2410_IISCON);
+	iismod  = readl(s3c24xx_i2s.regs + S3C2410_IISMOD);
+
+	DBG("r: IISCON: %lx IISMOD: %lx IISFCON: %lx\n", iiscon, iismod, iisfcon);
+
+	if (on) {
+		iisfcon |= S3C2410_IISFCON_TXDMA | S3C2410_IISFCON_TXENABLE;
+		iiscon  |= S3C2410_IISCON_TXDMAEN | S3C2410_IISCON_IISEN;
+		iiscon  &= ~S3C2410_IISCON_TXIDLE;
+		iismod  |= S3C2410_IISMOD_TXMODE;
+
+		writel(iismod,  s3c24xx_i2s.regs + S3C2410_IISMOD);
+		writel(iisfcon, s3c24xx_i2s.regs + S3C2410_IISFCON);
+		writel(iiscon,  s3c24xx_i2s.regs + S3C2410_IISCON);
+	} else {
+		/* note, we have to disable the FIFOs otherwise bad things
+		 * seem to happen when the DMA stops. According to the
+		 * Samsung supplied kernel, this should allow the DMA
+		 * engine and FIFOs to reset. If this isn't allowed, the
+		 * DMA engine will simply freeze randomly.
+		 */
+
+		iisfcon &= ~S3C2410_IISFCON_TXENABLE;
+		iisfcon &= ~S3C2410_IISFCON_TXDMA;
+		iiscon  |=  S3C2410_IISCON_TXIDLE;
+		iiscon  &= ~S3C2410_IISCON_TXDMAEN;
+		iismod  &= ~S3C2410_IISMOD_TXMODE;
+
+		writel(iiscon,  s3c24xx_i2s.regs + S3C2410_IISCON);
+		writel(iisfcon, s3c24xx_i2s.regs + S3C2410_IISFCON);
+		writel(iismod,  s3c24xx_i2s.regs + S3C2410_IISMOD);
+	}
+
+	DBG("w: IISCON: %lx IISMOD: %lx IISFCON: %lx\n", iiscon, iismod, iisfcon);
+}
+
+static void s3c24xx_snd_rxctrl(int on)
+{
+	u32 iisfcon;
+	u32 iiscon;
+	u32 iismod;
+
+	DBG("Entered %s\n", __FUNCTION__);
+
+	iisfcon = readl(s3c24xx_i2s.regs + S3C2410_IISFCON);
+	iiscon  = readl(s3c24xx_i2s.regs + S3C2410_IISCON);
+	iismod  = readl(s3c24xx_i2s.regs + S3C2410_IISMOD);
+
+	DBG("r: IISCON: %lx IISMOD: %lx IISFCON: %lx\n", iiscon, iismod, iisfcon);
+
+	if (on) {
+		iisfcon |= S3C2410_IISFCON_RXDMA | S3C2410_IISFCON_RXENABLE;
+		iiscon  |= S3C2410_IISCON_RXDMAEN | S3C2410_IISCON_IISEN;
+		iiscon  &= ~S3C2410_IISCON_RXIDLE;
+		iismod  |= S3C2410_IISMOD_RXMODE;
+
+		writel(iismod,  s3c24xx_i2s.regs + S3C2410_IISMOD);
+		writel(iisfcon, s3c24xx_i2s.regs + S3C2410_IISFCON);
+		writel(iiscon,  s3c24xx_i2s.regs + S3C2410_IISCON);
+	} else {
+		/* note, we have to disable the FIFOs otherwise bad things
+		 * seem to happen when the DMA stops. According to the
+		 * Samsung supplied kernel, this should allow the DMA
+		 * engine and FIFOs to reset. If this isn't allowed, the
+		 * DMA engine will simply freeze randomly.
+		 */
+
+        iisfcon &= ~S3C2410_IISFCON_RXENABLE;
+        iisfcon &= ~S3C2410_IISFCON_RXDMA;
+        iiscon  |= S3C2410_IISCON_RXIDLE;
+        iiscon  &= ~S3C2410_IISCON_RXDMAEN;
+		iismod  &= ~S3C2410_IISMOD_RXMODE;
+
+		writel(iisfcon, s3c24xx_i2s.regs + S3C2410_IISFCON);
+		writel(iiscon,  s3c24xx_i2s.regs + S3C2410_IISCON);
+		writel(iismod,  s3c24xx_i2s.regs + S3C2410_IISMOD);
+	}
+
+	DBG("w: IISCON: %lx IISMOD: %lx IISFCON: %lx\n", iiscon, iismod, iisfcon);
+}
+
+/*
+ * Wait for the LR signal to allow synchronisation to the L/R clock
+ * from the codec. May only be needed for slave mode.
+ */
+static int s3c24xx_snd_lrsync(void)
+{
+	u32 iiscon;
+	unsigned long timeout = jiffies + msecs_to_jiffies(5);
+
+	DBG("Entered %s\n", __FUNCTION__);
+
+	while (1) {
+		iiscon = readl(s3c24xx_i2s.regs + S3C2410_IISCON);
+		if (iiscon & S3C2410_IISCON_LRINDEX)
+			break;
+
+		if (timeout < jiffies)
+			return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+/*
+ * Check whether CPU is the master or slave
+ */
+static inline int s3c24xx_snd_is_clkmaster(void)
+{
+	DBG("Entered %s\n", __FUNCTION__);
+
+	return (readl(s3c24xx_i2s.regs + S3C2410_IISMOD) & S3C2410_IISMOD_SLAVE) ? 0:1;
+}
+
+/*
+ * Set S3C24xx I2S DAI format
+ */
+static int s3c24xx_i2s_set_fmt(struct snd_soc_cpu_dai *cpu_dai,
+		unsigned int fmt)
+{
+	u32 iismod;
+
+	DBG("Entered %s\n", __FUNCTION__);
+
+	iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD);
+	DBG("hw_params r: IISMOD: %lx \n", iismod);
+
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBM_CFM:
+		iismod |= S3C2410_IISMOD_SLAVE;
+		break;
+	case SND_SOC_DAIFMT_CBS_CFS:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_LEFT_J:
+		iismod |= S3C2410_IISMOD_MSB;
+		break;
+	case SND_SOC_DAIFMT_I2S:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD);
+	DBG("hw_params w: IISMOD: %lx \n", iismod);
+	return 0;
+}
+
+static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream,
+				struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	u32 iismod;
+
+	DBG("Entered %s\n", __FUNCTION__);
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		rtd->dai->cpu_dai->dma_data = &s3c24xx_i2s_pcm_stereo_out;
+	else
+		rtd->dai->cpu_dai->dma_data = &s3c24xx_i2s_pcm_stereo_in;
+
+	/* Working copies of register */
+	iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD);
+	DBG("hw_params r: IISMOD: %lx\n", iismod);
+
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S8:
+		break;
+	case SNDRV_PCM_FORMAT_S16_LE:
+		iismod |= S3C2410_IISMOD_16BIT;
+		break;
+	}
+
+	writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD);
+	DBG("hw_params w: IISMOD: %lx\n", iismod);
+	return 0;
+}
+
+static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	int ret = 0;
+
+	DBG("Entered %s\n", __FUNCTION__);
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		if (!s3c24xx_snd_is_clkmaster()) {
+			ret = s3c24xx_snd_lrsync();
+			if (ret)
+				goto exit_err;
+		}
+
+		if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+			s3c24xx_snd_rxctrl(1);
+		else
+			s3c24xx_snd_txctrl(1);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+			s3c24xx_snd_rxctrl(0);
+		else
+			s3c24xx_snd_txctrl(0);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+exit_err:
+	return ret;
+}
+
+/*
+ * Set S3C24xx Clock source
+ */
+static int s3c24xx_i2s_set_sysclk(struct snd_soc_cpu_dai *cpu_dai,
+	int clk_id, unsigned int freq, int dir)
+{
+	u32 iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD);
+
+	DBG("Entered %s\n", __FUNCTION__);
+
+	iismod &= ~S3C2440_IISMOD_MPLL;
+
+	switch (clk_id) {
+	case S3C24XX_CLKSRC_PCLK:
+		break;
+	case S3C24XX_CLKSRC_MPLL:
+		iismod |= S3C2440_IISMOD_MPLL;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD);
+	return 0;
+}
+
+/*
+ * Set S3C24xx Clock dividers
+ */
+static int s3c24xx_i2s_set_clkdiv(struct snd_soc_cpu_dai *cpu_dai,
+	int div_id, int div)
+{
+	u32 reg;
+
+	DBG("Entered %s\n", __FUNCTION__);
+
+	switch (div_id) {
+	case S3C24XX_DIV_MCLK:
+		reg = readl(s3c24xx_i2s.regs + S3C2410_IISMOD) & ~S3C2410_IISMOD_FS_MASK;
+		writel(reg | div, s3c24xx_i2s.regs + S3C2410_IISMOD);
+		break;
+	case S3C24XX_DIV_BCLK:
+		reg = readl(s3c24xx_i2s.regs + S3C2410_IISMOD) & ~(S3C2410_IISMOD_384FS);
+		writel(reg | div, s3c24xx_i2s.regs + S3C2410_IISMOD);
+		break;
+	case S3C24XX_DIV_PRESCALER:
+		writel(div, s3c24xx_i2s.regs + S3C2410_IISPSR);
+		reg = readl(s3c24xx_i2s.regs + S3C2410_IISCON);
+		writel(reg | S3C2410_IISCON_PSCEN, s3c24xx_i2s.regs + S3C2410_IISCON);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ * To avoid duplicating clock code, allow machine driver to
+ * get the clockrate from here.
+ */
+u32 s3c24xx_i2s_get_clockrate(void)
+{
+	return clk_get_rate(s3c24xx_i2s.iis_clk);
+}
+EXPORT_SYMBOL_GPL(s3c24xx_i2s_get_clockrate);
+
+static int s3c24xx_i2s_probe(struct platform_device *pdev)
+{
+	DBG("Entered %s\n", __FUNCTION__);
+
+	s3c24xx_i2s.regs = ioremap(S3C2410_PA_IIS, 0x100);
+	if (s3c24xx_i2s.regs == NULL)
+		return -ENXIO;
+
+	s3c24xx_i2s.iis_clk=clk_get(&pdev->dev, "iis");
+	if (s3c24xx_i2s.iis_clk == NULL) {
+		DBG("failed to get iis_clock\n");
+		return -ENODEV;
+	}
+	clk_enable(s3c24xx_i2s.iis_clk);
+
+	/* Configure the I2S pins in correct mode */
+	s3c2410_gpio_cfgpin(S3C2410_GPE0, S3C2410_GPE0_I2SLRCK);
+	s3c2410_gpio_cfgpin(S3C2410_GPE1, S3C2410_GPE1_I2SSCLK);
+	s3c2410_gpio_cfgpin(S3C2410_GPE2, S3C2410_GPE2_CDCLK);
+	s3c2410_gpio_cfgpin(S3C2410_GPE3, S3C2410_GPE3_I2SSDI);
+	s3c2410_gpio_cfgpin(S3C2410_GPE4, S3C2410_GPE4_I2SSDO);
+
+	writel(S3C2410_IISCON_IISEN, s3c24xx_i2s.regs + S3C2410_IISCON);
+
+	s3c24xx_snd_txctrl(0);
+	s3c24xx_snd_rxctrl(0);
+
+	return 0;
+}
+
+#define S3C24XX_I2S_RATES \
+	(SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \
+	SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
+	SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
+
+struct snd_soc_cpu_dai s3c24xx_i2s_dai = {
+	.name = "s3c24xx-i2s",
+	.id = 0,
+	.type = SND_SOC_DAI_I2S,
+	.probe = s3c24xx_i2s_probe,
+	.playback = {
+		.channels_min = 2,
+		.channels_max = 2,
+		.rates = S3C24XX_I2S_RATES,
+		.formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,},
+	.capture = {
+		.channels_min = 2,
+		.channels_max = 2,
+		.rates = S3C24XX_I2S_RATES,
+		.formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,},
+	.ops = {
+		.trigger = s3c24xx_i2s_trigger,
+		.hw_params = s3c24xx_i2s_hw_params,},
+	.dai_ops = {
+		.set_fmt = s3c24xx_i2s_set_fmt,
+		.set_clkdiv = s3c24xx_i2s_set_clkdiv,
+		.set_sysclk = s3c24xx_i2s_set_sysclk,
+	},
+};
+EXPORT_SYMBOL_GPL(s3c24xx_i2s_dai);
+
+/* Module information */
+MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
+MODULE_DESCRIPTION("s3c24xx I2S SoC Interface");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/s3c24xx/s3c24xx-i2s.h b/sound/soc/s3c24xx/s3c24xx-i2s.h
new file mode 100644
index 000000000000..537b4ecce8a3
--- /dev/null
+++ b/sound/soc/s3c24xx/s3c24xx-i2s.h
@@ -0,0 +1,37 @@
+/*
+ * s3c24xx-i2s.c  --  ALSA Soc Audio Layer
+ *
+ * Copyright 2005 Wolfson Microelectronics PLC.
+ * Author: Graeme Gregory
+ *         graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
+ *
+ *  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.
+ *
+ *  Revision history
+ *    10th Nov 2006   Initial version.
+ */
+
+#ifndef S3C24XXI2S_H_
+#define S3C24XXI2S_H_
+
+/* clock sources */
+#define S3C24XX_CLKSRC_PCLK 0
+#define S3C24XX_CLKSRC_MPLL 1
+
+/* Clock dividers */
+#define S3C24XX_DIV_MCLK	0
+#define S3C24XX_DIV_BCLK	1
+#define S3C24XX_DIV_PRESCALER	2
+
+/* prescaler */
+#define S3C24XX_PRESCALE(a,b) \
+	(((a - 1) << S3C2410_IISPSR_INTSHIFT) | ((b - 1) << S3C2410_IISPSR_EXTSHFIT))
+
+u32 s3c24xx_i2s_get_clockrate(void);
+
+extern struct snd_soc_cpu_dai s3c24xx_i2s_dai;
+
+#endif /*S3C24XXI2S_H_*/
diff --git a/sound/soc/s3c24xx/s3c24xx-pcm.c b/sound/soc/s3c24xx/s3c24xx-pcm.c
new file mode 100644
index 000000000000..21dc6974d6a3
--- /dev/null
+++ b/sound/soc/s3c24xx/s3c24xx-pcm.c
@@ -0,0 +1,468 @@
+/*
+ * s3c24xx-pcm.c  --  ALSA Soc Audio Layer
+ *
+ * (c) 2006 Wolfson Microelectronics PLC.
+ * Graeme Gregory graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
+ *
+ * (c) 2004-2005 Simtec Electronics
+ *	http://armlinux.simtec.co.uk/
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ *  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.
+ *
+ *  Revision history
+ *    11th Dec 2006   Merged with Simtec driver
+ *    10th Nov 2006   Initial version.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/arch/dma.h>
+#include <asm/arch/audio.h>
+
+#include "s3c24xx-pcm.h"
+
+#define S3C24XX_PCM_DEBUG 0
+#if S3C24XX_PCM_DEBUG
+#define DBG(x...) printk(KERN_DEBUG x)
+#else
+#define DBG(x...)
+#endif
+
+static const struct snd_pcm_hardware s3c24xx_pcm_hardware = {
+	.info			= SNDRV_PCM_INFO_INTERLEAVED |
+				    SNDRV_PCM_INFO_BLOCK_TRANSFER |
+				    SNDRV_PCM_INFO_MMAP |
+				    SNDRV_PCM_INFO_MMAP_VALID,
+	.formats		= SNDRV_PCM_FMTBIT_S16_LE |
+				    SNDRV_PCM_FMTBIT_U16_LE |
+				    SNDRV_PCM_FMTBIT_U8 |
+				    SNDRV_PCM_FMTBIT_S8,
+	.channels_min		= 2,
+	.channels_max		= 2,
+	.buffer_bytes_max	= 128*1024,
+	.period_bytes_min	= PAGE_SIZE,
+	.period_bytes_max	= PAGE_SIZE*2,
+	.periods_min		= 2,
+	.periods_max		= 128,
+	.fifo_size		= 32,
+};
+
+struct s3c24xx_runtime_data {
+	spinlock_t lock;
+	int state;
+	unsigned int dma_loaded;
+	unsigned int dma_limit;
+	unsigned int dma_period;
+	dma_addr_t dma_start;
+	dma_addr_t dma_pos;
+	dma_addr_t dma_end;
+	struct s3c24xx_pcm_dma_params *params;
+};
+
+/* s3c24xx_pcm_enqueue
+ *
+ * place a dma buffer onto the queue for the dma system
+ * to handle.
+*/
+static void s3c24xx_pcm_enqueue(struct snd_pcm_substream *substream)
+{
+	struct s3c24xx_runtime_data *prtd = substream->runtime->private_data;
+	dma_addr_t pos = prtd->dma_pos;
+	int ret;
+
+	DBG("Entered %s\n", __FUNCTION__);
+
+	while (prtd->dma_loaded < prtd->dma_limit) {
+		unsigned long len = prtd->dma_period;
+
+		DBG("dma_loaded: %d\n",prtd->dma_loaded);
+
+		if ((pos + len) > prtd->dma_end) {
+			len  = prtd->dma_end - pos;
+			DBG(KERN_DEBUG "%s: corrected dma len %ld\n",
+			       __FUNCTION__, len);
+		}
+
+		ret = s3c2410_dma_enqueue(prtd->params->channel, 
+			substream, pos, len);
+
+		if (ret == 0) {
+			prtd->dma_loaded++;
+			pos += prtd->dma_period;
+			if (pos >= prtd->dma_end)
+				pos = prtd->dma_start;
+		} else
+			break;
+	}
+
+	prtd->dma_pos = pos;
+}
+
+static void s3c24xx_audio_buffdone(struct s3c2410_dma_chan *channel,
+				void *dev_id, int size,
+				enum s3c2410_dma_buffresult result)
+{
+	struct snd_pcm_substream *substream = dev_id;
+	struct s3c24xx_runtime_data *prtd;
+
+	DBG("Entered %s\n", __FUNCTION__);
+
+	if (result == S3C2410_RES_ABORT || result == S3C2410_RES_ERR)
+		return;
+
+	prtd = substream->runtime->private_data;
+	
+	if (substream)
+		snd_pcm_period_elapsed(substream);
+
+	spin_lock(&prtd->lock);
+	if (prtd->state & ST_RUNNING) {
+		prtd->dma_loaded--;
+		s3c24xx_pcm_enqueue(substream);
+	}
+
+	spin_unlock(&prtd->lock);
+}
+
+static int s3c24xx_pcm_hw_params(struct snd_pcm_substream *substream,
+	struct snd_pcm_hw_params *params)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct s3c24xx_runtime_data *prtd = runtime->private_data;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct s3c24xx_pcm_dma_params *dma = rtd->dai->cpu_dai->dma_data;
+	unsigned long totbytes = params_buffer_bytes(params);
+	int ret=0;
+
+	DBG("Entered %s\n", __FUNCTION__);
+
+	/* return if this is a bufferless transfer e.g.
+	 * codec <--> BT codec or GSM modem -- lg FIXME */
+	if (!dma)
+		return 0;
+
+	/* prepare DMA */
+	prtd->params = dma;
+
+	DBG("params %p, client %p, channel %d\n", prtd->params,
+		prtd->params->client, prtd->params->channel);
+
+	ret = s3c2410_dma_request(prtd->params->channel,
+				  prtd->params->client, NULL);
+
+	if (ret) {
+		DBG(KERN_ERR "failed to get dma channel\n");
+		return ret;
+	}
+
+	/* channel needs configuring for mem=>device, increment memory addr,
+	 * sync to pclk, half-word transfers to the IIS-FIFO. */
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		s3c2410_dma_devconfig(prtd->params->channel,
+				S3C2410_DMASRC_MEM, S3C2410_DISRCC_INC |
+				S3C2410_DISRCC_APB, prtd->params->dma_addr);
+
+		s3c2410_dma_config(prtd->params->channel,
+				prtd->params->dma_size,
+				S3C2410_DCON_SYNC_PCLK | 
+				S3C2410_DCON_HANDSHAKE);
+	} else {
+		s3c2410_dma_config(prtd->params->channel,
+				prtd->params->dma_size,
+				S3C2410_DCON_HANDSHAKE | 
+				S3C2410_DCON_SYNC_PCLK);
+
+		s3c2410_dma_devconfig(prtd->params->channel,
+					S3C2410_DMASRC_HW, 0x3,
+					prtd->params->dma_addr);
+	}
+
+	s3c2410_dma_set_buffdone_fn(prtd->params->channel,
+				    s3c24xx_audio_buffdone);
+
+	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
+
+	runtime->dma_bytes = totbytes;
+
+	spin_lock_irq(&prtd->lock);
+	prtd->dma_loaded = 0;
+	prtd->dma_limit = runtime->hw.periods_min;
+	prtd->dma_period = params_period_bytes(params);
+	prtd->dma_start = runtime->dma_addr;
+	prtd->dma_pos = prtd->dma_start;
+	prtd->dma_end = prtd->dma_start + totbytes;
+	spin_unlock_irq(&prtd->lock);
+
+	return 0;
+}
+
+static int s3c24xx_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+	struct s3c24xx_runtime_data *prtd = substream->runtime->private_data;
+
+	DBG("Entered %s\n", __FUNCTION__);
+
+	/* TODO - do we need to ensure DMA flushed */
+	snd_pcm_set_runtime_buffer(substream, NULL);
+
+	if (prtd->params) {
+		s3c2410_dma_free(prtd->params->channel, prtd->params->client);
+		prtd->params = NULL;
+	}
+
+	return 0;
+}
+
+static int s3c24xx_pcm_prepare(struct snd_pcm_substream *substream)
+{
+	struct s3c24xx_runtime_data *prtd = substream->runtime->private_data;
+	int ret = 0;
+
+	DBG("Entered %s\n", __FUNCTION__);
+
+	/* return if this is a bufferless transfer e.g.
+	 * codec <--> BT codec or GSM modem -- lg FIXME */
+	if (!prtd->params)
+	 	return 0;
+
+	/* flush the DMA channel */
+	s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_FLUSH);
+	prtd->dma_loaded = 0;
+	prtd->dma_pos = prtd->dma_start;
+
+	/* enqueue dma buffers */
+	s3c24xx_pcm_enqueue(substream);
+
+	return ret;
+}
+
+static int s3c24xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	struct s3c24xx_runtime_data *prtd = substream->runtime->private_data;
+	int ret = 0;
+
+	DBG("Entered %s\n", __FUNCTION__);
+
+	spin_lock(&prtd->lock);
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		prtd->state |= ST_RUNNING;
+		s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_START);
+		s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_STARTED);
+		break;
+
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		prtd->state &= ~ST_RUNNING;
+		s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_STOP);
+		break;
+
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	spin_unlock(&prtd->lock);
+
+	return ret;
+}
+
+static snd_pcm_uframes_t 
+	s3c24xx_pcm_pointer(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct s3c24xx_runtime_data *prtd = runtime->private_data;
+	unsigned long res;
+	dma_addr_t src, dst;
+
+	DBG("Entered %s\n", __FUNCTION__);
+
+	spin_lock(&prtd->lock);
+	s3c2410_dma_getposition(prtd->params->channel, &src, &dst);
+
+	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+		res = dst - prtd->dma_start;
+	else
+		res = src - prtd->dma_start;
+
+	spin_unlock(&prtd->lock);
+
+	DBG("Pointer %x %x\n",src,dst);
+
+	/* we seem to be getting the odd error from the pcm library due
+	 * to out-of-bounds pointers. this is maybe due to the dma engine
+	 * not having loaded the new values for the channel before being
+	 * callled... (todo - fix )
+	 */
+
+	if (res >= snd_pcm_lib_buffer_bytes(substream)) {
+		if (res == snd_pcm_lib_buffer_bytes(substream))
+			res = 0;
+	}
+
+	return bytes_to_frames(substream->runtime, res);
+}
+
+static int s3c24xx_pcm_open(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct s3c24xx_runtime_data *prtd;
+
+	DBG("Entered %s\n", __FUNCTION__);
+
+	snd_soc_set_runtime_hwparams(substream, &s3c24xx_pcm_hardware);
+
+	prtd = kzalloc(sizeof(struct s3c24xx_runtime_data), GFP_KERNEL);
+	if (prtd == NULL)
+		return -ENOMEM;
+
+	runtime->private_data = prtd;
+	return 0;
+}
+
+static int s3c24xx_pcm_close(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct s3c24xx_runtime_data *prtd = runtime->private_data;
+
+	DBG("Entered %s\n", __FUNCTION__);
+
+	if (prtd)
+		kfree(prtd);
+	else
+		DBG("s3c24xx_pcm_close called with prtd == NULL\n");
+
+	return 0;
+}
+
+static int s3c24xx_pcm_mmap(struct snd_pcm_substream *substream,
+	struct vm_area_struct *vma)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+
+	DBG("Entered %s\n", __FUNCTION__);
+
+	return dma_mmap_writecombine(substream->pcm->card->dev, vma,
+                                     runtime->dma_area,
+                                     runtime->dma_addr,
+                                     runtime->dma_bytes);
+}
+
+static struct snd_pcm_ops s3c24xx_pcm_ops = {
+	.open		= s3c24xx_pcm_open,
+	.close		= s3c24xx_pcm_close,
+	.ioctl		= snd_pcm_lib_ioctl,
+	.hw_params	= s3c24xx_pcm_hw_params,
+	.hw_free	= s3c24xx_pcm_hw_free,
+	.prepare	= s3c24xx_pcm_prepare,
+	.trigger	= s3c24xx_pcm_trigger,
+	.pointer	= s3c24xx_pcm_pointer,
+	.mmap		= s3c24xx_pcm_mmap,
+};
+
+static int s3c24xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
+{
+	struct snd_pcm_substream *substream = pcm->streams[stream].substream;
+	struct snd_dma_buffer *buf = &substream->dma_buffer;
+	size_t size = s3c24xx_pcm_hardware.buffer_bytes_max;
+
+	DBG("Entered %s\n", __FUNCTION__);
+
+	buf->dev.type = SNDRV_DMA_TYPE_DEV;
+	buf->dev.dev = pcm->card->dev;
+	buf->private_data = NULL;
+	buf->area = dma_alloc_writecombine(pcm->card->dev, size,
+					   &buf->addr, GFP_KERNEL);
+	if (!buf->area)
+		return -ENOMEM;
+	buf->bytes = size;
+	return 0;
+}
+
+static void s3c24xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
+{
+	struct snd_pcm_substream *substream;
+	struct snd_dma_buffer *buf;
+	int stream;
+
+	DBG("Entered %s\n", __FUNCTION__);
+
+	for (stream = 0; stream < 2; stream++) {
+		substream = pcm->streams[stream].substream;
+		if (!substream)
+			continue;
+
+		buf = &substream->dma_buffer;
+		if (!buf->area)
+			continue;
+
+		dma_free_writecombine(pcm->card->dev, buf->bytes,
+				      buf->area, buf->addr);
+		buf->area = NULL;
+	}
+}
+
+static u64 s3c24xx_pcm_dmamask = DMA_32BIT_MASK;
+
+static int s3c24xx_pcm_new(struct snd_card *card, 
+	struct snd_soc_codec_dai *dai, struct snd_pcm *pcm)
+{
+	int ret = 0;
+
+	DBG("Entered %s\n", __FUNCTION__);
+
+	if (!card->dev->dma_mask)
+		card->dev->dma_mask = &s3c24xx_pcm_dmamask;
+	if (!card->dev->coherent_dma_mask)
+		card->dev->coherent_dma_mask = 0xffffffff;
+
+	if (dai->playback.channels_min) {
+		ret = s3c24xx_pcm_preallocate_dma_buffer(pcm,
+			SNDRV_PCM_STREAM_PLAYBACK);
+		if (ret)
+			goto out;
+	}
+
+	if (dai->capture.channels_min) {
+		ret = s3c24xx_pcm_preallocate_dma_buffer(pcm,
+			SNDRV_PCM_STREAM_CAPTURE);
+		if (ret)
+			goto out;
+	}
+ out:
+	return ret;
+}
+
+struct snd_soc_platform s3c24xx_soc_platform = {
+	.name		= "s3c24xx-audio",
+	.pcm_ops 	= &s3c24xx_pcm_ops,
+	.pcm_new	= s3c24xx_pcm_new,
+	.pcm_free	= s3c24xx_pcm_free_dma_buffers,
+};
+
+EXPORT_SYMBOL_GPL(s3c24xx_soc_platform);
+
+MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
+MODULE_DESCRIPTION("Samsung S3C24XX PCM DMA module");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/s3c24xx/s3c24xx-pcm.h b/sound/soc/s3c24xx/s3c24xx-pcm.h
new file mode 100644
index 000000000000..0088c79822ea
--- /dev/null
+++ b/sound/soc/s3c24xx/s3c24xx-pcm.h
@@ -0,0 +1,31 @@
+/*
+ *  s3c24xx-pcm.h --
+ *
+ *  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.
+ *
+ *  ALSA PCM interface for the Samsung S3C24xx CPU
+ */
+
+#ifndef _S3C24XX_PCM_H
+#define _S3C24XX_PCM_H
+
+#define ST_RUNNING		(1<<0)
+#define ST_OPENED		(1<<1)
+
+struct s3c24xx_pcm_dma_params {
+	struct s3c2410_dma_client *client;	/* stream identifier */
+	int channel;				/* Channel ID */
+	dma_addr_t dma_addr;
+	int dma_size;			/* Size of the DMA transfer */
+};
+
+#define S3C24XX_DAI_I2S			0
+
+/* platform data */
+extern struct snd_soc_platform s3c24xx_soc_platform;
+extern struct snd_ac97_bus_ops s3c24xx_ac97_ops;
+
+#endif
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 7caf8c7b0ac5..96bce55572a0 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -882,13 +882,15 @@ int snd_soc_dapm_connect_input(struct snd_soc_codec *codec, const char *sink,
 	if (wsink->id == snd_soc_dapm_input) {
 		if (wsource->id == snd_soc_dapm_micbias ||
 			wsource->id == snd_soc_dapm_mic ||
-			wsink->id == snd_soc_dapm_line)
+			wsink->id == snd_soc_dapm_line ||
+			wsink->id == snd_soc_dapm_output)
 			wsink->ext = 1;
 	}
 	if (wsource->id == snd_soc_dapm_output) {
 		if (wsink->id == snd_soc_dapm_spk ||
 			wsink->id == snd_soc_dapm_hp ||
-			wsink->id == snd_soc_dapm_line)
+			wsink->id == snd_soc_dapm_line ||
+			wsink->id == snd_soc_dapm_input)
 			wsource->ext = 1;
 	}
 
diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c
index 900a00de35fd..dca0344cc1bc 100644
--- a/sound/sparc/cs4231.c
+++ b/sound/sparc/cs4231.c
@@ -661,11 +661,9 @@ static int snd_cs4231_trigger(struct snd_pcm_substream *substream, int cmd)
 	{
 		unsigned int what = 0;
 		struct snd_pcm_substream *s;
-		struct list_head *pos;
 		unsigned long flags;
 
-		snd_pcm_group_for_each(pos, substream) {
-			s = snd_pcm_group_substream_entry(pos);
+		snd_pcm_group_for_each_entry(s, substream) {
 			if (s == chip->playback_substream) {
 				what |= CS4231_PLAYBACK_ENABLE;
 				snd_pcm_trigger_done(s, substream);
diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig
index f05d02f5b69f..315360f31278 100644
--- a/sound/usb/Kconfig
+++ b/sound/usb/Kconfig
@@ -29,5 +29,33 @@ config SND_USB_USX2Y
 	  To compile this driver as a module, choose M here: the module
 	  will be called snd-usb-usx2y.
 
+config SND_USB_CAIAQ
+	tristate "Native Instruments USB audio devices"
+	 depends on SND && USB
+	 select SND_HWDEP
+	 select SND_RAWMIDI
+	 select SND_PCM
+	 help
+	   Say Y here to include support for caiaq USB audio interfaces,
+	   namely:
+
+	    * Native Instruments RigKontrol2
+	    * Native Instruments Kore Controller
+	    * Native Instruments Audio Kontrol 1
+	    * Native Instruments Audio 8 DJ
+
+	   To compile this driver as a module, choose M here: the module
+	   will be called snd-usb-caiaq.
+
+config SND_USB_CAIAQ_INPUT
+	bool "enable input device for controllers"
+	depends on SND_USB_CAIAQ
+	help
+	  Say Y here to support input controllers like buttons, knobs,
+	  alpha dials and analog pedals on the following products:
+
+	   * Native Instruments RigKontrol2
+	   * Native Instruments Audio Kontrol 1
+
 endmenu
 
diff --git a/sound/usb/Makefile b/sound/usb/Makefile
index 2c1dc11a72e2..aa252ef2ebfb 100644
--- a/sound/usb/Makefile
+++ b/sound/usb/Makefile
@@ -9,4 +9,4 @@ snd-usb-lib-objs := usbmidi.o
 obj-$(CONFIG_SND_USB_AUDIO) += snd-usb-audio.o snd-usb-lib.o
 obj-$(CONFIG_SND_USB_USX2Y) += snd-usb-lib.o
 
-obj-$(CONFIG_SND) += usx2y/
+obj-$(CONFIG_SND) += usx2y/ caiaq/
diff --git a/sound/usb/caiaq/Makefile b/sound/usb/caiaq/Makefile
new file mode 100644
index 000000000000..455c8c58a1bd
--- /dev/null
+++ b/sound/usb/caiaq/Makefile
@@ -0,0 +1,3 @@
+snd-usb-caiaq-objs := caiaq-device.o caiaq-audio.o caiaq-midi.o caiaq-input.o
+
+obj-$(CONFIG_SND_USB_CAIAQ) += snd-usb-caiaq.o
diff --git a/sound/usb/caiaq/caiaq-audio.c b/sound/usb/caiaq/caiaq-audio.c
new file mode 100644
index 000000000000..0414d766ba07
--- /dev/null
+++ b/sound/usb/caiaq/caiaq-audio.c
@@ -0,0 +1,707 @@
+/*
+ *   Copyright (c) 2006,2007 Daniel Mack, Karsten Wiese
+ *
+ *   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 <sound/driver.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/interrupt.h>
+#include <linux/usb.h>
+#include <linux/spinlock.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/pcm.h>
+#include <sound/rawmidi.h>
+#ifdef CONFIG_SND_USB_CAIAQ_INPUT
+#include <linux/input.h>
+#endif
+
+#include "caiaq-device.h"
+#include "caiaq-audio.h"
+
+#define N_URBS			32
+#define CLOCK_DRIFT_TOLERANCE	5
+#define FRAMES_PER_URB		8
+#define BYTES_PER_FRAME		512
+#define CHANNELS_PER_STREAM	2
+#define BYTES_PER_SAMPLE	3
+#define BYTES_PER_SAMPLE_USB	4
+#define MAX_BUFFER_SIZE		(128*1024)
+				 
+#define ENDPOINT_CAPTURE	2
+#define ENDPOINT_PLAYBACK	6
+
+#define MAKE_CHECKBYTE(dev,stream,i) \
+	(stream << 1) | (~(i / (dev->n_streams * BYTES_PER_SAMPLE_USB)) & 1)
+
+static struct snd_pcm_hardware snd_usb_caiaq_pcm_hardware = {
+	.info 		= (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | 
+			   SNDRV_PCM_INFO_BLOCK_TRANSFER),
+	.formats 	= SNDRV_PCM_FMTBIT_S24_3BE,
+	.rates 		= (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | 
+			   SNDRV_PCM_RATE_96000),
+	.rate_min	= 44100,
+	.rate_max	= 0, /* will overwrite later */
+	.channels_min	= CHANNELS_PER_STREAM,
+	.channels_max	= CHANNELS_PER_STREAM,
+	.buffer_bytes_max = MAX_BUFFER_SIZE,
+	.period_bytes_min = 4096,
+	.period_bytes_max = MAX_BUFFER_SIZE,
+	.periods_min	= 1,
+	.periods_max	= 1024,
+};
+
+static void
+activate_substream(struct snd_usb_caiaqdev *dev,
+	           struct snd_pcm_substream *sub)
+{
+	if (sub->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		dev->sub_playback[sub->number] = sub;
+	else
+		dev->sub_capture[sub->number] = sub;
+}
+
+static void 
+deactivate_substream(struct snd_usb_caiaqdev *dev,
+		     struct snd_pcm_substream *sub)
+{
+	if (sub->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		dev->sub_playback[sub->number] = NULL;
+	else
+		dev->sub_capture[sub->number] = NULL;
+}
+
+static int
+all_substreams_zero(struct snd_pcm_substream **subs)
+{
+	int i;
+	for (i = 0; i < MAX_STREAMS; i++)
+		if (subs[i] != NULL)
+			return 0;
+	return 1;
+}
+
+static int stream_start(struct snd_usb_caiaqdev *dev)
+{
+	int i, ret;
+
+	debug("stream_start(%p)\n", dev);
+	spin_lock_irq(&dev->spinlock);
+	if (dev->streaming) {
+		spin_unlock_irq(&dev->spinlock);
+		return -EINVAL;
+	}
+
+	dev->input_panic = 0;
+	dev->output_panic = 0;
+	dev->first_packet = 1;
+	dev->streaming = 1;
+
+	for (i = 0; i < N_URBS; i++) {
+		ret = usb_submit_urb(dev->data_urbs_in[i], GFP_ATOMIC);
+		if (ret) {
+			log("unable to trigger initial read #%d! (ret = %d)\n",
+				i, ret);
+			dev->streaming = 0;
+			spin_unlock_irq(&dev->spinlock);
+			return -EPIPE;
+		}
+	}
+	
+	spin_unlock_irq(&dev->spinlock);
+	return 0;
+}
+
+static void stream_stop(struct snd_usb_caiaqdev *dev)
+{
+	int i;
+	
+	debug("stream_stop(%p)\n", dev);
+	if (!dev->streaming)
+		return;
+	
+	dev->streaming = 0;
+	for (i = 0; i < N_URBS; i++) {
+		usb_unlink_urb(dev->data_urbs_in[i]);
+		usb_unlink_urb(dev->data_urbs_out[i]);
+	}
+}
+
+static int snd_usb_caiaq_substream_open(struct snd_pcm_substream *substream)
+{
+	struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(substream);
+	debug("snd_usb_caiaq_substream_open(%p)\n", substream);
+	substream->runtime->hw = dev->pcm_info;
+	snd_pcm_limit_hw_rates(substream->runtime);
+	return 0;
+}
+
+static int snd_usb_caiaq_substream_close(struct snd_pcm_substream *substream)
+{
+	struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(substream);
+
+	debug("snd_usb_caiaq_substream_close(%p)\n", substream);
+	if (all_substreams_zero(dev->sub_playback) &&
+	    all_substreams_zero(dev->sub_capture)) {
+		/* when the last client has stopped streaming, 
+		 * all sample rates are allowed again */
+		stream_stop(dev);
+		dev->pcm_info.rates = dev->samplerates;
+	}
+	
+	return 0;
+}
+
+static int snd_usb_caiaq_pcm_hw_params(struct snd_pcm_substream *sub,
+			     		struct snd_pcm_hw_params *hw_params)
+{
+	debug("snd_usb_caiaq_pcm_hw_params(%p)\n", sub);
+	return snd_pcm_lib_malloc_pages(sub, params_buffer_bytes(hw_params));
+}
+
+static int snd_usb_caiaq_pcm_hw_free(struct snd_pcm_substream *sub)
+{
+	struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(sub);
+	debug("snd_usb_caiaq_pcm_hw_free(%p)\n", sub);
+	spin_lock_irq(&dev->spinlock);
+	deactivate_substream(dev, sub);
+	spin_unlock_irq(&dev->spinlock);
+	return snd_pcm_lib_free_pages(sub);
+}
+
+/* this should probably go upstream */
+#if SNDRV_PCM_RATE_5512 != 1 << 0 || SNDRV_PCM_RATE_192000 != 1 << 12
+#error "Change this table"
+#endif
+
+static unsigned int rates[] = { 5512, 8000, 11025, 16000, 22050, 32000, 44100,
+                                 48000, 64000, 88200, 96000, 176400, 192000 };
+
+static int snd_usb_caiaq_pcm_prepare(struct snd_pcm_substream *substream)
+{
+	int bytes_per_sample, bpp, ret, i;
+	int index = substream->number;
+	struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(substream);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+
+	debug("snd_usb_caiaq_pcm_prepare(%p)\n", substream);
+	
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		dev->audio_out_buf_pos[index] = BYTES_PER_SAMPLE + 1;
+	else
+		dev->audio_in_buf_pos[index] = 0;
+	
+	if (dev->streaming)
+		return 0;
+	
+	/* the first client that opens a stream defines the sample rate
+	 * setting for all subsequent calls, until the last client closed. */
+	for (i=0; i < ARRAY_SIZE(rates); i++)
+		if (runtime->rate == rates[i])
+			dev->pcm_info.rates = 1 << i;
+	
+	snd_pcm_limit_hw_rates(runtime);
+
+	bytes_per_sample = BYTES_PER_SAMPLE;
+	if (dev->spec.data_alignment == 2)
+		bytes_per_sample++;
+	
+	bpp = ((runtime->rate / 8000) + CLOCK_DRIFT_TOLERANCE)
+		* bytes_per_sample * CHANNELS_PER_STREAM * dev->n_streams;
+	
+	ret = snd_usb_caiaq_set_audio_params(dev, runtime->rate,
+					     runtime->sample_bits, bpp);
+	if (ret)
+		return ret;
+
+	ret = stream_start(dev);
+	if (ret)
+		return ret;
+	
+	dev->output_running = 0;
+	wait_event_timeout(dev->prepare_wait_queue, dev->output_running, HZ);
+	if (!dev->output_running) {
+		stream_stop(dev);
+		return -EPIPE;
+	}
+
+	return 0;
+}
+
+static int snd_usb_caiaq_pcm_trigger(struct snd_pcm_substream *sub, int cmd)
+{
+	struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(sub);
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		spin_lock(&dev->spinlock);
+		activate_substream(dev, sub);
+		spin_unlock(&dev->spinlock);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		spin_lock(&dev->spinlock);
+		deactivate_substream(dev, sub);
+		spin_unlock(&dev->spinlock);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static snd_pcm_uframes_t
+snd_usb_caiaq_pcm_pointer(struct snd_pcm_substream *sub)
+{
+	int index = sub->number;
+	struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(sub);
+
+	if (dev->input_panic || dev->output_panic)
+		return SNDRV_PCM_POS_XRUN;
+
+	if (sub->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		return bytes_to_frames(sub->runtime, 
+					dev->audio_out_buf_pos[index]);
+	else
+		return bytes_to_frames(sub->runtime,
+					dev->audio_in_buf_pos[index]);
+}
+
+/* operators for both playback and capture */
+static struct snd_pcm_ops snd_usb_caiaq_ops = {
+	.open =		snd_usb_caiaq_substream_open,
+	.close =	snd_usb_caiaq_substream_close,
+	.ioctl =	snd_pcm_lib_ioctl,
+	.hw_params =	snd_usb_caiaq_pcm_hw_params,
+	.hw_free =	snd_usb_caiaq_pcm_hw_free,
+	.prepare =	snd_usb_caiaq_pcm_prepare,
+	.trigger =	snd_usb_caiaq_pcm_trigger,
+	.pointer =	snd_usb_caiaq_pcm_pointer
+};
+	
+static void check_for_elapsed_periods(struct snd_usb_caiaqdev *dev,
+				      struct snd_pcm_substream **subs)
+{
+	int stream, pb, *cnt;
+	struct snd_pcm_substream *sub;
+
+	for (stream = 0; stream < dev->n_streams; stream++) {
+		sub = subs[stream];
+		if (!sub)
+			continue;
+
+		pb = frames_to_bytes(sub->runtime, 
+				     sub->runtime->period_size);
+		cnt = (sub->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
+					&dev->period_out_count[stream] :
+					&dev->period_in_count[stream];
+
+		if (*cnt >= pb) {
+			snd_pcm_period_elapsed(sub);
+			*cnt %= pb;
+		}
+	}
+}
+
+static void read_in_urb_mode0(struct snd_usb_caiaqdev *dev,
+			      const struct urb *urb,
+			      const struct usb_iso_packet_descriptor *iso)
+{
+	unsigned char *usb_buf = urb->transfer_buffer + iso->offset;
+	struct snd_pcm_substream *sub;
+	int stream, i;
+
+	if (all_substreams_zero(dev->sub_capture))
+		return;
+
+	spin_lock(&dev->spinlock);
+	
+	for (i = 0; i < iso->actual_length;) {
+		for (stream = 0; stream < dev->n_streams; stream++, i++) {
+			sub = dev->sub_capture[stream];
+			if (sub) {
+				struct snd_pcm_runtime *rt = sub->runtime;
+				char *audio_buf = rt->dma_area;
+				int sz = frames_to_bytes(rt, rt->buffer_size);
+				audio_buf[dev->audio_in_buf_pos[stream]++] 
+					= usb_buf[i];
+				dev->period_in_count[stream]++;
+				if (dev->audio_in_buf_pos[stream] == sz)
+					dev->audio_in_buf_pos[stream] = 0;
+			}
+		}
+	}
+	
+	spin_unlock(&dev->spinlock);
+}
+
+static void read_in_urb_mode2(struct snd_usb_caiaqdev *dev,
+			      const struct urb *urb,
+			      const struct usb_iso_packet_descriptor *iso)
+{
+	unsigned char *usb_buf = urb->transfer_buffer + iso->offset;
+	unsigned char check_byte;
+	struct snd_pcm_substream *sub;
+	int stream, i;
+
+	spin_lock(&dev->spinlock);
+	
+	for (i = 0; i < iso->actual_length;) {
+		if (i % (dev->n_streams * BYTES_PER_SAMPLE_USB) == 0) {
+			for (stream = 0; 
+			     stream < dev->n_streams; 
+			     stream++, i++) {
+				if (dev->first_packet)
+					continue;
+
+				check_byte = MAKE_CHECKBYTE(dev, stream, i);
+				
+				if ((usb_buf[i] & 0x3f) != check_byte)
+					dev->input_panic = 1;
+
+				if (usb_buf[i] & 0x80)
+					dev->output_panic = 1;
+			}
+		}
+		dev->first_packet = 0;
+
+		for (stream = 0; stream < dev->n_streams; stream++, i++) {
+			sub = dev->sub_capture[stream];
+			if (sub) {
+				struct snd_pcm_runtime *rt = sub->runtime;
+				char *audio_buf = rt->dma_area;
+				int sz = frames_to_bytes(rt, rt->buffer_size);
+				audio_buf[dev->audio_in_buf_pos[stream]++] =
+					usb_buf[i];
+				dev->period_in_count[stream]++;
+				if (dev->audio_in_buf_pos[stream] == sz)
+					dev->audio_in_buf_pos[stream] = 0;
+			}
+		}
+	}
+
+	spin_unlock(&dev->spinlock);
+}
+
+static void read_in_urb(struct snd_usb_caiaqdev *dev,
+			const struct urb *urb,
+			const struct usb_iso_packet_descriptor *iso)
+{
+	if (!dev->streaming)
+		return;
+
+	switch (dev->spec.data_alignment) {
+	case 0:
+		read_in_urb_mode0(dev, urb, iso);
+		break;
+	case 2:
+		read_in_urb_mode2(dev, urb, iso);
+		break;
+	}
+
+	if (dev->input_panic || dev->output_panic) {
+		debug("streaming error detected %s %s\n", 
+				dev->input_panic ? "(input)" : "",
+				dev->output_panic ? "(output)" : "");
+	}
+
+	check_for_elapsed_periods(dev, dev->sub_capture);
+}
+
+static void fill_out_urb(struct snd_usb_caiaqdev *dev, 
+			 struct urb *urb, 
+			 const struct usb_iso_packet_descriptor *iso)
+{
+	unsigned char *usb_buf = urb->transfer_buffer + iso->offset;
+	struct snd_pcm_substream *sub;
+	int stream, i;
+
+	spin_lock(&dev->spinlock);
+	
+	for (i = 0; i < iso->length;) {
+		for (stream = 0; stream < dev->n_streams; stream++, i++) {
+			sub = dev->sub_playback[stream];
+			if (sub) {
+				struct snd_pcm_runtime *rt = sub->runtime;
+				char *audio_buf = rt->dma_area;
+				int sz = frames_to_bytes(rt, rt->buffer_size);
+				usb_buf[i] =
+					audio_buf[dev->audio_out_buf_pos[stream]];
+				dev->period_out_count[stream]++;
+				dev->audio_out_buf_pos[stream]++;
+				if (dev->audio_out_buf_pos[stream] == sz)
+					dev->audio_out_buf_pos[stream] = 0;
+			} else
+				usb_buf[i] = 0;
+		}
+
+		/* fill in the check bytes */
+		if (dev->spec.data_alignment == 2 &&
+		    i % (dev->n_streams * BYTES_PER_SAMPLE_USB) == 
+		    	(dev->n_streams * CHANNELS_PER_STREAM))
+		    for (stream = 0; stream < dev->n_streams; stream++, i++)
+		    	usb_buf[i] = MAKE_CHECKBYTE(dev, stream, i);
+	}
+
+	spin_unlock(&dev->spinlock);
+	check_for_elapsed_periods(dev, dev->sub_playback);
+}
+
+static void read_completed(struct urb *urb)
+{
+	struct snd_usb_caiaq_cb_info *info = urb->context; 
+	struct snd_usb_caiaqdev *dev;
+	struct urb *out;
+	int frame, len, send_it = 0, outframe = 0;
+
+	if (urb->status || !info)
+		return;
+
+	dev = info->dev;
+	if (!dev->streaming)
+		return;
+
+	out = dev->data_urbs_out[info->index];
+
+	/* read the recently received packet and send back one which has
+	 * the same layout */
+	for (frame = 0; frame < FRAMES_PER_URB; frame++) {
+		if (urb->iso_frame_desc[frame].status)
+			continue;
+
+		len = urb->iso_frame_desc[outframe].actual_length;
+		out->iso_frame_desc[outframe].length = len;
+		out->iso_frame_desc[outframe].actual_length = 0;
+		out->iso_frame_desc[outframe].offset = BYTES_PER_FRAME * frame;
+		
+		if (len > 0) {
+			fill_out_urb(dev, out, &out->iso_frame_desc[outframe]);
+			read_in_urb(dev, urb, &urb->iso_frame_desc[frame]);
+			send_it = 1;
+		}
+
+		outframe++;
+	}
+
+	if (send_it) {
+		out->number_of_packets = FRAMES_PER_URB;
+		out->transfer_flags = URB_ISO_ASAP;
+		usb_submit_urb(out, GFP_ATOMIC);
+	}
+	
+	/* re-submit inbound urb */
+	for (frame = 0; frame < FRAMES_PER_URB; frame++) {
+		urb->iso_frame_desc[frame].offset = BYTES_PER_FRAME * frame;
+		urb->iso_frame_desc[frame].length = BYTES_PER_FRAME;
+		urb->iso_frame_desc[frame].actual_length = 0;
+	}
+	
+	urb->number_of_packets = FRAMES_PER_URB;
+	urb->transfer_flags = URB_ISO_ASAP;
+	usb_submit_urb(urb, GFP_ATOMIC);
+}
+
+static void write_completed(struct urb *urb)
+{
+	struct snd_usb_caiaq_cb_info *info = urb->context;
+	struct snd_usb_caiaqdev *dev = info->dev;
+
+	if (!dev->output_running) {
+		dev->output_running = 1;
+		wake_up(&dev->prepare_wait_queue);
+	}
+}
+
+static struct urb **alloc_urbs(struct snd_usb_caiaqdev *dev, int dir, int *ret)
+{
+	int i, frame;
+	struct urb **urbs;
+	struct usb_device *usb_dev = dev->chip.dev;
+	unsigned int pipe;
+
+	pipe = (dir == SNDRV_PCM_STREAM_PLAYBACK) ? 
+		usb_sndisocpipe(usb_dev, ENDPOINT_PLAYBACK) :
+		usb_rcvisocpipe(usb_dev, ENDPOINT_CAPTURE);
+
+	urbs = kmalloc(N_URBS * sizeof(*urbs), GFP_KERNEL);
+	if (!urbs) {
+		log("unable to kmalloc() urbs, OOM!?\n");
+		*ret = -ENOMEM;
+		return NULL;
+	}
+
+	for (i = 0; i < N_URBS; i++) {
+		urbs[i] = usb_alloc_urb(FRAMES_PER_URB, GFP_KERNEL);
+		if (!urbs[i]) {
+			log("unable to usb_alloc_urb(), OOM!?\n");
+			*ret = -ENOMEM;
+			return urbs;
+		}
+
+		urbs[i]->transfer_buffer = 
+			kmalloc(FRAMES_PER_URB * BYTES_PER_FRAME, GFP_KERNEL);
+		if (!urbs[i]->transfer_buffer) {
+			log("unable to kmalloc() transfer buffer, OOM!?\n");
+			*ret = -ENOMEM;
+			return urbs;
+		}
+		
+		for (frame = 0; frame < FRAMES_PER_URB; frame++) {
+			struct usb_iso_packet_descriptor *iso = 
+				&urbs[i]->iso_frame_desc[frame];
+			
+			iso->offset = BYTES_PER_FRAME * frame;
+			iso->length = BYTES_PER_FRAME;
+		}
+		
+		urbs[i]->dev = usb_dev;
+		urbs[i]->pipe = pipe;
+		urbs[i]->transfer_buffer_length = FRAMES_PER_URB 
+						* BYTES_PER_FRAME;
+		urbs[i]->context = &dev->data_cb_info[i];
+		urbs[i]->interval = 1;
+		urbs[i]->transfer_flags = URB_ISO_ASAP;
+		urbs[i]->number_of_packets = FRAMES_PER_URB;
+		urbs[i]->complete = (dir == SNDRV_PCM_STREAM_CAPTURE) ?
+					read_completed : write_completed;
+	}
+
+	*ret = 0;
+	return urbs;
+}
+
+static void free_urbs(struct urb **urbs)
+{
+	int i;
+
+	if (!urbs)
+		return;
+
+	for (i = 0; i < N_URBS; i++) {
+		if (!urbs[i])
+			continue;
+		
+		usb_kill_urb(urbs[i]);
+		kfree(urbs[i]->transfer_buffer);
+		usb_free_urb(urbs[i]);
+	}
+
+	kfree(urbs);
+}
+
+int __devinit snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *dev)
+{
+	int i, ret;
+
+	dev->n_audio_in  = max(dev->spec.num_analog_audio_in, 
+			       dev->spec.num_digital_audio_in) / 
+				CHANNELS_PER_STREAM;
+	dev->n_audio_out = max(dev->spec.num_analog_audio_out,
+			       dev->spec.num_digital_audio_out) / 
+				CHANNELS_PER_STREAM;
+	dev->n_streams = max(dev->n_audio_in, dev->n_audio_out);
+
+	debug("dev->n_audio_in = %d\n", dev->n_audio_in);
+	debug("dev->n_audio_out = %d\n", dev->n_audio_out);
+	debug("dev->n_streams = %d\n", dev->n_streams);
+
+	if (dev->n_streams > MAX_STREAMS) {
+		log("unable to initialize device, too many streams.\n");
+		return -EINVAL;
+	}
+
+	ret = snd_pcm_new(dev->chip.card, dev->product_name, 0, 
+			dev->n_audio_out, dev->n_audio_in, &dev->pcm);
+
+	if (ret < 0) {
+		log("snd_pcm_new() returned %d\n", ret);
+		return ret;
+	}
+
+	dev->pcm->private_data = dev;
+	strcpy(dev->pcm->name, dev->product_name);
+
+	memset(dev->sub_playback, 0, sizeof(dev->sub_playback));
+	memset(dev->sub_capture, 0, sizeof(dev->sub_capture));
+	
+	memcpy(&dev->pcm_info, &snd_usb_caiaq_pcm_hardware,
+			sizeof(snd_usb_caiaq_pcm_hardware));
+
+	/* setup samplerates */
+	dev->samplerates = dev->pcm_info.rates;
+	switch (dev->chip.usb_id) {
+	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1):
+		dev->samplerates |= SNDRV_PCM_RATE_88200;
+		dev->samplerates |= SNDRV_PCM_RATE_192000;
+		break;
+	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ):
+		dev->samplerates |= SNDRV_PCM_RATE_88200;
+		break;
+	}
+
+	snd_pcm_set_ops(dev->pcm, SNDRV_PCM_STREAM_PLAYBACK, 
+				&snd_usb_caiaq_ops);
+	snd_pcm_set_ops(dev->pcm, SNDRV_PCM_STREAM_CAPTURE, 
+				&snd_usb_caiaq_ops);
+
+	snd_pcm_lib_preallocate_pages_for_all(dev->pcm,
+					SNDRV_DMA_TYPE_CONTINUOUS,
+					snd_dma_continuous_data(GFP_KERNEL),
+					MAX_BUFFER_SIZE, MAX_BUFFER_SIZE);
+
+	dev->data_cb_info =
+		kmalloc(sizeof(struct snd_usb_caiaq_cb_info) * N_URBS, 
+					GFP_KERNEL);
+
+	if (!dev->data_cb_info)
+		return -ENOMEM;
+
+	for (i = 0; i < N_URBS; i++) {
+		dev->data_cb_info[i].dev = dev;
+		dev->data_cb_info[i].index = i;
+	}
+	
+	dev->data_urbs_in = alloc_urbs(dev, SNDRV_PCM_STREAM_CAPTURE, &ret);
+	if (ret < 0) {
+		kfree(dev->data_cb_info);
+		free_urbs(dev->data_urbs_in);
+		return ret;
+	}
+	
+	dev->data_urbs_out = alloc_urbs(dev, SNDRV_PCM_STREAM_PLAYBACK, &ret);
+	if (ret < 0) {
+		kfree(dev->data_cb_info);
+		free_urbs(dev->data_urbs_in);
+		free_urbs(dev->data_urbs_out);
+		return ret;
+	}
+
+	return 0;
+}
+
+void snd_usb_caiaq_audio_free(struct snd_usb_caiaqdev *dev)
+{
+	debug("snd_usb_caiaq_audio_free (%p)\n", dev);
+	stream_stop(dev);
+	free_urbs(dev->data_urbs_in);
+	free_urbs(dev->data_urbs_out);
+	kfree(dev->data_cb_info);
+}
+
diff --git a/sound/usb/caiaq/caiaq-audio.h b/sound/usb/caiaq/caiaq-audio.h
new file mode 100644
index 000000000000..8ab1f8d9529e
--- /dev/null
+++ b/sound/usb/caiaq/caiaq-audio.h
@@ -0,0 +1,7 @@
+#ifndef CAIAQ_AUDIO_H
+#define CAIAQ_AUDIO_H
+
+int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *dev);
+void snd_usb_caiaq_audio_free(struct snd_usb_caiaqdev *dev);
+
+#endif /* CAIAQ_AUDIO_H */
diff --git a/sound/usb/caiaq/caiaq-device.c b/sound/usb/caiaq/caiaq-device.c
new file mode 100644
index 000000000000..4709347326f9
--- /dev/null
+++ b/sound/usb/caiaq/caiaq-device.c
@@ -0,0 +1,436 @@
+/*
+ * caiaq.c: ALSA driver for caiaq/NativeInstruments devices
+ *
+ *   Copyright (c) 2007 Daniel Mack <daniel@caiaq.de>
+ *                      Karsten Wiese <fzu@wemgehoertderstaat.de>
+ *
+ *   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 <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/interrupt.h>
+#include <linux/usb.h>
+#include <linux/input.h>
+#include <linux/spinlock.h>
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/pcm.h>
+#include <sound/rawmidi.h>
+
+#include "caiaq-device.h"
+#include "caiaq-audio.h"
+#include "caiaq-midi.h"
+
+#ifdef CONFIG_SND_USB_CAIAQ_INPUT
+#include "caiaq-input.h"
+#endif
+
+MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
+MODULE_DESCRIPTION("caiaq USB audio, version 1.1.0");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2},"
+			 "{Native Instruments, Kore Controller},"
+			 "{Native Instruments, Audio Kontrol 1}"
+			 "{Native Instruments, Audio 8 DJ}}");
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */
+static char* id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for this card */
+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
+static int snd_card_used[SNDRV_CARDS];
+
+module_param_array(index, int, NULL, 0444);
+MODULE_PARM_DESC(index, "Index value for the caiaq sound device");
+module_param_array(id, charp, NULL, 0444);
+MODULE_PARM_DESC(id, "ID string for the caiaq soundcard.");
+module_param_array(enable, bool, NULL, 0444);
+MODULE_PARM_DESC(enable, "Enable the caiaq soundcard.");
+
+enum {
+	SAMPLERATE_44100	= 0,
+	SAMPLERATE_48000	= 1,
+	SAMPLERATE_96000	= 2,
+	SAMPLERATE_192000	= 3,
+	SAMPLERATE_88200	= 4,
+	SAMPLERATE_INVALID	= 0xff
+};
+
+enum {
+	DEPTH_NONE	= 0,
+	DEPTH_16	= 1,
+	DEPTH_24	= 2,
+	DEPTH_32	= 3
+};
+
+static struct usb_device_id snd_usb_id_table[] = {
+	{
+		.match_flags =	USB_DEVICE_ID_MATCH_DEVICE,
+		.idVendor =	USB_VID_NATIVEINSTRUMENTS,
+		.idProduct =	USB_PID_RIGKONTROL2 
+	},
+	{
+		.match_flags =	USB_DEVICE_ID_MATCH_DEVICE,
+		.idVendor =	USB_VID_NATIVEINSTRUMENTS,
+		.idProduct =	USB_PID_KORECONTROLLER
+	},
+	{
+		.match_flags =  USB_DEVICE_ID_MATCH_DEVICE,
+		.idVendor =     USB_VID_NATIVEINSTRUMENTS,
+		.idProduct =    USB_PID_AK1
+	},
+	{
+		.match_flags =  USB_DEVICE_ID_MATCH_DEVICE,
+		.idVendor =     USB_VID_NATIVEINSTRUMENTS,
+		.idProduct =    USB_PID_AUDIO8DJ
+	},
+	{ /* terminator */ }
+};
+
+static void usb_ep1_command_reply_dispatch (struct urb* urb)
+{
+	int ret;
+	struct snd_usb_caiaqdev *dev = urb->context;
+	unsigned char *buf = urb->transfer_buffer;
+
+	if (urb->status || !dev) {
+		log("received EP1 urb->status = %i\n", urb->status);
+		return;
+	}
+
+	switch(buf[0]) {
+	case EP1_CMD_GET_DEVICE_INFO:
+	 	memcpy(&dev->spec, buf+1, sizeof(struct caiaq_device_spec));
+		dev->spec.fw_version = le16_to_cpu(dev->spec.fw_version);
+		debug("device spec (firmware %d): audio: %d in, %d out, "
+			"MIDI: %d in, %d out, data alignment %d\n",
+			dev->spec.fw_version,
+			dev->spec.num_analog_audio_in,
+			dev->spec.num_analog_audio_out,
+			dev->spec.num_midi_in,
+			dev->spec.num_midi_out,
+			dev->spec.data_alignment);
+
+		dev->spec_received++;
+		wake_up(&dev->ep1_wait_queue);
+		break;
+	case EP1_CMD_AUDIO_PARAMS:
+		dev->audio_parm_answer = buf[1];
+		wake_up(&dev->ep1_wait_queue);
+		break;
+	case EP1_CMD_MIDI_READ:
+		snd_usb_caiaq_midi_handle_input(dev, buf[1], buf + 3, buf[2]);
+		break;
+
+#ifdef CONFIG_SND_USB_CAIAQ_INPUT
+	case EP1_CMD_READ_ERP:
+	case EP1_CMD_READ_ANALOG:
+	case EP1_CMD_READ_IO:
+		snd_usb_caiaq_input_dispatch(dev, buf, urb->actual_length);
+		break;
+#endif
+	}
+
+	dev->ep1_in_urb.actual_length = 0;
+	ret = usb_submit_urb(&dev->ep1_in_urb, GFP_ATOMIC);
+	if (ret < 0)
+		log("unable to submit urb. OOM!?\n");
+}
+
+static int send_command (struct snd_usb_caiaqdev *dev,
+			 unsigned char command, 
+			 const unsigned char *buffer,
+			 int len)
+{
+	int actual_len;
+	struct usb_device *usb_dev = dev->chip.dev;
+
+	if (!usb_dev)
+		return -EIO;
+
+	if (len > EP1_BUFSIZE - 1)
+		len = EP1_BUFSIZE - 1;
+
+	if (buffer && len > 0)
+		memcpy(dev->ep1_out_buf+1, buffer, len);
+	
+	dev->ep1_out_buf[0] = command;
+	return usb_bulk_msg(usb_dev, usb_sndbulkpipe(usb_dev, 1),
+			   dev->ep1_out_buf, len+1, &actual_len, 200);
+}
+
+int snd_usb_caiaq_set_audio_params (struct snd_usb_caiaqdev *dev,
+		   		    int rate, int depth, int bpp)
+{
+	int ret;
+	char tmp[5];
+	
+	switch (rate) {
+	case 44100:	tmp[0] = SAMPLERATE_44100;   break;
+	case 48000:	tmp[0] = SAMPLERATE_48000;   break;
+	case 88200:	tmp[0] = SAMPLERATE_88200;   break;
+	case 96000:	tmp[0] = SAMPLERATE_96000;   break;
+	case 192000:	tmp[0] = SAMPLERATE_192000;  break;
+	default:	return -EINVAL;
+	}
+
+	switch (depth) {
+	case 16:	tmp[1] = DEPTH_16;   break;
+	case 24:	tmp[1] = DEPTH_24;   break;
+	default:	return -EINVAL;
+	}
+
+	tmp[2] = bpp & 0xff;
+	tmp[3] = bpp >> 8;
+	tmp[4] = 1; /* packets per microframe */
+
+	debug("setting audio params: %d Hz, %d bits, %d bpp\n",
+		rate, depth, bpp);
+
+	dev->audio_parm_answer = -1;
+	ret = send_command(dev, EP1_CMD_AUDIO_PARAMS, tmp, sizeof(tmp));
+
+	if (ret)
+		return ret;
+	
+	if (!wait_event_timeout(dev->ep1_wait_queue, 
+	    dev->audio_parm_answer >= 0, HZ))
+		return -EPIPE;
+		
+	if (dev->audio_parm_answer != 1) 
+		debug("unable to set the device's audio params\n");
+
+	return dev->audio_parm_answer == 1 ? 0 : -EINVAL;
+}
+
+int snd_usb_caiaq_set_auto_msg (struct snd_usb_caiaqdev *dev, 
+				int digital, int analog, int erp)
+{
+	char tmp[3] = { digital, analog, erp };
+	return send_command(dev, EP1_CMD_AUTO_MSG, tmp, sizeof(tmp));
+}
+
+static void setup_card(struct snd_usb_caiaqdev *dev)
+{
+	int ret;
+	char val[3];
+	
+	/* device-specific startup specials */
+	switch (dev->chip.usb_id) {
+	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL2):
+		/* RigKontrol2 - display centered dash ('-') */
+		val[0] = 0x00;
+		val[1] = 0x00;
+		val[2] = 0x01;
+		send_command(dev, EP1_CMD_WRITE_IO, val, 3);
+		break;
+	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1):
+		/* Audio Kontrol 1 - make USB-LED stop blinking */
+		val[0] = 0x00;
+		send_command(dev, EP1_CMD_WRITE_IO, val, 1);
+		break;
+	}
+	
+	ret = snd_usb_caiaq_audio_init(dev);
+	if (ret < 0)
+		log("Unable to set up audio system (ret=%d)\n", ret);
+	
+	ret = snd_usb_caiaq_midi_init(dev);
+	if (ret < 0)
+		log("Unable to set up MIDI system (ret=%d)\n", ret);
+
+#ifdef CONFIG_SND_USB_CAIAQ_INPUT
+	ret = snd_usb_caiaq_input_init(dev);
+	if (ret < 0)
+		log("Unable to set up input system (ret=%d)\n", ret);
+#endif
+
+	/* finally, register the card and all its sub-instances */
+	ret = snd_card_register(dev->chip.card);
+	if (ret < 0) {
+		log("snd_card_register() returned %d\n", ret);
+		snd_card_free(dev->chip.card);
+	}
+}
+
+static struct snd_card* create_card(struct usb_device* usb_dev)
+{
+	int devnum;
+	struct snd_card *card;
+	struct snd_usb_caiaqdev *dev;
+
+	for (devnum = 0; devnum < SNDRV_CARDS; devnum++)
+		if (enable[devnum] && !snd_card_used[devnum])
+			break;
+
+	if (devnum >= SNDRV_CARDS)
+		return NULL;
+
+	card = snd_card_new(index[devnum], id[devnum], THIS_MODULE, 
+					sizeof(struct snd_usb_caiaqdev));
+	if (!card)
+		return NULL;
+
+	dev = caiaqdev(card);
+	dev->chip.dev = usb_dev;
+	dev->chip.card = card;
+	dev->chip.usb_id = USB_ID(usb_dev->descriptor.idVendor,
+					usb_dev->descriptor.idProduct);
+	spin_lock_init(&dev->spinlock);
+	snd_card_set_dev(card, &usb_dev->dev);
+
+	return card;
+}
+
+static int init_card(struct snd_usb_caiaqdev *dev)
+{
+	char *c;
+	struct usb_device *usb_dev = dev->chip.dev;
+	struct snd_card *card = dev->chip.card;
+	int err, len;
+	
+	if (usb_set_interface(usb_dev, 0, 1) != 0) {
+		log("can't set alt interface.\n");
+		return -EIO;
+	}
+
+	usb_init_urb(&dev->ep1_in_urb);
+	usb_init_urb(&dev->midi_out_urb);
+
+	usb_fill_bulk_urb(&dev->ep1_in_urb, usb_dev, 
+			  usb_rcvbulkpipe(usb_dev, 0x1),
+			  dev->ep1_in_buf, EP1_BUFSIZE, 
+			  usb_ep1_command_reply_dispatch, dev);
+
+	usb_fill_bulk_urb(&dev->midi_out_urb, usb_dev, 
+			  usb_sndbulkpipe(usb_dev, 0x1),
+			  dev->midi_out_buf, EP1_BUFSIZE, 
+			  snd_usb_caiaq_midi_output_done, dev);
+	
+	init_waitqueue_head(&dev->ep1_wait_queue);
+	init_waitqueue_head(&dev->prepare_wait_queue);
+	
+	if (usb_submit_urb(&dev->ep1_in_urb, GFP_KERNEL) != 0)
+		return -EIO;
+
+	err = send_command(dev, EP1_CMD_GET_DEVICE_INFO, NULL, 0);
+	if (err)
+		return err;
+
+	if (!wait_event_timeout(dev->ep1_wait_queue, dev->spec_received, HZ))
+		return -ENODEV;
+
+	usb_string(usb_dev, usb_dev->descriptor.iManufacturer,
+		   dev->vendor_name, CAIAQ_USB_STR_LEN);
+	
+	usb_string(usb_dev, usb_dev->descriptor.iProduct,
+		   dev->product_name, CAIAQ_USB_STR_LEN);
+	
+	usb_string(usb_dev, usb_dev->descriptor.iSerialNumber,
+		   dev->serial, CAIAQ_USB_STR_LEN);
+
+	/* terminate serial string at first white space occurence */
+	c = strchr(dev->serial, ' ');
+	if (c)
+		*c = '\0';
+	
+	strcpy(card->driver, MODNAME);
+	strcpy(card->shortname, dev->product_name);
+
+	len = snprintf(card->longname, sizeof(card->longname),
+		       "%s %s (serial %s, ",
+		       dev->vendor_name, dev->product_name, dev->serial);
+
+	if (len < sizeof(card->longname) - 2)
+		len += usb_make_path(usb_dev, card->longname + len,
+				     sizeof(card->longname) - len);
+
+	card->longname[len++] = ')';
+	card->longname[len] = '\0';
+	setup_card(dev);
+	return 0;
+}
+
+static int snd_probe(struct usb_interface *intf, 
+		     const struct usb_device_id *id)
+{
+	int ret;
+	struct snd_card *card;
+	struct usb_device *device = interface_to_usbdev(intf);
+	
+	card = create_card(device);
+	
+	if (!card)
+		return -ENOMEM;
+			
+	dev_set_drvdata(&intf->dev, card);
+	ret = init_card(caiaqdev(card));
+	if (ret < 0) {
+		log("unable to init card! (ret=%d)\n", ret);
+		snd_card_free(card);
+		return ret;
+	}
+	
+	return 0;
+}
+
+static void snd_disconnect(struct usb_interface *intf)
+{
+	struct snd_usb_caiaqdev *dev;
+	struct snd_card *card = dev_get_drvdata(&intf->dev);
+
+	debug("snd_disconnect(%p)\n", intf);
+
+	if (!card)
+		return;
+
+	dev = caiaqdev(card);
+	snd_card_disconnect(card);
+
+#ifdef CONFIG_SND_USB_CAIAQ_INPUT
+	snd_usb_caiaq_input_free(dev);
+#endif
+	snd_usb_caiaq_audio_free(dev);
+	
+	usb_kill_urb(&dev->ep1_in_urb);
+	usb_kill_urb(&dev->midi_out_urb);
+	
+	snd_card_free(card);
+	usb_reset_device(interface_to_usbdev(intf));
+}
+
+
+MODULE_DEVICE_TABLE(usb, snd_usb_id_table);
+static struct usb_driver snd_usb_driver = {
+	.name 		= MODNAME,
+	.probe 		= snd_probe,
+	.disconnect	= snd_disconnect,
+	.id_table 	= snd_usb_id_table,
+};
+
+static int __init snd_module_init(void)
+{
+	return usb_register(&snd_usb_driver);
+}
+
+static void __exit snd_module_exit(void)
+{
+	usb_deregister(&snd_usb_driver);
+}
+
+module_init(snd_module_init)
+module_exit(snd_module_exit)
+
diff --git a/sound/usb/caiaq/caiaq-device.h b/sound/usb/caiaq/caiaq-device.h
new file mode 100644
index 000000000000..088d5ec241f3
--- /dev/null
+++ b/sound/usb/caiaq/caiaq-device.h
@@ -0,0 +1,116 @@
+#ifndef CAIAQ_DEVICE_H
+#define CAIAQ_DEVICE_H
+
+#include "../usbaudio.h"
+
+#define USB_VID_NATIVEINSTRUMENTS 0x17cc
+
+#define USB_PID_RIGKONTROL2	0x1969
+#define USB_PID_KORECONTROLLER 	0x4711
+#define USB_PID_AK1		0x0815
+#define USB_PID_AUDIO8DJ	0x1978
+
+#define EP1_BUFSIZE 64
+#define CAIAQ_USB_STR_LEN 0xff
+#define MAX_STREAMS 32
+
+//#define	SND_USB_CAIAQ_DEBUG
+
+#define MODNAME "snd-usb-caiaq"
+#define log(x...) snd_printk(KERN_WARNING MODNAME" log: " x)
+
+#ifdef SND_USB_CAIAQ_DEBUG
+#define debug(x...) snd_printk(KERN_WARNING MODNAME " debug: " x)
+#else
+#define debug(x...) do { } while(0)
+#endif
+
+#define EP1_CMD_GET_DEVICE_INFO	0x1
+#define EP1_CMD_READ_ERP	0x2
+#define EP1_CMD_READ_ANALOG	0x3
+#define EP1_CMD_READ_IO		0x4
+#define EP1_CMD_WRITE_IO	0x5
+#define EP1_CMD_MIDI_READ	0x6
+#define EP1_CMD_MIDI_WRITE	0x7
+#define EP1_CMD_AUDIO_PARAMS	0x9
+#define EP1_CMD_AUTO_MSG	0xb
+
+struct caiaq_device_spec {
+	unsigned short fw_version;
+	unsigned char hw_subtype;
+	unsigned char num_erp;
+	unsigned char num_analog_in;
+	unsigned char num_digital_in;
+	unsigned char num_digital_out;
+	unsigned char num_analog_audio_out;
+	unsigned char num_analog_audio_in;
+	unsigned char num_digital_audio_out;
+	unsigned char num_digital_audio_in;
+	unsigned char num_midi_out;
+	unsigned char num_midi_in;
+	unsigned char data_alignment;
+} __attribute__ ((packed));
+
+struct snd_usb_caiaq_cb_info;
+
+struct snd_usb_caiaqdev {
+	struct snd_usb_audio chip;
+
+	struct urb ep1_in_urb;
+	struct urb midi_out_urb;
+	struct urb **data_urbs_in;
+	struct urb **data_urbs_out;
+	struct snd_usb_caiaq_cb_info *data_cb_info;
+	
+	unsigned char ep1_in_buf[EP1_BUFSIZE];
+	unsigned char ep1_out_buf[EP1_BUFSIZE];
+	unsigned char midi_out_buf[EP1_BUFSIZE];
+
+	struct caiaq_device_spec spec;
+	spinlock_t spinlock;
+	wait_queue_head_t ep1_wait_queue;
+	wait_queue_head_t prepare_wait_queue;
+	int spec_received, audio_parm_answer;
+	
+	char vendor_name[CAIAQ_USB_STR_LEN];
+	char product_name[CAIAQ_USB_STR_LEN];
+	char serial[CAIAQ_USB_STR_LEN];
+
+	int n_streams, n_audio_in, n_audio_out;
+	int streaming, first_packet, output_running;
+	int audio_in_buf_pos[MAX_STREAMS];
+	int audio_out_buf_pos[MAX_STREAMS];
+	int period_in_count[MAX_STREAMS];
+	int period_out_count[MAX_STREAMS];
+	int input_panic, output_panic;
+	char *audio_in_buf, *audio_out_buf;
+	unsigned int samplerates;
+
+	struct snd_pcm_substream *sub_playback[MAX_STREAMS];
+	struct snd_pcm_substream *sub_capture[MAX_STREAMS];
+
+	/* Linux input */
+#ifdef CONFIG_SND_USB_CAIAQ_INPUT
+	struct input_dev *input_dev;
+#endif
+	
+	/* ALSA */
+	struct snd_pcm *pcm;
+	struct snd_pcm_hardware pcm_info;
+	struct snd_rawmidi *rmidi;
+	struct snd_rawmidi_substream *midi_receive_substream;
+	struct snd_rawmidi_substream *midi_out_substream;
+};
+
+struct snd_usb_caiaq_cb_info {
+	struct snd_usb_caiaqdev *dev;
+	int index;
+};
+
+#define caiaqdev(c) ((struct snd_usb_caiaqdev*)(c)->private_data)
+
+int snd_usb_caiaq_set_audio_params (struct snd_usb_caiaqdev *dev, int rate, int depth, int bbp);
+int snd_usb_caiaq_set_auto_msg (struct snd_usb_caiaqdev *dev, int digital, int analog, int erp);
+
+
+#endif /* CAIAQ_DEVICE_H */
diff --git a/sound/usb/caiaq/caiaq-input.c b/sound/usb/caiaq/caiaq-input.c
new file mode 100644
index 000000000000..3acd12db6952
--- /dev/null
+++ b/sound/usb/caiaq/caiaq-input.c
@@ -0,0 +1,246 @@
+/*
+ *   Copyright (c) 2006,2007 Daniel Mack, Tim Ruetz
+ *
+ *   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 <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/input.h>
+#include <linux/usb.h>
+#include <linux/spinlock.h>
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/rawmidi.h>
+#include <sound/pcm.h>
+#include "caiaq-device.h"
+#include "caiaq-input.h"
+
+#ifdef CONFIG_SND_USB_CAIAQ_INPUT
+
+static unsigned char keycode_ak1[] =  { KEY_C, KEY_B, KEY_A };
+static unsigned char keycode_rk2[] =  { KEY_1, KEY_2, KEY_3, KEY_4, 
+					KEY_5, KEY_6, KEY_7 };
+
+#define DEG90  (range/2)
+#define DEG180 (range)
+#define DEG270 (DEG90 + DEG180)
+#define DEG360 (DEG180 * 2)
+#define HIGH_PEAK (268)
+#define LOW_PEAK (-7)
+
+/* some of these devices have endless rotation potentiometers
+ * built in which use two tapers, 90 degrees phase shifted.
+ * this algorithm decodes them to one single value, ranging
+ * from 0 to 999 */
+static unsigned int decode_erp(unsigned char a, unsigned char b)
+{
+	int weight_a, weight_b;
+	int pos_a, pos_b;
+	int ret;
+	int range = HIGH_PEAK - LOW_PEAK;
+	int mid_value = (HIGH_PEAK + LOW_PEAK) / 2;
+
+	weight_b = abs(mid_value-a) - (range/2 - 100)/2;
+	
+	if (weight_b < 0)
+		weight_b = 0;
+
+	if (weight_b > 100)
+		weight_b = 100;
+
+	weight_a = 100 - weight_b;
+
+	if (a < mid_value) {
+		/* 0..90 and 270..360 degrees */
+		pos_b = b - LOW_PEAK + DEG270;
+		if (pos_b >= DEG360)
+			pos_b -= DEG360;
+	} else
+		/* 90..270 degrees */
+		pos_b = HIGH_PEAK - b + DEG90;
+
+
+	if (b > mid_value)
+		/* 0..180 degrees */
+		pos_a = a - LOW_PEAK;
+	else
+		/* 180..360 degrees */
+		pos_a = HIGH_PEAK - a + DEG180;
+
+	/* interpolate both slider values, depending on weight factors */
+	/* 0..99 x DEG360 */
+	ret = pos_a * weight_a + pos_b * weight_b;
+
+	/* normalize to 0..999 */
+	ret *= 10;
+	ret /= DEG360;
+
+	if (ret < 0)
+		ret += 1000;
+	
+	if (ret >= 1000)
+		ret -= 1000;
+
+	return ret;
+}
+
+#undef DEG90
+#undef DEG180
+#undef DEG270
+#undef DEG360
+#undef HIGH_PEAK
+#undef LOW_PEAK
+
+
+static void snd_caiaq_input_read_analog(struct snd_usb_caiaqdev *dev, 
+					const char *buf, unsigned int len)
+{
+	switch(dev->input_dev->id.product) {
+	case USB_PID_RIGKONTROL2:
+		input_report_abs(dev->input_dev, ABS_X, (buf[4] << 8) |buf[5]);
+		input_report_abs(dev->input_dev, ABS_Y, (buf[0] << 8) |buf[1]);
+		input_report_abs(dev->input_dev, ABS_Z, (buf[2] << 8) |buf[3]);
+		input_sync(dev->input_dev);
+		break;
+	}
+}
+
+static void snd_caiaq_input_read_erp(struct snd_usb_caiaqdev *dev, 
+				     const char *buf, unsigned int len)
+{
+	int i;
+
+	switch(dev->input_dev->id.product) {
+	case USB_PID_AK1:
+		i = decode_erp(buf[0], buf[1]);
+		input_report_abs(dev->input_dev, ABS_X, i);
+		input_sync(dev->input_dev);	
+		break;
+	}
+}
+
+static void snd_caiaq_input_read_io(struct snd_usb_caiaqdev *dev, 
+				    char *buf, unsigned int len)
+{
+	int i;
+	unsigned char *keycode = dev->input_dev->keycode;
+
+	if (!keycode)
+		return;
+
+	if (dev->input_dev->id.product == USB_PID_RIGKONTROL2)
+		for (i=0; i<len; i++)
+			buf[i] = ~buf[i];
+
+	for (i=0; (i<dev->input_dev->keycodemax) && (i < len); i++)
+		input_report_key(dev->input_dev, keycode[i], 
+					buf[i/8] & (1 << (i%8)));
+
+	input_sync(dev->input_dev);
+}
+
+void snd_usb_caiaq_input_dispatch(struct snd_usb_caiaqdev *dev, 
+				  char *buf, 
+				  unsigned int len)
+{
+	if (!dev->input_dev || (len < 1))
+		return;
+
+	switch (buf[0]) {
+	case EP1_CMD_READ_ANALOG:
+		snd_caiaq_input_read_analog(dev, buf+1, len-1);
+		break;
+	case EP1_CMD_READ_ERP:
+		snd_caiaq_input_read_erp(dev, buf+1, len-1);
+		break;
+	case EP1_CMD_READ_IO:
+		snd_caiaq_input_read_io(dev, buf+1, len-1);
+		break;
+	}
+}
+
+int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *dev)
+{
+	struct usb_device *usb_dev = dev->chip.dev;
+	struct input_dev *input;
+	int i, ret;
+
+	input = input_allocate_device();
+	if (!input)
+		return -ENOMEM;
+
+	input->name = dev->product_name;
+	input->id.bustype = BUS_USB;
+	input->id.vendor  = usb_dev->descriptor.idVendor;
+	input->id.product = usb_dev->descriptor.idProduct;
+	input->id.version = usb_dev->descriptor.bcdDevice;
+
+        switch (dev->chip.usb_id) {
+	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL2):
+		input->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+		input->absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_Z);
+		input->keycode = keycode_rk2;
+		input->keycodesize = sizeof(char);
+		input->keycodemax = ARRAY_SIZE(keycode_rk2);
+		for (i=0; i<ARRAY_SIZE(keycode_rk2); i++)
+			set_bit(keycode_rk2[i], input->keybit);
+
+		input_set_abs_params(input, ABS_X, 0, 4096, 0, 10);
+		input_set_abs_params(input, ABS_Y, 0, 4096, 0, 10);
+		input_set_abs_params(input, ABS_Z, 0, 4096, 0, 10);
+		snd_usb_caiaq_set_auto_msg(dev, 1, 10, 0);
+		break;
+	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1):
+		input->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+		input->absbit[0] = BIT(ABS_X);
+		input->keycode = keycode_ak1;
+		input->keycodesize = sizeof(char);
+		input->keycodemax = ARRAY_SIZE(keycode_ak1);
+		for (i=0; i<ARRAY_SIZE(keycode_ak1); i++)
+			set_bit(keycode_ak1[i], input->keybit);
+
+		input_set_abs_params(input, ABS_X, 0, 999, 0, 10);
+		snd_usb_caiaq_set_auto_msg(dev, 1, 0, 5);
+		break;
+	default:
+		/* no input methods supported on this device */
+		input_free_device(input);
+		return 0;
+	}
+
+	ret = input_register_device(input);
+	if (ret < 0) {
+		input_free_device(input);
+		return ret;
+	}
+
+	dev->input_dev = input;
+	return 0;
+}
+
+void snd_usb_caiaq_input_free(struct snd_usb_caiaqdev *dev)
+{
+	if (!dev || !dev->input_dev)
+		return;
+
+	input_unregister_device(dev->input_dev);
+	input_free_device(dev->input_dev);
+	dev->input_dev = NULL;
+}
+
+#endif /* CONFIG_SND_USB_CAIAQ_INPUT */
+
diff --git a/sound/usb/caiaq/caiaq-input.h b/sound/usb/caiaq/caiaq-input.h
new file mode 100644
index 000000000000..ced535577864
--- /dev/null
+++ b/sound/usb/caiaq/caiaq-input.h
@@ -0,0 +1,8 @@
+#ifndef CAIAQ_INPUT_H
+#define CAIAQ_INPUT_H
+
+void snd_usb_caiaq_input_dispatch(struct snd_usb_caiaqdev *dev, char *buf, unsigned int len);
+int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *dev);
+void snd_usb_caiaq_input_free(struct snd_usb_caiaqdev *dev);
+
+#endif
diff --git a/sound/usb/caiaq/caiaq-midi.c b/sound/usb/caiaq/caiaq-midi.c
new file mode 100644
index 000000000000..793ca20ce349
--- /dev/null
+++ b/sound/usb/caiaq/caiaq-midi.c
@@ -0,0 +1,177 @@
+/*
+ *   Copyright (c) 2006,2007 Daniel Mack
+ *
+ *   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 <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/interrupt.h>
+#include <linux/usb.h>
+#include <linux/input.h>
+#include <linux/spinlock.h>
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/rawmidi.h>
+#include <sound/pcm.h>
+
+#include "caiaq-device.h"
+#include "caiaq-midi.h"
+
+
+static int snd_usb_caiaq_midi_input_open(struct snd_rawmidi_substream *substream)
+{
+	return 0;
+}
+
+static int snd_usb_caiaq_midi_input_close(struct snd_rawmidi_substream *substream)
+{
+	return 0;
+}
+
+static void snd_usb_caiaq_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
+{
+	struct snd_usb_caiaqdev *dev = substream->rmidi->private_data;
+
+	if (!dev)
+		return;
+	
+	dev->midi_receive_substream = up ? substream : NULL;
+}
+
+
+static int snd_usb_caiaq_midi_output_open(struct snd_rawmidi_substream *substream)
+{
+	return 0;
+}
+
+static int snd_usb_caiaq_midi_output_close(struct snd_rawmidi_substream *substream)
+{
+	return 0;
+}
+
+static void snd_usb_caiaq_midi_send(struct snd_usb_caiaqdev *dev,
+				    struct snd_rawmidi_substream *substream)
+{
+	int len, ret;
+	
+	dev->midi_out_buf[0] = EP1_CMD_MIDI_WRITE;
+	dev->midi_out_buf[1] = 0; /* port */
+	len = snd_rawmidi_transmit_peek(substream, dev->midi_out_buf+3, EP1_BUFSIZE-3);
+	
+	if (len <= 0)
+		return;
+	
+	dev->midi_out_buf[2] = len;
+	dev->midi_out_urb.transfer_buffer_length = len+3;
+	
+	ret = usb_submit_urb(&dev->midi_out_urb, GFP_ATOMIC);
+	if (ret < 0)
+		log("snd_usb_caiaq_midi_send(%p): usb_submit_urb() failed, %d\n",
+				substream, ret);
+}
+
+static void snd_usb_caiaq_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
+{
+	struct snd_usb_caiaqdev *dev = substream->rmidi->private_data;
+	
+	if (dev->midi_out_substream != NULL)
+		return;
+	
+	if (!up) {
+		dev->midi_out_substream = NULL;
+		return;
+	}
+	
+	dev->midi_out_substream = substream;
+	snd_usb_caiaq_midi_send(dev, substream);
+}
+
+
+static struct snd_rawmidi_ops snd_usb_caiaq_midi_output =
+{
+	.open =		snd_usb_caiaq_midi_output_open,
+	.close =	snd_usb_caiaq_midi_output_close,
+	.trigger =      snd_usb_caiaq_midi_output_trigger,
+};
+
+static struct snd_rawmidi_ops snd_usb_caiaq_midi_input =
+{
+	.open =		snd_usb_caiaq_midi_input_open,
+	.close =	snd_usb_caiaq_midi_input_close,
+	.trigger =      snd_usb_caiaq_midi_input_trigger,
+};
+
+void snd_usb_caiaq_midi_handle_input(struct snd_usb_caiaqdev *dev, 
+				     int port, const char *buf, int len)
+{
+	if (!dev->midi_receive_substream)
+		return;
+	
+	snd_rawmidi_receive(dev->midi_receive_substream, buf, len);
+}
+
+int __devinit snd_usb_caiaq_midi_init(struct snd_usb_caiaqdev *device)
+{
+	int ret;
+	struct snd_rawmidi *rmidi;
+
+	ret = snd_rawmidi_new(device->chip.card, device->product_name, 0,
+					device->spec.num_midi_out,
+					device->spec.num_midi_in,
+					&rmidi);
+
+	if (ret < 0)
+		return ret;
+
+	strcpy(rmidi->name, device->product_name);
+
+	rmidi->info_flags = SNDRV_RAWMIDI_INFO_DUPLEX;
+	rmidi->private_data = device;
+
+	if (device->spec.num_midi_out > 0) {
+		rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;
+		snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, 
+				    &snd_usb_caiaq_midi_output);
+	}
+
+	if (device->spec.num_midi_in > 0) {
+		rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
+		snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, 
+				    &snd_usb_caiaq_midi_input);
+	}
+	
+	device->rmidi = rmidi;
+
+	return 0;
+}
+
+void snd_usb_caiaq_midi_output_done(struct urb* urb)
+{
+	struct snd_usb_caiaqdev *dev = urb->context;
+      	char *buf = urb->transfer_buffer;
+	
+	if (urb->status != 0)
+		return;
+
+	if (!dev->midi_out_substream)
+		return;
+
+	snd_rawmidi_transmit_ack(dev->midi_out_substream, buf[2]);
+	dev->midi_out_substream = NULL;
+	snd_usb_caiaq_midi_send(dev, dev->midi_out_substream);
+}
+
diff --git a/sound/usb/caiaq/caiaq-midi.h b/sound/usb/caiaq/caiaq-midi.h
new file mode 100644
index 000000000000..9d16db027fc3
--- /dev/null
+++ b/sound/usb/caiaq/caiaq-midi.h
@@ -0,0 +1,8 @@
+#ifndef CAIAQ_MIDI_H
+#define CAIAQ_MIDI_H
+
+int snd_usb_caiaq_midi_init(struct snd_usb_caiaqdev *dev);
+void snd_usb_caiaq_midi_handle_input(struct snd_usb_caiaqdev *dev, int port, const char *buf, int len);
+void snd_usb_caiaq_midi_output_done(struct urb* urb);
+
+#endif /* CAIAQ_MIDI_H */
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index b6d886373bb0..8ebc1adb5ed9 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -1878,6 +1878,9 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
 	}
 
 	/* set the period time minimum 1ms */
+	/* FIXME: high-speed mode allows 125us minimum period, but many parts
+	 * in the current code assume the 1ms period.
+	 */
 	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME,
 				     1000 * MIN_PACKS_URB,
 				     /*(nrpacks * MAX_URBS) * 1000*/ UINT_MAX);
diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c
index 24f5a26c5f0c..99295f9b7691 100644
--- a/sound/usb/usbmidi.c
+++ b/sound/usb/usbmidi.c
@@ -1,7 +1,7 @@
 /*
  * usbmidi.c - ALSA USB MIDI driver
  *
- * Copyright (c) 2002-2005 Clemens Ladisch
+ * Copyright (c) 2002-2007 Clemens Ladisch
  * All rights reserved.
  *
  * Based on the OSS usb-midi driver by NAGANO Daisuke,
@@ -145,6 +145,7 @@ struct snd_usb_midi_in_endpoint {
 	struct urb* urb;
 	struct usbmidi_in_port {
 		struct snd_rawmidi_substream *substream;
+		u8 running_status_length;
 	} ports[0x10];
 	u8 seen_f5;
 	u8 error_resubmit;
@@ -366,6 +367,46 @@ static void snd_usbmidi_midiman_input(struct snd_usb_midi_in_endpoint* ep,
 }
 
 /*
+ * Buggy M-Audio device: running status on input results in a packet that has
+ * the data bytes but not the status byte and that is marked with CIN 4.
+ */
+static void snd_usbmidi_maudio_broken_running_status_input(
+					struct snd_usb_midi_in_endpoint* ep,
+					uint8_t* buffer, int buffer_length)
+{
+	int i;
+
+	for (i = 0; i + 3 < buffer_length; i += 4)
+		if (buffer[i] != 0) {
+			int cable = buffer[i] >> 4;
+			u8 cin = buffer[i] & 0x0f;
+			struct usbmidi_in_port *port = &ep->ports[cable];
+			int length;
+			
+			length = snd_usbmidi_cin_length[cin];
+			if (cin == 0xf && buffer[i + 1] >= 0xf8)
+				; /* realtime msg: no running status change */
+			else if (cin >= 0x8 && cin <= 0xe)
+				/* channel msg */
+				port->running_status_length = length - 1;
+			else if (cin == 0x4 &&
+				 port->running_status_length != 0 &&
+				 buffer[i + 1] < 0x80)
+				/* CIN 4 that is not a SysEx */
+				length = port->running_status_length;
+			else
+				/*
+				 * All other msgs cannot begin running status.
+				 * (A channel msg sent as two or three CIN 0xF
+				 * packets could in theory, but this device
+				 * doesn't use this format.)
+				 */
+				port->running_status_length = 0;
+			snd_usbmidi_input_data(ep, cable, &buffer[i + 1], length);
+		}
+}
+
+/*
  * Adds one USB MIDI packet to the output buffer.
  */
 static void snd_usbmidi_output_standard_packet(struct urb* urb, uint8_t p0,
@@ -525,6 +566,12 @@ static struct usb_protocol_ops snd_usbmidi_midiman_ops = {
 	.output_packet = snd_usbmidi_output_midiman_packet,
 };
 
+static struct usb_protocol_ops snd_usbmidi_maudio_broken_running_status_ops = {
+	.input = snd_usbmidi_maudio_broken_running_status_input,
+	.output = snd_usbmidi_standard_output, 
+	.output_packet = snd_usbmidi_output_standard_packet,
+};
+
 /*
  * Novation USB MIDI protocol: number of data bytes is in the first byte
  * (when receiving) (+1!) or in the second byte (when sending); data begins
@@ -918,7 +965,11 @@ static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi* umidi,
 	}
 	/* we never use interrupt output pipes */
 	pipe = usb_sndbulkpipe(umidi->chip->dev, ep_info->out_ep);
-	ep->max_transfer = usb_maxpacket(umidi->chip->dev, pipe, 1);
+	if (umidi->chip->usb_id == USB_ID(0x0a92, 0x1020)) /* ESI M4U */
+		/* FIXME: we need more URBs to get reasonable bandwidth here: */
+		ep->max_transfer = 4;
+	else
+		ep->max_transfer = usb_maxpacket(umidi->chip->dev, pipe, 1);
 	buffer = usb_buffer_alloc(umidi->chip->dev, ep->max_transfer,
 				  GFP_KERNEL, &ep->urb->transfer_dma);
 	if (!buffer) {
@@ -1606,6 +1657,9 @@ int snd_usb_create_midi_interface(struct snd_usb_audio* chip,
 	switch (quirk ? quirk->type : QUIRK_MIDI_STANDARD_INTERFACE) {
 	case QUIRK_MIDI_STANDARD_INTERFACE:
 		err = snd_usbmidi_get_ms_info(umidi, endpoints);
+		if (chip->usb_id == USB_ID(0x0763, 0x0150)) /* M-Audio Uno */
+			umidi->usb_protocol_ops =
+				&snd_usbmidi_maudio_broken_running_status_ops;
 		break;
 	case QUIRK_MIDI_FIXED_ENDPOINT:
 		memcpy(&endpoints[0], quirk->data,
diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h
index 858262068f4f..8fcbe93b2589 100644
--- a/sound/usb/usbquirks.h
+++ b/sound/usb/usbquirks.h
@@ -40,6 +40,29 @@
 	.bInterfaceClass = USB_CLASS_VENDOR_SPEC
 
 /*
+ * Logitech QuickCam: bDeviceClass is vendor-specific, so generic interface
+ * class matches do not take effect without an explicit ID match.
+ */
+{
+	.match_flags = USB_DEVICE_ID_MATCH_DEVICE |
+		       USB_DEVICE_ID_MATCH_INT_CLASS |
+		       USB_DEVICE_ID_MATCH_INT_SUBCLASS,
+	.idVendor = 0x046d,
+	.idProduct = 0x08f0,
+	.bInterfaceClass = USB_CLASS_AUDIO,
+	.bInterfaceSubClass = USB_SUBCLASS_AUDIO_CONTROL
+},
+{
+	.match_flags = USB_DEVICE_ID_MATCH_DEVICE |
+		       USB_DEVICE_ID_MATCH_INT_CLASS |
+		       USB_DEVICE_ID_MATCH_INT_SUBCLASS,
+	.idVendor = 0x046d,
+	.idProduct = 0x08f6,
+	.bInterfaceClass = USB_CLASS_AUDIO,
+	.bInterfaceSubClass = USB_SUBCLASS_AUDIO_CONTROL
+},
+
+/*
  * Yamaha devices
  */