Daniel Mack <zonque <at> gmail.com> writes: > >> This is a known bug, also most probably flaw in the CMEDIA chip, > >> and not yet properly worked around in the snd-usb driver. If you > >> want to investigate, have a look at the feedback format > >> autodetection code in sound/usb/endpoint.c. > > > > Thanks, I'll have a look. > > I believe what's going on here is that the device is confused after > sample rate changes and keeps sending back feedback data for the old > rate on its feedback endpoint. That causes the autodetection algorithm, > which kicks in on every first packet of a stream, to go nuts, which > causes the part of the driver that sends the data assume a very wrong > rate. Some printk() there should give you a hint. I had a look at this using another C-Media CM6631 based device, the Corda Daccord (usbid 0x0d8c, 0x0309). As far as I can see, what happens in the feedback format auto-detection is: When starting playback of a file with a different sampling frequency than the previous file, the reported feedback frequency is in the same range as the previously played file, varying within +-1%. The feedback format detection gives a shift of -1 and reports the feedback frequency as ~48kHz when playing a 44.1kHz file after a 96kHz file. Same thing happens when playing a 96kHz file after a 44.1kHz file, the device reports feedback frequency in the 44.1kHz range, the feedback format detection gives a shift of +1 and reports the feedback frequency as ~88kHz. Bypassing the feedback format detection by hard-coding the frequency shift to zero and setting the feedback frequency ep->freqm equal to the nominal frequency ep->freqn if the feedback frequency is far off from the expected value (like 48kHz when expecting 44.1kHz) does not change the distortion. Similarly, forcing the feedback detection to run multiple times until it reaches an acceptable value just keeps the feedback detection to repeatedly until playback is stopped. This probably means any amount of skipping packages early in the stream won't work. It seems like the device stays in the previous frequency until the interface is reset. One possible workaround is to call usb_set_interface() again after snd_usb_init_sample_rate(), like this: diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index d82e378..01978a6 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -710,6 +710,16 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) subs->need_setup_ep = false; } + /* Some devices doesn't respond to sample rate changes while the + * interface is active. */ + switch (subs->stream->chip->usb_id) { + case USB_ID(0x0d8c, 0x0304): /* C-Media - Schiit USB Interface */ + case USB_ID(0x0d8c, 0x0309): /* C-Media CM6631 */ + usb_set_interface(subs->dev, subs->cur_audiofmt->iface, + subs->cur_audiofmt->altset_idx); + break; + } + /* some unit conversions in runtime */ subs->data_endpoint->maxframesize = bytes_to_frames(runtime, subs->data_endpoint->maxpacksize); This fixes all problems related to sample rate changes for me. I have only tested with the Daccord, but it should work for the Schiit and other CM6631 based devices as well. I was initially thinking this could be done in snd_usb_endpoint_start_quirk(), but the call to usb_set_interface() must be performed before start_endpoints(). Torstein ------------------------------------------------------------------------------ Everyone hates slow websites. So do we. Make your web apps faster with AppDynamics Download AppDynamics Lite for free today: http://p.sf.net/sfu/appdyn_d2d_feb _______________________________________________ Alsa-user mailing list Alsa-user@xxxxxxxxxxxxxxxxxxxxx https://lists.sourceforge.net/lists/listinfo/alsa-user