hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/sound/usb/card.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * (Tentative) USB Audio Driver for ALSA
34 *
....@@ -8,21 +9,6 @@
89 * Thomas Sailer (sailer@ife.ee.ethz.ch)
910 *
1011 * Audio Class 3.0 support by Ruslan Bilovol <ruslan.bilovol@gmail.com>
11
- *
12
- * This program is free software; you can redistribute it and/or modify
13
- * it under the terms of the GNU General Public License as published by
14
- * the Free Software Foundation; either version 2 of the License, or
15
- * (at your option) any later version.
16
- *
17
- * This program is distributed in the hope that it will be useful,
18
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20
- * GNU General Public License for more details.
21
- *
22
- * You should have received a copy of the GNU General Public License
23
- * along with this program; if not, write to the Free Software
24
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25
- *
2612 *
2713 * NOTES:
2814 *
....@@ -68,6 +54,7 @@
6854 #include "format.h"
6955 #include "power.h"
7056 #include "stream.h"
57
+#include "media.h"
7158
7259 MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
7360 MODULE_DESCRIPTION("USB Audio");
....@@ -85,8 +72,10 @@
8572 static bool ignore_ctl_error;
8673 static bool autoclock = true;
8774 static char *quirk_alias[SNDRV_CARDS];
75
+static char *delayed_register[SNDRV_CARDS];
8876
8977 bool snd_usb_use_vmalloc = true;
78
+bool snd_usb_skip_validation;
9079
9180 module_param_array(index, int, NULL, 0444);
9281 MODULE_PARM_DESC(index, "Index value for the USB audio adapter.");
....@@ -107,8 +96,12 @@
10796 MODULE_PARM_DESC(autoclock, "Enable auto-clock selection for UAC2 devices (default: yes).");
10897 module_param_array(quirk_alias, charp, NULL, 0444);
10998 MODULE_PARM_DESC(quirk_alias, "Quirk aliases, e.g. 0123abcd:5678beef.");
99
+module_param_array(delayed_register, charp, NULL, 0444);
100
+MODULE_PARM_DESC(delayed_register, "Quirk for delayed registration, given by id:iface, e.g. 0123abcd:4.");
110101 module_param_named(use_vmalloc, snd_usb_use_vmalloc, bool, 0444);
111102 MODULE_PARM_DESC(use_vmalloc, "Use vmalloc for PCM intermediate buffers (default: yes).");
103
+module_param_named(skip_validation, snd_usb_skip_validation, bool, 0444);
104
+MODULE_PARM_DESC(skip_validation, "Skip unit descriptor validation (default: no).");
112105
113106 /*
114107 * we keep the snd_usb_audio_t instances by ourselves for merging
....@@ -119,15 +112,119 @@
119112 static struct snd_usb_audio *usb_chip[SNDRV_CARDS];
120113 static struct usb_driver usb_audio_driver;
121114
122
-/**
123
- * find_snd_usb_substream - helper API to find usb substream context
124
- * information using card number, pcm device number and direction.
125
- * @card_num: card number
126
- * @pcm_idx: pcm device number
127
- * @direction: SNDRV_PCM_STREAM_PLAYBACK or SNDRV_PCM_STREAM_CAPTURE
128
- * @uchip: substream context.
129
- * disconnect_cb: callback to use for cleanup on disconnect.
130
- */
115
+static struct snd_usb_audio_vendor_ops *usb_vendor_ops;
116
+
117
+int snd_vendor_set_ops(struct snd_usb_audio_vendor_ops *ops)
118
+{
119
+ if ((!ops->connect) ||
120
+ (!ops->disconnect) ||
121
+ (!ops->set_interface) ||
122
+ (!ops->set_rate) ||
123
+ (!ops->set_pcm_buf) ||
124
+ (!ops->set_pcm_intf) ||
125
+ (!ops->set_pcm_connection) ||
126
+ (!ops->set_pcm_binterval) ||
127
+ (!ops->usb_add_ctls))
128
+ return -EINVAL;
129
+
130
+ usb_vendor_ops = ops;
131
+ return 0;
132
+}
133
+EXPORT_SYMBOL_GPL(snd_vendor_set_ops);
134
+
135
+struct snd_usb_audio_vendor_ops *snd_vendor_get_ops(void)
136
+{
137
+ return usb_vendor_ops;
138
+}
139
+
140
+static int snd_vendor_connect(struct usb_interface *intf)
141
+{
142
+ struct snd_usb_audio_vendor_ops *ops = snd_vendor_get_ops();
143
+
144
+ if (ops)
145
+ return ops->connect(intf);
146
+ return 0;
147
+}
148
+
149
+static void snd_vendor_disconnect(struct usb_interface *intf)
150
+{
151
+ struct snd_usb_audio_vendor_ops *ops = snd_vendor_get_ops();
152
+
153
+ if (ops)
154
+ ops->disconnect(intf);
155
+}
156
+
157
+int snd_vendor_set_interface(struct usb_device *udev,
158
+ struct usb_host_interface *intf,
159
+ int iface, int alt)
160
+{
161
+ struct snd_usb_audio_vendor_ops *ops = snd_vendor_get_ops();
162
+
163
+ if (ops)
164
+ return ops->set_interface(udev, intf, iface, alt);
165
+ return 0;
166
+}
167
+
168
+int snd_vendor_set_rate(struct usb_interface *intf, int iface, int rate,
169
+ int alt)
170
+{
171
+ struct snd_usb_audio_vendor_ops *ops = snd_vendor_get_ops();
172
+
173
+ if (ops)
174
+ return ops->set_rate(intf, iface, rate, alt);
175
+ return 0;
176
+}
177
+
178
+int snd_vendor_set_pcm_buf(struct usb_device *udev, int iface)
179
+{
180
+ struct snd_usb_audio_vendor_ops *ops = snd_vendor_get_ops();
181
+
182
+ if (ops)
183
+ ops->set_pcm_buf(udev, iface);
184
+ return 0;
185
+}
186
+
187
+int snd_vendor_set_pcm_intf(struct usb_interface *intf, int iface, int alt,
188
+ int direction)
189
+{
190
+ struct snd_usb_audio_vendor_ops *ops = snd_vendor_get_ops();
191
+
192
+ if (ops)
193
+ return ops->set_pcm_intf(intf, iface, alt, direction);
194
+ return 0;
195
+}
196
+
197
+int snd_vendor_set_pcm_connection(struct usb_device *udev,
198
+ enum snd_vendor_pcm_open_close onoff,
199
+ int direction)
200
+{
201
+ struct snd_usb_audio_vendor_ops *ops = snd_vendor_get_ops();
202
+
203
+ if (ops)
204
+ return ops->set_pcm_connection(udev, onoff, direction);
205
+ return 0;
206
+}
207
+
208
+int snd_vendor_set_pcm_binterval(struct audioformat *fp,
209
+ struct audioformat *found,
210
+ int *cur_attr, int *attr)
211
+{
212
+ struct snd_usb_audio_vendor_ops *ops = snd_vendor_get_ops();
213
+
214
+ if (ops)
215
+ return ops->set_pcm_binterval(fp, found, cur_attr, attr);
216
+ return 0;
217
+}
218
+
219
+static int snd_vendor_usb_add_ctls(struct snd_usb_audio *chip)
220
+{
221
+ struct snd_usb_audio_vendor_ops *ops = snd_vendor_get_ops();
222
+
223
+ if (ops)
224
+ return ops->usb_add_ctls(chip);
225
+ return 0;
226
+}
227
+
131228 struct snd_usb_substream *find_snd_usb_substream(unsigned int card_num,
132229 unsigned int pcm_idx, unsigned int direction, struct snd_usb_audio
133230 **uchip, void (*disconnect_cb)(struct snd_usb_audio *chip))
....@@ -143,7 +240,7 @@
143240 * search using chip->card->number
144241 */
145242 for (idx = 0; idx < SNDRV_CARDS; idx++) {
146
- if (!usb_chip[idx] || !usb_chip[idx]->card)
243
+ if (!usb_chip[idx])
147244 continue;
148245 if (usb_chip[idx]->card->number == card_num) {
149246 chip = usb_chip[idx];
....@@ -152,20 +249,19 @@
152249 }
153250
154251 if (!chip || atomic_read(&chip->shutdown)) {
155
- pr_debug("%s: instance of usb card # %d does not exist\n",
252
+ pr_debug("%s: instance of usb crad # %d does not exist\n",
156253 __func__, card_num);
157254 goto err;
158255 }
159256
160257 if (pcm_idx >= chip->pcm_devs) {
161
- usb_audio_err(chip, "%s: invalid pcm dev number %u > %d\n",
162
- __func__, pcm_idx, chip->pcm_devs);
258
+ pr_err("%s: invalid pcm dev number %u > %d\n", __func__,
259
+ pcm_idx, chip->pcm_devs);
163260 goto err;
164261 }
165262
166263 if (direction > SNDRV_PCM_STREAM_CAPTURE) {
167
- usb_audio_err(chip, "%s: invalid direction %u\n", __func__,
168
- direction);
264
+ pr_err("%s: invalid direction %u\n", __func__, direction);
169265 goto err;
170266 }
171267
....@@ -173,9 +269,9 @@
173269 if (as->pcm_index == pcm_idx) {
174270 subs = &as->substream[direction];
175271 if (subs->interface < 0 && !subs->data_endpoint &&
176
- !subs->sync_endpoint) {
177
- usb_audio_err(chip, "%s: stream disconnected, bail out\n",
178
- __func__);
272
+ !subs->sync_endpoint) {
273
+ pr_debug("%s: stream disconnected, bail out\n",
274
+ __func__);
179275 subs = NULL;
180276 goto err;
181277 }
....@@ -189,7 +285,7 @@
189285 err:
190286 *uchip = chip;
191287 if (!subs)
192
- pr_err("%s: substream instance not found\n", __func__);
288
+ pr_debug("%s: substream instance not found\n", __func__);
193289 mutex_unlock(&register_mutex);
194290 return subs;
195291 }
....@@ -313,7 +409,7 @@
313409 dev_warn(&dev->dev,
314410 "unknown interface protocol %#02x, assuming v1\n",
315411 protocol);
316
- /* fall through */
412
+ fallthrough;
317413
318414 case UAC_VERSION_1: {
319415 struct uac1_ac_header_descriptor *h1;
....@@ -416,6 +512,121 @@
416512 }
417513
418514 /*
515
+ * Profile name preset table
516
+ */
517
+struct usb_audio_device_name {
518
+ u32 id;
519
+ const char *vendor_name;
520
+ const char *product_name;
521
+ const char *profile_name; /* override card->longname */
522
+};
523
+
524
+#define PROFILE_NAME(vid, pid, vendor, product, profile) \
525
+ { .id = USB_ID(vid, pid), .vendor_name = (vendor), \
526
+ .product_name = (product), .profile_name = (profile) }
527
+#define DEVICE_NAME(vid, pid, vendor, product) \
528
+ PROFILE_NAME(vid, pid, vendor, product, NULL)
529
+
530
+/* vendor/product and profile name presets, sorted in device id order */
531
+static const struct usb_audio_device_name usb_audio_names[] = {
532
+ /* HP Thunderbolt Dock Audio Headset */
533
+ PROFILE_NAME(0x03f0, 0x0269, "HP", "Thunderbolt Dock Audio Headset",
534
+ "HP-Thunderbolt-Dock-Audio-Headset"),
535
+ /* HP Thunderbolt Dock Audio Module */
536
+ PROFILE_NAME(0x03f0, 0x0567, "HP", "Thunderbolt Dock Audio Module",
537
+ "HP-Thunderbolt-Dock-Audio-Module"),
538
+
539
+ /* Two entries for Gigabyte TRX40 Aorus Master:
540
+ * TRX40 Aorus Master has two USB-audio devices, one for the front
541
+ * headphone with ESS SABRE9218 DAC chip, while another for the rest
542
+ * I/O (the rear panel and the front mic) with Realtek ALC1220-VB.
543
+ * Here we provide two distinct names for making UCM profiles easier.
544
+ */
545
+ PROFILE_NAME(0x0414, 0xa000, "Gigabyte", "Aorus Master Front Headphone",
546
+ "Gigabyte-Aorus-Master-Front-Headphone"),
547
+ PROFILE_NAME(0x0414, 0xa001, "Gigabyte", "Aorus Master Main Audio",
548
+ "Gigabyte-Aorus-Master-Main-Audio"),
549
+
550
+ /* Gigabyte TRX40 Aorus Pro WiFi */
551
+ PROFILE_NAME(0x0414, 0xa002,
552
+ "Realtek", "ALC1220-VB-DT", "Realtek-ALC1220-VB-Desktop"),
553
+
554
+ /* Creative/E-Mu devices */
555
+ DEVICE_NAME(0x041e, 0x3010, "Creative Labs", "Sound Blaster MP3+"),
556
+ /* Creative/Toshiba Multimedia Center SB-0500 */
557
+ DEVICE_NAME(0x041e, 0x3048, "Toshiba", "SB-0500"),
558
+
559
+ DEVICE_NAME(0x046d, 0x0990, "Logitech, Inc.", "QuickCam Pro 9000"),
560
+
561
+ /* ASUS ROG Zenith II: this machine has also two devices, one for
562
+ * the front headphone and another for the rest
563
+ */
564
+ PROFILE_NAME(0x0b05, 0x1915, "ASUS", "Zenith II Front Headphone",
565
+ "Zenith-II-Front-Headphone"),
566
+ PROFILE_NAME(0x0b05, 0x1916, "ASUS", "Zenith II Main Audio",
567
+ "Zenith-II-Main-Audio"),
568
+
569
+ /* ASUS ROG Strix */
570
+ PROFILE_NAME(0x0b05, 0x1917,
571
+ "Realtek", "ALC1220-VB-DT", "Realtek-ALC1220-VB-Desktop"),
572
+ /* ASUS PRIME TRX40 PRO-S */
573
+ PROFILE_NAME(0x0b05, 0x1918,
574
+ "Realtek", "ALC1220-VB-DT", "Realtek-ALC1220-VB-Desktop"),
575
+
576
+ /* Dell WD15 Dock */
577
+ PROFILE_NAME(0x0bda, 0x4014, "Dell", "WD15 Dock", "Dell-WD15-Dock"),
578
+ /* Dell WD19 Dock */
579
+ PROFILE_NAME(0x0bda, 0x402e, "Dell", "WD19 Dock", "Dell-WD15-Dock"),
580
+
581
+ DEVICE_NAME(0x0ccd, 0x0028, "TerraTec", "Aureon5.1MkII"),
582
+
583
+ /*
584
+ * The original product_name is "USB Sound Device", however this name
585
+ * is also used by the CM106 based cards, so make it unique.
586
+ */
587
+ DEVICE_NAME(0x0d8c, 0x0102, NULL, "ICUSBAUDIO7D"),
588
+ DEVICE_NAME(0x0d8c, 0x0103, NULL, "Audio Advantage MicroII"),
589
+
590
+ /* MSI TRX40 Creator */
591
+ PROFILE_NAME(0x0db0, 0x0d64,
592
+ "Realtek", "ALC1220-VB-DT", "Realtek-ALC1220-VB-Desktop"),
593
+ /* MSI TRX40 */
594
+ PROFILE_NAME(0x0db0, 0x543d,
595
+ "Realtek", "ALC1220-VB-DT", "Realtek-ALC1220-VB-Desktop"),
596
+
597
+ /* Stanton/N2IT Final Scratch v1 device ('Scratchamp') */
598
+ DEVICE_NAME(0x103d, 0x0100, "Stanton", "ScratchAmp"),
599
+ DEVICE_NAME(0x103d, 0x0101, "Stanton", "ScratchAmp"),
600
+
601
+ /* aka. Serato Scratch Live DJ Box */
602
+ DEVICE_NAME(0x13e5, 0x0001, "Rane", "SL-1"),
603
+
604
+ /* Lenovo ThinkStation P620 Rear Line-in, Line-out and Microphone */
605
+ PROFILE_NAME(0x17aa, 0x1046, "Lenovo", "ThinkStation P620 Rear",
606
+ "Lenovo-ThinkStation-P620-Rear"),
607
+ /* Lenovo ThinkStation P620 Internal Speaker + Front Headset */
608
+ PROFILE_NAME(0x17aa, 0x104d, "Lenovo", "ThinkStation P620 Main",
609
+ "Lenovo-ThinkStation-P620-Main"),
610
+
611
+ /* Asrock TRX40 Creator */
612
+ PROFILE_NAME(0x26ce, 0x0a01,
613
+ "Realtek", "ALC1220-VB-DT", "Realtek-ALC1220-VB-Desktop"),
614
+
615
+ { } /* terminator */
616
+};
617
+
618
+static const struct usb_audio_device_name *
619
+lookup_device_name(u32 id)
620
+{
621
+ static const struct usb_audio_device_name *p;
622
+
623
+ for (p = usb_audio_names; p->id; p++)
624
+ if (p->id == id)
625
+ return p;
626
+ return NULL;
627
+}
628
+
629
+/*
419630 * free the chip instance
420631 *
421632 * here we have to do not much, since pcm and controls are already freed
....@@ -441,10 +652,16 @@
441652 const struct snd_usb_audio_quirk *quirk)
442653 {
443654 struct snd_card *card = chip->card;
655
+ const struct usb_audio_device_name *preset;
656
+ const char *s = NULL;
444657
445
- if (quirk && quirk->product_name && *quirk->product_name) {
446
- strlcpy(card->shortname, quirk->product_name,
447
- sizeof(card->shortname));
658
+ preset = lookup_device_name(chip->usb_id);
659
+ if (preset && preset->product_name)
660
+ s = preset->product_name;
661
+ else if (quirk && quirk->product_name)
662
+ s = quirk->product_name;
663
+ if (s && *s) {
664
+ strlcpy(card->shortname, s, sizeof(card->shortname));
448665 return;
449666 }
450667
....@@ -466,17 +683,26 @@
466683 const struct snd_usb_audio_quirk *quirk)
467684 {
468685 struct snd_card *card = chip->card;
686
+ const struct usb_audio_device_name *preset;
687
+ const char *s = NULL;
469688 int len;
470689
690
+ preset = lookup_device_name(chip->usb_id);
691
+
471692 /* shortcut - if any pre-defined string is given, use it */
472
- if (quirk && quirk->profile_name && *quirk->profile_name) {
473
- strlcpy(card->longname, quirk->profile_name,
474
- sizeof(card->longname));
693
+ if (preset && preset->profile_name)
694
+ s = preset->profile_name;
695
+ if (s && *s) {
696
+ strlcpy(card->longname, s, sizeof(card->longname));
475697 return;
476698 }
477699
478
- if (quirk && quirk->vendor_name && *quirk->vendor_name) {
479
- len = strlcpy(card->longname, quirk->vendor_name, sizeof(card->longname));
700
+ if (preset && preset->vendor_name)
701
+ s = preset->vendor_name;
702
+ else if (quirk && quirk->vendor_name)
703
+ s = quirk->vendor_name;
704
+ if (s && *s) {
705
+ len = strlcpy(card->longname, s, sizeof(card->longname));
480706 } else {
481707 /* retrieve the vendor and device strings as longname */
482708 if (dev->descriptor.iManufacturer)
....@@ -613,6 +839,21 @@
613839 return false;
614840 }
615841
842
+static bool check_delayed_register_option(struct snd_usb_audio *chip, int iface)
843
+{
844
+ int i;
845
+ unsigned int id, inum;
846
+
847
+ for (i = 0; i < ARRAY_SIZE(delayed_register); i++) {
848
+ if (delayed_register[i] &&
849
+ sscanf(delayed_register[i], "%x:%x", &id, &inum) == 2 &&
850
+ id == chip->usb_id)
851
+ return iface < inum;
852
+ }
853
+
854
+ return false;
855
+}
856
+
616857 static const struct usb_device_id usb_audio_ids[]; /* defined below */
617858
618859 /* look for the corresponding quirk */
....@@ -668,6 +909,10 @@
668909 if (err < 0)
669910 return err;
670911
912
+ err = snd_vendor_connect(intf);
913
+ if (err)
914
+ return err;
915
+
671916 /*
672917 * found a config. now register to ALSA
673918 */
....@@ -688,6 +933,10 @@
688933 }
689934 }
690935 if (! chip) {
936
+ err = snd_usb_apply_boot_quirk_once(dev, intf, quirk, id);
937
+ if (err < 0)
938
+ goto __error;
939
+
691940 /* it's a fresh one.
692941 * now look for an empty slot and create a new card instance
693942 */
....@@ -700,7 +949,6 @@
700949 id, &chip);
701950 if (err < 0)
702951 goto __error;
703
- chip->pm_intf = intf;
704952 break;
705953 } else if (vid[i] != -1 || pid[i] != -1) {
706954 dev_info(&dev->dev,
....@@ -717,7 +965,16 @@
717965 goto __error;
718966 }
719967 }
968
+
969
+ if (chip->num_interfaces >= MAX_CARD_INTERFACES) {
970
+ dev_info(&dev->dev, "Too many interfaces assigned to the single USB-audio card\n");
971
+ err = -EINVAL;
972
+ goto __error;
973
+ }
974
+
720975 dev_set_drvdata(&dev->dev, chip);
976
+
977
+ snd_vendor_usb_add_ctls(chip);
721978
722979 /*
723980 * For devices with more than one control interface, we assume the
....@@ -746,16 +1003,33 @@
7461003 goto __error;
7471004 }
7481005
1006
+ if (chip->need_delayed_register) {
1007
+ dev_info(&dev->dev,
1008
+ "Found post-registration device assignment: %08x:%02x\n",
1009
+ chip->usb_id, ifnum);
1010
+ chip->need_delayed_register = false; /* clear again */
1011
+ }
1012
+
7491013 /* we are allowed to call snd_card_register() many times, but first
7501014 * check to see if a device needs to skip it or do anything special
7511015 */
752
- if (!snd_usb_registration_quirk(chip, ifnum)) {
1016
+ if (!snd_usb_registration_quirk(chip, ifnum) &&
1017
+ !check_delayed_register_option(chip, ifnum)) {
7531018 err = snd_card_register(chip->card);
7541019 if (err < 0)
7551020 goto __error;
7561021 }
7571022
1023
+ if (quirk && quirk->shares_media_device) {
1024
+ /* don't want to fail when snd_media_device_create() fails */
1025
+ snd_media_device_create(chip, intf);
1026
+ }
1027
+
1028
+ if (quirk)
1029
+ chip->quirk_type = quirk->type;
1030
+
7581031 usb_chip[chip->index] = chip;
1032
+ chip->intf[chip->num_interfaces] = intf;
7591033 chip->num_interfaces++;
7601034 usb_set_intfdata(intf, chip);
7611035 atomic_dec(&chip->active);
....@@ -790,6 +1064,11 @@
7901064
7911065 card = chip->card;
7921066
1067
+ if (chip->disconnect_cb)
1068
+ chip->disconnect_cb(chip);
1069
+
1070
+ snd_vendor_disconnect(intf);
1071
+
7931072 mutex_lock(&register_mutex);
7941073 if (atomic_inc_return(&chip->shutdown) == 1) {
7951074 struct snd_usb_stream *as;
....@@ -814,11 +1093,22 @@
8141093 list_for_each(p, &chip->midi_list) {
8151094 snd_usbmidi_disconnect(p);
8161095 }
1096
+ /*
1097
+ * Nice to check quirk && quirk->shares_media_device and
1098
+ * then call the snd_media_device_delete(). Don't have
1099
+ * access to the quirk here. snd_media_device_delete()
1100
+ * accesses mixer_list
1101
+ */
1102
+ snd_media_device_delete(chip);
1103
+
8171104 /* release mixer resources */
8181105 list_for_each_entry(mixer, &chip->mixer_list, list) {
8191106 snd_usb_mixer_disconnect(mixer);
8201107 }
8211108 }
1109
+
1110
+ if (chip->quirk_type == QUIRK_SETUP_DISABLE_AUTOSUSPEND)
1111
+ usb_enable_autosuspend(interface_to_usbdev(intf));
8221112
8231113 chip->num_interfaces--;
8241114 if (chip->num_interfaces <= 0) {
....@@ -863,19 +1153,37 @@
8631153
8641154 int snd_usb_autoresume(struct snd_usb_audio *chip)
8651155 {
1156
+ int i, err;
1157
+
8661158 if (atomic_read(&chip->shutdown))
8671159 return -EIO;
868
- if (atomic_inc_return(&chip->active) == 1)
869
- return usb_autopm_get_interface(chip->pm_intf);
1160
+ if (atomic_inc_return(&chip->active) != 1)
1161
+ return 0;
1162
+
1163
+ for (i = 0; i < chip->num_interfaces; i++) {
1164
+ err = usb_autopm_get_interface(chip->intf[i]);
1165
+ if (err < 0) {
1166
+ /* rollback */
1167
+ while (--i >= 0)
1168
+ usb_autopm_put_interface(chip->intf[i]);
1169
+ atomic_dec(&chip->active);
1170
+ return err;
1171
+ }
1172
+ }
8701173 return 0;
8711174 }
8721175
8731176 void snd_usb_autosuspend(struct snd_usb_audio *chip)
8741177 {
1178
+ int i;
1179
+
8751180 if (atomic_read(&chip->shutdown))
8761181 return;
877
- if (atomic_dec_and_test(&chip->active))
878
- usb_autopm_put_interface(chip->pm_intf);
1182
+ if (!atomic_dec_and_test(&chip->active))
1183
+ return;
1184
+
1185
+ for (i = 0; i < chip->num_interfaces; i++)
1186
+ usb_autopm_put_interface(chip->intf[i]);
8791187 }
8801188
8811189 static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message)
....@@ -890,7 +1198,6 @@
8901198
8911199 if (!chip->num_suspended_intf++) {
8921200 list_for_each_entry(as, &chip->pcm_list, list) {
893
- snd_pcm_suspend_all(as->pcm);
8941201 snd_usb_pcm_suspend(as);
8951202 as->substream[0].need_setup_ep =
8961203 as->substream[1].need_setup_ep = true;