Commit 167c9dc8 authored by Takashi Iwai's avatar Takashi Iwai

ALSA: usb-audio: Fix implicit feedback sync setup for Pioneer devices

Pioneer devices have both playback and capture streams sharing the
same iface/altsetting, and those need to be paired as implicit
feedback.  Instead of a half-baked (and broken) static quirk entry,
set up more generically for those devices by checking the number of
endpoints and the attribute of the secondary EP.

Fixes: bf6313a0 ("ALSA: usb-audio: Refactor endpoint management")
Reported-by: default avatarFrantišek Kučera <konference@frantovo.cz>
Link: https://lore.kernel.org/r/20210108075219.21463-6-tiwai@suse.deSigned-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent eae4d054
...@@ -58,8 +58,6 @@ static const struct snd_usb_implicit_fb_match playback_implicit_fb_quirks[] = { ...@@ -58,8 +58,6 @@ static const struct snd_usb_implicit_fb_match playback_implicit_fb_quirks[] = {
IMPLICIT_FB_FIXED_DEV(0x0499, 0x172f, 0x81, 2), /* Steinberg UR22C */ IMPLICIT_FB_FIXED_DEV(0x0499, 0x172f, 0x81, 2), /* Steinberg UR22C */
IMPLICIT_FB_FIXED_DEV(0x0d9a, 0x00df, 0x81, 2), /* RTX6001 */ IMPLICIT_FB_FIXED_DEV(0x0d9a, 0x00df, 0x81, 2), /* RTX6001 */
IMPLICIT_FB_FIXED_DEV(0x22f0, 0x0006, 0x81, 3), /* Allen&Heath Qu-16 */ IMPLICIT_FB_FIXED_DEV(0x22f0, 0x0006, 0x81, 3), /* Allen&Heath Qu-16 */
IMPLICIT_FB_FIXED_DEV(0x2b73, 0x000a, 0x82, 0), /* Pioneer DJ DJM-900NXS2 */
IMPLICIT_FB_FIXED_DEV(0x2b73, 0x0017, 0x82, 0), /* Pioneer DJ DJM-250MK2 */
IMPLICIT_FB_FIXED_DEV(0x1686, 0xf029, 0x82, 2), /* Zoom UAC-2 */ IMPLICIT_FB_FIXED_DEV(0x1686, 0xf029, 0x82, 2), /* Zoom UAC-2 */
IMPLICIT_FB_FIXED_DEV(0x2466, 0x8003, 0x86, 2), /* Fractal Audio Axe-Fx II */ IMPLICIT_FB_FIXED_DEV(0x2466, 0x8003, 0x86, 2), /* Fractal Audio Axe-Fx II */
IMPLICIT_FB_FIXED_DEV(0x0499, 0x172a, 0x86, 2), /* Yamaha MODX */ IMPLICIT_FB_FIXED_DEV(0x0499, 0x172a, 0x86, 2), /* Yamaha MODX */
...@@ -100,7 +98,7 @@ static const struct snd_usb_implicit_fb_match capture_implicit_fb_quirks[] = { ...@@ -100,7 +98,7 @@ static const struct snd_usb_implicit_fb_match capture_implicit_fb_quirks[] = {
/* set up sync EP information on the audioformat */ /* set up sync EP information on the audioformat */
static int add_implicit_fb_sync_ep(struct snd_usb_audio *chip, static int add_implicit_fb_sync_ep(struct snd_usb_audio *chip,
struct audioformat *fmt, struct audioformat *fmt,
int ep, int ifnum, int ep, int ep_idx, int ifnum,
const struct usb_host_interface *alts) const struct usb_host_interface *alts)
{ {
struct usb_interface *iface; struct usb_interface *iface;
...@@ -115,7 +113,7 @@ static int add_implicit_fb_sync_ep(struct snd_usb_audio *chip, ...@@ -115,7 +113,7 @@ static int add_implicit_fb_sync_ep(struct snd_usb_audio *chip,
fmt->sync_ep = ep; fmt->sync_ep = ep;
fmt->sync_iface = ifnum; fmt->sync_iface = ifnum;
fmt->sync_altsetting = alts->desc.bAlternateSetting; fmt->sync_altsetting = alts->desc.bAlternateSetting;
fmt->sync_ep_idx = 0; fmt->sync_ep_idx = ep_idx;
fmt->implicit_fb = 1; fmt->implicit_fb = 1;
usb_audio_dbg(chip, usb_audio_dbg(chip,
"%d:%d: added %s implicit_fb sync_ep %x, iface %d:%d\n", "%d:%d: added %s implicit_fb sync_ep %x, iface %d:%d\n",
...@@ -147,7 +145,7 @@ static int add_generic_uac2_implicit_fb(struct snd_usb_audio *chip, ...@@ -147,7 +145,7 @@ static int add_generic_uac2_implicit_fb(struct snd_usb_audio *chip,
(epd->bmAttributes & USB_ENDPOINT_USAGE_MASK) != (epd->bmAttributes & USB_ENDPOINT_USAGE_MASK) !=
USB_ENDPOINT_USAGE_IMPLICIT_FB) USB_ENDPOINT_USAGE_IMPLICIT_FB)
return 0; return 0;
return add_implicit_fb_sync_ep(chip, fmt, epd->bEndpointAddress, return add_implicit_fb_sync_ep(chip, fmt, epd->bEndpointAddress, 0,
ifnum, alts); ifnum, alts);
} }
...@@ -173,10 +171,32 @@ static int add_roland_implicit_fb(struct snd_usb_audio *chip, ...@@ -173,10 +171,32 @@ static int add_roland_implicit_fb(struct snd_usb_audio *chip,
(epd->bmAttributes & USB_ENDPOINT_USAGE_MASK) != (epd->bmAttributes & USB_ENDPOINT_USAGE_MASK) !=
USB_ENDPOINT_USAGE_IMPLICIT_FB) USB_ENDPOINT_USAGE_IMPLICIT_FB)
return 0; return 0;
return add_implicit_fb_sync_ep(chip, fmt, epd->bEndpointAddress, return add_implicit_fb_sync_ep(chip, fmt, epd->bEndpointAddress, 0,
ifnum, alts); ifnum, alts);
} }
/* Pioneer devices: playback and capture streams sharing the same iface/altset
*/
static int add_pioneer_implicit_fb(struct snd_usb_audio *chip,
struct audioformat *fmt,
struct usb_host_interface *alts)
{
struct usb_endpoint_descriptor *epd;
if (alts->desc.bNumEndpoints != 2)
return 0;
epd = get_endpoint(alts, 1);
if (!usb_endpoint_is_isoc_in(epd) ||
(epd->bmAttributes & USB_ENDPOINT_SYNCTYPE) != USB_ENDPOINT_SYNC_ASYNC ||
((epd->bmAttributes & USB_ENDPOINT_USAGE_MASK) !=
USB_ENDPOINT_USAGE_DATA &&
(epd->bmAttributes & USB_ENDPOINT_USAGE_MASK) !=
USB_ENDPOINT_USAGE_IMPLICIT_FB))
return 0;
return add_implicit_fb_sync_ep(chip, fmt, epd->bEndpointAddress, 1,
alts->desc.bInterfaceNumber, alts);
}
static int __add_generic_implicit_fb(struct snd_usb_audio *chip, static int __add_generic_implicit_fb(struct snd_usb_audio *chip,
struct audioformat *fmt, struct audioformat *fmt,
...@@ -197,7 +217,7 @@ static int __add_generic_implicit_fb(struct snd_usb_audio *chip, ...@@ -197,7 +217,7 @@ static int __add_generic_implicit_fb(struct snd_usb_audio *chip,
if (!usb_endpoint_is_isoc_in(epd) || if (!usb_endpoint_is_isoc_in(epd) ||
(epd->bmAttributes & USB_ENDPOINT_SYNCTYPE) != USB_ENDPOINT_SYNC_ASYNC) (epd->bmAttributes & USB_ENDPOINT_SYNCTYPE) != USB_ENDPOINT_SYNC_ASYNC)
return 0; return 0;
return add_implicit_fb_sync_ep(chip, fmt, epd->bEndpointAddress, return add_implicit_fb_sync_ep(chip, fmt, epd->bEndpointAddress, 0,
iface, alts); iface, alts);
} }
...@@ -250,7 +270,7 @@ static int audioformat_implicit_fb_quirk(struct snd_usb_audio *chip, ...@@ -250,7 +270,7 @@ static int audioformat_implicit_fb_quirk(struct snd_usb_audio *chip,
case IMPLICIT_FB_NONE: case IMPLICIT_FB_NONE:
return 0; /* No quirk */ return 0; /* No quirk */
case IMPLICIT_FB_FIXED: case IMPLICIT_FB_FIXED:
return add_implicit_fb_sync_ep(chip, fmt, p->ep_num, return add_implicit_fb_sync_ep(chip, fmt, p->ep_num, 0,
p->iface, NULL); p->iface, NULL);
} }
} }
...@@ -278,6 +298,14 @@ static int audioformat_implicit_fb_quirk(struct snd_usb_audio *chip, ...@@ -278,6 +298,14 @@ static int audioformat_implicit_fb_quirk(struct snd_usb_audio *chip,
return 1; return 1;
} }
/* Pioneer devices implicit feedback with vendor spec class */
if (attr == USB_ENDPOINT_SYNC_ASYNC &&
alts->desc.bInterfaceClass == USB_CLASS_VENDOR_SPEC &&
USB_ID_VENDOR(chip->usb_id) == 0x2b73 /* Pioneer */) {
if (add_pioneer_implicit_fb(chip, fmt, alts))
return 1;
}
/* Try the generic implicit fb if available */ /* Try the generic implicit fb if available */
if (chip->generic_implicit_fb) if (chip->generic_implicit_fb)
return add_generic_implicit_fb(chip, fmt, alts); return add_generic_implicit_fb(chip, fmt, alts);
...@@ -295,8 +323,8 @@ static int audioformat_capture_quirk(struct snd_usb_audio *chip, ...@@ -295,8 +323,8 @@ static int audioformat_capture_quirk(struct snd_usb_audio *chip,
p = find_implicit_fb_entry(chip, capture_implicit_fb_quirks, alts); p = find_implicit_fb_entry(chip, capture_implicit_fb_quirks, alts);
if (p && p->type == IMPLICIT_FB_FIXED) if (p && p->type == IMPLICIT_FB_FIXED)
return add_implicit_fb_sync_ep(chip, fmt, p->ep_num, p->iface, return add_implicit_fb_sync_ep(chip, fmt, p->ep_num, 0,
NULL); p->iface, NULL);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment