diff options
Diffstat (limited to 'sound/pci/hda/patch_sigmatel.c')
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 62 |
1 files changed, 60 insertions, 2 deletions
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 07d06f7c4390..9d503da7320d 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -36,6 +36,10 @@ | |||
36 | 36 | ||
37 | #undef STAC_TEST | 37 | #undef STAC_TEST |
38 | 38 | ||
39 | #define NUM_CONTROL_ALLOC 32 | ||
40 | #define STAC_HP_EVENT 0x37 | ||
41 | #define STAC_UNSOL_ENABLE (AC_USRSP_EN | STAC_HP_EVENT) | ||
42 | |||
39 | struct sigmatel_spec { | 43 | struct sigmatel_spec { |
40 | snd_kcontrol_new_t *mixers[4]; | 44 | snd_kcontrol_new_t *mixers[4]; |
41 | unsigned int num_mixers; | 45 | unsigned int num_mixers; |
@@ -507,8 +511,6 @@ static int stac92xx_build_pcms(struct hda_codec *codec) | |||
507 | return 0; | 511 | return 0; |
508 | } | 512 | } |
509 | 513 | ||
510 | #define NUM_CONTROL_ALLOC 32 | ||
511 | |||
512 | enum { | 514 | enum { |
513 | STAC_CTL_WIDGET_VOL, | 515 | STAC_CTL_WIDGET_VOL, |
514 | STAC_CTL_WIDGET_MUTE, | 516 | STAC_CTL_WIDGET_MUTE, |
@@ -617,10 +619,18 @@ static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec, struct auto_pin | |||
617 | hda_nid_t pin = cfg->hp_pin; | 619 | hda_nid_t pin = cfg->hp_pin; |
618 | hda_nid_t nid; | 620 | hda_nid_t nid; |
619 | int i, err; | 621 | int i, err; |
622 | unsigned int wid_caps; | ||
620 | 623 | ||
621 | if (! pin) | 624 | if (! pin) |
622 | return 0; | 625 | return 0; |
623 | 626 | ||
627 | wid_caps = snd_hda_param_read(codec, pin, AC_PAR_AUDIO_WIDGET_CAP); | ||
628 | if (wid_caps & AC_WCAP_UNSOL_CAP) | ||
629 | /* Enable unsolicited responses on the HP widget */ | ||
630 | snd_hda_codec_write(codec, pin, 0, | ||
631 | AC_VERB_SET_UNSOLICITED_ENABLE, | ||
632 | STAC_UNSOL_ENABLE); | ||
633 | |||
624 | nid = snd_hda_codec_read(codec, pin, 0, AC_VERB_GET_CONNECT_LIST, 0) & 0xff; | 634 | nid = snd_hda_codec_read(codec, pin, 0, AC_VERB_GET_CONNECT_LIST, 0) & 0xff; |
625 | for (i = 0; i < cfg->line_outs; i++) { | 635 | for (i = 0; i < cfg->line_outs; i++) { |
626 | if (! spec->multiout.dac_nids[i]) | 636 | if (! spec->multiout.dac_nids[i]) |
@@ -828,6 +838,53 @@ static void stac92xx_free(struct hda_codec *codec) | |||
828 | kfree(spec); | 838 | kfree(spec); |
829 | } | 839 | } |
830 | 840 | ||
841 | static void stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid, | ||
842 | unsigned int flag) | ||
843 | { | ||
844 | unsigned int pin_ctl = snd_hda_codec_read(codec, nid, | ||
845 | 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00); | ||
846 | snd_hda_codec_write(codec, nid, 0, | ||
847 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
848 | pin_ctl | flag); | ||
849 | } | ||
850 | |||
851 | static void stac92xx_reset_pinctl(struct hda_codec *codec, hda_nid_t nid, | ||
852 | unsigned int flag) | ||
853 | { | ||
854 | unsigned int pin_ctl = snd_hda_codec_read(codec, nid, | ||
855 | 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00); | ||
856 | snd_hda_codec_write(codec, nid, 0, | ||
857 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
858 | pin_ctl & ~flag); | ||
859 | } | ||
860 | |||
861 | static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) | ||
862 | { | ||
863 | struct sigmatel_spec *spec = codec->spec; | ||
864 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
865 | int i, presence; | ||
866 | |||
867 | if ((res >> 26) != STAC_HP_EVENT) | ||
868 | return; | ||
869 | |||
870 | presence = snd_hda_codec_read(codec, cfg->hp_pin, 0, | ||
871 | AC_VERB_GET_PIN_SENSE, 0x00) >> 31; | ||
872 | |||
873 | if (presence) { | ||
874 | /* disable lineouts, enable hp */ | ||
875 | for (i = 0; i < cfg->line_outs; i++) | ||
876 | stac92xx_reset_pinctl(codec, cfg->line_out_pins[i], | ||
877 | AC_PINCTL_OUT_EN); | ||
878 | stac92xx_set_pinctl(codec, cfg->hp_pin, AC_PINCTL_OUT_EN); | ||
879 | } else { | ||
880 | /* enable lineouts, disable hp */ | ||
881 | for (i = 0; i < cfg->line_outs; i++) | ||
882 | stac92xx_set_pinctl(codec, cfg->line_out_pins[i], | ||
883 | AC_PINCTL_OUT_EN); | ||
884 | stac92xx_reset_pinctl(codec, cfg->hp_pin, AC_PINCTL_OUT_EN); | ||
885 | } | ||
886 | } | ||
887 | |||
831 | #ifdef CONFIG_PM | 888 | #ifdef CONFIG_PM |
832 | static int stac92xx_resume(struct hda_codec *codec) | 889 | static int stac92xx_resume(struct hda_codec *codec) |
833 | { | 890 | { |
@@ -851,6 +908,7 @@ static struct hda_codec_ops stac92xx_patch_ops = { | |||
851 | .build_pcms = stac92xx_build_pcms, | 908 | .build_pcms = stac92xx_build_pcms, |
852 | .init = stac92xx_init, | 909 | .init = stac92xx_init, |
853 | .free = stac92xx_free, | 910 | .free = stac92xx_free, |
911 | .unsol_event = stac92xx_unsol_event, | ||
854 | #ifdef CONFIG_PM | 912 | #ifdef CONFIG_PM |
855 | .resume = stac92xx_resume, | 913 | .resume = stac92xx_resume, |
856 | #endif | 914 | #endif |