blob: 6ac13e1c089e2743c01a00d6ac00e6b9f16f4aec [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Clock domain and sample rate management functions
4 */
5
6#include <linux/bitops.h>
7#include <linux/init.h>
8#include <linux/string.h>
9#include <linux/usb.h>
10#include <linux/usb/audio.h>
11#include <linux/usb/audio-v2.h>
12#include <linux/usb/audio-v3.h>
13
14#include <sound/core.h>
15#include <sound/info.h>
16#include <sound/pcm.h>
17
18#include "usbaudio.h"
19#include "card.h"
20#include "helper.h"
21#include "clock.h"
22#include "quirks.h"
23
24/* check whether the descriptor bLength has the minimal length */
25#define DESC_LENGTH_CHECK(p) \
26 (p->bLength >= sizeof(*p))
27
28static void *find_uac_clock_desc(struct usb_host_interface *iface, int id,
29 bool (*validator)(void *, int), u8 type)
30{
31 void *cs = NULL;
32
33 while ((cs = snd_usb_find_csint_desc(iface->extra, iface->extralen,
34 cs, type))) {
35 if (validator(cs, id))
36 return cs;
37 }
38
39 return NULL;
40}
41
42static bool validate_clock_source_v2(void *p, int id)
43{
44 struct uac_clock_source_descriptor *cs = p;
45 if (!DESC_LENGTH_CHECK(cs))
46 return false;
47 return cs->bClockID == id;
48}
49
50static bool validate_clock_source_v3(void *p, int id)
51{
52 struct uac3_clock_source_descriptor *cs = p;
53 if (!DESC_LENGTH_CHECK(cs))
54 return false;
55 return cs->bClockID == id;
56}
57
58static bool validate_clock_selector_v2(void *p, int id)
59{
60 struct uac_clock_selector_descriptor *cs = p;
61 if (!DESC_LENGTH_CHECK(cs))
62 return false;
63 if (cs->bClockID != id)
64 return false;
65 /* additional length check for baCSourceID array (in bNrInPins size)
66 * and two more fields (which sizes depend on the protocol)
67 */
68 return cs->bLength >= sizeof(*cs) + cs->bNrInPins +
69 1 /* bmControls */ + 1 /* iClockSelector */;
70}
71
72static bool validate_clock_selector_v3(void *p, int id)
73{
74 struct uac3_clock_selector_descriptor *cs = p;
75 if (!DESC_LENGTH_CHECK(cs))
76 return false;
77 if (cs->bClockID != id)
78 return false;
79 /* additional length check for baCSourceID array (in bNrInPins size)
80 * and two more fields (which sizes depend on the protocol)
81 */
82 return cs->bLength >= sizeof(*cs) + cs->bNrInPins +
83 4 /* bmControls */ + 2 /* wCSelectorDescrStr */;
84}
85
86static bool validate_clock_multiplier_v2(void *p, int id)
87{
88 struct uac_clock_multiplier_descriptor *cs = p;
89 if (!DESC_LENGTH_CHECK(cs))
90 return false;
91 return cs->bClockID == id;
92}
93
94static bool validate_clock_multiplier_v3(void *p, int id)
95{
96 struct uac3_clock_multiplier_descriptor *cs = p;
97 if (!DESC_LENGTH_CHECK(cs))
98 return false;
99 return cs->bClockID == id;
100}
101
102#define DEFINE_FIND_HELPER(name, obj, validator, type) \
103static obj *name(struct usb_host_interface *iface, int id) \
104{ \
105 return find_uac_clock_desc(iface, id, validator, type); \
106}
107
108DEFINE_FIND_HELPER(snd_usb_find_clock_source,
109 struct uac_clock_source_descriptor,
110 validate_clock_source_v2, UAC2_CLOCK_SOURCE);
111DEFINE_FIND_HELPER(snd_usb_find_clock_source_v3,
112 struct uac3_clock_source_descriptor,
113 validate_clock_source_v3, UAC3_CLOCK_SOURCE);
114
115DEFINE_FIND_HELPER(snd_usb_find_clock_selector,
116 struct uac_clock_selector_descriptor,
117 validate_clock_selector_v2, UAC2_CLOCK_SELECTOR);
118DEFINE_FIND_HELPER(snd_usb_find_clock_selector_v3,
119 struct uac3_clock_selector_descriptor,
120 validate_clock_selector_v3, UAC3_CLOCK_SELECTOR);
121
122DEFINE_FIND_HELPER(snd_usb_find_clock_multiplier,
123 struct uac_clock_multiplier_descriptor,
124 validate_clock_multiplier_v2, UAC2_CLOCK_MULTIPLIER);
125DEFINE_FIND_HELPER(snd_usb_find_clock_multiplier_v3,
126 struct uac3_clock_multiplier_descriptor,
127 validate_clock_multiplier_v3, UAC3_CLOCK_MULTIPLIER);
128
129static int uac_clock_selector_get_val(struct snd_usb_audio *chip, int selector_id)
130{
131 unsigned char buf;
132 int ret;
133
134 ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0),
135 UAC2_CS_CUR,
136 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
137 UAC2_CX_CLOCK_SELECTOR << 8,
138 snd_usb_ctrl_intf(chip) | (selector_id << 8),
139 &buf, sizeof(buf));
140
141 if (ret < 0)
142 return ret;
143
144 return buf;
145}
146
147static int uac_clock_selector_set_val(struct snd_usb_audio *chip, int selector_id,
148 unsigned char pin)
149{
150 int ret;
151
152 ret = snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0),
153 UAC2_CS_CUR,
154 USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
155 UAC2_CX_CLOCK_SELECTOR << 8,
156 snd_usb_ctrl_intf(chip) | (selector_id << 8),
157 &pin, sizeof(pin));
158 if (ret < 0)
159 return ret;
160
161 if (ret != sizeof(pin)) {
162 usb_audio_err(chip,
163 "setting selector (id %d) unexpected length %d\n",
164 selector_id, ret);
165 return -EINVAL;
166 }
167
168 ret = uac_clock_selector_get_val(chip, selector_id);
169 if (ret < 0)
170 return ret;
171
172 if (ret != pin) {
173 usb_audio_err(chip,
174 "setting selector (id %d) to %x failed (current: %d)\n",
175 selector_id, pin, ret);
176 return -EINVAL;
177 }
178
179 return ret;
180}
181
182static bool uac_clock_source_is_valid_quirk(struct snd_usb_audio *chip,
183 struct audioformat *fmt,
184 int source_id)
185{
186 bool ret = false;
187 int count;
188 unsigned char data;
189 struct usb_device *dev = chip->dev;
190
191 if (fmt->protocol == UAC_VERSION_2) {
192 struct uac_clock_source_descriptor *cs_desc =
193 snd_usb_find_clock_source(chip->ctrl_intf, source_id);
194
195 if (!cs_desc)
196 return false;
197
198 /*
199 * Assume the clock is valid if clock source supports only one
200 * single sample rate, the terminal is connected directly to it
201 * (there is no clock selector) and clock type is internal.
202 * This is to deal with some Denon DJ controllers that always
203 * reports that clock is invalid.
204 */
205 if (fmt->nr_rates == 1 &&
206 (fmt->clock & 0xff) == cs_desc->bClockID &&
207 (cs_desc->bmAttributes & 0x3) !=
208 UAC_CLOCK_SOURCE_TYPE_EXT)
209 return true;
210 }
211
212 /*
213 * MOTU MicroBook IIc
214 * Sample rate changes takes more than 2 seconds for this device. Clock
215 * validity request returns false during that period.
216 */
217 if (chip->usb_id == USB_ID(0x07fd, 0x0004)) {
218 count = 0;
219
220 while ((!ret) && (count < 50)) {
221 int err;
222
223 msleep(100);
224
225 err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
226 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
227 UAC2_CS_CONTROL_CLOCK_VALID << 8,
228 snd_usb_ctrl_intf(chip) | (source_id << 8),
229 &data, sizeof(data));
230 if (err < 0) {
231 dev_warn(&dev->dev,
232 "%s(): cannot get clock validity for id %d\n",
233 __func__, source_id);
234 return false;
235 }
236
237 ret = !!data;
238 count++;
239 }
240 }
241
242 return ret;
243}
244
245static bool uac_clock_source_is_valid(struct snd_usb_audio *chip,
246 struct audioformat *fmt,
247 int source_id)
248{
249 int err;
250 unsigned char data;
251 struct usb_device *dev = chip->dev;
252 u32 bmControls;
253
254 if (fmt->protocol == UAC_VERSION_3) {
255 struct uac3_clock_source_descriptor *cs_desc =
256 snd_usb_find_clock_source_v3(chip->ctrl_intf, source_id);
257
258 if (!cs_desc)
259 return false;
260 bmControls = le32_to_cpu(cs_desc->bmControls);
261 } else { /* UAC_VERSION_1/2 */
262 struct uac_clock_source_descriptor *cs_desc =
263 snd_usb_find_clock_source(chip->ctrl_intf, source_id);
264
265 if (!cs_desc)
266 return false;
267 bmControls = cs_desc->bmControls;
268 }
269
270 /* If a clock source can't tell us whether it's valid, we assume it is */
271 if (!uac_v2v3_control_is_readable(bmControls,
272 UAC2_CS_CONTROL_CLOCK_VALID))
273 return true;
274
275 err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
276 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
277 UAC2_CS_CONTROL_CLOCK_VALID << 8,
278 snd_usb_ctrl_intf(chip) | (source_id << 8),
279 &data, sizeof(data));
280
281 if (err < 0) {
282 dev_warn(&dev->dev,
283 "%s(): cannot get clock validity for id %d\n",
284 __func__, source_id);
285 return false;
286 }
287
288 if (data)
289 return true;
290 else
291 return uac_clock_source_is_valid_quirk(chip, fmt, source_id);
292}
293
294static int __uac_clock_find_source(struct snd_usb_audio *chip,
295 struct audioformat *fmt, int entity_id,
296 unsigned long *visited, bool validate)
297{
298 struct uac_clock_source_descriptor *source;
299 struct uac_clock_selector_descriptor *selector;
300 struct uac_clock_multiplier_descriptor *multiplier;
301
302 entity_id &= 0xff;
303
304 if (test_and_set_bit(entity_id, visited)) {
305 usb_audio_warn(chip,
306 "%s(): recursive clock topology detected, id %d.\n",
307 __func__, entity_id);
308 return -EINVAL;
309 }
310
311 /* first, see if the ID we're looking for is a clock source already */
312 source = snd_usb_find_clock_source(chip->ctrl_intf, entity_id);
313 if (source) {
314 entity_id = source->bClockID;
315 if (validate && !uac_clock_source_is_valid(chip, fmt,
316 entity_id)) {
317 usb_audio_err(chip,
318 "clock source %d is not valid, cannot use\n",
319 entity_id);
320 return -ENXIO;
321 }
322 return entity_id;
323 }
324
325 selector = snd_usb_find_clock_selector(chip->ctrl_intf, entity_id);
326 if (selector) {
327 int ret, i, cur, err;
328
329 /* the entity ID we are looking for is a selector.
330 * find out what it currently selects */
331 ret = uac_clock_selector_get_val(chip, selector->bClockID);
332 if (ret < 0)
333 return ret;
334
335 /* Selector values are one-based */
336
337 if (ret > selector->bNrInPins || ret < 1) {
338 usb_audio_err(chip,
339 "%s(): selector reported illegal value, id %d, ret %d\n",
340 __func__, selector->bClockID, ret);
341
342 return -EINVAL;
343 }
344
345 cur = ret;
346 ret = __uac_clock_find_source(chip, fmt,
347 selector->baCSourceID[ret - 1],
348 visited, validate);
349 if (ret > 0) {
350 /*
351 * For Samsung USBC Headset (AKG), setting clock selector again
352 * will result in incorrect default clock setting problems
353 */
354 if (chip->usb_id == USB_ID(0x04e8, 0xa051))
355 return ret;
356 err = uac_clock_selector_set_val(chip, entity_id, cur);
357 if (err < 0)
358 return err;
359 }
360
361 if (!validate || ret > 0 || !chip->autoclock)
362 return ret;
363
364 /* The current clock source is invalid, try others. */
365 for (i = 1; i <= selector->bNrInPins; i++) {
366 if (i == cur)
367 continue;
368
369 ret = __uac_clock_find_source(chip, fmt,
370 selector->baCSourceID[i - 1],
371 visited, true);
372 if (ret < 0)
373 continue;
374
375 err = uac_clock_selector_set_val(chip, entity_id, i);
376 if (err < 0)
377 continue;
378
379 usb_audio_info(chip,
380 "found and selected valid clock source %d\n",
381 ret);
382 return ret;
383 }
384
385 return -ENXIO;
386 }
387
388 /* FIXME: multipliers only act as pass-thru element for now */
389 multiplier = snd_usb_find_clock_multiplier(chip->ctrl_intf, entity_id);
390 if (multiplier)
391 return __uac_clock_find_source(chip, fmt,
392 multiplier->bCSourceID,
393 visited, validate);
394
395 return -EINVAL;
396}
397
398static int __uac3_clock_find_source(struct snd_usb_audio *chip,
399 struct audioformat *fmt, int entity_id,
400 unsigned long *visited, bool validate)
401{
402 struct uac3_clock_source_descriptor *source;
403 struct uac3_clock_selector_descriptor *selector;
404 struct uac3_clock_multiplier_descriptor *multiplier;
405
406 entity_id &= 0xff;
407
408 if (test_and_set_bit(entity_id, visited)) {
409 usb_audio_warn(chip,
410 "%s(): recursive clock topology detected, id %d.\n",
411 __func__, entity_id);
412 return -EINVAL;
413 }
414
415 /* first, see if the ID we're looking for is a clock source already */
416 source = snd_usb_find_clock_source_v3(chip->ctrl_intf, entity_id);
417 if (source) {
418 entity_id = source->bClockID;
419 if (validate && !uac_clock_source_is_valid(chip, fmt,
420 entity_id)) {
421 usb_audio_err(chip,
422 "clock source %d is not valid, cannot use\n",
423 entity_id);
424 return -ENXIO;
425 }
426 return entity_id;
427 }
428
429 selector = snd_usb_find_clock_selector_v3(chip->ctrl_intf, entity_id);
430 if (selector) {
431 int ret, i, cur, err;
432
433 /* the entity ID we are looking for is a selector.
434 * find out what it currently selects */
435 ret = uac_clock_selector_get_val(chip, selector->bClockID);
436 if (ret < 0)
437 return ret;
438
439 /* Selector values are one-based */
440
441 if (ret > selector->bNrInPins || ret < 1) {
442 usb_audio_err(chip,
443 "%s(): selector reported illegal value, id %d, ret %d\n",
444 __func__, selector->bClockID, ret);
445
446 return -EINVAL;
447 }
448
449 cur = ret;
450 ret = __uac3_clock_find_source(chip, fmt,
451 selector->baCSourceID[ret - 1],
452 visited, validate);
453 if (ret > 0) {
454 err = uac_clock_selector_set_val(chip, entity_id, cur);
455 if (err < 0)
456 return err;
457 }
458
459 if (!validate || ret > 0 || !chip->autoclock)
460 return ret;
461
462 /* The current clock source is invalid, try others. */
463 for (i = 1; i <= selector->bNrInPins; i++) {
464 int err;
465
466 if (i == cur)
467 continue;
468
469 ret = __uac3_clock_find_source(chip, fmt,
470 selector->baCSourceID[i - 1],
471 visited, true);
472 if (ret < 0)
473 continue;
474
475 err = uac_clock_selector_set_val(chip, entity_id, i);
476 if (err < 0)
477 continue;
478
479 usb_audio_info(chip,
480 "found and selected valid clock source %d\n",
481 ret);
482 return ret;
483 }
484
485 return -ENXIO;
486 }
487
488 /* FIXME: multipliers only act as pass-thru element for now */
489 multiplier = snd_usb_find_clock_multiplier_v3(chip->ctrl_intf,
490 entity_id);
491 if (multiplier)
492 return __uac3_clock_find_source(chip, fmt,
493 multiplier->bCSourceID,
494 visited, validate);
495
496 return -EINVAL;
497}
498
499/*
500 * For all kinds of sample rate settings and other device queries,
501 * the clock source (end-leaf) must be used. However, clock selectors,
502 * clock multipliers and sample rate converters may be specified as
503 * clock source input to terminal. This functions walks the clock path
504 * to its end and tries to find the source.
505 *
506 * The 'visited' bitfield is used internally to detect recursive loops.
507 *
508 * Returns the clock source UnitID (>=0) on success, or an error.
509 */
510int snd_usb_clock_find_source(struct snd_usb_audio *chip,
511 struct audioformat *fmt, bool validate)
512{
513 DECLARE_BITMAP(visited, 256);
514 memset(visited, 0, sizeof(visited));
515
516 switch (fmt->protocol) {
517 case UAC_VERSION_2:
518 return __uac_clock_find_source(chip, fmt, fmt->clock, visited,
519 validate);
520 case UAC_VERSION_3:
521 return __uac3_clock_find_source(chip, fmt, fmt->clock, visited,
522 validate);
523 default:
524 return -EINVAL;
525 }
526}
527
528static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface,
529 struct usb_host_interface *alts,
530 struct audioformat *fmt, int rate)
531{
532 struct usb_device *dev = chip->dev;
533 unsigned int ep;
534 unsigned char data[3];
535 int err, crate;
536
537 if (get_iface_desc(alts)->bNumEndpoints < 1)
538 return -EINVAL;
539 ep = get_endpoint(alts, 0)->bEndpointAddress;
540
541 /* if endpoint doesn't have sampling rate control, bail out */
542 if (!(fmt->attributes & UAC_EP_CS_ATTR_SAMPLE_RATE))
543 return 0;
544
545 data[0] = rate;
546 data[1] = rate >> 8;
547 data[2] = rate >> 16;
548 err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR,
549 USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_OUT,
550 UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep,
551 data, sizeof(data));
552 if (err < 0) {
553 dev_err(&dev->dev, "%d:%d: cannot set freq %d to ep %#x\n",
554 iface, fmt->altsetting, rate, ep);
555 return err;
556 }
557
558 /* Don't check the sample rate for devices which we know don't
559 * support reading */
560 if (snd_usb_get_sample_rate_quirk(chip))
561 return 0;
562 /* the firmware is likely buggy, don't repeat to fail too many times */
563 if (chip->sample_rate_read_error > 2)
564 return 0;
565
566 err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC_GET_CUR,
567 USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_IN,
568 UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep,
569 data, sizeof(data));
570 if (err < 0) {
571 dev_err(&dev->dev, "%d:%d: cannot get freq at ep %#x\n",
572 iface, fmt->altsetting, ep);
573 chip->sample_rate_read_error++;
574 return 0; /* some devices don't support reading */
575 }
576
577 crate = data[0] | (data[1] << 8) | (data[2] << 16);
578 if (!crate) {
579 dev_info(&dev->dev, "failed to read current rate; disabling the check\n");
580 chip->sample_rate_read_error = 3; /* three strikes, see above */
581 return 0;
582 }
583
584 if (crate != rate) {
585 dev_warn(&dev->dev, "current rate %d is different from the runtime rate %d\n", crate, rate);
586 // runtime->rate = crate;
587 }
588
589 return 0;
590}
591
592static int get_sample_rate_v2v3(struct snd_usb_audio *chip, int iface,
593 int altsetting, int clock)
594{
595 struct usb_device *dev = chip->dev;
596 __le32 data;
597 int err;
598
599 err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
600 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
601 UAC2_CS_CONTROL_SAM_FREQ << 8,
602 snd_usb_ctrl_intf(chip) | (clock << 8),
603 &data, sizeof(data));
604 if (err < 0) {
605 dev_warn(&dev->dev, "%d:%d: cannot get freq (v2/v3): err %d\n",
606 iface, altsetting, err);
607 return 0;
608 }
609
610 return le32_to_cpu(data);
611}
612
613static int set_sample_rate_v2v3(struct snd_usb_audio *chip, int iface,
614 struct usb_host_interface *alts,
615 struct audioformat *fmt, int rate)
616{
617 struct usb_device *dev = chip->dev;
618 __le32 data;
619 int err, cur_rate, prev_rate;
620 int clock;
621 bool writeable;
622 u32 bmControls;
623
624 /* First, try to find a valid clock. This may trigger
625 * automatic clock selection if the current clock is not
626 * valid.
627 */
628 clock = snd_usb_clock_find_source(chip, fmt, true);
629 if (clock < 0) {
630 /* We did not find a valid clock, but that might be
631 * because the current sample rate does not match an
632 * external clock source. Try again without validation
633 * and we will do another validation after setting the
634 * rate.
635 */
636 clock = snd_usb_clock_find_source(chip, fmt, false);
637 if (clock < 0)
638 return clock;
639 }
640
641 prev_rate = get_sample_rate_v2v3(chip, iface, fmt->altsetting, clock);
642 if (prev_rate == rate)
643 goto validation;
644
645 if (fmt->protocol == UAC_VERSION_3) {
646 struct uac3_clock_source_descriptor *cs_desc;
647
648 cs_desc = snd_usb_find_clock_source_v3(chip->ctrl_intf, clock);
649 bmControls = le32_to_cpu(cs_desc->bmControls);
650 } else {
651 struct uac_clock_source_descriptor *cs_desc;
652
653 cs_desc = snd_usb_find_clock_source(chip->ctrl_intf, clock);
654 bmControls = cs_desc->bmControls;
655 }
656
657 writeable = uac_v2v3_control_is_writeable(bmControls,
658 UAC2_CS_CONTROL_SAM_FREQ);
659 if (writeable) {
660 data = cpu_to_le32(rate);
661 err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC2_CS_CUR,
662 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
663 UAC2_CS_CONTROL_SAM_FREQ << 8,
664 snd_usb_ctrl_intf(chip) | (clock << 8),
665 &data, sizeof(data));
666 if (err < 0) {
667 usb_audio_err(chip,
668 "%d:%d: cannot set freq %d (v2/v3): err %d\n",
669 iface, fmt->altsetting, rate, err);
670 return err;
671 }
672
673 cur_rate = get_sample_rate_v2v3(chip, iface,
674 fmt->altsetting, clock);
675 } else {
676 cur_rate = prev_rate;
677 }
678
679 if (cur_rate != rate) {
680 if (!writeable) {
681 usb_audio_warn(chip,
682 "%d:%d: freq mismatch (RO clock): req %d, clock runs @%d\n",
683 iface, fmt->altsetting, rate, cur_rate);
684 return -ENXIO;
685 }
686 usb_audio_dbg(chip,
687 "current rate %d is different from the runtime rate %d\n",
688 cur_rate, rate);
689 }
690
691 /* Some devices doesn't respond to sample rate changes while the
692 * interface is active. */
693 if (rate != prev_rate) {
694 usb_set_interface(dev, iface, 0);
695
696 snd_vendor_set_interface(dev, alts, iface, 0);
697
698 snd_usb_set_interface_quirk(dev);
699 usb_set_interface(dev, iface, fmt->altsetting);
700
701 snd_vendor_set_interface(dev, alts, iface, fmt->altsetting);
702 snd_usb_set_interface_quirk(dev);
703 }
704
705validation:
706 /* validate clock after rate change */
707 if (!uac_clock_source_is_valid(chip, fmt, clock))
708 return -ENXIO;
709 return 0;
710}
711
712int snd_usb_init_sample_rate(struct snd_usb_audio *chip, int iface,
713 struct usb_host_interface *alts,
714 struct audioformat *fmt, int rate)
715{
716 switch (fmt->protocol) {
717 case UAC_VERSION_1:
718 default:
719 return set_sample_rate_v1(chip, iface, alts, fmt, rate);
720
721 case UAC_VERSION_3:
722 if (chip->badd_profile >= UAC3_FUNCTION_SUBCLASS_GENERIC_IO) {
723 if (rate != UAC3_BADD_SAMPLING_RATE)
724 return -ENXIO;
725 else
726 return 0;
727 }
728 /* fall through */
729 case UAC_VERSION_2:
730 return set_sample_rate_v2v3(chip, iface, alts, fmt, rate);
731 }
732}
733