diff options
author | Jiang zhe <zhe.jiang@intel.com> | 2008-03-20 07:12:39 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2008-04-24 06:00:29 -0400 |
commit | 0e31daf7d6484c60e96f63a905eb9b959b975da5 (patch) | |
tree | 492fc31362442237e54f0a7b19e179bd6cd7897a /sound/pci/hda | |
parent | 07bcb316cf3510d5048bc251bb23cd6452c16fc2 (diff) |
[ALSA] hda-codec - model for alc262 to support Lenovo 3000
This model is to support the Lenovo 3000 y410.
ALSA bug#3856:
https://bugtrack.alsa-project.org/alsa-bug/view.php?id=3856
Signed-off-by: Jiang zhe <zhe.jiang@intel.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda')
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index eb40f4820c8b..8b819072af3a 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -98,6 +98,7 @@ enum { | |||
98 | ALC262_SONY_ASSAMD, | 98 | ALC262_SONY_ASSAMD, |
99 | ALC262_BENQ_T31, | 99 | ALC262_BENQ_T31, |
100 | ALC262_ULTRA, | 100 | ALC262_ULTRA, |
101 | ALC262_LENOVO_3000, | ||
101 | ALC262_AUTO, | 102 | ALC262_AUTO, |
102 | ALC262_MODEL_LAST /* last tag */ | 103 | ALC262_MODEL_LAST /* last tag */ |
103 | }; | 104 | }; |
@@ -8728,6 +8729,12 @@ static struct hda_verb alc262_fujitsu_unsol_verbs[] = { | |||
8728 | {} | 8729 | {} |
8729 | }; | 8730 | }; |
8730 | 8731 | ||
8732 | static struct hda_verb alc262_lenovo_3000_unsol_verbs[] = { | ||
8733 | {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT}, | ||
8734 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
8735 | {} | ||
8736 | }; | ||
8737 | |||
8731 | static struct hda_input_mux alc262_fujitsu_capture_source = { | 8738 | static struct hda_input_mux alc262_fujitsu_capture_source = { |
8732 | .num_items = 3, | 8739 | .num_items = 3, |
8733 | .items = { | 8740 | .items = { |
@@ -8808,6 +8815,46 @@ static struct hda_bind_ctls alc262_fujitsu_bind_master_vol = { | |||
8808 | }, | 8815 | }, |
8809 | }; | 8816 | }; |
8810 | 8817 | ||
8818 | /* mute/unmute internal speaker according to the hp jack and mute state */ | ||
8819 | static void alc262_lenovo_3000_automute(struct hda_codec *codec, int force) | ||
8820 | { | ||
8821 | struct alc_spec *spec = codec->spec; | ||
8822 | unsigned int mute; | ||
8823 | |||
8824 | if (force || !spec->sense_updated) { | ||
8825 | unsigned int present_int_hp; | ||
8826 | /* need to execute and sync at first */ | ||
8827 | snd_hda_codec_read(codec, 0x1b, 0, AC_VERB_SET_PIN_SENSE, 0); | ||
8828 | present_int_hp = snd_hda_codec_read(codec, 0x1b, 0, | ||
8829 | AC_VERB_GET_PIN_SENSE, 0); | ||
8830 | spec->jack_present = (present_int_hp & 0x80000000) != 0; | ||
8831 | spec->sense_updated = 1; | ||
8832 | } | ||
8833 | if (spec->jack_present) { | ||
8834 | /* mute internal speaker */ | ||
8835 | snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, | ||
8836 | HDA_AMP_MUTE, HDA_AMP_MUTE); | ||
8837 | snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0, | ||
8838 | HDA_AMP_MUTE, HDA_AMP_MUTE); | ||
8839 | } else { | ||
8840 | /* unmute internal speaker if necessary */ | ||
8841 | mute = snd_hda_codec_amp_read(codec, 0x1b, 0, HDA_OUTPUT, 0); | ||
8842 | snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0, | ||
8843 | HDA_AMP_MUTE, mute); | ||
8844 | snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0, | ||
8845 | HDA_AMP_MUTE, mute); | ||
8846 | } | ||
8847 | } | ||
8848 | |||
8849 | /* unsolicited event for HP jack sensing */ | ||
8850 | static void alc262_lenovo_3000_unsol_event(struct hda_codec *codec, | ||
8851 | unsigned int res) | ||
8852 | { | ||
8853 | if ((res >> 26) != ALC_HP_EVENT) | ||
8854 | return; | ||
8855 | alc262_lenovo_3000_automute(codec, 1); | ||
8856 | } | ||
8857 | |||
8811 | /* bind hp and internal speaker mute (with plug check) */ | 8858 | /* bind hp and internal speaker mute (with plug check) */ |
8812 | static int alc262_fujitsu_master_sw_put(struct snd_kcontrol *kcontrol, | 8859 | static int alc262_fujitsu_master_sw_put(struct snd_kcontrol *kcontrol, |
8813 | struct snd_ctl_elem_value *ucontrol) | 8860 | struct snd_ctl_elem_value *ucontrol) |
@@ -8849,6 +8896,44 @@ static struct snd_kcontrol_new alc262_fujitsu_mixer[] = { | |||
8849 | { } /* end */ | 8896 | { } /* end */ |
8850 | }; | 8897 | }; |
8851 | 8898 | ||
8899 | /* bind hp and internal speaker mute (with plug check) */ | ||
8900 | static int alc262_lenovo_3000_master_sw_put(struct snd_kcontrol *kcontrol, | ||
8901 | struct snd_ctl_elem_value *ucontrol) | ||
8902 | { | ||
8903 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
8904 | long *valp = ucontrol->value.integer.value; | ||
8905 | int change; | ||
8906 | |||
8907 | change = snd_hda_codec_amp_stereo(codec, 0x1b, HDA_OUTPUT, 0, | ||
8908 | HDA_AMP_MUTE, | ||
8909 | valp ? 0 : HDA_AMP_MUTE); | ||
8910 | |||
8911 | if (change) | ||
8912 | alc262_lenovo_3000_automute(codec, 0); | ||
8913 | return change; | ||
8914 | } | ||
8915 | |||
8916 | static struct snd_kcontrol_new alc262_lenovo_3000_mixer[] = { | ||
8917 | HDA_BIND_VOL("Master Playback Volume", &alc262_fujitsu_bind_master_vol), | ||
8918 | { | ||
8919 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
8920 | .name = "Master Playback Switch", | ||
8921 | .info = snd_hda_mixer_amp_switch_info, | ||
8922 | .get = snd_hda_mixer_amp_switch_get, | ||
8923 | .put = alc262_lenovo_3000_master_sw_put, | ||
8924 | .private_value = HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT), | ||
8925 | }, | ||
8926 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | ||
8927 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | ||
8928 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | ||
8929 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
8930 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
8931 | HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT), | ||
8932 | HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | ||
8933 | HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | ||
8934 | { } /* end */ | ||
8935 | }; | ||
8936 | |||
8852 | /* additional init verbs for Benq laptops */ | 8937 | /* additional init verbs for Benq laptops */ |
8853 | static struct hda_verb alc262_EAPD_verbs[] = { | 8938 | static struct hda_verb alc262_EAPD_verbs[] = { |
8854 | {0x20, AC_VERB_SET_COEF_INDEX, 0x07}, | 8939 | {0x20, AC_VERB_SET_COEF_INDEX, 0x07}, |
@@ -9398,6 +9483,7 @@ static const char *alc262_models[ALC262_MODEL_LAST] = { | |||
9398 | [ALC262_BENQ_T31] = "benq-t31", | 9483 | [ALC262_BENQ_T31] = "benq-t31", |
9399 | [ALC262_SONY_ASSAMD] = "sony-assamd", | 9484 | [ALC262_SONY_ASSAMD] = "sony-assamd", |
9400 | [ALC262_ULTRA] = "ultra", | 9485 | [ALC262_ULTRA] = "ultra", |
9486 | [ALC262_LENOVO_3000] = "lenovo-3000", | ||
9401 | [ALC262_AUTO] = "auto", | 9487 | [ALC262_AUTO] = "auto", |
9402 | }; | 9488 | }; |
9403 | 9489 | ||
@@ -9434,6 +9520,7 @@ static struct snd_pci_quirk alc262_cfg_tbl[] = { | |||
9434 | SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FUJITSU), | 9520 | SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FUJITSU), |
9435 | SND_PCI_QUIRK(0x144d, 0xc032, "Samsung Q1 Ultra", ALC262_ULTRA), | 9521 | SND_PCI_QUIRK(0x144d, 0xc032, "Samsung Q1 Ultra", ALC262_ULTRA), |
9436 | SND_PCI_QUIRK(0x144d, 0xc039, "Samsung Q1U EL", ALC262_ULTRA), | 9522 | SND_PCI_QUIRK(0x144d, 0xc039, "Samsung Q1U EL", ALC262_ULTRA), |
9523 | SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000 y410", ALC262_LENOVO_3000), | ||
9437 | SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_BENQ_ED8), | 9524 | SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_BENQ_ED8), |
9438 | SND_PCI_QUIRK(0x17ff, 0x058d, "Benq T31-16", ALC262_BENQ_T31), | 9525 | SND_PCI_QUIRK(0x17ff, 0x058d, "Benq T31-16", ALC262_BENQ_T31), |
9439 | SND_PCI_QUIRK(0x17ff, 0x058f, "Benq Hippo", ALC262_HIPPO_1), | 9526 | SND_PCI_QUIRK(0x17ff, 0x058f, "Benq Hippo", ALC262_HIPPO_1), |
@@ -9596,6 +9683,19 @@ static struct alc_config_preset alc262_presets[] = { | |||
9596 | .unsol_event = alc262_ultra_unsol_event, | 9683 | .unsol_event = alc262_ultra_unsol_event, |
9597 | .init_hook = alc262_ultra_automute, | 9684 | .init_hook = alc262_ultra_automute, |
9598 | }, | 9685 | }, |
9686 | [ALC262_LENOVO_3000] = { | ||
9687 | .mixers = { alc262_lenovo_3000_mixer }, | ||
9688 | .init_verbs = { alc262_init_verbs, alc262_EAPD_verbs, | ||
9689 | alc262_lenovo_3000_unsol_verbs }, | ||
9690 | .num_dacs = ARRAY_SIZE(alc262_dac_nids), | ||
9691 | .dac_nids = alc262_dac_nids, | ||
9692 | .hp_nid = 0x03, | ||
9693 | .dig_out_nid = ALC262_DIGOUT_NID, | ||
9694 | .num_channel_mode = ARRAY_SIZE(alc262_modes), | ||
9695 | .channel_mode = alc262_modes, | ||
9696 | .input_mux = &alc262_fujitsu_capture_source, | ||
9697 | .unsol_event = alc262_lenovo_3000_unsol_event, | ||
9698 | }, | ||
9599 | }; | 9699 | }; |
9600 | 9700 | ||
9601 | static int patch_alc262(struct hda_codec *codec) | 9701 | static int patch_alc262(struct hda_codec *codec) |