[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>

authored by Matt and committed by Jaroslav Kysela 4e55096e 41e2fce4

+63 -2
+3
sound/pci/hda/hda_codec.h
··· 262 #define AC_PINCTL_OUT_EN (1<<6) 263 #define AC_PINCTL_HP_EN (1<<7) 264 265 /* configuration default - 32bit */ 266 #define AC_DEFCFG_SEQUENCE (0xf<<0) 267 #define AC_DEFCFG_DEF_ASSOC (0xf<<4)
··· 262 #define AC_PINCTL_OUT_EN (1<<6) 263 #define AC_PINCTL_HP_EN (1<<7) 264 265 + /* Unsolicited response - 8bit */ 266 + #define AC_USRSP_EN (1<<7) 267 + 268 /* configuration default - 32bit */ 269 #define AC_DEFCFG_SEQUENCE (0xf<<0) 270 #define AC_DEFCFG_DEF_ASSOC (0xf<<4)
+60 -2
sound/pci/hda/patch_sigmatel.c
··· 36 37 #undef STAC_TEST 38 39 struct sigmatel_spec { 40 snd_kcontrol_new_t *mixers[4]; 41 unsigned int num_mixers; ··· 511 return 0; 512 } 513 514 - #define NUM_CONTROL_ALLOC 32 515 - 516 enum { 517 STAC_CTL_WIDGET_VOL, 518 STAC_CTL_WIDGET_MUTE, ··· 619 hda_nid_t pin = cfg->hp_pin; 620 hda_nid_t nid; 621 int i, err; 622 623 if (! pin) 624 return 0; 625 626 nid = snd_hda_codec_read(codec, pin, 0, AC_VERB_GET_CONNECT_LIST, 0) & 0xff; 627 for (i = 0; i < cfg->line_outs; i++) { ··· 838 kfree(spec); 839 } 840 841 #ifdef CONFIG_PM 842 static int stac92xx_resume(struct hda_codec *codec) 843 { ··· 908 .build_pcms = stac92xx_build_pcms, 909 .init = stac92xx_init, 910 .free = stac92xx_free, 911 #ifdef CONFIG_PM 912 .resume = stac92xx_resume, 913 #endif
··· 36 37 #undef STAC_TEST 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 + 43 struct sigmatel_spec { 44 snd_kcontrol_new_t *mixers[4]; 45 unsigned int num_mixers; ··· 507 return 0; 508 } 509 510 enum { 511 STAC_CTL_WIDGET_VOL, 512 STAC_CTL_WIDGET_MUTE, ··· 617 hda_nid_t pin = cfg->hp_pin; 618 hda_nid_t nid; 619 int i, err; 620 + unsigned int wid_caps; 621 622 if (! pin) 623 return 0; 624 + 625 + wid_caps = snd_hda_param_read(codec, pin, AC_PAR_AUDIO_WIDGET_CAP); 626 + if (wid_caps & AC_WCAP_UNSOL_CAP) 627 + /* Enable unsolicited responses on the HP widget */ 628 + snd_hda_codec_write(codec, pin, 0, 629 + AC_VERB_SET_UNSOLICITED_ENABLE, 630 + STAC_UNSOL_ENABLE); 631 632 nid = snd_hda_codec_read(codec, pin, 0, AC_VERB_GET_CONNECT_LIST, 0) & 0xff; 633 for (i = 0; i < cfg->line_outs; i++) { ··· 828 kfree(spec); 829 } 830 831 + static void stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid, 832 + unsigned int flag) 833 + { 834 + unsigned int pin_ctl = snd_hda_codec_read(codec, nid, 835 + 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00); 836 + snd_hda_codec_write(codec, nid, 0, 837 + AC_VERB_SET_PIN_WIDGET_CONTROL, 838 + pin_ctl | flag); 839 + } 840 + 841 + static void stac92xx_reset_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_unsol_event(struct hda_codec *codec, unsigned int res) 852 + { 853 + struct sigmatel_spec *spec = codec->spec; 854 + struct auto_pin_cfg *cfg = &spec->autocfg; 855 + int i, presence; 856 + 857 + if ((res >> 26) != STAC_HP_EVENT) 858 + return; 859 + 860 + presence = snd_hda_codec_read(codec, cfg->hp_pin, 0, 861 + AC_VERB_GET_PIN_SENSE, 0x00) >> 31; 862 + 863 + if (presence) { 864 + /* disable lineouts, enable hp */ 865 + for (i = 0; i < cfg->line_outs; i++) 866 + stac92xx_reset_pinctl(codec, cfg->line_out_pins[i], 867 + AC_PINCTL_OUT_EN); 868 + stac92xx_set_pinctl(codec, cfg->hp_pin, AC_PINCTL_OUT_EN); 869 + } else { 870 + /* enable lineouts, disable hp */ 871 + for (i = 0; i < cfg->line_outs; i++) 872 + stac92xx_set_pinctl(codec, cfg->line_out_pins[i], 873 + AC_PINCTL_OUT_EN); 874 + stac92xx_reset_pinctl(codec, cfg->hp_pin, AC_PINCTL_OUT_EN); 875 + } 876 + } 877 + 878 #ifdef CONFIG_PM 879 static int stac92xx_resume(struct hda_codec *codec) 880 { ··· 851 .build_pcms = stac92xx_build_pcms, 852 .init = stac92xx_init, 853 .free = stac92xx_free, 854 + .unsol_event = stac92xx_unsol_event, 855 #ifdef CONFIG_PM 856 .resume = stac92xx_resume, 857 #endif