aboutsummaryrefslogtreecommitdiffstats
path: root/sound/usb
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2013-02-03 16:31:20 -0500
committerClemens Ladisch <clemens@ladisch.de>2013-06-27 15:59:47 -0400
commitba7c2be114243fa4cfcbc66a81db18e1d55abf4b (patch)
tree0452886296dc4564d4ca7cd5105231d74e97d88a /sound/usb
parent8f898e92aea2c24c7f379ee265d178f69ebb9c07 (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.c41
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
301static 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)) &&