Merge branch 'topic/snd-device' into for-next
diff --git a/Documentation/devicetree/bindings/sound/pcm512x.txt b/Documentation/devicetree/bindings/sound/pcm512x.txt
index faff75e..98e0d34 100644
--- a/Documentation/devicetree/bindings/sound/pcm512x.txt
+++ b/Documentation/devicetree/bindings/sound/pcm512x.txt
@@ -5,7 +5,8 @@
 
 Required properties:
 
-  - compatible : One of "ti,pcm5121" or "ti,pcm5122"
+  - compatible : One of "ti,pcm5121", "ti,pcm5122", "ti,pcm5141" or
+                 "ti,pcm5142"
 
   - reg : the I2C address of the device for I2C, the chip select
           number for SPI.
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index ecee3bc..26b3199 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -830,6 +830,8 @@
 
 	intel_runtime_pm_enable(dev_priv);
 
+	i915_audio_component_init(dev_priv);
+
 	return 0;
 
 out_power_well:
@@ -870,6 +872,8 @@
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int ret;
 
+	i915_audio_component_cleanup(dev_priv);
+
 	ret = i915_gem_suspend(dev);
 	if (ret) {
 		DRM_ERROR("failed to idle hardware: %d\n", ret);
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 7643300..489b220 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -934,8 +934,7 @@
 
 static int i915_pm_suspend_late(struct device *dev)
 {
-	struct pci_dev *pdev = to_pci_dev(dev);
-	struct drm_device *drm_dev = pci_get_drvdata(pdev);
+	struct drm_device *drm_dev = dev_to_i915(dev)->dev;
 
 	/*
 	 * We have a suspedn ordering issue with the snd-hda driver also
@@ -954,8 +953,7 @@
 
 static int i915_pm_resume_early(struct device *dev)
 {
-	struct pci_dev *pdev = to_pci_dev(dev);
-	struct drm_device *drm_dev = pci_get_drvdata(pdev);
+	struct drm_device *drm_dev = dev_to_i915(dev)->dev;
 
 	if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF)
 		return 0;
@@ -965,8 +963,7 @@
 
 static int i915_pm_resume(struct device *dev)
 {
-	struct pci_dev *pdev = to_pci_dev(dev);
-	struct drm_device *drm_dev = pci_get_drvdata(pdev);
+	struct drm_device *drm_dev = dev_to_i915(dev)->dev;
 
 	if (drm_dev->switch_power_state == DRM_SWITCH_POWER_OFF)
 		return 0;
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 9d7a715..24cc36a 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1698,6 +1698,9 @@
 	struct drm_property *broadcast_rgb_property;
 	struct drm_property *force_audio_property;
 
+	/* hda/i915 audio component */
+	bool audio_component_registered;
+
 	uint32_t hw_context_size;
 	struct list_head context_list;
 
@@ -1781,6 +1784,11 @@
 	return dev->dev_private;
 }
 
+static inline struct drm_i915_private *dev_to_i915(struct device *dev)
+{
+	return to_i915(dev_get_drvdata(dev));
+}
+
 /* Iterate over initialised rings */
 #define for_each_ring(ring__, dev_priv__, i__) \
 	for ((i__) = 0; (i__) < I915_NUM_RINGS; (i__)++) \
diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c
index 2c7ed5c..ee41b88 100644
--- a/drivers/gpu/drm/i915/intel_audio.c
+++ b/drivers/gpu/drm/i915/intel_audio.c
@@ -22,6 +22,9 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/component.h>
+#include <drm/i915_component.h>
+#include "intel_drv.h"
 
 #include <drm/drmP.h>
 #include <drm/drm_edid.h>
@@ -461,3 +464,110 @@
 		dev_priv->display.audio_codec_disable = ilk_audio_codec_disable;
 	}
 }
+
+static void i915_audio_component_get_power(struct device *dev)
+{
+	intel_display_power_get(dev_to_i915(dev), POWER_DOMAIN_AUDIO);
+}
+
+static void i915_audio_component_put_power(struct device *dev)
+{
+	intel_display_power_put(dev_to_i915(dev), POWER_DOMAIN_AUDIO);
+}
+
+/* Get CDCLK in kHz  */
+static int i915_audio_component_get_cdclk_freq(struct device *dev)
+{
+	struct drm_i915_private *dev_priv = dev_to_i915(dev);
+	int ret;
+
+	if (WARN_ON_ONCE(!HAS_DDI(dev_priv)))
+		return -ENODEV;
+
+	intel_display_power_get(dev_priv, POWER_DOMAIN_AUDIO);
+	ret = intel_ddi_get_cdclk_freq(dev_priv);
+	intel_display_power_put(dev_priv, POWER_DOMAIN_AUDIO);
+
+	return ret;
+}
+
+static const struct i915_audio_component_ops i915_audio_component_ops = {
+	.owner		= THIS_MODULE,
+	.get_power	= i915_audio_component_get_power,
+	.put_power	= i915_audio_component_put_power,
+	.get_cdclk_freq	= i915_audio_component_get_cdclk_freq,
+};
+
+static int i915_audio_component_bind(struct device *i915_dev,
+				     struct device *hda_dev, void *data)
+{
+	struct i915_audio_component *acomp = data;
+
+	if (WARN_ON(acomp->ops || acomp->dev))
+		return -EEXIST;
+
+	acomp->ops = &i915_audio_component_ops;
+	acomp->dev = i915_dev;
+
+	return 0;
+}
+
+static void i915_audio_component_unbind(struct device *i915_dev,
+					struct device *hda_dev, void *data)
+{
+	struct i915_audio_component *acomp = data;
+
+	acomp->ops = NULL;
+	acomp->dev = NULL;
+}
+
+static const struct component_ops i915_audio_component_bind_ops = {
+	.bind	= i915_audio_component_bind,
+	.unbind	= i915_audio_component_unbind,
+};
+
+/**
+ * i915_audio_component_init - initialize and register the audio component
+ * @dev_priv: i915 device instance
+ *
+ * This will register with the component framework a child component which
+ * will bind dynamically to the snd_hda_intel driver's corresponding master
+ * component when the latter is registered. During binding the child
+ * initializes an instance of struct i915_audio_component which it receives
+ * from the master. The master can then start to use the interface defined by
+ * this struct. Each side can break the binding at any point by deregistering
+ * its own component after which each side's component unbind callback is
+ * called.
+ *
+ * We ignore any error during registration and continue with reduced
+ * functionality (i.e. without HDMI audio).
+ */
+void i915_audio_component_init(struct drm_i915_private *dev_priv)
+{
+	int ret;
+
+	ret = component_add(dev_priv->dev->dev, &i915_audio_component_bind_ops);
+	if (ret < 0) {
+		DRM_ERROR("failed to add audio component (%d)\n", ret);
+		/* continue with reduced functionality */
+		return;
+	}
+
+	dev_priv->audio_component_registered = true;
+}
+
+/**
+ * i915_audio_component_cleanup - deregister the audio component
+ * @dev_priv: i915 device instance
+ *
+ * Deregisters the audio component, breaking any existing binding to the
+ * corresponding snd_hda_intel driver's master component.
+ */
+void i915_audio_component_cleanup(struct drm_i915_private *dev_priv)
+{
+	if (!dev_priv->audio_component_registered)
+		return;
+
+	component_del(dev_priv->dev->dev, &i915_audio_component_bind_ops);
+	dev_priv->audio_component_registered = false;
+}
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 3b40a17..29ba962 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -873,6 +873,8 @@
 void intel_init_audio(struct drm_device *dev);
 void intel_audio_codec_enable(struct intel_encoder *encoder);
 void intel_audio_codec_disable(struct intel_encoder *encoder);
+void i915_audio_component_init(struct drm_i915_private *dev_priv);
+void i915_audio_component_cleanup(struct drm_i915_private *dev_priv);
 
 /* intel_display.c */
 const char *intel_output_name(int output);
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
index ac6da71..39ddf40 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -31,7 +31,6 @@
 
 #include "i915_drv.h"
 #include "intel_drv.h"
-#include <drm/i915_powerwell.h>
 
 /**
  * DOC: runtime pm
@@ -50,8 +49,6 @@
  * present for a given platform.
  */
 
-static struct i915_power_domains *hsw_pwr;
-
 #define for_each_power_well(i, power_well, domain_mask, power_domains)	\
 	for (i = 0;							\
 	     i < (power_domains)->power_well_count &&			\
@@ -1071,10 +1068,8 @@
 	 */
 	if (IS_HASWELL(dev_priv->dev)) {
 		set_power_wells(power_domains, hsw_power_wells);
-		hsw_pwr = power_domains;
 	} else if (IS_BROADWELL(dev_priv->dev)) {
 		set_power_wells(power_domains, bdw_power_wells);
-		hsw_pwr = power_domains;
 	} else if (IS_CHERRYVIEW(dev_priv->dev)) {
 		set_power_wells(power_domains, chv_power_wells);
 	} else if (IS_VALLEYVIEW(dev_priv->dev)) {
@@ -1118,8 +1113,6 @@
 	 * the power well is not enabled, so just enable it in case
 	 * we're going to unload/reload. */
 	intel_display_set_init_power(dev_priv, true);
-
-	hsw_pwr = NULL;
 }
 
 static void intel_power_domains_resume(struct drm_i915_private *dev_priv)
@@ -1328,52 +1321,3 @@
 	pm_runtime_put_autosuspend(device);
 }
 
-/* Display audio driver power well request */
-int i915_request_power_well(void)
-{
-	struct drm_i915_private *dev_priv;
-
-	if (!hsw_pwr)
-		return -ENODEV;
-
-	dev_priv = container_of(hsw_pwr, struct drm_i915_private,
-				power_domains);
-	intel_display_power_get(dev_priv, POWER_DOMAIN_AUDIO);
-	return 0;
-}
-EXPORT_SYMBOL_GPL(i915_request_power_well);
-
-/* Display audio driver power well release */
-int i915_release_power_well(void)
-{
-	struct drm_i915_private *dev_priv;
-
-	if (!hsw_pwr)
-		return -ENODEV;
-
-	dev_priv = container_of(hsw_pwr, struct drm_i915_private,
-				power_domains);
-	intel_display_power_put(dev_priv, POWER_DOMAIN_AUDIO);
-	return 0;
-}
-EXPORT_SYMBOL_GPL(i915_release_power_well);
-
-/*
- * Private interface for the audio driver to get CDCLK in kHz.
- *
- * Caller must request power well using i915_request_power_well() prior to
- * making the call.
- */
-int i915_get_cdclk_freq(void)
-{
-	struct drm_i915_private *dev_priv;
-
-	if (!hsw_pwr)
-		return -ENODEV;
-
-	dev_priv = container_of(hsw_pwr, struct drm_i915_private,
-				power_domains);
-
-	return intel_ddi_get_cdclk_freq(dev_priv);
-}
-EXPORT_SYMBOL_GPL(i915_get_cdclk_freq);
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 815de37..9049dd9 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -46,8 +46,6 @@
 
 source "drivers/staging/rts5208/Kconfig"
 
-source "drivers/staging/line6/Kconfig"
-
 source "drivers/staging/octeon/Kconfig"
 
 source "drivers/staging/octeon-usb/Kconfig"
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index 33c640b..fe26ff1 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -15,7 +15,6 @@
 obj-$(CONFIG_R8188EU)		+= rtl8188eu/
 obj-$(CONFIG_R8723AU)		+= rtl8723au/
 obj-$(CONFIG_RTS5208)		+= rts5208/
-obj-$(CONFIG_LINE6_USB)		+= line6/
 obj-$(CONFIG_NETLOGIC_XLR_NET)	+= netlogic/
 obj-$(CONFIG_OCTEON_ETHERNET)	+= octeon/
 obj-$(CONFIG_OCTEON_USB)	+= octeon-usb/
diff --git a/drivers/staging/line6/Kconfig b/drivers/staging/line6/Kconfig
deleted file mode 100644
index 4f1219b..0000000
--- a/drivers/staging/line6/Kconfig
+++ /dev/null
@@ -1,38 +0,0 @@
-menuconfig LINE6_USB
-	tristate "Line6 USB support"
-	depends on USB && SND
-	select SND_RAWMIDI
-	select SND_PCM
-	help
-	  This is a driver for the guitar amp, cab, and effects modeller
-	  PODxt Pro by Line6 (and similar devices), supporting the
-	  following features:
-	    * Reading/writing individual parameters
-	    * Reading/writing complete channel, effects setup, and amp
-	      setup data
-	    * Channel switching
-	    * Virtual MIDI interface
-	    * Tuner access
-	    * Playback/capture/mixer device for any ALSA-compatible PCM
-	      audio application
-	    * Signal routing (record clean/processed guitar signal,
-	      re-amping)
-
-	  Preliminary support for the Variax Workbench and TonePort
-	  devices is included.
-
-if LINE6_USB
-
-config LINE6_USB_IMPULSE_RESPONSE
-	bool "measure impulse response"
-	default n
-	help
-	  Say Y here to add code to measure the impulse response of a Line6
-	  device. This is more accurate than user-space methods since it
-	  bypasses any PCM data buffering (e.g., by ALSA or jack). This is
-	  useful for assessing the performance of new devices, but is not
-	  required for normal operation.
-
-	  If unsure, say N.
-
-endif # LINE6_USB
diff --git a/drivers/staging/line6/Makefile b/drivers/staging/line6/Makefile
deleted file mode 100644
index ae5c374..0000000
--- a/drivers/staging/line6/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-obj-$(CONFIG_LINE6_USB)		+= line6usb.o
-
-line6usb-y := 		\
-		audio.o		\
-		capture.o	\
-		driver.o	\
-		midi.o		\
-		midibuf.o	\
-		pcm.o		\
-		playback.o	\
-		pod.o		\
-		toneport.o	\
-		variax.o	\
-		podhd.o
diff --git a/drivers/staging/line6/audio.c b/drivers/staging/line6/audio.c
deleted file mode 100644
index 171d80c..0000000
--- a/drivers/staging/line6/audio.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Line6 Linux USB driver - 0.9.1beta
- *
- * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
- *
- *	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, version 2.
- *
- */
-
-#include <sound/core.h>
-#include <sound/initval.h>
-#include <linux/export.h>
-
-#include "driver.h"
-#include "audio.h"
-
-/*
-	Initialize the Line6 USB audio system.
-*/
-int line6_init_audio(struct usb_line6 *line6)
-{
-	struct snd_card *card;
-	int err;
-
-	err = snd_card_new(line6->ifcdev,
-			   SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
-			   THIS_MODULE, 0, &card);
-	if (err < 0)
-		return err;
-
-	line6->card = card;
-
-	strcpy(card->id, line6->properties->id);
-	strcpy(card->driver, DRIVER_NAME);
-	strcpy(card->shortname, line6->properties->name);
-	/* longname is 80 chars - see asound.h */
-	sprintf(card->longname, "Line6 %s at USB %s", line6->properties->name,
-		dev_name(line6->ifcdev));
-	return 0;
-}
-
-/*
-	Register the Line6 USB audio system.
-*/
-int line6_register_audio(struct usb_line6 *line6)
-{
-	int err;
-
-	err = snd_card_register(line6->card);
-	if (err < 0)
-		return err;
-
-	return 0;
-}
-
-/*
-	Cleanup the Line6 USB audio system.
-*/
-void line6_cleanup_audio(struct usb_line6 *line6)
-{
-	struct snd_card *card = line6->card;
-
-	if (card == NULL)
-		return;
-
-	snd_card_disconnect(card);
-	snd_card_free(card);
-	line6->card = NULL;
-}
diff --git a/drivers/staging/line6/audio.h b/drivers/staging/line6/audio.h
deleted file mode 100644
index 5f8a09a..0000000
--- a/drivers/staging/line6/audio.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Line6 Linux USB driver - 0.9.1beta
- *
- * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
- *
- *	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, version 2.
- *
- */
-
-#ifndef AUDIO_H
-#define AUDIO_H
-
-#include "driver.h"
-
-extern void line6_cleanup_audio(struct usb_line6 *);
-extern int line6_init_audio(struct usb_line6 *);
-extern int line6_register_audio(struct usb_line6 *);
-
-#endif
diff --git a/drivers/staging/line6/capture.c b/drivers/staging/line6/capture.c
deleted file mode 100644
index e6ca631..0000000
--- a/drivers/staging/line6/capture.c
+++ /dev/null
@@ -1,432 +0,0 @@
-/*
- * Line6 Linux USB driver - 0.9.1beta
- *
- * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
- *
- *	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, version 2.
- *
- */
-
-#include <linux/slab.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-
-#include "audio.h"
-#include "capture.h"
-#include "driver.h"
-#include "pcm.h"
-#include "pod.h"
-
-/*
-	Find a free URB and submit it.
-*/
-static int submit_audio_in_urb(struct snd_line6_pcm *line6pcm)
-{
-	int index;
-	unsigned long flags;
-	int i, urb_size;
-	int ret;
-	struct urb *urb_in;
-
-	spin_lock_irqsave(&line6pcm->lock_audio_in, flags);
-	index =
-	    find_first_zero_bit(&line6pcm->active_urb_in, LINE6_ISO_BUFFERS);
-
-	if (index < 0 || index >= LINE6_ISO_BUFFERS) {
-		spin_unlock_irqrestore(&line6pcm->lock_audio_in, flags);
-		dev_err(line6pcm->line6->ifcdev, "no free URB found\n");
-		return -EINVAL;
-	}
-
-	urb_in = line6pcm->urb_audio_in[index];
-	urb_size = 0;
-
-	for (i = 0; i < LINE6_ISO_PACKETS; ++i) {
-		struct usb_iso_packet_descriptor *fin =
-		    &urb_in->iso_frame_desc[i];
-		fin->offset = urb_size;
-		fin->length = line6pcm->max_packet_size;
-		urb_size += line6pcm->max_packet_size;
-	}
-
-	urb_in->transfer_buffer =
-	    line6pcm->buffer_in +
-	    index * LINE6_ISO_PACKETS * line6pcm->max_packet_size;
-	urb_in->transfer_buffer_length = urb_size;
-	urb_in->context = line6pcm;
-
-	ret = usb_submit_urb(urb_in, GFP_ATOMIC);
-
-	if (ret == 0)
-		set_bit(index, &line6pcm->active_urb_in);
-	else
-		dev_err(line6pcm->line6->ifcdev,
-			"URB in #%d submission failed (%d)\n", index, ret);
-
-	spin_unlock_irqrestore(&line6pcm->lock_audio_in, flags);
-	return 0;
-}
-
-/*
-	Submit all currently available capture URBs.
-*/
-int line6_submit_audio_in_all_urbs(struct snd_line6_pcm *line6pcm)
-{
-	int ret, i;
-
-	for (i = 0; i < LINE6_ISO_BUFFERS; ++i) {
-		ret = submit_audio_in_urb(line6pcm);
-		if (ret < 0)
-			return ret;
-	}
-
-	return 0;
-}
-
-/*
-	Unlink all currently active capture URBs.
-*/
-void line6_unlink_audio_in_urbs(struct snd_line6_pcm *line6pcm)
-{
-	unsigned int i;
-
-	for (i = LINE6_ISO_BUFFERS; i--;) {
-		if (test_bit(i, &line6pcm->active_urb_in)) {
-			if (!test_and_set_bit(i, &line6pcm->unlink_urb_in)) {
-				struct urb *u = line6pcm->urb_audio_in[i];
-
-				usb_unlink_urb(u);
-			}
-		}
-	}
-}
-
-/*
-	Wait until unlinking of all currently active capture URBs has been
-	finished.
-*/
-void line6_wait_clear_audio_in_urbs(struct snd_line6_pcm *line6pcm)
-{
-	int timeout = HZ;
-	unsigned int i;
-	int alive;
-
-	do {
-		alive = 0;
-		for (i = LINE6_ISO_BUFFERS; i--;) {
-			if (test_bit(i, &line6pcm->active_urb_in))
-				alive++;
-		}
-		if (!alive)
-			break;
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(1);
-	} while (--timeout > 0);
-	if (alive)
-		snd_printk(KERN_ERR "timeout: still %d active urbs..\n", alive);
-}
-
-/*
-	Unlink all currently active capture URBs, and wait for finishing.
-*/
-void line6_unlink_wait_clear_audio_in_urbs(struct snd_line6_pcm *line6pcm)
-{
-	line6_unlink_audio_in_urbs(line6pcm);
-	line6_wait_clear_audio_in_urbs(line6pcm);
-}
-
-/*
-	Copy data into ALSA capture buffer.
-*/
-void line6_capture_copy(struct snd_line6_pcm *line6pcm, char *fbuf, int fsize)
-{
-	struct snd_pcm_substream *substream =
-	    get_substream(line6pcm, SNDRV_PCM_STREAM_CAPTURE);
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	const int bytes_per_frame = line6pcm->properties->bytes_per_frame;
-	int frames = fsize / bytes_per_frame;
-
-	if (runtime == NULL)
-		return;
-
-	if (line6pcm->pos_in_done + frames > runtime->buffer_size) {
-		/*
-		   The transferred area goes over buffer boundary,
-		   copy two separate chunks.
-		 */
-		int len;
-
-		len = runtime->buffer_size - line6pcm->pos_in_done;
-
-		if (len > 0) {
-			memcpy(runtime->dma_area +
-			       line6pcm->pos_in_done * bytes_per_frame, fbuf,
-			       len * bytes_per_frame);
-			memcpy(runtime->dma_area, fbuf + len * bytes_per_frame,
-			       (frames - len) * bytes_per_frame);
-		} else {
-			/* this is somewhat paranoid */
-			dev_err(line6pcm->line6->ifcdev,
-				"driver bug: len = %d\n", len);
-		}
-	} else {
-		/* copy single chunk */
-		memcpy(runtime->dma_area +
-		       line6pcm->pos_in_done * bytes_per_frame, fbuf, fsize);
-	}
-
-	line6pcm->pos_in_done += frames;
-	if (line6pcm->pos_in_done >= runtime->buffer_size)
-		line6pcm->pos_in_done -= runtime->buffer_size;
-}
-
-void line6_capture_check_period(struct snd_line6_pcm *line6pcm, int length)
-{
-	struct snd_pcm_substream *substream =
-	    get_substream(line6pcm, SNDRV_PCM_STREAM_CAPTURE);
-
-	line6pcm->bytes_in += length;
-	if (line6pcm->bytes_in >= line6pcm->period_in) {
-		line6pcm->bytes_in %= line6pcm->period_in;
-		snd_pcm_period_elapsed(substream);
-	}
-}
-
-void line6_free_capture_buffer(struct snd_line6_pcm *line6pcm)
-{
-	kfree(line6pcm->buffer_in);
-	line6pcm->buffer_in = NULL;
-}
-
-/*
- * Callback for completed capture URB.
- */
-static void audio_in_callback(struct urb *urb)
-{
-	int i, index, length = 0, shutdown = 0;
-	unsigned long flags;
-
-	struct snd_line6_pcm *line6pcm = (struct snd_line6_pcm *)urb->context;
-
-	line6pcm->last_frame_in = urb->start_frame;
-
-	/* find index of URB */
-	for (index = 0; index < LINE6_ISO_BUFFERS; ++index)
-		if (urb == line6pcm->urb_audio_in[index])
-			break;
-
-	spin_lock_irqsave(&line6pcm->lock_audio_in, flags);
-
-	for (i = 0; i < LINE6_ISO_PACKETS; ++i) {
-		char *fbuf;
-		int fsize;
-		struct usb_iso_packet_descriptor *fin = &urb->iso_frame_desc[i];
-
-		if (fin->status == -EXDEV) {
-			shutdown = 1;
-			break;
-		}
-
-		fbuf = urb->transfer_buffer + fin->offset;
-		fsize = fin->actual_length;
-
-		if (fsize > line6pcm->max_packet_size) {
-			dev_err(line6pcm->line6->ifcdev,
-				"driver and/or device bug: packet too large (%d > %d)\n",
-				fsize, line6pcm->max_packet_size);
-		}
-
-		length += fsize;
-
-		/* the following assumes LINE6_ISO_PACKETS == 1: */
-		line6pcm->prev_fbuf = fbuf;
-		line6pcm->prev_fsize = fsize;
-
-#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
-		if (!(line6pcm->flags & LINE6_BITS_PCM_IMPULSE))
-#endif
-			if (test_bit(LINE6_INDEX_PCM_ALSA_CAPTURE_STREAM,
-				     &line6pcm->flags) && (fsize > 0))
-				line6_capture_copy(line6pcm, fbuf, fsize);
-	}
-
-	clear_bit(index, &line6pcm->active_urb_in);
-
-	if (test_and_clear_bit(index, &line6pcm->unlink_urb_in))
-		shutdown = 1;
-
-	spin_unlock_irqrestore(&line6pcm->lock_audio_in, flags);
-
-	if (!shutdown) {
-		submit_audio_in_urb(line6pcm);
-
-#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
-		if (!(line6pcm->flags & LINE6_BITS_PCM_IMPULSE))
-#endif
-			if (test_bit(LINE6_INDEX_PCM_ALSA_CAPTURE_STREAM,
-				     &line6pcm->flags))
-				line6_capture_check_period(line6pcm, length);
-	}
-}
-
-/* open capture callback */
-static int snd_line6_capture_open(struct snd_pcm_substream *substream)
-{
-	int err;
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
-
-	err = snd_pcm_hw_constraint_ratdens(runtime, 0,
-					    SNDRV_PCM_HW_PARAM_RATE,
-					    (&line6pcm->
-					     properties->snd_line6_rates));
-	if (err < 0)
-		return err;
-
-	runtime->hw = line6pcm->properties->snd_line6_capture_hw;
-	return 0;
-}
-
-/* close capture callback */
-static int snd_line6_capture_close(struct snd_pcm_substream *substream)
-{
-	return 0;
-}
-
-/* hw_params capture callback */
-static int snd_line6_capture_hw_params(struct snd_pcm_substream *substream,
-				       struct snd_pcm_hw_params *hw_params)
-{
-	int ret;
-	struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
-
-	/* -- Florian Demski [FD] */
-	/* don't ask me why, but this fixes the bug on my machine */
-	if (line6pcm == NULL) {
-		if (substream->pcm == NULL)
-			return -ENOMEM;
-		if (substream->pcm->private_data == NULL)
-			return -ENOMEM;
-		substream->private_data = substream->pcm->private_data;
-		line6pcm = snd_pcm_substream_chip(substream);
-	}
-	/* -- [FD] end */
-
-	ret = line6_pcm_acquire(line6pcm, LINE6_BIT_PCM_ALSA_CAPTURE_BUFFER);
-
-	if (ret < 0)
-		return ret;
-
-	ret = snd_pcm_lib_malloc_pages(substream,
-				       params_buffer_bytes(hw_params));
-	if (ret < 0) {
-		line6_pcm_release(line6pcm, LINE6_BIT_PCM_ALSA_CAPTURE_BUFFER);
-		return ret;
-	}
-
-	line6pcm->period_in = params_period_bytes(hw_params);
-	return 0;
-}
-
-/* hw_free capture callback */
-static int snd_line6_capture_hw_free(struct snd_pcm_substream *substream)
-{
-	struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
-
-	line6_pcm_release(line6pcm, LINE6_BIT_PCM_ALSA_CAPTURE_BUFFER);
-	return snd_pcm_lib_free_pages(substream);
-}
-
-/* trigger callback */
-int snd_line6_capture_trigger(struct snd_line6_pcm *line6pcm, int cmd)
-{
-	int err;
-
-	switch (cmd) {
-	case SNDRV_PCM_TRIGGER_START:
-#ifdef CONFIG_PM
-	case SNDRV_PCM_TRIGGER_RESUME:
-#endif
-		err = line6_pcm_acquire(line6pcm,
-					LINE6_BIT_PCM_ALSA_CAPTURE_STREAM);
-
-		if (err < 0)
-			return err;
-
-		break;
-
-	case SNDRV_PCM_TRIGGER_STOP:
-#ifdef CONFIG_PM
-	case SNDRV_PCM_TRIGGER_SUSPEND:
-#endif
-		err = line6_pcm_release(line6pcm,
-					LINE6_BIT_PCM_ALSA_CAPTURE_STREAM);
-
-		if (err < 0)
-			return err;
-
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-/* capture pointer callback */
-static snd_pcm_uframes_t
-snd_line6_capture_pointer(struct snd_pcm_substream *substream)
-{
-	struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
-
-	return line6pcm->pos_in_done;
-}
-
-/* capture operators */
-struct snd_pcm_ops snd_line6_capture_ops = {
-	.open = snd_line6_capture_open,
-	.close = snd_line6_capture_close,
-	.ioctl = snd_pcm_lib_ioctl,
-	.hw_params = snd_line6_capture_hw_params,
-	.hw_free = snd_line6_capture_hw_free,
-	.prepare = snd_line6_prepare,
-	.trigger = snd_line6_trigger,
-	.pointer = snd_line6_capture_pointer,
-};
-
-int line6_create_audio_in_urbs(struct snd_line6_pcm *line6pcm)
-{
-	int i;
-
-	/* create audio URBs and fill in constant values: */
-	for (i = 0; i < LINE6_ISO_BUFFERS; ++i) {
-		struct urb *urb;
-
-		/* URB for audio in: */
-		urb = line6pcm->urb_audio_in[i] =
-		    usb_alloc_urb(LINE6_ISO_PACKETS, GFP_KERNEL);
-
-		if (urb == NULL) {
-			dev_err(line6pcm->line6->ifcdev, "Out of memory\n");
-			return -ENOMEM;
-		}
-
-		urb->dev = line6pcm->line6->usbdev;
-		urb->pipe =
-		    usb_rcvisocpipe(line6pcm->line6->usbdev,
-				    line6pcm->ep_audio_read &
-				    USB_ENDPOINT_NUMBER_MASK);
-		urb->transfer_flags = URB_ISO_ASAP;
-		urb->start_frame = -1;
-		urb->number_of_packets = LINE6_ISO_PACKETS;
-		urb->interval = LINE6_ISO_INTERVAL;
-		urb->error_count = 0;
-		urb->complete = audio_in_callback;
-	}
-
-	return 0;
-}
diff --git a/drivers/staging/line6/driver.c b/drivers/staging/line6/driver.c
deleted file mode 100644
index 503b2d7..0000000
--- a/drivers/staging/line6/driver.c
+++ /dev/null
@@ -1,1162 +0,0 @@
-/*
- * Line6 Linux USB driver - 0.9.1beta
- *
- * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
- *
- *	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, version 2.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/usb.h>
-
-#include "audio.h"
-#include "capture.h"
-#include "driver.h"
-#include "midi.h"
-#include "playback.h"
-#include "pod.h"
-#include "podhd.h"
-#include "revision.h"
-#include "toneport.h"
-#include "usbdefs.h"
-#include "variax.h"
-
-#define DRIVER_AUTHOR  "Markus Grabner <grabner@icg.tugraz.at>"
-#define DRIVER_DESC    "Line6 USB Driver"
-#define DRIVER_VERSION "0.9.1beta" DRIVER_REVISION
-
-/* table of devices that work with this driver */
-static const struct usb_device_id line6_id_table[] = {
-	{USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_BASSPODXT)},
-	{USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_BASSPODXTLIVE)},
-	{USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_BASSPODXTPRO)},
-	{USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_GUITARPORT)},
-	{USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_POCKETPOD)},
-	{USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODHD300)},
-	{USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODHD400)},
-	{USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODHD500)},
-	{USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODSTUDIO_GX)},
-	{USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODSTUDIO_UX1)},
-	{USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODSTUDIO_UX2)},
-	{USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODX3)},
-	{USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODX3LIVE)},
-	{USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODXT)},
-	{USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODXTLIVE)},
-	{USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_PODXTPRO)},
-	{USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_TONEPORT_GX)},
-	{USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_TONEPORT_UX1)},
-	{USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_TONEPORT_UX2)},
-	{USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_VARIAX)},
-	{},
-};
-
-MODULE_DEVICE_TABLE(usb, line6_id_table);
-
-#define L6PROP(dev_bit, dev_id, dev_name, dev_cap)\
-	{.device_bit = LINE6_BIT_##dev_bit, .id = dev_id,\
-	 .name = dev_name, .capabilities = LINE6_BIT_##dev_cap}
-
-/* *INDENT-OFF* */
-static const struct line6_properties line6_properties_table[] = {
-	L6PROP(BASSPODXT,     "BassPODxt",     "BassPODxt",        CTRL_PCM_HW),
-	L6PROP(BASSPODXTLIVE, "BassPODxtLive", "BassPODxt Live",   CTRL_PCM_HW),
-	L6PROP(BASSPODXTPRO,  "BassPODxtPro",  "BassPODxt Pro",    CTRL_PCM_HW),
-	L6PROP(GUITARPORT,    "GuitarPort",    "GuitarPort",       PCM),
-	L6PROP(POCKETPOD,     "PocketPOD",     "Pocket POD",       CONTROL),
-	L6PROP(PODHD300,      "PODHD300",      "POD HD300",        CTRL_PCM_HW),
-	L6PROP(PODHD400,      "PODHD400",      "POD HD400",        CTRL_PCM_HW),
-	L6PROP(PODHD500,      "PODHD500",      "POD HD500",        CTRL_PCM_HW),
-	L6PROP(PODSTUDIO_GX,  "PODStudioGX",   "POD Studio GX",    PCM),
-	L6PROP(PODSTUDIO_UX1, "PODStudioUX1",  "POD Studio UX1",   PCM),
-	L6PROP(PODSTUDIO_UX2, "PODStudioUX2",  "POD Studio UX2",   PCM),
-	L6PROP(PODX3,         "PODX3",         "POD X3",           PCM),
-	L6PROP(PODX3LIVE,     "PODX3Live",     "POD X3 Live",      PCM),
-	L6PROP(PODXT,         "PODxt",         "PODxt",            CTRL_PCM_HW),
-	L6PROP(PODXTLIVE,     "PODxtLive",     "PODxt Live",       CTRL_PCM_HW),
-	L6PROP(PODXTPRO,      "PODxtPro",      "PODxt Pro",        CTRL_PCM_HW),
-	L6PROP(TONEPORT_GX,   "TonePortGX",    "TonePort GX",      PCM),
-	L6PROP(TONEPORT_UX1,  "TonePortUX1",   "TonePort UX1",     PCM),
-	L6PROP(TONEPORT_UX2,  "TonePortUX2",   "TonePort UX2",     PCM),
-	L6PROP(VARIAX,        "Variax",        "Variax Workbench", CONTROL),
-};
-/* *INDENT-ON* */
-
-/*
-	This is Line6's MIDI manufacturer ID.
-*/
-const unsigned char line6_midi_id[] = {
-	0x00, 0x01, 0x0c
-};
-
-/*
-	Code to request version of POD, Variax interface
-	(and maybe other devices).
-*/
-static const char line6_request_version[] = {
-	0xf0, 0x7e, 0x7f, 0x06, 0x01, 0xf7
-};
-
-/**
-	 Class for asynchronous messages.
-*/
-struct message {
-	struct usb_line6 *line6;
-	const char *buffer;
-	int size;
-	int done;
-};
-
-/*
-	Forward declarations.
-*/
-static void line6_data_received(struct urb *urb);
-static int line6_send_raw_message_async_part(struct message *msg,
-					     struct urb *urb);
-
-/*
-	Start to listen on endpoint.
-*/
-static int line6_start_listen(struct usb_line6 *line6)
-{
-	int err;
-
-	usb_fill_int_urb(line6->urb_listen, line6->usbdev,
-			 usb_rcvintpipe(line6->usbdev, line6->ep_control_read),
-			 line6->buffer_listen, LINE6_BUFSIZE_LISTEN,
-			 line6_data_received, line6, line6->interval);
-	line6->urb_listen->actual_length = 0;
-	err = usb_submit_urb(line6->urb_listen, GFP_ATOMIC);
-	return err;
-}
-
-/*
-	Stop listening on endpoint.
-*/
-static void line6_stop_listen(struct usb_line6 *line6)
-{
-	usb_kill_urb(line6->urb_listen);
-}
-
-/*
-	Send raw message in pieces of wMaxPacketSize bytes.
-*/
-int line6_send_raw_message(struct usb_line6 *line6, const char *buffer,
-			   int size)
-{
-	int i, done = 0;
-
-	for (i = 0; i < size; i += line6->max_packet_size) {
-		int partial;
-		const char *frag_buf = buffer + i;
-		int frag_size = min(line6->max_packet_size, size - i);
-		int retval;
-
-		retval = usb_interrupt_msg(line6->usbdev,
-					usb_sndintpipe(line6->usbdev,
-						line6->ep_control_write),
-					(char *)frag_buf, frag_size,
-					&partial, LINE6_TIMEOUT * HZ);
-
-		if (retval) {
-			dev_err(line6->ifcdev,
-				"usb_interrupt_msg failed (%d)\n", retval);
-			break;
-		}
-
-		done += frag_size;
-	}
-
-	return done;
-}
-
-/*
-	Notification of completion of asynchronous request transmission.
-*/
-static void line6_async_request_sent(struct urb *urb)
-{
-	struct message *msg = (struct message *)urb->context;
-
-	if (msg->done >= msg->size) {
-		usb_free_urb(urb);
-		kfree(msg);
-	} else
-		line6_send_raw_message_async_part(msg, urb);
-}
-
-/*
-	Asynchronously send part of a raw message.
-*/
-static int line6_send_raw_message_async_part(struct message *msg,
-					     struct urb *urb)
-{
-	int retval;
-	struct usb_line6 *line6 = msg->line6;
-	int done = msg->done;
-	int bytes = min(msg->size - done, line6->max_packet_size);
-
-	usb_fill_int_urb(urb, line6->usbdev,
-			 usb_sndintpipe(line6->usbdev, line6->ep_control_write),
-			 (char *)msg->buffer + done, bytes,
-			 line6_async_request_sent, msg, line6->interval);
-
-	msg->done += bytes;
-	retval = usb_submit_urb(urb, GFP_ATOMIC);
-
-	if (retval < 0) {
-		dev_err(line6->ifcdev, "%s: usb_submit_urb failed (%d)\n",
-			__func__, retval);
-		usb_free_urb(urb);
-		kfree(msg);
-		return retval;
-	}
-
-	return 0;
-}
-
-/*
-	Setup and start timer.
-*/
-void line6_start_timer(struct timer_list *timer, unsigned int msecs,
-		       void (*function)(unsigned long), unsigned long data)
-{
-	setup_timer(timer, function, data);
-	timer->expires = jiffies + msecs * HZ / 1000;
-	add_timer(timer);
-}
-
-/*
-	Asynchronously send raw message.
-*/
-int line6_send_raw_message_async(struct usb_line6 *line6, const char *buffer,
-				 int size)
-{
-	struct message *msg;
-	struct urb *urb;
-
-	/* create message: */
-	msg = kmalloc(sizeof(struct message), GFP_ATOMIC);
-	if (msg == NULL)
-		return -ENOMEM;
-
-	/* create URB: */
-	urb = usb_alloc_urb(0, GFP_ATOMIC);
-
-	if (urb == NULL) {
-		kfree(msg);
-		dev_err(line6->ifcdev, "Out of memory\n");
-		return -ENOMEM;
-	}
-
-	/* set message data: */
-	msg->line6 = line6;
-	msg->buffer = buffer;
-	msg->size = size;
-	msg->done = 0;
-
-	/* start sending: */
-	return line6_send_raw_message_async_part(msg, urb);
-}
-
-/*
-	Send asynchronous device version request.
-*/
-int line6_version_request_async(struct usb_line6 *line6)
-{
-	char *buffer;
-	int retval;
-
-	buffer = kmemdup(line6_request_version,
-			sizeof(line6_request_version), GFP_ATOMIC);
-	if (buffer == NULL) {
-		dev_err(line6->ifcdev, "Out of memory");
-		return -ENOMEM;
-	}
-
-	retval = line6_send_raw_message_async(line6, buffer,
-					      sizeof(line6_request_version));
-	kfree(buffer);
-	return retval;
-}
-
-/*
-	Send sysex message in pieces of wMaxPacketSize bytes.
-*/
-int line6_send_sysex_message(struct usb_line6 *line6, const char *buffer,
-			     int size)
-{
-	return line6_send_raw_message(line6, buffer,
-				      size + SYSEX_EXTRA_SIZE) -
-	    SYSEX_EXTRA_SIZE;
-}
-
-/*
-	Allocate buffer for sysex message and prepare header.
-	@param code sysex message code
-	@param size number of bytes between code and sysex end
-*/
-char *line6_alloc_sysex_buffer(struct usb_line6 *line6, int code1, int code2,
-			       int size)
-{
-	char *buffer = kmalloc(size + SYSEX_EXTRA_SIZE, GFP_ATOMIC);
-
-	if (!buffer)
-		return NULL;
-
-	buffer[0] = LINE6_SYSEX_BEGIN;
-	memcpy(buffer + 1, line6_midi_id, sizeof(line6_midi_id));
-	buffer[sizeof(line6_midi_id) + 1] = code1;
-	buffer[sizeof(line6_midi_id) + 2] = code2;
-	buffer[sizeof(line6_midi_id) + 3 + size] = LINE6_SYSEX_END;
-	return buffer;
-}
-
-/*
-	Notification of data received from the Line6 device.
-*/
-static void line6_data_received(struct urb *urb)
-{
-	struct usb_line6 *line6 = (struct usb_line6 *)urb->context;
-	struct midi_buffer *mb = &line6->line6midi->midibuf_in;
-	int done;
-
-	if (urb->status == -ESHUTDOWN)
-		return;
-
-	done =
-	    line6_midibuf_write(mb, urb->transfer_buffer, urb->actual_length);
-
-	if (done < urb->actual_length) {
-		line6_midibuf_ignore(mb, done);
-		dev_dbg(line6->ifcdev, "%d %d buffer overflow - message skipped\n",
-			done, urb->actual_length);
-	}
-
-	for (;;) {
-		done =
-		    line6_midibuf_read(mb, line6->buffer_message,
-				       LINE6_MESSAGE_MAXLEN);
-
-		if (done == 0)
-			break;
-
-		line6->message_length = done;
-		line6_midi_receive(line6, line6->buffer_message, done);
-
-		switch (le16_to_cpu(line6->usbdev->descriptor.idProduct)) {
-		case LINE6_DEVID_BASSPODXT:
-		case LINE6_DEVID_BASSPODXTLIVE:
-		case LINE6_DEVID_BASSPODXTPRO:
-		case LINE6_DEVID_PODXT:
-		case LINE6_DEVID_PODXTPRO:
-		case LINE6_DEVID_POCKETPOD:
-			line6_pod_process_message((struct usb_line6_pod *)
-						  line6);
-			break;
-
-		case LINE6_DEVID_PODHD300:
-		case LINE6_DEVID_PODHD400:
-		case LINE6_DEVID_PODHD500:
-			break; /* let userspace handle MIDI */
-
-		case LINE6_DEVID_PODXTLIVE:
-			switch (line6->interface_number) {
-			case PODXTLIVE_INTERFACE_POD:
-				line6_pod_process_message((struct usb_line6_pod
-							   *)line6);
-				break;
-
-			case PODXTLIVE_INTERFACE_VARIAX:
-				line6_variax_process_message((struct
-							      usb_line6_variax
-							      *)line6);
-				break;
-
-			default:
-				dev_err(line6->ifcdev,
-					"PODxt Live interface %d not supported\n",
-					line6->interface_number);
-			}
-			break;
-
-		case LINE6_DEVID_VARIAX:
-			line6_variax_process_message((struct usb_line6_variax *)
-						     line6);
-			break;
-
-		default:
-			MISSING_CASE;
-		}
-	}
-
-	line6_start_listen(line6);
-}
-
-/*
-	Send channel number (i.e., switch to a different sound).
-*/
-int line6_send_program(struct usb_line6 *line6, u8 value)
-{
-	int retval;
-	unsigned char *buffer;
-	int partial;
-
-	buffer = kmalloc(2, GFP_KERNEL);
-	if (!buffer)
-		return -ENOMEM;
-
-	buffer[0] = LINE6_PROGRAM_CHANGE | LINE6_CHANNEL_HOST;
-	buffer[1] = value;
-
-	retval = usb_interrupt_msg(line6->usbdev,
-				   usb_sndintpipe(line6->usbdev,
-						  line6->ep_control_write),
-				   buffer, 2, &partial, LINE6_TIMEOUT * HZ);
-
-	if (retval)
-		dev_err(line6->ifcdev, "usb_interrupt_msg failed (%d)\n",
-			retval);
-
-	kfree(buffer);
-	return retval;
-}
-
-/*
-	Transmit Line6 control parameter.
-*/
-int line6_transmit_parameter(struct usb_line6 *line6, int param, u8 value)
-{
-	int retval;
-	unsigned char *buffer;
-	int partial;
-
-	buffer = kmalloc(3, GFP_KERNEL);
-	if (!buffer)
-		return -ENOMEM;
-
-	buffer[0] = LINE6_PARAM_CHANGE | LINE6_CHANNEL_HOST;
-	buffer[1] = param;
-	buffer[2] = value;
-
-	retval = usb_interrupt_msg(line6->usbdev,
-				   usb_sndintpipe(line6->usbdev,
-						  line6->ep_control_write),
-				   buffer, 3, &partial, LINE6_TIMEOUT * HZ);
-
-	if (retval)
-		dev_err(line6->ifcdev, "usb_interrupt_msg failed (%d)\n",
-			retval);
-
-	kfree(buffer);
-	return retval;
-}
-
-/*
-	Read data from device.
-*/
-int line6_read_data(struct usb_line6 *line6, int address, void *data,
-		    size_t datalen)
-{
-	struct usb_device *usbdev = line6->usbdev;
-	int ret;
-	unsigned char len;
-
-	/* query the serial number: */
-	ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x67,
-			      USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
-			      (datalen << 8) | 0x21, address,
-			      NULL, 0, LINE6_TIMEOUT * HZ);
-
-	if (ret < 0) {
-		dev_err(line6->ifcdev, "read request failed (error %d)\n", ret);
-		return ret;
-	}
-
-	/* Wait for data length. We'll get 0xff until length arrives. */
-	do {
-		ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), 0x67,
-				      USB_TYPE_VENDOR | USB_RECIP_DEVICE |
-				      USB_DIR_IN,
-				      0x0012, 0x0000, &len, 1,
-				      LINE6_TIMEOUT * HZ);
-		if (ret < 0) {
-			dev_err(line6->ifcdev,
-				"receive length failed (error %d)\n", ret);
-			return ret;
-		}
-	} while (len == 0xff);
-
-	if (len != datalen) {
-		/* should be equal or something went wrong */
-		dev_err(line6->ifcdev,
-			"length mismatch (expected %d, got %d)\n",
-			(int)datalen, (int)len);
-		return -EINVAL;
-	}
-
-	/* receive the result: */
-	ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), 0x67,
-			      USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
-			      0x0013, 0x0000, data, datalen,
-			      LINE6_TIMEOUT * HZ);
-
-	if (ret < 0) {
-		dev_err(line6->ifcdev, "read failed (error %d)\n", ret);
-		return ret;
-	}
-
-	return 0;
-}
-
-/*
-	Write data to device.
-*/
-int line6_write_data(struct usb_line6 *line6, int address, void *data,
-		     size_t datalen)
-{
-	struct usb_device *usbdev = line6->usbdev;
-	int ret;
-	unsigned char status;
-
-	ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x67,
-			      USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
-			      0x0022, address, data, datalen,
-			      LINE6_TIMEOUT * HZ);
-
-	if (ret < 0) {
-		dev_err(line6->ifcdev,
-			"write request failed (error %d)\n", ret);
-		return ret;
-	}
-
-	do {
-		ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0),
-				      0x67,
-				      USB_TYPE_VENDOR | USB_RECIP_DEVICE |
-				      USB_DIR_IN,
-				      0x0012, 0x0000,
-				      &status, 1, LINE6_TIMEOUT * HZ);
-
-		if (ret < 0) {
-			dev_err(line6->ifcdev,
-				"receiving status failed (error %d)\n", ret);
-			return ret;
-		}
-	} while (status == 0xff);
-
-	if (status != 0) {
-		dev_err(line6->ifcdev, "write failed (error %d)\n", ret);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-/*
-	Read Line6 device serial number.
-	(POD, TonePort, GuitarPort)
-*/
-int line6_read_serial_number(struct usb_line6 *line6, int *serial_number)
-{
-	return line6_read_data(line6, 0x80d0, serial_number,
-			       sizeof(*serial_number));
-}
-
-/*
-	No operation (i.e., unsupported).
-*/
-ssize_t line6_nop_read(struct device *dev, struct device_attribute *attr,
-		       char *buf)
-{
-	return 0;
-}
-
-/*
-	Generic destructor.
-*/
-static void line6_destruct(struct usb_interface *interface)
-{
-	struct usb_line6 *line6;
-
-	if (interface == NULL)
-		return;
-	line6 = usb_get_intfdata(interface);
-	if (line6 == NULL)
-		return;
-
-	/* free buffer memory first: */
-	kfree(line6->buffer_message);
-	kfree(line6->buffer_listen);
-
-	/* then free URBs: */
-	usb_free_urb(line6->urb_listen);
-
-	/* make sure the device isn't destructed twice: */
-	usb_set_intfdata(interface, NULL);
-
-	/* free interface data: */
-	kfree(line6);
-}
-
-/*
-	Probe USB device.
-*/
-static int line6_probe(struct usb_interface *interface,
-		       const struct usb_device_id *id)
-{
-	int devtype;
-	struct usb_device *usbdev;
-	struct usb_line6 *line6;
-	const struct line6_properties *properties;
-	int interface_number, alternate = 0;
-	int product;
-	int size = 0;
-	int ep_read = 0, ep_write = 0;
-	int ret;
-
-	if (interface == NULL)
-		return -ENODEV;
-	usbdev = interface_to_usbdev(interface);
-	if (usbdev == NULL)
-		return -ENODEV;
-
-	/* we don't handle multiple configurations */
-	if (usbdev->descriptor.bNumConfigurations != 1) {
-		ret = -ENODEV;
-		goto err_put;
-	}
-
-	/* check vendor and product id */
-	for (devtype = ARRAY_SIZE(line6_id_table) - 1; devtype--;) {
-		u16 idVendor = le16_to_cpu(usbdev->descriptor.idVendor);
-		u16 idProduct = le16_to_cpu(usbdev->descriptor.idProduct);
-
-		if (idVendor == line6_id_table[devtype].idVendor &&
-		    idProduct == line6_id_table[devtype].idProduct)
-			break;
-	}
-
-	if (devtype < 0) {
-		ret = -ENODEV;
-		goto err_put;
-	}
-
-	/* initialize device info: */
-	properties = &line6_properties_table[devtype];
-	dev_info(&interface->dev, "Line6 %s found\n", properties->name);
-	product = le16_to_cpu(usbdev->descriptor.idProduct);
-
-	/* query interface number */
-	interface_number = interface->cur_altsetting->desc.bInterfaceNumber;
-
-	switch (product) {
-	case LINE6_DEVID_BASSPODXTLIVE:
-	case LINE6_DEVID_PODXTLIVE:
-	case LINE6_DEVID_VARIAX:
-		alternate = 1;
-		break;
-
-	case LINE6_DEVID_POCKETPOD:
-		switch (interface_number) {
-		case 0:
-			return -ENODEV;	/* this interface has no endpoints */
-		case 1:
-			alternate = 0;
-			break;
-		default:
-			MISSING_CASE;
-		}
-		break;
-
-	case LINE6_DEVID_PODHD500:
-	case LINE6_DEVID_PODX3:
-	case LINE6_DEVID_PODX3LIVE:
-		switch (interface_number) {
-		case 0:
-			alternate = 1;
-			break;
-		case 1:
-			alternate = 0;
-			break;
-		default:
-			MISSING_CASE;
-		}
-		break;
-
-	case LINE6_DEVID_BASSPODXT:
-	case LINE6_DEVID_BASSPODXTPRO:
-	case LINE6_DEVID_PODXT:
-	case LINE6_DEVID_PODXTPRO:
-	case LINE6_DEVID_PODHD300:
-	case LINE6_DEVID_PODHD400:
-		alternate = 5;
-		break;
-
-	case LINE6_DEVID_GUITARPORT:
-	case LINE6_DEVID_PODSTUDIO_GX:
-	case LINE6_DEVID_PODSTUDIO_UX1:
-	case LINE6_DEVID_TONEPORT_GX:
-	case LINE6_DEVID_TONEPORT_UX1:
-		alternate = 2;	/* 1..4 seem to be ok */
-		break;
-
-	case LINE6_DEVID_TONEPORT_UX2:
-	case LINE6_DEVID_PODSTUDIO_UX2:
-		switch (interface_number) {
-		case 0:
-			/* defaults to 44.1kHz, 16-bit */
-			alternate = 2;
-			break;
-		case 1:
-			/* don't know yet what this is ...
-			   alternate = 1;
-			   break;
-			 */
-			return -ENODEV;
-		default:
-			MISSING_CASE;
-		}
-		break;
-
-	default:
-		MISSING_CASE;
-		ret = -ENODEV;
-		goto err_put;
-	}
-
-	ret = usb_set_interface(usbdev, interface_number, alternate);
-	if (ret < 0) {
-		dev_err(&interface->dev, "set_interface failed\n");
-		goto err_put;
-	}
-
-	/* initialize device data based on product id: */
-	switch (product) {
-	case LINE6_DEVID_BASSPODXT:
-	case LINE6_DEVID_BASSPODXTLIVE:
-	case LINE6_DEVID_BASSPODXTPRO:
-	case LINE6_DEVID_PODXT:
-	case LINE6_DEVID_PODXTPRO:
-		size = sizeof(struct usb_line6_pod);
-		ep_read = 0x84;
-		ep_write = 0x03;
-		break;
-
-	case LINE6_DEVID_PODHD300:
-	case LINE6_DEVID_PODHD400:
-		size = sizeof(struct usb_line6_podhd);
-		ep_read = 0x84;
-		ep_write = 0x03;
-		break;
-
-	case LINE6_DEVID_PODHD500:
-		size = sizeof(struct usb_line6_podhd);
-		ep_read = 0x81;
-		ep_write = 0x01;
-		break;
-
-	case LINE6_DEVID_POCKETPOD:
-		size = sizeof(struct usb_line6_pod);
-		ep_read = 0x82;
-		ep_write = 0x02;
-		break;
-
-	case LINE6_DEVID_PODX3:
-	case LINE6_DEVID_PODX3LIVE:
-		/* currently unused! */
-		size = sizeof(struct usb_line6_pod);
-		ep_read = 0x81;
-		ep_write = 0x01;
-		break;
-
-	case LINE6_DEVID_PODSTUDIO_GX:
-	case LINE6_DEVID_PODSTUDIO_UX1:
-	case LINE6_DEVID_PODSTUDIO_UX2:
-	case LINE6_DEVID_TONEPORT_GX:
-	case LINE6_DEVID_TONEPORT_UX1:
-	case LINE6_DEVID_TONEPORT_UX2:
-	case LINE6_DEVID_GUITARPORT:
-		size = sizeof(struct usb_line6_toneport);
-		/* these don't have a control channel */
-		break;
-
-	case LINE6_DEVID_PODXTLIVE:
-		switch (interface_number) {
-		case PODXTLIVE_INTERFACE_POD:
-			size = sizeof(struct usb_line6_pod);
-			ep_read = 0x84;
-			ep_write = 0x03;
-			break;
-
-		case PODXTLIVE_INTERFACE_VARIAX:
-			size = sizeof(struct usb_line6_variax);
-			ep_read = 0x86;
-			ep_write = 0x05;
-			break;
-
-		default:
-			ret = -ENODEV;
-			goto err_put;
-		}
-		break;
-
-	case LINE6_DEVID_VARIAX:
-		size = sizeof(struct usb_line6_variax);
-		ep_read = 0x82;
-		ep_write = 0x01;
-		break;
-
-	default:
-		MISSING_CASE;
-		ret = -ENODEV;
-		goto err_put;
-	}
-
-	if (size == 0) {
-		dev_err(&interface->dev,
-			"driver bug: interface data size not set\n");
-		ret = -ENODEV;
-		goto err_put;
-	}
-
-	line6 = kzalloc(size, GFP_KERNEL);
-	if (line6 == NULL) {
-		ret = -ENODEV;
-		goto err_put;
-	}
-
-	/* store basic data: */
-	line6->interface_number = interface_number;
-	line6->properties = properties;
-	line6->usbdev = usbdev;
-	line6->ifcdev = &interface->dev;
-	line6->ep_control_read = ep_read;
-	line6->ep_control_write = ep_write;
-	line6->product = product;
-
-	/* get data from endpoint descriptor (see usb_maxpacket): */
-	{
-		struct usb_host_endpoint *ep;
-		unsigned epnum =
-		    usb_pipeendpoint(usb_rcvintpipe(usbdev, ep_read));
-		ep = usbdev->ep_in[epnum];
-
-		if (ep != NULL) {
-			line6->interval = ep->desc.bInterval;
-			line6->max_packet_size =
-			    le16_to_cpu(ep->desc.wMaxPacketSize);
-		} else {
-			line6->interval = LINE6_FALLBACK_INTERVAL;
-			line6->max_packet_size = LINE6_FALLBACK_MAXPACKETSIZE;
-			dev_err(line6->ifcdev,
-				"endpoint not available, using fallback values");
-		}
-	}
-
-	usb_set_intfdata(interface, line6);
-
-	if (properties->capabilities & LINE6_BIT_CONTROL) {
-		/* initialize USB buffers: */
-		line6->buffer_listen =
-		    kmalloc(LINE6_BUFSIZE_LISTEN, GFP_KERNEL);
-		if (line6->buffer_listen == NULL) {
-			ret = -ENOMEM;
-			goto err_destruct;
-		}
-
-		line6->buffer_message =
-		    kmalloc(LINE6_MESSAGE_MAXLEN, GFP_KERNEL);
-		if (line6->buffer_message == NULL) {
-			ret = -ENOMEM;
-			goto err_destruct;
-		}
-
-		line6->urb_listen = usb_alloc_urb(0, GFP_KERNEL);
-
-		if (line6->urb_listen == NULL) {
-			dev_err(&interface->dev, "Out of memory\n");
-			line6_destruct(interface);
-			ret = -ENOMEM;
-			goto err_destruct;
-		}
-
-		ret = line6_start_listen(line6);
-		if (ret < 0) {
-			dev_err(&interface->dev, "%s: usb_submit_urb failed\n",
-				__func__);
-			goto err_destruct;
-		}
-	}
-
-	/* initialize device data based on product id: */
-	switch (product) {
-	case LINE6_DEVID_BASSPODXT:
-	case LINE6_DEVID_BASSPODXTLIVE:
-	case LINE6_DEVID_BASSPODXTPRO:
-	case LINE6_DEVID_POCKETPOD:
-	case LINE6_DEVID_PODX3:
-	case LINE6_DEVID_PODX3LIVE:
-	case LINE6_DEVID_PODXT:
-	case LINE6_DEVID_PODXTPRO:
-		ret = line6_pod_init(interface, (struct usb_line6_pod *)line6);
-		break;
-
-	case LINE6_DEVID_PODHD300:
-	case LINE6_DEVID_PODHD400:
-	case LINE6_DEVID_PODHD500:
-		ret = line6_podhd_init(interface,
-				       (struct usb_line6_podhd *)line6);
-		break;
-
-	case LINE6_DEVID_PODXTLIVE:
-		switch (interface_number) {
-		case PODXTLIVE_INTERFACE_POD:
-			ret =
-			    line6_pod_init(interface,
-					   (struct usb_line6_pod *)line6);
-			break;
-
-		case PODXTLIVE_INTERFACE_VARIAX:
-			ret =
-			    line6_variax_init(interface,
-					      (struct usb_line6_variax *)line6);
-			break;
-
-		default:
-			dev_err(&interface->dev,
-				"PODxt Live interface %d not supported\n",
-				interface_number);
-			ret = -ENODEV;
-		}
-
-		break;
-
-	case LINE6_DEVID_VARIAX:
-		ret =
-		    line6_variax_init(interface,
-				      (struct usb_line6_variax *)line6);
-		break;
-
-	case LINE6_DEVID_PODSTUDIO_GX:
-	case LINE6_DEVID_PODSTUDIO_UX1:
-	case LINE6_DEVID_PODSTUDIO_UX2:
-	case LINE6_DEVID_TONEPORT_GX:
-	case LINE6_DEVID_TONEPORT_UX1:
-	case LINE6_DEVID_TONEPORT_UX2:
-	case LINE6_DEVID_GUITARPORT:
-		ret =
-		    line6_toneport_init(interface,
-					(struct usb_line6_toneport *)line6);
-		break;
-
-	default:
-		MISSING_CASE;
-		ret = -ENODEV;
-	}
-
-	if (ret < 0)
-		goto err_destruct;
-
-	ret = sysfs_create_link(&interface->dev.kobj, &usbdev->dev.kobj,
-				"usb_device");
-	if (ret < 0)
-		goto err_destruct;
-
-	/* creation of additional special files should go here */
-
-	dev_info(&interface->dev, "Line6 %s now attached\n",
-		 line6->properties->name);
-
-	switch (product) {
-	case LINE6_DEVID_PODX3:
-	case LINE6_DEVID_PODX3LIVE:
-		dev_info(&interface->dev,
-			 "NOTE: the Line6 %s is detected, but not yet supported\n",
-			 line6->properties->name);
-	}
-
-	/* increment reference counters: */
-	usb_get_intf(interface);
-	usb_get_dev(usbdev);
-
-	return 0;
-
-err_destruct:
-	line6_destruct(interface);
-err_put:
-	return ret;
-}
-
-/*
-	Line6 device disconnected.
-*/
-static void line6_disconnect(struct usb_interface *interface)
-{
-	struct usb_line6 *line6;
-	struct usb_device *usbdev;
-	int interface_number;
-
-	if (interface == NULL)
-		return;
-	usbdev = interface_to_usbdev(interface);
-	if (usbdev == NULL)
-		return;
-
-	/* removal of additional special files should go here */
-
-	sysfs_remove_link(&interface->dev.kobj, "usb_device");
-
-	interface_number = interface->cur_altsetting->desc.bInterfaceNumber;
-	line6 = usb_get_intfdata(interface);
-
-	if (line6 != NULL) {
-		if (line6->urb_listen != NULL)
-			line6_stop_listen(line6);
-
-		if (usbdev != line6->usbdev)
-			dev_err(line6->ifcdev,
-				"driver bug: inconsistent usb device\n");
-
-		switch (le16_to_cpu(line6->usbdev->descriptor.idProduct)) {
-		case LINE6_DEVID_BASSPODXT:
-		case LINE6_DEVID_BASSPODXTLIVE:
-		case LINE6_DEVID_BASSPODXTPRO:
-		case LINE6_DEVID_POCKETPOD:
-		case LINE6_DEVID_PODX3:
-		case LINE6_DEVID_PODX3LIVE:
-		case LINE6_DEVID_PODXT:
-		case LINE6_DEVID_PODXTPRO:
-			line6_pod_disconnect(interface);
-			break;
-
-		case LINE6_DEVID_PODHD300:
-		case LINE6_DEVID_PODHD400:
-		case LINE6_DEVID_PODHD500:
-			line6_podhd_disconnect(interface);
-			break;
-
-		case LINE6_DEVID_PODXTLIVE:
-			switch (interface_number) {
-			case PODXTLIVE_INTERFACE_POD:
-				line6_pod_disconnect(interface);
-				break;
-
-			case PODXTLIVE_INTERFACE_VARIAX:
-				line6_variax_disconnect(interface);
-				break;
-			}
-
-			break;
-
-		case LINE6_DEVID_VARIAX:
-			line6_variax_disconnect(interface);
-			break;
-
-		case LINE6_DEVID_PODSTUDIO_GX:
-		case LINE6_DEVID_PODSTUDIO_UX1:
-		case LINE6_DEVID_PODSTUDIO_UX2:
-		case LINE6_DEVID_TONEPORT_GX:
-		case LINE6_DEVID_TONEPORT_UX1:
-		case LINE6_DEVID_TONEPORT_UX2:
-		case LINE6_DEVID_GUITARPORT:
-			line6_toneport_disconnect(interface);
-			break;
-
-		default:
-			MISSING_CASE;
-		}
-
-		dev_info(&interface->dev, "Line6 %s now disconnected\n",
-			 line6->properties->name);
-	}
-
-	line6_destruct(interface);
-
-	/* decrement reference counters: */
-	usb_put_intf(interface);
-	usb_put_dev(usbdev);
-}
-
-#ifdef CONFIG_PM
-
-/*
-	Suspend Line6 device.
-*/
-static int line6_suspend(struct usb_interface *interface, pm_message_t message)
-{
-	struct usb_line6 *line6 = usb_get_intfdata(interface);
-	struct snd_line6_pcm *line6pcm = line6->line6pcm;
-
-	snd_power_change_state(line6->card, SNDRV_CTL_POWER_D3hot);
-
-	if (line6->properties->capabilities & LINE6_BIT_CONTROL)
-		line6_stop_listen(line6);
-
-	if (line6pcm != NULL) {
-		snd_pcm_suspend_all(line6pcm->pcm);
-		line6_pcm_disconnect(line6pcm);
-		line6pcm->flags = 0;
-	}
-
-	return 0;
-}
-
-/*
-	Resume Line6 device.
-*/
-static int line6_resume(struct usb_interface *interface)
-{
-	struct usb_line6 *line6 = usb_get_intfdata(interface);
-
-	if (line6->properties->capabilities & LINE6_BIT_CONTROL)
-		line6_start_listen(line6);
-
-	snd_power_change_state(line6->card, SNDRV_CTL_POWER_D0);
-	return 0;
-}
-
-/*
-	Resume Line6 device after reset.
-*/
-static int line6_reset_resume(struct usb_interface *interface)
-{
-	struct usb_line6 *line6 = usb_get_intfdata(interface);
-
-	switch (le16_to_cpu(line6->usbdev->descriptor.idProduct)) {
-	case LINE6_DEVID_PODSTUDIO_GX:
-	case LINE6_DEVID_PODSTUDIO_UX1:
-	case LINE6_DEVID_PODSTUDIO_UX2:
-	case LINE6_DEVID_TONEPORT_GX:
-	case LINE6_DEVID_TONEPORT_UX1:
-	case LINE6_DEVID_TONEPORT_UX2:
-	case LINE6_DEVID_GUITARPORT:
-		line6_toneport_reset_resume((struct usb_line6_toneport *)line6);
-	}
-
-	return line6_resume(interface);
-}
-
-#endif /* CONFIG_PM */
-
-static struct usb_driver line6_driver = {
-	.name = DRIVER_NAME,
-	.probe = line6_probe,
-	.disconnect = line6_disconnect,
-#ifdef CONFIG_PM
-	.suspend = line6_suspend,
-	.resume = line6_resume,
-	.reset_resume = line6_reset_resume,
-#endif
-	.id_table = line6_id_table,
-};
-
-module_usb_driver(line6_driver);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
-MODULE_VERSION(DRIVER_VERSION);
diff --git a/drivers/staging/line6/driver.h b/drivers/staging/line6/driver.h
deleted file mode 100644
index 16e3fc2..0000000
--- a/drivers/staging/line6/driver.h
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * Line6 Linux USB driver - 0.9.1beta
- *
- * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
- *
- *	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, version 2.
- *
- */
-
-#ifndef DRIVER_H
-#define DRIVER_H
-
-#include <linux/spinlock.h>
-#include <linux/usb.h>
-#include <sound/core.h>
-
-#include "midi.h"
-
-#define DRIVER_NAME "line6usb"
-
-#define LINE6_TIMEOUT 1
-#define LINE6_BUFSIZE_LISTEN 32
-#define LINE6_MESSAGE_MAXLEN 256
-
-/*
-	Line6 MIDI control commands
-*/
-#define LINE6_PARAM_CHANGE   0xb0
-#define LINE6_PROGRAM_CHANGE 0xc0
-#define LINE6_SYSEX_BEGIN    0xf0
-#define LINE6_SYSEX_END      0xf7
-#define LINE6_RESET          0xff
-
-/*
-	MIDI channel for messages initiated by the host
-	(and eventually echoed back by the device)
-*/
-#define LINE6_CHANNEL_HOST   0x00
-
-/*
-	MIDI channel for messages initiated by the device
-*/
-#define LINE6_CHANNEL_DEVICE 0x02
-
-#define LINE6_CHANNEL_UNKNOWN 5	/* don't know yet what this is good for */
-
-#define LINE6_CHANNEL_MASK 0x0f
-
-#define MISSING_CASE	\
-	pr_err("line6usb driver bug: missing case in %s:%d\n", \
-		__FILE__, __LINE__)
-
-#define CHECK_RETURN(x)		\
-do {				\
-	err = x;		\
-	if (err < 0)		\
-		return err;	\
-} while (0)
-
-#define CHECK_STARTUP_PROGRESS(x, n)	\
-do {					\
-	if ((x) >= (n))			\
-		return;			\
-	x = (n);			\
-} while (0)
-
-extern const unsigned char line6_midi_id[3];
-
-static const int SYSEX_DATA_OFS = sizeof(line6_midi_id) + 3;
-static const int SYSEX_EXTRA_SIZE = sizeof(line6_midi_id) + 4;
-
-/**
-	 Common properties of Line6 devices.
-*/
-struct line6_properties {
-	/**
-		 Bit identifying this device in the line6usb driver.
-	*/
-	int device_bit;
-
-	/**
-		 Card id string (maximum 16 characters).
-		 This can be used to address the device in ALSA programs as
-		 "default:CARD=<id>"
-	*/
-	const char *id;
-
-	/**
-		 Card short name (maximum 32 characters).
-	*/
-	const char *name;
-
-	/**
-		 Bit vector defining this device's capabilities in the
-		 line6usb driver.
-	*/
-	int capabilities;
-};
-
-/**
-	 Common data shared by all Line6 devices.
-	 Corresponds to a pair of USB endpoints.
-*/
-struct usb_line6 {
-	/**
-		 USB device.
-	*/
-	struct usb_device *usbdev;
-
-	/**
-		 Product id.
-	*/
-	int product;
-
-	/**
-		 Properties.
-	*/
-	const struct line6_properties *properties;
-
-	/**
-		 Interface number.
-	*/
-	int interface_number;
-
-	/**
-		 Interval (ms).
-	*/
-	int interval;
-
-	/**
-		 Maximum size of USB packet.
-	*/
-	int max_packet_size;
-
-	/**
-		 Device representing the USB interface.
-	*/
-	struct device *ifcdev;
-
-	/**
-		 Line6 sound card data structure.
-		 Each device has at least MIDI or PCM.
-	*/
-	struct snd_card *card;
-
-	/**
-		 Line6 PCM device data structure.
-	*/
-	struct snd_line6_pcm *line6pcm;
-
-	/**
-		 Line6 MIDI device data structure.
-	*/
-	struct snd_line6_midi *line6midi;
-
-	/**
-		 USB endpoint for listening to control commands.
-	*/
-	int ep_control_read;
-
-	/**
-		 USB endpoint for writing control commands.
-	*/
-	int ep_control_write;
-
-	/**
-		 URB for listening to PODxt Pro control endpoint.
-	*/
-	struct urb *urb_listen;
-
-	/**
-		 Buffer for listening to PODxt Pro control endpoint.
-	*/
-	unsigned char *buffer_listen;
-
-	/**
-		 Buffer for message to be processed.
-	*/
-	unsigned char *buffer_message;
-
-	/**
-		 Length of message to be processed.
-	*/
-	int message_length;
-};
-
-extern char *line6_alloc_sysex_buffer(struct usb_line6 *line6, int code1,
-				      int code2, int size);
-extern ssize_t line6_nop_read(struct device *dev,
-			      struct device_attribute *attr, char *buf);
-extern int line6_read_data(struct usb_line6 *line6, int address, void *data,
-			   size_t datalen);
-extern int line6_read_serial_number(struct usb_line6 *line6,
-				    int *serial_number);
-extern int line6_send_program(struct usb_line6 *line6, u8 value);
-extern int line6_send_raw_message(struct usb_line6 *line6, const char *buffer,
-				  int size);
-extern int line6_send_raw_message_async(struct usb_line6 *line6,
-					const char *buffer, int size);
-extern int line6_send_sysex_message(struct usb_line6 *line6,
-				    const char *buffer, int size);
-extern ssize_t line6_set_raw(struct device *dev, struct device_attribute *attr,
-			     const char *buf, size_t count);
-extern void line6_start_timer(struct timer_list *timer, unsigned int msecs,
-			      void (*function)(unsigned long),
-			      unsigned long data);
-extern int line6_transmit_parameter(struct usb_line6 *line6, int param,
-				    u8 value);
-extern int line6_version_request_async(struct usb_line6 *line6);
-extern int line6_write_data(struct usb_line6 *line6, int address, void *data,
-			    size_t datalen);
-
-#endif
diff --git a/drivers/staging/line6/midi.h b/drivers/staging/line6/midi.h
deleted file mode 100644
index 78f903f..0000000
--- a/drivers/staging/line6/midi.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Line6 Linux USB driver - 0.9.1beta
- *
- * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
- *
- *	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, version 2.
- *
- */
-
-#ifndef MIDI_H
-#define MIDI_H
-
-#include <sound/rawmidi.h>
-
-#include "midibuf.h"
-
-#define MIDI_BUFFER_SIZE 1024
-
-struct snd_line6_midi {
-	/**
-		 Pointer back to the Line6 driver data structure.
-	*/
-	struct usb_line6 *line6;
-
-	/**
-		 MIDI substream for receiving (or NULL if not active).
-	*/
-	struct snd_rawmidi_substream *substream_receive;
-
-	/**
-		 MIDI substream for transmitting (or NULL if not active).
-	*/
-	struct snd_rawmidi_substream *substream_transmit;
-
-	/**
-		 Number of currently active MIDI send URBs.
-	*/
-	int num_active_send_urbs;
-
-	/**
-		 Spin lock to protect updates of send_urb.
-	*/
-	spinlock_t send_urb_lock;
-
-	/**
-		 Spin lock to protect MIDI buffer handling.
-	*/
-	spinlock_t midi_transmit_lock;
-
-	/**
-		 Wait queue for MIDI transmission.
-	*/
-	wait_queue_head_t send_wait;
-
-	/**
-		 Buffer for incoming MIDI stream.
-	*/
-	struct midi_buffer midibuf_in;
-
-	/**
-		 Buffer for outgoing MIDI stream.
-	*/
-	struct midi_buffer midibuf_out;
-};
-
-extern int line6_init_midi(struct usb_line6 *line6);
-extern void line6_midi_receive(struct usb_line6 *line6, unsigned char *data,
-			       int length);
-
-#endif
diff --git a/drivers/staging/line6/pcm.c b/drivers/staging/line6/pcm.c
deleted file mode 100644
index a3136b1..0000000
--- a/drivers/staging/line6/pcm.c
+++ /dev/null
@@ -1,576 +0,0 @@
-/*
- * Line6 Linux USB driver - 0.9.1beta
- *
- * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
- *
- *	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, version 2.
- *
- */
-
-#include <linux/slab.h>
-#include <sound/core.h>
-#include <sound/control.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-
-#include "audio.h"
-#include "capture.h"
-#include "driver.h"
-#include "playback.h"
-#include "pod.h"
-
-#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
-
-static struct snd_line6_pcm *dev2pcm(struct device *dev)
-{
-	struct usb_interface *interface = to_usb_interface(dev);
-	struct usb_line6 *line6 = usb_get_intfdata(interface);
-	struct snd_line6_pcm *line6pcm = line6->line6pcm;
-	return line6pcm;
-}
-
-/*
-	"read" request on "impulse_volume" special file.
-*/
-static ssize_t impulse_volume_show(struct device *dev,
-				   struct device_attribute *attr, char *buf)
-{
-	return sprintf(buf, "%d\n", dev2pcm(dev)->impulse_volume);
-}
-
-/*
-	"write" request on "impulse_volume" special file.
-*/
-static ssize_t impulse_volume_store(struct device *dev,
-				    struct device_attribute *attr,
-				    const char *buf, size_t count)
-{
-	struct snd_line6_pcm *line6pcm = dev2pcm(dev);
-	int value;
-	int ret;
-
-	ret = kstrtoint(buf, 10, &value);
-	if (ret < 0)
-		return ret;
-
-	line6pcm->impulse_volume = value;
-
-	if (value > 0)
-		line6_pcm_acquire(line6pcm, LINE6_BITS_PCM_IMPULSE);
-	else
-		line6_pcm_release(line6pcm, LINE6_BITS_PCM_IMPULSE);
-
-	return count;
-}
-static DEVICE_ATTR_RW(impulse_volume);
-
-/*
-	"read" request on "impulse_period" special file.
-*/
-static ssize_t impulse_period_show(struct device *dev,
-				   struct device_attribute *attr, char *buf)
-{
-	return sprintf(buf, "%d\n", dev2pcm(dev)->impulse_period);
-}
-
-/*
-	"write" request on "impulse_period" special file.
-*/
-static ssize_t impulse_period_store(struct device *dev,
-				    struct device_attribute *attr,
-				    const char *buf, size_t count)
-{
-	int value;
-	int ret;
-
-	ret = kstrtoint(buf, 10, &value);
-	if (ret < 0)
-		return ret;
-
-	dev2pcm(dev)->impulse_period = value;
-	return count;
-}
-static DEVICE_ATTR_RW(impulse_period);
-
-#endif
-
-static bool test_flags(unsigned long flags0, unsigned long flags1,
-		       unsigned long mask)
-{
-	return ((flags0 & mask) == 0) && ((flags1 & mask) != 0);
-}
-
-int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int channels)
-{
-	unsigned long flags_old, flags_new, flags_final;
-	int err;
-
-	do {
-		flags_old = ACCESS_ONCE(line6pcm->flags);
-		flags_new = flags_old | channels;
-	} while (cmpxchg(&line6pcm->flags, flags_old, flags_new) != flags_old);
-
-	flags_final = flags_old;
-
-	line6pcm->prev_fbuf = NULL;
-
-	if (test_flags(flags_old, flags_new, LINE6_BITS_CAPTURE_BUFFER)) {
-		/* Invoked multiple times in a row so allocate once only */
-		if (!line6pcm->buffer_in) {
-			line6pcm->buffer_in =
-				kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS *
-					line6pcm->max_packet_size, GFP_KERNEL);
-			if (!line6pcm->buffer_in) {
-				err = -ENOMEM;
-				goto pcm_acquire_error;
-			}
-
-			flags_final |= channels & LINE6_BITS_CAPTURE_BUFFER;
-		}
-	}
-
-	if (test_flags(flags_old, flags_new, LINE6_BITS_CAPTURE_STREAM)) {
-		/*
-		   Waiting for completion of active URBs in the stop handler is
-		   a bug, we therefore report an error if capturing is restarted
-		   too soon.
-		 */
-		if (line6pcm->active_urb_in | line6pcm->unlink_urb_in) {
-			dev_err(line6pcm->line6->ifcdev, "Device not yet ready\n");
-			return -EBUSY;
-		}
-
-		line6pcm->count_in = 0;
-		line6pcm->prev_fsize = 0;
-		err = line6_submit_audio_in_all_urbs(line6pcm);
-
-		if (err < 0)
-			goto pcm_acquire_error;
-
-		flags_final |= channels & LINE6_BITS_CAPTURE_STREAM;
-	}
-
-	if (test_flags(flags_old, flags_new, LINE6_BITS_PLAYBACK_BUFFER)) {
-		/* Invoked multiple times in a row so allocate once only */
-		if (!line6pcm->buffer_out) {
-			line6pcm->buffer_out =
-				kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS *
-					line6pcm->max_packet_size, GFP_KERNEL);
-			if (!line6pcm->buffer_out) {
-				err = -ENOMEM;
-				goto pcm_acquire_error;
-			}
-
-			flags_final |= channels & LINE6_BITS_PLAYBACK_BUFFER;
-		}
-	}
-
-	if (test_flags(flags_old, flags_new, LINE6_BITS_PLAYBACK_STREAM)) {
-		/*
-		  See comment above regarding PCM restart.
-		*/
-		if (line6pcm->active_urb_out | line6pcm->unlink_urb_out) {
-			dev_err(line6pcm->line6->ifcdev, "Device not yet ready\n");
-			return -EBUSY;
-		}
-
-		line6pcm->count_out = 0;
-		err = line6_submit_audio_out_all_urbs(line6pcm);
-
-		if (err < 0)
-			goto pcm_acquire_error;
-
-		flags_final |= channels & LINE6_BITS_PLAYBACK_STREAM;
-	}
-
-	return 0;
-
-pcm_acquire_error:
-	/*
-	   If not all requested resources/streams could be obtained, release
-	   those which were successfully obtained (if any).
-	*/
-	line6_pcm_release(line6pcm, flags_final & channels);
-	return err;
-}
-
-int line6_pcm_release(struct snd_line6_pcm *line6pcm, int channels)
-{
-	unsigned long flags_old, flags_new;
-
-	do {
-		flags_old = ACCESS_ONCE(line6pcm->flags);
-		flags_new = flags_old & ~channels;
-	} while (cmpxchg(&line6pcm->flags, flags_old, flags_new) != flags_old);
-
-	if (test_flags(flags_new, flags_old, LINE6_BITS_CAPTURE_STREAM))
-		line6_unlink_audio_in_urbs(line6pcm);
-
-	if (test_flags(flags_new, flags_old, LINE6_BITS_CAPTURE_BUFFER)) {
-		line6_wait_clear_audio_in_urbs(line6pcm);
-		line6_free_capture_buffer(line6pcm);
-	}
-
-	if (test_flags(flags_new, flags_old, LINE6_BITS_PLAYBACK_STREAM))
-		line6_unlink_audio_out_urbs(line6pcm);
-
-	if (test_flags(flags_new, flags_old, LINE6_BITS_PLAYBACK_BUFFER)) {
-		line6_wait_clear_audio_out_urbs(line6pcm);
-		line6_free_playback_buffer(line6pcm);
-	}
-
-	return 0;
-}
-
-/* trigger callback */
-int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd)
-{
-	struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
-	struct snd_pcm_substream *s;
-	int err;
-	unsigned long flags;
-
-	spin_lock_irqsave(&line6pcm->lock_trigger, flags);
-	clear_bit(LINE6_INDEX_PREPARED, &line6pcm->flags);
-
-	snd_pcm_group_for_each_entry(s, substream) {
-		switch (s->stream) {
-		case SNDRV_PCM_STREAM_PLAYBACK:
-			err = snd_line6_playback_trigger(line6pcm, cmd);
-
-			if (err < 0) {
-				spin_unlock_irqrestore(&line6pcm->lock_trigger,
-						       flags);
-				return err;
-			}
-
-			break;
-
-		case SNDRV_PCM_STREAM_CAPTURE:
-			err = snd_line6_capture_trigger(line6pcm, cmd);
-
-			if (err < 0) {
-				spin_unlock_irqrestore(&line6pcm->lock_trigger,
-						       flags);
-				return err;
-			}
-
-			break;
-
-		default:
-			dev_err(line6pcm->line6->ifcdev,
-				"Unknown stream direction %d\n", s->stream);
-		}
-	}
-
-	spin_unlock_irqrestore(&line6pcm->lock_trigger, flags);
-	return 0;
-}
-
-/* control info callback */
-static int snd_line6_control_playback_info(struct snd_kcontrol *kcontrol,
-					   struct snd_ctl_elem_info *uinfo)
-{
-	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
-	uinfo->count = 2;
-	uinfo->value.integer.min = 0;
-	uinfo->value.integer.max = 256;
-	return 0;
-}
-
-/* control get callback */
-static int snd_line6_control_playback_get(struct snd_kcontrol *kcontrol,
-					  struct snd_ctl_elem_value *ucontrol)
-{
-	int i;
-	struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
-
-	for (i = 2; i--;)
-		ucontrol->value.integer.value[i] = line6pcm->volume_playback[i];
-
-	return 0;
-}
-
-/* control put callback */
-static int snd_line6_control_playback_put(struct snd_kcontrol *kcontrol,
-					  struct snd_ctl_elem_value *ucontrol)
-{
-	int i, changed = 0;
-	struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
-
-	for (i = 2; i--;)
-		if (line6pcm->volume_playback[i] !=
-		    ucontrol->value.integer.value[i]) {
-			line6pcm->volume_playback[i] =
-			    ucontrol->value.integer.value[i];
-			changed = 1;
-		}
-
-	return changed;
-}
-
-/* control definition */
-static struct snd_kcontrol_new line6_control_playback = {
-	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-	.name = "PCM Playback Volume",
-	.index = 0,
-	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
-	.info = snd_line6_control_playback_info,
-	.get = snd_line6_control_playback_get,
-	.put = snd_line6_control_playback_put
-};
-
-/*
-	Cleanup the PCM device.
-*/
-static void line6_cleanup_pcm(struct snd_pcm *pcm)
-{
-	int i;
-	struct snd_line6_pcm *line6pcm = snd_pcm_chip(pcm);
-
-#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
-	device_remove_file(line6pcm->line6->ifcdev, &dev_attr_impulse_volume);
-	device_remove_file(line6pcm->line6->ifcdev, &dev_attr_impulse_period);
-#endif
-
-	for (i = LINE6_ISO_BUFFERS; i--;) {
-		if (line6pcm->urb_audio_out[i]) {
-			usb_kill_urb(line6pcm->urb_audio_out[i]);
-			usb_free_urb(line6pcm->urb_audio_out[i]);
-		}
-		if (line6pcm->urb_audio_in[i]) {
-			usb_kill_urb(line6pcm->urb_audio_in[i]);
-			usb_free_urb(line6pcm->urb_audio_in[i]);
-		}
-	}
-}
-
-/* create a PCM device */
-static int snd_line6_new_pcm(struct snd_line6_pcm *line6pcm)
-{
-	struct snd_pcm *pcm;
-	int err;
-
-	err = snd_pcm_new(line6pcm->line6->card,
-			  (char *)line6pcm->line6->properties->name,
-			  0, 1, 1, &pcm);
-	if (err < 0)
-		return err;
-
-	pcm->private_data = line6pcm;
-	pcm->private_free = line6_cleanup_pcm;
-	line6pcm->pcm = pcm;
-	strcpy(pcm->name, line6pcm->line6->properties->name);
-
-	/* set operators */
-	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
-			&snd_line6_playback_ops);
-	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_line6_capture_ops);
-
-	/* pre-allocation of buffers */
-	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
-					      snd_dma_continuous_data
-					      (GFP_KERNEL), 64 * 1024,
-					      128 * 1024);
-
-	return 0;
-}
-
-/* PCM device destructor */
-static int snd_line6_pcm_free(struct snd_device *device)
-{
-	return 0;
-}
-
-/*
-	Stop substream if still running.
-*/
-static void pcm_disconnect_substream(struct snd_pcm_substream *substream)
-{
-	if (substream->runtime && snd_pcm_running(substream)) {
-		snd_pcm_stream_lock_irq(substream);
-		snd_pcm_stop(substream, SNDRV_PCM_STATE_DISCONNECTED);
-		snd_pcm_stream_unlock_irq(substream);
-	}
-}
-
-/*
-	Stop PCM stream.
-*/
-void line6_pcm_disconnect(struct snd_line6_pcm *line6pcm)
-{
-	pcm_disconnect_substream(get_substream
-				 (line6pcm, SNDRV_PCM_STREAM_CAPTURE));
-	pcm_disconnect_substream(get_substream
-				 (line6pcm, SNDRV_PCM_STREAM_PLAYBACK));
-	line6_unlink_wait_clear_audio_out_urbs(line6pcm);
-	line6_unlink_wait_clear_audio_in_urbs(line6pcm);
-}
-
-/*
-	Create and register the PCM device and mixer entries.
-	Create URBs for playback and capture.
-*/
-int line6_init_pcm(struct usb_line6 *line6,
-		   struct line6_pcm_properties *properties)
-{
-	static struct snd_device_ops pcm_ops = {
-		.dev_free = snd_line6_pcm_free,
-	};
-
-	int err;
-	int ep_read = 0, ep_write = 0;
-	struct snd_line6_pcm *line6pcm;
-
-	if (!(line6->properties->capabilities & LINE6_BIT_PCM))
-		return 0;	/* skip PCM initialization and report success */
-
-	/* initialize PCM subsystem based on product id: */
-	switch (line6->product) {
-	case LINE6_DEVID_BASSPODXT:
-	case LINE6_DEVID_BASSPODXTLIVE:
-	case LINE6_DEVID_BASSPODXTPRO:
-	case LINE6_DEVID_PODXT:
-	case LINE6_DEVID_PODXTLIVE:
-	case LINE6_DEVID_PODXTPRO:
-	case LINE6_DEVID_PODHD300:
-	case LINE6_DEVID_PODHD400:
-		ep_read = 0x82;
-		ep_write = 0x01;
-		break;
-
-	case LINE6_DEVID_PODHD500:
-	case LINE6_DEVID_PODX3:
-	case LINE6_DEVID_PODX3LIVE:
-		ep_read = 0x86;
-		ep_write = 0x02;
-		break;
-
-	case LINE6_DEVID_POCKETPOD:
-		ep_read = 0x82;
-		ep_write = 0x02;
-		break;
-
-	case LINE6_DEVID_GUITARPORT:
-	case LINE6_DEVID_PODSTUDIO_GX:
-	case LINE6_DEVID_PODSTUDIO_UX1:
-	case LINE6_DEVID_PODSTUDIO_UX2:
-	case LINE6_DEVID_TONEPORT_GX:
-	case LINE6_DEVID_TONEPORT_UX1:
-	case LINE6_DEVID_TONEPORT_UX2:
-		ep_read = 0x82;
-		ep_write = 0x01;
-		break;
-
-	/* this is for interface_number == 1:
-	case LINE6_DEVID_TONEPORT_UX2:
-	case LINE6_DEVID_PODSTUDIO_UX2:
-		ep_read  = 0x87;
-		ep_write = 0x00;
-		break; */
-
-	default:
-		MISSING_CASE;
-	}
-
-	line6pcm = kzalloc(sizeof(*line6pcm), GFP_KERNEL);
-
-	if (line6pcm == NULL)
-		return -ENOMEM;
-
-	line6pcm->volume_playback[0] = line6pcm->volume_playback[1] = 255;
-	line6pcm->volume_monitor = 255;
-	line6pcm->line6 = line6;
-	line6pcm->ep_audio_read = ep_read;
-	line6pcm->ep_audio_write = ep_write;
-
-	/* Read and write buffers are sized identically, so choose minimum */
-	line6pcm->max_packet_size = min(
-			usb_maxpacket(line6->usbdev,
-				usb_rcvisocpipe(line6->usbdev, ep_read), 0),
-			usb_maxpacket(line6->usbdev,
-				usb_sndisocpipe(line6->usbdev, ep_write), 1));
-
-	line6pcm->properties = properties;
-	line6->line6pcm = line6pcm;
-
-	/* PCM device: */
-	err = snd_device_new(line6->card, SNDRV_DEV_PCM, line6, &pcm_ops);
-	if (err < 0)
-		return err;
-
-	err = snd_line6_new_pcm(line6pcm);
-	if (err < 0)
-		return err;
-
-	spin_lock_init(&line6pcm->lock_audio_out);
-	spin_lock_init(&line6pcm->lock_audio_in);
-	spin_lock_init(&line6pcm->lock_trigger);
-
-	err = line6_create_audio_out_urbs(line6pcm);
-	if (err < 0)
-		return err;
-
-	err = line6_create_audio_in_urbs(line6pcm);
-	if (err < 0)
-		return err;
-
-	/* mixer: */
-	err =
-	    snd_ctl_add(line6->card,
-			snd_ctl_new1(&line6_control_playback, line6pcm));
-	if (err < 0)
-		return err;
-
-#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
-	/* impulse response test: */
-	err = device_create_file(line6->ifcdev, &dev_attr_impulse_volume);
-	if (err < 0)
-		return err;
-
-	err = device_create_file(line6->ifcdev, &dev_attr_impulse_period);
-	if (err < 0)
-		return err;
-
-	line6pcm->impulse_period = LINE6_IMPULSE_DEFAULT_PERIOD;
-#endif
-
-	return 0;
-}
-
-/* prepare pcm callback */
-int snd_line6_prepare(struct snd_pcm_substream *substream)
-{
-	struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
-
-	switch (substream->stream) {
-	case SNDRV_PCM_STREAM_PLAYBACK:
-		if ((line6pcm->flags & LINE6_BITS_PLAYBACK_STREAM) == 0)
-			line6_unlink_wait_clear_audio_out_urbs(line6pcm);
-
-		break;
-
-	case SNDRV_PCM_STREAM_CAPTURE:
-		if ((line6pcm->flags & LINE6_BITS_CAPTURE_STREAM) == 0)
-			line6_unlink_wait_clear_audio_in_urbs(line6pcm);
-
-		break;
-
-	default:
-		MISSING_CASE;
-	}
-
-	if (!test_and_set_bit(LINE6_INDEX_PREPARED, &line6pcm->flags)) {
-		line6pcm->count_out = 0;
-		line6pcm->pos_out = 0;
-		line6pcm->pos_out_done = 0;
-		line6pcm->bytes_out = 0;
-		line6pcm->count_in = 0;
-		line6pcm->pos_in_done = 0;
-		line6pcm->bytes_in = 0;
-	}
-
-	return 0;
-}
diff --git a/drivers/staging/line6/pcm.h b/drivers/staging/line6/pcm.h
deleted file mode 100644
index 6aa0d46..0000000
--- a/drivers/staging/line6/pcm.h
+++ /dev/null
@@ -1,382 +0,0 @@
-/*
- * Line6 Linux USB driver - 0.9.1beta
- *
- * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
- *
- *	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, version 2.
- *
- */
-
-/*
-	PCM interface to POD series devices.
-*/
-
-#ifndef PCM_H
-#define PCM_H
-
-#include <sound/pcm.h>
-
-#include "driver.h"
-#include "usbdefs.h"
-
-/* number of URBs */
-#define LINE6_ISO_BUFFERS	2
-
-/*
-	number of USB frames per URB
-	The Line6 Windows driver always transmits two frames per packet, but
-	the Linux driver performs significantly better (i.e., lower latency)
-	with only one frame per packet.
-*/
-#define LINE6_ISO_PACKETS	1
-
-/* in a "full speed" device (such as the PODxt Pro) this means 1ms */
-#define LINE6_ISO_INTERVAL	1
-
-#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
-#define LINE6_IMPULSE_DEFAULT_PERIOD 100
-#endif
-
-/*
-	Get substream from Line6 PCM data structure
-*/
-#define get_substream(line6pcm, stream)	\
-		(line6pcm->pcm->streams[stream].substream)
-
-/*
-	PCM mode bits.
-
-	There are several features of the Line6 USB driver which require PCM
-	data to be exchanged with the device:
-	*) PCM playback and capture via ALSA
-	*) software monitoring (for devices without hardware monitoring)
-	*) optional impulse response measurement
-	However, from the device's point of view, there is just a single
-	capture and playback stream, which must be shared between these
-	subsystems. It is therefore necessary to maintain the state of the
-	subsystems with respect to PCM usage. We define several constants of
-	the form LINE6_BIT_PCM_<subsystem>_<direction>_<resource> with the
-	following meanings:
-	*) <subsystem> is one of
-	-) ALSA: PCM playback and capture via ALSA
-	-) MONITOR: software monitoring
-	-) IMPULSE: optional impulse response measurement
-	*) <direction> is one of
-	-) PLAYBACK: audio output (from host to device)
-	-) CAPTURE: audio input (from device to host)
-	*) <resource> is one of
-	-) BUFFER: buffer required by PCM data stream
-	-) STREAM: actual PCM data stream
-
-	The subsystems call line6_pcm_acquire() to acquire the (shared)
-	resources needed for a particular operation (e.g., allocate the buffer
-	for ALSA playback or start the capture stream for software monitoring).
-	When a resource is no longer needed, it is released by calling
-	line6_pcm_release(). Buffer allocation and stream startup are handled
-	separately to allow the ALSA kernel driver to perform them at
-	appropriate places (since the callback which starts a PCM stream is not
-	allowed to sleep).
-*/
-enum {
-	/* individual bit indices: */
-	LINE6_INDEX_PCM_ALSA_PLAYBACK_BUFFER,
-	LINE6_INDEX_PCM_ALSA_PLAYBACK_STREAM,
-	LINE6_INDEX_PCM_ALSA_CAPTURE_BUFFER,
-	LINE6_INDEX_PCM_ALSA_CAPTURE_STREAM,
-	LINE6_INDEX_PCM_MONITOR_PLAYBACK_BUFFER,
-	LINE6_INDEX_PCM_MONITOR_PLAYBACK_STREAM,
-	LINE6_INDEX_PCM_MONITOR_CAPTURE_BUFFER,
-	LINE6_INDEX_PCM_MONITOR_CAPTURE_STREAM,
-#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
-	LINE6_INDEX_PCM_IMPULSE_PLAYBACK_BUFFER,
-	LINE6_INDEX_PCM_IMPULSE_PLAYBACK_STREAM,
-	LINE6_INDEX_PCM_IMPULSE_CAPTURE_BUFFER,
-	LINE6_INDEX_PCM_IMPULSE_CAPTURE_STREAM,
-#endif
-	LINE6_INDEX_PAUSE_PLAYBACK,
-	LINE6_INDEX_PREPARED,
-
-	/* individual bit masks: */
-	LINE6_BIT(PCM_ALSA_PLAYBACK_BUFFER),
-	LINE6_BIT(PCM_ALSA_PLAYBACK_STREAM),
-	LINE6_BIT(PCM_ALSA_CAPTURE_BUFFER),
-	LINE6_BIT(PCM_ALSA_CAPTURE_STREAM),
-	LINE6_BIT(PCM_MONITOR_PLAYBACK_BUFFER),
-	LINE6_BIT(PCM_MONITOR_PLAYBACK_STREAM),
-	LINE6_BIT(PCM_MONITOR_CAPTURE_BUFFER),
-	LINE6_BIT(PCM_MONITOR_CAPTURE_STREAM),
-#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
-	LINE6_BIT(PCM_IMPULSE_PLAYBACK_BUFFER),
-	LINE6_BIT(PCM_IMPULSE_PLAYBACK_STREAM),
-	LINE6_BIT(PCM_IMPULSE_CAPTURE_BUFFER),
-	LINE6_BIT(PCM_IMPULSE_CAPTURE_STREAM),
-#endif
-	LINE6_BIT(PAUSE_PLAYBACK),
-	LINE6_BIT(PREPARED),
-
-	/* combined bit masks (by operation): */
-	LINE6_BITS_PCM_ALSA_BUFFER =
-	    LINE6_BIT_PCM_ALSA_PLAYBACK_BUFFER |
-	    LINE6_BIT_PCM_ALSA_CAPTURE_BUFFER,
-
-	LINE6_BITS_PCM_ALSA_STREAM =
-	    LINE6_BIT_PCM_ALSA_PLAYBACK_STREAM |
-	    LINE6_BIT_PCM_ALSA_CAPTURE_STREAM,
-
-	LINE6_BITS_PCM_MONITOR =
-	    LINE6_BIT_PCM_MONITOR_PLAYBACK_BUFFER |
-	    LINE6_BIT_PCM_MONITOR_PLAYBACK_STREAM |
-	    LINE6_BIT_PCM_MONITOR_CAPTURE_BUFFER |
-	    LINE6_BIT_PCM_MONITOR_CAPTURE_STREAM,
-
-#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
-	LINE6_BITS_PCM_IMPULSE =
-	    LINE6_BIT_PCM_IMPULSE_PLAYBACK_BUFFER |
-	    LINE6_BIT_PCM_IMPULSE_PLAYBACK_STREAM |
-	    LINE6_BIT_PCM_IMPULSE_CAPTURE_BUFFER |
-	    LINE6_BIT_PCM_IMPULSE_CAPTURE_STREAM,
-#endif
-
-	/* combined bit masks (by direction): */
-	LINE6_BITS_PLAYBACK_BUFFER =
-#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
-	    LINE6_BIT_PCM_IMPULSE_PLAYBACK_BUFFER |
-#endif
-	    LINE6_BIT_PCM_ALSA_PLAYBACK_BUFFER |
-	    LINE6_BIT_PCM_MONITOR_PLAYBACK_BUFFER ,
-
-	LINE6_BITS_PLAYBACK_STREAM =
-#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
-	    LINE6_BIT_PCM_IMPULSE_PLAYBACK_STREAM |
-#endif
-	    LINE6_BIT_PCM_ALSA_PLAYBACK_STREAM |
-	    LINE6_BIT_PCM_MONITOR_PLAYBACK_STREAM ,
-
-	LINE6_BITS_CAPTURE_BUFFER =
-#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
-	    LINE6_BIT_PCM_IMPULSE_CAPTURE_BUFFER |
-#endif
-	    LINE6_BIT_PCM_ALSA_CAPTURE_BUFFER |
-	    LINE6_BIT_PCM_MONITOR_CAPTURE_BUFFER ,
-
-	LINE6_BITS_CAPTURE_STREAM =
-#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
-	    LINE6_BIT_PCM_IMPULSE_CAPTURE_STREAM |
-#endif
-	    LINE6_BIT_PCM_ALSA_CAPTURE_STREAM |
-	    LINE6_BIT_PCM_MONITOR_CAPTURE_STREAM,
-
-	LINE6_BITS_STREAM =
-	    LINE6_BITS_PLAYBACK_STREAM |
-	    LINE6_BITS_CAPTURE_STREAM
-};
-
-struct line6_pcm_properties {
-	struct snd_pcm_hardware snd_line6_playback_hw, snd_line6_capture_hw;
-	struct snd_pcm_hw_constraint_ratdens snd_line6_rates;
-	int bytes_per_frame;
-};
-
-struct snd_line6_pcm {
-	/**
-		 Pointer back to the Line6 driver data structure.
-	*/
-	struct usb_line6 *line6;
-
-	/**
-		 Properties.
-	*/
-	struct line6_pcm_properties *properties;
-
-	/**
-		 ALSA pcm stream
-	*/
-	struct snd_pcm *pcm;
-
-	/**
-		 URBs for audio playback.
-	*/
-	struct urb *urb_audio_out[LINE6_ISO_BUFFERS];
-
-	/**
-		 URBs for audio capture.
-	*/
-	struct urb *urb_audio_in[LINE6_ISO_BUFFERS];
-
-	/**
-		 Temporary buffer for playback.
-		 Since the packet size is not known in advance, this buffer is
-		 large enough to store maximum size packets.
-	*/
-	unsigned char *buffer_out;
-
-	/**
-		 Temporary buffer for capture.
-		 Since the packet size is not known in advance, this buffer is
-		 large enough to store maximum size packets.
-	*/
-	unsigned char *buffer_in;
-
-	/**
-		 Previously captured frame (for software monitoring).
-	*/
-	unsigned char *prev_fbuf;
-
-	/**
-		 Size of previously captured frame (for software monitoring).
-	*/
-	int prev_fsize;
-
-	/**
-		 Free frame position in the playback buffer.
-	*/
-	snd_pcm_uframes_t pos_out;
-
-	/**
-		 Count processed bytes for playback.
-		 This is modulo period size (to determine when a period is
-		 finished).
-	*/
-	unsigned bytes_out;
-
-	/**
-		 Counter to create desired playback sample rate.
-	*/
-	unsigned count_out;
-
-	/**
-		 Playback period size in bytes
-	*/
-	unsigned period_out;
-
-	/**
-		 Processed frame position in the playback buffer.
-		 The contents of the output ring buffer have been consumed by
-		 the USB subsystem (i.e., sent to the USB device) up to this
-		 position.
-	*/
-	snd_pcm_uframes_t pos_out_done;
-
-	/**
-		 Count processed bytes for capture.
-		 This is modulo period size (to determine when a period is
-		 finished).
-	*/
-	unsigned bytes_in;
-
-	/**
-		 Counter to create desired capture sample rate.
-	*/
-	unsigned count_in;
-
-	/**
-		 Capture period size in bytes
-	*/
-	unsigned period_in;
-
-	/**
-		 Processed frame position in the capture buffer.
-		 The contents of the output ring buffer have been consumed by
-		 the USB subsystem (i.e., sent to the USB device) up to this
-		 position.
-	*/
-	snd_pcm_uframes_t pos_in_done;
-
-	/**
-		 Bit mask of active playback URBs.
-	*/
-	unsigned long active_urb_out;
-
-	/**
-		 Maximum size of USB packet.
-	*/
-	int max_packet_size;
-
-	/**
-		 USB endpoint for listening to audio data.
-	*/
-	int ep_audio_read;
-
-	/**
-		 USB endpoint for writing audio data.
-	*/
-	int ep_audio_write;
-
-	/**
-		 Bit mask of active capture URBs.
-	*/
-	unsigned long active_urb_in;
-
-	/**
-		 Bit mask of playback URBs currently being unlinked.
-	*/
-	unsigned long unlink_urb_out;
-
-	/**
-		 Bit mask of capture URBs currently being unlinked.
-	*/
-	unsigned long unlink_urb_in;
-
-	/**
-		 Spin lock to protect updates of the playback buffer positions (not
-		 contents!)
-	*/
-	spinlock_t lock_audio_out;
-
-	/**
-		 Spin lock to protect updates of the capture buffer positions (not
-		 contents!)
-	*/
-	spinlock_t lock_audio_in;
-
-	/**
-		 Spin lock to protect trigger.
-	*/
-	spinlock_t lock_trigger;
-
-	/**
-		 PCM playback volume (left and right).
-	*/
-	int volume_playback[2];
-
-	/**
-		 PCM monitor volume.
-	*/
-	int volume_monitor;
-
-#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
-	/**
-		 Volume of impulse response test signal (if zero, test is disabled).
-	*/
-	int impulse_volume;
-
-	/**
-		 Period of impulse response test signal.
-	*/
-	int impulse_period;
-
-	/**
-		 Counter for impulse response test signal.
-	*/
-	int impulse_count;
-#endif
-
-	/**
-		 Several status bits (see LINE6_BIT_*).
-	*/
-	unsigned long flags;
-
-	int last_frame_in, last_frame_out;
-};
-
-extern int line6_init_pcm(struct usb_line6 *line6,
-			  struct line6_pcm_properties *properties);
-extern int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd);
-extern int snd_line6_prepare(struct snd_pcm_substream *substream);
-extern void line6_pcm_disconnect(struct snd_line6_pcm *line6pcm);
-extern int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int channels);
-extern int line6_pcm_release(struct snd_line6_pcm *line6pcm, int channels);
-
-#endif
diff --git a/drivers/staging/line6/playback.c b/drivers/staging/line6/playback.c
deleted file mode 100644
index 2ca8900..0000000
--- a/drivers/staging/line6/playback.c
+++ /dev/null
@@ -1,592 +0,0 @@
-/*
- * Line6 Linux USB driver - 0.9.1beta
- *
- * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
- *
- *	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, version 2.
- *
- */
-
-#include <linux/slab.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-
-#include "audio.h"
-#include "capture.h"
-#include "driver.h"
-#include "pcm.h"
-#include "pod.h"
-#include "playback.h"
-
-/*
-	Software stereo volume control.
-*/
-static void change_volume(struct urb *urb_out, int volume[],
-			  int bytes_per_frame)
-{
-	int chn = 0;
-
-	if (volume[0] == 256 && volume[1] == 256)
-		return;		/* maximum volume - no change */
-
-	if (bytes_per_frame == 4) {
-		short *p, *buf_end;
-
-		p = (short *)urb_out->transfer_buffer;
-		buf_end = p + urb_out->transfer_buffer_length / sizeof(*p);
-
-		for (; p < buf_end; ++p) {
-			*p = (*p * volume[chn & 1]) >> 8;
-			++chn;
-		}
-	} else if (bytes_per_frame == 6) {
-		unsigned char *p, *buf_end;
-
-		p = (unsigned char *)urb_out->transfer_buffer;
-		buf_end = p + urb_out->transfer_buffer_length;
-
-		for (; p < buf_end; p += 3) {
-			int val;
-
-			val = p[0] + (p[1] << 8) + ((signed char)p[2] << 16);
-			val = (val * volume[chn & 1]) >> 8;
-			p[0] = val;
-			p[1] = val >> 8;
-			p[2] = val >> 16;
-			++chn;
-		}
-	}
-}
-
-#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
-
-/*
-	Create signal for impulse response test.
-*/
-static void create_impulse_test_signal(struct snd_line6_pcm *line6pcm,
-				       struct urb *urb_out, int bytes_per_frame)
-{
-	int frames = urb_out->transfer_buffer_length / bytes_per_frame;
-
-	if (bytes_per_frame == 4) {
-		int i;
-		short *pi = (short *)line6pcm->prev_fbuf;
-		short *po = (short *)urb_out->transfer_buffer;
-
-		for (i = 0; i < frames; ++i) {
-			po[0] = pi[0];
-			po[1] = 0;
-			pi += 2;
-			po += 2;
-		}
-	} else if (bytes_per_frame == 6) {
-		int i, j;
-		unsigned char *pi = line6pcm->prev_fbuf;
-		unsigned char *po = urb_out->transfer_buffer;
-
-		for (i = 0; i < frames; ++i) {
-			for (j = 0; j < bytes_per_frame / 2; ++j)
-				po[j] = pi[j];
-
-			for (; j < bytes_per_frame; ++j)
-				po[j] = 0;
-
-			pi += bytes_per_frame;
-			po += bytes_per_frame;
-		}
-	}
-	if (--line6pcm->impulse_count <= 0) {
-		((unsigned char *)(urb_out->transfer_buffer))[bytes_per_frame -
-							      1] =
-		    line6pcm->impulse_volume;
-		line6pcm->impulse_count = line6pcm->impulse_period;
-	}
-}
-
-#endif
-
-/*
-	Add signal to buffer for software monitoring.
-*/
-static void add_monitor_signal(struct urb *urb_out, unsigned char *signal,
-			       int volume, int bytes_per_frame)
-{
-	if (volume == 0)
-		return;		/* zero volume - no change */
-
-	if (bytes_per_frame == 4) {
-		short *pi, *po, *buf_end;
-
-		pi = (short *)signal;
-		po = (short *)urb_out->transfer_buffer;
-		buf_end = po + urb_out->transfer_buffer_length / sizeof(*po);
-
-		for (; po < buf_end; ++pi, ++po)
-			*po += (*pi * volume) >> 8;
-	}
-
-	/*
-	   We don't need to handle devices with 6 bytes per frame here
-	   since they all support hardware monitoring.
-	 */
-}
-
-/*
-	Find a free URB, prepare audio data, and submit URB.
-*/
-static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm)
-{
-	int index;
-	unsigned long flags;
-	int i, urb_size, urb_frames;
-	int ret;
-	const int bytes_per_frame = line6pcm->properties->bytes_per_frame;
-	const int frame_increment =
-	    line6pcm->properties->snd_line6_rates.rats[0].num_min;
-	const int frame_factor =
-	    line6pcm->properties->snd_line6_rates.rats[0].den *
-	    (USB_INTERVALS_PER_SECOND / LINE6_ISO_INTERVAL);
-	struct urb *urb_out;
-
-	spin_lock_irqsave(&line6pcm->lock_audio_out, flags);
-	index =
-	    find_first_zero_bit(&line6pcm->active_urb_out, LINE6_ISO_BUFFERS);
-
-	if (index < 0 || index >= LINE6_ISO_BUFFERS) {
-		spin_unlock_irqrestore(&line6pcm->lock_audio_out, flags);
-		dev_err(line6pcm->line6->ifcdev, "no free URB found\n");
-		return -EINVAL;
-	}
-
-	urb_out = line6pcm->urb_audio_out[index];
-	urb_size = 0;
-
-	for (i = 0; i < LINE6_ISO_PACKETS; ++i) {
-		/* compute frame size for given sampling rate */
-		int fsize = 0;
-		struct usb_iso_packet_descriptor *fout =
-		    &urb_out->iso_frame_desc[i];
-
-		if (line6pcm->flags & LINE6_BITS_CAPTURE_STREAM)
-			fsize = line6pcm->prev_fsize;
-
-		if (fsize == 0) {
-			int n;
-
-			line6pcm->count_out += frame_increment;
-			n = line6pcm->count_out / frame_factor;
-			line6pcm->count_out -= n * frame_factor;
-			fsize = n * bytes_per_frame;
-		}
-
-		fout->offset = urb_size;
-		fout->length = fsize;
-		urb_size += fsize;
-	}
-
-	if (urb_size == 0) {
-		/* can't determine URB size */
-		spin_unlock_irqrestore(&line6pcm->lock_audio_out, flags);
-		dev_err(line6pcm->line6->ifcdev, "driver bug: urb_size = 0\n");
-		return -EINVAL;
-	}
-
-	urb_frames = urb_size / bytes_per_frame;
-	urb_out->transfer_buffer =
-	    line6pcm->buffer_out +
-	    index * LINE6_ISO_PACKETS * line6pcm->max_packet_size;
-	urb_out->transfer_buffer_length = urb_size;
-	urb_out->context = line6pcm;
-
-	if (test_bit(LINE6_INDEX_PCM_ALSA_PLAYBACK_STREAM, &line6pcm->flags) &&
-	    !test_bit(LINE6_INDEX_PAUSE_PLAYBACK, &line6pcm->flags)) {
-		struct snd_pcm_runtime *runtime =
-		    get_substream(line6pcm, SNDRV_PCM_STREAM_PLAYBACK)->runtime;
-
-		if (line6pcm->pos_out + urb_frames > runtime->buffer_size) {
-			/*
-			   The transferred area goes over buffer boundary,
-			   copy the data to the temp buffer.
-			 */
-			int len;
-
-			len = runtime->buffer_size - line6pcm->pos_out;
-
-			if (len > 0) {
-				memcpy(urb_out->transfer_buffer,
-				       runtime->dma_area +
-				       line6pcm->pos_out * bytes_per_frame,
-				       len * bytes_per_frame);
-				memcpy(urb_out->transfer_buffer +
-				       len * bytes_per_frame, runtime->dma_area,
-				       (urb_frames - len) * bytes_per_frame);
-			} else
-				dev_err(line6pcm->line6->ifcdev, "driver bug: len = %d\n",
-					len);
-		} else {
-			memcpy(urb_out->transfer_buffer,
-			       runtime->dma_area +
-			       line6pcm->pos_out * bytes_per_frame,
-			       urb_out->transfer_buffer_length);
-		}
-
-		line6pcm->pos_out += urb_frames;
-		if (line6pcm->pos_out >= runtime->buffer_size)
-			line6pcm->pos_out -= runtime->buffer_size;
-	} else {
-		memset(urb_out->transfer_buffer, 0,
-		       urb_out->transfer_buffer_length);
-	}
-
-	change_volume(urb_out, line6pcm->volume_playback, bytes_per_frame);
-
-	if (line6pcm->prev_fbuf != NULL) {
-#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
-		if (line6pcm->flags & LINE6_BITS_PCM_IMPULSE) {
-			create_impulse_test_signal(line6pcm, urb_out,
-						   bytes_per_frame);
-			if (line6pcm->flags &
-			    LINE6_BIT_PCM_ALSA_CAPTURE_STREAM) {
-				line6_capture_copy(line6pcm,
-						   urb_out->transfer_buffer,
-						   urb_out->
-						   transfer_buffer_length);
-				line6_capture_check_period(line6pcm,
-					urb_out->transfer_buffer_length);
-			}
-		} else {
-#endif
-			if (!
-			    (line6pcm->line6->
-			     properties->capabilities & LINE6_BIT_HWMON)
-			    && (line6pcm->flags & LINE6_BITS_PLAYBACK_STREAM)
-			    && (line6pcm->flags & LINE6_BITS_CAPTURE_STREAM))
-				add_monitor_signal(urb_out, line6pcm->prev_fbuf,
-						   line6pcm->volume_monitor,
-						   bytes_per_frame);
-#ifdef CONFIG_LINE6_USB_IMPULSE_RESPONSE
-		}
-#endif
-	}
-
-	ret = usb_submit_urb(urb_out, GFP_ATOMIC);
-
-	if (ret == 0)
-		set_bit(index, &line6pcm->active_urb_out);
-	else
-		dev_err(line6pcm->line6->ifcdev,
-			"URB out #%d submission failed (%d)\n", index, ret);
-
-	spin_unlock_irqrestore(&line6pcm->lock_audio_out, flags);
-	return 0;
-}
-
-/*
-	Submit all currently available playback URBs.
-*/
-int line6_submit_audio_out_all_urbs(struct snd_line6_pcm *line6pcm)
-{
-	int ret, i;
-
-	for (i = 0; i < LINE6_ISO_BUFFERS; ++i) {
-		ret = submit_audio_out_urb(line6pcm);
-		if (ret < 0)
-			return ret;
-	}
-
-	return 0;
-}
-
-/*
-	Unlink all currently active playback URBs.
-*/
-void line6_unlink_audio_out_urbs(struct snd_line6_pcm *line6pcm)
-{
-	unsigned int i;
-
-	for (i = LINE6_ISO_BUFFERS; i--;) {
-		if (test_bit(i, &line6pcm->active_urb_out)) {
-			if (!test_and_set_bit(i, &line6pcm->unlink_urb_out)) {
-				struct urb *u = line6pcm->urb_audio_out[i];
-
-				usb_unlink_urb(u);
-			}
-		}
-	}
-}
-
-/*
-	Wait until unlinking of all currently active playback URBs has been
-	finished.
-*/
-void line6_wait_clear_audio_out_urbs(struct snd_line6_pcm *line6pcm)
-{
-	int timeout = HZ;
-	unsigned int i;
-	int alive;
-
-	do {
-		alive = 0;
-		for (i = LINE6_ISO_BUFFERS; i--;) {
-			if (test_bit(i, &line6pcm->active_urb_out))
-				alive++;
-		}
-		if (!alive)
-			break;
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(1);
-	} while (--timeout > 0);
-	if (alive)
-		snd_printk(KERN_ERR "timeout: still %d active urbs..\n", alive);
-}
-
-/*
-	Unlink all currently active playback URBs, and wait for finishing.
-*/
-void line6_unlink_wait_clear_audio_out_urbs(struct snd_line6_pcm *line6pcm)
-{
-	line6_unlink_audio_out_urbs(line6pcm);
-	line6_wait_clear_audio_out_urbs(line6pcm);
-}
-
-void line6_free_playback_buffer(struct snd_line6_pcm *line6pcm)
-{
-	kfree(line6pcm->buffer_out);
-	line6pcm->buffer_out = NULL;
-}
-
-/*
-	Callback for completed playback URB.
-*/
-static void audio_out_callback(struct urb *urb)
-{
-	int i, index, length = 0, shutdown = 0;
-	unsigned long flags;
-	struct snd_line6_pcm *line6pcm = (struct snd_line6_pcm *)urb->context;
-	struct snd_pcm_substream *substream =
-	    get_substream(line6pcm, SNDRV_PCM_STREAM_PLAYBACK);
-
-#if USE_CLEAR_BUFFER_WORKAROUND
-	memset(urb->transfer_buffer, 0, urb->transfer_buffer_length);
-#endif
-
-	line6pcm->last_frame_out = urb->start_frame;
-
-	/* find index of URB */
-	for (index = LINE6_ISO_BUFFERS; index--;)
-		if (urb == line6pcm->urb_audio_out[index])
-			break;
-
-	if (index < 0)
-		return;		/* URB has been unlinked asynchronously */
-
-	for (i = LINE6_ISO_PACKETS; i--;)
-		length += urb->iso_frame_desc[i].length;
-
-	spin_lock_irqsave(&line6pcm->lock_audio_out, flags);
-
-	if (test_bit(LINE6_INDEX_PCM_ALSA_PLAYBACK_STREAM, &line6pcm->flags)) {
-		struct snd_pcm_runtime *runtime = substream->runtime;
-
-		line6pcm->pos_out_done +=
-		    length / line6pcm->properties->bytes_per_frame;
-
-		if (line6pcm->pos_out_done >= runtime->buffer_size)
-			line6pcm->pos_out_done -= runtime->buffer_size;
-	}
-
-	clear_bit(index, &line6pcm->active_urb_out);
-
-	for (i = LINE6_ISO_PACKETS; i--;)
-		if (urb->iso_frame_desc[i].status == -EXDEV) {
-			shutdown = 1;
-			break;
-		}
-
-	if (test_and_clear_bit(index, &line6pcm->unlink_urb_out))
-		shutdown = 1;
-
-	spin_unlock_irqrestore(&line6pcm->lock_audio_out, flags);
-
-	if (!shutdown) {
-		submit_audio_out_urb(line6pcm);
-
-		if (test_bit(LINE6_INDEX_PCM_ALSA_PLAYBACK_STREAM,
-			     &line6pcm->flags)) {
-			line6pcm->bytes_out += length;
-			if (line6pcm->bytes_out >= line6pcm->period_out) {
-				line6pcm->bytes_out %= line6pcm->period_out;
-				snd_pcm_period_elapsed(substream);
-			}
-		}
-	}
-}
-
-/* open playback callback */
-static int snd_line6_playback_open(struct snd_pcm_substream *substream)
-{
-	int err;
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
-
-	err = snd_pcm_hw_constraint_ratdens(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
-					    (&line6pcm->
-					     properties->snd_line6_rates));
-	if (err < 0)
-		return err;
-
-	runtime->hw = line6pcm->properties->snd_line6_playback_hw;
-	return 0;
-}
-
-/* close playback callback */
-static int snd_line6_playback_close(struct snd_pcm_substream *substream)
-{
-	return 0;
-}
-
-/* hw_params playback callback */
-static int snd_line6_playback_hw_params(struct snd_pcm_substream *substream,
-					struct snd_pcm_hw_params *hw_params)
-{
-	int ret;
-	struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
-
-	/* -- Florian Demski [FD] */
-	/* don't ask me why, but this fixes the bug on my machine */
-	if (line6pcm == NULL) {
-		if (substream->pcm == NULL)
-			return -ENOMEM;
-		if (substream->pcm->private_data == NULL)
-			return -ENOMEM;
-		substream->private_data = substream->pcm->private_data;
-		line6pcm = snd_pcm_substream_chip(substream);
-	}
-	/* -- [FD] end */
-
-	ret = line6_pcm_acquire(line6pcm, LINE6_BIT_PCM_ALSA_PLAYBACK_BUFFER);
-
-	if (ret < 0)
-		return ret;
-
-	ret = snd_pcm_lib_malloc_pages(substream,
-				       params_buffer_bytes(hw_params));
-	if (ret < 0) {
-		line6_pcm_release(line6pcm, LINE6_BIT_PCM_ALSA_PLAYBACK_BUFFER);
-		return ret;
-	}
-
-	line6pcm->period_out = params_period_bytes(hw_params);
-	return 0;
-}
-
-/* hw_free playback callback */
-static int snd_line6_playback_hw_free(struct snd_pcm_substream *substream)
-{
-	struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
-
-	line6_pcm_release(line6pcm, LINE6_BIT_PCM_ALSA_PLAYBACK_BUFFER);
-	return snd_pcm_lib_free_pages(substream);
-}
-
-/* trigger playback callback */
-int snd_line6_playback_trigger(struct snd_line6_pcm *line6pcm, int cmd)
-{
-	int err;
-
-	switch (cmd) {
-	case SNDRV_PCM_TRIGGER_START:
-#ifdef CONFIG_PM
-	case SNDRV_PCM_TRIGGER_RESUME:
-#endif
-		err = line6_pcm_acquire(line6pcm,
-					LINE6_BIT_PCM_ALSA_PLAYBACK_STREAM);
-
-		if (err < 0)
-			return err;
-
-		break;
-
-	case SNDRV_PCM_TRIGGER_STOP:
-#ifdef CONFIG_PM
-	case SNDRV_PCM_TRIGGER_SUSPEND:
-#endif
-		err = line6_pcm_release(line6pcm,
-					LINE6_BIT_PCM_ALSA_PLAYBACK_STREAM);
-
-		if (err < 0)
-			return err;
-
-		break;
-
-	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		set_bit(LINE6_INDEX_PAUSE_PLAYBACK, &line6pcm->flags);
-		break;
-
-	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		clear_bit(LINE6_INDEX_PAUSE_PLAYBACK, &line6pcm->flags);
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-/* playback pointer callback */
-static snd_pcm_uframes_t
-snd_line6_playback_pointer(struct snd_pcm_substream *substream)
-{
-	struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
-
-	return line6pcm->pos_out_done;
-}
-
-/* playback operators */
-struct snd_pcm_ops snd_line6_playback_ops = {
-	.open = snd_line6_playback_open,
-	.close = snd_line6_playback_close,
-	.ioctl = snd_pcm_lib_ioctl,
-	.hw_params = snd_line6_playback_hw_params,
-	.hw_free = snd_line6_playback_hw_free,
-	.prepare = snd_line6_prepare,
-	.trigger = snd_line6_trigger,
-	.pointer = snd_line6_playback_pointer,
-};
-
-int line6_create_audio_out_urbs(struct snd_line6_pcm *line6pcm)
-{
-	int i;
-
-	/* create audio URBs and fill in constant values: */
-	for (i = 0; i < LINE6_ISO_BUFFERS; ++i) {
-		struct urb *urb;
-
-		/* URB for audio out: */
-		urb = line6pcm->urb_audio_out[i] =
-		    usb_alloc_urb(LINE6_ISO_PACKETS, GFP_KERNEL);
-
-		if (urb == NULL) {
-			dev_err(line6pcm->line6->ifcdev, "Out of memory\n");
-			return -ENOMEM;
-		}
-
-		urb->dev = line6pcm->line6->usbdev;
-		urb->pipe =
-		    usb_sndisocpipe(line6pcm->line6->usbdev,
-				    line6pcm->ep_audio_write &
-				    USB_ENDPOINT_NUMBER_MASK);
-		urb->transfer_flags = URB_ISO_ASAP;
-		urb->start_frame = -1;
-		urb->number_of_packets = LINE6_ISO_PACKETS;
-		urb->interval = LINE6_ISO_INTERVAL;
-		urb->error_count = 0;
-		urb->complete = audio_out_callback;
-	}
-
-	return 0;
-}
diff --git a/drivers/staging/line6/pod.h b/drivers/staging/line6/pod.h
deleted file mode 100644
index 3e3f167..0000000
--- a/drivers/staging/line6/pod.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Line6 Linux USB driver - 0.9.1beta
- *
- * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
- *
- *	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, version 2.
- *
- */
-
-#ifndef POD_H
-#define POD_H
-
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/usb.h>
-
-#include <sound/core.h>
-
-#include "driver.h"
-
-/*
-	PODxt Live interfaces
-*/
-#define PODXTLIVE_INTERFACE_POD    0
-#define PODXTLIVE_INTERFACE_VARIAX 1
-
-/*
-	Locate name in binary program dump
-*/
-#define	POD_NAME_OFFSET 0
-#define	POD_NAME_LENGTH 16
-
-/*
-	Other constants
-*/
-#define POD_CONTROL_SIZE 0x80
-#define POD_BUFSIZE_DUMPREQ 7
-#define POD_STARTUP_DELAY 1000
-
-/*
-	Stages of POD startup procedure
-*/
-enum {
-	POD_STARTUP_INIT = 1,
-	POD_STARTUP_VERSIONREQ,
-	POD_STARTUP_WORKQUEUE,
-	POD_STARTUP_SETUP,
-	POD_STARTUP_LAST = POD_STARTUP_SETUP - 1
-};
-
-struct usb_line6_pod {
-	/**
-		Generic Line6 USB data.
-	*/
-	struct usb_line6 line6;
-
-	/**
-		Instrument monitor level.
-	*/
-	int monitor_level;
-
-	/**
-		Timer for device initializaton.
-	*/
-	struct timer_list startup_timer;
-
-	/**
-		Work handler for device initializaton.
-	*/
-	struct work_struct startup_work;
-
-	/**
-		Current progress in startup procedure.
-	*/
-	int startup_progress;
-
-	/**
-		Serial number of device.
-	*/
-	int serial_number;
-
-	/**
-		Firmware version (x 100).
-	*/
-	int firmware_version;
-
-	/**
-		Device ID.
-	*/
-	int device_id;
-};
-
-extern void line6_pod_disconnect(struct usb_interface *interface);
-extern int line6_pod_init(struct usb_interface *interface,
-			  struct usb_line6_pod *pod);
-extern void line6_pod_process_message(struct usb_line6_pod *pod);
-extern void line6_pod_transmit_parameter(struct usb_line6_pod *pod, int param,
-					 u8 value);
-
-#endif
diff --git a/drivers/staging/line6/podhd.c b/drivers/staging/line6/podhd.c
deleted file mode 100644
index 7ef4543..0000000
--- a/drivers/staging/line6/podhd.c
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Line6 Pod HD
- *
- * Copyright (C) 2011 Stefan Hajnoczi <stefanha@gmail.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, version 2.
- *
- */
-
-#include <sound/core.h>
-#include <sound/pcm.h>
-
-#include "audio.h"
-#include "driver.h"
-#include "pcm.h"
-#include "podhd.h"
-
-#define PODHD_BYTES_PER_FRAME 6	/* 24bit audio (stereo) */
-
-static struct snd_ratden podhd_ratden = {
-	.num_min = 48000,
-	.num_max = 48000,
-	.num_step = 1,
-	.den = 1,
-};
-
-static struct line6_pcm_properties podhd_pcm_properties = {
-	.snd_line6_playback_hw = {
-				  .info = (SNDRV_PCM_INFO_MMAP |
-					   SNDRV_PCM_INFO_INTERLEAVED |
-					   SNDRV_PCM_INFO_BLOCK_TRANSFER |
-					   SNDRV_PCM_INFO_MMAP_VALID |
-					   SNDRV_PCM_INFO_PAUSE |
-#ifdef CONFIG_PM
-					   SNDRV_PCM_INFO_RESUME |
-#endif
-					   SNDRV_PCM_INFO_SYNC_START),
-				  .formats = SNDRV_PCM_FMTBIT_S24_3LE,
-				  .rates = SNDRV_PCM_RATE_48000,
-				  .rate_min = 48000,
-				  .rate_max = 48000,
-				  .channels_min = 2,
-				  .channels_max = 2,
-				  .buffer_bytes_max = 60000,
-				  .period_bytes_min = 64,
-				  .period_bytes_max = 8192,
-				  .periods_min = 1,
-				  .periods_max = 1024},
-	.snd_line6_capture_hw = {
-				 .info = (SNDRV_PCM_INFO_MMAP |
-					  SNDRV_PCM_INFO_INTERLEAVED |
-					  SNDRV_PCM_INFO_BLOCK_TRANSFER |
-					  SNDRV_PCM_INFO_MMAP_VALID |
-#ifdef CONFIG_PM
-					  SNDRV_PCM_INFO_RESUME |
-#endif
-					  SNDRV_PCM_INFO_SYNC_START),
-				 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
-				 .rates = SNDRV_PCM_RATE_48000,
-				 .rate_min = 48000,
-				 .rate_max = 48000,
-				 .channels_min = 2,
-				 .channels_max = 2,
-				 .buffer_bytes_max = 60000,
-				 .period_bytes_min = 64,
-				 .period_bytes_max = 8192,
-				 .periods_min = 1,
-				 .periods_max = 1024},
-	.snd_line6_rates = {
-			    .nrats = 1,
-			    .rats = &podhd_ratden},
-	.bytes_per_frame = PODHD_BYTES_PER_FRAME
-};
-
-/*
-	POD HD destructor.
-*/
-static void podhd_destruct(struct usb_interface *interface)
-{
-	struct usb_line6_podhd *podhd = usb_get_intfdata(interface);
-
-	if (podhd == NULL)
-		return;
-	line6_cleanup_audio(&podhd->line6);
-}
-
-/*
-	Try to init POD HD device.
-*/
-static int podhd_try_init(struct usb_interface *interface,
-			  struct usb_line6_podhd *podhd)
-{
-	int err;
-	struct usb_line6 *line6 = &podhd->line6;
-
-	if ((interface == NULL) || (podhd == NULL))
-		return -ENODEV;
-
-	/* initialize audio system: */
-	err = line6_init_audio(line6);
-	if (err < 0)
-		return err;
-
-	/* initialize MIDI subsystem: */
-	err = line6_init_midi(line6);
-	if (err < 0)
-		return err;
-
-	/* initialize PCM subsystem: */
-	err = line6_init_pcm(line6, &podhd_pcm_properties);
-	if (err < 0)
-		return err;
-
-	/* register USB audio system: */
-	err = line6_register_audio(line6);
-	return err;
-}
-
-/*
-	Init POD HD device (and clean up in case of failure).
-*/
-int line6_podhd_init(struct usb_interface *interface,
-		     struct usb_line6_podhd *podhd)
-{
-	int err = podhd_try_init(interface, podhd);
-
-	if (err < 0)
-		podhd_destruct(interface);
-
-	return err;
-}
-
-/*
-	POD HD device disconnected.
-*/
-void line6_podhd_disconnect(struct usb_interface *interface)
-{
-	struct usb_line6_podhd *podhd;
-
-	if (interface == NULL)
-		return;
-	podhd = usb_get_intfdata(interface);
-
-	if (podhd != NULL) {
-		struct snd_line6_pcm *line6pcm = podhd->line6.line6pcm;
-
-		if (line6pcm != NULL)
-			line6_pcm_disconnect(line6pcm);
-	}
-
-	podhd_destruct(interface);
-}
diff --git a/drivers/staging/line6/podhd.h b/drivers/staging/line6/podhd.h
deleted file mode 100644
index 652f740..0000000
--- a/drivers/staging/line6/podhd.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Line6 Pod HD
- *
- * Copyright (C) 2011 Stefan Hajnoczi <stefanha@gmail.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, version 2.
- *
- */
-
-#ifndef PODHD_H
-#define PODHD_H
-
-#include <linux/usb.h>
-
-#include "driver.h"
-
-struct usb_line6_podhd {
-	/**
-		Generic Line6 USB data.
-	*/
-	struct usb_line6 line6;
-};
-
-extern void line6_podhd_disconnect(struct usb_interface *interface);
-extern int line6_podhd_init(struct usb_interface *interface,
-			    struct usb_line6_podhd *podhd);
-
-#endif /* PODHD_H */
diff --git a/drivers/staging/line6/revision.h b/drivers/staging/line6/revision.h
deleted file mode 100644
index b4eee2b..0000000
--- a/drivers/staging/line6/revision.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#ifndef DRIVER_REVISION
-/* current subversion revision */
-#define DRIVER_REVISION " (904)"
-#endif
diff --git a/drivers/staging/line6/toneport.c b/drivers/staging/line6/toneport.c
deleted file mode 100644
index 6943715..0000000
--- a/drivers/staging/line6/toneport.c
+++ /dev/null
@@ -1,460 +0,0 @@
-/*
- * Line6 Linux USB driver - 0.9.1beta
- *
- * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
- *                         Emil Myhrman (emil.myhrman@gmail.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, version 2.
- *
- */
-
-#include <linux/wait.h>
-#include <sound/control.h>
-
-#include "audio.h"
-#include "capture.h"
-#include "driver.h"
-#include "playback.h"
-#include "toneport.h"
-
-static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2);
-
-#define TONEPORT_PCM_DELAY 1
-
-static struct snd_ratden toneport_ratden = {
-	.num_min = 44100,
-	.num_max = 44100,
-	.num_step = 1,
-	.den = 1
-};
-
-static struct line6_pcm_properties toneport_pcm_properties = {
-	.snd_line6_playback_hw = {
-				  .info = (SNDRV_PCM_INFO_MMAP |
-					   SNDRV_PCM_INFO_INTERLEAVED |
-					   SNDRV_PCM_INFO_BLOCK_TRANSFER |
-					   SNDRV_PCM_INFO_MMAP_VALID |
-					   SNDRV_PCM_INFO_PAUSE |
-#ifdef CONFIG_PM
-					   SNDRV_PCM_INFO_RESUME |
-#endif
-					   SNDRV_PCM_INFO_SYNC_START),
-				  .formats = SNDRV_PCM_FMTBIT_S16_LE,
-				  .rates = SNDRV_PCM_RATE_KNOT,
-				  .rate_min = 44100,
-				  .rate_max = 44100,
-				  .channels_min = 2,
-				  .channels_max = 2,
-				  .buffer_bytes_max = 60000,
-				  .period_bytes_min = 64,
-				  .period_bytes_max = 8192,
-				  .periods_min = 1,
-				  .periods_max = 1024},
-	.snd_line6_capture_hw = {
-				 .info = (SNDRV_PCM_INFO_MMAP |
-					  SNDRV_PCM_INFO_INTERLEAVED |
-					  SNDRV_PCM_INFO_BLOCK_TRANSFER |
-					  SNDRV_PCM_INFO_MMAP_VALID |
-#ifdef CONFIG_PM
-					  SNDRV_PCM_INFO_RESUME |
-#endif
-					  SNDRV_PCM_INFO_SYNC_START),
-				 .formats = SNDRV_PCM_FMTBIT_S16_LE,
-				 .rates = SNDRV_PCM_RATE_KNOT,
-				 .rate_min = 44100,
-				 .rate_max = 44100,
-				 .channels_min = 2,
-				 .channels_max = 2,
-				 .buffer_bytes_max = 60000,
-				 .period_bytes_min = 64,
-				 .period_bytes_max = 8192,
-				 .periods_min = 1,
-				 .periods_max = 1024},
-	.snd_line6_rates = {
-			    .nrats = 1,
-			    .rats = &toneport_ratden},
-	.bytes_per_frame = 4
-};
-
-/*
-	For the led on Guitarport.
-	Brightness goes from 0x00 to 0x26. Set a value above this to have led
-	blink.
-	(void cmd_0x02(byte red, byte green)
-*/
-static int led_red = 0x00;
-static int led_green = 0x26;
-
-static const struct {
-	const char *name;
-	int code;
-} toneport_source_info[] = {
-	{"Microphone", 0x0a01},
-	{"Line", 0x0801},
-	{"Instrument", 0x0b01},
-	{"Inst & Mic", 0x0901}
-};
-
-static bool toneport_has_led(short product)
-{
-	return
-	    (product == LINE6_DEVID_GUITARPORT) ||
-	    (product == LINE6_DEVID_TONEPORT_GX);
-	/* add your device here if you are missing support for the LEDs */
-}
-
-static void toneport_update_led(struct device *dev)
-{
-	struct usb_interface *interface = to_usb_interface(dev);
-	struct usb_line6_toneport *tp = usb_get_intfdata(interface);
-	struct usb_line6 *line6;
-
-	if (!tp)
-		return;
-
-	line6 = &tp->line6;
-	if (line6)
-		toneport_send_cmd(line6->usbdev, (led_red << 8) | 0x0002,
-				  led_green);
-}
-
-static ssize_t toneport_set_led_red(struct device *dev,
-				    struct device_attribute *attr,
-				    const char *buf, size_t count)
-{
-	int retval;
-
-	retval = kstrtoint(buf, 10, &led_red);
-	if (retval)
-		return retval;
-
-	toneport_update_led(dev);
-	return count;
-}
-
-static ssize_t toneport_set_led_green(struct device *dev,
-				      struct device_attribute *attr,
-				      const char *buf, size_t count)
-{
-	int retval;
-
-	retval = kstrtoint(buf, 10, &led_green);
-	if (retval)
-		return retval;
-
-	toneport_update_led(dev);
-	return count;
-}
-
-static DEVICE_ATTR(led_red, S_IWUSR | S_IRUGO, line6_nop_read,
-		   toneport_set_led_red);
-static DEVICE_ATTR(led_green, S_IWUSR | S_IRUGO, line6_nop_read,
-		   toneport_set_led_green);
-
-static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2)
-{
-	int ret;
-
-	ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x67,
-			      USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
-			      cmd1, cmd2, NULL, 0, LINE6_TIMEOUT * HZ);
-
-	if (ret < 0) {
-		dev_err(&usbdev->dev, "send failed (error %d)\n", ret);
-		return ret;
-	}
-
-	return 0;
-}
-
-/* monitor info callback */
-static int snd_toneport_monitor_info(struct snd_kcontrol *kcontrol,
-				     struct snd_ctl_elem_info *uinfo)
-{
-	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
-	uinfo->count = 1;
-	uinfo->value.integer.min = 0;
-	uinfo->value.integer.max = 256;
-	return 0;
-}
-
-/* monitor get callback */
-static int snd_toneport_monitor_get(struct snd_kcontrol *kcontrol,
-				    struct snd_ctl_elem_value *ucontrol)
-{
-	struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
-
-	ucontrol->value.integer.value[0] = line6pcm->volume_monitor;
-	return 0;
-}
-
-/* monitor put callback */
-static int snd_toneport_monitor_put(struct snd_kcontrol *kcontrol,
-				    struct snd_ctl_elem_value *ucontrol)
-{
-	struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
-
-	if (ucontrol->value.integer.value[0] == line6pcm->volume_monitor)
-		return 0;
-
-	line6pcm->volume_monitor = ucontrol->value.integer.value[0];
-
-	if (line6pcm->volume_monitor > 0)
-		line6_pcm_acquire(line6pcm, LINE6_BITS_PCM_MONITOR);
-	else
-		line6_pcm_release(line6pcm, LINE6_BITS_PCM_MONITOR);
-
-	return 1;
-}
-
-/* source info callback */
-static int snd_toneport_source_info(struct snd_kcontrol *kcontrol,
-				    struct snd_ctl_elem_info *uinfo)
-{
-	const int size = ARRAY_SIZE(toneport_source_info);
-
-	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
-	uinfo->count = 1;
-	uinfo->value.enumerated.items = size;
-
-	if (uinfo->value.enumerated.item >= size)
-		uinfo->value.enumerated.item = size - 1;
-
-	strcpy(uinfo->value.enumerated.name,
-	       toneport_source_info[uinfo->value.enumerated.item].name);
-
-	return 0;
-}
-
-/* source get callback */
-static int snd_toneport_source_get(struct snd_kcontrol *kcontrol,
-				   struct snd_ctl_elem_value *ucontrol)
-{
-	struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
-	struct usb_line6_toneport *toneport =
-	    (struct usb_line6_toneport *)line6pcm->line6;
-	ucontrol->value.enumerated.item[0] = toneport->source;
-	return 0;
-}
-
-/* source put callback */
-static int snd_toneport_source_put(struct snd_kcontrol *kcontrol,
-				   struct snd_ctl_elem_value *ucontrol)
-{
-	struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
-	struct usb_line6_toneport *toneport =
-	    (struct usb_line6_toneport *)line6pcm->line6;
-	unsigned int source;
-
-	source = ucontrol->value.enumerated.item[0];
-	if (source >= ARRAY_SIZE(toneport_source_info))
-		return -EINVAL;
-	if (source == toneport->source)
-		return 0;
-
-	toneport->source = source;
-	toneport_send_cmd(toneport->line6.usbdev,
-			  toneport_source_info[source].code, 0x0000);
-	return 1;
-}
-
-static void toneport_start_pcm(unsigned long arg)
-{
-	struct usb_line6_toneport *toneport = (struct usb_line6_toneport *)arg;
-	struct usb_line6 *line6 = &toneport->line6;
-
-	line6_pcm_acquire(line6->line6pcm, LINE6_BITS_PCM_MONITOR);
-}
-
-/* control definition */
-static struct snd_kcontrol_new toneport_control_monitor = {
-	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-	.name = "Monitor Playback Volume",
-	.index = 0,
-	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
-	.info = snd_toneport_monitor_info,
-	.get = snd_toneport_monitor_get,
-	.put = snd_toneport_monitor_put
-};
-
-/* source selector definition */
-static struct snd_kcontrol_new toneport_control_source = {
-	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-	.name = "PCM Capture Source",
-	.index = 0,
-	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
-	.info = snd_toneport_source_info,
-	.get = snd_toneport_source_get,
-	.put = snd_toneport_source_put
-};
-
-/*
-	Toneport destructor.
-*/
-static void toneport_destruct(struct usb_interface *interface)
-{
-	struct usb_line6_toneport *toneport = usb_get_intfdata(interface);
-
-	if (toneport == NULL)
-		return;
-	line6_cleanup_audio(&toneport->line6);
-}
-
-/*
-	Setup Toneport device.
-*/
-static void toneport_setup(struct usb_line6_toneport *toneport)
-{
-	int ticks;
-	struct usb_line6 *line6 = &toneport->line6;
-	struct usb_device *usbdev = line6->usbdev;
-	u16 idProduct = le16_to_cpu(usbdev->descriptor.idProduct);
-
-	/* sync time on device with host: */
-	ticks = (int)get_seconds();
-	line6_write_data(line6, 0x80c6, &ticks, 4);
-
-	/* enable device: */
-	toneport_send_cmd(usbdev, 0x0301, 0x0000);
-
-	/* initialize source select: */
-	switch (le16_to_cpu(usbdev->descriptor.idProduct)) {
-	case LINE6_DEVID_TONEPORT_UX1:
-	case LINE6_DEVID_TONEPORT_UX2:
-	case LINE6_DEVID_PODSTUDIO_UX1:
-	case LINE6_DEVID_PODSTUDIO_UX2:
-		toneport_send_cmd(usbdev,
-				  toneport_source_info[toneport->source].code,
-				  0x0000);
-	}
-
-	if (toneport_has_led(idProduct))
-		toneport_update_led(&usbdev->dev);
-}
-
-/*
-	 Try to init Toneport device.
-*/
-static int toneport_try_init(struct usb_interface *interface,
-			     struct usb_line6_toneport *toneport)
-{
-	int err;
-	struct usb_line6 *line6 = &toneport->line6;
-	struct usb_device *usbdev = line6->usbdev;
-	u16 idProduct = le16_to_cpu(usbdev->descriptor.idProduct);
-
-	if ((interface == NULL) || (toneport == NULL))
-		return -ENODEV;
-
-	/* initialize audio system: */
-	err = line6_init_audio(line6);
-	if (err < 0)
-		return err;
-
-	/* initialize PCM subsystem: */
-	err = line6_init_pcm(line6, &toneport_pcm_properties);
-	if (err < 0)
-		return err;
-
-	/* register monitor control: */
-	err = snd_ctl_add(line6->card,
-			  snd_ctl_new1(&toneport_control_monitor,
-				       line6->line6pcm));
-	if (err < 0)
-		return err;
-
-	/* register source select control: */
-	switch (le16_to_cpu(usbdev->descriptor.idProduct)) {
-	case LINE6_DEVID_TONEPORT_UX1:
-	case LINE6_DEVID_TONEPORT_UX2:
-	case LINE6_DEVID_PODSTUDIO_UX1:
-	case LINE6_DEVID_PODSTUDIO_UX2:
-		err =
-		    snd_ctl_add(line6->card,
-				snd_ctl_new1(&toneport_control_source,
-					     line6->line6pcm));
-		if (err < 0)
-			return err;
-	}
-
-	/* register audio system: */
-	err = line6_register_audio(line6);
-	if (err < 0)
-		return err;
-
-	line6_read_serial_number(line6, &toneport->serial_number);
-	line6_read_data(line6, 0x80c2, &toneport->firmware_version, 1);
-
-	if (toneport_has_led(idProduct)) {
-		CHECK_RETURN(device_create_file
-			     (&interface->dev, &dev_attr_led_red));
-		CHECK_RETURN(device_create_file
-			     (&interface->dev, &dev_attr_led_green));
-	}
-
-	toneport_setup(toneport);
-
-	init_timer(&toneport->timer);
-	toneport->timer.expires = jiffies + TONEPORT_PCM_DELAY * HZ;
-	toneport->timer.function = toneport_start_pcm;
-	toneport->timer.data = (unsigned long)toneport;
-	add_timer(&toneport->timer);
-
-	return 0;
-}
-
-/*
-	 Init Toneport device (and clean up in case of failure).
-*/
-int line6_toneport_init(struct usb_interface *interface,
-			struct usb_line6_toneport *toneport)
-{
-	int err = toneport_try_init(interface, toneport);
-
-	if (err < 0)
-		toneport_destruct(interface);
-
-	return err;
-}
-
-/*
-	Resume Toneport device after reset.
-*/
-void line6_toneport_reset_resume(struct usb_line6_toneport *toneport)
-{
-	toneport_setup(toneport);
-}
-
-/*
-	Toneport device disconnected.
-*/
-void line6_toneport_disconnect(struct usb_interface *interface)
-{
-	struct usb_line6_toneport *toneport;
-	u16 idProduct;
-
-	if (interface == NULL)
-		return;
-
-	toneport = usb_get_intfdata(interface);
-	del_timer_sync(&toneport->timer);
-	idProduct = le16_to_cpu(toneport->line6.usbdev->descriptor.idProduct);
-
-	if (toneport_has_led(idProduct)) {
-		device_remove_file(&interface->dev, &dev_attr_led_red);
-		device_remove_file(&interface->dev, &dev_attr_led_green);
-	}
-
-	if (toneport != NULL) {
-		struct snd_line6_pcm *line6pcm = toneport->line6.line6pcm;
-
-		if (line6pcm != NULL) {
-			line6_pcm_release(line6pcm, LINE6_BITS_PCM_MONITOR);
-			line6_pcm_disconnect(line6pcm);
-		}
-	}
-
-	toneport_destruct(interface);
-}
diff --git a/drivers/staging/line6/toneport.h b/drivers/staging/line6/toneport.h
deleted file mode 100644
index 8576b72..0000000
--- a/drivers/staging/line6/toneport.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Line6 Linux USB driver - 0.9.1beta
- *
- * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
- *
- *	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, version 2.
- *
- */
-
-#ifndef TONEPORT_H
-#define TONEPORT_H
-
-#include <linux/usb.h>
-#include <sound/core.h>
-
-#include "driver.h"
-
-struct usb_line6_toneport {
-	/**
-		Generic Line6 USB data.
-	*/
-	struct usb_line6 line6;
-
-	/**
-		Source selector.
-	*/
-	int source;
-
-	/**
-		Serial number of device.
-	*/
-	int serial_number;
-
-	/**
-		Firmware version (x 100).
-	*/
-	int firmware_version;
-
-	/**
-		 Timer for delayed PCM startup.
-	*/
-	struct timer_list timer;
-};
-
-extern void line6_toneport_disconnect(struct usb_interface *interface);
-extern int line6_toneport_init(struct usb_interface *interface,
-			       struct usb_line6_toneport *toneport);
-extern void line6_toneport_reset_resume(struct usb_line6_toneport *toneport);
-
-#endif
diff --git a/drivers/staging/line6/usbdefs.h b/drivers/staging/line6/usbdefs.h
deleted file mode 100644
index 2d1cc47..0000000
--- a/drivers/staging/line6/usbdefs.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Line6 Linux USB driver - 0.9.1beta
- *
- * Copyright (C) 2005-2008 Markus Grabner (grabner@icg.tugraz.at)
- *
- *	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, version 2.
- *
- */
-
-#ifndef USBDEFS_H
-#define USBDEFS_H
-
-#define LINE6_VENDOR_ID  0x0e41
-
-#define USB_INTERVALS_PER_SECOND 1000
-
-/*
-	Device ids.
-*/
-#define LINE6_DEVID_BASSPODXT     0x4250
-#define LINE6_DEVID_BASSPODXTLIVE 0x4642
-#define LINE6_DEVID_BASSPODXTPRO  0x4252
-#define LINE6_DEVID_GUITARPORT    0x4750
-#define LINE6_DEVID_POCKETPOD     0x5051
-#define LINE6_DEVID_PODHD300      0x5057
-#define LINE6_DEVID_PODHD400      0x5058
-#define LINE6_DEVID_PODHD500      0x414D
-#define LINE6_DEVID_PODSTUDIO_GX  0x4153
-#define LINE6_DEVID_PODSTUDIO_UX1 0x4150
-#define LINE6_DEVID_PODSTUDIO_UX2 0x4151
-#define LINE6_DEVID_PODX3         0x414a
-#define LINE6_DEVID_PODX3LIVE     0x414b
-#define LINE6_DEVID_PODXT         0x5044
-#define LINE6_DEVID_PODXTLIVE     0x4650
-#define LINE6_DEVID_PODXTPRO      0x5050
-#define LINE6_DEVID_TONEPORT_GX   0x4147
-#define LINE6_DEVID_TONEPORT_UX1  0x4141
-#define LINE6_DEVID_TONEPORT_UX2  0x4142
-#define LINE6_DEVID_VARIAX        0x534d
-
-#define LINE6_BIT(x) LINE6_BIT_ ## x = 1 << LINE6_INDEX_ ## x
-
-enum {
-	LINE6_INDEX_BASSPODXT,
-	LINE6_INDEX_BASSPODXTLIVE,
-	LINE6_INDEX_BASSPODXTPRO,
-	LINE6_INDEX_GUITARPORT,
-	LINE6_INDEX_POCKETPOD,
-	LINE6_INDEX_PODHD300,
-	LINE6_INDEX_PODHD400,
-	LINE6_INDEX_PODHD500,
-	LINE6_INDEX_PODSTUDIO_GX,
-	LINE6_INDEX_PODSTUDIO_UX1,
-	LINE6_INDEX_PODSTUDIO_UX2,
-	LINE6_INDEX_PODX3,
-	LINE6_INDEX_PODX3LIVE,
-	LINE6_INDEX_PODXT,
-	LINE6_INDEX_PODXTLIVE,
-	LINE6_INDEX_PODXTPRO,
-	LINE6_INDEX_TONEPORT_GX,
-	LINE6_INDEX_TONEPORT_UX1,
-	LINE6_INDEX_TONEPORT_UX2,
-	LINE6_INDEX_VARIAX,
-
-	LINE6_BIT(BASSPODXT),
-	LINE6_BIT(BASSPODXTLIVE),
-	LINE6_BIT(BASSPODXTPRO),
-	LINE6_BIT(GUITARPORT),
-	LINE6_BIT(POCKETPOD),
-	LINE6_BIT(PODHD300),
-	LINE6_BIT(PODHD400),
-	LINE6_BIT(PODHD500),
-	LINE6_BIT(PODSTUDIO_GX),
-	LINE6_BIT(PODSTUDIO_UX1),
-	LINE6_BIT(PODSTUDIO_UX2),
-	LINE6_BIT(PODX3),
-	LINE6_BIT(PODX3LIVE),
-	LINE6_BIT(PODXT),
-	LINE6_BIT(PODXTLIVE),
-	LINE6_BIT(PODXTPRO),
-	LINE6_BIT(TONEPORT_GX),
-	LINE6_BIT(TONEPORT_UX1),
-	LINE6_BIT(TONEPORT_UX2),
-	LINE6_BIT(VARIAX),
-
-	LINE6_BITS_PRO = LINE6_BIT_BASSPODXTPRO | LINE6_BIT_PODXTPRO,
-	LINE6_BITS_LIVE = LINE6_BIT_BASSPODXTLIVE | LINE6_BIT_PODXTLIVE |
-			  LINE6_BIT_PODX3LIVE,
-	LINE6_BITS_PODXTALL = LINE6_BIT_PODXT | LINE6_BIT_PODXTLIVE |
-			      LINE6_BIT_PODXTPRO,
-	LINE6_BITS_PODX3ALL = LINE6_BIT_PODX3 | LINE6_BIT_PODX3LIVE,
-	LINE6_BITS_PODHDALL = LINE6_BIT_PODHD300 |
-			      LINE6_BIT_PODHD400 |
-			      LINE6_BIT_PODHD500,
-	LINE6_BITS_BASSPODXTALL	= LINE6_BIT_BASSPODXT |
-				  LINE6_BIT_BASSPODXTLIVE |
-				  LINE6_BIT_BASSPODXTPRO
-};
-
-/* device supports settings parameter via USB */
-#define LINE6_BIT_CONTROL (1 << 0)
-/* device supports PCM input/output via USB */
-#define LINE6_BIT_PCM (1 << 1)
-/* device support hardware monitoring */
-#define LINE6_BIT_HWMON (1 << 2)
-
-#define LINE6_BIT_CTRL_PCM_HW	(LINE6_BIT_CONTROL |	\
-					 LINE6_BIT_PCM |	\
-					 LINE6_BIT_HWMON)
-
-#define LINE6_FALLBACK_INTERVAL 10
-#define LINE6_FALLBACK_MAXPACKETSIZE 16
-
-#endif
diff --git a/drivers/staging/line6/variax.h b/drivers/staging/line6/variax.h
deleted file mode 100644
index 24de796..0000000
--- a/drivers/staging/line6/variax.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Line6 Linux USB driver - 0.9.1beta
- *
- * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
- *
- *	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, version 2.
- *
- */
-
-#ifndef VARIAX_H
-#define VARIAX_H
-
-#include <linux/spinlock.h>
-#include <linux/usb.h>
-#include <linux/wait.h>
-#include <sound/core.h>
-
-#include "driver.h"
-
-#define VARIAX_STARTUP_DELAY1 1000
-#define VARIAX_STARTUP_DELAY3 100
-#define VARIAX_STARTUP_DELAY4 100
-
-/*
-	Stages of Variax startup procedure
-*/
-enum {
-	VARIAX_STARTUP_INIT = 1,
-	VARIAX_STARTUP_VERSIONREQ,
-	VARIAX_STARTUP_WAIT,
-	VARIAX_STARTUP_ACTIVATE,
-	VARIAX_STARTUP_WORKQUEUE,
-	VARIAX_STARTUP_SETUP,
-	VARIAX_STARTUP_LAST = VARIAX_STARTUP_SETUP - 1
-};
-
-struct usb_line6_variax {
-	/**
-		Generic Line6 USB data.
-	*/
-	struct usb_line6 line6;
-
-	/**
-		Buffer for activation code.
-	*/
-	unsigned char *buffer_activate;
-
-	/**
-		Handler for device initializaton.
-	*/
-	struct work_struct startup_work;
-
-	/**
-		Timers for device initializaton.
-	*/
-	struct timer_list startup_timer1;
-	struct timer_list startup_timer2;
-
-	/**
-		Current progress in startup procedure.
-	*/
-	int startup_progress;
-};
-
-extern void line6_variax_disconnect(struct usb_interface *interface);
-extern int line6_variax_init(struct usb_interface *interface,
-			     struct usb_line6_variax *variax);
-extern void line6_variax_process_message(struct usb_line6_variax *variax);
-
-#endif
diff --git a/include/drm/i915_component.h b/include/drm/i915_component.h
new file mode 100644
index 0000000..3e2f22e
--- /dev/null
+++ b/include/drm/i915_component.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright © 2014 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef _I915_COMPONENT_H_
+#define _I915_COMPONENT_H_
+
+struct i915_audio_component {
+	struct device *dev;
+
+	const struct i915_audio_component_ops {
+		struct module *owner;
+		void (*get_power)(struct device *);
+		void (*put_power)(struct device *);
+		int (*get_cdclk_freq)(struct device *);
+	} *ops;
+};
+
+#endif /* _I915_COMPONENT_H_ */
diff --git a/include/drm/i915_powerwell.h b/include/drm/i915_powerwell.h
deleted file mode 100644
index baa6f11..0000000
--- a/include/drm/i915_powerwell.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2013 Intel Inc.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- *
- **************************************************************************/
-
-#ifndef _I915_POWERWELL_H_
-#define _I915_POWERWELL_H_
-
-/* For use by hda_i915 driver */
-extern int i915_request_power_well(void);
-extern int i915_release_power_well(void);
-extern int i915_get_cdclk_freq(void);
-
-#endif				/* _I915_POWERWELL_H_ */
diff --git a/include/sound/ad1816a.h b/include/sound/ad1816a.h
index abdf609..f2d3a6d 100644
--- a/include/sound/ad1816a.h
+++ b/include/sound/ad1816a.h
@@ -170,10 +170,9 @@
 			      int irq, int dma1, int dma2,
 			      struct snd_ad1816a *chip);
 
-extern int snd_ad1816a_pcm(struct snd_ad1816a *chip, int device, struct snd_pcm **rpcm);
+extern int snd_ad1816a_pcm(struct snd_ad1816a *chip, int device);
 extern int snd_ad1816a_mixer(struct snd_ad1816a *chip);
-extern int snd_ad1816a_timer(struct snd_ad1816a *chip, int device,
-			     struct snd_timer **rtimer);
+extern int snd_ad1816a_timer(struct snd_ad1816a *chip, int device);
 #ifdef CONFIG_PM
 extern void snd_ad1816a_suspend(struct snd_ad1816a *chip);
 extern void snd_ad1816a_resume(struct snd_ad1816a *chip);
diff --git a/include/sound/ak4113.h b/include/sound/ak4113.h
index 2609048..58c1456 100644
--- a/include/sound/ak4113.h
+++ b/include/sound/ak4113.h
@@ -286,7 +286,8 @@
 	ak4113_write_t *write;
 	ak4113_read_t *read;
 	void *private_data;
-	unsigned int init:1;
+	atomic_t wq_processing;
+	struct mutex reinit_mutex;
 	spinlock_t lock;
 	unsigned char regmap[AK4113_WRITABLE_REGS];
 	struct snd_kcontrol *kctls[AK4113_CONTROLS];
@@ -317,5 +318,13 @@
 int snd_ak4113_external_rate(struct ak4113 *ak4113);
 int snd_ak4113_check_rate_and_errors(struct ak4113 *ak4113, unsigned int flags);
 
+#ifdef CONFIG_PM
+void snd_ak4113_suspend(struct ak4113 *chip);
+void snd_ak4113_resume(struct ak4113 *chip);
+#else
+static inline void snd_ak4113_suspend(struct ak4113 *chip) {}
+static inline void snd_ak4113_resume(struct ak4113 *chip) {}
+#endif
+
 #endif /* __SOUND_AK4113_H */
 
diff --git a/include/sound/ak4114.h b/include/sound/ak4114.h
index 52f02a6..b6feb7e 100644
--- a/include/sound/ak4114.h
+++ b/include/sound/ak4114.h
@@ -168,7 +168,8 @@
 	ak4114_write_t * write;
 	ak4114_read_t * read;
 	void * private_data;
-	unsigned int init: 1;
+	atomic_t wq_processing;
+	struct mutex reinit_mutex;
 	spinlock_t lock;
 	unsigned char regmap[6];
 	unsigned char txcsb[5];
@@ -199,5 +200,13 @@
 int snd_ak4114_external_rate(struct ak4114 *ak4114);
 int snd_ak4114_check_rate_and_errors(struct ak4114 *ak4114, unsigned int flags);
 
+#ifdef CONFIG_PM
+void snd_ak4114_suspend(struct ak4114 *chip);
+void snd_ak4114_resume(struct ak4114 *chip);
+#else
+static inline void snd_ak4114_suspend(struct ak4114 *chip) {}
+static inline void snd_ak4114_resume(struct ak4114 *chip) {}
+#endif
+
 #endif /* __SOUND_AK4114_H */
 
diff --git a/include/sound/compress_driver.h b/include/sound/compress_driver.h
index 1d0593b..f48089d 100644
--- a/include/sound/compress_driver.h
+++ b/include/sound/compress_driver.h
@@ -27,6 +27,7 @@
 
 #include <linux/types.h>
 #include <linux/sched.h>
+#include <sound/core.h>
 #include <sound/compress_offload.h>
 #include <sound/asound.h>
 #include <sound/pcm.h>
diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h
index c46908c..0de95cc 100644
--- a/include/sound/emu10k1.h
+++ b/include/sound/emu10k1.h
@@ -33,8 +33,8 @@
 #include <linux/interrupt.h>
 #include <linux/mutex.h>
 #include <linux/firmware.h>
+#include <linux/io.h>
 
-#include <asm/io.h>
 #include <uapi/sound/emu10k1.h>
 
 /* ------------------- DEFINES -------------------- */
@@ -1809,17 +1809,17 @@
 		       uint subsystem,
 		       struct snd_emu10k1 ** remu);
 
-int snd_emu10k1_pcm(struct snd_emu10k1 * emu, int device, struct snd_pcm ** rpcm);
-int snd_emu10k1_pcm_mic(struct snd_emu10k1 * emu, int device, struct snd_pcm ** rpcm);
-int snd_emu10k1_pcm_efx(struct snd_emu10k1 * emu, int device, struct snd_pcm ** rpcm);
-int snd_p16v_pcm(struct snd_emu10k1 * emu, int device, struct snd_pcm ** rpcm);
+int snd_emu10k1_pcm(struct snd_emu10k1 *emu, int device);
+int snd_emu10k1_pcm_mic(struct snd_emu10k1 *emu, int device);
+int snd_emu10k1_pcm_efx(struct snd_emu10k1 *emu, int device);
+int snd_p16v_pcm(struct snd_emu10k1 *emu, int device);
 int snd_p16v_free(struct snd_emu10k1 * emu);
 int snd_p16v_mixer(struct snd_emu10k1 * emu);
-int snd_emu10k1_pcm_multi(struct snd_emu10k1 * emu, int device, struct snd_pcm ** rpcm);
-int snd_emu10k1_fx8010_pcm(struct snd_emu10k1 * emu, int device, struct snd_pcm ** rpcm);
+int snd_emu10k1_pcm_multi(struct snd_emu10k1 *emu, int device);
+int snd_emu10k1_fx8010_pcm(struct snd_emu10k1 *emu, int device);
 int snd_emu10k1_mixer(struct snd_emu10k1 * emu, int pcm_device, int multi_device);
 int snd_emu10k1_timer(struct snd_emu10k1 * emu, int device);
-int snd_emu10k1_fx8010_new(struct snd_emu10k1 *emu, int device, struct snd_hwdep ** rhwdep);
+int snd_emu10k1_fx8010_new(struct snd_emu10k1 *emu, int device);
 
 irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id);
 
diff --git a/include/sound/es1688.h b/include/sound/es1688.h
index 1d636a2..b34f23a 100644
--- a/include/sound/es1688.h
+++ b/include/sound/es1688.h
@@ -115,8 +115,7 @@
 		      int mpu_irq,
 		      int dma8,
 		      unsigned short hardware);
-int snd_es1688_pcm(struct snd_card *card, struct snd_es1688 *chip, int device,
-		   struct snd_pcm **rpcm);
+int snd_es1688_pcm(struct snd_card *card, struct snd_es1688 *chip, int device);
 int snd_es1688_mixer(struct snd_card *card, struct snd_es1688 *chip);
 int snd_es1688_reset(struct snd_es1688 *chip);
 
diff --git a/include/sound/gus.h b/include/sound/gus.h
index 42905d8..07c116fe 100644
--- a/include/sound/gus.h
+++ b/include/sound/gus.h
@@ -27,7 +27,7 @@
 #include <sound/timer.h>
 #include <sound/seq_midi_emul.h>
 #include <sound/seq_device.h>
-#include <asm/io.h>
+#include <linux/io.h>
 
 /* IO ports */
 
@@ -591,7 +591,7 @@
 
 /* gus_pcm.c */
 
-int snd_gf1_pcm_new(struct snd_gus_card * gus, int pcm_dev, int control_index, struct snd_pcm ** rpcm);
+int snd_gf1_pcm_new(struct snd_gus_card *gus, int pcm_dev, int control_index);
 
 #ifdef CONFIG_SND_DEBUG
 extern void snd_gf1_print_voice_registers(struct snd_gus_card * gus);
@@ -620,7 +620,7 @@
 
 /* gus_uart.c */
 
-int snd_gf1_rawmidi_new(struct snd_gus_card * gus, int device, struct snd_rawmidi **rrawmidi);
+int snd_gf1_rawmidi_new(struct snd_gus_card *gus, int device);
 
 /* gus_dram.c */
 int snd_gus_dram_write(struct snd_gus_card *gus, char __user *ptr,
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 735bd0c..44e9c2f 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -94,9 +94,6 @@
 #define SNDRV_PCM_DEVICES	8
 #endif
 
-#define SNDRV_PCM_IOCTL1_FALSE		((void *)0)
-#define SNDRV_PCM_IOCTL1_TRUE		((void *)1)
-
 #define SNDRV_PCM_IOCTL1_RESET		0
 #define SNDRV_PCM_IOCTL1_INFO		1
 #define SNDRV_PCM_IOCTL1_CHANNEL_INFO	2
@@ -109,6 +106,7 @@
 #define SNDRV_PCM_TRIGGER_PAUSE_RELEASE	4
 #define SNDRV_PCM_TRIGGER_SUSPEND	5
 #define SNDRV_PCM_TRIGGER_RESUME	6
+#define SNDRV_PCM_TRIGGER_DRAIN		7
 
 #define SNDRV_PCM_POS_XRUN		((snd_pcm_uframes_t)-1)
 
@@ -520,7 +518,6 @@
 int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, struct file *file,
 			     struct snd_pcm_substream **rsubstream);
 void snd_pcm_detach_substream(struct snd_pcm_substream *substream);
-void snd_pcm_vma_notify_data(void *client, void *data);
 int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file, struct vm_area_struct *area);
 
 
@@ -986,21 +983,15 @@
 ssize_t snd_pcm_format_size(snd_pcm_format_t format, size_t samples);
 const unsigned char *snd_pcm_format_silence_64(snd_pcm_format_t format);
 int snd_pcm_format_set_silence(snd_pcm_format_t format, void *buf, unsigned int frames);
-snd_pcm_format_t snd_pcm_build_linear_format(int width, int unsigned, int big_endian);
 
 void snd_pcm_set_ops(struct snd_pcm * pcm, int direction,
 		     const struct snd_pcm_ops *ops);
 void snd_pcm_set_sync(struct snd_pcm_substream *substream);
-int snd_pcm_lib_interleave_len(struct snd_pcm_substream *substream);
 int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream,
 		      unsigned int cmd, void *arg);                      
 int snd_pcm_update_state(struct snd_pcm_substream *substream,
 			 struct snd_pcm_runtime *runtime);
 int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream);
-int snd_pcm_playback_xrun_check(struct snd_pcm_substream *substream);
-int snd_pcm_capture_xrun_check(struct snd_pcm_substream *substream);
-int snd_pcm_playback_xrun_asap(struct snd_pcm_substream *substream);
-int snd_pcm_capture_xrun_asap(struct snd_pcm_substream *substream);
 void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_uframes_t new_hw_ptr);
 void snd_pcm_period_elapsed(struct snd_pcm_substream *substream);
 snd_pcm_sframes_t snd_pcm_lib_write(struct snd_pcm_substream *substream,
diff --git a/include/sound/pcm_params.h b/include/sound/pcm_params.h
index 6b1c78f..3c45f39 100644
--- a/include/sound/pcm_params.h
+++ b/include/sound/pcm_params.h
@@ -38,31 +38,6 @@
 #define MASK_OFS(i)	((i) >> 5)
 #define MASK_BIT(i)	(1U << ((i) & 31))
 
-static inline unsigned int ld2(u_int32_t v)
-{
-        unsigned r = 0;
-
-        if (v >= 0x10000) {
-                v >>= 16;
-                r += 16;
-        }
-        if (v >= 0x100) {
-                v >>= 8;
-                r += 8;
-        }
-        if (v >= 0x10) {
-                v >>= 4;
-                r += 4;
-        }
-        if (v >= 4) {
-                v >>= 2;
-                r += 2;
-        }
-        if (v >= 2)
-                r++;
-        return r;
-}
-
 static inline size_t snd_mask_sizeof(void)
 {
 	return sizeof(struct snd_mask);
@@ -92,7 +67,7 @@
 	int i;
 	for (i = 0; i < SNDRV_MASK_SIZE; i++) {
 		if (mask->bits[i])
-			return ffs(mask->bits[i]) - 1 + (i << 5);
+			return __ffs(mask->bits[i]) + (i << 5);
 	}
 	return 0;
 }
@@ -102,7 +77,7 @@
 	int i;
 	for (i = SNDRV_MASK_SIZE - 1; i >= 0; i--) {
 		if (mask->bits[i])
-			return ld2(mask->bits[i]) + (i << 5);
+			return __fls(mask->bits[i]) + (i << 5);
 	}
 	return 0;
 }
@@ -325,43 +300,68 @@
 		i1->max == i2->max && i1->openmax == i2->openmax;
 }
 
-static inline unsigned int add(unsigned int a, unsigned int b)
+/**
+ * params_access - get the access type from the hw params
+ * @p: hw params
+ */
+static inline snd_pcm_access_t params_access(const struct snd_pcm_hw_params *p)
 {
-	if (a >= UINT_MAX - b)
-		return UINT_MAX;
-	return a + b;
+	return (__force snd_pcm_access_t)snd_mask_min(hw_param_mask_c(p,
+		SNDRV_PCM_HW_PARAM_ACCESS));
 }
 
-static inline unsigned int sub(unsigned int a, unsigned int b)
+/**
+ * params_format - get the sample format from the hw params
+ * @p: hw params
+ */
+static inline snd_pcm_format_t params_format(const struct snd_pcm_hw_params *p)
 {
-	if (a > b)
-		return a - b;
-	return 0;
+	return (__force snd_pcm_format_t)snd_mask_min(hw_param_mask_c(p,
+		SNDRV_PCM_HW_PARAM_FORMAT));
 }
 
-#define params_access(p) ((__force snd_pcm_access_t)\
-		snd_mask_min(hw_param_mask_c((p), SNDRV_PCM_HW_PARAM_ACCESS)))
-#define params_format(p) ((__force snd_pcm_format_t)\
-		snd_mask_min(hw_param_mask_c((p), SNDRV_PCM_HW_PARAM_FORMAT)))
-#define params_subformat(p) \
-	snd_mask_min(hw_param_mask_c((p), SNDRV_PCM_HW_PARAM_SUBFORMAT))
+/**
+ * params_subformat - get the sample subformat from the hw params
+ * @p: hw params
+ */
+static inline snd_pcm_subformat_t
+params_subformat(const struct snd_pcm_hw_params *p)
+{
+	return (__force snd_pcm_subformat_t)snd_mask_min(hw_param_mask_c(p,
+		SNDRV_PCM_HW_PARAM_SUBFORMAT));
+}
 
+/**
+ * params_period_bytes - get the period size (in bytes) from the hw params
+ * @p: hw params
+ */
 static inline unsigned int
 params_period_bytes(const struct snd_pcm_hw_params *p)
 {
-	return (params_period_size(p) *
-		snd_pcm_format_physical_width(params_format(p)) *
-		params_channels(p)) / 8;
+	return hw_param_interval_c(p, SNDRV_PCM_HW_PARAM_PERIOD_BYTES)->min;
 }
 
-static inline int
-params_width(const struct snd_pcm_hw_params *p)
+/**
+ * params_width - get the number of bits of the sample format from the hw params
+ * @p: hw params
+ *
+ * This function returns the number of bits per sample that the selected sample
+ * format of the hw params has.
+ */
+static inline int params_width(const struct snd_pcm_hw_params *p)
 {
 	return snd_pcm_format_width(params_format(p));
 }
 
-static inline int
-params_physical_width(const struct snd_pcm_hw_params *p)
+/*
+ * params_physical_width - get the storage size of the sample format from the hw params
+ * @p: hw params
+ *
+ * This functions returns the number of bits per sample that the selected sample
+ * format of the hw params takes up in memory. This will be equal or larger than
+ * params_width().
+ */
+static inline int params_physical_width(const struct snd_pcm_hw_params *p)
 {
 	return snd_pcm_format_physical_width(params_format(p));
 }
diff --git a/include/sound/sb.h b/include/sound/sb.h
index ba39603..bacefae 100644
--- a/include/sound/sb.h
+++ b/include/sound/sb.h
@@ -25,7 +25,7 @@
 #include <sound/pcm.h>
 #include <sound/rawmidi.h>
 #include <linux/interrupt.h>
-#include <asm/io.h>
+#include <linux/io.h>
 
 enum sb_hw_type {
 	SB_HW_AUTO,
@@ -308,7 +308,7 @@
 #endif
 
 /* sb8_init.c */
-int snd_sb8dsp_pcm(struct snd_sb *chip, int device, struct snd_pcm ** rpcm);
+int snd_sb8dsp_pcm(struct snd_sb *chip, int device);
 /* sb8.c */
 irqreturn_t snd_sb8dsp_interrupt(struct snd_sb *chip);
 int snd_sb8_playback_open(struct snd_pcm_substream *substream);
@@ -317,10 +317,10 @@
 int snd_sb8_capture_close(struct snd_pcm_substream *substream);
 /* midi8.c */
 irqreturn_t snd_sb8dsp_midi_interrupt(struct snd_sb *chip);
-int snd_sb8dsp_midi(struct snd_sb *chip, int device, struct snd_rawmidi ** rrawmidi);
+int snd_sb8dsp_midi(struct snd_sb *chip, int device);
 
 /* sb16_init.c */
-int snd_sb16dsp_pcm(struct snd_sb *chip, int device, struct snd_pcm ** rpcm);
+int snd_sb16dsp_pcm(struct snd_sb *chip, int device);
 const struct snd_pcm_ops *snd_sb16dsp_get_pcm_ops(int direction);
 int snd_sb16dsp_configure(struct snd_sb *chip);
 /* sb16.c */
diff --git a/include/sound/seq_kernel.h b/include/sound/seq_kernel.h
index eea5400..18a2ac5 100644
--- a/include/sound/seq_kernel.h
+++ b/include/sound/seq_kernel.h
@@ -27,11 +27,8 @@
 typedef struct snd_seq_real_time snd_seq_real_time_t;
 typedef union snd_seq_timestamp snd_seq_timestamp_t;
 
-/* maximum number of events dequeued per schedule interval */
-#define SNDRV_SEQ_MAX_DEQUEUE		50
-
 /* maximum number of queues */
-#define SNDRV_SEQ_MAX_QUEUES		8
+#define SNDRV_SEQ_MAX_QUEUES		32
 
 /* max number of concurrent clients */
 #define SNDRV_SEQ_MAX_CLIENTS 		192
@@ -42,9 +39,6 @@
 /* max number of events in memory pool */
 #define SNDRV_SEQ_MAX_EVENTS		2000
 
-/* default number of events in memory chunk */
-#define SNDRV_SEQ_DEFAULT_CHUNK_EVENTS	64
-
 /* default number of events in memory pool */
 #define SNDRV_SEQ_DEFAULT_EVENTS	500
 
@@ -70,7 +64,6 @@
 	int (*unuse)(void *private_data, struct snd_seq_port_subscribe *info);
 	int (*event_input)(struct snd_seq_event *ev, int direct, void *private_data, int atomic, int hop);
 	void (*private_free)(void *private_data);
-	unsigned int callback_all;	/* call subscribe callbacks at each connection/disconnection */
 	/*...*/
 };
 
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h
index 89823cf..ecffecc 100644
--- a/include/sound/soc-dapm.h
+++ b/include/sound/soc-dapm.h
@@ -431,7 +431,6 @@
 					   const char *pin);
 int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm,
 				const char *pin);
-void snd_soc_dapm_auto_nc_pins(struct snd_soc_card *card);
 unsigned int dapm_kcontrol_get_value(const struct snd_kcontrol *kcontrol);
 
 /* Mostly internal - should not normally be used */
diff --git a/include/sound/wss.h b/include/sound/wss.h
index 0c7f034..1823e3a 100644
--- a/include/sound/wss.h
+++ b/include/sound/wss.h
@@ -154,8 +154,8 @@
 		      unsigned short hardware,
 		      unsigned short hwshare,
 		      struct snd_wss **rchip);
-int snd_wss_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm);
-int snd_wss_timer(struct snd_wss *chip, int device, struct snd_timer **rtimer);
+int snd_wss_pcm(struct snd_wss *chip, int device);
+int snd_wss_timer(struct snd_wss *chip, int device);
 int snd_wss_mixer(struct snd_wss *chip);
 
 const struct snd_pcm_ops *snd_wss_get_pcm_ops(int direction);
@@ -167,7 +167,7 @@
 		      unsigned short hardware,
 		      unsigned short hwshare,
 		      struct snd_wss **rchip);
-int snd_cs4236_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm);
+int snd_cs4236_pcm(struct snd_wss *chip, int device);
 int snd_cs4236_mixer(struct snd_wss *chip);
 
 /*
diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h
index 1f23cd6..0e88e7a 100644
--- a/include/uapi/sound/asound.h
+++ b/include/uapi/sound/asound.h
@@ -268,6 +268,7 @@
 #define SNDRV_PCM_INFO_SYNC_START	0x00400000	/* pcm support some kind of sync go */
 #define SNDRV_PCM_INFO_NO_PERIOD_WAKEUP	0x00800000	/* period wakeup can be disabled */
 #define SNDRV_PCM_INFO_HAS_WALL_CLOCK   0x01000000      /* has audio wall clock for audio/system time sync */
+#define SNDRV_PCM_INFO_DRAIN_TRIGGER	0x40000000		/* internal kernel flag - trigger in drain */
 #define SNDRV_PCM_INFO_FIFO_IN_FRAMES	0x80000000	/* internal kernel flag - FIFO size is in frames */
 
 typedef int __bitwise snd_pcm_state_t;
diff --git a/include/uapi/sound/usb_stream.h b/include/uapi/sound/usb_stream.h
new file mode 100644
index 0000000..cfe8fba
--- /dev/null
+++ b/include/uapi/sound/usb_stream.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2007, 2008 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _UAPI__SOUND_USB_STREAM_H
+#define _UAPI__SOUND_USB_STREAM_H
+
+#define USB_STREAM_INTERFACE_VERSION 2
+
+#define SNDRV_USB_STREAM_IOCTL_SET_PARAMS \
+	_IOW('H', 0x90, struct usb_stream_config)
+
+struct usb_stream_packet {
+	unsigned offset;
+	unsigned length;
+};
+
+
+struct usb_stream_config {
+	unsigned version;
+	unsigned sample_rate;
+	unsigned period_frames;
+	unsigned frame_size;
+};
+
+struct usb_stream {
+	struct usb_stream_config cfg;
+	unsigned read_size;
+	unsigned write_size;
+
+	int period_size;
+
+	unsigned state;
+
+	int idle_insize;
+	int idle_outsize;
+	int sync_packet;
+	unsigned insize_done;
+	unsigned periods_done;
+	unsigned periods_polled;
+
+	struct usb_stream_packet outpacket[2];
+	unsigned		 inpackets;
+	unsigned		 inpacket_head;
+	unsigned		 inpacket_split;
+	unsigned		 inpacket_split_at;
+	unsigned		 next_inpacket_split;
+	unsigned		 next_inpacket_split_at;
+	struct usb_stream_packet inpacket[0];
+};
+
+enum usb_stream_state {
+	usb_stream_invalid,
+	usb_stream_stopped,
+	usb_stream_sync0,
+	usb_stream_sync1,
+	usb_stream_ready,
+	usb_stream_running,
+	usb_stream_xrun,
+};
+
+#endif /* _UAPI__SOUND_USB_STREAM_H */
diff --git a/sound/aoa/soundbus/i2sbus/control.c b/sound/aoa/soundbus/i2sbus/control.c
index 4dc9b49..f4495de 100644
--- a/sound/aoa/soundbus/i2sbus/control.c
+++ b/sound/aoa/soundbus/i2sbus/control.c
@@ -9,8 +9,8 @@
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
+#include <linux/io.h>
 
-#include <asm/io.h>
 #include <asm/prom.h>
 #include <asm/macio.h>
 #include <asm/pmac_feature.h>
diff --git a/sound/aoa/soundbus/i2sbus/core.c b/sound/aoa/soundbus/i2sbus/core.c
index 4e2b4fb..b9737fa 100644
--- a/sound/aoa/soundbus/i2sbus/core.c
+++ b/sound/aoa/soundbus/i2sbus/core.c
@@ -74,10 +74,9 @@
 	int i;
 
 	i2sdev = container_of(dev, struct i2sbus_dev, sound.ofdev.dev);
-
- 	if (i2sdev->intfregs) iounmap(i2sdev->intfregs);
- 	if (i2sdev->out.dbdma) iounmap(i2sdev->out.dbdma);
- 	if (i2sdev->in.dbdma) iounmap(i2sdev->in.dbdma);
+	iounmap(i2sdev->intfregs);
+	iounmap(i2sdev->out.dbdma);
+	iounmap(i2sdev->in.dbdma);
 	for (i = aoa_resource_i2smmio; i <= aoa_resource_rxdbdma; i++)
 		release_and_free_resource(i2sdev->allocated_resource[i]);
 	free_dbdma_descriptor_ring(i2sdev, &i2sdev->out.dbdma_ring);
@@ -318,9 +317,9 @@
 			free_irq(dev->interrupts[i], dev);
 	free_dbdma_descriptor_ring(dev, &dev->out.dbdma_ring);
 	free_dbdma_descriptor_ring(dev, &dev->in.dbdma_ring);
-	if (dev->intfregs) iounmap(dev->intfregs);
-	if (dev->out.dbdma) iounmap(dev->out.dbdma);
-	if (dev->in.dbdma) iounmap(dev->in.dbdma);
+	iounmap(dev->intfregs);
+	iounmap(dev->out.dbdma);
+	iounmap(dev->in.dbdma);
 	for (i=0;i<3;i++)
 		release_and_free_resource(dev->allocated_resource[i]);
 	mutex_destroy(&dev->lock);
@@ -381,10 +380,8 @@
 
 	list_for_each_entry(i2sdev, &control->list, item) {
 		/* Notify Alsa */
-		if (i2sdev->sound.pcm) {
-			/* Suspend PCM streams */
-			snd_pcm_suspend_all(i2sdev->sound.pcm);
-		}
+		/* Suspend PCM streams */
+		snd_pcm_suspend_all(i2sdev->sound.pcm);
 
 		/* Notify codecs */
 		list_for_each_entry(cii, &i2sdev->sound.codec_list, list) {
diff --git a/sound/aoa/soundbus/i2sbus/pcm.c b/sound/aoa/soundbus/i2sbus/pcm.c
index a02b7b8..053b09c 100644
--- a/sound/aoa/soundbus/i2sbus/pcm.c
+++ b/sound/aoa/soundbus/i2sbus/pcm.c
@@ -6,7 +6,7 @@
  * GPL v2, can be found in COPYING.
  */
 
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <sound/core.h>
diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c
index 0e83a73..4140b1b 100644
--- a/sound/arm/aaci.c
+++ b/sound/arm/aaci.c
@@ -889,8 +889,8 @@
 static void aaci_free_card(struct snd_card *card)
 {
 	struct aaci *aaci = card->private_data;
-	if (aaci->base)
-		iounmap(aaci->base);
+
+	iounmap(aaci->base);
 }
 
 static struct aaci *aaci_init_card(struct amba_device *dev)
diff --git a/sound/atmel/ac97c.c b/sound/atmel/ac97c.c
index 4f6b14d..cf4cedf 100644
--- a/sound/atmel/ac97c.c
+++ b/sound/atmel/ac97c.c
@@ -22,6 +22,9 @@
 #include <linux/gpio.h>
 #include <linux/types.h>
 #include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/of_device.h>
 
 #include <sound/core.h>
 #include <sound/initval.h>
@@ -34,10 +37,10 @@
 #include <linux/platform_data/dma-dw.h>
 #include <linux/dma/dw.h>
 
+#ifdef CONFIG_AVR32
 #include <mach/cpu.h>
-
-#ifdef CONFIG_ARCH_AT91
-#include <mach/hardware.h>
+#else
+#define cpu_is_at32ap7000() 0
 #endif
 
 #include "ac97c.h"
@@ -902,6 +905,40 @@
 	}
 }
 
+#ifdef CONFIG_OF
+static const struct of_device_id atmel_ac97c_dt_ids[] = {
+	{ .compatible = "atmel,at91sam9263-ac97c", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, atmel_ac97c_dt_ids);
+
+static struct ac97c_platform_data *atmel_ac97c_probe_dt(struct device *dev)
+{
+	struct ac97c_platform_data *pdata;
+	struct device_node *node = dev->of_node;
+	const struct of_device_id *match;
+
+	if (!node) {
+		dev_err(dev, "Device does not have associated DT data\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		return ERR_PTR(-ENOMEM);
+
+	pdata->reset_pin = of_get_named_gpio(dev->of_node, "ac97-gpios", 2);
+
+	return pdata;
+}
+#else
+static struct ac97c_platform_data *atmel_ac97c_probe_dt(struct device *dev)
+{
+	dev_err(dev, "no platform data defined\n");
+	return ERR_PTR(-ENXIO);
+}
+#endif
+
 static int atmel_ac97c_probe(struct platform_device *pdev)
 {
 	struct snd_card			*card;
@@ -922,10 +959,11 @@
 		return -ENXIO;
 	}
 
-	pdata = pdev->dev.platform_data;
+	pdata = dev_get_platdata(&pdev->dev);
 	if (!pdata) {
-		dev_dbg(&pdev->dev, "no platform data\n");
-		return -ENXIO;
+		pdata = atmel_ac97c_probe_dt(&pdev->dev);
+		if (IS_ERR(pdata))
+			return PTR_ERR(pdata);
 	}
 
 	irq = platform_get_irq(pdev, 0);
@@ -1204,6 +1242,7 @@
 	.driver		= {
 		.name	= "atmel_ac97c",
 		.pm	= ATMEL_AC97C_PM_OPS,
+		.of_match_table = of_match_ptr(atmel_ac97c_dt_ids),
 	},
 };
 module_platform_driver(atmel_ac97c_driver);
diff --git a/sound/core/memory.c b/sound/core/memory.c
index 36c0f1a..4cd664e 100644
--- a/sound/core/memory.c
+++ b/sound/core/memory.c
@@ -21,8 +21,8 @@
  */
 
 #include <linux/export.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
 #include <sound/core.h>
 
 /**
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index ada69d7..80423a4c 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -719,7 +719,7 @@
 
 	oss_buffer_size = snd_pcm_plug_client_size(substream,
 						   snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, NULL)) * oss_frame_size;
-	oss_buffer_size = 1 << ld2(oss_buffer_size);
+	oss_buffer_size = rounddown_pow_of_two(oss_buffer_size);
 	if (atomic_read(&substream->mmap_count)) {
 		if (oss_buffer_size > runtime->oss.mmap_bytes)
 			oss_buffer_size = runtime->oss.mmap_bytes;
@@ -755,14 +755,14 @@
 	min_period_size = snd_pcm_plug_client_size(substream,
 						   snd_pcm_hw_param_value_min(slave_params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, NULL));
 	min_period_size *= oss_frame_size;
-	min_period_size = 1 << (ld2(min_period_size - 1) + 1);
+	min_period_size = roundup_pow_of_two(min_period_size);
 	if (oss_period_size < min_period_size)
 		oss_period_size = min_period_size;
 
 	max_period_size = snd_pcm_plug_client_size(substream,
 						   snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, NULL));
 	max_period_size *= oss_frame_size;
-	max_period_size = 1 << ld2(max_period_size);
+	max_period_size = rounddown_pow_of_two(max_period_size);
 	if (oss_period_size > max_period_size)
 		oss_period_size = max_period_size;
 
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index ec9e786..db05e04 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -1299,8 +1299,14 @@
 	int width = l & 0xffff;
 	unsigned int msbits = l >> 16;
 	struct snd_interval *i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS);
-	if (snd_interval_single(i) && snd_interval_value(i) == width)
-		params->msbits = msbits;
+
+	if (!snd_interval_single(i))
+		return 0;
+
+	if ((snd_interval_value(i) == width) ||
+	    (width == 0 && snd_interval_value(i) > msbits))
+		params->msbits = min_not_zero(params->msbits, msbits);
+
 	return 0;
 }
 
@@ -1311,6 +1317,11 @@
  * @width: sample bits width
  * @msbits: msbits width
  *
+ * This constraint will set the number of most significant bits (msbits) if a
+ * sample format with the specified width has been select. If width is set to 0
+ * the msbits will be set for any sample format with a width larger than the
+ * specified msbits.
+ *
  * Return: Zero if successful, or a negative error code on failure.
  */
 int snd_pcm_hw_constraint_msbits(struct snd_pcm_runtime *runtime, 
diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c
index 54debc0..b45f6aa 100644
--- a/sound/core/pcm_memory.c
+++ b/sound/core/pcm_memory.c
@@ -19,7 +19,7 @@
  *
  */
 
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/time.h>
 #include <linux/init.h>
 #include <linux/slab.h>
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 095d957..932234d 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -26,6 +26,7 @@
 #include <linux/time.h>
 #include <linux/pm_qos.h>
 #include <linux/aio.h>
+#include <linux/io.h>
 #include <linux/dma-mapping.h>
 #include <sound/core.h>
 #include <sound/control.h>
@@ -34,7 +35,6 @@
 #include <sound/pcm_params.h>
 #include <sound/timer.h>
 #include <sound/minors.h>
-#include <asm/io.h>
 
 /*
  *  Compatibility
@@ -420,7 +420,8 @@
 
 	hw = &substream->runtime->hw;
 	if (!params->info) {
-		params->info = hw->info & ~SNDRV_PCM_INFO_FIFO_IN_FRAMES;
+		params->info = hw->info & ~(SNDRV_PCM_INFO_FIFO_IN_FRAMES |
+					    SNDRV_PCM_INFO_DRAIN_TRIGGER);
 		if (!hw_support_mmap(substream))
 			params->info &= ~(SNDRV_PCM_INFO_MMAP |
 					  SNDRV_PCM_INFO_MMAP_VALID);
@@ -1566,6 +1567,13 @@
 			snd_pcm_post_stop(substream, new_state);
 		}
 	}
+
+	if (runtime->status->state == SNDRV_PCM_STATE_DRAINING &&
+	    runtime->trigger_master == substream &&
+	    (runtime->hw.info & SNDRV_PCM_INFO_DRAIN_TRIGGER))
+		return substream->ops->trigger(substream,
+					       SNDRV_PCM_TRIGGER_DRAIN);
+
 	return 0;
 }
 
diff --git a/sound/core/seq/oss/seq_oss_midi.c b/sound/core/seq/oss/seq_oss_midi.c
index 3a45696..e79cc44 100644
--- a/sound/core/seq/oss/seq_oss_midi.c
+++ b/sound/core/seq/oss/seq_oss_midi.c
@@ -237,8 +237,7 @@
 		spin_unlock_irqrestore(&register_lock, flags);
 		snd_use_lock_free(&mdev->use_lock);
 		snd_use_lock_sync(&mdev->use_lock);
-		if (mdev->coder)
-			snd_midi_event_free(mdev->coder);
+		snd_midi_event_free(mdev->coder);
 		kfree(mdev);
 	}
 	spin_lock_irqsave(&register_lock, flags);
@@ -265,8 +264,7 @@
 	spin_lock_irqsave(&register_lock, flags);
 	for (i = 0; i < max_midi_devs; i++) {
 		if ((mdev = midi_devs[i]) != NULL) {
-			if (mdev->coder)
-				snd_midi_event_free(mdev->coder);
+			snd_midi_event_free(mdev->coder);
 			kfree(mdev);
 			midi_devs[i] = NULL;
 		}
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
index 2b62cd0..4828765 100644
--- a/sound/core/seq/seq_clientmgr.c
+++ b/sound/core/seq/seq_clientmgr.c
@@ -1133,7 +1133,7 @@
 	/* fill the info fields */
 	info.queues = SNDRV_SEQ_MAX_QUEUES;
 	info.clients = SNDRV_SEQ_MAX_CLIENTS;
-	info.ports = 256;	/* fixed limit */
+	info.ports = SNDRV_SEQ_MAX_PORTS;
 	info.channels = 256;	/* fixed limit */
 	info.cur_clients = client_usage.cur;
 	info.cur_queues = snd_seq_queue_get_cur_queues();
@@ -1279,7 +1279,6 @@
 				port->owner = callback->owner;
 			port->private_data = callback->private_data;
 			port->private_free = callback->private_free;
-			port->callback_all = callback->callback_all;
 			port->event_input = callback->event_input;
 			port->c_src.open = callback->subscribe;
 			port->c_src.close = callback->unsubscribe;
diff --git a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c
index a1fd77a..68fec77 100644
--- a/sound/core/seq/seq_midi.c
+++ b/sound/core/seq/seq_midi.c
@@ -268,8 +268,7 @@
 		snd_seq_event_port_detach(msynth->seq_client, msynth->seq_port);
 	}
 
-	if (msynth->parser)
-		snd_midi_event_free(msynth->parser);
+	snd_midi_event_free(msynth->parser);
 }
 
 /* register new midi synth port */
diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c
index 794a341..46ff593 100644
--- a/sound/core/seq/seq_ports.c
+++ b/sound/core/seq/seq_ports.c
@@ -134,7 +134,7 @@
 	if (snd_BUG_ON(!client))
 		return NULL;
 
-	if (client->num_ports >= SNDRV_SEQ_MAX_PORTS - 1) {
+	if (client->num_ports >= SNDRV_SEQ_MAX_PORTS) {
 		pr_warn("ALSA: seq: too many ports for client %d\n", client->number);
 		return NULL;
 	}
@@ -411,9 +411,6 @@
  * invoked.
  * This feature is useful if these callbacks are associated with
  * initialization or termination of devices (see seq_midi.c).
- *
- * If callback_all option is set, the callback function is invoked
- * at each connection/disconnection. 
  */
 
 static int subscribe_port(struct snd_seq_client *client,
@@ -427,7 +424,7 @@
 	if (!try_module_get(port->owner))
 		return -EFAULT;
 	grp->count++;
-	if (grp->open && (port->callback_all || grp->count == 1)) {
+	if (grp->open && grp->count == 1) {
 		err = grp->open(port->private_data, info);
 		if (err < 0) {
 			module_put(port->owner);
@@ -452,7 +449,7 @@
 	if (! grp->count)
 		return -EINVAL;
 	grp->count--;
-	if (grp->close && (port->callback_all || grp->count == 0))
+	if (grp->close && grp->count == 0)
 		err = grp->close(port->private_data, info);
 	if (send_ack && client->type == USER_CLIENT)
 		snd_seq_client_notify_subscription(port->addr.client, port->addr.port,
diff --git a/sound/core/seq/seq_ports.h b/sound/core/seq/seq_ports.h
index 9d71171..26bd71f 100644
--- a/sound/core/seq/seq_ports.h
+++ b/sound/core/seq/seq_ports.h
@@ -73,7 +73,6 @@
 			   int atomic, int hop);
 	void (*private_free)(void *private_data);
 	void *private_data;
-	unsigned int callback_all : 1;
 	unsigned int closing : 1;
 	unsigned int timestamping: 1;
 	unsigned int time_real: 1;
diff --git a/sound/core/timer.c b/sound/core/timer.c
index 9f0c703..490b489 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -1030,9 +1030,7 @@
 		snd_timer_free(timer);
 		return -ENOMEM;
 	}
-	init_timer(&priv->tlist);
-	priv->tlist.function = snd_timer_s_function;
-	priv->tlist.data = (unsigned long) timer;
+	setup_timer(&priv->tlist, snd_timer_s_function, (unsigned long) timer);
 	timer->private_data = priv;
 	timer->private_free = snd_timer_free_system;
 	return snd_timer_global_register(timer);
diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c
index 7ea5339..7f9126e 100644
--- a/sound/drivers/aloop.c
+++ b/sound/drivers/aloop.c
@@ -181,8 +181,7 @@
 	}
 	tick = dpcm->period_size_frac - dpcm->irq_pos;
 	tick = (tick + dpcm->pcm_bps - 1) / dpcm->pcm_bps;
-	dpcm->timer.expires = jiffies + tick;
-	add_timer(&dpcm->timer);
+	mod_timer(&dpcm->timer, jiffies + tick);
 }
 
 /* call in cable->lock */
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c
index 5d0dfb7..d11baaf 100644
--- a/sound/drivers/dummy.c
+++ b/sound/drivers/dummy.c
@@ -245,9 +245,8 @@
 
 static void dummy_systimer_rearm(struct dummy_systimer_pcm *dpcm)
 {
-	dpcm->timer.expires = jiffies +
-		(dpcm->frac_period_rest + dpcm->rate - 1) / dpcm->rate;
-	add_timer(&dpcm->timer);
+	mod_timer(&dpcm->timer, jiffies +
+		(dpcm->frac_period_rest + dpcm->rate - 1) / dpcm->rate);
 }
 
 static void dummy_systimer_update(struct dummy_systimer_pcm *dpcm)
@@ -340,9 +339,8 @@
 	if (!dpcm)
 		return -ENOMEM;
 	substream->runtime->private_data = dpcm;
-	init_timer(&dpcm->timer);
-	dpcm->timer.data = (unsigned long) dpcm;
-	dpcm->timer.function = dummy_systimer_callback;
+	setup_timer(&dpcm->timer, dummy_systimer_callback,
+			(unsigned long) dpcm);
 	spin_lock_init(&dpcm->lock);
 	dpcm->substream = substream;
 	return 0;
diff --git a/sound/drivers/ml403-ac97cr.c b/sound/drivers/ml403-ac97cr.c
index bcca825..bdcb572 100644
--- a/sound/drivers/ml403-ac97cr.c
+++ b/sound/drivers/ml403-ac97cr.c
@@ -1094,8 +1094,7 @@
 	if (ml403_ac97cr->capture_irq >= 0)
 		free_irq(ml403_ac97cr->capture_irq, ml403_ac97cr);
 	/* give back "port" */
-	if (ml403_ac97cr->port != NULL)
-		iounmap(ml403_ac97cr->port);
+	iounmap(ml403_ac97cr->port);
 	kfree(ml403_ac97cr);
 	PDEBUG(INIT_INFO, "free(): (done)\n");
 	return 0;
@@ -1238,14 +1237,11 @@
 }
 
 static int
-snd_ml403_ac97cr_pcm(struct snd_ml403_ac97cr *ml403_ac97cr, int device,
-		     struct snd_pcm **rpcm)
+snd_ml403_ac97cr_pcm(struct snd_ml403_ac97cr *ml403_ac97cr, int device)
 {
 	struct snd_pcm *pcm;
 	int err;
 
-	if (rpcm)
-		*rpcm = NULL;
 	err = snd_pcm_new(ml403_ac97cr->card, "ML403AC97CR/1", device, 1, 1,
 			  &pcm);
 	if (err < 0)
@@ -1263,8 +1259,6 @@
 					  snd_dma_continuous_data(GFP_KERNEL),
 					  64 * 1024,
 					  128 * 1024);
-	if (rpcm)
-		*rpcm = pcm;
 	return 0;
 }
 
@@ -1298,7 +1292,7 @@
 		return err;
 	}
 	PDEBUG(INIT_INFO, "probe(): mixer done\n");
-	err = snd_ml403_ac97cr_pcm(ml403_ac97cr, 0, NULL);
+	err = snd_ml403_ac97cr_pcm(ml403_ac97cr, 0);
 	if (err < 0) {
 		snd_card_free(card);
 		return err;
diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c
index e3a90d0..776596b 100644
--- a/sound/drivers/mpu401/mpu401_uart.c
+++ b/sound/drivers/mpu401/mpu401_uart.c
@@ -28,7 +28,7 @@
  *
  */
 
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -176,8 +176,7 @@
 
 	spin_lock_irqsave(&mpu->timer_lock, flags);
 	/*mpu->mode |= MPU401_MODE_TIMER;*/
-	mpu->timer.expires = 1 + jiffies;
-	add_timer(&mpu->timer);
+	mod_timer(&mpu->timer,  1 + jiffies);
 	spin_unlock_irqrestore(&mpu->timer_lock, flags);
 	if (mpu->rmidi)
 		_snd_mpu401_uart_interrupt(mpu);
@@ -192,11 +191,9 @@
 
 	spin_lock_irqsave (&mpu->timer_lock, flags);
 	if (mpu->timer_invoked == 0) {
-		init_timer(&mpu->timer);
-		mpu->timer.data = (unsigned long)mpu;
-		mpu->timer.function = snd_mpu401_uart_timer;
-		mpu->timer.expires = 1 + jiffies;
-		add_timer(&mpu->timer);
+		setup_timer(&mpu->timer, snd_mpu401_uart_timer,
+			    (unsigned long)mpu);
+		mod_timer(&mpu->timer, 1 + jiffies);
 	} 
 	mpu->timer_invoked |= input ? MPU401_MODE_INPUT_TIMER :
 		MPU401_MODE_OUTPUT_TIMER;
diff --git a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c
index 1576944..30e8a1d 100644
--- a/sound/drivers/mtpav.c
+++ b/sound/drivers/mtpav.c
@@ -414,8 +414,7 @@
 
 	spin_lock_irqsave(&chip->spinlock, flags);
 	/* reprogram timer */
-	chip->timer.expires = 1 + jiffies;
-	add_timer(&chip->timer);
+	mod_timer(&chip->timer, 1 + jiffies);
 	/* process each port */
 	for (p = 0; p <= chip->num_ports * 2 + MTPAV_PIDX_BROADCAST; p++) {
 		struct mtpav_port *portp = &chip->ports[p];
@@ -428,8 +427,7 @@
 /* spinlock held! */
 static void snd_mtpav_add_output_timer(struct mtpav *chip)
 {
-	chip->timer.expires = 1 + jiffies;
-	add_timer(&chip->timer);
+	mod_timer(&chip->timer, 1 + jiffies);
 }
 
 /* spinlock held! */
@@ -704,15 +702,13 @@
 
 	mtp_card = card->private_data;
 	spin_lock_init(&mtp_card->spinlock);
-	init_timer(&mtp_card->timer);
 	mtp_card->card = card;
 	mtp_card->irq = -1;
 	mtp_card->share_irq = 0;
 	mtp_card->inmidistate = 0;
 	mtp_card->outmidihwport = 0xffffffff;
-	init_timer(&mtp_card->timer);
-	mtp_card->timer.function = snd_mtpav_output_timer;
-	mtp_card->timer.data = (unsigned long) mtp_card;
+	setup_timer(&mtp_card->timer, snd_mtpav_output_timer,
+		    (unsigned long) mtp_card);
 
 	card->private_free = snd_mtpav_free;
 
diff --git a/sound/drivers/opl3/opl3_lib.c b/sound/drivers/opl3/opl3_lib.c
index f66af58..369cef2 100644
--- a/sound/drivers/opl3/opl3_lib.c
+++ b/sound/drivers/opl3/opl3_lib.c
@@ -24,7 +24,7 @@
  */
 
 #include <sound/opl3.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/init.h>
diff --git a/sound/drivers/opl3/opl3_midi.c b/sound/drivers/opl3/opl3_midi.c
index 6c6d09a..f62780e 100644
--- a/sound/drivers/opl3/opl3_midi.c
+++ b/sound/drivers/opl3/opl3_midi.c
@@ -258,12 +258,10 @@
 	spin_unlock_irqrestore(&opl3->voice_lock, flags);
 
 	spin_lock_irqsave(&opl3->sys_timer_lock, flags);
-	if (again) {
-		opl3->tlist.expires = jiffies + 1;	/* invoke again */
-		add_timer(&opl3->tlist);
-	} else {
+	if (again)
+		mod_timer(&opl3->tlist, jiffies + 1);	/* invoke again */
+	else
 		opl3->sys_timer_status = 0;
-	}
 	spin_unlock_irqrestore(&opl3->sys_timer_lock, flags);
 }
 
@@ -275,8 +273,7 @@
 	unsigned long flags;
 	spin_lock_irqsave(&opl3->sys_timer_lock, flags);
 	if (! opl3->sys_timer_status) {
-		opl3->tlist.expires = jiffies + 1;
-		add_timer(&opl3->tlist);
+		mod_timer(&opl3->tlist, jiffies + 1);
 		opl3->sys_timer_status = 1;
 	}
 	spin_unlock_irqrestore(&opl3->sys_timer_lock, flags);
diff --git a/sound/drivers/opl3/opl3_seq.c b/sound/drivers/opl3/opl3_seq.c
index 6839953..a9f618e 100644
--- a/sound/drivers/opl3/opl3_seq.c
+++ b/sound/drivers/opl3/opl3_seq.c
@@ -247,9 +247,7 @@
 	}
 
 	/* setup system timer */
-	init_timer(&opl3->tlist);
-	opl3->tlist.function = snd_opl3_timer_func;
-	opl3->tlist.data = (unsigned long) opl3;
+	setup_timer(&opl3->tlist, snd_opl3_timer_func, (unsigned long) opl3);
 	spin_lock_init(&opl3->sys_timer_lock);
 	opl3->sys_timer_status = 0;
 
diff --git a/sound/drivers/opl4/opl4_lib.c b/sound/drivers/opl4/opl4_lib.c
index b953fb4..3b0ee42 100644
--- a/sound/drivers/opl4/opl4_lib.c
+++ b/sound/drivers/opl4/opl4_lib.c
@@ -23,7 +23,7 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/module.h>
-#include <asm/io.h>
+#include <linux/io.h>
 
 MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
 MODULE_DESCRIPTION("OPL4 driver");
diff --git a/sound/drivers/opl4/opl4_synth.c b/sound/drivers/opl4/opl4_synth.c
index 4b91adc..7bc1e58 100644
--- a/sound/drivers/opl4/opl4_synth.c
+++ b/sound/drivers/opl4/opl4_synth.c
@@ -33,7 +33,7 @@
 
 #include "opl4_local.h"
 #include <linux/delay.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <sound/asoundef.h>
 
 /* GM2 controllers */
diff --git a/sound/drivers/pcsp/pcsp.c b/sound/drivers/pcsp/pcsp.c
index 2adc754..d9647bd 100644
--- a/sound/drivers/pcsp/pcsp.c
+++ b/sound/drivers/pcsp/pcsp.c
@@ -13,7 +13,7 @@
 #include <sound/pcm.h>
 #include <linux/input.h>
 #include <linux/delay.h>
-#include <asm/bitops.h>
+#include <linux/bitops.h>
 #include "pcsp_input.h"
 #include "pcsp.h"
 
diff --git a/sound/drivers/pcsp/pcsp_input.c b/sound/drivers/pcsp/pcsp_input.c
index 0ecf8a4..bfc2581 100644
--- a/sound/drivers/pcsp/pcsp_input.c
+++ b/sound/drivers/pcsp/pcsp_input.c
@@ -14,7 +14,7 @@
 
 #include <linux/init.h>
 #include <linux/input.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include "pcsp.h"
 #include "pcsp_input.h"
 
diff --git a/sound/drivers/pcsp/pcsp_lib.c b/sound/drivers/pcsp/pcsp_lib.c
index 29ebaa4..3689f5f 100644
--- a/sound/drivers/pcsp/pcsp_lib.c
+++ b/sound/drivers/pcsp/pcsp_lib.c
@@ -10,8 +10,8 @@
 #include <linux/gfp.h>
 #include <linux/moduleparam.h>
 #include <linux/interrupt.h>
+#include <linux/io.h>
 #include <sound/pcm.h>
-#include <asm/io.h>
 #include "pcsp.h"
 
 static bool nforce_wa;
diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c
index 13a34e3..1927b89 100644
--- a/sound/drivers/serial-u16550.c
+++ b/sound/drivers/serial-u16550.c
@@ -37,6 +37,7 @@
 #include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/module.h>
+#include <linux/io.h>
 #include <sound/core.h>
 #include <sound/rawmidi.h>
 #include <sound/initval.h>
@@ -44,8 +45,6 @@
 #include <linux/serial_reg.h>
 #include <linux/jiffies.h>
 
-#include <asm/io.h>
-
 MODULE_DESCRIPTION("MIDI serial u16550");
 MODULE_LICENSE("GPL");
 MODULE_SUPPORTED_DEVICE("{{ALSA, MIDI serial u16550}}");
@@ -174,9 +173,8 @@
 {
 	if (!uart->timer_running) {
 		/* timer 38600bps * 10bit * 16byte */
-		uart->buffer_timer.expires = jiffies + (HZ+255)/256;
+		mod_timer(&uart->buffer_timer, jiffies + (HZ + 255) / 256);
 		uart->timer_running = 1;
-		add_timer(&uart->buffer_timer);
 	}
 }
 
@@ -830,9 +828,8 @@
 	uart->prev_in = 0;
 	uart->rstatus = 0;
 	memset(uart->prev_status, 0x80, sizeof(unsigned char) * SNDRV_SERIAL_MAX_OUTS);
-	init_timer(&uart->buffer_timer);
-	uart->buffer_timer.function = snd_uart16550_buffer_timer;
-	uart->buffer_timer.data = (unsigned long)uart;
+	setup_timer(&uart->buffer_timer, snd_uart16550_buffer_timer,
+		    (unsigned long)uart);
 	uart->timer_running = 0;
 
 	/* Register device */
diff --git a/sound/drivers/vx/vx_core.c b/sound/drivers/vx/vx_core.c
index fc05a37..289f041 100644
--- a/sound/drivers/vx/vx_core.c
+++ b/sound/drivers/vx/vx_core.c
@@ -27,11 +27,11 @@
 #include <linux/device.h>
 #include <linux/firmware.h>
 #include <linux/module.h>
+#include <linux/io.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/asoundef.h>
 #include <sound/info.h>
-#include <asm/io.h>
 #include <sound/vx_core.h>
 #include "vx_cmd.h"
 
diff --git a/sound/i2c/other/ak4113.c b/sound/i2c/other/ak4113.c
index 1a3a6fa..8884488 100644
--- a/sound/i2c/other/ak4113.c
+++ b/sound/i2c/other/ak4113.c
@@ -56,8 +56,7 @@
 
 static void snd_ak4113_free(struct ak4113 *chip)
 {
-	chip->init = 1;	/* don't schedule new work */
-	mb();
+	atomic_inc(&chip->wq_processing);	/* don't schedule new work */
 	cancel_delayed_work_sync(&chip->work);
 	kfree(chip);
 }
@@ -89,6 +88,8 @@
 	chip->write = write;
 	chip->private_data = private_data;
 	INIT_DELAYED_WORK(&chip->work, ak4113_stats);
+	atomic_set(&chip->wq_processing, 0);
+	mutex_init(&chip->reinit_mutex);
 
 	for (reg = 0; reg < AK4113_WRITABLE_REGS ; reg++)
 		chip->regmap[reg] = pgm[reg];
@@ -139,13 +140,13 @@
 
 void snd_ak4113_reinit(struct ak4113 *chip)
 {
-	chip->init = 1;
-	mb();
-	flush_delayed_work(&chip->work);
+	if (atomic_inc_return(&chip->wq_processing) == 1)
+		cancel_delayed_work_sync(&chip->work);
+	mutex_lock(&chip->reinit_mutex);
 	ak4113_init_regs(chip);
+	mutex_unlock(&chip->reinit_mutex);
 	/* bring up statistics / event queing */
-	chip->init = 0;
-	if (chip->kctls[0])
+	if (atomic_dec_and_test(&chip->wq_processing))
 		schedule_delayed_work(&chip->work, HZ / 10);
 }
 EXPORT_SYMBOL_GPL(snd_ak4113_reinit);
@@ -632,8 +633,25 @@
 {
 	struct ak4113 *chip = container_of(work, struct ak4113, work.work);
 
-	if (!chip->init)
+	if (atomic_inc_return(&chip->wq_processing) == 1)
 		snd_ak4113_check_rate_and_errors(chip, chip->check_flags);
 
-	schedule_delayed_work(&chip->work, HZ / 10);
+	if (atomic_dec_and_test(&chip->wq_processing))
+		schedule_delayed_work(&chip->work, HZ / 10);
 }
+
+#ifdef CONFIG_PM
+void snd_ak4113_suspend(struct ak4113 *chip)
+{
+	atomic_inc(&chip->wq_processing); /* don't schedule new work */
+	cancel_delayed_work_sync(&chip->work);
+}
+EXPORT_SYMBOL(snd_ak4113_suspend);
+
+void snd_ak4113_resume(struct ak4113 *chip)
+{
+	atomic_dec(&chip->wq_processing);
+	snd_ak4113_reinit(chip);
+}
+EXPORT_SYMBOL(snd_ak4113_resume);
+#endif
diff --git a/sound/i2c/other/ak4114.c b/sound/i2c/other/ak4114.c
index c7f5633..5a4cf3f 100644
--- a/sound/i2c/other/ak4114.c
+++ b/sound/i2c/other/ak4114.c
@@ -66,8 +66,7 @@
 
 static void snd_ak4114_free(struct ak4114 *chip)
 {
-	chip->init = 1;	/* don't schedule new work */
-	mb();
+	atomic_inc(&chip->wq_processing);	/* don't schedule new work */
 	cancel_delayed_work_sync(&chip->work);
 	kfree(chip);
 }
@@ -100,6 +99,8 @@
 	chip->write = write;
 	chip->private_data = private_data;
 	INIT_DELAYED_WORK(&chip->work, ak4114_stats);
+	atomic_set(&chip->wq_processing, 0);
+	mutex_init(&chip->reinit_mutex);
 
 	for (reg = 0; reg < 6; reg++)
 		chip->regmap[reg] = pgm[reg];
@@ -122,6 +123,7 @@
 	snd_ak4114_free(chip);
 	return err < 0 ? err : -EIO;
 }
+EXPORT_SYMBOL(snd_ak4114_create);
 
 void snd_ak4114_reg_write(struct ak4114 *chip, unsigned char reg, unsigned char mask, unsigned char val)
 {
@@ -131,6 +133,7 @@
 		reg_write(chip, reg,
 			  (chip->txcsb[reg-AK4114_REG_TXCSB0] & ~mask) | val);
 }
+EXPORT_SYMBOL(snd_ak4114_reg_write);
 
 static void ak4114_init_regs(struct ak4114 *chip)
 {
@@ -152,15 +155,16 @@
 
 void snd_ak4114_reinit(struct ak4114 *chip)
 {
-	chip->init = 1;
-	mb();
-	flush_delayed_work(&chip->work);
+	if (atomic_inc_return(&chip->wq_processing) == 1)
+		cancel_delayed_work_sync(&chip->work);
+	mutex_lock(&chip->reinit_mutex);
 	ak4114_init_regs(chip);
+	mutex_unlock(&chip->reinit_mutex);
 	/* bring up statistics / event queing */
-	chip->init = 0;
-	if (chip->kctls[0])
+	if (atomic_dec_and_test(&chip->wq_processing))
 		schedule_delayed_work(&chip->work, HZ / 10);
 }
+EXPORT_SYMBOL(snd_ak4114_reinit);
 
 static unsigned int external_rate(unsigned char rcs1)
 {
@@ -505,6 +509,7 @@
 	schedule_delayed_work(&ak4114->work, HZ / 10);
 	return 0;
 }
+EXPORT_SYMBOL(snd_ak4114_build);
 
 /* notify kcontrols if any parameters are changed */
 static void ak4114_notify(struct ak4114 *ak4114,
@@ -560,6 +565,7 @@
 	rcs1 = reg_read(ak4114, AK4114_REG_RCS1);
 	return external_rate(rcs1);
 }
+EXPORT_SYMBOL(snd_ak4114_external_rate);
 
 int snd_ak4114_check_rate_and_errors(struct ak4114 *ak4114, unsigned int flags)
 {
@@ -607,20 +613,30 @@
 	}
 	return res;
 }
+EXPORT_SYMBOL(snd_ak4114_check_rate_and_errors);
 
 static void ak4114_stats(struct work_struct *work)
 {
 	struct ak4114 *chip = container_of(work, struct ak4114, work.work);
 
-	if (!chip->init)
+	if (atomic_inc_return(&chip->wq_processing) == 1)
 		snd_ak4114_check_rate_and_errors(chip, chip->check_flags);
-
-	schedule_delayed_work(&chip->work, HZ / 10);
+	if (atomic_dec_and_test(&chip->wq_processing))
+		schedule_delayed_work(&chip->work, HZ / 10);
 }
 
-EXPORT_SYMBOL(snd_ak4114_create);
-EXPORT_SYMBOL(snd_ak4114_reg_write);
-EXPORT_SYMBOL(snd_ak4114_reinit);
-EXPORT_SYMBOL(snd_ak4114_build);
-EXPORT_SYMBOL(snd_ak4114_external_rate);
-EXPORT_SYMBOL(snd_ak4114_check_rate_and_errors);
+#ifdef CONFIG_PM
+void snd_ak4114_suspend(struct ak4114 *chip)
+{
+	atomic_inc(&chip->wq_processing); /* don't schedule new work */
+	cancel_delayed_work_sync(&chip->work);
+}
+EXPORT_SYMBOL(snd_ak4114_suspend);
+
+void snd_ak4114_resume(struct ak4114 *chip)
+{
+	atomic_dec(&chip->wq_processing);
+	snd_ak4114_reinit(chip);
+}
+EXPORT_SYMBOL(snd_ak4114_resume);
+#endif
diff --git a/sound/i2c/other/ak4117.c b/sound/i2c/other/ak4117.c
index 88452e8..48848909 100644
--- a/sound/i2c/other/ak4117.c
+++ b/sound/i2c/other/ak4117.c
@@ -91,9 +91,7 @@
 	chip->read = read;
 	chip->write = write;
 	chip->private_data = private_data;
-	init_timer(&chip->timer);
-	chip->timer.data = (unsigned long)chip;
-	chip->timer.function = snd_ak4117_timer;
+	setup_timer(&chip->timer, snd_ak4117_timer, (unsigned long)chip);
 
 	for (reg = 0; reg < 5; reg++)
 		chip->regmap[reg] = pgm[reg];
@@ -139,8 +137,7 @@
 	/* release powerdown, everything is initialized now */
 	reg_write(chip, AK4117_REG_PWRDN, old | AK4117_RST | AK4117_PWN);
 	chip->init = 0;
-	chip->timer.expires = 1 + jiffies;
-	add_timer(&chip->timer);
+	mod_timer(&chip->timer, 1 + jiffies);
 }
 
 static unsigned int external_rate(unsigned char rcs1)
@@ -540,8 +537,7 @@
 	if (chip->init)
 		return;
 	snd_ak4117_check_rate_and_errors(chip, 0);
-	chip->timer.expires = 1 + jiffies;
-	add_timer(&chip->timer);
+	mod_timer(&chip->timer, 1 + jiffies);
 }
 
 EXPORT_SYMBOL(snd_ak4117_create);
diff --git a/sound/i2c/other/ak4xxx-adda.c b/sound/i2c/other/ak4xxx-adda.c
index 67dbfde..c657310 100644
--- a/sound/i2c/other/ak4xxx-adda.c
+++ b/sound/i2c/other/ak4xxx-adda.c
@@ -21,7 +21,7 @@
  *
  */
 
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
diff --git a/sound/isa/ad1816a/ad1816a.c b/sound/isa/ad1816a/ad1816a.c
index f481a41..7692265 100644
--- a/sound/isa/ad1816a/ad1816a.c
+++ b/sound/isa/ad1816a/ad1816a.c
@@ -142,7 +142,6 @@
 	struct snd_card *card;
 	struct snd_ad1816a *chip;
 	struct snd_opl3 *opl3;
-	struct snd_timer *timer;
 
 	error = snd_card_new(&pcard->card->dev,
 			     index[dev], id[dev], THIS_MODULE,
@@ -172,7 +171,7 @@
 	sprintf(card->longname, "%s, SS at 0x%lx, irq %d, dma %d&%d",
 		card->shortname, chip->port, irq[dev], dma1[dev], dma2[dev]);
 
-	if ((error = snd_ad1816a_pcm(chip, 0, NULL)) < 0) {
+	if ((error = snd_ad1816a_pcm(chip, 0)) < 0) {
 		snd_card_free(card);
 		return error;
 	}
@@ -182,7 +181,7 @@
 		return error;
 	}
 
-	error = snd_ad1816a_timer(chip, 0, &timer);
+	error = snd_ad1816a_timer(chip, 0);
 	if (error < 0) {
 		snd_card_free(card);
 		return error;
diff --git a/sound/isa/ad1816a/ad1816a_lib.c b/sound/isa/ad1816a/ad1816a_lib.c
index 01a0798..5c815f5 100644
--- a/sound/isa/ad1816a/ad1816a_lib.c
+++ b/sound/isa/ad1816a/ad1816a_lib.c
@@ -22,11 +22,11 @@
 #include <linux/interrupt.h>
 #include <linux/slab.h>
 #include <linux/ioport.h>
+#include <linux/io.h>
 #include <sound/core.h>
 #include <sound/tlv.h>
 #include <sound/ad1816a.h>
 
-#include <asm/io.h>
 #include <asm/dma.h>
 
 static inline int snd_ad1816a_busy_wait(struct snd_ad1816a *chip)
@@ -675,7 +675,7 @@
 	.pointer =	snd_ad1816a_capture_pointer,
 };
 
-int snd_ad1816a_pcm(struct snd_ad1816a *chip, int device, struct snd_pcm **rpcm)
+int snd_ad1816a_pcm(struct snd_ad1816a *chip, int device)
 {
 	int error;
 	struct snd_pcm *pcm;
@@ -697,13 +697,10 @@
 					      64*1024, chip->dma1 > 3 || chip->dma2 > 3 ? 128*1024 : 64*1024);
 
 	chip->pcm = pcm;
-	if (rpcm)
-		*rpcm = pcm;
 	return 0;
 }
 
-int snd_ad1816a_timer(struct snd_ad1816a *chip, int device,
-		      struct snd_timer **rtimer)
+int snd_ad1816a_timer(struct snd_ad1816a *chip, int device)
 {
 	struct snd_timer *timer;
 	struct snd_timer_id tid;
@@ -720,8 +717,6 @@
 	timer->private_data = chip;
 	chip->timer = timer;
 	timer->hw = snd_ad1816a_timer_table;
-	if (rtimer)
-		*rtimer = timer;
 	return 0;
 }
 
diff --git a/sound/isa/ad1848/ad1848.c b/sound/isa/ad1848/ad1848.c
index 093f22a..f159da4e 100644
--- a/sound/isa/ad1848/ad1848.c
+++ b/sound/isa/ad1848/ad1848.c
@@ -88,7 +88,6 @@
 {
 	struct snd_card *card;
 	struct snd_wss *chip;
-	struct snd_pcm *pcm;
 	int error;
 
 	error = snd_card_new(dev, index[n], id[n], THIS_MODULE, 0, &card);
@@ -103,7 +102,7 @@
 
 	card->private_data = chip;
 
-	error = snd_wss_pcm(chip, 0, &pcm);
+	error = snd_wss_pcm(chip, 0);
 	if (error < 0)
 		goto out;
 
@@ -112,10 +111,10 @@
 		goto out;
 
 	strcpy(card->driver, "AD1848");
-	strcpy(card->shortname, pcm->name);
+	strcpy(card->shortname, chip->pcm->name);
 
 	sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d",
-		pcm->name, chip->port, irq[n], dma1[n]);
+		chip->pcm->name, chip->port, irq[n], dma1[n]);
 	if (thinkpad[n])
 		strcat(card->longname, " [Thinkpad]");
 
diff --git a/sound/isa/als100.c b/sound/isa/als100.c
index 32d0152..bc9ea30 100644
--- a/sound/isa/als100.c
+++ b/sound/isa/als100.c
@@ -233,7 +233,7 @@
 			irq[dev], dma8[dev], dma16[dev]);
 	}
 
-	if ((error = snd_sb16dsp_pcm(chip, 0, &chip->pcm)) < 0) {
+	if ((error = snd_sb16dsp_pcm(chip, 0)) < 0) {
 		snd_card_free(card);
 		return error;
 	}
diff --git a/sound/isa/azt2320.c b/sound/isa/azt2320.c
index 0ea75fc..fff186f 100644
--- a/sound/isa/azt2320.c
+++ b/sound/isa/azt2320.c
@@ -29,7 +29,7 @@
     activation method (full-duplex audio!).
 */
 
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/time.h>
@@ -215,7 +215,7 @@
 	sprintf(card->longname, "%s, WSS at 0x%lx, irq %i, dma %i&%i",
 		card->shortname, chip->port, irq[dev], dma1[dev], dma2[dev]);
 
-	error = snd_wss_pcm(chip, 0, NULL);
+	error = snd_wss_pcm(chip, 0);
 	if (error < 0) {
 		snd_card_free(card);
 		return error;
@@ -225,7 +225,7 @@
 		snd_card_free(card);
 		return error;
 	}
-	error = snd_wss_timer(chip, 0, NULL);
+	error = snd_wss_timer(chip, 0);
 	if (error < 0) {
 		snd_card_free(card);
 		return error;
diff --git a/sound/isa/cmi8328.c b/sound/isa/cmi8328.c
index 4778852..2c89d95 100644
--- a/sound/isa/cmi8328.c
+++ b/sound/isa/cmi8328.c
@@ -307,7 +307,7 @@
 	if (err < 0)
 		goto error;
 
-	err = snd_wss_pcm(cmi->wss, 0, NULL);
+	err = snd_wss_pcm(cmi->wss, 0);
 	if (err < 0)
 		goto error;
 
@@ -318,7 +318,7 @@
 	if (err < 0)
 		goto error;
 
-	if (snd_wss_timer(cmi->wss, 0, NULL) < 0)
+	if (snd_wss_timer(cmi->wss, 0) < 0)
 		snd_printk(KERN_WARNING "error initializing WSS timer\n");
 
 	if (mpuport[ndev] == SNDRV_AUTO_PORT) {
diff --git a/sound/isa/cs423x/cs4231.c b/sound/isa/cs423x/cs4231.c
index 7dba07a..282cd75 100644
--- a/sound/isa/cs423x/cs4231.c
+++ b/sound/isa/cs423x/cs4231.c
@@ -92,7 +92,6 @@
 {
 	struct snd_card *card;
 	struct snd_wss *chip;
-	struct snd_pcm *pcm;
 	int error;
 
 	error = snd_card_new(dev, index[n], id[n], THIS_MODULE, 0, &card);
@@ -106,15 +105,15 @@
 
 	card->private_data = chip;
 
-	error = snd_wss_pcm(chip, 0, &pcm);
+	error = snd_wss_pcm(chip, 0);
 	if (error < 0)
 		goto out;
 
 	strcpy(card->driver, "CS4231");
-	strcpy(card->shortname, pcm->name);
+	strcpy(card->shortname, chip->pcm->name);
 
 	sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d",
-		pcm->name, chip->port, irq[n], dma1[n]);
+		chip->pcm->name, chip->port, irq[n], dma1[n]);
 	if (dma2[n] >= 0)
 		sprintf(card->longname + strlen(card->longname), "&%d", dma2[n]);
 
@@ -122,7 +121,7 @@
 	if (error < 0)
 		goto out;
 
-	error = snd_wss_timer(chip, 0, NULL);
+	error = snd_wss_timer(chip, 0);
 	if (error < 0)
 		goto out;
 
diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c
index 750f51c..9d7582c 100644
--- a/sound/isa/cs423x/cs4236.c
+++ b/sound/isa/cs423x/cs4236.c
@@ -382,7 +382,6 @@
 static int snd_cs423x_probe(struct snd_card *card, int dev)
 {
 	struct snd_card_cs4236 *acard;
-	struct snd_pcm *pcm;
 	struct snd_wss *chip;
 	struct snd_opl3 *opl3;
 	int err;
@@ -404,7 +403,7 @@
 	acard->chip = chip;
 	if (chip->hardware & WSS_HW_CS4236B_MASK) {
 
-		err = snd_cs4236_pcm(chip, 0, &pcm);
+		err = snd_cs4236_pcm(chip, 0);
 		if (err < 0)
 			return err;
 
@@ -412,7 +411,7 @@
 		if (err < 0)
 			return err;
 	} else {
-		err = snd_wss_pcm(chip, 0, &pcm);
+		err = snd_wss_pcm(chip, 0);
 		if (err < 0)
 			return err;
 
@@ -420,17 +419,17 @@
 		if (err < 0)
 			return err;
 	}
-	strcpy(card->driver, pcm->name);
-	strcpy(card->shortname, pcm->name);
+	strcpy(card->driver, chip->pcm->name);
+	strcpy(card->shortname, chip->pcm->name);
 	sprintf(card->longname, "%s at 0x%lx, irq %i, dma %i",
-		pcm->name,
+		chip->pcm->name,
 		chip->port,
 		irq[dev],
 		dma1[dev]);
 	if (dma2[dev] >= 0)
 		sprintf(card->longname + strlen(card->longname), "&%d", dma2[dev]);
 
-	err = snd_wss_timer(chip, 0, NULL);
+	err = snd_wss_timer(chip, 0);
 	if (err < 0)
 		return err;
 
diff --git a/sound/isa/cs423x/cs4236_lib.c b/sound/isa/cs423x/cs4236_lib.c
index c5adca3..2b7cc59 100644
--- a/sound/isa/cs423x/cs4236_lib.c
+++ b/sound/isa/cs423x/cs4236_lib.c
@@ -79,7 +79,7 @@
  *
  */
 
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/time.h>
@@ -376,17 +376,14 @@
 	return 0;
 }
 
-int snd_cs4236_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm)
+int snd_cs4236_pcm(struct snd_wss *chip, int device)
 {
-	struct snd_pcm *pcm;
 	int err;
 	
-	err = snd_wss_pcm(chip, device, &pcm);
+	err = snd_wss_pcm(chip, device);
 	if (err < 0)
 		return err;
-	pcm->info_flags &= ~SNDRV_PCM_INFO_JOINT_DUPLEX;
-	if (rpcm)
-		*rpcm = pcm;
+	chip->pcm->info_flags &= ~SNDRV_PCM_INFO_JOINT_DUPLEX;
 	return 0;
 }
 
diff --git a/sound/isa/es1688/es1688.c b/sound/isa/es1688/es1688.c
index 76001fe0..1901c2b 100644
--- a/sound/isa/es1688/es1688.c
+++ b/sound/isa/es1688/es1688.c
@@ -138,10 +138,9 @@
 {
 	struct snd_es1688 *chip = card->private_data;
 	struct snd_opl3 *opl3;
-	struct snd_pcm *pcm;
 	int error;
 
-	error = snd_es1688_pcm(card, chip, 0, &pcm);
+	error = snd_es1688_pcm(card, chip, 0);
 	if (error < 0)
 		return error;
 
@@ -150,9 +149,9 @@
 		return error;
 
 	strlcpy(card->driver, "ES1688", sizeof(card->driver));
-	strlcpy(card->shortname, pcm->name, sizeof(card->shortname));
+	strlcpy(card->shortname, chip->pcm->name, sizeof(card->shortname));
 	snprintf(card->longname, sizeof(card->longname),
-		"%s at 0x%lx, irq %i, dma %i", pcm->name, chip->port,
+		"%s at 0x%lx, irq %i, dma %i", chip->pcm->name, chip->port,
 		 chip->irq, chip->dma8);
 
 	if (fm_port[n] == SNDRV_AUTO_PORT)
diff --git a/sound/isa/es1688/es1688_lib.c b/sound/isa/es1688/es1688_lib.c
index b545014..e2cf508 100644
--- a/sound/isa/es1688/es1688_lib.c
+++ b/sound/isa/es1688/es1688_lib.c
@@ -25,11 +25,11 @@
 #include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/module.h>
+#include <linux/io.h>
 #include <sound/core.h>
 #include <sound/es1688.h>
 #include <sound/initval.h>
 
-#include <asm/io.h>
 #include <asm/dma.h>
 
 MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
@@ -728,8 +728,7 @@
 	.pointer =		snd_es1688_capture_pointer,
 };
 
-int snd_es1688_pcm(struct snd_card *card, struct snd_es1688 *chip,
-		   int device, struct snd_pcm **rpcm)
+int snd_es1688_pcm(struct snd_card *card, struct snd_es1688 *chip, int device)
 {
 	struct snd_pcm *pcm;
 	int err;
@@ -749,9 +748,6 @@
 	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
 					      snd_dma_isa_data(),
 					      64*1024, 64*1024);
-
-	if (rpcm)
-		*rpcm = pcm;
 	return 0;
 }
 
diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c
index b481bb8..5094b62 100644
--- a/sound/isa/es18xx.c
+++ b/sound/isa/es18xx.c
@@ -84,8 +84,8 @@
 #include <linux/isapnp.h>
 #include <linux/module.h>
 #include <linux/delay.h>
+#include <linux/io.h>
 
-#include <asm/io.h>
 #include <asm/dma.h>
 #include <sound/core.h>
 #include <sound/control.h>
@@ -1687,16 +1687,13 @@
 	.pointer =	snd_es18xx_capture_pointer,
 };
 
-static int snd_es18xx_pcm(struct snd_card *card, int device,
-			  struct snd_pcm **rpcm)
+static int snd_es18xx_pcm(struct snd_card *card, int device)
 {
 	struct snd_es18xx *chip = card->private_data;
         struct snd_pcm *pcm;
 	char str[16];
 	int err;
 
-	if (rpcm)
-		*rpcm = NULL;
 	sprintf(str, "ES%x", chip->version);
 	if (chip->caps & ES18XX_PCM2)
 		err = snd_pcm_new(card, str, device, 2, 1, &pcm);
@@ -1722,9 +1719,6 @@
 					      snd_dma_isa_data(),
 					      64*1024,
 					      chip->dma1 > 3 || chip->dma2 > 3 ? 128*1024 : 64*1024);
-
-        if (rpcm)
-        	*rpcm = pcm;
 	return 0;
 }
 
@@ -2154,7 +2148,7 @@
 			chip->port,
 			irq[dev], dma1[dev]);
 
-	err = snd_es18xx_pcm(card, 0, NULL);
+	err = snd_es18xx_pcm(card, 0);
 	if (err < 0)
 		return err;
 
diff --git a/sound/isa/galaxy/galaxy.c b/sound/isa/galaxy/galaxy.c
index 1eb2b1e..3227884 100644
--- a/sound/isa/galaxy/galaxy.c
+++ b/sound/isa/galaxy/galaxy.c
@@ -569,7 +569,7 @@
 	if (err < 0)
 		goto error;
 
-	err = snd_wss_pcm(chip, 0, NULL);
+	err = snd_wss_pcm(chip, 0);
 	if (err < 0)
 		goto error;
 
@@ -577,7 +577,7 @@
 	if (err < 0)
 		goto error;
 
-	err = snd_wss_timer(chip, 0, NULL);
+	err = snd_wss_timer(chip, 0);
 	if (err < 0)
 		goto error;
 
diff --git a/sound/isa/gus/gus_instr.c b/sound/isa/gus/gus_instr.c
deleted file mode 100644
index 4dc9caf..0000000
--- a/sound/isa/gus/gus_instr.c
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- *  Routines for Gravis UltraSound soundcards - Synthesizer
- *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
- *
- *
- *   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/time.h>
-#include <sound/core.h>
-#include <sound/gus.h>
-
-/*
- *
- */
-
-int snd_gus_iwffff_put_sample(void *private_data, struct iwffff_wave *wave,
-			      char __user *data, long len, int atomic)
-{
-	struct snd_gus_card *gus = private_data;
-	struct snd_gf1_mem_block *block;
-	int err;
-
-	if (wave->format & IWFFFF_WAVE_ROM)
-		return 0;	/* it's probably ok - verify the address? */
-	if (wave->format & IWFFFF_WAVE_STEREO)
-		return -EINVAL;	/* not supported */
-	block = snd_gf1_mem_alloc(&gus->gf1.mem_alloc,
-				  SNDRV_GF1_MEM_OWNER_WAVE_IWFFFF,
-				  NULL, wave->size,
-				  wave->format & IWFFFF_WAVE_16BIT, 1,
-				  wave->share_id);
-	if (block == NULL)
-		return -ENOMEM;
-	err = snd_gus_dram_write(gus, data,
-				 block->ptr, wave->size);
-	if (err < 0) {
-		snd_gf1_mem_lock(&gus->gf1.mem_alloc, 0);
-		snd_gf1_mem_xfree(&gus->gf1.mem_alloc, block);
-		snd_gf1_mem_lock(&gus->gf1.mem_alloc, 1);
-		return err;
-	}
-	wave->address.memory = block->ptr;
-	return 0;
-}
-
-int snd_gus_iwffff_get_sample(void *private_data, struct iwffff_wave *wave,
-			      char __user *data, long len, int atomic)
-{
-	struct snd_gus_card *gus = private_data;
-
-	return snd_gus_dram_read(gus, data, wave->address.memory, wave->size,
-				 wave->format & IWFFFF_WAVE_ROM ? 1 : 0);
-}
-
-int snd_gus_iwffff_remove_sample(void *private_data, struct iwffff_wave *wave,
-				 int atomic)
-{
-	struct snd_gus_card *gus = private_data;
-
-	if (wave->format & IWFFFF_WAVE_ROM)
-		return 0;	/* it's probably ok - verify the address? */	
-	return snd_gf1_mem_free(&gus->gf1.mem_alloc, wave->address.memory);
-}
-
-/*
- *
- */
-
-int snd_gus_gf1_put_sample(void *private_data, struct gf1_wave *wave,
-			   char __user *data, long len, int atomic)
-{
-	struct snd_gus_card *gus = private_data;
-	struct snd_gf1_mem_block *block;
-	int err;
-
-	if (wave->format & GF1_WAVE_STEREO)
-		return -EINVAL;	/* not supported */
-	block = snd_gf1_mem_alloc(&gus->gf1.mem_alloc,
-				  SNDRV_GF1_MEM_OWNER_WAVE_GF1,
-				  NULL, wave->size,
-				  wave->format & GF1_WAVE_16BIT, 1,
-				  wave->share_id);
-	if (block == NULL)
-		return -ENOMEM;
-	err = snd_gus_dram_write(gus, data,
-				 block->ptr, wave->size);
-	if (err < 0) {
-		snd_gf1_mem_lock(&gus->gf1.mem_alloc, 0);
-		snd_gf1_mem_xfree(&gus->gf1.mem_alloc, block);
-		snd_gf1_mem_lock(&gus->gf1.mem_alloc, 1);
-		return err;
-	}
-	wave->address.memory = block->ptr;
-	return 0;
-}
-
-int snd_gus_gf1_get_sample(void *private_data, struct gf1_wave *wave,
-			   char __user *data, long len, int atomic)
-{
-	struct snd_gus_card *gus = private_data;
-
-	return snd_gus_dram_read(gus, data, wave->address.memory, wave->size, 0);
-}
-
-int snd_gus_gf1_remove_sample(void *private_data, struct gf1_wave *wave,
-			      int atomic)
-{
-	struct snd_gus_card *gus = private_data;
-
-	return snd_gf1_mem_free(&gus->gf1.mem_alloc, wave->address.memory);
-}
-
-/*
- *
- */
-
-int snd_gus_simple_put_sample(void *private_data, struct simple_instrument *instr,
-			      char __user *data, long len, int atomic)
-{
-	struct snd_gus_card *gus = private_data;
-	struct snd_gf1_mem_block *block;
-	int err;
-
-	if (instr->format & SIMPLE_WAVE_STEREO)
-		return -EINVAL;	/* not supported */
-	block = snd_gf1_mem_alloc(&gus->gf1.mem_alloc,
-				  SNDRV_GF1_MEM_OWNER_WAVE_SIMPLE,
-				  NULL, instr->size,
-				  instr->format & SIMPLE_WAVE_16BIT, 1,
-				  instr->share_id);
-	if (block == NULL)
-		return -ENOMEM;
-	err = snd_gus_dram_write(gus, data, block->ptr, instr->size);
-	if (err < 0) {
-		snd_gf1_mem_lock(&gus->gf1.mem_alloc, 0);
-		snd_gf1_mem_xfree(&gus->gf1.mem_alloc, block);
-		snd_gf1_mem_lock(&gus->gf1.mem_alloc, 1);
-		return err;
-	}
-	instr->address.memory = block->ptr;
-	return 0;
-}
-
-int snd_gus_simple_get_sample(void *private_data, struct simple_instrument *instr,
-			      char __user *data, long len, int atomic)
-{
-	struct snd_gus_card *gus = private_data;
-
-	return snd_gus_dram_read(gus, data, instr->address.memory, instr->size, 0);
-}
-
-int snd_gus_simple_remove_sample(void *private_data, struct simple_instrument *instr,
-			         int atomic)
-{
-	struct snd_gus_card *gus = private_data;
-
-	return snd_gf1_mem_free(&gus->gf1.mem_alloc, instr->address.memory);
-}
diff --git a/sound/isa/gus/gus_pcm.c b/sound/isa/gus/gus_pcm.c
index 2dcf45b..25f6788 100644
--- a/sound/isa/gus/gus_pcm.c
+++ b/sound/isa/gus/gus_pcm.c
@@ -849,7 +849,7 @@
 	.pointer =	snd_gf1_pcm_capture_pointer,
 };
 
-int snd_gf1_pcm_new(struct snd_gus_card * gus, int pcm_dev, int control_index, struct snd_pcm ** rpcm)
+int snd_gf1_pcm_new(struct snd_gus_card *gus, int pcm_dev, int control_index)
 {
 	struct snd_card *card;
 	struct snd_kcontrol *kctl;
@@ -857,8 +857,6 @@
 	struct snd_pcm_substream *substream;
 	int capture, err;
 
-	if (rpcm)
-		*rpcm = NULL;
 	card = gus->card;
 	capture = !gus->interwave && !gus->ess_flag && !gus->ace_flag ? 1 : 0;
 	err = snd_pcm_new(card,
@@ -903,8 +901,6 @@
 		return err;
 	kctl->id.index = control_index;
 
-	if (rpcm)
-		*rpcm = pcm;
 	return 0;
 }
 
diff --git a/sound/isa/gus/gus_uart.c b/sound/isa/gus/gus_uart.c
index 21cc42e..3992912 100644
--- a/sound/isa/gus/gus_uart.c
+++ b/sound/isa/gus/gus_uart.c
@@ -241,13 +241,11 @@
 	.trigger =	snd_gf1_uart_input_trigger,
 };
 
-int snd_gf1_rawmidi_new(struct snd_gus_card * gus, int device, struct snd_rawmidi ** rrawmidi)
+int snd_gf1_rawmidi_new(struct snd_gus_card *gus, int device)
 {
 	struct snd_rawmidi *rmidi;
 	int err;
 
-	if (rrawmidi)
-		*rrawmidi = NULL;
 	if ((err = snd_rawmidi_new(gus->card, "GF1", device, 1, 1, &rmidi)) < 0)
 		return err;
 	strcpy(rmidi->name, gus->interwave ? "AMD InterWave" : "GF1");
@@ -256,7 +254,5 @@
 	rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX;
 	rmidi->private_data = gus;
 	gus->midi_uart = rmidi;
-	if (rrawmidi)
-		*rrawmidi = rmidi;
 	return err;
 }
diff --git a/sound/isa/gus/gusclassic.c b/sound/isa/gus/gusclassic.c
index 7ce29ff..f001971 100644
--- a/sound/isa/gus/gusclassic.c
+++ b/sound/isa/gus/gusclassic.c
@@ -181,12 +181,12 @@
 	if (error < 0)
 		goto out;
 
-	error = snd_gf1_pcm_new(gus, 0, 0, NULL);
+	error = snd_gf1_pcm_new(gus, 0, 0);
 	if (error < 0)
 		goto out;
 
 	if (!gus->ace_flag) {
-		error = snd_gf1_rawmidi_new(gus, 0, NULL);
+		error = snd_gf1_rawmidi_new(gus, 0);
 		if (error < 0)
 			goto out;
 	}
diff --git a/sound/isa/gus/gusextreme.c b/sound/isa/gus/gusextreme.c
index 28a1693..693d95f 100644
--- a/sound/isa/gus/gusextreme.c
+++ b/sound/isa/gus/gusextreme.c
@@ -284,7 +284,7 @@
 	}
 	gus->codec_flag = 1;
 
-	error = snd_es1688_pcm(card, es1688, 0, NULL);
+	error = snd_es1688_pcm(card, es1688, 0);
 	if (error < 0)
 		goto out;
 
@@ -295,7 +295,7 @@
 	snd_component_add(card, "ES1688");
 
 	if (pcm_channels[n] > 0) {
-		error = snd_gf1_pcm_new(gus, 1, 1, NULL);
+		error = snd_gf1_pcm_new(gus, 1, 1);
 		if (error < 0)
 			goto out;
 	}
diff --git a/sound/isa/gus/gusmax.c b/sound/isa/gus/gusmax.c
index 39df36c..8216e8d 100644
--- a/sound/isa/gus/gusmax.c
+++ b/sound/isa/gus/gusmax.c
@@ -309,7 +309,7 @@
 	if (err < 0)
 		goto _err;
 
-	err = snd_wss_pcm(wss, 0, NULL);
+	err = snd_wss_pcm(wss, 0);
 	if (err < 0)
 		goto _err;
 
@@ -317,19 +317,19 @@
 	if (err < 0)
 		goto _err;
 
-	err = snd_wss_timer(wss, 2, NULL);
+	err = snd_wss_timer(wss, 2);
 	if (err < 0)
 		goto _err;
 
 	if (pcm_channels[dev] > 0) {
-		if ((err = snd_gf1_pcm_new(gus, 1, 1, NULL)) < 0)
+		if ((err = snd_gf1_pcm_new(gus, 1, 1)) < 0)
 			goto _err;
 	}
 	err = snd_gusmax_mixer(wss);
 	if (err < 0)
 		goto _err;
 
-	err = snd_gf1_rawmidi_new(gus, 0, NULL);
+	err = snd_gf1_rawmidi_new(gus, 0);
 	if (err < 0)
 		goto _err;
 
diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c
index ad55e5c..70d0040 100644
--- a/sound/isa/gus/interwave.c
+++ b/sound/isa/gus/interwave.c
@@ -647,7 +647,6 @@
 #ifdef SNDRV_STB
 	struct snd_i2c_bus *i2c_bus;
 #endif
-	struct snd_pcm *pcm;
 	char *str;
 	int err;
 
@@ -695,14 +694,15 @@
 	if (err < 0)
 		return err;
 
-	err = snd_wss_pcm(wss, 0, &pcm);
+	err = snd_wss_pcm(wss, 0);
 	if (err < 0)
 		return err;
 
-	sprintf(pcm->name + strlen(pcm->name), " rev %c", gus->revision + 'A');
-	strcat(pcm->name, " (codec)");
+	sprintf(wss->pcm->name + strlen(wss->pcm->name), " rev %c",
+		gus->revision + 'A');
+	strcat(wss->pcm->name, " (codec)");
 
-	err = snd_wss_timer(wss, 2, NULL);
+	err = snd_wss_timer(wss, 2);
 	if (err < 0)
 		return err;
 
@@ -711,7 +711,7 @@
 		return err;
 
 	if (pcm_channels[dev] > 0) {
-		err = snd_gf1_pcm_new(gus, 1, 1, NULL);
+		err = snd_gf1_pcm_new(gus, 1, 1);
 		if (err < 0)
 			return err;
 	}
@@ -740,7 +740,7 @@
 #endif
 
 	gus->uart_enable = midi[dev];
-	if ((err = snd_gf1_rawmidi_new(gus, 0, NULL)) < 0)
+	if ((err = snd_gf1_rawmidi_new(gus, 0)) < 0)
 		return err;
 
 #ifndef SNDRV_STB
diff --git a/sound/isa/msnd/msnd.c b/sound/isa/msnd/msnd.c
index 1cee18f..835d4aa 100644
--- a/sound/isa/msnd/msnd.c
+++ b/sound/isa/msnd/msnd.c
@@ -679,8 +679,7 @@
 };
 
 
-int snd_msnd_pcm(struct snd_card *card, int device,
-			struct snd_pcm **rpcm)
+int snd_msnd_pcm(struct snd_card *card, int device)
 {
 	struct snd_msnd *chip = card->private_data;
 	struct snd_pcm	*pcm;
@@ -696,9 +695,6 @@
 	pcm->private_data = chip;
 	strcpy(pcm->name, "Hurricane");
 
-
-	if (rpcm)
-		*rpcm = pcm;
 	return 0;
 }
 EXPORT_SYMBOL(snd_msnd_pcm);
diff --git a/sound/isa/msnd/msnd.h b/sound/isa/msnd/msnd.h
index dbac3a4..5f3c7dc 100644
--- a/sound/isa/msnd/msnd.h
+++ b/sound/isa/msnd/msnd.h
@@ -297,7 +297,7 @@
 void snd_msnd_dsp_halt(struct snd_msnd *chip, struct file *file);
 int snd_msnd_DAPQ(struct snd_msnd *chip, int start);
 int snd_msnd_DARQ(struct snd_msnd *chip, int start);
-int snd_msnd_pcm(struct snd_card *card, int device, struct snd_pcm **rpcm);
+int snd_msnd_pcm(struct snd_card *card, int device);
 
 int snd_msndmidi_new(struct snd_card *card, int device);
 void snd_msndmidi_input_read(void *mpu);
diff --git a/sound/isa/msnd/msnd_pinnacle.c b/sound/isa/msnd/msnd_pinnacle.c
index 5016bf9..4c07266 100644
--- a/sound/isa/msnd/msnd_pinnacle.c
+++ b/sound/isa/msnd/msnd_pinnacle.c
@@ -582,7 +582,7 @@
 	if (err < 0)
 		goto err_release_region;
 
-	err = snd_msnd_pcm(card, 0, NULL);
+	err = snd_msnd_pcm(card, 0);
 	if (err < 0) {
 		printk(KERN_ERR LOGNAME ": error creating new PCM device\n");
 		goto err_release_region;
@@ -627,8 +627,7 @@
 	return 0;
 
 err_release_region:
-	if (chip->mappedbase)
-		iounmap(chip->mappedbase);
+	iounmap(chip->mappedbase);
 	release_mem_region(chip->base, BUFFSIZE);
 	release_region(chip->io, DSP_NUMIO);
 	free_irq(chip->irq, chip);
diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c
index a219bc3..ae13363 100644
--- a/sound/isa/opl3sa2.c
+++ b/sound/isa/opl3sa2.c
@@ -26,6 +26,7 @@
 #include <linux/pm.h>
 #include <linux/pnp.h>
 #include <linux/module.h>
+#include <linux/io.h>
 #include <sound/core.h>
 #include <sound/wss.h>
 #include <sound/mpu401.h>
@@ -33,8 +34,6 @@
 #include <sound/initval.h>
 #include <sound/tlv.h>
 
-#include <asm/io.h>
-
 MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
 MODULE_DESCRIPTION("Yamaha OPL3SA2+");
 MODULE_LICENSE("GPL");
@@ -684,7 +683,7 @@
 		return err;
 	}
 	chip->wss = wss;
-	err = snd_wss_pcm(wss, 0, NULL);
+	err = snd_wss_pcm(wss, 0);
 	if (err < 0)
 		return err;
 	err = snd_wss_mixer(wss);
@@ -693,7 +692,7 @@
 	err = snd_opl3sa2_mixer(card);
 	if (err < 0)
 		return err;
-	err = snd_wss_timer(wss, 0, NULL);
+	err = snd_wss_timer(wss, 0);
 	if (err < 0)
 		return err;
 	if (fm_port[dev] >= 0x340 && fm_port[dev] < 0x400) {
diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c
index c2ca681..3a9067d 100644
--- a/sound/isa/opti9xx/miro.c
+++ b/sound/isa/opti9xx/miro.c
@@ -29,7 +29,7 @@
 #include <linux/delay.h>
 #include <linux/ioport.h>
 #include <linux/module.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <asm/dma.h>
 #include <sound/core.h>
 #include <sound/wss.h>
@@ -1270,8 +1270,6 @@
 	int error;
 	struct snd_miro *miro = card->private_data;
 	struct snd_wss *codec;
-	struct snd_timer *timer;
-	struct snd_pcm *pcm;
 	struct snd_rawmidi *rmidi;
 
 	if (!miro->res_mc_base) {
@@ -1310,7 +1308,7 @@
 	if (error < 0)
 		return error;
 
-	error = snd_wss_pcm(codec, 0, &pcm);
+	error = snd_wss_pcm(codec, 0);
 	if (error < 0)
 		return error;
 
@@ -1318,11 +1316,11 @@
 	if (error < 0)
 		return error;
 
-	error = snd_wss_timer(codec, 0, &timer);
+	error = snd_wss_timer(codec, 0);
 	if (error < 0)
 		return error;
 
-	miro->pcm = pcm;
+	miro->pcm = codec->pcm;
 
 	error = snd_miro_mixer(card, miro);
 	if (error < 0)
@@ -1356,8 +1354,8 @@
 
 	strcpy(card->driver, "miro");
 	sprintf(card->longname, "%s: OPTi%s, %s at 0x%lx, irq %d, dma %d&%d",
-		card->shortname, miro->name, pcm->name, miro->wss_base + 4,
-		miro->irq, miro->dma1, miro->dma2);
+		card->shortname, miro->name, codec->pcm->name,
+		miro->wss_base + 4, miro->irq, miro->dma1, miro->dma2);
 
 	if (mpu_port <= 0 || mpu_port == SNDRV_AUTO_PORT)
 		rmidi = NULL;
diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c
index c9b5828..0a52660 100644
--- a/sound/isa/opti9xx/opti92x-ad1848.c
+++ b/sound/isa/opti9xx/opti92x-ad1848.c
@@ -29,7 +29,7 @@
 #include <linux/delay.h>
 #include <linux/pnp.h>
 #include <linux/module.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <asm/dma.h>
 #include <sound/core.h>
 #include <sound/tlv.h>
@@ -820,10 +820,6 @@
 	int xdma2;
 	struct snd_opti9xx *chip = card->private_data;
 	struct snd_wss *codec;
-#ifdef CS4231
-	struct snd_timer *timer;
-#endif
-	struct snd_pcm *pcm;
 	struct snd_rawmidi *rmidi;
 	struct snd_hwdep *synth;
 
@@ -855,7 +851,7 @@
 	if (error < 0)
 		return error;
 	chip->codec = codec;
-	error = snd_wss_pcm(codec, 0, &pcm);
+	error = snd_wss_pcm(codec, 0);
 	if (error < 0)
 		return error;
 	error = snd_wss_mixer(codec);
@@ -867,7 +863,7 @@
 		return error;
 #endif
 #ifdef CS4231
-	error = snd_wss_timer(codec, 0, &timer);
+	error = snd_wss_timer(codec, 0);
 	if (error < 0)
 		return error;
 #endif
@@ -884,11 +880,12 @@
 	sprintf(card->shortname, "OPTi %s", card->driver);
 #if defined(CS4231) || defined(OPTi93X)
 	sprintf(card->longname, "%s, %s at 0x%lx, irq %d, dma %d&%d",
-		card->shortname, pcm->name,
+		card->shortname, codec->pcm->name,
 		chip->wss_base + 4, irq, dma1, xdma2);
 #else
 	sprintf(card->longname, "%s, %s at 0x%lx, irq %d, dma %d",
-		card->shortname, pcm->name, chip->wss_base + 4, irq, dma1);
+		card->shortname, codec->pcm->name, chip->wss_base + 4, irq,
+		dma1);
 #endif	/* CS4231 || OPTi93X */
 
 	if (mpu_port <= 0 || mpu_port == SNDRV_AUTO_PORT)
diff --git a/sound/isa/sb/emu8000.c b/sound/isa/sb/emu8000.c
index 45fcdff..94c4112 100644
--- a/sound/isa/sb/emu8000.c
+++ b/sound/isa/sb/emu8000.c
@@ -26,11 +26,11 @@
 #include <linux/ioport.h>
 #include <linux/export.h>
 #include <linux/delay.h>
+#include <linux/io.h>
 #include <sound/core.h>
 #include <sound/emu8000.h>
 #include <sound/emu8000_reg.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/init.h>
 #include <sound/control.h>
 #include <sound/initval.h>
@@ -378,13 +378,12 @@
 static void
 size_dram(struct snd_emu8000 *emu)
 {
-	int i, size, detected_size;
+	int i, size;
 
 	if (emu->dram_checked)
 		return;
 
 	size = 0;
-	detected_size = 0;
 
 	/* write out a magic number */
 	snd_emu8000_dma_chan(emu, 0, EMU8000_RAM_WRITE);
@@ -392,10 +391,19 @@
 	EMU8000_SMALW_WRITE(emu, EMU8000_DRAM_OFFSET);
 	EMU8000_SMLD_WRITE(emu, UNIQUE_ID1);
 	snd_emu8000_init_fm(emu); /* This must really be here and not 2 lines back even */
+	snd_emu8000_write_wait(emu);
 
-	while (size < EMU8000_MAX_DRAM) {
+	/*
+	 * Detect first 512 KiB.  If a write succeeds at the beginning of a
+	 * 512 KiB page we assume that the whole page is there.
+	 */
+	EMU8000_SMALR_WRITE(emu, EMU8000_DRAM_OFFSET);
+	EMU8000_SMLD_READ(emu); /* discard stale data  */
+	if (EMU8000_SMLD_READ(emu) != UNIQUE_ID1)
+		goto skip_detect;   /* No RAM */
+	snd_emu8000_read_wait(emu);
 
-		size += 512 * 1024;  /* increment 512kbytes */
+	for (size = 512 * 1024; size < EMU8000_MAX_DRAM; size += 512 * 1024) {
 
 		/* Write a unique data on the test address.
 		 * if the address is out of range, the data is written on
@@ -431,18 +439,9 @@
 		snd_emu8000_read_wait(emu);
 
 		/* Otherwise, it's valid memory. */
-		detected_size = size + 512 * 1024;
 	}
 
-	/* Distinguish 512 KiB from 0. */
-	if (detected_size == 0) {
-		snd_emu8000_read_wait(emu);
-		EMU8000_SMALR_WRITE(emu, EMU8000_DRAM_OFFSET);
-		EMU8000_SMLD_READ(emu); /* discard stale data  */
-		if (EMU8000_SMLD_READ(emu) == UNIQUE_ID1)
-			detected_size = 512 * 1024;
-	}
-
+skip_detect:
 	/* wait until FULL bit in SMAxW register is false */
 	for (i = 0; i < 10000; i++) {
 		if ((EMU8000_SMALW_READ(emu) & 0x80000000) == 0)
@@ -454,10 +453,10 @@
 	snd_emu8000_dma_chan(emu, 0, EMU8000_RAM_CLOSE);
 	snd_emu8000_dma_chan(emu, 1, EMU8000_RAM_CLOSE);
 
-	snd_printdd("EMU8000 [0x%lx]: %d Kb on-board memory detected\n",
-		    emu->port1, detected_size/1024);
+	pr_info("EMU8000 [0x%lx]: %d KiB on-board DRAM detected\n",
+		    emu->port1, size/1024);
 
-	emu->mem_size = detected_size;
+	emu->mem_size = size;
 	emu->dram_checked = 1;
 }
 
diff --git a/sound/isa/sb/emu8000_patch.c b/sound/isa/sb/emu8000_patch.c
index c99c607..71d13c0 100644
--- a/sound/isa/sb/emu8000_patch.c
+++ b/sound/isa/sb/emu8000_patch.c
@@ -20,7 +20,7 @@
  */
 
 #include "emu8000_local.h"
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/moduleparam.h>
 
 static int emu8000_reset_addr;
diff --git a/sound/isa/sb/emu8000_pcm.c b/sound/isa/sb/emu8000_pcm.c
index 2f85c66..250fd00 100644
--- a/sound/isa/sb/emu8000_pcm.c
+++ b/sound/isa/sb/emu8000_pcm.c
@@ -207,8 +207,7 @@
 	rec->last_ptr = ptr;
 
 	/* reprogram timer */
-	rec->timer.expires = jiffies + 1;
-	add_timer(&rec->timer);
+	mod_timer(&rec->timer, jiffies + 1);
 
 	/* update period */
 	if (rec->period_pos >= (int)rec->period_size) {
@@ -240,9 +239,7 @@
 	runtime->private_data = rec;
 
 	spin_lock_init(&rec->timer_lock);
-	init_timer(&rec->timer);
-	rec->timer.function = emu8k_pcm_timer_func;
-	rec->timer.data = (unsigned long)rec;
+	setup_timer(&rec->timer, emu8k_pcm_timer_func, (unsigned long)rec);
 
 	runtime->hw = emu8k_pcm_hw;
 	runtime->hw.buffer_bytes_max = emu->mem_size - LOOP_BLANK_SIZE * 3;
@@ -359,8 +356,7 @@
 	/* start timer */
 	spin_lock_irqsave(&rec->timer_lock, flags);
 	if (! rec->timer_running) {
-		rec->timer.expires = jiffies + 1;
-		add_timer(&rec->timer);
+		mod_timer(&rec->timer, jiffies + 1);
 		rec->timer_running = 1;
 	}
 	spin_unlock_irqrestore(&rec->timer_lock, flags);
diff --git a/sound/isa/sb/emu8000_synth.c b/sound/isa/sb/emu8000_synth.c
index 95b39be..72332df 100644
--- a/sound/isa/sb/emu8000_synth.c
+++ b/sound/isa/sb/emu8000_synth.c
@@ -103,8 +103,7 @@
 	hw = dev->driver_data;
 	if (hw->pcm)
 		snd_device_free(dev->card, hw->pcm);
-	if (hw->emu)
-		snd_emux_free(hw->emu);
+	snd_emux_free(hw->emu);
 	snd_util_memhdr_free(hw->memhdr);
 	hw->emu = NULL;
 	hw->memhdr = NULL;
diff --git a/sound/isa/sb/jazz16.c b/sound/isa/sb/jazz16.c
index 90d2eba..6b4884d 100644
--- a/sound/isa/sb/jazz16.c
+++ b/sound/isa/sb/jazz16.c
@@ -297,7 +297,7 @@
 		"Media Vision Jazz16 at 0x%lx, irq %d, dma8 %d, dma16 %d",
 		port[dev], xirq, xdma8, xdma16);
 
-	err = snd_sb8dsp_pcm(chip, 0, NULL);
+	err = snd_sb8dsp_pcm(chip, 0);
 	if (err < 0)
 		goto err_free;
 	err = snd_sbmixer_new(chip);
diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c
index 3f69454..4a7d7c8 100644
--- a/sound/isa/sb/sb16.c
+++ b/sound/isa/sb/sb16.c
@@ -374,7 +374,7 @@
 	if (! is_isapnp_selected(dev) && (err = snd_sb16dsp_configure(chip)) < 0)
 		return err;
 
-	if ((err = snd_sb16dsp_pcm(chip, 0, &chip->pcm)) < 0)
+	if ((err = snd_sb16dsp_pcm(chip, 0)) < 0)
 		return err;
 
 	strcpy(card->driver,
diff --git a/sound/isa/sb/sb16_main.c b/sound/isa/sb/sb16_main.c
index 72b10f4..8b2d6c6 100644
--- a/sound/isa/sb/sb16_main.c
+++ b/sound/isa/sb/sb16_main.c
@@ -33,7 +33,7 @@
  *
  */
 
-#include <asm/io.h>
+#include <linux/io.h>
 #include <asm/dma.h>
 #include <linux/init.h>
 #include <linux/time.h>
@@ -860,19 +860,18 @@
 	.pointer =	snd_sb16_capture_pointer,
 };
 
-int snd_sb16dsp_pcm(struct snd_sb * chip, int device, struct snd_pcm ** rpcm)
+int snd_sb16dsp_pcm(struct snd_sb *chip, int device)
 {
 	struct snd_card *card = chip->card;
 	struct snd_pcm *pcm;
 	int err;
 
-	if (rpcm)
-		*rpcm = NULL;
 	if ((err = snd_pcm_new(card, "SB16 DSP", device, 1, 1, &pcm)) < 0)
 		return err;
 	sprintf(pcm->name, "DSP v%i.%i", chip->version >> 8, chip->version & 0xff);
 	pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
 	pcm->private_data = chip;
+	chip->pcm = pcm;
 
 	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_sb16_playback_ops);
 	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_sb16_capture_ops);
@@ -885,9 +884,6 @@
 	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
 					      snd_dma_isa_data(),
 					      64*1024, 128*1024);
-
-	if (rpcm)
-		*rpcm = pcm;
 	return 0;
 }
 
diff --git a/sound/isa/sb/sb8.c b/sound/isa/sb/sb8.c
index 6c32b3a..b8e2391 100644
--- a/sound/isa/sb/sb8.c
+++ b/sound/isa/sb/sb8.c
@@ -157,7 +157,7 @@
 		goto _err;
 	}
 
-	if ((err = snd_sb8dsp_pcm(chip, 0, NULL)) < 0)
+	if ((err = snd_sb8dsp_pcm(chip, 0)) < 0)
 		goto _err;
 
 	if ((err = snd_sbmixer_new(chip)) < 0)
@@ -182,7 +182,7 @@
 			goto _err;
 	}
 
-	if ((err = snd_sb8dsp_midi(chip, 0, NULL)) < 0)
+	if ((err = snd_sb8dsp_midi(chip, 0)) < 0)
 		goto _err;
 
 	strcpy(card->driver, chip->hardware == SB_HW_PRO ? "SB Pro" : "SB8");
diff --git a/sound/isa/sb/sb8_main.c b/sound/isa/sb/sb8_main.c
index 24d4121..9043397 100644
--- a/sound/isa/sb/sb8_main.c
+++ b/sound/isa/sb/sb8_main.c
@@ -30,7 +30,7 @@
  *   Cleaned up and rewrote lowlevel routines.
  */
 
-#include <asm/io.h>
+#include <linux/io.h>
 #include <asm/dma.h>
 #include <linux/init.h>
 #include <linux/time.h>
@@ -594,15 +594,13 @@
 	.pointer =		snd_sb8_capture_pointer,
 };
 
-int snd_sb8dsp_pcm(struct snd_sb *chip, int device, struct snd_pcm ** rpcm)
+int snd_sb8dsp_pcm(struct snd_sb *chip, int device)
 {
 	struct snd_card *card = chip->card;
 	struct snd_pcm *pcm;
 	int err;
 	size_t max_prealloc = 64 * 1024;
 
-	if (rpcm)
-		*rpcm = NULL;
 	if ((err = snd_pcm_new(card, "SB8 DSP", device, 1, 1, &pcm)) < 0)
 		return err;
 	sprintf(pcm->name, "DSP v%i.%i", chip->version >> 8, chip->version & 0xff);
@@ -618,8 +616,6 @@
 					      snd_dma_isa_data(),
 					      64*1024, max_prealloc);
 
-	if (rpcm)
-		*rpcm = pcm;
 	return 0;
 }
 
diff --git a/sound/isa/sb/sb8_midi.c b/sound/isa/sb/sb8_midi.c
index 988a8b7..d551c50 100644
--- a/sound/isa/sb/sb8_midi.c
+++ b/sound/isa/sb/sb8_midi.c
@@ -26,7 +26,7 @@
  *   Added full duplex UART mode for DSP version 2.0 and later.
  */
 
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/time.h>
 #include <sound/core.h>
 #include <sound/sb.h>
@@ -216,8 +216,7 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&chip->open_lock, flags);
-	chip->midi_timer.expires = 1 + jiffies;
-	add_timer(&chip->midi_timer);
+	mod_timer(&chip->midi_timer, 1 + jiffies);
 	spin_unlock_irqrestore(&chip->open_lock, flags);	
 	snd_sb8dsp_midi_output_write(substream);
 }
@@ -231,11 +230,10 @@
 	spin_lock_irqsave(&chip->open_lock, flags);
 	if (up) {
 		if (!(chip->open & SB_OPEN_MIDI_OUTPUT_TRIGGER)) {
-			init_timer(&chip->midi_timer);
-			chip->midi_timer.function = snd_sb8dsp_midi_output_timer;
-			chip->midi_timer.data = (unsigned long) substream;
-			chip->midi_timer.expires = 1 + jiffies;
-			add_timer(&chip->midi_timer);
+			setup_timer(&chip->midi_timer,
+				    snd_sb8dsp_midi_output_timer,
+				    (unsigned long) substream);
+			mod_timer(&chip->midi_timer, 1 + jiffies);
 			chip->open |= SB_OPEN_MIDI_OUTPUT_TRIGGER;
 		}
 	} else {
@@ -263,13 +261,11 @@
 	.trigger =	snd_sb8dsp_midi_input_trigger,
 };
 
-int snd_sb8dsp_midi(struct snd_sb *chip, int device, struct snd_rawmidi ** rrawmidi)
+int snd_sb8dsp_midi(struct snd_sb *chip, int device)
 {
 	struct snd_rawmidi *rmidi;
 	int err;
 
-	if (rrawmidi)
-		*rrawmidi = NULL;
 	if ((err = snd_rawmidi_new(chip->card, "SB8 MIDI", device, 1, 1, &rmidi)) < 0)
 		return err;
 	strcpy(rmidi->name, "SB8 MIDI");
@@ -280,7 +276,5 @@
 		rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX;
 	rmidi->private_data = chip;
 	chip->rmidi = rmidi;
-	if (rrawmidi)
-		*rrawmidi = rmidi;
 	return 0;
 }
diff --git a/sound/isa/sb/sb_common.c b/sound/isa/sb/sb_common.c
index f22b448..787a4ad 100644
--- a/sound/isa/sb/sb_common.c
+++ b/sound/isa/sb/sb_common.c
@@ -26,11 +26,11 @@
 #include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/module.h>
+#include <linux/io.h>
 #include <sound/core.h>
 #include <sound/sb.h>
 #include <sound/initval.h>
 
-#include <asm/io.h>
 #include <asm/dma.h>
 
 MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
diff --git a/sound/isa/sb/sb_mixer.c b/sound/isa/sb/sb_mixer.c
index e403334..add1d3f 100644
--- a/sound/isa/sb/sb_mixer.c
+++ b/sound/isa/sb/sb_mixer.c
@@ -19,7 +19,7 @@
  *
  */
 
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/time.h>
 #include <sound/core.h>
diff --git a/sound/isa/sc6000.c b/sound/isa/sc6000.c
index 15a152e..51cfa76 100644
--- a/sound/isa/sc6000.c
+++ b/sound/isa/sc6000.c
@@ -625,7 +625,7 @@
 	if (err < 0)
 		goto err_unmap2;
 
-	err = snd_wss_pcm(chip, 0, NULL);
+	err = snd_wss_pcm(chip, 0);
 	if (err < 0) {
 		snd_printk(KERN_ERR PFX
 			   "error creating new WSS PCM device\n");
diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c
index 44405df..7b248cd 100644
--- a/sound/isa/sscape.c
+++ b/sound/isa/sscape.c
@@ -23,6 +23,7 @@
 
 #include <linux/init.h>
 #include <linux/err.h>
+#include <linux/io.h>
 #include <linux/isa.h>
 #include <linux/delay.h>
 #include <linux/firmware.h>
@@ -877,7 +878,6 @@
 			     codec_type, WSS_HWSHARE_DMA1, &chip);
 	if (!err) {
 		unsigned long flags;
-		struct snd_pcm *pcm;
 
 		if (sscape->type != SSCAPE_VIVO) {
 			/*
@@ -893,7 +893,7 @@
 
 		}
 
-		err = snd_wss_pcm(chip, 0, &pcm);
+		err = snd_wss_pcm(chip, 0);
 		if (err < 0) {
 			snd_printk(KERN_ERR "sscape: No PCM device "
 					    "for AD1845 chip\n");
@@ -907,7 +907,7 @@
 			goto _error;
 		}
 		if (chip->hardware != WSS_HW_AD1848) {
-			err = snd_wss_timer(chip, 0, NULL);
+			err = snd_wss_timer(chip, 0);
 			if (err < 0) {
 				snd_printk(KERN_ERR "sscape: No timer device "
 						    "for AD1845 chip\n");
diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c
index bfbf38c..a0987a5 100644
--- a/sound/isa/wavefront/wavefront.c
+++ b/sound/isa/wavefront/wavefront.c
@@ -380,11 +380,11 @@
 		return err;
 	}
 
-	err = snd_wss_pcm(chip, 0, NULL);
+	err = snd_wss_pcm(chip, 0);
 	if (err < 0)
 		return err;
 
-	err = snd_wss_timer(chip, 0, NULL);
+	err = snd_wss_timer(chip, 0);
 	if (err < 0)
 		return err;
 
diff --git a/sound/isa/wavefront/wavefront_fx.c b/sound/isa/wavefront/wavefront_fx.c
index b77883c..b5a1970 100644
--- a/sound/isa/wavefront/wavefront_fx.c
+++ b/sound/isa/wavefront/wavefront_fx.c
@@ -16,7 +16,7 @@
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
 
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/init.h>
 #include <linux/time.h>
 #include <linux/wait.h>
diff --git a/sound/isa/wavefront/wavefront_midi.c b/sound/isa/wavefront/wavefront_midi.c
index 7dc9916..8a80fc6 100644
--- a/sound/isa/wavefront/wavefront_midi.c
+++ b/sound/isa/wavefront/wavefront_midi.c
@@ -47,7 +47,7 @@
  *  
  */
 
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/init.h>
 #include <linux/time.h>
 #include <linux/wait.h>
@@ -356,8 +356,7 @@
 	unsigned long flags;
 	
 	spin_lock_irqsave (&midi->virtual, flags);
-	midi->timer.expires = 1 + jiffies;
-	add_timer(&midi->timer);
+	mod_timer(&midi->timer, 1 + jiffies);
 	spin_unlock_irqrestore (&midi->virtual, flags);
 	snd_wavefront_midi_output_write(card);
 }
@@ -384,11 +383,10 @@
 	if (up) {
 		if ((midi->mode[mpu] & MPU401_MODE_OUTPUT_TRIGGER) == 0) {
 			if (!midi->istimer) {
-				init_timer(&midi->timer);
-				midi->timer.function = snd_wavefront_midi_output_timer;
-				midi->timer.data = (unsigned long) substream->rmidi->card->private_data;
-				midi->timer.expires = 1 + jiffies;
-				add_timer(&midi->timer);
+				setup_timer(&midi->timer,
+					    snd_wavefront_midi_output_timer,
+					    (unsigned long) substream->rmidi->card->private_data);
+				mod_timer(&midi->timer, 1 + jiffies);
 			}
 			midi->istimer++;
 			midi->mode[mpu] |= MPU401_MODE_OUTPUT_TRIGGER;
diff --git a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c
index e5db001..33f5ec1 100644
--- a/sound/isa/wavefront/wavefront_synth.c
+++ b/sound/isa/wavefront/wavefront_synth.c
@@ -20,7 +20,7 @@
  *
  */
 
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/delay.h>
diff --git a/sound/isa/wss/wss_lib.c b/sound/isa/wss/wss_lib.c
index 347bb1b..913b731 100644
--- a/sound/isa/wss/wss_lib.c
+++ b/sound/isa/wss/wss_lib.c
@@ -31,12 +31,12 @@
 #include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/module.h>
+#include <linux/io.h>
 #include <sound/core.h>
 #include <sound/wss.h>
 #include <sound/pcm_params.h>
 #include <sound/tlv.h>
 
-#include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/irq.h>
 
@@ -1923,7 +1923,7 @@
 	.pointer =	snd_wss_capture_pointer,
 };
 
-int snd_wss_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm)
+int snd_wss_pcm(struct snd_wss *chip, int device)
 {
 	struct snd_pcm *pcm;
 	int err;
@@ -1949,8 +1949,6 @@
 					      64*1024, chip->dma1 > 3 || chip->dma2 > 3 ? 128*1024 : 64*1024);
 
 	chip->pcm = pcm;
-	if (rpcm)
-		*rpcm = pcm;
 	return 0;
 }
 EXPORT_SYMBOL(snd_wss_pcm);
@@ -1961,7 +1959,7 @@
 	chip->timer = NULL;
 }
 
-int snd_wss_timer(struct snd_wss *chip, int device, struct snd_timer **rtimer)
+int snd_wss_timer(struct snd_wss *chip, int device)
 {
 	struct snd_timer *timer;
 	struct snd_timer_id tid;
@@ -1980,8 +1978,6 @@
 	timer->private_free = snd_wss_timer_free;
 	timer->hw = snd_wss_timer_table;
 	chip->timer = timer;
-	if (rtimer)
-		*rtimer = timer;
 	return 0;
 }
 EXPORT_SYMBOL(snd_wss_timer);
diff --git a/sound/oss/msnd_pinnacle.c b/sound/oss/msnd_pinnacle.c
index c23f9f9..a8ceef8 100644
--- a/sound/oss/msnd_pinnacle.c
+++ b/sound/oss/msnd_pinnacle.c
@@ -675,7 +675,7 @@
 		timeout);
 	clear_bit(F_WRITEFLUSH, &dev.flags);
 	if (!signal_pending(current)) {
-		current->state = TASK_INTERRUPTIBLE;
+		__set_current_state(TASK_INTERRUPTIBLE);
 		schedule_timeout(get_play_delay_jiffies(DAP_BUFF_SIZE));
 	}
 	clear_bit(F_WRITING, &dev.flags);
@@ -1288,7 +1288,7 @@
 		       & ~0x0001, dev.SMA + SMA_wCurrHostStatusFlags);
 	if (msnd_send_word(&dev, 0, 0, HDEXAR_CAL_A_TO_D) == 0 &&
 	    chk_send_dsp_cmd(&dev, HDEX_AUX_REQ) == 0) {
-		current->state = TASK_INTERRUPTIBLE;
+		__set_current_state(TASK_INTERRUPTIBLE);
 		schedule_timeout(HZ / 3);
 		return 0;
 	}
diff --git a/sound/oss/pss.c b/sound/oss/pss.c
index ca0d6e9..81314f9 100644
--- a/sound/oss/pss.c
+++ b/sound/oss/pss.c
@@ -1228,7 +1228,7 @@
 {
 	if(!pss_no_sound)
 	{
-		if(fw_load && pss_synth)
+		if (fw_load)
 			vfree(pss_synth);
 		if(pssmss)
 			unload_pss_mss(&cfg2);
diff --git a/sound/oss/swarm_cs4297a.c b/sound/oss/swarm_cs4297a.c
index a33e8ce..213a416 100644
--- a/sound/oss/swarm_cs4297a.c
+++ b/sound/oss/swarm_cs4297a.c
@@ -1654,7 +1654,7 @@
         s->dma_dac.hwptr = s->dma_dac.swptr = hwptr;
         spin_unlock_irqrestore(&s->lock, flags);
 	remove_wait_queue(&s->dma_dac.wait, &wait);
-	current->state = TASK_RUNNING;
+	__set_current_state(TASK_RUNNING);
 	return 0;
 }
 
diff --git a/sound/oss/trix.c b/sound/oss/trix.c
index 944e0c0..3c494dc 100644
--- a/sound/oss/trix.c
+++ b/sound/oss/trix.c
@@ -487,7 +487,7 @@
 
 static void __exit cleanup_trix(void)
 {
-	if (fw_load && trix_boot)
+	if (fw_load)
 		vfree(trix_boot);
 	if (sb)
 		unload_trix_sb(&cfg2);
diff --git a/sound/parisc/harmony.c b/sound/parisc/harmony.c
index 29604a2..99b64cb 100644
--- a/sound/parisc/harmony.c
+++ b/sound/parisc/harmony.c
@@ -44,6 +44,7 @@
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
 #include <linux/dma-mapping.h>
+#include <linux/io.h>
 
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -52,7 +53,6 @@
 #include <sound/initval.h>
 #include <sound/info.h>
 
-#include <asm/io.h>
 #include <asm/hardware.h>
 #include <asm/parisc-device.h>
 
@@ -893,9 +893,7 @@
 	if (h->irq >= 0)
 		free_irq(h->irq, h);
 
-	if (h->iobase)
-		iounmap(h->iobase);
-
+	iounmap(h->iobase);
 	kfree(h);
 	return 0;
 }
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index 50dd008..edfc1b8 100644
--- a/sound/pci/Kconfig
+++ b/sound/pci/Kconfig
@@ -793,6 +793,15 @@
 	  To compile this driver as a module, choose M here: the module
 	  will be called snd-rme9652.
 
+config SND_SE6X
+	tristate "Studio Evolution SE6X"
+	depends on SND_OXYGEN=n && SND_VIRTUOSO=n  # PCI ID conflict
+	select SND_OXYGEN_LIB
+	select SND_PCM
+	select SND_MPU401_UART
+	help
+	  Say Y or M here only if you actually have this sound card.
+
 config SND_SIS7019
 	tristate "SiS 7019 Audio Accelerator"
 	depends on X86_32
diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c
index 1610c38..850a8c9 100644
--- a/sound/pci/ad1889.c
+++ b/sound/pci/ad1889.c
@@ -40,14 +40,13 @@
 #include <linux/compiler.h>
 #include <linux/delay.h>
 #include <linux/module.h>
+#include <linux/io.h>
 
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/initval.h>
 #include <sound/ac97_codec.h>
 
-#include <asm/io.h>
-
 #include "ad1889.h"
 #include "ac97/ac97_id.h"
 
@@ -623,14 +622,11 @@
 }
 
 static int
-snd_ad1889_pcm_init(struct snd_ad1889 *chip, int device, struct snd_pcm **rpcm)
+snd_ad1889_pcm_init(struct snd_ad1889 *chip, int device)
 {
 	int err;
 	struct snd_pcm *pcm;
 
-	if (rpcm)
-		*rpcm = NULL;
-
 	err = snd_pcm_new(chip->card, chip->card->driver, device, 1, 1, &pcm);
 	if (err < 0)
 		return err;
@@ -658,9 +654,6 @@
 		return err;
 	}
 	
-	if (rpcm)
-		*rpcm = pcm;
-	
 	return 0;
 }
 
@@ -859,12 +852,9 @@
 		free_irq(chip->irq, chip);
 
 skip_hw:
-	if (chip->iobase)
-		iounmap(chip->iobase);
-
+	iounmap(chip->iobase);
 	pci_release_regions(chip->pci);
 	pci_disable_device(chip->pci);
-
 	kfree(chip);
 	return 0;
 }
@@ -1016,7 +1006,7 @@
 	if (err < 0)
 		goto free_and_ret;
 	
-	err = snd_ad1889_pcm_init(chip, 0, NULL);
+	err = snd_ad1889_pcm_init(chip, 0);
 	if (err < 0)
 		goto free_and_ret;
 
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c
index af89e42..c8d4995 100644
--- a/sound/pci/ali5451/ali5451.c
+++ b/sound/pci/ali5451/ali5451.c
@@ -25,7 +25,7 @@
  *
  */
 
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
@@ -1873,7 +1873,6 @@
 #ifdef CONFIG_PM_SLEEP
 static int ali_suspend(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct snd_ali *chip = card->private_data;
 	struct snd_ali_image *im;
@@ -1914,16 +1913,11 @@
 	outl(0xffffffff, ALI_REG(chip, ALI_STOP));
 
 	spin_unlock_irq(&chip->reg_lock);
-
-	pci_disable_device(pci);
-	pci_save_state(pci);
-	pci_set_power_state(pci, PCI_D3hot);
 	return 0;
 }
 
 static int ali_resume(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct snd_ali *chip = card->private_data;
 	struct snd_ali_image *im;
@@ -1933,15 +1927,6 @@
 	if (!im)
 		return 0;
 
-	pci_set_power_state(pci, PCI_D0);
-	pci_restore_state(pci);
-	if (pci_enable_device(pci) < 0) {
-		dev_err(dev, "pci_enable_device failed, disabling device\n");
-		snd_card_disconnect(card);
-		return -EIO;
-	}
-	pci_set_master(pci);
-
 	spin_lock_irq(&chip->reg_lock);
 	
 	for (i = 0; i < ALI_CHANNELS; i++) {
diff --git a/sound/pci/als300.c b/sound/pci/als300.c
index 7bb6ac5..57e034f 100644
--- a/sound/pci/als300.c
+++ b/sound/pci/als300.c
@@ -37,8 +37,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/interrupt.h>
 #include <linux/slab.h>
-
-#include <asm/io.h>
+#include <linux/io.h>
 
 #include <sound/core.h>
 #include <sound/control.h>
@@ -728,35 +727,20 @@
 #ifdef CONFIG_PM_SLEEP
 static int snd_als300_suspend(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct snd_als300 *chip = card->private_data;
 
 	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
 	snd_pcm_suspend_all(chip->pcm);
 	snd_ac97_suspend(chip->ac97);
-
-	pci_disable_device(pci);
-	pci_save_state(pci);
-	pci_set_power_state(pci, PCI_D3hot);
 	return 0;
 }
 
 static int snd_als300_resume(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct snd_als300 *chip = card->private_data;
 
-	pci_set_power_state(pci, PCI_D0);
-	pci_restore_state(pci);
-	if (pci_enable_device(pci) < 0) {
-		dev_err(dev, "pci_enable_device failed, disabling device\n");
-		snd_card_disconnect(card);
-		return -EIO;
-	}
-	pci_set_master(pci);
-
 	snd_als300_init(chip);
 	snd_ac97_resume(chip->ac97);
 
diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c
index d3e6424..a3dea46 100644
--- a/sound/pci/als4000.c
+++ b/sound/pci/als4000.c
@@ -65,7 +65,7 @@
  * - power management? (card can do voice wakeup according to datasheet!!)
  */
 
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/gameport.h>
@@ -988,7 +988,6 @@
 #ifdef CONFIG_PM_SLEEP
 static int snd_als4000_suspend(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct snd_card_als4000 *acard = card->private_data;
 	struct snd_sb *chip = acard->chip;
@@ -997,29 +996,15 @@
 	
 	snd_pcm_suspend_all(chip->pcm);
 	snd_sbmixer_suspend(chip);
-
-	pci_disable_device(pci);
-	pci_save_state(pci);
-	pci_set_power_state(pci, PCI_D3hot);
 	return 0;
 }
 
 static int snd_als4000_resume(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct snd_card_als4000 *acard = card->private_data;
 	struct snd_sb *chip = acard->chip;
 
-	pci_set_power_state(pci, PCI_D0);
-	pci_restore_state(pci);
-	if (pci_enable_device(pci) < 0) {
-		dev_err(dev, "pci_enable_device failed, disabling device\n");
-		snd_card_disconnect(card);
-		return -EIO;
-	}
-	pci_set_master(pci);
-
 	snd_als4000_configure(chip);
 	snd_sbdsp_reset(chip);
 	snd_sbmixer_resume(chip);
diff --git a/sound/pci/asihpi/asihpi.c b/sound/pci/asihpi/asihpi.c
index e9273fb..e5cd7be 100644
--- a/sound/pci/asihpi/asihpi.c
+++ b/sound/pci/asihpi/asihpi.c
@@ -540,9 +540,8 @@
 	expiry = HZ / 200;
 
 	expiry = max(expiry, 1); /* don't let it be zero! */
-	dpcm->timer.expires = jiffies + expiry;
+	mod_timer(&dpcm->timer, jiffies + expiry);
 	dpcm->respawn_timer = 1;
-	add_timer(&dpcm->timer);
 }
 
 static void snd_card_asihpi_pcm_timer_stop(struct snd_pcm_substream *substream)
@@ -1064,9 +1063,8 @@
 	    If internal and other stream playing, can't switch
 	*/
 
-	init_timer(&dpcm->timer);
-	dpcm->timer.data = (unsigned long) dpcm;
-	dpcm->timer.function = snd_card_asihpi_timer_function;
+	setup_timer(&dpcm->timer, snd_card_asihpi_timer_function,
+		    (unsigned long) dpcm);
 	dpcm->substream = substream;
 	runtime->private_data = dpcm;
 	runtime->private_free = snd_card_asihpi_runtime_free;
@@ -1246,9 +1244,8 @@
 	if (err)
 		return -EIO;
 
-	init_timer(&dpcm->timer);
-	dpcm->timer.data = (unsigned long) dpcm;
-	dpcm->timer.function = snd_card_asihpi_timer_function;
+	setup_timer(&dpcm->timer, snd_card_asihpi_timer_function,
+		    (unsigned long) dpcm);
 	dpcm->substream = substream;
 	runtime->private_data = dpcm;
 	runtime->private_free = snd_card_asihpi_runtime_free;
@@ -2832,14 +2829,11 @@
 /* results in /dev/snd/hwC#D0 file for each card with index #
    also /proc/asound/hwdep will contain '#-00: asihpi (HPI) for each card'
 */
-static int snd_asihpi_hpi_new(struct snd_card_asihpi *asihpi,
-			      int device, struct snd_hwdep **rhwdep)
+static int snd_asihpi_hpi_new(struct snd_card_asihpi *asihpi, int device)
 {
 	struct snd_hwdep *hw;
 	int err;
 
-	if (rhwdep)
-		*rhwdep = NULL;
 	err = snd_hwdep_new(asihpi->card, "HPI", device, &hw);
 	if (err < 0)
 		return err;
@@ -2849,8 +2843,6 @@
 	hw->ops.ioctl = snd_asihpi_hpi_ioctl;
 	hw->ops.release = snd_asihpi_hpi_release;
 	hw->private_data = asihpi;
-	if (rhwdep)
-		*rhwdep = hw;
 	return 0;
 }
 
@@ -2993,7 +2985,7 @@
 
 	/* always create, can be enabled or disabled dynamically
 	    by enable_hwdep  module param*/
-	snd_asihpi_hpi_new(asihpi, 0, NULL);
+	snd_asihpi_hpi_new(asihpi, 0);
 
 	strcpy(card->driver, "ASIHPI");
 
diff --git a/sound/pci/asihpi/hpi6000.c b/sound/pci/asihpi/hpi6000.c
index 2414d7a..2d63648 100644
--- a/sound/pci/asihpi/hpi6000.c
+++ b/sound/pci/asihpi/hpi6000.c
@@ -47,7 +47,7 @@
 
 /* operational/messaging errors */
 #define HPI6000_ERROR_MSG_RESP_IDLE_TIMEOUT             901
-
+#define HPI6000_ERROR_RESP_GET_LEN                      902
 #define HPI6000_ERROR_MSG_RESP_GET_RESP_ACK             903
 #define HPI6000_ERROR_MSG_GET_ADR                       904
 #define HPI6000_ERROR_RESP_GET_ADR                      905
@@ -1365,7 +1365,10 @@
 		length = hpi_read_word(pdo, HPI_HIF_ADDR(length));
 	} while (hpi6000_check_PCI2040_error_flag(pao, H6READ) && --timeout);
 	if (!timeout)
-		length = sizeof(struct hpi_response);
+		return HPI6000_ERROR_RESP_GET_LEN;
+
+	if (length > phr->size)
+		return HPI_ERROR_RESPONSE_BUFFER_TOO_SMALL;
 
 	/* get the response */
 	p_data = (u32 *)phr;
diff --git a/sound/pci/asihpi/hpioctl.c b/sound/pci/asihpi/hpioctl.c
index 6aa677e..6610bd0 100644
--- a/sound/pci/asihpi/hpioctl.c
+++ b/sound/pci/asihpi/hpioctl.c
@@ -28,7 +28,7 @@
 #include <linux/interrupt.h>
 #include <linux/slab.h>
 #include <linux/moduleparam.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/pci.h>
 #include <linux/stringify.h>
 #include <linux/module.h>
@@ -153,6 +153,8 @@
 		goto out;
 	}
 
+	res_max_size = min_t(size_t, res_max_size, sizeof(*hr));
+
 	switch (hm->h.function) {
 	case HPI_SUBSYS_CREATE_ADAPTER:
 	case HPI_ADAPTER_DELETE:
@@ -539,10 +541,8 @@
 	hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL);
 
 	/* unmap PCI memory space, mapped during device init. */
-	for (idx = 0; idx < HPI_MAX_ADAPTER_MEM_SPACES; idx++) {
-		if (pci.ap_mem_base[idx])
-			iounmap(pci.ap_mem_base[idx]);
-	}
+	for (idx = 0; idx < HPI_MAX_ADAPTER_MEM_SPACES; ++idx)
+		iounmap(pci.ap_mem_base[idx]);
 
 	if (pa->irq)
 		free_irq(pa->irq, pa);
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c
index 9c1c445..d5f15c9 100644
--- a/sound/pci/atiixp.c
+++ b/sound/pci/atiixp.c
@@ -19,7 +19,7 @@
  *
  */
 
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
@@ -1474,7 +1474,6 @@
  */
 static int snd_atiixp_suspend(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct atiixp *chip = card->private_data;
 	int i;
@@ -1492,29 +1491,15 @@
 		snd_ac97_suspend(chip->ac97[i]);
 	snd_atiixp_aclink_down(chip);
 	snd_atiixp_chip_stop(chip);
-
-	pci_disable_device(pci);
-	pci_save_state(pci);
-	pci_set_power_state(pci, PCI_D3hot);
 	return 0;
 }
 
 static int snd_atiixp_resume(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct atiixp *chip = card->private_data;
 	int i;
 
-	pci_set_power_state(pci, PCI_D0);
-	pci_restore_state(pci);
-	if (pci_enable_device(pci) < 0) {
-		dev_err(dev, "pci_enable_device failed, disabling device\n");
-		snd_card_disconnect(card);
-		return -EIO;
-	}
-	pci_set_master(pci);
-
 	snd_atiixp_aclink_reset(chip);
 	snd_atiixp_chip_start(chip);
 
@@ -1585,8 +1570,7 @@
       __hw_end:
 	if (chip->irq >= 0)
 		free_irq(chip->irq, chip);
-	if (chip->remap_addr)
-		iounmap(chip->remap_addr);
+	iounmap(chip->remap_addr);
 	pci_release_regions(chip->pci);
 	pci_disable_device(chip->pci);
 	kfree(chip);
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c
index b2f63e0..0a38e08 100644
--- a/sound/pci/atiixp_modem.c
+++ b/sound/pci/atiixp_modem.c
@@ -19,7 +19,7 @@
  *
  */
 
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
@@ -1120,7 +1120,6 @@
  */
 static int snd_atiixp_suspend(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct atiixp_modem *chip = card->private_data;
 	int i;
@@ -1132,29 +1131,15 @@
 		snd_ac97_suspend(chip->ac97[i]);
 	snd_atiixp_aclink_down(chip);
 	snd_atiixp_chip_stop(chip);
-
-	pci_disable_device(pci);
-	pci_save_state(pci);
-	pci_set_power_state(pci, PCI_D3hot);
 	return 0;
 }
 
 static int snd_atiixp_resume(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct atiixp_modem *chip = card->private_data;
 	int i;
 
-	pci_set_power_state(pci, PCI_D0);
-	pci_restore_state(pci);
-	if (pci_enable_device(pci) < 0) {
-		dev_err(dev, "pci_enable_device failed, disabling device\n");
-		snd_card_disconnect(card);
-		return -EIO;
-	}
-	pci_set_master(pci);
-
 	snd_atiixp_aclink_reset(chip);
 	snd_atiixp_chip_start(chip);
 
@@ -1211,8 +1196,7 @@
       __hw_end:
 	if (chip->irq >= 0)
 		free_irq(chip->irq, chip);
-	if (chip->remap_addr)
-		iounmap(chip->remap_addr);
+	iounmap(chip->remap_addr);
 	pci_release_regions(chip->pci);
 	pci_disable_device(chip->pci);
 	kfree(chip);
diff --git a/sound/pci/au88x0/au88x0.h b/sound/pci/au88x0/au88x0.h
index 3a8fefe..bcc648b 100644
--- a/sound/pci/au88x0/au88x0.h
+++ b/sound/pci/au88x0/au88x0.h
@@ -17,9 +17,8 @@
 #ifndef __SOUND_AU88X0_H
 #define __SOUND_AU88X0_H
 
-#ifdef __KERNEL__
 #include <linux/pci.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/rawmidi.h>
@@ -27,7 +26,6 @@
 #include <sound/hwdep.h>
 #include <sound/ac97_codec.h>
 #include <sound/tlv.h>
-#endif
 
 #ifndef CHIP_AU8820
 #include "au88x0_eq.h"
diff --git a/sound/pci/aw2/aw2-alsa.c b/sound/pci/aw2/aw2-alsa.c
index e1cf019..8d2fee7 100644
--- a/sound/pci/aw2/aw2-alsa.c
+++ b/sound/pci/aw2/aw2-alsa.c
@@ -229,9 +229,7 @@
 	if (chip->irq >= 0)
 		free_irq(chip->irq, (void *)chip);
 	/* release the i/o ports & memory */
-	if (chip->iobase_virt)
-		iounmap(chip->iobase_virt);
-
+	iounmap(chip->iobase_virt);
 	pci_release_regions(chip->pci);
 	/* disable the PCI entry */
 	pci_disable_device(chip->pci);
diff --git a/sound/pci/aw2/aw2-saa7146.c b/sound/pci/aw2/aw2-saa7146.c
index 6d24e95..1d78904 100644
--- a/sound/pci/aw2/aw2-saa7146.c
+++ b/sound/pci/aw2/aw2-saa7146.c
@@ -27,7 +27,7 @@
 #include <linux/pci.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <sound/core.h>
 #include <sound/initval.h>
 #include <sound/pcm.h>
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c
index fdbb9c0..a40a2b4 100644
--- a/sound/pci/azt3328.c
+++ b/sound/pci/azt3328.c
@@ -179,7 +179,7 @@
  *  - use MMIO (memory-mapped I/O)? Slightly faster access, e.g. for gameport.
  */
 
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/init.h>
 #include <linux/bug.h> /* WARN_ONCE */
 #include <linux/pci.h>
@@ -2694,7 +2694,6 @@
 static int
 snd_azf3328_suspend(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct snd_azf3328 *chip = card->private_data;
 	u16 *saved_regs_ctrl_u16;
@@ -2720,29 +2719,15 @@
 		ARRAY_SIZE(chip->saved_regs_mpu), chip->saved_regs_mpu);
 	snd_azf3328_suspend_regs(chip, chip->opl3_io,
 		ARRAY_SIZE(chip->saved_regs_opl3), chip->saved_regs_opl3);
-
-	pci_disable_device(pci);
-	pci_save_state(pci);
-	pci_set_power_state(pci, PCI_D3hot);
 	return 0;
 }
 
 static int
 snd_azf3328_resume(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	const struct snd_azf3328 *chip = card->private_data;
 
-	pci_set_power_state(pci, PCI_D0);
-	pci_restore_state(pci);
-	if (pci_enable_device(pci) < 0) {
-		dev_err(dev, "pci_enable_device failed, disabling device\n");
-		snd_card_disconnect(card);
-		return -EIO;
-	}
-	pci_set_master(pci);
-
 	snd_azf3328_resume_regs(chip, chip->saved_regs_game, chip->game_io,
 					ARRAY_SIZE(chip->saved_regs_game));
 	snd_azf3328_resume_regs(chip, chip->saved_regs_mpu, chip->mpu_io,
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c
index 058b997..5925b71 100644
--- a/sound/pci/bt87x.c
+++ b/sound/pci/bt87x.c
@@ -27,7 +27,7 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/bitops.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -690,8 +690,7 @@
 		snd_bt87x_stop(chip);
 	if (chip->irq >= 0)
 		free_irq(chip->irq, chip);
-	if (chip->mmio)
-		iounmap(chip->mmio);
+	iounmap(chip->mmio);
 	pci_release_regions(chip->pci);
 	pci_disable_device(chip->pci);
 	kfree(chip);
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
index 96af339..dd75b75 100644
--- a/sound/pci/ca0106/ca0106_main.c
+++ b/sound/pci/ca0106/ca0106_main.c
@@ -1910,7 +1910,6 @@
 #ifdef CONFIG_PM_SLEEP
 static int snd_ca0106_suspend(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct snd_ca0106 *chip = card->private_data;
 	int i;
@@ -1923,30 +1922,15 @@
 	snd_ca0106_mixer_suspend(chip);
 
 	ca0106_stop_chip(chip);
-
-	pci_disable_device(pci);
-	pci_save_state(pci);
-	pci_set_power_state(pci, PCI_D3hot);
 	return 0;
 }
 
 static int snd_ca0106_resume(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct snd_ca0106 *chip = card->private_data;
 	int i;
 
-	pci_set_power_state(pci, PCI_D0);
-	pci_restore_state(pci);
-
-	if (pci_enable_device(pci) < 0) {
-		snd_card_disconnect(card);
-		return -EIO;
-	}
-
-	pci_set_master(pci);
-
 	ca0106_init_chip(chip, 1);
 
 	if (chip->details->ac97)
diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c
index 68c0eb0..025805c 100644
--- a/sound/pci/ca0106/ca0106_mixer.c
+++ b/sound/pci/ca0106/ca0106_mixer.c
@@ -70,7 +70,7 @@
 #include <sound/ac97_codec.h>
 #include <sound/info.h>
 #include <sound/tlv.h>
-#include <asm/io.h>
+#include <linux/io.h>
 
 #include "ca0106.h"
 
diff --git a/sound/pci/ca0106/ca0106_proc.c b/sound/pci/ca0106/ca0106_proc.c
index 4f9c282..2c5c28a 100644
--- a/sound/pci/ca0106/ca0106_proc.c
+++ b/sound/pci/ca0106/ca0106_proc.c
@@ -64,13 +64,13 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/moduleparam.h>
+#include <linux/io.h>
 #include <sound/core.h>
 #include <sound/initval.h>
 #include <sound/pcm.h>
 #include <sound/ac97_codec.h>
 #include <sound/info.h>
 #include <sound/asoundef.h>
-#include <asm/io.h>
 
 #include "ca0106.h"
 
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c
index 85ed403..1d0f2ca 100644
--- a/sound/pci/cmipci.c
+++ b/sound/pci/cmipci.c
@@ -20,7 +20,7 @@
 /* Does not work. Warning may block system in capture mode */
 /* #define USE_VAR48KRATE */
 
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
@@ -3347,7 +3347,6 @@
 
 static int snd_cmipci_suspend(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct cmipci *cm = card->private_data;
 	int i;
@@ -3366,29 +3365,15 @@
 
 	/* disable ints */
 	snd_cmipci_write(cm, CM_REG_INT_HLDCLR, 0);
-
-	pci_disable_device(pci);
-	pci_save_state(pci);
-	pci_set_power_state(pci, PCI_D3hot);
 	return 0;
 }
 
 static int snd_cmipci_resume(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct cmipci *cm = card->private_data;
 	int i;
 
-	pci_set_power_state(pci, PCI_D0);
-	pci_restore_state(pci);
-	if (pci_enable_device(pci) < 0) {
-		dev_err(dev, "pci_enable_device failed, disabling device\n");
-		snd_card_disconnect(card);
-		return -EIO;
-	}
-	pci_set_master(pci);
-
 	/* reset / initialize to a sane state */
 	snd_cmipci_write(cm, CM_REG_INT_HLDCLR, 0);
 	snd_cmipci_ch_reset(cm, CM_CH_PLAY);
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c
index 4c49b5c..c296fd0 100644
--- a/sound/pci/cs4281.c
+++ b/sound/pci/cs4281.c
@@ -19,7 +19,7 @@
  *
  */
 
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
@@ -973,14 +973,11 @@
 	.pointer =	snd_cs4281_pointer,
 };
 
-static int snd_cs4281_pcm(struct cs4281 *chip, int device,
-			  struct snd_pcm **rpcm)
+static int snd_cs4281_pcm(struct cs4281 *chip, int device)
 {
 	struct snd_pcm *pcm;
 	int err;
 
-	if (rpcm)
-		*rpcm = NULL;
 	err = snd_pcm_new(chip->card, "CS4281", device, 1, 1, &pcm);
 	if (err < 0)
 		return err;
@@ -996,8 +993,6 @@
 	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
 					      snd_dma_pci_data(chip->pci), 64*1024, 512*1024);
 
-	if (rpcm)
-		*rpcm = pcm;
 	return 0;
 }
 
@@ -1321,10 +1316,8 @@
 
 	if (chip->irq >= 0)
 		free_irq(chip->irq, chip);
-	if (chip->ba0)
-		iounmap(chip->ba0);
-	if (chip->ba1)
-		iounmap(chip->ba1);
+	iounmap(chip->ba0);
+	iounmap(chip->ba1);
 	pci_release_regions(chip->pci);
 	pci_disable_device(chip->pci);
 
@@ -1788,14 +1781,11 @@
 	.trigger =	snd_cs4281_midi_input_trigger,
 };
 
-static int snd_cs4281_midi(struct cs4281 *chip, int device,
-			   struct snd_rawmidi **rrawmidi)
+static int snd_cs4281_midi(struct cs4281 *chip, int device)
 {
 	struct snd_rawmidi *rmidi;
 	int err;
 
-	if (rrawmidi)
-		*rrawmidi = NULL;
 	if ((err = snd_rawmidi_new(chip->card, "CS4281", device, 1, 1, &rmidi)) < 0)
 		return err;
 	strcpy(rmidi->name, "CS4281");
@@ -1804,8 +1794,6 @@
 	rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX;
 	rmidi->private_data = chip;
 	chip->rmidi = rmidi;
-	if (rrawmidi)
-		*rrawmidi = rmidi;
 	return 0;
 }
 
@@ -1941,11 +1929,11 @@
 		snd_card_free(card);
 		return err;
 	}
-	if ((err = snd_cs4281_pcm(chip, 0, NULL)) < 0) {
+	if ((err = snd_cs4281_pcm(chip, 0)) < 0) {
 		snd_card_free(card);
 		return err;
 	}
-	if ((err = snd_cs4281_midi(chip, 0, NULL)) < 0) {
+	if ((err = snd_cs4281_midi(chip, 0)) < 0) {
 		snd_card_free(card);
 		return err;
 	}
@@ -2008,7 +1996,6 @@
 
 static int cs4281_suspend(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct cs4281 *chip = card->private_data;
 	u32 ulCLK;
@@ -2047,30 +2034,16 @@
 	ulCLK = snd_cs4281_peekBA0(chip, BA0_CLKCR1);
 	ulCLK &= ~CLKCR1_CKRA;
 	snd_cs4281_pokeBA0(chip, BA0_CLKCR1, ulCLK);
-
-	pci_disable_device(pci);
-	pci_save_state(pci);
-	pci_set_power_state(pci, PCI_D3hot);
 	return 0;
 }
 
 static int cs4281_resume(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct cs4281 *chip = card->private_data;
 	unsigned int i;
 	u32 ulCLK;
 
-	pci_set_power_state(pci, PCI_D0);
-	pci_restore_state(pci);
-	if (pci_enable_device(pci) < 0) {
-		dev_err(dev, "pci_enable_device failed, disabling device\n");
-		snd_card_disconnect(card);
-		return -EIO;
-	}
-	pci_set_master(pci);
-
 	ulCLK = snd_cs4281_peekBA0(chip, BA0_CLKCR1);
 	ulCLK |= CLKCR1_CKRA;
 	snd_cs4281_pokeBA0(chip, BA0_CLKCR1, ulCLK);
diff --git a/sound/pci/cs46xx/cs46xx.c b/sound/pci/cs46xx/cs46xx.c
index 6a6858c..655fbea 100644
--- a/sound/pci/cs46xx/cs46xx.c
+++ b/sound/pci/cs46xx/cs46xx.c
@@ -100,16 +100,16 @@
 	}
 	card->private_data = chip;
 	chip->accept_valid = mmap_valid[dev];
-	if ((err = snd_cs46xx_pcm(chip, 0, NULL)) < 0) {
+	if ((err = snd_cs46xx_pcm(chip, 0)) < 0) {
 		snd_card_free(card);
 		return err;
 	}
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
-	if ((err = snd_cs46xx_pcm_rear(chip,1, NULL)) < 0) {
+	if ((err = snd_cs46xx_pcm_rear(chip, 1)) < 0) {
 		snd_card_free(card);
 		return err;
 	}
-	if ((err = snd_cs46xx_pcm_iec958(chip,2,NULL)) < 0) {
+	if ((err = snd_cs46xx_pcm_iec958(chip, 2)) < 0) {
 		snd_card_free(card);
 		return err;
 	}
@@ -120,13 +120,13 @@
 	}
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
 	if (chip->nr_ac97_codecs ==2) {
-		if ((err = snd_cs46xx_pcm_center_lfe(chip,3,NULL)) < 0) {
+		if ((err = snd_cs46xx_pcm_center_lfe(chip, 3)) < 0) {
 			snd_card_free(card);
 			return err;
 		}
 	}
 #endif
-	if ((err = snd_cs46xx_midi(chip, 0, NULL)) < 0) {
+	if ((err = snd_cs46xx_midi(chip, 0)) < 0) {
 		snd_card_free(card);
 		return err;
 	}
diff --git a/sound/pci/cs46xx/cs46xx.h b/sound/pci/cs46xx/cs46xx.h
index c49a082..9c9f89a 100644
--- a/sound/pci/cs46xx/cs46xx.h
+++ b/sound/pci/cs46xx/cs46xx.h
@@ -1737,12 +1737,12 @@
 		      struct snd_cs46xx **rcodec);
 extern const struct dev_pm_ops snd_cs46xx_pm;
 
-int snd_cs46xx_pcm(struct snd_cs46xx *chip, int device, struct snd_pcm **rpcm);
-int snd_cs46xx_pcm_rear(struct snd_cs46xx *chip, int device, struct snd_pcm **rpcm);
-int snd_cs46xx_pcm_iec958(struct snd_cs46xx *chip, int device, struct snd_pcm **rpcm);
-int snd_cs46xx_pcm_center_lfe(struct snd_cs46xx *chip, int device, struct snd_pcm **rpcm);
+int snd_cs46xx_pcm(struct snd_cs46xx *chip, int device);
+int snd_cs46xx_pcm_rear(struct snd_cs46xx *chip, int device);
+int snd_cs46xx_pcm_iec958(struct snd_cs46xx *chip, int device);
+int snd_cs46xx_pcm_center_lfe(struct snd_cs46xx *chip, int device);
 int snd_cs46xx_mixer(struct snd_cs46xx *chip, int spdif_device);
-int snd_cs46xx_midi(struct snd_cs46xx *chip, int device, struct snd_rawmidi **rmidi);
+int snd_cs46xx_midi(struct snd_cs46xx *chip, int device);
 int snd_cs46xx_start_dsp(struct snd_cs46xx *chip);
 int snd_cs46xx_gameport(struct snd_cs46xx *chip);
 
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c
index 32b44f2..8d74004 100644
--- a/sound/pci/cs46xx/cs46xx_lib.c
+++ b/sound/pci/cs46xx/cs46xx_lib.c
@@ -57,6 +57,7 @@
 #include <linux/module.h>
 #include <linux/firmware.h>
 #include <linux/vmalloc.h>
+#include <linux/io.h>
 
 #include <sound/core.h>
 #include <sound/control.h>
@@ -65,8 +66,6 @@
 #include <sound/pcm_params.h>
 #include "cs46xx.h"
 
-#include <asm/io.h>
-
 #include "cs46xx_lib.h"
 #include "dsp_spos.h"
 
@@ -1778,13 +1777,11 @@
 #define MAX_PLAYBACK_CHANNELS	1
 #endif
 
-int snd_cs46xx_pcm(struct snd_cs46xx *chip, int device, struct snd_pcm **rpcm)
+int snd_cs46xx_pcm(struct snd_cs46xx *chip, int device)
 {
 	struct snd_pcm *pcm;
 	int err;
 
-	if (rpcm)
-		*rpcm = NULL;
 	if ((err = snd_pcm_new(chip->card, "CS46xx", device, MAX_PLAYBACK_CHANNELS, 1, &pcm)) < 0)
 		return err;
 
@@ -1801,23 +1798,16 @@
 	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
 					      snd_dma_pci_data(chip->pci), 64*1024, 256*1024);
 
-	if (rpcm)
-		*rpcm = pcm;
-
 	return 0;
 }
 
 
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
-int snd_cs46xx_pcm_rear(struct snd_cs46xx *chip, int device,
-			struct snd_pcm **rpcm)
+int snd_cs46xx_pcm_rear(struct snd_cs46xx *chip, int device)
 {
 	struct snd_pcm *pcm;
 	int err;
 
-	if (rpcm)
-		*rpcm = NULL;
-
 	if ((err = snd_pcm_new(chip->card, "CS46xx - Rear", device, MAX_PLAYBACK_CHANNELS, 0, &pcm)) < 0)
 		return err;
 
@@ -1833,21 +1823,14 @@
 	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
 					      snd_dma_pci_data(chip->pci), 64*1024, 256*1024);
 
-	if (rpcm)
-		*rpcm = pcm;
-
 	return 0;
 }
 
-int snd_cs46xx_pcm_center_lfe(struct snd_cs46xx *chip, int device,
-			      struct snd_pcm **rpcm)
+int snd_cs46xx_pcm_center_lfe(struct snd_cs46xx *chip, int device)
 {
 	struct snd_pcm *pcm;
 	int err;
 
-	if (rpcm)
-		*rpcm = NULL;
-
 	if ((err = snd_pcm_new(chip->card, "CS46xx - Center LFE", device, MAX_PLAYBACK_CHANNELS, 0, &pcm)) < 0)
 		return err;
 
@@ -1863,21 +1846,14 @@
 	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
 					      snd_dma_pci_data(chip->pci), 64*1024, 256*1024);
 
-	if (rpcm)
-		*rpcm = pcm;
-
 	return 0;
 }
 
-int snd_cs46xx_pcm_iec958(struct snd_cs46xx *chip, int device,
-			  struct snd_pcm **rpcm)
+int snd_cs46xx_pcm_iec958(struct snd_cs46xx *chip, int device)
 {
 	struct snd_pcm *pcm;
 	int err;
 
-	if (rpcm)
-		*rpcm = NULL;
-
 	if ((err = snd_pcm_new(chip->card, "CS46xx - IEC958", device, 1, 0, &pcm)) < 0)
 		return err;
 
@@ -1893,9 +1869,6 @@
 	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
 					      snd_dma_pci_data(chip->pci), 64*1024, 256*1024);
 
-	if (rpcm)
-		*rpcm = pcm;
-
 	return 0;
 }
 #endif
@@ -2724,13 +2697,11 @@
 	.trigger =	snd_cs46xx_midi_input_trigger,
 };
 
-int snd_cs46xx_midi(struct snd_cs46xx *chip, int device, struct snd_rawmidi **rrawmidi)
+int snd_cs46xx_midi(struct snd_cs46xx *chip, int device)
 {
 	struct snd_rawmidi *rmidi;
 	int err;
 
-	if (rrawmidi)
-		*rrawmidi = NULL;
 	if ((err = snd_rawmidi_new(chip->card, "CS46XX", device, 1, 1, &rmidi)) < 0)
 		return err;
 	strcpy(rmidi->name, "CS46XX");
@@ -2739,8 +2710,6 @@
 	rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX;
 	rmidi->private_data = chip;
 	chip->rmidi = rmidi;
-	if (rrawmidi)
-		*rrawmidi = NULL;
 	return 0;
 }
 
@@ -2979,8 +2948,8 @@
 
 	for (idx = 0; idx < 5; idx++) {
 		struct snd_cs46xx_region *region = &chip->region.idx[idx];
-		if (region->remap_addr)
-			iounmap(region->remap_addr);
+
+		iounmap(region->remap_addr);
 		release_and_free_resource(region->resource);
 	}
 
@@ -3804,7 +3773,6 @@
 
 static int snd_cs46xx_suspend(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct snd_cs46xx *chip = card->private_data;
 	int i, amp_saved;
@@ -3829,16 +3797,11 @@
 	/* disable CLKRUN */
 	chip->active_ctrl(chip, -chip->amplifier);
 	chip->amplifier = amp_saved; /* restore the status */
-
-	pci_disable_device(pci);
-	pci_save_state(pci);
-	pci_set_power_state(pci, PCI_D3hot);
 	return 0;
 }
 
 static int snd_cs46xx_resume(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct snd_cs46xx *chip = card->private_data;
 	int amp_saved;
@@ -3847,15 +3810,6 @@
 #endif
 	unsigned int tmp;
 
-	pci_set_power_state(pci, PCI_D0);
-	pci_restore_state(pci);
-	if (pci_enable_device(pci) < 0) {
-		dev_err(dev, "pci_enable_device failed, disabling device\n");
-		snd_card_disconnect(card);
-		return -EIO;
-	}
-	pci_set_master(pci);
-
 	amp_saved = chip->amplifier;
 	chip->amplifier = 0;
 	chip->active_ctrl(chip, 1); /* force to on */
diff --git a/sound/pci/cs46xx/dsp_spos.c b/sound/pci/cs46xx/dsp_spos.c
index 1c4a0fb..5c99efb 100644
--- a/sound/pci/cs46xx/dsp_spos.c
+++ b/sound/pci/cs46xx/dsp_spos.c
@@ -20,7 +20,7 @@
  */
 
 
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/init.h>
diff --git a/sound/pci/cs46xx/dsp_spos_scb_lib.c b/sound/pci/cs46xx/dsp_spos_scb_lib.c
index 8284bc9..2c90c0b 100644
--- a/sound/pci/cs46xx/dsp_spos_scb_lib.c
+++ b/sound/pci/cs46xx/dsp_spos_scb_lib.c
@@ -21,7 +21,7 @@
  */
 
 
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/init.h>
diff --git a/sound/pci/cs5530.c b/sound/pci/cs5530.c
index b102550..0a8cf94 100644
--- a/sound/pci/cs5530.c
+++ b/sound/pci/cs5530.c
@@ -223,7 +223,7 @@
 		return err;
 	}
 
-	err = snd_sb16dsp_pcm(chip->sb, 0, &chip->sb->pcm);
+	err = snd_sb16dsp_pcm(chip->sb, 0);
 	if (err < 0) {
 		dev_err(card->dev, "Could not create PCM\n");
 		snd_cs5530_free(chip);
diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c
index 16288e4..802c33f 100644
--- a/sound/pci/cs5535audio/cs5535audio.c
+++ b/sound/pci/cs5535audio/cs5535audio.c
@@ -27,7 +27,7 @@
 #include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/module.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <sound/core.h>
 #include <sound/control.h>
 #include <sound/pcm.h>
diff --git a/sound/pci/cs5535audio/cs5535audio_pm.c b/sound/pci/cs5535audio/cs5535audio_pm.c
index 34cc600..06ac5d8 100644
--- a/sound/pci/cs5535audio/cs5535audio_pm.c
+++ b/sound/pci/cs5535audio/cs5535audio_pm.c
@@ -57,7 +57,6 @@
 
 static int snd_cs5535audio_suspend(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct cs5535audio *cs5535au = card->private_data;
 	int i;
@@ -72,34 +71,17 @@
 	}
 	/* save important regs, then disable aclink in hw */
 	snd_cs5535audio_stop_hardware(cs5535au);
-
-	if (pci_save_state(pci)) {
-		dev_err(dev, "pci_save_state failed!\n");
-		return -EIO;
-	}
-	pci_disable_device(pci);
-	pci_set_power_state(pci, PCI_D3hot);
 	return 0;
 }
 
 static int snd_cs5535audio_resume(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct cs5535audio *cs5535au = card->private_data;
 	u32 tmp;
 	int timeout;
 	int i;
 
-	pci_set_power_state(pci, PCI_D0);
-	pci_restore_state(pci);
-	if (pci_enable_device(pci) < 0) {
-		dev_err(dev, "pci_enable_device failed, disabling device\n");
-		snd_card_disconnect(card);
-		return -EIO;
-	}
-	pci_set_master(pci);
-
 	/* set LNK_WRM_RST to reset AC link */
 	cs_writel(cs5535au, ACC_CODEC_CNTL, ACC_CODEC_CNTL_LNK_WRM_RST);
 
diff --git a/sound/pci/ctxfi/cthw20k1.c b/sound/pci/ctxfi/cthw20k1.c
index b425aa8..1cac55f 100644
--- a/sound/pci/ctxfi/cthw20k1.c
+++ b/sound/pci/ctxfi/cthw20k1.c
@@ -1985,10 +1985,7 @@
 		free_irq(hw->irq, hw);
 
 	hw->irq	= -1;
-
-	if (hw->mem_base)
-		iounmap(hw->mem_base);
-
+	iounmap(hw->mem_base);
 	hw->mem_base = NULL;
 
 	if (hw->io_base)
@@ -2099,20 +2096,11 @@
 		pci_write_config_dword(pci, UAA_CFG_SPACE_FLAG, 0x0);
 	}
 
-	pci_disable_device(pci);
-	pci_save_state(pci);
-	pci_set_power_state(pci, PCI_D3hot);
-
 	return 0;
 }
 
 static int hw_resume(struct hw *hw, struct card_conf *info)
 {
-	struct pci_dev *pci = hw->pci;
-
-	pci_set_power_state(pci, PCI_D0);
-	pci_restore_state(pci);
-
 	/* Re-initialize card hardware. */
 	return hw_card_init(hw, info);
 }
diff --git a/sound/pci/ctxfi/cthw20k2.c b/sound/pci/ctxfi/cthw20k2.c
index 253899d..955ad87 100644
--- a/sound/pci/ctxfi/cthw20k2.c
+++ b/sound/pci/ctxfi/cthw20k2.c
@@ -2110,10 +2110,7 @@
 		free_irq(hw->irq, hw);
 
 	hw->irq	= -1;
-
-	if (hw->mem_base)
-		iounmap(hw->mem_base);
-
+	iounmap(hw->mem_base);
 	hw->mem_base = NULL;
 
 	if (hw->io_base)
@@ -2209,24 +2206,12 @@
 #ifdef CONFIG_PM_SLEEP
 static int hw_suspend(struct hw *hw)
 {
-	struct pci_dev *pci = hw->pci;
-
 	hw_card_stop(hw);
-
-	pci_disable_device(pci);
-	pci_save_state(pci);
-	pci_set_power_state(pci, PCI_D3hot);
-
 	return 0;
 }
 
 static int hw_resume(struct hw *hw, struct card_conf *info)
 {
-	struct pci_dev *pci = hw->pci;
-
-	pci_set_power_state(pci, PCI_D0);
-	pci_restore_state(pci);
-
 	/* Re-initialize card hardware. */
 	return hw_card_init(hw, info);
 }
diff --git a/sound/pci/echoaudio/darla20.c b/sound/pci/echoaudio/darla20.c
index 4632946..c95da63 100644
--- a/sound/pci/echoaudio/darla20.c
+++ b/sound/pci/echoaudio/darla20.c
@@ -43,6 +43,7 @@
 #include <linux/module.h>
 #include <linux/firmware.h>
 #include <linux/slab.h>
+#include <linux/io.h>
 #include <sound/core.h>
 #include <sound/info.h>
 #include <sound/control.h>
@@ -51,7 +52,6 @@
 #include <sound/pcm_params.h>
 #include <sound/asoundef.h>
 #include <sound/initval.h>
-#include <asm/io.h>
 #include <linux/atomic.h>
 #include "echoaudio.h"
 
diff --git a/sound/pci/echoaudio/darla24.c b/sound/pci/echoaudio/darla24.c
index f81c839..3013b4d 100644
--- a/sound/pci/echoaudio/darla24.c
+++ b/sound/pci/echoaudio/darla24.c
@@ -47,6 +47,7 @@
 #include <linux/module.h>
 #include <linux/firmware.h>
 #include <linux/slab.h>
+#include <linux/io.h>
 #include <sound/core.h>
 #include <sound/info.h>
 #include <sound/control.h>
@@ -55,7 +56,6 @@
 #include <sound/pcm_params.h>
 #include <sound/asoundef.h>
 #include <sound/initval.h>
-#include <asm/io.h>
 #include <linux/atomic.h>
 #include "echoaudio.h"
 
diff --git a/sound/pci/echoaudio/echo3g.c b/sound/pci/echoaudio/echo3g.c
index 3a5346c..1f34a07 100644
--- a/sound/pci/echoaudio/echo3g.c
+++ b/sound/pci/echoaudio/echo3g.c
@@ -54,6 +54,7 @@
 #include <linux/module.h>
 #include <linux/firmware.h>
 #include <linux/slab.h>
+#include <linux/io.h>
 #include <sound/core.h>
 #include <sound/info.h>
 #include <sound/control.h>
@@ -63,7 +64,6 @@
 #include <sound/asoundef.h>
 #include <sound/initval.h>
 #include <sound/rawmidi.h>
-#include <asm/io.h>
 #include <linux/atomic.h>
 #include "echoaudio.h"
 
diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c
index 21228ad..a962de0 100644
--- a/sound/pci/echoaudio/echoaudio.c
+++ b/sound/pci/echoaudio/echoaudio.c
@@ -1872,12 +1872,8 @@
 	if (chip->comm_page)
 		snd_dma_free_pages(&chip->commpage_dma_buf);
 
-	if (chip->dsp_registers)
-		iounmap(chip->dsp_registers);
-
+	iounmap(chip->dsp_registers);
 	release_and_free_resource(chip->iores);
-
-
 	pci_disable_device(chip->pci);
 
 	/* release chip data */
@@ -2162,7 +2158,6 @@
 
 static int snd_echo_suspend(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct echoaudio *chip = dev_get_drvdata(dev);
 
 	snd_pcm_suspend_all(chip->analog_pcm);
@@ -2188,9 +2183,6 @@
 	chip->dsp_code = NULL;
 	free_irq(chip->irq, chip);
 	chip->irq = -1;
-	pci_save_state(pci);
-	pci_disable_device(pci);
-
 	return 0;
 }
 
@@ -2204,7 +2196,6 @@
 	u32 pipe_alloc_mask;
 	int err;
 
-	pci_restore_state(pci);
 	commpage_bak = kmalloc(sizeof(struct echoaudio), GFP_KERNEL);
 	if (commpage_bak == NULL)
 		return -ENOMEM;
diff --git a/sound/pci/echoaudio/gina20.c b/sound/pci/echoaudio/gina20.c
index 9cb81c5..4fa32a2 100644
--- a/sound/pci/echoaudio/gina20.c
+++ b/sound/pci/echoaudio/gina20.c
@@ -47,6 +47,7 @@
 #include <linux/module.h>
 #include <linux/firmware.h>
 #include <linux/slab.h>
+#include <linux/io.h>
 #include <sound/core.h>
 #include <sound/info.h>
 #include <sound/control.h>
@@ -55,7 +56,6 @@
 #include <sound/pcm_params.h>
 #include <sound/asoundef.h>
 #include <sound/initval.h>
-#include <asm/io.h>
 #include <linux/atomic.h>
 #include "echoaudio.h"
 
diff --git a/sound/pci/echoaudio/gina24.c b/sound/pci/echoaudio/gina24.c
index 35d3e6e..b1bcaca 100644
--- a/sound/pci/echoaudio/gina24.c
+++ b/sound/pci/echoaudio/gina24.c
@@ -53,6 +53,7 @@
 #include <linux/module.h>
 #include <linux/firmware.h>
 #include <linux/slab.h>
+#include <linux/io.h>
 #include <sound/core.h>
 #include <sound/info.h>
 #include <sound/control.h>
@@ -61,7 +62,6 @@
 #include <sound/pcm_params.h>
 #include <sound/asoundef.h>
 #include <sound/initval.h>
-#include <asm/io.h>
 #include <linux/atomic.h>
 #include "echoaudio.h"
 
diff --git a/sound/pci/echoaudio/indigo.c b/sound/pci/echoaudio/indigo.c
index 8d91842..175af9b 100644
--- a/sound/pci/echoaudio/indigo.c
+++ b/sound/pci/echoaudio/indigo.c
@@ -45,6 +45,7 @@
 #include <linux/module.h>
 #include <linux/firmware.h>
 #include <linux/slab.h>
+#include <linux/io.h>
 #include <sound/core.h>
 #include <sound/info.h>
 #include <sound/control.h>
@@ -53,7 +54,6 @@
 #include <sound/pcm_params.h>
 #include <sound/asoundef.h>
 #include <sound/initval.h>
-#include <asm/io.h>
 #include <linux/atomic.h>
 #include "echoaudio.h"
 
diff --git a/sound/pci/echoaudio/indigodj.c b/sound/pci/echoaudio/indigodj.c
index 289cb96..8c60314 100644
--- a/sound/pci/echoaudio/indigodj.c
+++ b/sound/pci/echoaudio/indigodj.c
@@ -45,6 +45,7 @@
 #include <linux/module.h>
 #include <linux/firmware.h>
 #include <linux/slab.h>
+#include <linux/io.h>
 #include <sound/core.h>
 #include <sound/info.h>
 #include <sound/control.h>
@@ -53,7 +54,6 @@
 #include <sound/pcm_params.h>
 #include <sound/asoundef.h>
 #include <sound/initval.h>
-#include <asm/io.h>
 #include <linux/atomic.h>
 #include "echoaudio.h"
 
diff --git a/sound/pci/echoaudio/indigoio.c b/sound/pci/echoaudio/indigoio.c
index 405a3f2..f7618ed 100644
--- a/sound/pci/echoaudio/indigoio.c
+++ b/sound/pci/echoaudio/indigoio.c
@@ -46,6 +46,7 @@
 #include <linux/module.h>
 #include <linux/firmware.h>
 #include <linux/slab.h>
+#include <linux/io.h>
 #include <sound/core.h>
 #include <sound/info.h>
 #include <sound/control.h>
@@ -54,7 +55,6 @@
 #include <sound/pcm_params.h>
 #include <sound/asoundef.h>
 #include <sound/initval.h>
-#include <asm/io.h>
 #include <linux/atomic.h>
 #include "echoaudio.h"
 
diff --git a/sound/pci/echoaudio/layla20.c b/sound/pci/echoaudio/layla20.c
index b392dd7..12e5d21 100644
--- a/sound/pci/echoaudio/layla20.c
+++ b/sound/pci/echoaudio/layla20.c
@@ -52,6 +52,7 @@
 #include <linux/module.h>
 #include <linux/firmware.h>
 #include <linux/slab.h>
+#include <linux/io.h>
 #include <sound/core.h>
 #include <sound/info.h>
 #include <sound/control.h>
@@ -61,7 +62,6 @@
 #include <sound/asoundef.h>
 #include <sound/initval.h>
 #include <sound/rawmidi.h>
-#include <asm/io.h>
 #include <linux/atomic.h>
 #include "echoaudio.h"
 
diff --git a/sound/pci/echoaudio/layla24.c b/sound/pci/echoaudio/layla24.c
index bc7f730..6e40237 100644
--- a/sound/pci/echoaudio/layla24.c
+++ b/sound/pci/echoaudio/layla24.c
@@ -54,6 +54,7 @@
 #include <linux/module.h>
 #include <linux/firmware.h>
 #include <linux/slab.h>
+#include <linux/io.h>
 #include <sound/core.h>
 #include <sound/info.h>
 #include <sound/control.h>
@@ -63,7 +64,6 @@
 #include <sound/asoundef.h>
 #include <sound/initval.h>
 #include <sound/rawmidi.h>
-#include <asm/io.h>
 #include <linux/atomic.h>
 #include "echoaudio.h"
 
diff --git a/sound/pci/echoaudio/mia.c b/sound/pci/echoaudio/mia.c
index 27a9a6e..2f7562f 100644
--- a/sound/pci/echoaudio/mia.c
+++ b/sound/pci/echoaudio/mia.c
@@ -53,6 +53,7 @@
 #include <linux/module.h>
 #include <linux/firmware.h>
 #include <linux/slab.h>
+#include <linux/io.h>
 #include <sound/core.h>
 #include <sound/info.h>
 #include <sound/control.h>
@@ -62,7 +63,6 @@
 #include <sound/asoundef.h>
 #include <sound/initval.h>
 #include <sound/rawmidi.h>
-#include <asm/io.h>
 #include <linux/atomic.h>
 #include "echoaudio.h"
 
diff --git a/sound/pci/echoaudio/midi.c b/sound/pci/echoaudio/midi.c
index d913749..a8fe583 100644
--- a/sound/pci/echoaudio/midi.c
+++ b/sound/pci/echoaudio/midi.c
@@ -257,9 +257,8 @@
 	spin_lock_irq(&chip->lock);
 	if (up) {
 		if (!chip->tinuse) {
-			init_timer(&chip->timer);
-			chip->timer.function = snd_echo_midi_output_write;
-			chip->timer.data = (unsigned long)chip;
+			setup_timer(&chip->timer, snd_echo_midi_output_write,
+				    (unsigned long)chip);
 			chip->tinuse = 1;
 		}
 	} else {
diff --git a/sound/pci/echoaudio/mona.c b/sound/pci/echoaudio/mona.c
index 3d13875..34d4994 100644
--- a/sound/pci/echoaudio/mona.c
+++ b/sound/pci/echoaudio/mona.c
@@ -51,6 +51,7 @@
 #include <linux/module.h>
 #include <linux/firmware.h>
 #include <linux/slab.h>
+#include <linux/io.h>
 #include <sound/core.h>
 #include <sound/info.h>
 #include <sound/control.h>
@@ -59,7 +60,6 @@
 #include <sound/pcm_params.h>
 #include <sound/asoundef.h>
 #include <sound/initval.h>
-#include <asm/io.h>
 #include <linux/atomic.h>
 #include "echoaudio.h"
 
diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c
index 4c171636e..37d0220 100644
--- a/sound/pci/emu10k1/emu10k1.c
+++ b/sound/pci/emu10k1/emu10k1.c
@@ -132,11 +132,11 @@
 		goto error;
 	card->private_data = emu;
 	emu->delay_pcm_irq = delay_pcm_irq[dev] & 0x1f;
-	if ((err = snd_emu10k1_pcm(emu, 0, NULL)) < 0)
+	if ((err = snd_emu10k1_pcm(emu, 0)) < 0)
 		goto error;
-	if ((err = snd_emu10k1_pcm_mic(emu, 1, NULL)) < 0)
+	if ((err = snd_emu10k1_pcm_mic(emu, 1)) < 0)
 		goto error;
-	if ((err = snd_emu10k1_pcm_efx(emu, 2, NULL)) < 0)
+	if ((err = snd_emu10k1_pcm_efx(emu, 2)) < 0)
 		goto error;
 	/* This stores the periods table. */
 	if (emu->card_capabilities->ca0151_chip) { /* P16V */	
@@ -151,10 +151,10 @@
 	if ((err = snd_emu10k1_timer(emu, 0)) < 0)
 		goto error;
 
-	if ((err = snd_emu10k1_pcm_multi(emu, 3, NULL)) < 0)
+	if ((err = snd_emu10k1_pcm_multi(emu, 3)) < 0)
 		goto error;
 	if (emu->card_capabilities->ca0151_chip) { /* P16V */
-		if ((err = snd_p16v_pcm(emu, 4, NULL)) < 0)
+		if ((err = snd_p16v_pcm(emu, 4)) < 0)
 			goto error;
 	}
 	if (emu->audigy) {
@@ -164,7 +164,7 @@
 		if ((err = snd_emu10k1_midi(emu)) < 0)
 			goto error;
 	}
-	if ((err = snd_emu10k1_fx8010_new(emu, 0, NULL)) < 0)
+	if ((err = snd_emu10k1_fx8010_new(emu, 0)) < 0)
 		goto error;
 #ifdef ENABLE_SYNTH
 	if (snd_seq_device_new(card, 1, SNDRV_SEQ_DEV_ID_EMU10K1_SYNTH,
@@ -210,7 +210,6 @@
 #ifdef CONFIG_PM_SLEEP
 static int snd_emu10k1_suspend(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct snd_emu10k1 *emu = card->private_data;
 
@@ -232,28 +231,14 @@
 		snd_p16v_suspend(emu);
 
 	snd_emu10k1_done(emu);
-
-	pci_disable_device(pci);
-	pci_save_state(pci);
-	pci_set_power_state(pci, PCI_D3hot);
 	return 0;
 }
 
 static int snd_emu10k1_resume(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct snd_emu10k1 *emu = card->private_data;
 
-	pci_set_power_state(pci, PCI_D0);
-	pci_restore_state(pci);
-	if (pci_enable_device(pci) < 0) {
-		dev_err(dev, "pci_enable_device failed, disabling device\n");
-		snd_card_disconnect(card);
-		return -EIO;
-	}
-	pci_set_master(pci);
-
 	snd_emu10k1_resume_init(emu);
 	snd_emu10k1_efx_resume(emu);
 	snd_ac97_resume(emu->ac97);
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c
index 15933f9..6d1b98d 100644
--- a/sound/pci/emu10k1/emu10k1x.c
+++ b/sound/pci/emu10k1/emu10k1x.c
@@ -847,15 +847,13 @@
 	{ }
 };
 
-static int snd_emu10k1x_pcm(struct emu10k1x *emu, int device, struct snd_pcm **rpcm)
+static int snd_emu10k1x_pcm(struct emu10k1x *emu, int device)
 {
 	struct snd_pcm *pcm;
 	const struct snd_pcm_chmap_elem *map = NULL;
 	int err;
 	int capture = 0;
   
-	if (rpcm)
-		*rpcm = NULL;
 	if (device == 0)
 		capture = 1;
 	
@@ -896,15 +894,8 @@
 					      snd_dma_pci_data(emu->pci), 
 					      32*1024, 32*1024);
   
-	err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, map, 2,
+	return snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, map, 2,
 				     1 << 2, NULL);
-	if (err < 0)
-		return err;
-
-	if (rpcm)
-		*rpcm = pcm;
-  
-	return 0;
 }
 
 static int snd_emu10k1x_create(struct snd_card *card,
@@ -1583,15 +1574,15 @@
 		return err;
 	}
 
-	if ((err = snd_emu10k1x_pcm(chip, 0, NULL)) < 0) {
+	if ((err = snd_emu10k1x_pcm(chip, 0)) < 0) {
 		snd_card_free(card);
 		return err;
 	}
-	if ((err = snd_emu10k1x_pcm(chip, 1, NULL)) < 0) {
+	if ((err = snd_emu10k1x_pcm(chip, 1)) < 0) {
 		snd_card_free(card);
 		return err;
 	}
-	if ((err = snd_emu10k1x_pcm(chip, 2, NULL)) < 0) {
+	if ((err = snd_emu10k1x_pcm(chip, 2)) < 0) {
 		snd_card_free(card);
 		return err;
 	}
diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c
index eb5c0ab..56fc47b 100644
--- a/sound/pci/emu10k1/emufx.c
+++ b/sound/pci/emu10k1/emufx.c
@@ -2641,14 +2641,11 @@
 	return 0;
 }
 
-int snd_emu10k1_fx8010_new(struct snd_emu10k1 *emu, int device,
-			   struct snd_hwdep **rhwdep)
+int snd_emu10k1_fx8010_new(struct snd_emu10k1 *emu, int device)
 {
 	struct snd_hwdep *hw;
 	int err;
 	
-	if (rhwdep)
-		*rhwdep = NULL;
 	if ((err = snd_hwdep_new(emu->card, "FX8010", device, &hw)) < 0)
 		return err;
 	strcpy(hw->name, "EMU10K1 (FX8010)");
@@ -2657,8 +2654,6 @@
 	hw->ops.ioctl = snd_emu10k1_fx8010_ioctl;
 	hw->ops.release = snd_emu10k1_fx8010_release;
 	hw->private_data = emu;
-	if (rhwdep)
-		*rhwdep = hw;
 	return 0;
 }
 
diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c
index f82481b..0dc0738 100644
--- a/sound/pci/emu10k1/emupcm.c
+++ b/sound/pci/emu10k1/emupcm.c
@@ -1400,15 +1400,12 @@
 	.page =			snd_pcm_sgbuf_ops_page,
 };
 
-int snd_emu10k1_pcm(struct snd_emu10k1 *emu, int device, struct snd_pcm **rpcm)
+int snd_emu10k1_pcm(struct snd_emu10k1 *emu, int device)
 {
 	struct snd_pcm *pcm;
 	struct snd_pcm_substream *substream;
 	int err;
 
-	if (rpcm)
-		*rpcm = NULL;
-
 	if ((err = snd_pcm_new(emu->card, "emu10k1", device, 32, 1, &pcm)) < 0)
 		return err;
 
@@ -1429,22 +1426,15 @@
 	for (substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; substream; substream = substream->next)
 		snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(emu->pci), 64*1024, 64*1024);
 
-	if (rpcm)
-		*rpcm = pcm;
-
 	return 0;
 }
 
-int snd_emu10k1_pcm_multi(struct snd_emu10k1 *emu, int device,
-			  struct snd_pcm **rpcm)
+int snd_emu10k1_pcm_multi(struct snd_emu10k1 *emu, int device)
 {
 	struct snd_pcm *pcm;
 	struct snd_pcm_substream *substream;
 	int err;
 
-	if (rpcm)
-		*rpcm = NULL;
-
 	if ((err = snd_pcm_new(emu->card, "emu10k1", device, 1, 0, &pcm)) < 0)
 		return err;
 
@@ -1461,9 +1451,6 @@
 		if ((err = snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV_SG, snd_dma_pci_data(emu->pci), 64*1024, 64*1024)) < 0)
 			return err;
 
-	if (rpcm)
-		*rpcm = pcm;
-
 	return 0;
 }
 
@@ -1479,15 +1466,11 @@
 	.pointer =		snd_emu10k1_capture_pointer,
 };
 
-int snd_emu10k1_pcm_mic(struct snd_emu10k1 *emu, int device,
-			struct snd_pcm **rpcm)
+int snd_emu10k1_pcm_mic(struct snd_emu10k1 *emu, int device)
 {
 	struct snd_pcm *pcm;
 	int err;
 
-	if (rpcm)
-		*rpcm = NULL;
-
 	if ((err = snd_pcm_new(emu->card, "emu10k1 mic", device, 0, 1, &pcm)) < 0)
 		return err;
 
@@ -1501,8 +1484,6 @@
 
 	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(emu->pci), 64*1024, 64*1024);
 
-	if (rpcm)
-		*rpcm = pcm;
 	return 0;
 }
 
@@ -1822,16 +1803,12 @@
 	.ack =			snd_emu10k1_fx8010_playback_transfer,
 };
 
-int snd_emu10k1_pcm_efx(struct snd_emu10k1 *emu, int device,
-			struct snd_pcm **rpcm)
+int snd_emu10k1_pcm_efx(struct snd_emu10k1 *emu, int device)
 {
 	struct snd_pcm *pcm;
 	struct snd_kcontrol *kctl;
 	int err;
 
-	if (rpcm)
-		*rpcm = NULL;
-
 	if ((err = snd_pcm_new(emu->card, "emu10k1 efx", device, 8, 1, &pcm)) < 0)
 		return err;
 
@@ -1843,8 +1820,6 @@
 	pcm->info_flags = 0;
 	strcpy(pcm->name, "Multichannel Capture/PT Playback");
 	emu->pcm_efx = pcm;
-	if (rpcm)
-		*rpcm = pcm;
 
 	/* EFX capture - record the "FXBUS2" channels, by default we connect the EXTINs 
 	 * to these
diff --git a/sound/pci/emu10k1/p16v.c b/sound/pci/emu10k1/p16v.c
index 7ef3898..3c60b43 100644
--- a/sound/pci/emu10k1/p16v.c
+++ b/sound/pci/emu10k1/p16v.c
@@ -166,11 +166,8 @@
 static void snd_p16v_pcm_free_substream(struct snd_pcm_runtime *runtime)
 {
 	struct snd_emu10k1_pcm *epcm = runtime->private_data;
-  
-	if (epcm) {
-		/* dev_dbg(emu->card->dev, "epcm free: %p\n", epcm); */
-		kfree(epcm);
-	}
+
+	kfree(epcm);
 }
 
 /* open_playback callback */
@@ -640,7 +637,7 @@
 	return 0;
 }
 
-int snd_p16v_pcm(struct snd_emu10k1 *emu, int device, struct snd_pcm **rpcm)
+int snd_p16v_pcm(struct snd_emu10k1 *emu, int device)
 {
 	struct snd_pcm *pcm;
 	struct snd_pcm_substream *substream;
@@ -649,8 +646,6 @@
   
 	/* dev_dbg(emu->card->dev, "snd_p16v_pcm called. device=%d\n", device); */
 	emu->p16v_device_offset = device;
-	if (rpcm)
-		*rpcm = NULL;
 
 	if ((err = snd_pcm_new(emu->card, "p16v", device, 1, capture, &pcm)) < 0)
 		return err;
@@ -694,9 +689,6 @@
 		*/
 	}
   
-	if (rpcm)
-		*rpcm = pcm;
-  
 	return 0;
 }
 
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c
index d94cb3c..0dc44eb 100644
--- a/sound/pci/ens1370.c
+++ b/sound/pci/ens1370.c
@@ -26,7 +26,7 @@
  * by Kurt J. Bosch
  */
 
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
@@ -1268,14 +1268,11 @@
 	{ }
 };
 
-static int snd_ensoniq_pcm(struct ensoniq *ensoniq, int device,
-			   struct snd_pcm **rpcm)
+static int snd_ensoniq_pcm(struct ensoniq *ensoniq, int device)
 {
 	struct snd_pcm *pcm;
 	int err;
 
-	if (rpcm)
-		*rpcm = NULL;
 	err = snd_pcm_new(ensoniq->card, CHIP_NAME "/1", device, 1, 1, &pcm);
 	if (err < 0)
 		return err;
@@ -1302,22 +1299,14 @@
 	err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
 				     snd_pcm_std_chmaps, 2, 0, NULL);
 #endif
-	if (err < 0)
-		return err;
-
-	if (rpcm)
-		*rpcm = pcm;
-	return 0;
+	return err;
 }
 
-static int snd_ensoniq_pcm2(struct ensoniq *ensoniq, int device,
-			    struct snd_pcm **rpcm)
+static int snd_ensoniq_pcm2(struct ensoniq *ensoniq, int device)
 {
 	struct snd_pcm *pcm;
 	int err;
 
-	if (rpcm)
-		*rpcm = NULL;
 	err = snd_pcm_new(ensoniq->card, CHIP_NAME "/2", device, 1, 0, &pcm);
 	if (err < 0)
 		return err;
@@ -1342,12 +1331,7 @@
 	err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
 				     surround_map, 2, 0, NULL);
 #endif
-	if (err < 0)
-		return err;
-
-	if (rpcm)
-		*rpcm = pcm;
-	return 0;
+	return err;
 }
 
 /*
@@ -2049,7 +2033,6 @@
 #ifdef CONFIG_PM_SLEEP
 static int snd_ensoniq_suspend(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct ensoniq *ensoniq = card->private_data;
 	
@@ -2070,28 +2053,14 @@
 	udelay(100);
 	snd_ak4531_suspend(ensoniq->u.es1370.ak4531);
 #endif	
-
-	pci_disable_device(pci);
-	pci_save_state(pci);
-	pci_set_power_state(pci, PCI_D3hot);
 	return 0;
 }
 
 static int snd_ensoniq_resume(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct ensoniq *ensoniq = card->private_data;
 
-	pci_set_power_state(pci, PCI_D0);
-	pci_restore_state(pci);
-	if (pci_enable_device(pci) < 0) {
-		dev_err(dev, "pci_enable_device failed, disabling device\n");
-		snd_card_disconnect(card);
-		return -EIO;
-	}
-	pci_set_master(pci);
-
 	snd_ensoniq_chip_init(ensoniq);
 
 #ifdef CHIP1371	
@@ -2362,14 +2331,11 @@
 	.trigger =	snd_ensoniq_midi_input_trigger,
 };
 
-static int snd_ensoniq_midi(struct ensoniq *ensoniq, int device,
-			    struct snd_rawmidi **rrawmidi)
+static int snd_ensoniq_midi(struct ensoniq *ensoniq, int device)
 {
 	struct snd_rawmidi *rmidi;
 	int err;
 
-	if (rrawmidi)
-		*rrawmidi = NULL;
 	if ((err = snd_rawmidi_new(ensoniq->card, "ES1370/1", device, 1, 1, &rmidi)) < 0)
 		return err;
 	strcpy(rmidi->name, CHIP_NAME);
@@ -2379,8 +2345,6 @@
 		SNDRV_RAWMIDI_INFO_DUPLEX;
 	rmidi->private_data = ensoniq;
 	ensoniq->rmidi = rmidi;
-	if (rrawmidi)
-		*rrawmidi = rmidi;
 	return 0;
 }
 
@@ -2462,15 +2426,15 @@
 		return err;
 	}
 #endif
-	if ((err = snd_ensoniq_pcm(ensoniq, 0, NULL)) < 0) {
+	if ((err = snd_ensoniq_pcm(ensoniq, 0)) < 0) {
 		snd_card_free(card);
 		return err;
 	}
-	if ((err = snd_ensoniq_pcm2(ensoniq, 1, NULL)) < 0) {
+	if ((err = snd_ensoniq_pcm2(ensoniq, 1)) < 0) {
 		snd_card_free(card);
 		return err;
 	}
-	if ((err = snd_ensoniq_midi(ensoniq, 0, NULL)) < 0) {
+	if ((err = snd_ensoniq_midi(ensoniq, 0)) < 0) {
 		snd_card_free(card);
 		return err;
 	}
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c
index 0fc46eb..e1858d9 100644
--- a/sound/pci/es1938.c
+++ b/sound/pci/es1938.c
@@ -55,6 +55,7 @@
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/dma-mapping.h>
+#include <linux/io.h>
 #include <sound/core.h>
 #include <sound/control.h>
 #include <sound/pcm.h>
@@ -63,8 +64,6 @@
 #include <sound/initval.h>
 #include <sound/tlv.h>
 
-#include <asm/io.h>
-
 MODULE_AUTHOR("Jaromir Koutek <miri@punknet.cz>");
 MODULE_DESCRIPTION("ESS Solo-1");
 MODULE_LICENSE("GPL");
@@ -1454,7 +1453,6 @@
 
 static int es1938_suspend(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct es1938 *chip = card->private_data;
 	unsigned char *s, *d;
@@ -1471,9 +1469,6 @@
 		free_irq(chip->irq, chip);
 		chip->irq = -1;
 	}
-	pci_disable_device(pci);
-	pci_save_state(pci);
-	pci_set_power_state(pci, PCI_D3hot);
 	return 0;
 }
 
@@ -1484,14 +1479,6 @@
 	struct es1938 *chip = card->private_data;
 	unsigned char *s, *d;
 
-	pci_set_power_state(pci, PCI_D0);
-	pci_restore_state(pci);
-	if (pci_enable_device(pci) < 0) {
-		dev_err(dev, "pci_enable_device failed, disabling device\n");
-		snd_card_disconnect(card);
-		return -EIO;
-	}
-
 	if (request_irq(pci->irq, snd_es1938_interrupt,
 			IRQF_SHARED, KBUILD_MODNAME, chip)) {
 		dev_err(dev, "unable to grab IRQ %d, disabling device\n",
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
index 6039700..059f384 100644
--- a/sound/pci/es1968.c
+++ b/sound/pci/es1968.c
@@ -94,7 +94,7 @@
  *	places.
  */
 
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
@@ -2383,7 +2383,6 @@
  */
 static int es1968_suspend(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct es1968 *chip = card->private_data;
 
@@ -2396,16 +2395,11 @@
 	snd_pcm_suspend_all(chip->pcm);
 	snd_ac97_suspend(chip->ac97);
 	snd_es1968_bob_stop(chip);
-
-	pci_disable_device(pci);
-	pci_save_state(pci);
-	pci_set_power_state(pci, PCI_D3hot);
 	return 0;
 }
 
 static int es1968_resume(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct es1968 *chip = card->private_data;
 	struct esschan *es;
@@ -2413,16 +2407,6 @@
 	if (! chip->do_pm)
 		return 0;
 
-	/* restore all our config */
-	pci_set_power_state(pci, PCI_D0);
-	pci_restore_state(pci);
-	if (pci_enable_device(pci) < 0) {
-		dev_err(dev, "pci_enable_device failed, disabling device\n");
-		snd_card_disconnect(card);
-		return -EIO;
-	}
-	pci_set_master(pci);
-
 	snd_es1968_chip_init(chip);
 
 	/* need to restore the base pointers.. */ 
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c
index d167aff..1fdd92b6 100644
--- a/sound/pci/fm801.c
+++ b/sound/pci/fm801.c
@@ -2,8 +2,6 @@
  *  The driver for the ForteMedia FM801 based soundcards
  *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
  *
- *  Support FM only card by Andy Shevchenko <andy@smile.org.ua>
- *
  *   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
@@ -14,10 +12,6 @@
  *   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/delay.h>
@@ -704,13 +698,11 @@
 	.pointer =	snd_fm801_capture_pointer,
 };
 
-static int snd_fm801_pcm(struct fm801 *chip, int device, struct snd_pcm **rpcm)
+static int snd_fm801_pcm(struct fm801 *chip, int device)
 {
 	struct snd_pcm *pcm;
 	int err;
 
-	if (rpcm)
-		*rpcm = NULL;
 	if ((err = snd_pcm_new(chip->card, "FM801", device, 1, 1, &pcm)) < 0)
 		return err;
 
@@ -726,16 +718,10 @@
 					      snd_dma_pci_data(chip->pci),
 					      chip->multichannel ? 128*1024 : 64*1024, 128*1024);
 
-	err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+	return snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
 				     snd_pcm_alt_chmaps,
 				     chip->multichannel ? 6 : 2, 0,
 				     NULL);
-	if (err < 0)
-		return err;
-
-	if (rpcm)
-		*rpcm = pcm;
-	return 0;
 }
 
 /*
@@ -1186,12 +1172,6 @@
 		v4l2_device_unregister(&chip->v4l2_dev);
 	}
 #endif
-	if (chip->irq >= 0)
-		free_irq(chip->irq, chip);
-	pci_release_regions(chip->pci);
-	pci_disable_device(chip->pci);
-
-	kfree(chip);
 	return 0;
 }
 
@@ -1214,28 +1194,23 @@
 	};
 
 	*rchip = NULL;
-	if ((err = pci_enable_device(pci)) < 0)
+	if ((err = pcim_enable_device(pci)) < 0)
 		return err;
-	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-	if (chip == NULL) {
-		pci_disable_device(pci);
+	chip = devm_kzalloc(&pci->dev, sizeof(*chip), GFP_KERNEL);
+	if (chip == NULL)
 		return -ENOMEM;
-	}
 	spin_lock_init(&chip->reg_lock);
 	chip->card = card;
 	chip->pci = pci;
 	chip->irq = -1;
 	chip->tea575x_tuner = tea575x_tuner;
-	if ((err = pci_request_regions(pci, "FM801")) < 0) {
-		kfree(chip);
-		pci_disable_device(pci);
+	if ((err = pci_request_regions(pci, "FM801")) < 0)
 		return err;
-	}
 	chip->port = pci_resource_start(pci, 0);
 	if ((tea575x_tuner & TUNER_ONLY) == 0) {
-		if (request_irq(pci->irq, snd_fm801_interrupt, IRQF_SHARED,
-				KBUILD_MODNAME, chip)) {
-			dev_err(card->dev, "unable to grab IRQ %d\n", chip->irq);
+		if (devm_request_irq(&pci->dev, pci->irq, snd_fm801_interrupt,
+				IRQF_SHARED, KBUILD_MODNAME, chip)) {
+			dev_err(card->dev, "unable to grab IRQ %d\n", pci->irq);
 			snd_fm801_free(chip);
 			return -EBUSY;
 		}
@@ -1250,12 +1225,6 @@
 	/* init might set tuner access method */
 	tea575x_tuner = chip->tea575x_tuner;
 
-	if (chip->irq >= 0 && (tea575x_tuner & TUNER_ONLY)) {
-		pci_clear_master(pci);
-		free_irq(chip->irq, chip);
-		chip->irq = -1;
-	}
-
 	if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
 		snd_fm801_free(chip);
 		return err;
@@ -1340,7 +1309,7 @@
 	if (chip->tea575x_tuner & TUNER_ONLY)
 		goto __fm801_tuner_only;
 
-	if ((err = snd_fm801_pcm(chip, 0, NULL)) < 0) {
+	if ((err = snd_fm801_pcm(chip, 0)) < 0) {
 		snd_card_free(card);
 		return err;
 	}
@@ -1392,7 +1361,6 @@
 
 static int snd_fm801_suspend(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct fm801 *chip = card->private_data;
 	int i;
@@ -1404,29 +1372,15 @@
 	for (i = 0; i < ARRAY_SIZE(saved_regs); i++)
 		chip->saved_regs[i] = inw(chip->port + saved_regs[i]);
 	/* FIXME: tea575x suspend */
-
-	pci_disable_device(pci);
-	pci_save_state(pci);
-	pci_set_power_state(pci, PCI_D3hot);
 	return 0;
 }
 
 static int snd_fm801_resume(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct fm801 *chip = card->private_data;
 	int i;
 
-	pci_set_power_state(pci, PCI_D0);
-	pci_restore_state(pci);
-	if (pci_enable_device(pci) < 0) {
-		dev_err(dev, "pci_enable_device failed, disabling device\n");
-		snd_card_disconnect(card);
-		return -EIO;
-	}
-	pci_set_master(pci);
-
 	snd_fm801_chip_init(chip, 1);
 	snd_ac97_resume(chip->ac97);
 	snd_ac97_resume(chip->ac97_sec);
diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig
index ebf4c2fb..7f0f2c5 100644
--- a/sound/pci/hda/Kconfig
+++ b/sound/pci/hda/Kconfig
@@ -107,6 +107,7 @@
 config SND_HDA_CODEC_REALTEK
 	tristate "Build Realtek HD-audio codec support"
 	select SND_HDA_GENERIC
+	select INPUT
 	help
 	  Say Y or M here to include Realtek HD-audio codec support in
 	  snd-hda-intel driver, such as ALC880.
diff --git a/sound/pci/hda/hda_auto_parser.c b/sound/pci/hda/hda_auto_parser.c
index 1ede822..3f8706b 100644
--- a/sound/pci/hda/hda_auto_parser.c
+++ b/sound/pci/hda/hda_auto_parser.c
@@ -409,10 +409,10 @@
 	/*
 	 * debug prints of the parsed results
 	 */
-	codec_info(codec, "autoconfig: line_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x) type:%s\n",
-		   cfg->line_outs, cfg->line_out_pins[0], cfg->line_out_pins[1],
-		   cfg->line_out_pins[2], cfg->line_out_pins[3],
-		   cfg->line_out_pins[4],
+	codec_info(codec, "autoconfig for %s: line_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x) type:%s\n",
+		   codec->chip_name, cfg->line_outs, cfg->line_out_pins[0],
+		   cfg->line_out_pins[1], cfg->line_out_pins[2],
+		   cfg->line_out_pins[3], cfg->line_out_pins[4],
 		   cfg->line_out_type == AUTO_PIN_HP_OUT ? "hp" :
 		   (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT ?
 		    "speaker" : "line"));
@@ -920,6 +920,8 @@
 			codec->fixup_id = pq->value;
 #ifdef CONFIG_SND_DEBUG_VERBOSE
 			codec->fixup_name = pq->name;
+			codec_dbg(codec, "%s: picked fixup %s (pin match)\n",
+				  codec->chip_name, codec->fixup_name);
 #endif
 			codec->fixup_list = fixlist;
 			return;
@@ -960,6 +962,8 @@
 		codec->fixup_list = NULL;
 		codec->fixup_name = NULL;
 		codec->fixup_id = HDA_FIXUP_ID_NO_FIXUP;
+		codec_dbg(codec, "%s: picked no fixup (nofixup specified)\n",
+			  codec->chip_name);
 		return;
 	}
 
@@ -969,6 +973,8 @@
 				codec->fixup_id = models->id;
 				codec->fixup_name = models->name;
 				codec->fixup_list = fixlist;
+				codec_dbg(codec, "%s: picked fixup %s (model specified)\n",
+					  codec->chip_name, codec->fixup_name);
 				return;
 			}
 			models++;
@@ -980,6 +986,8 @@
 			id = q->value;
 #ifdef CONFIG_SND_DEBUG_VERBOSE
 			name = q->name;
+			codec_dbg(codec, "%s: picked fixup %s (PCI SSID%s)\n",
+				  codec->chip_name, name, q->subdevice_mask ? "" : " - vendor generic");
 #endif
 		}
 	}
@@ -992,6 +1000,8 @@
 				id = q->value;
 #ifdef CONFIG_SND_DEBUG_VERBOSE
 				name = q->name;
+				codec_dbg(codec, "%s: picked fixup %s (codec SSID)\n",
+					  codec->chip_name, name);
 #endif
 				break;
 			}
diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c
index 712ec5c..27dcb14 100644
--- a/sound/pci/hda/hda_controller.c
+++ b/sound/pci/hda/hda_controller.c
@@ -1994,4 +1994,4 @@
 EXPORT_SYMBOL_GPL(azx_notifier_unregister);
 
 MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Common HDA driver funcitons");
+MODULE_DESCRIPTION("Common HDA driver functions");
diff --git a/sound/pci/hda/hda_i915.c b/sound/pci/hda/hda_i915.c
index d4d0375..7148945 100644
--- a/sound/pci/hda/hda_i915.c
+++ b/sound/pci/hda/hda_i915.c
@@ -18,10 +18,12 @@
 
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/component.h>
+#include <drm/i915_component.h>
 #include <sound/core.h>
-#include <drm/i915_powerwell.h>
 #include "hda_priv.h"
-#include "hda_i915.h"
+#include "hda_intel.h"
 
 /* Intel HSW/BDW display HDA controller Extended Mode registers.
  * EM4 (M value) and EM5 (N Value) are used to convert CDClk (Core Display
@@ -31,32 +33,33 @@
 #define AZX_REG_EM4			0x100c
 #define AZX_REG_EM5			0x1010
 
-static int (*get_power)(void);
-static int (*put_power)(void);
-static int (*get_cdclk)(void);
-
-int hda_display_power(bool enable)
+int hda_display_power(struct hda_intel *hda, bool enable)
 {
-	if (!get_power || !put_power)
+	struct i915_audio_component *acomp = &hda->audio_component;
+
+	if (!acomp->ops)
 		return -ENODEV;
 
-	pr_debug("HDA display power %s \n",
-			enable ? "Enable" : "Disable");
+	dev_dbg(&hda->chip.pci->dev, "display power %s\n",
+		enable ? "enable" : "disable");
 	if (enable)
-		return get_power();
+		acomp->ops->get_power(acomp->dev);
 	else
-		return put_power();
+		acomp->ops->put_power(acomp->dev);
+
+	return 0;
 }
 
-void haswell_set_bclk(struct azx *chip)
+void haswell_set_bclk(struct hda_intel *hda)
 {
 	int cdclk_freq;
 	unsigned int bclk_m, bclk_n;
+	struct i915_audio_component *acomp = &hda->audio_component;
 
-	if (!get_cdclk)
+	if (!acomp->ops)
 		return;
 
-	cdclk_freq = get_cdclk();
+	cdclk_freq = acomp->ops->get_cdclk_freq(acomp->dev);
 	switch (cdclk_freq) {
 	case 337500:
 		bclk_m = 16;
@@ -80,51 +83,108 @@
 		break;
 	}
 
-	azx_writew(chip, EM4, bclk_m);
-	azx_writew(chip, EM5, bclk_n);
+	azx_writew(&hda->chip, EM4, bclk_m);
+	azx_writew(&hda->chip, EM5, bclk_n);
 }
 
-
-int hda_i915_init(void)
+static int hda_component_master_bind(struct device *dev)
 {
-	int err = 0;
+	struct snd_card *card = dev_get_drvdata(dev);
+	struct azx *chip = card->private_data;
+	struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
+	struct i915_audio_component *acomp = &hda->audio_component;
+	int ret;
 
-	get_power = symbol_request(i915_request_power_well);
-	if (!get_power) {
-		pr_warn("hda-i915: get_power symbol get fail\n");
-		return -ENODEV;
+	ret = component_bind_all(dev, acomp);
+	if (ret < 0)
+		return ret;
+
+	if (WARN_ON(!(acomp->dev && acomp->ops && acomp->ops->get_power &&
+		      acomp->ops->put_power && acomp->ops->get_cdclk_freq))) {
+		ret = -EINVAL;
+		goto out_unbind;
 	}
 
-	put_power = symbol_request(i915_release_power_well);
-	if (!put_power) {
-		symbol_put(i915_request_power_well);
-		get_power = NULL;
-		return -ENODEV;
+	/*
+	 * Atm, we don't support dynamic unbinding initiated by the child
+	 * component, so pin its containing module until we unbind.
+	 */
+	if (!try_module_get(acomp->ops->owner)) {
+		ret = -ENODEV;
+		goto out_unbind;
 	}
 
-	get_cdclk = symbol_request(i915_get_cdclk_freq);
-	if (!get_cdclk)	/* may have abnormal BCLK and audio playback rate */
-		pr_warn("hda-i915: get_cdclk symbol get fail\n");
+	return 0;
 
-	pr_debug("HDA driver get symbol successfully from i915 module\n");
+out_unbind:
+	component_unbind_all(dev, acomp);
 
-	return err;
+	return ret;
 }
 
-int hda_i915_exit(void)
+static void hda_component_master_unbind(struct device *dev)
 {
-	if (get_power) {
-		symbol_put(i915_request_power_well);
-		get_power = NULL;
+	struct snd_card *card = dev_get_drvdata(dev);
+	struct azx *chip = card->private_data;
+	struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
+	struct i915_audio_component *acomp = &hda->audio_component;
+
+	module_put(acomp->ops->owner);
+	component_unbind_all(dev, acomp);
+	WARN_ON(acomp->ops || acomp->dev);
+}
+
+static const struct component_master_ops hda_component_master_ops = {
+	.bind = hda_component_master_bind,
+	.unbind = hda_component_master_unbind,
+};
+
+static int hda_component_master_match(struct device *dev, void *data)
+{
+	/* i915 is the only supported component */
+	return !strcmp(dev->driver->name, "i915");
+}
+
+int hda_i915_init(struct hda_intel *hda)
+{
+	struct component_match *match = NULL;
+	struct device *dev = &hda->chip.pci->dev;
+	struct i915_audio_component *acomp = &hda->audio_component;
+	int ret;
+
+	component_match_add(dev, &match, hda_component_master_match, hda);
+	ret = component_master_add_with_match(dev, &hda_component_master_ops,
+					      match);
+	if (ret < 0)
+		goto out_err;
+
+	/*
+	 * Atm, we don't support deferring the component binding, so make sure
+	 * i915 is loaded and that the binding successfully completes.
+	 */
+	request_module("i915");
+
+	if (!acomp->ops) {
+		ret = -ENODEV;
+		goto out_master_del;
 	}
-	if (put_power) {
-		symbol_put(i915_release_power_well);
-		put_power = NULL;
-	}
-	if (get_cdclk) {
-		symbol_put(i915_get_cdclk_freq);
-		get_cdclk = NULL;
-	}
+
+	dev_dbg(dev, "bound to i915 component master\n");
+
+	return 0;
+out_master_del:
+	component_master_del(dev, &hda_component_master_ops);
+out_err:
+	dev_err(dev, "failed to add i915 component master (%d)\n", ret);
+
+	return ret;
+}
+
+int hda_i915_exit(struct hda_intel *hda)
+{
+	struct device *dev = &hda->chip.pci->dev;
+
+	component_master_del(dev, &hda_component_master_ops);
 
 	return 0;
 }
diff --git a/sound/pci/hda/hda_i915.h b/sound/pci/hda/hda_i915.h
deleted file mode 100644
index e6072c6..0000000
--- a/sound/pci/hda/hda_i915.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- *  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.
- */
-#ifndef __SOUND_HDA_I915_H
-#define __SOUND_HDA_I915_H
-
-#ifdef CONFIG_SND_HDA_I915
-int hda_display_power(bool enable);
-void haswell_set_bclk(struct azx *chip);
-int hda_i915_init(void);
-int hda_i915_exit(void);
-#else
-static inline int hda_display_power(bool enable) { return 0; }
-static inline void haswell_set_bclk(struct azx *chip) { return; }
-static inline int hda_i915_init(void)
-{
-	return -ENODEV;
-}
-static inline int hda_i915_exit(void)
-{
-	return 0;
-}
-#endif
-
-#endif
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index d426a0b..36d2f20 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -63,7 +63,7 @@
 #include "hda_codec.h"
 #include "hda_controller.h"
 #include "hda_priv.h"
-#include "hda_i915.h"
+#include "hda_intel.h"
 
 /* position fix mode */
 enum {
@@ -354,31 +354,6 @@
 	[AZX_DRIVER_GENERIC] = "HD-Audio Generic",
 };
 
-struct hda_intel {
-	struct azx chip;
-
-	/* for pending irqs */
-	struct work_struct irq_pending_work;
-
-	/* sync probing */
-	struct completion probe_wait;
-	struct work_struct probe_work;
-
-	/* card list (for power_save trigger) */
-	struct list_head list;
-
-	/* extra flags */
-	unsigned int irq_pending_warned:1;
-
-	/* VGA-switcheroo setup */
-	unsigned int use_vga_switcheroo:1;
-	unsigned int vga_switcheroo_registered:1;
-	unsigned int init_failed:1; /* delayed init failed */
-
-	/* secondary power domain for hdmi audio under vga device */
-	struct dev_pm_domain hdmi_pm_domain;
-};
-
 #ifdef CONFIG_X86
 static void __mark_pages_wc(struct azx *chip, struct snd_dma_buffer *dmab, bool on)
 {
@@ -795,7 +770,6 @@
  */
 static int azx_suspend(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct azx *chip;
 	struct hda_intel *hda;
@@ -824,11 +798,8 @@
 
 	if (chip->msi)
 		pci_disable_msi(chip->pci);
-	pci_disable_device(pci);
-	pci_save_state(pci);
-	pci_set_power_state(pci, PCI_D3hot);
 	if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
-		hda_display_power(false);
+		hda_display_power(hda, false);
 	return 0;
 }
 
@@ -848,18 +819,9 @@
 		return 0;
 
 	if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
-		hda_display_power(true);
-		haswell_set_bclk(chip);
+		hda_display_power(hda, true);
+		haswell_set_bclk(hda);
 	}
-	pci_set_power_state(pci, PCI_D0);
-	pci_restore_state(pci);
-	if (pci_enable_device(pci) < 0) {
-		dev_err(chip->card->dev,
-			"pci_enable_device failed, disabling device\n");
-		snd_card_disconnect(card);
-		return -EIO;
-	}
-	pci_set_master(pci);
 	if (chip->msi)
 		if (pci_enable_msi(pci) < 0)
 			chip->msi = 0;
@@ -901,7 +863,7 @@
 	azx_enter_link_reset(chip);
 	azx_clear_irq_pending(chip);
 	if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
-		hda_display_power(false);
+		hda_display_power(hda, false);
 
 	return 0;
 }
@@ -927,8 +889,8 @@
 		return 0;
 
 	if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
-		hda_display_power(true);
-		haswell_set_bclk(chip);
+		hda_display_power(hda, true);
+		haswell_set_bclk(hda);
 	}
 
 	/* Read STATESTS before controller reset */
@@ -1138,8 +1100,7 @@
 		free_irq(chip->irq, (void*)chip);
 	if (chip->msi)
 		pci_disable_msi(chip->pci);
-	if (chip->remap_addr)
-		iounmap(chip->remap_addr);
+	iounmap(chip->remap_addr);
 
 	azx_free_stream_pages(chip);
 	if (chip->region_requested)
@@ -1150,8 +1111,8 @@
 	release_firmware(chip->fw);
 #endif
 	if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
-		hda_display_power(false);
-		hda_i915_exit();
+		hda_display_power(hda, false);
+		hda_i915_exit(hda);
 	}
 	kfree(hda);
 
@@ -1629,8 +1590,12 @@
 	/* initialize chip */
 	azx_init_pci(chip);
 
-	if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
-		haswell_set_bclk(chip);
+	if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
+		struct hda_intel *hda;
+
+		hda = container_of(chip, struct hda_intel, chip);
+		haswell_set_bclk(hda);
+	}
 
 	azx_init_chip(chip, (probe_only[dev] & 2) == 0);
 
@@ -1910,13 +1875,10 @@
 	/* Request power well for Haswell HDA controller and codec */
 	if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
 #ifdef CONFIG_SND_HDA_I915
-		err = hda_i915_init();
-		if (err < 0) {
-			dev_err(chip->card->dev,
-				"Error request power-well from i915\n");
+		err = hda_i915_init(hda);
+		if (err < 0)
 			goto out_free;
-		}
-		err = hda_display_power(true);
+		err = hda_display_power(hda, true);
 		if (err < 0) {
 			dev_err(chip->card->dev,
 				"Cannot turn on display power on i915\n");
diff --git a/sound/pci/hda/hda_intel.h b/sound/pci/hda/hda_intel.h
new file mode 100644
index 0000000..3486118
--- /dev/null
+++ b/sound/pci/hda/hda_intel.h
@@ -0,0 +1,71 @@
+/*
+ *  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.
+ */
+#ifndef __SOUND_HDA_INTEL_H
+#define __SOUND_HDA_INTEL_H
+
+#include <drm/i915_component.h>
+#include "hda_priv.h"
+
+struct hda_intel {
+	struct azx chip;
+
+	/* for pending irqs */
+	struct work_struct irq_pending_work;
+
+	/* sync probing */
+	struct completion probe_wait;
+	struct work_struct probe_work;
+
+	/* card list (for power_save trigger) */
+	struct list_head list;
+
+	/* extra flags */
+	unsigned int irq_pending_warned:1;
+
+	/* VGA-switcheroo setup */
+	unsigned int use_vga_switcheroo:1;
+	unsigned int vga_switcheroo_registered:1;
+	unsigned int init_failed:1; /* delayed init failed */
+
+	/* secondary power domain for hdmi audio under vga device */
+	struct dev_pm_domain hdmi_pm_domain;
+
+	/* i915 component interface */
+	struct i915_audio_component audio_component;
+};
+
+#ifdef CONFIG_SND_HDA_I915
+int hda_display_power(struct hda_intel *hda, bool enable);
+void haswell_set_bclk(struct hda_intel *hda);
+int hda_i915_init(struct hda_intel *hda);
+int hda_i915_exit(struct hda_intel *hda);
+#else
+static inline int hda_display_power(struct hda_intel *hda, bool enable)
+{
+	return 0;
+}
+static inline void haswell_set_bclk(struct hda_intel *hda) { return; }
+static inline int hda_i915_init(struct hda_intel *hda)
+{
+	return -ENODEV;
+}
+static inline int hda_i915_exit(struct hda_intel *hda)
+{
+	return 0;
+}
+#endif
+
+#endif
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index a9d78e2..d285904 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -739,39 +739,6 @@
  *      E/F quad mic array
  */
 
-#ifdef ENABLE_AD_STATIC_QUIRKS
-static int ad198x_ch_mode_info(struct snd_kcontrol *kcontrol,
-			       struct snd_ctl_elem_info *uinfo)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct ad198x_spec *spec = codec->spec;
-	return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
-				    spec->num_channel_mode);
-}
-
-static int ad198x_ch_mode_get(struct snd_kcontrol *kcontrol,
-			      struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct ad198x_spec *spec = codec->spec;
-	return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
-				   spec->num_channel_mode, spec->multiout.max_channels);
-}
-
-static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
-			      struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct ad198x_spec *spec = codec->spec;
-	int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
-				      spec->num_channel_mode,
-				      &spec->multiout.max_channels);
-	if (err >= 0 && spec->need_dac_fix)
-		spec->multiout.num_dacs = spec->multiout.max_channels / 2;
-	return err;
-}
-#endif /* ENABLE_AD_STATIC_QUIRKS */
-
 static int ad1988_auto_smux_enum_info(struct snd_kcontrol *kcontrol,
 				      struct snd_ctl_elem_info *uinfo)
 {
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 65f1f4e..0403061 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -29,6 +29,7 @@
 #include <linux/pci.h>
 #include <linux/dmi.h>
 #include <linux/module.h>
+#include <linux/input.h>
 #include <sound/core.h>
 #include <sound/jack.h>
 #include "hda_codec.h"
@@ -120,6 +121,7 @@
 	hda_nid_t pll_nid;
 	unsigned int pll_coef_idx, pll_coef_bit;
 	unsigned int coef0;
+	struct input_dev *kb_dev;
 };
 
 /*
@@ -3472,6 +3474,79 @@
 	}
 }
 
+static void gpio2_mic_hotkey_event(struct hda_codec *codec,
+				   struct hda_jack_callback *event)
+{
+	struct alc_spec *spec = codec->spec;
+
+	/* GPIO2 just toggles on a keypress/keyrelease cycle. Therefore
+	   send both key on and key off event for every interrupt. */
+	input_report_key(spec->kb_dev, KEY_MICMUTE, 1);
+	input_sync(spec->kb_dev);
+	input_report_key(spec->kb_dev, KEY_MICMUTE, 0);
+	input_sync(spec->kb_dev);
+}
+
+static void alc280_fixup_hp_gpio2_mic_hotkey(struct hda_codec *codec,
+					     const struct hda_fixup *fix, int action)
+{
+	/* GPIO1 = set according to SKU external amp
+	   GPIO2 = mic mute hotkey
+	   GPIO3 = mute LED
+	   GPIO4 = mic mute LED */
+	static const struct hda_verb gpio_init[] = {
+		{ 0x01, AC_VERB_SET_GPIO_MASK, 0x1e },
+		{ 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x1a },
+		{ 0x01, AC_VERB_SET_GPIO_DATA, 0x02 },
+		{}
+	};
+
+	struct alc_spec *spec = codec->spec;
+
+	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
+		spec->kb_dev = input_allocate_device();
+		if (!spec->kb_dev) {
+			codec_err(codec, "Out of memory (input_allocate_device)\n");
+			return;
+		}
+		spec->kb_dev->name = "Microphone Mute Button";
+		spec->kb_dev->evbit[0] = BIT_MASK(EV_KEY);
+		spec->kb_dev->keybit[BIT_WORD(KEY_MICMUTE)] = BIT_MASK(KEY_MICMUTE);
+		if (input_register_device(spec->kb_dev)) {
+			codec_err(codec, "input_register_device failed\n");
+			input_free_device(spec->kb_dev);
+			spec->kb_dev = NULL;
+			return;
+		}
+
+		snd_hda_add_verbs(codec, gpio_init);
+		snd_hda_codec_write_cache(codec, codec->afg, 0,
+					  AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x04);
+		snd_hda_jack_detect_enable_callback(codec, codec->afg,
+						    gpio2_mic_hotkey_event);
+
+		spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook;
+		spec->gen.cap_sync_hook = alc_fixup_gpio_mic_mute_hook;
+		spec->gpio_led = 0;
+		spec->mute_led_polarity = 0;
+		spec->gpio_mute_led_mask = 0x08;
+		spec->gpio_mic_led_mask = 0x10;
+		return;
+	}
+
+	if (!spec->kb_dev)
+		return;
+
+	switch (action) {
+	case HDA_FIXUP_ACT_PROBE:
+		spec->init_amp = ALC_INIT_DEFAULT;
+		break;
+	case HDA_FIXUP_ACT_FREE:
+		input_unregister_device(spec->kb_dev);
+		spec->kb_dev = NULL;
+	}
+}
+
 static void alc269_fixup_hp_line1_mic1_led(struct hda_codec *codec,
 				const struct hda_fixup *fix, int action)
 {
@@ -4341,6 +4416,8 @@
 	ALC282_FIXUP_ASPIRE_V5_PINS,
 	ALC280_FIXUP_HP_GPIO4,
 	ALC286_FIXUP_HP_GPIO_LED,
+	ALC280_FIXUP_HP_GPIO2_MIC_HOTKEY,
+	ALC280_FIXUP_HP_DOCK_PINS,
 };
 
 static const struct hda_fixup alc269_fixups[] = {
@@ -4814,6 +4891,21 @@
 		.type = HDA_FIXUP_FUNC,
 		.v.func = alc286_fixup_hp_gpio_led,
 	},
+	[ALC280_FIXUP_HP_GPIO2_MIC_HOTKEY] = {
+		.type = HDA_FIXUP_FUNC,
+		.v.func = alc280_fixup_hp_gpio2_mic_hotkey,
+	},
+	[ALC280_FIXUP_HP_DOCK_PINS] = {
+		.type = HDA_FIXUP_PINS,
+		.v.pins = (const struct hda_pintbl[]) {
+			{ 0x1b, 0x21011020 }, /* line-out */
+			{ 0x1a, 0x01a1903c }, /* headset mic */
+			{ 0x18, 0x2181103f }, /* line-in */
+			{ },
+		},
+		.chained = true,
+		.chain_id = ALC280_FIXUP_HP_GPIO4
+	},
 };
 
 static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -4843,6 +4935,7 @@
 	SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
 	SND_PCI_QUIRK(0x103c, 0x18e6, "HP", ALC269_FIXUP_HP_GPIO_LED),
 	SND_PCI_QUIRK(0x103c, 0x218b, "HP", ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED),
+	SND_PCI_QUIRK(0x103c, 0x225f, "HP", ALC280_FIXUP_HP_GPIO2_MIC_HOTKEY),
 	/* ALC282 */
 	SND_PCI_QUIRK(0x103c, 0x2210, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x2214, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
@@ -4856,6 +4949,7 @@
 	SND_PCI_QUIRK(0x103c, 0x226b, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x226e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x2271, "HP", ALC286_FIXUP_HP_GPIO_LED),
+	SND_PCI_QUIRK(0x103c, 0x2272, "HP", ALC280_FIXUP_HP_DOCK_PINS),
 	SND_PCI_QUIRK(0x103c, 0x229e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x22b2, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x22b7, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
diff --git a/sound/pci/ice1712/ak4xxx.c b/sound/pci/ice1712/ak4xxx.c
index 3981823..179ef7a 100644
--- a/sound/pci/ice1712/ak4xxx.c
+++ b/sound/pci/ice1712/ak4xxx.c
@@ -21,7 +21,7 @@
  *
  */      
 
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/slab.h>
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c
index b039b46..f7b1523 100644
--- a/sound/pci/ice1712/ice1712.c
+++ b/sound/pci/ice1712/ice1712.c
@@ -880,13 +880,11 @@
 	.pointer =	snd_ice1712_capture_pointer,
 };
 
-static int snd_ice1712_pcm(struct snd_ice1712 *ice, int device, struct snd_pcm **rpcm)
+static int snd_ice1712_pcm(struct snd_ice1712 *ice, int device)
 {
 	struct snd_pcm *pcm;
 	int err;
 
-	if (rpcm)
-		*rpcm = NULL;
 	err = snd_pcm_new(ice->card, "ICE1712 consumer", device, 1, 1, &pcm);
 	if (err < 0)
 		return err;
@@ -902,22 +900,17 @@
 	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
 					      snd_dma_pci_data(ice->pci), 64*1024, 64*1024);
 
-	if (rpcm)
-		*rpcm = pcm;
-
 	dev_warn(ice->card->dev,
 		 "Consumer PCM code does not work well at the moment --jk\n");
 
 	return 0;
 }
 
-static int snd_ice1712_pcm_ds(struct snd_ice1712 *ice, int device, struct snd_pcm **rpcm)
+static int snd_ice1712_pcm_ds(struct snd_ice1712 *ice, int device)
 {
 	struct snd_pcm *pcm;
 	int err;
 
-	if (rpcm)
-		*rpcm = NULL;
 	err = snd_pcm_new(ice->card, "ICE1712 consumer (DS)", device, 6, 0, &pcm);
 	if (err < 0)
 		return err;
@@ -932,9 +925,6 @@
 	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
 					      snd_dma_pci_data(ice->pci), 64*1024, 128*1024);
 
-	if (rpcm)
-		*rpcm = pcm;
-
 	return 0;
 }
 
@@ -1260,13 +1250,11 @@
 	.pointer =	snd_ice1712_capture_pro_pointer,
 };
 
-static int snd_ice1712_pcm_profi(struct snd_ice1712 *ice, int device, struct snd_pcm **rpcm)
+static int snd_ice1712_pcm_profi(struct snd_ice1712 *ice, int device)
 {
 	struct snd_pcm *pcm;
 	int err;
 
-	if (rpcm)
-		*rpcm = NULL;
 	err = snd_pcm_new(ice->card, "ICE1712 multi", device, 1, 1, &pcm);
 	if (err < 0)
 		return err;
@@ -1282,8 +1270,6 @@
 					      snd_dma_pci_data(ice->pci), 256*1024, 256*1024);
 
 	ice->pcm_pro = pcm;
-	if (rpcm)
-		*rpcm = pcm;
 
 	if (ice->cs8427) {
 		/* assign channels to iec958 */
@@ -2691,14 +2677,14 @@
 	c = &no_matched;
  __found:
 
-	err = snd_ice1712_pcm_profi(ice, pcm_dev++, NULL);
+	err = snd_ice1712_pcm_profi(ice, pcm_dev++);
 	if (err < 0) {
 		snd_card_free(card);
 		return err;
 	}
 
 	if (ice_has_con_ac97(ice)) {
-		err = snd_ice1712_pcm(ice, pcm_dev++, NULL);
+		err = snd_ice1712_pcm(ice, pcm_dev++);
 		if (err < 0) {
 			snd_card_free(card);
 			return err;
@@ -2726,7 +2712,7 @@
 	}
 
 	if (ice_has_con_ac97(ice)) {
-		err = snd_ice1712_pcm_ds(ice, pcm_dev++, NULL);
+		err = snd_ice1712_pcm_ds(ice, pcm_dev++);
 		if (err < 0) {
 			snd_card_free(card);
 			return err;
@@ -2798,7 +2784,6 @@
 #ifdef CONFIG_PM_SLEEP
 static int snd_ice1712_suspend(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct snd_ice1712 *ice = card->private_data;
 
@@ -2820,16 +2805,11 @@
 
 	if (ice->pm_suspend)
 		ice->pm_suspend(ice);
-
-	pci_disable_device(pci);
-	pci_save_state(pci);
-	pci_set_power_state(pci, PCI_D3hot);
 	return 0;
 }
 
 static int snd_ice1712_resume(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct snd_ice1712 *ice = card->private_data;
 	int rate;
@@ -2837,16 +2817,6 @@
 	if (!ice->pm_suspend_enabled)
 		return 0;
 
-	pci_set_power_state(pci, PCI_D0);
-	pci_restore_state(pci);
-
-	if (pci_enable_device(pci) < 0) {
-		snd_card_disconnect(card);
-		return -EIO;
-	}
-
-	pci_set_master(pci);
-
 	if (ice->cur_rate)
 		rate = ice->cur_rate;
 	else
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
index d73da15..0b22c00 100644
--- a/sound/pci/ice1712/ice1724.c
+++ b/sound/pci/ice1712/ice1724.c
@@ -2798,7 +2798,6 @@
 #ifdef CONFIG_PM_SLEEP
 static int snd_vt1724_suspend(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct snd_ice1712 *ice = card->private_data;
 
@@ -2821,32 +2820,17 @@
 
 	if (ice->pm_suspend)
 		ice->pm_suspend(ice);
-
-	pci_disable_device(pci);
-	pci_save_state(pci);
-	pci_set_power_state(pci, PCI_D3hot);
 	return 0;
 }
 
 static int snd_vt1724_resume(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct snd_ice1712 *ice = card->private_data;
 
 	if (!ice->pm_suspend_enabled)
 		return 0;
 
-	pci_set_power_state(pci, PCI_D0);
-	pci_restore_state(pci);
-
-	if (pci_enable_device(pci) < 0) {
-		snd_card_disconnect(card);
-		return -EIO;
-	}
-
-	pci_set_master(pci);
-
 	snd_vt1724_chip_reset(ice);
 
 	if (snd_vt1724_chip_init(ice) < 0) {
diff --git a/sound/pci/ice1712/juli.c b/sound/pci/ice1712/juli.c
index a1536c1..4f02134 100644
--- a/sound/pci/ice1712/juli.c
+++ b/sound/pci/ice1712/juli.c
@@ -491,15 +491,17 @@
 	/* akm4358 un-reset, un-mute */
 	snd_akm4xxx_reset(ak, 0);
 	/* reinit ak4114 */
-	snd_ak4114_reinit(spec->ak4114);
+	snd_ak4114_resume(spec->ak4114);
 	return 0;
 }
 
 static int juli_suspend(struct snd_ice1712 *ice)
 {
 	struct snd_akm4xxx *ak = ice->akm;
+	struct juli_spec *spec = ice->spec;
 	/* akm4358 reset and soft-mute */
 	snd_akm4xxx_reset(ak, 1);
+	snd_ak4114_suspend(spec->ak4114);
 	return 0;
 }
 #endif
diff --git a/sound/pci/ice1712/wm8766.c b/sound/pci/ice1712/wm8766.c
index 21b373b..f7ac8d5 100644
--- a/sound/pci/ice1712/wm8766.c
+++ b/sound/pci/ice1712/wm8766.c
@@ -183,22 +183,6 @@
 	snd_wm8766_write(wm, WM8766_REG_IFCTRL, val | dac);
 }
 
-void snd_wm8766_set_master_mode(struct snd_wm8766 *wm, u16 mode)
-{
-	u16 val = wm->regs[WM8766_REG_DACCTRL3] & ~WM8766_DAC3_MSTR_MASK;
-
-	mode &= WM8766_DAC3_MSTR_MASK;
-	snd_wm8766_write(wm, WM8766_REG_DACCTRL3, val | mode);
-}
-
-void snd_wm8766_set_power(struct snd_wm8766 *wm, u16 power)
-{
-	u16 val = wm->regs[WM8766_REG_DACCTRL3] & ~WM8766_DAC3_POWER_MASK;
-
-	power &= WM8766_DAC3_POWER_MASK;
-	snd_wm8766_write(wm, WM8766_REG_DACCTRL3, val | power);
-}
-
 void snd_wm8766_volume_restore(struct snd_wm8766 *wm)
 {
 	u16 val = wm->regs[WM8766_REG_DACR1];
diff --git a/sound/pci/ice1712/wm8766.h b/sound/pci/ice1712/wm8766.h
index c119f84..18c8d9d 100644
--- a/sound/pci/ice1712/wm8766.h
+++ b/sound/pci/ice1712/wm8766.h
@@ -155,8 +155,6 @@
 void snd_wm8766_init(struct snd_wm8766 *wm);
 void snd_wm8766_resume(struct snd_wm8766 *wm);
 void snd_wm8766_set_if(struct snd_wm8766 *wm, u16 dac);
-void snd_wm8766_set_master_mode(struct snd_wm8766 *wm, u16 mode);
-void snd_wm8766_set_power(struct snd_wm8766 *wm, u16 power);
 void snd_wm8766_volume_restore(struct snd_wm8766 *wm);
 int snd_wm8766_build_controls(struct snd_wm8766 *wm);
 
diff --git a/sound/pci/ice1712/wm8776.c b/sound/pci/ice1712/wm8776.c
index e66c0da..ebd2fe4 100644
--- a/sound/pci/ice1712/wm8776.c
+++ b/sound/pci/ice1712/wm8776.c
@@ -452,21 +452,6 @@
 		snd_wm8776_write(wm, i, wm->regs[i]);
 }
 
-void snd_wm8776_set_dac_if(struct snd_wm8776 *wm, u16 dac)
-{
-	snd_wm8776_write(wm, WM8776_REG_DACIFCTRL, dac);
-}
-
-void snd_wm8776_set_adc_if(struct snd_wm8776 *wm, u16 adc)
-{
-	snd_wm8776_write(wm, WM8776_REG_ADCIFCTRL, adc);
-}
-
-void snd_wm8776_set_master_mode(struct snd_wm8776 *wm, u16 mode)
-{
-	snd_wm8776_write(wm, WM8776_REG_MSTRCTRL, mode);
-}
-
 void snd_wm8776_set_power(struct snd_wm8776 *wm, u16 power)
 {
 	snd_wm8776_write(wm, WM8776_REG_PWRDOWN, power);
diff --git a/sound/pci/ice1712/wm8776.h b/sound/pci/ice1712/wm8776.h
index 93a2d69..42acef0 100644
--- a/sound/pci/ice1712/wm8776.h
+++ b/sound/pci/ice1712/wm8776.h
@@ -216,9 +216,6 @@
 
 void snd_wm8776_init(struct snd_wm8776 *wm);
 void snd_wm8776_resume(struct snd_wm8776 *wm);
-void snd_wm8776_set_dac_if(struct snd_wm8776 *wm, u16 dac);
-void snd_wm8776_set_adc_if(struct snd_wm8776 *wm, u16 adc);
-void snd_wm8776_set_master_mode(struct snd_wm8776 *wm, u16 mode);
 void snd_wm8776_set_power(struct snd_wm8776 *wm, u16 power);
 void snd_wm8776_volume_restore(struct snd_wm8776 *wm);
 int snd_wm8776_build_controls(struct snd_wm8776 *wm);
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index 4a28252..2c5484e 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -26,7 +26,7 @@
  *
  */      
 
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
@@ -2654,7 +2654,6 @@
  */
 static int intel8x0_suspend(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct intel8x0 *chip = card->private_data;
 	int i;
@@ -2682,12 +2681,6 @@
 		free_irq(chip->irq, chip);
 		chip->irq = -1;
 	}
-	pci_disable_device(pci);
-	pci_save_state(pci);
-	/* The call below may disable built-in speaker on some laptops
-	 * after S2RAM.  So, don't touch it.
-	 */
-	/* pci_set_power_state(pci, PCI_D3hot); */
 	return 0;
 }
 
@@ -2698,14 +2691,6 @@
 	struct intel8x0 *chip = card->private_data;
 	int i;
 
-	pci_set_power_state(pci, PCI_D0);
-	pci_restore_state(pci);
-	if (pci_enable_device(pci) < 0) {
-		dev_err(dev, "pci_enable_device failed, disabling device\n");
-		snd_card_disconnect(card);
-		return -EIO;
-	}
-	pci_set_master(pci);
 	snd_intel8x0_chip_init(chip, 0);
 	if (request_irq(pci->irq, snd_intel8x0_interrupt,
 			IRQF_SHARED, KBUILD_MODNAME, chip)) {
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c
index 6b40235..7577f31 100644
--- a/sound/pci/intel8x0m.c
+++ b/sound/pci/intel8x0m.c
@@ -23,7 +23,7 @@
  *
  */      
 
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
@@ -1023,7 +1023,6 @@
  */
 static int intel8x0m_suspend(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct intel8x0m *chip = card->private_data;
 	int i;
@@ -1036,9 +1035,6 @@
 		free_irq(chip->irq, chip);
 		chip->irq = -1;
 	}
-	pci_disable_device(pci);
-	pci_save_state(pci);
-	pci_set_power_state(pci, PCI_D3hot);
 	return 0;
 }
 
@@ -1048,14 +1044,6 @@
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct intel8x0m *chip = card->private_data;
 
-	pci_set_power_state(pci, PCI_D0);
-	pci_restore_state(pci);
-	if (pci_enable_device(pci) < 0) {
-		dev_err(dev, "pci_enable_device failed, disabling device\n");
-		snd_card_disconnect(card);
-		return -EIO;
-	}
-	pci_set_master(pci);
 	if (request_irq(pci->irq, snd_intel8x0m_interrupt,
 			IRQF_SHARED, KBUILD_MODNAME, chip)) {
 		dev_err(dev, "unable to grab IRQ %d, disabling device\n",
diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c
index 59d21c9..7acbc21 100644
--- a/sound/pci/korg1212/korg1212.c
+++ b/sound/pci/korg1212/korg1212.c
@@ -28,6 +28,7 @@
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/firmware.h>
+#include <linux/io.h>
 
 #include <sound/core.h>
 #include <sound/info.h>
@@ -36,8 +37,6 @@
 #include <sound/pcm_params.h>
 #include <sound/initval.h>
 
-#include <asm/io.h>
-
 // ----------------------------------------------------------------------------
 // Debug Stuff
 // ----------------------------------------------------------------------------
@@ -585,8 +584,7 @@
 		korg1212->sharedBufferPtr->cardCommand = 0xffffffff;
 		/* program the timer */
 		korg1212->stop_pending_cnt = HZ;
-		korg1212->timer.expires = jiffies + 1;
-		add_timer(&korg1212->timer);
+		mod_timer(&korg1212->timer, jiffies + 1);
 	}
 }
 
@@ -617,8 +615,7 @@
 	} else {
 		if (--korg1212->stop_pending_cnt > 0) {
 			/* reprogram timer */
-			korg1212->timer.expires = jiffies + 1;
-			add_timer(&korg1212->timer);
+			mod_timer(&korg1212->timer, jiffies + 1);
 		} else {
 			snd_printd("korg1212_timer_func timeout\n");
 			korg1212->sharedBufferPtr->cardCommand = 0;
@@ -2172,9 +2169,8 @@
         init_waitqueue_head(&korg1212->wait);
         spin_lock_init(&korg1212->lock);
 	mutex_init(&korg1212->open_mutex);
-	init_timer(&korg1212->timer);
-	korg1212->timer.function = snd_korg1212_timer_func;
-	korg1212->timer.data = (unsigned long)korg1212;
+	setup_timer(&korg1212->timer, snd_korg1212_timer_func,
+		    (unsigned long)korg1212);
 
         korg1212->irq = -1;
         korg1212->clkSource = K1212_CLKIDX_Local;
diff --git a/sound/pci/lola/lola.c b/sound/pci/lola/lola.c
index 4cf4be5..9ff60008 100644
--- a/sound/pci/lola/lola.c
+++ b/sound/pci/lola/lola.c
@@ -551,10 +551,8 @@
 	lola_free_mixer(chip);
 	if (chip->irq >= 0)
 		free_irq(chip->irq, (void *)chip);
-	if (chip->bar[0].remap_addr)
-		iounmap(chip->bar[0].remap_addr);
-	if (chip->bar[1].remap_addr)
-		iounmap(chip->bar[1].remap_addr);
+	iounmap(chip->bar[0].remap_addr);
+	iounmap(chip->bar[1].remap_addr);
 	if (chip->rb.area)
 		snd_dma_free_pages(&chip->rb);
 	pci_release_regions(chip->pci);
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c
index 98823d1..9be6609 100644
--- a/sound/pci/maestro3.c
+++ b/sound/pci/maestro3.c
@@ -31,7 +31,7 @@
 #define CARD_NAME "ESS Maestro3/Allegro/Canyon3D-2"
 #define DRIVER_NAME "Maestro3"
 
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
@@ -2395,7 +2395,6 @@
 #ifdef CONFIG_PM_SLEEP
 static int m3_suspend(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct snd_m3 *chip = card->private_data;
 	int i, dsp_index;
@@ -2421,16 +2420,11 @@
 	for (i = REV_B_DATA_MEMORY_BEGIN ; i <= REV_B_DATA_MEMORY_END; i++)
 		chip->suspend_mem[dsp_index++] =
 			snd_m3_assp_read(chip, MEMTYPE_INTERNAL_DATA, i);
-
-	pci_disable_device(pci);
-	pci_save_state(pci);
-	pci_set_power_state(pci, PCI_D3hot);
 	return 0;
 }
 
 static int m3_resume(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct snd_m3 *chip = card->private_data;
 	int i, dsp_index;
@@ -2438,15 +2432,6 @@
 	if (chip->suspend_mem == NULL)
 		return 0;
 
-	pci_set_power_state(pci, PCI_D0);
-	pci_restore_state(pci);
-	if (pci_enable_device(pci) < 0) {
-		dev_err(dev, "pci_enable_device failed, disabling device\n");
-		snd_card_disconnect(card);
-		return -EIO;
-	}
-	pci_set_master(pci);
-
 	/* first lets just bring everything back. .*/
 	snd_m3_outw(chip, 0, 0x54);
 	snd_m3_outw(chip, 0, 0x56);
diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c
index 1faf47e..c3a9f39 100644
--- a/sound/pci/mixart/mixart.c
+++ b/sound/pci/mixart/mixart.c
@@ -1114,10 +1114,9 @@
 	}
 
 	/* release the i/o ports */
-	for (i = 0; i < 2; i++) {
-		if (mgr->mem[i].virt)
-			iounmap(mgr->mem[i].virt);
-	}
+	for (i = 0; i < 2; ++i)
+		iounmap(mgr->mem[i].virt);
+
 	pci_release_regions(mgr->pci);
 
 	/* free flowarray */
diff --git a/sound/pci/mixart/mixart_core.c b/sound/pci/mixart/mixart_core.c
index fe80313..dccf3db 100644
--- a/sound/pci/mixart/mixart_core.c
+++ b/sound/pci/mixart/mixart_core.c
@@ -23,8 +23,8 @@
 #include <linux/interrupt.h>
 #include <linux/mutex.h>
 #include <linux/pci.h>
+#include <linux/io.h>
 
-#include <asm/io.h>
 #include <sound/core.h>
 #include "mixart.h"
 #include "mixart_hwdep.h"
diff --git a/sound/pci/mixart/mixart_hwdep.c b/sound/pci/mixart/mixart_hwdep.c
index 9996a4d..5bfd3ac 100644
--- a/sound/pci/mixart/mixart_hwdep.c
+++ b/sound/pci/mixart/mixart_hwdep.c
@@ -26,7 +26,7 @@
 #include <linux/vmalloc.h>
 #include <linux/slab.h>
 #include <linux/module.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <sound/core.h>
 #include "mixart.h"
 #include "mixart_mixer.h"
diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c
index 4e41a4e..4735e27 100644
--- a/sound/pci/nm256/nm256.c
+++ b/sound/pci/nm256/nm256.c
@@ -24,7 +24,7 @@
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
   
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
@@ -1392,7 +1392,6 @@
  */
 static int nm256_suspend(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct nm256 *chip = card->private_data;
 
@@ -1400,15 +1399,11 @@
 	snd_pcm_suspend_all(chip->pcm);
 	snd_ac97_suspend(chip->ac97);
 	chip->coeffs_current = 0;
-	pci_disable_device(pci);
-	pci_save_state(pci);
-	pci_set_power_state(pci, PCI_D3hot);
 	return 0;
 }
 
 static int nm256_resume(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct nm256 *chip = card->private_data;
 	int i;
@@ -1416,15 +1411,6 @@
 	/* Perform a full reset on the hardware */
 	chip->in_resume = 1;
 
-	pci_set_power_state(pci, PCI_D0);
-	pci_restore_state(pci);
-	if (pci_enable_device(pci) < 0) {
-		dev_err(dev, "pci_enable_device failed, disabling device\n");
-		snd_card_disconnect(card);
-		return -EIO;
-	}
-	pci_set_master(pci);
-
 	snd_nm256_init_chip(chip);
 
 	/* restore ac97 */
@@ -1460,10 +1446,8 @@
 	if (chip->irq >= 0)
 		free_irq(chip->irq, chip);
 
-	if (chip->cport)
-		iounmap(chip->cport);
-	if (chip->buffer)
-		iounmap(chip->buffer);
+	iounmap(chip->cport);
+	iounmap(chip->buffer);
 	release_and_free_resource(chip->res_cport);
 	release_and_free_resource(chip->res_buffer);
 
diff --git a/sound/pci/oxygen/Makefile b/sound/pci/oxygen/Makefile
index 8f4c409..ab085d7 100644
--- a/sound/pci/oxygen/Makefile
+++ b/sound/pci/oxygen/Makefile
@@ -1,8 +1,10 @@
 snd-oxygen-lib-objs := oxygen_io.o oxygen_lib.o oxygen_mixer.o oxygen_pcm.o
 snd-oxygen-objs := oxygen.o xonar_dg_mixer.o xonar_dg.o
+snd-se6x-objs := se6x.o
 snd-virtuoso-objs := virtuoso.o xonar_lib.o \
 	xonar_pcm179x.o xonar_cs43xx.o xonar_wm87x6.o xonar_hdmi.o
 
 obj-$(CONFIG_SND_OXYGEN_LIB) += snd-oxygen-lib.o
 obj-$(CONFIG_SND_OXYGEN) += snd-oxygen.o
+obj-$(CONFIG_SND_SE6X) += snd-se6x.o
 obj-$(CONFIG_SND_VIRTUOSO) += snd-virtuoso.o
diff --git a/sound/pci/oxygen/oxygen.h b/sound/pci/oxygen/oxygen.h
index c10ab07..293d0b9 100644
--- a/sound/pci/oxygen/oxygen.h
+++ b/sound/pci/oxygen/oxygen.h
@@ -35,7 +35,7 @@
 #define CAPTURE_1_FROM_SPDIF	0x0080
 #define CAPTURE_2_FROM_I2S_2	0x0100
 #define CAPTURE_2_FROM_AC97_1	0x0200
-     /* CAPTURE_3_FROM_I2S_3		not implemented */
+#define CAPTURE_3_FROM_I2S_3	0x0400
 #define MIDI_OUTPUT		0x0800
 #define MIDI_INPUT		0x1000
 #define AC97_CD_INPUT		0x2000
diff --git a/sound/pci/oxygen/oxygen_io.c b/sound/pci/oxygen/oxygen_io.c
index 4b8a32c..c7851da 100644
--- a/sound/pci/oxygen/oxygen_io.c
+++ b/sound/pci/oxygen/oxygen_io.c
@@ -20,9 +20,9 @@
 #include <linux/delay.h>
 #include <linux/sched.h>
 #include <linux/export.h>
+#include <linux/io.h>
 #include <sound/core.h>
 #include <sound/mpu401.h>
-#include <asm/io.h>
 #include "oxygen.h"
 
 u8 oxygen_read8(struct oxygen *chip, unsigned int reg)
diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c
index b67e306..ffff3b2 100644
--- a/sound/pci/oxygen/oxygen_lib.c
+++ b/sound/pci/oxygen/oxygen_lib.c
@@ -319,11 +319,12 @@
 
 static void configure_pcie_bridge(struct pci_dev *pci)
 {
-	enum { PEX811X, PI7C9X110 };
+	enum { PEX811X, PI7C9X110, XIO2001 };
 	static const struct pci_device_id bridge_ids[] = {
 		{ PCI_VDEVICE(PLX, 0x8111), .driver_data = PEX811X },
 		{ PCI_VDEVICE(PLX, 0x8112), .driver_data = PEX811X },
 		{ PCI_DEVICE(0x12d8, 0xe110), .driver_data = PI7C9X110 },
+		{ PCI_VDEVICE(TI, 0x8240), .driver_data = XIO2001 },
 		{ }
 	};
 	struct pci_dev *bridge;
@@ -357,6 +358,14 @@
 		tmp |= 1;	/* park the PCI arbiter to the sound chip */
 		pci_write_config_dword(bridge, 0x40, tmp);
 		break;
+
+	case XIO2001: /* Texas Instruments XIO2001 PCIe/PCI bridge */
+		pci_read_config_dword(bridge, 0xe8, &tmp);
+		tmp &= ~0xf;	/* request length limit: 64 bytes */
+		tmp &= ~(0xf << 8);
+		tmp |= 1 << 8;	/* request count limit: one buffer */
+		pci_write_config_dword(bridge, 0xe8, tmp);
+		break;
 	}
 }
 
@@ -441,9 +450,18 @@
 		oxygen_write16(chip, OXYGEN_I2S_B_FORMAT,
 			       OXYGEN_I2S_MASTER |
 			       OXYGEN_I2S_MUTE_MCLK);
-	oxygen_write16(chip, OXYGEN_I2S_C_FORMAT,
-		       OXYGEN_I2S_MASTER |
-		       OXYGEN_I2S_MUTE_MCLK);
+	if (chip->model.device_config & CAPTURE_3_FROM_I2S_3)
+		oxygen_write16(chip, OXYGEN_I2S_C_FORMAT,
+			       OXYGEN_RATE_48000 |
+			       chip->model.adc_i2s_format |
+			       OXYGEN_I2S_MCLK(chip->model.adc_mclks) |
+			       OXYGEN_I2S_BITS_16 |
+			       OXYGEN_I2S_MASTER |
+			       OXYGEN_I2S_BCLK_64);
+	else
+		oxygen_write16(chip, OXYGEN_I2S_C_FORMAT,
+			       OXYGEN_I2S_MASTER |
+			       OXYGEN_I2S_MUTE_MCLK);
 	oxygen_clear_bits32(chip, OXYGEN_SPDIF_CONTROL,
 			    OXYGEN_SPDIF_OUT_ENABLE |
 			    OXYGEN_SPDIF_LOOPBACK);
@@ -728,7 +746,6 @@
 #ifdef CONFIG_PM_SLEEP
 static int oxygen_pci_suspend(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct oxygen *chip = card->private_data;
 	unsigned int i, saved_interrupt_mask;
@@ -736,8 +753,7 @@
 	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
 
 	for (i = 0; i < PCM_COUNT; ++i)
-		if (chip->streams[i])
-			snd_pcm_suspend(chip->streams[i]);
+		snd_pcm_suspend(chip->streams[i]);
 
 	if (chip->model.suspend)
 		chip->model.suspend(chip);
@@ -753,10 +769,6 @@
 	flush_work(&chip->spdif_input_bits_work);
 	flush_work(&chip->gpio_work);
 	chip->interrupt_mask = saved_interrupt_mask;
-
-	pci_disable_device(pci);
-	pci_save_state(pci);
-	pci_set_power_state(pci, PCI_D3hot);
 	return 0;
 }
 
@@ -788,20 +800,10 @@
 
 static int oxygen_pci_resume(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct oxygen *chip = card->private_data;
 	unsigned int i;
 
-	pci_set_power_state(pci, PCI_D0);
-	pci_restore_state(pci);
-	if (pci_enable_device(pci) < 0) {
-		dev_err(dev, "cannot reenable device");
-		snd_card_disconnect(card);
-		return -EIO;
-	}
-	pci_set_master(pci);
-
 	oxygen_write16(chip, OXYGEN_DMA_STATUS, 0);
 	oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, 0);
 	for (i = 0; i < OXYGEN_IO_SIZE; ++i)
diff --git a/sound/pci/oxygen/oxygen_mixer.c b/sound/pci/oxygen/oxygen_mixer.c
index 5988e04..6492bca 100644
--- a/sound/pci/oxygen/oxygen_mixer.c
+++ b/sound/pci/oxygen/oxygen_mixer.c
@@ -786,6 +786,9 @@
 		.get = upmix_get,
 		.put = upmix_put,
 	},
+};
+
+static const struct snd_kcontrol_new spdif_output_controls[] = {
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, SWITCH),
@@ -938,6 +941,33 @@
 		},
 	},
 	{
+		.pcm_dev = CAPTURE_3_FROM_I2S_3,
+		.controls = {
+			{
+				.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+				.name = "Analog Input Monitor Playback Switch",
+				.index = 2,
+				.info = snd_ctl_boolean_mono_info,
+				.get = monitor_get,
+				.put = monitor_put,
+				.private_value = OXYGEN_ADC_MONITOR_C,
+			},
+			{
+				.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+				.name = "Analog Input Monitor Playback Volume",
+				.index = 2,
+				.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+					  SNDRV_CTL_ELEM_ACCESS_TLV_READ,
+				.info = monitor_volume_info,
+				.get = monitor_get,
+				.put = monitor_put,
+				.private_value = OXYGEN_ADC_MONITOR_C_HALF_VOL
+						| (1 << 8),
+				.tlv = { .p = monitor_db_scale, },
+			},
+		},
+	},
+	{
 		.pcm_dev = CAPTURE_1_FROM_SPDIF,
 		.controls = {
 			{
@@ -1073,6 +1103,12 @@
 	err = add_controls(chip, controls, ARRAY_SIZE(controls));
 	if (err < 0)
 		return err;
+	if (chip->model.device_config & PLAYBACK_1_TO_SPDIF) {
+		err = add_controls(chip, spdif_output_controls,
+				   ARRAY_SIZE(spdif_output_controls));
+		if (err < 0)
+			return err;
+	}
 	if (chip->model.device_config & CAPTURE_1_FROM_SPDIF) {
 		err = add_controls(chip, spdif_input_controls,
 				   ARRAY_SIZE(spdif_input_controls));
diff --git a/sound/pci/oxygen/oxygen_pcm.c b/sound/pci/oxygen/oxygen_pcm.c
index 0282824..aa2ebd1 100644
--- a/sound/pci/oxygen/oxygen_pcm.c
+++ b/sound/pci/oxygen/oxygen_pcm.c
@@ -144,9 +144,11 @@
 		runtime->hw = *oxygen_hardware[channel];
 	switch (channel) {
 	case PCM_C:
-		runtime->hw.rates &= ~(SNDRV_PCM_RATE_32000 |
-				       SNDRV_PCM_RATE_64000);
-		runtime->hw.rate_min = 44100;
+		if (chip->model.device_config & CAPTURE_1_FROM_SPDIF) {
+			runtime->hw.rates &= ~(SNDRV_PCM_RATE_32000 |
+					       SNDRV_PCM_RATE_64000);
+			runtime->hw.rate_min = 44100;
+		}
 		/* fall through */
 	case PCM_A:
 	case PCM_B:
@@ -430,17 +432,36 @@
 				  struct snd_pcm_hw_params *hw_params)
 {
 	struct oxygen *chip = snd_pcm_substream_chip(substream);
+	bool is_spdif;
 	int err;
 
 	err = oxygen_hw_params(substream, hw_params);
 	if (err < 0)
 		return err;
 
+	is_spdif = chip->model.device_config & CAPTURE_1_FROM_SPDIF;
+
 	spin_lock_irq(&chip->reg_lock);
 	oxygen_write8_masked(chip, OXYGEN_REC_FORMAT,
 			     oxygen_format(hw_params) << OXYGEN_REC_FORMAT_C_SHIFT,
 			     OXYGEN_REC_FORMAT_C_MASK);
+	if (!is_spdif)
+		oxygen_write16_masked(chip, OXYGEN_I2S_C_FORMAT,
+				      oxygen_rate(hw_params) |
+				      chip->model.adc_i2s_format |
+				      get_mclk(chip, PCM_B, hw_params) |
+				      oxygen_i2s_bits(hw_params),
+				      OXYGEN_I2S_RATE_MASK |
+				      OXYGEN_I2S_FORMAT_MASK |
+				      OXYGEN_I2S_MCLK_MASK |
+				      OXYGEN_I2S_BITS_MASK);
 	spin_unlock_irq(&chip->reg_lock);
+
+	if (!is_spdif) {
+		mutex_lock(&chip->mutex);
+		chip->model.set_adc_params(chip, hw_params);
+		mutex_unlock(&chip->mutex);
+	}
 	return 0;
 }
 
@@ -676,11 +697,6 @@
 	.pointer   = oxygen_pointer,
 };
 
-static void oxygen_pcm_free(struct snd_pcm *pcm)
-{
-	snd_pcm_lib_preallocate_free_for_all(pcm);
-}
-
 int oxygen_pcm_init(struct oxygen *chip)
 {
 	struct snd_pcm *pcm;
@@ -705,7 +721,6 @@
 			snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
 					&oxygen_rec_b_ops);
 		pcm->private_data = chip;
-		pcm->private_free = oxygen_pcm_free;
 		strcpy(pcm->name, "Multichannel");
 		if (outs)
 			snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream,
@@ -734,7 +749,6 @@
 			snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
 					&oxygen_rec_c_ops);
 		pcm->private_data = chip;
-		pcm->private_free = oxygen_pcm_free;
 		strcpy(pcm->name, "Digital");
 		snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
 						      snd_dma_pci_data(chip->pci),
@@ -765,12 +779,29 @@
 			snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
 					&oxygen_rec_b_ops);
 		pcm->private_data = chip;
-		pcm->private_free = oxygen_pcm_free;
 		strcpy(pcm->name, outs ? "Front Panel" : "Analog 2");
 		snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
 						      snd_dma_pci_data(chip->pci),
 						      DEFAULT_BUFFER_BYTES,
 						      BUFFER_BYTES_MAX);
 	}
+
+	ins = !!(chip->model.device_config & CAPTURE_3_FROM_I2S_3);
+	if (ins) {
+		err = snd_pcm_new(chip->card, "Analog3", 3, 0, ins, &pcm);
+		if (err < 0)
+			return err;
+		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
+				&oxygen_rec_c_ops);
+		oxygen_write8_masked(chip, OXYGEN_REC_ROUTING,
+				     OXYGEN_REC_C_ROUTE_I2S_ADC_3,
+				     OXYGEN_REC_C_ROUTE_MASK);
+		pcm->private_data = chip;
+		strcpy(pcm->name, "Analog 3");
+		snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+						      snd_dma_pci_data(chip->pci),
+						      DEFAULT_BUFFER_BYTES,
+						      BUFFER_BYTES_MAX);
+	}
 	return 0;
 }
diff --git a/sound/pci/oxygen/se6x.c b/sound/pci/oxygen/se6x.c
new file mode 100644
index 0000000..f70d514
--- /dev/null
+++ b/sound/pci/oxygen/se6x.c
@@ -0,0 +1,160 @@
+/*
+ * C-Media CMI8787 driver for the Studio Evolution SE6X
+ *
+ * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
+ *
+ *  This driver is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License, version 2.
+ *
+ *  This driver 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 driver; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * CMI8787:
+ *
+ *   SPI    -> microcontroller (not actually used)
+ *   GPIO 0 -> do.
+ *   GPIO 2 -> do.
+ *
+ *   DAC0   -> both PCM1792A (L+R, each in mono mode)
+ *   ADC1  <-  1st PCM1804
+ *   ADC2  <-  2nd PCM1804
+ *   ADC3  <-  3rd PCM1804
+ */
+
+#include <linux/pci.h>
+#include <linux/module.h>
+#include <sound/core.h>
+#include <sound/control.h>
+#include <sound/initval.h>
+#include <sound/pcm.h>
+#include "oxygen.h"
+
+MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
+MODULE_DESCRIPTION("Studio Evolution SE6X driver");
+MODULE_LICENSE("GPL v2");
+MODULE_SUPPORTED_DEVICE("{{Studio Evolution,SE6X}}");
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+
+module_param_array(index, int, NULL, 0444);
+MODULE_PARM_DESC(index, "card index");
+module_param_array(id, charp, NULL, 0444);
+MODULE_PARM_DESC(id, "ID string");
+module_param_array(enable, bool, NULL, 0444);
+MODULE_PARM_DESC(enable, "enable card");
+
+static const struct pci_device_id se6x_ids[] = {
+	{ OXYGEN_PCI_SUBID(0x13f6, 0x8788) },
+	{ }
+};
+MODULE_DEVICE_TABLE(pci, se6x_ids);
+
+static void se6x_init(struct oxygen *chip)
+{
+	oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, 0x005);
+
+	snd_component_add(chip->card, "PCM1792A");
+	snd_component_add(chip->card, "PCM1804");
+}
+
+static int se6x_control_filter(struct snd_kcontrol_new *template)
+{
+	/* no DAC volume/mute */
+	if (!strncmp(template->name, "Master Playback ", 16))
+		return 1;
+	return 0;
+}
+
+static void se6x_cleanup(struct oxygen *chip)
+{
+}
+
+static void set_pcm1792a_params(struct oxygen *chip,
+				struct snd_pcm_hw_params *params)
+{
+	/* nothing to do (the microcontroller monitors DAC_LRCK) */
+}
+
+static void set_pcm1804_params(struct oxygen *chip,
+			       struct snd_pcm_hw_params *params)
+{
+}
+
+static unsigned int se6x_adjust_dac_routing(struct oxygen *chip,
+					    unsigned int play_routing)
+{
+	/* route the same stereo pair to DAC0 and DAC1 */
+	return ( play_routing       & OXYGEN_PLAY_DAC0_SOURCE_MASK) |
+	       ((play_routing << 2) & OXYGEN_PLAY_DAC1_SOURCE_MASK);
+}
+
+static const struct oxygen_model model_se6x = {
+	.shortname = "Studio Evolution SE6X",
+	.longname = "C-Media Oxygen HD Audio",
+	.chip = "CMI8787",
+	.init = se6x_init,
+	.control_filter = se6x_control_filter,
+	.cleanup = se6x_cleanup,
+	.set_dac_params = set_pcm1792a_params,
+	.set_adc_params = set_pcm1804_params,
+	.adjust_dac_routing = se6x_adjust_dac_routing,
+	.device_config = PLAYBACK_0_TO_I2S |
+			 CAPTURE_0_FROM_I2S_1 |
+			 CAPTURE_2_FROM_I2S_2 |
+			 CAPTURE_3_FROM_I2S_3,
+	.dac_channels_pcm = 2,
+	.function_flags = OXYGEN_FUNCTION_SPI,
+	.dac_mclks = OXYGEN_MCLKS(256, 128, 128),
+	.adc_mclks = OXYGEN_MCLKS(256, 256, 128),
+	.dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
+	.adc_i2s_format = OXYGEN_I2S_FORMAT_I2S,
+};
+
+static int se6x_get_model(struct oxygen *chip,
+			  const struct pci_device_id *pci_id)
+{
+	chip->model = model_se6x;
+	return 0;
+}
+
+static int se6x_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
+{
+	static int dev;
+	int err;
+
+	if (dev >= SNDRV_CARDS)
+		return -ENODEV;
+	if (!enable[dev]) {
+		++dev;
+		return -ENOENT;
+	}
+	err = oxygen_pci_probe(pci, index[dev], id[dev], THIS_MODULE,
+			       se6x_ids, se6x_get_model);
+	if (err >= 0)
+		++dev;
+	return err;
+}
+
+static struct pci_driver se6x_driver = {
+	.name = KBUILD_MODNAME,
+	.id_table = se6x_ids,
+	.probe = se6x_probe,
+	.remove = oxygen_pci_remove,
+#ifdef CONFIG_PM_SLEEP
+	.driver = {
+		.pm = &oxygen_pci_pm,
+	},
+#endif
+	.shutdown = oxygen_pci_shutdown,
+};
+
+module_pci_driver(se6x_driver);
diff --git a/sound/pci/pcxhr/pcxhr_core.c b/sound/pci/pcxhr/pcxhr_core.c
index 181f772..c5194f5 100644
--- a/sound/pci/pcxhr/pcxhr_core.c
+++ b/sound/pci/pcxhr/pcxhr_core.c
@@ -24,7 +24,7 @@
 #include <linux/firmware.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <sound/core.h>
 #include "pcxhr.h"
 #include "pcxhr_mixer.h"
diff --git a/sound/pci/pcxhr/pcxhr_hwdep.c b/sound/pci/pcxhr/pcxhr_hwdep.c
index 15a8ce5..8063305 100644
--- a/sound/pci/pcxhr/pcxhr_hwdep.c
+++ b/sound/pci/pcxhr/pcxhr_hwdep.c
@@ -25,7 +25,7 @@
 #include <linux/firmware.h>
 #include <linux/pci.h>
 #include <linux/module.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <sound/core.h>
 #include <sound/hwdep.h>
 #include "pcxhr.h"
diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c
index 6abc2ac..29f2827 100644
--- a/sound/pci/riptide/riptide.c
+++ b/sound/pci/riptide/riptide.c
@@ -99,7 +99,7 @@
 #include <linux/firmware.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <sound/core.h>
 #include <sound/info.h>
 #include <sound/control.h>
@@ -1153,7 +1153,6 @@
 #ifdef CONFIG_PM_SLEEP
 static int riptide_suspend(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct snd_riptide *chip = card->private_data;
 
@@ -1161,27 +1160,14 @@
 	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
 	snd_pcm_suspend_all(chip->pcm);
 	snd_ac97_suspend(chip->ac97);
-	pci_disable_device(pci);
-	pci_save_state(pci);
-	pci_set_power_state(pci, PCI_D3hot);
 	return 0;
 }
 
 static int riptide_resume(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct snd_riptide *chip = card->private_data;
 
-	pci_set_power_state(pci, PCI_D0);
-	pci_restore_state(pci);
-	if (pci_enable_device(pci) < 0) {
-		printk(KERN_ERR "riptide: pci_enable_device failed, "
-		       "disabling device\n");
-		snd_card_disconnect(card);
-		return -EIO;
-	}
-	pci_set_master(pci);
 	snd_riptide_initialize(chip);
 	snd_ac97_resume(chip->ac97);
 	snd_power_change_state(card, SNDRV_CTL_POWER_D0);
@@ -1706,14 +1692,11 @@
 	.pointer = snd_riptide_pointer,
 };
 
-static int
-snd_riptide_pcm(struct snd_riptide *chip, int device, struct snd_pcm **rpcm)
+static int snd_riptide_pcm(struct snd_riptide *chip, int device)
 {
 	struct snd_pcm *pcm;
 	int err;
 
-	if (rpcm)
-		*rpcm = NULL;
 	if ((err =
 	     snd_pcm_new(chip->card, "RIPTIDE", device, PLAYBACK_SUBSTREAMS, 1,
 			 &pcm)) < 0)
@@ -1729,8 +1712,6 @@
 	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
 					      snd_dma_pci_data(chip->pci),
 					      64 * 1024, 128 * 1024);
-	if (rpcm)
-		*rpcm = pcm;
 	return 0;
 }
 
@@ -2092,7 +2073,7 @@
 	if (err < 0)
 		goto error;
 	card->private_data = chip;
-	err = snd_riptide_pcm(chip, 0, NULL);
+	err = snd_riptide_pcm(chip, 0);
 	if (err < 0)
 		goto error;
 	err = snd_riptide_mixer(chip);
diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c
index 6c60dcd..23d7f5d 100644
--- a/sound/pci/rme32.c
+++ b/sound/pci/rme32.c
@@ -75,6 +75,7 @@
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/module.h>
+#include <linux/io.h>
 
 #include <sound/core.h>
 #include <sound/info.h>
@@ -85,8 +86,6 @@
 #include <sound/asoundef.h>
 #include <sound/initval.h>
 
-#include <asm/io.h>
-
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
 static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;	/* Enable this card */
@@ -632,7 +631,7 @@
 	}
 }
 
-static int snd_rme32_setformat(struct rme32 * rme32, int format)
+static int snd_rme32_setformat(struct rme32 *rme32, snd_pcm_format_t format)
 {
 	switch (format) {
 	case SNDRV_PCM_FORMAT_S16_LE:
diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c
index 2f1a851..2306ccf 100644
--- a/sound/pci/rme96.c
+++ b/sound/pci/rme96.c
@@ -29,6 +29,7 @@
 #include <linux/pci.h>
 #include <linux/module.h>
 #include <linux/vmalloc.h>
+#include <linux/io.h>
 
 #include <sound/core.h>
 #include <sound/info.h>
@@ -38,8 +39,6 @@
 #include <sound/asoundef.h>
 #include <sound/initval.h>
 
-#include <asm/io.h>
-
 /* note, two last pcis should be equal, it is not a bug */
 
 MODULE_AUTHOR("Anders Torger <torger@ludd.luth.se>");
@@ -922,8 +921,7 @@
 }
 
 static int
-snd_rme96_playback_setformat(struct rme96 *rme96,
-			     int format)
+snd_rme96_playback_setformat(struct rme96 *rme96, snd_pcm_format_t format)
 {
 	switch (format) {
 	case SNDRV_PCM_FORMAT_S16_LE:
@@ -940,8 +938,7 @@
 }
 
 static int
-snd_rme96_capture_setformat(struct rme96 *rme96,
-			    int format)
+snd_rme96_capture_setformat(struct rme96 *rme96, snd_pcm_format_t format)
 {
 	switch (format) {
 	case SNDRV_PCM_FORMAT_S16_LE:
@@ -2358,7 +2355,6 @@
 
 static int rme96_suspend(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct rme96 *rme96 = card->private_data;
 
@@ -2381,26 +2377,14 @@
 	/* disable the DAC  */
 	rme96->areg &= ~RME96_AR_DAC_EN;
 	writel(rme96->areg, rme96->iobase + RME96_IO_ADDITIONAL_REG);
-
-	pci_disable_device(pci);
-	pci_save_state(pci);
-
 	return 0;
 }
 
 static int rme96_resume(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct rme96 *rme96 = card->private_data;
 
-	pci_restore_state(pci);
-	if (pci_enable_device(pci) < 0) {
-		dev_err(dev, "pci_enable_device failed, disabling device\n");
-		snd_card_disconnect(card);
-		return -EIO;
-	}
-
 	/* reset playback and record buffer pointers */
 	writel(0, rme96->iobase + RME96_IO_SET_PLAY_POS
 		  + rme96->playback_pointer);
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
index cf5a6c8..c19e021 100644
--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -29,6 +29,7 @@
 #include <linux/module.h>
 #include <linux/math64.h>
 #include <linux/vmalloc.h>
+#include <linux/io.h>
 
 #include <sound/core.h>
 #include <sound/control.h>
@@ -42,7 +43,6 @@
 
 #include <asm/byteorder.h>
 #include <asm/current.h>
-#include <asm/io.h>
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
@@ -1428,10 +1428,8 @@
 	   leaving istimer wherever it was set before.
 	*/
 
-	if (hmidi->istimer) {
-		hmidi->timer.expires = 1 + jiffies;
-		add_timer(&hmidi->timer);
-	}
+	if (hmidi->istimer)
+		mod_timer(&hmidi->timer, 1 + jiffies);
 
 	spin_unlock_irqrestore (&hmidi->lock, flags);
 }
@@ -1445,11 +1443,9 @@
 	spin_lock_irqsave (&hmidi->lock, flags);
 	if (up) {
 		if (!hmidi->istimer) {
-			init_timer(&hmidi->timer);
-			hmidi->timer.function = snd_hdsp_midi_output_timer;
-			hmidi->timer.data = (unsigned long) hmidi;
-			hmidi->timer.expires = 1 + jiffies;
-			add_timer(&hmidi->timer);
+			setup_timer(&hmidi->timer, snd_hdsp_midi_output_timer,
+				    (unsigned long) hmidi);
+			mod_timer(&hmidi->timer, 1 + jiffies);
 			hmidi->istimer++;
 		}
 	} else {
@@ -5309,9 +5305,7 @@
 
 	release_firmware(hdsp->firmware);
 	vfree(hdsp->fw_uploaded);
-
-	if (hdsp->iobase)
-		iounmap(hdsp->iobase);
+	iounmap(hdsp->iobase);
 
 	if (hdsp->port)
 		pci_release_regions(hdsp->pci);
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
index 3342705..2c363fdc 100644
--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -136,7 +136,7 @@
 #include <linux/slab.h>
 #include <linux/pci.h>
 #include <linux/math64.h>
-#include <asm/io.h>
+#include <linux/io.h>
 
 #include <sound/core.h>
 #include <sound/control.h>
@@ -1957,10 +1957,8 @@
 	   leaving istimer wherever it was set before.
 	*/
 
-	if (hmidi->istimer) {
-		hmidi->timer.expires = 1 + jiffies;
-		add_timer(&hmidi->timer);
-	}
+	if (hmidi->istimer)
+		mod_timer(&hmidi->timer, 1 + jiffies);
 
 	spin_unlock_irqrestore (&hmidi->lock, flags);
 }
@@ -1975,11 +1973,9 @@
 	spin_lock_irqsave (&hmidi->lock, flags);
 	if (up) {
 		if (!hmidi->istimer) {
-			init_timer(&hmidi->timer);
-			hmidi->timer.function = snd_hdspm_midi_output_timer;
-			hmidi->timer.data = (unsigned long) hmidi;
-			hmidi->timer.expires = 1 + jiffies;
-			add_timer(&hmidi->timer);
+			setup_timer(&hmidi->timer, snd_hdspm_midi_output_timer,
+				    (unsigned long) hmidi);
+			mod_timer(&hmidi->timer, 1 + jiffies);
 			hmidi->istimer++;
 		}
 	} else {
@@ -6965,9 +6961,7 @@
 		free_irq(hdspm->irq, (void *) hdspm);
 
 	kfree(hdspm->mixer);
-
-	if (hdspm->iobase)
-		iounmap(hdspm->iobase);
+	iounmap(hdspm->iobase);
 
 	if (hdspm->port)
 		pci_release_regions(hdspm->pci);
diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c
index 6521521..fdbc0aa 100644
--- a/sound/pci/rme9652/rme9652.c
+++ b/sound/pci/rme9652/rme9652.c
@@ -25,6 +25,7 @@
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/module.h>
+#include <linux/io.h>
 
 #include <sound/core.h>
 #include <sound/control.h>
@@ -34,7 +35,6 @@
 #include <sound/initval.h>
 
 #include <asm/current.h>
-#include <asm/io.h>
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
@@ -1756,8 +1756,7 @@
 
 	if (rme9652->irq >= 0)
 		free_irq(rme9652->irq, (void *)rme9652);
-	if (rme9652->iobase)
-		iounmap(rme9652->iobase);
+	iounmap(rme9652->iobase);
 	if (rme9652->port)
 		pci_release_regions(rme9652->pci);
 
diff --git a/sound/pci/sis7019.c b/sound/pci/sis7019.c
index 7f6a0a0..efe669b 100644
--- a/sound/pci/sis7019.c
+++ b/sound/pci/sis7019.c
@@ -1064,12 +1064,9 @@
 	if (sis->irq >= 0)
 		free_irq(sis->irq, sis);
 
-	if (sis->ioaddr)
-		iounmap(sis->ioaddr);
-
+	iounmap(sis->ioaddr);
 	pci_release_regions(sis->pci);
 	pci_disable_device(sis->pci);
-
 	sis_free_suspend(sis);
 	return 0;
 }
@@ -1211,7 +1208,6 @@
 #ifdef CONFIG_PM_SLEEP
 static int sis_suspend(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct sis7019 *sis = card->private_data;
 	void __iomem *ioaddr = sis->ioaddr;
@@ -1240,9 +1236,6 @@
 		ioaddr += 4096;
 	}
 
-	pci_disable_device(pci);
-	pci_save_state(pci);
-	pci_set_power_state(pci, PCI_D3hot);
 	return 0;
 }
 
@@ -1254,14 +1247,6 @@
 	void __iomem *ioaddr = sis->ioaddr;
 	int i;
 
-	pci_set_power_state(pci, PCI_D0);
-	pci_restore_state(pci);
-
-	if (pci_enable_device(pci) < 0) {
-		dev_err(&pci->dev, "unable to re-enable device\n");
-		goto error;
-	}
-
 	if (sis_chip_init(sis)) {
 		dev_err(&pci->dev, "unable to re-init controller\n");
 		goto error;
@@ -1284,7 +1269,6 @@
 	memset(sis->suspend_state[0], 0, 4096);
 
 	sis->irq = pci->irq;
-	pci_set_master(pci);
 
 	if (sis->codecs_present & SIS_PRIMARY_CODEC_PRESENT)
 		snd_ac97_resume(sis->ac97[0]);
diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c
index 313a732..0f40624 100644
--- a/sound/pci/sonicvibes.c
+++ b/sound/pci/sonicvibes.c
@@ -30,6 +30,7 @@
 #include <linux/gameport.h>
 #include <linux/module.h>
 #include <linux/dma-mapping.h>
+#include <linux/io.h>
 
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -39,8 +40,6 @@
 #include <sound/opl3.h>
 #include <sound/initval.h>
 
-#include <asm/io.h>
-
 MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
 MODULE_DESCRIPTION("S3 SonicVibes PCI");
 MODULE_LICENSE("GPL");
@@ -880,8 +879,7 @@
 	.pointer =	snd_sonicvibes_capture_pointer,
 };
 
-static int snd_sonicvibes_pcm(struct sonicvibes *sonic, int device,
-			      struct snd_pcm **rpcm)
+static int snd_sonicvibes_pcm(struct sonicvibes *sonic, int device)
 {
 	struct snd_pcm *pcm;
 	int err;
@@ -902,8 +900,6 @@
 	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
 					      snd_dma_pci_data(sonic->pci), 64*1024, 128*1024);
 
-	if (rpcm)
-		*rpcm = pcm;
 	return 0;
 }
 
@@ -1491,7 +1487,7 @@
 		(unsigned long long)pci_resource_start(pci, 1),
 		sonic->irq);
 
-	if ((err = snd_sonicvibes_pcm(sonic, 0, NULL)) < 0) {
+	if ((err = snd_sonicvibes_pcm(sonic, 0)) < 0) {
 		snd_card_free(card);
 		return err;
 	}
diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c
index a54cd68..cedf13b 100644
--- a/sound/pci/trident/trident.c
+++ b/sound/pci/trident/trident.c
@@ -127,21 +127,21 @@
 	sprintf(card->longname, "%s PCI Audio at 0x%lx, irq %d",
 		card->shortname, trident->port, trident->irq);
 
-	if ((err = snd_trident_pcm(trident, pcm_dev++, NULL)) < 0) {
+	if ((err = snd_trident_pcm(trident, pcm_dev++)) < 0) {
 		snd_card_free(card);
 		return err;
 	}
 	switch (trident->device) {
 	case TRIDENT_DEVICE_ID_DX:
 	case TRIDENT_DEVICE_ID_NX:
-		if ((err = snd_trident_foldback_pcm(trident, pcm_dev++, NULL)) < 0) {
+		if ((err = snd_trident_foldback_pcm(trident, pcm_dev++)) < 0) {
 			snd_card_free(card);
 			return err;
 		}
 		break;
 	}
 	if (trident->device == TRIDENT_DEVICE_ID_NX || trident->device == TRIDENT_DEVICE_ID_SI7018) {
-		if ((err = snd_trident_spdif_pcm(trident, pcm_dev++, NULL)) < 0) {
+		if ((err = snd_trident_spdif_pcm(trident, pcm_dev++)) < 0) {
 			snd_card_free(card);
 			return err;
 		}
diff --git a/sound/pci/trident/trident.h b/sound/pci/trident/trident.h
index 5f110eb..9624e59 100644
--- a/sound/pci/trident/trident.h
+++ b/sound/pci/trident/trident.h
@@ -420,9 +420,9 @@
 		       struct snd_trident ** rtrident);
 int snd_trident_create_gameport(struct snd_trident *trident);
 
-int snd_trident_pcm(struct snd_trident * trident, int device, struct snd_pcm **rpcm);
-int snd_trident_foldback_pcm(struct snd_trident * trident, int device, struct snd_pcm **rpcm);
-int snd_trident_spdif_pcm(struct snd_trident * trident, int device, struct snd_pcm **rpcm);
+int snd_trident_pcm(struct snd_trident *trident, int device);
+int snd_trident_foldback_pcm(struct snd_trident *trident, int device);
+int snd_trident_spdif_pcm(struct snd_trident *trident, int device);
 int snd_trident_attach_synthesizer(struct snd_trident * trident);
 struct snd_trident_voice *snd_trident_alloc_voice(struct snd_trident * trident, int type,
 					     int client, int port);
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c
index 57cd757..b72be03 100644
--- a/sound/pci/trident/trident_main.c
+++ b/sound/pci/trident/trident_main.c
@@ -36,6 +36,7 @@
 #include <linux/gameport.h>
 #include <linux/dma-mapping.h>
 #include <linux/export.h>
+#include <linux/io.h>
 
 #include <sound/core.h>
 #include <sound/info.h>
@@ -44,8 +45,6 @@
 #include "trident.h"
 #include <sound/asoundef.h>
 
-#include <asm/io.h>
-
 static int snd_trident_pcm_mixer_build(struct snd_trident *trident,
 				       struct snd_trident_voice * voice,
 				       struct snd_pcm_substream *substream);
@@ -2172,14 +2171,11 @@
   
   ---------------------------------------------------------------------------*/
 
-int snd_trident_pcm(struct snd_trident *trident,
-		    int device, struct snd_pcm **rpcm)
+int snd_trident_pcm(struct snd_trident *trident, int device)
 {
 	struct snd_pcm *pcm;
 	int err;
 
-	if (rpcm)
-		*rpcm = NULL;
 	if ((err = snd_pcm_new(trident->card, "trident_dx_nx", device, trident->ChanPCM, 1, &pcm)) < 0)
 		return err;
 
@@ -2214,8 +2210,6 @@
 						      snd_dma_pci_data(trident->pci), 64*1024, 128*1024);
 	}
 
-	if (rpcm)
-		*rpcm = pcm;
 	return 0;
 }
 
@@ -2230,16 +2224,13 @@
   
   ---------------------------------------------------------------------------*/
 
-int snd_trident_foldback_pcm(struct snd_trident *trident,
-			     int device, struct snd_pcm **rpcm)
+int snd_trident_foldback_pcm(struct snd_trident *trident, int device)
 {
 	struct snd_pcm *foldback;
 	int err;
 	int num_chan = 3;
 	struct snd_pcm_substream *substream;
 
-	if (rpcm)
-		*rpcm = NULL;
 	if (trident->device == TRIDENT_DEVICE_ID_NX)
 		num_chan = 4;
 	if ((err = snd_pcm_new(trident->card, "trident_dx_nx", device, 0, num_chan, &foldback)) < 0)
@@ -2271,8 +2262,6 @@
 		snd_pcm_lib_preallocate_pages_for_all(foldback, SNDRV_DMA_TYPE_DEV,
 						      snd_dma_pci_data(trident->pci), 64*1024, 128*1024);
 
-	if (rpcm)
-		*rpcm = foldback;
 	return 0;
 }
 
@@ -2287,14 +2276,11 @@
   
   ---------------------------------------------------------------------------*/
 
-int snd_trident_spdif_pcm(struct snd_trident *trident,
-			  int device, struct snd_pcm **rpcm)
+int snd_trident_spdif_pcm(struct snd_trident *trident, int device)
 {
 	struct snd_pcm *spdif;
 	int err;
 
-	if (rpcm)
-		*rpcm = NULL;
 	if ((err = snd_pcm_new(trident->card, "trident_dx_nx IEC958", device, 1, 0, &spdif)) < 0)
 		return err;
 
@@ -2310,8 +2296,6 @@
 
 	snd_pcm_lib_preallocate_pages_for_all(spdif, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(trident->pci), 64*1024, 128*1024);
 
-	if (rpcm)
-		*rpcm = spdif;
 	return 0;
 }
 
@@ -3926,7 +3910,6 @@
 #ifdef CONFIG_PM_SLEEP
 static int snd_trident_suspend(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct snd_trident *trident = card->private_data;
 
@@ -3938,28 +3921,14 @@
 
 	snd_ac97_suspend(trident->ac97);
 	snd_ac97_suspend(trident->ac97_sec);
-
-	pci_disable_device(pci);
-	pci_save_state(pci);
-	pci_set_power_state(pci, PCI_D3hot);
 	return 0;
 }
 
 static int snd_trident_resume(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct snd_trident *trident = card->private_data;
 
-	pci_set_power_state(pci, PCI_D0);
-	pci_restore_state(pci);
-	if (pci_enable_device(pci) < 0) {
-		dev_err(dev, "pci_enable_device failed, disabling device\n");
-		snd_card_disconnect(card);
-		return -EIO;
-	}
-	pci_set_master(pci);
-
 	switch (trident->device) {
 	case TRIDENT_DEVICE_ID_DX:
 		snd_trident_4d_dx_init(trident);
diff --git a/sound/pci/trident/trident_memory.c b/sound/pci/trident/trident_memory.c
index 04c4746..b9ebb51 100644
--- a/sound/pci/trident/trident_memory.c
+++ b/sound/pci/trident/trident_memory.c
@@ -23,7 +23,7 @@
  *
  */
 
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/pci.h>
 #include <linux/time.h>
 #include <linux/mutex.h>
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c
index e088467..8622283 100644
--- a/sound/pci/via82xx.c
+++ b/sound/pci/via82xx.c
@@ -46,7 +46,7 @@
  *	- Optimize position calculation for the 823x chips. 
  */
 
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
@@ -2271,7 +2271,6 @@
  */
 static int snd_via82xx_suspend(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct via82xx *chip = card->private_data;
 	int i;
@@ -2291,28 +2290,15 @@
 		chip->capture_src_saved[1] = inb(chip->port + VIA_REG_CAPTURE_CHANNEL + 0x10);
 	}
 
-	pci_disable_device(pci);
-	pci_save_state(pci);
-	pci_set_power_state(pci, PCI_D3hot);
 	return 0;
 }
 
 static int snd_via82xx_resume(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct via82xx *chip = card->private_data;
 	int i;
 
-	pci_set_power_state(pci, PCI_D0);
-	pci_restore_state(pci);
-	if (pci_enable_device(pci) < 0) {
-		dev_err(dev, "pci_enable_device failed, disabling device\n");
-		snd_card_disconnect(card);
-		return -EIO;
-	}
-	pci_set_master(pci);
-
 	snd_via82xx_chip_init(chip);
 
 	if (chip->chip_type == TYPE_VIA686) {
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c
index fd46ffe..99b9137 100644
--- a/sound/pci/via82xx_modem.c
+++ b/sound/pci/via82xx_modem.c
@@ -31,7 +31,7 @@
  *      modems.
  */
 
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
@@ -1031,7 +1031,6 @@
  */
 static int snd_via82xx_suspend(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct via82xx_modem *chip = card->private_data;
 	int i;
@@ -1043,29 +1042,15 @@
 		snd_via82xx_channel_reset(chip, &chip->devs[i]);
 	synchronize_irq(chip->irq);
 	snd_ac97_suspend(chip->ac97);
-
-	pci_disable_device(pci);
-	pci_save_state(pci);
-	pci_set_power_state(pci, PCI_D3hot);
 	return 0;
 }
 
 static int snd_via82xx_resume(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct via82xx_modem *chip = card->private_data;
 	int i;
 
-	pci_set_power_state(pci, PCI_D0);
-	pci_restore_state(pci);
-	if (pci_enable_device(pci) < 0) {
-		dev_err(dev, "pci_enable_device failed, disabling device\n");
-		snd_card_disconnect(card);
-		return -EIO;
-	}
-	pci_set_master(pci);
-
 	snd_via82xx_chip_init(chip);
 
 	snd_ac97_resume(chip->ac97);
diff --git a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c
index c5a25e3..ecbaf47 100644
--- a/sound/pci/vx222/vx222.c
+++ b/sound/pci/vx222/vx222.c
@@ -259,32 +259,17 @@
 #ifdef CONFIG_PM_SLEEP
 static int snd_vx222_suspend(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct snd_vx222 *vx = card->private_data;
-	int err;
 
-	err = snd_vx_suspend(&vx->core);
-	pci_disable_device(pci);
-	pci_save_state(pci);
-	pci_set_power_state(pci, PCI_D3hot);
-	return err;
+	return snd_vx_suspend(&vx->core);
 }
 
 static int snd_vx222_resume(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct snd_vx222 *vx = card->private_data;
 
-	pci_set_power_state(pci, PCI_D0);
-	pci_restore_state(pci);
-	if (pci_enable_device(pci) < 0) {
-		dev_err(dev, "pci_enable_device failed, disabling device\n");
-		snd_card_disconnect(card);
-		return -EIO;
-	}
-	pci_set_master(pci);
 	return snd_vx_resume(&vx->core);
 }
 
diff --git a/sound/pci/vx222/vx222_ops.c b/sound/pci/vx222/vx222_ops.c
index 52c1a8d..af83b3b 100644
--- a/sound/pci/vx222/vx222_ops.c
+++ b/sound/pci/vx222/vx222_ops.c
@@ -24,11 +24,11 @@
 #include <linux/device.h>
 #include <linux/firmware.h>
 #include <linux/mutex.h>
+#include <linux/io.h>
 
 #include <sound/core.h>
 #include <sound/control.h>
 #include <sound/tlv.h>
-#include <asm/io.h>
 #include "vx222.h"
 
 
diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c
index 47a1923..812e27a 100644
--- a/sound/pci/ymfpci/ymfpci.c
+++ b/sound/pci/ymfpci/ymfpci.c
@@ -283,11 +283,11 @@
 		card->shortname,
 		chip->reg_area_phys,
 		chip->irq);
-	if ((err = snd_ymfpci_pcm(chip, 0, NULL)) < 0) {
+	if ((err = snd_ymfpci_pcm(chip, 0)) < 0) {
 		snd_card_free(card);
 		return err;
 	}
-	if ((err = snd_ymfpci_pcm_spdif(chip, 1, NULL)) < 0) {
+	if ((err = snd_ymfpci_pcm_spdif(chip, 1)) < 0) {
 		snd_card_free(card);
 		return err;
 	}
@@ -297,12 +297,12 @@
 		return err;
 	}
 	if (chip->ac97->ext_id & AC97_EI_SDAC) {
-		err = snd_ymfpci_pcm_4ch(chip, 2, NULL);
+		err = snd_ymfpci_pcm_4ch(chip, 2);
 		if (err < 0) {
 			snd_card_free(card);
 			return err;
 		}
-		err = snd_ymfpci_pcm2(chip, 3, NULL);
+		err = snd_ymfpci_pcm2(chip, 3);
 		if (err < 0) {
 			snd_card_free(card);
 			return err;
diff --git a/sound/pci/ymfpci/ymfpci.h b/sound/pci/ymfpci/ymfpci.h
index 4631a23..149d4cb 100644
--- a/sound/pci/ymfpci/ymfpci.h
+++ b/sound/pci/ymfpci/ymfpci.h
@@ -379,10 +379,10 @@
 
 extern const struct dev_pm_ops snd_ymfpci_pm;
 
-int snd_ymfpci_pcm(struct snd_ymfpci *chip, int device, struct snd_pcm **rpcm);
-int snd_ymfpci_pcm2(struct snd_ymfpci *chip, int device, struct snd_pcm **rpcm);
-int snd_ymfpci_pcm_spdif(struct snd_ymfpci *chip, int device, struct snd_pcm **rpcm);
-int snd_ymfpci_pcm_4ch(struct snd_ymfpci *chip, int device, struct snd_pcm **rpcm);
+int snd_ymfpci_pcm(struct snd_ymfpci *chip, int device);
+int snd_ymfpci_pcm2(struct snd_ymfpci *chip, int device);
+int snd_ymfpci_pcm_spdif(struct snd_ymfpci *chip, int device);
+int snd_ymfpci_pcm_4ch(struct snd_ymfpci *chip, int device);
 int snd_ymfpci_mixer(struct snd_ymfpci *chip, int rear_switch);
 int snd_ymfpci_timer(struct snd_ymfpci *chip, int device);
 
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c
index 81c916a..4c26076 100644
--- a/sound/pci/ymfpci/ymfpci_main.c
+++ b/sound/pci/ymfpci/ymfpci_main.c
@@ -27,6 +27,7 @@
 #include <linux/slab.h>
 #include <linux/mutex.h>
 #include <linux/module.h>
+#include <linux/io.h>
 
 #include <sound/core.h>
 #include <sound/control.h>
@@ -36,7 +37,6 @@
 #include <sound/asoundef.h>
 #include <sound/mpu401.h>
 
-#include <asm/io.h>
 #include <asm/byteorder.h>
 
 /*
@@ -1145,13 +1145,11 @@
 	.pointer =		snd_ymfpci_capture_pointer,
 };
 
-int snd_ymfpci_pcm(struct snd_ymfpci *chip, int device, struct snd_pcm **rpcm)
+int snd_ymfpci_pcm(struct snd_ymfpci *chip, int device)
 {
 	struct snd_pcm *pcm;
 	int err;
 
-	if (rpcm)
-		*rpcm = NULL;
 	if ((err = snd_pcm_new(chip->card, "YMFPCI", device, 32, 1, &pcm)) < 0)
 		return err;
 	pcm->private_data = chip;
@@ -1167,14 +1165,8 @@
 	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
 					      snd_dma_pci_data(chip->pci), 64*1024, 256*1024);
 
-	err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+	return snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
 				     snd_pcm_std_chmaps, 2, 0, NULL);
-	if (err < 0)
-		return err;
-
-	if (rpcm)
-		*rpcm = pcm;
-	return 0;
 }
 
 static struct snd_pcm_ops snd_ymfpci_capture_ac97_ops = {
@@ -1188,13 +1180,11 @@
 	.pointer =		snd_ymfpci_capture_pointer,
 };
 
-int snd_ymfpci_pcm2(struct snd_ymfpci *chip, int device, struct snd_pcm **rpcm)
+int snd_ymfpci_pcm2(struct snd_ymfpci *chip, int device)
 {
 	struct snd_pcm *pcm;
 	int err;
 
-	if (rpcm)
-		*rpcm = NULL;
 	if ((err = snd_pcm_new(chip->card, "YMFPCI - PCM2", device, 0, 1, &pcm)) < 0)
 		return err;
 	pcm->private_data = chip;
@@ -1210,8 +1200,6 @@
 	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
 					      snd_dma_pci_data(chip->pci), 64*1024, 256*1024);
 
-	if (rpcm)
-		*rpcm = pcm;
 	return 0;
 }
 
@@ -1226,14 +1214,11 @@
 	.pointer =		snd_ymfpci_playback_pointer,
 };
 
-int snd_ymfpci_pcm_spdif(struct snd_ymfpci *chip, int device,
-			 struct snd_pcm **rpcm)
+int snd_ymfpci_pcm_spdif(struct snd_ymfpci *chip, int device)
 {
 	struct snd_pcm *pcm;
 	int err;
 
-	if (rpcm)
-		*rpcm = NULL;
 	if ((err = snd_pcm_new(chip->card, "YMFPCI - IEC958", device, 1, 0, &pcm)) < 0)
 		return err;
 	pcm->private_data = chip;
@@ -1248,8 +1233,6 @@
 	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
 					      snd_dma_pci_data(chip->pci), 64*1024, 256*1024);
 
-	if (rpcm)
-		*rpcm = pcm;
 	return 0;
 }
 
@@ -1272,14 +1255,11 @@
 	{ }
 };
 
-int snd_ymfpci_pcm_4ch(struct snd_ymfpci *chip, int device,
-		       struct snd_pcm **rpcm)
+int snd_ymfpci_pcm_4ch(struct snd_ymfpci *chip, int device)
 {
 	struct snd_pcm *pcm;
 	int err;
 
-	if (rpcm)
-		*rpcm = NULL;
 	if ((err = snd_pcm_new(chip->card, "YMFPCI - Rear", device, 1, 0, &pcm)) < 0)
 		return err;
 	pcm->private_data = chip;
@@ -1294,14 +1274,8 @@
 	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
 					      snd_dma_pci_data(chip->pci), 64*1024, 256*1024);
 
-	err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+	return snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
 				     surround_map, 2, 0, NULL);
-	if (err < 0)
-		return err;
-
-	if (rpcm)
-		*rpcm = pcm;
-	return 0;
 }
 
 static int snd_ymfpci_spdif_default_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
@@ -2272,8 +2246,7 @@
 	release_and_free_resource(chip->mpu_res);
 	release_and_free_resource(chip->fm_res);
 	snd_ymfpci_free_gameport(chip);
-	if (chip->reg_area_virt)
-		iounmap(chip->reg_area_virt);
+	iounmap(chip->reg_area_virt);
 	if (chip->work_ptr.area)
 		snd_dma_free_pages(&chip->work_ptr);
 	
@@ -2326,7 +2299,6 @@
 
 static int snd_ymfpci_suspend(struct device *dev)
 {
-	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct snd_ymfpci *chip = card->private_data;
 	unsigned int i;
@@ -2347,9 +2319,6 @@
 	snd_ymfpci_writel(chip, YDSXGR_NATIVEDACOUTVOL, 0);
 	snd_ymfpci_writel(chip, YDSXGR_BUF441OUTVOL, 0);
 	snd_ymfpci_disable_dsp(chip);
-	pci_disable_device(pci);
-	pci_save_state(pci);
-	pci_set_power_state(pci, PCI_D3hot);
 	return 0;
 }
 
@@ -2360,14 +2329,6 @@
 	struct snd_ymfpci *chip = card->private_data;
 	unsigned int i;
 
-	pci_set_power_state(pci, PCI_D0);
-	pci_restore_state(pci);
-	if (pci_enable_device(pci) < 0) {
-		dev_err(dev, "pci_enable_device failed, disabling device\n");
-		snd_card_disconnect(card);
-		return -EIO;
-	}
-	pci_set_master(pci);
 	snd_ymfpci_aclink_reset(pci);
 	snd_ymfpci_codec_ready(chip, 0);
 	snd_ymfpci_download_image(chip);
diff --git a/sound/ppc/awacs.c b/sound/ppc/awacs.c
index 5fbf5db..09da7b5 100644
--- a/sound/ppc/awacs.c
+++ b/sound/ppc/awacs.c
@@ -20,7 +20,7 @@
  */
 
 
-#include <asm/io.h>
+#include <linux/io.h>
 #include <asm/nvram.h>
 #include <linux/init.h>
 #include <linux/delay.h>
diff --git a/sound/ppc/beep.c b/sound/ppc/beep.c
index 0040f04..d3524f9 100644
--- a/sound/ppc/beep.c
+++ b/sound/ppc/beep.c
@@ -18,7 +18,7 @@
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
 
-#include <asm/io.h>
+#include <linux/io.h>
 #include <asm/irq.h>
 #include <linux/init.h>
 #include <linux/slab.h>
diff --git a/sound/ppc/burgundy.c b/sound/ppc/burgundy.c
index cb4f0a5..b86159e 100644
--- a/sound/ppc/burgundy.c
+++ b/sound/ppc/burgundy.c
@@ -19,7 +19,7 @@
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
 
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <sound/core.h>
diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c
index 5a13b22..13146d7 100644
--- a/sound/ppc/pmac.c
+++ b/sound/ppc/pmac.c
@@ -20,7 +20,7 @@
  */
 
 
-#include <asm/io.h>
+#include <linux/io.h>
 #include <asm/irq.h>
 #include <linux/init.h>
 #include <linux/delay.h>
@@ -867,16 +867,11 @@
 	snd_pmac_dbdma_free(chip, &chip->capture.cmd);
 	snd_pmac_dbdma_free(chip, &chip->extra_dma);
 	snd_pmac_dbdma_free(chip, &emergency_dbdma);
-	if (chip->macio_base)
-		iounmap(chip->macio_base);
-	if (chip->latch_base)
-		iounmap(chip->latch_base);
-	if (chip->awacs)
-		iounmap(chip->awacs);
-	if (chip->playback.dma)
-		iounmap(chip->playback.dma);
-	if (chip->capture.dma)
-		iounmap(chip->capture.dma);
+	iounmap(chip->macio_base);
+	iounmap(chip->latch_base);
+	iounmap(chip->awacs);
+	iounmap(chip->playback.dma);
+	iounmap(chip->capture.dma);
 
 	if (chip->node) {
 		int i;
diff --git a/sound/ppc/snd_ps3.c b/sound/ppc/snd_ps3.c
index 58f292a..3682425 100644
--- a/sound/ppc/snd_ps3.c
+++ b/sound/ppc/snd_ps3.c
@@ -1044,7 +1044,7 @@
 	if (!the_card.null_buffer_start_vaddr) {
 		pr_info("%s: nullbuffer alloc failed\n", __func__);
 		ret = -ENOMEM;
-		goto clean_preallocate;
+		goto clean_card;
 	}
 	pr_debug("%s: null vaddr=%p dma=%#llx\n", __func__,
 		 the_card.null_buffer_start_vaddr,
@@ -1066,8 +1066,6 @@
 			  PAGE_SIZE,
 			  the_card.null_buffer_start_vaddr,
 			  the_card.null_buffer_start_dma_addr);
-clean_preallocate:
-	snd_pcm_lib_preallocate_free_for_all(the_card.pcm);
 clean_card:
 	snd_card_free(the_card.card);
 clean_irq:
diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c
index 24c8766..c8fafba 100644
--- a/sound/ppc/tumbler.c
+++ b/sound/ppc/tumbler.c
@@ -32,8 +32,8 @@
 #include <linux/interrupt.h>
 #include <linux/string.h>
 #include <linux/of_irq.h>
+#include <linux/io.h>
 #include <sound/core.h>
-#include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/machdep.h>
 #include <asm/pmac_feature.h>
diff --git a/sound/sh/aica.c b/sound/sh/aica.c
index f44dda6..ad3d9ae 100644
--- a/sound/sh/aica.c
+++ b/sound/sh/aica.c
@@ -35,12 +35,12 @@
 #include <linux/timer.h>
 #include <linux/delay.h>
 #include <linux/workqueue.h>
+#include <linux/io.h>
 #include <sound/core.h>
 #include <sound/control.h>
 #include <sound/pcm.h>
 #include <sound/initval.h>
 #include <sound/info.h>
-#include <asm/io.h>
 #include <asm/dma.h>
 #include <mach/sysasic.h>
 #include "aica.h"
@@ -343,11 +343,9 @@
 		mod_timer(&dreamcastcard->timer, jiffies + 4);
 		return;
 	}
-	init_timer(&(dreamcastcard->timer));
-	dreamcastcard->timer.data = (unsigned long) substream;
-	dreamcastcard->timer.function = aica_period_elapsed;
-	dreamcastcard->timer.expires = jiffies + 4;
-	add_timer(&(dreamcastcard->timer));
+	setup_timer(&dreamcastcard->timer, aica_period_elapsed,
+		    (unsigned long) substream);
+	mod_timer(&dreamcastcard->timer, jiffies + 4);
 }
 
 static int snd_aicapcm_pcm_open(struct snd_pcm_substream
diff --git a/sound/soc/codecs/pcm512x-i2c.c b/sound/soc/codecs/pcm512x-i2c.c
index d0547fa..dcdfac0 100644
--- a/sound/soc/codecs/pcm512x-i2c.c
+++ b/sound/soc/codecs/pcm512x-i2c.c
@@ -46,6 +46,8 @@
 static const struct i2c_device_id pcm512x_i2c_id[] = {
 	{ "pcm5121", },
 	{ "pcm5122", },
+	{ "pcm5141", },
+	{ "pcm5142", },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, pcm512x_i2c_id);
@@ -53,6 +55,8 @@
 static const struct of_device_id pcm512x_of_match[] = {
 	{ .compatible = "ti,pcm5121", },
 	{ .compatible = "ti,pcm5122", },
+	{ .compatible = "ti,pcm5141", },
+	{ .compatible = "ti,pcm5142", },
 	{ }
 };
 MODULE_DEVICE_TABLE(of, pcm512x_of_match);
diff --git a/sound/soc/codecs/pcm512x-spi.c b/sound/soc/codecs/pcm512x-spi.c
index f297058..7b64a9c 100644
--- a/sound/soc/codecs/pcm512x-spi.c
+++ b/sound/soc/codecs/pcm512x-spi.c
@@ -43,6 +43,8 @@
 static const struct spi_device_id pcm512x_spi_id[] = {
 	{ "pcm5121", },
 	{ "pcm5122", },
+	{ "pcm5141", },
+	{ "pcm5142", },
 	{ },
 };
 MODULE_DEVICE_TABLE(spi, pcm512x_spi_id);
@@ -50,6 +52,8 @@
 static const struct of_device_id pcm512x_of_match[] = {
 	{ .compatible = "ti,pcm5121", },
 	{ .compatible = "ti,pcm5122", },
+	{ .compatible = "ti,pcm5141", },
+	{ .compatible = "ti,pcm5142", },
 	{ }
 };
 MODULE_DEVICE_TABLE(of, pcm512x_of_match);
diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c
index 8a0833d..0a027bc 100644
--- a/sound/soc/codecs/rt5670.c
+++ b/sound/soc/codecs/rt5670.c
@@ -14,10 +14,12 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/pm.h>
+#include <linux/pm_runtime.h>
 #include <linux/i2c.h>
 #include <linux/platform_device.h>
 #include <linux/acpi.h>
 #include <linux/spi/spi.h>
+#include <linux/dmi.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -2188,6 +2190,13 @@
 	if (freq == rt5670->sysclk && clk_id == rt5670->sysclk_src)
 		return 0;
 
+	if (rt5670->pdata.jd_mode) {
+		if (clk_id == RT5670_SCLK_S_PLL1)
+			snd_soc_dapm_force_enable_pin(&codec->dapm, "PLL1");
+		else
+			snd_soc_dapm_disable_pin(&codec->dapm, "PLL1");
+		snd_soc_dapm_sync(&codec->dapm);
+	}
 	switch (clk_id) {
 	case RT5670_SCLK_S_MCLK:
 		reg_val |= RT5670_SCLK_SRC_MCLK;
@@ -2549,6 +2558,17 @@
 MODULE_DEVICE_TABLE(acpi, rt5670_acpi_match);
 #endif
 
+static const struct dmi_system_id dmi_platform_intel_braswell[] = {
+	{
+		.ident = "Intel Braswell",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
+			DMI_MATCH(DMI_BOARD_NAME, "Braswell CRB"),
+		},
+	},
+	{}
+};
+
 static int rt5670_i2c_probe(struct i2c_client *i2c,
 		    const struct i2c_device_id *id)
 {
@@ -2568,6 +2588,12 @@
 	if (pdata)
 		rt5670->pdata = *pdata;
 
+	if (dmi_check_system(dmi_platform_intel_braswell)) {
+		rt5670->pdata.dmic_en = true;
+		rt5670->pdata.dmic1_data_pin = RT5670_DMIC_DATA_IN2P;
+		rt5670->pdata.jd_mode = 1;
+	}
+
 	rt5670->regmap = devm_regmap_init_i2c(i2c, &rt5670_regmap);
 	if (IS_ERR(rt5670->regmap)) {
 		ret = PTR_ERR(rt5670->regmap);
@@ -2609,6 +2635,10 @@
 	}
 
 	if (rt5670->pdata.jd_mode) {
+		regmap_update_bits(rt5670->regmap, RT5670_GLB_CLK,
+				   RT5670_SCLK_SRC_MASK, RT5670_SCLK_SRC_RCCLK);
+		rt5670->sysclk = 0;
+		rt5670->sysclk_src = RT5670_SCLK_S_RCCLK;
 		regmap_update_bits(rt5670->regmap, RT5670_PWR_ANLG1,
 				   RT5670_PWR_MB, RT5670_PWR_MB);
 		regmap_update_bits(rt5670->regmap, RT5670_PWR_ANLG2,
@@ -2716,18 +2746,26 @@
 
 	}
 
+	pm_runtime_enable(&i2c->dev);
+	pm_request_idle(&i2c->dev);
+
 	ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5670,
 			rt5670_dai, ARRAY_SIZE(rt5670_dai));
 	if (ret < 0)
 		goto err;
 
+	pm_runtime_put(&i2c->dev);
+
 	return 0;
 err:
+	pm_runtime_disable(&i2c->dev);
+
 	return ret;
 }
 
 static int rt5670_i2c_remove(struct i2c_client *i2c)
 {
+	pm_runtime_disable(&i2c->dev);
 	snd_soc_unregister_codec(&i2c->dev);
 
 	return 0;
diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c
index 918ada9..d27630a 100644
--- a/sound/soc/codecs/rt5677.c
+++ b/sound/soc/codecs/rt5677.c
@@ -922,6 +922,97 @@
 		return 0;
 }
 
+static int is_using_asrc(struct snd_soc_dapm_widget *source,
+			 struct snd_soc_dapm_widget *sink)
+{
+	unsigned int reg, shift, val;
+
+	if (source->reg == RT5677_ASRC_1) {
+		switch (source->shift) {
+		case 12:
+			reg = RT5677_ASRC_4;
+			shift = 0;
+			break;
+		case 13:
+			reg = RT5677_ASRC_4;
+			shift = 4;
+			break;
+		case 14:
+			reg = RT5677_ASRC_4;
+			shift = 8;
+			break;
+		case 15:
+			reg = RT5677_ASRC_4;
+			shift = 12;
+			break;
+		default:
+			return 0;
+		}
+	} else {
+		switch (source->shift) {
+		case 0:
+			reg = RT5677_ASRC_6;
+			shift = 8;
+			break;
+		case 1:
+			reg = RT5677_ASRC_6;
+			shift = 12;
+			break;
+		case 2:
+			reg = RT5677_ASRC_5;
+			shift = 0;
+			break;
+		case 3:
+			reg = RT5677_ASRC_5;
+			shift = 4;
+			break;
+		case 4:
+			reg = RT5677_ASRC_5;
+			shift = 8;
+			break;
+		case 5:
+			reg = RT5677_ASRC_5;
+			shift = 12;
+			break;
+		case 12:
+			reg = RT5677_ASRC_3;
+			shift = 0;
+			break;
+		case 13:
+			reg = RT5677_ASRC_3;
+			shift = 4;
+			break;
+		case 14:
+			reg = RT5677_ASRC_3;
+			shift = 12;
+			break;
+		default:
+			return 0;
+		}
+	}
+
+	val = (snd_soc_read(source->codec, reg) >> shift) & 0xf;
+	switch (val) {
+	case 1 ... 6:
+		return 1;
+	default:
+		return 0;
+	}
+
+}
+
+static int can_use_asrc(struct snd_soc_dapm_widget *source,
+			 struct snd_soc_dapm_widget *sink)
+{
+	struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm);
+	struct rt5677_priv *rt5677 = snd_soc_codec_get_drvdata(codec);
+
+	if (rt5677->sysclk > rt5677->lrck[RT5677_AIF1] * 384)
+		return 1;
+
+	return 0;
+}
+
 /* Digital Mixer */
 static const struct snd_kcontrol_new rt5677_sto1_adc_l_mix[] = {
 	SOC_DAPM_SINGLE("ADC1 Switch", RT5677_STO1_ADC_MIXER,
@@ -2226,6 +2317,45 @@
 		0, rt5677_set_pll2_event, SND_SOC_DAPM_PRE_PMU |
 		SND_SOC_DAPM_POST_PMU),
 
+	/* ASRC */
+	SND_SOC_DAPM_SUPPLY_S("I2S1 ASRC", 1, RT5677_ASRC_1, 0, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY_S("I2S2 ASRC", 1, RT5677_ASRC_1, 1, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY_S("I2S3 ASRC", 1, RT5677_ASRC_1, 2, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY_S("I2S4 ASRC", 1, RT5677_ASRC_1, 3, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY_S("DAC STO ASRC", 1, RT5677_ASRC_2, 14, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY_S("DAC MONO2 L ASRC", 1, RT5677_ASRC_2, 13, 0, NULL,
+		0),
+	SND_SOC_DAPM_SUPPLY_S("DAC MONO2 R ASRC", 1, RT5677_ASRC_2, 12, 0, NULL,
+		0),
+	SND_SOC_DAPM_SUPPLY_S("DAC MONO3 L ASRC", 1, RT5677_ASRC_1, 15, 0, NULL,
+		0),
+	SND_SOC_DAPM_SUPPLY_S("DAC MONO3 R ASRC", 1, RT5677_ASRC_1, 14, 0, NULL,
+		0),
+	SND_SOC_DAPM_SUPPLY_S("DAC MONO4 L ASRC", 1, RT5677_ASRC_1, 13, 0, NULL,
+		0),
+	SND_SOC_DAPM_SUPPLY_S("DAC MONO4 R ASRC", 1, RT5677_ASRC_1, 12, 0, NULL,
+		0),
+	SND_SOC_DAPM_SUPPLY_S("DMIC STO1 ASRC", 1, RT5677_ASRC_2, 11, 0, NULL,
+		0),
+	SND_SOC_DAPM_SUPPLY_S("DMIC STO2 ASRC", 1, RT5677_ASRC_2, 10, 0, NULL,
+		0),
+	SND_SOC_DAPM_SUPPLY_S("DMIC STO3 ASRC", 1, RT5677_ASRC_2, 9, 0, NULL,
+		0),
+	SND_SOC_DAPM_SUPPLY_S("DMIC STO4 ASRC", 1, RT5677_ASRC_2, 8, 0, NULL,
+		0),
+	SND_SOC_DAPM_SUPPLY_S("DMIC MONO L ASRC", 1, RT5677_ASRC_2, 7, 0, NULL,
+		0),
+	SND_SOC_DAPM_SUPPLY_S("DMIC MONO R ASRC", 1, RT5677_ASRC_2, 6, 0, NULL,
+		0),
+	SND_SOC_DAPM_SUPPLY_S("ADC STO1 ASRC", 1, RT5677_ASRC_2, 5, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY_S("ADC STO2 ASRC", 1, RT5677_ASRC_2, 4, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY_S("ADC STO3 ASRC", 1, RT5677_ASRC_2, 3, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY_S("ADC STO4 ASRC", 1, RT5677_ASRC_2, 2, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY_S("ADC MONO L ASRC", 1, RT5677_ASRC_2, 1, 0, NULL,
+		0),
+	SND_SOC_DAPM_SUPPLY_S("ADC MONO R ASRC", 1, RT5677_ASRC_2, 0, 0, NULL,
+		0),
+
 	/* Input Side */
 	/* micbias */
 	SND_SOC_DAPM_SUPPLY("MICBIAS1", RT5677_PWR_ANLG2, RT5677_PWR_MB1_BIT,
@@ -2656,10 +2786,18 @@
 	/* DAC Mixer */
 	SND_SOC_DAPM_SUPPLY("dac stereo1 filter", RT5677_PWR_DIG2,
 		RT5677_PWR_DAC_S1F_BIT, 0, NULL, 0),
-	SND_SOC_DAPM_SUPPLY("dac mono left filter", RT5677_PWR_DIG2,
+	SND_SOC_DAPM_SUPPLY("dac mono2 left filter", RT5677_PWR_DIG2,
 		RT5677_PWR_DAC_M2F_L_BIT, 0, NULL, 0),
-	SND_SOC_DAPM_SUPPLY("dac mono right filter", RT5677_PWR_DIG2,
+	SND_SOC_DAPM_SUPPLY("dac mono2 right filter", RT5677_PWR_DIG2,
 		RT5677_PWR_DAC_M2F_R_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("dac mono3 left filter", RT5677_PWR_DIG2,
+		RT5677_PWR_DAC_M3F_L_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("dac mono3 right filter", RT5677_PWR_DIG2,
+		RT5677_PWR_DAC_M3F_R_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("dac mono4 left filter", RT5677_PWR_DIG2,
+		RT5677_PWR_DAC_M4F_L_BIT, 0, NULL, 0),
+	SND_SOC_DAPM_SUPPLY("dac mono4 right filter", RT5677_PWR_DIG2,
+		RT5677_PWR_DAC_M4F_R_BIT, 0, NULL, 0),
 
 	SND_SOC_DAPM_MIXER("Stereo DAC MIXL", SND_SOC_NOPM, 0, 0,
 		rt5677_sto1_dac_l_mix, ARRAY_SIZE(rt5677_sto1_dac_l_mix)),
@@ -2732,6 +2870,31 @@
 };
 
 static const struct snd_soc_dapm_route rt5677_dapm_routes[] = {
+	{ "Stereo1 DMIC Mux", NULL, "DMIC STO1 ASRC", can_use_asrc },
+	{ "Stereo2 DMIC Mux", NULL, "DMIC STO2 ASRC", can_use_asrc },
+	{ "Stereo3 DMIC Mux", NULL, "DMIC STO3 ASRC", can_use_asrc },
+	{ "Stereo4 DMIC Mux", NULL, "DMIC STO4 ASRC", can_use_asrc },
+	{ "Mono DMIC L Mux", NULL, "DMIC MONO L ASRC", can_use_asrc },
+	{ "Mono DMIC R Mux", NULL, "DMIC MONO R ASRC", can_use_asrc },
+	{ "I2S1", NULL, "I2S1 ASRC", can_use_asrc},
+	{ "I2S2", NULL, "I2S2 ASRC", can_use_asrc},
+	{ "I2S3", NULL, "I2S3 ASRC", can_use_asrc},
+	{ "I2S4", NULL, "I2S4 ASRC", can_use_asrc},
+
+	{ "dac stereo1 filter", NULL, "DAC STO ASRC", is_using_asrc },
+	{ "dac mono2 left filter", NULL, "DAC MONO2 L ASRC", is_using_asrc },
+	{ "dac mono2 right filter", NULL, "DAC MONO2 R ASRC", is_using_asrc },
+	{ "dac mono3 left filter", NULL, "DAC MONO3 L ASRC", is_using_asrc },
+	{ "dac mono3 right filter", NULL, "DAC MONO3 R ASRC", is_using_asrc },
+	{ "dac mono4 left filter", NULL, "DAC MONO4 L ASRC", is_using_asrc },
+	{ "dac mono4 right filter", NULL, "DAC MONO4 R ASRC", is_using_asrc },
+	{ "adc stereo1 filter", NULL, "ADC STO1 ASRC", is_using_asrc },
+	{ "adc stereo2 filter", NULL, "ADC STO2 ASRC", is_using_asrc },
+	{ "adc stereo3 filter", NULL, "ADC STO3 ASRC", is_using_asrc },
+	{ "adc stereo4 filter", NULL, "ADC STO4 ASRC", is_using_asrc },
+	{ "adc mono left filter", NULL, "ADC MONO L ASRC", is_using_asrc },
+	{ "adc mono right filter", NULL, "ADC MONO R ASRC", is_using_asrc },
+
 	{ "DMIC1", NULL, "DMIC L1" },
 	{ "DMIC1", NULL, "DMIC R1" },
 	{ "DMIC2", NULL, "DMIC L2" },
@@ -2862,8 +3025,6 @@
 
 	{ "Stereo1 ADC MIXL", NULL, "Sto1 ADC MIXL" },
 	{ "Stereo1 ADC MIXL", NULL, "adc stereo1 filter" },
-	{ "adc stereo1 filter", NULL, "PLL1", is_sys_clk_from_pll },
-
 	{ "Stereo1 ADC MIXR", NULL, "Sto1 ADC MIXR" },
 	{ "Stereo1 ADC MIXR", NULL, "adc stereo1 filter" },
 	{ "adc stereo1 filter", NULL, "PLL1", is_sys_clk_from_pll },
@@ -2884,8 +3045,6 @@
 
 	{ "Stereo2 ADC MIXL", NULL, "Stereo2 ADC LR Mux" },
 	{ "Stereo2 ADC MIXL", NULL, "adc stereo2 filter" },
-	{ "adc stereo2 filter", NULL, "PLL1", is_sys_clk_from_pll },
-
 	{ "Stereo2 ADC MIXR", NULL, "Sto2 ADC MIXR" },
 	{ "Stereo2 ADC MIXR", NULL, "adc stereo2 filter" },
 	{ "adc stereo2 filter", NULL, "PLL1", is_sys_clk_from_pll },
@@ -2900,8 +3059,6 @@
 
 	{ "Stereo3 ADC MIXL", NULL, "Sto3 ADC MIXL" },
 	{ "Stereo3 ADC MIXL", NULL, "adc stereo3 filter" },
-	{ "adc stereo3 filter", NULL, "PLL1", is_sys_clk_from_pll },
-
 	{ "Stereo3 ADC MIXR", NULL, "Sto3 ADC MIXR" },
 	{ "Stereo3 ADC MIXR", NULL, "adc stereo3 filter" },
 	{ "adc stereo3 filter", NULL, "PLL1", is_sys_clk_from_pll },
@@ -2916,8 +3073,6 @@
 
 	{ "Stereo4 ADC MIXL", NULL, "Sto4 ADC MIXL" },
 	{ "Stereo4 ADC MIXL", NULL, "adc stereo4 filter" },
-	{ "adc stereo4 filter", NULL, "PLL1", is_sys_clk_from_pll },
-
 	{ "Stereo4 ADC MIXR", NULL, "Sto4 ADC MIXR" },
 	{ "Stereo4 ADC MIXR", NULL, "adc stereo4 filter" },
 	{ "adc stereo4 filter", NULL, "PLL1", is_sys_clk_from_pll },
@@ -3466,10 +3621,8 @@
 
 	{ "DAC1 MIXL", "Stereo ADC Switch", "ADDA1 Mux" },
 	{ "DAC1 MIXL", "DAC1 Switch", "DAC1 Mux" },
-	{ "DAC1 MIXL", NULL, "dac stereo1 filter" },
 	{ "DAC1 MIXR", "Stereo ADC Switch", "ADDA1 Mux" },
 	{ "DAC1 MIXR", "DAC1 Switch", "DAC1 Mux" },
-	{ "DAC1 MIXR", NULL, "dac stereo1 filter" },
 
 	{ "DAC1 FS", NULL, "DAC1 MIXL" },
 	{ "DAC1 FS", NULL, "DAC1 MIXR" },
@@ -3536,35 +3689,46 @@
 	{ "Stereo DAC MIXR", "DAC2 R Switch", "DAC2 R Mux" },
 	{ "Stereo DAC MIXR", "DAC1 L Switch", "DAC1 MIXL" },
 	{ "Stereo DAC MIXR", NULL, "dac stereo1 filter" },
+	{ "dac stereo1 filter", NULL, "PLL1", is_sys_clk_from_pll },
 
 	{ "Mono DAC MIXL", "ST L Switch", "Sidetone Mux" },
 	{ "Mono DAC MIXL", "DAC1 L Switch", "DAC1 MIXL" },
 	{ "Mono DAC MIXL", "DAC2 L Switch", "DAC2 L Mux" },
 	{ "Mono DAC MIXL", "DAC2 R Switch", "DAC2 R Mux" },
-	{ "Mono DAC MIXL", NULL, "dac mono left filter" },
+	{ "Mono DAC MIXL", NULL, "dac mono2 left filter" },
+	{ "dac mono2 left filter", NULL, "PLL1", is_sys_clk_from_pll },
 	{ "Mono DAC MIXR", "ST R Switch", "Sidetone Mux" },
 	{ "Mono DAC MIXR", "DAC1 R Switch", "DAC1 MIXR" },
 	{ "Mono DAC MIXR", "DAC2 R Switch", "DAC2 R Mux" },
 	{ "Mono DAC MIXR", "DAC2 L Switch", "DAC2 L Mux" },
-	{ "Mono DAC MIXR", NULL, "dac mono right filter" },
+	{ "Mono DAC MIXR", NULL, "dac mono2 right filter" },
+	{ "dac mono2 right filter", NULL, "PLL1", is_sys_clk_from_pll },
 
 	{ "DD1 MIXL", "Sto DAC Mix L Switch", "Stereo DAC MIXL" },
 	{ "DD1 MIXL", "Mono DAC Mix L Switch", "Mono DAC MIXL" },
 	{ "DD1 MIXL", "DAC3 L Switch", "DAC3 L Mux" },
 	{ "DD1 MIXL", "DAC3 R Switch", "DAC3 R Mux" },
+	{ "DD1 MIXL", NULL, "dac mono3 left filter" },
+	{ "dac mono3 left filter", NULL, "PLL1", is_sys_clk_from_pll },
 	{ "DD1 MIXR", "Sto DAC Mix R Switch", "Stereo DAC MIXR" },
 	{ "DD1 MIXR", "Mono DAC Mix R Switch", "Mono DAC MIXR" },
 	{ "DD1 MIXR", "DAC3 L Switch", "DAC3 L Mux" },
 	{ "DD1 MIXR", "DAC3 R Switch", "DAC3 R Mux" },
+	{ "DD1 MIXR", NULL, "dac mono3 right filter" },
+	{ "dac mono3 right filter", NULL, "PLL1", is_sys_clk_from_pll },
 
 	{ "DD2 MIXL", "Sto DAC Mix L Switch", "Stereo DAC MIXL" },
 	{ "DD2 MIXL", "Mono DAC Mix L Switch", "Mono DAC MIXL" },
 	{ "DD2 MIXL", "DAC4 L Switch", "DAC4 L Mux" },
 	{ "DD2 MIXL", "DAC4 R Switch", "DAC4 R Mux" },
+	{ "DD2 MIXL", NULL, "dac mono4 left filter" },
+	{ "dac mono4 left filter", NULL, "PLL1", is_sys_clk_from_pll },
 	{ "DD2 MIXR", "Sto DAC Mix R Switch", "Stereo DAC MIXR" },
 	{ "DD2 MIXR", "Mono DAC Mix R Switch", "Mono DAC MIXR" },
 	{ "DD2 MIXR", "DAC4 L Switch", "DAC4 L Mux" },
 	{ "DD2 MIXR", "DAC4 R Switch", "DAC4 R Mux" },
+	{ "DD2 MIXR", NULL, "dac mono4 right filter" },
+	{ "dac mono4 right filter", NULL, "PLL1", is_sys_clk_from_pll },
 
 	{ "Stereo DAC MIX", NULL, "Stereo DAC MIXL" },
 	{ "Stereo DAC MIX", NULL, "Stereo DAC MIXR" },
@@ -3586,11 +3750,8 @@
 	{ "DAC3 SRC Mux", "DD MIX2L", "DD2 MIXL" },
 
 	{ "DAC 1", NULL, "DAC12 SRC Mux" },
-	{ "DAC 1", NULL, "PLL1", is_sys_clk_from_pll },
 	{ "DAC 2", NULL, "DAC12 SRC Mux" },
-	{ "DAC 2", NULL, "PLL1", is_sys_clk_from_pll },
 	{ "DAC 3", NULL, "DAC3 SRC Mux" },
-	{ "DAC 3", NULL, "PLL1", is_sys_clk_from_pll },
 
 	{ "PDM1 L Mux", "STO1 DAC MIX", "Stereo DAC MIXL" },
 	{ "PDM1 L Mux", "MONO DAC MIX", "Mono DAC MIXL" },
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c
index f6847fd..eb0a164 100644
--- a/sound/soc/codecs/wm8750.c
+++ b/sound/soc/codecs/wm8750.c
@@ -323,7 +323,7 @@
 	SND_SOC_DAPM_OUTPUT("ROUT2"),
 	SND_SOC_DAPM_OUTPUT("MONO1"),
 	SND_SOC_DAPM_OUTPUT("OUT3"),
-	SND_SOC_DAPM_OUTPUT("VREF"),
+	SND_SOC_DAPM_VMID("VREF"),
 
 	SND_SOC_DAPM_INPUT("LINPUT1"),
 	SND_SOC_DAPM_INPUT("LINPUT2"),
diff --git a/sound/soc/dwc/designware_i2s.c b/sound/soc/dwc/designware_i2s.c
index 8d18bbd..06d3a34 100644
--- a/sound/soc/dwc/designware_i2s.c
+++ b/sound/soc/dwc/designware_i2s.c
@@ -335,13 +335,47 @@
 #define dw_i2s_resume	NULL
 #endif
 
+static void dw_configure_dai_by_pd(struct dw_i2s_dev *dev,
+				   struct snd_soc_dai_driver *dw_i2s_dai,
+				   struct resource *res,
+				   const struct i2s_platform_data *pdata)
+{
+	/* Set DMA slaves info */
+
+	dev->play_dma_data.data = pdata->play_dma_data;
+	dev->capture_dma_data.data = pdata->capture_dma_data;
+	dev->play_dma_data.addr = res->start + I2S_TXDMA;
+	dev->capture_dma_data.addr = res->start + I2S_RXDMA;
+	dev->play_dma_data.max_burst = 16;
+	dev->capture_dma_data.max_burst = 16;
+	dev->play_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+	dev->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+	dev->play_dma_data.filter = pdata->filter;
+	dev->capture_dma_data.filter = pdata->filter;
+
+	if (pdata->cap & DWC_I2S_PLAY) {
+		dev_dbg(dev->dev, " designware: play supported\n");
+		dw_i2s_dai->playback.channels_min = MIN_CHANNEL_NUM;
+		dw_i2s_dai->playback.channels_max = pdata->channel;
+		dw_i2s_dai->playback.formats = pdata->snd_fmts;
+		dw_i2s_dai->playback.rates = pdata->snd_rates;
+	}
+
+	if (pdata->cap & DWC_I2S_RECORD) {
+		dev_dbg(dev->dev, "designware: record supported\n");
+		dw_i2s_dai->capture.channels_min = MIN_CHANNEL_NUM;
+		dw_i2s_dai->capture.channels_max = pdata->channel;
+		dw_i2s_dai->capture.formats = pdata->snd_fmts;
+		dw_i2s_dai->capture.rates = pdata->snd_rates;
+	}
+}
+
 static int dw_i2s_probe(struct platform_device *pdev)
 {
 	const struct i2s_platform_data *pdata = pdev->dev.platform_data;
 	struct dw_i2s_dev *dev;
 	struct resource *res;
 	int ret;
-	unsigned int cap;
 	struct snd_soc_dai_driver *dw_i2s_dai;
 
 	if (!pdata) {
@@ -356,44 +390,23 @@
 	}
 
 	dw_i2s_dai = devm_kzalloc(&pdev->dev, sizeof(*dw_i2s_dai), GFP_KERNEL);
-	if (!dw_i2s_dai) {
-		dev_err(&pdev->dev, "mem allocation failed for dai driver\n");
+	if (!dw_i2s_dai)
 		return -ENOMEM;
-	}
 
 	dw_i2s_dai->ops = &dw_i2s_dai_ops;
 	dw_i2s_dai->suspend = dw_i2s_suspend;
 	dw_i2s_dai->resume = dw_i2s_resume;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(&pdev->dev, "no i2s resource defined\n");
-		return -ENODEV;
-	}
-
 	dev->i2s_base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(dev->i2s_base)) {
-		dev_err(&pdev->dev, "ioremap fail for i2s_region\n");
+	if (IS_ERR(dev->i2s_base))
 		return PTR_ERR(dev->i2s_base);
-	}
 
-	cap = pdata->cap;
-	dev->capability = cap;
+	dev->dev = &pdev->dev;
+	dw_configure_dai_by_pd(dev, dw_i2s_dai, res, pdata);
+
+	dev->capability = pdata->cap;
 	dev->i2s_clk_cfg = pdata->i2s_clk_cfg;
-
-	/* Set DMA slaves info */
-
-	dev->play_dma_data.data = pdata->play_dma_data;
-	dev->capture_dma_data.data = pdata->capture_dma_data;
-	dev->play_dma_data.addr = res->start + I2S_TXDMA;
-	dev->capture_dma_data.addr = res->start + I2S_RXDMA;
-	dev->play_dma_data.max_burst = 16;
-	dev->capture_dma_data.max_burst = 16;
-	dev->play_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
-	dev->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
-	dev->play_dma_data.filter = pdata->filter;
-	dev->capture_dma_data.filter = pdata->filter;
-
 	dev->clk = clk_get(&pdev->dev, NULL);
 	if (IS_ERR(dev->clk))
 		return  PTR_ERR(dev->clk);
@@ -402,23 +415,6 @@
 	if (ret < 0)
 		goto err_clk_put;
 
-	if (cap & DWC_I2S_PLAY) {
-		dev_dbg(&pdev->dev, " designware: play supported\n");
-		dw_i2s_dai->playback.channels_min = MIN_CHANNEL_NUM;
-		dw_i2s_dai->playback.channels_max = pdata->channel;
-		dw_i2s_dai->playback.formats = pdata->snd_fmts;
-		dw_i2s_dai->playback.rates = pdata->snd_rates;
-	}
-
-	if (cap & DWC_I2S_RECORD) {
-		dev_dbg(&pdev->dev, "designware: record supported\n");
-		dw_i2s_dai->capture.channels_min = MIN_CHANNEL_NUM;
-		dw_i2s_dai->capture.channels_max = pdata->channel;
-		dw_i2s_dai->capture.formats = pdata->snd_fmts;
-		dw_i2s_dai->capture.rates = pdata->snd_rates;
-	}
-
-	dev->dev = &pdev->dev;
 	dev_set_drvdata(&pdev->dev, dev);
 	ret = snd_soc_register_component(&pdev->dev, &dw_i2s_component,
 					 dw_i2s_dai, 1);
diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig
index f86de12..c0813f5 100644
--- a/sound/soc/intel/Kconfig
+++ b/sound/soc/intel/Kconfig
@@ -46,7 +46,7 @@
 
 config SND_SOC_INTEL_HASWELL_MACH
 	tristate "ASoC Audio DSP support for Intel Haswell Lynxpoint"
-	depends on SND_SOC_INTEL_SST && X86_INTEL_LPSS && I2C && \\
+	depends on SND_SOC_INTEL_SST && X86_INTEL_LPSS && I2C && \
 		   I2C_DESIGNWARE_PLATFORM
 	select SND_SOC_INTEL_HASWELL
 	select SND_SOC_RT5640
@@ -76,7 +76,7 @@
 
 config SND_SOC_INTEL_BROADWELL_MACH
 	tristate "ASoC Audio DSP support for Intel Broadwell Wildcatpoint"
-	depends on SND_SOC_INTEL_SST && X86_INTEL_LPSS && DW_DMAC && \\
+	depends on SND_SOC_INTEL_SST && X86_INTEL_LPSS && DW_DMAC && \
 		   I2C_DESIGNWARE_PLATFORM
 	select SND_SOC_INTEL_HASWELL
 	select SND_COMPRESS_OFFLOAD
diff --git a/sound/soc/intel/bytcr_dpcm_rt5640.c b/sound/soc/intel/bytcr_dpcm_rt5640.c
index eef0c56..5930862 100644
--- a/sound/soc/intel/bytcr_dpcm_rt5640.c
+++ b/sound/soc/intel/bytcr_dpcm_rt5640.c
@@ -215,7 +215,6 @@
 
 static struct platform_driver snd_byt_mc_driver = {
 	.driver = {
-		.owner = THIS_MODULE,
 		.name = "bytt100_rt5640",
 		.pm = &snd_soc_pm_ops,
 	},
diff --git a/sound/soc/intel/cht_bsw_rt5672.c b/sound/soc/intel/cht_bsw_rt5672.c
index 9b8b561..a406c610 100644
--- a/sound/soc/intel/cht_bsw_rt5672.c
+++ b/sound/soc/intel/cht_bsw_rt5672.c
@@ -270,7 +270,6 @@
 
 static struct platform_driver snd_cht_mc_driver = {
 	.driver = {
-		.owner = THIS_MODULE,
 		.name = "cht-bsw-rt5672",
 		.pm = &snd_soc_pm_ops,
 	},
diff --git a/sound/soc/intel/sst-firmware.c b/sound/soc/intel/sst-firmware.c
index b3f9489..a2ae2c5 100644
--- a/sound/soc/intel/sst-firmware.c
+++ b/sound/soc/intel/sst-firmware.c
@@ -497,6 +497,7 @@
 	sst_module->sst_fw = sst_fw;
 	sst_module->scratch_size = template->scratch_size;
 	sst_module->persistent_size = template->persistent_size;
+	sst_module->entry = template->entry;
 
 	INIT_LIST_HEAD(&sst_module->block_list);
 	INIT_LIST_HEAD(&sst_module->runtime_list);
diff --git a/sound/soc/intel/sst/sst_acpi.c b/sound/soc/intel/sst/sst_acpi.c
index 2ac72eb..c3fbcde 100644
--- a/sound/soc/intel/sst/sst_acpi.c
+++ b/sound/soc/intel/sst/sst_acpi.c
@@ -245,7 +245,7 @@
 	return NULL;
 }
 
-int sst_acpi_probe(struct platform_device *pdev)
+static int sst_acpi_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	int ret = 0;
@@ -332,7 +332,7 @@
 * This function is called by OS when a device is unloaded
 * This frees the interrupt etc
 */
-int sst_acpi_remove(struct platform_device *pdev)
+static int sst_acpi_remove(struct platform_device *pdev)
 {
 	struct intel_sst_drv *ctx;
 
@@ -366,7 +366,6 @@
 static struct platform_driver sst_acpi_driver = {
 	.driver = {
 		.name			= "intel_sst_acpi",
-		.owner			= THIS_MODULE,
 		.acpi_match_table	= ACPI_PTR(sst_acpi_ids),
 		.pm			= &intel_sst_pm,
 	},
diff --git a/sound/soc/omap/omap-hdmi-audio.c b/sound/soc/omap/omap-hdmi-audio.c
index 3f9ac7d..ccfb41c 100644
--- a/sound/soc/omap/omap-hdmi-audio.c
+++ b/sound/soc/omap/omap-hdmi-audio.c
@@ -393,7 +393,6 @@
 static struct platform_driver hdmi_audio_driver = {
 	.driver = {
 		.name = DRV_NAME,
-		.owner = THIS_MODULE,
 	},
 	.probe = omap_hdmi_audio_probe,
 	.remove = omap_hdmi_audio_remove,
diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c
index d7d5fb2..a6d680a 100644
--- a/sound/soc/pxa/spitz.c
+++ b/sound/soc/pxa/spitz.c
@@ -352,7 +352,6 @@
 static struct platform_driver spitz_driver = {
 	.driver		= {
 		.name	= "spitz-audio",
-		.owner	= THIS_MODULE,
 		.pm     = &snd_soc_pm_ops,
 	},
 	.probe		= spitz_probe,
diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c
index dcc26ed..acb5be5 100644
--- a/sound/soc/rockchip/rockchip_i2s.c
+++ b/sound/soc/rockchip/rockchip_i2s.c
@@ -247,6 +247,10 @@
 
 	regmap_update_bits(i2s->regmap, I2S_TXCR, I2S_TXCR_VDW_MASK, val);
 	regmap_update_bits(i2s->regmap, I2S_RXCR, I2S_RXCR_VDW_MASK, val);
+	regmap_update_bits(i2s->regmap, I2S_DMACR, I2S_DMACR_TDL_MASK,
+			   I2S_DMACR_TDL(16));
+	regmap_update_bits(i2s->regmap, I2S_DMACR, I2S_DMACR_RDL_MASK,
+			   I2S_DMACR_RDL(16));
 
 	return 0;
 }
diff --git a/sound/soc/samsung/arndale_rt5631.c b/sound/soc/samsung/arndale_rt5631.c
index 1e2b61c..8bf2e2c 100644
--- a/sound/soc/samsung/arndale_rt5631.c
+++ b/sound/soc/samsung/arndale_rt5631.c
@@ -135,7 +135,6 @@
 static struct platform_driver arndale_audio_driver = {
 	.driver = {
 		.name   = "arndale-audio",
-		.owner  = THIS_MODULE,
 		.pm = &snd_soc_pm_ops,
 		.of_match_table = of_match_ptr(samsung_arndale_rt5631_of_match),
 	},
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 2c62620..c024962 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -1626,9 +1626,6 @@
 		}
 	}
 
-	if (card->fully_routed)
-		snd_soc_dapm_auto_nc_pins(card);
-
 	snd_soc_dapm_new_widgets(card);
 
 	ret = snd_card_register(card->snd_card);
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index c5136bb..ea49684 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -2279,6 +2279,9 @@
 
 	switch (w->id) {
 	case snd_soc_dapm_input:
+		/* On a fully routed card a input is never a source */
+		if (w->dapm->card->fully_routed)
+			break;
 		w->is_source = 1;
 		list_for_each_entry(p, &w->sources, list_sink) {
 			if (p->source->id == snd_soc_dapm_micbias ||
@@ -2291,6 +2294,9 @@
 		}
 		break;
 	case snd_soc_dapm_output:
+		/* On a fully routed card a output is never a sink */
+		if (w->dapm->card->fully_routed)
+			break;
 		w->is_sink = 1;
 		list_for_each_entry(p, &w->sinks, list_source) {
 			if (p->sink->id == snd_soc_dapm_spk ||
@@ -3085,16 +3091,24 @@
 
 	switch (w->id) {
 	case snd_soc_dapm_mic:
-	case snd_soc_dapm_input:
 		w->is_source = 1;
 		w->power_check = dapm_generic_check_power;
 		break;
+	case snd_soc_dapm_input:
+		if (!dapm->card->fully_routed)
+			w->is_source = 1;
+		w->power_check = dapm_generic_check_power;
+		break;
 	case snd_soc_dapm_spk:
 	case snd_soc_dapm_hp:
-	case snd_soc_dapm_output:
 		w->is_sink = 1;
 		w->power_check = dapm_generic_check_power;
 		break;
+	case snd_soc_dapm_output:
+		if (!dapm->card->fully_routed)
+			w->is_sink = 1;
+		w->power_check = dapm_generic_check_power;
+		break;
 	case snd_soc_dapm_vmid:
 	case snd_soc_dapm_siggen:
 		w->is_source = 1;
@@ -3809,93 +3823,6 @@
 EXPORT_SYMBOL_GPL(snd_soc_dapm_ignore_suspend);
 
 /**
- * dapm_is_external_path() - Checks if a path is a external path
- * @card: The card the path belongs to
- * @path: The path to check
- *
- * Returns true if the path is either between two different DAPM contexts or
- * between two external pins of the same DAPM context. Otherwise returns
- * false.
- */
-static bool dapm_is_external_path(struct snd_soc_card *card,
-	struct snd_soc_dapm_path *path)
-{
-	dev_dbg(card->dev,
-		"... Path %s(id:%d dapm:%p) - %s(id:%d dapm:%p)\n",
-		path->source->name, path->source->id, path->source->dapm,
-		path->sink->name, path->sink->id, path->sink->dapm);
-
-	/* Connection between two different DAPM contexts */
-	if (path->source->dapm != path->sink->dapm)
-		return true;
-
-	/* Loopback connection from external pin to external pin */
-	if (path->sink->id == snd_soc_dapm_input) {
-		switch (path->source->id) {
-		case snd_soc_dapm_output:
-		case snd_soc_dapm_micbias:
-			return true;
-		default:
-			break;
-		}
-	}
-
-	return false;
-}
-
-static bool snd_soc_dapm_widget_in_card_paths(struct snd_soc_card *card,
-					      struct snd_soc_dapm_widget *w)
-{
-	struct snd_soc_dapm_path *p;
-
-	list_for_each_entry(p, &w->sources, list_sink) {
-		if (dapm_is_external_path(card, p))
-			return true;
-	}
-
-	list_for_each_entry(p, &w->sinks, list_source) {
-		if (dapm_is_external_path(card, p))
-			return true;
-	}
-
-	return false;
-}
-
-/**
- * snd_soc_dapm_auto_nc_pins - call snd_soc_dapm_nc_pin for unused pins
- * @card: The card whose pins should be processed
- *
- * Automatically call snd_soc_dapm_nc_pin() for any external pins in the card
- * which are unused. Pins are used if they are connected externally to a
- * component, whether that be to some other device, or a loop-back connection to
- * the component itself.
- */
-void snd_soc_dapm_auto_nc_pins(struct snd_soc_card *card)
-{
-	struct snd_soc_dapm_widget *w;
-
-	dev_dbg(card->dev, "ASoC: Auto NC: DAPMs: card:%p\n", &card->dapm);
-
-	list_for_each_entry(w, &card->widgets, list) {
-		switch (w->id) {
-		case snd_soc_dapm_input:
-		case snd_soc_dapm_output:
-		case snd_soc_dapm_micbias:
-			dev_dbg(card->dev, "ASoC: Auto NC: Checking widget %s\n",
-				w->name);
-			if (!snd_soc_dapm_widget_in_card_paths(card, w)) {
-				dev_dbg(card->dev,
-					"... Not in map; disabling\n");
-				snd_soc_dapm_nc_pin(w->dapm, w->name);
-			}
-			break;
-		default:
-			break;
-		}
-	}
-}
-
-/**
  * snd_soc_dapm_free - free dapm resources
  * @dapm: DAPM context
  *
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index eb87d96e2..6b0136e 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -301,34 +301,18 @@
 	return symmetry;
 }
 
-/*
- * List of sample sizes that might go over the bus for parameter
- * application.  There ought to be a wildcard sample size for things
- * like the DAC/ADC resolution to use but there isn't right now.
- */
-static int sample_sizes[] = {
-	24, 32,
-};
-
 static void soc_pcm_set_msb(struct snd_pcm_substream *substream, int bits)
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	int ret, i;
+	int ret;
 
 	if (!bits)
 		return;
 
-	for (i = 0; i < ARRAY_SIZE(sample_sizes); i++) {
-		if (bits >= sample_sizes[i])
-			continue;
-
-		ret = snd_pcm_hw_constraint_msbits(substream->runtime, 0,
-						   sample_sizes[i], bits);
-		if (ret != 0)
-			dev_warn(rtd->dev,
-				 "ASoC: Failed to set MSB %d/%d: %d\n",
-				 bits, sample_sizes[i], ret);
-	}
+	ret = snd_pcm_hw_constraint_msbits(substream->runtime, 0, 0, bits);
+	if (ret != 0)
+		dev_warn(rtd->dev, "ASoC: Failed to set MSB %d: %d\n",
+				 bits, ret);
 }
 
 static void soc_pcm_apply_msb(struct snd_pcm_substream *substream)
@@ -746,7 +730,8 @@
 							      codec_dai);
 			if (ret < 0) {
 				dev_err(codec_dai->dev,
-					"ASoC: DAI prepare error: %d\n", ret);
+					"ASoC: codec DAI prepare error: %d\n",
+					ret);
 				goto out;
 			}
 		}
@@ -755,8 +740,8 @@
 	if (cpu_dai->driver->ops && cpu_dai->driver->ops->prepare) {
 		ret = cpu_dai->driver->ops->prepare(substream, cpu_dai);
 		if (ret < 0) {
-			dev_err(cpu_dai->dev, "ASoC: DAI prepare error: %d\n",
-				ret);
+			dev_err(cpu_dai->dev,
+				"ASoC: cpu DAI prepare error: %d\n", ret);
 			goto out;
 		}
 	}
diff --git a/sound/sparc/amd7930.c b/sound/sparc/amd7930.c
index 86280d6..1b1a89e 100644
--- a/sound/sparc/amd7930.c
+++ b/sound/sparc/amd7930.c
@@ -37,6 +37,7 @@
 #include <linux/moduleparam.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/io.h>
 
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -44,7 +45,6 @@
 #include <sound/control.h>
 #include <sound/initval.h>
 
-#include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/prom.h>
 
diff --git a/sound/synth/emux/emux.c b/sound/synth/emux/emux.c
index 9352207..4919532 100644
--- a/sound/synth/emux/emux.c
+++ b/sound/synth/emux/emux.c
@@ -53,9 +53,7 @@
 	emu->max_voices = 0;
 	emu->use_time = 0;
 
-	init_timer(&emu->tlist);
-	emu->tlist.function = snd_emux_timer_callback;
-	emu->tlist.data = (unsigned long)emu;
+	setup_timer(&emu->tlist, snd_emux_timer_callback, (unsigned long)emu);
 	emu->timer_active = 0;
 
 	*remu = emu;
@@ -160,12 +158,8 @@
 	snd_emux_detach_seq_oss(emu);
 #endif
 	snd_emux_detach_seq(emu);
-
 	snd_emux_delete_hwdep(emu);
-
-	if (emu->sflist)
-		snd_sf_free(emu->sflist);
-
+	snd_sf_free(emu->sflist);
 	kfree(emu->voices);
 	kfree(emu->name);
 	kfree(emu);
diff --git a/sound/synth/emux/emux_hwdep.c b/sound/synth/emux/emux_hwdep.c
index 5ae1eae..e557946 100644
--- a/sound/synth/emux/emux_hwdep.c
+++ b/sound/synth/emux/emux_hwdep.c
@@ -21,7 +21,7 @@
 
 #include <sound/core.h>
 #include <sound/hwdep.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include "emux_voice.h"
 
 
diff --git a/sound/synth/emux/emux_oss.c b/sound/synth/emux/emux_oss.c
index 319754c..ab37add 100644
--- a/sound/synth/emux/emux_oss.c
+++ b/sound/synth/emux/emux_oss.c
@@ -26,7 +26,7 @@
 #ifdef CONFIG_SND_SEQUENCER_OSS
 
 #include <linux/export.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <sound/core.h>
 #include "emux_voice.h"
 #include <sound/asoundef.h>
diff --git a/sound/synth/emux/emux_synth.c b/sound/synth/emux/emux_synth.c
index 9a38de4..599551b 100644
--- a/sound/synth/emux/emux_synth.c
+++ b/sound/synth/emux/emux_synth.c
@@ -186,8 +186,7 @@
 				 */
 				vp->state = SNDRV_EMUX_ST_PENDING;
 				if (! emu->timer_active) {
-					emu->tlist.expires = jiffies + 1;
-					add_timer(&emu->tlist);
+					mod_timer(&emu->tlist, jiffies + 1);
 					emu->timer_active = 1;
 				}
 			} else
@@ -223,8 +222,7 @@
 		}
 	}
 	if (do_again) {
-		emu->tlist.expires = jiffies + 1;
-		add_timer(&emu->tlist);
+		mod_timer(&emu->tlist, jiffies + 1);
 		emu->timer_active = 1;
 	} else
 		emu->timer_active = 0;
diff --git a/sound/synth/emux/soundfont.c b/sound/synth/emux/soundfont.c
index 78683b2..31a4ea9 100644
--- a/sound/synth/emux/soundfont.c
+++ b/sound/synth/emux/soundfont.c
@@ -25,7 +25,7 @@
  * of doing things so that the old sfxload utility can be used.
  * Everything may change when there is an alsa way of doing things.
  */
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/slab.h>
 #include <linux/export.h>
 #include <sound/core.h>
diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig
index d393153..a452ad7 100644
--- a/sound/usb/Kconfig
+++ b/sound/usb/Kconfig
@@ -160,5 +160,7 @@
 	  To compile this driver as a module, choose M here: the module
 	  will be called snd-bcd2000.
 
+source "sound/usb/line6/Kconfig"
+
 endif	# SND_USB
 
diff --git a/sound/usb/Makefile b/sound/usb/Makefile
index bcee406..2d2d122 100644
--- a/sound/usb/Makefile
+++ b/sound/usb/Makefile
@@ -25,3 +25,4 @@
 obj-$(CONFIG_SND_USB_US122L) += snd-usbmidi-lib.o
 
 obj-$(CONFIG_SND) += misc/ usx2y/ caiaq/ 6fire/ hiface/ bcd2000/
+obj-$(CONFIG_SND_USB_LINE6)	+= line6/
diff --git a/sound/usb/line6/Kconfig b/sound/usb/line6/Kconfig
new file mode 100644
index 0000000..f4585d37
--- /dev/null
+++ b/sound/usb/line6/Kconfig
@@ -0,0 +1,42 @@
+config SND_USB_LINE6
+	tristate
+	select SND_RAWMIDI
+	select SND_PCM
+
+config SND_USB_POD
+	tristate "Line 6 POD USB support"
+	select SND_USB_LINE6
+	help
+	  This is a driver for PODxt and other similar devices,
+	  supporting the following features:
+	    * Reading/writing individual parameters
+	    * Reading/writing complete channel, effects setup, and amp
+	      setup data
+	    * Channel switching
+	    * Virtual MIDI interface
+	    * Tuner access
+	    * Playback/capture/mixer device for any ALSA-compatible PCM
+	      audio application
+	    * Signal routing (record clean/processed guitar signal,
+	      re-amping)
+
+config SND_USB_PODHD
+	tristate "Line 6 POD HD300/400/500 USB support"
+	select SND_USB_LINE6
+	help
+	  This is a driver for POD HD300, 400 and 500 devices.
+
+config SND_USB_TONEPORT
+	tristate "TonePort GX, UX1 and UX2 USB support"
+	select SND_USB_LINE6
+	select NEW_LEDS
+	select LEDS_CLASS
+	help
+	  This is a driver for TonePort GX, UX1 and UX2 devices.
+
+config SND_USB_VARIAX
+	tristate "Variax Workbench USB support"
+	select SND_USB_LINE6
+	help
+	  This is a driver for Variax Workbench device.
+
diff --git a/sound/usb/line6/Makefile b/sound/usb/line6/Makefile
new file mode 100644
index 0000000..b8b3b2a
--- /dev/null
+++ b/sound/usb/line6/Makefile
@@ -0,0 +1,18 @@
+snd-usb-line6-y := 		\
+		capture.o	\
+		driver.o	\
+		midi.o		\
+		midibuf.o	\
+		pcm.o		\
+		playback.o
+
+snd-usb-pod-y := pod.o
+snd-usb-podhd-y := podhd.o
+snd-usb-toneport-y := toneport.o
+snd-usb-variax-y := variax.o
+
+obj-$(CONFIG_SND_USB_LINE6)	+= snd-usb-line6.o
+obj-$(CONFIG_SND_USB_POD)	+= snd-usb-pod.o
+obj-$(CONFIG_SND_USB_PODHD)	+= snd-usb-podhd.o
+obj-$(CONFIG_SND_USB_TONEPORT)	+= snd-usb-toneport.o
+obj-$(CONFIG_SND_USB_VARIAX)	+= snd-usb-variax.o
diff --git a/sound/usb/line6/capture.c b/sound/usb/line6/capture.c
new file mode 100644
index 0000000..f518fbb
--- /dev/null
+++ b/sound/usb/line6/capture.c
@@ -0,0 +1,275 @@
+/*
+ * Line 6 Linux USB driver
+ *
+ * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
+ *
+ *	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, version 2.
+ *
+ */
+
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+
+#include "capture.h"
+#include "driver.h"
+#include "pcm.h"
+
+/*
+	Find a free URB and submit it.
+	must be called in line6pcm->in.lock context
+*/
+static int submit_audio_in_urb(struct snd_line6_pcm *line6pcm)
+{
+	int index;
+	int i, urb_size;
+	int ret;
+	struct urb *urb_in;
+
+	index =
+	    find_first_zero_bit(&line6pcm->in.active_urbs, LINE6_ISO_BUFFERS);
+
+	if (index < 0 || index >= LINE6_ISO_BUFFERS) {
+		dev_err(line6pcm->line6->ifcdev, "no free URB found\n");
+		return -EINVAL;
+	}
+
+	urb_in = line6pcm->in.urbs[index];
+	urb_size = 0;
+
+	for (i = 0; i < LINE6_ISO_PACKETS; ++i) {
+		struct usb_iso_packet_descriptor *fin =
+		    &urb_in->iso_frame_desc[i];
+		fin->offset = urb_size;
+		fin->length = line6pcm->max_packet_size;
+		urb_size += line6pcm->max_packet_size;
+	}
+
+	urb_in->transfer_buffer =
+	    line6pcm->in.buffer +
+	    index * LINE6_ISO_PACKETS * line6pcm->max_packet_size;
+	urb_in->transfer_buffer_length = urb_size;
+	urb_in->context = line6pcm;
+
+	ret = usb_submit_urb(urb_in, GFP_ATOMIC);
+
+	if (ret == 0)
+		set_bit(index, &line6pcm->in.active_urbs);
+	else
+		dev_err(line6pcm->line6->ifcdev,
+			"URB in #%d submission failed (%d)\n", index, ret);
+
+	return 0;
+}
+
+/*
+	Submit all currently available capture URBs.
+	must be called in line6pcm->in.lock context
+*/
+int line6_submit_audio_in_all_urbs(struct snd_line6_pcm *line6pcm)
+{
+	int ret = 0, i;
+
+	for (i = 0; i < LINE6_ISO_BUFFERS; ++i) {
+		ret = submit_audio_in_urb(line6pcm);
+		if (ret < 0)
+			break;
+	}
+
+	return ret;
+}
+
+/*
+	Copy data into ALSA capture buffer.
+*/
+void line6_capture_copy(struct snd_line6_pcm *line6pcm, char *fbuf, int fsize)
+{
+	struct snd_pcm_substream *substream =
+	    get_substream(line6pcm, SNDRV_PCM_STREAM_CAPTURE);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	const int bytes_per_frame = line6pcm->properties->bytes_per_frame;
+	int frames = fsize / bytes_per_frame;
+
+	if (runtime == NULL)
+		return;
+
+	if (line6pcm->in.pos_done + frames > runtime->buffer_size) {
+		/*
+		   The transferred area goes over buffer boundary,
+		   copy two separate chunks.
+		 */
+		int len;
+
+		len = runtime->buffer_size - line6pcm->in.pos_done;
+
+		if (len > 0) {
+			memcpy(runtime->dma_area +
+			       line6pcm->in.pos_done * bytes_per_frame, fbuf,
+			       len * bytes_per_frame);
+			memcpy(runtime->dma_area, fbuf + len * bytes_per_frame,
+			       (frames - len) * bytes_per_frame);
+		} else {
+			/* this is somewhat paranoid */
+			dev_err(line6pcm->line6->ifcdev,
+				"driver bug: len = %d\n", len);
+		}
+	} else {
+		/* copy single chunk */
+		memcpy(runtime->dma_area +
+		       line6pcm->in.pos_done * bytes_per_frame, fbuf, fsize);
+	}
+
+	line6pcm->in.pos_done += frames;
+	if (line6pcm->in.pos_done >= runtime->buffer_size)
+		line6pcm->in.pos_done -= runtime->buffer_size;
+}
+
+void line6_capture_check_period(struct snd_line6_pcm *line6pcm, int length)
+{
+	struct snd_pcm_substream *substream =
+	    get_substream(line6pcm, SNDRV_PCM_STREAM_CAPTURE);
+
+	line6pcm->in.bytes += length;
+	if (line6pcm->in.bytes >= line6pcm->in.period) {
+		line6pcm->in.bytes %= line6pcm->in.period;
+		spin_unlock(&line6pcm->in.lock);
+		snd_pcm_period_elapsed(substream);
+		spin_lock(&line6pcm->in.lock);
+	}
+}
+
+/*
+ * Callback for completed capture URB.
+ */
+static void audio_in_callback(struct urb *urb)
+{
+	int i, index, length = 0, shutdown = 0;
+	unsigned long flags;
+
+	struct snd_line6_pcm *line6pcm = (struct snd_line6_pcm *)urb->context;
+
+	line6pcm->in.last_frame = urb->start_frame;
+
+	/* find index of URB */
+	for (index = 0; index < LINE6_ISO_BUFFERS; ++index)
+		if (urb == line6pcm->in.urbs[index])
+			break;
+
+	spin_lock_irqsave(&line6pcm->in.lock, flags);
+
+	for (i = 0; i < LINE6_ISO_PACKETS; ++i) {
+		char *fbuf;
+		int fsize;
+		struct usb_iso_packet_descriptor *fin = &urb->iso_frame_desc[i];
+
+		if (fin->status == -EXDEV) {
+			shutdown = 1;
+			break;
+		}
+
+		fbuf = urb->transfer_buffer + fin->offset;
+		fsize = fin->actual_length;
+
+		if (fsize > line6pcm->max_packet_size) {
+			dev_err(line6pcm->line6->ifcdev,
+				"driver and/or device bug: packet too large (%d > %d)\n",
+				fsize, line6pcm->max_packet_size);
+		}
+
+		length += fsize;
+
+		/* the following assumes LINE6_ISO_PACKETS == 1: */
+		line6pcm->prev_fbuf = fbuf;
+		line6pcm->prev_fsize = fsize;
+
+		if (!test_bit(LINE6_STREAM_IMPULSE, &line6pcm->in.running) &&
+		    test_bit(LINE6_STREAM_PCM, &line6pcm->in.running) &&
+		    fsize > 0)
+			line6_capture_copy(line6pcm, fbuf, fsize);
+	}
+
+	clear_bit(index, &line6pcm->in.active_urbs);
+
+	if (test_and_clear_bit(index, &line6pcm->in.unlink_urbs))
+		shutdown = 1;
+
+	if (!shutdown) {
+		submit_audio_in_urb(line6pcm);
+
+		if (!test_bit(LINE6_STREAM_IMPULSE, &line6pcm->in.running) &&
+		    test_bit(LINE6_STREAM_PCM, &line6pcm->in.running))
+			line6_capture_check_period(line6pcm, length);
+	}
+
+	spin_unlock_irqrestore(&line6pcm->in.lock, flags);
+}
+
+/* open capture callback */
+static int snd_line6_capture_open(struct snd_pcm_substream *substream)
+{
+	int err;
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
+
+	err = snd_pcm_hw_constraint_ratdens(runtime, 0,
+					    SNDRV_PCM_HW_PARAM_RATE,
+					    &line6pcm->properties->rates);
+	if (err < 0)
+		return err;
+
+	runtime->hw = line6pcm->properties->capture_hw;
+	return 0;
+}
+
+/* close capture callback */
+static int snd_line6_capture_close(struct snd_pcm_substream *substream)
+{
+	return 0;
+}
+
+/* capture operators */
+struct snd_pcm_ops snd_line6_capture_ops = {
+	.open = snd_line6_capture_open,
+	.close = snd_line6_capture_close,
+	.ioctl = snd_pcm_lib_ioctl,
+	.hw_params = snd_line6_hw_params,
+	.hw_free = snd_line6_hw_free,
+	.prepare = snd_line6_prepare,
+	.trigger = snd_line6_trigger,
+	.pointer = snd_line6_pointer,
+};
+
+int line6_create_audio_in_urbs(struct snd_line6_pcm *line6pcm)
+{
+	struct usb_line6 *line6 = line6pcm->line6;
+	int i;
+
+	/* create audio URBs and fill in constant values: */
+	for (i = 0; i < LINE6_ISO_BUFFERS; ++i) {
+		struct urb *urb;
+
+		/* URB for audio in: */
+		urb = line6pcm->in.urbs[i] =
+		    usb_alloc_urb(LINE6_ISO_PACKETS, GFP_KERNEL);
+
+		if (urb == NULL)
+			return -ENOMEM;
+
+		urb->dev = line6->usbdev;
+		urb->pipe =
+		    usb_rcvisocpipe(line6->usbdev,
+				    line6->properties->ep_audio_r &
+				    USB_ENDPOINT_NUMBER_MASK);
+		urb->transfer_flags = URB_ISO_ASAP;
+		urb->start_frame = -1;
+		urb->number_of_packets = LINE6_ISO_PACKETS;
+		urb->interval = LINE6_ISO_INTERVAL;
+		urb->error_count = 0;
+		urb->complete = audio_in_callback;
+	}
+
+	return 0;
+}
diff --git a/drivers/staging/line6/capture.h b/sound/usb/line6/capture.h
similarity index 64%
rename from drivers/staging/line6/capture.h
rename to sound/usb/line6/capture.h
index 4157bcb..890b21b 100644
--- a/drivers/staging/line6/capture.h
+++ b/sound/usb/line6/capture.h
@@ -1,5 +1,5 @@
 /*
- * Line6 Linux USB driver - 0.9.1beta
+ * Line 6 Linux USB driver
  *
  * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
  *
@@ -24,12 +24,6 @@
 extern void line6_capture_check_period(struct snd_line6_pcm *line6pcm,
 				       int length);
 extern int line6_create_audio_in_urbs(struct snd_line6_pcm *line6pcm);
-extern void line6_free_capture_buffer(struct snd_line6_pcm *line6pcm);
 extern int line6_submit_audio_in_all_urbs(struct snd_line6_pcm *line6pcm);
-extern void line6_unlink_audio_in_urbs(struct snd_line6_pcm *line6pcm);
-extern void line6_unlink_wait_clear_audio_in_urbs(struct snd_line6_pcm
-						  *line6pcm);
-extern void line6_wait_clear_audio_in_urbs(struct snd_line6_pcm *line6pcm);
-extern int snd_line6_capture_trigger(struct snd_line6_pcm *line6pcm, int cmd);
 
 #endif
diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c
new file mode 100644
index 0000000..e2a2603
--- /dev/null
+++ b/sound/usb/line6/driver.c
@@ -0,0 +1,642 @@
+/*
+ * Line 6 Linux USB driver
+ *
+ * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
+ *
+ *	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, version 2.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/export.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+
+#include <sound/core.h>
+#include <sound/initval.h>
+
+#include "capture.h"
+#include "driver.h"
+#include "midi.h"
+#include "playback.h"
+
+#define DRIVER_AUTHOR  "Markus Grabner <grabner@icg.tugraz.at>"
+#define DRIVER_DESC    "Line 6 USB Driver"
+
+/*
+	This is Line 6's MIDI manufacturer ID.
+*/
+const unsigned char line6_midi_id[] = {
+	0x00, 0x01, 0x0c
+};
+EXPORT_SYMBOL_GPL(line6_midi_id);
+
+/*
+	Code to request version of POD, Variax interface
+	(and maybe other devices).
+*/
+static const char line6_request_version[] = {
+	0xf0, 0x7e, 0x7f, 0x06, 0x01, 0xf7
+};
+
+/*
+	 Class for asynchronous messages.
+*/
+struct message {
+	struct usb_line6 *line6;
+	const char *buffer;
+	int size;
+	int done;
+};
+
+/*
+	Forward declarations.
+*/
+static void line6_data_received(struct urb *urb);
+static int line6_send_raw_message_async_part(struct message *msg,
+					     struct urb *urb);
+
+/*
+	Start to listen on endpoint.
+*/
+static int line6_start_listen(struct usb_line6 *line6)
+{
+	int err;
+
+	usb_fill_int_urb(line6->urb_listen, line6->usbdev,
+		usb_rcvintpipe(line6->usbdev, line6->properties->ep_ctrl_r),
+		line6->buffer_listen, LINE6_BUFSIZE_LISTEN,
+		line6_data_received, line6, line6->interval);
+	line6->urb_listen->actual_length = 0;
+	err = usb_submit_urb(line6->urb_listen, GFP_ATOMIC);
+	return err;
+}
+
+/*
+	Stop listening on endpoint.
+*/
+static void line6_stop_listen(struct usb_line6 *line6)
+{
+	usb_kill_urb(line6->urb_listen);
+}
+
+/*
+	Send raw message in pieces of wMaxPacketSize bytes.
+*/
+static int line6_send_raw_message(struct usb_line6 *line6, const char *buffer,
+				  int size)
+{
+	int i, done = 0;
+
+	for (i = 0; i < size; i += line6->max_packet_size) {
+		int partial;
+		const char *frag_buf = buffer + i;
+		int frag_size = min(line6->max_packet_size, size - i);
+		int retval;
+
+		retval = usb_interrupt_msg(line6->usbdev,
+					usb_sndintpipe(line6->usbdev,
+						line6->properties->ep_ctrl_w),
+					(char *)frag_buf, frag_size,
+					&partial, LINE6_TIMEOUT * HZ);
+
+		if (retval) {
+			dev_err(line6->ifcdev,
+				"usb_interrupt_msg failed (%d)\n", retval);
+			break;
+		}
+
+		done += frag_size;
+	}
+
+	return done;
+}
+
+/*
+	Notification of completion of asynchronous request transmission.
+*/
+static void line6_async_request_sent(struct urb *urb)
+{
+	struct message *msg = (struct message *)urb->context;
+
+	if (msg->done >= msg->size) {
+		usb_free_urb(urb);
+		kfree(msg);
+	} else
+		line6_send_raw_message_async_part(msg, urb);
+}
+
+/*
+	Asynchronously send part of a raw message.
+*/
+static int line6_send_raw_message_async_part(struct message *msg,
+					     struct urb *urb)
+{
+	int retval;
+	struct usb_line6 *line6 = msg->line6;
+	int done = msg->done;
+	int bytes = min(msg->size - done, line6->max_packet_size);
+
+	usb_fill_int_urb(urb, line6->usbdev,
+		usb_sndintpipe(line6->usbdev, line6->properties->ep_ctrl_w),
+		(char *)msg->buffer + done, bytes,
+		line6_async_request_sent, msg, line6->interval);
+
+	msg->done += bytes;
+	retval = usb_submit_urb(urb, GFP_ATOMIC);
+
+	if (retval < 0) {
+		dev_err(line6->ifcdev, "%s: usb_submit_urb failed (%d)\n",
+			__func__, retval);
+		usb_free_urb(urb);
+		kfree(msg);
+		return retval;
+	}
+
+	return 0;
+}
+
+/*
+	Setup and start timer.
+*/
+void line6_start_timer(struct timer_list *timer, unsigned long msecs,
+		       void (*function)(unsigned long), unsigned long data)
+{
+	setup_timer(timer, function, data);
+	mod_timer(timer, jiffies + msecs_to_jiffies(msecs));
+}
+EXPORT_SYMBOL_GPL(line6_start_timer);
+
+/*
+	Asynchronously send raw message.
+*/
+int line6_send_raw_message_async(struct usb_line6 *line6, const char *buffer,
+				 int size)
+{
+	struct message *msg;
+	struct urb *urb;
+
+	/* create message: */
+	msg = kmalloc(sizeof(struct message), GFP_ATOMIC);
+	if (msg == NULL)
+		return -ENOMEM;
+
+	/* create URB: */
+	urb = usb_alloc_urb(0, GFP_ATOMIC);
+
+	if (urb == NULL) {
+		kfree(msg);
+		return -ENOMEM;
+	}
+
+	/* set message data: */
+	msg->line6 = line6;
+	msg->buffer = buffer;
+	msg->size = size;
+	msg->done = 0;
+
+	/* start sending: */
+	return line6_send_raw_message_async_part(msg, urb);
+}
+EXPORT_SYMBOL_GPL(line6_send_raw_message_async);
+
+/*
+	Send asynchronous device version request.
+*/
+int line6_version_request_async(struct usb_line6 *line6)
+{
+	char *buffer;
+	int retval;
+
+	buffer = kmemdup(line6_request_version,
+			sizeof(line6_request_version), GFP_ATOMIC);
+	if (buffer == NULL)
+		return -ENOMEM;
+
+	retval = line6_send_raw_message_async(line6, buffer,
+					      sizeof(line6_request_version));
+	kfree(buffer);
+	return retval;
+}
+EXPORT_SYMBOL_GPL(line6_version_request_async);
+
+/*
+	Send sysex message in pieces of wMaxPacketSize bytes.
+*/
+int line6_send_sysex_message(struct usb_line6 *line6, const char *buffer,
+			     int size)
+{
+	return line6_send_raw_message(line6, buffer,
+				      size + SYSEX_EXTRA_SIZE) -
+	    SYSEX_EXTRA_SIZE;
+}
+EXPORT_SYMBOL_GPL(line6_send_sysex_message);
+
+/*
+	Allocate buffer for sysex message and prepare header.
+	@param code sysex message code
+	@param size number of bytes between code and sysex end
+*/
+char *line6_alloc_sysex_buffer(struct usb_line6 *line6, int code1, int code2,
+			       int size)
+{
+	char *buffer = kmalloc(size + SYSEX_EXTRA_SIZE, GFP_ATOMIC);
+
+	if (!buffer)
+		return NULL;
+
+	buffer[0] = LINE6_SYSEX_BEGIN;
+	memcpy(buffer + 1, line6_midi_id, sizeof(line6_midi_id));
+	buffer[sizeof(line6_midi_id) + 1] = code1;
+	buffer[sizeof(line6_midi_id) + 2] = code2;
+	buffer[sizeof(line6_midi_id) + 3 + size] = LINE6_SYSEX_END;
+	return buffer;
+}
+EXPORT_SYMBOL_GPL(line6_alloc_sysex_buffer);
+
+/*
+	Notification of data received from the Line 6 device.
+*/
+static void line6_data_received(struct urb *urb)
+{
+	struct usb_line6 *line6 = (struct usb_line6 *)urb->context;
+	struct midi_buffer *mb = &line6->line6midi->midibuf_in;
+	int done;
+
+	if (urb->status == -ESHUTDOWN)
+		return;
+
+	done =
+	    line6_midibuf_write(mb, urb->transfer_buffer, urb->actual_length);
+
+	if (done < urb->actual_length) {
+		line6_midibuf_ignore(mb, done);
+		dev_dbg(line6->ifcdev, "%d %d buffer overflow - message skipped\n",
+			done, urb->actual_length);
+	}
+
+	for (;;) {
+		done =
+		    line6_midibuf_read(mb, line6->buffer_message,
+				       LINE6_MESSAGE_MAXLEN);
+
+		if (done == 0)
+			break;
+
+		line6->message_length = done;
+		line6_midi_receive(line6, line6->buffer_message, done);
+
+		if (line6->process_message)
+			line6->process_message(line6);
+	}
+
+	line6_start_listen(line6);
+}
+
+/*
+	Read data from device.
+*/
+int line6_read_data(struct usb_line6 *line6, int address, void *data,
+		    size_t datalen)
+{
+	struct usb_device *usbdev = line6->usbdev;
+	int ret;
+	unsigned char len;
+
+	/* query the serial number: */
+	ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x67,
+			      USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
+			      (datalen << 8) | 0x21, address,
+			      NULL, 0, LINE6_TIMEOUT * HZ);
+
+	if (ret < 0) {
+		dev_err(line6->ifcdev, "read request failed (error %d)\n", ret);
+		return ret;
+	}
+
+	/* Wait for data length. We'll get 0xff until length arrives. */
+	do {
+		ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), 0x67,
+				      USB_TYPE_VENDOR | USB_RECIP_DEVICE |
+				      USB_DIR_IN,
+				      0x0012, 0x0000, &len, 1,
+				      LINE6_TIMEOUT * HZ);
+		if (ret < 0) {
+			dev_err(line6->ifcdev,
+				"receive length failed (error %d)\n", ret);
+			return ret;
+		}
+	} while (len == 0xff);
+
+	if (len != datalen) {
+		/* should be equal or something went wrong */
+		dev_err(line6->ifcdev,
+			"length mismatch (expected %d, got %d)\n",
+			(int)datalen, (int)len);
+		return -EINVAL;
+	}
+
+	/* receive the result: */
+	ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), 0x67,
+			      USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
+			      0x0013, 0x0000, data, datalen,
+			      LINE6_TIMEOUT * HZ);
+
+	if (ret < 0) {
+		dev_err(line6->ifcdev, "read failed (error %d)\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(line6_read_data);
+
+/*
+	Write data to device.
+*/
+int line6_write_data(struct usb_line6 *line6, int address, void *data,
+		     size_t datalen)
+{
+	struct usb_device *usbdev = line6->usbdev;
+	int ret;
+	unsigned char status;
+
+	ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x67,
+			      USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
+			      0x0022, address, data, datalen,
+			      LINE6_TIMEOUT * HZ);
+
+	if (ret < 0) {
+		dev_err(line6->ifcdev,
+			"write request failed (error %d)\n", ret);
+		return ret;
+	}
+
+	do {
+		ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0),
+				      0x67,
+				      USB_TYPE_VENDOR | USB_RECIP_DEVICE |
+				      USB_DIR_IN,
+				      0x0012, 0x0000,
+				      &status, 1, LINE6_TIMEOUT * HZ);
+
+		if (ret < 0) {
+			dev_err(line6->ifcdev,
+				"receiving status failed (error %d)\n", ret);
+			return ret;
+		}
+	} while (status == 0xff);
+
+	if (status != 0) {
+		dev_err(line6->ifcdev, "write failed (error %d)\n", ret);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(line6_write_data);
+
+/*
+	Read Line 6 device serial number.
+	(POD, TonePort, GuitarPort)
+*/
+int line6_read_serial_number(struct usb_line6 *line6, int *serial_number)
+{
+	return line6_read_data(line6, 0x80d0, serial_number,
+			       sizeof(*serial_number));
+}
+EXPORT_SYMBOL_GPL(line6_read_serial_number);
+
+/*
+	Card destructor.
+*/
+static void line6_destruct(struct snd_card *card)
+{
+	struct usb_line6 *line6 = card->private_data;
+	struct usb_device *usbdev = line6->usbdev;
+
+	/* free buffer memory first: */
+	kfree(line6->buffer_message);
+	kfree(line6->buffer_listen);
+
+	/* then free URBs: */
+	usb_free_urb(line6->urb_listen);
+
+	/* decrement reference counters: */
+	usb_put_dev(usbdev);
+}
+
+/* get data from endpoint descriptor (see usb_maxpacket): */
+static void line6_get_interval(struct usb_line6 *line6)
+{
+	struct usb_device *usbdev = line6->usbdev;
+	struct usb_host_endpoint *ep;
+	unsigned pipe = usb_rcvintpipe(usbdev, line6->properties->ep_ctrl_r);
+	unsigned epnum = usb_pipeendpoint(pipe);
+
+	ep = usbdev->ep_in[epnum];
+	if (ep) {
+		line6->interval = ep->desc.bInterval;
+		line6->max_packet_size = le16_to_cpu(ep->desc.wMaxPacketSize);
+	} else {
+		dev_err(line6->ifcdev,
+			"endpoint not available, using fallback values");
+		line6->interval = LINE6_FALLBACK_INTERVAL;
+		line6->max_packet_size = LINE6_FALLBACK_MAXPACKETSIZE;
+	}
+}
+
+static int line6_init_cap_control(struct usb_line6 *line6)
+{
+	int ret;
+
+	/* initialize USB buffers: */
+	line6->buffer_listen = kmalloc(LINE6_BUFSIZE_LISTEN, GFP_KERNEL);
+	if (!line6->buffer_listen)
+		return -ENOMEM;
+
+	line6->buffer_message = kmalloc(LINE6_MESSAGE_MAXLEN, GFP_KERNEL);
+	if (!line6->buffer_message)
+		return -ENOMEM;
+
+	line6->urb_listen = usb_alloc_urb(0, GFP_KERNEL);
+	if (!line6->urb_listen)
+		return -ENOMEM;
+
+	ret = line6_start_listen(line6);
+	if (ret < 0) {
+		dev_err(line6->ifcdev, "cannot start listening: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+/*
+	Probe USB device.
+*/
+int line6_probe(struct usb_interface *interface,
+		const struct usb_device_id *id,
+		const struct line6_properties *properties,
+		int (*private_init)(struct usb_line6 *, const struct usb_device_id *id),
+		size_t data_size)
+{
+	struct usb_device *usbdev = interface_to_usbdev(interface);
+	struct snd_card *card;
+	struct usb_line6 *line6;
+	int interface_number;
+	int ret;
+
+	if (WARN_ON(data_size < sizeof(*line6)))
+		return -EINVAL;
+
+	/* we don't handle multiple configurations */
+	if (usbdev->descriptor.bNumConfigurations != 1)
+		return -ENODEV;
+
+	ret = snd_card_new(&interface->dev,
+			   SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
+			   THIS_MODULE, data_size, &card);
+	if (ret < 0)
+		return ret;
+
+	/* store basic data: */
+	line6 = card->private_data;
+	line6->card = card;
+	line6->properties = properties;
+	line6->usbdev = usbdev;
+	line6->ifcdev = &interface->dev;
+
+	strcpy(card->id, properties->id);
+	strcpy(card->driver, DRIVER_NAME);
+	strcpy(card->shortname, properties->name);
+	sprintf(card->longname, "Line 6 %s at USB %s", properties->name,
+		dev_name(line6->ifcdev));
+	card->private_free = line6_destruct;
+
+	usb_set_intfdata(interface, line6);
+
+	/* increment reference counters: */
+	usb_get_dev(usbdev);
+
+	/* initialize device info: */
+	dev_info(&interface->dev, "Line 6 %s found\n", properties->name);
+
+	/* query interface number */
+	interface_number = interface->cur_altsetting->desc.bInterfaceNumber;
+
+	ret = usb_set_interface(usbdev, interface_number,
+				properties->altsetting);
+	if (ret < 0) {
+		dev_err(&interface->dev, "set_interface failed\n");
+		goto error;
+	}
+
+	line6_get_interval(line6);
+
+	if (properties->capabilities & LINE6_CAP_CONTROL) {
+		ret = line6_init_cap_control(line6);
+		if (ret < 0)
+			goto error;
+	}
+
+	/* initialize device data based on device: */
+	ret = private_init(line6, id);
+	if (ret < 0)
+		goto error;
+
+	/* creation of additional special files should go here */
+
+	dev_info(&interface->dev, "Line 6 %s now attached\n",
+		 properties->name);
+
+	return 0;
+
+ error:
+	if (line6->disconnect)
+		line6->disconnect(line6);
+	snd_card_free(card);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(line6_probe);
+
+/*
+	Line 6 device disconnected.
+*/
+void line6_disconnect(struct usb_interface *interface)
+{
+	struct usb_line6 *line6 = usb_get_intfdata(interface);
+	struct usb_device *usbdev = interface_to_usbdev(interface);
+
+	if (!line6)
+		return;
+
+	if (WARN_ON(usbdev != line6->usbdev))
+		return;
+
+	if (line6->urb_listen != NULL)
+		line6_stop_listen(line6);
+
+	snd_card_disconnect(line6->card);
+	if (line6->line6pcm)
+		line6_pcm_disconnect(line6->line6pcm);
+	if (line6->disconnect)
+		line6->disconnect(line6);
+
+	dev_info(&interface->dev, "Line 6 %s now disconnected\n",
+		 line6->properties->name);
+
+	/* make sure the device isn't destructed twice: */
+	usb_set_intfdata(interface, NULL);
+
+	snd_card_free_when_closed(line6->card);
+}
+EXPORT_SYMBOL_GPL(line6_disconnect);
+
+#ifdef CONFIG_PM
+
+/*
+	Suspend Line 6 device.
+*/
+int line6_suspend(struct usb_interface *interface, pm_message_t message)
+{
+	struct usb_line6 *line6 = usb_get_intfdata(interface);
+	struct snd_line6_pcm *line6pcm = line6->line6pcm;
+
+	snd_power_change_state(line6->card, SNDRV_CTL_POWER_D3hot);
+
+	if (line6->properties->capabilities & LINE6_CAP_CONTROL)
+		line6_stop_listen(line6);
+
+	if (line6pcm != NULL) {
+		snd_pcm_suspend_all(line6pcm->pcm);
+		line6pcm->flags = 0;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(line6_suspend);
+
+/*
+	Resume Line 6 device.
+*/
+int line6_resume(struct usb_interface *interface)
+{
+	struct usb_line6 *line6 = usb_get_intfdata(interface);
+
+	if (line6->properties->capabilities & LINE6_CAP_CONTROL)
+		line6_start_listen(line6);
+
+	snd_power_change_state(line6->card, SNDRV_CTL_POWER_D0);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(line6_resume);
+
+#endif /* CONFIG_PM */
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
diff --git a/sound/usb/line6/driver.h b/sound/usb/line6/driver.h
new file mode 100644
index 0000000..2276b78
--- /dev/null
+++ b/sound/usb/line6/driver.h
@@ -0,0 +1,182 @@
+/*
+ * Line 6 Linux USB driver
+ *
+ * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
+ *
+ *	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, version 2.
+ *
+ */
+
+#ifndef DRIVER_H
+#define DRIVER_H
+
+#include <linux/spinlock.h>
+#include <linux/usb.h>
+#include <sound/core.h>
+
+#include "midi.h"
+
+#define DRIVER_NAME "line6usb"
+
+#define USB_INTERVALS_PER_SECOND 1000
+
+/* Fallback USB interval and max packet size values */
+#define LINE6_FALLBACK_INTERVAL 10
+#define LINE6_FALLBACK_MAXPACKETSIZE 16
+
+#define LINE6_TIMEOUT 1
+#define LINE6_BUFSIZE_LISTEN 32
+#define LINE6_MESSAGE_MAXLEN 256
+
+/*
+	Line 6 MIDI control commands
+*/
+#define LINE6_PARAM_CHANGE   0xb0
+#define LINE6_PROGRAM_CHANGE 0xc0
+#define LINE6_SYSEX_BEGIN    0xf0
+#define LINE6_SYSEX_END      0xf7
+#define LINE6_RESET          0xff
+
+/*
+	MIDI channel for messages initiated by the host
+	(and eventually echoed back by the device)
+*/
+#define LINE6_CHANNEL_HOST   0x00
+
+/*
+	MIDI channel for messages initiated by the device
+*/
+#define LINE6_CHANNEL_DEVICE 0x02
+
+#define LINE6_CHANNEL_UNKNOWN 5	/* don't know yet what this is good for */
+
+#define LINE6_CHANNEL_MASK 0x0f
+
+#define CHECK_STARTUP_PROGRESS(x, n)	\
+do {					\
+	if ((x) >= (n))			\
+		return;			\
+	x = (n);			\
+} while (0)
+
+extern const unsigned char line6_midi_id[3];
+
+static const int SYSEX_DATA_OFS = sizeof(line6_midi_id) + 3;
+static const int SYSEX_EXTRA_SIZE = sizeof(line6_midi_id) + 4;
+
+/*
+	 Common properties of Line 6 devices.
+*/
+struct line6_properties {
+	/* Card id string (maximum 16 characters).
+	 * This can be used to address the device in ALSA programs as
+	 * "default:CARD=<id>"
+	 */
+	const char *id;
+
+	/* Card short name (maximum 32 characters) */
+	const char *name;
+
+	/* Bit vector defining this device's capabilities in line6usb driver */
+	int capabilities;
+
+	int altsetting;
+
+	unsigned ep_ctrl_r;
+	unsigned ep_ctrl_w;
+	unsigned ep_audio_r;
+	unsigned ep_audio_w;
+};
+
+/* Capability bits */
+enum {
+	/* device supports settings parameter via USB */
+	LINE6_CAP_CONTROL =	1 << 0,
+	/* device supports PCM input/output via USB */
+	LINE6_CAP_PCM =		1 << 1,
+	/* device support hardware monitoring */
+	LINE6_CAP_HWMON =	1 << 2,
+};
+
+/*
+	 Common data shared by all Line 6 devices.
+	 Corresponds to a pair of USB endpoints.
+*/
+struct usb_line6 {
+	/* USB device */
+	struct usb_device *usbdev;
+
+	/* Properties */
+	const struct line6_properties *properties;
+
+	/* Interval (ms) */
+	int interval;
+
+	/* Maximum size of USB packet */
+	int max_packet_size;
+
+	/* Device representing the USB interface */
+	struct device *ifcdev;
+
+	/* Line 6 sound card data structure.
+	 * Each device has at least MIDI or PCM.
+	 */
+	struct snd_card *card;
+
+	/* Line 6 PCM device data structure */
+	struct snd_line6_pcm *line6pcm;
+
+	/* Line 6 MIDI device data structure */
+	struct snd_line6_midi *line6midi;
+
+	/* URB for listening to PODxt Pro control endpoint */
+	struct urb *urb_listen;
+
+	/* Buffer for listening to PODxt Pro control endpoint */
+	unsigned char *buffer_listen;
+
+	/* Buffer for message to be processed */
+	unsigned char *buffer_message;
+
+	/* Length of message to be processed */
+	int message_length;
+
+	void (*process_message)(struct usb_line6 *);
+	void (*disconnect)(struct usb_line6 *line6);
+};
+
+extern char *line6_alloc_sysex_buffer(struct usb_line6 *line6, int code1,
+				      int code2, int size);
+extern int line6_read_data(struct usb_line6 *line6, int address, void *data,
+			   size_t datalen);
+extern int line6_read_serial_number(struct usb_line6 *line6,
+				    int *serial_number);
+extern int line6_send_raw_message_async(struct usb_line6 *line6,
+					const char *buffer, int size);
+extern int line6_send_sysex_message(struct usb_line6 *line6,
+				    const char *buffer, int size);
+extern ssize_t line6_set_raw(struct device *dev, struct device_attribute *attr,
+			     const char *buf, size_t count);
+extern void line6_start_timer(struct timer_list *timer, unsigned long msecs,
+			      void (*function)(unsigned long),
+			      unsigned long data);
+extern int line6_version_request_async(struct usb_line6 *line6);
+extern int line6_write_data(struct usb_line6 *line6, int address, void *data,
+			    size_t datalen);
+
+int line6_probe(struct usb_interface *interface,
+		const struct usb_device_id *id,
+		const struct line6_properties *properties,
+		int (*private_init)(struct usb_line6 *, const struct usb_device_id *id),
+		size_t data_size);
+
+void line6_disconnect(struct usb_interface *interface);
+
+#ifdef CONFIG_PM
+int line6_suspend(struct usb_interface *interface, pm_message_t message);
+int line6_resume(struct usb_interface *interface);
+#endif
+
+#endif
diff --git a/drivers/staging/line6/midi.c b/sound/usb/line6/midi.c
similarity index 76%
rename from drivers/staging/line6/midi.c
rename to sound/usb/line6/midi.c
index 1ac343b..cebea9b 100644
--- a/drivers/staging/line6/midi.c
+++ b/sound/usb/line6/midi.c
@@ -1,5 +1,5 @@
 /*
- * Line6 Linux USB driver - 0.9.1beta
+ * Line 6 Linux USB driver
  *
  * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
  *
@@ -11,14 +11,12 @@
 
 #include <linux/slab.h>
 #include <linux/usb.h>
+#include <linux/export.h>
 #include <sound/core.h>
 #include <sound/rawmidi.h>
 
-#include "audio.h"
 #include "driver.h"
 #include "midi.h"
-#include "pod.h"
-#include "usbdefs.h"
 
 #define line6_rawmidi_substream_midi(substream) \
 	((struct snd_line6_midi *)((substream)->rmidi->private_data))
@@ -46,12 +44,9 @@
 	    line6_rawmidi_substream_midi(substream)->line6;
 	struct snd_line6_midi *line6midi = line6->line6midi;
 	struct midi_buffer *mb = &line6midi->midibuf_out;
-	unsigned long flags;
 	unsigned char chunk[LINE6_FALLBACK_MAXPACKETSIZE];
 	int req, done;
 
-	spin_lock_irqsave(&line6->line6midi->midi_transmit_lock, flags);
-
 	for (;;) {
 		req = min(line6_midibuf_bytes_free(mb), line6->max_packet_size);
 		done = snd_rawmidi_transmit_peek(substream, chunk, req);
@@ -72,8 +67,6 @@
 
 		send_midi_async(line6, chunk, done);
 	}
-
-	spin_unlock_irqrestore(&line6->line6midi->midi_transmit_lock, flags);
 }
 
 /*
@@ -93,7 +86,7 @@
 	if (status == -ESHUTDOWN)
 		return;
 
-	spin_lock_irqsave(&line6->line6midi->send_urb_lock, flags);
+	spin_lock_irqsave(&line6->line6midi->lock, flags);
 	num = --line6->line6midi->num_active_send_urbs;
 
 	if (num == 0) {
@@ -104,12 +97,12 @@
 	if (num == 0)
 		wake_up(&line6->line6midi->send_wait);
 
-	spin_unlock_irqrestore(&line6->line6midi->send_urb_lock, flags);
+	spin_unlock_irqrestore(&line6->line6midi->lock, flags);
 }
 
 /*
 	Send an asynchronous MIDI message.
-	Assumes that line6->line6midi->send_urb_lock is held
+	Assumes that line6->line6midi->lock is held
 	(i.e., this function is serialized).
 */
 static int send_midi_async(struct usb_line6 *line6, unsigned char *data,
@@ -121,22 +114,19 @@
 
 	urb = usb_alloc_urb(0, GFP_ATOMIC);
 
-	if (urb == NULL) {
-		dev_err(line6->ifcdev, "Out of memory\n");
+	if (urb == NULL)
 		return -ENOMEM;
-	}
 
 	transfer_buffer = kmemdup(data, length, GFP_ATOMIC);
 
 	if (transfer_buffer == NULL) {
 		usb_free_urb(urb);
-		dev_err(line6->ifcdev, "Out of memory\n");
 		return -ENOMEM;
 	}
 
 	usb_fill_int_urb(urb, line6->usbdev,
 			 usb_sndbulkpipe(line6->usbdev,
-					 line6->ep_control_write),
+					 line6->properties->ep_ctrl_w),
 			 transfer_buffer, length, midi_sent, line6,
 			 line6->interval);
 	urb->actual_length = 0;
@@ -170,12 +160,12 @@
 	    line6_rawmidi_substream_midi(substream)->line6;
 
 	line6->line6midi->substream_transmit = substream;
-	spin_lock_irqsave(&line6->line6midi->send_urb_lock, flags);
+	spin_lock_irqsave(&line6->line6midi->lock, flags);
 
 	if (line6->line6midi->num_active_send_urbs == 0)
 		line6_midi_transmit(substream);
 
-	spin_unlock_irqrestore(&line6->line6midi->send_urb_lock, flags);
+	spin_unlock_irqrestore(&line6->line6midi->lock, flags);
 }
 
 static void line6_midi_output_drain(struct snd_rawmidi_substream *substream)
@@ -223,28 +213,20 @@
 	.trigger = line6_midi_input_trigger,
 };
 
-/*
-	Cleanup the Line6 MIDI device.
-*/
-static void line6_cleanup_midi(struct snd_rawmidi *rmidi)
-{
-}
-
 /* Create a MIDI device */
-static int snd_line6_new_midi(struct snd_line6_midi *line6midi)
+static int snd_line6_new_midi(struct usb_line6 *line6,
+			      struct snd_rawmidi **rmidi_ret)
 {
 	struct snd_rawmidi *rmidi;
 	int err;
 
-	err = snd_rawmidi_new(line6midi->line6->card, "Line6 MIDI", 0, 1, 1,
-			      &rmidi);
+	err = snd_rawmidi_new(line6->card, "Line 6 MIDI", 0, 1, 1, rmidi_ret);
 	if (err < 0)
 		return err;
 
-	rmidi->private_data = line6midi;
-	rmidi->private_free = line6_cleanup_midi;
-	strcpy(rmidi->id, line6midi->line6->properties->id);
-	strcpy(rmidi->name, line6midi->line6->properties->name);
+	rmidi = *rmidi_ret;
+	strcpy(rmidi->id, line6->properties->id);
+	strcpy(rmidi->name, line6->properties->name);
 
 	rmidi->info_flags =
 	    SNDRV_RAWMIDI_INFO_OUTPUT |
@@ -258,64 +240,53 @@
 }
 
 /* MIDI device destructor */
-static int snd_line6_midi_free(struct snd_device *device)
+static void snd_line6_midi_free(struct snd_rawmidi *rmidi)
 {
-	struct snd_line6_midi *line6midi = device->device_data;
+	struct snd_line6_midi *line6midi = rmidi->private_data;
 
 	line6_midibuf_destroy(&line6midi->midibuf_in);
 	line6_midibuf_destroy(&line6midi->midibuf_out);
-	return 0;
+	kfree(line6midi);
 }
 
 /*
-	Initialize the Line6 MIDI subsystem.
+	Initialize the Line 6 MIDI subsystem.
 */
 int line6_init_midi(struct usb_line6 *line6)
 {
-	static struct snd_device_ops midi_ops = {
-		.dev_free = snd_line6_midi_free,
-	};
-
 	int err;
+	struct snd_rawmidi *rmidi;
 	struct snd_line6_midi *line6midi;
 
-	if (!(line6->properties->capabilities & LINE6_BIT_CONTROL)) {
+	if (!(line6->properties->capabilities & LINE6_CAP_CONTROL)) {
 		/* skip MIDI initialization and report success */
 		return 0;
 	}
 
-	line6midi = kzalloc(sizeof(struct snd_line6_midi), GFP_KERNEL);
+	err = snd_line6_new_midi(line6, &rmidi);
+	if (err < 0)
+		return err;
 
-	if (line6midi == NULL)
+	line6midi = kzalloc(sizeof(struct snd_line6_midi), GFP_KERNEL);
+	if (!line6midi)
 		return -ENOMEM;
 
-	err = line6_midibuf_init(&line6midi->midibuf_in, MIDI_BUFFER_SIZE, 0);
-	if (err < 0) {
-		kfree(line6midi);
-		return err;
-	}
-
-	err = line6_midibuf_init(&line6midi->midibuf_out, MIDI_BUFFER_SIZE, 1);
-	if (err < 0) {
-		kfree(line6midi->midibuf_in.buf);
-		kfree(line6midi);
-		return err;
-	}
-
-	line6midi->line6 = line6;
-	line6->line6midi = line6midi;
-
-	err = snd_device_new(line6->card, SNDRV_DEV_RAWMIDI, line6midi,
-			     &midi_ops);
-	if (err < 0)
-		return err;
-
-	err = snd_line6_new_midi(line6midi);
-	if (err < 0)
-		return err;
+	rmidi->private_data = line6midi;
+	rmidi->private_free = snd_line6_midi_free;
 
 	init_waitqueue_head(&line6midi->send_wait);
-	spin_lock_init(&line6midi->send_urb_lock);
-	spin_lock_init(&line6midi->midi_transmit_lock);
+	spin_lock_init(&line6midi->lock);
+	line6midi->line6 = line6;
+
+	err = line6_midibuf_init(&line6midi->midibuf_in, MIDI_BUFFER_SIZE, 0);
+	if (err < 0)
+		return err;
+
+	err = line6_midibuf_init(&line6midi->midibuf_out, MIDI_BUFFER_SIZE, 1);
+	if (err < 0)
+		return err;
+
+	line6->line6midi = line6midi;
 	return 0;
 }
+EXPORT_SYMBOL_GPL(line6_init_midi);
diff --git a/sound/usb/line6/midi.h b/sound/usb/line6/midi.h
new file mode 100644
index 0000000..cf82d69
--- /dev/null
+++ b/sound/usb/line6/midi.h
@@ -0,0 +1,51 @@
+/*
+ * Line 6 Linux USB driver
+ *
+ * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
+ *
+ *	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, version 2.
+ *
+ */
+
+#ifndef MIDI_H
+#define MIDI_H
+
+#include <sound/rawmidi.h>
+
+#include "midibuf.h"
+
+#define MIDI_BUFFER_SIZE 1024
+
+struct snd_line6_midi {
+	/* Pointer back to the Line 6 driver data structure */
+	struct usb_line6 *line6;
+
+	/* MIDI substream for receiving (or NULL if not active) */
+	struct snd_rawmidi_substream *substream_receive;
+
+	/* MIDI substream for transmitting (or NULL if not active) */
+	struct snd_rawmidi_substream *substream_transmit;
+
+	/* Number of currently active MIDI send URBs */
+	int num_active_send_urbs;
+
+	/* Spin lock to protect MIDI buffer handling */
+	spinlock_t lock;
+
+	/* Wait queue for MIDI transmission */
+	wait_queue_head_t send_wait;
+
+	/* Buffer for incoming MIDI stream */
+	struct midi_buffer midibuf_in;
+
+	/* Buffer for outgoing MIDI stream */
+	struct midi_buffer midibuf_out;
+};
+
+extern int line6_init_midi(struct usb_line6 *line6);
+extern void line6_midi_receive(struct usb_line6 *line6, unsigned char *data,
+			       int length);
+
+#endif
diff --git a/drivers/staging/line6/midibuf.c b/sound/usb/line6/midibuf.c
similarity index 90%
rename from drivers/staging/line6/midibuf.c
rename to sound/usb/line6/midibuf.c
index 1ff8569..36a610b 100644
--- a/drivers/staging/line6/midibuf.c
+++ b/sound/usb/line6/midibuf.c
@@ -1,5 +1,5 @@
 /*
- * Line6 Linux USB driver - 0.9.1beta
+ * Line 6 Linux USB driver
  *
  * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
  *
@@ -26,7 +26,7 @@
 	} else {
 		/*
 		   Note that according to the MIDI specification 0xf2 is
-		   the "Song Position Pointer", but this is used by Line6
+		   the "Song Position Pointer", but this is used by Line 6
 		   to send sysex messages to the host.
 		 */
 		static const int length[] = { -1, 2, -1, 2, -1, -1, 1, 1, 1, 1,
@@ -67,13 +67,6 @@
 	return 0;
 }
 
-void line6_midibuf_status(struct midi_buffer *this)
-{
-	pr_debug("midibuf size=%d split=%d pos_read=%d pos_write=%d full=%d command_prev=%02x\n",
-		 this->size, this->split, this->pos_read, this->pos_write,
-		 this->full, this->command_prev);
-}
-
 int line6_midibuf_bytes_free(struct midi_buffer *this)
 {
 	return
@@ -252,17 +245,6 @@
 	return length;
 }
 
-int line6_midibuf_skip_message(struct midi_buffer *this, unsigned short mask)
-{
-	int cmd = this->command_prev;
-
-	if ((cmd >= 0x80) && (cmd < 0xf0))
-		if ((mask & (1 << (cmd & 0x0f))) == 0)
-			return 1;
-
-	return 0;
-}
-
 void line6_midibuf_destroy(struct midi_buffer *this)
 {
 	kfree(this->buf);
diff --git a/drivers/staging/line6/midibuf.h b/sound/usb/line6/midibuf.h
similarity index 84%
rename from drivers/staging/line6/midibuf.h
rename to sound/usb/line6/midibuf.h
index 707482b..6ea21ff 100644
--- a/drivers/staging/line6/midibuf.h
+++ b/sound/usb/line6/midibuf.h
@@ -1,5 +1,5 @@
 /*
- * Line6 Linux USB driver - 0.9.1beta
+ * Line 6 Linux USB driver
  *
  * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
  *
@@ -29,9 +29,6 @@
 extern int line6_midibuf_read(struct midi_buffer *mb, unsigned char *data,
 			      int length);
 extern void line6_midibuf_reset(struct midi_buffer *mb);
-extern int line6_midibuf_skip_message(struct midi_buffer *mb,
-				      unsigned short mask);
-extern void line6_midibuf_status(struct midi_buffer *mb);
 extern int line6_midibuf_write(struct midi_buffer *mb, unsigned char *data,
 			       int length);
 
diff --git a/sound/usb/line6/pcm.c b/sound/usb/line6/pcm.c
new file mode 100644
index 0000000..8461d6b
--- /dev/null
+++ b/sound/usb/line6/pcm.c
@@ -0,0 +1,588 @@
+/*
+ * Line 6 Linux USB driver
+ *
+ * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
+ *
+ *	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, version 2.
+ *
+ */
+
+#include <linux/slab.h>
+#include <linux/export.h>
+#include <sound/core.h>
+#include <sound/control.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+
+#include "capture.h"
+#include "driver.h"
+#include "playback.h"
+
+/* impulse response volume controls */
+static int snd_line6_impulse_volume_info(struct snd_kcontrol *kcontrol,
+					 struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 255;
+	return 0;
+}
+
+static int snd_line6_impulse_volume_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
+
+	ucontrol->value.integer.value[0] = line6pcm->impulse_volume;
+	return 0;
+}
+
+static int snd_line6_impulse_volume_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
+	int value = ucontrol->value.integer.value[0];
+	int err;
+
+	if (line6pcm->impulse_volume == value)
+		return 0;
+
+	line6pcm->impulse_volume = value;
+	if (value > 0) {
+		err = line6_pcm_acquire(line6pcm, LINE6_STREAM_IMPULSE);
+		if (err < 0) {
+			line6pcm->impulse_volume = 0;
+			line6_pcm_release(line6pcm, LINE6_STREAM_IMPULSE);
+			return err;
+		}
+	} else {
+		line6_pcm_release(line6pcm, LINE6_STREAM_IMPULSE);
+	}
+	return 1;
+}
+
+/* impulse response period controls */
+static int snd_line6_impulse_period_info(struct snd_kcontrol *kcontrol,
+					 struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 2000;
+	return 0;
+}
+
+static int snd_line6_impulse_period_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
+
+	ucontrol->value.integer.value[0] = line6pcm->impulse_period;
+	return 0;
+}
+
+static int snd_line6_impulse_period_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
+	int value = ucontrol->value.integer.value[0];
+
+	if (line6pcm->impulse_period == value)
+		return 0;
+
+	line6pcm->impulse_period = value;
+	return 1;
+}
+
+/*
+	Unlink all currently active URBs.
+*/
+static void line6_unlink_audio_urbs(struct snd_line6_pcm *line6pcm,
+				    struct line6_pcm_stream *pcms)
+{
+	int i;
+
+	for (i = 0; i < LINE6_ISO_BUFFERS; i++) {
+		if (test_bit(i, &pcms->active_urbs)) {
+			if (!test_and_set_bit(i, &pcms->unlink_urbs))
+				usb_unlink_urb(pcms->urbs[i]);
+		}
+	}
+}
+
+/*
+	Wait until unlinking of all currently active URBs has been finished.
+*/
+static void line6_wait_clear_audio_urbs(struct snd_line6_pcm *line6pcm,
+					struct line6_pcm_stream *pcms)
+{
+	int timeout = HZ;
+	int i;
+	int alive;
+
+	do {
+		alive = 0;
+		for (i = 0; i < LINE6_ISO_BUFFERS; i++) {
+			if (test_bit(i, &pcms->active_urbs))
+				alive++;
+		}
+		if (!alive)
+			break;
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(1);
+	} while (--timeout > 0);
+	if (alive)
+		dev_err(line6pcm->line6->ifcdev,
+			"timeout: still %d active urbs..\n", alive);
+}
+
+static inline struct line6_pcm_stream *
+get_stream(struct snd_line6_pcm *line6pcm, int direction)
+{
+	return (direction == SNDRV_PCM_STREAM_PLAYBACK) ?
+		&line6pcm->out : &line6pcm->in;
+}
+
+/* allocate a buffer if not opened yet;
+ * call this in line6pcm.state_change mutex
+ */
+static int line6_buffer_acquire(struct snd_line6_pcm *line6pcm,
+				struct line6_pcm_stream *pstr, int type)
+{
+	/* Invoked multiple times in a row so allocate once only */
+	if (!test_and_set_bit(type, &pstr->opened) && !pstr->buffer) {
+		pstr->buffer = kmalloc(LINE6_ISO_BUFFERS * LINE6_ISO_PACKETS *
+				       line6pcm->max_packet_size, GFP_KERNEL);
+		if (!pstr->buffer)
+			return -ENOMEM;
+	}
+	return 0;
+}
+
+/* free a buffer if all streams are closed;
+ * call this in line6pcm.state_change mutex
+ */
+static void line6_buffer_release(struct snd_line6_pcm *line6pcm,
+				 struct line6_pcm_stream *pstr, int type)
+{
+
+	clear_bit(type, &pstr->opened);
+	if (!pstr->opened) {
+		line6_wait_clear_audio_urbs(line6pcm, pstr);
+		kfree(pstr->buffer);
+		pstr->buffer = NULL;
+	}
+}
+
+/* start a PCM stream */
+static int line6_stream_start(struct snd_line6_pcm *line6pcm, int direction,
+			      int type)
+{
+	unsigned long flags;
+	struct line6_pcm_stream *pstr = get_stream(line6pcm, direction);
+	int ret = 0;
+
+	spin_lock_irqsave(&pstr->lock, flags);
+	if (!test_and_set_bit(type, &pstr->running)) {
+		if (pstr->active_urbs || pstr->unlink_urbs) {
+			ret = -EBUSY;
+			goto error;
+		}
+
+		pstr->count = 0;
+		/* Submit all currently available URBs */
+		if (direction == SNDRV_PCM_STREAM_PLAYBACK)
+			ret = line6_submit_audio_out_all_urbs(line6pcm);
+		else
+			ret = line6_submit_audio_in_all_urbs(line6pcm);
+	}
+ error:
+	if (ret < 0)
+		clear_bit(type, &pstr->running);
+	spin_unlock_irqrestore(&pstr->lock, flags);
+	return ret;
+}
+
+/* stop a PCM stream; this doesn't sync with the unlinked URBs */
+static void line6_stream_stop(struct snd_line6_pcm *line6pcm, int direction,
+			  int type)
+{
+	unsigned long flags;
+	struct line6_pcm_stream *pstr = get_stream(line6pcm, direction);
+
+	spin_lock_irqsave(&pstr->lock, flags);
+	clear_bit(type, &pstr->running);
+	if (!pstr->running) {
+		line6_unlink_audio_urbs(line6pcm, pstr);
+		if (direction == SNDRV_PCM_STREAM_CAPTURE) {
+			line6pcm->prev_fbuf = NULL;
+			line6pcm->prev_fsize = 0;
+		}
+	}
+	spin_unlock_irqrestore(&pstr->lock, flags);
+}
+
+/* common PCM trigger callback */
+int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
+	struct snd_pcm_substream *s;
+	int err;
+
+	clear_bit(LINE6_FLAG_PREPARED, &line6pcm->flags);
+
+	snd_pcm_group_for_each_entry(s, substream) {
+		if (s->pcm->card != substream->pcm->card)
+			continue;
+
+		switch (cmd) {
+		case SNDRV_PCM_TRIGGER_START:
+		case SNDRV_PCM_TRIGGER_RESUME:
+			err = line6_stream_start(line6pcm, s->stream,
+						 LINE6_STREAM_PCM);
+			if (err < 0)
+				return err;
+			break;
+
+		case SNDRV_PCM_TRIGGER_STOP:
+		case SNDRV_PCM_TRIGGER_SUSPEND:
+			line6_stream_stop(line6pcm, s->stream,
+					  LINE6_STREAM_PCM);
+			break;
+
+		case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+			if (s->stream != SNDRV_PCM_STREAM_PLAYBACK)
+				return -EINVAL;
+			set_bit(LINE6_FLAG_PAUSE_PLAYBACK, &line6pcm->flags);
+			break;
+
+		case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+			if (s->stream != SNDRV_PCM_STREAM_PLAYBACK)
+				return -EINVAL;
+			clear_bit(LINE6_FLAG_PAUSE_PLAYBACK, &line6pcm->flags);
+			break;
+
+		default:
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+/* common PCM pointer callback */
+snd_pcm_uframes_t snd_line6_pointer(struct snd_pcm_substream *substream)
+{
+	struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
+	struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream);
+
+	return pstr->pos_done;
+}
+
+/* Acquire and start duplex streams:
+ * type is either LINE6_STREAM_IMPULSE or LINE6_STREAM_MONITOR
+ */
+int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int type)
+{
+	struct line6_pcm_stream *pstr;
+	int ret = 0, dir;
+
+	mutex_lock(&line6pcm->state_mutex);
+	for (dir = 0; dir < 2; dir++) {
+		pstr = get_stream(line6pcm, dir);
+		ret = line6_buffer_acquire(line6pcm, pstr, type);
+		if (ret < 0)
+			goto error;
+		if (!pstr->running)
+			line6_wait_clear_audio_urbs(line6pcm, pstr);
+	}
+	for (dir = 0; dir < 2; dir++) {
+		ret = line6_stream_start(line6pcm, dir, type);
+		if (ret < 0)
+			goto error;
+	}
+ error:
+	mutex_unlock(&line6pcm->state_mutex);
+	if (ret < 0)
+		line6_pcm_release(line6pcm, type);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(line6_pcm_acquire);
+
+/* Stop and release duplex streams */
+void line6_pcm_release(struct snd_line6_pcm *line6pcm, int type)
+{
+	struct line6_pcm_stream *pstr;
+	int dir;
+
+	mutex_lock(&line6pcm->state_mutex);
+	for (dir = 0; dir < 2; dir++)
+		line6_stream_stop(line6pcm, dir, type);
+	for (dir = 0; dir < 2; dir++) {
+		pstr = get_stream(line6pcm, dir);
+		line6_buffer_release(line6pcm, pstr, type);
+	}
+	mutex_unlock(&line6pcm->state_mutex);
+}
+EXPORT_SYMBOL_GPL(line6_pcm_release);
+
+/* common PCM hw_params callback */
+int snd_line6_hw_params(struct snd_pcm_substream *substream,
+			struct snd_pcm_hw_params *hw_params)
+{
+	int ret;
+	struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
+	struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream);
+
+	mutex_lock(&line6pcm->state_mutex);
+	ret = line6_buffer_acquire(line6pcm, pstr, LINE6_STREAM_PCM);
+	if (ret < 0)
+		goto error;
+
+	ret = snd_pcm_lib_malloc_pages(substream,
+				       params_buffer_bytes(hw_params));
+	if (ret < 0) {
+		line6_buffer_release(line6pcm, pstr, LINE6_STREAM_PCM);
+		goto error;
+	}
+
+	pstr->period = params_period_bytes(hw_params);
+ error:
+	mutex_unlock(&line6pcm->state_mutex);
+	return ret;
+}
+
+/* common PCM hw_free callback */
+int snd_line6_hw_free(struct snd_pcm_substream *substream)
+{
+	struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
+	struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream);
+
+	mutex_lock(&line6pcm->state_mutex);
+	line6_buffer_release(line6pcm, pstr, LINE6_STREAM_PCM);
+	mutex_unlock(&line6pcm->state_mutex);
+	return snd_pcm_lib_free_pages(substream);
+}
+
+
+/* control info callback */
+static int snd_line6_control_playback_info(struct snd_kcontrol *kcontrol,
+					   struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 2;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 256;
+	return 0;
+}
+
+/* control get callback */
+static int snd_line6_control_playback_get(struct snd_kcontrol *kcontrol,
+					  struct snd_ctl_elem_value *ucontrol)
+{
+	int i;
+	struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
+
+	for (i = 0; i < 2; i++)
+		ucontrol->value.integer.value[i] = line6pcm->volume_playback[i];
+
+	return 0;
+}
+
+/* control put callback */
+static int snd_line6_control_playback_put(struct snd_kcontrol *kcontrol,
+					  struct snd_ctl_elem_value *ucontrol)
+{
+	int i, changed = 0;
+	struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
+
+	for (i = 0; i < 2; i++)
+		if (line6pcm->volume_playback[i] !=
+		    ucontrol->value.integer.value[i]) {
+			line6pcm->volume_playback[i] =
+			    ucontrol->value.integer.value[i];
+			changed = 1;
+		}
+
+	return changed;
+}
+
+/* control definition */
+static struct snd_kcontrol_new line6_controls[] = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "PCM Playback Volume",
+		.info = snd_line6_control_playback_info,
+		.get = snd_line6_control_playback_get,
+		.put = snd_line6_control_playback_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Impulse Response Volume",
+		.info = snd_line6_impulse_volume_info,
+		.get = snd_line6_impulse_volume_get,
+		.put = snd_line6_impulse_volume_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Impulse Response Period",
+		.info = snd_line6_impulse_period_info,
+		.get = snd_line6_impulse_period_get,
+		.put = snd_line6_impulse_period_put
+	},
+};
+
+/*
+	Cleanup the PCM device.
+*/
+static void cleanup_urbs(struct line6_pcm_stream *pcms)
+{
+	int i;
+
+	for (i = 0; i < LINE6_ISO_BUFFERS; i++) {
+		if (pcms->urbs[i]) {
+			usb_kill_urb(pcms->urbs[i]);
+			usb_free_urb(pcms->urbs[i]);
+		}
+	}
+}
+
+static void line6_cleanup_pcm(struct snd_pcm *pcm)
+{
+	struct snd_line6_pcm *line6pcm = snd_pcm_chip(pcm);
+
+	cleanup_urbs(&line6pcm->out);
+	cleanup_urbs(&line6pcm->in);
+	kfree(line6pcm);
+}
+
+/* create a PCM device */
+static int snd_line6_new_pcm(struct usb_line6 *line6, struct snd_pcm **pcm_ret)
+{
+	struct snd_pcm *pcm;
+	int err;
+
+	err = snd_pcm_new(line6->card, (char *)line6->properties->name,
+			  0, 1, 1, pcm_ret);
+	if (err < 0)
+		return err;
+	pcm = *pcm_ret;
+	strcpy(pcm->name, line6->properties->name);
+
+	/* set operators */
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+			&snd_line6_playback_ops);
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_line6_capture_ops);
+
+	/* pre-allocation of buffers */
+	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
+					      snd_dma_continuous_data
+					      (GFP_KERNEL), 64 * 1024,
+					      128 * 1024);
+	return 0;
+}
+
+/*
+	Sync with PCM stream stops.
+*/
+void line6_pcm_disconnect(struct snd_line6_pcm *line6pcm)
+{
+	line6_unlink_audio_urbs(line6pcm, &line6pcm->out);
+	line6_unlink_audio_urbs(line6pcm, &line6pcm->in);
+	line6_wait_clear_audio_urbs(line6pcm, &line6pcm->out);
+	line6_wait_clear_audio_urbs(line6pcm, &line6pcm->in);
+}
+
+/*
+	Create and register the PCM device and mixer entries.
+	Create URBs for playback and capture.
+*/
+int line6_init_pcm(struct usb_line6 *line6,
+		   struct line6_pcm_properties *properties)
+{
+	int i, err;
+	unsigned ep_read = line6->properties->ep_audio_r;
+	unsigned ep_write = line6->properties->ep_audio_w;
+	struct snd_pcm *pcm;
+	struct snd_line6_pcm *line6pcm;
+
+	if (!(line6->properties->capabilities & LINE6_CAP_PCM))
+		return 0;	/* skip PCM initialization and report success */
+
+	err = snd_line6_new_pcm(line6, &pcm);
+	if (err < 0)
+		return err;
+
+	line6pcm = kzalloc(sizeof(*line6pcm), GFP_KERNEL);
+	if (!line6pcm)
+		return -ENOMEM;
+
+	mutex_init(&line6pcm->state_mutex);
+	line6pcm->pcm = pcm;
+	line6pcm->properties = properties;
+	line6pcm->volume_playback[0] = line6pcm->volume_playback[1] = 255;
+	line6pcm->volume_monitor = 255;
+	line6pcm->line6 = line6;
+
+	/* Read and write buffers are sized identically, so choose minimum */
+	line6pcm->max_packet_size = min(
+			usb_maxpacket(line6->usbdev,
+				usb_rcvisocpipe(line6->usbdev, ep_read), 0),
+			usb_maxpacket(line6->usbdev,
+				usb_sndisocpipe(line6->usbdev, ep_write), 1));
+
+	spin_lock_init(&line6pcm->out.lock);
+	spin_lock_init(&line6pcm->in.lock);
+	line6pcm->impulse_period = LINE6_IMPULSE_DEFAULT_PERIOD;
+
+	line6->line6pcm = line6pcm;
+
+	pcm->private_data = line6pcm;
+	pcm->private_free = line6_cleanup_pcm;
+
+	err = line6_create_audio_out_urbs(line6pcm);
+	if (err < 0)
+		return err;
+
+	err = line6_create_audio_in_urbs(line6pcm);
+	if (err < 0)
+		return err;
+
+	/* mixer: */
+	for (i = 0; i < ARRAY_SIZE(line6_controls); i++) {
+		err = snd_ctl_add(line6->card,
+				  snd_ctl_new1(&line6_controls[i], line6pcm));
+		if (err < 0)
+			return err;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(line6_init_pcm);
+
+/* prepare pcm callback */
+int snd_line6_prepare(struct snd_pcm_substream *substream)
+{
+	struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
+	struct line6_pcm_stream *pstr = get_stream(line6pcm, substream->stream);
+
+	mutex_lock(&line6pcm->state_mutex);
+	if (!pstr->running)
+		line6_wait_clear_audio_urbs(line6pcm, pstr);
+
+	if (!test_and_set_bit(LINE6_FLAG_PREPARED, &line6pcm->flags)) {
+		line6pcm->out.count = 0;
+		line6pcm->out.pos = 0;
+		line6pcm->out.pos_done = 0;
+		line6pcm->out.bytes = 0;
+		line6pcm->in.count = 0;
+		line6pcm->in.pos_done = 0;
+		line6pcm->in.bytes = 0;
+	}
+
+	mutex_unlock(&line6pcm->state_mutex);
+	return 0;
+}
diff --git a/sound/usb/line6/pcm.h b/sound/usb/line6/pcm.h
new file mode 100644
index 0000000..508410a
--- /dev/null
+++ b/sound/usb/line6/pcm.h
@@ -0,0 +1,197 @@
+/*
+ * Line 6 Linux USB driver
+ *
+ * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
+ *
+ *	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, version 2.
+ *
+ */
+
+/*
+	PCM interface to POD series devices.
+*/
+
+#ifndef PCM_H
+#define PCM_H
+
+#include <sound/pcm.h>
+
+#include "driver.h"
+
+/* number of URBs */
+#define LINE6_ISO_BUFFERS	2
+
+/*
+	number of USB frames per URB
+	The Line 6 Windows driver always transmits two frames per packet, but
+	the Linux driver performs significantly better (i.e., lower latency)
+	with only one frame per packet.
+*/
+#define LINE6_ISO_PACKETS	1
+
+/* in a "full speed" device (such as the PODxt Pro) this means 1ms */
+#define LINE6_ISO_INTERVAL	1
+
+#define LINE6_IMPULSE_DEFAULT_PERIOD 100
+
+/*
+	Get substream from Line 6 PCM data structure
+*/
+#define get_substream(line6pcm, stream)	\
+		(line6pcm->pcm->streams[stream].substream)
+
+/*
+	PCM mode bits.
+
+	There are several features of the Line 6 USB driver which require PCM
+	data to be exchanged with the device:
+	*) PCM playback and capture via ALSA
+	*) software monitoring (for devices without hardware monitoring)
+	*) optional impulse response measurement
+	However, from the device's point of view, there is just a single
+	capture and playback stream, which must be shared between these
+	subsystems. It is therefore necessary to maintain the state of the
+	subsystems with respect to PCM usage.
+
+	We define two bit flags, "opened" and "running", for each playback
+	or capture stream.  Both can contain the bit flag corresponding to
+	LINE6_STREAM_* type,
+	  LINE6_STREAM_PCM = ALSA PCM playback or capture
+	  LINE6_STREAM_MONITOR = software monitoring
+	  IMPULSE = optional impulse response measurement
+	The opened flag indicates whether the buffer is allocated while
+	the running flag indicates whether the stream is running.
+
+	For monitor or impulse operations, the driver needs to call
+	line6_pcm_acquire() or line6_pcm_release() with the appropriate
+	LINE6_STREAM_* flag.
+*/
+
+/* stream types */
+enum {
+	LINE6_STREAM_PCM,
+	LINE6_STREAM_MONITOR,
+	LINE6_STREAM_IMPULSE,
+};
+
+/* misc bit flags for PCM operation */
+enum {
+	LINE6_FLAG_PAUSE_PLAYBACK,
+	LINE6_FLAG_PREPARED,
+};
+
+struct line6_pcm_properties {
+	struct snd_pcm_hardware playback_hw, capture_hw;
+	struct snd_pcm_hw_constraint_ratdens rates;
+	int bytes_per_frame;
+};
+
+struct line6_pcm_stream {
+	/* allocated URBs */
+	struct urb *urbs[LINE6_ISO_BUFFERS];
+
+	/* Temporary buffer;
+	 * Since the packet size is not known in advance, this buffer is
+	 * large enough to store maximum size packets.
+	 */
+	unsigned char *buffer;
+
+	/* Free frame position in the buffer. */
+	snd_pcm_uframes_t pos;
+
+	/* Count processed bytes;
+	 * This is modulo period size (to determine when a period is finished).
+	 */
+	unsigned bytes;
+
+	/* Counter to create desired sample rate */
+	unsigned count;
+
+	/* period size in bytes */
+	unsigned period;
+
+	/* Processed frame position in the buffer;
+	 * The contents of the ring buffer have been consumed by the USB
+	 * subsystem (i.e., sent to the USB device) up to this position.
+	 */
+	snd_pcm_uframes_t pos_done;
+
+	/* Bit mask of active URBs */
+	unsigned long active_urbs;
+
+	/* Bit mask of URBs currently being unlinked */
+	unsigned long unlink_urbs;
+
+	/* Spin lock to protect updates of the buffer positions (not contents)
+	 */
+	spinlock_t lock;
+
+	/* Bit flags for operational stream types */
+	unsigned long opened;
+
+	/* Bit flags for running stream types */
+	unsigned long running;
+
+	int last_frame;
+};
+
+struct snd_line6_pcm {
+	/* Pointer back to the Line 6 driver data structure */
+	struct usb_line6 *line6;
+
+	/* Properties. */
+	struct line6_pcm_properties *properties;
+
+	/* ALSA pcm stream */
+	struct snd_pcm *pcm;
+
+	/* protection to state changes of in/out streams */
+	struct mutex state_mutex;
+
+	/* Capture and playback streams */
+	struct line6_pcm_stream in;
+	struct line6_pcm_stream out;
+
+	/* Previously captured frame (for software monitoring) */
+	unsigned char *prev_fbuf;
+
+	/* Size of previously captured frame (for software monitoring) */
+	int prev_fsize;
+
+	/* Maximum size of USB packet */
+	int max_packet_size;
+
+	/* PCM playback volume (left and right) */
+	int volume_playback[2];
+
+	/* PCM monitor volume */
+	int volume_monitor;
+
+	/* Volume of impulse response test signal (if zero, test is disabled) */
+	int impulse_volume;
+
+	/* Period of impulse response test signal */
+	int impulse_period;
+
+	/* Counter for impulse response test signal */
+	int impulse_count;
+
+	/* Several status bits (see LINE6_FLAG_*) */
+	unsigned long flags;
+};
+
+extern int line6_init_pcm(struct usb_line6 *line6,
+			  struct line6_pcm_properties *properties);
+extern int snd_line6_trigger(struct snd_pcm_substream *substream, int cmd);
+extern int snd_line6_prepare(struct snd_pcm_substream *substream);
+extern int snd_line6_hw_params(struct snd_pcm_substream *substream,
+			       struct snd_pcm_hw_params *hw_params);
+extern int snd_line6_hw_free(struct snd_pcm_substream *substream);
+extern snd_pcm_uframes_t snd_line6_pointer(struct snd_pcm_substream *substream);
+extern void line6_pcm_disconnect(struct snd_line6_pcm *line6pcm);
+extern int line6_pcm_acquire(struct snd_line6_pcm *line6pcm, int type);
+extern void line6_pcm_release(struct snd_line6_pcm *line6pcm, int type);
+
+#endif
diff --git a/sound/usb/line6/playback.c b/sound/usb/line6/playback.c
new file mode 100644
index 0000000..05dee69
--- /dev/null
+++ b/sound/usb/line6/playback.c
@@ -0,0 +1,429 @@
+/*
+ * Line 6 Linux USB driver
+ *
+ * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
+ *
+ *	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, version 2.
+ *
+ */
+
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+
+#include "capture.h"
+#include "driver.h"
+#include "pcm.h"
+#include "playback.h"
+
+/*
+	Software stereo volume control.
+*/
+static void change_volume(struct urb *urb_out, int volume[],
+			  int bytes_per_frame)
+{
+	int chn = 0;
+
+	if (volume[0] == 256 && volume[1] == 256)
+		return;		/* maximum volume - no change */
+
+	if (bytes_per_frame == 4) {
+		__le16 *p, *buf_end;
+
+		p = (__le16 *)urb_out->transfer_buffer;
+		buf_end = p + urb_out->transfer_buffer_length / sizeof(*p);
+
+		for (; p < buf_end; ++p) {
+			short pv = le16_to_cpu(*p);
+			int val = (pv * volume[chn & 1]) >> 8;
+			pv = clamp(val, 0x7fff, -0x8000);
+			*p = cpu_to_le16(pv);
+			++chn;
+		}
+	} else if (bytes_per_frame == 6) {
+		unsigned char *p, *buf_end;
+
+		p = (unsigned char *)urb_out->transfer_buffer;
+		buf_end = p + urb_out->transfer_buffer_length;
+
+		for (; p < buf_end; p += 3) {
+			int val;
+
+			val = p[0] + (p[1] << 8) + ((signed char)p[2] << 16);
+			val = (val * volume[chn & 1]) >> 8;
+			val = clamp(val, 0x7fffff, -0x800000);
+			p[0] = val;
+			p[1] = val >> 8;
+			p[2] = val >> 16;
+			++chn;
+		}
+	}
+}
+
+/*
+	Create signal for impulse response test.
+*/
+static void create_impulse_test_signal(struct snd_line6_pcm *line6pcm,
+				       struct urb *urb_out, int bytes_per_frame)
+{
+	int frames = urb_out->transfer_buffer_length / bytes_per_frame;
+
+	if (bytes_per_frame == 4) {
+		int i;
+		short *pi = (short *)line6pcm->prev_fbuf;
+		short *po = (short *)urb_out->transfer_buffer;
+
+		for (i = 0; i < frames; ++i) {
+			po[0] = pi[0];
+			po[1] = 0;
+			pi += 2;
+			po += 2;
+		}
+	} else if (bytes_per_frame == 6) {
+		int i, j;
+		unsigned char *pi = line6pcm->prev_fbuf;
+		unsigned char *po = urb_out->transfer_buffer;
+
+		for (i = 0; i < frames; ++i) {
+			for (j = 0; j < bytes_per_frame / 2; ++j)
+				po[j] = pi[j];
+
+			for (; j < bytes_per_frame; ++j)
+				po[j] = 0;
+
+			pi += bytes_per_frame;
+			po += bytes_per_frame;
+		}
+	}
+	if (--line6pcm->impulse_count <= 0) {
+		((unsigned char *)(urb_out->transfer_buffer))[bytes_per_frame -
+							      1] =
+		    line6pcm->impulse_volume;
+		line6pcm->impulse_count = line6pcm->impulse_period;
+	}
+}
+
+/*
+	Add signal to buffer for software monitoring.
+*/
+static void add_monitor_signal(struct urb *urb_out, unsigned char *signal,
+			       int volume, int bytes_per_frame)
+{
+	if (volume == 0)
+		return;		/* zero volume - no change */
+
+	if (bytes_per_frame == 4) {
+		__le16 *pi, *po, *buf_end;
+
+		pi = (__le16 *)signal;
+		po = (__le16 *)urb_out->transfer_buffer;
+		buf_end = po + urb_out->transfer_buffer_length / sizeof(*po);
+
+		for (; po < buf_end; ++pi, ++po) {
+			short pov = le16_to_cpu(*po);
+			short piv = le16_to_cpu(*pi);
+			int val = pov + ((piv * volume) >> 8);
+			pov = clamp(val, 0x7fff, -0x8000);
+			*po = cpu_to_le16(pov);
+		}
+	}
+
+	/*
+	   We don't need to handle devices with 6 bytes per frame here
+	   since they all support hardware monitoring.
+	 */
+}
+
+/*
+	Find a free URB, prepare audio data, and submit URB.
+	must be called in line6pcm->out.lock context
+*/
+static int submit_audio_out_urb(struct snd_line6_pcm *line6pcm)
+{
+	int index;
+	int i, urb_size, urb_frames;
+	int ret;
+	const int bytes_per_frame = line6pcm->properties->bytes_per_frame;
+	const int frame_increment =
+		line6pcm->properties->rates.rats[0].num_min;
+	const int frame_factor =
+		line6pcm->properties->rates.rats[0].den *
+		(USB_INTERVALS_PER_SECOND / LINE6_ISO_INTERVAL);
+	struct urb *urb_out;
+
+	index =
+	    find_first_zero_bit(&line6pcm->out.active_urbs, LINE6_ISO_BUFFERS);
+
+	if (index < 0 || index >= LINE6_ISO_BUFFERS) {
+		dev_err(line6pcm->line6->ifcdev, "no free URB found\n");
+		return -EINVAL;
+	}
+
+	urb_out = line6pcm->out.urbs[index];
+	urb_size = 0;
+
+	for (i = 0; i < LINE6_ISO_PACKETS; ++i) {
+		/* compute frame size for given sampling rate */
+		int fsize = 0;
+		struct usb_iso_packet_descriptor *fout =
+		    &urb_out->iso_frame_desc[i];
+
+		fsize = line6pcm->prev_fsize;
+		if (fsize == 0) {
+			int n;
+
+			line6pcm->out.count += frame_increment;
+			n = line6pcm->out.count / frame_factor;
+			line6pcm->out.count -= n * frame_factor;
+			fsize = n * bytes_per_frame;
+		}
+
+		fout->offset = urb_size;
+		fout->length = fsize;
+		urb_size += fsize;
+	}
+
+	if (urb_size == 0) {
+		/* can't determine URB size */
+		dev_err(line6pcm->line6->ifcdev, "driver bug: urb_size = 0\n");
+		return -EINVAL;
+	}
+
+	urb_frames = urb_size / bytes_per_frame;
+	urb_out->transfer_buffer =
+	    line6pcm->out.buffer +
+	    index * LINE6_ISO_PACKETS * line6pcm->max_packet_size;
+	urb_out->transfer_buffer_length = urb_size;
+	urb_out->context = line6pcm;
+
+	if (test_bit(LINE6_STREAM_PCM, &line6pcm->out.running) &&
+	    !test_bit(LINE6_FLAG_PAUSE_PLAYBACK, &line6pcm->flags)) {
+		struct snd_pcm_runtime *runtime =
+		    get_substream(line6pcm, SNDRV_PCM_STREAM_PLAYBACK)->runtime;
+
+		if (line6pcm->out.pos + urb_frames > runtime->buffer_size) {
+			/*
+			   The transferred area goes over buffer boundary,
+			   copy the data to the temp buffer.
+			 */
+			int len;
+
+			len = runtime->buffer_size - line6pcm->out.pos;
+
+			if (len > 0) {
+				memcpy(urb_out->transfer_buffer,
+				       runtime->dma_area +
+				       line6pcm->out.pos * bytes_per_frame,
+				       len * bytes_per_frame);
+				memcpy(urb_out->transfer_buffer +
+				       len * bytes_per_frame, runtime->dma_area,
+				       (urb_frames - len) * bytes_per_frame);
+			} else
+				dev_err(line6pcm->line6->ifcdev, "driver bug: len = %d\n",
+					len);
+		} else {
+			memcpy(urb_out->transfer_buffer,
+			       runtime->dma_area +
+			       line6pcm->out.pos * bytes_per_frame,
+			       urb_out->transfer_buffer_length);
+		}
+
+		line6pcm->out.pos += urb_frames;
+		if (line6pcm->out.pos >= runtime->buffer_size)
+			line6pcm->out.pos -= runtime->buffer_size;
+
+		change_volume(urb_out, line6pcm->volume_playback,
+			      bytes_per_frame);
+	} else {
+		memset(urb_out->transfer_buffer, 0,
+		       urb_out->transfer_buffer_length);
+	}
+
+	spin_lock_nested(&line6pcm->in.lock, SINGLE_DEPTH_NESTING);
+	if (line6pcm->prev_fbuf) {
+		if (test_bit(LINE6_STREAM_IMPULSE, &line6pcm->out.running)) {
+			create_impulse_test_signal(line6pcm, urb_out,
+						   bytes_per_frame);
+			if (test_bit(LINE6_STREAM_PCM, &line6pcm->in.running)) {
+				line6_capture_copy(line6pcm,
+						   urb_out->transfer_buffer,
+						   urb_out->
+						   transfer_buffer_length);
+				line6_capture_check_period(line6pcm,
+					urb_out->transfer_buffer_length);
+			}
+		} else {
+			if (!(line6pcm->line6->properties->capabilities & LINE6_CAP_HWMON)
+			    && line6pcm->out.running && line6pcm->in.running)
+				add_monitor_signal(urb_out, line6pcm->prev_fbuf,
+						   line6pcm->volume_monitor,
+						   bytes_per_frame);
+		}
+		line6pcm->prev_fbuf = NULL;
+		line6pcm->prev_fsize = 0;
+	}
+	spin_unlock(&line6pcm->in.lock);
+
+	ret = usb_submit_urb(urb_out, GFP_ATOMIC);
+
+	if (ret == 0)
+		set_bit(index, &line6pcm->out.active_urbs);
+	else
+		dev_err(line6pcm->line6->ifcdev,
+			"URB out #%d submission failed (%d)\n", index, ret);
+
+	return 0;
+}
+
+/*
+	Submit all currently available playback URBs.
+	must be called in line6pcm->out.lock context
+ */
+int line6_submit_audio_out_all_urbs(struct snd_line6_pcm *line6pcm)
+{
+	int ret = 0, i;
+
+	for (i = 0; i < LINE6_ISO_BUFFERS; ++i) {
+		ret = submit_audio_out_urb(line6pcm);
+		if (ret < 0)
+			break;
+	}
+
+	return ret;
+}
+
+/*
+	Callback for completed playback URB.
+*/
+static void audio_out_callback(struct urb *urb)
+{
+	int i, index, length = 0, shutdown = 0;
+	unsigned long flags;
+	struct snd_line6_pcm *line6pcm = (struct snd_line6_pcm *)urb->context;
+	struct snd_pcm_substream *substream =
+	    get_substream(line6pcm, SNDRV_PCM_STREAM_PLAYBACK);
+
+#if USE_CLEAR_BUFFER_WORKAROUND
+	memset(urb->transfer_buffer, 0, urb->transfer_buffer_length);
+#endif
+
+	line6pcm->out.last_frame = urb->start_frame;
+
+	/* find index of URB */
+	for (index = 0; index < LINE6_ISO_BUFFERS; index++)
+		if (urb == line6pcm->out.urbs[index])
+			break;
+
+	if (index >= LINE6_ISO_BUFFERS)
+		return;		/* URB has been unlinked asynchronously */
+
+	for (i = 0; i < LINE6_ISO_PACKETS; i++)
+		length += urb->iso_frame_desc[i].length;
+
+	spin_lock_irqsave(&line6pcm->out.lock, flags);
+
+	if (test_bit(LINE6_STREAM_PCM, &line6pcm->out.running)) {
+		struct snd_pcm_runtime *runtime = substream->runtime;
+
+		line6pcm->out.pos_done +=
+		    length / line6pcm->properties->bytes_per_frame;
+
+		if (line6pcm->out.pos_done >= runtime->buffer_size)
+			line6pcm->out.pos_done -= runtime->buffer_size;
+	}
+
+	clear_bit(index, &line6pcm->out.active_urbs);
+
+	for (i = 0; i < LINE6_ISO_PACKETS; i++)
+		if (urb->iso_frame_desc[i].status == -EXDEV) {
+			shutdown = 1;
+			break;
+		}
+
+	if (test_and_clear_bit(index, &line6pcm->out.unlink_urbs))
+		shutdown = 1;
+
+	if (!shutdown) {
+		submit_audio_out_urb(line6pcm);
+
+		if (test_bit(LINE6_STREAM_PCM, &line6pcm->out.running)) {
+			line6pcm->out.bytes += length;
+			if (line6pcm->out.bytes >= line6pcm->out.period) {
+				line6pcm->out.bytes %= line6pcm->out.period;
+				spin_unlock(&line6pcm->out.lock);
+				snd_pcm_period_elapsed(substream);
+				spin_lock(&line6pcm->out.lock);
+			}
+		}
+	}
+	spin_unlock_irqrestore(&line6pcm->out.lock, flags);
+}
+
+/* open playback callback */
+static int snd_line6_playback_open(struct snd_pcm_substream *substream)
+{
+	int err;
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_line6_pcm *line6pcm = snd_pcm_substream_chip(substream);
+
+	err = snd_pcm_hw_constraint_ratdens(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+					    &line6pcm->properties->rates);
+	if (err < 0)
+		return err;
+
+	runtime->hw = line6pcm->properties->playback_hw;
+	return 0;
+}
+
+/* close playback callback */
+static int snd_line6_playback_close(struct snd_pcm_substream *substream)
+{
+	return 0;
+}
+
+/* playback operators */
+struct snd_pcm_ops snd_line6_playback_ops = {
+	.open = snd_line6_playback_open,
+	.close = snd_line6_playback_close,
+	.ioctl = snd_pcm_lib_ioctl,
+	.hw_params = snd_line6_hw_params,
+	.hw_free = snd_line6_hw_free,
+	.prepare = snd_line6_prepare,
+	.trigger = snd_line6_trigger,
+	.pointer = snd_line6_pointer,
+};
+
+int line6_create_audio_out_urbs(struct snd_line6_pcm *line6pcm)
+{
+	struct usb_line6 *line6 = line6pcm->line6;
+	int i;
+
+	/* create audio URBs and fill in constant values: */
+	for (i = 0; i < LINE6_ISO_BUFFERS; ++i) {
+		struct urb *urb;
+
+		/* URB for audio out: */
+		urb = line6pcm->out.urbs[i] =
+		    usb_alloc_urb(LINE6_ISO_PACKETS, GFP_KERNEL);
+
+		if (urb == NULL)
+			return -ENOMEM;
+
+		urb->dev = line6->usbdev;
+		urb->pipe =
+		    usb_sndisocpipe(line6->usbdev,
+				    line6->properties->ep_audio_w &
+				    USB_ENDPOINT_NUMBER_MASK);
+		urb->transfer_flags = URB_ISO_ASAP;
+		urb->start_frame = -1;
+		urb->number_of_packets = LINE6_ISO_PACKETS;
+		urb->interval = LINE6_ISO_INTERVAL;
+		urb->error_count = 0;
+		urb->complete = audio_out_callback;
+	}
+
+	return 0;
+}
diff --git a/drivers/staging/line6/playback.h b/sound/usb/line6/playback.h
similarity index 71%
rename from drivers/staging/line6/playback.h
rename to sound/usb/line6/playback.h
index 743bd6f..51fce29 100644
--- a/drivers/staging/line6/playback.h
+++ b/sound/usb/line6/playback.h
@@ -1,5 +1,5 @@
 /*
- * Line6 Linux USB driver - 0.9.1beta
+ * Line 6 Linux USB driver
  *
  * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
  *
@@ -30,12 +30,6 @@
 extern struct snd_pcm_ops snd_line6_playback_ops;
 
 extern int line6_create_audio_out_urbs(struct snd_line6_pcm *line6pcm);
-extern void line6_free_playback_buffer(struct snd_line6_pcm *line6pcm);
 extern int line6_submit_audio_out_all_urbs(struct snd_line6_pcm *line6pcm);
-extern void line6_unlink_audio_out_urbs(struct snd_line6_pcm *line6pcm);
-extern void line6_unlink_wait_clear_audio_out_urbs(struct snd_line6_pcm
-						   *line6pcm);
-extern void line6_wait_clear_audio_out_urbs(struct snd_line6_pcm *line6pcm);
-extern int snd_line6_playback_trigger(struct snd_line6_pcm *line6pcm, int cmd);
 
 #endif
diff --git a/drivers/staging/line6/pod.c b/sound/usb/line6/pod.c
similarity index 63%
rename from drivers/staging/line6/pod.c
rename to sound/usb/line6/pod.c
index 44f4b2f..61aadd7 100644
--- a/drivers/staging/line6/pod.c
+++ b/sound/usb/line6/pod.c
@@ -1,5 +1,5 @@
 /*
- * Line6 Linux USB driver - 0.9.1beta
+ * Line 6 Linux USB driver
  *
  * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
  *
@@ -11,13 +11,76 @@
 
 #include <linux/slab.h>
 #include <linux/wait.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+
+#include <sound/core.h>
 #include <sound/control.h>
 
-#include "audio.h"
 #include "capture.h"
 #include "driver.h"
 #include "playback.h"
-#include "pod.h"
+
+/*
+	Locate name in binary program dump
+*/
+#define	POD_NAME_OFFSET 0
+#define	POD_NAME_LENGTH 16
+
+/*
+	Other constants
+*/
+#define POD_CONTROL_SIZE 0x80
+#define POD_BUFSIZE_DUMPREQ 7
+#define POD_STARTUP_DELAY 1000
+
+/*
+	Stages of POD startup procedure
+*/
+enum {
+	POD_STARTUP_INIT = 1,
+	POD_STARTUP_VERSIONREQ,
+	POD_STARTUP_WORKQUEUE,
+	POD_STARTUP_SETUP,
+	POD_STARTUP_LAST = POD_STARTUP_SETUP - 1
+};
+
+enum {
+	LINE6_BASSPODXT,
+	LINE6_BASSPODXTLIVE,
+	LINE6_BASSPODXTPRO,
+	LINE6_POCKETPOD,
+	LINE6_PODXT,
+	LINE6_PODXTLIVE_POD,
+	LINE6_PODXTPRO,
+};
+
+struct usb_line6_pod {
+	/* Generic Line 6 USB data */
+	struct usb_line6 line6;
+
+	/* Instrument monitor level */
+	int monitor_level;
+
+	/* Timer for device initialization */
+	struct timer_list startup_timer;
+
+	/* Work handler for device initialization */
+	struct work_struct startup_work;
+
+	/* Current progress in startup procedure */
+	int startup_progress;
+
+	/* Serial number of device */
+	int serial_number;
+
+	/* Firmware version (x 100) */
+	int firmware_version;
+
+	/* Device ID */
+	int device_id;
+};
 
 #define POD_SYSEX_CODE 3
 #define POD_BYTES_PER_FRAME 6	/* 24bit audio (stereo) */
@@ -66,15 +129,12 @@
 };
 
 static struct line6_pcm_properties pod_pcm_properties = {
-	.snd_line6_playback_hw = {
+	.playback_hw = {
 				  .info = (SNDRV_PCM_INFO_MMAP |
 					   SNDRV_PCM_INFO_INTERLEAVED |
 					   SNDRV_PCM_INFO_BLOCK_TRANSFER |
 					   SNDRV_PCM_INFO_MMAP_VALID |
 					   SNDRV_PCM_INFO_PAUSE |
-#ifdef CONFIG_PM
-					   SNDRV_PCM_INFO_RESUME |
-#endif
 					   SNDRV_PCM_INFO_SYNC_START),
 				  .formats = SNDRV_PCM_FMTBIT_S24_3LE,
 				  .rates = SNDRV_PCM_RATE_KNOT,
@@ -87,14 +147,11 @@
 				  .period_bytes_max = 8192,
 				  .periods_min = 1,
 				  .periods_max = 1024},
-	.snd_line6_capture_hw = {
+	.capture_hw = {
 				 .info = (SNDRV_PCM_INFO_MMAP |
 					  SNDRV_PCM_INFO_INTERLEAVED |
 					  SNDRV_PCM_INFO_BLOCK_TRANSFER |
 					  SNDRV_PCM_INFO_MMAP_VALID |
-#ifdef CONFIG_PM
-					  SNDRV_PCM_INFO_RESUME |
-#endif
 					  SNDRV_PCM_INFO_SYNC_START),
 				 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
 				 .rates = SNDRV_PCM_RATE_KNOT,
@@ -107,7 +164,7 @@
 				 .period_bytes_max = 8192,
 				 .periods_min = 1,
 				 .periods_max = 1024},
-	.snd_line6_rates = {
+	.rates = {
 			    .nrats = 1,
 			    .rats = &pod_ratden},
 	.bytes_per_frame = POD_BYTES_PER_FRAME
@@ -131,8 +188,9 @@
 /*
 	Process a completely received message.
 */
-void line6_pod_process_message(struct usb_line6_pod *pod)
+static void line6_pod_process_message(struct usb_line6 *line6)
 {
+	struct usb_line6_pod *pod = (struct usb_line6_pod *) line6;
 	const unsigned char *buf = pod->line6.buffer_message;
 
 	if (memcmp(buf, pod_version_header, sizeof(pod_version_header)) == 0) {
@@ -159,15 +217,6 @@
 }
 
 /*
-	Transmit PODxt Pro control parameter.
-*/
-void line6_pod_transmit_parameter(struct usb_line6_pod *pod, int param,
-				  u8 value)
-{
-	line6_transmit_parameter(&pod->line6, param, value);
-}
-
-/*
 	Send system parameter (from integer).
 */
 static int pod_set_system_param_int(struct usb_line6_pod *pod, int value,
@@ -273,7 +322,7 @@
 	line6_read_serial_number(&pod->line6, &pod->serial_number);
 
 	/* ALSA audio interface: */
-	line6_register_audio(line6);
+	snd_card_register(line6->card);
 }
 
 /* POD special files: */
@@ -331,17 +380,19 @@
 };
 
 /*
-	POD destructor.
+	POD device disconnected.
 */
-static void pod_destruct(struct usb_interface *interface)
+static void line6_pod_disconnect(struct usb_line6 *line6)
 {
-	struct usb_line6_pod *pod = usb_get_intfdata(interface);
+	struct usb_line6_pod *pod = (struct usb_line6_pod *)line6;
+	struct device *dev = line6->ifcdev;
 
-	if (pod == NULL)
-		return;
-	line6_cleanup_audio(&pod->line6);
+	/* remove sysfs entries: */
+	device_remove_file(dev, &dev_attr_device_id);
+	device_remove_file(dev, &dev_attr_firmware_version);
+	device_remove_file(dev, &dev_attr_serial_number);
 
-	del_timer(&pod->startup_timer);
+	del_timer_sync(&pod->startup_timer);
 	cancel_work_sync(&pod->startup_work);
 }
 
@@ -352,34 +403,35 @@
 {
 	int err;
 
-	CHECK_RETURN(device_create_file(dev, &dev_attr_device_id));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_firmware_version));
-	CHECK_RETURN(device_create_file(dev, &dev_attr_serial_number));
+	err = device_create_file(dev, &dev_attr_device_id);
+	if (err < 0)
+		return err;
+	err = device_create_file(dev, &dev_attr_firmware_version);
+	if (err < 0)
+		return err;
+	err = device_create_file(dev, &dev_attr_serial_number);
+	if (err < 0)
+		return err;
 	return 0;
 }
 
 /*
 	 Try to init POD device.
 */
-static int pod_try_init(struct usb_interface *interface,
-			struct usb_line6_pod *pod)
+static int pod_init(struct usb_line6 *line6,
+		    const struct usb_device_id *id)
 {
 	int err;
-	struct usb_line6 *line6 = &pod->line6;
+	struct usb_line6_pod *pod = (struct usb_line6_pod *) line6;
+
+	line6->process_message = line6_pod_process_message;
+	line6->disconnect = line6_pod_disconnect;
 
 	init_timer(&pod->startup_timer);
 	INIT_WORK(&pod->startup_work, pod_startup4);
 
-	if ((interface == NULL) || (pod == NULL))
-		return -ENODEV;
-
 	/* create sysfs entries: */
-	err = pod_create_files2(&interface->dev);
-	if (err < 0)
-		return err;
-
-	/* initialize audio system: */
-	err = line6_init_audio(line6);
+	err = pod_create_files2(line6->ifcdev);
 	if (err < 0)
 		return err;
 
@@ -405,7 +457,7 @@
 	   handler.
 	 */
 
-	if (pod->line6.properties->capabilities & LINE6_BIT_CONTROL) {
+	if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL) {
 		pod->monitor_level = POD_SYSTEM_INVALID;
 
 		/* initiate startup procedure: */
@@ -415,44 +467,131 @@
 	return 0;
 }
 
-/*
-	 Init POD device (and clean up in case of failure).
-*/
-int line6_pod_init(struct usb_interface *interface, struct usb_line6_pod *pod)
-{
-	int err = pod_try_init(interface, pod);
+#define LINE6_DEVICE(prod) USB_DEVICE(0x0e41, prod)
+#define LINE6_IF_NUM(prod, n) USB_DEVICE_INTERFACE_NUMBER(0x0e41, prod, n)
 
-	if (err < 0)
-		pod_destruct(interface);
+/* table of devices that work with this driver */
+static const struct usb_device_id pod_id_table[] = {
+	{ LINE6_DEVICE(0x4250),    .driver_info = LINE6_BASSPODXT },
+	{ LINE6_DEVICE(0x4642),    .driver_info = LINE6_BASSPODXTLIVE },
+	{ LINE6_DEVICE(0x4252),    .driver_info = LINE6_BASSPODXTPRO },
+	{ LINE6_IF_NUM(0x5051, 1), .driver_info = LINE6_POCKETPOD },
+	{ LINE6_DEVICE(0x5044),    .driver_info = LINE6_PODXT },
+	{ LINE6_IF_NUM(0x4650, 0), .driver_info = LINE6_PODXTLIVE_POD },
+	{ LINE6_DEVICE(0x5050),    .driver_info = LINE6_PODXTPRO },
+	{}
+};
 
-	return err;
-}
+MODULE_DEVICE_TABLE(usb, pod_id_table);
+
+static const struct line6_properties pod_properties_table[] = {
+	[LINE6_BASSPODXT] = {
+		.id = "BassPODxt",
+		.name = "BassPODxt",
+		.capabilities	= LINE6_CAP_CONTROL
+				| LINE6_CAP_PCM
+				| LINE6_CAP_HWMON,
+		.altsetting = 5,
+		.ep_ctrl_r = 0x84,
+		.ep_ctrl_w = 0x03,
+		.ep_audio_r = 0x82,
+		.ep_audio_w = 0x01,
+	},
+	[LINE6_BASSPODXTLIVE] = {
+		.id = "BassPODxtLive",
+		.name = "BassPODxt Live",
+		.capabilities	= LINE6_CAP_CONTROL
+				| LINE6_CAP_PCM
+				| LINE6_CAP_HWMON,
+		.altsetting = 1,
+		.ep_ctrl_r = 0x84,
+		.ep_ctrl_w = 0x03,
+		.ep_audio_r = 0x82,
+		.ep_audio_w = 0x01,
+	},
+	[LINE6_BASSPODXTPRO] = {
+		.id = "BassPODxtPro",
+		.name = "BassPODxt Pro",
+		.capabilities	= LINE6_CAP_CONTROL
+				| LINE6_CAP_PCM
+				| LINE6_CAP_HWMON,
+		.altsetting = 5,
+		.ep_ctrl_r = 0x84,
+		.ep_ctrl_w = 0x03,
+		.ep_audio_r = 0x82,
+		.ep_audio_w = 0x01,
+	},
+	[LINE6_POCKETPOD] = {
+		.id = "PocketPOD",
+		.name = "Pocket POD",
+		.capabilities	= LINE6_CAP_CONTROL,
+		.altsetting = 0,
+		.ep_ctrl_r = 0x82,
+		.ep_ctrl_w = 0x02,
+		/* no audio channel */
+	},
+	[LINE6_PODXT] = {
+		.id = "PODxt",
+		.name = "PODxt",
+		.capabilities	= LINE6_CAP_CONTROL
+				| LINE6_CAP_PCM
+				| LINE6_CAP_HWMON,
+		.altsetting = 5,
+		.ep_ctrl_r = 0x84,
+		.ep_ctrl_w = 0x03,
+		.ep_audio_r = 0x82,
+		.ep_audio_w = 0x01,
+	},
+	[LINE6_PODXTLIVE_POD] = {
+		.id = "PODxtLive",
+		.name = "PODxt Live",
+		.capabilities	= LINE6_CAP_CONTROL
+				| LINE6_CAP_PCM
+				| LINE6_CAP_HWMON,
+		.altsetting = 1,
+		.ep_ctrl_r = 0x84,
+		.ep_ctrl_w = 0x03,
+		.ep_audio_r = 0x82,
+		.ep_audio_w = 0x01,
+	},
+	[LINE6_PODXTPRO] = {
+		.id = "PODxtPro",
+		.name = "PODxt Pro",
+		.capabilities	= LINE6_CAP_CONTROL
+				| LINE6_CAP_PCM
+				| LINE6_CAP_HWMON,
+		.altsetting = 5,
+		.ep_ctrl_r = 0x84,
+		.ep_ctrl_w = 0x03,
+		.ep_audio_r = 0x82,
+		.ep_audio_w = 0x01,
+	},
+};
 
 /*
-	POD device disconnected.
+	Probe USB device.
 */
-void line6_pod_disconnect(struct usb_interface *interface)
+static int pod_probe(struct usb_interface *interface,
+		     const struct usb_device_id *id)
 {
-	struct usb_line6_pod *pod;
-
-	if (interface == NULL)
-		return;
-	pod = usb_get_intfdata(interface);
-
-	if (pod != NULL) {
-		struct snd_line6_pcm *line6pcm = pod->line6.line6pcm;
-		struct device *dev = &interface->dev;
-
-		if (line6pcm != NULL)
-			line6_pcm_disconnect(line6pcm);
-
-		if (dev != NULL) {
-			/* remove sysfs entries: */
-			device_remove_file(dev, &dev_attr_device_id);
-			device_remove_file(dev, &dev_attr_firmware_version);
-			device_remove_file(dev, &dev_attr_serial_number);
-		}
-	}
-
-	pod_destruct(interface);
+	return line6_probe(interface, id,
+			   &pod_properties_table[id->driver_info],
+			   pod_init, sizeof(struct usb_line6_pod));
 }
+
+static struct usb_driver pod_driver = {
+	.name = KBUILD_MODNAME,
+	.probe = pod_probe,
+	.disconnect = line6_disconnect,
+#ifdef CONFIG_PM
+	.suspend = line6_suspend,
+	.resume = line6_resume,
+	.reset_resume = line6_resume,
+#endif
+	.id_table = pod_id_table,
+};
+
+module_usb_driver(pod_driver);
+
+MODULE_DESCRIPTION("Line 6 POD USB driver");
+MODULE_LICENSE("GPL");
diff --git a/sound/usb/line6/podhd.c b/sound/usb/line6/podhd.c
new file mode 100644
index 0000000..9c3c744
--- /dev/null
+++ b/sound/usb/line6/podhd.c
@@ -0,0 +1,192 @@
+/*
+ * Line 6 Pod HD
+ *
+ * Copyright (C) 2011 Stefan Hajnoczi <stefanha@gmail.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, version 2.
+ *
+ */
+
+#include <linux/usb.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+
+#include "driver.h"
+#include "pcm.h"
+
+enum {
+	LINE6_PODHD300,
+	LINE6_PODHD400,
+	LINE6_PODHD500_0,
+	LINE6_PODHD500_1,
+};
+
+#define PODHD_BYTES_PER_FRAME 6	/* 24bit audio (stereo) */
+
+static struct snd_ratden podhd_ratden = {
+	.num_min = 48000,
+	.num_max = 48000,
+	.num_step = 1,
+	.den = 1,
+};
+
+static struct line6_pcm_properties podhd_pcm_properties = {
+	.playback_hw = {
+				  .info = (SNDRV_PCM_INFO_MMAP |
+					   SNDRV_PCM_INFO_INTERLEAVED |
+					   SNDRV_PCM_INFO_BLOCK_TRANSFER |
+					   SNDRV_PCM_INFO_MMAP_VALID |
+					   SNDRV_PCM_INFO_PAUSE |
+					   SNDRV_PCM_INFO_SYNC_START),
+				  .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+				  .rates = SNDRV_PCM_RATE_48000,
+				  .rate_min = 48000,
+				  .rate_max = 48000,
+				  .channels_min = 2,
+				  .channels_max = 2,
+				  .buffer_bytes_max = 60000,
+				  .period_bytes_min = 64,
+				  .period_bytes_max = 8192,
+				  .periods_min = 1,
+				  .periods_max = 1024},
+	.capture_hw = {
+				 .info = (SNDRV_PCM_INFO_MMAP |
+					  SNDRV_PCM_INFO_INTERLEAVED |
+					  SNDRV_PCM_INFO_BLOCK_TRANSFER |
+					  SNDRV_PCM_INFO_MMAP_VALID |
+					  SNDRV_PCM_INFO_SYNC_START),
+				 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+				 .rates = SNDRV_PCM_RATE_48000,
+				 .rate_min = 48000,
+				 .rate_max = 48000,
+				 .channels_min = 2,
+				 .channels_max = 2,
+				 .buffer_bytes_max = 60000,
+				 .period_bytes_min = 64,
+				 .period_bytes_max = 8192,
+				 .periods_min = 1,
+				 .periods_max = 1024},
+	.rates = {
+			    .nrats = 1,
+			    .rats = &podhd_ratden},
+	.bytes_per_frame = PODHD_BYTES_PER_FRAME
+};
+
+/*
+	Try to init POD HD device.
+*/
+static int podhd_init(struct usb_line6 *line6,
+		      const struct usb_device_id *id)
+{
+	int err;
+
+	/* initialize MIDI subsystem: */
+	err = line6_init_midi(line6);
+	if (err < 0)
+		return err;
+
+	/* initialize PCM subsystem: */
+	err = line6_init_pcm(line6, &podhd_pcm_properties);
+	if (err < 0)
+		return err;
+
+	/* register USB audio system: */
+	return snd_card_register(line6->card);
+}
+
+#define LINE6_DEVICE(prod) USB_DEVICE(0x0e41, prod)
+#define LINE6_IF_NUM(prod, n) USB_DEVICE_INTERFACE_NUMBER(0x0e41, prod, n)
+
+/* table of devices that work with this driver */
+static const struct usb_device_id podhd_id_table[] = {
+	{ LINE6_DEVICE(0x5057),    .driver_info = LINE6_PODHD300 },
+	{ LINE6_DEVICE(0x5058),    .driver_info = LINE6_PODHD400 },
+	{ LINE6_IF_NUM(0x414D, 0), .driver_info = LINE6_PODHD500_0 },
+	{ LINE6_IF_NUM(0x414D, 1), .driver_info = LINE6_PODHD500_1 },
+	{}
+};
+
+MODULE_DEVICE_TABLE(usb, podhd_id_table);
+
+static const struct line6_properties podhd_properties_table[] = {
+	[LINE6_PODHD300] = {
+		.id = "PODHD300",
+		.name = "POD HD300",
+		.capabilities	= LINE6_CAP_CONTROL
+				| LINE6_CAP_PCM
+				| LINE6_CAP_HWMON,
+		.altsetting = 5,
+		.ep_ctrl_r = 0x84,
+		.ep_ctrl_w = 0x03,
+		.ep_audio_r = 0x82,
+		.ep_audio_w = 0x01,
+	},
+	[LINE6_PODHD400] = {
+		.id = "PODHD400",
+		.name = "POD HD400",
+		.capabilities	= LINE6_CAP_CONTROL
+				| LINE6_CAP_PCM
+				| LINE6_CAP_HWMON,
+		.altsetting = 5,
+		.ep_ctrl_r = 0x84,
+		.ep_ctrl_w = 0x03,
+		.ep_audio_r = 0x82,
+		.ep_audio_w = 0x01,
+	},
+	[LINE6_PODHD500_0] = {
+		.id = "PODHD500",
+		.name = "POD HD500",
+		.capabilities	= LINE6_CAP_CONTROL
+				| LINE6_CAP_PCM
+				| LINE6_CAP_HWMON,
+		.altsetting = 1,
+		.ep_ctrl_r = 0x81,
+		.ep_ctrl_w = 0x01,
+		.ep_audio_r = 0x86,
+		.ep_audio_w = 0x02,
+	},
+	[LINE6_PODHD500_1] = {
+		.id = "PODHD500",
+		.name = "POD HD500",
+		.capabilities	= LINE6_CAP_CONTROL
+				| LINE6_CAP_PCM
+				| LINE6_CAP_HWMON,
+		.altsetting = 1,
+		.ep_ctrl_r = 0x81,
+		.ep_ctrl_w = 0x01,
+		.ep_audio_r = 0x86,
+		.ep_audio_w = 0x02,
+	},
+};
+
+/*
+	Probe USB device.
+*/
+static int podhd_probe(struct usb_interface *interface,
+		       const struct usb_device_id *id)
+{
+	return line6_probe(interface, id,
+			   &podhd_properties_table[id->driver_info],
+			   podhd_init, sizeof(struct usb_line6));
+}
+
+static struct usb_driver podhd_driver = {
+	.name = KBUILD_MODNAME,
+	.probe = podhd_probe,
+	.disconnect = line6_disconnect,
+#ifdef CONFIG_PM
+	.suspend = line6_suspend,
+	.resume = line6_resume,
+	.reset_resume = line6_resume,
+#endif
+	.id_table = podhd_id_table,
+};
+
+module_usb_driver(podhd_driver);
+
+MODULE_DESCRIPTION("Line 6 PODHD USB driver");
+MODULE_LICENSE("GPL");
diff --git a/sound/usb/line6/toneport.c b/sound/usb/line6/toneport.c
new file mode 100644
index 0000000..b107cf4
--- /dev/null
+++ b/sound/usb/line6/toneport.c
@@ -0,0 +1,575 @@
+/*
+ * Line 6 Linux USB driver
+ *
+ * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
+ *                         Emil Myhrman (emil.myhrman@gmail.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, version 2.
+ *
+ */
+
+#include <linux/wait.h>
+#include <linux/usb.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/leds.h>
+#include <sound/core.h>
+#include <sound/control.h>
+
+#include "capture.h"
+#include "driver.h"
+#include "playback.h"
+
+enum line6_device_type {
+	LINE6_GUITARPORT,
+	LINE6_PODSTUDIO_GX,
+	LINE6_PODSTUDIO_UX1,
+	LINE6_PODSTUDIO_UX2,
+	LINE6_TONEPORT_GX,
+	LINE6_TONEPORT_UX1,
+	LINE6_TONEPORT_UX2,
+};
+
+struct usb_line6_toneport;
+
+struct toneport_led {
+	struct led_classdev dev;
+	char name[64];
+	struct usb_line6_toneport *toneport;
+	bool registered;
+};
+
+struct usb_line6_toneport {
+	/* Generic Line 6 USB data */
+	struct usb_line6 line6;
+
+	/* Source selector */
+	int source;
+
+	/* Serial number of device */
+	int serial_number;
+
+	/* Firmware version (x 100) */
+	int firmware_version;
+
+	/* Timer for delayed PCM startup */
+	struct timer_list timer;
+
+	/* Device type */
+	enum line6_device_type type;
+
+	/* LED instances */
+	struct toneport_led leds[2];
+};
+
+static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2);
+
+#define TONEPORT_PCM_DELAY 1
+
+static struct snd_ratden toneport_ratden = {
+	.num_min = 44100,
+	.num_max = 44100,
+	.num_step = 1,
+	.den = 1
+};
+
+static struct line6_pcm_properties toneport_pcm_properties = {
+	.playback_hw = {
+				  .info = (SNDRV_PCM_INFO_MMAP |
+					   SNDRV_PCM_INFO_INTERLEAVED |
+					   SNDRV_PCM_INFO_BLOCK_TRANSFER |
+					   SNDRV_PCM_INFO_MMAP_VALID |
+					   SNDRV_PCM_INFO_PAUSE |
+					   SNDRV_PCM_INFO_SYNC_START),
+				  .formats = SNDRV_PCM_FMTBIT_S16_LE,
+				  .rates = SNDRV_PCM_RATE_KNOT,
+				  .rate_min = 44100,
+				  .rate_max = 44100,
+				  .channels_min = 2,
+				  .channels_max = 2,
+				  .buffer_bytes_max = 60000,
+				  .period_bytes_min = 64,
+				  .period_bytes_max = 8192,
+				  .periods_min = 1,
+				  .periods_max = 1024},
+	.capture_hw = {
+				 .info = (SNDRV_PCM_INFO_MMAP |
+					  SNDRV_PCM_INFO_INTERLEAVED |
+					  SNDRV_PCM_INFO_BLOCK_TRANSFER |
+					  SNDRV_PCM_INFO_MMAP_VALID |
+					  SNDRV_PCM_INFO_SYNC_START),
+				 .formats = SNDRV_PCM_FMTBIT_S16_LE,
+				 .rates = SNDRV_PCM_RATE_KNOT,
+				 .rate_min = 44100,
+				 .rate_max = 44100,
+				 .channels_min = 2,
+				 .channels_max = 2,
+				 .buffer_bytes_max = 60000,
+				 .period_bytes_min = 64,
+				 .period_bytes_max = 8192,
+				 .periods_min = 1,
+				 .periods_max = 1024},
+	.rates = {
+			    .nrats = 1,
+			    .rats = &toneport_ratden},
+	.bytes_per_frame = 4
+};
+
+static const struct {
+	const char *name;
+	int code;
+} toneport_source_info[] = {
+	{"Microphone", 0x0a01},
+	{"Line", 0x0801},
+	{"Instrument", 0x0b01},
+	{"Inst & Mic", 0x0901}
+};
+
+static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2)
+{
+	int ret;
+
+	ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x67,
+			      USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
+			      cmd1, cmd2, NULL, 0, LINE6_TIMEOUT * HZ);
+
+	if (ret < 0) {
+		dev_err(&usbdev->dev, "send failed (error %d)\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+/* monitor info callback */
+static int snd_toneport_monitor_info(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 256;
+	return 0;
+}
+
+/* monitor get callback */
+static int snd_toneport_monitor_get(struct snd_kcontrol *kcontrol,
+				    struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
+
+	ucontrol->value.integer.value[0] = line6pcm->volume_monitor;
+	return 0;
+}
+
+/* monitor put callback */
+static int snd_toneport_monitor_put(struct snd_kcontrol *kcontrol,
+				    struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
+	int err;
+
+	if (ucontrol->value.integer.value[0] == line6pcm->volume_monitor)
+		return 0;
+
+	line6pcm->volume_monitor = ucontrol->value.integer.value[0];
+
+	if (line6pcm->volume_monitor > 0) {
+		err = line6_pcm_acquire(line6pcm, LINE6_STREAM_MONITOR);
+		if (err < 0) {
+			line6pcm->volume_monitor = 0;
+			line6_pcm_release(line6pcm, LINE6_STREAM_MONITOR);
+			return err;
+		}
+	} else {
+		line6_pcm_release(line6pcm, LINE6_STREAM_MONITOR);
+	}
+
+	return 1;
+}
+
+/* source info callback */
+static int snd_toneport_source_info(struct snd_kcontrol *kcontrol,
+				    struct snd_ctl_elem_info *uinfo)
+{
+	const int size = ARRAY_SIZE(toneport_source_info);
+
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = size;
+
+	if (uinfo->value.enumerated.item >= size)
+		uinfo->value.enumerated.item = size - 1;
+
+	strcpy(uinfo->value.enumerated.name,
+	       toneport_source_info[uinfo->value.enumerated.item].name);
+
+	return 0;
+}
+
+/* source get callback */
+static int snd_toneport_source_get(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
+	struct usb_line6_toneport *toneport =
+	    (struct usb_line6_toneport *)line6pcm->line6;
+	ucontrol->value.enumerated.item[0] = toneport->source;
+	return 0;
+}
+
+/* source put callback */
+static int snd_toneport_source_put(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_line6_pcm *line6pcm = snd_kcontrol_chip(kcontrol);
+	struct usb_line6_toneport *toneport =
+	    (struct usb_line6_toneport *)line6pcm->line6;
+	unsigned int source;
+
+	source = ucontrol->value.enumerated.item[0];
+	if (source >= ARRAY_SIZE(toneport_source_info))
+		return -EINVAL;
+	if (source == toneport->source)
+		return 0;
+
+	toneport->source = source;
+	toneport_send_cmd(toneport->line6.usbdev,
+			  toneport_source_info[source].code, 0x0000);
+	return 1;
+}
+
+static void toneport_start_pcm(unsigned long arg)
+{
+	struct usb_line6_toneport *toneport = (struct usb_line6_toneport *)arg;
+	struct usb_line6 *line6 = &toneport->line6;
+
+	line6_pcm_acquire(line6->line6pcm, LINE6_STREAM_MONITOR);
+}
+
+/* control definition */
+static struct snd_kcontrol_new toneport_control_monitor = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "Monitor Playback Volume",
+	.index = 0,
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+	.info = snd_toneport_monitor_info,
+	.get = snd_toneport_monitor_get,
+	.put = snd_toneport_monitor_put
+};
+
+/* source selector definition */
+static struct snd_kcontrol_new toneport_control_source = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "PCM Capture Source",
+	.index = 0,
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+	.info = snd_toneport_source_info,
+	.get = snd_toneport_source_get,
+	.put = snd_toneport_source_put
+};
+
+/*
+	For the led on Guitarport.
+	Brightness goes from 0x00 to 0x26. Set a value above this to have led
+	blink.
+	(void cmd_0x02(byte red, byte green)
+*/
+
+static bool toneport_has_led(enum line6_device_type type)
+{
+	return
+	    (type == LINE6_GUITARPORT) ||
+	    (type == LINE6_TONEPORT_GX);
+	/* add your device here if you are missing support for the LEDs */
+}
+
+static const char * const led_colors[2] = { "red", "green" };
+static const int led_init_vals[2] = { 0x00, 0x26 };
+
+static void toneport_update_led(struct usb_line6_toneport *toneport)
+{
+	toneport_send_cmd(toneport->line6.usbdev,
+			  (toneport->leds[0].dev.brightness << 8) | 0x0002,
+			  toneport->leds[1].dev.brightness);
+}
+
+static void toneport_led_brightness_set(struct led_classdev *led_cdev,
+					enum led_brightness brightness)
+{
+	struct toneport_led *leds =
+		container_of(led_cdev, struct toneport_led, dev);
+	toneport_update_led(leds->toneport);
+}
+
+static int toneport_init_leds(struct usb_line6_toneport *toneport)
+{
+	struct device *dev = &toneport->line6.usbdev->dev;
+	int i, err;
+
+	for (i = 0; i < 2; i++) {
+		struct toneport_led *led = &toneport->leds[i];
+		struct led_classdev *leddev = &led->dev;
+
+		led->toneport = toneport;
+		snprintf(led->name, sizeof(led->name), "%s::%s",
+			 dev_name(dev), led_colors[i]);
+		leddev->name = led->name;
+		leddev->brightness = led_init_vals[i];
+		leddev->max_brightness = 0x26;
+		leddev->brightness_set = toneport_led_brightness_set;
+		err = led_classdev_register(dev, leddev);
+		if (err)
+			return err;
+		led->registered = true;
+	}
+
+	return 0;
+}
+
+static void toneport_remove_leds(struct usb_line6_toneport *toneport)
+{
+	struct toneport_led *led;
+	int i;
+
+	for (i = 0; i < 2; i++) {
+		led = &toneport->leds[i];
+		if (!led->registered)
+			break;
+		led_classdev_unregister(&led->dev);
+		led->registered = false;
+	}
+}
+
+/*
+	Setup Toneport device.
+*/
+static void toneport_setup(struct usb_line6_toneport *toneport)
+{
+	int ticks;
+	struct usb_line6 *line6 = &toneport->line6;
+	struct usb_device *usbdev = line6->usbdev;
+
+	/* sync time on device with host: */
+	ticks = (int)get_seconds();
+	line6_write_data(line6, 0x80c6, &ticks, 4);
+
+	/* enable device: */
+	toneport_send_cmd(usbdev, 0x0301, 0x0000);
+
+	/* initialize source select: */
+	switch (toneport->type) {
+	case LINE6_TONEPORT_UX1:
+	case LINE6_TONEPORT_UX2:
+	case LINE6_PODSTUDIO_UX1:
+	case LINE6_PODSTUDIO_UX2:
+		toneport_send_cmd(usbdev,
+				  toneport_source_info[toneport->source].code,
+				  0x0000);
+	default:
+		break;
+	}
+
+	if (toneport_has_led(toneport->type))
+		toneport_update_led(toneport);
+
+	mod_timer(&toneport->timer, jiffies + TONEPORT_PCM_DELAY * HZ);
+}
+
+/*
+	Toneport device disconnected.
+*/
+static void line6_toneport_disconnect(struct usb_line6 *line6)
+{
+	struct usb_line6_toneport *toneport =
+		(struct usb_line6_toneport *)line6;
+
+	del_timer_sync(&toneport->timer);
+
+	if (toneport_has_led(toneport->type))
+		toneport_remove_leds(toneport);
+}
+
+
+/*
+	 Try to init Toneport device.
+*/
+static int toneport_init(struct usb_line6 *line6,
+			 const struct usb_device_id *id)
+{
+	int err;
+	struct usb_line6_toneport *toneport =  (struct usb_line6_toneport *) line6;
+
+	toneport->type = id->driver_info;
+	setup_timer(&toneport->timer, toneport_start_pcm,
+		    (unsigned long)toneport);
+
+	line6->disconnect = line6_toneport_disconnect;
+
+	/* initialize PCM subsystem: */
+	err = line6_init_pcm(line6, &toneport_pcm_properties);
+	if (err < 0)
+		return err;
+
+	/* register monitor control: */
+	err = snd_ctl_add(line6->card,
+			  snd_ctl_new1(&toneport_control_monitor,
+				       line6->line6pcm));
+	if (err < 0)
+		return err;
+
+	/* register source select control: */
+	switch (toneport->type) {
+	case LINE6_TONEPORT_UX1:
+	case LINE6_TONEPORT_UX2:
+	case LINE6_PODSTUDIO_UX1:
+	case LINE6_PODSTUDIO_UX2:
+		err =
+		    snd_ctl_add(line6->card,
+				snd_ctl_new1(&toneport_control_source,
+					     line6->line6pcm));
+		if (err < 0)
+			return err;
+
+	default:
+		break;
+	}
+
+	line6_read_serial_number(line6, &toneport->serial_number);
+	line6_read_data(line6, 0x80c2, &toneport->firmware_version, 1);
+
+	if (toneport_has_led(toneport->type)) {
+		err = toneport_init_leds(toneport);
+		if (err < 0)
+			return err;
+	}
+
+	toneport_setup(toneport);
+
+	/* register audio system: */
+	return snd_card_register(line6->card);
+}
+
+#ifdef CONFIG_PM
+/*
+	Resume Toneport device after reset.
+*/
+static int toneport_reset_resume(struct usb_interface *interface)
+{
+	toneport_setup(usb_get_intfdata(interface));
+	return line6_resume(interface);
+}
+#endif
+
+#define LINE6_DEVICE(prod) USB_DEVICE(0x0e41, prod)
+#define LINE6_IF_NUM(prod, n) USB_DEVICE_INTERFACE_NUMBER(0x0e41, prod, n)
+
+/* table of devices that work with this driver */
+static const struct usb_device_id toneport_id_table[] = {
+	{ LINE6_DEVICE(0x4750),    .driver_info = LINE6_GUITARPORT },
+	{ LINE6_DEVICE(0x4153),    .driver_info = LINE6_PODSTUDIO_GX },
+	{ LINE6_DEVICE(0x4150),    .driver_info = LINE6_PODSTUDIO_UX1 },
+	{ LINE6_IF_NUM(0x4151, 0), .driver_info = LINE6_PODSTUDIO_UX2 },
+	{ LINE6_DEVICE(0x4147),    .driver_info = LINE6_TONEPORT_GX },
+	{ LINE6_DEVICE(0x4141),    .driver_info = LINE6_TONEPORT_UX1 },
+	{ LINE6_IF_NUM(0x4142, 0), .driver_info = LINE6_TONEPORT_UX2 },
+	{}
+};
+
+MODULE_DEVICE_TABLE(usb, toneport_id_table);
+
+static const struct line6_properties toneport_properties_table[] = {
+	[LINE6_GUITARPORT] = {
+		.id = "GuitarPort",
+		.name = "GuitarPort",
+		.capabilities	= LINE6_CAP_PCM,
+		.altsetting = 2,  /* 1..4 seem to be ok */
+		/* no control channel */
+		.ep_audio_r = 0x82,
+		.ep_audio_w = 0x01,
+	},
+	[LINE6_PODSTUDIO_GX] = {
+		.id = "PODStudioGX",
+		.name = "POD Studio GX",
+		.capabilities	= LINE6_CAP_PCM,
+		.altsetting = 2,  /* 1..4 seem to be ok */
+		/* no control channel */
+		.ep_audio_r = 0x82,
+		.ep_audio_w = 0x01,
+	},
+	[LINE6_PODSTUDIO_UX1] = {
+		.id = "PODStudioUX1",
+		.name = "POD Studio UX1",
+		.capabilities	= LINE6_CAP_PCM,
+		.altsetting = 2,  /* 1..4 seem to be ok */
+		/* no control channel */
+		.ep_audio_r = 0x82,
+		.ep_audio_w = 0x01,
+	},
+	[LINE6_PODSTUDIO_UX2] = {
+		.id = "PODStudioUX2",
+		.name = "POD Studio UX2",
+		.capabilities	= LINE6_CAP_PCM,
+		.altsetting = 2,  /* defaults to 44.1kHz, 16-bit */
+		/* no control channel */
+		.ep_audio_r = 0x82,
+		.ep_audio_w = 0x01,
+	},
+	[LINE6_TONEPORT_GX] = {
+		.id = "TonePortGX",
+		.name = "TonePort GX",
+		.capabilities	= LINE6_CAP_PCM,
+		.altsetting = 2,  /* 1..4 seem to be ok */
+		/* no control channel */
+		.ep_audio_r = 0x82,
+		.ep_audio_w = 0x01,
+	},
+	[LINE6_TONEPORT_UX1] = {
+		.id = "TonePortUX1",
+		.name = "TonePort UX1",
+		.capabilities	= LINE6_CAP_PCM,
+		.altsetting = 2,  /* 1..4 seem to be ok */
+		/* no control channel */
+		.ep_audio_r = 0x82,
+		.ep_audio_w = 0x01,
+	},
+	[LINE6_TONEPORT_UX2] = {
+		.id = "TonePortUX2",
+		.name = "TonePort UX2",
+		.capabilities	= LINE6_CAP_PCM,
+		.altsetting = 2,  /* defaults to 44.1kHz, 16-bit */
+		/* no control channel */
+		.ep_audio_r = 0x82,
+		.ep_audio_w = 0x01,
+	},
+};
+
+/*
+	Probe USB device.
+*/
+static int toneport_probe(struct usb_interface *interface,
+			  const struct usb_device_id *id)
+{
+	return line6_probe(interface, id,
+			   &toneport_properties_table[id->driver_info],
+			   toneport_init, sizeof(struct usb_line6_toneport));
+}
+
+static struct usb_driver toneport_driver = {
+	.name = KBUILD_MODNAME,
+	.probe = toneport_probe,
+	.disconnect = line6_disconnect,
+#ifdef CONFIG_PM
+	.suspend = line6_suspend,
+	.resume = line6_resume,
+	.reset_resume = toneport_reset_resume,
+#endif
+	.id_table = toneport_id_table,
+};
+
+module_usb_driver(toneport_driver);
+
+MODULE_DESCRIPTION("TonePort USB driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/line6/variax.c b/sound/usb/line6/variax.c
similarity index 60%
rename from drivers/staging/line6/variax.c
rename to sound/usb/line6/variax.c
index ae2be99..b1c1de6 100644
--- a/drivers/staging/line6/variax.c
+++ b/sound/usb/line6/variax.c
@@ -1,5 +1,5 @@
 /*
- * Line6 Linux USB driver - 0.9.1beta
+ * Line 6 Linux USB driver
  *
  * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
  *
@@ -10,10 +10,53 @@
  */
 
 #include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/usb.h>
+#include <linux/wait.h>
+#include <linux/module.h>
+#include <sound/core.h>
 
-#include "audio.h"
 #include "driver.h"
-#include "variax.h"
+
+#define VARIAX_STARTUP_DELAY1 1000
+#define VARIAX_STARTUP_DELAY3 100
+#define VARIAX_STARTUP_DELAY4 100
+
+/*
+	Stages of Variax startup procedure
+*/
+enum {
+	VARIAX_STARTUP_INIT = 1,
+	VARIAX_STARTUP_VERSIONREQ,
+	VARIAX_STARTUP_WAIT,
+	VARIAX_STARTUP_ACTIVATE,
+	VARIAX_STARTUP_WORKQUEUE,
+	VARIAX_STARTUP_SETUP,
+	VARIAX_STARTUP_LAST = VARIAX_STARTUP_SETUP - 1
+};
+
+enum {
+	LINE6_PODXTLIVE_VARIAX,
+	LINE6_VARIAX
+};
+
+struct usb_line6_variax {
+	/* Generic Line 6 USB data */
+	struct usb_line6 line6;
+
+	/* Buffer for activation code */
+	unsigned char *buffer_activate;
+
+	/* Handler for device initialization */
+	struct work_struct startup_work;
+
+	/* Timers for device initialization */
+	struct timer_list startup_timer1;
+	struct timer_list startup_timer2;
+
+	/* Current progress in startup procedure */
+	int startup_progress;
+};
 
 #define VARIAX_OFFSET_ACTIVATE 7
 
@@ -124,14 +167,15 @@
 	CHECK_STARTUP_PROGRESS(variax->startup_progress, VARIAX_STARTUP_SETUP);
 
 	/* ALSA audio interface: */
-	line6_register_audio(&variax->line6);
+	snd_card_register(variax->line6.card);
 }
 
 /*
 	Process a completely received message.
 */
-void line6_variax_process_message(struct usb_line6_variax *variax)
+static void line6_variax_process_message(struct usb_line6 *line6)
 {
+	struct usb_line6_variax *variax = (struct usb_line6_variax *) line6;
 	const unsigned char *buf = variax->line6.buffer_message;
 
 	switch (buf[0]) {
@@ -155,13 +199,9 @@
 /*
 	Variax destructor.
 */
-static void variax_destruct(struct usb_interface *interface)
+static void line6_variax_disconnect(struct usb_line6 *line6)
 {
-	struct usb_line6_variax *variax = usb_get_intfdata(interface);
-
-	if (variax == NULL)
-		return;
-	line6_cleanup_audio(&variax->line6);
+	struct usb_line6_variax *variax = (struct usb_line6_variax *)line6;
 
 	del_timer(&variax->startup_timer1);
 	del_timer(&variax->startup_timer2);
@@ -173,31 +213,25 @@
 /*
 	 Try to init workbench device.
 */
-static int variax_try_init(struct usb_interface *interface,
-			   struct usb_line6_variax *variax)
+static int variax_init(struct usb_line6 *line6,
+		       const struct usb_device_id *id)
 {
+	struct usb_line6_variax *variax = (struct usb_line6_variax *) line6;
 	int err;
 
+	line6->process_message = line6_variax_process_message;
+	line6->disconnect = line6_variax_disconnect;
+
 	init_timer(&variax->startup_timer1);
 	init_timer(&variax->startup_timer2);
 	INIT_WORK(&variax->startup_work, variax_startup6);
 
-	if ((interface == NULL) || (variax == NULL))
-		return -ENODEV;
-
 	/* initialize USB buffers: */
 	variax->buffer_activate = kmemdup(variax_activate,
 					  sizeof(variax_activate), GFP_KERNEL);
 
-	if (variax->buffer_activate == NULL) {
-		dev_err(&interface->dev, "Out of memory\n");
+	if (variax->buffer_activate == NULL)
 		return -ENOMEM;
-	}
-
-	/* initialize audio system: */
-	err = line6_init_audio(&variax->line6);
-	if (err < 0)
-		return err;
 
 	/* initialize MIDI subsystem: */
 	err = line6_init_midi(&variax->line6);
@@ -209,27 +243,64 @@
 	return 0;
 }
 
-/*
-	 Init workbench device (and clean up in case of failure).
-*/
-int line6_variax_init(struct usb_interface *interface,
-		      struct usb_line6_variax *variax)
-{
-	int err = variax_try_init(interface, variax);
+#define LINE6_DEVICE(prod) USB_DEVICE(0x0e41, prod)
+#define LINE6_IF_NUM(prod, n) USB_DEVICE_INTERFACE_NUMBER(0x0e41, prod, n)
 
-	if (err < 0)
-		variax_destruct(interface);
+/* table of devices that work with this driver */
+static const struct usb_device_id variax_id_table[] = {
+	{ LINE6_IF_NUM(0x4650, 1), .driver_info = LINE6_PODXTLIVE_VARIAX },
+	{ LINE6_DEVICE(0x534d),    .driver_info = LINE6_VARIAX },
+	{}
+};
 
-	return err;
-}
+MODULE_DEVICE_TABLE(usb, variax_id_table);
+
+static const struct line6_properties variax_properties_table[] = {
+	[LINE6_PODXTLIVE_VARIAX] = {
+		.id = "PODxtLive",
+		.name = "PODxt Live",
+		.capabilities	= LINE6_CAP_CONTROL,
+		.altsetting = 1,
+		.ep_ctrl_r = 0x86,
+		.ep_ctrl_w = 0x05,
+		.ep_audio_r = 0x82,
+		.ep_audio_w = 0x01,
+	},
+	[LINE6_VARIAX] = {
+		.id = "Variax",
+		.name = "Variax Workbench",
+		.capabilities	= LINE6_CAP_CONTROL,
+		.altsetting = 1,
+		.ep_ctrl_r = 0x82,
+		.ep_ctrl_w = 0x01,
+		/* no audio channel */
+	}
+};
 
 /*
-	Workbench device disconnected.
+	Probe USB device.
 */
-void line6_variax_disconnect(struct usb_interface *interface)
+static int variax_probe(struct usb_interface *interface,
+			const struct usb_device_id *id)
 {
-	if (interface == NULL)
-		return;
-
-	variax_destruct(interface);
+	return line6_probe(interface, id,
+			   &variax_properties_table[id->driver_info],
+			   variax_init, sizeof(struct usb_line6_variax));
 }
+
+static struct usb_driver variax_driver = {
+	.name = KBUILD_MODNAME,
+	.probe = variax_probe,
+	.disconnect = line6_disconnect,
+#ifdef CONFIG_PM
+	.suspend = line6_suspend,
+	.resume = line6_resume,
+	.reset_resume = line6_resume,
+#endif
+	.id_table = variax_id_table,
+};
+
+module_usb_driver(variax_driver);
+
+MODULE_DESCRIPTION("Vairax Workbench USB driver");
+MODULE_LICENSE("GPL");
diff --git a/sound/usb/midi.c b/sound/usb/midi.c
index 5bfb695..417ebb1 100644
--- a/sound/usb/midi.c
+++ b/sound/usb/midi.c
@@ -2292,14 +2292,13 @@
 	umidi->iface = iface;
 	umidi->quirk = quirk;
 	umidi->usb_protocol_ops = &snd_usbmidi_standard_ops;
-	init_timer(&umidi->error_timer);
 	spin_lock_init(&umidi->disc_lock);
 	init_rwsem(&umidi->disc_rwsem);
 	mutex_init(&umidi->mutex);
 	umidi->usb_id = USB_ID(le16_to_cpu(umidi->dev->descriptor.idVendor),
 			       le16_to_cpu(umidi->dev->descriptor.idProduct));
-	umidi->error_timer.function = snd_usbmidi_error_timer;
-	umidi->error_timer.data = (unsigned long)umidi;
+	setup_timer(&umidi->error_timer, snd_usbmidi_error_timer,
+		    (unsigned long)umidi);
 
 	/* detect the endpoint(s) to use */
 	memset(endpoints, 0, sizeof(endpoints));
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index 0a598af..67d4765 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -2486,6 +2486,28 @@
 	}
 },
 
+{
+	/* Akai MPC Element */
+	USB_DEVICE(0x09e8, 0x0021),
+	.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+		.ifnum = QUIRK_ANY_INTERFACE,
+		.type = QUIRK_COMPOSITE,
+		.data = & (const struct snd_usb_audio_quirk[]) {
+			{
+				.ifnum = 0,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 1,
+				.type = QUIRK_MIDI_STANDARD_INTERFACE
+			},
+			{
+				.ifnum = -1
+			}
+		}
+	}
+},
+
 /* TerraTec devices */
 {
 	USB_DEVICE_VENDOR_SPEC(0x0ccd, 0x0012),
diff --git a/sound/usb/usx2y/usb_stream.h b/sound/usb/usx2y/usb_stream.h
index 4dd74ab..9036900 100644
--- a/sound/usb/usx2y/usb_stream.h
+++ b/sound/usb/usx2y/usb_stream.h
@@ -1,76 +1,7 @@
-/*
- * Copyright (C) 2007, 2008 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
+#ifndef __USB_STREAM_H
+#define __USB_STREAM_H
 
-#define USB_STREAM_INTERFACE_VERSION 2
-
-#define SNDRV_USB_STREAM_IOCTL_SET_PARAMS \
-	_IOW('H', 0x90, struct usb_stream_config)
-
-struct usb_stream_packet {
-	unsigned offset;
-	unsigned length;
-};
-
-
-struct usb_stream_config {
-	unsigned version;
-	unsigned sample_rate;
-	unsigned period_frames;
-	unsigned frame_size;
-};
-
-struct usb_stream {
-	struct usb_stream_config cfg;
-	unsigned read_size;
-	unsigned write_size;
-
-	int period_size;
-
-	unsigned state;
-
-	int idle_insize;
-	int idle_outsize;
-	int sync_packet;
-	unsigned insize_done;
-	unsigned periods_done;
-	unsigned periods_polled;
-
-	struct usb_stream_packet outpacket[2];
-	unsigned		 inpackets;
-	unsigned		 inpacket_head;
-	unsigned		 inpacket_split;
-	unsigned		 inpacket_split_at;
-	unsigned		 next_inpacket_split;
-	unsigned		 next_inpacket_split_at;
-	struct usb_stream_packet inpacket[0];
-};
-
-enum usb_stream_state {
-	usb_stream_invalid,
-	usb_stream_stopped,
-	usb_stream_sync0,
-	usb_stream_sync1,
-	usb_stream_ready,
-	usb_stream_running,
-	usb_stream_xrun,
-};
-
-#if __KERNEL__
+#include <uapi/sound/usb_stream.h>
 
 #define USB_STREAM_NURBS 4
 #define USB_STREAM_URBDEPTH 4
@@ -108,5 +39,4 @@
 int usb_stream_start(struct usb_stream_kernel *);
 void usb_stream_stop(struct usb_stream_kernel *);
 
-
-#endif
+#endif /* __USB_STREAM_H */