1 | // 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 | union uac23_clock_source_desc { |
25 | struct uac_clock_source_descriptor v2; |
26 | struct uac3_clock_source_descriptor v3; |
27 | }; |
28 | |
29 | union uac23_clock_selector_desc { |
30 | struct uac_clock_selector_descriptor v2; |
31 | struct uac3_clock_selector_descriptor v3; |
32 | }; |
33 | |
34 | union uac23_clock_multiplier_desc { |
35 | struct uac_clock_multiplier_descriptor v2; |
36 | struct uac_clock_multiplier_descriptor v3; |
37 | }; |
38 | |
39 | #define GET_VAL(p, proto, field) \ |
40 | ((proto) == UAC_VERSION_3 ? (p)->v3.field : (p)->v2.field) |
41 | |
42 | static void *find_uac_clock_desc(struct usb_host_interface *iface, int id, |
43 | bool (*validator)(void *, int, int), |
44 | u8 type, int proto) |
45 | { |
46 | void *cs = NULL; |
47 | |
48 | while ((cs = snd_usb_find_csint_desc(descstart: iface->extra, desclen: iface->extralen, |
49 | after: cs, dsubtype: type))) { |
50 | if (validator(cs, id, proto)) |
51 | return cs; |
52 | } |
53 | |
54 | return NULL; |
55 | } |
56 | |
57 | static bool validate_clock_source(void *p, int id, int proto) |
58 | { |
59 | union uac23_clock_source_desc *cs = p; |
60 | |
61 | return GET_VAL(cs, proto, bClockID) == id; |
62 | } |
63 | |
64 | static bool validate_clock_selector(void *p, int id, int proto) |
65 | { |
66 | union uac23_clock_selector_desc *cs = p; |
67 | |
68 | return GET_VAL(cs, proto, bClockID) == id; |
69 | } |
70 | |
71 | static bool validate_clock_multiplier(void *p, int id, int proto) |
72 | { |
73 | union uac23_clock_multiplier_desc *cs = p; |
74 | |
75 | return GET_VAL(cs, proto, bClockID) == id; |
76 | } |
77 | |
78 | #define DEFINE_FIND_HELPER(name, obj, validator, type2, type3) \ |
79 | static obj *name(struct snd_usb_audio *chip, int id, int proto) \ |
80 | { \ |
81 | return find_uac_clock_desc(chip->ctrl_intf, id, validator, \ |
82 | proto == UAC_VERSION_3 ? (type3) : (type2), \ |
83 | proto); \ |
84 | } |
85 | |
86 | DEFINE_FIND_HELPER(snd_usb_find_clock_source, |
87 | union uac23_clock_source_desc, validate_clock_source, |
88 | UAC2_CLOCK_SOURCE, UAC3_CLOCK_SOURCE); |
89 | DEFINE_FIND_HELPER(snd_usb_find_clock_selector, |
90 | union uac23_clock_selector_desc, validate_clock_selector, |
91 | UAC2_CLOCK_SELECTOR, UAC3_CLOCK_SELECTOR); |
92 | DEFINE_FIND_HELPER(snd_usb_find_clock_multiplier, |
93 | union uac23_clock_multiplier_desc, validate_clock_multiplier, |
94 | UAC2_CLOCK_MULTIPLIER, UAC3_CLOCK_MULTIPLIER); |
95 | |
96 | static int uac_clock_selector_get_val(struct snd_usb_audio *chip, int selector_id) |
97 | { |
98 | unsigned char buf; |
99 | int ret; |
100 | |
101 | ret = snd_usb_ctl_msg(dev: chip->dev, usb_rcvctrlpipe(chip->dev, 0), |
102 | UAC2_CS_CUR, |
103 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, |
104 | UAC2_CX_CLOCK_SELECTOR << 8, |
105 | index: snd_usb_ctrl_intf(chip) | (selector_id << 8), |
106 | data: &buf, size: sizeof(buf)); |
107 | |
108 | if (ret < 0) |
109 | return ret; |
110 | |
111 | return buf; |
112 | } |
113 | |
114 | static int uac_clock_selector_set_val(struct snd_usb_audio *chip, int selector_id, |
115 | unsigned char pin) |
116 | { |
117 | int ret; |
118 | |
119 | ret = snd_usb_ctl_msg(dev: chip->dev, usb_sndctrlpipe(chip->dev, 0), |
120 | UAC2_CS_CUR, |
121 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, |
122 | UAC2_CX_CLOCK_SELECTOR << 8, |
123 | index: snd_usb_ctrl_intf(chip) | (selector_id << 8), |
124 | data: &pin, size: sizeof(pin)); |
125 | if (ret < 0) |
126 | return ret; |
127 | |
128 | if (ret != sizeof(pin)) { |
129 | usb_audio_err(chip, |
130 | "setting selector (id %d) unexpected length %d\n" , |
131 | selector_id, ret); |
132 | return -EINVAL; |
133 | } |
134 | |
135 | ret = uac_clock_selector_get_val(chip, selector_id); |
136 | if (ret < 0) |
137 | return ret; |
138 | |
139 | if (ret != pin) { |
140 | usb_audio_err(chip, |
141 | "setting selector (id %d) to %x failed (current: %d)\n" , |
142 | selector_id, pin, ret); |
143 | return -EINVAL; |
144 | } |
145 | |
146 | return ret; |
147 | } |
148 | |
149 | static bool uac_clock_source_is_valid_quirk(struct snd_usb_audio *chip, |
150 | const struct audioformat *fmt, |
151 | int source_id) |
152 | { |
153 | bool ret = false; |
154 | int count; |
155 | unsigned char data; |
156 | struct usb_device *dev = chip->dev; |
157 | union uac23_clock_source_desc *cs_desc; |
158 | |
159 | cs_desc = snd_usb_find_clock_source(chip, id: source_id, proto: fmt->protocol); |
160 | if (!cs_desc) |
161 | return false; |
162 | |
163 | if (fmt->protocol == UAC_VERSION_2) { |
164 | /* |
165 | * Assume the clock is valid if clock source supports only one |
166 | * single sample rate, the terminal is connected directly to it |
167 | * (there is no clock selector) and clock type is internal. |
168 | * This is to deal with some Denon DJ controllers that always |
169 | * reports that clock is invalid. |
170 | */ |
171 | if (fmt->nr_rates == 1 && |
172 | (fmt->clock & 0xff) == cs_desc->v2.bClockID && |
173 | (cs_desc->v2.bmAttributes & 0x3) != |
174 | UAC_CLOCK_SOURCE_TYPE_EXT) |
175 | return true; |
176 | } |
177 | |
178 | /* |
179 | * MOTU MicroBook IIc |
180 | * Sample rate changes takes more than 2 seconds for this device. Clock |
181 | * validity request returns false during that period. |
182 | */ |
183 | if (chip->usb_id == USB_ID(0x07fd, 0x0004)) { |
184 | count = 0; |
185 | |
186 | while ((!ret) && (count < 50)) { |
187 | int err; |
188 | |
189 | msleep(msecs: 100); |
190 | |
191 | err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR, |
192 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, |
193 | UAC2_CS_CONTROL_CLOCK_VALID << 8, |
194 | index: snd_usb_ctrl_intf(chip) | (source_id << 8), |
195 | data: &data, size: sizeof(data)); |
196 | if (err < 0) { |
197 | dev_warn(&dev->dev, |
198 | "%s(): cannot get clock validity for id %d\n" , |
199 | __func__, source_id); |
200 | return false; |
201 | } |
202 | |
203 | ret = !!data; |
204 | count++; |
205 | } |
206 | } |
207 | |
208 | return ret; |
209 | } |
210 | |
211 | static bool uac_clock_source_is_valid(struct snd_usb_audio *chip, |
212 | const struct audioformat *fmt, |
213 | int source_id) |
214 | { |
215 | int err; |
216 | unsigned char data; |
217 | struct usb_device *dev = chip->dev; |
218 | u32 bmControls; |
219 | union uac23_clock_source_desc *cs_desc; |
220 | |
221 | cs_desc = snd_usb_find_clock_source(chip, id: source_id, proto: fmt->protocol); |
222 | if (!cs_desc) |
223 | return false; |
224 | |
225 | if (fmt->protocol == UAC_VERSION_3) |
226 | bmControls = le32_to_cpu(cs_desc->v3.bmControls); |
227 | else |
228 | bmControls = cs_desc->v2.bmControls; |
229 | |
230 | /* If a clock source can't tell us whether it's valid, we assume it is */ |
231 | if (!uac_v2v3_control_is_readable(bmControls, |
232 | UAC2_CS_CONTROL_CLOCK_VALID)) |
233 | return true; |
234 | |
235 | err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR, |
236 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, |
237 | UAC2_CS_CONTROL_CLOCK_VALID << 8, |
238 | index: snd_usb_ctrl_intf(chip) | (source_id << 8), |
239 | data: &data, size: sizeof(data)); |
240 | |
241 | if (err < 0) { |
242 | dev_warn(&dev->dev, |
243 | "%s(): cannot get clock validity for id %d\n" , |
244 | __func__, source_id); |
245 | return false; |
246 | } |
247 | |
248 | if (data) |
249 | return true; |
250 | else |
251 | return uac_clock_source_is_valid_quirk(chip, fmt, source_id); |
252 | } |
253 | |
254 | static int __uac_clock_find_source(struct snd_usb_audio *chip, |
255 | const struct audioformat *fmt, int entity_id, |
256 | unsigned long *visited, bool validate) |
257 | { |
258 | union uac23_clock_source_desc *source; |
259 | union uac23_clock_selector_desc *selector; |
260 | union uac23_clock_multiplier_desc *multiplier; |
261 | int ret, i, cur, err, pins, clock_id; |
262 | const u8 *sources; |
263 | int proto = fmt->protocol; |
264 | bool readable, writeable; |
265 | u32 bmControls; |
266 | |
267 | entity_id &= 0xff; |
268 | |
269 | if (test_and_set_bit(nr: entity_id, addr: visited)) { |
270 | usb_audio_warn(chip, |
271 | "%s(): recursive clock topology detected, id %d.\n" , |
272 | __func__, entity_id); |
273 | return -EINVAL; |
274 | } |
275 | |
276 | /* first, see if the ID we're looking at is a clock source already */ |
277 | source = snd_usb_find_clock_source(chip, id: entity_id, proto); |
278 | if (source) { |
279 | entity_id = GET_VAL(source, proto, bClockID); |
280 | if (validate && !uac_clock_source_is_valid(chip, fmt, |
281 | source_id: entity_id)) { |
282 | usb_audio_err(chip, |
283 | "clock source %d is not valid, cannot use\n" , |
284 | entity_id); |
285 | return -ENXIO; |
286 | } |
287 | return entity_id; |
288 | } |
289 | |
290 | selector = snd_usb_find_clock_selector(chip, id: entity_id, proto); |
291 | if (selector) { |
292 | pins = GET_VAL(selector, proto, bNrInPins); |
293 | clock_id = GET_VAL(selector, proto, bClockID); |
294 | sources = GET_VAL(selector, proto, baCSourceID); |
295 | cur = 0; |
296 | |
297 | if (proto == UAC_VERSION_3) |
298 | bmControls = le32_to_cpu(*(__le32 *)(&selector->v3.baCSourceID[0] + pins)); |
299 | else |
300 | bmControls = *(__u8 *)(&selector->v2.baCSourceID[0] + pins); |
301 | |
302 | readable = uac_v2v3_control_is_readable(bmControls, |
303 | UAC2_CX_CLOCK_SELECTOR); |
304 | writeable = uac_v2v3_control_is_writeable(bmControls, |
305 | UAC2_CX_CLOCK_SELECTOR); |
306 | |
307 | if (pins == 1) { |
308 | ret = 1; |
309 | goto find_source; |
310 | } |
311 | |
312 | /* for now just warn about buggy device */ |
313 | if (!readable) |
314 | usb_audio_warn(chip, |
315 | "%s(): clock selector control is not readable, id %d\n" , |
316 | __func__, clock_id); |
317 | |
318 | /* the entity ID we are looking at is a selector. |
319 | * find out what it currently selects */ |
320 | ret = uac_clock_selector_get_val(chip, selector_id: clock_id); |
321 | if (ret < 0) { |
322 | if (!chip->autoclock) |
323 | return ret; |
324 | goto find_others; |
325 | } |
326 | |
327 | /* Selector values are one-based */ |
328 | |
329 | if (ret > pins || ret < 1) { |
330 | usb_audio_err(chip, |
331 | "%s(): selector reported illegal value, id %d, ret %d\n" , |
332 | __func__, clock_id, ret); |
333 | |
334 | if (!chip->autoclock) |
335 | return -EINVAL; |
336 | goto find_others; |
337 | } |
338 | |
339 | find_source: |
340 | cur = ret; |
341 | ret = __uac_clock_find_source(chip, fmt, |
342 | entity_id: sources[ret - 1], |
343 | visited, validate); |
344 | if (ret > 0) { |
345 | /* Skip setting clock selector again for some devices */ |
346 | if (chip->quirk_flags & QUIRK_FLAG_SKIP_CLOCK_SELECTOR || |
347 | !writeable) |
348 | return ret; |
349 | err = uac_clock_selector_set_val(chip, selector_id: entity_id, pin: cur); |
350 | if (err < 0) { |
351 | if (pins == 1) { |
352 | usb_audio_dbg(chip, |
353 | "%s(): selector returned an error, " |
354 | "assuming a firmware bug, id %d, ret %d\n" , |
355 | __func__, clock_id, err); |
356 | return ret; |
357 | } |
358 | return err; |
359 | } |
360 | } |
361 | |
362 | if (!validate || ret > 0 || !chip->autoclock) |
363 | return ret; |
364 | |
365 | find_others: |
366 | if (!writeable) |
367 | return -ENXIO; |
368 | |
369 | /* The current clock source is invalid, try others. */ |
370 | for (i = 1; i <= pins; i++) { |
371 | if (i == cur) |
372 | continue; |
373 | |
374 | ret = __uac_clock_find_source(chip, fmt, |
375 | entity_id: sources[i - 1], |
376 | visited, validate: true); |
377 | if (ret < 0) |
378 | continue; |
379 | |
380 | err = uac_clock_selector_set_val(chip, selector_id: entity_id, pin: i); |
381 | if (err < 0) |
382 | continue; |
383 | |
384 | usb_audio_info(chip, |
385 | "found and selected valid clock source %d\n" , |
386 | ret); |
387 | return ret; |
388 | } |
389 | |
390 | return -ENXIO; |
391 | } |
392 | |
393 | /* FIXME: multipliers only act as pass-thru element for now */ |
394 | multiplier = snd_usb_find_clock_multiplier(chip, id: entity_id, proto); |
395 | if (multiplier) |
396 | return __uac_clock_find_source(chip, fmt, |
397 | GET_VAL(multiplier, proto, bCSourceID), |
398 | visited, validate); |
399 | |
400 | return -EINVAL; |
401 | } |
402 | |
403 | /* |
404 | * For all kinds of sample rate settings and other device queries, |
405 | * the clock source (end-leaf) must be used. However, clock selectors, |
406 | * clock multipliers and sample rate converters may be specified as |
407 | * clock source input to terminal. This functions walks the clock path |
408 | * to its end and tries to find the source. |
409 | * |
410 | * The 'visited' bitfield is used internally to detect recursive loops. |
411 | * |
412 | * Returns the clock source UnitID (>=0) on success, or an error. |
413 | */ |
414 | int snd_usb_clock_find_source(struct snd_usb_audio *chip, |
415 | const struct audioformat *fmt, bool validate) |
416 | { |
417 | DECLARE_BITMAP(visited, 256); |
418 | memset(visited, 0, sizeof(visited)); |
419 | |
420 | switch (fmt->protocol) { |
421 | case UAC_VERSION_2: |
422 | case UAC_VERSION_3: |
423 | return __uac_clock_find_source(chip, fmt, entity_id: fmt->clock, visited, |
424 | validate); |
425 | default: |
426 | return -EINVAL; |
427 | } |
428 | } |
429 | |
430 | static int set_sample_rate_v1(struct snd_usb_audio *chip, |
431 | const struct audioformat *fmt, int rate) |
432 | { |
433 | struct usb_device *dev = chip->dev; |
434 | unsigned char data[3]; |
435 | int err, crate; |
436 | |
437 | /* if endpoint doesn't have sampling rate control, bail out */ |
438 | if (!(fmt->attributes & UAC_EP_CS_ATTR_SAMPLE_RATE)) |
439 | return 0; |
440 | |
441 | data[0] = rate; |
442 | data[1] = rate >> 8; |
443 | data[2] = rate >> 16; |
444 | err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR, |
445 | USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_OUT, |
446 | UAC_EP_CS_ATTR_SAMPLE_RATE << 8, |
447 | index: fmt->endpoint, data, size: sizeof(data)); |
448 | if (err < 0) { |
449 | dev_err(&dev->dev, "%d:%d: cannot set freq %d to ep %#x\n" , |
450 | fmt->iface, fmt->altsetting, rate, fmt->endpoint); |
451 | return err; |
452 | } |
453 | |
454 | /* Don't check the sample rate for devices which we know don't |
455 | * support reading */ |
456 | if (chip->quirk_flags & QUIRK_FLAG_GET_SAMPLE_RATE) |
457 | return 0; |
458 | /* the firmware is likely buggy, don't repeat to fail too many times */ |
459 | if (chip->sample_rate_read_error > 2) |
460 | return 0; |
461 | |
462 | err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC_GET_CUR, |
463 | USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_IN, |
464 | UAC_EP_CS_ATTR_SAMPLE_RATE << 8, |
465 | index: fmt->endpoint, data, size: sizeof(data)); |
466 | if (err < 0) { |
467 | dev_err(&dev->dev, "%d:%d: cannot get freq at ep %#x\n" , |
468 | fmt->iface, fmt->altsetting, fmt->endpoint); |
469 | chip->sample_rate_read_error++; |
470 | return 0; /* some devices don't support reading */ |
471 | } |
472 | |
473 | crate = data[0] | (data[1] << 8) | (data[2] << 16); |
474 | if (!crate) { |
475 | dev_info(&dev->dev, "failed to read current rate; disabling the check\n" ); |
476 | chip->sample_rate_read_error = 3; /* three strikes, see above */ |
477 | return 0; |
478 | } |
479 | |
480 | if (crate != rate) { |
481 | dev_warn(&dev->dev, "current rate %d is different from the runtime rate %d\n" , crate, rate); |
482 | // runtime->rate = crate; |
483 | } |
484 | |
485 | return 0; |
486 | } |
487 | |
488 | static int get_sample_rate_v2v3(struct snd_usb_audio *chip, int iface, |
489 | int altsetting, int clock) |
490 | { |
491 | struct usb_device *dev = chip->dev; |
492 | __le32 data; |
493 | int err; |
494 | |
495 | err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR, |
496 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, |
497 | UAC2_CS_CONTROL_SAM_FREQ << 8, |
498 | index: snd_usb_ctrl_intf(chip) | (clock << 8), |
499 | data: &data, size: sizeof(data)); |
500 | if (err < 0) { |
501 | dev_warn(&dev->dev, "%d:%d: cannot get freq (v2/v3): err %d\n" , |
502 | iface, altsetting, err); |
503 | return 0; |
504 | } |
505 | |
506 | return le32_to_cpu(data); |
507 | } |
508 | |
509 | /* |
510 | * Try to set the given sample rate: |
511 | * |
512 | * Return 0 if the clock source is read-only, the actual rate on success, |
513 | * or a negative error code. |
514 | * |
515 | * This function gets called from format.c to validate each sample rate, too. |
516 | * Hence no message is shown upon error |
517 | */ |
518 | int snd_usb_set_sample_rate_v2v3(struct snd_usb_audio *chip, |
519 | const struct audioformat *fmt, |
520 | int clock, int rate) |
521 | { |
522 | bool writeable; |
523 | u32 bmControls; |
524 | __le32 data; |
525 | int err; |
526 | union uac23_clock_source_desc *cs_desc; |
527 | |
528 | cs_desc = snd_usb_find_clock_source(chip, id: clock, proto: fmt->protocol); |
529 | |
530 | if (!cs_desc) |
531 | return 0; |
532 | |
533 | if (fmt->protocol == UAC_VERSION_3) |
534 | bmControls = le32_to_cpu(cs_desc->v3.bmControls); |
535 | else |
536 | bmControls = cs_desc->v2.bmControls; |
537 | |
538 | writeable = uac_v2v3_control_is_writeable(bmControls, |
539 | UAC2_CS_CONTROL_SAM_FREQ); |
540 | if (!writeable) |
541 | return 0; |
542 | |
543 | data = cpu_to_le32(rate); |
544 | err = snd_usb_ctl_msg(dev: chip->dev, usb_sndctrlpipe(chip->dev, 0), UAC2_CS_CUR, |
545 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, |
546 | UAC2_CS_CONTROL_SAM_FREQ << 8, |
547 | index: snd_usb_ctrl_intf(chip) | (clock << 8), |
548 | data: &data, size: sizeof(data)); |
549 | if (err < 0) |
550 | return err; |
551 | |
552 | return get_sample_rate_v2v3(chip, iface: fmt->iface, altsetting: fmt->altsetting, clock); |
553 | } |
554 | |
555 | static int set_sample_rate_v2v3(struct snd_usb_audio *chip, |
556 | const struct audioformat *fmt, int rate) |
557 | { |
558 | int cur_rate, prev_rate; |
559 | int clock; |
560 | |
561 | /* First, try to find a valid clock. This may trigger |
562 | * automatic clock selection if the current clock is not |
563 | * valid. |
564 | */ |
565 | clock = snd_usb_clock_find_source(chip, fmt, validate: true); |
566 | if (clock < 0) { |
567 | /* We did not find a valid clock, but that might be |
568 | * because the current sample rate does not match an |
569 | * external clock source. Try again without validation |
570 | * and we will do another validation after setting the |
571 | * rate. |
572 | */ |
573 | clock = snd_usb_clock_find_source(chip, fmt, validate: false); |
574 | |
575 | /* Hardcoded sample rates */ |
576 | if (chip->quirk_flags & QUIRK_FLAG_IGNORE_CLOCK_SOURCE) |
577 | return 0; |
578 | |
579 | if (clock < 0) |
580 | return clock; |
581 | } |
582 | |
583 | prev_rate = get_sample_rate_v2v3(chip, iface: fmt->iface, altsetting: fmt->altsetting, clock); |
584 | if (prev_rate == rate) |
585 | goto validation; |
586 | |
587 | cur_rate = snd_usb_set_sample_rate_v2v3(chip, fmt, clock, rate); |
588 | if (cur_rate < 0) { |
589 | usb_audio_err(chip, |
590 | "%d:%d: cannot set freq %d (v2/v3): err %d\n" , |
591 | fmt->iface, fmt->altsetting, rate, cur_rate); |
592 | return cur_rate; |
593 | } |
594 | |
595 | if (!cur_rate) |
596 | cur_rate = prev_rate; |
597 | |
598 | if (cur_rate != rate) { |
599 | usb_audio_dbg(chip, |
600 | "%d:%d: freq mismatch: req %d, clock runs @%d\n" , |
601 | fmt->iface, fmt->altsetting, rate, cur_rate); |
602 | /* continue processing */ |
603 | } |
604 | |
605 | /* FIXME - TEAC devices require the immediate interface setup */ |
606 | if (USB_ID_VENDOR(chip->usb_id) == 0x0644) { |
607 | bool cur_base_48k = (rate % 48000 == 0); |
608 | bool prev_base_48k = (prev_rate % 48000 == 0); |
609 | if (cur_base_48k != prev_base_48k) { |
610 | usb_set_interface(dev: chip->dev, ifnum: fmt->iface, alternate: fmt->altsetting); |
611 | if (chip->quirk_flags & QUIRK_FLAG_IFACE_DELAY) |
612 | msleep(msecs: 50); |
613 | } |
614 | } |
615 | |
616 | validation: |
617 | /* validate clock after rate change */ |
618 | if (!uac_clock_source_is_valid(chip, fmt, source_id: clock)) |
619 | return -ENXIO; |
620 | return 0; |
621 | } |
622 | |
623 | int snd_usb_init_sample_rate(struct snd_usb_audio *chip, |
624 | const struct audioformat *fmt, int rate) |
625 | { |
626 | usb_audio_dbg(chip, "%d:%d Set sample rate %d, clock %d\n" , |
627 | fmt->iface, fmt->altsetting, rate, fmt->clock); |
628 | |
629 | switch (fmt->protocol) { |
630 | case UAC_VERSION_1: |
631 | default: |
632 | return set_sample_rate_v1(chip, fmt, rate); |
633 | |
634 | case UAC_VERSION_3: |
635 | if (chip->badd_profile >= UAC3_FUNCTION_SUBCLASS_GENERIC_IO) { |
636 | if (rate != UAC3_BADD_SAMPLING_RATE) |
637 | return -ENXIO; |
638 | else |
639 | return 0; |
640 | } |
641 | fallthrough; |
642 | case UAC_VERSION_2: |
643 | return set_sample_rate_v2v3(chip, fmt, rate); |
644 | } |
645 | } |
646 | |
647 | |