diff options
author | Takashi Iwai <tiwai@suse.de> | 2008-11-12 04:02:04 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2008-11-12 04:02:04 -0500 |
commit | 90d0be2fc33b4c4e11fc596da4736189be947d99 (patch) | |
tree | 0dd7e261f8d79d933c0a93c1a714b9a72fa05c28 /sound/pci/hda | |
parent | f43aa025b7de79d6a615ea4c1e6be7e6b1cea538 (diff) | |
parent | d7a8943635485597ae7c6d554a8ccf3ce5a42d2d (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.c | 2 | ||||
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 87 |
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] = { | |||
3859 | static struct snd_pci_quirk ad1884a_cfg_tbl[] = { | 3859 | static 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 | */ | ||
3900 | static 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 | |||
3887 | static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res) | 3917 | static 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 | ||
3940 | static void stac92xx_pin_sense(struct hda_codec *codec, int idx) | 3979 | static void stac92xx_pin_sense(struct hda_codec *codec, int idx) |