Skip to content

Commit

Permalink
ALSA: usb-audio: UAC2: support read-only freq control
Browse files Browse the repository at this point in the history
Some clocks might be read-only, e.g., external clocks (see also
UAC2 4.7.2.1).

In this case, setting the sample frequency will always fail
(even if the rate is equal to the current clock rate),
therefore do not write, but read the value and compare to the
requested rate.
If the clock is read only, avoid reading it twice.

If it doesn't match, return -ENXIO since the clock is invalid for
this configuration.

Signed-off-by: Eldad Zack <eldad@fogrefinery.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
  • Loading branch information
eldad authored and tiwai committed Apr 4, 2013
1 parent 027bbc1 commit 1dc669f
Showing 1 changed file with 26 additions and 11 deletions.
37 changes: 26 additions & 11 deletions sound/usb/clock.c
Original file line number Diff line number Diff line change
Expand Up @@ -347,27 +347,42 @@ static int set_sample_rate_v2(struct snd_usb_audio *chip, int iface,
__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)
return clock;

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);
Expand Down

0 comments on commit 1dc669f

Please sign in to comment.