All of lore.kernel.org
 help / color / mirror / Atom feed
From: Takashi Iwai <tiwai@suse.de>
To: jasmeet.bhatia.us@gmail.com
Cc: Takashi Iwai <tiwai@suse.com>, Jaroslav Kysela <perex@perex.cz>,
	"Geoffrey D . Bennett" <g@b4.vu>,
	linux-sound@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH] ALSA: usb-audio: Reset Blue Yeti firmware 0.20 after resume
Date: Thu, 22 Oct 2026 17:48:03 +0200	[thread overview]
Message-ID: <87o6clbuto.wl-tiwai@suse.de> (raw)
In-Reply-To: <20261021231754.16928-1-jasmeet.bhatia.us@gmail.com>

On Thu, 22 Oct 2026 01:17:54 +0200,
jasmeet.bhatia.us@gmail.com wrote:
> 
> From: "Jasmeet (Jazz) Bhatia" <jasmeet.bhatia.us@gmail.com>
> 
> Blue Yeti Classic microphones with firmware 0.20 remain enumerated
> after a system suspend/resume cycle but stop delivering capture
> samples. This results in an attempt to capture audio failing with
> -EIO.
> 
> Instead, the device should be recovered by sending its volatile ROM
> reset command after a system resume. The command restarts the device's
> MCU and USB logic, causing it to disconnect and re-enumerate with
> working capture.
> 
> Defering the reset to system_freezable_wq provided best results when
> testing, ensuring device resumes only after callbacks have completed.
> 
> Limits the quirk to USB ID 046d:0ab7 with bcdDevice 0x0020.
> 
> Signed-off-by: Jasmeet (Jazz) Bhatia <jasmeet.bhatia.us@gmail.com>

Apart from the issues Sashiko already reported, I find this way a bit
too scary, and I'm not sure whether the usb-audio driver is the right
place to perform such a thing.  Couldn't it be better done in the
lower USB layer somehow?


thanks,

Takashi

> ---
>  sound/usb/card.c   |  3 ++
>  sound/usb/quirks.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++
>  sound/usb/quirks.h |  1 +
>  3 files changed, 81 insertions(+)
> 
> diff --git a/sound/usb/card.c b/sound/usb/card.c
> index 9307da95efbe..ebacb98fc34e 100644
> --- a/sound/usb/card.c
> +++ b/sound/usb/card.c
> @@ -1280,6 +1280,9 @@ static int usb_audio_resume(struct usb_interface *intf)
>  	if (chip->num_suspended_intf > 1)
>  		goto out;
>  
> +	if (chip->system_suspend)
> +		snd_usb_apply_resume_quirk(chip);
> +
>  	list_for_each_entry(as, &chip->pcm_list, list) {
>  		err = snd_usb_pcm_resume(as);
>  		if (err < 0) {
> diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
> index a54fabce7920..42d955c7b7a4 100644
> --- a/sound/usb/quirks.c
> +++ b/sound/usb/quirks.c
> @@ -10,6 +10,8 @@
>  #include <linux/usb.h>
>  #include <linux/usb/audio.h>
>  #include <linux/usb/midi.h>
> +#include <linux/module.h>
> +#include <linux/workqueue.h>
>  #include <linux/bits.h>
>  
>  #include <sound/control.h>
> @@ -1626,6 +1628,81 @@ int snd_usb_apply_interface_quirk(struct snd_usb_audio *chip,
>  	return 0;
>  }
>  
> +/*
> + * Blue Yeti Classic firmware 0.20 may stop delivering capture samples
> + * after a system suspend/resume while otherwise remaining enumerated.
> + *
> + * Sending the device's volatile ROM reset command restarts its MCU and
> + * USB logic, causing it to re-enumerate and restoring capture.
> + *
> + * Do not send the command directly from the USB resume callback because
> + * it deliberately disconnects the device.  Queue it on the freezable
> + * workqueue so it runs after device resume callbacks have completed.
> + */
> +struct snd_usb_yeti_reset {
> +	struct work_struct work;
> +	struct usb_device *dev;
> +};
> +
> +static void snd_usb_yeti_reset_work(struct work_struct *work)
> +{
> +	struct snd_usb_yeti_reset *yeti =
> +		container_of(work, struct snd_usb_yeti_reset, work);
> +	struct usb_device *dev = yeti->dev;
> +	static const u8 reset_cmd[8] = {
> +		0x00, 0x09, 0x00, 0x00,
> +		0x00, 0x00, 0x00, 0x00
> +	};
> +	int err;
> +
> +	err = usb_control_msg_send(dev, 0, UAC_SET_CUR,
> +				   USB_DIR_OUT | USB_TYPE_CLASS |
> +				   USB_RECIP_INTERFACE,
> +				   0x0a00, 0x1900,
> +				   reset_cmd, sizeof(reset_cmd),
> +				   USB_CTRL_SET_TIMEOUT, GFP_KERNEL);
> +
> +	if (err && err != -ENODEV)
> +		dev_warn(&dev->dev,
> +			 "Blue Yeti resume reset failed: %d\n", err);
> +
> +	usb_put_dev(dev);
> +	kfree(yeti);
> +	module_put(THIS_MODULE);
> +}
> +
> +static void snd_usb_yeti_resume_quirk(struct snd_usb_audio *chip)
> +{
> +	struct usb_device *dev = chip->dev;
> +	struct snd_usb_yeti_reset *yeti;
> +
> +	if (chip->usb_id != USB_ID(0x046d, 0x0ab7) ||
> +	    le16_to_cpu(dev->descriptor.bcdDevice) != 0x0020)
> +		return;
> +
> +	yeti = kmalloc_obj(*yeti);
> +	if (!yeti) {
> +		dev_warn(&dev->dev,
> +			 "Blue Yeti resume reset allocation failed\n");
> +		return;
> +	}
> +
> +	INIT_WORK(&yeti->work, snd_usb_yeti_reset_work);
> +	yeti->dev = usb_get_dev(dev);
> +	__module_get(THIS_MODULE);
> +
> +	if (!queue_work(system_freezable_wq, &yeti->work)) {
> +		module_put(THIS_MODULE);
> +		usb_put_dev(yeti->dev);
> +		kfree(yeti);
> +	}
> +}
> +
> +void snd_usb_apply_resume_quirk(struct snd_usb_audio *chip)
> +{
> +	snd_usb_yeti_resume_quirk(chip);
> +}
> +
>  int snd_usb_apply_boot_quirk(struct usb_device *dev,
>  			     struct usb_interface *intf,
>  			     const struct snd_usb_audio_quirk *quirk,
> diff --git a/sound/usb/quirks.h b/sound/usb/quirks.h
> index 0a723c266bb4..9988e185538f 100644
> --- a/sound/usb/quirks.h
> +++ b/sound/usb/quirks.h
> @@ -15,6 +15,7 @@ int snd_usb_apply_interface_quirk(struct snd_usb_audio *chip,
>  				  int iface,
>  				  int altno);
>  
> +void snd_usb_apply_resume_quirk(struct snd_usb_audio *chip);
>  int snd_usb_apply_boot_quirk(struct usb_device *dev,
>  			     struct usb_interface *intf,
>  			     const struct snd_usb_audio_quirk *quirk,
> 
> base-commit: 4df4d2a577db2d3d57b888bcfb1206fc74661d16
> -- 
> 2.56.0
> 

      parent reply	other threads:[~2026-10-22 15:48 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-21 23:17 [PATCH] ALSA: usb-audio: Reset Blue Yeti firmware 0.20 after resume jasmeet.bhatia.us
2026-10-21 23:42 ` sashiko-bot
2026-10-22 15:48 ` Takashi Iwai [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87o6clbuto.wl-tiwai@suse.de \
    --to=tiwai@suse.de \
    --cc=g@b4.vu \
    --cc=jasmeet.bhatia.us@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-sound@vger.kernel.org \
    --cc=perex@perex.cz \
    --cc=tiwai@suse.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.