summary refs log tree commit diff
path: root/sound/usb
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2009-12-09 17:14:38 +1100
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2009-12-09 17:14:38 +1100
commitbcd6acd51f3d4d1ada201e9bc5c40a31d6d80c71 (patch)
tree2f6dffd2d3e4dd67355a224de7e7a960335a92fd /sound/usb
parent11c34c7deaeeebcee342cbc35e1bb2a6711b2431 (diff)
parent3ff6a468b45b5dfeb0e903e56f4eb27d34b2437c (diff)
downloadlinux-bcd6acd51f3d4d1ada201e9bc5c40a31d6d80c71.tar.gz
Merge commit 'origin/master' into next
Conflicts:
	include/linux/kvm.h
Diffstat (limited to 'sound/usb')
-rw-r--r--sound/usb/usbaudio.c38
-rw-r--r--sound/usb/usbaudio.h7
-rw-r--r--sound/usb/usbmidi.c208
-rw-r--r--sound/usb/usbmixer_maps.c23
-rw-r--r--sound/usb/usbquirks.h23
-rw-r--r--sound/usb/usx2y/us122l.c135
-rw-r--r--sound/usb/usx2y/us122l.h4
-rw-r--r--sound/usb/usx2y/usX2Yhwdep.c8
-rw-r--r--sound/usb/usx2y/usbusx2y.c28
-rw-r--r--sound/usb/usx2y/usbusx2y.h6
-rw-r--r--sound/usb/usx2y/usbusx2yaudio.c34
-rw-r--r--sound/usb/usx2y/usx2yhwdeppcm.c8
12 files changed, 370 insertions, 152 deletions
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index 8db0374e10d5..b074a594c595 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -2893,7 +2893,9 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif)
 		if ((altsd->bInterfaceClass == USB_CLASS_AUDIO ||
 		     altsd->bInterfaceClass == USB_CLASS_VENDOR_SPEC) &&
 		    altsd->bInterfaceSubClass == USB_SUBCLASS_MIDI_STREAMING) {
-			if (snd_usb_create_midi_interface(chip, iface, NULL) < 0) {
+			int err = snd_usbmidi_create(chip->card, iface,
+						     &chip->midi_list, NULL);
+			if (err < 0) {
 				snd_printk(KERN_ERR "%d:%u:%d: cannot create sequencer device\n", dev->devnum, ctrlif, j);
 				continue;
 			}
@@ -3038,12 +3040,11 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip,
 			.type = QUIRK_MIDI_FIXED_ENDPOINT,
 			.data = &uaxx_ep
 		};
-		if (chip->usb_id == USB_ID(0x0582, 0x002b))
-			return snd_usb_create_midi_interface(chip, iface,
-							     &ua700_quirk);
-		else
-			return snd_usb_create_midi_interface(chip, iface,
-							     &uaxx_quirk);
+		const struct snd_usb_audio_quirk *quirk =
+			chip->usb_id == USB_ID(0x0582, 0x002b)
+			? &ua700_quirk : &uaxx_quirk;
+		return snd_usbmidi_create(chip->card, iface,
+					  &chip->midi_list, quirk);
 	}
 
 	if (altsd->bNumEndpoints != 1)
@@ -3370,6 +3371,13 @@ static int audiophile_skip_setting_quirk(struct snd_usb_audio *chip,
 	return 0; /* keep this altsetting */
 }
 
+static int create_any_midi_quirk(struct snd_usb_audio *chip,
+				 struct usb_interface *intf,
+				 const struct snd_usb_audio_quirk *quirk)
+{
+	return snd_usbmidi_create(chip->card, intf, &chip->midi_list, quirk);
+}
+
 /*
  * audio-interface quirks
  *
@@ -3387,14 +3395,14 @@ static int snd_usb_create_quirk(struct snd_usb_audio *chip,
 	static const quirk_func_t quirk_funcs[] = {
 		[QUIRK_IGNORE_INTERFACE] = ignore_interface_quirk,
 		[QUIRK_COMPOSITE] = create_composite_quirk,
-		[QUIRK_MIDI_STANDARD_INTERFACE] = snd_usb_create_midi_interface,
-		[QUIRK_MIDI_FIXED_ENDPOINT] = snd_usb_create_midi_interface,
-		[QUIRK_MIDI_YAMAHA] = snd_usb_create_midi_interface,
-		[QUIRK_MIDI_MIDIMAN] = snd_usb_create_midi_interface,
-		[QUIRK_MIDI_NOVATION] = snd_usb_create_midi_interface,
-		[QUIRK_MIDI_FASTLANE] = snd_usb_create_midi_interface,
-		[QUIRK_MIDI_EMAGIC] = snd_usb_create_midi_interface,
-		[QUIRK_MIDI_CME] = snd_usb_create_midi_interface,
+		[QUIRK_MIDI_STANDARD_INTERFACE] = create_any_midi_quirk,
+		[QUIRK_MIDI_FIXED_ENDPOINT] = create_any_midi_quirk,
+		[QUIRK_MIDI_YAMAHA] = create_any_midi_quirk,
+		[QUIRK_MIDI_MIDIMAN] = create_any_midi_quirk,
+		[QUIRK_MIDI_NOVATION] = create_any_midi_quirk,
+		[QUIRK_MIDI_FASTLANE] = create_any_midi_quirk,
+		[QUIRK_MIDI_EMAGIC] = create_any_midi_quirk,
+		[QUIRK_MIDI_CME] = create_any_midi_quirk,
 		[QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk,
 		[QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk,
 		[QUIRK_AUDIO_EDIROL_UA1000] = create_ua1000_quirk,
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index e9a3a9dca15c..40ba8115fb81 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -132,7 +132,6 @@ struct snd_usb_audio {
 	int pcm_devs;
 
 	struct list_head midi_list;	/* list of midi interfaces */
-	int next_midi_device;
 
 	struct list_head mixer_list;	/* list of mixer interfaces */
 };
@@ -227,8 +226,10 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
 			 int ignore_error);
 void snd_usb_mixer_disconnect(struct list_head *p);
 
-int snd_usb_create_midi_interface(struct snd_usb_audio *chip, struct usb_interface *iface,
-				  const struct snd_usb_audio_quirk *quirk);
+int snd_usbmidi_create(struct snd_card *card,
+		       struct usb_interface *iface,
+		       struct list_head *midi_list,
+		       const struct snd_usb_audio_quirk *quirk);
 void snd_usbmidi_input_stop(struct list_head* p);
 void snd_usbmidi_input_start(struct list_head* p);
 void snd_usbmidi_disconnect(struct list_head *p);
diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c
index 0eff19ceb7e1..6e89b8368d9a 100644
--- a/sound/usb/usbmidi.c
+++ b/sound/usb/usbmidi.c
@@ -1,7 +1,7 @@
 /*
  * usbmidi.c - ALSA USB MIDI driver
  *
- * Copyright (c) 2002-2007 Clemens Ladisch
+ * Copyright (c) 2002-2009 Clemens Ladisch
  * All rights reserved.
  *
  * Based on the OSS usb-midi driver by NAGANO Daisuke,
@@ -47,6 +47,7 @@
 #include <linux/usb.h>
 #include <linux/wait.h>
 #include <sound/core.h>
+#include <sound/control.h>
 #include <sound/rawmidi.h>
 #include <sound/asequencer.h>
 #include "usbaudio.h"
@@ -101,7 +102,8 @@ struct usb_protocol_ops {
 };
 
 struct snd_usb_midi {
-	struct snd_usb_audio *chip;
+	struct usb_device *dev;
+	struct snd_card *card;
 	struct usb_interface *iface;
 	const struct snd_usb_audio_quirk *quirk;
 	struct snd_rawmidi *rmidi;
@@ -109,13 +111,19 @@ struct snd_usb_midi {
 	struct list_head list;
 	struct timer_list error_timer;
 	spinlock_t disc_lock;
+	struct mutex mutex;
+	u32 usb_id;
+	int next_midi_device;
 
 	struct snd_usb_midi_endpoint {
 		struct snd_usb_midi_out_endpoint *out;
 		struct snd_usb_midi_in_endpoint *in;
 	} endpoints[MIDI_MAX_ENDPOINTS];
 	unsigned long input_triggered;
+	unsigned int opened;
 	unsigned char disconnected;
+
+	struct snd_kcontrol *roland_load_ctl;
 };
 
 struct snd_usb_midi_out_endpoint {
@@ -255,7 +263,7 @@ static void snd_usbmidi_in_urb_complete(struct urb* urb)
 		}
 	}
 
-	urb->dev = ep->umidi->chip->dev;
+	urb->dev = ep->umidi->dev;
 	snd_usbmidi_submit_urb(urb, GFP_ATOMIC);
 }
 
@@ -296,7 +304,7 @@ static void snd_usbmidi_do_output(struct snd_usb_midi_out_endpoint* ep)
 	unsigned long flags;
 
 	spin_lock_irqsave(&ep->buffer_lock, flags);
-	if (ep->umidi->chip->shutdown) {
+	if (ep->umidi->disconnected) {
 		spin_unlock_irqrestore(&ep->buffer_lock, flags);
 		return;
 	}
@@ -312,7 +320,7 @@ static void snd_usbmidi_do_output(struct snd_usb_midi_out_endpoint* ep)
 
 			dump_urb("sending", urb->transfer_buffer,
 				 urb->transfer_buffer_length);
-			urb->dev = ep->umidi->chip->dev;
+			urb->dev = ep->umidi->dev;
 			if (snd_usbmidi_submit_urb(urb, GFP_ATOMIC) < 0)
 				break;
 			ep->active_urbs |= 1 << urb_index;
@@ -349,7 +357,7 @@ static void snd_usbmidi_error_timer(unsigned long data)
 		if (in && in->error_resubmit) {
 			in->error_resubmit = 0;
 			for (j = 0; j < INPUT_URBS; ++j) {
-				in->urbs[j]->dev = umidi->chip->dev;
+				in->urbs[j]->dev = umidi->dev;
 				snd_usbmidi_submit_urb(in->urbs[j], GFP_ATOMIC);
 			}
 		}
@@ -369,7 +377,7 @@ static int send_bulk_static_data(struct snd_usb_midi_out_endpoint* ep,
 		return -ENOMEM;
 	dump_urb("sending", buf, len);
 	if (ep->urbs[0].urb)
-		err = usb_bulk_msg(ep->umidi->chip->dev, ep->urbs[0].urb->pipe,
+		err = usb_bulk_msg(ep->umidi->dev, ep->urbs[0].urb->pipe,
 				   buf, len, NULL, 250);
 	kfree(buf);
 	return err;
@@ -724,8 +732,7 @@ static void snd_usbmidi_us122l_output(struct snd_usb_midi_out_endpoint *ep,
 
 	if (!ep->ports[0].active)
 		return;
-	count = snd_usb_get_speed(ep->umidi->chip->dev) == USB_SPEED_HIGH
-		? 1 : 2;
+	count = snd_usb_get_speed(ep->umidi->dev) == USB_SPEED_HIGH ? 1 : 2;
 	count = snd_rawmidi_transmit(ep->ports[0].substream,
 				     urb->transfer_buffer,
 				     count);
@@ -879,6 +886,50 @@ static struct usb_protocol_ops snd_usbmidi_emagic_ops = {
 };
 
 
+static void update_roland_altsetting(struct snd_usb_midi* umidi)
+{
+	struct usb_interface *intf;
+	struct usb_host_interface *hostif;
+	struct usb_interface_descriptor *intfd;
+	int is_light_load;
+
+	intf = umidi->iface;
+	is_light_load = intf->cur_altsetting != intf->altsetting;
+	if (umidi->roland_load_ctl->private_value == is_light_load)
+		return;
+	hostif = &intf->altsetting[umidi->roland_load_ctl->private_value];
+	intfd = get_iface_desc(hostif);
+	snd_usbmidi_input_stop(&umidi->list);
+	usb_set_interface(umidi->dev, intfd->bInterfaceNumber,
+			  intfd->bAlternateSetting);
+	snd_usbmidi_input_start(&umidi->list);
+}
+
+static void substream_open(struct snd_rawmidi_substream *substream, int open)
+{
+	struct snd_usb_midi* umidi = substream->rmidi->private_data;
+	struct snd_kcontrol *ctl;
+
+	mutex_lock(&umidi->mutex);
+	if (open) {
+		if (umidi->opened++ == 0 && umidi->roland_load_ctl) {
+			ctl = umidi->roland_load_ctl;
+			ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+			snd_ctl_notify(umidi->card,
+				       SNDRV_CTL_EVENT_MASK_INFO, &ctl->id);
+			update_roland_altsetting(umidi);
+		}
+	} else {
+		if (--umidi->opened == 0 && umidi->roland_load_ctl) {
+			ctl = umidi->roland_load_ctl;
+			ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+			snd_ctl_notify(umidi->card,
+				       SNDRV_CTL_EVENT_MASK_INFO, &ctl->id);
+		}
+	}
+	mutex_unlock(&umidi->mutex);
+}
+
 static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream)
 {
 	struct snd_usb_midi* umidi = substream->rmidi->private_data;
@@ -898,11 +949,13 @@ static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream)
 	}
 	substream->runtime->private_data = port;
 	port->state = STATE_UNKNOWN;
+	substream_open(substream, 1);
 	return 0;
 }
 
 static int snd_usbmidi_output_close(struct snd_rawmidi_substream *substream)
 {
+	substream_open(substream, 0);
 	return 0;
 }
 
@@ -912,7 +965,7 @@ static void snd_usbmidi_output_trigger(struct snd_rawmidi_substream *substream,
 
 	port->active = up;
 	if (up) {
-		if (port->ep->umidi->chip->shutdown) {
+		if (port->ep->umidi->disconnected) {
 			/* gobble up remaining bytes to prevent wait in
 			 * snd_rawmidi_drain_output */
 			while (!snd_rawmidi_transmit_empty(substream))
@@ -954,11 +1007,13 @@ static void snd_usbmidi_output_drain(struct snd_rawmidi_substream *substream)
 
 static int snd_usbmidi_input_open(struct snd_rawmidi_substream *substream)
 {
+	substream_open(substream, 1);
 	return 0;
 }
 
 static int snd_usbmidi_input_close(struct snd_rawmidi_substream *substream)
 {
+	substream_open(substream, 0);
 	return 0;
 }
 
