ALSA: usb-audio: set the interface format after resume on Dell WD19
Recently we found the headset-mic on the Dell Dock WD19 doesn't work anymore after s3 (s2i or deep), this problem could be workarounded by closing (pcm_close) the app and then reopening (pcm_open) the app, so this bug is not easy to be detected by users. When problem happens, retire_capture_urb() could still be called periodically, but the size of captured data is always 0, it could be a firmware bug on the dock. Anyway I found after resuming, the snd_usb_pcm_prepare() will be called, and if we forcibly run set_format() to set the interface and its endpoint, the capture size will be normal again. This problem and workaound also apply to playback. To fix it in the kernel, add a quirk to let set_format() run forcibly once after resume. Signed-off-by: Hui Wang <hui.wang@canonical.com> Cc: <stable@vger.kernel.org> Link: https://lore.kernel.org/r/20191218132650.6303-1-hui.wang@canonical.com Signed-off-by: Takashi Iwai <tiwai@suse.de>
Šī revīzija ir iekļauta:

revīziju iesūtīja
Takashi Iwai

vecāks
7c497d7992
revīzija
92adc96f8e
@@ -510,11 +510,11 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
|
||||
if (WARN_ON(altsd->bAlternateSetting != fmt->altsetting))
|
||||
return -EINVAL;
|
||||
|
||||
if (fmt == subs->cur_audiofmt)
|
||||
if (fmt == subs->cur_audiofmt && !subs->need_setup_fmt)
|
||||
return 0;
|
||||
|
||||
/* close the old interface */
|
||||
if (subs->interface >= 0 && subs->interface != fmt->iface) {
|
||||
if (subs->interface >= 0 && (subs->interface != fmt->iface || subs->need_setup_fmt)) {
|
||||
if (!subs->stream->chip->keep_iface) {
|
||||
err = usb_set_interface(subs->dev, subs->interface, 0);
|
||||
if (err < 0) {
|
||||
@@ -528,6 +528,9 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
|
||||
subs->altset_idx = 0;
|
||||
}
|
||||
|
||||
if (subs->need_setup_fmt)
|
||||
subs->need_setup_fmt = false;
|
||||
|
||||
/* set interface */
|
||||
if (iface->cur_altsetting != alts) {
|
||||
err = snd_usb_select_mode_quirk(subs, fmt);
|
||||
@@ -1728,6 +1731,13 @@ static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substrea
|
||||
subs->data_endpoint->retire_data_urb = retire_playback_urb;
|
||||
subs->running = 0;
|
||||
return 0;
|
||||
case SNDRV_PCM_TRIGGER_SUSPEND:
|
||||
if (subs->stream->chip->setup_fmt_after_resume_quirk) {
|
||||
stop_endpoints(subs, true);
|
||||
subs->need_setup_fmt = true;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
@@ -1760,6 +1770,13 @@ static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream
|
||||
subs->data_endpoint->retire_data_urb = retire_capture_urb;
|
||||
subs->running = 1;
|
||||
return 0;
|
||||
case SNDRV_PCM_TRIGGER_SUSPEND:
|
||||
if (subs->stream->chip->setup_fmt_after_resume_quirk) {
|
||||
stop_endpoints(subs, true);
|
||||
subs->need_setup_fmt = true;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
|
Atsaukties uz šo jaunā problēmā
Block a user