summary refs log tree commit diff
path: root/sound/usb
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-10-28 14:25:01 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2011-10-28 14:25:01 -0700
commit68d99b2c8efcb6ed3807a55569300c53b5f88be5 (patch)
treef189c8f2132d3668a2f0e503f5c3f8695b26a1c8 /sound/usb
parent0e59e7e7feb5a12938fbf9135147eeda3238c6c4 (diff)
parent8128c9f21509f9a8b6da94ac432d845dda458406 (diff)
downloadlinux-68d99b2c8efcb6ed3807a55569300c53b5f88be5.tar.gz
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (549 commits)
  ALSA: hda - Fix ADC input-amp handling for Cx20549 codec
  ALSA: hda - Keep EAPD turned on for old Conexant chips
  ALSA: hda/realtek - Fix missing volume controls with ALC260
  ASoC: wm8940: Properly set codec->dapm.bias_level
  ALSA: hda - Fix pin-config for ASUS W90V
  ALSA: hda - Fix surround/CLFE headphone and speaker pins order
  ALSA: hda - Fix typo
  ALSA: Update the sound git tree URL
  ALSA: HDA: Add new revision for ALC662
  ASoC: max98095: Convert codec->hw_write to snd_soc_write
  ASoC: keep pointer to resource so it can be freed
  ASoC: sgtl5000: Fix wrong mask in some snd_soc_update_bits calls
  ASoC: wm8996: Fix wrong mask for setting WM8996_AIF_CLOCKING_2
  ASoC: da7210: Add support for line out and DAC
  ASoC: da7210: Add support for DAPM
  ALSA: hda/realtek - Fix DAC assignments of multiple speakers
  ASoC: Use SGTL5000_LINREG_VDDD_MASK instead of hardcoded mask value
  ASoC: Set sgtl5000->ldo in ldo_regulator_register
  ASoC: wm8996: Use SND_SOC_DAPM_AIF_OUT for AIF2 Capture
  ASoC: wm8994: Use SND_SOC_DAPM_AIF_OUT for AIF3 Capture
  ...
Diffstat (limited to 'sound/usb')
-rw-r--r--sound/usb/6fire/firmware.c25
-rw-r--r--sound/usb/Kconfig2
-rw-r--r--sound/usb/Makefile12
-rw-r--r--sound/usb/caiaq/device.c8
-rw-r--r--sound/usb/caiaq/device.h1
-rw-r--r--sound/usb/caiaq/input.c155
-rw-r--r--sound/usb/card.c4
-rw-r--r--sound/usb/card.h2
-rw-r--r--sound/usb/clock.c12
-rw-r--r--sound/usb/endpoint.c1199
-rw-r--r--sound/usb/endpoint.h20
-rw-r--r--sound/usb/format.c4
-rw-r--r--sound/usb/helper.c4
-rw-r--r--sound/usb/helper.h2
-rw-r--r--sound/usb/midi.c27
-rw-r--r--sound/usb/mixer.c21
-rw-r--r--sound/usb/mixer_quirks.c10
-rw-r--r--sound/usb/pcm.c34
-rw-r--r--sound/usb/pcm.h3
-rw-r--r--sound/usb/quirks-table.h25
-rw-r--r--sound/usb/quirks.c16
-rw-r--r--sound/usb/stream.c452
-rw-r--r--sound/usb/stream.h12
-rw-r--r--sound/usb/urb.c941
-rw-r--r--sound/usb/urb.h21
-rw-r--r--sound/usb/usbaudio.h1
26 files changed, 1648 insertions, 1365 deletions
diff --git a/sound/usb/6fire/firmware.c b/sound/usb/6fire/firmware.c
index 1e3ae3327dd3..07bcfe4d18a7 100644
--- a/sound/usb/6fire/firmware.c
+++ b/sound/usb/6fire/firmware.c
@@ -16,6 +16,7 @@
 
 #include <linux/firmware.h>
 #include <linux/bitrev.h>
+#include <linux/kernel.h>
 
 #include "firmware.h"
 #include "chip.h"
@@ -59,21 +60,19 @@ struct ihex_record {
 	unsigned int txt_offset; /* current position in txt_data */
 };
 
-static u8 usb6fire_fw_ihex_nibble(const u8 n)
-{
-	if (n >= '0' && n <= '9')
-		return n - '0';
-	else if (n >= 'A' && n <= 'F')
-		return n - ('A' - 10);
-	else if (n >= 'a' && n <= 'f')
-		return n - ('a' - 10);
-	return 0;
-}
-
 static u8 usb6fire_fw_ihex_hex(const u8 *data, u8 *crc)
 {
-	u8 val = (usb6fire_fw_ihex_nibble(data[0]) << 4) |
-			usb6fire_fw_ihex_nibble(data[1]);
+	u8 val = 0;
+	int hval;
+
+	hval = hex_to_bin(data[0]);
+	if (hval >= 0)
+		val |= (hval << 4);
+
+	hval = hex_to_bin(data[1]);
+	if (hval >= 0)
+		val |= hval;
+
 	*crc += val;
 	return val;
 }
diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig
index 8beb77563da2..3efc21c3d67c 100644
--- a/sound/usb/Kconfig
+++ b/sound/usb/Kconfig
@@ -67,6 +67,7 @@ config SND_USB_CAIAQ
 	    * Native Instruments Guitar Rig mobile
 	    * Native Instruments Traktor Kontrol X1
 	    * Native Instruments Traktor Kontrol S4
+	    * Native Instruments Maschine Controller
 
 	   To compile this driver as a module, choose M here: the module
 	   will be called snd-usb-caiaq.
@@ -85,6 +86,7 @@ config SND_USB_CAIAQ_INPUT
 	   * Native Instruments Kore Controller 2
 	   * Native Instruments Audio Kontrol 1
 	   * Native Instruments Traktor Kontrol S4
+	   * Native Instruments Maschine Controller
 
 config SND_USB_US122L
 	tristate "Tascam US-122L USB driver"
diff --git a/sound/usb/Makefile b/sound/usb/Makefile
index cf9ed66445fa..ac256dc4c6be 100644
--- a/sound/usb/Makefile
+++ b/sound/usb/Makefile
@@ -3,16 +3,16 @@
 #
 
 snd-usb-audio-objs := 	card.o \
+			clock.o \
+			endpoint.o \
+			format.o \
+			helper.o \
 			mixer.o \
 			mixer_quirks.o \
+			pcm.o \
 			proc.o \
 			quirks.o \
-			format.o \
-			endpoint.o \
-			urb.o \
-			pcm.o \
-			helper.o \
-			clock.o
+			stream.o
 
 snd-usbmidi-lib-objs := midi.o
 
diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c
index 45bc4a2dc6f0..3eb605bd9503 100644
--- a/sound/usb/caiaq/device.c
+++ b/sound/usb/caiaq/device.c
@@ -50,7 +50,8 @@ MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2},"
 			 "{Native Instruments, Session I/O},"
 			 "{Native Instruments, GuitarRig mobile}"
 			 "{Native Instruments, Traktor Kontrol X1}"
-			 "{Native Instruments, Traktor Kontrol S4}");
+			 "{Native Instruments, Traktor Kontrol S4}"
+			 "{Native Instruments, Maschine Controller}");
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */
 static char* id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for this card */
@@ -146,6 +147,11 @@ static struct usb_device_id snd_usb_id_table[] = {
 		.idVendor =     USB_VID_NATIVEINSTRUMENTS,
 		.idProduct =    USB_PID_TRAKTORAUDIO2
 	},
+	{
+		.match_flags =  USB_DEVICE_ID_MATCH_DEVICE,
+		.idVendor =     USB_VID_NATIVEINSTRUMENTS,
+		.idProduct =    USB_PID_MASCHINECONTROLLER
+	},
 	{ /* terminator */ }
 };
 
diff --git a/sound/usb/caiaq/device.h b/sound/usb/caiaq/device.h
index 3f9c6339ae90..562b0bff9c41 100644
--- a/sound/usb/caiaq/device.h
+++ b/sound/usb/caiaq/device.h
@@ -18,6 +18,7 @@
 #define USB_PID_TRAKTORKONTROLX1	0x2305
 #define USB_PID_TRAKTORKONTROLS4	0xbaff
 #define USB_PID_TRAKTORAUDIO2		0x041d
+#define USB_PID_MASCHINECONTROLLER  0x0808
 
 #define EP1_BUFSIZE 64
 #define EP4_BUFSIZE 512
diff --git a/sound/usb/caiaq/input.c b/sound/usb/caiaq/input.c
index a213813487bd..26a121b42c3c 100644
--- a/sound/usb/caiaq/input.c
+++ b/sound/usb/caiaq/input.c
@@ -67,6 +67,61 @@ static unsigned short keycode_kore[] = {
 	KEY_BRL_DOT5
 };
 
+#define MASCHINE_BUTTONS   (42)
+#define MASCHINE_BUTTON(X) ((X) + BTN_MISC)
+#define MASCHINE_PADS      (16)
+#define MASCHINE_PAD(X)    ((X) + ABS_PRESSURE)
+
+static unsigned short keycode_maschine[] = {
+	MASCHINE_BUTTON(40), /* mute       */
+	MASCHINE_BUTTON(39), /* solo       */
+	MASCHINE_BUTTON(38), /* select     */
+	MASCHINE_BUTTON(37), /* duplicate  */
+	MASCHINE_BUTTON(36), /* navigate   */
+	MASCHINE_BUTTON(35), /* pad mode   */
+	MASCHINE_BUTTON(34), /* pattern    */
+	MASCHINE_BUTTON(33), /* scene      */
+	KEY_RESERVED, /* spacer */
+
+	MASCHINE_BUTTON(30), /* rec        */
+	MASCHINE_BUTTON(31), /* erase      */
+	MASCHINE_BUTTON(32), /* shift      */
+	MASCHINE_BUTTON(28), /* grid       */
+	MASCHINE_BUTTON(27), /* >          */
+	MASCHINE_BUTTON(26), /* <          */
+	MASCHINE_BUTTON(25), /* restart    */
+
+	MASCHINE_BUTTON(21), /* E          */
+	MASCHINE_BUTTON(22), /* F          */
+	MASCHINE_BUTTON(23), /* G          */
+	MASCHINE_BUTTON(24), /* H          */
+	MASCHINE_BUTTON(20), /* D          */
+	MASCHINE_BUTTON(19), /* C          */
+	MASCHINE_BUTTON(18), /* B          */
+	MASCHINE_BUTTON(17), /* A          */
+
+	MASCHINE_BUTTON(0),  /* control    */
+	MASCHINE_BUTTON(2),  /* browse     */
+	MASCHINE_BUTTON(4),  /* <          */
+	MASCHINE_BUTTON(6),  /* snap       */
+	MASCHINE_BUTTON(7),  /* autowrite  */
+	MASCHINE_BUTTON(5),  /* >          */
+	MASCHINE_BUTTON(3),  /* sampling   */
+	MASCHINE_BUTTON(1),  /* step       */
+
+	MASCHINE_BUTTON(15), /* 8 softkeys */
+	MASCHINE_BUTTON(14),
+	MASCHINE_BUTTON(13),
+	MASCHINE_BUTTON(12),
+	MASCHINE_BUTTON(11),
+	MASCHINE_BUTTON(10),
+	MASCHINE_BUTTON(9),
+	MASCHINE_BUTTON(8),
+
+	MASCHINE_BUTTON(16), /* note repeat */
+	MASCHINE_BUTTON(29)  /* play        */
+};
+
 #define KONTROLX1_INPUTS	(40)
 #define KONTROLS4_BUTTONS	(12 * 8)
 #define KONTROLS4_AXIS		(46)
@@ -218,6 +273,29 @@ static void snd_caiaq_input_read_erp(struct snd_usb_caiaqdev *dev,
 		input_report_abs(input_dev, ABS_HAT3Y, i);
 		input_sync(input_dev);
 		break;
+
+	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_MASCHINECONTROLLER):
+		/* 4 under the left screen */
+		input_report_abs(input_dev, ABS_HAT0X, decode_erp(buf[21], buf[20]));
+		input_report_abs(input_dev, ABS_HAT0Y, decode_erp(buf[15], buf[14]));
+		input_report_abs(input_dev, ABS_HAT1X, decode_erp(buf[9],  buf[8]));
+		input_report_abs(input_dev, ABS_HAT1Y, decode_erp(buf[3],  buf[2]));
+
+		/* 4 under the right screen */
+		input_report_abs(input_dev, ABS_HAT2X, decode_erp(buf[19], buf[18]));
+		input_report_abs(input_dev, ABS_HAT2Y, decode_erp(buf[13], buf[12]));
+		input_report_abs(input_dev, ABS_HAT3X, decode_erp(buf[7],  buf[6]));
+		input_report_abs(input_dev, ABS_HAT3Y, decode_erp(buf[1],  buf[0]));
+
+		/* volume */
+		input_report_abs(input_dev, ABS_RX, decode_erp(buf[17], buf[16]));
+		/* tempo */
+		input_report_abs(input_dev, ABS_RY, decode_erp(buf[11], buf[10]));
+		/* swing */
+		input_report_abs(input_dev, ABS_RZ, decode_erp(buf[5],  buf[4]));
+
+		input_sync(input_dev);
+		break;
 	}
 }
 
@@ -400,6 +478,25 @@ static void snd_usb_caiaq_tks4_dispatch(struct snd_usb_caiaqdev *dev,
 	input_sync(dev->input_dev);
 }
 
+#define MASCHINE_MSGBLOCK_SIZE 2
+
+static void snd_usb_caiaq_maschine_dispatch(struct snd_usb_caiaqdev *dev,
+					const unsigned char *buf,
+					unsigned int len)
+{
+	unsigned int i, pad_id;
+	uint16_t pressure;
+
+	for (i = 0; i < MASCHINE_PADS; i++) {
+		pressure = be16_to_cpu(buf[i * 2] << 8 | buf[(i * 2) + 1]);
+		pad_id = pressure >> 12;
+
+		input_report_abs(dev->input_dev, MASCHINE_PAD(pad_id), pressure & 0xfff);
+	}
+
+	input_sync(dev->input_dev);
+}
+
 static void snd_usb_caiaq_ep4_reply_dispatch(struct urb *urb)
 {
 	struct snd_usb_caiaqdev *dev = urb->context;
@@ -425,6 +522,13 @@ static void snd_usb_caiaq_ep4_reply_dispatch(struct urb *urb)
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLS4):
 		snd_usb_caiaq_tks4_dispatch(dev, buf, urb->actual_length);
 		break;
+
+	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_MASCHINECONTROLLER):
+		if (urb->actual_length < (MASCHINE_PADS * MASCHINE_MSGBLOCK_SIZE))
+			goto requeue;
+
+		snd_usb_caiaq_maschine_dispatch(dev, buf, urb->actual_length);
+		break;
 	}
 
 requeue:
@@ -444,6 +548,7 @@ static int snd_usb_caiaq_input_open(struct input_dev *idev)
 	switch (dev->chip.usb_id) {
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLS4):
+	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_MASCHINECONTROLLER):
 		if (usb_submit_urb(dev->ep4_in_urb, GFP_KERNEL) != 0)
 			return -EIO;
 		break;
@@ -462,6 +567,7 @@ static void snd_usb_caiaq_input_close(struct input_dev *idev)
 	switch (dev->chip.usb_id) {
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLS4):
+	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_MASCHINECONTROLLER):
 		usb_kill_urb(dev->ep4_in_urb);
 		break;
 	}
@@ -652,6 +758,50 @@ int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *dev)
 
 		break;
 
+	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_MASCHINECONTROLLER):
+		input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+		input->absbit[0] = BIT_MASK(ABS_HAT0X) | BIT_MASK(ABS_HAT0Y) |
+			BIT_MASK(ABS_HAT1X) | BIT_MASK(ABS_HAT1Y) |
+			BIT_MASK(ABS_HAT2X) | BIT_MASK(ABS_HAT2Y) |
+			BIT_MASK(ABS_HAT3X) | BIT_MASK(ABS_HAT3Y) |
+			BIT_MASK(ABS_RX) | BIT_MASK(ABS_RY) |
+			BIT_MASK(ABS_RZ);
+
+		BUILD_BUG_ON(sizeof(dev->keycode) < sizeof(keycode_maschine));
+		memcpy(dev->keycode, keycode_maschine, sizeof(keycode_maschine));
+		input->keycodemax = ARRAY_SIZE(keycode_maschine);
+
+		for (i = 0; i < MASCHINE_PADS; i++) {
+			input->absbit[0] |= MASCHINE_PAD(i);
+			input_set_abs_params(input, MASCHINE_PAD(i), 0, 0xfff, 5, 10);
+		}
+
+		input_set_abs_params(input, ABS_HAT0X, 0, 999, 0, 10);
+		input_set_abs_params(input, ABS_HAT0Y, 0, 999, 0, 10);
+		input_set_abs_params(input, ABS_HAT1X, 0, 999, 0, 10);
+		input_set_abs_params(input, ABS_HAT1Y, 0, 999, 0, 10);
+		input_set_abs_params(input, ABS_HAT2X, 0, 999, 0, 10);
+		input_set_abs_params(input, ABS_HAT2Y, 0, 999, 0, 10);
+		input_set_abs_params(input, ABS_HAT3X, 0, 999, 0, 10);
+		input_set_abs_params(input, ABS_HAT3Y, 0, 999, 0, 10);
+		input_set_abs_params(input, ABS_RX, 0, 999, 0, 10);
+		input_set_abs_params(input, ABS_RY, 0, 999, 0, 10);
+		input_set_abs_params(input, ABS_RZ, 0, 999, 0, 10);
+
+		dev->ep4_in_urb = usb_alloc_urb(0, GFP_KERNEL);
+		if (!dev->ep4_in_urb) {
+			ret = -ENOMEM;
+			goto exit_free_idev;
+		}
+
+		usb_fill_bulk_urb(dev->ep4_in_urb, usb_dev,
+				  usb_rcvbulkpipe(usb_dev, 0x4),
+				  dev->ep4_in_buf, EP4_BUFSIZE,
+				  snd_usb_caiaq_ep4_reply_dispatch, dev);
+
+		snd_usb_caiaq_set_auto_msg(dev, 1, 10, 5);
+		break;
+
 	default:
 		/* no input methods supported on this device */
 		goto exit_free_idev;
@@ -664,15 +814,17 @@ int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *dev)
 	for (i = 0; i < input->keycodemax; i++)
 		__set_bit(dev->keycode[i], input->keybit);
 
+	dev->input_dev = input;
+
 	ret = input_register_device(input);
 	if (ret < 0)
 		goto exit_free_idev;
 
-	dev->input_dev = input;
 	return 0;
 
 exit_free_idev:
 	input_free_device(input);
+	dev->input_dev = NULL;
 	return ret;
 }
 
@@ -688,4 +840,3 @@ void snd_usb_caiaq_input_free(struct snd_usb_caiaqdev *dev)
 	input_unregister_device(dev->input_dev);
 	dev->input_dev = NULL;
 }
-
diff --git a/sound/usb/card.c b/sound/usb/card.c
index 3068f043099a..05c1aae0b010 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -65,9 +65,9 @@
 #include "helper.h"
 #include "debug.h"
 #include "pcm.h"
-#include "urb.h"
 #include "format.h"
 #include "power.h"
+#include "stream.h"
 
 MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
 MODULE_DESCRIPTION("USB Audio");
@@ -185,7 +185,7 @@ static int snd_usb_create_stream(struct snd_usb_audio *chip, int ctrlif, int int
 		return -EINVAL;
 	}
 
-	if (! snd_usb_parse_audio_endpoints(chip, interface)) {
+	if (! snd_usb_parse_audio_interface(chip, interface)) {
 		usb_set_interface(dev, interface, 0); /* reset the current interface */
 		usb_driver_claim_interface(&usb_audio_driver, iface, (void *)-1L);
 		return -EINVAL;
diff --git a/sound/usb/card.h b/sound/usb/card.h
index ae4251d5abf7..a39edcc32a93 100644
--- a/sound/usb/card.h
+++ b/sound/usb/card.h
@@ -94,6 +94,8 @@ struct snd_usb_substream {
 	spinlock_t lock;
 
 	struct snd_urb_ops ops;		/* callbacks (must be filled at init) */
+	int last_frame_number;          /* stored frame number */
+	int last_delay;                 /* stored delay */
 };
 
 struct snd_usb_stream {
diff --git a/sound/usb/clock.c b/sound/usb/clock.c
index 075195e8661a..379baad3d5ad 100644
--- a/sound/usb/clock.c
+++ b/sound/usb/clock.c
@@ -91,7 +91,7 @@ static int uac_clock_selector_get_val(struct snd_usb_audio *chip, int selector_i
 			      USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
 			      UAC2_CX_CLOCK_SELECTOR << 8,
 			      snd_usb_ctrl_intf(chip) | (selector_id << 8),
-			      &buf, sizeof(buf), 1000);
+			      &buf, sizeof(buf));
 
 	if (ret < 0)
 		return ret;
@@ -118,7 +118,7 @@ static bool uac_clock_source_is_valid(struct snd_usb_audio *chip, int source_id)
 			      USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
 			      UAC2_CS_CONTROL_CLOCK_VALID << 8,
 			      snd_usb_ctrl_intf(chip) | (source_id << 8),
-			      &data, sizeof(data), 1000);
+			      &data, sizeof(data));
 
 	if (err < 0) {
 		snd_printk(KERN_WARNING "%s(): cannot get clock validity for id %d\n",
@@ -222,7 +222,7 @@ static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface,
 	if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR,
 				   USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_OUT,
 				   UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep,
-				   data, sizeof(data), 1000)) < 0) {
+				   data, sizeof(data))) < 0) {
 		snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d to ep %#x\n",
 			   dev->devnum, iface, fmt->altsetting, rate, ep);
 		return err;
@@ -231,7 +231,7 @@ static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface,
 	if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC_GET_CUR,
 				   USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_IN,
 				   UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep,
-				   data, sizeof(data), 1000)) < 0) {
+				   data, sizeof(data))) < 0) {
 		snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq at ep %#x\n",
 			   dev->devnum, iface, fmt->altsetting, ep);
 		return 0; /* some devices don't support reading */
@@ -273,7 +273,7 @@ static int set_sample_rate_v2(struct snd_usb_audio *chip, int iface,
 				   USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
 				   UAC2_CS_CONTROL_SAM_FREQ << 8,
 				   snd_usb_ctrl_intf(chip) | (clock << 8),
-				   data, sizeof(data), 1000)) < 0) {
+				   data, sizeof(data))) < 0) {
 		snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d (v2)\n",
 			   dev->devnum, iface, fmt->altsetting, rate);
 		return err;
@@ -283,7 +283,7 @@ static int set_sample_rate_v2(struct snd_usb_audio *chip, int iface,
 				   USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
 				   UAC2_CS_CONTROL_SAM_FREQ << 8,
 				   snd_usb_ctrl_intf(chip) | (clock << 8),
-				   data, sizeof(data), 1000)) < 0) {
+				   data, sizeof(data))) < 0) {
 		snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq (v2)\n",
 			   dev->devnum, iface, fmt->altsetting);
 		return err;
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index 7d46e482375d..81c6edecd862 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -15,436 +15,951 @@
  *
  */
 
+#include <linux/gfp.h>
 #include <linux/init.h>
-#include <linux/slab.h>
 #include <linux/usb.h>
 #include <linux/usb/audio.h>
-#include <linux/usb/audio-v2.h>
 
 #include <sound/core.h>
 #include <sound/pcm.h>
 
 #include "usbaudio.h"
+#include "helper.h"
 #include "card.h"
-#include "proc.h"
-#include "quirks.h"
 #include "endpoint.h"
-#include "urb.h"
 #include "pcm.h"
-#include "helper.h"
-#include "format.h"
-#include "clock.h"
 
 /*
- * free a substream
+ * convert a sampling rate into our full speed format (fs/1000 in Q16.16)
+ * this will overflow at approx 524 kHz
  */
-static void free_substream(struct snd_usb_substream *subs)
+static inline unsigned get_usb_full_speed_rate(unsigned int rate)
 {
-	struct list_head *p, *n;
-
-	if (!subs->num_formats)
-		return; /* not initialized */
-	list_for_each_safe(p, n, &subs->fmt_list) {
-		struct audioformat *fp = list_entry(p, struct audioformat, list);
-		kfree(fp->rate_table);
-		kfree(fp);
-	}
-	kfree(subs->rate_list.list);
+	return ((rate << 13) + 62) / 125;
 }
 
+/*
+ * convert a sampling rate into USB high speed format (fs/8000 in Q16.16)
+ * this will overflow at approx 4 MHz
+ */
+static inline unsigned get_usb_high_speed_rate(unsigned int rate)
+{
+	return ((rate << 10) + 62) / 125;
+}
 
 /*
- * free a usb stream instance
+ * unlink active urbs.
  */
-static void snd_usb_audio_stream_free(struct snd_usb_stream *stream)
+static int deactivate_urbs(struct snd_usb_substream *subs, int force, int can_sleep)
 {
-	free_substream(&stream->substream[0]);
-	free_substream(&stream->substream[1]);
-	list_del(&stream->list);
-	kfree(stream);
+	struct snd_usb_audio *chip = subs->stream->chip;
+	unsigned int i;
+	int async;
+
+	subs->running = 0;
+
+	if (!force && subs->stream->chip->shutdown) /* to be sure... */
+		return -EBADFD;
+
+	async = !can_sleep && chip->async_unlink;
+
+	if (!async && in_interrupt())
+		return 0;
+
+	for (i = 0; i < subs->nurbs; i++) {
+		if (test_bit(i, &subs->active_mask)) {
+			if (!test_and_set_bit(i, &subs->unlink_mask)) {
+				struct urb *u = subs->dataurb[i].urb;
+				if (async)
+					usb_unlink_urb(u);
+				else
+					usb_kill_urb(u);
+			}
+		}
+	}
+	if (subs->syncpipe) {
+		for (i = 0; i < SYNC_URBS; i++) {
+			if (test_bit(i+16, &subs->active_mask)) {
+				if (!test_and_set_bit(i+16, &subs->unlink_mask)) {
+					struct urb *u = subs->syncurb[i].urb;
+					if (async)
+						usb_unlink_urb(u);
+					else
+						usb_kill_urb(u);
+				}
+			}
+		}
+	}
+	return 0;
 }
 
-static void snd_usb_audio_pcm_free(struct snd_pcm *pcm)
+
+/*
+ * release a urb data
+ */
+static void release_urb_ctx(struct snd_urb_ctx *u)
 {
-	struct snd_usb_stream *stream = pcm->private_data;
-	if (stream) {
-		stream->pcm = NULL;
-		snd_usb_audio_stream_free(stream);
+	if (u->urb) {
+		if (u->buffer_size)
+			usb_free_coherent(u->subs->dev, u->buffer_size,
+					u->urb->transfer_buffer,
+					u->urb->transfer_dma);
+		usb_free_urb(u->urb);
+		u->urb = NULL;
 	}
 }
 
+/*
+ *  wait until all urbs are processed.
+ */
+static int wait_clear_urbs(struct snd_usb_substream *subs)
+{
+	unsigned long end_time = jiffies + msecs_to_jiffies(1000);
+	unsigned int i;
+	int alive;
+
+	do {
+		alive = 0;
+		for (i = 0; i < subs->nurbs; i++) {
+			if (test_bit(i, &subs->active_mask))
+				alive++;
+		}
+		if (subs->syncpipe) {
+			for (i = 0; i < SYNC_URBS; i++) {
+				if (test_bit(i + 16, &subs->active_mask))
+					alive++;
+			}
+		}
+		if (! alive)
+			break;
+		schedule_timeout_uninterruptible(1);
+	} while (time_before(jiffies, end_time));
+	if (alive)
+		snd_printk(KERN_ERR "timeout: still %d active urbs..\n", alive);
+	return 0;
+}
 
 /*
- * add this endpoint to the chip instance.
- * if a stream with the same endpoint already exists, append to it.
- * if not, create a new pcm stream.
+ * release a substream
  */
-int snd_usb_add_audio_endpoint(struct snd_usb_audio *chip, int stream, struct audioformat *fp)
+void snd_usb_release_substream_urbs(struct snd_usb_substream *subs, int force)
 {
-	struct list_head *p;
-	struct snd_usb_stream *as;
-	struct snd_usb_substream *subs;
-	struct snd_pcm *pcm;
-	int err;
+	int i;
+
+	/* stop urbs (to be sure) */
+	deactivate_urbs(subs, force, 1);
+	wait_clear_urbs(subs);
+
+	for (i = 0; i < MAX_URBS; i++)
+		release_urb_ctx(&subs->dataurb[i]);
+	for (i = 0; i < SYNC_URBS; i++)
+		release_urb_ctx(&subs->syncurb[i]);
+	usb_free_coherent(subs->dev, SYNC_URBS * 4,
+			subs->syncbuf, subs->sync_dma);
+	subs->syncbuf = NULL;
+	subs->nurbs = 0;
+}
 
-	list_for_each(p, &chip->pcm_list) {
-		as = list_entry(p, struct snd_usb_stream, list);
-		if (as->fmt_type != fp->fmt_type)
-			continue;
-		subs = &as->substream[stream];
-		if (!subs->endpoint)
-			continue;
-		if (subs->endpoint == fp->endpoint) {
-			list_add_tail(&fp->list, &subs->fmt_list);
-			subs->num_formats++;
-			subs->formats |= fp->formats;
-			return 0;
+/*
+ * complete callback from data urb
+ */
+static void snd_complete_urb(struct urb *urb)
+{
+	struct snd_urb_ctx *ctx = urb->context;
+	struct snd_usb_substream *subs = ctx->subs;
+	struct snd_pcm_substream *substream = ctx->subs->pcm_substream;
+	int err = 0;
+
+	if ((subs->running && subs->ops.retire(subs, substream->runtime, urb)) ||
+	    !subs->running || /* can be stopped during retire callback */
+	    (err = subs->ops.prepare(subs, substream->runtime, urb)) < 0 ||
+	    (err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
+		clear_bit(ctx->index, &subs->active_mask);
+		if (err < 0) {
+			snd_printd(KERN_ERR "cannot submit urb (err = %d)\n", err);
+			snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
 		}
 	}
-	/* look for an empty stream */
-	list_for_each(p, &chip->pcm_list) {
-		as = list_entry(p, struct snd_usb_stream, list);
-		if (as->fmt_type != fp->fmt_type)
-			continue;
-		subs = &as->substream[stream];
-		if (subs->endpoint)
-			continue;
-		err = snd_pcm_new_stream(as->pcm, stream, 1);
-		if (err < 0)
-			return err;
-		snd_usb_init_substream(as, stream, fp);
-		return 0;
+}
+
+
+/*
+ * complete callback from sync urb
+ */
+static void snd_complete_sync_urb(struct urb *urb)
+{
+	struct snd_urb_ctx *ctx = urb->context;
+	struct snd_usb_substream *subs = ctx->subs;
+	struct snd_pcm_substream *substream = ctx->subs->pcm_substream;
+	int err = 0;
+
+	if ((subs->running && subs->ops.retire_sync(subs, substream->runtime, urb)) ||
+	    !subs->running || /* can be stopped during retire callback */
+	    (err = subs->ops.prepare_sync(subs, substream->runtime, urb)) < 0 ||
+	    (err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
+		clear_bit(ctx->index + 16, &subs->active_mask);
+		if (err < 0) {
+			snd_printd(KERN_ERR "cannot submit sync urb (err = %d)\n", err);
+			snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
+		}
 	}
+}
+
 
-	/* create a new pcm */
-	as = kzalloc(sizeof(*as), GFP_KERNEL);
-	if (!as)
-		return -ENOMEM;
-	as->pcm_index = chip->pcm_devs;
-	as->chip = chip;
-	as->fmt_type = fp->fmt_type;
-	err = snd_pcm_new(chip->card, "USB Audio", chip->pcm_devs,
-			  stream == SNDRV_PCM_STREAM_PLAYBACK ? 1 : 0,
-			  stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1,
-			  &pcm);
-	if (err < 0) {
-		kfree(as);
-		return err;
+/*
+ * initialize a substream for plaback/capture
+ */
+int snd_usb_init_substream_urbs(struct snd_usb_substream *subs,
+				unsigned int period_bytes,
+				unsigned int rate,
+				unsigned int frame_bits)
+{
+	unsigned int maxsize, i;
+	int is_playback = subs->direction == SNDRV_PCM_STREAM_PLAYBACK;
+	unsigned int urb_packs, total_packs, packs_per_ms;
+	struct snd_usb_audio *chip = subs->stream->chip;
+
+	/* calculate the frequency in 16.16 format */
+	if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL)
+		subs->freqn = get_usb_full_speed_rate(rate);
+	else
+		subs->freqn = get_usb_high_speed_rate(rate);
+	subs->freqm = subs->freqn;
+	subs->freqshift = INT_MIN;
+	/* calculate max. frequency */
+	if (subs->maxpacksize) {
+		/* whatever fits into a max. size packet */
+		maxsize = subs->maxpacksize;
+		subs->freqmax = (maxsize / (frame_bits >> 3))
+				<< (16 - subs->datainterval);
+	} else {
+		/* no max. packet size: just take 25% higher than nominal */
+		subs->freqmax = subs->freqn + (subs->freqn >> 2);
+		maxsize = ((subs->freqmax + 0xffff) * (frame_bits >> 3))
+				>> (16 - subs->datainterval);
 	}
-	as->pcm = pcm;
-	pcm->private_data = as;
-	pcm->private_free = snd_usb_audio_pcm_free;
-	pcm->info_flags = 0;
-	if (chip->pcm_devs > 0)
-		sprintf(pcm->name, "USB Audio #%d", chip->pcm_devs);
+	subs->phase = 0;
+
+	if (subs->fill_max)
+		subs->curpacksize = subs->maxpacksize;
 	else
-		strcpy(pcm->name, "USB Audio");
+		subs->curpacksize = maxsize;
 
-	snd_usb_init_substream(as, stream, fp);
+	if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL)
+		packs_per_ms = 8 >> subs->datainterval;
+	else
+		packs_per_ms = 1;
+
+	if (is_playback) {
+		urb_packs = max(chip->nrpacks, 1);
+		urb_packs = min(urb_packs, (unsigned int)MAX_PACKS);
+	} else
+		urb_packs = 1;
+	urb_packs *= packs_per_ms;
+	if (subs->syncpipe)
+		urb_packs = min(urb_packs, 1U << subs->syncinterval);
+
+	/* decide how many packets to be used */
+	if (is_playback) {
+		unsigned int minsize, maxpacks;
+		/* determine how small a packet can be */
+		minsize = (subs->freqn >> (16 - subs->datainterval))
+			  * (frame_bits >> 3);
+		/* with sync from device, assume it can be 12% lower */
+		if (subs->syncpipe)
+			minsize -= minsize >> 3;
+		minsize = max(minsize, 1u);
+		total_packs = (period_bytes + minsize - 1) / minsize;
+		/* we need at least two URBs for queueing */
+		if (total_packs < 2) {
+			total_packs = 2;
+		} else {
+			/* and we don't want too long a queue either */
+			maxpacks = max(MAX_QUEUE * packs_per_ms, urb_packs * 2);
+			total_packs = min(total_packs, maxpacks);
+		}
+	} else {
+		while (urb_packs > 1 && urb_packs * maxsize >= period_bytes)
+			urb_packs >>= 1;
+		total_packs = MAX_URBS * urb_packs;
+	}
+	subs->nurbs = (total_packs + urb_packs - 1) / urb_packs;
+	if (subs->nurbs > MAX_URBS) {
+		/* too much... */
+		subs->nurbs = MAX_URBS;
+		total_packs = MAX_URBS * urb_packs;
+	} else if (subs->nurbs < 2) {
+		/* too little - we need at least two packets
+		 * to ensure contiguous playback/capture
+		 */
+		subs->nurbs = 2;
+	}
 
-	list_add(&as->list, &chip->pcm_list);
-	chip->pcm_devs++;
+	/* allocate and initialize data urbs */
+	for (i = 0; i < subs->nurbs; i++) {
+		struct snd_urb_ctx *u = &subs->dataurb[i];
+		u->index = i;
+		u->subs = subs;
+		u->packets = (i + 1) * total_packs / subs->nurbs
+			- i * total_packs / subs->nurbs;
+		u->buffer_size = maxsize * u->packets;
+		if (subs->fmt_type == UAC_FORMAT_TYPE_II)
+			u->packets++; /* for transfer delimiter */
+		u->urb = usb_alloc_urb(u->packets, GFP_KERNEL);
+		if (!u->urb)
+			goto out_of_memory;
+		u->urb->transfer_buffer =
+			usb_alloc_coherent(subs->dev, u->buffer_size,
+					   GFP_KERNEL, &u->urb->transfer_dma);
+		if (!u->urb->transfer_buffer)
+			goto out_of_memory;
+		u->urb->pipe = subs->datapipe;
+		u->urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
+		u->urb->interval = 1 << subs->datainterval;
+		u->urb->context = u;
+		u->urb->complete = snd_complete_urb;
+	}
+
+	if (subs->syncpipe) {
+		/* allocate and initialize sync urbs */
+		subs->syncbuf = usb_alloc_coherent(subs->dev, SYNC_URBS * 4,
+						 GFP_KERNEL, &subs->sync_dma);
+		if (!subs->syncbuf)
+			goto out_of_memory;
+		for (i = 0; i < SYNC_URBS; i++) {
+			struct snd_urb_ctx *u = &subs->syncurb[i];
+			u->index = i;
+			u->subs = subs;
+			u->packets = 1;
+			u->urb = usb_alloc_urb(1, GFP_KERNEL);
+			if (!u->urb)
+				goto out_of_memory;
+			u->urb->transfer_buffer = subs->syncbuf + i * 4;
+			u->urb->transfer_dma = subs->sync_dma + i * 4;
+			u->urb->transfer_buffer_length = 4;
+			u->urb->pipe = subs->syncpipe;
+			u->urb->transfer_flags = URB_ISO_ASAP |
+						 URB_NO_TRANSFER_DMA_MAP;
+			u->urb->number_of_packets = 1;
+			u->urb->interval = 1 << subs->syncinterval;
+			u->urb->context = u;
+			u->urb->complete = snd_complete_sync_urb;
+		}
+	}
+	return 0;
 
-	snd_usb_proc_pcm_format_add(as);
+out_of_memory:
+	snd_usb_release_substream_urbs(subs, 0);
+	return -ENOMEM;
+}
 
+/*
+ * prepare urb for full speed capture sync pipe
+ *
+ * fill the length and offset of each urb descriptor.
+ * the fixed 10.14 frequency is passed through the pipe.
+ */
+static int prepare_capture_sync_urb(struct snd_usb_substream *subs,
+				    struct snd_pcm_runtime *runtime,
+				    struct urb *urb)
+{
+	unsigned char *cp = urb->transfer_buffer;
+	struct snd_urb_ctx *ctx = urb->context;
+
+	urb->dev = ctx->subs->dev; /* we need to set this at each time */
+	urb->iso_frame_desc[0].length = 3;
+	urb->iso_frame_desc[0].offset = 0;
+	cp[0] = subs->freqn >> 2;
+	cp[1] = subs->freqn >> 10;
+	cp[2] = subs->freqn >> 18;
 	return 0;
 }
 
-static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip,
-					 struct usb_host_interface *alts,
-					 int protocol, int iface_no)
+/*
+ * prepare urb for high speed capture sync pipe
+ *
+ * fill the length and offset of each urb descriptor.
+ * the fixed 12.13 frequency is passed as 16.16 through the pipe.
+ */
+static int prepare_capture_sync_urb_hs(struct snd_usb_substream *subs,
+				       struct snd_pcm_runtime *runtime,
+				       struct urb *urb)
 {
-	/* parsed with a v1 header here. that's ok as we only look at the
-	 * header first which is the same for both versions */
-	struct uac_iso_endpoint_descriptor *csep;
-	struct usb_interface_descriptor *altsd = get_iface_desc(alts);
-	int attributes = 0;
-
-	csep = snd_usb_find_desc(alts->endpoint[0].extra, alts->endpoint[0].extralen, NULL, USB_DT_CS_ENDPOINT);
-
-	/* Creamware Noah has this descriptor after the 2nd endpoint */
-	if (!csep && altsd->bNumEndpoints >= 2)
-		csep = snd_usb_find_desc(alts->endpoint[1].extra, alts->endpoint[1].extralen, NULL, USB_DT_CS_ENDPOINT);
-
-	if (!csep || csep->bLength < 7 ||
-	    csep->bDescriptorSubtype != UAC_EP_GENERAL) {
-		snd_printk(KERN_WARNING "%d:%u:%d : no or invalid"
-			   " class specific endpoint descriptor\n",
-			   chip->dev->devnum, iface_no,
-			   altsd->bAlternateSetting);
-		return 0;
-	}
+	unsigned char *cp = urb->transfer_buffer;
+	struct snd_urb_ctx *ctx = urb->context;
+
+	urb->dev = ctx->subs->dev; /* we need to set this at each time */
+	urb->iso_frame_desc[0].length = 4;
+	urb->iso_frame_desc[0].offset = 0;
+	cp[0] = subs->freqn;
+	cp[1] = subs->freqn >> 8;
+	cp[2] = subs->freqn >> 16;
+	cp[3] = subs->freqn >> 24;
+	return 0;
+}
 
-	if (protocol == UAC_VERSION_1) {
-		attributes = csep->bmAttributes;
-	} else {
-		struct uac2_iso_endpoint_descriptor *csep2 =
-			(struct uac2_iso_endpoint_descriptor *) csep;
+/*
+ * process after capture sync complete
+ * - nothing to do
+ */
+static int retire_capture_sync_urb(struct snd_usb_substream *subs,
+				   struct snd_pcm_runtime *runtime,
+				   struct urb *urb)
+{
+	return 0;
+}
 
-		attributes = csep->bmAttributes & UAC_EP_CS_ATTR_FILL_MAX;
+/*
+ * prepare urb for capture data pipe
+ *
+ * fill the offset and length of each descriptor.
+ *
+ * we use a temporary buffer to write the captured data.
+ * since the length of written data is determined by host, we cannot
+ * write onto the pcm buffer directly...  the data is thus copied
+ * later at complete callback to the global buffer.
+ */
+static int prepare_capture_urb(struct snd_usb_substream *subs,
+			       struct snd_pcm_runtime *runtime,
+			       struct urb *urb)
+{
+	int i, offs;
+	struct snd_urb_ctx *ctx = urb->context;
+
+	offs = 0;
+	urb->dev = ctx->subs->dev; /* we need to set this at each time */
+	for (i = 0; i < ctx->packets; i++) {
+		urb->iso_frame_desc[i].offset = offs;
+		urb->iso_frame_desc[i].length = subs->curpacksize;
+		offs += subs->curpacksize;
+	}
+	urb->transfer_buffer_length = offs;
+	urb->number_of_packets = ctx->packets;
+	return 0;
+}
 
-		/* emulate the endpoint attributes of a v1 device */
-		if (csep2->bmControls & UAC2_CONTROL_PITCH)
-			attributes |= UAC_EP_CS_ATTR_PITCH_CONTROL;
+/*
+ * process after capture complete
+ *
+ * copy the data from each desctiptor to the pcm buffer, and
+ * update the current position.
+ */
+static int retire_capture_urb(struct snd_usb_substream *subs,
+			      struct snd_pcm_runtime *runtime,
+			      struct urb *urb)
+{
+	unsigned long flags;
+	unsigned char *cp;
+	int i;
+	unsigned int stride, frames, bytes, oldptr;
+	int period_elapsed = 0;
+
+	stride = runtime->frame_bits >> 3;
+
+	for (i = 0; i < urb->number_of_packets; i++) {
+		cp = (unsigned char *)urb->transfer_buffer + urb->iso_frame_desc[i].offset;
+		if (urb->iso_frame_desc[i].status) {
+			snd_printd(KERN_ERR "frame %d active: %d\n", i, urb->iso_frame_desc[i].status);
+			// continue;
+		}
+		bytes = urb->iso_frame_desc[i].actual_length;
+		frames = bytes / stride;
+		if (!subs->txfr_quirk)
+			bytes = frames * stride;
+		if (bytes % (runtime->sample_bits >> 3) != 0) {
+#ifdef CONFIG_SND_DEBUG_VERBOSE
+			int oldbytes = bytes;
+#endif
+			bytes = frames * stride;
+			snd_printdd(KERN_ERR "Corrected urb data len. %d->%d\n",
+							oldbytes, bytes);
+		}
+		/* update the current pointer */
+		spin_lock_irqsave(&subs->lock, flags);
+		oldptr = subs->hwptr_done;
+		subs->hwptr_done += bytes;
+		if (subs->hwptr_done >= runtime->buffer_size * stride)
+			subs->hwptr_done -= runtime->buffer_size * stride;
+		frames = (bytes + (oldptr % stride)) / stride;
+		subs->transfer_done += frames;
+		if (subs->transfer_done >= runtime->period_size) {
+			subs->transfer_done -= runtime->period_size;
+			period_elapsed = 1;
+		}
+		spin_unlock_irqrestore(&subs->lock, flags);
+		/* copy a data chunk */
+		if (oldptr + bytes > runtime->buffer_size * stride) {
+			unsigned int bytes1 =
+					runtime->buffer_size * stride - oldptr;
+			memcpy(runtime->dma_area + oldptr, cp, bytes1);
+			memcpy(runtime->dma_area, cp + bytes1, bytes - bytes1);
+		} else {
+			memcpy(runtime->dma_area + oldptr, cp, bytes);
+		}
 	}
+	if (period_elapsed)
+		snd_pcm_period_elapsed(subs->pcm_substream);
+	return 0;
+}
 
-	return attributes;
+/*
+ * Process after capture complete when paused.  Nothing to do.
+ */
+static int retire_paused_capture_urb(struct snd_usb_substream *subs,
+				     struct snd_pcm_runtime *runtime,
+				     struct urb *urb)
+{
+	return 0;
 }
 
-static struct uac2_input_terminal_descriptor *
-	snd_usb_find_input_terminal_descriptor(struct usb_host_interface *ctrl_iface,
-					       int terminal_id)
+
+/*
+ * prepare urb for playback sync pipe
+ *
+ * set up the offset and length to receive the current frequency.
+ */
+static int prepare_playback_sync_urb(struct snd_usb_substream *subs,
+				     struct snd_pcm_runtime *runtime,
+				     struct urb *urb)
 {
-	struct uac2_input_terminal_descriptor *term = NULL;
+	struct snd_urb_ctx *ctx = urb->context;
+
+	urb->dev = ctx->subs->dev; /* we need to set this at each time */
+	urb->iso_frame_desc[0].length = min(4u, ctx->subs->syncmaxsize);
+	urb->iso_frame_desc[0].offset = 0;
+	return 0;
+}
 
-	while ((term = snd_usb_find_csint_desc(ctrl_iface->extra,
-					       ctrl_iface->extralen,
-					       term, UAC_INPUT_TERMINAL))) {
-		if (term->bTerminalID == terminal_id)
-			return term;
+/*
+ * process after playback sync complete
+ *
+ * Full speed devices report feedback values in 10.14 format as samples per
+ * frame, high speed devices in 16.16 format as samples per microframe.
+ * Because the Audio Class 1 spec was written before USB 2.0, many high speed
+ * devices use a wrong interpretation, some others use an entirely different
+ * format.  Therefore, we cannot predict what format any particular device uses
+ * and must detect it automatically.
+ */
+static int retire_playback_sync_urb(struct snd_usb_substream *subs,
+				    struct snd_pcm_runtime *runtime,
+				    struct urb *urb)
+{
+	unsigned int f;
+	int shift;
+	unsigned long flags;
+
+	if (urb->iso_frame_desc[0].status != 0 ||
+	    urb->iso_frame_desc[0].actual_length < 3)
+		return 0;
+
+	f = le32_to_cpup(urb->transfer_buffer);
+	if (urb->iso_frame_desc[0].actual_length == 3)
+		f &= 0x00ffffff;
+	else
+		f &= 0x0fffffff;
+	if (f == 0)
+		return 0;
+
+	if (unlikely(subs->freqshift == INT_MIN)) {
+		/*
+		 * The first time we see a feedback value, determine its format
+		 * by shifting it left or right until it matches the nominal
+		 * frequency value.  This assumes that the feedback does not
+		 * differ from the nominal value more than +50% or -25%.
+		 */
+		shift = 0;
+		while (f < subs->freqn - subs->freqn / 4) {
+			f <<= 1;
+			shift++;
+		}
+		while (f > subs->freqn + subs->freqn / 2) {
+			f >>= 1;
+			shift--;
+		}
+		subs->freqshift = shift;
+	}
+	else if (subs->freqshift >= 0)
+		f <<= subs->freqshift;
+	else
+		f >>= -subs->freqshift;
+
+	if (likely(f >= subs->freqn - subs->freqn / 8 && f <= subs->freqmax)) {
+		/*
+		 * If the frequency looks valid, set it.
+		 * This value is referred to in prepare_playback_urb().
+		 */
+		spin_lock_irqsave(&subs->lock, flags);
+		subs->freqm = f;
+		spin_unlock_irqrestore(&subs->lock, flags);
+	} else {
+		/*
+		 * Out of range; maybe the shift value is wrong.
+		 * Reset it so that we autodetect again the next time.
+		 */
+		subs->freqshift = INT_MIN;
 	}
 
-	return NULL;
+	return 0;
 }
 
-static struct uac2_output_terminal_descriptor *
-	snd_usb_find_output_terminal_descriptor(struct usb_host_interface *ctrl_iface,
-						int terminal_id)
+/* determine the number of frames in the next packet */
+static int snd_usb_audio_next_packet_size(struct snd_usb_substream *subs)
 {
-	struct uac2_output_terminal_descriptor *term = NULL;
-
-	while ((term = snd_usb_find_csint_desc(ctrl_iface->extra,
-					       ctrl_iface->extralen,
-					       term, UAC_OUTPUT_TERMINAL))) {
-		if (term->bTerminalID == terminal_id)
-			return term;
+	if (subs->fill_max)
+		return subs->maxframesize;
+	else {
+		subs->phase = (subs->phase & 0xffff)
+			+ (subs->freqm << subs->datainterval);
+		return min(subs->phase >> 16, subs->maxframesize);
 	}
+}
 
-	return NULL;
+/*
+ * Prepare urb for streaming before playback starts or when paused.
+ *
+ * We don't have any data, so we send silence.
+ */
+static int prepare_nodata_playback_urb(struct snd_usb_substream *subs,
+				       struct snd_pcm_runtime *runtime,
+				       struct urb *urb)
+{
+	unsigned int i, offs, counts;
+	struct snd_urb_ctx *ctx = urb->context;
+	int stride = runtime->frame_bits >> 3;
+
+	offs = 0;
+	urb->dev = ctx->subs->dev;
+	for (i = 0; i < ctx->packets; ++i) {
+		counts = snd_usb_audio_next_packet_size(subs);
+		urb->iso_frame_desc[i].offset = offs * stride;
+		urb->iso_frame_desc[i].length = counts * stride;
+		offs += counts;
+	}
+	urb->number_of_packets = ctx->packets;
+	urb->transfer_buffer_length = offs * stride;
+	memset(urb->transfer_buffer,
+	       runtime->format == SNDRV_PCM_FORMAT_U8 ? 0x80 : 0,
+	       offs * stride);
+	return 0;
 }
 
-int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
+/*
+ * prepare urb for playback data pipe
+ *
+ * Since a URB can handle only a single linear buffer, we must use double
+ * buffering when the data to be transferred overflows the buffer boundary.
+ * To avoid inconsistencies when updating hwptr_done, we use double buffering
+ * for all URBs.
+ */
+static int prepare_playback_urb(struct snd_usb_substream *subs,
+				struct snd_pcm_runtime *runtime,
+				struct urb *urb)
 {
-	struct usb_device *dev;
-	struct usb_interface *iface;
-	struct usb_host_interface *alts;
-	struct usb_interface_descriptor *altsd;
-	int i, altno, err, stream;
-	int format = 0, num_channels = 0;
-	struct audioformat *fp = NULL;
-	int num, protocol, clock = 0;
-	struct uac_format_type_i_continuous_descriptor *fmt;
+	int i, stride;
+	unsigned int counts, frames, bytes;
+	unsigned long flags;
+	int period_elapsed = 0;
+	struct snd_urb_ctx *ctx = urb->context;
+
+	stride = runtime->frame_bits >> 3;
+
+	frames = 0;
+	urb->dev = ctx->subs->dev; /* we need to set this at each time */
+	urb->number_of_packets = 0;
+	spin_lock_irqsave(&subs->lock, flags);
+	for (i = 0; i < ctx->packets; i++) {
+		counts = snd_usb_audio_next_packet_size(subs);
+		/* set up descriptor */
+		urb->iso_frame_desc[i].offset = frames * stride;
+		urb->iso_frame_desc[i].length = counts * stride;
+		frames += counts;
+		urb->number_of_packets++;
+		subs->transfer_done += counts;
+		if (subs->transfer_done >= runtime->period_size) {
+			subs->transfer_done -= runtime->period_size;
+			period_elapsed = 1;
+			if (subs->fmt_type == UAC_FORMAT_TYPE_II) {
+				if (subs->transfer_done > 0) {
+					/* FIXME: fill-max mode is not
+					 * supported yet */
+					frames -= subs->transfer_done;
+					counts -= subs->transfer_done;
+					urb->iso_frame_desc[i].length =
+						counts * stride;
+					subs->transfer_done = 0;
+				}
+				i++;
+				if (i < ctx->packets) {
+					/* add a transfer delimiter */
+					urb->iso_frame_desc[i].offset =
+						frames * stride;
+					urb->iso_frame_desc[i].length = 0;
+					urb->number_of_packets++;
+				}
+				break;
+			}
+		}
+		if (period_elapsed) /* finish at the period boundary */
+			break;
+	}
+	bytes = frames * stride;
+	if (subs->hwptr_done + bytes > runtime->buffer_size * stride) {
+		/* err, the transferred area goes over buffer boundary. */
+		unsigned int bytes1 =
+			runtime->buffer_size * stride - subs->hwptr_done;
+		memcpy(urb->transfer_buffer,
+		       runtime->dma_area + subs->hwptr_done, bytes1);
+		memcpy(urb->transfer_buffer + bytes1,
+		       runtime->dma_area, bytes - bytes1);
+	} else {
+		memcpy(urb->transfer_buffer,
+		       runtime->dma_area + subs->hwptr_done, bytes);
+	}
+	subs->hwptr_done += bytes;
+	if (subs->hwptr_done >= runtime->buffer_size * stride)
+		subs->hwptr_done -= runtime->buffer_size * stride;
+
+	/* update delay with exact number of samples queued */
+	runtime->delay = subs->last_delay;
+	runtime->delay += frames;
+	subs->last_delay = runtime->delay;
+
+	/* realign last_frame_number */
+	subs->last_frame_number = usb_get_current_frame_number(subs->dev);
+	subs->last_frame_number &= 0xFF; /* keep 8 LSBs */
+
+	spin_unlock_irqrestore(&subs->lock, flags);
+	urb->transfer_buffer_length = bytes;
+	if (period_elapsed)
+		snd_pcm_period_elapsed(subs->pcm_substream);
+	return 0;
+}
 
-	dev = chip->dev;
+/*
+ * process after playback data complete
+ * - decrease the delay count again
+ */
+static int retire_playback_urb(struct snd_usb_substream *subs,
+			       struct snd_pcm_runtime *runtime,
+			       struct urb *urb)
+{
+	unsigned long flags;
+	int stride = runtime->frame_bits >> 3;
+	int processed = urb->transfer_buffer_length / stride;
+	int est_delay;
 
-	/* parse the interface's altsettings */
-	iface = usb_ifnum_to_if(dev, iface_no);
+	spin_lock_irqsave(&subs->lock, flags);
 
-	num = iface->num_altsetting;
+	est_delay = snd_usb_pcm_delay(subs, runtime->rate);
+	/* update delay with exact number of samples played */
+	if (processed > subs->last_delay)
+		subs->last_delay = 0;
+	else
+		subs->last_delay -= processed;
+	runtime->delay = subs->last_delay;
 
 	/*
-	 * Dallas DS4201 workaround: It presents 5 altsettings, but the last
-	 * one misses syncpipe, and does not produce any sound.
+	 * Report when delay estimate is off by more than 2ms.
+	 * The error should be lower than 2ms since the estimate relies
+	 * on two reads of a counter updated every ms.
 	 */
-	if (chip->usb_id == USB_ID(0x04fa, 0x4201))
-		num = 4;
-
-	for (i = 0; i < num; i++) {
-		alts = &iface->altsetting[i];
-		altsd = get_iface_desc(alts);
-		protocol = altsd->bInterfaceProtocol;
-		/* skip invalid one */
-		if ((altsd->bInterfaceClass != USB_CLASS_AUDIO &&
-		     altsd->bInterfaceClass != USB_CLASS_VENDOR_SPEC) ||
-		    (altsd->bInterfaceSubClass != USB_SUBCLASS_AUDIOSTREAMING &&
-		     altsd->bInterfaceSubClass != USB_SUBCLASS_VENDOR_SPEC) ||
-		    altsd->bNumEndpoints < 1 ||
-		    le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize) == 0)
-			continue;
-		/* must be isochronous */
-		if ((get_endpoint(alts, 0)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) !=
-		    USB_ENDPOINT_XFER_ISOC)
-			continue;
-		/* check direction */
-		stream = (get_endpoint(alts, 0)->bEndpointAddress & USB_DIR_IN) ?
-			SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
-		altno = altsd->bAlternateSetting;
-
-		if (snd_usb_apply_interface_quirk(chip, iface_no, altno))
-			continue;
-
-		/* get audio formats */
-		switch (protocol) {
-		default:
-			snd_printdd(KERN_WARNING "%d:%u:%d: unknown interface protocol %#02x, assuming v1\n",
-				    dev->devnum, iface_no, altno, protocol);
-			protocol = UAC_VERSION_1;
-			/* fall through */
-
-		case UAC_VERSION_1: {
-			struct uac1_as_header_descriptor *as =
-				snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL);
-
-			if (!as) {
-				snd_printk(KERN_ERR "%d:%u:%d : UAC_AS_GENERAL descriptor not found\n",
-					   dev->devnum, iface_no, altno);
-				continue;
-			}
+	if (abs(est_delay - subs->last_delay) * 1000 > runtime->rate * 2)
+		snd_printk(KERN_DEBUG "delay: estimated %d, actual %d\n",
+			est_delay, subs->last_delay);
 
-			if (as->bLength < sizeof(*as)) {
-				snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_AS_GENERAL desc\n",
-					   dev->devnum, iface_no, altno);
-				continue;
-			}
+	spin_unlock_irqrestore(&subs->lock, flags);
+	return 0;
+}
 
-			format = le16_to_cpu(as->wFormatTag); /* remember the format value */
-			break;
-		}
+static const char *usb_error_string(int err)
+{
+	switch (err) {
+	case -ENODEV:
+		return "no device";
+	case -ENOENT:
+		return "endpoint not enabled";
+	case -EPIPE:
+		return "endpoint stalled";
+	case -ENOSPC:
+		return "not enough bandwidth";
+	case -ESHUTDOWN:
+		return "device disabled";
+	case -EHOSTUNREACH:
+		return "device suspended";
+	case -EINVAL:
+	case -EAGAIN:
+	case -EFBIG:
+	case -EMSGSIZE:
+		return "internal error";
+	default:
+		return "unknown error";
+	}
+}
 
-		case UAC_VERSION_2: {
-			struct uac2_input_terminal_descriptor *input_term;
-			struct uac2_output_terminal_descriptor *output_term;
-			struct uac2_as_header_descriptor *as =
-				snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL);
+/*
+ * set up and start data/sync urbs
+ */
+static int start_urbs(struct snd_usb_substream *subs, struct snd_pcm_runtime *runtime)
+{
+	unsigned int i;
+	int err;
 
-			if (!as) {
-				snd_printk(KERN_ERR "%d:%u:%d : UAC_AS_GENERAL descriptor not found\n",
-					   dev->devnum, iface_no, altno);
-				continue;
+	if (subs->stream->chip->shutdown)
+		return -EBADFD;
+
+	for (i = 0; i < subs->nurbs; i++) {
+		if (snd_BUG_ON(!subs->dataurb[i].urb))
+			return -EINVAL;
+		if (subs->ops.prepare(subs, runtime, subs->dataurb[i].urb) < 0) {
+			snd_printk(KERN_ERR "cannot prepare datapipe for urb %d\n", i);
+			goto __error;
+		}
+	}
+	if (subs->syncpipe) {
+		for (i = 0; i < SYNC_URBS; i++) {
+			if (snd_BUG_ON(!subs->syncurb[i].urb))
+				return -EINVAL;
+			if (subs->ops.prepare_sync(subs, runtime, subs->syncurb[i].urb) < 0) {
+				snd_printk(KERN_ERR "cannot prepare syncpipe for urb %d\n", i);
+				goto __error;
 			}
+		}
+	}
 
-			if (as->bLength < sizeof(*as)) {
-				snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_AS_GENERAL desc\n",
-					   dev->devnum, iface_no, altno);
-				continue;
+	subs->active_mask = 0;
+	subs->unlink_mask = 0;
+	subs->running = 1;
+	for (i = 0; i < subs->nurbs; i++) {
+		err = usb_submit_urb(subs->dataurb[i].urb, GFP_ATOMIC);
+		if (err < 0) {
+			snd_printk(KERN_ERR "cannot submit datapipe "
+				   "for urb %d, error %d: %s\n",
+				   i, err, usb_error_string(err));
+			goto __error;
+		}
+		set_bit(i, &subs->active_mask);
+	}
+	if (subs->syncpipe) {
+		for (i = 0; i < SYNC_URBS; i++) {
+			err = usb_submit_urb(subs->syncurb[i].urb, GFP_ATOMIC);
+			if (err < 0) {
+				snd_printk(KERN_ERR "cannot submit syncpipe "
+					   "for urb %d, error %d: %s\n",
+					   i, err, usb_error_string(err));
+				goto __error;
 			}
+			set_bit(i + 16, &subs->active_mask);
+		}
+	}
+	return 0;
 
-			num_channels = as->bNrChannels;
-			format = le32_to_cpu(as->bmFormats);
+ __error:
+	// snd_pcm_stop(subs->pcm_substream, SNDRV_PCM_STATE_XRUN);
+	deactivate_urbs(subs, 0, 0);
+	return -EPIPE;
+}
 
-			/* lookup the terminal associated to this interface
-			 * to extract the clock */
-			input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
-									    as->bTerminalLink);
-			if (input_term) {
-				clock = input_term->bCSourceID;
-				break;
-			}
 
-			output_term = snd_usb_find_output_terminal_descriptor(chip->ctrl_intf,
-									      as->bTerminalLink);
-			if (output_term) {
-				clock = output_term->bCSourceID;
-				break;
-			}
+/*
+ */
+static struct snd_urb_ops audio_urb_ops[2] = {
+	{
+		.prepare =	prepare_nodata_playback_urb,
+		.retire =	retire_playback_urb,
+		.prepare_sync =	prepare_playback_sync_urb,
+		.retire_sync =	retire_playback_sync_urb,
+	},
+	{
+		.prepare =	prepare_capture_urb,
+		.retire =	retire_capture_urb,
+		.prepare_sync =	prepare_capture_sync_urb,
+		.retire_sync =	retire_capture_sync_urb,
+	},
+};
 
-			snd_printk(KERN_ERR "%d:%u:%d : bogus bTerminalLink %d\n",
-				   dev->devnum, iface_no, altno, as->bTerminalLink);
-			continue;
-		}
-		}
+/*
+ * initialize the substream instance.
+ */
 
-		/* get format type */
-		fmt = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_FORMAT_TYPE);
-		if (!fmt) {
-			snd_printk(KERN_ERR "%d:%u:%d : no UAC_FORMAT_TYPE desc\n",
-				   dev->devnum, iface_no, altno);
-			continue;
-		}
-		if (((protocol == UAC_VERSION_1) && (fmt->bLength < 8)) ||
-		    ((protocol == UAC_VERSION_2) && (fmt->bLength < 6))) {
-			snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_FORMAT_TYPE desc\n",
-				   dev->devnum, iface_no, altno);
-			continue;
-		}
+void snd_usb_init_substream(struct snd_usb_stream *as,
+			    int stream, struct audioformat *fp)
+{
+	struct snd_usb_substream *subs = &as->substream[stream];
+
+	INIT_LIST_HEAD(&subs->fmt_list);
+	spin_lock_init(&subs->lock);
+
+	subs->stream = as;
+	subs->direction = stream;
+	subs->dev = as->chip->dev;
+	subs->txfr_quirk = as->chip->txfr_quirk;
+	subs->ops = audio_urb_ops[stream];
+	if (snd_usb_get_speed(subs->dev) >= USB_SPEED_HIGH)
+		subs->ops.prepare_sync = prepare_capture_sync_urb_hs;
+
+	snd_usb_set_pcm_ops(as->pcm, stream);
+
+	list_add_tail(&fp->list, &subs->fmt_list);
+	subs->formats |= fp->formats;
+	subs->endpoint = fp->endpoint;
+	subs->num_formats++;
+	subs->fmt_type = fp->fmt_type;
+}
 
-		/*
-		 * Blue Microphones workaround: The last altsetting is identical
-		 * with the previous one, except for a larger packet size, but
-		 * is actually a mislabeled two-channel setting; ignore it.
-		 */
-		if (fmt->bNrChannels == 1 &&
-		    fmt->bSubframeSize == 2 &&
-		    altno == 2 && num == 3 &&
-		    fp && fp->altsetting == 1 && fp->channels == 1 &&
-		    fp->formats == SNDRV_PCM_FMTBIT_S16_LE &&
-		    protocol == UAC_VERSION_1 &&
-		    le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize) ==
-							fp->maxpacksize * 2)
-			continue;
-
-		fp = kzalloc(sizeof(*fp), GFP_KERNEL);
-		if (! fp) {
-			snd_printk(KERN_ERR "cannot malloc\n");
-			return -ENOMEM;
-		}
+int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	struct snd_usb_substream *subs = substream->runtime->private_data;
 
-		fp->iface = iface_no;
-		fp->altsetting = altno;
-		fp->altset_idx = i;
-		fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress;
-		fp->ep_attr = get_endpoint(alts, 0)->bmAttributes;
-		fp->datainterval = snd_usb_parse_datainterval(chip, alts);
-		fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
-		/* num_channels is only set for v2 interfaces */
-		fp->channels = num_channels;
-		if (snd_usb_get_speed(dev) == USB_SPEED_HIGH)
-			fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1)
-					* (fp->maxpacksize & 0x7ff);
-		fp->attributes = parse_uac_endpoint_attributes(chip, alts, protocol, iface_no);
-		fp->clock = clock;
-
-		/* some quirks for attributes here */
-
-		switch (chip->usb_id) {
-		case USB_ID(0x0a92, 0x0053): /* AudioTrak Optoplay */
-			/* Optoplay sets the sample rate attribute although
-			 * it seems not supporting it in fact.
-			 */
-			fp->attributes &= ~UAC_EP_CS_ATTR_SAMPLE_RATE;
-			break;
-		case USB_ID(0x041e, 0x3020): /* Creative SB Audigy 2 NX */
-		case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */
-			/* doesn't set the sample rate attribute, but supports it */
-			fp->attributes |= UAC_EP_CS_ATTR_SAMPLE_RATE;
-			break;
-		case USB_ID(0x0763, 0x2001):  /* M-Audio Quattro USB */
-		case USB_ID(0x0763, 0x2012):  /* M-Audio Fast Track Pro USB */
-		case USB_ID(0x047f, 0x0ca1): /* plantronics headset */
-		case USB_ID(0x077d, 0x07af): /* Griffin iMic (note that there is
-						an older model 77d:223) */
-		/*
-		 * plantronics headset and Griffin iMic have set adaptive-in
-		 * although it's really not...
-		 */
-			fp->ep_attr &= ~USB_ENDPOINT_SYNCTYPE;
-			if (stream == SNDRV_PCM_STREAM_PLAYBACK)
-				fp->ep_attr |= USB_ENDPOINT_SYNC_ADAPTIVE;
-			else
-				fp->ep_attr |= USB_ENDPOINT_SYNC_SYNC;
-			break;
-		}
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		subs->ops.prepare = prepare_playback_urb;
+		return 0;
+	case SNDRV_PCM_TRIGGER_STOP:
+		return deactivate_urbs(subs, 0, 0);
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		subs->ops.prepare = prepare_nodata_playback_urb;
+		return 0;
+	}
 
-		/* ok, let's parse further... */
-		if (snd_usb_parse_audio_format(chip, fp, format, fmt, stream, alts) < 0) {
-			kfree(fp->rate_table);
-			kfree(fp);
-			fp = NULL;
-			continue;
-		}
+	return -EINVAL;
+}
 
-		snd_printdd(KERN_INFO "%d:%u:%d: add audio endpoint %#x\n", dev->devnum, iface_no, altno, fp->endpoint);
-		err = snd_usb_add_audio_endpoint(chip, stream, fp);
-		if (err < 0) {
-			kfree(fp->rate_table);
-			kfree(fp);
-			return err;
-		}
-		/* try to set the interface... */
-		usb_set_interface(chip->dev, iface_no, altno);
-		snd_usb_init_pitch(chip, iface_no, alts, fp);
-		snd_usb_init_sample_rate(chip, iface_no, alts, fp, fp->rate_max);
+int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	struct snd_usb_substream *subs = substream->runtime->private_data;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		subs->ops.retire = retire_capture_urb;
+		return start_urbs(subs, substream->runtime);
+	case SNDRV_PCM_TRIGGER_STOP:
+		return deactivate_urbs(subs, 0, 0);
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		subs->ops.retire = retire_paused_capture_urb;
+		return 0;
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		subs->ops.retire = retire_capture_urb;
+		return 0;
 	}
