diff options
author | Takashi Iwai <tiwai@suse.de> | 2012-03-12 07:35:27 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2012-03-12 09:52:43 -0400 |
commit | 420b0febe54099ea9003bddad0a81e882a8472af (patch) | |
tree | 625829e2a6b6958a6ab6ae9e18b5a631b137c4ec /sound/pci/hda/patch_realtek.c | |
parent | 2faa3bf15ba69fa12bc53926b88982b3875abb3f (diff) |
ALSA: hda - Rewrite the mute-LED control with vmaster hook for ALC269
We've had ugly static handling of the mute-LED with a powersave hook
for ALC269 HP laptops just like done in patch_sigmatel.c. This is now
rewritten with the new vmaster hook and a fixup code.
For that, the new fixup action, ALC_FIXUP_ACT_BUILD, is introduced.
It's called after build_controls is called. The reason of this new
action is that vmaster hook must be added at this stage (not in init
or probe).
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/patch_realtek.c')
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 82 |
1 files changed, 44 insertions, 38 deletions
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 1de0c1629bab..901547216c4e 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -198,6 +198,7 @@ struct alc_spec { | |||
198 | 198 | ||
199 | /* for virtual master */ | 199 | /* for virtual master */ |
200 | hda_nid_t vmaster_nid; | 200 | hda_nid_t vmaster_nid; |
201 | struct snd_kcontrol *vmaster_sw_kctl; | ||
201 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 202 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
202 | struct hda_loopback_check loopback; | 203 | struct hda_loopback_check loopback; |
203 | int num_loopbacks; | 204 | int num_loopbacks; |
@@ -1441,6 +1442,7 @@ enum { | |||
1441 | ALC_FIXUP_ACT_PRE_PROBE, | 1442 | ALC_FIXUP_ACT_PRE_PROBE, |
1442 | ALC_FIXUP_ACT_PROBE, | 1443 | ALC_FIXUP_ACT_PROBE, |
1443 | ALC_FIXUP_ACT_INIT, | 1444 | ALC_FIXUP_ACT_INIT, |
1445 | ALC_FIXUP_ACT_BUILD, | ||
1444 | }; | 1446 | }; |
1445 | 1447 | ||
1446 | static void alc_apply_fixup(struct hda_codec *codec, int action) | 1448 | static void alc_apply_fixup(struct hda_codec *codec, int action) |
@@ -1955,9 +1957,10 @@ static int __alc_build_controls(struct hda_codec *codec) | |||
1955 | } | 1957 | } |
1956 | if (!spec->no_analog && | 1958 | if (!spec->no_analog && |
1957 | !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) { | 1959 | !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) { |
1958 | err = snd_hda_add_vmaster(codec, "Master Playback Switch", | 1960 | err = __snd_hda_add_vmaster(codec, "Master Playback Switch", |
1959 | NULL, alc_slave_pfxs, | 1961 | NULL, alc_slave_pfxs, |
1960 | "Playback Switch"); | 1962 | "Playback Switch", |
1963 | true, &spec->vmaster_sw_kctl); | ||
1961 | if (err < 0) | 1964 | if (err < 0) |
1962 | return err; | 1965 | return err; |
1963 | } | 1966 | } |
@@ -2042,7 +2045,11 @@ static int alc_build_controls(struct hda_codec *codec) | |||
2042 | int err = __alc_build_controls(codec); | 2045 | int err = __alc_build_controls(codec); |
2043 | if (err < 0) | 2046 | if (err < 0) |
2044 | return err; | 2047 | return err; |
2045 | return snd_hda_jack_add_kctls(codec, &spec->autocfg); | 2048 | err = snd_hda_jack_add_kctls(codec, &spec->autocfg); |
2049 | if (err < 0) | ||
2050 | return err; | ||
2051 | alc_apply_fixup(codec, ALC_FIXUP_ACT_BUILD); | ||
2052 | return 0; | ||
2046 | } | 2053 | } |
2047 | 2054 | ||
2048 | 2055 | ||
@@ -5721,35 +5728,6 @@ static const struct hda_pcm_stream alc269_44k_pcm_analog_capture = { | |||
5721 | /* NID is set in alc_build_pcms */ | 5728 | /* NID is set in alc_build_pcms */ |
5722 | }; | 5729 | }; |
5723 | 5730 | ||
5724 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
5725 | static int alc269_mic2_for_mute_led(struct hda_codec *codec) | ||
5726 | { | ||
5727 | switch (codec->subsystem_id) { | ||
5728 | case 0x103c1586: | ||
5729 | return 1; | ||
5730 | } | ||
5731 | return 0; | ||
5732 | } | ||
5733 | |||
5734 | static int alc269_mic2_mute_check_ps(struct hda_codec *codec, hda_nid_t nid) | ||
5735 | { | ||
5736 | /* update mute-LED according to the speaker mute state */ | ||
5737 | if (nid == 0x01 || nid == 0x14) { | ||
5738 | int pinval; | ||
5739 | if (snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0) & | ||
5740 | HDA_AMP_MUTE) | ||
5741 | pinval = 0x24; | ||
5742 | else | ||
5743 | pinval = 0x20; | ||
5744 | /* mic2 vref pin is used for mute LED control */ | ||
5745 | snd_hda_codec_update_cache(codec, 0x19, 0, | ||
5746 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
5747 | pinval); | ||
5748 | } | ||
5749 | return alc_check_power_status(codec, nid); | ||
5750 | } | ||
5751 | #endif /* CONFIG_SND_HDA_POWER_SAVE */ | ||
5752 | |||
5753 | /* different alc269-variants */ | 5731 | /* different alc269-variants */ |
5754 | enum { | 5732 | enum { |
5755 | ALC269_TYPE_ALC269VA, | 5733 | ALC269_TYPE_ALC269VA, |
@@ -5900,6 +5878,33 @@ static void alc269_fixup_quanta_mute(struct hda_codec *codec, | |||
5900 | spec->automute_hook = alc269_quanta_automute; | 5878 | spec->automute_hook = alc269_quanta_automute; |
5901 | } | 5879 | } |
5902 | 5880 | ||
5881 | /* update mute-LED according to the speaker mute state via mic2 VREF pin */ | ||
5882 | static void alc269_fixup_mic2_mute_hook(void *private_data, int enabled) | ||
5883 | { | ||
5884 | struct hda_codec *codec = private_data; | ||
5885 | unsigned int pinval = enabled ? 0x20 : 0x24; | ||
5886 | snd_hda_codec_update_cache(codec, 0x19, 0, | ||
5887 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
5888 | pinval); | ||
5889 | } | ||
5890 | |||
5891 | static void alc269_fixup_mic2_mute(struct hda_codec *codec, | ||
5892 | const struct alc_fixup *fix, int action) | ||
5893 | { | ||
5894 | struct alc_spec *spec = codec->spec; | ||
5895 | switch (action) { | ||
5896 | case ALC_FIXUP_ACT_BUILD: | ||
5897 | if (!spec->vmaster_sw_kctl) | ||
5898 | return; | ||
5899 | snd_ctl_add_vmaster_hook(spec->vmaster_sw_kctl, | ||
5900 | alc269_fixup_mic2_mute_hook, codec); | ||
5901 | /* fallthru */ | ||
5902 | case ALC_FIXUP_ACT_INIT: | ||
5903 | snd_ctl_sync_vmaster_hook(spec->vmaster_sw_kctl); | ||
5904 | break; | ||
5905 | } | ||
5906 | } | ||
5907 | |||
5903 | enum { | 5908 | enum { |
5904 | ALC269_FIXUP_SONY_VAIO, | 5909 | ALC269_FIXUP_SONY_VAIO, |
5905 | ALC275_FIXUP_SONY_VAIO_GPIO2, | 5910 | ALC275_FIXUP_SONY_VAIO_GPIO2, |
@@ -5917,6 +5922,7 @@ enum { | |||
5917 | ALC269_FIXUP_DMIC, | 5922 | ALC269_FIXUP_DMIC, |
5918 | ALC269VB_FIXUP_AMIC, | 5923 | ALC269VB_FIXUP_AMIC, |
5919 | ALC269VB_FIXUP_DMIC, | 5924 | ALC269VB_FIXUP_DMIC, |
5925 | ALC269_FIXUP_MIC2_MUTE_LED, | ||
5920 | }; | 5926 | }; |
5921 | 5927 | ||
5922 | static const struct alc_fixup alc269_fixups[] = { | 5928 | static const struct alc_fixup alc269_fixups[] = { |
@@ -6037,9 +6043,14 @@ static const struct alc_fixup alc269_fixups[] = { | |||
6037 | { } | 6043 | { } |
6038 | }, | 6044 | }, |
6039 | }, | 6045 | }, |
6046 | [ALC269_FIXUP_MIC2_MUTE_LED] = { | ||
6047 | .type = ALC_FIXUP_FUNC, | ||
6048 | .v.func = alc269_fixup_mic2_mute, | ||
6049 | }, | ||
6040 | }; | 6050 | }; |
6041 | 6051 | ||
6042 | static const struct snd_pci_quirk alc269_fixup_tbl[] = { | 6052 | static const struct snd_pci_quirk alc269_fixup_tbl[] = { |
6053 | SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_MIC2_MUTE_LED), | ||
6043 | SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW), | 6054 | SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW), |
6044 | SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC), | 6055 | SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC), |
6045 | SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC), | 6056 | SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC), |
@@ -6231,11 +6242,6 @@ static int patch_alc269(struct hda_codec *codec) | |||
6231 | #endif | 6242 | #endif |
6232 | spec->shutup = alc269_shutup; | 6243 | spec->shutup = alc269_shutup; |
6233 | 6244 | ||
6234 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
6235 | if (alc269_mic2_for_mute_led(codec)) | ||
6236 | codec->patch_ops.check_power_status = alc269_mic2_mute_check_ps; | ||
6237 | #endif | ||
6238 | |||
6239 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); | 6245 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); |
6240 | 6246 | ||
6241 | return 0; | 6247 | return 0; |