From: Sasha Levin Date: Mon, 11 Nov 2024 16:58:46 +0000 (-0500) Subject: Fixes for 5.15 X-Git-Tag: v5.15.172~22 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b46a5cfa3b6a5e88bb53ca833caf94e90c28578b;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 5.15 Signed-off-by: Sasha Levin --- diff --git a/queue-5.15/alsa-usb-audio-add-quirks-for-dell-wd19-dock.patch b/queue-5.15/alsa-usb-audio-add-quirks-for-dell-wd19-dock.patch new file mode 100644 index 00000000000..3408a21d60d --- /dev/null +++ b/queue-5.15/alsa-usb-audio-add-quirks-for-dell-wd19-dock.patch @@ -0,0 +1,47 @@ +From e8ae73dee7bf9f00cc11f7ec4a5bdfbe403f6307 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 29 Oct 2024 23:12:49 +0100 +Subject: ALSA: usb-audio: Add quirks for Dell WD19 dock +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Jan Schär + +[ Upstream commit 4413665dd6c528b31284119e3571c25f371e1c36 ] + +The WD19 family of docks has the same audio chipset as the WD15. This +change enables jack detection on the WD19. + +We don't need the dell_dock_mixer_init quirk for the WD19. It is only +needed because of the dell_alc4020_map quirk for the WD15 in +mixer_maps.c, which disables the volume controls. Even for the WD15, +this quirk was apparently only needed when the dock firmware was not +updated. + +Signed-off-by: Jan Schär +Cc: +Link: https://patch.msgid.link/20241029221249.15661-1-jan@jschaer.ch +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + sound/usb/mixer_quirks.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c +index 25bad7a791d7a..e150c4ee2417d 100644 +--- a/sound/usb/mixer_quirks.c ++++ b/sound/usb/mixer_quirks.c +@@ -3441,6 +3441,9 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) + break; + err = dell_dock_mixer_init(mixer); + break; ++ case USB_ID(0x0bda, 0x402e): /* Dell WD19 dock */ ++ err = dell_dock_mixer_create(mixer); ++ break; + + case USB_ID(0x2a39, 0x3fd2): /* RME ADI-2 Pro */ + case USB_ID(0x2a39, 0x3fd3): /* RME ADI-2 DAC */ +-- +2.43.0 + diff --git a/queue-5.15/alsa-usb-audio-support-jack-detection-on-dell-dock.patch b/queue-5.15/alsa-usb-audio-support-jack-detection-on-dell-dock.patch new file mode 100644 index 00000000000..9dbcab7b460 --- /dev/null +++ b/queue-5.15/alsa-usb-audio-support-jack-detection-on-dell-dock.patch @@ -0,0 +1,233 @@ +From 106d633d0348874f77e78f2df82b505f3608d794 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 27 Jun 2022 19:18:54 +0200 +Subject: ALSA: usb-audio: Support jack detection on Dell dock +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Jan Schär + +[ Upstream commit 4b8ea38fabab45ad911a32a336416062553dfe9c ] + +The Dell WD15 dock has a headset and a line out port. Add support for +detecting if a jack is inserted into one of these ports. +For the headset jack, additionally determine if a mic is present. + +The WD15 contains an ALC4020 USB audio controller and ALC3263 audio codec +from Realtek. It is a UAC 1 device, and UAC 1 does not support jack +detection. Instead, jack detection works by sending HD Audio commands over +vendor-type USB messages. + +I found out how it works by looking at USB captures on Windows. +The audio codec is very similar to the one supported by +sound/soc/codecs/rt298.c / rt298.h, some constant names and the mic +detection are adapted from there. The realtek_add_jack function is adapted +from build_connector_control in sound/usb/mixer.c. + +I tested this on a WD15 dock with the latest firmware. + +Signed-off-by: Jan Schär +Link: https://lore.kernel.org/r/20220627171855.42338-1-jan@jschaer.ch +Signed-off-by: Takashi Iwai +Stable-dep-of: 4413665dd6c5 ("ALSA: usb-audio: Add quirks for Dell WD19 dock") +Signed-off-by: Sasha Levin +--- + sound/usb/mixer_quirks.c | 167 +++++++++++++++++++++++++++++++++++++++ + 1 file changed, 167 insertions(+) + +diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c +index 9d58f8d20f6a5..25bad7a791d7a 100644 +--- a/sound/usb/mixer_quirks.c ++++ b/sound/usb/mixer_quirks.c +@@ -24,6 +24,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -1934,6 +1935,169 @@ static int snd_soundblaster_e1_switch_create(struct usb_mixer_interface *mixer) + NULL); + } + ++/* ++ * Dell WD15 dock jack detection ++ * ++ * The WD15 contains an ALC4020 USB audio controller and ALC3263 audio codec ++ * from Realtek. It is a UAC 1 device, and UAC 1 does not support jack ++ * detection. Instead, jack detection works by sending HD Audio commands over ++ * vendor-type USB messages. ++ */ ++ ++#define HDA_VERB_CMD(V, N, D) (((N) << 20) | ((V) << 8) | (D)) ++ ++#define REALTEK_HDA_VALUE 0x0038 ++ ++#define REALTEK_HDA_SET 62 ++#define REALTEK_HDA_GET_OUT 88 ++#define REALTEK_HDA_GET_IN 89 ++ ++#define REALTEK_LINE1 0x1a ++#define REALTEK_VENDOR_REGISTERS 0x20 ++#define REALTEK_HP_OUT 0x21 ++ ++#define REALTEK_CBJ_CTRL2 0x50 ++ ++#define REALTEK_JACK_INTERRUPT_NODE 5 ++ ++#define REALTEK_MIC_FLAG 0x100 ++ ++static int realtek_hda_set(struct snd_usb_audio *chip, u32 cmd) ++{ ++ struct usb_device *dev = chip->dev; ++ u32 buf = cpu_to_be32(cmd); ++ ++ return snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), REALTEK_HDA_SET, ++ USB_RECIP_DEVICE | USB_TYPE_VENDOR | USB_DIR_OUT, ++ REALTEK_HDA_VALUE, 0, &buf, sizeof(buf)); ++} ++ ++static int realtek_hda_get(struct snd_usb_audio *chip, u32 cmd, u32 *value) ++{ ++ struct usb_device *dev = chip->dev; ++ int err; ++ u32 buf = cpu_to_be32(cmd); ++ ++ err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), REALTEK_HDA_GET_OUT, ++ USB_RECIP_DEVICE | USB_TYPE_VENDOR | USB_DIR_OUT, ++ REALTEK_HDA_VALUE, 0, &buf, sizeof(buf)); ++ if (err < 0) ++ return err; ++ err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), REALTEK_HDA_GET_IN, ++ USB_RECIP_DEVICE | USB_TYPE_VENDOR | USB_DIR_IN, ++ REALTEK_HDA_VALUE, 0, &buf, sizeof(buf)); ++ if (err < 0) ++ return err; ++ ++ *value = be32_to_cpu(buf); ++ return 0; ++} ++ ++static int realtek_ctl_connector_get(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct usb_mixer_elem_info *cval = kcontrol->private_data; ++ struct snd_usb_audio *chip = cval->head.mixer->chip; ++ u32 pv = kcontrol->private_value; ++ u32 node_id = pv & 0xff; ++ u32 sense; ++ u32 cbj_ctrl2; ++ bool presence; ++ int err; ++ ++ err = snd_usb_lock_shutdown(chip); ++ if (err < 0) ++ return err; ++ err = realtek_hda_get(chip, ++ HDA_VERB_CMD(AC_VERB_GET_PIN_SENSE, node_id, 0), ++ &sense); ++ if (err < 0) ++ goto err; ++ if (pv & REALTEK_MIC_FLAG) { ++ err = realtek_hda_set(chip, ++ HDA_VERB_CMD(AC_VERB_SET_COEF_INDEX, ++ REALTEK_VENDOR_REGISTERS, ++ REALTEK_CBJ_CTRL2)); ++ if (err < 0) ++ goto err; ++ err = realtek_hda_get(chip, ++ HDA_VERB_CMD(AC_VERB_GET_PROC_COEF, ++ REALTEK_VENDOR_REGISTERS, 0), ++ &cbj_ctrl2); ++ if (err < 0) ++ goto err; ++ } ++err: ++ snd_usb_unlock_shutdown(chip); ++ if (err < 0) ++ return err; ++ ++ presence = sense & AC_PINSENSE_PRESENCE; ++ if (pv & REALTEK_MIC_FLAG) ++ presence = presence && (cbj_ctrl2 & 0x0070) == 0x0070; ++ ucontrol->value.integer.value[0] = presence; ++ return 0; ++} ++ ++static const struct snd_kcontrol_new realtek_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 = realtek_ctl_connector_get, ++}; ++ ++static int realtek_resume_jack(struct usb_mixer_elem_list *list) ++{ ++ snd_ctl_notify(list->mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE, ++ &list->kctl->id); ++ return 0; ++} ++ ++static int realtek_add_jack(struct usb_mixer_interface *mixer, ++ char *name, u32 val) ++{ ++ struct usb_mixer_elem_info *cval; ++ struct snd_kcontrol *kctl; ++ ++ cval = kzalloc(sizeof(*cval), GFP_KERNEL); ++ if (!cval) ++ return -ENOMEM; ++ snd_usb_mixer_elem_init_std(&cval->head, mixer, ++ REALTEK_JACK_INTERRUPT_NODE); ++ cval->head.resume = realtek_resume_jack; ++ cval->val_type = USB_MIXER_BOOLEAN; ++ cval->channels = 1; ++ cval->min = 0; ++ cval->max = 1; ++ kctl = snd_ctl_new1(&realtek_connector_ctl_ro, cval); ++ if (!kctl) { ++ kfree(cval); ++ return -ENOMEM; ++ } ++ kctl->private_value = val; ++ strscpy(kctl->id.name, name, sizeof(kctl->id.name)); ++ kctl->private_free = snd_usb_mixer_elem_free; ++ return snd_usb_mixer_add_control(&cval->head, kctl); ++} ++ ++static int dell_dock_mixer_create(struct usb_mixer_interface *mixer) ++{ ++ int err; ++ ++ err = realtek_add_jack(mixer, "Line Out Jack", REALTEK_LINE1); ++ if (err < 0) ++ return err; ++ err = realtek_add_jack(mixer, "Headphone Jack", REALTEK_HP_OUT); ++ if (err < 0) ++ return err; ++ err = realtek_add_jack(mixer, "Headset Mic Jack", ++ REALTEK_HP_OUT | REALTEK_MIC_FLAG); ++ if (err < 0) ++ return err; ++ return 0; ++} ++ + static void dell_dock_init_vol(struct snd_usb_audio *chip, int ch, int id) + { + u16 buf = 0; +@@ -3272,6 +3436,9 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) + err = snd_soundblaster_e1_switch_create(mixer); + break; + case USB_ID(0x0bda, 0x4014): /* Dell WD15 dock */ ++ err = dell_dock_mixer_create(mixer); ++ if (err < 0) ++ break; + err = dell_dock_mixer_init(mixer); + break; + +-- +2.43.0 + diff --git a/queue-5.15/series b/queue-5.15/series index 3c85a79b7f9..e596278d943 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -68,3 +68,5 @@ usb-serial-option-add-quectel-rg650v.patch irqchip-gic-v3-force-propagation-of-the-active-state-with-a-read-back.patch ocfs2-remove-entry-once-instead-of-null-ptr-dereference-in-ocfs2_xa_remove.patch ucounts-fix-counter-leak-in-inc_rlimit_get_ucounts.patch +alsa-usb-audio-support-jack-detection-on-dell-dock.patch +alsa-usb-audio-add-quirks-for-dell-wd19-dock.patch