aboutsummaryrefslogtreecommitdiffstats
path: root/sound/usb
diff options
context:
space:
mode:
authorJan Schär <jan@jschaer.ch>2022-06-27 19:18:55 +0200
committerTakashi Iwai <tiwai@suse.de>2022-07-04 14:27:16 +0200
commit2e57a3358dda20128593fff9b39b522f1bdd26c6 (patch)
tree3a041aaa0f0fcf9df2bf90b8c071b4da18a73e4c /sound/usb
parentALSA: usb-audio: Support jack detection on Dell dock (diff)
downloadlinux-dev-2e57a3358dda20128593fff9b39b522f1bdd26c6.tar.xz
linux-dev-2e57a3358dda20128593fff9b39b522f1bdd26c6.zip
ALSA: usb-audio: Turn off 'manual mode' on Dell dock
This removes the need to power cycle the Dell WD15 dock if it has been attached to a Windows machine. The Windows driver puts the ALC4020 USB audio controller into 'manual mode', and then does all the power management and other configuration itself, by sending HD audio commands directly to the ALC3263 audio codec via vendor-type USB messages. If manual mode is off, this is all handled by the firmware, and works well enough. If manual mode is turned on, the latency of the SET INTERFACE command goes from several hundred ms to less than 1 ms (see https://bugzilla.suse.com/show_bug.cgi?id=1089467), but I'm not sure if the additional code that would be required is worth it. Funnily enough, the Windows driver tries to turn off manual mode when the dock is disconnected, which doesn't work for obvious reasons. Additionally, fix a bug in dell_dock_init_vol, which didn't work because the Control Selector was missing. Now, it properly resets the volume to 0dB. Fixes: 964af639ad69 ("ALSA: usb-audio: Initialize Dell Dock playback volumes") Signed-off-by: Jan Schär <jan@jschaer.ch> Link: https://lore.kernel.org/r/20220627171855.42338-2-jan@jschaer.ch Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/usb')
-rw-r--r--sound/usb/mixer_quirks.c20
1 files changed, 19 insertions, 1 deletions
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
index 66b6476994eb..5a45822e60e7 100644
--- a/sound/usb/mixer_quirks.c
+++ b/sound/usb/mixer_quirks.c
@@ -1949,9 +1949,11 @@ static int snd_soundblaster_e1_switch_create(struct usb_mixer_interface *mixer)
#define REALTEK_HDA_VALUE 0x0038
#define REALTEK_HDA_SET 62
+#define REALTEK_MANUAL_MODE 72
#define REALTEK_HDA_GET_OUT 88
#define REALTEK_HDA_GET_IN 89
+#define REALTEK_AUDIO_FUNCTION_GROUP 0x01
#define REALTEK_LINE1 0x1a
#define REALTEK_VENDOR_REGISTERS 0x20
#define REALTEK_HP_OUT 0x21
@@ -2084,6 +2086,21 @@ static int realtek_add_jack(struct usb_mixer_interface *mixer,
static int dell_dock_mixer_create(struct usb_mixer_interface *mixer)
{
int err;
+ struct usb_device *dev = mixer->chip->dev;
+
+ /* Power down the audio codec to avoid loud pops in the next step. */
+ realtek_hda_set(mixer->chip,
+ HDA_VERB_CMD(AC_VERB_SET_POWER_STATE,
+ REALTEK_AUDIO_FUNCTION_GROUP,
+ AC_PWRST_D3));
+
+ /*
+ * Turn off 'manual mode' in case it was enabled. This removes the need
+ * to power cycle the dock after it was attached to a Windows machine.
+ */
+ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), REALTEK_MANUAL_MODE,
+ USB_RECIP_DEVICE | USB_TYPE_VENDOR | USB_DIR_OUT,
+ 0, 0, NULL, 0);
err = realtek_add_jack(mixer, "Line Out Jack", REALTEK_LINE1);
if (err < 0)
@@ -2104,7 +2121,8 @@ static void dell_dock_init_vol(struct snd_usb_audio *chip, int ch, int id)
snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0), UAC_SET_CUR,
USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
- ch, snd_usb_ctrl_intf(chip) | (id << 8),
+ (UAC_FU_VOLUME << 8) | ch,
+ snd_usb_ctrl_intf(chip) | (id << 8),
&buf, 2);
}