| From 352c22153cd7347e8ed400bbaa7515f95dbde156 Mon Sep 17 00:00:00 2001 |
| From: Alexander Tsoy <alexander@tsoy.me> |
| Date: Sun, 12 Jan 2020 13:23:58 +0300 |
| Subject: [PATCH] ALSA: usb-audio: Add boot quirk for MOTU M Series |
| |
| commit 73ac9f5e5b43a5dbadb61f27dae7a971f7ec0d22 upstream. |
| |
| Add delay to make sure that audio urbs are not sent too early. |
| Otherwise the device hangs. Windows driver makes ~2s delay, so use |
| about the same time delay value. |
| |
| snd_usb_apply_boot_quirk() is called 3 times for my MOTU M4, which |
| is an overkill. Thus a quirk that is called only once is implemented. |
| |
| Also send two vendor-specific control messages before and after |
| the delay. This behaviour is blindly copied from the Windows driver. |
| |
| Signed-off-by: Alexander Tsoy <alexander@tsoy.me> |
| Link: https://lore.kernel.org/r/20200112102358.18085-1-alexander@tsoy.me |
| Signed-off-by: Takashi Iwai <tiwai@suse.de> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/sound/usb/card.c b/sound/usb/card.c |
| index db91dc76cc91..e6a618a23994 100644 |
| --- a/sound/usb/card.c |
| +++ b/sound/usb/card.c |
| @@ -597,6 +597,10 @@ static int usb_audio_probe(struct usb_interface *intf, |
| } |
| } |
| if (! chip) { |
| + err = snd_usb_apply_boot_quirk_once(dev, intf, quirk, id); |
| + if (err < 0) |
| + return err; |
| + |
| /* it's a fresh one. |
| * now look for an empty slot and create a new card instance |
| */ |
| diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c |
| index 1ed25b1d2a6a..7448ab07bd36 100644 |
| --- a/sound/usb/quirks.c |
| +++ b/sound/usb/quirks.c |
| @@ -1113,6 +1113,31 @@ static int snd_usb_motu_microbookii_boot_quirk(struct usb_device *dev) |
| return err; |
| } |
| |
| +static int snd_usb_motu_m_series_boot_quirk(struct usb_device *dev) |
| +{ |
| + int ret; |
| + |
| + if (snd_usb_pipe_sanity_check(dev, usb_sndctrlpipe(dev, 0))) |
| + return -EINVAL; |
| + ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), |
| + 1, USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
| + 0x0, 0, NULL, 0, 1000); |
| + |
| + if (ret < 0) |
| + return ret; |
| + |
| + msleep(2000); |
| + |
| + ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), |
| + 1, USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
| + 0x20, 0, NULL, 0, 1000); |
| + |
| + if (ret < 0) |
| + return ret; |
| + |
| + return 0; |
| +} |
| + |
| /* |
| * Setup quirks |
| */ |
| @@ -1297,6 +1322,19 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev, |
| return 0; |
| } |
| |
| +int snd_usb_apply_boot_quirk_once(struct usb_device *dev, |
| + struct usb_interface *intf, |
| + const struct snd_usb_audio_quirk *quirk, |
| + unsigned int id) |
| +{ |
| + switch (id) { |
| + case USB_ID(0x07fd, 0x0008): /* MOTU M Series */ |
| + return snd_usb_motu_m_series_boot_quirk(dev); |
| + } |
| + |
| + return 0; |
| +} |
| + |
| /* |
| * check if the device uses big-endian samples |
| */ |
| diff --git a/sound/usb/quirks.h b/sound/usb/quirks.h |
| index a80e0ddd0736..df0355843a4c 100644 |
| --- a/sound/usb/quirks.h |
| +++ b/sound/usb/quirks.h |
| @@ -20,6 +20,11 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev, |
| const struct snd_usb_audio_quirk *quirk, |
| unsigned int usb_id); |
| |
| +int snd_usb_apply_boot_quirk_once(struct usb_device *dev, |
| + struct usb_interface *intf, |
| + const struct snd_usb_audio_quirk *quirk, |
| + unsigned int usb_id); |
| + |
| void snd_usb_set_format_quirk(struct snd_usb_substream *subs, |
| struct audioformat *fmt); |
| |
| -- |
| 2.7.4 |
| |