diff options
Diffstat (limited to 'sound/pci/hda/patch_sigmatel.c')
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 1318 |
1 files changed, 772 insertions, 546 deletions
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index b77f330d2650..35b83dc6e19e 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -30,17 +30,17 @@ | |||
30 | #include <linux/pci.h> | 30 | #include <linux/pci.h> |
31 | #include <sound/core.h> | 31 | #include <sound/core.h> |
32 | #include <sound/asoundef.h> | 32 | #include <sound/asoundef.h> |
33 | #include <sound/jack.h> | ||
33 | #include "hda_codec.h" | 34 | #include "hda_codec.h" |
34 | #include "hda_local.h" | 35 | #include "hda_local.h" |
35 | #include "hda_patch.h" | ||
36 | #include "hda_beep.h" | 36 | #include "hda_beep.h" |
37 | 37 | ||
38 | #define NUM_CONTROL_ALLOC 32 | 38 | enum { |
39 | 39 | STAC_VREF_EVENT = 1, | |
40 | #define STAC_VREF_EVENT 0x00 | 40 | STAC_INSERT_EVENT, |
41 | #define STAC_INSERT_EVENT 0x10 | 41 | STAC_PWR_EVENT, |
42 | #define STAC_PWR_EVENT 0x20 | 42 | STAC_HP_EVENT, |
43 | #define STAC_HP_EVENT 0x30 | 43 | }; |
44 | 44 | ||
45 | enum { | 45 | enum { |
46 | STAC_REF, | 46 | STAC_REF, |
@@ -137,6 +137,19 @@ enum { | |||
137 | STAC_927X_MODELS | 137 | STAC_927X_MODELS |
138 | }; | 138 | }; |
139 | 139 | ||
140 | struct sigmatel_event { | ||
141 | hda_nid_t nid; | ||
142 | unsigned char type; | ||
143 | unsigned char tag; | ||
144 | int data; | ||
145 | }; | ||
146 | |||
147 | struct sigmatel_jack { | ||
148 | hda_nid_t nid; | ||
149 | int type; | ||
150 | struct snd_jack *jack; | ||
151 | }; | ||
152 | |||
140 | struct sigmatel_spec { | 153 | struct sigmatel_spec { |
141 | struct snd_kcontrol_new *mixers[4]; | 154 | struct snd_kcontrol_new *mixers[4]; |
142 | unsigned int num_mixers; | 155 | unsigned int num_mixers; |
@@ -144,8 +157,6 @@ struct sigmatel_spec { | |||
144 | int board_config; | 157 | int board_config; |
145 | unsigned int eapd_switch: 1; | 158 | unsigned int eapd_switch: 1; |
146 | unsigned int surr_switch: 1; | 159 | unsigned int surr_switch: 1; |
147 | unsigned int line_switch: 1; | ||
148 | unsigned int mic_switch: 1; | ||
149 | unsigned int alt_switch: 1; | 160 | unsigned int alt_switch: 1; |
150 | unsigned int hp_detect: 1; | 161 | unsigned int hp_detect: 1; |
151 | unsigned int spdif_mute: 1; | 162 | unsigned int spdif_mute: 1; |
@@ -170,12 +181,20 @@ struct sigmatel_spec { | |||
170 | hda_nid_t *pwr_nids; | 181 | hda_nid_t *pwr_nids; |
171 | hda_nid_t *dac_list; | 182 | hda_nid_t *dac_list; |
172 | 183 | ||
184 | /* jack detection */ | ||
185 | struct snd_array jacks; | ||
186 | |||
187 | /* events */ | ||
188 | struct snd_array events; | ||
189 | |||
173 | /* playback */ | 190 | /* playback */ |
174 | struct hda_input_mux *mono_mux; | 191 | struct hda_input_mux *mono_mux; |
175 | struct hda_input_mux *amp_mux; | 192 | struct hda_input_mux *amp_mux; |
176 | unsigned int cur_mmux; | 193 | unsigned int cur_mmux; |
177 | struct hda_multi_out multiout; | 194 | struct hda_multi_out multiout; |
178 | hda_nid_t dac_nids[5]; | 195 | hda_nid_t dac_nids[5]; |
196 | hda_nid_t hp_dacs[5]; | ||
197 | hda_nid_t speaker_dacs[5]; | ||
179 | 198 | ||
180 | /* capture */ | 199 | /* capture */ |
181 | hda_nid_t *adc_nids; | 200 | hda_nid_t *adc_nids; |
@@ -199,7 +218,6 @@ struct sigmatel_spec { | |||
199 | hda_nid_t *pin_nids; | 218 | hda_nid_t *pin_nids; |
200 | unsigned int num_pins; | 219 | unsigned int num_pins; |
201 | unsigned int *pin_configs; | 220 | unsigned int *pin_configs; |
202 | unsigned int *bios_pin_configs; | ||
203 | 221 | ||
204 | /* codec specific stuff */ | 222 | /* codec specific stuff */ |
205 | struct hda_verb *init; | 223 | struct hda_verb *init; |
@@ -220,15 +238,16 @@ struct sigmatel_spec { | |||
220 | /* i/o switches */ | 238 | /* i/o switches */ |
221 | unsigned int io_switch[2]; | 239 | unsigned int io_switch[2]; |
222 | unsigned int clfe_swap; | 240 | unsigned int clfe_swap; |
223 | unsigned int hp_switch; /* NID of HP as line-out */ | 241 | hda_nid_t line_switch; /* shared line-in for input and output */ |
242 | hda_nid_t mic_switch; /* shared mic-in for input and output */ | ||
243 | hda_nid_t hp_switch; /* NID of HP as line-out */ | ||
224 | unsigned int aloopback; | 244 | unsigned int aloopback; |
225 | 245 | ||
226 | struct hda_pcm pcm_rec[2]; /* PCM information */ | 246 | struct hda_pcm pcm_rec[2]; /* PCM information */ |
227 | 247 | ||
228 | /* dynamic controls and input_mux */ | 248 | /* dynamic controls and input_mux */ |
229 | struct auto_pin_cfg autocfg; | 249 | struct auto_pin_cfg autocfg; |
230 | unsigned int num_kctl_alloc, num_kctl_used; | 250 | struct snd_array kctls; |
231 | struct snd_kcontrol_new *kctl_alloc; | ||
232 | struct hda_input_mux private_dimux; | 251 | struct hda_input_mux private_dimux; |
233 | struct hda_input_mux private_imux; | 252 | struct hda_input_mux private_imux; |
234 | struct hda_input_mux private_smux; | 253 | struct hda_input_mux private_smux; |
@@ -272,9 +291,6 @@ static hda_nid_t stac92hd73xx_dmic_nids[STAC92HD73XX_NUM_DMICS + 1] = { | |||
272 | }; | 291 | }; |
273 | 292 | ||
274 | #define STAC92HD73_DAC_COUNT 5 | 293 | #define STAC92HD73_DAC_COUNT 5 |
275 | static hda_nid_t stac92hd73xx_dac_nids[STAC92HD73_DAC_COUNT] = { | ||
276 | 0x15, 0x16, 0x17, 0x18, 0x19, | ||
277 | }; | ||
278 | 294 | ||
279 | static hda_nid_t stac92hd73xx_mux_nids[4] = { | 295 | static hda_nid_t stac92hd73xx_mux_nids[4] = { |
280 | 0x28, 0x29, 0x2a, 0x2b, | 296 | 0x28, 0x29, 0x2a, 0x2b, |
@@ -293,11 +309,7 @@ static hda_nid_t stac92hd83xxx_dmic_nids[STAC92HD83XXX_NUM_DMICS + 1] = { | |||
293 | 0x11, 0x12, 0 | 309 | 0x11, 0x12, 0 |
294 | }; | 310 | }; |
295 | 311 | ||
296 | #define STAC92HD81_DAC_COUNT 2 | ||
297 | #define STAC92HD83_DAC_COUNT 3 | 312 | #define STAC92HD83_DAC_COUNT 3 |
298 | static hda_nid_t stac92hd83xxx_dac_nids[STAC92HD73_DAC_COUNT] = { | ||
299 | 0x13, 0x14, 0x22, | ||
300 | }; | ||
301 | 313 | ||
302 | static hda_nid_t stac92hd83xxx_dmux_nids[2] = { | 314 | static hda_nid_t stac92hd83xxx_dmux_nids[2] = { |
303 | 0x17, 0x18, | 315 | 0x17, 0x18, |
@@ -339,10 +351,6 @@ static hda_nid_t stac92hd71bxx_smux_nids[2] = { | |||
339 | 0x24, 0x25, | 351 | 0x24, 0x25, |
340 | }; | 352 | }; |
341 | 353 | ||
342 | static hda_nid_t stac92hd71bxx_dac_nids[1] = { | ||
343 | 0x10, /*0x11, */ | ||
344 | }; | ||
345 | |||
346 | #define STAC92HD71BXX_NUM_DMICS 2 | 354 | #define STAC92HD71BXX_NUM_DMICS 2 |
347 | static hda_nid_t stac92hd71bxx_dmic_nids[STAC92HD71BXX_NUM_DMICS + 1] = { | 355 | static hda_nid_t stac92hd71bxx_dmic_nids[STAC92HD71BXX_NUM_DMICS + 1] = { |
348 | 0x18, 0x19, 0 | 356 | 0x18, 0x19, 0 |
@@ -574,12 +582,12 @@ static int stac92xx_smux_enum_put(struct snd_kcontrol *kcontrol, | |||
574 | else | 582 | else |
575 | nid = codec->slave_dig_outs[smux_idx - 1]; | 583 | nid = codec->slave_dig_outs[smux_idx - 1]; |
576 | if (spec->cur_smux[smux_idx] == smux->num_items - 1) | 584 | if (spec->cur_smux[smux_idx] == smux->num_items - 1) |
577 | val = AMP_OUT_MUTE; | 585 | val = HDA_AMP_MUTE; |
578 | else | 586 | else |
579 | val = AMP_OUT_UNMUTE; | 587 | val = 0; |
580 | /* un/mute SPDIF out */ | 588 | /* un/mute SPDIF out */ |
581 | snd_hda_codec_write_cache(codec, nid, 0, | 589 | snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0, |
582 | AC_VERB_SET_AMP_GAIN_MUTE, val); | 590 | HDA_AMP_MUTE, val); |
583 | } | 591 | } |
584 | return 0; | 592 | return 0; |
585 | } | 593 | } |
@@ -744,10 +752,6 @@ static struct hda_verb stac9200_eapd_init[] = { | |||
744 | static struct hda_verb stac92hd73xx_6ch_core_init[] = { | 752 | static struct hda_verb stac92hd73xx_6ch_core_init[] = { |
745 | /* set master volume and direct control */ | 753 | /* set master volume and direct control */ |
746 | { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, | 754 | { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, |
747 | /* setup audio connections */ | ||
748 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
749 | { 0x10, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
750 | { 0x11, AC_VERB_SET_CONNECT_SEL, 0x02}, | ||
751 | /* setup adcs to point to mixer */ | 755 | /* setup adcs to point to mixer */ |
752 | { 0x20, AC_VERB_SET_CONNECT_SEL, 0x0b}, | 756 | { 0x20, AC_VERB_SET_CONNECT_SEL, 0x0b}, |
753 | { 0x21, AC_VERB_SET_CONNECT_SEL, 0x0b}, | 757 | { 0x21, AC_VERB_SET_CONNECT_SEL, 0x0b}, |
@@ -766,10 +770,6 @@ static struct hda_verb dell_eq_core_init[] = { | |||
766 | /* set master volume to max value without distortion | 770 | /* set master volume to max value without distortion |
767 | * and direct control */ | 771 | * and direct control */ |
768 | { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xec}, | 772 | { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xec}, |
769 | /* setup audio connections */ | ||
770 | { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
771 | { 0x0a, AC_VERB_SET_CONNECT_SEL, 0x02}, | ||
772 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
773 | /* setup adcs to point to mixer */ | 773 | /* setup adcs to point to mixer */ |
774 | { 0x20, AC_VERB_SET_CONNECT_SEL, 0x0b}, | 774 | { 0x20, AC_VERB_SET_CONNECT_SEL, 0x0b}, |
775 | { 0x21, AC_VERB_SET_CONNECT_SEL, 0x0b}, | 775 | { 0x21, AC_VERB_SET_CONNECT_SEL, 0x0b}, |
@@ -783,10 +783,6 @@ static struct hda_verb dell_eq_core_init[] = { | |||
783 | 783 | ||
784 | static struct hda_verb dell_m6_core_init[] = { | 784 | static struct hda_verb dell_m6_core_init[] = { |
785 | { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, | 785 | { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, |
786 | /* setup audio connections */ | ||
787 | { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
788 | { 0x0a, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
789 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x02}, | ||
790 | /* setup adcs to point to mixer */ | 786 | /* setup adcs to point to mixer */ |
791 | { 0x20, AC_VERB_SET_CONNECT_SEL, 0x0b}, | 787 | { 0x20, AC_VERB_SET_CONNECT_SEL, 0x0b}, |
792 | { 0x21, AC_VERB_SET_CONNECT_SEL, 0x0b}, | 788 | { 0x21, AC_VERB_SET_CONNECT_SEL, 0x0b}, |
@@ -801,13 +797,6 @@ static struct hda_verb dell_m6_core_init[] = { | |||
801 | static struct hda_verb stac92hd73xx_8ch_core_init[] = { | 797 | static struct hda_verb stac92hd73xx_8ch_core_init[] = { |
802 | /* set master volume and direct control */ | 798 | /* set master volume and direct control */ |
803 | { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, | 799 | { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, |
804 | /* setup audio connections */ | ||
805 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
806 | { 0x10, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
807 | { 0x11, AC_VERB_SET_CONNECT_SEL, 0x02}, | ||
808 | /* connect hp ports to dac3 */ | ||
809 | { 0x0a, AC_VERB_SET_CONNECT_SEL, 0x03}, | ||
810 | { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x03}, | ||
811 | /* setup adcs to point to mixer */ | 800 | /* setup adcs to point to mixer */ |
812 | { 0x20, AC_VERB_SET_CONNECT_SEL, 0x0b}, | 801 | { 0x20, AC_VERB_SET_CONNECT_SEL, 0x0b}, |
813 | { 0x21, AC_VERB_SET_CONNECT_SEL, 0x0b}, | 802 | { 0x21, AC_VERB_SET_CONNECT_SEL, 0x0b}, |
@@ -825,15 +814,8 @@ static struct hda_verb stac92hd73xx_8ch_core_init[] = { | |||
825 | static struct hda_verb stac92hd73xx_10ch_core_init[] = { | 814 | static struct hda_verb stac92hd73xx_10ch_core_init[] = { |
826 | /* set master volume and direct control */ | 815 | /* set master volume and direct control */ |
827 | { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, | 816 | { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, |
828 | /* setup audio connections */ | ||
829 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, | ||
830 | { 0x10, AC_VERB_SET_CONNECT_SEL, 0x01 }, | ||
831 | { 0x11, AC_VERB_SET_CONNECT_SEL, 0x02 }, | ||
832 | /* dac3 is connected to import3 mux */ | 817 | /* dac3 is connected to import3 mux */ |
833 | { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb07f}, | 818 | { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb07f}, |
834 | /* connect hp ports to dac4 */ | ||
835 | { 0x0a, AC_VERB_SET_CONNECT_SEL, 0x04}, | ||
836 | { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x04}, | ||
837 | /* setup adcs to point to mixer */ | 819 | /* setup adcs to point to mixer */ |
838 | { 0x20, AC_VERB_SET_CONNECT_SEL, 0x0b}, | 820 | { 0x20, AC_VERB_SET_CONNECT_SEL, 0x0b}, |
839 | { 0x21, AC_VERB_SET_CONNECT_SEL, 0x0b}, | 821 | { 0x21, AC_VERB_SET_CONNECT_SEL, 0x0b}, |
@@ -865,8 +847,6 @@ static struct hda_verb stac92hd83xxx_core_init[] = { | |||
865 | static struct hda_verb stac92hd71bxx_core_init[] = { | 847 | static struct hda_verb stac92hd71bxx_core_init[] = { |
866 | /* set master volume and direct control */ | 848 | /* set master volume and direct control */ |
867 | { 0x28, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, | 849 | { 0x28, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, |
868 | /* connect headphone jack to dac1 */ | ||
869 | { 0x0a, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
870 | /* unmute right and left channels for nodes 0x0a, 0xd, 0x0f */ | 850 | /* unmute right and left channels for nodes 0x0a, 0xd, 0x0f */ |
871 | { 0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 851 | { 0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
872 | { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 852 | { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
@@ -886,8 +866,6 @@ static struct hda_verb stac92hd71bxx_analog_core_init[] = { | |||
886 | 866 | ||
887 | /* set master volume and direct control */ | 867 | /* set master volume and direct control */ |
888 | { 0x28, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, | 868 | { 0x28, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, |
889 | /* connect headphone jack to dac1 */ | ||
890 | { 0x0a, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
891 | /* unmute right and left channels for nodes 0x0a, 0xd */ | 869 | /* unmute right and left channels for nodes 0x0a, 0xd */ |
892 | { 0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 870 | { 0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
893 | { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 871 | { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
@@ -1087,21 +1065,21 @@ static struct snd_kcontrol_new stac92hd83xxx_mixer[] = { | |||
1087 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x18, 0x0, HDA_OUTPUT), | 1065 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x18, 0x0, HDA_OUTPUT), |
1088 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x18, 0x0, HDA_OUTPUT), | 1066 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x18, 0x0, HDA_OUTPUT), |
1089 | 1067 | ||
1090 | HDA_CODEC_VOLUME("DAC0 Capture Volume", 0x1b, 0, HDA_INPUT), | 1068 | HDA_CODEC_VOLUME("DAC0 Capture Volume", 0x1b, 0x3, HDA_INPUT), |
1091 | HDA_CODEC_MUTE("DAC0 Capture Switch", 0x1b, 0, HDA_INPUT), | 1069 | HDA_CODEC_MUTE("DAC0 Capture Switch", 0x1b, 0x3, HDA_INPUT), |
1092 | 1070 | ||
1093 | HDA_CODEC_VOLUME("DAC1 Capture Volume", 0x1b, 0x1, HDA_INPUT), | 1071 | HDA_CODEC_VOLUME("DAC1 Capture Volume", 0x1b, 0x4, HDA_INPUT), |
1094 | HDA_CODEC_MUTE("DAC1 Capture Switch", 0x1b, 0x1, HDA_INPUT), | 1072 | HDA_CODEC_MUTE("DAC1 Capture Switch", 0x1b, 0x4, HDA_INPUT), |
1095 | 1073 | ||
1096 | HDA_CODEC_VOLUME("Front Mic Capture Volume", 0x1b, 0x2, HDA_INPUT), | 1074 | HDA_CODEC_VOLUME("Front Mic Capture Volume", 0x1b, 0x0, HDA_INPUT), |
1097 | HDA_CODEC_MUTE("Front Mic Capture Switch", 0x1b, 0x2, HDA_INPUT), | 1075 | HDA_CODEC_MUTE("Front Mic Capture Switch", 0x1b, 0x0, HDA_INPUT), |
1098 | 1076 | ||
1099 | HDA_CODEC_VOLUME("Line In Capture Volume", 0x1b, 0x3, HDA_INPUT), | 1077 | HDA_CODEC_VOLUME("Line In Capture Volume", 0x1b, 0x2, HDA_INPUT), |
1100 | HDA_CODEC_MUTE("Line In Capture Switch", 0x1b, 0x3, HDA_INPUT), | 1078 | HDA_CODEC_MUTE("Line In Capture Switch", 0x1b, 0x2, HDA_INPUT), |
1101 | 1079 | ||
1102 | /* | 1080 | /* |
1103 | HDA_CODEC_VOLUME("Mic Capture Volume", 0x1b, 0x4, HDA_INPUT), | 1081 | HDA_CODEC_VOLUME("Mic Capture Volume", 0x1b, 0x1, HDA_INPUT), |
1104 | HDA_CODEC_MUTE("Mic Capture Switch", 0x1b 0x4, HDA_INPUT), | 1082 | HDA_CODEC_MUTE("Mic Capture Switch", 0x1b 0x1, HDA_INPUT), |
1105 | */ | 1083 | */ |
1106 | { } /* end */ | 1084 | { } /* end */ |
1107 | }; | 1085 | }; |
@@ -1240,9 +1218,14 @@ static const char *slave_sws[] = { | |||
1240 | NULL | 1218 | NULL |
1241 | }; | 1219 | }; |
1242 | 1220 | ||
1221 | static void stac92xx_free_kctls(struct hda_codec *codec); | ||
1222 | static int stac92xx_add_jack(struct hda_codec *codec, hda_nid_t nid, int type); | ||
1223 | |||
1243 | static int stac92xx_build_controls(struct hda_codec *codec) | 1224 | static int stac92xx_build_controls(struct hda_codec *codec) |
1244 | { | 1225 | { |
1245 | struct sigmatel_spec *spec = codec->spec; | 1226 | struct sigmatel_spec *spec = codec->spec; |
1227 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
1228 | hda_nid_t nid; | ||
1246 | int err; | 1229 | int err; |
1247 | int i; | 1230 | int i; |
1248 | 1231 | ||
@@ -1257,7 +1240,7 @@ static int stac92xx_build_controls(struct hda_codec *codec) | |||
1257 | } | 1240 | } |
1258 | if (spec->num_dmuxes > 0) { | 1241 | if (spec->num_dmuxes > 0) { |
1259 | stac_dmux_mixer.count = spec->num_dmuxes; | 1242 | stac_dmux_mixer.count = spec->num_dmuxes; |
1260 | err = snd_ctl_add(codec->bus->card, | 1243 | err = snd_hda_ctl_add(codec, |
1261 | snd_ctl_new1(&stac_dmux_mixer, codec)); | 1244 | snd_ctl_new1(&stac_dmux_mixer, codec)); |
1262 | if (err < 0) | 1245 | if (err < 0) |
1263 | return err; | 1246 | return err; |
@@ -1273,7 +1256,7 @@ static int stac92xx_build_controls(struct hda_codec *codec) | |||
1273 | spec->spdif_mute = 1; | 1256 | spec->spdif_mute = 1; |
1274 | } | 1257 | } |
1275 | stac_smux_mixer.count = spec->num_smuxes; | 1258 | stac_smux_mixer.count = spec->num_smuxes; |
1276 | err = snd_ctl_add(codec->bus->card, | 1259 | err = snd_hda_ctl_add(codec, |
1277 | snd_ctl_new1(&stac_smux_mixer, codec)); | 1260 | snd_ctl_new1(&stac_smux_mixer, codec)); |
1278 | if (err < 0) | 1261 | if (err < 0) |
1279 | return err; | 1262 | return err; |
@@ -1312,6 +1295,37 @@ static int stac92xx_build_controls(struct hda_codec *codec) | |||
1312 | return err; | 1295 | return err; |
1313 | } | 1296 | } |
1314 | 1297 | ||
1298 | stac92xx_free_kctls(codec); /* no longer needed */ | ||
1299 | |||
1300 | /* create jack input elements */ | ||
1301 | if (spec->hp_detect) { | ||
1302 | for (i = 0; i < cfg->hp_outs; i++) { | ||
1303 | int type = SND_JACK_HEADPHONE; | ||
1304 | nid = cfg->hp_pins[i]; | ||
1305 | /* jack detection */ | ||
1306 | if (cfg->hp_outs == i) | ||
1307 | type |= SND_JACK_LINEOUT; | ||
1308 | err = stac92xx_add_jack(codec, nid, type); | ||
1309 | if (err < 0) | ||
1310 | return err; | ||
1311 | } | ||
1312 | } | ||
1313 | for (i = 0; i < cfg->line_outs; i++) { | ||
1314 | err = stac92xx_add_jack(codec, cfg->line_out_pins[i], | ||
1315 | SND_JACK_LINEOUT); | ||
1316 | if (err < 0) | ||
1317 | return err; | ||
1318 | } | ||
1319 | for (i = 0; i < AUTO_PIN_LAST; i++) { | ||
1320 | nid = cfg->input_pins[i]; | ||
1321 | if (nid) { | ||
1322 | err = stac92xx_add_jack(codec, nid, | ||
1323 | SND_JACK_MICROPHONE); | ||
1324 | if (err < 0) | ||
1325 | return err; | ||
1326 | } | ||
1327 | } | ||
1328 | |||
1315 | return 0; | 1329 | return 0; |
1316 | } | 1330 | } |
1317 | 1331 | ||
@@ -1720,6 +1734,8 @@ static struct snd_pci_quirk stac92hd71bxx_cfg_tbl[] = { | |||
1720 | "HP dv5", STAC_HP_M4), | 1734 | "HP dv5", STAC_HP_M4), |
1721 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x30f4, | 1735 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x30f4, |
1722 | "HP dv7", STAC_HP_M4), | 1736 | "HP dv7", STAC_HP_M4), |
1737 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x30fc, | ||
1738 | "HP dv7", STAC_HP_M4), | ||
1723 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x361a, | 1739 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x361a, |
1724 | "unknown HP", STAC_HP_M4), | 1740 | "unknown HP", STAC_HP_M4), |
1725 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0233, | 1741 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0233, |
@@ -2203,12 +2219,11 @@ static int stac92xx_save_bios_config_regs(struct hda_codec *codec) | |||
2203 | int i; | 2219 | int i; |
2204 | struct sigmatel_spec *spec = codec->spec; | 2220 | struct sigmatel_spec *spec = codec->spec; |
2205 | 2221 | ||
2206 | if (! spec->bios_pin_configs) { | 2222 | kfree(spec->pin_configs); |
2207 | spec->bios_pin_configs = kcalloc(spec->num_pins, | 2223 | spec->pin_configs = kcalloc(spec->num_pins, sizeof(*spec->pin_configs), |
2208 | sizeof(*spec->bios_pin_configs), GFP_KERNEL); | 2224 | GFP_KERNEL); |
2209 | if (! spec->bios_pin_configs) | 2225 | if (!spec->pin_configs) |
2210 | return -ENOMEM; | 2226 | return -ENOMEM; |
2211 | } | ||
2212 | 2227 | ||
2213 | for (i = 0; i < spec->num_pins; i++) { | 2228 | for (i = 0; i < spec->num_pins; i++) { |
2214 | hda_nid_t nid = spec->pin_nids[i]; | 2229 | hda_nid_t nid = spec->pin_nids[i]; |
@@ -2218,7 +2233,7 @@ static int stac92xx_save_bios_config_regs(struct hda_codec *codec) | |||
2218 | AC_VERB_GET_CONFIG_DEFAULT, 0x00); | 2233 | AC_VERB_GET_CONFIG_DEFAULT, 0x00); |
2219 | snd_printdd(KERN_INFO "hda_codec: pin nid %2.2x bios pin config %8.8x\n", | 2234 | snd_printdd(KERN_INFO "hda_codec: pin nid %2.2x bios pin config %8.8x\n", |
2220 | nid, pin_cfg); | 2235 | nid, pin_cfg); |
2221 | spec->bios_pin_configs[i] = pin_cfg; | 2236 | spec->pin_configs[i] = pin_cfg; |
2222 | } | 2237 | } |
2223 | 2238 | ||
2224 | return 0; | 2239 | return 0; |
@@ -2260,6 +2275,39 @@ static void stac92xx_set_config_regs(struct hda_codec *codec) | |||
2260 | spec->pin_configs[i]); | 2275 | spec->pin_configs[i]); |
2261 | } | 2276 | } |
2262 | 2277 | ||
2278 | static int stac_save_pin_cfgs(struct hda_codec *codec, unsigned int *pins) | ||
2279 | { | ||
2280 | struct sigmatel_spec *spec = codec->spec; | ||
2281 | |||
2282 | if (!pins) | ||
2283 | return stac92xx_save_bios_config_regs(codec); | ||
2284 | |||
2285 | kfree(spec->pin_configs); | ||
2286 | spec->pin_configs = kmemdup(pins, | ||
2287 | spec->num_pins * sizeof(*pins), | ||
2288 | GFP_KERNEL); | ||
2289 | if (!spec->pin_configs) | ||
2290 | return -ENOMEM; | ||
2291 | |||
2292 | stac92xx_set_config_regs(codec); | ||
2293 | return 0; | ||
2294 | } | ||
2295 | |||
2296 | static void stac_change_pin_config(struct hda_codec *codec, hda_nid_t nid, | ||
2297 | unsigned int cfg) | ||
2298 | { | ||
2299 | struct sigmatel_spec *spec = codec->spec; | ||
2300 | int i; | ||
2301 | |||
2302 | for (i = 0; i < spec->num_pins; i++) { | ||
2303 | if (spec->pin_nids[i] == nid) { | ||
2304 | spec->pin_configs[i] = cfg; | ||
2305 | stac92xx_set_config_reg(codec, nid, cfg); | ||
2306 | break; | ||
2307 | } | ||
2308 | } | ||
2309 | } | ||
2310 | |||
2263 | /* | 2311 | /* |
2264 | * Analog playback callbacks | 2312 | * Analog playback callbacks |
2265 | */ | 2313 | */ |
@@ -2337,7 +2385,7 @@ static int stac92xx_capture_pcm_prepare(struct hda_pcm_stream *hinfo, | |||
2337 | 2385 | ||
2338 | if (spec->powerdown_adcs) { | 2386 | if (spec->powerdown_adcs) { |
2339 | msleep(40); | 2387 | msleep(40); |
2340 | snd_hda_codec_write_cache(codec, nid, 0, | 2388 | snd_hda_codec_write(codec, nid, 0, |
2341 | AC_VERB_SET_POWER_STATE, AC_PWRST_D0); | 2389 | AC_VERB_SET_POWER_STATE, AC_PWRST_D0); |
2342 | } | 2390 | } |
2343 | snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format); | 2391 | snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format); |
@@ -2353,7 +2401,7 @@ static int stac92xx_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, | |||
2353 | 2401 | ||
2354 | snd_hda_codec_cleanup_stream(codec, nid); | 2402 | snd_hda_codec_cleanup_stream(codec, nid); |
2355 | if (spec->powerdown_adcs) | 2403 | if (spec->powerdown_adcs) |
2356 | snd_hda_codec_write_cache(codec, nid, 0, | 2404 | snd_hda_codec_write(codec, nid, 0, |
2357 | AC_VERB_SET_POWER_STATE, AC_PWRST_D3); | 2405 | AC_VERB_SET_POWER_STATE, AC_PWRST_D3); |
2358 | return 0; | 2406 | return 0; |
2359 | } | 2407 | } |
@@ -2485,6 +2533,9 @@ static int stac92xx_hp_switch_get(struct snd_kcontrol *kcontrol, | |||
2485 | return 0; | 2533 | return 0; |
2486 | } | 2534 | } |
2487 | 2535 | ||
2536 | static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid, | ||
2537 | unsigned char type); | ||
2538 | |||
2488 | static int stac92xx_hp_switch_put(struct snd_kcontrol *kcontrol, | 2539 | static int stac92xx_hp_switch_put(struct snd_kcontrol *kcontrol, |
2489 | struct snd_ctl_elem_value *ucontrol) | 2540 | struct snd_ctl_elem_value *ucontrol) |
2490 | { | 2541 | { |
@@ -2497,7 +2548,7 @@ static int stac92xx_hp_switch_put(struct snd_kcontrol *kcontrol, | |||
2497 | /* check to be sure that the ports are upto date with | 2548 | /* check to be sure that the ports are upto date with |
2498 | * switch changes | 2549 | * switch changes |
2499 | */ | 2550 | */ |
2500 | codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26); | 2551 | stac_issue_unsol_event(codec, nid, STAC_HP_EVENT); |
2501 | 2552 | ||
2502 | return 1; | 2553 | return 1; |
2503 | } | 2554 | } |
@@ -2537,7 +2588,7 @@ static int stac92xx_io_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ | |||
2537 | * appropriately according to the pin direction | 2588 | * appropriately according to the pin direction |
2538 | */ | 2589 | */ |
2539 | if (spec->hp_detect) | 2590 | if (spec->hp_detect) |
2540 | codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26); | 2591 | stac_issue_unsol_event(codec, nid, STAC_HP_EVENT); |
2541 | 2592 | ||
2542 | return 1; | 2593 | return 1; |
2543 | } | 2594 | } |
@@ -2632,28 +2683,16 @@ static int stac92xx_add_control_temp(struct sigmatel_spec *spec, | |||
2632 | { | 2683 | { |
2633 | struct snd_kcontrol_new *knew; | 2684 | struct snd_kcontrol_new *knew; |
2634 | 2685 | ||
2635 | if (spec->num_kctl_used >= spec->num_kctl_alloc) { | 2686 | snd_array_init(&spec->kctls, sizeof(*knew), 32); |
2636 | int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC; | 2687 | knew = snd_array_new(&spec->kctls); |
2637 | 2688 | if (!knew) | |
2638 | knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); /* array + terminator */ | 2689 | return -ENOMEM; |
2639 | if (! knew) | ||
2640 | return -ENOMEM; | ||
2641 | if (spec->kctl_alloc) { | ||
2642 | memcpy(knew, spec->kctl_alloc, sizeof(*knew) * spec->num_kctl_alloc); | ||
2643 | kfree(spec->kctl_alloc); | ||
2644 | } | ||
2645 | spec->kctl_alloc = knew; | ||
2646 | spec->num_kctl_alloc = num; | ||
2647 | } | ||
2648 | |||
2649 | knew = &spec->kctl_alloc[spec->num_kctl_used]; | ||
2650 | *knew = *ktemp; | 2690 | *knew = *ktemp; |
2651 | knew->index = idx; | 2691 | knew->index = idx; |
2652 | knew->name = kstrdup(name, GFP_KERNEL); | 2692 | knew->name = kstrdup(name, GFP_KERNEL); |
2653 | if (!knew->name) | 2693 | if (!knew->name) |
2654 | return -ENOMEM; | 2694 | return -ENOMEM; |
2655 | knew->private_value = val; | 2695 | knew->private_value = val; |
2656 | spec->num_kctl_used++; | ||
2657 | return 0; | 2696 | return 0; |
2658 | } | 2697 | } |
2659 | 2698 | ||
@@ -2674,70 +2713,53 @@ static inline int stac92xx_add_control(struct sigmatel_spec *spec, int type, | |||
2674 | return stac92xx_add_control_idx(spec, type, 0, name, val); | 2713 | return stac92xx_add_control_idx(spec, type, 0, name, val); |
2675 | } | 2714 | } |
2676 | 2715 | ||
2677 | /* flag inputs as additional dynamic lineouts */ | 2716 | /* check whether the line-input can be used as line-out */ |
2678 | static int stac92xx_add_dyn_out_pins(struct hda_codec *codec, struct auto_pin_cfg *cfg) | 2717 | static hda_nid_t check_line_out_switch(struct hda_codec *codec) |
2679 | { | 2718 | { |
2680 | struct sigmatel_spec *spec = codec->spec; | 2719 | struct sigmatel_spec *spec = codec->spec; |
2681 | unsigned int wcaps, wtype; | 2720 | struct auto_pin_cfg *cfg = &spec->autocfg; |
2682 | int i, num_dacs = 0; | 2721 | hda_nid_t nid; |
2683 | 2722 | unsigned int pincap; | |
2684 | /* use the wcaps cache to count all DACs available for line-outs */ | ||
2685 | for (i = 0; i < codec->num_nodes; i++) { | ||
2686 | wcaps = codec->wcaps[i]; | ||
2687 | wtype = (wcaps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; | ||
2688 | 2723 | ||
2689 | if (wtype == AC_WID_AUD_OUT && !(wcaps & AC_WCAP_DIGITAL)) | 2724 | if (cfg->line_out_type != AUTO_PIN_LINE_OUT) |
2690 | num_dacs++; | 2725 | return 0; |
2691 | } | 2726 | nid = cfg->input_pins[AUTO_PIN_LINE]; |
2727 | pincap = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); | ||
2728 | if (pincap & AC_PINCAP_OUT) | ||
2729 | return nid; | ||
2730 | return 0; | ||
2731 | } | ||
2692 | 2732 | ||
2693 | snd_printdd("%s: total dac count=%d\n", __func__, num_dacs); | 2733 | /* check whether the mic-input can be used as line-out */ |
2694 | 2734 | static hda_nid_t check_mic_out_switch(struct hda_codec *codec) | |
2695 | switch (cfg->line_outs) { | 2735 | { |
2696 | case 3: | 2736 | struct sigmatel_spec *spec = codec->spec; |
2697 | /* add line-in as side */ | 2737 | struct auto_pin_cfg *cfg = &spec->autocfg; |
2698 | if (cfg->input_pins[AUTO_PIN_LINE] && num_dacs > 3) { | 2738 | unsigned int def_conf, pincap; |
2699 | cfg->line_out_pins[cfg->line_outs] = | 2739 | unsigned int mic_pin; |
2700 | cfg->input_pins[AUTO_PIN_LINE]; | 2740 | |
2701 | spec->line_switch = 1; | 2741 | if (cfg->line_out_type != AUTO_PIN_LINE_OUT) |
2702 | cfg->line_outs++; | 2742 | return 0; |
2703 | } | 2743 | mic_pin = AUTO_PIN_MIC; |
2704 | break; | 2744 | for (;;) { |
2705 | case 2: | 2745 | hda_nid_t nid = cfg->input_pins[mic_pin]; |
2706 | /* add line-in as clfe and mic as side */ | 2746 | def_conf = snd_hda_codec_read(codec, nid, 0, |
2707 | if (cfg->input_pins[AUTO_PIN_LINE] && num_dacs > 2) { | 2747 | AC_VERB_GET_CONFIG_DEFAULT, 0); |
2708 | cfg->line_out_pins[cfg->line_outs] = | 2748 | /* some laptops have an internal analog microphone |
2709 | cfg->input_pins[AUTO_PIN_LINE]; | 2749 | * which can't be used as a output */ |
2710 | spec->line_switch = 1; | 2750 | if (get_defcfg_connect(def_conf) != AC_JACK_PORT_FIXED) { |
2711 | cfg->line_outs++; | 2751 | pincap = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); |
2712 | } | 2752 | if (pincap & AC_PINCAP_OUT) |
2713 | if (cfg->input_pins[AUTO_PIN_MIC] && num_dacs > 3) { | 2753 | return nid; |
2714 | cfg->line_out_pins[cfg->line_outs] = | ||
2715 | cfg->input_pins[AUTO_PIN_MIC]; | ||
2716 | spec->mic_switch = 1; | ||
2717 | cfg->line_outs++; | ||
2718 | } | ||
2719 | break; | ||
2720 | case 1: | ||
2721 | /* add line-in as surr and mic as clfe */ | ||
2722 | if (cfg->input_pins[AUTO_PIN_LINE] && num_dacs > 1) { | ||
2723 | cfg->line_out_pins[cfg->line_outs] = | ||
2724 | cfg->input_pins[AUTO_PIN_LINE]; | ||
2725 | spec->line_switch = 1; | ||
2726 | cfg->line_outs++; | ||
2727 | } | ||
2728 | if (cfg->input_pins[AUTO_PIN_MIC] && num_dacs > 2) { | ||
2729 | cfg->line_out_pins[cfg->line_outs] = | ||
2730 | cfg->input_pins[AUTO_PIN_MIC]; | ||
2731 | spec->mic_switch = 1; | ||
2732 | cfg->line_outs++; | ||
2733 | } | 2754 | } |
2734 | break; | 2755 | if (mic_pin == AUTO_PIN_MIC) |
2756 | mic_pin = AUTO_PIN_FRONT_MIC; | ||
2757 | else | ||
2758 | break; | ||
2735 | } | 2759 | } |
2736 | |||
2737 | return 0; | 2760 | return 0; |
2738 | } | 2761 | } |
2739 | 2762 | ||
2740 | |||
2741 | static int is_in_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid) | 2763 | static int is_in_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid) |
2742 | { | 2764 | { |
2743 | int i; | 2765 | int i; |
@@ -2750,6 +2772,52 @@ static int is_in_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid) | |||
2750 | return 0; | 2772 | return 0; |
2751 | } | 2773 | } |
2752 | 2774 | ||
2775 | static int check_all_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid) | ||
2776 | { | ||
2777 | int i; | ||
2778 | if (is_in_dac_nids(spec, nid)) | ||
2779 | return 1; | ||
2780 | for (i = 0; i < spec->autocfg.hp_outs; i++) | ||
2781 | if (spec->hp_dacs[i] == nid) | ||
2782 | return 1; | ||
2783 | for (i = 0; i < spec->autocfg.speaker_outs; i++) | ||
2784 | if (spec->speaker_dacs[i] == nid) | ||
2785 | return 1; | ||
2786 | return 0; | ||
2787 | } | ||
2788 | |||
2789 | static hda_nid_t get_unassigned_dac(struct hda_codec *codec, hda_nid_t nid) | ||
2790 | { | ||
2791 | struct sigmatel_spec *spec = codec->spec; | ||
2792 | int j, conn_len; | ||
2793 | hda_nid_t conn[HDA_MAX_CONNECTIONS]; | ||
2794 | unsigned int wcaps, wtype; | ||
2795 | |||
2796 | conn_len = snd_hda_get_connections(codec, nid, conn, | ||
2797 | HDA_MAX_CONNECTIONS); | ||
2798 | for (j = 0; j < conn_len; j++) { | ||
2799 | wcaps = snd_hda_param_read(codec, conn[j], | ||
2800 | AC_PAR_AUDIO_WIDGET_CAP); | ||
2801 | wtype = (wcaps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; | ||
2802 | /* we check only analog outputs */ | ||
2803 | if (wtype != AC_WID_AUD_OUT || (wcaps & AC_WCAP_DIGITAL)) | ||
2804 | continue; | ||
2805 | /* if this route has a free DAC, assign it */ | ||
2806 | if (!check_all_dac_nids(spec, conn[j])) { | ||
2807 | if (conn_len > 1) { | ||
2808 | /* select this DAC in the pin's input mux */ | ||
2809 | snd_hda_codec_write_cache(codec, nid, 0, | ||
2810 | AC_VERB_SET_CONNECT_SEL, j); | ||
2811 | } | ||
2812 | return conn[j]; | ||
2813 | } | ||
2814 | } | ||
2815 | return 0; | ||
2816 | } | ||
2817 | |||
2818 | static int add_spec_dacs(struct sigmatel_spec *spec, hda_nid_t nid); | ||
2819 | static int add_spec_extra_dacs(struct sigmatel_spec *spec, hda_nid_t nid); | ||
2820 | |||
2753 | /* | 2821 | /* |
2754 | * Fill in the dac_nids table from the parsed pin configuration | 2822 | * Fill in the dac_nids table from the parsed pin configuration |
2755 | * This function only works when every pin in line_out_pins[] | 2823 | * This function only works when every pin in line_out_pins[] |
@@ -2757,31 +2825,17 @@ static int is_in_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid) | |||
2757 | * codecs are not connected directly to a DAC, such as the 9200 | 2825 | * codecs are not connected directly to a DAC, such as the 9200 |
2758 | * and 9202/925x. For those, dac_nids[] must be hard-coded. | 2826 | * and 9202/925x. For those, dac_nids[] must be hard-coded. |
2759 | */ | 2827 | */ |
2760 | static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec, | 2828 | static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec) |
2761 | struct auto_pin_cfg *cfg) | ||
2762 | { | 2829 | { |
2763 | struct sigmatel_spec *spec = codec->spec; | 2830 | struct sigmatel_spec *spec = codec->spec; |
2764 | int i, j, conn_len = 0; | 2831 | struct auto_pin_cfg *cfg = &spec->autocfg; |
2765 | hda_nid_t nid, conn[HDA_MAX_CONNECTIONS]; | 2832 | int i; |
2766 | unsigned int wcaps, wtype; | 2833 | hda_nid_t nid, dac; |
2767 | 2834 | ||
2768 | for (i = 0; i < cfg->line_outs; i++) { | 2835 | for (i = 0; i < cfg->line_outs; i++) { |
2769 | nid = cfg->line_out_pins[i]; | 2836 | nid = cfg->line_out_pins[i]; |
2770 | conn_len = snd_hda_get_connections(codec, nid, conn, | 2837 | dac = get_unassigned_dac(codec, nid); |
2771 | HDA_MAX_CONNECTIONS); | 2838 | if (!dac) { |
2772 | for (j = 0; j < conn_len; j++) { | ||
2773 | wcaps = snd_hda_param_read(codec, conn[j], | ||
2774 | AC_PAR_AUDIO_WIDGET_CAP); | ||
2775 | wtype = (wcaps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; | ||
2776 | if (wtype != AC_WID_AUD_OUT || | ||
2777 | (wcaps & AC_WCAP_DIGITAL)) | ||
2778 | continue; | ||
2779 | /* conn[j] is a DAC routed to this line-out */ | ||
2780 | if (!is_in_dac_nids(spec, conn[j])) | ||
2781 | break; | ||
2782 | } | ||
2783 | |||
2784 | if (j == conn_len) { | ||
2785 | if (spec->multiout.num_dacs > 0) { | 2839 | if (spec->multiout.num_dacs > 0) { |
2786 | /* we have already working output pins, | 2840 | /* we have already working output pins, |
2787 | * so let's drop the broken ones again | 2841 | * so let's drop the broken ones again |
@@ -2795,24 +2849,64 @@ static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec, | |||
2795 | __func__, nid); | 2849 | __func__, nid); |
2796 | return -ENODEV; | 2850 | return -ENODEV; |
2797 | } | 2851 | } |
2852 | add_spec_dacs(spec, dac); | ||
2853 | } | ||
2798 | 2854 | ||
2799 | spec->multiout.dac_nids[i] = conn[j]; | 2855 | /* add line-in as output */ |
2800 | spec->multiout.num_dacs++; | 2856 | nid = check_line_out_switch(codec); |
2801 | if (conn_len > 1) { | 2857 | if (nid) { |
2802 | /* select this DAC in the pin's input mux */ | 2858 | dac = get_unassigned_dac(codec, nid); |
2803 | snd_hda_codec_write_cache(codec, nid, 0, | 2859 | if (dac) { |
2804 | AC_VERB_SET_CONNECT_SEL, j); | 2860 | snd_printdd("STAC: Add line-in 0x%x as output %d\n", |
2861 | nid, cfg->line_outs); | ||
2862 | cfg->line_out_pins[cfg->line_outs] = nid; | ||
2863 | cfg->line_outs++; | ||
2864 | spec->line_switch = nid; | ||
2865 | add_spec_dacs(spec, dac); | ||
2866 | } | ||
2867 | } | ||
2868 | /* add mic as output */ | ||
2869 | nid = check_mic_out_switch(codec); | ||
2870 | if (nid) { | ||
2871 | dac = get_unassigned_dac(codec, nid); | ||
2872 | if (dac) { | ||
2873 | snd_printdd("STAC: Add mic-in 0x%x as output %d\n", | ||
2874 | nid, cfg->line_outs); | ||
2875 | cfg->line_out_pins[cfg->line_outs] = nid; | ||
2876 | cfg->line_outs++; | ||
2877 | spec->mic_switch = nid; | ||
2878 | add_spec_dacs(spec, dac); | ||
2879 | } | ||
2880 | } | ||
2805 | 2881 | ||
2882 | for (i = 0; i < cfg->hp_outs; i++) { | ||
2883 | nid = cfg->hp_pins[i]; | ||
2884 | dac = get_unassigned_dac(codec, nid); | ||
2885 | if (dac) { | ||
2886 | if (!spec->multiout.hp_nid) | ||
2887 | spec->multiout.hp_nid = dac; | ||
2888 | else | ||
2889 | add_spec_extra_dacs(spec, dac); | ||
2806 | } | 2890 | } |
2891 | spec->hp_dacs[i] = dac; | ||
2892 | } | ||
2893 | |||
2894 | for (i = 0; i < cfg->speaker_outs; i++) { | ||
2895 | nid = cfg->speaker_pins[i]; | ||
2896 | dac = get_unassigned_dac(codec, nid); | ||
2897 | if (dac) | ||
2898 | add_spec_extra_dacs(spec, dac); | ||
2899 | spec->speaker_dacs[i] = dac; | ||
2807 | } | 2900 | } |
2808 | 2901 | ||
2809 | snd_printd("dac_nids=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n", | 2902 | snd_printd("stac92xx: dac_nids=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n", |
2810 | spec->multiout.num_dacs, | 2903 | spec->multiout.num_dacs, |
2811 | spec->multiout.dac_nids[0], | 2904 | spec->multiout.dac_nids[0], |
2812 | spec->multiout.dac_nids[1], | 2905 | spec->multiout.dac_nids[1], |
2813 | spec->multiout.dac_nids[2], | 2906 | spec->multiout.dac_nids[2], |
2814 | spec->multiout.dac_nids[3], | 2907 | spec->multiout.dac_nids[3], |
2815 | spec->multiout.dac_nids[4]); | 2908 | spec->multiout.dac_nids[4]); |
2909 | |||
2816 | return 0; | 2910 | return 0; |
2817 | } | 2911 | } |
2818 | 2912 | ||
@@ -2837,9 +2931,7 @@ static int create_controls(struct sigmatel_spec *spec, const char *pfx, hda_nid_ | |||
2837 | 2931 | ||
2838 | static int add_spec_dacs(struct sigmatel_spec *spec, hda_nid_t nid) | 2932 | static int add_spec_dacs(struct sigmatel_spec *spec, hda_nid_t nid) |
2839 | { | 2933 | { |
2840 | if (!spec->multiout.hp_nid) | 2934 | if (spec->multiout.num_dacs > 4) { |
2841 | spec->multiout.hp_nid = nid; | ||
2842 | else if (spec->multiout.num_dacs > 4) { | ||
2843 | printk(KERN_WARNING "stac92xx: No space for DAC 0x%x\n", nid); | 2935 | printk(KERN_WARNING "stac92xx: No space for DAC 0x%x\n", nid); |
2844 | return 1; | 2936 | return 1; |
2845 | } else { | 2937 | } else { |
@@ -2849,35 +2941,47 @@ static int add_spec_dacs(struct sigmatel_spec *spec, hda_nid_t nid) | |||
2849 | return 0; | 2941 | return 0; |
2850 | } | 2942 | } |
2851 | 2943 | ||
2852 | static int check_in_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid) | 2944 | static int add_spec_extra_dacs(struct sigmatel_spec *spec, hda_nid_t nid) |
2853 | { | 2945 | { |
2854 | if (is_in_dac_nids(spec, nid)) | 2946 | int i; |
2855 | return 1; | 2947 | for (i = 0; i < ARRAY_SIZE(spec->multiout.extra_out_nid); i++) { |
2948 | if (!spec->multiout.extra_out_nid[i]) { | ||
2949 | spec->multiout.extra_out_nid[i] = nid; | ||
2950 | return 0; | ||
2951 | } | ||
2952 | } | ||
2953 | printk(KERN_WARNING "stac92xx: No space for extra DAC 0x%x\n", nid); | ||
2954 | return 1; | ||
2955 | } | ||
2956 | |||
2957 | static int is_unique_dac(struct sigmatel_spec *spec, hda_nid_t nid) | ||
2958 | { | ||
2959 | int i; | ||
2960 | |||
2961 | if (spec->autocfg.line_outs != 1) | ||
2962 | return 0; | ||
2856 | if (spec->multiout.hp_nid == nid) | 2963 | if (spec->multiout.hp_nid == nid) |
2857 | return 1; | 2964 | return 0; |
2858 | return 0; | 2965 | for (i = 0; i < ARRAY_SIZE(spec->multiout.extra_out_nid); i++) |
2966 | if (spec->multiout.extra_out_nid[i] == nid) | ||
2967 | return 0; | ||
2968 | return 1; | ||
2859 | } | 2969 | } |
2860 | 2970 | ||
2861 | /* add playback controls from the parsed DAC table */ | 2971 | /* add playback controls from the parsed DAC table */ |
2862 | static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec, | 2972 | static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec, |
2863 | const struct auto_pin_cfg *cfg) | 2973 | const struct auto_pin_cfg *cfg) |
2864 | { | 2974 | { |
2975 | struct sigmatel_spec *spec = codec->spec; | ||
2865 | static const char *chname[4] = { | 2976 | static const char *chname[4] = { |
2866 | "Front", "Surround", NULL /*CLFE*/, "Side" | 2977 | "Front", "Surround", NULL /*CLFE*/, "Side" |
2867 | }; | 2978 | }; |
2868 | hda_nid_t nid = 0; | 2979 | hda_nid_t nid = 0; |
2869 | int i, err; | 2980 | int i, err; |
2981 | unsigned int wid_caps; | ||
2870 | 2982 | ||
2871 | struct sigmatel_spec *spec = codec->spec; | 2983 | for (i = 0; i < cfg->line_outs && spec->multiout.dac_nids[i]; i++) { |
2872 | unsigned int wid_caps, pincap; | ||
2873 | |||
2874 | |||
2875 | for (i = 0; i < cfg->line_outs && i < spec->multiout.num_dacs; i++) { | ||
2876 | if (!spec->multiout.dac_nids[i]) | ||
2877 | continue; | ||
2878 | |||
2879 | nid = spec->multiout.dac_nids[i]; | 2984 | nid = spec->multiout.dac_nids[i]; |
2880 | |||
2881 | if (i == 2) { | 2985 | if (i == 2) { |
2882 | /* Center/LFE */ | 2986 | /* Center/LFE */ |
2883 | err = create_controls(spec, "Center", nid, 1); | 2987 | err = create_controls(spec, "Center", nid, 1); |
@@ -2899,16 +3003,24 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec, | |||
2899 | } | 3003 | } |
2900 | 3004 | ||
2901 | } else { | 3005 | } else { |
2902 | err = create_controls(spec, chname[i], nid, 3); | 3006 | const char *name = chname[i]; |
3007 | /* if it's a single DAC, assign a better name */ | ||
3008 | if (!i && is_unique_dac(spec, nid)) { | ||
3009 | switch (cfg->line_out_type) { | ||
3010 | case AUTO_PIN_HP_OUT: | ||
3011 | name = "Headphone"; | ||
3012 | break; | ||
3013 | case AUTO_PIN_SPEAKER_OUT: | ||
3014 | name = "Speaker"; | ||
3015 | break; | ||
3016 | } | ||
3017 | } | ||
3018 | err = create_controls(spec, name, nid, 3); | ||
2903 | if (err < 0) | 3019 | if (err < 0) |
2904 | return err; | 3020 | return err; |
2905 | } | 3021 | } |
2906 | } | 3022 | } |
2907 | 3023 | ||
2908 | if ((spec->multiout.num_dacs - cfg->line_outs) > 0 && | ||
2909 | cfg->hp_outs == 1 && !spec->multiout.hp_nid) | ||
2910 | spec->multiout.hp_nid = nid; | ||
2911 | |||
2912 | if (cfg->hp_outs > 1 && cfg->line_out_type == AUTO_PIN_LINE_OUT) { | 3024 | if (cfg->hp_outs > 1 && cfg->line_out_type == AUTO_PIN_LINE_OUT) { |
2913 | err = stac92xx_add_control(spec, | 3025 | err = stac92xx_add_control(spec, |
2914 | STAC_CTL_WIDGET_HP_SWITCH, | 3026 | STAC_CTL_WIDGET_HP_SWITCH, |
@@ -2919,45 +3031,19 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec, | |||
2919 | } | 3031 | } |
2920 | 3032 | ||
2921 | if (spec->line_switch) { | 3033 | if (spec->line_switch) { |
2922 | nid = cfg->input_pins[AUTO_PIN_LINE]; | 3034 | err = stac92xx_add_control(spec, STAC_CTL_WIDGET_IO_SWITCH, |
2923 | pincap = snd_hda_param_read(codec, nid, | 3035 | "Line In as Output Switch", |
2924 | AC_PAR_PIN_CAP); | 3036 | spec->line_switch << 8); |
2925 | if (pincap & AC_PINCAP_OUT) { | 3037 | if (err < 0) |
2926 | err = stac92xx_add_control(spec, | 3038 | return err; |
2927 | STAC_CTL_WIDGET_IO_SWITCH, | ||
2928 | "Line In as Output Switch", nid << 8); | ||
2929 | if (err < 0) | ||
2930 | return err; | ||
2931 | } | ||
2932 | } | 3039 | } |
2933 | 3040 | ||
2934 | if (spec->mic_switch) { | 3041 | if (spec->mic_switch) { |
2935 | unsigned int def_conf; | 3042 | err = stac92xx_add_control(spec, STAC_CTL_WIDGET_IO_SWITCH, |
2936 | unsigned int mic_pin = AUTO_PIN_MIC; | 3043 | "Mic as Output Switch", |
2937 | again: | 3044 | (spec->mic_switch << 8) | 1); |
2938 | nid = cfg->input_pins[mic_pin]; | 3045 | if (err < 0) |
2939 | def_conf = snd_hda_codec_read(codec, nid, 0, | 3046 | return err; |
2940 | AC_VERB_GET_CONFIG_DEFAULT, 0); | ||
2941 | /* some laptops have an internal analog microphone | ||
2942 | * which can't be used as a output */ | ||
2943 | if (get_defcfg_connect(def_conf) != AC_JACK_PORT_FIXED) { | ||
2944 | pincap = snd_hda_param_read(codec, nid, | ||
2945 | AC_PAR_PIN_CAP); | ||
2946 | if (pincap & AC_PINCAP_OUT) { | ||
2947 | err = stac92xx_add_control(spec, | ||
2948 | STAC_CTL_WIDGET_IO_SWITCH, | ||
2949 | "Mic as Output Switch", (nid << 8) | 1); | ||
2950 | nid = snd_hda_codec_read(codec, nid, 0, | ||
2951 | AC_VERB_GET_CONNECT_LIST, 0) & 0xff; | ||
2952 | if (!check_in_dac_nids(spec, nid)) | ||
2953 | add_spec_dacs(spec, nid); | ||
2954 | if (err < 0) | ||
2955 | return err; | ||
2956 | } | ||
2957 | } else if (mic_pin == AUTO_PIN_MIC) { | ||
2958 | mic_pin = AUTO_PIN_FRONT_MIC; | ||
2959 | goto again; | ||
2960 | } | ||
2961 | } | 3047 | } |
2962 | 3048 | ||
2963 | return 0; | 3049 | return 0; |
@@ -2969,55 +3055,39 @@ static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec, | |||
2969 | { | 3055 | { |
2970 | struct sigmatel_spec *spec = codec->spec; | 3056 | struct sigmatel_spec *spec = codec->spec; |
2971 | hda_nid_t nid; | 3057 | hda_nid_t nid; |
2972 | int i, old_num_dacs, err; | 3058 | int i, err, nums; |
2973 | 3059 | ||
2974 | old_num_dacs = spec->multiout.num_dacs; | 3060 | nums = 0; |
2975 | for (i = 0; i < cfg->hp_outs; i++) { | 3061 | for (i = 0; i < cfg->hp_outs; i++) { |
3062 | static const char *pfxs[] = { | ||
3063 | "Headphone", "Headphone2", "Headphone3", | ||
3064 | }; | ||
2976 | unsigned int wid_caps = get_wcaps(codec, cfg->hp_pins[i]); | 3065 | unsigned int wid_caps = get_wcaps(codec, cfg->hp_pins[i]); |
2977 | if (wid_caps & AC_WCAP_UNSOL_CAP) | 3066 | if (wid_caps & AC_WCAP_UNSOL_CAP) |
2978 | spec->hp_detect = 1; | 3067 | spec->hp_detect = 1; |
2979 | nid = snd_hda_codec_read(codec, cfg->hp_pins[i], 0, | 3068 | if (nums >= ARRAY_SIZE(pfxs)) |
2980 | AC_VERB_GET_CONNECT_LIST, 0) & 0xff; | ||
2981 | if (check_in_dac_nids(spec, nid)) | ||
2982 | nid = 0; | ||
2983 | if (! nid) | ||
2984 | continue; | 3069 | continue; |
2985 | add_spec_dacs(spec, nid); | 3070 | nid = spec->hp_dacs[i]; |
2986 | } | 3071 | if (!nid) |
2987 | for (i = 0; i < cfg->speaker_outs; i++) { | ||
2988 | nid = snd_hda_codec_read(codec, cfg->speaker_pins[i], 0, | ||
2989 | AC_VERB_GET_CONNECT_LIST, 0) & 0xff; | ||
2990 | if (check_in_dac_nids(spec, nid)) | ||
2991 | nid = 0; | ||
2992 | if (! nid) | ||
2993 | continue; | 3072 | continue; |
2994 | add_spec_dacs(spec, nid); | 3073 | err = create_controls(spec, pfxs[nums++], nid, 3); |
2995 | } | 3074 | if (err < 0) |
2996 | for (i = 0; i < cfg->line_outs; i++) { | 3075 | return err; |
2997 | nid = snd_hda_codec_read(codec, cfg->line_out_pins[i], 0, | ||
2998 | AC_VERB_GET_CONNECT_LIST, 0) & 0xff; | ||
2999 | if (check_in_dac_nids(spec, nid)) | ||
3000 | nid = 0; | ||
3001 | if (! nid) | ||
3002 | continue; | ||
3003 | add_spec_dacs(spec, nid); | ||
3004 | } | 3076 | } |
3005 | for (i = old_num_dacs; i < spec->multiout.num_dacs; i++) { | 3077 | nums = 0; |
3078 | for (i = 0; i < cfg->speaker_outs; i++) { | ||
3006 | static const char *pfxs[] = { | 3079 | static const char *pfxs[] = { |
3007 | "Speaker", "External Speaker", "Speaker2", | 3080 | "Speaker", "External Speaker", "Speaker2", |
3008 | }; | 3081 | }; |
3009 | err = create_controls(spec, pfxs[i - old_num_dacs], | 3082 | if (nums >= ARRAY_SIZE(pfxs)) |
3010 | spec->multiout.dac_nids[i], 3); | 3083 | continue; |
3011 | if (err < 0) | 3084 | nid = spec->speaker_dacs[i]; |
3012 | return err; | 3085 | if (!nid) |
3013 | } | 3086 | continue; |
3014 | if (spec->multiout.hp_nid) { | 3087 | err = create_controls(spec, pfxs[nums++], nid, 3); |
3015 | err = create_controls(spec, "Headphone", | ||
3016 | spec->multiout.hp_nid, 3); | ||
3017 | if (err < 0) | 3088 | if (err < 0) |
3018 | return err; | 3089 | return err; |
3019 | } | 3090 | } |
3020 | |||
3021 | return 0; | 3091 | return 0; |
3022 | } | 3092 | } |
3023 | 3093 | ||
@@ -3355,7 +3425,6 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out | |||
3355 | { | 3425 | { |
3356 | struct sigmatel_spec *spec = codec->spec; | 3426 | struct sigmatel_spec *spec = codec->spec; |
3357 | int err; | 3427 | int err; |
3358 | int hp_speaker_swap = 0; | ||
3359 | 3428 | ||
3360 | if ((err = snd_hda_parse_pin_def_config(codec, | 3429 | if ((err = snd_hda_parse_pin_def_config(codec, |
3361 | &spec->autocfg, | 3430 | &spec->autocfg, |
@@ -3373,13 +3442,15 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out | |||
3373 | * speaker_outs so that the following routines can handle | 3442 | * speaker_outs so that the following routines can handle |
3374 | * HP pins as primary outputs. | 3443 | * HP pins as primary outputs. |
3375 | */ | 3444 | */ |
3445 | snd_printdd("stac92xx: Enabling multi-HPs workaround\n"); | ||
3376 | memcpy(spec->autocfg.speaker_pins, spec->autocfg.line_out_pins, | 3446 | memcpy(spec->autocfg.speaker_pins, spec->autocfg.line_out_pins, |
3377 | sizeof(spec->autocfg.line_out_pins)); | 3447 | sizeof(spec->autocfg.line_out_pins)); |
3378 | spec->autocfg.speaker_outs = spec->autocfg.line_outs; | 3448 | spec->autocfg.speaker_outs = spec->autocfg.line_outs; |
3379 | memcpy(spec->autocfg.line_out_pins, spec->autocfg.hp_pins, | 3449 | memcpy(spec->autocfg.line_out_pins, spec->autocfg.hp_pins, |
3380 | sizeof(spec->autocfg.hp_pins)); | 3450 | sizeof(spec->autocfg.hp_pins)); |
3381 | spec->autocfg.line_outs = spec->autocfg.hp_outs; | 3451 | spec->autocfg.line_outs = spec->autocfg.hp_outs; |
3382 | hp_speaker_swap = 1; | 3452 | spec->autocfg.line_out_type = AUTO_PIN_HP_OUT; |
3453 | spec->autocfg.hp_outs = 0; | ||
3383 | } | 3454 | } |
3384 | if (spec->autocfg.mono_out_pin) { | 3455 | if (spec->autocfg.mono_out_pin) { |
3385 | int dir = get_wcaps(codec, spec->autocfg.mono_out_pin) & | 3456 | int dir = get_wcaps(codec, spec->autocfg.mono_out_pin) & |
@@ -3431,11 +3502,11 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out | |||
3431 | AC_PINCTL_OUT_EN); | 3502 | AC_PINCTL_OUT_EN); |
3432 | } | 3503 | } |
3433 | 3504 | ||
3434 | if ((err = stac92xx_add_dyn_out_pins(codec, &spec->autocfg)) < 0) | 3505 | if (!spec->multiout.num_dacs) { |
3435 | return err; | 3506 | err = stac92xx_auto_fill_dac_nids(codec); |
3436 | if (spec->multiout.num_dacs == 0) | 3507 | if (err < 0) |
3437 | if ((err = stac92xx_auto_fill_dac_nids(codec, &spec->autocfg)) < 0) | ||
3438 | return err; | 3508 | return err; |
3509 | } | ||
3439 | 3510 | ||
3440 | err = stac92xx_auto_create_multi_out_ctls(codec, &spec->autocfg); | 3511 | err = stac92xx_auto_create_multi_out_ctls(codec, &spec->autocfg); |
3441 | 3512 | ||
@@ -3473,19 +3544,6 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out | |||
3473 | } | 3544 | } |
3474 | #endif | 3545 | #endif |
3475 | 3546 | ||
3476 | if (hp_speaker_swap == 1) { | ||
3477 | /* Restore the hp_outs and line_outs */ | ||
3478 | memcpy(spec->autocfg.hp_pins, spec->autocfg.line_out_pins, | ||
3479 | sizeof(spec->autocfg.line_out_pins)); | ||
3480 | spec->autocfg.hp_outs = spec->autocfg.line_outs; | ||
3481 | memcpy(spec->autocfg.line_out_pins, spec->autocfg.speaker_pins, | ||
3482 | sizeof(spec->autocfg.speaker_pins)); | ||
3483 | spec->autocfg.line_outs = spec->autocfg.speaker_outs; | ||
3484 | memset(spec->autocfg.speaker_pins, 0, | ||
3485 | sizeof(spec->autocfg.speaker_pins)); | ||
3486 | spec->autocfg.speaker_outs = 0; | ||
3487 | } | ||
3488 | |||
3489 | err = stac92xx_auto_create_hp_ctls(codec, &spec->autocfg); | 3547 | err = stac92xx_auto_create_hp_ctls(codec, &spec->autocfg); |
3490 | 3548 | ||
3491 | if (err < 0) | 3549 | if (err < 0) |
@@ -3530,11 +3588,12 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out | |||
3530 | if (dig_in && spec->autocfg.dig_in_pin) | 3588 | if (dig_in && spec->autocfg.dig_in_pin) |
3531 | spec->dig_in_nid = dig_in; | 3589 | spec->dig_in_nid = dig_in; |
3532 | 3590 | ||
3533 | if (spec->kctl_alloc) | 3591 | if (spec->kctls.list) |
3534 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 3592 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
3535 | 3593 | ||
3536 | spec->input_mux = &spec->private_imux; | 3594 | spec->input_mux = &spec->private_imux; |
3537 | spec->dinput_mux = &spec->private_dimux; | 3595 | if (!spec->dinput_mux) |
3596 | spec->dinput_mux = &spec->private_dimux; | ||
3538 | spec->sinput_mux = &spec->private_smux; | 3597 | spec->sinput_mux = &spec->private_smux; |
3539 | spec->mono_mux = &spec->private_mono_mux; | 3598 | spec->mono_mux = &spec->private_mono_mux; |
3540 | spec->amp_mux = &spec->private_amp_mux; | 3599 | spec->amp_mux = &spec->private_amp_mux; |
@@ -3638,8 +3697,8 @@ static int stac9200_parse_auto_config(struct hda_codec *codec) | |||
3638 | if (spec->autocfg.dig_in_pin) | 3697 | if (spec->autocfg.dig_in_pin) |
3639 | spec->dig_in_nid = 0x04; | 3698 | spec->dig_in_nid = 0x04; |
3640 | 3699 | ||
3641 | if (spec->kctl_alloc) | 3700 | if (spec->kctls.list) |
3642 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 3701 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
3643 | 3702 | ||
3644 | spec->input_mux = &spec->private_imux; | 3703 | spec->input_mux = &spec->private_imux; |
3645 | spec->dinput_mux = &spec->private_dimux; | 3704 | spec->dinput_mux = &spec->private_dimux; |
@@ -3683,13 +3742,101 @@ static void stac_gpio_set(struct hda_codec *codec, unsigned int mask, | |||
3683 | AC_VERB_SET_GPIO_DATA, gpiostate); /* sync */ | 3742 | AC_VERB_SET_GPIO_DATA, gpiostate); /* sync */ |
3684 | } | 3743 | } |
3685 | 3744 | ||
3745 | static int stac92xx_add_jack(struct hda_codec *codec, | ||
3746 | hda_nid_t nid, int type) | ||
3747 | { | ||
3748 | #ifdef CONFIG_SND_JACK | ||
3749 | struct sigmatel_spec *spec = codec->spec; | ||
3750 | struct sigmatel_jack *jack; | ||
3751 | int def_conf = snd_hda_codec_read(codec, nid, | ||
3752 | 0, AC_VERB_GET_CONFIG_DEFAULT, 0); | ||
3753 | int connectivity = get_defcfg_connect(def_conf); | ||
3754 | char name[32]; | ||
3755 | |||
3756 | if (connectivity && connectivity != AC_JACK_PORT_FIXED) | ||
3757 | return 0; | ||
3758 | |||
3759 | snd_array_init(&spec->jacks, sizeof(*jack), 32); | ||
3760 | jack = snd_array_new(&spec->jacks); | ||
3761 | if (!jack) | ||
3762 | return -ENOMEM; | ||
3763 | jack->nid = nid; | ||
3764 | jack->type = type; | ||
3765 | |||
3766 | sprintf(name, "%s at %s %s Jack", | ||
3767 | snd_hda_get_jack_type(def_conf), | ||
3768 | snd_hda_get_jack_connectivity(def_conf), | ||
3769 | snd_hda_get_jack_location(def_conf)); | ||
3770 | |||
3771 | return snd_jack_new(codec->bus->card, name, type, &jack->jack); | ||
3772 | #else | ||
3773 | return 0; | ||
3774 | #endif | ||
3775 | } | ||
3776 | |||
3777 | static int stac_add_event(struct sigmatel_spec *spec, hda_nid_t nid, | ||
3778 | unsigned char type, int data) | ||
3779 | { | ||
3780 | struct sigmatel_event *event; | ||
3781 | |||
3782 | snd_array_init(&spec->events, sizeof(*event), 32); | ||
3783 | event = snd_array_new(&spec->events); | ||
3784 | if (!event) | ||
3785 | return -ENOMEM; | ||
3786 | event->nid = nid; | ||
3787 | event->type = type; | ||
3788 | event->tag = spec->events.used; | ||
3789 | event->data = data; | ||
3790 | |||
3791 | return event->tag; | ||
3792 | } | ||
3793 | |||
3794 | static struct sigmatel_event *stac_get_event(struct hda_codec *codec, | ||
3795 | hda_nid_t nid, unsigned char type) | ||
3796 | { | ||
3797 | struct sigmatel_spec *spec = codec->spec; | ||
3798 | struct sigmatel_event *event = spec->events.list; | ||
3799 | int i; | ||
3800 | |||
3801 | for (i = 0; i < spec->events.used; i++, event++) { | ||
3802 | if (event->nid == nid && event->type == type) | ||
3803 | return event; | ||
3804 | } | ||
3805 | return NULL; | ||
3806 | } | ||
3807 | |||
3808 | static struct sigmatel_event *stac_get_event_from_tag(struct hda_codec *codec, | ||
3809 | unsigned char tag) | ||
3810 | { | ||
3811 | struct sigmatel_spec *spec = codec->spec; | ||
3812 | struct sigmatel_event *event = spec->events.list; | ||
3813 | int i; | ||
3814 | |||
3815 | for (i = 0; i < spec->events.used; i++, event++) { | ||
3816 | if (event->tag == tag) | ||
3817 | return event; | ||
3818 | } | ||
3819 | return NULL; | ||
3820 | } | ||
3821 | |||
3686 | static void enable_pin_detect(struct hda_codec *codec, hda_nid_t nid, | 3822 | static void enable_pin_detect(struct hda_codec *codec, hda_nid_t nid, |
3687 | unsigned int event) | 3823 | unsigned int type) |
3688 | { | 3824 | { |
3689 | if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) | 3825 | struct sigmatel_event *event; |
3690 | snd_hda_codec_write_cache(codec, nid, 0, | 3826 | int tag; |
3691 | AC_VERB_SET_UNSOLICITED_ENABLE, | 3827 | |
3692 | (AC_USRSP_EN | event)); | 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); | ||
3693 | } | 3840 | } |
3694 | 3841 | ||
3695 | static int is_nid_hp_pin(struct auto_pin_cfg *cfg, hda_nid_t nid) | 3842 | static int is_nid_hp_pin(struct auto_pin_cfg *cfg, hda_nid_t nid) |
@@ -3709,9 +3856,8 @@ static void stac92xx_power_down(struct hda_codec *codec) | |||
3709 | /* power down inactive DACs */ | 3856 | /* power down inactive DACs */ |
3710 | hda_nid_t *dac; | 3857 | hda_nid_t *dac; |
3711 | for (dac = spec->dac_list; *dac; dac++) | 3858 | for (dac = spec->dac_list; *dac; dac++) |
3712 | if (!is_in_dac_nids(spec, *dac) && | 3859 | if (!check_all_dac_nids(spec, *dac)) |
3713 | spec->multiout.hp_nid != *dac) | 3860 | snd_hda_codec_write(codec, *dac, 0, |
3714 | snd_hda_codec_write_cache(codec, *dac, 0, | ||
3715 | AC_VERB_SET_POWER_STATE, AC_PWRST_D3); | 3861 | AC_VERB_SET_POWER_STATE, AC_PWRST_D3); |
3716 | } | 3862 | } |
3717 | 3863 | ||
@@ -3730,7 +3876,7 @@ static int stac92xx_init(struct hda_codec *codec) | |||
3730 | /* power down adcs initially */ | 3876 | /* power down adcs initially */ |
3731 | if (spec->powerdown_adcs) | 3877 | if (spec->powerdown_adcs) |
3732 | for (i = 0; i < spec->num_adcs; i++) | 3878 | for (i = 0; i < spec->num_adcs; i++) |
3733 | snd_hda_codec_write_cache(codec, | 3879 | snd_hda_codec_write(codec, |
3734 | spec->adc_nids[i], 0, | 3880 | spec->adc_nids[i], 0, |
3735 | AC_VERB_SET_POWER_STATE, AC_PWRST_D3); | 3881 | AC_VERB_SET_POWER_STATE, AC_PWRST_D3); |
3736 | 3882 | ||
@@ -3746,37 +3892,51 @@ static int stac92xx_init(struct hda_codec *codec) | |||
3746 | /* set up pins */ | 3892 | /* set up pins */ |
3747 | if (spec->hp_detect) { | 3893 | if (spec->hp_detect) { |
3748 | /* Enable unsolicited responses on the HP widget */ | 3894 | /* Enable unsolicited responses on the HP widget */ |
3749 | for (i = 0; i < cfg->hp_outs; i++) | 3895 | for (i = 0; i < cfg->hp_outs; i++) { |
3750 | enable_pin_detect(codec, cfg->hp_pins[i], | 3896 | hda_nid_t nid = cfg->hp_pins[i]; |
3751 | STAC_HP_EVENT); | 3897 | enable_pin_detect(codec, nid, STAC_HP_EVENT); |
3898 | } | ||
3752 | /* force to enable the first line-out; the others are set up | 3899 | /* force to enable the first line-out; the others are set up |
3753 | * in unsol_event | 3900 | * in unsol_event |
3754 | */ | 3901 | */ |
3755 | stac92xx_auto_set_pinctl(codec, spec->autocfg.line_out_pins[0], | 3902 | stac92xx_auto_set_pinctl(codec, spec->autocfg.line_out_pins[0], |
3756 | AC_PINCTL_OUT_EN); | 3903 | AC_PINCTL_OUT_EN); |
3757 | stac92xx_auto_init_hp_out(codec); | ||
3758 | /* fake event to set up pins */ | 3904 | /* fake event to set up pins */ |
3759 | codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26); | 3905 | stac_issue_unsol_event(codec, spec->autocfg.hp_pins[0], |
3906 | STAC_HP_EVENT); | ||
3760 | } else { | 3907 | } else { |
3761 | stac92xx_auto_init_multi_out(codec); | 3908 | stac92xx_auto_init_multi_out(codec); |
3762 | stac92xx_auto_init_hp_out(codec); | 3909 | stac92xx_auto_init_hp_out(codec); |
3910 | for (i = 0; i < cfg->hp_outs; i++) | ||
3911 | stac_toggle_power_map(codec, cfg->hp_pins[i], 1); | ||
3763 | } | 3912 | } |
3764 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 3913 | for (i = 0; i < AUTO_PIN_LAST; i++) { |
3765 | hda_nid_t nid = cfg->input_pins[i]; | 3914 | hda_nid_t nid = cfg->input_pins[i]; |
3766 | if (nid) { | 3915 | if (nid) { |
3767 | unsigned int pinctl; | 3916 | unsigned int pinctl, conf; |
3768 | if (i == AUTO_PIN_MIC || i == AUTO_PIN_FRONT_MIC) { | 3917 | if (i == AUTO_PIN_MIC || i == AUTO_PIN_FRONT_MIC) { |
3769 | /* for mic pins, force to initialize */ | 3918 | /* for mic pins, force to initialize */ |
3770 | pinctl = stac92xx_get_vref(codec, nid); | 3919 | pinctl = stac92xx_get_vref(codec, nid); |
3920 | pinctl |= AC_PINCTL_IN_EN; | ||
3921 | stac92xx_auto_set_pinctl(codec, nid, pinctl); | ||
3771 | } else { | 3922 | } else { |
3772 | pinctl = snd_hda_codec_read(codec, nid, 0, | 3923 | pinctl = snd_hda_codec_read(codec, nid, 0, |
3773 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | 3924 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); |
3774 | /* if PINCTL already set then skip */ | 3925 | /* if PINCTL already set then skip */ |
3775 | if (pinctl & AC_PINCTL_IN_EN) | 3926 | if (!(pinctl & AC_PINCTL_IN_EN)) { |
3776 | continue; | 3927 | pinctl |= AC_PINCTL_IN_EN; |
3928 | stac92xx_auto_set_pinctl(codec, nid, | ||
3929 | pinctl); | ||
3930 | } | ||
3931 | } | ||
3932 | conf = snd_hda_codec_read(codec, nid, 0, | ||
3933 | AC_VERB_GET_CONFIG_DEFAULT, 0); | ||
3934 | if (get_defcfg_connect(conf) != AC_JACK_PORT_FIXED) { | ||
3935 | enable_pin_detect(codec, nid, | ||
3936 | STAC_INSERT_EVENT); | ||
3937 | stac_issue_unsol_event(codec, nid, | ||
3938 | STAC_INSERT_EVENT); | ||
3777 | } | 3939 | } |
3778 | pinctl |= AC_PINCTL_IN_EN; | ||
3779 | stac92xx_auto_set_pinctl(codec, nid, pinctl); | ||
3780 | } | 3940 | } |
3781 | } | 3941 | } |
3782 | for (i = 0; i < spec->num_dmics; i++) | 3942 | for (i = 0; i < spec->num_dmics; i++) |
@@ -3791,9 +3951,14 @@ static int stac92xx_init(struct hda_codec *codec) | |||
3791 | for (i = 0; i < spec->num_pwrs; i++) { | 3951 | for (i = 0; i < spec->num_pwrs; i++) { |
3792 | hda_nid_t nid = spec->pwr_nids[i]; | 3952 | hda_nid_t nid = spec->pwr_nids[i]; |
3793 | int pinctl, def_conf; | 3953 | int pinctl, def_conf; |
3794 | int event = STAC_PWR_EVENT; | ||
3795 | 3954 | ||
3796 | if (is_nid_hp_pin(cfg, nid) && spec->hp_detect) | 3955 | /* power on when no jack detection is available */ |
3956 | if (!spec->hp_detect) { | ||
3957 | stac_toggle_power_map(codec, nid, 1); | ||
3958 | continue; | ||
3959 | } | ||
3960 | |||
3961 | if (is_nid_hp_pin(cfg, nid)) | ||
3797 | continue; /* already has an unsol event */ | 3962 | continue; /* already has an unsol event */ |
3798 | 3963 | ||
3799 | pinctl = snd_hda_codec_read(codec, nid, 0, | 3964 | pinctl = snd_hda_codec_read(codec, nid, 0, |
@@ -3802,8 +3967,10 @@ static int stac92xx_init(struct hda_codec *codec) | |||
3802 | * any attempts on powering down a input port cause the | 3967 | * any attempts on powering down a input port cause the |
3803 | * referenced VREF to act quirky. | 3968 | * referenced VREF to act quirky. |
3804 | */ | 3969 | */ |
3805 | if (pinctl & AC_PINCTL_IN_EN) | 3970 | if (pinctl & AC_PINCTL_IN_EN) { |
3971 | stac_toggle_power_map(codec, nid, 1); | ||
3806 | continue; | 3972 | continue; |
3973 | } | ||
3807 | def_conf = snd_hda_codec_read(codec, nid, 0, | 3974 | def_conf = snd_hda_codec_read(codec, nid, 0, |
3808 | AC_VERB_GET_CONFIG_DEFAULT, 0); | 3975 | AC_VERB_GET_CONFIG_DEFAULT, 0); |
3809 | def_conf = get_defcfg_connect(def_conf); | 3976 | def_conf = get_defcfg_connect(def_conf); |
@@ -3814,30 +3981,54 @@ static int stac92xx_init(struct hda_codec *codec) | |||
3814 | stac_toggle_power_map(codec, nid, 1); | 3981 | stac_toggle_power_map(codec, nid, 1); |
3815 | continue; | 3982 | continue; |
3816 | } | 3983 | } |
3817 | enable_pin_detect(codec, spec->pwr_nids[i], event | i); | 3984 | if (!stac_get_event(codec, nid, STAC_INSERT_EVENT)) { |
3818 | codec->patch_ops.unsol_event(codec, (event | i) << 26); | 3985 | enable_pin_detect(codec, nid, STAC_PWR_EVENT); |
3986 | stac_issue_unsol_event(codec, nid, STAC_PWR_EVENT); | ||
3987 | } | ||
3819 | } | 3988 | } |
3820 | if (spec->dac_list) | 3989 | if (spec->dac_list) |
3821 | stac92xx_power_down(codec); | 3990 | stac92xx_power_down(codec); |
3822 | return 0; | 3991 | return 0; |
3823 | } | 3992 | } |
3824 | 3993 | ||
3994 | static void stac92xx_free_jacks(struct hda_codec *codec) | ||
3995 | { | ||
3996 | #ifdef CONFIG_SND_JACK | ||
3997 | /* free jack instances manually when clearing/reconfiguring */ | ||
3998 | struct sigmatel_spec *spec = codec->spec; | ||
3999 | if (!codec->bus->shutdown && spec->jacks.list) { | ||
4000 | struct sigmatel_jack *jacks = spec->jacks.list; | ||
4001 | int i; | ||
4002 | for (i = 0; i < spec->jacks.used; i++) | ||
4003 | snd_device_free(codec->bus->card, &jacks[i].jack); | ||
4004 | } | ||
4005 | snd_array_free(&spec->jacks); | ||
4006 | #endif | ||
4007 | } | ||
4008 | |||
4009 | static void stac92xx_free_kctls(struct hda_codec *codec) | ||
4010 | { | ||
4011 | struct sigmatel_spec *spec = codec->spec; | ||
4012 | |||
4013 | if (spec->kctls.list) { | ||
4014 | struct snd_kcontrol_new *kctl = spec->kctls.list; | ||
4015 | int i; | ||
4016 | for (i = 0; i < spec->kctls.used; i++) | ||
4017 | kfree(kctl[i].name); | ||
4018 | } | ||
4019 | snd_array_free(&spec->kctls); | ||
4020 | } | ||
4021 | |||
3825 | static void stac92xx_free(struct hda_codec *codec) | 4022 | static void stac92xx_free(struct hda_codec *codec) |
3826 | { | 4023 | { |
3827 | struct sigmatel_spec *spec = codec->spec; | 4024 | struct sigmatel_spec *spec = codec->spec; |
3828 | int i; | ||
3829 | 4025 | ||
3830 | if (! spec) | 4026 | if (! spec) |
3831 | return; | 4027 | return; |
3832 | 4028 | ||
3833 | if (spec->kctl_alloc) { | 4029 | kfree(spec->pin_configs); |
3834 | for (i = 0; i < spec->num_kctl_used; i++) | 4030 | stac92xx_free_jacks(codec); |
3835 | kfree(spec->kctl_alloc[i].name); | 4031 | snd_array_free(&spec->events); |
3836 | kfree(spec->kctl_alloc); | ||
3837 | } | ||
3838 | |||
3839 | if (spec->bios_pin_configs) | ||
3840 | kfree(spec->bios_pin_configs); | ||
3841 | 4032 | ||
3842 | kfree(spec); | 4033 | kfree(spec); |
3843 | snd_hda_detach_beep_device(codec); | 4034 | snd_hda_detach_beep_device(codec); |
@@ -3856,11 +4047,7 @@ static void stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid, | |||
3856 | * "xxx as Output" mixer switch | 4047 | * "xxx as Output" mixer switch |
3857 | */ | 4048 | */ |
3858 | struct sigmatel_spec *spec = codec->spec; | 4049 | struct sigmatel_spec *spec = codec->spec; |
3859 | struct auto_pin_cfg *cfg = &spec->autocfg; | 4050 | if (nid == spec->line_switch || nid == spec->mic_switch) |
3860 | if ((nid == cfg->input_pins[AUTO_PIN_LINE] && | ||
3861 | spec->line_switch) || | ||
3862 | (nid == cfg->input_pins[AUTO_PIN_MIC] && | ||
3863 | spec->mic_switch)) | ||
3864 | return; | 4051 | return; |
3865 | } | 4052 | } |
3866 | 4053 | ||
@@ -3884,20 +4071,13 @@ static void stac92xx_reset_pinctl(struct hda_codec *codec, hda_nid_t nid, | |||
3884 | pin_ctl & ~flag); | 4071 | pin_ctl & ~flag); |
3885 | } | 4072 | } |
3886 | 4073 | ||
3887 | static int get_hp_pin_presence(struct hda_codec *codec, hda_nid_t nid) | 4074 | static int get_pin_presence(struct hda_codec *codec, hda_nid_t nid) |
3888 | { | 4075 | { |
3889 | if (!nid) | 4076 | if (!nid) |
3890 | return 0; | 4077 | return 0; |
3891 | if (snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_SENSE, 0x00) | 4078 | if (snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_SENSE, 0x00) |
3892 | & (1 << 31)) { | 4079 | & (1 << 31)) |
3893 | unsigned int pinctl; | 4080 | return 1; |
3894 | pinctl = snd_hda_codec_read(codec, nid, 0, | ||
3895 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | ||
3896 | if (pinctl & AC_PINCTL_IN_EN) | ||
3897 | return 0; /* mic- or line-input */ | ||
3898 | else | ||
3899 | return 1; /* HP-output */ | ||
3900 | } | ||
3901 | return 0; | 4081 | return 0; |
3902 | } | 4082 | } |
3903 | 4083 | ||
@@ -3909,11 +4089,9 @@ static int no_hp_sensing(struct sigmatel_spec *spec, int i) | |||
3909 | struct auto_pin_cfg *cfg = &spec->autocfg; | 4089 | struct auto_pin_cfg *cfg = &spec->autocfg; |
3910 | 4090 | ||
3911 | /* ignore sensing of shared line and mic jacks */ | 4091 | /* ignore sensing of shared line and mic jacks */ |
3912 | if (spec->line_switch && | 4092 | if (cfg->hp_pins[i] == spec->line_switch) |
3913 | cfg->hp_pins[i] == cfg->input_pins[AUTO_PIN_LINE]) | ||
3914 | return 1; | 4093 | return 1; |
3915 | if (spec->mic_switch && | 4094 | if (cfg->hp_pins[i] == spec->mic_switch) |
3916 | cfg->hp_pins[i] == cfg->input_pins[AUTO_PIN_MIC]) | ||
3917 | return 1; | 4095 | return 1; |
3918 | /* ignore if the pin is set as line-out */ | 4096 | /* ignore if the pin is set as line-out */ |
3919 | if (cfg->hp_pins[i] == spec->hp_switch) | 4097 | if (cfg->hp_pins[i] == spec->hp_switch) |
@@ -3921,7 +4099,7 @@ static int no_hp_sensing(struct sigmatel_spec *spec, int i) | |||
3921 | return 0; | 4099 | return 0; |
3922 | } | 4100 | } |
3923 | 4101 | ||
3924 | static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res) | 4102 | static void stac92xx_hp_detect(struct hda_codec *codec) |
3925 | { | 4103 | { |
3926 | struct sigmatel_spec *spec = codec->spec; | 4104 | struct sigmatel_spec *spec = codec->spec; |
3927 | struct auto_pin_cfg *cfg = &spec->autocfg; | 4105 | struct auto_pin_cfg *cfg = &spec->autocfg; |
@@ -3937,7 +4115,14 @@ static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res) | |||
3937 | break; | 4115 | break; |
3938 | if (no_hp_sensing(spec, i)) | 4116 | if (no_hp_sensing(spec, i)) |
3939 | continue; | 4117 | continue; |
3940 | presence = get_hp_pin_presence(codec, cfg->hp_pins[i]); | 4118 | presence = get_pin_presence(codec, cfg->hp_pins[i]); |
4119 | if (presence) { | ||
4120 | unsigned int pinctl; | ||
4121 | pinctl = snd_hda_codec_read(codec, cfg->hp_pins[i], 0, | ||
4122 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | ||
4123 | if (pinctl & AC_PINCTL_IN_EN) | ||
4124 | presence = 0; /* mic- or line-input */ | ||
4125 | } | ||
3941 | } | 4126 | } |
3942 | 4127 | ||
3943 | if (presence) { | 4128 | if (presence) { |
@@ -4014,50 +4199,145 @@ static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid, | |||
4014 | 4199 | ||
4015 | static void stac92xx_pin_sense(struct hda_codec *codec, hda_nid_t nid) | 4200 | static void stac92xx_pin_sense(struct hda_codec *codec, hda_nid_t nid) |
4016 | { | 4201 | { |
4017 | stac_toggle_power_map(codec, nid, get_hp_pin_presence(codec, nid)); | 4202 | stac_toggle_power_map(codec, nid, get_pin_presence(codec, nid)); |
4203 | } | ||
4204 | |||
4205 | static void stac92xx_report_jack(struct hda_codec *codec, hda_nid_t nid) | ||
4206 | { | ||
4207 | struct sigmatel_spec *spec = codec->spec; | ||
4208 | struct sigmatel_jack *jacks = spec->jacks.list; | ||
4209 | |||
4210 | if (jacks) { | ||
4211 | int i; | ||
4212 | for (i = 0; i < spec->jacks.used; i++) { | ||
4213 | if (jacks->nid == nid) { | ||
4214 | unsigned int pin_ctl = | ||
4215 | snd_hda_codec_read(codec, nid, | ||
4216 | 0, AC_VERB_GET_PIN_WIDGET_CONTROL, | ||
4217 | 0x00); | ||
4218 | int type = jacks->type; | ||
4219 | if (type == (SND_JACK_LINEOUT | ||
4220 | | SND_JACK_HEADPHONE)) | ||
4221 | type = (pin_ctl & AC_PINCTL_HP_EN) | ||
4222 | ? SND_JACK_HEADPHONE : SND_JACK_LINEOUT; | ||
4223 | snd_jack_report(jacks->jack, | ||
4224 | get_pin_presence(codec, nid) | ||
4225 | ? type : 0); | ||
4226 | } | ||
4227 | jacks++; | ||
4228 | } | ||
4229 | } | ||
4230 | } | ||
4231 | |||
4232 | static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid, | ||
4233 | unsigned char type) | ||
4234 | { | ||
4235 | struct sigmatel_event *event = stac_get_event(codec, nid, type); | ||
4236 | if (!event) | ||
4237 | return; | ||
4238 | codec->patch_ops.unsol_event(codec, (unsigned)event->tag << 26); | ||
4018 | } | 4239 | } |
4019 | 4240 | ||
4020 | static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) | 4241 | static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) |
4021 | { | 4242 | { |
4022 | struct sigmatel_spec *spec = codec->spec; | 4243 | struct sigmatel_spec *spec = codec->spec; |
4023 | int idx = res >> 26 & 0x0f; | 4244 | struct sigmatel_event *event; |
4245 | int tag, data; | ||
4024 | 4246 | ||
4025 | switch ((res >> 26) & 0x70) { | 4247 | tag = (res >> 26) & 0x7f; |
4248 | event = stac_get_event_from_tag(codec, tag); | ||
4249 | if (!event) | ||
4250 | return; | ||
4251 | |||
4252 | switch (event->type) { | ||
4026 | case STAC_HP_EVENT: | 4253 | case STAC_HP_EVENT: |
4027 | stac92xx_hp_detect(codec, res); | 4254 | stac92xx_hp_detect(codec); |
4028 | /* fallthru */ | 4255 | /* fallthru */ |
4256 | case STAC_INSERT_EVENT: | ||
4029 | case STAC_PWR_EVENT: | 4257 | case STAC_PWR_EVENT: |
4030 | if (spec->num_pwrs > 0) | 4258 | if (spec->num_pwrs > 0) |
4031 | stac92xx_pin_sense(codec, idx); | 4259 | stac92xx_pin_sense(codec, event->nid); |
4260 | stac92xx_report_jack(codec, event->nid); | ||
4032 | break; | 4261 | break; |
4033 | case STAC_VREF_EVENT: { | 4262 | case STAC_VREF_EVENT: |
4034 | int data = snd_hda_codec_read(codec, codec->afg, 0, | 4263 | data = snd_hda_codec_read(codec, codec->afg, 0, |
4035 | AC_VERB_GET_GPIO_DATA, 0); | 4264 | AC_VERB_GET_GPIO_DATA, 0); |
4036 | /* toggle VREF state based on GPIOx status */ | 4265 | /* toggle VREF state based on GPIOx status */ |
4037 | snd_hda_codec_write(codec, codec->afg, 0, 0x7e0, | 4266 | snd_hda_codec_write(codec, codec->afg, 0, 0x7e0, |
4038 | !!(data & (1 << idx))); | 4267 | !!(data & (1 << event->data))); |
4039 | break; | 4268 | break; |
4040 | } | ||
4041 | } | 4269 | } |
4042 | } | 4270 | } |
4043 | 4271 | ||
4272 | #ifdef CONFIG_PROC_FS | ||
4273 | static void stac92hd_proc_hook(struct snd_info_buffer *buffer, | ||
4274 | struct hda_codec *codec, hda_nid_t nid) | ||
4275 | { | ||
4276 | if (nid == codec->afg) | ||
4277 | snd_iprintf(buffer, "Power-Map: 0x%02x\n", | ||
4278 | snd_hda_codec_read(codec, nid, 0, 0x0fec, 0x0)); | ||
4279 | } | ||
4280 | |||
4281 | static void analog_loop_proc_hook(struct snd_info_buffer *buffer, | ||
4282 | struct hda_codec *codec, | ||
4283 | unsigned int verb) | ||
4284 | { | ||
4285 | snd_iprintf(buffer, "Analog Loopback: 0x%02x\n", | ||
4286 | snd_hda_codec_read(codec, codec->afg, 0, verb, 0)); | ||
4287 | } | ||
4288 | |||
4289 | /* stac92hd71bxx, stac92hd73xx */ | ||
4290 | static void stac92hd7x_proc_hook(struct snd_info_buffer *buffer, | ||
4291 | struct hda_codec *codec, hda_nid_t nid) | ||
4292 | { | ||
4293 | stac92hd_proc_hook(buffer, codec, nid); | ||
4294 | if (nid == codec->afg) | ||
4295 | analog_loop_proc_hook(buffer, codec, 0xfa0); | ||
4296 | } | ||
4297 | |||
4298 | static void stac9205_proc_hook(struct snd_info_buffer *buffer, | ||
4299 | struct hda_codec *codec, hda_nid_t nid) | ||
4300 | { | ||
4301 | if (nid == codec->afg) | ||
4302 | analog_loop_proc_hook(buffer, codec, 0xfe0); | ||
4303 | } | ||
4304 | |||
4305 | static void stac927x_proc_hook(struct snd_info_buffer *buffer, | ||
4306 | struct hda_codec *codec, hda_nid_t nid) | ||
4307 | { | ||
4308 | if (nid == codec->afg) | ||
4309 | analog_loop_proc_hook(buffer, codec, 0xfeb); | ||
4310 | } | ||
4311 | #else | ||
4312 | #define stac92hd_proc_hook NULL | ||
4313 | #define stac92hd7x_proc_hook NULL | ||
4314 | #define stac9205_proc_hook NULL | ||
4315 | #define stac927x_proc_hook NULL | ||
4316 | #endif | ||
4317 | |||
4044 | #ifdef SND_HDA_NEEDS_RESUME | 4318 | #ifdef SND_HDA_NEEDS_RESUME |
4045 | static int stac92xx_resume(struct hda_codec *codec) | 4319 | static int stac92xx_resume(struct hda_codec *codec) |
4046 | { | 4320 | { |
4047 | struct sigmatel_spec *spec = codec->spec; | 4321 | struct sigmatel_spec *spec = codec->spec; |
4048 | 4322 | ||
4049 | stac92xx_set_config_regs(codec); | 4323 | stac92xx_set_config_regs(codec); |
4050 | snd_hda_sequence_write(codec, spec->init); | 4324 | stac92xx_init(codec); |
4051 | stac_gpio_set(codec, spec->gpio_mask, | ||
4052 | spec->gpio_dir, spec->gpio_data); | ||
4053 | snd_hda_codec_resume_amp(codec); | 4325 | snd_hda_codec_resume_amp(codec); |
4054 | snd_hda_codec_resume_cache(codec); | 4326 | snd_hda_codec_resume_cache(codec); |
4055 | /* power down inactive DACs */ | 4327 | /* fake event to set up pins again to override cached values */ |
4056 | if (spec->dac_list) | ||
4057 | stac92xx_power_down(codec); | ||
4058 | /* invoke unsolicited event to reset the HP state */ | ||
4059 | if (spec->hp_detect) | 4328 | if (spec->hp_detect) |
4060 | codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26); | 4329 | stac_issue_unsol_event(codec, spec->autocfg.hp_pins[0], |
4330 | STAC_HP_EVENT); | ||
4331 | return 0; | ||
4332 | } | ||
4333 | |||
4334 | static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state) | ||
4335 | { | ||
4336 | struct sigmatel_spec *spec = codec->spec; | ||
4337 | if (spec->eapd_mask) | ||
4338 | stac_gpio_set(codec, spec->gpio_mask, | ||
4339 | spec->gpio_dir, spec->gpio_data & | ||
4340 | ~spec->eapd_mask); | ||
4061 | return 0; | 4341 | return 0; |
4062 | } | 4342 | } |
4063 | #endif | 4343 | #endif |
@@ -4069,6 +4349,7 @@ static struct hda_codec_ops stac92xx_patch_ops = { | |||
4069 | .free = stac92xx_free, | 4349 | .free = stac92xx_free, |
4070 | .unsol_event = stac92xx_unsol_event, | 4350 | .unsol_event = stac92xx_unsol_event, |
4071 | #ifdef SND_HDA_NEEDS_RESUME | 4351 | #ifdef SND_HDA_NEEDS_RESUME |
4352 | .suspend = stac92xx_suspend, | ||
4072 | .resume = stac92xx_resume, | 4353 | .resume = stac92xx_resume, |
4073 | #endif | 4354 | #endif |
4074 | }; | 4355 | }; |
@@ -4091,14 +4372,12 @@ static int patch_stac9200(struct hda_codec *codec) | |||
4091 | if (spec->board_config < 0) { | 4372 | if (spec->board_config < 0) { |
4092 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9200, using BIOS defaults\n"); | 4373 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9200, using BIOS defaults\n"); |
4093 | err = stac92xx_save_bios_config_regs(codec); | 4374 | err = stac92xx_save_bios_config_regs(codec); |
4094 | if (err < 0) { | 4375 | } else |
4095 | stac92xx_free(codec); | 4376 | err = stac_save_pin_cfgs(codec, |
4096 | return err; | 4377 | stac9200_brd_tbl[spec->board_config]); |
4097 | } | 4378 | if (err < 0) { |
4098 | spec->pin_configs = spec->bios_pin_configs; | 4379 | stac92xx_free(codec); |
4099 | } else { | 4380 | return err; |
4100 | spec->pin_configs = stac9200_brd_tbl[spec->board_config]; | ||
4101 | stac92xx_set_config_regs(codec); | ||
4102 | } | 4381 | } |
4103 | 4382 | ||
4104 | spec->multiout.max_channels = 2; | 4383 | spec->multiout.max_channels = 2; |
@@ -4154,14 +4433,12 @@ static int patch_stac925x(struct hda_codec *codec) | |||
4154 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC925x," | 4433 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC925x," |
4155 | "using BIOS defaults\n"); | 4434 | "using BIOS defaults\n"); |
4156 | err = stac92xx_save_bios_config_regs(codec); | 4435 | err = stac92xx_save_bios_config_regs(codec); |
4157 | if (err < 0) { | 4436 | } else |
4158 | stac92xx_free(codec); | 4437 | err = stac_save_pin_cfgs(codec, |
4159 | return err; | 4438 | stac925x_brd_tbl[spec->board_config]); |
4160 | } | 4439 | if (err < 0) { |
4161 | spec->pin_configs = spec->bios_pin_configs; | 4440 | stac92xx_free(codec); |
4162 | } else if (stac925x_brd_tbl[spec->board_config] != NULL){ | 4441 | return err; |
4163 | spec->pin_configs = stac925x_brd_tbl[spec->board_config]; | ||
4164 | stac92xx_set_config_regs(codec); | ||
4165 | } | 4442 | } |
4166 | 4443 | ||
4167 | spec->multiout.max_channels = 2; | 4444 | spec->multiout.max_channels = 2; |
@@ -4225,6 +4502,7 @@ static int patch_stac92hd73xx(struct hda_codec *codec) | |||
4225 | struct sigmatel_spec *spec; | 4502 | struct sigmatel_spec *spec; |
4226 | hda_nid_t conn[STAC92HD73_DAC_COUNT + 2]; | 4503 | hda_nid_t conn[STAC92HD73_DAC_COUNT + 2]; |
4227 | int err = 0; | 4504 | int err = 0; |
4505 | int num_dacs; | ||
4228 | 4506 | ||
4229 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 4507 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
4230 | if (spec == NULL) | 4508 | if (spec == NULL) |
@@ -4243,43 +4521,37 @@ again: | |||
4243 | snd_printdd(KERN_INFO "hda_codec: Unknown model for" | 4521 | snd_printdd(KERN_INFO "hda_codec: Unknown model for" |
4244 | " STAC92HD73XX, using BIOS defaults\n"); | 4522 | " STAC92HD73XX, using BIOS defaults\n"); |
4245 | err = stac92xx_save_bios_config_regs(codec); | 4523 | err = stac92xx_save_bios_config_regs(codec); |
4246 | if (err < 0) { | 4524 | } else |
4247 | stac92xx_free(codec); | 4525 | err = stac_save_pin_cfgs(codec, |
4248 | return err; | 4526 | stac92hd73xx_brd_tbl[spec->board_config]); |
4249 | } | 4527 | if (err < 0) { |
4250 | spec->pin_configs = spec->bios_pin_configs; | 4528 | stac92xx_free(codec); |
4251 | } else { | 4529 | return err; |
4252 | spec->pin_configs = stac92hd73xx_brd_tbl[spec->board_config]; | ||
4253 | stac92xx_set_config_regs(codec); | ||
4254 | } | 4530 | } |
4255 | 4531 | ||
4256 | spec->multiout.num_dacs = snd_hda_get_connections(codec, 0x0a, | 4532 | num_dacs = snd_hda_get_connections(codec, 0x0a, |
4257 | conn, STAC92HD73_DAC_COUNT + 2) - 1; | 4533 | conn, STAC92HD73_DAC_COUNT + 2) - 1; |
4258 | 4534 | ||
4259 | if (spec->multiout.num_dacs < 0) { | 4535 | if (num_dacs < 3 || num_dacs > 5) { |
4260 | printk(KERN_WARNING "hda_codec: Could not determine " | 4536 | printk(KERN_WARNING "hda_codec: Could not determine " |
4261 | "number of channels defaulting to DAC count\n"); | 4537 | "number of channels defaulting to DAC count\n"); |
4262 | spec->multiout.num_dacs = STAC92HD73_DAC_COUNT; | 4538 | num_dacs = STAC92HD73_DAC_COUNT; |
4263 | } | 4539 | } |
4264 | 4540 | switch (num_dacs) { | |
4265 | switch (spec->multiout.num_dacs) { | ||
4266 | case 0x3: /* 6 Channel */ | 4541 | case 0x3: /* 6 Channel */ |
4267 | spec->multiout.hp_nid = 0x17; | ||
4268 | spec->mixer = stac92hd73xx_6ch_mixer; | 4542 | spec->mixer = stac92hd73xx_6ch_mixer; |
4269 | spec->init = stac92hd73xx_6ch_core_init; | 4543 | spec->init = stac92hd73xx_6ch_core_init; |
4270 | break; | 4544 | break; |
4271 | case 0x4: /* 8 Channel */ | 4545 | case 0x4: /* 8 Channel */ |
4272 | spec->multiout.hp_nid = 0x18; | ||
4273 | spec->mixer = stac92hd73xx_8ch_mixer; | 4546 | spec->mixer = stac92hd73xx_8ch_mixer; |
4274 | spec->init = stac92hd73xx_8ch_core_init; | 4547 | spec->init = stac92hd73xx_8ch_core_init; |
4275 | break; | 4548 | break; |
4276 | case 0x5: /* 10 Channel */ | 4549 | case 0x5: /* 10 Channel */ |
4277 | spec->multiout.hp_nid = 0x19; | ||
4278 | spec->mixer = stac92hd73xx_10ch_mixer; | 4550 | spec->mixer = stac92hd73xx_10ch_mixer; |
4279 | spec->init = stac92hd73xx_10ch_core_init; | 4551 | spec->init = stac92hd73xx_10ch_core_init; |
4280 | }; | 4552 | } |
4553 | spec->multiout.dac_nids = spec->dac_nids; | ||
4281 | 4554 | ||
4282 | spec->multiout.dac_nids = stac92hd73xx_dac_nids; | ||
4283 | spec->aloopback_mask = 0x01; | 4555 | spec->aloopback_mask = 0x01; |
4284 | spec->aloopback_shift = 8; | 4556 | spec->aloopback_shift = 8; |
4285 | 4557 | ||
@@ -4310,9 +4582,8 @@ again: | |||
4310 | spec->amp_nids = &stac92hd73xx_amp_nids[DELL_M6_AMP]; | 4582 | spec->amp_nids = &stac92hd73xx_amp_nids[DELL_M6_AMP]; |
4311 | spec->eapd_switch = 0; | 4583 | spec->eapd_switch = 0; |
4312 | spec->num_amps = 1; | 4584 | spec->num_amps = 1; |
4313 | spec->multiout.hp_nid = 0; /* dual HPs */ | ||
4314 | 4585 | ||
4315 | if (!spec->init) | 4586 | if (spec->board_config != STAC_DELL_EQ) |
4316 | spec->init = dell_m6_core_init; | 4587 | spec->init = dell_m6_core_init; |
4317 | switch (spec->board_config) { | 4588 | switch (spec->board_config) { |
4318 | case STAC_DELL_M6_AMIC: /* Analog Mics */ | 4589 | case STAC_DELL_M6_AMIC: /* Analog Mics */ |
@@ -4370,6 +4641,8 @@ again: | |||
4370 | 4641 | ||
4371 | codec->patch_ops = stac92xx_patch_ops; | 4642 | codec->patch_ops = stac92xx_patch_ops; |
4372 | 4643 | ||
4644 | codec->proc_widget_hook = stac92hd7x_proc_hook; | ||
4645 | |||
4373 | return 0; | 4646 | return 0; |
4374 | } | 4647 | } |
4375 | 4648 | ||
@@ -4401,17 +4674,15 @@ static int patch_stac92hd83xxx(struct hda_codec *codec) | |||
4401 | spec->pwr_nids = stac92hd83xxx_pwr_nids; | 4674 | spec->pwr_nids = stac92hd83xxx_pwr_nids; |
4402 | spec->pwr_mapping = stac92hd83xxx_pwr_mapping; | 4675 | spec->pwr_mapping = stac92hd83xxx_pwr_mapping; |
4403 | spec->num_pwrs = ARRAY_SIZE(stac92hd83xxx_pwr_nids); | 4676 | spec->num_pwrs = ARRAY_SIZE(stac92hd83xxx_pwr_nids); |
4404 | spec->multiout.dac_nids = stac92hd83xxx_dac_nids; | 4677 | spec->multiout.dac_nids = spec->dac_nids; |
4405 | 4678 | ||
4406 | spec->init = stac92hd83xxx_core_init; | 4679 | spec->init = stac92hd83xxx_core_init; |
4407 | switch (codec->vendor_id) { | 4680 | switch (codec->vendor_id) { |
4408 | case 0x111d7605: | 4681 | case 0x111d7605: |
4409 | spec->multiout.num_dacs = STAC92HD81_DAC_COUNT; | ||
4410 | break; | 4682 | break; |
4411 | default: | 4683 | default: |
4412 | spec->num_pwrs--; | 4684 | spec->num_pwrs--; |
4413 | spec->init++; /* switch to config #2 */ | 4685 | spec->init++; /* switch to config #2 */ |
4414 | spec->multiout.num_dacs = STAC92HD83_DAC_COUNT; | ||
4415 | } | 4686 | } |
4416 | 4687 | ||
4417 | spec->mixer = stac92hd83xxx_mixer; | 4688 | spec->mixer = stac92hd83xxx_mixer; |
@@ -4430,14 +4701,12 @@ again: | |||
4430 | snd_printdd(KERN_INFO "hda_codec: Unknown model for" | 4701 | snd_printdd(KERN_INFO "hda_codec: Unknown model for" |
4431 | " STAC92HD83XXX, using BIOS defaults\n"); | 4702 | " STAC92HD83XXX, using BIOS defaults\n"); |
4432 | err = stac92xx_save_bios_config_regs(codec); | 4703 | err = stac92xx_save_bios_config_regs(codec); |
4433 | if (err < 0) { | 4704 | } else |
4434 | stac92xx_free(codec); | 4705 | err = stac_save_pin_cfgs(codec, |
4435 | return err; | 4706 | stac92hd83xxx_brd_tbl[spec->board_config]); |
4436 | } | 4707 | if (err < 0) { |
4437 | spec->pin_configs = spec->bios_pin_configs; | 4708 | stac92xx_free(codec); |
4438 | } else { | 4709 | return err; |
4439 | spec->pin_configs = stac92hd83xxx_brd_tbl[spec->board_config]; | ||
4440 | stac92xx_set_config_regs(codec); | ||
4441 | } | 4710 | } |
4442 | 4711 | ||
4443 | err = stac92xx_parse_auto_config(codec, 0x1d, 0); | 4712 | err = stac92xx_parse_auto_config(codec, 0x1d, 0); |
@@ -4458,56 +4727,10 @@ again: | |||
4458 | 4727 | ||
4459 | codec->patch_ops = stac92xx_patch_ops; | 4728 | codec->patch_ops = stac92xx_patch_ops; |
4460 | 4729 | ||
4461 | return 0; | 4730 | codec->proc_widget_hook = stac92hd_proc_hook; |
4462 | } | ||
4463 | 4731 | ||
4464 | #ifdef SND_HDA_NEEDS_RESUME | ||
4465 | static void stac92hd71xx_set_power_state(struct hda_codec *codec, int pwr) | ||
4466 | { | ||
4467 | struct sigmatel_spec *spec = codec->spec; | ||
4468 | int i; | ||
4469 | snd_hda_codec_write_cache(codec, codec->afg, 0, | ||
4470 | AC_VERB_SET_POWER_STATE, pwr); | ||
4471 | |||
4472 | msleep(1); | ||
4473 | for (i = 0; i < spec->num_adcs; i++) { | ||
4474 | snd_hda_codec_write_cache(codec, | ||
4475 | spec->adc_nids[i], 0, | ||
4476 | AC_VERB_SET_POWER_STATE, pwr); | ||
4477 | } | ||
4478 | }; | ||
4479 | |||
4480 | static int stac92hd71xx_resume(struct hda_codec *codec) | ||
4481 | { | ||
4482 | stac92hd71xx_set_power_state(codec, AC_PWRST_D0); | ||
4483 | return stac92xx_resume(codec); | ||
4484 | } | ||
4485 | |||
4486 | static int stac92hd71xx_suspend(struct hda_codec *codec, pm_message_t state) | ||
4487 | { | ||
4488 | struct sigmatel_spec *spec = codec->spec; | ||
4489 | |||
4490 | stac92hd71xx_set_power_state(codec, AC_PWRST_D3); | ||
4491 | if (spec->eapd_mask) | ||
4492 | stac_gpio_set(codec, spec->gpio_mask, | ||
4493 | spec->gpio_dir, spec->gpio_data & | ||
4494 | ~spec->eapd_mask); | ||
4495 | return 0; | 4732 | return 0; |
4496 | }; | 4733 | } |
4497 | |||
4498 | #endif | ||
4499 | |||
4500 | static struct hda_codec_ops stac92hd71bxx_patch_ops = { | ||
4501 | .build_controls = stac92xx_build_controls, | ||
4502 | .build_pcms = stac92xx_build_pcms, | ||
4503 | .init = stac92xx_init, | ||
4504 | .free = stac92xx_free, | ||
4505 | .unsol_event = stac92xx_unsol_event, | ||
4506 | #ifdef SND_HDA_NEEDS_RESUME | ||
4507 | .resume = stac92hd71xx_resume, | ||
4508 | .suspend = stac92hd71xx_suspend, | ||
4509 | #endif | ||
4510 | }; | ||
4511 | 4734 | ||
4512 | static struct hda_input_mux stac92hd71bxx_dmux = { | 4735 | static struct hda_input_mux stac92hd71bxx_dmux = { |
4513 | .num_items = 4, | 4736 | .num_items = 4, |
@@ -4544,14 +4767,12 @@ again: | |||
4544 | snd_printdd(KERN_INFO "hda_codec: Unknown model for" | 4767 | snd_printdd(KERN_INFO "hda_codec: Unknown model for" |
4545 | " STAC92HD71BXX, using BIOS defaults\n"); | 4768 | " STAC92HD71BXX, using BIOS defaults\n"); |
4546 | err = stac92xx_save_bios_config_regs(codec); | 4769 | err = stac92xx_save_bios_config_regs(codec); |
4547 | if (err < 0) { | 4770 | } else |
4548 | stac92xx_free(codec); | 4771 | err = stac_save_pin_cfgs(codec, |
4549 | return err; | 4772 | stac92hd71bxx_brd_tbl[spec->board_config]); |
4550 | } | 4773 | if (err < 0) { |
4551 | spec->pin_configs = spec->bios_pin_configs; | 4774 | stac92xx_free(codec); |
4552 | } else { | 4775 | return err; |
4553 | spec->pin_configs = stac92hd71bxx_brd_tbl[spec->board_config]; | ||
4554 | stac92xx_set_config_regs(codec); | ||
4555 | } | 4776 | } |
4556 | 4777 | ||
4557 | if (spec->board_config > STAC_92HD71BXX_REF) { | 4778 | if (spec->board_config > STAC_92HD71BXX_REF) { |
@@ -4574,21 +4795,21 @@ again: | |||
4574 | switch (spec->board_config) { | 4795 | switch (spec->board_config) { |
4575 | case STAC_HP_M4: | 4796 | case STAC_HP_M4: |
4576 | /* Enable VREF power saving on GPIO1 detect */ | 4797 | /* Enable VREF power saving on GPIO1 detect */ |
4798 | err = stac_add_event(spec, codec->afg, | ||
4799 | STAC_VREF_EVENT, 0x02); | ||
4800 | if (err < 0) | ||
4801 | return err; | ||
4577 | snd_hda_codec_write_cache(codec, codec->afg, 0, | 4802 | snd_hda_codec_write_cache(codec, codec->afg, 0, |
4578 | AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x02); | 4803 | AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x02); |
4579 | snd_hda_codec_write_cache(codec, codec->afg, 0, | 4804 | snd_hda_codec_write_cache(codec, codec->afg, 0, |
4580 | AC_VERB_SET_UNSOLICITED_ENABLE, | 4805 | AC_VERB_SET_UNSOLICITED_ENABLE, |
4581 | (AC_USRSP_EN | STAC_VREF_EVENT | 0x01)); | 4806 | AC_USRSP_EN | err); |
4582 | spec->gpio_mask |= 0x02; | 4807 | spec->gpio_mask |= 0x02; |
4583 | break; | 4808 | break; |
4584 | } | 4809 | } |
4585 | if ((codec->revision_id & 0xf) == 0 || | 4810 | if ((codec->revision_id & 0xf) == 0 || |
4586 | (codec->revision_id & 0xf) == 1) { | 4811 | (codec->revision_id & 0xf) == 1) |
4587 | #ifdef SND_HDA_NEEDS_RESUME | ||
4588 | codec->patch_ops = stac92hd71bxx_patch_ops; | ||
4589 | #endif | ||
4590 | spec->stream_delay = 40; /* 40 milliseconds */ | 4812 | spec->stream_delay = 40; /* 40 milliseconds */ |
4591 | } | ||
4592 | 4813 | ||
4593 | /* no output amps */ | 4814 | /* no output amps */ |
4594 | spec->num_pwrs = 0; | 4815 | spec->num_pwrs = 0; |
@@ -4597,15 +4818,11 @@ again: | |||
4597 | 4818 | ||
4598 | /* disable VSW */ | 4819 | /* disable VSW */ |
4599 | spec->init = &stac92hd71bxx_analog_core_init[HD_DISABLE_PORTF]; | 4820 | spec->init = &stac92hd71bxx_analog_core_init[HD_DISABLE_PORTF]; |
4600 | stac92xx_set_config_reg(codec, 0xf, 0x40f000f0); | 4821 | stac_change_pin_config(codec, 0xf, 0x40f000f0); |
4601 | break; | 4822 | break; |
4602 | case 0x111d7603: /* 6 Port with Analog Mixer */ | 4823 | case 0x111d7603: /* 6 Port with Analog Mixer */ |
4603 | if ((codec->revision_id & 0xf) == 1) { | 4824 | if ((codec->revision_id & 0xf) == 1) |
4604 | #ifdef SND_HDA_NEEDS_RESUME | ||
4605 | codec->patch_ops = stac92hd71bxx_patch_ops; | ||
4606 | #endif | ||
4607 | spec->stream_delay = 40; /* 40 milliseconds */ | 4825 | spec->stream_delay = 40; /* 40 milliseconds */ |
4608 | } | ||
4609 | 4826 | ||
4610 | /* no output amps */ | 4827 | /* no output amps */ |
4611 | spec->num_pwrs = 0; | 4828 | spec->num_pwrs = 0; |
@@ -4635,7 +4852,7 @@ again: | |||
4635 | switch (spec->board_config) { | 4852 | switch (spec->board_config) { |
4636 | case STAC_HP_M4: | 4853 | case STAC_HP_M4: |
4637 | /* enable internal microphone */ | 4854 | /* enable internal microphone */ |
4638 | stac92xx_set_config_reg(codec, 0x0e, 0x01813040); | 4855 | stac_change_pin_config(codec, 0x0e, 0x01813040); |
4639 | stac92xx_auto_set_pinctl(codec, 0x0e, | 4856 | stac92xx_auto_set_pinctl(codec, 0x0e, |
4640 | AC_PINCTL_IN_EN | AC_PINCTL_VREF_80); | 4857 | AC_PINCTL_IN_EN | AC_PINCTL_VREF_80); |
4641 | /* fallthru */ | 4858 | /* fallthru */ |
@@ -4656,9 +4873,7 @@ again: | |||
4656 | spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids); | 4873 | spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids); |
4657 | }; | 4874 | }; |
4658 | 4875 | ||
4659 | spec->multiout.num_dacs = 1; | 4876 | spec->multiout.dac_nids = spec->dac_nids; |
4660 | spec->multiout.hp_nid = 0x11; | ||
4661 | spec->multiout.dac_nids = stac92hd71bxx_dac_nids; | ||
4662 | if (spec->dinput_mux) | 4877 | if (spec->dinput_mux) |
4663 | spec->private_dimux.num_items += | 4878 | spec->private_dimux.num_items += |
4664 | spec->num_dmics - | 4879 | spec->num_dmics - |
@@ -4680,6 +4895,8 @@ again: | |||
4680 | return err; | 4895 | return err; |
4681 | } | 4896 | } |
4682 | 4897 | ||
4898 | codec->proc_widget_hook = stac92hd7x_proc_hook; | ||
4899 | |||
4683 | return 0; | 4900 | return 0; |
4684 | }; | 4901 | }; |
4685 | 4902 | ||
@@ -4741,14 +4958,12 @@ static int patch_stac922x(struct hda_codec *codec) | |||
4741 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC922x, " | 4958 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC922x, " |
4742 | "using BIOS defaults\n"); | 4959 | "using BIOS defaults\n"); |
4743 | err = stac92xx_save_bios_config_regs(codec); | 4960 | err = stac92xx_save_bios_config_regs(codec); |
4744 | if (err < 0) { | 4961 | } else |
4745 | stac92xx_free(codec); | 4962 | err = stac_save_pin_cfgs(codec, |
4746 | return err; | 4963 | stac922x_brd_tbl[spec->board_config]); |
4747 | } | 4964 | if (err < 0) { |
4748 | spec->pin_configs = spec->bios_pin_configs; | 4965 | stac92xx_free(codec); |
4749 | } else if (stac922x_brd_tbl[spec->board_config] != NULL) { | 4966 | return err; |
4750 | spec->pin_configs = stac922x_brd_tbl[spec->board_config]; | ||
4751 | stac92xx_set_config_regs(codec); | ||
4752 | } | 4967 | } |
4753 | 4968 | ||
4754 | spec->adc_nids = stac922x_adc_nids; | 4969 | spec->adc_nids = stac922x_adc_nids; |
@@ -4811,14 +5026,12 @@ static int patch_stac927x(struct hda_codec *codec) | |||
4811 | snd_printdd(KERN_INFO "hda_codec: Unknown model for" | 5026 | snd_printdd(KERN_INFO "hda_codec: Unknown model for" |
4812 | "STAC927x, using BIOS defaults\n"); | 5027 | "STAC927x, using BIOS defaults\n"); |
4813 | err = stac92xx_save_bios_config_regs(codec); | 5028 | err = stac92xx_save_bios_config_regs(codec); |
4814 | if (err < 0) { | 5029 | } else |
4815 | stac92xx_free(codec); | 5030 | err = stac_save_pin_cfgs(codec, |
4816 | return err; | 5031 | stac927x_brd_tbl[spec->board_config]); |
4817 | } | 5032 | if (err < 0) { |
4818 | spec->pin_configs = spec->bios_pin_configs; | 5033 | stac92xx_free(codec); |
4819 | } else { | 5034 | return err; |
4820 | spec->pin_configs = stac927x_brd_tbl[spec->board_config]; | ||
4821 | stac92xx_set_config_regs(codec); | ||
4822 | } | 5035 | } |
4823 | 5036 | ||
4824 | spec->digbeep_nid = 0x23; | 5037 | spec->digbeep_nid = 0x23; |
@@ -4848,15 +5061,15 @@ static int patch_stac927x(struct hda_codec *codec) | |||
4848 | case 0x10280209: | 5061 | case 0x10280209: |
4849 | case 0x1028022e: | 5062 | case 0x1028022e: |
4850 | /* correct the device field to SPDIF out */ | 5063 | /* correct the device field to SPDIF out */ |
4851 | stac92xx_set_config_reg(codec, 0x21, 0x01442070); | 5064 | stac_change_pin_config(codec, 0x21, 0x01442070); |
4852 | break; | 5065 | break; |
4853 | }; | 5066 | }; |
4854 | /* configure the analog microphone on some laptops */ | 5067 | /* configure the analog microphone on some laptops */ |
4855 | stac92xx_set_config_reg(codec, 0x0c, 0x90a79130); | 5068 | stac_change_pin_config(codec, 0x0c, 0x90a79130); |
4856 | /* correct the front output jack as a hp out */ | 5069 | /* correct the front output jack as a hp out */ |
4857 | stac92xx_set_config_reg(codec, 0x0f, 0x0227011f); | 5070 | stac_change_pin_config(codec, 0x0f, 0x0227011f); |
4858 | /* correct the front input jack as a mic */ | 5071 | /* correct the front input jack as a mic */ |
4859 | stac92xx_set_config_reg(codec, 0x0e, 0x02a79130); | 5072 | stac_change_pin_config(codec, 0x0e, 0x02a79130); |
4860 | /* fallthru */ | 5073 | /* fallthru */ |
4861 | case STAC_DELL_3ST: | 5074 | case STAC_DELL_3ST: |
4862 | /* GPIO2 High = Enable EAPD */ | 5075 | /* GPIO2 High = Enable EAPD */ |
@@ -4904,6 +5117,8 @@ static int patch_stac927x(struct hda_codec *codec) | |||
4904 | 5117 | ||
4905 | codec->patch_ops = stac92xx_patch_ops; | 5118 | codec->patch_ops = stac92xx_patch_ops; |
4906 | 5119 | ||
5120 | codec->proc_widget_hook = stac927x_proc_hook; | ||
5121 | |||
4907 | /* | 5122 | /* |
4908 | * !!FIXME!! | 5123 | * !!FIXME!! |
4909 | * The STAC927x seem to require fairly long delays for certain | 5124 | * The STAC927x seem to require fairly long delays for certain |
@@ -4942,14 +5157,12 @@ static int patch_stac9205(struct hda_codec *codec) | |||
4942 | if (spec->board_config < 0) { | 5157 | if (spec->board_config < 0) { |
4943 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9205, using BIOS defaults\n"); | 5158 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9205, using BIOS defaults\n"); |
4944 | err = stac92xx_save_bios_config_regs(codec); | 5159 | err = stac92xx_save_bios_config_regs(codec); |
4945 | if (err < 0) { | 5160 | } else |
4946 | stac92xx_free(codec); | 5161 | err = stac_save_pin_cfgs(codec, |
4947 | return err; | 5162 | stac9205_brd_tbl[spec->board_config]); |
4948 | } | 5163 | if (err < 0) { |
4949 | spec->pin_configs = spec->bios_pin_configs; | 5164 | stac92xx_free(codec); |
4950 | } else { | 5165 | return err; |
4951 | spec->pin_configs = stac9205_brd_tbl[spec->board_config]; | ||
4952 | stac92xx_set_config_regs(codec); | ||
4953 | } | 5166 | } |
4954 | 5167 | ||
4955 | spec->digbeep_nid = 0x23; | 5168 | spec->digbeep_nid = 0x23; |
@@ -4976,15 +5189,18 @@ static int patch_stac9205(struct hda_codec *codec) | |||
4976 | switch (spec->board_config){ | 5189 | switch (spec->board_config){ |
4977 | case STAC_9205_DELL_M43: | 5190 | case STAC_9205_DELL_M43: |
4978 | /* Enable SPDIF in/out */ | 5191 | /* Enable SPDIF in/out */ |
4979 | stac92xx_set_config_reg(codec, 0x1f, 0x01441030); | 5192 | stac_change_pin_config(codec, 0x1f, 0x01441030); |
4980 | stac92xx_set_config_reg(codec, 0x20, 0x1c410030); | 5193 | stac_change_pin_config(codec, 0x20, 0x1c410030); |
4981 | 5194 | ||
4982 | /* Enable unsol response for GPIO4/Dock HP connection */ | 5195 | /* Enable unsol response for GPIO4/Dock HP connection */ |
5196 | err = stac_add_event(spec, codec->afg, STAC_VREF_EVENT, 0x01); | ||
5197 | if (err < 0) | ||
5198 | return err; | ||
4983 | snd_hda_codec_write_cache(codec, codec->afg, 0, | 5199 | snd_hda_codec_write_cache(codec, codec->afg, 0, |
4984 | AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x10); | 5200 | AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x10); |
4985 | snd_hda_codec_write_cache(codec, codec->afg, 0, | 5201 | snd_hda_codec_write_cache(codec, codec->afg, 0, |
4986 | AC_VERB_SET_UNSOLICITED_ENABLE, | 5202 | AC_VERB_SET_UNSOLICITED_ENABLE, |
4987 | (AC_USRSP_EN | STAC_HP_EVENT)); | 5203 | AC_USRSP_EN | err); |
4988 | 5204 | ||
4989 | spec->gpio_dir = 0x0b; | 5205 | spec->gpio_dir = 0x0b; |
4990 | spec->eapd_mask = 0x01; | 5206 | spec->eapd_mask = 0x01; |
@@ -5022,6 +5238,8 @@ static int patch_stac9205(struct hda_codec *codec) | |||
5022 | 5238 | ||
5023 | codec->patch_ops = stac92xx_patch_ops; | 5239 | codec->patch_ops = stac92xx_patch_ops; |
5024 | 5240 | ||
5241 | codec->proc_widget_hook = stac9205_proc_hook; | ||
5242 | |||
5025 | return 0; | 5243 | return 0; |
5026 | } | 5244 | } |
5027 | 5245 | ||
@@ -5078,29 +5296,11 @@ static struct hda_verb vaio_ar_init[] = { | |||
5078 | {} | 5296 | {} |
5079 | }; | 5297 | }; |
5080 | 5298 | ||
5081 | /* bind volumes of both NID 0x02 and 0x05 */ | ||
5082 | static struct hda_bind_ctls vaio_bind_master_vol = { | ||
5083 | .ops = &snd_hda_bind_vol, | ||
5084 | .values = { | ||
5085 | HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT), | ||
5086 | HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT), | ||
5087 | 0 | ||
5088 | }, | ||
5089 | }; | ||
5090 | |||
5091 | /* bind volumes of both NID 0x02 and 0x05 */ | ||
5092 | static struct hda_bind_ctls vaio_bind_master_sw = { | ||
5093 | .ops = &snd_hda_bind_sw, | ||
5094 | .values = { | ||
5095 | HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT), | ||
5096 | HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT), | ||
5097 | 0, | ||
5098 | }, | ||
5099 | }; | ||
5100 | |||
5101 | static struct snd_kcontrol_new vaio_mixer[] = { | 5299 | static struct snd_kcontrol_new vaio_mixer[] = { |
5102 | HDA_BIND_VOL("Master Playback Volume", &vaio_bind_master_vol), | 5300 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x02, 0, HDA_OUTPUT), |
5103 | HDA_BIND_SW("Master Playback Switch", &vaio_bind_master_sw), | 5301 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x02, 0, HDA_OUTPUT), |
5302 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x05, 0, HDA_OUTPUT), | ||
5303 | HDA_CODEC_MUTE("Speaker Playback Switch", 0x05, 0, HDA_OUTPUT), | ||
5104 | /* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */ | 5304 | /* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */ |
5105 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT), | 5305 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT), |
5106 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT), | 5306 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT), |
@@ -5116,8 +5316,10 @@ static struct snd_kcontrol_new vaio_mixer[] = { | |||
5116 | }; | 5316 | }; |
5117 | 5317 | ||
5118 | static struct snd_kcontrol_new vaio_ar_mixer[] = { | 5318 | static struct snd_kcontrol_new vaio_ar_mixer[] = { |
5119 | HDA_BIND_VOL("Master Playback Volume", &vaio_bind_master_vol), | 5319 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x02, 0, HDA_OUTPUT), |
5120 | HDA_BIND_SW("Master Playback Switch", &vaio_bind_master_sw), | 5320 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x02, 0, HDA_OUTPUT), |
5321 | HDA_CODEC_VOLUME("Speaker Playback Volume", 0x05, 0, HDA_OUTPUT), | ||
5322 | HDA_CODEC_MUTE("Speaker Playback Switch", 0x05, 0, HDA_OUTPUT), | ||
5121 | /* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */ | 5323 | /* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */ |
5122 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT), | 5324 | HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT), |
5123 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT), | 5325 | HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT), |
@@ -5158,7 +5360,7 @@ static int stac9872_vaio_init(struct hda_codec *codec) | |||
5158 | 5360 | ||
5159 | static void stac9872_vaio_hp_detect(struct hda_codec *codec, unsigned int res) | 5361 | static void stac9872_vaio_hp_detect(struct hda_codec *codec, unsigned int res) |
5160 | { | 5362 | { |
5161 | if (get_hp_pin_presence(codec, 0x0a)) { | 5363 | if (get_pin_presence(codec, 0x0a)) { |
5162 | stac92xx_reset_pinctl(codec, 0x0f, AC_PINCTL_OUT_EN); | 5364 | stac92xx_reset_pinctl(codec, 0x0f, AC_PINCTL_OUT_EN); |
5163 | stac92xx_set_pinctl(codec, 0x0a, AC_PINCTL_OUT_EN); | 5365 | stac92xx_set_pinctl(codec, 0x0a, AC_PINCTL_OUT_EN); |
5164 | } else { | 5366 | } else { |
@@ -5269,7 +5471,7 @@ static int patch_stac9872(struct hda_codec *codec) | |||
5269 | /* | 5471 | /* |
5270 | * patch entries | 5472 | * patch entries |
5271 | */ | 5473 | */ |
5272 | struct hda_codec_preset snd_hda_preset_sigmatel[] = { | 5474 | static struct hda_codec_preset snd_hda_preset_sigmatel[] = { |
5273 | { .id = 0x83847690, .name = "STAC9200", .patch = patch_stac9200 }, | 5475 | { .id = 0x83847690, .name = "STAC9200", .patch = patch_stac9200 }, |
5274 | { .id = 0x83847882, .name = "STAC9220 A1", .patch = patch_stac922x }, | 5476 | { .id = 0x83847882, .name = "STAC9220 A1", .patch = patch_stac922x }, |
5275 | { .id = 0x83847680, .name = "STAC9221 A1", .patch = patch_stac922x }, | 5477 | { .id = 0x83847680, .name = "STAC9221 A1", .patch = patch_stac922x }, |
@@ -5333,3 +5535,27 @@ struct hda_codec_preset snd_hda_preset_sigmatel[] = { | |||
5333 | { .id = 0x111d76b7, .name = "92HD71B5X", .patch = patch_stac92hd71bxx }, | 5535 | { .id = 0x111d76b7, .name = "92HD71B5X", .patch = patch_stac92hd71bxx }, |
5334 | {} /* terminator */ | 5536 | {} /* terminator */ |
5335 | }; | 5537 | }; |
5538 | |||
5539 | MODULE_ALIAS("snd-hda-codec-id:8384*"); | ||
5540 | MODULE_ALIAS("snd-hda-codec-id:111d*"); | ||
5541 | |||
5542 | MODULE_LICENSE("GPL"); | ||
5543 | MODULE_DESCRIPTION("IDT/Sigmatel HD-audio codec"); | ||
5544 | |||
5545 | static struct hda_codec_preset_list sigmatel_list = { | ||
5546 | .preset = snd_hda_preset_sigmatel, | ||
5547 | .owner = THIS_MODULE, | ||
5548 | }; | ||
5549 | |||
5550 | static int __init patch_sigmatel_init(void) | ||
5551 | { | ||
5552 | return snd_hda_add_codec_preset(&sigmatel_list); | ||
5553 | } | ||
5554 | |||
5555 | static void __exit patch_sigmatel_exit(void) | ||
5556 | { | ||
5557 | snd_hda_delete_codec_preset(&sigmatel_list); | ||
5558 | } | ||
5559 | |||
5560 | module_init(patch_sigmatel_init) | ||
5561 | module_exit(patch_sigmatel_exit) | ||