From 8a463225b11047455b374729d18c8a371fe6e591 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 2 May 2018 10:04:27 +0200 Subject: [PATCH] ALSA: usb-audio: Add keep_iface flag Git-commit: 8a463225b11047455b374729d18c8a371fe6e591 Patch-mainline: v4.18-rc1 References: bsc#1089467 Introduce a new flag to struct snd_usb_audio for allowing the device to skip usb_set_interface() calls at changing or closing the stream. As of this patch, the flag is nowhere set, so it's just a place holder. The dynamic switching will be added in the following patch. A background information for this change: Dell WD15 dock with Realtek chip gives a very long pause at each time the driver changes the altset, which eventually happens at every PCM stream open/close and parameter change. As the long pause happens in each usb_set_interface() call, there is nothing we can do as long as it's called. The workaround is to reduce calling it as much as possible, and this flag indicates that behavior. Signed-off-by: Takashi Iwai --- sound/usb/pcm.c | 17 ++++++++++------- sound/usb/usbaudio.h | 3 +++ 2 files changed, 13 insertions(+), 7 deletions(-) --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -517,12 +517,14 @@ static int set_format(struct snd_usb_sub /* close the old interface */ if (subs->interface >= 0 && subs->interface != fmt->iface) { - err = usb_set_interface(subs->dev, subs->interface, 0); - if (err < 0) { - dev_err(&dev->dev, - "%d:%d: return to setting 0 failed (%d)\n", - fmt->iface, fmt->altsetting, err); - return -EIO; + if (!subs->stream->chip->keep_iface) { + err = usb_set_interface(subs->dev, subs->interface, 0); + if (err < 0) { + dev_err(&dev->dev, + "%d:%d: return to setting 0 failed (%d)\n", + fmt->iface, fmt->altsetting, err); + return -EIO; + } } subs->interface = -1; subs->altset_idx = 0; @@ -1261,7 +1263,8 @@ static int snd_usb_pcm_close(struct snd_ stop_endpoints(subs, true); - if (subs->interface >= 0 && + if (!as->chip->keep_iface && + subs->interface >= 0 && !snd_usb_lock_shutdown(subs->stream->chip)) { usb_set_interface(subs->dev, subs->interface, 0); subs->interface = -1; --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -59,6 +59,9 @@ struct snd_usb_audio { int setup; /* from the 'device_setup' module param */ bool autoclock; /* from the 'autoclock' module param */ + bool keep_iface; /* keep interface/altset after closing + * or parameter change + */ struct usb_host_interface *ctrl_intf; /* the audio control interface */ };