]> git.baikalelectronics.ru Git - kernel.git/commitdiff
ALSA: usb-audio: Turn off 'manual mode' on Dell dock
authorJan Schär <jan@jschaer.ch>
Mon, 27 Jun 2022 17:18:55 +0000 (19:18 +0200)
committerTakashi Iwai <tiwai@suse.de>
Mon, 4 Jul 2022 12:27:16 +0000 (14:27 +0200)
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: dd28bf8af7fd ("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>
sound/usb/mixer_quirks.c

index 66b6476994eb963839233699291d1fbc02b9392a..5a45822e60e743357d5a610e56bb13cf52a41514 100644 (file)
@@ -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);
 }