]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 5.15
authorSasha Levin <sashal@kernel.org>
Mon, 11 Nov 2024 16:58:46 +0000 (11:58 -0500)
committerSasha Levin <sashal@kernel.org>
Mon, 11 Nov 2024 16:58:46 +0000 (11:58 -0500)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-5.15/alsa-usb-audio-add-quirks-for-dell-wd19-dock.patch [new file with mode: 0644]
queue-5.15/alsa-usb-audio-support-jack-detection-on-dell-dock.patch [new file with mode: 0644]
queue-5.15/series

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 (file)
index 0000000..3408a21
--- /dev/null
@@ -0,0 +1,47 @@
+From e8ae73dee7bf9f00cc11f7ec4a5bdfbe403f6307 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <jan@jschaer.ch>
+
+[ 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 <jan@jschaer.ch>
+Cc: <stable@vger.kernel.org>
+Link: https://patch.msgid.link/20241029221249.15661-1-jan@jschaer.ch
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..9dbcab7
--- /dev/null
@@ -0,0 +1,233 @@
+From 106d633d0348874f77e78f2df82b505f3608d794 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <jan@jschaer.ch>
+
+[ 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 <jan@jschaer.ch>
+Link: https://lore.kernel.org/r/20220627171855.42338-1-jan@jschaer.ch
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Stable-dep-of: 4413665dd6c5 ("ALSA: usb-audio: Add quirks for Dell WD19 dock")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 <sound/asoundef.h>
+ #include <sound/core.h>
+ #include <sound/control.h>
++#include <sound/hda_verbs.h>
+ #include <sound/hwdep.h>
+ #include <sound/info.h>
+ #include <sound/tlv.h>
+@@ -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
+
index 3c85a79b7f9e1bdf174e96db32a9ae68f3e8a952..e596278d94389d2e309a9177d06b7e6263ad5a42 100644 (file)
@@ -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