提交 1dc669fe 编写于 作者: E Eldad Zack 提交者: Takashi Iwai

ALSA: usb-audio: UAC2: support read-only freq control

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: NEldad Zack <eldad@fogrefinery.com>
Signed-off-by: NTakashi Iwai <tiwai@suse.de>
上级 027bbc15
...@@ -347,6 +347,8 @@ static int set_sample_rate_v2(struct snd_usb_audio *chip, int iface, ...@@ -347,6 +347,8 @@ static int set_sample_rate_v2(struct snd_usb_audio *chip, int iface,
__le32 data; __le32 data;
int err, cur_rate, prev_rate; int err, cur_rate, prev_rate;
int clock; int clock;
bool writeable;
struct uac_clock_source_descriptor *cs_desc;
clock = snd_usb_clock_find_source(chip, fmt->clock, true); clock = snd_usb_clock_find_source(chip, fmt->clock, true);
if (clock < 0) if (clock < 0)
...@@ -354,20 +356,33 @@ static int set_sample_rate_v2(struct snd_usb_audio *chip, int iface, ...@@ -354,20 +356,33 @@ static int set_sample_rate_v2(struct snd_usb_audio *chip, int iface,
prev_rate = get_sample_rate_v2(chip, iface, fmt->altsetting, clock); prev_rate = get_sample_rate_v2(chip, iface, fmt->altsetting, clock);
data = cpu_to_le32(rate); cs_desc = snd_usb_find_clock_source(chip->ctrl_intf, clock);
if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC2_CS_CUR, writeable = uac2_control_is_writeable(cs_desc->bmControls, UAC2_CS_CONTROL_SAM_FREQ - 1);
USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT, if (writeable) {
UAC2_CS_CONTROL_SAM_FREQ << 8, data = cpu_to_le32(rate);
snd_usb_ctrl_intf(chip) | (clock << 8), err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC2_CS_CUR,
&data, sizeof(data))) < 0) { USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d (v2): err %d\n", UAC2_CS_CONTROL_SAM_FREQ << 8,
dev->devnum, iface, fmt->altsetting, rate, err); snd_usb_ctrl_intf(chip) | (clock << 8),
return err; &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 (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 snd_printd(KERN_WARNING
"current rate %d is different from the runtime rate %d\n", "current rate %d is different from the runtime rate %d\n",
cur_rate, rate); cur_rate, rate);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册