diff options
author | Takashi Iwai <tiwai@suse.de> | 2009-07-29 08:23:09 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2009-07-29 08:28:37 -0400 |
commit | 62558ce15759ee93223132258588320967e1e521 (patch) | |
tree | f2c7f7b7fb63105ce56e11934fb712ce76a86c44 /sound/pci/hda/patch_sigmatel.c | |
parent | 50c62f068ee67b5a0178855f502f4ea2ee931eed (diff) |
ALSA: hda - Avoid overwrite of jack events with STAC/IDT
Since only one event can be associated to a (pin) widget, it's safer
to avoid the multiple mapping. This patch fixes the behavior of the
STAC/IDT codec driver.
Now stac_get_event() doesn't take the type argument but simply returns
the first hit element. Then enable_pin_detect() checks the validity
of the type, and returns non-zero only if a valid entry. The caller
can call stac_issue_unsol_event() after checking the return value.
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.c | 59 |
1 files changed, 30 insertions, 29 deletions
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 66b1f3cfc871..307e86ceede1 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -2620,8 +2620,7 @@ static int stac92xx_hp_switch_get(struct snd_kcontrol *kcontrol, | |||
2620 | return 0; | 2620 | return 0; |
2621 | } | 2621 | } |
2622 | 2622 | ||
2623 | static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid, | 2623 | static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid); |
2624 | unsigned char type); | ||
2625 | 2624 | ||
2626 | static int stac92xx_hp_switch_put(struct snd_kcontrol *kcontrol, | 2625 | static int stac92xx_hp_switch_put(struct snd_kcontrol *kcontrol, |
2627 | struct snd_ctl_elem_value *ucontrol) | 2626 | struct snd_ctl_elem_value *ucontrol) |
@@ -2635,7 +2634,7 @@ static int stac92xx_hp_switch_put(struct snd_kcontrol *kcontrol, | |||
2635 | /* check to be sure that the ports are upto date with | 2634 | /* check to be sure that the ports are upto date with |
2636 | * switch changes | 2635 | * switch changes |
2637 | */ | 2636 | */ |
2638 | stac_issue_unsol_event(codec, nid, STAC_HP_EVENT); | 2637 | stac_issue_unsol_event(codec, nid); |
2639 | 2638 | ||
2640 | return 1; | 2639 | return 1; |
2641 | } | 2640 | } |
@@ -2768,7 +2767,7 @@ static int stac92xx_io_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ | |||
2768 | * appropriately according to the pin direction | 2767 | * appropriately according to the pin direction |
2769 | */ | 2768 | */ |
2770 | if (spec->hp_detect) | 2769 | if (spec->hp_detect) |
2771 | stac_issue_unsol_event(codec, nid, STAC_HP_EVENT); | 2770 | stac_issue_unsol_event(codec, nid); |
2772 | 2771 | ||
2773 | return 1; | 2772 | return 1; |
2774 | } | 2773 | } |
@@ -4107,14 +4106,14 @@ static int stac_add_event(struct sigmatel_spec *spec, hda_nid_t nid, | |||
4107 | } | 4106 | } |
4108 | 4107 | ||
4109 | static struct sigmatel_event *stac_get_event(struct hda_codec *codec, | 4108 | static struct sigmatel_event *stac_get_event(struct hda_codec *codec, |
4110 | hda_nid_t nid, unsigned char type) | 4109 | hda_nid_t nid) |
4111 | { | 4110 | { |
4112 | struct sigmatel_spec *spec = codec->spec; | 4111 | struct sigmatel_spec *spec = codec->spec; |
4113 | struct sigmatel_event *event = spec->events.list; | 4112 | struct sigmatel_event *event = spec->events.list; |
4114 | int i; | 4113 | int i; |
4115 | 4114 | ||
4116 | for (i = 0; i < spec->events.used; i++, event++) { | 4115 | for (i = 0; i < spec->events.used; i++, event++) { |
4117 | if (event->nid == nid && event->type == type) | 4116 | if (event->nid == nid) |
4118 | return event; | 4117 | return event; |
4119 | } | 4118 | } |
4120 | return NULL; | 4119 | return NULL; |
@@ -4134,24 +4133,32 @@ static struct sigmatel_event *stac_get_event_from_tag(struct hda_codec *codec, | |||
4134 | return NULL; | 4133 | return NULL; |
4135 | } | 4134 | } |
4136 | 4135 | ||
4137 | static void enable_pin_detect(struct hda_codec *codec, hda_nid_t nid, | 4136 | /* check if given nid is a valid pin and no other events are assigned |
4138 | unsigned int type) | 4137 | * to it. If OK, assign the event, set the unsol flag, and returns 1. |
4138 | * Otherwise, returns zero. | ||
4139 | */ | ||
4140 | static int enable_pin_detect(struct hda_codec *codec, hda_nid_t nid, | ||
4141 | unsigned int type) | ||
4139 | { | 4142 | { |
4140 | struct sigmatel_event *event; | 4143 | struct sigmatel_event *event; |
4141 | int tag; | 4144 | int tag; |
4142 | 4145 | ||
4143 | if (!(get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP)) | 4146 | if (!(get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP)) |
4144 | return; | 4147 | return 0; |
4145 | event = stac_get_event(codec, nid, type); | 4148 | event = stac_get_event(codec, nid); |
4146 | if (event) | 4149 | if (event) { |
4150 | if (event->type != type) | ||
4151 | return 0; | ||
4147 | tag = event->tag; | 4152 | tag = event->tag; |
4148 | else | 4153 | } else { |
4149 | tag = stac_add_event(codec->spec, nid, type, 0); | 4154 | tag = stac_add_event(codec->spec, nid, type, 0); |
4150 | if (tag < 0) | 4155 | if (tag < 0) |
4151 | return; | 4156 | return 0; |
4157 | } | ||
4152 | snd_hda_codec_write_cache(codec, nid, 0, | 4158 | snd_hda_codec_write_cache(codec, nid, 0, |
4153 | AC_VERB_SET_UNSOLICITED_ENABLE, | 4159 | AC_VERB_SET_UNSOLICITED_ENABLE, |
4154 | AC_USRSP_EN | tag); | 4160 | AC_USRSP_EN | tag); |
4161 | return 1; | ||
4155 | } | 4162 | } |
4156 | 4163 | ||
4157 | static int is_nid_hp_pin(struct auto_pin_cfg *cfg, hda_nid_t nid) | 4164 | static int is_nid_hp_pin(struct auto_pin_cfg *cfg, hda_nid_t nid) |
@@ -4250,8 +4257,7 @@ static int stac92xx_init(struct hda_codec *codec) | |||
4250 | stac92xx_auto_set_pinctl(codec, spec->autocfg.line_out_pins[0], | 4257 | stac92xx_auto_set_pinctl(codec, spec->autocfg.line_out_pins[0], |
4251 | AC_PINCTL_OUT_EN); | 4258 | AC_PINCTL_OUT_EN); |
4252 | /* fake event to set up pins */ | 4259 | /* fake event to set up pins */ |
4253 | stac_issue_unsol_event(codec, spec->autocfg.hp_pins[0], | 4260 | stac_issue_unsol_event(codec, spec->autocfg.hp_pins[0]); |
4254 | STAC_HP_EVENT); | ||
4255 | } else { | 4261 | } else { |
4256 | stac92xx_auto_init_multi_out(codec); | 4262 | stac92xx_auto_init_multi_out(codec); |
4257 | stac92xx_auto_init_hp_out(codec); | 4263 | stac92xx_auto_init_hp_out(codec); |
@@ -4284,10 +4290,9 @@ static int stac92xx_init(struct hda_codec *codec) | |||
4284 | } | 4290 | } |
4285 | conf = snd_hda_codec_get_pincfg(codec, nid); | 4291 | conf = snd_hda_codec_get_pincfg(codec, nid); |
4286 | if (get_defcfg_connect(conf) != AC_JACK_PORT_FIXED) { | 4292 | if (get_defcfg_connect(conf) != AC_JACK_PORT_FIXED) { |
4287 | enable_pin_detect(codec, nid, | 4293 | if (enable_pin_detect(codec, nid, |
4288 | STAC_INSERT_EVENT); | 4294 | STAC_INSERT_EVENT)) |
4289 | stac_issue_unsol_event(codec, nid, | 4295 | stac_issue_unsol_event(codec, nid); |
4290 | STAC_INSERT_EVENT); | ||
4291 | } | 4296 | } |
4292 | } | 4297 | } |
4293 | } | 4298 | } |
@@ -4332,10 +4337,8 @@ static int stac92xx_init(struct hda_codec *codec) | |||
4332 | stac_toggle_power_map(codec, nid, 1); | 4337 | stac_toggle_power_map(codec, nid, 1); |
4333 | continue; | 4338 | continue; |
4334 | } | 4339 | } |
4335 | if (!stac_get_event(codec, nid, STAC_INSERT_EVENT)) { | 4340 | if (enable_pin_detect(codec, nid, STAC_PWR_EVENT)) |
4336 | enable_pin_detect(codec, nid, STAC_PWR_EVENT); | 4341 | stac_issue_unsol_event(codec, nid); |
4337 | stac_issue_unsol_event(codec, nid, STAC_PWR_EVENT); | ||
4338 | } | ||
4339 | } | 4342 | } |
4340 | if (spec->dac_list) | 4343 | if (spec->dac_list) |
4341 | stac92xx_power_down(codec); | 4344 | stac92xx_power_down(codec); |
@@ -4598,10 +4601,9 @@ static void stac92xx_report_jack(struct hda_codec *codec, hda_nid_t nid) | |||
4598 | } | 4601 | } |
4599 | } | 4602 | } |
4600 | 4603 | ||
4601 | static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid, | 4604 | static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid) |
4602 | unsigned char type) | ||
4603 | { | 4605 | { |
4604 | struct sigmatel_event *event = stac_get_event(codec, nid, type); | 4606 | struct sigmatel_event *event = stac_get_event(codec, nid); |
4605 | if (!event) | 4607 | if (!event) |
4606 | return; | 4608 | return; |
4607 | codec->patch_ops.unsol_event(codec, (unsigned)event->tag << 26); | 4609 | codec->patch_ops.unsol_event(codec, (unsigned)event->tag << 26); |
@@ -4712,8 +4714,7 @@ static int stac92xx_resume(struct hda_codec *codec) | |||
4712 | snd_hda_codec_resume_cache(codec); | 4714 | snd_hda_codec_resume_cache(codec); |
4713 | /* fake event to set up pins again to override cached values */ | 4715 | /* fake event to set up pins again to override cached values */ |
4714 | if (spec->hp_detect) | 4716 | if (spec->hp_detect) |
4715 | stac_issue_unsol_event(codec, spec->autocfg.hp_pins[0], | 4717 | stac_issue_unsol_event(codec, spec->autocfg.hp_pins[0]); |
4716 | STAC_HP_EVENT); | ||
4717 | return 0; | 4718 | return 0; |
4718 | } | 4719 | } |
4719 | 4720 | ||