diff options
author | Takashi Iwai <tiwai@suse.de> | 2009-09-10 09:33:07 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2009-09-10 09:33:07 -0400 |
commit | fd30afa454282bbe1b36d5d77bd72c0ea5b3f97c (patch) | |
tree | 37557d4c96d89641eef362995322547b91b24669 | |
parent | b34c8663940dfc7da767c42b37605e5ad3ae11f7 (diff) | |
parent | f1e6d3c5cf86675e54a17a89668aa6685d2ef59d (diff) |
Merge branch 'topic/usb-audio' into for-linus
* topic/usb-audio:
ALSA: usb-audio - Fix types taken in min()
sound: usb-audio: do not make URBs longer than sync packet interval
sound: usb-audio: add MIDI drain callback
sound: usb-audio: use multiple output URBs
sound: usb-audio: use multiple input URBs
sound: usb-audio: Xonar U1 digital output support
-rw-r--r-- | sound/usb/usbaudio.c | 2 | ||||
-rw-r--r-- | sound/usb/usbmidi.c | 290 | ||||
-rw-r--r-- | sound/usb/usbmixer.c | 60 |
3 files changed, 256 insertions, 96 deletions
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index 3a53c79f48b8..8db0374e10d5 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c | |||
@@ -1083,6 +1083,8 @@ static int init_substream_urbs(struct snd_usb_substream *subs, unsigned int peri | |||
1083 | } else | 1083 | } else |
1084 | urb_packs = 1; | 1084 | urb_packs = 1; |
1085 | urb_packs *= packs_per_ms; | 1085 | urb_packs *= packs_per_ms; |
1086 | if (subs->syncpipe) | ||
1087 | urb_packs = min(urb_packs, 1U << subs->syncinterval); | ||
1086 | 1088 | ||
1087 | /* decide how many packets to be used */ | 1089 | /* decide how many packets to be used */ |
1088 | if (is_playback) { | 1090 | if (is_playback) { |
diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c index 2fb35cc22a30..0eff19ceb7e1 100644 --- a/sound/usb/usbmidi.c +++ b/sound/usb/usbmidi.c | |||
@@ -45,6 +45,7 @@ | |||
45 | #include <linux/slab.h> | 45 | #include <linux/slab.h> |
46 | #include <linux/timer.h> | 46 | #include <linux/timer.h> |
47 | #include <linux/usb.h> | 47 | #include <linux/usb.h> |
48 | #include <linux/wait.h> | ||
48 | #include <sound/core.h> | 49 | #include <sound/core.h> |
49 | #include <sound/rawmidi.h> | 50 | #include <sound/rawmidi.h> |
50 | #include <sound/asequencer.h> | 51 | #include <sound/asequencer.h> |
@@ -62,6 +63,9 @@ | |||
62 | */ | 63 | */ |
63 | #define ERROR_DELAY_JIFFIES (HZ / 10) | 64 | #define ERROR_DELAY_JIFFIES (HZ / 10) |
64 | 65 | ||
66 | #define OUTPUT_URBS 7 | ||
67 | #define INPUT_URBS 7 | ||
68 | |||
65 | 69 | ||
66 | MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); | 70 | MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); |
67 | MODULE_DESCRIPTION("USB Audio/MIDI helper module"); | 71 | MODULE_DESCRIPTION("USB Audio/MIDI helper module"); |
@@ -90,7 +94,7 @@ struct snd_usb_midi_endpoint; | |||
90 | 94 | ||
91 | struct usb_protocol_ops { | 95 | struct usb_protocol_ops { |
92 | void (*input)(struct snd_usb_midi_in_endpoint*, uint8_t*, int); | 96 | void (*input)(struct snd_usb_midi_in_endpoint*, uint8_t*, int); |
93 | void (*output)(struct snd_usb_midi_out_endpoint*); | 97 | void (*output)(struct snd_usb_midi_out_endpoint *ep, struct urb *urb); |
94 | void (*output_packet)(struct urb*, uint8_t, uint8_t, uint8_t, uint8_t); | 98 | void (*output_packet)(struct urb*, uint8_t, uint8_t, uint8_t, uint8_t); |
95 | void (*init_out_endpoint)(struct snd_usb_midi_out_endpoint*); | 99 | void (*init_out_endpoint)(struct snd_usb_midi_out_endpoint*); |
96 | void (*finish_out_endpoint)(struct snd_usb_midi_out_endpoint*); | 100 | void (*finish_out_endpoint)(struct snd_usb_midi_out_endpoint*); |
@@ -116,11 +120,15 @@ struct snd_usb_midi { | |||
116 | 120 | ||
117 | struct snd_usb_midi_out_endpoint { | 121 | struct snd_usb_midi_out_endpoint { |
118 | struct snd_usb_midi* umidi; | 122 | struct snd_usb_midi* umidi; |
119 | struct urb* urb; | 123 | struct out_urb_context { |
120 | int urb_active; | 124 | struct urb *urb; |
125 | struct snd_usb_midi_out_endpoint *ep; | ||
126 | } urbs[OUTPUT_URBS]; | ||
127 | unsigned int active_urbs; | ||
128 | unsigned int drain_urbs; | ||
121 | int max_transfer; /* size of urb buffer */ | 129 | int max_transfer; /* size of urb buffer */ |
122 | struct tasklet_struct tasklet; | 130 | struct tasklet_struct tasklet; |
123 | 131 | unsigned int next_urb; | |
124 | spinlock_t buffer_lock; | 132 | spinlock_t buffer_lock; |
125 | 133 | ||
126 | struct usbmidi_out_port { | 134 | struct usbmidi_out_port { |
@@ -139,11 +147,13 @@ struct snd_usb_midi_out_endpoint { | |||
139 | uint8_t data[2]; | 147 | uint8_t data[2]; |
140 | } ports[0x10]; | 148 | } ports[0x10]; |
141 | int current_port; | 149 | int current_port; |
150 | |||
151 | wait_queue_head_t drain_wait; | ||
142 | }; | 152 | }; |
143 | 153 | ||
144 | struct snd_usb_midi_in_endpoint { | 154 | struct snd_usb_midi_in_endpoint { |
145 | struct snd_usb_midi* umidi; | 155 | struct snd_usb_midi* umidi; |
146 | struct urb* urb; | 156 | struct urb* urbs[INPUT_URBS]; |
147 | struct usbmidi_in_port { | 157 | struct usbmidi_in_port { |
148 | struct snd_rawmidi_substream *substream; | 158 | struct snd_rawmidi_substream *substream; |
149 | u8 running_status_length; | 159 | u8 running_status_length; |
@@ -251,10 +261,17 @@ static void snd_usbmidi_in_urb_complete(struct urb* urb) | |||
251 | 261 | ||
252 | static void snd_usbmidi_out_urb_complete(struct urb* urb) | 262 | static void snd_usbmidi_out_urb_complete(struct urb* urb) |
253 | { | 263 | { |
254 | struct snd_usb_midi_out_endpoint* ep = urb->context; | 264 | struct out_urb_context *context = urb->context; |
265 | struct snd_usb_midi_out_endpoint* ep = context->ep; | ||
266 | unsigned int urb_index; | ||
255 | 267 | ||
256 | spin_lock(&ep->buffer_lock); | 268 | spin_lock(&ep->buffer_lock); |
257 | ep->urb_active = 0; | 269 | urb_index = context - ep->urbs; |
270 | ep->active_urbs &= ~(1 << urb_index); | ||
271 | if (unlikely(ep->drain_urbs)) { | ||
272 | ep->drain_urbs &= ~(1 << urb_index); | ||
273 | wake_up(&ep->drain_wait); | ||
274 | } | ||
258 | spin_unlock(&ep->buffer_lock); | 275 | spin_unlock(&ep->buffer_lock); |
259 | if (urb->status < 0) { | 276 | if (urb->status < 0) { |
260 | int err = snd_usbmidi_urb_error(urb->status); | 277 | int err = snd_usbmidi_urb_error(urb->status); |
@@ -274,24 +291,38 @@ static void snd_usbmidi_out_urb_complete(struct urb* urb) | |||
274 | */ | 291 | */ |
275 | static void snd_usbmidi_do_output(struct snd_usb_midi_out_endpoint* ep) | 292 | static void snd_usbmidi_do_output(struct snd_usb_midi_out_endpoint* ep) |
276 | { | 293 | { |
277 | struct urb* urb = ep->urb; | 294 | unsigned int urb_index; |
295 | struct urb* urb; | ||
278 | unsigned long flags; | 296 | unsigned long flags; |
279 | 297 | ||
280 | spin_lock_irqsave(&ep->buffer_lock, flags); | 298 | spin_lock_irqsave(&ep->buffer_lock, flags); |
281 | if (ep->urb_active || ep->umidi->chip->shutdown) { | 299 | if (ep->umidi->chip->shutdown) { |
282 | spin_unlock_irqrestore(&ep->buffer_lock, flags); | 300 | spin_unlock_irqrestore(&ep->buffer_lock, flags); |
283 | return; | 301 | return; |
284 | } | 302 | } |
285 | 303 | ||
286 | urb->transfer_buffer_length = 0; | 304 | urb_index = ep->next_urb; |
287 | ep->umidi->usb_protocol_ops->output(ep); | 305 | for (;;) { |
306 | if (!(ep->active_urbs & (1 << urb_index))) { | ||
307 | urb = ep->urbs[urb_index].urb; | ||
308 | urb->transfer_buffer_length = 0; | ||
309 | ep->umidi->usb_protocol_ops->output(ep, urb); | ||
310 | if (urb->transfer_buffer_length == 0) | ||
311 | break; | ||
288 | 312 | ||
289 | if (urb->transfer_buffer_length > 0) { | 313 | dump_urb("sending", urb->transfer_buffer, |
290 | dump_urb("sending", urb->transfer_buffer, | 314 | urb->transfer_buffer_length); |
291 | urb->transfer_buffer_length); | 315 | urb->dev = ep->umidi->chip->dev; |
292 | urb->dev = ep->umidi->chip->dev; | 316 | if (snd_usbmidi_submit_urb(urb, GFP_ATOMIC) < 0) |
293 | ep->urb_active = snd_usbmidi_submit_urb(urb, GFP_ATOMIC) >= 0; | 317 | break; |
318 | ep->active_urbs |= 1 << urb_index; | ||
319 | } | ||
320 | if (++urb_index >= OUTPUT_URBS) | ||
321 | urb_index = 0; | ||
322 | if (urb_index == ep->next_urb) | ||
323 | break; | ||
294 | } | 324 | } |
325 | ep->next_urb = urb_index; | ||
295 | spin_unlock_irqrestore(&ep->buffer_lock, flags); | 326 | spin_unlock_irqrestore(&ep->buffer_lock, flags); |
296 | } | 327 | } |
297 | 328 | ||
@@ -306,7 +337,7 @@ static void snd_usbmidi_out_tasklet(unsigned long data) | |||
306 | static void snd_usbmidi_error_timer(unsigned long data) | 337 | static void snd_usbmidi_error_timer(unsigned long data) |
307 | { | 338 | { |
308 | struct snd_usb_midi *umidi = (struct snd_usb_midi *)data; | 339 | struct snd_usb_midi *umidi = (struct snd_usb_midi *)data; |
309 | int i; | 340 | unsigned int i, j; |
310 | 341 | ||
311 | spin_lock(&umidi->disc_lock); | 342 | spin_lock(&umidi->disc_lock); |
312 | if (umidi->disconnected) { | 343 | if (umidi->disconnected) { |
@@ -317,8 +348,10 @@ static void snd_usbmidi_error_timer(unsigned long data) | |||
317 | struct snd_usb_midi_in_endpoint *in = umidi->endpoints[i].in; | 348 | struct snd_usb_midi_in_endpoint *in = umidi->endpoints[i].in; |
318 | if (in && in->error_resubmit) { | 349 | if (in && in->error_resubmit) { |
319 | in->error_resubmit = 0; | 350 | in->error_resubmit = 0; |
320 | in->urb->dev = umidi->chip->dev; | 351 | for (j = 0; j < INPUT_URBS; ++j) { |
321 | snd_usbmidi_submit_urb(in->urb, GFP_ATOMIC); | 352 | in->urbs[j]->dev = umidi->chip->dev; |
353 | snd_usbmidi_submit_urb(in->urbs[j], GFP_ATOMIC); | ||
354 | } | ||
322 | } | 355 | } |
323 | if (umidi->endpoints[i].out) | 356 | if (umidi->endpoints[i].out) |
324 | snd_usbmidi_do_output(umidi->endpoints[i].out); | 357 | snd_usbmidi_do_output(umidi->endpoints[i].out); |
@@ -330,13 +363,14 @@ static void snd_usbmidi_error_timer(unsigned long data) | |||
330 | static int send_bulk_static_data(struct snd_usb_midi_out_endpoint* ep, | 363 | static int send_bulk_static_data(struct snd_usb_midi_out_endpoint* ep, |
331 | const void *data, int len) | 364 | const void *data, int len) |
332 | { | 365 | { |
333 | int err; | 366 | int err = 0; |
334 | void *buf = kmemdup(data, len, GFP_KERNEL); | 367 | void *buf = kmemdup(data, len, GFP_KERNEL); |
335 | if (!buf) | 368 | if (!buf) |
336 | return -ENOMEM; | 369 | return -ENOMEM; |
337 | dump_urb("sending", buf, len); | 370 | dump_urb("sending", buf, len); |
338 | err = usb_bulk_msg(ep->umidi->chip->dev, ep->urb->pipe, buf, len, | 371 | if (ep->urbs[0].urb) |
339 | NULL, 250); | 372 | err = usb_bulk_msg(ep->umidi->chip->dev, ep->urbs[0].urb->pipe, |
373 | buf, len, NULL, 250); | ||
340 | kfree(buf); | 374 | kfree(buf); |
341 | return err; | 375 | return err; |
342 | } | 376 | } |
@@ -554,9 +588,9 @@ static void snd_usbmidi_transmit_byte(struct usbmidi_out_port* port, | |||
554 | } | 588 | } |
555 | } | 589 | } |
556 | 590 | ||
557 | static void snd_usbmidi_standard_output(struct snd_usb_midi_out_endpoint* ep) | 591 | static void snd_usbmidi_standard_output(struct snd_usb_midi_out_endpoint* ep, |
592 | struct urb *urb) | ||
558 | { | 593 | { |
559 | struct urb* urb = ep->urb; | ||
560 | int p; | 594 | int p; |
561 | 595 | ||
562 | /* FIXME: lower-numbered ports can starve higher-numbered ports */ | 596 | /* FIXME: lower-numbered ports can starve higher-numbered ports */ |
@@ -613,14 +647,15 @@ static void snd_usbmidi_novation_input(struct snd_usb_midi_in_endpoint* ep, | |||
613 | snd_usbmidi_input_data(ep, 0, &buffer[2], buffer[0] - 1); | 647 | snd_usbmidi_input_data(ep, 0, &buffer[2], buffer[0] - 1); |
614 | } | 648 | } |
615 | 649 | ||
616 | static void snd_usbmidi_novation_output(struct snd_usb_midi_out_endpoint* ep) | 650 | static void snd_usbmidi_novation_output(struct snd_usb_midi_out_endpoint* ep, |
651 | struct urb *urb) | ||
617 | { | 652 | { |
618 | uint8_t* transfer_buffer; | 653 | uint8_t* transfer_buffer; |
619 | int count; | 654 | int count; |
620 | 655 | ||
621 | if (!ep->ports[0].active) | 656 | if (!ep->ports[0].active) |
622 | return; | 657 | return; |
623 | transfer_buffer = ep->urb->transfer_buffer; | 658 | transfer_buffer = urb->transfer_buffer; |
624 | count = snd_rawmidi_transmit(ep->ports[0].substream, | 659 | count = snd_rawmidi_transmit(ep->ports[0].substream, |
625 | &transfer_buffer[2], | 660 | &transfer_buffer[2], |
626 | ep->max_transfer - 2); | 661 | ep->max_transfer - 2); |
@@ -630,7 +665,7 @@ static void snd_usbmidi_novation_output(struct snd_usb_midi_out_endpoint* ep) | |||
630 | } | 665 | } |
631 | transfer_buffer[0] = 0; | 666 | transfer_buffer[0] = 0; |
632 | transfer_buffer[1] = count; | 667 | transfer_buffer[1] = count; |
633 | ep->urb->transfer_buffer_length = 2 + count; | 668 | urb->transfer_buffer_length = 2 + count; |
634 | } | 669 | } |
635 | 670 | ||
636 | static struct usb_protocol_ops snd_usbmidi_novation_ops = { | 671 | static struct usb_protocol_ops snd_usbmidi_novation_ops = { |
@@ -648,20 +683,21 @@ static void snd_usbmidi_raw_input(struct snd_usb_midi_in_endpoint* ep, | |||
648 | snd_usbmidi_input_data(ep, 0, buffer, buffer_length); | 683 | snd_usbmidi_input_data(ep, 0, buffer, buffer_length); |
649 | } | 684 | } |
650 | 685 | ||
651 | static void snd_usbmidi_raw_output(struct snd_usb_midi_out_endpoint* ep) | 686 | static void snd_usbmidi_raw_output(struct snd_usb_midi_out_endpoint* ep, |
687 | struct urb *urb) | ||
652 | { | 688 | { |
653 | int count; | 689 | int count; |
654 | 690 | ||
655 | if (!ep->ports[0].active) | 691 | if (!ep->ports[0].active) |
656 | return; | 692 | return; |
657 | count = snd_rawmidi_transmit(ep->ports[0].substream, | 693 | count = snd_rawmidi_transmit(ep->ports[0].substream, |
658 | ep->urb->transfer_buffer, | 694 | urb->transfer_buffer, |
659 | ep->max_transfer); | 695 | ep->max_transfer); |
660 | if (count < 1) { | 696 | if (count < 1) { |
661 | ep->ports[0].active = 0; | 697 | ep->ports[0].active = 0; |
662 | return; | 698 | return; |
663 | } | 699 | } |
664 | ep->urb->transfer_buffer_length = count; | 700 | urb->transfer_buffer_length = count; |
665 | } | 701 | } |
666 | 702 | ||
667 | static struct usb_protocol_ops snd_usbmidi_raw_ops = { | 703 | static struct usb_protocol_ops snd_usbmidi_raw_ops = { |
@@ -681,23 +717,25 @@ static void snd_usbmidi_us122l_input(struct snd_usb_midi_in_endpoint *ep, | |||
681 | snd_usbmidi_input_data(ep, 0, buffer, buffer_length); | 717 | snd_usbmidi_input_data(ep, 0, buffer, buffer_length); |
682 | } | 718 | } |
683 | 719 | ||
684 | static void snd_usbmidi_us122l_output(struct snd_usb_midi_out_endpoint *ep) | 720 | static void snd_usbmidi_us122l_output(struct snd_usb_midi_out_endpoint *ep, |
721 | struct urb *urb) | ||
685 | { | 722 | { |
686 | int count; | 723 | int count; |
687 | 724 | ||
688 | if (!ep->ports[0].active) | 725 | if (!ep->ports[0].active) |
689 | return; | 726 | return; |
690 | count = ep->urb->dev->speed == USB_SPEED_HIGH ? 1 : 2; | 727 | count = snd_usb_get_speed(ep->umidi->chip->dev) == USB_SPEED_HIGH |
728 | ? 1 : 2; | ||
691 | count = snd_rawmidi_transmit(ep->ports[0].substream, | 729 | count = snd_rawmidi_transmit(ep->ports[0].substream, |
692 | ep->urb->transfer_buffer, | 730 | urb->transfer_buffer, |
693 | count); | 731 | count); |
694 | if (count < 1) { | 732 | if (count < 1) { |
695 | ep->ports[0].active = 0; | 733 | ep->ports[0].active = 0; |
696 | return; | 734 | return; |
697 | } | 735 | } |
698 | 736 | ||
699 | memset(ep->urb->transfer_buffer + count, 0xFD, 9 - count); | 737 | memset(urb->transfer_buffer + count, 0xFD, 9 - count); |
700 | ep->urb->transfer_buffer_length = count; | 738 | urb->transfer_buffer_length = count; |
701 | } | 739 | } |
702 | 740 | ||
703 | static struct usb_protocol_ops snd_usbmidi_122l_ops = { | 741 | static struct usb_protocol_ops snd_usbmidi_122l_ops = { |
@@ -786,10 +824,11 @@ static void snd_usbmidi_emagic_input(struct snd_usb_midi_in_endpoint* ep, | |||
786 | } | 824 | } |
787 | } | 825 | } |
788 | 826 | ||
789 | static void snd_usbmidi_emagic_output(struct snd_usb_midi_out_endpoint* ep) | 827 | static void snd_usbmidi_emagic_output(struct snd_usb_midi_out_endpoint* ep, |
828 | struct urb *urb) | ||
790 | { | 829 | { |
791 | int port0 = ep->current_port; | 830 | int port0 = ep->current_port; |
792 | uint8_t* buf = ep->urb->transfer_buffer; | 831 | uint8_t* buf = urb->transfer_buffer; |
793 | int buf_free = ep->max_transfer; | 832 | int buf_free = ep->max_transfer; |
794 | int length, i; | 833 | int length, i; |
795 | 834 | ||
@@ -829,7 +868,7 @@ static void snd_usbmidi_emagic_output(struct snd_usb_midi_out_endpoint* ep) | |||
829 | *buf = 0xff; | 868 | *buf = 0xff; |
830 | --buf_free; | 869 | --buf_free; |
831 | } | 870 | } |
832 | ep->urb->transfer_buffer_length = ep->max_transfer - buf_free; | 871 | urb->transfer_buffer_length = ep->max_transfer - buf_free; |
833 | } | 872 | } |
834 | 873 | ||
835 | static struct usb_protocol_ops snd_usbmidi_emagic_ops = { | 874 | static struct usb_protocol_ops snd_usbmidi_emagic_ops = { |
@@ -884,6 +923,35 @@ static void snd_usbmidi_output_trigger(struct snd_rawmidi_substream *substream, | |||
884 | } | 923 | } |
885 | } | 924 | } |
886 | 925 | ||
926 | static void snd_usbmidi_output_drain(struct snd_rawmidi_substream *substream) | ||
927 | { | ||
928 | struct usbmidi_out_port* port = substream->runtime->private_data; | ||
929 | struct snd_usb_midi_out_endpoint *ep = port->ep; | ||
930 | unsigned int drain_urbs; | ||
931 | DEFINE_WAIT(wait); | ||
932 | long timeout = msecs_to_jiffies(50); | ||
933 | |||
934 | /* | ||
935 | * The substream buffer is empty, but some data might still be in the | ||
936 | * currently active URBs, so we have to wait for those to complete. | ||
937 | */ | ||
938 | spin_lock_irq(&ep->buffer_lock); | ||
939 | drain_urbs = ep->active_urbs; | ||
940 | if (drain_urbs) { | ||
941 | ep->drain_urbs |= drain_urbs; | ||
942 | do { | ||
943 | prepare_to_wait(&ep->drain_wait, &wait, | ||
944 | TASK_UNINTERRUPTIBLE); | ||
945 | spin_unlock_irq(&ep->buffer_lock); | ||
946 | timeout = schedule_timeout(timeout); | ||
947 | spin_lock_irq(&ep->buffer_lock); | ||
948 | drain_urbs &= ep->drain_urbs; | ||
949 | } while (drain_urbs && timeout); | ||
950 | finish_wait(&ep->drain_wait, &wait); | ||
951 | } | ||
952 | spin_unlock_irq(&ep->buffer_lock); | ||
953 | } | ||
954 | |||
887 | static int snd_usbmidi_input_open(struct snd_rawmidi_substream *substream) | 955 | static int snd_usbmidi_input_open(struct snd_rawmidi_substream *substream) |
888 | { | 956 | { |
889 | return 0; | 957 | return 0; |
@@ -908,6 +976,7 @@ static struct snd_rawmidi_ops snd_usbmidi_output_ops = { | |||
908 | .open = snd_usbmidi_output_open, | 976 | .open = snd_usbmidi_output_open, |
909 | .close = snd_usbmidi_output_close, | 977 | .close = snd_usbmidi_output_close, |
910 | .trigger = snd_usbmidi_output_trigger, | 978 | .trigger = snd_usbmidi_output_trigger, |
979 | .drain = snd_usbmidi_output_drain, | ||
911 | }; | 980 | }; |
912 | 981 | ||
913 | static struct snd_rawmidi_ops snd_usbmidi_input_ops = { | 982 | static struct snd_rawmidi_ops snd_usbmidi_input_ops = { |
@@ -916,19 +985,26 @@ static struct snd_rawmidi_ops snd_usbmidi_input_ops = { | |||
916 | .trigger = snd_usbmidi_input_trigger | 985 | .trigger = snd_usbmidi_input_trigger |
917 | }; | 986 | }; |
918 | 987 | ||
988 | static void free_urb_and_buffer(struct snd_usb_midi *umidi, struct urb *urb, | ||
989 | unsigned int buffer_length) | ||
990 | { | ||
991 | usb_buffer_free(umidi->chip->dev, buffer_length, | ||
992 | urb->transfer_buffer, urb->transfer_dma); | ||
993 | usb_free_urb(urb); | ||
994 | } | ||
995 | |||
919 | /* | 996 | /* |
920 | * Frees an input endpoint. | 997 | * Frees an input endpoint. |
921 | * May be called when ep hasn't been initialized completely. | 998 | * May be called when ep hasn't been initialized completely. |
922 | */ | 999 | */ |
923 | static void snd_usbmidi_in_endpoint_delete(struct snd_usb_midi_in_endpoint* ep) | 1000 | static void snd_usbmidi_in_endpoint_delete(struct snd_usb_midi_in_endpoint* ep) |
924 | { | 1001 | { |
925 | if (ep->urb) { | 1002 | unsigned int i; |
926 | usb_buffer_free(ep->umidi->chip->dev, | 1003 | |
927 | ep->urb->transfer_buffer_length, | 1004 | for (i = 0; i < INPUT_URBS; ++i) |
928 | ep->urb->transfer_buffer, | 1005 | if (ep->urbs[i]) |
929 | ep->urb->transfer_dma); | 1006 | free_urb_and_buffer(ep->umidi, ep->urbs[i], |
930 | usb_free_urb(ep->urb); | 1007 | ep->urbs[i]->transfer_buffer_length); |
931 | } | ||
932 | kfree(ep); | 1008 | kfree(ep); |
933 | } | 1009 | } |
934 | 1010 | ||
@@ -943,6 +1019,7 @@ static int snd_usbmidi_in_endpoint_create(struct snd_usb_midi* umidi, | |||
943 | void* buffer; | 1019 | void* buffer; |
944 | unsigned int pipe; | 1020 | unsigned int pipe; |
945 | int length; | 1021 | int length; |
1022 | unsigned int i; | ||
946 | 1023 | ||
947 | rep->in = NULL; | 1024 | rep->in = NULL; |
948 | ep = kzalloc(sizeof(*ep), GFP_KERNEL); | 1025 | ep = kzalloc(sizeof(*ep), GFP_KERNEL); |
@@ -950,30 +1027,36 @@ static int snd_usbmidi_in_endpoint_create(struct snd_usb_midi* umidi, | |||
950 | return -ENOMEM; | 1027 | return -ENOMEM; |
951 | ep->umidi = umidi; | 1028 | ep->umidi = umidi; |
952 | 1029 | ||
953 | ep->urb = usb_alloc_urb(0, GFP_KERNEL); | 1030 | for (i = 0; i < INPUT_URBS; ++i) { |
954 | if (!ep->urb) { | 1031 | ep->urbs[i] = usb_alloc_urb(0, GFP_KERNEL); |
955 | snd_usbmidi_in_endpoint_delete(ep); | 1032 | if (!ep->urbs[i]) { |
956 | return -ENOMEM; | 1033 | snd_usbmidi_in_endpoint_delete(ep); |
1034 | return -ENOMEM; | ||
1035 | } | ||
957 | } | 1036 | } |
958 | if (ep_info->in_interval) | 1037 | if (ep_info->in_interval) |
959 | pipe = usb_rcvintpipe(umidi->chip->dev, ep_info->in_ep); | 1038 | pipe = usb_rcvintpipe(umidi->chip->dev, ep_info->in_ep); |
960 | else | 1039 | else |
961 | pipe = usb_rcvbulkpipe(umidi->chip->dev, ep_info->in_ep); | 1040 | pipe = usb_rcvbulkpipe(umidi->chip->dev, ep_info->in_ep); |
962 | length = usb_maxpacket(umidi->chip->dev, pipe, 0); | 1041 | length = usb_maxpacket(umidi->chip->dev, pipe, 0); |
963 | buffer = usb_buffer_alloc(umidi->chip->dev, length, GFP_KERNEL, | 1042 | for (i = 0; i < INPUT_URBS; ++i) { |
964 | &ep->urb->transfer_dma); | 1043 | buffer = usb_buffer_alloc(umidi->chip->dev, length, GFP_KERNEL, |
965 | if (!buffer) { | 1044 | &ep->urbs[i]->transfer_dma); |
966 | snd_usbmidi_in_endpoint_delete(ep); | 1045 | if (!buffer) { |
967 | return -ENOMEM; | 1046 | snd_usbmidi_in_endpoint_delete(ep); |
1047 | return -ENOMEM; | ||
1048 | } | ||
1049 | if (ep_info->in_interval) | ||
1050 | usb_fill_int_urb(ep->urbs[i], umidi->chip->dev, | ||
1051 | pipe, buffer, length, | ||
1052 | snd_usbmidi_in_urb_complete, | ||
1053 | ep, ep_info->in_interval); | ||
1054 | else | ||
1055 | usb_fill_bulk_urb(ep->urbs[i], umidi->chip->dev, | ||
1056 | pipe, buffer, length, | ||
1057 | snd_usbmidi_in_urb_complete, ep); | ||
1058 | ep->urbs[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP; | ||
968 | } | 1059 | } |
969 | if (ep_info->in_interval) | ||
970 | usb_fill_int_urb(ep->urb, umidi->chip->dev, pipe, buffer, | ||
971 | length, snd_usbmidi_in_urb_complete, ep, | ||
972 | ep_info->in_interval); | ||
973 | else | ||
974 | usb_fill_bulk_urb(ep->urb, umidi->chip->dev, pipe, buffer, | ||
975 | length, snd_usbmidi_in_urb_complete, ep); | ||
976 | ep->urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; | ||
977 | 1060 | ||
978 | rep->in = ep; | 1061 | rep->in = ep; |
979 | return 0; | 1062 | return 0; |
@@ -994,12 +1077,12 @@ static unsigned int snd_usbmidi_count_bits(unsigned int x) | |||
994 | */ | 1077 | */ |
995 | static void snd_usbmidi_out_endpoint_delete(struct snd_usb_midi_out_endpoint* ep) | 1078 | static void snd_usbmidi_out_endpoint_delete(struct snd_usb_midi_out_endpoint* ep) |
996 | { | 1079 | { |
997 | if (ep->urb) { | 1080 | unsigned int i; |
998 | usb_buffer_free(ep->umidi->chip->dev, ep->max_transfer, | 1081 | |
999 | ep->urb->transfer_buffer, | 1082 | for (i = 0; i < OUTPUT_URBS; ++i) |
1000 | ep->urb->transfer_dma); | 1083 | if (ep->urbs[i].urb) |
1001 | usb_free_urb(ep->urb); | 1084 | free_urb_and_buffer(ep->umidi, ep->urbs[i].urb, |
1002 | } | 1085 | ep->max_transfer); |
1003 | kfree(ep); | 1086 | kfree(ep); |
1004 | } | 1087 | } |
1005 | 1088 | ||
@@ -1011,7 +1094,7 @@ static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi* umidi, | |||
1011 | struct snd_usb_midi_endpoint* rep) | 1094 | struct snd_usb_midi_endpoint* rep) |
1012 | { | 1095 | { |
1013 | struct snd_usb_midi_out_endpoint* ep; | 1096 | struct snd_usb_midi_out_endpoint* ep; |
1014 | int i; | 1097 | unsigned int i; |
1015 | unsigned int pipe; | 1098 | unsigned int pipe; |
1016 | void* buffer; | 1099 | void* buffer; |
1017 | 1100 | ||
@@ -1021,38 +1104,46 @@ static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi* umidi, | |||
1021 | return -ENOMEM; | 1104 | return -ENOMEM; |
1022 | ep->umidi = umidi; | 1105 | ep->umidi = umidi; |
1023 | 1106 | ||
1024 | ep->urb = usb_alloc_urb(0, GFP_KERNEL); | 1107 | for (i = 0; i < OUTPUT_URBS; ++i) { |
1025 | if (!ep->urb) { | 1108 | ep->urbs[i].urb = usb_alloc_urb(0, GFP_KERNEL); |
1026 | snd_usbmidi_out_endpoint_delete(ep); | 1109 | if (!ep->urbs[i].urb) { |
1027 | return -ENOMEM; | 1110 | snd_usbmidi_out_endpoint_delete(ep); |
1111 | return -ENOMEM; | ||
1112 | } | ||
1113 | ep->urbs[i].ep = ep; | ||
1028 | } | 1114 | } |
1029 | if (ep_info->out_interval) | 1115 | if (ep_info->out_interval) |
1030 | pipe = usb_sndintpipe(umidi->chip->dev, ep_info->out_ep); | 1116 | pipe = usb_sndintpipe(umidi->chip->dev, ep_info->out_ep); |
1031 | else | 1117 | else |
1032 | pipe = usb_sndbulkpipe(umidi->chip->dev, ep_info->out_ep); | 1118 | pipe = usb_sndbulkpipe(umidi->chip->dev, ep_info->out_ep); |
1033 | if (umidi->chip->usb_id == USB_ID(0x0a92, 0x1020)) /* ESI M4U */ | 1119 | if (umidi->chip->usb_id == USB_ID(0x0a92, 0x1020)) /* ESI M4U */ |
1034 | /* FIXME: we need more URBs to get reasonable bandwidth here: */ | ||
1035 | ep->max_transfer = 4; | 1120 | ep->max_transfer = 4; |
1036 | else | 1121 | else |
1037 | ep->max_transfer = usb_maxpacket(umidi->chip->dev, pipe, 1); | 1122 | ep->max_transfer = usb_maxpacket(umidi->chip->dev, pipe, 1); |
1038 | buffer = usb_buffer_alloc(umidi->chip->dev, ep->max_transfer, | 1123 | for (i = 0; i < OUTPUT_URBS; ++i) { |
1039 | GFP_KERNEL, &ep->urb->transfer_dma); | 1124 | buffer = usb_buffer_alloc(umidi->chip->dev, |
1040 | if (!buffer) { | 1125 | ep->max_transfer, GFP_KERNEL, |
1041 | snd_usbmidi_out_endpoint_delete(ep); | 1126 | &ep->urbs[i].urb->transfer_dma); |
1042 | return -ENOMEM; | 1127 | if (!buffer) { |
1128 | snd_usbmidi_out_endpoint_delete(ep); | ||
1129 | return -ENOMEM; | ||
1130 | } | ||
1131 | if (ep_info->out_interval) | ||
1132 | usb_fill_int_urb(ep->urbs[i].urb, umidi->chip->dev, | ||
1133 | pipe, buffer, ep->max_transfer, | ||
1134 | snd_usbmidi_out_urb_complete, | ||
1135 | &ep->urbs[i], ep_info->out_interval); | ||
1136 | else | ||
1137 | usb_fill_bulk_urb(ep->urbs[i].urb, umidi->chip->dev, | ||
1138 | pipe, buffer, ep->max_transfer, | ||
1139 | snd_usbmidi_out_urb_complete, | ||
1140 | &ep->urbs[i]); | ||
1141 | ep->urbs[i].urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; | ||
1043 | } | 1142 | } |
1044 | if (ep_info->out_interval) | ||
1045 | usb_fill_int_urb(ep->urb, umidi->chip->dev, pipe, buffer, | ||
1046 | ep->max_transfer, snd_usbmidi_out_urb_complete, | ||
1047 | ep, ep_info->out_interval); | ||
1048 | else | ||
1049 | usb_fill_bulk_urb(ep->urb, umidi->chip->dev, | ||
1050 | pipe, buffer, ep->max_transfer, | ||
1051 | snd_usbmidi_out_urb_complete, ep); | ||
1052 | ep->urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; | ||
1053 | 1143 | ||
1054 | spin_lock_init(&ep->buffer_lock); | 1144 | spin_lock_init(&ep->buffer_lock); |
1055 | tasklet_init(&ep->tasklet, snd_usbmidi_out_tasklet, (unsigned long)ep); | 1145 | tasklet_init(&ep->tasklet, snd_usbmidi_out_tasklet, (unsigned long)ep); |
1146 | init_waitqueue_head(&ep->drain_wait); | ||
1056 | 1147 | ||
1057 | for (i = 0; i < 0x10; ++i) | 1148 | for (i = 0; i < 0x10; ++i) |
1058 | if (ep_info->out_cables & (1 << i)) { | 1149 | if (ep_info->out_cables & (1 << i)) { |
@@ -1090,7 +1181,7 @@ static void snd_usbmidi_free(struct snd_usb_midi* umidi) | |||
1090 | void snd_usbmidi_disconnect(struct list_head* p) | 1181 | void snd_usbmidi_disconnect(struct list_head* p) |
1091 | { | 1182 | { |
1092 | struct snd_usb_midi* umidi; | 1183 | struct snd_usb_midi* umidi; |
1093 | int i; | 1184 | unsigned int i, j; |
1094 | 1185 | ||
1095 | umidi = list_entry(p, struct snd_usb_midi, list); | 1186 | umidi = list_entry(p, struct snd_usb_midi, list); |
1096 | /* | 1187 | /* |
@@ -1105,13 +1196,15 @@ void snd_usbmidi_disconnect(struct list_head* p) | |||
1105 | struct snd_usb_midi_endpoint* ep = &umidi->endpoints[i]; | 1196 | struct snd_usb_midi_endpoint* ep = &umidi->endpoints[i]; |
1106 | if (ep->out) | 1197 | if (ep->out) |
1107 | tasklet_kill(&ep->out->tasklet); | 1198 | tasklet_kill(&ep->out->tasklet); |
1108 | if (ep->out && ep->out->urb) { | 1199 | if (ep->out) { |
1109 | usb_kill_urb(ep->out->urb); | 1200 | for (j = 0; j < OUTPUT_URBS; ++j) |
1201 | usb_kill_urb(ep->out->urbs[j].urb); | ||
1110 | if (umidi->usb_protocol_ops->finish_out_endpoint) | 1202 | if (umidi->usb_protocol_ops->finish_out_endpoint) |
1111 | umidi->usb_protocol_ops->finish_out_endpoint(ep->out); | 1203 | umidi->usb_protocol_ops->finish_out_endpoint(ep->out); |
1112 | } | 1204 | } |
1113 | if (ep->in) | 1205 | if (ep->in) |
1114 | usb_kill_urb(ep->in->urb); | 1206 | for (j = 0; j < INPUT_URBS; ++j) |
1207 | usb_kill_urb(ep->in->urbs[j]); | ||
1115 | /* free endpoints here; later call can result in Oops */ | 1208 | /* free endpoints here; later call can result in Oops */ |
1116 | if (ep->out) { | 1209 | if (ep->out) { |
1117 | snd_usbmidi_out_endpoint_delete(ep->out); | 1210 | snd_usbmidi_out_endpoint_delete(ep->out); |
@@ -1692,20 +1785,25 @@ static int snd_usbmidi_create_rawmidi(struct snd_usb_midi* umidi, | |||
1692 | void snd_usbmidi_input_stop(struct list_head* p) | 1785 | void snd_usbmidi_input_stop(struct list_head* p) |
1693 | { | 1786 | { |
1694 | struct snd_usb_midi* umidi; | 1787 | struct snd_usb_midi* umidi; |
1695 | int i; | 1788 | unsigned int i, j; |
1696 | 1789 | ||
1697 | umidi = list_entry(p, struct snd_usb_midi, list); | 1790 | umidi = list_entry(p, struct snd_usb_midi, list); |
1698 | for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) { | 1791 | for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) { |
1699 | struct snd_usb_midi_endpoint* ep = &umidi->endpoints[i]; | 1792 | struct snd_usb_midi_endpoint* ep = &umidi->endpoints[i]; |
1700 | if (ep->in) | 1793 | if (ep->in) |
1701 | usb_kill_urb(ep->in->urb); | 1794 | for (j = 0; j < INPUT_URBS; ++j) |
1795 | usb_kill_urb(ep->in->urbs[j]); | ||
1702 | } | 1796 | } |
1703 | } | 1797 | } |
1704 | 1798 | ||
1705 | static void snd_usbmidi_input_start_ep(struct snd_usb_midi_in_endpoint* ep) | 1799 | static void snd_usbmidi_input_start_ep(struct snd_usb_midi_in_endpoint* ep) |
1706 | { | 1800 | { |
1707 | if (ep) { | 1801 | unsigned int i; |
1708 | struct urb* urb = ep->urb; | 1802 | |
1803 | if (!ep) | ||
1804 | return; | ||
1805 | for (i = 0; i < INPUT_URBS; ++i) { | ||
1806 | struct urb* urb = ep->urbs[i]; | ||
1709 | urb->dev = ep->umidi->chip->dev; | 1807 | urb->dev = ep->umidi->chip->dev; |
1710 | snd_usbmidi_submit_urb(urb, GFP_KERNEL); | 1808 | snd_usbmidi_submit_urb(urb, GFP_KERNEL); |
1711 | } | 1809 | } |
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c index df8969188d15..ab5a3ac2ac47 100644 --- a/sound/usb/usbmixer.c +++ b/sound/usb/usbmixer.c | |||
@@ -86,6 +86,7 @@ struct usb_mixer_interface { | |||
86 | u8 rc_buffer[6]; | 86 | u8 rc_buffer[6]; |
87 | 87 | ||
88 | u8 audigy2nx_leds[3]; | 88 | u8 audigy2nx_leds[3]; |
89 | u8 xonar_u1_status; | ||
89 | }; | 90 | }; |
90 | 91 | ||
91 | 92 | ||
@@ -2042,6 +2043,58 @@ static void snd_audigy2nx_proc_read(struct snd_info_entry *entry, | |||
2042 | } | 2043 | } |
2043 | } | 2044 | } |
2044 | 2045 | ||
2046 | static int snd_xonar_u1_switch_get(struct snd_kcontrol *kcontrol, | ||
2047 | struct snd_ctl_elem_value *ucontrol) | ||
2048 | { | ||
2049 | struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol); | ||
2050 | |||
2051 | ucontrol->value.integer.value[0] = !!(mixer->xonar_u1_status & 0x02); | ||
2052 | return 0; | ||
2053 | } | ||
2054 | |||
2055 | static int snd_xonar_u1_switch_put(struct snd_kcontrol *kcontrol, | ||
2056 | struct snd_ctl_elem_value *ucontrol) | ||
2057 | { | ||
2058 | struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol); | ||
2059 | u8 old_status, new_status; | ||
2060 | int err, changed; | ||
2061 | |||
2062 | old_status = mixer->xonar_u1_status; | ||
2063 | if (ucontrol->value.integer.value[0]) | ||
2064 | new_status = old_status | 0x02; | ||
2065 | else | ||
2066 | new_status = old_status & ~0x02; | ||
2067 | changed = new_status != old_status; | ||
2068 | err = snd_usb_ctl_msg(mixer->chip->dev, | ||
2069 | usb_sndctrlpipe(mixer->chip->dev, 0), 0x08, | ||
2070 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, | ||
2071 | 50, 0, &new_status, 1, 100); | ||
2072 | if (err < 0) | ||
2073 | return err; | ||
2074 | mixer->xonar_u1_status = new_status; | ||
2075 | return changed; | ||
2076 | } | ||
2077 | |||
2078 | static struct snd_kcontrol_new snd_xonar_u1_output_switch = { | ||
2079 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2080 | .name = "Digital Playback Switch", | ||
2081 | .info = snd_ctl_boolean_mono_info, | ||
2082 | .get = snd_xonar_u1_switch_get, | ||
2083 | .put = snd_xonar_u1_switch_put, | ||
2084 | }; | ||
2085 | |||
2086 | static int snd_xonar_u1_controls_create(struct usb_mixer_interface *mixer) | ||
2087 | { | ||
2088 | int err; | ||
2089 | |||
2090 | err = snd_ctl_add(mixer->chip->card, | ||
2091 | snd_ctl_new1(&snd_xonar_u1_output_switch, mixer)); | ||
2092 | if (err < 0) | ||
2093 | return err; | ||
2094 | mixer->xonar_u1_status = 0x05; | ||
2095 | return 0; | ||
2096 | } | ||
2097 | |||
2045 | int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif, | 2098 | int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif, |
2046 | int ignore_error) | 2099 | int ignore_error) |
2047 | { | 2100 | { |
@@ -2084,6 +2137,13 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif, | |||
2084 | snd_audigy2nx_proc_read); | 2137 | snd_audigy2nx_proc_read); |
2085 | } | 2138 | } |
2086 | 2139 | ||
2140 | if (mixer->chip->usb_id == USB_ID(0x0b05, 0x1739) || | ||
2141 | mixer->chip->usb_id == USB_ID(0x0b05, 0x1743)) { | ||
2142 | err = snd_xonar_u1_controls_create(mixer); | ||
2143 | if (err < 0) | ||
2144 | goto _error; | ||
2145 | } | ||
2146 | |||
2087 | err = snd_device_new(chip->card, SNDRV_DEV_LOWLEVEL, mixer, &dev_ops); | 2147 | err = snd_device_new(chip->card, SNDRV_DEV_LOWLEVEL, mixer, &dev_ops); |
2088 | if (err < 0) | 2148 | if (err < 0) |
2089 | goto _error; | 2149 | goto _error; |