Commit 5fd255f4 authored by Takashi Iwai's avatar Takashi Iwai

ALSA: usb-audio: Avoid doubly initialization for implicit fb

The implicit feedback mode initializes both the main data stream and
the sync data stream.  When a sync stream was already opened, this
would result in the doubly initialization and might screw up things.

Add the check of already opened sync streams and skip the unnecessary
initialization.
Tested-by: default avatarKeith Milner <kamilner@superlative.org>
Tested-by: default avatarDylan Robinson <dylan_robinson@motu.com>
Link: https://lore.kernel.org/r/20201123085347.19667-14-tiwai@suse.deSigned-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 7ec827b9
...@@ -601,8 +601,9 @@ static int set_sync_endpoint(struct snd_usb_substream *subs, ...@@ -601,8 +601,9 @@ static int set_sync_endpoint(struct snd_usb_substream *subs,
subs->data_endpoint->sync_master = subs->sync_endpoint; subs->data_endpoint->sync_master = subs->sync_endpoint;
if (subs->data_endpoint->iface != subs->sync_endpoint->iface || if (!subs->sync_endpoint->use_count &&
subs->data_endpoint->altsetting != subs->sync_endpoint->altsetting) { (subs->data_endpoint->iface != subs->sync_endpoint->iface ||
subs->data_endpoint->altsetting != subs->sync_endpoint->altsetting)) {
err = usb_set_interface(subs->dev, err = usb_set_interface(subs->dev,
subs->sync_endpoint->iface, subs->sync_endpoint->iface,
subs->sync_endpoint->altsetting); subs->sync_endpoint->altsetting);
...@@ -625,6 +626,7 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) ...@@ -625,6 +626,7 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
struct usb_device *dev = subs->dev; struct usb_device *dev = subs->dev;
struct usb_host_interface *alts; struct usb_host_interface *alts;
struct usb_interface *iface; struct usb_interface *iface;
struct snd_usb_endpoint *ep;
int err; int err;
iface = usb_ifnum_to_if(dev, fmt->iface); iface = usb_ifnum_to_if(dev, fmt->iface);
...@@ -637,6 +639,14 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) ...@@ -637,6 +639,14 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
if (fmt == subs->cur_audiofmt && !subs->need_setup_fmt) if (fmt == subs->cur_audiofmt && !subs->need_setup_fmt)
return 0; return 0;
/* shared EP with implicit fb */
if (fmt->implicit_fb && !subs->need_setup_fmt) {
ep = snd_usb_get_endpoint(subs->stream->chip, fmt->endpoint,
fmt->iface, fmt->altsetting);
if (ep && ep->use_count > 0)
goto add_data_ep;
}
/* close the old interface */ /* close the old interface */
if (subs->interface >= 0 && (subs->interface != fmt->iface || subs->need_setup_fmt)) { if (subs->interface >= 0 && (subs->interface != fmt->iface || subs->need_setup_fmt)) {
if (!subs->stream->chip->keep_iface) { if (!subs->stream->chip->keep_iface) {
...@@ -673,6 +683,9 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) ...@@ -673,6 +683,9 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
snd_usb_set_interface_quirk(dev); snd_usb_set_interface_quirk(dev);
} }
subs->need_setup_ep = true;
add_data_ep:
subs->interface = fmt->iface; subs->interface = fmt->iface;
subs->altset_idx = fmt->altset_idx; subs->altset_idx = fmt->altset_idx;
subs->data_endpoint = snd_usb_add_endpoint(subs->stream->chip, subs->data_endpoint = snd_usb_add_endpoint(subs->stream->chip,
...@@ -686,9 +699,11 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt) ...@@ -686,9 +699,11 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
if (err < 0) if (err < 0)
return err; return err;
if (subs->need_setup_ep) {
err = snd_usb_init_pitch(subs->stream->chip, fmt->iface, alts, fmt); err = snd_usb_init_pitch(subs->stream->chip, fmt->iface, alts, fmt);
if (err < 0) if (err < 0)
return err; return err;
}
subs->cur_audiofmt = fmt; subs->cur_audiofmt = fmt;
...@@ -940,10 +955,6 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, ...@@ -940,10 +955,6 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
if (ret < 0) if (ret < 0)
goto unlock; goto unlock;
subs->interface = fmt->iface;
subs->altset_idx = fmt->altset_idx;
subs->need_setup_ep = true;
unlock: unlock:
snd_usb_unlock_shutdown(subs->stream->chip); snd_usb_unlock_shutdown(subs->stream->chip);
if (ret < 0) if (ret < 0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment