[alsa-devel] [PATCH - 1/2] HDA - Add SND_JACK_HEADSET and Headset jack kctl

Raymond Yau superquad.vortex2 at gmail.com
Mon Sep 21 04:12:32 CEST 2015


>From b3ed187912eccf922000aee09c04f9546b068925 Mon Sep 17 00:00:00 2001
From: Raymond Yau <superquad.vortex2 at gmail.com>
Date: Sun, 20 Sep 2015 22:10:18 +0800
Subject: [PATCH -  1/2] HDA - Add SND_JACK_HEADSET and Headset jack kctl

add headset jack kctl for alsa jack type SND_JACK_HEADSET

skip creation of Headset Mic Phantom Jack

use Headset Playback Volume and Headset Playback Switch

allow auto mic selection by using HP pin for jack sense

Signed-off-by: Raymond Yau <superquad.vortex2 at gmail.com>

diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index 24f9111..ce6da6f 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -2140,7 +2140,8 @@ static int create_hp_out_ctls(struct hda_codec *codec)
     struct hda_gen_spec *spec = codec->spec;
     return create_extra_outs(codec, spec->autocfg.hp_outs,
                  spec->hp_paths,
-                 "Headphone");
+                 spec->hs_mic_use_hp_sense ?
+                "Headset" : "Headphone");
 }

 static int create_speaker_out_ctls(struct hda_codec *codec)
@@ -4362,6 +4363,16 @@ void snd_hda_gen_line_automute(struct hda_codec
*codec,
 }
 EXPORT_SYMBOL_GPL(snd_hda_gen_line_automute);

+bool is_headset_mic(struct auto_pin_cfg *cfg, hda_nid_t pin)
+{
+    int i;
+
+    for (i = 0; i < cfg->num_inputs; i++)
+        if (cfg->inputs[i].pin == pin)
+            return cfg->inputs[i].is_headset_mic;
+    return 0;
+}
+
 /**
  * snd_hda_gen_mic_autoswitch - standard mic auto-switch helper
  * @codec: the HDA codec
@@ -4381,6 +4392,9 @@ void snd_hda_gen_mic_autoswitch(struct hda_codec
*codec,
         /* don't detect pins retasked as outputs */
         if (snd_hda_codec_get_pin_target(codec, pin) & AC_PINCTL_OUT_EN)
             continue;
+        if (spec->hs_mic_use_hp_sense &&
+            is_headset_mic(&spec->autocfg, pin))
+            pin = auto_cfg_hp_pins(&spec->autocfg)[0];
         if (snd_hda_jack_detect_state(codec, pin) == HDA_JACK_PRESENT) {
             mux_select(codec, 0, spec->am_entry[i].idx);
             return;
@@ -4662,7 +4676,9 @@ static int check_auto_mic_availability(struct
hda_codec *codec)
             if (!spec->line_in_auto_switch &&
                 cfg->inputs[i].type != AUTO_PIN_MIC)
                 return 0; /* only mic is allowed */
-            if (!is_jack_detectable(codec, nid))
+            if (!is_jack_detectable(codec, nid) &&
+                !(cfg->inputs[i].is_headset_mic &&
+                spec->hs_mic_use_hp_sense))
                 return 0; /* no unsol support */
             break;
         }
diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h
index 56e4139..96f8214 100644
--- a/sound/pci/hda/hda_generic.h
+++ b/sound/pci/hda/hda_generic.h
@@ -236,6 +236,7 @@ struct hda_gen_spec {
     unsigned int indep_hp_enabled:1; /* independent HP enabled */
     unsigned int have_aamix_ctl:1;
     unsigned int hp_mic_jack_modes:1;
+    unsigned int hs_mic_use_hp_sense:1;

     /* additional mute flags (only effective with auto_mute_via_amp=1) */
     u64 mute_bits;
diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c
index 366efbf..5fa8ace 100644
--- a/sound/pci/hda/hda_jack.c
+++ b/sound/pci/hda/hda_jack.c
@@ -19,6 +19,7 @@
 #include "hda_local.h"
 #include "hda_auto_parser.h"
 #include "hda_jack.h"
+#include "hda_generic.h"

 /**
  * is_jack_detectable - Check whether the given pin is jack-detectable
@@ -350,11 +351,14 @@ EXPORT_SYMBOL_GPL(snd_hda_jack_report_sync);
 static int get_input_jack_type(struct hda_codec *codec, hda_nid_t nid)
 {
     unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid);
+    struct hda_gen_spec *spec = codec->spec;
     switch (get_defcfg_device(def_conf)) {
     case AC_JACK_LINE_OUT:
     case AC_JACK_SPEAKER:
         return SND_JACK_LINEOUT;
     case AC_JACK_HP_OUT:
+        if (spec->hs_mic_use_hp_sense)
+            return SND_JACK_HEADSET;
         return SND_JACK_HEADPHONE;
     case AC_JACK_SPDIF_OUT:
     case AC_JACK_DIG_OTHER_OUT:
@@ -434,6 +438,7 @@ static int add_jack_kctl(struct hda_codec *codec,
hda_nid_t nid,
     char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
     int err;
     bool phantom_jack;
+    struct hda_gen_spec *spec = codec->spec;

     if (!nid)
         return 0;
@@ -446,8 +451,13 @@ static int add_jack_kctl(struct hda_codec *codec,
hda_nid_t nid,

     if (base_name)
         strlcpy(name, base_name, sizeof(name));
-    else
+    else {
         snd_hda_get_pin_label(codec, nid, cfg, name, sizeof(name), NULL);
+        if ((strcmp(name, "Headphone") == 0) &&
+            (nid == auto_cfg_hp_pins(cfg)[0]) &&
+            spec->hs_mic_use_hp_sense)
+            strlcpy(name, "Headset", sizeof(name));
+    }
     if (phantom_jack)
         /* Example final name: "Internal Mic Phantom Jack" */
         strncat(name, " Phantom", sizeof(name) - strlen(name) - 1);
@@ -469,6 +479,7 @@ int snd_hda_jack_add_kctls(struct hda_codec *codec,
                const struct auto_pin_cfg *cfg)
 {
     const hda_nid_t *p;
+    struct hda_gen_spec *spec = codec->spec;
     int i, err;

     for (i = 0; i < cfg->num_inputs; i++) {
@@ -482,6 +493,10 @@ int snd_hda_jack_add_kctls(struct hda_codec *codec,
                 err = add_jack_kctl(codec, cfg->inputs[i].pin,
                             cfg, "Headphone Mic");
         } else
+        if (cfg->inputs[i].is_headset_mic &&
+            spec->hs_mic_use_hp_sense)
+            err = 0;
+        else
             err = add_jack_kctl(codec, cfg->inputs[i].pin, cfg,
                         NULL);
         if (err < 0)
-- 
2.5.0


More information about the Alsa-devel mailing list