diff options
author | Takashi Iwai <tiwai@suse.de> | 2011-06-17 10:59:21 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2011-06-20 10:23:55 -0400 |
commit | 24088a58d694ca5acc31ba67f966f60385789235 (patch) | |
tree | b853d685a49f53ea05dce9f1d63796f01ce3729f /sound/pci/hda/patch_via.c | |
parent | 5f4b36d64d1f1ba1da46bee3ec4f0519dfaf68e6 (diff) |
ALSA: hda - Add control to suppress the dynamic pin-power for VIA
Currently VIA driver controls the power-state of each pin per jack
detection. But, it means that the power-state mismatch may occur when
the machine doesn't give the proper jack-detection.
For avoiding this problem, a new control element "Dynamic Power-Control"
is provided so that user can turn on/off the pin-power control.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/patch_via.c')
-rw-r--r-- | sound/pci/hda/patch_via.c | 60 |
1 files changed, 59 insertions, 1 deletions
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 995974d0b120..8a9791ab43c0 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c | |||
@@ -153,6 +153,7 @@ struct via_spec { | |||
153 | unsigned int hp_independent_mode_index; | 153 | unsigned int hp_independent_mode_index; |
154 | unsigned int smart51_enabled; | 154 | unsigned int smart51_enabled; |
155 | unsigned int dmic_enabled; | 155 | unsigned int dmic_enabled; |
156 | unsigned int no_pin_power_ctl; | ||
156 | enum VIA_HDA_CODEC codec_type; | 157 | enum VIA_HDA_CODEC codec_type; |
157 | 158 | ||
158 | /* work to check hp jack state */ | 159 | /* work to check hp jack state */ |
@@ -605,8 +606,12 @@ static void set_pin_power_state(struct hda_codec *codec, hda_nid_t nid, | |||
605 | unsigned no_presence = (def_conf & AC_DEFCFG_MISC) | 606 | unsigned no_presence = (def_conf & AC_DEFCFG_MISC) |
606 | >> AC_DEFCFG_MISC_SHIFT | 607 | >> AC_DEFCFG_MISC_SHIFT |
607 | & AC_DEFCFG_MISC_NO_PRESENCE; /* do not support pin sense */ | 608 | & AC_DEFCFG_MISC_NO_PRESENCE; /* do not support pin sense */ |
608 | unsigned present = snd_hda_jack_detect(codec, nid); | ||
609 | struct via_spec *spec = codec->spec; | 609 | struct via_spec *spec = codec->spec; |
610 | unsigned present = 0; | ||
611 | |||
612 | no_presence |= spec->no_pin_power_ctl; | ||
613 | if (!no_presence) | ||
614 | present = snd_hda_jack_detect(codec, nid); | ||
610 | if ((spec->smart51_enabled && is_smart51_pins(spec, nid)) | 615 | if ((spec->smart51_enabled && is_smart51_pins(spec, nid)) |
611 | || ((no_presence || present) | 616 | || ((no_presence || present) |
612 | && get_defcfg_connect(def_conf) != AC_JACK_PORT_NONE)) { | 617 | && get_defcfg_connect(def_conf) != AC_JACK_PORT_NONE)) { |
@@ -618,6 +623,55 @@ static void set_pin_power_state(struct hda_codec *codec, hda_nid_t nid, | |||
618 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE, parm); | 623 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE, parm); |
619 | } | 624 | } |
620 | 625 | ||
626 | static int via_pin_power_ctl_info(struct snd_kcontrol *kcontrol, | ||
627 | struct snd_ctl_elem_info *uinfo) | ||
628 | { | ||
629 | static const char * const texts[] = { | ||
630 | "Disabled", "Enabled" | ||
631 | }; | ||
632 | |||
633 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
634 | uinfo->count = 1; | ||
635 | uinfo->value.enumerated.items = 2; | ||
636 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
637 | uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; | ||
638 | strcpy(uinfo->value.enumerated.name, | ||
639 | texts[uinfo->value.enumerated.item]); | ||
640 | return 0; | ||
641 | } | ||
642 | |||
643 | static int via_pin_power_ctl_get(struct snd_kcontrol *kcontrol, | ||
644 | struct snd_ctl_elem_value *ucontrol) | ||
645 | { | ||
646 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
647 | struct via_spec *spec = codec->spec; | ||
648 | ucontrol->value.enumerated.item[0] = !spec->no_pin_power_ctl; | ||
649 | return 0; | ||
650 | } | ||
651 | |||
652 | static int via_pin_power_ctl_put(struct snd_kcontrol *kcontrol, | ||
653 | struct snd_ctl_elem_value *ucontrol) | ||
654 | { | ||
655 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
656 | struct via_spec *spec = codec->spec; | ||
657 | unsigned int val = !ucontrol->value.enumerated.item[0]; | ||
658 | |||
659 | if (val == spec->no_pin_power_ctl) | ||
660 | return 0; | ||
661 | spec->no_pin_power_ctl = val; | ||
662 | set_widgets_power_state(codec); | ||
663 | return 1; | ||
664 | } | ||
665 | |||
666 | static const struct snd_kcontrol_new via_pin_power_ctl_enum = { | ||
667 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
668 | .name = "Dynamic Power-Control", | ||
669 | .info = via_pin_power_ctl_info, | ||
670 | .get = via_pin_power_ctl_get, | ||
671 | .put = via_pin_power_ctl_put, | ||
672 | }; | ||
673 | |||
674 | |||
621 | /* | 675 | /* |
622 | * input MUX handling | 676 | * input MUX handling |
623 | */ | 677 | */ |
@@ -1480,6 +1534,10 @@ static int via_build_controls(struct hda_codec *codec) | |||
1480 | const struct snd_kcontrol_new *knew; | 1534 | const struct snd_kcontrol_new *knew; |
1481 | int err, i; | 1535 | int err, i; |
1482 | 1536 | ||
1537 | if (spec->set_widgets_power_state) | ||
1538 | if (!via_clone_control(spec, &via_pin_power_ctl_enum)) | ||
1539 | return -ENOMEM; | ||
1540 | |||
1483 | for (i = 0; i < spec->num_mixers; i++) { | 1541 | for (i = 0; i < spec->num_mixers; i++) { |
1484 | err = snd_hda_add_new_ctls(codec, spec->mixers[i]); | 1542 | err = snd_hda_add_new_ctls(codec, spec->mixers[i]); |
1485 | if (err < 0) | 1543 | if (err < 0) |