Skip to content

Commit 92099de

Browse files
tatokistiwai
authored andcommitted
ALSA: usb-audio: Implement jack detection for HP Thunderbolt Dock G2
The HP Thunderbolt Dock G2 includes a headset jack with support for jack detection. However, this being a UAC1 device, detection is implemented via vendor-defined URB Controls. Implement it in a similar way to the Dell WD15/19 docks, but with different commands. Signed-off-by: Tasos Sahanidis <tasos@tasossah.com> Link: https://patch.msgid.link/20251126003805.2705503-3-tasos@tasossah.com Signed-off-by: Takashi Iwai <tiwai@suse.de>
1 parent fba2747 commit 92099de

1 file changed

Lines changed: 102 additions & 0 deletions

File tree

sound/usb/mixer_quirks.c

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2363,6 +2363,105 @@ static int dell_dock_mixer_init(struct usb_mixer_interface *mixer)
23632363
return 0;
23642364
}
23652365

2366+
/*
2367+
* HP Thunderbolt Dock G2 jack detection
2368+
*
2369+
* Similar to the Dell WD15/WD19, but with different commands.
2370+
*/
2371+
2372+
#define HP_DOCK_JACK_INTERRUPT_NODE 7
2373+
2374+
#define HP_DOCK_GET 37
2375+
2376+
#define HP_DOCK_JACK_PRESENCE 0xffb8
2377+
#define HP_DOCK_JACK_PRESENCE_BIT BIT(2)
2378+
2379+
#define HP_DOCK_MIC_SENSE 0xf753
2380+
#define HP_DOCK_MIC_SENSE_COMPLETE_BIT BIT(4)
2381+
2382+
#define HP_DOCK_MIC_SENSE_MASK (BIT(2) | BIT(1) | BIT(0))
2383+
/* #define HP_DOCK_MIC_SENSE_PRESENT 0x2 */
2384+
#define HP_DOCK_MIC_SENSE_NOT_PRESENT 0x4
2385+
2386+
static int hp_dock_ctl_connector_get(struct snd_kcontrol *kcontrol,
2387+
struct snd_ctl_elem_value *ucontrol)
2388+
{
2389+
struct usb_mixer_elem_info *cval = snd_kcontrol_chip(kcontrol);
2390+
struct snd_usb_audio *chip = cval->head.mixer->chip;
2391+
u32 pv = kcontrol->private_value;
2392+
bool presence;
2393+
int err;
2394+
u8 buf;
2395+
2396+
CLASS(snd_usb_lock, pm)(chip);
2397+
if (pm.err < 0)
2398+
return pm.err;
2399+
2400+
err = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0),
2401+
HP_DOCK_GET,
2402+
USB_RECIP_DEVICE | USB_TYPE_VENDOR | USB_DIR_IN,
2403+
0, HP_DOCK_JACK_PRESENCE, &buf, sizeof(buf));
2404+
if (err < 0)
2405+
return err;
2406+
2407+
presence = !(buf & HP_DOCK_JACK_PRESENCE_BIT);
2408+
2409+
if (pv && presence) {
2410+
for (int i = 0; i < 20; i++) {
2411+
err = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0),
2412+
HP_DOCK_GET,
2413+
USB_RECIP_DEVICE | USB_TYPE_VENDOR | USB_DIR_IN,
2414+
0, HP_DOCK_MIC_SENSE, &buf, sizeof(buf));
2415+
if (err < 0)
2416+
return err;
2417+
2418+
/* Mic sense is complete, we have a result. */
2419+
if (buf & HP_DOCK_MIC_SENSE_COMPLETE_BIT)
2420+
break;
2421+
2422+
msleep(100);
2423+
}
2424+
2425+
/*
2426+
* If we reach the retry limit without mic sense having
2427+
* completed, buf will contain HP_DOCK_MIC_SENSE_PRESENT,
2428+
* thus presence remains true even when detection fails.
2429+
*/
2430+
if ((buf & HP_DOCK_MIC_SENSE_MASK) == HP_DOCK_MIC_SENSE_NOT_PRESENT)
2431+
presence = false;
2432+
}
2433+
ucontrol->value.integer.value[0] = presence;
2434+
return 0;
2435+
}
2436+
2437+
static const struct snd_kcontrol_new hp_dock_connector_ctl_ro = {
2438+
.iface = SNDRV_CTL_ELEM_IFACE_CARD,
2439+
.name = "", /* will be filled later manually */
2440+
.access = SNDRV_CTL_ELEM_ACCESS_READ,
2441+
.info = snd_ctl_boolean_mono_info,
2442+
.get = hp_dock_ctl_connector_get,
2443+
};
2444+
2445+
static int hp_dock_mixer_create(struct usb_mixer_interface *mixer)
2446+
{
2447+
int err;
2448+
2449+
err = realtek_add_jack(mixer, "Headsets Playback Jack", 0,
2450+
HP_DOCK_JACK_INTERRUPT_NODE,
2451+
&hp_dock_connector_ctl_ro);
2452+
if (err < 0)
2453+
return err;
2454+
2455+
err = realtek_add_jack(mixer, "Headset Capture Jack", 1,
2456+
HP_DOCK_JACK_INTERRUPT_NODE,
2457+
&hp_dock_connector_ctl_ro);
2458+
if (err < 0)
2459+
return err;
2460+
2461+
return 0;
2462+
}
2463+
2464+
23662465
/* RME Class Compliant device quirks */
23672466

23682467
#define SND_RME_GET_STATUS1 23
@@ -4414,6 +4513,9 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
44144513
case USB_ID(0x2b73, 0x0034): /* Pioneer DJ DJM-V10 */
44154514
err = snd_djm_controls_create(mixer, SND_DJM_V10_IDX);
44164515
break;
4516+
case USB_ID(0x03f0, 0x0269): /* HP TB Dock G2 */
4517+
err = hp_dock_mixer_create(mixer);
4518+
break;
44174519
}
44184520

44194521
return err;

0 commit comments

Comments
 (0)