]>
Commit | Line | Data |
---|---|---|
2cb7cef9 BS |
1 | From: Takashi Iwai <tiwai@suse.de> |
2 | Subject: Backport fixes for patch_sigmatel.c from 2.6.29 | |
3 | Patch-mainline: 2.6.29 | |
4 | References: bcn#457472, bnc#462913, bnc#467381, bnc#479558, bnc#480617, bnc#480809 | |
5 | ||
6 | Backport patch_sigmatel fixes from 2.6.29. | |
7 | This includes fixes for multiple Dell and HP laptops. | |
8 | ||
9 | Signed-off-by: Takashi Iwai <tiwai@suse.de> | |
10 | ||
11 | --- | |
12 | sound/pci/hda/patch_sigmatel.c | 896 +++++++++++++++++++++-------------------- | |
13 | 1 file changed, 480 insertions(+), 416 deletions(-) | |
14 | ||
15 | --- a/sound/pci/hda/patch_sigmatel.c | |
16 | +++ b/sound/pci/hda/patch_sigmatel.c | |
17 | @@ -82,6 +82,7 @@ | |
18 | ||
19 | enum { | |
20 | STAC_92HD83XXX_REF, | |
21 | + STAC_92HD83XXX_PWR_REF, | |
22 | STAC_92HD83XXX_MODELS | |
23 | }; | |
24 | ||
25 | @@ -144,6 +145,13 @@ | |
26 | STAC_927X_MODELS | |
27 | }; | |
28 | ||
29 | +struct sigmatel_event { | |
30 | + hda_nid_t nid; | |
31 | + unsigned char type; | |
32 | + unsigned char tag; | |
33 | + int data; | |
34 | +}; | |
35 | + | |
36 | struct sigmatel_spec { | |
37 | struct snd_kcontrol_new *mixers[4]; | |
38 | unsigned int num_mixers; | |
39 | @@ -151,8 +159,6 @@ | |
40 | int board_config; | |
41 | unsigned int eapd_switch: 1; | |
42 | unsigned int surr_switch: 1; | |
43 | - unsigned int line_switch: 1; | |
44 | - unsigned int mic_switch: 1; | |
45 | unsigned int alt_switch: 1; | |
46 | unsigned int hp_detect: 1; | |
47 | unsigned int spdif_mute: 1; | |
48 | @@ -178,12 +184,18 @@ | |
49 | hda_nid_t *pwr_nids; | |
50 | hda_nid_t *dac_list; | |
51 | ||
52 | + /* events */ | |
53 | + int num_events; | |
54 | + struct sigmatel_event events[32]; | |
55 | + | |
56 | /* playback */ | |
57 | struct hda_input_mux *mono_mux; | |
58 | struct hda_input_mux *amp_mux; | |
59 | unsigned int cur_mmux; | |
60 | struct hda_multi_out multiout; | |
61 | hda_nid_t dac_nids[5]; | |
62 | + hda_nid_t hp_dacs[5]; | |
63 | + hda_nid_t speaker_dacs[5]; | |
64 | ||
65 | int volume_offset; | |
66 | ||
67 | @@ -230,7 +242,9 @@ | |
68 | /* i/o switches */ | |
69 | unsigned int io_switch[2]; | |
70 | unsigned int clfe_swap; | |
71 | - unsigned int hp_switch; /* NID of HP as line-out */ | |
72 | + hda_nid_t line_switch; /* shared line-in for input and output */ | |
73 | + hda_nid_t mic_switch; /* shared mic-in for input and output */ | |
74 | + hda_nid_t hp_switch; /* NID of HP as line-out */ | |
75 | unsigned int aloopback; | |
76 | ||
77 | struct hda_pcm pcm_rec[2]; /* PCM information */ | |
78 | @@ -282,9 +296,6 @@ | |
79 | }; | |
80 | ||
81 | #define STAC92HD73_DAC_COUNT 5 | |
82 | -static hda_nid_t stac92hd73xx_dac_nids[STAC92HD73_DAC_COUNT] = { | |
83 | - 0x15, 0x16, 0x17, 0x18, 0x19, | |
84 | -}; | |
85 | ||
86 | static hda_nid_t stac92hd73xx_mux_nids[4] = { | |
87 | 0x28, 0x29, 0x2a, 0x2b, | |
88 | @@ -303,11 +314,7 @@ | |
89 | 0x11, 0x12, 0 | |
90 | }; | |
91 | ||
92 | -#define STAC92HD81_DAC_COUNT 2 | |
93 | #define STAC92HD83_DAC_COUNT 3 | |
94 | -static hda_nid_t stac92hd83xxx_dac_nids[STAC92HD73_DAC_COUNT] = { | |
95 | - 0x13, 0x14, 0x22, | |
96 | -}; | |
97 | ||
98 | static hda_nid_t stac92hd83xxx_dmux_nids[2] = { | |
99 | 0x17, 0x18, | |
100 | @@ -326,7 +333,11 @@ | |
101 | }; | |
102 | ||
103 | static unsigned int stac92hd83xxx_pwr_mapping[4] = { | |
104 | - 0x03, 0x0c, 0x10, 0x40, | |
105 | + 0x03, 0x0c, 0x20, 0x40, | |
106 | +}; | |
107 | + | |
108 | +static hda_nid_t stac92hd83xxx_amp_nids[1] = { | |
109 | + 0xc, | |
110 | }; | |
111 | ||
112 | static hda_nid_t stac92hd71bxx_pwr_nids[3] = { | |
113 | @@ -349,10 +360,6 @@ | |
114 | 0x24, 0x25, | |
115 | }; | |
116 | ||
117 | -static hda_nid_t stac92hd71bxx_dac_nids[1] = { | |
118 | - 0x10, /*0x11, */ | |
119 | -}; | |
120 | - | |
121 | #define STAC92HD71BXX_NUM_DMICS 2 | |
122 | static hda_nid_t stac92hd71bxx_dmic_nids[STAC92HD71BXX_NUM_DMICS + 1] = { | |
123 | 0x18, 0x19, 0 | |
124 | @@ -584,12 +591,12 @@ | |
125 | else | |
126 | nid = codec->slave_dig_outs[smux_idx - 1]; | |
127 | if (spec->cur_smux[smux_idx] == smux->num_items - 1) | |
128 | - val = AMP_OUT_MUTE; | |
129 | + val = HDA_AMP_MUTE; | |
130 | else | |
131 | - val = AMP_OUT_UNMUTE; | |
132 | + val = 0; | |
133 | /* un/mute SPDIF out */ | |
134 | - snd_hda_codec_write_cache(codec, nid, 0, | |
135 | - AC_VERB_SET_AMP_GAIN_MUTE, val); | |
136 | + snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0, | |
137 | + HDA_AMP_MUTE, val); | |
138 | } | |
139 | return 0; | |
140 | } | |
141 | @@ -754,10 +761,6 @@ | |
142 | static struct hda_verb stac92hd73xx_6ch_core_init[] = { | |
143 | /* set master volume and direct control */ | |
144 | { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, | |
145 | - /* setup audio connections */ | |
146 | - { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00}, | |
147 | - { 0x10, AC_VERB_SET_CONNECT_SEL, 0x01}, | |
148 | - { 0x11, AC_VERB_SET_CONNECT_SEL, 0x02}, | |
149 | /* setup adcs to point to mixer */ | |
150 | { 0x20, AC_VERB_SET_CONNECT_SEL, 0x0b}, | |
151 | { 0x21, AC_VERB_SET_CONNECT_SEL, 0x0b}, | |
152 | @@ -776,10 +779,6 @@ | |
153 | /* set master volume to max value without distortion | |
154 | * and direct control */ | |
155 | { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xec}, | |
156 | - /* setup audio connections */ | |
157 | - { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00}, | |
158 | - { 0x0a, AC_VERB_SET_CONNECT_SEL, 0x02}, | |
159 | - { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x01}, | |
160 | /* setup adcs to point to mixer */ | |
161 | { 0x20, AC_VERB_SET_CONNECT_SEL, 0x0b}, | |
162 | { 0x21, AC_VERB_SET_CONNECT_SEL, 0x0b}, | |
163 | @@ -793,10 +792,6 @@ | |
164 | ||
165 | static struct hda_verb dell_m6_core_init[] = { | |
166 | { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, | |
167 | - /* setup audio connections */ | |
168 | - { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00}, | |
169 | - { 0x0a, AC_VERB_SET_CONNECT_SEL, 0x01}, | |
170 | - { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x02}, | |
171 | /* setup adcs to point to mixer */ | |
172 | { 0x20, AC_VERB_SET_CONNECT_SEL, 0x0b}, | |
173 | { 0x21, AC_VERB_SET_CONNECT_SEL, 0x0b}, | |
174 | @@ -811,13 +806,6 @@ | |
175 | static struct hda_verb stac92hd73xx_8ch_core_init[] = { | |
176 | /* set master volume and direct control */ | |
177 | { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, | |
178 | - /* setup audio connections */ | |
179 | - { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00}, | |
180 | - { 0x10, AC_VERB_SET_CONNECT_SEL, 0x01}, | |
181 | - { 0x11, AC_VERB_SET_CONNECT_SEL, 0x02}, | |
182 | - /* connect hp ports to dac3 */ | |
183 | - { 0x0a, AC_VERB_SET_CONNECT_SEL, 0x03}, | |
184 | - { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x03}, | |
185 | /* setup adcs to point to mixer */ | |
186 | { 0x20, AC_VERB_SET_CONNECT_SEL, 0x0b}, | |
187 | { 0x21, AC_VERB_SET_CONNECT_SEL, 0x0b}, | |
188 | @@ -835,15 +823,8 @@ | |
189 | static struct hda_verb stac92hd73xx_10ch_core_init[] = { | |
190 | /* set master volume and direct control */ | |
191 | { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, | |
192 | - /* setup audio connections */ | |
193 | - { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 }, | |
194 | - { 0x10, AC_VERB_SET_CONNECT_SEL, 0x01 }, | |
195 | - { 0x11, AC_VERB_SET_CONNECT_SEL, 0x02 }, | |
196 | /* dac3 is connected to import3 mux */ | |
197 | { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb07f}, | |
198 | - /* connect hp ports to dac4 */ | |
199 | - { 0x0a, AC_VERB_SET_CONNECT_SEL, 0x04}, | |
200 | - { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x04}, | |
201 | /* setup adcs to point to mixer */ | |
202 | { 0x20, AC_VERB_SET_CONNECT_SEL, 0x0b}, | |
203 | { 0x21, AC_VERB_SET_CONNECT_SEL, 0x0b}, | |
204 | @@ -859,10 +840,6 @@ | |
205 | }; | |
206 | ||
207 | static struct hda_verb stac92hd83xxx_core_init[] = { | |
208 | - /* start of config #1 */ | |
209 | - { 0xe, AC_VERB_SET_CONNECT_SEL, 0x3}, | |
210 | - | |
211 | - /* start of config #2 */ | |
212 | { 0xa, AC_VERB_SET_CONNECT_SEL, 0x0}, | |
213 | { 0xb, AC_VERB_SET_CONNECT_SEL, 0x0}, | |
214 | { 0xd, AC_VERB_SET_CONNECT_SEL, 0x1}, | |
215 | @@ -875,8 +852,6 @@ | |
216 | static struct hda_verb stac92hd71bxx_core_init[] = { | |
217 | /* set master volume and direct control */ | |
218 | { 0x28, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, | |
219 | - /* connect headphone jack to dac1 */ | |
220 | - { 0x0a, AC_VERB_SET_CONNECT_SEL, 0x01}, | |
221 | /* unmute right and left channels for nodes 0x0a, 0xd, 0x0f */ | |
222 | { 0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | |
223 | { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | |
224 | @@ -896,8 +871,6 @@ | |
225 | ||
226 | /* set master volume and direct control */ | |
227 | { 0x28, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, | |
228 | - /* connect headphone jack to dac1 */ | |
229 | - { 0x0a, AC_VERB_SET_CONNECT_SEL, 0x01}, | |
230 | /* unmute right and left channels for nodes 0x0a, 0xd */ | |
231 | { 0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | |
232 | { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | |
233 | @@ -1099,21 +1072,21 @@ | |
234 | HDA_CODEC_VOLUME_IDX("Capture Volume", 0x1, 0x18, 0x0, HDA_OUTPUT), | |
235 | HDA_CODEC_MUTE_IDX("Capture Switch", 0x1, 0x18, 0x0, HDA_OUTPUT), | |
236 | ||
237 | - HDA_CODEC_VOLUME("DAC0 Capture Volume", 0x1b, 0, HDA_INPUT), | |
238 | - HDA_CODEC_MUTE("DAC0 Capture Switch", 0x1b, 0, HDA_INPUT), | |
239 | + HDA_CODEC_VOLUME("DAC0 Capture Volume", 0x1b, 0x3, HDA_INPUT), | |
240 | + HDA_CODEC_MUTE("DAC0 Capture Switch", 0x1b, 0x3, HDA_INPUT), | |
241 | ||
242 | - HDA_CODEC_VOLUME("DAC1 Capture Volume", 0x1b, 0x1, HDA_INPUT), | |
243 | - HDA_CODEC_MUTE("DAC1 Capture Switch", 0x1b, 0x1, HDA_INPUT), | |
244 | + HDA_CODEC_VOLUME("DAC1 Capture Volume", 0x1b, 0x4, HDA_INPUT), | |
245 | + HDA_CODEC_MUTE("DAC1 Capture Switch", 0x1b, 0x4, HDA_INPUT), | |
246 | ||
247 | - HDA_CODEC_VOLUME("Front Mic Capture Volume", 0x1b, 0x2, HDA_INPUT), | |
248 | - HDA_CODEC_MUTE("Front Mic Capture Switch", 0x1b, 0x2, HDA_INPUT), | |
249 | + HDA_CODEC_VOLUME("Front Mic Capture Volume", 0x1b, 0x0, HDA_INPUT), | |
250 | + HDA_CODEC_MUTE("Front Mic Capture Switch", 0x1b, 0x0, HDA_INPUT), | |
251 | ||
252 | - HDA_CODEC_VOLUME("Line In Capture Volume", 0x1b, 0x3, HDA_INPUT), | |
253 | - HDA_CODEC_MUTE("Line In Capture Switch", 0x1b, 0x3, HDA_INPUT), | |
254 | + HDA_CODEC_VOLUME("Line In Capture Volume", 0x1b, 0x2, HDA_INPUT), | |
255 | + HDA_CODEC_MUTE("Line In Capture Switch", 0x1b, 0x2, HDA_INPUT), | |
256 | ||
257 | /* | |
258 | - HDA_CODEC_VOLUME("Mic Capture Volume", 0x1b, 0x4, HDA_INPUT), | |
259 | - HDA_CODEC_MUTE("Mic Capture Switch", 0x1b 0x4, HDA_INPUT), | |
260 | + HDA_CODEC_VOLUME("Mic Capture Volume", 0x1b, 0x1, HDA_INPUT), | |
261 | + HDA_CODEC_MUTE("Mic Capture Switch", 0x1b 0x1, HDA_INPUT), | |
262 | */ | |
263 | { } /* end */ | |
264 | }; | |
265 | @@ -1726,10 +1699,12 @@ | |
266 | ||
267 | static unsigned int *stac92hd83xxx_brd_tbl[STAC_92HD83XXX_MODELS] = { | |
268 | [STAC_92HD83XXX_REF] = ref92hd83xxx_pin_configs, | |
269 | + [STAC_92HD83XXX_PWR_REF] = ref92hd83xxx_pin_configs, | |
270 | }; | |
271 | ||
272 | static const char *stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = { | |
273 | [STAC_92HD83XXX_REF] = "ref", | |
274 | + [STAC_92HD83XXX_PWR_REF] = "mic-ref", | |
275 | }; | |
276 | ||
277 | static struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { | |
278 | @@ -1788,11 +1763,13 @@ | |
279 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x30f2, | |
280 | "HP dv5", STAC_HP_M4), | |
281 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x30f4, | |
282 | - "HP dv7", STAC_HP_M4), | |
283 | + "HP dv7", STAC_HP_DV5), | |
284 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x30f7, | |
285 | "HP dv4", STAC_HP_DV5), | |
286 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x30fc, | |
287 | "HP dv7", STAC_HP_M4), | |
288 | + SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3600, | |
289 | + "HP dv5", STAC_HP_DV5), | |
290 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3603, | |
291 | "HP dv5", STAC_HP_DV5), | |
292 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x361a, | |
293 | @@ -2419,7 +2396,7 @@ | |
294 | ||
295 | if (spec->powerdown_adcs) { | |
296 | msleep(40); | |
297 | - snd_hda_codec_write_cache(codec, nid, 0, | |
298 | + snd_hda_codec_write(codec, nid, 0, | |
299 | AC_VERB_SET_POWER_STATE, AC_PWRST_D0); | |
300 | } | |
301 | snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format); | |
302 | @@ -2435,7 +2412,7 @@ | |
303 | ||
304 | snd_hda_codec_cleanup_stream(codec, nid); | |
305 | if (spec->powerdown_adcs) | |
306 | - snd_hda_codec_write_cache(codec, nid, 0, | |
307 | + snd_hda_codec_write(codec, nid, 0, | |
308 | AC_VERB_SET_POWER_STATE, AC_PWRST_D3); | |
309 | return 0; | |
310 | } | |
311 | @@ -2569,6 +2546,9 @@ | |
312 | return 0; | |
313 | } | |
314 | ||
315 | +static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid, | |
316 | + unsigned char type); | |
317 | + | |
318 | static int stac92xx_hp_switch_put(struct snd_kcontrol *kcontrol, | |
319 | struct snd_ctl_elem_value *ucontrol) | |
320 | { | |
321 | @@ -2581,8 +2561,7 @@ | |
322 | /* check to be sure that the ports are upto date with | |
323 | * switch changes | |
324 | */ | |
325 | - codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26); | |
326 | - | |
327 | + stac_issue_unsol_event(codec, nid, STAC_HP_EVENT); | |
328 | return 1; | |
329 | } | |
330 | ||
331 | @@ -2621,7 +2600,7 @@ | |
332 | * appropriately according to the pin direction | |
333 | */ | |
334 | if (spec->hp_detect) | |
335 | - codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26); | |
336 | + stac_issue_unsol_event(codec, nid, STAC_HP_EVENT); | |
337 | ||
338 | return 1; | |
339 | } | |
340 | @@ -2758,70 +2737,53 @@ | |
341 | return stac92xx_add_control_idx(spec, type, 0, name, val); | |
342 | } | |
343 | ||
344 | -/* flag inputs as additional dynamic lineouts */ | |
345 | -static int stac92xx_add_dyn_out_pins(struct hda_codec *codec, struct auto_pin_cfg *cfg) | |
346 | +/* check whether the line-input can be used as line-out */ | |
347 | +static hda_nid_t check_line_out_switch(struct hda_codec *codec) | |
348 | { | |
349 | struct sigmatel_spec *spec = codec->spec; | |
350 | - unsigned int wcaps, wtype; | |
351 | - int i, num_dacs = 0; | |
352 | - | |
353 | - /* use the wcaps cache to count all DACs available for line-outs */ | |
354 | - for (i = 0; i < codec->num_nodes; i++) { | |
355 | - wcaps = codec->wcaps[i]; | |
356 | - wtype = (wcaps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; | |
357 | + struct auto_pin_cfg *cfg = &spec->autocfg; | |
358 | + hda_nid_t nid; | |
359 | + unsigned int pincap; | |
360 | ||
361 | - if (wtype == AC_WID_AUD_OUT && !(wcaps & AC_WCAP_DIGITAL)) | |
362 | - num_dacs++; | |
363 | - } | |
364 | + if (cfg->line_out_type != AUTO_PIN_LINE_OUT) | |
365 | + return 0; | |
366 | + nid = cfg->input_pins[AUTO_PIN_LINE]; | |
367 | + pincap = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); | |
368 | + if (pincap & AC_PINCAP_OUT) | |
369 | + return nid; | |
370 | + return 0; | |
371 | +} | |
372 | ||
373 | - snd_printdd("%s: total dac count=%d\n", __func__, num_dacs); | |
374 | - | |
375 | - switch (cfg->line_outs) { | |
376 | - case 3: | |
377 | - /* add line-in as side */ | |
378 | - if (cfg->input_pins[AUTO_PIN_LINE] && num_dacs > 3) { | |
379 | - cfg->line_out_pins[cfg->line_outs] = | |
380 | - cfg->input_pins[AUTO_PIN_LINE]; | |
381 | - spec->line_switch = 1; | |
382 | - cfg->line_outs++; | |
383 | - } | |
384 | - break; | |
385 | - case 2: | |
386 | - /* add line-in as clfe and mic as side */ | |
387 | - if (cfg->input_pins[AUTO_PIN_LINE] && num_dacs > 2) { | |
388 | - cfg->line_out_pins[cfg->line_outs] = | |
389 | - cfg->input_pins[AUTO_PIN_LINE]; | |
390 | - spec->line_switch = 1; | |
391 | - cfg->line_outs++; | |
392 | - } | |
393 | - if (cfg->input_pins[AUTO_PIN_MIC] && num_dacs > 3) { | |
394 | - cfg->line_out_pins[cfg->line_outs] = | |
395 | - cfg->input_pins[AUTO_PIN_MIC]; | |
396 | - spec->mic_switch = 1; | |
397 | - cfg->line_outs++; | |
398 | - } | |
399 | - break; | |
400 | - case 1: | |
401 | - /* add line-in as surr and mic as clfe */ | |
402 | - if (cfg->input_pins[AUTO_PIN_LINE] && num_dacs > 1) { | |
403 | - cfg->line_out_pins[cfg->line_outs] = | |
404 | - cfg->input_pins[AUTO_PIN_LINE]; | |
405 | - spec->line_switch = 1; | |
406 | - cfg->line_outs++; | |
407 | - } | |
408 | - if (cfg->input_pins[AUTO_PIN_MIC] && num_dacs > 2) { | |
409 | - cfg->line_out_pins[cfg->line_outs] = | |
410 | - cfg->input_pins[AUTO_PIN_MIC]; | |
411 | - spec->mic_switch = 1; | |
412 | - cfg->line_outs++; | |
413 | +/* check whether the mic-input can be used as line-out */ | |
414 | +static hda_nid_t check_mic_out_switch(struct hda_codec *codec) | |
415 | +{ | |
416 | + struct sigmatel_spec *spec = codec->spec; | |
417 | + struct auto_pin_cfg *cfg = &spec->autocfg; | |
418 | + unsigned int def_conf, pincap; | |
419 | + unsigned int mic_pin; | |
420 | + | |
421 | + if (cfg->line_out_type != AUTO_PIN_LINE_OUT) | |
422 | + return 0; | |
423 | + mic_pin = AUTO_PIN_MIC; | |
424 | + for (;;) { | |
425 | + hda_nid_t nid = cfg->input_pins[mic_pin]; | |
426 | + def_conf = snd_hda_codec_read(codec, nid, 0, | |
427 | + AC_VERB_GET_CONFIG_DEFAULT, 0); | |
428 | + /* some laptops have an internal analog microphone | |
429 | + * which can't be used as a output */ | |
430 | + if (get_defcfg_connect(def_conf) != AC_JACK_PORT_FIXED) { | |
431 | + pincap = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP); | |
432 | + if (pincap & AC_PINCAP_OUT) | |
433 | + return nid; | |
434 | } | |
435 | - break; | |
436 | + if (mic_pin == AUTO_PIN_MIC) | |
437 | + mic_pin = AUTO_PIN_FRONT_MIC; | |
438 | + else | |
439 | + break; | |
440 | } | |
441 | - | |
442 | return 0; | |
443 | } | |
444 | ||
445 | - | |
446 | static int is_in_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid) | |
447 | { | |
448 | int i; | |
449 | @@ -2834,6 +2796,52 @@ | |
450 | return 0; | |
451 | } | |
452 | ||
453 | +static int check_all_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid) | |
454 | +{ | |
455 | + int i; | |
456 | + if (is_in_dac_nids(spec, nid)) | |
457 | + return 1; | |
458 | + for (i = 0; i < spec->autocfg.hp_outs; i++) | |
459 | + if (spec->hp_dacs[i] == nid) | |
460 | + return 1; | |
461 | + for (i = 0; i < spec->autocfg.speaker_outs; i++) | |
462 | + if (spec->speaker_dacs[i] == nid) | |
463 | + return 1; | |
464 | + return 0; | |
465 | +} | |
466 | + | |
467 | +static hda_nid_t get_unassigned_dac(struct hda_codec *codec, hda_nid_t nid) | |
468 | +{ | |
469 | + struct sigmatel_spec *spec = codec->spec; | |
470 | + int j, conn_len; | |
471 | + hda_nid_t conn[HDA_MAX_CONNECTIONS]; | |
472 | + unsigned int wcaps, wtype; | |
473 | + | |
474 | + conn_len = snd_hda_get_connections(codec, nid, conn, | |
475 | + HDA_MAX_CONNECTIONS); | |
476 | + for (j = 0; j < conn_len; j++) { | |
477 | + wcaps = snd_hda_param_read(codec, conn[j], | |
478 | + AC_PAR_AUDIO_WIDGET_CAP); | |
479 | + wtype = (wcaps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; | |
480 | + /* we check only analog outputs */ | |
481 | + if (wtype != AC_WID_AUD_OUT || (wcaps & AC_WCAP_DIGITAL)) | |
482 | + continue; | |
483 | + /* if this route has a free DAC, assign it */ | |
484 | + if (!check_all_dac_nids(spec, conn[j])) { | |
485 | + if (conn_len > 1) { | |
486 | + /* select this DAC in the pin's input mux */ | |
487 | + snd_hda_codec_write_cache(codec, nid, 0, | |
488 | + AC_VERB_SET_CONNECT_SEL, j); | |
489 | + } | |
490 | + return conn[j]; | |
491 | + } | |
492 | + } | |
493 | + return 0; | |
494 | +} | |
495 | + | |
496 | +static int add_spec_dacs(struct sigmatel_spec *spec, hda_nid_t nid); | |
497 | +static int add_spec_extra_dacs(struct sigmatel_spec *spec, hda_nid_t nid); | |
498 | + | |
499 | /* | |
500 | * Fill in the dac_nids table from the parsed pin configuration | |
501 | * This function only works when every pin in line_out_pins[] | |
502 | @@ -2841,31 +2849,17 @@ | |
503 | * codecs are not connected directly to a DAC, such as the 9200 | |
504 | * and 9202/925x. For those, dac_nids[] must be hard-coded. | |
505 | */ | |
506 | -static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec, | |
507 | - struct auto_pin_cfg *cfg) | |
508 | +static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec) | |
509 | { | |
510 | struct sigmatel_spec *spec = codec->spec; | |
511 | - int i, j, conn_len = 0; | |
512 | - hda_nid_t nid, conn[HDA_MAX_CONNECTIONS]; | |
513 | - unsigned int wcaps, wtype; | |
514 | + struct auto_pin_cfg *cfg = &spec->autocfg; | |
515 | + int i; | |
516 | + hda_nid_t nid, dac; | |
517 | ||
518 | for (i = 0; i < cfg->line_outs; i++) { | |
519 | nid = cfg->line_out_pins[i]; | |
520 | - conn_len = snd_hda_get_connections(codec, nid, conn, | |
521 | - HDA_MAX_CONNECTIONS); | |
522 | - for (j = 0; j < conn_len; j++) { | |
523 | - wcaps = snd_hda_param_read(codec, conn[j], | |
524 | - AC_PAR_AUDIO_WIDGET_CAP); | |
525 | - wtype = (wcaps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; | |
526 | - if (wtype != AC_WID_AUD_OUT || | |
527 | - (wcaps & AC_WCAP_DIGITAL)) | |
528 | - continue; | |
529 | - /* conn[j] is a DAC routed to this line-out */ | |
530 | - if (!is_in_dac_nids(spec, conn[j])) | |
531 | - break; | |
532 | - } | |
533 | - | |
534 | - if (j == conn_len) { | |
535 | + dac = get_unassigned_dac(codec, nid); | |
536 | + if (!dac) { | |
537 | if (spec->multiout.num_dacs > 0) { | |
538 | /* we have already working output pins, | |
539 | * so let's drop the broken ones again | |
540 | @@ -2879,24 +2873,64 @@ | |
541 | __func__, nid); | |
542 | return -ENODEV; | |
543 | } | |
544 | + add_spec_dacs(spec, dac); | |
545 | + } | |
546 | ||
547 | - spec->multiout.dac_nids[i] = conn[j]; | |
548 | - spec->multiout.num_dacs++; | |
549 | - if (conn_len > 1) { | |
550 | - /* select this DAC in the pin's input mux */ | |
551 | - snd_hda_codec_write_cache(codec, nid, 0, | |
552 | - AC_VERB_SET_CONNECT_SEL, j); | |
553 | + /* add line-in as output */ | |
554 | + nid = check_line_out_switch(codec); | |
555 | + if (nid) { | |
556 | + dac = get_unassigned_dac(codec, nid); | |
557 | + if (dac) { | |
558 | + snd_printdd("STAC: Add line-in 0x%x as output %d\n", | |
559 | + nid, cfg->line_outs); | |
560 | + cfg->line_out_pins[cfg->line_outs] = nid; | |
561 | + cfg->line_outs++; | |
562 | + spec->line_switch = nid; | |
563 | + add_spec_dacs(spec, dac); | |
564 | + } | |
565 | + } | |
566 | + /* add mic as output */ | |
567 | + nid = check_mic_out_switch(codec); | |
568 | + if (nid) { | |
569 | + dac = get_unassigned_dac(codec, nid); | |
570 | + if (dac) { | |
571 | + snd_printdd("STAC: Add mic-in 0x%x as output %d\n", | |
572 | + nid, cfg->line_outs); | |
573 | + cfg->line_out_pins[cfg->line_outs] = nid; | |
574 | + cfg->line_outs++; | |
575 | + spec->mic_switch = nid; | |
576 | + add_spec_dacs(spec, dac); | |
577 | + } | |
578 | + } | |
579 | ||
580 | + for (i = 0; i < cfg->hp_outs; i++) { | |
581 | + nid = cfg->hp_pins[i]; | |
582 | + dac = get_unassigned_dac(codec, nid); | |
583 | + if (dac) { | |
584 | + if (!spec->multiout.hp_nid) | |
585 | + spec->multiout.hp_nid = dac; | |
586 | + else | |
587 | + add_spec_extra_dacs(spec, dac); | |
588 | } | |
589 | + spec->hp_dacs[i] = dac; | |
590 | } | |
591 | ||
592 | - snd_printd("dac_nids=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n", | |
593 | + for (i = 0; i < cfg->speaker_outs; i++) { | |
594 | + nid = cfg->speaker_pins[i]; | |
595 | + dac = get_unassigned_dac(codec, nid); | |
596 | + if (dac) | |
597 | + add_spec_extra_dacs(spec, dac); | |
598 | + spec->speaker_dacs[i] = dac; | |
599 | + } | |
600 | + | |
601 | + snd_printd("stac92xx: dac_nids=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n", | |
602 | spec->multiout.num_dacs, | |
603 | spec->multiout.dac_nids[0], | |
604 | spec->multiout.dac_nids[1], | |
605 | spec->multiout.dac_nids[2], | |
606 | spec->multiout.dac_nids[3], | |
607 | spec->multiout.dac_nids[4]); | |
608 | + | |
609 | return 0; | |
610 | } | |
611 | ||
612 | @@ -2941,9 +2975,7 @@ | |
613 | ||
614 | static int add_spec_dacs(struct sigmatel_spec *spec, hda_nid_t nid) | |
615 | { | |
616 | - if (!spec->multiout.hp_nid) | |
617 | - spec->multiout.hp_nid = nid; | |
618 | - else if (spec->multiout.num_dacs > 4) { | |
619 | + if (spec->multiout.num_dacs > 4) { | |
620 | printk(KERN_WARNING "stac92xx: No space for DAC 0x%x\n", nid); | |
621 | return 1; | |
622 | } else { | |
623 | @@ -2953,35 +2985,47 @@ | |
624 | return 0; | |
625 | } | |
626 | ||
627 | -static int check_in_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid) | |
628 | +static int add_spec_extra_dacs(struct sigmatel_spec *spec, hda_nid_t nid) | |
629 | { | |
630 | - if (is_in_dac_nids(spec, nid)) | |
631 | - return 1; | |
632 | + int i; | |
633 | + for (i = 0; i < ARRAY_SIZE(spec->multiout.extra_out_nid); i++) { | |
634 | + if (!spec->multiout.extra_out_nid[i]) { | |
635 | + spec->multiout.extra_out_nid[i] = nid; | |
636 | + return 0; | |
637 | + } | |
638 | + } | |
639 | + printk(KERN_WARNING "stac92xx: No space for extra DAC 0x%x\n", nid); | |
640 | + return 1; | |
641 | +} | |
642 | + | |
643 | +static int is_unique_dac(struct sigmatel_spec *spec, hda_nid_t nid) | |
644 | +{ | |
645 | + int i; | |
646 | + | |
647 | + if (spec->autocfg.line_outs != 1) | |
648 | + return 0; | |
649 | if (spec->multiout.hp_nid == nid) | |
650 | - return 1; | |
651 | - return 0; | |
652 | + return 0; | |
653 | + for (i = 0; i < ARRAY_SIZE(spec->multiout.extra_out_nid); i++) | |
654 | + if (spec->multiout.extra_out_nid[i] == nid) | |
655 | + return 0; | |
656 | + return 1; | |
657 | } | |
658 | ||
659 | /* add playback controls from the parsed DAC table */ | |
660 | static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec, | |
661 | const struct auto_pin_cfg *cfg) | |
662 | { | |
663 | + struct sigmatel_spec *spec = codec->spec; | |
664 | static const char *chname[4] = { | |
665 | "Front", "Surround", NULL /*CLFE*/, "Side" | |
666 | }; | |
667 | hda_nid_t nid = 0; | |
668 | int i, err; | |
669 | + unsigned int wid_caps; | |
670 | ||
671 | - struct sigmatel_spec *spec = codec->spec; | |
672 | - unsigned int wid_caps, pincap; | |
673 | - | |
674 | - | |
675 | - for (i = 0; i < cfg->line_outs && i < spec->multiout.num_dacs; i++) { | |
676 | - if (!spec->multiout.dac_nids[i]) | |
677 | - continue; | |
678 | - | |
679 | + for (i = 0; i < cfg->line_outs && spec->multiout.dac_nids[i]; i++) { | |
680 | nid = spec->multiout.dac_nids[i]; | |
681 | - | |
682 | if (i == 2) { | |
683 | /* Center/LFE */ | |
684 | err = create_controls(codec, "Center", nid, 1); | |
685 | @@ -3003,16 +3047,24 @@ | |
686 | } | |
687 | ||
688 | } else { | |
689 | - err = create_controls(codec, chname[i], nid, 3); | |
690 | + const char *name = chname[i]; | |
691 | + /* if it's a single DAC, assign a better name */ | |
692 | + if (!i && is_unique_dac(spec, nid)) { | |
693 | + switch (cfg->line_out_type) { | |
694 | + case AUTO_PIN_HP_OUT: | |
695 | + name = "Headphone"; | |
696 | + break; | |
697 | + case AUTO_PIN_SPEAKER_OUT: | |
698 | + name = "Speaker"; | |
699 | + break; | |
700 | + } | |
701 | + } | |
702 | + err = create_controls(codec, name, nid, 3); | |
703 | if (err < 0) | |
704 | return err; | |
705 | } | |
706 | } | |
707 | ||
708 | - if ((spec->multiout.num_dacs - cfg->line_outs) > 0 && | |
709 | - cfg->hp_outs == 1 && !spec->multiout.hp_nid) | |
710 | - spec->multiout.hp_nid = nid; | |
711 | - | |
712 | if (cfg->hp_outs > 1 && cfg->line_out_type == AUTO_PIN_LINE_OUT) { | |
713 | err = stac92xx_add_control(spec, | |
714 | STAC_CTL_WIDGET_HP_SWITCH, | |
715 | @@ -3023,45 +3075,19 @@ | |
716 | } | |
717 | ||
718 | if (spec->line_switch) { | |
719 | - nid = cfg->input_pins[AUTO_PIN_LINE]; | |
720 | - pincap = snd_hda_param_read(codec, nid, | |
721 | - AC_PAR_PIN_CAP); | |
722 | - if (pincap & AC_PINCAP_OUT) { | |
723 | - err = stac92xx_add_control(spec, | |
724 | - STAC_CTL_WIDGET_IO_SWITCH, | |
725 | - "Line In as Output Switch", nid << 8); | |
726 | - if (err < 0) | |
727 | - return err; | |
728 | - } | |
729 | + err = stac92xx_add_control(spec, STAC_CTL_WIDGET_IO_SWITCH, | |
730 | + "Line In as Output Switch", | |
731 | + spec->line_switch << 8); | |
732 | + if (err < 0) | |
733 | + return err; | |
734 | } | |
735 | ||
736 | if (spec->mic_switch) { | |
737 | - unsigned int def_conf; | |
738 | - unsigned int mic_pin = AUTO_PIN_MIC; | |
739 | -again: | |
740 | - nid = cfg->input_pins[mic_pin]; | |
741 | - def_conf = snd_hda_codec_read(codec, nid, 0, | |
742 | - AC_VERB_GET_CONFIG_DEFAULT, 0); | |
743 | - /* some laptops have an internal analog microphone | |
744 | - * which can't be used as a output */ | |
745 | - if (get_defcfg_connect(def_conf) != AC_JACK_PORT_FIXED) { | |
746 | - pincap = snd_hda_param_read(codec, nid, | |
747 | - AC_PAR_PIN_CAP); | |
748 | - if (pincap & AC_PINCAP_OUT) { | |
749 | - err = stac92xx_add_control(spec, | |
750 | - STAC_CTL_WIDGET_IO_SWITCH, | |
751 | - "Mic as Output Switch", (nid << 8) | 1); | |
752 | - nid = snd_hda_codec_read(codec, nid, 0, | |
753 | - AC_VERB_GET_CONNECT_LIST, 0) & 0xff; | |
754 | - if (!check_in_dac_nids(spec, nid)) | |
755 | - add_spec_dacs(spec, nid); | |
756 | - if (err < 0) | |
757 | - return err; | |
758 | - } | |
759 | - } else if (mic_pin == AUTO_PIN_MIC) { | |
760 | - mic_pin = AUTO_PIN_FRONT_MIC; | |
761 | - goto again; | |
762 | - } | |
763 | + err = stac92xx_add_control(spec, STAC_CTL_WIDGET_IO_SWITCH, | |
764 | + "Mic as Output Switch", | |
765 | + (spec->mic_switch << 8) | 1); | |
766 | + if (err < 0) | |
767 | + return err; | |
768 | } | |
769 | ||
770 | return 0; | |
771 | @@ -3073,55 +3099,39 @@ | |
772 | { | |
773 | struct sigmatel_spec *spec = codec->spec; | |
774 | hda_nid_t nid; | |
775 | - int i, old_num_dacs, err; | |
776 | + int i, err, nums; | |
777 | ||
778 | - old_num_dacs = spec->multiout.num_dacs; | |
779 | + nums = 0; | |
780 | for (i = 0; i < cfg->hp_outs; i++) { | |
781 | + static const char *pfxs[] = { | |
782 | + "Headphone", "Headphone2", "Headphone3", | |
783 | + }; | |
784 | unsigned int wid_caps = get_wcaps(codec, cfg->hp_pins[i]); | |
785 | if (wid_caps & AC_WCAP_UNSOL_CAP) | |
786 | spec->hp_detect = 1; | |
787 | - nid = snd_hda_codec_read(codec, cfg->hp_pins[i], 0, | |
788 | - AC_VERB_GET_CONNECT_LIST, 0) & 0xff; | |
789 | - if (check_in_dac_nids(spec, nid)) | |
790 | - nid = 0; | |
791 | - if (! nid) | |
792 | + if (nums >= ARRAY_SIZE(pfxs)) | |
793 | continue; | |
794 | - add_spec_dacs(spec, nid); | |
795 | - } | |
796 | - for (i = 0; i < cfg->speaker_outs; i++) { | |
797 | - nid = snd_hda_codec_read(codec, cfg->speaker_pins[i], 0, | |
798 | - AC_VERB_GET_CONNECT_LIST, 0) & 0xff; | |
799 | - if (check_in_dac_nids(spec, nid)) | |
800 | - nid = 0; | |
801 | - if (! nid) | |
802 | + nid = spec->hp_dacs[i]; | |
803 | + if (!nid) | |
804 | continue; | |
805 | - add_spec_dacs(spec, nid); | |
806 | - } | |
807 | - for (i = 0; i < cfg->line_outs; i++) { | |
808 | - nid = snd_hda_codec_read(codec, cfg->line_out_pins[i], 0, | |
809 | - AC_VERB_GET_CONNECT_LIST, 0) & 0xff; | |
810 | - if (check_in_dac_nids(spec, nid)) | |
811 | - nid = 0; | |
812 | - if (! nid) | |
813 | - continue; | |
814 | - add_spec_dacs(spec, nid); | |
815 | + err = create_controls(codec, pfxs[nums++], nid, 3); | |
816 | + if (err < 0) | |
817 | + return err; | |
818 | } | |
819 | - for (i = old_num_dacs; i < spec->multiout.num_dacs; i++) { | |
820 | + nums = 0; | |
821 | + for (i = 0; i < cfg->speaker_outs; i++) { | |
822 | static const char *pfxs[] = { | |
823 | "Speaker", "External Speaker", "Speaker2", | |
824 | }; | |
825 | - err = create_controls(codec, pfxs[i - old_num_dacs], | |
826 | - spec->multiout.dac_nids[i], 3); | |
827 | - if (err < 0) | |
828 | - return err; | |
829 | - } | |
830 | - if (spec->multiout.hp_nid) { | |
831 | - err = create_controls(codec, "Headphone", | |
832 | - spec->multiout.hp_nid, 3); | |
833 | + if (nums >= ARRAY_SIZE(pfxs)) | |
834 | + continue; | |
835 | + nid = spec->speaker_dacs[i]; | |
836 | + if (!nid) | |
837 | + continue; | |
838 | + err = create_controls(codec, pfxs[nums++], nid, 3); | |
839 | if (err < 0) | |
840 | return err; | |
841 | } | |
842 | - | |
843 | return 0; | |
844 | } | |
845 | ||
846 | @@ -3459,7 +3469,6 @@ | |
847 | { | |
848 | struct sigmatel_spec *spec = codec->spec; | |
849 | int err; | |
850 | - int hp_speaker_swap = 0; | |
851 | ||
852 | if ((err = snd_hda_parse_pin_def_config(codec, | |
853 | &spec->autocfg, | |
854 | @@ -3477,13 +3486,15 @@ | |
855 | * speaker_outs so that the following routines can handle | |
856 | * HP pins as primary outputs. | |
857 | */ | |
858 | + snd_printdd("stac92xx: Enabling multi-HPs workaround\n"); | |
859 | memcpy(spec->autocfg.speaker_pins, spec->autocfg.line_out_pins, | |
860 | sizeof(spec->autocfg.line_out_pins)); | |
861 | spec->autocfg.speaker_outs = spec->autocfg.line_outs; | |
862 | memcpy(spec->autocfg.line_out_pins, spec->autocfg.hp_pins, | |
863 | sizeof(spec->autocfg.hp_pins)); | |
864 | spec->autocfg.line_outs = spec->autocfg.hp_outs; | |
865 | - hp_speaker_swap = 1; | |
866 | + spec->autocfg.line_out_type = AUTO_PIN_HP_OUT; | |
867 | + spec->autocfg.hp_outs = 0; | |
868 | } | |
869 | if (spec->autocfg.mono_out_pin) { | |
870 | int dir = get_wcaps(codec, spec->autocfg.mono_out_pin) & | |
871 | @@ -3535,10 +3546,9 @@ | |
872 | AC_PINCTL_OUT_EN); | |
873 | } | |
874 | ||
875 | - if ((err = stac92xx_add_dyn_out_pins(codec, &spec->autocfg)) < 0) | |
876 | - return err; | |
877 | - if (spec->multiout.num_dacs == 0) { | |
878 | - if ((err = stac92xx_auto_fill_dac_nids(codec, &spec->autocfg)) < 0) | |
879 | + if (!spec->multiout.num_dacs) { | |
880 | + err = stac92xx_auto_fill_dac_nids(codec); | |
881 | + if (err < 0) | |
882 | return err; | |
883 | err = stac92xx_auto_create_multi_out_ctls(codec, | |
884 | &spec->autocfg); | |
885 | @@ -3577,19 +3587,6 @@ | |
886 | } | |
887 | #endif | |
888 | ||
889 | - if (hp_speaker_swap == 1) { | |
890 | - /* Restore the hp_outs and line_outs */ | |
891 | - memcpy(spec->autocfg.hp_pins, spec->autocfg.line_out_pins, | |
892 | - sizeof(spec->autocfg.line_out_pins)); | |
893 | - spec->autocfg.hp_outs = spec->autocfg.line_outs; | |
894 | - memcpy(spec->autocfg.line_out_pins, spec->autocfg.speaker_pins, | |
895 | - sizeof(spec->autocfg.speaker_pins)); | |
896 | - spec->autocfg.line_outs = spec->autocfg.speaker_outs; | |
897 | - memset(spec->autocfg.speaker_pins, 0, | |
898 | - sizeof(spec->autocfg.speaker_pins)); | |
899 | - spec->autocfg.speaker_outs = 0; | |
900 | - } | |
901 | - | |
902 | err = stac92xx_auto_create_hp_ctls(codec, &spec->autocfg); | |
903 | ||
904 | if (err < 0) | |
905 | @@ -3638,7 +3635,8 @@ | |
906 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | |
907 | ||
908 | spec->input_mux = &spec->private_imux; | |
909 | - spec->dinput_mux = &spec->private_dimux; | |
910 | + if (!spec->dinput_mux) | |
911 | + spec->dinput_mux = &spec->private_dimux; | |
912 | spec->sinput_mux = &spec->private_smux; | |
913 | spec->mono_mux = &spec->private_mono_mux; | |
914 | spec->amp_mux = &spec->private_amp_mux; | |
915 | @@ -3787,13 +3785,68 @@ | |
916 | AC_VERB_SET_GPIO_DATA, gpiostate); /* sync */ | |
917 | } | |
918 | ||
919 | +static int stac_add_event(struct sigmatel_spec *spec, hda_nid_t nid, | |
920 | + unsigned char type, int data) | |
921 | +{ | |
922 | + struct sigmatel_event *event; | |
923 | + | |
924 | + if (spec->num_events >= ARRAY_SIZE(spec->events)) | |
925 | + return -ENOMEM; | |
926 | + event = &spec->events[spec->num_events++]; | |
927 | + event->nid = nid; | |
928 | + event->type = type; | |
929 | + event->tag = spec->num_events; | |
930 | + event->data = data; | |
931 | + | |
932 | + return event->tag; | |
933 | +} | |
934 | + | |
935 | +static struct sigmatel_event *stac_get_event(struct hda_codec *codec, | |
936 | + hda_nid_t nid, unsigned char type) | |
937 | +{ | |
938 | + struct sigmatel_spec *spec = codec->spec; | |
939 | + struct sigmatel_event *event = spec->events; | |
940 | + int i; | |
941 | + | |
942 | + for (i = 0; i < spec->num_events; i++, event++) { | |
943 | + if (event->nid == nid && event->type == type) | |
944 | + return event; | |
945 | + } | |
946 | + return NULL; | |
947 | +} | |
948 | + | |
949 | +static struct sigmatel_event *stac_get_event_from_tag(struct hda_codec *codec, | |
950 | + unsigned char tag) | |
951 | +{ | |
952 | + struct sigmatel_spec *spec = codec->spec; | |
953 | + struct sigmatel_event *event = spec->events; | |
954 | + int i; | |
955 | + | |
956 | + for (i = 0; i < spec->num_events; i++, event++) { | |
957 | + if (event->tag == tag) | |
958 | + return event; | |
959 | + } | |
960 | + return NULL; | |
961 | +} | |
962 | + | |
963 | static void enable_pin_detect(struct hda_codec *codec, hda_nid_t nid, | |
964 | - unsigned int event) | |
965 | + unsigned int type) | |
966 | { | |
967 | - if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) | |
968 | - snd_hda_codec_write_cache(codec, nid, 0, | |
969 | - AC_VERB_SET_UNSOLICITED_ENABLE, | |
970 | - (AC_USRSP_EN | event)); | |
971 | + struct sigmatel_event *event; | |
972 | + int tag; | |
973 | + | |
974 | + if (!(get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP)) | |
975 | + return; | |
976 | + event = stac_get_event(codec, nid, type); | |
977 | + if (event) | |
978 | + tag = event->tag; | |
979 | + else | |
980 | + tag = stac_add_event(codec->spec, nid, type, 0); | |
981 | + if (tag < 0) | |
982 | + return; | |
983 | + snd_hda_codec_write_cache(codec, nid, 0, | |
984 | + AC_VERB_SET_UNSOLICITED_ENABLE, | |
985 | + AC_USRSP_EN | tag); | |
986 | } | |
987 | ||
988 | static int is_nid_hp_pin(struct auto_pin_cfg *cfg, hda_nid_t nid) | |
989 | @@ -3813,9 +3866,8 @@ | |
990 | /* power down inactive DACs */ | |
991 | hda_nid_t *dac; | |
992 | for (dac = spec->dac_list; *dac; dac++) | |
993 | - if (!is_in_dac_nids(spec, *dac) && | |
994 | - spec->multiout.hp_nid != *dac) | |
995 | - snd_hda_codec_write_cache(codec, *dac, 0, | |
996 | + if (!check_all_dac_nids(spec, *dac)) | |
997 | + snd_hda_codec_write(codec, *dac, 0, | |
998 | AC_VERB_SET_POWER_STATE, AC_PWRST_D3); | |
999 | } | |
1000 | ||
1001 | @@ -3834,7 +3886,7 @@ | |
1002 | /* power down adcs initially */ | |
1003 | if (spec->powerdown_adcs) | |
1004 | for (i = 0; i < spec->num_adcs; i++) | |
1005 | - snd_hda_codec_write_cache(codec, | |
1006 | + snd_hda_codec_write(codec, | |
1007 | spec->adc_nids[i], 0, | |
1008 | AC_VERB_SET_POWER_STATE, AC_PWRST_D3); | |
1009 | ||
1010 | @@ -3850,37 +3902,51 @@ | |
1011 | /* set up pins */ | |
1012 | if (spec->hp_detect) { | |
1013 | /* Enable unsolicited responses on the HP widget */ | |
1014 | - for (i = 0; i < cfg->hp_outs; i++) | |
1015 | - enable_pin_detect(codec, cfg->hp_pins[i], | |
1016 | - STAC_HP_EVENT); | |
1017 | + for (i = 0; i < cfg->hp_outs; i++) { | |
1018 | + hda_nid_t nid = cfg->hp_pins[i]; | |
1019 | + enable_pin_detect(codec, nid, STAC_HP_EVENT); | |
1020 | + } | |
1021 | /* force to enable the first line-out; the others are set up | |
1022 | * in unsol_event | |
1023 | */ | |
1024 | stac92xx_auto_set_pinctl(codec, spec->autocfg.line_out_pins[0], | |
1025 | AC_PINCTL_OUT_EN); | |
1026 | - stac92xx_auto_init_hp_out(codec); | |
1027 | /* fake event to set up pins */ | |
1028 | - codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26); | |
1029 | + stac_issue_unsol_event(codec, spec->autocfg.hp_pins[0], | |
1030 | + STAC_HP_EVENT); | |
1031 | } else { | |
1032 | stac92xx_auto_init_multi_out(codec); | |
1033 | stac92xx_auto_init_hp_out(codec); | |
1034 | + for (i = 0; i < cfg->hp_outs; i++) | |
1035 | + stac_toggle_power_map(codec, cfg->hp_pins[i], 1); | |
1036 | } | |
1037 | for (i = 0; i < AUTO_PIN_LAST; i++) { | |
1038 | hda_nid_t nid = cfg->input_pins[i]; | |
1039 | if (nid) { | |
1040 | - unsigned int pinctl; | |
1041 | + unsigned int pinctl, conf; | |
1042 | if (i == AUTO_PIN_MIC || i == AUTO_PIN_FRONT_MIC) { | |
1043 | /* for mic pins, force to initialize */ | |
1044 | pinctl = stac92xx_get_vref(codec, nid); | |
1045 | + pinctl |= AC_PINCTL_IN_EN; | |
1046 | + stac92xx_auto_set_pinctl(codec, nid, pinctl); | |
1047 | } else { | |
1048 | pinctl = snd_hda_codec_read(codec, nid, 0, | |
1049 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | |
1050 | /* if PINCTL already set then skip */ | |
1051 | - if (pinctl & AC_PINCTL_IN_EN) | |
1052 | - continue; | |
1053 | + if (!(pinctl & AC_PINCTL_IN_EN)) { | |
1054 | + pinctl |= AC_PINCTL_IN_EN; | |
1055 | + stac92xx_auto_set_pinctl(codec, nid, | |
1056 | + pinctl); | |
1057 | + } | |
1058 | + } | |
1059 | + conf = snd_hda_codec_read(codec, nid, 0, | |
1060 | + AC_VERB_GET_CONFIG_DEFAULT, 0); | |
1061 | + if (get_defcfg_connect(conf) != AC_JACK_PORT_FIXED) { | |
1062 | + enable_pin_detect(codec, nid, | |
1063 | + STAC_INSERT_EVENT); | |
1064 | + stac_issue_unsol_event(codec, nid, | |
1065 | + STAC_INSERT_EVENT); | |
1066 | } | |
1067 | - pinctl |= AC_PINCTL_IN_EN; | |
1068 | - stac92xx_auto_set_pinctl(codec, nid, pinctl); | |
1069 | } | |
1070 | } | |
1071 | for (i = 0; i < spec->num_dmics; i++) | |
1072 | @@ -3895,9 +3961,14 @@ | |
1073 | for (i = 0; i < spec->num_pwrs; i++) { | |
1074 | hda_nid_t nid = spec->pwr_nids[i]; | |
1075 | int pinctl, def_conf; | |
1076 | - int event = STAC_PWR_EVENT; | |
1077 | ||
1078 | - if (is_nid_hp_pin(cfg, nid) && spec->hp_detect) | |
1079 | + /* power on when no jack detection is available */ | |
1080 | + if (!spec->hp_detect) { | |
1081 | + stac_toggle_power_map(codec, nid, 1); | |
1082 | + continue; | |
1083 | + } | |
1084 | + | |
1085 | + if (is_nid_hp_pin(cfg, nid)) | |
1086 | continue; /* already has an unsol event */ | |
1087 | ||
1088 | pinctl = snd_hda_codec_read(codec, nid, 0, | |
1089 | @@ -3906,8 +3977,10 @@ | |
1090 | * any attempts on powering down a input port cause the | |
1091 | * referenced VREF to act quirky. | |
1092 | */ | |
1093 | - if (pinctl & AC_PINCTL_IN_EN) | |
1094 | + if (pinctl & AC_PINCTL_IN_EN) { | |
1095 | + stac_toggle_power_map(codec, nid, 1); | |
1096 | continue; | |
1097 | + } | |
1098 | def_conf = snd_hda_codec_read(codec, nid, 0, | |
1099 | AC_VERB_GET_CONFIG_DEFAULT, 0); | |
1100 | def_conf = get_defcfg_connect(def_conf); | |
1101 | @@ -3918,8 +3991,10 @@ | |
1102 | stac_toggle_power_map(codec, nid, 1); | |
1103 | continue; | |
1104 | } | |
1105 | - enable_pin_detect(codec, spec->pwr_nids[i], event | i); | |
1106 | - codec->patch_ops.unsol_event(codec, (event | i) << 26); | |
1107 | + if (!stac_get_event(codec, nid, STAC_INSERT_EVENT)) { | |
1108 | + enable_pin_detect(codec, nid, STAC_PWR_EVENT); | |
1109 | + stac_issue_unsol_event(codec, nid, STAC_PWR_EVENT); | |
1110 | + } | |
1111 | } | |
1112 | if (spec->dac_list) | |
1113 | stac92xx_power_down(codec); | |
1114 | @@ -3960,11 +4035,7 @@ | |
1115 | * "xxx as Output" mixer switch | |
1116 | */ | |
1117 | struct sigmatel_spec *spec = codec->spec; | |
1118 | - struct auto_pin_cfg *cfg = &spec->autocfg; | |
1119 | - if ((nid == cfg->input_pins[AUTO_PIN_LINE] && | |
1120 | - spec->line_switch) || | |
1121 | - (nid == cfg->input_pins[AUTO_PIN_MIC] && | |
1122 | - spec->mic_switch)) | |
1123 | + if (nid == spec->line_switch || nid == spec->mic_switch) | |
1124 | return; | |
1125 | } | |
1126 | ||
1127 | @@ -3988,20 +4059,13 @@ | |
1128 | pin_ctl & ~flag); | |
1129 | } | |
1130 | ||
1131 | -static int get_hp_pin_presence(struct hda_codec *codec, hda_nid_t nid) | |
1132 | +static int get_pin_presence(struct hda_codec *codec, hda_nid_t nid) | |
1133 | { | |
1134 | if (!nid) | |
1135 | return 0; | |
1136 | if (snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_SENSE, 0x00) | |
1137 | - & (1 << 31)) { | |
1138 | - unsigned int pinctl; | |
1139 | - pinctl = snd_hda_codec_read(codec, nid, 0, | |
1140 | - AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | |
1141 | - if (pinctl & AC_PINCTL_IN_EN) | |
1142 | - return 0; /* mic- or line-input */ | |
1143 | - else | |
1144 | - return 1; /* HP-output */ | |
1145 | - } | |
1146 | + & (1 << 31)) | |
1147 | + return 1; | |
1148 | return 0; | |
1149 | } | |
1150 | ||
1151 | @@ -4013,11 +4077,9 @@ | |
1152 | struct auto_pin_cfg *cfg = &spec->autocfg; | |
1153 | ||
1154 | /* ignore sensing of shared line and mic jacks */ | |
1155 | - if (spec->line_switch && | |
1156 | - cfg->hp_pins[i] == cfg->input_pins[AUTO_PIN_LINE]) | |
1157 | + if (cfg->hp_pins[i] == spec->line_switch) | |
1158 | return 1; | |
1159 | - if (spec->mic_switch && | |
1160 | - cfg->hp_pins[i] == cfg->input_pins[AUTO_PIN_MIC]) | |
1161 | + if (cfg->hp_pins[i] == spec->mic_switch) | |
1162 | return 1; | |
1163 | /* ignore if the pin is set as line-out */ | |
1164 | if (cfg->hp_pins[i] == spec->hp_switch) | |
1165 | @@ -4025,7 +4087,7 @@ | |
1166 | return 0; | |
1167 | } | |
1168 | ||
1169 | -static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res) | |
1170 | +static void stac92xx_hp_detect(struct hda_codec *codec) | |
1171 | { | |
1172 | struct sigmatel_spec *spec = codec->spec; | |
1173 | struct auto_pin_cfg *cfg = &spec->autocfg; | |
1174 | @@ -4041,7 +4103,14 @@ | |
1175 | break; | |
1176 | if (no_hp_sensing(spec, i)) | |
1177 | continue; | |
1178 | - presence = get_hp_pin_presence(codec, cfg->hp_pins[i]); | |
1179 | + presence = get_pin_presence(codec, cfg->hp_pins[i]); | |
1180 | + if (presence) { | |
1181 | + unsigned int pinctl; | |
1182 | + pinctl = snd_hda_codec_read(codec, cfg->hp_pins[i], 0, | |
1183 | + AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | |
1184 | + if (pinctl & AC_PINCTL_IN_EN) | |
1185 | + presence = 0; /* mic- or line-input */ | |
1186 | + } | |
1187 | } | |
1188 | ||
1189 | if (presence) { | |
1190 | @@ -4082,8 +4151,19 @@ | |
1191 | continue; | |
1192 | if (presence) | |
1193 | stac92xx_set_pinctl(codec, cfg->hp_pins[i], val); | |
1194 | +#if 0 /* FIXME */ | |
1195 | +/* Resetting the pinctl like below may lead to (a sort of) regressions | |
1196 | + * on some devices since they use the HP pin actually for line/speaker | |
1197 | + * outs although the default pin config shows a different pin (that is | |
1198 | + * wrong and useless). | |
1199 | + * | |
1200 | + * So, it's basically a problem of default pin configs, likely a BIOS issue. | |
1201 | + * But, disabling the code below just works around it, and I'm too tired of | |
1202 | + * bug reports with such devices... | |
1203 | + */ | |
1204 | else | |
1205 | stac92xx_reset_pinctl(codec, cfg->hp_pins[i], val); | |
1206 | +#endif /* FIXME */ | |
1207 | } | |
1208 | } | |
1209 | ||
1210 | @@ -4118,30 +4198,45 @@ | |
1211 | ||
1212 | static void stac92xx_pin_sense(struct hda_codec *codec, hda_nid_t nid) | |
1213 | { | |
1214 | - stac_toggle_power_map(codec, nid, get_hp_pin_presence(codec, nid)); | |
1215 | + stac_toggle_power_map(codec, nid, get_pin_presence(codec, nid)); | |
1216 | +} | |
1217 | + | |
1218 | +static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid, | |
1219 | + unsigned char type) | |
1220 | +{ | |
1221 | + struct sigmatel_event *event = stac_get_event(codec, nid, type); | |
1222 | + if (!event) | |
1223 | + return; | |
1224 | + codec->patch_ops.unsol_event(codec, (unsigned)event->tag << 26); | |
1225 | } | |
1226 | ||
1227 | static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) | |
1228 | { | |
1229 | struct sigmatel_spec *spec = codec->spec; | |
1230 | - int idx = res >> 26 & 0x0f; | |
1231 | + struct sigmatel_event *event; | |
1232 | + int tag, data; | |
1233 | + | |
1234 | + tag = (res >> 26) & 0x7f; | |
1235 | + event = stac_get_event_from_tag(codec, tag); | |
1236 | + if (!event) | |
1237 | + return; | |
1238 | ||
1239 | - switch ((res >> 26) & 0x70) { | |
1240 | + switch (event->type) { | |
1241 | case STAC_HP_EVENT: | |
1242 | - stac92xx_hp_detect(codec, res); | |
1243 | + stac92xx_hp_detect(codec); | |
1244 | /* fallthru */ | |
1245 | + case STAC_INSERT_EVENT: | |
1246 | case STAC_PWR_EVENT: | |
1247 | if (spec->num_pwrs > 0) | |
1248 | - stac92xx_pin_sense(codec, idx); | |
1249 | + stac92xx_pin_sense(codec, event->nid); | |
1250 | break; | |
1251 | - case STAC_VREF_EVENT: { | |
1252 | - int data = snd_hda_codec_read(codec, codec->afg, 0, | |
1253 | - AC_VERB_GET_GPIO_DATA, 0); | |
1254 | + case STAC_VREF_EVENT: | |
1255 | + data = snd_hda_codec_read(codec, codec->afg, 0, | |
1256 | + AC_VERB_GET_GPIO_DATA, 0); | |
1257 | /* toggle VREF state based on GPIOx status */ | |
1258 | snd_hda_codec_write(codec, codec->afg, 0, 0x7e0, | |
1259 | - !!(data & (1 << idx))); | |
1260 | + !!(data & (1 << event->data))); | |
1261 | break; | |
1262 | - } | |
1263 | } | |
1264 | } | |
1265 | ||
1266 | @@ -4151,17 +4246,23 @@ | |
1267 | struct sigmatel_spec *spec = codec->spec; | |
1268 | ||
1269 | stac92xx_set_config_regs(codec); | |
1270 | - snd_hda_sequence_write(codec, spec->init); | |
1271 | - stac_gpio_set(codec, spec->gpio_mask, | |
1272 | - spec->gpio_dir, spec->gpio_data); | |
1273 | + stac92xx_init(codec); | |
1274 | snd_hda_codec_resume_amp(codec); | |
1275 | snd_hda_codec_resume_cache(codec); | |
1276 | - /* power down inactive DACs */ | |
1277 | - if (spec->dac_list) | |
1278 | - stac92xx_power_down(codec); | |
1279 | - /* invoke unsolicited event to reset the HP state */ | |
1280 | + /* fake event to set up pins again to override cached values */ | |
1281 | if (spec->hp_detect) | |
1282 | - codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26); | |
1283 | + stac_issue_unsol_event(codec, spec->autocfg.hp_pins[0], | |
1284 | + STAC_HP_EVENT); | |
1285 | + return 0; | |
1286 | +} | |
1287 | + | |
1288 | +static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state) | |
1289 | +{ | |
1290 | + struct sigmatel_spec *spec = codec->spec; | |
1291 | + if (spec->eapd_mask) | |
1292 | + stac_gpio_set(codec, spec->gpio_mask, | |
1293 | + spec->gpio_dir, spec->gpio_data & | |
1294 | + ~spec->eapd_mask); | |
1295 | return 0; | |
1296 | } | |
1297 | #endif | |
1298 | @@ -4173,6 +4274,7 @@ | |
1299 | .free = stac92xx_free, | |
1300 | .unsol_event = stac92xx_unsol_event, | |
1301 | #ifdef SND_HDA_NEEDS_RESUME | |
1302 | + .suspend = stac92xx_suspend, | |
1303 | .resume = stac92xx_resume, | |
1304 | #endif | |
1305 | }; | |
1306 | @@ -4234,6 +4336,12 @@ | |
1307 | return err; | |
1308 | } | |
1309 | ||
1310 | + /* CF-74 has no headphone detection, and the driver should *NOT* | |
1311 | + * do detection and HP/speaker toggle because the hardware does it. | |
1312 | + */ | |
1313 | + if (spec->board_config == STAC_9200_PANASONIC) | |
1314 | + spec->hp_detect = 0; | |
1315 | + | |
1316 | codec->patch_ops = stac92xx_patch_ops; | |
1317 | ||
1318 | return 0; | |
1319 | @@ -4340,6 +4448,7 @@ | |
1320 | struct sigmatel_spec *spec; | |
1321 | hda_nid_t conn[STAC92HD73_DAC_COUNT + 2]; | |
1322 | int err = 0; | |
1323 | + int num_dacs; | |
1324 | ||
1325 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | |
1326 | if (spec == NULL) | |
1327 | @@ -4368,33 +4477,29 @@ | |
1328 | stac92xx_set_config_regs(codec); | |
1329 | } | |
1330 | ||
1331 | - spec->multiout.num_dacs = snd_hda_get_connections(codec, 0x0a, | |
1332 | + num_dacs = snd_hda_get_connections(codec, 0x0a, | |
1333 | conn, STAC92HD73_DAC_COUNT + 2) - 1; | |
1334 | ||
1335 | - if (spec->multiout.num_dacs < 0) { | |
1336 | + if (num_dacs < 3 || num_dacs > 5) { | |
1337 | printk(KERN_WARNING "hda_codec: Could not determine " | |
1338 | "number of channels defaulting to DAC count\n"); | |
1339 | - spec->multiout.num_dacs = STAC92HD73_DAC_COUNT; | |
1340 | + num_dacs = STAC92HD73_DAC_COUNT; | |
1341 | } | |
1342 | - | |
1343 | - switch (spec->multiout.num_dacs) { | |
1344 | + switch (num_dacs) { | |
1345 | case 0x3: /* 6 Channel */ | |
1346 | - spec->multiout.hp_nid = 0x17; | |
1347 | spec->mixer = stac92hd73xx_6ch_mixer; | |
1348 | spec->init = stac92hd73xx_6ch_core_init; | |
1349 | break; | |
1350 | case 0x4: /* 8 Channel */ | |
1351 | - spec->multiout.hp_nid = 0x18; | |
1352 | spec->mixer = stac92hd73xx_8ch_mixer; | |
1353 | spec->init = stac92hd73xx_8ch_core_init; | |
1354 | break; | |
1355 | case 0x5: /* 10 Channel */ | |
1356 | - spec->multiout.hp_nid = 0x19; | |
1357 | spec->mixer = stac92hd73xx_10ch_mixer; | |
1358 | spec->init = stac92hd73xx_10ch_core_init; | |
1359 | - }; | |
1360 | + } | |
1361 | + spec->multiout.dac_nids = spec->dac_nids; | |
1362 | ||
1363 | - spec->multiout.dac_nids = stac92hd73xx_dac_nids; | |
1364 | spec->aloopback_mask = 0x01; | |
1365 | spec->aloopback_shift = 8; | |
1366 | ||
1367 | @@ -4425,9 +4530,8 @@ | |
1368 | spec->amp_nids = &stac92hd73xx_amp_nids[DELL_M6_AMP]; | |
1369 | spec->eapd_switch = 0; | |
1370 | spec->num_amps = 1; | |
1371 | - spec->multiout.hp_nid = 0; /* dual HPs */ | |
1372 | ||
1373 | - if (!spec->init) | |
1374 | + if (spec->board_config != STAC_DELL_EQ) | |
1375 | spec->init = dell_m6_core_init; | |
1376 | switch (spec->board_config) { | |
1377 | case STAC_DELL_M6_AMIC: /* Analog Mics */ | |
1378 | @@ -4500,7 +4604,9 @@ | |
1379 | static int patch_stac92hd83xxx(struct hda_codec *codec) | |
1380 | { | |
1381 | struct sigmatel_spec *spec; | |
1382 | + hda_nid_t conn[STAC92HD83_DAC_COUNT + 1]; | |
1383 | int err; | |
1384 | + int num_dacs; | |
1385 | ||
1386 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | |
1387 | if (spec == NULL) | |
1388 | @@ -4514,25 +4620,25 @@ | |
1389 | spec->dmux_nids = stac92hd83xxx_dmux_nids; | |
1390 | spec->adc_nids = stac92hd83xxx_adc_nids; | |
1391 | spec->pwr_nids = stac92hd83xxx_pwr_nids; | |
1392 | + spec->amp_nids = stac92hd83xxx_amp_nids; | |
1393 | spec->pwr_mapping = stac92hd83xxx_pwr_mapping; | |
1394 | spec->num_pwrs = ARRAY_SIZE(stac92hd83xxx_pwr_nids); | |
1395 | - spec->multiout.dac_nids = stac92hd83xxx_dac_nids; | |
1396 | + spec->multiout.dac_nids = spec->dac_nids; | |
1397 | ||
1398 | - spec->init = stac92hd83xxx_core_init; | |
1399 | - switch (codec->vendor_id) { | |
1400 | - case 0x111d7605: | |
1401 | - spec->multiout.num_dacs = STAC92HD81_DAC_COUNT; | |
1402 | - break; | |
1403 | - default: | |
1404 | - spec->num_pwrs--; | |
1405 | - spec->init++; /* switch to config #2 */ | |
1406 | - spec->multiout.num_dacs = STAC92HD83_DAC_COUNT; | |
1407 | - } | |
1408 | + /* set port 0xe to select the last DAC | |
1409 | + */ | |
1410 | + num_dacs = snd_hda_get_connections(codec, 0x0e, | |
1411 | + conn, STAC92HD83_DAC_COUNT + 1) - 1; | |
1412 | + | |
1413 | + snd_hda_codec_write_cache(codec, 0xe, 0, | |
1414 | + AC_VERB_SET_CONNECT_SEL, num_dacs); | |
1415 | ||
1416 | + spec->init = stac92hd83xxx_core_init; | |
1417 | spec->mixer = stac92hd83xxx_mixer; | |
1418 | spec->num_pins = ARRAY_SIZE(stac92hd83xxx_pin_nids); | |
1419 | spec->num_dmuxes = ARRAY_SIZE(stac92hd83xxx_dmux_nids); | |
1420 | spec->num_adcs = ARRAY_SIZE(stac92hd83xxx_adc_nids); | |
1421 | + spec->num_amps = ARRAY_SIZE(stac92hd83xxx_amp_nids); | |
1422 | spec->num_dmics = STAC92HD83XXX_NUM_DMICS; | |
1423 | spec->dinput_mux = &stac92hd83xxx_dmux; | |
1424 | spec->pin_nids = stac92hd83xxx_pin_nids; | |
1425 | @@ -4555,6 +4661,15 @@ | |
1426 | stac92xx_set_config_regs(codec); | |
1427 | } | |
1428 | ||
1429 | + switch (codec->vendor_id) { | |
1430 | + case 0x111d7604: | |
1431 | + case 0x111d7605: | |
1432 | + if (spec->board_config == STAC_92HD83XXX_PWR_REF) | |
1433 | + break; | |
1434 | + spec->num_pwrs = 0; | |
1435 | + break; | |
1436 | + } | |
1437 | + | |
1438 | err = stac92xx_parse_auto_config(codec, 0x1d, 0); | |
1439 | if (!err) { | |
1440 | if (spec->board_config < 0) { | |
1441 | @@ -4576,54 +4691,6 @@ | |
1442 | return 0; | |
1443 | } | |
1444 | ||
1445 | -#ifdef SND_HDA_NEEDS_RESUME | |
1446 | -static void stac92hd71xx_set_power_state(struct hda_codec *codec, int pwr) | |
1447 | -{ | |
1448 | - struct sigmatel_spec *spec = codec->spec; | |
1449 | - int i; | |
1450 | - snd_hda_codec_write_cache(codec, codec->afg, 0, | |
1451 | - AC_VERB_SET_POWER_STATE, pwr); | |
1452 | - | |
1453 | - msleep(1); | |
1454 | - for (i = 0; i < spec->num_adcs; i++) { | |
1455 | - snd_hda_codec_write_cache(codec, | |
1456 | - spec->adc_nids[i], 0, | |
1457 | - AC_VERB_SET_POWER_STATE, pwr); | |
1458 | - } | |
1459 | -}; | |
1460 | - | |
1461 | -static int stac92hd71xx_resume(struct hda_codec *codec) | |
1462 | -{ | |
1463 | - stac92hd71xx_set_power_state(codec, AC_PWRST_D0); | |
1464 | - return stac92xx_resume(codec); | |
1465 | -} | |
1466 | - | |
1467 | -static int stac92hd71xx_suspend(struct hda_codec *codec, pm_message_t state) | |
1468 | -{ | |
1469 | - struct sigmatel_spec *spec = codec->spec; | |
1470 | - | |
1471 | - stac92hd71xx_set_power_state(codec, AC_PWRST_D3); | |
1472 | - if (spec->eapd_mask) | |
1473 | - stac_gpio_set(codec, spec->gpio_mask, | |
1474 | - spec->gpio_dir, spec->gpio_data & | |
1475 | - ~spec->eapd_mask); | |
1476 | - return 0; | |
1477 | -}; | |
1478 | - | |
1479 | -#endif | |
1480 | - | |
1481 | -static struct hda_codec_ops stac92hd71bxx_patch_ops = { | |
1482 | - .build_controls = stac92xx_build_controls, | |
1483 | - .build_pcms = stac92xx_build_pcms, | |
1484 | - .init = stac92xx_init, | |
1485 | - .free = stac92xx_free, | |
1486 | - .unsol_event = stac92xx_unsol_event, | |
1487 | -#ifdef SND_HDA_NEEDS_RESUME | |
1488 | - .resume = stac92hd71xx_resume, | |
1489 | - .suspend = stac92hd71xx_suspend, | |
1490 | -#endif | |
1491 | -}; | |
1492 | - | |
1493 | static struct hda_input_mux stac92hd71bxx_dmux = { | |
1494 | .num_items = 4, | |
1495 | .items = { | |
1496 | @@ -4689,21 +4756,21 @@ | |
1497 | switch (spec->board_config) { | |
1498 | case STAC_HP_M4: | |
1499 | /* Enable VREF power saving on GPIO1 detect */ | |
1500 | + err = stac_add_event(spec, codec->afg, | |
1501 | + STAC_VREF_EVENT, 0x02); | |
1502 | + if (err < 0) | |
1503 | + return err; | |
1504 | snd_hda_codec_write_cache(codec, codec->afg, 0, | |
1505 | AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x02); | |
1506 | snd_hda_codec_write_cache(codec, codec->afg, 0, | |
1507 | - AC_VERB_SET_UNSOLICITED_ENABLE, | |
1508 | - (AC_USRSP_EN | STAC_VREF_EVENT | 0x01)); | |
1509 | + AC_VERB_SET_UNSOLICITED_ENABLE, | |
1510 | + AC_USRSP_EN | err); | |
1511 | spec->gpio_mask |= 0x02; | |
1512 | break; | |
1513 | } | |
1514 | if ((codec->revision_id & 0xf) == 0 || | |
1515 | - (codec->revision_id & 0xf) == 1) { | |
1516 | -#ifdef SND_HDA_NEEDS_RESUME | |
1517 | - codec->patch_ops = stac92hd71bxx_patch_ops; | |
1518 | -#endif | |
1519 | + (codec->revision_id & 0xf) == 1) | |
1520 | spec->stream_delay = 40; /* 40 milliseconds */ | |
1521 | - } | |
1522 | ||
1523 | /* no output amps */ | |
1524 | spec->num_pwrs = 0; | |
1525 | @@ -4715,12 +4782,8 @@ | |
1526 | stac92xx_set_config_reg(codec, 0xf, 0x40f000f0); | |
1527 | break; | |
1528 | case 0x111d7603: /* 6 Port with Analog Mixer */ | |
1529 | - if ((codec->revision_id & 0xf) == 1) { | |
1530 | -#ifdef SND_HDA_NEEDS_RESUME | |
1531 | - codec->patch_ops = stac92hd71bxx_patch_ops; | |
1532 | -#endif | |
1533 | + if ((codec->revision_id & 0xf) == 1) | |
1534 | spec->stream_delay = 40; /* 40 milliseconds */ | |
1535 | - } | |
1536 | ||
1537 | /* no output amps */ | |
1538 | spec->num_pwrs = 0; | |
1539 | @@ -4763,7 +4826,7 @@ | |
1540 | case STAC_DELL_M4_3: | |
1541 | spec->num_dmics = 1; | |
1542 | spec->num_smuxes = 0; | |
1543 | - spec->num_dmuxes = 0; | |
1544 | + spec->num_dmuxes = 1; | |
1545 | break; | |
1546 | default: | |
1547 | spec->num_dmics = STAC92HD71BXX_NUM_DMICS; | |
1548 | @@ -4771,9 +4834,7 @@ | |
1549 | spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids); | |
1550 | }; | |
1551 | ||
1552 | - spec->multiout.num_dacs = 1; | |
1553 | - spec->multiout.hp_nid = 0x11; | |
1554 | - spec->multiout.dac_nids = stac92hd71bxx_dac_nids; | |
1555 | + spec->multiout.dac_nids = spec->dac_nids; | |
1556 | if (spec->dinput_mux) | |
1557 | spec->private_dimux.num_items += | |
1558 | spec->num_dmics - | |
1559 | @@ -5097,11 +5158,14 @@ | |
1560 | stac92xx_set_config_reg(codec, 0x20, 0x1c410030); | |
1561 | ||
1562 | /* Enable unsol response for GPIO4/Dock HP connection */ | |
1563 | + err = stac_add_event(spec, codec->afg, STAC_VREF_EVENT, 0x01); | |
1564 | + if (err < 0) | |
1565 | + return err; | |
1566 | snd_hda_codec_write_cache(codec, codec->afg, 0, | |
1567 | AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x10); | |
1568 | snd_hda_codec_write_cache(codec, codec->afg, 0, | |
1569 | AC_VERB_SET_UNSOLICITED_ENABLE, | |
1570 | - (AC_USRSP_EN | STAC_HP_EVENT)); | |
1571 | + AC_USRSP_EN | err); | |
1572 | ||
1573 | spec->gpio_dir = 0x0b; | |
1574 | spec->eapd_mask = 0x01; | |
1575 | @@ -5275,7 +5339,7 @@ | |
1576 | ||
1577 | static void stac9872_vaio_hp_detect(struct hda_codec *codec, unsigned int res) | |
1578 | { | |
1579 | - if (get_hp_pin_presence(codec, 0x0a)) { | |
1580 | + if (get_pin_presence(codec, 0x0a)) { | |
1581 | stac92xx_reset_pinctl(codec, 0x0f, AC_PINCTL_OUT_EN); | |
1582 | stac92xx_set_pinctl(codec, 0x0a, AC_PINCTL_OUT_EN); | |
1583 | } else { |