At Wed, 03 Apr 2013 12:15:49 +0200, Clemens Ladisch wrote:
Takashi Iwai wrote:
Torstein Hegge wrote:
The C-Media CM6631 USB receiver doesn't respond to changes in sample rate while the interface is active. The same behavior is observed in other UAC2 hardware like the VIA VT1731.
Reset the interface after setting the sampling frequency on sample rate changes, to ensure that the sample rate set by snd_usb_init_sample_rate() is used. Otherwise, the device will try to use the sample rate of the previous stream, causing distorted sound on sample rate changes.
The reset is performed for all UAC2 devices, as it should not affect a standards compliant device, but it is only necessary for C-Media CM6631, VIA VT1731 and possibly others.
Failure to read sample rate from the device is not handled as an error in set_sample_rate_v2(), as (permanent or intermittent) failure to read sample rate isn't essential for a successful sample rate set.
Signed-off-by: Torstein Hegge hegge@resisty.net
What about the latest status of the patch?
If both Clemens and Daniel are happy with it, I can apply it for the next 3.9-rc.
Acked-by: Clemens Ladisch clemens@ladisch.de with or without this change:
OK, I applied the patch now without modification for for-linus branch. Then back-merged to for-next branch with the additional clean-up patch below.
Eldad, please rebase your patches to for-next branch of sound git tree.
thanks,
Takashi
--- From: Takashi Iwai tiwai@suse.de Subject: [PATCH] ALSA: usb-audio: Clean up the code in set_sample_rate_v2()
Just for cleaning up, introduce a new function get_sample_rate_v2() for replacing two identical calls in set_sample_rate_v2().
No functional change.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/usb/clock.c | 47 +++++++++++++++++++++++------------------------ 1 file changed, 23 insertions(+), 24 deletions(-)
diff --git a/sound/usb/clock.c b/sound/usb/clock.c index 9e2703a..e3ccf3d 100644 --- a/sound/usb/clock.c +++ b/sound/usb/clock.c @@ -247,6 +247,27 @@ static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface, return 0; }
+static int get_sample_rate_v2(struct snd_usb_audio *chip, int iface, + int altsetting, int clock) +{ + struct usb_device *dev = chip->dev; + unsigned char data[4]; + int err; + + err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR, + USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, + UAC2_CS_CONTROL_SAM_FREQ << 8, + snd_usb_ctrl_intf(chip) | (clock << 8), + data, sizeof(data)); + if (err < 0) { + snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq (v2)\n", + dev->devnum, iface, altsetting); + return 0; + } + + return data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24); +} + static int set_sample_rate_v2(struct snd_usb_audio *chip, int iface, struct usb_host_interface *alts, struct audioformat *fmt, int rate) @@ -266,18 +287,7 @@ static int set_sample_rate_v2(struct snd_usb_audio *chip, int iface, return -ENXIO; }
- err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR, - USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, - UAC2_CS_CONTROL_SAM_FREQ << 8, - snd_usb_ctrl_intf(chip) | (clock << 8), - data, sizeof(data)); - if (err < 0) { - snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq (v2)\n", - dev->devnum, iface, fmt->altsetting); - prev_rate = 0; - } else { - prev_rate = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24); - } + prev_rate = get_sample_rate_v2(chip, iface, fmt->altsetting, clock);
data[0] = rate; data[1] = rate >> 8; @@ -293,18 +303,7 @@ static int set_sample_rate_v2(struct snd_usb_audio *chip, int iface, return err; }
- err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR, - USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN, - UAC2_CS_CONTROL_SAM_FREQ << 8, - snd_usb_ctrl_intf(chip) | (clock << 8), - data, sizeof(data)); - if (err < 0) { - snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq (v2)\n", - dev->devnum, iface, fmt->altsetting); - cur_rate = 0; - } else { - cur_rate = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24); - } + cur_rate = get_sample_rate_v2(chip, iface, fmt->altsetting, clock);
if (cur_rate != rate) { snd_printd(KERN_WARNING