[PATCH v2] Pioneer devices: engage implicit feedback sync for playback
Takashi Iwai
tiwai at suse.de
Tue Apr 6 13:48:50 CEST 2021
On Mon, 05 Apr 2021 15:49:20 +0200,
Geraldo wrote:
>
> Dear Linux users of Pioneer gear, please disregard v1 of this patch and test
> this instead if at all possible.
>
> My initial assessment that we needed to let the capture EP be opened twice was
> clearly proven wrong by further testing. This is good because if we really
> needed that it would require a lot of reengineering inside ALSA.
>
> One thing that still boggles my mind though is why we need a special Pioneer
> case inside snd_usb_parse_implicit_fb_quirk that returns 1 like a capture
> quirk was found.
>
> This is a highly experimental patch on top of 5.12-rc6 that's supposed to
> engage implicit feedback sync on the playback for Pioneer devices. Without
> implicit feedback sync the inputs started glitching due to clock drift in
> about an hour in my Pioneer DJ DDJ-SR2.
>
> Once again I'd like to thank Takashi Iwai. He's the true author of the bulk of
> this code, I just adapted it and coerced it into working.
>
> Signed-off-by: Geraldo Nascimento <geraldogabriel at gmail.com>
Thanks for the patch!
It's interesting that Pioneer devices would actually work with the
implicit feedback mode. It seems that the key point is to skip the
capture side; IIRC, we checked applying the quirk to the playback
side, but this wasn't enough or not properly working on some devices.
If that's the case, I believe a patch like below would be safer and
more inconsistent: it checks the device from both playback and capture
quirks with the same helper function.
Could you check whether this one works? (It's totally untested.)
thanks,
Takashi
---
--- a/sound/usb/implicit.c
+++ b/sound/usb/implicit.c
@@ -167,18 +167,27 @@ static int add_roland_implicit_fb(struct snd_usb_audio *chip,
ifnum, alts);
}
-/* Playback and capture EPs on Pioneer devices share the same iface/altset,
- * but they don't seem working with the implicit fb mode well, hence we
- * just return as if the sync were already set up.
+/* Playback and capture EPs on Pioneer devices share the same iface/altset
+ * for the implicit feedback operation
*/
-static int skip_pioneer_sync_ep(struct snd_usb_audio *chip,
- struct audioformat *fmt,
- struct usb_host_interface *alts)
+static bool is_pioneer_implicit_fb(struct snd_usb_audio *chip,
+ struct usb_host_interface *alts)
+
{
struct usb_endpoint_descriptor *epd;
+ if (USB_ID_VENDOR(chip->usb_id) != 0x2b73 &&
+ USB_ID_VENDOR(chip->usb_id) != 0x08e4)
+ return false;
+ if (alts->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC)
+ return false;
if (alts->desc.bNumEndpoints != 2)
- return 0;
+ return false;
+
+ epd = get_endpoint(alts, 0);
+ if (!usb_endpoint_is_isoc_out(epd) ||
+ (epd->bmAttributes & USB_ENDPOINT_SYNCTYPE) != USB_ENDPOINT_SYNC_ASYNC)
+ return false;
epd = get_endpoint(alts, 1);
if (!usb_endpoint_is_isoc_in(epd) ||
@@ -187,8 +196,9 @@ static int skip_pioneer_sync_ep(struct snd_usb_audio *chip,
USB_ENDPOINT_USAGE_DATA &&
(epd->bmAttributes & USB_ENDPOINT_USAGE_MASK) !=
USB_ENDPOINT_USAGE_IMPLICIT_FB))
- return 0;
- return 1; /* don't handle with the implicit fb, just skip sync EP */
+ return false;
+
+ return true;
}
static int __add_generic_implicit_fb(struct snd_usb_audio *chip,
@@ -297,13 +307,11 @@ static int audioformat_implicit_fb_quirk(struct snd_usb_audio *chip,
}
/* Pioneer devices 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 */
- USB_ID_VENDOR(chip->usb_id) == 0x08e4 /* Pioneer */)) {
- if (skip_pioneer_sync_ep(chip, fmt, alts))
- return 1;
- }
+ if (is_pioneer_implicit_fb(chip, alts))
+ return add_implicit_fb_sync_ep(chip, fmt,
+ get_endpoint(alts, 1)->bEndpointAddress,
+ 1, alts->desc.bInterfaceNumber,
+ alts);
/* Try the generic implicit fb if available */
if (chip->generic_implicit_fb)
@@ -324,6 +332,8 @@ static int audioformat_capture_quirk(struct snd_usb_audio *chip,
if (p && p->type == IMPLICIT_FB_FIXED)
return add_implicit_fb_sync_ep(chip, fmt, p->ep_num, 0,
p->iface, NULL);
+ if (is_pioneer_implicit_fb(chip, alts))
+ return 1; /* skip */
return 0;
}
More information about the Alsa-devel
mailing list