+
+	return -EINVAL;
+}
+
+int snd_usb_substream_prepare(struct snd_usb_substream *subs,
+			      struct snd_pcm_runtime *runtime)
+{
+	/* clear urbs (to be sure) */
+	deactivate_urbs(subs, 0, 1);
+	wait_clear_urbs(subs);
+
+	/* for playback, submit the URBs now; otherwise, the first hwptr_done
+	 * updates for all URBs would happen at the same time when starting */
+	if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) {
+		subs->ops.prepare = prepare_nodata_playback_urb;
+		return start_urbs(subs, runtime);
+	}
+
 	return 0;
 }
 
diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h
index 64dd0db023b2..88eb63a636eb 100644
--- a/sound/usb/endpoint.h
+++ b/sound/usb/endpoint.h
@@ -1,11 +1,21 @@
 #ifndef __USBAUDIO_ENDPOINT_H
 #define __USBAUDIO_ENDPOINT_H
 
-int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip,
-				  int iface_no);
+void snd_usb_init_substream(struct snd_usb_stream *as,
+			    int stream,
+			    struct audioformat *fp);
 
-int snd_usb_add_audio_endpoint(struct snd_usb_audio *chip,
-			       int stream,
-			       struct audioformat *fp);
+int snd_usb_init_substream_urbs(struct snd_usb_substream *subs,
+				unsigned int period_bytes,
+				unsigned int rate,
+				unsigned int frame_bits);
+
+void snd_usb_release_substream_urbs(struct snd_usb_substream *subs, int force);
+
+int snd_usb_substream_prepare(struct snd_usb_substream *subs,
+			      struct snd_pcm_runtime *runtime);
+
+int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substream, int cmd);
+int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream, int cmd);
 
 #endif /* __USBAUDIO_ENDPOINT_H */
diff --git a/sound/usb/format.c b/sound/usb/format.c
index 8d042dce0d16..89421d176570 100644
--- a/sound/usb/format.c
+++ b/sound/usb/format.c
@@ -286,7 +286,7 @@ static int parse_audio_format_rates_v2(struct snd_usb_audio *chip,
 			      USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
 			      UAC2_CS_CONTROL_SAM_FREQ << 8,
 			      snd_usb_ctrl_intf(chip) | (clock << 8),
-			      tmp, sizeof(tmp), 1000);
+			      tmp, sizeof(tmp));
 
 	if (ret < 0) {
 		snd_printk(KERN_ERR "%s(): unable to retrieve number of sample rates (clock %d)\n",
@@ -307,7 +307,7 @@ static int parse_audio_format_rates_v2(struct snd_usb_audio *chip,
 			      USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
 			      UAC2_CS_CONTROL_SAM_FREQ << 8,
 			      snd_usb_ctrl_intf(chip) | (clock << 8),
-			      data, data_size, 1000);
+			      data, data_size);
 
 	if (ret < 0) {
 		snd_printk(KERN_ERR "%s(): unable to retrieve sample rate range (clock %d)\n",
diff --git a/sound/usb/helper.c b/sound/usb/helper.c
index f280c1903c25..9eed8f40b179 100644
--- a/sound/usb/helper.c
+++ b/sound/usb/helper.c
@@ -81,7 +81,7 @@ void *snd_usb_find_csint_desc(void *buffer, int buflen, void *after, u8 dsubtype
  */
 int snd_usb_ctl_msg(struct usb_device *dev, unsigned int pipe, __u8 request,
 		    __u8 requesttype, __u16 value, __u16 index, void *data,
-		    __u16 size, int timeout)
+		    __u16 size)
 {
 	int err;
 	void *buf = NULL;
@@ -92,7 +92,7 @@ int snd_usb_ctl_msg(struct usb_device *dev, unsigned int pipe, __u8 request,
 			return -ENOMEM;
 	}
 	err = usb_control_msg(dev, pipe, request, requesttype,
-			      value, index, buf, size, timeout);
+			      value, index, buf, size, 1000);
 	if (size > 0) {
 		memcpy(data, buf, size);
 		kfree(buf);
diff --git a/sound/usb/helper.h b/sound/usb/helper.h
index 09bd943c43bf..805c300dd004 100644
--- a/sound/usb/helper.h
+++ b/sound/usb/helper.h
@@ -8,7 +8,7 @@ void *snd_usb_find_csint_desc(void *descstart, int desclen, void *after, u8 dsub
 
 int snd_usb_ctl_msg(struct usb_device *dev, unsigned int pipe,
 		    __u8 request, __u8 requesttype, __u16 value, __u16 index,
-		    void *data, __u16 size, int timeout);
+		    void *data, __u16 size);
 
 unsigned char snd_usb_parse_datainterval(struct snd_usb_audio *chip,
 					 struct usb_host_interface *alts);
diff --git a/sound/usb/midi.c b/sound/usb/midi.c
index f9289102886a..e21f026d9577 100644
--- a/sound/usb/midi.c
+++ b/sound/usb/midi.c
@@ -816,6 +816,22 @@ static struct usb_protocol_ops snd_usbmidi_raw_ops = {
 	.output = snd_usbmidi_raw_output,
 };
 
+/*
+ * FTDI protocol: raw MIDI bytes, but input packets have two modem status bytes.
+ */
+
+static void snd_usbmidi_ftdi_input(struct snd_usb_midi_in_endpoint* ep,
+				   uint8_t* buffer, int buffer_length)
+{
+	if (buffer_length > 2)
+		snd_usbmidi_input_data(ep, 0, buffer + 2, buffer_length - 2);
+}
+
+static struct usb_protocol_ops snd_usbmidi_ftdi_ops = {
+	.input = snd_usbmidi_ftdi_input,
+	.output = snd_usbmidi_raw_output,
+};
+
 static void snd_usbmidi_us122l_input(struct snd_usb_midi_in_endpoint *ep,
 				     uint8_t *buffer, int buffer_length)
 {
@@ -2163,6 +2179,17 @@ int snd_usbmidi_create(struct snd_card *card,
 		/* endpoint 1 is input-only */
 		endpoints[1].out_cables = 0;
 		break;
+	case QUIRK_MIDI_FTDI:
+		umidi->usb_protocol_ops = &snd_usbmidi_ftdi_ops;
+
+		/* set baud rate to 31250 (48 MHz / 16 / 96) */
+		err = usb_control_msg(umidi->dev, usb_sndctrlpipe(umidi->dev, 0),
+				      3, 0x40, 0x60, 0, NULL, 0, 1000);
+		if (err < 0)
+			break;
+
+		err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints);
+		break;
 	default:
 		snd_printd(KERN_ERR "invalid quirk type %d\n", quirk->type);
 		err = -ENXIO;
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index cdd19d7fe500..60f65ace7474 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -296,7 +296,7 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int v
 		if (snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request,
 				    USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
 				    validx, snd_usb_ctrl_intf(chip) | (cval->id << 8),
-				    buf, val_len, 100) >= val_len) {
+				    buf, val_len) >= val_len) {
 			*value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len));
 			snd_usb_autosuspend(cval->mixer->chip);
 			return 0;
@@ -333,7 +333,7 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v
 	ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest,
 			      USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
 			      validx, snd_usb_ctrl_intf(chip) | (cval->id << 8),
-			      buf, size, 1000);
+			      buf, size);
 	snd_usb_autosuspend(chip);
 
 	if (ret < 0) {
@@ -445,7 +445,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
 				    usb_sndctrlpipe(chip->dev, 0), request,
 				    USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
 				    validx, snd_usb_ctrl_intf(chip) | (cval->id << 8),
-				    buf, val_len, 100) >= 0) {
+				    buf, val_len) >= 0) {
 			snd_usb_autosuspend(chip);
 			return 0;
 		}
@@ -881,8 +881,17 @@ static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol, struct snd_ctl_
 		uinfo->value.integer.min = 0;
 		uinfo->value.integer.max = 1;
 	} else {
-		if (! cval->initialized)
-			get_min_max(cval,  0);
+		if (!cval->initialized) {
+			get_min_max(cval, 0);
+			if (cval->initialized && cval->dBmin >= cval->dBmax) {
+				kcontrol->vd[0].access &= 
+					~(SNDRV_CTL_ELEM_ACCESS_TLV_READ |
+					  SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK);
+				snd_ctl_notify(cval->mixer->chip->card,
+					       SNDRV_CTL_EVENT_MASK_INFO,
+					       &kcontrol->id);
+			}
+		}
 		uinfo->value.integer.min = 0;
 		uinfo->value.integer.max =
 			(cval->max - cval->min + cval->res - 1) / cval->res;
@@ -1250,7 +1259,7 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void
 				build_feature_ctl(state, _ftr, 0, i, &iterm, unitid, 0);
 		}
 	} else { /* UAC_VERSION_2 */
-		for (i = 0; i < 30/2; i++) {
+		for (i = 0; i < ARRAY_SIZE(audio_feature_info); i++) {
 			unsigned int ch_bits = 0;
 			unsigned int ch_read_only = 0;
 
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
index 3d0f4873112b..ab125ee0b0f0 100644
--- a/sound/usb/mixer_quirks.c
+++ b/sound/usb/mixer_quirks.c
@@ -190,18 +190,18 @@ static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
 		err = snd_usb_ctl_msg(mixer->chip->dev,
 			      usb_sndctrlpipe(mixer->chip->dev, 0), 0x24,
 			      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
-			      !value, 0, NULL, 0, 100);
+			      !value, 0, NULL, 0);
 	/* USB X-Fi S51 Pro */
 	if (mixer->chip->usb_id == USB_ID(0x041e, 0x30df))
 		err = snd_usb_ctl_msg(mixer->chip->dev,
 			      usb_sndctrlpipe(mixer->chip->dev, 0), 0x24,
 			      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
-			      !value, 0, NULL, 0, 100);
+			      !value, 0, NULL, 0);
 	else
 		err = snd_usb_ctl_msg(mixer->chip->dev,
 			      usb_sndctrlpipe(mixer->chip->dev, 0), 0x24,
 			      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
-			      value, index + 2, NULL, 0, 100);
+			      value, index + 2, NULL, 0);
 	if (err < 0)
 		return err;
 	mixer->audigy2nx_leds[index] = value;
@@ -299,7 +299,7 @@ static void snd_audigy2nx_proc_read(struct snd_info_entry *entry,
 				      usb_rcvctrlpipe(mixer->chip->dev, 0),
 				      UAC_GET_MEM, USB_DIR_IN | USB_TYPE_CLASS |
 				      USB_RECIP_INTERFACE, 0,
-				      jacks[i].unitid << 8, buf, 3, 100);
+				      jacks[i].unitid << 8, buf, 3);
 		if (err == 3 && (buf[0] == 3 || buf[0] == 6))
 			snd_iprintf(buffer, "%02x %02x\n", buf[1], buf[2]);
 		else
@@ -332,7 +332,7 @@ static int snd_xonar_u1_switch_put(struct snd_kcontrol *kcontrol,
 	err = snd_usb_ctl_msg(mixer->chip->dev,
 			      usb_sndctrlpipe(mixer->chip->dev, 0), 0x08,
 			      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
-			      50, 0, &new_status, 1, 100);
+			      50, 0, &new_status, 1);
 	if (err < 0)
 		return err;
 	mixer->xonar_u1_status = new_status;
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index b8dcbf407bbb..0220b0f335b9 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -28,12 +28,36 @@
 #include "card.h"
 #include "quirks.h"
 #include "debug.h"
-#include "urb.h"
+#include "endpoint.h"
 #include "helper.h"
 #include "pcm.h"
 #include "clock.h"
 #include "power.h"
 
+/* return the estimated delay based on USB frame counters */
+snd_pcm_uframes_t snd_usb_pcm_delay(struct snd_usb_substream *subs,
+				    unsigned int rate)
+{
+	int current_frame_number;
+	int frame_diff;
+	int est_delay;
+
+	current_frame_number = usb_get_current_frame_number(subs->dev);
+	/*
+	 * HCD implementations use different widths, use lower 8 bits.
+	 * The delay will be managed up to 256ms, which is more than
+	 * enough
+	 */
+	frame_diff = (current_frame_number - subs->last_frame_number) & 0xff;
+
+	/* Approximation based on number of samples per USB frame (ms),
+	   some truncation for 44.1 but the estimate is good enough */
+	est_delay =  subs->last_delay - (frame_diff * rate / 1000);
+	if (est_delay < 0)
+		est_delay = 0;
+	return est_delay;
+}
+
 /*
  * return the current pcm pointer.  just based on the hwptr_done value.
  */
@@ -45,6 +69,8 @@ static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream
 	subs = (struct snd_usb_substream *)substream->runtime->private_data;
 	spin_lock(&subs->lock);
 	hwptr_done = subs->hwptr_done;
+	substream->runtime->delay = snd_usb_pcm_delay(subs,
+						substream->runtime->rate);
 	spin_unlock(&subs->lock);
 	return hwptr_done / (substream->runtime->frame_bits >> 3);
 }
@@ -126,7 +152,7 @@ static int init_pitch_v1(struct snd_usb_audio *chip, int iface,
 	if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR,
 				   USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT,
 				   UAC_EP_CS_ATTR_PITCH_CONTROL << 8, ep,
-				   data, sizeof(data), 1000)) < 0) {
+				   data, sizeof(data))) < 0) {
 		snd_printk(KERN_ERR "%d:%d:%d: cannot set enable PITCH\n",
 			   dev->devnum, iface, ep);
 		return err;
@@ -150,7 +176,7 @@ static int init_pitch_v2(struct snd_usb_audio *chip, int iface,
 	if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC2_CS_CUR,
 				   USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_OUT,
 				   UAC2_EP_CS_PITCH << 8, 0,
-				   data, sizeof(data), 1000)) < 0) {
+				   data, sizeof(data))) < 0) {
 		snd_printk(KERN_ERR "%d:%d:%d: cannot set enable PITCH (v2)\n",
 			   dev->devnum, iface, fmt->altsetting);
 		return err;
@@ -417,6 +443,8 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
 	subs->hwptr_done = 0;
 	subs->transfer_done = 0;
 	subs->phase = 0;
+	subs->last_delay = 0;
+	subs->last_frame_number = 0;
 	runtime->delay = 0;
 
 	return snd_usb_substream_prepare(subs, runtime);
diff --git a/sound/usb/pcm.h b/sound/usb/pcm.h
index ed3e283f618d..df7a003682ad 100644
--- a/sound/usb/pcm.h
+++ b/sound/usb/pcm.h
@@ -1,6 +1,9 @@
 #ifndef __USBAUDIO_PCM_H
 #define __USBAUDIO_PCM_H
 
+snd_pcm_uframes_t snd_usb_pcm_delay(struct snd_usb_substream *subs,
+				    unsigned int rate);
+
 void snd_usb_set_pcm_ops(struct snd_pcm *pcm, int stream);
 
 int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface,
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index a42e3ef3832d..b61945f3af9e 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -39,6 +39,17 @@
 	.idProduct = prod, \
 	.bInterfaceClass = USB_CLASS_VENDOR_SPEC
 
+/* FTDI devices */
+{
+	USB_DEVICE(0x0403, 0xb8d8),
+	.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+		/* .vendor_name = "STARR LABS", */
+		/* .product_name = "Starr Labs MIDI USB device", */
+		.ifnum = 0,
+		.type = QUIRK_MIDI_FTDI
+	}
+},
+
 /* Creative/Toshiba Multimedia Center SB-0500 */
 {
 	USB_DEVICE(0x041e, 0x3048),
@@ -1678,6 +1689,20 @@ YAMAHA_DEVICE(0x7010, "UB99"),
 	}
 },
 {
+	/* Added support for Roland UM-ONE which differs from UM-1 */
+	USB_DEVICE(0x0582, 0x012a),
+	.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+		/* .vendor_name = "ROLAND", */
+		/* .product_name = "UM-ONE", */
+		.ifnum = 0,
+		.type = QUIRK_MIDI_FIXED_ENDPOINT,
+		.data = & (const struct snd_usb_midi_endpoint_info) {
+			.out_cables = 0x0001,
+			.in_cables  = 0x0003
+		}
+	}
+},
+{
 	USB_DEVICE(0x0582, 0x011e),
 	.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
 		/* .vendor_name = "BOSS", */
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 81e07d842581..2e5bc7344026 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -34,6 +34,7 @@
 #include "endpoint.h"
 #include "pcm.h"
 #include "clock.h"
+#include "stream.h"
 
 /*
  * handle the quirks for the contained interfaces
@@ -106,7 +107,7 @@ static int create_standard_audio_quirk(struct snd_usb_audio *chip,
 
 	alts = &iface->altsetting[0];
 	altsd = get_iface_desc(alts);
-	err = snd_usb_parse_audio_endpoints(chip, altsd->bInterfaceNumber);
+	err = snd_usb_parse_audio_interface(chip, altsd->bInterfaceNumber);
 	if (err < 0) {
 		snd_printk(KERN_ERR "cannot setup if %d: error %d\n",
 			   altsd->bInterfaceNumber, err);
@@ -147,7 +148,7 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip,
 
 	stream = (fp->endpoint & USB_DIR_IN)
 		? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
-	err = snd_usb_add_audio_endpoint(chip, stream, fp);
+	err = snd_usb_add_audio_stream(chip, stream, fp);
 	if (err < 0) {
 		kfree(fp);
 		kfree(rate_table);
@@ -254,7 +255,7 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip,
 
 	stream = (fp->endpoint & USB_DIR_IN)
 		? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
-	err = snd_usb_add_audio_endpoint(chip, stream, fp);
+	err = snd_usb_add_audio_stream(chip, stream, fp);
 	if (err < 0) {
 		kfree(fp);
 		return err;
@@ -306,6 +307,7 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip,
 		[QUIRK_MIDI_EMAGIC] = create_any_midi_quirk,
 		[QUIRK_MIDI_CME] = create_any_midi_quirk,
 		[QUIRK_MIDI_AKAI] = create_any_midi_quirk,
+		[QUIRK_MIDI_FTDI] = create_any_midi_quirk,
 		[QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk,
 		[QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk,
 		[QUIRK_AUDIO_EDIROL_UAXX] = create_uaxx_quirk,
@@ -338,7 +340,7 @@ static int snd_usb_extigy_boot_quirk(struct usb_device *dev, struct usb_interfac
 		snd_printdd("sending Extigy boot sequence...\n");
 		/* Send message to force it to reconnect with full interface. */
 		err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev,0),
