Lines Matching +full:chip +full:- +full:id
1 // SPDX-License-Identifier: GPL-2.0-or-later
11 #include <linux/usb/audio-v2.h>
12 #include <linux/usb/audio-v3.h>
24 static void *find_uac_clock_desc(struct usb_host_interface *iface, int id, in find_uac_clock_desc() argument
29 while ((cs = snd_usb_find_csint_desc(iface->extra, iface->extralen, in find_uac_clock_desc()
31 if (validator(cs, id)) in find_uac_clock_desc()
38 static bool validate_clock_source_v2(void *p, int id) in validate_clock_source_v2() argument
41 return cs->bClockID == id; in validate_clock_source_v2()
44 static bool validate_clock_source_v3(void *p, int id) in validate_clock_source_v3() argument
47 return cs->bClockID == id; in validate_clock_source_v3()
50 static bool validate_clock_selector_v2(void *p, int id) in validate_clock_selector_v2() argument
53 return cs->bClockID == id; in validate_clock_selector_v2()
56 static bool validate_clock_selector_v3(void *p, int id) in validate_clock_selector_v3() argument
59 return cs->bClockID == id; in validate_clock_selector_v3()
62 static bool validate_clock_multiplier_v2(void *p, int id) in validate_clock_multiplier_v2() argument
65 return cs->bClockID == id; in validate_clock_multiplier_v2()
68 static bool validate_clock_multiplier_v3(void *p, int id) in validate_clock_multiplier_v3() argument
71 return cs->bClockID == id; in validate_clock_multiplier_v3()
75 static obj *name(struct usb_host_interface *iface, int id) \
77 return find_uac_clock_desc(iface, id, validator, type); \
101 static int uac_clock_selector_get_val(struct snd_usb_audio *chip, int selector_id) in uac_clock_selector_get_val() argument
106 ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), in uac_clock_selector_get_val()
110 snd_usb_ctrl_intf(chip) | (selector_id << 8), in uac_clock_selector_get_val()
119 static int uac_clock_selector_set_val(struct snd_usb_audio *chip, int selector_id, in uac_clock_selector_set_val() argument
124 ret = snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0), in uac_clock_selector_set_val()
128 snd_usb_ctrl_intf(chip) | (selector_id << 8), in uac_clock_selector_set_val()
134 usb_audio_err(chip, in uac_clock_selector_set_val()
135 "setting selector (id %d) unexpected length %d\n", in uac_clock_selector_set_val()
137 return -EINVAL; in uac_clock_selector_set_val()
140 ret = uac_clock_selector_get_val(chip, selector_id); in uac_clock_selector_set_val()
145 usb_audio_err(chip, in uac_clock_selector_set_val()
146 "setting selector (id %d) to %x failed (current: %d)\n", in uac_clock_selector_set_val()
148 return -EINVAL; in uac_clock_selector_set_val()
154 static bool uac_clock_source_is_valid_quirk(struct snd_usb_audio *chip, in uac_clock_source_is_valid_quirk() argument
161 struct usb_device *dev = chip->dev; in uac_clock_source_is_valid_quirk()
163 if (fmt->protocol == UAC_VERSION_2) { in uac_clock_source_is_valid_quirk()
165 snd_usb_find_clock_source(chip->ctrl_intf, source_id); in uac_clock_source_is_valid_quirk()
177 if (fmt->nr_rates == 1 && in uac_clock_source_is_valid_quirk()
178 (fmt->clock & 0xff) == cs_desc->bClockID && in uac_clock_source_is_valid_quirk()
179 (cs_desc->bmAttributes & 0x3) != in uac_clock_source_is_valid_quirk()
189 if (chip->usb_id == USB_ID(0x07fd, 0x0004)) { in uac_clock_source_is_valid_quirk()
200 snd_usb_ctrl_intf(chip) | (source_id << 8), in uac_clock_source_is_valid_quirk()
203 dev_warn(&dev->dev, in uac_clock_source_is_valid_quirk()
204 "%s(): cannot get clock validity for id %d\n", in uac_clock_source_is_valid_quirk()
217 static bool uac_clock_source_is_valid(struct snd_usb_audio *chip, in uac_clock_source_is_valid() argument
223 struct usb_device *dev = chip->dev; in uac_clock_source_is_valid()
226 if (fmt->protocol == UAC_VERSION_3) { in uac_clock_source_is_valid()
228 snd_usb_find_clock_source_v3(chip->ctrl_intf, source_id); in uac_clock_source_is_valid()
232 bmControls = le32_to_cpu(cs_desc->bmControls); in uac_clock_source_is_valid()
235 snd_usb_find_clock_source(chip->ctrl_intf, source_id); in uac_clock_source_is_valid()
239 bmControls = cs_desc->bmControls; in uac_clock_source_is_valid()
250 snd_usb_ctrl_intf(chip) | (source_id << 8), in uac_clock_source_is_valid()
254 dev_warn(&dev->dev, in uac_clock_source_is_valid()
255 "%s(): cannot get clock validity for id %d\n", in uac_clock_source_is_valid()
263 return uac_clock_source_is_valid_quirk(chip, fmt, source_id); in uac_clock_source_is_valid()
266 static int __uac_clock_find_source(struct snd_usb_audio *chip, in __uac_clock_find_source() argument
277 usb_audio_warn(chip, in __uac_clock_find_source()
278 "%s(): recursive clock topology detected, id %d.\n", in __uac_clock_find_source()
280 return -EINVAL; in __uac_clock_find_source()
283 /* first, see if the ID we're looking for is a clock source already */ in __uac_clock_find_source()
284 source = snd_usb_find_clock_source(chip->ctrl_intf, entity_id); in __uac_clock_find_source()
286 entity_id = source->bClockID; in __uac_clock_find_source()
287 if (validate && !uac_clock_source_is_valid(chip, fmt, in __uac_clock_find_source()
289 usb_audio_err(chip, in __uac_clock_find_source()
292 return -ENXIO; in __uac_clock_find_source()
297 selector = snd_usb_find_clock_selector(chip->ctrl_intf, entity_id); in __uac_clock_find_source()
301 /* the entity ID we are looking for is a selector. in __uac_clock_find_source()
303 ret = uac_clock_selector_get_val(chip, selector->bClockID); in __uac_clock_find_source()
307 /* Selector values are one-based */ in __uac_clock_find_source()
309 if (ret > selector->bNrInPins || ret < 1) { in __uac_clock_find_source()
310 usb_audio_err(chip, in __uac_clock_find_source()
311 "%s(): selector reported illegal value, id %d, ret %d\n", in __uac_clock_find_source()
312 __func__, selector->bClockID, ret); in __uac_clock_find_source()
314 return -EINVAL; in __uac_clock_find_source()
318 ret = __uac_clock_find_source(chip, fmt, in __uac_clock_find_source()
319 selector->baCSourceID[ret - 1], in __uac_clock_find_source()
326 if (chip->usb_id == USB_ID(0x04e8, 0xa051)) in __uac_clock_find_source()
328 err = uac_clock_selector_set_val(chip, entity_id, cur); in __uac_clock_find_source()
333 if (!validate || ret > 0 || !chip->autoclock) in __uac_clock_find_source()
337 for (i = 1; i <= selector->bNrInPins; i++) { in __uac_clock_find_source()
341 ret = __uac_clock_find_source(chip, fmt, in __uac_clock_find_source()
342 selector->baCSourceID[i - 1], in __uac_clock_find_source()
347 err = uac_clock_selector_set_val(chip, entity_id, i); in __uac_clock_find_source()
351 usb_audio_info(chip, in __uac_clock_find_source()
357 return -ENXIO; in __uac_clock_find_source()
360 /* FIXME: multipliers only act as pass-thru element for now */ in __uac_clock_find_source()
361 multiplier = snd_usb_find_clock_multiplier(chip->ctrl_intf, entity_id); in __uac_clock_find_source()
363 return __uac_clock_find_source(chip, fmt, in __uac_clock_find_source()
364 multiplier->bCSourceID, in __uac_clock_find_source()
367 return -EINVAL; in __uac_clock_find_source()
370 static int __uac3_clock_find_source(struct snd_usb_audio *chip, in __uac3_clock_find_source() argument
381 usb_audio_warn(chip, in __uac3_clock_find_source()
382 "%s(): recursive clock topology detected, id %d.\n", in __uac3_clock_find_source()
384 return -EINVAL; in __uac3_clock_find_source()
387 /* first, see if the ID we're looking for is a clock source already */ in __uac3_clock_find_source()
388 source = snd_usb_find_clock_source_v3(chip->ctrl_intf, entity_id); in __uac3_clock_find_source()
390 entity_id = source->bClockID; in __uac3_clock_find_source()
391 if (validate && !uac_clock_source_is_valid(chip, fmt, in __uac3_clock_find_source()
393 usb_audio_err(chip, in __uac3_clock_find_source()
396 return -ENXIO; in __uac3_clock_find_source()
401 selector = snd_usb_find_clock_selector_v3(chip->ctrl_intf, entity_id); in __uac3_clock_find_source()
405 /* the entity ID we are looking for is a selector. in __uac3_clock_find_source()
407 ret = uac_clock_selector_get_val(chip, selector->bClockID); in __uac3_clock_find_source()
411 /* Selector values are one-based */ in __uac3_clock_find_source()
413 if (ret > selector->bNrInPins || ret < 1) { in __uac3_clock_find_source()
414 usb_audio_err(chip, in __uac3_clock_find_source()
415 "%s(): selector reported illegal value, id %d, ret %d\n", in __uac3_clock_find_source()
416 __func__, selector->bClockID, ret); in __uac3_clock_find_source()
418 return -EINVAL; in __uac3_clock_find_source()
422 ret = __uac3_clock_find_source(chip, fmt, in __uac3_clock_find_source()
423 selector->baCSourceID[ret - 1], in __uac3_clock_find_source()
426 err = uac_clock_selector_set_val(chip, entity_id, cur); in __uac3_clock_find_source()
431 if (!validate || ret > 0 || !chip->autoclock) in __uac3_clock_find_source()
435 for (i = 1; i <= selector->bNrInPins; i++) { in __uac3_clock_find_source()
441 ret = __uac3_clock_find_source(chip, fmt, in __uac3_clock_find_source()
442 selector->baCSourceID[i - 1], in __uac3_clock_find_source()
447 err = uac_clock_selector_set_val(chip, entity_id, i); in __uac3_clock_find_source()
451 usb_audio_info(chip, in __uac3_clock_find_source()
457 return -ENXIO; in __uac3_clock_find_source()
460 /* FIXME: multipliers only act as pass-thru element for now */ in __uac3_clock_find_source()
461 multiplier = snd_usb_find_clock_multiplier_v3(chip->ctrl_intf, in __uac3_clock_find_source()
464 return __uac3_clock_find_source(chip, fmt, in __uac3_clock_find_source()
465 multiplier->bCSourceID, in __uac3_clock_find_source()
468 return -EINVAL; in __uac3_clock_find_source()
473 * the clock source (end-leaf) must be used. However, clock selectors,
482 int snd_usb_clock_find_source(struct snd_usb_audio *chip, in snd_usb_clock_find_source() argument
488 switch (fmt->protocol) { in snd_usb_clock_find_source()
490 return __uac_clock_find_source(chip, fmt, fmt->clock, visited, in snd_usb_clock_find_source()
493 return __uac3_clock_find_source(chip, fmt, fmt->clock, visited, in snd_usb_clock_find_source()
496 return -EINVAL; in snd_usb_clock_find_source()
500 static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface, in set_sample_rate_v1() argument
504 struct usb_device *dev = chip->dev; in set_sample_rate_v1()
509 if (get_iface_desc(alts)->bNumEndpoints < 1) in set_sample_rate_v1()
510 return -EINVAL; in set_sample_rate_v1()
511 ep = get_endpoint(alts, 0)->bEndpointAddress; in set_sample_rate_v1()
514 if (!(fmt->attributes & UAC_EP_CS_ATTR_SAMPLE_RATE)) in set_sample_rate_v1()
525 dev_err(&dev->dev, "%d:%d: cannot set freq %d to ep %#x\n", in set_sample_rate_v1()
526 iface, fmt->altsetting, rate, ep); in set_sample_rate_v1()
532 if (snd_usb_get_sample_rate_quirk(chip)) in set_sample_rate_v1()
535 if (chip->sample_rate_read_error > 2) in set_sample_rate_v1()
543 dev_err(&dev->dev, "%d:%d: cannot get freq at ep %#x\n", in set_sample_rate_v1()
544 iface, fmt->altsetting, ep); in set_sample_rate_v1()
545 chip->sample_rate_read_error++; in set_sample_rate_v1()
551 dev_info(&dev->dev, "failed to read current rate; disabling the check\n"); in set_sample_rate_v1()
552 chip->sample_rate_read_error = 3; /* three strikes, see above */ in set_sample_rate_v1()
557 dev_warn(&dev->dev, "current rate %d is different from the runtime rate %d\n", crate, rate); in set_sample_rate_v1()
558 // runtime->rate = crate; in set_sample_rate_v1()
564 static int get_sample_rate_v2v3(struct snd_usb_audio *chip, int iface, in get_sample_rate_v2v3() argument
567 struct usb_device *dev = chip->dev; in get_sample_rate_v2v3()
574 snd_usb_ctrl_intf(chip) | (clock << 8), in get_sample_rate_v2v3()
577 dev_warn(&dev->dev, "%d:%d: cannot get freq (v2/v3): err %d\n", in get_sample_rate_v2v3()
585 static int set_sample_rate_v2v3(struct snd_usb_audio *chip, int iface, in set_sample_rate_v2v3() argument
589 struct usb_device *dev = chip->dev; in set_sample_rate_v2v3()
600 clock = snd_usb_clock_find_source(chip, fmt, true); in set_sample_rate_v2v3()
608 clock = snd_usb_clock_find_source(chip, fmt, false); in set_sample_rate_v2v3()
613 prev_rate = get_sample_rate_v2v3(chip, iface, fmt->altsetting, clock); in set_sample_rate_v2v3()
617 if (fmt->protocol == UAC_VERSION_3) { in set_sample_rate_v2v3()
620 cs_desc = snd_usb_find_clock_source_v3(chip->ctrl_intf, clock); in set_sample_rate_v2v3()
621 bmControls = le32_to_cpu(cs_desc->bmControls); in set_sample_rate_v2v3()
625 cs_desc = snd_usb_find_clock_source(chip->ctrl_intf, clock); in set_sample_rate_v2v3()
626 bmControls = cs_desc->bmControls; in set_sample_rate_v2v3()
636 snd_usb_ctrl_intf(chip) | (clock << 8), in set_sample_rate_v2v3()
639 usb_audio_err(chip, in set_sample_rate_v2v3()
641 iface, fmt->altsetting, rate, err); in set_sample_rate_v2v3()
645 cur_rate = get_sample_rate_v2v3(chip, iface, in set_sample_rate_v2v3()
646 fmt->altsetting, clock); in set_sample_rate_v2v3()
653 usb_audio_warn(chip, in set_sample_rate_v2v3()
655 iface, fmt->altsetting, rate, cur_rate); in set_sample_rate_v2v3()
656 return -ENXIO; in set_sample_rate_v2v3()
658 usb_audio_dbg(chip, in set_sample_rate_v2v3()
668 usb_set_interface(dev, iface, fmt->altsetting); in set_sample_rate_v2v3()
674 if (!uac_clock_source_is_valid(chip, fmt, clock)) in set_sample_rate_v2v3()
675 return -ENXIO; in set_sample_rate_v2v3()
679 int snd_usb_init_sample_rate(struct snd_usb_audio *chip, int iface, in snd_usb_init_sample_rate() argument
683 switch (fmt->protocol) { in snd_usb_init_sample_rate()
686 return set_sample_rate_v1(chip, iface, alts, fmt, rate); in snd_usb_init_sample_rate()
689 if (chip->badd_profile >= UAC3_FUNCTION_SUBCLASS_GENERIC_IO) { in snd_usb_init_sample_rate()
691 return -ENXIO; in snd_usb_init_sample_rate()
697 return set_sample_rate_v2v3(chip, iface, alts, fmt, rate); in snd_usb_init_sample_rate()