aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/pci/hda/patch_sigmatel.c159
1 files changed, 101 insertions, 58 deletions
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 09b3f4b1db4d..4b7dda57c0e9 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -36,10 +36,12 @@
36#include "hda_patch.h" 36#include "hda_patch.h"
37#include "hda_beep.h" 37#include "hda_beep.h"
38 38
39#define STAC_VREF_EVENT 0x00 39enum {
40#define STAC_INSERT_EVENT 0x10 40 STAC_VREF_EVENT = 1,
41#define STAC_PWR_EVENT 0x20 41 STAC_INSERT_EVENT,
42#define STAC_HP_EVENT 0x30 42 STAC_PWR_EVENT,
43 STAC_HP_EVENT,
44};
43 45
44enum { 46enum {
45 STAC_REF, 47 STAC_REF,
@@ -134,6 +136,8 @@ enum {
134 136
135struct sigmatel_event { 137struct sigmatel_event {
136 hda_nid_t nid; 138 hda_nid_t nid;
139 unsigned char type;
140 unsigned char tag;
137 int data; 141 int data;
138}; 142};
139 143
@@ -2549,6 +2553,9 @@ static int stac92xx_hp_switch_get(struct snd_kcontrol *kcontrol,
2549 return 0; 2553 return 0;
2550} 2554}
2551 2555
2556static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid,
2557 unsigned char type);
2558
2552static int stac92xx_hp_switch_put(struct snd_kcontrol *kcontrol, 2559static int stac92xx_hp_switch_put(struct snd_kcontrol *kcontrol,
2553 struct snd_ctl_elem_value *ucontrol) 2560 struct snd_ctl_elem_value *ucontrol)
2554{ 2561{
@@ -2561,7 +2568,7 @@ static int stac92xx_hp_switch_put(struct snd_kcontrol *kcontrol,
2561 /* check to be sure that the ports are upto date with 2568 /* check to be sure that the ports are upto date with
2562 * switch changes 2569 * switch changes
2563 */ 2570 */
2564 codec->patch_ops.unsol_event(codec, (STAC_HP_EVENT | nid) << 26); 2571 stac_issue_unsol_event(codec, nid, STAC_HP_EVENT);
2565 2572
2566 return 1; 2573 return 1;
2567} 2574}
@@ -2601,8 +2608,7 @@ static int stac92xx_io_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_
2601 * appropriately according to the pin direction 2608 * appropriately according to the pin direction
2602 */ 2609 */
2603 if (spec->hp_detect) 2610 if (spec->hp_detect)
2604 codec->patch_ops.unsol_event(codec, 2611 stac_issue_unsol_event(codec, nid, STAC_HP_EVENT);
2605 (STAC_HP_EVENT | nid) << 26);
2606 2612
2607 return 1; 2613 return 1;
2608} 2614}
@@ -3768,8 +3774,8 @@ static int stac92xx_add_jack(struct hda_codec *codec,
3768#endif 3774#endif
3769} 3775}
3770 3776
3771static int stac92xx_add_event(struct sigmatel_spec *spec, hda_nid_t nid, 3777static int stac_add_event(struct sigmatel_spec *spec, hda_nid_t nid,
3772 int data) 3778 unsigned char type, int data)
3773{ 3779{
3774 struct sigmatel_event *event; 3780 struct sigmatel_event *event;
3775 3781
@@ -3778,32 +3784,59 @@ static int stac92xx_add_event(struct sigmatel_spec *spec, hda_nid_t nid,
3778 if (!event) 3784 if (!event)
3779 return -ENOMEM; 3785 return -ENOMEM;
3780 event->nid = nid; 3786 event->nid = nid;
3787 event->type = type;
3788 event->tag = spec->events.used;
3781 event->data = data; 3789 event->data = data;
3782 3790
3783 return 0; 3791 return event->tag;
3784} 3792}
3785 3793
3786static int stac92xx_event_data(struct hda_codec *codec, hda_nid_t nid) 3794static struct sigmatel_event *stac_get_event(struct hda_codec *codec,
3795 hda_nid_t nid, unsigned char type)
3787{ 3796{
3788 struct sigmatel_spec *spec = codec->spec; 3797 struct sigmatel_spec *spec = codec->spec;
3789 struct sigmatel_event *events = spec->events.list; 3798 struct sigmatel_event *event = spec->events.list;
3790 if (events) { 3799 int i;
3791 int i; 3800
3792 for (i = 0; i < spec->events.used; i++) 3801 for (i = 0; i < spec->events.used; i++, event++) {
3793 if (events[i].nid == nid) 3802 if (event->nid == nid && event->type == type)
3794 return events[i].data; 3803 return event;
3795 } 3804 }
3796 return 0; 3805 return NULL;
3797} 3806}
3798 3807
3799static void enable_pin_detect(struct hda_codec *codec, hda_nid_t nid, 3808static struct sigmatel_event *stac_get_event_from_tag(struct hda_codec *codec,
3800 unsigned int event) 3809 unsigned char tag)
3801{ 3810{
3802 if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) { 3811 struct sigmatel_spec *spec = codec->spec;
3803 snd_hda_codec_write_cache(codec, nid, 0, 3812 struct sigmatel_event *event = spec->events.list;
3804 AC_VERB_SET_UNSOLICITED_ENABLE, 3813 int i;
3805 (AC_USRSP_EN | event | nid)); 3814
3815 for (i = 0; i < spec->events.used; i++, event++) {
3816 if (event->tag == tag)
3817 return event;
3806 } 3818 }
3819 return NULL;
3820}
3821
3822static void enable_pin_detect(struct hda_codec *codec, hda_nid_t nid,
3823 unsigned int type)
3824{
3825 struct sigmatel_event *event;
3826 int tag;
3827
3828 if (!(get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP))
3829 return;
3830 event = stac_get_event(codec, nid, type);
3831 if (event)
3832 tag = event->tag;
3833 else
3834 tag = stac_add_event(codec->spec, nid, type, 0);
3835 if (tag < 0)
3836 return;
3837 snd_hda_codec_write_cache(codec, nid, 0,
3838 AC_VERB_SET_UNSOLICITED_ENABLE,
3839 AC_USRSP_EN | tag);
3807} 3840}
3808 3841
3809static int is_nid_hp_pin(struct auto_pin_cfg *cfg, hda_nid_t nid) 3842static int is_nid_hp_pin(struct auto_pin_cfg *cfg, hda_nid_t nid)
@@ -3862,7 +3895,7 @@ static int stac92xx_init(struct hda_codec *codec)
3862 /* Enable unsolicited responses on the HP widget */ 3895 /* Enable unsolicited responses on the HP widget */
3863 for (i = 0; i < cfg->hp_outs; i++) { 3896 for (i = 0; i < cfg->hp_outs; i++) {
3864 hda_nid_t nid = cfg->hp_pins[i]; 3897 hda_nid_t nid = cfg->hp_pins[i];
3865 enable_pin_detect(codec, nid, STAC_HP_EVENT | nid); 3898 enable_pin_detect(codec, nid, STAC_HP_EVENT);
3866 } 3899 }
3867 /* force to enable the first line-out; the others are set up 3900 /* force to enable the first line-out; the others are set up
3868 * in unsol_event 3901 * in unsol_event
@@ -3870,8 +3903,8 @@ static int stac92xx_init(struct hda_codec *codec)
3870 stac92xx_auto_set_pinctl(codec, spec->autocfg.line_out_pins[0], 3903 stac92xx_auto_set_pinctl(codec, spec->autocfg.line_out_pins[0],
3871 AC_PINCTL_OUT_EN); 3904 AC_PINCTL_OUT_EN);
3872 /* fake event to set up pins */ 3905 /* fake event to set up pins */
3873 codec->patch_ops.unsol_event(codec, 3906 stac_issue_unsol_event(codec, spec->autocfg.hp_pins[0],
3874 (STAC_HP_EVENT | spec->autocfg.hp_pins[0]) << 26); 3907 STAC_HP_EVENT);
3875 } else { 3908 } else {
3876 stac92xx_auto_init_multi_out(codec); 3909 stac92xx_auto_init_multi_out(codec);
3877 stac92xx_auto_init_hp_out(codec); 3910 stac92xx_auto_init_hp_out(codec);
@@ -3892,7 +3925,7 @@ static int stac92xx_init(struct hda_codec *codec)
3892 } 3925 }
3893 pinctl |= AC_PINCTL_IN_EN; 3926 pinctl |= AC_PINCTL_IN_EN;
3894 stac92xx_auto_set_pinctl(codec, nid, pinctl); 3927 stac92xx_auto_set_pinctl(codec, nid, pinctl);
3895 enable_pin_detect(codec, nid, STAC_INSERT_EVENT | nid); 3928 enable_pin_detect(codec, nid, STAC_INSERT_EVENT);
3896 } 3929 }
3897 } 3930 }
3898 for (i = 0; i < spec->num_dmics; i++) 3931 for (i = 0; i < spec->num_dmics; i++)
@@ -3907,7 +3940,6 @@ static int stac92xx_init(struct hda_codec *codec)
3907 for (i = 0; i < spec->num_pwrs; i++) { 3940 for (i = 0; i < spec->num_pwrs; i++) {
3908 hda_nid_t nid = spec->pwr_nids[i]; 3941 hda_nid_t nid = spec->pwr_nids[i];
3909 int pinctl, def_conf; 3942 int pinctl, def_conf;
3910 int event = STAC_PWR_EVENT;
3911 3943
3912 if (is_nid_hp_pin(cfg, nid) && spec->hp_detect) 3944 if (is_nid_hp_pin(cfg, nid) && spec->hp_detect)
3913 continue; /* already has an unsol event */ 3945 continue; /* already has an unsol event */
@@ -3930,8 +3962,8 @@ static int stac92xx_init(struct hda_codec *codec)
3930 stac_toggle_power_map(codec, nid, 1); 3962 stac_toggle_power_map(codec, nid, 1);
3931 continue; 3963 continue;
3932 } 3964 }
3933 enable_pin_detect(codec, spec->pwr_nids[i], event | i); 3965 enable_pin_detect(codec, nid, STAC_PWR_EVENT);
3934 codec->patch_ops.unsol_event(codec, (event | i) << 26); 3966 stac_issue_unsol_event(codec, nid, STAC_PWR_EVENT);
3935 } 3967 }
3936 if (spec->dac_list) 3968 if (spec->dac_list)
3937 stac92xx_power_down(codec); 3969 stac92xx_power_down(codec);
@@ -4059,7 +4091,7 @@ static int no_hp_sensing(struct sigmatel_spec *spec, int i)
4059 return 0; 4091 return 0;
4060} 4092}
4061 4093
4062static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res) 4094static void stac92xx_hp_detect(struct hda_codec *codec)
4063{ 4095{
4064 struct sigmatel_spec *spec = codec->spec; 4096 struct sigmatel_spec *spec = codec->spec;
4065 struct auto_pin_cfg *cfg = &spec->autocfg; 4097 struct auto_pin_cfg *cfg = &spec->autocfg;
@@ -4182,33 +4214,43 @@ static void stac92xx_report_jack(struct hda_codec *codec, hda_nid_t nid)
4182 } 4214 }
4183} 4215}
4184 4216
4217static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid,
4218 unsigned char type)
4219{
4220 struct sigmatel_event *event = stac_get_event(codec, nid, type);
4221 if (!event)
4222 return;
4223 codec->patch_ops.unsol_event(codec, (unsigned)event->tag << 26);
4224}
4225
4185static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) 4226static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res)
4186{ 4227{
4187 struct sigmatel_spec *spec = codec->spec; 4228 struct sigmatel_spec *spec = codec->spec;
4188 int event = (res >> 26) & 0x70; 4229 struct sigmatel_event *event;
4189 int nid = res >> 26 & 0x0f; 4230 int tag, data;
4190 4231
4191 switch (event) { 4232 tag = (res >> 26) & 0x7f;
4233 event = stac_get_event_from_tag(codec, tag);
4234 if (!event)
4235 return;
4236
4237 switch (event->type) {
4192 case STAC_HP_EVENT: 4238 case STAC_HP_EVENT:
4193 stac92xx_hp_detect(codec, res); 4239 stac92xx_hp_detect(codec);
4194 /* fallthru */ 4240 /* fallthru */
4195 case STAC_INSERT_EVENT: 4241 case STAC_INSERT_EVENT:
4196 case STAC_PWR_EVENT: 4242 case STAC_PWR_EVENT:
4197 if (nid) { 4243 if (spec->num_pwrs > 0)
4198 if (spec->num_pwrs > 0) 4244 stac92xx_pin_sense(codec, event->nid);
4199 stac92xx_pin_sense(codec, nid); 4245 stac92xx_report_jack(codec, event->nid);
4200 stac92xx_report_jack(codec, nid);
4201 }
4202 break; 4246 break;
4203 case STAC_VREF_EVENT: { 4247 case STAC_VREF_EVENT:
4204 int data = snd_hda_codec_read(codec, codec->afg, 0, 4248 data = snd_hda_codec_read(codec, codec->afg, 0,
4205 AC_VERB_GET_GPIO_DATA, 0); 4249 AC_VERB_GET_GPIO_DATA, 0);
4206 int idx = stac92xx_event_data(codec, nid);
4207 /* toggle VREF state based on GPIOx status */ 4250 /* toggle VREF state based on GPIOx status */
4208 snd_hda_codec_write(codec, codec->afg, 0, 0x7e0, 4251 snd_hda_codec_write(codec, codec->afg, 0, 0x7e0,
4209 !!(data & (1 << idx))); 4252 !!(data & (1 << event->data)));
4210 break; 4253 break;
4211 }
4212 } 4254 }
4213} 4255}
4214 4256
@@ -4223,8 +4265,8 @@ static int stac92xx_resume(struct hda_codec *codec)
4223 snd_hda_codec_resume_cache(codec); 4265 snd_hda_codec_resume_cache(codec);
4224 /* fake event to set up pins again to override cached values */ 4266 /* fake event to set up pins again to override cached values */
4225 if (spec->hp_detect) 4267 if (spec->hp_detect)
4226 codec->patch_ops.unsol_event(codec, 4268 stac_issue_unsol_event(codec, spec->autocfg.hp_pins[0],
4227 (STAC_HP_EVENT | spec->autocfg.hp_pins[0]) << 26); 4269 STAC_HP_EVENT);
4228 return 0; 4270 return 0;
4229} 4271}
4230 4272
@@ -4732,14 +4774,15 @@ again:
4732 switch (spec->board_config) { 4774 switch (spec->board_config) {
4733 case STAC_HP_M4: 4775 case STAC_HP_M4:
4734 /* Enable VREF power saving on GPIO1 detect */ 4776 /* Enable VREF power saving on GPIO1 detect */
4777 err = stac_add_event(spec, codec->afg,
4778 STAC_VREF_EVENT, 0x02);
4779 if (err < 0)
4780 return err;
4735 snd_hda_codec_write_cache(codec, codec->afg, 0, 4781 snd_hda_codec_write_cache(codec, codec->afg, 0,
4736 AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x02); 4782 AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x02);
4737 snd_hda_codec_write_cache(codec, codec->afg, 0, 4783 snd_hda_codec_write_cache(codec, codec->afg, 0,
4738 AC_VERB_SET_UNSOLICITED_ENABLE, 4784 AC_VERB_SET_UNSOLICITED_ENABLE,
4739 (AC_USRSP_EN | STAC_VREF_EVENT | codec->afg)); 4785 AC_USRSP_EN | err);
4740 err = stac92xx_add_event(spec, codec->afg, 0x02);
4741 if (err < 0)
4742 return err;
4743 spec->gpio_mask |= 0x02; 4786 spec->gpio_mask |= 0x02;
4744 break; 4787 break;
4745 } 4788 }
@@ -5131,14 +5174,14 @@ static int patch_stac9205(struct hda_codec *codec)
5131 stac_change_pin_config(codec, 0x20, 0x1c410030); 5174 stac_change_pin_config(codec, 0x20, 0x1c410030);
5132 5175
5133 /* Enable unsol response for GPIO4/Dock HP connection */ 5176 /* Enable unsol response for GPIO4/Dock HP connection */
5177 err = stac_add_event(spec, codec->afg, STAC_VREF_EVENT, 0x01);
5178 if (err < 0)
5179 return err;
5134 snd_hda_codec_write_cache(codec, codec->afg, 0, 5180 snd_hda_codec_write_cache(codec, codec->afg, 0,
5135 AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x10); 5181 AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x10);
5136 snd_hda_codec_write_cache(codec, codec->afg, 0, 5182 snd_hda_codec_write_cache(codec, codec->afg, 0,
5137 AC_VERB_SET_UNSOLICITED_ENABLE, 5183 AC_VERB_SET_UNSOLICITED_ENABLE,
5138 (AC_USRSP_EN | STAC_VREF_EVENT | codec->afg)); 5184 AC_USRSP_EN | err);
5139 err = stac92xx_add_event(spec, codec->afg, 0x01);
5140 if (err < 0)
5141 return err;
5142 5185
5143 spec->gpio_dir = 0x0b; 5186 spec->gpio_dir = 0x0b;
5144 spec->eapd_mask = 0x01; 5187 spec->eapd_mask = 0x01;