-				      0x10, 0x43, 0x0001, 0x000a, NULL, 0, 1000);
+				      0x10, 0x43, 0x0001, 0x000a, NULL, 0);
 		if (err < 0) snd_printdd("error sending boot message: %d\n", err);
 		err = usb_get_descriptor(dev, USB_DT_DEVICE, 0,
 				&dev->descriptor, sizeof(dev->descriptor));
@@ -359,11 +361,11 @@ static int snd_usb_audigy2nx_boot_quirk(struct usb_device *dev)
 
 	snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), 0x2a,
 			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_OTHER,
-			0, 0, &buf, 1, 1000);
+			0, 0, &buf, 1);
 	if (buf == 0) {
 		snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 0x29,
 				USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
-				1, 2000, NULL, 0, 1000);
+				1, 2000, NULL, 0);
 		return -ENODEV;
 	}
 	return 0;
@@ -406,7 +408,7 @@ static int snd_usb_cm106_write_int_reg(struct usb_device *dev, int reg, u16 valu
 	buf[3] = reg;
 	return snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_CONFIGURATION,
 			       USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_ENDPOINT,
-			       0, 0, &buf, 4, 1000);
+			       0, 0, &buf, 4);
 }
 
 static int snd_usb_cm106_boot_quirk(struct usb_device *dev)
diff --git a/sound/usb/stream.c b/sound/usb/stream.c
new file mode 100644
index 000000000000..5ff8010b2d6f
--- /dev/null
+++ b/sound/usb/stream.c
@@ -0,0 +1,452 @@
+/*
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <linux/usb/audio.h>
+#include <linux/usb/audio-v2.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+
+#include "usbaudio.h"
+#include "card.h"
+#include "proc.h"
+#include "quirks.h"
+#include "endpoint.h"
+#include "pcm.h"
+#include "helper.h"
+#include "format.h"
+#include "clock.h"
+#include "stream.h"
+
+/*
+ * free a substream
+ */
+static void free_substream(struct snd_usb_substream *subs)
+{
+	struct list_head *p, *n;
+
+	if (!subs->num_formats)
+		return; /* not initialized */
+	list_for_each_safe(p, n, &subs->fmt_list) {
+		struct audioformat *fp = list_entry(p, struct audioformat, list);
+		kfree(fp->rate_table);
+		kfree(fp);
+	}
+	kfree(subs->rate_list.list);
+}
+
+
+/*
+ * free a usb stream instance
+ */
+static void snd_usb_audio_stream_free(struct snd_usb_stream *stream)
+{
+	free_substream(&stream->substream[0]);
+	free_substream(&stream->substream[1]);
+	list_del(&stream->list);
+	kfree(stream);
+}
+
+static void snd_usb_audio_pcm_free(struct snd_pcm *pcm)
+{
+	struct snd_usb_stream *stream = pcm->private_data;
+	if (stream) {
+		stream->pcm = NULL;
+		snd_usb_audio_stream_free(stream);
+	}
+}
+
+
+/*
+ * add this endpoint to the chip instance.
+ * if a stream with the same endpoint already exists, append to it.
+ * if not, create a new pcm stream.
+ */
+int snd_usb_add_audio_stream(struct snd_usb_audio *chip,
+			     int stream,
+			     struct audioformat *fp)
+{
+	struct list_head *p;
+	struct snd_usb_stream *as;
+	struct snd_usb_substream *subs;
+	struct snd_pcm *pcm;
+	int err;
+
+	list_for_each(p, &chip->pcm_list) {
+		as = list_entry(p, struct snd_usb_stream, list);
+		if (as->fmt_type != fp->fmt_type)
+			continue;
+		subs = &as->substream[stream];
+		if (!subs->endpoint)
+			continue;
+		if (subs->endpoint == fp->endpoint) {
+			list_add_tail(&fp->list, &subs->fmt_list);
+			subs->num_formats++;
+			subs->formats |= fp->formats;
+			return 0;
+		}
+	}
+	/* look for an empty stream */
+	list_for_each(p, &chip->pcm_list) {
+		as = list_entry(p, struct snd_usb_stream, list);
+		if (as->fmt_type != fp->fmt_type)
+			continue;
+		subs = &as->substream[stream];
+		if (subs->endpoint)
+			continue;
+		err = snd_pcm_new_stream(as->pcm, stream, 1);
+		if (err < 0)
+			return err;
+		snd_usb_init_substream(as, stream, fp);
+		return 0;
+	}
+
+	/* create a new pcm */
+	as = kzalloc(sizeof(*as), GFP_KERNEL);
+	if (!as)
+		return -ENOMEM;
+	as->pcm_index = chip->pcm_devs;
+	as->chip = chip;
+	as->fmt_type = fp->fmt_type;
+	err = snd_pcm_new(chip->card, "USB Audio", chip->pcm_devs,
+			  stream == SNDRV_PCM_STREAM_PLAYBACK ? 1 : 0,
+			  stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1,
+			  &pcm);
+	if (err < 0) {
+		kfree(as);
+		return err;
+	}
+	as->pcm = pcm;
+	pcm->private_data = as;
+	pcm->private_free = snd_usb_audio_pcm_free;
+	pcm->info_flags = 0;
+	if (chip->pcm_devs > 0)
+		sprintf(pcm->name, "USB Audio #%d", chip->pcm_devs);
+	else
+		strcpy(pcm->name, "USB Audio");
+
+	snd_usb_init_substream(as, stream, fp);
+
+	list_add(&as->list, &chip->pcm_list);
+	chip->pcm_devs++;
+
+	snd_usb_proc_pcm_format_add(as);
+
+	return 0;
+}
+
+static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip,
+					 struct usb_host_interface *alts,
+					 int protocol, int iface_no)
+{
+	/* parsed with a v1 header here. that's ok as we only look at the
+	 * header first which is the same for both versions */
+	struct uac_iso_endpoint_descriptor *csep;
+	struct usb_interface_descriptor *altsd = get_iface_desc(alts);
+	int attributes = 0;
+
+	csep = snd_usb_find_desc(alts->endpoint[0].extra, alts->endpoint[0].extralen, NULL, USB_DT_CS_ENDPOINT);
+
+	/* Creamware Noah has this descriptor after the 2nd endpoint */
+	if (!csep && altsd->bNumEndpoints >= 2)
+		csep = snd_usb_find_desc(alts->endpoint[1].extra, alts->endpoint[1].extralen, NULL, USB_DT_CS_ENDPOINT);
+
+	if (!csep || csep->bLength < 7 ||
+	    csep->bDescriptorSubtype != UAC_EP_GENERAL) {
+		snd_printk(KERN_WARNING "%d:%u:%d : no or invalid"
+			   " class specific endpoint descriptor\n",
+			   chip->dev->devnum, iface_no,
+			   altsd->bAlternateSetting);
+		return 0;
+	}
+
+	if (protocol == UAC_VERSION_1) {
+		attributes = csep->bmAttributes;
+	} else {
+		struct uac2_iso_endpoint_descriptor *csep2 =
+			(struct uac2_iso_endpoint_descriptor *) csep;
+
+		attributes = csep->bmAttributes & UAC_EP_CS_ATTR_FILL_MAX;
+
+		/* emulate the endpoint attributes of a v1 device */
+		if (csep2->bmControls & UAC2_CONTROL_PITCH)
+			attributes |= UAC_EP_CS_ATTR_PITCH_CONTROL;
+	}
+
+	return attributes;
+}
+
+static struct uac2_input_terminal_descriptor *
+	snd_usb_find_input_terminal_descriptor(struct usb_host_interface *ctrl_iface,
+					       int terminal_id)
+{
+	struct uac2_input_terminal_descriptor *term = NULL;
+
+	while ((term = snd_usb_find_csint_desc(ctrl_iface->extra,
+					       ctrl_iface->extralen,
+					       term, UAC_INPUT_TERMINAL))) {
+		if (term->bTerminalID == terminal_id)
+			return term;
+	}
+
+	return NULL;
+}
+
+static struct uac2_output_terminal_descriptor *
+	snd_usb_find_output_terminal_descriptor(struct usb_host_interface *ctrl_iface,
+						int terminal_id)
+{
+	struct uac2_output_terminal_descriptor *term = NULL;
+
+	while ((term = snd_usb_find_csint_desc(ctrl_iface->extra,
+					       ctrl_iface->extralen,
+					       term, UAC_OUTPUT_TERMINAL))) {
+		if (term->bTerminalID == terminal_id)
+			return term;
+	}
+
+	return NULL;
+}
+
+int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
+{
+	struct usb_device *dev;
+	struct usb_interface *iface;
+	struct usb_host_interface *alts;
+	struct usb_interface_descriptor *altsd;
+	int i, altno, err, stream;
+	int format = 0, num_channels = 0;
+	struct audioformat *fp = NULL;
+	int num, protocol, clock = 0;
+	struct uac_format_type_i_continuous_descriptor *fmt;
+
+	dev = chip->dev;
+
+	/* parse the interface's altsettings */
+	iface = usb_ifnum_to_if(dev, iface_no);
+
+	num = iface->num_altsetting;
+
+	/*
+	 * Dallas DS4201 workaround: It presents 5 altsettings, but the last
+	 * one misses syncpipe, and does not produce any sound.
+	 */
+	if (chip->usb_id == USB_ID(0x04fa, 0x4201))
+		num = 4;
+
+	for (i = 0; i < num; i++) {
+		alts = &iface->altsetting[i];
+		altsd = get_iface_desc(alts);
+		protocol = altsd->bInterfaceProtocol;
+		/* skip invalid one */
+		if ((altsd->bInterfaceClass != USB_CLASS_AUDIO &&
+		     altsd->bInterfaceClass != USB_CLASS_VENDOR_SPEC) ||
+		    (altsd->bInterfaceSubClass != USB_SUBCLASS_AUDIOSTREAMING &&
+		     altsd->bInterfaceSubClass != USB_SUBCLASS_VENDOR_SPEC) ||
+		    altsd->bNumEndpoints < 1 ||
+		    le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize) == 0)
+			continue;
+		/* must be isochronous */
+		if ((get_endpoint(alts, 0)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) !=
+		    USB_ENDPOINT_XFER_ISOC)
+			continue;
+		/* check direction */
+		stream = (get_endpoint(alts, 0)->bEndpointAddress & USB_DIR_IN) ?
+			SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
+		altno = altsd->bAlternateSetting;
+
+		if (snd_usb_apply_interface_quirk(chip, iface_no, altno))
+			continue;
+
+		/* get audio formats */
+		switch (protocol) {
+		default:
+			snd_printdd(KERN_WARNING "%d:%u:%d: unknown interface protocol %#02x, assuming v1\n",
+				    dev->devnum, iface_no, altno, protocol);
+			protocol = UAC_VERSION_1;
+			/* fall through */
+
+		case UAC_VERSION_1: {
+			struct uac1_as_header_descriptor *as =
+				snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL);
+
+			if (!as) {
+				snd_printk(KERN_ERR "%d:%u:%d : UAC_AS_GENERAL descriptor not found\n",
+					   dev->devnum, iface_no, altno);
+				continue;
+			}
+
+			if (as->bLength < sizeof(*as)) {
+				snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_AS_GENERAL desc\n",
+					   dev->devnum, iface_no, altno);
+				continue;
+			}
+
+			format = le16_to_cpu(as->wFormatTag); /* remember the format value */
+			break;
+		}
+
+		case UAC_VERSION_2: {
+			struct uac2_input_terminal_descriptor *input_term;
+			struct uac2_output_terminal_descriptor *output_term;
+			struct uac2_as_header_descriptor *as =
+				snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL);
+
+			if (!as) {
+				snd_printk(KERN_ERR "%d:%u:%d : UAC_AS_GENERAL descriptor not found\n",
+					   dev->devnum, iface_no, altno);
+				continue;
+			}
+
+			if (as->bLength < sizeof(*as)) {
+				snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_AS_GENERAL desc\n",
+					   dev->devnum, iface_no, altno);
+				continue;
+			}
+
+			num_channels = as->bNrChannels;
+			format = le32_to_cpu(as->bmFormats);
+
+			/* lookup the terminal associated to this interface
+			 * to extract the clock */
+			input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
+									    as->bTerminalLink);
+			if (input_term) {
+				clock = input_term->bCSourceID;
+				break;
+			}
+
+			output_term = snd_usb_find_output_terminal_descriptor(chip->ctrl_intf,
+									      as->bTerminalLink);
+			if (output_term) {
+				clock = output_term->bCSourceID;
+				break;
+			}
+
+			snd_printk(KERN_ERR "%d:%u:%d : bogus bTerminalLink %d\n",
+				   dev->devnum, iface_no, altno, as->bTerminalLink);
+			continue;
+		}
+		}
+
+		/* get format type */
+		fmt = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_FORMAT_TYPE);
+		if (!fmt) {
+			snd_printk(KERN_ERR "%d:%u:%d : no UAC_FORMAT_TYPE desc\n",
+				   dev->devnum, iface_no, altno);
+			continue;
+		}
+		if (((protocol == UAC_VERSION_1) && (fmt->bLength < 8)) ||
+		    ((protocol == UAC_VERSION_2) && (fmt->bLength < 6))) {
+			snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_FORMAT_TYPE desc\n",
+				   dev->devnum, iface_no, altno);
+			continue;
+		}
+
+		/*
+		 * Blue Microphones workaround: The last altsetting is identical
+		 * with the previous one, except for a larger packet size, but
+		 * is actually a mislabeled two-channel setting; ignore it.
+		 */
+		if (fmt->bNrChannels == 1 &&
+		    fmt->bSubframeSize == 2 &&
+		    altno == 2 && num == 3 &&
+		    fp && fp->altsetting == 1 && fp->channels == 1 &&
+		    fp->formats == SNDRV_PCM_FMTBIT_S16_LE &&
+		    protocol == UAC_VERSION_1 &&
+		    le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize) ==
+							fp->maxpacksize * 2)
+			continue;
+
+		fp = kzalloc(sizeof(*fp), GFP_KERNEL);
+		if (! fp) {
+			snd_printk(KERN_ERR "cannot malloc\n");
+			return -ENOMEM;
+		}
+
+		fp->iface = iface_no;
+		fp->altsetting = altno;
+		fp->altset_idx = i;
+		fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress;
+		fp->ep_attr = get_endpoint(alts, 0)->bmAttributes;
+		fp->datainterval = snd_usb_parse_datainterval(chip, alts);
+		fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
+		/* num_channels is only set for v2 interfaces */
+		fp->channels = num_channels;
+		if (snd_usb_get_speed(dev) == USB_SPEED_HIGH)
+			fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1)
+					* (fp->maxpacksize & 0x7ff);
+		fp->attributes = parse_uac_endpoint_attributes(chip, alts, protocol, iface_no);
+		fp->clock = clock;
+
+		/* some quirks for attributes here */
+
+		switch (chip->usb_id) {
+		case USB_ID(0x0a92, 0x0053): /* AudioTrak Optoplay */
+			/* Optoplay sets the sample rate attribute although
+			 * it seems not supporting it in fact.
+			 */
+			fp->attributes &= ~UAC_EP_CS_ATTR_SAMPLE_RATE;
+			break;
+		case USB_ID(0x041e, 0x3020): /* Creative SB Audigy 2 NX */
+		case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */
+			/* doesn't set the sample rate attribute, but supports it */
+			fp->attributes |= UAC_EP_CS_ATTR_SAMPLE_RATE;
+			break;
+		case USB_ID(0x0763, 0x2001):  /* M-Audio Quattro USB */
+		case USB_ID(0x0763, 0x2012):  /* M-Audio Fast Track Pro USB */
+		case USB_ID(0x047f, 0x0ca1): /* plantronics headset */
+		case USB_ID(0x077d, 0x07af): /* Griffin iMic (note that there is
+						an older model 77d:223) */
+		/*
+		 * plantronics headset and Griffin iMic have set adaptive-in
+		 * although it's really not...
+		 */
+			fp->ep_attr &= ~USB_ENDPOINT_SYNCTYPE;
+			if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+				fp->ep_attr |= USB_ENDPOINT_SYNC_ADAPTIVE;
+			else
+				fp->ep_attr |= USB_ENDPOINT_SYNC_SYNC;
+			break;
+		}
+
+		/* ok, let's parse further... */
+		if (snd_usb_parse_audio_format(chip, fp, format, fmt, stream, alts) < 0) {
+			kfree(fp->rate_table);
+			kfree(fp);
+			fp = NULL;
+			continue;
+		}
+
+		snd_printdd(KERN_INFO "%d:%u:%d: add audio endpoint %#x\n", dev->devnum, iface_no, altno, fp->endpoint);
+		err = snd_usb_add_audio_stream(chip, stream, fp);
+		if (err < 0) {
+			kfree(fp->rate_table);
+			kfree(fp);
+			return err;
+		}
+		/* try to set the interface... */
+		usb_set_interface(chip->dev, iface_no, altno);
+		snd_usb_init_pitch(chip, iface_no, alts, fp);
+		snd_usb_init_sample_rate(chip, iface_no, alts, fp, fp->rate_max);
+	}
+	return 0;
+}
+
diff --git a/sound/usb/stream.h b/sound/usb/stream.h
new file mode 100644
index 000000000000..c97f679fc84f
--- /dev/null
+++ b/sound/usb/stream.h
@@ -0,0 +1,12 @@
+#ifndef __USBAUDIO_STREAM_H
+#define __USBAUDIO_STREAM_H
+
+int snd_usb_parse_audio_interface(struct snd_usb_audio *chip,
+				  int iface_no);
+
+int snd_usb_add_audio_stream(struct snd_usb_audio *chip,
+			     int stream,
+			     struct audioformat *fp);
+
+#endif /* __USBAUDIO_STREAM_H */
+
diff --git a/sound/usb/urb.c b/sound/usb/urb.c
deleted file mode 100644
index e184349aee83..000000000000
--- a/sound/usb/urb.c
+++ /dev/null
@@ -1,941 +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
- *
- */
-
-#include <linux/gfp.h>
-#include <linux/init.h>
-#include <linux/usb.h>
-#include <linux/usb/audio.h>
-
-#include <sound/core.h>
-#include <sound/pcm.h>
-
-#include "usbaudio.h"
-#include "helper.h"
-#include "card.h"
-#include "urb.h"
-#include "pcm.h"
-
-/*
- * convert a sampling rate into our full speed format (fs/1000 in Q16.16)
- * this will overflow at approx 524 kHz
- */
-static inline unsigned get_usb_full_speed_rate(unsigned int rate)
-{
-	return ((rate << 13) + 62) / 125;
-}
-
-/*
- * convert a sampling rate into USB high speed format (fs/8000 in Q16.16)
- * this will overflow at approx 4 MHz
- */
-static inline unsigned get_usb_high_speed_rate(unsigned int rate)
-{
-	return ((rate << 10) + 62) / 125;
-}
-
-/*
- * unlink active urbs.
- */
-static int deactivate_urbs(struct snd_usb_substream *subs, int force, int can_sleep)
-{
-	struct snd_usb_audio *chip = subs->stream->chip;
-	unsigned int i;
-	int async;
-
-	subs->running = 0;
-
-	if (!force && subs->stream->chip->shutdown) /* to be sure... */
-		return -EBADFD;
-
-	async = !can_sleep && chip->async_unlink;
-
-	if (!async && in_interrupt())
-		return 0;
-
-	for (i = 0; i < subs->nurbs; i++) {
-		if (test_bit(i, &subs->active_mask)) {
-			if (!test_and_set_bit(i, &subs->unlink_mask)) {
-				struct urb *u = subs->dataurb[i].urb;
-				if (async)
-					usb_unlink_urb(u);
-				else
-					usb_kill_urb(u);
-			}
-		}
-	}
-	if (subs->syncpipe) {
-		for (i = 0; i < SYNC_URBS; i++) {
-			if (test_bit(i+16, &subs->active_mask)) {
-				if (!test_and_set_bit(i+16, &subs->unlink_mask)) {
-					struct urb *u = subs->syncurb[i].urb;
-					if (async)
-						usb_unlink_urb(u);
-					else
-						usb_kill_urb(u);
-				}
-			}
-		}
-	}
-	return 0;
-}
-
-
-/*
- * release a urb data
- */
-static void release_urb_ctx(struct snd_urb_ctx *u)
-{
-	if (u->urb) {
-		if (u->buffer_size)
-			usb_free_coherent(u->subs->dev, u->buffer_size,
-					u->urb->transfer_buffer,
-					u->urb->transfer_dma);
-		usb_free_urb(u->urb);
-		u->urb = NULL;
-	}
-}
-
-/*
- *  wait until all urbs are processed.
- */
-static int wait_clear_urbs(struct snd_usb_substream *subs)
-{
-	unsigned long end_time = jiffies + msecs_to_jiffies(1000);
-	unsigned int i;
-	int alive;
-
-	do {
-		alive = 0;
-		for (i = 0; i < subs->nurbs; i++) {
-			if (test_bit(i, &subs->active_mask))
-				alive++;
-		}
-		if (subs->syncpipe) {
-			for (i = 0; i < SYNC_URBS; i++) {
-				if (test_bit(i + 16, &subs->active_mask))
-					alive++;
-			}
-		}
-		if (! alive)
-			break;
-		schedule_timeout_uninterruptible(1);
-	} while (time_before(jiffies, end_time));
-	if (alive)
-		snd_printk(KERN_ERR "timeout: still %d active urbs..\n", alive);
-	return 0;
-}
-
-/*
- * release a substream
- */
-void snd_usb_release_substream_urbs(struct snd_usb_substream *subs, int force)
-{
-	int i;
-
-	/* stop urbs (to be sure) */
-	deactivate_urbs(subs, force, 1);
-	wait_clear_urbs(subs);
-
-	for (i = 0; i < MAX_URBS; i++)
-		release_urb_ctx(&subs->dataurb[i]);
-	for (i = 0; i < SYNC_URBS; i++)
-		release_urb_ctx(&subs->syncurb[i]);
-	usb_free_coherent(subs->dev, SYNC_URBS * 4,
-			subs->syncbuf, subs->sync_dma);
-	subs->syncbuf = NULL;
-	subs->nurbs = 0;
-}
-
-/*
- * complete callback from data urb
- */
-static void snd_complete_urb(struct urb *urb)
-{
-	struct snd_urb_ctx *ctx = urb->context;
-	struct snd_usb_substream *subs = ctx->subs;
-	struct snd_pcm_substream *substream = ctx->subs->pcm_substream;
-	int err = 0;
-
-	if ((subs->running && subs->ops.retire(subs, substream->runtime, urb)) ||
-	    !subs->running || /* can be stopped during retire callback */
-	    (err = subs->ops.prepare(subs, substream->runtime, urb)) < 0 ||
-	    (err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
-		clear_bit(ctx->index, &subs->active_mask);
-		if (err < 0) {
-			snd_printd(KERN_ERR "cannot submit urb (err = %d)\n", err);
-			snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
-		}
-	}
-}
-
-
-/*
- * complete callback from sync urb
- */
-static void snd_complete_sync_urb(struct urb *urb)
-{
-	struct snd_urb_ctx *ctx = urb->context;
-	struct snd_usb_substream *subs = ctx->subs;
-	struct snd_pcm_substream *substream = ctx->subs->pcm_substream;
-	int err = 0;
-
-	if ((subs->running && subs->ops.retire_sync(subs, substream->runtime, urb)) ||
-	    !subs->running || /* can be stopped during retire callback */
-	    (err = subs->ops.prepare_sync(subs, substream->runtime, urb)) < 0 ||
-	    (err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
-		clear_bit(ctx->index + 16, &subs->active_mask);
-		if (err < 0) {
-			snd_printd(KERN_ERR "cannot submit sync urb (err = %d)\n", err);
-			snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
-		}
-	}
-}
-
-
-/*
- * initialize a substream for plaback/capture
- */
-int snd_usb_init_substream_urbs(struct snd_usb_substream *subs,
-				unsigned int period_bytes,
-				unsigned int rate,
-				unsigned int frame_bits)
-{
-	unsigned int maxsize, i;
-	int is_playback = subs->direction == SNDRV_PCM_STREAM_PLAYBACK;
-	unsigned int urb_packs, total_packs, packs_per_ms;
-	struct snd_usb_audio *chip = subs->stream->chip;
-
-	/* calculate the frequency in 16.16 format */
-	if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL)
-		subs->freqn = get_usb_full_speed_rate(rate);
-	else
-		subs->freqn = get_usb_high_speed_rate(rate);
-	subs->freqm = subs->freqn;
-	subs->freqshift = INT_MIN;
-	/* calculate max. frequency */
-	if (subs->maxpacksize) {
-		/* whatever fits into a max. size packet */
-		maxsize = subs->maxpacksize;
-		subs->freqmax = (maxsize / (frame_bits >> 3))
-				<< (16 - subs->datainterval);
-	} else {
-		/* no max. packet size: just take 25% higher than nominal */
-		subs->freqmax = subs->freqn + (subs->freqn >> 2);
-		maxsize = ((subs->freqmax + 0xffff) * (frame_bits >> 3))
-				>> (16 - subs->datainterval);
-	}
-	subs->phase = 0;
-
-	if (subs->fill_max)
-		subs->curpacksize = subs->maxpacksize;
-	else
-		subs->curpacksize = maxsize;
-
-	if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL)
-		packs_per_ms = 8 >> subs->datainterval;
-	else
-		packs_per_ms = 1;
-
-	if (is_playback) {
-		urb_packs = max(chip->nrpacks, 1);
-		urb_packs = min(urb_packs, (unsigned int)MAX_PACKS);
-	} else
-		urb_packs = 1;
-	urb_packs *= packs_per_ms;
-	if (subs->syncpipe)
-		urb_packs = min(urb_packs, 1U << subs->syncinterval);
-
-	/* decide how many packets to be used */
-	if (is_playback) {
-		unsigned int minsize, maxpacks;
-		/* determine how small a packet can be */
-		minsize = (subs->freqn >> (16 - subs->datainterval))
-			  * (frame_bits >> 3);
-		/* with sync from device, assume it can be 12% lower */
-		if (subs->syncpipe)
-			minsize -= minsize >> 3;
-		minsize = max(minsize, 1u);
-		total_packs = (period_bytes + minsize - 1) / minsize;
-		/* we need at least two URBs for queueing */
-		if (total_packs < 2) {
-			total_packs = 2;
-		} else {
-			/* and we don't want too long a queue either */
-			maxpacks = max(MAX_QUEUE * packs_per_ms, urb_packs * 2);
-			total_packs = min(total_packs, maxpacks);
-		}
-	} else {
-		while (urb_packs > 1 && urb_packs * maxsize >= period_bytes)
-			urb_packs >>= 1;
-		total_packs = MAX_URBS * urb_packs;
-	}
-	subs->nurbs = (total_packs + urb_packs - 1) / urb_packs;
-	if (subs->nurbs > MAX_URBS) {
-		/* too much... */
-		subs->nurbs = MAX_URBS;
-		total_packs = MAX_URBS * urb_packs;
-	} else if (subs->nurbs < 2) {
-		/* too little - we need at least two packets
-		 * to ensure contiguous playback/capture
-		 */
-		subs->nurbs = 2;
-	}
-
-	/* allocate and initialize data urbs */
-	for (i = 0; i < subs->nurbs; i++) {
-		struct snd_urb_ctx *u = &subs->dataurb[i];
-		u->index = i;
-		u->subs = subs;
-		u->packets = (i + 1) * total_packs / subs->nurbs
-			- i * total_packs / subs->nurbs;
-		u->buffer_size = maxsize * u->packets;
-		if (subs->fmt_type == UAC_FORMAT_TYPE_II)
-			u->packets++; /* for transfer delimiter */
-		u->urb = usb_alloc_urb(u->packets, GFP_KERNEL);
-		if (!u->urb)
-			goto out_of_memory;
-		u->urb->transfer_buffer =
-			usb_alloc_coherent(subs->dev, u->buffer_size,
-					   GFP_KERNEL, &u->urb->transfer_dma);
-		if (!u->urb->transfer_buffer)
-			goto out_of_memory;
-		u->urb->pipe = subs->datapipe;
-		u->urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
-		u->urb->interval = 1 << subs->datainterval;
-		u->urb->context = u;
-		u->urb->complete = snd_complete_urb;
-	}
-
-	if (subs->syncpipe) {
-		/* allocate and initialize sync urbs */
-		subs->syncbuf = usb_alloc_coherent(subs->dev, SYNC_URBS * 4,
-						 GFP_KERNEL, &subs->sync_dma);
-		if (!subs->syncbuf)
-			goto out_of_memory;
-		for (i = 0; i < SYNC_URBS; i++) {
-			struct snd_urb_ctx *u = &subs->syncurb[i];
-			u->index = i;
-			u->subs = subs;
-			u->packets = 1;
-			u->urb = usb_alloc_urb(1, GFP_KERNEL);
-			if (!u->urb)
-				goto out_of_memory;
-			u->urb->transfer_buffer = subs->syncbuf + i * 4;
-			u->urb->transfer_dma = subs->sync_dma + i * 4;
-			u->urb->transfer_buffer_length = 4;
-			u->urb->pipe = subs->syncpipe;
-			u->urb->transfer_flags = URB_ISO_ASAP |
-						 URB_NO_TRANSFER_DMA_MAP;
-			u->urb->number_of_packets = 1;
-			u->urb->interval = 1 << subs->syncinterval;
-			u->urb->context = u;
-			u->urb->complete = snd_complete_sync_urb;
-		}
-	}
-	return 0;
-
-out_of_memory:
-	snd_usb_release_substream_urbs(subs, 0);
-	return -ENOMEM;
-}
-
-/*
- * prepare urb for full speed capture sync pipe
- *
- * fill the length and offset of each urb descriptor.
- * the fixed 10.14 frequency is passed through the pipe.
- */
-static int prepare_capture_sync_urb(struct snd_usb_substream *subs,
-				    struct snd_pcm_runtime *runtime,
-				    struct urb *urb)
-{
-	unsigned char *cp = urb->transfer_buffer;
-	struct snd_urb_ctx *ctx = urb->context;
-
-	urb->dev = ctx->subs->dev; /* we need to set this at each time */
-	urb->iso_frame_desc[0].length = 3;
-	urb->iso_frame_desc[0].offset = 0;
-	cp[0] = subs->freqn >> 2;
-	cp[1] = subs->freqn >> 10;
-	cp[2] = subs->freqn >> 18;
-	return 0;
-}
-
-/*
- * prepare urb for high speed capture sync pipe
- *
- * fill the length and offset of each urb descriptor.
- * the fixed 12.13 frequency is passed as 16.16 through the pipe.
- */
-static int prepare_capture_sync_urb_hs(struct snd_usb_substream *subs,
-				       struct snd_pcm_runtime *runtime,
-				       struct urb *urb)
-{
-	unsigned char *cp = urb->transfer_buffer;
-	struct snd_urb_ctx *ctx = urb->context;
-
-	urb->dev = ctx->subs->dev; /* we need to set this at each time */
-	urb->iso_frame_desc[0].length = 4;
-	urb->iso_frame_desc[0].offset = 0;
-	cp[0] = subs->freqn;
-	cp[1] = subs->freqn >> 8;
-	cp[2] = subs->freqn >> 16;
-	cp[3] = subs->freqn >> 24;
-	return 0;
-}
-
-/*
- * process after capture sync complete
- * - nothing to do
- */
-static int retire_capture_sync_urb(struct snd_usb_substream *subs,
-				   struct snd_pcm_runtime *runtime,
-				   struct urb *urb)
-{
-	return 0;
-}
-
-/*
- * prepare urb for capture data pipe
- *
- * fill the offset and length of each descriptor.
- *
- * we use a temporary buffer to write the captured data.
- * since the length of written data is determined by host, we cannot
- * write onto the pcm buffer directly...  the data is thus copied
- * later at complete callback to the global buffer.
- */
-static int prepare_capture_urb(struct snd_usb_substream *subs,
-			       struct snd_pcm_runtime *runtime,
-			       struct urb *urb)
-{
-	int i, offs;
-	struct snd_urb_ctx *ctx = urb->context;
-
-	offs = 0;
-	urb->dev = ctx->subs->dev; /* we need to set this at each time */
-	for (i = 0; i < ctx->packets; i++) {
-		urb->iso_frame_desc[i].offset = offs;
-		urb->iso_frame_desc[i].length = subs->curpacksize;
-		offs += subs->curpacksize;
-	}
-	urb->transfer_buffer_length = offs;
-	urb->number_of_packets = ctx->packets;
-	return 0;
-}
-
-/*
- * process after capture complete
- *
- * copy the data from each desctiptor to the pcm buffer, and
- * update the current position.
- */
-static int retire_capture_urb(struct snd_usb_substream *subs,
-			      struct snd_pcm_runtime *runtime,
-			      struct urb *urb)
-{
-	unsigned long flags;
-	unsigned char *cp;
-	int i;
-	unsigned int stride, frames, bytes, oldptr;
-	int period_elapsed = 0;
-
-	stride = runtime->frame_bits >> 3;
-
-	for (i = 0; i < urb->number_of_packets; i++) {
-		cp = (unsigned char *)urb->transfer_buffer + urb->iso_frame_desc[i].offset;
-		if (urb->iso_frame_desc[i].status) {
-			snd_printd(KERN_ERR "frame %d active: %d\n", i, urb->iso_frame_desc[i].status);
-			// continue;
-		}
-		bytes = urb->iso_frame_desc[i].actual_length;
-		frames = bytes / stride;
-		if (!subs->txfr_quirk)
-			bytes = frames * stride;
-		if (bytes % (runtime->sample_bits >> 3) != 0) {
-#ifdef CONFIG_SND_DEBUG_VERBOSE
-			int oldbytes = bytes;
-#endif
-			bytes = frames * stride;
-			snd_printdd(KERN_ERR "Corrected urb data len. %d->%d\n",
-							oldbytes, bytes);
-		}
-		/* update the current pointer */
-		spin_lock_irqsave(&subs->lock, flags);
-		oldptr = subs->hwptr_done;
-		subs->hwptr_done += bytes;
-		if (subs->hwptr_done >= runtime->buffer_size * stride)
-			subs->hwptr_done -= runtime->buffer_size * stride;
-		frames = (bytes + (oldptr % stride)) / stride;
-		subs->transfer_done += frames;
-		if (subs->transfer_done >= runtime->period_size) {
-			subs->transfer_done -= runtime->period_size;
-			period_elapsed = 1;
-		}
-		spin_unlock_irqrestore(&subs->lock, flags);
-		/* copy a data chunk */
-		if (oldptr + bytes > runtime->buffer_size * stride) {
-			unsigned int bytes1 =
-					runtime->buffer_size * stride - oldptr;
-			memcpy(runtime->dma_area + oldptr, cp, bytes1);
-			memcpy(runtime->dma_area, cp + bytes1, bytes - bytes1);
-		} else {
-			memcpy(runtime->dma_area + oldptr, cp, bytes);
-		}
-	}
-	if (period_elapsed)
-		snd_pcm_period_elapsed(subs->pcm_substream);
-	return 0;
-}
-
-/*
- * Process after capture complete when paused.  Nothing to do.
- */
-static int retire_paused_capture_urb(struct snd_usb_substream *subs,
-				     struct snd_pcm_runtime *runtime,
-				     struct urb *urb)
-{
-	return 0;
-}
-
-
-/*
- * prepare urb for playback sync pipe
- *
- * set up the offset and length to receive the current frequency.
- */
-static int prepare_playback_sync_urb(struct snd_usb_substream *subs,
-				     struct snd_pcm_runtime *runtime,
-				     struct urb *urb)
-{
-	struct snd_urb_ctx *ctx = urb->context;
-
-	urb->dev = ctx->subs->dev; /* we need to set this at each time */
-	urb->iso_frame_desc[0].length = min(4u, ctx->subs->syncmaxsize);
-	urb->iso_frame_desc[0].offset = 0;
-	return 0;
-}
-
-/*
- * process after playback sync complete
- *
- * Full speed devices report feedback values in 10.14 format as samples per
- * frame, high speed devices in 16.16 format as samples per microframe.
- * Because the Audio Class 1 spec was written before USB 2.0, many high speed
- * devices use a wrong interpretation, some others use an entirely different
- * format.  Therefore, we cannot predict what format any particular device uses
- * and must detect it automatically.
- */
-static int retire_playback_sync_urb(struct snd_usb_substream *subs,
-				    struct snd_pcm_runtime *runtime,
-				    struct urb *urb)
-{
-	unsigned int f;
-	int shift;
-	unsigned long flags;
-
-	if (urb->iso_frame_desc[0].status != 0 ||
-	    urb->iso_frame_desc[0].actual_length < 3)
-		return 0;
-
-	f = le32_to_cpup(urb->transfer_buffer);
-	if (urb->iso_frame_desc[0].actual_length == 3)
-		f &= 0x00ffffff;
-	else
-		f &= 0x0fffffff;
-	if (f == 0)
-		return 0;
-
-	if (unlikely(subs->freqshift == INT_MIN)) {
-		/*
-		 * The first time we see a feedback value, determine its format
-		 * by shifting it left or right until it matches the nominal
-		 * frequency value.  This assumes that the feedback does not
-		 * differ from the nominal value more than +50% or -25%.
-		 */
-		shift = 0;
-		while (f < subs->freqn - subs->freqn / 4) {
-			f <<= 1;
-			shift++;
-		}
-		while (f > subs->freqn + subs->freqn / 2) {
-			f >>= 1;
-			shift--;
-		}
-		subs->freqshift = shift;
-	}
-	else if (subs->freqshift >= 0)
-		f <<= subs->freqshift;
-	else
-		f >>= -subs->freqshift;
-
-	if (likely(f >= subs->freqn - subs->freqn / 8 && f <= subs->freqmax)) {
-		/*
-		 * If the frequency looks valid, set it.
-		 * This value is referred to in prepare_playback_urb().
-		 */
-		spin_lock_irqsave(&subs->lock, flags);
-		subs->freqm = f;
-		spin_unlock_irqrestore(&subs->lock, flags);
-	} else {
-		/*
-		 * Out of range; maybe the shift value is wrong.
-		 * Reset it so that we autodetect again the next time.
-		 */
-		subs->freqshift = INT_MIN;
-	}
-
-	return 0;
-}
-
-/* determine the number of frames in the next packet */
-static int snd_usb_audio_next_packet_size(struct snd_usb_substream *subs)
-{
-	if (subs->fill_max)
-		return subs->maxframesize;
-	else {
-		subs->phase = (subs->phase & 0xffff)
-			+ (subs->freqm << subs->datainterval);
-		return min(subs->phase >> 16, subs->maxframesize);
-	}
-}
-
-/*
- * Prepare urb for streaming before playback starts or when paused.
- *
- * We don't have any data, so we send silence.
- */
-static int prepare_nodata_playback_urb(struct snd_usb_substream *subs,
-				       struct snd_pcm_runtime *runtime,
-				       struct urb *urb)
-{
-	unsigned int i, offs, counts;
-	struct snd_urb_ctx *ctx = urb->context;
-	int stride = runtime->frame_bits >> 3;
-
-	offs = 0;
-	urb->dev = ctx->subs->dev;
-	for (i = 0; i < ctx->packets; ++i) {
-		counts = snd_usb_audio_next_packet_size(subs);
-		urb->iso_frame_desc[i].offset = offs * stride;
-		urb->iso_frame_desc[i].length = counts * stride;
-		offs += counts;
-	}
-	urb->number_of_packets = ctx->packets;
-	urb->transfer_buffer_length = offs * stride;
-	memset(urb->transfer_buffer,
-	       runtime->format == SNDRV_PCM_FORMAT_U8 ? 0x80 : 0,
-	       offs * stride);
-	return 0;
-}
-
-/*
- * prepare urb for playback data pipe
- *
- * Since a URB can handle only a single linear buffer, we must use double
- * buffering when the data to be transferred overflows the buffer boundary.
- * To avoid inconsistencies when updating hwptr_done, we use double buffering
- * for all URBs.
- */
-static int prepare_playback_urb(struct snd_usb_substream *subs,
-				struct snd_pcm_runtime *runtime,
-				struct urb *urb)
-{
-	int i, stride;
-	unsigned int counts, frames, bytes;
-	unsigned long flags;
-	int period_elapsed = 0;
-	struct snd_urb_ctx *ctx = urb->context;
-
-	stride = runtime->frame_bits >> 3;
-
-	frames = 0;
-	urb->dev = ctx->subs->dev; /* we need to set this at each time */
-	urb->number_of_packets = 0;
-	spin_lock_irqsave(&subs->lock, flags);
-	for (i = 0; i < ctx->packets; i++) {
-		counts = snd_usb_audio_next_packet_size(subs);
-		/* set up descriptor */
-		urb->iso_frame_desc[i].offset = frames * stride;
-		urb->iso_frame_desc[i].length = counts * stride;
-		frames += counts;
-		urb->number_of_packets++;
-		subs->transfer_done += counts;
-		if (subs->transfer_done >= runtime->period_size) {
-			subs->transfer_done -= runtime->period_size;
-			period_elapsed = 1;
-			if (subs->fmt_type == UAC_FORMAT_TYPE_II) {
-				if (subs->transfer_done > 0) {
-					/* FIXME: fill-max mode is not
-					 * supported yet */
-					frames -= subs->transfer_done;
-					counts -= subs->transfer_done;
-					urb->iso_frame_desc[i].length =
-						counts * stride;
-					subs->transfer_done = 0;
-				}
-				i++;
-				if (i < ctx->packets) {
-					/* add a transfer delimiter */
-					urb->iso_frame_desc[i].offset =
-						frames * stride;
-					urb->iso_frame_desc[i].length = 0;
-					urb->number_of_packets++;
-				}
-				break;
-			}
-		}
-		if (period_elapsed) /* finish at the period boundary */
-			break;
-	}
-	bytes = frames * stride;
-	if (subs->hwptr_done + bytes > runtime->buffer_size * stride) {
-		/* err, the transferred area goes over buffer boundary. */
-		unsigned int bytes1 =
-			runtime->buffer_size * stride - subs->hwptr_done;
-		memcpy(urb->transfer_buffer,
-		       runtime->dma_area + subs->hwptr_done, bytes1);
-		memcpy(urb->transfer_buffer + bytes1,
-		       runtime->dma_area, bytes - bytes1);
-	} else {
-		memcpy(urb->transfer_buffer,
-		       runtime->dma_area + subs->hwptr_done, bytes);
-	}
-	subs->hwptr_done += bytes;
-	if (subs->hwptr_done >= runtime->buffer_size * stride)
-		subs->hwptr_done -= runtime->buffer_size * stride;
-	runtime->delay += frames;
-	spin_unlock_irqrestore(&subs->lock, flags);
-	urb->transfer_buffer_length = bytes;
-	if (period_elapsed)
-		snd_pcm_period_elapsed(subs->pcm_substream);
-	return 0;
-}
-
-/*
- * process after playback data complete
- * - decrease the delay count again
- */
-static int retire_playback_urb(struct snd_usb_substream *subs,
-			       struct snd_pcm_runtime *runtime,
-			       struct urb *urb)
-{
-	unsigned long flags;
-	int stride = runtime->frame_bits >> 3;
-	int processed = urb->transfer_buffer_length / stride;
-
-	spin_lock_irqsave(&subs->lock, flags);
-	if (processed > runtime->delay)
-		runtime->delay = 0;
-	else
-		runtime->delay -= processed;
-	spin_unlock_irqrestore(&subs->lock, flags);
-	return 0;
-}
-
-static const char *usb_error_string(int err)
-{
-	switch (err) {
-	case -ENODEV:
-		return "no device";
-	case -ENOENT:
-		return "endpoint not enabled";
-	case -EPIPE:
-		return "endpoint stalled";
-	case -ENOSPC:
-		return "not enough bandwidth";
-	case -ESHUTDOWN:
-		return "device disabled";
-	case -EHOSTUNREACH:
-		return "device suspended";
-	case -EINVAL:
-	case -EAGAIN:
-	case -EFBIG:
-	case -EMSGSIZE:
-		return "internal error";
-	default:
-		return "unknown error";
-	}
-}
-
-/*
- * set up and start data/sync urbs
- */
-static int start_urbs(struct snd_usb_substream *subs, struct snd_pcm_runtime *runtime)
-{
-	unsigned int i;
-	int err;
-
-	if (subs->stream->chip->shutdown)
-		return -EBADFD;
-
-	for (i = 0; i < subs->nurbs; i++) {
-		if (snd_BUG_ON(!subs->dataurb[i].urb))
-			return -EINVAL;
-		if (subs->ops.prepare(subs, runtime, subs->dataurb[i].urb) < 0) {
-			snd_printk(KERN_ERR "cannot prepare datapipe for urb %d\n", i);
-			goto __error;
-		}
-	}
-	if (subs->syncpipe) {
-		for (i = 0; i < SYNC_URBS; i++) {
-			if (snd_BUG_ON(!subs->syncurb[i].urb))
-				return -EINVAL;
-			if (subs->ops.prepare_sync(subs, runtime, subs->syncurb[i].urb) < 0) {
-				snd_printk(KERN_ERR "cannot prepare syncpipe for urb %d\n", i);
-				goto __error;
-			}
-		}
-	}
-
-	subs->active_mask = 0;
-	subs->unlink_mask = 0;
-	subs->running = 1;
-	for (i = 0; i < subs->nurbs; i++) {
-		err = usb_submit_urb(subs->dataurb[i].urb, GFP_ATOMIC);
-		if (err < 0) {
-			snd_printk(KERN_ERR "cannot submit datapipe "
-				   "for urb %d, error %d: %s\n",
-				   i, err, usb_error_string(err));
-			goto __error;
-		}
-		set_bit(i, &subs->active_mask);
-	}
-	if (subs->syncpipe) {
-		for (i = 0; i < SYNC_URBS; i++) {
-			err = usb_submit_urb(subs->syncurb[i].urb, GFP_ATOMIC);
-			if (err < 0) {
-				snd_printk(KERN_ERR "cannot submit syncpipe "
-					   "for urb %d, error %d: %s\n",
-					   i, err, usb_error_string(err));
-				goto __error;
-			}
-			set_bit(i + 16, &subs->active_mask);
-		}
-	}
-	return 0;
-
- __error:
-	// snd_pcm_stop(subs->pcm_substream, SNDRV_PCM_STATE_XRUN);
-	deactivate_urbs(subs, 0, 0);
-	return -EPIPE;
-}
-
-
-/*
- */
-static struct snd_urb_ops audio_urb_ops[2] = {
-	{
-		.prepare =	prepare_nodata_playback_urb,
-		.retire =	retire_playback_urb,
-		.prepare_sync =	prepare_playback_sync_urb,
-		.retire_sync =	retire_playback_sync_urb,
-	},
-	{
-		.prepare =	prepare_capture_urb,
-		.retire =	retire_capture_urb,
-		.prepare_sync =	prepare_capture_sync_urb,
-		.retire_sync =	retire_capture_sync_urb,
-	},
-};
-
-/*
- * initialize the substream instance.
- */
-
-void snd_usb_init_substream(struct snd_usb_stream *as,
-			    int stream, struct audioformat *fp)
-{
-	struct snd_usb_substream *subs = &as->substream[stream];
-
-	INIT_LIST_HEAD(&subs->fmt_list);
-	spin_lock_init(&subs->lock);
-
-	subs->stream = as;
-	subs->direction = stream;
-	subs->dev = as->chip->dev;
-	subs->txfr_quirk = as->chip->txfr_quirk;
-	subs->ops = audio_urb_ops[stream];
-	if (snd_usb_get_speed(subs->dev) >= USB_SPEED_HIGH)
-		subs->ops.prepare_sync = prepare_capture_sync_urb_hs;
-
-	snd_usb_set_pcm_ops(as->pcm, stream);
-
-	list_add_tail(&fp->list, &subs->fmt_list);
-	subs->formats |= fp->formats;
-	subs->endpoint = fp->endpoint;
-	subs->num_formats++;
-	subs->fmt_type = fp->fmt_type;
-}
-
-int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substream, int cmd)
-{
-	struct snd_usb_substream *subs = substream->runtime->private_data;
-
-	switch (cmd) {
-	case SNDRV_PCM_TRIGGER_START:
-	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		subs->ops.prepare = prepare_playback_urb;
-		return 0;
-	case SNDRV_PCM_TRIGGER_STOP:
-		return deactivate_urbs(subs, 0, 0);
-	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		subs->ops.prepare = prepare_nodata_playback_urb;
-		return 0;
-	}
-
-	return -EINVAL;
-}
-
-int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream, int cmd)
-{
-	struct snd_usb_substream *subs = substream->runtime->private_data;
-
-	switch (cmd) {
-	case SNDRV_PCM_TRIGGER_START:
-		subs->ops.retire = retire_capture_urb;
-		return start_urbs(subs, substream->runtime);
-	case SNDRV_PCM_TRIGGER_STOP:
-		return deactivate_urbs(subs, 0, 0);
-	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		subs->ops.retire = retire_paused_capture_urb;
-		return 0;
-	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		subs->ops.retire = retire_capture_urb;
-		return 0;
-	}
-
-	return -EINVAL;
-}
-
-int snd_usb_substream_prepare(struct snd_usb_substream *subs,
-			      struct snd_pcm_runtime *runtime)
-{
-	/* clear urbs (to be sure) */
-	deactivate_urbs(subs, 0, 1);
-	wait_clear_urbs(subs);
-
-	/* for playback, submit the URBs now; otherwise, the first hwptr_done
-	 * updates for all URBs would happen at the same time when starting */
-	if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) {
-		subs->ops.prepare = prepare_nodata_playback_urb;
-		return start_urbs(subs, runtime);
-	}
-
-	return 0;
-}
-
diff --git a/sound/usb/urb.h b/sound/usb/urb.h
deleted file mode 100644
index 888da38079cf..000000000000
--- a/sound/usb/urb.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef __USBAUDIO_URB_H
-#define __USBAUDIO_URB_H
-
-void snd_usb_init_substream(struct snd_usb_stream *as,
-			    int stream,
-			    struct audioformat *fp);
-
-int snd_usb_init_substream_urbs(struct snd_usb_substream *subs,
-				unsigned int period_bytes,
-				unsigned int rate,
-				unsigned int frame_bits);
-
-void snd_usb_release_substream_urbs(struct snd_usb_substream *subs, int force);
-
-int snd_usb_substream_prepare(struct snd_usb_substream *subs,
-			      struct snd_pcm_runtime *runtime);
-
-int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substream, int cmd);
-int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream, int cmd);
-
-#endif /* __USBAUDIO_URB_H */
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index 1e79986b5777..3e2b03577936 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -80,6 +80,7 @@ enum quirk_type {
 	QUIRK_MIDI_CME,
 	QUIRK_MIDI_AKAI,
 	QUIRK_MIDI_US122L,
+	QUIRK_MIDI_FTDI,
 	QUIRK_AUDIO_STANDARD_INTERFACE,
 	QUIRK_AUDIO_FIXED_ENDPOINT,
 	QUIRK_AUDIO_EDIROL_UAXX,