diff options
author | Clemens Ladisch <clemens@ladisch.de> | 2013-02-03 16:31:20 -0500 |
---|---|---|
committer | Clemens Ladisch <clemens@ladisch.de> | 2013-06-27 15:59:47 -0400 |
commit | ba7c2be114243fa4cfcbc66a81db18e1d55abf4b (patch) | |
tree | 0452886296dc4564d4ca7cd5105231d74e97d88a /sound/usb | |
parent | 8f898e92aea2c24c7f379ee265d178f69ebb9c07 (diff) |
ALSA: usb-audio: detect implicit feedback on Roland devices
All the Roland/Edirol/BOSS USB audio devices that need implicit feedback
show this unambiguously in their descriptors, so it might be a good idea
to let the driver detect this.
This should make playback work correctly (at least with Jack) with the
following devices:
- BOSS GT-100
- BOSS JS-8 Jam Station
- Edirol M-16DX
- Roland GAIA SH-01
Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Diffstat (limited to 'sound/usb')
-rw-r--r-- | sound/usb/pcm.c | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 776c58c7cba0..15b151ed4899 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c | |||
@@ -298,6 +298,35 @@ static int deactivate_endpoints(struct snd_usb_substream *subs) | |||
298 | return 0; | 298 | return 0; |
299 | } | 299 | } |
300 | 300 | ||
301 | static int search_roland_implicit_fb(struct usb_device *dev, int ifnum, | ||
302 | unsigned int altsetting, | ||
303 | struct usb_host_interface **alts, | ||
304 | unsigned int *ep) | ||
305 | { | ||
306 | struct usb_interface *iface; | ||
307 | struct usb_interface_descriptor *altsd; | ||
308 | struct usb_endpoint_descriptor *epd; | ||
309 | |||
310 | iface = usb_ifnum_to_if(dev, ifnum); | ||
311 | if (!iface || iface->num_altsetting < altsetting + 1) | ||
312 | return -ENOENT; | ||
313 | *alts = &iface->altsetting[altsetting]; | ||
314 | altsd = get_iface_desc(*alts); | ||
315 | if (altsd->bAlternateSetting != altsetting || | ||
316 | altsd->bInterfaceClass != USB_CLASS_VENDOR_SPEC || | ||
317 | (altsd->bInterfaceSubClass != 2 && | ||
318 | altsd->bInterfaceProtocol != 2 ) || | ||
319 | altsd->bNumEndpoints < 1) | ||
320 | return -ENOENT; | ||
321 | epd = get_endpoint(*alts, 0); | ||
322 | if (!usb_endpoint_is_isoc_in(epd) || | ||
323 | (epd->bmAttributes & USB_ENDPOINT_USAGE_MASK) != | ||
324 | USB_ENDPOINT_USAGE_IMPLICIT_FB) | ||
325 | return -ENOENT; | ||
326 | *ep = epd->bEndpointAddress; | ||
327 | return 0; | ||
328 | } | ||
329 | |||
301 | /* | 330 | /* |
302 | * find a matching format and set up the interface | 331 | * find a matching format and set up the interface |
303 | */ | 332 | */ |
@@ -393,6 +422,18 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) | |||
393 | goto add_sync_ep; | 422 | goto add_sync_ep; |
394 | } | 423 | } |
395 | } | 424 | } |
425 | if (is_playback && | ||
426 | attr == USB_ENDPOINT_SYNC_ASYNC && | ||
427 | altsd->bInterfaceClass == USB_CLASS_VENDOR_SPEC && | ||
428 | altsd->bInterfaceProtocol == 2 && | ||
429 | altsd->bNumEndpoints == 1 && | ||
430 | USB_ID_VENDOR(subs->stream->chip->usb_id) == 0x0582 /* Roland */ && | ||
431 | search_roland_implicit_fb(dev, altsd->bInterfaceNumber + 1, | ||
432 | altsd->bAlternateSetting, | ||
433 | &alts, &ep) >= 0) { | ||
434 | implicit_fb = 1; | ||
435 | goto add_sync_ep; | ||
436 | } | ||
396 | 437 | ||
397 | if (((is_playback && attr == USB_ENDPOINT_SYNC_ASYNC) || | 438 | if (((is_playback && attr == USB_ENDPOINT_SYNC_ASYNC) || |
398 | (!is_playback && attr == USB_ENDPOINT_SYNC_ADAPTIVE)) && | 439 | (!is_playback && attr == USB_ENDPOINT_SYNC_ADAPTIVE)) && |