aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_sigmatel.c
diff options
context:
space:
mode:
authorMatt <matt@embeddedalley.com>2005-07-04 11:51:39 -0400
committerJaroslav Kysela <perex@suse.cz>2005-07-28 06:21:52 -0400
commit4e55096e27d745908e44c6abd2cc0c5b615854a4 (patch)
treecd0aae0c7084de3d9e7696d3c7514cb3ae552df2 /sound/pci/hda/patch_sigmatel.c
parent41e2fce431070cb2d91391808077378582d3e6b1 (diff)
[ALSA] hda: add sigmatel hp detect support
HDA Codec driver Adds support for detecting hp insertion/removal and enable/disable of lineouts based on unsolicited events. Signed-off-by: Matt <matt@embeddedalley.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/patch_sigmatel.c')
-rw-r--r--sound/pci/hda/patch_sigmatel.c62
1 files changed, 60 insertions, 2 deletions
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 07d06f7c439..9d503da7320 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
39struct sigmatel_spec { 43struct 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
512enum { 514enum {
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
841static 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
851static 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
861static 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
832static int stac92xx_resume(struct hda_codec *codec) 889static 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