]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
drop alsa patch from all queues
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 9 Oct 2024 08:08:51 +0000 (10:08 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 9 Oct 2024 08:08:51 +0000 (10:08 +0200)
14 files changed:
queue-6.1/alsa-usb-audio-add-logitech-audio-profile-quirk.patch
queue-6.1/alsa-usb-audio-support-multiple-control-interfaces.patch [deleted file]
queue-6.1/series
queue-6.10/alsa-usb-audio-add-logitech-audio-profile-quirk.patch
queue-6.10/alsa-usb-audio-add-mixer-quirk-for-rme-digiface-usb.patch
queue-6.10/alsa-usb-audio-support-multiple-control-interfaces.patch [deleted file]
queue-6.10/series
queue-6.11/alsa-usb-audio-add-logitech-audio-profile-quirk.patch
queue-6.11/alsa-usb-audio-add-mixer-quirk-for-rme-digiface-usb.patch
queue-6.11/alsa-usb-audio-support-multiple-control-interfaces.patch [deleted file]
queue-6.11/series
queue-6.6/alsa-usb-audio-add-logitech-audio-profile-quirk.patch
queue-6.6/alsa-usb-audio-support-multiple-control-interfaces.patch [deleted file]
queue-6.6/series

index 3c87204c2db564555688c57722bec9943ea44676..8a51bbd459ff37a039df9c032f6d436a187355c8 100644 (file)
@@ -15,14 +15,12 @@ Link: https://patch.msgid.link/20240912152635.1859737-1-joshuapius@google.com
 Signed-off-by: Takashi Iwai <tiwai@suse.de>
 Signed-off-by: Sasha Levin <sashal@kernel.org>
 ---
- sound/usb/card.c | 6 ++++++
+ sound/usb/card.c |    6 ++++++
  1 file changed, 6 insertions(+)
 
-diff --git a/sound/usb/card.c b/sound/usb/card.c
-index 811bda4eeb9cf..74c5a87dff38e 100644
 --- a/sound/usb/card.c
 +++ b/sound/usb/card.c
-@@ -384,6 +384,12 @@ static const struct usb_audio_device_name usb_audio_names[] = {
+@@ -382,6 +382,12 @@ static const struct usb_audio_device_nam
        /* Creative/Toshiba Multimedia Center SB-0500 */
        DEVICE_NAME(0x041e, 0x3048, "Toshiba", "SB-0500"),
  
@@ -35,6 +33,3 @@ index 811bda4eeb9cf..74c5a87dff38e 100644
        DEVICE_NAME(0x046d, 0x0990, "Logitech, Inc.", "QuickCam Pro 9000"),
  
        DEVICE_NAME(0x05e1, 0x0408, "Syntek", "STK1160"),
--- 
-2.43.0
-
diff --git a/queue-6.1/alsa-usb-audio-support-multiple-control-interfaces.patch b/queue-6.1/alsa-usb-audio-support-multiple-control-interfaces.patch
deleted file mode 100644 (file)
index cfc5e64..0000000
+++ /dev/null
@@ -1,659 +0,0 @@
-From 3a84e7746b37d4d8dce8d7d4f9f64542cbf68612 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Sun, 11 Aug 2024 17:29:56 -0700
-Subject: ALSA: usb-audio: Support multiple control interfaces
-
-From: Karol Kosik <k.kosik@outlook.com>
-
-[ Upstream commit 6aa8700150f7dc62f60b4cf5b1624e2e3d9ed78e ]
-
-Registering Numark Party Mix II fails with error 'bogus bTerminalLink 1'.
-The problem stems from the driver not being able to find input/output
-terminals required to configure audio streaming. The information about
-those terminals is stored in AudioControl Interface. Numark device
-contains 2 AudioControl Interfaces and the driver checks only one of them.
-
-According to the USB standard, a device can have multiple audio functions,
-each represented by Audio Interface Collection. Every audio function is
-considered to be closed box and will contain unique AudioControl Interface
-and zero or more AudioStreaming and MIDIStreaming Interfaces.
-
-The Numark device adheres to the standard and defines two audio functions:
-- MIDIStreaming function
-- AudioStreaming function
-It starts with MIDI function, followed by the audio function. The driver
-saves the first AudioControl Interface in `snd_usb_audio` structure
-associated with the entire device. It then attempts to use this interface
-to query for terminals and clocks. However, this fails because the correct
-information is stored in the second AudioControl Interface, defined in the
-second Audio Interface Collection.
-
-This patch introduces a structure holding association between each
-MIDI/Audio Interface and its corresponding AudioControl Interface,
-instead of relying on AudioControl Interface defined for the entire
-device. This structure is populated during usb probing phase and leveraged
-later when querying for terminals and when sending USB requests.
-
-Alternative solutions considered include:
-- defining a quirk for Numark where the order of interface is manually
-changed, or terminals are hardcoded in the driver. This solution would
-have fixed only this model, though it seems that device is USB compliant,
-and it also seems that other devices from this company may be affected.
-What's more, it looks like products from other manufacturers have similar
-problems, i.e. Rane One DJ console
-- keeping a list of all AudioControl Interfaces and querying all of them
-to find required information. That would have solved my problem and have
-low probability of breaking other devices, as we would always start with
-the same logic of querying first AudioControl Interface. This solution
-would not have followed the standard though.
-
-This patch preserves the `snd_usb_audio.ctrl_intf` variable, which holds
-the first AudioControl Interface, and uses it as a fallback when some
-interfaces are not parsed correctly and lack an associated AudioControl
-Interface, i.e., when configured via quirks.
-
-Link: https://bugzilla.kernel.org/show_bug.cgi?id=217865
-Signed-off-by: Karol Kosik <k.kosik@outlook.com>
-Link: https://patch.msgid.link/AS8P190MB1285893F4735C8B32AD3886BEC852@AS8P190MB1285.EURP190.PROD.OUTLOOK.COM
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- sound/usb/card.c           |  2 ++
- sound/usb/clock.c          | 62 ++++++++++++++++++++++++--------------
- sound/usb/format.c         |  6 ++--
- sound/usb/helper.c         | 34 +++++++++++++++++++++
- sound/usb/helper.h         | 10 ++++--
- sound/usb/mixer.c          |  2 +-
- sound/usb/mixer_quirks.c   | 17 ++++++-----
- sound/usb/mixer_scarlett.c |  4 +--
- sound/usb/power.c          |  3 +-
- sound/usb/power.h          |  1 +
- sound/usb/stream.c         | 21 ++++++++-----
- sound/usb/usbaudio.h       | 12 ++++++++
- 12 files changed, 127 insertions(+), 47 deletions(-)
-
-diff --git a/sound/usb/card.c b/sound/usb/card.c
-index 26268ffb82742..811bda4eeb9cf 100644
---- a/sound/usb/card.c
-+++ b/sound/usb/card.c
-@@ -206,6 +206,8 @@ static int snd_usb_create_stream(struct snd_usb_audio *chip, int ctrlif, int int
-               return -EINVAL;
-       }
-+      snd_usb_add_ctrl_interface_link(chip, interface, ctrlif);
-+
-       if (! snd_usb_parse_audio_interface(chip, interface)) {
-               usb_set_interface(dev, interface, 0); /* reset the current interface */
-               return usb_driver_claim_interface(&usb_audio_driver, iface,
-diff --git a/sound/usb/clock.c b/sound/usb/clock.c
-index a676ad093d189..6f0693c428b0b 100644
---- a/sound/usb/clock.c
-+++ b/sound/usb/clock.c
-@@ -76,11 +76,14 @@ static bool validate_clock_multiplier(void *p, int id, int proto)
- }
- #define DEFINE_FIND_HELPER(name, obj, validator, type2, type3)                \
--static obj *name(struct snd_usb_audio *chip, int id, int proto)       \
-+static obj *name(struct snd_usb_audio *chip, int id,  \
-+                              const struct audioformat *fmt)  \
- {                                                                     \
--      return find_uac_clock_desc(chip->ctrl_intf, id, validator,      \
--                                 proto == UAC_VERSION_3 ? (type3) : (type2), \
--                                 proto);                              \
-+      struct usb_host_interface *ctrl_intf =  \
-+              snd_usb_find_ctrl_interface(chip, fmt->iface); \
-+      return find_uac_clock_desc(ctrl_intf, id, validator,    \
-+                                 fmt->protocol == UAC_VERSION_3 ? (type3) : (type2), \
-+                                 fmt->protocol);                              \
- }
- DEFINE_FIND_HELPER(snd_usb_find_clock_source,
-@@ -93,16 +96,19 @@ DEFINE_FIND_HELPER(snd_usb_find_clock_multiplier,
-                  union uac23_clock_multiplier_desc, validate_clock_multiplier,
-                  UAC2_CLOCK_MULTIPLIER, UAC3_CLOCK_MULTIPLIER);
--static int uac_clock_selector_get_val(struct snd_usb_audio *chip, int selector_id)
-+static int uac_clock_selector_get_val(struct snd_usb_audio *chip,
-+                              int selector_id, int iface_no)
- {
-+      struct usb_host_interface *ctrl_intf;
-       unsigned char buf;
-       int ret;
-+      ctrl_intf = snd_usb_find_ctrl_interface(chip, iface_no);
-       ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0),
-                             UAC2_CS_CUR,
-                             USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-                             UAC2_CX_CLOCK_SELECTOR << 8,
--                            snd_usb_ctrl_intf(chip) | (selector_id << 8),
-+                            snd_usb_ctrl_intf(ctrl_intf) | (selector_id << 8),
-                             &buf, sizeof(buf));
-       if (ret < 0)
-@@ -111,16 +117,18 @@ static int uac_clock_selector_get_val(struct snd_usb_audio *chip, int selector_i
-       return buf;
- }
--static int uac_clock_selector_set_val(struct snd_usb_audio *chip, int selector_id,
--                                      unsigned char pin)
-+static int uac_clock_selector_set_val(struct snd_usb_audio *chip,
-+                                      int selector_id, unsigned char pin, int iface_no)
- {
-+      struct usb_host_interface *ctrl_intf;
-       int ret;
-+      ctrl_intf = snd_usb_find_ctrl_interface(chip, iface_no);
-       ret = snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0),
-                             UAC2_CS_CUR,
-                             USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
-                             UAC2_CX_CLOCK_SELECTOR << 8,
--                            snd_usb_ctrl_intf(chip) | (selector_id << 8),
-+                            snd_usb_ctrl_intf(ctrl_intf) | (selector_id << 8),
-                             &pin, sizeof(pin));
-       if (ret < 0)
-               return ret;
-@@ -132,7 +140,7 @@ static int uac_clock_selector_set_val(struct snd_usb_audio *chip, int selector_i
-               return -EINVAL;
-       }
--      ret = uac_clock_selector_get_val(chip, selector_id);
-+      ret = uac_clock_selector_get_val(chip, selector_id, iface_no);
-       if (ret < 0)
-               return ret;
-@@ -155,8 +163,10 @@ static bool uac_clock_source_is_valid_quirk(struct snd_usb_audio *chip,
-       unsigned char data;
-       struct usb_device *dev = chip->dev;
-       union uac23_clock_source_desc *cs_desc;
-+      struct usb_host_interface *ctrl_intf;
--      cs_desc = snd_usb_find_clock_source(chip, source_id, fmt->protocol);
-+      ctrl_intf = snd_usb_find_ctrl_interface(chip, fmt->iface);
-+      cs_desc = snd_usb_find_clock_source(chip, source_id, fmt);
-       if (!cs_desc)
-               return false;
-@@ -191,7 +201,7 @@ static bool uac_clock_source_is_valid_quirk(struct snd_usb_audio *chip,
-                       err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
-                                             USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
-                                             UAC2_CS_CONTROL_CLOCK_VALID << 8,
--                                            snd_usb_ctrl_intf(chip) | (source_id << 8),
-+                                            snd_usb_ctrl_intf(ctrl_intf) | (source_id << 8),
-                                             &data, sizeof(data));
-                       if (err < 0) {
-                               dev_warn(&dev->dev,
-@@ -217,8 +227,10 @@ static bool uac_clock_source_is_valid(struct snd_usb_audio *chip,
-       struct usb_device *dev = chip->dev;
-       u32 bmControls;
-       union uac23_clock_source_desc *cs_desc;
-+      struct usb_host_interface *ctrl_intf;
--      cs_desc = snd_usb_find_clock_source(chip, source_id, fmt->protocol);
-+      ctrl_intf = snd_usb_find_ctrl_interface(chip, fmt->iface);
-+      cs_desc = snd_usb_find_clock_source(chip, source_id, fmt);
-       if (!cs_desc)
-               return false;
-@@ -235,7 +247,7 @@ static bool uac_clock_source_is_valid(struct snd_usb_audio *chip,
-       err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
-                             USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
-                             UAC2_CS_CONTROL_CLOCK_VALID << 8,
--                            snd_usb_ctrl_intf(chip) | (source_id << 8),
-+                            snd_usb_ctrl_intf(ctrl_intf) | (source_id << 8),
-                             &data, sizeof(data));
-       if (err < 0) {
-@@ -272,7 +284,7 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
-       }
-       /* first, see if the ID we're looking at is a clock source already */
--      source = snd_usb_find_clock_source(chip, entity_id, proto);
-+      source = snd_usb_find_clock_source(chip, entity_id, fmt);
-       if (source) {
-               entity_id = GET_VAL(source, proto, bClockID);
-               if (validate && !uac_clock_source_is_valid(chip, fmt,
-@@ -285,7 +297,7 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
-               return entity_id;
-       }
--      selector = snd_usb_find_clock_selector(chip, entity_id, proto);
-+      selector = snd_usb_find_clock_selector(chip, entity_id, fmt);
-       if (selector) {
-               pins = GET_VAL(selector, proto, bNrInPins);
-               clock_id = GET_VAL(selector, proto, bClockID);
-@@ -299,7 +311,7 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
-               /* the entity ID we are looking at is a selector.
-                * find out what it currently selects */
--              ret = uac_clock_selector_get_val(chip, clock_id);
-+              ret = uac_clock_selector_get_val(chip, clock_id, fmt->iface);
-               if (ret < 0) {
-                       if (!chip->autoclock)
-                               return ret;
-@@ -327,7 +339,7 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
-                       /* Skip setting clock selector again for some devices */
-                       if (chip->quirk_flags & QUIRK_FLAG_SKIP_CLOCK_SELECTOR)
-                               return ret;
--                      err = uac_clock_selector_set_val(chip, entity_id, cur);
-+                      err = uac_clock_selector_set_val(chip, entity_id, cur, fmt->iface);
-                       if (err < 0) {
-                               if (pins == 1) {
-                                       usb_audio_dbg(chip,
-@@ -355,7 +367,7 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
-                       if (ret < 0)
-                               continue;
--                      err = uac_clock_selector_set_val(chip, entity_id, i);
-+                      err = uac_clock_selector_set_val(chip, entity_id, i, fmt->iface);
-                       if (err < 0)
-                               continue;
-@@ -369,7 +381,7 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
-       }
-       /* FIXME: multipliers only act as pass-thru element for now */
--      multiplier = snd_usb_find_clock_multiplier(chip, entity_id, proto);
-+      multiplier = snd_usb_find_clock_multiplier(chip, entity_id, fmt);
-       if (multiplier)
-               return __uac_clock_find_source(chip, fmt,
-                                              GET_VAL(multiplier, proto, bCSourceID),
-@@ -469,11 +481,13 @@ static int get_sample_rate_v2v3(struct snd_usb_audio *chip, int iface,
-       struct usb_device *dev = chip->dev;
-       __le32 data;
-       int err;
-+      struct usb_host_interface *ctrl_intf;
-+      ctrl_intf = snd_usb_find_ctrl_interface(chip, iface);
-       err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
-                             USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
-                             UAC2_CS_CONTROL_SAM_FREQ << 8,
--                            snd_usb_ctrl_intf(chip) | (clock << 8),
-+                            snd_usb_ctrl_intf(ctrl_intf) | (clock << 8),
-                             &data, sizeof(data));
-       if (err < 0) {
-               dev_warn(&dev->dev, "%d:%d: cannot get freq (v2/v3): err %d\n",
-@@ -502,8 +516,10 @@ int snd_usb_set_sample_rate_v2v3(struct snd_usb_audio *chip,
-       __le32 data;
-       int err;
-       union uac23_clock_source_desc *cs_desc;
-+      struct usb_host_interface *ctrl_intf;
--      cs_desc = snd_usb_find_clock_source(chip, clock, fmt->protocol);
-+      ctrl_intf = snd_usb_find_ctrl_interface(chip, fmt->iface);
-+      cs_desc = snd_usb_find_clock_source(chip, clock, fmt);
-       if (!cs_desc)
-               return 0;
-@@ -522,7 +538,7 @@ int snd_usb_set_sample_rate_v2v3(struct snd_usb_audio *chip,
-       err = snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0), UAC2_CS_CUR,
-                             USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
-                             UAC2_CS_CONTROL_SAM_FREQ << 8,
--                            snd_usb_ctrl_intf(chip) | (clock << 8),
-+                            snd_usb_ctrl_intf(ctrl_intf) | (clock << 8),
-                             &data, sizeof(data));
-       if (err < 0)
-               return err;
-diff --git a/sound/usb/format.c b/sound/usb/format.c
-index 3b45d0ee76938..61c4aca8be09e 100644
---- a/sound/usb/format.c
-+++ b/sound/usb/format.c
-@@ -548,7 +548,9 @@ static int parse_audio_format_rates_v2v3(struct snd_usb_audio *chip,
-       unsigned char tmp[2], *data;
-       int nr_triplets, data_size, ret = 0, ret_l6;
-       int clock = snd_usb_clock_find_source(chip, fp, false);
-+      struct usb_host_interface *ctrl_intf;
-+      ctrl_intf = snd_usb_find_ctrl_interface(chip, fp->iface);
-       if (clock < 0) {
-               dev_err(&dev->dev,
-                       "%s(): unable to find clock source (clock %d)\n",
-@@ -560,7 +562,7 @@ static int parse_audio_format_rates_v2v3(struct snd_usb_audio *chip,
-       ret = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_RANGE,
-                             USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
-                             UAC2_CS_CONTROL_SAM_FREQ << 8,
--                            snd_usb_ctrl_intf(chip) | (clock << 8),
-+                            snd_usb_ctrl_intf(ctrl_intf) | (clock << 8),
-                             tmp, sizeof(tmp));
-       if (ret < 0) {
-@@ -595,7 +597,7 @@ static int parse_audio_format_rates_v2v3(struct snd_usb_audio *chip,
-       ret = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_RANGE,
-                             USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
-                             UAC2_CS_CONTROL_SAM_FREQ << 8,
--                            snd_usb_ctrl_intf(chip) | (clock << 8),
-+                            snd_usb_ctrl_intf(ctrl_intf) | (clock << 8),
-                             data, data_size);
-       if (ret < 0) {
-diff --git a/sound/usb/helper.c b/sound/usb/helper.c
-index a4410267bf701..f582a2ced3fd1 100644
---- a/sound/usb/helper.c
-+++ b/sound/usb/helper.c
-@@ -131,3 +131,37 @@ snd_usb_get_host_interface(struct snd_usb_audio *chip, int ifnum, int altsetting
-               return NULL;
-       return usb_altnum_to_altsetting(iface, altsetting);
- }
-+
-+int snd_usb_add_ctrl_interface_link(struct snd_usb_audio *chip, int ifnum,
-+              int ctrlif)
-+{
-+      struct usb_device *dev = chip->dev;
-+      struct usb_host_interface *host_iface;
-+
-+      if (chip->num_intf_to_ctrl >= MAX_CARD_INTERFACES) {
-+              dev_info(&dev->dev, "Too many interfaces assigned to the single USB-audio card\n");
-+              return -EINVAL;
-+      }
-+
-+      /* find audiocontrol interface */
-+      host_iface = &usb_ifnum_to_if(dev, ctrlif)->altsetting[0];
-+
-+      chip->intf_to_ctrl[chip->num_intf_to_ctrl].interface = ifnum;
-+      chip->intf_to_ctrl[chip->num_intf_to_ctrl].ctrl_intf = host_iface;
-+      chip->num_intf_to_ctrl++;
-+
-+      return 0;
-+}
-+
-+struct usb_host_interface *snd_usb_find_ctrl_interface(struct snd_usb_audio *chip,
-+                                                      int ifnum)
-+{
-+      int i;
-+
-+      for (i = 0; i < chip->num_intf_to_ctrl; ++i)
-+              if (chip->intf_to_ctrl[i].interface == ifnum)
-+                      return chip->intf_to_ctrl[i].ctrl_intf;
-+
-+      /* Fallback to first audiocontrol interface */
-+      return chip->ctrl_intf;
-+}
-diff --git a/sound/usb/helper.h b/sound/usb/helper.h
-index e2b51ec96ec62..0372e050b3dc4 100644
---- a/sound/usb/helper.h
-+++ b/sound/usb/helper.h
-@@ -17,6 +17,12 @@ unsigned char snd_usb_parse_datainterval(struct snd_usb_audio *chip,
- struct usb_host_interface *
- snd_usb_get_host_interface(struct snd_usb_audio *chip, int ifnum, int altsetting);
-+int snd_usb_add_ctrl_interface_link(struct snd_usb_audio *chip, int ifnum,
-+              int ctrlif);
-+
-+struct usb_host_interface *snd_usb_find_ctrl_interface(struct snd_usb_audio *chip,
-+                                                              int ifnum);
-+
- /*
-  * retrieve usb_interface descriptor from the host interface
-  * (conditional for compatibility with the older API)
-@@ -28,9 +34,9 @@ snd_usb_get_host_interface(struct snd_usb_audio *chip, int ifnum, int altsetting
- #define snd_usb_get_speed(dev) ((dev)->speed)
--static inline int snd_usb_ctrl_intf(struct snd_usb_audio *chip)
-+static inline int snd_usb_ctrl_intf(struct usb_host_interface *ctrl_intf)
- {
--      return get_iface_desc(chip->ctrl_intf)->bInterfaceNumber;
-+      return get_iface_desc(ctrl_intf)->bInterfaceNumber;
- }
- /* in validate.c */
-diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
-index 49facdf35b159..7bda8e9a93deb 100644
---- a/sound/usb/mixer.c
-+++ b/sound/usb/mixer.c
-@@ -728,7 +728,7 @@ static int get_cluster_channels_v3(struct mixer_build *state, unsigned int clust
-                       UAC3_CS_REQ_HIGH_CAPABILITY_DESCRIPTOR,
-                       USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-                       cluster_id,
--                      snd_usb_ctrl_intf(state->chip),
-+                      snd_usb_ctrl_intf(state->mixer->hostif),
-                       &c_header, sizeof(c_header));
-       if (err < 0)
-               goto error;
-diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
-index c8d48566e1759..2323504339328 100644
---- a/sound/usb/mixer_quirks.c
-+++ b/sound/usb/mixer_quirks.c
-@@ -1043,7 +1043,7 @@ static int snd_ftu_eff_switch_init(struct usb_mixer_interface *mixer,
-       err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC_GET_CUR,
-                             USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-                             pval & 0xff00,
--                            snd_usb_ctrl_intf(mixer->chip) | ((pval & 0xff) << 8),
-+                            snd_usb_ctrl_intf(mixer->hostif) | ((pval & 0xff) << 8),
-                             value, 2);
-       if (err < 0)
-               return err;
-@@ -1077,7 +1077,7 @@ static int snd_ftu_eff_switch_update(struct usb_mixer_elem_list *list)
-                             UAC_SET_CUR,
-                             USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
-                             pval & 0xff00,
--                            snd_usb_ctrl_intf(chip) | ((pval & 0xff) << 8),
-+                            snd_usb_ctrl_intf(list->mixer->hostif) | ((pval & 0xff) << 8),
-                             value, 2);
-       snd_usb_unlock_shutdown(chip);
-       return err;
-@@ -2115,24 +2115,25 @@ static int dell_dock_mixer_create(struct usb_mixer_interface *mixer)
-       return 0;
- }
--static void dell_dock_init_vol(struct snd_usb_audio *chip, int ch, int id)
-+static void dell_dock_init_vol(struct usb_mixer_interface *mixer, int ch, int id)
- {
-+      struct snd_usb_audio *chip = mixer->chip;
-       u16 buf = 0;
-       snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0), UAC_SET_CUR,
-                       USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
-                       (UAC_FU_VOLUME << 8) | ch,
--                      snd_usb_ctrl_intf(chip) | (id << 8),
-+                      snd_usb_ctrl_intf(mixer->hostif) | (id << 8),
-                       &buf, 2);
- }
- static int dell_dock_mixer_init(struct usb_mixer_interface *mixer)
- {
-       /* fix to 0dB playback volumes */
--      dell_dock_init_vol(mixer->chip, 1, 16);
--      dell_dock_init_vol(mixer->chip, 2, 16);
--      dell_dock_init_vol(mixer->chip, 1, 19);
--      dell_dock_init_vol(mixer->chip, 2, 19);
-+      dell_dock_init_vol(mixer, 1, 16);
-+      dell_dock_init_vol(mixer, 2, 16);
-+      dell_dock_init_vol(mixer, 1, 19);
-+      dell_dock_init_vol(mixer, 2, 19);
-       return 0;
- }
-diff --git a/sound/usb/mixer_scarlett.c b/sound/usb/mixer_scarlett.c
-index 0d6e4f15bf77c..ff548041679bb 100644
---- a/sound/usb/mixer_scarlett.c
-+++ b/sound/usb/mixer_scarlett.c
-@@ -460,7 +460,7 @@ static int scarlett_ctl_meter_get(struct snd_kcontrol *kctl,
-       struct snd_usb_audio *chip = elem->head.mixer->chip;
-       unsigned char buf[2 * MAX_CHANNELS] = {0, };
-       int wValue = (elem->control << 8) | elem->idx_off;
--      int idx = snd_usb_ctrl_intf(chip) | (elem->head.id << 8);
-+      int idx = snd_usb_ctrl_intf(elem->head.mixer->hostif) | (elem->head.id << 8);
-       int err;
-       err = snd_usb_ctl_msg(chip->dev,
-@@ -1002,7 +1002,7 @@ int snd_scarlett_controls_create(struct usb_mixer_interface *mixer)
-       err = snd_usb_ctl_msg(mixer->chip->dev,
-               usb_sndctrlpipe(mixer->chip->dev, 0), UAC2_CS_CUR,
-               USB_RECIP_INTERFACE | USB_TYPE_CLASS |
--              USB_DIR_OUT, 0x0100, snd_usb_ctrl_intf(mixer->chip) |
-+              USB_DIR_OUT, 0x0100, snd_usb_ctrl_intf(mixer->hostif) |
-               (0x29 << 8), sample_rate_buffer, 4);
-       if (err < 0)
-               return err;
-diff --git a/sound/usb/power.c b/sound/usb/power.c
-index 606a2cb23eab6..66bd4daa68fd5 100644
---- a/sound/usb/power.c
-+++ b/sound/usb/power.c
-@@ -40,6 +40,7 @@ snd_usb_find_power_domain(struct usb_host_interface *ctrl_iface,
-                                       le16_to_cpu(pd_desc->waRecoveryTime1);
-                               pd->pd_d2d0_rec =
-                                       le16_to_cpu(pd_desc->waRecoveryTime2);
-+                              pd->ctrl_iface = ctrl_iface;
-                               return pd;
-                       }
-               }
-@@ -57,7 +58,7 @@ int snd_usb_power_domain_set(struct snd_usb_audio *chip,
-       unsigned char current_state;
-       int err, idx;
--      idx = snd_usb_ctrl_intf(chip) | (pd->pd_id << 8);
-+      idx = snd_usb_ctrl_intf(pd->ctrl_iface) | (pd->pd_id << 8);
-       err = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0),
-                             UAC2_CS_CUR,
-diff --git a/sound/usb/power.h b/sound/usb/power.h
-index 396e3e51440a7..1fa92ad0ca925 100644
---- a/sound/usb/power.h
-+++ b/sound/usb/power.h
-@@ -6,6 +6,7 @@ struct snd_usb_power_domain {
-       int pd_id;              /* UAC3 Power Domain ID */
-       int pd_d1d0_rec;        /* D1 to D0 recovery time */
-       int pd_d2d0_rec;        /* D2 to D0 recovery time */
-+      struct usb_host_interface *ctrl_iface; /* Control interface */
- };
- enum {
-diff --git a/sound/usb/stream.c b/sound/usb/stream.c
-index e14c725acebf2..d70c140813d68 100644
---- a/sound/usb/stream.c
-+++ b/sound/usb/stream.c
-@@ -713,10 +713,13 @@ snd_usb_get_audioformat_uac12(struct snd_usb_audio *chip,
-       struct usb_device *dev = chip->dev;
-       struct uac_format_type_i_continuous_descriptor *fmt;
-       unsigned int num_channels = 0, chconfig = 0;
-+      struct usb_host_interface *ctrl_intf;
-       struct audioformat *fp;
-       int clock = 0;
-       u64 format;
-+      ctrl_intf = snd_usb_find_ctrl_interface(chip, iface_no);
-+
-       /* get audio formats */
-       if (protocol == UAC_VERSION_1) {
-               struct uac1_as_header_descriptor *as =
-@@ -740,7 +743,7 @@ snd_usb_get_audioformat_uac12(struct snd_usb_audio *chip,
-               format = le16_to_cpu(as->wFormatTag); /* remember the format value */
--              iterm = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
-+              iterm = snd_usb_find_input_terminal_descriptor(ctrl_intf,
-                                                              as->bTerminalLink,
-                                                              protocol);
-               if (iterm) {
-@@ -776,7 +779,7 @@ snd_usb_get_audioformat_uac12(struct snd_usb_audio *chip,
-                * lookup the terminal associated to this interface
-                * to extract the clock
-                */
--              input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
-+              input_term = snd_usb_find_input_terminal_descriptor(ctrl_intf,
-                                                                   as->bTerminalLink,
-                                                                   protocol);
-               if (input_term) {
-@@ -786,7 +789,7 @@ snd_usb_get_audioformat_uac12(struct snd_usb_audio *chip,
-                       goto found_clock;
-               }
--              output_term = snd_usb_find_output_terminal_descriptor(chip->ctrl_intf,
-+              output_term = snd_usb_find_output_terminal_descriptor(ctrl_intf,
-                                                                     as->bTerminalLink,
-                                                                     protocol);
-               if (output_term) {
-@@ -870,6 +873,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,
-       struct uac3_cluster_header_descriptor *cluster;
-       struct uac3_as_header_descriptor *as = NULL;
-       struct uac3_hc_descriptor_header hc_header;
-+      struct usb_host_interface *ctrl_intf;
-       struct snd_pcm_chmap_elem *chmap;
-       struct snd_usb_power_domain *pd;
-       unsigned char badd_profile;
-@@ -881,6 +885,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,
-       int err;
-       badd_profile = chip->badd_profile;
-+      ctrl_intf = snd_usb_find_ctrl_interface(chip, iface_no);
-       if (badd_profile >= UAC3_FUNCTION_SUBCLASS_GENERIC_IO) {
-               unsigned int maxpacksize =
-@@ -966,7 +971,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,
-                       UAC3_CS_REQ_HIGH_CAPABILITY_DESCRIPTOR,
-                       USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-                       cluster_id,
--                      snd_usb_ctrl_intf(chip),
-+                      snd_usb_ctrl_intf(ctrl_intf),
-                       &hc_header, sizeof(hc_header));
-       if (err < 0)
-               return ERR_PTR(err);
-@@ -990,7 +995,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,
-                       UAC3_CS_REQ_HIGH_CAPABILITY_DESCRIPTOR,
-                       USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-                       cluster_id,
--                      snd_usb_ctrl_intf(chip),
-+                      snd_usb_ctrl_intf(ctrl_intf),
-                       cluster, wLength);
-       if (err < 0) {
-               kfree(cluster);
-@@ -1011,7 +1016,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,
-        * lookup the terminal associated to this interface
-        * to extract the clock
-        */
--      input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
-+      input_term = snd_usb_find_input_terminal_descriptor(ctrl_intf,
-                                                           as->bTerminalLink,
-                                                           UAC_VERSION_3);
-       if (input_term) {
-@@ -1019,7 +1024,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,
-               goto found_clock;
-       }
--      output_term = snd_usb_find_output_terminal_descriptor(chip->ctrl_intf,
-+      output_term = snd_usb_find_output_terminal_descriptor(ctrl_intf,
-                                                             as->bTerminalLink,
-                                                             UAC_VERSION_3);
-       if (output_term) {
-@@ -1068,7 +1073,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,
-                                                              UAC_VERSION_3,
-                                                              iface_no);
--              pd = snd_usb_find_power_domain(chip->ctrl_intf,
-+              pd = snd_usb_find_power_domain(ctrl_intf,
-                                              as->bTerminalLink);
-               /* ok, let's parse further... */
-diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
-index f5a8dca66457f..1f56a07827aa7 100644
---- a/sound/usb/usbaudio.h
-+++ b/sound/usb/usbaudio.h
-@@ -21,6 +21,15 @@ struct media_intf_devnode;
- #define MAX_CARD_INTERFACES   16
-+/*
-+ * Structure holding assosiation between Audio Control Interface
-+ * and given Streaming or Midi Interface.
-+ */
-+struct snd_intf_to_ctrl {
-+      u8 interface;
-+      struct usb_host_interface *ctrl_intf;
-+};
-+
- struct snd_usb_audio {
-       int index;
-       struct usb_device *dev;
-@@ -61,6 +70,9 @@ struct snd_usb_audio {
-       struct usb_host_interface *ctrl_intf;   /* the audio control interface */
-       struct media_device *media_dev;
-       struct media_intf_devnode *ctl_intf_media_devnode;
-+
-+      unsigned int num_intf_to_ctrl;
-+      struct snd_intf_to_ctrl intf_to_ctrl[MAX_CARD_INTERFACES];
- };
- #define USB_AUDIO_IFACE_UNUSED        ((void *)-1L)
--- 
-2.43.0
-
index 2659633fd64d0f16e674c6d9ebe39bd63e7879d7..770f03e36d4fab07c465579af65ede031897e845 100644 (file)
@@ -453,7 +453,6 @@ wifi-mwifiex-fix-memcpy-field-spanning-write-warning.patch
 nfp-use-irqf_no_autoen-flag-in-request_irq.patch
 alsa-usb-audio-add-input-value-sanity-checks-for-sta.patch
 x86-ioapic-handle-allocation-failures-gracefully.patch
-alsa-usb-audio-support-multiple-control-interfaces.patch
 alsa-usb-audio-define-macros-for-quirk-table-entries.patch
 alsa-usb-audio-replace-complex-quirk-lines-with-macr.patch
 alsa-usb-audio-add-logitech-audio-profile-quirk.patch
index 8ad6c53212310b28f0bd606b23b85bd744b3d4ca..18f1afbdc6517087648b9d67f2440707083b2556 100644 (file)
@@ -15,14 +15,12 @@ Link: https://patch.msgid.link/20240912152635.1859737-1-joshuapius@google.com
 Signed-off-by: Takashi Iwai <tiwai@suse.de>
 Signed-off-by: Sasha Levin <sashal@kernel.org>
 ---
- sound/usb/card.c | 6 ++++++
+ sound/usb/card.c |    6 ++++++
  1 file changed, 6 insertions(+)
 
-diff --git a/sound/usb/card.c b/sound/usb/card.c
-index 778de9244f1e7..9c411b82a218d 100644
 --- a/sound/usb/card.c
 +++ b/sound/usb/card.c
-@@ -384,6 +384,12 @@ static const struct usb_audio_device_name usb_audio_names[] = {
+@@ -382,6 +382,12 @@ static const struct usb_audio_device_nam
        /* Creative/Toshiba Multimedia Center SB-0500 */
        DEVICE_NAME(0x041e, 0x3048, "Toshiba", "SB-0500"),
  
@@ -35,6 +33,3 @@ index 778de9244f1e7..9c411b82a218d 100644
        DEVICE_NAME(0x046d, 0x0990, "Logitech, Inc.", "QuickCam Pro 9000"),
  
        DEVICE_NAME(0x05e1, 0x0408, "Syntek", "STK1160"),
--- 
-2.43.0
-
index 08d34f8331e09e2bedbe0cca7d44330f86a8d2fa..d84d089fa33d805ec729ae799c0a4a23285d7c75 100644 (file)
@@ -23,12 +23,10 @@ Link: https://patch.msgid.link/20240903-rme-digiface-v2-2-71b06c912e97@asahilina
 Signed-off-by: Takashi Iwai <tiwai@suse.de>
 Signed-off-by: Sasha Levin <sashal@kernel.org>
 ---
- sound/usb/mixer_quirks.c | 413 +++++++++++++++++++++++++++++++++++++++
- sound/usb/quirks-table.h |   1 +
+ sound/usb/mixer_quirks.c |  413 +++++++++++++++++++++++++++++++++++++++++++++++
+ sound/usb/quirks-table.h |    1 
  2 files changed, 414 insertions(+)
 
-diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
-index 1d8bf1ecfed44..3727dbd123597 100644
 --- a/sound/usb/mixer_quirks.c
 +++ b/sound/usb/mixer_quirks.c
 @@ -14,6 +14,7 @@
@@ -39,11 +37,10 @@ index 1d8bf1ecfed44..3727dbd123597 100644
  #include <linux/hid.h>
  #include <linux/init.h>
  #include <linux/math64.h>
-@@ -2926,6 +2927,415 @@ static int snd_bbfpro_controls_create(struct usb_mixer_interface *mixer)
-       return 0;
+@@ -2926,6 +2927,415 @@ static int snd_bbfpro_controls_create(st
  }
  
-+/*
+ /*
 + * RME Digiface USB
 + */
 +
@@ -452,10 +449,11 @@ index 1d8bf1ecfed44..3727dbd123597 100644
 +      return 0;
 +}
 +
- /*
++/*
   * Pioneer DJ DJM Mixers
   *
-@@ -3484,6 +3894,9 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
+  * These devices generally have options for soft-switching the playback and
+@@ -3483,6 +3893,9 @@ int snd_usb_mixer_apply_create_quirk(str
        case USB_ID(0x2a39, 0x3fb0): /* RME Babyface Pro FS */
                err = snd_bbfpro_controls_create(mixer);
                break;
@@ -465,8 +463,6 @@ index 1d8bf1ecfed44..3727dbd123597 100644
        case USB_ID(0x2b73, 0x0017): /* Pioneer DJ DJM-250MK2 */
                err = snd_djm_controls_create(mixer, SND_DJM_250MK2_IDX);
                break;
-diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
-index 631b9ab80f6cd..24c981c9b2405 100644
 --- a/sound/usb/quirks-table.h
 +++ b/sound/usb/quirks-table.h
 @@ -3620,6 +3620,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
@@ -477,6 +473,3 @@ index 631b9ab80f6cd..24c981c9b2405 100644
                        {
                                QUIRK_DATA_AUDIOFORMAT(0) {
                                        .formats = SNDRV_PCM_FMTBIT_S32_LE,
--- 
-2.43.0
-
diff --git a/queue-6.10/alsa-usb-audio-support-multiple-control-interfaces.patch b/queue-6.10/alsa-usb-audio-support-multiple-control-interfaces.patch
deleted file mode 100644 (file)
index 03d755c..0000000
+++ /dev/null
@@ -1,659 +0,0 @@
-From 1900d66454dede84d5e1cdca46b1443b272293a3 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Sun, 11 Aug 2024 17:29:56 -0700
-Subject: ALSA: usb-audio: Support multiple control interfaces
-
-From: Karol Kosik <k.kosik@outlook.com>
-
-[ Upstream commit 6aa8700150f7dc62f60b4cf5b1624e2e3d9ed78e ]
-
-Registering Numark Party Mix II fails with error 'bogus bTerminalLink 1'.
-The problem stems from the driver not being able to find input/output
-terminals required to configure audio streaming. The information about
-those terminals is stored in AudioControl Interface. Numark device
-contains 2 AudioControl Interfaces and the driver checks only one of them.
-
-According to the USB standard, a device can have multiple audio functions,
-each represented by Audio Interface Collection. Every audio function is
-considered to be closed box and will contain unique AudioControl Interface
-and zero or more AudioStreaming and MIDIStreaming Interfaces.
-
-The Numark device adheres to the standard and defines two audio functions:
-- MIDIStreaming function
-- AudioStreaming function
-It starts with MIDI function, followed by the audio function. The driver
-saves the first AudioControl Interface in `snd_usb_audio` structure
-associated with the entire device. It then attempts to use this interface
-to query for terminals and clocks. However, this fails because the correct
-information is stored in the second AudioControl Interface, defined in the
-second Audio Interface Collection.
-
-This patch introduces a structure holding association between each
-MIDI/Audio Interface and its corresponding AudioControl Interface,
-instead of relying on AudioControl Interface defined for the entire
-device. This structure is populated during usb probing phase and leveraged
-later when querying for terminals and when sending USB requests.
-
-Alternative solutions considered include:
-- defining a quirk for Numark where the order of interface is manually
-changed, or terminals are hardcoded in the driver. This solution would
-have fixed only this model, though it seems that device is USB compliant,
-and it also seems that other devices from this company may be affected.
-What's more, it looks like products from other manufacturers have similar
-problems, i.e. Rane One DJ console
-- keeping a list of all AudioControl Interfaces and querying all of them
-to find required information. That would have solved my problem and have
-low probability of breaking other devices, as we would always start with
-the same logic of querying first AudioControl Interface. This solution
-would not have followed the standard though.
-
-This patch preserves the `snd_usb_audio.ctrl_intf` variable, which holds
-the first AudioControl Interface, and uses it as a fallback when some
-interfaces are not parsed correctly and lack an associated AudioControl
-Interface, i.e., when configured via quirks.
-
-Link: https://bugzilla.kernel.org/show_bug.cgi?id=217865
-Signed-off-by: Karol Kosik <k.kosik@outlook.com>
-Link: https://patch.msgid.link/AS8P190MB1285893F4735C8B32AD3886BEC852@AS8P190MB1285.EURP190.PROD.OUTLOOK.COM
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- sound/usb/card.c           |  2 ++
- sound/usb/clock.c          | 62 ++++++++++++++++++++++++--------------
- sound/usb/format.c         |  6 ++--
- sound/usb/helper.c         | 34 +++++++++++++++++++++
- sound/usb/helper.h         | 10 ++++--
- sound/usb/mixer.c          |  2 +-
- sound/usb/mixer_quirks.c   | 17 ++++++-----
- sound/usb/mixer_scarlett.c |  4 +--
- sound/usb/power.c          |  3 +-
- sound/usb/power.h          |  1 +
- sound/usb/stream.c         | 21 ++++++++-----
- sound/usb/usbaudio.h       | 12 ++++++++
- 12 files changed, 127 insertions(+), 47 deletions(-)
-
-diff --git a/sound/usb/card.c b/sound/usb/card.c
-index bdb04fa37a71d..778de9244f1e7 100644
---- a/sound/usb/card.c
-+++ b/sound/usb/card.c
-@@ -206,6 +206,8 @@ static int snd_usb_create_stream(struct snd_usb_audio *chip, int ctrlif, int int
-               return -EINVAL;
-       }
-+      snd_usb_add_ctrl_interface_link(chip, interface, ctrlif);
-+
-       if (! snd_usb_parse_audio_interface(chip, interface)) {
-               usb_set_interface(dev, interface, 0); /* reset the current interface */
-               return usb_driver_claim_interface(&usb_audio_driver, iface,
-diff --git a/sound/usb/clock.c b/sound/usb/clock.c
-index 60fcb872a80b6..8f85200292f3f 100644
---- a/sound/usb/clock.c
-+++ b/sound/usb/clock.c
-@@ -76,11 +76,14 @@ static bool validate_clock_multiplier(void *p, int id, int proto)
- }
- #define DEFINE_FIND_HELPER(name, obj, validator, type2, type3)                \
--static obj *name(struct snd_usb_audio *chip, int id, int proto)       \
-+static obj *name(struct snd_usb_audio *chip, int id,  \
-+                              const struct audioformat *fmt)  \
- {                                                                     \
--      return find_uac_clock_desc(chip->ctrl_intf, id, validator,      \
--                                 proto == UAC_VERSION_3 ? (type3) : (type2), \
--                                 proto);                              \
-+      struct usb_host_interface *ctrl_intf =  \
-+              snd_usb_find_ctrl_interface(chip, fmt->iface); \
-+      return find_uac_clock_desc(ctrl_intf, id, validator,    \
-+                                 fmt->protocol == UAC_VERSION_3 ? (type3) : (type2), \
-+                                 fmt->protocol);                              \
- }
- DEFINE_FIND_HELPER(snd_usb_find_clock_source,
-@@ -93,16 +96,19 @@ DEFINE_FIND_HELPER(snd_usb_find_clock_multiplier,
-                  union uac23_clock_multiplier_desc, validate_clock_multiplier,
-                  UAC2_CLOCK_MULTIPLIER, UAC3_CLOCK_MULTIPLIER);
--static int uac_clock_selector_get_val(struct snd_usb_audio *chip, int selector_id)
-+static int uac_clock_selector_get_val(struct snd_usb_audio *chip,
-+                              int selector_id, int iface_no)
- {
-+      struct usb_host_interface *ctrl_intf;
-       unsigned char buf;
-       int ret;
-+      ctrl_intf = snd_usb_find_ctrl_interface(chip, iface_no);
-       ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0),
-                             UAC2_CS_CUR,
-                             USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-                             UAC2_CX_CLOCK_SELECTOR << 8,
--                            snd_usb_ctrl_intf(chip) | (selector_id << 8),
-+                            snd_usb_ctrl_intf(ctrl_intf) | (selector_id << 8),
-                             &buf, sizeof(buf));
-       if (ret < 0)
-@@ -111,16 +117,18 @@ static int uac_clock_selector_get_val(struct snd_usb_audio *chip, int selector_i
-       return buf;
- }
--static int uac_clock_selector_set_val(struct snd_usb_audio *chip, int selector_id,
--                                      unsigned char pin)
-+static int uac_clock_selector_set_val(struct snd_usb_audio *chip,
-+                                      int selector_id, unsigned char pin, int iface_no)
- {
-+      struct usb_host_interface *ctrl_intf;
-       int ret;
-+      ctrl_intf = snd_usb_find_ctrl_interface(chip, iface_no);
-       ret = snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0),
-                             UAC2_CS_CUR,
-                             USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
-                             UAC2_CX_CLOCK_SELECTOR << 8,
--                            snd_usb_ctrl_intf(chip) | (selector_id << 8),
-+                            snd_usb_ctrl_intf(ctrl_intf) | (selector_id << 8),
-                             &pin, sizeof(pin));
-       if (ret < 0)
-               return ret;
-@@ -132,7 +140,7 @@ static int uac_clock_selector_set_val(struct snd_usb_audio *chip, int selector_i
-               return -EINVAL;
-       }
--      ret = uac_clock_selector_get_val(chip, selector_id);
-+      ret = uac_clock_selector_get_val(chip, selector_id, iface_no);
-       if (ret < 0)
-               return ret;
-@@ -155,8 +163,10 @@ static bool uac_clock_source_is_valid_quirk(struct snd_usb_audio *chip,
-       unsigned char data;
-       struct usb_device *dev = chip->dev;
-       union uac23_clock_source_desc *cs_desc;
-+      struct usb_host_interface *ctrl_intf;
--      cs_desc = snd_usb_find_clock_source(chip, source_id, fmt->protocol);
-+      ctrl_intf = snd_usb_find_ctrl_interface(chip, fmt->iface);
-+      cs_desc = snd_usb_find_clock_source(chip, source_id, fmt);
-       if (!cs_desc)
-               return false;
-@@ -191,7 +201,7 @@ static bool uac_clock_source_is_valid_quirk(struct snd_usb_audio *chip,
-                       err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
-                                             USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
-                                             UAC2_CS_CONTROL_CLOCK_VALID << 8,
--                                            snd_usb_ctrl_intf(chip) | (source_id << 8),
-+                                            snd_usb_ctrl_intf(ctrl_intf) | (source_id << 8),
-                                             &data, sizeof(data));
-                       if (err < 0) {
-                               dev_warn(&dev->dev,
-@@ -217,8 +227,10 @@ static bool uac_clock_source_is_valid(struct snd_usb_audio *chip,
-       struct usb_device *dev = chip->dev;
-       u32 bmControls;
-       union uac23_clock_source_desc *cs_desc;
-+      struct usb_host_interface *ctrl_intf;
--      cs_desc = snd_usb_find_clock_source(chip, source_id, fmt->protocol);
-+      ctrl_intf = snd_usb_find_ctrl_interface(chip, fmt->iface);
-+      cs_desc = snd_usb_find_clock_source(chip, source_id, fmt);
-       if (!cs_desc)
-               return false;
-@@ -235,7 +247,7 @@ static bool uac_clock_source_is_valid(struct snd_usb_audio *chip,
-       err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
-                             USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
-                             UAC2_CS_CONTROL_CLOCK_VALID << 8,
--                            snd_usb_ctrl_intf(chip) | (source_id << 8),
-+                            snd_usb_ctrl_intf(ctrl_intf) | (source_id << 8),
-                             &data, sizeof(data));
-       if (err < 0) {
-@@ -274,7 +286,7 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
-       }
-       /* first, see if the ID we're looking at is a clock source already */
--      source = snd_usb_find_clock_source(chip, entity_id, proto);
-+      source = snd_usb_find_clock_source(chip, entity_id, fmt);
-       if (source) {
-               entity_id = GET_VAL(source, proto, bClockID);
-               if (validate && !uac_clock_source_is_valid(chip, fmt,
-@@ -287,7 +299,7 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
-               return entity_id;
-       }
--      selector = snd_usb_find_clock_selector(chip, entity_id, proto);
-+      selector = snd_usb_find_clock_selector(chip, entity_id, fmt);
-       if (selector) {
-               pins = GET_VAL(selector, proto, bNrInPins);
-               clock_id = GET_VAL(selector, proto, bClockID);
-@@ -317,7 +329,7 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
-               /* the entity ID we are looking at is a selector.
-                * find out what it currently selects */
--              ret = uac_clock_selector_get_val(chip, clock_id);
-+              ret = uac_clock_selector_get_val(chip, clock_id, fmt->iface);
-               if (ret < 0) {
-                       if (!chip->autoclock)
-                               return ret;
-@@ -346,7 +358,7 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
-                       if (chip->quirk_flags & QUIRK_FLAG_SKIP_CLOCK_SELECTOR ||
-                           !writeable)
-                               return ret;
--                      err = uac_clock_selector_set_val(chip, entity_id, cur);
-+                      err = uac_clock_selector_set_val(chip, entity_id, cur, fmt->iface);
-                       if (err < 0) {
-                               if (pins == 1) {
-                                       usb_audio_dbg(chip,
-@@ -377,7 +389,7 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
-                       if (ret < 0)
-                               continue;
--                      err = uac_clock_selector_set_val(chip, entity_id, i);
-+                      err = uac_clock_selector_set_val(chip, entity_id, i, fmt->iface);
-                       if (err < 0)
-                               continue;
-@@ -391,7 +403,7 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
-       }
-       /* FIXME: multipliers only act as pass-thru element for now */
--      multiplier = snd_usb_find_clock_multiplier(chip, entity_id, proto);
-+      multiplier = snd_usb_find_clock_multiplier(chip, entity_id, fmt);
-       if (multiplier)
-               return __uac_clock_find_source(chip, fmt,
-                                              GET_VAL(multiplier, proto, bCSourceID),
-@@ -491,11 +503,13 @@ static int get_sample_rate_v2v3(struct snd_usb_audio *chip, int iface,
-       struct usb_device *dev = chip->dev;
-       __le32 data;
-       int err;
-+      struct usb_host_interface *ctrl_intf;
-+      ctrl_intf = snd_usb_find_ctrl_interface(chip, iface);
-       err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
-                             USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
-                             UAC2_CS_CONTROL_SAM_FREQ << 8,
--                            snd_usb_ctrl_intf(chip) | (clock << 8),
-+                            snd_usb_ctrl_intf(ctrl_intf) | (clock << 8),
-                             &data, sizeof(data));
-       if (err < 0) {
-               dev_warn(&dev->dev, "%d:%d: cannot get freq (v2/v3): err %d\n",
-@@ -524,8 +538,10 @@ int snd_usb_set_sample_rate_v2v3(struct snd_usb_audio *chip,
-       __le32 data;
-       int err;
-       union uac23_clock_source_desc *cs_desc;
-+      struct usb_host_interface *ctrl_intf;
--      cs_desc = snd_usb_find_clock_source(chip, clock, fmt->protocol);
-+      ctrl_intf = snd_usb_find_ctrl_interface(chip, fmt->iface);
-+      cs_desc = snd_usb_find_clock_source(chip, clock, fmt);
-       if (!cs_desc)
-               return 0;
-@@ -544,7 +560,7 @@ int snd_usb_set_sample_rate_v2v3(struct snd_usb_audio *chip,
-       err = snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0), UAC2_CS_CUR,
-                             USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
-                             UAC2_CS_CONTROL_SAM_FREQ << 8,
--                            snd_usb_ctrl_intf(chip) | (clock << 8),
-+                            snd_usb_ctrl_intf(ctrl_intf) | (clock << 8),
-                             &data, sizeof(data));
-       if (err < 0)
-               return err;
-diff --git a/sound/usb/format.c b/sound/usb/format.c
-index 3b45d0ee76938..61c4aca8be09e 100644
---- a/sound/usb/format.c
-+++ b/sound/usb/format.c
-@@ -548,7 +548,9 @@ static int parse_audio_format_rates_v2v3(struct snd_usb_audio *chip,
-       unsigned char tmp[2], *data;
-       int nr_triplets, data_size, ret = 0, ret_l6;
-       int clock = snd_usb_clock_find_source(chip, fp, false);
-+      struct usb_host_interface *ctrl_intf;
-+      ctrl_intf = snd_usb_find_ctrl_interface(chip, fp->iface);
-       if (clock < 0) {
-               dev_err(&dev->dev,
-                       "%s(): unable to find clock source (clock %d)\n",
-@@ -560,7 +562,7 @@ static int parse_audio_format_rates_v2v3(struct snd_usb_audio *chip,
-       ret = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_RANGE,
-                             USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
-                             UAC2_CS_CONTROL_SAM_FREQ << 8,
--                            snd_usb_ctrl_intf(chip) | (clock << 8),
-+                            snd_usb_ctrl_intf(ctrl_intf) | (clock << 8),
-                             tmp, sizeof(tmp));
-       if (ret < 0) {
-@@ -595,7 +597,7 @@ static int parse_audio_format_rates_v2v3(struct snd_usb_audio *chip,
-       ret = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_RANGE,
-                             USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
-                             UAC2_CS_CONTROL_SAM_FREQ << 8,
--                            snd_usb_ctrl_intf(chip) | (clock << 8),
-+                            snd_usb_ctrl_intf(ctrl_intf) | (clock << 8),
-                             data, data_size);
-       if (ret < 0) {
-diff --git a/sound/usb/helper.c b/sound/usb/helper.c
-index bf80e55d013a8..72b671fb2c84c 100644
---- a/sound/usb/helper.c
-+++ b/sound/usb/helper.c
-@@ -130,3 +130,37 @@ snd_usb_get_host_interface(struct snd_usb_audio *chip, int ifnum, int altsetting
-               return NULL;
-       return usb_altnum_to_altsetting(iface, altsetting);
- }
-+
-+int snd_usb_add_ctrl_interface_link(struct snd_usb_audio *chip, int ifnum,
-+              int ctrlif)
-+{
-+      struct usb_device *dev = chip->dev;
-+      struct usb_host_interface *host_iface;
-+
-+      if (chip->num_intf_to_ctrl >= MAX_CARD_INTERFACES) {
-+              dev_info(&dev->dev, "Too many interfaces assigned to the single USB-audio card\n");
-+              return -EINVAL;
-+      }
-+
-+      /* find audiocontrol interface */
-+      host_iface = &usb_ifnum_to_if(dev, ctrlif)->altsetting[0];
-+
-+      chip->intf_to_ctrl[chip->num_intf_to_ctrl].interface = ifnum;
-+      chip->intf_to_ctrl[chip->num_intf_to_ctrl].ctrl_intf = host_iface;
-+      chip->num_intf_to_ctrl++;
-+
-+      return 0;
-+}
-+
-+struct usb_host_interface *snd_usb_find_ctrl_interface(struct snd_usb_audio *chip,
-+                                                      int ifnum)
-+{
-+      int i;
-+
-+      for (i = 0; i < chip->num_intf_to_ctrl; ++i)
-+              if (chip->intf_to_ctrl[i].interface == ifnum)
-+                      return chip->intf_to_ctrl[i].ctrl_intf;
-+
-+      /* Fallback to first audiocontrol interface */
-+      return chip->ctrl_intf;
-+}
-diff --git a/sound/usb/helper.h b/sound/usb/helper.h
-index e2b51ec96ec62..0372e050b3dc4 100644
---- a/sound/usb/helper.h
-+++ b/sound/usb/helper.h
-@@ -17,6 +17,12 @@ unsigned char snd_usb_parse_datainterval(struct snd_usb_audio *chip,
- struct usb_host_interface *
- snd_usb_get_host_interface(struct snd_usb_audio *chip, int ifnum, int altsetting);
-+int snd_usb_add_ctrl_interface_link(struct snd_usb_audio *chip, int ifnum,
-+              int ctrlif);
-+
-+struct usb_host_interface *snd_usb_find_ctrl_interface(struct snd_usb_audio *chip,
-+                                                              int ifnum);
-+
- /*
-  * retrieve usb_interface descriptor from the host interface
-  * (conditional for compatibility with the older API)
-@@ -28,9 +34,9 @@ snd_usb_get_host_interface(struct snd_usb_audio *chip, int ifnum, int altsetting
- #define snd_usb_get_speed(dev) ((dev)->speed)
--static inline int snd_usb_ctrl_intf(struct snd_usb_audio *chip)
-+static inline int snd_usb_ctrl_intf(struct usb_host_interface *ctrl_intf)
- {
--      return get_iface_desc(chip->ctrl_intf)->bInterfaceNumber;
-+      return get_iface_desc(ctrl_intf)->bInterfaceNumber;
- }
- /* in validate.c */
-diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
-index 197fd07e69edd..017b50322d88f 100644
---- a/sound/usb/mixer.c
-+++ b/sound/usb/mixer.c
-@@ -728,7 +728,7 @@ static int get_cluster_channels_v3(struct mixer_build *state, unsigned int clust
-                       UAC3_CS_REQ_HIGH_CAPABILITY_DESCRIPTOR,
-                       USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-                       cluster_id,
--                      snd_usb_ctrl_intf(state->chip),
-+                      snd_usb_ctrl_intf(state->mixer->hostif),
-                       &c_header, sizeof(c_header));
-       if (err < 0)
-               goto error;
-diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
-index 212b5e6443d88..1d8bf1ecfed44 100644
---- a/sound/usb/mixer_quirks.c
-+++ b/sound/usb/mixer_quirks.c
-@@ -1043,7 +1043,7 @@ static int snd_ftu_eff_switch_init(struct usb_mixer_interface *mixer,
-       err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC_GET_CUR,
-                             USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-                             pval & 0xff00,
--                            snd_usb_ctrl_intf(mixer->chip) | ((pval & 0xff) << 8),
-+                            snd_usb_ctrl_intf(mixer->hostif) | ((pval & 0xff) << 8),
-                             value, 2);
-       if (err < 0)
-               return err;
-@@ -1077,7 +1077,7 @@ static int snd_ftu_eff_switch_update(struct usb_mixer_elem_list *list)
-                             UAC_SET_CUR,
-                             USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
-                             pval & 0xff00,
--                            snd_usb_ctrl_intf(chip) | ((pval & 0xff) << 8),
-+                            snd_usb_ctrl_intf(list->mixer->hostif) | ((pval & 0xff) << 8),
-                             value, 2);
-       snd_usb_unlock_shutdown(chip);
-       return err;
-@@ -2115,24 +2115,25 @@ static int dell_dock_mixer_create(struct usb_mixer_interface *mixer)
-       return 0;
- }
--static void dell_dock_init_vol(struct snd_usb_audio *chip, int ch, int id)
-+static void dell_dock_init_vol(struct usb_mixer_interface *mixer, int ch, int id)
- {
-+      struct snd_usb_audio *chip = mixer->chip;
-       u16 buf = 0;
-       snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0), UAC_SET_CUR,
-                       USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
-                       (UAC_FU_VOLUME << 8) | ch,
--                      snd_usb_ctrl_intf(chip) | (id << 8),
-+                      snd_usb_ctrl_intf(mixer->hostif) | (id << 8),
-                       &buf, 2);
- }
- static int dell_dock_mixer_init(struct usb_mixer_interface *mixer)
- {
-       /* fix to 0dB playback volumes */
--      dell_dock_init_vol(mixer->chip, 1, 16);
--      dell_dock_init_vol(mixer->chip, 2, 16);
--      dell_dock_init_vol(mixer->chip, 1, 19);
--      dell_dock_init_vol(mixer->chip, 2, 19);
-+      dell_dock_init_vol(mixer, 1, 16);
-+      dell_dock_init_vol(mixer, 2, 16);
-+      dell_dock_init_vol(mixer, 1, 19);
-+      dell_dock_init_vol(mixer, 2, 19);
-       return 0;
- }
-diff --git a/sound/usb/mixer_scarlett.c b/sound/usb/mixer_scarlett.c
-index 0d6e4f15bf77c..ff548041679bb 100644
---- a/sound/usb/mixer_scarlett.c
-+++ b/sound/usb/mixer_scarlett.c
-@@ -460,7 +460,7 @@ static int scarlett_ctl_meter_get(struct snd_kcontrol *kctl,
-       struct snd_usb_audio *chip = elem->head.mixer->chip;
-       unsigned char buf[2 * MAX_CHANNELS] = {0, };
-       int wValue = (elem->control << 8) | elem->idx_off;
--      int idx = snd_usb_ctrl_intf(chip) | (elem->head.id << 8);
-+      int idx = snd_usb_ctrl_intf(elem->head.mixer->hostif) | (elem->head.id << 8);
-       int err;
-       err = snd_usb_ctl_msg(chip->dev,
-@@ -1002,7 +1002,7 @@ int snd_scarlett_controls_create(struct usb_mixer_interface *mixer)
-       err = snd_usb_ctl_msg(mixer->chip->dev,
-               usb_sndctrlpipe(mixer->chip->dev, 0), UAC2_CS_CUR,
-               USB_RECIP_INTERFACE | USB_TYPE_CLASS |
--              USB_DIR_OUT, 0x0100, snd_usb_ctrl_intf(mixer->chip) |
-+              USB_DIR_OUT, 0x0100, snd_usb_ctrl_intf(mixer->hostif) |
-               (0x29 << 8), sample_rate_buffer, 4);
-       if (err < 0)
-               return err;
-diff --git a/sound/usb/power.c b/sound/usb/power.c
-index 606a2cb23eab6..66bd4daa68fd5 100644
---- a/sound/usb/power.c
-+++ b/sound/usb/power.c
-@@ -40,6 +40,7 @@ snd_usb_find_power_domain(struct usb_host_interface *ctrl_iface,
-                                       le16_to_cpu(pd_desc->waRecoveryTime1);
-                               pd->pd_d2d0_rec =
-                                       le16_to_cpu(pd_desc->waRecoveryTime2);
-+                              pd->ctrl_iface = ctrl_iface;
-                               return pd;
-                       }
-               }
-@@ -57,7 +58,7 @@ int snd_usb_power_domain_set(struct snd_usb_audio *chip,
-       unsigned char current_state;
-       int err, idx;
--      idx = snd_usb_ctrl_intf(chip) | (pd->pd_id << 8);
-+      idx = snd_usb_ctrl_intf(pd->ctrl_iface) | (pd->pd_id << 8);
-       err = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0),
-                             UAC2_CS_CUR,
-diff --git a/sound/usb/power.h b/sound/usb/power.h
-index 396e3e51440a7..1fa92ad0ca925 100644
---- a/sound/usb/power.h
-+++ b/sound/usb/power.h
-@@ -6,6 +6,7 @@ struct snd_usb_power_domain {
-       int pd_id;              /* UAC3 Power Domain ID */
-       int pd_d1d0_rec;        /* D1 to D0 recovery time */
-       int pd_d2d0_rec;        /* D2 to D0 recovery time */
-+      struct usb_host_interface *ctrl_iface; /* Control interface */
- };
- enum {
-diff --git a/sound/usb/stream.c b/sound/usb/stream.c
-index e14c725acebf2..d70c140813d68 100644
---- a/sound/usb/stream.c
-+++ b/sound/usb/stream.c
-@@ -713,10 +713,13 @@ snd_usb_get_audioformat_uac12(struct snd_usb_audio *chip,
-       struct usb_device *dev = chip->dev;
-       struct uac_format_type_i_continuous_descriptor *fmt;
-       unsigned int num_channels = 0, chconfig = 0;
-+      struct usb_host_interface *ctrl_intf;
-       struct audioformat *fp;
-       int clock = 0;
-       u64 format;
-+      ctrl_intf = snd_usb_find_ctrl_interface(chip, iface_no);
-+
-       /* get audio formats */
-       if (protocol == UAC_VERSION_1) {
-               struct uac1_as_header_descriptor *as =
-@@ -740,7 +743,7 @@ snd_usb_get_audioformat_uac12(struct snd_usb_audio *chip,
-               format = le16_to_cpu(as->wFormatTag); /* remember the format value */
--              iterm = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
-+              iterm = snd_usb_find_input_terminal_descriptor(ctrl_intf,
-                                                              as->bTerminalLink,
-                                                              protocol);
-               if (iterm) {
-@@ -776,7 +779,7 @@ snd_usb_get_audioformat_uac12(struct snd_usb_audio *chip,
-                * lookup the terminal associated to this interface
-                * to extract the clock
-                */
--              input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
-+              input_term = snd_usb_find_input_terminal_descriptor(ctrl_intf,
-                                                                   as->bTerminalLink,
-                                                                   protocol);
-               if (input_term) {
-@@ -786,7 +789,7 @@ snd_usb_get_audioformat_uac12(struct snd_usb_audio *chip,
-                       goto found_clock;
-               }
--              output_term = snd_usb_find_output_terminal_descriptor(chip->ctrl_intf,
-+              output_term = snd_usb_find_output_terminal_descriptor(ctrl_intf,
-                                                                     as->bTerminalLink,
-                                                                     protocol);
-               if (output_term) {
-@@ -870,6 +873,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,
-       struct uac3_cluster_header_descriptor *cluster;
-       struct uac3_as_header_descriptor *as = NULL;
-       struct uac3_hc_descriptor_header hc_header;
-+      struct usb_host_interface *ctrl_intf;
-       struct snd_pcm_chmap_elem *chmap;
-       struct snd_usb_power_domain *pd;
-       unsigned char badd_profile;
-@@ -881,6 +885,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,
-       int err;
-       badd_profile = chip->badd_profile;
-+      ctrl_intf = snd_usb_find_ctrl_interface(chip, iface_no);
-       if (badd_profile >= UAC3_FUNCTION_SUBCLASS_GENERIC_IO) {
-               unsigned int maxpacksize =
-@@ -966,7 +971,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,
-                       UAC3_CS_REQ_HIGH_CAPABILITY_DESCRIPTOR,
-                       USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-                       cluster_id,
--                      snd_usb_ctrl_intf(chip),
-+                      snd_usb_ctrl_intf(ctrl_intf),
-                       &hc_header, sizeof(hc_header));
-       if (err < 0)
-               return ERR_PTR(err);
-@@ -990,7 +995,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,
-                       UAC3_CS_REQ_HIGH_CAPABILITY_DESCRIPTOR,
-                       USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-                       cluster_id,
--                      snd_usb_ctrl_intf(chip),
-+                      snd_usb_ctrl_intf(ctrl_intf),
-                       cluster, wLength);
-       if (err < 0) {
-               kfree(cluster);
-@@ -1011,7 +1016,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,
-        * lookup the terminal associated to this interface
-        * to extract the clock
-        */
--      input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
-+      input_term = snd_usb_find_input_terminal_descriptor(ctrl_intf,
-                                                           as->bTerminalLink,
-                                                           UAC_VERSION_3);
-       if (input_term) {
-@@ -1019,7 +1024,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,
-               goto found_clock;
-       }
--      output_term = snd_usb_find_output_terminal_descriptor(chip->ctrl_intf,
-+      output_term = snd_usb_find_output_terminal_descriptor(ctrl_intf,
-                                                             as->bTerminalLink,
-                                                             UAC_VERSION_3);
-       if (output_term) {
-@@ -1068,7 +1073,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,
-                                                              UAC_VERSION_3,
-                                                              iface_no);
--              pd = snd_usb_find_power_domain(chip->ctrl_intf,
-+              pd = snd_usb_find_power_domain(ctrl_intf,
-                                              as->bTerminalLink);
-               /* ok, let's parse further... */
-diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
-index 43d4029edab46..b0f042c996087 100644
---- a/sound/usb/usbaudio.h
-+++ b/sound/usb/usbaudio.h
-@@ -21,6 +21,15 @@ struct media_intf_devnode;
- #define MAX_CARD_INTERFACES   16
-+/*
-+ * Structure holding assosiation between Audio Control Interface
-+ * and given Streaming or Midi Interface.
-+ */
-+struct snd_intf_to_ctrl {
-+      u8 interface;
-+      struct usb_host_interface *ctrl_intf;
-+};
-+
- struct snd_usb_audio {
-       int index;
-       struct usb_device *dev;
-@@ -63,6 +72,9 @@ struct snd_usb_audio {
-       struct usb_host_interface *ctrl_intf;   /* the audio control interface */
-       struct media_device *media_dev;
-       struct media_intf_devnode *ctl_intf_media_devnode;
-+
-+      unsigned int num_intf_to_ctrl;
-+      struct snd_intf_to_ctrl intf_to_ctrl[MAX_CARD_INTERFACES];
- };
- #define USB_AUDIO_IFACE_UNUSED        ((void *)-1L)
--- 
-2.43.0
-
index 98d6c4b952cd74ef15409f6a93cdb1873e621e35..c011b7d31edf20c5e26211a14b835ad06e602b40 100644 (file)
@@ -138,7 +138,6 @@ nfp-use-irqf_no_autoen-flag-in-request_irq.patch
 alsa-usb-audio-add-input-value-sanity-checks-for-sta.patch
 x86-ioapic-handle-allocation-failures-gracefully.patch
 x86-apic-remove-logical-destination-mode-for-64-bit.patch
-alsa-usb-audio-support-multiple-control-interfaces.patch
 alsa-usb-audio-define-macros-for-quirk-table-entries.patch
 alsa-usb-audio-replace-complex-quirk-lines-with-macr.patch
 alsa-usb-audio-add-quirk-for-rme-digiface-usb.patch
index ecb2786e5891a5b3bc3d06f4bbbdcd0310934ae1..a4e568b026746f5c637c84906535274fa6eca90a 100644 (file)
@@ -15,14 +15,12 @@ Link: https://patch.msgid.link/20240912152635.1859737-1-joshuapius@google.com
 Signed-off-by: Takashi Iwai <tiwai@suse.de>
 Signed-off-by: Sasha Levin <sashal@kernel.org>
 ---
- sound/usb/card.c | 6 ++++++
+ sound/usb/card.c |    6 ++++++
  1 file changed, 6 insertions(+)
 
-diff --git a/sound/usb/card.c b/sound/usb/card.c
-index 778de9244f1e7..9c411b82a218d 100644
 --- a/sound/usb/card.c
 +++ b/sound/usb/card.c
-@@ -384,6 +384,12 @@ static const struct usb_audio_device_name usb_audio_names[] = {
+@@ -382,6 +382,12 @@ static const struct usb_audio_device_nam
        /* Creative/Toshiba Multimedia Center SB-0500 */
        DEVICE_NAME(0x041e, 0x3048, "Toshiba", "SB-0500"),
  
@@ -35,6 +33,3 @@ index 778de9244f1e7..9c411b82a218d 100644
        DEVICE_NAME(0x046d, 0x0990, "Logitech, Inc.", "QuickCam Pro 9000"),
  
        DEVICE_NAME(0x05e1, 0x0408, "Syntek", "STK1160"),
--- 
-2.43.0
-
index d98edf5a8f8edbae4b671c9f101711b974d2bfde..6bd4dfb1cc78618fbe44cbc578ccc885c7f1b753 100644 (file)
@@ -23,12 +23,10 @@ Link: https://patch.msgid.link/20240903-rme-digiface-v2-2-71b06c912e97@asahilina
 Signed-off-by: Takashi Iwai <tiwai@suse.de>
 Signed-off-by: Sasha Levin <sashal@kernel.org>
 ---
- sound/usb/mixer_quirks.c | 413 +++++++++++++++++++++++++++++++++++++++
- sound/usb/quirks-table.h |   1 +
+ sound/usb/mixer_quirks.c |  413 +++++++++++++++++++++++++++++++++++++++++++++++
+ sound/usb/quirks-table.h |    1 
  2 files changed, 414 insertions(+)
 
-diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
-index 8cbfb65846047..74abc44be77ca 100644
 --- a/sound/usb/mixer_quirks.c
 +++ b/sound/usb/mixer_quirks.c
 @@ -14,6 +14,7 @@
@@ -39,11 +37,10 @@ index 8cbfb65846047..74abc44be77ca 100644
  #include <linux/hid.h>
  #include <linux/init.h>
  #include <linux/math64.h>
-@@ -2926,6 +2927,415 @@ static int snd_bbfpro_controls_create(struct usb_mixer_interface *mixer)
-       return 0;
+@@ -2926,6 +2927,415 @@ static int snd_bbfpro_controls_create(st
  }
  
-+/*
+ /*
 + * RME Digiface USB
 + */
 +
@@ -452,10 +449,11 @@ index 8cbfb65846047..74abc44be77ca 100644
 +      return 0;
 +}
 +
- /*
++/*
   * Pioneer DJ DJM Mixers
   *
-@@ -3484,6 +3894,9 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
+  * These devices generally have options for soft-switching the playback and
+@@ -3483,6 +3893,9 @@ int snd_usb_mixer_apply_create_quirk(str
        case USB_ID(0x2a39, 0x3fb0): /* RME Babyface Pro FS */
                err = snd_bbfpro_controls_create(mixer);
                break;
@@ -465,8 +463,6 @@ index 8cbfb65846047..74abc44be77ca 100644
        case USB_ID(0x2b73, 0x0017): /* Pioneer DJ DJM-250MK2 */
                err = snd_djm_controls_create(mixer, SND_DJM_250MK2_IDX);
                break;
-diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
-index 631b9ab80f6cd..24c981c9b2405 100644
 --- a/sound/usb/quirks-table.h
 +++ b/sound/usb/quirks-table.h
 @@ -3620,6 +3620,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
@@ -477,6 +473,3 @@ index 631b9ab80f6cd..24c981c9b2405 100644
                        {
                                QUIRK_DATA_AUDIOFORMAT(0) {
                                        .formats = SNDRV_PCM_FMTBIT_S32_LE,
--- 
-2.43.0
-
diff --git a/queue-6.11/alsa-usb-audio-support-multiple-control-interfaces.patch b/queue-6.11/alsa-usb-audio-support-multiple-control-interfaces.patch
deleted file mode 100644 (file)
index 0f911a1..0000000
+++ /dev/null
@@ -1,659 +0,0 @@
-From 0d5ff56702cf94d5a85af9d602ad1a4548d51eae Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Sun, 11 Aug 2024 17:29:56 -0700
-Subject: ALSA: usb-audio: Support multiple control interfaces
-
-From: Karol Kosik <k.kosik@outlook.com>
-
-[ Upstream commit 6aa8700150f7dc62f60b4cf5b1624e2e3d9ed78e ]
-
-Registering Numark Party Mix II fails with error 'bogus bTerminalLink 1'.
-The problem stems from the driver not being able to find input/output
-terminals required to configure audio streaming. The information about
-those terminals is stored in AudioControl Interface. Numark device
-contains 2 AudioControl Interfaces and the driver checks only one of them.
-
-According to the USB standard, a device can have multiple audio functions,
-each represented by Audio Interface Collection. Every audio function is
-considered to be closed box and will contain unique AudioControl Interface
-and zero or more AudioStreaming and MIDIStreaming Interfaces.
-
-The Numark device adheres to the standard and defines two audio functions:
-- MIDIStreaming function
-- AudioStreaming function
-It starts with MIDI function, followed by the audio function. The driver
-saves the first AudioControl Interface in `snd_usb_audio` structure
-associated with the entire device. It then attempts to use this interface
-to query for terminals and clocks. However, this fails because the correct
-information is stored in the second AudioControl Interface, defined in the
-second Audio Interface Collection.
-
-This patch introduces a structure holding association between each
-MIDI/Audio Interface and its corresponding AudioControl Interface,
-instead of relying on AudioControl Interface defined for the entire
-device. This structure is populated during usb probing phase and leveraged
-later when querying for terminals and when sending USB requests.
-
-Alternative solutions considered include:
-- defining a quirk for Numark where the order of interface is manually
-changed, or terminals are hardcoded in the driver. This solution would
-have fixed only this model, though it seems that device is USB compliant,
-and it also seems that other devices from this company may be affected.
-What's more, it looks like products from other manufacturers have similar
-problems, i.e. Rane One DJ console
-- keeping a list of all AudioControl Interfaces and querying all of them
-to find required information. That would have solved my problem and have
-low probability of breaking other devices, as we would always start with
-the same logic of querying first AudioControl Interface. This solution
-would not have followed the standard though.
-
-This patch preserves the `snd_usb_audio.ctrl_intf` variable, which holds
-the first AudioControl Interface, and uses it as a fallback when some
-interfaces are not parsed correctly and lack an associated AudioControl
-Interface, i.e., when configured via quirks.
-
-Link: https://bugzilla.kernel.org/show_bug.cgi?id=217865
-Signed-off-by: Karol Kosik <k.kosik@outlook.com>
-Link: https://patch.msgid.link/AS8P190MB1285893F4735C8B32AD3886BEC852@AS8P190MB1285.EURP190.PROD.OUTLOOK.COM
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- sound/usb/card.c           |  2 ++
- sound/usb/clock.c          | 62 ++++++++++++++++++++++++--------------
- sound/usb/format.c         |  6 ++--
- sound/usb/helper.c         | 34 +++++++++++++++++++++
- sound/usb/helper.h         | 10 ++++--
- sound/usb/mixer.c          |  2 +-
- sound/usb/mixer_quirks.c   | 17 ++++++-----
- sound/usb/mixer_scarlett.c |  4 +--
- sound/usb/power.c          |  3 +-
- sound/usb/power.h          |  1 +
- sound/usb/stream.c         | 21 ++++++++-----
- sound/usb/usbaudio.h       | 12 ++++++++
- 12 files changed, 127 insertions(+), 47 deletions(-)
-
-diff --git a/sound/usb/card.c b/sound/usb/card.c
-index bdb04fa37a71d..778de9244f1e7 100644
---- a/sound/usb/card.c
-+++ b/sound/usb/card.c
-@@ -206,6 +206,8 @@ static int snd_usb_create_stream(struct snd_usb_audio *chip, int ctrlif, int int
-               return -EINVAL;
-       }
-+      snd_usb_add_ctrl_interface_link(chip, interface, ctrlif);
-+
-       if (! snd_usb_parse_audio_interface(chip, interface)) {
-               usb_set_interface(dev, interface, 0); /* reset the current interface */
-               return usb_driver_claim_interface(&usb_audio_driver, iface,
-diff --git a/sound/usb/clock.c b/sound/usb/clock.c
-index 60fcb872a80b6..8f85200292f3f 100644
---- a/sound/usb/clock.c
-+++ b/sound/usb/clock.c
-@@ -76,11 +76,14 @@ static bool validate_clock_multiplier(void *p, int id, int proto)
- }
- #define DEFINE_FIND_HELPER(name, obj, validator, type2, type3)                \
--static obj *name(struct snd_usb_audio *chip, int id, int proto)       \
-+static obj *name(struct snd_usb_audio *chip, int id,  \
-+                              const struct audioformat *fmt)  \
- {                                                                     \
--      return find_uac_clock_desc(chip->ctrl_intf, id, validator,      \
--                                 proto == UAC_VERSION_3 ? (type3) : (type2), \
--                                 proto);                              \
-+      struct usb_host_interface *ctrl_intf =  \
-+              snd_usb_find_ctrl_interface(chip, fmt->iface); \
-+      return find_uac_clock_desc(ctrl_intf, id, validator,    \
-+                                 fmt->protocol == UAC_VERSION_3 ? (type3) : (type2), \
-+                                 fmt->protocol);                              \
- }
- DEFINE_FIND_HELPER(snd_usb_find_clock_source,
-@@ -93,16 +96,19 @@ DEFINE_FIND_HELPER(snd_usb_find_clock_multiplier,
-                  union uac23_clock_multiplier_desc, validate_clock_multiplier,
-                  UAC2_CLOCK_MULTIPLIER, UAC3_CLOCK_MULTIPLIER);
--static int uac_clock_selector_get_val(struct snd_usb_audio *chip, int selector_id)
-+static int uac_clock_selector_get_val(struct snd_usb_audio *chip,
-+                              int selector_id, int iface_no)
- {
-+      struct usb_host_interface *ctrl_intf;
-       unsigned char buf;
-       int ret;
-+      ctrl_intf = snd_usb_find_ctrl_interface(chip, iface_no);
-       ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0),
-                             UAC2_CS_CUR,
-                             USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-                             UAC2_CX_CLOCK_SELECTOR << 8,
--                            snd_usb_ctrl_intf(chip) | (selector_id << 8),
-+                            snd_usb_ctrl_intf(ctrl_intf) | (selector_id << 8),
-                             &buf, sizeof(buf));
-       if (ret < 0)
-@@ -111,16 +117,18 @@ static int uac_clock_selector_get_val(struct snd_usb_audio *chip, int selector_i
-       return buf;
- }
--static int uac_clock_selector_set_val(struct snd_usb_audio *chip, int selector_id,
--                                      unsigned char pin)
-+static int uac_clock_selector_set_val(struct snd_usb_audio *chip,
-+                                      int selector_id, unsigned char pin, int iface_no)
- {
-+      struct usb_host_interface *ctrl_intf;
-       int ret;
-+      ctrl_intf = snd_usb_find_ctrl_interface(chip, iface_no);
-       ret = snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0),
-                             UAC2_CS_CUR,
-                             USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
-                             UAC2_CX_CLOCK_SELECTOR << 8,
--                            snd_usb_ctrl_intf(chip) | (selector_id << 8),
-+                            snd_usb_ctrl_intf(ctrl_intf) | (selector_id << 8),
-                             &pin, sizeof(pin));
-       if (ret < 0)
-               return ret;
-@@ -132,7 +140,7 @@ static int uac_clock_selector_set_val(struct snd_usb_audio *chip, int selector_i
-               return -EINVAL;
-       }
--      ret = uac_clock_selector_get_val(chip, selector_id);
-+      ret = uac_clock_selector_get_val(chip, selector_id, iface_no);
-       if (ret < 0)
-               return ret;
-@@ -155,8 +163,10 @@ static bool uac_clock_source_is_valid_quirk(struct snd_usb_audio *chip,
-       unsigned char data;
-       struct usb_device *dev = chip->dev;
-       union uac23_clock_source_desc *cs_desc;
-+      struct usb_host_interface *ctrl_intf;
--      cs_desc = snd_usb_find_clock_source(chip, source_id, fmt->protocol);
-+      ctrl_intf = snd_usb_find_ctrl_interface(chip, fmt->iface);
-+      cs_desc = snd_usb_find_clock_source(chip, source_id, fmt);
-       if (!cs_desc)
-               return false;
-@@ -191,7 +201,7 @@ static bool uac_clock_source_is_valid_quirk(struct snd_usb_audio *chip,
-                       err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
-                                             USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
-                                             UAC2_CS_CONTROL_CLOCK_VALID << 8,
--                                            snd_usb_ctrl_intf(chip) | (source_id << 8),
-+                                            snd_usb_ctrl_intf(ctrl_intf) | (source_id << 8),
-                                             &data, sizeof(data));
-                       if (err < 0) {
-                               dev_warn(&dev->dev,
-@@ -217,8 +227,10 @@ static bool uac_clock_source_is_valid(struct snd_usb_audio *chip,
-       struct usb_device *dev = chip->dev;
-       u32 bmControls;
-       union uac23_clock_source_desc *cs_desc;
-+      struct usb_host_interface *ctrl_intf;
--      cs_desc = snd_usb_find_clock_source(chip, source_id, fmt->protocol);
-+      ctrl_intf = snd_usb_find_ctrl_interface(chip, fmt->iface);
-+      cs_desc = snd_usb_find_clock_source(chip, source_id, fmt);
-       if (!cs_desc)
-               return false;
-@@ -235,7 +247,7 @@ static bool uac_clock_source_is_valid(struct snd_usb_audio *chip,
-       err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
-                             USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
-                             UAC2_CS_CONTROL_CLOCK_VALID << 8,
--                            snd_usb_ctrl_intf(chip) | (source_id << 8),
-+                            snd_usb_ctrl_intf(ctrl_intf) | (source_id << 8),
-                             &data, sizeof(data));
-       if (err < 0) {
-@@ -274,7 +286,7 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
-       }
-       /* first, see if the ID we're looking at is a clock source already */
--      source = snd_usb_find_clock_source(chip, entity_id, proto);
-+      source = snd_usb_find_clock_source(chip, entity_id, fmt);
-       if (source) {
-               entity_id = GET_VAL(source, proto, bClockID);
-               if (validate && !uac_clock_source_is_valid(chip, fmt,
-@@ -287,7 +299,7 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
-               return entity_id;
-       }
--      selector = snd_usb_find_clock_selector(chip, entity_id, proto);
-+      selector = snd_usb_find_clock_selector(chip, entity_id, fmt);
-       if (selector) {
-               pins = GET_VAL(selector, proto, bNrInPins);
-               clock_id = GET_VAL(selector, proto, bClockID);
-@@ -317,7 +329,7 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
-               /* the entity ID we are looking at is a selector.
-                * find out what it currently selects */
--              ret = uac_clock_selector_get_val(chip, clock_id);
-+              ret = uac_clock_selector_get_val(chip, clock_id, fmt->iface);
-               if (ret < 0) {
-                       if (!chip->autoclock)
-                               return ret;
-@@ -346,7 +358,7 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
-                       if (chip->quirk_flags & QUIRK_FLAG_SKIP_CLOCK_SELECTOR ||
-                           !writeable)
-                               return ret;
--                      err = uac_clock_selector_set_val(chip, entity_id, cur);
-+                      err = uac_clock_selector_set_val(chip, entity_id, cur, fmt->iface);
-                       if (err < 0) {
-                               if (pins == 1) {
-                                       usb_audio_dbg(chip,
-@@ -377,7 +389,7 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
-                       if (ret < 0)
-                               continue;
--                      err = uac_clock_selector_set_val(chip, entity_id, i);
-+                      err = uac_clock_selector_set_val(chip, entity_id, i, fmt->iface);
-                       if (err < 0)
-                               continue;
-@@ -391,7 +403,7 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
-       }
-       /* FIXME: multipliers only act as pass-thru element for now */
--      multiplier = snd_usb_find_clock_multiplier(chip, entity_id, proto);
-+      multiplier = snd_usb_find_clock_multiplier(chip, entity_id, fmt);
-       if (multiplier)
-               return __uac_clock_find_source(chip, fmt,
-                                              GET_VAL(multiplier, proto, bCSourceID),
-@@ -491,11 +503,13 @@ static int get_sample_rate_v2v3(struct snd_usb_audio *chip, int iface,
-       struct usb_device *dev = chip->dev;
-       __le32 data;
-       int err;
-+      struct usb_host_interface *ctrl_intf;
-+      ctrl_intf = snd_usb_find_ctrl_interface(chip, iface);
-       err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
-                             USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
-                             UAC2_CS_CONTROL_SAM_FREQ << 8,
--                            snd_usb_ctrl_intf(chip) | (clock << 8),
-+                            snd_usb_ctrl_intf(ctrl_intf) | (clock << 8),
-                             &data, sizeof(data));
-       if (err < 0) {
-               dev_warn(&dev->dev, "%d:%d: cannot get freq (v2/v3): err %d\n",
-@@ -524,8 +538,10 @@ int snd_usb_set_sample_rate_v2v3(struct snd_usb_audio *chip,
-       __le32 data;
-       int err;
-       union uac23_clock_source_desc *cs_desc;
-+      struct usb_host_interface *ctrl_intf;
--      cs_desc = snd_usb_find_clock_source(chip, clock, fmt->protocol);
-+      ctrl_intf = snd_usb_find_ctrl_interface(chip, fmt->iface);
-+      cs_desc = snd_usb_find_clock_source(chip, clock, fmt);
-       if (!cs_desc)
-               return 0;
-@@ -544,7 +560,7 @@ int snd_usb_set_sample_rate_v2v3(struct snd_usb_audio *chip,
-       err = snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0), UAC2_CS_CUR,
-                             USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
-                             UAC2_CS_CONTROL_SAM_FREQ << 8,
--                            snd_usb_ctrl_intf(chip) | (clock << 8),
-+                            snd_usb_ctrl_intf(ctrl_intf) | (clock << 8),
-                             &data, sizeof(data));
-       if (err < 0)
-               return err;
-diff --git a/sound/usb/format.c b/sound/usb/format.c
-index 1bb6a455a1b46..0cbf1d4fbe6ed 100644
---- a/sound/usb/format.c
-+++ b/sound/usb/format.c
-@@ -545,7 +545,9 @@ static int parse_audio_format_rates_v2v3(struct snd_usb_audio *chip,
-       unsigned char tmp[2], *data;
-       int nr_triplets, data_size, ret = 0, ret_l6;
-       int clock = snd_usb_clock_find_source(chip, fp, false);
-+      struct usb_host_interface *ctrl_intf;
-+      ctrl_intf = snd_usb_find_ctrl_interface(chip, fp->iface);
-       if (clock < 0) {
-               dev_err(&dev->dev,
-                       "%s(): unable to find clock source (clock %d)\n",
-@@ -557,7 +559,7 @@ static int parse_audio_format_rates_v2v3(struct snd_usb_audio *chip,
-       ret = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_RANGE,
-                             USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
-                             UAC2_CS_CONTROL_SAM_FREQ << 8,
--                            snd_usb_ctrl_intf(chip) | (clock << 8),
-+                            snd_usb_ctrl_intf(ctrl_intf) | (clock << 8),
-                             tmp, sizeof(tmp));
-       if (ret < 0) {
-@@ -592,7 +594,7 @@ static int parse_audio_format_rates_v2v3(struct snd_usb_audio *chip,
-       ret = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_RANGE,
-                             USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
-                             UAC2_CS_CONTROL_SAM_FREQ << 8,
--                            snd_usb_ctrl_intf(chip) | (clock << 8),
-+                            snd_usb_ctrl_intf(ctrl_intf) | (clock << 8),
-                             data, data_size);
-       if (ret < 0) {
-diff --git a/sound/usb/helper.c b/sound/usb/helper.c
-index bf80e55d013a8..72b671fb2c84c 100644
---- a/sound/usb/helper.c
-+++ b/sound/usb/helper.c
-@@ -130,3 +130,37 @@ snd_usb_get_host_interface(struct snd_usb_audio *chip, int ifnum, int altsetting
-               return NULL;
-       return usb_altnum_to_altsetting(iface, altsetting);
- }
-+
-+int snd_usb_add_ctrl_interface_link(struct snd_usb_audio *chip, int ifnum,
-+              int ctrlif)
-+{
-+      struct usb_device *dev = chip->dev;
-+      struct usb_host_interface *host_iface;
-+
-+      if (chip->num_intf_to_ctrl >= MAX_CARD_INTERFACES) {
-+              dev_info(&dev->dev, "Too many interfaces assigned to the single USB-audio card\n");
-+              return -EINVAL;
-+      }
-+
-+      /* find audiocontrol interface */
-+      host_iface = &usb_ifnum_to_if(dev, ctrlif)->altsetting[0];
-+
-+      chip->intf_to_ctrl[chip->num_intf_to_ctrl].interface = ifnum;
-+      chip->intf_to_ctrl[chip->num_intf_to_ctrl].ctrl_intf = host_iface;
-+      chip->num_intf_to_ctrl++;
-+
-+      return 0;
-+}
-+
-+struct usb_host_interface *snd_usb_find_ctrl_interface(struct snd_usb_audio *chip,
-+                                                      int ifnum)
-+{
-+      int i;
-+
-+      for (i = 0; i < chip->num_intf_to_ctrl; ++i)
-+              if (chip->intf_to_ctrl[i].interface == ifnum)
-+                      return chip->intf_to_ctrl[i].ctrl_intf;
-+
-+      /* Fallback to first audiocontrol interface */
-+      return chip->ctrl_intf;
-+}
-diff --git a/sound/usb/helper.h b/sound/usb/helper.h
-index e2b51ec96ec62..0372e050b3dc4 100644
---- a/sound/usb/helper.h
-+++ b/sound/usb/helper.h
-@@ -17,6 +17,12 @@ unsigned char snd_usb_parse_datainterval(struct snd_usb_audio *chip,
- struct usb_host_interface *
- snd_usb_get_host_interface(struct snd_usb_audio *chip, int ifnum, int altsetting);
-+int snd_usb_add_ctrl_interface_link(struct snd_usb_audio *chip, int ifnum,
-+              int ctrlif);
-+
-+struct usb_host_interface *snd_usb_find_ctrl_interface(struct snd_usb_audio *chip,
-+                                                              int ifnum);
-+
- /*
-  * retrieve usb_interface descriptor from the host interface
-  * (conditional for compatibility with the older API)
-@@ -28,9 +34,9 @@ snd_usb_get_host_interface(struct snd_usb_audio *chip, int ifnum, int altsetting
- #define snd_usb_get_speed(dev) ((dev)->speed)
--static inline int snd_usb_ctrl_intf(struct snd_usb_audio *chip)
-+static inline int snd_usb_ctrl_intf(struct usb_host_interface *ctrl_intf)
- {
--      return get_iface_desc(chip->ctrl_intf)->bInterfaceNumber;
-+      return get_iface_desc(ctrl_intf)->bInterfaceNumber;
- }
- /* in validate.c */
-diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
-index 2d27d729c3bea..9945ae55b0d08 100644
---- a/sound/usb/mixer.c
-+++ b/sound/usb/mixer.c
-@@ -728,7 +728,7 @@ static int get_cluster_channels_v3(struct mixer_build *state, unsigned int clust
-                       UAC3_CS_REQ_HIGH_CAPABILITY_DESCRIPTOR,
-                       USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-                       cluster_id,
--                      snd_usb_ctrl_intf(state->chip),
-+                      snd_usb_ctrl_intf(state->mixer->hostif),
-                       &c_header, sizeof(c_header));
-       if (err < 0)
-               goto error;
-diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
-index 2bc344cf54a83..8cbfb65846047 100644
---- a/sound/usb/mixer_quirks.c
-+++ b/sound/usb/mixer_quirks.c
-@@ -1043,7 +1043,7 @@ static int snd_ftu_eff_switch_init(struct usb_mixer_interface *mixer,
-       err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC_GET_CUR,
-                             USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-                             pval & 0xff00,
--                            snd_usb_ctrl_intf(mixer->chip) | ((pval & 0xff) << 8),
-+                            snd_usb_ctrl_intf(mixer->hostif) | ((pval & 0xff) << 8),
-                             value, 2);
-       if (err < 0)
-               return err;
-@@ -1077,7 +1077,7 @@ static int snd_ftu_eff_switch_update(struct usb_mixer_elem_list *list)
-                             UAC_SET_CUR,
-                             USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
-                             pval & 0xff00,
--                            snd_usb_ctrl_intf(chip) | ((pval & 0xff) << 8),
-+                            snd_usb_ctrl_intf(list->mixer->hostif) | ((pval & 0xff) << 8),
-                             value, 2);
-       snd_usb_unlock_shutdown(chip);
-       return err;
-@@ -2115,24 +2115,25 @@ static int dell_dock_mixer_create(struct usb_mixer_interface *mixer)
-       return 0;
- }
--static void dell_dock_init_vol(struct snd_usb_audio *chip, int ch, int id)
-+static void dell_dock_init_vol(struct usb_mixer_interface *mixer, int ch, int id)
- {
-+      struct snd_usb_audio *chip = mixer->chip;
-       u16 buf = 0;
-       snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0), UAC_SET_CUR,
-                       USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
-                       (UAC_FU_VOLUME << 8) | ch,
--                      snd_usb_ctrl_intf(chip) | (id << 8),
-+                      snd_usb_ctrl_intf(mixer->hostif) | (id << 8),
-                       &buf, 2);
- }
- static int dell_dock_mixer_init(struct usb_mixer_interface *mixer)
- {
-       /* fix to 0dB playback volumes */
--      dell_dock_init_vol(mixer->chip, 1, 16);
--      dell_dock_init_vol(mixer->chip, 2, 16);
--      dell_dock_init_vol(mixer->chip, 1, 19);
--      dell_dock_init_vol(mixer->chip, 2, 19);
-+      dell_dock_init_vol(mixer, 1, 16);
-+      dell_dock_init_vol(mixer, 2, 16);
-+      dell_dock_init_vol(mixer, 1, 19);
-+      dell_dock_init_vol(mixer, 2, 19);
-       return 0;
- }
-diff --git a/sound/usb/mixer_scarlett.c b/sound/usb/mixer_scarlett.c
-index 0d6e4f15bf77c..ff548041679bb 100644
---- a/sound/usb/mixer_scarlett.c
-+++ b/sound/usb/mixer_scarlett.c
-@@ -460,7 +460,7 @@ static int scarlett_ctl_meter_get(struct snd_kcontrol *kctl,
-       struct snd_usb_audio *chip = elem->head.mixer->chip;
-       unsigned char buf[2 * MAX_CHANNELS] = {0, };
-       int wValue = (elem->control << 8) | elem->idx_off;
--      int idx = snd_usb_ctrl_intf(chip) | (elem->head.id << 8);
-+      int idx = snd_usb_ctrl_intf(elem->head.mixer->hostif) | (elem->head.id << 8);
-       int err;
-       err = snd_usb_ctl_msg(chip->dev,
-@@ -1002,7 +1002,7 @@ int snd_scarlett_controls_create(struct usb_mixer_interface *mixer)
-       err = snd_usb_ctl_msg(mixer->chip->dev,
-               usb_sndctrlpipe(mixer->chip->dev, 0), UAC2_CS_CUR,
-               USB_RECIP_INTERFACE | USB_TYPE_CLASS |
--              USB_DIR_OUT, 0x0100, snd_usb_ctrl_intf(mixer->chip) |
-+              USB_DIR_OUT, 0x0100, snd_usb_ctrl_intf(mixer->hostif) |
-               (0x29 << 8), sample_rate_buffer, 4);
-       if (err < 0)
-               return err;
-diff --git a/sound/usb/power.c b/sound/usb/power.c
-index 606a2cb23eab6..66bd4daa68fd5 100644
---- a/sound/usb/power.c
-+++ b/sound/usb/power.c
-@@ -40,6 +40,7 @@ snd_usb_find_power_domain(struct usb_host_interface *ctrl_iface,
-                                       le16_to_cpu(pd_desc->waRecoveryTime1);
-                               pd->pd_d2d0_rec =
-                                       le16_to_cpu(pd_desc->waRecoveryTime2);
-+                              pd->ctrl_iface = ctrl_iface;
-                               return pd;
-                       }
-               }
-@@ -57,7 +58,7 @@ int snd_usb_power_domain_set(struct snd_usb_audio *chip,
-       unsigned char current_state;
-       int err, idx;
--      idx = snd_usb_ctrl_intf(chip) | (pd->pd_id << 8);
-+      idx = snd_usb_ctrl_intf(pd->ctrl_iface) | (pd->pd_id << 8);
-       err = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0),
-                             UAC2_CS_CUR,
-diff --git a/sound/usb/power.h b/sound/usb/power.h
-index 396e3e51440a7..1fa92ad0ca925 100644
---- a/sound/usb/power.h
-+++ b/sound/usb/power.h
-@@ -6,6 +6,7 @@ struct snd_usb_power_domain {
-       int pd_id;              /* UAC3 Power Domain ID */
-       int pd_d1d0_rec;        /* D1 to D0 recovery time */
-       int pd_d2d0_rec;        /* D2 to D0 recovery time */
-+      struct usb_host_interface *ctrl_iface; /* Control interface */
- };
- enum {
-diff --git a/sound/usb/stream.c b/sound/usb/stream.c
-index e14c725acebf2..d70c140813d68 100644
---- a/sound/usb/stream.c
-+++ b/sound/usb/stream.c
-@@ -713,10 +713,13 @@ snd_usb_get_audioformat_uac12(struct snd_usb_audio *chip,
-       struct usb_device *dev = chip->dev;
-       struct uac_format_type_i_continuous_descriptor *fmt;
-       unsigned int num_channels = 0, chconfig = 0;
-+      struct usb_host_interface *ctrl_intf;
-       struct audioformat *fp;
-       int clock = 0;
-       u64 format;
-+      ctrl_intf = snd_usb_find_ctrl_interface(chip, iface_no);
-+
-       /* get audio formats */
-       if (protocol == UAC_VERSION_1) {
-               struct uac1_as_header_descriptor *as =
-@@ -740,7 +743,7 @@ snd_usb_get_audioformat_uac12(struct snd_usb_audio *chip,
-               format = le16_to_cpu(as->wFormatTag); /* remember the format value */
--              iterm = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
-+              iterm = snd_usb_find_input_terminal_descriptor(ctrl_intf,
-                                                              as->bTerminalLink,
-                                                              protocol);
-               if (iterm) {
-@@ -776,7 +779,7 @@ snd_usb_get_audioformat_uac12(struct snd_usb_audio *chip,
-                * lookup the terminal associated to this interface
-                * to extract the clock
-                */
--              input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
-+              input_term = snd_usb_find_input_terminal_descriptor(ctrl_intf,
-                                                                   as->bTerminalLink,
-                                                                   protocol);
-               if (input_term) {
-@@ -786,7 +789,7 @@ snd_usb_get_audioformat_uac12(struct snd_usb_audio *chip,
-                       goto found_clock;
-               }
--              output_term = snd_usb_find_output_terminal_descriptor(chip->ctrl_intf,
-+              output_term = snd_usb_find_output_terminal_descriptor(ctrl_intf,
-                                                                     as->bTerminalLink,
-                                                                     protocol);
-               if (output_term) {
-@@ -870,6 +873,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,
-       struct uac3_cluster_header_descriptor *cluster;
-       struct uac3_as_header_descriptor *as = NULL;
-       struct uac3_hc_descriptor_header hc_header;
-+      struct usb_host_interface *ctrl_intf;
-       struct snd_pcm_chmap_elem *chmap;
-       struct snd_usb_power_domain *pd;
-       unsigned char badd_profile;
-@@ -881,6 +885,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,
-       int err;
-       badd_profile = chip->badd_profile;
-+      ctrl_intf = snd_usb_find_ctrl_interface(chip, iface_no);
-       if (badd_profile >= UAC3_FUNCTION_SUBCLASS_GENERIC_IO) {
-               unsigned int maxpacksize =
-@@ -966,7 +971,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,
-                       UAC3_CS_REQ_HIGH_CAPABILITY_DESCRIPTOR,
-                       USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-                       cluster_id,
--                      snd_usb_ctrl_intf(chip),
-+                      snd_usb_ctrl_intf(ctrl_intf),
-                       &hc_header, sizeof(hc_header));
-       if (err < 0)
-               return ERR_PTR(err);
-@@ -990,7 +995,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,
-                       UAC3_CS_REQ_HIGH_CAPABILITY_DESCRIPTOR,
-                       USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-                       cluster_id,
--                      snd_usb_ctrl_intf(chip),
-+                      snd_usb_ctrl_intf(ctrl_intf),
-                       cluster, wLength);
-       if (err < 0) {
-               kfree(cluster);
-@@ -1011,7 +1016,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,
-        * lookup the terminal associated to this interface
-        * to extract the clock
-        */
--      input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
-+      input_term = snd_usb_find_input_terminal_descriptor(ctrl_intf,
-                                                           as->bTerminalLink,
-                                                           UAC_VERSION_3);
-       if (input_term) {
-@@ -1019,7 +1024,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,
-               goto found_clock;
-       }
--      output_term = snd_usb_find_output_terminal_descriptor(chip->ctrl_intf,
-+      output_term = snd_usb_find_output_terminal_descriptor(ctrl_intf,
-                                                             as->bTerminalLink,
-                                                             UAC_VERSION_3);
-       if (output_term) {
-@@ -1068,7 +1073,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,
-                                                              UAC_VERSION_3,
-                                                              iface_no);
--              pd = snd_usb_find_power_domain(chip->ctrl_intf,
-+              pd = snd_usb_find_power_domain(ctrl_intf,
-                                              as->bTerminalLink);
-               /* ok, let's parse further... */
-diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
-index 43d4029edab46..b0f042c996087 100644
---- a/sound/usb/usbaudio.h
-+++ b/sound/usb/usbaudio.h
-@@ -21,6 +21,15 @@ struct media_intf_devnode;
- #define MAX_CARD_INTERFACES   16
-+/*
-+ * Structure holding assosiation between Audio Control Interface
-+ * and given Streaming or Midi Interface.
-+ */
-+struct snd_intf_to_ctrl {
-+      u8 interface;
-+      struct usb_host_interface *ctrl_intf;
-+};
-+
- struct snd_usb_audio {
-       int index;
-       struct usb_device *dev;
-@@ -63,6 +72,9 @@ struct snd_usb_audio {
-       struct usb_host_interface *ctrl_intf;   /* the audio control interface */
-       struct media_device *media_dev;
-       struct media_intf_devnode *ctl_intf_media_devnode;
-+
-+      unsigned int num_intf_to_ctrl;
-+      struct snd_intf_to_ctrl intf_to_ctrl[MAX_CARD_INTERFACES];
- };
- #define USB_AUDIO_IFACE_UNUSED        ((void *)-1L)
--- 
-2.43.0
-
index a16857c4bf8b64e0b8a7d2b082e33cb13eef5123..b03622ac60d51e506f762757019d542e170a4e61 100644 (file)
@@ -165,7 +165,6 @@ nfp-use-irqf_no_autoen-flag-in-request_irq.patch
 alsa-usb-audio-add-input-value-sanity-checks-for-sta.patch
 x86-ioapic-handle-allocation-failures-gracefully.patch
 x86-apic-remove-logical-destination-mode-for-64-bit.patch
-alsa-usb-audio-support-multiple-control-interfaces.patch
 alsa-usb-audio-define-macros-for-quirk-table-entries.patch
 alsa-usb-audio-replace-complex-quirk-lines-with-macr.patch
 alsa-usb-audio-add-quirk-for-rme-digiface-usb.patch
index 1706792127dedbbe7ab90a8580c7527136ecebe3..1f7f597ac06dbf7931140edfbc033e8150887b2b 100644 (file)
@@ -15,14 +15,12 @@ Link: https://patch.msgid.link/20240912152635.1859737-1-joshuapius@google.com
 Signed-off-by: Takashi Iwai <tiwai@suse.de>
 Signed-off-by: Sasha Levin <sashal@kernel.org>
 ---
- sound/usb/card.c | 6 ++++++
+ sound/usb/card.c |    6 ++++++
  1 file changed, 6 insertions(+)
 
-diff --git a/sound/usb/card.c b/sound/usb/card.c
-index 7c98cc831b8d9..753fb47d25913 100644
 --- a/sound/usb/card.c
 +++ b/sound/usb/card.c
-@@ -384,6 +384,12 @@ static const struct usb_audio_device_name usb_audio_names[] = {
+@@ -382,6 +382,12 @@ static const struct usb_audio_device_nam
        /* Creative/Toshiba Multimedia Center SB-0500 */
        DEVICE_NAME(0x041e, 0x3048, "Toshiba", "SB-0500"),
  
@@ -35,6 +33,3 @@ index 7c98cc831b8d9..753fb47d25913 100644
        DEVICE_NAME(0x046d, 0x0990, "Logitech, Inc.", "QuickCam Pro 9000"),
  
        DEVICE_NAME(0x05e1, 0x0408, "Syntek", "STK1160"),
--- 
-2.43.0
-
diff --git a/queue-6.6/alsa-usb-audio-support-multiple-control-interfaces.patch b/queue-6.6/alsa-usb-audio-support-multiple-control-interfaces.patch
deleted file mode 100644 (file)
index 811d448..0000000
+++ /dev/null
@@ -1,659 +0,0 @@
-From 4e61357fcd14afe57ede4e02ad249cf7763f3afb Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Sun, 11 Aug 2024 17:29:56 -0700
-Subject: ALSA: usb-audio: Support multiple control interfaces
-
-From: Karol Kosik <k.kosik@outlook.com>
-
-[ Upstream commit 6aa8700150f7dc62f60b4cf5b1624e2e3d9ed78e ]
-
-Registering Numark Party Mix II fails with error 'bogus bTerminalLink 1'.
-The problem stems from the driver not being able to find input/output
-terminals required to configure audio streaming. The information about
-those terminals is stored in AudioControl Interface. Numark device
-contains 2 AudioControl Interfaces and the driver checks only one of them.
-
-According to the USB standard, a device can have multiple audio functions,
-each represented by Audio Interface Collection. Every audio function is
-considered to be closed box and will contain unique AudioControl Interface
-and zero or more AudioStreaming and MIDIStreaming Interfaces.
-
-The Numark device adheres to the standard and defines two audio functions:
-- MIDIStreaming function
-- AudioStreaming function
-It starts with MIDI function, followed by the audio function. The driver
-saves the first AudioControl Interface in `snd_usb_audio` structure
-associated with the entire device. It then attempts to use this interface
-to query for terminals and clocks. However, this fails because the correct
-information is stored in the second AudioControl Interface, defined in the
-second Audio Interface Collection.
-
-This patch introduces a structure holding association between each
-MIDI/Audio Interface and its corresponding AudioControl Interface,
-instead of relying on AudioControl Interface defined for the entire
-device. This structure is populated during usb probing phase and leveraged
-later when querying for terminals and when sending USB requests.
-
-Alternative solutions considered include:
-- defining a quirk for Numark where the order of interface is manually
-changed, or terminals are hardcoded in the driver. This solution would
-have fixed only this model, though it seems that device is USB compliant,
-and it also seems that other devices from this company may be affected.
-What's more, it looks like products from other manufacturers have similar
-problems, i.e. Rane One DJ console
-- keeping a list of all AudioControl Interfaces and querying all of them
-to find required information. That would have solved my problem and have
-low probability of breaking other devices, as we would always start with
-the same logic of querying first AudioControl Interface. This solution
-would not have followed the standard though.
-
-This patch preserves the `snd_usb_audio.ctrl_intf` variable, which holds
-the first AudioControl Interface, and uses it as a fallback when some
-interfaces are not parsed correctly and lack an associated AudioControl
-Interface, i.e., when configured via quirks.
-
-Link: https://bugzilla.kernel.org/show_bug.cgi?id=217865
-Signed-off-by: Karol Kosik <k.kosik@outlook.com>
-Link: https://patch.msgid.link/AS8P190MB1285893F4735C8B32AD3886BEC852@AS8P190MB1285.EURP190.PROD.OUTLOOK.COM
-Signed-off-by: Takashi Iwai <tiwai@suse.de>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- sound/usb/card.c           |  2 ++
- sound/usb/clock.c          | 62 ++++++++++++++++++++++++--------------
- sound/usb/format.c         |  6 ++--
- sound/usb/helper.c         | 34 +++++++++++++++++++++
- sound/usb/helper.h         | 10 ++++--
- sound/usb/mixer.c          |  2 +-
- sound/usb/mixer_quirks.c   | 17 ++++++-----
- sound/usb/mixer_scarlett.c |  4 +--
- sound/usb/power.c          |  3 +-
- sound/usb/power.h          |  1 +
- sound/usb/stream.c         | 21 ++++++++-----
- sound/usb/usbaudio.h       | 12 ++++++++
- 12 files changed, 127 insertions(+), 47 deletions(-)
-
-diff --git a/sound/usb/card.c b/sound/usb/card.c
-index 1b2edc0fd2e99..7c98cc831b8d9 100644
---- a/sound/usb/card.c
-+++ b/sound/usb/card.c
-@@ -206,6 +206,8 @@ static int snd_usb_create_stream(struct snd_usb_audio *chip, int ctrlif, int int
-               return -EINVAL;
-       }
-+      snd_usb_add_ctrl_interface_link(chip, interface, ctrlif);
-+
-       if (! snd_usb_parse_audio_interface(chip, interface)) {
-               usb_set_interface(dev, interface, 0); /* reset the current interface */
-               return usb_driver_claim_interface(&usb_audio_driver, iface,
-diff --git a/sound/usb/clock.c b/sound/usb/clock.c
-index a676ad093d189..6f0693c428b0b 100644
---- a/sound/usb/clock.c
-+++ b/sound/usb/clock.c
-@@ -76,11 +76,14 @@ static bool validate_clock_multiplier(void *p, int id, int proto)
- }
- #define DEFINE_FIND_HELPER(name, obj, validator, type2, type3)                \
--static obj *name(struct snd_usb_audio *chip, int id, int proto)       \
-+static obj *name(struct snd_usb_audio *chip, int id,  \
-+                              const struct audioformat *fmt)  \
- {                                                                     \
--      return find_uac_clock_desc(chip->ctrl_intf, id, validator,      \
--                                 proto == UAC_VERSION_3 ? (type3) : (type2), \
--                                 proto);                              \
-+      struct usb_host_interface *ctrl_intf =  \
-+              snd_usb_find_ctrl_interface(chip, fmt->iface); \
-+      return find_uac_clock_desc(ctrl_intf, id, validator,    \
-+                                 fmt->protocol == UAC_VERSION_3 ? (type3) : (type2), \
-+                                 fmt->protocol);                              \
- }
- DEFINE_FIND_HELPER(snd_usb_find_clock_source,
-@@ -93,16 +96,19 @@ DEFINE_FIND_HELPER(snd_usb_find_clock_multiplier,
-                  union uac23_clock_multiplier_desc, validate_clock_multiplier,
-                  UAC2_CLOCK_MULTIPLIER, UAC3_CLOCK_MULTIPLIER);
--static int uac_clock_selector_get_val(struct snd_usb_audio *chip, int selector_id)
-+static int uac_clock_selector_get_val(struct snd_usb_audio *chip,
-+                              int selector_id, int iface_no)
- {
-+      struct usb_host_interface *ctrl_intf;
-       unsigned char buf;
-       int ret;
-+      ctrl_intf = snd_usb_find_ctrl_interface(chip, iface_no);
-       ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0),
-                             UAC2_CS_CUR,
-                             USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-                             UAC2_CX_CLOCK_SELECTOR << 8,
--                            snd_usb_ctrl_intf(chip) | (selector_id << 8),
-+                            snd_usb_ctrl_intf(ctrl_intf) | (selector_id << 8),
-                             &buf, sizeof(buf));
-       if (ret < 0)
-@@ -111,16 +117,18 @@ static int uac_clock_selector_get_val(struct snd_usb_audio *chip, int selector_i
-       return buf;
- }
--static int uac_clock_selector_set_val(struct snd_usb_audio *chip, int selector_id,
--                                      unsigned char pin)
-+static int uac_clock_selector_set_val(struct snd_usb_audio *chip,
-+                                      int selector_id, unsigned char pin, int iface_no)
- {
-+      struct usb_host_interface *ctrl_intf;
-       int ret;
-+      ctrl_intf = snd_usb_find_ctrl_interface(chip, iface_no);
-       ret = snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0),
-                             UAC2_CS_CUR,
-                             USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
-                             UAC2_CX_CLOCK_SELECTOR << 8,
--                            snd_usb_ctrl_intf(chip) | (selector_id << 8),
-+                            snd_usb_ctrl_intf(ctrl_intf) | (selector_id << 8),
-                             &pin, sizeof(pin));
-       if (ret < 0)
-               return ret;
-@@ -132,7 +140,7 @@ static int uac_clock_selector_set_val(struct snd_usb_audio *chip, int selector_i
-               return -EINVAL;
-       }
--      ret = uac_clock_selector_get_val(chip, selector_id);
-+      ret = uac_clock_selector_get_val(chip, selector_id, iface_no);
-       if (ret < 0)
-               return ret;
-@@ -155,8 +163,10 @@ static bool uac_clock_source_is_valid_quirk(struct snd_usb_audio *chip,
-       unsigned char data;
-       struct usb_device *dev = chip->dev;
-       union uac23_clock_source_desc *cs_desc;
-+      struct usb_host_interface *ctrl_intf;
--      cs_desc = snd_usb_find_clock_source(chip, source_id, fmt->protocol);
-+      ctrl_intf = snd_usb_find_ctrl_interface(chip, fmt->iface);
-+      cs_desc = snd_usb_find_clock_source(chip, source_id, fmt);
-       if (!cs_desc)
-               return false;
-@@ -191,7 +201,7 @@ static bool uac_clock_source_is_valid_quirk(struct snd_usb_audio *chip,
-                       err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
-                                             USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
-                                             UAC2_CS_CONTROL_CLOCK_VALID << 8,
--                                            snd_usb_ctrl_intf(chip) | (source_id << 8),
-+                                            snd_usb_ctrl_intf(ctrl_intf) | (source_id << 8),
-                                             &data, sizeof(data));
-                       if (err < 0) {
-                               dev_warn(&dev->dev,
-@@ -217,8 +227,10 @@ static bool uac_clock_source_is_valid(struct snd_usb_audio *chip,
-       struct usb_device *dev = chip->dev;
-       u32 bmControls;
-       union uac23_clock_source_desc *cs_desc;
-+      struct usb_host_interface *ctrl_intf;
--      cs_desc = snd_usb_find_clock_source(chip, source_id, fmt->protocol);
-+      ctrl_intf = snd_usb_find_ctrl_interface(chip, fmt->iface);
-+      cs_desc = snd_usb_find_clock_source(chip, source_id, fmt);
-       if (!cs_desc)
-               return false;
-@@ -235,7 +247,7 @@ static bool uac_clock_source_is_valid(struct snd_usb_audio *chip,
-       err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
-                             USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
-                             UAC2_CS_CONTROL_CLOCK_VALID << 8,
--                            snd_usb_ctrl_intf(chip) | (source_id << 8),
-+                            snd_usb_ctrl_intf(ctrl_intf) | (source_id << 8),
-                             &data, sizeof(data));
-       if (err < 0) {
-@@ -272,7 +284,7 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
-       }
-       /* first, see if the ID we're looking at is a clock source already */
--      source = snd_usb_find_clock_source(chip, entity_id, proto);
-+      source = snd_usb_find_clock_source(chip, entity_id, fmt);
-       if (source) {
-               entity_id = GET_VAL(source, proto, bClockID);
-               if (validate && !uac_clock_source_is_valid(chip, fmt,
-@@ -285,7 +297,7 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
-               return entity_id;
-       }
--      selector = snd_usb_find_clock_selector(chip, entity_id, proto);
-+      selector = snd_usb_find_clock_selector(chip, entity_id, fmt);
-       if (selector) {
-               pins = GET_VAL(selector, proto, bNrInPins);
-               clock_id = GET_VAL(selector, proto, bClockID);
-@@ -299,7 +311,7 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
-               /* the entity ID we are looking at is a selector.
-                * find out what it currently selects */
--              ret = uac_clock_selector_get_val(chip, clock_id);
-+              ret = uac_clock_selector_get_val(chip, clock_id, fmt->iface);
-               if (ret < 0) {
-                       if (!chip->autoclock)
-                               return ret;
-@@ -327,7 +339,7 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
-                       /* Skip setting clock selector again for some devices */
-                       if (chip->quirk_flags & QUIRK_FLAG_SKIP_CLOCK_SELECTOR)
-                               return ret;
--                      err = uac_clock_selector_set_val(chip, entity_id, cur);
-+                      err = uac_clock_selector_set_val(chip, entity_id, cur, fmt->iface);
-                       if (err < 0) {
-                               if (pins == 1) {
-                                       usb_audio_dbg(chip,
-@@ -355,7 +367,7 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
-                       if (ret < 0)
-                               continue;
--                      err = uac_clock_selector_set_val(chip, entity_id, i);
-+                      err = uac_clock_selector_set_val(chip, entity_id, i, fmt->iface);
-                       if (err < 0)
-                               continue;
-@@ -369,7 +381,7 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
-       }
-       /* FIXME: multipliers only act as pass-thru element for now */
--      multiplier = snd_usb_find_clock_multiplier(chip, entity_id, proto);
-+      multiplier = snd_usb_find_clock_multiplier(chip, entity_id, fmt);
-       if (multiplier)
-               return __uac_clock_find_source(chip, fmt,
-                                              GET_VAL(multiplier, proto, bCSourceID),
-@@ -469,11 +481,13 @@ static int get_sample_rate_v2v3(struct snd_usb_audio *chip, int iface,
-       struct usb_device *dev = chip->dev;
-       __le32 data;
-       int err;
-+      struct usb_host_interface *ctrl_intf;
-+      ctrl_intf = snd_usb_find_ctrl_interface(chip, iface);
-       err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
-                             USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
-                             UAC2_CS_CONTROL_SAM_FREQ << 8,
--                            snd_usb_ctrl_intf(chip) | (clock << 8),
-+                            snd_usb_ctrl_intf(ctrl_intf) | (clock << 8),
-                             &data, sizeof(data));
-       if (err < 0) {
-               dev_warn(&dev->dev, "%d:%d: cannot get freq (v2/v3): err %d\n",
-@@ -502,8 +516,10 @@ int snd_usb_set_sample_rate_v2v3(struct snd_usb_audio *chip,
-       __le32 data;
-       int err;
-       union uac23_clock_source_desc *cs_desc;
-+      struct usb_host_interface *ctrl_intf;
--      cs_desc = snd_usb_find_clock_source(chip, clock, fmt->protocol);
-+      ctrl_intf = snd_usb_find_ctrl_interface(chip, fmt->iface);
-+      cs_desc = snd_usb_find_clock_source(chip, clock, fmt);
-       if (!cs_desc)
-               return 0;
-@@ -522,7 +538,7 @@ int snd_usb_set_sample_rate_v2v3(struct snd_usb_audio *chip,
-       err = snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0), UAC2_CS_CUR,
-                             USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
-                             UAC2_CS_CONTROL_SAM_FREQ << 8,
--                            snd_usb_ctrl_intf(chip) | (clock << 8),
-+                            snd_usb_ctrl_intf(ctrl_intf) | (clock << 8),
-                             &data, sizeof(data));
-       if (err < 0)
-               return err;
-diff --git a/sound/usb/format.c b/sound/usb/format.c
-index 3b45d0ee76938..61c4aca8be09e 100644
---- a/sound/usb/format.c
-+++ b/sound/usb/format.c
-@@ -548,7 +548,9 @@ static int parse_audio_format_rates_v2v3(struct snd_usb_audio *chip,
-       unsigned char tmp[2], *data;
-       int nr_triplets, data_size, ret = 0, ret_l6;
-       int clock = snd_usb_clock_find_source(chip, fp, false);
-+      struct usb_host_interface *ctrl_intf;
-+      ctrl_intf = snd_usb_find_ctrl_interface(chip, fp->iface);
-       if (clock < 0) {
-               dev_err(&dev->dev,
-                       "%s(): unable to find clock source (clock %d)\n",
-@@ -560,7 +562,7 @@ static int parse_audio_format_rates_v2v3(struct snd_usb_audio *chip,
-       ret = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_RANGE,
-                             USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
-                             UAC2_CS_CONTROL_SAM_FREQ << 8,
--                            snd_usb_ctrl_intf(chip) | (clock << 8),
-+                            snd_usb_ctrl_intf(ctrl_intf) | (clock << 8),
-                             tmp, sizeof(tmp));
-       if (ret < 0) {
-@@ -595,7 +597,7 @@ static int parse_audio_format_rates_v2v3(struct snd_usb_audio *chip,
-       ret = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_RANGE,
-                             USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
-                             UAC2_CS_CONTROL_SAM_FREQ << 8,
--                            snd_usb_ctrl_intf(chip) | (clock << 8),
-+                            snd_usb_ctrl_intf(ctrl_intf) | (clock << 8),
-                             data, data_size);
-       if (ret < 0) {
-diff --git a/sound/usb/helper.c b/sound/usb/helper.c
-index bf80e55d013a8..72b671fb2c84c 100644
---- a/sound/usb/helper.c
-+++ b/sound/usb/helper.c
-@@ -130,3 +130,37 @@ snd_usb_get_host_interface(struct snd_usb_audio *chip, int ifnum, int altsetting
-               return NULL;
-       return usb_altnum_to_altsetting(iface, altsetting);
- }
-+
-+int snd_usb_add_ctrl_interface_link(struct snd_usb_audio *chip, int ifnum,
-+              int ctrlif)
-+{
-+      struct usb_device *dev = chip->dev;
-+      struct usb_host_interface *host_iface;
-+
-+      if (chip->num_intf_to_ctrl >= MAX_CARD_INTERFACES) {
-+              dev_info(&dev->dev, "Too many interfaces assigned to the single USB-audio card\n");
-+              return -EINVAL;
-+      }
-+
-+      /* find audiocontrol interface */
-+      host_iface = &usb_ifnum_to_if(dev, ctrlif)->altsetting[0];
-+
-+      chip->intf_to_ctrl[chip->num_intf_to_ctrl].interface = ifnum;
-+      chip->intf_to_ctrl[chip->num_intf_to_ctrl].ctrl_intf = host_iface;
-+      chip->num_intf_to_ctrl++;
-+
-+      return 0;
-+}
-+
-+struct usb_host_interface *snd_usb_find_ctrl_interface(struct snd_usb_audio *chip,
-+                                                      int ifnum)
-+{
-+      int i;
-+
-+      for (i = 0; i < chip->num_intf_to_ctrl; ++i)
-+              if (chip->intf_to_ctrl[i].interface == ifnum)
-+                      return chip->intf_to_ctrl[i].ctrl_intf;
-+
-+      /* Fallback to first audiocontrol interface */
-+      return chip->ctrl_intf;
-+}
-diff --git a/sound/usb/helper.h b/sound/usb/helper.h
-index e2b51ec96ec62..0372e050b3dc4 100644
---- a/sound/usb/helper.h
-+++ b/sound/usb/helper.h
-@@ -17,6 +17,12 @@ unsigned char snd_usb_parse_datainterval(struct snd_usb_audio *chip,
- struct usb_host_interface *
- snd_usb_get_host_interface(struct snd_usb_audio *chip, int ifnum, int altsetting);
-+int snd_usb_add_ctrl_interface_link(struct snd_usb_audio *chip, int ifnum,
-+              int ctrlif);
-+
-+struct usb_host_interface *snd_usb_find_ctrl_interface(struct snd_usb_audio *chip,
-+                                                              int ifnum);
-+
- /*
-  * retrieve usb_interface descriptor from the host interface
-  * (conditional for compatibility with the older API)
-@@ -28,9 +34,9 @@ snd_usb_get_host_interface(struct snd_usb_audio *chip, int ifnum, int altsetting
- #define snd_usb_get_speed(dev) ((dev)->speed)
--static inline int snd_usb_ctrl_intf(struct snd_usb_audio *chip)
-+static inline int snd_usb_ctrl_intf(struct usb_host_interface *ctrl_intf)
- {
--      return get_iface_desc(chip->ctrl_intf)->bInterfaceNumber;
-+      return get_iface_desc(ctrl_intf)->bInterfaceNumber;
- }
- /* in validate.c */
-diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
-index 197fd07e69edd..017b50322d88f 100644
---- a/sound/usb/mixer.c
-+++ b/sound/usb/mixer.c
-@@ -728,7 +728,7 @@ static int get_cluster_channels_v3(struct mixer_build *state, unsigned int clust
-                       UAC3_CS_REQ_HIGH_CAPABILITY_DESCRIPTOR,
-                       USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-                       cluster_id,
--                      snd_usb_ctrl_intf(state->chip),
-+                      snd_usb_ctrl_intf(state->mixer->hostif),
-                       &c_header, sizeof(c_header));
-       if (err < 0)
-               goto error;
-diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
-index c8d48566e1759..2323504339328 100644
---- a/sound/usb/mixer_quirks.c
-+++ b/sound/usb/mixer_quirks.c
-@@ -1043,7 +1043,7 @@ static int snd_ftu_eff_switch_init(struct usb_mixer_interface *mixer,
-       err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC_GET_CUR,
-                             USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-                             pval & 0xff00,
--                            snd_usb_ctrl_intf(mixer->chip) | ((pval & 0xff) << 8),
-+                            snd_usb_ctrl_intf(mixer->hostif) | ((pval & 0xff) << 8),
-                             value, 2);
-       if (err < 0)
-               return err;
-@@ -1077,7 +1077,7 @@ static int snd_ftu_eff_switch_update(struct usb_mixer_elem_list *list)
-                             UAC_SET_CUR,
-                             USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
-                             pval & 0xff00,
--                            snd_usb_ctrl_intf(chip) | ((pval & 0xff) << 8),
-+                            snd_usb_ctrl_intf(list->mixer->hostif) | ((pval & 0xff) << 8),
-                             value, 2);
-       snd_usb_unlock_shutdown(chip);
-       return err;
-@@ -2115,24 +2115,25 @@ static int dell_dock_mixer_create(struct usb_mixer_interface *mixer)
-       return 0;
- }
--static void dell_dock_init_vol(struct snd_usb_audio *chip, int ch, int id)
-+static void dell_dock_init_vol(struct usb_mixer_interface *mixer, int ch, int id)
- {
-+      struct snd_usb_audio *chip = mixer->chip;
-       u16 buf = 0;
-       snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0), UAC_SET_CUR,
-                       USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
-                       (UAC_FU_VOLUME << 8) | ch,
--                      snd_usb_ctrl_intf(chip) | (id << 8),
-+                      snd_usb_ctrl_intf(mixer->hostif) | (id << 8),
-                       &buf, 2);
- }
- static int dell_dock_mixer_init(struct usb_mixer_interface *mixer)
- {
-       /* fix to 0dB playback volumes */
--      dell_dock_init_vol(mixer->chip, 1, 16);
--      dell_dock_init_vol(mixer->chip, 2, 16);
--      dell_dock_init_vol(mixer->chip, 1, 19);
--      dell_dock_init_vol(mixer->chip, 2, 19);
-+      dell_dock_init_vol(mixer, 1, 16);
-+      dell_dock_init_vol(mixer, 2, 16);
-+      dell_dock_init_vol(mixer, 1, 19);
-+      dell_dock_init_vol(mixer, 2, 19);
-       return 0;
- }
-diff --git a/sound/usb/mixer_scarlett.c b/sound/usb/mixer_scarlett.c
-index 0d6e4f15bf77c..ff548041679bb 100644
---- a/sound/usb/mixer_scarlett.c
-+++ b/sound/usb/mixer_scarlett.c
-@@ -460,7 +460,7 @@ static int scarlett_ctl_meter_get(struct snd_kcontrol *kctl,
-       struct snd_usb_audio *chip = elem->head.mixer->chip;
-       unsigned char buf[2 * MAX_CHANNELS] = {0, };
-       int wValue = (elem->control << 8) | elem->idx_off;
--      int idx = snd_usb_ctrl_intf(chip) | (elem->head.id << 8);
-+      int idx = snd_usb_ctrl_intf(elem->head.mixer->hostif) | (elem->head.id << 8);
-       int err;
-       err = snd_usb_ctl_msg(chip->dev,
-@@ -1002,7 +1002,7 @@ int snd_scarlett_controls_create(struct usb_mixer_interface *mixer)
-       err = snd_usb_ctl_msg(mixer->chip->dev,
-               usb_sndctrlpipe(mixer->chip->dev, 0), UAC2_CS_CUR,
-               USB_RECIP_INTERFACE | USB_TYPE_CLASS |
--              USB_DIR_OUT, 0x0100, snd_usb_ctrl_intf(mixer->chip) |
-+              USB_DIR_OUT, 0x0100, snd_usb_ctrl_intf(mixer->hostif) |
-               (0x29 << 8), sample_rate_buffer, 4);
-       if (err < 0)
-               return err;
-diff --git a/sound/usb/power.c b/sound/usb/power.c
-index 606a2cb23eab6..66bd4daa68fd5 100644
---- a/sound/usb/power.c
-+++ b/sound/usb/power.c
-@@ -40,6 +40,7 @@ snd_usb_find_power_domain(struct usb_host_interface *ctrl_iface,
-                                       le16_to_cpu(pd_desc->waRecoveryTime1);
-                               pd->pd_d2d0_rec =
-                                       le16_to_cpu(pd_desc->waRecoveryTime2);
-+                              pd->ctrl_iface = ctrl_iface;
-                               return pd;
-                       }
-               }
-@@ -57,7 +58,7 @@ int snd_usb_power_domain_set(struct snd_usb_audio *chip,
-       unsigned char current_state;
-       int err, idx;
--      idx = snd_usb_ctrl_intf(chip) | (pd->pd_id << 8);
-+      idx = snd_usb_ctrl_intf(pd->ctrl_iface) | (pd->pd_id << 8);
-       err = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0),
-                             UAC2_CS_CUR,
-diff --git a/sound/usb/power.h b/sound/usb/power.h
-index 396e3e51440a7..1fa92ad0ca925 100644
---- a/sound/usb/power.h
-+++ b/sound/usb/power.h
-@@ -6,6 +6,7 @@ struct snd_usb_power_domain {
-       int pd_id;              /* UAC3 Power Domain ID */
-       int pd_d1d0_rec;        /* D1 to D0 recovery time */
-       int pd_d2d0_rec;        /* D2 to D0 recovery time */
-+      struct usb_host_interface *ctrl_iface; /* Control interface */
- };
- enum {
-diff --git a/sound/usb/stream.c b/sound/usb/stream.c
-index e14c725acebf2..d70c140813d68 100644
---- a/sound/usb/stream.c
-+++ b/sound/usb/stream.c
-@@ -713,10 +713,13 @@ snd_usb_get_audioformat_uac12(struct snd_usb_audio *chip,
-       struct usb_device *dev = chip->dev;
-       struct uac_format_type_i_continuous_descriptor *fmt;
-       unsigned int num_channels = 0, chconfig = 0;
-+      struct usb_host_interface *ctrl_intf;
-       struct audioformat *fp;
-       int clock = 0;
-       u64 format;
-+      ctrl_intf = snd_usb_find_ctrl_interface(chip, iface_no);
-+
-       /* get audio formats */
-       if (protocol == UAC_VERSION_1) {
-               struct uac1_as_header_descriptor *as =
-@@ -740,7 +743,7 @@ snd_usb_get_audioformat_uac12(struct snd_usb_audio *chip,
-               format = le16_to_cpu(as->wFormatTag); /* remember the format value */
--              iterm = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
-+              iterm = snd_usb_find_input_terminal_descriptor(ctrl_intf,
-                                                              as->bTerminalLink,
-                                                              protocol);
-               if (iterm) {
-@@ -776,7 +779,7 @@ snd_usb_get_audioformat_uac12(struct snd_usb_audio *chip,
-                * lookup the terminal associated to this interface
-                * to extract the clock
-                */
--              input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
-+              input_term = snd_usb_find_input_terminal_descriptor(ctrl_intf,
-                                                                   as->bTerminalLink,
-                                                                   protocol);
-               if (input_term) {
-@@ -786,7 +789,7 @@ snd_usb_get_audioformat_uac12(struct snd_usb_audio *chip,
-                       goto found_clock;
-               }
--              output_term = snd_usb_find_output_terminal_descriptor(chip->ctrl_intf,
-+              output_term = snd_usb_find_output_terminal_descriptor(ctrl_intf,
-                                                                     as->bTerminalLink,
-                                                                     protocol);
-               if (output_term) {
-@@ -870,6 +873,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,
-       struct uac3_cluster_header_descriptor *cluster;
-       struct uac3_as_header_descriptor *as = NULL;
-       struct uac3_hc_descriptor_header hc_header;
-+      struct usb_host_interface *ctrl_intf;
-       struct snd_pcm_chmap_elem *chmap;
-       struct snd_usb_power_domain *pd;
-       unsigned char badd_profile;
-@@ -881,6 +885,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,
-       int err;
-       badd_profile = chip->badd_profile;
-+      ctrl_intf = snd_usb_find_ctrl_interface(chip, iface_no);
-       if (badd_profile >= UAC3_FUNCTION_SUBCLASS_GENERIC_IO) {
-               unsigned int maxpacksize =
-@@ -966,7 +971,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,
-                       UAC3_CS_REQ_HIGH_CAPABILITY_DESCRIPTOR,
-                       USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-                       cluster_id,
--                      snd_usb_ctrl_intf(chip),
-+                      snd_usb_ctrl_intf(ctrl_intf),
-                       &hc_header, sizeof(hc_header));
-       if (err < 0)
-               return ERR_PTR(err);
-@@ -990,7 +995,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,
-                       UAC3_CS_REQ_HIGH_CAPABILITY_DESCRIPTOR,
-                       USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-                       cluster_id,
--                      snd_usb_ctrl_intf(chip),
-+                      snd_usb_ctrl_intf(ctrl_intf),
-                       cluster, wLength);
-       if (err < 0) {
-               kfree(cluster);
-@@ -1011,7 +1016,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,
-        * lookup the terminal associated to this interface
-        * to extract the clock
-        */
--      input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
-+      input_term = snd_usb_find_input_terminal_descriptor(ctrl_intf,
-                                                           as->bTerminalLink,
-                                                           UAC_VERSION_3);
-       if (input_term) {
-@@ -1019,7 +1024,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,
-               goto found_clock;
-       }
--      output_term = snd_usb_find_output_terminal_descriptor(chip->ctrl_intf,
-+      output_term = snd_usb_find_output_terminal_descriptor(ctrl_intf,
-                                                             as->bTerminalLink,
-                                                             UAC_VERSION_3);
-       if (output_term) {
-@@ -1068,7 +1073,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,
-                                                              UAC_VERSION_3,
-                                                              iface_no);
--              pd = snd_usb_find_power_domain(chip->ctrl_intf,
-+              pd = snd_usb_find_power_domain(ctrl_intf,
-                                              as->bTerminalLink);
-               /* ok, let's parse further... */
-diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
-index 43d4029edab46..b0f042c996087 100644
---- a/sound/usb/usbaudio.h
-+++ b/sound/usb/usbaudio.h
-@@ -21,6 +21,15 @@ struct media_intf_devnode;
- #define MAX_CARD_INTERFACES   16
-+/*
-+ * Structure holding assosiation between Audio Control Interface
-+ * and given Streaming or Midi Interface.
-+ */
-+struct snd_intf_to_ctrl {
-+      u8 interface;
-+      struct usb_host_interface *ctrl_intf;
-+};
-+
- struct snd_usb_audio {
-       int index;
-       struct usb_device *dev;
-@@ -63,6 +72,9 @@ struct snd_usb_audio {
-       struct usb_host_interface *ctrl_intf;   /* the audio control interface */
-       struct media_device *media_dev;
-       struct media_intf_devnode *ctl_intf_media_devnode;
-+
-+      unsigned int num_intf_to_ctrl;
-+      struct snd_intf_to_ctrl intf_to_ctrl[MAX_CARD_INTERFACES];
- };
- #define USB_AUDIO_IFACE_UNUSED        ((void *)-1L)
--- 
-2.43.0
-
index 959a66d7fe8f7fc241713de2c3fa5eb5eda34420..d42048d3707f16a9e618e4538411472c769b5ffb 100644 (file)
@@ -106,7 +106,6 @@ wifi-mwifiex-fix-memcpy-field-spanning-write-warning.patch
 nfp-use-irqf_no_autoen-flag-in-request_irq.patch
 alsa-usb-audio-add-input-value-sanity-checks-for-sta.patch
 x86-ioapic-handle-allocation-failures-gracefully.patch
-alsa-usb-audio-support-multiple-control-interfaces.patch
 alsa-usb-audio-define-macros-for-quirk-table-entries.patch
 alsa-usb-audio-replace-complex-quirk-lines-with-macr.patch
 alsa-usb-audio-add-logitech-audio-profile-quirk.patch