aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda
diff options
context:
space:
mode:
authorJiang zhe <zhe.jiang@intel.com>2008-03-20 07:12:39 -0400
committerTakashi Iwai <tiwai@suse.de>2008-04-24 06:00:29 -0400
commit0e31daf7d6484c60e96f63a905eb9b959b975da5 (patch)
tree492fc31362442237e54f0a7b19e179bd6cd7897a /sound/pci/hda
parent07bcb316cf3510d5048bc251bb23cd6452c16fc2 (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.c100
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
8732static 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
8731static struct hda_input_mux alc262_fujitsu_capture_source = { 8738static 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 */
8819static 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 */
8850static 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) */
8812static int alc262_fujitsu_master_sw_put(struct snd_kcontrol *kcontrol, 8859static 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) */
8900static 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
8916static 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 */
8853static struct hda_verb alc262_EAPD_verbs[] = { 8938static 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
9601static int patch_alc262(struct hda_codec *codec) 9701static int patch_alc262(struct hda_codec *codec)