diff options
author | Takashi Iwai <tiwai@suse.de> | 2012-02-20 06:30:59 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2012-02-29 11:38:51 -0500 |
commit | 07cafff288266c3aa082f4bda3d47989e73ee85d (patch) | |
tree | 1557aee6baa4039240c927153a8c53d5d03da6f2 /sound/pci | |
parent | 3e93f5efaf9cd48bae97ae6436cbc5f91be8003c (diff) |
ALSA: hda/conexant - Clear unsol events on unused pins
It seems that Lenovo machines (or codec chip itself?) leave the unsol
event tags and the enablement-flag from other pins bogusly even on the
unused pins. Although this shouldn't be too critical, it's better to
clear them up sanely.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci')
-rw-r--r-- | sound/pci/hda/patch_conexant.c | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 6bbdbb6dd4e5..f3b79031fcca 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
@@ -3931,6 +3931,50 @@ static void enable_unsol_pins(struct hda_codec *codec, int num_pins, | |||
3931 | snd_hda_jack_detect_enable(codec, pins[i], action); | 3931 | snd_hda_jack_detect_enable(codec, pins[i], action); |
3932 | } | 3932 | } |
3933 | 3933 | ||
3934 | static bool found_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums) | ||
3935 | { | ||
3936 | int i; | ||
3937 | for (i = 0; i < nums; i++) | ||
3938 | if (list[i] == nid) | ||
3939 | return true; | ||
3940 | return false; | ||
3941 | } | ||
3942 | |||
3943 | /* is the given NID found in any of autocfg items? */ | ||
3944 | static bool found_in_autocfg(struct auto_pin_cfg *cfg, hda_nid_t nid) | ||
3945 | { | ||
3946 | int i; | ||
3947 | |||
3948 | if (found_in_nid_list(nid, cfg->line_out_pins, cfg->line_outs) || | ||
3949 | found_in_nid_list(nid, cfg->hp_pins, cfg->hp_outs) || | ||
3950 | found_in_nid_list(nid, cfg->speaker_pins, cfg->speaker_outs) || | ||
3951 | found_in_nid_list(nid, cfg->dig_out_pins, cfg->dig_outs)) | ||
3952 | return true; | ||
3953 | for (i = 0; i < cfg->num_inputs; i++) | ||
3954 | if (cfg->inputs[i].pin == nid) | ||
3955 | return true; | ||
3956 | if (cfg->dig_in_pin == nid) | ||
3957 | return true; | ||
3958 | return false; | ||
3959 | } | ||
3960 | |||
3961 | /* clear unsol-event tags on unused pins; Conexant codecs seem to leave | ||
3962 | * invalid unsol tags by some reason | ||
3963 | */ | ||
3964 | static void clear_unsol_on_unused_pins(struct hda_codec *codec) | ||
3965 | { | ||
3966 | struct conexant_spec *spec = codec->spec; | ||
3967 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
3968 | int i; | ||
3969 | |||
3970 | for (i = 0; i < codec->init_pins.used; i++) { | ||
3971 | struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i); | ||
3972 | if (!found_in_autocfg(cfg, pin->nid)) | ||
3973 | snd_hda_codec_write(codec, pin->nid, 0, | ||
3974 | AC_VERB_SET_UNSOLICITED_ENABLE, 0); | ||
3975 | } | ||
3976 | } | ||
3977 | |||
3934 | static void cx_auto_init_output(struct hda_codec *codec) | 3978 | static void cx_auto_init_output(struct hda_codec *codec) |
3935 | { | 3979 | { |
3936 | struct conexant_spec *spec = codec->spec; | 3980 | struct conexant_spec *spec = codec->spec; |
@@ -3971,6 +4015,7 @@ static void cx_auto_init_output(struct hda_codec *codec) | |||
3971 | /* turn on all EAPDs if no individual EAPD control is available */ | 4015 | /* turn on all EAPDs if no individual EAPD control is available */ |
3972 | if (!spec->pin_eapd_ctrls) | 4016 | if (!spec->pin_eapd_ctrls) |
3973 | cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, true); | 4017 | cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, true); |
4018 | clear_unsol_on_unused_pins(codec); | ||
3974 | } | 4019 | } |
3975 | 4020 | ||
3976 | static void cx_auto_init_input(struct hda_codec *codec) | 4021 | static void cx_auto_init_input(struct hda_codec *codec) |