summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRong Zhang <i@rong.moe>2026-09-08 03:34:40 +0800
committerTakashi Iwai <tiwai@suse.de>2026-09-08 09:11:44 +0200
commit8dbd4900598a2c0f486a2cee8cc548b018f75b3b (patch)
treee6806612cd47cbe704b16f3fa4ab3f9582e44b49
parent4ee51cf8141396e2b59c27cd983c1d5c9fd48297 (diff)
downloadlinux-next-8dbd4900598a2c0f486a2cee8cc548b018f75b3b.tar.gz
linux-next-8dbd4900598a2c0f486a2cee8cc548b018f75b3b.zip
ALSA: usb-audio: Add quirks for HP Elite x3 Lap Dock
The HP Elite x3 Lap Dock is a laptop-like external display device with a FHD screen, a keyboard, and a MT touchpad. It can be connected via USB-C or Miracast. As an e-waste collector, I recently brought one for 69 CNY (10.2 USD). The price already indicates how broken the device's design and compatibility are ;-P When connecting via USB-C, the video source is, of course, DisplayPort Alternate Mode. However, the audio source has nothing to do with the DisplayPort signal and is actually from a builtin UAC device. The builtin UAC device provides three Alternate Settings: - 1:1 - Capture, S16_LE, 8000/32000/44100/48000Hz - 2:1 - Playback, S16_LE, 48000Hz - 2:2 - Playback, S24_3LE, 48000Hz Unfortunately, the last one is broken because: - it doesn't accept SET_CUR(SAMPLE_RATE). QUIRK_FLAG_FIXED_RATE works around it, however... - it constantly produces severe harmonic distortion once the capture stream is also opened. The interface 2 must be closed and reopened to make it recover. IOW, simply closing the capture stream makes no difference. Considering that S24_3LE offers no additional benefit on small speakers compared to S16_LE, and 2:1 is always usable as an alternative, skip 2:2 to get rid of the trouble. Setting chip->setup to any non-default value disables the fixup and reenables 2:2 (in this case QUIRK_FLAG_FIXED_RATE is required). Quirky device sample: usb 7-1.4: new full-speed USB device number 50 using xhci_hcd usb 7-1.4: New USB device found, idVendor=03f0, idProduct=0c56, bcdDevice= 0.00 usb 7-1.4: New USB device strings: Mfr=1, Product=2, SerialNumber=0 usb 7-1.4: Product: HP Elite x3 Lap Dock usb 7-1.4: Manufacturer: HP usb 7-1.4: Found last interface = 0 usb 7-1.4: 1:1: add audio endpoint 0x81 usb 7-1.4: Creating new data endpoint #81 usb 7-1.4: 1:1 Set sample rate 48000, clock 0 usb 7-1.4: 2:1: add audio endpoint 0x1 usb 7-1.4: Creating new data endpoint #1 usb 7-1.4: 2:1 Set sample rate 48000, clock 0 usb 7-1.4: 2:2: add audio endpoint 0x1 usb 7-1.4: 2:2 Set sample rate 48000, clock 0 usb 7-1.4: 2:2: cannot set freq 48000 to ep 0x1 usb 7-1.4: [9] FU [Sidetone Playback Switch] ch = 1, val = 0/1/1 usb 7-1.4: cannot set ctl value: req = 0x4, wValue = 0x200, wIndex = 0x900, type = 4, data = 0x40/0x0 usb 7-1.4: [9] FU [Sidetone Playback Volume] ch = 1, val = -17664/0/128 usb 7-1.4: [2] FU [Headset Playback Switch] ch = 1, val = 0/1/1 usb 7-1.4: [2] FU [Headset Playback Volume] ch = 2, val = -18944/0/1 usb 7-1.4: [6] FU [Headset Capture Switch] ch = 1, val = 0/1/1 usb 7-1.4: [6] FU [Headset Capture Volume] ch = 2, val = -18944/0/1 input: HP HP Elite x3 Lap Dock Consumer Control as /devices/pci0000:00/0000:00:08.3/0000:c9:00.4/usb7/7-1/7-1.4/7-1.4:1.3/0003:03F0:0C56.0033/input/input129 input: HP HP Elite x3 Lap Dock as /devices/pci0000:00/0000:00:08.3/0000:c9:00.4/usb7/7-1/7-1.4/7-1.4:1.3/0003:03F0:0C56.0033/input/input130 hid-generic 0003:03F0:0C56.0033: input,hiddev100,hidraw8: USB HID v1.11 Device [HP HP Elite x3 Lap Dock] on usb-0000:c9:00.4-1.4/input3 Signed-off-by: Rong Zhang <i@rong.moe> Signed-off-by: Takashi Iwai <tiwai@suse.de> Link: https://patch.msgid.link/20260908-uac-hp-elite-x3-lap-dock-v1-2-e226cfe4038e@rong.moe
-rw-r--r--sound/usb/quirks.c38
1 files changed, 38 insertions, 0 deletions
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 61cb3f769012..8c6593ed6d2e 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -1586,11 +1586,47 @@ static int s1810c_skip_setting_quirk(struct snd_usb_audio *chip,
return 0;
}
+static int hp_elite_x3_lap_dock_skip_setting_quirk(struct snd_usb_audio *chip,
+ int iface, int altno)
+{
+ /*
+ * 1:1 - Capture, S16_LE, 8000/32000/44100/48000Hz
+ * 2:1 - Playback, S16_LE, 48000Hz
+ * 2:2 - Playback, S24_3LE, 48000Hz
+ *
+ * 2:2 is broken because:
+ * - it doesn't accept SET_CUR(SAMPLE_RATE). QUIRK_FLAG_FIXED_RATE works
+ * around it, however...
+ * - it constantly produces severe harmonic distortion once the capture
+ * stream is also opened. The interface 2 must be closed and reopened
+ * to make it recover. IOW, simply closing the capture stream makes no
+ * difference.
+ *
+ * Considering that S24_3LE offers no additional benefit on small
+ * speakers compared to S16_LE, and 2:1 is always usable as an
+ * alternative, skip 2:2 to get rid of the trouble.
+ *
+ * Setting chip->setup to any non-default value disables the fixup and
+ * reenables 2:2 (in this case QUIRK_FLAG_FIXED_RATE is required).
+ */
+ if (!chip->setup && iface == 2 && altno == 2) {
+ usb_audio_info(chip,
+ "%d:%d: skipping broken altsetting on HP Elite x3 Lap Dock\n",
+ iface, altno);
+ return 1;
+ }
+
+ return 0;
+}
+
int snd_usb_apply_interface_quirk(struct snd_usb_audio *chip,
int iface,
int altno)
{
switch (chip->usb_id) {
+ /* HP Elite x3 Lap Dock: skip broken altsets */
+ case USB_ID(0x03f0, 0x0c56):
+ return hp_elite_x3_lap_dock_skip_setting_quirk(chip, iface, altno);
/* quattro usb: skip altsets incompatible with device_setup */
case USB_ID(0x0763, 0x2001):
return quattro_skip_setting_quirk(chip, iface, altno);
@@ -2289,6 +2325,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
QUIRK_FLAG_FORCE_IFACE_RESET | QUIRK_FLAG_IFACE_DELAY),
DEVICE_FLG(0x0124, 0x0c21, /* Generic USB Headphone */
QUIRK_FLAG_FORCE_IFACE_RESET | QUIRK_FLAG_IFACE_DELAY),
+ DEVICE_FLG(0x03f0, 0x0c56, /* HP Elite x3 Lap Dock */
+ QUIRK_FLAG_FIXED_RATE),
DEVICE_FLG(0x03f0, 0x654a, /* HP 320 FHD Webcam */
QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_MIC_RES_16),
DEVICE_FLG(0x041e, 0x3000, /* Creative SB Extigy */