ALSA: hda - Add snd_hda_get_default_vref() helper function
authorTakashi Iwai <tiwai@suse.de>
Fri, 20 Apr 2012 11:06:53 +0000 (13:06 +0200)
committerTakashi Iwai <tiwai@suse.de>
Fri, 20 Apr 2012 11:06:53 +0000 (13:06 +0200)
Add a new helper function to guess the default VREF pin control bits
for mic in.  This can be used to set the pin control value safely
matching with the actual pin capabilities.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_local.h
sound/pci/hda/patch_analog.c
sound/pci/hda/patch_ca0110.c
sound/pci/hda/patch_ca0132.c
sound/pci/hda/patch_cirrus.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/pci/hda/patch_via.c

index 2d9716e7a116aae3ced1523d4375d9928da5ec83..8b8b74a1284c1f7542f4f746c88d0024e7fc6aa4 100644 (file)
@@ -4795,6 +4795,33 @@ int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
 }
 EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_cleanup);
 
+/**
+ * snd_hda_get_default_vref - Get the default (mic) VREF pin bits
+ *
+ * Guess the suitable VREF pin bits to be set as the pin-control value.
+ * Note: the function doesn't set the AC_PINCTL_IN_EN bit.
+ */
+unsigned int snd_hda_get_default_vref(struct hda_codec *codec, hda_nid_t pin)
+{
+       unsigned int pincap;
+       unsigned int oldval;
+       oldval = snd_hda_codec_read(codec, pin, 0,
+                                   AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+       pincap = snd_hda_query_pin_caps(codec, pin);
+       pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
+       /* Exception: if the default pin setup is vref50, we give it priority */
+       if ((pincap & AC_PINCAP_VREF_80) && oldval != PIN_VREF50)
+               return AC_PINCTL_VREF_80;
+       else if (pincap & AC_PINCAP_VREF_50)
+               return AC_PINCTL_VREF_50;
+       else if (pincap & AC_PINCAP_VREF_100)
+               return AC_PINCTL_VREF_100;
+       else if (pincap & AC_PINCAP_VREF_GRD)
+               return AC_PINCTL_VREF_GRD;
+       return AC_PINCTL_VREF_HIZ;
+}
+EXPORT_SYMBOL_HDA(snd_hda_get_default_vref);
+
 int _snd_hda_set_pin_ctl(struct hda_codec *codec, hda_nid_t pin,
                         unsigned int val, bool cached)
 {
index 17d425775c99cbafb90e600de17bd9a169021cf8..a5cee952547d1e61f82da6244b867596080675ab 100644 (file)
@@ -502,6 +502,7 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
 #define PIN_HP                 (AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN)
 #define PIN_HP_AMP             (AC_PINCTL_HP_EN)
 
+unsigned int snd_hda_get_default_vref(struct hda_codec *codec, hda_nid_t pin);
 int _snd_hda_set_pin_ctl(struct hda_codec *codec, hda_nid_t pin,
                         unsigned int val, bool cached);
 
@@ -517,6 +518,7 @@ int _snd_hda_set_pin_ctl(struct hda_codec *codec, hda_nid_t pin,
  * HP-drive capability, the HP bit is omitted.
  *
  * The function doesn't check the input VREF capability bits, though.
+ * Use snd_hda_get_default_vref() to guess the right value.
  * Also, this function is only for analog pins, not for HDMI pins.
  */
 static inline int
index 38163abeea92f8168bf64f5eea9b5fc33bd92291..723bb9cb5f09d2fa92588aaaea5ddda7ffd701c6 100644 (file)
@@ -3155,6 +3155,7 @@ static void ad1988_auto_init_analog_input(struct hda_codec *codec)
        for (i = 0; i < cfg->num_inputs; i++) {
                hda_nid_t nid = cfg->inputs[i].pin;
                int type = cfg->inputs[i].type;
+               int val;
                switch (nid) {
                case 0x15: /* port-C */
                        snd_hda_codec_write(codec, 0x33, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
@@ -3163,8 +3164,10 @@ static void ad1988_auto_init_analog_input(struct hda_codec *codec)
                        snd_hda_codec_write(codec, 0x34, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
                        break;
                }
-               snd_hda_set_pin_ctl(codec, nid,
-                                   type == AUTO_PIN_MIC ? PIN_VREF80 : PIN_IN);
+               val = PIN_IN;
+               if (type == AUTO_PIN_MIC)
+                       val |= snd_hda_get_default_vref(codec, nid);
+               snd_hda_set_pin_ctl(codec, nid, val);
                if (nid != AD1988_PIN_CD_NID)
                        snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
                                            AMP_OUT_MUTE);
index 646dc976f4bdd314cb8b2677c6a5fd099daa0610..a3b70a8f6df876716496a0182cde9fe11c84120a 100644 (file)
@@ -355,7 +355,8 @@ static void init_output(struct hda_codec *codec, hda_nid_t pin, hda_nid_t dac)
 static void init_input(struct hda_codec *codec, hda_nid_t pin, hda_nid_t adc)
 {
        if (pin) {
-               snd_hda_set_pin_ctl(codec, pin, PIN_VREF80);
+               snd_hda_set_pin_ctl(codec, pin, PIN_IN |
+                                   snd_hda_get_default_vref(codec, pin));
                if (get_wcaps(codec, pin) & AC_WCAP_IN_AMP)
                        snd_hda_codec_write(codec, pin, 0,
                                            AC_VERB_SET_AMP_GAIN_MUTE,
index ea63333f41fecea3a9301774fb74c9e2e808a212..d290a8ff0108b047fe29bdc31253f01cda22d6e0 100644 (file)
@@ -253,7 +253,8 @@ static void init_output(struct hda_codec *codec, hda_nid_t pin, hda_nid_t dac)
 static void init_input(struct hda_codec *codec, hda_nid_t pin, hda_nid_t adc)
 {
        if (pin) {
-               snd_hda_set_pin_ctl(codec, pin, PIN_VREF80);
+               snd_hda_set_pin_ctl(codec, pin, PIN_IN |
+                                   snd_hda_get_default_vref(codec, pin));
                if (get_wcaps(codec, pin) & AC_WCAP_IN_AMP)
                        snd_hda_codec_write(codec, pin, 0,
                                            AC_VERB_SET_AMP_GAIN_MUTE,
index 778e4b9dd88c999ef9d9761c5beaa0441b1f7427..48c6d8186e90589c173e2a50fe8734e79e76b7b4 100644 (file)
@@ -1057,12 +1057,8 @@ static void init_input(struct hda_codec *codec)
                        continue;
                /* set appropriate pin control and mute first */
                ctl = PIN_IN;
-               if (cfg->inputs[i].type == AUTO_PIN_MIC) {
-                       unsigned int caps = snd_hda_query_pin_caps(codec, pin);
-                       caps >>= AC_PINCAP_VREF_SHIFT;
-                       if (caps & AC_PINCAP_VREF_80)
-                               ctl = PIN_VREF80;
-               }
+               if (cfg->inputs[i].type == AUTO_PIN_MIC)
+                       ctl |= snd_hda_get_default_vref(codec, pin);
                snd_hda_set_pin_ctl(codec, pin, ctl);
                snd_hda_codec_write(codec, spec->adc_nid[i], 0,
                                    AC_VERB_SET_AMP_GAIN_MUTE,
index afa510f0b99367fe337e5bf0ada528b2a8ebe322..aabdb9e9a484c2978f21ef19873e7ce51001eb26 100644 (file)
@@ -4020,12 +4020,11 @@ static void cx_auto_init_input(struct hda_codec *codec)
        }
 
        for (i = 0; i < cfg->num_inputs; i++) {
-               unsigned int type;
+               hda_nid_t pin = cfg->inputs[i].pin;
+               unsigned int type = PIN_IN;
                if (cfg->inputs[i].type == AUTO_PIN_MIC)
-                       type = PIN_VREF80;
-               else
-                       type = PIN_IN;
-               snd_hda_set_pin_ctl(codec, cfg->inputs[i].pin, type);
+                       type |= snd_hda_get_default_vref(codec, pin);
+               snd_hda_set_pin_ctl(codec, pin, type);
        }
 
        if (spec->auto_mic) {
index 9560b8e1e85c1a2e4eca7131fc3ce78eb181f7fa..951a090cef4ac351392e2fcbc6472f3b9d39b0b0 100644 (file)
@@ -325,7 +325,7 @@ static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx,
                 * first is the real internal mic and the second is HP jack.
                 */
                if (spec->cur_mux[adc_idx])
-                       val = PIN_VREF80;
+                       val = snd_hda_get_default_vref(codec, pin) | PIN_IN;
                else
                        val = PIN_HP;
                snd_hda_set_pin_ctl(codec, pin, val);
@@ -379,24 +379,8 @@ static void alc_set_input_pin(struct hda_codec *codec, hda_nid_t nid,
                              int auto_pin_type)
 {
        unsigned int val = PIN_IN;
-
-       if (auto_pin_type == AUTO_PIN_MIC) {
-               unsigned int pincap;
-               unsigned int oldval;
-               oldval = snd_hda_codec_read(codec, nid, 0,
-                                           AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
-               pincap = snd_hda_query_pin_caps(codec, nid);
-               pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
-               /* if the default pin setup is vref50, we give it priority */
-               if ((pincap & AC_PINCAP_VREF_80) && oldval != PIN_VREF50)
-                       val = PIN_VREF80;
-               else if (pincap & AC_PINCAP_VREF_50)
-                       val = PIN_VREF50;
-               else if (pincap & AC_PINCAP_VREF_100)
-                       val = PIN_VREF100;
-               else if (pincap & AC_PINCAP_VREF_GRD)
-                       val = PIN_VREFGRD;
-       }
+       if (auto_pin_type == AUTO_PIN_MIC)
+               val |= snd_hda_get_default_vref(codec, nid);
        snd_hda_set_pin_ctl(codec, nid, val);
 }
 
index 21de62b7c991ddf25b9499b77ff7dec9b82cf7b8..884f8ad351fd713510125bf023921cad030db492 100644 (file)
@@ -2503,22 +2503,6 @@ static int stac92xx_build_pcms(struct hda_codec *codec)
        return 0;
 }
 
-static unsigned int stac92xx_get_default_vref(struct hda_codec *codec,
-                                       hda_nid_t nid)
-{
-       unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
-       pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
-       if (pincap & AC_PINCAP_VREF_100)
-               return AC_PINCTL_VREF_100;
-       if (pincap & AC_PINCAP_VREF_80)
-               return AC_PINCTL_VREF_80;
-       if (pincap & AC_PINCAP_VREF_50)
-               return AC_PINCTL_VREF_50;
-       if (pincap & AC_PINCAP_VREF_GRD)
-               return AC_PINCTL_VREF_GRD;
-       return 0;
-}
-
 static void stac92xx_auto_set_pinctl(struct hda_codec *codec, hda_nid_t nid, int pin_type)
 
 {
@@ -2591,7 +2575,7 @@ static int stac92xx_dc_bias_get(struct snd_kcontrol *kcontrol,
        hda_nid_t nid = kcontrol->private_value;
        unsigned int vref = stac92xx_vref_get(codec, nid);
 
-       if (vref == stac92xx_get_default_vref(codec, nid))
+       if (vref == snd_hda_get_default_vref(codec, nid))
                ucontrol->value.enumerated.item[0] = 0;
        else if (vref == AC_PINCTL_VREF_GRD)
                ucontrol->value.enumerated.item[0] = 1;
@@ -2610,7 +2594,7 @@ static int stac92xx_dc_bias_put(struct snd_kcontrol *kcontrol,
        hda_nid_t nid = kcontrol->private_value;
 
        if (ucontrol->value.enumerated.item[0] == 0)
-               new_vref = stac92xx_get_default_vref(codec, nid);
+               new_vref = snd_hda_get_default_vref(codec, nid);
        else if (ucontrol->value.enumerated.item[0] == 1)
                new_vref = AC_PINCTL_VREF_GRD;
        else if (ucontrol->value.enumerated.item[0] == 2)
@@ -2676,7 +2660,7 @@ static int stac92xx_io_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_
        else {
                unsigned int pinctl = AC_PINCTL_IN_EN;
                if (io_idx) /* set VREF for mic */
-                       pinctl |= stac92xx_get_default_vref(codec, nid);
+                       pinctl |= snd_hda_get_default_vref(codec, nid);
                stac92xx_auto_set_pinctl(codec, nid, pinctl);
        }
 
@@ -2844,7 +2828,7 @@ static inline int stac92xx_add_jack_mode_control(struct hda_codec *codec,
        char name[22];
 
        if (snd_hda_get_input_pin_attr(def_conf) != INPUT_PIN_ATTR_INT) {
-               if (stac92xx_get_default_vref(codec, nid) == AC_PINCTL_VREF_GRD
+               if (snd_hda_get_default_vref(codec, nid) == AC_PINCTL_VREF_GRD
                        && nid == spec->line_switch)
                        control = STAC_CTL_WIDGET_IO_SWITCH;
                else if (snd_hda_query_pin_caps(codec, nid)
@@ -4351,7 +4335,7 @@ static int stac92xx_init(struct hda_codec *codec)
                unsigned int pinctl, conf;
                if (type == AUTO_PIN_MIC) {
                        /* for mic pins, force to initialize */
-                       pinctl = stac92xx_get_default_vref(codec, nid);
+                       pinctl = snd_hda_get_default_vref(codec, nid);
                        pinctl |= AC_PINCTL_IN_EN;
                        stac92xx_auto_set_pinctl(codec, nid, pinctl);
                } else {
index 8ee531aeda6e6c3cfe123eb9f95775d1e8cc2f99..92e11672b91cd620ed0a05a696d489e2c50cfd3b 100644 (file)
@@ -661,10 +661,11 @@ static void via_auto_init_analog_input(struct hda_codec *codec)
                hda_nid_t nid = cfg->inputs[i].pin;
                if (spec->smart51_enabled && is_smart51_pins(codec, nid))
                        ctl = PIN_OUT;
-               else if (cfg->inputs[i].type == AUTO_PIN_MIC)
-                       ctl = PIN_VREF50;
-               else
+               else {
                        ctl = PIN_IN;
+                       if (cfg->inputs[i].type == AUTO_PIN_MIC)
+                               ctl |= snd_hda_get_default_vref(codec, nid);
+               }
                snd_hda_set_pin_ctl(codec, nid, ctl);
        }