@@ -988,7 +1043,7 @@ static struct snd_rawmidi_ops snd_usbmidi_input_ops = {
 static void free_urb_and_buffer(struct snd_usb_midi *umidi, struct urb *urb,
 				unsigned int buffer_length)
 {
-	usb_buffer_free(umidi->chip->dev, buffer_length,
+	usb_buffer_free(umidi->dev, buffer_length,
 			urb->transfer_buffer, urb->transfer_dma);
 	usb_free_urb(urb);
 }
@@ -1035,24 +1090,24 @@ static int snd_usbmidi_in_endpoint_create(struct snd_usb_midi* umidi,
 		}
 	}
 	if (ep_info->in_interval)
-		pipe = usb_rcvintpipe(umidi->chip->dev, ep_info->in_ep);
+		pipe = usb_rcvintpipe(umidi->dev, ep_info->in_ep);
 	else
-		pipe = usb_rcvbulkpipe(umidi->chip->dev, ep_info->in_ep);
-	length = usb_maxpacket(umidi->chip->dev, pipe, 0);
+		pipe = usb_rcvbulkpipe(umidi->dev, ep_info->in_ep);
+	length = usb_maxpacket(umidi->dev, pipe, 0);
 	for (i = 0; i < INPUT_URBS; ++i) {
-		buffer = usb_buffer_alloc(umidi->chip->dev, length, GFP_KERNEL,
+		buffer = usb_buffer_alloc(umidi->dev, length, GFP_KERNEL,
 					  &ep->urbs[i]->transfer_dma);
 		if (!buffer) {
 			snd_usbmidi_in_endpoint_delete(ep);
 			return -ENOMEM;
 		}
 		if (ep_info->in_interval)
-			usb_fill_int_urb(ep->urbs[i], umidi->chip->dev,
+			usb_fill_int_urb(ep->urbs[i], umidi->dev,
 					 pipe, buffer, length,
 					 snd_usbmidi_in_urb_complete,
 					 ep, ep_info->in_interval);
 		else
-			usb_fill_bulk_urb(ep->urbs[i], umidi->chip->dev,
+			usb_fill_bulk_urb(ep->urbs[i], umidi->dev,
 					  pipe, buffer, length,
 					  snd_usbmidi_in_urb_complete, ep);
 		ep->urbs[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
@@ -1062,15 +1117,6 @@ static int snd_usbmidi_in_endpoint_create(struct snd_usb_midi* umidi,
 	return 0;
 }
 
-static unsigned int snd_usbmidi_count_bits(unsigned int x)
-{
-	unsigned int bits;
-
-	for (bits = 0; x; ++bits)
-		x &= x - 1;
-	return bits;
-}
-
 /*
  * Frees an output endpoint.
  * May be called when ep hasn't been initialized completely.
@@ -1113,15 +1159,15 @@ static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi* umidi,
 		ep->urbs[i].ep = ep;
 	}
 	if (ep_info->out_interval)
-		pipe = usb_sndintpipe(umidi->chip->dev, ep_info->out_ep);
+		pipe = usb_sndintpipe(umidi->dev, ep_info->out_ep);
 	else
-		pipe = usb_sndbulkpipe(umidi->chip->dev, ep_info->out_ep);
-	if (umidi->chip->usb_id == USB_ID(0x0a92, 0x1020)) /* ESI M4U */
+		pipe = usb_sndbulkpipe(umidi->dev, ep_info->out_ep);
+	if (umidi->usb_id == USB_ID(0x0a92, 0x1020)) /* ESI M4U */
 		ep->max_transfer = 4;
 	else
-		ep->max_transfer = usb_maxpacket(umidi->chip->dev, pipe, 1);
+		ep->max_transfer = usb_maxpacket(umidi->dev, pipe, 1);
 	for (i = 0; i < OUTPUT_URBS; ++i) {
-		buffer = usb_buffer_alloc(umidi->chip->dev,
+		buffer = usb_buffer_alloc(umidi->dev,
 					  ep->max_transfer, GFP_KERNEL,
 					  &ep->urbs[i].urb->transfer_dma);
 		if (!buffer) {
@@ -1129,12 +1175,12 @@ static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi* umidi,
 			return -ENOMEM;
 		}
 		if (ep_info->out_interval)
-			usb_fill_int_urb(ep->urbs[i].urb, umidi->chip->dev,
+			usb_fill_int_urb(ep->urbs[i].urb, umidi->dev,
 					 pipe, buffer, ep->max_transfer,
 					 snd_usbmidi_out_urb_complete,
 					 &ep->urbs[i], ep_info->out_interval);
 		else
-			usb_fill_bulk_urb(ep->urbs[i].urb, umidi->chip->dev,
+			usb_fill_bulk_urb(ep->urbs[i].urb, umidi->dev,
 					  pipe, buffer, ep->max_transfer,
 					  snd_usbmidi_out_urb_complete,
 					  &ep->urbs[i]);
@@ -1172,6 +1218,7 @@ static void snd_usbmidi_free(struct snd_usb_midi* umidi)
 		if (ep->in)
 			snd_usbmidi_in_endpoint_delete(ep->in);
 	}
+	mutex_destroy(&umidi->mutex);
 	kfree(umidi);
 }
 
@@ -1367,7 +1414,7 @@ static struct port_info *find_port_info(struct snd_usb_midi* umidi, int number)
 	int i;
 
 	for (i = 0; i < ARRAY_SIZE(snd_usbmidi_port_info); ++i) {
-		if (snd_usbmidi_port_info[i].id == umidi->chip->usb_id &&
+		if (snd_usbmidi_port_info[i].id == umidi->usb_id &&
 		    snd_usbmidi_port_info[i].port == number)
 			return &snd_usbmidi_port_info[i];
 	}
@@ -1405,7 +1452,7 @@ static void snd_usbmidi_init_substream(struct snd_usb_midi* umidi,
 	port_info = find_port_info(umidi, number);
 	name_format = port_info ? port_info->name : "%s MIDI %d";
 	snprintf(substream->name, sizeof(substream->name),
-		 name_format, umidi->chip->card->shortname, number + 1);
+		 name_format, umidi->card->shortname, number + 1);
 
 	*rsubstream = substream;
 }
@@ -1503,7 +1550,7 @@ static int snd_usbmidi_get_ms_info(struct snd_usb_midi* umidi,
 			endpoints[epidx].out_ep = usb_endpoint_num(ep);
 			if (usb_endpoint_xfer_int(ep))
 				endpoints[epidx].out_interval = ep->bInterval;
-			else if (snd_usb_get_speed(umidi->chip->dev) == USB_SPEED_LOW)
+			else if (snd_usb_get_speed(umidi->dev) == USB_SPEED_LOW)
 				/*
 				 * Low speed bulk transfers don't exist, so
 				 * force interrupt transfers for devices like
@@ -1523,7 +1570,7 @@ static int snd_usbmidi_get_ms_info(struct snd_usb_midi* umidi,
 			endpoints[epidx].in_ep = usb_endpoint_num(ep);
 			if (usb_endpoint_xfer_int(ep))
 				endpoints[epidx].in_interval = ep->bInterval;
-			else if (snd_usb_get_speed(umidi->chip->dev) == USB_SPEED_LOW)
+			else if (snd_usb_get_speed(umidi->dev) == USB_SPEED_LOW)
 				endpoints[epidx].in_interval = 1;
 			endpoints[epidx].in_cables = (1 << ms_ep->bNumEmbMIDIJack) - 1;
 			snd_printdd(KERN_INFO "EP %02X: %d jack(s)\n",
@@ -1533,6 +1580,52 @@ static int snd_usbmidi_get_ms_info(struct snd_usb_midi* umidi,
 	return 0;
 }
 
+static int roland_load_info(struct snd_kcontrol *kcontrol,
+			    struct snd_ctl_elem_info *info)
+{
+	static const char *const names[] = { "High Load", "Light Load" };
+
+	info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	info->count = 1;
+	info->value.enumerated.items = 2;
+	if (info->value.enumerated.item > 1)
+		info->value.enumerated.item = 1;
+	strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
+	return 0;
+}
+
+static int roland_load_get(struct snd_kcontrol *kcontrol,
+			   struct snd_ctl_elem_value *value)
+{
+	value->value.enumerated.item[0] = kcontrol->private_value;
+	return 0;
+}
+
+static int roland_load_put(struct snd_kcontrol *kcontrol,
+			   struct snd_ctl_elem_value *value)
+{
+	struct snd_usb_midi* umidi = kcontrol->private_data;
+	int changed;
+
+	if (value->value.enumerated.item[0] > 1)
+		return -EINVAL;
+	mutex_lock(&umidi->mutex);
+	changed = value->value.enumerated.item[0] != kcontrol->private_value;
+	if (changed)
+		kcontrol->private_value = value->value.enumerated.item[0];
+	mutex_unlock(&umidi->mutex);
+	return changed;
+}
+
+static struct snd_kcontrol_new roland_load_ctl = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "MIDI Input Mode",
+	.info = roland_load_info,
+	.get = roland_load_get,
+	.put = roland_load_put,
+	.private_value = 1,
+};
+
 /*
  * On Roland devices, use the second alternate setting to be able to use
  * the interrupt input endpoint.
@@ -1556,8 +1649,12 @@ static void snd_usbmidi_switch_roland_altsetting(struct snd_usb_midi* umidi)
 
 	snd_printdd(KERN_INFO "switching to altsetting %d with int ep\n",
 		    intfd->bAlternateSetting);
-	usb_set_interface(umidi->chip->dev, intfd->bInterfaceNumber,
+	usb_set_interface(umidi->dev, intfd->bInterfaceNumber,
 			  intfd->bAlternateSetting);
+
+	umidi->roland_load_ctl = snd_ctl_new1(&roland_load_ctl, umidi);
+	if (snd_ctl_add(umidi->card, umidi->roland_load_ctl) < 0)
+		umidi->roland_load_ctl = NULL;
 }
 
 /*
@@ -1573,7 +1670,7 @@ static int snd_usbmidi_detect_endpoints(struct snd_usb_midi* umidi,
 	struct usb_endpoint_descriptor* epd;
 	int i, out_eps = 0, in_eps = 0;
 
-	if (USB_ID_VENDOR(umidi->chip->usb_id) == 0x0582)
+	if (USB_ID_VENDOR(umidi->usb_id) == 0x0582)
 		snd_usbmidi_switch_roland_altsetting(umidi);
 
 	if (endpoint[0].out_ep || endpoint[0].in_ep)
@@ -1760,12 +1857,12 @@ static int snd_usbmidi_create_rawmidi(struct snd_usb_midi* umidi,
 	struct snd_rawmidi *rmidi;
 	int err;
 
-	err = snd_rawmidi_new(umidi->chip->card, "USB MIDI",
-			      umidi->chip->next_midi_device++,
+	err = snd_rawmidi_new(umidi->card, "USB MIDI",
+			      umidi->next_midi_device++,
 			      out_ports, in_ports, &rmidi);
 	if (err < 0)
 		return err;
-	strcpy(rmidi->name, umidi->chip->card->shortname);
+	strcpy(rmidi->name, umidi->card->shortname);
 	rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT |
 			    SNDRV_RAWMIDI_INFO_INPUT |
 			    SNDRV_RAWMIDI_INFO_DUPLEX;
@@ -1804,7 +1901,7 @@ static void snd_usbmidi_input_start_ep(struct snd_usb_midi_in_endpoint* ep)
 		return;
 	for (i = 0; i < INPUT_URBS; ++i) {
 		struct urb* urb = ep->urbs[i];
-		urb->dev = ep->umidi->chip->dev;
+		urb->dev = ep->umidi->dev;
 		snd_usbmidi_submit_urb(urb, GFP_KERNEL);
 	}
 }
@@ -1825,9 +1922,10 @@ void snd_usbmidi_input_start(struct list_head* p)
 /*
  * Creates and registers everything needed for a MIDI streaming interface.
  */
-int snd_usb_create_midi_interface(struct snd_usb_audio* chip,
-				  struct usb_interface* iface,
-				  const struct snd_usb_audio_quirk* quirk)
+int snd_usbmidi_create(struct snd_card *card,
+		       struct usb_interface* iface,
+		       struct list_head *midi_list,
+		       const struct snd_usb_audio_quirk* quirk)
 {
 	struct snd_usb_midi* umidi;
 	struct snd_usb_midi_endpoint_info endpoints[MIDI_MAX_ENDPOINTS];
@@ -1837,12 +1935,16 @@ int snd_usb_create_midi_interface(struct snd_usb_audio* chip,
 	umidi = kzalloc(sizeof(*umidi), GFP_KERNEL);
 	if (!umidi)
 		return -ENOMEM;
-	umidi->chip = chip;
+	umidi->dev = interface_to_usbdev(iface);
+	umidi->card = card;
 	umidi->iface = iface;
 	umidi->quirk = quirk;
 	umidi->usb_protocol_ops = &snd_usbmidi_standard_ops;
 	init_timer(&umidi->error_timer);
 	spin_lock_init(&umidi->disc_lock);
+	mutex_init(&umidi->mutex);
+	umidi->usb_id = USB_ID(le16_to_cpu(umidi->dev->descriptor.idVendor),
+			       le16_to_cpu(umidi->dev->descriptor.idProduct));
 	umidi->error_timer.function = snd_usbmidi_error_timer;
 	umidi->error_timer.data = (unsigned long)umidi;
 
@@ -1851,7 +1953,7 @@ int snd_usb_create_midi_interface(struct snd_usb_audio* chip,
 	switch (quirk ? quirk->type : QUIRK_MIDI_STANDARD_INTERFACE) {
 	case QUIRK_MIDI_STANDARD_INTERFACE:
 		err = snd_usbmidi_get_ms_info(umidi, endpoints);
-		if (chip->usb_id == USB_ID(0x0763, 0x0150)) /* M-Audio Uno */
+		if (umidi->usb_id == USB_ID(0x0763, 0x0150)) /* M-Audio Uno */
 			umidi->usb_protocol_ops =
 				&snd_usbmidi_maudio_broken_running_status_ops;
 		break;
@@ -1887,7 +1989,7 @@ int snd_usb_create_midi_interface(struct snd_usb_audio* chip,
 		 * interface 0, so we have to make sure that the USB core looks
 		 * again at interface 0 by calling usb_set_interface() on it.
 		 */
-		usb_set_interface(umidi->chip->dev, 0, 0);
+		usb_set_interface(umidi->dev, 0, 0);
 		err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints);
 		break;
 	case QUIRK_MIDI_EMAGIC:
@@ -1914,8 +2016,8 @@ int snd_usb_create_midi_interface(struct snd_usb_audio* chip,
 	out_ports = 0;
 	in_ports = 0;
 	for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
-		out_ports += snd_usbmidi_count_bits(endpoints[i].out_cables);
-		in_ports += snd_usbmidi_count_bits(endpoints[i].in_cables);
+		out_ports += hweight16(endpoints[i].out_cables);
+		in_ports += hweight16(endpoints[i].in_cables);
 	}
 	err = snd_usbmidi_create_rawmidi(umidi, out_ports, in_ports);
 	if (err < 0) {
@@ -1933,14 +2035,14 @@ int snd_usb_create_midi_interface(struct snd_usb_audio* chip,
 		return err;
 	}
 
-	list_add(&umidi->list, &umidi->chip->midi_list);
+	list_add_tail(&umidi->list, midi_list);
 
 	for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i)
 		snd_usbmidi_input_start_ep(umidi->endpoints[i].in);
 	return 0;
 }
 
-EXPORT_SYMBOL(snd_usb_create_midi_interface);
+EXPORT_SYMBOL(snd_usbmidi_create);
 EXPORT_SYMBOL(snd_usbmidi_input_stop);
 EXPORT_SYMBOL(snd_usbmidi_input_start);
 EXPORT_SYMBOL(snd_usbmidi_disconnect);
diff --git a/sound/usb/usbmixer_maps.c b/sound/usb/usbmixer_maps.c
index 3e5d66cf1f5a..77c35885e21c 100644
--- a/sound/usb/usbmixer_maps.c
+++ b/sound/usb/usbmixer_maps.c
@@ -277,6 +277,22 @@ static struct usbmix_name_map scratch_live_map[] = {
 	{ 0 } /* terminator */
 };
 
+/* "Gamesurround Muse Pocket LT" looks same like "Sound Blaster MP3+"
+ *  most importand difference is SU[8], it should be set to "Capture Source"
+ *  to make alsamixer and PA working properly.
+ *  FIXME: or mp3plus_map should use "Capture Source" too,
+ *  so this maps can be merget
+ */
+static struct usbmix_name_map hercules_usb51_map[] = {
+	{ 8, "Capture Source" },	/* SU, default "PCM Capture Source" */
+	{ 9, "Master Playback" },	/* FU, default "Speaker Playback" */
+	{ 10, "Mic Boost", 7 },		/* FU, default "Auto Gain Input" */
+	{ 11, "Line Capture" },		/* FU, default "PCM Capture" */
+	{ 13, "Mic Bypass Playback" },	/* FU, default "Mic Playback" */
+	{ 14, "Line Bypass Playback" },	/* FU, default "Line Playback" */
+	{ 0 }				/* terminator */
+};
+
 /*
  * Control map entries
  */
@@ -316,6 +332,13 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = {
 		.ignore_ctl_error = 1,
 	},
 	{
+		/* Hercules Gamesurround Muse Pocket LT
+		 * (USB 5.1 Channel Audio Adapter)
+		 */
+		.id = USB_ID(0x06f8, 0xc000),
+		.map = hercules_usb51_map,
+	},
+	{
 		.id = USB_ID(0x08bb, 0x2702),
 		.map = linex_map,
 		.ignore_ctl_error = 1,
diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h
index f6f201eb24ce..a892bda03df9 100644
--- a/sound/usb/usbquirks.h
+++ b/sound/usb/usbquirks.h
@@ -1563,6 +1563,29 @@ YAMAHA_DEVICE(0x7010, "UB99"),
 		}
 	}
 },
+{
+	/* has ID 0x00ea when not in Advanced Driver mode */
+	USB_DEVICE_VENDOR_SPEC(0x0582, 0x00e9),
+	.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+		/* .vendor_name = "Roland", */
+		/* .product_name = "UA-1G", */
+		.ifnum = QUIRK_ANY_INTERFACE,
+		.type = QUIRK_COMPOSITE,
+		.data = (const struct snd_usb_audio_quirk[]) {
+			{
+				.ifnum = 0,
+				.type = QUIRK_AUDIO_STANDARD_INTERFACE
+			},
+			{
+				.ifnum = 1,
+				.type = QUIRK_AUDIO_STANDARD_INTERFACE
+			},
+			{
+				.ifnum = -1
+			}
+		}
+	}
+},
 
 /* Guillemot devices */
 {
diff --git a/sound/usb/usx2y/us122l.c b/sound/usb/usx2y/us122l.c
index 99f33766cd51..f71cd28eca6b 100644
--- a/sound/usb/usx2y/us122l.c
+++ b/sound/usb/usx2y/us122l.c
@@ -59,11 +59,33 @@ static int us122l_create_usbmidi(struct snd_card *card)
 		.type = QUIRK_MIDI_US122L,
 		.data = &quirk_data
 	};
-	struct usb_device *dev = US122L(card)->chip.dev;
+	struct usb_device *dev = US122L(card)->dev;
 	struct usb_interface *iface = usb_ifnum_to_if(dev, 1);
 
-	return snd_usb_create_midi_interface(&US122L(card)->chip,
-					     iface, &quirk);
+	return snd_usbmidi_create(card, iface,
+				  &US122L(card)->midi_list, &quirk);
+}
+
+static int us144_create_usbmidi(struct snd_card *card)
+{
+	static struct snd_usb_midi_endpoint_info quirk_data = {
+		.out_ep = 4,
+		.in_ep = 3,
+		.out_cables =	0x001,
+		.in_cables =	0x001
+	};
+	static struct snd_usb_audio_quirk quirk = {
+		.vendor_name =	"US144",
+		.product_name =	NAME_ALLCAPS,
+		.ifnum = 	0,
+		.type = QUIRK_MIDI_US122L,
+		.data = &quirk_data
+	};
+	struct usb_device *dev = US122L(card)->dev;
+	struct usb_interface *iface = usb_ifnum_to_if(dev, 0);
+
+	return snd_usbmidi_create(card, iface,
+				  &US122L(card)->midi_list, &quirk);
 }
 
 /*
@@ -171,7 +193,12 @@ static int usb_stream_hwdep_open(struct snd_hwdep *hw, struct file *file)
 
 	if (!us122l->first)
 		us122l->first = file;
-	iface = usb_ifnum_to_if(us122l->chip.dev, 1);
+
+	if (us122l->dev->descriptor.idProduct == USB_ID_US144) {
+		iface = usb_ifnum_to_if(us122l->dev, 0);
+		usb_autopm_get_interface(iface);
+	}
+	iface = usb_ifnum_to_if(us122l->dev, 1);
 	usb_autopm_get_interface(iface);
 	return 0;
 }
@@ -179,8 +206,14 @@ static int usb_stream_hwdep_open(struct snd_hwdep *hw, struct file *file)
 static int usb_stream_hwdep_release(struct snd_hwdep *hw, struct file *file)
 {
 	struct us122l	*us122l = hw->private_data;
-	struct usb_interface *iface = usb_ifnum_to_if(us122l->chip.dev, 1);
+	struct usb_interface *iface;
 	snd_printdd(KERN_DEBUG "%p %p\n", hw, file);
+
+	if (us122l->dev->descriptor.idProduct == USB_ID_US144) {
+		iface = usb_ifnum_to_if(us122l->dev, 0);
+		usb_autopm_put_interface(iface);
+	}
+	iface = usb_ifnum_to_if(us122l->dev, 1);
 	usb_autopm_put_interface(iface);
 	if (us122l->first == file)
 		us122l->first = NULL;
@@ -264,7 +297,7 @@ static unsigned int usb_stream_hwdep_poll(struct snd_hwdep *hw,
 static void us122l_stop(struct us122l *us122l)
 {
 	struct list_head *p;
-	list_for_each(p, &us122l->chip.midi_list)
+	list_for_each(p, &us122l->midi_list)
 		snd_usbmidi_input_stop(p);
 
 	usb_stream_stop(&us122l->sk);
@@ -297,7 +330,7 @@ static bool us122l_start(struct us122l *us122l,
 	unsigned use_packsize = 0;
 	bool success = false;
 
-	if (us122l->chip.dev->speed == USB_SPEED_HIGH) {
+	if (us122l->dev->speed == USB_SPEED_HIGH) {
 		/* The us-122l's descriptor defaults to iso max_packsize 78,
 		   which isn't needed for samplerates <= 48000.
 		   Lets save some memory:
@@ -314,11 +347,11 @@ static bool us122l_start(struct us122l *us122l,
 			break;
 		}
 	}
-	if (!usb_stream_new(&us122l->sk, us122l->chip.dev, 1, 2,
+	if (!usb_stream_new(&us122l->sk, us122l->dev, 1, 2,
 			    rate, use_packsize, period_frames, 6))
 		goto out;
 
-	err = us122l_set_sample_rate(us122l->chip.dev, rate);
+	err = us122l_set_sample_rate(us122l->dev, rate);
 	if (err < 0) {
 		us122l_stop(us122l);
 		snd_printk(KERN_ERR "us122l_set_sample_rate error \n");
@@ -330,7 +363,7 @@ static bool us122l_start(struct us122l *us122l,
 		snd_printk(KERN_ERR "us122l_start error %i \n", err);
 		goto out;
 	}
-	list_for_each(p, &us122l->chip.midi_list)
+	list_for_each(p, &us122l->midi_list)
 		snd_usbmidi_input_start(p);
 	success = true;
 out:
@@ -357,7 +390,7 @@ static int usb_stream_hwdep_ioctl(struct snd_hwdep *hw, struct file *file,
 		err = -ENXIO;
 		goto free;
 	}
-	high_speed = us122l->chip.dev->speed == USB_SPEED_HIGH;
+	high_speed = us122l->dev->speed == USB_SPEED_HIGH;
 	if ((cfg->sample_rate != 44100 && cfg->sample_rate != 48000  &&
 	     (!high_speed ||
 	      (cfg->sample_rate != 88200 && cfg->sample_rate != 96000))) ||
@@ -417,7 +450,7 @@ static int usb_stream_hwdep_new(struct snd_card *card)
 {
 	int err;
 	struct snd_hwdep *hw;
-	struct usb_device *dev = US122L(card)->chip.dev;
+	struct usb_device *dev = US122L(card)->dev;
 
 	err = snd_hwdep_new(card, SND_USB_STREAM_ID, 0, &hw);
 	if (err < 0)
@@ -443,19 +476,29 @@ static bool us122l_create_card(struct snd_card *card)
 	int err;
 	struct us122l *us122l = US122L(card);
 
-	err = usb_set_interface(us122l->chip.dev, 1, 1);
+	if (us122l->dev->descriptor.idProduct == USB_ID_US144) {
+		err = usb_set_interface(us122l->dev, 0, 1);
+		if (err) {
+			snd_printk(KERN_ERR "usb_set_interface error \n");
+			return false;
+		}
+	}
+	err = usb_set_interface(us122l->dev, 1, 1);
 	if (err) {
 		snd_printk(KERN_ERR "usb_set_interface error \n");
 		return false;
 	}
 
-	pt_info_set(us122l->chip.dev, 0x11);
-	pt_info_set(us122l->chip.dev, 0x10);
+	pt_info_set(us122l->dev, 0x11);
+	pt_info_set(us122l->dev, 0x10);
 
 	if (!us122l_start(us122l, 44100, 256))
 		return false;
 
-	err = us122l_create_usbmidi(card);
+	if (us122l->dev->descriptor.idProduct == USB_ID_US144)
+		err = us144_create_usbmidi(card);
+	else
+		err = us122l_create_usbmidi(card);
 	if (err < 0) {
 		snd_printk(KERN_ERR "us122l_create_usbmidi error %i \n", err);
 		us122l_stop(us122l);
@@ -465,7 +508,7 @@ static bool us122l_create_card(struct snd_card *card)
 	if (err < 0) {
 /* release the midi resources */
 		struct list_head *p;
-		list_for_each(p, &us122l->chip.midi_list)
+		list_for_each(p, &us122l->midi_list)
 			snd_usbmidi_disconnect(p);
 
 		us122l_stop(us122l);
@@ -477,7 +520,7 @@ static bool us122l_create_card(struct snd_card *card)
 static void snd_us122l_free(struct snd_card *card)
 {
 	struct us122l	*us122l = US122L(card);
-	int		index = us122l->chip.index;
+	int		index = us122l->card_index;
 	if (index >= 0  &&  index < SNDRV_CARDS)
 		snd_us122l_card_used[index] = 0;
 }
@@ -497,13 +540,12 @@ static int usx2y_create_card(struct usb_device *device, struct snd_card **cardp)
 			      sizeof(struct us122l), &card);
 	if (err < 0)
 		return err;
-	snd_us122l_card_used[US122L(card)->chip.index = dev] = 1;
+	snd_us122l_card_used[US122L(card)->card_index = dev] = 1;
 	card->private_free = snd_us122l_free;
-	US122L(card)->chip.dev = device;
-	US122L(card)->chip.card = card;
+	US122L(card)->dev = device;
 	mutex_init(&US122L(card)->mutex);
 	init_waitqueue_head(&US122L(card)->sk.sleep);
-	INIT_LIST_HEAD(&US122L(card)->chip.midi_list);
+	INIT_LIST_HEAD(&US122L(card)->midi_list);
 	strcpy(card->driver, "USB "NAME_ALLCAPS"");
 	sprintf(card->shortname, "TASCAM "NAME_ALLCAPS"");
 	sprintf(card->longname, "%s (%x:%x if %d at %03d/%03d)",
@@ -511,8 +553,8 @@ static int usx2y_create_card(struct usb_device *device, struct snd_card **cardp)
 		le16_to_cpu(device->descriptor.idVendor),
 		le16_to_cpu(device->descriptor.idProduct),
 		0,
-		US122L(card)->chip.dev->bus->busnum,
-		US122L(card)->chip.dev->devnum
+		US122L(card)->dev->bus->busnum,
+		US122L(card)->dev->devnum
 		);
 	*cardp = card;
 	return 0;
@@ -542,6 +584,7 @@ static int us122l_usb_probe(struct usb_interface *intf,
 		return err;
 	}
 
+	usb_get_intf(usb_ifnum_to_if(device, 0));
 	usb_get_dev(device);
 	*cardp = card;
 	return 0;
@@ -550,9 +593,16 @@ static int us122l_usb_probe(struct usb_interface *intf,
 static int snd_us122l_probe(struct usb_interface *intf,
 			    const struct usb_device_id *id)
 {
+	struct usb_device *device = interface_to_usbdev(intf);
 	struct snd_card *card;
 	int err;
 
+	if (device->descriptor.idProduct == USB_ID_US144
+		&& device->speed == USB_SPEED_HIGH) {
+		snd_printk(KERN_ERR "disable ehci-hcd to run US-144 \n");
+		return -ENODEV;
+	}
+
 	snd_printdd(KERN_DEBUG"%p:%i\n",
 		    intf, intf->cur_altsetting->desc.bInterfaceNumber);
 	if (intf->cur_altsetting->desc.bInterfaceNumber != 1)
@@ -584,15 +634,15 @@ static void snd_us122l_disconnect(struct usb_interface *intf)
 	mutex_lock(&us122l->mutex);
 	us122l_stop(us122l);
 	mutex_unlock(&us122l->mutex);
-	us122l->chip.shutdown = 1;
 
 /* release the midi resources */
-	list_for_each(p, &us122l->chip.midi_list) {
+	list_for_each(p, &us122l->midi_list) {
 		snd_usbmidi_disconnect(p);
 	}
 
-	usb_put_intf(intf);
-	usb_put_dev(us122l->chip.dev);
+	usb_put_intf(usb_ifnum_to_if(us122l->dev, 0));
+	usb_put_intf(usb_ifnum_to_if(us122l->dev, 1));
+	usb_put_dev(us122l->dev);
 
 	while (atomic_read(&us122l->mmap_count))
 		msleep(500);
@@ -615,7 +665,7 @@ static int snd_us122l_suspend(struct usb_interface *intf, pm_message_t message)
 	if (!us122l)
 		return 0;
 
-	list_for_each(p, &us122l->chip.midi_list)
+	list_for_each(p, &us122l->midi_list)
 		snd_usbmidi_input_stop(p);
 
 	mutex_lock(&us122l->mutex);
@@ -642,16 +692,23 @@ static int snd_us122l_resume(struct usb_interface *intf)
 
 	mutex_lock(&us122l->mutex);
 	/* needed, doesn't restart without: */
-	err = usb_set_interface(us122l->chip.dev, 1, 1);
+	if (us122l->dev->descriptor.idProduct == USB_ID_US144) {
+		err = usb_set_interface(us122l->dev, 0, 1);
+		if (err) {
+			snd_printk(KERN_ERR "usb_set_interface error \n");
+			goto unlock;
+		}
+	}
+	err = usb_set_interface(us122l->dev, 1, 1);
 	if (err) {
 		snd_printk(KERN_ERR "usb_set_interface error \n");
 		goto unlock;
 	}
 
-	pt_info_set(us122l->chip.dev, 0x11);
-	pt_info_set(us122l->chip.dev, 0x10);
+	pt_info_set(us122l->dev, 0x11);
+	pt_info_set(us122l->dev, 0x10);
 
-	err = us122l_set_sample_rate(us122l->chip.dev,
+	err = us122l_set_sample_rate(us122l->dev,
 				     us122l->sk.s->cfg.sample_rate);
 	if (err < 0) {
 		snd_printk(KERN_ERR "us122l_set_sample_rate error \n");
@@ -661,7 +718,7 @@ static int snd_us122l_resume(struct usb_interface *intf)
 	if (err)
 		goto unlock;
 
-	list_for_each(p, &us122l->chip.midi_list)
+	list_for_each(p, &us122l->midi_list)
 		snd_usbmidi_input_start(p);
 unlock:
 	mutex_unlock(&us122l->mutex);
@@ -675,11 +732,11 @@ static struct usb_device_id snd_us122l_usb_id_table[] = {
 		.idVendor =	0x0644,
 		.idProduct =	USB_ID_US122L
 	},
-/*  	{ */		/* US-144 maybe works when @USB1.1. Untested. */
-/* 		.match_flags =	USB_DEVICE_ID_MATCH_DEVICE, */
-/* 		.idVendor =	0x0644, */
-/* 		.idProduct =	USB_ID_US144 */
-/* 	}, */
+	{	/* US-144 only works at USB1.1! Disable module ehci-hcd. */
+		.match_flags =	USB_DEVICE_ID_MATCH_DEVICE,
+		.idVendor =	0x0644,
+		.idProduct =	USB_ID_US144
+	},
 	{ /* terminator */ }
 };
 
diff --git a/sound/usb/usx2y/us122l.h b/sound/usb/usx2y/us122l.h
index 3d10c4b2a0f5..4daf1982e821 100644
--- a/sound/usb/usx2y/us122l.h
+++ b/sound/usb/usx2y/us122l.h
@@ -3,7 +3,8 @@
 
 
 struct us122l {
-	struct snd_usb_audio 	chip;
+	struct usb_device	*dev;
+	int			card_index;
 	int			stride;
 	struct usb_stream_kernel sk;
 
@@ -12,6 +13,7 @@ struct us122l {
 	unsigned		second_periods_polled;
 	struct file		*master;
 	struct file		*slave;
+	struct list_head	midi_list;
 
 	atomic_t		mmap_count;
 };
diff --git a/sound/usb/usx2y/usX2Yhwdep.c b/sound/usb/usx2y/usX2Yhwdep.c
index 52e04b2f35d3..1879b72c40f8 100644
--- a/sound/usb/usx2y/usX2Yhwdep.c
+++ b/sound/usb/usx2y/usX2Yhwdep.c
@@ -114,7 +114,7 @@ static int snd_usX2Y_hwdep_dsp_status(struct snd_hwdep *hw,
 	struct usX2Ydev	*us428 = hw->private_data;
 	int id = -1;
 
-	switch (le16_to_cpu(us428->chip.dev->descriptor.idProduct)) {
+	switch (le16_to_cpu(us428->dev->descriptor.idProduct)) {
 	case USB_ID_US122:
 		id = USX2Y_TYPE_122;
 		break;
@@ -164,14 +164,14 @@ static int usX2Y_create_usbmidi(struct snd_card *card)
        		.type = QUIRK_MIDI_FIXED_ENDPOINT,
 		.data = &quirk_data_2
 	};
-	struct usb_device *dev = usX2Y(card)->chip.dev;
+	struct usb_device *dev = usX2Y(card)->dev;
 	struct usb_interface *iface = usb_ifnum_to_if(dev, 0);
 	struct snd_usb_audio_quirk *quirk =
 		le16_to_cpu(dev->descriptor.idProduct) == USB_ID_US428 ?
 		&quirk_2 : &quirk_1;
 
 	snd_printdd("usX2Y_create_usbmidi \n");
-	return snd_usb_create_midi_interface(&usX2Y(card)->chip, iface, quirk);
+	return snd_usbmidi_create(card, iface, &usX2Y(card)->midi_list, quirk);
 }
 
 static int usX2Y_create_alsa_devices(struct snd_card *card)
@@ -202,7 +202,7 @@ static int snd_usX2Y_hwdep_dsp_load(struct snd_hwdep *hw,
 	snd_printdd( "dsp_load %s\n", dsp->name);
 
 	if (access_ok(VERIFY_READ, dsp->image, dsp->length)) {
-		struct usb_device* dev = priv->chip.dev;
+		struct usb_device* dev = priv->dev;
 		char *buf;
 
 		buf = memdup_user(dsp->image, dsp->length);
diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c
index cb4bb8373ca2..c42350eed2eb 100644
--- a/sound/usb/usx2y/usbusx2y.c
+++ b/sound/usb/usx2y/usbusx2y.c
@@ -239,8 +239,8 @@ static void i_usX2Y_In04Int(struct urb *urb)
 				for (j = 0; j < URBS_AsyncSeq  &&  !err; ++j)
 					if (0 == usX2Y->AS04.urb[j]->status) {
 						struct us428_p4out *p4out = us428ctls->p4out + send;	// FIXME if more than 1 p4out is new, 1 gets lost.
-						usb_fill_bulk_urb(usX2Y->AS04.urb[j], usX2Y->chip.dev,
-								  usb_sndbulkpipe(usX2Y->chip.dev, 0x04), &p4out->val.vol, 
+						usb_fill_bulk_urb(usX2Y->AS04.urb[j], usX2Y->dev,
+								  usb_sndbulkpipe(usX2Y->dev, 0x04), &p4out->val.vol,
 								  p4out->type == eLT_Light ? sizeof(struct us428_lights) : 5,
 								  i_usX2Y_Out04Int, usX2Y);
 						err = usb_submit_urb(usX2Y->AS04.urb[j], GFP_ATOMIC);
@@ -253,7 +253,7 @@ static void i_usX2Y_In04Int(struct urb *urb)
 	if (err)
 		snd_printk(KERN_ERR "In04Int() usb_submit_urb err=%i\n", err);
 
-	urb->dev = usX2Y->chip.dev;
+	urb->dev = usX2Y->dev;
 	usb_submit_urb(urb, GFP_ATOMIC);
 }
 
@@ -273,8 +273,8 @@ int usX2Y_AsyncSeq04_init(struct usX2Ydev *usX2Y)
 				err = -ENOMEM;
 				break;
 			}
-			usb_fill_bulk_urb(	usX2Y->AS04.urb[i], usX2Y->chip.dev,
-						usb_sndbulkpipe(usX2Y->chip.dev, 0x04),
+			usb_fill_bulk_urb(	usX2Y->AS04.urb[i], usX2Y->dev,
+						usb_sndbulkpipe(usX2Y->dev, 0x04),
 						usX2Y->AS04.buffer + URB_DataLen_AsyncSeq*i, 0,
 						i_usX2Y_Out04Int, usX2Y
 				);
@@ -293,7 +293,7 @@ int usX2Y_In04_init(struct usX2Ydev *usX2Y)
 	}
 	 
 	init_waitqueue_head(&usX2Y->In04WaitQueue);
-	usb_fill_int_urb(usX2Y->In04urb, usX2Y->chip.dev, usb_rcvintpipe(usX2Y->chip.dev, 0x4),
+	usb_fill_int_urb(usX2Y->In04urb, usX2Y->dev, usb_rcvintpipe(usX2Y->dev, 0x4),
 			 usX2Y->In04Buf, 21,
 			 i_usX2Y_In04Int, usX2Y,
 			 10);
@@ -348,13 +348,12 @@ static int usX2Y_create_card(struct usb_device *device, struct snd_card **cardp)
 			      sizeof(struct usX2Ydev), &card);
 	if (err < 0)
 		return err;
-	snd_usX2Y_card_used[usX2Y(card)->chip.index = dev] = 1;
+	snd_usX2Y_card_used[usX2Y(card)->card_index = dev] = 1;
 	card->private_free = snd_usX2Y_card_private_free;
-	usX2Y(card)->chip.dev = device;
-	usX2Y(card)->chip.card = card;
+	usX2Y(card)->dev = device;
 	init_waitqueue_head(&usX2Y(card)->prepare_wait_queue);
 	mutex_init(&usX2Y(card)->prepare_mutex);
-	INIT_LIST_HEAD(&usX2Y(card)->chip.midi_list);
+	INIT_LIST_HEAD(&usX2Y(card)->midi_list);
 	strcpy(card->driver, "USB "NAME_ALLCAPS"");
 	sprintf(card->shortname, "TASCAM "NAME_ALLCAPS"");
 	sprintf(card->longname, "%s (%x:%x if %d at %03d/%03d)",
@@ -362,7 +361,7 @@ static int usX2Y_create_card(struct usb_device *device, struct snd_card **cardp)
 		le16_to_cpu(device->descriptor.idVendor),
 		le16_to_cpu(device->descriptor.idProduct),
 		0,//us428(card)->usbmidi.ifnum,
-		usX2Y(card)->chip.dev->bus->busnum, usX2Y(card)->chip.dev->devnum
+		usX2Y(card)->dev->bus->busnum, usX2Y(card)->dev->devnum
 		);
 	*cardp = card;
 	return 0;
@@ -432,8 +431,8 @@ static void snd_usX2Y_card_private_free(struct snd_card *card)
 	usb_free_urb(usX2Y(card)->In04urb);
 	if (usX2Y(card)->us428ctls_sharedmem)
 		snd_free_pages(usX2Y(card)->us428ctls_sharedmem, sizeof(*usX2Y(card)->us428ctls_sharedmem));
-	if (usX2Y(card)->chip.index >= 0  &&  usX2Y(card)->chip.index < SNDRV_CARDS)
-		snd_usX2Y_card_used[usX2Y(card)->chip.index] = 0;
+	if (usX2Y(card)->card_index >= 0  &&  usX2Y(card)->card_index < SNDRV_CARDS)
+		snd_usX2Y_card_used[usX2Y(card)->card_index] = 0;
 }
 
 /*
@@ -445,13 +444,12 @@ static void usX2Y_usb_disconnect(struct usb_device *device, void* ptr)
 		struct snd_card *card = ptr;
 		struct usX2Ydev *usX2Y = usX2Y(card);
 		struct list_head *p;
-		usX2Y->chip.shutdown = 1;
 		usX2Y->chip_status = USX2Y_STAT_CHIP_HUP;
 		usX2Y_unlinkSeq(&usX2Y->AS04);
 		usb_kill_urb(usX2Y->In04urb);
 		snd_card_disconnect(card);
 		/* release the midi resources */
-		list_for_each(p, &usX2Y->chip.midi_list) {
+		list_for_each(p, &usX2Y->midi_list) {
 			snd_usbmidi_disconnect(p);
 		}
 		if (usX2Y->us428ctls_sharedmem) 
diff --git a/sound/usb/usx2y/usbusx2y.h b/sound/usb/usx2y/usbusx2y.h
index 456b5fdbc339..1d174cea352b 100644
--- a/sound/usb/usx2y/usbusx2y.h
+++ b/sound/usb/usx2y/usbusx2y.h
@@ -22,7 +22,8 @@ struct snd_usX2Y_urbSeq {
 #include "usx2yhwdeppcm.h"
 
 struct usX2Ydev {
-	struct snd_usb_audio 	chip;
+	struct usb_device	*dev;
+	int			card_index;
 	int			stride;
 	struct urb		*In04urb;
 	void			*In04Buf;
@@ -42,6 +43,9 @@ struct usX2Ydev {
 	struct snd_usX2Y_substream	*subs[4];
 	struct snd_usX2Y_substream	* volatile  prepare_subs;
 	wait_queue_head_t	prepare_wait_queue;
+	struct list_head	midi_list;
+	struct list_head	pcm_list;
+	int			pcm_devs;
 };
 
 
diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c
index 9efd27f6b52f..74a67a85aa81 100644
--- a/sound/usb/usx2y/usbusx2yaudio.c
+++ b/sound/usb/usx2y/usbusx2yaudio.c
@@ -199,7 +199,7 @@ static int usX2Y_urb_submit(struct snd_usX2Y_substream *subs, struct urb *urb, i
 		return -ENODEV;
 	urb->start_frame = (frame + NRURBS * nr_of_packs());  // let hcd do rollover sanity checks
 	urb->hcpriv = NULL;
-	urb->dev = subs->usX2Y->chip.dev; /* we need to set this at each time */
+	urb->dev = subs->usX2Y->dev; /* we need to set this at each time */
 	if ((err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
 		snd_printk(KERN_ERR "usb_submit_urb() returned %i\n", err);
 		return err;
@@ -300,7 +300,7 @@ static void usX2Y_error_sequence(struct usX2Ydev *usX2Y,
 "Sequence Error!(hcd_frame=%i ep=%i%s;wait=%i,frame=%i).\n"
 "Most propably some urb of usb-frame %i is still missing.\n"
 "Cause could be too long delays in usb-hcd interrupt handling.\n",
-		   usb_get_current_frame_number(usX2Y->chip.dev),
+		   usb_get_current_frame_number(usX2Y->dev),
 		   subs->endpoint, usb_pipein(urb->pipe) ? "in" : "out",
 		   usX2Y->wait_iso_frame, urb->start_frame, usX2Y->wait_iso_frame);
 	usX2Y_clients_stop(usX2Y);
@@ -313,7 +313,7 @@ static void i_usX2Y_urb_complete(struct urb *urb)
 
 	if (unlikely(atomic_read(&subs->state) < state_PREPARED)) {
 		snd_printdd("hcd_frame=%i ep=%i%s status=%i start_frame=%i\n",
-			    usb_get_current_frame_number(usX2Y->chip.dev),
+			    usb_get_current_frame_number(usX2Y->dev),
 			    subs->endpoint, usb_pipein(urb->pipe) ? "in" : "out",
 			    urb->status, urb->start_frame);
 		return;
@@ -424,7 +424,7 @@ static int usX2Y_urbs_allocate(struct snd_usX2Y_substream *subs)
 	int i;
 	unsigned int pipe;
 	int is_playback = subs == subs->usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK];
-	struct usb_device *dev = subs->usX2Y->chip.dev;
+	struct usb_device *dev = subs->usX2Y->dev;
 
 	pipe = is_playback ? usb_sndisocpipe(dev, subs->endpoint) :
 			usb_rcvisocpipe(dev, subs->endpoint);
@@ -500,7 +500,7 @@ static int usX2Y_urbs_start(struct snd_usX2Y_substream *subs)
 			unsigned long pack;
 			if (0 == i)
 				atomic_set(&subs->state, state_STARTING3);
-			urb->dev = usX2Y->chip.dev;
+			urb->dev = usX2Y->dev;
 			urb->transfer_flags = URB_ISO_ASAP;
 			for (pack = 0; pack < nr_of_packs(); pack++) {
 				urb->iso_frame_desc[pack].offset = subs->maxpacksize * pack;
@@ -692,7 +692,7 @@ static int usX2Y_rate_set(struct usX2Ydev *usX2Y, int rate)
 			}
 			((char*)(usbdata + i))[0] = ra[i].c1;
 			((char*)(usbdata + i))[1] = ra[i].c2;
-			usb_fill_bulk_urb(us->urb[i], usX2Y->chip.dev, usb_sndbulkpipe(usX2Y->chip.dev, 4),
+			usb_fill_bulk_urb(us->urb[i], usX2Y->dev, usb_sndbulkpipe(usX2Y->dev, 4),
 					  usbdata + i, 2, i_usX2Y_04Int, usX2Y);
 #ifdef OLD_USB
 			us->urb[i]->transfer_flags = USB_QUEUE_BULK;
@@ -740,17 +740,17 @@ static int usX2Y_format_set(struct usX2Ydev *usX2Y, snd_pcm_format_t format)
 		alternate = 1;
 		usX2Y->stride = 4;
 	}
-	list_for_each(p, &usX2Y->chip.midi_list) {
+	list_for_each(p, &usX2Y->midi_list) {
 		snd_usbmidi_input_stop(p);
 	}
 	usb_kill_urb(usX2Y->In04urb);
-	if ((err = usb_set_interface(usX2Y->chip.dev, 0, alternate))) {
+	if ((err = usb_set_interface(usX2Y->dev, 0, alternate))) {
 		snd_printk(KERN_ERR "usb_set_interface error \n");
 		return err;
 	}
-	usX2Y->In04urb->dev = usX2Y->chip.dev;
+	usX2Y->In04urb->dev = usX2Y->dev;
 	err = usb_submit_urb(usX2Y->In04urb, GFP_KERNEL);
-	list_for_each(p, &usX2Y->chip.midi_list) {
+	list_for_each(p, &usX2Y->midi_list) {
 		snd_usbmidi_input_start(p);
 	}
 	usX2Y->format = format;
@@ -955,7 +955,7 @@ static int usX2Y_audio_stream_new(struct snd_card *card, int playback_endpoint,
 	struct snd_pcm *pcm;
 	int err, i;
 	struct snd_usX2Y_substream **usX2Y_substream =
-		usX2Y(card)->subs + 2 * usX2Y(card)->chip.pcm_devs;
+		usX2Y(card)->subs + 2 * usX2Y(card)->pcm_devs;
 
 	for (i = playback_endpoint ? SNDRV_PCM_STREAM_PLAYBACK : SNDRV_PCM_STREAM_CAPTURE;
 	     i <= SNDRV_PCM_STREAM_CAPTURE; ++i) {
@@ -971,7 +971,7 @@ static int usX2Y_audio_stream_new(struct snd_card *card, int playback_endpoint,
 		usX2Y_substream[SNDRV_PCM_STREAM_PLAYBACK]->endpoint = playback_endpoint;
 	usX2Y_substream[SNDRV_PCM_STREAM_CAPTURE]->endpoint = capture_endpoint;
 
-	err = snd_pcm_new(card, NAME_ALLCAPS" Audio", usX2Y(card)->chip.pcm_devs,
+	err = snd_pcm_new(card, NAME_ALLCAPS" Audio", usX2Y(card)->pcm_devs,
 			  playback_endpoint ? 1 : 0, 1,
 			  &pcm);
 	if (err < 0) {
@@ -987,7 +987,7 @@ static int usX2Y_audio_stream_new(struct snd_card *card, int playback_endpoint,
 	pcm->private_free = snd_usX2Y_pcm_private_free;
 	pcm->info_flags = 0;
 
-	sprintf(pcm->name, NAME_ALLCAPS" Audio #%d", usX2Y(card)->chip.pcm_devs);
+	sprintf(pcm->name, NAME_ALLCAPS" Audio #%d", usX2Y(card)->pcm_devs);
 
 	if ((playback_endpoint &&
 	     0 > (err = snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream,
@@ -1001,7 +1001,7 @@ static int usX2Y_audio_stream_new(struct snd_card *card, int playback_endpoint,
 		snd_usX2Y_pcm_private_free(pcm);
 		return err;
 	}
-	usX2Y(card)->chip.pcm_devs++;
+	usX2Y(card)->pcm_devs++;
 
 	return 0;
 }
@@ -1013,14 +1013,14 @@ int usX2Y_audio_create(struct snd_card *card)
 {
 	int err = 0;
 	
-	INIT_LIST_HEAD(&usX2Y(card)->chip.pcm_list);
+	INIT_LIST_HEAD(&usX2Y(card)->pcm_list);
 
 	if (0 > (err = usX2Y_audio_stream_new(card, 0xA, 0x8)))
 		return err;
-	if (le16_to_cpu(usX2Y(card)->chip.dev->descriptor.idProduct) == USB_ID_US428)
+	if (le16_to_cpu(usX2Y(card)->dev->descriptor.idProduct) == USB_ID_US428)
 	     if (0 > (err = usX2Y_audio_stream_new(card, 0, 0xA)))
 		     return err;
-	if (le16_to_cpu(usX2Y(card)->chip.dev->descriptor.idProduct) != USB_ID_US122)
+	if (le16_to_cpu(usX2Y(card)->dev->descriptor.idProduct) != USB_ID_US122)
 		err = usX2Y_rate_set(usX2Y(card), 44100);	// Lets us428 recognize output-volume settings, disturbs us122.
 	return err;
 }
diff --git a/sound/usb/usx2y/usx2yhwdeppcm.c b/sound/usb/usx2y/usx2yhwdeppcm.c
index 4b2304c2e02d..9ed6c3956ca7 100644
--- a/sound/usb/usx2y/usx2yhwdeppcm.c
+++ b/sound/usb/usx2y/usx2yhwdeppcm.c
@@ -234,7 +234,7 @@ static void i_usX2Y_usbpcm_urb_complete(struct urb *urb)
 
 	if (unlikely(atomic_read(&subs->state) < state_PREPARED)) {
 		snd_printdd("hcd_frame=%i ep=%i%s status=%i start_frame=%i\n",
-			    usb_get_current_frame_number(usX2Y->chip.dev),
+			    usb_get_current_frame_number(usX2Y->dev),
 			    subs->endpoint, usb_pipein(urb->pipe) ? "in" : "out",
 			    urb->status, urb->start_frame);
 		return;
@@ -318,7 +318,7 @@ static int usX2Y_usbpcm_urbs_allocate(struct snd_usX2Y_substream *subs)
 	int i;
 	unsigned int pipe;
 	int is_playback = subs == subs->usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK];
-	struct usb_device *dev = subs->usX2Y->chip.dev;
+	struct usb_device *dev = subs->usX2Y->dev;
 
 	pipe = is_playback ? usb_sndisocpipe(dev, subs->endpoint) :
 			usb_rcvisocpipe(dev, subs->endpoint);
@@ -441,7 +441,7 @@ static int usX2Y_usbpcm_urbs_start(struct snd_usX2Y_substream *subs)
 					unsigned long pack;
 					if (0 == u)
 						atomic_set(&subs->state, state_STARTING3);
-					urb->dev = usX2Y->chip.dev;
+					urb->dev = usX2Y->dev;
 					urb->transfer_flags = URB_ISO_ASAP;
 					for (pack = 0; pack < nr_of_packs(); pack++) {
 						urb->iso_frame_desc[pack].offset = subs->maxpacksize * (pack + u * nr_of_packs());
@@ -741,7 +741,7 @@ int usX2Y_hwdep_pcm_new(struct snd_card *card)
 	int err;
 	struct snd_hwdep *hw;
 	struct snd_pcm *pcm;
-	struct usb_device *dev = usX2Y(card)->chip.dev;
+	struct usb_device *dev = usX2Y(card)->dev;
 	if (1 != nr_of_packs())
 		return 0;