summaryrefslogtreecommitdiff
path: root/sound/usb
diff options
context:
space:
mode:
Diffstat (limited to 'sound/usb')
-rw-r--r--sound/usb/endpoint.c1
-rw-r--r--sound/usb/format.c70
-rw-r--r--sound/usb/mixer_scarlett2.c2
-rw-r--r--sound/usb/quirks.c2
4 files changed, 70 insertions, 5 deletions
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index 686f09529067..1a020ea55875 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -221,6 +221,7 @@ int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep,
packet = ctx->packet_size[idx];
if (packet) {
+ packet = min(packet, ep->maxframesize);
if (avail && packet >= avail)
return -EAGAIN;
return packet;
diff --git a/sound/usb/format.c b/sound/usb/format.c
index 64cfe4a9d8cd..1207c507882a 100644
--- a/sound/usb/format.c
+++ b/sound/usb/format.c
@@ -305,17 +305,48 @@ static bool s1810c_valid_sample_rate(struct audioformat *fp,
}
/*
- * Many Focusrite devices supports a limited set of sampling rates per
- * altsetting. Maximum rate is exposed in the last 4 bytes of Format Type
- * descriptor which has a non-standard bLength = 10.
+ * Focusrite devices use rate pairs: 44100/48000, 88200/96000, and
+ * 176400/192000. Return true if rate is in the pair for max_rate.
+ */
+static bool focusrite_rate_pair(unsigned int rate,
+ unsigned int max_rate)
+{
+ switch (max_rate) {
+ case 48000: return rate == 44100 || rate == 48000;
+ case 96000: return rate == 88200 || rate == 96000;
+ case 192000: return rate == 176400 || rate == 192000;
+ default: return true;
+ }
+}
+
+/*
+ * Focusrite devices report all supported rates in a single clock
+ * source but only a subset is valid per altsetting.
+ *
+ * Detection uses two descriptor features:
+ *
+ * 1. Format Type descriptor bLength == 10: non-standard extension
+ * with max sample rate in bytes 6..9.
+ *
+ * 2. bmControls VAL_ALT_SETTINGS readable bit: when set, the device
+ * only supports the highest rate pair for that altsetting, and when
+ * clear, all rates up to max_rate are valid.
+ *
+ * For devices without the bLength == 10 extension but with
+ * VAL_ALT_SETTINGS readable and multiple altsettings (only seen in
+ * Scarlett 18i8 3rd Gen playback), fall back to the Focusrite
+ * convention: alt 1 = 48kHz, alt 2 = 96kHz, alt 3 = 192kHz.
*/
static bool focusrite_valid_sample_rate(struct snd_usb_audio *chip,
struct audioformat *fp,
unsigned int rate)
{
+ struct usb_interface *iface;
struct usb_host_interface *alts;
+ struct uac2_as_header_descriptor *as;
unsigned char *fmt;
unsigned int max_rate;
+ bool val_alt;
alts = snd_usb_get_host_interface(chip, fp->iface, fp->altsetting);
if (!alts)
@@ -326,9 +357,21 @@ static bool focusrite_valid_sample_rate(struct snd_usb_audio *chip,
if (!fmt)
return true;
+ as = snd_usb_find_csint_desc(alts->extra, alts->extralen,
+ NULL, UAC_AS_GENERAL);
+ if (!as)
+ return true;
+
+ val_alt = uac_v2v3_control_is_readable(as->bmControls,
+ UAC2_AS_VAL_ALT_SETTINGS);
+
if (fmt[0] == 10) { /* bLength */
max_rate = combine_quad(&fmt[6]);
+ if (val_alt)
+ return focusrite_rate_pair(rate, max_rate);
+
+ /* No val_alt: rates fall through from higher */
switch (max_rate) {
case 192000:
if (rate == 176400 || rate == 192000)
@@ -344,12 +387,29 @@ static bool focusrite_valid_sample_rate(struct snd_usb_audio *chip,
usb_audio_info(chip,
"%u:%d : unexpected max rate: %u\n",
fp->iface, fp->altsetting, max_rate);
-
return true;
}
}
- return true;
+ if (!val_alt)
+ return true;
+
+ /* Multi-altsetting device with val_alt but no max_rate
+ * in the format descriptor. Use Focusrite convention:
+ * alt 1 = 48kHz, alt 2 = 96kHz, alt 3 = 192kHz.
+ */
+ iface = usb_ifnum_to_if(chip->dev, fp->iface);
+ if (!iface || iface->num_altsetting <= 2)
+ return true;
+
+ switch (fp->altsetting) {
+ case 1: max_rate = 48000; break;
+ case 2: max_rate = 96000; break;
+ case 3: max_rate = 192000; break;
+ default: return true;
+ }
+
+ return focusrite_rate_pair(rate, max_rate);
}
/*
diff --git a/sound/usb/mixer_scarlett2.c b/sound/usb/mixer_scarlett2.c
index 7b31504c5f24..4342d93ab771 100644
--- a/sound/usb/mixer_scarlett2.c
+++ b/sound/usb/mixer_scarlett2.c
@@ -8251,6 +8251,8 @@ static int scarlett2_find_fc_interface(struct usb_device *dev,
if (desc->bInterfaceClass != 255)
continue;
+ if (desc->bNumEndpoints < 1)
+ continue;
epd = get_endpoint(intf->altsetting, 0);
private->bInterfaceNumber = desc->bInterfaceNumber;
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index a89ea2233180..caca0e586d83 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -2363,6 +2363,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
DEVICE_FLG(0x2040, 0x7281, /* Hauppauge HVR-950Q-MXL */
QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+ DEVICE_FLG(0x20b1, 0x2009, /* XMOS Ltd DIYINHK USB Audio 2.0 */
+ QUIRK_FLAG_SKIP_IMPLICIT_FB | QUIRK_FLAG_DSD_RAW),
DEVICE_FLG(0x2040, 0x8200, /* Hauppauge Woodbury */
QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
DEVICE_FLG(0x21b4, 0x0081, /* AudioQuest DragonFly */