Commit | Line | Data |
---|---|---|
1a59d1b8 | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
79f920fb DM |
2 | /* |
3 | * Clock domain and sample rate management functions | |
79f920fb DM |
4 | */ |
5 | ||
6 | #include <linux/bitops.h> | |
7 | #include <linux/init.h> | |
79f920fb DM |
8 | #include <linux/string.h> |
9 | #include <linux/usb.h> | |
79f920fb DM |
10 | #include <linux/usb/audio.h> |
11 | #include <linux/usb/audio-v2.h> | |
9a2fe9b8 | 12 | #include <linux/usb/audio-v3.h> |
79f920fb DM |
13 | |
14 | #include <sound/core.h> | |
15 | #include <sound/info.h> | |
16 | #include <sound/pcm.h> | |
79f920fb DM |
17 | |
18 | #include "usbaudio.h" | |
19 | #include "card.h" | |
79f920fb | 20 | #include "helper.h" |
f22aa949 | 21 | #include "clock.h" |
21bb5aaf | 22 | #include "quirks.h" |
79f920fb | 23 | |
9ec73005 TI |
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 | ||
f7645bd6 | 42 | static void *find_uac_clock_desc(struct usb_host_interface *iface, int id, |
9ec73005 TI |
43 | bool (*validator)(void *, int, int), |
44 | u8 type, int proto) | |
79f920fb | 45 | { |
f7645bd6 | 46 | void *cs = NULL; |
79f920fb | 47 | |
f7645bd6 TI |
48 | while ((cs = snd_usb_find_csint_desc(iface->extra, iface->extralen, |
49 | cs, type))) { | |
9ec73005 | 50 | if (validator(cs, id, proto)) |
79f920fb DM |
51 | return cs; |
52 | } | |
53 | ||
54 | return NULL; | |
55 | } | |
56 | ||
9ec73005 | 57 | static bool validate_clock_source(void *p, int id, int proto) |
9a2fe9b8 | 58 | { |
9ec73005 | 59 | union uac23_clock_source_desc *cs = p; |
9a2fe9b8 | 60 | |
9ec73005 | 61 | return GET_VAL(cs, proto, bClockID) == id; |
79f920fb DM |
62 | } |
63 | ||
9ec73005 | 64 | static bool validate_clock_selector(void *p, int id, int proto) |
9a2fe9b8 | 65 | { |
9ec73005 | 66 | union uac23_clock_selector_desc *cs = p; |
9a2fe9b8 | 67 | |
9ec73005 | 68 | return GET_VAL(cs, proto, bClockID) == id; |
79f920fb DM |
69 | } |
70 | ||
9ec73005 | 71 | static bool validate_clock_multiplier(void *p, int id, int proto) |
9a2fe9b8 | 72 | { |
9ec73005 | 73 | union uac23_clock_multiplier_desc *cs = p; |
9a2fe9b8 | 74 | |
9ec73005 | 75 | return GET_VAL(cs, proto, bClockID) == id; |
f7645bd6 | 76 | } |
9a2fe9b8 | 77 | |
9ec73005 TI |
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); \ | |
9a2fe9b8 RB |
84 | } |
85 | ||
f7645bd6 | 86 | DEFINE_FIND_HELPER(snd_usb_find_clock_source, |
9ec73005 TI |
87 | union uac23_clock_source_desc, validate_clock_source, |
88 | UAC2_CLOCK_SOURCE, UAC3_CLOCK_SOURCE); | |
f7645bd6 | 89 | DEFINE_FIND_HELPER(snd_usb_find_clock_selector, |
9ec73005 TI |
90 | union uac23_clock_selector_desc, validate_clock_selector, |
91 | UAC2_CLOCK_SELECTOR, UAC3_CLOCK_SELECTOR); | |
f7645bd6 | 92 | DEFINE_FIND_HELPER(snd_usb_find_clock_multiplier, |
9ec73005 TI |
93 | union uac23_clock_multiplier_desc, validate_clock_multiplier, |
94 | UAC2_CLOCK_MULTIPLIER, UAC3_CLOCK_MULTIPLIER); | |
f7645bd6 | 95 | |
79f920fb DM |
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(chip->dev, usb_rcvctrlpipe(chip->dev, 0), | |
102 | UAC2_CS_CUR, | |
103 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, | |
11bcbc44 DM |
104 | UAC2_CX_CLOCK_SELECTOR << 8, |
105 | snd_usb_ctrl_intf(chip) | (selector_id << 8), | |
17d900c4 | 106 | &buf, sizeof(buf)); |
79f920fb DM |
107 | |
108 | if (ret < 0) | |
109 | return ret; | |
110 | ||
111 | return buf; | |
112 | } | |
113 | ||
8c55af3f EZ |
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(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 | snd_usb_ctrl_intf(chip) | (selector_id << 8), | |
124 | &pin, sizeof(pin)); | |
125 | if (ret < 0) | |
126 | return ret; | |
127 | ||
128 | if (ret != sizeof(pin)) { | |
0ba41d91 TI |
129 | usb_audio_err(chip, |
130 | "setting selector (id %d) unexpected length %d\n", | |
131 | selector_id, ret); | |
8c55af3f EZ |
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) { | |
0ba41d91 TI |
140 | usb_audio_err(chip, |
141 | "setting selector (id %d) to %x failed (current: %d)\n", | |
142 | selector_id, pin, ret); | |
8c55af3f EZ |
143 | return -EINVAL; |
144 | } | |
145 | ||
146 | return ret; | |
147 | } | |
148 | ||
9f35a312 | 149 | static bool uac_clock_source_is_valid_quirk(struct snd_usb_audio *chip, |
cab941b7 | 150 | const struct audioformat *fmt, |
9f35a312 AT |
151 | int source_id) |
152 | { | |
2edb84e3 AT |
153 | bool ret = false; |
154 | int count; | |
155 | unsigned char data; | |
156 | struct usb_device *dev = chip->dev; | |
9ec73005 | 157 | union uac23_clock_source_desc *cs_desc; |
2edb84e3 | 158 | |
9ec73005 TI |
159 | cs_desc = snd_usb_find_clock_source(chip, source_id, fmt->protocol); |
160 | if (!cs_desc) | |
161 | return false; | |
9f35a312 | 162 | |
9ec73005 | 163 | if (fmt->protocol == UAC_VERSION_2) { |
2edb84e3 AT |
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 && | |
9ec73005 TI |
172 | (fmt->clock & 0xff) == cs_desc->v2.bClockID && |
173 | (cs_desc->v2.bmAttributes & 0x3) != | |
2edb84e3 AT |
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(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 | snd_usb_ctrl_intf(chip) | (source_id << 8), | |
195 | &data, 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 | } | |
9f35a312 AT |
206 | } |
207 | ||
2edb84e3 | 208 | return ret; |
9f35a312 AT |
209 | } |
210 | ||
9a2fe9b8 | 211 | static bool uac_clock_source_is_valid(struct snd_usb_audio *chip, |
cab941b7 | 212 | const struct audioformat *fmt, |
9a2fe9b8 | 213 | int source_id) |
79f920fb DM |
214 | { |
215 | int err; | |
216 | unsigned char data; | |
217 | struct usb_device *dev = chip->dev; | |
9a2fe9b8 | 218 | u32 bmControls; |
9ec73005 | 219 | union uac23_clock_source_desc *cs_desc; |
9a2fe9b8 | 220 | |
9ec73005 TI |
221 | cs_desc = snd_usb_find_clock_source(chip, source_id, fmt->protocol); |
222 | if (!cs_desc) | |
223 | return false; | |
9a2fe9b8 | 224 | |
9ec73005 TI |
225 | if (fmt->protocol == UAC_VERSION_3) |
226 | bmControls = le32_to_cpu(cs_desc->v3.bmControls); | |
227 | else | |
228 | bmControls = cs_desc->v2.bmControls; | |
3bc6fbc7 DM |
229 | |
230 | /* If a clock source can't tell us whether it's valid, we assume it is */ | |
9a2fe9b8 | 231 | if (!uac_v2v3_control_is_readable(bmControls, |
21e9b3e9 | 232 | UAC2_CS_CONTROL_CLOCK_VALID)) |
1d4961d9 | 233 | return true; |
79f920fb DM |
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, | |
11bcbc44 DM |
237 | UAC2_CS_CONTROL_CLOCK_VALID << 8, |
238 | snd_usb_ctrl_intf(chip) | (source_id << 8), | |
17d900c4 | 239 | &data, sizeof(data)); |
79f920fb DM |
240 | |
241 | if (err < 0) { | |
0ba41d91 TI |
242 | dev_warn(&dev->dev, |
243 | "%s(): cannot get clock validity for id %d\n", | |
79f920fb | 244 | __func__, source_id); |
1d4961d9 | 245 | return false; |
79f920fb DM |
246 | } |
247 | ||
9f35a312 AT |
248 | if (data) |
249 | return true; | |
250 | else | |
251 | return uac_clock_source_is_valid_quirk(chip, fmt, source_id); | |
79f920fb DM |
252 | } |
253 | ||
9f35a312 | 254 | static int __uac_clock_find_source(struct snd_usb_audio *chip, |
cab941b7 | 255 | const struct audioformat *fmt, int entity_id, |
9a2fe9b8 | 256 | unsigned long *visited, bool validate) |
79f920fb | 257 | { |
9ec73005 TI |
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; | |
79f920fb DM |
264 | |
265 | entity_id &= 0xff; | |
266 | ||
267 | if (test_and_set_bit(entity_id, visited)) { | |
0ba41d91 TI |
268 | usb_audio_warn(chip, |
269 | "%s(): recursive clock topology detected, id %d.\n", | |
270 | __func__, entity_id); | |
79f920fb DM |
271 | return -EINVAL; |
272 | } | |
273 | ||
882e013a | 274 | /* first, see if the ID we're looking at is a clock source already */ |
9ec73005 | 275 | source = snd_usb_find_clock_source(chip, entity_id, proto); |
06ffc1eb | 276 | if (source) { |
9ec73005 | 277 | entity_id = GET_VAL(source, proto, bClockID); |
9f35a312 | 278 | if (validate && !uac_clock_source_is_valid(chip, fmt, |
9a2fe9b8 | 279 | entity_id)) { |
0ba41d91 TI |
280 | usb_audio_err(chip, |
281 | "clock source %d is not valid, cannot use\n", | |
282 | entity_id); | |
06ffc1eb EZ |
283 | return -ENXIO; |
284 | } | |
285 | return entity_id; | |
286 | } | |
79f920fb | 287 | |
9ec73005 | 288 | selector = snd_usb_find_clock_selector(chip, entity_id, proto); |
79f920fb | 289 | if (selector) { |
9ec73005 TI |
290 | pins = GET_VAL(selector, proto, bNrInPins); |
291 | clock_id = GET_VAL(selector, proto, bClockID); | |
292 | sources = GET_VAL(selector, proto, baCSourceID); | |
be22db77 | 293 | cur = 0; |
79f920fb | 294 | |
9ec73005 | 295 | if (pins == 1) { |
086b957c TI |
296 | ret = 1; |
297 | goto find_source; | |
298 | } | |
299 | ||
882e013a | 300 | /* the entity ID we are looking at is a selector. |
79f920fb | 301 | * find out what it currently selects */ |
9ec73005 | 302 | ret = uac_clock_selector_get_val(chip, clock_id); |
481f17c4 TI |
303 | if (ret < 0) { |
304 | if (!chip->autoclock) | |
305 | return ret; | |
306 | goto find_others; | |
307 | } | |
79f920fb | 308 | |
157a57b6 DM |
309 | /* Selector values are one-based */ |
310 | ||
9ec73005 | 311 | if (ret > pins || ret < 1) { |
0ba41d91 | 312 | usb_audio_err(chip, |
79f920fb | 313 | "%s(): selector reported illegal value, id %d, ret %d\n", |
9ec73005 | 314 | __func__, clock_id, ret); |
79f920fb | 315 | |
481f17c4 TI |
316 | if (!chip->autoclock) |
317 | return -EINVAL; | |
481f17c4 | 318 | goto find_others; |
79f920fb DM |
319 | } |
320 | ||
086b957c | 321 | find_source: |
8c55af3f | 322 | cur = ret; |
9f35a312 | 323 | ret = __uac_clock_find_source(chip, fmt, |
9ec73005 | 324 | sources[ret - 1], |
9f35a312 | 325 | visited, validate); |
d2e8f641 | 326 | if (ret > 0) { |
f21dca85 TI |
327 | /* Skip setting clock selector again for some devices */ |
328 | if (chip->quirk_flags & QUIRK_FLAG_SKIP_CLOCK_SELECTOR) | |
4511781f | 329 | return ret; |
d2e8f641 TI |
330 | err = uac_clock_selector_set_val(chip, entity_id, cur); |
331 | if (err < 0) | |
332 | return err; | |
333 | } | |
334 | ||
ef02e29b | 335 | if (!validate || ret > 0 || !chip->autoclock) |
8c55af3f EZ |
336 | return ret; |
337 | ||
481f17c4 | 338 | find_others: |
8c55af3f | 339 | /* The current clock source is invalid, try others. */ |
9ec73005 | 340 | for (i = 1; i <= pins; i++) { |
8c55af3f EZ |
341 | if (i == cur) |
342 | continue; | |
343 | ||
9f35a312 | 344 | ret = __uac_clock_find_source(chip, fmt, |
9ec73005 | 345 | sources[i - 1], |
9f35a312 | 346 | visited, true); |
8c55af3f EZ |
347 | if (ret < 0) |
348 | continue; | |
349 | ||
350 | err = uac_clock_selector_set_val(chip, entity_id, i); | |
351 | if (err < 0) | |
352 | continue; | |
353 | ||
0ba41d91 TI |
354 | usb_audio_info(chip, |
355 | "found and selected valid clock source %d\n", | |
356 | ret); | |
8c55af3f EZ |
357 | return ret; |
358 | } | |
359 | ||
360 | return -ENXIO; | |
79f920fb DM |
361 | } |
362 | ||
363 | /* FIXME: multipliers only act as pass-thru element for now */ | |
9ec73005 | 364 | multiplier = snd_usb_find_clock_multiplier(chip, entity_id, proto); |
79f920fb | 365 | if (multiplier) |
9f35a312 | 366 | return __uac_clock_find_source(chip, fmt, |
9ec73005 | 367 | GET_VAL(multiplier, proto, bCSourceID), |
9a2fe9b8 | 368 | visited, validate); |
9a2fe9b8 RB |
369 | |
370 | return -EINVAL; | |
371 | } | |
372 | ||
157a57b6 DM |
373 | /* |
374 | * For all kinds of sample rate settings and other device queries, | |
375 | * the clock source (end-leaf) must be used. However, clock selectors, | |
376 | * clock multipliers and sample rate converters may be specified as | |
377 | * clock source input to terminal. This functions walks the clock path | |
378 | * to its end and tries to find the source. | |
379 | * | |
380 | * The 'visited' bitfield is used internally to detect recursive loops. | |
381 | * | |
382 | * Returns the clock source UnitID (>=0) on success, or an error. | |
383 | */ | |
9f35a312 | 384 | int snd_usb_clock_find_source(struct snd_usb_audio *chip, |
cab941b7 | 385 | const struct audioformat *fmt, bool validate) |
79f920fb DM |
386 | { |
387 | DECLARE_BITMAP(visited, 256); | |
388 | memset(visited, 0, sizeof(visited)); | |
9a2fe9b8 | 389 | |
9f35a312 | 390 | switch (fmt->protocol) { |
9a2fe9b8 | 391 | case UAC_VERSION_2: |
9a2fe9b8 | 392 | case UAC_VERSION_3: |
9ec73005 | 393 | return __uac_clock_find_source(chip, fmt, fmt->clock, visited, |
9a2fe9b8 RB |
394 | validate); |
395 | default: | |
396 | return -EINVAL; | |
397 | } | |
79f920fb DM |
398 | } |
399 | ||
953a446b | 400 | static int set_sample_rate_v1(struct snd_usb_audio *chip, |
cab941b7 | 401 | const struct audioformat *fmt, int rate) |
79f920fb DM |
402 | { |
403 | struct usb_device *dev = chip->dev; | |
79f920fb DM |
404 | unsigned char data[3]; |
405 | int err, crate; | |
406 | ||
79f920fb | 407 | /* if endpoint doesn't have sampling rate control, bail out */ |
d32d552e | 408 | if (!(fmt->attributes & UAC_EP_CS_ATTR_SAMPLE_RATE)) |
79f920fb | 409 | return 0; |
79f920fb DM |
410 | |
411 | data[0] = rate; | |
412 | data[1] = rate >> 8; | |
413 | data[2] = rate >> 16; | |
f25ecf8f TI |
414 | err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR, |
415 | USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_OUT, | |
87cb9af9 TI |
416 | UAC_EP_CS_ATTR_SAMPLE_RATE << 8, |
417 | fmt->endpoint, data, sizeof(data)); | |
f25ecf8f | 418 | if (err < 0) { |
0ba41d91 | 419 | dev_err(&dev->dev, "%d:%d: cannot set freq %d to ep %#x\n", |
87cb9af9 | 420 | fmt->iface, fmt->altsetting, rate, fmt->endpoint); |
79f920fb DM |
421 | return err; |
422 | } | |
423 | ||
b62b9980 JT |
424 | /* Don't check the sample rate for devices which we know don't |
425 | * support reading */ | |
4d4dee0a | 426 | if (chip->quirk_flags & QUIRK_FLAG_GET_SAMPLE_RATE) |
b62b9980 | 427 | return 0; |
57dd5414 TI |
428 | /* the firmware is likely buggy, don't repeat to fail too many times */ |
429 | if (chip->sample_rate_read_error > 2) | |
430 | return 0; | |
b62b9980 | 431 | |
f25ecf8f TI |
432 | err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC_GET_CUR, |
433 | USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_IN, | |
87cb9af9 TI |
434 | UAC_EP_CS_ATTR_SAMPLE_RATE << 8, |
435 | fmt->endpoint, data, sizeof(data)); | |
f25ecf8f | 436 | if (err < 0) { |
0ba41d91 | 437 | dev_err(&dev->dev, "%d:%d: cannot get freq at ep %#x\n", |
87cb9af9 | 438 | fmt->iface, fmt->altsetting, fmt->endpoint); |
57dd5414 | 439 | chip->sample_rate_read_error++; |
79f920fb DM |
440 | return 0; /* some devices don't support reading */ |
441 | } | |
442 | ||
443 | crate = data[0] | (data[1] << 8) | (data[2] << 16); | |
9df28edc TI |
444 | if (!crate) { |
445 | dev_info(&dev->dev, "failed to read current rate; disabling the check\n"); | |
446 | chip->sample_rate_read_error = 3; /* three strikes, see above */ | |
447 | return 0; | |
448 | } | |
449 | ||
79f920fb | 450 | if (crate != rate) { |
0ba41d91 | 451 | dev_warn(&dev->dev, "current rate %d is different from the runtime rate %d\n", crate, rate); |
79f920fb DM |
452 | // runtime->rate = crate; |
453 | } | |
454 | ||
455 | return 0; | |
456 | } | |
457 | ||
9a2fe9b8 | 458 | static int get_sample_rate_v2v3(struct snd_usb_audio *chip, int iface, |
7c517465 TI |
459 | int altsetting, int clock) |
460 | { | |
461 | struct usb_device *dev = chip->dev; | |
f6a8bc70 | 462 | __le32 data; |
7c517465 TI |
463 | int err; |
464 | ||
465 | err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR, | |
466 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, | |
467 | UAC2_CS_CONTROL_SAM_FREQ << 8, | |
468 | snd_usb_ctrl_intf(chip) | (clock << 8), | |
f6a8bc70 | 469 | &data, sizeof(data)); |
7c517465 | 470 | if (err < 0) { |
9a2fe9b8 | 471 | dev_warn(&dev->dev, "%d:%d: cannot get freq (v2/v3): err %d\n", |
0ba41d91 | 472 | iface, altsetting, err); |
7c517465 TI |
473 | return 0; |
474 | } | |
475 | ||
f6a8bc70 | 476 | return le32_to_cpu(data); |
7c517465 TI |
477 | } |
478 | ||
93db51d0 TI |
479 | /* |
480 | * Try to set the given sample rate: | |
481 | * | |
482 | * Return 0 if the clock source is read-only, the actual rate on success, | |
483 | * or a negative error code. | |
484 | * | |
485 | * This function gets called from format.c to validate each sample rate, too. | |
486 | * Hence no message is shown upon error | |
487 | */ | |
488 | int snd_usb_set_sample_rate_v2v3(struct snd_usb_audio *chip, | |
489 | const struct audioformat *fmt, | |
490 | int clock, int rate) | |
491 | { | |
492 | bool writeable; | |
493 | u32 bmControls; | |
494 | __le32 data; | |
495 | int err; | |
9ec73005 | 496 | union uac23_clock_source_desc *cs_desc; |
93db51d0 | 497 | |
9ec73005 | 498 | cs_desc = snd_usb_find_clock_source(chip, clock, fmt->protocol); |
b97053df CY |
499 | |
500 | if (!cs_desc) | |
501 | return 0; | |
502 | ||
9ec73005 TI |
503 | if (fmt->protocol == UAC_VERSION_3) |
504 | bmControls = le32_to_cpu(cs_desc->v3.bmControls); | |
505 | else | |
506 | bmControls = cs_desc->v2.bmControls; | |
93db51d0 TI |
507 | |
508 | writeable = uac_v2v3_control_is_writeable(bmControls, | |
509 | UAC2_CS_CONTROL_SAM_FREQ); | |
510 | if (!writeable) | |
511 | return 0; | |
512 | ||
513 | data = cpu_to_le32(rate); | |
514 | err = snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0), UAC2_CS_CUR, | |
515 | USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, | |
516 | UAC2_CS_CONTROL_SAM_FREQ << 8, | |
517 | snd_usb_ctrl_intf(chip) | (clock << 8), | |
518 | &data, sizeof(data)); | |
519 | if (err < 0) | |
520 | return err; | |
521 | ||
522 | return get_sample_rate_v2v3(chip, fmt->iface, fmt->altsetting, clock); | |
523 | } | |
524 | ||
953a446b | 525 | static int set_sample_rate_v2v3(struct snd_usb_audio *chip, |
cab941b7 | 526 | const struct audioformat *fmt, int rate) |
79f920fb | 527 | { |
93db51d0 | 528 | int cur_rate, prev_rate; |
8c55af3f | 529 | int clock; |
79f920fb | 530 | |
58cabe87 AG |
531 | /* First, try to find a valid clock. This may trigger |
532 | * automatic clock selection if the current clock is not | |
533 | * valid. | |
534 | */ | |
9f35a312 | 535 | clock = snd_usb_clock_find_source(chip, fmt, true); |
58cabe87 AG |
536 | if (clock < 0) { |
537 | /* We did not find a valid clock, but that might be | |
538 | * because the current sample rate does not match an | |
539 | * external clock source. Try again without validation | |
540 | * and we will do another validation after setting the | |
541 | * rate. | |
542 | */ | |
9f35a312 | 543 | clock = snd_usb_clock_find_source(chip, fmt, false); |
7fdabab8 | 544 | |
f21dca85 TI |
545 | /* Hardcoded sample rates */ |
546 | if (chip->quirk_flags & QUIRK_FLAG_IGNORE_CLOCK_SOURCE) | |
7fdabab8 DZ |
547 | return 0; |
548 | ||
58cabe87 AG |
549 | if (clock < 0) |
550 | return clock; | |
551 | } | |
79f920fb | 552 | |
953a446b | 553 | prev_rate = get_sample_rate_v2v3(chip, fmt->iface, fmt->altsetting, clock); |
fa92dd77 | 554 | if (prev_rate == rate) |
58cabe87 | 555 | goto validation; |
690a863f | 556 | |
93db51d0 TI |
557 | cur_rate = snd_usb_set_sample_rate_v2v3(chip, fmt, clock, rate); |
558 | if (cur_rate < 0) { | |
559 | usb_audio_err(chip, | |
560 | "%d:%d: cannot set freq %d (v2/v3): err %d\n", | |
953a446b | 561 | fmt->iface, fmt->altsetting, rate, cur_rate); |
93db51d0 | 562 | return cur_rate; |
9a2fe9b8 RB |
563 | } |
564 | ||
93db51d0 | 565 | if (!cur_rate) |
1dc669fe | 566 | cur_rate = prev_rate; |
79f920fb | 567 | |
690a863f | 568 | if (cur_rate != rate) { |
dcf269b3 TI |
569 | usb_audio_dbg(chip, |
570 | "%d:%d: freq mismatch: req %d, clock runs @%d\n", | |
571 | fmt->iface, fmt->altsetting, rate, cur_rate); | |
572 | /* continue processing */ | |
690a863f TH |
573 | } |
574 | ||
5ce0b06a | 575 | /* FIXME - TEAC devices require the immediate interface setup */ |
3753fcc2 TI |
576 | if (USB_ID_VENDOR(chip->usb_id) == 0x0644) { |
577 | bool cur_base_48k = (rate % 48000 == 0); | |
578 | bool prev_base_48k = (prev_rate % 48000 == 0); | |
579 | if (cur_base_48k != prev_base_48k) { | |
580 | usb_set_interface(chip->dev, fmt->iface, fmt->altsetting); | |
581 | if (chip->quirk_flags & QUIRK_FLAG_IFACE_DELAY) | |
582 | msleep(50); | |
583 | } | |
5ce0b06a TI |
584 | } |
585 | ||
58cabe87 AG |
586 | validation: |
587 | /* validate clock after rate change */ | |
9f35a312 | 588 | if (!uac_clock_source_is_valid(chip, fmt, clock)) |
58cabe87 | 589 | return -ENXIO; |
79f920fb DM |
590 | return 0; |
591 | } | |
592 | ||
953a446b | 593 | int snd_usb_init_sample_rate(struct snd_usb_audio *chip, |
cab941b7 | 594 | const struct audioformat *fmt, int rate) |
79f920fb | 595 | { |
bf6313a0 TI |
596 | usb_audio_dbg(chip, "%d:%d Set sample rate %d, clock %d\n", |
597 | fmt->iface, fmt->altsetting, rate, fmt->clock); | |
598 | ||
8f898e92 | 599 | switch (fmt->protocol) { |
79f920fb | 600 | case UAC_VERSION_1: |
a2acad82 | 601 | default: |
953a446b | 602 | return set_sample_rate_v1(chip, fmt, rate); |
79f920fb | 603 | |
9a2fe9b8 | 604 | case UAC_VERSION_3: |
17156f23 RB |
605 | if (chip->badd_profile >= UAC3_FUNCTION_SUBCLASS_GENERIC_IO) { |
606 | if (rate != UAC3_BADD_SAMPLING_RATE) | |
607 | return -ENXIO; | |
608 | else | |
609 | return 0; | |
610 | } | |
c0dbbdad | 611 | fallthrough; |
17156f23 | 612 | case UAC_VERSION_2: |
953a446b | 613 | return set_sample_rate_v2v3(chip, fmt, rate); |
79f920fb | 614 | } |
79f920fb DM |
615 | } |
616 |