diff options
author | Takashi Iwai <tiwai@suse.de> | 2011-12-20 09:42:57 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2011-12-20 09:42:57 -0500 |
commit | 78c058df6a120044455b5635daefdc515bf9d899 (patch) | |
tree | d349e70e384404a9a2d9860feb0219e9f8acb212 /sound/pci/hda/patch_sigmatel.c | |
parent | db9c6f842fa957b41984cd8ceea1f07c53fb3fbf (diff) | |
parent | 31ef22579302ac42054bebecb528710f46580925 (diff) |
Merge branch 'test/hda-jack' into topic/hda
Conflicts:
sound/pci/hda/patch_hdmi.c
sound/pci/hda/patch_via.c
Diffstat (limited to 'sound/pci/hda/patch_sigmatel.c')
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 196 |
1 files changed, 57 insertions, 139 deletions
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index aaed004eacc5..03145aec65f1 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include "hda_codec.h" | 37 | #include "hda_codec.h" |
38 | #include "hda_local.h" | 38 | #include "hda_local.h" |
39 | #include "hda_beep.h" | 39 | #include "hda_beep.h" |
40 | #include "hda_jack.h" | ||
40 | 41 | ||
41 | enum { | 42 | enum { |
42 | STAC_VREF_EVENT = 1, | 43 | STAC_VREF_EVENT = 1, |
@@ -175,13 +176,6 @@ enum { | |||
175 | STAC_9872_MODELS | 176 | STAC_9872_MODELS |
176 | }; | 177 | }; |
177 | 178 | ||
178 | struct sigmatel_event { | ||
179 | hda_nid_t nid; | ||
180 | unsigned char type; | ||
181 | unsigned char tag; | ||
182 | int data; | ||
183 | }; | ||
184 | |||
185 | struct sigmatel_mic_route { | 179 | struct sigmatel_mic_route { |
186 | hda_nid_t pin; | 180 | hda_nid_t pin; |
187 | signed char mux_idx; | 181 | signed char mux_idx; |
@@ -230,9 +224,6 @@ struct sigmatel_spec { | |||
230 | const hda_nid_t *pwr_nids; | 224 | const hda_nid_t *pwr_nids; |
231 | const hda_nid_t *dac_list; | 225 | const hda_nid_t *dac_list; |
232 | 226 | ||
233 | /* events */ | ||
234 | struct snd_array events; | ||
235 | |||
236 | /* playback */ | 227 | /* playback */ |
237 | struct hda_input_mux *mono_mux; | 228 | struct hda_input_mux *mono_mux; |
238 | unsigned int cur_mmux; | 229 | unsigned int cur_mmux; |
@@ -1093,13 +1084,10 @@ static const char * const slave_sws[] = { | |||
1093 | }; | 1084 | }; |
1094 | 1085 | ||
1095 | static void stac92xx_free_kctls(struct hda_codec *codec); | 1086 | static void stac92xx_free_kctls(struct hda_codec *codec); |
1096 | static int stac92xx_add_jack(struct hda_codec *codec, hda_nid_t nid, int type); | ||
1097 | 1087 | ||
1098 | static int stac92xx_build_controls(struct hda_codec *codec) | 1088 | static int stac92xx_build_controls(struct hda_codec *codec) |
1099 | { | 1089 | { |
1100 | struct sigmatel_spec *spec = codec->spec; | 1090 | struct sigmatel_spec *spec = codec->spec; |
1101 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
1102 | hda_nid_t nid; | ||
1103 | int err; | 1091 | int err; |
1104 | int i; | 1092 | int i; |
1105 | 1093 | ||
@@ -1185,31 +1173,9 @@ static int stac92xx_build_controls(struct hda_codec *codec) | |||
1185 | 1173 | ||
1186 | stac92xx_free_kctls(codec); /* no longer needed */ | 1174 | stac92xx_free_kctls(codec); /* no longer needed */ |
1187 | 1175 | ||
1188 | /* create jack input elements */ | 1176 | err = snd_hda_jack_add_kctls(codec, &spec->autocfg); |
1189 | if (spec->hp_detect) { | 1177 | if (err < 0) |
1190 | for (i = 0; i < cfg->hp_outs; i++) { | 1178 | return err; |
1191 | int type = SND_JACK_HEADPHONE; | ||
1192 | nid = cfg->hp_pins[i]; | ||
1193 | /* jack detection */ | ||
1194 | if (cfg->hp_outs == i) | ||
1195 | type |= SND_JACK_LINEOUT; | ||
1196 | err = stac92xx_add_jack(codec, nid, type); | ||
1197 | if (err < 0) | ||
1198 | return err; | ||
1199 | } | ||
1200 | } | ||
1201 | for (i = 0; i < cfg->line_outs; i++) { | ||
1202 | err = stac92xx_add_jack(codec, cfg->line_out_pins[i], | ||
1203 | SND_JACK_LINEOUT); | ||
1204 | if (err < 0) | ||
1205 | return err; | ||
1206 | } | ||
1207 | for (i = 0; i < cfg->num_inputs; i++) { | ||
1208 | nid = cfg->inputs[i].pin; | ||
1209 | err = stac92xx_add_jack(codec, nid, SND_JACK_MICROPHONE); | ||
1210 | if (err < 0) | ||
1211 | return err; | ||
1212 | } | ||
1213 | 1179 | ||
1214 | return 0; | 1180 | return 0; |
1215 | } | 1181 | } |
@@ -2871,7 +2837,8 @@ static inline int stac92xx_add_jack_mode_control(struct hda_codec *codec, | |||
2871 | } | 2837 | } |
2872 | 2838 | ||
2873 | if (control) { | 2839 | if (control) { |
2874 | strcpy(name, hda_get_input_pin_label(codec, nid, 1)); | 2840 | snd_hda_get_pin_label(codec, nid, &spec->autocfg, |
2841 | name, sizeof(name), NULL); | ||
2875 | return stac92xx_add_control(codec->spec, control, | 2842 | return stac92xx_add_control(codec->spec, control, |
2876 | strcat(name, " Jack Mode"), nid); | 2843 | strcat(name, " Jack Mode"), nid); |
2877 | } | 2844 | } |
@@ -3549,7 +3516,7 @@ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec, | |||
3549 | for (i = 0; i < spec->num_dmics; i++) { | 3516 | for (i = 0; i < spec->num_dmics; i++) { |
3550 | hda_nid_t nid; | 3517 | hda_nid_t nid; |
3551 | int index, type_idx; | 3518 | int index, type_idx; |
3552 | const char *label; | 3519 | char label[32]; |
3553 | 3520 | ||
3554 | nid = spec->dmic_nids[i]; | 3521 | nid = spec->dmic_nids[i]; |
3555 | if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN) | 3522 | if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN) |
@@ -3562,7 +3529,8 @@ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec, | |||
3562 | if (index < 0) | 3529 | if (index < 0) |
3563 | continue; | 3530 | continue; |
3564 | 3531 | ||
3565 | label = hda_get_input_pin_label(codec, nid, 1); | 3532 | snd_hda_get_pin_label(codec, nid, &spec->autocfg, |
3533 | label, sizeof(label), NULL); | ||
3566 | snd_hda_add_imux_item(dimux, label, index, &type_idx); | 3534 | snd_hda_add_imux_item(dimux, label, index, &type_idx); |
3567 | if (snd_hda_get_bool_hint(codec, "separate_dmux") != 1) | 3535 | if (snd_hda_get_bool_hint(codec, "separate_dmux") != 1) |
3568 | snd_hda_add_imux_item(imux, label, index, &type_idx); | 3536 | snd_hda_add_imux_item(imux, label, index, &type_idx); |
@@ -4160,65 +4128,18 @@ static void stac_gpio_set(struct hda_codec *codec, unsigned int mask, | |||
4160 | AC_VERB_SET_GPIO_DATA, gpiostate); /* sync */ | 4128 | AC_VERB_SET_GPIO_DATA, gpiostate); /* sync */ |
4161 | } | 4129 | } |
4162 | 4130 | ||
4163 | static int stac92xx_add_jack(struct hda_codec *codec, | 4131 | static int stac_add_event(struct hda_codec *codec, hda_nid_t nid, |
4164 | hda_nid_t nid, int type) | ||
4165 | { | ||
4166 | #ifdef CONFIG_SND_HDA_INPUT_JACK | ||
4167 | int def_conf = snd_hda_codec_get_pincfg(codec, nid); | ||
4168 | int connectivity = get_defcfg_connect(def_conf); | ||
4169 | |||
4170 | if (connectivity && connectivity != AC_JACK_PORT_FIXED) | ||
4171 | return 0; | ||
4172 | |||
4173 | return snd_hda_input_jack_add(codec, nid, type, NULL); | ||
4174 | #else | ||
4175 | return 0; | ||
4176 | #endif /* CONFIG_SND_HDA_INPUT_JACK */ | ||
4177 | } | ||
4178 | |||
4179 | static int stac_add_event(struct sigmatel_spec *spec, hda_nid_t nid, | ||
4180 | unsigned char type, int data) | 4132 | unsigned char type, int data) |
4181 | { | 4133 | { |
4182 | struct sigmatel_event *event; | 4134 | struct hda_jack_tbl *event; |
4183 | 4135 | ||
4184 | snd_array_init(&spec->events, sizeof(*event), 32); | 4136 | event = snd_hda_jack_tbl_new(codec, nid); |
4185 | event = snd_array_new(&spec->events); | ||
4186 | if (!event) | 4137 | if (!event) |
4187 | return -ENOMEM; | 4138 | return -ENOMEM; |
4188 | event->nid = nid; | 4139 | event->action = type; |
4189 | event->type = type; | 4140 | event->private_data = data; |
4190 | event->tag = spec->events.used; | ||
4191 | event->data = data; | ||
4192 | |||
4193 | return event->tag; | ||
4194 | } | ||
4195 | |||
4196 | static struct sigmatel_event *stac_get_event(struct hda_codec *codec, | ||
4197 | hda_nid_t nid) | ||
4198 | { | ||
4199 | struct sigmatel_spec *spec = codec->spec; | ||
4200 | struct sigmatel_event *event = spec->events.list; | ||
4201 | int i; | ||
4202 | |||
4203 | for (i = 0; i < spec->events.used; i++, event++) { | ||
4204 | if (event->nid == nid) | ||
4205 | return event; | ||
4206 | } | ||
4207 | return NULL; | ||
4208 | } | ||
4209 | |||
4210 | static struct sigmatel_event *stac_get_event_from_tag(struct hda_codec *codec, | ||
4211 | unsigned char tag) | ||
4212 | { | ||
4213 | struct sigmatel_spec *spec = codec->spec; | ||
4214 | struct sigmatel_event *event = spec->events.list; | ||
4215 | int i; | ||
4216 | 4141 | ||
4217 | for (i = 0; i < spec->events.used; i++, event++) { | 4142 | return 0; |
4218 | if (event->tag == tag) | ||
4219 | return event; | ||
4220 | } | ||
4221 | return NULL; | ||
4222 | } | 4143 | } |
4223 | 4144 | ||
4224 | /* check if given nid is a valid pin and no other events are assigned | 4145 | /* check if given nid is a valid pin and no other events are assigned |
@@ -4228,24 +4149,17 @@ static struct sigmatel_event *stac_get_event_from_tag(struct hda_codec *codec, | |||
4228 | static int enable_pin_detect(struct hda_codec *codec, hda_nid_t nid, | 4149 | static int enable_pin_detect(struct hda_codec *codec, hda_nid_t nid, |
4229 | unsigned int type) | 4150 | unsigned int type) |
4230 | { | 4151 | { |
4231 | struct sigmatel_event *event; | 4152 | struct hda_jack_tbl *event; |
4232 | int tag; | ||
4233 | 4153 | ||
4234 | if (!is_jack_detectable(codec, nid)) | 4154 | if (!is_jack_detectable(codec, nid)) |
4235 | return 0; | 4155 | return 0; |
4236 | event = stac_get_event(codec, nid); | 4156 | event = snd_hda_jack_tbl_new(codec, nid); |
4237 | if (event) { | 4157 | if (!event) |
4238 | if (event->type != type) | 4158 | return -ENOMEM; |
4239 | return 0; | 4159 | if (event->action && event->action != type) |
4240 | tag = event->tag; | 4160 | return 0; |
4241 | } else { | 4161 | event->action = type; |
4242 | tag = stac_add_event(codec->spec, nid, type, 0); | 4162 | snd_hda_jack_detect_enable(codec, nid, 0); |
4243 | if (tag < 0) | ||
4244 | return 0; | ||
4245 | } | ||
4246 | snd_hda_codec_write_cache(codec, nid, 0, | ||
4247 | AC_VERB_SET_UNSOLICITED_ENABLE, | ||
4248 | AC_USRSP_EN | tag); | ||
4249 | return 1; | 4163 | return 1; |
4250 | } | 4164 | } |
4251 | 4165 | ||
@@ -4473,6 +4387,8 @@ static int stac92xx_init(struct hda_codec *codec) | |||
4473 | stac_toggle_power_map(codec, nid, 0); | 4387 | stac_toggle_power_map(codec, nid, 0); |
4474 | } | 4388 | } |
4475 | 4389 | ||
4390 | snd_hda_jack_report_sync(codec); | ||
4391 | |||
4476 | /* sync mute LED */ | 4392 | /* sync mute LED */ |
4477 | if (spec->gpio_led) | 4393 | if (spec->gpio_led) |
4478 | hda_call_check_power_status(codec, 0x01); | 4394 | hda_call_check_power_status(codec, 0x01); |
@@ -4529,8 +4445,6 @@ static void stac92xx_free(struct hda_codec *codec) | |||
4529 | return; | 4445 | return; |
4530 | 4446 | ||
4531 | stac92xx_shutup(codec); | 4447 | stac92xx_shutup(codec); |
4532 | snd_hda_input_jack_free(codec); | ||
4533 | snd_array_free(&spec->events); | ||
4534 | 4448 | ||
4535 | kfree(spec); | 4449 | kfree(spec); |
4536 | snd_hda_detach_beep_device(codec); | 4450 | snd_hda_detach_beep_device(codec); |
@@ -4794,26 +4708,13 @@ static void stac92xx_mic_detect(struct hda_codec *codec) | |||
4794 | mic->mux_idx); | 4708 | mic->mux_idx); |
4795 | } | 4709 | } |
4796 | 4710 | ||
4797 | static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid) | 4711 | static void handle_unsol_event(struct hda_codec *codec, |
4798 | { | 4712 | struct hda_jack_tbl *event) |
4799 | struct sigmatel_event *event = stac_get_event(codec, nid); | ||
4800 | if (!event) | ||
4801 | return; | ||
4802 | codec->patch_ops.unsol_event(codec, (unsigned)event->tag << 26); | ||
4803 | } | ||
4804 | |||
4805 | static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) | ||
4806 | { | 4713 | { |
4807 | struct sigmatel_spec *spec = codec->spec; | 4714 | struct sigmatel_spec *spec = codec->spec; |
4808 | struct sigmatel_event *event; | 4715 | int data; |
4809 | int tag, data; | ||
4810 | |||
4811 | tag = (res >> 26) & 0x7f; | ||
4812 | event = stac_get_event_from_tag(codec, tag); | ||
4813 | if (!event) | ||
4814 | return; | ||
4815 | 4716 | ||
4816 | switch (event->type) { | 4717 | switch (event->action) { |
4817 | case STAC_HP_EVENT: | 4718 | case STAC_HP_EVENT: |
4818 | case STAC_LO_EVENT: | 4719 | case STAC_LO_EVENT: |
4819 | stac92xx_hp_detect(codec); | 4720 | stac92xx_hp_detect(codec); |
@@ -4823,7 +4724,7 @@ static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) | |||
4823 | break; | 4724 | break; |
4824 | } | 4725 | } |
4825 | 4726 | ||
4826 | switch (event->type) { | 4727 | switch (event->action) { |
4827 | case STAC_HP_EVENT: | 4728 | case STAC_HP_EVENT: |
4828 | case STAC_LO_EVENT: | 4729 | case STAC_LO_EVENT: |
4829 | case STAC_MIC_EVENT: | 4730 | case STAC_MIC_EVENT: |
@@ -4831,7 +4732,6 @@ static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) | |||
4831 | case STAC_PWR_EVENT: | 4732 | case STAC_PWR_EVENT: |
4832 | if (spec->num_pwrs > 0) | 4733 | if (spec->num_pwrs > 0) |
4833 | stac92xx_pin_sense(codec, event->nid); | 4734 | stac92xx_pin_sense(codec, event->nid); |
4834 | snd_hda_input_jack_report(codec, event->nid); | ||
4835 | 4735 | ||
4836 | switch (codec->subsystem_id) { | 4736 | switch (codec->subsystem_id) { |
4837 | case 0x103c308f: | 4737 | case 0x103c308f: |
@@ -4856,11 +4756,33 @@ static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) | |||
4856 | AC_VERB_GET_GPIO_DATA, 0); | 4756 | AC_VERB_GET_GPIO_DATA, 0); |
4857 | /* toggle VREF state based on GPIOx status */ | 4757 | /* toggle VREF state based on GPIOx status */ |
4858 | snd_hda_codec_write(codec, codec->afg, 0, 0x7e0, | 4758 | snd_hda_codec_write(codec, codec->afg, 0, 0x7e0, |
4859 | !!(data & (1 << event->data))); | 4759 | !!(data & (1 << event->private_data))); |
4860 | break; | 4760 | break; |
4861 | } | 4761 | } |
4862 | } | 4762 | } |
4863 | 4763 | ||
4764 | static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid) | ||
4765 | { | ||
4766 | struct hda_jack_tbl *event = snd_hda_jack_tbl_get(codec, nid); | ||
4767 | if (!event) | ||
4768 | return; | ||
4769 | handle_unsol_event(codec, event); | ||
4770 | } | ||
4771 | |||
4772 | static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) | ||
4773 | { | ||
4774 | struct hda_jack_tbl *event; | ||
4775 | int tag; | ||
4776 | |||
4777 | tag = (res >> 26) & 0x7f; | ||
4778 | event = snd_hda_jack_tbl_get_from_tag(codec, tag); | ||
4779 | if (!event) | ||
4780 | return; | ||
4781 | event->jack_dirty = 1; | ||
4782 | handle_unsol_event(codec, event); | ||
4783 | snd_hda_jack_report_sync(codec); | ||
4784 | } | ||
4785 | |||
4864 | static int hp_blike_system(u32 subsystem_id); | 4786 | static int hp_blike_system(u32 subsystem_id); |
4865 | 4787 | ||
4866 | static void set_hp_led_gpio(struct hda_codec *codec) | 4788 | static void set_hp_led_gpio(struct hda_codec *codec) |
@@ -5837,15 +5759,13 @@ again: | |||
5837 | switch (spec->board_config) { | 5759 | switch (spec->board_config) { |
5838 | case STAC_HP_M4: | 5760 | case STAC_HP_M4: |
5839 | /* Enable VREF power saving on GPIO1 detect */ | 5761 | /* Enable VREF power saving on GPIO1 detect */ |
5840 | err = stac_add_event(spec, codec->afg, | 5762 | err = stac_add_event(codec, codec->afg, |
5841 | STAC_VREF_EVENT, 0x02); | 5763 | STAC_VREF_EVENT, 0x02); |
5842 | if (err < 0) | 5764 | if (err < 0) |
5843 | return err; | 5765 | return err; |
5844 | snd_hda_codec_write_cache(codec, codec->afg, 0, | 5766 | snd_hda_codec_write_cache(codec, codec->afg, 0, |
5845 | AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x02); | 5767 | AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x02); |
5846 | snd_hda_codec_write_cache(codec, codec->afg, 0, | 5768 | snd_hda_jack_detect_enable(codec, codec->afg, 0); |
5847 | AC_VERB_SET_UNSOLICITED_ENABLE, | ||
5848 | AC_USRSP_EN | err); | ||
5849 | spec->gpio_mask |= 0x02; | 5769 | spec->gpio_mask |= 0x02; |
5850 | break; | 5770 | break; |
5851 | } | 5771 | } |
@@ -6316,14 +6236,12 @@ static int patch_stac9205(struct hda_codec *codec) | |||
6316 | snd_hda_codec_set_pincfg(codec, 0x20, 0x1c410030); | 6236 | snd_hda_codec_set_pincfg(codec, 0x20, 0x1c410030); |
6317 | 6237 | ||
6318 | /* Enable unsol response for GPIO4/Dock HP connection */ | 6238 | /* Enable unsol response for GPIO4/Dock HP connection */ |
6319 | err = stac_add_event(spec, codec->afg, STAC_VREF_EVENT, 0x01); | 6239 | err = stac_add_event(codec, codec->afg, STAC_VREF_EVENT, 0x01); |
6320 | if (err < 0) | 6240 | if (err < 0) |
6321 | return err; | 6241 | return err; |
6322 | snd_hda_codec_write_cache(codec, codec->afg, 0, | 6242 | snd_hda_codec_write_cache(codec, codec->afg, 0, |
6323 | AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x10); | 6243 | AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x10); |
6324 | snd_hda_codec_write_cache(codec, codec->afg, 0, | 6244 | snd_hda_jack_detect_enable(codec, codec->afg, 0); |
6325 | AC_VERB_SET_UNSOLICITED_ENABLE, | ||
6326 | AC_USRSP_EN | err); | ||
6327 | 6245 | ||
6328 | spec->gpio_dir = 0x0b; | 6246 | spec->gpio_dir = 0x0b; |
6329 | spec->eapd_mask = 0x01; | 6247 | spec->eapd_mask = 0x01; |