|
@@ -471,6 +471,10 @@ struct snd_usb_endpoint *snd_usb_add_endpoint(struct snd_usb_audio *chip,
|
|
|
ep->syncinterval = 3;
|
|
|
|
|
|
ep->syncmaxsize = le16_to_cpu(get_endpoint(alts, 1)->wMaxPacketSize);
|
|
|
+
|
|
|
+ if (chip->usb_id == USB_ID(0x0644, 0x8038) /* TEAC UD-H01 */ &&
|
|
|
+ ep->syncmaxsize == 4)
|
|
|
+ ep->udh01_fb_quirk = 1;
|
|
|
}
|
|
|
|
|
|
list_add_tail(&ep->list, &chip->ep_list);
|
|
@@ -1105,7 +1109,16 @@ void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep,
|
|
|
if (f == 0)
|
|
|
return;
|
|
|
|
|
|
- if (unlikely(ep->freqshift == INT_MIN)) {
|
|
|
+ if (unlikely(sender->udh01_fb_quirk)) {
|
|
|
+ /*
|
|
|
+ * The TEAC UD-H01 firmware sometimes changes the feedback value
|
|
|
+ * by +/- 0x1.0000.
|
|
|
+ */
|
|
|
+ if (f < ep->freqn - 0x8000)
|
|
|
+ f += 0x10000;
|
|
|
+ else if (f > ep->freqn + 0x8000)
|
|
|
+ f -= 0x10000;
|
|
|
+ } else if (unlikely(ep->freqshift == INT_MIN)) {
|
|
|
/*
|
|
|
* The first time we see a feedback value, determine its format
|
|
|
* by shifting it left or right until it matches the nominal
|