aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2008-11-12 04:02:04 -0500
committerTakashi Iwai <tiwai@suse.de>2008-11-12 04:02:04 -0500
commit90d0be2fc33b4c4e11fc596da4736189be947d99 (patch)
tree0dd7e261f8d79d933c0a93c1a714b9a72fa05c28 /sound/pci/hda
parentf43aa025b7de79d6a615ea4c1e6be7e6b1cea538 (diff)
parentd7a8943635485597ae7c6d554a8ccf3ce5a42d2d (diff)
Merge branch 'topic/fix/hda' into topic/hda
Conflicts: sound/pci/hda/patch_sigmatel.c
Diffstat (limited to 'sound/pci/hda')
-rw-r--r--sound/pci/hda/patch_analog.c2
-rw-r--r--sound/pci/hda/patch_sigmatel.c87
2 files changed, 65 insertions, 24 deletions
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index d0d66f341cda..032cbb4bd985 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -3859,6 +3859,8 @@ static const char *ad1884a_models[AD1884A_MODELS] = {
3859static struct snd_pci_quirk ad1884a_cfg_tbl[] = { 3859static struct snd_pci_quirk ad1884a_cfg_tbl[] = {
3860 SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE), 3860 SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE),
3861 SND_PCI_QUIRK(0x103c, 0x3056, "HP", AD1884A_MOBILE), 3861 SND_PCI_QUIRK(0x103c, 0x3056, "HP", AD1884A_MOBILE),
3862 SND_PCI_QUIRK(0x103c, 0x30e7, "HP EliteBook 8530p", AD1884A_LAPTOP),
3863 SND_PCI_QUIRK(0x103c, 0x3614, "HP 6730s", AD1884A_LAPTOP),
3862 SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD), 3864 SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD),
3863 {} 3865 {}
3864}; 3866};
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 12c88c42d7f3..ec8f5ab9c54d 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -230,7 +230,7 @@ struct sigmatel_spec {
230 /* i/o switches */ 230 /* i/o switches */
231 unsigned int io_switch[2]; 231 unsigned int io_switch[2];
232 unsigned int clfe_swap; 232 unsigned int clfe_swap;
233 unsigned int hp_switch; 233 unsigned int hp_switch; /* NID of HP as line-out */
234 unsigned int aloopback; 234 unsigned int aloopback;
235 235
236 struct hda_pcm pcm_rec[2]; /* PCM information */ 236 struct hda_pcm pcm_rec[2]; /* PCM information */
@@ -2463,7 +2463,7 @@ static int stac92xx_hp_switch_get(struct snd_kcontrol *kcontrol,
2463 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 2463 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2464 struct sigmatel_spec *spec = codec->spec; 2464 struct sigmatel_spec *spec = codec->spec;
2465 2465
2466 ucontrol->value.integer.value[0] = spec->hp_switch; 2466 ucontrol->value.integer.value[0] = !!spec->hp_switch;
2467 return 0; 2467 return 0;
2468} 2468}
2469 2469
@@ -2472,10 +2472,9 @@ static int stac92xx_hp_switch_put(struct snd_kcontrol *kcontrol,
2472{ 2472{
2473 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 2473 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2474 struct sigmatel_spec *spec = codec->spec; 2474 struct sigmatel_spec *spec = codec->spec;
2475 struct auto_pin_cfg *cfg = &spec->autocfg; 2475 int nid = kcontrol->private_value;
2476 int nid = cfg->hp_pins[cfg->hp_outs - 1]; 2476
2477 2477 spec->hp_switch = ucontrol->value.integer.value[0] ? nid : 0;
2478 spec->hp_switch = ucontrol->value.integer.value[0];
2479 2478
2480 /* check to be sure that the ports are upto date with 2479 /* check to be sure that the ports are upto date with
2481 * switch changes 2480 * switch changes
@@ -2873,7 +2872,8 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
2873 if (cfg->hp_outs > 1) { 2872 if (cfg->hp_outs > 1) {
2874 err = stac92xx_add_control(spec, 2873 err = stac92xx_add_control(spec,
2875 STAC_CTL_WIDGET_HP_SWITCH, 2874 STAC_CTL_WIDGET_HP_SWITCH,
2876 "Headphone as Line Out Switch", 0); 2875 "Headphone as Line Out Switch",
2876 cfg->hp_pins[cfg->hp_outs - 1]);
2877 if (err < 0) 2877 if (err < 0)
2878 return err; 2878 return err;
2879 } 2879 }
@@ -3541,6 +3541,12 @@ static int stac9200_parse_auto_config(struct hda_codec *codec)
3541 if ((err = stac9200_auto_create_lfe_ctls(codec, &spec->autocfg)) < 0) 3541 if ((err = stac9200_auto_create_lfe_ctls(codec, &spec->autocfg)) < 0)
3542 return err; 3542 return err;
3543 3543
3544 if (spec->num_muxes > 0) {
3545 err = stac92xx_auto_create_mux_input_ctls(codec);
3546 if (err < 0)
3547 return err;
3548 }
3549
3544 if (spec->autocfg.dig_out_pin) 3550 if (spec->autocfg.dig_out_pin)
3545 spec->multiout.dig_out_nid = 0x05; 3551 spec->multiout.dig_out_nid = 0x05;
3546 if (spec->autocfg.dig_in_pin) 3552 if (spec->autocfg.dig_in_pin)
@@ -3730,14 +3736,18 @@ static int stac92xx_init(struct hda_codec *codec)
3730 for (i = 0; i < AUTO_PIN_LAST; i++) { 3736 for (i = 0; i < AUTO_PIN_LAST; i++) {
3731 hda_nid_t nid = cfg->input_pins[i]; 3737 hda_nid_t nid = cfg->input_pins[i];
3732 if (nid) { 3738 if (nid) {
3733 unsigned int pinctl = snd_hda_codec_read(codec, nid, 3739 unsigned int pinctl;
3734 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0); 3740 if (i == AUTO_PIN_MIC || i == AUTO_PIN_FRONT_MIC) {
3735 /* if PINCTL already set then skip */ 3741 /* for mic pins, force to initialize */
3736 if (pinctl & AC_PINCAP_IN) 3742 pinctl = stac92xx_get_vref(codec, nid);
3737 continue; 3743 } else {
3738 pinctl = AC_PINCTL_IN_EN; 3744 pinctl = snd_hda_codec_read(codec, nid, 0,
3739 if (i == AUTO_PIN_MIC || i == AUTO_PIN_FRONT_MIC) 3745 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
3740 pinctl |= stac92xx_get_vref(codec, nid); 3746 /* if PINCTL already set then skip */
3747 if (pinctl & AC_PINCTL_IN_EN)
3748 continue;
3749 }
3750 pinctl |= AC_PINCTL_IN_EN;
3741 stac92xx_auto_set_pinctl(codec, nid, pinctl); 3751 stac92xx_auto_set_pinctl(codec, nid, pinctl);
3742 err = stac92xx_add_jack(codec, nid, 3752 err = stac92xx_add_jack(codec, nid,
3743 SND_JACK_MICROPHONE); 3753 SND_JACK_MICROPHONE);
@@ -3884,11 +3894,30 @@ static int get_hp_pin_presence(struct hda_codec *codec, hda_nid_t nid)
3884 return 0; 3894 return 0;
3885} 3895}
3886 3896
3897/* return non-zero if the hp-pin of the given array index isn't
3898 * a jack-detection target
3899 */
3900static int no_hp_sensing(struct sigmatel_spec *spec, int i)
3901{
3902 struct auto_pin_cfg *cfg = &spec->autocfg;
3903
3904 /* ignore sensing of shared line and mic jacks */
3905 if (spec->line_switch &&
3906 cfg->hp_pins[i] == cfg->input_pins[AUTO_PIN_LINE])
3907 return 1;
3908 if (spec->mic_switch &&
3909 cfg->hp_pins[i] == cfg->input_pins[AUTO_PIN_MIC])
3910 return 1;
3911 /* ignore if the pin is set as line-out */
3912 if (cfg->hp_pins[i] == spec->hp_switch)
3913 return 1;
3914 return 0;
3915}
3916
3887static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res) 3917static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res)
3888{ 3918{
3889 struct sigmatel_spec *spec = codec->spec; 3919 struct sigmatel_spec *spec = codec->spec;
3890 struct auto_pin_cfg *cfg = &spec->autocfg; 3920 struct auto_pin_cfg *cfg = &spec->autocfg;
3891 int nid = cfg->hp_pins[cfg->hp_outs - 1];
3892 int i, presence; 3921 int i, presence;
3893 3922
3894 presence = 0; 3923 presence = 0;
@@ -3899,15 +3928,16 @@ static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res)
3899 for (i = 0; i < cfg->hp_outs; i++) { 3928 for (i = 0; i < cfg->hp_outs; i++) {
3900 if (presence) 3929 if (presence)
3901 break; 3930 break;
3902 if (spec->hp_switch && cfg->hp_pins[i] == nid) 3931 if (no_hp_sensing(spec, i))
3903 break; 3932 continue;
3904 presence = get_hp_pin_presence(codec, cfg->hp_pins[i]); 3933 presence = get_hp_pin_presence(codec, cfg->hp_pins[i]);
3905 } 3934 }
3906 3935
3907 if (presence) { 3936 if (presence) {
3908 /* disable lineouts, enable hp */ 3937 /* disable lineouts */
3909 if (spec->hp_switch) 3938 if (spec->hp_switch)
3910 stac92xx_reset_pinctl(codec, nid, AC_PINCTL_OUT_EN); 3939 stac92xx_reset_pinctl(codec, spec->hp_switch,
3940 AC_PINCTL_OUT_EN);
3911 for (i = 0; i < cfg->line_outs; i++) 3941 for (i = 0; i < cfg->line_outs; i++)
3912 stac92xx_reset_pinctl(codec, cfg->line_out_pins[i], 3942 stac92xx_reset_pinctl(codec, cfg->line_out_pins[i],
3913 AC_PINCTL_OUT_EN); 3943 AC_PINCTL_OUT_EN);
@@ -3919,9 +3949,10 @@ static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res)
3919 spec->gpio_dir, spec->gpio_data & 3949 spec->gpio_dir, spec->gpio_data &
3920 ~spec->eapd_mask); 3950 ~spec->eapd_mask);
3921 } else { 3951 } else {
3922 /* enable lineouts, disable hp */ 3952 /* enable lineouts */
3923 if (spec->hp_switch) 3953 if (spec->hp_switch)
3924 stac92xx_set_pinctl(codec, nid, AC_PINCTL_OUT_EN); 3954 stac92xx_set_pinctl(codec, spec->hp_switch,
3955 AC_PINCTL_OUT_EN);
3925 for (i = 0; i < cfg->line_outs; i++) 3956 for (i = 0; i < cfg->line_outs; i++)
3926 stac92xx_set_pinctl(codec, cfg->line_out_pins[i], 3957 stac92xx_set_pinctl(codec, cfg->line_out_pins[i],
3927 AC_PINCTL_OUT_EN); 3958 AC_PINCTL_OUT_EN);
@@ -3933,8 +3964,16 @@ static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res)
3933 spec->gpio_dir, spec->gpio_data | 3964 spec->gpio_dir, spec->gpio_data |
3934 spec->eapd_mask); 3965 spec->eapd_mask);
3935 } 3966 }
3936 if (!spec->hp_switch && cfg->hp_outs > 1 && presence) 3967 /* toggle hp outs */
3937 stac92xx_set_pinctl(codec, nid, AC_PINCTL_OUT_EN); 3968 for (i = 0; i < cfg->hp_outs; i++) {
3969 unsigned int val = AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN;
3970 if (no_hp_sensing(spec, i))
3971 continue;
3972 if (presence)
3973 stac92xx_set_pinctl(codec, cfg->hp_pins[i], val);
3974 else
3975 stac92xx_reset_pinctl(codec, cfg->hp_pins[i], val);
3976 }
3938} 3977}
3939 3978
3940static void stac92xx_pin_sense(struct hda_codec *codec, int idx) 3979static void stac92xx_pin_sense(struct hda_codec *codec, int idx)