__le32 data;
int err, cur_rate, prev_rate;
int clock;
+ bool writeable;
+ struct uac_clock_source_descriptor *cs_desc;
clock = snd_usb_clock_find_source(chip, fmt->clock, true);
if (clock < 0)
prev_rate = get_sample_rate_v2(chip, iface, fmt->altsetting, clock);
- data = cpu_to_le32(rate);
- if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC2_CS_CUR,
- USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
- UAC2_CS_CONTROL_SAM_FREQ << 8,
- snd_usb_ctrl_intf(chip) | (clock << 8),
- &data, sizeof(data))) < 0) {
- snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d (v2): err %d\n",
- dev->devnum, iface, fmt->altsetting, rate, err);
- return err;
- }
+ cs_desc = snd_usb_find_clock_source(chip->ctrl_intf, clock);
+ writeable = uac2_control_is_writeable(cs_desc->bmControls, UAC2_CS_CONTROL_SAM_FREQ - 1);
+ if (writeable) {
+ data = cpu_to_le32(rate);
+ err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC2_CS_CUR,
+ USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
+ UAC2_CS_CONTROL_SAM_FREQ << 8,
+ snd_usb_ctrl_intf(chip) | (clock << 8),
+ &data, sizeof(data));
+ if (err < 0) {
+ snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d (v2): err %d\n",
+ dev->devnum, iface, fmt->altsetting, rate, err);
+ return err;
+ }
- cur_rate = get_sample_rate_v2(chip, iface, fmt->altsetting, clock);
+ cur_rate = get_sample_rate_v2(chip, iface, fmt->altsetting, clock);
+ } else {
+ cur_rate = prev_rate;
+ }
if (cur_rate != rate) {
+ if (!writeable) {
+ snd_printk(KERN_WARNING
+ "%d:%d:%d: freq mismatch (RO clock): req %d, clock runs @%d\n",
+ dev->devnum, iface, fmt->altsetting, rate, cur_rate);
+ return -ENXIO;
+ }
snd_printd(KERN_WARNING
"current rate %d is different from the runtime rate %d\n",
cur_rate, rate);