Commit 2e57a335 authored by Jan Schär's avatar Jan Schär Committed by Takashi Iwai

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: 964af639 ("ALSA: usb-audio: Initialize Dell Dock playback volumes")
Signed-off-by: default avatarJan Schär <jan@jschaer.ch>
Link: https://lore.kernel.org/r/20220627171855.42338-2-jan@jschaer.chSigned-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 4b8ea38f
...@@ -1949,9 +1949,11 @@ static int snd_soundblaster_e1_switch_create(struct usb_mixer_interface *mixer) ...@@ -1949,9 +1949,11 @@ static int snd_soundblaster_e1_switch_create(struct usb_mixer_interface *mixer)
#define REALTEK_HDA_VALUE 0x0038 #define REALTEK_HDA_VALUE 0x0038
#define REALTEK_HDA_SET 62 #define REALTEK_HDA_SET 62
#define REALTEK_MANUAL_MODE 72
#define REALTEK_HDA_GET_OUT 88 #define REALTEK_HDA_GET_OUT 88
#define REALTEK_HDA_GET_IN 89 #define REALTEK_HDA_GET_IN 89
#define REALTEK_AUDIO_FUNCTION_GROUP 0x01
#define REALTEK_LINE1 0x1a #define REALTEK_LINE1 0x1a
#define REALTEK_VENDOR_REGISTERS 0x20 #define REALTEK_VENDOR_REGISTERS 0x20
#define REALTEK_HP_OUT 0x21 #define REALTEK_HP_OUT 0x21
...@@ -2084,6 +2086,21 @@ static int realtek_add_jack(struct usb_mixer_interface *mixer, ...@@ -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) static int dell_dock_mixer_create(struct usb_mixer_interface *mixer)
{ {
int err; 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); err = realtek_add_jack(mixer, "Line Out Jack", REALTEK_LINE1);
if (err < 0) if (err < 0)
...@@ -2104,7 +2121,8 @@ static void dell_dock_init_vol(struct snd_usb_audio *chip, int ch, int id) ...@@ -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, snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0), UAC_SET_CUR,
USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, 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); &buf, 2);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment