aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_sigmatel.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2011-12-20 09:42:57 -0500
committerTakashi Iwai <tiwai@suse.de>2011-12-20 09:42:57 -0500
commit78c058df6a120044455b5635daefdc515bf9d899 (patch)
treed349e70e384404a9a2d9860feb0219e9f8acb212 /sound/pci/hda/patch_sigmatel.c
parentdb9c6f842fa957b41984cd8ceea1f07c53fb3fbf (diff)
parent31ef22579302ac42054bebecb528710f46580925 (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.c196
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
41enum { 42enum {
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
178struct sigmatel_event {
179 hda_nid_t nid;
180 unsigned char type;
181 unsigned char tag;
182 int data;
183};
184
185struct sigmatel_mic_route { 179struct 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
1095static void stac92xx_free_kctls(struct hda_codec *codec); 1086static void stac92xx_free_kctls(struct hda_codec *codec);
1096static int stac92xx_add_jack(struct hda_codec *codec, hda_nid_t nid, int type);
1097 1087
1098static int stac92xx_build_controls(struct hda_codec *codec) 1088static 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
4163static int stac92xx_add_jack(struct hda_codec *codec, 4131static 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
4179static 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
4196static 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
4210static 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,
4228static int enable_pin_detect(struct hda_codec *codec, hda_nid_t nid, 4149static 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
4797static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid) 4711static 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
4805static 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
4764static 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
4772static 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
4864static int hp_blike_system(u32 subsystem_id); 4786static int hp_blike_system(u32 subsystem_id);
4865 4787
4866static void set_hp_led_gpio(struct hda_codec *codec) 4788static 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;