mirror of https://github.com/torvalds/linux.git
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>
This commit is contained in:
parent
fba274760d
commit
92099de846
|
|
@ -2363,6 +2363,105 @@ static int dell_dock_mixer_init(struct usb_mixer_interface *mixer)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* HP Thunderbolt Dock G2 jack detection
|
||||
*
|
||||
* Similar to the Dell WD15/WD19, but with different commands.
|
||||
*/
|
||||
|
||||
#define HP_DOCK_JACK_INTERRUPT_NODE 7
|
||||
|
||||
#define HP_DOCK_GET 37
|
||||
|
||||
#define HP_DOCK_JACK_PRESENCE 0xffb8
|
||||
#define HP_DOCK_JACK_PRESENCE_BIT BIT(2)
|
||||
|
||||
#define HP_DOCK_MIC_SENSE 0xf753
|
||||
#define HP_DOCK_MIC_SENSE_COMPLETE_BIT BIT(4)
|
||||
|
||||
#define HP_DOCK_MIC_SENSE_MASK (BIT(2) | BIT(1) | BIT(0))
|
||||
/* #define HP_DOCK_MIC_SENSE_PRESENT 0x2 */
|
||||
#define HP_DOCK_MIC_SENSE_NOT_PRESENT 0x4
|
||||
|
||||
static int hp_dock_ctl_connector_get(struct snd_kcontrol *kcontrol,
|
||||
struct snd_ctl_elem_value *ucontrol)
|
||||
{
|
||||
struct usb_mixer_elem_info *cval = snd_kcontrol_chip(kcontrol);
|
||||
struct snd_usb_audio *chip = cval->head.mixer->chip;
|
||||
u32 pv = kcontrol->private_value;
|
||||
bool presence;
|
||||
int err;
|
||||
u8 buf;
|
||||
|
||||
CLASS(snd_usb_lock, pm)(chip);
|
||||
if (pm.err < 0)
|
||||
return pm.err;
|
||||
|
||||
err = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0),
|
||||
HP_DOCK_GET,
|
||||
USB_RECIP_DEVICE | USB_TYPE_VENDOR | USB_DIR_IN,
|
||||
0, HP_DOCK_JACK_PRESENCE, &buf, sizeof(buf));
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
presence = !(buf & HP_DOCK_JACK_PRESENCE_BIT);
|
||||
|
||||
if (pv && presence) {
|
||||
for (int i = 0; i < 20; i++) {
|
||||
err = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0),
|
||||
HP_DOCK_GET,
|
||||
USB_RECIP_DEVICE | USB_TYPE_VENDOR | USB_DIR_IN,
|
||||
0, HP_DOCK_MIC_SENSE, &buf, sizeof(buf));
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
/* Mic sense is complete, we have a result. */
|
||||
if (buf & HP_DOCK_MIC_SENSE_COMPLETE_BIT)
|
||||
break;
|
||||
|
||||
msleep(100);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we reach the retry limit without mic sense having
|
||||
* completed, buf will contain HP_DOCK_MIC_SENSE_PRESENT,
|
||||
* thus presence remains true even when detection fails.
|
||||
*/
|
||||
if ((buf & HP_DOCK_MIC_SENSE_MASK) == HP_DOCK_MIC_SENSE_NOT_PRESENT)
|
||||
presence = false;
|
||||
}
|
||||
ucontrol->value.integer.value[0] = presence;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct snd_kcontrol_new hp_dock_connector_ctl_ro = {
|
||||
.iface = SNDRV_CTL_ELEM_IFACE_CARD,
|
||||
.name = "", /* will be filled later manually */
|
||||
.access = SNDRV_CTL_ELEM_ACCESS_READ,
|
||||
.info = snd_ctl_boolean_mono_info,
|
||||
.get = hp_dock_ctl_connector_get,
|
||||
};
|
||||
|
||||
static int hp_dock_mixer_create(struct usb_mixer_interface *mixer)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = realtek_add_jack(mixer, "Headsets Playback Jack", 0,
|
||||
HP_DOCK_JACK_INTERRUPT_NODE,
|
||||
&hp_dock_connector_ctl_ro);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = realtek_add_jack(mixer, "Headset Capture Jack", 1,
|
||||
HP_DOCK_JACK_INTERRUPT_NODE,
|
||||
&hp_dock_connector_ctl_ro);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* RME Class Compliant device quirks */
|
||||
|
||||
#define SND_RME_GET_STATUS1 23
|
||||
|
|
@ -4414,6 +4513,9 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
|
|||
case USB_ID(0x2b73, 0x0034): /* Pioneer DJ DJM-V10 */
|
||||
err = snd_djm_controls_create(mixer, SND_DJM_V10_IDX);
|
||||
break;
|
||||
case USB_ID(0x03f0, 0x0269): /* HP TB Dock G2 */
|
||||
err = hp_dock_mixer_create(mixer);
|
||||
break;
|
||||
}
|
||||
|
||||
return err;
|
||||
|
|
|
|||
Loading…
Reference in New Issue