aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/usb/clock.c37
1 files changed, 26 insertions, 11 deletions
diff --git a/sound/usb/clock.c b/sound/usb/clock.c
index a694e1c42fdf..ae35e7d22e73 100644
--- a/sound/usb/clock.c
+++ b/sound/usb/clock.c
@@ -347,6 +347,8 @@ static int set_sample_rate_v2(struct snd_usb_audio *chip, int iface,
347 __le32 data; 347 __le32 data;
348 int err, cur_rate, prev_rate; 348 int err, cur_rate, prev_rate;
349 int clock; 349 int clock;
350 bool writeable;
351 struct uac_clock_source_descriptor *cs_desc;
350 352
351 clock = snd_usb_clock_find_source(chip, fmt->clock, true); 353 clock = snd_usb_clock_find_source(chip, fmt->clock, true);
352 if (clock < 0) 354 if (clock < 0)
@@ -354,20 +356,33 @@ static int set_sample_rate_v2(struct snd_usb_audio *chip, int iface,
354 356
355 prev_rate = get_sample_rate_v2(chip, iface, fmt->altsetting, clock); 357 prev_rate = get_sample_rate_v2(chip, iface, fmt->altsetting, clock);
356 358
357 data = cpu_to_le32(rate); 359 cs_desc = snd_usb_find_clock_source(chip->ctrl_intf, clock);
358 if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC2_CS_CUR, 360 writeable = uac2_control_is_writeable(cs_desc->bmControls, UAC2_CS_CONTROL_SAM_FREQ - 1);
359 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, 361 if (writeable) {
360 UAC2_CS_CONTROL_SAM_FREQ << 8, 362 data = cpu_to_le32(rate);
361 snd_usb_ctrl_intf(chip) | (clock << 8), 363 err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC2_CS_CUR,
362 &data, sizeof(data))) < 0) { 364 USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
363 snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d (v2): err %d\n", 365 UAC2_CS_CONTROL_SAM_FREQ << 8,
364 dev->devnum, iface, fmt->altsetting, rate, err); 366 snd_usb_ctrl_intf(chip) | (clock << 8),
365 return err; 367 &data, sizeof(data));
366 } 368 if (err < 0) {
369 snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d (v2): err %d\n",
370 dev->devnum, iface, fmt->altsetting, rate, err);
371 return err;
372 }
367 373
368 cur_rate = get_sample_rate_v2(chip, iface, fmt->altsetting, clock); 374 cur_rate = get_sample_rate_v2(chip, iface, fmt->altsetting, clock);
375 } else {
376 cur_rate = prev_rate;
377 }
369 378
370 if (cur_rate != rate) { 379 if (cur_rate != rate) {
380 if (!writeable) {
381 snd_printk(KERN_WARNING
382 "%d:%d:%d: freq mismatch (RO clock): req %d, clock runs @%d\n",
383 dev->devnum, iface, fmt->altsetting, rate, cur_rate);
384 return -ENXIO;
385 }
371 snd_printd(KERN_WARNING 386 snd_printd(KERN_WARNING
372 "current rate %d is different from the runtime rate %d\n", 387 "current rate %d is different from the runtime rate %d\n",
373 cur_rate, rate); 388 cur_rate, rate);